modernc.org/knuth@v0.0.4/mf/internal/trap/mf.go (about)

     1  // Code generated by '[/tmp/go-build1429805405/b001/exe/generate]', DO NOT EDIT.
     2  
     3  // % This program is copyright (C) 1984 by D. E. Knuth; all rights are reserved.
     4  // % Unlimited copying and redistribution of this file are permitted as long
     5  // % as this file is not modified. Modifications are permitted, but only if
     6  // % the resulting file is not named mf.web. (The WEB system provides
     7  // % for alterations via an auxiliary file; the master file should stay intact.)
     8  // % In other words, METAFONT is under essentially the same ground rules as TeX.
     9  //
    10  // % TeX is a trademark of the American Mathematical Society.
    11  // % METAFONT is a trademark of Addison-Wesley Publishing Company.
    12  //
    13  // % Version 0 was completed on July 28, 1984.
    14  // % Version 1 was completed on January 4, 1986; it corresponds to "Volume D".
    15  // % Version 1.1 trivially corrected the punctuation in one message (June 1986).
    16  // % Version 1.2 corrected an arithmetic overflow problem (July 1986).
    17  // % Version 1.3 improved rounding when elliptical pens are made (November 1986).
    18  // % Version 1.4 corrected scan_declared_variable timing (May 1988).
    19  // % Version 1.5 fixed negative halving in allocator when mem_min<0 (June 1988).
    20  // % Version 1.6 kept open_log_file from calling fatal_error (November 1988).
    21  // % Version 1.7 solved that problem a better way (December 1988).
    22  // % Version 1.8 introduced major changes for 8-bit extensions (September 1989).
    23  // % Version 1.9 improved skimping and was edited for style (December 1989).
    24  // % Version 2.0 fixed bug in addto; released with TeX version 3.0 (March 1990).
    25  // % Version 2.7 made consistent with TeX version 3.1 (September 1990).
    26  // % Version 2.71 fixed bug in draw, allowed unprintable filenames (March 1992).
    27  // % Version 2.718 fixed bug in <Choose a dependent...> (March 1995).
    28  // % Version 2.7182 fixed bugs related to "<unprintable char>" (August 1996).
    29  // % Version 2.71828 suppressed autorounding in dangerous cases (June 2003).
    30  // % Version 2.718281 was a general cleanup with minor fixes (February 2008).
    31  // % Version 2.7182818 was similar (January 2014).
    32  // % Version 2.71828182 was similar (January 2021).
    33  //
    34  // % A reward of $327.68 will be paid to the first finder of any remaining bug.
    35  //
    36  // % Although considerable effort has been expended to make the METAFONT program
    37  // % correct and reliable, no warranty is implied; the author disclaims any
    38  // % obligation or liability for damages, including but not limited to
    39  // % special, indirect, or consequential damages arising out of or in
    40  // % connection with the use or performance of this software. This work has
    41  // % been a ``labor of love'' and the author hopes that users enjoy it.
    42  //
    43  // % Here is TeX material that gets inserted after \input webmac
    44  // \def\hang[\hangindent 3em\noindent\ignorespaces]
    45  // \def\textindent#1[\hangindent2.5em\noindent\hbox to2.5em[\hss#1 ]\ignorespaces]
    46  // \font\ninerm=cmr9
    47  // \let\mc=\ninerm % medium caps for names like SAIL
    48  // \def\PASCAL[Pascal]
    49  // \def\ph[\hbox[Pascal-H]]
    50  // \def\psqrt#1[\sqrt[\mathstrut#1]]
    51  // \def\k[_[k+1]]
    52  // \def\pct![[\char`\%]] % percent sign in ordinary text
    53  // \font\tenlogo=logo10 % font used for the METAFONT logo
    54  // \font\logos=logosl10
    55  // \font\eightlogo=logo8
    56  // \def\MF[[\tenlogo META]\-[\tenlogo FONT]]
    57  // \def\<#1>[$\langle#1\rangle$]
    58  // \def\section[\mathhexbox278]
    59  // \let\swap=\leftrightarrow
    60  // \def\round[\mathop[\rm round]\nolimits]
    61  //
    62  // \def\(#1)[] % this is used to make section names sort themselves better
    63  // \def\9#1[] % this is used for sort keys in the index via @:sort key][entry@>
    64  //
    65  // \outer\def\N#1. \[#2]#3.[\MN#1.\vfil\eject % begin starred section
    66  //   \def\rhead[PART #2:\uppercase[#3]] % define running headline
    67  //   \message[*\modno] % progress report
    68  //   \edef\next[\write\cont[\Z[\?#2]#3][\modno][\the\pageno]]]\next
    69  //   \ifon\startsection[\bf\ignorespaces#3.\quad]\ignorespaces]
    70  // \let\?=\relax % we want to be able to \write a \?
    71  //
    72  // \def\title[[\eightlogo METAFONT]]
    73  // \def\topofcontents[\hsize 5.5in
    74  //   \vglue -30pt plus 1fil minus 1.5in
    75  //   \def\?##1][\hbox to 1in[\hfil##1.\ ]]
    76  //   ]
    77  // \def\botofcontents[\vskip 0pt plus 1fil minus 1.5in]
    78  // \pageno=3
    79  // \def\glob[13] % this should be the section number of "<Global...>"
    80  // \def\gglob[20, 26] % this should be the next two sections of "<Global...>"
    81  //
    82  //
    83  
    84  // 1. \[1] Introduction
    85  
    86  // tangle:pos ../../mf.web:80:22:
    87  
    88  // This is \MF, a font compiler intended to produce typefaces of high quality.
    89  // The \PASCAL\ program that follows is the definition of \MF84, a standard
    90  // \xref[PASCAL][\PASCAL]
    91  //  \xref[METAFONT84][\MF84]
    92  // version of \MF\ that is designed to be highly portable so that identical output
    93  // will be obtainable on a great variety of computers. The conventions
    94  // of \MF84 are the same as those of \TeX82.
    95  //
    96  // The main purpose of the following program is to explain the algorithms of \MF\
    97  // as clearly as possible. As a result, the program will not necessarily be very
    98  // efficient when a particular \PASCAL\ compiler has translated it into a
    99  // particular machine language. However, the program has been written so that it
   100  // can be tuned to run efficiently in a wide variety of operating environments
   101  // by making comparatively few changes. Such flexibility is possible because
   102  // the documentation that follows is written in the \.[WEB] language, which is
   103  // at a higher level than \PASCAL; the preprocessing step that converts \.[WEB]
   104  // to \PASCAL\ is able to introduce most of the necessary refinements.
   105  // Semi-automatic translation to other languages is also feasible, because the
   106  // program below does not make extensive use of features that are peculiar to
   107  // \PASCAL.
   108  //
   109  // A large piece of software like \MF\ has inherent complexity that cannot
   110  // be reduced below a certain level of difficulty, although each individual
   111  // part is fairly simple by itself. The \.[WEB] language is intended to make
   112  // the algorithms as readable as possible, by reflecting the way the
   113  // individual program pieces fit together and by providing the
   114  // cross-references that connect different parts. Detailed comments about
   115  // what is going on, and about why things were done in certain ways, have
   116  // been liberally sprinkled throughout the program.  These comments explain
   117  // features of the implementation, but they rarely attempt to explain the
   118  // \MF\ language itself, since the reader is supposed to be familiar with
   119  // [\sl The [\logos METAFONT\/]book].
   120  // \xref[WEB]
   121  // \xref[METAFONTbook][\sl The [\logos METAFONT\/]book]
   122  
   123  // 2.
   124  
   125  // tangle:pos ../../mf.web:116:3:
   126  
   127  // The present implementation has a long ancestry, beginning in the spring
   128  // of~1977, when its author wrote a prototype set of subroutines and macros
   129  // \xref[Knuth, Donald Ervin]
   130  // that were used to develop the first Computer Modern fonts.
   131  // This original proto-\MF\ required the user to recompile a [\mc SAIL] program
   132  // whenever any character was changed, because it was not a ``language'' for
   133  // font design; the language was [\mc SAIL]. After several hundred characters
   134  // had been designed in that way, the author developed an interpretable language
   135  // called \MF, in which it was possible to express the Computer Modern programs
   136  // less cryptically. A complete \MF\ processor was designed and coded by the
   137  // author in 1979. This program, written in [\mc SAIL], was adapted for use
   138  // with a variety of typesetting equipment and display terminals by Leo Guibas,
   139  // Lyle Ramshaw, and David Fuchs.
   140  // \xref[Guibas, Leonidas Ioannis]
   141  // \xref[Ramshaw, Lyle Harold]
   142  // \xref[Fuchs, David Raymond]
   143  // Major improvements to the design of Computer Modern fonts were made in the
   144  // spring of 1982, after which it became clear that a new language would
   145  // better express the needs of letterform designers. Therefore an entirely
   146  // new \MF\ language and system were developed in 1984; the present system
   147  // retains the name and some of the spirit of \MF79, but all of the details
   148  // have changed.
   149  //
   150  // No doubt there still is plenty of room for improvement, but the author
   151  // is firmly committed to keeping \MF84 ``frozen'' from now on; stability
   152  // and reliability are to be its main virtues.
   153  //
   154  // On the other hand, the \.[WEB] description can be extended without changing
   155  // the core of \MF84 itself, and the program has been designed so that such
   156  // extensions are not extremely difficult to make.
   157  // The |banner| string defined here should be changed whenever \MF\
   158  // undergoes any modifications, so that it will be clear which version of
   159  // \MF\ might be the guilty party when a problem arises.
   160  // \xref[extensions to \MF]
   161  // \xref[system dependencies]
   162  //
   163  // If this program is changed, the resulting system should not be called
   164  // `\MF\kern.5pt'; the official name `\MF\kern.5pt' by itself is reserved
   165  // for software systems that are fully compatible with each other.
   166  // A special test suite called the ``\.[TRAP] test'' is available for
   167  // helping to determine whether an implementation deserves to be
   168  // known as `\MF\kern.5pt' [cf.~Stanford Computer Science report CS1095,
   169  // January 1986].
   170  
   171  // 3.
   172  
   173  // tangle:pos ../../mf.web:162:3:
   174  
   175  // Different \PASCAL s have slightly different conventions, and the present
   176  //  \xref[PASCAL H][\ph]
   177  // program expresses \MF\ in terms of the \PASCAL\ that was
   178  // available to the author in 1984. Constructions that apply to
   179  // this particular compiler, which we shall call \ph, should help the
   180  // reader see how to make an appropriate interface for other systems
   181  // if necessary. (\ph\ is Charles Hedrick's modification of a compiler
   182  // \xref[Hedrick, Charles Locke]
   183  // for the DECsystem-10 that was originally developed at the University of
   184  // Hamburg; cf.\ [\sl Software---Practice and Experience \bf6] (1976),
   185  // 29--42. The \MF\ program below is intended to be adaptable, without
   186  // extensive changes, to most other versions of \PASCAL, so it does not fully
   187  // use the admirable features of \ph. Indeed, a conscious effort has been
   188  // made here to avoid using several idiosyncratic features of standard
   189  // \PASCAL\ itself, so that most of the code can be translated mechanically
   190  // into other high-level languages. For example, the `\&[with]' and `\\[new]'
   191  // features are not used, nor are pointer types, set types, or enumerated
   192  // scalar types; there are no `\&[var]' parameters, except in the case of files
   193  // or in the system-dependent |paint_row| procedure;
   194  // there are no tag fields on variant records; there are no |real| variables;
   195  // no procedures are declared local to other procedures.)
   196  //
   197  // The portions of this program that involve system-dependent code, where
   198  // changes might be necessary because of differences between \PASCAL\ compilers
   199  // and/or differences between
   200  // operating systems, can be identified by looking at the sections whose
   201  // numbers are listed under `system dependencies' in the index. Furthermore,
   202  // the index entries for `dirty \PASCAL' list all places where the restrictions
   203  // of \PASCAL\ have not been followed perfectly, for one reason or another.
   204  //  \xref[system dependencies]
   205  //  \xref[dirty \PASCAL]
   206  
   207  // 4.
   208  
   209  // tangle:pos ../../mf.web:194:3:
   210  
   211  // The program begins with a normal \PASCAL\ program heading, whose
   212  // components will be filled in later, using the conventions of \.[WEB].
   213  // \xref[WEB]
   214  // For example, the portion of the program called `\X\glob:Global
   215  // variables\X' below will be replaced by a sequence of variable declarations
   216  // that starts in $\section\glob$ of this documentation. In this way, we are able
   217  // to define each individual global variable when we are prepared to
   218  // understand what it means; we do not have to define all of the globals at
   219  // once.  Cross references in $\section\glob$, where it says ``See also
   220  // sections \gglob, \dots,'' also make it possible to look at the set of
   221  // all global variables, if desired.  Similar remarks apply to the other
   222  // portions of the program heading.
   223  //
   224  // Actually the heading shown here is not quite normal: The |program| line
   225  // does not mention any |output| file, because \ph\ would ask the \MF\ user
   226  // to specify a file name if |output| were specified here.
   227  // \xref[PASCAL H][\ph]
   228  // \xref[system dependencies]
   229  // \4
   230  // Compiler directives
   231  // $C-,A+,D-
   232  // no range check, catch arithmetic overflow, no debug overhead
   233  //  [$C+,D+]  [  ]
   234  // but turn everything on when debugging
   235  
   236  package trap
   237  
   238  import (
   239  	"math"
   240  	"unsafe"
   241  
   242  	"modernc.org/knuth"
   243  )
   244  
   245  var (
   246  	_ = math.MaxInt32
   247  	_ unsafe.Pointer
   248  )
   249  
   250  type (
   251  	char   = byte
   252  	signal int
   253  )
   254  
   255  func strcopy(dst []char, src string) {
   256  	for i := 0; i < len(dst) && i < len(src); i++ {
   257  		dst[i] = src[i]
   258  	}
   259  }
   260  
   261  func arraystr(a []char) string {
   262  	b := make([]byte, len(a))
   263  	for i, c := range a {
   264  		b[i] = c
   265  	}
   266  	return string(b)
   267  }
   268  
   269  func abs(n int32) int32 {
   270  	if n >= 0 {
   271  		return n
   272  	}
   273  
   274  	return -n
   275  }
   276  
   277  func fabs(f float64) float64 {
   278  	if f >= 0 {
   279  		return f
   280  	}
   281  
   282  	return -f
   283  }
   284  
   285  func round(f float64) int32 {
   286  	if f >= 0 {
   287  		return int32(f + 0.5)
   288  	}
   289  
   290  	return int32(f - 0.5)
   291  }
   292  
   293  // key control points
   294  
   295  const (
   296  	startOfMf = 1    /* go here when \MF's variables are initialized */
   297  	endOfMf   = 9998 /* go here to close files and terminate gracefully */
   298  	finalEnd  = 9999 /* this label marks the ending of the program */
   299  	memMin    = 0    // smallest index in the |mem| array, must not be less
   300  	//   than |min_halfword|
   301  
   302  	hashSize = 2100 // maximum number of symbolic tokens,
   303  	//   must be less than |max_halfword-3*param_size|
   304  
   305  	hashPrime = 1777 /* a prime number equal to about 85\pct! of |hash_size| */
   306  	maxInOpen = 6    // maximum number of input files and error insertions that
   307  	//   can be going on simultaneously
   308  
   309  	paramSize = 150 // maximum number of simultaneous macro parameters
   310  	// \xref[system dependencies]
   311  
   312  	exit                    = 10  /* go here to leave a procedure */
   313  	restart                 = 20  /* go here to start a procedure again */
   314  	reswitch                = 21  /* go here to start a case statement again */
   315  	continue1               = 22  /* go here to resume a loop */
   316  	done                    = 30  /* go here to exit a loop */
   317  	done1                   = 31  /* like |done|, when there is more than one loop */
   318  	done2                   = 32  /* for exiting the second loop in a long block */
   319  	done3                   = 33  /* for exiting the third loop in a very long block */
   320  	done4                   = 34  /* for exiting the fourth loop in an extremely long block */
   321  	done5                   = 35  /* for exiting the fifth loop in an immense block */
   322  	done6                   = 36  /* for exiting the sixth loop in a block */
   323  	found                   = 40  /* go here when you've found it */
   324  	found1                  = 41  /* like |found|, when there's more than one per routine */
   325  	found2                  = 42  /* like |found|, when there's more than two per routine */
   326  	notFound                = 45  /* go here when you've found nothing */
   327  	commonEnding            = 50  /* go here when you want to merge with another branch */
   328  	firstTextChar           = 0   /* ordinal number of the smallest element of |text_char| */
   329  	lastTextChar            = 255 /* ordinal number of the largest element of |text_char| */
   330  	maxStrRef               = 127 /* ``infinite'' number of references */
   331  	noPrint                 = 0   /* |selector| setting that makes data disappear */
   332  	termOnly                = 1   /* printing is destined for the terminal only */
   333  	logOnly                 = 2   /* printing is destined for the transcript file only */
   334  	termAndLog              = 3   /* normal |selector| setting */
   335  	pseudo                  = 4   /* special |selector| setting for |show_context| */
   336  	newString               = 5   /* printing is deflected to the string pool */
   337  	maxSelector             = 5   /* highest selector setting */
   338  	batchMode               = 0   /* omits all stops and omits terminal output */
   339  	nonstopMode             = 1   /* omits all stops */
   340  	scrollMode              = 2   /* omits error stops */
   341  	errorStopMode           = 3   /* stops at every opportunity to interact */
   342  	spotless                = 0   /* |history| value when nothing has been amiss yet */
   343  	warningIssued           = 1   /* |history| value when |begin_diagnostic| has been called */
   344  	errorMessageIssued      = 2   /* |history| value when |error| has been called */
   345  	fatalErrorStop          = 3   /* |history| value when termination was premature */
   346  	negateX                 = 1
   347  	negateY                 = 2
   348  	switchXAndY             = 4
   349  	firstOctant             = 1
   350  	secondOctant            = firstOctant + switchXAndY
   351  	thirdOctant             = firstOctant + switchXAndY + negateX
   352  	fourthOctant            = firstOctant + negateX
   353  	fifthOctant             = firstOctant + negateX + negateY
   354  	sixthOctant             = firstOctant + switchXAndY + negateX + negateY
   355  	seventhOctant           = firstOctant + switchXAndY + negateY
   356  	eighthOctant            = firstOctant + negateY
   357  	minQuarterword          = 0   /* smallest allowable value in a |quarterword| */
   358  	maxQuarterword          = 255 /* largest allowable value in a |quarterword| */
   359  	ifTest                  = 1   /* conditional text (\&[if]) */
   360  	fiOrElse                = 2   /* delimiters for conditionals (\&[elseif], \&[else], \&[fi]) */
   361  	input                   = 3   /* input a source file (\&[input], \&[endinput]) */
   362  	iteration               = 4   /* iterate (\&[for], \&[forsuffixes], \&[forever], \&[endfor]) */
   363  	repeatLoop              = 5   /* special command substituted for \&[endfor] */
   364  	exitTest                = 6   /* premature exit from a loop (\&[exitif]) */
   365  	relax                   = 7   /* do nothing (\.[\char`\\]) */
   366  	scanTokens              = 8   /* put a string into the input buffer */
   367  	expandAfter             = 9   /* look ahead one token */
   368  	definedMacro            = 10  /* a macro defined by the user */
   369  	minCommand              = definedMacro + 1
   370  	displayCommand          = 11 /* online graphic output (\&[display]) */
   371  	saveCommand             = 12 /* save a list of tokens (\&[save]) */
   372  	interimCommand          = 13 /* save an internal quantity (\&[interim]) */
   373  	letCommand              = 14 /* redefine a symbolic token (\&[let]) */
   374  	newInternal             = 15 /* define a new internal quantity (\&[newinternal]) */
   375  	macroDef                = 16 /* define a macro (\&[def], \&[vardef], etc.) */
   376  	shipOutCommand          = 17 /* output a character (\&[shipout]) */
   377  	addToCommand            = 18 /* add to edges (\&[addto]) */
   378  	cullCommand             = 19 /* cull and normalize edges (\&[cull]) */
   379  	tfmCommand              = 20 /* command for font metric info (\&[ligtable], etc.) */
   380  	protectionCommand       = 21 /* set protection flag (\&[outer], \&[inner]) */
   381  	showCommand             = 22 /* diagnostic output (\&[show], \&[showvariable], etc.) */
   382  	modeCommand             = 23 /* set interaction level (\&[batchmode], etc.) */
   383  	randomSeed              = 24 /* initialize random number generator (\&[randomseed]) */
   384  	messageCommand          = 25 /* communicate to user (\&[message], \&[errmessage]) */
   385  	everyJobCommand         = 26 /* designate a starting token (\&[everyjob]) */
   386  	delimiters              = 27 /* define a pair of delimiters (\&[delimiters]) */
   387  	openWindow              = 28 /* define a window on the screen (\&[openwindow]) */
   388  	specialCommand          = 29 /* output special info (\&[special], \&[numspecial]) */
   389  	typeName                = 30 /* declare a type (\&[numeric], \&[pair], etc.) */
   390  	maxStatementCommand     = typeName
   391  	minPrimaryCommand       = typeName
   392  	leftDelimiter           = 31 /* the left delimiter of a matching pair */
   393  	beginGroup              = 32 /* beginning of a group (\&[begingroup]) */
   394  	nullary                 = 33 /* an operator without arguments (e.g., \&[normaldeviate]) */
   395  	unary                   = 34 /* an operator with one argument (e.g., \&[sqrt]) */
   396  	strOp                   = 35 /* convert a suffix to a string (\&[str]) */
   397  	cycle                   = 36 /* close a cyclic path (\&[cycle]) */
   398  	primaryBinary           = 37 /* binary operation taking `\&[of]' (e.g., \&[point]) */
   399  	capsuleToken            = 38 /* a value that has been put into a token list */
   400  	stringToken             = 39 /* a string constant (e.g., |"hello"|) */
   401  	internalQuantity        = 40 /* internal numeric parameter (e.g., \&[pausing]) */
   402  	minSuffixToken          = internalQuantity
   403  	tagToken                = 41 /* a symbolic token without a primitive meaning */
   404  	numericToken            = 42 /* a numeric constant (e.g., \.[3.14159]) */
   405  	maxSuffixToken          = numericToken
   406  	plusOrMinus             = 43          /* either `\.+' or `\.-' */
   407  	maxPrimaryCommand       = plusOrMinus /* should also be |numeric_token+1| */
   408  	minTertiaryCommand      = plusOrMinus
   409  	tertiarySecondaryMacro  = 44 /* a macro defined by \&[secondarydef] */
   410  	tertiaryBinary          = 45 /* an operator at the tertiary level (e.g., `\.[++]') */
   411  	maxTertiaryCommand      = tertiaryBinary
   412  	leftBrace               = 46 /* the operator `\.[\char`\[]' */
   413  	minExpressionCommand    = leftBrace
   414  	pathJoin                = 47 /* the operator `\.[..]' */
   415  	ampersand               = 48 /* the operator `\.\&' */
   416  	expressionTertiaryMacro = 49 /* a macro defined by \&[tertiarydef] */
   417  	expressionBinary        = 50 /* an operator at the expression level (e.g., `\.<') */
   418  	equals                  = 51 /* the operator `\.=' */
   419  	maxExpressionCommand    = equals
   420  	andCommand              = 52 /* the operator `\&[and]' */
   421  	minSecondaryCommand     = andCommand
   422  	secondaryPrimaryMacro   = 53 /* a macro defined by \&[primarydef] */
   423  	slash                   = 54 /* the operator `\./' */
   424  	secondaryBinary         = 55 /* an operator at the binary level (e.g., \&[shifted]) */
   425  	maxSecondaryCommand     = secondaryBinary
   426  	paramType               = 56 /* type of parameter (\&[primary], \&[expr], \&[suffix], etc.) */
   427  	controls                = 57 /* specify control points explicitly (\&[controls]) */
   428  	tension                 = 58 /* specify tension between knots (\&[tension]) */
   429  	atLeast                 = 59 /* bounded tension value (\&[atleast]) */
   430  	curlCommand             = 60 /* specify curl at an end knot (\&[curl]) */
   431  	macroSpecial            = 61 /* special macro operators (\&[quote], \.[\#\AT!], etc.) */
   432  	rightDelimiter          = 62 /* the right delimiter of a matching pair */
   433  	leftBracket             = 63 /* the operator `\.[' */
   434  	rightBracket            = 64 /* the operator `\.]' */
   435  	rightBrace              = 65 /* the operator `\.[\char`\]]' */
   436  	withOption              = 66 /* option for filling (\&[withpen], \&[withweight]) */
   437  	cullOp                  = 67 /* the operator `\&[keeping]' or `\&[dropping]' */
   438  	thingToAdd              = 68
   439  	/* variant of \&[addto] (\&[contour], \&[doublepath], \&[also]) */
   440  	ofToken      = 69 /* the operator `\&[of]' */
   441  	fromToken    = 70 /* the operator `\&[from]' */
   442  	toToken      = 71 /* the operator `\&[to]' */
   443  	atToken      = 72 /* the operator `\&[at]' */
   444  	inWindow     = 73 /* the operator `\&[inwindow]' */
   445  	stepToken    = 74 /* the operator `\&[step]' */
   446  	untilToken   = 75 /* the operator `\&[until]' */
   447  	ligKernToken = 76
   448  	/* the operators `\&[kern]' and `\.[=:]' and `\.[=:\char'174]', etc. */
   449  	assignment        = 77 /* the operator `\.[:=]' */
   450  	skipTo            = 78 /* the operation `\&[skipto]' */
   451  	bcharLabel        = 79 /* the operator `\.[\char'174\char'174:]' */
   452  	doubleColon       = 80 /* the operator `\.[::]' */
   453  	colon             = 81 /* the operator `\.:' */
   454  	comma             = 82 /* the operator `\.,', must be |colon+1| */
   455  	semicolon         = 83 /* the operator `\.;', must be |comma+1| */
   456  	endGroup          = 84 /* end a group (\&[endgroup]), must be |semicolon+1| */
   457  	stop              = 85 /* end a job (\&[end], \&[dump]), must be |end_group+1| */
   458  	maxCommandCode    = stop
   459  	outerTag          = maxCommandCode + 1 /* protection code added to command code */
   460  	undefined         = 0                  /* no type has been declared */
   461  	unknownTag        = 1                  /* this constant is added to certain type codes below */
   462  	vacuous           = 1                  /* no expression was present */
   463  	booleanType       = 2                  /* \&[boolean] with a known value */
   464  	unknownBoolean    = booleanType + unknownTag
   465  	stringType        = 4 /* \&[string] with a known value */
   466  	unknownString     = stringType + unknownTag
   467  	penType           = 6 /* \&[pen] with a known value */
   468  	unknownPen        = penType + unknownTag
   469  	futurePen         = 8 /* subexpression that will become a \&[pen] at a higher level */
   470  	pathType          = 9 /* \&[path] with a known value */
   471  	unknownPath       = pathType + unknownTag
   472  	pictureType       = 11 /* \&[picture] with a known value */
   473  	unknownPicture    = pictureType + unknownTag
   474  	transformType     = 13 /* \&[transform] variable or capsule */
   475  	pairType          = 14 /* \&[pair] variable or capsule */
   476  	numericType       = 15 /* variable that has been declared \&[numeric] but not used */
   477  	known             = 16 /* \&[numeric] with a known value */
   478  	dependent         = 17 /* a linear combination with |fraction| coefficients */
   479  	protoDependent    = 18 /* a linear combination with |scaled| coefficients */
   480  	independent       = 19 /* \&[numeric] with unknown value */
   481  	tokenList         = 20 /* variable name or suffix argument or text argument */
   482  	structured        = 21 /* variable with subscripts and attributes */
   483  	unsuffixedMacro   = 22 /* variable defined with \&[vardef] but no \.[\AT!\#] */
   484  	suffixedMacro     = 23 /* variable defined with \&[vardef] and \.[\AT!\#] */
   485  	root              = 0  /* |name_type| at the top level of a variable */
   486  	savedRoot         = 1  /* same, when the variable has been saved */
   487  	structuredRoot    = 2  /* |name_type| where a |structured| branch occurs */
   488  	subscr            = 3  /* |name_type| in a subscript node */
   489  	attr              = 4  /* |name_type| in an attribute node */
   490  	xPartSector       = 5  /* |name_type| in the \&[xpart] of a node */
   491  	yPartSector       = 6  /* |name_type| in the \&[ypart] of a node */
   492  	xxPartSector      = 7  /* |name_type| in the \&[xxpart] of a node */
   493  	xyPartSector      = 8  /* |name_type| in the \&[xypart] of a node */
   494  	yxPartSector      = 9  /* |name_type| in the \&[yxpart] of a node */
   495  	yyPartSector      = 10 /* |name_type| in the \&[yypart] of a node */
   496  	capsule           = 11 /* |name_type| in stashed-away subexpressions */
   497  	token             = 12 /* |name_type| in a numeric token or string token */
   498  	trueCode          = 30 /* operation code for \.[true] */
   499  	falseCode         = 31 /* operation code for \.[false] */
   500  	nullPictureCode   = 32 /* operation code for \.[nullpicture] */
   501  	nullPenCode       = 33 /* operation code for \.[nullpen] */
   502  	jobNameOp         = 34 /* operation code for \.[jobname] */
   503  	readStringOp      = 35 /* operation code for \.[readstring] */
   504  	penCircle         = 36 /* operation code for \.[pencircle] */
   505  	normalDeviate     = 37 /* operation code for \.[normaldeviate] */
   506  	oddOp             = 38 /* operation code for \.[odd] */
   507  	knownOp           = 39 /* operation code for \.[known] */
   508  	unknownOp         = 40 /* operation code for \.[unknown] */
   509  	notOp             = 41 /* operation code for \.[not] */
   510  	decimal           = 42 /* operation code for \.[decimal] */
   511  	reverse           = 43 /* operation code for \.[reverse] */
   512  	makePathOp        = 44 /* operation code for \.[makepath] */
   513  	makePenOp         = 45 /* operation code for \.[makepen] */
   514  	totalWeightOp     = 46 /* operation code for \.[totalweight] */
   515  	octOp             = 47 /* operation code for \.[oct] */
   516  	hexOp             = 48 /* operation code for \.[hex] */
   517  	asciiOp           = 49 /* operation code for \.[ASCII] */
   518  	charOp            = 50 /* operation code for \.[char] */
   519  	lengthOp          = 51 /* operation code for \.[length] */
   520  	turningOp         = 52 /* operation code for \.[turningnumber] */
   521  	xPart             = 53 /* operation code for \.[xpart] */
   522  	yPart             = 54 /* operation code for \.[ypart] */
   523  	xxPart            = 55 /* operation code for \.[xxpart] */
   524  	xyPart            = 56 /* operation code for \.[xypart] */
   525  	yxPart            = 57 /* operation code for \.[yxpart] */
   526  	yyPart            = 58 /* operation code for \.[yypart] */
   527  	sqrtOp            = 59 /* operation code for \.[sqrt] */
   528  	mExpOp            = 60 /* operation code for \.[mexp] */
   529  	mLogOp            = 61 /* operation code for \.[mlog] */
   530  	sinDOp            = 62 /* operation code for \.[sind] */
   531  	cosDOp            = 63 /* operation code for \.[cosd] */
   532  	floorOp           = 64 /* operation code for \.[floor] */
   533  	uniformDeviate    = 65 /* operation code for \.[uniformdeviate] */
   534  	charExistsOp      = 66 /* operation code for \.[charexists] */
   535  	angleOp           = 67 /* operation code for \.[angle] */
   536  	cycleOp           = 68 /* operation code for \.[cycle] */
   537  	plus              = 69 /* operation code for \.+ */
   538  	minus             = 70 /* operation code for \.- */
   539  	times             = 71 /* operation code for \.* */
   540  	over              = 72 /* operation code for \./ */
   541  	pythagAdd         = 73 /* operation code for \.[++] */
   542  	pythagSub         = 74 /* operation code for \.[+-+] */
   543  	orOp              = 75 /* operation code for \.[or] */
   544  	andOp             = 76 /* operation code for \.[and] */
   545  	lessThan          = 77 /* operation code for \.< */
   546  	lessOrEqual       = 78 /* operation code for \.[<=] */
   547  	greaterThan       = 79 /* operation code for \.> */
   548  	greaterOrEqual    = 80 /* operation code for \.[>=] */
   549  	equalTo           = 81 /* operation code for \.= */
   550  	unequalTo         = 82 /* operation code for \.[<>] */
   551  	concatenate       = 83 /* operation code for \.\& */
   552  	rotatedBy         = 84 /* operation code for \.[rotated] */
   553  	slantedBy         = 85 /* operation code for \.[slanted] */
   554  	scaledBy          = 86 /* operation code for \.[scaled] */
   555  	shiftedBy         = 87 /* operation code for \.[shifted] */
   556  	transformedBy     = 88 /* operation code for \.[transformed] */
   557  	xScaled           = 89 /* operation code for \.[xscaled] */
   558  	yScaled           = 90 /* operation code for \.[yscaled] */
   559  	zScaled           = 91 /* operation code for \.[zscaled] */
   560  	intersect         = 92 /* operation code for \.[intersectiontimes] */
   561  	doubleDot         = 93 /* operation code for improper \.[..] */
   562  	substringOf       = 94 /* operation code for \.[substring] */
   563  	minOf             = substringOf
   564  	subpathOf         = 95  /* operation code for \.[subpath] */
   565  	directionTimeOf   = 96  /* operation code for \.[directiontime] */
   566  	pointOf           = 97  /* operation code for \.[point] */
   567  	precontrolOf      = 98  /* operation code for \.[precontrol] */
   568  	postcontrolOf     = 99  /* operation code for \.[postcontrol] */
   569  	penOffsetOf       = 100 /* operation code for \.[penoffset] */
   570  	tracingTitles     = 1   /* show titles online when they appear */
   571  	tracingEquations  = 2   /* show each variable when it becomes known */
   572  	tracingCapsules   = 3   /* show capsules too */
   573  	tracingChoices    = 4   /* show the control points chosen for paths */
   574  	tracingSpecs      = 5   /* show subdivision of paths into octants before digitizing */
   575  	tracingPens       = 6   /* show details of pens that are made */
   576  	tracingCommands   = 7   /* show commands and operations before they are performed */
   577  	tracingRestores   = 8   /* show when a variable or internal is restored */
   578  	tracingMacros     = 9   /* show macros before they are expanded */
   579  	tracingEdges      = 10  /* show digitized edges as they are computed */
   580  	tracingOutput     = 11  /* show digitized edges as they are output */
   581  	tracingStats      = 12  /* show memory usage at end of job */
   582  	tracingOnline     = 13  /* show long diagnostics on terminal and in the log file */
   583  	year              = 14  /* the current year (e.g., 1984) */
   584  	month             = 15  /* the current month (e.g., 3 $\equiv$ March) */
   585  	day               = 16  /* the current day of the month */
   586  	time              = 17  /* the number of minutes past midnight when this job started */
   587  	charCode          = 18  /* the number of the next character to be output */
   588  	charExt           = 19  /* the extension code of the next character to be output */
   589  	charWd            = 20  /* the width of the next character to be output */
   590  	charHt            = 21  /* the height of the next character to be output */
   591  	charDp            = 22  /* the depth of the next character to be output */
   592  	charIc            = 23  /* the italic correction of the next character to be output */
   593  	charDx            = 24  /* the device's $x$ movement for the next character, in pixels */
   594  	charDy            = 25  /* the device's $y$ movement for the next character, in pixels */
   595  	designSize        = 26  /* the unit of measure used for |char_wd..char_ic|, in points */
   596  	hppp              = 27  /* the number of horizontal pixels per point */
   597  	vppp              = 28  /* the number of vertical pixels per point */
   598  	xOffset           = 29  /* horizontal displacement of shipped-out characters */
   599  	yOffset           = 30  /* vertical displacement of shipped-out characters */
   600  	pausing           = 31  /* positive to display lines on the terminal before they are read */
   601  	showstopping      = 32  /* positive to stop after each \&[show] command */
   602  	fontmaking        = 33  /* positive if font metric output is to be produced */
   603  	proofing          = 34  /* positive for proof mode, negative to suppress output */
   604  	smoothing         = 35  /* positive if moves are to be ``smoothed'' */
   605  	autorounding      = 36  /* controls path modification to ``good'' points */
   606  	granularity       = 37  /* autorounding uses this pixel size */
   607  	fillin            = 38  /* extra darkness of diagonal lines */
   608  	turningCheck      = 39  /* controls reorientation of clockwise paths */
   609  	warningCheck      = 40  /* controls error message when variable value is large */
   610  	boundaryChar      = 41  /* the boundary character for ligatures */
   611  	maxGivenInternal  = 41
   612  	digitClass        = 0   /* the class number of \.[0123456789] */
   613  	periodClass       = 1   /* the class number of `\..' */
   614  	spaceClass        = 2   /* the class number of spaces and nonstandard characters */
   615  	percentClass      = 3   /* the class number of `\.\%' */
   616  	stringClass       = 4   /* the class number of `\."' */
   617  	rightParenClass   = 8   /* the class number of `\.)' */
   618  	letterClass       = 9   /* letters and the underline character */
   619  	leftBracketClass  = 17  /* `\.[' */
   620  	rightBracketClass = 18  /* `\.]' */
   621  	invalidClass      = 20  /* bad character in the input */
   622  	maxClass          = 20  /* the largest class number */
   623  	hashBase          = 257 /* hashing actually starts here */
   624  	tokenNodeSize     = 2   /* the number of words in a large token node */
   625  	generalMacro      = 0   /* preface to a macro defined with a parameter list */
   626  	primaryMacro      = 1   /* preface to a macro with a \&[primary] parameter */
   627  	secondaryMacro    = 2   /* preface to a macro with a \&[secondary] parameter */
   628  	tertiaryMacro     = 3   /* preface to a macro with a \&[tertiary] parameter */
   629  	exprMacro         = 4   /* preface to a macro with an undelimited \&[expr] parameter */
   630  	ofMacro           = 5   // preface to a macro with
   631  	//   undelimited `\&[expr] |x| \&[of]~|y|' parameters
   632  
   633  	suffixMacro           = 6  /* preface to a macro with an undelimited \&[suffix] parameter */
   634  	textMacro             = 7  /* preface to a macro with an undelimited \&[text] parameter */
   635  	valueNodeSize         = 2  /* the number of words in a value node */
   636  	attrNodeSize          = 3  /* the number of words in an attribute node */
   637  	subscrNodeSize        = 3  /* the number of words in a subscript node */
   638  	collectiveSubscript   = 0  /* code for the attribute `\.[[]]' */
   639  	pairNodeSize          = 4  /* the number of words in a pair node */
   640  	transformNodeSize     = 12 /* the number of words in a transform node */
   641  	saveNodeSize          = 2  /* number of words per non-boundary save-stack node */
   642  	endpoint              = 0  /* |left_type| at path beginning and |right_type| at path end */
   643  	knotNodeSize          = 7  /* number of words in a knot node */
   644  	explicit              = 1  /* |left_type| or |right_type| when control points are known */
   645  	given                 = 2  /* |left_type| or |right_type| when a direction is given */
   646  	curl                  = 3  /* |left_type| or |right_type| when a curl is desired */
   647  	open                  = 4  /* |left_type| or |right_type| when \MF\ should choose the direction */
   648  	endCycle              = open + 1
   649  	moveIncrement         = 11 /* number of items pushed by |make_moves| */
   650  	zeroW                 = 4
   651  	rowNodeSize           = 2    /* number of words in a row header node */
   652  	zeroField             = 4096 /* amount added to coordinates to make them positive */
   653  	edgeHeaderSize        = 6    /* number of words in an edge-structure header */
   654  	fastCaseUp            = 60   /* for octants 1 and 4 */
   655  	fastCaseDown          = 61   /* for octants 5 and 8 */
   656  	slowCaseUp            = 62   /* for octants 2 and 3 */
   657  	slowCaseDown          = 63   /* for octants 6 and 7 */
   658  	axis                  = 0    /* a transition across the $x'$- or $y'$-axis */
   659  	diagonal              = 1    /* a transition where $y'=\pm x'$ */
   660  	doublePathCode        = 0    /* command modifier for `\&[doublepath]' */
   661  	contourCode           = 1    /* command modifier for `\&[contour]' */
   662  	alsoCode              = 2    /* command modifier for `\&[also]' */
   663  	penNodeSize           = 10
   664  	coordNodeSize         = 3
   665  	intPackets            = 20                          /* number of words to represent $U_k$, $V_k$, $X_k$, and $Y_k$ */
   666  	intIncrement          = intPackets + intPackets + 5 /* number of stack words per level */
   667  	maxPatience           = 5000
   668  	white                 = 0  /* background pixels */
   669  	black                 = 1  /* visible pixels */
   670  	sScale                = 64 /* the serial numbers are multiplied by this factor */
   671  	depNodeSize           = 2  /* the number of words per dependency node */
   672  	independentNeedingFix = 0
   673  	fractionThreshold     = 2685          /* a |fraction| coefficient less than this is zeroed */
   674  	halfFractionThreshold = 1342          /* half of |fraction_threshold| */
   675  	scaledThreshold       = 8             /* a |scaled| coefficient less than this is zeroed */
   676  	halfScaledThreshold   = 4             /* half of |scaled_threshold| */
   677  	independentBeingFixed = 1             /* this variable already appears in |s| */
   678  	foreverText           = maxInOpen + 1 /* |token_type| code for loop texts */
   679  	loopText              = maxInOpen + 2 /* |token_type| code for loop texts */
   680  	parameter             = maxInOpen + 3 /* |token_type| code for parameter texts */
   681  	backedUp              = maxInOpen + 4 /* |token_type| code for texts to be reread */
   682  	inserted              = maxInOpen + 5 /* |token_type| code for inserted texts */
   683  	macro                 = maxInOpen + 6 /* |token_type| code for macro replacement texts */
   684  	normal                = 0             /* |scanner_status| at ``quiet times'' */
   685  	skipping              = 1             /* |scanner_status| when false conditional text is being skipped */
   686  	flushing              = 2             /* |scanner_status| when junk after a statement is being ignored */
   687  	absorbing             = 3             /* |scanner_status| when a \&[text] parameter is being scanned */
   688  	varDefining           = 4             /* |scanner_status| when a \&[vardef] is being scanned */
   689  	opDefining            = 5             /* |scanner_status| when a macro \&[def] is being scanned */
   690  	loopDefining          = 6             /* |scanner_status| when a \&[for] loop is being scanned */
   691  	switch1               = 25            /* a label in |get_next| */
   692  	startNumericToken     = 85            /* another */
   693  	startDecimalToken     = 86            /* and another */
   694  	finNumericToken       = 87
   695  	/* and still another, although |goto| is considered harmful */
   696  	startDef             = 1                 /* command modifier for \&[def] */
   697  	varDef               = 2                 /* command modifier for \&[vardef] */
   698  	endDef               = 0                 /* command modifier for \&[enddef] */
   699  	startForever         = 1                 /* command modifier for \&[forever] */
   700  	endFor               = 0                 /* command modifier for \&[endfor] */
   701  	quote                = 0                 /* |macro_special| modifier for \&[quote] */
   702  	macroPrefix          = 1                 /* |macro_special| modifier for \.[\#\AT!] */
   703  	macroAt              = 2                 /* |macro_special| modifier for \.[\AT!] */
   704  	macroSuffix          = 3                 /* |macro_special| modifier for \.[\AT!\#] */
   705  	ifNodeSize           = 2                 /* number of words in stack entry for conditionals */
   706  	ifCode               = 1                 /* code for \&[if] being evaluated */
   707  	fiCode               = 2                 /* code for \&[fi] */
   708  	elseCode             = 3                 /* code for \&[else] */
   709  	elseIfCode           = 4                 /* code for \&[elseif] */
   710  	loopNodeSize         = 2                 /* the number of words in a loop control node */
   711  	progressionNodeSize  = 4                 /* the number of words in a progression node */
   712  	baseDefaultLength    = 18                /* length of the |MF_base_default| string */
   713  	baseAreaLength       = 8                 /* length of its area part */
   714  	baseExtLength        = 5                 /* length of its `\.[.base]' part */
   715  	baseExtension        = /* ".base" */ 742 /* the extension, as a \.[WEB] constant */
   716  	continuePath         = 25                /* a label inside of |scan_expression| */
   717  	finishPath           = 26                /* another */
   718  	showTokenCode        = 0                 /* show the meaning of a single token */
   719  	showStatsCode        = 1                 /* show current memory and string usage */
   720  	showCode             = 2                 /* show a list of expressions */
   721  	showVarCode          = 3                 /* show a variable and its descendents */
   722  	showDependenciesCode = 4                 /* show dependent variables in terms of independents */
   723  	dropCode             = 0                 /* command modifier for `\&[dropping]' */
   724  	keepCode             = 1                 /* command modifier for `\&[keeping]' */
   725  	messageCode          = 0
   726  	errMessageCode       = 1
   727  	errHelpCode          = 2
   728  	noTag                = 0 /* vanilla character */
   729  	ligTag               = 1 /* character has a ligature/kerning program */
   730  	listTag              = 2 /* character has a successor in a charlist */
   731  	extTag               = 3 /* character is extensible */
   732  	stopFlag             = 128 + minQuarterword
   733  	/* value indicating `\.[STOP]' in a lig/kern program */
   734  	kernFlag         = 128 + minQuarterword /* op code for a kern step */
   735  	slantCode        = 1
   736  	spaceCode        = 2
   737  	spaceStretchCode = 3
   738  	spaceShrinkCode  = 4
   739  	xHeightCode      = 5
   740  	quadCode         = 6
   741  	extraSpaceCode   = 7
   742  	charListCode     = 0
   743  	ligTableCode     = 1
   744  	extensibleCode   = 2
   745  	headerByteCode   = 3
   746  	fontDimenCode    = 4
   747  	gfIdByte         = 131 /* identifies the kind of \.[GF] files described here */
   748  	paint0           = 0   /* beginning of the \\[paint] commands */
   749  	paint1           = 64  // move right a given number of columns, then
   750  	//   black$[]\swap[]$white
   751  
   752  	boc        = 67   /* beginning of a character */
   753  	boc1       = 68   /* short form of |boc| */
   754  	eoc        = 69   /* end of a character */
   755  	skip0      = 70   /* skip no blank rows */
   756  	skip1      = 71   /* skip over blank rows */
   757  	newRow0    = 74   /* move down one row and then right */
   758  	maxNewRow  = 164  /* the largest \\[new\_row] command is |new_row_164| */
   759  	xxx1       = 239  /* for \&[special] strings */
   760  	xxx3       = 241  /* for long \&[special] strings */
   761  	yyy        = 243  /* for \&[numspecial] numbers */
   762  	charLoc    = 245  /* character locators in the postamble */
   763  	pre        = 247  /* preamble */
   764  	post       = 248  /* postamble beginning */
   765  	postPost   = 249  /* postamble ending */
   766  	offBase    = 6666 /* go here if the base file is unacceptable */
   767  	breakpoint = 888  /* place where a breakpoint is desirable */
   768  
   769  	// Constants in the outer block
   770  	memMax = 3000 // greatest index in \MF's internal |mem| array;
   771  	//   must be strictly less than |max_halfword|;
   772  	//   must be equal to |mem_top| in \.[INIMF], otherwise |>=mem_top|
   773  
   774  	maxInternal = 100 // maximum number of internal quantities
   775  	bufSize     = 500 // maximum number of characters simultaneously present in
   776  	//   current lines of open files; must not exceed |max_halfword|
   777  
   778  	errorLine     = 64 // width of context lines on terminal error messages
   779  	halfErrorLine = 32 // width of first lines of contexts in terminal
   780  	//   error messages; should be between 30 and |error_line-15|
   781  
   782  	maxPrintLine    = 72   // width of longest text lines output; should be at least 60
   783  	screenWidth     = 100  // number of pixels in each row of screen display
   784  	screenDepth     = 200  // number of pixels in each column of screen display
   785  	stackSize       = 30   // maximum number of simultaneous input sources
   786  	maxStrings      = 2000 // maximum number of strings; must not exceed |max_halfword|
   787  	stringVacancies = 8000 // the minimum number of characters that should be
   788  	//   available for the user's identifier names and strings,
   789  	//   after \MF's own error messages are stored
   790  
   791  	poolSize = 32000 // maximum number of characters in strings, including all
   792  	//   error messages and help texts, and the names of all identifiers;
   793  	//   must exceed |string_vacancies| by the total
   794  	//   length of \MF's own strings, which is currently about 22000
   795  
   796  	moveSize     = 5000 // space for storing moves in a single octant
   797  	maxWiggle    = 300  // number of autorounded points per cycle
   798  	gfBufSize    = 8    // size of the output buffer, must be a multiple of 8
   799  	fileNameSize = 40   // file names shouldn't be longer than this
   800  	poolName     = "MFbases:MF.POOL                         "
   801  	// string of length |file_name_size|; tells where the string pool appears
   802  	// \xref[MFbases]
   803  	pathSize    = 300 // maximum number of knots between breakpoints of a path
   804  	bistackSize = 785 // size of stack for bisection algorithms;
   805  	//   should probably be left at this value
   806  
   807  	headerSize   = 100  // maximum number of \.[TFM] header words, times~4
   808  	ligTableSize = 5000 // maximum number of ligature/kern steps, must be
   809  	//   at least 255 and at most 32510
   810  
   811  	maxKerns     = 500 // maximum number of distinct kern amounts
   812  	maxFontDimen = 50  // maximum number of \&[fontdimen] parameters
   813  )
   814  
   815  type (
   816  	// Types in the outer block
   817  	asciiCode = /* 0..255 */ byte // eight-bit numbers
   818  
   819  	eightBits = /* 0..255 */ byte // unsigned one-byte quantity
   820  	alphaFile = knuth.File        // files that contain textual data
   821  	byteFile  = knuth.File        // files that contain binary data
   822  
   823  	poolPointer     = /* 0..poolSize */ uint16   // for variables that point into |str_pool|
   824  	strNumber       = /* 0..maxStrings */ uint16 // for variables that point into |str_start|
   825  	packedAsciiCode = /* 0..255 */ byte          // elements of |str_pool| array
   826  
   827  	scaled      = int32            // this type is used for scaled integers
   828  	smallNumber = /* 0..63 */ byte // this type is self-explanatory
   829  
   830  	fraction = int32 // this type is used for scaled fractions
   831  
   832  	angle = int32 // this type is used for scaled angles
   833  
   834  	quarterword  = /* minQuarterword..maxQuarterword */ byte // 1/4 of a word
   835  	halfword     = /* 0..65535 */ uint16                     // 1/2 of a word
   836  	twoChoices   = /* 1..2 */ byte                           // used when there are two variants in a record
   837  	threeChoices = /* 1..3 */ byte                           // used when there are three variants in a record
   838  	twoHalves    struct{ data uint32 }
   839  	fourQuarters = struct {
   840  		b0 quarterword
   841  		b1 quarterword
   842  		b2 quarterword
   843  		b3 quarterword
   844  	}
   845  	memoryWord struct{ data uint32 }
   846  	wordFile   = knuth.File
   847  
   848  	commandCode = /* 1..maxCommandCode */ byte
   849  
   850  	screenRow  = /* 0..screenDepth */ byte // a row number on the screen
   851  	screenCol  = /* 0..screenWidth */ byte // a column number on the screen
   852  	transSpec  [101]screenCol              // a transition spec, see below
   853  	pixelColor = /* white..black */ byte   // specifies one of the two pixel values
   854  
   855  	windowNumber = /* 0..15 */ byte
   856  
   857  	inStateRecord = struct {
   858  		indexField                                  quarterword
   859  		startField, locField, limitField, nameField halfword
   860  	}
   861  
   862  	gfIndex = /* 0..gfBufSize */ byte // an index into the output buffer
   863  )
   864  
   865  func (r *memoryWord) hh() *twoHalves {
   866  	return (*twoHalves)(unsafe.Add(unsafe.Pointer(&r.data), 0))
   867  }
   868  
   869  func (r *memoryWord) int() *int32 {
   870  	return (*int32)(unsafe.Add(unsafe.Pointer(&r.data), 0))
   871  }
   872  
   873  func (r *memoryWord) qqqq() *fourQuarters {
   874  	return (*fourQuarters)(unsafe.Add(unsafe.Pointer(&r.data), 0))
   875  }
   876  
   877  func (r *twoHalves) b0() *quarterword {
   878  	return (*quarterword)(unsafe.Add(unsafe.Pointer(&r.data), 2))
   879  }
   880  
   881  func (r *twoHalves) b1() *quarterword {
   882  	return (*quarterword)(unsafe.Add(unsafe.Pointer(&r.data), 3))
   883  }
   884  
   885  func (r *twoHalves) lh() *halfword {
   886  	return (*halfword)(unsafe.Add(unsafe.Pointer(&r.data), 2))
   887  }
   888  
   889  func (r *twoHalves) rh() *halfword {
   890  	return (*halfword)(unsafe.Add(unsafe.Pointer(&r.data), 0))
   891  }
   892  
   893  type prg struct {
   894  	stdin, stdout, stderr knuth.File
   895  	// Global variables
   896  	bad int32 // is some ``constant'' wrong?
   897  
   898  	xord [256]asciiCode
   899  	// specifies conversion of input characters
   900  	xchr [256]char
   901  	// specifies conversion of output characters
   902  
   903  	nameOfFile [40]char
   904  
   905  	// on some systems this may be a \&[record] variable
   906  	nameLength/* 0..fileNameSize */ byte
   907  	// this many characters are actually
   908  	//   relevant in |name_of_file| (the rest are blank)
   909  
   910  	buffer                             [501]asciiCode // lines of characters being read
   911  	first/* 0..bufSize */ uint16       // the first unused position in |buffer|
   912  	last/* 0..bufSize */ uint16        // end of the line just input to |buffer|
   913  	maxBufStack/* 0..bufSize */ uint16 // largest index used in |buffer|
   914  
   915  	termIn  alphaFile // the terminal as an input file
   916  	termOut alphaFile // the terminal as an output file
   917  
   918  	strPool     [32001]packedAsciiCode // the characters
   919  	strStart    [2001]poolPointer      // the starting pointers
   920  	poolPtr     poolPointer            // first unused position in |str_pool|
   921  	strPtr      strNumber              // number of the current string being created
   922  	initPoolPtr poolPointer            // the starting value of |pool_ptr|
   923  	initStrPtr  strNumber              // the starting value of |str_ptr|
   924  	maxPoolPtr  poolPointer            // the maximum so far of |pool_ptr|
   925  	maxStrPtr   strNumber              // the maximum so far of |str_ptr|
   926  
   927  	strRef [2001] /* 0..maxStrRef */ byte
   928  
   929  	poolFile alphaFile // the string-pool file output by \.[TANGLE]
   930  
   931  	logFile                           alphaFile // transcript of \MF\ session
   932  	selector/* 0..maxSelector */ byte // where to print a message
   933  	dig                               [23] /* 0..15 */ byte // digits in a number being output
   934  	tally                             int32                 // the number of characters recently printed
   935  	termOffset/* 0..maxPrintLine */ byte
   936  	// the number of characters on the current terminal line
   937  	fileOffset/* 0..maxPrintLine */ byte
   938  	// the number of characters on the current file line
   939  	trickBuf [65]asciiCode // circular buffer for
   940  	//   pseudoprinting
   941  
   942  	trickCount int32 // threshold for pseudoprinting, explained later
   943  	firstCount int32 // another variable for pseudoprinting
   944  
   945  	interaction/* batchMode..errorStopMode */ byte // current level of interaction
   946  
   947  	deletionsAllowed                           bool // is it safe for |error| to call |get_next|?
   948  	history/* spotless..fatalErrorStop */ byte // has the source input been clean so far?
   949  	errorCount/*  -1..100 */ int8              // the number of scrolled errors since the
   950  	//   last statement ended
   951  
   952  	helpLine               [6]strNumber // helps for the next |error|
   953  	helpPtr/* 0..6 */ byte // the number of help lines present
   954  	useErrHelp             bool      // should the |err_help| string be shown?
   955  	errHelp                strNumber // a string set up by \&[errhelp]
   956  
   957  	interrupt     int32 // should \MF\ pause for instructions?
   958  	okToInterrupt bool  // should interrupts be observed?
   959  
   960  	arithError bool // has arithmetic overflow occurred recently?
   961  
   962  	twoToThe [31]int32 // powers of two
   963  	specLog  [28]int32 // special logarithms
   964  
   965  	specAtan [26]angle // $\arctan2^[-k]$ times $2^[20]\cdot180/\pi$
   966  
   967  	nSin, nCos fraction // results computed by |n_sin_cos|
   968  
   969  	randoms                 [55]fraction // the last 55 random values generated
   970  	jRandom/* 0..54 */ byte // the number of unused |randoms|
   971  
   972  	mem      [3001]memoryWord // the big dynamic storage area
   973  	loMemMax halfword         // the largest location of variable-size memory in use
   974  	hiMemMin halfword         // the smallest location of one-word memory in use
   975  
   976  	varUsed, dynUsed int32 // how much memory is in use
   977  
   978  	avail  halfword // head of the list of available one-word nodes
   979  	memEnd halfword // the last one-word node used in |mem|
   980  
   981  	rover halfword // points to some node in the list of empties
   982  
   983  	//   free: packed array [mem_min..mem_max] of boolean; [free cells]
   984  	// [ \hskip1em ] was_free: packed array [mem_min..mem_max] of boolean;
   985  	//   [previously free cells]
   986  	// [ \hskip1em ] was_mem_end, was_lo_max, was_hi_min: halfword ;
   987  	//   [previous |mem_end|, |lo_mem_max|, and |hi_mem_min|]
   988  	// [ \hskip1em ] panicking:boolean; [do we want to check memory constantly?]
   989  	// [  ]
   990  
   991  	internal [100]scaled
   992  	// the values of internal quantities
   993  	intName [100]strNumber
   994  	// their names
   995  	intPtr/* maxGivenInternal..maxInternal */ byte
   996  	// the maximum internal quantity defined so far
   997  
   998  	oldSetting/* 0..maxSelector */ byte
   999  	sysTime, sysDay, sysMonth, sysYear int32
  1000  	// date and time supplied by external system
  1001  
  1002  	charClass [256] /* 0..maxClass */ byte // the class numbers
  1003  
  1004  	hashUsed halfword // allocation pointer for |hash|
  1005  	stCount  int32    // total number of known identifiers
  1006  
  1007  	hash [2369]twoHalves // the hash table
  1008  	eqtb [2369]twoHalves // the equivalents
  1009  
  1010  	gPointer halfword // (global) parameter to the |forward| procedures
  1011  
  1012  	bigNodeSize [2]smallNumber
  1013  
  1014  	savePtr halfword // the most recently saved item
  1015  
  1016  	pathTail halfword // the node that links to the beginning of a path
  1017  
  1018  	deltaX, deltaY, delta [301]scaled // knot differences
  1019  	psi                   [300]angle  // turning angles
  1020  
  1021  	theta [301]angle    // values of $\theta_k$
  1022  	uu    [301]fraction // values of $u_k$
  1023  	vv    [301]angle    // values of $v_k$
  1024  	ww    [301]fraction // values of $w_k$
  1025  
  1026  	st, ct, sf, cf fraction // sines and cosines
  1027  
  1028  	move                            [5001]int32 // the recorded moves
  1029  	movePtr/* 0..moveSize */ uint16 // the number of items in the |move| list
  1030  
  1031  	bisectStack [786]int32
  1032  	bisectPtr/* 0..bistackSize */ uint16
  1033  
  1034  	curEdges halfword // the edge structure of current interest
  1035  	curWt    int32    // the edge weight of current interest
  1036  
  1037  	traceX  int32 // $x$~coordinate most recently shown in a trace
  1038  	traceY  int32 // $y$~coordinate most recently shown in a trace
  1039  	traceYy int32 // $y$~coordinate most recently encountered
  1040  
  1041  	octant/* firstOctant..sixthOctant */ byte // the current octant of interest
  1042  
  1043  	curX, curY scaled
  1044  	// outputs of |skew|, |unskew|, and a few other routines
  1045  
  1046  	octantDir [8]strNumber
  1047  
  1048  	curSpec                                           halfword // the principal output of |make_spec|
  1049  	turningNumber                                     int32    // another output of |make_spec|
  1050  	curPen                                            halfword // an implicit input of |make_spec|, used in autorounding
  1051  	curPathType/* doublePathCode..contourCode */ byte // likewise
  1052  	maxAllowed                                        scaled // coordinates must be at most this big
  1053  
  1054  	before, after                           [301]scaled   // data for |make_safe|
  1055  	nodeToRound                             [301]halfword // reference back to the path
  1056  	curRoundingPtr/* 0..maxWiggle */ uint16 // how many are being used
  1057  	maxRoundingPtr/* 0..maxWiggle */ uint16 // how many have been used
  1058  
  1059  	curGran scaled // the current granularity (which normally is |unity|)
  1060  
  1061  	octantNumber [8] /* 1..8 */ byte
  1062  	octantCode   [8] /* firstOctant..sixthOctant */ byte
  1063  
  1064  	revTurns bool // should we make U-turns in the English manner?
  1065  
  1066  	yCorr, xyCorr, zCorr [8] /* 0..1 */ byte
  1067  	xCorr                [8] /*  -1..1 */ int8
  1068  
  1069  	m0, n0, m1, n1        int32 // lattice point coordinates
  1070  	d0, d1/* 0..1 */ byte // displacement corrections
  1071  
  1072  	envMove [5001]int32
  1073  
  1074  	tolStep/* 0..6 */ byte // either 0 or 3, usually
  1075  
  1076  	curT, curTt int32 // controls and results of |cubic_intersection|
  1077  	timeToGo    int32 // this many backtracks before giving up
  1078  	maxT        int32 // maximum of $2^[l+1]$ so far achieved
  1079  
  1080  	delx, dely                        int32 // the components of $\Delta=2^l(w_0-z_0)$
  1081  	tol                               int32 // bound on the uncertainty in the overlap test
  1082  	uv, xy/* 0..bistackSize */ uint16 // pointers to the current packets of interest
  1083  	threeL                            int32 // |tol_step| times the bisection level
  1084  	apprT, apprTt                     int32 // best approximations known to the answers
  1085  
  1086  	//  screen_pixel:array[screen_row,screen_col] of pixel_color[ ;  ]
  1087  
  1088  	screenStarted bool // have the screen primitives been initialized?
  1089  	screenOk      bool // is it legitimate to call |blank_rectangle|,
  1090  	//   |paint_row|, and |update_screen|?
  1091  
  1092  	windowOpen [16]bool
  1093  	// has this window been opened?
  1094  	leftCol [16]screenCol
  1095  	// leftmost column position on screen
  1096  	rightCol [16]screenCol
  1097  	// rightmost column position, plus~1
  1098  	topRow [16]screenRow
  1099  	// topmost row position on screen
  1100  	botRow [16]screenRow
  1101  	// bottommost row position, plus~1
  1102  	mWindow [16]int32
  1103  	// offset between user and screen columns
  1104  	nWindow [16]int32
  1105  	// offset between user and screen rows
  1106  	windowTime [16]int32
  1107  	// it has been updated this often
  1108  
  1109  	rowTransition transSpec // an array of |black|/|white| transitions
  1110  
  1111  	serialNo int32 // the most recent serial number, times |s_scale|
  1112  
  1113  	fixNeeded  bool     // does at least one |independent| variable need scaling?
  1114  	watchCoefs bool     // should we scale coefficients that exceed |coef_bound|?
  1115  	depFinal   halfword // location of the constant term and final link
  1116  
  1117  	curCmd eightBits // current command set by |get_next|
  1118  	curMod int32     // operand of current command
  1119  	curSym halfword  // hash address of current symbol
  1120  
  1121  	inputStack                        [31]inStateRecord
  1122  	inputPtr/* 0..stackSize */ byte   // first unused location of |input_stack|
  1123  	maxInStack/* 0..stackSize */ byte // largest value of |input_ptr| when pushing
  1124  	curInput                          inStateRecord // the ``top'' input state
  1125  
  1126  	inOpen/* 0..maxInOpen */ byte     // the number of lines in the buffer, less one
  1127  	openParens/* 0..maxInOpen */ byte // the number of open text files
  1128  	inputFile                         [6]alphaFile
  1129  	line                              int32 // current line number in the current source file
  1130  	lineStack                         [6]int32
  1131  
  1132  	paramStack [151]halfword
  1133  	// token list pointers for parameters
  1134  	paramPtr/* 0..paramSize */ byte // first unused entry in |param_stack|
  1135  	maxParamStack                   int32
  1136  	// largest value of |param_ptr|
  1137  
  1138  	filePtr/* 0..stackSize */ byte // shallowest level shown by |show_context|
  1139  
  1140  	scannerStatus/* normal..loopDefining */ byte // are we scanning at high speed?
  1141  	warningInfo                                  int32 // if so, what else do we need to know,
  1142  	//     in case an error occurs?
  1143  
  1144  	forceEof bool // should the next \&[input] be aborted early?
  1145  
  1146  	bgLoc, egLoc/* 1..hashBase+2112 */ uint16
  1147  	// hash addresses of `\.[begingroup]' and `\.[endgroup]'
  1148  
  1149  	condPtr                              halfword // top of the condition stack
  1150  	ifLimit/* normal..elseIfCode */ byte // upper bound on |fi_or_else| codes
  1151  	curIf                                smallNumber // type of conditional being worked on
  1152  	ifLine                               int32       // line where that conditional began
  1153  
  1154  	loopPtr halfword // top of the loop-control-node stack
  1155  
  1156  	curName strNumber // name of file just scanned
  1157  	curArea strNumber // file area just scanned, or \.[""]
  1158  	curExt  strNumber // file extension just scanned, or \.[""]
  1159  
  1160  	areaDelimiter poolPointer // the most recent `\.>' or `\.:', if any
  1161  	extDelimiter  poolPointer // the relevant `\..', if any
  1162  
  1163  	mfBaseDefault [18]char
  1164  
  1165  	jobName   strNumber // principal file name
  1166  	logOpened bool      // has the transcript file been opened?
  1167  	logName   strNumber // full name of the log file
  1168  
  1169  	gfExt strNumber // default extension for the output file
  1170  
  1171  	gfFile         byteFile  // the generic font output goes here
  1172  	outputFileName strNumber // full name of the output file
  1173  
  1174  	curType smallNumber // the type of the expression just found
  1175  	curExp  int32       // the value of the expression just found
  1176  
  1177  	maxC [2]int32
  1178  	// max coefficient magnitude
  1179  	maxPtr [2]halfword
  1180  	// where |p| occurs with |max_c|
  1181  	maxLink [2]halfword
  1182  	// other occurrences of |p|
  1183  
  1184  	varFlag/* 0..maxCommandCode */ byte // command that wants a variable
  1185  
  1186  	txx, txy, tyx, tyy, tx, ty scaled // current transform coefficients
  1187  
  1188  	startSym halfword // a symbolic token to insert at beginning of job
  1189  
  1190  	longHelpSeen bool // has the long \&[errmessage] help been used?
  1191  
  1192  	tfmFile        byteFile  // the font metric output goes here
  1193  	metricFileName strNumber // full name of the font metric file
  1194  
  1195  	bc, ec        eightBits                          // smallest and largest character codes shipped out
  1196  	tfmWidth      [256]scaled                        // \&[charwd] values
  1197  	tfmHeight     [256]scaled                        // \&[charht] values
  1198  	tfmDepth      [256]scaled                        // \&[chardp] values
  1199  	tfmItalCorr   [256]scaled                        // \&[charic] values
  1200  	charExists    [256]bool                          // has this code been shipped out?
  1201  	charTag       [256] /* noTag..extTag */ byte     // |remainder| category
  1202  	charRemainder [256] /* 0..ligTableSize */ uint16 // the |remainder| byte
  1203  	headerByte    [100] /*  -1..255 */ int16
  1204  	// bytes of the \.[TFM] header, or $-1$ if unset
  1205  	ligKern                              [5001]fourQuarters // the ligature/kern table
  1206  	nl/* 0..32767-256 */ uint16          // the number of ligature/kern steps so far
  1207  	kern                                 [501]scaled // distinct kerning amounts
  1208  	nk/* 0..maxKerns */ uint16           // the number of distinct kerns so far
  1209  	exten                                [256]fourQuarters // extensible character recipes
  1210  	ne/* 0..256 */ uint16                // the number of extensible characters so far
  1211  	param                                [50]scaled // \&[fontdimen] parameters
  1212  	np/* 0..maxFontDimen */ byte         // the largest \&[fontdimen] parameter specified so far
  1213  	nw, nh, nd, ni/* 0..256 */ uint16    // sizes of \.[TFM] subtables
  1214  	skipTable                            [256] /* 0..ligTableSize */ uint16 // local label status
  1215  	lkStarted                            bool                               // has there been a lig/kern step in this command yet?
  1216  	bchar                                int32                              // right boundary character
  1217  	bchLabel/* 0..ligTableSize */ uint16 // left boundary starting location
  1218  	ll, lll/* 0..ligTableSize */ uint16  // registers used for lig/kern processing
  1219  	labelLoc                             [257] /*  -1..ligTableSize */ int16 // lig/kern starting addresses
  1220  	labelChar                            [256]eightBits                      // characters for |label_loc|
  1221  	labelPtr/* 0..256 */ uint16          // highest position occupied in |label_loc|
  1222  
  1223  	perturbation scaled // quantity related to \.[TFM] rounding
  1224  	excess       int32  // the list is this much too long
  1225  
  1226  	dimenHead [4]halfword // lists of \.[TFM] dimensions
  1227  
  1228  	maxTfmDimen scaled // bound on widths, heights, kerns, etc.
  1229  	tfmChanged  int32  // the number of data entries that were out of bounds
  1230  
  1231  	gfMinM, gfMaxM, gfMinN, gfMaxN int32      // bounding rectangle
  1232  	gfPrevPtr                      int32      // where the present/next character started/starts
  1233  	totalChars                     int32      // the number of characters output so far
  1234  	charPtr                        [256]int32 // where individual characters started
  1235  	gfDx, gfDy                     [256]int32 // device escapements
  1236  
  1237  	gfBuf    [9]eightBits // buffer for \.[GF] output
  1238  	halfBuf  gfIndex      // half of |gf_buf_size|
  1239  	gfLimit  gfIndex      // end of the current half buffer
  1240  	gfPtr    gfIndex      // the next available buffer address
  1241  	gfOffset int32        // |gf_buf_size| times the number of times the
  1242  	//   output buffer has been fully emptied
  1243  
  1244  	bocC, bocP int32 // parameters of the next |boc| command
  1245  
  1246  	baseIdent strNumber
  1247  
  1248  	baseFile wordFile // for input or output of base information
  1249  
  1250  	readyAlready int32 // a sacrifice of purity for economy
  1251  }
  1252  
  1253  func (prg *prg) initialize() { // this procedure gets things started properly
  1254  	var (
  1255  		// Local variables for initialization
  1256  		i int32
  1257  
  1258  		k int32 // all-purpose loop index
  1259  	)
  1260  	prg.xchr[040] = ' '
  1261  	prg.xchr[041] = '!'
  1262  	prg.xchr[042] = '"'
  1263  	prg.xchr[043] = '#'
  1264  	prg.xchr[044] = '$'
  1265  	prg.xchr[045] = '%'
  1266  	prg.xchr[046] = '&'
  1267  	prg.xchr[047] = '\''
  1268  
  1269  	prg.xchr[050] = '('
  1270  	prg.xchr[051] = ')'
  1271  	prg.xchr[052] = '*'
  1272  	prg.xchr[053] = '+'
  1273  	prg.xchr[054] = ','
  1274  	prg.xchr[055] = '-'
  1275  	prg.xchr[056] = '.'
  1276  	prg.xchr[057] = '/'
  1277  
  1278  	prg.xchr[060] = '0'
  1279  	prg.xchr[061] = '1'
  1280  	prg.xchr[062] = '2'
  1281  	prg.xchr[063] = '3'
  1282  	prg.xchr[064] = '4'
  1283  	prg.xchr[065] = '5'
  1284  	prg.xchr[066] = '6'
  1285  	prg.xchr[067] = '7'
  1286  
  1287  	prg.xchr[070] = '8'
  1288  	prg.xchr[071] = '9'
  1289  	prg.xchr[072] = ':'
  1290  	prg.xchr[073] = ';'
  1291  	prg.xchr[074] = '<'
  1292  	prg.xchr[075] = '='
  1293  	prg.xchr[076] = '>'
  1294  	prg.xchr[077] = '?'
  1295  
  1296  	prg.xchr[0100] = '@'
  1297  	prg.xchr[0101] = 'A'
  1298  	prg.xchr[0102] = 'B'
  1299  	prg.xchr[0103] = 'C'
  1300  	prg.xchr[0104] = 'D'
  1301  	prg.xchr[0105] = 'E'
  1302  	prg.xchr[0106] = 'F'
  1303  	prg.xchr[0107] = 'G'
  1304  
  1305  	prg.xchr[0110] = 'H'
  1306  	prg.xchr[0111] = 'I'
  1307  	prg.xchr[0112] = 'J'
  1308  	prg.xchr[0113] = 'K'
  1309  	prg.xchr[0114] = 'L'
  1310  	prg.xchr[0115] = 'M'
  1311  	prg.xchr[0116] = 'N'
  1312  	prg.xchr[0117] = 'O'
  1313  
  1314  	prg.xchr[0120] = 'P'
  1315  	prg.xchr[0121] = 'Q'
  1316  	prg.xchr[0122] = 'R'
  1317  	prg.xchr[0123] = 'S'
  1318  	prg.xchr[0124] = 'T'
  1319  	prg.xchr[0125] = 'U'
  1320  	prg.xchr[0126] = 'V'
  1321  	prg.xchr[0127] = 'W'
  1322  
  1323  	prg.xchr[0130] = 'X'
  1324  	prg.xchr[0131] = 'Y'
  1325  	prg.xchr[0132] = 'Z'
  1326  	prg.xchr[0133] = '['
  1327  	prg.xchr[0134] = '\\'
  1328  	prg.xchr[0135] = ']'
  1329  	prg.xchr[0136] = '^'
  1330  	prg.xchr[0137] = '_'
  1331  
  1332  	prg.xchr[0140] = '`'
  1333  	prg.xchr[0141] = 'a'
  1334  	prg.xchr[0142] = 'b'
  1335  	prg.xchr[0143] = 'c'
  1336  	prg.xchr[0144] = 'd'
  1337  	prg.xchr[0145] = 'e'
  1338  	prg.xchr[0146] = 'f'
  1339  	prg.xchr[0147] = 'g'
  1340  
  1341  	prg.xchr[0150] = 'h'
  1342  	prg.xchr[0151] = 'i'
  1343  	prg.xchr[0152] = 'j'
  1344  	prg.xchr[0153] = 'k'
  1345  	prg.xchr[0154] = 'l'
  1346  	prg.xchr[0155] = 'm'
  1347  	prg.xchr[0156] = 'n'
  1348  	prg.xchr[0157] = 'o'
  1349  
  1350  	prg.xchr[0160] = 'p'
  1351  	prg.xchr[0161] = 'q'
  1352  	prg.xchr[0162] = 'r'
  1353  	prg.xchr[0163] = 's'
  1354  	prg.xchr[0164] = 't'
  1355  	prg.xchr[0165] = 'u'
  1356  	prg.xchr[0166] = 'v'
  1357  	prg.xchr[0167] = 'w'
  1358  
  1359  	prg.xchr[0170] = 'x'
  1360  	prg.xchr[0171] = 'y'
  1361  	prg.xchr[0172] = 'z'
  1362  	prg.xchr[0173] = '{'
  1363  	prg.xchr[0174] = '|'
  1364  	prg.xchr[0175] = '}'
  1365  	prg.xchr[0176] = '~'
  1366  
  1367  	for ii := int32(0); ii <= 037; ii++ {
  1368  		i = ii
  1369  		_ = i
  1370  		prg.xchr[i] = ' '
  1371  	}
  1372  	for ii := int32(0177); ii <= 0377; ii++ {
  1373  		i = ii
  1374  		_ = i
  1375  		prg.xchr[i] = ' '
  1376  	}
  1377  
  1378  	for ii := int32(firstTextChar); ii <= lastTextChar; ii++ {
  1379  		i = ii
  1380  		_ = i
  1381  		prg.xord[char(i)] = 0177
  1382  	}
  1383  	for ii := int32(0200); ii <= 0377; ii++ {
  1384  		i = ii
  1385  		_ = i
  1386  		prg.xord[prg.xchr[i]] = byte(i)
  1387  	}
  1388  	for ii := int32(0); ii <= 0176; ii++ {
  1389  		i = ii
  1390  		_ = i
  1391  		prg.xord[prg.xchr[i]] = byte(i)
  1392  	}
  1393  
  1394  	prg.interaction = byte(errorStopMode)
  1395  
  1396  	prg.deletionsAllowed = true
  1397  	prg.errorCount = 0 // |history| is initialized elsewhere
  1398  
  1399  	prg.helpPtr = 0
  1400  	prg.useErrHelp = false
  1401  	prg.errHelp = 0
  1402  
  1403  	prg.interrupt = 0
  1404  	prg.okToInterrupt = true
  1405  
  1406  	prg.arithError = false
  1407  
  1408  	prg.twoToThe[0] = 1
  1409  	for ii := int32(1); ii <= 30; ii++ {
  1410  		k = ii
  1411  		_ = k
  1412  		prg.twoToThe[k] = 2 * prg.twoToThe[k-1]
  1413  	}
  1414  	prg.specLog[1-1] = 93032640
  1415  	prg.specLog[2-1] = 38612034
  1416  	prg.specLog[3-1] = 17922280
  1417  	prg.specLog[4-1] = 8662214
  1418  	prg.specLog[5-1] = 4261238
  1419  	prg.specLog[6-1] = 2113709
  1420  	prg.specLog[7-1] = 1052693
  1421  	prg.specLog[8-1] = 525315
  1422  	prg.specLog[9-1] = 262400
  1423  	prg.specLog[10-1] = 131136
  1424  	prg.specLog[11-1] = 65552
  1425  	prg.specLog[12-1] = 32772
  1426  	prg.specLog[13-1] = 16385
  1427  	for ii := int32(14); ii <= 27; ii++ {
  1428  		k = ii
  1429  		_ = k
  1430  		prg.specLog[k-1] = prg.twoToThe[27-k]
  1431  	}
  1432  	prg.specLog[28-1] = 1
  1433  
  1434  	prg.specAtan[1-1] = 27855475
  1435  	prg.specAtan[2-1] = 14718068
  1436  	prg.specAtan[3-1] = 7471121
  1437  	prg.specAtan[4-1] = 3750058
  1438  	prg.specAtan[5-1] = 1876857
  1439  	prg.specAtan[6-1] = 938658
  1440  	prg.specAtan[7-1] = 469357
  1441  	prg.specAtan[8-1] = 234682
  1442  	prg.specAtan[9-1] = 117342
  1443  	prg.specAtan[10-1] = 58671
  1444  	prg.specAtan[11-1] = 29335
  1445  	prg.specAtan[12-1] = 14668
  1446  	prg.specAtan[13-1] = 7334
  1447  	prg.specAtan[14-1] = 3667
  1448  	prg.specAtan[15-1] = 1833
  1449  	prg.specAtan[16-1] = 917
  1450  	prg.specAtan[17-1] = 458
  1451  	prg.specAtan[18-1] = 229
  1452  	prg.specAtan[19-1] = 115
  1453  	prg.specAtan[20-1] = 57
  1454  	prg.specAtan[21-1] = 29
  1455  	prg.specAtan[22-1] = 14
  1456  	prg.specAtan[23-1] = 7
  1457  	prg.specAtan[24-1] = 4
  1458  	prg.specAtan[25-1] = 2
  1459  	prg.specAtan[26-1] = 1
  1460  
  1461  	//  was_mem_end:=mem_min; [indicate that everything was previously free]
  1462  	// was_lo_max:=mem_min; was_hi_min:=mem_max;
  1463  	// panicking:=false;
  1464  	// [  ]
  1465  
  1466  	for ii := int32(1); ii <= maxGivenInternal; ii++ {
  1467  		k = ii
  1468  		_ = k
  1469  		prg.internal[k-1] = 0
  1470  	}
  1471  	prg.intPtr = byte(maxGivenInternal)
  1472  
  1473  	for ii := int32('0'); ii <= '9'; ii++ {
  1474  		k = ii
  1475  		_ = k
  1476  		prg.charClass[k] = byte(digitClass)
  1477  	}
  1478  	prg.charClass['.'] = byte(periodClass)
  1479  	prg.charClass[' '] = byte(spaceClass)
  1480  	prg.charClass['%'] = byte(percentClass)
  1481  	prg.charClass['"'] = byte(stringClass)
  1482  
  1483  	prg.charClass[','] = 5
  1484  	prg.charClass[';'] = 6
  1485  	prg.charClass['('] = 7
  1486  	prg.charClass[')'] = byte(rightParenClass)
  1487  	for ii := int32('A'); ii <= 'Z'; ii++ {
  1488  		k = ii
  1489  		_ = k
  1490  		prg.charClass[k] = byte(letterClass)
  1491  	}
  1492  	for ii := int32('a'); ii <= 'z'; ii++ {
  1493  		k = ii
  1494  		_ = k
  1495  		prg.charClass[k] = byte(letterClass)
  1496  	}
  1497  	prg.charClass['_'] = byte(letterClass)
  1498  
  1499  	prg.charClass['<'] = 10
  1500  	prg.charClass['='] = 10
  1501  	prg.charClass['>'] = 10
  1502  	prg.charClass[':'] = 10
  1503  	prg.charClass['|'] = 10
  1504  
  1505  	prg.charClass['`'] = 11
  1506  	prg.charClass['\''] = 11
  1507  
  1508  	prg.charClass['+'] = 12
  1509  	prg.charClass['-'] = 12
  1510  
  1511  	prg.charClass['/'] = 13
  1512  	prg.charClass['*'] = 13
  1513  	prg.charClass['\\'] = 13
  1514  
  1515  	prg.charClass['!'] = 14
  1516  	prg.charClass['?'] = 14
  1517  
  1518  	prg.charClass['#'] = 15
  1519  	prg.charClass['&'] = 15
  1520  	prg.charClass['@'] = 15
  1521  	prg.charClass['$'] = 15
  1522  
  1523  	prg.charClass['^'] = 16
  1524  	prg.charClass['~'] = 16
  1525  
  1526  	prg.charClass['['] = byte(leftBracketClass)
  1527  	prg.charClass[']'] = byte(rightBracketClass)
  1528  
  1529  	prg.charClass['{'] = 19
  1530  	prg.charClass['}'] = 19
  1531  
  1532  	for ii := int32(0); ii <= ' '-1; ii++ {
  1533  		k = ii
  1534  		_ = k
  1535  		prg.charClass[k] = byte(invalidClass)
  1536  	}
  1537  	for ii := int32(127); ii <= 255; ii++ {
  1538  		k = ii
  1539  		_ = k
  1540  		prg.charClass[k] = byte(invalidClass)
  1541  	}
  1542  
  1543  	*prg.hash[1-1].lh() = 0
  1544  	*prg.hash[1-1].rh() = 0
  1545  	*prg.eqtb[1-1].lh() = uint16(tagToken)
  1546  	*prg.eqtb[1-1].rh() = uint16(memMin)
  1547  	for ii := int32(2); ii <= hashBase+hashSize+12; ii++ {
  1548  		k = ii
  1549  		_ = k
  1550  		prg.hash[k-1] = prg.hash[1-1]
  1551  		prg.eqtb[k-1] = prg.eqtb[1-1]
  1552  	}
  1553  
  1554  	prg.bigNodeSize[transformType-13] = byte(transformNodeSize)
  1555  	prg.bigNodeSize[pairType-13] = byte(pairNodeSize)
  1556  
  1557  	prg.savePtr = uint16(memMin)
  1558  
  1559  	prg.octantDir[firstOctant-1] = /* "ENE" */ 548
  1560  	prg.octantDir[secondOctant-1] = /* "NNE" */ 549
  1561  	prg.octantDir[thirdOctant-1] = /* "NNW" */ 550
  1562  	prg.octantDir[fourthOctant-1] = /* "WNW" */ 551
  1563  	prg.octantDir[fifthOctant-1] = /* "WSW" */ 552
  1564  	prg.octantDir[sixthOctant-1] = /* "SSW" */ 553
  1565  	prg.octantDir[seventhOctant-1] = /* "SSE" */ 554
  1566  	prg.octantDir[eighthOctant-1] = /* "ESE" */ 555
  1567  
  1568  	prg.maxRoundingPtr = 0
  1569  
  1570  	prg.octantCode[1-1] = byte(firstOctant)
  1571  	prg.octantCode[2-1] = byte(secondOctant)
  1572  	prg.octantCode[3-1] = byte(thirdOctant)
  1573  	prg.octantCode[4-1] = byte(fourthOctant)
  1574  	prg.octantCode[5-1] = byte(fifthOctant)
  1575  	prg.octantCode[6-1] = byte(sixthOctant)
  1576  	prg.octantCode[7-1] = byte(seventhOctant)
  1577  	prg.octantCode[8-1] = byte(eighthOctant)
  1578  	for ii := int32(1); ii <= 8; ii++ {
  1579  		k = ii
  1580  		_ = k
  1581  		prg.octantNumber[prg.octantCode[k-1]-1] = byte(k)
  1582  	}
  1583  
  1584  	prg.revTurns = false
  1585  
  1586  	prg.xCorr[firstOctant-1] = 0
  1587  	prg.yCorr[firstOctant-1] = 0
  1588  	prg.xyCorr[firstOctant-1] = 0
  1589  
  1590  	prg.xCorr[secondOctant-1] = 0
  1591  	prg.yCorr[secondOctant-1] = 0
  1592  	prg.xyCorr[secondOctant-1] = 1
  1593  
  1594  	prg.xCorr[thirdOctant-1] = int8(-1)
  1595  	prg.yCorr[thirdOctant-1] = 1
  1596  	prg.xyCorr[thirdOctant-1] = 0
  1597  
  1598  	prg.xCorr[fourthOctant-1] = 1
  1599  	prg.yCorr[fourthOctant-1] = 0
  1600  	prg.xyCorr[fourthOctant-1] = 1
  1601  
  1602  	prg.xCorr[fifthOctant-1] = 0
  1603  	prg.yCorr[fifthOctant-1] = 1
  1604  	prg.xyCorr[fifthOctant-1] = 1
  1605  
  1606  	prg.xCorr[sixthOctant-1] = 0
  1607  	prg.yCorr[sixthOctant-1] = 1
  1608  	prg.xyCorr[sixthOctant-1] = 0
  1609  
  1610  	prg.xCorr[seventhOctant-1] = 1
  1611  	prg.yCorr[seventhOctant-1] = 0
  1612  	prg.xyCorr[seventhOctant-1] = 1
  1613  
  1614  	prg.xCorr[eighthOctant-1] = int8(-1)
  1615  	prg.yCorr[eighthOctant-1] = 1
  1616  	prg.xyCorr[eighthOctant-1] = 0
  1617  
  1618  	for ii := int32(1); ii <= 8; ii++ {
  1619  		k = ii
  1620  		_ = k
  1621  		prg.zCorr[k-1] = byte(int32(prg.xyCorr[k-1]) - int32(prg.xCorr[k-1]))
  1622  	}
  1623  
  1624  	prg.screenStarted = false
  1625  	prg.screenOk = false
  1626  
  1627  	for ii := int32(0); ii <= 15; ii++ {
  1628  		k = ii
  1629  		_ = k
  1630  		prg.windowOpen[k] = false
  1631  		prg.windowTime[k] = 0
  1632  	}
  1633  
  1634  	prg.fixNeeded = false
  1635  	prg.watchCoefs = true
  1636  
  1637  	prg.condPtr = uint16(memMin)
  1638  	prg.ifLimit = byte(normal)
  1639  	prg.curIf = 0
  1640  	prg.ifLine = 0
  1641  
  1642  	prg.loopPtr = uint16(memMin)
  1643  
  1644  	strcopy(prg.mfBaseDefault[:], "MFbases:plain.base")
  1645  	// \xref[MFbases]
  1646  	// \xref[plain]
  1647  	// \xref[system dependencies]
  1648  
  1649  	prg.curExp = 0
  1650  
  1651  	prg.varFlag = 0
  1652  
  1653  	prg.startSym = 0
  1654  
  1655  	prg.longHelpSeen = false
  1656  
  1657  	for ii := int32(0); ii <= 255; ii++ {
  1658  		k = ii
  1659  		_ = k
  1660  		prg.tfmWidth[k] = 0
  1661  		prg.tfmHeight[k] = 0
  1662  		prg.tfmDepth[k] = 0
  1663  		prg.tfmItalCorr[k] = 0
  1664  		prg.charExists[k] = false
  1665  		prg.charTag[k] = byte(noTag)
  1666  		prg.charRemainder[k] = 0
  1667  		prg.skipTable[k] = uint16(ligTableSize)
  1668  	}
  1669  	for ii := int32(1); ii <= headerSize; ii++ {
  1670  		k = ii
  1671  		_ = k
  1672  		prg.headerByte[k-1] = int16(-1)
  1673  	}
  1674  	prg.bc = 255
  1675  	prg.ec = 0
  1676  	prg.nl = 0
  1677  	prg.nk = 0
  1678  	prg.ne = 0
  1679  	prg.np = 0
  1680  
  1681  	prg.internal[boundaryChar-1] = -0200000
  1682  	prg.bchLabel = uint16(ligTableSize)
  1683  
  1684  	prg.labelLoc[0] = int16(-1)
  1685  	prg.labelPtr = 0
  1686  
  1687  	prg.gfPrevPtr = 0
  1688  	prg.totalChars = 0
  1689  
  1690  	prg.halfBuf = byte(gfBufSize / 2)
  1691  	prg.gfLimit = byte(gfBufSize)
  1692  	prg.gfPtr = 0
  1693  	prg.gfOffset = 0
  1694  
  1695  	prg.baseIdent = 0
  1696  
  1697  }
  1698  
  1699  // \4
  1700  // Basic printing procedures
  1701  func (prg *prg) printLn() {
  1702  	switch prg.selector {
  1703  	case termAndLog:
  1704  		prg.termOut.Writeln()
  1705  		prg.logFile.Writeln()
  1706  		prg.termOffset = 0
  1707  		prg.fileOffset = 0
  1708  
  1709  	case logOnly:
  1710  		prg.logFile.Writeln()
  1711  		prg.fileOffset = 0
  1712  
  1713  	case termOnly:
  1714  		prg.termOut.Writeln()
  1715  		prg.termOffset = 0
  1716  
  1717  	case noPrint, pseudo, newString:
  1718  	} // there are no other cases
  1719  } // note that |tally| is not affected
  1720  
  1721  func (prg *prg) printChar(s asciiCode) {
  1722  	switch prg.selector {
  1723  	case termAndLog:
  1724  		prg.termOut.Write(string(rune(prg.xchr[s])))
  1725  		prg.logFile.Write(string(rune(prg.xchr[s])))
  1726  		prg.termOffset = byte(int32(prg.termOffset) + 1)
  1727  		prg.fileOffset = byte(int32(prg.fileOffset) + 1)
  1728  		if int32(prg.termOffset) == maxPrintLine {
  1729  			prg.termOut.Writeln()
  1730  			prg.termOffset = 0
  1731  		}
  1732  		if int32(prg.fileOffset) == maxPrintLine {
  1733  			prg.logFile.Writeln()
  1734  			prg.fileOffset = 0
  1735  		}
  1736  
  1737  	case logOnly:
  1738  		prg.logFile.Write(string(rune(prg.xchr[s])))
  1739  		prg.fileOffset = byte(int32(prg.fileOffset) + 1)
  1740  		if int32(prg.fileOffset) == maxPrintLine {
  1741  			prg.printLn()
  1742  		}
  1743  
  1744  	case termOnly:
  1745  		prg.termOut.Write(string(rune(prg.xchr[s])))
  1746  		prg.termOffset = byte(int32(prg.termOffset) + 1)
  1747  		if int32(prg.termOffset) == maxPrintLine {
  1748  			prg.printLn()
  1749  		}
  1750  
  1751  	case noPrint:
  1752  	case pseudo:
  1753  		if prg.tally < prg.trickCount {
  1754  			prg.trickBuf[prg.tally%errorLine] = s
  1755  		}
  1756  	case newString:
  1757  		if int32(prg.poolPtr) < poolSize {
  1758  			prg.strPool[prg.poolPtr] = s
  1759  			prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  1760  		}
  1761  		// we drop characters if the string space is full
  1762  	} // there are no other cases
  1763  	prg.tally = prg.tally + 1
  1764  }
  1765  
  1766  func (prg *prg) print(s int32) { // prints string |s|
  1767  	var (
  1768  		j poolPointer // current character code position
  1769  	)
  1770  	if s < 0 || s >= int32(prg.strPtr) {
  1771  		s = /* "???" */ 259
  1772  	} // this can't happen
  1773  	// \xref[???]
  1774  	if s < 256 && int32(prg.selector) > pseudo {
  1775  		prg.printChar(asciiCode(s))
  1776  	} else {
  1777  		j = prg.strStart[s]
  1778  		for int32(j) < int32(prg.strStart[s+1]) {
  1779  			prg.printChar(prg.strPool[j])
  1780  			j = uint16(int32(j) + 1)
  1781  		}
  1782  	}
  1783  }
  1784  
  1785  func (prg *prg) slowPrint(s int32) { // prints string |s|
  1786  	var (
  1787  		j poolPointer // current character code position
  1788  	)
  1789  	if s < 0 || s >= int32(prg.strPtr) {
  1790  		s = /* "???" */ 259
  1791  	} // this can't happen
  1792  	// \xref[???]
  1793  	if s < 256 && int32(prg.selector) > pseudo {
  1794  		prg.printChar(asciiCode(s))
  1795  	} else {
  1796  		j = prg.strStart[s]
  1797  		for int32(j) < int32(prg.strStart[s+1]) {
  1798  			prg.print(int32(prg.strPool[j]))
  1799  			j = uint16(int32(j) + 1)
  1800  		}
  1801  	}
  1802  }
  1803  
  1804  func (prg *prg) printNl(s strNumber) {
  1805  	if int32(prg.termOffset) > 0 && prg.selector&1 != 0 || int32(prg.fileOffset) > 0 && int32(prg.selector) >= logOnly {
  1806  		prg.printLn()
  1807  	}
  1808  	prg.print(int32(s))
  1809  }
  1810  
  1811  func (prg *prg) printTheDigs(k eightBits) {
  1812  	for int32(k) > 0 {
  1813  		k = byte(int32(k) - 1)
  1814  		prg.printChar(asciiCode('0' + int32(prg.dig[k])))
  1815  	}
  1816  }
  1817  
  1818  func (prg *prg) printInt(n int32) { // prints an integer in decimal form
  1819  	var (
  1820  		k/* 0..23 */ byte       // index to current digit; we assume that $\vert n\vert<10^[23]$
  1821  		m                 int32 // used to negate |n| in possibly dangerous cases
  1822  	)
  1823  	k = 0
  1824  	if n < 0 {
  1825  		prg.printChar(asciiCode('-'))
  1826  		if n > -100000000 {
  1827  			n = -n
  1828  		} else {
  1829  			m = -1 - n
  1830  			n = m / 10
  1831  			m = m%10 + 1
  1832  			k = 1
  1833  			if m < 10 {
  1834  				prg.dig[0] = byte(m)
  1835  			} else {
  1836  				prg.dig[0] = 0
  1837  				n = n + 1
  1838  			}
  1839  		}
  1840  	}
  1841  	for {
  1842  		prg.dig[k] = byte(n % 10)
  1843  		n = n / 10
  1844  		k = byte(int32(k) + 1)
  1845  		if n == 0 {
  1846  			break
  1847  		}
  1848  	}
  1849  	prg.printTheDigs(k)
  1850  }
  1851  
  1852  func (prg *prg) printScaled(s scaled) { // prints scaled real, rounded to five
  1853  	//   digits
  1854  
  1855  	var (
  1856  		delta scaled // amount of allowable inaccuracy
  1857  	)
  1858  	if s < 0 {
  1859  		prg.printChar(asciiCode('-'))
  1860  		s = -s // print the sign, if negative
  1861  	}
  1862  	prg.printInt(s / 0200000) // print the integer part
  1863  	s = 10*(s%0200000) + 5
  1864  	if s != 5 {
  1865  		delta = 10
  1866  		prg.printChar(asciiCode('.'))
  1867  		for {
  1868  			if delta > 0200000 {
  1869  				s = s + 0100000 - delta/2
  1870  			} // round the final digit
  1871  			prg.printChar(asciiCode('0' + s/0200000))
  1872  			s = 10 * (s % 0200000)
  1873  			delta = delta * 10
  1874  			if s <= delta {
  1875  				break
  1876  			}
  1877  		}
  1878  	}
  1879  }
  1880  
  1881  func (prg *prg) printTwo(x, y scaled) {
  1882  	prg.printChar(asciiCode('('))
  1883  	prg.printScaled(x)
  1884  	prg.printChar(asciiCode(','))
  1885  	prg.printScaled(y)
  1886  	prg.printChar(asciiCode(')'))
  1887  }
  1888  
  1889  func (prg *prg) printType(t smallNumber) {
  1890  	switch t {
  1891  	case vacuous:
  1892  		prg.print( /* "vacuous" */ 324)
  1893  	case booleanType:
  1894  		prg.print( /* "boolean" */ 325)
  1895  	case unknownBoolean:
  1896  		prg.print( /* "unknown boolean" */ 326)
  1897  	case stringType:
  1898  		prg.print( /* "string" */ 327)
  1899  	case unknownString:
  1900  		prg.print( /* "unknown string" */ 328)
  1901  	case penType:
  1902  		prg.print( /* "pen" */ 329)
  1903  	case unknownPen:
  1904  		prg.print( /* "unknown pen" */ 330)
  1905  	case futurePen:
  1906  		prg.print( /* "future pen" */ 331)
  1907  	case pathType:
  1908  		prg.print( /* "path" */ 332)
  1909  	case unknownPath:
  1910  		prg.print( /* "unknown path" */ 333)
  1911  	case pictureType:
  1912  		prg.print( /* "picture" */ 334)
  1913  	case unknownPicture:
  1914  		prg.print( /* "unknown picture" */ 335)
  1915  	case transformType:
  1916  		prg.print( /* "transform" */ 336)
  1917  	case pairType:
  1918  		prg.print( /* "pair" */ 337)
  1919  	case known:
  1920  		prg.print( /* "known numeric" */ 338)
  1921  	case dependent:
  1922  		prg.print( /* "dependent" */ 339)
  1923  	case protoDependent:
  1924  		prg.print( /* "proto-dependent" */ 340)
  1925  	case numericType:
  1926  		prg.print( /* "numeric" */ 341)
  1927  	case independent:
  1928  		prg.print( /* "independent" */ 342)
  1929  	case tokenList:
  1930  		prg.print( /* "token list" */ 343)
  1931  	case structured:
  1932  		prg.print( /* "structured" */ 344)
  1933  	case unsuffixedMacro:
  1934  		prg.print( /* "unsuffixed macro" */ 345)
  1935  	case suffixedMacro:
  1936  		prg.print( /* "suffixed macro" */ 346)
  1937  
  1938  	default:
  1939  		prg.print( /* "undefined" */ 347)
  1940  	}
  1941  }
  1942  
  1943  func (prg *prg) beginDiagnostic() {
  1944  	prg.oldSetting = prg.selector
  1945  	if prg.internal[tracingOnline-1] <= 0 && int32(prg.selector) == termAndLog {
  1946  		prg.selector = byte(int32(prg.selector) - 1)
  1947  		if int32(prg.history) == spotless {
  1948  			prg.history = byte(warningIssued)
  1949  		}
  1950  	}
  1951  }
  1952  
  1953  func (prg *prg) endDiagnostic(blankLine bool) {
  1954  	prg.printNl(strNumber( /* "" */ 285))
  1955  	if blankLine {
  1956  		prg.printLn()
  1957  	}
  1958  	prg.selector = prg.oldSetting
  1959  }
  1960  
  1961  func (prg *prg) printDiagnostic(s, t strNumber, nuline bool) {
  1962  	prg.beginDiagnostic()
  1963  	if nuline {
  1964  		prg.printNl(s)
  1965  	} else {
  1966  		prg.print(int32(s))
  1967  	}
  1968  	prg.print( /* " at line " */ 265)
  1969  	prg.printInt(prg.line)
  1970  	prg.print(int32(t))
  1971  	prg.printChar(asciiCode(':'))
  1972  }
  1973  
  1974  func (prg *prg) printFileName(n, a, e int32) {
  1975  	prg.slowPrint(a)
  1976  	prg.slowPrint(n)
  1977  	prg.slowPrint(e)
  1978  } // \2
  1979  
  1980  // \4\hskip-\fontdimen2\font
  1981  //  procedure debug_help;
  1982  //   forward;  [  ]
  1983  
  1984  // \4
  1985  // Declare the procedure called |flush_string|
  1986  func (prg *prg) flushString(s strNumber) {
  1987  	if int32(s) < int32(prg.strPtr)-1 {
  1988  		prg.strRef[s] = 0
  1989  	} else {
  1990  		for {
  1991  			prg.strPtr = uint16(int32(prg.strPtr) - 1)
  1992  			if int32(prg.strRef[int32(prg.strPtr)-1]) != 0 {
  1993  				break
  1994  			}
  1995  		}
  1996  	}
  1997  	prg.poolPtr = prg.strStart[prg.strPtr]
  1998  }
  1999  
  2000  func (prg *prg) jumpOut() {
  2001  	panic(signal(endOfMf))
  2002  }
  2003  
  2004  func (prg *prg) error1() {
  2005  	var (
  2006  		c          asciiCode   // what the user types
  2007  		s1, s2, s3 int32       // used to save global variables when deleting tokens
  2008  		j          poolPointer // character position being printed
  2009  	)
  2010  	if int32(prg.history) < errorMessageIssued {
  2011  		prg.history = byte(errorMessageIssued)
  2012  	}
  2013  	prg.printChar(asciiCode('.'))
  2014  	prg.showContext()
  2015  	if int32(prg.interaction) == errorStopMode {
  2016  		for true {
  2017  		continue1:
  2018  			if int32(prg.interaction) != errorStopMode {
  2019  				goto exit
  2020  			}
  2021  			prg.clearForErrorPrompt()
  2022  			{
  2023  				prg.print( /* "? " */ 263)
  2024  				prg.termInput()
  2025  			}
  2026  			// \xref[?\relax]
  2027  			if int32(prg.last) == int32(prg.first) {
  2028  				goto exit
  2029  			}
  2030  			c = prg.buffer[prg.first]
  2031  			if int32(c) >= 'a' {
  2032  				c = byte(int32(c) + 'A' - 'a')
  2033  			} // convert to uppercase
  2034  
  2035  			// Interpret code |c| and |return| if done
  2036  			switch c {
  2037  			case '0', '1', '2', '3',
  2038  				'4', '5', '6', '7',
  2039  				'8', '9':
  2040  				if prg.deletionsAllowed {
  2041  					s1 = int32(prg.curCmd)
  2042  					s2 = prg.curMod
  2043  					s3 = int32(prg.curSym)
  2044  					prg.okToInterrupt = false
  2045  					if int32(prg.last) > int32(prg.first)+1 && int32(prg.buffer[int32(prg.first)+1]) >= '0' && int32(prg.buffer[int32(prg.first)+1]) <= '9' {
  2046  						c = byte(int32(c)*10 + int32(prg.buffer[int32(prg.first)+1]) - '0'*11)
  2047  					} else {
  2048  						c = byte(int32(c) - '0')
  2049  					}
  2050  					for int32(c) > 0 {
  2051  						prg.getNext() // one-level recursive call of |error| is possible
  2052  
  2053  						// Decrease the string reference count, if the current token is a string
  2054  						if int32(prg.curCmd) == stringToken {
  2055  							if int32(prg.strRef[prg.curMod]) < maxStrRef {
  2056  								if int32(prg.strRef[prg.curMod]) > 1 {
  2057  									prg.strRef[prg.curMod] = byte(int32(prg.strRef[prg.curMod]) - 1)
  2058  								} else {
  2059  									prg.flushString(strNumber(prg.curMod))
  2060  								}
  2061  							}
  2062  						}
  2063  						c = byte(int32(c) - 1)
  2064  					}
  2065  					prg.curCmd = byte(s1)
  2066  					prg.curMod = s2
  2067  					prg.curSym = uint16(s3)
  2068  					prg.okToInterrupt = true
  2069  					{
  2070  						prg.helpPtr = 2
  2071  						prg.helpLine[1] = /* "I have just deleted some text, as you asked." */ 278
  2072  						prg.helpLine[0] = /* "You can now delete more, or insert, or whatever." */ 279
  2073  					}
  2074  					prg.showContext()
  2075  					goto continue1
  2076  				}
  2077  
  2078  			// \4\4
  2079  			//  ["D"=]68:begin debug_help;goto continue; end; [  ]
  2080  
  2081  			// "E"=
  2082  			case 'E':
  2083  				if int32(prg.filePtr) > 0 {
  2084  					if int32(prg.inputStack[prg.filePtr].nameField) >= 256 {
  2085  						prg.printNl(strNumber( /* "You want to edit file " */ 264))
  2086  						// \xref[You want to edit file x]
  2087  						prg.slowPrint(int32(prg.inputStack[prg.filePtr].nameField))
  2088  						prg.print( /* " at line " */ 265)
  2089  						prg.printInt(prg.line)
  2090  
  2091  						prg.interaction = byte(scrollMode)
  2092  						prg.jumpOut()
  2093  					}
  2094  				}
  2095  			// "H"=
  2096  			case 'H':
  2097  				// Print the help information and |goto continue|
  2098  				if prg.useErrHelp {
  2099  					j = prg.strStart[prg.errHelp]
  2100  					for int32(j) < int32(prg.strStart[int32(prg.errHelp)+1]) {
  2101  						if int32(prg.strPool[j]) != '%' {
  2102  							prg.print(int32(prg.strPool[j]))
  2103  						} else if int32(j)+1 == int32(prg.strStart[int32(prg.errHelp)+1]) {
  2104  							prg.printLn()
  2105  						} else if int32(prg.strPool[int32(j)+1]) != '%' {
  2106  							prg.printLn()
  2107  						} else {
  2108  							j = uint16(int32(j) + 1)
  2109  							prg.printChar(asciiCode('%'))
  2110  						}
  2111  						j = uint16(int32(j) + 1)
  2112  					}
  2113  					prg.useErrHelp = false
  2114  				} else {
  2115  					if int32(prg.helpPtr) == 0 {
  2116  						prg.helpPtr = 2
  2117  						prg.helpLine[1] = /* "Sorry, I don't know how to help in this situation." */ 280
  2118  						prg.helpLine[0] = /* "Maybe you should try asking a human?" */ 281
  2119  					}
  2120  					for {
  2121  						prg.helpPtr = byte(int32(prg.helpPtr) - 1)
  2122  						prg.print(int32(prg.helpLine[prg.helpPtr]))
  2123  						prg.printLn()
  2124  						if int32(prg.helpPtr) == 0 {
  2125  							break
  2126  						}
  2127  					}
  2128  				}
  2129  				{
  2130  					prg.helpPtr = 4
  2131  					prg.helpLine[3] = /* "Sorry, I already gave what help I could..." */ 282
  2132  					prg.helpLine[2] = /* "Maybe you should try asking a human?" */ 281
  2133  					prg.helpLine[1] = /* "An error might have occurred before I noticed any problems." */ 283
  2134  					prg.helpLine[0] = /* "``If all else fails, read the instructions.''" */ 284
  2135  				}
  2136  
  2137  				goto continue1
  2138  
  2139  			// "I"=
  2140  			case 'I':
  2141  				// Introduce new material from the terminal and |return|
  2142  				prg.beginFileReading() // enter a new syntactic level for terminal input
  2143  				if int32(prg.last) > int32(prg.first)+1 {
  2144  					prg.curInput.locField = uint16(int32(prg.first) + 1)
  2145  					prg.buffer[prg.first] = ' '
  2146  				} else {
  2147  					{
  2148  						prg.print( /* "insert>" */ 277)
  2149  						prg.termInput()
  2150  					}
  2151  					prg.curInput.locField = prg.first
  2152  					// \xref[insert>]
  2153  				}
  2154  				prg.first = uint16(int32(prg.last) + 1)
  2155  				prg.curInput.limitField = prg.last
  2156  				goto exit
  2157  
  2158  			// "Q"=
  2159  			case 'Q', 'R', 'S':
  2160  				// Change the interaction level and |return|
  2161  				prg.errorCount = 0
  2162  				prg.interaction = byte(batchMode + int32(c) - 'Q')
  2163  				prg.print( /* "OK, entering " */ 272)
  2164  				switch c {
  2165  				case 'Q':
  2166  					prg.print( /* "batchmode" */ 273)
  2167  					prg.selector = byte(int32(prg.selector) - 1)
  2168  
  2169  				// "R"=
  2170  				case 'R':
  2171  					prg.print( /* "nonstopmode" */ 274)
  2172  				// "S"=
  2173  				case 'S':
  2174  					prg.print( /* "scrollmode" */ 275)
  2175  				} // there are no other cases
  2176  				prg.print( /* "..." */ 276)
  2177  				prg.printLn()
  2178  				goto exit
  2179  
  2180  			// "X"=
  2181  			case 'X':
  2182  				prg.interaction = byte(scrollMode)
  2183  				prg.jumpOut()
  2184  
  2185  			default:
  2186  			}
  2187  
  2188  			// Print the menu of available options
  2189  			{
  2190  				prg.print( /* "Type <return> to proceed, S to scroll future error messages," */ 266)
  2191  
  2192  				// \xref[Type <return> to proceed...]
  2193  				prg.printNl(strNumber( /* "R to run without stopping, Q to run quietly," */ 267))
  2194  
  2195  				prg.printNl(strNumber( /* "I to insert something, " */ 268))
  2196  				if int32(prg.filePtr) > 0 {
  2197  					if int32(prg.inputStack[prg.filePtr].nameField) >= 256 {
  2198  						prg.print( /* "E to edit your file," */ 269)
  2199  					}
  2200  				}
  2201  				if prg.deletionsAllowed {
  2202  					prg.printNl(strNumber( /* "1 or ... or 9 to ignore the next 1 to 9 tokens of input," */ 270))
  2203  				}
  2204  				prg.printNl(strNumber( /* "H for help, X to quit." */ 271))
  2205  			}
  2206  		}
  2207  	}
  2208  	prg.errorCount = int8(int32(prg.errorCount) + 1)
  2209  	if int32(prg.errorCount) == 100 {
  2210  		prg.printNl(strNumber( /* "(That makes 100 errors; please try again.)" */ 262))
  2211  		// \xref[That makes 100 errors...]
  2212  		prg.history = byte(fatalErrorStop)
  2213  		prg.jumpOut()
  2214  	}
  2215  
  2216  	// Put help message on the transcript file
  2217  	if int32(prg.interaction) > batchMode {
  2218  		prg.selector = byte(int32(prg.selector) - 1)
  2219  	} // avoid terminal output
  2220  	if prg.useErrHelp {
  2221  		prg.printNl(strNumber( /* "" */ 285))
  2222  
  2223  		// Print the string |err_help|, possibly on several lines
  2224  		j = prg.strStart[prg.errHelp]
  2225  		for int32(j) < int32(prg.strStart[int32(prg.errHelp)+1]) {
  2226  			if int32(prg.strPool[j]) != '%' {
  2227  				prg.print(int32(prg.strPool[j]))
  2228  			} else if int32(j)+1 == int32(prg.strStart[int32(prg.errHelp)+1]) {
  2229  				prg.printLn()
  2230  			} else if int32(prg.strPool[int32(j)+1]) != '%' {
  2231  				prg.printLn()
  2232  			} else {
  2233  				j = uint16(int32(j) + 1)
  2234  				prg.printChar(asciiCode('%'))
  2235  			}
  2236  			j = uint16(int32(j) + 1)
  2237  		}
  2238  	} else {
  2239  		for int32(prg.helpPtr) > 0 {
  2240  			prg.helpPtr = byte(int32(prg.helpPtr) - 1)
  2241  			prg.printNl(prg.helpLine[prg.helpPtr])
  2242  		}
  2243  	}
  2244  	prg.printLn()
  2245  	if int32(prg.interaction) > batchMode {
  2246  		prg.selector = byte(int32(prg.selector) + 1)
  2247  	} // re-enable terminal output
  2248  	prg.printLn()
  2249  
  2250  exit:
  2251  }
  2252  
  2253  func (prg *prg) fatalError(s strNumber) {
  2254  	prg.normalizeSelector()
  2255  
  2256  	{
  2257  		if int32(prg.interaction) == errorStopMode {
  2258  		}
  2259  		prg.printNl(strNumber( /* "! " */ 261))
  2260  		prg.print( /* "Emergency stop" */ 286) /* \xref[!\relax]  */
  2261  	}
  2262  	{
  2263  		prg.helpPtr = 1
  2264  		prg.helpLine[0] = s
  2265  	}
  2266  	{
  2267  		if int32(prg.interaction) == errorStopMode {
  2268  			prg.interaction = byte(scrollMode)
  2269  		}
  2270  		if prg.logOpened {
  2271  			prg.error1()
  2272  		} /*  if interaction>batch_mode then debug_help; [  ] */
  2273  		prg.history = byte(fatalErrorStop)
  2274  		prg.jumpOut()
  2275  	}
  2276  	// \xref[Emergency stop]
  2277  }
  2278  
  2279  func (prg *prg) overflow(s strNumber, n int32) {
  2280  	prg.normalizeSelector()
  2281  	{
  2282  		if int32(prg.interaction) == errorStopMode {
  2283  		}
  2284  		prg.printNl(strNumber( /* "! " */ 261))
  2285  		prg.print( /* "METAFONT capacity exceeded, sorry [" */ 287) /* \xref[!\relax]  */
  2286  	}
  2287  	// \xref[METAFONT capacity exceeded ...]
  2288  	prg.print(int32(s))
  2289  	prg.printChar(asciiCode('='))
  2290  	prg.printInt(n)
  2291  	prg.printChar(asciiCode(']'))
  2292  	{
  2293  		prg.helpPtr = 2
  2294  		prg.helpLine[1] = /* "If you really absolutely need more capacity," */ 288
  2295  		prg.helpLine[0] = /* "you can ask a wizard to enlarge me." */ 289
  2296  	}
  2297  	{
  2298  		if int32(prg.interaction) == errorStopMode {
  2299  			prg.interaction = byte(scrollMode)
  2300  		}
  2301  		if prg.logOpened {
  2302  			prg.error1()
  2303  		} /*  if interaction>batch_mode then debug_help; [  ] */
  2304  		prg.history = byte(fatalErrorStop)
  2305  		prg.jumpOut()
  2306  	}
  2307  }
  2308  
  2309  func (prg *prg) confusion(s strNumber) {
  2310  	prg.normalizeSelector()
  2311  	if int32(prg.history) < errorMessageIssued {
  2312  		{
  2313  			if int32(prg.interaction) == errorStopMode {
  2314  			}
  2315  			prg.printNl(strNumber( /* "! " */ 261))
  2316  			prg.print( /* "This can't happen (" */ 290) /* \xref[!\relax]  */
  2317  		}
  2318  		prg.print(int32(s))
  2319  		prg.printChar(asciiCode(')'))
  2320  		// \xref[This can't happen]
  2321  		{
  2322  			prg.helpPtr = 1
  2323  			prg.helpLine[0] = /* "I'm broken. Please show this to someone who can fix can fix" */ 291
  2324  		}
  2325  	} else {
  2326  		{
  2327  			if int32(prg.interaction) == errorStopMode {
  2328  			}
  2329  			prg.printNl(strNumber( /* "! " */ 261))
  2330  			prg.print( /* "I can't go on meeting you like this" */ 292) /* \xref[!\relax]  */
  2331  		}
  2332  		// \xref[I can't go on...]
  2333  		{
  2334  			prg.helpPtr = 2
  2335  			prg.helpLine[1] = /* "One of your faux pas seems to have wounded me deeply..." */ 293
  2336  			prg.helpLine[0] = /* "in fact, I'm barely conscious. Please fix it and try again." */ 294
  2337  		}
  2338  	}
  2339  	{
  2340  		if int32(prg.interaction) == errorStopMode {
  2341  			prg.interaction = byte(scrollMode)
  2342  		}
  2343  		if prg.logOpened {
  2344  			prg.error1()
  2345  		} /*  if interaction>batch_mode then debug_help; [  ] */
  2346  		prg.history = byte(fatalErrorStop)
  2347  		prg.jumpOut()
  2348  	}
  2349  }
  2350  
  2351  // 5.
  2352  
  2353  // tangle:pos ../../mf.web:231:3:
  2354  
  2355  // The overall \MF\ program begins with the heading just shown, after which
  2356  // comes a bunch of procedure declarations and function declarations.
  2357  // Finally we will get to the main program, which begins with the
  2358  // comment `|start_here|'. If you want to skip down to the
  2359  // main program now, you can look up `|start_here|' in the index.
  2360  // But the author suggests that the best way to understand this program
  2361  // is to follow pretty much the order of \MF's components as they appear in the
  2362  // \.[WEB] description you are now reading, since the present ordering is
  2363  // intended to combine the advantages of the ``bottom up'' and ``top down''
  2364  // approaches to the problem of understanding a somewhat complicated system.
  2365  
  2366  // 7.
  2367  
  2368  // tangle:pos ../../mf.web:253:3:
  2369  
  2370  // Some of the code below is intended to be used only when diagnosing the
  2371  // strange behavior that sometimes occurs when \MF\ is being installed or
  2372  // when system wizards are fooling around with \MF\ without quite knowing
  2373  // what they are doing. Such code will not normally be compiled; it is
  2374  // delimited by the codewords `$|debug|\ldots|gubed|$', with apologies
  2375  // to people who wish to preserve the purity of English.
  2376  //
  2377  // Similarly, there is some conditional code delimited by
  2378  // `$|stat|\ldots|tats|$' that is intended for use when statistics are to be
  2379  // kept about \MF's memory usage.  The |stat| $\ldots$ |tats| code also
  2380  // implements special diagnostic information that is printed when
  2381  // $\\[tracingedges]>1$.
  2382  // \xref[debugging]
  2383  
  2384  // 8.
  2385  
  2386  // tangle:pos ../../mf.web:279:3:
  2387  
  2388  // This program has two important variations: (1) There is a long and slow
  2389  // version called \.[INIMF], which does the extra calculations needed to
  2390  // \xref[INIMF]
  2391  // initialize \MF's internal tables; and (2)~there is a shorter and faster
  2392  // production version, which cuts the initialization to a bare minimum.
  2393  // Parts of the program that are needed in (1) but not in (2) are delimited by
  2394  // the codewords `$|init|\ldots|tini|$'.
  2395  
  2396  // 10.
  2397  
  2398  // tangle:pos ../../mf.web:307:3:
  2399  
  2400  // This \MF\ implementation conforms to the rules of the [\sl Pascal User
  2401  // \xref[PASCAL][\PASCAL]
  2402  // \xref[system dependencies]
  2403  // Manual] published by Jensen and Wirth in 1975, except where system-dependent
  2404  // \xref[Wirth, Niklaus]
  2405  // \xref[Jensen, Kathleen]
  2406  // code is necessary to make a useful system program, and except in another
  2407  // respect where such conformity would unnecessarily obscure the meaning
  2408  // and clutter up the code: We assume that |case| statements may include a
  2409  // default case that applies if no matching label is found. Thus, we shall use
  2410  // constructions like
  2411  // $$\vbox[\halign[\ignorespaces#\hfil\cr
  2412  // |case x of|\cr
  2413  // 1: $\langle\,$code for $x=1\,\rangle$;\cr
  2414  // 3: $\langle\,$code for $x=3\,\rangle$;\cr
  2415  // |othercases| $\langle\,$code for |x<>1| and |x<>3|$\,\rangle$\cr
  2416  // |endcases|\cr]]$$
  2417  // since most \PASCAL\ compilers have plugged this hole in the language by
  2418  // incorporating some sort of default mechanism. For example, the \ph\
  2419  // compiler allows `|others|:' as a default label, and other \PASCAL s allow
  2420  // syntaxes like `\&[else]' or `\&[otherwise]' or `\\[otherwise]:', etc. The
  2421  // definitions of |othercases| and |endcases| should be changed to agree with
  2422  // local conventions.  Note that no semicolon appears before |endcases| in
  2423  // this program, so the definition of |endcases| should include a semicolon
  2424  // if the compiler wants one. (Of course, if no default mechanism is
  2425  // available, the |case| statements of \MF\ will have to be laboriously
  2426  // extended by listing all remaining cases. People who are stuck with such
  2427  // \PASCAL s have, in fact, done this, successfully but not happily!)
  2428  // \xref[PASCAL H][\ph]
  2429  
  2430  // 12.
  2431  
  2432  // tangle:pos ../../mf.web:386:3:
  2433  
  2434  // Like the preceding parameters, the following quantities can be changed
  2435  // at compile time to extend or reduce \MF's capacity. But if they are changed,
  2436  // it is necessary to rerun the initialization program \.[INIMF]
  2437  // \xref[INIMF]
  2438  // to generate new tables for the production \MF\ program.
  2439  // One can't simply make helter-skelter changes to the following constants,
  2440  // since certain rather complex initialization
  2441  // numbers are computed from them. They are defined here using
  2442  // \.[WEB] macros, instead of being put into \PASCAL's |const| list, in order to
  2443  // emphasize this distinction.
  2444  
  2445  // 15.
  2446  
  2447  // tangle:pos ../../mf.web:432:3:
  2448  
  2449  // Labels are given symbolic names by the following definitions, so that
  2450  // occasional |goto| statements will be meaningful. We insert the label
  2451  // `|exit|' just before the `\ignorespaces|end|\unskip' of a procedure in
  2452  // which we have used the `|return|' statement defined below; the label
  2453  // `|restart|' is occasionally used at the very beginning of a procedure; and
  2454  // the label `|reswitch|' is occasionally used just prior to a |case|
  2455  // statement in which some cases change the conditions and we wish to branch
  2456  // to the newly applicable case.  Loops that are set up with the |loop|
  2457  // construction defined below are commonly exited by going to `|done|' or to
  2458  // `|found|' or to `|not_found|', and they are sometimes repeated by going to
  2459  // `|continue|'.  If two or more parts of a subroutine start differently but
  2460  // end up the same, the shared code may be gathered together at
  2461  // `|common_ending|'.
  2462  //
  2463  // Incidentally, this program never declares a label that isn't actually used,
  2464  // because some fussy \PASCAL\ compilers will complain about redundant labels.
  2465  
  2466  // 16.
  2467  
  2468  // tangle:pos ../../mf.web:466:3:
  2469  
  2470  // Here are some macros for common programming idioms.
  2471  
  2472  // 17. \[2] The character set
  2473  
  2474  // tangle:pos ../../mf.web:479:27:
  2475  
  2476  // In order to make \MF\ readily portable to a wide variety of
  2477  // computers, all of its input text is converted to an internal eight-bit
  2478  // code that includes standard ASCII, the ``American Standard Code for
  2479  // Information Interchange.''  This conversion is done immediately when each
  2480  // character is read in. Conversely, characters are converted from ASCII to
  2481  // the user's external representation just before they are output to a
  2482  // text file.
  2483  // \xref[ASCII code]
  2484  //
  2485  // Such an internal code is relevant to users of \MF\ only with respect to
  2486  // the \&[char] and \&[ASCII] operations, and the comparison of strings.
  2487  
  2488  // 26.
  2489  
  2490  // tangle:pos ../../mf.web:742:3:
  2491  
  2492  // The \ph\ compiler with which the present version of \MF\ was prepared has
  2493  // extended the rules of \PASCAL\ in a very convenient way. To open file~|f|,
  2494  // we can write
  2495  // $$\vbox[\halign[#\hfil\qquad&#\hfil\cr
  2496  // |reset(f,\\[name],'/O')|&for input;\cr
  2497  // |rewrite(f,\\[name],'/O')|&for output.\cr]]$$
  2498  // The `\\[name]' parameter, which is of type `\ignorespaces|packed
  2499  // array[\<\\[any]>] of text_char|', stands for the name of
  2500  // the external file that is being opened for input or output.
  2501  // Blank spaces that might appear in \\[name] are ignored.
  2502  //
  2503  // The `\.[/O]' parameter tells the operating system not to issue its own
  2504  // error messages if something goes wrong. If a file of the specified name
  2505  // cannot be found, or if such a file cannot be opened for some other reason
  2506  // (e.g., someone may already be trying to write the same file), we will have
  2507  // | erstat(f)<>0| after an unsuccessful |reset| or |rewrite|.  This allows
  2508  // \MF\ to undertake appropriate corrective action.
  2509  // \xref[PASCAL H][\ph]
  2510  // \xref[system dependencies]
  2511  //
  2512  // \MF's file-opening procedures return |false| if no file identified by
  2513  // |name_of_file| could be opened.
  2514  func (prg *prg) aOpenIn(f alphaFile) (r bool) {
  2515  	f.Reset(arraystr(prg.nameOfFile[:]), "/O")
  2516  	r = f.ErStat() == 0
  2517  	return r
  2518  }
  2519  
  2520  func (prg *prg) aOpenOut(f alphaFile) (r bool) {
  2521  	f.Rewrite(arraystr(prg.nameOfFile[:]), "/O")
  2522  	r = f.ErStat() == 0
  2523  	return r
  2524  }
  2525  
  2526  func (prg *prg) bOpenOut(f byteFile) (r bool) {
  2527  	f.Rewrite(arraystr(prg.nameOfFile[:]), "/O")
  2528  	r = f.ErStat() == 0
  2529  	return r
  2530  }
  2531  
  2532  func (prg *prg) wOpenIn(f wordFile) (r bool) {
  2533  	f.Reset(arraystr(prg.nameOfFile[:]), "/O")
  2534  	r = f.ErStat() == 0
  2535  	return r
  2536  }
  2537  
  2538  func (prg *prg) wOpenOut(f wordFile) (r bool) {
  2539  	f.Rewrite(arraystr(prg.nameOfFile[:]), "/O")
  2540  	r = f.ErStat() == 0
  2541  	return r
  2542  }
  2543  
  2544  // 27.
  2545  
  2546  // tangle:pos ../../mf.web:793:3:
  2547  
  2548  // Files can be closed with the \ph\ routine `|close(f)|', which
  2549  // \xref[PASCAL H][\ph]
  2550  // \xref[system dependencies]
  2551  // should be used when all input or output with respect to |f| has been completed.
  2552  // This makes |f| available to be opened again, if desired; and if |f| was used for
  2553  // output, the |close| operation makes the corresponding external file appear
  2554  // on the user's area, ready to be read.
  2555  func (prg *prg) aClose(f alphaFile) {
  2556  	f.Close()
  2557  }
  2558  
  2559  func (prg *prg) bClose(f byteFile) {
  2560  	f.Close()
  2561  }
  2562  
  2563  func (prg *prg) wClose(f wordFile) {
  2564  	f.Close()
  2565  }
  2566  
  2567  // 28.
  2568  
  2569  // tangle:pos ../../mf.web:813:3:
  2570  
  2571  // Binary input and output are done with \PASCAL's ordinary |get| and |put|
  2572  // procedures, so we don't have to make any other special arrangements for
  2573  // binary~I/O. Text output is also easy to do with standard \PASCAL\ routines.
  2574  // The treatment of text input is more difficult, however, because
  2575  // of the necessary translation to |ASCII_code| values.
  2576  // \MF's conventions should be efficient, and they should
  2577  // blend nicely with the user's operating environment.
  2578  
  2579  // 30.
  2580  
  2581  // tangle:pos ../../mf.web:834:3:
  2582  
  2583  // The |input_ln| function brings the next line of input from the specified
  2584  // file into available positions of the buffer array and returns the value
  2585  // |true|, unless the file has already been entirely read, in which case it
  2586  // returns |false| and sets |last:=first|.  In general, the |ASCII_code|
  2587  // numbers that represent the next line of the file are input into
  2588  // |buffer[first]|, |buffer[first+1]|, \dots, |buffer[last-1]|; and the
  2589  // global variable |last| is set equal to |first| plus the length of the
  2590  // line. Trailing blanks are removed from the line; thus, either |last=first|
  2591  // (in which case the line was entirely blank) or |buffer[last-1]<>" "|.
  2592  // \xref[inner loop]
  2593  //
  2594  // An overflow error is given, however, if the normal actions of |input_ln|
  2595  // would make |last>=buf_size|; this is done so that other parts of \MF\
  2596  // can safely look at the contents of |buffer[last+1]| without overstepping
  2597  // the bounds of the |buffer| array. Upon entry to |input_ln|, the condition
  2598  // |first<buf_size| will always hold, so that there is always room for an
  2599  // ``empty'' line.
  2600  //
  2601  // The variable |max_buf_stack|, which is used to keep track of how large
  2602  // the |buf_size| parameter must be to accommodate the present job, is
  2603  // also kept up to date by |input_ln|.
  2604  //
  2605  // If the |bypass_eoln| parameter is |true|, |input_ln| will do a |get|
  2606  // before looking at the first character of the line; this skips over
  2607  // an |eoln| that was in |f^|. The procedure does not do a |get| when it
  2608  // reaches the end of the line; therefore it can be used to acquire input
  2609  // from the user's terminal as well as from ordinary text files.
  2610  //
  2611  // Standard \PASCAL\ says that a file should have |eoln| immediately
  2612  // before |eof|, but \MF\ needs only a weaker restriction: If |eof|
  2613  // occurs in the middle of a line, the system function |eoln| should return
  2614  // a |true| result (even though |f^| will be undefined).
  2615  func (prg *prg) inputLn(f alphaFile, bypassEoln bool) (r bool) {
  2616  	// inputs the next line or returns |false|
  2617  	var (
  2618  		lastNonblank /* 0..bufSize */ uint16 // |last| with trailing blanks removed
  2619  	)
  2620  	if bypassEoln {
  2621  		if !f.EOF() {
  2622  			f.Get()
  2623  		}
  2624  	}
  2625  	// input the first character of the line into |f^|
  2626  	prg.last = prg.first // cf.\ Matthew 19\thinspace:\thinspace30
  2627  	if f.EOF() {
  2628  		r = false
  2629  	} else {
  2630  		lastNonblank = prg.first
  2631  		for !f.EOLN() {
  2632  			if int32(prg.last) >= int32(prg.maxBufStack) {
  2633  				prg.maxBufStack = uint16(int32(prg.last) + 1)
  2634  				if int32(prg.maxBufStack) == bufSize {
  2635  					if int32(prg.baseIdent) == 0 {
  2636  						prg.termOut.Writeln("Buffer size exceeded!")
  2637  						panic(signal(finalEnd))
  2638  						// \xref[Buffer size exceeded]
  2639  					} else {
  2640  						prg.curInput.locField = prg.first
  2641  						prg.curInput.limitField = uint16(int32(prg.last) - 1)
  2642  						prg.overflow(strNumber( /* "buffer size" */ 256), bufSize)
  2643  						// \xref[METAFONT capacity exceeded buffer size][\quad buffer size]
  2644  					}
  2645  				}
  2646  			}
  2647  			prg.buffer[prg.last] = prg.xord[*f.ByteP()]
  2648  			f.Get()
  2649  			prg.last = uint16(int32(prg.last) + 1)
  2650  			if int32(prg.buffer[int32(prg.last)-1]) != ' ' {
  2651  				lastNonblank = prg.last
  2652  			}
  2653  		}
  2654  		prg.last = lastNonblank
  2655  		r = true
  2656  	}
  2657  	return r
  2658  }
  2659  
  2660  // 32.
  2661  
  2662  // tangle:pos ../../mf.web:898:3:
  2663  
  2664  // Here is how to open the terminal files
  2665  // in \ph. The `\.[/I]' switch suppresses the first |get|.
  2666  // \xref[PASCAL H][\ph]
  2667  // \xref[system dependencies]
  2668  
  2669  // 33.
  2670  
  2671  // tangle:pos ../../mf.web:907:3:
  2672  
  2673  // Sometimes it is necessary to synchronize the input/output mixture that
  2674  // happens on the user's terminal, and three system-dependent
  2675  // procedures are used for this
  2676  // purpose. The first of these, |update_terminal|, is called when we want
  2677  // to make sure that everything we have output to the terminal so far has
  2678  // actually left the computer's internal buffers and been sent.
  2679  // The second, |clear_terminal|, is called when we wish to cancel any
  2680  // input that the user may have typed ahead (since we are about to
  2681  // issue an unexpected error message). The third, |wake_up_terminal|,
  2682  // is supposed to revive the terminal if the user has disabled it by
  2683  // some instruction to the operating system.  The following macros show how
  2684  // these operations can be specified in \ph:
  2685  // \xref[PASCAL H][\ph]
  2686  // \xref[system dependencies]
  2687  
  2688  // 35.
  2689  
  2690  // tangle:pos ../../mf.web:963:3:
  2691  
  2692  // Different systems have different ways to get started. But regardless of
  2693  // what conventions are adopted, the routine that initializes the terminal
  2694  // should satisfy the following specifications:
  2695  //
  2696  // \yskip\textindent[1)]It should open file |term_in| for input from the
  2697  //   terminal. (The file |term_out| will already be open for output to the
  2698  //   terminal.)
  2699  //
  2700  // \textindent[2)]If the user has given a command line, this line should be
  2701  //   considered the first line of terminal input. Otherwise the
  2702  //   user should be prompted with `\.[**]', and the first line of input
  2703  //   should be whatever is typed in response.
  2704  //
  2705  // \textindent[3)]The first line of input, which might or might not be a
  2706  //   command line, should appear in locations |first| to |last-1| of the
  2707  //   |buffer| array.
  2708  //
  2709  // \textindent[4)]The global variable |loc| should be set so that the
  2710  //   character to be read next by \MF\ is in |buffer[loc]|. This
  2711  //   character should not be blank, and we should have |loc<last|.
  2712  //
  2713  // \yskip\noindent(It may be necessary to prompt the user several times
  2714  // before a non-blank line comes in. The prompt is `\.[**]' instead of the
  2715  // later `\.*' because the meaning is slightly different: `\.[input]' need
  2716  // not be typed immediately after~`\.[**]'.)
  2717  
  2718  // 36.
  2719  
  2720  // tangle:pos ../../mf.web:991:3:
  2721  
  2722  // The following program does the required initialization
  2723  // without retrieving a possible command line.
  2724  // It should be clear how to modify this routine to deal with command lines,
  2725  // if the system permits them.
  2726  // \xref[system dependencies]
  2727  func (prg *prg) initTerminal() (r bool) {
  2728  	prg.termIn.Reset("TTY:", "/O/I")
  2729  	for true {
  2730  		prg.termOut.Write("**")
  2731  		// \xref[**]
  2732  		if !prg.inputLn(prg.termIn, false) {
  2733  			prg.termOut.Writeln()
  2734  			prg.termOut.Write("! End of file on the terminal... why?")
  2735  			// \xref[End of file on the terminal]
  2736  			r = false
  2737  			goto exit
  2738  		}
  2739  		prg.curInput.locField = prg.first
  2740  		for int32(prg.curInput.locField) < int32(prg.last) && int32(prg.buffer[prg.curInput.locField]) == ' ' {
  2741  			prg.curInput.locField = uint16(int32(prg.curInput.locField) + 1)
  2742  		}
  2743  		if int32(prg.curInput.locField) < int32(prg.last) {
  2744  			r = true
  2745  
  2746  			goto exit // return unless the line was all blank
  2747  		}
  2748  		prg.termOut.Writeln("Please type the name of your input file.")
  2749  	}
  2750  
  2751  exit:
  2752  	;
  2753  	return r
  2754  }
  2755  
  2756  // 39.
  2757  
  2758  // tangle:pos ../../mf.web:1077:3:
  2759  
  2760  // Several of the elementary string operations are performed using \.[WEB]
  2761  // macros instead of \PASCAL\ procedures, because many of the
  2762  // operations are done quite frequently and we want to avoid the
  2763  // overhead of procedure calls. For example, here is
  2764  // a simple macro that computes the length of a string.
  2765  // \xref[WEB]
  2766  
  2767  // 40.
  2768  
  2769  // tangle:pos ../../mf.web:1087:3:
  2770  
  2771  // The length of the current string is called |cur_length|:
  2772  
  2773  // 41.
  2774  
  2775  // tangle:pos ../../mf.web:1091:3:
  2776  
  2777  // Strings are created by appending character codes to |str_pool|.
  2778  // The |append_char| macro, defined here, does not check to see if the
  2779  // value of |pool_ptr| has gotten too high; this test is supposed to be
  2780  // made before |append_char| is used.
  2781  //
  2782  // To test if there is room to append |l| more characters to |str_pool|,
  2783  // we shall write |str_room(l)|, which aborts \MF\ and gives an
  2784  // apologetic error message if there isn't enough room.
  2785  
  2786  // 44.
  2787  
  2788  // tangle:pos ../../mf.web:1153:3:
  2789  
  2790  // Once a sequence of characters has been appended to |str_pool|, it
  2791  // officially becomes a string when the function |make_string| is called.
  2792  // This function returns the identification number of the new string as its
  2793  // value.
  2794  func (prg *prg) makeString() (r strNumber) {
  2795  	if int32(prg.strPtr) == int32(prg.maxStrPtr) {
  2796  		if int32(prg.strPtr) == maxStrings {
  2797  			prg.overflow(strNumber( /* "number of strings" */ 258), maxStrings-int32(prg.initStrPtr))
  2798  		}
  2799  		// \xref[METAFONT capacity exceeded number of strings][\quad number of strings]
  2800  		prg.maxStrPtr = uint16(int32(prg.maxStrPtr) + 1)
  2801  	}
  2802  	prg.strRef[prg.strPtr] = 1
  2803  	prg.strPtr = uint16(int32(prg.strPtr) + 1)
  2804  	prg.strStart[prg.strPtr] = prg.poolPtr
  2805  	r = uint16(int32(prg.strPtr) - 1)
  2806  	return r
  2807  }
  2808  
  2809  // 45.
  2810  
  2811  // tangle:pos ../../mf.web:1169:3:
  2812  
  2813  // The following subroutine compares string |s| with another string of the
  2814  // same length that appears in |buffer| starting at position |k|;
  2815  // the result is |true| if and only if the strings are equal.
  2816  func (prg *prg) strEqBuf(s strNumber, k int32) (r bool) { // loop exit
  2817  	var (
  2818  		j      poolPointer // running index
  2819  		result bool        // result of comparison
  2820  	)
  2821  	j = prg.strStart[s]
  2822  	for int32(j) < int32(prg.strStart[int32(s)+1]) {
  2823  		if int32(prg.strPool[j]) != int32(prg.buffer[k]) {
  2824  			result = false
  2825  			goto notFound
  2826  		}
  2827  		j = uint16(int32(j) + 1)
  2828  		k = k + 1
  2829  	}
  2830  	result = true
  2831  
  2832  notFound:
  2833  	r = result
  2834  	return r
  2835  }
  2836  
  2837  // 46.
  2838  
  2839  // tangle:pos ../../mf.web:1189:3:
  2840  
  2841  // Here is a similar routine, but it compares two strings in the string pool,
  2842  // and it does not assume that they have the same length. If the first string
  2843  // is lexicographically greater than, less than, or equal to the second,
  2844  // the result is respectively positive, negative, or zero.
  2845  func (prg *prg) strVsStr(s, t strNumber) (r int32) {
  2846  	var (
  2847  		j, k   poolPointer // running indices
  2848  		ls, lt int32       // lengths
  2849  		l      int32       // length remaining to test
  2850  	)
  2851  	ls = int32(prg.strStart[int32(s)+1]) - int32(prg.strStart[s])
  2852  	lt = int32(prg.strStart[int32(t)+1]) - int32(prg.strStart[t])
  2853  	if ls <= lt {
  2854  		l = ls
  2855  	} else {
  2856  		l = lt
  2857  	}
  2858  	j = prg.strStart[s]
  2859  	k = prg.strStart[t]
  2860  	for l > 0 {
  2861  		if int32(prg.strPool[j]) != int32(prg.strPool[k]) {
  2862  			r = int32(prg.strPool[j]) - int32(prg.strPool[k])
  2863  			goto exit
  2864  		}
  2865  		j = uint16(int32(j) + 1)
  2866  		k = uint16(int32(k) + 1)
  2867  		l = l - 1
  2868  	}
  2869  	r = ls - lt
  2870  
  2871  exit:
  2872  	;
  2873  	return r
  2874  }
  2875  
  2876  // 47.
  2877  
  2878  // tangle:pos ../../mf.web:1212:3:
  2879  
  2880  // The initial values of |str_pool|, |str_start|, |pool_ptr|,
  2881  // and |str_ptr| are computed by the \.[INIMF] program, based in part
  2882  // on the information that \.[WEB] has output while processing \MF.
  2883  // \xref[INIMF]
  2884  // \xref[string pool]
  2885  func (prg *prg) getStringsStarted() (r bool) {
  2886  	var (
  2887  		k, l/* 0..255 */ byte           // small indices or counters
  2888  		m, n                  char      // characters input from |pool_file|
  2889  		g                     strNumber // the string just created
  2890  		a                     int32     // accumulator for check sum
  2891  		c                     bool      // check sum has been checked
  2892  	)
  2893  	prg.poolPtr = 0
  2894  	prg.strPtr = 0
  2895  	prg.maxPoolPtr = 0
  2896  	prg.maxStrPtr = 0
  2897  	prg.strStart[0] = 0
  2898  
  2899  	// Make the first 256 strings
  2900  	for ii := int32(0); ii <= 255; ii++ {
  2901  		k = byte(ii)
  2902  		_ = k
  2903  		if int32(k) < ' ' || int32(k) > '~' {
  2904  			{
  2905  				prg.strPool[prg.poolPtr] = '^'
  2906  				prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  2907  			}
  2908  			{
  2909  				prg.strPool[prg.poolPtr] = '^'
  2910  				prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  2911  			}
  2912  			if int32(k) < 0100 {
  2913  				prg.strPool[prg.poolPtr] = byte(int32(k) + 0100)
  2914  				prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  2915  			} else if int32(k) < 0200 {
  2916  				prg.strPool[prg.poolPtr] = byte(int32(k) - 0100)
  2917  				prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  2918  			} else {
  2919  				l = byte(int32(k) / 16)
  2920  				if int32(l) < 10 {
  2921  					prg.strPool[prg.poolPtr] = byte(int32(l) + '0')
  2922  					prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  2923  				} else {
  2924  					prg.strPool[prg.poolPtr] = byte(int32(l) - 10 + 'a')
  2925  					prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  2926  				}
  2927  				l = byte(int32(k) % 16)
  2928  				if int32(l) < 10 {
  2929  					prg.strPool[prg.poolPtr] = byte(int32(l) + '0')
  2930  					prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  2931  				} else {
  2932  					prg.strPool[prg.poolPtr] = byte(int32(l) - 10 + 'a')
  2933  					prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  2934  				}
  2935  			}
  2936  		} else {
  2937  			prg.strPool[prg.poolPtr] = k
  2938  			prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  2939  		}
  2940  		g = prg.makeString()
  2941  		prg.strRef[g] = byte(maxStrRef)
  2942  	}
  2943  
  2944  	// Read the other strings from the \.[MF.POOL] file and return |true|, or give an error message and return |false|
  2945  	strcopy(prg.nameOfFile[:], "MFbases:MF.POOL                         ") // we needn't set |name_length|
  2946  	if prg.aOpenIn(prg.poolFile) {
  2947  		c = false
  2948  		for {
  2949  			// Read one string, but return |false| if the string memory space is getting too tight for comfort
  2950  			{
  2951  				if prg.poolFile.EOF() {
  2952  					prg.termOut.Writeln("! MF.POOL has no check sum.")
  2953  					prg.aClose(prg.poolFile)
  2954  					r = false
  2955  					goto exit
  2956  				}
  2957  				// \xref[MF.POOL has no check sum]
  2958  				prg.poolFile.Read(&m, &n) // read two digits of string length
  2959  				if int32(m) == '*' {
  2960  					a = 0
  2961  					k = 1
  2962  					for true {
  2963  						if int32(prg.xord[n]) < '0' || int32(prg.xord[n]) > '9' {
  2964  							prg.termOut.Writeln("! MF.POOL check sum doesn't have nine digits.")
  2965  							prg.aClose(prg.poolFile)
  2966  							r = false
  2967  							goto exit
  2968  						}
  2969  						// \xref[MF.POOL check sum...]
  2970  						a = 10*a + int32(prg.xord[n]) - '0'
  2971  						if int32(k) == 9 {
  2972  							goto done
  2973  						}
  2974  						k = byte(int32(k) + 1)
  2975  						prg.poolFile.Read(&n)
  2976  					}
  2977  
  2978  				done:
  2979  					if a != 461259239 {
  2980  						prg.termOut.Writeln("! MF.POOL doesn't match; TANGLE me again.")
  2981  						prg.aClose(prg.poolFile)
  2982  						r = false
  2983  						goto exit
  2984  					}
  2985  					// \xref[MF.POOL doesn't match]
  2986  					c = true
  2987  				} else {
  2988  					if int32(prg.xord[m]) < '0' || int32(prg.xord[m]) > '9' || int32(prg.xord[n]) < '0' || int32(prg.xord[n]) > '9' {
  2989  						prg.termOut.Writeln("! MF.POOL line doesn't begin with two digits.")
  2990  						prg.aClose(prg.poolFile)
  2991  						r = false
  2992  						goto exit
  2993  					}
  2994  					// \xref[MF.POOL line doesn't...]
  2995  					l = byte(int32(prg.xord[m])*10 + int32(prg.xord[n]) - '0'*11) // compute the length
  2996  					if int32(prg.poolPtr)+int32(l)+stringVacancies > poolSize {
  2997  						prg.termOut.Writeln("! You have to increase POOLSIZE.")
  2998  						prg.aClose(prg.poolFile)
  2999  						r = false
  3000  						goto exit
  3001  					}
  3002  					// \xref[You have to increase POOLSIZE]
  3003  					for ii := int32(1); ii <= int32(l); ii++ {
  3004  						k = byte(ii)
  3005  						_ = k
  3006  						if prg.poolFile.EOLN() {
  3007  							m = ' '
  3008  						} else {
  3009  							prg.poolFile.Read(&m)
  3010  						}
  3011  						{
  3012  							prg.strPool[prg.poolPtr] = prg.xord[m]
  3013  							prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  3014  						}
  3015  					}
  3016  					prg.poolFile.Readln()
  3017  					g = prg.makeString()
  3018  					prg.strRef[g] = byte(maxStrRef)
  3019  				}
  3020  			}
  3021  			if c {
  3022  				break
  3023  			}
  3024  		}
  3025  		prg.aClose(prg.poolFile)
  3026  		r = true
  3027  	} else {
  3028  		prg.termOut.Writeln("! I can't read MF.POOL.")
  3029  		prg.aClose(prg.poolFile)
  3030  		r = false
  3031  		goto exit
  3032  	}
  3033  
  3034  exit:
  3035  	;
  3036  	return r
  3037  }
  3038  
  3039  // 56.
  3040  
  3041  // tangle:pos ../../mf.web:1406:3:
  3042  
  3043  // Macro abbreviations for output to the terminal and to the log file are
  3044  // defined here for convenience. Some systems need special conventions
  3045  // for terminal output, and it is possible to adhere to those conventions
  3046  // by changing |wterm|, |wterm_ln|, and |wterm_cr| here.
  3047  // \xref[system dependencies]
  3048  
  3049  // 65.
  3050  
  3051  // tangle:pos ../../mf.web:1560:3:
  3052  
  3053  // \MF\ also makes use of a trivial procedure to print two digits. The
  3054  // following subroutine is usually called with a parameter in the range |0<=n<=99|.
  3055  func (prg *prg) printDd(n int32) {
  3056  	n = abs(n) % 100
  3057  	prg.printChar(asciiCode('0' + n/10))
  3058  	prg.printChar(asciiCode('0' + n%10))
  3059  } // \2
  3060  
  3061  func (prg *prg) termInput() { // gets a line from the terminal
  3062  	var (
  3063  		k /* 0..bufSize */ uint16 // index into |buffer|
  3064  	) // now the user sees the prompt for sure
  3065  	if !prg.inputLn(prg.termIn, true) {
  3066  		prg.fatalError(strNumber( /* "End of file on the terminal!" */ 260))
  3067  	}
  3068  	// \xref[End of file on the terminal]
  3069  	prg.termOffset = 0                           // the user's line ended with \<\rm return>
  3070  	prg.selector = byte(int32(prg.selector) - 1) // prepare to echo the input
  3071  	if int32(prg.last) != int32(prg.first) {
  3072  		for ii := int32(prg.first); ii <= int32(prg.last)-1; ii++ {
  3073  			k = uint16(ii)
  3074  			_ = k
  3075  			prg.print(int32(prg.buffer[k]))
  3076  		}
  3077  	}
  3078  	prg.printLn()
  3079  	prg.buffer[prg.last] = '%'
  3080  	prg.selector = byte(int32(prg.selector) + 1) // restore previous status
  3081  }
  3082  
  3083  // \4
  3084  // Error handling procedures
  3085  func (prg *prg) normalizeSelector() {
  3086  	if prg.logOpened {
  3087  		prg.selector = byte(termAndLog)
  3088  	} else {
  3089  		prg.selector = byte(termOnly)
  3090  	}
  3091  	if int32(prg.jobName) == 0 {
  3092  		prg.openLogFile()
  3093  	}
  3094  	if int32(prg.interaction) == batchMode {
  3095  		prg.selector = byte(int32(prg.selector) - 1)
  3096  	}
  3097  }
  3098  
  3099  // 93.
  3100  
  3101  // tangle:pos ../../mf.web:1993:3:
  3102  
  3103  // When an interrupt has been detected, the program goes into its
  3104  // highest interaction level and lets the user have the full flexibility of
  3105  // the |error| routine.  \MF\ checks for interrupts only at times when it is
  3106  // safe to do this.
  3107  func (prg *prg) pauseForInstructions() {
  3108  	if prg.okToInterrupt {
  3109  		prg.interaction = byte(errorStopMode)
  3110  		if int32(prg.selector) == logOnly || int32(prg.selector) == noPrint {
  3111  			prg.selector = byte(int32(prg.selector) + 1)
  3112  		}
  3113  		{
  3114  			if int32(prg.interaction) == errorStopMode {
  3115  			}
  3116  			prg.printNl(strNumber( /* "! " */ 261))
  3117  			prg.print( /* "Interruption" */ 295) /* \xref[!\relax]  */
  3118  		}
  3119  		// \xref[Interruption]
  3120  		{
  3121  			prg.helpPtr = 3
  3122  			prg.helpLine[2] = /* "You rang?" */ 296
  3123  			prg.helpLine[1] = /* "Try to insert an instruction for me (e.g., `I show x;')," */ 297
  3124  			prg.helpLine[0] = /* "unless you just want to quit by typing `X'." */ 298
  3125  		}
  3126  		prg.deletionsAllowed = false
  3127  		prg.error1()
  3128  		prg.deletionsAllowed = true
  3129  		prg.interrupt = 0
  3130  	}
  3131  }
  3132  
  3133  // 94.
  3134  
  3135  // tangle:pos ../../mf.web:2013:3:
  3136  
  3137  // Many of \MF's error messages state that a missing token has been
  3138  // inserted behind the scenes. We can save string space and program space
  3139  // by putting this common code into a subroutine.
  3140  func (prg *prg) missingErr(s strNumber) {
  3141  	{
  3142  		if int32(prg.interaction) == errorStopMode {
  3143  		}
  3144  		prg.printNl(strNumber( /* "! " */ 261))
  3145  		prg.print( /* "Missing `" */ 299) /* \xref[!\relax]  */
  3146  	}
  3147  	prg.print(int32(s))
  3148  	prg.print( /* "' has been inserted" */ 300)
  3149  	// \xref[Missing...inserted]
  3150  }
  3151  
  3152  // 95. \[7] Arithmetic with scaled numbers
  3153  
  3154  // tangle:pos ../../mf.web:2022:40:
  3155  
  3156  // The principal computations performed by \MF\ are done entirely in terms of
  3157  // integers less than $2^[31]$ in magnitude; thus, the arithmetic specified in this
  3158  // program can be carried out in exactly the same way on a wide variety of
  3159  // computers, including some small ones.
  3160  // \xref[small computers]
  3161  //
  3162  // But \PASCAL\ does not define the  |div|
  3163  // operation in the case of negative dividends; for example, the result of
  3164  // |(-2*n-1) div 2| is |-(n+1)| on some computers and |-n| on others.
  3165  // There are two principal types of arithmetic: ``translation-preserving,''
  3166  // in which the identity |(a+q*b)div b=(a div b)+q| is valid; and
  3167  // ``negation-preserving,'' in which |(-a)div b=-(a div b)|. This leads to
  3168  // two \MF s, which can produce different results, although the differences
  3169  // should be negligible when the language is being used properly.
  3170  // The \TeX\ processor has been defined carefully so that both varieties
  3171  // of arithmetic will produce identical output, but it would be too
  3172  // inefficient to constrain \MF\ in a similar way.
  3173  
  3174  // 96.
  3175  
  3176  // tangle:pos ../../mf.web:2043:3:
  3177  
  3178  // One of \MF's most common operations is the calculation of
  3179  // $\lfloor[a+b\over2]\rfloor$,
  3180  // the midpoint of two given integers |a| and~|b|. The only decent way to do
  3181  // this in \PASCAL\ is to write `|(a+b) div 2|'; but on most machines it is
  3182  // far more efficient to calculate `|(a+b)| right shifted one bit'.
  3183  //
  3184  // Therefore the midpoint operation will always be denoted by `|half(a+b)|'
  3185  // in this program. If \MF\ is being implemented with languages that permit
  3186  // binary shifting, the |half| macro should be changed to make this operation
  3187  // as efficient as possible.
  3188  
  3189  // 99.
  3190  
  3191  // tangle:pos ../../mf.web:2068:3:
  3192  
  3193  // At crucial points the program will say |check_arith|, to test if
  3194  // an arithmetic error has been detected.
  3195  func (prg *prg) clearArith() {
  3196  	{
  3197  		if int32(prg.interaction) == errorStopMode {
  3198  		}
  3199  		prg.printNl(strNumber( /* "! " */ 261))
  3200  		prg.print( /* "Arithmetic overflow" */ 301) /* \xref[!\relax]  */
  3201  	}
  3202  	// \xref[Arithmetic overflow]
  3203  	{
  3204  		prg.helpPtr = 4
  3205  		prg.helpLine[3] = /* "Uh, oh. A little while ago one of the quantities that I was" */ 302
  3206  		prg.helpLine[2] = /* "computing got too large, so I'm afraid your answers will be" */ 303
  3207  		prg.helpLine[1] = /* "somewhat askew. You'll probably have to adopt different" */ 304
  3208  		prg.helpLine[0] = /* "tactics next time. But I shall try to carry on anyway." */ 305
  3209  	}
  3210  	prg.error1()
  3211  	prg.arithError = false
  3212  }
  3213  
  3214  // 100.
  3215  
  3216  // tangle:pos ../../mf.web:2083:3:
  3217  
  3218  // Addition is not always checked to make sure that it doesn't overflow,
  3219  // but in places where overflow isn't too unlikely the |slow_add| routine
  3220  // is used.
  3221  func (prg *prg) slowAdd(x, y int32) (r int32) {
  3222  	if x >= 0 {
  3223  		if y <= 017777777777-x {
  3224  			r = x + y
  3225  		} else {
  3226  			prg.arithError = true
  3227  			r = 017777777777
  3228  		}
  3229  	} else if -y <= 017777777777+x {
  3230  		r = x + y
  3231  	} else {
  3232  		prg.arithError = true
  3233  		r = -017777777777
  3234  	}
  3235  	return r
  3236  }
  3237  
  3238  // 102.
  3239  
  3240  // tangle:pos ../../mf.web:2112:3:
  3241  
  3242  // The following function is used to create a scaled integer from a given decimal
  3243  // fraction $(.d_0d_1\ldots d_[k-1])$, where |0<=k<=17|. The digit $d_i$ is
  3244  // given in |dig[i]|, and the calculation produces a correctly rounded result.
  3245  func (prg *prg) roundDecimals(k smallNumber) (r scaled) {
  3246  	// converts a decimal fraction
  3247  	var (
  3248  		a int32 // the accumulator
  3249  	)
  3250  	a = 0
  3251  	for int32(k) > 0 {
  3252  		k = byte(int32(k) - 1)
  3253  		a = (a + int32(prg.dig[k])*0400000) / 10
  3254  	}
  3255  	r = (a + 1) / 2
  3256  	return r
  3257  }
  3258  
  3259  // 107.
  3260  
  3261  // tangle:pos ../../mf.web:2194:3:
  3262  
  3263  // The |make_fraction| routine produces the |fraction| equivalent of
  3264  // |p/q|, given integers |p| and~|q|; it computes the integer
  3265  // $f=\lfloor2^[28]p/q+[1\over2]\rfloor$, when $p$ and $q$ are
  3266  // positive. If |p| and |q| are both of the same scaled type |t|,
  3267  // the ``type relation'' |make_fraction(t,t)=fraction| is valid;
  3268  // and it's also possible to use the subroutine ``backwards,'' using
  3269  // the relation |make_fraction(t,fraction)=t| between scaled types.
  3270  //
  3271  // If the result would have magnitude $2^[31]$ or more, |make_fraction|
  3272  // sets |arith_error:=true|. Most of \MF's internal computations have
  3273  // been designed to avoid this sort of error.
  3274  //
  3275  // Notice that if 64-bit integer arithmetic were available,
  3276  // we could simply compute |$(2^[29]$*p+q)div (2*q)|.
  3277  // But when we are restricted to \PASCAL's 32-bit arithmetic we
  3278  // must either resort to multiple-precision maneuvering
  3279  // or use a simple but slow iteration. The multiple-precision technique
  3280  // would be about three times faster than the code adopted here, but it
  3281  // would be comparatively long and tricky, involving about sixteen
  3282  // additional multiplications and divisions.
  3283  //
  3284  // This operation is part of \MF's ``inner loop''; indeed, it will
  3285  // consume nearly 10\pct! of the running time (exclusive of input and output)
  3286  // if the code below is left unchanged. A machine-dependent recoding
  3287  // will therefore make \MF\ run faster. The present implementation
  3288  // is highly portable, but slow; it avoids multiplication and division
  3289  // except in the initial stage. System wizards should be careful to
  3290  // replace it with a routine that is guaranteed to produce identical
  3291  // results in all cases.
  3292  // \xref[system dependencies]
  3293  //
  3294  // As noted below, a few more routines should also be replaced by machine-dependent
  3295  // code, for efficiency. But when a procedure is not part of the ``inner loop,''
  3296  // such changes aren't advisable; simplicity and robustness are
  3297  // preferable to trickery, unless the cost is too high.
  3298  // \xref[inner loop]
  3299  func (prg *prg) makeFraction(p, q int32) (r fraction) {
  3300  	var (
  3301  		f         int32 // the fraction bits, with a leading 1 bit
  3302  		n         int32 // the integer part of $\vert p/q\vert$
  3303  		negative  bool  // should the result be negated?
  3304  		beCareful int32 // disables certain compiler optimizations
  3305  	)
  3306  	if p >= 0 {
  3307  		negative = false
  3308  	} else {
  3309  		p = -p
  3310  		negative = true
  3311  	}
  3312  	if q <= 0 {
  3313  		q = -q
  3314  		negative = !negative
  3315  	}
  3316  	n = p / q
  3317  	p = p % q
  3318  	if n >= 8 {
  3319  		prg.arithError = true
  3320  		if negative {
  3321  			r = -017777777777
  3322  		} else {
  3323  			r = 017777777777
  3324  		}
  3325  	} else {
  3326  		n = (n - 1) * 02000000000
  3327  
  3328  		// Compute $f=\lfloor 2^[28](1+p/q)+[1\over2]\rfloor$
  3329  		f = 1
  3330  		for {
  3331  			beCareful = p - q
  3332  			p = beCareful + p
  3333  			if p >= 0 {
  3334  				f = f + f + 1
  3335  			} else {
  3336  				f = f + f
  3337  				p = p + q
  3338  			}
  3339  			if f >= 02000000000 {
  3340  				break
  3341  			}
  3342  		}
  3343  		beCareful = p - q
  3344  		if beCareful+p >= 0 {
  3345  			f = f + 1
  3346  		}
  3347  		if negative {
  3348  			r = -(f + n)
  3349  		} else {
  3350  			r = f + n
  3351  		}
  3352  	}
  3353  	return r
  3354  }
  3355  
  3356  // 109.
  3357  
  3358  // tangle:pos ../../mf.web:2278:3:
  3359  
  3360  // The dual of |make_fraction| is |take_fraction|, which multiplies a
  3361  // given integer~|q| by a fraction~|f|. When the operands are positive, it
  3362  // computes $p=\lfloor qf/2^[28]+[1\over2]\rfloor$, a symmetric function
  3363  // of |q| and~|f|.
  3364  //
  3365  // This routine is even more ``inner loopy'' than |make_fraction|;
  3366  // the present implementation consumes almost 20\pct! of \MF's computation
  3367  // time during typical jobs, so a machine-language or 64-bit
  3368  // substitute is advisable.
  3369  // \xref[inner loop] \xref[system dependencies]
  3370  func (prg *prg) takeFraction(q int32, f fraction) (r int32) {
  3371  	var (
  3372  		p         int32 // the fraction so far
  3373  		negative  bool  // should the result be negated?
  3374  		n         int32 // additional multiple of $q$
  3375  		beCareful int32 // disables certain compiler optimizations
  3376  	)
  3377  	if f >= 0 {
  3378  		negative = false
  3379  	} else {
  3380  		f = -f
  3381  		negative = true
  3382  	}
  3383  	if q < 0 {
  3384  		q = -q
  3385  		negative = !negative
  3386  	}
  3387  
  3388  	if f < 02000000000 {
  3389  		n = 0
  3390  	} else {
  3391  		n = f / 02000000000
  3392  		f = f % 02000000000
  3393  		if q <= 017777777777/n {
  3394  			n = n * q
  3395  		} else {
  3396  			prg.arithError = true
  3397  			n = 017777777777
  3398  		}
  3399  	}
  3400  	f = f + 02000000000
  3401  
  3402  	// Compute $p=\lfloor qf/2^[28]+[1\over2]\rfloor-q$
  3403  	p = 01000000000 // that's $2^[27]$; the invariants hold now with $k=28$
  3404  	if q < 010000000000 {
  3405  		for {
  3406  			if f&1 != 0 {
  3407  				p = (p + q) / 2
  3408  			} else {
  3409  				p = p / 2
  3410  			}
  3411  			f = f / 2
  3412  			if f == 1 {
  3413  				break
  3414  			}
  3415  		}
  3416  	} else {
  3417  		for {
  3418  			if f&1 != 0 {
  3419  				p = p + (q-p)/2
  3420  			} else {
  3421  				p = p / 2
  3422  			}
  3423  			f = f / 2
  3424  			if f == 1 {
  3425  				break
  3426  			}
  3427  		}
  3428  	}
  3429  	beCareful = n - 017777777777
  3430  	if beCareful+p > 0 {
  3431  		prg.arithError = true
  3432  		n = 017777777777 - p
  3433  	}
  3434  	if negative {
  3435  		r = -(n + p)
  3436  	} else {
  3437  		r = n + p
  3438  	}
  3439  	return r
  3440  }
  3441  
  3442  // 112.
  3443  
  3444  // tangle:pos ../../mf.web:2335:3:
  3445  
  3446  // When we want to multiply something by a |scaled| quantity, we use a scheme
  3447  // analogous to |take_fraction| but with a different scaling.
  3448  // Given positive operands, |take_scaled|
  3449  // computes the quantity $p=\lfloor qf/2^[16]+[1\over2]\rfloor$.
  3450  //
  3451  // Once again it is a good idea to use 64-bit arithmetic if
  3452  // possible; otherwise |take_scaled| will use more than 2\pct! of the running time
  3453  // when the Computer Modern fonts are being generated.
  3454  // \xref[inner loop]
  3455  func (prg *prg) takeScaled(q int32, f scaled) (r int32) {
  3456  	var (
  3457  		p         int32 // the fraction so far
  3458  		negative  bool  // should the result be negated?
  3459  		n         int32 // additional multiple of $q$
  3460  		beCareful int32 // disables certain compiler optimizations
  3461  	)
  3462  	if f >= 0 {
  3463  		negative = false
  3464  	} else {
  3465  		f = -f
  3466  		negative = true
  3467  	}
  3468  	if q < 0 {
  3469  		q = -q
  3470  		negative = !negative
  3471  	}
  3472  
  3473  	if f < 0200000 {
  3474  		n = 0
  3475  	} else {
  3476  		n = f / 0200000
  3477  		f = f % 0200000
  3478  		if q <= 017777777777/n {
  3479  			n = n * q
  3480  		} else {
  3481  			prg.arithError = true
  3482  			n = 017777777777
  3483  		}
  3484  	}
  3485  	f = f + 0200000
  3486  
  3487  	// Compute $p=\lfloor qf/2^[16]+[1\over2]\rfloor-q$
  3488  	p = 0100000 // that's $2^[15]$; the invariants hold now with $k=16$
  3489  	// \xref[inner loop]
  3490  	if q < 010000000000 {
  3491  		for {
  3492  			if f&1 != 0 {
  3493  				p = (p + q) / 2
  3494  			} else {
  3495  				p = p / 2
  3496  			}
  3497  			f = f / 2
  3498  			if f == 1 {
  3499  				break
  3500  			}
  3501  		}
  3502  	} else {
  3503  		for {
  3504  			if f&1 != 0 {
  3505  				p = p + (q-p)/2
  3506  			} else {
  3507  				p = p / 2
  3508  			}
  3509  			f = f / 2
  3510  			if f == 1 {
  3511  				break
  3512  			}
  3513  		}
  3514  	}
  3515  	beCareful = n - 017777777777
  3516  	if beCareful+p > 0 {
  3517  		prg.arithError = true
  3518  		n = 017777777777 - p
  3519  	}
  3520  	if negative {
  3521  		r = -(n + p)
  3522  	} else {
  3523  		r = n + p
  3524  	}
  3525  	return r
  3526  }
  3527  
  3528  // 114.
  3529  
  3530  // tangle:pos ../../mf.web:2378:3:
  3531  
  3532  // For completeness, there's also |make_scaled|, which computes a
  3533  // quotient as a |scaled| number instead of as a |fraction|.
  3534  // In other words, the result is $\lfloor2^[16]p/q+[1\over2]\rfloor$, if the
  3535  // operands are positive. \ (This procedure is not used especially often,
  3536  // so it is not part of \MF's inner loop.)
  3537  func (prg *prg) makeScaled(p, q int32) (r scaled) {
  3538  	var (
  3539  		f         int32 // the fraction bits, with a leading 1 bit
  3540  		n         int32 // the integer part of $\vert p/q\vert$
  3541  		negative  bool  // should the result be negated?
  3542  		beCareful int32 // disables certain compiler optimizations
  3543  	)
  3544  	if p >= 0 {
  3545  		negative = false
  3546  	} else {
  3547  		p = -p
  3548  		negative = true
  3549  	}
  3550  	if q <= 0 {
  3551  		q = -q
  3552  		negative = !negative
  3553  	}
  3554  	n = p / q
  3555  	p = p % q
  3556  	if n >= 0100000 {
  3557  		prg.arithError = true
  3558  		if negative {
  3559  			r = -017777777777
  3560  		} else {
  3561  			r = 017777777777
  3562  		}
  3563  	} else {
  3564  		n = (n - 1) * 0200000
  3565  
  3566  		// Compute $f=\lfloor 2^[16](1+p/q)+[1\over2]\rfloor$
  3567  		f = 1
  3568  		for {
  3569  			beCareful = p - q
  3570  			p = beCareful + p
  3571  			if p >= 0 {
  3572  				f = f + f + 1
  3573  			} else {
  3574  				f = f + f
  3575  				p = p + q
  3576  			}
  3577  			if f >= 0200000 {
  3578  				break
  3579  			}
  3580  		}
  3581  		beCareful = p - q
  3582  		if beCareful+p >= 0 {
  3583  			f = f + 1
  3584  		}
  3585  		if negative {
  3586  			r = -(f + n)
  3587  		} else {
  3588  			r = f + n
  3589  		}
  3590  	}
  3591  	return r
  3592  }
  3593  
  3594  // 116.
  3595  
  3596  // tangle:pos ../../mf.web:2418:3:
  3597  
  3598  // Here is a typical example of how the routines above can be used.
  3599  // It computes the function
  3600  // $$[1\over3\tau]f(\theta,\phi)=
  3601  // [\tau^[-1]\bigl(2+\sqrt2\,(\sin\theta-[1\over16]\sin\phi)
  3602  //  (\sin\phi-[1\over16]\sin\theta)(\cos\theta-\cos\phi)\bigr)\over
  3603  // 3\,\bigl(1+[1\over2](\sqrt5-1)\cos\theta+[1\over2](3-\sqrt5\,)\cos\phi\bigr)],$$
  3604  // where $\tau$ is a |scaled| ``tension'' parameter. This is \MF's magic
  3605  // fudge factor for placing the first control point of a curve that starts
  3606  // at an angle $\theta$ and ends at an angle $\phi$ from the straight path.
  3607  // (Actually, if the stated quantity exceeds 4, \MF\ reduces it to~4.)
  3608  //
  3609  // The trigonometric quantity to be multiplied by $\sqrt2$ is less than $\sqrt2$.
  3610  // (It's a sum of eight terms whose absolute values can be bounded using
  3611  // relations such as $\sin\theta\cos\theta\L[1\over2]$.) Thus the numerator
  3612  // is positive; and since the tension $\tau$ is constrained to be at least
  3613  // $3\over4$, the numerator is less than $16\over3$. The denominator is
  3614  // nonnegative and at most~6.  Hence the fixed-point calculations below
  3615  // are guaranteed to stay within the bounds of a 32-bit computer word.
  3616  //
  3617  // The angles $\theta$ and $\phi$ are given implicitly in terms of |fraction|
  3618  // arguments |st|, |ct|, |sf|, and |cf|, representing $\sin\theta$, $\cos\theta$,
  3619  // $\sin\phi$, and $\cos\phi$, respectively.
  3620  func (prg *prg) velocity(st, ct, sf, cf fraction, t scaled) (r fraction) {
  3621  	var (
  3622  		acc, num, denom int32 // registers for intermediate calculations
  3623  	)
  3624  	acc = prg.takeFraction(st-sf/16, sf-st/16)
  3625  	acc = prg.takeFraction(acc, ct-cf)
  3626  	num = 04000000000 + prg.takeFraction(acc, fraction(379625062))
  3627  	// $2^[28]\sqrt2\approx379625062.497$
  3628  	denom = 06000000000 + prg.takeFraction(ct, fraction(497706707)) + prg.takeFraction(cf, fraction(307599661))
  3629  	// $3\cdot2^[27]\cdot(\sqrt5-1)\approx497706706.78$ and
  3630  	//     $3\cdot2^[27]\cdot(3-\sqrt5\,)\approx307599661.22$
  3631  
  3632  	if t != 0200000 {
  3633  		num = prg.makeScaled(num, t)
  3634  	}
  3635  	// |make_scaled(fraction,scaled)=fraction|
  3636  	if num/4 >= denom {
  3637  		r = 010000000000
  3638  	} else {
  3639  		r = prg.makeFraction(num, denom)
  3640  	}
  3641  	return r
  3642  }
  3643  
  3644  // 117.
  3645  
  3646  // tangle:pos ../../mf.web:2456:3:
  3647  
  3648  // The following somewhat different subroutine tests rigorously if $ab$ is
  3649  // greater than, equal to, or less than~$cd$,
  3650  // given integers $(a,b,c,d)$. In most cases a quick decision is reached.
  3651  // The result is $+1$, 0, or~$-1$ in the three respective cases.
  3652  func (prg *prg) abVsCd(a, b, c, d int32) (r int32) {
  3653  	var (
  3654  		q, r1 int32 // temporary registers
  3655  	)
  3656  	if a < 0 {
  3657  		a = -a
  3658  		b = -b
  3659  	}
  3660  	if c < 0 {
  3661  		c = -c
  3662  		d = -d
  3663  	}
  3664  	if d <= 0 {
  3665  		if b >= 0 {
  3666  			if (a == 0 || b == 0) && (c == 0 || d == 0) {
  3667  				r = 0
  3668  				goto exit
  3669  			} else {
  3670  				r = 1
  3671  				goto exit
  3672  			}
  3673  		}
  3674  		if d == 0 {
  3675  			if a == 0 {
  3676  				r = 0
  3677  				goto exit
  3678  			} else {
  3679  				r = -1
  3680  				goto exit
  3681  			}
  3682  		}
  3683  		q = a
  3684  		a = c
  3685  		c = q
  3686  		q = -b
  3687  		b = -d
  3688  		d = q
  3689  	} else if b <= 0 {
  3690  		if b < 0 {
  3691  			if a > 0 {
  3692  				r = -1
  3693  				goto exit
  3694  			}
  3695  		}
  3696  		if c == 0 {
  3697  			r = 0
  3698  			goto exit
  3699  		} else {
  3700  			r = -1
  3701  			goto exit
  3702  		}
  3703  	}
  3704  	for true {
  3705  		q = a / d
  3706  		r1 = c / b
  3707  		if q != r1 {
  3708  			if q > r1 {
  3709  				r = 1
  3710  				goto exit
  3711  			} else {
  3712  				r = -1
  3713  				goto exit
  3714  			}
  3715  		}
  3716  		q = a % d
  3717  		r1 = c % b
  3718  		if r1 == 0 {
  3719  			if q == 0 {
  3720  				r = 0
  3721  				goto exit
  3722  			} else {
  3723  				r = 1
  3724  				goto exit
  3725  			}
  3726  		}
  3727  		if q == 0 {
  3728  			r = -1
  3729  			goto exit
  3730  		}
  3731  		a = b
  3732  		b = q
  3733  		c = d
  3734  		d = r1
  3735  	} // now |a>d>0| and |c>b>0|
  3736  	// now |a>d>0| and |c>b>0|
  3737  exit:
  3738  	;
  3739  	return r
  3740  }
  3741  
  3742  // 119.
  3743  
  3744  // tangle:pos ../../mf.web:2499:3:
  3745  
  3746  // We conclude this set of elementary routines with some simple rounding
  3747  // and truncation operations that are coded in a machine-independent fashion.
  3748  // The routines are slightly complicated because we want them to work
  3749  // without overflow whenever $-2^[31]\L x<2^[31]$.
  3750  func (prg *prg) floorScaled(x scaled) (r scaled) {
  3751  	// $2^[16]\lfloor x/2^[16]\rfloor$
  3752  	var (
  3753  		beCareful int32 // temporary register
  3754  	)
  3755  	if x >= 0 {
  3756  		r = x - x%0200000
  3757  	} else {
  3758  		beCareful = x + 1
  3759  		r = x + -beCareful%0200000 + 1 - 0200000
  3760  	}
  3761  	return r
  3762  }
  3763  
  3764  func (prg *prg) floorUnscaled(x scaled) (r int32) {
  3765  	// $\lfloor x/2^[16]\rfloor$
  3766  	var (
  3767  		beCareful int32 // temporary register
  3768  	)
  3769  	if x >= 0 {
  3770  		r = x / 0200000
  3771  	} else {
  3772  		beCareful = x + 1
  3773  		r = -(1 + -beCareful/0200000)
  3774  	}
  3775  	return r
  3776  }
  3777  
  3778  func (prg *prg) roundUnscaled(x scaled) (r int32) {
  3779  	// $\lfloor x/2^[16]+.5\rfloor$
  3780  	var (
  3781  		beCareful int32 // temporary register
  3782  	)
  3783  	if x >= 0100000 {
  3784  		r = 1 + (x-0100000)/0200000
  3785  	} else if x >= -0100000 {
  3786  		r = 0
  3787  	} else {
  3788  		beCareful = x + 1
  3789  		r = -(1 + (-beCareful-0100000)/0200000)
  3790  	}
  3791  	return r
  3792  }
  3793  
  3794  func (prg *prg) roundFraction(x fraction) (r scaled) {
  3795  	// $\lfloor x/2^[12]+.5\rfloor$
  3796  	var (
  3797  		beCareful int32 // temporary register
  3798  	)
  3799  	if x >= 2048 {
  3800  		r = 1 + (x-2048)/4096
  3801  	} else if x >= -2048 {
  3802  		r = 0
  3803  	} else {
  3804  		beCareful = x + 1
  3805  		r = -(1 + (-beCareful-2048)/4096)
  3806  	}
  3807  	return r
  3808  }
  3809  
  3810  // 120. \[8] Algebraic and transcendental functions
  3811  
  3812  // tangle:pos ../../mf.web:2541:48:
  3813  
  3814  // \MF\ computes all of the necessary special functions from scratch, without
  3815  // relying on |real| arithmetic or system subroutines for sines, cosines, etc.
  3816  
  3817  // 121.
  3818  
  3819  // tangle:pos ../../mf.web:2545:3:
  3820  
  3821  // To get the square root of a |scaled| number |x|, we want to calculate
  3822  // $s=\lfloor 2^8\!\sqrt x +[1\over2]\rfloor$. If $x>0$, this is the unique
  3823  // integer such that $2^[16]x-s\L s^2<2^[16]x+s$. The following subroutine
  3824  // determines $s$ by an iterative method that maintains the invariant
  3825  // relations $x=2^[46-2k]x_0\bmod 2^[30]$, $0<y=\lfloor 2^[16-2k]x_0\rfloor
  3826  // -s^2+s\L q=2s$, where $x_0$ is the initial value of $x$. The value of~$y$
  3827  // might, however, be zero at the start of the first iteration.
  3828  func (prg *prg) squareRt(x scaled) (r scaled) {
  3829  	var (
  3830  		k    smallNumber // iteration control counter
  3831  		y, q int32       // registers for intermediate calculations
  3832  	)
  3833  	if x <= 0 {
  3834  		if x < 0 {
  3835  			{
  3836  				if int32(prg.interaction) == errorStopMode {
  3837  				}
  3838  				prg.printNl(strNumber( /* "! " */ 261))
  3839  				prg.print( /* "Square root of " */ 306) /* \xref[!\relax]  */
  3840  			}
  3841  			// \xref[Square root...replaced by 0]
  3842  			prg.printScaled(x)
  3843  			prg.print( /* " has been replaced by 0" */ 307)
  3844  			{
  3845  				prg.helpPtr = 2
  3846  				prg.helpLine[1] = /* "Since I don't take square roots of negative numbers," */ 308
  3847  				prg.helpLine[0] = /* "I'm zeroing this one. Proceed, with fingers crossed." */ 309
  3848  			}
  3849  			prg.error1()
  3850  		}
  3851  		r = 0
  3852  	} else {
  3853  		k = 23
  3854  		q = 2
  3855  		for x < 04000000000 { // i.e., |while x<$2^[29]$|\unskip
  3856  			k = byte(int32(k) - 1)
  3857  			x = x + x + x + x
  3858  		}
  3859  		if x < 010000000000 {
  3860  			y = 0
  3861  		} else {
  3862  			x = x - 010000000000
  3863  			y = 1
  3864  		}
  3865  		for {
  3866  			// Decrease |k| by 1, maintaining the invariant relations between |x|, |y|, and~|q|
  3867  			x = x + x
  3868  			y = y + y
  3869  			if x >= 010000000000 {
  3870  				x = x - 010000000000
  3871  				y = y + 1
  3872  			}
  3873  			x = x + x
  3874  			y = y + y - q
  3875  			q = q + q
  3876  			if x >= 010000000000 {
  3877  				x = x - 010000000000
  3878  				y = y + 1
  3879  			}
  3880  			if y > q {
  3881  				y = y - q
  3882  				q = q + 2
  3883  			} else if y <= 0 {
  3884  				q = q - 2
  3885  				y = y + q
  3886  			}
  3887  			k = byte(int32(k) - 1)
  3888  			if int32(k) == 0 {
  3889  				break
  3890  			}
  3891  		}
  3892  		r = q / 2
  3893  	}
  3894  	return r
  3895  }
  3896  
  3897  // 124.
  3898  
  3899  // tangle:pos ../../mf.web:2600:3:
  3900  
  3901  // Pythagorean addition $\psqrt[a^2+b^2]$ is implemented by an elegant
  3902  // iterative scheme due to Cleve Moler and Donald Morrison [[\sl IBM Journal
  3903  // \xref[Moler, Cleve Barry]
  3904  // \xref[Morrison, Donald Ross]
  3905  // of Research and Development\/ \bf27] (1983), 577--581]. It modifies |a| and~|b|
  3906  // in such a way that their Pythagorean sum remains invariant, while the
  3907  // smaller argument decreases.
  3908  func (prg *prg) pythAdd(a, b int32) (r int32) {
  3909  	var (
  3910  		r1  fraction // register used to transform |a| and |b|
  3911  		big bool     // is the result dangerously near $2^[31]$?
  3912  	)
  3913  	a = abs(a)
  3914  	b = abs(b)
  3915  	if a < b {
  3916  		r1 = b
  3917  		b = a
  3918  		a = r1
  3919  	} // now |0<=b<=a|
  3920  	if b > 0 {
  3921  		if a < 04000000000 {
  3922  			big = false
  3923  		} else {
  3924  			a = a / 4
  3925  			b = b / 4
  3926  			big = true
  3927  		} // we reduced the precision to avoid arithmetic overflow
  3928  
  3929  		// Replace |a| by an approximation to $\psqrt[a^2+b^2]$
  3930  		for true {
  3931  			r1 = prg.makeFraction(b, a)
  3932  			r1 = prg.takeFraction(r1, r1) // now $r\approx b^2/a^2$
  3933  			if r1 == 0 {
  3934  				goto done
  3935  			}
  3936  			r1 = prg.makeFraction(r1, 010000000000+r1)
  3937  			a = a + prg.takeFraction(a+a, r1)
  3938  			b = prg.takeFraction(b, r1)
  3939  		}
  3940  
  3941  	done:
  3942  		;
  3943  		if big {
  3944  			if a < 04000000000 {
  3945  				a = a + a + a + a
  3946  			} else {
  3947  				prg.arithError = true
  3948  				a = 017777777777
  3949  			}
  3950  		}
  3951  	}
  3952  	r = a
  3953  	return r
  3954  }
  3955  
  3956  // 126.
  3957  
  3958  // tangle:pos ../../mf.web:2641:3:
  3959  
  3960  // Here is a similar algorithm for $\psqrt[a^2-b^2]$.
  3961  // It converges slowly when $b$ is near $a$, but otherwise it works fine.
  3962  func (prg *prg) pythSub(a, b int32) (r int32) {
  3963  	var (
  3964  		r1  fraction // register used to transform |a| and |b|
  3965  		big bool     // is the input dangerously near $2^[31]$?
  3966  	)
  3967  	a = abs(a)
  3968  	b = abs(b)
  3969  	if a <= b {
  3970  		if a < b {
  3971  			{
  3972  				if int32(prg.interaction) == errorStopMode {
  3973  				}
  3974  				prg.printNl(strNumber( /* "! " */ 261))
  3975  				prg.print( /* "Pythagorean subtraction " */ 310) /* \xref[!\relax]  */
  3976  			}
  3977  			prg.printScaled(a)
  3978  			prg.print( /* "+-+" */ 311)
  3979  			prg.printScaled(b)
  3980  			prg.print( /* " has been replaced by 0" */ 307)
  3981  			// \xref[Pythagorean...]
  3982  			{
  3983  				prg.helpPtr = 2
  3984  				prg.helpLine[1] = /* "Since I don't take square roots of negative numbers," */ 308
  3985  				prg.helpLine[0] = /* "I'm zeroing this one. Proceed, with fingers crossed." */ 309
  3986  			}
  3987  			prg.error1()
  3988  		}
  3989  		a = 0
  3990  	} else {
  3991  		if a < 010000000000 {
  3992  			big = false
  3993  		} else {
  3994  			a = a / 2
  3995  			b = b / 2
  3996  			big = true
  3997  		}
  3998  
  3999  		// Replace |a| by an approximation to $\psqrt[a^2-b^2]$
  4000  		for true {
  4001  			r1 = prg.makeFraction(b, a)
  4002  			r1 = prg.takeFraction(r1, r1) // now $r\approx b^2/a^2$
  4003  			if r1 == 0 {
  4004  				goto done
  4005  			}
  4006  			r1 = prg.makeFraction(r1, 010000000000-r1)
  4007  			a = a - prg.takeFraction(a+a, r1)
  4008  			b = prg.takeFraction(b, r1)
  4009  		}
  4010  
  4011  	done:
  4012  		;
  4013  		if big {
  4014  			a = a + a
  4015  		}
  4016  	}
  4017  	r = a
  4018  	return r
  4019  }
  4020  
  4021  // 132.
  4022  
  4023  // tangle:pos ../../mf.web:2713:3:
  4024  
  4025  // Here is the routine that calculates $2^8$ times the natural logarithm
  4026  // of a |scaled| quantity; it is an integer approximation to $2^[24]\ln(x/2^[16])$,
  4027  // when |x| is a given positive integer.
  4028  //
  4029  // The method is based on exercise 1.2.2--25 in [\sl The Art of Computer
  4030  // Programming\/]: During the main iteration we have $1\L 2^[-30]x<1/(1-2^[1-k])$,
  4031  // and the logarithm of $2^[30]x$ remains to be added to an accumulator
  4032  // register called~$y$. Three auxiliary bits of accuracy are retained in~$y$
  4033  // during the calculation, and sixteen auxiliary bits to extend |y| are
  4034  // kept in~|z| during the initial argument reduction. (We add
  4035  // $100\cdot2^[16]=6553600$ to~|z| and subtract 100 from~|y| so that |z| will
  4036  // not become negative; also, the actual amount subtracted from~|y| is~96,
  4037  // not~100, because we want to add~4 for rounding before the final division by~8.)
  4038  func (prg *prg) mLog(x scaled) (r scaled) {
  4039  	var (
  4040  		y, z int32 // auxiliary registers
  4041  		k    int32 // iteration counter
  4042  	)
  4043  	if x <= 0 {
  4044  		{
  4045  			if int32(prg.interaction) == errorStopMode {
  4046  			}
  4047  			prg.printNl(strNumber( /* "! " */ 261))
  4048  			prg.print( /* "Logarithm of " */ 312) /* \xref[!\relax]  */
  4049  		}
  4050  		// \xref[Logarithm...replaced by 0]
  4051  		prg.printScaled(x)
  4052  		prg.print( /* " has been replaced by 0" */ 307)
  4053  		{
  4054  			prg.helpPtr = 2
  4055  			prg.helpLine[1] = /* "Since I don't take logs of non-positive numbers," */ 313
  4056  			prg.helpLine[0] = /* "I'm zeroing this one. Proceed, with fingers crossed." */ 309
  4057  		}
  4058  		prg.error1()
  4059  		r = 0
  4060  	} else {
  4061  		y = 1302456956 + 4 - 100 // $14\times2^[27]\ln2\approx1302456956.421063$
  4062  		z = 27595 + 6553600      // and $2^[16]\times .421063\approx 27595$
  4063  		for x < 010000000000 {
  4064  			x = x + x
  4065  			y = y - 93032639
  4066  			z = z - 48782
  4067  		} // $2^[27]\ln2\approx 93032639.74436163$
  4068  		//       and $2^[16]\times.74436163\approx 48782$
  4069  
  4070  		y = y + z/0200000
  4071  		k = 2
  4072  		for x > 010000000000+4 {
  4073  
  4074  			// Increase |k| until |x| can be multiplied by a factor of $2^[-k]$, and adjust $y$ accordingly
  4075  			z = (x-1)/prg.twoToThe[k] + 1 // $z=\lceil x/2^k\rceil$
  4076  			for x < 010000000000+z {
  4077  				z = (z + 1) / 2
  4078  				k = k + 1
  4079  			}
  4080  			y = y + prg.specLog[k-1]
  4081  			x = x - z
  4082  		}
  4083  		r = y / 8
  4084  	}
  4085  	return r
  4086  }
  4087  
  4088  // 135.
  4089  
  4090  // tangle:pos ../../mf.web:2762:3:
  4091  
  4092  // Conversely, the exponential routine calculates $\exp(x/2^8)$,
  4093  // when |x| is |scaled|. The result is an integer approximation to
  4094  // $2^[16]\exp(x/2^[24])$, when |x| is regarded as an integer.
  4095  func (prg *prg) mExp(x scaled) (r scaled) {
  4096  	var (
  4097  		k    smallNumber // loop control index
  4098  		y, z int32       // auxiliary registers
  4099  	)
  4100  	if x > 174436200 {
  4101  		prg.arithError = true
  4102  		r = 017777777777
  4103  	} else if x < -197694359 {
  4104  		r = 0
  4105  	} else {
  4106  		if x <= 0 {
  4107  			z = -(8 * x)
  4108  			y = 04000000 // $y=2^[20]$
  4109  		} else {
  4110  			if x <= 127919879 {
  4111  				z = 1023359037 - 8*x
  4112  			} else {
  4113  				z = 8 * (174436200 - x)
  4114  			} // |z| is always nonnegative
  4115  			y = 017777777777
  4116  		}
  4117  
  4118  		// Multiply |y| by $\exp(-z/2^[27])$
  4119  		k = 1
  4120  		for z > 0 {
  4121  			for z >= prg.specLog[k-1] {
  4122  				z = z - prg.specLog[k-1]
  4123  				y = y - 1 - (y-prg.twoToThe[int32(k)-1])/prg.twoToThe[k]
  4124  			}
  4125  			k = byte(int32(k) + 1)
  4126  		}
  4127  		if x <= 127919879 {
  4128  			r = (y + 8) / 16
  4129  		} else {
  4130  			r = y
  4131  		}
  4132  	}
  4133  	return r
  4134  }
  4135  
  4136  // 139.
  4137  
  4138  // tangle:pos ../../mf.web:2841:3:
  4139  
  4140  // Given integers |x| and |y|, not both zero, the |n_arg| function
  4141  // returns the |angle| whose tangent points in the direction $(x,y)$.
  4142  // This subroutine first determines the correct octant, then solves the
  4143  // problem for |0<=y<=x|, then converts the result appropriately to
  4144  // return an answer in the range |-one_eighty_deg<=$\theta$<=one_eighty_deg|.
  4145  // (The answer is |+one_eighty_deg| if |y=0| and |x<0|, but an answer of
  4146  // |-one_eighty_deg| is possible if, for example, |y=-1| and $x=-2^[30]$.)
  4147  //
  4148  // The octants are represented in a ``Gray code,'' since that turns out
  4149  // to be computationally simplest.
  4150  func (prg *prg) nArg(x, y int32) (r angle) {
  4151  	var (
  4152  		z                                         angle       // auxiliary register
  4153  		t                                         int32       // temporary storage
  4154  		k                                         smallNumber // loop counter
  4155  		octant/* firstOctant..sixthOctant */ byte             // octant code
  4156  	)
  4157  	if x >= 0 {
  4158  		octant = byte(firstOctant)
  4159  	} else {
  4160  		x = -x
  4161  		octant = byte(firstOctant + negateX)
  4162  	}
  4163  	if y < 0 {
  4164  		y = -y
  4165  		octant = byte(int32(octant) + negateY)
  4166  	}
  4167  	if x < y {
  4168  		t = y
  4169  		y = x
  4170  		x = t
  4171  		octant = byte(int32(octant) + switchXAndY)
  4172  	}
  4173  	if x == 0 {
  4174  		{
  4175  			if int32(prg.interaction) == errorStopMode {
  4176  			}
  4177  			prg.printNl(strNumber( /* "! " */ 261))
  4178  			prg.print( /* "angle(0,0) is taken as zero" */ 314) /* \xref[!\relax]  */
  4179  		}
  4180  		// \xref[angle(0,0)...zero]
  4181  		{
  4182  			prg.helpPtr = 2
  4183  			prg.helpLine[1] = /* "The `angle' between two identical points is undefined." */ 315
  4184  			prg.helpLine[0] = /* "I'm zeroing this one. Proceed, with fingers crossed." */ 309
  4185  		}
  4186  		prg.error1()
  4187  		r = 0
  4188  	} else {
  4189  		for x >= 04000000000 {
  4190  			x = x / 2
  4191  			y = y / 2
  4192  		}
  4193  		z = 0
  4194  		if y > 0 {
  4195  			for x < 02000000000 {
  4196  				x = x + x
  4197  				y = y + y
  4198  			}
  4199  
  4200  			// Increase |z| to the arg of $(x,y)$
  4201  			k = 0
  4202  			for {
  4203  				y = y + y
  4204  				k = byte(int32(k) + 1)
  4205  				if y > x {
  4206  					z = z + prg.specAtan[k-1]
  4207  					t = x
  4208  					x = x + y/prg.twoToThe[int32(k)+int32(k)]
  4209  					y = y - t
  4210  				}
  4211  				if int32(k) == 15 {
  4212  					break
  4213  				}
  4214  			}
  4215  			for {
  4216  				y = y + y
  4217  				k = byte(int32(k) + 1)
  4218  				if y > x {
  4219  					z = z + prg.specAtan[k-1]
  4220  					y = y - x
  4221  				}
  4222  				if int32(k) == 26 {
  4223  					break
  4224  				}
  4225  			}
  4226  		}
  4227  
  4228  		// Return an appropriate answer based on |z| and |octant|
  4229  		switch octant {
  4230  		case firstOctant:
  4231  			r = z
  4232  		case secondOctant:
  4233  			r = 0550000000 - z
  4234  		case thirdOctant:
  4235  			r = 0550000000 + z
  4236  		case fourthOctant:
  4237  			r = 01320000000 - z
  4238  		case fifthOctant:
  4239  			r = z - 01320000000
  4240  		case sixthOctant:
  4241  			r = -z - 0550000000
  4242  		case seventhOctant:
  4243  			r = z - 0550000000
  4244  		case eighthOctant:
  4245  			r = -z
  4246  		}
  4247  	}
  4248  	return r
  4249  }
  4250  
  4251  // 145.
  4252  
  4253  // tangle:pos ../../mf.web:2955:3:
  4254  
  4255  // Given an integer |z| that is $2^[20]$ times an angle $\theta$ in degrees,
  4256  // the purpose of |n_sin_cos(z)| is to set
  4257  // |x=$r\cos\theta$| and |y=$r\sin\theta$| (approximately),
  4258  // for some rather large number~|r|. The maximum of |x| and |y|
  4259  // will be between $2^[28]$ and $2^[30]$, so that there will be hardly
  4260  // any loss of accuracy. Then |x| and~|y| are divided by~|r|.
  4261  func (prg *prg) nSinCos(z angle) { // computes a multiple of the sine and cosine
  4262  	var (
  4263  		k                smallNumber // loop control variable
  4264  		q/* 0..7 */ byte             // specifies the quadrant
  4265  		r1               fraction    // magnitude of |(x,y)|
  4266  		x, y, t          int32       // temporary registers
  4267  	)
  4268  	for z < 0 {
  4269  		z = z + 02640000000
  4270  	}
  4271  	z = z % 02640000000 // now |0<=z<three_sixty_deg|
  4272  	q = byte(z / 0264000000)
  4273  	z = z % 0264000000
  4274  	x = 02000000000
  4275  	y = x
  4276  	if !(q&1 != 0) {
  4277  		z = 0264000000 - z
  4278  	}
  4279  
  4280  	// Subtract angle |z| from |(x,y)|
  4281  	k = 1
  4282  	for z > 0 {
  4283  		if z >= prg.specAtan[k-1] {
  4284  			z = z - prg.specAtan[k-1]
  4285  			t = x
  4286  
  4287  			x = t + y/prg.twoToThe[k]
  4288  			y = y - t/prg.twoToThe[k]
  4289  		}
  4290  		k = byte(int32(k) + 1)
  4291  	}
  4292  	if y < 0 {
  4293  		y = 0
  4294  	}
  4295  
  4296  	// Convert |(x,y)| to the octant determined by~|q|
  4297  	switch q {
  4298  	case 0:
  4299  	case 1:
  4300  		t = x
  4301  		x = y
  4302  		y = t
  4303  
  4304  	case 2:
  4305  		t = x
  4306  		x = -y
  4307  		y = t
  4308  
  4309  	case 3:
  4310  		x = -x
  4311  	case 4:
  4312  		x = -x
  4313  		y = -y
  4314  
  4315  	case 5:
  4316  		t = x
  4317  		x = -y
  4318  		y = -t
  4319  
  4320  	case 6:
  4321  		t = x
  4322  		x = y
  4323  		y = -t
  4324  
  4325  	case 7:
  4326  		y = -y
  4327  	}
  4328  	r1 = prg.pythAdd(x, y)
  4329  	prg.nCos = prg.makeFraction(x, r1)
  4330  	prg.nSin = prg.makeFraction(y, r1)
  4331  }
  4332  
  4333  // 149.
  4334  
  4335  // tangle:pos ../../mf.web:3029:3:
  4336  
  4337  // To consume a random fraction, the program below will say `|next_random|'
  4338  // and then it will fetch |randoms[j_random]|. The |next_random| macro
  4339  // actually accesses the numbers backwards; blocks of 55~$x$'s are
  4340  // essentially being ``flipped.'' But that doesn't make them less random.
  4341  func (prg *prg) newRandoms() {
  4342  	var (
  4343  		k/* 0..54 */ byte          // index into |randoms|
  4344  		x                 fraction // accumulator
  4345  	)
  4346  	for ii := int32(0); ii <= 23; ii++ {
  4347  		k = byte(ii)
  4348  		_ = k
  4349  		x = prg.randoms[k] - prg.randoms[int32(k)+31]
  4350  		if x < 0 {
  4351  			x = x + 02000000000
  4352  		}
  4353  		prg.randoms[k] = x
  4354  	}
  4355  	for ii := int32(24); ii <= 54; ii++ {
  4356  		k = byte(ii)
  4357  		_ = k
  4358  		x = prg.randoms[k] - prg.randoms[int32(k)-24]
  4359  		if x < 0 {
  4360  			x = x + 02000000000
  4361  		}
  4362  		prg.randoms[k] = x
  4363  	}
  4364  	prg.jRandom = 54
  4365  }
  4366  
  4367  // 150.
  4368  
  4369  // tangle:pos ../../mf.web:3053:3:
  4370  
  4371  // To initialize the |randoms| table, we call the following routine.
  4372  func (prg *prg) initRandoms(seed scaled) {
  4373  	var (
  4374  		j, jj, k          fraction // more or less random integers
  4375  		i/* 0..54 */ byte          // index into |randoms|
  4376  	)
  4377  	j = abs(seed)
  4378  	for j >= 02000000000 {
  4379  		j = j / 2
  4380  	}
  4381  	k = 1
  4382  	for ii := int32(0); ii <= 54; ii++ {
  4383  		i = byte(ii)
  4384  		_ = i
  4385  		jj = k
  4386  		k = j - k
  4387  		j = jj
  4388  		if k < 0 {
  4389  			k = k + 02000000000
  4390  		}
  4391  		prg.randoms[int32(i)*21%55] = j
  4392  	}
  4393  	prg.newRandoms()
  4394  	prg.newRandoms()
  4395  	prg.newRandoms() // ``warm up'' the array
  4396  }
  4397  
  4398  // 151.
  4399  
  4400  // tangle:pos ../../mf.web:3069:3:
  4401  
  4402  // To produce a uniform random number in the range |0<=u<x| or |0>=u>x|
  4403  // or |0=u=x|, given a |scaled| value~|x|, we proceed as shown here.
  4404  //
  4405  // Note that the call of |take_fraction| will produce the values 0 and~|x|
  4406  // with about half the probability that it will produce any other particular
  4407  // values between 0 and~|x|, because it rounds its answers.
  4408  func (prg *prg) unifRand(x scaled) (r scaled) {
  4409  	var (
  4410  		y scaled // trial value
  4411  	)
  4412  	if int32(prg.jRandom) == 0 {
  4413  		prg.newRandoms()
  4414  	} else {
  4415  		prg.jRandom = byte(int32(prg.jRandom) - 1)
  4416  	}
  4417  	y = prg.takeFraction(abs(x), prg.randoms[prg.jRandom])
  4418  	if y == abs(x) {
  4419  		r = 0
  4420  	} else if x > 0 {
  4421  		r = y
  4422  	} else {
  4423  		r = -y
  4424  	}
  4425  	return r
  4426  }
  4427  
  4428  // 152.
  4429  
  4430  // tangle:pos ../../mf.web:3084:3:
  4431  
  4432  // Finally, a normal deviate with mean zero and unit standard deviation
  4433  // can readily be obtained with the ratio method (Algorithm 3.4.1R in
  4434  // [\sl The Art of Computer Programming\/]).
  4435  func (prg *prg) normRand() (r scaled) {
  4436  	var (
  4437  		x, u, l int32 // what the book would call $2^[16]X$, $2^[28]U$,
  4438  	// and $-2^[24]\ln U$
  4439  	)
  4440  	for {
  4441  		for {
  4442  			if int32(prg.jRandom) == 0 {
  4443  				prg.newRandoms()
  4444  			} else {
  4445  				prg.jRandom = byte(int32(prg.jRandom) - 1)
  4446  			}
  4447  			x = prg.takeFraction(112429, prg.randoms[prg.jRandom]-01000000000)
  4448  			// $2^[16]\sqrt[8/e]\approx 112428.82793$
  4449  			if int32(prg.jRandom) == 0 {
  4450  				prg.newRandoms()
  4451  			} else {
  4452  				prg.jRandom = byte(int32(prg.jRandom) - 1)
  4453  			}
  4454  			u = prg.randoms[prg.jRandom]
  4455  			if abs(x) < u {
  4456  				break
  4457  			}
  4458  		}
  4459  		x = prg.makeFraction(x, u)
  4460  		l = 139548960 - prg.mLog(u) // $2^[24]\cdot12\ln2\approx139548959.6165$
  4461  		if prg.abVsCd(1024, l, x, x) >= 0 {
  4462  			break
  4463  		}
  4464  	}
  4465  	r = x
  4466  	return r
  4467  } // \2
  4468  
  4469  func (prg *prg) showTokenList(p, q int32, l, nullTally int32) {
  4470  	var (
  4471  		class, c smallNumber // the |char_class| of previous and new tokens
  4472  		r1, v    int32       // temporary registers
  4473  	)
  4474  	class = byte(percentClass)
  4475  	prg.tally = nullTally
  4476  	for p != memMin && prg.tally < l {
  4477  		if p == q {
  4478  			prg.firstCount = prg.tally
  4479  			prg.trickCount = prg.tally + 1 + errorLine - halfErrorLine
  4480  			if prg.trickCount < errorLine {
  4481  				prg.trickCount = errorLine
  4482  			}
  4483  		}
  4484  
  4485  		// Display token |p| and set |c| to its class; but |return| if there are problems
  4486  		c = byte(letterClass) // the default
  4487  		if p < memMin || p > int32(prg.memEnd) {
  4488  			prg.print( /* " CLOBBERED" */ 493)
  4489  			goto exit
  4490  			// \xref[CLOBBERED]
  4491  		}
  4492  		if p < int32(prg.hiMemMin) {
  4493  			if int32(*(*prg.mem[p].hh()).b1()) == token {
  4494  				if int32(*(*prg.mem[p].hh()).b0()) == known {
  4495  					if int32(class) == digitClass {
  4496  						prg.printChar(asciiCode(' '))
  4497  					}
  4498  					v = *prg.mem[p+1].int()
  4499  					if v < 0 {
  4500  						if int32(class) == leftBracketClass {
  4501  							prg.printChar(asciiCode(' '))
  4502  						}
  4503  						prg.printChar(asciiCode('['))
  4504  						prg.printScaled(v)
  4505  						prg.printChar(asciiCode(']'))
  4506  						c = byte(rightBracketClass)
  4507  					} else {
  4508  						prg.printScaled(v)
  4509  						c = byte(digitClass)
  4510  					}
  4511  				} else if int32(*(*prg.mem[p].hh()).b0()) != stringType {
  4512  					prg.print( /* " BAD" */ 496)
  4513  				} else {
  4514  					prg.printChar(asciiCode('"'))
  4515  					prg.slowPrint(*prg.mem[p+1].int())
  4516  					prg.printChar(asciiCode('"'))
  4517  					c = byte(stringClass)
  4518  				}
  4519  			} else if int32(*(*prg.mem[p].hh()).b1()) != capsule || int32(*(*prg.mem[p].hh()).b0()) < vacuous || int32(*(*prg.mem[p].hh()).b0()) > independent {
  4520  				prg.print( /* " BAD" */ 496)
  4521  			} else {
  4522  				prg.gPointer = uint16(p)
  4523  				prg.printCapsule()
  4524  				c = byte(rightParenClass)
  4525  			}
  4526  		} else {
  4527  			r1 = int32(*(*prg.mem[p].hh()).lh())
  4528  			if r1 >= hashBase+hashSize+12+1 {
  4529  				if r1 < hashBase+hashSize+12+1+paramSize {
  4530  					prg.print( /* "(EXPR" */ 498)
  4531  					r1 = r1 - (hashBase + hashSize + 12 + 1)
  4532  					// \xref[EXPR]
  4533  				} else if r1 < hashBase+hashSize+12+1+paramSize+paramSize {
  4534  					prg.print( /* "(SUFFIX" */ 499)
  4535  					r1 = r1 - (hashBase + hashSize + 12 + 1 + paramSize)
  4536  					// \xref[SUFFIX]
  4537  				} else {
  4538  					prg.print( /* "(TEXT" */ 500)
  4539  					r1 = r1 - (hashBase + hashSize + 12 + 1 + paramSize + paramSize)
  4540  					// \xref[TEXT]
  4541  				}
  4542  				prg.printInt(r1)
  4543  				prg.printChar(asciiCode(')'))
  4544  				c = byte(rightParenClass)
  4545  			} else if r1 < 1 {
  4546  				if r1 == 0 {
  4547  					if int32(class) == leftBracketClass {
  4548  						prg.printChar(asciiCode(' '))
  4549  					}
  4550  					prg.print( /* "[]" */ 497)
  4551  					c = byte(rightBracketClass)
  4552  				} else {
  4553  					prg.print( /* " IMPOSSIBLE" */ 494)
  4554  				}
  4555  			} else {
  4556  				r1 = int32(*prg.hash[r1-1].rh())
  4557  				if r1 < 0 || r1 >= int32(prg.strPtr) {
  4558  					prg.print( /* " NONEXISTENT" */ 495)
  4559  				} else {
  4560  					// Print string |r| as a symbolic token and set |c| to its class
  4561  					c = prg.charClass[prg.strPool[prg.strStart[r1]]]
  4562  					if int32(c) == int32(class) {
  4563  						switch c {
  4564  						case letterClass:
  4565  							prg.printChar(asciiCode('.'))
  4566  						case 5, 6, 7, 8:
  4567  
  4568  						default:
  4569  							prg.printChar(asciiCode(' '))
  4570  						}
  4571  					}
  4572  					prg.slowPrint(r1)
  4573  				}
  4574  			}
  4575  		}
  4576  		class = c
  4577  		p = int32(*(*prg.mem[p].hh()).rh())
  4578  	}
  4579  	if p != memMin {
  4580  		prg.print( /* " ETC." */ 492)
  4581  	}
  4582  	// \xref[ETC]
  4583  
  4584  	// \xref[ETC]
  4585  exit:
  4586  }
  4587  
  4588  // \4
  4589  // Declare the procedure called |runaway|
  4590  func (prg *prg) runaway() {
  4591  	if int32(prg.scannerStatus) > flushing {
  4592  		prg.printNl(strNumber( /* "Runaway " */ 637))
  4593  		switch prg.scannerStatus {
  4594  		case absorbing:
  4595  			prg.print( /* "text?" */ 638)
  4596  		case varDefining, opDefining:
  4597  			prg.print( /* "definition?" */ 639)
  4598  		case loopDefining:
  4599  			prg.print( /* "loop?" */ 640)
  4600  		} // there are no other cases
  4601  		prg.printLn()
  4602  		prg.showTokenList(int32(*(*prg.mem[3000-2].hh()).rh()), memMin, errorLine-10, 0)
  4603  	}
  4604  }
  4605  
  4606  // 163.
  4607  
  4608  // tangle:pos ../../mf.web:3304:3:
  4609  
  4610  // The function |get_avail| returns a pointer to a new one-word node whose
  4611  // |link| field is null. However, \MF\ will halt if there is no more room left.
  4612  // \xref[inner loop]
  4613  func (prg *prg) getAvail() (r halfword) { // single-word node allocation
  4614  	var (
  4615  		p halfword // the new node being got
  4616  	)
  4617  	p = prg.avail // get top location in the |avail| stack
  4618  	if int32(p) != memMin {
  4619  		prg.avail = *(*prg.mem[prg.avail].hh()).rh()
  4620  	} else if int32(prg.memEnd) < memMax {
  4621  		prg.memEnd = uint16(int32(prg.memEnd) + 1)
  4622  		p = prg.memEnd
  4623  	} else {
  4624  		prg.hiMemMin = uint16(int32(prg.hiMemMin) - 1)
  4625  		p = prg.hiMemMin
  4626  		if int32(prg.hiMemMin) <= int32(prg.loMemMax) {
  4627  			prg.runaway() // if memory is exhausted, display possible runaway text
  4628  			prg.overflow(strNumber( /* "main memory size" */ 316), memMax+1-memMin)
  4629  			// quit; all one-word nodes are busy
  4630  			// \xref[METAFONT capacity exceeded main memory size][\quad main memory size]
  4631  		}
  4632  	}
  4633  	*(*prg.mem[p].hh()).rh() = uint16(memMin) // provide an oft-desired initialization of the new node
  4634  	prg.dynUsed = prg.dynUsed + 1             // maintain statistics
  4635  	r = p
  4636  	return r
  4637  }
  4638  
  4639  // 164.
  4640  
  4641  // tangle:pos ../../mf.web:3328:3:
  4642  
  4643  // Conversely, a one-word node is recycled by calling |free_avail|.
  4644  
  4645  // 165.
  4646  
  4647  // tangle:pos ../../mf.web:3335:3:
  4648  
  4649  // There's also a |fast_get_avail| routine, which saves the procedure-call
  4650  // overhead at the expense of extra programming. This macro is used in
  4651  // the places that would otherwise account for the most calls of |get_avail|.
  4652  // \xref[inner loop]
  4653  
  4654  // 167.
  4655  
  4656  // tangle:pos ../../mf.web:3373:3:
  4657  
  4658  // A call to |get_node| with argument |s| returns a pointer to a new node
  4659  // of size~|s|, which must be 2~or more. The |link| field of the first word
  4660  // of this new node is set to null. An overflow stop occurs if no suitable
  4661  // space exists.
  4662  //
  4663  // If |get_node| is called with $s=2^[30]$, it simply merges adjacent free
  4664  // areas and returns the value |max_halfword|.
  4665  func (prg *prg) getNode(s int32) (r halfword) {
  4666  	var (
  4667  		p     halfword // the node currently under inspection
  4668  		q     halfword // the node physically after node |p|
  4669  		r1    int32    // the newly allocated node, or a candidate for this honor
  4670  		t, tt int32    // temporary registers
  4671  	// \xref[inner loop]
  4672  	)
  4673  restart:
  4674  	p = prg.rover // start at some free node in the ring
  4675  	for {
  4676  		// Try to allocate within node |p| and its physical successors, and |goto found| if allocation was possible
  4677  		q = uint16(int32(p) + int32(*(*prg.mem[p].hh()).lh())) // find the physical successor
  4678  		for int32(*(*prg.mem[q].hh()).rh()) == 65535 {         // merge node |p| with node |q|
  4679  			t = int32(*(*prg.mem[int32(q)+1].hh()).rh())
  4680  			tt = int32(*(*prg.mem[int32(q)+1].hh()).lh())
  4681  			// \xref[inner loop]
  4682  			if int32(q) == int32(prg.rover) {
  4683  				prg.rover = uint16(t)
  4684  			}
  4685  			*(*prg.mem[t+1].hh()).lh() = uint16(tt)
  4686  			*(*prg.mem[tt+1].hh()).rh() = uint16(t)
  4687  
  4688  			q = uint16(int32(q) + int32(*(*prg.mem[q].hh()).lh()))
  4689  		}
  4690  		r1 = int32(q) - s
  4691  		if r1 > int32(p)+1 {
  4692  			*(*prg.mem[p].hh()).lh() = uint16(r1 - int32(p)) // store the remaining size
  4693  			prg.rover = p                                    // start searching here next time
  4694  			// start searching here next time
  4695  			goto found
  4696  		}
  4697  		if r1 == int32(p) {
  4698  			if int32(*(*prg.mem[int32(p)+1].hh()).rh()) != int32(p) {
  4699  				prg.rover = *(*prg.mem[int32(p)+1].hh()).rh()
  4700  				t = int32(*(*prg.mem[int32(p)+1].hh()).lh())
  4701  				*(*prg.mem[int32(prg.rover)+1].hh()).lh() = uint16(t)
  4702  				*(*prg.mem[t+1].hh()).rh() = prg.rover
  4703  
  4704  				goto found
  4705  			}
  4706  		}
  4707  		*(*prg.mem[p].hh()).lh() = uint16(int32(q) - int32(p))
  4708  		p = *(*prg.mem[int32(p)+1].hh()).rh() // move to the next node in the ring
  4709  		if int32(p) == int32(prg.rover) {
  4710  			break
  4711  		}
  4712  	} // repeat until the whole list has been traversed
  4713  	if s == 010000000000 {
  4714  		r = 65535
  4715  		goto exit
  4716  	}
  4717  	if int32(prg.loMemMax)+2 < int32(prg.hiMemMin) {
  4718  		if int32(prg.loMemMax)+2 <= memMin+65535 {
  4719  			if int32(prg.hiMemMin)-int32(prg.loMemMax) >= 1998 {
  4720  				t = int32(prg.loMemMax) + 1000
  4721  			} else {
  4722  				t = int32(prg.loMemMax) + 1 + (int32(prg.hiMemMin)-int32(prg.loMemMax))/2
  4723  			}
  4724  			// |lo_mem_max+2<=t<hi_mem_min|
  4725  			if t > memMin+65535 {
  4726  				t = memMin + 65535
  4727  			}
  4728  			p = *(*prg.mem[int32(prg.rover)+1].hh()).lh()
  4729  			q = prg.loMemMax
  4730  			*(*prg.mem[int32(p)+1].hh()).rh() = q
  4731  			*(*prg.mem[int32(prg.rover)+1].hh()).lh() = q
  4732  
  4733  			*(*prg.mem[int32(q)+1].hh()).rh() = prg.rover
  4734  			*(*prg.mem[int32(q)+1].hh()).lh() = p
  4735  			*(*prg.mem[q].hh()).rh() = 65535
  4736  			*(*prg.mem[q].hh()).lh() = uint16(t - int32(prg.loMemMax))
  4737  
  4738  			prg.loMemMax = uint16(t)
  4739  			*(*prg.mem[prg.loMemMax].hh()).rh() = uint16(memMin)
  4740  			*(*prg.mem[prg.loMemMax].hh()).lh() = uint16(memMin)
  4741  			prg.rover = q
  4742  			goto restart
  4743  		}
  4744  	}
  4745  	prg.overflow(strNumber( /* "main memory size" */ 316), memMax+1-memMin)
  4746  	// sorry, nothing satisfactory is left
  4747  	// \xref[METAFONT capacity exceeded main memory size][\quad main memory size]
  4748  
  4749  	// sorry, nothing satisfactory is left
  4750  	// \xref[METAFONT capacity exceeded main memory size][\quad main memory size]
  4751  found:
  4752  	*(*prg.mem[r1].hh()).rh() = uint16(memMin) // this node is now nonempty
  4753  	prg.varUsed = prg.varUsed + s              // maintain usage statistics
  4754  
  4755  	r = uint16(r1)
  4756  
  4757  exit:
  4758  	;
  4759  	return r
  4760  }
  4761  
  4762  // 172.
  4763  
  4764  // tangle:pos ../../mf.web:3454:3:
  4765  
  4766  // Conversely, when some variable-size node |p| of size |s| is no longer needed,
  4767  // the operation |free_node(p,s)| will make its words available, by inserting
  4768  // |p| as a new empty node just before where |rover| now points.
  4769  func (prg *prg) freeNode(p halfword, s halfword) { // variable-size node
  4770  	//   liberation
  4771  
  4772  	var (
  4773  		q halfword // |llink(rover)|
  4774  	)
  4775  	*(*prg.mem[p].hh()).lh() = s
  4776  	*(*prg.mem[p].hh()).rh() = 65535
  4777  	// \xref[inner loop]
  4778  	q = *(*prg.mem[int32(prg.rover)+1].hh()).lh()
  4779  	*(*prg.mem[int32(p)+1].hh()).lh() = q
  4780  	*(*prg.mem[int32(p)+1].hh()).rh() = prg.rover // set both links
  4781  	*(*prg.mem[int32(prg.rover)+1].hh()).lh() = p
  4782  	*(*prg.mem[int32(q)+1].hh()).rh() = p // insert |p| into the ring
  4783  	prg.varUsed = prg.varUsed - int32(s)  // maintain statistics
  4784  }
  4785  
  4786  // 173.
  4787  
  4788  // tangle:pos ../../mf.web:3468:3:
  4789  
  4790  // Just before \.[INIMF] writes out the memory, it sorts the doubly linked
  4791  // available space list. The list is probably very short at such times, so a
  4792  // simple insertion sort is used. The smallest available location will be
  4793  // pointed to by |rover|, the next-smallest by |rlink(rover)|, etc.
  4794  func (prg *prg) sortAvail() { // sorts the available variable-size nodes
  4795  	//   by location
  4796  
  4797  	var (
  4798  		p, q, r1 halfword // indices into |mem|
  4799  		oldRover halfword // initial |rover| setting
  4800  	)
  4801  	p = prg.getNode(010000000000) // merge adjacent free areas
  4802  	p = *(*prg.mem[int32(prg.rover)+1].hh()).rh()
  4803  	*(*prg.mem[int32(prg.rover)+1].hh()).rh() = 65535
  4804  	oldRover = prg.rover
  4805  	for int32(p) != int32(oldRover) {
  4806  		// Sort |p| into the list starting at |rover| and advance |p| to |rlink(p)|
  4807  		if int32(p) < int32(prg.rover) {
  4808  			q = p
  4809  			p = *(*prg.mem[int32(q)+1].hh()).rh()
  4810  			*(*prg.mem[int32(q)+1].hh()).rh() = prg.rover
  4811  			prg.rover = q
  4812  		} else {
  4813  			q = prg.rover
  4814  			for int32(*(*prg.mem[int32(q)+1].hh()).rh()) < int32(p) {
  4815  				q = *(*prg.mem[int32(q)+1].hh()).rh()
  4816  			}
  4817  			r1 = *(*prg.mem[int32(p)+1].hh()).rh()
  4818  			*(*prg.mem[int32(p)+1].hh()).rh() = *(*prg.mem[int32(q)+1].hh()).rh()
  4819  			*(*prg.mem[int32(q)+1].hh()).rh() = p
  4820  			p = r1
  4821  		}
  4822  	}
  4823  	p = prg.rover
  4824  	for int32(*(*prg.mem[int32(p)+1].hh()).rh()) != 65535 {
  4825  		*(*prg.mem[int32(*(*prg.mem[int32(p)+1].hh()).rh())+1].hh()).lh() = p
  4826  		p = *(*prg.mem[int32(p)+1].hh()).rh()
  4827  	}
  4828  	*(*prg.mem[int32(p)+1].hh()).rh() = prg.rover
  4829  	*(*prg.mem[int32(prg.rover)+1].hh()).lh() = p
  4830  }
  4831  
  4832  // 175. \[11] Memory layout
  4833  
  4834  // tangle:pos ../../mf.web:3502:24:
  4835  
  4836  // Some areas of |mem| are dedicated to fixed usage, since static allocation is
  4837  // more efficient than dynamic allocation when we can get away with it. For
  4838  // example, locations |mem_min| to |mem_min+2| are always used to store the
  4839  // specification for null pen coordinates that are `$(0,0)$'. The
  4840  // following macro definitions accomplish the static allocation by giving
  4841  // symbolic names to the fixed positions. Static variable-size nodes appear
  4842  // in locations |mem_min| through |lo_mem_stat_max|, and static single-word nodes
  4843  // appear in locations |hi_mem_stat_min| through |mem_top|, inclusive.
  4844  
  4845  // 177.
  4846  
  4847  // tangle:pos ../../mf.web:3545:3:
  4848  
  4849  // The procedure |flush_list(p)| frees an entire linked list of one-word
  4850  // nodes that starts at a given position, until coming to |sentinel| or a
  4851  // pointer that is not in the one-word region. Another procedure,
  4852  // |flush_node_list|, frees an entire linked list of one-word and two-word
  4853  // nodes, until coming to a |null| pointer.
  4854  // \xref[inner loop]
  4855  func (prg *prg) flushList(p halfword) {
  4856  	var (
  4857  		q, r1 halfword // list traversers
  4858  	)
  4859  	if int32(p) >= int32(prg.hiMemMin) {
  4860  		if int32(p) != 3000 {
  4861  			r1 = p
  4862  			for {
  4863  				q = r1
  4864  				r1 = *(*prg.mem[r1].hh()).rh()
  4865  				prg.dynUsed = prg.dynUsed - 1
  4866  
  4867  				if int32(r1) < int32(prg.hiMemMin) {
  4868  					goto done
  4869  				}
  4870  				if int32(r1) == 3000 {
  4871  					break
  4872  				}
  4873  			}
  4874  
  4875  		done:
  4876  			*(*prg.mem[q].hh()).rh() = prg.avail
  4877  			prg.avail = p
  4878  		}
  4879  	}
  4880  }
  4881  
  4882  func (prg *prg) flushNodeList(p halfword) {
  4883  	var (
  4884  		q halfword // the node being recycled
  4885  	)
  4886  	for int32(p) != memMin {
  4887  		q = p
  4888  		p = *(*prg.mem[p].hh()).rh()
  4889  		if int32(q) < int32(prg.hiMemMin) {
  4890  			prg.freeNode(q, halfword(2))
  4891  		} else {
  4892  			*(*prg.mem[q].hh()).rh() = prg.avail
  4893  			prg.avail = q
  4894  			prg.dynUsed = prg.dynUsed - 1
  4895  		}
  4896  	}
  4897  }
  4898  
  4899  // 180.
  4900  
  4901  // tangle:pos ../../mf.web:3599:3:
  4902  
  4903  // Procedure |check_mem| makes sure that the available space lists of
  4904  // |mem| are well formed, and it optionally prints out all locations
  4905  // that are reserved now but were free the last time this procedure was called.
  4906  //  procedure check_mem( print_locs : boolean);
  4907  // label done1,done2; [loop exits]
  4908  // var  p, q, r:halfword ; [current locations of interest in |mem|]
  4909  //  clobbered:boolean; [is something amiss?]
  4910  // begin for p:=mem_min to lo_mem_max do free[p]:=false; [you can probably
  4911  //   do this faster]
  4912  // for p:=hi_mem_min to mem_end do free[p]:=false; [ditto]
  4913  //
  4914  // [ Check single-word |avail| list ]
  4915  // p:=avail; q:=mem_min ; clobbered:=false;
  4916  // while p<>mem_min  do
  4917  //   begin if (p>mem_end)or(p<hi_mem_min) then clobbered:=true
  4918  //   else if free[p] then clobbered:=true;
  4919  //   if clobbered then
  4920  //     begin print_nl(["AVAIL list clobbered at "=]317);
  4921  // [ \xref[AVAIL list clobbered...] ]
  4922  //     print_int(q); goto done1;
  4923  //     end;
  4924  //   free[p]:=true; q:=p; p:= mem[ q].hh.rh ;
  4925  //   end;
  4926  // done1:
  4927  //
  4928  // ;
  4929  //
  4930  // [ Check variable-size |avail| list ]
  4931  // p:=rover; q:=mem_min ; clobbered:=false;
  4932  // repeat if (p>=lo_mem_max)or(p<mem_min) then clobbered:=true
  4933  //   else if (  mem[  p+ 1].hh.rh  >=lo_mem_max)or(  mem[  p+ 1].hh.rh  <mem_min) then clobbered:=true
  4934  //   else if  not( ( mem[  p].hh.rh = 65535  ) )or(  mem[ p].hh.lh <2)or
  4935  //    (p+  mem[ p].hh.lh >lo_mem_max)or  (  mem[    mem[    p+ 1].hh.rh  + 1].hh.lh  <>p) then clobbered:=true;
  4936  //   if clobbered then
  4937  //   begin print_nl(["Double-AVAIL list clobbered at "=]318);
  4938  // [ \xref[Double-AVAIL list clobbered...] ]
  4939  //   print_int(q); goto done2;
  4940  //   end;
  4941  // for q:=p to p+  mem[ p].hh.lh -1 do [mark all locations free]
  4942  //   begin if free[q] then
  4943  //     begin print_nl(["Doubly free location at "=]319);
  4944  // [ \xref[Doubly free location...] ]
  4945  //     print_int(q); goto done2;
  4946  //     end;
  4947  //   free[q]:=true;
  4948  //   end;
  4949  // q:=p; p:=  mem[  p+ 1].hh.rh  ;
  4950  // until p=rover;
  4951  // done2:
  4952  //
  4953  // ;
  4954  //
  4955  // [ Check flags of unavailable nodes ]
  4956  // p:=mem_min;
  4957  // while p<=lo_mem_max do [node |p| should not be empty]
  4958  //   begin if  ( mem[  p].hh.rh = 65535  )  then
  4959  //     begin print_nl(["Bad flag at "=]320); print_int(p);
  4960  // [ \xref[Bad flag...] ]
  4961  //     end;
  4962  //   while (p<=lo_mem_max) and not free[p] do   p:= p+1 ;
  4963  //   while (p<=lo_mem_max) and free[p] do   p:= p+1 ;
  4964  //   end
  4965  //
  4966  // ;
  4967  //
  4968  // [ Check the list of linear dependencies ]
  4969  // q:=mem_min +3 +10 ; p:= mem[ q].hh.rh ;
  4970  // while p<>mem_min +3 +10  do
  4971  //   begin if  mem[    p+1 ].hh.lh  <>q then
  4972  //     begin print_nl(["Bad PREVDEP at "=]597); print_int(p);
  4973  // [ \xref[Bad PREVDEP...] ]
  4974  //     end;
  4975  //   p:= mem[    p+1 ].hh.rh  ; r:=mem_min +3 +10 +2 +2  +2 ;
  4976  //   repeat if mem[   mem[   p].hh.lh +1 ].int >=mem[  r+1 ].int  then
  4977  //     begin print_nl(["Out of order at "=]598); print_int(p);
  4978  // [ \xref[Out of order...] ]
  4979  //     end;
  4980  //   r:= mem[ p].hh.lh ; q:=p; p:= mem[ q].hh.rh ;
  4981  //   until r=mem_min ;
  4982  //   end
  4983  //
  4984  // ;
  4985  // if print_locs then
  4986  // [ Print newly busy locations ]
  4987  // begin print_nl(["New busy locs:"=]321);
  4988  // [ \xref[New busy locs] ]
  4989  // for p:=mem_min to lo_mem_max do
  4990  //   if not free[p] and ((p>was_lo_max) or was_free[p]) then
  4991  //     begin print_char([" "=]32); print_int(p);
  4992  //     end;
  4993  // for p:=hi_mem_min to mem_end do
  4994  //   if not free[p] and
  4995  //    ((p<was_hi_min) or (p>was_mem_end) or was_free[p]) then
  4996  //     begin print_char([" "=]32); print_int(p);
  4997  //     end;
  4998  // end
  4999  //
  5000  // ;
  5001  // for p:=mem_min to lo_mem_max do was_free[p]:=free[p];
  5002  // for p:=hi_mem_min to mem_end do was_free[p]:=free[p];
  5003  //   [|was_free:=free| might be faster]
  5004  // was_mem_end:=mem_end; was_lo_max:=lo_mem_max; was_hi_min:=hi_mem_min;
  5005  // end;
  5006  // [  ]
  5007  
  5008  // 185.
  5009  
  5010  // tangle:pos ../../mf.web:3684:3:
  5011  
  5012  // The |search_mem| procedure attempts to answer the question ``Who points
  5013  // to node~|p|?'' In doing so, it fetches |link| and |info| fields of |mem|
  5014  // that might not be of type |two_halves|. Strictly speaking, this is
  5015  // \xref[dirty \PASCAL]
  5016  // undefined in \PASCAL, and it can lead to ``false drops'' (words that seem to
  5017  // point to |p| purely by coincidence). But for debugging purposes, we want
  5018  // to rule out the places that do [\sl not\/] point to |p|, so a few false
  5019  // drops are tolerable.
  5020  //  procedure search_mem( p:halfword ); [look for pointers to |p|]
  5021  // var  q:integer; [current position being searched]
  5022  // begin for q:=mem_min to lo_mem_max do
  5023  //   begin if  mem[ q].hh.rh =p then
  5024  //     begin print_nl(["LINK("=]322); print_int(q); print_char([")"=]41);
  5025  //     end;
  5026  //   if  mem[ q].hh.lh =p then
  5027  //     begin print_nl(["INFO("=]323); print_int(q); print_char([")"=]41);
  5028  //     end;
  5029  //   end;
  5030  // for q:=hi_mem_min to mem_end do
  5031  //   begin if  mem[ q].hh.rh =p then
  5032  //     begin print_nl(["LINK("=]322); print_int(q); print_char([")"=]41);
  5033  //     end;
  5034  //   if  mem[ q].hh.lh =p then
  5035  //     begin print_nl(["INFO("=]323); print_int(q); print_char([")"=]41);
  5036  //     end;
  5037  //   end;
  5038  //
  5039  // [ Search |eqtb| for equivalents equal to |p| ]
  5040  // for q:=1 to hash_base+hash_size +12  do
  5041  //   begin if  eqtb[ q].rh =p then
  5042  //     begin print_nl(["EQUIV("=]458); print_int(q); print_char([")"=]41);
  5043  //     end;
  5044  //   end
  5045  //
  5046  // ;
  5047  // end;
  5048  // [  ]
  5049  
  5050  // 188.
  5051  
  5052  // tangle:pos ../../mf.web:3900:3:
  5053  
  5054  // Values inside \MF\ are stored in two-word nodes that have a |name_type|
  5055  // as well as a |type|. The possibilities for |name_type| are defined
  5056  // here; they will be explained in more detail later.
  5057  
  5058  // 189.
  5059  
  5060  // tangle:pos ../../mf.web:3918:3:
  5061  
  5062  // Primitive operations that produce values have a secondary identification
  5063  // code in addition to their command code; it's something like genera and species.
  5064  // For example, `\.*' has the command code |primary_binary|, and its
  5065  // secondary identification is |times|. The secondary codes start at 30 so that
  5066  // they don't overlap with the type codes; some type codes (e.g., |string_type|)
  5067  // are used as operators as well as type identifications.
  5068  func (prg *prg) printOp(c quarterword) {
  5069  	if int32(c) <= numericType {
  5070  		prg.printType(c)
  5071  	} else {
  5072  		switch c {
  5073  		case trueCode:
  5074  			prg.print( /* "true" */ 348)
  5075  		case falseCode:
  5076  			prg.print( /* "false" */ 349)
  5077  		case nullPictureCode:
  5078  			prg.print( /* "nullpicture" */ 350)
  5079  		case nullPenCode:
  5080  			prg.print( /* "nullpen" */ 351)
  5081  		case jobNameOp:
  5082  			prg.print( /* "jobname" */ 352)
  5083  		case readStringOp:
  5084  			prg.print( /* "readstring" */ 353)
  5085  		case penCircle:
  5086  			prg.print( /* "pencircle" */ 354)
  5087  		case normalDeviate:
  5088  			prg.print( /* "normaldeviate" */ 355)
  5089  		case oddOp:
  5090  			prg.print( /* "odd" */ 356)
  5091  		case knownOp:
  5092  			prg.print( /* "known" */ 357)
  5093  		case unknownOp:
  5094  			prg.print( /* "unknown" */ 358)
  5095  		case notOp:
  5096  			prg.print( /* "not" */ 359)
  5097  		case decimal:
  5098  			prg.print( /* "decimal" */ 360)
  5099  		case reverse:
  5100  			prg.print( /* "reverse" */ 361)
  5101  		case makePathOp:
  5102  			prg.print( /* "makepath" */ 362)
  5103  		case makePenOp:
  5104  			prg.print( /* "makepen" */ 363)
  5105  		case totalWeightOp:
  5106  			prg.print( /* "totalweight" */ 364)
  5107  		case octOp:
  5108  			prg.print( /* "oct" */ 365)
  5109  		case hexOp:
  5110  			prg.print( /* "hex" */ 366)
  5111  		case asciiOp:
  5112  			prg.print( /* "ASCII" */ 367)
  5113  		case charOp:
  5114  			prg.print( /* "char" */ 368)
  5115  		case lengthOp:
  5116  			prg.print( /* "length" */ 369)
  5117  		case turningOp:
  5118  			prg.print( /* "turningnumber" */ 370)
  5119  		case xPart:
  5120  			prg.print( /* "xpart" */ 371)
  5121  		case yPart:
  5122  			prg.print( /* "ypart" */ 372)
  5123  		case xxPart:
  5124  			prg.print( /* "xxpart" */ 373)
  5125  		case xyPart:
  5126  			prg.print( /* "xypart" */ 374)
  5127  		case yxPart:
  5128  			prg.print( /* "yxpart" */ 375)
  5129  		case yyPart:
  5130  			prg.print( /* "yypart" */ 376)
  5131  		case sqrtOp:
  5132  			prg.print( /* "sqrt" */ 377)
  5133  		case mExpOp:
  5134  			prg.print( /* "mexp" */ 378)
  5135  		case mLogOp:
  5136  			prg.print( /* "mlog" */ 379)
  5137  		case sinDOp:
  5138  			prg.print( /* "sind" */ 380)
  5139  		case cosDOp:
  5140  			prg.print( /* "cosd" */ 381)
  5141  		case floorOp:
  5142  			prg.print( /* "floor" */ 382)
  5143  		case uniformDeviate:
  5144  			prg.print( /* "uniformdeviate" */ 383)
  5145  		case charExistsOp:
  5146  			prg.print( /* "charexists" */ 384)
  5147  		case angleOp:
  5148  			prg.print( /* "angle" */ 385)
  5149  		case cycleOp:
  5150  			prg.print( /* "cycle" */ 386)
  5151  		case plus:
  5152  			prg.printChar(asciiCode('+'))
  5153  		case minus:
  5154  			prg.printChar(asciiCode('-'))
  5155  		case times:
  5156  			prg.printChar(asciiCode('*'))
  5157  		case over:
  5158  			prg.printChar(asciiCode('/'))
  5159  		case pythagAdd:
  5160  			prg.print( /* "++" */ 387)
  5161  		case pythagSub:
  5162  			prg.print( /* "+-+" */ 311)
  5163  		case orOp:
  5164  			prg.print( /* "or" */ 388)
  5165  		case andOp:
  5166  			prg.print( /* "and" */ 389)
  5167  		case lessThan:
  5168  			prg.printChar(asciiCode('<'))
  5169  		case lessOrEqual:
  5170  			prg.print( /* "<=" */ 390)
  5171  		case greaterThan:
  5172  			prg.printChar(asciiCode('>'))
  5173  		case greaterOrEqual:
  5174  			prg.print( /* ">=" */ 391)
  5175  		case equalTo:
  5176  			prg.printChar(asciiCode('='))
  5177  		case unequalTo:
  5178  			prg.print( /* "<>" */ 392)
  5179  		case concatenate:
  5180  			prg.print('&')
  5181  		case rotatedBy:
  5182  			prg.print( /* "rotated" */ 393)
  5183  		case slantedBy:
  5184  			prg.print( /* "slanted" */ 394)
  5185  		case scaledBy:
  5186  			prg.print( /* "scaled" */ 395)
  5187  		case shiftedBy:
  5188  			prg.print( /* "shifted" */ 396)
  5189  		case transformedBy:
  5190  			prg.print( /* "transformed" */ 397)
  5191  		case xScaled:
  5192  			prg.print( /* "xscaled" */ 398)
  5193  		case yScaled:
  5194  			prg.print( /* "yscaled" */ 399)
  5195  		case zScaled:
  5196  			prg.print( /* "zscaled" */ 400)
  5197  		case intersect:
  5198  			prg.print( /* "intersectiontimes" */ 401)
  5199  		case substringOf:
  5200  			prg.print( /* "substring" */ 402)
  5201  		case subpathOf:
  5202  			prg.print( /* "subpath" */ 403)
  5203  		case directionTimeOf:
  5204  			prg.print( /* "directiontime" */ 404)
  5205  		case pointOf:
  5206  			prg.print( /* "point" */ 405)
  5207  		case precontrolOf:
  5208  			prg.print( /* "precontrol" */ 406)
  5209  		case postcontrolOf:
  5210  			prg.print( /* "postcontrol" */ 407)
  5211  		case penOffsetOf:
  5212  			prg.print( /* "penoffset" */ 408)
  5213  
  5214  		default:
  5215  			prg.print( /* ".." */ 409)
  5216  		}
  5217  	}
  5218  }
  5219  
  5220  // 194.
  5221  
  5222  // tangle:pos ../../mf.web:4268:3:
  5223  
  5224  // The following procedure, which is called just before \MF\ initializes its
  5225  // input and output, establishes the initial values of the date and time.
  5226  // \xref[system dependencies]
  5227  // Since standard \PASCAL\ cannot provide such information, something special
  5228  // is needed. The program here simply assumes that suitable values appear in
  5229  // the global variables \\[sys\_time], \\[sys\_day], \\[sys\_month], and
  5230  // \\[sys\_year] (which are initialized to noon on 4 July 1776,
  5231  // in case the implementor is careless).
  5232  //
  5233  // Note that the values are |scaled| integers. Hence \MF\ can no longer
  5234  // be used after the year 32767.
  5235  func (prg *prg) fixDateAndTime() {
  5236  	prg.sysTime = 12 * 60
  5237  	prg.sysDay = 4
  5238  	prg.sysMonth = 7
  5239  	prg.sysYear = 1776                             // self-evident truths
  5240  	prg.internal[time-1] = prg.sysTime * 0200000   // minutes since midnight
  5241  	prg.internal[day-1] = prg.sysDay * 0200000     // day of the month
  5242  	prg.internal[month-1] = prg.sysMonth * 0200000 // month of the year
  5243  	prg.internal[year-1] = prg.sysYear * 0200000   // Anno Domini
  5244  }
  5245  
  5246  // 205.
  5247  
  5248  // tangle:pos ../../mf.web:4485:3:
  5249  
  5250  // Here is the subroutine that searches the hash table for an identifier
  5251  // that matches a given string of length~|l| appearing in |buffer[j..
  5252  // (j+l-1)]|. If the identifier is not found, it is inserted; hence it
  5253  // will always be found, and the corresponding hash table address
  5254  // will be returned.
  5255  func (prg *prg) idLookup(j, l int32) (r halfword) { // go here when you've found it
  5256  	var (
  5257  		h int32    // hash code
  5258  		p halfword // index in |hash| array
  5259  		k halfword // index in |buffer| array
  5260  	)
  5261  	if l == 1 {
  5262  		p = uint16(int32(prg.buffer[j]) + 1)
  5263  		*prg.hash[p-1].rh() = uint16(int32(p) - 1)
  5264  		goto found
  5265  	}
  5266  
  5267  	// Compute the hash code |h|
  5268  	h = int32(prg.buffer[j])
  5269  	for ii := j + 1; ii <= j+l-1; ii++ {
  5270  		k = halfword(ii)
  5271  		_ = k
  5272  		h = h + h + int32(prg.buffer[k])
  5273  		for h >= hashPrime {
  5274  			h = h - hashPrime
  5275  		}
  5276  	}
  5277  	p = uint16(h + hashBase) // we start searching here; note that |0<=h<hash_prime|
  5278  	for true {
  5279  		if int32(*prg.hash[p-1].rh()) > 0 {
  5280  			if int32(prg.strStart[int32(*prg.hash[p-1].rh())+1])-int32(prg.strStart[*prg.hash[p-1].rh()]) == l {
  5281  				if prg.strEqBuf(*prg.hash[p-1].rh(), j) {
  5282  					goto found
  5283  				}
  5284  			}
  5285  		}
  5286  		if int32(*prg.hash[p-1].lh()) == 0 {
  5287  			if int32(*prg.hash[p-1].rh()) > 0 {
  5288  				for {
  5289  					if int32(prg.hashUsed) == hashBase {
  5290  						prg.overflow(strNumber( /* "hash size" */ 457), hashSize)
  5291  					}
  5292  					// \xref[METAFONT capacity exceeded hash size][\quad hash size]
  5293  					prg.hashUsed = uint16(int32(prg.hashUsed) - 1)
  5294  					if int32(*prg.hash[prg.hashUsed-1].rh()) == 0 {
  5295  						break
  5296  					}
  5297  				} // search for an empty location in |hash|
  5298  				*prg.hash[p-1].lh() = prg.hashUsed
  5299  				p = prg.hashUsed
  5300  			}
  5301  			{
  5302  				if int32(prg.poolPtr)+l > int32(prg.maxPoolPtr) {
  5303  					if int32(prg.poolPtr)+l > poolSize {
  5304  						prg.overflow(strNumber( /* "pool size" */ 257), poolSize-int32(prg.initPoolPtr))
  5305  					} /* \xref[METAFONT capacity exceeded pool size][\quad pool size]  */
  5306  					prg.maxPoolPtr = uint16(int32(prg.poolPtr) + l)
  5307  				}
  5308  			}
  5309  			for ii := j; ii <= j+l-1; ii++ {
  5310  				k = halfword(ii)
  5311  				_ = k
  5312  				prg.strPool[prg.poolPtr] = prg.buffer[k]
  5313  				prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  5314  			}
  5315  			*prg.hash[p-1].rh() = prg.makeString()
  5316  			prg.strRef[*prg.hash[p-1].rh()] = byte(maxStrRef)
  5317  			prg.stCount = prg.stCount + 1
  5318  
  5319  			goto found
  5320  		}
  5321  		p = *prg.hash[p-1].lh()
  5322  	}
  5323  
  5324  found:
  5325  	r = p
  5326  	return r
  5327  }
  5328  
  5329  // 210.
  5330  
  5331  // tangle:pos ../../mf.web:4549:3:
  5332  
  5333  // We need to put \MF's ``primitive'' symbolic tokens into the hash
  5334  // table, together with their command code (which will be the |eq_type|)
  5335  // and an operand (which will be the |equiv|). The |primitive| procedure
  5336  // does this, in a way that no \MF\ user can. The global value |cur_sym|
  5337  // contains the new |eqtb| pointer after |primitive| has acted.
  5338  func (prg *prg) primitive(s strNumber, c halfword, o halfword) {
  5339  	var (
  5340  		k poolPointer // index into |str_pool|
  5341  		j smallNumber // index into |buffer|
  5342  		l smallNumber // length of the string
  5343  	)
  5344  	k = prg.strStart[s]
  5345  	l = byte(int32(prg.strStart[int32(s)+1]) - int32(k))
  5346  	// we will move |s| into the (empty) |buffer|
  5347  	for ii := int32(0); ii <= int32(l)-1; ii++ {
  5348  		j = smallNumber(ii)
  5349  		_ = j
  5350  		prg.buffer[j] = prg.strPool[int32(k)+int32(j)]
  5351  	}
  5352  	prg.curSym = prg.idLookup(0, int32(l))
  5353  
  5354  	if int32(s) >= 256 {
  5355  		prg.flushString(strNumber(int32(prg.strPtr) - 1))
  5356  		*prg.hash[prg.curSym-1].rh() = s
  5357  	}
  5358  	*prg.eqtb[prg.curSym-1].lh() = c
  5359  	*prg.eqtb[prg.curSym-1].rh() = o
  5360  }
  5361  
  5362  // 213.
  5363  
  5364  // tangle:pos ../../mf.web:4712:3:
  5365  
  5366  // We will deal with the other primitives later, at some point in the program
  5367  // where their |eq_type| and |equiv| values are more meaningful.  For example,
  5368  // the primitives for macro definitions will be loaded when we consider the
  5369  // routines that define macros.
  5370  // It is easy to find where each particular
  5371  // primitive was treated by looking in the index at the end; for example, the
  5372  // section where |"def"| entered |eqtb| is listed under `\&[def] primitive'.
  5373  
  5374  // 215.
  5375  
  5376  // tangle:pos ../../mf.web:4764:3:
  5377  
  5378  // A numeric token is created by the following trivial routine.
  5379  func (prg *prg) newNumTok(v scaled) (r halfword) {
  5380  	var (
  5381  		p halfword // the new node
  5382  	)
  5383  	p = prg.getNode(tokenNodeSize)
  5384  	*prg.mem[int32(p)+1].int() = v
  5385  	*(*prg.mem[p].hh()).b0() = byte(known)
  5386  	*(*prg.mem[p].hh()).b1() = byte(token)
  5387  	r = p
  5388  	return r
  5389  } // \2
  5390  
  5391  func (prg *prg) flushTokenList(p halfword) {
  5392  	var (
  5393  		q halfword // the node being recycled
  5394  	)
  5395  	for int32(p) != memMin {
  5396  		q = p
  5397  		p = *(*prg.mem[p].hh()).rh()
  5398  		if int32(q) >= int32(prg.hiMemMin) {
  5399  			*(*prg.mem[q].hh()).rh() = prg.avail
  5400  			prg.avail = q
  5401  			prg.dynUsed = prg.dynUsed - 1
  5402  		} else {
  5403  			switch *(*prg.mem[q].hh()).b0() {
  5404  			case vacuous, booleanType, known:
  5405  			case stringType:
  5406  				if int32(prg.strRef[*prg.mem[int32(q)+1].int()]) < maxStrRef {
  5407  					if int32(prg.strRef[*prg.mem[int32(q)+1].int()]) > 1 {
  5408  						prg.strRef[*prg.mem[int32(q)+1].int()] = byte(int32(prg.strRef[*prg.mem[int32(q)+1].int()]) - 1)
  5409  					} else {
  5410  						prg.flushString(strNumber(*prg.mem[int32(q)+1].int()))
  5411  					}
  5412  				}
  5413  			case unknownBoolean, unknownString, unknownPen, unknownPicture,
  5414  				unknownPath, penType, pathType, futurePen,
  5415  				pictureType, pairType, transformType, dependent,
  5416  				protoDependent, independent:
  5417  				prg.gPointer = q
  5418  				prg.tokenRecycle()
  5419  
  5420  			default:
  5421  				prg.confusion(strNumber( /* "token" */ 491))
  5422  				// \xref[this can't happen token][\quad token]
  5423  			}
  5424  
  5425  			prg.freeNode(q, halfword(tokenNodeSize))
  5426  		}
  5427  	}
  5428  }
  5429  
  5430  // 226.
  5431  
  5432  // tangle:pos ../../mf.web:4940:3:
  5433  
  5434  // Macro definitions are kept in \MF's memory in the form of token lists
  5435  // that have a few extra one-word nodes at the beginning.
  5436  //
  5437  // The first node contains a reference count that is used to tell when the
  5438  // list is no longer needed. To emphasize the fact that a reference count is
  5439  // present, we shall refer to the |info| field of this special node as the
  5440  // |ref_count| field.
  5441  // \xref[reference counts]
  5442  //
  5443  // The next node or nodes after the reference count serve to describe the
  5444  // formal parameters. They consist of zero or more parameter tokens followed
  5445  // by a code for the type of macro.
  5446  func (prg *prg) deleteMacRef(p halfword) {
  5447  	if int32(*(*prg.mem[p].hh()).lh()) == memMin {
  5448  		prg.flushTokenList(p)
  5449  	} else {
  5450  		*(*prg.mem[p].hh()).lh() = uint16(int32(*(*prg.mem[p].hh()).lh()) - 1)
  5451  	}
  5452  }
  5453  
  5454  // 227.
  5455  
  5456  // tangle:pos ../../mf.web:4972:3:
  5457  
  5458  // The following subroutine displays a macro, given a pointer to its
  5459  // reference count.
  5460  // \4
  5461  // Declare the procedure called |print_cmd_mod|
  5462  func (prg *prg) printCmdMod(c, m int32) {
  5463  	switch c {
  5464  	case addToCommand:
  5465  		prg.print( /* "addto" */ 462)
  5466  	case assignment:
  5467  		prg.print( /* ":=" */ 461)
  5468  	case atLeast:
  5469  		prg.print( /* "atleast" */ 464)
  5470  	case atToken:
  5471  		prg.print( /* "at" */ 463)
  5472  	case bcharLabel:
  5473  		prg.print( /* "||:" */ 460)
  5474  	case beginGroup:
  5475  		prg.print( /* "begingroup" */ 465)
  5476  	case colon:
  5477  		prg.print(':')
  5478  	case comma:
  5479  		prg.print(',')
  5480  	case controls:
  5481  		prg.print( /* "controls" */ 466)
  5482  	case cullCommand:
  5483  		prg.print( /* "cull" */ 467)
  5484  	case curlCommand:
  5485  		prg.print( /* "curl" */ 468)
  5486  	case delimiters:
  5487  		prg.print( /* "delimiters" */ 469)
  5488  	case displayCommand:
  5489  		prg.print( /* "display" */ 470)
  5490  	case doubleColon:
  5491  		prg.print( /* "::" */ 459)
  5492  	case endGroup:
  5493  		prg.print( /* "endgroup" */ 453)
  5494  	case everyJobCommand:
  5495  		prg.print( /* "everyjob" */ 471)
  5496  	case exitTest:
  5497  		prg.print( /* "exitif" */ 472)
  5498  	case expandAfter:
  5499  		prg.print( /* "expandafter" */ 473)
  5500  	case fromToken:
  5501  		prg.print( /* "from" */ 474)
  5502  	case inWindow:
  5503  		prg.print( /* "inwindow" */ 475)
  5504  	case interimCommand:
  5505  		prg.print( /* "interim" */ 476)
  5506  	case leftBrace:
  5507  		prg.print('{')
  5508  	case leftBracket:
  5509  		prg.print('[')
  5510  	case letCommand:
  5511  		prg.print( /* "let" */ 477)
  5512  	case newInternal:
  5513  		prg.print( /* "newinternal" */ 478)
  5514  	case ofToken:
  5515  		prg.print( /* "of" */ 479)
  5516  	case openWindow:
  5517  		prg.print( /* "openwindow" */ 480)
  5518  	case pathJoin:
  5519  		prg.print( /* ".." */ 409)
  5520  	case randomSeed:
  5521  		prg.print( /* "randomseed" */ 481)
  5522  	case relax:
  5523  		prg.printChar(asciiCode('\\'))
  5524  	case rightBrace:
  5525  		prg.print('}')
  5526  	case rightBracket:
  5527  		prg.print(']')
  5528  	case saveCommand:
  5529  		prg.print( /* "save" */ 482)
  5530  	case scanTokens:
  5531  		prg.print( /* "scantokens" */ 483)
  5532  	case semicolon:
  5533  		prg.print(';')
  5534  	case shipOutCommand:
  5535  		prg.print( /* "shipout" */ 484)
  5536  	case skipTo:
  5537  		prg.print( /* "skipto" */ 485)
  5538  	case stepToken:
  5539  		prg.print( /* "step" */ 486)
  5540  	case strOp:
  5541  		prg.print( /* "str" */ 487)
  5542  	case tension:
  5543  		prg.print( /* "tension" */ 488)
  5544  	case toToken:
  5545  		prg.print( /* "to" */ 489)
  5546  	case untilToken:
  5547  		prg.print( /* "until" */ 490)
  5548  
  5549  	case macroDef:
  5550  		if m <= varDef {
  5551  			if m == startDef {
  5552  				prg.print( /* "def" */ 654)
  5553  			} else if m < startDef {
  5554  				prg.print( /* "enddef" */ 454)
  5555  			} else {
  5556  				prg.print( /* "vardef" */ 655)
  5557  			}
  5558  		} else if m == secondaryPrimaryMacro {
  5559  			prg.print( /* "primarydef" */ 656)
  5560  		} else if m == tertiarySecondaryMacro {
  5561  			prg.print( /* "secondarydef" */ 657)
  5562  		} else {
  5563  			prg.print( /* "tertiarydef" */ 658)
  5564  		}
  5565  	case iteration:
  5566  		if m <= startForever {
  5567  			if m == startForever {
  5568  				prg.print( /* "forever" */ 661)
  5569  			} else {
  5570  				prg.print( /* "endfor" */ 455)
  5571  			}
  5572  		} else if m == hashBase+hashSize+12+1 {
  5573  			prg.print( /* "for" */ 659)
  5574  		} else {
  5575  			prg.print( /* "forsuffixes" */ 660)
  5576  		}
  5577  
  5578  	case macroSpecial:
  5579  		switch m {
  5580  		case macroPrefix:
  5581  			prg.print( /* "#@" */ 663)
  5582  		case macroAt:
  5583  			prg.printChar(asciiCode('@'))
  5584  		case macroSuffix:
  5585  			prg.print( /* "@#" */ 664)
  5586  
  5587  		default:
  5588  			prg.print( /* "quote" */ 662)
  5589  		}
  5590  
  5591  	case paramType:
  5592  		if m >= hashBase+hashSize+12+1 {
  5593  			if m == hashBase+hashSize+12+1 {
  5594  				prg.print( /* "expr" */ 675)
  5595  			} else if m == hashBase+hashSize+12+1+paramSize {
  5596  				prg.print( /* "suffix" */ 676)
  5597  			} else {
  5598  				prg.print( /* "text" */ 677)
  5599  			}
  5600  		} else if m < secondaryMacro {
  5601  			prg.print( /* "primary" */ 678)
  5602  		} else if m == secondaryMacro {
  5603  			prg.print( /* "secondary" */ 679)
  5604  		} else {
  5605  			prg.print( /* "tertiary" */ 680)
  5606  		}
  5607  
  5608  	case input:
  5609  		if m == 0 {
  5610  			prg.print( /* "input" */ 690)
  5611  		} else {
  5612  			prg.print( /* "endinput" */ 616)
  5613  		}
  5614  
  5615  	case ifTest, fiOrElse:
  5616  		switch m {
  5617  		case ifCode:
  5618  			prg.print( /* "if" */ 717)
  5619  		case fiCode:
  5620  			prg.print( /* "fi" */ 452)
  5621  		case elseCode:
  5622  			prg.print( /* "else" */ 718)
  5623  
  5624  		default:
  5625  			prg.print( /* "elseif" */ 719)
  5626  		}
  5627  
  5628  	case nullary, unary, primaryBinary, secondaryBinary,
  5629  		tertiaryBinary, expressionBinary, cycle, plusOrMinus,
  5630  		slash, ampersand, equals, andCommand:
  5631  		prg.printOp(quarterword(m))
  5632  
  5633  	case typeName:
  5634  		prg.printType(smallNumber(m))
  5635  
  5636  	case stop:
  5637  		if m == 0 {
  5638  			prg.print( /* "end" */ 912)
  5639  		} else {
  5640  			prg.print( /* "dump" */ 913)
  5641  		}
  5642  
  5643  	case modeCommand:
  5644  		switch m {
  5645  		case batchMode:
  5646  			prg.print( /* "batchmode" */ 273)
  5647  		case nonstopMode:
  5648  			prg.print( /* "nonstopmode" */ 274)
  5649  		case scrollMode:
  5650  			prg.print( /* "scrollmode" */ 275)
  5651  
  5652  		default:
  5653  			prg.print( /* "errorstopmode" */ 919)
  5654  		}
  5655  
  5656  	case protectionCommand:
  5657  		if m == 0 {
  5658  			prg.print( /* "inner" */ 920)
  5659  		} else {
  5660  			prg.print( /* "outer" */ 921)
  5661  		}
  5662  
  5663  	case showCommand:
  5664  		switch m {
  5665  		case showTokenCode:
  5666  			prg.print( /* "showtoken" */ 935)
  5667  		case showStatsCode:
  5668  			prg.print( /* "showstats" */ 936)
  5669  		case showCode:
  5670  			prg.print( /* "show" */ 937)
  5671  		case showVarCode:
  5672  			prg.print( /* "showvariable" */ 938)
  5673  
  5674  		default:
  5675  			prg.print( /* "showdependencies" */ 939)
  5676  		}
  5677  
  5678  	case leftDelimiter, rightDelimiter:
  5679  		if c == leftDelimiter {
  5680  			prg.print( /* "lef" */ 942)
  5681  		} else {
  5682  			prg.print( /* "righ" */ 943)
  5683  		}
  5684  		prg.print( /* "t delimiter that matches " */ 944)
  5685  		prg.slowPrint(int32(*prg.hash[m-1].rh()))
  5686  
  5687  	case tagToken:
  5688  		if m == memMin {
  5689  			prg.print( /* "tag" */ 945)
  5690  		} else {
  5691  			prg.print( /* "variable" */ 946)
  5692  		}
  5693  	case definedMacro:
  5694  		prg.print( /* "macro:" */ 947)
  5695  	case secondaryPrimaryMacro, tertiarySecondaryMacro, expressionTertiaryMacro:
  5696  		prg.printCmdMod(macroDef, c)
  5697  		prg.print( /* "'d macro:" */ 948)
  5698  		prg.printLn()
  5699  		prg.showTokenList(int32(*(*prg.mem[*(*prg.mem[m].hh()).rh()].hh()).rh()), memMin, 1000, 0)
  5700  
  5701  	case repeatLoop:
  5702  		prg.print( /* "[repeat the loop]" */ 949)
  5703  	case internalQuantity:
  5704  		prg.slowPrint(int32(prg.intName[m-1]))
  5705  
  5706  	case thingToAdd:
  5707  		if m == contourCode {
  5708  			prg.print( /* "contour" */ 956)
  5709  		} else if m == doublePathCode {
  5710  			prg.print( /* "doublepath" */ 957)
  5711  		} else {
  5712  			prg.print( /* "also" */ 958)
  5713  		}
  5714  	case withOption:
  5715  		if m == penType {
  5716  			prg.print( /* "withpen" */ 959)
  5717  		} else {
  5718  			prg.print( /* "withweight" */ 960)
  5719  		}
  5720  	case cullOp:
  5721  		if m == dropCode {
  5722  			prg.print( /* "dropping" */ 961)
  5723  		} else {
  5724  			prg.print( /* "keeping" */ 962)
  5725  		}
  5726  
  5727  	case messageCommand:
  5728  		if m < errMessageCode {
  5729  			prg.print( /* "message" */ 992)
  5730  		} else if m == errMessageCode {
  5731  			prg.print( /* "errmessage" */ 993)
  5732  		} else {
  5733  			prg.print( /* "errhelp" */ 994)
  5734  		}
  5735  
  5736  	case tfmCommand:
  5737  		switch m {
  5738  		case charListCode:
  5739  			prg.print( /* "charlist" */ 1004)
  5740  		case ligTableCode:
  5741  			prg.print( /* "ligtable" */ 1005)
  5742  		case extensibleCode:
  5743  			prg.print( /* "extensible" */ 1006)
  5744  		case headerByteCode:
  5745  			prg.print( /* "headerbyte" */ 1007)
  5746  
  5747  		default:
  5748  			prg.print( /* "fontdimen" */ 1008)
  5749  		}
  5750  
  5751  	case ligKernToken:
  5752  		switch m {
  5753  		case 0:
  5754  			prg.print( /* "=:" */ 1026)
  5755  		case 1:
  5756  			prg.print( /* "=:|" */ 1027)
  5757  		case 2:
  5758  			prg.print( /* "|=:" */ 1029)
  5759  		case 3:
  5760  			prg.print( /* "|=:|" */ 1031)
  5761  		case 5:
  5762  			prg.print( /* "=:|>" */ 1028)
  5763  		case 6:
  5764  			prg.print( /* "|=:>" */ 1030)
  5765  		case 7:
  5766  			prg.print( /* "|=:|>" */ 1032)
  5767  		case 11:
  5768  			prg.print( /* "|=:|>>" */ 1033)
  5769  
  5770  		default:
  5771  			prg.print( /* "kern" */ 1034)
  5772  		}
  5773  
  5774  	case specialCommand:
  5775  		if m == known {
  5776  			prg.print( /* "numspecial" */ 1059)
  5777  		} else {
  5778  			prg.print( /* "special" */ 1058)
  5779  		}
  5780  
  5781  	default:
  5782  		prg.print( /* "[unknown command code!]" */ 602)
  5783  	}
  5784  }
  5785  
  5786  func (prg *prg) showMacro(p halfword, q, l int32) {
  5787  	var (
  5788  		r1 halfword // temporary storage
  5789  	)
  5790  	p = *(*prg.mem[p].hh()).rh() // bypass the reference count
  5791  	for int32(*(*prg.mem[p].hh()).lh()) > textMacro {
  5792  		r1 = *(*prg.mem[p].hh()).rh()
  5793  		*(*prg.mem[p].hh()).rh() = uint16(memMin)
  5794  		prg.showTokenList(int32(p), memMin, l, 0)
  5795  		*(*prg.mem[p].hh()).rh() = r1
  5796  		p = r1
  5797  		if l > 0 {
  5798  			l = l - prg.tally
  5799  		} else {
  5800  			goto exit
  5801  		}
  5802  	} // control printing of `\.[ETC.]'
  5803  	// \xref[ETC]
  5804  	prg.tally = 0
  5805  	switch *(*prg.mem[p].hh()).lh() {
  5806  	case generalMacro:
  5807  		prg.print( /* "->" */ 501)
  5808  	// \xref[->]
  5809  	case primaryMacro, secondaryMacro, tertiaryMacro:
  5810  		prg.printChar(asciiCode('<'))
  5811  		prg.printCmdMod(paramType, int32(*(*prg.mem[p].hh()).lh()))
  5812  		prg.print( /* ">->" */ 502)
  5813  
  5814  	case exprMacro:
  5815  		prg.print( /* "<expr>->" */ 503)
  5816  	case ofMacro:
  5817  		prg.print( /* "<expr>of<primary>->" */ 504)
  5818  	case suffixMacro:
  5819  		prg.print( /* "<suffix>->" */ 505)
  5820  	case textMacro:
  5821  		prg.print( /* "<text>->" */ 506)
  5822  	} // there are no other cases
  5823  	prg.showTokenList(int32(*(*prg.mem[p].hh()).rh()), q, l-prg.tally, 0)
  5824  
  5825  exit:
  5826  }
  5827  
  5828  // 228. \[15] Data structures for variables
  5829  
  5830  // tangle:pos ../../mf.web:5001:40:
  5831  
  5832  // The variables of \MF\ programs can be simple, like `\.x', or they can
  5833  // combine the structural properties of arrays and records, like `\.[x20a.b]'.
  5834  // A \MF\ user assigns a type to a variable like \.[x20a.b] by saying, for
  5835  // example, `\.[boolean] \.[x[]a.b]'. It's time for us to study how such
  5836  // things are represented inside of the computer.
  5837  //
  5838  // Each variable value occupies two consecutive words, either in a two-word
  5839  // node called a value node, or as a two-word subfield of a larger node.  One
  5840  // of those two words is called the |value| field; it is an integer,
  5841  // containing either a |scaled| numeric value or the representation of some
  5842  // other type of quantity. (It might also be subdivided into halfwords, in
  5843  // which case it is referred to by other names instead of |value|.) The other
  5844  // word is broken into subfields called |type|, |name_type|, and |link|.  The
  5845  // |type| field is a quarterword that specifies the variable's type, and
  5846  // |name_type| is a quarterword from which \MF\ can reconstruct the
  5847  // variable's name (sometimes by using the |link| field as well).  Thus, only
  5848  // 1.25 words are actually devoted to the value itself; the other
  5849  // three-quarters of a word are overhead, but they aren't wasted because they
  5850  // allow \MF\ to deal with sparse arrays and to provide meaningful diagnostics.
  5851  //
  5852  // In this section we shall be concerned only with the structural aspects of
  5853  // variables, not their values. Later parts of the program will change the
  5854  // |type| and |value| fields, but we shall treat those fields as black boxes
  5855  // whose contents should not be touched.
  5856  //
  5857  // However, if the |type| field is |structured|, there is no |value| field,
  5858  // and the second word is broken into two pointer fields called |attr_head|
  5859  // and |subscr_head|. Those fields point to additional nodes that
  5860  // contain structural information, as we shall see.
  5861  
  5862  // 232.
  5863  
  5864  // tangle:pos ../../mf.web:5177:3:
  5865  
  5866  // If |type(p)=pair_type| or |transform_type| and if |value(p)=null|, the
  5867  // procedure call |init_big_node(p)| will allocate a pair or transform node
  5868  // for~|p|.  The individual parts of such nodes are initially of type
  5869  // |independent|.
  5870  func (prg *prg) initBigNode(p halfword) {
  5871  	var (
  5872  		q halfword    // the new node
  5873  		s smallNumber // its size
  5874  	)
  5875  	s = prg.bigNodeSize[*(*prg.mem[p].hh()).b0()-13]
  5876  	q = prg.getNode(int32(s))
  5877  	for {
  5878  		s = byte(int32(s) - 2)
  5879  		/* Make variable |q+s| newly independent  */ {
  5880  			if prg.serialNo > 017777777777-sScale {
  5881  				prg.overflow(strNumber( /* "independent variables" */ 587), prg.serialNo/sScale)
  5882  			} /* \xref[METAFONT capacity exceeded independent variables][\quad independent variables]  */
  5883  			*(*prg.mem[int32(q)+int32(s)].hh()).b0() = byte(independent)
  5884  			prg.serialNo = prg.serialNo + sScale
  5885  			*prg.mem[int32(q)+int32(s)+1].int() = prg.serialNo
  5886  		}
  5887  		*(*prg.mem[int32(q)+int32(s)].hh()).b1() = byte(int32(s)/2 + xPartSector)
  5888  		*(*prg.mem[int32(q)+int32(s)].hh()).rh() = uint16(memMin)
  5889  		if int32(s) == 0 {
  5890  			break
  5891  		}
  5892  	}
  5893  	*(*prg.mem[q].hh()).rh() = p
  5894  	*prg.mem[int32(p)+1].int() = int32(q)
  5895  }
  5896  
  5897  // 233.
  5898  
  5899  // tangle:pos ../../mf.web:5192:3:
  5900  
  5901  // The |id_transform| function creates a capsule for the
  5902  // identity transformation.
  5903  func (prg *prg) idTransform() (r halfword) {
  5904  	var (
  5905  		p, q, r1 halfword // list manipulation registers
  5906  	)
  5907  	p = prg.getNode(valueNodeSize)
  5908  	*(*prg.mem[p].hh()).b0() = byte(transformType)
  5909  	*(*prg.mem[p].hh()).b1() = byte(capsule)
  5910  	*prg.mem[int32(p)+1].int() = memMin
  5911  	prg.initBigNode(p)
  5912  	q = uint16(*prg.mem[int32(p)+1].int())
  5913  	r1 = uint16(int32(q) + transformNodeSize)
  5914  	for {
  5915  		r1 = uint16(int32(r1) - 2)
  5916  		*(*prg.mem[r1].hh()).b0() = byte(known)
  5917  		*prg.mem[int32(r1)+1].int() = 0
  5918  		if int32(r1) == int32(q) {
  5919  			break
  5920  		}
  5921  	}
  5922  	*prg.mem[int32(q)+4+1].int() = 0200000
  5923  	*prg.mem[int32(q)+10+1].int() = 0200000
  5924  	r = p
  5925  	return r
  5926  }
  5927  
  5928  // 234.
  5929  
  5930  // tangle:pos ../../mf.web:5207:3:
  5931  
  5932  // Tokens are of type |tag_token| when they first appear, but they point
  5933  // to |null| until they are first used as the root of a variable.
  5934  // The following subroutine establishes the root node on such grand occasions.
  5935  func (prg *prg) newRoot(x halfword) {
  5936  	var (
  5937  		p halfword // the new node
  5938  	)
  5939  	p = prg.getNode(valueNodeSize)
  5940  	*(*prg.mem[p].hh()).b0() = byte(undefined)
  5941  	*(*prg.mem[p].hh()).b1() = byte(root)
  5942  	*(*prg.mem[p].hh()).rh() = x
  5943  	*prg.eqtb[x-1].rh() = p
  5944  }
  5945  
  5946  // 235.
  5947  
  5948  // tangle:pos ../../mf.web:5217:3:
  5949  
  5950  // These conventions for variable representation are illustrated by the
  5951  // |print_variable_name| routine, which displays the full name of a
  5952  // variable given only a pointer to its two-word value packet.
  5953  func (prg *prg) printVariableName(p halfword) {
  5954  	var (
  5955  		q  halfword // a token list that will name the variable's suffix
  5956  		r1 halfword // temporary for token list creation
  5957  	)
  5958  	for int32(*(*prg.mem[p].hh()).b1()) >= xPartSector {
  5959  
  5960  		// Preface the output with a part specifier; |return| in the case of a capsule
  5961  		switch *(*prg.mem[p].hh()).b1() {
  5962  		case xPartSector:
  5963  			prg.printChar(asciiCode('x'))
  5964  		case yPartSector:
  5965  			prg.printChar(asciiCode('y'))
  5966  		case xxPartSector:
  5967  			prg.print( /* "xx" */ 509)
  5968  		case xyPartSector:
  5969  			prg.print( /* "xy" */ 510)
  5970  		case yxPartSector:
  5971  			prg.print( /* "yx" */ 511)
  5972  		case yyPartSector:
  5973  			prg.print( /* "yy" */ 512)
  5974  		case capsule:
  5975  			prg.print( /* "%CAPSULE" */ 513)
  5976  			prg.printInt(int32(p) - memMin)
  5977  			goto exit
  5978  			// \xref[CAPSULE]
  5979  
  5980  		} // there are no other cases
  5981  		prg.print( /* "part " */ 514)
  5982  		p = *(*prg.mem[int32(p)-2*(int32(*(*prg.mem[p].hh()).b1())-xPartSector)].hh()).rh()
  5983  	}
  5984  	q = uint16(memMin)
  5985  	for int32(*(*prg.mem[p].hh()).b1()) > savedRoot {
  5986  
  5987  		// Ascend one level, pushing a token onto list |q| and replacing |p| by its parent
  5988  		if int32(*(*prg.mem[p].hh()).b1()) == subscr {
  5989  			r1 = prg.newNumTok(*prg.mem[int32(p)+2].int())
  5990  			for {
  5991  				p = *(*prg.mem[p].hh()).rh()
  5992  				if int32(*(*prg.mem[p].hh()).b1()) == attr {
  5993  					break
  5994  				}
  5995  			}
  5996  		} else if int32(*(*prg.mem[p].hh()).b1()) == structuredRoot {
  5997  			p = *(*prg.mem[p].hh()).rh()
  5998  			goto found
  5999  		} else {
  6000  			if int32(*(*prg.mem[p].hh()).b1()) != attr {
  6001  				prg.confusion(strNumber( /* "var" */ 508))
  6002  			}
  6003  			// \xref[this can't happen var][\quad var]
  6004  			r1 = prg.getAvail()
  6005  			*(*prg.mem[r1].hh()).lh() = *(*prg.mem[int32(p)+2].hh()).lh()
  6006  		}
  6007  		*(*prg.mem[r1].hh()).rh() = q
  6008  		q = r1
  6009  
  6010  	found:
  6011  		p = *(*prg.mem[int32(p)+2].hh()).rh()
  6012  	}
  6013  	r1 = prg.getAvail()
  6014  	*(*prg.mem[r1].hh()).lh() = *(*prg.mem[p].hh()).rh()
  6015  	*(*prg.mem[r1].hh()).rh() = q
  6016  	if int32(*(*prg.mem[p].hh()).b1()) == savedRoot {
  6017  		prg.print( /* "(SAVED)" */ 507)
  6018  	}
  6019  	// \xref[SAVED]
  6020  	prg.showTokenList(int32(r1), memMin, 017777777777, prg.tally)
  6021  	prg.flushTokenList(r1)
  6022  
  6023  exit:
  6024  }
  6025  
  6026  // 238.
  6027  
  6028  // tangle:pos ../../mf.web:5270:3:
  6029  
  6030  // The |interesting| function returns |true| if a given variable is not
  6031  // in a capsule, or if the user wants to trace capsules.
  6032  func (prg *prg) interesting(p halfword) (r bool) {
  6033  	var (
  6034  		t smallNumber // a |name_type|
  6035  	)
  6036  	if prg.internal[tracingCapsules-1] > 0 {
  6037  		r = true
  6038  	} else {
  6039  		t = *(*prg.mem[p].hh()).b1()
  6040  		if int32(t) >= xPartSector {
  6041  			if int32(t) != capsule {
  6042  				t = *(*prg.mem[*(*prg.mem[int32(p)-2*(int32(t)-xPartSector)].hh()).rh()].hh()).b1()
  6043  			}
  6044  		}
  6045  		r = int32(t) != capsule
  6046  	}
  6047  	return r
  6048  }
  6049  
  6050  // 239.
  6051  
  6052  // tangle:pos ../../mf.web:5283:3:
  6053  
  6054  // Now here is a subroutine that converts an unstructured type into an
  6055  // equivalent structured type, by inserting a |structured| node that is
  6056  // capable of growing. This operation is done only when |name_type(p)=root|,
  6057  // |subscr|, or |attr|.
  6058  //
  6059  // The procedure returns a pointer to the new node that has taken node~|p|'s
  6060  // place in the structure. Node~|p| itself does not move, nor are its
  6061  // |value| or |type| fields changed in any way.
  6062  func (prg *prg) newStructure(p halfword) (r halfword) {
  6063  	var (
  6064  		q, r1 halfword // list manipulation registers
  6065  	)
  6066  	switch *(*prg.mem[p].hh()).b1() {
  6067  	case root:
  6068  		q = *(*prg.mem[p].hh()).rh()
  6069  		r1 = prg.getNode(valueNodeSize)
  6070  		*prg.eqtb[q-1].rh() = r1
  6071  
  6072  	case subscr:
  6073  		// Link a new subscript node |r| in place of node |p|
  6074  		q = p
  6075  		for {
  6076  			q = *(*prg.mem[q].hh()).rh()
  6077  			if int32(*(*prg.mem[q].hh()).b1()) == attr {
  6078  				break
  6079  			}
  6080  		}
  6081  		q = *(*prg.mem[int32(q)+2].hh()).rh()
  6082  		r1 = uint16(int32(q) + 1) // |link(r)=subscr_head(q)|
  6083  		for {
  6084  			q = r1
  6085  			r1 = *(*prg.mem[r1].hh()).rh()
  6086  			if int32(r1) == int32(p) {
  6087  				break
  6088  			}
  6089  		}
  6090  		r1 = prg.getNode(subscrNodeSize)
  6091  		*(*prg.mem[q].hh()).rh() = r1
  6092  		*prg.mem[int32(r1)+2].int() = *prg.mem[int32(p)+2].int()
  6093  
  6094  	case attr:
  6095  		// Link a new attribute node |r| in place of node |p|
  6096  		q = *(*prg.mem[int32(p)+2].hh()).rh()
  6097  		r1 = *(*prg.mem[int32(q)+1].hh()).lh()
  6098  		for {
  6099  			q = r1
  6100  			r1 = *(*prg.mem[r1].hh()).rh()
  6101  			if int32(r1) == int32(p) {
  6102  				break
  6103  			}
  6104  		}
  6105  		r1 = prg.getNode(attrNodeSize)
  6106  		*(*prg.mem[q].hh()).rh() = r1
  6107  
  6108  		prg.mem[int32(r1)+2] = prg.mem[int32(p)+2] // copy |attr_loc| and |parent|
  6109  		if int32(*(*prg.mem[int32(p)+2].hh()).lh()) == collectiveSubscript {
  6110  			q = uint16(int32(*(*prg.mem[int32(p)+2].hh()).rh()) + 1)
  6111  			for int32(*(*prg.mem[q].hh()).rh()) != int32(p) {
  6112  				q = *(*prg.mem[q].hh()).rh()
  6113  			}
  6114  			*(*prg.mem[q].hh()).rh() = r1
  6115  		}
  6116  
  6117  	default:
  6118  		prg.confusion(strNumber( /* "struct" */ 515))
  6119  		// \xref[this can't happen struct][\quad struct]
  6120  	}
  6121  
  6122  	*(*prg.mem[r1].hh()).rh() = *(*prg.mem[p].hh()).rh()
  6123  	*(*prg.mem[r1].hh()).b0() = byte(structured)
  6124  	*(*prg.mem[r1].hh()).b1() = *(*prg.mem[p].hh()).b1()
  6125  	*(*prg.mem[int32(r1)+1].hh()).lh() = p
  6126  	*(*prg.mem[p].hh()).b1() = byte(structuredRoot)
  6127  
  6128  	q = prg.getNode(attrNodeSize)
  6129  	*(*prg.mem[p].hh()).rh() = q
  6130  	*(*prg.mem[int32(r1)+1].hh()).rh() = q
  6131  	*(*prg.mem[int32(q)+2].hh()).rh() = r1
  6132  	*(*prg.mem[q].hh()).b0() = byte(undefined)
  6133  	*(*prg.mem[q].hh()).b1() = byte(attr)
  6134  	*(*prg.mem[q].hh()).rh() = uint16(memMin + 3 + 10 + 2 + 2)
  6135  	*(*prg.mem[int32(q)+2].hh()).lh() = uint16(collectiveSubscript)
  6136  	r = r1
  6137  	return r
  6138  }
  6139  
  6140  // 242.
  6141  
  6142  // tangle:pos ../../mf.web:5336:3:
  6143  
  6144  // The |find_variable| routine is given a pointer~|t| to a nonempty token
  6145  // list of suffixes; it returns a pointer to the corresponding two-word
  6146  // value. For example, if |t| points to token \.x followed by a numeric
  6147  // token containing the value~7, |find_variable| finds where the value of
  6148  // \.[x7] is stored in memory. This may seem a simple task, and it
  6149  // usually is, except when \.[x7] has never been referenced before.
  6150  // Indeed, \.x may never have even been subscripted before; complexities
  6151  // arise with respect to updating the collective subscript information.
  6152  //
  6153  // If a macro type is detected anywhere along path~|t|, or if the first
  6154  // item on |t| isn't a |tag_token|, the value |null| is returned.
  6155  // Otherwise |p| will be a non-null pointer to a node such that
  6156  // |undefined<type(p)<structured|.
  6157  func (prg *prg) findVariable(t halfword) (r halfword) {
  6158  	var (
  6159  		p, q, r1, s    halfword   // nodes in the ``value'' line
  6160  		pp, qq, rr, ss halfword   // nodes in the ``collective'' line
  6161  		n              int32      // subscript or attribute
  6162  		saveWord       memoryWord // temporary storage for a word of |mem|
  6163  	// \xref[inner loop]
  6164  	)
  6165  	p = *(*prg.mem[t].hh()).lh()
  6166  	t = *(*prg.mem[t].hh()).rh()
  6167  	if int32(*prg.eqtb[p-1].lh())%outerTag != tagToken {
  6168  		r = uint16(memMin)
  6169  		goto exit
  6170  	}
  6171  	if int32(*prg.eqtb[p-1].rh()) == memMin {
  6172  		prg.newRoot(p)
  6173  	}
  6174  	p = *prg.eqtb[p-1].rh()
  6175  	pp = p
  6176  	for int32(t) != memMin {
  6177  		if int32(*(*prg.mem[pp].hh()).b0()) != structured {
  6178  			if int32(*(*prg.mem[pp].hh()).b0()) > structured {
  6179  				r = uint16(memMin)
  6180  				goto exit
  6181  			}
  6182  			ss = prg.newStructure(pp)
  6183  			if int32(p) == int32(pp) {
  6184  				p = ss
  6185  			}
  6186  			pp = ss
  6187  		} // now |type(pp)=structured|
  6188  		if int32(*(*prg.mem[p].hh()).b0()) != structured {
  6189  			p = prg.newStructure(p)
  6190  		}
  6191  		if int32(t) < int32(prg.hiMemMin) {
  6192  			n = *prg.mem[int32(t)+1].int()
  6193  			pp = *(*prg.mem[*(*prg.mem[int32(pp)+1].hh()).lh()].hh()).rh() // now |attr_loc(pp)=collective_subscript|
  6194  			q = *(*prg.mem[*(*prg.mem[int32(p)+1].hh()).lh()].hh()).rh()
  6195  			saveWord = prg.mem[int32(q)+2]
  6196  			*prg.mem[int32(q)+2].int() = 017777777777
  6197  			s = uint16(int32(p) + 1) // |link(s)=subscr_head(p)|
  6198  			for {
  6199  				r1 = s
  6200  				s = *(*prg.mem[s].hh()).rh()
  6201  				if n <= *prg.mem[int32(s)+2].int() {
  6202  					break
  6203  				}
  6204  			}
  6205  			if n == *prg.mem[int32(s)+2].int() {
  6206  				p = s
  6207  			} else {
  6208  				p = prg.getNode(subscrNodeSize)
  6209  				*(*prg.mem[r1].hh()).rh() = p
  6210  				*(*prg.mem[p].hh()).rh() = s
  6211  				*prg.mem[int32(p)+2].int() = n
  6212  				*(*prg.mem[p].hh()).b1() = byte(subscr)
  6213  				*(*prg.mem[p].hh()).b0() = byte(undefined)
  6214  			}
  6215  			prg.mem[int32(q)+2] = saveWord
  6216  		} else {
  6217  			// Descend one level for the attribute |info(t)|
  6218  			n = int32(*(*prg.mem[t].hh()).lh())
  6219  			ss = *(*prg.mem[int32(pp)+1].hh()).lh()
  6220  			for {
  6221  				rr = ss
  6222  				ss = *(*prg.mem[ss].hh()).rh()
  6223  				if n <= int32(*(*prg.mem[int32(ss)+2].hh()).lh()) {
  6224  					break
  6225  				}
  6226  			}
  6227  			if n < int32(*(*prg.mem[int32(ss)+2].hh()).lh()) {
  6228  				qq = prg.getNode(attrNodeSize)
  6229  				*(*prg.mem[rr].hh()).rh() = qq
  6230  				*(*prg.mem[qq].hh()).rh() = ss
  6231  				*(*prg.mem[int32(qq)+2].hh()).lh() = uint16(n)
  6232  				*(*prg.mem[qq].hh()).b1() = byte(attr)
  6233  				*(*prg.mem[qq].hh()).b0() = byte(undefined)
  6234  				*(*prg.mem[int32(qq)+2].hh()).rh() = pp
  6235  				ss = qq
  6236  			}
  6237  			if int32(p) == int32(pp) {
  6238  				p = ss
  6239  				pp = ss
  6240  			} else {
  6241  				pp = ss
  6242  				s = *(*prg.mem[int32(p)+1].hh()).lh()
  6243  				for {
  6244  					r1 = s
  6245  					s = *(*prg.mem[s].hh()).rh()
  6246  					if n <= int32(*(*prg.mem[int32(s)+2].hh()).lh()) {
  6247  						break
  6248  					}
  6249  				}
  6250  				if n == int32(*(*prg.mem[int32(s)+2].hh()).lh()) {
  6251  					p = s
  6252  				} else {
  6253  					q = prg.getNode(attrNodeSize)
  6254  					*(*prg.mem[r1].hh()).rh() = q
  6255  					*(*prg.mem[q].hh()).rh() = s
  6256  					*(*prg.mem[int32(q)+2].hh()).lh() = uint16(n)
  6257  					*(*prg.mem[q].hh()).b1() = byte(attr)
  6258  					*(*prg.mem[q].hh()).b0() = byte(undefined)
  6259  					*(*prg.mem[int32(q)+2].hh()).rh() = p
  6260  					p = q
  6261  				}
  6262  			}
  6263  		}
  6264  		t = *(*prg.mem[t].hh()).rh()
  6265  	}
  6266  	if int32(*(*prg.mem[pp].hh()).b0()) >= structured {
  6267  		if int32(*(*prg.mem[pp].hh()).b0()) == structured {
  6268  			pp = *(*prg.mem[int32(pp)+1].hh()).lh()
  6269  		} else {
  6270  			r = uint16(memMin)
  6271  			goto exit
  6272  		}
  6273  	}
  6274  	if int32(*(*prg.mem[p].hh()).b0()) == structured {
  6275  		p = *(*prg.mem[int32(p)+1].hh()).lh()
  6276  	}
  6277  	if int32(*(*prg.mem[p].hh()).b0()) == undefined {
  6278  		if int32(*(*prg.mem[pp].hh()).b0()) == undefined {
  6279  			*(*prg.mem[pp].hh()).b0() = byte(numericType)
  6280  			*prg.mem[int32(pp)+1].int() = memMin
  6281  		}
  6282  		*(*prg.mem[p].hh()).b0() = *(*prg.mem[pp].hh()).b0()
  6283  		*prg.mem[int32(p)+1].int() = memMin
  6284  	}
  6285  	r = p
  6286  
  6287  exit:
  6288  	;
  6289  	return r
  6290  }
  6291  
  6292  // 246.
  6293  
  6294  // tangle:pos ../../mf.web:5440:3:
  6295  
  6296  // Variables lose their former values when they appear in a type declaration,
  6297  // or when they are defined to be macros or \&[let] equal to something else.
  6298  // A subroutine will be defined later that recycles the storage associated
  6299  // with any particular |type| or |value|; our goal now is to study a higher
  6300  // level process called |flush_variable|, which selectively frees parts of a
  6301  // variable structure.
  6302  //
  6303  // This routine has some complexity because of examples such as
  6304  // `\hbox[\tt numeric x[]a[]b]',
  6305  // which recycles all variables of the form \.[x[i]a[j]b] (and no others), while
  6306  // `\hbox[\tt vardef x[]a[]=...]'
  6307  // discards all variables of the form \.[x[i]a[j]] followed by an arbitrary
  6308  // suffix, except for the collective node \.[x[]a[]] itself. The obvious way
  6309  // to handle such examples is to use recursion; so that's what we~do.
  6310  // \xref[recursion]
  6311  //
  6312  // Parameter |p| points to the root information of the variable;
  6313  // parameter |t| points to a list of one-word nodes that represent
  6314  // suffixes, with |info=collective_subscript| for subscripts.
  6315  // \4
  6316  // Declare subroutines for printing expressions
  6317  func (prg *prg) printPath(h halfword, s strNumber, nuline bool) {
  6318  	var (
  6319  		p, q halfword // for list traversal
  6320  	)
  6321  	prg.printDiagnostic(strNumber( /* "Path" */ 517), s, nuline)
  6322  	prg.printLn()
  6323  	// \xref[Path at line...]
  6324  	p = h
  6325  	for {
  6326  		q = *(*prg.mem[p].hh()).rh()
  6327  		if int32(p) == memMin || int32(q) == memMin {
  6328  			prg.printNl(strNumber( /* "???" */ 259))
  6329  			goto done // this won't happen
  6330  			// \xref[???]
  6331  		}
  6332  
  6333  		// Print information for adjacent knots |p| and |q|
  6334  		prg.printTwo(*prg.mem[int32(p)+1].int(), *prg.mem[int32(p)+2].int())
  6335  		switch *(*prg.mem[p].hh()).b1() {
  6336  		case endpoint:
  6337  			if int32(*(*prg.mem[p].hh()).b0()) == open {
  6338  				prg.print( /* "[open?]" */ 518)
  6339  			} // can't happen
  6340  			// \xref[open?]
  6341  			if int32(*(*prg.mem[q].hh()).b0()) != endpoint || int32(q) != int32(h) {
  6342  				q = uint16(memMin)
  6343  			} // force an error
  6344  			// force an error
  6345  			goto done1
  6346  
  6347  		case explicit:
  6348  			// Print control points between |p| and |q|, then |goto done1|
  6349  			prg.print( /* "..controls " */ 524)
  6350  			prg.printTwo(*prg.mem[int32(p)+5].int(), *prg.mem[int32(p)+6].int())
  6351  			prg.print( /* " and " */ 523)
  6352  			if int32(*(*prg.mem[q].hh()).b0()) != explicit {
  6353  				prg.print( /* "??" */ 525)
  6354  			} else {
  6355  				prg.printTwo(*prg.mem[int32(q)+3].int(), *prg.mem[int32(q)+4].int())
  6356  			}
  6357  
  6358  			goto done1
  6359  
  6360  		case open:
  6361  			// Print information for a curve that begins |open|
  6362  			if int32(*(*prg.mem[p].hh()).b0()) != explicit && int32(*(*prg.mem[p].hh()).b0()) != open {
  6363  				prg.print( /* "[open?]" */ 518)
  6364  			} // can't happen
  6365  		// \xref[open?]
  6366  
  6367  		case curl, given:
  6368  			// Print information for a curve that begins |curl| or |given|
  6369  			if int32(*(*prg.mem[p].hh()).b0()) == open {
  6370  				prg.print( /* "??" */ 525)
  6371  			} // can't happen
  6372  			// \xref[??]
  6373  			if int32(*(*prg.mem[p].hh()).b1()) == curl {
  6374  				prg.print( /* "[curl " */ 521)
  6375  				prg.printScaled(*prg.mem[int32(p)+5].int())
  6376  			} else {
  6377  				prg.nSinCos(*prg.mem[int32(p)+5].int())
  6378  				prg.printChar(asciiCode('{'))
  6379  				prg.printScaled(prg.nCos)
  6380  				prg.printChar(asciiCode(','))
  6381  				prg.printScaled(prg.nSin)
  6382  			}
  6383  			prg.printChar(asciiCode('}'))
  6384  
  6385  		default:
  6386  			prg.print( /* "???" */ 259) // can't happen
  6387  			// \xref[???]
  6388  		}
  6389  
  6390  		if int32(*(*prg.mem[q].hh()).b0()) <= explicit {
  6391  			prg.print( /* "..control?" */ 519)
  6392  		} else if *prg.mem[int32(p)+6].int() != 0200000 || *prg.mem[int32(q)+4].int() != 0200000 {
  6393  			prg.print( /* "..tension " */ 522)
  6394  			if *prg.mem[int32(p)+6].int() < 0 {
  6395  				prg.print( /* "atleast" */ 464)
  6396  			}
  6397  			prg.printScaled(abs(*prg.mem[int32(p)+6].int()))
  6398  			if *prg.mem[int32(p)+6].int() != *prg.mem[int32(q)+4].int() {
  6399  				prg.print( /* " and " */ 523)
  6400  				if *prg.mem[int32(q)+4].int() < 0 {
  6401  					prg.print( /* "atleast" */ 464)
  6402  				}
  6403  				prg.printScaled(abs(*prg.mem[int32(q)+4].int()))
  6404  			}
  6405  		}
  6406  
  6407  	done1:
  6408  		;
  6409  		p = q
  6410  		if int32(p) != int32(h) || int32(*(*prg.mem[h].hh()).b0()) != endpoint {
  6411  			prg.printNl(strNumber( /* " .." */ 520))
  6412  			if int32(*(*prg.mem[p].hh()).b0()) == given {
  6413  				prg.nSinCos(*prg.mem[int32(p)+3].int())
  6414  				prg.printChar(asciiCode('{'))
  6415  				prg.printScaled(prg.nCos)
  6416  				prg.printChar(asciiCode(','))
  6417  				prg.printScaled(prg.nSin)
  6418  				prg.printChar(asciiCode('}'))
  6419  			} else if int32(*(*prg.mem[p].hh()).b0()) == curl {
  6420  				prg.print( /* "[curl " */ 521)
  6421  				prg.printScaled(*prg.mem[int32(p)+3].int())
  6422  				prg.printChar(asciiCode('}'))
  6423  			}
  6424  		}
  6425  		if int32(p) == int32(h) {
  6426  			break
  6427  		}
  6428  	}
  6429  	if int32(*(*prg.mem[h].hh()).b0()) != endpoint {
  6430  		prg.print( /* "cycle" */ 386)
  6431  	}
  6432  
  6433  done:
  6434  	prg.endDiagnostic(true)
  6435  }
  6436  
  6437  // \4
  6438  // Declare the procedure called |print_weight|
  6439  func (prg *prg) printWeight(q halfword, xOff int32) {
  6440  	var (
  6441  		w, m int32 // unpacked weight and coordinate
  6442  		d    int32 // temporary data register
  6443  	)
  6444  	d = int32(*(*prg.mem[q].hh()).lh()) - 0
  6445  	w = d % 8
  6446  	m = d/8 - int32(*(*prg.mem[int32(prg.curEdges)+3].hh()).lh())
  6447  	if int32(prg.fileOffset) > maxPrintLine-9 {
  6448  		prg.printNl(strNumber(' '))
  6449  	} else {
  6450  		prg.printChar(asciiCode(' '))
  6451  	}
  6452  	prg.printInt(m + xOff)
  6453  	for w > zeroW {
  6454  		prg.printChar(asciiCode('+'))
  6455  		w = w - 1
  6456  	}
  6457  	for w < zeroW {
  6458  		prg.printChar(asciiCode('-'))
  6459  		w = w + 1
  6460  	}
  6461  }
  6462  
  6463  func (prg *prg) printEdges(s strNumber, nuline bool, xOff, yOff int32) {
  6464  	var (
  6465  		p, q, r1 halfword // for list traversal
  6466  		n        int32    // row number
  6467  	)
  6468  	prg.printDiagnostic(strNumber( /* "Edge structure" */ 532), s, nuline)
  6469  	p = *(*prg.mem[prg.curEdges].hh()).lh()
  6470  	n = int32(*(*prg.mem[int32(prg.curEdges)+1].hh()).rh()) - zeroField
  6471  	for int32(p) != int32(prg.curEdges) {
  6472  		q = *(*prg.mem[int32(p)+1].hh()).lh()
  6473  		r1 = *(*prg.mem[int32(p)+1].hh()).rh()
  6474  		if int32(q) > memMin+1 || int32(r1) != 3000 {
  6475  			prg.printNl(strNumber( /* "row " */ 533))
  6476  			prg.printInt(n + yOff)
  6477  			prg.printChar(asciiCode(':'))
  6478  			for int32(q) > memMin+1 {
  6479  				prg.printWeight(q, xOff)
  6480  				q = *(*prg.mem[q].hh()).rh()
  6481  			}
  6482  			prg.print( /* " |" */ 534)
  6483  			for int32(r1) != 3000 {
  6484  				prg.printWeight(r1, xOff)
  6485  				r1 = *(*prg.mem[r1].hh()).rh()
  6486  			}
  6487  		}
  6488  		p = *(*prg.mem[p].hh()).lh()
  6489  		n = n - 1
  6490  	}
  6491  	prg.endDiagnostic(true)
  6492  }
  6493  
  6494  func (prg *prg) unskew(x, y scaled, octant smallNumber) {
  6495  	switch octant {
  6496  	case firstOctant:
  6497  		prg.curX = x + y
  6498  		prg.curY = y
  6499  	case secondOctant:
  6500  		prg.curX = y
  6501  		prg.curY = x + y
  6502  	case thirdOctant:
  6503  		prg.curX = -y
  6504  		prg.curY = x + y
  6505  	case fourthOctant:
  6506  		prg.curX = -x - y
  6507  		prg.curY = y
  6508  	case fifthOctant:
  6509  		prg.curX = -x - y
  6510  		prg.curY = -y
  6511  	case sixthOctant:
  6512  		prg.curX = -y
  6513  		prg.curY = -x - y
  6514  	case seventhOctant:
  6515  		prg.curX = y
  6516  		prg.curY = -x - y
  6517  	case eighthOctant:
  6518  		prg.curX = x + y
  6519  		prg.curY = -y
  6520  	} // there are no other cases
  6521  }
  6522  
  6523  func (prg *prg) printPen(p halfword, s strNumber, nuline bool) {
  6524  	var (
  6525  		nothingPrinted   bool     // has there been any action yet?
  6526  		k/* 1..8 */ byte          // octant number
  6527  		h                halfword // offset list head
  6528  		m, n             int32    // offset indices
  6529  		w, ww            halfword // pointers that traverse the offset list
  6530  	)
  6531  	prg.printDiagnostic(strNumber( /* "Pen polygon" */ 569), s, nuline)
  6532  	nothingPrinted = true
  6533  	prg.printLn()
  6534  	for ii := int32(1); ii <= 8; ii++ {
  6535  		k = byte(ii)
  6536  		_ = k
  6537  		prg.octant = prg.octantCode[k-1]
  6538  		h = uint16(int32(p) + int32(prg.octant))
  6539  		n = int32(*(*prg.mem[h].hh()).lh())
  6540  		w = *(*prg.mem[h].hh()).rh()
  6541  		if !(k&1 != 0) {
  6542  			w = *(*prg.mem[w].hh()).lh()
  6543  		} // in even octants, start at $w_[n+1]$
  6544  		for ii := int32(1); ii <= n+1; ii++ {
  6545  			m = ii
  6546  			_ = m
  6547  			if k&1 != 0 {
  6548  				ww = *(*prg.mem[w].hh()).rh()
  6549  			} else {
  6550  				ww = *(*prg.mem[w].hh()).lh()
  6551  			}
  6552  			if *prg.mem[int32(ww)+1].int() != *prg.mem[int32(w)+1].int() || *prg.mem[int32(ww)+2].int() != *prg.mem[int32(w)+2].int() {
  6553  				if nothingPrinted {
  6554  					nothingPrinted = false
  6555  				} else {
  6556  					prg.printNl(strNumber( /* " .. " */ 571))
  6557  				}
  6558  				prg.unskew(*prg.mem[int32(ww)+1].int(), *prg.mem[int32(ww)+2].int(), prg.octant)
  6559  				prg.printTwo(prg.curX, prg.curY)
  6560  			}
  6561  			w = ww
  6562  		}
  6563  	}
  6564  	if nothingPrinted {
  6565  		w = *(*prg.mem[int32(p)+firstOctant].hh()).rh()
  6566  		prg.printTwo(*prg.mem[int32(w)+1].int()+*prg.mem[int32(w)+2].int(), *prg.mem[int32(w)+2].int())
  6567  	}
  6568  	prg.printNl(strNumber( /* " .. cycle" */ 570))
  6569  	prg.endDiagnostic(true)
  6570  }
  6571  
  6572  func (prg *prg) printDependency(p halfword, t smallNumber) {
  6573  	var (
  6574  		v     int32    // a coefficient
  6575  		pp, q halfword // for list manipulation
  6576  	)
  6577  	pp = p
  6578  	for true {
  6579  		v = abs(*prg.mem[int32(p)+1].int())
  6580  		q = *(*prg.mem[p].hh()).lh()
  6581  		if int32(q) == memMin {
  6582  			if v != 0 || int32(p) == int32(pp) {
  6583  				if *prg.mem[int32(p)+1].int() > 0 {
  6584  					if int32(p) != int32(pp) {
  6585  						prg.printChar(asciiCode('+'))
  6586  					}
  6587  				}
  6588  				prg.printScaled(*prg.mem[int32(p)+1].int())
  6589  			}
  6590  
  6591  			goto exit
  6592  		}
  6593  
  6594  		// Print the coefficient, unless it's $\pm1.0$
  6595  		if *prg.mem[int32(p)+1].int() < 0 {
  6596  			prg.printChar(asciiCode('-'))
  6597  		} else if int32(p) != int32(pp) {
  6598  			prg.printChar(asciiCode('+'))
  6599  		}
  6600  		if int32(t) == dependent {
  6601  			v = prg.roundFraction(v)
  6602  		}
  6603  		if v != 0200000 {
  6604  			prg.printScaled(v)
  6605  		}
  6606  		if int32(*(*prg.mem[q].hh()).b0()) != independent {
  6607  			prg.confusion(strNumber( /* "dep" */ 588))
  6608  		}
  6609  		// \xref[this can't happen dep][\quad dep]
  6610  		prg.printVariableName(q)
  6611  		v = *prg.mem[int32(q)+1].int() % sScale
  6612  		for v > 0 {
  6613  			prg.print( /* "*4" */ 589)
  6614  			v = v - 2
  6615  		}
  6616  		p = *(*prg.mem[p].hh()).rh()
  6617  	}
  6618  
  6619  exit:
  6620  }
  6621  
  6622  // \4
  6623  // Declare the procedure called |print_dp|
  6624  func (prg *prg) printDp(t smallNumber, p halfword, verbosity smallNumber) {
  6625  	var (
  6626  		q halfword // the node following |p|
  6627  	)
  6628  	q = *(*prg.mem[p].hh()).rh()
  6629  	if int32(*(*prg.mem[q].hh()).lh()) == memMin || int32(verbosity) > 0 {
  6630  		prg.printDependency(p, t)
  6631  	} else {
  6632  		prg.print( /* "linearform" */ 764)
  6633  	}
  6634  	// \xref[linearform]
  6635  }
  6636  
  6637  // \4
  6638  // Declare the stashing/unstashing routines
  6639  func (prg *prg) stashCurExp() (r halfword) {
  6640  	var (
  6641  		p halfword // the capsule that will be returned
  6642  	)
  6643  	switch prg.curType {
  6644  	case unknownBoolean, unknownString, unknownPen, unknownPicture,
  6645  		unknownPath, transformType, pairType, dependent,
  6646  		protoDependent, independent:
  6647  		p = uint16(prg.curExp)
  6648  
  6649  	default:
  6650  		p = prg.getNode(valueNodeSize)
  6651  		*(*prg.mem[p].hh()).b1() = byte(capsule)
  6652  		*(*prg.mem[p].hh()).b0() = prg.curType
  6653  		*prg.mem[int32(p)+1].int() = prg.curExp
  6654  
  6655  	}
  6656  
  6657  	prg.curType = byte(vacuous)
  6658  	*(*prg.mem[p].hh()).rh() = uint16(memMin + 1)
  6659  	r = p
  6660  	return r
  6661  }
  6662  
  6663  func (prg *prg) unstashCurExp(p halfword) {
  6664  	prg.curType = *(*prg.mem[p].hh()).b0()
  6665  	switch prg.curType {
  6666  	case unknownBoolean, unknownString, unknownPen, unknownPicture,
  6667  		unknownPath, transformType, pairType, dependent,
  6668  		protoDependent, independent:
  6669  		prg.curExp = int32(p)
  6670  
  6671  	default:
  6672  		prg.curExp = *prg.mem[int32(p)+1].int()
  6673  		prg.freeNode(p, halfword(valueNodeSize))
  6674  
  6675  	}
  6676  
  6677  }
  6678  
  6679  func (prg *prg) printExp(p halfword, verbosity smallNumber) {
  6680  	var (
  6681  		restoreCurExp bool        // should |cur_exp| be restored?
  6682  		t             smallNumber // the type of the expression
  6683  		v             int32       // the value of the expression
  6684  		q             halfword    // a big node being displayed
  6685  	)
  6686  	if int32(p) != memMin {
  6687  		restoreCurExp = false
  6688  	} else {
  6689  		p = prg.stashCurExp()
  6690  		restoreCurExp = true
  6691  	}
  6692  	t = *(*prg.mem[p].hh()).b0()
  6693  	if int32(t) < dependent {
  6694  		v = *prg.mem[int32(p)+1].int()
  6695  	} else if int32(t) < independent {
  6696  		v = int32(*(*prg.mem[int32(p)+1].hh()).rh())
  6697  	}
  6698  
  6699  	// Print an abbreviated value of |v| with format depending on |t|
  6700  	switch t {
  6701  	case vacuous:
  6702  		prg.print( /* "vacuous" */ 324)
  6703  	case booleanType:
  6704  		if v == trueCode {
  6705  			prg.print( /* "true" */ 348)
  6706  		} else {
  6707  			prg.print( /* "false" */ 349)
  6708  		}
  6709  	case unknownBoolean, unknownString, unknownPen, unknownPicture,
  6710  		unknownPath, numericType:
  6711  		// Display a variable that's been declared but not defined
  6712  		prg.printType(t)
  6713  		if v != memMin {
  6714  			prg.printChar(asciiCode(' '))
  6715  			for int32(*(*prg.mem[v].hh()).b1()) == capsule && v != int32(p) {
  6716  				v = *prg.mem[v+1].int()
  6717  			}
  6718  			prg.printVariableName(halfword(v))
  6719  		}
  6720  
  6721  	case stringType:
  6722  		prg.printChar(asciiCode('"'))
  6723  		prg.slowPrint(v)
  6724  		prg.printChar(asciiCode('"'))
  6725  
  6726  	case penType, futurePen, pathType, pictureType:
  6727  		// Display a complex type
  6728  		if int32(verbosity) <= 1 {
  6729  			prg.printType(t)
  6730  		} else {
  6731  			if int32(prg.selector) == termAndLog {
  6732  				if prg.internal[tracingOnline-1] <= 0 {
  6733  					prg.selector = byte(termOnly)
  6734  					prg.printType(t)
  6735  					prg.print( /* " (see the transcript file)" */ 762)
  6736  					prg.selector = byte(termAndLog)
  6737  				}
  6738  			}
  6739  			switch t {
  6740  			case penType:
  6741  				prg.printPen(halfword(v), strNumber( /* "" */ 285), false)
  6742  			case futurePen:
  6743  				prg.printPath(halfword(v), strNumber( /* " (future pen)" */ 763), false)
  6744  			case pathType:
  6745  				prg.printPath(halfword(v), strNumber( /* "" */ 285), false)
  6746  			case pictureType:
  6747  				prg.curEdges = uint16(v)
  6748  				prg.printEdges(strNumber( /* "" */ 285), false, 0, 0)
  6749  
  6750  			} // there are no other cases
  6751  		}
  6752  
  6753  	case transformType, pairType:
  6754  		if v == memMin {
  6755  			prg.printType(t)
  6756  		} else {
  6757  			// Display a big node
  6758  			prg.printChar(asciiCode('('))
  6759  			q = uint16(v + int32(prg.bigNodeSize[t-13]))
  6760  			for {
  6761  				if int32(*(*prg.mem[v].hh()).b0()) == known {
  6762  					prg.printScaled(*prg.mem[v+1].int())
  6763  				} else if int32(*(*prg.mem[v].hh()).b0()) == independent {
  6764  					prg.printVariableName(halfword(v))
  6765  				} else {
  6766  					prg.printDp(*(*prg.mem[v].hh()).b0(), *(*prg.mem[v+1].hh()).rh(), verbosity)
  6767  				}
  6768  				v = v + 2
  6769  				if v != int32(q) {
  6770  					prg.printChar(asciiCode(','))
  6771  				}
  6772  				if v == int32(q) {
  6773  					break
  6774  				}
  6775  			}
  6776  			prg.printChar(asciiCode(')'))
  6777  		}
  6778  
  6779  	case known:
  6780  		prg.printScaled(v)
  6781  	case dependent, protoDependent:
  6782  		prg.printDp(t, halfword(v), verbosity)
  6783  	case independent:
  6784  		prg.printVariableName(p)
  6785  
  6786  	default:
  6787  		prg.confusion(strNumber( /* "exp" */ 761))
  6788  		// \xref[this can't happen exp][\quad exp]
  6789  	}
  6790  	if restoreCurExp {
  6791  		prg.unstashCurExp(p)
  6792  	}
  6793  }
  6794  
  6795  func (prg *prg) dispErr(p halfword, s strNumber) {
  6796  	if int32(prg.interaction) == errorStopMode {
  6797  	}
  6798  	prg.printNl(strNumber( /* ">> " */ 765))
  6799  	// \xref[>>]
  6800  	prg.printExp(p, smallNumber(1)) // ``medium verbose'' printing of the expression
  6801  	if int32(s) != 285 {
  6802  		prg.printNl(strNumber( /* "! " */ 261))
  6803  		prg.print(int32(s))
  6804  		// \xref[!\relax]
  6805  	}
  6806  }
  6807  
  6808  // \4
  6809  // Declare basic dependency-list subroutines
  6810  func (prg *prg) pPlusFq(p halfword, f int32, q halfword,
  6811  	t, tt smallNumber) (r halfword) {
  6812  	var (
  6813  		pp, qq    halfword // |info(p)| and |info(q)|, respectively
  6814  		r1, s     halfword // for list manipulation
  6815  		threshold int32    // defines a neighborhood of zero
  6816  		v         int32    // temporary register
  6817  	)
  6818  	if int32(t) == dependent {
  6819  		threshold = fractionThreshold
  6820  	} else {
  6821  		threshold = scaledThreshold
  6822  	}
  6823  	r1 = uint16(3000 - 1)
  6824  	pp = *(*prg.mem[p].hh()).lh()
  6825  	qq = *(*prg.mem[q].hh()).lh()
  6826  	for true {
  6827  		if int32(pp) == int32(qq) {
  6828  			if int32(pp) == memMin {
  6829  				goto done
  6830  			} else {
  6831  				// Contribute a term from |p|, plus |f| times the corresponding term from |q|
  6832  				if int32(tt) == dependent {
  6833  					v = *prg.mem[int32(p)+1].int() + prg.takeFraction(f, *prg.mem[int32(q)+1].int())
  6834  				} else {
  6835  					v = *prg.mem[int32(p)+1].int() + prg.takeScaled(f, *prg.mem[int32(q)+1].int())
  6836  				}
  6837  				*prg.mem[int32(p)+1].int() = v
  6838  				s = p
  6839  				p = *(*prg.mem[p].hh()).rh()
  6840  				if abs(v) < threshold {
  6841  					prg.freeNode(s, halfword(depNodeSize))
  6842  				} else {
  6843  					if abs(v) >= 04525252525 {
  6844  						if prg.watchCoefs {
  6845  							*(*prg.mem[qq].hh()).b0() = byte(independentNeedingFix)
  6846  							prg.fixNeeded = true
  6847  						}
  6848  					}
  6849  					*(*prg.mem[r1].hh()).rh() = s
  6850  					r1 = s
  6851  				}
  6852  				pp = *(*prg.mem[p].hh()).lh()
  6853  				q = *(*prg.mem[q].hh()).rh()
  6854  				qq = *(*prg.mem[q].hh()).lh()
  6855  			}
  6856  		} else if *prg.mem[int32(pp)+1].int() < *prg.mem[int32(qq)+1].int() {
  6857  			if int32(tt) == dependent {
  6858  				v = prg.takeFraction(f, *prg.mem[int32(q)+1].int())
  6859  			} else {
  6860  				v = prg.takeScaled(f, *prg.mem[int32(q)+1].int())
  6861  			}
  6862  			if abs(v) > threshold/2 {
  6863  				s = prg.getNode(depNodeSize)
  6864  				*(*prg.mem[s].hh()).lh() = qq
  6865  				*prg.mem[int32(s)+1].int() = v
  6866  				if abs(v) >= 04525252525 {
  6867  					if prg.watchCoefs {
  6868  						*(*prg.mem[qq].hh()).b0() = byte(independentNeedingFix)
  6869  						prg.fixNeeded = true
  6870  					}
  6871  				}
  6872  				*(*prg.mem[r1].hh()).rh() = s
  6873  				r1 = s
  6874  			}
  6875  			q = *(*prg.mem[q].hh()).rh()
  6876  			qq = *(*prg.mem[q].hh()).lh()
  6877  		} else {
  6878  			*(*prg.mem[r1].hh()).rh() = p
  6879  			r1 = p
  6880  			p = *(*prg.mem[p].hh()).rh()
  6881  			pp = *(*prg.mem[p].hh()).lh()
  6882  		}
  6883  	}
  6884  
  6885  done:
  6886  	if int32(t) == dependent {
  6887  		*prg.mem[int32(p)+1].int() = prg.slowAdd(*prg.mem[int32(p)+1].int(), prg.takeFraction(*prg.mem[int32(q)+1].int(), f))
  6888  	} else {
  6889  		*prg.mem[int32(p)+1].int() = prg.slowAdd(*prg.mem[int32(p)+1].int(), prg.takeScaled(*prg.mem[int32(q)+1].int(), f))
  6890  	}
  6891  	*(*prg.mem[r1].hh()).rh() = p
  6892  	prg.depFinal = p
  6893  	r = *(*prg.mem[3000-1].hh()).rh()
  6894  	return r
  6895  }
  6896  
  6897  func (prg *prg) pOverV(p halfword, v scaled,
  6898  	t0, t1 smallNumber) (r halfword) {
  6899  	var (
  6900  		r1, s       halfword // for list manipulation
  6901  		w           int32    // tentative coefficient
  6902  		threshold   int32
  6903  		scalingDown bool
  6904  	)
  6905  	if int32(t0) != int32(t1) {
  6906  		scalingDown = true
  6907  	} else {
  6908  		scalingDown = false
  6909  	}
  6910  	if int32(t1) == dependent {
  6911  		threshold = halfFractionThreshold
  6912  	} else {
  6913  		threshold = halfScaledThreshold
  6914  	}
  6915  	r1 = uint16(3000 - 1)
  6916  	for int32(*(*prg.mem[p].hh()).lh()) != memMin {
  6917  		if scalingDown {
  6918  			if abs(v) < 02000000 {
  6919  				w = prg.makeScaled(*prg.mem[int32(p)+1].int(), v*010000)
  6920  			} else {
  6921  				w = prg.makeScaled(prg.roundFraction(*prg.mem[int32(p)+1].int()), v)
  6922  			}
  6923  		} else {
  6924  			w = prg.makeScaled(*prg.mem[int32(p)+1].int(), v)
  6925  		}
  6926  		if abs(w) <= threshold {
  6927  			s = *(*prg.mem[p].hh()).rh()
  6928  			prg.freeNode(p, halfword(depNodeSize))
  6929  			p = s
  6930  		} else {
  6931  			if abs(w) >= 04525252525 {
  6932  				prg.fixNeeded = true
  6933  				*(*prg.mem[*(*prg.mem[p].hh()).lh()].hh()).b0() = byte(independentNeedingFix)
  6934  			}
  6935  			*(*prg.mem[r1].hh()).rh() = p
  6936  			r1 = p
  6937  			*prg.mem[int32(p)+1].int() = w
  6938  			p = *(*prg.mem[p].hh()).rh()
  6939  		}
  6940  	}
  6941  	*(*prg.mem[r1].hh()).rh() = p
  6942  	*prg.mem[int32(p)+1].int() = prg.makeScaled(*prg.mem[int32(p)+1].int(), v)
  6943  	r = *(*prg.mem[3000-1].hh()).rh()
  6944  	return r
  6945  }
  6946  
  6947  func (prg *prg) valTooBig(x scaled) {
  6948  	if prg.internal[warningCheck-1] > 0 {
  6949  		{
  6950  			if int32(prg.interaction) == errorStopMode {
  6951  			}
  6952  			prg.printNl(strNumber( /* "! " */ 261))
  6953  			prg.print( /* "Value is too large (" */ 590) /* \xref[!\relax]  */
  6954  		}
  6955  		prg.printScaled(x)
  6956  		prg.printChar(asciiCode(')'))
  6957  		// \xref[Value is too large]
  6958  		{
  6959  			prg.helpPtr = 4
  6960  			prg.helpLine[3] = /* "The equation I just processed has given some variable" */ 591
  6961  			prg.helpLine[2] = /* "a value of 4096 or more. Continue and I'll try to cope" */ 592
  6962  			prg.helpLine[1] = /* "with that big value; but it might be dangerous." */ 593
  6963  			prg.helpLine[0] = /* "(Set warningcheck:=0 to suppress this message.)" */ 594
  6964  		}
  6965  		prg.error1()
  6966  	}
  6967  }
  6968  
  6969  func (prg *prg) makeKnown(p, q halfword) {
  6970  	var (
  6971  		t /* dependent..protoDependent */ byte // the previous type
  6972  	)
  6973  	*(*prg.mem[int32(*(*prg.mem[q].hh()).rh())+1].hh()).lh() = *(*prg.mem[int32(p)+1].hh()).lh()
  6974  	*(*prg.mem[*(*prg.mem[int32(p)+1].hh()).lh()].hh()).rh() = *(*prg.mem[q].hh()).rh()
  6975  	t = *(*prg.mem[p].hh()).b0()
  6976  	*(*prg.mem[p].hh()).b0() = byte(known)
  6977  	*prg.mem[int32(p)+1].int() = *prg.mem[int32(q)+1].int()
  6978  	prg.freeNode(q, halfword(depNodeSize))
  6979  	if abs(*prg.mem[int32(p)+1].int()) >= 02000000000 {
  6980  		prg.valTooBig(*prg.mem[int32(p)+1].int())
  6981  	}
  6982  	if prg.internal[tracingEquations-1] > 0 {
  6983  		if prg.interesting(p) {
  6984  			prg.beginDiagnostic()
  6985  			prg.printNl(strNumber( /* "#### " */ 595))
  6986  			// \xref[]]]\#\#\#\#_][\.[\#\#\#\#]]
  6987  			prg.printVariableName(p)
  6988  			prg.printChar(asciiCode('='))
  6989  			prg.printScaled(*prg.mem[int32(p)+1].int())
  6990  			prg.endDiagnostic(false)
  6991  		}
  6992  	}
  6993  	if prg.curExp == int32(p) {
  6994  		if int32(prg.curType) == int32(t) {
  6995  			prg.curType = byte(known)
  6996  			prg.curExp = *prg.mem[int32(p)+1].int()
  6997  			prg.freeNode(p, halfword(valueNodeSize))
  6998  		}
  6999  	}
  7000  }
  7001  
  7002  func (prg *prg) fixDependencies() {
  7003  	var (
  7004  		p, q, r1, s, t halfword // list manipulation registers
  7005  		x              halfword // an independent variable
  7006  	)
  7007  	r1 = *(*prg.mem[memMin+3+10].hh()).rh()
  7008  	s = uint16(memMin)
  7009  	for int32(r1) != memMin+3+10 {
  7010  		t = r1
  7011  
  7012  		// Run through the dependency list for variable |t|, fixing all nodes, and ending with final link~|q|
  7013  		r1 = uint16(int32(t) + 1) // |link(r)=dep_list(t)|
  7014  		for true {
  7015  			q = *(*prg.mem[r1].hh()).rh()
  7016  			x = *(*prg.mem[q].hh()).lh()
  7017  			if int32(x) == memMin {
  7018  				goto done
  7019  			}
  7020  			if int32(*(*prg.mem[x].hh()).b0()) <= independentBeingFixed {
  7021  				if int32(*(*prg.mem[x].hh()).b0()) < independentBeingFixed {
  7022  					p = prg.getAvail()
  7023  					*(*prg.mem[p].hh()).rh() = s
  7024  					s = p
  7025  					*(*prg.mem[s].hh()).lh() = x
  7026  					*(*prg.mem[x].hh()).b0() = byte(independentBeingFixed)
  7027  				}
  7028  				*prg.mem[int32(q)+1].int() = *prg.mem[int32(q)+1].int() / 4
  7029  				if *prg.mem[int32(q)+1].int() == 0 {
  7030  					*(*prg.mem[r1].hh()).rh() = *(*prg.mem[q].hh()).rh()
  7031  					prg.freeNode(q, halfword(depNodeSize))
  7032  					q = r1
  7033  				}
  7034  			}
  7035  			r1 = q
  7036  		}
  7037  
  7038  	done:
  7039  		;
  7040  		r1 = *(*prg.mem[q].hh()).rh()
  7041  		if int32(q) == int32(*(*prg.mem[int32(t)+1].hh()).rh()) {
  7042  			prg.makeKnown(t, q)
  7043  		}
  7044  	}
  7045  	for int32(s) != memMin {
  7046  		p = *(*prg.mem[s].hh()).rh()
  7047  		x = *(*prg.mem[s].hh()).lh()
  7048  		{
  7049  			*(*prg.mem[s].hh()).rh() = prg.avail
  7050  			prg.avail = s
  7051  			prg.dynUsed = prg.dynUsed - 1
  7052  		}
  7053  		s = p
  7054  		*(*prg.mem[x].hh()).b0() = byte(independent)
  7055  		*prg.mem[int32(x)+1].int() = *prg.mem[int32(x)+1].int() + 2
  7056  	}
  7057  	prg.fixNeeded = false
  7058  }
  7059  
  7060  // \4
  7061  // Declare the recycling subroutines
  7062  func (prg *prg) tossKnotList(p halfword) {
  7063  	var (
  7064  		q  halfword // the node being freed
  7065  		r1 halfword // the next node
  7066  	)
  7067  	q = p
  7068  	for {
  7069  		r1 = *(*prg.mem[q].hh()).rh()
  7070  		prg.freeNode(q, halfword(knotNodeSize))
  7071  		q = r1
  7072  		if int32(q) == int32(p) {
  7073  			break
  7074  		}
  7075  	}
  7076  }
  7077  
  7078  func (prg *prg) tossEdges(h halfword) {
  7079  	var (
  7080  		p, q halfword // for list manipulation
  7081  	)
  7082  	q = *(*prg.mem[h].hh()).rh()
  7083  	for int32(q) != int32(h) {
  7084  		prg.flushList(*(*prg.mem[int32(q)+1].hh()).rh())
  7085  		if int32(*(*prg.mem[int32(q)+1].hh()).lh()) > memMin+1 {
  7086  			prg.flushList(*(*prg.mem[int32(q)+1].hh()).lh())
  7087  		}
  7088  		p = q
  7089  		q = *(*prg.mem[q].hh()).rh()
  7090  		prg.freeNode(p, halfword(rowNodeSize))
  7091  	}
  7092  	prg.freeNode(h, halfword(edgeHeaderSize))
  7093  }
  7094  
  7095  func (prg *prg) tossPen(p halfword) {
  7096  	var (
  7097  		k/* 1..8 */ byte          // relative header locations
  7098  		w, ww            halfword // pointers to offset nodes
  7099  	)
  7100  	if int32(p) != memMin+3 {
  7101  		for ii := int32(1); ii <= 8; ii++ {
  7102  			k = byte(ii)
  7103  			_ = k
  7104  			w = *(*prg.mem[int32(p)+int32(k)].hh()).rh()
  7105  			for {
  7106  				ww = *(*prg.mem[w].hh()).rh()
  7107  				prg.freeNode(w, halfword(coordNodeSize))
  7108  				w = ww
  7109  				if int32(w) == int32(*(*prg.mem[int32(p)+int32(k)].hh()).rh()) {
  7110  					break
  7111  				}
  7112  			}
  7113  		}
  7114  		prg.freeNode(p, halfword(penNodeSize))
  7115  	}
  7116  }
  7117  
  7118  func (prg *prg) ringDelete(p halfword) {
  7119  	var (
  7120  		q halfword
  7121  	)
  7122  	q = uint16(*prg.mem[int32(p)+1].int())
  7123  	if int32(q) != memMin {
  7124  		if int32(q) != int32(p) {
  7125  			for *prg.mem[int32(q)+1].int() != int32(p) {
  7126  				q = uint16(*prg.mem[int32(q)+1].int())
  7127  			}
  7128  			*prg.mem[int32(q)+1].int() = *prg.mem[int32(p)+1].int()
  7129  		}
  7130  	}
  7131  }
  7132  
  7133  func (prg *prg) recycleValue(p halfword) {
  7134  	var (
  7135  		t            smallNumber // a type code
  7136  		v            int32       // a value
  7137  		vv           int32       // another value
  7138  		q, r1, s, pp halfword    // link manipulation registers
  7139  	)
  7140  	t = *(*prg.mem[p].hh()).b0()
  7141  	if int32(t) < dependent {
  7142  		v = *prg.mem[int32(p)+1].int()
  7143  	}
  7144  	switch t {
  7145  	case undefined, vacuous, booleanType, known,
  7146  		numericType:
  7147  	case unknownBoolean, unknownString, unknownPen, unknownPicture,
  7148  		unknownPath:
  7149  		prg.ringDelete(p)
  7150  	case stringType:
  7151  		if int32(prg.strRef[v]) < maxStrRef {
  7152  			if int32(prg.strRef[v]) > 1 {
  7153  				prg.strRef[v] = byte(int32(prg.strRef[v]) - 1)
  7154  			} else {
  7155  				prg.flushString(strNumber(v))
  7156  			}
  7157  		}
  7158  	case penType:
  7159  		if int32(*(*prg.mem[v].hh()).lh()) == memMin {
  7160  			prg.tossPen(halfword(v))
  7161  		} else {
  7162  			*(*prg.mem[v].hh()).lh() = uint16(int32(*(*prg.mem[v].hh()).lh()) - 1)
  7163  		}
  7164  	case pathType, futurePen:
  7165  		prg.tossKnotList(halfword(v))
  7166  	case pictureType:
  7167  		prg.tossEdges(halfword(v))
  7168  	case pairType, transformType:
  7169  		// Recycle a big node
  7170  		if v != memMin {
  7171  			q = uint16(v + int32(prg.bigNodeSize[t-13]))
  7172  			for {
  7173  				q = uint16(int32(q) - 2)
  7174  				prg.recycleValue(q)
  7175  				if int32(q) == v {
  7176  					break
  7177  				}
  7178  			}
  7179  			prg.freeNode(halfword(v), halfword(prg.bigNodeSize[t-13]))
  7180  		}
  7181  
  7182  	case dependent, protoDependent:
  7183  		// Recycle a dependency list
  7184  		q = *(*prg.mem[int32(p)+1].hh()).rh()
  7185  		for int32(*(*prg.mem[q].hh()).lh()) != memMin {
  7186  			q = *(*prg.mem[q].hh()).rh()
  7187  		}
  7188  		*(*prg.mem[*(*prg.mem[int32(p)+1].hh()).lh()].hh()).rh() = *(*prg.mem[q].hh()).rh()
  7189  		*(*prg.mem[int32(*(*prg.mem[q].hh()).rh())+1].hh()).lh() = *(*prg.mem[int32(p)+1].hh()).lh()
  7190  		*(*prg.mem[q].hh()).rh() = uint16(memMin)
  7191  		prg.flushNodeList(*(*prg.mem[int32(p)+1].hh()).rh())
  7192  
  7193  	case independent:
  7194  		// Recycle an independent variable
  7195  		prg.maxC[dependent-17] = 0
  7196  		prg.maxC[protoDependent-17] = 0
  7197  
  7198  		prg.maxLink[dependent-17] = uint16(memMin)
  7199  		prg.maxLink[protoDependent-17] = uint16(memMin)
  7200  
  7201  		q = *(*prg.mem[memMin+3+10].hh()).rh()
  7202  		for int32(q) != memMin+3+10 {
  7203  			s = uint16(int32(q) + 1) // now |link(s)=dep_list(q)|
  7204  			for true {
  7205  				r1 = *(*prg.mem[s].hh()).rh()
  7206  				if int32(*(*prg.mem[r1].hh()).lh()) == memMin {
  7207  					goto done
  7208  				}
  7209  				if int32(*(*prg.mem[r1].hh()).lh()) != int32(p) {
  7210  					s = r1
  7211  				} else {
  7212  					t = *(*prg.mem[q].hh()).b0()
  7213  					*(*prg.mem[s].hh()).rh() = *(*prg.mem[r1].hh()).rh()
  7214  					*(*prg.mem[r1].hh()).lh() = q
  7215  					if abs(*prg.mem[int32(r1)+1].int()) > prg.maxC[t-17] {
  7216  						if prg.maxC[t-17] > 0 {
  7217  							*(*prg.mem[prg.maxPtr[t-17]].hh()).rh() = prg.maxLink[t-17]
  7218  							prg.maxLink[t-17] = prg.maxPtr[t-17]
  7219  						}
  7220  						prg.maxC[t-17] = abs(*prg.mem[int32(r1)+1].int())
  7221  						prg.maxPtr[t-17] = r1
  7222  					} else {
  7223  						*(*prg.mem[r1].hh()).rh() = prg.maxLink[t-17]
  7224  						prg.maxLink[t-17] = r1
  7225  					}
  7226  				}
  7227  			}
  7228  
  7229  		done:
  7230  			q = *(*prg.mem[r1].hh()).rh()
  7231  		}
  7232  		if prg.maxC[dependent-17] > 0 || prg.maxC[protoDependent-17] > 0 {
  7233  			if prg.maxC[dependent-17]/010000 >= prg.maxC[protoDependent-17] {
  7234  				t = byte(dependent)
  7235  			} else {
  7236  				t = byte(protoDependent)
  7237  			}
  7238  
  7239  			// Determine the dependency list |s| to substitute for the independent variable~|p|
  7240  			s = prg.maxPtr[t-17]
  7241  			pp = *(*prg.mem[s].hh()).lh()
  7242  			v = *prg.mem[int32(s)+1].int()
  7243  			if int32(t) == dependent {
  7244  				*prg.mem[int32(s)+1].int() = -02000000000
  7245  			} else {
  7246  				*prg.mem[int32(s)+1].int() = -0200000
  7247  			}
  7248  			r1 = *(*prg.mem[int32(pp)+1].hh()).rh()
  7249  			*(*prg.mem[s].hh()).rh() = r1
  7250  			for int32(*(*prg.mem[r1].hh()).lh()) != memMin {
  7251  				r1 = *(*prg.mem[r1].hh()).rh()
  7252  			}
  7253  			q = *(*prg.mem[r1].hh()).rh()
  7254  			*(*prg.mem[r1].hh()).rh() = uint16(memMin)
  7255  			*(*prg.mem[int32(q)+1].hh()).lh() = *(*prg.mem[int32(pp)+1].hh()).lh()
  7256  			*(*prg.mem[*(*prg.mem[int32(pp)+1].hh()).lh()].hh()).rh() = q
  7257  			{
  7258  				if prg.serialNo > 017777777777-sScale {
  7259  					prg.overflow(strNumber( /* "independent variables" */ 587), prg.serialNo/sScale)
  7260  				} /* \xref[METAFONT capacity exceeded independent variables][\quad independent variables]  */
  7261  				*(*prg.mem[pp].hh()).b0() = byte(independent)
  7262  				prg.serialNo = prg.serialNo + sScale
  7263  				*prg.mem[int32(pp)+1].int() = prg.serialNo
  7264  			}
  7265  			if prg.curExp == int32(pp) {
  7266  				if int32(prg.curType) == int32(t) {
  7267  					prg.curType = byte(independent)
  7268  				}
  7269  			}
  7270  			if prg.internal[tracingEquations-1] > 0 {
  7271  				if prg.interesting(p) {
  7272  					prg.beginDiagnostic()
  7273  					prg.printNl(strNumber( /* "### " */ 767))
  7274  					// \xref[]]]\#\#\#_][\.[\#\#\#]]
  7275  					if v > 0 {
  7276  						prg.printChar(asciiCode('-'))
  7277  					}
  7278  					if int32(t) == dependent {
  7279  						vv = prg.roundFraction(prg.maxC[dependent-17])
  7280  					} else {
  7281  						vv = prg.maxC[protoDependent-17]
  7282  					}
  7283  					if vv != 0200000 {
  7284  						prg.printScaled(vv)
  7285  					}
  7286  					prg.printVariableName(p)
  7287  					for *prg.mem[int32(p)+1].int()%sScale > 0 {
  7288  						prg.print( /* "*4" */ 589)
  7289  						*prg.mem[int32(p)+1].int() = *prg.mem[int32(p)+1].int() - 2
  7290  					}
  7291  					if int32(t) == dependent {
  7292  						prg.printChar(asciiCode('='))
  7293  					} else {
  7294  						prg.print( /* " = " */ 768)
  7295  					}
  7296  					prg.printDependency(s, t)
  7297  					prg.endDiagnostic(false)
  7298  				}
  7299  			}
  7300  			t = byte(dependent + protoDependent - int32(t)) // complement |t|
  7301  			if prg.maxC[t-17] > 0 {
  7302  				*(*prg.mem[prg.maxPtr[t-17]].hh()).rh() = prg.maxLink[t-17]
  7303  				prg.maxLink[t-17] = prg.maxPtr[t-17]
  7304  			}
  7305  			if int32(t) != dependent {
  7306  				for ii := int32(dependent); ii <= protoDependent; ii++ {
  7307  					t = smallNumber(ii)
  7308  					_ = t
  7309  					r1 = prg.maxLink[t-17]
  7310  					for int32(r1) != memMin {
  7311  						q = *(*prg.mem[r1].hh()).lh()
  7312  						*(*prg.mem[int32(q)+1].hh()).rh() = prg.pPlusFq(*(*prg.mem[int32(q)+1].hh()).rh(), prg.makeFraction(*prg.mem[int32(r1)+1].int(), -v), s, t, smallNumber(dependent))
  7313  						if int32(*(*prg.mem[int32(q)+1].hh()).rh()) == int32(prg.depFinal) {
  7314  							prg.makeKnown(q, prg.depFinal)
  7315  						}
  7316  						q = r1
  7317  						r1 = *(*prg.mem[r1].hh()).rh()
  7318  						prg.freeNode(q, halfword(depNodeSize))
  7319  					}
  7320  				}
  7321  			} else {
  7322  				// Substitute new proto-dependencies in place of |p|
  7323  				for ii := int32(dependent); ii <= protoDependent; ii++ {
  7324  					t = smallNumber(ii)
  7325  					_ = t
  7326  					r1 = prg.maxLink[t-17]
  7327  					for int32(r1) != memMin {
  7328  						q = *(*prg.mem[r1].hh()).lh()
  7329  						if int32(t) == dependent {
  7330  							if prg.curExp == int32(q) {
  7331  								if int32(prg.curType) == dependent {
  7332  									prg.curType = byte(protoDependent)
  7333  								}
  7334  							}
  7335  							*(*prg.mem[int32(q)+1].hh()).rh() = prg.pOverV(*(*prg.mem[int32(q)+1].hh()).rh(), scaled(0200000), smallNumber(dependent), smallNumber(protoDependent))
  7336  							*(*prg.mem[q].hh()).b0() = byte(protoDependent)
  7337  							*prg.mem[int32(r1)+1].int() = prg.roundFraction(*prg.mem[int32(r1)+1].int())
  7338  						}
  7339  						*(*prg.mem[int32(q)+1].hh()).rh() = prg.pPlusFq(*(*prg.mem[int32(q)+1].hh()).rh(), prg.makeScaled(*prg.mem[int32(r1)+1].int(), -v), s, smallNumber(protoDependent), smallNumber(protoDependent))
  7340  						if int32(*(*prg.mem[int32(q)+1].hh()).rh()) == int32(prg.depFinal) {
  7341  							prg.makeKnown(q, prg.depFinal)
  7342  						}
  7343  						q = r1
  7344  						r1 = *(*prg.mem[r1].hh()).rh()
  7345  						prg.freeNode(q, halfword(depNodeSize))
  7346  					}
  7347  				}
  7348  			}
  7349  			prg.flushNodeList(s)
  7350  			if prg.fixNeeded {
  7351  				prg.fixDependencies()
  7352  			}
  7353  			{
  7354  				if prg.arithError {
  7355  					prg.clearArith()
  7356  				}
  7357  			}
  7358  		}
  7359  
  7360  	case tokenList, structured:
  7361  		prg.confusion(strNumber( /* "recycle" */ 766))
  7362  	// \xref[this can't happen recycle][\quad recycle]
  7363  	case unsuffixedMacro, suffixedMacro:
  7364  		prg.deleteMacRef(halfword(*prg.mem[int32(p)+1].int()))
  7365  	} // there are no other cases
  7366  	*(*prg.mem[p].hh()).b0() = byte(undefined)
  7367  }
  7368  
  7369  // \4
  7370  // Declare the procedure called |flush_cur_exp|
  7371  func (prg *prg) flushCurExp(v scaled) {
  7372  	switch prg.curType {
  7373  	case unknownBoolean, unknownString, unknownPen, unknownPicture,
  7374  		unknownPath, transformType, pairType, dependent,
  7375  		protoDependent, independent:
  7376  		prg.recycleValue(halfword(prg.curExp))
  7377  		prg.freeNode(halfword(prg.curExp), halfword(valueNodeSize))
  7378  
  7379  	case penType:
  7380  		if int32(*(*prg.mem[prg.curExp].hh()).lh()) == memMin {
  7381  			prg.tossPen(halfword(prg.curExp))
  7382  		} else {
  7383  			*(*prg.mem[prg.curExp].hh()).lh() = uint16(int32(*(*prg.mem[prg.curExp].hh()).lh()) - 1)
  7384  		}
  7385  	case stringType:
  7386  		if int32(prg.strRef[prg.curExp]) < maxStrRef {
  7387  			if int32(prg.strRef[prg.curExp]) > 1 {
  7388  				prg.strRef[prg.curExp] = byte(int32(prg.strRef[prg.curExp]) - 1)
  7389  			} else {
  7390  				prg.flushString(strNumber(prg.curExp))
  7391  			}
  7392  		}
  7393  	case futurePen, pathType:
  7394  		prg.tossKnotList(halfword(prg.curExp))
  7395  	case pictureType:
  7396  		prg.tossEdges(halfword(prg.curExp))
  7397  
  7398  	default:
  7399  	}
  7400  
  7401  	prg.curType = byte(known)
  7402  	prg.curExp = v
  7403  }
  7404  
  7405  func (prg *prg) flushError(v scaled) { prg.error1(); prg.flushCurExp(v) } // \2
  7406  
  7407  func (prg *prg) putGetError() { prg.backError(); prg.getXNext() }
  7408  
  7409  func (prg *prg) putGetFlushError(v scaled) {
  7410  	prg.putGetError()
  7411  	prg.flushCurExp(v)
  7412  }
  7413  
  7414  // \4
  7415  // Declare the procedure called |flush_below_variable|
  7416  func (prg *prg) flushBelowVariable(p halfword) {
  7417  	var (
  7418  		q, r1 halfword // list manipulation registers
  7419  	)
  7420  	if int32(*(*prg.mem[p].hh()).b0()) != structured {
  7421  		prg.recycleValue(p)
  7422  	} else {
  7423  		q = *(*prg.mem[int32(p)+1].hh()).rh()
  7424  		for int32(*(*prg.mem[q].hh()).b1()) == subscr {
  7425  			prg.flushBelowVariable(q)
  7426  			r1 = q
  7427  			q = *(*prg.mem[q].hh()).rh()
  7428  			prg.freeNode(r1, halfword(subscrNodeSize))
  7429  		}
  7430  		r1 = *(*prg.mem[int32(p)+1].hh()).lh()
  7431  		q = *(*prg.mem[r1].hh()).rh()
  7432  		prg.recycleValue(r1)
  7433  		if int32(*(*prg.mem[p].hh()).b1()) <= savedRoot {
  7434  			prg.freeNode(r1, halfword(valueNodeSize))
  7435  		} else {
  7436  			prg.freeNode(r1, halfword(subscrNodeSize))
  7437  		}
  7438  		// we assume that |subscr_node_size=attr_node_size|
  7439  		for {
  7440  			prg.flushBelowVariable(q)
  7441  			r1 = q
  7442  			q = *(*prg.mem[q].hh()).rh()
  7443  			prg.freeNode(r1, halfword(attrNodeSize))
  7444  			if int32(q) == memMin+3+10+2+2 {
  7445  				break
  7446  			}
  7447  		}
  7448  		*(*prg.mem[p].hh()).b0() = byte(undefined)
  7449  	}
  7450  }
  7451  
  7452  func (prg *prg) flushVariable(p, t halfword, discardSuffixes bool) {
  7453  	var (
  7454  		q, r1 halfword // list manipulation
  7455  		n     halfword // attribute to match
  7456  	)
  7457  	for int32(t) != memMin {
  7458  		if int32(*(*prg.mem[p].hh()).b0()) != structured {
  7459  			goto exit
  7460  		}
  7461  		n = *(*prg.mem[t].hh()).lh()
  7462  		t = *(*prg.mem[t].hh()).rh()
  7463  		if int32(n) == collectiveSubscript {
  7464  			r1 = uint16(int32(p) + 1)
  7465  			q = *(*prg.mem[r1].hh()).rh() // |q=subscr_head(p)|
  7466  			for int32(*(*prg.mem[q].hh()).b1()) == subscr {
  7467  				prg.flushVariable(q, t, discardSuffixes)
  7468  				if int32(t) == memMin {
  7469  					if int32(*(*prg.mem[q].hh()).b0()) == structured {
  7470  						r1 = q
  7471  					} else {
  7472  						*(*prg.mem[r1].hh()).rh() = *(*prg.mem[q].hh()).rh()
  7473  						prg.freeNode(q, halfword(subscrNodeSize))
  7474  					}
  7475  				} else {
  7476  					r1 = q
  7477  				}
  7478  				q = *(*prg.mem[r1].hh()).rh()
  7479  			}
  7480  		}
  7481  		p = *(*prg.mem[int32(p)+1].hh()).lh()
  7482  		for {
  7483  			r1 = p
  7484  			p = *(*prg.mem[p].hh()).rh()
  7485  			if int32(*(*prg.mem[int32(p)+2].hh()).lh()) >= int32(n) {
  7486  				break
  7487  			}
  7488  		}
  7489  		if int32(*(*prg.mem[int32(p)+2].hh()).lh()) != int32(n) {
  7490  			goto exit
  7491  		}
  7492  	}
  7493  	if discardSuffixes {
  7494  		prg.flushBelowVariable(p)
  7495  	} else {
  7496  		if int32(*(*prg.mem[p].hh()).b0()) == structured {
  7497  			p = *(*prg.mem[int32(p)+1].hh()).lh()
  7498  		}
  7499  		prg.recycleValue(p)
  7500  	}
  7501  
  7502  exit:
  7503  }
  7504  
  7505  // 248.
  7506  
  7507  // tangle:pos ../../mf.web:5518:3:
  7508  
  7509  // Just before assigning a new value to a variable, we will recycle the
  7510  // old value and make the old value undefined. The |und_type| routine
  7511  // determines what type of undefined value should be given, based on
  7512  // the current type before recycling.
  7513  func (prg *prg) undType(p halfword) (r smallNumber) {
  7514  	switch *(*prg.mem[p].hh()).b0() {
  7515  	case undefined, vacuous:
  7516  		r = byte(undefined)
  7517  	case booleanType, unknownBoolean:
  7518  		r = byte(unknownBoolean)
  7519  	case stringType, unknownString:
  7520  		r = byte(unknownString)
  7521  	case penType, unknownPen, futurePen:
  7522  		r = byte(unknownPen)
  7523  	case pathType, unknownPath:
  7524  		r = byte(unknownPath)
  7525  	case pictureType, unknownPicture:
  7526  		r = byte(unknownPicture)
  7527  	case transformType, pairType, numericType:
  7528  		r = *(*prg.mem[p].hh()).b0()
  7529  	case known, dependent, protoDependent, independent:
  7530  		r = byte(numericType)
  7531  	} // there are no other cases
  7532  	return r
  7533  }
  7534  
  7535  // 249.
  7536  
  7537  // tangle:pos ../../mf.web:5536:3:
  7538  
  7539  // The |clear_symbol| routine is used when we want to redefine the equivalent
  7540  // of a symbolic token. It must remove any variable structure or macro
  7541  // definition that is currently attached to that symbol. If the |saving|
  7542  // parameter is true, a subsidiary structure is saved instead of destroyed.
  7543  func (prg *prg) clearSymbol(p halfword, saving bool) {
  7544  	var (
  7545  		q halfword // |equiv(p)|
  7546  	)
  7547  	q = *prg.eqtb[p-1].rh()
  7548  	switch int32(*prg.eqtb[p-1].lh()) % outerTag {
  7549  	case definedMacro, secondaryPrimaryMacro, tertiarySecondaryMacro, expressionTertiaryMacro:
  7550  		if !saving {
  7551  			prg.deleteMacRef(q)
  7552  		}
  7553  	case tagToken:
  7554  		if int32(q) != memMin {
  7555  			if saving {
  7556  				*(*prg.mem[q].hh()).b1() = byte(savedRoot)
  7557  			} else {
  7558  				prg.flushBelowVariable(q)
  7559  				prg.freeNode(q, halfword(valueNodeSize))
  7560  			}
  7561  		}
  7562  
  7563  	default:
  7564  	}
  7565  
  7566  	prg.eqtb[p-1] = prg.eqtb[hashBase+hashSize+12-1]
  7567  }
  7568  
  7569  // 252.
  7570  
  7571  // tangle:pos ../../mf.web:5596:3:
  7572  
  7573  // The |save_variable| routine is given a hash address |q|; it salts this
  7574  // address away in the save stack, together with its current equivalent,
  7575  // then makes token~|q| behave as though it were brand new.
  7576  //
  7577  // Nothing is stacked when |save_ptr=null|, however; there's no way to remove
  7578  // things from the stack when the program is not inside a group, so there's
  7579  // no point in wasting the space.
  7580  func (prg *prg) saveVariable(q halfword) {
  7581  	var (
  7582  		p halfword // temporary register
  7583  	)
  7584  	if int32(prg.savePtr) != memMin {
  7585  		p = prg.getNode(saveNodeSize)
  7586  		*(*prg.mem[p].hh()).lh() = q
  7587  		*(*prg.mem[p].hh()).rh() = prg.savePtr
  7588  		*prg.mem[int32(p)+1].hh() = prg.eqtb[q-1]
  7589  		prg.savePtr = p
  7590  	}
  7591  	prg.clearSymbol(q, int32(prg.savePtr) != memMin)
  7592  }
  7593  
  7594  // 253.
  7595  
  7596  // tangle:pos ../../mf.web:5613:3:
  7597  
  7598  // Similarly, |save_internal| is given the location |q| of an internal
  7599  // quantity like |tracing_pens|. It creates a save stack entry of the
  7600  // third kind.
  7601  func (prg *prg) saveInternal(q halfword) {
  7602  	var (
  7603  		p halfword // new item for the save stack
  7604  	)
  7605  	if int32(prg.savePtr) != memMin {
  7606  		p = prg.getNode(saveNodeSize)
  7607  		*(*prg.mem[p].hh()).lh() = uint16(hashBase + hashSize + 12 + int32(q))
  7608  		*(*prg.mem[p].hh()).rh() = prg.savePtr
  7609  		*prg.mem[int32(p)+1].int() = prg.internal[q-1]
  7610  		prg.savePtr = p
  7611  	}
  7612  }
  7613  
  7614  // 254.
  7615  
  7616  // tangle:pos ../../mf.web:5625:3:
  7617  
  7618  // At the end of a group, the |unsave| routine restores all of the saved
  7619  // equivalents in reverse order. This routine will be called only when there
  7620  // is at least one boundary item on the save stack.
  7621  func (prg *prg) unsave() {
  7622  	var (
  7623  		q halfword // index to saved item
  7624  		p halfword // temporary register
  7625  	)
  7626  	for int32(*(*prg.mem[prg.savePtr].hh()).lh()) != 0 {
  7627  		q = *(*prg.mem[prg.savePtr].hh()).lh()
  7628  		if int32(q) > hashBase+hashSize+12 {
  7629  			if prg.internal[tracingRestores-1] > 0 {
  7630  				prg.beginDiagnostic()
  7631  				prg.printNl(strNumber( /* "[restoring " */ 516))
  7632  				prg.slowPrint(int32(prg.intName[int32(q)-(hashBase+hashSize+12)-1]))
  7633  				prg.printChar(asciiCode('='))
  7634  				prg.printScaled(*prg.mem[int32(prg.savePtr)+1].int())
  7635  				prg.printChar(asciiCode('}'))
  7636  				prg.endDiagnostic(false)
  7637  			}
  7638  			prg.internal[int32(q)-(hashBase+hashSize+12)-1] = *prg.mem[int32(prg.savePtr)+1].int()
  7639  		} else {
  7640  			if prg.internal[tracingRestores-1] > 0 {
  7641  				prg.beginDiagnostic()
  7642  				prg.printNl(strNumber( /* "[restoring " */ 516))
  7643  				prg.slowPrint(int32(*prg.hash[q-1].rh()))
  7644  				prg.printChar(asciiCode('}'))
  7645  				prg.endDiagnostic(false)
  7646  			}
  7647  			prg.clearSymbol(q, false)
  7648  			prg.eqtb[q-1] = *prg.mem[int32(prg.savePtr)+1].hh()
  7649  			if int32(*prg.eqtb[q-1].lh())%outerTag == tagToken {
  7650  				p = *prg.eqtb[q-1].rh()
  7651  				if int32(p) != memMin {
  7652  					*(*prg.mem[p].hh()).b1() = byte(root)
  7653  				}
  7654  			}
  7655  		}
  7656  		p = *(*prg.mem[prg.savePtr].hh()).rh()
  7657  		prg.freeNode(prg.savePtr, halfword(saveNodeSize))
  7658  		prg.savePtr = p
  7659  	}
  7660  	p = *(*prg.mem[prg.savePtr].hh()).rh()
  7661  	{
  7662  		*(*prg.mem[prg.savePtr].hh()).rh() = prg.avail
  7663  		prg.avail = prg.savePtr
  7664  		prg.dynUsed = prg.dynUsed - 1
  7665  	}
  7666  	prg.savePtr = p
  7667  }
  7668  
  7669  // 255. \[17] Data structures for paths
  7670  
  7671  // tangle:pos ../../mf.web:5660:36:
  7672  
  7673  // When a \MF\ user specifies a path, \MF\ will create a list of knots
  7674  // and control points for the associated cubic spline curves. If the
  7675  // knots are $z_0$, $z_1$, \dots, $z_n$, there are control points
  7676  // $z_k^+$ and $z_[k+1]^-$ such that the cubic splines between knots
  7677  // $z_k$ and $z_[k+1]$ are defined by B\'ezier's formula
  7678  // \xref[Bezier][B\'ezier, Pierre Etienne]
  7679  // $$\eqalign[z(t)&=B(z_k,z_k^+,z_[k+1]^-,z_[k+1];t)\cr
  7680  // &=(1-t)^3z_k+3(1-t)^2tz_k^++3(1-t)t^2z_[k+1]^-+t^3z_[k+1]\cr]$$
  7681  // for |0<=t<=1|.
  7682  //
  7683  // There is a 7-word node for each knot $z_k$, containing one word of
  7684  // control information and six words for the |x| and |y| coordinates
  7685  // of $z_k^-$ and $z_k$ and~$z_k^+$. The control information appears
  7686  // in the |left_type| and |right_type| fields, which each occupy
  7687  // a quarter of the first word in the node; they specify properties
  7688  // of the curve as it enters and leaves the knot. There's also a
  7689  // halfword |link| field, which points to the following knot.
  7690  //
  7691  // If the path is a closed contour, knots 0 and |n| are identical;
  7692  // i.e., the |link| in knot |n-1| points to knot~0. But if the path
  7693  // is not closed, the |left_type| of knot~0 and the |right_type| of knot~|n|
  7694  // are equal to |endpoint|. In the latter case the |link| in knot~|n| points
  7695  // to knot~0, and the control points $z_0^-$ and $z_n^+$ are not used.
  7696  
  7697  // 256.
  7698  
  7699  // tangle:pos ../../mf.web:5696:3:
  7700  
  7701  // Before the B\'ezier control points have been calculated, the memory
  7702  // space they will ultimately occupy is taken up by information that can be
  7703  // used to compute them. There are four cases:
  7704  //
  7705  // \yskip
  7706  // \textindent[$\bullet$] If |right_type=open|, the curve should leave
  7707  // the knot in the same direction it entered; \MF\ will figure out a
  7708  // suitable direction.
  7709  //
  7710  // \yskip
  7711  // \textindent[$\bullet$] If |right_type=curl|, the curve should leave the
  7712  // knot in a direction depending on the angle at which it enters the next
  7713  // knot and on the curl parameter stored in |right_curl|.
  7714  //
  7715  // \yskip
  7716  // \textindent[$\bullet$] If |right_type=given|, the curve should leave the
  7717  // knot in a nonzero direction stored as an |angle| in |right_given|.
  7718  //
  7719  // \yskip
  7720  // \textindent[$\bullet$] If |right_type=explicit|, the B\'ezier control
  7721  // point for leaving this knot has already been computed; it is in the
  7722  // |right_x| and |right_y| fields.
  7723  //
  7724  // \yskip\noindent
  7725  // The rules for |left_type| are similar, but they refer to the curve entering
  7726  // the knot, and to \\[left] fields instead of \\[right] fields.
  7727  //
  7728  // Non-|explicit| control points will be chosen based on ``tension'' parameters
  7729  // in the |left_tension| and |right_tension| fields. The
  7730  // `\&[atleast]' option is represented by negative tension values.
  7731  // \xref[at_least_][\&[atleast] primitive]
  7732  //
  7733  // For example, the \MF\ path specification
  7734  // $$\.[z0..z1..tension atleast 1..\[curl 2\]z2..z3\[-1,-2\]..tension
  7735  //   3 and 4..p],$$
  7736  // where \.p is the path `\.[z4..controls z45 and z54..z5]', will be represented
  7737  // by the six knots
  7738  // \def\lodash[\hbox to 1.1em[\thinspace\hrulefill\thinspace]]
  7739  // $$\vbox[\halign[#\hfil&&\qquad#\hfil\cr
  7740  // |left_type|&\\[left] info&|x_coord,y_coord|&|right_type|&\\[right] info\cr
  7741  // \noalign[\yskip]
  7742  // |endpoint|&\lodash$,\,$\lodash&$x_0,y_0$&|curl|&$1.0,1.0$\cr
  7743  // |open|&\lodash$,1.0$&$x_1,y_1$&|open|&\lodash$,-1.0$\cr
  7744  // |curl|&$2.0,-1.0$&$x_2,y_2$&|curl|&$2.0,1.0$\cr
  7745  // |given|&$d,1.0$&$x_3,y_3$&|given|&$d,3.0$\cr
  7746  // |open|&\lodash$,4.0$&$x_4,y_4$&|explicit|&$x_[45],y_[45]$\cr
  7747  // |explicit|&$x_[54],y_[54]$&$x_5,y_5$&|endpoint|&\lodash$,\,$\lodash\cr]]$$
  7748  // Here |d| is the |angle| obtained by calling |n_arg(-unity,-two)|.
  7749  // Of course, this example is more complicated than anything a normal user
  7750  // would ever write.
  7751  //
  7752  // These types must satisfy certain restrictions because of the form of \MF's
  7753  // path syntax:
  7754  // (i)~|open| type never appears in the same node together with |endpoint|,
  7755  // |given|, or |curl|.
  7756  // (ii)~The |right_type| of a node is |explicit| if and only if the
  7757  // |left_type| of the following node is |explicit|.
  7758  // (iii)~|endpoint| types occur only at the ends, as mentioned above.
  7759  
  7760  // 264.
  7761  
  7762  // tangle:pos ../../mf.web:5865:3:
  7763  
  7764  // If we want to duplicate a knot node, we can say |copy_knot|:
  7765  func (prg *prg) copyKnot(p halfword) (r halfword) {
  7766  	var (
  7767  		q                             halfword // the copy
  7768  		k/* 0..knotNodeSize-1 */ byte          // runs through the words of a knot node
  7769  	)
  7770  	q = prg.getNode(knotNodeSize)
  7771  	for ii := int32(0); ii <= knotNodeSize-1; ii++ {
  7772  		k = byte(ii)
  7773  		_ = k
  7774  		prg.mem[int32(q)+int32(k)] = prg.mem[int32(p)+int32(k)]
  7775  	}
  7776  	r = q
  7777  	return r
  7778  }
  7779  
  7780  // 265.
  7781  
  7782  // tangle:pos ../../mf.web:5875:3:
  7783  
  7784  // The |copy_path| routine makes a clone of a given path.
  7785  func (prg *prg) copyPath(p halfword) (r halfword) {
  7786  	var (
  7787  		q, pp, qq halfword // for list manipulation
  7788  	)
  7789  	q = prg.getNode(knotNodeSize) // this will correspond to |p|
  7790  	qq = q
  7791  	pp = p
  7792  	for true {
  7793  		*(*prg.mem[qq].hh()).b0() = *(*prg.mem[pp].hh()).b0()
  7794  		*(*prg.mem[qq].hh()).b1() = *(*prg.mem[pp].hh()).b1()
  7795  
  7796  		*prg.mem[int32(qq)+1].int() = *prg.mem[int32(pp)+1].int()
  7797  		*prg.mem[int32(qq)+2].int() = *prg.mem[int32(pp)+2].int()
  7798  
  7799  		*prg.mem[int32(qq)+3].int() = *prg.mem[int32(pp)+3].int()
  7800  		*prg.mem[int32(qq)+4].int() = *prg.mem[int32(pp)+4].int()
  7801  
  7802  		*prg.mem[int32(qq)+5].int() = *prg.mem[int32(pp)+5].int()
  7803  		*prg.mem[int32(qq)+6].int() = *prg.mem[int32(pp)+6].int()
  7804  
  7805  		if int32(*(*prg.mem[pp].hh()).rh()) == int32(p) {
  7806  			*(*prg.mem[qq].hh()).rh() = q
  7807  			r = q
  7808  			goto exit
  7809  		}
  7810  		*(*prg.mem[qq].hh()).rh() = prg.getNode(knotNodeSize)
  7811  		qq = *(*prg.mem[qq].hh()).rh()
  7812  		pp = *(*prg.mem[pp].hh()).rh()
  7813  	}
  7814  
  7815  exit:
  7816  	;
  7817  	return r
  7818  }
  7819  
  7820  // 266.
  7821  
  7822  // tangle:pos ../../mf.web:5894:3:
  7823  
  7824  // Similarly, there's a way to copy the [\sl reverse\/] of a path. This procedure
  7825  // returns a pointer to the first node of the copy, if the path is a cycle,
  7826  // but to the final node of a non-cyclic copy. The global
  7827  // variable |path_tail| will point to the final node of the original path;
  7828  // this trick makes it easier to implement `\&[doublepath]'.
  7829  //
  7830  // All node types are assumed to be |endpoint| or |explicit| only.
  7831  func (prg *prg) htapYpoc(p halfword) (r halfword) {
  7832  	var (
  7833  		q, pp, qq, rr halfword // for list manipulation
  7834  	)
  7835  	q = prg.getNode(knotNodeSize) // this will correspond to |p|
  7836  	qq = q
  7837  	pp = p
  7838  	for true {
  7839  		*(*prg.mem[qq].hh()).b1() = *(*prg.mem[pp].hh()).b0()
  7840  		*(*prg.mem[qq].hh()).b0() = *(*prg.mem[pp].hh()).b1()
  7841  
  7842  		*prg.mem[int32(qq)+1].int() = *prg.mem[int32(pp)+1].int()
  7843  		*prg.mem[int32(qq)+2].int() = *prg.mem[int32(pp)+2].int()
  7844  
  7845  		*prg.mem[int32(qq)+5].int() = *prg.mem[int32(pp)+3].int()
  7846  		*prg.mem[int32(qq)+6].int() = *prg.mem[int32(pp)+4].int()
  7847  
  7848  		*prg.mem[int32(qq)+3].int() = *prg.mem[int32(pp)+5].int()
  7849  		*prg.mem[int32(qq)+4].int() = *prg.mem[int32(pp)+6].int()
  7850  
  7851  		if int32(*(*prg.mem[pp].hh()).rh()) == int32(p) {
  7852  			*(*prg.mem[q].hh()).rh() = qq
  7853  			prg.pathTail = pp
  7854  			r = q
  7855  			goto exit
  7856  		}
  7857  		rr = prg.getNode(knotNodeSize)
  7858  		*(*prg.mem[rr].hh()).rh() = qq
  7859  		qq = rr
  7860  		pp = *(*prg.mem[pp].hh()).rh()
  7861  	}
  7862  
  7863  exit:
  7864  	;
  7865  	return r
  7866  }
  7867  
  7868  // 269. \[18] Choosing control points
  7869  
  7870  // tangle:pos ../../mf.web:5933:34:
  7871  
  7872  // Now we must actually delve into one of \MF's more difficult routines,
  7873  // the |make_choices| procedure that chooses angles and control points for
  7874  // the splines of a curve when the user has not specified them explicitly.
  7875  // The parameter to |make_choices| points to a list of knots and
  7876  // path information, as described above.
  7877  //
  7878  // A path decomposes into independent segments at “breakpoint” knots,
  7879  // which are knots whose left and right angles are both prespecified in
  7880  // some way (i.e., their |left_type| and |right_type| aren't both open).
  7881  // \4
  7882  // Declare the procedure called |solve_choices|
  7883  // \4
  7884  // Declare subroutines needed by |solve_choices|
  7885  func (prg *prg) curlRatio(gamma, aTension, bTension scaled) (r fraction) {
  7886  	var (
  7887  		alpha, beta, num, denom, ff fraction // registers
  7888  	)
  7889  	alpha = prg.makeFraction(0200000, aTension)
  7890  	beta = prg.makeFraction(0200000, bTension)
  7891  
  7892  	if alpha <= beta {
  7893  		ff = prg.makeFraction(alpha, beta)
  7894  		ff = prg.takeFraction(ff, ff)
  7895  		gamma = prg.takeFraction(gamma, ff)
  7896  
  7897  		beta = beta / 010000 // convert |fraction| to |scaled|
  7898  		denom = prg.takeFraction(gamma, alpha) + 0600000 - beta
  7899  		num = prg.takeFraction(gamma, 06000000000-alpha) + beta
  7900  	} else {
  7901  		ff = prg.makeFraction(beta, alpha)
  7902  		ff = prg.takeFraction(ff, ff)
  7903  		beta = prg.takeFraction(beta, ff) / 010000 // convert |fraction| to |scaled|
  7904  		denom = prg.takeFraction(gamma, alpha) + ff/1365 - beta
  7905  		// $1365\approx 2^[12]/3$
  7906  		num = prg.takeFraction(gamma, 06000000000-alpha) + beta
  7907  	}
  7908  	if num >= denom+denom+denom+denom {
  7909  		r = 010000000000
  7910  	} else {
  7911  		r = prg.makeFraction(num, denom)
  7912  	}
  7913  	return r
  7914  }
  7915  
  7916  func (prg *prg) setControls(p, q halfword, k int32) {
  7917  	var (
  7918  		rr, ss fraction // velocities, divided by thrice the tension
  7919  		lt, rt scaled   // tensions
  7920  		sine   fraction // $\sin(\theta+\phi)$
  7921  	)
  7922  	lt = abs(*prg.mem[int32(q)+4].int())
  7923  	rt = abs(*prg.mem[int32(p)+6].int())
  7924  	rr = prg.velocity(prg.st, prg.ct, prg.sf, prg.cf, rt)
  7925  	ss = prg.velocity(prg.sf, prg.cf, prg.st, prg.ct, lt)
  7926  	if *prg.mem[int32(p)+6].int() < 0 || *prg.mem[int32(q)+4].int() < 0 {
  7927  		if prg.st >= 0 && prg.sf >= 0 || prg.st <= 0 && prg.sf <= 0 {
  7928  			sine = prg.takeFraction(abs(prg.st), prg.cf) + prg.takeFraction(abs(prg.sf), prg.ct)
  7929  			if sine > 0 {
  7930  				sine = prg.takeFraction(sine, 02000000000+0200000) // safety factor
  7931  				if *prg.mem[int32(p)+6].int() < 0 {
  7932  					if prg.abVsCd(abs(prg.sf), 02000000000, rr, sine) < 0 {
  7933  						rr = prg.makeFraction(abs(prg.sf), sine)
  7934  					}
  7935  				}
  7936  				if *prg.mem[int32(q)+4].int() < 0 {
  7937  					if prg.abVsCd(abs(prg.st), 02000000000, ss, sine) < 0 {
  7938  						ss = prg.makeFraction(abs(prg.st), sine)
  7939  					}
  7940  				}
  7941  			}
  7942  		}
  7943  	}
  7944  	*prg.mem[int32(p)+5].int() = *prg.mem[int32(p)+1].int() + prg.takeFraction(prg.takeFraction(prg.deltaX[k], prg.ct)-prg.takeFraction(prg.deltaY[k], prg.st), rr)
  7945  	*prg.mem[int32(p)+6].int() = *prg.mem[int32(p)+2].int() + prg.takeFraction(prg.takeFraction(prg.deltaY[k], prg.ct)+prg.takeFraction(prg.deltaX[k], prg.st), rr)
  7946  	*prg.mem[int32(q)+3].int() = *prg.mem[int32(q)+1].int() - prg.takeFraction(prg.takeFraction(prg.deltaX[k], prg.cf)+prg.takeFraction(prg.deltaY[k], prg.sf), ss)
  7947  	*prg.mem[int32(q)+4].int() = *prg.mem[int32(q)+2].int() - prg.takeFraction(prg.takeFraction(prg.deltaY[k], prg.cf)-prg.takeFraction(prg.deltaX[k], prg.sf), ss)
  7948  	*(*prg.mem[p].hh()).b1() = byte(explicit)
  7949  	*(*prg.mem[q].hh()).b0() = byte(explicit)
  7950  }
  7951  
  7952  func (prg *prg) solveChoices(p, q halfword, n halfword) {
  7953  	var (
  7954  		k/* 0..pathSize */ uint16          // current knot number
  7955  		r1, s, t                  halfword // registers for list traversal
  7956  
  7957  		// Other local variables for |solve_choices|
  7958  		aa, bb, cc, ff, acc fraction // temporary registers
  7959  		dd, ee              scaled   // likewise, but |scaled|
  7960  		lt, rt              scaled   // tension values
  7961  	)
  7962  	k = 0
  7963  	s = p
  7964  	for true {
  7965  		t = *(*prg.mem[s].hh()).rh()
  7966  		if int32(k) == 0 {
  7967  			switch *(*prg.mem[s].hh()).b1() {
  7968  			case given:
  7969  				if int32(*(*prg.mem[t].hh()).b0()) == given {
  7970  					aa = prg.nArg(prg.deltaX[0], prg.deltaY[0])
  7971  
  7972  					prg.nSinCos(*prg.mem[int32(p)+5].int() - aa)
  7973  					prg.ct = prg.nCos
  7974  					prg.st = prg.nSin
  7975  
  7976  					prg.nSinCos(*prg.mem[int32(q)+3].int() - aa)
  7977  					prg.cf = prg.nCos
  7978  					prg.sf = -prg.nSin
  7979  
  7980  					prg.setControls(p, q, 0)
  7981  					goto exit
  7982  				} else {
  7983  					// Set up the equation for a given value of $\theta_0$
  7984  					prg.vv[0] = *prg.mem[int32(s)+5].int() - prg.nArg(prg.deltaX[0], prg.deltaY[0])
  7985  					if abs(prg.vv[0]) > 01320000000 {
  7986  						if prg.vv[0] > 0 {
  7987  							prg.vv[0] = prg.vv[0] - 02640000000
  7988  						} else {
  7989  							prg.vv[0] = prg.vv[0] + 02640000000
  7990  						}
  7991  					}
  7992  					prg.uu[0] = 0
  7993  					prg.ww[0] = 0
  7994  				}
  7995  
  7996  			case curl:
  7997  				if int32(*(*prg.mem[t].hh()).b0()) == curl {
  7998  					*(*prg.mem[p].hh()).b1() = byte(explicit)
  7999  					*(*prg.mem[q].hh()).b0() = byte(explicit)
  8000  					lt = abs(*prg.mem[int32(q)+4].int())
  8001  					rt = abs(*prg.mem[int32(p)+6].int())
  8002  					if rt == 0200000 {
  8003  						if prg.deltaX[0] >= 0 {
  8004  							*prg.mem[int32(p)+5].int() = *prg.mem[int32(p)+1].int() + (prg.deltaX[0]+1)/3
  8005  						} else {
  8006  							*prg.mem[int32(p)+5].int() = *prg.mem[int32(p)+1].int() + (prg.deltaX[0]-1)/3
  8007  						}
  8008  						if prg.deltaY[0] >= 0 {
  8009  							*prg.mem[int32(p)+6].int() = *prg.mem[int32(p)+2].int() + (prg.deltaY[0]+1)/3
  8010  						} else {
  8011  							*prg.mem[int32(p)+6].int() = *prg.mem[int32(p)+2].int() + (prg.deltaY[0]-1)/3
  8012  						}
  8013  					} else {
  8014  						ff = prg.makeFraction(0200000, 3*rt) // $\alpha/3$
  8015  						*prg.mem[int32(p)+5].int() = *prg.mem[int32(p)+1].int() + prg.takeFraction(prg.deltaX[0], ff)
  8016  						*prg.mem[int32(p)+6].int() = *prg.mem[int32(p)+2].int() + prg.takeFraction(prg.deltaY[0], ff)
  8017  					}
  8018  					if lt == 0200000 {
  8019  						if prg.deltaX[0] >= 0 {
  8020  							*prg.mem[int32(q)+3].int() = *prg.mem[int32(q)+1].int() - (prg.deltaX[0]+1)/3
  8021  						} else {
  8022  							*prg.mem[int32(q)+3].int() = *prg.mem[int32(q)+1].int() - (prg.deltaX[0]-1)/3
  8023  						}
  8024  						if prg.deltaY[0] >= 0 {
  8025  							*prg.mem[int32(q)+4].int() = *prg.mem[int32(q)+2].int() - (prg.deltaY[0]+1)/3
  8026  						} else {
  8027  							*prg.mem[int32(q)+4].int() = *prg.mem[int32(q)+2].int() - (prg.deltaY[0]-1)/3
  8028  						}
  8029  					} else {
  8030  						ff = prg.makeFraction(0200000, 3*lt) // $\beta/3$
  8031  						*prg.mem[int32(q)+3].int() = *prg.mem[int32(q)+1].int() - prg.takeFraction(prg.deltaX[0], ff)
  8032  						*prg.mem[int32(q)+4].int() = *prg.mem[int32(q)+2].int() - prg.takeFraction(prg.deltaY[0], ff)
  8033  					}
  8034  
  8035  					goto exit
  8036  				} else {
  8037  					// Set up the equation for a curl at $\theta_0$
  8038  					cc = *prg.mem[int32(s)+5].int()
  8039  					lt = abs(*prg.mem[int32(t)+4].int())
  8040  					rt = abs(*prg.mem[int32(s)+6].int())
  8041  					if rt == 0200000 && lt == 0200000 {
  8042  						prg.uu[0] = prg.makeFraction(cc+cc+0200000, cc+0400000)
  8043  					} else {
  8044  						prg.uu[0] = prg.curlRatio(cc, rt, lt)
  8045  					}
  8046  					prg.vv[0] = -prg.takeFraction(prg.psi[1-1], prg.uu[0])
  8047  					prg.ww[0] = 0
  8048  				}
  8049  
  8050  			case open:
  8051  				prg.uu[0] = 0
  8052  				prg.vv[0] = 0
  8053  				prg.ww[0] = 02000000000
  8054  				// this begins a cycle
  8055  			}
  8056  		} else {
  8057  			switch *(*prg.mem[s].hh()).b0() {
  8058  			case endCycle, open:
  8059  				// Set up equation to match mock curvatures at $z_k$; then |goto found| with $\theta_n$ adjusted to equal $\theta_0$, if a cycle has ended
  8060  				if abs(*prg.mem[int32(r1)+6].int()) == 0200000 {
  8061  					aa = 01000000000
  8062  					dd = 2 * prg.delta[k]
  8063  				} else {
  8064  					aa = prg.makeFraction(0200000, 3*abs(*prg.mem[int32(r1)+6].int())-0200000)
  8065  					dd = prg.takeFraction(prg.delta[k],
  8066  						06000000000-prg.makeFraction(0200000, abs(*prg.mem[int32(r1)+6].int())))
  8067  				}
  8068  				if abs(*prg.mem[int32(t)+4].int()) == 0200000 {
  8069  					bb = 01000000000
  8070  					ee = 2 * prg.delta[int32(k)-1]
  8071  				} else {
  8072  					bb = prg.makeFraction(0200000, 3*abs(*prg.mem[int32(t)+4].int())-0200000)
  8073  					ee = prg.takeFraction(prg.delta[int32(k)-1],
  8074  						06000000000-prg.makeFraction(0200000, abs(*prg.mem[int32(t)+4].int())))
  8075  				}
  8076  				cc = 02000000000 - prg.takeFraction(prg.uu[int32(k)-1], aa)
  8077  
  8078  				// Calculate the ratio $\\[ff]=C_k/(C_k+B_k-u_[k-1]A_k)$
  8079  				dd = prg.takeFraction(dd, cc)
  8080  				lt = abs(*prg.mem[int32(s)+4].int())
  8081  				rt = abs(*prg.mem[int32(s)+6].int())
  8082  				if lt != rt {
  8083  					if lt < rt {
  8084  						ff = prg.makeFraction(lt, rt)
  8085  						ff = prg.takeFraction(ff, ff) // $\alpha_k^2/\beta_k^2$
  8086  						dd = prg.takeFraction(dd, ff)
  8087  					} else {
  8088  						ff = prg.makeFraction(rt, lt)
  8089  						ff = prg.takeFraction(ff, ff) // $\beta_k^2/\alpha_k^2$
  8090  						ee = prg.takeFraction(ee, ff)
  8091  					}
  8092  				}
  8093  				ff = prg.makeFraction(ee, ee+dd)
  8094  				prg.uu[k] = prg.takeFraction(ff, bb)
  8095  
  8096  				// Calculate the values of $v_k$ and $w_k$
  8097  				acc = -prg.takeFraction(prg.psi[int32(k)+1-1], prg.uu[k])
  8098  				if int32(*(*prg.mem[r1].hh()).b1()) == curl {
  8099  					prg.ww[k] = 0
  8100  					prg.vv[k] = acc - prg.takeFraction(prg.psi[1-1], 02000000000-ff)
  8101  				} else {
  8102  					ff = prg.makeFraction(02000000000-ff, cc) // this is
  8103  					//     $B_k/(C_k+B_k-u_[k-1]A_k)<5$
  8104  
  8105  					acc = acc - prg.takeFraction(prg.psi[k-1], ff)
  8106  					ff = prg.takeFraction(ff, aa) // this is $A_k/(C_k+B_k-u_[k-1]A_k)$
  8107  					prg.vv[k] = acc - prg.takeFraction(prg.vv[int32(k)-1], ff)
  8108  					if prg.ww[int32(k)-1] == 0 {
  8109  						prg.ww[k] = 0
  8110  					} else {
  8111  						prg.ww[k] = -prg.takeFraction(prg.ww[int32(k)-1], ff)
  8112  					}
  8113  				}
  8114  				if int32(*(*prg.mem[s].hh()).b0()) == endCycle {
  8115  					aa = 0
  8116  					bb = 02000000000 // we have |k=n|
  8117  					for {
  8118  						k = uint16(int32(k) - 1)
  8119  						if int32(k) == 0 {
  8120  							k = n
  8121  						}
  8122  						aa = prg.vv[k] - prg.takeFraction(aa, prg.uu[k])
  8123  						bb = prg.ww[k] - prg.takeFraction(bb, prg.uu[k])
  8124  						if int32(k) == int32(n) {
  8125  							break
  8126  						}
  8127  					} // now $\theta_n=\\[aa]+\\[bb]\cdot\theta_n$
  8128  					aa = prg.makeFraction(aa, 02000000000-bb)
  8129  					prg.theta[n] = aa
  8130  					prg.vv[0] = aa
  8131  					for ii := int32(1); ii <= int32(n)-1; ii++ {
  8132  						k = uint16(ii)
  8133  						_ = k
  8134  						prg.vv[k] = prg.vv[k] + prg.takeFraction(aa, prg.ww[k])
  8135  					}
  8136  
  8137  					goto found
  8138  				}
  8139  
  8140  			case curl:
  8141  				// Set up equation for a curl at $\theta_n$ and |goto found|
  8142  				cc = *prg.mem[int32(s)+3].int()
  8143  				lt = abs(*prg.mem[int32(s)+4].int())
  8144  				rt = abs(*prg.mem[int32(r1)+6].int())
  8145  				if rt == 0200000 && lt == 0200000 {
  8146  					ff = prg.makeFraction(cc+cc+0200000, cc+0400000)
  8147  				} else {
  8148  					ff = prg.curlRatio(cc, lt, rt)
  8149  				}
  8150  				prg.theta[n] = -prg.makeFraction(prg.takeFraction(prg.vv[int32(n)-1], ff),
  8151  					02000000000-prg.takeFraction(ff, prg.uu[int32(n)-1]))
  8152  
  8153  				goto found
  8154  
  8155  			case given:
  8156  				// Calculate the given value of $\theta_n$ and |goto found|
  8157  				prg.theta[n] = *prg.mem[int32(s)+3].int() - prg.nArg(prg.deltaX[int32(n)-1], prg.deltaY[int32(n)-1])
  8158  				if abs(prg.theta[n]) > 01320000000 {
  8159  					if prg.theta[n] > 0 {
  8160  						prg.theta[n] = prg.theta[n] - 02640000000
  8161  					} else {
  8162  						prg.theta[n] = prg.theta[n] + 02640000000
  8163  					}
  8164  				}
  8165  
  8166  				goto found
  8167  
  8168  			}
  8169  		} // there are no other cases
  8170  		r1 = s
  8171  		s = t
  8172  		k = uint16(int32(k) + 1)
  8173  	}
  8174  
  8175  found:
  8176  	for ii := int32(n) - 1; ii >= 0; ii-- {
  8177  		k = uint16(ii)
  8178  		_ = k
  8179  		prg.theta[k] = prg.vv[k] - prg.takeFraction(prg.theta[int32(k)+1], prg.uu[k])
  8180  	}
  8181  	s = p
  8182  	k = 0
  8183  	for {
  8184  		t = *(*prg.mem[s].hh()).rh()
  8185  
  8186  		prg.nSinCos(prg.theta[k])
  8187  		prg.st = prg.nSin
  8188  		prg.ct = prg.nCos
  8189  
  8190  		prg.nSinCos(-prg.psi[int32(k)+1-1] - prg.theta[int32(k)+1])
  8191  		prg.sf = prg.nSin
  8192  		prg.cf = prg.nCos
  8193  
  8194  		prg.setControls(s, t, int32(k))
  8195  
  8196  		k = uint16(int32(k) + 1)
  8197  		s = t
  8198  		if int32(k) == int32(n) {
  8199  			break
  8200  		}
  8201  	}
  8202  
  8203  exit:
  8204  }
  8205  
  8206  func (prg *prg) makeChoices(knots halfword) {
  8207  	var (
  8208  		h    halfword // the first breakpoint
  8209  		p, q halfword // consecutive breakpoints being processed
  8210  
  8211  		// Other local variables for |make_choices|
  8212  		k, n/* 0..pathSize */ uint16          // current and final knot numbers
  8213  		s, t                         halfword // registers for list traversal
  8214  		delx, dely                   scaled   // directions where |open| meets |explicit|
  8215  		sine, cosine                 fraction // trig functions of various angles
  8216  	)
  8217  	{
  8218  		if prg.arithError {
  8219  			prg.clearArith()
  8220  		}
  8221  	} // make sure that |arith_error=false|
  8222  	if prg.internal[tracingChoices-1] > 0 {
  8223  		prg.printPath(knots, strNumber( /* ", before choices" */ 526), true)
  8224  	}
  8225  
  8226  	// If consecutive knots are equal, join them explicitly
  8227  	p = knots
  8228  	for {
  8229  		q = *(*prg.mem[p].hh()).rh()
  8230  		if *prg.mem[int32(p)+1].int() == *prg.mem[int32(q)+1].int() {
  8231  			if *prg.mem[int32(p)+2].int() == *prg.mem[int32(q)+2].int() {
  8232  				if int32(*(*prg.mem[p].hh()).b1()) > explicit {
  8233  					*(*prg.mem[p].hh()).b1() = byte(explicit)
  8234  					if int32(*(*prg.mem[p].hh()).b0()) == open {
  8235  						*(*prg.mem[p].hh()).b0() = byte(curl)
  8236  						*prg.mem[int32(p)+3].int() = 0200000
  8237  					}
  8238  					*(*prg.mem[q].hh()).b0() = byte(explicit)
  8239  					if int32(*(*prg.mem[q].hh()).b1()) == open {
  8240  						*(*prg.mem[q].hh()).b1() = byte(curl)
  8241  						*prg.mem[int32(q)+5].int() = 0200000
  8242  					}
  8243  					*prg.mem[int32(p)+5].int() = *prg.mem[int32(p)+1].int()
  8244  					*prg.mem[int32(q)+3].int() = *prg.mem[int32(p)+1].int()
  8245  
  8246  					*prg.mem[int32(p)+6].int() = *prg.mem[int32(p)+2].int()
  8247  					*prg.mem[int32(q)+4].int() = *prg.mem[int32(p)+2].int()
  8248  				}
  8249  			}
  8250  		}
  8251  		p = q
  8252  		if int32(p) == int32(knots) {
  8253  			break
  8254  		}
  8255  	}
  8256  
  8257  	// Find the first breakpoint, |h|, on the path; insert an artificial breakpoint if the path is an unbroken cycle
  8258  	h = knots
  8259  	for true {
  8260  		if int32(*(*prg.mem[h].hh()).b0()) != open {
  8261  			goto done
  8262  		}
  8263  		if int32(*(*prg.mem[h].hh()).b1()) != open {
  8264  			goto done
  8265  		}
  8266  		h = *(*prg.mem[h].hh()).rh()
  8267  		if int32(h) == int32(knots) {
  8268  			*(*prg.mem[h].hh()).b0() = byte(endCycle)
  8269  			goto done
  8270  		}
  8271  	}
  8272  
  8273  done:
  8274  	;
  8275  	p = h
  8276  	for {
  8277  		// Fill in the control points between |p| and the next breakpoint, then advance |p| to that breakpoint
  8278  		q = *(*prg.mem[p].hh()).rh()
  8279  		if int32(*(*prg.mem[p].hh()).b1()) >= given {
  8280  			for int32(*(*prg.mem[q].hh()).b0()) == open && int32(*(*prg.mem[q].hh()).b1()) == open {
  8281  				q = *(*prg.mem[q].hh()).rh()
  8282  			}
  8283  
  8284  			// Fill in the control information between consecutive breakpoints |p| and |q|
  8285  
  8286  			// Calculate the turning angles $\psi_k$ and the distances $d_[k,k+1]$; set $n$ to the length of the path
  8287  			k = 0
  8288  			s = p
  8289  			n = uint16(pathSize)
  8290  			for {
  8291  				t = *(*prg.mem[s].hh()).rh()
  8292  				prg.deltaX[k] = *prg.mem[int32(t)+1].int() - *prg.mem[int32(s)+1].int()
  8293  				prg.deltaY[k] = *prg.mem[int32(t)+2].int() - *prg.mem[int32(s)+2].int()
  8294  				prg.delta[k] = prg.pythAdd(prg.deltaX[k], prg.deltaY[k])
  8295  				if int32(k) > 0 {
  8296  					sine = prg.makeFraction(prg.deltaY[int32(k)-1], prg.delta[int32(k)-1])
  8297  					cosine = prg.makeFraction(prg.deltaX[int32(k)-1], prg.delta[int32(k)-1])
  8298  					prg.psi[k-1] = prg.nArg(prg.takeFraction(prg.deltaX[k], cosine)+prg.takeFraction(prg.deltaY[k], sine), prg.takeFraction(prg.deltaY[k], cosine)-prg.takeFraction(prg.deltaX[k], sine))
  8299  				}
  8300  				// \xref[METAFONT capacity exceeded path size][\quad path size]
  8301  				k = uint16(int32(k) + 1)
  8302  				s = t
  8303  				if int32(k) == pathSize {
  8304  					prg.overflow(strNumber( /* "path size" */ 531), pathSize)
  8305  				}
  8306  				if int32(s) == int32(q) {
  8307  					n = k
  8308  				}
  8309  				if int32(k) >= int32(n) && int32(*(*prg.mem[s].hh()).b0()) != endCycle {
  8310  					break
  8311  				}
  8312  			}
  8313  			if int32(k) == int32(n) {
  8314  				prg.psi[n-1] = 0
  8315  			} else {
  8316  				prg.psi[k-1] = prg.psi[1-1]
  8317  			}
  8318  
  8319  			// Remove |open| types at the breakpoints
  8320  			if int32(*(*prg.mem[q].hh()).b0()) == open {
  8321  				delx = *prg.mem[int32(q)+5].int() - *prg.mem[int32(q)+1].int()
  8322  				dely = *prg.mem[int32(q)+6].int() - *prg.mem[int32(q)+2].int()
  8323  				if delx == 0 && dely == 0 {
  8324  					*(*prg.mem[q].hh()).b0() = byte(curl)
  8325  					*prg.mem[int32(q)+3].int() = 0200000
  8326  				} else {
  8327  					*(*prg.mem[q].hh()).b0() = byte(given)
  8328  					*prg.mem[int32(q)+3].int() = prg.nArg(delx, dely)
  8329  				}
  8330  			}
  8331  			if int32(*(*prg.mem[p].hh()).b1()) == open && int32(*(*prg.mem[p].hh()).b0()) == explicit {
  8332  				delx = *prg.mem[int32(p)+1].int() - *prg.mem[int32(p)+3].int()
  8333  				dely = *prg.mem[int32(p)+2].int() - *prg.mem[int32(p)+4].int()
  8334  				if delx == 0 && dely == 0 {
  8335  					*(*prg.mem[p].hh()).b1() = byte(curl)
  8336  					*prg.mem[int32(p)+5].int() = 0200000
  8337  				} else {
  8338  					*(*prg.mem[p].hh()).b1() = byte(given)
  8339  					*prg.mem[int32(p)+5].int() = prg.nArg(delx, dely)
  8340  				}
  8341  			}
  8342  			prg.solveChoices(p, q, n)
  8343  		}
  8344  		p = q
  8345  		if int32(p) == int32(h) {
  8346  			break
  8347  		}
  8348  	}
  8349  	if prg.internal[tracingChoices-1] > 0 {
  8350  		prg.printPath(knots, strNumber( /* ", after choices" */ 527), true)
  8351  	}
  8352  	if prg.arithError {
  8353  		{
  8354  			if int32(prg.interaction) == errorStopMode {
  8355  			}
  8356  			prg.printNl(strNumber( /* "! " */ 261))
  8357  			prg.print( /* "Some number got too big" */ 528) /* \xref[!\relax]  */
  8358  		}
  8359  		// \xref[Some number got too big]
  8360  		{
  8361  			prg.helpPtr = 2
  8362  			prg.helpLine[1] = /* "The path that I just computed is out of range." */ 529
  8363  			prg.helpLine[0] = /* "So it will probably look funny. Proceed, for a laugh." */ 530
  8364  		}
  8365  		prg.putGetError()
  8366  		prg.arithError = false
  8367  	}
  8368  }
  8369  
  8370  // 274.
  8371  
  8372  // tangle:pos ../../mf.web:6025:3:
  8373  
  8374  // Before we can go further into the way choices are made, we need to
  8375  // consider the underlying theory. The basic ideas implemented in |make_choices|
  8376  // are due to John Hobby, who introduced the notion of ``mock curvature''
  8377  // \xref[Hobby, John Douglas]
  8378  // at a knot. Angles are chosen so that they preserve mock curvature when
  8379  // a knot is passed, and this has been found to produce excellent results.
  8380  //
  8381  // It is convenient to introduce some notations that simplify the necessary
  8382  // formulas. Let $d_[k,k+1]=\vert z\k-z_k\vert$ be the (nonzero) distance
  8383  // between knots |k| and |k+1|; and let
  8384  // $$[z\k-z_k\over z_k-z_[k-1]]=[d_[k,k+1]\over d_[k-1,k]]e^[i\psi_k]$$
  8385  // so that a polygonal line from $z_[k-1]$ to $z_k$ to $z\k$ turns left
  8386  // through an angle of~$\psi_k$. We assume that $\vert\psi_k\vert\L180^\circ$.
  8387  // The control points for the spline from $z_k$ to $z\k$ will be denoted by
  8388  // $$\eqalign[z_k^+&=z_k+
  8389  //   \textstyle[1\over3]\rho_k e^[i\theta_k](z\k-z_k),\cr
  8390  //  z\k^-&=z\k-
  8391  //   \textstyle[1\over3]\sigma\k e^[-i\phi\k](z\k-z_k),\cr]$$
  8392  // where $\rho_k$ and $\sigma\k$ are nonnegative ``velocity ratios'' at the
  8393  // beginning and end of the curve, while $\theta_k$ and $\phi\k$ are the
  8394  // corresponding ``offset angles.'' These angles satisfy the condition
  8395  // $$\theta_k+\phi_k+\psi_k=0,\eqno(*)$$
  8396  // whenever the curve leaves an intermediate knot~|k| in the direction that
  8397  // it enters.
  8398  
  8399  // 275.
  8400  
  8401  // tangle:pos ../../mf.web:6050:3:
  8402  
  8403  // Let $\alpha_k$ and $\beta\k$ be the reciprocals of the ``tension'' of
  8404  // the curve at its beginning and ending points. This means that
  8405  // $\rho_k=\alpha_k f(\theta_k,\phi\k)$ and $\sigma\k=\beta\k f(\phi\k,\theta_k)$,
  8406  // where $f(\theta,\phi)$ is \MF's standard velocity function defined in
  8407  // the |velocity| subroutine. The cubic spline $B(z_k^[\phantom+],z_k^+,
  8408  // z\k^-,z\k^[\phantom+];t)$
  8409  // has curvature
  8410  // \xref[curvature]
  8411  // $$[2\sigma\k\sin(\theta_k+\phi\k)-6\sin\theta_k\over\rho_k^2d_[k,k+1]]
  8412  // \qquad[\rm and]\qquad
  8413  // [2\rho_k\sin(\theta_k+\phi\k)-6\sin\phi\k\over\sigma\k^2d_[k,k+1]]$$
  8414  // at |t=0| and |t=1|, respectively. The mock curvature is the linear
  8415  // \xref[mock curvature]
  8416  // approximation to this true curvature that arises in the limit for
  8417  // small $\theta_k$ and~$\phi\k$, if second-order terms are discarded.
  8418  // The standard velocity function satisfies
  8419  // $$f(\theta,\phi)=1+O(\theta^2+\theta\phi+\phi^2);$$
  8420  // hence the mock curvatures are respectively
  8421  // $$[2\beta\k(\theta_k+\phi\k)-6\theta_k\over\alpha_k^2d_[k,k+1]]
  8422  // \qquad[\rm and]\qquad
  8423  // [2\alpha_k(\theta_k+\phi\k)-6\phi\k\over\beta\k^2d_[k,k+1]].\eqno(**)$$
  8424  
  8425  // 276.
  8426  
  8427  // tangle:pos ../../mf.web:6072:3:
  8428  
  8429  // The turning angles $\psi_k$ are given, and equation $(*)$ above
  8430  // determines $\phi_k$ when $\theta_k$ is known, so the task of
  8431  // angle selection is essentially to choose appropriate values for each
  8432  // $\theta_k$. When equation~$(*)$ is used to eliminate $\phi$~variables
  8433  // from $(**)$, we obtain a system of linear equations of the form
  8434  // $$A_k\theta_[k-1]+(B_k+C_k)\theta_k+D_k\theta\k=-B_k\psi_k-D_k\psi\k,$$
  8435  // where
  8436  // $$A_k=[\alpha_[k-1]\over\beta_k^2d_[k-1,k]],
  8437  // \qquad B_k=[3-\alpha_[k-1]\over\beta_k^2d_[k-1,k]],
  8438  // \qquad C_k=[3-\beta\k\over\alpha_k^2d_[k,k+1]],
  8439  // \qquad D_k=[\beta\k\over\alpha_k^2d_[k,k+1]].$$
  8440  // The tensions are always $3\over4$ or more, hence each $\alpha$ and~$\beta$
  8441  // will be at most $4\over3$. It follows that $B_k\G[5\over4]A_k$ and
  8442  // $C_k\G[5\over4]D_k$; hence the equations are diagonally dominant;
  8443  // hence they have a unique solution. Moreover, in most cases the tensions
  8444  // are equal to~1, so that $B_k=2A_k$ and $C_k=2D_k$. This makes the
  8445  // solution numerically stable, and there is an exponential damping
  8446  // effect: The data at knot $k\pm j$ affects the angle at knot~$k$ by
  8447  // a factor of~$O(2^[-j])$.
  8448  
  8449  // 277.
  8450  
  8451  // tangle:pos ../../mf.web:6092:3:
  8452  
  8453  // However, we still must consider the angles at the starting and ending
  8454  // knots of a non-cyclic path. These angles might be given explicitly, or
  8455  // they might be specified implicitly in terms of an amount of ``curl.''
  8456  //
  8457  // Let's assume that angles need to be determined for a non-cyclic path
  8458  // starting at $z_0$ and ending at~$z_n$. Then equations of the form
  8459  // $$A_k\theta_[k-1]+(B_k+C_k)\theta_k+D_k\theta_[k+1]=R_k$$
  8460  // have been given for $0<k<n$, and it will be convenient to introduce
  8461  // equations of the same form for $k=0$ and $k=n$, where
  8462  // $$A_0=B_0=C_n=D_n=0.$$
  8463  // If $\theta_0$ is supposed to have a given value $E_0$, we simply
  8464  // define $C_0=1$, $D_0=0$, and $R_0=E_0$. Otherwise a curl
  8465  // parameter, $\gamma_0$, has been specified at~$z_0$; this means
  8466  // that the mock curvature at $z_0$ should be $\gamma_0$ times the
  8467  // mock curvature at $z_1$; i.e.,
  8468  // $$[2\beta_1(\theta_0+\phi_1)-6\theta_0\over\alpha_0^2d_[01]]
  8469  // =\gamma_0[2\alpha_0(\theta_0+\phi_1)-6\phi_1\over\beta_1^2d_[01]].$$
  8470  // This equation simplifies to
  8471  // $$(\alpha_0\chi_0+3-\beta_1)\theta_0+
  8472  //  \bigl((3-\alpha_0)\chi_0+\beta_1\bigr)\theta_1=
  8473  //  -\bigl((3-\alpha_0)\chi_0+\beta_1\bigr)\psi_1,$$
  8474  // where $\chi_0=\alpha_0^2\gamma_0/\beta_1^2$; so we can set $C_0=
  8475  // \chi_0\alpha_0+3-\beta_1$, $D_0=(3-\alpha_0)\chi_0+\beta_1$, $R_0=-D_0\psi_1$.
  8476  // It can be shown that $C_0>0$ and $C_0B_1-A_1D_0>0$ when $\gamma_0\G0$,
  8477  // hence the linear equations remain nonsingular.
  8478  //
  8479  // Similar considerations apply at the right end, when the final angle $\phi_n$
  8480  // may or may not need to be determined. It is convenient to let $\psi_n=0$,
  8481  // hence $\theta_n=-\phi_n$. We either have an explicit equation $\theta_n=E_n$,
  8482  // or we have
  8483  // $$\bigl((3-\beta_n)\chi_n+\alpha_[n-1]\bigr)\theta_[n-1]+
  8484  // (\beta_n\chi_n+3-\alpha_[n-1])\theta_n=0,\qquad
  8485  //   \chi_n=[\beta_n^2\gamma_n\over\alpha_[n-1]^2].$$
  8486  //
  8487  // When |make_choices| chooses angles, it must compute the coefficients of
  8488  // these linear equations, then solve the equations. To compute the coefficients,
  8489  // it is necessary to compute arctangents of the given turning angles~$\psi_k$.
  8490  // When the equations are solved, the chosen directions $\theta_k$ are put
  8491  // back into the form of control points by essentially computing sines and
  8492  // cosines.
  8493  
  8494  // 303. \[19] Generating discrete moves
  8495  
  8496  // tangle:pos ../../mf.web:6573:36:
  8497  
  8498  // The purpose of the next part of \MF\ is to compute discrete approximations
  8499  // to curves described as parametric polynomial functions $z(t)$.
  8500  // We shall start with the low level first, because an efficient ``engine''
  8501  // is needed to support the high-level constructions.
  8502  //
  8503  // Most of the subroutines are based on variations of a single theme,
  8504  // namely the idea of [\sl bisection]. Given a Bernshte[\u\i]n polynomial
  8505  // \xref[Bernshte[\u\i]n, Serge[\u\i] Natanovich]
  8506  // $$B(z_0,z_1,\ldots,z_n;t)=\sum_k[n\choose k]t^k(1-t)^[n-k]z_k,$$
  8507  // we can conveniently bisect its range as follows:
  8508  //
  8509  // \smallskip
  8510  // \textindent[1)] Let $z_k^[(0)]=z_k$, for |0<=k<=n|.
  8511  //
  8512  // \smallskip
  8513  // \textindent[2)] Let $z_k^[(j+1)]=[1\over2](z_k^[(j)]+z\k^[(j)])$, for
  8514  // |0<=k<n-j|, for |0<=j<n|.
  8515  //
  8516  // \smallskip\noindent
  8517  // Then
  8518  // $$B(z_0,z_1,\ldots,z_n;t)=B(z_0^[(0)],z_0^[(1)],\ldots,z_0^[(n)];2t)
  8519  //  =B(z_0^[(n)],z_1^[(n-1)],\ldots,z_n^[(0)];2t-1).$$
  8520  // This formula gives us the coefficients of polynomials to use over the ranges
  8521  // $0\L t\L[1\over2]$ and $[1\over2]\L t\L1$.
  8522  //
  8523  // In our applications it will usually be possible to work indirectly with
  8524  // numbers that allow us to deduce relevant properties of the polynomials
  8525  // without actually computing the polynomial values. We will deal with
  8526  // coefficients $Z_k=2^l(z_k-z_[k-1])$ for |1<=k<=n|, instead of
  8527  // the actual numbers $z_0$, $z_1$, \dots,~$z_n$, and the value of~|l| will
  8528  // increase by~1 at each bisection step. This technique reduces the
  8529  // amount of calculation needed for bisection and also increases the
  8530  // accuracy of evaluation (since one bit of precision is gained at each
  8531  // bisection). Indeed, the bisection process now becomes one level shorter:
  8532  //
  8533  // \smallskip
  8534  // \textindent[$1'$)] Let $Z_k^[(1)]=Z_k$, for |1<=k<=n|.
  8535  //
  8536  // \smallskip
  8537  // \textindent[$2'$)] Let $Z_k^[(j+1)]=[1\over2](Z_k^[(j)]+Z\k^[(j)])$, for
  8538  // |1<=k<=n-j|, for |1<=j<n|.
  8539  //
  8540  // \smallskip\noindent
  8541  // The relevant coefficients $(Z'_1,\ldots,Z'_n)$ and $(Z''_1,\ldots,Z''_n)$
  8542  // for the two subintervals after bisection are respectively
  8543  // $(Z_1^[(1)],Z_1^[(2)],\ldots,Z_1^[(n)])$ and
  8544  // $(Z_1^[(n)],Z_2^[(n-1)],\ldots,Z_n^[(1)])$.
  8545  // And the values of $z_0$ appropriate for the bisected interval are $z'_0=z_0$
  8546  // and $z''_0=z_0+(Z'_1+Z'_2+\cdots+Z'_n)/2^[l+1]$.
  8547  //
  8548  // Step $2'$ involves division by~2, which introduces computational errors
  8549  // of at most $1\over2$ at each step; thus after $l$~levels of bisection the
  8550  // integers $Z_k$ will differ from their true values by at most $(n-1)l/2$.
  8551  // This error rate is quite acceptable, considering that we have $l$~more
  8552  // bits of precision in the $Z$'s by comparison with the~$z$'s.  Note also
  8553  // that the $Z$'s remain bounded; there's no danger of integer overflow, even
  8554  // though we have the identity $Z_k=2^l(z_k-z_[k-1])$ for arbitrarily large~$l$.
  8555  //
  8556  // In fact, we can show not only that the $Z$'s remain bounded, but also that
  8557  // they become nearly equal, since they are control points for a polynomial
  8558  // of one less degree. If $\vert Z\k-Z_k\vert\L M$ initially, it is possible
  8559  // to prove that $\vert Z\k-Z_k\vert\L\lceil M/2^l\rceil$ after $l$~levels
  8560  // of bisection, even in the presence of rounding errors. Here's the
  8561  // proof [cf.~Lane and Riesenfeld, [\sl IEEE Trans.\ on Pattern Analysis
  8562  // \xref[Lane, Jeffrey Michael]
  8563  // \xref[Riesenfeld, Richard Franklin]
  8564  // and Machine Intelligence\/ \bf PAMI-2] (1980), 35--46]: Assuming that
  8565  // $\vert Z\k-Z_k\vert\L M$ before bisection, we want to prove that
  8566  // $\vert Z\k-Z_k\vert\L\lceil M/2\rceil$ afterward. First we show that
  8567  // $\vert Z\k^[(j)]-Z_k^[(j)]\vert\L M$ for all $j$ and~$k$, by induction
  8568  // on~$j$; this follows from the fact that
  8569  // $$\bigl\vert\\[half](a+b)-\\[half](b+c)\bigr\vert\L
  8570  //  \max\bigl(\vert a-b\vert,\vert b-c\vert\bigr)$$
  8571  // holds for both of the rounding rules $\\[half](x)=\lfloor x/2\rfloor$
  8572  // and $\\[half](x)=[\rm sign](x)\lfloor\vert x/2\vert\rfloor$.
  8573  // (If $\vert a-b\vert$ and $\vert b-c\vert$ are equal, then
  8574  // $a+b$ and $b+c$ are both even or both odd. The rounding errors either
  8575  // cancel or round the numbers toward each other; hence
  8576  // $$\eqalign[\bigl\vert\\[half](a+b)-\\[half](b+c)\bigr\vert
  8577  // &\L\textstyle\bigl\vert[1\over2](a+b)-[1\over2](b+c)\bigr\vert\cr
  8578  // &=\textstyle\bigl\vert[1\over2](a-b)+[1\over2](b-c)\bigr\vert
  8579  // \L\max\bigl(\vert a-b\vert,\vert b-c\vert\bigr),\cr]$$
  8580  // as required. A simpler argument applies if $\vert a-b\vert$ and
  8581  // $\vert b-c\vert$ are unequal.)  Now it is easy to see that
  8582  // $\vert Z_1^[(j+1)]-Z_1^[(j)]\vert\L\bigl\lfloor[1\over2]
  8583  // \vert Z_2^[(j)]-Z_1^[(j)]\vert+[1\over2]\bigr\rfloor
  8584  // \L\bigl\lfloor[1\over2](M+1)\bigr\rfloor=\lceil M/2\rceil$.
  8585  //
  8586  // Another interesting fact about bisection is the identity
  8587  // $$Z_1'+\cdots+Z_n'+Z_1''+\cdots+Z_n''=2(Z_1+\cdots+Z_n+E),$$
  8588  // where $E$ is the sum of the rounding errors in all of the halving
  8589  // operations ($\vert E\vert\L n(n-1)/4$).
  8590  
  8591  // 304.
  8592  
  8593  // tangle:pos ../../mf.web:6667:3:
  8594  
  8595  // We will later reduce the problem of digitizing a complex cubic
  8596  // $z(t)=B(z_0,z_1,z_2,z_3;t)$ to the following simpler problem:
  8597  // Given two real cubics
  8598  // $x(t)=B(x_0,x_1,x_2,x_3;t)$
  8599  // and $y(t)=B(y_0,y_1,y_2,y_3;t)$ that are monotone nondecreasing,
  8600  // determine the set of integer points
  8601  // $$P=\bigl\[\bigl(\lfloor x(t)\rfloor,\lfloor y(t)\rfloor\bigr)
  8602  // \bigm\vert 0\L t\L 1\bigr\].$$
  8603  // Well, the problem isn't actually quite so clean as this; when the path
  8604  // goes very near an integer point $(a,b)$, computational errors may
  8605  // make us think that $P$ contains $(a-1,b)$ while in reality it should
  8606  // contain $(a,b-1)$. Furthermore, if the path goes [\sl exactly\/]
  8607  // through the integer points $(a-1,b-1)$ and
  8608  // $(a,b)$, we will want $P$ to contain one
  8609  // of the two points $(a-1,b)$ or $(a,b-1)$, so that $P$ can be described
  8610  // entirely by ``rook moves'' upwards or to the right; no diagonal
  8611  // moves from $(a-1,b-1)$ to~$(a,b)$ will be allowed.
  8612  //
  8613  // Thus, the set $P$ we wish to compute will merely be an approximation
  8614  // to the set described in the formula above. It will consist of
  8615  // $\lfloor x(1)\rfloor-\lfloor x(0)\rfloor$ rightward moves and
  8616  // $\lfloor y(1)\rfloor-\lfloor y(0)\rfloor$ upward moves, intermixed
  8617  // in some order. Our job will be to figure out a suitable order.
  8618  //
  8619  // The following recursive strategy suggests itself, when we recall that
  8620  // $x(0)=x_0$, $x(1)=x_3$, $y(0)=y_0$, and $y(1)=y_3$:
  8621  //
  8622  // \smallskip
  8623  // If $\lfloor x_0\rfloor=\lfloor x_3\rfloor$ then take
  8624  // $\lfloor y_3\rfloor-\lfloor y_0\rfloor$ steps up.
  8625  //
  8626  // Otherwise if $\lfloor y_0\rfloor=\lfloor y_3\rfloor$ then take
  8627  // $\lfloor x_3\rfloor-\lfloor x_0\rfloor$ steps to the right.
  8628  //
  8629  // Otherwise bisect the current cubics and repeat the process on both halves.
  8630  //
  8631  // \yskip\noindent
  8632  // This intuitively appealing formulation does not quite solve the problem,
  8633  // because it may never terminate. For example, it's not hard to see that
  8634  // no steps will [\sl ever\/] be taken if $(x_0,x_1,x_2,x_3)=(y_0,y_1,y_2,y_3)$!
  8635  // However, we can surmount this difficulty with a bit of care; so let's
  8636  // proceed to flesh out the algorithm as stated, before worrying about
  8637  // such details.
  8638  //
  8639  // The bisect-and-double strategy discussed above suggests that we represent
  8640  // $(x_0,x_1,x_2,x_3)$ by $(X_1,X_2,X_3)$, where $X_k=2^l(x_k-x_[k-1])$
  8641  // for some~$l$. Initially $l=16$, since the $x$'s are |scaled|.
  8642  // In order to deal with other aspects of the algorithm we will want to
  8643  // maintain also the quantities $m=\lfloor x_3\rfloor-\lfloor x_0\rfloor$
  8644  // and $R=2^l(x_0\bmod 1)$. Similarly,
  8645  // $(y_0,y_1,y_2,y_3)$ will be represented by $(Y_1,Y_2,Y_3)$,
  8646  // $n=\lfloor y_3\rfloor-\lfloor y_0\rfloor$,
  8647  // and $S=2^l(y_0\bmod 1)$. The algorithm now takes the following form:
  8648  //
  8649  // \smallskip
  8650  // If $m=0$ then take $n$ steps up.
  8651  //
  8652  // Otherwise if $n=0$ then take $m$ steps to the right.
  8653  //
  8654  // Otherwise bisect the current cubics and repeat the process on both halves.
  8655  //
  8656  // \smallskip\noindent
  8657  // The bisection process for $(X_1,X_2,X_3,m,R,l)$ reduces, in essence,
  8658  // to the following formulas:
  8659  // $$\vbox[\halign[$#\hfil$\cr
  8660  // X_2'=\\[half](X_1+X_2),\quad
  8661  // X_2''=\\[half](X_2+X_3),\quad
  8662  // X_3'=\\[half](X_2'+X_2''),\cr
  8663  // X_1'=X_1,\quad
  8664  // X_1''=X_3',\quad
  8665  // X_3''=X_3,\cr
  8666  // R'=2R,\quad
  8667  // T=X_1'+X_2'+X_3'+R',\quad
  8668  // R''=T\bmod 2^[l+1],\cr
  8669  // m'=\lfloor T/2^[l+1]\rfloor,\quad
  8670  // m''=m-m'.\cr]]$$
  8671  
  8672  // 305.
  8673  
  8674  // tangle:pos ../../mf.web:6744:3:
  8675  
  8676  // When $m=n=1$, the computation can be speeded up because we simply
  8677  // need to decide between two alternatives, (up,\thinspace right)
  8678  // versus (right,\thinspace up). There appears to be no simple, direct
  8679  // way to make the correct decision by looking at the values of
  8680  // $(X_1,X_2,X_3,R)$ and
  8681  // $(Y_1,Y_2,Y_3,S)$; but we can streamline the bisection process, and
  8682  // we can use the fact that only one of the two descendants needs to
  8683  // be examined after each bisection. Furthermore, we observed earlier
  8684  // that after several levels of bisection the $X$'s and $Y$'s will be nearly
  8685  // equal; so we will be justified in assuming that the curve is essentially a
  8686  // straight line. (This, incidentally, solves the problem of infinite
  8687  // recursion mentioned earlier.)
  8688  //
  8689  // It is possible to show that
  8690  // $$m=\bigl\lfloor(X_1+X_2+X_3+R+E)\,/\,2^l\bigr\rfloor,$$
  8691  // where $E$ is an accumulated rounding error that is at most
  8692  // $3\cdot(2^[l-16]-1)$ in absolute value. We will make sure that
  8693  // the $X$'s are less than $2^[28]$; hence when $l=30$ we must
  8694  // have |m<=1|. This proves that the special case $m=n=1$ is
  8695  // bound to be reached by the time $l=30$. Furthermore $l=30$ is
  8696  // a suitable time to make the straight line approximation,
  8697  // if the recursion hasn't already died out, because the maximum
  8698  // difference between $X$'s will then be $<2^[14]$; this corresponds
  8699  // to an error of $<1$ with respect to the original scaling.
  8700  // (Stating this another way, each bisection makes the curve two bits
  8701  // closer to a straight line, hence 14 bisections are sufficient for
  8702  // 28-bit accuracy.)
  8703  //
  8704  // In the case of a straight line, the curve goes first right, then up,
  8705  // if and only if $(T-2^l)(2^l-S)>(U-2^l)(2^l-R)$, where
  8706  // $T=X_1+X_2+X_3+R$ and $U=Y_1+Y_2+Y_3+S$. For the actual curve
  8707  // essentially runs from $(R/2^l,S/2^l)$ to $(T/2^l,U/2^l)$, and
  8708  // we are testing whether or not $(1,1)$ is above the straight
  8709  // line connecting these two points. (This formula assumes that $(1,1)$
  8710  // is not exactly on the line.)
  8711  
  8712  // 306.
  8713  
  8714  // tangle:pos ../../mf.web:6780:3:
  8715  
  8716  // We have glossed over the problem of tie-breaking in ambiguous
  8717  // cases when the cubic curve passes exactly through integer points.
  8718  // \MF\ finesses this problem by assuming that coordinates
  8719  // $(x,y)$ actually stand for slightly perturbed values $(x+\xi,y+\eta)$,
  8720  // where $\xi$ and~$\eta$ are infinitesimals whose signs will determine
  8721  // what to do when $x$ and/or~$y$ are exact integers. The quantities
  8722  // $\lfloor x\rfloor$ and~$\lfloor y\rfloor$ in the formulas above
  8723  // should actually read $\lfloor x+\xi\rfloor$ and $\lfloor y+\eta\rfloor$.
  8724  //
  8725  // If $x$ is a |scaled| value, we have $\lfloor x+\xi\rfloor=\lfloor x\rfloor$
  8726  // if $\xi>0$, and $\lfloor x+\xi\rfloor=\lfloor x-2^[-16]\rfloor$ if
  8727  // $\xi<0$. It is convenient to represent $\xi$ by the integer |xi_corr|,
  8728  // defined to be 0~if $\xi>0$ and 1~if $\xi<0$; then, for example, the
  8729  // integer $\lfloor x+\xi\rfloor$ can be computed as
  8730  // |floor_unscaled(x-xi_corr)|. Similarly, $\eta$ is conveniently
  8731  // represented by~|eta_corr|.
  8732  //
  8733  // In our applications the sign of $\xi-\eta$ will always be the same as
  8734  // the sign of $\xi$. Therefore it turns out that the rule for straight
  8735  // lines, as stated above, should be modified as follows in the case of
  8736  // ties: The line goes first right, then up, if and only if
  8737  // $(T-2^l)(2^l-S)+\xi>(U-2^l)(2^l-R)$. And this relation holds iff
  8738  // $|ab_vs_cd|(T-2^l,2^l-S,U-2^l,2^l-R)-|xi_corr|\ge0$.
  8739  //
  8740  // These conventions for rounding are symmetrical, in the sense that the
  8741  // digitized moves obtained from $(x_0,x_1,x_2,x_3,y_0,y_1,y_2,y_3,\xi,\eta)$
  8742  // will be exactly complementary to the moves that would be obtained from
  8743  // $(-x_3,-x_2,-x_1,-x_0,-y_3,-y_2,-y_1,-y_0,-\xi,-\eta)$, if arithmetic
  8744  // is exact. However, truncation errors in the bisection process might
  8745  // upset the symmetry. We can restore much of the lost symmetry by adding
  8746  // |xi_corr| or |eta_corr| when halving the data.
  8747  
  8748  // 307.
  8749  
  8750  // tangle:pos ../../mf.web:6812:3:
  8751  
  8752  // One further possibility needs to be mentioned: The algorithm
  8753  // will be applied only to cubic polynomials $B(x_0,x_1,x_2,x_3;t)$ that
  8754  // are nondecreasing as $t$~varies from 0 to~1; this condition turns
  8755  // out to hold if and only if $x_0\L x_1$ and $x_2\L x_3$, and either
  8756  // $x_1\L x_2$ or $(x_1-x_2)^2\L(x_1-x_0)(x_3-x_2)$. If bisection were
  8757  // carried out with perfect accuracy, these relations would remain
  8758  // invariant. But rounding errors can creep in, hence the bisection
  8759  // algorithm can produce non-monotonic subproblems from monotonic
  8760  // initial conditions. This leads to the potential danger that $m$ or~$n$
  8761  // could become negative in the algorithm described above.
  8762  //
  8763  // For example, if we start with $(x_1-x_0,x_2-x_1,x_3-x_2)=
  8764  // (X_1,X_2,X_3)=(7,-16,39)$, the corresponding polynomial is
  8765  // monotonic, because $16^2<7\cdot39$. But the bisection algorithm
  8766  // produces the left descendant $(7,-5,3)$, which is nonmonotonic;
  8767  // its right descendant is~$(0,-1,3)$.
  8768  //
  8769  // \def\xt[[\tilde x]]
  8770  // Fortunately we can prove that such rounding errors will never cause
  8771  // the algorithm to make a tragic mistake. At every stage we are working
  8772  // with numbers corresponding to a cubic polynomial $B(\xt_0,
  8773  // \xt_1,\xt_2,\xt_3)$ that approximates some
  8774  // monotonic polynomial $B(x_0,x_1,x_2,x_3)$. The accumulated errors are
  8775  // controlled so that $\vert x_k-\xt_k\vert<\epsilon=3\cdot2^[-16]$.
  8776  // If bisection is done at some stage of the recursion, we have
  8777  // $m=\lfloor\xt_3\rfloor-\lfloor\xt_0\rfloor>0$, and the algorithm
  8778  // computes a bisection value $\bar x$ such that $m'=\lfloor\bar x\rfloor-
  8779  // \lfloor\xt_0\rfloor$
  8780  // and $m''=\lfloor\xt_3\rfloor-\lfloor\bar x\rfloor$. We want to prove
  8781  // that neither $m'$ nor $m''$ can be negative. Since $\bar x$ is an
  8782  // approximation to a value in the interval $[x_0,x_3]$, we have
  8783  // $\bar x>x_0-\epsilon$ and $\bar x<x_3+\epsilon$, hence $\bar x>
  8784  // \xt_0-2\epsilon$ and $\bar x<\xt_3+2\epsilon$.
  8785  // If $m'$ is negative we must have $\xt_0\bmod 1<2\epsilon$;
  8786  // if $m''$ is negative we must have $\xt_3\bmod 1>1-2\epsilon$.
  8787  // In either case the condition $\lfloor\xt_3\rfloor-\lfloor\xt_0\rfloor>0$
  8788  // implies that $\xt_3-\xt_0>1-2\epsilon$, hence $x_3-x_0>1-4\epsilon$.
  8789  // But it can be shown that if $B(x_0,x_1,x_2,x_3;t)$ is a monotonic
  8790  // cubic, then $B(x_0,x_1,x_2,x_3;[1\over2])$ is always between
  8791  // $.06[x_0,x_3]$ and $.94[x_0,x_3]$; and it is impossible for $\bar x$
  8792  // to be within~$\epsilon$ of such a number. Contradiction!
  8793  // (The constant .06 is actually $(2-\sqrt3\,)/4$; the worst case
  8794  // occurs for polynomials like $B(0,2-\sqrt3,1-\sqrt3,3;t)$.)
  8795  
  8796  // 311.
  8797  
  8798  // tangle:pos ../../mf.web:6907:3:
  8799  
  8800  // The |make_moves| subroutine is given |scaled| values $(x_0,x_1,x_2,x_3)$
  8801  // and $(y_0,y_1,y_2,y_3)$ that represent monotone-nondecreasing polynomials;
  8802  // it makes $\lfloor x_3+\xi\rfloor-\lfloor x_0+\xi\rfloor$ rightward moves
  8803  // and $\lfloor y_3+\eta\rfloor-\lfloor y_0+\eta\rfloor$ upward moves, as
  8804  // explained earlier.  (Here $\lfloor x+\xi\rfloor$ actually stands for
  8805  // $\lfloor x/2^[16]-|xi_corr|\rfloor$, if $x$ is regarded as an integer
  8806  // without scaling.) The unscaled integers $x_k$ and~$y_k$ should be less
  8807  // than $2^[28]$ in magnitude.
  8808  //
  8809  // It is assumed that $|move_ptr| + \lfloor y_3+\eta\rfloor -
  8810  // \lfloor y_0+\eta\rfloor < |move_size|$ when this procedure is called,
  8811  // so that the capacity of the |move| array will not be exceeded.
  8812  //
  8813  // The variables |r| and |s| in this procedure stand respectively for
  8814  // $R-|xi_corr|$ and $S-|eta_corr|$ in the theory discussed above.
  8815  func (prg *prg) makeMoves(xx0, xx1, xx2, xx3, yy0, yy1, yy2, yy3 scaled, xiCorr, etaCorr smallNumber) {
  8816  	var (
  8817  		x1, x2, x3, m, r1, y1, y2, y3, n, s, l int32
  8818  		// bisection variables explained above
  8819  		q, t, u, x2a, x3a, y2a, y3a int32 // additional temporary registers
  8820  	)
  8821  	if xx3 < xx0 || yy3 < yy0 {
  8822  		prg.confusion(strNumber('m'))
  8823  	}
  8824  	// \xref[this can't happen m][\quad m]
  8825  	l = 16
  8826  	prg.bisectPtr = 0
  8827  
  8828  	x1 = xx1 - xx0
  8829  	x2 = xx2 - xx1
  8830  	x3 = xx3 - xx2
  8831  	if xx0 >= int32(xiCorr) {
  8832  		r1 = (xx0 - int32(xiCorr)) % 0200000
  8833  	} else {
  8834  		r1 = 0200000 - 1 - (-xx0+int32(xiCorr)-1)%0200000
  8835  	}
  8836  	m = (xx3 - xx0 + r1) / 0200000
  8837  
  8838  	y1 = yy1 - yy0
  8839  	y2 = yy2 - yy1
  8840  	y3 = yy3 - yy2
  8841  	if yy0 >= int32(etaCorr) {
  8842  		s = (yy0 - int32(etaCorr)) % 0200000
  8843  	} else {
  8844  		s = 0200000 - 1 - (-yy0+int32(etaCorr)-1)%0200000
  8845  	}
  8846  	n = (yy3 - yy0 + s) / 0200000
  8847  
  8848  	if xx3-xx0 >= 02000000000 || yy3-yy0 >= 02000000000 {
  8849  		x1 = (x1 + int32(xiCorr)) / 2
  8850  		x2 = (x2 + int32(xiCorr)) / 2
  8851  		x3 = (x3 + int32(xiCorr)) / 2
  8852  		r1 = (r1 + int32(xiCorr)) / 2
  8853  
  8854  		y1 = (y1 + int32(etaCorr)) / 2
  8855  		y2 = (y2 + int32(etaCorr)) / 2
  8856  		y3 = (y3 + int32(etaCorr)) / 2
  8857  		s = (s + int32(etaCorr)) / 2
  8858  
  8859  		l = 15
  8860  	}
  8861  	for true {
  8862  	continue1:
  8863  		if m == 0 {
  8864  			for n > 0 {
  8865  				prg.movePtr = uint16(int32(prg.movePtr) + 1)
  8866  				prg.move[prg.movePtr] = 1
  8867  				n = n - 1
  8868  			}
  8869  		} else if n == 0 {
  8870  			prg.move[prg.movePtr] = prg.move[prg.movePtr] + m
  8871  		} else if m+n == 2 {
  8872  			r1 = prg.twoToThe[l] - r1
  8873  			s = prg.twoToThe[l] - s
  8874  
  8875  			for l < 30 {
  8876  				x3a = x3
  8877  				x2a = (x2 + x3 + int32(xiCorr)) / 2
  8878  				x2 = (x1 + x2 + int32(xiCorr)) / 2
  8879  				x3 = (x2 + x2a + int32(xiCorr)) / 2
  8880  				t = x1 + x2 + x3
  8881  				r1 = r1 + r1 - int32(xiCorr)
  8882  
  8883  				y3a = y3
  8884  				y2a = (y2 + y3 + int32(etaCorr)) / 2
  8885  				y2 = (y1 + y2 + int32(etaCorr)) / 2
  8886  				y3 = (y2 + y2a + int32(etaCorr)) / 2
  8887  				u = y1 + y2 + y3
  8888  				s = s + s - int32(etaCorr)
  8889  
  8890  				if t < r1 {
  8891  					if u < s {
  8892  						x1 = x3
  8893  						x2 = x2a
  8894  						x3 = x3a
  8895  						r1 = r1 - t
  8896  						y1 = y3
  8897  						y2 = y2a
  8898  						y3 = y3a
  8899  						s = s - u
  8900  					} else {
  8901  						{
  8902  							prg.movePtr = uint16(int32(prg.movePtr) + 1)
  8903  							prg.move[prg.movePtr] = 2
  8904  						}
  8905  						goto done
  8906  					}
  8907  				} else if u < s {
  8908  					{
  8909  						prg.move[prg.movePtr] = prg.move[prg.movePtr] + 1
  8910  						prg.movePtr = uint16(int32(prg.movePtr) + 1)
  8911  						prg.move[prg.movePtr] = 1
  8912  					}
  8913  					goto done
  8914  				}
  8915  				l = l + 1
  8916  			}
  8917  			r1 = r1 - int32(xiCorr)
  8918  			s = s - int32(etaCorr)
  8919  			if prg.abVsCd(x1+x2+x3, s, y1+y2+y3, r1)-int32(xiCorr) >= 0 {
  8920  				prg.move[prg.movePtr] = prg.move[prg.movePtr] + 1
  8921  				prg.movePtr = uint16(int32(prg.movePtr) + 1)
  8922  				prg.move[prg.movePtr] = 1
  8923  			} else {
  8924  				// Move up then right
  8925  				prg.movePtr = uint16(int32(prg.movePtr) + 1)
  8926  				prg.move[prg.movePtr] = 2
  8927  			}
  8928  
  8929  		done:
  8930  		} else {
  8931  			l = l + 1
  8932  			prg.bisectStack[int32(prg.bisectPtr)+10] = l
  8933  
  8934  			prg.bisectStack[int32(prg.bisectPtr)+2] = x3
  8935  			prg.bisectStack[int32(prg.bisectPtr)+1] = (x2 + x3 + int32(xiCorr)) / 2
  8936  			x2 = (x1 + x2 + int32(xiCorr)) / 2
  8937  			x3 = (x2 + prg.bisectStack[int32(prg.bisectPtr)+1] + int32(xiCorr)) / 2
  8938  			prg.bisectStack[prg.bisectPtr] = x3
  8939  
  8940  			r1 = r1 + r1 + int32(xiCorr)
  8941  			t = x1 + x2 + x3 + r1
  8942  
  8943  			q = t / prg.twoToThe[l]
  8944  			prg.bisectStack[int32(prg.bisectPtr)+3] = t % prg.twoToThe[l]
  8945  
  8946  			prg.bisectStack[int32(prg.bisectPtr)+4] = m - q
  8947  			m = q
  8948  
  8949  			prg.bisectStack[int32(prg.bisectPtr)+7] = y3
  8950  			prg.bisectStack[int32(prg.bisectPtr)+6] = (y2 + y3 + int32(etaCorr)) / 2
  8951  			y2 = (y1 + y2 + int32(etaCorr)) / 2
  8952  			y3 = (y2 + prg.bisectStack[int32(prg.bisectPtr)+6] + int32(etaCorr)) / 2
  8953  			prg.bisectStack[int32(prg.bisectPtr)+5] = y3
  8954  
  8955  			s = s + s + int32(etaCorr)
  8956  			u = y1 + y2 + y3 + s
  8957  
  8958  			q = u / prg.twoToThe[l]
  8959  			prg.bisectStack[int32(prg.bisectPtr)+8] = u % prg.twoToThe[l]
  8960  
  8961  			prg.bisectStack[int32(prg.bisectPtr)+9] = n - q
  8962  			n = q
  8963  
  8964  			prg.bisectPtr = uint16(int32(prg.bisectPtr) + moveIncrement)
  8965  			goto continue1
  8966  		}
  8967  		if int32(prg.bisectPtr) == 0 {
  8968  			goto exit
  8969  		}
  8970  
  8971  		// Remove a subproblem for |make_moves| from the stack
  8972  		prg.bisectPtr = uint16(int32(prg.bisectPtr) - moveIncrement)
  8973  
  8974  		x1 = prg.bisectStack[prg.bisectPtr]
  8975  		x2 = prg.bisectStack[int32(prg.bisectPtr)+1]
  8976  		x3 = prg.bisectStack[int32(prg.bisectPtr)+2]
  8977  		r1 = prg.bisectStack[int32(prg.bisectPtr)+3]
  8978  		m = prg.bisectStack[int32(prg.bisectPtr)+4]
  8979  
  8980  		y1 = prg.bisectStack[int32(prg.bisectPtr)+5]
  8981  		y2 = prg.bisectStack[int32(prg.bisectPtr)+6]
  8982  		y3 = prg.bisectStack[int32(prg.bisectPtr)+7]
  8983  		s = prg.bisectStack[int32(prg.bisectPtr)+8]
  8984  		n = prg.bisectStack[int32(prg.bisectPtr)+9]
  8985  
  8986  		l = prg.bisectStack[int32(prg.bisectPtr)+10]
  8987  	}
  8988  
  8989  exit:
  8990  }
  8991  
  8992  // 321.
  8993  
  8994  // tangle:pos ../../mf.web:7034:3:
  8995  
  8996  // After |make_moves| has acted, possibly for several curves that move toward
  8997  // the same octant, a ``smoothing'' operation might be done on the |move| array.
  8998  // This removes optical glitches that can arise even when the curve has been
  8999  // digitized without rounding errors.
  9000  //
  9001  // The smoothing process replaces the integers $a_0\ldots a_n$ in
  9002  // |move[b..t]| by ``smoothed'' integers $a_0'\ldots a_n'$ defined as
  9003  // follows:
  9004  // $$a_k'=a_k+\delta\k-\delta_k;\qquad
  9005  // \delta_k=\cases[+1,&if $1<k<n$ and $a_[k-2]\G a_[k-1]\ll a_k\G a\k$;\cr
  9006  // -1,&if $1<k<n$ and $a_[k-2]\L a_[k-1]\gg a_k\L a\k$;\cr
  9007  // 0,&otherwise.\cr]$$
  9008  // Here $a\ll b$ means that $a\L b-2$, and $a\gg b$ means that $a\G b+2$.
  9009  //
  9010  // The smoothing operation is symmetric in the sense that, if $a_0\ldots a_n$
  9011  // smooths to $a_0'\ldots a_n'$, then the reverse sequence $a_n\ldots a_0$
  9012  // smooths to $a_n'\ldots a_0'$; also the complementary sequence
  9013  // $(m-a_0)\ldots(m-a_n)$ smooths to $(m-a_0')\ldots(m-a_n')$.
  9014  // We have $a_0'+\cdots+a_n'=a_0+\cdots+a_n$ because $\delta_0=\delta_[n+1]=0$.
  9015  func (prg *prg) smoothMoves(b, t int32) {
  9016  	var (
  9017  		k/* 1..moveSize */ uint16       // index into |move|
  9018  		a, aa, aaa                int32 // original values of |move[k],move[k-1],move[k-2]|
  9019  	)
  9020  	if t-b >= 3 {
  9021  		k = uint16(b + 2)
  9022  		aa = prg.move[int32(k)-1]
  9023  		aaa = prg.move[int32(k)-2]
  9024  		for {
  9025  			a = prg.move[k]
  9026  			if abs(a-aa) > 1 {
  9027  				if a > aa {
  9028  					if aaa >= aa {
  9029  						if a >= prg.move[int32(k)+1] {
  9030  							prg.move[int32(k)-1] = prg.move[int32(k)-1] + 1
  9031  							prg.move[k] = a - 1
  9032  						}
  9033  					}
  9034  				} else {
  9035  					if aaa <= aa {
  9036  						if a <= prg.move[int32(k)+1] {
  9037  							prg.move[int32(k)-1] = prg.move[int32(k)-1] - 1
  9038  							prg.move[k] = a + 1
  9039  						}
  9040  					}
  9041  				}
  9042  			}
  9043  			k = uint16(int32(k) + 1)
  9044  			aaa = aa
  9045  			aa = a
  9046  			if int32(k) == t {
  9047  				break
  9048  			}
  9049  		}
  9050  	}
  9051  }
  9052  
  9053  // 323. \[20] Edge structures
  9054  
  9055  // tangle:pos ../../mf.web:7078:26:
  9056  
  9057  // Now we come to \MF's internal scheme for representing what the user can
  9058  // actually ``see,'' the edges between pixels. Each pixel has an integer
  9059  // weight, obtained by summing the weights on all edges to its left. \MF\
  9060  // represents only the nonzero edge weights, since most of the edges are
  9061  // weightless; in this way, the data storage requirements grow only linearly
  9062  // with respect to the number of pixels per point, even though two-dimensional
  9063  // data is being represented. (Well, the actual dependence on the underlying
  9064  // resolution is order $n\log n$, but the $\log n$ factor is buried in our
  9065  // implicit restriction on the maximum raster size.) The sum of all edge
  9066  // weights in each row should be zero.
  9067  //
  9068  // The data structure for edge weights must be compact and flexible,
  9069  // yet it should support efficient updating and display operations. We
  9070  // want to be able to have many different edge structures in memory at
  9071  // once, and we want the computer to be able to translate them, reflect them,
  9072  // and/or merge them together with relative ease.
  9073  //
  9074  // \MF's solution to this problem requires one single-word node per
  9075  // nonzero edge weight, plus one two-word node for each row in a contiguous
  9076  // set of rows. There's also a header node that provides global information
  9077  // about the entire structure.
  9078  
  9079  // 325.
  9080  
  9081  // tangle:pos ../../mf.web:7144:3:
  9082  
  9083  // The rows themselves are represented by row header nodes that
  9084  // contain four link fields. Two of these four, |sorted| and |unsorted|,
  9085  // point to the first items of the edge-weight lists just mentioned.
  9086  // The other two, |link| and |knil|, point to the headers of the two
  9087  // adjacent rows. If |p| points to the header for row number~|n|, then
  9088  // |link(p)| points up to the header for row~|n+1|, and |knil(p)| points
  9089  // down to the header for row~|n-1|. This double linking makes it
  9090  // convenient to move through consecutive rows either upward or downward;
  9091  // as usual, we have |link(knil(p))=knil(link(p))=p| for all row headers~|p|.
  9092  //
  9093  // The row associated with a given value of |n| contains weights for
  9094  // edges that run between the lattice points |(m,n)| and |(m,n+1)|.
  9095  
  9096  // 326.
  9097  
  9098  // tangle:pos ../../mf.web:7163:3:
  9099  
  9100  // The main header node |h| for an edge structure has |link| and |knil|
  9101  // fields that link it above the topmost row and below the bottommost row.
  9102  // It also has fields called |m_min|, |m_max|, |n_min|, and |n_max| that
  9103  // bound the current extent of the edge data: All |m| values in edge-weight
  9104  // nodes should lie between |m_min(h)-4096| and |m_max(h)-4096|, inclusive.
  9105  // Furthermore the topmost row header, pointed to by |knil(h)|,
  9106  // is for row number |n_max(h)-4096|; the bottommost row header, pointed to by
  9107  // |link(h)|, is for row number |n_min(h)-4096|.
  9108  //
  9109  // The offset constant |c| that's used in all of the edge-weight data is
  9110  // represented implicitly in |m_offset(h)|; its actual value is
  9111  // $$\hbox[|c=min_halfword+zero_w+8*m_offset(h)|.]$$
  9112  // Notice that it's possible to shift an entire edge structure by an
  9113  // amount $(\Delta m,\Delta n)$ by adding $\Delta n$ to |n_min(h)| and |n_max(h)|,
  9114  // adding $\Delta m$ to |m_min(h)| and |m_max(h)|, and subtracting
  9115  // $\Delta m$ from |m_offset(h)|;
  9116  // none of the other edge data needs to be modified. Initially the |m_offset|
  9117  // field is~4096, but it will change if the user requests such a shift.
  9118  // The contents of these five fields should always be positive and less than
  9119  // 8192; |n_max| should, in fact, be less than 8191.  Furthermore
  9120  // |m_min+m_offset-4096| and |m_max+m_offset-4096| must also lie strictly
  9121  // between 0 and 8192, so that the |info| fields of edge-weight nodes will
  9122  // fit in a halfword.
  9123  //
  9124  // The header node of an edge structure also contains two somewhat unusual
  9125  // fields that are called |last_window(h)| and |last_window_time(h)|. When this
  9126  // structure is displayed in window~|k| of the user's screen, after that
  9127  // window has been updated |t| times, \MF\ sets |last_window(h):=k| and
  9128  // |last_window_time(h):=t|; it also sets |unsorted(p):=void| for all row
  9129  // headers~|p|, after merging any existing unsorted weights with the sorted
  9130  // ones.  A subsequent display in the same window will be able to avoid
  9131  // redisplaying rows whose |unsorted| list is still |void|, if the window
  9132  // hasn't been used for something else in the meantime.
  9133  //
  9134  // A pointer to the row header of row |n_pos(h)-4096| is provided in
  9135  // |n_rover(h)|. Most of the algorithms that update an edge structure
  9136  // are able to get by without random row references; they usually
  9137  // access rows that are neighbors of each other or of the current |n_pos| row.
  9138  // Exception: If |link(h)=h| (so that the edge structure contains
  9139  // no rows), we have |n_rover(h)=h|, and |n_pos(h)| is irrelevant.
  9140  func (prg *prg) initEdges(h halfword) {
  9141  	*(*prg.mem[h].hh()).lh() = h
  9142  	*(*prg.mem[h].hh()).rh() = h
  9143  
  9144  	*(*prg.mem[int32(h)+1].hh()).lh() = uint16(zeroField + 4095)
  9145  	*(*prg.mem[int32(h)+1].hh()).rh() = uint16(zeroField - 4095)
  9146  	*(*prg.mem[int32(h)+2].hh()).lh() = uint16(zeroField + 4095)
  9147  	*(*prg.mem[int32(h)+2].hh()).rh() = uint16(zeroField - 4095)
  9148  	*(*prg.mem[int32(h)+3].hh()).lh() = uint16(zeroField)
  9149  
  9150  	*(*prg.mem[int32(h)+3].hh()).rh() = 0
  9151  	*prg.mem[int32(h)+4].int() = 0
  9152  
  9153  	*(*prg.mem[int32(h)+5].hh()).rh() = h
  9154  	*(*prg.mem[int32(h)+5].hh()).lh() = 0
  9155  
  9156  }
  9157  
  9158  // 328.
  9159  
  9160  // tangle:pos ../../mf.web:7239:3:
  9161  
  9162  // The |fix_offset| routine goes through all the edge-weight nodes of
  9163  // |cur_edges| and adds a constant to their |info| fields, so that
  9164  // |m_offset(cur_edges)| can be brought back to |zero_field|. (This
  9165  // is necessary only in unusual cases when the offset has gotten too
  9166  // large or too small.)
  9167  func (prg *prg) fixOffset() {
  9168  	var (
  9169  		p, q  halfword // list traversers
  9170  		delta int32    // the amount of change
  9171  	)
  9172  	delta = 8 * (int32(*(*prg.mem[int32(prg.curEdges)+3].hh()).lh()) - zeroField)
  9173  	*(*prg.mem[int32(prg.curEdges)+3].hh()).lh() = uint16(zeroField)
  9174  	q = *(*prg.mem[prg.curEdges].hh()).rh()
  9175  	for int32(q) != int32(prg.curEdges) {
  9176  		p = *(*prg.mem[int32(q)+1].hh()).rh()
  9177  		for int32(p) != 3000 {
  9178  			*(*prg.mem[p].hh()).lh() = uint16(int32(*(*prg.mem[p].hh()).lh()) - delta)
  9179  			p = *(*prg.mem[p].hh()).rh()
  9180  		}
  9181  		p = *(*prg.mem[int32(q)+1].hh()).lh()
  9182  		for int32(p) > memMin+1 {
  9183  			*(*prg.mem[p].hh()).lh() = uint16(int32(*(*prg.mem[p].hh()).lh()) - delta)
  9184  			p = *(*prg.mem[p].hh()).rh()
  9185  		}
  9186  		q = *(*prg.mem[q].hh()).rh()
  9187  	}
  9188  }
  9189  
  9190  // 329.
  9191  
  9192  // tangle:pos ../../mf.web:7264:3:
  9193  
  9194  // The |edge_prep| routine makes the |cur_edges| structure ready to
  9195  // accept new data whose coordinates satisfy |ml<=m<=mr| and |nl<=n<=nr-1|,
  9196  // assuming that |-4096<ml<=mr<4096| and |-4096<nl<=nr<4096|. It makes
  9197  // appropriate adjustments to |m_min|, |m_max|, |n_min|, and |n_max|,
  9198  // adding new empty rows if necessary.
  9199  func (prg *prg) edgePrep(ml, mr, nl, nr int32) {
  9200  	var (
  9201  		delta halfword // amount of change
  9202  		p, q  halfword // for list manipulation
  9203  	)
  9204  	ml = ml + zeroField
  9205  	mr = mr + zeroField
  9206  	nl = nl + zeroField
  9207  	nr = nr - 1 + zeroField
  9208  
  9209  	if ml < int32(*(*prg.mem[int32(prg.curEdges)+2].hh()).lh()) {
  9210  		*(*prg.mem[int32(prg.curEdges)+2].hh()).lh() = uint16(ml)
  9211  	}
  9212  	if mr > int32(*(*prg.mem[int32(prg.curEdges)+2].hh()).rh()) {
  9213  		*(*prg.mem[int32(prg.curEdges)+2].hh()).rh() = uint16(mr)
  9214  	}
  9215  	if !(abs(int32(*(*prg.mem[int32(prg.curEdges)+2].hh()).lh())+int32(*(*prg.mem[int32(prg.curEdges)+3].hh()).lh())-zeroField-4096) < 4096) || !(abs(int32(*(*prg.mem[int32(prg.curEdges)+2].hh()).rh())+int32(*(*prg.mem[int32(prg.curEdges)+3].hh()).lh())-zeroField-4096) < 4096) {
  9216  		prg.fixOffset()
  9217  	}
  9218  	if int32(*(*prg.mem[prg.curEdges].hh()).rh()) == int32(prg.curEdges) {
  9219  		*(*prg.mem[int32(prg.curEdges)+1].hh()).lh() = uint16(nr + 1)
  9220  		*(*prg.mem[int32(prg.curEdges)+1].hh()).rh() = uint16(nr)
  9221  	}
  9222  	if nl < int32(*(*prg.mem[int32(prg.curEdges)+1].hh()).lh()) {
  9223  		delta = uint16(int32(*(*prg.mem[int32(prg.curEdges)+1].hh()).lh()) - nl)
  9224  		*(*prg.mem[int32(prg.curEdges)+1].hh()).lh() = uint16(nl)
  9225  		p = *(*prg.mem[prg.curEdges].hh()).rh()
  9226  		for {
  9227  			q = prg.getNode(rowNodeSize)
  9228  			*(*prg.mem[int32(q)+1].hh()).rh() = 3000
  9229  			*(*prg.mem[int32(q)+1].hh()).lh() = uint16(memMin + 1)
  9230  			*(*prg.mem[p].hh()).lh() = q
  9231  			*(*prg.mem[q].hh()).rh() = p
  9232  			p = q
  9233  			delta = uint16(int32(delta) - 1)
  9234  			if int32(delta) == 0 {
  9235  				break
  9236  			}
  9237  		}
  9238  		*(*prg.mem[p].hh()).lh() = prg.curEdges
  9239  		*(*prg.mem[prg.curEdges].hh()).rh() = p
  9240  		if int32(*(*prg.mem[int32(prg.curEdges)+5].hh()).rh()) == int32(prg.curEdges) {
  9241  			*(*prg.mem[int32(prg.curEdges)+5].hh()).lh() = uint16(nl - 1)
  9242  		}
  9243  	}
  9244  	if nr > int32(*(*prg.mem[int32(prg.curEdges)+1].hh()).rh()) {
  9245  		delta = uint16(nr - int32(*(*prg.mem[int32(prg.curEdges)+1].hh()).rh()))
  9246  		*(*prg.mem[int32(prg.curEdges)+1].hh()).rh() = uint16(nr)
  9247  		p = *(*prg.mem[prg.curEdges].hh()).lh()
  9248  		for {
  9249  			q = prg.getNode(rowNodeSize)
  9250  			*(*prg.mem[int32(q)+1].hh()).rh() = 3000
  9251  			*(*prg.mem[int32(q)+1].hh()).lh() = uint16(memMin + 1)
  9252  			*(*prg.mem[p].hh()).rh() = q
  9253  			*(*prg.mem[q].hh()).lh() = p
  9254  			p = q
  9255  			delta = uint16(int32(delta) - 1)
  9256  			if int32(delta) == 0 {
  9257  				break
  9258  			}
  9259  		}
  9260  		*(*prg.mem[p].hh()).rh() = prg.curEdges
  9261  		*(*prg.mem[prg.curEdges].hh()).lh() = p
  9262  		if int32(*(*prg.mem[int32(prg.curEdges)+5].hh()).rh()) == int32(prg.curEdges) {
  9263  			*(*prg.mem[int32(prg.curEdges)+5].hh()).lh() = uint16(nr + 1)
  9264  		}
  9265  	}
  9266  }
  9267  
  9268  // 334.
  9269  
  9270  // tangle:pos ../../mf.web:7353:3:
  9271  
  9272  // Here's a trivial subroutine that copies an edge structure. (Let's hope
  9273  // that the given structure isn't too gigantic.)
  9274  func (prg *prg) copyEdges(h halfword) (r halfword) {
  9275  	var (
  9276  		p, r1              halfword // variables that traverse the given structure
  9277  		hh, pp, qq, rr, ss halfword // variables that traverse the new structure
  9278  	)
  9279  	hh = prg.getNode(edgeHeaderSize)
  9280  	prg.mem[int32(hh)+1] = prg.mem[int32(h)+1]
  9281  	prg.mem[int32(hh)+2] = prg.mem[int32(h)+2]
  9282  	prg.mem[int32(hh)+3] = prg.mem[int32(h)+3]
  9283  	prg.mem[int32(hh)+4] = prg.mem[int32(h)+4] // we've now copied |n_min|, |n_max|,
  9284  	//   |m_min|, |m_max|, |m_offset|, |last_window|, and |last_window_time|
  9285  
  9286  	*(*prg.mem[int32(hh)+5].hh()).lh() = uint16(int32(*(*prg.mem[int32(hh)+1].hh()).rh()) + 1)
  9287  	*(*prg.mem[int32(hh)+5].hh()).rh() = hh
  9288  
  9289  	p = *(*prg.mem[h].hh()).rh()
  9290  	qq = hh
  9291  	for int32(p) != int32(h) {
  9292  		pp = prg.getNode(rowNodeSize)
  9293  		*(*prg.mem[qq].hh()).rh() = pp
  9294  		*(*prg.mem[pp].hh()).lh() = qq
  9295  
  9296  		// Copy both |sorted| and |unsorted| lists of |p| to |pp|
  9297  		r1 = *(*prg.mem[int32(p)+1].hh()).rh()
  9298  		rr = uint16(int32(pp) + 1) // |link(rr)=sorted(pp)|
  9299  		for int32(r1) != 3000 {
  9300  			ss = prg.getAvail()
  9301  			*(*prg.mem[rr].hh()).rh() = ss
  9302  			rr = ss
  9303  			*(*prg.mem[rr].hh()).lh() = *(*prg.mem[r1].hh()).lh()
  9304  
  9305  			r1 = *(*prg.mem[r1].hh()).rh()
  9306  		}
  9307  		*(*prg.mem[rr].hh()).rh() = 3000
  9308  
  9309  		r1 = *(*prg.mem[int32(p)+1].hh()).lh()
  9310  		rr = uint16(3000 - 1)
  9311  		for int32(r1) > memMin+1 {
  9312  			ss = prg.getAvail()
  9313  			*(*prg.mem[rr].hh()).rh() = ss
  9314  			rr = ss
  9315  			*(*prg.mem[rr].hh()).lh() = *(*prg.mem[r1].hh()).lh()
  9316  
  9317  			r1 = *(*prg.mem[r1].hh()).rh()
  9318  		}
  9319  		*(*prg.mem[rr].hh()).rh() = r1
  9320  		*(*prg.mem[int32(pp)+1].hh()).lh() = *(*prg.mem[3000-1].hh()).rh()
  9321  		p = *(*prg.mem[p].hh()).rh()
  9322  		qq = pp
  9323  	}
  9324  	*(*prg.mem[qq].hh()).rh() = hh
  9325  	*(*prg.mem[hh].hh()).lh() = qq
  9326  	r = hh
  9327  	return r
  9328  }
  9329  
  9330  // 336.
  9331  
  9332  // tangle:pos ../../mf.web:7388:3:
  9333  
  9334  // Another trivial routine flips |cur_edges| about the |x|-axis
  9335  // (i.e., negates all the |y| coordinates), assuming that at least
  9336  // one row is present.
  9337  func (prg *prg) yReflectEdges() {
  9338  	var (
  9339  		p, q, r1 halfword // list manipulation registers
  9340  	)
  9341  	p = *(*prg.mem[int32(prg.curEdges)+1].hh()).lh()
  9342  	*(*prg.mem[int32(prg.curEdges)+1].hh()).lh() = uint16(zeroField + zeroField - 1 - int32(*(*prg.mem[int32(prg.curEdges)+1].hh()).rh()))
  9343  	*(*prg.mem[int32(prg.curEdges)+1].hh()).rh() = uint16(zeroField + zeroField - 1 - int32(p))
  9344  	*(*prg.mem[int32(prg.curEdges)+5].hh()).lh() = uint16(zeroField + zeroField - 1 - int32(*(*prg.mem[int32(prg.curEdges)+5].hh()).lh()))
  9345  
  9346  	p = *(*prg.mem[prg.curEdges].hh()).rh()
  9347  	q = prg.curEdges // we assume that |p<>q|
  9348  	for {
  9349  		r1 = *(*prg.mem[p].hh()).rh()
  9350  		*(*prg.mem[p].hh()).rh() = q
  9351  		*(*prg.mem[q].hh()).lh() = p
  9352  		q = p
  9353  		p = r1
  9354  		if int32(q) == int32(prg.curEdges) {
  9355  			break
  9356  		}
  9357  	}
  9358  	*prg.mem[int32(prg.curEdges)+4].int() = 0
  9359  }
  9360  
  9361  // 337.
  9362  
  9363  // tangle:pos ../../mf.web:7404:3:
  9364  
  9365  // It's somewhat more difficult, yet not too hard, to reflect about the |y|-axis.
  9366  func (prg *prg) xReflectEdges() {
  9367  	var (
  9368  		p, q, r1, s halfword // list manipulation registers
  9369  		m           int32    // |info| fields will be reflected with respect to this number
  9370  	)
  9371  	p = *(*prg.mem[int32(prg.curEdges)+2].hh()).lh()
  9372  	*(*prg.mem[int32(prg.curEdges)+2].hh()).lh() = uint16(zeroField + zeroField - int32(*(*prg.mem[int32(prg.curEdges)+2].hh()).rh()))
  9373  	*(*prg.mem[int32(prg.curEdges)+2].hh()).rh() = uint16(zeroField + zeroField - int32(p))
  9374  	m = (zeroField+int32(*(*prg.mem[int32(prg.curEdges)+3].hh()).lh()))*8 + zeroW + 0 + zeroW + 0
  9375  	*(*prg.mem[int32(prg.curEdges)+3].hh()).lh() = uint16(zeroField)
  9376  	p = *(*prg.mem[prg.curEdges].hh()).rh()
  9377  	for {
  9378  		// Reflect the edge-and-weight data in |sorted(p)|
  9379  		q = *(*prg.mem[int32(p)+1].hh()).rh()
  9380  		r1 = 3000
  9381  		for int32(q) != 3000 {
  9382  			s = *(*prg.mem[q].hh()).rh()
  9383  			*(*prg.mem[q].hh()).rh() = r1
  9384  			r1 = q
  9385  			*(*prg.mem[r1].hh()).lh() = uint16(m - int32(*(*prg.mem[q].hh()).lh()))
  9386  			q = s
  9387  		}
  9388  		*(*prg.mem[int32(p)+1].hh()).rh() = r1
  9389  
  9390  		// Reflect the edge-and-weight data in |unsorted(p)|
  9391  		q = *(*prg.mem[int32(p)+1].hh()).lh()
  9392  		for int32(q) > memMin+1 {
  9393  			*(*prg.mem[q].hh()).lh() = uint16(m - int32(*(*prg.mem[q].hh()).lh()))
  9394  			q = *(*prg.mem[q].hh()).rh()
  9395  		}
  9396  		p = *(*prg.mem[p].hh()).rh()
  9397  		if int32(p) == int32(prg.curEdges) {
  9398  			break
  9399  		}
  9400  	}
  9401  	*prg.mem[int32(prg.curEdges)+4].int() = 0
  9402  }
  9403  
  9404  // 340.
  9405  
  9406  // tangle:pos ../../mf.web:7443:3:
  9407  
  9408  // Now let's multiply all the $y$~coordinates of a nonempty edge structure
  9409  // by a small integer $s>1$:
  9410  func (prg *prg) yScaleEdges(s int32) {
  9411  	var (
  9412  		p, q, pp, r1, rr, ss halfword // list manipulation registers
  9413  		t                    int32    // replication counter
  9414  	)
  9415  	if s*(int32(*(*prg.mem[int32(prg.curEdges)+1].hh()).rh())+1-zeroField) >= 4096 || s*(int32(*(*prg.mem[int32(prg.curEdges)+1].hh()).lh())-zeroField) <= -4096 {
  9416  		{
  9417  			if int32(prg.interaction) == errorStopMode {
  9418  			}
  9419  			prg.printNl(strNumber( /* "! " */ 261))
  9420  			prg.print( /* "Scaled picture would be too big" */ 535) /* \xref[!\relax]  */
  9421  		}
  9422  		// \xref[Scaled picture...big]
  9423  		{
  9424  			prg.helpPtr = 3
  9425  			prg.helpLine[2] = /* "I can't yscale the picture as requested---it would" */ 536
  9426  			prg.helpLine[1] = /* "make some coordinates too large or too small." */ 537
  9427  			prg.helpLine[0] = /* "Proceed, and I'll omit the transformation." */ 538
  9428  		}
  9429  		prg.putGetError()
  9430  	} else {
  9431  		*(*prg.mem[int32(prg.curEdges)+1].hh()).rh() = uint16(s*(int32(*(*prg.mem[int32(prg.curEdges)+1].hh()).rh())+1-zeroField) - 1 + zeroField)
  9432  		*(*prg.mem[int32(prg.curEdges)+1].hh()).lh() = uint16(s*(int32(*(*prg.mem[int32(prg.curEdges)+1].hh()).lh())-zeroField) + zeroField)
  9433  
  9434  		// Replicate every row exactly $s$ times
  9435  		p = prg.curEdges
  9436  		for {
  9437  			q = p
  9438  			p = *(*prg.mem[p].hh()).rh()
  9439  			for ii := int32(2); ii <= s; ii++ {
  9440  				t = ii
  9441  				_ = t
  9442  				pp = prg.getNode(rowNodeSize)
  9443  				*(*prg.mem[q].hh()).rh() = pp
  9444  				*(*prg.mem[p].hh()).lh() = pp
  9445  				*(*prg.mem[pp].hh()).rh() = p
  9446  				*(*prg.mem[pp].hh()).lh() = q
  9447  				q = pp
  9448  
  9449  				// Copy both |sorted| and |unsorted|...
  9450  				r1 = *(*prg.mem[int32(p)+1].hh()).rh()
  9451  				rr = uint16(int32(pp) + 1) // |link(rr)=sorted(pp)|
  9452  				for int32(r1) != 3000 {
  9453  					ss = prg.getAvail()
  9454  					*(*prg.mem[rr].hh()).rh() = ss
  9455  					rr = ss
  9456  					*(*prg.mem[rr].hh()).lh() = *(*prg.mem[r1].hh()).lh()
  9457  
  9458  					r1 = *(*prg.mem[r1].hh()).rh()
  9459  				}
  9460  				*(*prg.mem[rr].hh()).rh() = 3000
  9461  
  9462  				r1 = *(*prg.mem[int32(p)+1].hh()).lh()
  9463  				rr = uint16(3000 - 1)
  9464  				for int32(r1) > memMin+1 {
  9465  					ss = prg.getAvail()
  9466  					*(*prg.mem[rr].hh()).rh() = ss
  9467  					rr = ss
  9468  					*(*prg.mem[rr].hh()).lh() = *(*prg.mem[r1].hh()).lh()
  9469  
  9470  					r1 = *(*prg.mem[r1].hh()).rh()
  9471  				}
  9472  				*(*prg.mem[rr].hh()).rh() = r1
  9473  				*(*prg.mem[int32(pp)+1].hh()).lh() = *(*prg.mem[3000-1].hh()).rh()
  9474  			}
  9475  			if int32(*(*prg.mem[p].hh()).rh()) == int32(prg.curEdges) {
  9476  				break
  9477  			}
  9478  		}
  9479  		*prg.mem[int32(prg.curEdges)+4].int() = 0
  9480  	}
  9481  }
  9482  
  9483  // 342.
  9484  
  9485  // tangle:pos ../../mf.web:7475:3:
  9486  
  9487  // Scaling the $x$~coordinates is, of course, our next task.
  9488  func (prg *prg) xScaleEdges(s int32) {
  9489  	var (
  9490  		p, q                   halfword // list manipulation registers
  9491  		t/* 0..65535 */ uint16          // unpacked |info| field
  9492  		w/* 0..7 */ byte                // unpacked weight
  9493  		delta                  int32    // amount added to scaled |info|
  9494  	)
  9495  	if s*(int32(*(*prg.mem[int32(prg.curEdges)+2].hh()).rh())-zeroField) >= 4096 || s*(int32(*(*prg.mem[int32(prg.curEdges)+2].hh()).lh())-zeroField) <= -4096 {
  9496  		{
  9497  			if int32(prg.interaction) == errorStopMode {
  9498  			}
  9499  			prg.printNl(strNumber( /* "! " */ 261))
  9500  			prg.print( /* "Scaled picture would be too big" */ 535) /* \xref[!\relax]  */
  9501  		}
  9502  		// \xref[Scaled picture...big]
  9503  		{
  9504  			prg.helpPtr = 3
  9505  			prg.helpLine[2] = /* "I can't xscale the picture as requested---it would" */ 539
  9506  			prg.helpLine[1] = /* "make some coordinates too large or too small." */ 537
  9507  			prg.helpLine[0] = /* "Proceed, and I'll omit the transformation." */ 538
  9508  		}
  9509  		prg.putGetError()
  9510  	} else if int32(*(*prg.mem[int32(prg.curEdges)+2].hh()).rh()) != zeroField || int32(*(*prg.mem[int32(prg.curEdges)+2].hh()).lh()) != zeroField {
  9511  		*(*prg.mem[int32(prg.curEdges)+2].hh()).rh() = uint16(s*(int32(*(*prg.mem[int32(prg.curEdges)+2].hh()).rh())-zeroField) + zeroField)
  9512  		*(*prg.mem[int32(prg.curEdges)+2].hh()).lh() = uint16(s*(int32(*(*prg.mem[int32(prg.curEdges)+2].hh()).lh())-zeroField) + zeroField)
  9513  		delta = 8*(zeroField-s*int32(*(*prg.mem[int32(prg.curEdges)+3].hh()).lh())) + 0
  9514  		*(*prg.mem[int32(prg.curEdges)+3].hh()).lh() = uint16(zeroField)
  9515  
  9516  		// Scale the $x$~coordinates of each row by $s$
  9517  		q = *(*prg.mem[prg.curEdges].hh()).rh()
  9518  		for {
  9519  			p = *(*prg.mem[int32(q)+1].hh()).rh()
  9520  			for int32(p) != 3000 {
  9521  				t = uint16(int32(*(*prg.mem[p].hh()).lh()) - 0)
  9522  				w = byte(int32(t) % 8)
  9523  				*(*prg.mem[p].hh()).lh() = uint16((int32(t)-int32(w))*s + int32(w) + delta)
  9524  				p = *(*prg.mem[p].hh()).rh()
  9525  			}
  9526  			p = *(*prg.mem[int32(q)+1].hh()).lh()
  9527  			for int32(p) > memMin+1 {
  9528  				t = uint16(int32(*(*prg.mem[p].hh()).lh()) - 0)
  9529  				w = byte(int32(t) % 8)
  9530  				*(*prg.mem[p].hh()).lh() = uint16((int32(t)-int32(w))*s + int32(w) + delta)
  9531  				p = *(*prg.mem[p].hh()).rh()
  9532  			}
  9533  			q = *(*prg.mem[q].hh()).rh()
  9534  			if int32(q) == int32(prg.curEdges) {
  9535  				break
  9536  			}
  9537  		}
  9538  		*prg.mem[int32(prg.curEdges)+4].int() = 0
  9539  	}
  9540  }
  9541  
  9542  // 344.
  9543  
  9544  // tangle:pos ../../mf.web:7516:3:
  9545  
  9546  // Here is a routine that changes the signs of all the weights, without
  9547  // changing anything else.
  9548  func (prg *prg) negateEdges(h halfword) {
  9549  	var (
  9550  		p, q, r1, s, t, u halfword // structure traversers
  9551  	)
  9552  	p = *(*prg.mem[h].hh()).rh()
  9553  	for int32(p) != int32(h) {
  9554  		q = *(*prg.mem[int32(p)+1].hh()).lh()
  9555  		for int32(q) > memMin+1 {
  9556  			*(*prg.mem[q].hh()).lh() = uint16(8 - 2*((int32(*(*prg.mem[q].hh()).lh())-0)%8) + int32(*(*prg.mem[q].hh()).lh()))
  9557  			q = *(*prg.mem[q].hh()).rh()
  9558  		}
  9559  		q = *(*prg.mem[int32(p)+1].hh()).rh()
  9560  		if int32(q) != 3000 {
  9561  			for {
  9562  				*(*prg.mem[q].hh()).lh() = uint16(8 - 2*((int32(*(*prg.mem[q].hh()).lh())-0)%8) + int32(*(*prg.mem[q].hh()).lh()))
  9563  				q = *(*prg.mem[q].hh()).rh()
  9564  				if int32(q) == 3000 {
  9565  					break
  9566  				}
  9567  			}
  9568  
  9569  			// Put the list |sorted(p)| back into sort
  9570  			u = uint16(int32(p) + 1)
  9571  			q = *(*prg.mem[u].hh()).rh()
  9572  			r1 = q
  9573  			s = *(*prg.mem[r1].hh()).rh() // |q=sorted(p)|
  9574  			for true {
  9575  				if int32(*(*prg.mem[s].hh()).lh()) > int32(*(*prg.mem[r1].hh()).lh()) {
  9576  					*(*prg.mem[u].hh()).rh() = q
  9577  					if int32(s) == 3000 {
  9578  						goto done
  9579  					}
  9580  					u = r1
  9581  					q = s
  9582  					r1 = q
  9583  					s = *(*prg.mem[r1].hh()).rh()
  9584  				} else {
  9585  					t = s
  9586  					s = *(*prg.mem[t].hh()).rh()
  9587  					*(*prg.mem[t].hh()).rh() = q
  9588  					q = t
  9589  				}
  9590  			}
  9591  
  9592  		done:
  9593  			*(*prg.mem[r1].hh()).rh() = 3000
  9594  		}
  9595  		p = *(*prg.mem[p].hh()).rh()
  9596  	}
  9597  	*prg.mem[int32(h)+4].int() = 0
  9598  }
  9599  
  9600  // 346.
  9601  
  9602  // tangle:pos ../../mf.web:7558:3:
  9603  
  9604  // The |unsorted| edges of a row are merged into the |sorted| ones by
  9605  // a subroutine called |sort_edges|. It uses simple insertion sort,
  9606  // followed by a merge, because the unsorted list is supposedly quite short.
  9607  // However, the unsorted list is assumed to be nonempty.
  9608  func (prg *prg) sortEdges(h halfword) {
  9609  	var (
  9610  		k           halfword // key register that we compare to |info(q)|
  9611  		p, q, r1, s halfword
  9612  	)
  9613  	r1 = *(*prg.mem[int32(h)+1].hh()).lh()
  9614  	*(*prg.mem[int32(h)+1].hh()).lh() = uint16(memMin)
  9615  	p = *(*prg.mem[r1].hh()).rh()
  9616  	*(*prg.mem[r1].hh()).rh() = 3000
  9617  	*(*prg.mem[3000-1].hh()).rh() = r1
  9618  	for int32(p) > memMin+1 { // sort node |p| into the list that starts at |temp_head|
  9619  		k = *(*prg.mem[p].hh()).lh()
  9620  		q = uint16(3000 - 1)
  9621  		for {
  9622  			r1 = q
  9623  			q = *(*prg.mem[r1].hh()).rh()
  9624  			if int32(k) <= int32(*(*prg.mem[q].hh()).lh()) {
  9625  				break
  9626  			}
  9627  		}
  9628  		*(*prg.mem[r1].hh()).rh() = p
  9629  		r1 = *(*prg.mem[p].hh()).rh()
  9630  		*(*prg.mem[p].hh()).rh() = q
  9631  		p = r1
  9632  	}
  9633  
  9634  	// Merge the |temp_head| list into |sorted(h)|
  9635  	{
  9636  		r1 = uint16(int32(h) + 1)
  9637  		q = *(*prg.mem[r1].hh()).rh()
  9638  		p = *(*prg.mem[3000-1].hh()).rh()
  9639  		for true {
  9640  			k = *(*prg.mem[p].hh()).lh()
  9641  			for int32(k) > int32(*(*prg.mem[q].hh()).lh()) {
  9642  				r1 = q
  9643  				q = *(*prg.mem[r1].hh()).rh()
  9644  			}
  9645  			*(*prg.mem[r1].hh()).rh() = p
  9646  			s = *(*prg.mem[p].hh()).rh()
  9647  			*(*prg.mem[p].hh()).rh() = q
  9648  			if int32(s) == 3000 {
  9649  				goto done
  9650  			}
  9651  			r1 = p
  9652  			p = s
  9653  		}
  9654  
  9655  	done:
  9656  	}
  9657  }
  9658  
  9659  // 348.
  9660  
  9661  // tangle:pos ../../mf.web:7592:3:
  9662  
  9663  // The |cull_edges| procedure ``optimizes'' an edge structure by making all
  9664  // the pixel weights either |w_out| or~|w_in|. The weight will be~|w_in| after the
  9665  // operation if and only if it was in the closed interval |[w_lo,w_hi]|
  9666  // before, where |w_lo<=w_hi|. Either |w_out| or |w_in| is zero, while the other is
  9667  // $\pm1$, $\pm2$, or $\pm3$. The parameters will be such that zero-weight
  9668  // pixels will remain of weight zero.  (This is fortunate,
  9669  // because there are infinitely many of them.)
  9670  //
  9671  // The procedure also computes the tightest possible bounds on the resulting
  9672  // data, by updating |m_min|, |m_max|, |n_min|, and~|n_max|.
  9673  func (prg *prg) cullEdges(wLo, wHi, wOut, wIn int32) {
  9674  	var (
  9675  		p, q, r1, s   halfword // for list manipulation
  9676  		w             int32    // new weight after culling
  9677  		d             int32    // data register for unpacking
  9678  		m             int32    // the previous column number, including |m_offset|
  9679  		mm            int32    // the next column number, including |m_offset|
  9680  		ww            int32    // accumulated weight before culling
  9681  		prevW         int32    // value of |w| before column |m|
  9682  		n, minN, maxN halfword // current and extreme row numbers
  9683  		minD, maxD    halfword // extremes of the new edge-and-weight data
  9684  	)
  9685  	minD = 65535
  9686  	maxD = 0
  9687  	minN = 65535
  9688  	maxN = 0
  9689  
  9690  	p = *(*prg.mem[prg.curEdges].hh()).rh()
  9691  	n = *(*prg.mem[int32(prg.curEdges)+1].hh()).lh()
  9692  	for int32(p) != int32(prg.curEdges) {
  9693  		if int32(*(*prg.mem[int32(p)+1].hh()).lh()) > memMin+1 {
  9694  			prg.sortEdges(p)
  9695  		}
  9696  		if int32(*(*prg.mem[int32(p)+1].hh()).rh()) != 3000 {
  9697  			r1 = uint16(3000 - 1)
  9698  			q = *(*prg.mem[int32(p)+1].hh()).rh()
  9699  			ww = 0
  9700  			m = 1000000
  9701  			prevW = 0
  9702  			for true {
  9703  				if int32(q) == 3000 {
  9704  					mm = 1000000
  9705  				} else {
  9706  					d = int32(*(*prg.mem[q].hh()).lh()) - 0
  9707  					mm = d / 8
  9708  					ww = ww + d%8 - zeroW
  9709  				}
  9710  				if mm > m {
  9711  					if w != prevW {
  9712  						s = prg.getAvail()
  9713  						*(*prg.mem[r1].hh()).rh() = s
  9714  						*(*prg.mem[s].hh()).lh() = uint16(8*m + 0 + zeroW + w - prevW)
  9715  						r1 = s
  9716  						prevW = w
  9717  					}
  9718  					if int32(q) == 3000 {
  9719  						goto done
  9720  					}
  9721  				}
  9722  				m = mm
  9723  				if ww >= wLo {
  9724  					if ww <= wHi {
  9725  						w = wIn
  9726  					} else {
  9727  						w = wOut
  9728  					}
  9729  				} else {
  9730  					w = wOut
  9731  				}
  9732  				s = *(*prg.mem[q].hh()).rh()
  9733  				{
  9734  					*(*prg.mem[q].hh()).rh() = prg.avail
  9735  					prg.avail = q
  9736  					prg.dynUsed = prg.dynUsed - 1
  9737  				}
  9738  				q = s
  9739  			}
  9740  
  9741  		done:
  9742  			*(*prg.mem[r1].hh()).rh() = 3000
  9743  			*(*prg.mem[int32(p)+1].hh()).rh() = *(*prg.mem[3000-1].hh()).rh()
  9744  			if int32(r1) != 3000-1 {
  9745  				if int32(minN) == 65535 {
  9746  					minN = n
  9747  				}
  9748  				maxN = n
  9749  				if int32(minD) > int32(*(*prg.mem[*(*prg.mem[3000-1].hh()).rh()].hh()).lh()) {
  9750  					minD = *(*prg.mem[*(*prg.mem[3000-1].hh()).rh()].hh()).lh()
  9751  				}
  9752  				if int32(maxD) < int32(*(*prg.mem[r1].hh()).lh()) {
  9753  					maxD = *(*prg.mem[r1].hh()).lh()
  9754  				}
  9755  			}
  9756  		}
  9757  		p = *(*prg.mem[p].hh()).rh()
  9758  		n = uint16(int32(n) + 1)
  9759  	}
  9760  
  9761  	// Delete empty rows at the top and/or bottom; update the boundary values in the header
  9762  	if int32(minN) > int32(maxN) {
  9763  		p = *(*prg.mem[prg.curEdges].hh()).rh()
  9764  		for int32(p) != int32(prg.curEdges) {
  9765  			q = *(*prg.mem[p].hh()).rh()
  9766  			prg.freeNode(p, halfword(rowNodeSize))
  9767  			p = q
  9768  		}
  9769  		prg.initEdges(prg.curEdges)
  9770  	} else {
  9771  		n = *(*prg.mem[int32(prg.curEdges)+1].hh()).lh()
  9772  		*(*prg.mem[int32(prg.curEdges)+1].hh()).lh() = minN
  9773  		for int32(minN) > int32(n) {
  9774  			p = *(*prg.mem[prg.curEdges].hh()).rh()
  9775  			*(*prg.mem[prg.curEdges].hh()).rh() = *(*prg.mem[p].hh()).rh()
  9776  			*(*prg.mem[*(*prg.mem[p].hh()).rh()].hh()).lh() = prg.curEdges
  9777  			prg.freeNode(p, halfword(rowNodeSize))
  9778  			n = uint16(int32(n) + 1)
  9779  		}
  9780  		n = *(*prg.mem[int32(prg.curEdges)+1].hh()).rh()
  9781  		*(*prg.mem[int32(prg.curEdges)+1].hh()).rh() = maxN
  9782  		*(*prg.mem[int32(prg.curEdges)+5].hh()).lh() = uint16(int32(maxN) + 1)
  9783  		*(*prg.mem[int32(prg.curEdges)+5].hh()).rh() = prg.curEdges
  9784  		for int32(maxN) < int32(n) {
  9785  			p = *(*prg.mem[prg.curEdges].hh()).lh()
  9786  			*(*prg.mem[prg.curEdges].hh()).lh() = *(*prg.mem[p].hh()).lh()
  9787  			*(*prg.mem[*(*prg.mem[p].hh()).lh()].hh()).rh() = prg.curEdges
  9788  			prg.freeNode(p, halfword(rowNodeSize))
  9789  			n = uint16(int32(n) - 1)
  9790  		}
  9791  		*(*prg.mem[int32(prg.curEdges)+2].hh()).lh() = uint16((int32(minD)-0)/8 - int32(*(*prg.mem[int32(prg.curEdges)+3].hh()).lh()) + zeroField)
  9792  		*(*prg.mem[int32(prg.curEdges)+2].hh()).rh() = uint16((int32(maxD)-0)/8 - int32(*(*prg.mem[int32(prg.curEdges)+3].hh()).lh()) + zeroField)
  9793  	}
  9794  	*prg.mem[int32(prg.curEdges)+4].int() = 0
  9795  }
  9796  
  9797  // 354.
  9798  
  9799  // tangle:pos ../../mf.web:7698:3:
  9800  
  9801  // The last and most difficult routine for transforming an edge structure---and
  9802  // the most interesting one!---is |xy_swap_edges|, which interchanges the
  9803  // r\^^Doles of rows and columns. Its task can be viewed as the job of
  9804  // creating an edge structure that contains only horizontal edges, linked
  9805  // together in columns, given an edge structure that contains only
  9806  // vertical edges linked together in rows; we must do this without changing
  9807  // the implied pixel weights.
  9808  //
  9809  // Given any two adjacent rows of an edge structure, it is not difficult to
  9810  // determine the horizontal edges that lie ``between'' them: We simply look
  9811  // for vertically adjacent pixels that have different weight, and insert
  9812  // a horizontal edge containing the difference in weights. Every horizontal
  9813  // edge determined in this way should be put into an appropriate linked
  9814  // list. Since random access to these linked lists is desirable, we use
  9815  // the |move| array to hold the list heads. If we work through the given
  9816  // edge structure from top to bottom, the constructed lists will not need
  9817  // to be sorted, since they will already be in order.
  9818  //
  9819  // The following algorithm makes use of some ideas suggested by John Hobby.
  9820  // \xref[Hobby, John Douglas]
  9821  // It assumes that the edge structure is non-null, i.e., that |link(cur_edges)
  9822  // <>cur_edges|, hence |m_max(cur_edges)>=m_min(cur_edges)|.
  9823  func (prg *prg) xySwapEdges() {
  9824  	var (
  9825  		mMagic, nMagic int32    // special values that account for offsets
  9826  		p, q, r1, s    halfword // pointers that traverse the given structure
  9827  
  9828  		// Other local variables for |xy_swap_edges|
  9829  		mSpread                       int32 // the difference between |m_max| and |m_min|
  9830  		j, jj/* 0..moveSize */ uint16       // indices into |move|
  9831  		m, mm                         int32 // |m| values at vertical edges
  9832  		pd, rd                        int32 // data fields from edge-and-weight nodes
  9833  		pm, rm                        int32 // |m| values from edge-and-weight nodes
  9834  		w                             int32 // the difference in accumulated weight
  9835  		ww                            int32 // as much of |w| that can be stored in a single node
  9836  		dw                            int32 // an increment to be added to |w|
  9837  
  9838  		extras              int32 // the number of additional nodes to make weights |>3|
  9839  		xw/*  -3..3 */ int8       // the additional weight in extra nodes
  9840  		k                   int32 // loop counter for inserting extra nodes
  9841  	)
  9842  	mSpread = int32(*(*prg.mem[int32(prg.curEdges)+2].hh()).rh()) - int32(*(*prg.mem[int32(prg.curEdges)+2].hh()).lh()) // this is |>=0| by assumption
  9843  	if mSpread > moveSize {
  9844  		prg.overflow(strNumber( /* "move table size" */ 540), moveSize)
  9845  	}
  9846  	// \xref[METAFONT capacity exceeded move table size][\quad move table size]
  9847  	for ii := int32(0); ii <= mSpread; ii++ {
  9848  		j = uint16(ii)
  9849  		_ = j
  9850  		prg.move[j] = 3000
  9851  	}
  9852  
  9853  	// Insert blank rows at the top and bottom, and set |p| to the new top row
  9854  	p = prg.getNode(rowNodeSize)
  9855  	*(*prg.mem[int32(p)+1].hh()).rh() = 3000
  9856  	*(*prg.mem[int32(p)+1].hh()).lh() = uint16(memMin)
  9857  
  9858  	*(*prg.mem[p].hh()).lh() = prg.curEdges
  9859  	*(*prg.mem[*(*prg.mem[prg.curEdges].hh()).rh()].hh()).lh() = p // the new bottom row
  9860  	p = prg.getNode(rowNodeSize)
  9861  	*(*prg.mem[int32(p)+1].hh()).rh() = 3000
  9862  	*(*prg.mem[p].hh()).lh() = *(*prg.mem[prg.curEdges].hh()).lh() // the new top row
  9863  
  9864  	// Compute the magic offset values
  9865  	mMagic = int32(*(*prg.mem[int32(prg.curEdges)+2].hh()).lh()) + int32(*(*prg.mem[int32(prg.curEdges)+3].hh()).lh()) - zeroField
  9866  	nMagic = 8*int32(*(*prg.mem[int32(prg.curEdges)+1].hh()).rh()) + 8 + zeroW + 0
  9867  	for {
  9868  		q = *(*prg.mem[p].hh()).lh()
  9869  		if int32(*(*prg.mem[int32(q)+1].hh()).lh()) > memMin+1 {
  9870  			prg.sortEdges(q)
  9871  		}
  9872  
  9873  		// Insert the horizontal edges defined by adjacent rows |p,q|, and destroy row~|p|
  9874  		r1 = *(*prg.mem[int32(p)+1].hh()).rh()
  9875  		prg.freeNode(p, halfword(rowNodeSize))
  9876  		p = r1
  9877  
  9878  		pd = int32(*(*prg.mem[p].hh()).lh()) - 0
  9879  		pm = pd / 8
  9880  
  9881  		r1 = *(*prg.mem[int32(q)+1].hh()).rh()
  9882  		rd = int32(*(*prg.mem[r1].hh()).lh()) - 0
  9883  		rm = rd / 8
  9884  		w = 0
  9885  		for true {
  9886  			if pm < rm {
  9887  				mm = pm
  9888  			} else {
  9889  				mm = rm
  9890  			}
  9891  			if w != 0 {
  9892  				if m != mm {
  9893  					if mm-mMagic >= moveSize {
  9894  						prg.confusion(strNumber( /* "xy" */ 510))
  9895  					}
  9896  					// \xref[this can't happen xy][\quad xy]
  9897  					extras = (abs(w) - 1) / 3
  9898  					if extras > 0 {
  9899  						if w > 0 {
  9900  							xw = int8(+3)
  9901  						} else {
  9902  							xw = int8(-3)
  9903  						}
  9904  						ww = w - extras*int32(xw)
  9905  					} else {
  9906  						ww = w
  9907  					}
  9908  					for {
  9909  						j = uint16(m - mMagic)
  9910  						for ii := int32(1); ii <= extras; ii++ {
  9911  							k = ii
  9912  							_ = k
  9913  							s = prg.getAvail()
  9914  							*(*prg.mem[s].hh()).lh() = uint16(nMagic + int32(xw))
  9915  							*(*prg.mem[s].hh()).rh() = uint16(prg.move[j])
  9916  							prg.move[j] = int32(s)
  9917  						}
  9918  						s = prg.getAvail()
  9919  						*(*prg.mem[s].hh()).lh() = uint16(nMagic + ww)
  9920  						*(*prg.mem[s].hh()).rh() = uint16(prg.move[j])
  9921  						prg.move[j] = int32(s)
  9922  
  9923  						m = m + 1
  9924  						if m == mm {
  9925  							break
  9926  						}
  9927  					}
  9928  				}
  9929  			}
  9930  			if pd < rd {
  9931  				dw = pd%8 - zeroW
  9932  
  9933  				// Advance pointer |p| to the next vertical edge, after destroying the previous one
  9934  				s = *(*prg.mem[p].hh()).rh()
  9935  				{
  9936  					*(*prg.mem[p].hh()).rh() = prg.avail
  9937  					prg.avail = p
  9938  					prg.dynUsed = prg.dynUsed - 1
  9939  				}
  9940  				p = s
  9941  				pd = int32(*(*prg.mem[p].hh()).lh()) - 0
  9942  				pm = pd / 8
  9943  			} else {
  9944  				if int32(r1) == 3000 {
  9945  					goto done
  9946  				} // |rd=pd=ho(max_halfword)|
  9947  				dw = -(rd%8 - zeroW)
  9948  
  9949  				// Advance pointer |r| to the next vertical edge
  9950  				r1 = *(*prg.mem[r1].hh()).rh()
  9951  				rd = int32(*(*prg.mem[r1].hh()).lh()) - 0
  9952  				rm = rd / 8
  9953  			}
  9954  			m = mm
  9955  			w = w + dw
  9956  		}
  9957  
  9958  	done:
  9959  		;
  9960  		p = q
  9961  		nMagic = nMagic - 8
  9962  		if int32(*(*prg.mem[p].hh()).lh()) == int32(prg.curEdges) {
  9963  			break
  9964  		}
  9965  	}
  9966  	prg.freeNode(p, halfword(rowNodeSize)) // now all original rows have been recycled
  9967  
  9968  	// Adjust the header to reflect the new edges
  9969  	prg.move[mSpread] = 0
  9970  	j = 0
  9971  	for prg.move[j] == 3000 {
  9972  		j = uint16(int32(j) + 1)
  9973  	}
  9974  	if int32(j) == mSpread {
  9975  		prg.initEdges(prg.curEdges)
  9976  	} else {
  9977  		mm = int32(*(*prg.mem[int32(prg.curEdges)+2].hh()).lh())
  9978  		*(*prg.mem[int32(prg.curEdges)+2].hh()).lh() = *(*prg.mem[int32(prg.curEdges)+1].hh()).lh()
  9979  		*(*prg.mem[int32(prg.curEdges)+2].hh()).rh() = uint16(int32(*(*prg.mem[int32(prg.curEdges)+1].hh()).rh()) + 1)
  9980  		*(*prg.mem[int32(prg.curEdges)+3].hh()).lh() = uint16(zeroField)
  9981  		jj = uint16(mSpread - 1)
  9982  		for prg.move[jj] == 3000 {
  9983  			jj = uint16(int32(jj) - 1)
  9984  		}
  9985  		*(*prg.mem[int32(prg.curEdges)+1].hh()).lh() = uint16(int32(j) + mm)
  9986  		*(*prg.mem[int32(prg.curEdges)+1].hh()).rh() = uint16(int32(jj) + mm)
  9987  		q = prg.curEdges
  9988  		for {
  9989  			p = prg.getNode(rowNodeSize)
  9990  			*(*prg.mem[q].hh()).rh() = p
  9991  			*(*prg.mem[p].hh()).lh() = q
  9992  			*(*prg.mem[int32(p)+1].hh()).rh() = uint16(prg.move[j])
  9993  			*(*prg.mem[int32(p)+1].hh()).lh() = uint16(memMin)
  9994  			j = uint16(int32(j) + 1)
  9995  			q = p
  9996  			if int32(j) > int32(jj) {
  9997  				break
  9998  			}
  9999  		}
 10000  		*(*prg.mem[q].hh()).rh() = prg.curEdges
 10001  		*(*prg.mem[prg.curEdges].hh()).lh() = q
 10002  		*(*prg.mem[int32(prg.curEdges)+5].hh()).lh() = uint16(int32(*(*prg.mem[int32(prg.curEdges)+1].hh()).rh()) + 1)
 10003  		*(*prg.mem[int32(prg.curEdges)+5].hh()).rh() = prg.curEdges
 10004  		*prg.mem[int32(prg.curEdges)+4].int() = 0
 10005  	}
 10006  
 10007  }
 10008  
 10009  // 361.
 10010  
 10011  // tangle:pos ../../mf.web:7797:3:
 10012  
 10013  // Certain ``magic'' values are needed to make the following code work,
 10014  // because of the various offsets in our data structure. For now, let's not
 10015  // worry about their precise values; we shall compute |m_magic| and |n_magic|
 10016  // later, after we see what the code looks like.
 10017  
 10018  // 366.
 10019  
 10020  // tangle:pos ../../mf.web:7858:3:
 10021  
 10022  // Now let's look at the subroutine that merges the edges from a given
 10023  // edge structure into |cur_edges|. The given edge structure loses all its
 10024  // edges.
 10025  func (prg *prg) mergeEdges(h halfword) {
 10026  	var (
 10027  		p, q, r1, pp, qq, rr halfword // list manipulation registers
 10028  		n                    int32    // row number
 10029  		k                    halfword // key register that we compare to |info(q)|
 10030  		delta                int32    // change to the edge/weight data
 10031  	)
 10032  	if int32(*(*prg.mem[h].hh()).rh()) != int32(h) {
 10033  		if int32(*(*prg.mem[int32(h)+2].hh()).lh()) < int32(*(*prg.mem[int32(prg.curEdges)+2].hh()).lh()) || int32(*(*prg.mem[int32(h)+2].hh()).rh()) > int32(*(*prg.mem[int32(prg.curEdges)+2].hh()).rh()) || int32(*(*prg.mem[int32(h)+1].hh()).lh()) < int32(*(*prg.mem[int32(prg.curEdges)+1].hh()).lh()) || int32(*(*prg.mem[int32(h)+1].hh()).rh()) > int32(*(*prg.mem[int32(prg.curEdges)+1].hh()).rh()) {
 10034  			prg.edgePrep(int32(*(*prg.mem[int32(h)+2].hh()).lh())-zeroField, int32(*(*prg.mem[int32(h)+2].hh()).rh())-zeroField, int32(*(*prg.mem[int32(h)+1].hh()).lh())-zeroField, int32(*(*prg.mem[int32(h)+1].hh()).rh())-zeroField+1)
 10035  		}
 10036  		if int32(*(*prg.mem[int32(h)+3].hh()).lh()) != int32(*(*prg.mem[int32(prg.curEdges)+3].hh()).lh()) {
 10037  			pp = *(*prg.mem[h].hh()).rh()
 10038  			delta = 8 * (int32(*(*prg.mem[int32(prg.curEdges)+3].hh()).lh()) - int32(*(*prg.mem[int32(h)+3].hh()).lh()))
 10039  			for {
 10040  				qq = *(*prg.mem[int32(pp)+1].hh()).rh()
 10041  				for int32(qq) != 3000 {
 10042  					*(*prg.mem[qq].hh()).lh() = uint16(int32(*(*prg.mem[qq].hh()).lh()) + delta)
 10043  					qq = *(*prg.mem[qq].hh()).rh()
 10044  				}
 10045  				qq = *(*prg.mem[int32(pp)+1].hh()).lh()
 10046  				for int32(qq) > memMin+1 {
 10047  					*(*prg.mem[qq].hh()).lh() = uint16(int32(*(*prg.mem[qq].hh()).lh()) + delta)
 10048  					qq = *(*prg.mem[qq].hh()).rh()
 10049  				}
 10050  				pp = *(*prg.mem[pp].hh()).rh()
 10051  				if int32(pp) == int32(h) {
 10052  					break
 10053  				}
 10054  			}
 10055  		}
 10056  		n = int32(*(*prg.mem[int32(prg.curEdges)+1].hh()).lh())
 10057  		p = *(*prg.mem[prg.curEdges].hh()).rh()
 10058  		pp = *(*prg.mem[h].hh()).rh()
 10059  		for n < int32(*(*prg.mem[int32(h)+1].hh()).lh()) {
 10060  			n = n + 1
 10061  			p = *(*prg.mem[p].hh()).rh()
 10062  		}
 10063  		for {
 10064  			// Merge row |pp| into row |p|
 10065  			qq = *(*prg.mem[int32(pp)+1].hh()).lh()
 10066  			if int32(qq) > memMin+1 {
 10067  				if int32(*(*prg.mem[int32(p)+1].hh()).lh()) <= memMin+1 {
 10068  					*(*prg.mem[int32(p)+1].hh()).lh() = qq
 10069  				} else {
 10070  					for int32(*(*prg.mem[qq].hh()).rh()) > memMin+1 {
 10071  						qq = *(*prg.mem[qq].hh()).rh()
 10072  					}
 10073  					*(*prg.mem[qq].hh()).rh() = *(*prg.mem[int32(p)+1].hh()).lh()
 10074  					*(*prg.mem[int32(p)+1].hh()).lh() = *(*prg.mem[int32(pp)+1].hh()).lh()
 10075  				}
 10076  			}
 10077  			*(*prg.mem[int32(pp)+1].hh()).lh() = uint16(memMin)
 10078  			qq = *(*prg.mem[int32(pp)+1].hh()).rh()
 10079  			if int32(qq) != 3000 {
 10080  				if int32(*(*prg.mem[int32(p)+1].hh()).lh()) == memMin+1 {
 10081  					*(*prg.mem[int32(p)+1].hh()).lh() = uint16(memMin)
 10082  				}
 10083  				*(*prg.mem[int32(pp)+1].hh()).rh() = 3000
 10084  				r1 = uint16(int32(p) + 1)
 10085  				q = *(*prg.mem[r1].hh()).rh() // |q=sorted(p)|
 10086  				if int32(q) == 3000 {
 10087  					*(*prg.mem[int32(p)+1].hh()).rh() = qq
 10088  				} else {
 10089  					for true {
 10090  						k = *(*prg.mem[qq].hh()).lh()
 10091  						for int32(k) > int32(*(*prg.mem[q].hh()).lh()) {
 10092  							r1 = q
 10093  							q = *(*prg.mem[r1].hh()).rh()
 10094  						}
 10095  						*(*prg.mem[r1].hh()).rh() = qq
 10096  						rr = *(*prg.mem[qq].hh()).rh()
 10097  						*(*prg.mem[qq].hh()).rh() = q
 10098  						if int32(rr) == 3000 {
 10099  							goto done
 10100  						}
 10101  						r1 = qq
 10102  						qq = rr
 10103  					}
 10104  				}
 10105  			}
 10106  
 10107  		done:
 10108  			;
 10109  			pp = *(*prg.mem[pp].hh()).rh()
 10110  			p = *(*prg.mem[p].hh()).rh()
 10111  			if int32(pp) == int32(h) {
 10112  				break
 10113  			}
 10114  		}
 10115  	}
 10116  }
 10117  
 10118  // 369.
 10119  
 10120  // tangle:pos ../../mf.web:7926:3:
 10121  
 10122  // The |total_weight| routine computes the total of all pixel weights
 10123  // in a given edge structure. It's not difficult to prove that this is
 10124  // the sum of $(-w)$ times $x$ taken over all edges,
 10125  // where $w$ and~$x$ are the weight and $x$~coordinates stored in an edge.
 10126  // It's not necessary to worry that this quantity will overflow the
 10127  // size of an |integer| register, because it will be less than~$2^[31]$
 10128  // unless the edge structure has more than 174,762 edges. However, we had
 10129  // better not try to compute it as a |scaled| integer, because a total
 10130  // weight of almost $12\times 2^[12]$ can be produced by only four edges.
 10131  func (prg *prg) totalWeight(h halfword) (r int32) { // |h| is an edge header
 10132  	var (
 10133  		p, q                   halfword // variables that traverse the given structure
 10134  		n                      int32    // accumulated total so far
 10135  		m/* 0..65535 */ uint16          // packed $x$ and $w$ values, including offsets
 10136  	)
 10137  	n = 0
 10138  	p = *(*prg.mem[h].hh()).rh()
 10139  	for int32(p) != int32(h) {
 10140  		q = *(*prg.mem[int32(p)+1].hh()).rh()
 10141  		for int32(q) != 3000 {
 10142  
 10143  			// Add the contribution of node |q| to the total weight, and set |q:=link(q)|
 10144  			m = uint16(int32(*(*prg.mem[q].hh()).lh()) - 0)
 10145  			n = n - (int32(m)%8-zeroW)*(int32(m)/8)
 10146  			q = *(*prg.mem[q].hh()).rh()
 10147  		}
 10148  		q = *(*prg.mem[int32(p)+1].hh()).lh()
 10149  		for int32(q) > memMin+1 {
 10150  
 10151  			// Add the contribution of node |q| to the total weight, and set |q:=link(q)|
 10152  			m = uint16(int32(*(*prg.mem[q].hh()).lh()) - 0)
 10153  			n = n - (int32(m)%8-zeroW)*(int32(m)/8)
 10154  			q = *(*prg.mem[q].hh()).rh()
 10155  		}
 10156  		p = *(*prg.mem[p].hh()).rh()
 10157  	}
 10158  	r = n
 10159  	return r
 10160  }
 10161  
 10162  // 372.
 10163  
 10164  // tangle:pos ../../mf.web:7983:3:
 10165  
 10166  // Edge tracing is initiated by the |begin_edge_tracing| routine,
 10167  // continued by the |trace_a_corner| routine, and terminated by the
 10168  // |end_edge_tracing| routine.
 10169  func (prg *prg) beginEdgeTracing() {
 10170  	prg.printDiagnostic(strNumber( /* "Tracing edges" */ 541), strNumber( /* "" */ 285), true)
 10171  	prg.print( /* " (weight " */ 542)
 10172  	prg.printInt(prg.curWt)
 10173  	prg.printChar(asciiCode(')'))
 10174  	prg.traceX = -4096
 10175  }
 10176  
 10177  func (prg *prg) traceACorner() {
 10178  	if int32(prg.fileOffset) > maxPrintLine-13 {
 10179  		prg.printNl(strNumber( /* "" */ 285))
 10180  	}
 10181  	prg.printChar(asciiCode('('))
 10182  	prg.printInt(prg.traceX)
 10183  	prg.printChar(asciiCode(','))
 10184  	prg.printInt(prg.traceYy)
 10185  	prg.printChar(asciiCode(')'))
 10186  	prg.traceY = prg.traceYy
 10187  }
 10188  
 10189  func (prg *prg) endEdgeTracing() {
 10190  	if prg.traceX == -4096 {
 10191  		prg.printNl(strNumber( /* "(No new edges added.)" */ 543))
 10192  	} else {
 10193  		prg.traceACorner()
 10194  		prg.printChar(asciiCode('.'))
 10195  	}
 10196  	prg.endDiagnostic(true)
 10197  }
 10198  
 10199  // 373.
 10200  
 10201  // tangle:pos ../../mf.web:8006:3:
 10202  
 10203  // Just after a new edge weight has been put into the |info| field of
 10204  // node~|r|, in row~|n|, the following routine continues an ongoing trace.
 10205  func (prg *prg) traceNewEdge(r1 halfword, n int32) {
 10206  	var (
 10207  		d                  int32 // temporary data register
 10208  		w/*  -3..3 */ int8       // weight associated with an edge transition
 10209  		m, n0, n1          int32 // column and row numbers
 10210  	)
 10211  	d = int32(*(*prg.mem[r1].hh()).lh()) - 0
 10212  	w = int8(d%8 - zeroW)
 10213  	m = d/8 - int32(*(*prg.mem[int32(prg.curEdges)+3].hh()).lh())
 10214  	if int32(w) == prg.curWt {
 10215  		n0 = n + 1
 10216  		n1 = n
 10217  	} else {
 10218  		n0 = n
 10219  		n1 = n + 1
 10220  	} // the edges run from |(m,n0)| to |(m,n1)|
 10221  	if m != prg.traceX {
 10222  		if prg.traceX == -4096 {
 10223  			prg.printNl(strNumber( /* "" */ 285))
 10224  			prg.traceYy = n0
 10225  		} else if prg.traceYy != n0 {
 10226  			prg.printChar(asciiCode('?'))
 10227  		} else {
 10228  			prg.traceACorner()
 10229  		}
 10230  		prg.traceX = m
 10231  		prg.traceACorner()
 10232  	} else {
 10233  		if n0 != prg.traceYy {
 10234  			prg.printChar(asciiCode('!'))
 10235  		} // shouldn't happen
 10236  		if n0 < n1 && prg.traceY > prg.traceYy || n0 > n1 && prg.traceY < prg.traceYy {
 10237  			prg.traceACorner()
 10238  		}
 10239  	}
 10240  	prg.traceYy = n1
 10241  }
 10242  
 10243  // 374.
 10244  
 10245  // tangle:pos ../../mf.web:8034:3:
 10246  
 10247  // One way to put new edge weights into an edge structure is to use the
 10248  // following routine, which simply draws a straight line from |(x0,y0)| to
 10249  // |(x1,y1)|. More precisely, it introduces weights for the edges of the
 10250  // discrete path $\bigl(\lfloor t[x_0,x_1]+[1\over2]+\epsilon\rfloor,
 10251  // \lfloor t[y_0,y_1]+[1\over2]+\epsilon\delta\rfloor\bigr)$,
 10252  // as $t$ varies from 0 to~1, where $\epsilon$ and $\delta$ are extremely small
 10253  // positive numbers.
 10254  //
 10255  // The structure header is assumed to be |cur_edges|; downward edge weights
 10256  // will be |cur_wt|, while upward ones will be |-cur_wt|.
 10257  //
 10258  // Of course, this subroutine will be called only in connection with others
 10259  // that eventually draw a complete cycle, so that the sum of the edge weights
 10260  // in each row will be zero whenever the row is displayed.
 10261  func (prg *prg) lineEdges(x0, y0, x1, y1 scaled) {
 10262  	var (
 10263  		m0, n0, m1, n1 int32    // rounded and unscaled coordinates
 10264  		delx, dely     scaled   // the coordinate differences of the line
 10265  		yt             scaled   // smallest |y| coordinate that rounds the same as |y0|
 10266  		tx             scaled   // tentative change in |x|
 10267  		p, r1          halfword // list manipulation registers
 10268  		base           int32    // amount added to edge-and-weight data
 10269  		n              int32    // current row number
 10270  	)
 10271  	n0 = prg.roundUnscaled(y0)
 10272  	n1 = prg.roundUnscaled(y1)
 10273  	if n0 != n1 {
 10274  		m0 = prg.roundUnscaled(x0)
 10275  		m1 = prg.roundUnscaled(x1)
 10276  		delx = x1 - x0
 10277  		dely = y1 - y0
 10278  		yt = n0*0200000 - 0100000
 10279  		y0 = y0 - yt
 10280  		y1 = y1 - yt
 10281  		if n0 < n1 {
 10282  			base = 8*int32(*(*prg.mem[int32(prg.curEdges)+3].hh()).lh()) + 0 + zeroW - prg.curWt
 10283  			if m0 <= m1 {
 10284  				prg.edgePrep(m0, m1, n0, n1)
 10285  			} else {
 10286  				prg.edgePrep(m1, m0, n0, n1)
 10287  			}
 10288  
 10289  			// Move to row |n0|, pointed to by |p|
 10290  			n = int32(*(*prg.mem[int32(prg.curEdges)+5].hh()).lh()) - zeroField
 10291  			p = *(*prg.mem[int32(prg.curEdges)+5].hh()).rh()
 10292  			if n != n0 {
 10293  				if n < n0 {
 10294  					for {
 10295  						n = n + 1
 10296  						p = *(*prg.mem[p].hh()).rh()
 10297  						if n == n0 {
 10298  							break
 10299  						}
 10300  					}
 10301  				} else {
 10302  					for {
 10303  						n = n - 1
 10304  						p = *(*prg.mem[p].hh()).lh()
 10305  						if n == n0 {
 10306  							break
 10307  						}
 10308  					}
 10309  				}
 10310  			}
 10311  			y0 = 0200000 - y0
 10312  			for true {
 10313  				r1 = prg.getAvail()
 10314  				*(*prg.mem[r1].hh()).rh() = *(*prg.mem[int32(p)+1].hh()).lh()
 10315  				*(*prg.mem[int32(p)+1].hh()).lh() = r1
 10316  
 10317  				tx = prg.takeFraction(delx, prg.makeFraction(y0, dely))
 10318  				if prg.abVsCd(delx, y0, dely, tx) < 0 {
 10319  					tx = tx - 1
 10320  				}
 10321  				// now $|tx|=\lfloor|y0|\cdot|delx|/|dely|\rfloor$
 10322  				*(*prg.mem[r1].hh()).lh() = uint16(8*prg.roundUnscaled(x0+tx) + base)
 10323  
 10324  				y1 = y1 - 0200000
 10325  				if prg.internal[tracingEdges-1] > 0 {
 10326  					prg.traceNewEdge(r1, n)
 10327  				}
 10328  				if y1 < 0200000 {
 10329  					goto done
 10330  				}
 10331  				p = *(*prg.mem[p].hh()).rh()
 10332  				y0 = y0 + 0200000
 10333  				n = n + 1
 10334  			}
 10335  
 10336  		done:
 10337  		} else {
 10338  			// Insert downward edges for a line
 10339  			base = 8*int32(*(*prg.mem[int32(prg.curEdges)+3].hh()).lh()) + 0 + zeroW + prg.curWt
 10340  			if m0 <= m1 {
 10341  				prg.edgePrep(m0, m1, n1, n0)
 10342  			} else {
 10343  				prg.edgePrep(m1, m0, n1, n0)
 10344  			}
 10345  			n0 = n0 - 1
 10346  			// Move to row |n0|, pointed to by |p|
 10347  			n = int32(*(*prg.mem[int32(prg.curEdges)+5].hh()).lh()) - zeroField
 10348  			p = *(*prg.mem[int32(prg.curEdges)+5].hh()).rh()
 10349  			if n != n0 {
 10350  				if n < n0 {
 10351  					for {
 10352  						n = n + 1
 10353  						p = *(*prg.mem[p].hh()).rh()
 10354  						if n == n0 {
 10355  							break
 10356  						}
 10357  					}
 10358  				} else {
 10359  					for {
 10360  						n = n - 1
 10361  						p = *(*prg.mem[p].hh()).lh()
 10362  						if n == n0 {
 10363  							break
 10364  						}
 10365  					}
 10366  				}
 10367  			}
 10368  			for true {
 10369  				r1 = prg.getAvail()
 10370  				*(*prg.mem[r1].hh()).rh() = *(*prg.mem[int32(p)+1].hh()).lh()
 10371  				*(*prg.mem[int32(p)+1].hh()).lh() = r1
 10372  
 10373  				tx = prg.takeFraction(delx, prg.makeFraction(y0, dely))
 10374  				if prg.abVsCd(delx, y0, dely, tx) < 0 {
 10375  					tx = tx + 1
 10376  				}
 10377  				// now $|tx|=\lceil|y0|\cdot|delx|/|dely|\rceil$, since |dely<0|
 10378  				*(*prg.mem[r1].hh()).lh() = uint16(8*prg.roundUnscaled(x0-tx) + base)
 10379  
 10380  				y1 = y1 + 0200000
 10381  				if prg.internal[tracingEdges-1] > 0 {
 10382  					prg.traceNewEdge(r1, n)
 10383  				}
 10384  				if y1 >= 0 {
 10385  					goto done1
 10386  				}
 10387  				p = *(*prg.mem[p].hh()).lh()
 10388  				y0 = y0 + 0200000
 10389  				n = n - 1
 10390  			}
 10391  
 10392  		done1:
 10393  		}
 10394  		*(*prg.mem[int32(prg.curEdges)+5].hh()).rh() = p
 10395  		*(*prg.mem[int32(prg.curEdges)+5].hh()).lh() = uint16(n + zeroField)
 10396  	}
 10397  }
 10398  
 10399  // 378.
 10400  
 10401  // tangle:pos ../../mf.web:8114:3:
 10402  
 10403  // \MF\ inserts most of its edges into edge structures via the
 10404  // |move_to_edges| subroutine, which uses the data stored in the |move| array
 10405  // to specify a sequence of ``rook moves.'' The starting point |(m0,n0)|
 10406  // and finishing point |(m1,n1)| of these moves, as seen from the standpoint
 10407  // of the first octant, are supplied as parameters; the moves should, however,
 10408  // be rotated into a given octant.  (We're going to study octant
 10409  // transformations in great detail later; the reader may wish to come back to
 10410  // this part of the program after mastering the mysteries of octants.)
 10411  //
 10412  // The rook moves themselves are defined as follows, from a |first_octant|
 10413  // point of view: ``Go right |move[k]| steps, then go up one, for |0<=k<n1-n0|;
 10414  // then go right |move[n1-n0]| steps and stop.'' The sum of |move[k]|
 10415  // for |0<=k<=n1-n0| will be equal to |m1-m0|.
 10416  //
 10417  // As in the |line_edges| routine, we use |+cur_wt| as the weight of
 10418  // all downward edges and |-cur_wt| as the weight of all upward edges,
 10419  // after the moves have been rotated to the proper octant direction.
 10420  //
 10421  // There are two main cases to consider: \\[fast\_case] is for moves that
 10422  // travel in the direction of octants 1, 4, 5, and~8, while \\[slow\_case]
 10423  // is for moves that travel toward octants 2, 3, 6, and~7. The latter directions
 10424  // are comparatively cumbersome because they generate more upward or downward
 10425  // edges; a curve that travels horizontally doesn't produce any edges at all,
 10426  // but a curve that travels vertically touches lots of rows.
 10427  func (prg *prg) moveToEdges(m0, n0, m1, n1 int32) {
 10428  	var (
 10429  		delta/* 0..moveSize */ uint16          // extent of |move| data
 10430  		k/* 0..moveSize */ uint16              // index into |move|
 10431  		p, r1                         halfword // list manipulation registers
 10432  		dx                            int32    // change in edge-weight |info| when |x| changes by 1
 10433  		edgeAndWeight                 int32    // |info| to insert
 10434  		j                             int32    // number of consecutive vertical moves
 10435  		n                             int32    // the current row pointed to by |p|
 10436  	// sum:integer; [  ]
 10437  	)
 10438  	delta = uint16(n1 - n0)
 10439  	//  sum:=move[0]; for k:=1 to delta do sum:=sum+abs(move[k]);
 10440  	// if sum<>m1-m0 then confusion(["0"=]48); [  ]
 10441  
 10442  	// \xref[this can't happen 0][\quad 0]
 10443  
 10444  	// Prepare for and switch to the appropriate case, based on |octant|
 10445  	switch prg.octant {
 10446  	case firstOctant:
 10447  		dx = 8
 10448  		prg.edgePrep(m0, m1, n0, n1)
 10449  		goto fastCaseUp
 10450  
 10451  	case secondOctant:
 10452  		dx = 8
 10453  		prg.edgePrep(n0, n1, m0, m1)
 10454  		goto slowCaseUp
 10455  
 10456  	case thirdOctant:
 10457  		dx = -8
 10458  		prg.edgePrep(-n1, -n0, m0, m1)
 10459  		n0 = -n0
 10460  
 10461  		goto slowCaseUp
 10462  
 10463  	case fourthOctant:
 10464  		dx = -8
 10465  		prg.edgePrep(-m1, -m0, n0, n1)
 10466  		m0 = -m0
 10467  
 10468  		goto fastCaseUp
 10469  
 10470  	case fifthOctant:
 10471  		dx = -8
 10472  		prg.edgePrep(-m1, -m0, -n1, -n0)
 10473  		m0 = -m0
 10474  
 10475  		goto fastCaseDown
 10476  
 10477  	case sixthOctant:
 10478  		dx = -8
 10479  		prg.edgePrep(-n1, -n0, -m1, -m0)
 10480  		n0 = -n0
 10481  
 10482  		goto slowCaseDown
 10483  
 10484  	case seventhOctant:
 10485  		dx = 8
 10486  		prg.edgePrep(n0, n1, -m1, -m0)
 10487  		goto slowCaseDown
 10488  
 10489  	case eighthOctant:
 10490  		dx = 8
 10491  		prg.edgePrep(m0, m1, -n1, -n0)
 10492  		goto fastCaseDown
 10493  
 10494  	} // there are only eight octants
 10495  
 10496  fastCaseUp:
 10497  	n = int32(*(*prg.mem[int32(prg.curEdges)+5].hh()).lh()) - zeroField
 10498  	p = *(*prg.mem[int32(prg.curEdges)+5].hh()).rh()
 10499  	if n != n0 {
 10500  		if n < n0 {
 10501  			for {
 10502  				n = n + 1
 10503  				p = *(*prg.mem[p].hh()).rh()
 10504  				if n == n0 {
 10505  					break
 10506  				}
 10507  			}
 10508  		} else {
 10509  			for {
 10510  				n = n - 1
 10511  				p = *(*prg.mem[p].hh()).lh()
 10512  				if n == n0 {
 10513  					break
 10514  				}
 10515  			}
 10516  		}
 10517  	}
 10518  	if int32(delta) > 0 {
 10519  		k = 0
 10520  		edgeAndWeight = 8*(m0+int32(*(*prg.mem[int32(prg.curEdges)+3].hh()).lh())) + 0 + zeroW - prg.curWt
 10521  		for {
 10522  			edgeAndWeight = edgeAndWeight + dx*prg.move[k]
 10523  			/*   */ {
 10524  				r1 = prg.avail
 10525  				if int32(r1) == memMin {
 10526  					r1 = prg.getAvail()
 10527  				} else {
 10528  					prg.avail = *(*prg.mem[r1].hh()).rh()
 10529  					*(*prg.mem[r1].hh()).rh() = uint16(memMin)
 10530  					prg.dynUsed = prg.dynUsed + 1
 10531  				}
 10532  			}
 10533  			*(*prg.mem[r1].hh()).rh() = *(*prg.mem[int32(p)+1].hh()).lh()
 10534  			*(*prg.mem[r1].hh()).lh() = uint16(edgeAndWeight)
 10535  			if prg.internal[tracingEdges-1] > 0 {
 10536  				prg.traceNewEdge(r1, n)
 10537  			}
 10538  			*(*prg.mem[int32(p)+1].hh()).lh() = r1
 10539  			p = *(*prg.mem[p].hh()).rh()
 10540  			k = uint16(int32(k) + 1)
 10541  			n = n + 1
 10542  			if int32(k) == int32(delta) {
 10543  				break
 10544  			}
 10545  		}
 10546  	}
 10547  
 10548  	goto done
 10549  
 10550  fastCaseDown:
 10551  	n0 = -n0 - 1
 10552  	// Move to row |n0|, pointed to by |p|
 10553  	n = int32(*(*prg.mem[int32(prg.curEdges)+5].hh()).lh()) - zeroField
 10554  	p = *(*prg.mem[int32(prg.curEdges)+5].hh()).rh()
 10555  	if n != n0 {
 10556  		if n < n0 {
 10557  			for {
 10558  				n = n + 1
 10559  				p = *(*prg.mem[p].hh()).rh()
 10560  				if n == n0 {
 10561  					break
 10562  				}
 10563  			}
 10564  		} else {
 10565  			for {
 10566  				n = n - 1
 10567  				p = *(*prg.mem[p].hh()).lh()
 10568  				if n == n0 {
 10569  					break
 10570  				}
 10571  			}
 10572  		}
 10573  	}
 10574  	if int32(delta) > 0 {
 10575  		k = 0
 10576  		edgeAndWeight = 8*(m0+int32(*(*prg.mem[int32(prg.curEdges)+3].hh()).lh())) + 0 + zeroW + prg.curWt
 10577  		for {
 10578  			edgeAndWeight = edgeAndWeight + dx*prg.move[k]
 10579  			/*   */ {
 10580  				r1 = prg.avail
 10581  				if int32(r1) == memMin {
 10582  					r1 = prg.getAvail()
 10583  				} else {
 10584  					prg.avail = *(*prg.mem[r1].hh()).rh()
 10585  					*(*prg.mem[r1].hh()).rh() = uint16(memMin)
 10586  					prg.dynUsed = prg.dynUsed + 1
 10587  				}
 10588  			}
 10589  			*(*prg.mem[r1].hh()).rh() = *(*prg.mem[int32(p)+1].hh()).lh()
 10590  			*(*prg.mem[r1].hh()).lh() = uint16(edgeAndWeight)
 10591  			if prg.internal[tracingEdges-1] > 0 {
 10592  				prg.traceNewEdge(r1, n)
 10593  			}
 10594  			*(*prg.mem[int32(p)+1].hh()).lh() = r1
 10595  			p = *(*prg.mem[p].hh()).lh()
 10596  			k = uint16(int32(k) + 1)
 10597  			n = n - 1
 10598  			if int32(k) == int32(delta) {
 10599  				break
 10600  			}
 10601  		}
 10602  	}
 10603  
 10604  	goto done
 10605  
 10606  slowCaseUp:
 10607  	edgeAndWeight = 8*(n0+int32(*(*prg.mem[int32(prg.curEdges)+3].hh()).lh())) + 0 + zeroW - prg.curWt
 10608  	n0 = m0
 10609  	k = 0
 10610  	// Move to row |n0|, pointed to by |p|
 10611  	n = int32(*(*prg.mem[int32(prg.curEdges)+5].hh()).lh()) - zeroField
 10612  	p = *(*prg.mem[int32(prg.curEdges)+5].hh()).rh()
 10613  	if n != n0 {
 10614  		if n < n0 {
 10615  			for {
 10616  				n = n + 1
 10617  				p = *(*prg.mem[p].hh()).rh()
 10618  				if n == n0 {
 10619  					break
 10620  				}
 10621  			}
 10622  		} else {
 10623  			for {
 10624  				n = n - 1
 10625  				p = *(*prg.mem[p].hh()).lh()
 10626  				if n == n0 {
 10627  					break
 10628  				}
 10629  			}
 10630  		}
 10631  	}
 10632  	for {
 10633  		j = prg.move[k]
 10634  		for j > 0 {
 10635  			{
 10636  				r1 = prg.avail
 10637  				if int32(r1) == memMin {
 10638  					r1 = prg.getAvail()
 10639  				} else {
 10640  					prg.avail = *(*prg.mem[r1].hh()).rh()
 10641  					*(*prg.mem[r1].hh()).rh() = uint16(memMin)
 10642  					prg.dynUsed = prg.dynUsed + 1
 10643  				}
 10644  			}
 10645  			*(*prg.mem[r1].hh()).rh() = *(*prg.mem[int32(p)+1].hh()).lh()
 10646  			*(*prg.mem[r1].hh()).lh() = uint16(edgeAndWeight)
 10647  			if prg.internal[tracingEdges-1] > 0 {
 10648  				prg.traceNewEdge(r1, n)
 10649  			}
 10650  			*(*prg.mem[int32(p)+1].hh()).lh() = r1
 10651  			p = *(*prg.mem[p].hh()).rh()
 10652  			j = j - 1
 10653  			n = n + 1
 10654  		}
 10655  		edgeAndWeight = edgeAndWeight + dx
 10656  		k = uint16(int32(k) + 1)
 10657  		if int32(k) > int32(delta) {
 10658  			break
 10659  		}
 10660  	}
 10661  
 10662  	goto done
 10663  
 10664  slowCaseDown:
 10665  	edgeAndWeight = 8*(n0+int32(*(*prg.mem[int32(prg.curEdges)+3].hh()).lh())) + 0 + zeroW + prg.curWt
 10666  	n0 = -m0 - 1
 10667  	k = 0
 10668  	// Move to row |n0|, pointed to by |p|
 10669  	n = int32(*(*prg.mem[int32(prg.curEdges)+5].hh()).lh()) - zeroField
 10670  	p = *(*prg.mem[int32(prg.curEdges)+5].hh()).rh()
 10671  	if n != n0 {
 10672  		if n < n0 {
 10673  			for {
 10674  				n = n + 1
 10675  				p = *(*prg.mem[p].hh()).rh()
 10676  				if n == n0 {
 10677  					break
 10678  				}
 10679  			}
 10680  		} else {
 10681  			for {
 10682  				n = n - 1
 10683  				p = *(*prg.mem[p].hh()).lh()
 10684  				if n == n0 {
 10685  					break
 10686  				}
 10687  			}
 10688  		}
 10689  	}
 10690  	for {
 10691  		j = prg.move[k]
 10692  		for j > 0 {
 10693  			{
 10694  				r1 = prg.avail
 10695  				if int32(r1) == memMin {
 10696  					r1 = prg.getAvail()
 10697  				} else {
 10698  					prg.avail = *(*prg.mem[r1].hh()).rh()
 10699  					*(*prg.mem[r1].hh()).rh() = uint16(memMin)
 10700  					prg.dynUsed = prg.dynUsed + 1
 10701  				}
 10702  			}
 10703  			*(*prg.mem[r1].hh()).rh() = *(*prg.mem[int32(p)+1].hh()).lh()
 10704  			*(*prg.mem[r1].hh()).lh() = uint16(edgeAndWeight)
 10705  			if prg.internal[tracingEdges-1] > 0 {
 10706  				prg.traceNewEdge(r1, n)
 10707  			}
 10708  			*(*prg.mem[int32(p)+1].hh()).lh() = r1
 10709  			p = *(*prg.mem[p].hh()).lh()
 10710  			j = j - 1
 10711  			n = n - 1
 10712  		}
 10713  		edgeAndWeight = edgeAndWeight + dx
 10714  		k = uint16(int32(k) + 1)
 10715  		if int32(k) > int32(delta) {
 10716  			break
 10717  		}
 10718  	}
 10719  
 10720  	goto done
 10721  
 10722  done:
 10723  	*(*prg.mem[int32(prg.curEdges)+5].hh()).lh() = uint16(n + zeroField)
 10724  	*(*prg.mem[int32(prg.curEdges)+5].hh()).rh() = p
 10725  }
 10726  
 10727  // 386. \[21] Subdivision into octants
 10728  
 10729  // tangle:pos ../../mf.web:8266:35:
 10730  
 10731  // When \MF\ digitizes a path, it reduces the problem to the special
 10732  // case of paths that travel in ``first octant'' directions; i.e.,
 10733  // each cubic $z(t)=\bigl(x(t),y(t)\bigr)$ being digitized will have the property
 10734  // that $0\L y'(t)\L x'(t)$. This assumption makes digitizing simpler
 10735  // and faster than if the direction of motion has to be tested repeatedly.
 10736  //
 10737  // When $z(t)$ is cubic, $x'(t)$ and $y'(t)$ are quadratic, hence the four
 10738  // polynomials $x'(t)$, $y'(t)$, $x'(t)-y'(t)$, and $x'(t)+y'(t)$ cross
 10739  // through~0 at most twice each. If we subdivide the given cubic at these
 10740  // places, we get at most nine subintervals in each of which
 10741  // $x'(t)$, $y'(t)$, $x'(t)-y'(t)$, and $x'(t)+y'(t)$ all have a constant
 10742  // sign. The curve can be transformed in each of these subintervals so that
 10743  // it travels entirely in first octant directions, if we reflect $x\swap-x$,
 10744  // $y\swap-y$, and/or $x\swap y$ as necessary. (Incidentally, it can be
 10745  // shown that a cubic such that $x'(t)=16(2t-1)^2+2(2t-1)-1$ and
 10746  // $y'(t)=8(2t-1)^2+4(2t-1)$ does indeed split into nine subintervals.)
 10747  
 10748  // 387.
 10749  
 10750  // tangle:pos ../../mf.web:8284:3:
 10751  
 10752  // The transformation that rotates coordinates, so that first octant motion
 10753  // can be assumed, is defined by the |skew| subroutine, which sets global
 10754  // variables |cur_x| and |cur_y| to the values that are appropriate in a
 10755  // given octant.  (Octants are encoded as they were in the |n_arg| subroutine.)
 10756  //
 10757  // This transformation is ``skewed'' by replacing |(x,y)| by |(x-y,y)|,
 10758  // once first octant motion has been established. It turns out that
 10759  // skewed coordinates are somewhat better to work with when curves are
 10760  // actually digitized.
 10761  func (prg *prg) skew(x, y scaled, octant smallNumber) {
 10762  	switch octant {
 10763  	case firstOctant:
 10764  		prg.curX = x - y
 10765  		prg.curY = y
 10766  	case secondOctant:
 10767  		prg.curX = y - x
 10768  		prg.curY = x
 10769  	case thirdOctant:
 10770  		prg.curX = y + x
 10771  		prg.curY = -x
 10772  	case fourthOctant:
 10773  		prg.curX = -x - y
 10774  		prg.curY = y
 10775  	case fifthOctant:
 10776  		prg.curX = -x + y
 10777  		prg.curY = -y
 10778  	case sixthOctant:
 10779  		prg.curX = -y + x
 10780  		prg.curY = -x
 10781  	case seventhOctant:
 10782  		prg.curX = -y - x
 10783  		prg.curY = x
 10784  	case eighthOctant:
 10785  		prg.curX = x + y
 10786  		prg.curY = -y
 10787  	} // there are no other cases
 10788  }
 10789  
 10790  // 390.
 10791  
 10792  // tangle:pos ../../mf.web:8333:3:
 10793  
 10794  // The conversion to skewed and rotated coordinates takes place in
 10795  // stages, and at one point in the transformation we will have negated the
 10796  // $x$ and/or $y$ coordinates so as to make curves travel in the first
 10797  // [\sl quadrant]. At this point the relevant ``octant'' code will be
 10798  // either |first_octant| (when no transformation has been done),
 10799  // or |fourth_octant=first_octant+negate_x| (when $x$ has been negated),
 10800  // or |fifth_octant=first_octant+negate_x+negate_y| (when both have been
 10801  // negated), or |eighth_octant=first_octant+negate_y| (when $y$ has been
 10802  // negated). The |abnegate| routine is sometimes needed to convert
 10803  // from one of these transformations to another.
 10804  func (prg *prg) abnegate(x, y scaled,
 10805  	octantBefore, octantAfter smallNumber) {
 10806  	if octantBefore&1 != 0 == (octantAfter&1 != 0) {
 10807  		prg.curX = x
 10808  	} else {
 10809  		prg.curX = -x
 10810  	}
 10811  	if int32(octantBefore) > negateY == (int32(octantAfter) > negateY) {
 10812  		prg.curY = y
 10813  	} else {
 10814  		prg.curY = -y
 10815  	}
 10816  }
 10817  
 10818  // 391.
 10819  
 10820  // tangle:pos ../../mf.web:8352:3:
 10821  
 10822  // Now here's a subroutine that's handy for subdivision: Given a
 10823  // quadratic polynomial $B(a,b,c;t)$, the |crossing_point| function
 10824  // returns the unique |fraction| value |t| between 0 and~1 at which
 10825  // $B(a,b,c;t)$ changes from positive to negative, or returns
 10826  // |t=fraction_one+1| if no such value exists. If |a<0| (so that $B(a,b,c;t)$
 10827  // is already negative at |t=0|), |crossing_point| returns the value zero.
 10828  func (prg *prg) crossingPoint(a, b, c int32) (r fraction) {
 10829  	var (
 10830  		d                 int32 // recursive counter
 10831  		x, xx, x0, x1, x2 int32 // temporary registers for bisection
 10832  	)
 10833  	if a < 0 {
 10834  		r = 0
 10835  		goto exit
 10836  	}
 10837  	if c >= 0 {
 10838  		if b >= 0 {
 10839  			if c > 0 {
 10840  				r = 02000000000 + 1
 10841  				goto exit
 10842  			} else if a == 0 && b == 0 {
 10843  				r = 02000000000 + 1
 10844  				goto exit
 10845  			} else {
 10846  				r = 02000000000
 10847  				goto exit
 10848  			}
 10849  		}
 10850  		if a == 0 {
 10851  			r = 0
 10852  			goto exit
 10853  		}
 10854  	} else if a == 0 {
 10855  		if b <= 0 {
 10856  			r = 0
 10857  			goto exit
 10858  		}
 10859  	}
 10860  
 10861  	// Use bisection to find the crossing point, if one exists
 10862  	d = 1
 10863  	x0 = a
 10864  	x1 = a - b
 10865  	x2 = b - c
 10866  	for {
 10867  		x = (x1 + x2) / 2
 10868  		if x1-x0 > x0 {
 10869  			x2 = x
 10870  			x0 = x0 + x0
 10871  			d = d + d
 10872  		} else {
 10873  			xx = x1 + x - x0
 10874  			if xx > x0 {
 10875  				x2 = x
 10876  				x0 = x0 + x0
 10877  				d = d + d
 10878  			} else {
 10879  				x0 = x0 - xx
 10880  				if x <= x0 {
 10881  					if x+x2 <= x0 {
 10882  						r = 02000000000 + 1
 10883  						goto exit
 10884  					}
 10885  				}
 10886  				x1 = x
 10887  				d = d + d + 1
 10888  			}
 10889  		}
 10890  		if d >= 02000000000 {
 10891  			break
 10892  		}
 10893  	}
 10894  	r = d - 02000000000
 10895  
 10896  exit:
 10897  	;
 10898  	return r
 10899  }
 10900  
 10901  // 393.
 10902  
 10903  // tangle:pos ../../mf.web:8422:3:
 10904  
 10905  // Octant subdivision is applied only to cycles, i.e., to closed paths.
 10906  // A ``cycle spec'' is a data structure that contains specifications of
 10907  //  \xref[cycle spec]
 10908  // cubic curves and octant mappings for the cycle that has been subdivided
 10909  // into segments belonging to single octants. It is composed entirely of
 10910  // knot nodes, similar to those in the representation of paths; but the
 10911  // |explicit| type indications have been replaced by positive numbers
 10912  // that give further information. Additional |endpoint| data is also
 10913  // inserted at the octant boundaries.
 10914  //
 10915  // Recall that a cubic polynomial is represented by four control points
 10916  // that appear in adjacent nodes |p| and~|q| of a knot list. The |x|~coordinates
 10917  // are |x_coord(p)|, |right_x(p)|, |left_x(q)|, and |x_coord(q)|; the
 10918  // |y|~coordinates are similar. We shall call this ``the cubic following~|p|''
 10919  // or ``the cubic between |p| and~|q|'' or ``the cubic preceding~|q|.''
 10920  //
 10921  // Cycle specs are circular lists of cubic curves mixed with octant
 10922  // boundaries. Like cubics, the octant boundaries are represented in
 10923  // consecutive knot nodes |p| and~|q|. In such cases |right_type(p)=
 10924  // left_type(q)=endpoint|, and the fields |right_x(p)|, |right_y(p)|,
 10925  // |left_x(q)|, and |left_y(q)| are replaced by other fields called
 10926  // |right_octant(p)|, |right_transition(p)|, |left_octant(q)|, and
 10927  // |left_transition(q)|, respectively. For example, when the curve direction
 10928  // moves from the third octant to the fourth octant, the boundary nodes say
 10929  // |right_octant(p)=third_octant|, |left_octant(q)=fourth_octant|,
 10930  // and |right_transition(p)=left_transition(q)=diagonal|. A |diagonal|
 10931  // transition occurs when moving between octants 1~\AM~2, 3~\AM~4, 5~\AM~6, or
 10932  // 7~\AM~8; an |axis| transition occurs when moving between octants 8~\AM~1,
 10933  // 2~\AM~3, 4~\AM~5, 6~\AM~7. (Such transition information is redundant
 10934  // but convenient.) Fields |x_coord(p)| and |y_coord(p)| will contain
 10935  // coordinates of the transition point after rotation from third octant
 10936  // to first octant; i.e., if the true coordinates are $(x,y)$, the
 10937  // coordinates $(y,-x)$ will appear in node~|p|. Similarly, a fourth-octant
 10938  // transformation will have been applied after the transition, so
 10939  // we will have |x_coord(q)=$-x$| and |y_coord(q)=y|.
 10940  //
 10941  // The cubic between |p| and |q| will contain positive numbers in the
 10942  // fields |right_type(p)| and |left_type(q)|; this makes cubics
 10943  // distinguishable from octant boundaries, because |endpoint=0|.
 10944  // The value of |right_type(p)| will be the current octant code,
 10945  // during the time that cycle specs are being constructed; it will
 10946  // refer later to a pen offset position, if the envelope of a cycle is
 10947  // being computed. A cubic that comes from some subinterval of the $k$th
 10948  // step in the original cyclic path will have |left_type(q)=k|.
 10949  
 10950  // 394.
 10951  
 10952  // tangle:pos ../../mf.web:8474:3:
 10953  
 10954  // Here's a routine that prints a cycle spec in symbolic form, so that it
 10955  // is possible to see what subdivision has been made.  The point coordinates
 10956  // are converted back from \MF's internal ``rotated'' form to the external
 10957  // ``true'' form. The global variable~|cur_spec| should point to a knot just
 10958  // after the beginning of an octant boundary, i.e., such that
 10959  // |left_type(cur_spec)=endpoint|.
 10960  func (prg *prg) printSpec(s strNumber) {
 10961  	var (
 10962  		p, q   halfword    // for list traversal
 10963  		octant smallNumber // the current octant code
 10964  	)
 10965  	prg.printDiagnostic(strNumber( /* "Cycle spec" */ 544), s, true)
 10966  	// \xref[Cycle spec at line...]
 10967  	p = prg.curSpec
 10968  	octant = byte(*prg.mem[int32(p)+3].int())
 10969  	prg.printLn()
 10970  	prg.unskew(*prg.mem[int32(prg.curSpec)+1].int(), *prg.mem[int32(prg.curSpec)+2].int(), octant)
 10971  	prg.printTwo(prg.curX, prg.curY)
 10972  	prg.print( /* " % beginning in octant `" */ 545)
 10973  	for true {
 10974  		prg.print(int32(prg.octantDir[octant-1]))
 10975  		prg.printChar(asciiCode('\''))
 10976  		for true {
 10977  			q = *(*prg.mem[p].hh()).rh()
 10978  			if int32(*(*prg.mem[p].hh()).b1()) == endpoint {
 10979  				goto notFound
 10980  			}
 10981  
 10982  			// Print the cubic between |p| and |q|
 10983  			{
 10984  				prg.printNl(strNumber( /* "   ..controls " */ 556))
 10985  				prg.unskew(*prg.mem[int32(p)+5].int(), *prg.mem[int32(p)+6].int(), octant)
 10986  				prg.printTwo(prg.curX, prg.curY)
 10987  				prg.print( /* " and " */ 523)
 10988  				prg.unskew(*prg.mem[int32(q)+3].int(), *prg.mem[int32(q)+4].int(), octant)
 10989  				prg.printTwo(prg.curX, prg.curY)
 10990  				prg.printNl(strNumber( /* " .." */ 520))
 10991  				prg.unskew(*prg.mem[int32(q)+1].int(), *prg.mem[int32(q)+2].int(), octant)
 10992  				prg.printTwo(prg.curX, prg.curY)
 10993  				prg.print( /* " % segment " */ 557)
 10994  				prg.printInt(int32(*(*prg.mem[q].hh()).b0()) - 1)
 10995  			}
 10996  			p = q
 10997  		}
 10998  
 10999  	notFound:
 11000  		if int32(q) == int32(prg.curSpec) {
 11001  			goto done
 11002  		}
 11003  		p = q
 11004  		octant = byte(*prg.mem[int32(p)+3].int())
 11005  		prg.printNl(strNumber( /* "% entering octant `" */ 546))
 11006  	}
 11007  	// \xref[entering the nth octant]
 11008  
 11009  	// \xref[entering the nth octant]
 11010  done:
 11011  	prg.printNl(strNumber( /* " & cycle" */ 547))
 11012  	prg.endDiagnostic(true)
 11013  }
 11014  
 11015  // 398.
 11016  
 11017  // tangle:pos ../../mf.web:8530:3:
 11018  
 11019  // A much more compact version of a spec is printed to help users identify
 11020  // ``strange paths.''
 11021  func (prg *prg) printStrange(s strNumber) {
 11022  	var (
 11023  		p halfword // for list traversal
 11024  		f halfword // starting point in the cycle
 11025  		q halfword // octant boundary to be printed
 11026  		t int32    // segment number, plus 1
 11027  	)
 11028  	if int32(prg.interaction) == errorStopMode {
 11029  	}
 11030  	prg.printNl(strNumber('>'))
 11031  	// \xref[>\relax]
 11032  
 11033  	// Find the starting point, |f|
 11034  	p = prg.curSpec
 11035  	t = maxQuarterword + 1
 11036  	for {
 11037  		p = *(*prg.mem[p].hh()).rh()
 11038  		if int32(*(*prg.mem[p].hh()).b0()) != endpoint {
 11039  			if int32(*(*prg.mem[p].hh()).b0()) < t {
 11040  				f = p
 11041  			}
 11042  			t = int32(*(*prg.mem[p].hh()).b0())
 11043  		}
 11044  		if int32(p) == int32(prg.curSpec) {
 11045  			break
 11046  		}
 11047  	}
 11048  
 11049  	// Determine the octant boundary |q| that precedes |f|
 11050  	p = prg.curSpec
 11051  	q = p
 11052  	for {
 11053  		p = *(*prg.mem[p].hh()).rh()
 11054  		if int32(*(*prg.mem[p].hh()).b0()) == endpoint {
 11055  			q = p
 11056  		}
 11057  		if int32(p) == int32(f) {
 11058  			break
 11059  		}
 11060  	}
 11061  	t = 0
 11062  	for {
 11063  		if int32(*(*prg.mem[p].hh()).b0()) != endpoint {
 11064  			if int32(*(*prg.mem[p].hh()).b0()) != t {
 11065  				t = int32(*(*prg.mem[p].hh()).b0())
 11066  				prg.printChar(asciiCode(' '))
 11067  				prg.printInt(t - 1)
 11068  			}
 11069  			if int32(q) != memMin {
 11070  				if int32(*(*prg.mem[*(*prg.mem[q].hh()).rh()].hh()).b0()) == endpoint {
 11071  					prg.print( /* " (" */ 558)
 11072  					prg.print(int32(prg.octantDir[*prg.mem[int32(q)+3].int()-1]))
 11073  					q = *(*prg.mem[q].hh()).rh()
 11074  					for int32(*(*prg.mem[*(*prg.mem[q].hh()).rh()].hh()).b0()) == endpoint {
 11075  						prg.printChar(asciiCode(' '))
 11076  						prg.print(int32(prg.octantDir[*prg.mem[int32(q)+3].int()-1]))
 11077  						q = *(*prg.mem[q].hh()).rh()
 11078  					}
 11079  					prg.printChar(asciiCode(')'))
 11080  				}
 11081  				prg.printChar(asciiCode(' '))
 11082  				prg.print(int32(prg.octantDir[*prg.mem[int32(q)+3].int()-1]))
 11083  				q = uint16(memMin)
 11084  			}
 11085  		} else if int32(q) == memMin {
 11086  			q = p
 11087  		}
 11088  		p = *(*prg.mem[p].hh()).rh()
 11089  		if int32(p) == int32(f) {
 11090  			break
 11091  		}
 11092  	}
 11093  	prg.printChar(asciiCode(' '))
 11094  	prg.printInt(int32(*(*prg.mem[p].hh()).b0()) - 1)
 11095  	if int32(q) != memMin {
 11096  		if int32(*(*prg.mem[*(*prg.mem[q].hh()).rh()].hh()).b0()) == endpoint {
 11097  			prg.print( /* " (" */ 558)
 11098  			prg.print(int32(prg.octantDir[*prg.mem[int32(q)+3].int()-1]))
 11099  			q = *(*prg.mem[q].hh()).rh()
 11100  			for int32(*(*prg.mem[*(*prg.mem[q].hh()).rh()].hh()).b0()) == endpoint {
 11101  				prg.printChar(asciiCode(' '))
 11102  				prg.print(int32(prg.octantDir[*prg.mem[int32(q)+3].int()-1]))
 11103  				q = *(*prg.mem[q].hh()).rh()
 11104  			}
 11105  			prg.printChar(asciiCode(')'))
 11106  		}
 11107  	}
 11108  	{
 11109  		if int32(prg.interaction) == errorStopMode {
 11110  		}
 11111  		prg.printNl(strNumber( /* "! " */ 261))
 11112  		prg.print(int32(s)) /* \xref[!\relax]  */
 11113  	}
 11114  }
 11115  
 11116  // 402.
 11117  
 11118  // tangle:pos ../../mf.web:8597:3:
 11119  
 11120  // The |make_spec| routine is what subdivides paths into octants:
 11121  // Given a pointer |cur_spec| to a cyclic path, |make_spec| mungs the path data
 11122  // and returns a pointer to the corresponding cyclic spec.
 11123  // All “dead” cubics (i.e., cubics that don't move at all from
 11124  // their starting points) will have been removed from the result.
 11125  //
 11126  //	\xref[dead cubics]
 11127  //
 11128  // The idea of |make_spec| is fairly simple: Each cubic is first
 11129  // subdivided, if necessary, into pieces belonging to single octants;
 11130  // then the octant boundaries are inserted. But some of the details of
 11131  // this transformation are not quite obvious.
 11132  //
 11133  // If |autorounding>0|, the path will be adjusted so that critical tangent
 11134  // directions occur at “good” points with respect to the pen called |cur_pen|.
 11135  //
 11136  // The resulting spec will have all |x| and |y| coordinates at most
 11137  // $2^[28]-|half_unit|-1-|safety_margin|$ in absolute value.  The pointer
 11138  // that is returned will start some octant, as required by |print_spec|.
 11139  // \4
 11140  // Declare subroutines needed by |make_spec|
 11141  func (prg *prg) removeCubic(p halfword) { // removes the cubic following~|p|
 11142  	var (
 11143  		q halfword // the node that disappears
 11144  	)
 11145  	q = *(*prg.mem[p].hh()).rh()
 11146  	*(*prg.mem[p].hh()).b1() = *(*prg.mem[q].hh()).b1()
 11147  	*(*prg.mem[p].hh()).rh() = *(*prg.mem[q].hh()).rh()
 11148  
 11149  	*prg.mem[int32(p)+1].int() = *prg.mem[int32(q)+1].int()
 11150  	*prg.mem[int32(p)+2].int() = *prg.mem[int32(q)+2].int()
 11151  
 11152  	*prg.mem[int32(p)+5].int() = *prg.mem[int32(q)+5].int()
 11153  	*prg.mem[int32(p)+6].int() = *prg.mem[int32(q)+6].int()
 11154  
 11155  	prg.freeNode(q, halfword(knotNodeSize))
 11156  }
 11157  
 11158  // \4
 11159  // Declare the procedure called |split_cubic|
 11160  func (prg *prg) splitCubic(p halfword, t fraction,
 11161  	xq, yq scaled) { // splits the cubic after |p|
 11162  	var (
 11163  		v     scaled   // an intermediate value
 11164  		q, r1 halfword // for list manipulation
 11165  	)
 11166  	q = *(*prg.mem[p].hh()).rh()
 11167  	r1 = prg.getNode(knotNodeSize)
 11168  	*(*prg.mem[p].hh()).rh() = r1
 11169  	*(*prg.mem[r1].hh()).rh() = q
 11170  
 11171  	*(*prg.mem[r1].hh()).b0() = *(*prg.mem[q].hh()).b0()
 11172  	*(*prg.mem[r1].hh()).b1() = *(*prg.mem[p].hh()).b1()
 11173  
 11174  	v = *prg.mem[int32(p)+5].int() - prg.takeFraction(*prg.mem[int32(p)+5].int()-*prg.mem[int32(q)+3].int(), t)
 11175  	*prg.mem[int32(p)+5].int() = *prg.mem[int32(p)+1].int() - prg.takeFraction(*prg.mem[int32(p)+1].int()-*prg.mem[int32(p)+5].int(), t)
 11176  	*prg.mem[int32(q)+3].int() = *prg.mem[int32(q)+3].int() - prg.takeFraction(*prg.mem[int32(q)+3].int()-xq, t)
 11177  	*prg.mem[int32(r1)+3].int() = *prg.mem[int32(p)+5].int() - prg.takeFraction(*prg.mem[int32(p)+5].int()-v, t)
 11178  	*prg.mem[int32(r1)+5].int() = v - prg.takeFraction(v-*prg.mem[int32(q)+3].int(), t)
 11179  	*prg.mem[int32(r1)+1].int() = *prg.mem[int32(r1)+3].int() - prg.takeFraction(*prg.mem[int32(r1)+3].int()-*prg.mem[int32(r1)+5].int(), t)
 11180  
 11181  	v = *prg.mem[int32(p)+6].int() - prg.takeFraction(*prg.mem[int32(p)+6].int()-*prg.mem[int32(q)+4].int(), t)
 11182  	*prg.mem[int32(p)+6].int() = *prg.mem[int32(p)+2].int() - prg.takeFraction(*prg.mem[int32(p)+2].int()-*prg.mem[int32(p)+6].int(), t)
 11183  	*prg.mem[int32(q)+4].int() = *prg.mem[int32(q)+4].int() - prg.takeFraction(*prg.mem[int32(q)+4].int()-yq, t)
 11184  	*prg.mem[int32(r1)+4].int() = *prg.mem[int32(p)+6].int() - prg.takeFraction(*prg.mem[int32(p)+6].int()-v, t)
 11185  	*prg.mem[int32(r1)+6].int() = v - prg.takeFraction(v-*prg.mem[int32(q)+4].int(), t)
 11186  	*prg.mem[int32(r1)+2].int() = *prg.mem[int32(r1)+4].int() - prg.takeFraction(*prg.mem[int32(r1)+4].int()-*prg.mem[int32(r1)+6].int(), t)
 11187  }
 11188  
 11189  func (prg *prg) quadrantSubdivide() {
 11190  	var (
 11191  		p, q, r1, s, pp, qq         halfword // for traversing the lists
 11192  		firstX, firstY              scaled   // unnegated coordinates of node |cur_spec|
 11193  		del1, del2, del3, del, dmax scaled   // proportional to the control
 11194  		//   points of a quadratic derived from a cubic
 11195  
 11196  		t            fraction // where a quadratic crosses zero
 11197  		destX, destY scaled   // final values of |x| and |y| in the current cubic
 11198  		constantX    bool     // is |x| constant between |p| and |q|?
 11199  	)
 11200  	p = prg.curSpec
 11201  	firstX = *prg.mem[int32(prg.curSpec)+1].int()
 11202  	firstY = *prg.mem[int32(prg.curSpec)+2].int()
 11203  	for {
 11204  	continue1:
 11205  		q = *(*prg.mem[p].hh()).rh()
 11206  
 11207  		// Subdivide the cubic between |p| and |q| so that the results travel toward the right halfplane
 11208  		if int32(q) == int32(prg.curSpec) {
 11209  			destX = firstX
 11210  			destY = firstY
 11211  		} else {
 11212  			destX = *prg.mem[int32(q)+1].int()
 11213  			destY = *prg.mem[int32(q)+2].int()
 11214  		}
 11215  		del1 = *prg.mem[int32(p)+5].int() - *prg.mem[int32(p)+1].int()
 11216  		del2 = *prg.mem[int32(q)+3].int() - *prg.mem[int32(p)+5].int()
 11217  		del3 = destX - *prg.mem[int32(q)+3].int()
 11218  
 11219  		// Scale up |del1|, |del2|, and |del3| for greater accuracy; also set |del| to the first nonzero element of |(del1,del2,del3)|
 11220  		if del1 != 0 {
 11221  			del = del1
 11222  		} else if del2 != 0 {
 11223  			del = del2
 11224  		} else {
 11225  			del = del3
 11226  		}
 11227  		if del != 0 {
 11228  			dmax = abs(del1)
 11229  			if abs(del2) > dmax {
 11230  				dmax = abs(del2)
 11231  			}
 11232  			if abs(del3) > dmax {
 11233  				dmax = abs(del3)
 11234  			}
 11235  			for dmax < 01000000000 {
 11236  				dmax = dmax + dmax
 11237  				del1 = del1 + del1
 11238  				del2 = del2 + del2
 11239  				del3 = del3 + del3
 11240  			}
 11241  		}
 11242  		if del == 0 {
 11243  			constantX = true
 11244  		} else {
 11245  			constantX = false
 11246  			if del < 0 {
 11247  				*prg.mem[int32(p)+1].int() = -*prg.mem[int32(p)+1].int()
 11248  				*prg.mem[int32(p)+5].int() = -*prg.mem[int32(p)+5].int()
 11249  				*prg.mem[int32(q)+3].int() = -*prg.mem[int32(q)+3].int()
 11250  
 11251  				del1 = -del1
 11252  				del2 = -del2
 11253  				del3 = -del3
 11254  
 11255  				destX = -destX
 11256  				*(*prg.mem[p].hh()).b1() = byte(firstOctant + negateX)
 11257  			}
 11258  			t = prg.crossingPoint(del1, del2, del3)
 11259  			if t < 02000000000 {
 11260  				prg.splitCubic(p, t, destX, destY)
 11261  				r1 = *(*prg.mem[p].hh()).rh()
 11262  				if int32(*(*prg.mem[r1].hh()).b1()) > negateX {
 11263  					*(*prg.mem[r1].hh()).b1() = byte(firstOctant)
 11264  				} else {
 11265  					*(*prg.mem[r1].hh()).b1() = byte(firstOctant + negateX)
 11266  				}
 11267  				if *prg.mem[int32(r1)+1].int() < *prg.mem[int32(p)+1].int() {
 11268  					*prg.mem[int32(r1)+1].int() = *prg.mem[int32(p)+1].int()
 11269  				}
 11270  				*prg.mem[int32(r1)+3].int() = *prg.mem[int32(r1)+1].int()
 11271  				if *prg.mem[int32(p)+5].int() > *prg.mem[int32(r1)+1].int() {
 11272  					*prg.mem[int32(p)+5].int() = *prg.mem[int32(r1)+1].int()
 11273  				}
 11274  				// we always have |x_coord(p)<=right_x(p)|
 11275  				*prg.mem[int32(r1)+1].int() = -*prg.mem[int32(r1)+1].int()
 11276  				*prg.mem[int32(r1)+5].int() = *prg.mem[int32(r1)+1].int()
 11277  				*prg.mem[int32(q)+3].int() = -*prg.mem[int32(q)+3].int()
 11278  				destX = -destX
 11279  
 11280  				del2 = del2 - prg.takeFraction(del2-del3, t)
 11281  				// now |0,del2,del3| represent $x'$ on the remaining interval
 11282  				if del2 > 0 {
 11283  					del2 = 0
 11284  				}
 11285  				t = prg.crossingPoint(0, -del2, -del3)
 11286  				if t < 02000000000 {
 11287  					prg.splitCubic(r1, t, destX, destY)
 11288  					s = *(*prg.mem[r1].hh()).rh()
 11289  					if *prg.mem[int32(s)+1].int() < destX {
 11290  						*prg.mem[int32(s)+1].int() = destX
 11291  					}
 11292  					if *prg.mem[int32(s)+1].int() < *prg.mem[int32(r1)+1].int() {
 11293  						*prg.mem[int32(s)+1].int() = *prg.mem[int32(r1)+1].int()
 11294  					}
 11295  					*(*prg.mem[s].hh()).b1() = *(*prg.mem[p].hh()).b1()
 11296  					*prg.mem[int32(s)+3].int() = *prg.mem[int32(s)+1].int() // now |x_coord(r)=right_x(r)<=left_x(s)|
 11297  					if *prg.mem[int32(q)+3].int() < destX {
 11298  						*prg.mem[int32(q)+3].int() = -destX
 11299  					} else if *prg.mem[int32(q)+3].int() > *prg.mem[int32(s)+1].int() {
 11300  						*prg.mem[int32(q)+3].int() = -*prg.mem[int32(s)+1].int()
 11301  					} else {
 11302  						*prg.mem[int32(q)+3].int() = -*prg.mem[int32(q)+3].int()
 11303  					}
 11304  					*prg.mem[int32(s)+1].int() = -*prg.mem[int32(s)+1].int()
 11305  					*prg.mem[int32(s)+5].int() = *prg.mem[int32(s)+1].int()
 11306  				} else {
 11307  					if *prg.mem[int32(r1)+1].int() > destX {
 11308  						*prg.mem[int32(r1)+1].int() = destX
 11309  						*prg.mem[int32(r1)+3].int() = -*prg.mem[int32(r1)+1].int()
 11310  						*prg.mem[int32(r1)+5].int() = *prg.mem[int32(r1)+1].int()
 11311  					}
 11312  					if *prg.mem[int32(q)+3].int() > destX {
 11313  						*prg.mem[int32(q)+3].int() = destX
 11314  					} else if *prg.mem[int32(q)+3].int() < *prg.mem[int32(r1)+1].int() {
 11315  						*prg.mem[int32(q)+3].int() = *prg.mem[int32(r1)+1].int()
 11316  					}
 11317  				}
 11318  			}
 11319  		}
 11320  
 11321  		// Subdivide all cubics between |p| and |q| so that the results travel toward the first quadrant; but |return| or |goto continue| if the cubic from |p| to |q| was dead
 11322  		pp = p
 11323  		for {
 11324  			qq = *(*prg.mem[pp].hh()).rh()
 11325  			prg.abnegate(*prg.mem[int32(qq)+1].int(), *prg.mem[int32(qq)+2].int(), *(*prg.mem[qq].hh()).b1(), *(*prg.mem[pp].hh()).b1())
 11326  			destX = prg.curX
 11327  			destY = prg.curY
 11328  
 11329  			del1 = *prg.mem[int32(pp)+6].int() - *prg.mem[int32(pp)+2].int()
 11330  			del2 = *prg.mem[int32(qq)+4].int() - *prg.mem[int32(pp)+6].int()
 11331  			del3 = destY - *prg.mem[int32(qq)+4].int()
 11332  
 11333  			// Scale up |del1|, |del2|, and |del3| for greater accuracy; also set |del| to the first nonzero element of |(del1,del2,del3)|
 11334  			if del1 != 0 {
 11335  				del = del1
 11336  			} else if del2 != 0 {
 11337  				del = del2
 11338  			} else {
 11339  				del = del3
 11340  			}
 11341  			if del != 0 {
 11342  				dmax = abs(del1)
 11343  				if abs(del2) > dmax {
 11344  					dmax = abs(del2)
 11345  				}
 11346  				if abs(del3) > dmax {
 11347  					dmax = abs(del3)
 11348  				}
 11349  				for dmax < 01000000000 {
 11350  					dmax = dmax + dmax
 11351  					del1 = del1 + del1
 11352  					del2 = del2 + del2
 11353  					del3 = del3 + del3
 11354  				}
 11355  			}
 11356  			if del != 0 {
 11357  				if del < 0 {
 11358  					*prg.mem[int32(pp)+2].int() = -*prg.mem[int32(pp)+2].int()
 11359  					*prg.mem[int32(pp)+6].int() = -*prg.mem[int32(pp)+6].int()
 11360  					*prg.mem[int32(qq)+4].int() = -*prg.mem[int32(qq)+4].int()
 11361  
 11362  					del1 = -del1
 11363  					del2 = -del2
 11364  					del3 = -del3
 11365  
 11366  					destY = -destY
 11367  					*(*prg.mem[pp].hh()).b1() = byte(int32(*(*prg.mem[pp].hh()).b1()) + negateY)
 11368  				}
 11369  				t = prg.crossingPoint(del1, del2, del3)
 11370  				if t < 02000000000 {
 11371  					prg.splitCubic(pp, t, destX, destY)
 11372  					r1 = *(*prg.mem[pp].hh()).rh()
 11373  					if int32(*(*prg.mem[r1].hh()).b1()) > negateY {
 11374  						*(*prg.mem[r1].hh()).b1() = byte(int32(*(*prg.mem[r1].hh()).b1()) - negateY)
 11375  					} else {
 11376  						*(*prg.mem[r1].hh()).b1() = byte(int32(*(*prg.mem[r1].hh()).b1()) + negateY)
 11377  					}
 11378  					if *prg.mem[int32(r1)+2].int() < *prg.mem[int32(pp)+2].int() {
 11379  						*prg.mem[int32(r1)+2].int() = *prg.mem[int32(pp)+2].int()
 11380  					}
 11381  					*prg.mem[int32(r1)+4].int() = *prg.mem[int32(r1)+2].int()
 11382  					if *prg.mem[int32(pp)+6].int() > *prg.mem[int32(r1)+2].int() {
 11383  						*prg.mem[int32(pp)+6].int() = *prg.mem[int32(r1)+2].int()
 11384  					}
 11385  					// we always have |y_coord(pp)<=right_y(pp)|
 11386  					*prg.mem[int32(r1)+2].int() = -*prg.mem[int32(r1)+2].int()
 11387  					*prg.mem[int32(r1)+6].int() = *prg.mem[int32(r1)+2].int()
 11388  					*prg.mem[int32(qq)+4].int() = -*prg.mem[int32(qq)+4].int()
 11389  					destY = -destY
 11390  
 11391  					if *prg.mem[int32(r1)+1].int() < *prg.mem[int32(pp)+1].int() {
 11392  						*prg.mem[int32(r1)+1].int() = *prg.mem[int32(pp)+1].int()
 11393  					} else if *prg.mem[int32(r1)+1].int() > destX {
 11394  						*prg.mem[int32(r1)+1].int() = destX
 11395  					}
 11396  					if *prg.mem[int32(r1)+3].int() > *prg.mem[int32(r1)+1].int() {
 11397  						*prg.mem[int32(r1)+3].int() = *prg.mem[int32(r1)+1].int()
 11398  						if *prg.mem[int32(pp)+5].int() > *prg.mem[int32(r1)+1].int() {
 11399  							*prg.mem[int32(pp)+5].int() = *prg.mem[int32(r1)+1].int()
 11400  						}
 11401  					}
 11402  					if *prg.mem[int32(r1)+5].int() < *prg.mem[int32(r1)+1].int() {
 11403  						*prg.mem[int32(r1)+5].int() = *prg.mem[int32(r1)+1].int()
 11404  						if *prg.mem[int32(qq)+3].int() < *prg.mem[int32(r1)+1].int() {
 11405  							*prg.mem[int32(qq)+3].int() = *prg.mem[int32(r1)+1].int()
 11406  						}
 11407  					}
 11408  					del2 = del2 - prg.takeFraction(del2-del3, t)
 11409  					// now |0,del2,del3| represent $y'$ on the remaining interval
 11410  					if del2 > 0 {
 11411  						del2 = 0
 11412  					}
 11413  					t = prg.crossingPoint(0, -del2, -del3)
 11414  					if t < 02000000000 {
 11415  						prg.splitCubic(r1, t, destX, destY)
 11416  						s = *(*prg.mem[r1].hh()).rh()
 11417  
 11418  						if *prg.mem[int32(s)+2].int() < destY {
 11419  							*prg.mem[int32(s)+2].int() = destY
 11420  						}
 11421  						if *prg.mem[int32(s)+2].int() < *prg.mem[int32(r1)+2].int() {
 11422  							*prg.mem[int32(s)+2].int() = *prg.mem[int32(r1)+2].int()
 11423  						}
 11424  						*(*prg.mem[s].hh()).b1() = *(*prg.mem[pp].hh()).b1()
 11425  						*prg.mem[int32(s)+4].int() = *prg.mem[int32(s)+2].int() // now |y_coord(r)=right_y(r)<=left_y(s)|
 11426  						if *prg.mem[int32(qq)+4].int() < destY {
 11427  							*prg.mem[int32(qq)+4].int() = -destY
 11428  						} else if *prg.mem[int32(qq)+4].int() > *prg.mem[int32(s)+2].int() {
 11429  							*prg.mem[int32(qq)+4].int() = -*prg.mem[int32(s)+2].int()
 11430  						} else {
 11431  							*prg.mem[int32(qq)+4].int() = -*prg.mem[int32(qq)+4].int()
 11432  						}
 11433  						*prg.mem[int32(s)+2].int() = -*prg.mem[int32(s)+2].int()
 11434  						*prg.mem[int32(s)+6].int() = *prg.mem[int32(s)+2].int()
 11435  						if *prg.mem[int32(s)+1].int() < *prg.mem[int32(r1)+1].int() {
 11436  							*prg.mem[int32(s)+1].int() = *prg.mem[int32(r1)+1].int()
 11437  						} else if *prg.mem[int32(s)+1].int() > destX {
 11438  							*prg.mem[int32(s)+1].int() = destX
 11439  						}
 11440  						if *prg.mem[int32(s)+3].int() > *prg.mem[int32(s)+1].int() {
 11441  							*prg.mem[int32(s)+3].int() = *prg.mem[int32(s)+1].int()
 11442  							if *prg.mem[int32(r1)+5].int() > *prg.mem[int32(s)+1].int() {
 11443  								*prg.mem[int32(r1)+5].int() = *prg.mem[int32(s)+1].int()
 11444  							}
 11445  						}
 11446  						if *prg.mem[int32(s)+5].int() < *prg.mem[int32(s)+1].int() {
 11447  							*prg.mem[int32(s)+5].int() = *prg.mem[int32(s)+1].int()
 11448  							if *prg.mem[int32(qq)+3].int() < *prg.mem[int32(s)+1].int() {
 11449  								*prg.mem[int32(qq)+3].int() = *prg.mem[int32(s)+1].int()
 11450  							}
 11451  						}
 11452  					} else {
 11453  						if *prg.mem[int32(r1)+2].int() > destY {
 11454  							*prg.mem[int32(r1)+2].int() = destY
 11455  							*prg.mem[int32(r1)+4].int() = -*prg.mem[int32(r1)+2].int()
 11456  							*prg.mem[int32(r1)+6].int() = *prg.mem[int32(r1)+2].int()
 11457  						}
 11458  						if *prg.mem[int32(qq)+4].int() > destY {
 11459  							*prg.mem[int32(qq)+4].int() = destY
 11460  						} else if *prg.mem[int32(qq)+4].int() < *prg.mem[int32(r1)+2].int() {
 11461  							*prg.mem[int32(qq)+4].int() = *prg.mem[int32(r1)+2].int()
 11462  						}
 11463  					}
 11464  				}
 11465  			} else if constantX {
 11466  				if int32(q) != int32(p) {
 11467  					prg.removeCubic(p) // remove the dead cycle and recycle node |q|
 11468  					if int32(prg.curSpec) != int32(q) {
 11469  						goto continue1
 11470  					} else {
 11471  						prg.curSpec = p
 11472  						goto exit
 11473  					} // the final cubic was dead and is gone
 11474  				}
 11475  			} else if !(*(*prg.mem[pp].hh()).b1()&1 != 0) {
 11476  				*prg.mem[int32(pp)+2].int() = -*prg.mem[int32(pp)+2].int()
 11477  				*prg.mem[int32(pp)+6].int() = -*prg.mem[int32(pp)+6].int()
 11478  				*prg.mem[int32(qq)+4].int() = -*prg.mem[int32(qq)+4].int()
 11479  
 11480  				del1 = -del1
 11481  				del2 = -del2
 11482  				del3 = -del3
 11483  
 11484  				destY = -destY
 11485  				*(*prg.mem[pp].hh()).b1() = byte(int32(*(*prg.mem[pp].hh()).b1()) + negateY)
 11486  			}
 11487  			pp = qq
 11488  			if int32(pp) == int32(q) {
 11489  				break
 11490  			}
 11491  		}
 11492  		if constantX {
 11493  			pp = p
 11494  			for {
 11495  				qq = *(*prg.mem[pp].hh()).rh()
 11496  				if int32(*(*prg.mem[pp].hh()).b1()) > negateY {
 11497  					*(*prg.mem[pp].hh()).b1() = byte(int32(*(*prg.mem[pp].hh()).b1()) + negateX)
 11498  					*prg.mem[int32(pp)+1].int() = -*prg.mem[int32(pp)+1].int()
 11499  					*prg.mem[int32(pp)+5].int() = -*prg.mem[int32(pp)+5].int()
 11500  					*prg.mem[int32(qq)+3].int() = -*prg.mem[int32(qq)+3].int()
 11501  				}
 11502  				pp = qq
 11503  				if int32(pp) == int32(q) {
 11504  					break
 11505  				}
 11506  			}
 11507  		}
 11508  		p = q
 11509  		if int32(p) == int32(prg.curSpec) {
 11510  			break
 11511  		}
 11512  	}
 11513  
 11514  exit:
 11515  }
 11516  
 11517  func (prg *prg) octantSubdivide() {
 11518  	var (
 11519  		p, q, r1, s                 halfword // for traversing the lists
 11520  		del1, del2, del3, del, dmax scaled   // proportional to the control
 11521  		//   points of a quadratic derived from a cubic
 11522  
 11523  		t            fraction // where a quadratic crosses zero
 11524  		destX, destY scaled   // final values of |x| and |y| in the current cubic
 11525  	)
 11526  	p = prg.curSpec
 11527  	for {
 11528  		q = *(*prg.mem[p].hh()).rh()
 11529  
 11530  		*prg.mem[int32(p)+1].int() = *prg.mem[int32(p)+1].int() - *prg.mem[int32(p)+2].int()
 11531  		*prg.mem[int32(p)+5].int() = *prg.mem[int32(p)+5].int() - *prg.mem[int32(p)+6].int()
 11532  		*prg.mem[int32(q)+3].int() = *prg.mem[int32(q)+3].int() - *prg.mem[int32(q)+4].int()
 11533  
 11534  		// Subdivide the cubic between |p| and |q| so that the results travel toward the first octant
 11535  
 11536  		// Set up the variables |(del1,del2,del3)| to represent $x'-y'$
 11537  		if int32(q) == int32(prg.curSpec) {
 11538  			prg.unskew(*prg.mem[int32(q)+1].int(), *prg.mem[int32(q)+2].int(), *(*prg.mem[q].hh()).b1())
 11539  			prg.skew(prg.curX, prg.curY, *(*prg.mem[p].hh()).b1())
 11540  			destX = prg.curX
 11541  			destY = prg.curY
 11542  		} else {
 11543  			prg.abnegate(*prg.mem[int32(q)+1].int(), *prg.mem[int32(q)+2].int(), *(*prg.mem[q].hh()).b1(), *(*prg.mem[p].hh()).b1())
 11544  			destX = prg.curX - prg.curY
 11545  			destY = prg.curY
 11546  		}
 11547  		del1 = *prg.mem[int32(p)+5].int() - *prg.mem[int32(p)+1].int()
 11548  		del2 = *prg.mem[int32(q)+3].int() - *prg.mem[int32(p)+5].int()
 11549  		del3 = destX - *prg.mem[int32(q)+3].int()
 11550  
 11551  		// Scale up |del1|, |del2|, and |del3| for greater accuracy; also set |del| to the first nonzero element of |(del1,del2,del3)|
 11552  		if del1 != 0 {
 11553  			del = del1
 11554  		} else if del2 != 0 {
 11555  			del = del2
 11556  		} else {
 11557  			del = del3
 11558  		}
 11559  		if del != 0 {
 11560  			dmax = abs(del1)
 11561  			if abs(del2) > dmax {
 11562  				dmax = abs(del2)
 11563  			}
 11564  			if abs(del3) > dmax {
 11565  				dmax = abs(del3)
 11566  			}
 11567  			for dmax < 01000000000 {
 11568  				dmax = dmax + dmax
 11569  				del1 = del1 + del1
 11570  				del2 = del2 + del2
 11571  				del3 = del3 + del3
 11572  			}
 11573  		}
 11574  		if del != 0 {
 11575  			if del < 0 {
 11576  				*prg.mem[int32(p)+2].int() = *prg.mem[int32(p)+1].int() + *prg.mem[int32(p)+2].int()
 11577  				*prg.mem[int32(p)+1].int() = -*prg.mem[int32(p)+1].int()
 11578  
 11579  				*prg.mem[int32(p)+6].int() = *prg.mem[int32(p)+5].int() + *prg.mem[int32(p)+6].int()
 11580  				*prg.mem[int32(p)+5].int() = -*prg.mem[int32(p)+5].int()
 11581  
 11582  				*prg.mem[int32(q)+4].int() = *prg.mem[int32(q)+3].int() + *prg.mem[int32(q)+4].int()
 11583  				*prg.mem[int32(q)+3].int() = -*prg.mem[int32(q)+3].int()
 11584  
 11585  				del1 = -del1
 11586  				del2 = -del2
 11587  				del3 = -del3
 11588  
 11589  				destY = destX + destY
 11590  				destX = -destX
 11591  
 11592  				*(*prg.mem[p].hh()).b1() = byte(int32(*(*prg.mem[p].hh()).b1()) + switchXAndY)
 11593  			}
 11594  			t = prg.crossingPoint(del1, del2, del3)
 11595  			if t < 02000000000 {
 11596  				prg.splitCubic(p, t, destX, destY)
 11597  				r1 = *(*prg.mem[p].hh()).rh()
 11598  				if int32(*(*prg.mem[r1].hh()).b1()) > switchXAndY {
 11599  					*(*prg.mem[r1].hh()).b1() = byte(int32(*(*prg.mem[r1].hh()).b1()) - switchXAndY)
 11600  				} else {
 11601  					*(*prg.mem[r1].hh()).b1() = byte(int32(*(*prg.mem[r1].hh()).b1()) + switchXAndY)
 11602  				}
 11603  				if *prg.mem[int32(r1)+2].int() < *prg.mem[int32(p)+2].int() {
 11604  					*prg.mem[int32(r1)+2].int() = *prg.mem[int32(p)+2].int()
 11605  				} else if *prg.mem[int32(r1)+2].int() > destY {
 11606  					*prg.mem[int32(r1)+2].int() = destY
 11607  				}
 11608  				if *prg.mem[int32(p)+1].int()+*prg.mem[int32(r1)+2].int() > destX+destY {
 11609  					*prg.mem[int32(r1)+2].int() = destX + destY - *prg.mem[int32(p)+1].int()
 11610  				}
 11611  				if *prg.mem[int32(r1)+4].int() > *prg.mem[int32(r1)+2].int() {
 11612  					*prg.mem[int32(r1)+4].int() = *prg.mem[int32(r1)+2].int()
 11613  					if *prg.mem[int32(p)+6].int() > *prg.mem[int32(r1)+2].int() {
 11614  						*prg.mem[int32(p)+6].int() = *prg.mem[int32(r1)+2].int()
 11615  					}
 11616  				}
 11617  				if *prg.mem[int32(r1)+6].int() < *prg.mem[int32(r1)+2].int() {
 11618  					*prg.mem[int32(r1)+6].int() = *prg.mem[int32(r1)+2].int()
 11619  					if *prg.mem[int32(q)+4].int() < *prg.mem[int32(r1)+2].int() {
 11620  						*prg.mem[int32(q)+4].int() = *prg.mem[int32(r1)+2].int()
 11621  					}
 11622  				}
 11623  				if *prg.mem[int32(r1)+1].int() < *prg.mem[int32(p)+1].int() {
 11624  					*prg.mem[int32(r1)+1].int() = *prg.mem[int32(p)+1].int()
 11625  				} else if *prg.mem[int32(r1)+1].int()+*prg.mem[int32(r1)+2].int() > destX+destY {
 11626  					*prg.mem[int32(r1)+1].int() = destX + destY - *prg.mem[int32(r1)+2].int()
 11627  				}
 11628  				*prg.mem[int32(r1)+3].int() = *prg.mem[int32(r1)+1].int()
 11629  				if *prg.mem[int32(p)+5].int() > *prg.mem[int32(r1)+1].int() {
 11630  					*prg.mem[int32(p)+5].int() = *prg.mem[int32(r1)+1].int()
 11631  				}
 11632  				// we always have |x_coord(p)<=right_x(p)|
 11633  				*prg.mem[int32(r1)+2].int() = *prg.mem[int32(r1)+2].int() + *prg.mem[int32(r1)+1].int()
 11634  				*prg.mem[int32(r1)+6].int() = *prg.mem[int32(r1)+6].int() + *prg.mem[int32(r1)+1].int()
 11635  
 11636  				*prg.mem[int32(r1)+1].int() = -*prg.mem[int32(r1)+1].int()
 11637  				*prg.mem[int32(r1)+5].int() = *prg.mem[int32(r1)+1].int()
 11638  
 11639  				*prg.mem[int32(q)+4].int() = *prg.mem[int32(q)+4].int() + *prg.mem[int32(q)+3].int()
 11640  				*prg.mem[int32(q)+3].int() = -*prg.mem[int32(q)+3].int()
 11641  
 11642  				destY = destY + destX
 11643  				destX = -destX
 11644  				if *prg.mem[int32(r1)+6].int() < *prg.mem[int32(r1)+2].int() {
 11645  					*prg.mem[int32(r1)+6].int() = *prg.mem[int32(r1)+2].int()
 11646  					if *prg.mem[int32(q)+4].int() < *prg.mem[int32(r1)+2].int() {
 11647  						*prg.mem[int32(q)+4].int() = *prg.mem[int32(r1)+2].int()
 11648  					}
 11649  				}
 11650  				del2 = del2 - prg.takeFraction(del2-del3, t)
 11651  				// now |0,del2,del3| represent $x'-y'$ on the remaining interval
 11652  				if del2 > 0 {
 11653  					del2 = 0
 11654  				}
 11655  				t = prg.crossingPoint(0, -del2, -del3)
 11656  				if t < 02000000000 {
 11657  					prg.splitCubic(r1, t, destX, destY)
 11658  					s = *(*prg.mem[r1].hh()).rh()
 11659  
 11660  					if *prg.mem[int32(s)+2].int() < *prg.mem[int32(r1)+2].int() {
 11661  						*prg.mem[int32(s)+2].int() = *prg.mem[int32(r1)+2].int()
 11662  					} else if *prg.mem[int32(s)+2].int() > destY {
 11663  						*prg.mem[int32(s)+2].int() = destY
 11664  					}
 11665  					if *prg.mem[int32(r1)+1].int()+*prg.mem[int32(s)+2].int() > destX+destY {
 11666  						*prg.mem[int32(s)+2].int() = destX + destY - *prg.mem[int32(r1)+1].int()
 11667  					}
 11668  					if *prg.mem[int32(s)+4].int() > *prg.mem[int32(s)+2].int() {
 11669  						*prg.mem[int32(s)+4].int() = *prg.mem[int32(s)+2].int()
 11670  						if *prg.mem[int32(r1)+6].int() > *prg.mem[int32(s)+2].int() {
 11671  							*prg.mem[int32(r1)+6].int() = *prg.mem[int32(s)+2].int()
 11672  						}
 11673  					}
 11674  					if *prg.mem[int32(s)+6].int() < *prg.mem[int32(s)+2].int() {
 11675  						*prg.mem[int32(s)+6].int() = *prg.mem[int32(s)+2].int()
 11676  						if *prg.mem[int32(q)+4].int() < *prg.mem[int32(s)+2].int() {
 11677  							*prg.mem[int32(q)+4].int() = *prg.mem[int32(s)+2].int()
 11678  						}
 11679  					}
 11680  					if *prg.mem[int32(s)+1].int()+*prg.mem[int32(s)+2].int() > destX+destY {
 11681  						*prg.mem[int32(s)+1].int() = destX + destY - *prg.mem[int32(s)+2].int()
 11682  					} else {
 11683  						if *prg.mem[int32(s)+1].int() < destX {
 11684  							*prg.mem[int32(s)+1].int() = destX
 11685  						}
 11686  						if *prg.mem[int32(s)+1].int() < *prg.mem[int32(r1)+1].int() {
 11687  							*prg.mem[int32(s)+1].int() = *prg.mem[int32(r1)+1].int()
 11688  						}
 11689  					}
 11690  					*(*prg.mem[s].hh()).b1() = *(*prg.mem[p].hh()).b1()
 11691  					*prg.mem[int32(s)+3].int() = *prg.mem[int32(s)+1].int() // now |x_coord(r)=right_x(r)<=left_x(s)|
 11692  					if *prg.mem[int32(q)+3].int() < destX {
 11693  						*prg.mem[int32(q)+4].int() = *prg.mem[int32(q)+4].int() + destX
 11694  						*prg.mem[int32(q)+3].int() = -destX
 11695  					} else if *prg.mem[int32(q)+3].int() > *prg.mem[int32(s)+1].int() {
 11696  						*prg.mem[int32(q)+4].int() = *prg.mem[int32(q)+4].int() + *prg.mem[int32(s)+1].int()
 11697  						*prg.mem[int32(q)+3].int() = -*prg.mem[int32(s)+1].int()
 11698  					} else {
 11699  						*prg.mem[int32(q)+4].int() = *prg.mem[int32(q)+4].int() + *prg.mem[int32(q)+3].int()
 11700  						*prg.mem[int32(q)+3].int() = -*prg.mem[int32(q)+3].int()
 11701  					}
 11702  					*prg.mem[int32(s)+2].int() = *prg.mem[int32(s)+2].int() + *prg.mem[int32(s)+1].int()
 11703  					*prg.mem[int32(s)+6].int() = *prg.mem[int32(s)+6].int() + *prg.mem[int32(s)+1].int()
 11704  
 11705  					*prg.mem[int32(s)+1].int() = -*prg.mem[int32(s)+1].int()
 11706  					*prg.mem[int32(s)+5].int() = *prg.mem[int32(s)+1].int()
 11707  
 11708  					if *prg.mem[int32(s)+6].int() < *prg.mem[int32(s)+2].int() {
 11709  						*prg.mem[int32(s)+6].int() = *prg.mem[int32(s)+2].int()
 11710  						if *prg.mem[int32(q)+4].int() < *prg.mem[int32(s)+2].int() {
 11711  							*prg.mem[int32(q)+4].int() = *prg.mem[int32(s)+2].int()
 11712  						}
 11713  					}
 11714  				} else {
 11715  					if *prg.mem[int32(r1)+1].int() > destX {
 11716  						*prg.mem[int32(r1)+1].int() = destX
 11717  						*prg.mem[int32(r1)+3].int() = -*prg.mem[int32(r1)+1].int()
 11718  						*prg.mem[int32(r1)+5].int() = *prg.mem[int32(r1)+1].int()
 11719  					}
 11720  					if *prg.mem[int32(q)+3].int() > destX {
 11721  						*prg.mem[int32(q)+3].int() = destX
 11722  					} else if *prg.mem[int32(q)+3].int() < *prg.mem[int32(r1)+1].int() {
 11723  						*prg.mem[int32(q)+3].int() = *prg.mem[int32(r1)+1].int()
 11724  					}
 11725  				}
 11726  			}
 11727  		}
 11728  		p = q
 11729  		if int32(p) == int32(prg.curSpec) {
 11730  			break
 11731  		}
 11732  	}
 11733  }
 11734  
 11735  func (prg *prg) makeSafe() {
 11736  	var (
 11737  		k/* 0..maxWiggle */ uint16        // runs through the list of inputs
 11738  		allSafe                    bool   // does everything look OK so far?
 11739  		nextA                      scaled // |after[k]| before it might have changed
 11740  		deltaA, deltaB             scaled // |after[k+1]-after[k]| and |before[k+1]-before[k]|
 11741  	)
 11742  	prg.before[prg.curRoundingPtr] = prg.before[0] // wrap around
 11743  	prg.nodeToRound[prg.curRoundingPtr] = prg.nodeToRound[0]
 11744  	for {
 11745  		prg.after[prg.curRoundingPtr] = prg.after[0]
 11746  		allSafe = true
 11747  		nextA = prg.after[0]
 11748  		for ii := int32(0); ii <= int32(prg.curRoundingPtr)-1; ii++ {
 11749  			k = uint16(ii)
 11750  			_ = k
 11751  			deltaB = prg.before[int32(k)+1] - prg.before[k]
 11752  			if deltaB >= 0 {
 11753  				deltaA = prg.after[int32(k)+1] - nextA
 11754  			} else {
 11755  				deltaA = nextA - prg.after[int32(k)+1]
 11756  			}
 11757  			nextA = prg.after[int32(k)+1]
 11758  			if deltaA < 0 || deltaA > abs(deltaB+deltaB) {
 11759  				allSafe = false
 11760  				prg.after[k] = prg.before[k]
 11761  				if int32(k) == int32(prg.curRoundingPtr)-1 {
 11762  					prg.after[0] = prg.before[0]
 11763  				} else {
 11764  					prg.after[int32(k)+1] = prg.before[int32(k)+1]
 11765  				}
 11766  			}
 11767  		}
 11768  		if allSafe {
 11769  			break
 11770  		}
 11771  	}
 11772  }
 11773  
 11774  func (prg *prg) beforeAndAfter(b, a scaled, p halfword) {
 11775  	if int32(prg.curRoundingPtr) == int32(prg.maxRoundingPtr) {
 11776  		if int32(prg.maxRoundingPtr) < maxWiggle {
 11777  			prg.maxRoundingPtr = uint16(int32(prg.maxRoundingPtr) + 1)
 11778  		} else {
 11779  			prg.overflow(strNumber( /* "rounding table size" */ 568), maxWiggle)
 11780  		}
 11781  	}
 11782  	// \xref[METAFONT capacity exceeded rounding table size][\quad rounding table size]
 11783  	prg.after[prg.curRoundingPtr] = a
 11784  	prg.before[prg.curRoundingPtr] = b
 11785  	prg.nodeToRound[prg.curRoundingPtr] = p
 11786  	prg.curRoundingPtr = uint16(int32(prg.curRoundingPtr) + 1)
 11787  }
 11788  
 11789  func (prg *prg) goodVal(b, o scaled) (r scaled) {
 11790  	var (
 11791  		a scaled // accumulator
 11792  	)
 11793  	a = b + o
 11794  	if a >= 0 {
 11795  		a = a - a%prg.curGran - o
 11796  	} else {
 11797  		a = a + -(a+1)%prg.curGran - prg.curGran + 1 - o
 11798  	}
 11799  	if b-a < a+prg.curGran-b {
 11800  		r = a
 11801  	} else {
 11802  		r = a + prg.curGran
 11803  	}
 11804  	return r
 11805  }
 11806  
 11807  func (prg *prg) compromise(u, v scaled) (r scaled) {
 11808  	r = prg.goodVal(u+u, -u-v) / 2
 11809  	return r
 11810  }
 11811  
 11812  func (prg *prg) xyRound() {
 11813  	var (
 11814  		p, q    halfword // list manipulation registers
 11815  		b, a    scaled   // before and after values
 11816  		penEdge scaled   // offset that governs rounding
 11817  		alpha   fraction // coefficient of linear transformation
 11818  	)
 11819  	prg.curGran = abs(prg.internal[granularity-1])
 11820  	if prg.curGran == 0 {
 11821  		prg.curGran = 0200000
 11822  	}
 11823  	p = prg.curSpec
 11824  	prg.curRoundingPtr = 0
 11825  	for {
 11826  		q = *(*prg.mem[p].hh()).rh()
 11827  
 11828  		// If node |q| is a transition point for |x| coordinates, compute and save its before-and-after coordinates
 11829  		if *(*prg.mem[p].hh()).b1()&1 != 0 != (*(*prg.mem[q].hh()).b1()&1 != 0) {
 11830  			if *(*prg.mem[q].hh()).b1()&1 != 0 {
 11831  				b = *prg.mem[int32(q)+1].int()
 11832  			} else {
 11833  				b = -*prg.mem[int32(q)+1].int()
 11834  			}
 11835  			if abs(*prg.mem[int32(q)+1].int()-*prg.mem[int32(q)+5].int()) < 655 || abs(*prg.mem[int32(q)+1].int()+*prg.mem[int32(q)+3].int()) < 655 {
 11836  				if int32(prg.curPen) == memMin+3 {
 11837  					penEdge = 0
 11838  				} else if int32(prg.curPathType) == doublePathCode {
 11839  					penEdge = prg.compromise(*prg.mem[int32(*(*prg.mem[int32(prg.curPen)+secondOctant].hh()).rh())+2].int(), *prg.mem[int32(*(*prg.mem[int32(prg.curPen)+seventhOctant].hh()).rh())+2].int())
 11840  				} else if *(*prg.mem[q].hh()).b1()&1 != 0 {
 11841  					penEdge = *prg.mem[int32(*(*prg.mem[int32(prg.curPen)+seventhOctant].hh()).rh())+2].int()
 11842  				} else {
 11843  					penEdge = *prg.mem[int32(*(*prg.mem[int32(prg.curPen)+secondOctant].hh()).rh())+2].int()
 11844  				}
 11845  				a = prg.goodVal(b, penEdge)
 11846  			} else {
 11847  				a = b
 11848  			}
 11849  			if abs(a) > prg.maxAllowed {
 11850  				if a > 0 {
 11851  					a = prg.maxAllowed
 11852  				} else {
 11853  					a = -prg.maxAllowed
 11854  				}
 11855  			}
 11856  			prg.beforeAndAfter(b, a, q)
 11857  		}
 11858  		p = q
 11859  		if int32(p) == int32(prg.curSpec) {
 11860  			break
 11861  		}
 11862  	}
 11863  	if int32(prg.curRoundingPtr) > 0 {
 11864  		prg.makeSafe()
 11865  		for {
 11866  			prg.curRoundingPtr = uint16(int32(prg.curRoundingPtr) - 1)
 11867  			if prg.after[prg.curRoundingPtr] != prg.before[prg.curRoundingPtr] || prg.after[int32(prg.curRoundingPtr)+1] != prg.before[int32(prg.curRoundingPtr)+1] {
 11868  				p = prg.nodeToRound[prg.curRoundingPtr]
 11869  				if *(*prg.mem[p].hh()).b1()&1 != 0 {
 11870  					b = prg.before[prg.curRoundingPtr]
 11871  					a = prg.after[prg.curRoundingPtr]
 11872  				} else {
 11873  					b = -prg.before[prg.curRoundingPtr]
 11874  					a = -prg.after[prg.curRoundingPtr]
 11875  				}
 11876  				if prg.before[prg.curRoundingPtr] == prg.before[int32(prg.curRoundingPtr)+1] {
 11877  					alpha = 02000000000
 11878  				} else {
 11879  					alpha = prg.makeFraction(prg.after[int32(prg.curRoundingPtr)+1]-prg.after[prg.curRoundingPtr], prg.before[int32(prg.curRoundingPtr)+1]-prg.before[prg.curRoundingPtr])
 11880  				}
 11881  				for {
 11882  					*prg.mem[int32(p)+1].int() = prg.takeFraction(alpha, *prg.mem[int32(p)+1].int()-b) + a
 11883  					*prg.mem[int32(p)+5].int() = prg.takeFraction(alpha, *prg.mem[int32(p)+5].int()-b) + a
 11884  					p = *(*prg.mem[p].hh()).rh()
 11885  					*prg.mem[int32(p)+3].int() = prg.takeFraction(alpha, *prg.mem[int32(p)+3].int()-b) + a
 11886  					if int32(p) == int32(prg.nodeToRound[int32(prg.curRoundingPtr)+1]) {
 11887  						break
 11888  					}
 11889  				}
 11890  			}
 11891  			if int32(prg.curRoundingPtr) == 0 {
 11892  				break
 11893  			}
 11894  		}
 11895  	}
 11896  	p = prg.curSpec
 11897  	prg.curRoundingPtr = 0
 11898  	for {
 11899  		q = *(*prg.mem[p].hh()).rh()
 11900  
 11901  		// If node |q| is a transition point for |y| coordinates, compute and save its before-and-after coordinates
 11902  		if int32(*(*prg.mem[p].hh()).b1()) > negateY != (int32(*(*prg.mem[q].hh()).b1()) > negateY) {
 11903  			if int32(*(*prg.mem[q].hh()).b1()) <= negateY {
 11904  				b = *prg.mem[int32(q)+2].int()
 11905  			} else {
 11906  				b = -*prg.mem[int32(q)+2].int()
 11907  			}
 11908  			if abs(*prg.mem[int32(q)+2].int()-*prg.mem[int32(q)+6].int()) < 655 || abs(*prg.mem[int32(q)+2].int()+*prg.mem[int32(q)+4].int()) < 655 {
 11909  				if int32(prg.curPen) == memMin+3 {
 11910  					penEdge = 0
 11911  				} else if int32(prg.curPathType) == doublePathCode {
 11912  					penEdge = prg.compromise(*prg.mem[int32(*(*prg.mem[int32(prg.curPen)+fourthOctant].hh()).rh())+2].int(), *prg.mem[int32(*(*prg.mem[int32(prg.curPen)+firstOctant].hh()).rh())+2].int())
 11913  				} else if int32(*(*prg.mem[q].hh()).b1()) <= negateY {
 11914  					penEdge = *prg.mem[int32(*(*prg.mem[int32(prg.curPen)+firstOctant].hh()).rh())+2].int()
 11915  				} else {
 11916  					penEdge = *prg.mem[int32(*(*prg.mem[int32(prg.curPen)+fourthOctant].hh()).rh())+2].int()
 11917  				}
 11918  				a = prg.goodVal(b, penEdge)
 11919  			} else {
 11920  				a = b
 11921  			}
 11922  			if abs(a) > prg.maxAllowed {
 11923  				if a > 0 {
 11924  					a = prg.maxAllowed
 11925  				} else {
 11926  					a = -prg.maxAllowed
 11927  				}
 11928  			}
 11929  			prg.beforeAndAfter(b, a, q)
 11930  		}
 11931  		p = q
 11932  		if int32(p) == int32(prg.curSpec) {
 11933  			break
 11934  		}
 11935  	}
 11936  	if int32(prg.curRoundingPtr) > 0 {
 11937  		prg.makeSafe()
 11938  		for {
 11939  			prg.curRoundingPtr = uint16(int32(prg.curRoundingPtr) - 1)
 11940  			if prg.after[prg.curRoundingPtr] != prg.before[prg.curRoundingPtr] || prg.after[int32(prg.curRoundingPtr)+1] != prg.before[int32(prg.curRoundingPtr)+1] {
 11941  				p = prg.nodeToRound[prg.curRoundingPtr]
 11942  				if int32(*(*prg.mem[p].hh()).b1()) <= negateY {
 11943  					b = prg.before[prg.curRoundingPtr]
 11944  					a = prg.after[prg.curRoundingPtr]
 11945  				} else {
 11946  					b = -prg.before[prg.curRoundingPtr]
 11947  					a = -prg.after[prg.curRoundingPtr]
 11948  				}
 11949  				if prg.before[prg.curRoundingPtr] == prg.before[int32(prg.curRoundingPtr)+1] {
 11950  					alpha = 02000000000
 11951  				} else {
 11952  					alpha = prg.makeFraction(prg.after[int32(prg.curRoundingPtr)+1]-prg.after[prg.curRoundingPtr], prg.before[int32(prg.curRoundingPtr)+1]-prg.before[prg.curRoundingPtr])
 11953  				}
 11954  				for {
 11955  					*prg.mem[int32(p)+2].int() = prg.takeFraction(alpha, *prg.mem[int32(p)+2].int()-b) + a
 11956  					*prg.mem[int32(p)+6].int() = prg.takeFraction(alpha, *prg.mem[int32(p)+6].int()-b) + a
 11957  					p = *(*prg.mem[p].hh()).rh()
 11958  					*prg.mem[int32(p)+4].int() = prg.takeFraction(alpha, *prg.mem[int32(p)+4].int()-b) + a
 11959  					if int32(p) == int32(prg.nodeToRound[int32(prg.curRoundingPtr)+1]) {
 11960  						break
 11961  					}
 11962  				}
 11963  			}
 11964  			if int32(prg.curRoundingPtr) == 0 {
 11965  				break
 11966  			}
 11967  		}
 11968  	}
 11969  }
 11970  
 11971  func (prg *prg) diagRound() {
 11972  	var (
 11973  		p, q, pp                   halfword // list manipulation registers
 11974  		b, a, bb, aa, d, c, dd, cc scaled   // before and after values
 11975  		penEdge                    scaled   // offset that governs rounding
 11976  		alpha, beta                fraction // coefficients of linear transformation
 11977  		nextA                      scaled   // |after[k]| before it might have changed
 11978  		allSafe                    bool     // does everything look OK so far?
 11979  		k/* 0..maxWiggle */ uint16          // runs through before-and-after values
 11980  		firstX, firstY             scaled   // coordinates before rounding
 11981  	)
 11982  	p = prg.curSpec
 11983  	prg.curRoundingPtr = 0
 11984  	for {
 11985  		q = *(*prg.mem[p].hh()).rh()
 11986  
 11987  		// If node |q| is a transition point between octants, compute and save its before-and-after coordinates
 11988  		if int32(*(*prg.mem[p].hh()).b1()) != int32(*(*prg.mem[q].hh()).b1()) {
 11989  			if int32(*(*prg.mem[q].hh()).b1()) > switchXAndY {
 11990  				b = -*prg.mem[int32(q)+1].int()
 11991  			} else {
 11992  				b = *prg.mem[int32(q)+1].int()
 11993  			}
 11994  			if abs(int32(*(*prg.mem[q].hh()).b1())-int32(*(*prg.mem[p].hh()).b1())) == switchXAndY {
 11995  				if abs(*prg.mem[int32(q)+1].int()-*prg.mem[int32(q)+5].int()) < 655 || abs(*prg.mem[int32(q)+1].int()+*prg.mem[int32(q)+3].int()) < 655 {
 11996  					if int32(prg.curPen) == memMin+3 {
 11997  						penEdge = 0
 11998  					} else if int32(prg.curPathType) == doublePathCode {
 11999  						switch *(*prg.mem[q].hh()).b1() {
 12000  						case firstOctant, secondOctant:
 12001  							penEdge = prg.compromise(*prg.mem[int32(*(*prg.mem[*(*prg.mem[int32(prg.curPen)+firstOctant].hh()).rh()].hh()).lh())+1].int(), -*prg.mem[int32(*(*prg.mem[*(*prg.mem[int32(prg.curPen)+fifthOctant].hh()).rh()].hh()).lh())+1].int())
 12002  						case fifthOctant, sixthOctant:
 12003  							penEdge = -prg.compromise(*prg.mem[int32(*(*prg.mem[*(*prg.mem[int32(prg.curPen)+firstOctant].hh()).rh()].hh()).lh())+1].int(), -*prg.mem[int32(*(*prg.mem[*(*prg.mem[int32(prg.curPen)+fifthOctant].hh()).rh()].hh()).lh())+1].int())
 12004  						case thirdOctant, fourthOctant:
 12005  							penEdge = prg.compromise(*prg.mem[int32(*(*prg.mem[*(*prg.mem[int32(prg.curPen)+fourthOctant].hh()).rh()].hh()).lh())+1].int(), -*prg.mem[int32(*(*prg.mem[*(*prg.mem[int32(prg.curPen)+eighthOctant].hh()).rh()].hh()).lh())+1].int())
 12006  						case seventhOctant, eighthOctant:
 12007  							penEdge = -prg.compromise(*prg.mem[int32(*(*prg.mem[*(*prg.mem[int32(prg.curPen)+fourthOctant].hh()).rh()].hh()).lh())+1].int(), -*prg.mem[int32(*(*prg.mem[*(*prg.mem[int32(prg.curPen)+eighthOctant].hh()).rh()].hh()).lh())+1].int())
 12008  						}
 12009  					} else if int32(*(*prg.mem[q].hh()).b1()) <= switchXAndY {
 12010  						penEdge = *prg.mem[int32(*(*prg.mem[*(*prg.mem[int32(prg.curPen)+int32(*(*prg.mem[q].hh()).b1())].hh()).rh()].hh()).lh())+1].int()
 12011  					} else {
 12012  						penEdge = -*prg.mem[int32(*(*prg.mem[*(*prg.mem[int32(prg.curPen)+int32(*(*prg.mem[q].hh()).b1())].hh()).rh()].hh()).lh())+1].int()
 12013  					}
 12014  					if *(*prg.mem[q].hh()).b1()&1 != 0 {
 12015  						a = prg.goodVal(b, penEdge+prg.curGran/2)
 12016  					} else {
 12017  						a = prg.goodVal(b-1, penEdge+prg.curGran/2)
 12018  					}
 12019  				} else {
 12020  					a = b
 12021  				}
 12022  			} else {
 12023  				a = b
 12024  			}
 12025  			prg.beforeAndAfter(b, a, q)
 12026  		}
 12027  		p = q
 12028  		if int32(p) == int32(prg.curSpec) {
 12029  			break
 12030  		}
 12031  	}
 12032  	if int32(prg.curRoundingPtr) > 0 {
 12033  		p = prg.nodeToRound[0]
 12034  		firstX = *prg.mem[int32(p)+1].int()
 12035  		firstY = *prg.mem[int32(p)+2].int()
 12036  
 12037  		// Make sure that all the diagonal roundings are safe
 12038  		prg.before[prg.curRoundingPtr] = prg.before[0] // cf.~|make_safe|
 12039  		prg.nodeToRound[prg.curRoundingPtr] = prg.nodeToRound[0]
 12040  		for {
 12041  			prg.after[prg.curRoundingPtr] = prg.after[0]
 12042  			allSafe = true
 12043  			nextA = prg.after[0]
 12044  			for ii := int32(0); ii <= int32(prg.curRoundingPtr)-1; ii++ {
 12045  				k = uint16(ii)
 12046  				_ = k
 12047  				a = nextA
 12048  				b = prg.before[k]
 12049  				nextA = prg.after[int32(k)+1]
 12050  				aa = nextA
 12051  				bb = prg.before[int32(k)+1]
 12052  				if a != b || aa != bb {
 12053  					p = prg.nodeToRound[k]
 12054  					pp = prg.nodeToRound[int32(k)+1]
 12055  
 12056  					// Determine the before-and-after values of both coordinates
 12057  					if aa == bb {
 12058  						if int32(pp) == int32(prg.nodeToRound[0]) {
 12059  							prg.unskew(firstX, firstY, *(*prg.mem[pp].hh()).b1())
 12060  						} else {
 12061  							prg.unskew(*prg.mem[int32(pp)+1].int(), *prg.mem[int32(pp)+2].int(), *(*prg.mem[pp].hh()).b1())
 12062  						}
 12063  						prg.skew(prg.curX, prg.curY, *(*prg.mem[p].hh()).b1())
 12064  						bb = prg.curX
 12065  						aa = bb
 12066  						dd = prg.curY
 12067  						cc = dd
 12068  						if int32(*(*prg.mem[p].hh()).b1()) > switchXAndY {
 12069  							b = -b
 12070  							a = -a
 12071  						}
 12072  					} else {
 12073  						if int32(*(*prg.mem[p].hh()).b1()) > switchXAndY {
 12074  							bb = -bb
 12075  							aa = -aa
 12076  							b = -b
 12077  							a = -a
 12078  						}
 12079  						if int32(pp) == int32(prg.nodeToRound[0]) {
 12080  							dd = firstY - bb
 12081  						} else {
 12082  							dd = *prg.mem[int32(pp)+2].int() - bb
 12083  						}
 12084  						if (aa-bb)&1 != 0 {
 12085  							if int32(*(*prg.mem[p].hh()).b1()) > switchXAndY {
 12086  								cc = dd - (aa-bb+1)/2
 12087  							} else {
 12088  								cc = dd - (aa-bb-1)/2
 12089  							}
 12090  						} else {
 12091  							cc = dd - (aa-bb)/2
 12092  						}
 12093  					}
 12094  					d = *prg.mem[int32(p)+2].int()
 12095  					if (a-b)&1 != 0 {
 12096  						if int32(*(*prg.mem[p].hh()).b1()) > switchXAndY {
 12097  							c = d - (a-b-1)/2
 12098  						} else {
 12099  							c = d - (a-b+1)/2
 12100  						}
 12101  					} else {
 12102  						c = d - (a-b)/2
 12103  					}
 12104  					if aa < a || cc < c || aa-a > 2*(bb-b) || cc-c > 2*(dd-d) {
 12105  						allSafe = false
 12106  						prg.after[k] = prg.before[k]
 12107  						if int32(k) == int32(prg.curRoundingPtr)-1 {
 12108  							prg.after[0] = prg.before[0]
 12109  						} else {
 12110  							prg.after[int32(k)+1] = prg.before[int32(k)+1]
 12111  						}
 12112  					}
 12113  				}
 12114  			}
 12115  			if allSafe {
 12116  				break
 12117  			}
 12118  		}
 12119  		for ii := int32(0); ii <= int32(prg.curRoundingPtr)-1; ii++ {
 12120  			k = uint16(ii)
 12121  			_ = k
 12122  			a = prg.after[k]
 12123  			b = prg.before[k]
 12124  			aa = prg.after[int32(k)+1]
 12125  			bb = prg.before[int32(k)+1]
 12126  			if a != b || aa != bb {
 12127  				p = prg.nodeToRound[k]
 12128  				pp = prg.nodeToRound[int32(k)+1]
 12129  
 12130  				// Determine the before-and-after values of both coordinates
 12131  				if aa == bb {
 12132  					if int32(pp) == int32(prg.nodeToRound[0]) {
 12133  						prg.unskew(firstX, firstY, *(*prg.mem[pp].hh()).b1())
 12134  					} else {
 12135  						prg.unskew(*prg.mem[int32(pp)+1].int(), *prg.mem[int32(pp)+2].int(), *(*prg.mem[pp].hh()).b1())
 12136  					}
 12137  					prg.skew(prg.curX, prg.curY, *(*prg.mem[p].hh()).b1())
 12138  					bb = prg.curX
 12139  					aa = bb
 12140  					dd = prg.curY
 12141  					cc = dd
 12142  					if int32(*(*prg.mem[p].hh()).b1()) > switchXAndY {
 12143  						b = -b
 12144  						a = -a
 12145  					}
 12146  				} else {
 12147  					if int32(*(*prg.mem[p].hh()).b1()) > switchXAndY {
 12148  						bb = -bb
 12149  						aa = -aa
 12150  						b = -b
 12151  						a = -a
 12152  					}
 12153  					if int32(pp) == int32(prg.nodeToRound[0]) {
 12154  						dd = firstY - bb
 12155  					} else {
 12156  						dd = *prg.mem[int32(pp)+2].int() - bb
 12157  					}
 12158  					if (aa-bb)&1 != 0 {
 12159  						if int32(*(*prg.mem[p].hh()).b1()) > switchXAndY {
 12160  							cc = dd - (aa-bb+1)/2
 12161  						} else {
 12162  							cc = dd - (aa-bb-1)/2
 12163  						}
 12164  					} else {
 12165  						cc = dd - (aa-bb)/2
 12166  					}
 12167  				}
 12168  				d = *prg.mem[int32(p)+2].int()
 12169  				if (a-b)&1 != 0 {
 12170  					if int32(*(*prg.mem[p].hh()).b1()) > switchXAndY {
 12171  						c = d - (a-b-1)/2
 12172  					} else {
 12173  						c = d - (a-b+1)/2
 12174  					}
 12175  				} else {
 12176  					c = d - (a-b)/2
 12177  				}
 12178  				if b == bb {
 12179  					alpha = 02000000000
 12180  				} else {
 12181  					alpha = prg.makeFraction(aa-a, bb-b)
 12182  				}
 12183  				if d == dd {
 12184  					beta = 02000000000
 12185  				} else {
 12186  					beta = prg.makeFraction(cc-c, dd-d)
 12187  				}
 12188  				for {
 12189  					*prg.mem[int32(p)+1].int() = prg.takeFraction(alpha, *prg.mem[int32(p)+1].int()-b) + a
 12190  					*prg.mem[int32(p)+2].int() = prg.takeFraction(beta, *prg.mem[int32(p)+2].int()-d) + c
 12191  					*prg.mem[int32(p)+5].int() = prg.takeFraction(alpha, *prg.mem[int32(p)+5].int()-b) + a
 12192  					*prg.mem[int32(p)+6].int() = prg.takeFraction(beta, *prg.mem[int32(p)+6].int()-d) + c
 12193  					p = *(*prg.mem[p].hh()).rh()
 12194  					*prg.mem[int32(p)+3].int() = prg.takeFraction(alpha, *prg.mem[int32(p)+3].int()-b) + a
 12195  					*prg.mem[int32(p)+4].int() = prg.takeFraction(beta, *prg.mem[int32(p)+4].int()-d) + c
 12196  					if int32(p) == int32(pp) {
 12197  						break
 12198  					}
 12199  				}
 12200  			}
 12201  		}
 12202  	}
 12203  }
 12204  
 12205  func (prg *prg) newBoundary(p halfword, octant smallNumber) {
 12206  	var (
 12207  		q, r1 halfword // for list manipulation
 12208  	)
 12209  	q = *(*prg.mem[p].hh()).rh() // we assume that |right_type(q)<>endpoint|
 12210  	r1 = prg.getNode(knotNodeSize)
 12211  	*(*prg.mem[r1].hh()).rh() = q
 12212  	*(*prg.mem[p].hh()).rh() = r1
 12213  	*(*prg.mem[r1].hh()).b0() = *(*prg.mem[q].hh()).b0() // but possibly |left_type(q)=endpoint|
 12214  	*prg.mem[int32(r1)+3].int() = *prg.mem[int32(q)+3].int()
 12215  	*prg.mem[int32(r1)+4].int() = *prg.mem[int32(q)+4].int()
 12216  	*(*prg.mem[r1].hh()).b1() = byte(endpoint)
 12217  	*(*prg.mem[q].hh()).b0() = byte(endpoint)
 12218  	*prg.mem[int32(r1)+5].int() = int32(octant)
 12219  	*prg.mem[int32(q)+3].int() = int32(*(*prg.mem[q].hh()).b1())
 12220  	prg.unskew(*prg.mem[int32(q)+1].int(), *prg.mem[int32(q)+2].int(), *(*prg.mem[q].hh()).b1())
 12221  	prg.skew(prg.curX, prg.curY, octant)
 12222  	*prg.mem[int32(r1)+1].int() = prg.curX
 12223  	*prg.mem[int32(r1)+2].int() = prg.curY
 12224  }
 12225  
 12226  func (prg *prg) makeSpec(h halfword,
 12227  	safetyMargin scaled, tracing int32) (r halfword) {
 12228  	var (
 12229  		p, q, r1, s halfword // for traversing the lists
 12230  		k           int32    // serial number of path segment, or octant code
 12231  		chopped     int32    // positive if data truncated,
 12232  		//           negative if data dangerously large
 12233  
 12234  		// Other local variables for |make_spec|
 12235  		o1, o2             smallNumber // octant numbers
 12236  		clockwise          bool        // should we turn clockwise?
 12237  		dx1, dy1, dx2, dy2 int32       // directions of travel at a cusp
 12238  		dmax, del          int32       // temporary registers
 12239  	)
 12240  	prg.curSpec = h
 12241  	if tracing > 0 {
 12242  		prg.printPath(prg.curSpec, strNumber( /* ", before subdivision into octants" */ 559), true)
 12243  	}
 12244  	prg.maxAllowed = 02000000000 - 0100000 - 1 - safetyMargin
 12245  
 12246  	// Truncate the values of all coordinates that exceed |max_allowed|, and stamp segment numbers in each |left_type| field
 12247  	p = prg.curSpec
 12248  	k = 1
 12249  	chopped = 0
 12250  	dmax = prg.maxAllowed / 2
 12251  	for {
 12252  		if abs(*prg.mem[int32(p)+3].int()) >= dmax {
 12253  			if abs(*prg.mem[int32(p)+3].int()) > prg.maxAllowed {
 12254  				chopped = 1
 12255  				if *prg.mem[int32(p)+3].int() > 0 {
 12256  					*prg.mem[int32(p)+3].int() = prg.maxAllowed
 12257  				} else {
 12258  					*prg.mem[int32(p)+3].int() = -prg.maxAllowed
 12259  				}
 12260  			} else if chopped == 0 {
 12261  				chopped = -1
 12262  			}
 12263  		}
 12264  		if abs(*prg.mem[int32(p)+4].int()) >= dmax {
 12265  			if abs(*prg.mem[int32(p)+4].int()) > prg.maxAllowed {
 12266  				chopped = 1
 12267  				if *prg.mem[int32(p)+4].int() > 0 {
 12268  					*prg.mem[int32(p)+4].int() = prg.maxAllowed
 12269  				} else {
 12270  					*prg.mem[int32(p)+4].int() = -prg.maxAllowed
 12271  				}
 12272  			} else if chopped == 0 {
 12273  				chopped = -1
 12274  			}
 12275  		}
 12276  		if abs(*prg.mem[int32(p)+1].int()) >= dmax {
 12277  			if abs(*prg.mem[int32(p)+1].int()) > prg.maxAllowed {
 12278  				chopped = 1
 12279  				if *prg.mem[int32(p)+1].int() > 0 {
 12280  					*prg.mem[int32(p)+1].int() = prg.maxAllowed
 12281  				} else {
 12282  					*prg.mem[int32(p)+1].int() = -prg.maxAllowed
 12283  				}
 12284  			} else if chopped == 0 {
 12285  				chopped = -1
 12286  			}
 12287  		}
 12288  		if abs(*prg.mem[int32(p)+2].int()) >= dmax {
 12289  			if abs(*prg.mem[int32(p)+2].int()) > prg.maxAllowed {
 12290  				chopped = 1
 12291  				if *prg.mem[int32(p)+2].int() > 0 {
 12292  					*prg.mem[int32(p)+2].int() = prg.maxAllowed
 12293  				} else {
 12294  					*prg.mem[int32(p)+2].int() = -prg.maxAllowed
 12295  				}
 12296  			} else if chopped == 0 {
 12297  				chopped = -1
 12298  			}
 12299  		}
 12300  		if abs(*prg.mem[int32(p)+5].int()) >= dmax {
 12301  			if abs(*prg.mem[int32(p)+5].int()) > prg.maxAllowed {
 12302  				chopped = 1
 12303  				if *prg.mem[int32(p)+5].int() > 0 {
 12304  					*prg.mem[int32(p)+5].int() = prg.maxAllowed
 12305  				} else {
 12306  					*prg.mem[int32(p)+5].int() = -prg.maxAllowed
 12307  				}
 12308  			} else if chopped == 0 {
 12309  				chopped = -1
 12310  			}
 12311  		}
 12312  		if abs(*prg.mem[int32(p)+6].int()) >= dmax {
 12313  			if abs(*prg.mem[int32(p)+6].int()) > prg.maxAllowed {
 12314  				chopped = 1
 12315  				if *prg.mem[int32(p)+6].int() > 0 {
 12316  					*prg.mem[int32(p)+6].int() = prg.maxAllowed
 12317  				} else {
 12318  					*prg.mem[int32(p)+6].int() = -prg.maxAllowed
 12319  				}
 12320  			} else if chopped == 0 {
 12321  				chopped = -1
 12322  			}
 12323  		}
 12324  
 12325  		p = *(*prg.mem[p].hh()).rh()
 12326  		*(*prg.mem[p].hh()).b0() = byte(k)
 12327  		if k < maxQuarterword {
 12328  			k = k + 1
 12329  		} else {
 12330  			k = 1
 12331  		}
 12332  		if int32(p) == int32(prg.curSpec) {
 12333  			break
 12334  		}
 12335  	}
 12336  	if chopped > 0 {
 12337  		{
 12338  			if int32(prg.interaction) == errorStopMode {
 12339  			}
 12340  			prg.printNl(strNumber( /* "! " */ 261))
 12341  			prg.print( /* "Curve out of range" */ 563) /* \xref[!\relax]  */
 12342  		}
 12343  		// \xref[Curve out of range]
 12344  		{
 12345  			prg.helpPtr = 4
 12346  			prg.helpLine[3] = /* "At least one of the coordinates in the path I'm about to" */ 564
 12347  			prg.helpLine[2] = /* "digitize was really huge (potentially bigger than 4095)." */ 565
 12348  			prg.helpLine[1] = /* "So I've cut it back to the maximum size." */ 566
 12349  			prg.helpLine[0] = /* "The results will probably be pretty wild." */ 567
 12350  		}
 12351  		prg.putGetError()
 12352  	}
 12353  	prg.quadrantSubdivide() // subdivide each cubic into pieces belonging to quadrants
 12354  	if prg.internal[autorounding-1] > 0 && chopped == 0 {
 12355  		prg.xyRound()
 12356  	}
 12357  	prg.octantSubdivide() // complete the subdivision
 12358  	if prg.internal[autorounding-1] > 0200000 && chopped == 0 {
 12359  		prg.diagRound()
 12360  	}
 12361  
 12362  	// Remove dead cubics
 12363  	p = prg.curSpec
 12364  	for {
 12365  	continue1:
 12366  		q = *(*prg.mem[p].hh()).rh()
 12367  		if int32(p) != int32(q) {
 12368  			if *prg.mem[int32(p)+1].int() == *prg.mem[int32(p)+5].int() {
 12369  				if *prg.mem[int32(p)+2].int() == *prg.mem[int32(p)+6].int() {
 12370  					if *prg.mem[int32(p)+1].int() == *prg.mem[int32(q)+3].int() {
 12371  						if *prg.mem[int32(p)+2].int() == *prg.mem[int32(q)+4].int() {
 12372  							prg.unskew(*prg.mem[int32(q)+1].int(), *prg.mem[int32(q)+2].int(), *(*prg.mem[q].hh()).b1())
 12373  							prg.skew(prg.curX, prg.curY, *(*prg.mem[p].hh()).b1())
 12374  							if *prg.mem[int32(p)+1].int() == prg.curX {
 12375  								if *prg.mem[int32(p)+2].int() == prg.curY {
 12376  									prg.removeCubic(p) // remove the cubic following |p|
 12377  									if int32(q) != int32(prg.curSpec) {
 12378  										goto continue1
 12379  									}
 12380  									prg.curSpec = p
 12381  									q = p
 12382  								}
 12383  							}
 12384  						}
 12385  					}
 12386  				}
 12387  			}
 12388  		}
 12389  		p = q
 12390  		if int32(p) == int32(prg.curSpec) {
 12391  			break
 12392  		}
 12393  	}
 12394  
 12395  	// Insert octant boundaries and compute the turning number
 12396  	prg.turningNumber = 0
 12397  	p = prg.curSpec
 12398  	q = *(*prg.mem[p].hh()).rh()
 12399  	for {
 12400  		r1 = *(*prg.mem[q].hh()).rh()
 12401  		if int32(*(*prg.mem[p].hh()).b1()) != int32(*(*prg.mem[q].hh()).b1()) || int32(q) == int32(r1) {
 12402  			prg.newBoundary(p, *(*prg.mem[p].hh()).b1())
 12403  			s = *(*prg.mem[p].hh()).rh()
 12404  			o1 = prg.octantNumber[*(*prg.mem[p].hh()).b1()-1]
 12405  			o2 = prg.octantNumber[*(*prg.mem[q].hh()).b1()-1]
 12406  			switch int32(o2) - int32(o1) {
 12407  			case 1, -7, 7, -1:
 12408  				goto done
 12409  			case 2, -6:
 12410  				clockwise = false
 12411  			case 3, -5, 4, -4,
 12412  				5, -3:
 12413  				// Decide whether or not to go clockwise
 12414  				dx1 = *prg.mem[int32(s)+1].int() - *prg.mem[int32(s)+3].int()
 12415  				dy1 = *prg.mem[int32(s)+2].int() - *prg.mem[int32(s)+4].int()
 12416  				if dx1 == 0 {
 12417  					if dy1 == 0 {
 12418  						dx1 = *prg.mem[int32(s)+1].int() - *prg.mem[int32(p)+5].int()
 12419  						dy1 = *prg.mem[int32(s)+2].int() - *prg.mem[int32(p)+6].int()
 12420  						if dx1 == 0 {
 12421  							if dy1 == 0 {
 12422  								dx1 = *prg.mem[int32(s)+1].int() - *prg.mem[int32(p)+1].int()
 12423  								dy1 = *prg.mem[int32(s)+2].int() - *prg.mem[int32(p)+2].int()
 12424  							}
 12425  						} // and they [\sl can't] both be zero
 12426  					}
 12427  				}
 12428  				dmax = abs(dx1)
 12429  				if abs(dy1) > dmax {
 12430  					dmax = abs(dy1)
 12431  				}
 12432  				for dmax < 02000000000 {
 12433  					dmax = dmax + dmax
 12434  					dx1 = dx1 + dx1
 12435  					dy1 = dy1 + dy1
 12436  				}
 12437  				dx2 = *prg.mem[int32(q)+5].int() - *prg.mem[int32(q)+1].int()
 12438  				dy2 = *prg.mem[int32(q)+6].int() - *prg.mem[int32(q)+2].int()
 12439  				if dx2 == 0 {
 12440  					if dy2 == 0 {
 12441  						dx2 = *prg.mem[int32(r1)+3].int() - *prg.mem[int32(q)+1].int()
 12442  						dy2 = *prg.mem[int32(r1)+4].int() - *prg.mem[int32(q)+2].int()
 12443  						if dx2 == 0 {
 12444  							if dy2 == 0 {
 12445  								if int32(*(*prg.mem[r1].hh()).b1()) == endpoint {
 12446  									prg.curX = *prg.mem[int32(r1)+1].int()
 12447  									prg.curY = *prg.mem[int32(r1)+2].int()
 12448  								} else {
 12449  									prg.unskew(*prg.mem[int32(r1)+1].int(), *prg.mem[int32(r1)+2].int(), *(*prg.mem[r1].hh()).b1())
 12450  									prg.skew(prg.curX, prg.curY, *(*prg.mem[q].hh()).b1())
 12451  								}
 12452  								dx2 = prg.curX - *prg.mem[int32(q)+1].int()
 12453  								dy2 = prg.curY - *prg.mem[int32(q)+2].int()
 12454  							}
 12455  						} // and they [\sl can't] both be zero
 12456  					}
 12457  				}
 12458  				dmax = abs(dx2)
 12459  				if abs(dy2) > dmax {
 12460  					dmax = abs(dy2)
 12461  				}
 12462  				for dmax < 02000000000 {
 12463  					dmax = dmax + dmax
 12464  					dx2 = dx2 + dx2
 12465  					dy2 = dy2 + dy2
 12466  				}
 12467  				prg.unskew(dx1, dy1, *(*prg.mem[p].hh()).b1())
 12468  				del = prg.pythAdd(prg.curX, prg.curY)
 12469  
 12470  				dx1 = prg.makeFraction(prg.curX, del)
 12471  				dy1 = prg.makeFraction(prg.curY, del)
 12472  				// $\cos\theta_1$ and $\sin\theta_1$
 12473  				prg.unskew(dx2, dy2, *(*prg.mem[q].hh()).b1())
 12474  				del = prg.pythAdd(prg.curX, prg.curY)
 12475  
 12476  				dx2 = prg.makeFraction(prg.curX, del)
 12477  				dy2 = prg.makeFraction(prg.curY, del)
 12478  				// $\cos\theta_2$ and $\sin\theta_2$
 12479  				del = prg.takeFraction(dx1, dy2) - prg.takeFraction(dx2, dy1) // $\sin(\theta_2-\theta_1)$
 12480  				if del > 4684844 {
 12481  					clockwise = false
 12482  				} else if del < -4684844 {
 12483  					clockwise = true
 12484  				} else {
 12485  					clockwise = prg.revTurns
 12486  				}
 12487  
 12488  			case 6, -2:
 12489  				clockwise = true
 12490  			case 0:
 12491  				clockwise = prg.revTurns
 12492  			} // there are no other cases
 12493  
 12494  			// Insert additional boundary nodes, then |goto done|
 12495  			for true {
 12496  				if clockwise {
 12497  					if int32(o1) == 1 {
 12498  						o1 = 8
 12499  					} else {
 12500  						o1 = byte(int32(o1) - 1)
 12501  					}
 12502  				} else if int32(o1) == 8 {
 12503  					o1 = 1
 12504  				} else {
 12505  					o1 = byte(int32(o1) + 1)
 12506  				}
 12507  				if int32(o1) == int32(o2) {
 12508  					goto done
 12509  				}
 12510  				prg.newBoundary(s, prg.octantCode[o1-1])
 12511  				s = *(*prg.mem[s].hh()).rh()
 12512  				*prg.mem[int32(s)+3].int() = *prg.mem[int32(s)+5].int()
 12513  			}
 12514  
 12515  		done:
 12516  			if int32(q) == int32(r1) {
 12517  				q = *(*prg.mem[q].hh()).rh()
 12518  				r1 = q
 12519  				p = s
 12520  				*(*prg.mem[s].hh()).rh() = q
 12521  				*prg.mem[int32(q)+3].int() = *prg.mem[int32(q)+5].int()
 12522  				*(*prg.mem[q].hh()).b0() = byte(endpoint)
 12523  				prg.freeNode(prg.curSpec, halfword(knotNodeSize))
 12524  				prg.curSpec = q
 12525  			}
 12526  
 12527  			// Fix up the transition fields and adjust the turning number
 12528  			p = *(*prg.mem[p].hh()).rh()
 12529  			for {
 12530  				s = *(*prg.mem[p].hh()).rh()
 12531  				o1 = prg.octantNumber[*prg.mem[int32(p)+5].int()-1]
 12532  				o2 = prg.octantNumber[*prg.mem[int32(s)+3].int()-1]
 12533  				if abs(int32(o1)-int32(o2)) == 1 {
 12534  					if int32(o2) < int32(o1) {
 12535  						o2 = o1
 12536  					}
 12537  					if o2&1 != 0 {
 12538  						*prg.mem[int32(p)+6].int() = axis
 12539  					} else {
 12540  						*prg.mem[int32(p)+6].int() = diagonal
 12541  					}
 12542  				} else {
 12543  					if int32(o1) == 8 {
 12544  						prg.turningNumber = prg.turningNumber + 1
 12545  					} else {
 12546  						prg.turningNumber = prg.turningNumber - 1
 12547  					}
 12548  					*prg.mem[int32(p)+6].int() = axis
 12549  				}
 12550  				*prg.mem[int32(s)+4].int() = *prg.mem[int32(p)+6].int()
 12551  				p = s
 12552  				if int32(p) == int32(q) {
 12553  					break
 12554  				}
 12555  			}
 12556  		}
 12557  		p = q
 12558  		q = r1
 12559  		if int32(p) == int32(prg.curSpec) {
 12560  			break
 12561  		}
 12562  	}
 12563  
 12564  	for int32(*(*prg.mem[prg.curSpec].hh()).b0()) != endpoint {
 12565  		prg.curSpec = *(*prg.mem[prg.curSpec].hh()).rh()
 12566  	}
 12567  	if tracing > 0 {
 12568  		if prg.internal[autorounding-1] <= 0 || chopped != 0 {
 12569  			prg.printSpec(strNumber( /* ", after subdivision" */ 560))
 12570  		} else if prg.internal[autorounding-1] > 0200000 {
 12571  			prg.printSpec(strNumber( /* ", after subdivision and double autorounding" */ 561))
 12572  		} else {
 12573  			prg.printSpec(strNumber( /* ", after subdivision and autorounding" */ 562))
 12574  		}
 12575  	}
 12576  	r = prg.curSpec
 12577  	return r
 12578  }
 12579  
 12580  // 422.
 12581  
 12582  // tangle:pos ../../mf.web:9070:3:
 12583  
 12584  // The swapping here doesn't simply interchange |x| and |y| values,
 12585  // because the coordinates are skewed. It turns out that this is easier
 12586  // than ordinary swapping, because it can be done in two assignment statements
 12587  // rather than three.
 12588  
 12589  // 460. \[22] Filling a contour
 12590  
 12591  // tangle:pos ../../mf.web:9791:28:
 12592  
 12593  // Given the low-level machinery for making moves and for transforming a
 12594  // cyclic path into a cycle spec, we're almost able to fill a digitized path.
 12595  // All we need is a high-level routine that walks through the cycle spec and
 12596  // controls the overall process.
 12597  //
 12598  // Our overall goal is to plot the integer points $\bigl(\round(x(t)),
 12599  // \round(y(t))\bigr)$ and to connect them by rook moves, assuming that
 12600  // $\round(x(t))$ and $\round(y(t))$ don't both jump simultaneously from
 12601  // one integer to another as $t$~varies; these rook moves will be the edge
 12602  // of the contour that will be filled. We have reduced this problem to the
 12603  // case of curves that travel in first octant directions, i.e., curves
 12604  // such that $0\L y'(t)\L x'(t)$, by transforming the original coordinates.
 12605  //
 12606  // \def\xtilde[[\tilde x]] \def\ytilde[[\tilde y]]
 12607  // Another transformation makes the problem still simpler. We shall say that
 12608  // we are working with [\sl biased coordinates\/] when $(x,y)$ has been
 12609  // replaced by $(\xtilde,\ytilde)=(x-y,y+[1\over2])$. When a curve travels
 12610  // in first octant directions, the corresponding curve with biased
 12611  // coordinates travels in first [\sl quadrant\/] directions; the latter
 12612  // condition is symmetric in $x$ and~$y$, so it has advantages for the
 12613  // design of algorithms. The |make_spec| routine gives us skewed coordinates
 12614  // $(x-y,y)$, hence we obtain biased coordinates by simply adding $1\over2$
 12615  // to the second component.
 12616  //
 12617  // The most important fact about biased coordinates is that we can determine the
 12618  // rounded unbiased path $\bigl(\round(x(t)),\round(y(t))\bigr)$ from the
 12619  // truncated biased path $\bigl(\lfloor\xtilde(t)\rfloor,\lfloor\ytilde(t)\rfloor
 12620  // \bigr)$ and information about the initial and final endpoints. If the
 12621  // unrounded and unbiased
 12622  // path begins at $(x_0,y_0)$ and ends at $(x_1,y_1)$, it's possible to
 12623  // prove (by induction on the length of the truncated biased path) that the
 12624  // rounded unbiased path is obtained by the following construction:
 12625  //
 12626  // \yskip\textindent[1)] Start at $\bigl(\round(x_0),\round(y_0)\bigr)$.
 12627  //
 12628  // \yskip\textindent[2)] If $(x_0+[1\over2])\bmod1\G(y_0+[1\over2])\bmod1$,
 12629  // move one step right.
 12630  //
 12631  // \yskip\textindent[3)] Whenever the path
 12632  // $\bigl(\lfloor\xtilde(t)\rfloor,\lfloor\ytilde(t)\rfloor\bigr)$
 12633  // takes an upward step (i.e., when
 12634  // $\lfloor\xtilde(t+\epsilon)\rfloor=\lfloor\xtilde(t)\rfloor$ and
 12635  // $\lfloor\ytilde(t+\epsilon)\rfloor=\lfloor\ytilde(t)\rfloor+1$),
 12636  // move one step up and then one step right.
 12637  //
 12638  // \yskip\textindent[4)] Whenever the path
 12639  // $\bigl(\lfloor\xtilde(t)\rfloor,\lfloor\ytilde(t)\rfloor\bigr)$
 12640  // takes a rightward step (i.e., when
 12641  // $\lfloor\xtilde(t+\epsilon)\rfloor=\lfloor\xtilde(t)\rfloor+1$ and
 12642  // $\lfloor\ytilde(t+\epsilon)\rfloor=\lfloor\ytilde(t)\rfloor$),
 12643  // move one step right.
 12644  //
 12645  // \yskip\textindent[5)] Finally, if
 12646  // $(x_1+[1\over2])\bmod1\G(y_1+[1\over2])\bmod1$, move one step left (thereby
 12647  // cancelling the previous move, which was one step right). You will now be
 12648  // at the point $\bigl(\round(x_1),\round(y_1)\bigr)$.
 12649  
 12650  // 463.
 12651  
 12652  // tangle:pos ../../mf.web:9913:3:
 12653  
 12654  // Here's a procedure that handles the details of rounding at the
 12655  // endpoints: Given skewed coordinates |(x,y)|, it sets |(m1,n1)|
 12656  // to the corresponding rounded lattice points, taking the current
 12657  // |octant| into account. Global variable |d1| is also set to 1 if
 12658  // $(x+y+[1\over2])\bmod1\G(y+[1\over2])\bmod1$.
 12659  func (prg *prg) endRound(x, y scaled) {
 12660  	y = y + 0100000 - int32(prg.yCorr[prg.octant-1])
 12661  	x = x + y - int32(prg.xCorr[prg.octant-1])
 12662  	prg.m1 = prg.floorUnscaled(x)
 12663  	prg.n1 = prg.floorUnscaled(y)
 12664  	if x-0200000*prg.m1 >= y-0200000*prg.n1+int32(prg.zCorr[prg.octant-1]) {
 12665  		prg.d1 = 1
 12666  	} else {
 12667  		prg.d1 = 0
 12668  	}
 12669  }
 12670  
 12671  // 465.
 12672  
 12673  // tangle:pos ../../mf.web:9933:3:
 12674  
 12675  // We're ready now to fill the pixels enclosed by a given cycle spec~|h|;
 12676  // the knot list that represents the cycle is destroyed in the process.
 12677  // The edge structure that gets all the resulting data is |cur_edges|,
 12678  // and the edges are weighted by |cur_wt|.
 12679  func (prg *prg) fillSpec(h halfword) {
 12680  	var (
 12681  		p, q, r1, s halfword // for list traversal
 12682  	)
 12683  	if prg.internal[tracingEdges-1] > 0 {
 12684  		prg.beginEdgeTracing()
 12685  	}
 12686  	p = h // we assume that |left_type(h)=endpoint|
 12687  	for {
 12688  		prg.octant = byte(*prg.mem[int32(p)+3].int())
 12689  
 12690  		// Set variable |q| to the node at the end of the current octant
 12691  		q = p
 12692  		for int32(*(*prg.mem[q].hh()).b1()) != endpoint {
 12693  			q = *(*prg.mem[q].hh()).rh()
 12694  		}
 12695  		if int32(q) != int32(p) {
 12696  			prg.endRound(*prg.mem[int32(p)+1].int(), *prg.mem[int32(p)+2].int())
 12697  			prg.m0 = prg.m1
 12698  			prg.n0 = prg.n1
 12699  			prg.d0 = prg.d1
 12700  
 12701  			prg.endRound(*prg.mem[int32(q)+1].int(), *prg.mem[int32(q)+2].int())
 12702  
 12703  			// Make the moves for the current octant
 12704  			if prg.n1-prg.n0 >= moveSize {
 12705  				prg.overflow(strNumber( /* "move table size" */ 540), moveSize)
 12706  			}
 12707  			// \xref[METAFONT capacity exceeded move table size][\quad move table size]
 12708  			prg.move[0] = int32(prg.d0)
 12709  			prg.movePtr = 0
 12710  			r1 = p
 12711  			for {
 12712  				s = *(*prg.mem[r1].hh()).rh()
 12713  
 12714  				prg.makeMoves(*prg.mem[int32(r1)+1].int(), *prg.mem[int32(r1)+5].int(), *prg.mem[int32(s)+3].int(), *prg.mem[int32(s)+1].int(), *prg.mem[int32(r1)+2].int()+0100000, *prg.mem[int32(r1)+6].int()+0100000, *prg.mem[int32(s)+4].int()+0100000, *prg.mem[int32(s)+2].int()+0100000, prg.xyCorr[prg.octant-1], prg.yCorr[prg.octant-1])
 12715  				r1 = s
 12716  				if int32(r1) == int32(q) {
 12717  					break
 12718  				}
 12719  			}
 12720  			prg.move[prg.movePtr] = prg.move[prg.movePtr] - int32(prg.d1)
 12721  			if prg.internal[smoothing-1] > 0 {
 12722  				prg.smoothMoves(0, int32(prg.movePtr))
 12723  			}
 12724  			prg.moveToEdges(prg.m0, prg.n0, prg.m1, prg.n1)
 12725  		}
 12726  		p = *(*prg.mem[q].hh()).rh()
 12727  		if int32(p) == int32(h) {
 12728  			break
 12729  		}
 12730  	}
 12731  	prg.tossKnotList(h)
 12732  	if prg.internal[tracingEdges-1] > 0 {
 12733  		prg.endEdgeTracing()
 12734  	}
 12735  }
 12736  
 12737  // 469. \[23] Polygonal pens
 12738  
 12739  // tangle:pos ../../mf.web:9980:25:
 12740  
 12741  // The next few parts of the program deal with the additional complications
 12742  // associated with ``envelopes,'' leading up to an algorithm that fills a
 12743  // contour with respect to a pen whose boundary is a convex polygon. The
 12744  // mathematics underlying this algorithm is based on simple aspects of the
 12745  // theory of tracings developed by Leo Guibas, Lyle Ramshaw, and Jorge
 12746  // Stolfi [``A kinetic framework for computational geometry,''
 12747  // [\sl Proc.\ IEEE Symp.\ Foundations of Computer Science\/ \bf24] (1983),
 12748  // 100--111].
 12749  // \xref[Guibas, Leonidas Ioannis]
 12750  // \xref[Ramshaw, Lyle Harold]
 12751  // \xref[Stolfi, Jorge]
 12752  //
 12753  // If the vertices of the polygon are $w_0$, $w_1$, \dots, $w_[n-1]$, $w_n=w_0$,
 12754  // in counterclockwise order, the convexity condition requires that ``left
 12755  // turns'' are made at each vertex when a person proceeds from $w_0$ to
 12756  // $w_1$ to $\cdots$ to~$w_n$. The envelope is obtained if we offset a given
 12757  // curve $z(t)$ by $w_k$ when that curve is traveling in a direction
 12758  // $z'(t)$ lying between the directions $w_k-w_[k-1]$ and $w\k-w_k$.
 12759  // At times~$t$ when the curve direction $z'(t)$ increases past
 12760  // $w\k-w_k$, we temporarily stop plotting the offset curve and we insert
 12761  // a straight line from $z(t)+w_k$ to $z(t)+w\k$; notice that this straight
 12762  // line is tangent to the offset curve. Similarly, when the curve direction
 12763  // decreases past $w_k-w_[k-1]$, we stop plotting and insert a straight
 12764  // line from $z(t)+w_k$ to $z(t)+w_[k-1]$; the latter line is actually a
 12765  // ``retrograde'' step, which won't be part of the final envelope under
 12766  // \MF's assumptions. The result of this construction is a continuous path
 12767  // that consists of alternating curves and straight line segments. The
 12768  // segments are usually so short, in practice, that they blend with the
 12769  // curves; after all, it's possible to represent any digitized path as
 12770  // a sequence of digitized straight lines.
 12771  //
 12772  // The nicest feature of this approach to envelopes is that it blends
 12773  // perfectly with the octant subdivision process we have already developed.
 12774  // The envelope travels in the same direction as the curve itself, as we
 12775  // plot it, and we need merely be careful what offset is being added.
 12776  // Retrograde motion presents a problem, but we will see that there is
 12777  // a decent way to handle it.
 12778  
 12779  // 470.
 12780  
 12781  // tangle:pos ../../mf.web:10019:3:
 12782  
 12783  // We shall represent pens by maintaining eight lists of offsets,
 12784  // one for each octant direction. The offsets at the boundary points
 12785  // where a curve turns into a new octant will appear in the lists for
 12786  // both octants. This means that we can restrict consideration to
 12787  // segments of the original polygon whose directions aim in the first
 12788  // octant, as we have done in the simpler case when envelopes were not
 12789  // required.
 12790  //
 12791  // An example should help to clarify this situation: Consider the
 12792  // quadrilateral whose vertices are $w_0=(0,-1)$, $w_1=(3,-1)$,
 12793  // $w_2=(6,1)$, and $w_3=(1,2)$. A curve that travels in the first octant
 12794  // will be offset by $w_1$ or $w_2$, unless its slope drops to zero
 12795  // en route to the eighth octant; in the latter case we should switch to $w_0$ as
 12796  // we cross the octant boundary. Our list for the first octant will
 12797  // contain the three offsets $w_0$, $w_1$,~$w_2$. By convention we will
 12798  // duplicate a boundary offset if the angle between octants doesn't
 12799  // explicitly appear; in this case there is no explicit line of slope~1
 12800  // at the end of the list, so the full list is
 12801  // $$w_0\;w_1\;w_2\;w_2\;=\;(0,-1)\;(3,-1)\;(6,1)\;(6,1).$$
 12802  // With skewed coordinates $(u-v,v)$ instead of $(u,v)$ we obtain the list
 12803  // $$w_0\;w_1\;w_2\;w_2\;\mapsto\;(1,-1)\;(4,-1)\;(5,1)\;(5,1),$$
 12804  // which is what actually appears in the data structure. In the second
 12805  // octant there's only one offset; we list it twice (with coordinates
 12806  // interchanged, so as to make the second octant look like the first),
 12807  // and skew those coordinates, obtaining
 12808  // $$\tabskip\centering
 12809  // \halign to\hsize[$\hfil#\;\mapsto\;[]$\tabskip=0pt&
 12810  //   $#\hfil$&\quad in the #\hfil\tabskip\centering\cr
 12811  // w_2\;w_2&(-5,6)\;(-5,6)\cr
 12812  // \noalign[\vskip\belowdisplayskip
 12813  // \vbox[\noindent\strut as the list of transformed and skewed offsets to use
 12814  // when curves travel in the second octant. Similarly, we will have\strut]
 12815  // \vskip\abovedisplayskip]
 12816  // w_2\;w_2&(7,-6)\;(7,-6)&third;\cr
 12817  // w_2\;w_2\;w_3\;w_3&(-7,1)\;(-7,1)\;(-3,2)\;(-3,2)&fourth;\cr
 12818  // w_3\;w_3&(1,-2)\;(1,-2)&fifth;\cr
 12819  // w_3\;w_3\;w_0\;w_0&(-1,1)\;(-1,1)\;(1,0)\;(1,0)&sixth;\cr
 12820  // w_0\;w_0&(1,0)\;(1,0)&seventh;\cr
 12821  // w_0\;w_0&(-1,1)\;(-1,1)&eighth.\cr]$$
 12822  // Notice that $w_1$ is considered here to be internal to the first octant;
 12823  // it's not part of the eighth. We could equally well have taken $w_0$ out
 12824  // of the first octant list and put it into the eighth; then the first octant
 12825  // list would have been
 12826  // $$w_1\;w_1\;w_2\;w_2\;\mapsto\;(4,-1)\;(4,-1)\;(5,1)\;(5,1)$$
 12827  // and the eighth octant list would have been
 12828  // $$w_0\;w_0\;w_1\;\mapsto\;(-1,1)\;(-1,1)\;(2,1).$$
 12829  //
 12830  // Actually, there's one more complication: The order of offsets is reversed
 12831  // in even-numbered octants, because the transformation of coordinates has
 12832  // reversed counterclockwise and clockwise orientations in those octants.
 12833  // The offsets in the fourth octant, for example, are really $w_3$, $w_3$,
 12834  // $w_2$,~$w_2$, not $w_2$, $w_2$, $w_3$,~$w_3$.
 12835  
 12836  // 471.
 12837  
 12838  // tangle:pos ../../mf.web:10072:3:
 12839  
 12840  // In general, the list of offsets for an octant will have the form
 12841  // $$w_0\;\;w_1\;\;\ldots\;\;w_n\;\;w_[n+1]$$
 12842  // (if we renumber the subscripts in each list), where $w_0$ and $w_[n+1]$
 12843  // are offsets common to the neighboring lists. We'll often have $w_0=w_1$
 12844  // and/or $w_n=w_[n+1]$, but the other $w$'s will be distinct. Curves
 12845  // that travel between slope~0 and direction $w_2-w_1$ will use offset~$w_1$;
 12846  // curves that travel between directions $w_k-w_[k-1]$ and $w\k-w_k$ will
 12847  // use offset~$w_k$, for $1<k<n$; curves between direction $w_n-w_[n-1]$
 12848  // and slope~1 (actually slope~$\infty$ after skewing) will use offset~$w_n$.
 12849  // In even-numbered octants, the directions are actually $w_k-w\k$ instead
 12850  // of $w\k-w_k$, because the offsets have been listed in reverse order.
 12851  //
 12852  // Each offset $w_k$ is represented by skewed coordinates $(u_k-v_k,v_k)$,
 12853  // where $(u_k,v_k)$ is the representation of $w_k$ after it has been rotated
 12854  // into a first-octant disguise.
 12855  
 12856  // 472.
 12857  
 12858  // tangle:pos ../../mf.web:10088:3:
 12859  
 12860  // The top-level data structure of a pen polygon is a 10-word node containing
 12861  // a reference count followed by pointers to the eight offset lists, followed
 12862  // by an indication of the pen's range of values.
 12863  // \xref[reference counts]
 12864  //
 12865  // If |p|~points to such a node, and if the
 12866  // offset list for, say, the fourth octant has entries $w_0$, $w_1$, \dots,
 12867  // $w_n$,~$w_[n+1]$, then |info(p+fourth_octant)| will equal~$n$, and
 12868  // |link(p+fourth_octant)| will point to the offset node containing~$w_0$.
 12869  // Memory location |p+fourth_octant| is said to be the [\sl header\/] of
 12870  // the pen-offset list for the fourth octant. Since this is an even-numbered
 12871  // octant, $w_0$ is the offset that goes with the fifth octant, and
 12872  // $w_[n+1]$ goes with the third.
 12873  //
 12874  // The elements of the offset list themselves are doubly linked 3-word nodes,
 12875  // containing coordinates in their |x_coord| and |y_coord| fields.
 12876  // The two link fields are called |link| and |knil|; if |w|~points to
 12877  // the node for~$w_k$, then |link(w)| and |knil(w)| point respectively
 12878  // to the nodes for $w\k$ and~$w_[k-1]$. If |h| is the list header,
 12879  // |link(h)| points to the node for~$w_0$ and |knil(link(h))| to the
 12880  // node for~$w_[n+1]$.
 12881  //
 12882  // The tenth word of a pen header node contains the maximum absolute value of
 12883  // an $x$ or $y$ coordinate among all of the unskewed pen offsets.
 12884  //
 12885  // The |link| field of a pen header node should be |null| if and only if
 12886  // the pen is a single point.
 12887  
 12888  // 476.
 12889  
 12890  // tangle:pos ../../mf.web:10171:3:
 12891  
 12892  // Here's a trivial subroutine that inserts a copy of an offset
 12893  // on the |link| side of its clone in the doubly linked list.
 12894  func (prg *prg) dupOffset(w halfword) {
 12895  	var (
 12896  		r1 halfword // the new node
 12897  	)
 12898  	r1 = prg.getNode(coordNodeSize)
 12899  	*prg.mem[int32(r1)+1].int() = *prg.mem[int32(w)+1].int()
 12900  	*prg.mem[int32(r1)+2].int() = *prg.mem[int32(w)+2].int()
 12901  	*(*prg.mem[r1].hh()).rh() = *(*prg.mem[w].hh()).rh()
 12902  	*(*prg.mem[*(*prg.mem[w].hh()).rh()].hh()).lh() = r1
 12903  	*(*prg.mem[r1].hh()).lh() = w
 12904  	*(*prg.mem[w].hh()).rh() = r1
 12905  }
 12906  
 12907  // 477.
 12908  
 12909  // tangle:pos ../../mf.web:10183:3:
 12910  
 12911  // The following algorithm is somewhat more interesting: It converts a
 12912  // knot list for a cyclic path into a pen polygon, ignoring everything
 12913  // but the |x_coord|, |y_coord|, and |link| fields. If the given path
 12914  // vertices do not define a convex polygon, an error message is issued
 12915  // and the null pen is returned.
 12916  func (prg *prg) makePen(h halfword) (r halfword) {
 12917  	var (
 12918  		o, oo, k        smallNumber // octant numbers---old, new, and current
 12919  		p               halfword    // top-level node for the new pen
 12920  		q, r1, s, w, hh halfword    // for list manipulation
 12921  		n               int32       // offset counter
 12922  		dx, dy          scaled      // polygon direction
 12923  		mc              scaled      // the largest coordinate
 12924  	)
 12925  	q = h
 12926  	r1 = *(*prg.mem[q].hh()).rh()
 12927  	mc = abs(*prg.mem[int32(h)+1].int())
 12928  	if int32(q) == int32(r1) {
 12929  		hh = h
 12930  		*(*prg.mem[h].hh()).b1() = 0 // this trick is explained below
 12931  		if mc < abs(*prg.mem[int32(h)+2].int()) {
 12932  			mc = abs(*prg.mem[int32(h)+2].int())
 12933  		}
 12934  	} else {
 12935  		o = 0
 12936  		hh = uint16(memMin)
 12937  		for true {
 12938  			s = *(*prg.mem[r1].hh()).rh()
 12939  			if mc < abs(*prg.mem[int32(r1)+1].int()) {
 12940  				mc = abs(*prg.mem[int32(r1)+1].int())
 12941  			}
 12942  			if mc < abs(*prg.mem[int32(r1)+2].int()) {
 12943  				mc = abs(*prg.mem[int32(r1)+2].int())
 12944  			}
 12945  			dx = *prg.mem[int32(r1)+1].int() - *prg.mem[int32(q)+1].int()
 12946  			dy = *prg.mem[int32(r1)+2].int() - *prg.mem[int32(q)+2].int()
 12947  			if dx == 0 {
 12948  				if dy == 0 {
 12949  					goto notFound
 12950  				}
 12951  			} // double point
 12952  			if prg.abVsCd(dx, *prg.mem[int32(s)+2].int()-*prg.mem[int32(r1)+2].int(), dy, *prg.mem[int32(s)+1].int()-*prg.mem[int32(r1)+1].int()) < 0 {
 12953  				goto notFound
 12954  			} // right turn
 12955  
 12956  			// Determine the octant code for direction |(dx,dy)|
 12957  			if dx > 0 {
 12958  				prg.octant = byte(firstOctant)
 12959  			} else if dx == 0 {
 12960  				if dy > 0 {
 12961  					prg.octant = byte(firstOctant)
 12962  				} else {
 12963  					prg.octant = byte(firstOctant + negateX)
 12964  				}
 12965  			} else {
 12966  				dx = -dx
 12967  				prg.octant = byte(firstOctant + negateX)
 12968  			}
 12969  			if dy < 0 {
 12970  				dy = -dy
 12971  				prg.octant = byte(int32(prg.octant) + negateY)
 12972  			} else if dy == 0 {
 12973  				if int32(prg.octant) > firstOctant {
 12974  					prg.octant = byte(firstOctant + negateX + negateY)
 12975  				}
 12976  			}
 12977  			if dx < dy {
 12978  				prg.octant = byte(int32(prg.octant) + switchXAndY)
 12979  			}
 12980  			*(*prg.mem[q].hh()).b1() = prg.octant
 12981  			oo = prg.octantNumber[prg.octant-1]
 12982  			if int32(o) > int32(oo) {
 12983  				if int32(hh) != memMin {
 12984  					goto notFound
 12985  				} // $>360^\circ$
 12986  				hh = q
 12987  			}
 12988  			o = oo
 12989  			if int32(q) == int32(h) && int32(hh) != memMin {
 12990  				goto done
 12991  			}
 12992  			q = r1
 12993  			r1 = s
 12994  		}
 12995  
 12996  	done:
 12997  	}
 12998  	if mc >= 02000000000-0100000 {
 12999  		goto notFound
 13000  	}
 13001  	p = prg.getNode(penNodeSize)
 13002  	q = hh
 13003  	*prg.mem[int32(p)+9].int() = mc
 13004  	*(*prg.mem[p].hh()).lh() = uint16(memMin)
 13005  	if int32(*(*prg.mem[q].hh()).rh()) != int32(q) {
 13006  		*(*prg.mem[p].hh()).rh() = uint16(memMin + 1)
 13007  	}
 13008  	for ii := int32(1); ii <= 8; ii++ {
 13009  		k = smallNumber(ii)
 13010  		_ = k
 13011  		// Construct the offset list for the |k|th octant
 13012  		prg.octant = prg.octantCode[k-1]
 13013  		n = 0
 13014  		h = uint16(int32(p) + int32(prg.octant))
 13015  		for true {
 13016  			r1 = prg.getNode(coordNodeSize)
 13017  			prg.skew(*prg.mem[int32(q)+1].int(), *prg.mem[int32(q)+2].int(), prg.octant)
 13018  			*prg.mem[int32(r1)+1].int() = prg.curX
 13019  			*prg.mem[int32(r1)+2].int() = prg.curY
 13020  			if n == 0 {
 13021  				*(*prg.mem[h].hh()).rh() = r1
 13022  			} else if k&1 != 0 {
 13023  				*(*prg.mem[w].hh()).rh() = r1
 13024  				*(*prg.mem[r1].hh()).lh() = w
 13025  			} else {
 13026  				*(*prg.mem[w].hh()).lh() = r1
 13027  				*(*prg.mem[r1].hh()).rh() = w
 13028  			}
 13029  			w = r1
 13030  			if int32(*(*prg.mem[q].hh()).b1()) != int32(prg.octant) {
 13031  				goto done1
 13032  			}
 13033  			q = *(*prg.mem[q].hh()).rh()
 13034  			n = n + 1
 13035  		}
 13036  
 13037  	done1:
 13038  		r1 = *(*prg.mem[h].hh()).rh()
 13039  		if k&1 != 0 {
 13040  			*(*prg.mem[w].hh()).rh() = r1
 13041  			*(*prg.mem[r1].hh()).lh() = w
 13042  		} else {
 13043  			*(*prg.mem[w].hh()).lh() = r1
 13044  			*(*prg.mem[r1].hh()).rh() = w
 13045  			*(*prg.mem[h].hh()).rh() = w
 13046  			r1 = w
 13047  		}
 13048  		if *prg.mem[int32(r1)+2].int() != *prg.mem[int32(*(*prg.mem[r1].hh()).rh())+2].int() || n == 0 {
 13049  			prg.dupOffset(r1)
 13050  			n = n + 1
 13051  		}
 13052  		r1 = *(*prg.mem[r1].hh()).lh()
 13053  		if *prg.mem[int32(r1)+1].int() != *prg.mem[int32(*(*prg.mem[r1].hh()).lh())+1].int() {
 13054  			prg.dupOffset(r1)
 13055  		} else {
 13056  			n = n - 1
 13057  		}
 13058  		if n >= maxQuarterword {
 13059  			prg.overflow(strNumber( /* "pen polygon size" */ 579), maxQuarterword)
 13060  		}
 13061  		// \xref[METAFONT capacity exceeded pen polygon size][\quad pen polygon size]
 13062  		*(*prg.mem[h].hh()).lh() = uint16(n)
 13063  	}
 13064  
 13065  	goto found
 13066  
 13067  notFound:
 13068  	p = uint16(memMin + 3)
 13069  	// Complain about a bad pen path
 13070  	if mc >= 02000000000-0100000 {
 13071  		{
 13072  			if int32(prg.interaction) == errorStopMode {
 13073  			}
 13074  			prg.printNl(strNumber( /* "! " */ 261))
 13075  			prg.print( /* "Pen too large" */ 573) /* \xref[!\relax]  */
 13076  		}
 13077  		// \xref[Pen too large]
 13078  		{
 13079  			prg.helpPtr = 2
 13080  			prg.helpLine[1] = /* "The cycle you specified has a coordinate of 4095.5 or more." */ 574
 13081  			prg.helpLine[0] = /* "So I've replaced it by the trivial path `(0,0)..cycle'." */ 575
 13082  		}
 13083  
 13084  	} else {
 13085  		{
 13086  			if int32(prg.interaction) == errorStopMode {
 13087  			}
 13088  			prg.printNl(strNumber( /* "! " */ 261))
 13089  			prg.print( /* "Pen cycle must be convex" */ 576) /* \xref[!\relax]  */
 13090  		}
 13091  		// \xref[Pen cycle must be convex]
 13092  		{
 13093  			prg.helpPtr = 3
 13094  			prg.helpLine[2] = /* "The cycle you specified either has consecutive equal points" */ 577
 13095  			prg.helpLine[1] = /* "or turns right or turns through more than 360 degrees." */ 578
 13096  			prg.helpLine[0] = /* "So I've replaced it by the trivial path `(0,0)..cycle'." */ 575
 13097  		}
 13098  
 13099  	}
 13100  	prg.putGetError()
 13101  
 13102  found:
 13103  	if prg.internal[tracingPens-1] > 0 {
 13104  		prg.printPen(p, strNumber( /* " (newly created)" */ 572), true)
 13105  	}
 13106  	r = p
 13107  	return r
 13108  }
 13109  
 13110  // 484.
 13111  
 13112  // tangle:pos ../../mf.web:10332:3:
 13113  
 13114  // Conversely, |make_path| goes back from a pen to a cyclic path that
 13115  // might have generated it. The structure of this subroutine is essentially
 13116  // the same as |print_pen|.
 13117  // \4
 13118  // Declare the function called |trivial_knot|
 13119  func (prg *prg) trivialKnot(x, y scaled) (r halfword) {
 13120  	var (
 13121  		p halfword // a new knot for explicit coordinates |x| and |y|
 13122  	)
 13123  	p = prg.getNode(knotNodeSize)
 13124  	*(*prg.mem[p].hh()).b0() = byte(explicit)
 13125  	*(*prg.mem[p].hh()).b1() = byte(explicit)
 13126  
 13127  	*prg.mem[int32(p)+1].int() = x
 13128  	*prg.mem[int32(p)+3].int() = x
 13129  	*prg.mem[int32(p)+5].int() = x
 13130  
 13131  	*prg.mem[int32(p)+2].int() = y
 13132  	*prg.mem[int32(p)+4].int() = y
 13133  	*prg.mem[int32(p)+6].int() = y
 13134  
 13135  	r = p
 13136  	return r
 13137  }
 13138  
 13139  func (prg *prg) makePath(penHead halfword) (r halfword) {
 13140  	var (
 13141  		p                halfword // the most recently copied knot
 13142  		k/* 1..8 */ byte          // octant number
 13143  		h                halfword // offset list head
 13144  		m, n             int32    // offset indices
 13145  		w, ww            halfword // pointers that traverse the offset list
 13146  	)
 13147  	p = uint16(3000 - 1)
 13148  	for ii := int32(1); ii <= 8; ii++ {
 13149  		k = byte(ii)
 13150  		_ = k
 13151  		prg.octant = prg.octantCode[k-1]
 13152  		h = uint16(int32(penHead) + int32(prg.octant))
 13153  		n = int32(*(*prg.mem[h].hh()).lh())
 13154  		w = *(*prg.mem[h].hh()).rh()
 13155  		if !(k&1 != 0) {
 13156  			w = *(*prg.mem[w].hh()).lh()
 13157  		} // in even octants, start at $w_[n+1]$
 13158  		for ii := int32(1); ii <= n+1; ii++ {
 13159  			m = ii
 13160  			_ = m
 13161  			if k&1 != 0 {
 13162  				ww = *(*prg.mem[w].hh()).rh()
 13163  			} else {
 13164  				ww = *(*prg.mem[w].hh()).lh()
 13165  			}
 13166  			if *prg.mem[int32(ww)+1].int() != *prg.mem[int32(w)+1].int() || *prg.mem[int32(ww)+2].int() != *prg.mem[int32(w)+2].int() {
 13167  				prg.unskew(*prg.mem[int32(ww)+1].int(), *prg.mem[int32(ww)+2].int(), prg.octant)
 13168  				*(*prg.mem[p].hh()).rh() = prg.trivialKnot(prg.curX, prg.curY)
 13169  				p = *(*prg.mem[p].hh()).rh()
 13170  			}
 13171  			w = ww
 13172  		}
 13173  	}
 13174  	if int32(p) == 3000-1 {
 13175  		w = *(*prg.mem[int32(penHead)+firstOctant].hh()).rh()
 13176  		p = prg.trivialKnot(*prg.mem[int32(w)+1].int()+*prg.mem[int32(w)+2].int(), *prg.mem[int32(w)+2].int())
 13177  		*(*prg.mem[3000-1].hh()).rh() = p
 13178  	}
 13179  	*(*prg.mem[p].hh()).rh() = *(*prg.mem[3000-1].hh()).rh()
 13180  	r = *(*prg.mem[3000-1].hh()).rh()
 13181  	return r
 13182  }
 13183  
 13184  // 488.
 13185  
 13186  // tangle:pos ../../mf.web:10396:3:
 13187  
 13188  // The |find_offset| procedure sets |(cur_x,cur_y)| to the offset associated
 13189  // with a given direction~|(x,y)| and a given pen~|p|. If |x=y=0|, the
 13190  // result is |(0,0)|. If two different offsets apply, one of them is
 13191  // chosen arbitrarily.
 13192  func (prg *prg) findOffset(x, y scaled, p halfword) {
 13193  	var (
 13194  		octant/* firstOctant..sixthOctant */ byte          // octant code for |(x,y)|
 13195  		s/*  -1.. +1 */ int8                               // sign of the octant
 13196  		n                                         int32    // number of offsets remaining
 13197  		h, w, ww                                  halfword // list traversal registers
 13198  	)
 13199  	if x > 0 {
 13200  		octant = byte(firstOctant)
 13201  	} else if x == 0 {
 13202  		if y <= 0 {
 13203  			if y == 0 {
 13204  				prg.curX = 0
 13205  				prg.curY = 0
 13206  				goto exit
 13207  			} else {
 13208  				octant = byte(firstOctant + negateX)
 13209  			}
 13210  		} else {
 13211  			octant = byte(firstOctant)
 13212  		}
 13213  	} else {
 13214  		x = -x
 13215  		if y == 0 {
 13216  			octant = byte(firstOctant + negateX + negateY)
 13217  		} else {
 13218  			octant = byte(firstOctant + negateX)
 13219  		}
 13220  	}
 13221  	if y < 0 {
 13222  		octant = byte(int32(octant) + negateY)
 13223  		y = -y
 13224  	}
 13225  	if x >= y {
 13226  		x = x - y
 13227  	} else {
 13228  		octant = byte(int32(octant) + switchXAndY)
 13229  		x = y - x
 13230  		y = y - x
 13231  	}
 13232  	if prg.octantNumber[octant-1]&1 != 0 {
 13233  		s = int8(-1)
 13234  	} else {
 13235  		s = int8(+1)
 13236  	}
 13237  	h = uint16(int32(p) + int32(octant))
 13238  	w = *(*prg.mem[*(*prg.mem[h].hh()).rh()].hh()).rh()
 13239  	ww = *(*prg.mem[w].hh()).rh()
 13240  	n = int32(*(*prg.mem[h].hh()).lh())
 13241  	for n > 1 {
 13242  		if prg.abVsCd(x, *prg.mem[int32(ww)+2].int()-*prg.mem[int32(w)+2].int(), y, *prg.mem[int32(ww)+1].int()-*prg.mem[int32(w)+1].int()) != int32(s) {
 13243  			goto done
 13244  		}
 13245  		w = ww
 13246  		ww = *(*prg.mem[w].hh()).rh()
 13247  		n = n - 1
 13248  	}
 13249  
 13250  done:
 13251  	prg.unskew(*prg.mem[int32(w)+1].int(), *prg.mem[int32(w)+2].int(), octant)
 13252  
 13253  exit:
 13254  }
 13255  
 13256  // 490. \[24] Filling an envelope
 13257  
 13258  // tangle:pos ../../mf.web:10438:30:
 13259  
 13260  // We are about to reach the culmination of \MF's digital plotting routines:
 13261  // Almost all of the previous algorithms will be brought to bear on \MF's
 13262  // most difficult task, which is to fill the envelope of a given cyclic path
 13263  // with respect to a given pen polygon.
 13264  //
 13265  // But we still must complete some of the preparatory work before taking such
 13266  // a big plunge.
 13267  
 13268  // 491.
 13269  
 13270  // tangle:pos ../../mf.web:10447:3:
 13271  
 13272  // Given a pointer |c| to a nonempty list of cubics,
 13273  // and a pointer~|h| to the header information of a pen polygon segment,
 13274  // the |offset_prep| routine changes the list into cubics that are
 13275  // associated with particular pen offsets. Namely, the cubic between |p|
 13276  // and~|q| should be associated with the |k|th offset when |right_type(p)=k|.
 13277  //
 13278  // List |c| is actually part of a cycle spec, so it terminates at the
 13279  // first node whose |right_type| is |endpoint|. The cubics all have
 13280  // monotone-nondecreasing $x(t)$ and $y(t)$.
 13281  // \4
 13282  // Declare subroutines needed by |offset_prep|
 13283  func (prg *prg) splitForOffset(p halfword, t fraction) {
 13284  	var (
 13285  		q  halfword // the successor of |p|
 13286  		r1 halfword // the new node
 13287  	)
 13288  	q = *(*prg.mem[p].hh()).rh()
 13289  	prg.splitCubic(p, t, *prg.mem[int32(q)+1].int(), *prg.mem[int32(q)+2].int())
 13290  	r1 = *(*prg.mem[p].hh()).rh()
 13291  	if *prg.mem[int32(r1)+2].int() < *prg.mem[int32(p)+2].int() {
 13292  		*prg.mem[int32(r1)+2].int() = *prg.mem[int32(p)+2].int()
 13293  	} else if *prg.mem[int32(r1)+2].int() > *prg.mem[int32(q)+2].int() {
 13294  		*prg.mem[int32(r1)+2].int() = *prg.mem[int32(q)+2].int()
 13295  	}
 13296  	if *prg.mem[int32(r1)+1].int() < *prg.mem[int32(p)+1].int() {
 13297  		*prg.mem[int32(r1)+1].int() = *prg.mem[int32(p)+1].int()
 13298  	} else if *prg.mem[int32(r1)+1].int() > *prg.mem[int32(q)+1].int() {
 13299  		*prg.mem[int32(r1)+1].int() = *prg.mem[int32(q)+1].int()
 13300  	}
 13301  }
 13302  
 13303  func (prg *prg) finOffsetPrep(p halfword, k halfword, w halfword,
 13304  	x0, x1, x2, y0, y1, y2 int32, rising bool, n int32) {
 13305  	var (
 13306  		ww         halfword // for list manipulation
 13307  		du, dv     scaled   // for slope calculation
 13308  		t0, t1, t2 int32    // test coefficients
 13309  		t          fraction // place where the derivative passes a critical slope
 13310  		s          fraction // slope or reciprocal slope
 13311  		v          int32    // intermediate value for updating |x0..y2|
 13312  	)
 13313  	for true {
 13314  		*(*prg.mem[p].hh()).b1() = byte(k)
 13315  		if rising {
 13316  			if int32(k) == n {
 13317  				goto exit
 13318  			} else {
 13319  				ww = *(*prg.mem[w].hh()).rh()
 13320  			}
 13321  		} else if int32(k) == 1 {
 13322  			goto exit
 13323  		} else {
 13324  			ww = *(*prg.mem[w].hh()).lh()
 13325  		} // a pointer to $w_[k-1]$
 13326  
 13327  		// Compute test coefficients |(t0,t1,t2)| for $s(t)$ versus $s_k$ or $s_[k-1]$
 13328  		du = *prg.mem[int32(ww)+1].int() - *prg.mem[int32(w)+1].int()
 13329  		dv = *prg.mem[int32(ww)+2].int() - *prg.mem[int32(w)+2].int()
 13330  		if abs(du) >= abs(dv) {
 13331  			s = prg.makeFraction(dv, du)
 13332  			t0 = prg.takeFraction(x0, s) - y0
 13333  			t1 = prg.takeFraction(x1, s) - y1
 13334  			t2 = prg.takeFraction(x2, s) - y2
 13335  		} else {
 13336  			s = prg.makeFraction(du, dv)
 13337  			t0 = x0 - prg.takeFraction(y0, s)
 13338  			t1 = x1 - prg.takeFraction(y1, s)
 13339  			t2 = x2 - prg.takeFraction(y2, s)
 13340  		}
 13341  		t = prg.crossingPoint(t0, t1, t2)
 13342  		if t >= 02000000000 {
 13343  			goto exit
 13344  		}
 13345  
 13346  		// Split the cubic at $t$, and split off another cubic if the derivative crosses back
 13347  		{
 13348  			prg.splitForOffset(p, t)
 13349  			*(*prg.mem[p].hh()).b1() = byte(k)
 13350  			p = *(*prg.mem[p].hh()).rh()
 13351  
 13352  			v = x0 - prg.takeFraction(x0-x1, t)
 13353  			x1 = x1 - prg.takeFraction(x1-x2, t)
 13354  			x0 = v - prg.takeFraction(v-x1, t)
 13355  
 13356  			v = y0 - prg.takeFraction(y0-y1, t)
 13357  			y1 = y1 - prg.takeFraction(y1-y2, t)
 13358  			y0 = v - prg.takeFraction(v-y1, t)
 13359  
 13360  			t1 = t1 - prg.takeFraction(t1-t2, t)
 13361  			if t1 > 0 {
 13362  				t1 = 0
 13363  			} // without rounding error, |t1| would be |<=0|
 13364  			t = prg.crossingPoint(0, -t1, -t2)
 13365  			if t < 02000000000 {
 13366  				prg.splitForOffset(p, t)
 13367  				*(*prg.mem[*(*prg.mem[p].hh()).rh()].hh()).b1() = byte(k)
 13368  
 13369  				v = x1 - prg.takeFraction(x1-x2, t)
 13370  				x1 = x0 - prg.takeFraction(x0-x1, t)
 13371  				x2 = x1 - prg.takeFraction(x1-v, t)
 13372  
 13373  				v = y1 - prg.takeFraction(y1-y2, t)
 13374  				y1 = y0 - prg.takeFraction(y0-y1, t)
 13375  				y2 = y1 - prg.takeFraction(y1-v, t)
 13376  			}
 13377  		}
 13378  		if rising {
 13379  			k = uint16(int32(k) + 1)
 13380  		} else {
 13381  			k = uint16(int32(k) - 1)
 13382  		}
 13383  		w = ww
 13384  	}
 13385  
 13386  exit:
 13387  }
 13388  
 13389  func (prg *prg) offsetPrep(c, h halfword) {
 13390  	var (
 13391  		n                halfword // the number of pen offsets
 13392  		p, q, r1, lh, ww halfword // for list manipulation
 13393  		k                halfword // the current offset index
 13394  		w                halfword // a pointer to offset $w_k$
 13395  
 13396  		// Other local variables for |offset_prep|
 13397  		x0, x1, x2, y0, y1, y2       int32    // representatives of derivatives
 13398  		t0, t1, t2                   int32    // coefficients of polynomial for slope testing
 13399  		du, dv, dx, dy               int32    // for slopes of the pen and the curve
 13400  		maxCoef                      int32    // used while scaling
 13401  		x0a, x1a, x2a, y0a, y1a, y2a int32    // intermediate values
 13402  		t                            fraction // where the derivative passes through zero
 13403  		s                            fraction // slope or reciprocal slope
 13404  	)
 13405  	p = c
 13406  	n = *(*prg.mem[h].hh()).lh()
 13407  	lh = *(*prg.mem[h].hh()).rh() // now |lh| points to $w_0$
 13408  	for int32(*(*prg.mem[p].hh()).b1()) != endpoint {
 13409  		q = *(*prg.mem[p].hh()).rh()
 13410  
 13411  		// Split the cubic between |p| and |q|, if necessary, into cubics associated with single offsets, after which |q| should point to the end of the final such cubic
 13412  		if int32(n) <= 1 {
 13413  			*(*prg.mem[p].hh()).b1() = 1
 13414  		} else {
 13415  			x0 = *prg.mem[int32(p)+5].int() - *prg.mem[int32(p)+1].int() // should be |>=0|
 13416  			x2 = *prg.mem[int32(q)+1].int() - *prg.mem[int32(q)+3].int() // likewise
 13417  			x1 = *prg.mem[int32(q)+3].int() - *prg.mem[int32(p)+5].int() // but this might be negative
 13418  			y0 = *prg.mem[int32(p)+6].int() - *prg.mem[int32(p)+2].int()
 13419  			y2 = *prg.mem[int32(q)+2].int() - *prg.mem[int32(q)+4].int()
 13420  			y1 = *prg.mem[int32(q)+4].int() - *prg.mem[int32(p)+6].int()
 13421  			maxCoef = abs(x0) // we take |abs| just to make sure
 13422  			if abs(x1) > maxCoef {
 13423  				maxCoef = abs(x1)
 13424  			}
 13425  			if abs(x2) > maxCoef {
 13426  				maxCoef = abs(x2)
 13427  			}
 13428  			if abs(y0) > maxCoef {
 13429  				maxCoef = abs(y0)
 13430  			}
 13431  			if abs(y1) > maxCoef {
 13432  				maxCoef = abs(y1)
 13433  			}
 13434  			if abs(y2) > maxCoef {
 13435  				maxCoef = abs(y2)
 13436  			}
 13437  			if maxCoef == 0 {
 13438  				goto notFound
 13439  			}
 13440  			for maxCoef < 01000000000 {
 13441  				maxCoef = maxCoef + maxCoef
 13442  				x0 = x0 + x0
 13443  				x1 = x1 + x1
 13444  				x2 = x2 + x2
 13445  				y0 = y0 + y0
 13446  				y1 = y1 + y1
 13447  				y2 = y2 + y2
 13448  			}
 13449  
 13450  			// Find the initial slope, |dy/dx|
 13451  			dx = x0
 13452  			dy = y0
 13453  			if dx == 0 {
 13454  				if dy == 0 {
 13455  					dx = x1
 13456  					dy = y1
 13457  					if dx == 0 {
 13458  						if dy == 0 {
 13459  							dx = x2
 13460  							dy = y2
 13461  						}
 13462  					}
 13463  				}
 13464  			}
 13465  			if dx == 0 {
 13466  				prg.finOffsetPrep(p, n, *(*prg.mem[*(*prg.mem[lh].hh()).lh()].hh()).lh(), -x0, -x1, -x2, -y0, -y1, -y2, false, int32(n))
 13467  			} else {
 13468  				k = 1
 13469  				w = *(*prg.mem[lh].hh()).rh()
 13470  				for true {
 13471  					if int32(k) == int32(n) {
 13472  						goto done
 13473  					}
 13474  					ww = *(*prg.mem[w].hh()).rh()
 13475  					if prg.abVsCd(dy, abs(*prg.mem[int32(ww)+1].int()-*prg.mem[int32(w)+1].int()), dx, abs(*prg.mem[int32(ww)+2].int()-*prg.mem[int32(w)+2].int())) >= 0 {
 13476  						k = uint16(int32(k) + 1)
 13477  						w = ww
 13478  					} else {
 13479  						goto done
 13480  					}
 13481  				}
 13482  
 13483  			done:
 13484  				;
 13485  
 13486  				// Complete the offset splitting process
 13487  				if int32(k) == 1 {
 13488  					t = 02000000000 + 1
 13489  				} else {
 13490  					ww = *(*prg.mem[w].hh()).lh()
 13491  					// Compute test coeff...
 13492  					du = *prg.mem[int32(ww)+1].int() - *prg.mem[int32(w)+1].int()
 13493  					dv = *prg.mem[int32(ww)+2].int() - *prg.mem[int32(w)+2].int()
 13494  					if abs(du) >= abs(dv) {
 13495  						s = prg.makeFraction(dv, du)
 13496  						t0 = prg.takeFraction(x0, s) - y0
 13497  						t1 = prg.takeFraction(x1, s) - y1
 13498  						t2 = prg.takeFraction(x2, s) - y2
 13499  					} else {
 13500  						s = prg.makeFraction(du, dv)
 13501  						t0 = x0 - prg.takeFraction(y0, s)
 13502  						t1 = x1 - prg.takeFraction(y1, s)
 13503  						t2 = x2 - prg.takeFraction(y2, s)
 13504  					}
 13505  					t = prg.crossingPoint(-t0, -t1, -t2)
 13506  				}
 13507  				if t >= 02000000000 {
 13508  					prg.finOffsetPrep(p, k, w, x0, x1, x2, y0, y1, y2, true, int32(n))
 13509  				} else {
 13510  					prg.splitForOffset(p, t)
 13511  					r1 = *(*prg.mem[p].hh()).rh()
 13512  
 13513  					x1a = x0 - prg.takeFraction(x0-x1, t)
 13514  					x1 = x1 - prg.takeFraction(x1-x2, t)
 13515  					x2a = x1a - prg.takeFraction(x1a-x1, t)
 13516  
 13517  					y1a = y0 - prg.takeFraction(y0-y1, t)
 13518  					y1 = y1 - prg.takeFraction(y1-y2, t)
 13519  					y2a = y1a - prg.takeFraction(y1a-y1, t)
 13520  
 13521  					prg.finOffsetPrep(p, k, w, x0, x1a, x2a, y0, y1a, y2a, true, int32(n))
 13522  					x0 = x2a
 13523  					y0 = y2a
 13524  					t1 = t1 - prg.takeFraction(t1-t2, t)
 13525  					if t1 < 0 {
 13526  						t1 = 0
 13527  					}
 13528  					t = prg.crossingPoint(0, t1, t2)
 13529  					if t < 02000000000 {
 13530  						prg.splitForOffset(r1, t)
 13531  
 13532  						x1a = x1 - prg.takeFraction(x1-x2, t)
 13533  						x1 = x0 - prg.takeFraction(x0-x1, t)
 13534  						x0a = x1 - prg.takeFraction(x1-x1a, t)
 13535  
 13536  						y1a = y1 - prg.takeFraction(y1-y2, t)
 13537  						y1 = y0 - prg.takeFraction(y0-y1, t)
 13538  						y0a = y1 - prg.takeFraction(y1-y1a, t)
 13539  
 13540  						prg.finOffsetPrep(*(*prg.mem[r1].hh()).rh(), k, w, x0a, x1a, x2, y0a, y1a, y2, true, int32(n))
 13541  						x2 = x0a
 13542  						y2 = y0a
 13543  					}
 13544  					prg.finOffsetPrep(r1, halfword(int32(k)-1), ww, -x0, -x1, -x2, -y0, -y1, -y2, false, int32(n))
 13545  				}
 13546  			}
 13547  
 13548  		notFound:
 13549  		}
 13550  
 13551  		// Advance |p| to node |q|, removing any “dead” cubics that might have been introduced by the splitting process
 13552  		for {
 13553  			r1 = *(*prg.mem[p].hh()).rh()
 13554  			if *prg.mem[int32(p)+1].int() == *prg.mem[int32(p)+5].int() {
 13555  				if *prg.mem[int32(p)+2].int() == *prg.mem[int32(p)+6].int() {
 13556  					if *prg.mem[int32(p)+1].int() == *prg.mem[int32(r1)+3].int() {
 13557  						if *prg.mem[int32(p)+2].int() == *prg.mem[int32(r1)+4].int() {
 13558  							if *prg.mem[int32(p)+1].int() == *prg.mem[int32(r1)+1].int() {
 13559  								if *prg.mem[int32(p)+2].int() == *prg.mem[int32(r1)+2].int() {
 13560  									prg.removeCubic(p)
 13561  									if int32(r1) == int32(q) {
 13562  										q = p
 13563  									}
 13564  									r1 = p
 13565  								}
 13566  							}
 13567  						}
 13568  					}
 13569  				}
 13570  			}
 13571  			p = r1
 13572  			if int32(p) == int32(q) {
 13573  				break
 13574  			}
 13575  		}
 13576  	}
 13577  }
 13578  
 13579  // 500.
 13580  
 13581  // tangle:pos ../../mf.web:10652:3:
 13582  
 13583  // Now we must consider the general problem of |offset_prep|, when
 13584  // nothing is known about a given cubic. We start by finding its
 13585  // slope $s(0)$ in the vicinity of |t=0|.
 13586  //
 13587  // If $z'(t)=0$, the given cubic is numerically unstable, since the
 13588  // slope direction is probably being influenced primarily by rounding
 13589  // errors. A user who specifies such cuspy curves should expect to generate
 13590  // rather wild results. The present code tries its best to believe the
 13591  // existing data, as if no rounding errors were present.
 13592  
 13593  // 506.
 13594  
 13595  // tangle:pos ../../mf.web:10725:3:
 13596  
 13597  // OK, it's time now for the biggie. The |fill_envelope| routine generalizes
 13598  // |fill_spec| to polygonal envelopes. Its outer structure is essentially the
 13599  // same as before, except that octants with no cubics do contribute to
 13600  // the envelope.
 13601  // \4
 13602  // Declare the procedure called |skew_line_edges|
 13603  func (prg *prg) skewLineEdges(p, w, ww halfword) {
 13604  	var (
 13605  		x0, y0, x1, y1 scaled // from and to
 13606  	)
 13607  	if *prg.mem[int32(w)+1].int() != *prg.mem[int32(ww)+1].int() || *prg.mem[int32(w)+2].int() != *prg.mem[int32(ww)+2].int() {
 13608  		x0 = *prg.mem[int32(p)+1].int() + *prg.mem[int32(w)+1].int()
 13609  		y0 = *prg.mem[int32(p)+2].int() + *prg.mem[int32(w)+2].int()
 13610  
 13611  		x1 = *prg.mem[int32(p)+1].int() + *prg.mem[int32(ww)+1].int()
 13612  		y1 = *prg.mem[int32(p)+2].int() + *prg.mem[int32(ww)+2].int()
 13613  
 13614  		prg.unskew(x0, y0, prg.octant) // unskew and unrotate the coordinates
 13615  		x0 = prg.curX
 13616  		y0 = prg.curY
 13617  
 13618  		prg.unskew(x1, y1, prg.octant)
 13619  
 13620  		if prg.internal[tracingEdges-1] > 0200000 {
 13621  			prg.printNl(strNumber( /* "@ retrograde line from " */ 584))
 13622  			// \xref[]]]\AT!_retro_][\.[\AT! retrograde line...]]
 13623  			// \xref[retrograde line...]
 13624  			prg.printTwo(x0, y0)
 13625  			prg.print( /* " to " */ 583)
 13626  			prg.printTwo(prg.curX, prg.curY)
 13627  			prg.printNl(strNumber( /* "" */ 285))
 13628  		}
 13629  
 13630  		prg.lineEdges(x0, y0, prg.curX, prg.curY) // then draw a straight line
 13631  	}
 13632  }
 13633  
 13634  // \4
 13635  // Declare the procedure called |dual_moves|
 13636  func (prg *prg) dualMoves(h, p, q halfword) {
 13637  	var (
 13638  		r1, s halfword // for list traversal
 13639  
 13640  		// Other local variables for |fill_envelope|
 13641  		m, n                                         int32    // current lattice position
 13642  		mm0, mm1                                     int32    // skewed equivalents of |m0| and |m1|
 13643  		k                                            int32    // current offset number
 13644  		w, ww                                        halfword // pointers to the current offset and its neighbor
 13645  		smoothBot, smoothTop/* 0..moveSize */ uint16          // boundaries of smoothing
 13646  		xx, yy, xp, yp, delx, dely, tx, ty           scaled
 13647  	// registers for coordinate calculations
 13648  	)
 13649  	k = int32(*(*prg.mem[h].hh()).lh()) + 1
 13650  	ww = *(*prg.mem[h].hh()).rh()
 13651  	w = *(*prg.mem[ww].hh()).lh()
 13652  
 13653  	mm0 = prg.floorUnscaled(*prg.mem[int32(p)+1].int() + *prg.mem[int32(w)+1].int() - int32(prg.xyCorr[prg.octant-1]))
 13654  	mm1 = prg.floorUnscaled(*prg.mem[int32(q)+1].int() + *prg.mem[int32(ww)+1].int() - int32(prg.xyCorr[prg.octant-1]))
 13655  	for ii := int32(1); ii <= prg.n1-prg.n0+1; ii++ {
 13656  		n = ii
 13657  		_ = n
 13658  		prg.envMove[n] = mm1
 13659  	}
 13660  	prg.envMove[0] = mm0
 13661  	prg.movePtr = 0
 13662  	m = mm0
 13663  	r1 = p // recall that |right_type(q)=endpoint=0| now
 13664  	for true {
 13665  		if int32(r1) == int32(q) {
 13666  			smoothTop = prg.movePtr
 13667  		}
 13668  		for int32(*(*prg.mem[r1].hh()).b1()) != k {
 13669  
 13670  			// Insert a line segment dually to approach the correct offset
 13671  			xx = *prg.mem[int32(r1)+1].int() + *prg.mem[int32(w)+1].int()
 13672  			yy = *prg.mem[int32(r1)+2].int() + *prg.mem[int32(w)+2].int() + 0100000
 13673  			if prg.internal[tracingEdges-1] > 0200000 {
 13674  				prg.printNl(strNumber( /* "@ transition line " */ 585))
 13675  				prg.printInt(k)
 13676  				prg.print( /* ", from " */ 586)
 13677  				// \xref[]]]\AT!_trans_][\.[\AT! transition line...]]
 13678  				// \xref[transition line...]
 13679  				prg.unskew(xx, yy-0100000, prg.octant)
 13680  				prg.printTwo(prg.curX, prg.curY)
 13681  			}
 13682  
 13683  			if int32(*(*prg.mem[r1].hh()).b1()) < k {
 13684  				k = k - 1
 13685  				w = *(*prg.mem[w].hh()).lh()
 13686  				xp = *prg.mem[int32(r1)+1].int() + *prg.mem[int32(w)+1].int()
 13687  				yp = *prg.mem[int32(r1)+2].int() + *prg.mem[int32(w)+2].int() + 0100000
 13688  				if yp != yy {
 13689  					ty = prg.floorScaled(yy - int32(prg.yCorr[prg.octant-1]))
 13690  					dely = yp - yy
 13691  					yy = yy - ty
 13692  					ty = yp - int32(prg.yCorr[prg.octant-1]) - ty
 13693  					if ty >= 0200000 {
 13694  						delx = xp - xx
 13695  						yy = 0200000 - yy
 13696  						for true {
 13697  							if m < prg.envMove[prg.movePtr] {
 13698  								prg.envMove[prg.movePtr] = m
 13699  							}
 13700  							tx = prg.takeFraction(delx, prg.makeFraction(yy, dely))
 13701  							if prg.abVsCd(tx, dely, delx, yy)+int32(prg.xyCorr[prg.octant-1]) > 0 {
 13702  								tx = tx - 1
 13703  							}
 13704  							m = prg.floorUnscaled(xx + tx)
 13705  							ty = ty - 0200000
 13706  							prg.movePtr = uint16(int32(prg.movePtr) + 1)
 13707  							if ty < 0200000 {
 13708  								goto done1
 13709  							}
 13710  							yy = yy + 0200000
 13711  						}
 13712  
 13713  					done1:
 13714  						if m < prg.envMove[prg.movePtr] {
 13715  							prg.envMove[prg.movePtr] = m
 13716  						}
 13717  					}
 13718  				}
 13719  			} else {
 13720  				k = k + 1
 13721  				w = *(*prg.mem[w].hh()).rh()
 13722  				xp = *prg.mem[int32(r1)+1].int() + *prg.mem[int32(w)+1].int()
 13723  				yp = *prg.mem[int32(r1)+2].int() + *prg.mem[int32(w)+2].int() + 0100000
 13724  			}
 13725  			if prg.internal[tracingEdges-1] > 0200000 {
 13726  				prg.print( /* " to " */ 583)
 13727  				prg.unskew(xp, yp-0100000, prg.octant)
 13728  				prg.printTwo(prg.curX, prg.curY)
 13729  				prg.printNl(strNumber( /* "" */ 285))
 13730  			}
 13731  
 13732  			m = prg.floorUnscaled(xp - int32(prg.xyCorr[prg.octant-1]))
 13733  			prg.movePtr = uint16(prg.floorUnscaled(yp-int32(prg.yCorr[prg.octant-1])) - prg.n0)
 13734  			if m < prg.envMove[prg.movePtr] {
 13735  				prg.envMove[prg.movePtr] = m
 13736  			}
 13737  		}
 13738  		if int32(r1) == int32(p) {
 13739  			smoothBot = prg.movePtr
 13740  		}
 13741  		if int32(r1) == int32(q) {
 13742  			goto done
 13743  		}
 13744  		prg.move[prg.movePtr] = 1
 13745  		n = int32(prg.movePtr)
 13746  		s = *(*prg.mem[r1].hh()).rh()
 13747  
 13748  		prg.makeMoves(*prg.mem[int32(r1)+1].int()+*prg.mem[int32(w)+1].int(), *prg.mem[int32(r1)+5].int()+*prg.mem[int32(w)+1].int(), *prg.mem[int32(s)+3].int()+*prg.mem[int32(w)+1].int(), *prg.mem[int32(s)+1].int()+*prg.mem[int32(w)+1].int(), *prg.mem[int32(r1)+2].int()+*prg.mem[int32(w)+2].int()+0100000, *prg.mem[int32(r1)+6].int()+*prg.mem[int32(w)+2].int()+0100000, *prg.mem[int32(s)+4].int()+*prg.mem[int32(w)+2].int()+0100000, *prg.mem[int32(s)+2].int()+*prg.mem[int32(w)+2].int()+0100000, prg.xyCorr[prg.octant-1], prg.yCorr[prg.octant-1])
 13749  
 13750  		// Transfer moves dually from the |move| array to |env_move|
 13751  		for {
 13752  			if m < prg.envMove[n] {
 13753  				prg.envMove[n] = m
 13754  			}
 13755  			m = m + prg.move[n] - 1
 13756  			n = n + 1
 13757  			if n > int32(prg.movePtr) {
 13758  				break
 13759  			}
 13760  		}
 13761  		r1 = s
 13762  	}
 13763  
 13764  done:
 13765  	prg.move[0] = int32(prg.d0) + prg.envMove[1] - mm0
 13766  	for ii := int32(1); ii <= int32(prg.movePtr); ii++ {
 13767  		n = ii
 13768  		_ = n
 13769  		prg.move[n] = prg.envMove[n+1] - prg.envMove[n] + 1
 13770  	}
 13771  	prg.move[prg.movePtr] = prg.move[prg.movePtr] - int32(prg.d1)
 13772  	if prg.internal[smoothing-1] > 0 {
 13773  		prg.smoothMoves(int32(smoothBot), int32(smoothTop))
 13774  	}
 13775  	prg.moveToEdges(prg.m0, prg.n0, prg.m1, prg.n1)
 13776  	if *prg.mem[int32(q)+6].int() == diagonal {
 13777  		w = *(*prg.mem[h].hh()).rh()
 13778  		prg.skewLineEdges(q, w, *(*prg.mem[w].hh()).lh())
 13779  	}
 13780  }
 13781  
 13782  func (prg *prg) fillEnvelope(specHead halfword) {
 13783  	var (
 13784  		p, q, r1, s halfword // for list traversal
 13785  		h           halfword // head of pen offset list for current octant
 13786  		www         halfword // a pen offset of temporary interest
 13787  
 13788  		// Other local variables for |fill_envelope|
 13789  		m, n                                         int32    // current lattice position
 13790  		mm0, mm1                                     int32    // skewed equivalents of |m0| and |m1|
 13791  		k                                            int32    // current offset number
 13792  		w, ww                                        halfword // pointers to the current offset and its neighbor
 13793  		smoothBot, smoothTop/* 0..moveSize */ uint16          // boundaries of smoothing
 13794  		xx, yy, xp, yp, delx, dely, tx, ty           scaled
 13795  	// registers for coordinate calculations
 13796  	)
 13797  	if prg.internal[tracingEdges-1] > 0 {
 13798  		prg.beginEdgeTracing()
 13799  	}
 13800  	p = specHead // we assume that |left_type(spec_head)=endpoint|
 13801  	for {
 13802  		prg.octant = byte(*prg.mem[int32(p)+3].int())
 13803  		h = uint16(int32(prg.curPen) + int32(prg.octant))
 13804  
 13805  		// Set variable |q| to the node at the end of the current octant
 13806  		q = p
 13807  		for int32(*(*prg.mem[q].hh()).b1()) != endpoint {
 13808  			q = *(*prg.mem[q].hh()).rh()
 13809  		}
 13810  
 13811  		// Determine the envelope's starting and ending lattice points |(m0,n0)| and |(m1,n1)|
 13812  		w = *(*prg.mem[h].hh()).rh()
 13813  		if *prg.mem[int32(p)+4].int() == diagonal {
 13814  			w = *(*prg.mem[w].hh()).lh()
 13815  		}
 13816  		if prg.internal[tracingEdges-1] > 0200000 {
 13817  			prg.printNl(strNumber( /* "@ Octant " */ 580))
 13818  			prg.print(int32(prg.octantDir[prg.octant-1]))
 13819  			// \xref[]]]\AT!_Octant][\.[\AT! Octant...]]
 13820  			prg.print( /* " (" */ 558)
 13821  			prg.printInt(int32(*(*prg.mem[h].hh()).lh()))
 13822  			prg.print( /* " offset" */ 581)
 13823  			if int32(*(*prg.mem[h].hh()).lh()) != 1 {
 13824  				prg.printChar(asciiCode('s'))
 13825  			}
 13826  			prg.print( /* "), from " */ 582)
 13827  			prg.unskew(*prg.mem[int32(p)+1].int()+*prg.mem[int32(w)+1].int(), *prg.mem[int32(p)+2].int()+*prg.mem[int32(w)+2].int(), prg.octant)
 13828  			prg.printTwo(prg.curX, prg.curY)
 13829  
 13830  			ww = *(*prg.mem[h].hh()).rh()
 13831  			if *prg.mem[int32(q)+6].int() == diagonal {
 13832  				ww = *(*prg.mem[ww].hh()).lh()
 13833  			}
 13834  			prg.print( /* " to " */ 583)
 13835  			prg.unskew(*prg.mem[int32(q)+1].int()+*prg.mem[int32(ww)+1].int(), *prg.mem[int32(q)+2].int()+*prg.mem[int32(ww)+2].int(), prg.octant)
 13836  			prg.printTwo(prg.curX, prg.curY)
 13837  		}
 13838  
 13839  		ww = *(*prg.mem[h].hh()).rh()
 13840  		www = ww // starting and ending offsets
 13841  		if prg.octantNumber[prg.octant-1]&1 != 0 {
 13842  			www = *(*prg.mem[www].hh()).lh()
 13843  		} else {
 13844  			ww = *(*prg.mem[ww].hh()).lh()
 13845  		}
 13846  		if int32(w) != int32(ww) {
 13847  			prg.skewLineEdges(p, w, ww)
 13848  		}
 13849  		prg.endRound(*prg.mem[int32(p)+1].int()+*prg.mem[int32(ww)+1].int(), *prg.mem[int32(p)+2].int()+*prg.mem[int32(ww)+2].int())
 13850  		prg.m0 = prg.m1
 13851  		prg.n0 = prg.n1
 13852  		prg.d0 = prg.d1
 13853  
 13854  		prg.endRound(*prg.mem[int32(q)+1].int()+*prg.mem[int32(www)+1].int(), *prg.mem[int32(q)+2].int()+*prg.mem[int32(www)+2].int())
 13855  		if prg.n1-prg.n0 >= moveSize {
 13856  			prg.overflow(strNumber( /* "move table size" */ 540), moveSize)
 13857  		}
 13858  		prg.offsetPrep(p, h) // this may clobber node~|q|, if it becomes ``dead''
 13859  
 13860  		// Set variable |q| to the node at the end of the current octant
 13861  		q = p
 13862  		for int32(*(*prg.mem[q].hh()).b1()) != endpoint {
 13863  			q = *(*prg.mem[q].hh()).rh()
 13864  		}
 13865  
 13866  		// Make the envelope moves for the current octant and insert them in the pixel data
 13867  		if prg.octantNumber[prg.octant-1]&1 != 0 {
 13868  			k = 0
 13869  			w = *(*prg.mem[h].hh()).rh()
 13870  			ww = *(*prg.mem[w].hh()).lh()
 13871  			mm0 = prg.floorUnscaled(*prg.mem[int32(p)+1].int() + *prg.mem[int32(w)+1].int() - int32(prg.xyCorr[prg.octant-1]))
 13872  			mm1 = prg.floorUnscaled(*prg.mem[int32(q)+1].int() + *prg.mem[int32(ww)+1].int() - int32(prg.xyCorr[prg.octant-1]))
 13873  			for ii := int32(0); ii <= prg.n1-prg.n0-1; ii++ {
 13874  				n = ii
 13875  				_ = n
 13876  				prg.envMove[n] = mm0
 13877  			}
 13878  			prg.envMove[prg.n1-prg.n0] = mm1
 13879  			prg.movePtr = 0
 13880  			m = mm0
 13881  			r1 = p
 13882  			*(*prg.mem[q].hh()).b1() = byte(int32(*(*prg.mem[h].hh()).lh()) + 1)
 13883  			for true {
 13884  				if int32(r1) == int32(q) {
 13885  					smoothTop = prg.movePtr
 13886  				}
 13887  				for int32(*(*prg.mem[r1].hh()).b1()) != k {
 13888  
 13889  					// Insert a line segment to approach the correct offset
 13890  					xx = *prg.mem[int32(r1)+1].int() + *prg.mem[int32(w)+1].int()
 13891  					yy = *prg.mem[int32(r1)+2].int() + *prg.mem[int32(w)+2].int() + 0100000
 13892  					if prg.internal[tracingEdges-1] > 0200000 {
 13893  						prg.printNl(strNumber( /* "@ transition line " */ 585))
 13894  						prg.printInt(k)
 13895  						prg.print( /* ", from " */ 586)
 13896  						// \xref[]]]\AT!_trans_][\.[\AT! transition line...]]
 13897  						// \xref[transition line...]
 13898  						prg.unskew(xx, yy-0100000, prg.octant)
 13899  						prg.printTwo(prg.curX, prg.curY)
 13900  					}
 13901  
 13902  					if int32(*(*prg.mem[r1].hh()).b1()) > k {
 13903  						k = k + 1
 13904  						w = *(*prg.mem[w].hh()).rh()
 13905  						xp = *prg.mem[int32(r1)+1].int() + *prg.mem[int32(w)+1].int()
 13906  						yp = *prg.mem[int32(r1)+2].int() + *prg.mem[int32(w)+2].int() + 0100000
 13907  						if yp != yy {
 13908  							ty = prg.floorScaled(yy - int32(prg.yCorr[prg.octant-1]))
 13909  							dely = yp - yy
 13910  							yy = yy - ty
 13911  							ty = yp - int32(prg.yCorr[prg.octant-1]) - ty
 13912  							if ty >= 0200000 {
 13913  								delx = xp - xx
 13914  								yy = 0200000 - yy
 13915  								for true {
 13916  									tx = prg.takeFraction(delx, prg.makeFraction(yy, dely))
 13917  									if prg.abVsCd(tx, dely, delx, yy)+int32(prg.xyCorr[prg.octant-1]) > 0 {
 13918  										tx = tx - 1
 13919  									}
 13920  									m = prg.floorUnscaled(xx + tx)
 13921  									if m > prg.envMove[prg.movePtr] {
 13922  										prg.envMove[prg.movePtr] = m
 13923  									}
 13924  									ty = ty - 0200000
 13925  									if ty < 0200000 {
 13926  										goto done1
 13927  									}
 13928  									yy = yy + 0200000
 13929  									prg.movePtr = uint16(int32(prg.movePtr) + 1)
 13930  								}
 13931  
 13932  							done1:
 13933  							}
 13934  						}
 13935  					} else {
 13936  						k = k - 1
 13937  						w = *(*prg.mem[w].hh()).lh()
 13938  						xp = *prg.mem[int32(r1)+1].int() + *prg.mem[int32(w)+1].int()
 13939  						yp = *prg.mem[int32(r1)+2].int() + *prg.mem[int32(w)+2].int() + 0100000
 13940  					}
 13941  					if prg.internal[tracingEdges-1] > 0200000 {
 13942  						prg.print( /* " to " */ 583)
 13943  						prg.unskew(xp, yp-0100000, prg.octant)
 13944  						prg.printTwo(prg.curX, prg.curY)
 13945  						prg.printNl(strNumber( /* "" */ 285))
 13946  					}
 13947  
 13948  					m = prg.floorUnscaled(xp - int32(prg.xyCorr[prg.octant-1]))
 13949  					prg.movePtr = uint16(prg.floorUnscaled(yp-int32(prg.yCorr[prg.octant-1])) - prg.n0)
 13950  					if m > prg.envMove[prg.movePtr] {
 13951  						prg.envMove[prg.movePtr] = m
 13952  					}
 13953  				}
 13954  				if int32(r1) == int32(p) {
 13955  					smoothBot = prg.movePtr
 13956  				}
 13957  				if int32(r1) == int32(q) {
 13958  					goto done
 13959  				}
 13960  				prg.move[prg.movePtr] = 1
 13961  				n = int32(prg.movePtr)
 13962  				s = *(*prg.mem[r1].hh()).rh()
 13963  
 13964  				prg.makeMoves(*prg.mem[int32(r1)+1].int()+*prg.mem[int32(w)+1].int(), *prg.mem[int32(r1)+5].int()+*prg.mem[int32(w)+1].int(), *prg.mem[int32(s)+3].int()+*prg.mem[int32(w)+1].int(), *prg.mem[int32(s)+1].int()+*prg.mem[int32(w)+1].int(), *prg.mem[int32(r1)+2].int()+*prg.mem[int32(w)+2].int()+0100000, *prg.mem[int32(r1)+6].int()+*prg.mem[int32(w)+2].int()+0100000, *prg.mem[int32(s)+4].int()+*prg.mem[int32(w)+2].int()+0100000, *prg.mem[int32(s)+2].int()+*prg.mem[int32(w)+2].int()+0100000, prg.xyCorr[prg.octant-1], prg.yCorr[prg.octant-1])
 13965  
 13966  				// Transfer moves from the |move| array to |env_move|
 13967  				for {
 13968  					m = m + prg.move[n] - 1
 13969  					if m > prg.envMove[n] {
 13970  						prg.envMove[n] = m
 13971  					}
 13972  					n = n + 1
 13973  					if n > int32(prg.movePtr) {
 13974  						break
 13975  					}
 13976  				}
 13977  				r1 = s
 13978  			}
 13979  
 13980  		done:
 13981  			prg.move[0] = int32(prg.d0) + prg.envMove[0] - mm0
 13982  			for ii := int32(1); ii <= int32(prg.movePtr); ii++ {
 13983  				n = ii
 13984  				_ = n
 13985  				prg.move[n] = prg.envMove[n] - prg.envMove[n-1] + 1
 13986  			}
 13987  			prg.move[prg.movePtr] = prg.move[prg.movePtr] - int32(prg.d1)
 13988  			if prg.internal[smoothing-1] > 0 {
 13989  				prg.smoothMoves(int32(smoothBot), int32(smoothTop))
 13990  			}
 13991  			prg.moveToEdges(prg.m0, prg.n0, prg.m1, prg.n1)
 13992  			if *prg.mem[int32(q)+6].int() == axis {
 13993  				w = *(*prg.mem[h].hh()).rh()
 13994  				prg.skewLineEdges(q, *(*prg.mem[w].hh()).lh(), w)
 13995  			}
 13996  		} else {
 13997  			prg.dualMoves(h, p, q)
 13998  		}
 13999  		*(*prg.mem[q].hh()).b1() = byte(endpoint)
 14000  		p = *(*prg.mem[q].hh()).rh()
 14001  		if int32(p) == int32(specHead) {
 14002  			break
 14003  		}
 14004  	}
 14005  	if prg.internal[tracingEdges-1] > 0 {
 14006  		prg.endEdgeTracing()
 14007  	}
 14008  	prg.tossKnotList(specHead)
 14009  }
 14010  
 14011  // 524. \[25] Elliptical pens
 14012  
 14013  // tangle:pos ../../mf.web:11071:26:
 14014  
 14015  // To get the envelope of a cyclic path with respect to an ellipse, \MF\
 14016  // calculates the envelope with respect to a polygonal approximation to
 14017  // the ellipse, using an approach due to John Hobby (Ph.D. thesis,
 14018  // Stanford University, 1985).
 14019  // \xref[Hobby, John Douglas]
 14020  // This has two important advantages over trying to obtain the ``exact''
 14021  // envelope:
 14022  //
 14023  // \yskip\textindent[1)]It gives better results, because the polygon has been
 14024  // designed to counteract problems that arise from digitization; the
 14025  // polygon includes sub-pixel corrections to an exact ellipse that make
 14026  // the results essentially independent of where the path falls on the raster.
 14027  // For example, the exact envelope with respect to a pen of diameter~1
 14028  // blackens a pixel if and only if the path intersects a circle of diameter~1
 14029  // inscribed in that pixel; the resulting pattern has ``blots'' when the path
 14030  // is traveling diagonally in unfortunate raster positions. A much better
 14031  // result is obtained when pixels are blackened only when the path intersects
 14032  // an inscribed [\sl diamond\/] of diameter~1. Such a diamond is precisely
 14033  // the polygon that \MF\ uses in the special case of a circle whose diameter is~1.
 14034  //
 14035  // \yskip\textindent[2)]Polygonal envelopes of cubic splines are cubic
 14036  // splines, hence it isn't necessary to introduce completely different
 14037  // routines. By contrast, exact envelopes of cubic splines with respect
 14038  // to circles are complicated curves, more difficult to plot than cubics.
 14039  
 14040  // 525.
 14041  
 14042  // tangle:pos ../../mf.web:11097:3:
 14043  
 14044  // Hobby's construction involves some interesting number theory.
 14045  // If $u$ and~$v$ are relatively prime integers, we divide the
 14046  // set of integer points $(m,n)$ into equivalence classes by saying
 14047  // that $(m,n)$ belongs to class $um+vn$. Then any two integer points
 14048  // that lie on a line of slope $-u/v$ belong to the same class, because
 14049  // such points have the form $(m+tv,n-tu)$. Neighboring lines of slope $-u/v$
 14050  // that go through integer points are separated by distance $1/\psqrt[u^2+v^2]$
 14051  // from each other, and these lines are perpendicular to lines of slope~$v/u$.
 14052  // If we start at the origin and travel a distance $k/\psqrt[u^2+v^2]$ in
 14053  // direction $(u,v)$, we reach the line of slope~$-u/v$ whose points
 14054  // belong to class~$k$.
 14055  //
 14056  // For example, let $u=2$ and $v=3$. Then the points $(0,0)$, $(3,-2)$,
 14057  // $\ldots$ belong to class~0; the points $(-1,1)$, $(2,-1)$, $\ldots$ belong
 14058  // to class~1; and the distance between these two lines is $1/\sqrt[13]$.
 14059  // The point $(2,3)$ itself belongs to class~13, hence its distance from
 14060  // the origin is $13/\sqrt[13]=\sqrt[13]$ (which we already knew).
 14061  //
 14062  // Suppose we wish to plot envelopes with respect to polygons with
 14063  // integer vertices. Then the best polygon for curves that travel in
 14064  // direction $(v,-u)$ will contain the points of class~$k$ such that
 14065  // $k/\psqrt[u^2+v^2]$ is as close as possible to~$d$, where $d$ is the
 14066  // maximum distance of the given ellipse from the line $ux+vy=0$.
 14067  //
 14068  // The |fillin| correction assumes that a diagonal line has an
 14069  // apparent thickness $$2f\cdot\min(\vert u\vert,\vert v\vert)/\psqrt[u^2+v^2]$$
 14070  // greater than would be obtained with truly square pixels. (If a
 14071  // white pixel at an exterior corner is assumed to have apparent
 14072  // darkness $f_1$ and a black pixel at an interior corner is assumed
 14073  // to have apparent darkness $1-f_2$, then $f=f_1-f_2$ is the |fillin|
 14074  // parameter.) Under this assumption we want to choose $k$ so that
 14075  // $\bigl(k+2f\cdot\min(\vert u\vert,\vert v\vert)\bigr)\big/\psqrt[u^2+v^2]$
 14076  // is as close as possible to $d$.
 14077  //
 14078  // Integer coordinates for the vertices work nicely because the thickness of
 14079  // the envelope at any given slope is independent of the position of the
 14080  // path with respect to the raster. It turns out, in fact, that the same
 14081  // property holds for polygons whose vertices have coordinates that are
 14082  // integer multiples of~$1\over2$, because ellipses are symmetric about
 14083  // the origin. It's convenient to double all dimensions and require the
 14084  // resulting polygon to have vertices with integer coordinates. For example,
 14085  // to get a circle of [\sl diameter]~$r$, we shall compute integer
 14086  // coordinates for a circle of [\sl radius]~$r$. The circle of radius~$r$
 14087  // will want to be represented by a polygon that contains the boundary
 14088  // points $(0,\pm r)$ and~$(\pm r,0)$; later we will divide everything
 14089  // by~2 and get a polygon with $(0,\pm[1\over2]r)$ and $(\pm[1\over2]r,0)$
 14090  // on its boundary.
 14091  
 14092  // 526.
 14093  
 14094  // tangle:pos ../../mf.web:11145:3:
 14095  
 14096  // In practice the important slopes are those having small values of
 14097  // $u$ and~$v$; these make regular patterns in which our eyes quickly
 14098  // spot irregularities. For example, horizontal and vertical lines
 14099  // (when $u=0$ and $\vert v\vert=1$, or $\vert u\vert=1$ and $v=0$)
 14100  // are the most important; diagonal lines (when $\vert u\vert=\vert v\vert=1$)
 14101  // are next; and then come lines with slope $\pm2$ or $\pm1/2$.
 14102  //
 14103  // The nicest way to generate all rational directions having small
 14104  // numerators and denominators is to generalize the Stern--Brocot tree
 14105  // [cf.~[\sl Concrete Mathematics], section 4.5]
 14106  // \xref[Brocot, Achille]
 14107  // \xref[Stern, Moritz Abraham]
 14108  // to a ``Stern--Brocot wreath'' as follows: Begin with four nodes
 14109  // arranged in a circle, containing the respective directions
 14110  // $(u,v)=(1,0)$, $(0,1)$, $(-1,0)$, and~$(0,-1)$. Then between pairs of
 14111  // consecutive terms $(u,v)$ and $(u',v')$ of the wreath, insert the
 14112  // direction $(u+u',v+v')$; continue doing this until some stopping
 14113  // criterion is fulfilled.
 14114  //
 14115  // It is not difficult to verify that, regardless of the stopping
 14116  // criterion, consecutive directions $(u,v)$ and $(u',v')$ of this
 14117  // wreath will always satisfy the relation $uv'-u'v=1$. Such pairs
 14118  // of directions have a nice property with respect to the equivalence
 14119  // classes described above. Let $l$ be a line of equivalent integer points
 14120  // $(m+tv,n-tu)$ with respect to~$(u,v)$, and let $l'$ be a line of
 14121  // equivalent integer points $(m'+tv',n'-tu')$ with respect to~$(u',v')$.
 14122  // Then $l$ and~$l'$ intersect in an integer point $(m'',n'')$, because
 14123  // the determinant of the linear equations for intersection is $uv'-u'v=1$.
 14124  // Notice that the class number of $(m'',n'')$ with respect to $(u+u',v+v')$
 14125  // is the sum of its class numbers with respect to $(u,v)$ and~$(u',v')$.
 14126  // Moreover, consecutive points on~$l$ and~$l'$ belong to classes that
 14127  // differ by exactly~1 with respect to $(u+u',v+v')$.
 14128  //
 14129  // This leads to a nice algorithm in which we construct a polygon having
 14130  // ``correct'' class numbers for as many small-integer directions $(u,v)$
 14131  // as possible: Assuming that lines $l$ and~$l'$ contain points of the
 14132  // correct class for $(u,v)$ and~$(u',v')$, respectively, we determine
 14133  // the intersection $(m'',n'')$ and compute its class with respect to
 14134  // $(u+u',v+v')$. If the class is too large to be the best approximation,
 14135  // we move back the proper number of steps from $(m'',n'')$ toward smaller
 14136  // class numbers on both $l$ and~$l'$, unless this requires moving to points
 14137  // that are no longer in the polygon; in this way we arrive at two points that
 14138  // determine a line~$l''$ having the appropriate class. The process continues
 14139  // recursively, until it cannot proceed without removing the last remaining
 14140  // point from the class for $(u,v)$ or the class for $(u',v')$.
 14141  
 14142  // 527.
 14143  
 14144  // tangle:pos ../../mf.web:11191:3:
 14145  
 14146  // The |make_ellipse| subroutine produces a pointer to a cyclic path
 14147  // whose vertices define a polygon suitable for envelopes. The control
 14148  // points on this path will be ignored; in fact, the fields in knot nodes
 14149  // that are usually reserved for control points are occupied by other
 14150  // data that helps |make_ellipse| compute the desired polygon.
 14151  //
 14152  // Parameters |major_axis| and |minor_axis| define the axes of the ellipse;
 14153  // and parameter |theta| is an angle by which the ellipse is rotated
 14154  // counterclockwise. If |theta=0|, the ellipse has the equation
 14155  // $(x/a)^2+(y/b)^2=1$, where |a=major_axis/2| and |b=minor_axis/2|.
 14156  // In general, the points of the ellipse are generated in the complex plane
 14157  // by the formula $e^[i\theta](a\cos t+ib\sin t)$, as $t$~ranges over all
 14158  // angles. Notice that if |major_axis=minor_axis=d|, we obtain a circle
 14159  // of diameter~|d|, regardless of the value of |theta|.
 14160  //
 14161  // The method sketched above is used to produce the elliptical polygon,
 14162  // except that the main work is done only in the halfplane obtained from
 14163  // the three starting directions $(0,-1)$, $(1,0)$,~$(0,1)$. Since the ellipse
 14164  // has circular symmetry, we use the fact that the last half of the polygon
 14165  // is simply the negative of the first half. Furthermore, we need to compute only
 14166  // one quarter of the polygon if the ellipse has axis symmetry.
 14167  func (prg *prg) makeEllipse(majorAxis, minorAxis scaled,
 14168  	theta angle) (r halfword) {
 14169  	var (
 14170  		p, q, r1, s               halfword // for list manipulation
 14171  		h                         halfword // head of the constructed knot list
 14172  		alpha, beta, gamma, delta int32    // special points
 14173  		c, d                      int32    // class numbers
 14174  		u, v                      int32    // directions
 14175  		symmetric                 bool     // should the result be symmetric about the axes?
 14176  	)
 14177  	if majorAxis == minorAxis || theta%0550000000 == 0 {
 14178  		symmetric = true
 14179  		alpha = 0
 14180  		if theta/0550000000&1 != 0 {
 14181  			beta = majorAxis
 14182  			gamma = minorAxis
 14183  			prg.nSin = 02000000000
 14184  			prg.nCos = 0 // |n_sin| and |n_cos| are used later
 14185  		} else {
 14186  			beta = minorAxis
 14187  			gamma = majorAxis
 14188  			theta = 0
 14189  		} // |n_sin| and |n_cos| aren't needed in this case
 14190  	} else {
 14191  		symmetric = false
 14192  		prg.nSinCos(theta) // set up $|n_sin|=\sin\theta$ and $|n_cos|=\cos\theta$
 14193  		gamma = prg.takeFraction(majorAxis, prg.nSin)
 14194  		delta = prg.takeFraction(minorAxis, prg.nCos)
 14195  		beta = prg.pythAdd(gamma, delta)
 14196  		alpha = prg.takeFraction(prg.takeFraction(majorAxis, prg.makeFraction(gamma, beta)), prg.nCos) - prg.takeFraction(prg.takeFraction(minorAxis, prg.makeFraction(delta, beta)), prg.nSin)
 14197  		alpha = (alpha + 0100000) / 0200000
 14198  		gamma = prg.pythAdd(prg.takeFraction(majorAxis, prg.nCos), prg.takeFraction(minorAxis, prg.nSin))
 14199  	}
 14200  	beta = (beta + 0100000) / 0200000
 14201  	gamma = (gamma + 0100000) / 0200000
 14202  	p = prg.getNode(knotNodeSize)
 14203  	q = prg.getNode(knotNodeSize)
 14204  	r1 = prg.getNode(knotNodeSize)
 14205  	if symmetric {
 14206  		s = uint16(memMin)
 14207  	} else {
 14208  		s = prg.getNode(knotNodeSize)
 14209  	}
 14210  	h = p
 14211  	*(*prg.mem[p].hh()).rh() = q
 14212  	*(*prg.mem[q].hh()).rh() = r1
 14213  	*(*prg.mem[r1].hh()).rh() = s // |s=null| or |link(s)=null|
 14214  
 14215  	// Revise the values of $\alpha$, $\beta$, $\gamma$, if necessary, so that degenerate lines of length zero will not be obtained
 14216  	if beta == 0 {
 14217  		beta = 1
 14218  	}
 14219  	if gamma == 0 {
 14220  		gamma = 1
 14221  	}
 14222  	if gamma <= abs(alpha) {
 14223  		if alpha > 0 {
 14224  			alpha = gamma - 1
 14225  		} else {
 14226  			alpha = 1 - gamma
 14227  		}
 14228  	}
 14229  	*prg.mem[int32(p)+1].int() = -(alpha * 0100000)
 14230  	*prg.mem[int32(p)+2].int() = -(beta * 0100000)
 14231  	*prg.mem[int32(q)+1].int() = gamma * 0100000
 14232  
 14233  	*prg.mem[int32(q)+2].int() = *prg.mem[int32(p)+2].int()
 14234  	*prg.mem[int32(r1)+1].int() = *prg.mem[int32(q)+1].int()
 14235  
 14236  	*prg.mem[int32(p)+5].int() = 0
 14237  	*prg.mem[int32(q)+3].int() = -0100000
 14238  
 14239  	*prg.mem[int32(q)+5].int() = 0100000
 14240  	*prg.mem[int32(r1)+3].int() = 0
 14241  
 14242  	*prg.mem[int32(r1)+5].int() = 0
 14243  	*prg.mem[int32(p)+6].int() = beta
 14244  	*prg.mem[int32(q)+6].int() = gamma
 14245  	*prg.mem[int32(r1)+6].int() = beta
 14246  
 14247  	*prg.mem[int32(q)+4].int() = gamma + alpha
 14248  	if symmetric {
 14249  		*prg.mem[int32(r1)+2].int() = 0
 14250  		*prg.mem[int32(r1)+4].int() = beta
 14251  	} else {
 14252  		*prg.mem[int32(r1)+2].int() = -*prg.mem[int32(p)+2].int()
 14253  		*prg.mem[int32(r1)+4].int() = beta + beta
 14254  
 14255  		*prg.mem[int32(s)+1].int() = -*prg.mem[int32(p)+1].int()
 14256  		*prg.mem[int32(s)+2].int() = *prg.mem[int32(r1)+2].int()
 14257  
 14258  		*prg.mem[int32(s)+3].int() = 0100000
 14259  		*prg.mem[int32(s)+4].int() = gamma - alpha
 14260  	}
 14261  
 14262  	// Interpolate new vertices in the ellipse data structure until improvement is impossible
 14263  	for true {
 14264  		u = *prg.mem[int32(p)+5].int() + *prg.mem[int32(q)+5].int()
 14265  		v = *prg.mem[int32(q)+3].int() + *prg.mem[int32(r1)+3].int()
 14266  		c = *prg.mem[int32(p)+6].int() + *prg.mem[int32(q)+6].int()
 14267  
 14268  		// Compute the distance |d| from class~0 to the edge of the ellipse in direction |(u,v)|, times $\psqrt[u^2+v^2]$, rounded to the nearest integer
 14269  		delta = prg.pythAdd(u, v)
 14270  		if majorAxis == minorAxis {
 14271  			d = majorAxis
 14272  		} else {
 14273  			if theta == 0 {
 14274  				alpha = u
 14275  				beta = v
 14276  			} else {
 14277  				alpha = prg.takeFraction(u, prg.nCos) + prg.takeFraction(v, prg.nSin)
 14278  				beta = prg.takeFraction(v, prg.nCos) - prg.takeFraction(u, prg.nSin)
 14279  			}
 14280  			alpha = prg.makeFraction(alpha, delta)
 14281  			beta = prg.makeFraction(beta, delta)
 14282  			d = prg.pythAdd(prg.takeFraction(majorAxis, alpha), prg.takeFraction(minorAxis, beta))
 14283  		}
 14284  		alpha = abs(u)
 14285  		beta = abs(v)
 14286  		if alpha < beta {
 14287  			alpha = abs(v)
 14288  			beta = abs(u)
 14289  		} // now $\alpha=\max(\vert u\vert,\vert v\vert)$,
 14290  		//       $\beta=\min(\vert u\vert,\vert v\vert)$
 14291  
 14292  		if prg.internal[fillin-1] != 0 {
 14293  			d = d - prg.takeFraction(prg.internal[fillin-1], prg.makeFraction(beta+beta, delta))
 14294  		}
 14295  		d = prg.takeFraction((d+4)/8, delta)
 14296  		alpha = alpha / 0100000
 14297  		if d < alpha {
 14298  			d = alpha
 14299  		}
 14300  		delta = c - d // we want to move |delta| steps back
 14301  		//       from the intersection vertex~|q|
 14302  
 14303  		if delta > 0 {
 14304  			if delta > *prg.mem[int32(r1)+4].int() {
 14305  				delta = *prg.mem[int32(r1)+4].int()
 14306  			}
 14307  			if delta >= *prg.mem[int32(q)+4].int() {
 14308  				delta = *prg.mem[int32(q)+4].int()
 14309  
 14310  				*prg.mem[int32(p)+6].int() = c - delta
 14311  				*prg.mem[int32(p)+5].int() = u
 14312  				*prg.mem[int32(q)+3].int() = v
 14313  
 14314  				*prg.mem[int32(q)+1].int() = *prg.mem[int32(q)+1].int() - delta**prg.mem[int32(r1)+3].int()
 14315  				*prg.mem[int32(q)+2].int() = *prg.mem[int32(q)+2].int() + delta**prg.mem[int32(q)+5].int()
 14316  
 14317  				*prg.mem[int32(r1)+4].int() = *prg.mem[int32(r1)+4].int() - delta
 14318  			} else {
 14319  				// Insert a new line for direction |(u,v)| between |p| and~|q|
 14320  				s = prg.getNode(knotNodeSize)
 14321  				*(*prg.mem[p].hh()).rh() = s
 14322  				*(*prg.mem[s].hh()).rh() = q
 14323  
 14324  				*prg.mem[int32(s)+1].int() = *prg.mem[int32(q)+1].int() + delta**prg.mem[int32(q)+3].int()
 14325  				*prg.mem[int32(s)+2].int() = *prg.mem[int32(q)+2].int() - delta**prg.mem[int32(p)+5].int()
 14326  
 14327  				*prg.mem[int32(q)+1].int() = *prg.mem[int32(q)+1].int() - delta**prg.mem[int32(r1)+3].int()
 14328  				*prg.mem[int32(q)+2].int() = *prg.mem[int32(q)+2].int() + delta**prg.mem[int32(q)+5].int()
 14329  
 14330  				*prg.mem[int32(s)+3].int() = *prg.mem[int32(q)+3].int()
 14331  				*prg.mem[int32(s)+5].int() = u
 14332  				*prg.mem[int32(q)+3].int() = v
 14333  
 14334  				*prg.mem[int32(s)+6].int() = c - delta
 14335  
 14336  				*prg.mem[int32(s)+4].int() = *prg.mem[int32(q)+4].int() - delta
 14337  				*prg.mem[int32(q)+4].int() = delta
 14338  				*prg.mem[int32(r1)+4].int() = *prg.mem[int32(r1)+4].int() - delta
 14339  			}
 14340  		} else {
 14341  			p = q
 14342  		}
 14343  
 14344  		// Move to the next remaining triple |(p,q,r)|, removing and skipping past zero-length lines that might be present; |goto done| if all triples have been processed
 14345  		for true {
 14346  			q = *(*prg.mem[p].hh()).rh()
 14347  			if int32(q) == memMin {
 14348  				goto done
 14349  			}
 14350  			if *prg.mem[int32(q)+4].int() == 0 {
 14351  				*(*prg.mem[p].hh()).rh() = *(*prg.mem[q].hh()).rh()
 14352  				*prg.mem[int32(p)+6].int() = *prg.mem[int32(q)+6].int()
 14353  				*prg.mem[int32(p)+5].int() = *prg.mem[int32(q)+5].int()
 14354  				prg.freeNode(q, halfword(knotNodeSize))
 14355  			} else {
 14356  				r1 = *(*prg.mem[q].hh()).rh()
 14357  				if int32(r1) == memMin {
 14358  					goto done
 14359  				}
 14360  				if *prg.mem[int32(r1)+4].int() == 0 {
 14361  					*(*prg.mem[p].hh()).rh() = r1
 14362  					prg.freeNode(q, halfword(knotNodeSize))
 14363  					p = r1
 14364  				} else {
 14365  					goto found
 14366  				}
 14367  			}
 14368  		}
 14369  
 14370  	found:
 14371  	}
 14372  
 14373  done:
 14374  	;
 14375  	if symmetric {
 14376  		s = uint16(memMin)
 14377  		q = h
 14378  		for true {
 14379  			r1 = prg.getNode(knotNodeSize)
 14380  			*(*prg.mem[r1].hh()).rh() = s
 14381  			s = r1
 14382  
 14383  			*prg.mem[int32(s)+1].int() = *prg.mem[int32(q)+1].int()
 14384  			*prg.mem[int32(s)+2].int() = -*prg.mem[int32(q)+2].int()
 14385  			if int32(q) == int32(p) {
 14386  				goto done1
 14387  			}
 14388  			q = *(*prg.mem[q].hh()).rh()
 14389  			if *prg.mem[int32(q)+2].int() == 0 {
 14390  				goto done1
 14391  			}
 14392  		}
 14393  
 14394  	done1:
 14395  		if int32(*(*prg.mem[p].hh()).rh()) != memMin {
 14396  			prg.freeNode(*(*prg.mem[p].hh()).rh(), halfword(knotNodeSize))
 14397  		}
 14398  		*(*prg.mem[p].hh()).rh() = s
 14399  		beta = -*prg.mem[int32(h)+2].int()
 14400  		for *prg.mem[int32(p)+2].int() != beta {
 14401  			p = *(*prg.mem[p].hh()).rh()
 14402  		}
 14403  		q = *(*prg.mem[p].hh()).rh()
 14404  	}
 14405  
 14406  	// Complete the ellipse by copying the negative of the half already computed
 14407  	if int32(q) != memMin {
 14408  		if *prg.mem[int32(h)+5].int() == 0 {
 14409  			p = h
 14410  			h = *(*prg.mem[h].hh()).rh()
 14411  			prg.freeNode(p, halfword(knotNodeSize))
 14412  
 14413  			*prg.mem[int32(q)+1].int() = -*prg.mem[int32(h)+1].int()
 14414  		}
 14415  		p = q
 14416  	} else {
 14417  		q = p
 14418  	}
 14419  	r1 = *(*prg.mem[h].hh()).rh() // now |p=q|, |x_coord(p)=-x_coord(h)|, |y_coord(p)=-y_coord(h)|
 14420  	for {
 14421  		s = prg.getNode(knotNodeSize)
 14422  		*(*prg.mem[p].hh()).rh() = s
 14423  		p = s
 14424  
 14425  		*prg.mem[int32(p)+1].int() = -*prg.mem[int32(r1)+1].int()
 14426  		*prg.mem[int32(p)+2].int() = -*prg.mem[int32(r1)+2].int()
 14427  		r1 = *(*prg.mem[r1].hh()).rh()
 14428  		if int32(r1) == int32(q) {
 14429  			break
 14430  		}
 14431  	}
 14432  	*(*prg.mem[p].hh()).rh() = h
 14433  	r = h
 14434  	return r
 14435  }
 14436  
 14437  // 538. \[26] Direction and intersection times
 14438  
 14439  // tangle:pos ../../mf.web:11496:43:
 14440  
 14441  // A path of length $n$ is defined parametrically by functions $x(t)$ and
 14442  // $y(t)$, for |0<=t<=n|; we can regard $t$ as the ``time'' at which the path
 14443  // reaches the point $\bigl(x(t),y(t)\bigr)$.  In this section of the program
 14444  // we shall consider operations that determine special times associated with
 14445  // given paths: the first time that a path travels in a given direction, and
 14446  // a pair of times at which two paths cross each other.
 14447  
 14448  // 539.
 14449  
 14450  // tangle:pos ../../mf.web:11504:3:
 14451  
 14452  // Let's start with the easier task. The function |find_direction_time| is
 14453  // given a direction |(x,y)| and a path starting at~|h|. If the path never
 14454  // travels in direction |(x,y)|, the direction time will be~|-1|; otherwise
 14455  // it will be nonnegative.
 14456  //
 14457  // Certain anomalous cases can arise: If |(x,y)=(0,0)|, so that the given
 14458  // direction is undefined, the direction time will be~0. If $\bigl(x'(t),
 14459  // y'(t)\bigr)=(0,0)$, so that the path direction is undefined, it will be
 14460  // assumed to match any given direction at time~|t|.
 14461  //
 14462  // The routine solves this problem in nondegenerate cases by rotating the path
 14463  // and the given direction so that |(x,y)=(1,0)|; i.e., the main task will be
 14464  // to find when a given path first travels ``due east.''
 14465  func (prg *prg) findDirectionTime(x, y scaled, h halfword) (r scaled) {
 14466  	var (
 14467  		max  scaled   // $\max\bigl(\vert x\vert,\vert y\vert\bigr)$
 14468  		p, q halfword // for list traversal
 14469  		n    scaled   // the direction time at knot |p|
 14470  		tt   scaled   // the direction time within a cubic
 14471  
 14472  		// Other local variables for |find_direction_time|
 14473  		x1, x2, x3, y1, y2, y3 scaled   // multiples of rotated derivatives
 14474  		theta, phi             angle    // angles of exit and entry at a knot
 14475  		t                      fraction // temp storage
 14476  	)
 14477  	if abs(x) < abs(y) {
 14478  		x = prg.makeFraction(x, abs(y))
 14479  		if y > 0 {
 14480  			y = 02000000000
 14481  		} else {
 14482  			y = -02000000000
 14483  		}
 14484  	} else if x == 0 {
 14485  		r = 0
 14486  		goto exit
 14487  	} else {
 14488  		y = prg.makeFraction(y, abs(x))
 14489  		if x > 0 {
 14490  			x = 02000000000
 14491  		} else {
 14492  			x = -02000000000
 14493  		}
 14494  	}
 14495  	n = 0
 14496  	p = h
 14497  	for true {
 14498  		if int32(*(*prg.mem[p].hh()).b1()) == endpoint {
 14499  			goto notFound
 14500  		}
 14501  		q = *(*prg.mem[p].hh()).rh()
 14502  
 14503  		// Rotate the cubic between |p| and |q|; then |goto found| if the rotated cubic travels due east at some time |tt|; but |goto not_found| if an entire cyclic path has been traversed
 14504  		tt = 0
 14505  
 14506  		// Set local variables |x1,x2,x3| and |y1,y2,y3| to multiples of the control points of the rotated derivatives
 14507  		x1 = *prg.mem[int32(p)+5].int() - *prg.mem[int32(p)+1].int()
 14508  		x2 = *prg.mem[int32(q)+3].int() - *prg.mem[int32(p)+5].int()
 14509  		x3 = *prg.mem[int32(q)+1].int() - *prg.mem[int32(q)+3].int()
 14510  
 14511  		y1 = *prg.mem[int32(p)+6].int() - *prg.mem[int32(p)+2].int()
 14512  		y2 = *prg.mem[int32(q)+4].int() - *prg.mem[int32(p)+6].int()
 14513  		y3 = *prg.mem[int32(q)+2].int() - *prg.mem[int32(q)+4].int()
 14514  
 14515  		max = abs(x1)
 14516  		if abs(x2) > max {
 14517  			max = abs(x2)
 14518  		}
 14519  		if abs(x3) > max {
 14520  			max = abs(x3)
 14521  		}
 14522  		if abs(y1) > max {
 14523  			max = abs(y1)
 14524  		}
 14525  		if abs(y2) > max {
 14526  			max = abs(y2)
 14527  		}
 14528  		if abs(y3) > max {
 14529  			max = abs(y3)
 14530  		}
 14531  		if max == 0 {
 14532  			goto found
 14533  		}
 14534  		for max < 01000000000 {
 14535  			max = max + max
 14536  			x1 = x1 + x1
 14537  			x2 = x2 + x2
 14538  			x3 = x3 + x3
 14539  			y1 = y1 + y1
 14540  			y2 = y2 + y2
 14541  			y3 = y3 + y3
 14542  		}
 14543  		t = x1
 14544  		x1 = prg.takeFraction(x1, x) + prg.takeFraction(y1, y)
 14545  		y1 = prg.takeFraction(y1, x) - prg.takeFraction(t, y)
 14546  
 14547  		t = x2
 14548  		x2 = prg.takeFraction(x2, x) + prg.takeFraction(y2, y)
 14549  		y2 = prg.takeFraction(y2, x) - prg.takeFraction(t, y)
 14550  
 14551  		t = x3
 14552  		x3 = prg.takeFraction(x3, x) + prg.takeFraction(y3, y)
 14553  		y3 = prg.takeFraction(y3, x) - prg.takeFraction(t, y)
 14554  		if y1 == 0 {
 14555  			if x1 >= 0 {
 14556  				goto found
 14557  			}
 14558  		}
 14559  		if n > 0 {
 14560  			theta = prg.nArg(x1, y1)
 14561  			if theta >= 0 {
 14562  				if phi <= 0 {
 14563  					if phi >= theta-01320000000 {
 14564  						goto found
 14565  					}
 14566  				}
 14567  			}
 14568  			if theta <= 0 {
 14569  				if phi >= 0 {
 14570  					if phi <= theta+01320000000 {
 14571  						goto found
 14572  					}
 14573  				}
 14574  			}
 14575  			if int32(p) == int32(h) {
 14576  				goto notFound
 14577  			}
 14578  		}
 14579  		if x3 != 0 || y3 != 0 {
 14580  			phi = prg.nArg(x3, y3)
 14581  		}
 14582  
 14583  		// Exit to |found| if the curve whose derivatives are specified by |x1,x2,x3,y1,y2,y3| travels eastward at some time~|tt|
 14584  		if x1 < 0 {
 14585  			if x2 < 0 {
 14586  				if x3 < 0 {
 14587  					goto done
 14588  				}
 14589  			}
 14590  		}
 14591  		if prg.abVsCd(y1, y3, y2, y2) == 0 {
 14592  			if prg.abVsCd(y1, y2, 0, 0) < 0 {
 14593  				t = prg.makeFraction(y1, y1-y2)
 14594  				x1 = x1 - prg.takeFraction(x1-x2, t)
 14595  				x2 = x2 - prg.takeFraction(x2-x3, t)
 14596  				if x1-prg.takeFraction(x1-x2, t) >= 0 {
 14597  					tt = (t + 04000) / 010000
 14598  					goto found
 14599  				}
 14600  			} else if y3 == 0 {
 14601  				if y1 == 0 {
 14602  					t = prg.crossingPoint(-x1, -x2, -x3)
 14603  					if t <= 02000000000 {
 14604  						tt = (t + 04000) / 010000
 14605  						goto found
 14606  					}
 14607  					if prg.abVsCd(x1, x3, x2, x2) <= 0 {
 14608  						t = prg.makeFraction(x1, x1-x2)
 14609  						{
 14610  							tt = (t + 04000) / 010000
 14611  							goto found
 14612  						}
 14613  					}
 14614  				} else if x3 >= 0 {
 14615  					tt = 0200000
 14616  					goto found
 14617  				}
 14618  			}
 14619  
 14620  			goto done
 14621  		}
 14622  		if y1 <= 0 {
 14623  			if y1 < 0 {
 14624  				y1 = -y1
 14625  				y2 = -y2
 14626  				y3 = -y3
 14627  			} else if y2 > 0 {
 14628  				y2 = -y2
 14629  				y3 = -y3
 14630  			}
 14631  		}
 14632  
 14633  		// Check the places where $B(y_1,y_2,y_3;t)=0$ to see if $B(x_1,x_2,x_3;t)\ge0$
 14634  		t = prg.crossingPoint(y1, y2, y3)
 14635  		if t > 02000000000 {
 14636  			goto done
 14637  		}
 14638  		y2 = y2 - prg.takeFraction(y2-y3, t)
 14639  		x1 = x1 - prg.takeFraction(x1-x2, t)
 14640  		x2 = x2 - prg.takeFraction(x2-x3, t)
 14641  		x1 = x1 - prg.takeFraction(x1-x2, t)
 14642  		if x1 >= 0 {
 14643  			tt = (t + 04000) / 010000
 14644  			goto found
 14645  		}
 14646  		if y2 > 0 {
 14647  			y2 = 0
 14648  		}
 14649  		tt = t
 14650  		t = prg.crossingPoint(0, -y2, -y3)
 14651  		if t > 02000000000 {
 14652  			goto done
 14653  		}
 14654  		x1 = x1 - prg.takeFraction(x1-x2, t)
 14655  		x2 = x2 - prg.takeFraction(x2-x3, t)
 14656  		if x1-prg.takeFraction(x1-x2, t) >= 0 {
 14657  			t = tt - prg.takeFraction(tt-02000000000, t)
 14658  			{
 14659  				tt = (t + 04000) / 010000
 14660  				goto found
 14661  			}
 14662  		}
 14663  
 14664  	done:
 14665  		;
 14666  		p = q
 14667  		n = n + 0200000
 14668  	}
 14669  
 14670  notFound:
 14671  	r = -0200000
 14672  	goto exit
 14673  
 14674  found:
 14675  	r = n + tt
 14676  
 14677  exit:
 14678  	;
 14679  	return r
 14680  }
 14681  
 14682  // 545.
 14683  
 14684  // tangle:pos ../../mf.web:11608:3:
 14685  
 14686  // In this step we want to use the |crossing_point| routine to find the
 14687  // roots of the quadratic equation $B(y_1,y_2,y_3;t)=0$.
 14688  // Several complications arise: If the quadratic equation has a double root,
 14689  // the curve never crosses zero, and |crossing_point| will find nothing;
 14690  // this case occurs iff $y_1y_3=y_2^2$ and $y_1y_2<0$. If the quadratic
 14691  // equation has simple roots, or only one root, we may have to negate it
 14692  // so that $B(y_1,y_2,y_3;t)$ crosses from positive to negative at its first root.
 14693  // And finally, we need to do special things if $B(y_1,y_2,y_3;t)$ is
 14694  // identically zero.
 14695  
 14696  // 550.
 14697  
 14698  // tangle:pos ../../mf.web:11692:3:
 14699  
 14700  // The intersection of two cubics can be found by an interesting variant
 14701  // of the general bisection scheme described in the introduction to |make_moves|.\
 14702  // Given $w(t)=B(w_0,w_1,w_2,w_3;t)$ and $z(t)=B(z_0,z_1,z_2,z_3;t)$,
 14703  // we wish to find a pair of times $(t_1,t_2)$ such that $w(t_1)=z(t_2)$,
 14704  // if an intersection exists. First we find the smallest rectangle that
 14705  // encloses the points $\[w_0,w_1,w_2,w_3\]$ and check that it overlaps
 14706  // the smallest rectangle that encloses
 14707  // $\[z_0,z_1,z_2,z_3\]$; if not, the cubics certainly don't intersect.
 14708  // But if the rectangles do overlap, we bisect the intervals, getting
 14709  // new cubics $w'$ and~$w''$, $z'$~and~$z''$; the intersection routine first
 14710  // tries for an intersection between $w'$ and~$z'$, then (if unsuccessful)
 14711  // between $w'$ and~$z''$, then (if still unsuccessful) between $w''$ and~$z'$,
 14712  // finally (if thrice unsuccessful) between $w''$ and~$z''$. After $l$~successful
 14713  // levels of bisection we will have determined the intersection times $t_1$
 14714  // and~$t_2$ to $l$~bits of accuracy.
 14715  //
 14716  // \def\submin[_[\rm min]] \def\submax[_[\rm max]]
 14717  // As before, it is better to work with the numbers $W_k=2^l(w_k-w_[k-1])$
 14718  // and $Z_k=2^l(z_k-z_[k-1])$ rather than the coefficients $w_k$ and $z_k$
 14719  // themselves. We also need one other quantity, $\Delta=2^l(w_0-z_0)$,
 14720  // to determine when the enclosing rectangles overlap. Here's why:
 14721  // The $x$~coordinates of~$w(t)$ are between $u\submin$ and $u\submax$,
 14722  // and the $x$~coordinates of~$z(t)$ are between $x\submin$ and $x\submax$,
 14723  // if we write $w_k=(u_k,v_k)$ and $z_k=(x_k,y_k)$ and $u\submin=
 14724  // \min(u_0,u_1,u_2,u_3)$, etc. These intervals of $x$~coordinates
 14725  // overlap if and only if $u\submin\L x\submax$ and
 14726  // $x\submin\L u\submax$. Letting
 14727  // $$U\submin=\min(0,U_1,U_1+U_2,U_1+U_2+U_3),\;
 14728  //   U\submax=\max(0,U_1,U_1+U_2,U_1+U_2+U_3),$$
 14729  // we have $2^lu\submin=2^lu_0+U\submin$, etc.; the condition for overlap
 14730  // reduces to
 14731  // $$X\submin-U\submax\L 2^l(u_0-x_0)\L X\submax-U\submin.$$
 14732  // Thus we want to maintain the quantity $2^l(u_0-x_0)$; similarly,
 14733  // the quantity $2^l(v_0-y_0)$ accounts for the $y$~coordinates. The
 14734  // coordinates of $\Delta=2^l(w_0-z_0)$ must stay bounded as $l$ increases,
 14735  // because of the overlap condition; i.e., we know that $X\submin$,
 14736  // $X\submax$, and their relatives are bounded, hence $X\submax-
 14737  // U\submin$ and $X\submin-U\submax$ are bounded.
 14738  
 14739  // 551.
 14740  
 14741  // tangle:pos ../../mf.web:11731:3:
 14742  
 14743  // Incidentally, if the given cubics intersect more than once, the process
 14744  // just sketched will not necessarily find the lexicographically smallest pair
 14745  // $(t_1,t_2)$. The solution actually obtained will be smallest in ``shuffled
 14746  // order''; i.e., if $t_1=(.a_1a_2\ldots a_[16])_2$ and
 14747  // $t_2=(.b_1b_2\ldots b_[16])_2$, then we will minimize
 14748  // $a_1b_1a_2b_2\ldots a_[16]b_[16]$, not
 14749  // $a_1a_2\ldots a_[16]b_1b_2\ldots b_[16]$.
 14750  // Shuffled order agrees with lexicographic order if all pairs of solutions
 14751  // $(t_1,t_2)$ and $(t_1',t_2')$ have the property that $t_1<t_1'$ iff
 14752  // $t_2<t_2'$; but in general, lexicographic order can be quite different,
 14753  // and the bisection algorithm would be substantially less efficient if it were
 14754  // constrained by lexicographic order.
 14755  //
 14756  // For example, suppose that an overlap has been found for $l=3$ and
 14757  // $(t_1,t_2)= (.101,.011)$ in binary, but that no overlap is produced by
 14758  // either of the alternatives $(.1010,.0110)$, $(.1010,.0111)$ at level~4.
 14759  // Then there is probably an intersection in one of the subintervals
 14760  // $(.1011,.011x)$; but lexicographic order would require us to explore
 14761  // $(.1010,.1xxx)$ and $(.1011,.00xx)$ and $(.1011,.010x)$ first. We wouldn't
 14762  // want to store all of the subdivision data for the second path, so the
 14763  // subdivisions would have to be regenerated many times. Such inefficiencies
 14764  // would be associated with every `1' in the binary representation of~$t_1$.
 14765  
 14766  // 554.
 14767  
 14768  // tangle:pos ../../mf.web:11839:3:
 14769  
 14770  // Computation of the min and max is a tedious but fairly fast sequence of
 14771  // instructions; exactly four comparisons are made in each branch.
 14772  
 14773  // 556.
 14774  
 14775  // tangle:pos ../../mf.web:11886:3:
 14776  
 14777  // The given cubics $B(w_0,w_1,w_2,w_3;t)$ and
 14778  // $B(z_0,z_1,z_2,z_3;t)$ are specified in adjacent knot nodes |(p,link(p))|
 14779  // and |(pp,link(pp))|, respectively.
 14780  func (prg *prg) cubicIntersection(p, pp halfword) {
 14781  	var (
 14782  		q, qq halfword // |link(p)|, |link(pp)|
 14783  	)
 14784  	prg.timeToGo = maxPatience
 14785  	prg.maxT = 2
 14786  
 14787  	// Initialize for intersections at level zero
 14788  	q = *(*prg.mem[p].hh()).rh()
 14789  	qq = *(*prg.mem[pp].hh()).rh()
 14790  	prg.bisectPtr = uint16(intPackets)
 14791  
 14792  	prg.bisectStack[int32(prg.bisectPtr)-5] = *prg.mem[int32(p)+5].int() - *prg.mem[int32(p)+1].int()
 14793  	prg.bisectStack[int32(prg.bisectPtr)-5+1] = *prg.mem[int32(q)+3].int() - *prg.mem[int32(p)+5].int()
 14794  	prg.bisectStack[int32(prg.bisectPtr)-5+2] = *prg.mem[int32(q)+1].int() - *prg.mem[int32(q)+3].int()
 14795  	if prg.bisectStack[int32(prg.bisectPtr)-5] < 0 {
 14796  		if prg.bisectStack[int32(prg.bisectPtr)-5+2] >= 0 {
 14797  			if prg.bisectStack[int32(prg.bisectPtr)-5+1] < 0 {
 14798  				prg.bisectStack[int32(prg.bisectPtr)-5+3] = prg.bisectStack[int32(prg.bisectPtr)-5] + prg.bisectStack[int32(prg.bisectPtr)-5+1]
 14799  			} else {
 14800  				prg.bisectStack[int32(prg.bisectPtr)-5+3] = prg.bisectStack[int32(prg.bisectPtr)-5]
 14801  			}
 14802  			prg.bisectStack[int32(prg.bisectPtr)-5+4] = prg.bisectStack[int32(prg.bisectPtr)-5] + prg.bisectStack[int32(prg.bisectPtr)-5+1] + prg.bisectStack[int32(prg.bisectPtr)-5+2]
 14803  			if prg.bisectStack[int32(prg.bisectPtr)-5+4] < 0 {
 14804  				prg.bisectStack[int32(prg.bisectPtr)-5+4] = 0
 14805  			}
 14806  		} else {
 14807  			prg.bisectStack[int32(prg.bisectPtr)-5+3] = prg.bisectStack[int32(prg.bisectPtr)-5] + prg.bisectStack[int32(prg.bisectPtr)-5+1] + prg.bisectStack[int32(prg.bisectPtr)-5+2]
 14808  			if prg.bisectStack[int32(prg.bisectPtr)-5+3] > prg.bisectStack[int32(prg.bisectPtr)-5] {
 14809  				prg.bisectStack[int32(prg.bisectPtr)-5+3] = prg.bisectStack[int32(prg.bisectPtr)-5]
 14810  			}
 14811  			prg.bisectStack[int32(prg.bisectPtr)-5+4] = prg.bisectStack[int32(prg.bisectPtr)-5] + prg.bisectStack[int32(prg.bisectPtr)-5+1]
 14812  			if prg.bisectStack[int32(prg.bisectPtr)-5+4] < 0 {
 14813  				prg.bisectStack[int32(prg.bisectPtr)-5+4] = 0
 14814  			}
 14815  		}
 14816  	} else if prg.bisectStack[int32(prg.bisectPtr)-5+2] <= 0 {
 14817  		if prg.bisectStack[int32(prg.bisectPtr)-5+1] > 0 {
 14818  			prg.bisectStack[int32(prg.bisectPtr)-5+4] = prg.bisectStack[int32(prg.bisectPtr)-5] + prg.bisectStack[int32(prg.bisectPtr)-5+1]
 14819  		} else {
 14820  			prg.bisectStack[int32(prg.bisectPtr)-5+4] = prg.bisectStack[int32(prg.bisectPtr)-5]
 14821  		}
 14822  		prg.bisectStack[int32(prg.bisectPtr)-5+3] = prg.bisectStack[int32(prg.bisectPtr)-5] + prg.bisectStack[int32(prg.bisectPtr)-5+1] + prg.bisectStack[int32(prg.bisectPtr)-5+2]
 14823  		if prg.bisectStack[int32(prg.bisectPtr)-5+3] > 0 {
 14824  			prg.bisectStack[int32(prg.bisectPtr)-5+3] = 0
 14825  		}
 14826  	} else {
 14827  		prg.bisectStack[int32(prg.bisectPtr)-5+4] = prg.bisectStack[int32(prg.bisectPtr)-5] + prg.bisectStack[int32(prg.bisectPtr)-5+1] + prg.bisectStack[int32(prg.bisectPtr)-5+2]
 14828  		if prg.bisectStack[int32(prg.bisectPtr)-5+4] < prg.bisectStack[int32(prg.bisectPtr)-5] {
 14829  			prg.bisectStack[int32(prg.bisectPtr)-5+4] = prg.bisectStack[int32(prg.bisectPtr)-5]
 14830  		}
 14831  		prg.bisectStack[int32(prg.bisectPtr)-5+3] = prg.bisectStack[int32(prg.bisectPtr)-5] + prg.bisectStack[int32(prg.bisectPtr)-5+1]
 14832  		if prg.bisectStack[int32(prg.bisectPtr)-5+3] > 0 {
 14833  			prg.bisectStack[int32(prg.bisectPtr)-5+3] = 0
 14834  		}
 14835  	}
 14836  
 14837  	prg.bisectStack[int32(prg.bisectPtr)-10] = *prg.mem[int32(p)+6].int() - *prg.mem[int32(p)+2].int()
 14838  	prg.bisectStack[int32(prg.bisectPtr)-10+1] = *prg.mem[int32(q)+4].int() - *prg.mem[int32(p)+6].int()
 14839  	prg.bisectStack[int32(prg.bisectPtr)-10+2] = *prg.mem[int32(q)+2].int() - *prg.mem[int32(q)+4].int()
 14840  	if prg.bisectStack[int32(prg.bisectPtr)-10] < 0 {
 14841  		if prg.bisectStack[int32(prg.bisectPtr)-10+2] >= 0 {
 14842  			if prg.bisectStack[int32(prg.bisectPtr)-10+1] < 0 {
 14843  				prg.bisectStack[int32(prg.bisectPtr)-10+3] = prg.bisectStack[int32(prg.bisectPtr)-10] + prg.bisectStack[int32(prg.bisectPtr)-10+1]
 14844  			} else {
 14845  				prg.bisectStack[int32(prg.bisectPtr)-10+3] = prg.bisectStack[int32(prg.bisectPtr)-10]
 14846  			}
 14847  			prg.bisectStack[int32(prg.bisectPtr)-10+4] = prg.bisectStack[int32(prg.bisectPtr)-10] + prg.bisectStack[int32(prg.bisectPtr)-10+1] + prg.bisectStack[int32(prg.bisectPtr)-10+2]
 14848  			if prg.bisectStack[int32(prg.bisectPtr)-10+4] < 0 {
 14849  				prg.bisectStack[int32(prg.bisectPtr)-10+4] = 0
 14850  			}
 14851  		} else {
 14852  			prg.bisectStack[int32(prg.bisectPtr)-10+3] = prg.bisectStack[int32(prg.bisectPtr)-10] + prg.bisectStack[int32(prg.bisectPtr)-10+1] + prg.bisectStack[int32(prg.bisectPtr)-10+2]
 14853  			if prg.bisectStack[int32(prg.bisectPtr)-10+3] > prg.bisectStack[int32(prg.bisectPtr)-10] {
 14854  				prg.bisectStack[int32(prg.bisectPtr)-10+3] = prg.bisectStack[int32(prg.bisectPtr)-10]
 14855  			}
 14856  			prg.bisectStack[int32(prg.bisectPtr)-10+4] = prg.bisectStack[int32(prg.bisectPtr)-10] + prg.bisectStack[int32(prg.bisectPtr)-10+1]
 14857  			if prg.bisectStack[int32(prg.bisectPtr)-10+4] < 0 {
 14858  				prg.bisectStack[int32(prg.bisectPtr)-10+4] = 0
 14859  			}
 14860  		}
 14861  	} else if prg.bisectStack[int32(prg.bisectPtr)-10+2] <= 0 {
 14862  		if prg.bisectStack[int32(prg.bisectPtr)-10+1] > 0 {
 14863  			prg.bisectStack[int32(prg.bisectPtr)-10+4] = prg.bisectStack[int32(prg.bisectPtr)-10] + prg.bisectStack[int32(prg.bisectPtr)-10+1]
 14864  		} else {
 14865  			prg.bisectStack[int32(prg.bisectPtr)-10+4] = prg.bisectStack[int32(prg.bisectPtr)-10]
 14866  		}
 14867  		prg.bisectStack[int32(prg.bisectPtr)-10+3] = prg.bisectStack[int32(prg.bisectPtr)-10] + prg.bisectStack[int32(prg.bisectPtr)-10+1] + prg.bisectStack[int32(prg.bisectPtr)-10+2]
 14868  		if prg.bisectStack[int32(prg.bisectPtr)-10+3] > 0 {
 14869  			prg.bisectStack[int32(prg.bisectPtr)-10+3] = 0
 14870  		}
 14871  	} else {
 14872  		prg.bisectStack[int32(prg.bisectPtr)-10+4] = prg.bisectStack[int32(prg.bisectPtr)-10] + prg.bisectStack[int32(prg.bisectPtr)-10+1] + prg.bisectStack[int32(prg.bisectPtr)-10+2]
 14873  		if prg.bisectStack[int32(prg.bisectPtr)-10+4] < prg.bisectStack[int32(prg.bisectPtr)-10] {
 14874  			prg.bisectStack[int32(prg.bisectPtr)-10+4] = prg.bisectStack[int32(prg.bisectPtr)-10]
 14875  		}
 14876  		prg.bisectStack[int32(prg.bisectPtr)-10+3] = prg.bisectStack[int32(prg.bisectPtr)-10] + prg.bisectStack[int32(prg.bisectPtr)-10+1]
 14877  		if prg.bisectStack[int32(prg.bisectPtr)-10+3] > 0 {
 14878  			prg.bisectStack[int32(prg.bisectPtr)-10+3] = 0
 14879  		}
 14880  	}
 14881  
 14882  	prg.bisectStack[int32(prg.bisectPtr)-15] = *prg.mem[int32(pp)+5].int() - *prg.mem[int32(pp)+1].int()
 14883  	prg.bisectStack[int32(prg.bisectPtr)-15+1] = *prg.mem[int32(qq)+3].int() - *prg.mem[int32(pp)+5].int()
 14884  	prg.bisectStack[int32(prg.bisectPtr)-15+2] = *prg.mem[int32(qq)+1].int() - *prg.mem[int32(qq)+3].int()
 14885  	if prg.bisectStack[int32(prg.bisectPtr)-15] < 0 {
 14886  		if prg.bisectStack[int32(prg.bisectPtr)-15+2] >= 0 {
 14887  			if prg.bisectStack[int32(prg.bisectPtr)-15+1] < 0 {
 14888  				prg.bisectStack[int32(prg.bisectPtr)-15+3] = prg.bisectStack[int32(prg.bisectPtr)-15] + prg.bisectStack[int32(prg.bisectPtr)-15+1]
 14889  			} else {
 14890  				prg.bisectStack[int32(prg.bisectPtr)-15+3] = prg.bisectStack[int32(prg.bisectPtr)-15]
 14891  			}
 14892  			prg.bisectStack[int32(prg.bisectPtr)-15+4] = prg.bisectStack[int32(prg.bisectPtr)-15] + prg.bisectStack[int32(prg.bisectPtr)-15+1] + prg.bisectStack[int32(prg.bisectPtr)-15+2]
 14893  			if prg.bisectStack[int32(prg.bisectPtr)-15+4] < 0 {
 14894  				prg.bisectStack[int32(prg.bisectPtr)-15+4] = 0
 14895  			}
 14896  		} else {
 14897  			prg.bisectStack[int32(prg.bisectPtr)-15+3] = prg.bisectStack[int32(prg.bisectPtr)-15] + prg.bisectStack[int32(prg.bisectPtr)-15+1] + prg.bisectStack[int32(prg.bisectPtr)-15+2]
 14898  			if prg.bisectStack[int32(prg.bisectPtr)-15+3] > prg.bisectStack[int32(prg.bisectPtr)-15] {
 14899  				prg.bisectStack[int32(prg.bisectPtr)-15+3] = prg.bisectStack[int32(prg.bisectPtr)-15]
 14900  			}
 14901  			prg.bisectStack[int32(prg.bisectPtr)-15+4] = prg.bisectStack[int32(prg.bisectPtr)-15] + prg.bisectStack[int32(prg.bisectPtr)-15+1]
 14902  			if prg.bisectStack[int32(prg.bisectPtr)-15+4] < 0 {
 14903  				prg.bisectStack[int32(prg.bisectPtr)-15+4] = 0
 14904  			}
 14905  		}
 14906  	} else if prg.bisectStack[int32(prg.bisectPtr)-15+2] <= 0 {
 14907  		if prg.bisectStack[int32(prg.bisectPtr)-15+1] > 0 {
 14908  			prg.bisectStack[int32(prg.bisectPtr)-15+4] = prg.bisectStack[int32(prg.bisectPtr)-15] + prg.bisectStack[int32(prg.bisectPtr)-15+1]
 14909  		} else {
 14910  			prg.bisectStack[int32(prg.bisectPtr)-15+4] = prg.bisectStack[int32(prg.bisectPtr)-15]
 14911  		}
 14912  		prg.bisectStack[int32(prg.bisectPtr)-15+3] = prg.bisectStack[int32(prg.bisectPtr)-15] + prg.bisectStack[int32(prg.bisectPtr)-15+1] + prg.bisectStack[int32(prg.bisectPtr)-15+2]
 14913  		if prg.bisectStack[int32(prg.bisectPtr)-15+3] > 0 {
 14914  			prg.bisectStack[int32(prg.bisectPtr)-15+3] = 0
 14915  		}
 14916  	} else {
 14917  		prg.bisectStack[int32(prg.bisectPtr)-15+4] = prg.bisectStack[int32(prg.bisectPtr)-15] + prg.bisectStack[int32(prg.bisectPtr)-15+1] + prg.bisectStack[int32(prg.bisectPtr)-15+2]
 14918  		if prg.bisectStack[int32(prg.bisectPtr)-15+4] < prg.bisectStack[int32(prg.bisectPtr)-15] {
 14919  			prg.bisectStack[int32(prg.bisectPtr)-15+4] = prg.bisectStack[int32(prg.bisectPtr)-15]
 14920  		}
 14921  		prg.bisectStack[int32(prg.bisectPtr)-15+3] = prg.bisectStack[int32(prg.bisectPtr)-15] + prg.bisectStack[int32(prg.bisectPtr)-15+1]
 14922  		if prg.bisectStack[int32(prg.bisectPtr)-15+3] > 0 {
 14923  			prg.bisectStack[int32(prg.bisectPtr)-15+3] = 0
 14924  		}
 14925  	}
 14926  
 14927  	prg.bisectStack[int32(prg.bisectPtr)-20] = *prg.mem[int32(pp)+6].int() - *prg.mem[int32(pp)+2].int()
 14928  	prg.bisectStack[int32(prg.bisectPtr)-20+1] = *prg.mem[int32(qq)+4].int() - *prg.mem[int32(pp)+6].int()
 14929  	prg.bisectStack[int32(prg.bisectPtr)-20+2] = *prg.mem[int32(qq)+2].int() - *prg.mem[int32(qq)+4].int()
 14930  	if prg.bisectStack[int32(prg.bisectPtr)-20] < 0 {
 14931  		if prg.bisectStack[int32(prg.bisectPtr)-20+2] >= 0 {
 14932  			if prg.bisectStack[int32(prg.bisectPtr)-20+1] < 0 {
 14933  				prg.bisectStack[int32(prg.bisectPtr)-20+3] = prg.bisectStack[int32(prg.bisectPtr)-20] + prg.bisectStack[int32(prg.bisectPtr)-20+1]
 14934  			} else {
 14935  				prg.bisectStack[int32(prg.bisectPtr)-20+3] = prg.bisectStack[int32(prg.bisectPtr)-20]
 14936  			}
 14937  			prg.bisectStack[int32(prg.bisectPtr)-20+4] = prg.bisectStack[int32(prg.bisectPtr)-20] + prg.bisectStack[int32(prg.bisectPtr)-20+1] + prg.bisectStack[int32(prg.bisectPtr)-20+2]
 14938  			if prg.bisectStack[int32(prg.bisectPtr)-20+4] < 0 {
 14939  				prg.bisectStack[int32(prg.bisectPtr)-20+4] = 0
 14940  			}
 14941  		} else {
 14942  			prg.bisectStack[int32(prg.bisectPtr)-20+3] = prg.bisectStack[int32(prg.bisectPtr)-20] + prg.bisectStack[int32(prg.bisectPtr)-20+1] + prg.bisectStack[int32(prg.bisectPtr)-20+2]
 14943  			if prg.bisectStack[int32(prg.bisectPtr)-20+3] > prg.bisectStack[int32(prg.bisectPtr)-20] {
 14944  				prg.bisectStack[int32(prg.bisectPtr)-20+3] = prg.bisectStack[int32(prg.bisectPtr)-20]
 14945  			}
 14946  			prg.bisectStack[int32(prg.bisectPtr)-20+4] = prg.bisectStack[int32(prg.bisectPtr)-20] + prg.bisectStack[int32(prg.bisectPtr)-20+1]
 14947  			if prg.bisectStack[int32(prg.bisectPtr)-20+4] < 0 {
 14948  				prg.bisectStack[int32(prg.bisectPtr)-20+4] = 0
 14949  			}
 14950  		}
 14951  	} else if prg.bisectStack[int32(prg.bisectPtr)-20+2] <= 0 {
 14952  		if prg.bisectStack[int32(prg.bisectPtr)-20+1] > 0 {
 14953  			prg.bisectStack[int32(prg.bisectPtr)-20+4] = prg.bisectStack[int32(prg.bisectPtr)-20] + prg.bisectStack[int32(prg.bisectPtr)-20+1]
 14954  		} else {
 14955  			prg.bisectStack[int32(prg.bisectPtr)-20+4] = prg.bisectStack[int32(prg.bisectPtr)-20]
 14956  		}
 14957  		prg.bisectStack[int32(prg.bisectPtr)-20+3] = prg.bisectStack[int32(prg.bisectPtr)-20] + prg.bisectStack[int32(prg.bisectPtr)-20+1] + prg.bisectStack[int32(prg.bisectPtr)-20+2]
 14958  		if prg.bisectStack[int32(prg.bisectPtr)-20+3] > 0 {
 14959  			prg.bisectStack[int32(prg.bisectPtr)-20+3] = 0
 14960  		}
 14961  	} else {
 14962  		prg.bisectStack[int32(prg.bisectPtr)-20+4] = prg.bisectStack[int32(prg.bisectPtr)-20] + prg.bisectStack[int32(prg.bisectPtr)-20+1] + prg.bisectStack[int32(prg.bisectPtr)-20+2]
 14963  		if prg.bisectStack[int32(prg.bisectPtr)-20+4] < prg.bisectStack[int32(prg.bisectPtr)-20] {
 14964  			prg.bisectStack[int32(prg.bisectPtr)-20+4] = prg.bisectStack[int32(prg.bisectPtr)-20]
 14965  		}
 14966  		prg.bisectStack[int32(prg.bisectPtr)-20+3] = prg.bisectStack[int32(prg.bisectPtr)-20] + prg.bisectStack[int32(prg.bisectPtr)-20+1]
 14967  		if prg.bisectStack[int32(prg.bisectPtr)-20+3] > 0 {
 14968  			prg.bisectStack[int32(prg.bisectPtr)-20+3] = 0
 14969  		}
 14970  	}
 14971  
 14972  	prg.delx = *prg.mem[int32(p)+1].int() - *prg.mem[int32(pp)+1].int()
 14973  	prg.dely = *prg.mem[int32(p)+2].int() - *prg.mem[int32(pp)+2].int()
 14974  
 14975  	prg.tol = 0
 14976  	prg.uv = prg.bisectPtr
 14977  	prg.xy = prg.bisectPtr
 14978  	prg.threeL = 0
 14979  	prg.curT = 1
 14980  	prg.curTt = 1
 14981  	for true {
 14982  	continue1:
 14983  		if prg.delx-prg.tol <= prg.bisectStack[int32(prg.xy)-15+4]-prg.bisectStack[int32(prg.uv)-5+3] {
 14984  			if prg.delx+prg.tol >= prg.bisectStack[int32(prg.xy)-15+3]-prg.bisectStack[int32(prg.uv)-5+4] {
 14985  				if prg.dely-prg.tol <= prg.bisectStack[int32(prg.xy)-20+4]-prg.bisectStack[int32(prg.uv)-10+3] {
 14986  					if prg.dely+prg.tol >= prg.bisectStack[int32(prg.xy)-20+3]-prg.bisectStack[int32(prg.uv)-10+4] {
 14987  						if prg.curT >= prg.maxT {
 14988  							if prg.maxT == 0400000 {
 14989  								prg.curT = (prg.curT + 1) / 2
 14990  								prg.curTt = (prg.curTt + 1) / 2
 14991  								goto exit
 14992  							}
 14993  							prg.maxT = prg.maxT + prg.maxT
 14994  							prg.apprT = prg.curT
 14995  							prg.apprTt = prg.curTt
 14996  						}
 14997  
 14998  						// Subdivide for a new level of intersection
 14999  						prg.bisectStack[prg.bisectPtr] = prg.delx
 15000  						prg.bisectStack[int32(prg.bisectPtr)+1] = prg.dely
 15001  						prg.bisectStack[int32(prg.bisectPtr)+2] = prg.tol
 15002  						prg.bisectStack[int32(prg.bisectPtr)+3] = int32(prg.uv)
 15003  						prg.bisectStack[int32(prg.bisectPtr)+4] = int32(prg.xy)
 15004  						prg.bisectPtr = uint16(int32(prg.bisectPtr) + intIncrement)
 15005  
 15006  						prg.curT = prg.curT + prg.curT
 15007  						prg.curTt = prg.curTt + prg.curTt
 15008  
 15009  						prg.bisectStack[int32(prg.bisectPtr)-intPackets-5] = prg.bisectStack[int32(prg.uv)-5]
 15010  						prg.bisectStack[int32(prg.bisectPtr)-5+2] = prg.bisectStack[int32(prg.uv)-5+2]
 15011  						prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+1] = (prg.bisectStack[int32(prg.bisectPtr)-intPackets-5] + prg.bisectStack[int32(prg.uv)-5+1]) / 2
 15012  						prg.bisectStack[int32(prg.bisectPtr)-5+1] = (prg.bisectStack[int32(prg.bisectPtr)-5+2] + prg.bisectStack[int32(prg.uv)-5+1]) / 2
 15013  						prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+2] = (prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+1] + prg.bisectStack[int32(prg.bisectPtr)-5+1]) / 2
 15014  						prg.bisectStack[int32(prg.bisectPtr)-5] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+2]
 15015  						if prg.bisectStack[int32(prg.bisectPtr)-intPackets-5] < 0 {
 15016  							if prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+2] >= 0 {
 15017  								if prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+1] < 0 {
 15018  									prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+3] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-5] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+1]
 15019  								} else {
 15020  									prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+3] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-5]
 15021  								}
 15022  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+4] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-5] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+1] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+2]
 15023  								if prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+4] < 0 {
 15024  									prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+4] = 0
 15025  								}
 15026  							} else {
 15027  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+3] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-5] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+1] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+2]
 15028  								if prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+3] > prg.bisectStack[int32(prg.bisectPtr)-intPackets-5] {
 15029  									prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+3] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-5]
 15030  								}
 15031  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+4] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-5] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+1]
 15032  								if prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+4] < 0 {
 15033  									prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+4] = 0
 15034  								}
 15035  							}
 15036  						} else if prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+2] <= 0 {
 15037  							if prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+1] > 0 {
 15038  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+4] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-5] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+1]
 15039  							} else {
 15040  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+4] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-5]
 15041  							}
 15042  							prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+3] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-5] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+1] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+2]
 15043  							if prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+3] > 0 {
 15044  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+3] = 0
 15045  							}
 15046  						} else {
 15047  							prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+4] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-5] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+1] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+2]
 15048  							if prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+4] < prg.bisectStack[int32(prg.bisectPtr)-intPackets-5] {
 15049  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+4] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-5]
 15050  							}
 15051  							prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+3] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-5] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+1]
 15052  							if prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+3] > 0 {
 15053  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-5+3] = 0
 15054  							}
 15055  						}
 15056  						if prg.bisectStack[int32(prg.bisectPtr)-5] < 0 {
 15057  							if prg.bisectStack[int32(prg.bisectPtr)-5+2] >= 0 {
 15058  								if prg.bisectStack[int32(prg.bisectPtr)-5+1] < 0 {
 15059  									prg.bisectStack[int32(prg.bisectPtr)-5+3] = prg.bisectStack[int32(prg.bisectPtr)-5] + prg.bisectStack[int32(prg.bisectPtr)-5+1]
 15060  								} else {
 15061  									prg.bisectStack[int32(prg.bisectPtr)-5+3] = prg.bisectStack[int32(prg.bisectPtr)-5]
 15062  								}
 15063  								prg.bisectStack[int32(prg.bisectPtr)-5+4] = prg.bisectStack[int32(prg.bisectPtr)-5] + prg.bisectStack[int32(prg.bisectPtr)-5+1] + prg.bisectStack[int32(prg.bisectPtr)-5+2]
 15064  								if prg.bisectStack[int32(prg.bisectPtr)-5+4] < 0 {
 15065  									prg.bisectStack[int32(prg.bisectPtr)-5+4] = 0
 15066  								}
 15067  							} else {
 15068  								prg.bisectStack[int32(prg.bisectPtr)-5+3] = prg.bisectStack[int32(prg.bisectPtr)-5] + prg.bisectStack[int32(prg.bisectPtr)-5+1] + prg.bisectStack[int32(prg.bisectPtr)-5+2]
 15069  								if prg.bisectStack[int32(prg.bisectPtr)-5+3] > prg.bisectStack[int32(prg.bisectPtr)-5] {
 15070  									prg.bisectStack[int32(prg.bisectPtr)-5+3] = prg.bisectStack[int32(prg.bisectPtr)-5]
 15071  								}
 15072  								prg.bisectStack[int32(prg.bisectPtr)-5+4] = prg.bisectStack[int32(prg.bisectPtr)-5] + prg.bisectStack[int32(prg.bisectPtr)-5+1]
 15073  								if prg.bisectStack[int32(prg.bisectPtr)-5+4] < 0 {
 15074  									prg.bisectStack[int32(prg.bisectPtr)-5+4] = 0
 15075  								}
 15076  							}
 15077  						} else if prg.bisectStack[int32(prg.bisectPtr)-5+2] <= 0 {
 15078  							if prg.bisectStack[int32(prg.bisectPtr)-5+1] > 0 {
 15079  								prg.bisectStack[int32(prg.bisectPtr)-5+4] = prg.bisectStack[int32(prg.bisectPtr)-5] + prg.bisectStack[int32(prg.bisectPtr)-5+1]
 15080  							} else {
 15081  								prg.bisectStack[int32(prg.bisectPtr)-5+4] = prg.bisectStack[int32(prg.bisectPtr)-5]
 15082  							}
 15083  							prg.bisectStack[int32(prg.bisectPtr)-5+3] = prg.bisectStack[int32(prg.bisectPtr)-5] + prg.bisectStack[int32(prg.bisectPtr)-5+1] + prg.bisectStack[int32(prg.bisectPtr)-5+2]
 15084  							if prg.bisectStack[int32(prg.bisectPtr)-5+3] > 0 {
 15085  								prg.bisectStack[int32(prg.bisectPtr)-5+3] = 0
 15086  							}
 15087  						} else {
 15088  							prg.bisectStack[int32(prg.bisectPtr)-5+4] = prg.bisectStack[int32(prg.bisectPtr)-5] + prg.bisectStack[int32(prg.bisectPtr)-5+1] + prg.bisectStack[int32(prg.bisectPtr)-5+2]
 15089  							if prg.bisectStack[int32(prg.bisectPtr)-5+4] < prg.bisectStack[int32(prg.bisectPtr)-5] {
 15090  								prg.bisectStack[int32(prg.bisectPtr)-5+4] = prg.bisectStack[int32(prg.bisectPtr)-5]
 15091  							}
 15092  							prg.bisectStack[int32(prg.bisectPtr)-5+3] = prg.bisectStack[int32(prg.bisectPtr)-5] + prg.bisectStack[int32(prg.bisectPtr)-5+1]
 15093  							if prg.bisectStack[int32(prg.bisectPtr)-5+3] > 0 {
 15094  								prg.bisectStack[int32(prg.bisectPtr)-5+3] = 0
 15095  							}
 15096  						}
 15097  
 15098  						prg.bisectStack[int32(prg.bisectPtr)-intPackets-10] = prg.bisectStack[int32(prg.uv)-10]
 15099  						prg.bisectStack[int32(prg.bisectPtr)-10+2] = prg.bisectStack[int32(prg.uv)-10+2]
 15100  						prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+1] = (prg.bisectStack[int32(prg.bisectPtr)-intPackets-10] + prg.bisectStack[int32(prg.uv)-10+1]) / 2
 15101  						prg.bisectStack[int32(prg.bisectPtr)-10+1] = (prg.bisectStack[int32(prg.bisectPtr)-10+2] + prg.bisectStack[int32(prg.uv)-10+1]) / 2
 15102  						prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+2] = (prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+1] + prg.bisectStack[int32(prg.bisectPtr)-10+1]) / 2
 15103  						prg.bisectStack[int32(prg.bisectPtr)-10] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+2]
 15104  						if prg.bisectStack[int32(prg.bisectPtr)-intPackets-10] < 0 {
 15105  							if prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+2] >= 0 {
 15106  								if prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+1] < 0 {
 15107  									prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+3] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-10] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+1]
 15108  								} else {
 15109  									prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+3] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-10]
 15110  								}
 15111  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+4] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-10] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+1] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+2]
 15112  								if prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+4] < 0 {
 15113  									prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+4] = 0
 15114  								}
 15115  							} else {
 15116  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+3] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-10] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+1] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+2]
 15117  								if prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+3] > prg.bisectStack[int32(prg.bisectPtr)-intPackets-10] {
 15118  									prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+3] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-10]
 15119  								}
 15120  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+4] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-10] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+1]
 15121  								if prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+4] < 0 {
 15122  									prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+4] = 0
 15123  								}
 15124  							}
 15125  						} else if prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+2] <= 0 {
 15126  							if prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+1] > 0 {
 15127  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+4] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-10] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+1]
 15128  							} else {
 15129  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+4] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-10]
 15130  							}
 15131  							prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+3] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-10] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+1] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+2]
 15132  							if prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+3] > 0 {
 15133  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+3] = 0
 15134  							}
 15135  						} else {
 15136  							prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+4] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-10] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+1] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+2]
 15137  							if prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+4] < prg.bisectStack[int32(prg.bisectPtr)-intPackets-10] {
 15138  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+4] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-10]
 15139  							}
 15140  							prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+3] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-10] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+1]
 15141  							if prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+3] > 0 {
 15142  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-10+3] = 0
 15143  							}
 15144  						}
 15145  						if prg.bisectStack[int32(prg.bisectPtr)-10] < 0 {
 15146  							if prg.bisectStack[int32(prg.bisectPtr)-10+2] >= 0 {
 15147  								if prg.bisectStack[int32(prg.bisectPtr)-10+1] < 0 {
 15148  									prg.bisectStack[int32(prg.bisectPtr)-10+3] = prg.bisectStack[int32(prg.bisectPtr)-10] + prg.bisectStack[int32(prg.bisectPtr)-10+1]
 15149  								} else {
 15150  									prg.bisectStack[int32(prg.bisectPtr)-10+3] = prg.bisectStack[int32(prg.bisectPtr)-10]
 15151  								}
 15152  								prg.bisectStack[int32(prg.bisectPtr)-10+4] = prg.bisectStack[int32(prg.bisectPtr)-10] + prg.bisectStack[int32(prg.bisectPtr)-10+1] + prg.bisectStack[int32(prg.bisectPtr)-10+2]
 15153  								if prg.bisectStack[int32(prg.bisectPtr)-10+4] < 0 {
 15154  									prg.bisectStack[int32(prg.bisectPtr)-10+4] = 0
 15155  								}
 15156  							} else {
 15157  								prg.bisectStack[int32(prg.bisectPtr)-10+3] = prg.bisectStack[int32(prg.bisectPtr)-10] + prg.bisectStack[int32(prg.bisectPtr)-10+1] + prg.bisectStack[int32(prg.bisectPtr)-10+2]
 15158  								if prg.bisectStack[int32(prg.bisectPtr)-10+3] > prg.bisectStack[int32(prg.bisectPtr)-10] {
 15159  									prg.bisectStack[int32(prg.bisectPtr)-10+3] = prg.bisectStack[int32(prg.bisectPtr)-10]
 15160  								}
 15161  								prg.bisectStack[int32(prg.bisectPtr)-10+4] = prg.bisectStack[int32(prg.bisectPtr)-10] + prg.bisectStack[int32(prg.bisectPtr)-10+1]
 15162  								if prg.bisectStack[int32(prg.bisectPtr)-10+4] < 0 {
 15163  									prg.bisectStack[int32(prg.bisectPtr)-10+4] = 0
 15164  								}
 15165  							}
 15166  						} else if prg.bisectStack[int32(prg.bisectPtr)-10+2] <= 0 {
 15167  							if prg.bisectStack[int32(prg.bisectPtr)-10+1] > 0 {
 15168  								prg.bisectStack[int32(prg.bisectPtr)-10+4] = prg.bisectStack[int32(prg.bisectPtr)-10] + prg.bisectStack[int32(prg.bisectPtr)-10+1]
 15169  							} else {
 15170  								prg.bisectStack[int32(prg.bisectPtr)-10+4] = prg.bisectStack[int32(prg.bisectPtr)-10]
 15171  							}
 15172  							prg.bisectStack[int32(prg.bisectPtr)-10+3] = prg.bisectStack[int32(prg.bisectPtr)-10] + prg.bisectStack[int32(prg.bisectPtr)-10+1] + prg.bisectStack[int32(prg.bisectPtr)-10+2]
 15173  							if prg.bisectStack[int32(prg.bisectPtr)-10+3] > 0 {
 15174  								prg.bisectStack[int32(prg.bisectPtr)-10+3] = 0
 15175  							}
 15176  						} else {
 15177  							prg.bisectStack[int32(prg.bisectPtr)-10+4] = prg.bisectStack[int32(prg.bisectPtr)-10] + prg.bisectStack[int32(prg.bisectPtr)-10+1] + prg.bisectStack[int32(prg.bisectPtr)-10+2]
 15178  							if prg.bisectStack[int32(prg.bisectPtr)-10+4] < prg.bisectStack[int32(prg.bisectPtr)-10] {
 15179  								prg.bisectStack[int32(prg.bisectPtr)-10+4] = prg.bisectStack[int32(prg.bisectPtr)-10]
 15180  							}
 15181  							prg.bisectStack[int32(prg.bisectPtr)-10+3] = prg.bisectStack[int32(prg.bisectPtr)-10] + prg.bisectStack[int32(prg.bisectPtr)-10+1]
 15182  							if prg.bisectStack[int32(prg.bisectPtr)-10+3] > 0 {
 15183  								prg.bisectStack[int32(prg.bisectPtr)-10+3] = 0
 15184  							}
 15185  						}
 15186  
 15187  						prg.bisectStack[int32(prg.bisectPtr)-intPackets-15] = prg.bisectStack[int32(prg.xy)-15]
 15188  						prg.bisectStack[int32(prg.bisectPtr)-15+2] = prg.bisectStack[int32(prg.xy)-15+2]
 15189  						prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+1] = (prg.bisectStack[int32(prg.bisectPtr)-intPackets-15] + prg.bisectStack[int32(prg.xy)-15+1]) / 2
 15190  						prg.bisectStack[int32(prg.bisectPtr)-15+1] = (prg.bisectStack[int32(prg.bisectPtr)-15+2] + prg.bisectStack[int32(prg.xy)-15+1]) / 2
 15191  						prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+2] = (prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+1] + prg.bisectStack[int32(prg.bisectPtr)-15+1]) / 2
 15192  						prg.bisectStack[int32(prg.bisectPtr)-15] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+2]
 15193  						if prg.bisectStack[int32(prg.bisectPtr)-intPackets-15] < 0 {
 15194  							if prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+2] >= 0 {
 15195  								if prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+1] < 0 {
 15196  									prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+3] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-15] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+1]
 15197  								} else {
 15198  									prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+3] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-15]
 15199  								}
 15200  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+4] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-15] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+1] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+2]
 15201  								if prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+4] < 0 {
 15202  									prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+4] = 0
 15203  								}
 15204  							} else {
 15205  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+3] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-15] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+1] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+2]
 15206  								if prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+3] > prg.bisectStack[int32(prg.bisectPtr)-intPackets-15] {
 15207  									prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+3] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-15]
 15208  								}
 15209  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+4] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-15] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+1]
 15210  								if prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+4] < 0 {
 15211  									prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+4] = 0
 15212  								}
 15213  							}
 15214  						} else if prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+2] <= 0 {
 15215  							if prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+1] > 0 {
 15216  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+4] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-15] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+1]
 15217  							} else {
 15218  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+4] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-15]
 15219  							}
 15220  							prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+3] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-15] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+1] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+2]
 15221  							if prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+3] > 0 {
 15222  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+3] = 0
 15223  							}
 15224  						} else {
 15225  							prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+4] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-15] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+1] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+2]
 15226  							if prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+4] < prg.bisectStack[int32(prg.bisectPtr)-intPackets-15] {
 15227  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+4] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-15]
 15228  							}
 15229  							prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+3] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-15] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+1]
 15230  							if prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+3] > 0 {
 15231  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-15+3] = 0
 15232  							}
 15233  						}
 15234  						if prg.bisectStack[int32(prg.bisectPtr)-15] < 0 {
 15235  							if prg.bisectStack[int32(prg.bisectPtr)-15+2] >= 0 {
 15236  								if prg.bisectStack[int32(prg.bisectPtr)-15+1] < 0 {
 15237  									prg.bisectStack[int32(prg.bisectPtr)-15+3] = prg.bisectStack[int32(prg.bisectPtr)-15] + prg.bisectStack[int32(prg.bisectPtr)-15+1]
 15238  								} else {
 15239  									prg.bisectStack[int32(prg.bisectPtr)-15+3] = prg.bisectStack[int32(prg.bisectPtr)-15]
 15240  								}
 15241  								prg.bisectStack[int32(prg.bisectPtr)-15+4] = prg.bisectStack[int32(prg.bisectPtr)-15] + prg.bisectStack[int32(prg.bisectPtr)-15+1] + prg.bisectStack[int32(prg.bisectPtr)-15+2]
 15242  								if prg.bisectStack[int32(prg.bisectPtr)-15+4] < 0 {
 15243  									prg.bisectStack[int32(prg.bisectPtr)-15+4] = 0
 15244  								}
 15245  							} else {
 15246  								prg.bisectStack[int32(prg.bisectPtr)-15+3] = prg.bisectStack[int32(prg.bisectPtr)-15] + prg.bisectStack[int32(prg.bisectPtr)-15+1] + prg.bisectStack[int32(prg.bisectPtr)-15+2]
 15247  								if prg.bisectStack[int32(prg.bisectPtr)-15+3] > prg.bisectStack[int32(prg.bisectPtr)-15] {
 15248  									prg.bisectStack[int32(prg.bisectPtr)-15+3] = prg.bisectStack[int32(prg.bisectPtr)-15]
 15249  								}
 15250  								prg.bisectStack[int32(prg.bisectPtr)-15+4] = prg.bisectStack[int32(prg.bisectPtr)-15] + prg.bisectStack[int32(prg.bisectPtr)-15+1]
 15251  								if prg.bisectStack[int32(prg.bisectPtr)-15+4] < 0 {
 15252  									prg.bisectStack[int32(prg.bisectPtr)-15+4] = 0
 15253  								}
 15254  							}
 15255  						} else if prg.bisectStack[int32(prg.bisectPtr)-15+2] <= 0 {
 15256  							if prg.bisectStack[int32(prg.bisectPtr)-15+1] > 0 {
 15257  								prg.bisectStack[int32(prg.bisectPtr)-15+4] = prg.bisectStack[int32(prg.bisectPtr)-15] + prg.bisectStack[int32(prg.bisectPtr)-15+1]
 15258  							} else {
 15259  								prg.bisectStack[int32(prg.bisectPtr)-15+4] = prg.bisectStack[int32(prg.bisectPtr)-15]
 15260  							}
 15261  							prg.bisectStack[int32(prg.bisectPtr)-15+3] = prg.bisectStack[int32(prg.bisectPtr)-15] + prg.bisectStack[int32(prg.bisectPtr)-15+1] + prg.bisectStack[int32(prg.bisectPtr)-15+2]
 15262  							if prg.bisectStack[int32(prg.bisectPtr)-15+3] > 0 {
 15263  								prg.bisectStack[int32(prg.bisectPtr)-15+3] = 0
 15264  							}
 15265  						} else {
 15266  							prg.bisectStack[int32(prg.bisectPtr)-15+4] = prg.bisectStack[int32(prg.bisectPtr)-15] + prg.bisectStack[int32(prg.bisectPtr)-15+1] + prg.bisectStack[int32(prg.bisectPtr)-15+2]
 15267  							if prg.bisectStack[int32(prg.bisectPtr)-15+4] < prg.bisectStack[int32(prg.bisectPtr)-15] {
 15268  								prg.bisectStack[int32(prg.bisectPtr)-15+4] = prg.bisectStack[int32(prg.bisectPtr)-15]
 15269  							}
 15270  							prg.bisectStack[int32(prg.bisectPtr)-15+3] = prg.bisectStack[int32(prg.bisectPtr)-15] + prg.bisectStack[int32(prg.bisectPtr)-15+1]
 15271  							if prg.bisectStack[int32(prg.bisectPtr)-15+3] > 0 {
 15272  								prg.bisectStack[int32(prg.bisectPtr)-15+3] = 0
 15273  							}
 15274  						}
 15275  
 15276  						prg.bisectStack[int32(prg.bisectPtr)-intPackets-20] = prg.bisectStack[int32(prg.xy)-20]
 15277  						prg.bisectStack[int32(prg.bisectPtr)-20+2] = prg.bisectStack[int32(prg.xy)-20+2]
 15278  						prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+1] = (prg.bisectStack[int32(prg.bisectPtr)-intPackets-20] + prg.bisectStack[int32(prg.xy)-20+1]) / 2
 15279  						prg.bisectStack[int32(prg.bisectPtr)-20+1] = (prg.bisectStack[int32(prg.bisectPtr)-20+2] + prg.bisectStack[int32(prg.xy)-20+1]) / 2
 15280  						prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+2] = (prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+1] + prg.bisectStack[int32(prg.bisectPtr)-20+1]) / 2
 15281  						prg.bisectStack[int32(prg.bisectPtr)-20] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+2]
 15282  						if prg.bisectStack[int32(prg.bisectPtr)-intPackets-20] < 0 {
 15283  							if prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+2] >= 0 {
 15284  								if prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+1] < 0 {
 15285  									prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+3] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-20] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+1]
 15286  								} else {
 15287  									prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+3] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-20]
 15288  								}
 15289  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+4] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-20] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+1] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+2]
 15290  								if prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+4] < 0 {
 15291  									prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+4] = 0
 15292  								}
 15293  							} else {
 15294  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+3] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-20] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+1] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+2]
 15295  								if prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+3] > prg.bisectStack[int32(prg.bisectPtr)-intPackets-20] {
 15296  									prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+3] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-20]
 15297  								}
 15298  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+4] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-20] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+1]
 15299  								if prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+4] < 0 {
 15300  									prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+4] = 0
 15301  								}
 15302  							}
 15303  						} else if prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+2] <= 0 {
 15304  							if prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+1] > 0 {
 15305  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+4] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-20] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+1]
 15306  							} else {
 15307  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+4] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-20]
 15308  							}
 15309  							prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+3] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-20] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+1] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+2]
 15310  							if prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+3] > 0 {
 15311  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+3] = 0
 15312  							}
 15313  						} else {
 15314  							prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+4] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-20] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+1] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+2]
 15315  							if prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+4] < prg.bisectStack[int32(prg.bisectPtr)-intPackets-20] {
 15316  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+4] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-20]
 15317  							}
 15318  							prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+3] = prg.bisectStack[int32(prg.bisectPtr)-intPackets-20] + prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+1]
 15319  							if prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+3] > 0 {
 15320  								prg.bisectStack[int32(prg.bisectPtr)-intPackets-20+3] = 0
 15321  							}
 15322  						}
 15323  						if prg.bisectStack[int32(prg.bisectPtr)-20] < 0 {
 15324  							if prg.bisectStack[int32(prg.bisectPtr)-20+2] >= 0 {
 15325  								if prg.bisectStack[int32(prg.bisectPtr)-20+1] < 0 {
 15326  									prg.bisectStack[int32(prg.bisectPtr)-20+3] = prg.bisectStack[int32(prg.bisectPtr)-20] + prg.bisectStack[int32(prg.bisectPtr)-20+1]
 15327  								} else {
 15328  									prg.bisectStack[int32(prg.bisectPtr)-20+3] = prg.bisectStack[int32(prg.bisectPtr)-20]
 15329  								}
 15330  								prg.bisectStack[int32(prg.bisectPtr)-20+4] = prg.bisectStack[int32(prg.bisectPtr)-20] + prg.bisectStack[int32(prg.bisectPtr)-20+1] + prg.bisectStack[int32(prg.bisectPtr)-20+2]
 15331  								if prg.bisectStack[int32(prg.bisectPtr)-20+4] < 0 {
 15332  									prg.bisectStack[int32(prg.bisectPtr)-20+4] = 0
 15333  								}
 15334  							} else {
 15335  								prg.bisectStack[int32(prg.bisectPtr)-20+3] = prg.bisectStack[int32(prg.bisectPtr)-20] + prg.bisectStack[int32(prg.bisectPtr)-20+1] + prg.bisectStack[int32(prg.bisectPtr)-20+2]
 15336  								if prg.bisectStack[int32(prg.bisectPtr)-20+3] > prg.bisectStack[int32(prg.bisectPtr)-20] {
 15337  									prg.bisectStack[int32(prg.bisectPtr)-20+3] = prg.bisectStack[int32(prg.bisectPtr)-20]
 15338  								}
 15339  								prg.bisectStack[int32(prg.bisectPtr)-20+4] = prg.bisectStack[int32(prg.bisectPtr)-20] + prg.bisectStack[int32(prg.bisectPtr)-20+1]
 15340  								if prg.bisectStack[int32(prg.bisectPtr)-20+4] < 0 {
 15341  									prg.bisectStack[int32(prg.bisectPtr)-20+4] = 0
 15342  								}
 15343  							}
 15344  						} else if prg.bisectStack[int32(prg.bisectPtr)-20+2] <= 0 {
 15345  							if prg.bisectStack[int32(prg.bisectPtr)-20+1] > 0 {
 15346  								prg.bisectStack[int32(prg.bisectPtr)-20+4] = prg.bisectStack[int32(prg.bisectPtr)-20] + prg.bisectStack[int32(prg.bisectPtr)-20+1]
 15347  							} else {
 15348  								prg.bisectStack[int32(prg.bisectPtr)-20+4] = prg.bisectStack[int32(prg.bisectPtr)-20]
 15349  							}
 15350  							prg.bisectStack[int32(prg.bisectPtr)-20+3] = prg.bisectStack[int32(prg.bisectPtr)-20] + prg.bisectStack[int32(prg.bisectPtr)-20+1] + prg.bisectStack[int32(prg.bisectPtr)-20+2]
 15351  							if prg.bisectStack[int32(prg.bisectPtr)-20+3] > 0 {
 15352  								prg.bisectStack[int32(prg.bisectPtr)-20+3] = 0
 15353  							}
 15354  						} else {
 15355  							prg.bisectStack[int32(prg.bisectPtr)-20+4] = prg.bisectStack[int32(prg.bisectPtr)-20] + prg.bisectStack[int32(prg.bisectPtr)-20+1] + prg.bisectStack[int32(prg.bisectPtr)-20+2]
 15356  							if prg.bisectStack[int32(prg.bisectPtr)-20+4] < prg.bisectStack[int32(prg.bisectPtr)-20] {
 15357  								prg.bisectStack[int32(prg.bisectPtr)-20+4] = prg.bisectStack[int32(prg.bisectPtr)-20]
 15358  							}
 15359  							prg.bisectStack[int32(prg.bisectPtr)-20+3] = prg.bisectStack[int32(prg.bisectPtr)-20] + prg.bisectStack[int32(prg.bisectPtr)-20+1]
 15360  							if prg.bisectStack[int32(prg.bisectPtr)-20+3] > 0 {
 15361  								prg.bisectStack[int32(prg.bisectPtr)-20+3] = 0
 15362  							}
 15363  						}
 15364  
 15365  						prg.uv = uint16(int32(prg.bisectPtr) - intPackets)
 15366  						prg.xy = uint16(int32(prg.bisectPtr) - intPackets)
 15367  						prg.delx = prg.delx + prg.delx
 15368  						prg.dely = prg.dely + prg.dely
 15369  
 15370  						prg.tol = prg.tol - prg.threeL + int32(prg.tolStep)
 15371  						prg.tol = prg.tol + prg.tol
 15372  						prg.threeL = prg.threeL + int32(prg.tolStep)
 15373  
 15374  						goto continue1
 15375  					}
 15376  				}
 15377  			}
 15378  		}
 15379  		if prg.timeToGo > 0 {
 15380  			prg.timeToGo = prg.timeToGo - 1
 15381  		} else {
 15382  			for prg.apprT < 0200000 {
 15383  				prg.apprT = prg.apprT + prg.apprT
 15384  				prg.apprTt = prg.apprTt + prg.apprTt
 15385  			}
 15386  			prg.curT = prg.apprT
 15387  			prg.curTt = prg.apprTt
 15388  			goto exit
 15389  		}
 15390  
 15391  		// Advance to the next pair |(cur_t,cur_tt)|
 15392  
 15393  		// Advance to the next pair |(cur_t,cur_tt)|
 15394  	notFound:
 15395  		if prg.curTt&1 != 0 {
 15396  			if prg.curT&1 != 0 {
 15397  				prg.curT = prg.curT / 2
 15398  				prg.curTt = prg.curTt / 2
 15399  				if prg.curT == 0 {
 15400  					goto exit
 15401  				}
 15402  				prg.bisectPtr = uint16(int32(prg.bisectPtr) - intIncrement)
 15403  				prg.threeL = prg.threeL - int32(prg.tolStep)
 15404  				prg.delx = prg.bisectStack[prg.bisectPtr]
 15405  				prg.dely = prg.bisectStack[int32(prg.bisectPtr)+1]
 15406  				prg.tol = prg.bisectStack[int32(prg.bisectPtr)+2]
 15407  				prg.uv = uint16(prg.bisectStack[int32(prg.bisectPtr)+3])
 15408  				prg.xy = uint16(prg.bisectStack[int32(prg.bisectPtr)+4])
 15409  
 15410  				goto notFound
 15411  			} else {
 15412  				prg.curT = prg.curT + 1
 15413  				prg.delx = prg.delx + prg.bisectStack[int32(prg.uv)-5] + prg.bisectStack[int32(prg.uv)-5+1] + prg.bisectStack[int32(prg.uv)-5+2]
 15414  				prg.dely = prg.dely + prg.bisectStack[int32(prg.uv)-10] + prg.bisectStack[int32(prg.uv)-10+1] + prg.bisectStack[int32(prg.uv)-10+2]
 15415  				prg.uv = uint16(int32(prg.uv) + intPackets) // switch from |l_packets| to |r_packets|
 15416  				prg.curTt = prg.curTt - 1
 15417  				prg.xy = uint16(int32(prg.xy) - intPackets) // switch from |r_packets| to |l_packets|
 15418  				prg.delx = prg.delx + prg.bisectStack[int32(prg.xy)-15] + prg.bisectStack[int32(prg.xy)-15+1] + prg.bisectStack[int32(prg.xy)-15+2]
 15419  				prg.dely = prg.dely + prg.bisectStack[int32(prg.xy)-20] + prg.bisectStack[int32(prg.xy)-20+1] + prg.bisectStack[int32(prg.xy)-20+2]
 15420  			}
 15421  		} else {
 15422  			prg.curTt = prg.curTt + 1
 15423  			prg.tol = prg.tol + prg.threeL
 15424  			prg.delx = prg.delx - prg.bisectStack[int32(prg.xy)-15] - prg.bisectStack[int32(prg.xy)-15+1] - prg.bisectStack[int32(prg.xy)-15+2]
 15425  			prg.dely = prg.dely - prg.bisectStack[int32(prg.xy)-20] - prg.bisectStack[int32(prg.xy)-20+1] - prg.bisectStack[int32(prg.xy)-20+2]
 15426  			prg.xy = uint16(int32(prg.xy) + intPackets) // switch from |l_packets| to |r_packets|
 15427  		}
 15428  	}
 15429  
 15430  exit:
 15431  }
 15432  
 15433  // 562.
 15434  
 15435  // tangle:pos ../../mf.web:12006:3:
 15436  
 15437  // The |path_intersection| procedure is much simpler.
 15438  // It invokes |cubic_intersection| in lexicographic order until finding a
 15439  // pair of cubics that intersect. The final intersection times are placed in
 15440  // |cur_t| and~|cur_tt|.
 15441  func (prg *prg) pathIntersection(h, hh halfword) {
 15442  	var (
 15443  		p, pp halfword // link registers that traverse the given paths
 15444  		n, nn int32    // integer parts of intersection times, minus |unity|
 15445  	)
 15446  	if int32(*(*prg.mem[h].hh()).b1()) == endpoint {
 15447  		*prg.mem[int32(h)+5].int() = *prg.mem[int32(h)+1].int()
 15448  		*prg.mem[int32(h)+3].int() = *prg.mem[int32(h)+1].int()
 15449  		*prg.mem[int32(h)+6].int() = *prg.mem[int32(h)+2].int()
 15450  		*prg.mem[int32(h)+4].int() = *prg.mem[int32(h)+2].int()
 15451  		*(*prg.mem[h].hh()).b1() = byte(explicit)
 15452  	}
 15453  	if int32(*(*prg.mem[hh].hh()).b1()) == endpoint {
 15454  		*prg.mem[int32(hh)+5].int() = *prg.mem[int32(hh)+1].int()
 15455  		*prg.mem[int32(hh)+3].int() = *prg.mem[int32(hh)+1].int()
 15456  		*prg.mem[int32(hh)+6].int() = *prg.mem[int32(hh)+2].int()
 15457  		*prg.mem[int32(hh)+4].int() = *prg.mem[int32(hh)+2].int()
 15458  		*(*prg.mem[hh].hh()).b1() = byte(explicit)
 15459  	}
 15460  
 15461  	prg.tolStep = 0
 15462  	for {
 15463  		n = -0200000
 15464  		p = h
 15465  		for {
 15466  			if int32(*(*prg.mem[p].hh()).b1()) != endpoint {
 15467  				nn = -0200000
 15468  				pp = hh
 15469  				for {
 15470  					if int32(*(*prg.mem[pp].hh()).b1()) != endpoint {
 15471  						prg.cubicIntersection(p, pp)
 15472  						if prg.curT > 0 {
 15473  							prg.curT = prg.curT + n
 15474  							prg.curTt = prg.curTt + nn
 15475  							goto exit
 15476  						}
 15477  					}
 15478  					nn = nn + 0200000
 15479  					pp = *(*prg.mem[pp].hh()).rh()
 15480  					if int32(pp) == int32(hh) {
 15481  						break
 15482  					}
 15483  				}
 15484  			}
 15485  			n = n + 0200000
 15486  			p = *(*prg.mem[p].hh()).rh()
 15487  			if int32(p) == int32(h) {
 15488  				break
 15489  			}
 15490  		}
 15491  		prg.tolStep = byte(int32(prg.tolStep) + 3)
 15492  		if int32(prg.tolStep) > 3 {
 15493  			break
 15494  		}
 15495  	}
 15496  	prg.curT = -0200000
 15497  	prg.curTt = -0200000
 15498  
 15499  exit:
 15500  }
 15501  
 15502  // 564. \[27] Online graphic output
 15503  
 15504  // tangle:pos ../../mf.web:12046:32:
 15505  
 15506  // \MF\ displays images on the user's screen by means of a few primitive
 15507  // operations that are defined below. These operations have deliberately been
 15508  // kept simple so that they can be implemented without great difficulty on a
 15509  // wide variety of machines. Since \PASCAL\ has no traditional standards for
 15510  // graphic output, some system-dependent code needs to be written in order to
 15511  // support this aspect of \MF; but the necessary routines are usually quite
 15512  // easy to write.
 15513  // \xref[system dependencies]
 15514  //
 15515  // In fact, there are exactly four such routines:
 15516  //
 15517  // \yskip\hang
 15518  // |init_screen| does whatever initialization is necessary to
 15519  // support the other operations; it is a boolean function that returns
 15520  // |false| if graphic output cannot be supported (e.g., if the other three
 15521  // routines have not been written, or if the user doesn't have the
 15522  // right kind of terminal).
 15523  //
 15524  // \yskip\hang
 15525  // |blank_rectangle| updates a buffer area in memory so that
 15526  // all pixels in a specified rectangle will be set to the background color.
 15527  //
 15528  // \yskip\hang
 15529  // |paint_row| assigns values to specified pixels in a row of
 15530  // the buffer just mentioned, based on ``transition'' indices explained below.
 15531  //
 15532  // \yskip\hang
 15533  // |update_screen| displays the current screen buffer; the
 15534  // effects of |blank_rectangle| and |paint_row| commands may or may not
 15535  // become visible until the next |update_screen| operation is performed.
 15536  // (Thus, |update_screen| is analogous to |update_terminal|.)
 15537  //
 15538  // \yskip\noindent
 15539  // The \PASCAL\ code here is a minimum version of |init_screen| and
 15540  // |update_screen|, usable on \MF\ installations that don't
 15541  // support screen output. If |init_screen| is changed to return |true|
 15542  // instead of |false|, the other routines will simply log the fact
 15543  // that they have been called; they won't really display anything.
 15544  // The standard test routines for \MF\ use this log information to check
 15545  // that \MF\ is working properly, but the |wlog| instructions should be
 15546  // removed from production versions of \MF.
 15547  func (prg *prg) initScreen() (r bool) {
 15548  	r = true // screen instructions will be logged
 15549  	return r
 15550  }
 15551  
 15552  func (prg *prg) updateScreen() {
 15553  	prg.logFile.Writeln("Calling UPDATESCREEN") // for testing only
 15554  }
 15555  
 15556  // 567.
 15557  
 15558  // tangle:pos ../../mf.web:12126:3:
 15559  
 15560  // The |blank_rectangle| routine simply whitens all pixels that lie in
 15561  // columns |left_col| through |right_col-1|, inclusive, of rows
 15562  // |top_row| through |bot_row-1|, inclusive, given four parameters that satisfy
 15563  // the relations
 15564  // $$\hbox[|0<=left_col<=right_col<=screen_width|,\quad
 15565  //   |0<=top_row<=bot_row<=screen_depth|.]$$
 15566  // If |left_col=right_col| or |top_row=bot_row|, nothing happens.
 15567  //
 15568  // The commented-out code in the following procedure is for illustrative
 15569  // purposes only.
 15570  // \xref[system dependencies]
 15571  func (prg *prg) blankRectangle(leftCol, rightCol screenCol,
 15572  	topRow, botRow screenRow) {
 15573  	prg.logFile.Writeln() // this will be done only after |init_screen=true|
 15574  	prg.logFile.Writeln("Calling BLANKRECTANGLE(", leftCol, knuth.WriteWidth(1), ",", rightCol, knuth.WriteWidth(1), ",", topRow, knuth.WriteWidth(1), ",", botRow, knuth.WriteWidth(1), ")")
 15575  }
 15576  
 15577  // 568.
 15578  
 15579  // tangle:pos ../../mf.web:12150:3:
 15580  
 15581  // The real work of screen display is done by |paint_row|. But it's not
 15582  // hard work, because the operation affects only
 15583  // one of the screen rows, and it affects only a contiguous set of columns
 15584  // in that row. There are four parameters: |r|~(the row),
 15585  // |b|~(the initial color),
 15586  // |a|~(the array of transition specifications),
 15587  // and |n|~(the number of transitions). The elements of~|a| will satisfy
 15588  // $$0\L a[0]<a[1]<\cdots<a[n]\L |screen_width|;$$
 15589  // the value of |r| will satisfy |0<=r<screen_depth|; and |n| will be positive.
 15590  //
 15591  // The general idea is to paint blocks of pixels in alternate colors;
 15592  // the precise details are best conveyed by means of a \PASCAL\
 15593  // program (see the commented-out code below).
 15594  // \xref[system dependencies]
 15595  func (prg *prg) paintRow(r1 screenRow, b pixelColor, a transSpec,
 15596  	n screenCol) {
 15597  	var (
 15598  		k screenCol // an index into |a|
 15599  	)
 15600  	prg.logFile.Write("Calling PAINTROW(", r1, knuth.WriteWidth(1), ",", b, knuth.WriteWidth(1), ";")
 15601  	// this is done only after |init_screen=true|
 15602  	for ii := int32(0); ii <= int32(n); ii++ {
 15603  		k = screenCol(ii)
 15604  		_ = k
 15605  		prg.logFile.Write(a[k], knuth.WriteWidth(1))
 15606  		if int32(k) != int32(n) {
 15607  			prg.logFile.Write(",")
 15608  		}
 15609  	}
 15610  	prg.logFile.Writeln(")")
 15611  }
 15612  
 15613  // 574.
 15614  
 15615  // tangle:pos ../../mf.web:12259:3:
 15616  
 15617  // Opening a window isn't like opening a file, because you can open it
 15618  // as often as you like, and you never have to close it again. The idea is
 15619  // simply to define special points on the current screen display.
 15620  //
 15621  // Overlapping window specifications may cause complex effects that can
 15622  // be understood only by scrutinizing \MF's display algorithms; thus it
 15623  // has been left undefined in the \MF\ user manual, although the behavior
 15624  // \xref[METAFONTbook][\sl The [\logos METAFONT\/]book]
 15625  // is in fact predictable.
 15626  //
 15627  // Here is a subroutine that implements the command `\&[openwindow]~|k|
 15628  // \&[from]~$(\\[r0],\\[c0])$ \&[to]~$(\\[r1],\\[c1])$ \&[at]~$(x,y)$'.
 15629  func (prg *prg) openAWindow(k windowNumber, r0, c0, r11, c1 scaled,
 15630  	x, y scaled) {
 15631  	var (
 15632  		m, n int32 // pixel coordinates
 15633  	)
 15634  	if r0 < 0 {
 15635  		r0 = 0
 15636  	} else {
 15637  		r0 = prg.roundUnscaled(r0)
 15638  	}
 15639  	r11 = prg.roundUnscaled(r11)
 15640  	if r11 > screenDepth {
 15641  		r11 = screenDepth
 15642  	}
 15643  	if r11 < r0 {
 15644  		if r0 > screenDepth {
 15645  			r0 = r11
 15646  		} else {
 15647  			r11 = r0
 15648  		}
 15649  	}
 15650  	if c0 < 0 {
 15651  		c0 = 0
 15652  	} else {
 15653  		c0 = prg.roundUnscaled(c0)
 15654  	}
 15655  	c1 = prg.roundUnscaled(c1)
 15656  	if c1 > screenWidth {
 15657  		c1 = screenWidth
 15658  	}
 15659  	if c1 < c0 {
 15660  		if c0 > screenWidth {
 15661  			c0 = c1
 15662  		} else {
 15663  			c1 = c0
 15664  		}
 15665  	}
 15666  	prg.windowOpen[k] = true
 15667  	prg.windowTime[k] = prg.windowTime[k] + 1
 15668  
 15669  	prg.leftCol[k] = byte(c0)
 15670  	prg.rightCol[k] = byte(c1)
 15671  	prg.topRow[k] = byte(r0)
 15672  	prg.botRow[k] = byte(r11)
 15673  
 15674  	// Compute the offsets between screen coordinates and actual coordinates
 15675  	m = prg.roundUnscaled(x)
 15676  	n = prg.roundUnscaled(y) - 1
 15677  
 15678  	prg.mWindow[k] = c0 - m
 15679  	prg.nWindow[k] = r0 + n
 15680  	{
 15681  		if !prg.screenStarted {
 15682  			prg.screenOk = prg.initScreen()
 15683  			prg.screenStarted = true
 15684  		}
 15685  	}
 15686  	if prg.screenOk {
 15687  		prg.blankRectangle(screenCol(c0), screenCol(c1), screenRow(r0), screenRow(r11))
 15688  		prg.updateScreen()
 15689  	}
 15690  }
 15691  
 15692  // 577.
 15693  
 15694  // tangle:pos ../../mf.web:12319:3:
 15695  
 15696  // Now here comes \MF's most complicated operation related to window
 15697  // display: Given the number~|k| of an open window, the pixels of positive
 15698  // weight in |cur_edges| will be shown as |black| in the window; all other
 15699  // pixels will be shown as |white|.
 15700  func (prg *prg) dispEdges(k windowNumber) {
 15701  	var (
 15702  		p, q         halfword // for list manipulation
 15703  		alreadyThere bool     // is a previous incarnation in the window?
 15704  		r1           int32    // row number
 15705  
 15706  		// Other local variables for |disp_edges|
 15707  		n           screenCol  // the highest active index in |row_transition|
 15708  		w, ww       int32      // old and new accumulated weights
 15709  		b           pixelColor // status of first pixel in the row transitions
 15710  		m, mm       int32      // old and new screen column positions
 15711  		d           int32      // edge-and-weight without |min_halfword| compensation
 15712  		mAdjustment int32      // conversion between edge and screen coordinates
 15713  		rightEdge   int32      // largest edge-and-weight that could affect the window
 15714  		minCol      screenCol  // the smallest screen column number in the window
 15715  	)
 15716  	if prg.screenOk {
 15717  		if int32(prg.leftCol[k]) < int32(prg.rightCol[k]) {
 15718  			if int32(prg.topRow[k]) < int32(prg.botRow[k]) {
 15719  				alreadyThere = false
 15720  				if int32(*(*prg.mem[int32(prg.curEdges)+3].hh()).rh()) == int32(k) {
 15721  					if *prg.mem[int32(prg.curEdges)+4].int() == prg.windowTime[k] {
 15722  						alreadyThere = true
 15723  					}
 15724  				}
 15725  				if !alreadyThere {
 15726  					prg.blankRectangle(prg.leftCol[k], prg.rightCol[k], prg.topRow[k], prg.botRow[k])
 15727  				}
 15728  
 15729  				// Initialize for the display computations
 15730  				mAdjustment = prg.mWindow[k] - int32(*(*prg.mem[int32(prg.curEdges)+3].hh()).lh())
 15731  
 15732  				rightEdge = 8 * (int32(prg.rightCol[k]) - mAdjustment)
 15733  
 15734  				minCol = prg.leftCol[k]
 15735  				p = *(*prg.mem[prg.curEdges].hh()).rh()
 15736  				r1 = prg.nWindow[k] - (int32(*(*prg.mem[int32(prg.curEdges)+1].hh()).lh()) - zeroField)
 15737  				for int32(p) != int32(prg.curEdges) && r1 >= int32(prg.topRow[k]) {
 15738  					if r1 < int32(prg.botRow[k]) {
 15739  						if int32(*(*prg.mem[int32(p)+1].hh()).lh()) > memMin+1 {
 15740  							prg.sortEdges(p)
 15741  						} else if int32(*(*prg.mem[int32(p)+1].hh()).lh()) == memMin+1 {
 15742  							if alreadyThere {
 15743  								goto done
 15744  							}
 15745  						}
 15746  						*(*prg.mem[int32(p)+1].hh()).lh() = uint16(memMin + 1) // this time we'll paint, but maybe not next time
 15747  
 15748  						// Set up the parameters needed for |paint_row|; but |goto done| if no painting is needed after all
 15749  						n = 0
 15750  						ww = 0
 15751  						m = -1
 15752  						w = 0
 15753  						q = *(*prg.mem[int32(p)+1].hh()).rh()
 15754  						prg.rowTransition[0] = minCol
 15755  						for true {
 15756  							if int32(q) == 3000 {
 15757  								d = rightEdge
 15758  							} else {
 15759  								d = int32(*(*prg.mem[q].hh()).lh()) - 0
 15760  							}
 15761  							mm = d/8 + mAdjustment
 15762  							if mm != m {
 15763  								if w <= 0 {
 15764  									if ww > 0 {
 15765  										if m > int32(minCol) {
 15766  											if int32(n) == 0 {
 15767  												if alreadyThere {
 15768  													b = byte(white)
 15769  													n = byte(int32(n) + 1)
 15770  												} else {
 15771  													b = byte(black)
 15772  												}
 15773  											} else {
 15774  												n = byte(int32(n) + 1)
 15775  											}
 15776  											prg.rowTransition[n] = byte(m)
 15777  										}
 15778  									}
 15779  								} else if ww <= 0 {
 15780  									if m > int32(minCol) {
 15781  										if int32(n) == 0 {
 15782  											b = byte(black)
 15783  										}
 15784  										n = byte(int32(n) + 1)
 15785  										prg.rowTransition[n] = byte(m)
 15786  									}
 15787  								}
 15788  								m = mm
 15789  								w = ww
 15790  							}
 15791  							if d >= rightEdge {
 15792  								goto found
 15793  							}
 15794  							ww = ww + d%8 - zeroW
 15795  							q = *(*prg.mem[q].hh()).rh()
 15796  						}
 15797  
 15798  					found:
 15799  						if alreadyThere || ww > 0 {
 15800  							if int32(n) == 0 {
 15801  								if ww > 0 {
 15802  									b = byte(black)
 15803  								} else {
 15804  									b = byte(white)
 15805  								}
 15806  							}
 15807  							n = byte(int32(n) + 1)
 15808  							prg.rowTransition[n] = prg.rightCol[k]
 15809  						} else if int32(n) == 0 {
 15810  							goto done
 15811  						}
 15812  
 15813  						prg.paintRow(screenRow(r1), b, prg.rowTransition, n)
 15814  
 15815  					done:
 15816  					}
 15817  					p = *(*prg.mem[p].hh()).rh()
 15818  					r1 = r1 - 1
 15819  				}
 15820  				prg.updateScreen()
 15821  				prg.windowTime[k] = prg.windowTime[k] + 1
 15822  				*(*prg.mem[int32(prg.curEdges)+3].hh()).rh() = uint16(k)
 15823  				*prg.mem[int32(prg.curEdges)+4].int() = prg.windowTime[k]
 15824  			}
 15825  		}
 15826  	}
 15827  }
 15828  
 15829  // 588.
 15830  
 15831  // tangle:pos ../../mf.web:12536:3:
 15832  
 15833  // Actually the description above contains a little white lie. There's
 15834  // another kind of variable called |proto_dependent|, which is
 15835  // just like a |dependent| one except that the $\alpha$ coefficients
 15836  // in its dependency list are |scaled| instead of being fractions.
 15837  // Proto-dependency lists are mixed with dependency lists in the
 15838  // nodes reachable from |dep_head|.
 15839  
 15840  // 591.
 15841  
 15842  // tangle:pos ../../mf.web:12578:3:
 15843  
 15844  // The maximum absolute value of a coefficient in a given dependency list
 15845  // is returned by the following simple function.
 15846  func (prg *prg) maxCoef(p halfword) (r fraction) {
 15847  	var (
 15848  		x fraction // the maximum so far
 15849  	)
 15850  	x = 0
 15851  	for int32(*(*prg.mem[p].hh()).lh()) != memMin {
 15852  		if abs(*prg.mem[int32(p)+1].int()) > x {
 15853  			x = abs(*prg.mem[int32(p)+1].int())
 15854  		}
 15855  		p = *(*prg.mem[p].hh()).rh()
 15856  	}
 15857  	r = x
 15858  	return r
 15859  }
 15860  
 15861  // 597.
 15862  
 15863  // tangle:pos ../../mf.web:12697:3:
 15864  
 15865  // It is convenient to have another subroutine for the special case
 15866  // of |p_plus_fq| when |f=1.0|. In this routine lists |p| and |q| are
 15867  // both of the same type~|t| (either |dependent| or |proto_dependent|).
 15868  func (prg *prg) pPlusQ(p halfword, q halfword, t smallNumber) (r halfword) {
 15869  	var (
 15870  		pp, qq    halfword // |info(p)| and |info(q)|, respectively
 15871  		r1, s     halfword // for list manipulation
 15872  		threshold int32    // defines a neighborhood of zero
 15873  		v         int32    // temporary register
 15874  	)
 15875  	if int32(t) == dependent {
 15876  		threshold = fractionThreshold
 15877  	} else {
 15878  		threshold = scaledThreshold
 15879  	}
 15880  	r1 = uint16(3000 - 1)
 15881  	pp = *(*prg.mem[p].hh()).lh()
 15882  	qq = *(*prg.mem[q].hh()).lh()
 15883  	for true {
 15884  		if int32(pp) == int32(qq) {
 15885  			if int32(pp) == memMin {
 15886  				goto done
 15887  			} else {
 15888  				// Contribute a term from |p|, plus the corresponding term from |q|
 15889  				v = *prg.mem[int32(p)+1].int() + *prg.mem[int32(q)+1].int()
 15890  				*prg.mem[int32(p)+1].int() = v
 15891  				s = p
 15892  				p = *(*prg.mem[p].hh()).rh()
 15893  				pp = *(*prg.mem[p].hh()).lh()
 15894  				if abs(v) < threshold {
 15895  					prg.freeNode(s, halfword(depNodeSize))
 15896  				} else {
 15897  					if abs(v) >= 04525252525 {
 15898  						if prg.watchCoefs {
 15899  							*(*prg.mem[qq].hh()).b0() = byte(independentNeedingFix)
 15900  							prg.fixNeeded = true
 15901  						}
 15902  					}
 15903  					*(*prg.mem[r1].hh()).rh() = s
 15904  					r1 = s
 15905  				}
 15906  				q = *(*prg.mem[q].hh()).rh()
 15907  				qq = *(*prg.mem[q].hh()).lh()
 15908  			}
 15909  		} else if *prg.mem[int32(pp)+1].int() < *prg.mem[int32(qq)+1].int() {
 15910  			s = prg.getNode(depNodeSize)
 15911  			*(*prg.mem[s].hh()).lh() = qq
 15912  			*prg.mem[int32(s)+1].int() = *prg.mem[int32(q)+1].int()
 15913  			q = *(*prg.mem[q].hh()).rh()
 15914  			qq = *(*prg.mem[q].hh()).lh()
 15915  			*(*prg.mem[r1].hh()).rh() = s
 15916  			r1 = s
 15917  		} else {
 15918  			*(*prg.mem[r1].hh()).rh() = p
 15919  			r1 = p
 15920  			p = *(*prg.mem[p].hh()).rh()
 15921  			pp = *(*prg.mem[p].hh()).lh()
 15922  		}
 15923  	}
 15924  
 15925  done:
 15926  	*prg.mem[int32(p)+1].int() = prg.slowAdd(*prg.mem[int32(p)+1].int(), *prg.mem[int32(q)+1].int())
 15927  	*(*prg.mem[r1].hh()).rh() = p
 15928  	prg.depFinal = p
 15929  	r = *(*prg.mem[3000-1].hh()).rh()
 15930  	return r
 15931  }
 15932  
 15933  // 599.
 15934  
 15935  // tangle:pos ../../mf.web:12736:3:
 15936  
 15937  // A somewhat simpler routine will multiply a dependency list
 15938  // by a given constant~|v|. The constant is either a |fraction| less than
 15939  // |fraction_one|, or it is |scaled|. In the latter case we might be forced to
 15940  // convert a dependency list to a proto-dependency list.
 15941  // Parameters |t0| and |t1| are the list types before and after;
 15942  // they should agree unless |t0=dependent| and |t1=proto_dependent|
 15943  // and |v_is_scaled=true|.
 15944  func (prg *prg) pTimesV(p halfword, v int32,
 15945  	t0, t1 smallNumber, vIsScaled bool) (r halfword) {
 15946  	var (
 15947  		r1, s       halfword // for list manipulation
 15948  		w           int32    // tentative coefficient
 15949  		threshold   int32
 15950  		scalingDown bool
 15951  	)
 15952  	if int32(t0) != int32(t1) {
 15953  		scalingDown = true
 15954  	} else {
 15955  		scalingDown = !vIsScaled
 15956  	}
 15957  	if int32(t1) == dependent {
 15958  		threshold = halfFractionThreshold
 15959  	} else {
 15960  		threshold = halfScaledThreshold
 15961  	}
 15962  	r1 = uint16(3000 - 1)
 15963  	for int32(*(*prg.mem[p].hh()).lh()) != memMin {
 15964  		if scalingDown {
 15965  			w = prg.takeFraction(v, *prg.mem[int32(p)+1].int())
 15966  		} else {
 15967  			w = prg.takeScaled(v, *prg.mem[int32(p)+1].int())
 15968  		}
 15969  		if abs(w) <= threshold {
 15970  			s = *(*prg.mem[p].hh()).rh()
 15971  			prg.freeNode(p, halfword(depNodeSize))
 15972  			p = s
 15973  		} else {
 15974  			if abs(w) >= 04525252525 {
 15975  				prg.fixNeeded = true
 15976  				*(*prg.mem[*(*prg.mem[p].hh()).lh()].hh()).b0() = byte(independentNeedingFix)
 15977  			}
 15978  			*(*prg.mem[r1].hh()).rh() = p
 15979  			r1 = p
 15980  			*prg.mem[int32(p)+1].int() = w
 15981  			p = *(*prg.mem[p].hh()).rh()
 15982  		}
 15983  	}
 15984  	*(*prg.mem[r1].hh()).rh() = p
 15985  	if vIsScaled {
 15986  		*prg.mem[int32(p)+1].int() = prg.takeScaled(*prg.mem[int32(p)+1].int(), v)
 15987  	} else {
 15988  		*prg.mem[int32(p)+1].int() = prg.takeFraction(*prg.mem[int32(p)+1].int(), v)
 15989  	}
 15990  	r = *(*prg.mem[3000-1].hh()).rh()
 15991  	return r
 15992  }
 15993  
 15994  // 601.
 15995  
 15996  // tangle:pos ../../mf.web:12804:3:
 15997  
 15998  // Here's another utility routine for dependency lists. When an independent
 15999  // variable becomes dependent, we want to remove it from all existing
 16000  // dependencies. The |p_with_x_becoming_q| function computes the
 16001  // dependency list of~|p| after variable~|x| has been replaced by~|q|.
 16002  //
 16003  // This procedure has basically the same calling conventions as |p_plus_fq|:
 16004  // List~|q| is unchanged; list~|p| is destroyed; the constant node and the
 16005  // final link are inherited from~|p|; and the fourth parameter tells whether
 16006  // or not |p| is |proto_dependent|. However, the global variable |dep_final|
 16007  // is not altered if |x| does not occur in list~|p|.
 16008  func (prg *prg) pWithXBecomingQ(p, x, q halfword, t smallNumber) (r halfword) {
 16009  	var (
 16010  		r1, s halfword // for list manipulation
 16011  		v     int32    // coefficient of |x|
 16012  		sx    int32    // serial number of |x|
 16013  	)
 16014  	s = p
 16015  	r1 = uint16(3000 - 1)
 16016  	sx = *prg.mem[int32(x)+1].int()
 16017  	for *prg.mem[int32(*(*prg.mem[s].hh()).lh())+1].int() > sx {
 16018  		r1 = s
 16019  		s = *(*prg.mem[s].hh()).rh()
 16020  	}
 16021  	if int32(*(*prg.mem[s].hh()).lh()) != int32(x) {
 16022  		r = p
 16023  	} else {
 16024  		*(*prg.mem[3000-1].hh()).rh() = p
 16025  		*(*prg.mem[r1].hh()).rh() = *(*prg.mem[s].hh()).rh()
 16026  		v = *prg.mem[int32(s)+1].int()
 16027  		prg.freeNode(s, halfword(depNodeSize))
 16028  		r = prg.pPlusFq(*(*prg.mem[3000-1].hh()).rh(), v, q, t, smallNumber(dependent))
 16029  	}
 16030  	return r
 16031  }
 16032  
 16033  // 606.
 16034  
 16035  // tangle:pos ../../mf.web:12916:3:
 16036  
 16037  // The |new_dep| routine installs a dependency list~|p| into the value node~|q|,
 16038  // linking it into the list of all known dependencies. We assume that
 16039  // |dep_final| points to the final node of list~|p|.
 16040  func (prg *prg) newDep(q, p halfword) {
 16041  	var (
 16042  		r1 halfword // what used to be the first dependency
 16043  	)
 16044  	*(*prg.mem[int32(q)+1].hh()).rh() = p
 16045  	*(*prg.mem[int32(q)+1].hh()).lh() = uint16(memMin + 3 + 10)
 16046  	r1 = *(*prg.mem[memMin+3+10].hh()).rh()
 16047  	*(*prg.mem[prg.depFinal].hh()).rh() = r1
 16048  	*(*prg.mem[int32(r1)+1].hh()).lh() = prg.depFinal
 16049  	*(*prg.mem[memMin+3+10].hh()).rh() = q
 16050  }
 16051  
 16052  // 607.
 16053  
 16054  // tangle:pos ../../mf.web:12927:3:
 16055  
 16056  // Here is one of the ways a dependency list gets started.
 16057  // The |const_dependency| routine produces a list that has nothing but
 16058  // a constant term.
 16059  func (prg *prg) constDependency(v scaled) (r halfword) {
 16060  	prg.depFinal = prg.getNode(depNodeSize)
 16061  	*prg.mem[int32(prg.depFinal)+1].int() = v
 16062  	*(*prg.mem[prg.depFinal].hh()).lh() = uint16(memMin)
 16063  	r = prg.depFinal
 16064  	return r
 16065  }
 16066  
 16067  // 608.
 16068  
 16069  // tangle:pos ../../mf.web:12937:3:
 16070  
 16071  // And here's a more interesting way to start a dependency list from scratch:
 16072  // The parameter to |single_dependency| is the location of an
 16073  // independent variable~|x|, and the result is the simple dependency list
 16074  // `|x+0|'.
 16075  //
 16076  // In the unlikely event that the given independent variable has been doubled so
 16077  // often that we can't refer to it with a nonzero coefficient,
 16078  // |single_dependency| returns the simple list `0'.  This case can be
 16079  // recognized by testing that the returned list pointer is equal to
 16080  // |dep_final|.
 16081  func (prg *prg) singleDependency(p halfword) (r halfword) {
 16082  	var (
 16083  		q halfword // the new dependency list
 16084  		m int32    // the number of doublings
 16085  	)
 16086  	m = *prg.mem[int32(p)+1].int() % sScale
 16087  	if m > 28 {
 16088  		r = prg.constDependency(scaled(0))
 16089  	} else {
 16090  		q = prg.getNode(depNodeSize)
 16091  		*prg.mem[int32(q)+1].int() = prg.twoToThe[28-m]
 16092  		*(*prg.mem[q].hh()).lh() = p
 16093  
 16094  		*(*prg.mem[q].hh()).rh() = prg.constDependency(scaled(0))
 16095  		r = q
 16096  	}
 16097  	return r
 16098  }
 16099  
 16100  // 609.
 16101  
 16102  // tangle:pos ../../mf.web:12959:3:
 16103  
 16104  // We sometimes need to make an exact copy of a dependency list.
 16105  func (prg *prg) copyDepList(p halfword) (r halfword) {
 16106  	var (
 16107  		q halfword // the new dependency list
 16108  	)
 16109  	q = prg.getNode(depNodeSize)
 16110  	prg.depFinal = q
 16111  	for true {
 16112  		*(*prg.mem[prg.depFinal].hh()).lh() = *(*prg.mem[p].hh()).lh()
 16113  		*prg.mem[int32(prg.depFinal)+1].int() = *prg.mem[int32(p)+1].int()
 16114  		if int32(*(*prg.mem[prg.depFinal].hh()).lh()) == memMin {
 16115  			goto done
 16116  		}
 16117  		*(*prg.mem[prg.depFinal].hh()).rh() = prg.getNode(depNodeSize)
 16118  		prg.depFinal = *(*prg.mem[prg.depFinal].hh()).rh()
 16119  		p = *(*prg.mem[p].hh()).rh()
 16120  	}
 16121  
 16122  done:
 16123  	r = q
 16124  	return r
 16125  }
 16126  
 16127  // 610.
 16128  
 16129  // tangle:pos ../../mf.web:12973:3:
 16130  
 16131  // But how do variables normally become known? Ah, now we get to the heart of the
 16132  // equation-solving mechanism. The |linear_eq| procedure is given a |dependent|
 16133  // or |proto_dependent| list,~|p|, in which at least one independent variable
 16134  // appears. It equates this list to zero, by choosing an independent variable
 16135  // with the largest coefficient and making it dependent on the others. The
 16136  // newly dependent variable is eliminated from all current dependencies,
 16137  // thereby possibly making other dependent variables known.
 16138  //
 16139  // The given list |p| is, of course, totally destroyed by all this processing.
 16140  func (prg *prg) linearEq(p halfword, t smallNumber) {
 16141  	var (
 16142  		q, r1, s  halfword // for link manipulation
 16143  		x         halfword // the variable that loses its independence
 16144  		n         int32    // the number of times |x| had been halved
 16145  		v         int32    // the coefficient of |x| in list |p|
 16146  		prevR     halfword // lags one step behind |r|
 16147  		finalNode halfword // the constant term of the new dependency list
 16148  		w         int32    // a tentative coefficient
 16149  	)
 16150  	q = p
 16151  	r1 = *(*prg.mem[p].hh()).rh()
 16152  	v = *prg.mem[int32(q)+1].int()
 16153  	for int32(*(*prg.mem[r1].hh()).lh()) != memMin {
 16154  		if abs(*prg.mem[int32(r1)+1].int()) > abs(v) {
 16155  			q = r1
 16156  			v = *prg.mem[int32(r1)+1].int()
 16157  		}
 16158  		r1 = *(*prg.mem[r1].hh()).rh()
 16159  	}
 16160  	x = *(*prg.mem[q].hh()).lh()
 16161  	n = *prg.mem[int32(x)+1].int() % sScale
 16162  
 16163  	// Divide list |p| by |-v|, removing node |q|
 16164  	s = uint16(3000 - 1)
 16165  	*(*prg.mem[s].hh()).rh() = p
 16166  	r1 = p
 16167  	for {
 16168  		if int32(r1) == int32(q) {
 16169  			*(*prg.mem[s].hh()).rh() = *(*prg.mem[r1].hh()).rh()
 16170  			prg.freeNode(r1, halfword(depNodeSize))
 16171  		} else {
 16172  			w = prg.makeFraction(*prg.mem[int32(r1)+1].int(), v)
 16173  			if abs(w) <= halfFractionThreshold {
 16174  				*(*prg.mem[s].hh()).rh() = *(*prg.mem[r1].hh()).rh()
 16175  				prg.freeNode(r1, halfword(depNodeSize))
 16176  			} else {
 16177  				*prg.mem[int32(r1)+1].int() = -w
 16178  				s = r1
 16179  			}
 16180  		}
 16181  		r1 = *(*prg.mem[s].hh()).rh()
 16182  		if int32(*(*prg.mem[r1].hh()).lh()) == memMin {
 16183  			break
 16184  		}
 16185  	}
 16186  	if int32(t) == protoDependent {
 16187  		*prg.mem[int32(r1)+1].int() = -prg.makeScaled(*prg.mem[int32(r1)+1].int(), v)
 16188  	} else if v != -02000000000 {
 16189  		*prg.mem[int32(r1)+1].int() = -prg.makeFraction(*prg.mem[int32(r1)+1].int(), v)
 16190  	}
 16191  	finalNode = r1
 16192  	p = *(*prg.mem[3000-1].hh()).rh()
 16193  	if prg.internal[tracingEquations-1] > 0 {
 16194  		if prg.interesting(x) {
 16195  			prg.beginDiagnostic()
 16196  			prg.printNl(strNumber( /* "## " */ 596))
 16197  			prg.printVariableName(x)
 16198  			// \xref[]]]\#\#_][\.[\#\#]]
 16199  			w = n
 16200  			for w > 0 {
 16201  				prg.print( /* "*4" */ 589)
 16202  				w = w - 2
 16203  			}
 16204  			prg.printChar(asciiCode('='))
 16205  			prg.printDependency(p, smallNumber(dependent))
 16206  			prg.endDiagnostic(false)
 16207  		}
 16208  	}
 16209  
 16210  	// Simplify all existing dependencies by substituting for |x|
 16211  	prevR = uint16(memMin + 3 + 10)
 16212  	r1 = *(*prg.mem[memMin+3+10].hh()).rh()
 16213  	for int32(r1) != memMin+3+10 {
 16214  		s = *(*prg.mem[int32(r1)+1].hh()).rh()
 16215  		q = prg.pWithXBecomingQ(s, x, p, *(*prg.mem[r1].hh()).b0())
 16216  		if int32(*(*prg.mem[q].hh()).lh()) == memMin {
 16217  			prg.makeKnown(r1, q)
 16218  		} else {
 16219  			*(*prg.mem[int32(r1)+1].hh()).rh() = q
 16220  			for {
 16221  				q = *(*prg.mem[q].hh()).rh()
 16222  				if int32(*(*prg.mem[q].hh()).lh()) == memMin {
 16223  					break
 16224  				}
 16225  			}
 16226  			prevR = q
 16227  		}
 16228  		r1 = *(*prg.mem[prevR].hh()).rh()
 16229  	}
 16230  
 16231  	// Change variable |x| from |independent| to |dependent| or |known|
 16232  	if n > 0 {
 16233  		s = uint16(3000 - 1)
 16234  		*(*prg.mem[3000-1].hh()).rh() = p
 16235  		r1 = p
 16236  		for {
 16237  			if n > 30 {
 16238  				w = 0
 16239  			} else {
 16240  				w = *prg.mem[int32(r1)+1].int() / prg.twoToThe[n]
 16241  			}
 16242  			if abs(w) <= halfFractionThreshold && int32(*(*prg.mem[r1].hh()).lh()) != memMin {
 16243  				*(*prg.mem[s].hh()).rh() = *(*prg.mem[r1].hh()).rh()
 16244  				prg.freeNode(r1, halfword(depNodeSize))
 16245  			} else {
 16246  				*prg.mem[int32(r1)+1].int() = w
 16247  				s = r1
 16248  			}
 16249  			r1 = *(*prg.mem[s].hh()).rh()
 16250  			if int32(*(*prg.mem[s].hh()).lh()) == memMin {
 16251  				break
 16252  			}
 16253  		}
 16254  		p = *(*prg.mem[3000-1].hh()).rh()
 16255  	}
 16256  	if int32(*(*prg.mem[p].hh()).lh()) == memMin {
 16257  		*(*prg.mem[x].hh()).b0() = byte(known)
 16258  		*prg.mem[int32(x)+1].int() = *prg.mem[int32(p)+1].int()
 16259  		if abs(*prg.mem[int32(x)+1].int()) >= 02000000000 {
 16260  			prg.valTooBig(*prg.mem[int32(x)+1].int())
 16261  		}
 16262  		prg.freeNode(p, halfword(depNodeSize))
 16263  		if prg.curExp == int32(x) {
 16264  			if int32(prg.curType) == independent {
 16265  				prg.curExp = *prg.mem[int32(x)+1].int()
 16266  				prg.curType = byte(known)
 16267  				prg.freeNode(x, halfword(valueNodeSize))
 16268  			}
 16269  		}
 16270  	} else {
 16271  		*(*prg.mem[x].hh()).b0() = byte(dependent)
 16272  		prg.depFinal = finalNode
 16273  		prg.newDep(x, p)
 16274  		if prg.curExp == int32(x) {
 16275  			if int32(prg.curType) == independent {
 16276  				prg.curType = byte(dependent)
 16277  			}
 16278  		}
 16279  	}
 16280  	if prg.fixNeeded {
 16281  		prg.fixDependencies()
 16282  	}
 16283  }
 16284  
 16285  // 618. \[29] Dynamic nonlinear equations
 16286  
 16287  // tangle:pos ../../mf.web:13105:38:
 16288  
 16289  // Variables of numeric type are maintained by the general scheme of
 16290  // independent, dependent, and known values that we have just studied;
 16291  // and the components of pair and transform variables are handled in the
 16292  // same way. But \MF\ also has five other types of values: \&[boolean],
 16293  // \&[string], \&[pen], \&[path], and \&[picture]; what about them?
 16294  //
 16295  // Equations are allowed between nonlinear quantities, but only in a
 16296  // simple form. Two variables that haven't yet been assigned values are
 16297  // either equal to each other, or they're not.
 16298  //
 16299  // Before a boolean variable has received a value, its type is |unknown_boolean|;
 16300  // similarly, there are variables whose type is |unknown_string|, |unknown_pen|,
 16301  // |unknown_path|, and |unknown_picture|. In such cases the value is either
 16302  // |null| (which means that no other variables are equivalent to this one), or
 16303  // it points to another variable of the same undefined type. The pointers in the
 16304  // latter case form a cycle of nodes, which we shall call a ``ring.''
 16305  // Rings of undefined variables may include capsules, which arise as
 16306  // intermediate results within expressions or as \&[expr] parameters to macros.
 16307  //
 16308  // When one member of a ring receives a value, the same value is given to
 16309  // all the other members. In the case of paths and pictures, this implies
 16310  // making separate copies of a potentially large data structure; users should
 16311  // restrain their enthusiasm for such generality, unless they have lots and
 16312  // lots of memory space.
 16313  
 16314  // 619.
 16315  
 16316  // tangle:pos ../../mf.web:13131:3:
 16317  
 16318  // The following procedure is called when a capsule node is being
 16319  // added to a ring (e.g., when an unknown variable is mentioned in an expression).
 16320  func (prg *prg) newRingEntry(p halfword) (r halfword) {
 16321  	var (
 16322  		q halfword // the new capsule node
 16323  	)
 16324  	q = prg.getNode(valueNodeSize)
 16325  	*(*prg.mem[q].hh()).b1() = byte(capsule)
 16326  	*(*prg.mem[q].hh()).b0() = *(*prg.mem[p].hh()).b0()
 16327  	if *prg.mem[int32(p)+1].int() == memMin {
 16328  		*prg.mem[int32(q)+1].int() = int32(p)
 16329  	} else {
 16330  		*prg.mem[int32(q)+1].int() = *prg.mem[int32(p)+1].int()
 16331  	}
 16332  	*prg.mem[int32(p)+1].int() = int32(q)
 16333  	r = q
 16334  	return r
 16335  }
 16336  
 16337  // 621.
 16338  
 16339  // tangle:pos ../../mf.web:13157:3:
 16340  
 16341  // Eventually there might be an equation that assigns values to all of the
 16342  // variables in a ring. The |nonlinear_eq| subroutine does the necessary
 16343  // propagation of values.
 16344  //
 16345  // If the parameter |flush_p| is |true|, node |p| itself needn't receive a
 16346  // value; it will soon be recycled.
 16347  func (prg *prg) nonlinearEq(v int32, p halfword, flushP bool) {
 16348  	var (
 16349  		t     smallNumber // the type of ring |p|
 16350  		q, r1 halfword    // link manipulation registers
 16351  	)
 16352  	t = byte(int32(*(*prg.mem[p].hh()).b0()) - unknownTag)
 16353  	q = uint16(*prg.mem[int32(p)+1].int())
 16354  	if flushP {
 16355  		*(*prg.mem[p].hh()).b0() = byte(vacuous)
 16356  	} else {
 16357  		p = q
 16358  	}
 16359  	for {
 16360  		r1 = uint16(*prg.mem[int32(q)+1].int())
 16361  		*(*prg.mem[q].hh()).b0() = t
 16362  		switch t {
 16363  		case booleanType:
 16364  			*prg.mem[int32(q)+1].int() = v
 16365  		case stringType:
 16366  			*prg.mem[int32(q)+1].int() = v
 16367  			{
 16368  				if int32(prg.strRef[v]) < maxStrRef {
 16369  					prg.strRef[v] = byte(int32(prg.strRef[v]) + 1)
 16370  				}
 16371  			}
 16372  
 16373  		case penType:
 16374  			*prg.mem[int32(q)+1].int() = v
 16375  			*(*prg.mem[v].hh()).lh() = uint16(int32(*(*prg.mem[v].hh()).lh()) + 1)
 16376  
 16377  		case pathType:
 16378  			*prg.mem[int32(q)+1].int() = int32(prg.copyPath(halfword(v)))
 16379  		case pictureType:
 16380  			*prg.mem[int32(q)+1].int() = int32(prg.copyEdges(halfword(v)))
 16381  		} // there ain't no more cases
 16382  		q = r1
 16383  		if int32(q) == int32(p) {
 16384  			break
 16385  		}
 16386  	}
 16387  }
 16388  
 16389  // 622.
 16390  
 16391  // tangle:pos ../../mf.web:13183:3:
 16392  
 16393  // If two members of rings are equated, and if they have the same type,
 16394  // the |ring_merge| procedure is called on to make them equivalent.
 16395  func (prg *prg) ringMerge(p, q halfword) {
 16396  	var (
 16397  		r1 halfword // traverses one list
 16398  	)
 16399  	r1 = uint16(*prg.mem[int32(p)+1].int())
 16400  	for int32(r1) != int32(p) {
 16401  		if int32(r1) == int32(q) {
 16402  			{
 16403  				{
 16404  					if int32(prg.interaction) == errorStopMode {
 16405  					}
 16406  					prg.printNl(strNumber( /* "! " */ 261))
 16407  					prg.print( /* "Redundant equation" */ 599) /* \xref[!\relax]  */
 16408  				}
 16409  
 16410  				// \xref[Redundant equation]
 16411  				{
 16412  					prg.helpPtr = 2
 16413  					prg.helpLine[1] = /* "I already knew that this equation was true." */ 600
 16414  					prg.helpLine[0] = /* "But perhaps no harm has been done; let's continue." */ 601
 16415  				}
 16416  
 16417  				prg.putGetError()
 16418  			}
 16419  
 16420  			goto exit
 16421  		}
 16422  		r1 = uint16(*prg.mem[int32(r1)+1].int())
 16423  	}
 16424  	r1 = uint16(*prg.mem[int32(p)+1].int())
 16425  	*prg.mem[int32(p)+1].int() = *prg.mem[int32(q)+1].int()
 16426  	*prg.mem[int32(q)+1].int() = int32(r1)
 16427  
 16428  exit:
 16429  }
 16430  
 16431  // 626.
 16432  
 16433  // tangle:pos ../../mf.web:13271:3:
 16434  
 16435  // Here is a procedure that displays a given command in braces, in the
 16436  // user's transcript file.
 16437  func (prg *prg) showCmdMod(c, m int32) {
 16438  	prg.beginDiagnostic()
 16439  	prg.printNl(strNumber('{'))
 16440  	prg.printCmdMod(c, m)
 16441  	prg.printChar(asciiCode('}'))
 16442  	prg.endDiagnostic(false)
 16443  } // \2
 16444  
 16445  func (prg *prg) showContext() {
 16446  	var (
 16447  		oldSetting/* 0..maxSelector */ byte // saved |selector| setting
 16448  
 16449  		// Local variables for formatting calculations
 16450  		i/* 0..bufSize */ uint16       // index into |buffer|
 16451  		l                        int32 // length of descriptive information on line 1
 16452  		m                        int32 // context information gathered for line 2
 16453  		n/* 0..errorLine */ byte       // length of line 1
 16454  		p                        int32 // starting or ending place in |trick_buf|
 16455  		q                        int32 // temporary index
 16456  	)
 16457  	prg.filePtr = prg.inputPtr
 16458  	prg.inputStack[prg.filePtr] = prg.curInput
 16459  	// store current state
 16460  	for true {
 16461  		prg.curInput = prg.inputStack[prg.filePtr] // enter into the context
 16462  
 16463  		// Display the current context
 16464  		if int32(prg.filePtr) == int32(prg.inputPtr) || int32(prg.curInput.indexField) <= maxInOpen || int32(prg.curInput.indexField) != backedUp || int32(prg.curInput.locField) != memMin {
 16465  			prg.tally = 0 // get ready to count characters
 16466  			oldSetting = prg.selector
 16467  			if int32(prg.curInput.indexField) <= maxInOpen {
 16468  				if int32(prg.curInput.nameField) <= 1 {
 16469  					if int32(prg.curInput.nameField) == 0 && int32(prg.filePtr) == 0 {
 16470  						prg.printNl(strNumber( /* "<*>" */ 603))
 16471  					} else {
 16472  						prg.printNl(strNumber( /* "<insert>" */ 604))
 16473  					}
 16474  				} else if int32(prg.curInput.nameField) == 2 {
 16475  					prg.printNl(strNumber( /* "<scantokens>" */ 605))
 16476  				} else {
 16477  					prg.printNl(strNumber( /* "l." */ 606))
 16478  					prg.printInt(prg.line)
 16479  				}
 16480  				prg.printChar(asciiCode(' '))
 16481  
 16482  				// Pseudoprint the line
 16483  				{
 16484  					l = prg.tally
 16485  					prg.tally = 0
 16486  					prg.selector = byte(pseudo)
 16487  					prg.trickCount = 1000000
 16488  				}
 16489  				if int32(prg.curInput.limitField) > 0 {
 16490  					for ii := int32(prg.curInput.startField); ii <= int32(prg.curInput.limitField)-1; ii++ {
 16491  						i = uint16(ii)
 16492  						_ = i
 16493  						if int32(i) == int32(prg.curInput.locField) {
 16494  							prg.firstCount = prg.tally
 16495  							prg.trickCount = prg.tally + 1 + errorLine - halfErrorLine
 16496  							if prg.trickCount < errorLine {
 16497  								prg.trickCount = errorLine
 16498  							}
 16499  						}
 16500  						prg.print(int32(prg.buffer[i]))
 16501  					}
 16502  				}
 16503  			} else {
 16504  				switch prg.curInput.indexField {
 16505  				case foreverText:
 16506  					prg.printNl(strNumber( /* "<forever> " */ 607))
 16507  				case loopText:
 16508  					// Print the current loop value
 16509  					prg.printNl(strNumber( /* "<for(" */ 612))
 16510  					p = int32(prg.paramStack[prg.curInput.limitField])
 16511  					if p != memMin {
 16512  						if int32(*(*prg.mem[p].hh()).rh()) == memMin+1 {
 16513  							prg.printExp(halfword(p), smallNumber(0))
 16514  						} else {
 16515  							prg.showTokenList(p, memMin, 20, prg.tally)
 16516  						}
 16517  					}
 16518  					prg.print( /* ")> " */ 613)
 16519  
 16520  				case parameter:
 16521  					prg.printNl(strNumber( /* "<argument> " */ 608))
 16522  				case backedUp:
 16523  					if int32(prg.curInput.locField) == memMin {
 16524  						prg.printNl(strNumber( /* "<recently read> " */ 609))
 16525  					} else {
 16526  						prg.printNl(strNumber( /* "<to be read again> " */ 610))
 16527  					}
 16528  				case inserted:
 16529  					prg.printNl(strNumber( /* "<inserted text> " */ 611))
 16530  				case macro:
 16531  					prg.printLn()
 16532  					if int32(prg.curInput.nameField) != memMin {
 16533  						prg.slowPrint(int32(*prg.hash[prg.curInput.nameField-1].rh()))
 16534  					} else {
 16535  						// Print the name of a \&[vardef]'d macro
 16536  						p = int32(prg.paramStack[prg.curInput.limitField])
 16537  						if p == memMin {
 16538  							prg.showTokenList(int32(prg.paramStack[int32(prg.curInput.limitField)+1]), memMin, 20, prg.tally)
 16539  						} else {
 16540  							q = p
 16541  							for int32(*(*prg.mem[q].hh()).rh()) != memMin {
 16542  								q = int32(*(*prg.mem[q].hh()).rh())
 16543  							}
 16544  							*(*prg.mem[q].hh()).rh() = prg.paramStack[int32(prg.curInput.limitField)+1]
 16545  							prg.showTokenList(p, memMin, 20, prg.tally)
 16546  							*(*prg.mem[q].hh()).rh() = uint16(memMin)
 16547  						}
 16548  					}
 16549  					prg.print( /* "->" */ 501)
 16550  
 16551  				default:
 16552  					prg.printNl(strNumber('?')) // this should never happen
 16553  					// \xref[?\relax]
 16554  				}
 16555  
 16556  				// Pseudoprint the token list
 16557  				{
 16558  					l = prg.tally
 16559  					prg.tally = 0
 16560  					prg.selector = byte(pseudo)
 16561  					prg.trickCount = 1000000
 16562  				}
 16563  				if int32(prg.curInput.indexField) != macro {
 16564  					prg.showTokenList(int32(prg.curInput.startField), int32(prg.curInput.locField), 100000, 0)
 16565  				} else {
 16566  					prg.showMacro(prg.curInput.startField, int32(prg.curInput.locField), 100000)
 16567  				}
 16568  			}
 16569  			prg.selector = oldSetting // stop pseudoprinting
 16570  
 16571  			// Print two lines using the tricky pseudoprinted information
 16572  			if prg.trickCount == 1000000 {
 16573  				prg.firstCount = prg.tally
 16574  				prg.trickCount = prg.tally + 1 + errorLine - halfErrorLine
 16575  				if prg.trickCount < errorLine {
 16576  					prg.trickCount = errorLine
 16577  				}
 16578  			}
 16579  			// |set_trick_count| must be performed
 16580  			if prg.tally < prg.trickCount {
 16581  				m = prg.tally - prg.firstCount
 16582  			} else {
 16583  				m = prg.trickCount - prg.firstCount
 16584  			} // context on line 2
 16585  			if l+prg.firstCount <= halfErrorLine {
 16586  				p = 0
 16587  				n = byte(l + prg.firstCount)
 16588  			} else {
 16589  				prg.print( /* "..." */ 276)
 16590  				p = l + prg.firstCount - halfErrorLine + 3
 16591  				n = byte(halfErrorLine)
 16592  			}
 16593  			for ii := p; ii <= prg.firstCount-1; ii++ {
 16594  				q = ii
 16595  				_ = q
 16596  				prg.printChar(prg.trickBuf[q%errorLine])
 16597  			}
 16598  			prg.printLn()
 16599  			for ii := int32(1); ii <= int32(n); ii++ {
 16600  				q = ii
 16601  				_ = q
 16602  				prg.printChar(asciiCode(' '))
 16603  			} // print |n| spaces to begin line~2
 16604  			if m+int32(n) <= errorLine {
 16605  				p = prg.firstCount + m
 16606  			} else {
 16607  				p = prg.firstCount + (errorLine - int32(n) - 3)
 16608  			}
 16609  			for ii := prg.firstCount; ii <= p-1; ii++ {
 16610  				q = ii
 16611  				_ = q
 16612  				prg.printChar(prg.trickBuf[q%errorLine])
 16613  			}
 16614  			if m+int32(n) > errorLine {
 16615  				prg.print( /* "..." */ 276)
 16616  			}
 16617  		}
 16618  		if int32(prg.curInput.indexField) <= maxInOpen {
 16619  			if int32(prg.curInput.nameField) > 2 || int32(prg.filePtr) == 0 {
 16620  				goto done
 16621  			}
 16622  		}
 16623  		prg.filePtr = byte(int32(prg.filePtr) - 1)
 16624  	}
 16625  
 16626  done:
 16627  	prg.curInput = prg.inputStack[prg.inputPtr] // restore original state
 16628  }
 16629  
 16630  // 642.
 16631  
 16632  // tangle:pos ../../mf.web:13601:3:
 16633  
 16634  // The following code tells the print routines to gather
 16635  // the desired information.
 16636  
 16637  // 647. \[32] Maintaining the input stacks
 16638  
 16639  // tangle:pos ../../mf.web:13655:39:
 16640  
 16641  // The following subroutines change the input status in commonly needed ways.
 16642  //
 16643  // First comes |push_input|, which stores the current state and creates a
 16644  // new level (having, initially, the same properties as the old).
 16645  
 16646  // 648.
 16647  
 16648  // tangle:pos ../../mf.web:13671:3:
 16649  
 16650  // And of course what goes up must come down.
 16651  
 16652  // 649.
 16653  
 16654  // tangle:pos ../../mf.web:13677:3:
 16655  
 16656  // Here is a procedure that starts a new level of token-list input, given
 16657  // a token list |p| and its type |t|. If |t=macro|, the calling routine should
 16658  // set |name|, reset~|loc|, and increase the macro's reference count.
 16659  func (prg *prg) beginTokenList(p halfword, t quarterword) {
 16660  	{
 16661  		if int32(prg.inputPtr) > int32(prg.maxInStack) {
 16662  			prg.maxInStack = prg.inputPtr
 16663  			if int32(prg.inputPtr) == stackSize {
 16664  				prg.overflow(strNumber( /* "input stack size" */ 614), stackSize)
 16665  			} /* \xref[METAFONT capacity exceeded input stack size][\quad input stack size]  */
 16666  		}
 16667  		prg.inputStack[prg.inputPtr] = prg.curInput
 16668  		prg.inputPtr = byte(int32(prg.inputPtr) + 1)
 16669  	}
 16670  	prg.curInput.startField = p
 16671  	prg.curInput.indexField = t
 16672  	prg.curInput.limitField = uint16(prg.paramPtr)
 16673  	prg.curInput.locField = p
 16674  }
 16675  
 16676  // 650.
 16677  
 16678  // tangle:pos ../../mf.web:13688:3:
 16679  
 16680  // When a token list has been fully scanned, the following computations
 16681  // should be done as we leave that level of input.
 16682  // \xref[inner loop]
 16683  func (prg *prg) endTokenList() {
 16684  	var (
 16685  		p halfword // temporary register
 16686  	)
 16687  	if int32(prg.curInput.indexField) >= backedUp {
 16688  		if int32(prg.curInput.indexField) <= inserted {
 16689  			prg.flushTokenList(prg.curInput.startField)
 16690  			goto done
 16691  		} else {
 16692  			prg.deleteMacRef(prg.curInput.startField)
 16693  		}
 16694  	} // update reference count
 16695  	for int32(prg.paramPtr) > int32(prg.curInput.limitField) { // parameters must be flushed
 16696  		prg.paramPtr = byte(int32(prg.paramPtr) - 1)
 16697  		p = prg.paramStack[prg.paramPtr]
 16698  		if int32(p) != memMin {
 16699  			if int32(*(*prg.mem[p].hh()).rh()) == memMin+1 {
 16700  				prg.recycleValue(p)
 16701  				prg.freeNode(p, halfword(valueNodeSize))
 16702  			} else {
 16703  				prg.flushTokenList(p)
 16704  			}
 16705  		} // it's a \&[suffix] or \&[text] parameter
 16706  	}
 16707  
 16708  done:
 16709  	{
 16710  		prg.inputPtr = byte(int32(prg.inputPtr) - 1)
 16711  		prg.curInput = prg.inputStack[prg.inputPtr]
 16712  	}
 16713  	{
 16714  		if prg.interrupt != 0 {
 16715  			prg.pauseForInstructions()
 16716  		}
 16717  	}
 16718  }
 16719  
 16720  // 651.
 16721  
 16722  // tangle:pos ../../mf.web:13712:3:
 16723  
 16724  // The contents of |cur_cmd,cur_mod,cur_sym| are placed into an equivalent
 16725  // token by the |cur_tok| routine.
 16726  // \xref[inner loop]
 16727  // \4
 16728  // Declare the procedure called |make_exp_copy|
 16729  // \4
 16730  // Declare subroutines needed by |make_exp_copy|
 16731  func (prg *prg) encapsulate(p halfword) {
 16732  	prg.curExp = int32(prg.getNode(valueNodeSize))
 16733  	*(*prg.mem[prg.curExp].hh()).b0() = prg.curType
 16734  	*(*prg.mem[prg.curExp].hh()).b1() = byte(capsule)
 16735  	prg.newDep(halfword(prg.curExp), p)
 16736  }
 16737  
 16738  func (prg *prg) install(r1, q halfword) {
 16739  	var (
 16740  		p halfword // temporary register
 16741  	)
 16742  	if int32(*(*prg.mem[q].hh()).b0()) == known {
 16743  		*prg.mem[int32(r1)+1].int() = *prg.mem[int32(q)+1].int()
 16744  		*(*prg.mem[r1].hh()).b0() = byte(known)
 16745  	} else if int32(*(*prg.mem[q].hh()).b0()) == independent {
 16746  		p = prg.singleDependency(q)
 16747  		if int32(p) == int32(prg.depFinal) {
 16748  			*(*prg.mem[r1].hh()).b0() = byte(known)
 16749  			*prg.mem[int32(r1)+1].int() = 0
 16750  			prg.freeNode(p, halfword(depNodeSize))
 16751  		} else {
 16752  			*(*prg.mem[r1].hh()).b0() = byte(dependent)
 16753  			prg.newDep(r1, p)
 16754  		}
 16755  	} else {
 16756  		*(*prg.mem[r1].hh()).b0() = *(*prg.mem[q].hh()).b0()
 16757  		prg.newDep(r1, prg.copyDepList(*(*prg.mem[int32(q)+1].hh()).rh()))
 16758  	}
 16759  }
 16760  
 16761  func (prg *prg) makeExpCopy(p halfword) {
 16762  	var (
 16763  		q, r1, t halfword // registers for list manipulation
 16764  	)
 16765  restart:
 16766  	prg.curType = *(*prg.mem[p].hh()).b0()
 16767  	switch prg.curType {
 16768  	case vacuous, booleanType, known:
 16769  		prg.curExp = *prg.mem[int32(p)+1].int()
 16770  	case unknownBoolean, unknownString, unknownPen, unknownPicture,
 16771  		unknownPath:
 16772  		prg.curExp = int32(prg.newRingEntry(p))
 16773  	case stringType:
 16774  		prg.curExp = *prg.mem[int32(p)+1].int()
 16775  		{
 16776  			if int32(prg.strRef[prg.curExp]) < maxStrRef {
 16777  				prg.strRef[prg.curExp] = byte(int32(prg.strRef[prg.curExp]) + 1)
 16778  			}
 16779  		}
 16780  
 16781  	case penType:
 16782  		prg.curExp = *prg.mem[int32(p)+1].int()
 16783  		*(*prg.mem[prg.curExp].hh()).lh() = uint16(int32(*(*prg.mem[prg.curExp].hh()).lh()) + 1)
 16784  
 16785  	case pictureType:
 16786  		prg.curExp = int32(prg.copyEdges(halfword(*prg.mem[int32(p)+1].int())))
 16787  	case pathType, futurePen:
 16788  		prg.curExp = int32(prg.copyPath(halfword(*prg.mem[int32(p)+1].int())))
 16789  	case transformType, pairType:
 16790  		// Copy the big node |p|
 16791  		if *prg.mem[int32(p)+1].int() == memMin {
 16792  			prg.initBigNode(p)
 16793  		}
 16794  		t = prg.getNode(valueNodeSize)
 16795  		*(*prg.mem[t].hh()).b1() = byte(capsule)
 16796  		*(*prg.mem[t].hh()).b0() = prg.curType
 16797  		prg.initBigNode(t)
 16798  
 16799  		q = uint16(*prg.mem[int32(p)+1].int() + int32(prg.bigNodeSize[prg.curType-13]))
 16800  		r1 = uint16(*prg.mem[int32(t)+1].int() + int32(prg.bigNodeSize[prg.curType-13]))
 16801  		for {
 16802  			q = uint16(int32(q) - 2)
 16803  			r1 = uint16(int32(r1) - 2)
 16804  			prg.install(r1, q)
 16805  			if int32(q) == *prg.mem[int32(p)+1].int() {
 16806  				break
 16807  			}
 16808  		}
 16809  		prg.curExp = int32(t)
 16810  
 16811  	case dependent, protoDependent:
 16812  		prg.encapsulate(prg.copyDepList(*(*prg.mem[int32(p)+1].hh()).rh()))
 16813  	case numericType:
 16814  		{
 16815  			if prg.serialNo > 017777777777-sScale {
 16816  				prg.overflow(strNumber( /* "independent variables" */ 587), prg.serialNo/sScale)
 16817  			} /* \xref[METAFONT capacity exceeded independent variables][\quad independent variables]  */
 16818  			*(*prg.mem[p].hh()).b0() = byte(independent)
 16819  			prg.serialNo = prg.serialNo + sScale
 16820  			*prg.mem[int32(p)+1].int() = prg.serialNo
 16821  		}
 16822  		goto restart
 16823  
 16824  	case independent:
 16825  		q = prg.singleDependency(p)
 16826  		if int32(q) == int32(prg.depFinal) {
 16827  			prg.curType = byte(known)
 16828  			prg.curExp = 0
 16829  			prg.freeNode(q, halfword(depNodeSize))
 16830  		} else {
 16831  			prg.curType = byte(dependent)
 16832  			prg.encapsulate(q)
 16833  		}
 16834  
 16835  	default:
 16836  		prg.confusion(strNumber( /* "copy" */ 800))
 16837  		// \xref[this can't happen copy][\quad copy]
 16838  	}
 16839  }
 16840  
 16841  func (prg *prg) curTok() (r halfword) {
 16842  	var (
 16843  		p        halfword    // a new token node
 16844  		saveType smallNumber // |cur_type| to be restored
 16845  		saveExp  int32       // |cur_exp| to be restored
 16846  	)
 16847  	if int32(prg.curSym) == 0 {
 16848  		if int32(prg.curCmd) == capsuleToken {
 16849  			saveType = prg.curType
 16850  			saveExp = prg.curExp
 16851  			prg.makeExpCopy(halfword(prg.curMod))
 16852  			p = prg.stashCurExp()
 16853  			*(*prg.mem[p].hh()).rh() = uint16(memMin)
 16854  			prg.curType = saveType
 16855  			prg.curExp = saveExp
 16856  		} else {
 16857  			p = prg.getNode(tokenNodeSize)
 16858  			*prg.mem[int32(p)+1].int() = prg.curMod
 16859  			*(*prg.mem[p].hh()).b1() = byte(token)
 16860  			if int32(prg.curCmd) == numericToken {
 16861  				*(*prg.mem[p].hh()).b0() = byte(known)
 16862  			} else {
 16863  				*(*prg.mem[p].hh()).b0() = byte(stringType)
 16864  			}
 16865  		}
 16866  	} else {
 16867  		{
 16868  			p = prg.avail
 16869  			if int32(p) == memMin {
 16870  				p = prg.getAvail()
 16871  			} else {
 16872  				prg.avail = *(*prg.mem[p].hh()).rh()
 16873  				*(*prg.mem[p].hh()).rh() = uint16(memMin)
 16874  				prg.dynUsed = prg.dynUsed + 1
 16875  			}
 16876  		}
 16877  		*(*prg.mem[p].hh()).lh() = prg.curSym
 16878  	}
 16879  	r = p
 16880  	return r
 16881  }
 16882  
 16883  // 652.
 16884  
 16885  // tangle:pos ../../mf.web:13737:3:
 16886  
 16887  // Sometimes \MF\ has read too far and wants to ``unscan'' what it has
 16888  // seen. The |back_input| procedure takes care of this by putting the token
 16889  // just scanned back into the input stream, ready to be read again.
 16890  // If |cur_sym<>0|, the values of |cur_cmd| and |cur_mod| are irrelevant.
 16891  func (prg *prg) backInput() { // undoes one token of input
 16892  	var (
 16893  		p halfword // a token list of length one
 16894  	)
 16895  	p = prg.curTok()
 16896  	for int32(prg.curInput.indexField) > maxInOpen && int32(prg.curInput.locField) == memMin {
 16897  		prg.endTokenList()
 16898  	} // conserve stack space
 16899  	prg.beginTokenList(p, quarterword(backedUp))
 16900  }
 16901  
 16902  func (prg *prg) backError() {
 16903  	prg.okToInterrupt = false
 16904  	prg.backInput()
 16905  	prg.okToInterrupt = true
 16906  	prg.error1()
 16907  }
 16908  
 16909  func (prg *prg) insError() {
 16910  	prg.okToInterrupt = false
 16911  	prg.backInput()
 16912  	prg.curInput.indexField = byte(inserted)
 16913  	prg.okToInterrupt = true
 16914  	prg.error1()
 16915  } // \2
 16916  
 16917  func (prg *prg) beginFileReading() {
 16918  	if int32(prg.inOpen) == maxInOpen {
 16919  		prg.overflow(strNumber( /* "text input levels" */ 615), maxInOpen)
 16920  	}
 16921  	// \xref[METAFONT capacity exceeded text input levels][\quad text input levels]
 16922  	if int32(prg.first) == bufSize {
 16923  		prg.overflow(strNumber( /* "buffer size" */ 256), bufSize)
 16924  	}
 16925  	// \xref[METAFONT capacity exceeded buffer size][\quad buffer size]
 16926  	prg.inOpen = byte(int32(prg.inOpen) + 1) /*   */
 16927  	{
 16928  		if int32(prg.inputPtr) > int32(prg.maxInStack) {
 16929  			prg.maxInStack = prg.inputPtr
 16930  			if int32(prg.inputPtr) == stackSize {
 16931  				prg.overflow(strNumber( /* "input stack size" */ 614), stackSize)
 16932  			} /* \xref[METAFONT capacity exceeded input stack size][\quad input stack size]  */
 16933  		}
 16934  		prg.inputStack[prg.inputPtr] = prg.curInput
 16935  		prg.inputPtr = byte(int32(prg.inputPtr) + 1)
 16936  	}
 16937  	prg.curInput.indexField = prg.inOpen
 16938  	prg.lineStack[prg.curInput.indexField-1] = prg.line
 16939  	prg.curInput.startField = prg.first
 16940  	prg.curInput.nameField = 0 // |terminal_input| is now |true|
 16941  }
 16942  
 16943  // 655.
 16944  
 16945  // tangle:pos ../../mf.web:13778:3:
 16946  
 16947  // Conversely, the variables must be downdated when such a level of input
 16948  // is finished:
 16949  func (prg *prg) endFileReading() {
 16950  	prg.first = prg.curInput.startField
 16951  	prg.line = prg.lineStack[prg.curInput.indexField-1]
 16952  	if int32(prg.curInput.indexField) != int32(prg.inOpen) {
 16953  		prg.confusion(strNumber( /* "endinput" */ 616))
 16954  	}
 16955  	// \xref[this can't happen endinput][\quad endinput]
 16956  	if int32(prg.curInput.nameField) > 2 {
 16957  		prg.aClose(prg.inputFile[prg.curInput.indexField-1])
 16958  	} // forget it
 16959  	//
 16960  	{
 16961  		prg.inputPtr = byte(int32(prg.inputPtr) - 1)
 16962  		prg.curInput = prg.inputStack[prg.inputPtr]
 16963  	}
 16964  	prg.inOpen = byte(int32(prg.inOpen) - 1)
 16965  } // \2
 16966  
 16967  func (prg *prg) clearForErrorPrompt() {
 16968  	for int32(prg.curInput.indexField) <= maxInOpen && int32(prg.curInput.nameField) == 0 && int32(prg.inputPtr) > 0 && int32(prg.curInput.locField) == int32(prg.curInput.limitField) {
 16969  		prg.endFileReading()
 16970  	}
 16971  	prg.printLn()
 16972  }
 16973  
 16974  // 658. \[33] Getting the next token
 16975  
 16976  // tangle:pos ../../mf.web:13813:33:
 16977  
 16978  // The heart of \MF's input mechanism is the |get_next| procedure, which
 16979  // we shall develop in the next few sections of the program. Perhaps we
 16980  // shouldn't actually call it the ``heart,'' however; it really acts as \MF's
 16981  // eyes and mouth, reading the source files and gobbling them up. And it also
 16982  // helps \MF\ to regurgitate stored token lists that are to be processed again.
 16983  //
 16984  // The main duty of |get_next| is to input one token and to set |cur_cmd|
 16985  // and |cur_mod| to that token's command code and modifier. Furthermore, if
 16986  // the input token is a symbolic token, that token's |hash| address
 16987  // is stored in |cur_sym|; otherwise |cur_sym| is set to zero.
 16988  //
 16989  // Underlying this simple description is a certain amount of complexity
 16990  // because of all the cases that need to be handled.
 16991  // However, the inner loop of |get_next| is reasonably short and fast.
 16992  
 16993  // 661.
 16994  
 16995  // tangle:pos ../../mf.web:13856:3:
 16996  
 16997  // The following subroutine
 16998  // is called when an `\&[outer]' symbolic token has been scanned or
 16999  // when the end of a file has been reached. These two cases are distinguished
 17000  // by |cur_sym|, which is zero at the end of a file.
 17001  func (prg *prg) checkOuterValidity() (r bool) {
 17002  	var (
 17003  		p halfword // points to inserted token list
 17004  	)
 17005  	if int32(prg.scannerStatus) == normal {
 17006  		r = true
 17007  	} else {
 17008  		prg.deletionsAllowed = false
 17009  
 17010  		// Back up an outer symbolic token so that it can be reread
 17011  		if int32(prg.curSym) != 0 {
 17012  			p = prg.getAvail()
 17013  			*(*prg.mem[p].hh()).lh() = prg.curSym
 17014  			prg.beginTokenList(p, quarterword(backedUp)) // prepare to read the symbolic token again
 17015  		}
 17016  		if int32(prg.scannerStatus) > skipping {
 17017  			prg.runaway() // print the definition-so-far
 17018  			if int32(prg.curSym) == 0 {
 17019  				if int32(prg.interaction) == errorStopMode {
 17020  				}
 17021  				prg.printNl(strNumber( /* "! " */ 261))
 17022  				prg.print( /* "File ended" */ 622) /* \xref[!\relax]  */
 17023  			} else {
 17024  				{
 17025  					if int32(prg.interaction) == errorStopMode {
 17026  					}
 17027  					prg.printNl(strNumber( /* "! " */ 261))
 17028  					prg.print( /* "Forbidden token found" */ 623) /* \xref[!\relax]  */
 17029  				}
 17030  				// \xref[Forbidden token found...]
 17031  			}
 17032  			prg.print( /* " while scanning " */ 624)
 17033  			{
 17034  				prg.helpPtr = 4
 17035  				prg.helpLine[3] = /* "I suspect you have forgotten an `enddef'," */ 625
 17036  				prg.helpLine[2] = /* "causing me to read past where you wanted me to stop." */ 626
 17037  				prg.helpLine[1] = /* "I'll try to recover; but if the error is serious," */ 627
 17038  				prg.helpLine[0] = /* "you'd better type `E' or `X' now and fix your file." */ 628
 17039  			}
 17040  
 17041  			switch prg.scannerStatus {
 17042  			case flushing:
 17043  				prg.print( /* "to the end of the statement" */ 629)
 17044  				prg.helpLine[3] = /* "A previous error seems to have propagated," */ 630
 17045  				prg.curSym = uint16(hashBase + hashSize + 6)
 17046  
 17047  			case absorbing:
 17048  				prg.print( /* "a text argument" */ 631)
 17049  				prg.helpLine[3] = /* "It seems that a right delimiter was left out," */ 632
 17050  				if prg.warningInfo == 0 {
 17051  					prg.curSym = uint16(hashBase + hashSize + 10)
 17052  				} else {
 17053  					prg.curSym = uint16(hashBase + hashSize + 2)
 17054  					*prg.eqtb[hashBase+hashSize+2-1].rh() = uint16(prg.warningInfo)
 17055  				}
 17056  
 17057  			case varDefining, opDefining:
 17058  				prg.print( /* "the definition of " */ 633)
 17059  				if int32(prg.scannerStatus) == opDefining {
 17060  					prg.slowPrint(int32(*prg.hash[prg.warningInfo-1].rh()))
 17061  				} else {
 17062  					prg.printVariableName(halfword(prg.warningInfo))
 17063  				}
 17064  				prg.curSym = uint16(hashBase + hashSize + 8)
 17065  
 17066  			case loopDefining:
 17067  				prg.print( /* "the text of a " */ 634)
 17068  				prg.slowPrint(int32(*prg.hash[prg.warningInfo-1].rh()))
 17069  				prg.print( /* " loop" */ 635)
 17070  				prg.helpLine[3] = /* "I suspect you have forgotten an `endfor'," */ 636
 17071  				prg.curSym = uint16(hashBase + hashSize + 7)
 17072  
 17073  			} // there are no other cases
 17074  			prg.insError()
 17075  		} else {
 17076  			{
 17077  				if int32(prg.interaction) == errorStopMode {
 17078  				}
 17079  				prg.printNl(strNumber( /* "! " */ 261))
 17080  				prg.print( /* "Incomplete if; all text was ignored after line " */ 617) /* \xref[!\relax]  */
 17081  			}
 17082  			// \xref[Incomplete if...]
 17083  			prg.printInt(prg.warningInfo)
 17084  
 17085  			{
 17086  				prg.helpPtr = 3
 17087  				prg.helpLine[2] = /* "A forbidden `outer' token occurred in skipped text." */ 618
 17088  				prg.helpLine[1] = /* "This kind of error happens when you say `if...' and forget" */ 619
 17089  				prg.helpLine[0] = /* "the matching `fi'. I've inserted a `fi'; this might work." */ 620
 17090  			}
 17091  			if int32(prg.curSym) == 0 {
 17092  				prg.helpLine[2] =
 17093  					/* "The file ended while I was skipping conditional text." */ 621
 17094  			}
 17095  			prg.curSym = uint16(hashBase + hashSize + 9)
 17096  			prg.insError()
 17097  		}
 17098  		prg.deletionsAllowed = true
 17099  		r = false
 17100  	}
 17101  	return r
 17102  } // \2
 17103  
 17104  func (prg *prg) getNext() {
 17105  	// go here at crucial stages when scanning a number
 17106  	var (
 17107  		k/* 0..bufSize */ uint16           // an index into |buffer|
 17108  		c                        asciiCode // the current character in the buffer
 17109  		class                    asciiCode // its class number
 17110  		n, f                     int32     // registers for decimal-to-binary conversion
 17111  	)
 17112  restart:
 17113  	prg.curSym = 0
 17114  	if int32(prg.curInput.indexField) <= maxInOpen {
 17115  	switch1:
 17116  		c = prg.buffer[prg.curInput.locField]
 17117  		prg.curInput.locField = uint16(int32(prg.curInput.locField) + 1)
 17118  		class = prg.charClass[c]
 17119  		switch class {
 17120  		case digitClass:
 17121  			goto startNumericToken
 17122  		case periodClass:
 17123  			class = prg.charClass[prg.buffer[prg.curInput.locField]]
 17124  			if int32(class) > periodClass {
 17125  				goto switch1
 17126  			} else if int32(class) < periodClass {
 17127  				n = 0
 17128  				goto startDecimalToken
 17129  			}
 17130  		// \xref[. ][\..\ token]
 17131  
 17132  		case spaceClass:
 17133  			goto switch1
 17134  		case percentClass:
 17135  			if int32(prg.curInput.nameField) > 2 {
 17136  				prg.line = prg.line + 1
 17137  				prg.first = prg.curInput.startField
 17138  				if !prg.forceEof {
 17139  					if prg.inputLn(prg.inputFile[prg.curInput.indexField-1], true) {
 17140  						prg.firmUpTheLine()
 17141  					} else {
 17142  						prg.forceEof = true
 17143  					}
 17144  				}
 17145  				if prg.forceEof {
 17146  					prg.printChar(asciiCode(')'))
 17147  					prg.openParens = byte(int32(prg.openParens) - 1)
 17148  					// show user that file has been read
 17149  					prg.forceEof = false
 17150  					prg.endFileReading() // resume previous level
 17151  					if prg.checkOuterValidity() {
 17152  						goto restart
 17153  					} else {
 17154  						goto restart
 17155  					}
 17156  				}
 17157  				prg.buffer[prg.curInput.limitField] = '%'
 17158  				prg.first = uint16(int32(prg.curInput.limitField) + 1)
 17159  				prg.curInput.locField = prg.curInput.startField // ready to read
 17160  			} else {
 17161  				if int32(prg.inputPtr) > 0 {
 17162  					prg.endFileReading()
 17163  					goto restart // resume previous level
 17164  				}
 17165  				if int32(prg.selector) < logOnly {
 17166  					prg.openLogFile()
 17167  				}
 17168  				if int32(prg.interaction) > nonstopMode {
 17169  					if int32(prg.curInput.limitField) == int32(prg.curInput.startField) {
 17170  						prg.printNl(strNumber( /* "(Please type a command or say `end')" */ 651))
 17171  					}
 17172  					// \xref[Please type...]
 17173  					prg.printLn()
 17174  					prg.first = prg.curInput.startField
 17175  					{
 17176  						prg.print('*')
 17177  						prg.termInput()
 17178  					} // input on-line into |buffer|
 17179  					// \xref[*\relax]
 17180  					prg.curInput.limitField = prg.last
 17181  					prg.buffer[prg.curInput.limitField] = '%'
 17182  					prg.first = uint16(int32(prg.curInput.limitField) + 1)
 17183  					prg.curInput.locField = prg.curInput.startField
 17184  				} else {
 17185  					prg.fatalError(strNumber( /* "*** (job aborted, no legal end found)" */ 652))
 17186  				}
 17187  				// \xref[job aborted]
 17188  				// nonstop mode, which is intended for overnight batch processing,
 17189  				//     never waits for on-line input
 17190  
 17191  			}
 17192  			{
 17193  				if prg.interrupt != 0 {
 17194  					prg.pauseForInstructions()
 17195  				}
 17196  			}
 17197  
 17198  			goto switch1
 17199  
 17200  		case stringClass:
 17201  			// Get a string token and |return|
 17202  			if int32(prg.buffer[prg.curInput.locField]) == '"' {
 17203  				prg.curMod = /* "" */ 285
 17204  			} else {
 17205  				k = prg.curInput.locField
 17206  				prg.buffer[int32(prg.curInput.limitField)+1] = '"'
 17207  				for {
 17208  					prg.curInput.locField = uint16(int32(prg.curInput.locField) + 1)
 17209  					if int32(prg.buffer[prg.curInput.locField]) == '"' {
 17210  						break
 17211  					}
 17212  				}
 17213  				if int32(prg.curInput.locField) > int32(prg.curInput.limitField) {
 17214  					prg.curInput.locField = prg.curInput.limitField // the next character to be read on this line will be |"%"|
 17215  					{
 17216  						if int32(prg.interaction) == errorStopMode {
 17217  						}
 17218  						prg.printNl(strNumber( /* "! " */ 261))
 17219  						prg.print( /* "Incomplete string token has been flushed" */ 644) /* \xref[!\relax]  */
 17220  					}
 17221  					// \xref[Incomplete string token...]
 17222  					{
 17223  						prg.helpPtr = 3
 17224  						prg.helpLine[2] = /* "Strings should finish on the same line as they began." */ 645
 17225  						prg.helpLine[1] = /* "I've deleted the partial string; you might want to" */ 646
 17226  						prg.helpLine[0] = /* "insert another by typing, e.g., `I\"new string\"'." */ 647
 17227  					}
 17228  
 17229  					prg.deletionsAllowed = false
 17230  					prg.error1()
 17231  					prg.deletionsAllowed = true
 17232  					goto restart
 17233  				}
 17234  				if int32(prg.curInput.locField) == int32(k)+1 && int32(prg.strStart[int32(prg.buffer[k])+1])-int32(prg.strStart[prg.buffer[k]]) == 1 {
 17235  					prg.curMod = int32(prg.buffer[k])
 17236  				} else {
 17237  					{
 17238  						if int32(prg.poolPtr)+int32(prg.curInput.locField)-int32(k) > int32(prg.maxPoolPtr) {
 17239  							if int32(prg.poolPtr)+int32(prg.curInput.locField)-int32(k) > poolSize {
 17240  								prg.overflow(strNumber( /* "pool size" */ 257), poolSize-int32(prg.initPoolPtr))
 17241  							} /* \xref[METAFONT capacity exceeded pool size][\quad pool size]  */
 17242  							prg.maxPoolPtr = uint16(int32(prg.poolPtr) + int32(prg.curInput.locField) - int32(k))
 17243  						}
 17244  					}
 17245  					for {
 17246  						{
 17247  							prg.strPool[prg.poolPtr] = prg.buffer[k]
 17248  							prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
 17249  						}
 17250  						k = uint16(int32(k) + 1)
 17251  						if int32(k) == int32(prg.curInput.locField) {
 17252  							break
 17253  						}
 17254  					}
 17255  					prg.curMod = int32(prg.makeString())
 17256  				}
 17257  			}
 17258  			prg.curInput.locField = uint16(int32(prg.curInput.locField) + 1)
 17259  			prg.curCmd = byte(stringToken)
 17260  			goto exit
 17261  
 17262  		case 5, 6, 7, 8:
 17263  			k = uint16(int32(prg.curInput.locField) - 1)
 17264  			goto found
 17265  
 17266  		case invalidClass:
 17267  			// Decry the invalid character and |goto restart|
 17268  			{
 17269  				if int32(prg.interaction) == errorStopMode {
 17270  				}
 17271  				prg.printNl(strNumber( /* "! " */ 261))
 17272  				prg.print( /* "Text line contains an invalid character" */ 641) /* \xref[!\relax]  */
 17273  			}
 17274  			// \xref[Text line contains...]
 17275  			{
 17276  				prg.helpPtr = 2
 17277  				prg.helpLine[1] = /* "A funny symbol that I can't read has just been input." */ 642
 17278  				prg.helpLine[0] = /* "Continue, and I'll forget that it ever happened." */ 643
 17279  			}
 17280  
 17281  			prg.deletionsAllowed = false
 17282  			prg.error1()
 17283  			prg.deletionsAllowed = true
 17284  
 17285  			goto restart
 17286  
 17287  		default: // letters, etc.
 17288  		}
 17289  
 17290  		k = uint16(int32(prg.curInput.locField) - 1)
 17291  		for int32(prg.charClass[prg.buffer[prg.curInput.locField]]) == int32(class) {
 17292  			prg.curInput.locField = uint16(int32(prg.curInput.locField) + 1)
 17293  		}
 17294  
 17295  		goto found
 17296  
 17297  	startNumericToken:
 17298  		n = int32(c) - '0'
 17299  		for int32(prg.charClass[prg.buffer[prg.curInput.locField]]) == digitClass {
 17300  			if n < 4096 {
 17301  				n = 10*n + int32(prg.buffer[prg.curInput.locField]) - '0'
 17302  			}
 17303  			prg.curInput.locField = uint16(int32(prg.curInput.locField) + 1)
 17304  		}
 17305  		if int32(prg.buffer[prg.curInput.locField]) == '.' {
 17306  			if int32(prg.charClass[prg.buffer[int32(prg.curInput.locField)+1]]) == digitClass {
 17307  				goto done
 17308  			}
 17309  		}
 17310  		f = 0
 17311  		goto finNumericToken
 17312  
 17313  	done:
 17314  		prg.curInput.locField = uint16(int32(prg.curInput.locField) + 1)
 17315  
 17316  	startDecimalToken:
 17317  		k = 0
 17318  		for {
 17319  			if int32(k) < 17 {
 17320  				prg.dig[k] = byte(int32(prg.buffer[prg.curInput.locField]) - '0')
 17321  				k = uint16(int32(k) + 1)
 17322  			}
 17323  			prg.curInput.locField = uint16(int32(prg.curInput.locField) + 1)
 17324  			if int32(prg.charClass[prg.buffer[prg.curInput.locField]]) != digitClass {
 17325  				break
 17326  			}
 17327  		}
 17328  		f = prg.roundDecimals(smallNumber(k))
 17329  		if f == 0200000 {
 17330  			n = n + 1
 17331  			f = 0
 17332  		}
 17333  
 17334  	finNumericToken:
 17335  		if n < 4096 {
 17336  			prg.curMod = n*0200000 + f
 17337  		} else {
 17338  			{
 17339  				if int32(prg.interaction) == errorStopMode {
 17340  				}
 17341  				prg.printNl(strNumber( /* "! " */ 261))
 17342  				prg.print( /* "Enormous number has been reduced" */ 648) /* \xref[!\relax]  */
 17343  			}
 17344  			// \xref[Enormous number...]
 17345  			{
 17346  				prg.helpPtr = 2
 17347  				prg.helpLine[1] = /* "I can't handle numbers bigger than about 4095.99998;" */ 649
 17348  				prg.helpLine[0] = /* "so I've changed your constant to that maximum amount." */ 650
 17349  			}
 17350  
 17351  			prg.deletionsAllowed = false
 17352  			prg.error1()
 17353  			prg.deletionsAllowed = true
 17354  			prg.curMod = 01777777777
 17355  		}
 17356  		prg.curCmd = byte(numericToken)
 17357  		goto exit
 17358  
 17359  	found:
 17360  		prg.curSym = prg.idLookup(int32(k), int32(prg.curInput.locField)-int32(k))
 17361  	} else if int32(prg.curInput.locField) >= int32(prg.hiMemMin) {
 17362  		prg.curSym = *(*prg.mem[prg.curInput.locField].hh()).lh()
 17363  		prg.curInput.locField = *(*prg.mem[prg.curInput.locField].hh()).rh() // move to next
 17364  		if int32(prg.curSym) >= hashBase+hashSize+12+1 {
 17365  			if int32(prg.curSym) >= hashBase+hashSize+12+1+paramSize {
 17366  				if int32(prg.curSym) >= hashBase+hashSize+12+1+paramSize+paramSize {
 17367  					prg.curSym = uint16(int32(prg.curSym) - paramSize)
 17368  				}
 17369  				// |param_size=text_base-suffix_base|
 17370  				prg.beginTokenList(prg.paramStack[int32(prg.curInput.limitField)+int32(prg.curSym)-(hashBase+hashSize+12+1+paramSize)], quarterword(parameter))
 17371  
 17372  				goto restart
 17373  			} else {
 17374  				prg.curCmd = byte(capsuleToken)
 17375  				prg.curMod = int32(prg.paramStack[int32(prg.curInput.limitField)+int32(prg.curSym)-(hashBase+hashSize+12+1)])
 17376  				prg.curSym = 0
 17377  				goto exit
 17378  			}
 17379  		}
 17380  	} else if int32(prg.curInput.locField) > memMin {
 17381  		if int32(*(*prg.mem[prg.curInput.locField].hh()).b1()) == token {
 17382  			prg.curMod = *prg.mem[int32(prg.curInput.locField)+1].int()
 17383  			if int32(*(*prg.mem[prg.curInput.locField].hh()).b0()) == known {
 17384  				prg.curCmd = byte(numericToken)
 17385  			} else {
 17386  				prg.curCmd = byte(stringToken)
 17387  				{
 17388  					if int32(prg.strRef[prg.curMod]) < maxStrRef {
 17389  						prg.strRef[prg.curMod] = byte(int32(prg.strRef[prg.curMod]) + 1)
 17390  					}
 17391  				}
 17392  			}
 17393  		} else {
 17394  			prg.curMod = int32(prg.curInput.locField)
 17395  			prg.curCmd = byte(capsuleToken)
 17396  		}
 17397  		prg.curInput.locField = *(*prg.mem[prg.curInput.locField].hh()).rh()
 17398  		goto exit
 17399  	} else {
 17400  		prg.endTokenList()
 17401  		goto restart // resume previous level
 17402  	}
 17403  
 17404  	// Finish getting the symbolic token in |cur_sym|; |goto restart| if it is illegal
 17405  	prg.curCmd = byte(*prg.eqtb[prg.curSym-1].lh())
 17406  	prg.curMod = int32(*prg.eqtb[prg.curSym-1].rh())
 17407  	if int32(prg.curCmd) >= outerTag {
 17408  		if prg.checkOuterValidity() {
 17409  			prg.curCmd = byte(int32(prg.curCmd) - outerTag)
 17410  		} else {
 17411  			goto restart
 17412  		}
 17413  	}
 17414  
 17415  exit:
 17416  }
 17417  
 17418  // 666.
 17419  
 17420  // tangle:pos ../../mf.web:13950:3:
 17421  
 17422  // We need to mention a procedure that may be called by |get_next|.
 17423  func (prg *prg) firmUpTheLine() {
 17424  	var (
 17425  		k /* 0..bufSize */ uint16 // an index into |buffer|
 17426  	)
 17427  	prg.curInput.limitField = prg.last
 17428  	if prg.internal[pausing-1] > 0 {
 17429  		if int32(prg.interaction) > nonstopMode {
 17430  			prg.printLn()
 17431  			if int32(prg.curInput.startField) < int32(prg.curInput.limitField) {
 17432  				for ii := int32(prg.curInput.startField); ii <= int32(prg.curInput.limitField)-1; ii++ {
 17433  					k = uint16(ii)
 17434  					_ = k
 17435  					prg.print(int32(prg.buffer[k]))
 17436  				}
 17437  			}
 17438  			prg.first = prg.curInput.limitField
 17439  			{
 17440  				prg.print( /* "=>" */ 653)
 17441  				prg.termInput()
 17442  			} // wait for user response
 17443  			// \xref[=>]
 17444  			if int32(prg.last) > int32(prg.first) {
 17445  				for ii := int32(prg.first); ii <= int32(prg.last)-1; ii++ {
 17446  					k = uint16(ii)
 17447  					_ = k // move line down in buffer
 17448  					prg.buffer[int32(k)+int32(prg.curInput.startField)-int32(prg.first)] = prg.buffer[k]
 17449  				}
 17450  				prg.curInput.limitField = uint16(int32(prg.curInput.startField) + int32(prg.last) - int32(prg.first))
 17451  			}
 17452  		}
 17453  	}
 17454  }
 17455  
 17456  // 685.
 17457  
 17458  // tangle:pos ../../mf.web:14273:3:
 17459  
 17460  // Different macro-absorbing operations have different syntaxes, but they
 17461  // also have a lot in common. There is a list of special symbols that are to
 17462  // be replaced by parameter tokens; there is a special command code that
 17463  // ends the definition; the quotation conventions are identical.  Therefore
 17464  // it makes sense to have most of the work done by a single subroutine. That
 17465  // subroutine is called |scan_toks|.
 17466  //
 17467  // The first parameter to |scan_toks| is the command code that will
 17468  // terminate scanning (either |macro_def| or |iteration|).
 17469  //
 17470  // The second parameter, |subst_list|, points to a (possibly empty) list
 17471  // of two-word nodes whose |info| and |value| fields specify symbol tokens
 17472  // before and after replacement. The list will be returned to free storage
 17473  // by |scan_toks|.
 17474  //
 17475  // The third parameter is simply appended to the token list that is built.
 17476  // And the final parameter tells how many of the special operations
 17477  // \.[\#\AT!], \.[\AT!], and \.[\AT!\#] are to be replaced by suffix parameters.
 17478  // When such parameters are present, they are called \.[(SUFFIX0)],
 17479  // \.[(SUFFIX1)], and \.[(SUFFIX2)].
 17480  func (prg *prg) scanToks(terminator commandCode,
 17481  	substList, tailEnd halfword, suffixCount smallNumber) (r halfword) {
 17482  	var (
 17483  		p       halfword // tail of the token list being built
 17484  		q       halfword // temporary for link management
 17485  		balance int32    // left delimiters minus right delimiters
 17486  	)
 17487  	p = uint16(3000 - 2)
 17488  	balance = 1
 17489  	*(*prg.mem[3000-2].hh()).rh() = uint16(memMin)
 17490  	for true {
 17491  		prg.getNext()
 17492  		if int32(prg.curSym) > 0 {
 17493  			{
 17494  				q = substList
 17495  				for int32(q) != memMin {
 17496  					if int32(*(*prg.mem[q].hh()).lh()) == int32(prg.curSym) {
 17497  						prg.curSym = uint16(*prg.mem[int32(q)+1].int())
 17498  						prg.curCmd = byte(relax)
 17499  						goto found
 17500  					}
 17501  					q = *(*prg.mem[q].hh()).rh()
 17502  				}
 17503  
 17504  			found:
 17505  			}
 17506  			if int32(prg.curCmd) == int32(terminator) {
 17507  				if prg.curMod > 0 {
 17508  					balance = balance + 1
 17509  				} else {
 17510  					balance = balance - 1
 17511  					if balance == 0 {
 17512  						goto done
 17513  					}
 17514  				}
 17515  			} else if int32(prg.curCmd) == macroSpecial {
 17516  				if prg.curMod == quote {
 17517  					prg.getNext()
 17518  				} else if prg.curMod <= int32(suffixCount) {
 17519  					prg.curSym = uint16(hashBase + hashSize + 12 + 1 + paramSize - 1 + prg.curMod)
 17520  				}
 17521  			}
 17522  		}
 17523  		*(*prg.mem[p].hh()).rh() = prg.curTok()
 17524  		p = *(*prg.mem[p].hh()).rh()
 17525  	}
 17526  
 17527  done:
 17528  	*(*prg.mem[p].hh()).rh() = tailEnd
 17529  	prg.flushNodeList(substList)
 17530  	r = *(*prg.mem[3000-2].hh()).rh()
 17531  	return r
 17532  }
 17533  
 17534  // 691.
 17535  
 17536  // tangle:pos ../../mf.web:14363:3:
 17537  
 17538  // Here is a routine that's used whenever a token will be redefined. If
 17539  // the user's token is unredefinable, the `|frozen_inaccessible|' token is
 17540  // substituted; the latter is redefinable but essentially impossible to use,
 17541  // hence \MF's tables won't get fouled up.
 17542  func (prg *prg) getSymbol() {
 17543  restart:
 17544  	prg.getNext()
 17545  	if int32(prg.curSym) == 0 || int32(prg.curSym) > hashBase+hashSize {
 17546  		{
 17547  			if int32(prg.interaction) == errorStopMode {
 17548  			}
 17549  			prg.printNl(strNumber( /* "! " */ 261))
 17550  			prg.print( /* "Missing symbolic token inserted" */ 665) /* \xref[!\relax]  */
 17551  		}
 17552  		// \xref[Missing symbolic token...]
 17553  		{
 17554  			prg.helpPtr = 3
 17555  			prg.helpLine[2] = /* "Sorry: You can't redefine a number, string, or expr." */ 666
 17556  			prg.helpLine[1] = /* "I've inserted an inaccessible symbol so that your" */ 667
 17557  			prg.helpLine[0] = /* "definition will be completed without mixing me up too badly." */ 668
 17558  		}
 17559  		if int32(prg.curSym) > 0 {
 17560  			prg.helpLine[2] = /* "Sorry: You can't redefine my error-recovery tokens." */ 669
 17561  		} else if int32(prg.curCmd) == stringToken {
 17562  			if int32(prg.strRef[prg.curMod]) < maxStrRef {
 17563  				if int32(prg.strRef[prg.curMod]) > 1 {
 17564  					prg.strRef[prg.curMod] = byte(int32(prg.strRef[prg.curMod]) - 1)
 17565  				} else {
 17566  					prg.flushString(strNumber(prg.curMod))
 17567  				}
 17568  			}
 17569  		}
 17570  		prg.curSym = uint16(hashBase + hashSize)
 17571  		prg.insError()
 17572  		goto restart
 17573  	}
 17574  }
 17575  
 17576  // 692.
 17577  
 17578  // tangle:pos ../../mf.web:14384:3:
 17579  
 17580  // Before we actually redefine a symbolic token, we need to clear away its
 17581  // former value, if it was a variable. The following stronger version of
 17582  // |get_symbol| does that.
 17583  func (prg *prg) getClearSymbol() {
 17584  	prg.getSymbol()
 17585  	prg.clearSymbol(prg.curSym, false)
 17586  }
 17587  
 17588  // 693.
 17589  
 17590  // tangle:pos ../../mf.web:14392:3:
 17591  
 17592  // Here's another little subroutine; it checks that an equals sign
 17593  // or assignment sign comes along at the proper place in a macro definition.
 17594  func (prg *prg) checkEquals() {
 17595  	if int32(prg.curCmd) != equals {
 17596  		if int32(prg.curCmd) != assignment {
 17597  			prg.missingErr(strNumber('='))
 17598  
 17599  			// \xref[Missing `=']
 17600  			{
 17601  				prg.helpPtr = 5
 17602  				prg.helpLine[4] = /* "The next thing in this `def' should have been `='," */ 670
 17603  				prg.helpLine[3] = /* "because I've already looked at the definition heading." */ 671
 17604  				prg.helpLine[2] = /* "But don't worry; I'll pretend that an equals sign" */ 672
 17605  				prg.helpLine[1] = /* "was present. Everything from here to `enddef'" */ 673
 17606  				prg.helpLine[0] = /* "will be the replacement text of this macro." */ 674
 17607  			}
 17608  			prg.backError()
 17609  		}
 17610  	}
 17611  }
 17612  
 17613  // 694.
 17614  
 17615  // tangle:pos ../../mf.web:14408:3:
 17616  
 17617  // A \&[primarydef], \&[secondarydef], or \&[tertiarydef] is rather easily
 17618  // handled now that we have |scan_toks|.  In this case there are
 17619  // two parameters, which will be \.[EXPR0] and \.[EXPR1] (i.e.,
 17620  // |expr_base| and |expr_base+1|).
 17621  func (prg *prg) makeOpDef() {
 17622  	var (
 17623  		m        commandCode // the type of definition
 17624  		p, q, r1 halfword    // for list manipulation
 17625  	)
 17626  	m = byte(prg.curMod)
 17627  
 17628  	prg.getSymbol()
 17629  	q = prg.getNode(tokenNodeSize)
 17630  	*(*prg.mem[q].hh()).lh() = prg.curSym
 17631  	*prg.mem[int32(q)+1].int() = hashBase + hashSize + 12 + 1
 17632  
 17633  	prg.getClearSymbol()
 17634  	prg.warningInfo = int32(prg.curSym)
 17635  
 17636  	prg.getSymbol()
 17637  	p = prg.getNode(tokenNodeSize)
 17638  	*(*prg.mem[p].hh()).lh() = prg.curSym
 17639  	*prg.mem[int32(p)+1].int() = hashBase + hashSize + 12 + 1 + 1
 17640  	*(*prg.mem[p].hh()).rh() = q
 17641  
 17642  	prg.getNext()
 17643  	prg.checkEquals()
 17644  
 17645  	prg.scannerStatus = byte(opDefining)
 17646  	q = prg.getAvail()
 17647  	*(*prg.mem[q].hh()).lh() = uint16(memMin)
 17648  	r1 = prg.getAvail()
 17649  	*(*prg.mem[q].hh()).rh() = r1
 17650  	*(*prg.mem[r1].hh()).lh() = uint16(generalMacro)
 17651  	*(*prg.mem[r1].hh()).rh() = prg.scanToks(commandCode(macroDef), p, halfword(memMin), smallNumber(0))
 17652  	prg.scannerStatus = byte(normal)
 17653  	*prg.eqtb[prg.warningInfo-1].lh() = uint16(m)
 17654  	*prg.eqtb[prg.warningInfo-1].rh() = q
 17655  	prg.getXNext()
 17656  }
 17657  
 17658  // 697.
 17659  
 17660  // tangle:pos ../../mf.web:14456:3:
 17661  
 17662  // Let's turn next to the more complex processing associated with \&[def]
 17663  // and \&[vardef]. When the following procedure is called, |cur_mod|
 17664  // should be either |start_def| or |var_def|.
 17665  // \4
 17666  // Declare the procedure called |check_delimiter|
 17667  func (prg *prg) checkDelimiter(lDelim, rDelim halfword) {
 17668  	if int32(prg.curCmd) == rightDelimiter {
 17669  		if prg.curMod == int32(lDelim) {
 17670  			goto exit
 17671  		}
 17672  	}
 17673  	if int32(prg.curSym) != int32(rDelim) {
 17674  		prg.missingErr(*prg.hash[rDelim-1].rh())
 17675  
 17676  		// \xref[Missing `)']
 17677  		{
 17678  			prg.helpPtr = 2
 17679  			prg.helpLine[1] = /* "I found no right delimiter to match a left one. So I've" */ 922
 17680  			prg.helpLine[0] = /* "put one in, behind the scenes; this may fix the problem." */ 923
 17681  		}
 17682  		prg.backError()
 17683  	} else {
 17684  		{
 17685  			if int32(prg.interaction) == errorStopMode {
 17686  			}
 17687  			prg.printNl(strNumber( /* "! " */ 261))
 17688  			prg.print( /* "The token `" */ 924) /* \xref[!\relax]  */
 17689  		}
 17690  		prg.slowPrint(int32(*prg.hash[rDelim-1].rh()))
 17691  		// \xref[The token...delimiter]
 17692  		prg.print( /* "' is no longer a right delimiter" */ 925)
 17693  		{
 17694  			prg.helpPtr = 3
 17695  			prg.helpLine[2] = /* "Strange: This token has lost its former meaning!" */ 926
 17696  			prg.helpLine[1] = /* "I'll read it as a right delimiter this time;" */ 927
 17697  			prg.helpLine[0] = /* "but watch out, I'll probably miss it later." */ 928
 17698  		}
 17699  		prg.error1()
 17700  	}
 17701  
 17702  exit:
 17703  }
 17704  
 17705  // \4
 17706  // Declare the function called |scan_declared_variable|
 17707  func (prg *prg) scanDeclaredVariable() (r halfword) {
 17708  	var (
 17709  		x    halfword // hash address of the variable's root
 17710  		h, t halfword // head and tail of the token list to be returned
 17711  		l    halfword // hash address of left bracket
 17712  	)
 17713  	prg.getSymbol()
 17714  	x = prg.curSym
 17715  	if int32(prg.curCmd) != tagToken {
 17716  		prg.clearSymbol(x, false)
 17717  	}
 17718  	h = prg.getAvail()
 17719  	*(*prg.mem[h].hh()).lh() = x
 17720  	t = h
 17721  
 17722  	for true {
 17723  		prg.getXNext()
 17724  		if int32(prg.curSym) == 0 {
 17725  			goto done
 17726  		}
 17727  		if int32(prg.curCmd) != tagToken {
 17728  			if int32(prg.curCmd) != internalQuantity {
 17729  				if int32(prg.curCmd) == leftBracket {
 17730  					l = prg.curSym
 17731  					prg.getXNext()
 17732  					if int32(prg.curCmd) != rightBracket {
 17733  						prg.backInput()
 17734  						prg.curSym = l
 17735  						prg.curCmd = byte(leftBracket)
 17736  						goto done
 17737  					} else {
 17738  						prg.curSym = uint16(collectiveSubscript)
 17739  					}
 17740  				} else {
 17741  					goto done
 17742  				}
 17743  			}
 17744  		}
 17745  		*(*prg.mem[t].hh()).rh() = prg.getAvail()
 17746  		t = *(*prg.mem[t].hh()).rh()
 17747  		*(*prg.mem[t].hh()).lh() = prg.curSym
 17748  	}
 17749  
 17750  done:
 17751  	if int32(*prg.eqtb[x-1].lh())%outerTag != tagToken {
 17752  		prg.clearSymbol(x, false)
 17753  	}
 17754  	if int32(*prg.eqtb[x-1].rh()) == memMin {
 17755  		prg.newRoot(x)
 17756  	}
 17757  	r = h
 17758  	return r
 17759  }
 17760  
 17761  func (prg *prg) scanDef() {
 17762  	var (
 17763  		m/* startDef..varDef */ byte                 // the type of definition
 17764  		n/* 0..3 */ byte                             // the number of special suffix parameters
 17765  		k/* 0..paramSize */ byte                     // the total number of parameters
 17766  		c/* generalMacro..textMacro */ byte          // the kind of macro we're defining
 17767  		r1                                  halfword // parameter-substitution list
 17768  		q                                   halfword // tail of the macro token list
 17769  		p                                   halfword // temporary storage
 17770  		base                                halfword // |expr_base|, |suffix_base|, or |text_base|
 17771  		lDelim, rDelim                      halfword // matching delimiters
 17772  	)
 17773  	m = byte(prg.curMod)
 17774  	c = byte(generalMacro)
 17775  	*(*prg.mem[3000-2].hh()).rh() = uint16(memMin)
 17776  
 17777  	q = prg.getAvail()
 17778  	*(*prg.mem[q].hh()).lh() = uint16(memMin)
 17779  	r1 = uint16(memMin)
 17780  
 17781  	// Scan the token or variable to be defined; set |n|, |scanner_status|, and |warning_info|
 17782  	if int32(m) == startDef {
 17783  		prg.getClearSymbol()
 17784  		prg.warningInfo = int32(prg.curSym)
 17785  		prg.getNext()
 17786  		prg.scannerStatus = byte(opDefining)
 17787  		n = 0
 17788  		*prg.eqtb[prg.warningInfo-1].lh() = uint16(definedMacro)
 17789  		*prg.eqtb[prg.warningInfo-1].rh() = q
 17790  	} else {
 17791  		p = prg.scanDeclaredVariable()
 17792  		prg.flushVariable(*prg.eqtb[*(*prg.mem[p].hh()).lh()-1].rh(), *(*prg.mem[p].hh()).rh(), true)
 17793  		prg.warningInfo = int32(prg.findVariable(p))
 17794  		prg.flushList(p)
 17795  		if prg.warningInfo == memMin {
 17796  			{
 17797  				if int32(prg.interaction) == errorStopMode {
 17798  				}
 17799  				prg.printNl(strNumber( /* "! " */ 261))
 17800  				prg.print( /* "This variable already starts with a macro" */ 681) /* \xref[!\relax]  */
 17801  			}
 17802  			// \xref[This variable already...]
 17803  			{
 17804  				prg.helpPtr = 2
 17805  				prg.helpLine[1] = /* "After `vardef a' you can't say `vardef a.b'." */ 682
 17806  				prg.helpLine[0] = /* "So I'll have to discard this definition." */ 683
 17807  			}
 17808  			prg.error1()
 17809  			prg.warningInfo = memMin + 3 + 10 + 2 + 2 + 2 + 2
 17810  		}
 17811  		prg.scannerStatus = byte(varDefining)
 17812  		n = 2
 17813  		if int32(prg.curCmd) == macroSpecial {
 17814  			if prg.curMod == macroSuffix {
 17815  				n = 3
 17816  				prg.getNext()
 17817  			}
 17818  		}
 17819  		*(*prg.mem[prg.warningInfo].hh()).b0() = byte(unsuffixedMacro - 2 + int32(n))
 17820  		*prg.mem[prg.warningInfo+1].int() = int32(q)
 17821  	}
 17822  	k = n
 17823  	if int32(prg.curCmd) == leftDelimiter {
 17824  		for {
 17825  			lDelim = prg.curSym
 17826  			rDelim = uint16(prg.curMod)
 17827  			prg.getNext()
 17828  			if int32(prg.curCmd) == paramType && prg.curMod >= hashBase+hashSize+12+1 {
 17829  				base = uint16(prg.curMod)
 17830  			} else {
 17831  				{
 17832  					if int32(prg.interaction) == errorStopMode {
 17833  					}
 17834  					prg.printNl(strNumber( /* "! " */ 261))
 17835  					prg.print( /* "Missing parameter type; `expr' will be assumed" */ 684) /* \xref[!\relax]  */
 17836  				}
 17837  				// \xref[Missing parameter type]
 17838  				{
 17839  					prg.helpPtr = 1
 17840  					prg.helpLine[0] = /* "You should've had `expr' or `suffix' or `text' here." */ 685
 17841  				}
 17842  				prg.backError()
 17843  				base = uint16(hashBase + hashSize + 12 + 1)
 17844  			}
 17845  
 17846  			// Absorb parameter tokens for type |base|
 17847  			for {
 17848  				*(*prg.mem[q].hh()).rh() = prg.getAvail()
 17849  				q = *(*prg.mem[q].hh()).rh()
 17850  				*(*prg.mem[q].hh()).lh() = uint16(int32(base) + int32(k))
 17851  
 17852  				prg.getSymbol()
 17853  				p = prg.getNode(tokenNodeSize)
 17854  				*prg.mem[int32(p)+1].int() = int32(base) + int32(k)
 17855  				*(*prg.mem[p].hh()).lh() = prg.curSym
 17856  				if int32(k) == paramSize {
 17857  					prg.overflow(strNumber( /* "parameter stack size" */ 686), paramSize)
 17858  				}
 17859  				// \xref[METAFONT capacity exceeded parameter stack size][\quad parameter stack size]
 17860  				k = byte(int32(k) + 1)
 17861  				*(*prg.mem[p].hh()).rh() = r1
 17862  				r1 = p
 17863  				prg.getNext()
 17864  				if int32(prg.curCmd) != comma {
 17865  					break
 17866  				}
 17867  			}
 17868  			prg.checkDelimiter(lDelim, rDelim)
 17869  			prg.getNext()
 17870  			if int32(prg.curCmd) != leftDelimiter {
 17871  				break
 17872  			}
 17873  		}
 17874  	}
 17875  	if int32(prg.curCmd) == paramType {
 17876  		p = prg.getNode(tokenNodeSize)
 17877  		if prg.curMod < hashBase+hashSize+12+1 {
 17878  			c = byte(prg.curMod)
 17879  			*prg.mem[int32(p)+1].int() = hashBase + hashSize + 12 + 1 + int32(k)
 17880  		} else {
 17881  			*prg.mem[int32(p)+1].int() = prg.curMod + int32(k)
 17882  			if prg.curMod == hashBase+hashSize+12+1 {
 17883  				c = byte(exprMacro)
 17884  			} else if prg.curMod == hashBase+hashSize+12+1+paramSize {
 17885  				c = byte(suffixMacro)
 17886  			} else {
 17887  				c = byte(textMacro)
 17888  			}
 17889  		}
 17890  		if int32(k) == paramSize {
 17891  			prg.overflow(strNumber( /* "parameter stack size" */ 686), paramSize)
 17892  		}
 17893  		k = byte(int32(k) + 1)
 17894  		prg.getSymbol()
 17895  		*(*prg.mem[p].hh()).lh() = prg.curSym
 17896  		*(*prg.mem[p].hh()).rh() = r1
 17897  		r1 = p
 17898  		prg.getNext()
 17899  		if int32(c) == exprMacro {
 17900  			if int32(prg.curCmd) == ofToken {
 17901  				c = byte(ofMacro)
 17902  				p = prg.getNode(tokenNodeSize)
 17903  				if int32(k) == paramSize {
 17904  					prg.overflow(strNumber( /* "parameter stack size" */ 686), paramSize)
 17905  				}
 17906  				*prg.mem[int32(p)+1].int() = hashBase + hashSize + 12 + 1 + int32(k)
 17907  				prg.getSymbol()
 17908  				*(*prg.mem[p].hh()).lh() = prg.curSym
 17909  				*(*prg.mem[p].hh()).rh() = r1
 17910  				r1 = p
 17911  				prg.getNext()
 17912  			}
 17913  		}
 17914  	}
 17915  	prg.checkEquals()
 17916  	p = prg.getAvail()
 17917  	*(*prg.mem[p].hh()).lh() = uint16(c)
 17918  	*(*prg.mem[q].hh()).rh() = p
 17919  
 17920  	// Attach the replacement text to the tail of node |p|
 17921  	if int32(m) == startDef {
 17922  		*(*prg.mem[p].hh()).rh() = prg.scanToks(commandCode(macroDef), r1, halfword(memMin), n)
 17923  	} else {
 17924  		q = prg.getAvail()
 17925  		*(*prg.mem[q].hh()).lh() = prg.bgLoc
 17926  		*(*prg.mem[p].hh()).rh() = q
 17927  		p = prg.getAvail()
 17928  		*(*prg.mem[p].hh()).lh() = prg.egLoc
 17929  		*(*prg.mem[q].hh()).rh() = prg.scanToks(commandCode(macroDef), r1, p, n)
 17930  	}
 17931  	if prg.warningInfo == memMin+3+10+2+2+2+2 {
 17932  		prg.flushTokenList(halfword(*prg.mem[memMin+3+10+2+2+2+2+1].int()))
 17933  	}
 17934  	prg.scannerStatus = byte(normal)
 17935  	prg.getXNext()
 17936  } // \2
 17937  
 17938  // \4
 17939  // Declare the procedure called |macro_call|
 17940  // \4
 17941  // Declare the procedure called |print_macro_name|
 17942  func (prg *prg) printMacroName(a, n halfword) {
 17943  	var (
 17944  		p, q halfword // they traverse the first part of |a|
 17945  	)
 17946  	if int32(n) != memMin {
 17947  		prg.slowPrint(int32(*prg.hash[n-1].rh()))
 17948  	} else {
 17949  		p = *(*prg.mem[a].hh()).lh()
 17950  		if int32(p) == memMin {
 17951  			prg.slowPrint(int32(*prg.hash[*(*prg.mem[*(*prg.mem[*(*prg.mem[a].hh()).rh()].hh()).lh()].hh()).lh()-1].rh()))
 17952  		} else {
 17953  			q = p
 17954  			for int32(*(*prg.mem[q].hh()).rh()) != memMin {
 17955  				q = *(*prg.mem[q].hh()).rh()
 17956  			}
 17957  			*(*prg.mem[q].hh()).rh() = *(*prg.mem[*(*prg.mem[a].hh()).rh()].hh()).lh()
 17958  			prg.showTokenList(int32(p), memMin, 1000, 0)
 17959  			*(*prg.mem[q].hh()).rh() = uint16(memMin)
 17960  		}
 17961  	}
 17962  }
 17963  
 17964  // \4
 17965  // Declare the procedure called |print_arg|
 17966  func (prg *prg) printArg(q halfword, n int32, b halfword) {
 17967  	if int32(*(*prg.mem[q].hh()).rh()) == memMin+1 {
 17968  		prg.printNl(strNumber( /* "(EXPR" */ 498))
 17969  	} else if int32(b) < hashBase+hashSize+12+1+paramSize+paramSize && int32(b) != textMacro {
 17970  		prg.printNl(strNumber( /* "(SUFFIX" */ 499))
 17971  	} else {
 17972  		prg.printNl(strNumber( /* "(TEXT" */ 500))
 17973  	}
 17974  	prg.printInt(n)
 17975  	prg.print( /* ")<-" */ 702)
 17976  	if int32(*(*prg.mem[q].hh()).rh()) == memMin+1 {
 17977  		prg.printExp(q, smallNumber(1))
 17978  	} else {
 17979  		prg.showTokenList(int32(q), memMin, 1000, 0)
 17980  	}
 17981  }
 17982  
 17983  // \4
 17984  // Declare the procedure called |scan_text_arg|
 17985  func (prg *prg) scanTextArg(lDelim, rDelim halfword) {
 17986  	var (
 17987  		balance int32    // excess of |l_delim| over |r_delim|
 17988  		p       halfword // list tail
 17989  	)
 17990  	prg.warningInfo = int32(lDelim)
 17991  	prg.scannerStatus = byte(absorbing)
 17992  	p = uint16(3000 - 2)
 17993  	balance = 1
 17994  	*(*prg.mem[3000-2].hh()).rh() = uint16(memMin)
 17995  	for true {
 17996  		prg.getNext()
 17997  		if int32(lDelim) == 0 {
 17998  			if int32(prg.curCmd) > comma {
 17999  				if balance == 1 {
 18000  					goto done
 18001  				} else if int32(prg.curCmd) == endGroup {
 18002  					balance = balance - 1
 18003  				}
 18004  			} else if int32(prg.curCmd) == beginGroup {
 18005  				balance = balance + 1
 18006  			}
 18007  		} else {
 18008  			// Adjust the balance for a delimited argument; |goto done| if done
 18009  			if int32(prg.curCmd) == rightDelimiter {
 18010  				if prg.curMod == int32(lDelim) {
 18011  					balance = balance - 1
 18012  					if balance == 0 {
 18013  						goto done
 18014  					}
 18015  				}
 18016  			} else if int32(prg.curCmd) == leftDelimiter {
 18017  				if prg.curMod == int32(rDelim) {
 18018  					balance = balance + 1
 18019  				}
 18020  			}
 18021  		}
 18022  		*(*prg.mem[p].hh()).rh() = prg.curTok()
 18023  		p = *(*prg.mem[p].hh()).rh()
 18024  	}
 18025  
 18026  done:
 18027  	prg.curExp = int32(*(*prg.mem[3000-2].hh()).rh())
 18028  	prg.curType = byte(tokenList)
 18029  	prg.scannerStatus = byte(normal)
 18030  }
 18031  
 18032  func (prg *prg) macroCall(defRef, argList, macroName halfword) {
 18033  	var (
 18034  		r1             halfword // current node in the macro's token list
 18035  		p, q           halfword // for list manipulation
 18036  		n              int32    // the number of arguments
 18037  		lDelim, rDelim halfword // a delimiter pair
 18038  		tail           halfword // tail of the argument list
 18039  	)
 18040  	r1 = *(*prg.mem[defRef].hh()).rh()
 18041  	*(*prg.mem[defRef].hh()).lh() = uint16(int32(*(*prg.mem[defRef].hh()).lh()) + 1)
 18042  	if int32(argList) == memMin {
 18043  		n = 0
 18044  	} else {
 18045  		// Determine the number |n| of arguments already supplied, and set |tail| to the tail of |arg_list|
 18046  		n = 1
 18047  		tail = argList
 18048  		for int32(*(*prg.mem[tail].hh()).rh()) != memMin {
 18049  			n = n + 1
 18050  			tail = *(*prg.mem[tail].hh()).rh()
 18051  		}
 18052  	}
 18053  	if prg.internal[tracingMacros-1] > 0 {
 18054  		prg.beginDiagnostic()
 18055  		prg.printLn()
 18056  		prg.printMacroName(argList, macroName)
 18057  		if n == 3 {
 18058  			prg.print( /* "@#" */ 664)
 18059  		} // indicate a suffixed macro
 18060  		prg.showMacro(defRef, memMin, 100000)
 18061  		if int32(argList) != memMin {
 18062  			n = 0
 18063  			p = argList
 18064  			for {
 18065  				q = *(*prg.mem[p].hh()).lh()
 18066  				prg.printArg(q, n, halfword(0))
 18067  				n = n + 1
 18068  				p = *(*prg.mem[p].hh()).rh()
 18069  				if int32(p) == memMin {
 18070  					break
 18071  				}
 18072  			}
 18073  		}
 18074  		prg.endDiagnostic(false)
 18075  	}
 18076  
 18077  	// Scan the remaining arguments, if any; set |r| to the first token of the replacement text
 18078  	prg.curCmd = byte(comma + 1) // anything |<>comma| will do
 18079  	for int32(*(*prg.mem[r1].hh()).lh()) >= hashBase+hashSize+12+1 {
 18080  		if int32(prg.curCmd) != comma {
 18081  			prg.getXNext()
 18082  			if int32(prg.curCmd) != leftDelimiter {
 18083  				{
 18084  					if int32(prg.interaction) == errorStopMode {
 18085  					}
 18086  					prg.printNl(strNumber( /* "! " */ 261))
 18087  					prg.print( /* "Missing argument to " */ 708) /* \xref[!\relax]  */
 18088  				}
 18089  				// \xref[Missing argument...]
 18090  				prg.printMacroName(argList, macroName)
 18091  				{
 18092  					prg.helpPtr = 3
 18093  					prg.helpLine[2] = /* "That macro has more parameters than you thought." */ 709
 18094  					prg.helpLine[1] = /* "I'll continue by pretending that each missing argument" */ 710
 18095  					prg.helpLine[0] = /* "is either zero or null." */ 711
 18096  				}
 18097  				if int32(*(*prg.mem[r1].hh()).lh()) >= hashBase+hashSize+12+1+paramSize {
 18098  					prg.curExp = memMin
 18099  					prg.curType = byte(tokenList)
 18100  				} else {
 18101  					prg.curExp = 0
 18102  					prg.curType = byte(known)
 18103  				}
 18104  				prg.backError()
 18105  				prg.curCmd = byte(rightDelimiter)
 18106  				goto found
 18107  			}
 18108  			lDelim = prg.curSym
 18109  			rDelim = uint16(prg.curMod)
 18110  		}
 18111  
 18112  		// Scan the argument represented by |info(r)|
 18113  		if int32(*(*prg.mem[r1].hh()).lh()) >= hashBase+hashSize+12+1+paramSize+paramSize {
 18114  			prg.scanTextArg(lDelim, rDelim)
 18115  		} else {
 18116  			prg.getXNext()
 18117  			if int32(*(*prg.mem[r1].hh()).lh()) >= hashBase+hashSize+12+1+paramSize {
 18118  				prg.scanSuffix()
 18119  			} else {
 18120  				prg.scanExpression()
 18121  			}
 18122  		}
 18123  		if int32(prg.curCmd) != comma {
 18124  			if int32(prg.curCmd) != rightDelimiter || prg.curMod != int32(lDelim) {
 18125  				if int32(*(*prg.mem[*(*prg.mem[r1].hh()).rh()].hh()).lh()) >= hashBase+hashSize+12+1 {
 18126  					prg.missingErr(strNumber(','))
 18127  					// \xref[Missing `,']
 18128  					{
 18129  						prg.helpPtr = 3
 18130  						prg.helpLine[2] = /* "I've finished reading a macro argument and am about to" */ 712
 18131  						prg.helpLine[1] = /* "read another; the arguments weren't delimited correctly." */ 713
 18132  						prg.helpLine[0] = /* "You might want to delete some tokens before continuing." */ 707
 18133  					}
 18134  					prg.backError()
 18135  					prg.curCmd = byte(comma)
 18136  				} else {
 18137  					prg.missingErr(*prg.hash[rDelim-1].rh())
 18138  					// \xref[Missing `)']
 18139  					{
 18140  						prg.helpPtr = 2
 18141  						prg.helpLine[1] = /* "I've gotten to the end of the macro parameter list." */ 714
 18142  						prg.helpLine[0] = /* "You might want to delete some tokens before continuing." */ 707
 18143  					}
 18144  					prg.backError()
 18145  				}
 18146  			}
 18147  		}
 18148  
 18149  	found:
 18150  		{
 18151  			p = prg.getAvail()
 18152  			if int32(prg.curType) == tokenList {
 18153  				*(*prg.mem[p].hh()).lh() = uint16(prg.curExp)
 18154  			} else {
 18155  				*(*prg.mem[p].hh()).lh() = prg.stashCurExp()
 18156  			}
 18157  			if prg.internal[tracingMacros-1] > 0 {
 18158  				prg.beginDiagnostic()
 18159  				prg.printArg(*(*prg.mem[p].hh()).lh(), n, *(*prg.mem[r1].hh()).lh())
 18160  				prg.endDiagnostic(false)
 18161  			}
 18162  			if int32(argList) == memMin {
 18163  				argList = p
 18164  			} else {
 18165  				*(*prg.mem[tail].hh()).rh() = p
 18166  			}
 18167  			tail = p
 18168  			n = n + 1
 18169  		}
 18170  		r1 = *(*prg.mem[r1].hh()).rh()
 18171  	}
 18172  	if int32(prg.curCmd) == comma {
 18173  		{
 18174  			if int32(prg.interaction) == errorStopMode {
 18175  			}
 18176  			prg.printNl(strNumber( /* "! " */ 261))
 18177  			prg.print( /* "Too many arguments to " */ 703) /* \xref[!\relax]  */
 18178  		}
 18179  		// \xref[Too many arguments...]
 18180  		prg.printMacroName(argList, macroName)
 18181  		prg.printChar(asciiCode(';'))
 18182  		prg.printNl(strNumber( /* "  Missing `" */ 704))
 18183  		prg.slowPrint(int32(*prg.hash[rDelim-1].rh()))
 18184  		// \xref[Missing `)'...]
 18185  		prg.print( /* "' has been inserted" */ 300)
 18186  		{
 18187  			prg.helpPtr = 3
 18188  			prg.helpLine[2] = /* "I'm going to assume that the comma I just read was a" */ 705
 18189  			prg.helpLine[1] = /* "right delimiter, and then I'll begin expanding the macro." */ 706
 18190  			prg.helpLine[0] = /* "You might want to delete some tokens before continuing." */ 707
 18191  		}
 18192  		prg.error1()
 18193  	}
 18194  	if int32(*(*prg.mem[r1].hh()).lh()) != generalMacro {
 18195  		if int32(*(*prg.mem[r1].hh()).lh()) < textMacro {
 18196  			prg.getXNext()
 18197  			if int32(*(*prg.mem[r1].hh()).lh()) != suffixMacro {
 18198  				if int32(prg.curCmd) == equals || int32(prg.curCmd) == assignment {
 18199  					prg.getXNext()
 18200  				}
 18201  			}
 18202  		}
 18203  		switch *(*prg.mem[r1].hh()).lh() {
 18204  		case primaryMacro:
 18205  			prg.scanPrimary()
 18206  		case secondaryMacro:
 18207  			prg.scanSecondary()
 18208  		case tertiaryMacro:
 18209  			prg.scanTertiary()
 18210  		case exprMacro:
 18211  			prg.scanExpression()
 18212  		case ofMacro:
 18213  			// Scan an expression followed by `\&[of] $\langle$primary$\rangle$'
 18214  			prg.scanExpression()
 18215  			p = prg.getAvail()
 18216  			*(*prg.mem[p].hh()).lh() = prg.stashCurExp()
 18217  			if prg.internal[tracingMacros-1] > 0 {
 18218  				prg.beginDiagnostic()
 18219  				prg.printArg(*(*prg.mem[p].hh()).lh(), n, halfword(0))
 18220  				prg.endDiagnostic(false)
 18221  			}
 18222  			if int32(argList) == memMin {
 18223  				argList = p
 18224  			} else {
 18225  				*(*prg.mem[tail].hh()).rh() = p
 18226  			}
 18227  			tail = p
 18228  			n = n + 1
 18229  			if int32(prg.curCmd) != ofToken {
 18230  				prg.missingErr(strNumber( /* "of" */ 479))
 18231  				prg.print( /* " for " */ 715)
 18232  				// \xref[Missing `of']
 18233  				prg.printMacroName(argList, macroName)
 18234  				{
 18235  					prg.helpPtr = 1
 18236  					prg.helpLine[0] = /* "I've got the first argument; will look now for the other." */ 716
 18237  				}
 18238  				prg.backError()
 18239  			}
 18240  			prg.getXNext()
 18241  			prg.scanPrimary()
 18242  
 18243  		case suffixMacro:
 18244  			// Scan a suffix with optional delimiters
 18245  			if int32(prg.curCmd) != leftDelimiter {
 18246  				lDelim = uint16(memMin)
 18247  			} else {
 18248  				lDelim = prg.curSym
 18249  				rDelim = uint16(prg.curMod)
 18250  				prg.getXNext()
 18251  			}
 18252  			prg.scanSuffix()
 18253  			if int32(lDelim) != memMin {
 18254  				if int32(prg.curCmd) != rightDelimiter || prg.curMod != int32(lDelim) {
 18255  					prg.missingErr(*prg.hash[rDelim-1].rh())
 18256  					// \xref[Missing `)']
 18257  					{
 18258  						prg.helpPtr = 2
 18259  						prg.helpLine[1] = /* "I've gotten to the end of the macro parameter list." */ 714
 18260  						prg.helpLine[0] = /* "You might want to delete some tokens before continuing." */ 707
 18261  					}
 18262  					prg.backError()
 18263  				}
 18264  				prg.getXNext()
 18265  			}
 18266  
 18267  		case textMacro:
 18268  			prg.scanTextArg(halfword(0), halfword(0))
 18269  		} // there are no other cases
 18270  		prg.backInput()
 18271  		// Append the current expression to |arg_list|
 18272  		{
 18273  			p = prg.getAvail()
 18274  			if int32(prg.curType) == tokenList {
 18275  				*(*prg.mem[p].hh()).lh() = uint16(prg.curExp)
 18276  			} else {
 18277  				*(*prg.mem[p].hh()).lh() = prg.stashCurExp()
 18278  			}
 18279  			if prg.internal[tracingMacros-1] > 0 {
 18280  				prg.beginDiagnostic()
 18281  				prg.printArg(*(*prg.mem[p].hh()).lh(), n, *(*prg.mem[r1].hh()).lh())
 18282  				prg.endDiagnostic(false)
 18283  			}
 18284  			if int32(argList) == memMin {
 18285  				argList = p
 18286  			} else {
 18287  				*(*prg.mem[tail].hh()).rh() = p
 18288  			}
 18289  			tail = p
 18290  			n = n + 1
 18291  		}
 18292  	}
 18293  	r1 = *(*prg.mem[r1].hh()).rh()
 18294  
 18295  	// Feed the arguments and replacement text to the scanner
 18296  	for int32(prg.curInput.indexField) > maxInOpen && int32(prg.curInput.locField) == memMin {
 18297  		prg.endTokenList()
 18298  	} // conserve stack space
 18299  	if int32(prg.paramPtr)+n > prg.maxParamStack {
 18300  		prg.maxParamStack = int32(prg.paramPtr) + n
 18301  		if prg.maxParamStack > paramSize {
 18302  			prg.overflow(strNumber( /* "parameter stack size" */ 686), paramSize)
 18303  		}
 18304  		// \xref[METAFONT capacity exceeded parameter stack size][\quad parameter stack size]
 18305  	}
 18306  	prg.beginTokenList(defRef, quarterword(macro))
 18307  	prg.curInput.nameField = macroName
 18308  	prg.curInput.locField = r1
 18309  	if n > 0 {
 18310  		p = argList
 18311  		for {
 18312  			prg.paramStack[prg.paramPtr] = *(*prg.mem[p].hh()).lh()
 18313  			prg.paramPtr = byte(int32(prg.paramPtr) + 1)
 18314  			p = *(*prg.mem[p].hh()).rh()
 18315  			if int32(p) == memMin {
 18316  				break
 18317  			}
 18318  		}
 18319  		prg.flushList(argList)
 18320  	}
 18321  } // \2
 18322  
 18323  // 707.
 18324  
 18325  // tangle:pos ../../mf.web:14608:3:
 18326  
 18327  // An auxiliary subroutine called |expand| is used by |get_x_next|
 18328  // when it has to do exotic expansion commands.
 18329  func (prg *prg) expand() {
 18330  	var (
 18331  		p halfword    // for list manipulation
 18332  		k int32       // something that we hope is |<=buf_size|
 18333  		j poolPointer // index into |str_pool|
 18334  	)
 18335  	if prg.internal[tracingCommands-1] > 0200000 {
 18336  		if int32(prg.curCmd) != definedMacro {
 18337  			prg.showCmdMod(int32(prg.curCmd), prg.curMod)
 18338  		}
 18339  	}
 18340  	switch prg.curCmd {
 18341  	case ifTest:
 18342  		prg.conditional() // this procedure is discussed in Part 36 below
 18343  	case fiOrElse:
 18344  		// Terminate the current conditional and skip to \&[fi]
 18345  		if prg.curMod > int32(prg.ifLimit) {
 18346  			if int32(prg.ifLimit) == ifCode {
 18347  				prg.missingErr(strNumber(':'))
 18348  				// \xref[Missing `:']
 18349  				prg.backInput()
 18350  				prg.curSym = uint16(hashBase + hashSize + 5)
 18351  				prg.insError()
 18352  			} else {
 18353  				{
 18354  					if int32(prg.interaction) == errorStopMode {
 18355  					}
 18356  					prg.printNl(strNumber( /* "! " */ 261))
 18357  					prg.print( /* "Extra " */ 723) /* \xref[!\relax]  */
 18358  				}
 18359  				prg.printCmdMod(fiOrElse, prg.curMod)
 18360  				// \xref[Extra else]
 18361  				// \xref[Extra elseif]
 18362  				// \xref[Extra fi]
 18363  				{
 18364  					prg.helpPtr = 1
 18365  					prg.helpLine[0] = /* "I'm ignoring this; it doesn't match any if." */ 724
 18366  				}
 18367  				prg.error1()
 18368  			}
 18369  		} else {
 18370  			for prg.curMod != fiCode {
 18371  				prg.passText()
 18372  			} // skip to \&[fi]
 18373  
 18374  			// Pop the condition stack
 18375  			{
 18376  				p = prg.condPtr
 18377  				prg.ifLine = *prg.mem[int32(p)+1].int()
 18378  				prg.curIf = *(*prg.mem[p].hh()).b1()
 18379  				prg.ifLimit = *(*prg.mem[p].hh()).b0()
 18380  				prg.condPtr = *(*prg.mem[p].hh()).rh()
 18381  				prg.freeNode(p, halfword(ifNodeSize))
 18382  			}
 18383  		}
 18384  
 18385  	case input:
 18386  		// Initiate or terminate input from a file
 18387  		if prg.curMod > 0 {
 18388  			prg.forceEof = true
 18389  		} else {
 18390  			prg.startInput()
 18391  		}
 18392  
 18393  	case iteration:
 18394  		if prg.curMod == endFor {
 18395  			{
 18396  				if int32(prg.interaction) == errorStopMode {
 18397  				}
 18398  				prg.printNl(strNumber( /* "! " */ 261))
 18399  				prg.print( /* "Extra `endfor'" */ 687) /* \xref[!\relax]  */
 18400  			}
 18401  			// \xref[Extra `endfor']
 18402  			{
 18403  				prg.helpPtr = 2
 18404  				prg.helpLine[1] = /* "I'm not currently working on a for loop," */ 688
 18405  				prg.helpLine[0] = /* "so I had better not try to end anything." */ 689
 18406  			}
 18407  
 18408  			prg.error1()
 18409  		} else {
 18410  			prg.beginIteration()
 18411  		} // this procedure is discussed in Part 37 below
 18412  	case repeatLoop:
 18413  		// Repeat a loop
 18414  		for int32(prg.curInput.indexField) > maxInOpen && int32(prg.curInput.locField) == memMin {
 18415  			prg.endTokenList()
 18416  		} // conserve stack space
 18417  		if int32(prg.loopPtr) == memMin {
 18418  			{
 18419  				if int32(prg.interaction) == errorStopMode {
 18420  				}
 18421  				prg.printNl(strNumber( /* "! " */ 261))
 18422  				prg.print( /* "Lost loop" */ 691) /* \xref[!\relax]  */
 18423  			}
 18424  			// \xref[Lost loop]
 18425  			{
 18426  				prg.helpPtr = 2
 18427  				prg.helpLine[1] = /* "I'm confused; after exiting from a loop, I still seem" */ 692
 18428  				prg.helpLine[0] = /* "to want to repeat it. I'll try to forget the problem." */ 693
 18429  			}
 18430  
 18431  			prg.error1()
 18432  		} else {
 18433  			prg.resumeIteration()
 18434  		} // this procedure is in Part 37 below
 18435  
 18436  	case exitTest:
 18437  		// Exit a loop if the proper time has come
 18438  		prg.getBoolean()
 18439  		if prg.internal[tracingCommands-1] > 0200000 {
 18440  			prg.showCmdMod(nullary, prg.curExp)
 18441  		}
 18442  		if prg.curExp == trueCode {
 18443  			if int32(prg.loopPtr) == memMin {
 18444  				{
 18445  					if int32(prg.interaction) == errorStopMode {
 18446  					}
 18447  					prg.printNl(strNumber( /* "! " */ 261))
 18448  					prg.print( /* "No loop is in progress" */ 694) /* \xref[!\relax]  */
 18449  				}
 18450  				// \xref[No loop is in progress]
 18451  				{
 18452  					prg.helpPtr = 1
 18453  					prg.helpLine[0] = /* "Why say `exitif' when there's nothing to exit from?" */ 695
 18454  				}
 18455  				if int32(prg.curCmd) == semicolon {
 18456  					prg.error1()
 18457  				} else {
 18458  					prg.backError()
 18459  				}
 18460  			} else {
 18461  				// Exit prematurely from an iteration
 18462  				p = uint16(memMin)
 18463  				for {
 18464  					if int32(prg.curInput.indexField) <= maxInOpen {
 18465  						prg.endFileReading()
 18466  					} else {
 18467  						if int32(prg.curInput.indexField) <= loopText {
 18468  							p = prg.curInput.startField
 18469  						}
 18470  						prg.endTokenList()
 18471  					}
 18472  					if int32(p) != memMin {
 18473  						break
 18474  					}
 18475  				}
 18476  				if int32(p) != int32(*(*prg.mem[prg.loopPtr].hh()).lh()) {
 18477  					prg.fatalError(strNumber( /* "*** (loop confusion)" */ 698))
 18478  				}
 18479  				// \xref[loop confusion]
 18480  				prg.stopIteration() // this procedure is in Part 37 below
 18481  			}
 18482  		} else if int32(prg.curCmd) != semicolon {
 18483  			prg.missingErr(strNumber(';'))
 18484  
 18485  			// \xref[Missing `;']
 18486  			{
 18487  				prg.helpPtr = 2
 18488  				prg.helpLine[1] = /* "After `exitif <boolean expr>' I expect to see a semicolon." */ 696
 18489  				prg.helpLine[0] = /* "I shall pretend that one was there." */ 697
 18490  			}
 18491  			prg.backError()
 18492  		}
 18493  
 18494  	case relax:
 18495  	case expandAfter:
 18496  		// Expand the token after the next token
 18497  		prg.getNext()
 18498  		p = prg.curTok()
 18499  		prg.getNext()
 18500  		if int32(prg.curCmd) < minCommand {
 18501  			prg.expand()
 18502  		} else {
 18503  			prg.backInput()
 18504  		}
 18505  		prg.beginTokenList(p, quarterword(backedUp))
 18506  
 18507  	case scanTokens:
 18508  		// Put a string into the input buffer
 18509  		prg.getXNext()
 18510  		prg.scanPrimary()
 18511  		if int32(prg.curType) != stringType {
 18512  			prg.dispErr(halfword(memMin), strNumber( /* "Not a string" */ 699))
 18513  			// \xref[Not a string]
 18514  			{
 18515  				prg.helpPtr = 2
 18516  				prg.helpLine[1] = /* "I'm going to flush this expression, since" */ 700
 18517  				prg.helpLine[0] = /* "scantokens should be followed by a known string." */ 701
 18518  			}
 18519  			prg.putGetFlushError(scaled(0))
 18520  		} else {
 18521  			prg.backInput()
 18522  			if int32(prg.strStart[prg.curExp+1])-int32(prg.strStart[prg.curExp]) > 0 {
 18523  				prg.beginFileReading()
 18524  				prg.curInput.nameField = 2
 18525  				k = int32(prg.first) + (int32(prg.strStart[prg.curExp+1]) - int32(prg.strStart[prg.curExp]))
 18526  				if k >= int32(prg.maxBufStack) {
 18527  					if k >= bufSize {
 18528  						prg.maxBufStack = uint16(bufSize)
 18529  						prg.overflow(strNumber( /* "buffer size" */ 256), bufSize)
 18530  						// \xref[METAFONT capacity exceeded buffer size][\quad buffer size]
 18531  					}
 18532  					prg.maxBufStack = uint16(k + 1)
 18533  				}
 18534  				j = prg.strStart[prg.curExp]
 18535  				prg.curInput.limitField = uint16(k)
 18536  				for int32(prg.first) < int32(prg.curInput.limitField) {
 18537  					prg.buffer[prg.first] = prg.strPool[j]
 18538  					j = uint16(int32(j) + 1)
 18539  					prg.first = uint16(int32(prg.first) + 1)
 18540  				}
 18541  				prg.buffer[prg.curInput.limitField] = '%'
 18542  				prg.first = uint16(int32(prg.curInput.limitField) + 1)
 18543  				prg.curInput.locField = prg.curInput.startField
 18544  				prg.flushCurExp(scaled(0))
 18545  			}
 18546  		}
 18547  
 18548  	case definedMacro:
 18549  		prg.macroCall(halfword(prg.curMod), halfword(memMin), prg.curSym)
 18550  	} // there are no other cases
 18551  } // \2
 18552  
 18553  func (prg *prg) getXNext() {
 18554  	var (
 18555  		saveExp halfword // a capsule to save |cur_type| and |cur_exp|
 18556  	)
 18557  	prg.getNext()
 18558  	if int32(prg.curCmd) < minCommand {
 18559  		saveExp = prg.stashCurExp()
 18560  		for {
 18561  			if int32(prg.curCmd) == definedMacro {
 18562  				prg.macroCall(halfword(prg.curMod), halfword(memMin), prg.curSym)
 18563  			} else {
 18564  				prg.expand()
 18565  			}
 18566  			prg.getNext()
 18567  			if int32(prg.curCmd) >= minCommand {
 18568  				break
 18569  			}
 18570  		}
 18571  		prg.unstashCurExp(saveExp) // that restores |cur_type| and |cur_exp|
 18572  	}
 18573  }
 18574  
 18575  // 719.
 18576  
 18577  // tangle:pos ../../mf.web:14767:3:
 18578  
 18579  // Now let's consider the |macro_call| procedure, which is used to start up
 18580  // all user-defined macros. Since the arguments to a macro might be expressions,
 18581  // |macro_call| is recursive.
 18582  // \xref[recursion]
 18583  //
 18584  // The first parameter to |macro_call| points to the reference count of the
 18585  // token list that defines the macro. The second parameter contains any
 18586  // arguments that have already been parsed (see below).  The third parameter
 18587  // points to the symbolic token that names the macro. If the third parameter
 18588  // is |null|, the macro was defined by \&[vardef], so its name can be
 18589  // reconstructed from the prefix and ``at'' arguments found within the
 18590  // second parameter.
 18591  //
 18592  // What is this second parameter? It's simply a linked list of one-word items,
 18593  // whose |info| fields point to the arguments. In other words, if |arg_list=null|,
 18594  // no arguments have been scanned yet; otherwise |info(arg_list)| points to
 18595  // the first scanned argument, and |link(arg_list)| points to the list of
 18596  // further arguments (if any).
 18597  //
 18598  // Arguments of type \&[expr] are so-called capsules, which we will
 18599  // discuss later when we concentrate on expressions; they can be
 18600  // recognized easily because their |link| field is |void|. Arguments of type
 18601  // \&[suffix] and \&[text] are token lists without reference counts.
 18602  
 18603  // 737.
 18604  
 18605  // tangle:pos ../../mf.web:15073:3:
 18606  
 18607  // It's sometimes necessary to put a single argument onto |param_stack|.
 18608  // The |stack_argument| subroutine does this.
 18609  func (prg *prg) stackArgument(p halfword) {
 18610  	if int32(prg.paramPtr) == prg.maxParamStack {
 18611  		prg.maxParamStack = prg.maxParamStack + 1
 18612  		if prg.maxParamStack > paramSize {
 18613  			prg.overflow(strNumber( /* "parameter stack size" */ 686), paramSize)
 18614  		}
 18615  		// \xref[METAFONT capacity exceeded parameter stack size][\quad parameter stack size]
 18616  	}
 18617  	prg.paramStack[prg.paramPtr] = p
 18618  	prg.paramPtr = byte(int32(prg.paramPtr) + 1)
 18619  } // \2
 18620  func (prg *prg) passText() {
 18621  	var (
 18622  		l int32
 18623  	)
 18624  	prg.scannerStatus = byte(skipping)
 18625  	l = 0
 18626  	prg.warningInfo = prg.line
 18627  	for true {
 18628  		prg.getNext()
 18629  		if int32(prg.curCmd) <= fiOrElse {
 18630  			if int32(prg.curCmd) < fiOrElse {
 18631  				l = l + 1
 18632  			} else {
 18633  				if l == 0 {
 18634  					goto done
 18635  				}
 18636  				if prg.curMod == fiCode {
 18637  					l = l - 1
 18638  				}
 18639  			}
 18640  		} else if int32(prg.curCmd) == stringToken {
 18641  			if int32(prg.strRef[prg.curMod]) < maxStrRef {
 18642  				if int32(prg.strRef[prg.curMod]) > 1 {
 18643  					prg.strRef[prg.curMod] = byte(int32(prg.strRef[prg.curMod]) - 1)
 18644  				} else {
 18645  					prg.flushString(strNumber(prg.curMod))
 18646  				}
 18647  			}
 18648  		}
 18649  	}
 18650  
 18651  done:
 18652  	prg.scannerStatus = byte(normal)
 18653  }
 18654  
 18655  // 746.
 18656  
 18657  // tangle:pos ../../mf.web:15182:3:
 18658  
 18659  // Here's a procedure that changes the |if_limit| code corresponding to
 18660  // a given value of |cond_ptr|.
 18661  func (prg *prg) changeIfLimit(l smallNumber, p halfword) {
 18662  	var (
 18663  		q halfword
 18664  	)
 18665  	if int32(p) == int32(prg.condPtr) {
 18666  		prg.ifLimit = l
 18667  	} else {
 18668  		q = prg.condPtr
 18669  		for true {
 18670  			if int32(q) == memMin {
 18671  				prg.confusion(strNumber( /* "if" */ 717))
 18672  			}
 18673  			// \xref[this can't happen if][\quad if]
 18674  			if int32(*(*prg.mem[q].hh()).rh()) == int32(p) {
 18675  				*(*prg.mem[q].hh()).b0() = l
 18676  				goto exit
 18677  			}
 18678  			q = *(*prg.mem[q].hh()).rh()
 18679  		}
 18680  	}
 18681  
 18682  exit:
 18683  }
 18684  
 18685  // 747.
 18686  
 18687  // tangle:pos ../../mf.web:15200:3:
 18688  
 18689  // The user is supposed to put colons into the proper parts of conditional
 18690  // statements. Therefore, \MF\ has to check for their presence.
 18691  func (prg *prg) checkColon() {
 18692  	if int32(prg.curCmd) != colon {
 18693  		prg.missingErr(strNumber(':'))
 18694  
 18695  		// \xref[Missing `:']
 18696  		{
 18697  			prg.helpPtr = 2
 18698  			prg.helpLine[1] = /* "There should've been a colon after the condition." */ 720
 18699  			prg.helpLine[0] = /* "I shall pretend that one was there." */ 697
 18700  		}
 18701  		prg.backError()
 18702  	}
 18703  } // \2
 18704  func (prg *prg) conditional() {
 18705  	var (
 18706  		saveCondPtr                             halfword // |cond_ptr| corresponding to this conditional
 18707  		newIfLimit/* fiCode..elseIfCode */ byte          // future value of |if_limit|
 18708  		p                                       halfword // temporary register
 18709  	)
 18710  	{
 18711  		p = prg.getNode(ifNodeSize)
 18712  		*(*prg.mem[p].hh()).rh() = prg.condPtr
 18713  		*(*prg.mem[p].hh()).b0() = prg.ifLimit
 18714  		*(*prg.mem[p].hh()).b1() = prg.curIf
 18715  		*prg.mem[int32(p)+1].int() = prg.ifLine
 18716  		prg.condPtr = p
 18717  		prg.ifLimit = byte(ifCode)
 18718  		prg.ifLine = prg.line
 18719  		prg.curIf = byte(ifCode)
 18720  	}
 18721  	saveCondPtr = prg.condPtr
 18722  
 18723  reswitch:
 18724  	prg.getBoolean()
 18725  	newIfLimit = byte(elseIfCode)
 18726  	if prg.internal[tracingCommands-1] > 0200000 {
 18727  		prg.beginDiagnostic()
 18728  		if prg.curExp == trueCode {
 18729  			prg.print( /* "[true]" */ 721)
 18730  		} else {
 18731  			prg.print( /* "[false]" */ 722)
 18732  		}
 18733  		prg.endDiagnostic(false)
 18734  	}
 18735  
 18736  found:
 18737  	prg.checkColon()
 18738  	if prg.curExp == trueCode {
 18739  		prg.changeIfLimit(newIfLimit, saveCondPtr)
 18740  
 18741  		goto exit // wait for \&[elseif], \&[else], or \&[fi]
 18742  	}
 18743  
 18744  	// Skip to \&[elseif] or \&[else] or \&[fi], then |goto done|
 18745  	for true {
 18746  		prg.passText()
 18747  		if int32(prg.condPtr) == int32(saveCondPtr) {
 18748  			goto done
 18749  		} else if prg.curMod == fiCode {
 18750  			p = prg.condPtr
 18751  			prg.ifLine = *prg.mem[int32(p)+1].int()
 18752  			prg.curIf = *(*prg.mem[p].hh()).b1()
 18753  			prg.ifLimit = *(*prg.mem[p].hh()).b0()
 18754  			prg.condPtr = *(*prg.mem[p].hh()).rh()
 18755  			prg.freeNode(p, halfword(ifNodeSize))
 18756  		}
 18757  	}
 18758  
 18759  done:
 18760  	prg.curIf = byte(prg.curMod)
 18761  	prg.ifLine = prg.line
 18762  	if prg.curMod == fiCode {
 18763  		p = prg.condPtr
 18764  		prg.ifLine = *prg.mem[int32(p)+1].int()
 18765  		prg.curIf = *(*prg.mem[p].hh()).b1()
 18766  		prg.ifLimit = *(*prg.mem[p].hh()).b0()
 18767  		prg.condPtr = *(*prg.mem[p].hh()).rh()
 18768  		prg.freeNode(p, halfword(ifNodeSize))
 18769  	} else if prg.curMod == elseIfCode {
 18770  		goto reswitch
 18771  	} else {
 18772  		prg.curExp = trueCode
 18773  		newIfLimit = byte(fiCode)
 18774  		prg.getXNext()
 18775  		goto found
 18776  	}
 18777  
 18778  exit:
 18779  }
 18780  
 18781  // 754.
 18782  
 18783  // tangle:pos ../../mf.web:15322:3:
 18784  
 18785  // If the expressions that define an arithmetic progression in
 18786  // a \&[for] loop don't have known numeric values, the |bad_for|
 18787  // subroutine screams at the user.
 18788  func (prg *prg) badFor(s strNumber) {
 18789  	prg.dispErr(halfword(memMin), strNumber( /* "Improper " */ 725)) // show the bad expression above the message
 18790  	// \xref[Improper...replaced by 0]
 18791  	prg.print(int32(s))
 18792  	prg.print( /* " has been replaced by 0" */ 307)
 18793  	{
 18794  		prg.helpPtr = 4
 18795  		prg.helpLine[3] = /* "When you say `for x=a step b until c'," */ 726
 18796  		prg.helpLine[2] = /* "the initial value `a' and the step size `b'" */ 727
 18797  		prg.helpLine[1] = /* "and the final value `c' must have known numeric values." */ 728
 18798  		prg.helpLine[0] = /* "I'm zeroing this one. Proceed, with fingers crossed." */ 309
 18799  	}
 18800  	prg.putGetFlushError(scaled(0))
 18801  } // \2
 18802  func (prg *prg) beginIteration() {
 18803  	var (
 18804  		m           halfword // |expr_base| (\&[for]) or |suffix_base| (\&[forsuffixes])
 18805  		n           halfword // hash address of the current symbol
 18806  		p, q, s, pp halfword // link manipulation registers
 18807  	)
 18808  	m = uint16(prg.curMod)
 18809  	n = prg.curSym
 18810  	s = prg.getNode(loopNodeSize)
 18811  	if int32(m) == startForever {
 18812  		*(*prg.mem[int32(s)+1].hh()).lh() = uint16(memMin + 1)
 18813  		p = uint16(memMin)
 18814  		prg.getXNext()
 18815  		goto found
 18816  	}
 18817  	prg.getSymbol()
 18818  	p = prg.getNode(tokenNodeSize)
 18819  	*(*prg.mem[p].hh()).lh() = prg.curSym
 18820  	*prg.mem[int32(p)+1].int() = int32(m)
 18821  
 18822  	prg.getXNext()
 18823  	if int32(prg.curCmd) != equals && int32(prg.curCmd) != assignment {
 18824  		prg.missingErr(strNumber('='))
 18825  
 18826  		// \xref[Missing `=']
 18827  		{
 18828  			prg.helpPtr = 3
 18829  			prg.helpLine[2] = /* "The next thing in this loop should have been `=' or `:='." */ 729
 18830  			prg.helpLine[1] = /* "But don't worry; I'll pretend that an equals sign" */ 672
 18831  			prg.helpLine[0] = /* "was present, and I'll look for the values next." */ 730
 18832  		}
 18833  
 18834  		prg.backError()
 18835  	}
 18836  
 18837  	// Scan the values to be used in the loop
 18838  	*(*prg.mem[int32(s)+1].hh()).lh() = uint16(memMin)
 18839  	q = uint16(int32(s) + 1)
 18840  	*(*prg.mem[q].hh()).rh() = uint16(memMin) // |link(q)=loop_list(s)|
 18841  	for {
 18842  		prg.getXNext()
 18843  		if int32(m) != hashBase+hashSize+12+1 {
 18844  			prg.scanSuffix()
 18845  		} else {
 18846  			if int32(prg.curCmd) >= colon {
 18847  				if int32(prg.curCmd) <= comma {
 18848  					goto continue1
 18849  				}
 18850  			}
 18851  			prg.scanExpression()
 18852  			if int32(prg.curCmd) == stepToken {
 18853  				if int32(q) == int32(s)+1 {
 18854  					if int32(prg.curType) != known {
 18855  						prg.badFor(strNumber( /* "initial value" */ 736))
 18856  					}
 18857  					pp = prg.getNode(progressionNodeSize)
 18858  					*prg.mem[int32(pp)+1].int() = prg.curExp
 18859  
 18860  					prg.getXNext()
 18861  					prg.scanExpression()
 18862  					if int32(prg.curType) != known {
 18863  						prg.badFor(strNumber( /* "step size" */ 737))
 18864  					}
 18865  					*prg.mem[int32(pp)+2].int() = prg.curExp
 18866  					if int32(prg.curCmd) != untilToken {
 18867  						prg.missingErr(strNumber( /* "until" */ 490))
 18868  
 18869  						// \xref[Missing `until']
 18870  						{
 18871  							prg.helpPtr = 2
 18872  							prg.helpLine[1] = /* "I assume you meant to say `until' after `step'." */ 738
 18873  							prg.helpLine[0] = /* "So I'll look for the final value and colon next." */ 739
 18874  						}
 18875  						prg.backError()
 18876  					}
 18877  					prg.getXNext()
 18878  					prg.scanExpression()
 18879  					if int32(prg.curType) != known {
 18880  						prg.badFor(strNumber( /* "final value" */ 740))
 18881  					}
 18882  					*prg.mem[int32(pp)+3].int() = prg.curExp
 18883  					*(*prg.mem[int32(s)+1].hh()).lh() = pp
 18884  					goto done
 18885  				}
 18886  			}
 18887  			prg.curExp = int32(prg.stashCurExp())
 18888  		}
 18889  		*(*prg.mem[q].hh()).rh() = prg.getAvail()
 18890  		q = *(*prg.mem[q].hh()).rh()
 18891  		*(*prg.mem[q].hh()).lh() = uint16(prg.curExp)
 18892  		prg.curType = byte(vacuous)
 18893  
 18894  	continue1:
 18895  		;
 18896  		if int32(prg.curCmd) != comma {
 18897  			break
 18898  		}
 18899  	}
 18900  
 18901  done:
 18902  	;
 18903  
 18904  found:
 18905  	if int32(prg.curCmd) != colon {
 18906  		prg.missingErr(strNumber(':'))
 18907  
 18908  		// \xref[Missing `:']
 18909  		{
 18910  			prg.helpPtr = 3
 18911  			prg.helpLine[2] = /* "The next thing in this loop should have been a `:'." */ 731
 18912  			prg.helpLine[1] = /* "So I'll pretend that a colon was present;" */ 732
 18913  			prg.helpLine[0] = /* "everything from here to `endfor' will be iterated." */ 733
 18914  		}
 18915  		prg.backError()
 18916  	}
 18917  
 18918  	// Scan the loop text and put it on the loop control stack
 18919  	q = prg.getAvail()
 18920  	*(*prg.mem[q].hh()).lh() = uint16(hashBase + hashSize + 1)
 18921  	prg.scannerStatus = byte(loopDefining)
 18922  	prg.warningInfo = int32(n)
 18923  	*(*prg.mem[s].hh()).lh() = prg.scanToks(commandCode(iteration), p, q, smallNumber(0))
 18924  	prg.scannerStatus = byte(normal)
 18925  
 18926  	*(*prg.mem[s].hh()).rh() = prg.loopPtr
 18927  	prg.loopPtr = s
 18928  	prg.resumeIteration()
 18929  } // \2
 18930  func (prg *prg) resumeIteration() {
 18931  	var (
 18932  		p, q halfword // link registers
 18933  	)
 18934  	p = *(*prg.mem[int32(prg.loopPtr)+1].hh()).lh()
 18935  	if int32(p) > memMin+1 {
 18936  		prg.curExp = *prg.mem[int32(p)+1].int()
 18937  		if *prg.mem[int32(p)+2].int() > 0 && prg.curExp > *prg.mem[int32(p)+3].int() || *prg.mem[int32(p)+2].int() < 0 && prg.curExp < *prg.mem[int32(p)+3].int() {
 18938  			// The arithmetic progression has ended
 18939  			goto notFound
 18940  		}
 18941  		prg.curType = byte(known)
 18942  		q = prg.stashCurExp()                                                // make |q| an \&[expr] argument
 18943  		*prg.mem[int32(p)+1].int() = prg.curExp + *prg.mem[int32(p)+2].int() // set |value(p)| for the next iteration
 18944  	} else if int32(p) < memMin+1 {
 18945  		p = *(*prg.mem[int32(prg.loopPtr)+1].hh()).rh()
 18946  		if int32(p) == memMin {
 18947  			goto notFound
 18948  		}
 18949  		*(*prg.mem[int32(prg.loopPtr)+1].hh()).rh() = *(*prg.mem[p].hh()).rh()
 18950  		q = *(*prg.mem[p].hh()).lh()
 18951  		{
 18952  			*(*prg.mem[p].hh()).rh() = prg.avail
 18953  			prg.avail = p
 18954  			prg.dynUsed = prg.dynUsed - 1
 18955  		}
 18956  	} else {
 18957  		prg.beginTokenList(*(*prg.mem[prg.loopPtr].hh()).lh(), quarterword(foreverText))
 18958  		goto exit
 18959  	}
 18960  	prg.beginTokenList(*(*prg.mem[prg.loopPtr].hh()).lh(), quarterword(loopText))
 18961  	prg.stackArgument(q)
 18962  	if prg.internal[tracingCommands-1] > 0200000 {
 18963  		prg.beginDiagnostic()
 18964  		prg.printNl(strNumber( /* "[loop value=" */ 735))
 18965  		// \xref[loop value=n]
 18966  		if int32(q) != memMin && int32(*(*prg.mem[q].hh()).rh()) == memMin+1 {
 18967  			prg.printExp(q, smallNumber(1))
 18968  		} else {
 18969  			prg.showTokenList(int32(q), memMin, 50, 0)
 18970  		}
 18971  		prg.printChar(asciiCode('}'))
 18972  		prg.endDiagnostic(false)
 18973  	}
 18974  
 18975  	goto exit
 18976  
 18977  notFound:
 18978  	prg.stopIteration()
 18979  
 18980  exit:
 18981  } // \2
 18982  func (prg *prg) stopIteration() {
 18983  	var (
 18984  		p, q halfword // the usual
 18985  	)
 18986  	p = *(*prg.mem[int32(prg.loopPtr)+1].hh()).lh()
 18987  	if int32(p) > memMin+1 {
 18988  		prg.freeNode(p, halfword(progressionNodeSize))
 18989  	} else if int32(p) < memMin+1 {
 18990  		q = *(*prg.mem[int32(prg.loopPtr)+1].hh()).rh()
 18991  		for int32(q) != memMin {
 18992  			p = *(*prg.mem[q].hh()).lh()
 18993  			if int32(p) != memMin {
 18994  				if int32(*(*prg.mem[p].hh()).rh()) == memMin+1 {
 18995  					prg.recycleValue(p)
 18996  					prg.freeNode(p, halfword(valueNodeSize))
 18997  				} else {
 18998  					prg.flushTokenList(p)
 18999  				}
 19000  			} // it's a \&[suffix] or \&[text] parameter
 19001  			p = q
 19002  			q = *(*prg.mem[q].hh()).rh()
 19003  			{
 19004  				*(*prg.mem[p].hh()).rh() = prg.avail
 19005  				prg.avail = p
 19006  				prg.dynUsed = prg.dynUsed - 1
 19007  			}
 19008  		}
 19009  	}
 19010  	p = prg.loopPtr
 19011  	prg.loopPtr = *(*prg.mem[p].hh()).rh()
 19012  	prg.flushTokenList(*(*prg.mem[p].hh()).lh())
 19013  	prg.freeNode(p, halfword(loopNodeSize))
 19014  }
 19015  
 19016  // 766. \[38] File names
 19017  
 19018  // tangle:pos ../../mf.web:15499:21:
 19019  
 19020  // It's time now to fret about file names.  Besides the fact that different
 19021  // operating systems treat files in different ways, we must cope with the
 19022  // fact that completely different naming conventions are used by different
 19023  // groups of people. The following programs show what is required for one
 19024  // particular operating system; similar routines for other systems are not
 19025  // difficult to devise.
 19026  // \xref[system dependencies]
 19027  //
 19028  // \MF\ assumes that a file name has three parts: the name proper; its
 19029  // ``extension''; and a ``file area'' where it is found in an external file
 19030  // system.  The extension of an input file is assumed to be
 19031  // `\.[.mf]' unless otherwise specified; it is `\.[.log]' on the
 19032  // transcript file that records each run of \MF; it is `\.[.tfm]' on the font
 19033  // metric files that describe characters in the fonts \MF\ creates; it is
 19034  // `\.[.gf]' on the output files that specify generic font information; and it
 19035  // is `\.[.base]' on the base files written by \.[INIMF] to initialize \MF.
 19036  // The file area can be arbitrary on input files, but files are usually
 19037  // output to the user's current area.  If an input file cannot be
 19038  // found on the specified area, \MF\ will look for it on a special system
 19039  // area; this special area is intended for commonly used input files.
 19040  //
 19041  // Simple uses of \MF\ refer only to file names that have no explicit
 19042  // extension or area. For example, a person usually says `\.[input] \.[cmr10]'
 19043  // instead of `\.[input] \.[cmr10.new]'. Simple file
 19044  // names are best, because they make the \MF\ source files portable;
 19045  // whenever a file name consists entirely of letters and digits, it should be
 19046  // treated in the same way by all implementations of \MF. However, users
 19047  // need the ability to refer to other files in their environment, especially
 19048  // when responding to error messages concerning unopenable files; therefore
 19049  // we want to let them use the syntax that appears in their favorite
 19050  // operating system.
 19051  
 19052  // 769.
 19053  
 19054  // tangle:pos ../../mf.web:15579:3:
 19055  
 19056  // Input files that can't be found in the user's area may appear in a standard
 19057  // system area called |MF_area|.
 19058  // This system area name will, of course, vary from place to place.
 19059  // \xref[system dependencies]
 19060  
 19061  // 770.
 19062  
 19063  // tangle:pos ../../mf.web:15587:3:
 19064  
 19065  // Here now is the first of the system-dependent routines for file name scanning.
 19066  // \xref[system dependencies]
 19067  func (prg *prg) beginName() {
 19068  	prg.areaDelimiter = 0
 19069  	prg.extDelimiter = 0
 19070  }
 19071  
 19072  // 771.
 19073  
 19074  // tangle:pos ../../mf.web:15594:3:
 19075  
 19076  // And here's the second.
 19077  // \xref[system dependencies]
 19078  func (prg *prg) moreName(c asciiCode) (r bool) {
 19079  	if int32(c) == ' ' {
 19080  		r = false
 19081  	} else {
 19082  		if int32(c) == '>' || int32(c) == ':' {
 19083  			prg.areaDelimiter = prg.poolPtr
 19084  			prg.extDelimiter = 0
 19085  		} else if int32(c) == '.' && int32(prg.extDelimiter) == 0 {
 19086  			prg.extDelimiter = prg.poolPtr
 19087  		}
 19088  		{
 19089  			if int32(prg.poolPtr)+1 > int32(prg.maxPoolPtr) {
 19090  				if int32(prg.poolPtr)+1 > poolSize {
 19091  					prg.overflow(strNumber( /* "pool size" */ 257), poolSize-int32(prg.initPoolPtr))
 19092  				} /* \xref[METAFONT capacity exceeded pool size][\quad pool size]  */
 19093  				prg.maxPoolPtr = uint16(int32(prg.poolPtr) + 1)
 19094  			}
 19095  		}
 19096  		{
 19097  			prg.strPool[prg.poolPtr] = c
 19098  			prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
 19099  		} // contribute |c| to the current string
 19100  		r = true
 19101  	}
 19102  	return r
 19103  }
 19104  
 19105  // 772.
 19106  
 19107  // tangle:pos ../../mf.web:15608:3:
 19108  
 19109  // The third.
 19110  // \xref[system dependencies]
 19111  func (prg *prg) endName() {
 19112  	if int32(prg.strPtr)+3 > int32(prg.maxStrPtr) {
 19113  		if int32(prg.strPtr)+3 > maxStrings {
 19114  			prg.overflow(strNumber( /* "number of strings" */ 258), maxStrings-int32(prg.initStrPtr))
 19115  		}
 19116  		// \xref[METAFONT capacity exceeded number of strings][\quad number of strings]
 19117  		prg.maxStrPtr = uint16(int32(prg.strPtr) + 3)
 19118  	}
 19119  	if int32(prg.areaDelimiter) == 0 {
 19120  		prg.curArea = /* "" */ 285
 19121  	} else {
 19122  		prg.curArea = prg.strPtr
 19123  		prg.strPtr = uint16(int32(prg.strPtr) + 1)
 19124  		prg.strStart[prg.strPtr] = uint16(int32(prg.areaDelimiter) + 1)
 19125  	}
 19126  	if int32(prg.extDelimiter) == 0 {
 19127  		prg.curExt = /* "" */ 285
 19128  		prg.curName = prg.makeString()
 19129  	} else {
 19130  		prg.curName = prg.strPtr
 19131  		prg.strPtr = uint16(int32(prg.strPtr) + 1)
 19132  		prg.strStart[prg.strPtr] = prg.extDelimiter
 19133  		prg.curExt = prg.makeString()
 19134  	}
 19135  }
 19136  
 19137  // 774.
 19138  
 19139  // tangle:pos ../../mf.web:15640:3:
 19140  
 19141  // Another system-dependent routine is needed to convert three internal
 19142  // \MF\ strings
 19143  // to the |name_of_file| value that is used to open files. The present code
 19144  // allows both lowercase and uppercase letters in the file name.
 19145  // \xref[system dependencies]
 19146  func (prg *prg) packFileName(n, a, e strNumber) {
 19147  	var (
 19148  		k int32       // number of positions filled in |name_of_file|
 19149  		c asciiCode   // character being packed
 19150  		j poolPointer // index into |str_pool|
 19151  	)
 19152  	k = 0
 19153  	for ii := int32(prg.strStart[a]); ii <= int32(prg.strStart[int32(a)+1])-1; ii++ {
 19154  		j = poolPointer(ii)
 19155  		_ = j
 19156  		c = prg.strPool[j]
 19157  		k = k + 1
 19158  		if k <= fileNameSize {
 19159  			prg.nameOfFile[k-1] = prg.xchr[c]
 19160  		}
 19161  	}
 19162  	for ii := int32(prg.strStart[n]); ii <= int32(prg.strStart[int32(n)+1])-1; ii++ {
 19163  		j = poolPointer(ii)
 19164  		_ = j
 19165  		c = prg.strPool[j]
 19166  		k = k + 1
 19167  		if k <= fileNameSize {
 19168  			prg.nameOfFile[k-1] = prg.xchr[c]
 19169  		}
 19170  	}
 19171  	for ii := int32(prg.strStart[e]); ii <= int32(prg.strStart[int32(e)+1])-1; ii++ {
 19172  		j = poolPointer(ii)
 19173  		_ = j
 19174  		c = prg.strPool[j]
 19175  		k = k + 1
 19176  		if k <= fileNameSize {
 19177  			prg.nameOfFile[k-1] = prg.xchr[c]
 19178  		}
 19179  	}
 19180  	if k <= fileNameSize {
 19181  		prg.nameLength = byte(k)
 19182  	} else {
 19183  		prg.nameLength = byte(fileNameSize)
 19184  	}
 19185  	for ii := int32(prg.nameLength) + 1; ii <= fileNameSize; ii++ {
 19186  		k = ii
 19187  		_ = k
 19188  		prg.nameOfFile[k-1] = ' '
 19189  	}
 19190  }
 19191  
 19192  // 778.
 19193  
 19194  // tangle:pos ../../mf.web:15685:3:
 19195  
 19196  // Here is the messy routine that was just mentioned. It sets |name_of_file|
 19197  // from the first |n| characters of |MF_base_default|, followed by
 19198  // |buffer[a..b]|, followed by the last |base_ext_length| characters of
 19199  // |MF_base_default|.
 19200  //
 19201  // We dare not give error messages here, since \MF\ calls this routine before
 19202  // the |error| routine is ready to roll. Instead, we simply drop excess characters,
 19203  // since the error will be detected in another way when a strange file name
 19204  // isn't found.
 19205  // \xref[system dependencies]
 19206  func (prg *prg) packBufferedName(n smallNumber, a, b int32) {
 19207  	var (
 19208  		k int32     // number of positions filled in |name_of_file|
 19209  		c asciiCode // character being packed
 19210  		j int32     // index into |buffer| or |MF_base_default|
 19211  	)
 19212  	if int32(n)+b-a+1+baseExtLength > fileNameSize {
 19213  		b = a + fileNameSize - int32(n) - 1 - baseExtLength
 19214  	}
 19215  	k = 0
 19216  	for ii := int32(1); ii <= int32(n); ii++ {
 19217  		j = ii
 19218  		_ = j
 19219  		c = prg.xord[prg.mfBaseDefault[j-1]]
 19220  		k = k + 1
 19221  		if k <= fileNameSize {
 19222  			prg.nameOfFile[k-1] = prg.xchr[c]
 19223  		}
 19224  	}
 19225  	for ii := a; ii <= b; ii++ {
 19226  		j = ii
 19227  		_ = j
 19228  		c = prg.buffer[j]
 19229  		k = k + 1
 19230  		if k <= fileNameSize {
 19231  			prg.nameOfFile[k-1] = prg.xchr[c]
 19232  		}
 19233  	}
 19234  	for ii := int32(baseDefaultLength - baseExtLength + 1); ii <= baseDefaultLength; ii++ {
 19235  		j = ii
 19236  		_ = j
 19237  		c = prg.xord[prg.mfBaseDefault[j-1]]
 19238  		k = k + 1
 19239  		if k <= fileNameSize {
 19240  			prg.nameOfFile[k-1] = prg.xchr[c]
 19241  		}
 19242  	}
 19243  	if k <= fileNameSize {
 19244  		prg.nameLength = byte(k)
 19245  	} else {
 19246  		prg.nameLength = byte(fileNameSize)
 19247  	}
 19248  	for ii := int32(prg.nameLength) + 1; ii <= fileNameSize; ii++ {
 19249  		k = ii
 19250  		_ = k
 19251  		prg.nameOfFile[k-1] = ' '
 19252  	}
 19253  }
 19254  
 19255  // 780.
 19256  
 19257  // tangle:pos ../../mf.web:15748:3:
 19258  
 19259  // Operating systems often make it possible to determine the exact name (and
 19260  // possible version number) of a file that has been opened. The following routine,
 19261  // which simply makes a \MF\ string from the value of |name_of_file|, should
 19262  // ideally be changed to deduce the full name of file~|f|, which is the file
 19263  // most recently opened, if it is possible to do this in a \PASCAL\ program.
 19264  // \xref[system dependencies]
 19265  //
 19266  // This routine might be called after string memory has overflowed, hence
 19267  // we dare not use `|str_room|'.
 19268  func (prg *prg) makeNameString() (r strNumber) {
 19269  	var (
 19270  		k /* 1..fileNameSize */ byte // index into |name_of_file|
 19271  	)
 19272  	if int32(prg.poolPtr)+int32(prg.nameLength) > poolSize || int32(prg.strPtr) == maxStrings {
 19273  		r = '?'
 19274  	} else {
 19275  		for ii := int32(1); ii <= int32(prg.nameLength); ii++ {
 19276  			k = byte(ii)
 19277  			_ = k
 19278  			prg.strPool[prg.poolPtr] = prg.xord[prg.nameOfFile[k-1]]
 19279  			prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
 19280  		}
 19281  		r = prg.makeString()
 19282  	}
 19283  	return r
 19284  }
 19285  func (prg *prg) aMakeNameString(f alphaFile) (r strNumber) {
 19286  	r = prg.makeNameString()
 19287  	return r
 19288  }
 19289  func (prg *prg) bMakeNameString(f byteFile) (r strNumber) {
 19290  	r = prg.makeNameString()
 19291  	return r
 19292  }
 19293  func (prg *prg) wMakeNameString(f wordFile) (r strNumber) {
 19294  	r = prg.makeNameString()
 19295  	return r
 19296  }
 19297  
 19298  // 781.
 19299  
 19300  // tangle:pos ../../mf.web:15776:3:
 19301  
 19302  // Now let's consider the ``driver''
 19303  // routines by which \MF\ deals with file names
 19304  // in a system-independent manner.  First comes a procedure that looks for a
 19305  // file name in the input by taking the information from the input buffer.
 19306  // (We can't use |get_next|, because the conversion to tokens would
 19307  // destroy necessary information.)
 19308  //
 19309  // This procedure doesn't allow semicolons or percent signs to be part of
 19310  // file names, because of other conventions of \MF. The manual doesn't
 19311  // use semicolons or percents immediately after file names, but some users
 19312  // no doubt will find it natural to do so; therefore system-dependent
 19313  // changes to allow such characters in file names should probably
 19314  // be made with reluctance, and only when an entire file name that
 19315  // includes special characters is ``quoted'' somehow.
 19316  // \xref[system dependencies]
 19317  func (prg *prg) scanFileName() {
 19318  	prg.beginName()
 19319  	for int32(prg.buffer[prg.curInput.locField]) == ' ' {
 19320  		prg.curInput.locField = uint16(int32(prg.curInput.locField) + 1)
 19321  	}
 19322  	for true {
 19323  		if int32(prg.buffer[prg.curInput.locField]) == ';' || int32(prg.buffer[prg.curInput.locField]) == '%' {
 19324  			goto done
 19325  		}
 19326  		if !prg.moreName(prg.buffer[prg.curInput.locField]) {
 19327  			goto done
 19328  		}
 19329  		prg.curInput.locField = uint16(int32(prg.curInput.locField) + 1)
 19330  	}
 19331  
 19332  done:
 19333  	prg.endName()
 19334  }
 19335  
 19336  // 784.
 19337  
 19338  // tangle:pos ../../mf.web:15818:3:
 19339  
 19340  // Here is a routine that manufactures the output file names, assuming that
 19341  // |job_name<>0|. It ignores and changes the current settings of |cur_area|
 19342  // and |cur_ext|.
 19343  func (prg *prg) packJobName(s strNumber) {
 19344  	prg.curArea = /* "" */ 285
 19345  	prg.curExt = s
 19346  	prg.curName = prg.jobName
 19347  	prg.packFileName(prg.curName, prg.curArea, prg.curExt)
 19348  }
 19349  
 19350  // 786.
 19351  
 19352  // tangle:pos ../../mf.web:15838:3:
 19353  
 19354  // If some trouble arises when \MF\ tries to open a file, the following
 19355  // routine calls upon the user to supply another file name. Parameter~|s|
 19356  // is used in the error message to identify the type of file; parameter~|e|
 19357  // is the default extension if none is given. Upon exit from the routine,
 19358  // variables |cur_name|, |cur_area|, |cur_ext|, and |name_of_file| are
 19359  // ready for another attempt at file opening.
 19360  func (prg *prg) promptFileName(s, e strNumber) {
 19361  	var (
 19362  		k /* 0..bufSize */ uint16 // index into |buffer|
 19363  	)
 19364  	if int32(prg.interaction) == scrollMode {
 19365  	}
 19366  	if int32(s) == 743 {
 19367  		if int32(prg.interaction) == errorStopMode {
 19368  		}
 19369  		prg.printNl(strNumber( /* "! " */ 261))
 19370  		prg.print( /* "I can't find file `" */ 744) /* \xref[!\relax]  */
 19371  	} else {
 19372  		if int32(prg.interaction) == errorStopMode {
 19373  		}
 19374  		prg.printNl(strNumber( /* "! " */ 261))
 19375  		prg.print( /* "I can't write on file `" */ 745) /* \xref[!\relax]  */
 19376  	}
 19377  	// \xref[I can't write on file x]
 19378  	prg.printFileName(int32(prg.curName), int32(prg.curArea), int32(prg.curExt))
 19379  	prg.print( /* "'." */ 746)
 19380  	if int32(e) == 747 {
 19381  		prg.showContext()
 19382  	}
 19383  	prg.printNl(strNumber( /* "Please type another " */ 748))
 19384  	prg.print(int32(s))
 19385  	// \xref[Please type...]
 19386  	if int32(prg.interaction) < scrollMode {
 19387  		prg.fatalError(strNumber( /* "*** (job aborted, file error in nonstop mode)" */ 749))
 19388  	}
 19389  	// \xref[job aborted, file error...]
 19390  	{
 19391  		prg.print( /* ": " */ 750)
 19392  		prg.termInput()
 19393  	}
 19394  	// Scan file name in the buffer
 19395  	{
 19396  		prg.beginName()
 19397  		k = prg.first
 19398  		for int32(prg.buffer[k]) == ' ' && int32(k) < int32(prg.last) {
 19399  			k = uint16(int32(k) + 1)
 19400  		}
 19401  		for true {
 19402  			if int32(k) == int32(prg.last) {
 19403  				goto done
 19404  			}
 19405  			if !prg.moreName(prg.buffer[k]) {
 19406  				goto done
 19407  			}
 19408  			k = uint16(int32(k) + 1)
 19409  		}
 19410  
 19411  	done:
 19412  		prg.endName()
 19413  	}
 19414  	if int32(prg.curExt) == 285 {
 19415  		prg.curExt = e
 19416  	}
 19417  	prg.packFileName(prg.curName, prg.curArea, prg.curExt)
 19418  } // \2
 19419  
 19420  func (prg *prg) openLogFile() {
 19421  	var (
 19422  		oldSetting/* 0..maxSelector */ byte          // previous |selector| setting
 19423  		k/* 0..bufSize */ uint16                     // index into |months| and |buffer|
 19424  		l/* 0..bufSize */ uint16                     // end of first input line
 19425  		months                              [36]char // abbreviations of month names
 19426  	)
 19427  	oldSetting = prg.selector
 19428  	if int32(prg.jobName) == 0 {
 19429  		prg.jobName = /* "mfput" */ 751
 19430  	}
 19431  	// \xref[mfput]
 19432  	prg.packJobName(strNumber( /* ".log" */ 752))
 19433  	for !prg.aOpenOut(prg.logFile) {
 19434  		// Try to get a different log file name
 19435  		prg.selector = byte(termOnly)
 19436  		prg.promptFileName(strNumber( /* "transcript file name" */ 754), strNumber( /* ".log" */ 752))
 19437  	}
 19438  	prg.logName = prg.aMakeNameString(prg.logFile)
 19439  	prg.selector = byte(logOnly)
 19440  	prg.logOpened = true
 19441  
 19442  	// Print the banner line, including the date and time
 19443  	{
 19444  		prg.logFile.Write("This is METAFONT, Version 2.71828182 (TRAP)")
 19445  		prg.slowPrint(int32(prg.baseIdent))
 19446  		prg.print( /* "  " */ 755)
 19447  		prg.printInt(prg.sysDay)
 19448  		prg.printChar(asciiCode(' '))
 19449  		strcopy(months[:], "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC")
 19450  		for ii := 3*prg.sysMonth - 2; ii <= 3*prg.sysMonth; ii++ {
 19451  			k = uint16(ii)
 19452  			_ = k
 19453  			prg.logFile.Write(string(rune(months[k-1])))
 19454  		}
 19455  		prg.printChar(asciiCode(' '))
 19456  		prg.printInt(prg.sysYear)
 19457  		prg.printChar(asciiCode(' '))
 19458  		prg.printDd(prg.sysTime / 60)
 19459  		prg.printChar(asciiCode(':'))
 19460  		prg.printDd(prg.sysTime % 60)
 19461  	}
 19462  	prg.inputStack[prg.inputPtr] = prg.curInput // make sure bottom level is in memory
 19463  	prg.printNl(strNumber( /* "**" */ 753))
 19464  	// \xref[**]
 19465  	l = uint16(int32(prg.inputStack[0].limitField) - 1) // last position of first line
 19466  	for ii := int32(1); ii <= int32(l); ii++ {
 19467  		k = uint16(ii)
 19468  		_ = k
 19469  		prg.print(int32(prg.buffer[k]))
 19470  	}
 19471  	prg.printLn()                              // now the transcript file contains the first line of input
 19472  	prg.selector = byte(int32(oldSetting) + 2) // |log_only| or |term_and_log|
 19473  } // \2
 19474  func (prg *prg) startInput() {
 19475  	for int32(prg.curInput.indexField) > maxInOpen && int32(prg.curInput.locField) == memMin {
 19476  		prg.endTokenList()
 19477  	}
 19478  	if int32(prg.curInput.indexField) > maxInOpen {
 19479  		{
 19480  			if int32(prg.interaction) == errorStopMode {
 19481  			}
 19482  			prg.printNl(strNumber( /* "! " */ 261))
 19483  			prg.print( /* "File names can't appear within macros" */ 757) /* \xref[!\relax]  */
 19484  		}
 19485  		// \xref[File names can't...]
 19486  		{
 19487  			prg.helpPtr = 3
 19488  			prg.helpLine[2] = /* "Sorry...I've converted what follows to tokens," */ 758
 19489  			prg.helpLine[1] = /* "possibly garbaging the name you gave." */ 759
 19490  			prg.helpLine[0] = /* "Please delete the tokens and insert the name again." */ 760
 19491  		}
 19492  
 19493  		prg.error1()
 19494  	}
 19495  	if int32(prg.curInput.indexField) <= maxInOpen {
 19496  		prg.scanFileName()
 19497  	} else {
 19498  		prg.curName = /* "" */ 285
 19499  		prg.curExt = /* "" */ 285
 19500  		prg.curArea = /* "" */ 285
 19501  	}
 19502  	if int32(prg.curExt) == 285 {
 19503  		prg.curExt = /* ".mf" */ 747
 19504  	}
 19505  	prg.packFileName(prg.curName, prg.curArea, prg.curExt)
 19506  	for true {
 19507  		prg.beginFileReading() // set up |cur_file| and new level of input
 19508  		if prg.aOpenIn(prg.inputFile[prg.curInput.indexField-1]) {
 19509  			goto done
 19510  		}
 19511  		if int32(prg.curArea) == 285 {
 19512  			prg.packFileName(prg.curName, strNumber( /* "MFinputs:" */ 741), prg.curExt)
 19513  			if prg.aOpenIn(prg.inputFile[prg.curInput.indexField-1]) {
 19514  				goto done
 19515  			}
 19516  		}
 19517  		prg.endFileReading() // remove the level that didn't work
 19518  		prg.promptFileName(strNumber( /* "input file name" */ 743), strNumber( /* ".mf" */ 747))
 19519  	}
 19520  
 19521  done:
 19522  	prg.curInput.nameField = prg.aMakeNameString(prg.inputFile[prg.curInput.indexField-1])
 19523  	prg.strRef[prg.curName] = byte(maxStrRef)
 19524  	if int32(prg.jobName) == 0 {
 19525  		prg.jobName = prg.curName
 19526  		prg.openLogFile()
 19527  	} // |open_log_file| doesn't |show_context|, so |limit|
 19528  	//     and |loc| needn't be set to meaningful values yet
 19529  
 19530  	if int32(prg.termOffset)+(int32(prg.strStart[int32(prg.curInput.nameField)+1])-int32(prg.strStart[prg.curInput.nameField])) > maxPrintLine-2 {
 19531  		prg.printLn()
 19532  	} else if int32(prg.termOffset) > 0 || int32(prg.fileOffset) > 0 {
 19533  		prg.printChar(asciiCode(' '))
 19534  	}
 19535  	prg.printChar(asciiCode('('))
 19536  	prg.openParens = byte(int32(prg.openParens) + 1)
 19537  	prg.slowPrint(int32(prg.curInput.nameField))
 19538  	if int32(prg.curInput.nameField) == int32(prg.strPtr)-1 {
 19539  		prg.flushString(prg.curInput.nameField)
 19540  		prg.curInput.nameField = prg.curName
 19541  	}
 19542  
 19543  	// Read the first line of the new file
 19544  	{
 19545  		prg.line = 1
 19546  		if prg.inputLn(prg.inputFile[prg.curInput.indexField-1], false) {
 19547  		}
 19548  		prg.firmUpTheLine()
 19549  		prg.buffer[prg.curInput.limitField] = '%'
 19550  		prg.first = uint16(int32(prg.curInput.limitField) + 1)
 19551  		prg.curInput.locField = prg.curInput.startField
 19552  	}
 19553  }
 19554  
 19555  // 798.
 19556  
 19557  // tangle:pos ../../mf.web:16035:3:
 19558  
 19559  // Many different kinds of expressions are possible, so it is wise to have
 19560  // precise descriptions of what |cur_type| and |cur_exp| mean in all cases:
 19561  //
 19562  // \smallskip\hang
 19563  // |cur_type=vacuous| means that this expression didn't turn out to have a
 19564  // value at all, because it arose from a \&[begingroup]$\,\ldots\,$\&[endgroup]
 19565  // construction in which there was no expression before the \&[endgroup].
 19566  // In this case |cur_exp| has some irrelevant value.
 19567  //
 19568  // \smallskip\hang
 19569  // |cur_type=boolean_type| means that |cur_exp| is either |true_code|
 19570  // or |false_code|.
 19571  //
 19572  // \smallskip\hang
 19573  // |cur_type=unknown_boolean| means that |cur_exp| points to a capsule
 19574  // node that is in
 19575  // a ring of equivalent booleans whose value has not yet been defined.
 19576  //
 19577  // \smallskip\hang
 19578  // |cur_type=string_type| means that |cur_exp| is a string number (i.e., an
 19579  // integer in the range |0<=cur_exp<str_ptr|). That string's reference count
 19580  // includes this particular reference.
 19581  //
 19582  // \smallskip\hang
 19583  // |cur_type=unknown_string| means that |cur_exp| points to a capsule
 19584  // node that is in
 19585  // a ring of equivalent strings whose value has not yet been defined.
 19586  //
 19587  // \smallskip\hang
 19588  // |cur_type=pen_type| means that |cur_exp| points to a pen header node. This
 19589  // node contains a reference count, which takes account of this particular
 19590  // reference.
 19591  //
 19592  // \smallskip\hang
 19593  // |cur_type=unknown_pen| means that |cur_exp| points to a capsule
 19594  // node that is in
 19595  // a ring of equivalent pens whose value has not yet been defined.
 19596  //
 19597  // \smallskip\hang
 19598  // |cur_type=future_pen| means that |cur_exp| points to a knot list that
 19599  // should eventually be made into a pen. Nobody else points to this particular
 19600  // knot list. The |future_pen| option occurs only as an output of |scan_primary|
 19601  // and |scan_secondary|, not as an output of |scan_tertiary| or |scan_expression|.
 19602  //
 19603  // \smallskip\hang
 19604  // |cur_type=path_type| means that |cur_exp| points to the first node of
 19605  // a path; nobody else points to this particular path. The control points of
 19606  // the path will have been chosen.
 19607  //
 19608  // \smallskip\hang
 19609  // |cur_type=unknown_path| means that |cur_exp| points to a capsule
 19610  // node that is in
 19611  // a ring of equivalent paths whose value has not yet been defined.
 19612  //
 19613  // \smallskip\hang
 19614  // |cur_type=picture_type| means that |cur_exp| points to an edges header node.
 19615  // Nobody else points to this particular set of edges.
 19616  //
 19617  // \smallskip\hang
 19618  // |cur_type=unknown_picture| means that |cur_exp| points to a capsule
 19619  // node that is in
 19620  // a ring of equivalent pictures whose value has not yet been defined.
 19621  //
 19622  // \smallskip\hang
 19623  // |cur_type=transform_type| means that |cur_exp| points to a |transform_type|
 19624  // capsule node. The |value| part of this capsule
 19625  // points to a transform node that contains six numeric values,
 19626  // each of which is |independent|, |dependent|, |proto_dependent|, or |known|.
 19627  //
 19628  // \smallskip\hang
 19629  // |cur_type=pair_type| means that |cur_exp| points to a capsule
 19630  // node whose type is |pair_type|. The |value| part of this capsule
 19631  // points to a pair node that contains two numeric values,
 19632  // each of which is |independent|, |dependent|, |proto_dependent|, or |known|.
 19633  //
 19634  // \smallskip\hang
 19635  // |cur_type=known| means that |cur_exp| is a |scaled| value.
 19636  //
 19637  // \smallskip\hang
 19638  // |cur_type=dependent| means that |cur_exp| points to a capsule node whose type
 19639  // is |dependent|. The |dep_list| field in this capsule points to the associated
 19640  // dependency list.
 19641  //
 19642  // \smallskip\hang
 19643  // |cur_type=proto_dependent| means that |cur_exp| points to a |proto_dependent|
 19644  // capsule node. The |dep_list| field in this capsule
 19645  // points to the associated dependency list.
 19646  //
 19647  // \smallskip\hang
 19648  // |cur_type=independent| means that |cur_exp| points to a capsule node
 19649  // whose type is |independent|. This somewhat unusual case can arise, for
 19650  // example, in the expression
 19651  // `$x+\&[begingroup]\penalty0\,\&[string]\,x; 0\,\&[endgroup]$'.
 19652  //
 19653  // \smallskip\hang
 19654  // |cur_type=token_list| means that |cur_exp| points to a linked list of
 19655  // tokens.
 19656  //
 19657  // \smallskip\noindent
 19658  // The possible settings of |cur_type| have been listed here in increasing
 19659  // numerical order. Notice that |cur_type| will never be |numeric_type| or
 19660  // |suffixed_macro| or |unsuffixed_macro|, although variables of those types
 19661  // are allowed.  Conversely, \MF\ has no variables of type |vacuous| or
 19662  // |token_list|.
 19663  
 19664  // 824.
 19665  
 19666  // tangle:pos ../../mf.web:16652:3:
 19667  
 19668  // Errors at the beginning of expressions are flagged by |bad_exp|.
 19669  func (prg *prg) badExp(s strNumber) {
 19670  	var (
 19671  		saveFlag /* 0..maxCommandCode */ byte
 19672  	)
 19673  	{
 19674  		if int32(prg.interaction) == errorStopMode {
 19675  		}
 19676  		prg.printNl(strNumber( /* "! " */ 261))
 19677  		prg.print(int32(s)) /* \xref[!\relax]  */
 19678  	}
 19679  	prg.print( /* " expression can't begin with `" */ 770)
 19680  	prg.printCmdMod(int32(prg.curCmd), prg.curMod)
 19681  	prg.printChar(asciiCode('\''))
 19682  	{
 19683  		prg.helpPtr = 4
 19684  		prg.helpLine[3] = /* "I'm afraid I need some sort of value in order to continue," */ 771
 19685  		prg.helpLine[2] = /* "so I've tentatively inserted `0'. You may want to" */ 772
 19686  		prg.helpLine[1] = /* "delete this zero and insert something else;" */ 773
 19687  		prg.helpLine[0] = /* "see Chapter 27 of The METAFONTbook for an example." */ 774
 19688  	}
 19689  	// \xref[METAFONTbook][\sl The [\logos METAFONT\/]book]
 19690  	prg.backInput()
 19691  	prg.curSym = 0
 19692  	prg.curCmd = byte(numericToken)
 19693  	prg.curMod = 0
 19694  	prg.insError()
 19695  
 19696  	saveFlag = prg.varFlag
 19697  	prg.varFlag = 0
 19698  	prg.getXNext()
 19699  	prg.varFlag = saveFlag
 19700  }
 19701  
 19702  // 827.
 19703  
 19704  // tangle:pos ../../mf.web:16681:3:
 19705  
 19706  // The |stash_in| subroutine puts the current (numeric) expression into a field
 19707  // within a ``big node.''
 19708  func (prg *prg) stashIn(p halfword) {
 19709  	var (
 19710  		q halfword // temporary register
 19711  	)
 19712  	*(*prg.mem[p].hh()).b0() = prg.curType
 19713  	if int32(prg.curType) == known {
 19714  		*prg.mem[int32(p)+1].int() = prg.curExp
 19715  	} else {
 19716  		if int32(prg.curType) == independent {
 19717  			q = prg.singleDependency(halfword(prg.curExp))
 19718  			if int32(q) == int32(prg.depFinal) {
 19719  				*(*prg.mem[p].hh()).b0() = byte(known)
 19720  				*prg.mem[int32(p)+1].int() = 0
 19721  				prg.freeNode(q, halfword(depNodeSize))
 19722  			} else {
 19723  				*(*prg.mem[p].hh()).b0() = byte(dependent)
 19724  				prg.newDep(p, q)
 19725  			}
 19726  			prg.recycleValue(halfword(prg.curExp))
 19727  		} else {
 19728  			prg.mem[int32(p)+1] = prg.mem[prg.curExp+1]
 19729  			// |dep_list(p):=dep_list(cur_exp)| and |prev_dep(p):=prev_dep(cur_exp)|
 19730  			*(*prg.mem[*(*prg.mem[int32(p)+1].hh()).lh()].hh()).rh() = p
 19731  		}
 19732  		prg.freeNode(halfword(prg.curExp), halfword(valueNodeSize))
 19733  	}
 19734  	prg.curType = byte(vacuous)
 19735  }
 19736  
 19737  // 828.
 19738  
 19739  // tangle:pos ../../mf.web:16699:3:
 19740  
 19741  // In rare cases the current expression can become |independent|. There
 19742  // may be many dependency lists pointing to such an independent capsule,
 19743  // so we can't simply move it into place within a big node. Instead,
 19744  // we copy it, then recycle it.
 19745  
 19746  // 842.
 19747  
 19748  // tangle:pos ../../mf.web:16865:3:
 19749  
 19750  // The most difficult part of |scan_primary| has been saved for last, since
 19751  // it was necessary to build up some confidence first. We can now face the task
 19752  // of scanning a variable.
 19753  //
 19754  // As we scan a variable, we build a token list containing the relevant
 19755  // names and subscript values, simultaneously following along in the
 19756  // ``collective'' structure to see if we are actually dealing with a macro
 19757  // instead of a value.
 19758  //
 19759  // The local variables |pre_head| and |post_head| will point to the beginning
 19760  // of the prefix and suffix lists; |tail| will point to the end of the list
 19761  // that is currently growing.
 19762  //
 19763  // Another local variable, |tt|, contains partial information about the
 19764  // declared type of the variable-so-far. If |tt>=unsuffixed_macro|, the
 19765  // relation |tt=type(q)| will always hold. If |tt=undefined|, the routine
 19766  // doesn't bother to update its information about type. And if
 19767  // |undefined<tt<unsuffixed_macro|, the precise value of |tt| isn't critical.
 19768  
 19769  // 848.
 19770  
 19771  // tangle:pos ../../mf.web:16939:3:
 19772  
 19773  // Here's a routine that puts the current expression back to be read again.
 19774  func (prg *prg) backExpr() {
 19775  	var (
 19776  		p halfword // capsule token
 19777  	)
 19778  	p = prg.stashCurExp()
 19779  	*(*prg.mem[p].hh()).rh() = uint16(memMin)
 19780  	prg.beginTokenList(p, quarterword(backedUp))
 19781  }
 19782  
 19783  // 849.
 19784  
 19785  // tangle:pos ../../mf.web:16946:3:
 19786  
 19787  // Unknown subscripts lead to the following error message.
 19788  func (prg *prg) badSubscript() {
 19789  	prg.dispErr(halfword(memMin), strNumber( /* "Improper subscript has been replaced by zero" */ 786))
 19790  	// \xref[Improper subscript...]
 19791  	{
 19792  		prg.helpPtr = 3
 19793  		prg.helpLine[2] = /* "A bracketed subscript must have a known numeric value;" */ 787
 19794  		prg.helpLine[1] = /* "unfortunately, what I found was the value that appears just" */ 788
 19795  		prg.helpLine[0] = /* "above this error message. So I'll try a zero subscript." */ 789
 19796  	}
 19797  	prg.flushError(scaled(0))
 19798  }
 19799  
 19800  // 851.
 19801  
 19802  // tangle:pos ../../mf.web:16982:3:
 19803  
 19804  // How do things stand now? Well, we have scanned an entire variable name,
 19805  // including possible subscripts and/or attributes; |cur_cmd|, |cur_mod|, and
 19806  // |cur_sym| represent the token that follows. If |post_head=null|, a
 19807  // token list for this variable name starts at |link(pre_head)|, with all
 19808  // subscripts evaluated. But if |post_head<>null|, the variable turned out
 19809  // to be a suffixed macro; |pre_head| is the head of the prefix list, while
 19810  // |post_head| is the head of a token list containing both `\.[\AT!]' and
 19811  // the suffix.
 19812  //
 19813  // Our immediate problem is to see if this variable still exists. (Variable
 19814  // structures can change drastically whenever we call |get_x_next|; users
 19815  // aren't supposed to do this, but the fact that it is possible means that
 19816  // we must be cautious.)
 19817  //
 19818  // The following procedure prints an error message when a variable
 19819  // unexpectedly disappears. Its help message isn't quite right for
 19820  // our present purposes, but we'll be able to fix that up.
 19821  func (prg *prg) obliterated(q halfword) {
 19822  	{
 19823  		if int32(prg.interaction) == errorStopMode {
 19824  		}
 19825  		prg.printNl(strNumber( /* "! " */ 261))
 19826  		prg.print( /* "Variable " */ 790) /* \xref[!\relax]  */
 19827  	}
 19828  	prg.showTokenList(int32(q), memMin, 1000, 0)
 19829  	prg.print( /* " has been obliterated" */ 791)
 19830  	// \xref[Variable...obliterated]
 19831  	{
 19832  		prg.helpPtr = 5
 19833  		prg.helpLine[4] = /* "It seems you did a nasty thing---probably by accident," */ 792
 19834  		prg.helpLine[3] = /* "but nevertheless you nearly hornswoggled me..." */ 793
 19835  		prg.helpLine[2] = /* "While I was evaluating the right-hand side of this" */ 794
 19836  		prg.helpLine[1] = /* "command, something happened, and the left-hand side" */ 795
 19837  		prg.helpLine[0] = /* "is no longer a variable! So I won't change anything." */ 796
 19838  	}
 19839  }
 19840  
 19841  // 863.
 19842  
 19843  // tangle:pos ../../mf.web:17227:3:
 19844  
 19845  // The following procedure calls a macro that has two parameters,
 19846  // |p| and |cur_exp|.
 19847  func (prg *prg) binaryMac(p, c, n halfword) {
 19848  	var (
 19849  		q, r1 halfword // nodes in the parameter list
 19850  	)
 19851  	q = prg.getAvail()
 19852  	r1 = prg.getAvail()
 19853  	*(*prg.mem[q].hh()).rh() = r1
 19854  
 19855  	*(*prg.mem[q].hh()).lh() = p
 19856  	*(*prg.mem[r1].hh()).lh() = prg.stashCurExp()
 19857  
 19858  	prg.macroCall(c, q, n)
 19859  }
 19860  
 19861  // 865.
 19862  
 19863  // tangle:pos ../../mf.web:17266:3:
 19864  
 19865  // A |future_pen| becomes a full-fledged pen here.
 19866  func (prg *prg) materializePen() {
 19867  	var (
 19868  		aMinusB, aPlusB, majorAxis, minorAxis scaled   // ellipse variables
 19869  		theta                                 angle    // amount by which the ellipse has been rotated
 19870  		p                                     halfword // path traverser
 19871  		q                                     halfword // the knot list to be made into a pen
 19872  	)
 19873  	q = uint16(prg.curExp)
 19874  	if int32(*(*prg.mem[q].hh()).b0()) == endpoint {
 19875  		{
 19876  			if int32(prg.interaction) == errorStopMode {
 19877  			}
 19878  			prg.printNl(strNumber( /* "! " */ 261))
 19879  			prg.print( /* "Pen path must be a cycle" */ 806) /* \xref[!\relax]  */
 19880  		}
 19881  		// \xref[Pen path must be a cycle]
 19882  		{
 19883  			prg.helpPtr = 2
 19884  			prg.helpLine[1] = /* "I can't make a pen from the given path." */ 807
 19885  			prg.helpLine[0] = /* "So I've replaced it by the trivial path `(0,0)..cycle'." */ 575
 19886  		}
 19887  		prg.putGetError()
 19888  		prg.curExp = memMin + 3
 19889  		goto commonEnding
 19890  	} else if int32(*(*prg.mem[q].hh()).b0()) == open {
 19891  		prg.tx = *prg.mem[int32(q)+1].int()
 19892  		prg.ty = *prg.mem[int32(q)+2].int()
 19893  		prg.txx = *prg.mem[int32(q)+3].int() - prg.tx
 19894  		prg.tyx = *prg.mem[int32(q)+4].int() - prg.ty
 19895  		prg.txy = *prg.mem[int32(q)+5].int() - prg.tx
 19896  		prg.tyy = *prg.mem[int32(q)+6].int() - prg.ty
 19897  		aMinusB = prg.pythAdd(prg.txx-prg.tyy, prg.tyx+prg.txy)
 19898  		aPlusB = prg.pythAdd(prg.txx+prg.tyy, prg.tyx-prg.txy)
 19899  		majorAxis = (aMinusB + aPlusB) / 2
 19900  		minorAxis = abs(aPlusB-aMinusB) / 2
 19901  		if majorAxis == minorAxis {
 19902  			theta = 0
 19903  		} else {
 19904  			theta = (prg.nArg(prg.txx-prg.tyy, prg.tyx+prg.txy) + prg.nArg(prg.txx+prg.tyy, prg.tyx-prg.txy)) / 2
 19905  		}
 19906  		prg.freeNode(q, halfword(knotNodeSize))
 19907  		q = prg.makeEllipse(majorAxis, minorAxis, theta)
 19908  		if prg.tx != 0 || prg.ty != 0 {
 19909  			p = q
 19910  			for {
 19911  				*prg.mem[int32(p)+1].int() = *prg.mem[int32(p)+1].int() + prg.tx
 19912  				*prg.mem[int32(p)+2].int() = *prg.mem[int32(p)+2].int() + prg.ty
 19913  				p = *(*prg.mem[p].hh()).rh()
 19914  				if int32(p) == int32(q) {
 19915  					break
 19916  				}
 19917  			}
 19918  		}
 19919  	}
 19920  	prg.curExp = int32(prg.makePen(q))
 19921  
 19922  commonEnding:
 19923  	prg.tossKnotList(q)
 19924  	prg.curType = byte(penType)
 19925  }
 19926  
 19927  // 871.
 19928  
 19929  // tangle:pos ../../mf.web:17413:3:
 19930  
 19931  // A pair of numeric values is changed into a knot node for a one-point path
 19932  // when \MF\ discovers that the pair is part of a path.
 19933  // \4
 19934  // Declare the procedure called |known_pair|
 19935  func (prg *prg) knownPair() {
 19936  	var (
 19937  		p halfword // the pair node
 19938  	)
 19939  	if int32(prg.curType) != pairType {
 19940  		prg.dispErr(halfword(memMin), strNumber( /* "Undefined coordinates have been replaced by (0,0)" */ 809))
 19941  		// \xref[Undefined coordinates...]
 19942  		{
 19943  			prg.helpPtr = 5
 19944  			prg.helpLine[4] = /* "I need x and y numbers for this part of the path." */ 810
 19945  			prg.helpLine[3] = /* "The value I found (see above) was no good;" */ 811
 19946  			prg.helpLine[2] = /* "so I'll try to keep going by using zero instead." */ 812
 19947  			prg.helpLine[1] = /* "(Chapter 27 of The METAFONTbook explains that" */ 813
 19948  			prg.helpLine[0] = /* "you might want to type `I ???' now.)" */ 814
 19949  		}
 19950  		prg.putGetFlushError(scaled(0))
 19951  		prg.curX = 0
 19952  		prg.curY = 0
 19953  	} else {
 19954  		p = uint16(*prg.mem[prg.curExp+1].int())
 19955  
 19956  		// Make sure that both |x| and |y| parts of |p| are known; copy them into |cur_x| and |cur_y|
 19957  		if int32(*(*prg.mem[p].hh()).b0()) == known {
 19958  			prg.curX = *prg.mem[int32(p)+1].int()
 19959  		} else {
 19960  			prg.dispErr(p, strNumber(
 19961  				/* "Undefined x coordinate has been replaced by 0" */ 815))
 19962  			// \xref[Undefined coordinates...]
 19963  			{
 19964  				prg.helpPtr = 5
 19965  				prg.helpLine[4] = /* "I need a `known' x value for this part of the path." */ 816
 19966  				prg.helpLine[3] = /* "The value I found (see above) was no good;" */ 811
 19967  				prg.helpLine[2] = /* "so I'll try to keep going by using zero instead." */ 812
 19968  				prg.helpLine[1] = /* "(Chapter 27 of The METAFONTbook explains that" */ 813
 19969  				prg.helpLine[0] = /* "you might want to type `I ???' now.)" */ 814
 19970  			}
 19971  			prg.putGetError()
 19972  			prg.recycleValue(p)
 19973  			prg.curX = 0
 19974  		}
 19975  		if int32(*(*prg.mem[int32(p)+2].hh()).b0()) == known {
 19976  			prg.curY = *prg.mem[int32(p)+2+1].int()
 19977  		} else {
 19978  			prg.dispErr(halfword(int32(p)+2), strNumber(
 19979  				/* "Undefined y coordinate has been replaced by 0" */ 817))
 19980  			{
 19981  				prg.helpPtr = 5
 19982  				prg.helpLine[4] = /* "I need a `known' y value for this part of the path." */ 818
 19983  				prg.helpLine[3] = /* "The value I found (see above) was no good;" */ 811
 19984  				prg.helpLine[2] = /* "so I'll try to keep going by using zero instead." */ 812
 19985  				prg.helpLine[1] = /* "(Chapter 27 of The METAFONTbook explains that" */ 813
 19986  				prg.helpLine[0] = /* "you might want to type `I ???' now.)" */ 814
 19987  			}
 19988  			prg.putGetError()
 19989  			prg.recycleValue(halfword(int32(p) + 2))
 19990  			prg.curY = 0
 19991  		}
 19992  		prg.flushCurExp(scaled(0))
 19993  	}
 19994  }
 19995  
 19996  func (prg *prg) newKnot() (r halfword) { // convert a pair to a knot with two endpoints
 19997  	var (
 19998  		q halfword // the new node
 19999  	)
 20000  	q = prg.getNode(knotNodeSize)
 20001  	*(*prg.mem[q].hh()).b0() = byte(endpoint)
 20002  	*(*prg.mem[q].hh()).b1() = byte(endpoint)
 20003  	*(*prg.mem[q].hh()).rh() = q
 20004  
 20005  	prg.knownPair()
 20006  	*prg.mem[int32(q)+1].int() = prg.curX
 20007  	*prg.mem[int32(q)+2].int() = prg.curY
 20008  	r = q
 20009  	return r
 20010  }
 20011  
 20012  // 875.
 20013  
 20014  // tangle:pos ../../mf.web:17490:3:
 20015  
 20016  // The |scan_direction| subroutine looks at the directional information
 20017  // that is enclosed in braces, and also scans ahead to the following character.
 20018  // A type code is returned, either |open| (if the direction was $(0,0)$),
 20019  // or |curl| (if the direction was a curl of known value |cur_exp|), or
 20020  // |given| (if the direction is given by the |angle| value that now
 20021  // appears in |cur_exp|).
 20022  //
 20023  // There's nothing difficult about this subroutine, but the program is rather
 20024  // lengthy because a variety of potential errors need to be nipped in the bud.
 20025  func (prg *prg) scanDirection() (r smallNumber) {
 20026  	var (
 20027  		t/* given..open */ byte        // the type of information found
 20028  		x                       scaled // an |x| coordinate
 20029  	)
 20030  	prg.getXNext()
 20031  	if int32(prg.curCmd) == curlCommand {
 20032  		prg.getXNext()
 20033  		prg.scanExpression()
 20034  		if int32(prg.curType) != known || prg.curExp < 0 {
 20035  			prg.dispErr(halfword(memMin), strNumber( /* "Improper curl has been replaced by 1" */ 821))
 20036  			// \xref[Improper curl]
 20037  			{
 20038  				prg.helpPtr = 1
 20039  				prg.helpLine[0] = /* "A curl must be a known, nonnegative number." */ 822
 20040  			}
 20041  			prg.putGetFlushError(scaled(0200000))
 20042  		}
 20043  		t = byte(curl)
 20044  	} else {
 20045  		// Scan a given direction
 20046  		prg.scanExpression()
 20047  		if int32(prg.curType) > pairType {
 20048  			if int32(prg.curType) != known {
 20049  				prg.dispErr(halfword(memMin), strNumber( /* "Undefined x coordinate has been replaced by 0" */ 815))
 20050  				// \xref[Undefined coordinates...]
 20051  				{
 20052  					prg.helpPtr = 5
 20053  					prg.helpLine[4] = /* "I need a `known' x value for this part of the path." */ 816
 20054  					prg.helpLine[3] = /* "The value I found (see above) was no good;" */ 811
 20055  					prg.helpLine[2] = /* "so I'll try to keep going by using zero instead." */ 812
 20056  					prg.helpLine[1] = /* "(Chapter 27 of The METAFONTbook explains that" */ 813
 20057  					prg.helpLine[0] = /* "you might want to type `I ???' now.)" */ 814
 20058  				}
 20059  				prg.putGetFlushError(scaled(0))
 20060  			}
 20061  			x = prg.curExp
 20062  			if int32(prg.curCmd) != comma {
 20063  				prg.missingErr(strNumber(','))
 20064  
 20065  				// \xref[Missing `,']
 20066  				{
 20067  					prg.helpPtr = 2
 20068  					prg.helpLine[1] = /* "I've got the x coordinate of a path direction;" */ 823
 20069  					prg.helpLine[0] = /* "will look for the y coordinate next." */ 824
 20070  				}
 20071  				prg.backError()
 20072  			}
 20073  			prg.getXNext()
 20074  			prg.scanExpression()
 20075  			if int32(prg.curType) != known {
 20076  				prg.dispErr(halfword(memMin), strNumber( /* "Undefined y coordinate has been replaced by 0" */ 817))
 20077  				{
 20078  					prg.helpPtr = 5
 20079  					prg.helpLine[4] = /* "I need a `known' y value for this part of the path." */ 818
 20080  					prg.helpLine[3] = /* "The value I found (see above) was no good;" */ 811
 20081  					prg.helpLine[2] = /* "so I'll try to keep going by using zero instead." */ 812
 20082  					prg.helpLine[1] = /* "(Chapter 27 of The METAFONTbook explains that" */ 813
 20083  					prg.helpLine[0] = /* "you might want to type `I ???' now.)" */ 814
 20084  				}
 20085  				prg.putGetFlushError(scaled(0))
 20086  			}
 20087  			prg.curY = prg.curExp
 20088  			prg.curX = x
 20089  		} else {
 20090  			prg.knownPair()
 20091  		}
 20092  		if prg.curX == 0 && prg.curY == 0 {
 20093  			t = byte(open)
 20094  		} else {
 20095  			t = byte(given)
 20096  			prg.curExp = prg.nArg(prg.curX, prg.curY)
 20097  		}
 20098  	}
 20099  	if int32(prg.curCmd) != rightBrace {
 20100  		prg.missingErr(strNumber('}'))
 20101  
 20102  		// \xref[Missing `\char`\]']
 20103  		{
 20104  			prg.helpPtr = 3
 20105  			prg.helpLine[2] = /* "I've scanned a direction spec for part of a path," */ 819
 20106  			prg.helpLine[1] = /* "so a right brace should have come next." */ 820
 20107  			prg.helpLine[0] = /* "I shall pretend that one was there." */ 697
 20108  		}
 20109  
 20110  		prg.backError()
 20111  	}
 20112  	prg.getXNext()
 20113  	r = t
 20114  	return r
 20115  }
 20116  
 20117  // 895.
 20118  
 20119  // tangle:pos ../../mf.web:17914:3:
 20120  
 20121  // OK, let's look at the simplest \\[do] procedure first.
 20122  func (prg *prg) doNullary(c quarterword) {
 20123  	var (
 20124  		k int32 // all-purpose loop index
 20125  	)
 20126  	{
 20127  		if prg.arithError {
 20128  			prg.clearArith()
 20129  		}
 20130  	}
 20131  	if prg.internal[tracingCommands-1] > 0400000 {
 20132  		prg.showCmdMod(nullary, int32(c))
 20133  	}
 20134  	switch c {
 20135  	case trueCode, falseCode:
 20136  		prg.curType = byte(booleanType)
 20137  		prg.curExp = int32(c)
 20138  
 20139  	case nullPictureCode:
 20140  		prg.curType = byte(pictureType)
 20141  		prg.curExp = int32(prg.getNode(edgeHeaderSize))
 20142  		prg.initEdges(halfword(prg.curExp))
 20143  
 20144  	case nullPenCode:
 20145  		prg.curType = byte(penType)
 20146  		prg.curExp = memMin + 3
 20147  
 20148  	case normalDeviate:
 20149  		prg.curType = byte(known)
 20150  		prg.curExp = prg.normRand()
 20151  
 20152  	case penCircle:
 20153  		// Make a special knot node for \&[pencircle]
 20154  		prg.curType = byte(futurePen)
 20155  		prg.curExp = int32(prg.getNode(knotNodeSize))
 20156  		*(*prg.mem[prg.curExp].hh()).b0() = byte(open)
 20157  		*(*prg.mem[prg.curExp].hh()).b1() = byte(open)
 20158  		*(*prg.mem[prg.curExp].hh()).rh() = uint16(prg.curExp)
 20159  
 20160  		*prg.mem[prg.curExp+1].int() = 0
 20161  		*prg.mem[prg.curExp+2].int() = 0
 20162  
 20163  		*prg.mem[prg.curExp+3].int() = 0200000
 20164  		*prg.mem[prg.curExp+4].int() = 0
 20165  
 20166  		*prg.mem[prg.curExp+5].int() = 0
 20167  		*prg.mem[prg.curExp+6].int() = 0200000
 20168  
 20169  	case jobNameOp:
 20170  		if int32(prg.jobName) == 0 {
 20171  			prg.openLogFile()
 20172  		}
 20173  		prg.curType = byte(stringType)
 20174  		prg.curExp = int32(prg.jobName)
 20175  
 20176  	case readStringOp:
 20177  		// Read a string from the terminal
 20178  		if int32(prg.interaction) <= nonstopMode {
 20179  			prg.fatalError(strNumber( /* "*** (cannot readstring in nonstop modes)" */ 835))
 20180  		}
 20181  		prg.beginFileReading()
 20182  		prg.curInput.nameField = 1
 20183  		{
 20184  			prg.print( /* "" */ 285)
 20185  			prg.termInput()
 20186  		}
 20187  		{
 20188  			if int32(prg.poolPtr)+int32(prg.last)-int32(prg.curInput.startField) > int32(prg.maxPoolPtr) {
 20189  				if int32(prg.poolPtr)+int32(prg.last)-int32(prg.curInput.startField) > poolSize {
 20190  					prg.overflow(strNumber( /* "pool size" */ 257), poolSize-int32(prg.initPoolPtr))
 20191  				} /* \xref[METAFONT capacity exceeded pool size][\quad pool size]  */
 20192  				prg.maxPoolPtr = uint16(int32(prg.poolPtr) + int32(prg.last) - int32(prg.curInput.startField))
 20193  			}
 20194  		}
 20195  		for ii := int32(prg.curInput.startField); ii <= int32(prg.last)-1; ii++ {
 20196  			k = ii
 20197  			_ = k
 20198  			prg.strPool[prg.poolPtr] = prg.buffer[k]
 20199  			prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
 20200  		}
 20201  		prg.endFileReading()
 20202  		prg.curType = byte(stringType)
 20203  		prg.curExp = int32(prg.makeString())
 20204  
 20205  	} // there are no other cases
 20206  	{
 20207  		if prg.arithError {
 20208  			prg.clearArith()
 20209  		}
 20210  	}
 20211  }
 20212  
 20213  // 898.
 20214  
 20215  // tangle:pos ../../mf.web:17958:3:
 20216  
 20217  // Things get a bit more interesting when there's an operand. The
 20218  // operand to |do_unary| appears in |cur_type| and |cur_exp|.
 20219  // \4
 20220  // Declare unary action procedures
 20221  func (prg *prg) nicePair(p int32, t quarterword) (r bool) {
 20222  	if int32(t) == pairType {
 20223  		p = *prg.mem[p+1].int()
 20224  		if int32(*(*prg.mem[p].hh()).b0()) == known {
 20225  			if int32(*(*prg.mem[p+2].hh()).b0()) == known {
 20226  				r = true
 20227  				goto exit
 20228  			}
 20229  		}
 20230  	}
 20231  	r = false
 20232  
 20233  exit:
 20234  	;
 20235  	return r
 20236  }
 20237  
 20238  func (prg *prg) printKnownOrUnknownType(t smallNumber, v int32) {
 20239  	prg.printChar(asciiCode('('))
 20240  	if int32(t) < dependent {
 20241  		if int32(t) != pairType {
 20242  			prg.printType(t)
 20243  		} else if prg.nicePair(v, quarterword(pairType)) {
 20244  			prg.print( /* "pair" */ 337)
 20245  		} else {
 20246  			prg.print( /* "unknown pair" */ 836)
 20247  		}
 20248  	} else {
 20249  		prg.print( /* "unknown numeric" */ 837)
 20250  	}
 20251  	prg.printChar(asciiCode(')'))
 20252  }
 20253  
 20254  func (prg *prg) badUnary(c quarterword) {
 20255  	prg.dispErr(halfword(memMin), strNumber( /* "Not implemented: " */ 838))
 20256  	prg.printOp(c)
 20257  	// \xref[Not implemented...]
 20258  	prg.printKnownOrUnknownType(prg.curType, prg.curExp)
 20259  	{
 20260  		prg.helpPtr = 3
 20261  		prg.helpLine[2] = /* "I'm afraid I don't know how to apply that operation to that" */ 839
 20262  		prg.helpLine[1] = /* "particular type. Continue, and I'll simply return the" */ 840
 20263  		prg.helpLine[0] = /* "argument (shown above) as the result of the operation." */ 841
 20264  	}
 20265  	prg.putGetError()
 20266  }
 20267  
 20268  func (prg *prg) negateDepList(p halfword) {
 20269  	for true {
 20270  		*prg.mem[int32(p)+1].int() = -*prg.mem[int32(p)+1].int()
 20271  		if int32(*(*prg.mem[p].hh()).lh()) == memMin {
 20272  			goto exit
 20273  		}
 20274  		p = *(*prg.mem[p].hh()).rh()
 20275  	}
 20276  
 20277  exit:
 20278  }
 20279  
 20280  func (prg *prg) pairToPath() {
 20281  	prg.curExp = int32(prg.newKnot())
 20282  	prg.curType = byte(pathType)
 20283  }
 20284  
 20285  func (prg *prg) takePart(c quarterword) {
 20286  	var (
 20287  		p halfword // the big node
 20288  	)
 20289  	p = uint16(*prg.mem[prg.curExp+1].int())
 20290  	*prg.mem[memMin+3+10+2+2+1].int() = int32(p)
 20291  	*(*prg.mem[memMin+3+10+2+2].hh()).b0() = prg.curType
 20292  	*(*prg.mem[p].hh()).rh() = uint16(memMin + 3 + 10 + 2 + 2)
 20293  	prg.freeNode(halfword(prg.curExp), halfword(valueNodeSize))
 20294  	prg.makeExpCopy(halfword(int32(p) + 2*(int32(c)-xPart)))
 20295  	prg.recycleValue(halfword(memMin + 3 + 10 + 2 + 2))
 20296  }
 20297  
 20298  func (prg *prg) strToNum(c quarterword) { // converts a string to a number
 20299  	var (
 20300  		n                 int32       // accumulator
 20301  		m                 asciiCode   // current character
 20302  		k                 poolPointer // index into |str_pool|
 20303  		b/* 8..16 */ byte             // radix of conversion
 20304  		badChar           bool        // did the string contain an invalid digit?
 20305  	)
 20306  	if int32(c) == asciiOp {
 20307  		if int32(prg.strStart[prg.curExp+1])-int32(prg.strStart[prg.curExp]) == 0 {
 20308  			n = -1
 20309  		} else {
 20310  			n = int32(prg.strPool[prg.strStart[prg.curExp]])
 20311  		}
 20312  	} else {
 20313  		if int32(c) == octOp {
 20314  			b = 8
 20315  		} else {
 20316  			b = 16
 20317  		}
 20318  		n = 0
 20319  		badChar = false
 20320  		for ii := int32(prg.strStart[prg.curExp]); ii <= int32(prg.strStart[prg.curExp+1])-1; ii++ {
 20321  			k = poolPointer(ii)
 20322  			_ = k
 20323  			m = prg.strPool[k]
 20324  			if int32(m) >= '0' && int32(m) <= '9' {
 20325  				m = byte(int32(m) - '0')
 20326  			} else if int32(m) >= 'A' && int32(m) <= 'F' {
 20327  				m = byte(int32(m) - 'A' + 10)
 20328  			} else if int32(m) >= 'a' && int32(m) <= 'f' {
 20329  				m = byte(int32(m) - 'a' + 10)
 20330  			} else {
 20331  				badChar = true
 20332  				m = 0
 20333  			}
 20334  			if int32(m) >= int32(b) {
 20335  				badChar = true
 20336  				m = 0
 20337  			}
 20338  			if n < 32768/int32(b) {
 20339  				n = n*int32(b) + int32(m)
 20340  			} else {
 20341  				n = 32767
 20342  			}
 20343  		}
 20344  
 20345  		// Give error messages if |bad_char| or |n>=4096|
 20346  		if badChar {
 20347  			prg.dispErr(halfword(memMin), strNumber( /* "String contains illegal digits" */ 843))
 20348  			// \xref[String contains illegal digits]
 20349  			if int32(c) == octOp {
 20350  				prg.helpPtr = 1
 20351  				prg.helpLine[0] = /* "I zeroed out characters that weren't in the range 0..7." */ 844
 20352  			} else {
 20353  				prg.helpPtr = 1
 20354  				prg.helpLine[0] = /* "I zeroed out characters that weren't hex digits." */ 845
 20355  			}
 20356  			prg.putGetError()
 20357  		}
 20358  		if n > 4095 {
 20359  			{
 20360  				if int32(prg.interaction) == errorStopMode {
 20361  				}
 20362  				prg.printNl(strNumber( /* "! " */ 261))
 20363  				prg.print( /* "Number too large (" */ 846) /* \xref[!\relax]  */
 20364  			}
 20365  			prg.printInt(n)
 20366  			prg.printChar(asciiCode(')'))
 20367  			// \xref[Number too large]
 20368  			{
 20369  				prg.helpPtr = 1
 20370  				prg.helpLine[0] = /* "I have trouble with numbers greater than 4095; watch out." */ 847
 20371  			}
 20372  			prg.putGetError()
 20373  		}
 20374  	}
 20375  	prg.flushCurExp(n * 0200000)
 20376  }
 20377  
 20378  func (prg *prg) pathLength() (r scaled) { // computes the length of the current path
 20379  	var (
 20380  		n scaled   // the path length so far
 20381  		p halfword // traverser
 20382  	)
 20383  	p = uint16(prg.curExp)
 20384  	if int32(*(*prg.mem[p].hh()).b0()) == endpoint {
 20385  		n = -0200000
 20386  	} else {
 20387  		n = 0
 20388  	}
 20389  	for {
 20390  		p = *(*prg.mem[p].hh()).rh()
 20391  		n = n + 0200000
 20392  		if int32(p) == prg.curExp {
 20393  			break
 20394  		}
 20395  	}
 20396  	r = n
 20397  	return r
 20398  }
 20399  
 20400  func (prg *prg) testKnown(c quarterword) {
 20401  	var (
 20402  		b/* trueCode..falseCode */ byte          // is the current expression known?
 20403  		p, q                            halfword // locations in a big node
 20404  	)
 20405  	b = byte(falseCode)
 20406  	switch prg.curType {
 20407  	case vacuous, booleanType, stringType, penType,
 20408  		futurePen, pathType, pictureType, known:
 20409  		b = byte(trueCode)
 20410  	case transformType, pairType:
 20411  		p = uint16(*prg.mem[prg.curExp+1].int())
 20412  		q = uint16(int32(p) + int32(prg.bigNodeSize[prg.curType-13]))
 20413  		for {
 20414  			q = uint16(int32(q) - 2)
 20415  			if int32(*(*prg.mem[q].hh()).b0()) != known {
 20416  				goto done
 20417  			}
 20418  			if int32(q) == int32(p) {
 20419  				break
 20420  			}
 20421  		}
 20422  		b = byte(trueCode)
 20423  
 20424  	done:
 20425  		;
 20426  
 20427  	default:
 20428  	}
 20429  	if int32(c) == knownOp {
 20430  		prg.flushCurExp(scaled(b))
 20431  	} else {
 20432  		prg.flushCurExp(trueCode + falseCode - int32(b))
 20433  	}
 20434  	prg.curType = byte(booleanType)
 20435  }
 20436  
 20437  func (prg *prg) doUnary(c quarterword) {
 20438  	var (
 20439  		p, q halfword // for list manipulation
 20440  		x    int32    // a temporary register
 20441  	)
 20442  	{
 20443  		if prg.arithError {
 20444  			prg.clearArith()
 20445  		}
 20446  	}
 20447  	if prg.internal[tracingCommands-1] > 0400000 {
 20448  		prg.beginDiagnostic()
 20449  		prg.printNl(strNumber('{'))
 20450  		prg.printOp(c)
 20451  		prg.printChar(asciiCode('('))
 20452  
 20453  		prg.printExp(halfword(memMin), smallNumber(0)) // show the operand, but not verbosely
 20454  		prg.print( /* ")]" */ 842)
 20455  		prg.endDiagnostic(false)
 20456  	}
 20457  	switch c {
 20458  	case plus:
 20459  		if int32(prg.curType) < pairType {
 20460  			if int32(prg.curType) != pictureType {
 20461  				prg.badUnary(quarterword(plus))
 20462  			}
 20463  		}
 20464  	case minus:
 20465  		// Negate the current expression
 20466  		switch prg.curType {
 20467  		case pairType, independent:
 20468  			q = uint16(prg.curExp)
 20469  			prg.makeExpCopy(q)
 20470  			if int32(prg.curType) == dependent {
 20471  				prg.negateDepList(*(*prg.mem[prg.curExp+1].hh()).rh())
 20472  			} else if int32(prg.curType) == pairType {
 20473  				p = uint16(*prg.mem[prg.curExp+1].int())
 20474  				if int32(*(*prg.mem[p].hh()).b0()) == known {
 20475  					*prg.mem[int32(p)+1].int() = -*prg.mem[int32(p)+1].int()
 20476  				} else {
 20477  					prg.negateDepList(*(*prg.mem[int32(p)+1].hh()).rh())
 20478  				}
 20479  				if int32(*(*prg.mem[int32(p)+2].hh()).b0()) == known {
 20480  					*prg.mem[int32(p)+2+1].int() = -*prg.mem[int32(p)+2+1].int()
 20481  				} else {
 20482  					prg.negateDepList(*(*prg.mem[int32(p)+2+1].hh()).rh())
 20483  				}
 20484  			} // if |cur_type=known| then |cur_exp=0|
 20485  			prg.recycleValue(q)
 20486  			prg.freeNode(q, halfword(valueNodeSize))
 20487  
 20488  		case dependent, protoDependent:
 20489  			prg.negateDepList(*(*prg.mem[prg.curExp+1].hh()).rh())
 20490  		case known:
 20491  			prg.curExp = -prg.curExp
 20492  		case pictureType:
 20493  			prg.negateEdges(halfword(prg.curExp))
 20494  
 20495  		default:
 20496  			prg.badUnary(quarterword(minus))
 20497  		}
 20498  
 20499  	// \4
 20500  	// Additional cases of unary operators
 20501  	case notOp:
 20502  		if int32(prg.curType) != booleanType {
 20503  			prg.badUnary(quarterword(notOp))
 20504  		} else {
 20505  			prg.curExp = trueCode + falseCode - prg.curExp
 20506  		}
 20507  
 20508  	case sqrtOp, mExpOp, mLogOp, sinDOp,
 20509  		cosDOp, floorOp, uniformDeviate, oddOp,
 20510  		charExistsOp: //
 20511  
 20512  		if int32(prg.curType) != known {
 20513  			prg.badUnary(c)
 20514  		} else {
 20515  			switch c {
 20516  			case sqrtOp:
 20517  				prg.curExp = prg.squareRt(prg.curExp)
 20518  			case mExpOp:
 20519  				prg.curExp = prg.mExp(prg.curExp)
 20520  			case mLogOp:
 20521  				prg.curExp = prg.mLog(prg.curExp)
 20522  			case sinDOp, cosDOp:
 20523  				prg.nSinCos(prg.curExp % 23592960 * 16)
 20524  				if int32(c) == sinDOp {
 20525  					prg.curExp = prg.roundFraction(prg.nSin)
 20526  				} else {
 20527  					prg.curExp = prg.roundFraction(prg.nCos)
 20528  				}
 20529  
 20530  			case floorOp:
 20531  				prg.curExp = prg.floorScaled(prg.curExp)
 20532  			case uniformDeviate:
 20533  				prg.curExp = prg.unifRand(prg.curExp)
 20534  			case oddOp:
 20535  				if prg.roundUnscaled(prg.curExp)&1 != 0 {
 20536  					prg.curExp = trueCode
 20537  				} else {
 20538  					prg.curExp = falseCode
 20539  				}
 20540  				prg.curType = byte(booleanType)
 20541  
 20542  			case charExistsOp:
 20543  				// Determine if a character has been shipped out
 20544  				prg.curExp = prg.roundUnscaled(prg.curExp) % 256
 20545  				if prg.curExp < 0 {
 20546  					prg.curExp = prg.curExp + 256
 20547  				}
 20548  				if prg.charExists[prg.curExp] {
 20549  					prg.curExp = trueCode
 20550  				} else {
 20551  					prg.curExp = falseCode
 20552  				}
 20553  				prg.curType = byte(booleanType)
 20554  
 20555  			}
 20556  		} // there are no other cases
 20557  
 20558  	case angleOp:
 20559  		if prg.nicePair(prg.curExp, prg.curType) {
 20560  			p = uint16(*prg.mem[prg.curExp+1].int())
 20561  			x = prg.nArg(*prg.mem[int32(p)+1].int(), *prg.mem[int32(p)+2+1].int())
 20562  			if x >= 0 {
 20563  				prg.flushCurExp((x + 8) / 16)
 20564  			} else {
 20565  				prg.flushCurExp(-((-x + 8) / 16))
 20566  			}
 20567  		} else {
 20568  			prg.badUnary(quarterword(angleOp))
 20569  		}
 20570  
 20571  	case xPart, yPart:
 20572  		if int32(prg.curType) <= pairType && int32(prg.curType) >= transformType {
 20573  			prg.takePart(c)
 20574  		} else {
 20575  			prg.badUnary(c)
 20576  		}
 20577  	case xxPart, xyPart, yxPart, yyPart:
 20578  		if int32(prg.curType) == transformType {
 20579  			prg.takePart(c)
 20580  		} else {
 20581  			prg.badUnary(c)
 20582  		}
 20583  
 20584  	case charOp:
 20585  		if int32(prg.curType) != known {
 20586  			prg.badUnary(quarterword(charOp))
 20587  		} else {
 20588  			prg.curExp = prg.roundUnscaled(prg.curExp) % 256
 20589  			prg.curType = byte(stringType)
 20590  			if prg.curExp < 0 {
 20591  				prg.curExp = prg.curExp + 256
 20592  			}
 20593  			if int32(prg.strStart[prg.curExp+1])-int32(prg.strStart[prg.curExp]) != 1 {
 20594  				{
 20595  					if int32(prg.poolPtr)+1 > int32(prg.maxPoolPtr) {
 20596  						if int32(prg.poolPtr)+1 > poolSize {
 20597  							prg.overflow(strNumber( /* "pool size" */ 257), poolSize-int32(prg.initPoolPtr))
 20598  						} /* \xref[METAFONT capacity exceeded pool size][\quad pool size]  */
 20599  						prg.maxPoolPtr = uint16(int32(prg.poolPtr) + 1)
 20600  					}
 20601  				}
 20602  				{
 20603  					prg.strPool[prg.poolPtr] = byte(prg.curExp)
 20604  					prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
 20605  				}
 20606  				prg.curExp = int32(prg.makeString())
 20607  			}
 20608  		}
 20609  	case decimal:
 20610  		if int32(prg.curType) != known {
 20611  			prg.badUnary(quarterword(decimal))
 20612  		} else {
 20613  			prg.oldSetting = prg.selector
 20614  			prg.selector = byte(newString)
 20615  			prg.printScaled(prg.curExp)
 20616  			prg.curExp = int32(prg.makeString())
 20617  			prg.selector = prg.oldSetting
 20618  			prg.curType = byte(stringType)
 20619  		}
 20620  	case octOp, hexOp, asciiOp:
 20621  		if int32(prg.curType) != stringType {
 20622  			prg.badUnary(c)
 20623  		} else {
 20624  			prg.strToNum(c)
 20625  		}
 20626  
 20627  	case lengthOp:
 20628  		if int32(prg.curType) == stringType {
 20629  			prg.flushCurExp((int32(prg.strStart[prg.curExp+1]) - int32(prg.strStart[prg.curExp])) * 0200000)
 20630  		} else if int32(prg.curType) == pathType {
 20631  			prg.flushCurExp(prg.pathLength())
 20632  		} else if int32(prg.curType) == known {
 20633  			prg.curExp = abs(prg.curExp)
 20634  		} else if prg.nicePair(prg.curExp, prg.curType) {
 20635  			prg.flushCurExp(prg.pythAdd(*prg.mem[*prg.mem[prg.curExp+1].int()+1].int(), *prg.mem[*prg.mem[prg.curExp+1].int()+2+1].int()))
 20636  		} else {
 20637  			prg.badUnary(c)
 20638  		}
 20639  
 20640  	case turningOp:
 20641  		if int32(prg.curType) == pairType {
 20642  			prg.flushCurExp(scaled(0))
 20643  		} else if int32(prg.curType) != pathType {
 20644  			prg.badUnary(quarterword(turningOp))
 20645  		} else if int32(*(*prg.mem[prg.curExp].hh()).b0()) == endpoint {
 20646  			prg.flushCurExp(scaled(0))
 20647  		} else {
 20648  			prg.curPen = uint16(memMin + 3)
 20649  			prg.curPathType = byte(contourCode)
 20650  			prg.curExp = int32(prg.makeSpec(halfword(prg.curExp),
 20651  				02000000000-0100000-1-017777777777, 0))
 20652  			prg.flushCurExp(prg.turningNumber * 0200000) // convert to |scaled|
 20653  		}
 20654  
 20655  	case booleanType:
 20656  		if int32(prg.curType) >= booleanType && int32(prg.curType) <= unknownBoolean {
 20657  			prg.flushCurExp(trueCode)
 20658  		} else {
 20659  			prg.flushCurExp(falseCode)
 20660  		}
 20661  		prg.curType = byte(booleanType)
 20662  	case stringType:
 20663  		if int32(prg.curType) >= stringType && int32(prg.curType) <= unknownString {
 20664  			prg.flushCurExp(trueCode)
 20665  		} else {
 20666  			prg.flushCurExp(falseCode)
 20667  		}
 20668  		prg.curType = byte(booleanType)
 20669  	case penType:
 20670  		if int32(prg.curType) >= penType && int32(prg.curType) <= futurePen {
 20671  			prg.flushCurExp(trueCode)
 20672  		} else {
 20673  			prg.flushCurExp(falseCode)
 20674  		}
 20675  		prg.curType = byte(booleanType)
 20676  	case pathType:
 20677  		if int32(prg.curType) >= pathType && int32(prg.curType) <= unknownPath {
 20678  			prg.flushCurExp(trueCode)
 20679  		} else {
 20680  			prg.flushCurExp(falseCode)
 20681  		}
 20682  		prg.curType = byte(booleanType)
 20683  	case pictureType:
 20684  		if int32(prg.curType) >= pictureType && int32(prg.curType) <= unknownPicture {
 20685  			prg.flushCurExp(trueCode)
 20686  		} else {
 20687  			prg.flushCurExp(falseCode)
 20688  		}
 20689  		prg.curType = byte(booleanType)
 20690  	case transformType, pairType:
 20691  		if int32(prg.curType) == int32(c) {
 20692  			prg.flushCurExp(trueCode)
 20693  		} else {
 20694  			prg.flushCurExp(falseCode)
 20695  		}
 20696  		prg.curType = byte(booleanType)
 20697  	case numericType:
 20698  		if int32(prg.curType) >= known && int32(prg.curType) <= independent {
 20699  			prg.flushCurExp(trueCode)
 20700  		} else {
 20701  			prg.flushCurExp(falseCode)
 20702  		}
 20703  		prg.curType = byte(booleanType)
 20704  	case knownOp, unknownOp:
 20705  		prg.testKnown(c)
 20706  
 20707  	case cycleOp:
 20708  		if int32(prg.curType) != pathType {
 20709  			prg.flushCurExp(falseCode)
 20710  		} else if int32(*(*prg.mem[prg.curExp].hh()).b0()) != endpoint {
 20711  			prg.flushCurExp(trueCode)
 20712  		} else {
 20713  			prg.flushCurExp(falseCode)
 20714  		}
 20715  		prg.curType = byte(booleanType)
 20716  
 20717  	case makePenOp:
 20718  		if int32(prg.curType) == pairType {
 20719  			prg.pairToPath()
 20720  		}
 20721  		if int32(prg.curType) == pathType {
 20722  			prg.curType = byte(futurePen)
 20723  		} else {
 20724  			prg.badUnary(quarterword(makePenOp))
 20725  		}
 20726  
 20727  	case makePathOp:
 20728  		if int32(prg.curType) == futurePen {
 20729  			prg.materializePen()
 20730  		}
 20731  		if int32(prg.curType) != penType {
 20732  			prg.badUnary(quarterword(makePathOp))
 20733  		} else {
 20734  			prg.flushCurExp(scaled(prg.makePath(halfword(prg.curExp))))
 20735  			prg.curType = byte(pathType)
 20736  		}
 20737  
 20738  	case totalWeightOp:
 20739  		if int32(prg.curType) != pictureType {
 20740  			prg.badUnary(quarterword(totalWeightOp))
 20741  		} else {
 20742  			prg.flushCurExp(prg.totalWeight(halfword(prg.curExp)))
 20743  		}
 20744  	case reverse:
 20745  		if int32(prg.curType) == pathType {
 20746  			p = prg.htapYpoc(halfword(prg.curExp))
 20747  			if int32(*(*prg.mem[p].hh()).b1()) == endpoint {
 20748  				p = *(*prg.mem[p].hh()).rh()
 20749  			}
 20750  			prg.tossKnotList(halfword(prg.curExp))
 20751  			prg.curExp = int32(p)
 20752  		} else if int32(prg.curType) == pairType {
 20753  			prg.pairToPath()
 20754  		} else {
 20755  			prg.badUnary(quarterword(reverse))
 20756  		}
 20757  
 20758  	} // there are no other cases
 20759  	{
 20760  		if prg.arithError {
 20761  			prg.clearArith()
 20762  		}
 20763  	}
 20764  }
 20765  
 20766  // 922.
 20767  
 20768  // tangle:pos ../../mf.web:18295:3:
 20769  
 20770  // Finally, we have the operations that combine a capsule~|p|
 20771  // with the current expression.
 20772  // \4
 20773  // Declare binary action procedures
 20774  func (prg *prg) badBinary(p halfword, c quarterword) {
 20775  	prg.dispErr(p, strNumber( /* "" */ 285))
 20776  	prg.dispErr(halfword(memMin), strNumber( /* "Not implemented: " */ 838))
 20777  	// \xref[Not implemented...]
 20778  	if int32(c) >= minOf {
 20779  		prg.printOp(c)
 20780  	}
 20781  	prg.printKnownOrUnknownType(*(*prg.mem[p].hh()).b0(), int32(p))
 20782  	if int32(c) >= minOf {
 20783  		prg.print( /* "of" */ 479)
 20784  	} else {
 20785  		prg.printOp(c)
 20786  	}
 20787  	prg.printKnownOrUnknownType(prg.curType, prg.curExp)
 20788  
 20789  	{
 20790  		prg.helpPtr = 3
 20791  		prg.helpLine[2] = /* "I'm afraid I don't know how to apply that operation to that" */ 839
 20792  		prg.helpLine[1] = /* "combination of types. Continue, and I'll return the second" */ 848
 20793  		prg.helpLine[0] = /* "argument (see above) as the result of the operation." */ 849
 20794  	}
 20795  	prg.putGetError()
 20796  }
 20797  
 20798  func (prg *prg) tarnished(p halfword) (r halfword) {
 20799  	var (
 20800  		q  halfword // beginning of the big node
 20801  		r1 halfword // current position in the big node
 20802  	)
 20803  	q = uint16(*prg.mem[int32(p)+1].int())
 20804  	r1 = uint16(int32(q) + int32(prg.bigNodeSize[*(*prg.mem[p].hh()).b0()-13]))
 20805  	for {
 20806  		r1 = uint16(int32(r1) - 2)
 20807  		if int32(*(*prg.mem[r1].hh()).b0()) == independent {
 20808  			r = uint16(memMin + 1)
 20809  			goto exit
 20810  		}
 20811  		if int32(r1) == int32(q) {
 20812  			break
 20813  		}
 20814  	}
 20815  	r = uint16(memMin)
 20816  
 20817  exit:
 20818  	;
 20819  	return r
 20820  }
 20821  
 20822  // \4
 20823  // Declare the procedure called |dep_finish|
 20824  func (prg *prg) depFinish(v, q halfword, t smallNumber) {
 20825  	var (
 20826  		p  halfword // the destination
 20827  		vv scaled   // the value, if it is |known|
 20828  	)
 20829  	if int32(q) == memMin {
 20830  		p = uint16(prg.curExp)
 20831  	} else {
 20832  		p = q
 20833  	}
 20834  	*(*prg.mem[int32(p)+1].hh()).rh() = v
 20835  	*(*prg.mem[p].hh()).b0() = t
 20836  	if int32(*(*prg.mem[v].hh()).lh()) == memMin {
 20837  		vv = *prg.mem[int32(v)+1].int()
 20838  		if int32(q) == memMin {
 20839  			prg.flushCurExp(vv)
 20840  		} else {
 20841  			prg.recycleValue(p)
 20842  			*(*prg.mem[q].hh()).b0() = byte(known)
 20843  			*prg.mem[int32(q)+1].int() = vv
 20844  		}
 20845  	} else if int32(q) == memMin {
 20846  		prg.curType = t
 20847  	}
 20848  	if prg.fixNeeded {
 20849  		prg.fixDependencies()
 20850  	}
 20851  }
 20852  
 20853  func (prg *prg) addOrSubtract(p, q halfword, c quarterword) {
 20854  	var (
 20855  		s, t smallNumber // operand types
 20856  		r1   halfword    // list traverser
 20857  		v    int32       // second operand value
 20858  	)
 20859  	if int32(q) == memMin {
 20860  		t = prg.curType
 20861  		if int32(t) < dependent {
 20862  			v = prg.curExp
 20863  		} else {
 20864  			v = int32(*(*prg.mem[prg.curExp+1].hh()).rh())
 20865  		}
 20866  	} else {
 20867  		t = *(*prg.mem[q].hh()).b0()
 20868  		if int32(t) < dependent {
 20869  			v = *prg.mem[int32(q)+1].int()
 20870  		} else {
 20871  			v = int32(*(*prg.mem[int32(q)+1].hh()).rh())
 20872  		}
 20873  	}
 20874  	if int32(t) == known {
 20875  		if int32(c) == minus {
 20876  			v = -v
 20877  		}
 20878  		if int32(*(*prg.mem[p].hh()).b0()) == known {
 20879  			v = prg.slowAdd(*prg.mem[int32(p)+1].int(), v)
 20880  			if int32(q) == memMin {
 20881  				prg.curExp = v
 20882  			} else {
 20883  				*prg.mem[int32(q)+1].int() = v
 20884  			}
 20885  
 20886  			goto exit
 20887  		}
 20888  
 20889  		// Add a known value to the constant term of |dep_list(p)|
 20890  		r1 = *(*prg.mem[int32(p)+1].hh()).rh()
 20891  		for int32(*(*prg.mem[r1].hh()).lh()) != memMin {
 20892  			r1 = *(*prg.mem[r1].hh()).rh()
 20893  		}
 20894  		*prg.mem[int32(r1)+1].int() = prg.slowAdd(*prg.mem[int32(r1)+1].int(), v)
 20895  		if int32(q) == memMin {
 20896  			q = prg.getNode(valueNodeSize)
 20897  			prg.curExp = int32(q)
 20898  			prg.curType = *(*prg.mem[p].hh()).b0()
 20899  			*(*prg.mem[q].hh()).b1() = byte(capsule)
 20900  		}
 20901  		*(*prg.mem[int32(q)+1].hh()).rh() = *(*prg.mem[int32(p)+1].hh()).rh()
 20902  		*(*prg.mem[q].hh()).b0() = *(*prg.mem[p].hh()).b0()
 20903  		*(*prg.mem[int32(q)+1].hh()).lh() = *(*prg.mem[int32(p)+1].hh()).lh()
 20904  		*(*prg.mem[*(*prg.mem[int32(p)+1].hh()).lh()].hh()).rh() = q
 20905  		*(*prg.mem[p].hh()).b0() = byte(known) // this will keep the recycler from collecting non-garbage
 20906  
 20907  	} else {
 20908  		if int32(c) == minus {
 20909  			prg.negateDepList(halfword(v))
 20910  		}
 20911  
 20912  		// Add operand |p| to the dependency list |v|
 20913  		if int32(*(*prg.mem[p].hh()).b0()) == known {
 20914  			for int32(*(*prg.mem[v].hh()).lh()) != memMin {
 20915  				v = int32(*(*prg.mem[v].hh()).rh())
 20916  			}
 20917  			*prg.mem[v+1].int() = prg.slowAdd(*prg.mem[int32(p)+1].int(), *prg.mem[v+1].int())
 20918  		} else {
 20919  			s = *(*prg.mem[p].hh()).b0()
 20920  			r1 = *(*prg.mem[int32(p)+1].hh()).rh()
 20921  			if int32(t) == dependent {
 20922  				if int32(s) == dependent {
 20923  					if prg.maxCoef(r1)+prg.maxCoef(halfword(v)) < 04525252525 {
 20924  						v = int32(prg.pPlusQ(halfword(v), r1, smallNumber(dependent)))
 20925  						goto done
 20926  					}
 20927  				} // |fix_needed| will necessarily be false
 20928  				t = byte(protoDependent)
 20929  				v = int32(prg.pOverV(halfword(v), scaled(0200000), smallNumber(dependent), smallNumber(protoDependent)))
 20930  			}
 20931  			if int32(s) == protoDependent {
 20932  				v = int32(prg.pPlusQ(halfword(v), r1, smallNumber(protoDependent)))
 20933  			} else {
 20934  				v = int32(prg.pPlusFq(halfword(v), 0200000, r1, smallNumber(protoDependent), smallNumber(dependent)))
 20935  			}
 20936  
 20937  		done:
 20938  			if int32(q) != memMin {
 20939  				prg.depFinish(halfword(v), q, t)
 20940  			} else {
 20941  				prg.curType = t
 20942  				prg.depFinish(halfword(v), halfword(memMin), t)
 20943  			}
 20944  		}
 20945  	}
 20946  
 20947  exit:
 20948  }
 20949  
 20950  func (prg *prg) depMult(p halfword, v int32, vIsScaled bool) {
 20951  	var (
 20952  		q    halfword    // the dependency list being multiplied by |v|
 20953  		s, t smallNumber // its type, before and after
 20954  	)
 20955  	if int32(p) == memMin {
 20956  		q = uint16(prg.curExp)
 20957  	} else if int32(*(*prg.mem[p].hh()).b0()) != known {
 20958  		q = p
 20959  	} else {
 20960  		if vIsScaled {
 20961  			*prg.mem[int32(p)+1].int() = prg.takeScaled(*prg.mem[int32(p)+1].int(), v)
 20962  		} else {
 20963  			*prg.mem[int32(p)+1].int() = prg.takeFraction(*prg.mem[int32(p)+1].int(), v)
 20964  		}
 20965  
 20966  		goto exit
 20967  	}
 20968  	t = *(*prg.mem[q].hh()).b0()
 20969  	q = *(*prg.mem[int32(q)+1].hh()).rh()
 20970  	s = t
 20971  	if int32(t) == dependent {
 20972  		if vIsScaled {
 20973  			if prg.abVsCd(prg.maxCoef(q), abs(v), 04525252525-1, 0200000) >= 0 {
 20974  				t = byte(protoDependent)
 20975  			}
 20976  		}
 20977  	}
 20978  	q = prg.pTimesV(q, v, s, t, vIsScaled)
 20979  	prg.depFinish(q, p, t)
 20980  
 20981  exit:
 20982  }
 20983  
 20984  func (prg *prg) hardTimes(p halfword) {
 20985  	var (
 20986  		q    halfword // a copy of the dependent variable |p|
 20987  		r1   halfword // the big node for the nice pair
 20988  		u, v scaled   // the known values of the nice pair
 20989  	)
 20990  	if int32(*(*prg.mem[p].hh()).b0()) == pairType {
 20991  		q = prg.stashCurExp()
 20992  		prg.unstashCurExp(p)
 20993  		p = q
 20994  	} // now |cur_type=pair_type|
 20995  	r1 = uint16(*prg.mem[prg.curExp+1].int())
 20996  	u = *prg.mem[int32(r1)+1].int()
 20997  	v = *prg.mem[int32(r1)+2+1].int()
 20998  
 20999  	// Move the dependent variable |p| into both parts of the pair node |r|
 21000  	*(*prg.mem[int32(r1)+2].hh()).b0() = *(*prg.mem[p].hh()).b0()
 21001  	prg.newDep(halfword(int32(r1)+2), prg.copyDepList(*(*prg.mem[int32(p)+1].hh()).rh()))
 21002  
 21003  	*(*prg.mem[r1].hh()).b0() = *(*prg.mem[p].hh()).b0()
 21004  	prg.mem[int32(r1)+1] = prg.mem[int32(p)+1]
 21005  	*(*prg.mem[*(*prg.mem[int32(p)+1].hh()).lh()].hh()).rh() = r1
 21006  	prg.freeNode(p, halfword(valueNodeSize))
 21007  	prg.depMult(r1, u, true)
 21008  	prg.depMult(halfword(int32(r1)+2), v, true)
 21009  }
 21010  
 21011  func (prg *prg) depDiv(p halfword, v scaled) {
 21012  	var (
 21013  		q    halfword    // the dependency list being divided by |v|
 21014  		s, t smallNumber // its type, before and after
 21015  	)
 21016  	if int32(p) == memMin {
 21017  		q = uint16(prg.curExp)
 21018  	} else if int32(*(*prg.mem[p].hh()).b0()) != known {
 21019  		q = p
 21020  	} else {
 21021  		*prg.mem[int32(p)+1].int() = prg.makeScaled(*prg.mem[int32(p)+1].int(), v)
 21022  		goto exit
 21023  	}
 21024  	t = *(*prg.mem[q].hh()).b0()
 21025  	q = *(*prg.mem[int32(q)+1].hh()).rh()
 21026  	s = t
 21027  	if int32(t) == dependent {
 21028  		if prg.abVsCd(prg.maxCoef(q), 0200000, 04525252525-1, abs(v)) >= 0 {
 21029  			t = byte(protoDependent)
 21030  		}
 21031  	}
 21032  	q = prg.pOverV(q, v, s, t)
 21033  	prg.depFinish(q, p, t)
 21034  
 21035  exit:
 21036  }
 21037  
 21038  func (prg *prg) setUpTrans(c quarterword) {
 21039  	var (
 21040  		p, q, r1 halfword // list manipulation registers
 21041  	)
 21042  	if int32(c) != transformedBy || int32(prg.curType) != transformType {
 21043  		p = prg.stashCurExp()
 21044  		prg.curExp = int32(prg.idTransform())
 21045  		prg.curType = byte(transformType)
 21046  		q = uint16(*prg.mem[prg.curExp+1].int())
 21047  		switch c {
 21048  		case rotatedBy:
 21049  			if int32(*(*prg.mem[p].hh()).b0()) == known {
 21050  				prg.nSinCos(*prg.mem[int32(p)+1].int() % 23592960 * 16)
 21051  				*prg.mem[int32(q)+4+1].int() = prg.roundFraction(prg.nCos)
 21052  				*prg.mem[int32(q)+8+1].int() = prg.roundFraction(prg.nSin)
 21053  				*prg.mem[int32(q)+6+1].int() = -*prg.mem[int32(q)+8+1].int()
 21054  				*prg.mem[int32(q)+10+1].int() = *prg.mem[int32(q)+4+1].int()
 21055  
 21056  				goto done
 21057  			}
 21058  
 21059  		case slantedBy:
 21060  			if int32(*(*prg.mem[p].hh()).b0()) > pairType {
 21061  				prg.install(halfword(int32(q)+6), p)
 21062  				goto done
 21063  			}
 21064  		case scaledBy:
 21065  			if int32(*(*prg.mem[p].hh()).b0()) > pairType {
 21066  				prg.install(halfword(int32(q)+4), p)
 21067  				prg.install(halfword(int32(q)+10), p)
 21068  				goto done
 21069  			}
 21070  		case shiftedBy:
 21071  			if int32(*(*prg.mem[p].hh()).b0()) == pairType {
 21072  				r1 = uint16(*prg.mem[int32(p)+1].int())
 21073  				prg.install(q, r1)
 21074  				prg.install(halfword(int32(q)+2), halfword(int32(r1)+2))
 21075  				goto done
 21076  			}
 21077  		case xScaled:
 21078  			if int32(*(*prg.mem[p].hh()).b0()) > pairType {
 21079  				prg.install(halfword(int32(q)+4), p)
 21080  				goto done
 21081  			}
 21082  		case yScaled:
 21083  			if int32(*(*prg.mem[p].hh()).b0()) > pairType {
 21084  				prg.install(halfword(int32(q)+10), p)
 21085  				goto done
 21086  			}
 21087  		case zScaled:
 21088  			if int32(*(*prg.mem[p].hh()).b0()) == pairType {
 21089  				r1 = uint16(*prg.mem[int32(p)+1].int())
 21090  				prg.install(halfword(int32(q)+4), r1)
 21091  				prg.install(halfword(int32(q)+10), r1)
 21092  				prg.install(halfword(int32(q)+8), halfword(int32(r1)+2))
 21093  				if int32(*(*prg.mem[int32(r1)+2].hh()).b0()) == known {
 21094  					*prg.mem[int32(r1)+2+1].int() = -*prg.mem[int32(r1)+2+1].int()
 21095  				} else {
 21096  					prg.negateDepList(*(*prg.mem[int32(r1)+2+1].hh()).rh())
 21097  				}
 21098  				prg.install(halfword(int32(q)+6), halfword(int32(r1)+2))
 21099  
 21100  				goto done
 21101  			}
 21102  
 21103  		case transformedBy:
 21104  
 21105  		} // there are no other cases
 21106  		prg.dispErr(p, strNumber( /* "Improper transformation argument" */ 858))
 21107  		// \xref[Improper transformation argument]
 21108  		{
 21109  			prg.helpPtr = 3
 21110  			prg.helpLine[2] = /* "The expression shown above has the wrong type," */ 859
 21111  			prg.helpLine[1] = /* "so I can't transform anything using it." */ 860
 21112  			prg.helpLine[0] = /* "Proceed, and I'll omit the transformation." */ 538
 21113  		}
 21114  		prg.putGetError()
 21115  
 21116  	done:
 21117  		prg.recycleValue(p)
 21118  		prg.freeNode(p, halfword(valueNodeSize))
 21119  	}
 21120  
 21121  	// If the current transform is entirely known, stash it in global variables; otherwise |return|
 21122  	q = uint16(*prg.mem[prg.curExp+1].int())
 21123  	r1 = uint16(int32(q) + transformNodeSize)
 21124  	for {
 21125  		r1 = uint16(int32(r1) - 2)
 21126  		if int32(*(*prg.mem[r1].hh()).b0()) != known {
 21127  			goto exit
 21128  		}
 21129  		if int32(r1) == int32(q) {
 21130  			break
 21131  		}
 21132  	}
 21133  	prg.txx = *prg.mem[int32(q)+4+1].int()
 21134  	prg.txy = *prg.mem[int32(q)+6+1].int()
 21135  	prg.tyx = *prg.mem[int32(q)+8+1].int()
 21136  	prg.tyy = *prg.mem[int32(q)+10+1].int()
 21137  	prg.tx = *prg.mem[int32(q)+1].int()
 21138  	prg.ty = *prg.mem[int32(q)+2+1].int()
 21139  	prg.flushCurExp(scaled(0))
 21140  
 21141  exit:
 21142  }
 21143  
 21144  func (prg *prg) setUpKnownTrans(c quarterword) {
 21145  	prg.setUpTrans(c)
 21146  	if int32(prg.curType) != known {
 21147  		prg.dispErr(halfword(memMin), strNumber( /* "Transform components aren't all known" */ 861))
 21148  		// \xref[Transform components...]
 21149  		{
 21150  			prg.helpPtr = 3
 21151  			prg.helpLine[2] = /* "I'm unable to apply a partially specified transformation" */ 862
 21152  			prg.helpLine[1] = /* "except to a fully known pair or transform." */ 863
 21153  			prg.helpLine[0] = /* "Proceed, and I'll omit the transformation." */ 538
 21154  		}
 21155  		prg.putGetFlushError(scaled(0))
 21156  		prg.txx = 0200000
 21157  		prg.txy = 0
 21158  		prg.tyx = 0
 21159  		prg.tyy = 0200000
 21160  		prg.tx = 0
 21161  		prg.ty = 0
 21162  	}
 21163  }
 21164  
 21165  func (prg *prg) trans(p, q halfword) {
 21166  	var (
 21167  		v scaled // the new |x| value
 21168  	)
 21169  	v = prg.takeScaled(*prg.mem[p].int(), prg.txx) + prg.takeScaled(*prg.mem[q].int(), prg.txy) + prg.tx
 21170  	*prg.mem[q].int() = prg.takeScaled(*prg.mem[p].int(), prg.tyx) + prg.takeScaled(*prg.mem[q].int(), prg.tyy) + prg.ty
 21171  	*prg.mem[p].int() = v
 21172  }
 21173  
 21174  func (prg *prg) pathTrans(p halfword, c quarterword) {
 21175  	var (
 21176  		q halfword // list traverser
 21177  	)
 21178  	prg.setUpKnownTrans(c)
 21179  	prg.unstashCurExp(p)
 21180  	if int32(prg.curType) == penType {
 21181  		if *prg.mem[prg.curExp+9].int() == 0 {
 21182  			if prg.tx == 0 {
 21183  				if prg.ty == 0 {
 21184  					goto exit
 21185  				}
 21186  			}
 21187  		}
 21188  		prg.flushCurExp(scaled(prg.makePath(halfword(prg.curExp))))
 21189  		prg.curType = byte(futurePen)
 21190  	}
 21191  	q = uint16(prg.curExp)
 21192  	for {
 21193  		if int32(*(*prg.mem[q].hh()).b0()) != endpoint {
 21194  			prg.trans(halfword(int32(q)+3), halfword(int32(q)+4))
 21195  		} // that's |left_x| and |left_y|
 21196  		prg.trans(halfword(int32(q)+1), halfword(int32(q)+2)) // that's |x_coord| and |y_coord|
 21197  		if int32(*(*prg.mem[q].hh()).b1()) != endpoint {
 21198  			prg.trans(halfword(int32(q)+5), halfword(int32(q)+6))
 21199  		} // that's |right_x| and |right_y|
 21200  		q = *(*prg.mem[q].hh()).rh()
 21201  		if int32(q) == prg.curExp {
 21202  			break
 21203  		}
 21204  	}
 21205  
 21206  exit:
 21207  }
 21208  
 21209  func (prg *prg) edgesTrans(p halfword, c quarterword) {
 21210  	prg.setUpKnownTrans(c)
 21211  	prg.unstashCurExp(p)
 21212  	prg.curEdges = uint16(prg.curExp)
 21213  	if int32(*(*prg.mem[prg.curEdges].hh()).rh()) == int32(prg.curEdges) {
 21214  		goto exit
 21215  	} // the empty set is easy to transform
 21216  	if prg.txx == 0 {
 21217  		if prg.tyy == 0 {
 21218  			if prg.txy%0200000 == 0 {
 21219  				if prg.tyx%0200000 == 0 {
 21220  					prg.xySwapEdges()
 21221  					prg.txx = prg.txy
 21222  					prg.tyy = prg.tyx
 21223  					prg.txy = 0
 21224  					prg.tyx = 0
 21225  					if int32(*(*prg.mem[prg.curEdges].hh()).rh()) == int32(prg.curEdges) {
 21226  						goto exit
 21227  					}
 21228  				}
 21229  			}
 21230  		}
 21231  	}
 21232  	if prg.txy == 0 {
 21233  		if prg.tyx == 0 {
 21234  			if prg.txx%0200000 == 0 {
 21235  				if prg.tyy%0200000 == 0 {
 21236  					if prg.txx == 0 || prg.tyy == 0 {
 21237  						prg.tossEdges(prg.curEdges)
 21238  						prg.curExp = int32(prg.getNode(edgeHeaderSize))
 21239  						prg.initEdges(halfword(prg.curExp))
 21240  					} else {
 21241  						if prg.txx < 0 {
 21242  							prg.xReflectEdges()
 21243  							prg.txx = -prg.txx
 21244  						}
 21245  						if prg.tyy < 0 {
 21246  							prg.yReflectEdges()
 21247  							prg.tyy = -prg.tyy
 21248  						}
 21249  						if prg.txx != 0200000 {
 21250  							prg.xScaleEdges(prg.txx / 0200000)
 21251  						}
 21252  						if prg.tyy != 0200000 {
 21253  							prg.yScaleEdges(prg.tyy / 0200000)
 21254  						}
 21255  
 21256  						// Shift the edges by |(tx,ty)|, rounded
 21257  						prg.tx = prg.roundUnscaled(prg.tx)
 21258  						prg.ty = prg.roundUnscaled(prg.ty)
 21259  						if int32(*(*prg.mem[int32(prg.curEdges)+2].hh()).lh())+prg.tx <= 0 || int32(*(*prg.mem[int32(prg.curEdges)+2].hh()).rh())+prg.tx >= 8192 || int32(*(*prg.mem[int32(prg.curEdges)+1].hh()).lh())+prg.ty <= 0 || int32(*(*prg.mem[int32(prg.curEdges)+1].hh()).rh())+prg.ty >= 8191 || abs(prg.tx) >= 4096 || abs(prg.ty) >= 4096 {
 21260  							{
 21261  								if int32(prg.interaction) == errorStopMode {
 21262  								}
 21263  								prg.printNl(strNumber( /* "! " */ 261))
 21264  								prg.print( /* "Too far to shift" */ 867) /* \xref[!\relax]  */
 21265  							}
 21266  							// \xref[Too far to shift]
 21267  							{
 21268  								prg.helpPtr = 3
 21269  								prg.helpLine[2] = /* "I can't shift the picture as requested---it would" */ 868
 21270  								prg.helpLine[1] = /* "make some coordinates too large or too small." */ 537
 21271  								prg.helpLine[0] = /* "Proceed, and I'll omit the transformation." */ 538
 21272  							}
 21273  							prg.putGetError()
 21274  						} else {
 21275  							if prg.tx != 0 {
 21276  								if !(abs(int32(*(*prg.mem[int32(prg.curEdges)+3].hh()).lh())-prg.tx-4096) < 4096) {
 21277  									prg.fixOffset()
 21278  								}
 21279  								*(*prg.mem[int32(prg.curEdges)+2].hh()).lh() = uint16(int32(*(*prg.mem[int32(prg.curEdges)+2].hh()).lh()) + prg.tx)
 21280  								*(*prg.mem[int32(prg.curEdges)+2].hh()).rh() = uint16(int32(*(*prg.mem[int32(prg.curEdges)+2].hh()).rh()) + prg.tx)
 21281  								*(*prg.mem[int32(prg.curEdges)+3].hh()).lh() = uint16(int32(*(*prg.mem[int32(prg.curEdges)+3].hh()).lh()) - prg.tx)
 21282  								*prg.mem[int32(prg.curEdges)+4].int() = 0
 21283  							}
 21284  							if prg.ty != 0 {
 21285  								*(*prg.mem[int32(prg.curEdges)+1].hh()).lh() = uint16(int32(*(*prg.mem[int32(prg.curEdges)+1].hh()).lh()) + prg.ty)
 21286  								*(*prg.mem[int32(prg.curEdges)+1].hh()).rh() = uint16(int32(*(*prg.mem[int32(prg.curEdges)+1].hh()).rh()) + prg.ty)
 21287  								*(*prg.mem[int32(prg.curEdges)+5].hh()).lh() = uint16(int32(*(*prg.mem[int32(prg.curEdges)+5].hh()).lh()) + prg.ty)
 21288  								*prg.mem[int32(prg.curEdges)+4].int() = 0
 21289  							}
 21290  						}
 21291  					}
 21292  
 21293  					goto exit
 21294  				}
 21295  			}
 21296  		}
 21297  	}
 21298  	{
 21299  		if int32(prg.interaction) == errorStopMode {
 21300  		}
 21301  		prg.printNl(strNumber( /* "! " */ 261))
 21302  		prg.print( /* "That transformation is too hard" */ 864) /* \xref[!\relax]  */
 21303  	}
 21304  	// \xref[That transformation...]
 21305  	{
 21306  		prg.helpPtr = 3
 21307  		prg.helpLine[2] = /* "I can apply complicated transformations to paths," */ 865
 21308  		prg.helpLine[1] = /* "but I can only do integer operations on pictures." */ 866
 21309  		prg.helpLine[0] = /* "Proceed, and I'll omit the transformation." */ 538
 21310  	}
 21311  	prg.putGetError()
 21312  
 21313  exit:
 21314  }
 21315  
 21316  // \4
 21317  // Declare subroutines needed by |big_trans|
 21318  func (prg *prg) bilin1(p halfword, t scaled, q halfword, u, delta scaled) {
 21319  	var (
 21320  		r1 halfword // list traverser
 21321  	)
 21322  	if t != 0200000 {
 21323  		prg.depMult(p, t, true)
 21324  	}
 21325  	if u != 0 {
 21326  		if int32(*(*prg.mem[q].hh()).b0()) == known {
 21327  			delta = delta + prg.takeScaled(*prg.mem[int32(q)+1].int(), u)
 21328  		} else {
 21329  			if int32(*(*prg.mem[p].hh()).b0()) != protoDependent {
 21330  				if int32(*(*prg.mem[p].hh()).b0()) == known {
 21331  					prg.newDep(p, prg.constDependency(*prg.mem[int32(p)+1].int()))
 21332  				} else {
 21333  					*(*prg.mem[int32(p)+1].hh()).rh() = prg.pTimesV(*(*prg.mem[int32(p)+1].hh()).rh(), 0200000, smallNumber(dependent), smallNumber(protoDependent), true)
 21334  				}
 21335  				*(*prg.mem[p].hh()).b0() = byte(protoDependent)
 21336  			}
 21337  			*(*prg.mem[int32(p)+1].hh()).rh() = prg.pPlusFq(*(*prg.mem[int32(p)+1].hh()).rh(), u, *(*prg.mem[int32(q)+1].hh()).rh(), smallNumber(protoDependent), *(*prg.mem[q].hh()).b0())
 21338  		}
 21339  	}
 21340  	if int32(*(*prg.mem[p].hh()).b0()) == known {
 21341  		*prg.mem[int32(p)+1].int() = *prg.mem[int32(p)+1].int() + delta
 21342  	} else {
 21343  		r1 = *(*prg.mem[int32(p)+1].hh()).rh()
 21344  		for int32(*(*prg.mem[r1].hh()).lh()) != memMin {
 21345  			r1 = *(*prg.mem[r1].hh()).rh()
 21346  		}
 21347  		delta = *prg.mem[int32(r1)+1].int() + delta
 21348  		if int32(r1) != int32(*(*prg.mem[int32(p)+1].hh()).rh()) {
 21349  			*prg.mem[int32(r1)+1].int() = delta
 21350  		} else {
 21351  			prg.recycleValue(p)
 21352  			*(*prg.mem[p].hh()).b0() = byte(known)
 21353  			*prg.mem[int32(p)+1].int() = delta
 21354  		}
 21355  	}
 21356  	if prg.fixNeeded {
 21357  		prg.fixDependencies()
 21358  	}
 21359  }
 21360  
 21361  func (prg *prg) addMultDep(p halfword, v scaled, r1 halfword) {
 21362  	if int32(*(*prg.mem[r1].hh()).b0()) == known {
 21363  		*prg.mem[int32(prg.depFinal)+1].int() = *prg.mem[int32(prg.depFinal)+1].int() + prg.takeScaled(*prg.mem[int32(r1)+1].int(), v)
 21364  	} else {
 21365  		*(*prg.mem[int32(p)+1].hh()).rh() = prg.pPlusFq(*(*prg.mem[int32(p)+1].hh()).rh(), v, *(*prg.mem[int32(r1)+1].hh()).rh(), smallNumber(protoDependent), *(*prg.mem[r1].hh()).b0())
 21366  		if prg.fixNeeded {
 21367  			prg.fixDependencies()
 21368  		}
 21369  	}
 21370  }
 21371  
 21372  func (prg *prg) bilin2(p, t halfword, v scaled, u, q halfword) {
 21373  	var (
 21374  		vv scaled // temporary storage for |value(p)|
 21375  	)
 21376  	vv = *prg.mem[int32(p)+1].int()
 21377  	*(*prg.mem[p].hh()).b0() = byte(protoDependent)
 21378  	prg.newDep(p, prg.constDependency(scaled(0))) // this sets |dep_final|
 21379  	if vv != 0 {
 21380  		prg.addMultDep(p, vv, t)
 21381  	} // |dep_final| doesn't change
 21382  	if v != 0 {
 21383  		prg.addMultDep(p, v, u)
 21384  	}
 21385  	if int32(q) != memMin {
 21386  		prg.addMultDep(p, scaled(0200000), q)
 21387  	}
 21388  	if int32(*(*prg.mem[int32(p)+1].hh()).rh()) == int32(prg.depFinal) {
 21389  		vv = *prg.mem[int32(prg.depFinal)+1].int()
 21390  		prg.recycleValue(p)
 21391  		*(*prg.mem[p].hh()).b0() = byte(known)
 21392  		*prg.mem[int32(p)+1].int() = vv
 21393  	}
 21394  }
 21395  
 21396  func (prg *prg) bilin3(p halfword, t, v, u, delta scaled) {
 21397  	if t != 0200000 {
 21398  		delta = delta + prg.takeScaled(*prg.mem[int32(p)+1].int(), t)
 21399  	} else {
 21400  		delta = delta + *prg.mem[int32(p)+1].int()
 21401  	}
 21402  	if u != 0 {
 21403  		*prg.mem[int32(p)+1].int() = delta + prg.takeScaled(v, u)
 21404  	} else {
 21405  		*prg.mem[int32(p)+1].int() = delta
 21406  	}
 21407  }
 21408  
 21409  func (prg *prg) bigTrans(p halfword, c quarterword) {
 21410  	var (
 21411  		q, r1, pp, qq halfword    // list manipulation registers
 21412  		s             smallNumber // size of a big node
 21413  	)
 21414  	s = prg.bigNodeSize[*(*prg.mem[p].hh()).b0()-13]
 21415  	q = uint16(*prg.mem[int32(p)+1].int())
 21416  	r1 = uint16(int32(q) + int32(s))
 21417  	for {
 21418  		r1 = uint16(int32(r1) - 2)
 21419  		if int32(*(*prg.mem[r1].hh()).b0()) != known {
 21420  			prg.setUpKnownTrans(c)
 21421  			prg.makeExpCopy(p)
 21422  			r1 = uint16(*prg.mem[prg.curExp+1].int())
 21423  			if int32(prg.curType) == transformType {
 21424  				prg.bilin1(halfword(int32(r1)+10), prg.tyy, halfword(int32(q)+6), prg.tyx, scaled(0))
 21425  				prg.bilin1(halfword(int32(r1)+8), prg.tyy, halfword(int32(q)+4), prg.tyx, scaled(0))
 21426  				prg.bilin1(halfword(int32(r1)+6), prg.txx, halfword(int32(q)+10), prg.txy, scaled(0))
 21427  				prg.bilin1(halfword(int32(r1)+4), prg.txx, halfword(int32(q)+8), prg.txy, scaled(0))
 21428  			}
 21429  			prg.bilin1(halfword(int32(r1)+2), prg.tyy, q, prg.tyx, prg.ty)
 21430  			prg.bilin1(r1, prg.txx, halfword(int32(q)+2), prg.txy, prg.tx)
 21431  
 21432  			goto exit
 21433  		}
 21434  		if int32(r1) == int32(q) {
 21435  			break
 21436  		}
 21437  	}
 21438  
 21439  	// Transform a known big node
 21440  	prg.setUpTrans(c)
 21441  	if int32(prg.curType) == known {
 21442  		prg.makeExpCopy(p)
 21443  		r1 = uint16(*prg.mem[prg.curExp+1].int())
 21444  		if int32(prg.curType) == transformType {
 21445  			prg.bilin3(halfword(int32(r1)+10), prg.tyy, *prg.mem[int32(q)+6+1].int(), prg.tyx, scaled(0))
 21446  			prg.bilin3(halfword(int32(r1)+8), prg.tyy, *prg.mem[int32(q)+4+1].int(), prg.tyx, scaled(0))
 21447  			prg.bilin3(halfword(int32(r1)+6), prg.txx, *prg.mem[int32(q)+10+1].int(), prg.txy, scaled(0))
 21448  			prg.bilin3(halfword(int32(r1)+4), prg.txx, *prg.mem[int32(q)+8+1].int(), prg.txy, scaled(0))
 21449  		}
 21450  		prg.bilin3(halfword(int32(r1)+2), prg.tyy, *prg.mem[int32(q)+1].int(), prg.tyx, prg.ty)
 21451  		prg.bilin3(r1, prg.txx, *prg.mem[int32(q)+2+1].int(), prg.txy, prg.tx)
 21452  	} else {
 21453  		pp = prg.stashCurExp()
 21454  		qq = uint16(*prg.mem[int32(pp)+1].int())
 21455  		prg.makeExpCopy(p)
 21456  		r1 = uint16(*prg.mem[prg.curExp+1].int())
 21457  		if int32(prg.curType) == transformType {
 21458  			prg.bilin2(halfword(int32(r1)+10), halfword(int32(qq)+10), *prg.mem[int32(q)+6+1].int(), halfword(int32(qq)+8), halfword(memMin))
 21459  			prg.bilin2(halfword(int32(r1)+8), halfword(int32(qq)+10), *prg.mem[int32(q)+4+1].int(), halfword(int32(qq)+8), halfword(memMin))
 21460  			prg.bilin2(halfword(int32(r1)+6), halfword(int32(qq)+4), *prg.mem[int32(q)+10+1].int(), halfword(int32(qq)+6), halfword(memMin))
 21461  			prg.bilin2(halfword(int32(r1)+4), halfword(int32(qq)+4), *prg.mem[int32(q)+8+1].int(), halfword(int32(qq)+6), halfword(memMin))
 21462  		}
 21463  		prg.bilin2(halfword(int32(r1)+2), halfword(int32(qq)+10), *prg.mem[int32(q)+1].int(), halfword(int32(qq)+8), halfword(int32(qq)+2))
 21464  		prg.bilin2(r1, halfword(int32(qq)+4), *prg.mem[int32(q)+2+1].int(), halfword(int32(qq)+6), qq)
 21465  		prg.recycleValue(pp)
 21466  		prg.freeNode(pp, halfword(valueNodeSize))
 21467  	}
 21468  
 21469  exit:
 21470  } // node |p| will now be recycled by |do_binary|
 21471  
 21472  func (prg *prg) cat(p halfword) {
 21473  	var (
 21474  		a, b strNumber   // the strings being concatenated
 21475  		k    poolPointer // index into |str_pool|
 21476  	)
 21477  	a = uint16(*prg.mem[int32(p)+1].int())
 21478  	b = uint16(prg.curExp)
 21479  	{
 21480  		if int32(prg.poolPtr)+(int32(prg.strStart[int32(a)+1])-int32(prg.strStart[a]))+(int32(prg.strStart[int32(b)+1])-int32(prg.strStart[b])) > int32(prg.maxPoolPtr) {
 21481  			if int32(prg.poolPtr)+(int32(prg.strStart[int32(a)+1])-int32(prg.strStart[a]))+(int32(prg.strStart[int32(b)+1])-int32(prg.strStart[b])) > poolSize {
 21482  				prg.overflow(strNumber( /* "pool size" */ 257), poolSize-int32(prg.initPoolPtr))
 21483  			} /* \xref[METAFONT capacity exceeded pool size][\quad pool size]  */
 21484  			prg.maxPoolPtr = uint16(int32(prg.poolPtr) + (int32(prg.strStart[int32(a)+1]) - int32(prg.strStart[a])) + (int32(prg.strStart[int32(b)+1]) - int32(prg.strStart[b])))
 21485  		}
 21486  	}
 21487  	for ii := int32(prg.strStart[a]); ii <= int32(prg.strStart[int32(a)+1])-1; ii++ {
 21488  		k = poolPointer(ii)
 21489  		_ = k
 21490  		prg.strPool[prg.poolPtr] = prg.strPool[k]
 21491  		prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
 21492  	}
 21493  	for ii := int32(prg.strStart[b]); ii <= int32(prg.strStart[int32(b)+1])-1; ii++ {
 21494  		k = poolPointer(ii)
 21495  		_ = k
 21496  		prg.strPool[prg.poolPtr] = prg.strPool[k]
 21497  		prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
 21498  	}
 21499  	prg.curExp = int32(prg.makeString())
 21500  	{
 21501  		if int32(prg.strRef[b]) < maxStrRef {
 21502  			if int32(prg.strRef[b]) > 1 {
 21503  				prg.strRef[b] = byte(int32(prg.strRef[b]) - 1)
 21504  			} else {
 21505  				prg.flushString(b)
 21506  			}
 21507  		}
 21508  	}
 21509  }
 21510  
 21511  func (prg *prg) chopString(p halfword) {
 21512  	var (
 21513  		a, b     int32     // start and stop points
 21514  		l        int32     // length of the original string
 21515  		k        int32     // runs from |a| to |b|
 21516  		s        strNumber // the original string
 21517  		reversed bool      // was |a>b|?
 21518  	)
 21519  	a = prg.roundUnscaled(*prg.mem[int32(p)+1].int())
 21520  	b = prg.roundUnscaled(*prg.mem[int32(p)+2+1].int())
 21521  	if a <= b {
 21522  		reversed = false
 21523  	} else {
 21524  		reversed = true
 21525  		k = a
 21526  		a = b
 21527  		b = k
 21528  	}
 21529  	s = uint16(prg.curExp)
 21530  	l = int32(prg.strStart[int32(s)+1]) - int32(prg.strStart[s])
 21531  	if a < 0 {
 21532  		a = 0
 21533  		if b < 0 {
 21534  			b = 0
 21535  		}
 21536  	}
 21537  	if b > l {
 21538  		b = l
 21539  		if a > l {
 21540  			a = l
 21541  		}
 21542  	}
 21543  	{
 21544  		if int32(prg.poolPtr)+b-a > int32(prg.maxPoolPtr) {
 21545  			if int32(prg.poolPtr)+b-a > poolSize {
 21546  				prg.overflow(strNumber( /* "pool size" */ 257), poolSize-int32(prg.initPoolPtr))
 21547  			} /* \xref[METAFONT capacity exceeded pool size][\quad pool size]  */
 21548  			prg.maxPoolPtr = uint16(int32(prg.poolPtr) + b - a)
 21549  		}
 21550  	}
 21551  	if reversed {
 21552  		for ii := int32(prg.strStart[s]) + b - 1; ii >= int32(prg.strStart[s])+a; ii-- {
 21553  			k = ii
 21554  			_ = k
 21555  			prg.strPool[prg.poolPtr] = prg.strPool[k]
 21556  			prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
 21557  		}
 21558  	} else {
 21559  		for ii := int32(prg.strStart[s]) + a; ii <= int32(prg.strStart[s])+b-1; ii++ {
 21560  			k = ii
 21561  			_ = k
 21562  			prg.strPool[prg.poolPtr] = prg.strPool[k]
 21563  			prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
 21564  		}
 21565  	}
 21566  	prg.curExp = int32(prg.makeString())
 21567  	{
 21568  		if int32(prg.strRef[s]) < maxStrRef {
 21569  			if int32(prg.strRef[s]) > 1 {
 21570  				prg.strRef[s] = byte(int32(prg.strRef[s]) - 1)
 21571  			} else {
 21572  				prg.flushString(s)
 21573  			}
 21574  		}
 21575  	}
 21576  }
 21577  
 21578  func (prg *prg) chopPath(p halfword) {
 21579  	var (
 21580  		q              halfword // a knot in the original path
 21581  		pp, qq, rr, ss halfword // link variables for copies of path nodes
 21582  		a, b, k, l     scaled   // indices for chopping
 21583  		reversed       bool     // was |a>b|?
 21584  	)
 21585  	l = prg.pathLength()
 21586  	a = *prg.mem[int32(p)+1].int()
 21587  	b = *prg.mem[int32(p)+2+1].int()
 21588  	if a <= b {
 21589  		reversed = false
 21590  	} else {
 21591  		reversed = true
 21592  		k = a
 21593  		a = b
 21594  		b = k
 21595  	}
 21596  
 21597  	// Dispense with the cases |a<0| and/or |b>l|
 21598  	if a < 0 {
 21599  		if int32(*(*prg.mem[prg.curExp].hh()).b0()) == endpoint {
 21600  			a = 0
 21601  			if b < 0 {
 21602  				b = 0
 21603  			}
 21604  		} else {
 21605  			for {
 21606  				a = a + l
 21607  				b = b + l
 21608  				if a >= 0 {
 21609  					break
 21610  				}
 21611  			}
 21612  		}
 21613  	} // a cycle always has length |l>0|
 21614  	if b > l {
 21615  		if int32(*(*prg.mem[prg.curExp].hh()).b0()) == endpoint {
 21616  			b = l
 21617  			if a > l {
 21618  				a = l
 21619  			}
 21620  		} else {
 21621  			for a >= l {
 21622  				a = a - l
 21623  				b = b - l
 21624  			}
 21625  		}
 21626  	}
 21627  	q = uint16(prg.curExp)
 21628  	for a >= 0200000 {
 21629  		q = *(*prg.mem[q].hh()).rh()
 21630  		a = a - 0200000
 21631  		b = b - 0200000
 21632  	}
 21633  	if b == a {
 21634  		if a > 0 {
 21635  			qq = *(*prg.mem[q].hh()).rh()
 21636  			prg.splitCubic(q, a*010000, *prg.mem[int32(qq)+1].int(), *prg.mem[int32(qq)+2].int())
 21637  			q = *(*prg.mem[q].hh()).rh()
 21638  		}
 21639  		pp = prg.copyKnot(q)
 21640  		qq = pp
 21641  	} else {
 21642  		// Construct a path from |pp| to |qq| of length $\lceil b\rceil$
 21643  		pp = prg.copyKnot(q)
 21644  		qq = pp
 21645  		for {
 21646  			q = *(*prg.mem[q].hh()).rh()
 21647  			rr = qq
 21648  			qq = prg.copyKnot(q)
 21649  			*(*prg.mem[rr].hh()).rh() = qq
 21650  			b = b - 0200000
 21651  			if b <= 0 {
 21652  				break
 21653  			}
 21654  		}
 21655  		if a > 0 {
 21656  			ss = pp
 21657  			pp = *(*prg.mem[pp].hh()).rh()
 21658  			prg.splitCubic(ss, a*010000, *prg.mem[int32(pp)+1].int(), *prg.mem[int32(pp)+2].int())
 21659  			pp = *(*prg.mem[ss].hh()).rh()
 21660  			prg.freeNode(ss, halfword(knotNodeSize))
 21661  			if int32(rr) == int32(ss) {
 21662  				b = prg.makeScaled(b, 0200000-a)
 21663  				rr = pp
 21664  			}
 21665  		}
 21666  		if b < 0 {
 21667  			prg.splitCubic(rr, (b+0200000)*010000, *prg.mem[int32(qq)+1].int(), *prg.mem[int32(qq)+2].int())
 21668  			prg.freeNode(qq, halfword(knotNodeSize))
 21669  			qq = *(*prg.mem[rr].hh()).rh()
 21670  		}
 21671  	}
 21672  	*(*prg.mem[pp].hh()).b0() = byte(endpoint)
 21673  	*(*prg.mem[qq].hh()).b1() = byte(endpoint)
 21674  	*(*prg.mem[qq].hh()).rh() = pp
 21675  	prg.tossKnotList(halfword(prg.curExp))
 21676  	if reversed {
 21677  		prg.curExp = int32(*(*prg.mem[prg.htapYpoc(pp)].hh()).rh())
 21678  		prg.tossKnotList(pp)
 21679  	} else {
 21680  		prg.curExp = int32(pp)
 21681  	}
 21682  }
 21683  
 21684  func (prg *prg) pairValue(x, y scaled) {
 21685  	var (
 21686  		p halfword // a pair node
 21687  	)
 21688  	p = prg.getNode(valueNodeSize)
 21689  	prg.flushCurExp(scaled(p))
 21690  	prg.curType = byte(pairType)
 21691  	*(*prg.mem[p].hh()).b0() = byte(pairType)
 21692  	*(*prg.mem[p].hh()).b1() = byte(capsule)
 21693  	prg.initBigNode(p)
 21694  	p = uint16(*prg.mem[int32(p)+1].int())
 21695  
 21696  	*(*prg.mem[p].hh()).b0() = byte(known)
 21697  	*prg.mem[int32(p)+1].int() = x
 21698  
 21699  	*(*prg.mem[int32(p)+2].hh()).b0() = byte(known)
 21700  	*prg.mem[int32(p)+2+1].int() = y
 21701  
 21702  }
 21703  
 21704  func (prg *prg) setUpOffset(p halfword) {
 21705  	prg.findOffset(*prg.mem[int32(p)+1].int(), *prg.mem[int32(p)+2+1].int(), halfword(prg.curExp))
 21706  	prg.pairValue(prg.curX, prg.curY)
 21707  }
 21708  
 21709  func (prg *prg) setUpDirectionTime(p halfword) {
 21710  	prg.flushCurExp(prg.findDirectionTime(*prg.mem[int32(p)+1].int(), *prg.mem[int32(p)+2+1].int(), halfword(prg.curExp)))
 21711  }
 21712  
 21713  func (prg *prg) findPoint(v scaled, c quarterword) {
 21714  	var (
 21715  		p halfword // the path
 21716  		n scaled   // its length
 21717  		q halfword // successor of |p|
 21718  	)
 21719  	p = uint16(prg.curExp)
 21720  
 21721  	if int32(*(*prg.mem[p].hh()).b0()) == endpoint {
 21722  		n = -0200000
 21723  	} else {
 21724  		n = 0
 21725  	}
 21726  	for {
 21727  		p = *(*prg.mem[p].hh()).rh()
 21728  		n = n + 0200000
 21729  		if int32(p) == prg.curExp {
 21730  			break
 21731  		}
 21732  	}
 21733  	if n == 0 {
 21734  		v = 0
 21735  	} else if v < 0 {
 21736  		if int32(*(*prg.mem[p].hh()).b0()) == endpoint {
 21737  			v = 0
 21738  		} else {
 21739  			v = n - 1 - (-v-1)%n
 21740  		}
 21741  	} else if v > n {
 21742  		if int32(*(*prg.mem[p].hh()).b0()) == endpoint {
 21743  			v = n
 21744  		} else {
 21745  			v = v % n
 21746  		}
 21747  	}
 21748  	p = uint16(prg.curExp)
 21749  	for v >= 0200000 {
 21750  		p = *(*prg.mem[p].hh()).rh()
 21751  		v = v - 0200000
 21752  	}
 21753  	if v != 0 {
 21754  		q = *(*prg.mem[p].hh()).rh()
 21755  		prg.splitCubic(p, v*010000, *prg.mem[int32(q)+1].int(), *prg.mem[int32(q)+2].int())
 21756  		p = *(*prg.mem[p].hh()).rh()
 21757  	}
 21758  
 21759  	// Set the current expression to the desired path coordinates
 21760  	switch c {
 21761  	case pointOf:
 21762  		prg.pairValue(*prg.mem[int32(p)+1].int(), *prg.mem[int32(p)+2].int())
 21763  	case precontrolOf:
 21764  		if int32(*(*prg.mem[p].hh()).b0()) == endpoint {
 21765  			prg.pairValue(*prg.mem[int32(p)+1].int(), *prg.mem[int32(p)+2].int())
 21766  		} else {
 21767  			prg.pairValue(*prg.mem[int32(p)+3].int(), *prg.mem[int32(p)+4].int())
 21768  		}
 21769  	case postcontrolOf:
 21770  		if int32(*(*prg.mem[p].hh()).b1()) == endpoint {
 21771  			prg.pairValue(*prg.mem[int32(p)+1].int(), *prg.mem[int32(p)+2].int())
 21772  		} else {
 21773  			prg.pairValue(*prg.mem[int32(p)+5].int(), *prg.mem[int32(p)+6].int())
 21774  		}
 21775  	}
 21776  }
 21777  
 21778  func (prg *prg) doBinary(p halfword, c quarterword) {
 21779  	var (
 21780  		q, r1, rr    halfword // for list manipulation
 21781  		oldP, oldExp halfword // capsules to recycle
 21782  		v            int32    // for numeric manipulation
 21783  	)
 21784  	{
 21785  		if prg.arithError {
 21786  			prg.clearArith()
 21787  		}
 21788  	}
 21789  	if prg.internal[tracingCommands-1] > 0400000 {
 21790  		prg.beginDiagnostic()
 21791  		prg.printNl(strNumber( /* "[(" */ 850))
 21792  		prg.printExp(p, smallNumber(0)) // show the operand, but not verbosely
 21793  		prg.printChar(asciiCode(')'))
 21794  		prg.printOp(c)
 21795  		prg.printChar(asciiCode('('))
 21796  
 21797  		prg.printExp(halfword(memMin), smallNumber(0))
 21798  		prg.print( /* ")]" */ 842)
 21799  		prg.endDiagnostic(false)
 21800  	}
 21801  
 21802  	// Sidestep |independent| cases in capsule |p|
 21803  	switch *(*prg.mem[p].hh()).b0() {
 21804  	case transformType, pairType:
 21805  		oldP = prg.tarnished(p)
 21806  	case independent:
 21807  		oldP = uint16(memMin + 1)
 21808  
 21809  	default:
 21810  		oldP = uint16(memMin)
 21811  	}
 21812  	if int32(oldP) != memMin {
 21813  		q = prg.stashCurExp()
 21814  		oldP = p
 21815  		prg.makeExpCopy(oldP)
 21816  		p = prg.stashCurExp()
 21817  		prg.unstashCurExp(q)
 21818  	}
 21819  
 21820  	// Sidestep |independent| cases in the current expression
 21821  	switch prg.curType {
 21822  	case transformType, pairType:
 21823  		oldExp = prg.tarnished(halfword(prg.curExp))
 21824  	case independent:
 21825  		oldExp = uint16(memMin + 1)
 21826  
 21827  	default:
 21828  		oldExp = uint16(memMin)
 21829  	}
 21830  	if int32(oldExp) != memMin {
 21831  		oldExp = uint16(prg.curExp)
 21832  		prg.makeExpCopy(oldExp)
 21833  	}
 21834  	switch c {
 21835  	case plus, minus:
 21836  		// Add or subtract the current expression from |p|
 21837  		if int32(prg.curType) < pairType || int32(*(*prg.mem[p].hh()).b0()) < pairType {
 21838  			if int32(prg.curType) == pictureType && int32(*(*prg.mem[p].hh()).b0()) == pictureType {
 21839  				if int32(c) == minus {
 21840  					prg.negateEdges(halfword(prg.curExp))
 21841  				}
 21842  				prg.curEdges = uint16(prg.curExp)
 21843  				prg.mergeEdges(halfword(*prg.mem[int32(p)+1].int()))
 21844  			} else {
 21845  				prg.badBinary(p, c)
 21846  			}
 21847  		} else if int32(prg.curType) == pairType {
 21848  			if int32(*(*prg.mem[p].hh()).b0()) != pairType {
 21849  				prg.badBinary(p, c)
 21850  			} else {
 21851  				q = uint16(*prg.mem[int32(p)+1].int())
 21852  				r1 = uint16(*prg.mem[prg.curExp+1].int())
 21853  				prg.addOrSubtract(q, r1, c)
 21854  				prg.addOrSubtract(halfword(int32(q)+2), halfword(int32(r1)+2), c)
 21855  			}
 21856  		} else if int32(*(*prg.mem[p].hh()).b0()) == pairType {
 21857  			prg.badBinary(p, c)
 21858  		} else {
 21859  			prg.addOrSubtract(p, halfword(memMin), c)
 21860  		}
 21861  
 21862  	// \4
 21863  	// Additional cases of binary operators
 21864  	case lessThan, lessOrEqual, greaterThan, greaterOrEqual,
 21865  		equalTo, unequalTo:
 21866  		if int32(prg.curType) > pairType && int32(*(*prg.mem[p].hh()).b0()) > pairType {
 21867  			prg.addOrSubtract(p, halfword(memMin), quarterword(minus))
 21868  		} else if int32(prg.curType) != int32(*(*prg.mem[p].hh()).b0()) {
 21869  			prg.badBinary(p, c)
 21870  			goto done
 21871  		} else if int32(prg.curType) == stringType {
 21872  			prg.flushCurExp(prg.strVsStr(strNumber(*prg.mem[int32(p)+1].int()), strNumber(prg.curExp)))
 21873  		} else if int32(prg.curType) == unknownString || int32(prg.curType) == unknownBoolean {
 21874  			q = uint16(*prg.mem[prg.curExp+1].int())
 21875  			for int32(q) != prg.curExp && int32(q) != int32(p) {
 21876  				q = uint16(*prg.mem[int32(q)+1].int())
 21877  			}
 21878  			if int32(q) == int32(p) {
 21879  				prg.flushCurExp(scaled(0))
 21880  			}
 21881  		} else if int32(prg.curType) == pairType || int32(prg.curType) == transformType {
 21882  			q = uint16(*prg.mem[int32(p)+1].int())
 21883  			r1 = uint16(*prg.mem[prg.curExp+1].int())
 21884  			rr = uint16(int32(r1) + int32(prg.bigNodeSize[prg.curType-13]) - 2)
 21885  			for true {
 21886  				prg.addOrSubtract(q, r1, quarterword(minus))
 21887  				if int32(*(*prg.mem[r1].hh()).b0()) != known {
 21888  					goto done1
 21889  				}
 21890  				if *prg.mem[int32(r1)+1].int() != 0 {
 21891  					goto done1
 21892  				}
 21893  				if int32(r1) == int32(rr) {
 21894  					goto done1
 21895  				}
 21896  				q = uint16(int32(q) + 2)
 21897  				r1 = uint16(int32(r1) + 2)
 21898  			}
 21899  
 21900  		done1:
 21901  			prg.takePart(quarterword(xPart + (int32(r1)-*prg.mem[prg.curExp+1].int())/2))
 21902  		} else if int32(prg.curType) == booleanType {
 21903  			prg.flushCurExp(prg.curExp - *prg.mem[int32(p)+1].int())
 21904  		} else {
 21905  			prg.badBinary(p, c)
 21906  			goto done
 21907  		}
 21908  
 21909  		// Compare the current expression with zero
 21910  		if int32(prg.curType) != known {
 21911  			if int32(prg.curType) < known {
 21912  				prg.dispErr(p, strNumber( /* "" */ 285))
 21913  				{
 21914  					prg.helpPtr = 1
 21915  					prg.helpLine[0] = /* "The quantities shown above have not been equated." */ 851
 21916  				}
 21917  			} else {
 21918  				prg.helpPtr = 2
 21919  				prg.helpLine[1] = /* "Oh dear. I can't decide if the expression above is positive," */ 852
 21920  				prg.helpLine[0] = /* "negative, or zero. So this comparison test won't be `true'." */ 853
 21921  			}
 21922  			prg.dispErr(halfword(memMin), strNumber( /* "Unknown relation will be considered false" */ 854))
 21923  			// \xref[Unknown relation...]
 21924  			prg.putGetFlushError(falseCode)
 21925  		} else {
 21926  			switch c {
 21927  			case lessThan:
 21928  				if prg.curExp < 0 {
 21929  					prg.curExp = trueCode
 21930  				} else {
 21931  					prg.curExp = falseCode
 21932  				}
 21933  			case lessOrEqual:
 21934  				if prg.curExp <= 0 {
 21935  					prg.curExp = trueCode
 21936  				} else {
 21937  					prg.curExp = falseCode
 21938  				}
 21939  			case greaterThan:
 21940  				if prg.curExp > 0 {
 21941  					prg.curExp = trueCode
 21942  				} else {
 21943  					prg.curExp = falseCode
 21944  				}
 21945  			case greaterOrEqual:
 21946  				if prg.curExp >= 0 {
 21947  					prg.curExp = trueCode
 21948  				} else {
 21949  					prg.curExp = falseCode
 21950  				}
 21951  			case equalTo:
 21952  				if prg.curExp == 0 {
 21953  					prg.curExp = trueCode
 21954  				} else {
 21955  					prg.curExp = falseCode
 21956  				}
 21957  			case unequalTo:
 21958  				if prg.curExp != 0 {
 21959  					prg.curExp = trueCode
 21960  				} else {
 21961  					prg.curExp = falseCode
 21962  				}
 21963  			}
 21964  		} // there are no other cases
 21965  		prg.curType = byte(booleanType)
 21966  
 21967  	done:
 21968  		;
 21969  
 21970  	case andOp, orOp:
 21971  		if int32(*(*prg.mem[p].hh()).b0()) != booleanType || int32(prg.curType) != booleanType {
 21972  			prg.badBinary(p, c)
 21973  		} else if *prg.mem[int32(p)+1].int() == int32(c)+falseCode-andOp {
 21974  			prg.curExp = *prg.mem[int32(p)+1].int()
 21975  		}
 21976  
 21977  	case times:
 21978  		if int32(prg.curType) < pairType || int32(*(*prg.mem[p].hh()).b0()) < pairType {
 21979  			prg.badBinary(p, quarterword(times))
 21980  		} else if int32(prg.curType) == known || int32(*(*prg.mem[p].hh()).b0()) == known {
 21981  			if int32(*(*prg.mem[p].hh()).b0()) == known {
 21982  				v = *prg.mem[int32(p)+1].int()
 21983  				prg.freeNode(p, halfword(valueNodeSize))
 21984  			} else {
 21985  				v = prg.curExp
 21986  				prg.unstashCurExp(p)
 21987  			}
 21988  			if int32(prg.curType) == known {
 21989  				prg.curExp = prg.takeScaled(prg.curExp, v)
 21990  			} else if int32(prg.curType) == pairType {
 21991  				p = uint16(*prg.mem[prg.curExp+1].int())
 21992  				prg.depMult(p, v, true)
 21993  				prg.depMult(halfword(int32(p)+2), v, true)
 21994  			} else {
 21995  				prg.depMult(halfword(memMin), v, true)
 21996  			}
 21997  
 21998  			goto exit
 21999  		} else if prg.nicePair(int32(p), *(*prg.mem[p].hh()).b0()) && int32(prg.curType) > pairType || prg.nicePair(prg.curExp, prg.curType) && int32(*(*prg.mem[p].hh()).b0()) > pairType {
 22000  			prg.hardTimes(p)
 22001  			goto exit
 22002  		} else {
 22003  			prg.badBinary(p, quarterword(times))
 22004  		}
 22005  
 22006  	case over:
 22007  		if int32(prg.curType) != known || int32(*(*prg.mem[p].hh()).b0()) < pairType {
 22008  			prg.badBinary(p, quarterword(over))
 22009  		} else {
 22010  			v = prg.curExp
 22011  			prg.unstashCurExp(p)
 22012  			if v == 0 {
 22013  				prg.dispErr(halfword(memMin), strNumber( /* "Division by zero" */ 784))
 22014  				// \xref[Division by zero]
 22015  				{
 22016  					prg.helpPtr = 2
 22017  					prg.helpLine[1] = /* "You're trying to divide the quantity shown above the error" */ 856
 22018  					prg.helpLine[0] = /* "message by zero. I'm going to divide it by one instead." */ 857
 22019  				}
 22020  				prg.putGetError()
 22021  			} else {
 22022  				if int32(prg.curType) == known {
 22023  					prg.curExp = prg.makeScaled(prg.curExp, v)
 22024  				} else if int32(prg.curType) == pairType {
 22025  					p = uint16(*prg.mem[prg.curExp+1].int())
 22026  					prg.depDiv(p, v)
 22027  					prg.depDiv(halfword(int32(p)+2), v)
 22028  				} else {
 22029  					prg.depDiv(halfword(memMin), v)
 22030  				}
 22031  			}
 22032  
 22033  			goto exit
 22034  		}
 22035  
 22036  	case pythagAdd, pythagSub:
 22037  		if int32(prg.curType) == known && int32(*(*prg.mem[p].hh()).b0()) == known {
 22038  			if int32(c) == pythagAdd {
 22039  				prg.curExp = prg.pythAdd(*prg.mem[int32(p)+1].int(), prg.curExp)
 22040  			} else {
 22041  				prg.curExp = prg.pythSub(*prg.mem[int32(p)+1].int(), prg.curExp)
 22042  			}
 22043  		} else {
 22044  			prg.badBinary(p, c)
 22045  		}
 22046  
 22047  	case rotatedBy, slantedBy, scaledBy, shiftedBy,
 22048  		transformedBy, xScaled, yScaled, zScaled: //
 22049  
 22050  		if int32(*(*prg.mem[p].hh()).b0()) == pathType || int32(*(*prg.mem[p].hh()).b0()) == futurePen || int32(*(*prg.mem[p].hh()).b0()) == penType {
 22051  			prg.pathTrans(p, c)
 22052  			goto exit
 22053  		} else if int32(*(*prg.mem[p].hh()).b0()) == pairType || int32(*(*prg.mem[p].hh()).b0()) == transformType {
 22054  			prg.bigTrans(p, c)
 22055  		} else if int32(*(*prg.mem[p].hh()).b0()) == pictureType {
 22056  			prg.edgesTrans(p, c)
 22057  			goto exit
 22058  		} else {
 22059  			prg.badBinary(p, c)
 22060  		}
 22061  
 22062  	case concatenate:
 22063  		if int32(prg.curType) == stringType && int32(*(*prg.mem[p].hh()).b0()) == stringType {
 22064  			prg.cat(p)
 22065  		} else {
 22066  			prg.badBinary(p, quarterword(concatenate))
 22067  		}
 22068  	case substringOf:
 22069  		if prg.nicePair(int32(p), *(*prg.mem[p].hh()).b0()) && int32(prg.curType) == stringType {
 22070  			prg.chopString(halfword(*prg.mem[int32(p)+1].int()))
 22071  		} else {
 22072  			prg.badBinary(p, quarterword(substringOf))
 22073  		}
 22074  	case subpathOf:
 22075  		if int32(prg.curType) == pairType {
 22076  			prg.pairToPath()
 22077  		}
 22078  		if prg.nicePair(int32(p), *(*prg.mem[p].hh()).b0()) && int32(prg.curType) == pathType {
 22079  			prg.chopPath(halfword(*prg.mem[int32(p)+1].int()))
 22080  		} else {
 22081  			prg.badBinary(p, quarterword(subpathOf))
 22082  		}
 22083  
 22084  	case pointOf, precontrolOf, postcontrolOf:
 22085  		if int32(prg.curType) == pairType {
 22086  			prg.pairToPath()
 22087  		}
 22088  		if int32(prg.curType) == pathType && int32(*(*prg.mem[p].hh()).b0()) == known {
 22089  			prg.findPoint(*prg.mem[int32(p)+1].int(), c)
 22090  		} else {
 22091  			prg.badBinary(p, c)
 22092  		}
 22093  
 22094  	case penOffsetOf:
 22095  		if int32(prg.curType) == futurePen {
 22096  			prg.materializePen()
 22097  		}
 22098  		if int32(prg.curType) == penType && prg.nicePair(int32(p), *(*prg.mem[p].hh()).b0()) {
 22099  			prg.setUpOffset(halfword(*prg.mem[int32(p)+1].int()))
 22100  		} else {
 22101  			prg.badBinary(p, quarterword(penOffsetOf))
 22102  		}
 22103  
 22104  	case directionTimeOf:
 22105  		if int32(prg.curType) == pairType {
 22106  			prg.pairToPath()
 22107  		}
 22108  		if int32(prg.curType) == pathType && prg.nicePair(int32(p), *(*prg.mem[p].hh()).b0()) {
 22109  			prg.setUpDirectionTime(halfword(*prg.mem[int32(p)+1].int()))
 22110  		} else {
 22111  			prg.badBinary(p, quarterword(directionTimeOf))
 22112  		}
 22113  
 22114  	case intersect:
 22115  		if int32(*(*prg.mem[p].hh()).b0()) == pairType {
 22116  			q = prg.stashCurExp()
 22117  			prg.unstashCurExp(p)
 22118  			prg.pairToPath()
 22119  			p = prg.stashCurExp()
 22120  			prg.unstashCurExp(q)
 22121  		}
 22122  		if int32(prg.curType) == pairType {
 22123  			prg.pairToPath()
 22124  		}
 22125  		if int32(prg.curType) == pathType && int32(*(*prg.mem[p].hh()).b0()) == pathType {
 22126  			prg.pathIntersection(halfword(*prg.mem[int32(p)+1].int()), halfword(prg.curExp))
 22127  			prg.pairValue(prg.curT, prg.curTt)
 22128  		} else {
 22129  			prg.badBinary(p, quarterword(intersect))
 22130  		}
 22131  
 22132  	} // there are no other cases
 22133  	prg.recycleValue(p)
 22134  	prg.freeNode(p, halfword(valueNodeSize)) // |return| to avoid this
 22135  	// |return| to avoid this
 22136  exit:
 22137  	{
 22138  		if prg.arithError {
 22139  			prg.clearArith()
 22140  		}
 22141  	}
 22142  	// Recycle any sidestepped |independent| capsules
 22143  	if int32(oldP) != memMin {
 22144  		prg.recycleValue(oldP)
 22145  		prg.freeNode(oldP, halfword(valueNodeSize))
 22146  	}
 22147  	if int32(oldExp) != memMin {
 22148  		prg.recycleValue(oldExp)
 22149  		prg.freeNode(oldExp, halfword(valueNodeSize))
 22150  	}
 22151  }
 22152  
 22153  // 944.
 22154  
 22155  // tangle:pos ../../mf.web:18630:3:
 22156  
 22157  // Here is a routine that is similar to |times|; but it is invoked only
 22158  // internally, when |v| is a |fraction| whose magnitude is at most~1,
 22159  // and when |cur_type>=pair_type|.
 22160  func (prg *prg) fracMult(n, d scaled) { // multiplies |cur_exp| by |n/d|
 22161  	var (
 22162  		p      halfword // a pair node
 22163  		oldExp halfword // a capsule to recycle
 22164  		v      fraction // |n/d|
 22165  	)
 22166  	if prg.internal[tracingCommands-1] > 0400000 {
 22167  		prg.beginDiagnostic()
 22168  		prg.printNl(strNumber( /* "[(" */ 850))
 22169  		prg.printScaled(n)
 22170  		prg.printChar(asciiCode('/'))
 22171  		prg.printScaled(d)
 22172  		prg.print( /* ")*(" */ 855)
 22173  		prg.printExp(halfword(memMin), smallNumber(0))
 22174  		prg.print( /* ")]" */ 842)
 22175  		prg.endDiagnostic(false)
 22176  	}
 22177  	switch prg.curType {
 22178  	case transformType, pairType:
 22179  		oldExp = prg.tarnished(halfword(prg.curExp))
 22180  	case independent:
 22181  		oldExp = uint16(memMin + 1)
 22182  
 22183  	default:
 22184  		oldExp = uint16(memMin)
 22185  	}
 22186  	if int32(oldExp) != memMin {
 22187  		oldExp = uint16(prg.curExp)
 22188  		prg.makeExpCopy(oldExp)
 22189  	}
 22190  	v = prg.makeFraction(n, d)
 22191  	if int32(prg.curType) == known {
 22192  		prg.curExp = prg.takeFraction(prg.curExp, v)
 22193  	} else if int32(prg.curType) == pairType {
 22194  		p = uint16(*prg.mem[prg.curExp+1].int())
 22195  		prg.depMult(p, v, false)
 22196  		prg.depMult(halfword(int32(p)+2), v, false)
 22197  	} else {
 22198  		prg.depMult(halfword(memMin), v, false)
 22199  	}
 22200  	if int32(oldExp) != memMin {
 22201  		prg.recycleValue(oldExp)
 22202  		prg.freeNode(oldExp, halfword(valueNodeSize))
 22203  	}
 22204  }
 22205  
 22206  // 989. \[43] Statements and commands
 22207  
 22208  // tangle:pos ../../mf.web:19313:34:
 22209  
 22210  // The chief executive of \MF\ is the |do_statement| routine, which
 22211  // contains the master switch that causes all the various pieces of \MF\
 22212  // to do their things, in the right order.
 22213  //
 22214  // In a sense, this is the grand climax of the program: It applies all the
 22215  // tools that we have worked so hard to construct. In another sense, this is
 22216  // the messiest part of the program: It necessarily refers to other pieces
 22217  // of code all over the place, so that a person can't fully understand what is
 22218  // going on without paging back and forth to be reminded of conventions that
 22219  // are defined elsewhere. We are now at the hub of the web.
 22220  //
 22221  // The structure of |do_statement| itself is quite simple.  The first token
 22222  // of the statement is fetched using |get_x_next|.  If it can be the first
 22223  // token of an expression, we look for an equation, an assignment, or a
 22224  // title. Otherwise we use a \&[case] construction to branch at high speed to
 22225  // the appropriate routine for various and sundry other types of commands,
 22226  // each of which has an “action procedure” that does the necessary work.
 22227  //
 22228  // The program uses the fact that
 22229  // $$\hbox[|min_primary_command=max_statement_command=type_name|]$$
 22230  // to interpret a statement that starts with, e.g., `\&[string]',
 22231  // as a type declaration rather than a boolean expression.
 22232  // \4
 22233  // Declare generic font output procedures
 22234  func (prg *prg) writeGf(a, b gfIndex) {
 22235  	var (
 22236  		k gfIndex
 22237  	)
 22238  	for ii := int32(a); ii <= int32(b); ii++ {
 22239  		k = gfIndex(ii)
 22240  		_ = k
 22241  		prg.gfFile.Write(prg.gfBuf[k])
 22242  	}
 22243  }
 22244  
 22245  func (prg *prg) gfSwap() {
 22246  	if int32(prg.gfLimit) == gfBufSize {
 22247  		prg.writeGf(gfIndex(0), gfIndex(int32(prg.halfBuf)-1))
 22248  		prg.gfLimit = prg.halfBuf
 22249  		prg.gfOffset = prg.gfOffset + gfBufSize
 22250  		prg.gfPtr = 0
 22251  	} else {
 22252  		prg.writeGf(prg.halfBuf, gfIndex(gfBufSize-1))
 22253  		prg.gfLimit = byte(gfBufSize)
 22254  	}
 22255  }
 22256  
 22257  func (prg *prg) gfFour(x int32) {
 22258  	if x >= 0 {
 22259  		prg.gfBuf[prg.gfPtr] = byte(x / 0100000000)
 22260  		prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22261  		if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22262  			prg.gfSwap()
 22263  		}
 22264  	} else {
 22265  		x = x + 010000000000
 22266  		x = x + 010000000000
 22267  		{
 22268  			prg.gfBuf[prg.gfPtr] = byte(x/0100000000 + 128)
 22269  			prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22270  			if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22271  				prg.gfSwap()
 22272  			}
 22273  		}
 22274  	}
 22275  	x = x % 0100000000
 22276  	{
 22277  		prg.gfBuf[prg.gfPtr] = byte(x / 0200000)
 22278  		prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22279  		if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22280  			prg.gfSwap()
 22281  		}
 22282  	}
 22283  	x = x % 0200000
 22284  	{
 22285  		prg.gfBuf[prg.gfPtr] = byte(x / 0400)
 22286  		prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22287  		if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22288  			prg.gfSwap()
 22289  		}
 22290  	}
 22291  	{
 22292  		prg.gfBuf[prg.gfPtr] = byte(x % 0400)
 22293  		prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22294  		if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22295  			prg.gfSwap()
 22296  		}
 22297  	}
 22298  }
 22299  
 22300  func (prg *prg) gfTwo(x int32) {
 22301  	{
 22302  		prg.gfBuf[prg.gfPtr] = byte(x / 0400)
 22303  		prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22304  		if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22305  			prg.gfSwap()
 22306  		}
 22307  	}
 22308  	{
 22309  		prg.gfBuf[prg.gfPtr] = byte(x % 0400)
 22310  		prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22311  		if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22312  			prg.gfSwap()
 22313  		}
 22314  	}
 22315  }
 22316  
 22317  func (prg *prg) gfThree(x int32) {
 22318  	{
 22319  		prg.gfBuf[prg.gfPtr] = byte(x / 0200000)
 22320  		prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22321  		if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22322  			prg.gfSwap()
 22323  		}
 22324  	}
 22325  	{
 22326  		prg.gfBuf[prg.gfPtr] = byte(x % 0200000 / 0400)
 22327  		prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22328  		if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22329  			prg.gfSwap()
 22330  		}
 22331  	}
 22332  	{
 22333  		prg.gfBuf[prg.gfPtr] = byte(x % 0400)
 22334  		prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22335  		if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22336  			prg.gfSwap()
 22337  		}
 22338  	}
 22339  }
 22340  
 22341  func (prg *prg) gfPaint(d int32) {
 22342  	if d < 64 {
 22343  		prg.gfBuf[prg.gfPtr] = byte(paint0 + d)
 22344  		prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22345  		if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22346  			prg.gfSwap()
 22347  		}
 22348  	} else if d < 256 {
 22349  		{
 22350  			prg.gfBuf[prg.gfPtr] = byte(paint1)
 22351  			prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22352  			if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22353  				prg.gfSwap()
 22354  			}
 22355  		}
 22356  		{
 22357  			prg.gfBuf[prg.gfPtr] = byte(d)
 22358  			prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22359  			if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22360  				prg.gfSwap()
 22361  			}
 22362  		}
 22363  	} else {
 22364  		{
 22365  			prg.gfBuf[prg.gfPtr] = byte(paint1 + 1)
 22366  			prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22367  			if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22368  				prg.gfSwap()
 22369  			}
 22370  		}
 22371  		prg.gfTwo(d)
 22372  	}
 22373  }
 22374  
 22375  func (prg *prg) gfString(s, t strNumber) {
 22376  	var (
 22377  		k poolPointer
 22378  		l int32 // length of the strings to output
 22379  	)
 22380  	if int32(s) != 0 {
 22381  		l = int32(prg.strStart[int32(s)+1]) - int32(prg.strStart[s])
 22382  		if int32(t) != 0 {
 22383  			l = l + (int32(prg.strStart[int32(t)+1]) - int32(prg.strStart[t]))
 22384  		}
 22385  		if l <= 255 {
 22386  			{
 22387  				prg.gfBuf[prg.gfPtr] = byte(xxx1)
 22388  				prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22389  				if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22390  					prg.gfSwap()
 22391  				}
 22392  			}
 22393  			{
 22394  				prg.gfBuf[prg.gfPtr] = byte(l)
 22395  				prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22396  				if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22397  					prg.gfSwap()
 22398  				}
 22399  			}
 22400  		} else {
 22401  			{
 22402  				prg.gfBuf[prg.gfPtr] = byte(xxx3)
 22403  				prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22404  				if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22405  					prg.gfSwap()
 22406  				}
 22407  			}
 22408  			prg.gfThree(l)
 22409  		}
 22410  		for ii := int32(prg.strStart[s]); ii <= int32(prg.strStart[int32(s)+1])-1; ii++ {
 22411  			k = poolPointer(ii)
 22412  			_ = k
 22413  			prg.gfBuf[prg.gfPtr] = prg.strPool[k]
 22414  			prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22415  			if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22416  				prg.gfSwap()
 22417  			}
 22418  		}
 22419  	}
 22420  	if int32(t) != 0 {
 22421  		for ii := int32(prg.strStart[t]); ii <= int32(prg.strStart[int32(t)+1])-1; ii++ {
 22422  			k = poolPointer(ii)
 22423  			_ = k
 22424  			prg.gfBuf[prg.gfPtr] = prg.strPool[k]
 22425  			prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22426  			if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22427  				prg.gfSwap()
 22428  			}
 22429  		}
 22430  	}
 22431  }
 22432  
 22433  func (prg *prg) gfBoc(minM, maxM, minN, maxN int32) {
 22434  	if minM < prg.gfMinM {
 22435  		prg.gfMinM = minM
 22436  	}
 22437  	if maxN > prg.gfMaxN {
 22438  		prg.gfMaxN = maxN
 22439  	}
 22440  	if prg.bocP == -1 {
 22441  		if prg.bocC >= 0 {
 22442  			if prg.bocC < 256 {
 22443  				if maxM-minM >= 0 {
 22444  					if maxM-minM < 256 {
 22445  						if maxM >= 0 {
 22446  							if maxM < 256 {
 22447  								if maxN-minN >= 0 {
 22448  									if maxN-minN < 256 {
 22449  										if maxN >= 0 {
 22450  											if maxN < 256 {
 22451  												{
 22452  													prg.gfBuf[prg.gfPtr] = byte(boc1)
 22453  													prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22454  													if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22455  														prg.gfSwap()
 22456  													}
 22457  												}
 22458  												{
 22459  													prg.gfBuf[prg.gfPtr] = byte(prg.bocC)
 22460  													prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22461  													if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22462  														prg.gfSwap()
 22463  													}
 22464  												}
 22465  
 22466  												{
 22467  													prg.gfBuf[prg.gfPtr] = byte(maxM - minM)
 22468  													prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22469  													if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22470  														prg.gfSwap()
 22471  													}
 22472  												}
 22473  												{
 22474  													prg.gfBuf[prg.gfPtr] = byte(maxM)
 22475  													prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22476  													if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22477  														prg.gfSwap()
 22478  													}
 22479  												}
 22480  												{
 22481  													prg.gfBuf[prg.gfPtr] = byte(maxN - minN)
 22482  													prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22483  													if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22484  														prg.gfSwap()
 22485  													}
 22486  												}
 22487  												{
 22488  													prg.gfBuf[prg.gfPtr] = byte(maxN)
 22489  													prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22490  													if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22491  														prg.gfSwap()
 22492  													}
 22493  												}
 22494  												goto exit
 22495  											}
 22496  										}
 22497  									}
 22498  								}
 22499  							}
 22500  						}
 22501  					}
 22502  				}
 22503  			}
 22504  		}
 22505  	}
 22506  	{
 22507  		prg.gfBuf[prg.gfPtr] = byte(boc)
 22508  		prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22509  		if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22510  			prg.gfSwap()
 22511  		}
 22512  	}
 22513  	prg.gfFour(prg.bocC)
 22514  	prg.gfFour(prg.bocP)
 22515  
 22516  	prg.gfFour(minM)
 22517  	prg.gfFour(maxM)
 22518  	prg.gfFour(minN)
 22519  	prg.gfFour(maxN)
 22520  
 22521  exit:
 22522  }
 22523  
 22524  func (prg *prg) initGf() {
 22525  	var (
 22526  		k eightBits // runs through all possible character codes
 22527  		t int32     // the time of this run
 22528  	)
 22529  	prg.gfMinM = 4096
 22530  	prg.gfMaxM = -4096
 22531  	prg.gfMinN = 4096
 22532  	prg.gfMaxN = -4096
 22533  	for ii := int32(0); ii <= 255; ii++ {
 22534  		k = eightBits(ii)
 22535  		_ = k
 22536  		prg.charPtr[k] = -1
 22537  	}
 22538  
 22539  	// Determine the file extension, |gf_ext|
 22540  	if prg.internal[hppp-1] <= 0 {
 22541  		prg.gfExt = /* ".gf" */ 1054
 22542  	} else {
 22543  		prg.oldSetting = prg.selector
 22544  		prg.selector = byte(newString)
 22545  		prg.printChar(asciiCode('.'))
 22546  		prg.printInt(prg.makeScaled(prg.internal[hppp-1], 59429463))
 22547  		// $2^[32]/72.27\approx59429463.07$
 22548  		prg.print( /* "gf" */ 1055)
 22549  		prg.gfExt = prg.makeString()
 22550  		prg.selector = prg.oldSetting
 22551  	}
 22552  	{
 22553  		if int32(prg.jobName) == 0 {
 22554  			prg.openLogFile()
 22555  		}
 22556  		prg.packJobName(prg.gfExt)
 22557  		for !prg.bOpenOut(prg.gfFile) {
 22558  			prg.promptFileName(strNumber( /* "file name for output" */ 756), prg.gfExt)
 22559  		}
 22560  		prg.outputFileName = prg.bMakeNameString(prg.gfFile)
 22561  	}
 22562  	{
 22563  		prg.gfBuf[prg.gfPtr] = byte(pre)
 22564  		prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22565  		if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22566  			prg.gfSwap()
 22567  		}
 22568  	}
 22569  	{
 22570  		prg.gfBuf[prg.gfPtr] = byte(gfIdByte)
 22571  		prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22572  		if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22573  			prg.gfSwap()
 22574  		}
 22575  	} // begin to output the preamble
 22576  	prg.oldSetting = prg.selector
 22577  	prg.selector = byte(newString)
 22578  	prg.print( /* " METAFONT output " */ 1053)
 22579  	prg.printInt(prg.roundUnscaled(prg.internal[year-1]))
 22580  	prg.printChar(asciiCode('.'))
 22581  	prg.printDd(prg.roundUnscaled(prg.internal[month-1]))
 22582  	prg.printChar(asciiCode('.'))
 22583  	prg.printDd(prg.roundUnscaled(prg.internal[day-1]))
 22584  	prg.printChar(asciiCode(':'))
 22585  
 22586  	t = prg.roundUnscaled(prg.internal[time-1])
 22587  	prg.printDd(t / 60)
 22588  	prg.printDd(t % 60)
 22589  
 22590  	prg.selector = prg.oldSetting
 22591  	{
 22592  		prg.gfBuf[prg.gfPtr] = byte(int32(prg.poolPtr) - int32(prg.strStart[prg.strPtr]))
 22593  		prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22594  		if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22595  			prg.gfSwap()
 22596  		}
 22597  	}
 22598  	prg.gfString(strNumber(0), prg.makeString())
 22599  	prg.strPtr = uint16(int32(prg.strPtr) - 1)
 22600  	prg.poolPtr = prg.strStart[prg.strPtr] // flush that string from memory
 22601  	prg.gfPrevPtr = prg.gfOffset + int32(prg.gfPtr)
 22602  }
 22603  
 22604  func (prg *prg) shipOut(c eightBits) {
 22605  	var (
 22606  		f            int32    // current character extension
 22607  		prevM, m, mm int32    // previous and current pixel column numbers
 22608  		prevN, n     int32    // previous and current pixel row numbers
 22609  		p, q         halfword // for list traversal
 22610  		prevW, w, ww int32    // old and new weights
 22611  		d            int32    // data from edge-weight node
 22612  		delta        int32    // number of rows to skip
 22613  		curMinM      int32    // starting column, relative to the current offset
 22614  		xOff, yOff   int32    // offsets, rounded to integers
 22615  	)
 22616  	if int32(prg.outputFileName) == 0 {
 22617  		prg.initGf()
 22618  	}
 22619  	f = prg.roundUnscaled(prg.internal[charExt-1])
 22620  
 22621  	xOff = prg.roundUnscaled(prg.internal[xOffset-1])
 22622  	yOff = prg.roundUnscaled(prg.internal[yOffset-1])
 22623  	if int32(prg.termOffset) > maxPrintLine-9 {
 22624  		prg.printLn()
 22625  	} else if int32(prg.termOffset) > 0 || int32(prg.fileOffset) > 0 {
 22626  		prg.printChar(asciiCode(' '))
 22627  	}
 22628  	prg.printChar(asciiCode('['))
 22629  	prg.printInt(int32(c))
 22630  	if f != 0 {
 22631  		prg.printChar(asciiCode('.'))
 22632  		prg.printInt(f)
 22633  	}
 22634  
 22635  	prg.bocC = 256*f + int32(c)
 22636  	prg.bocP = prg.charPtr[c]
 22637  	prg.charPtr[c] = prg.gfPrevPtr
 22638  
 22639  	if prg.internal[proofing-1] > 0 {
 22640  		if xOff != 0 {
 22641  			prg.gfString(strNumber( /* "xoffset" */ 438), strNumber(0))
 22642  			{
 22643  				prg.gfBuf[prg.gfPtr] = byte(yyy)
 22644  				prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22645  				if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22646  					prg.gfSwap()
 22647  				}
 22648  			}
 22649  			prg.gfFour(xOff * 0200000)
 22650  		}
 22651  		if yOff != 0 {
 22652  			prg.gfString(strNumber( /* "yoffset" */ 439), strNumber(0))
 22653  			{
 22654  				prg.gfBuf[prg.gfPtr] = byte(yyy)
 22655  				prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22656  				if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22657  					prg.gfSwap()
 22658  				}
 22659  			}
 22660  			prg.gfFour(yOff * 0200000)
 22661  		}
 22662  	}
 22663  
 22664  	// Output the character represented in |cur_edges|
 22665  	prevN = 4096
 22666  	p = *(*prg.mem[prg.curEdges].hh()).lh()
 22667  	n = int32(*(*prg.mem[int32(prg.curEdges)+1].hh()).rh()) - zeroField
 22668  	for int32(p) != int32(prg.curEdges) {
 22669  		if int32(*(*prg.mem[int32(p)+1].hh()).lh()) > memMin+1 {
 22670  			prg.sortEdges(p)
 22671  		}
 22672  		q = *(*prg.mem[int32(p)+1].hh()).rh()
 22673  		w = 0
 22674  		prevM = -02000000000 // $|fraction_one|\approx\infty$
 22675  		ww = 0
 22676  		prevW = 0
 22677  		m = prevM
 22678  		for {
 22679  			if int32(q) == 3000 {
 22680  				mm = 02000000000
 22681  			} else {
 22682  				d = int32(*(*prg.mem[q].hh()).lh()) - 0
 22683  				mm = d / 8
 22684  				ww = ww + d%8 - zeroW
 22685  			}
 22686  			if mm != m {
 22687  				if prevW <= 0 {
 22688  					if w > 0 {
 22689  						if prevM == -02000000000 {
 22690  							if prevN == 4096 {
 22691  								prg.gfBoc(int32(*(*prg.mem[int32(prg.curEdges)+2].hh()).lh())+xOff-zeroField, int32(*(*prg.mem[int32(prg.curEdges)+2].hh()).rh())+xOff-zeroField, int32(*(*prg.mem[int32(prg.curEdges)+1].hh()).lh())+yOff-zeroField, n+yOff)
 22692  								curMinM = int32(*(*prg.mem[int32(prg.curEdges)+2].hh()).lh()) - zeroField + int32(*(*prg.mem[int32(prg.curEdges)+3].hh()).lh())
 22693  							} else if prevN > n+1 {
 22694  								delta = prevN - n - 1
 22695  								if delta < 0400 {
 22696  									{
 22697  										prg.gfBuf[prg.gfPtr] = byte(skip1)
 22698  										prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22699  										if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22700  											prg.gfSwap()
 22701  										}
 22702  									}
 22703  									{
 22704  										prg.gfBuf[prg.gfPtr] = byte(delta)
 22705  										prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22706  										if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22707  											prg.gfSwap()
 22708  										}
 22709  									}
 22710  								} else {
 22711  									{
 22712  										prg.gfBuf[prg.gfPtr] = byte(skip1 + 1)
 22713  										prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22714  										if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22715  											prg.gfSwap()
 22716  										}
 22717  									}
 22718  									prg.gfTwo(delta)
 22719  								}
 22720  							} else {
 22721  								// Skip to column $m$ in the next row and |goto done|, or skip zero rows
 22722  								delta = m - curMinM
 22723  								if delta > maxNewRow {
 22724  									prg.gfBuf[prg.gfPtr] = byte(skip0)
 22725  									prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22726  									if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22727  										prg.gfSwap()
 22728  									}
 22729  								} else {
 22730  									{
 22731  										prg.gfBuf[prg.gfPtr] = byte(newRow0 + delta)
 22732  										prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22733  										if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22734  											prg.gfSwap()
 22735  										}
 22736  									}
 22737  									goto done
 22738  								}
 22739  							}
 22740  							prg.gfPaint(m - curMinM) // skip to column $m$, painting white
 22741  							// skip to column $m$, painting white
 22742  						done:
 22743  							prevN = n
 22744  						} else {
 22745  							prg.gfPaint(m - prevM)
 22746  						}
 22747  						prevM = m
 22748  						prevW = w
 22749  					}
 22750  				} else if w <= 0 {
 22751  					prg.gfPaint(m - prevM)
 22752  					prevM = m
 22753  					prevW = w
 22754  				}
 22755  				m = mm
 22756  			}
 22757  			w = ww
 22758  			q = *(*prg.mem[q].hh()).rh()
 22759  			if mm == 02000000000 {
 22760  				break
 22761  			}
 22762  		}
 22763  		if w != 0 {
 22764  			prg.printNl(strNumber( /* "(There's unbounded black in character shipped out!)" */ 1057))
 22765  		}
 22766  		// \xref[There's unbounded black...]
 22767  		if prevM-int32(*(*prg.mem[int32(prg.curEdges)+3].hh()).lh())+xOff > prg.gfMaxM {
 22768  			prg.gfMaxM = prevM - int32(*(*prg.mem[int32(prg.curEdges)+3].hh()).lh()) + xOff
 22769  		}
 22770  		p = *(*prg.mem[p].hh()).lh()
 22771  		n = n - 1
 22772  	}
 22773  	if prevN == 4096 {
 22774  		prg.gfBoc(0, 0, 0, 0)
 22775  		if prg.gfMaxM < 0 {
 22776  			prg.gfMaxM = 0
 22777  		}
 22778  		if prg.gfMinN > 0 {
 22779  			prg.gfMinN = 0
 22780  		}
 22781  	} else if prevN+yOff < prg.gfMinN {
 22782  		prg.gfMinN = prevN + yOff
 22783  	}
 22784  	{
 22785  		prg.gfBuf[prg.gfPtr] = byte(eoc)
 22786  		prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 22787  		if int32(prg.gfPtr) == int32(prg.gfLimit) {
 22788  			prg.gfSwap()
 22789  		}
 22790  	}
 22791  	prg.gfPrevPtr = prg.gfOffset + int32(prg.gfPtr)
 22792  	prg.totalChars = prg.totalChars + 1
 22793  	prg.printChar(asciiCode(']')) // progress report
 22794  	if prg.internal[tracingOutput-1] > 0 {
 22795  		prg.printEdges(strNumber( /* " (just shipped out)" */ 1056), true, xOff, yOff)
 22796  	}
 22797  }
 22798  
 22799  // \4
 22800  // Declare action procedures for use by |do_statement|
 22801  // \4
 22802  // Declare the procedure called |try_eq|
 22803  func (prg *prg) tryEq(l, r1 halfword) {
 22804  	var (
 22805  		p                                   halfword // dependency list for right operand minus left operand
 22806  		t/* known..independent */ byte               // the type of list |p|
 22807  		q                                   halfword // the constant term of |p| is here
 22808  		pp                                  halfword // dependency list for right operand
 22809  		tt/* dependent..independent */ byte          // the type of list |pp|
 22810  		copied                              bool     // have we copied a list that ought to be recycled?
 22811  	)
 22812  	t = *(*prg.mem[l].hh()).b0()
 22813  	if int32(t) == known {
 22814  		t = byte(dependent)
 22815  		p = prg.constDependency(-*prg.mem[int32(l)+1].int())
 22816  		q = p
 22817  	} else if int32(t) == independent {
 22818  		t = byte(dependent)
 22819  		p = prg.singleDependency(l)
 22820  		*prg.mem[int32(p)+1].int() = -*prg.mem[int32(p)+1].int()
 22821  		q = prg.depFinal
 22822  	} else {
 22823  		p = *(*prg.mem[int32(l)+1].hh()).rh()
 22824  		q = p
 22825  		for true {
 22826  			*prg.mem[int32(q)+1].int() = -*prg.mem[int32(q)+1].int()
 22827  			if int32(*(*prg.mem[q].hh()).lh()) == memMin {
 22828  				goto done
 22829  			}
 22830  			q = *(*prg.mem[q].hh()).rh()
 22831  		}
 22832  
 22833  	done:
 22834  		*(*prg.mem[*(*prg.mem[int32(l)+1].hh()).lh()].hh()).rh() = *(*prg.mem[q].hh()).rh()
 22835  		*(*prg.mem[int32(*(*prg.mem[q].hh()).rh())+1].hh()).lh() = *(*prg.mem[int32(l)+1].hh()).lh()
 22836  		*(*prg.mem[l].hh()).b0() = byte(known)
 22837  	}
 22838  
 22839  	// Add the right operand to list |p|
 22840  	if int32(r1) == memMin {
 22841  		if int32(prg.curType) == known {
 22842  			*prg.mem[int32(q)+1].int() = *prg.mem[int32(q)+1].int() + prg.curExp
 22843  			goto done1
 22844  		} else {
 22845  			tt = prg.curType
 22846  			if int32(tt) == independent {
 22847  				pp = prg.singleDependency(halfword(prg.curExp))
 22848  			} else {
 22849  				pp = *(*prg.mem[prg.curExp+1].hh()).rh()
 22850  			}
 22851  		}
 22852  	} else if int32(*(*prg.mem[r1].hh()).b0()) == known {
 22853  		*prg.mem[int32(q)+1].int() = *prg.mem[int32(q)+1].int() + *prg.mem[int32(r1)+1].int()
 22854  		goto done1
 22855  	} else {
 22856  		tt = *(*prg.mem[r1].hh()).b0()
 22857  		if int32(tt) == independent {
 22858  			pp = prg.singleDependency(r1)
 22859  		} else {
 22860  			pp = *(*prg.mem[int32(r1)+1].hh()).rh()
 22861  		}
 22862  	}
 22863  	if int32(tt) != independent {
 22864  		copied = false
 22865  	} else {
 22866  		copied = true
 22867  		tt = byte(dependent)
 22868  	}
 22869  
 22870  	// Add dependency list |pp| of type |tt| to dependency list~|p| of type~|t|
 22871  	prg.watchCoefs = false
 22872  	if int32(t) == int32(tt) {
 22873  		p = prg.pPlusQ(p, pp, t)
 22874  	} else if int32(t) == protoDependent {
 22875  		p = prg.pPlusFq(p, 0200000, pp, smallNumber(protoDependent), smallNumber(dependent))
 22876  	} else {
 22877  		q = p
 22878  		for int32(*(*prg.mem[q].hh()).lh()) != memMin {
 22879  			*prg.mem[int32(q)+1].int() = prg.roundFraction(*prg.mem[int32(q)+1].int())
 22880  			q = *(*prg.mem[q].hh()).rh()
 22881  		}
 22882  		t = byte(protoDependent)
 22883  		p = prg.pPlusQ(p, pp, t)
 22884  	}
 22885  	prg.watchCoefs = true
 22886  
 22887  	if copied {
 22888  		prg.flushNodeList(pp)
 22889  	}
 22890  
 22891  done1:
 22892  	;
 22893  	if int32(*(*prg.mem[p].hh()).lh()) == memMin {
 22894  		if abs(*prg.mem[int32(p)+1].int()) > 64 {
 22895  			{
 22896  				if int32(prg.interaction) == errorStopMode {
 22897  				}
 22898  				prg.printNl(strNumber( /* "! " */ 261))
 22899  				prg.print( /* "Inconsistent equation" */ 897) /* \xref[!\relax]  */
 22900  			}
 22901  
 22902  			// \xref[Inconsistent equation]
 22903  			prg.print( /* " (off by " */ 899)
 22904  			prg.printScaled(*prg.mem[int32(p)+1].int())
 22905  			prg.printChar(asciiCode(')'))
 22906  			{
 22907  				prg.helpPtr = 2
 22908  				prg.helpLine[1] = /* "The equation I just read contradicts what was said before." */ 898
 22909  				prg.helpLine[0] = /* "But don't worry; continue and I'll just ignore it." */ 896
 22910  			}
 22911  			prg.putGetError()
 22912  		} else if int32(r1) == memMin {
 22913  			{
 22914  				if int32(prg.interaction) == errorStopMode {
 22915  				}
 22916  				prg.printNl(strNumber( /* "! " */ 261))
 22917  				prg.print( /* "Redundant equation" */ 599) /* \xref[!\relax]  */
 22918  			}
 22919  
 22920  			// \xref[Redundant equation]
 22921  			{
 22922  				prg.helpPtr = 2
 22923  				prg.helpLine[1] = /* "I already knew that this equation was true." */ 600
 22924  				prg.helpLine[0] = /* "But perhaps no harm has been done; let's continue." */ 601
 22925  			}
 22926  
 22927  			prg.putGetError()
 22928  		}
 22929  		prg.freeNode(p, halfword(depNodeSize))
 22930  	} else {
 22931  		prg.linearEq(p, t)
 22932  		if int32(r1) == memMin {
 22933  			if int32(prg.curType) != known {
 22934  				if int32(*(*prg.mem[prg.curExp].hh()).b0()) == known {
 22935  					pp = uint16(prg.curExp)
 22936  					prg.curExp = *prg.mem[prg.curExp+1].int()
 22937  					prg.curType = byte(known)
 22938  					prg.freeNode(pp, halfword(valueNodeSize))
 22939  				}
 22940  			}
 22941  		}
 22942  	}
 22943  }
 22944  
 22945  // \4
 22946  // Declare the procedure called |make_eq|
 22947  func (prg *prg) makeEq(lhs halfword) {
 22948  	var (
 22949  		t    smallNumber // type of the left-hand side
 22950  		v    int32       // value of the left-hand side
 22951  		p, q halfword    // pointers inside of big nodes
 22952  	)
 22953  restart:
 22954  	t = *(*prg.mem[lhs].hh()).b0()
 22955  	if int32(t) <= pairType {
 22956  		v = *prg.mem[int32(lhs)+1].int()
 22957  	}
 22958  	switch t {
 22959  	case booleanType, stringType, penType, pathType,
 22960  		pictureType:
 22961  		if int32(prg.curType) == int32(t)+unknownTag {
 22962  			prg.nonlinearEq(v, halfword(prg.curExp), false)
 22963  			prg.unstashCurExp(halfword(prg.curExp))
 22964  			goto done
 22965  		} else if int32(prg.curType) == int32(t) {
 22966  			if int32(prg.curType) <= stringType {
 22967  				if int32(prg.curType) == stringType {
 22968  					if prg.strVsStr(strNumber(v), strNumber(prg.curExp)) != 0 {
 22969  						goto notFound
 22970  					}
 22971  				} else if v != prg.curExp {
 22972  					goto notFound
 22973  				}
 22974  
 22975  				// Exclaim about a redundant equation
 22976  				{
 22977  					{
 22978  						if int32(prg.interaction) == errorStopMode {
 22979  						}
 22980  						prg.printNl(strNumber( /* "! " */ 261))
 22981  						prg.print( /* "Redundant equation" */ 599) /* \xref[!\relax]  */
 22982  					}
 22983  
 22984  					// \xref[Redundant equation]
 22985  					{
 22986  						prg.helpPtr = 2
 22987  						prg.helpLine[1] = /* "I already knew that this equation was true." */ 600
 22988  						prg.helpLine[0] = /* "But perhaps no harm has been done; let's continue." */ 601
 22989  					}
 22990  
 22991  					prg.putGetError()
 22992  				}
 22993  				goto done
 22994  			}
 22995  			{
 22996  				if int32(prg.interaction) == errorStopMode {
 22997  				}
 22998  				prg.printNl(strNumber( /* "! " */ 261))
 22999  				prg.print( /* "Redundant or inconsistent equation" */ 894) /* \xref[!\relax]  */
 23000  			}
 23001  			// \xref[Redundant or inconsistent equation]
 23002  			{
 23003  				prg.helpPtr = 2
 23004  				prg.helpLine[1] = /* "An equation between already-known quantities can't help." */ 895
 23005  				prg.helpLine[0] = /* "But don't worry; continue and I'll just ignore it." */ 896
 23006  			}
 23007  			prg.putGetError()
 23008  			goto done
 23009  
 23010  		notFound:
 23011  			{
 23012  				if int32(prg.interaction) == errorStopMode {
 23013  				}
 23014  				prg.printNl(strNumber( /* "! " */ 261))
 23015  				prg.print( /* "Inconsistent equation" */ 897) /* \xref[!\relax]  */
 23016  			}
 23017  			// \xref[Inconsistent equation]
 23018  			{
 23019  				prg.helpPtr = 2
 23020  				prg.helpLine[1] = /* "The equation I just read contradicts what was said before." */ 898
 23021  				prg.helpLine[0] = /* "But don't worry; continue and I'll just ignore it." */ 896
 23022  			}
 23023  			prg.putGetError()
 23024  			goto done
 23025  		}
 23026  
 23027  	case unknownBoolean, unknownString, unknownPen, unknownPicture,
 23028  		unknownPath:
 23029  		if int32(prg.curType) == int32(t)-unknownTag {
 23030  			prg.nonlinearEq(prg.curExp, lhs, true)
 23031  			goto done
 23032  		} else if int32(prg.curType) == int32(t) {
 23033  			prg.ringMerge(lhs, halfword(prg.curExp))
 23034  			goto done
 23035  		} else if int32(prg.curType) == pairType {
 23036  			if int32(t) == unknownPath {
 23037  				prg.pairToPath()
 23038  				goto restart
 23039  			}
 23040  		}
 23041  	case transformType, pairType:
 23042  		if int32(prg.curType) == int32(t) {
 23043  			p = uint16(v + int32(prg.bigNodeSize[t-13]))
 23044  			q = uint16(*prg.mem[prg.curExp+1].int() + int32(prg.bigNodeSize[t-13]))
 23045  			for {
 23046  				p = uint16(int32(p) - 2)
 23047  				q = uint16(int32(q) - 2)
 23048  				prg.tryEq(p, q)
 23049  				if int32(p) == v {
 23050  					break
 23051  				}
 23052  			}
 23053  
 23054  			goto done
 23055  		}
 23056  
 23057  	case known, dependent, protoDependent, independent:
 23058  		if int32(prg.curType) >= known {
 23059  			prg.tryEq(lhs, halfword(memMin))
 23060  			goto done
 23061  		}
 23062  	case vacuous:
 23063  
 23064  	} // all cases have been listed
 23065  
 23066  	// Announce that the equation cannot be performed
 23067  	prg.dispErr(lhs, strNumber( /* "" */ 285))
 23068  	prg.dispErr(halfword(memMin), strNumber( /* "Equation cannot be performed (" */ 891))
 23069  	// \xref[Equation cannot be performed]
 23070  	if int32(*(*prg.mem[lhs].hh()).b0()) <= pairType {
 23071  		prg.printType(*(*prg.mem[lhs].hh()).b0())
 23072  	} else {
 23073  		prg.print( /* "numeric" */ 341)
 23074  	}
 23075  	prg.printChar(asciiCode('='))
 23076  	if int32(prg.curType) <= pairType {
 23077  		prg.printType(prg.curType)
 23078  	} else {
 23079  		prg.print( /* "numeric" */ 341)
 23080  	}
 23081  	prg.printChar(asciiCode(')'))
 23082  
 23083  	{
 23084  		prg.helpPtr = 2
 23085  		prg.helpLine[1] = /* "I'm sorry, but I don't know how to make such things equal." */ 892
 23086  		prg.helpLine[0] = /* "(See the two expressions just above the error message.)" */ 893
 23087  	}
 23088  	prg.putGetError()
 23089  
 23090  done:
 23091  	{
 23092  		if prg.arithError {
 23093  			prg.clearArith()
 23094  		}
 23095  	}
 23096  	prg.recycleValue(lhs)
 23097  	prg.freeNode(lhs, halfword(valueNodeSize))
 23098  } // \2
 23099  
 23100  func (prg *prg) doEquation() {
 23101  	var (
 23102  		lhs halfword // capsule for the left-hand side
 23103  		p   halfword // temporary register
 23104  	)
 23105  	lhs = prg.stashCurExp()
 23106  	prg.getXNext()
 23107  	prg.varFlag = byte(assignment)
 23108  	prg.scanExpression()
 23109  	if int32(prg.curCmd) == equals {
 23110  		prg.doEquation()
 23111  	} else if int32(prg.curCmd) == assignment {
 23112  		prg.doAssignment()
 23113  	}
 23114  	if prg.internal[tracingCommands-1] > 0400000 {
 23115  		prg.beginDiagnostic()
 23116  		prg.printNl(strNumber( /* "[(" */ 850))
 23117  		prg.printExp(lhs, smallNumber(0))
 23118  		prg.print( /* ")=(" */ 886)
 23119  		prg.printExp(halfword(memMin), smallNumber(0))
 23120  		prg.print( /* ")]" */ 842)
 23121  		prg.endDiagnostic(false)
 23122  	}
 23123  	if int32(prg.curType) == unknownPath {
 23124  		if int32(*(*prg.mem[lhs].hh()).b0()) == pairType {
 23125  			p = prg.stashCurExp()
 23126  			prg.unstashCurExp(lhs)
 23127  			lhs = p
 23128  		}
 23129  	} // in this case |make_eq| will change the pair to a path
 23130  	prg.makeEq(lhs) // equate |lhs| to |(cur_type,cur_exp)|
 23131  }
 23132  
 23133  func (prg *prg) doAssignment() {
 23134  	var (
 23135  		lhs halfword // token list for the left-hand side
 23136  		p   halfword // where the left-hand value is stored
 23137  		q   halfword // temporary capsule for the right-hand value
 23138  	)
 23139  	if int32(prg.curType) != tokenList {
 23140  		prg.dispErr(halfword(memMin), strNumber( /* "Improper `:=' will be changed to `='" */ 883))
 23141  		// \xref[Improper `:=']
 23142  		{
 23143  			prg.helpPtr = 2
 23144  			prg.helpLine[1] = /* "I didn't find a variable name at the left of the `:='," */ 884
 23145  			prg.helpLine[0] = /* "so I'm going to pretend that you said `=' instead." */ 885
 23146  		}
 23147  
 23148  		prg.error1()
 23149  		prg.doEquation()
 23150  	} else {
 23151  		lhs = uint16(prg.curExp)
 23152  		prg.curType = byte(vacuous)
 23153  
 23154  		prg.getXNext()
 23155  		prg.varFlag = byte(assignment)
 23156  		prg.scanExpression()
 23157  		if int32(prg.curCmd) == equals {
 23158  			prg.doEquation()
 23159  		} else if int32(prg.curCmd) == assignment {
 23160  			prg.doAssignment()
 23161  		}
 23162  		if prg.internal[tracingCommands-1] > 0400000 {
 23163  			prg.beginDiagnostic()
 23164  			prg.printNl(strNumber('{'))
 23165  			if int32(*(*prg.mem[lhs].hh()).lh()) > hashBase+hashSize+12 {
 23166  				prg.slowPrint(int32(prg.intName[int32(*(*prg.mem[lhs].hh()).lh())-(hashBase+hashSize+12)-1]))
 23167  			} else {
 23168  				prg.showTokenList(int32(lhs), memMin, 1000, 0)
 23169  			}
 23170  			prg.print( /* ":=" */ 461)
 23171  			prg.printExp(halfword(memMin), smallNumber(0))
 23172  			prg.printChar(asciiCode('}'))
 23173  			prg.endDiagnostic(false)
 23174  		}
 23175  		if int32(*(*prg.mem[lhs].hh()).lh()) > hashBase+hashSize+12 {
 23176  			if int32(prg.curType) == known {
 23177  				prg.internal[int32(*(*prg.mem[lhs].hh()).lh())-(hashBase+hashSize+12)-1] = prg.curExp
 23178  			} else {
 23179  				prg.dispErr(halfword(memMin), strNumber( /* "Internal quantity `" */ 887))
 23180  				// \xref[Internal quantity...]
 23181  				prg.slowPrint(int32(prg.intName[int32(*(*prg.mem[lhs].hh()).lh())-(hashBase+hashSize+12)-1]))
 23182  				prg.print( /* "' must receive a known value" */ 888)
 23183  				{
 23184  					prg.helpPtr = 2
 23185  					prg.helpLine[1] = /* "I can't set an internal quantity to anything but a known" */ 889
 23186  					prg.helpLine[0] = /* "numeric value, so I'll have to ignore this assignment." */ 890
 23187  				}
 23188  				prg.putGetError()
 23189  			}
 23190  		} else {
 23191  			// Assign the current expression to the variable |lhs|
 23192  			p = prg.findVariable(lhs)
 23193  			if int32(p) != memMin {
 23194  				q = prg.stashCurExp()
 23195  				prg.curType = prg.undType(p)
 23196  				prg.recycleValue(p)
 23197  				*(*prg.mem[p].hh()).b0() = prg.curType
 23198  				*prg.mem[int32(p)+1].int() = memMin
 23199  				prg.makeExpCopy(p)
 23200  				p = prg.stashCurExp()
 23201  				prg.unstashCurExp(q)
 23202  				prg.makeEq(p)
 23203  			} else {
 23204  				prg.obliterated(lhs)
 23205  				prg.putGetError()
 23206  			}
 23207  		}
 23208  		prg.flushNodeList(lhs)
 23209  	}
 23210  }
 23211  
 23212  func (prg *prg) doTypeDeclaration() {
 23213  	var (
 23214  		t smallNumber // the type being declared
 23215  		p halfword    // token list for a declared variable
 23216  		q halfword    // value node for the variable
 23217  	)
 23218  	if prg.curMod >= transformType {
 23219  		t = byte(prg.curMod)
 23220  	} else {
 23221  		t = byte(prg.curMod + unknownTag)
 23222  	}
 23223  	for {
 23224  		p = prg.scanDeclaredVariable()
 23225  		prg.flushVariable(*prg.eqtb[*(*prg.mem[p].hh()).lh()-1].rh(), *(*prg.mem[p].hh()).rh(), false)
 23226  
 23227  		q = prg.findVariable(p)
 23228  		if int32(q) != memMin {
 23229  			*(*prg.mem[q].hh()).b0() = t
 23230  			*prg.mem[int32(q)+1].int() = memMin
 23231  		} else {
 23232  			{
 23233  				if int32(prg.interaction) == errorStopMode {
 23234  				}
 23235  				prg.printNl(strNumber( /* "! " */ 261))
 23236  				prg.print( /* "Declared variable conflicts with previous vardef" */ 900) /* \xref[!\relax]  */
 23237  			}
 23238  			// \xref[Declared variable conflicts...]
 23239  			{
 23240  				prg.helpPtr = 2
 23241  				prg.helpLine[1] = /* "You can't use, e.g., `numeric foo[]' after `vardef foo'." */ 901
 23242  				prg.helpLine[0] = /* "Proceed, and I'll ignore the illegal redeclaration." */ 902
 23243  			}
 23244  			prg.putGetError()
 23245  		}
 23246  		prg.flushList(p)
 23247  		if int32(prg.curCmd) < comma {
 23248  			{
 23249  				if int32(prg.interaction) == errorStopMode {
 23250  				}
 23251  				prg.printNl(strNumber( /* "! " */ 261))
 23252  				prg.print( /* "Illegal suffix of declared variable will be flushed" */ 903) /* \xref[!\relax]  */
 23253  			}
 23254  			// \xref[Illegal suffix...flushed]
 23255  			{
 23256  				prg.helpPtr = 5
 23257  				prg.helpLine[4] = /* "Variables in declarations must consist entirely of" */ 904
 23258  				prg.helpLine[3] = /* "names and collective subscripts, e.g., `x[]a'." */ 905
 23259  				prg.helpLine[2] = /* "Are you trying to use a reserved word in a variable name?" */ 906
 23260  				prg.helpLine[1] = /* "I'm going to discard the junk I found here," */ 907
 23261  				prg.helpLine[0] = /* "up to the next comma or the end of the declaration." */ 908
 23262  			}
 23263  			if int32(prg.curCmd) == numericToken {
 23264  				prg.helpLine[2] = /* "Explicit subscripts like `x15a' aren't permitted." */ 909
 23265  			}
 23266  			prg.putGetError()
 23267  			prg.scannerStatus = byte(flushing)
 23268  			for {
 23269  				prg.getNext()
 23270  
 23271  				// Decrease the string reference count...
 23272  				if int32(prg.curCmd) == stringToken {
 23273  					if int32(prg.strRef[prg.curMod]) < maxStrRef {
 23274  						if int32(prg.strRef[prg.curMod]) > 1 {
 23275  							prg.strRef[prg.curMod] = byte(int32(prg.strRef[prg.curMod]) - 1)
 23276  						} else {
 23277  							prg.flushString(strNumber(prg.curMod))
 23278  						}
 23279  					}
 23280  				}
 23281  				if int32(prg.curCmd) >= comma {
 23282  					break
 23283  				}
 23284  			} // either |end_of_statement| or |cur_cmd=comma|
 23285  			prg.scannerStatus = byte(normal)
 23286  		}
 23287  		if int32(prg.curCmd) > comma {
 23288  			break
 23289  		}
 23290  	}
 23291  }
 23292  
 23293  func (prg *prg) doRandomSeed() {
 23294  	prg.getXNext()
 23295  	if int32(prg.curCmd) != assignment {
 23296  		prg.missingErr(strNumber( /* ":=" */ 461))
 23297  		// \xref[Missing `:=']
 23298  		{
 23299  			prg.helpPtr = 1
 23300  			prg.helpLine[0] = /* "Always say `randomseed:=<numeric expression>'." */ 914
 23301  		}
 23302  		prg.backError()
 23303  	}
 23304  	prg.getXNext()
 23305  	prg.scanExpression()
 23306  	if int32(prg.curType) != known {
 23307  		prg.dispErr(halfword(memMin), strNumber( /* "Unknown value will be ignored" */ 915))
 23308  		// \xref[Unknown value...ignored]
 23309  		{
 23310  			prg.helpPtr = 2
 23311  			prg.helpLine[1] = /* "Your expression was too random for me to handle," */ 916
 23312  			prg.helpLine[0] = /* "so I won't change the random seed just now." */ 917
 23313  		}
 23314  
 23315  		prg.putGetFlushError(scaled(0))
 23316  	} else {
 23317  		// Initialize the random seed to |cur_exp|
 23318  		prg.initRandoms(prg.curExp)
 23319  		if int32(prg.selector) >= logOnly {
 23320  			prg.oldSetting = prg.selector
 23321  			prg.selector = byte(logOnly)
 23322  			prg.printNl(strNumber( /* "[randomseed:=" */ 918))
 23323  			prg.printScaled(prg.curExp)
 23324  			prg.printChar(asciiCode('}'))
 23325  			prg.printNl(strNumber( /* "" */ 285))
 23326  			prg.selector = prg.oldSetting
 23327  		}
 23328  	}
 23329  }
 23330  
 23331  func (prg *prg) doProtection() {
 23332  	var (
 23333  		m/* 0..1 */ byte          // 0 to unprotect, 1 to protect
 23334  		t                halfword // the |eq_type| before we change it
 23335  	)
 23336  	m = byte(prg.curMod)
 23337  	for {
 23338  		prg.getSymbol()
 23339  		t = *prg.eqtb[prg.curSym-1].lh()
 23340  		if int32(m) == 0 {
 23341  			if int32(t) >= outerTag {
 23342  				*prg.eqtb[prg.curSym-1].lh() = uint16(int32(t) - outerTag)
 23343  			}
 23344  		} else if int32(t) < outerTag {
 23345  			*prg.eqtb[prg.curSym-1].lh() = uint16(int32(t) + outerTag)
 23346  		}
 23347  		prg.getXNext()
 23348  		if int32(prg.curCmd) != comma {
 23349  			break
 23350  		}
 23351  	}
 23352  }
 23353  
 23354  func (prg *prg) defDelims() {
 23355  	var (
 23356  		lDelim, rDelim halfword // the new delimiter pair
 23357  	)
 23358  	prg.getClearSymbol()
 23359  	lDelim = prg.curSym
 23360  
 23361  	prg.getClearSymbol()
 23362  	rDelim = prg.curSym
 23363  
 23364  	*prg.eqtb[lDelim-1].lh() = uint16(leftDelimiter)
 23365  	*prg.eqtb[lDelim-1].rh() = rDelim
 23366  
 23367  	*prg.eqtb[rDelim-1].lh() = uint16(rightDelimiter)
 23368  	*prg.eqtb[rDelim-1].rh() = lDelim
 23369  
 23370  	prg.getXNext()
 23371  } // \2
 23372  
 23373  func (prg *prg) doInterim() {
 23374  	prg.getXNext()
 23375  	if int32(prg.curCmd) != internalQuantity {
 23376  		{
 23377  			if int32(prg.interaction) == errorStopMode {
 23378  			}
 23379  			prg.printNl(strNumber( /* "! " */ 261))
 23380  			prg.print( /* "The token `" */ 924) /* \xref[!\relax]  */
 23381  		}
 23382  		// \xref[The token...quantity]
 23383  		if int32(prg.curSym) == 0 {
 23384  			prg.print( /* "(%CAPSULE)" */ 929)
 23385  		} else {
 23386  			prg.slowPrint(int32(*prg.hash[prg.curSym-1].rh()))
 23387  		}
 23388  		prg.print( /* "' isn't an internal quantity" */ 930)
 23389  		{
 23390  			prg.helpPtr = 1
 23391  			prg.helpLine[0] = /* "Something like `tracingonline' should follow `interim'." */ 931
 23392  		}
 23393  		prg.backError()
 23394  	} else {
 23395  		prg.saveInternal(halfword(prg.curMod))
 23396  		prg.backInput()
 23397  	}
 23398  	prg.doStatement()
 23399  }
 23400  
 23401  func (prg *prg) doLet() {
 23402  	var (
 23403  		l halfword // hash location of the left-hand symbol
 23404  	)
 23405  	prg.getSymbol()
 23406  	l = prg.curSym
 23407  	prg.getXNext()
 23408  	if int32(prg.curCmd) != equals {
 23409  		if int32(prg.curCmd) != assignment {
 23410  			prg.missingErr(strNumber('='))
 23411  			// \xref[Missing `=']
 23412  			{
 23413  				prg.helpPtr = 3
 23414  				prg.helpLine[2] = /* "You should have said `let symbol = something'." */ 932
 23415  				prg.helpLine[1] = /* "But don't worry; I'll pretend that an equals sign" */ 672
 23416  				prg.helpLine[0] = /* "was present. The next token I read will be `something'." */ 933
 23417  			}
 23418  			prg.backError()
 23419  		}
 23420  	}
 23421  	prg.getSymbol()
 23422  	switch prg.curCmd {
 23423  	case definedMacro, secondaryPrimaryMacro, tertiarySecondaryMacro, expressionTertiaryMacro:
 23424  		*(*prg.mem[prg.curMod].hh()).lh() = uint16(int32(*(*prg.mem[prg.curMod].hh()).lh()) + 1)
 23425  
 23426  	default:
 23427  	}
 23428  
 23429  	prg.clearSymbol(l, false)
 23430  	*prg.eqtb[l-1].lh() = uint16(prg.curCmd)
 23431  	if int32(prg.curCmd) == tagToken {
 23432  		*prg.eqtb[l-1].rh() = uint16(memMin)
 23433  	} else {
 23434  		*prg.eqtb[l-1].rh() = uint16(prg.curMod)
 23435  	}
 23436  	prg.getXNext()
 23437  }
 23438  
 23439  func (prg *prg) doNewInternal() {
 23440  	for {
 23441  		if int32(prg.intPtr) == maxInternal {
 23442  			prg.overflow(strNumber( /* "number of internals" */ 934), maxInternal)
 23443  		}
 23444  		// \xref[METAFONT capacity exceeded number of int][\quad number of internals]
 23445  		prg.getClearSymbol()
 23446  		prg.intPtr = byte(int32(prg.intPtr) + 1)
 23447  		*prg.eqtb[prg.curSym-1].lh() = uint16(internalQuantity)
 23448  		*prg.eqtb[prg.curSym-1].rh() = uint16(prg.intPtr)
 23449  		prg.intName[prg.intPtr-1] = *prg.hash[prg.curSym-1].rh()
 23450  		prg.internal[prg.intPtr-1] = 0
 23451  		prg.getXNext()
 23452  		if int32(prg.curCmd) != comma {
 23453  			break
 23454  		}
 23455  	}
 23456  }
 23457  
 23458  func (prg *prg) doShow() {
 23459  	for {
 23460  		prg.getXNext()
 23461  		prg.scanExpression()
 23462  		prg.printNl(strNumber( /* ">> " */ 765))
 23463  		// \xref[>>]
 23464  		prg.printExp(halfword(memMin), smallNumber(2))
 23465  		prg.flushCurExp(scaled(0))
 23466  		if int32(prg.curCmd) != comma {
 23467  			break
 23468  		}
 23469  	}
 23470  }
 23471  
 23472  func (prg *prg) dispToken() {
 23473  	prg.printNl(strNumber( /* "> " */ 940))
 23474  	// \xref[>\relax]
 23475  	if int32(prg.curSym) == 0 {
 23476  		if int32(prg.curCmd) == numericToken {
 23477  			prg.printScaled(prg.curMod)
 23478  		} else if int32(prg.curCmd) == capsuleToken {
 23479  			prg.gPointer = uint16(prg.curMod)
 23480  			prg.printCapsule()
 23481  		} else {
 23482  			prg.printChar(asciiCode('"'))
 23483  			prg.slowPrint(prg.curMod)
 23484  			prg.printChar(asciiCode('"'))
 23485  			{
 23486  				if int32(prg.strRef[prg.curMod]) < maxStrRef {
 23487  					if int32(prg.strRef[prg.curMod]) > 1 {
 23488  						prg.strRef[prg.curMod] = byte(int32(prg.strRef[prg.curMod]) - 1)
 23489  					} else {
 23490  						prg.flushString(strNumber(prg.curMod))
 23491  					}
 23492  				}
 23493  			}
 23494  		}
 23495  	} else {
 23496  		prg.slowPrint(int32(*prg.hash[prg.curSym-1].rh()))
 23497  		prg.printChar(asciiCode('='))
 23498  		if int32(*prg.eqtb[prg.curSym-1].lh()) >= outerTag {
 23499  			prg.print( /* "(outer) " */ 941)
 23500  		}
 23501  		prg.printCmdMod(int32(prg.curCmd), prg.curMod)
 23502  		if int32(prg.curCmd) == definedMacro {
 23503  			prg.printLn()
 23504  			prg.showMacro(halfword(prg.curMod), memMin, 100000)
 23505  		} // this avoids recursion between |show_macro| and |print_cmd_mod|
 23506  		// \xref[recursion]
 23507  	}
 23508  }
 23509  
 23510  func (prg *prg) doShowToken() {
 23511  	for {
 23512  		prg.getNext()
 23513  		prg.dispToken()
 23514  		prg.getXNext()
 23515  		if int32(prg.curCmd) != comma {
 23516  			break
 23517  		}
 23518  	}
 23519  }
 23520  
 23521  func (prg *prg) doShowStats() {
 23522  	prg.printNl(strNumber( /* "Memory usage " */ 950))
 23523  	// \xref[Memory usage...]
 23524  	prg.printInt(prg.varUsed)
 23525  	prg.printChar(asciiCode('&'))
 23526  	prg.printInt(prg.dynUsed)
 23527  	if false {
 23528  		prg.print( /* "unknown" */ 358)
 23529  	}
 23530  	prg.print( /* " (" */ 558)
 23531  	prg.printInt(int32(prg.hiMemMin) - int32(prg.loMemMax) - 1)
 23532  	prg.print( /* " still untouched)" */ 951)
 23533  	prg.printLn()
 23534  	prg.printNl(strNumber( /* "String usage " */ 952))
 23535  	prg.printInt(int32(prg.strPtr) - int32(prg.initStrPtr))
 23536  	prg.printChar(asciiCode('&'))
 23537  	prg.printInt(int32(prg.poolPtr) - int32(prg.initPoolPtr))
 23538  	prg.print( /* " (" */ 558)
 23539  	prg.printInt(maxStrings - int32(prg.maxStrPtr))
 23540  	prg.printChar(asciiCode('&'))
 23541  	prg.printInt(poolSize - int32(prg.maxPoolPtr))
 23542  	prg.print( /* " still untouched)" */ 951)
 23543  	prg.printLn()
 23544  	prg.getXNext()
 23545  }
 23546  
 23547  func (prg *prg) dispVar(p halfword) {
 23548  	var (
 23549  		q                           halfword // traverses attributes and subscripts
 23550  		n/* 0..maxPrintLine */ byte          // amount of macro text to show
 23551  	)
 23552  	if int32(*(*prg.mem[p].hh()).b0()) == structured {
 23553  		q = *(*prg.mem[int32(p)+1].hh()).lh()
 23554  		for {
 23555  			prg.dispVar(q)
 23556  			q = *(*prg.mem[q].hh()).rh()
 23557  			if int32(q) == memMin+3+10+2+2 {
 23558  				break
 23559  			}
 23560  		}
 23561  		q = *(*prg.mem[int32(p)+1].hh()).rh()
 23562  		for int32(*(*prg.mem[q].hh()).b1()) == subscr {
 23563  			prg.dispVar(q)
 23564  			q = *(*prg.mem[q].hh()).rh()
 23565  		}
 23566  	} else if int32(*(*prg.mem[p].hh()).b0()) >= unsuffixedMacro {
 23567  		prg.printNl(strNumber( /* "" */ 285))
 23568  		prg.printVariableName(p)
 23569  		if int32(*(*prg.mem[p].hh()).b0()) > unsuffixedMacro {
 23570  			prg.print( /* "@#" */ 664)
 23571  		} // |suffixed_macro|
 23572  		prg.print( /* "=macro:" */ 953)
 23573  		if int32(prg.fileOffset) >= maxPrintLine-20 {
 23574  			n = 5
 23575  		} else {
 23576  			n = byte(maxPrintLine - int32(prg.fileOffset) - 15)
 23577  		}
 23578  		prg.showMacro(halfword(*prg.mem[int32(p)+1].int()), memMin, int32(n))
 23579  	} else if int32(*(*prg.mem[p].hh()).b0()) != undefined {
 23580  		prg.printNl(strNumber( /* "" */ 285))
 23581  		prg.printVariableName(p)
 23582  		prg.printChar(asciiCode('='))
 23583  		prg.printExp(p, smallNumber(0))
 23584  	}
 23585  }
 23586  
 23587  func (prg *prg) doShowVar() {
 23588  	for {
 23589  		prg.getNext()
 23590  		if int32(prg.curSym) > 0 {
 23591  			if int32(prg.curSym) <= hashBase+hashSize+12 {
 23592  				if int32(prg.curCmd) == tagToken {
 23593  					if prg.curMod != memMin {
 23594  						prg.dispVar(halfword(prg.curMod))
 23595  						goto done
 23596  					}
 23597  				}
 23598  			}
 23599  		}
 23600  		prg.dispToken()
 23601  
 23602  	done:
 23603  		prg.getXNext()
 23604  		if int32(prg.curCmd) != comma {
 23605  			break
 23606  		}
 23607  	}
 23608  }
 23609  
 23610  func (prg *prg) doShowDependencies() {
 23611  	var (
 23612  		p halfword // link that runs through all dependencies
 23613  	)
 23614  	p = *(*prg.mem[memMin+3+10].hh()).rh()
 23615  	for int32(p) != memMin+3+10 {
 23616  		if prg.interesting(p) {
 23617  			prg.printNl(strNumber( /* "" */ 285))
 23618  			prg.printVariableName(p)
 23619  			if int32(*(*prg.mem[p].hh()).b0()) == dependent {
 23620  				prg.printChar(asciiCode('='))
 23621  			} else {
 23622  				prg.print( /* " = " */ 768)
 23623  			} // extra spaces imply proto-dependency
 23624  			prg.printDependency(*(*prg.mem[int32(p)+1].hh()).rh(), *(*prg.mem[p].hh()).b0())
 23625  		}
 23626  		p = *(*prg.mem[int32(p)+1].hh()).rh()
 23627  		for int32(*(*prg.mem[p].hh()).lh()) != memMin {
 23628  			p = *(*prg.mem[p].hh()).rh()
 23629  		}
 23630  		p = *(*prg.mem[p].hh()).rh()
 23631  	}
 23632  	prg.getXNext()
 23633  }
 23634  
 23635  func (prg *prg) doShowWhatever() {
 23636  	if int32(prg.interaction) == errorStopMode {
 23637  	}
 23638  	switch prg.curMod {
 23639  	case showTokenCode:
 23640  		prg.doShowToken()
 23641  	case showStatsCode:
 23642  		prg.doShowStats()
 23643  	case showCode:
 23644  		prg.doShow()
 23645  	case showVarCode:
 23646  		prg.doShowVar()
 23647  	case showDependenciesCode:
 23648  		prg.doShowDependencies()
 23649  	} // there are no other cases
 23650  	if prg.internal[showstopping-1] > 0 {
 23651  		{
 23652  			if int32(prg.interaction) == errorStopMode {
 23653  			}
 23654  			prg.printNl(strNumber( /* "! " */ 261))
 23655  			prg.print( /* "OK" */ 954) /* \xref[!\relax]  */
 23656  		}
 23657  		// \xref[OK]
 23658  		if int32(prg.interaction) < errorStopMode {
 23659  			prg.helpPtr = 0
 23660  			prg.errorCount = int8(int32(prg.errorCount) - 1)
 23661  		} else {
 23662  			prg.helpPtr = 1
 23663  			prg.helpLine[0] = /* "This isn't an error message; I'm just showing something." */ 955
 23664  		}
 23665  		if int32(prg.curCmd) == semicolon {
 23666  			prg.error1()
 23667  		} else {
 23668  			prg.putGetError()
 23669  		}
 23670  	}
 23671  }
 23672  
 23673  func (prg *prg) scanWith() (r bool) {
 23674  	var (
 23675  		t      smallNumber // |known| or |pen_type|
 23676  		result bool        // the value to return
 23677  	)
 23678  	t = byte(prg.curMod)
 23679  	prg.curType = byte(vacuous)
 23680  	prg.getXNext()
 23681  	prg.scanExpression()
 23682  	result = false
 23683  	if int32(prg.curType) != int32(t) {
 23684  		prg.dispErr(halfword(memMin), strNumber( /* "Improper type" */ 963))
 23685  		// \xref[Improper type]
 23686  		{
 23687  			prg.helpPtr = 2
 23688  			prg.helpLine[1] = /* "Next time say `withweight <known numeric expression>';" */ 964
 23689  			prg.helpLine[0] = /* "I'll ignore the bad `with' clause and look for another." */ 965
 23690  		}
 23691  		if int32(t) == penType {
 23692  			prg.helpLine[1] = /* "Next time say `withpen <known pen expression>';" */ 966
 23693  		}
 23694  		prg.putGetFlushError(scaled(0))
 23695  	} else if int32(prg.curType) == penType {
 23696  		result = true
 23697  	} else {
 23698  		// Check the tentative weight
 23699  		prg.curExp = prg.roundUnscaled(prg.curExp)
 23700  		if abs(prg.curExp) < 4 && prg.curExp != 0 {
 23701  			result = true
 23702  		} else {
 23703  			{
 23704  				if int32(prg.interaction) == errorStopMode {
 23705  				}
 23706  				prg.printNl(strNumber( /* "! " */ 261))
 23707  				prg.print( /* "Weight must be -3, -2, -1, +1, +2, or +3" */ 967) /* \xref[!\relax]  */
 23708  			}
 23709  			// \xref[Weight must be...]
 23710  			{
 23711  				prg.helpPtr = 1
 23712  				prg.helpLine[0] = /* "I'll ignore the bad `with' clause and look for another." */ 965
 23713  			}
 23714  			prg.putGetFlushError(scaled(0))
 23715  		}
 23716  	}
 23717  	r = result
 23718  	return r
 23719  }
 23720  
 23721  func (prg *prg) findEdgesVar(t halfword) {
 23722  	var (
 23723  		p halfword
 23724  	)
 23725  	p = prg.findVariable(t)
 23726  	prg.curEdges = uint16(memMin)
 23727  	if int32(p) == memMin {
 23728  		prg.obliterated(t)
 23729  		prg.putGetError()
 23730  	} else if int32(*(*prg.mem[p].hh()).b0()) != pictureType {
 23731  		{
 23732  			if int32(prg.interaction) == errorStopMode {
 23733  			}
 23734  			prg.printNl(strNumber( /* "! " */ 261))
 23735  			prg.print( /* "Variable " */ 790) /* \xref[!\relax]  */
 23736  		}
 23737  		prg.showTokenList(int32(t), memMin, 1000, 0)
 23738  		// \xref[Variable x is the wrong type]
 23739  		prg.print( /* " is the wrong type (" */ 968)
 23740  		prg.printType(*(*prg.mem[p].hh()).b0())
 23741  		prg.printChar(asciiCode(')'))
 23742  		{
 23743  			prg.helpPtr = 2
 23744  			prg.helpLine[1] = /* "I was looking for a \"known\" picture variable." */ 969
 23745  			prg.helpLine[0] = /* "So I'll not change anything just now." */ 970
 23746  		}
 23747  		prg.putGetError()
 23748  	} else {
 23749  		prg.curEdges = uint16(*prg.mem[int32(p)+1].int())
 23750  	}
 23751  	prg.flushNodeList(t)
 23752  }
 23753  
 23754  func (prg *prg) doAddTo() {
 23755  	var (
 23756  		lhs, rhs                                     halfword // variable on left, path on right
 23757  		w                                            int32    // tentative weight
 23758  		p                                            halfword // list manipulation register
 23759  		q                                            halfword // beginning of second half of doubled path
 23760  		addToType/* doublePathCode..alsoCode */ byte          // modifier of \&[addto]
 23761  	)
 23762  	prg.getXNext()
 23763  	prg.varFlag = byte(thingToAdd)
 23764  	prg.scanPrimary()
 23765  	if int32(prg.curType) != tokenList {
 23766  		prg.dispErr(halfword(memMin), strNumber( /* "Not a suitable variable" */ 971))
 23767  		// \xref[Not a suitable variable]
 23768  		{
 23769  			prg.helpPtr = 4
 23770  			prg.helpLine[3] = /* "At this point I needed to see the name of a picture variable." */ 972
 23771  			prg.helpLine[2] = /* "(Or perhaps you have indeed presented me with one; I might" */ 973
 23772  			prg.helpLine[1] = /* "have missed it, if it wasn't followed by the proper token.)" */ 974
 23773  			prg.helpLine[0] = /* "So I'll not change anything just now." */ 970
 23774  		}
 23775  		prg.putGetFlushError(scaled(0))
 23776  	} else {
 23777  		lhs = uint16(prg.curExp)
 23778  		addToType = byte(prg.curMod)
 23779  
 23780  		prg.curType = byte(vacuous)
 23781  		prg.getXNext()
 23782  		prg.scanExpression()
 23783  		if int32(addToType) == alsoCode {
 23784  			prg.findEdgesVar(lhs)
 23785  			if int32(prg.curEdges) == memMin {
 23786  				prg.flushCurExp(scaled(0))
 23787  			} else if int32(prg.curType) != pictureType {
 23788  				prg.dispErr(halfword(memMin), strNumber( /* "Improper `addto'" */ 975))
 23789  				// \xref[Improper `addto']
 23790  				{
 23791  					prg.helpPtr = 2
 23792  					prg.helpLine[1] = /* "This expression should have specified a known picture." */ 976
 23793  					prg.helpLine[0] = /* "So I'll not change anything just now." */ 970
 23794  				}
 23795  				prg.putGetFlushError(scaled(0))
 23796  			} else {
 23797  				prg.mergeEdges(halfword(prg.curExp))
 23798  				prg.flushCurExp(scaled(0))
 23799  			}
 23800  		} else {
 23801  			// Get ready to fill a contour, and fill it
 23802  			if int32(prg.curType) == pairType {
 23803  				prg.pairToPath()
 23804  			}
 23805  			if int32(prg.curType) != pathType {
 23806  				prg.dispErr(halfword(memMin), strNumber( /* "Improper `addto'" */ 975))
 23807  				// \xref[Improper `addto']
 23808  				{
 23809  					prg.helpPtr = 2
 23810  					prg.helpLine[1] = /* "This expression should have been a known path." */ 977
 23811  					prg.helpLine[0] = /* "So I'll not change anything just now." */ 970
 23812  				}
 23813  				prg.putGetFlushError(scaled(0))
 23814  				prg.flushTokenList(lhs)
 23815  			} else {
 23816  				rhs = uint16(prg.curExp)
 23817  				w = 1
 23818  				prg.curPen = uint16(memMin + 3)
 23819  				for int32(prg.curCmd) == withOption {
 23820  					if prg.scanWith() {
 23821  						if int32(prg.curType) == known {
 23822  							w = prg.curExp
 23823  						} else {
 23824  							// Change the tentative pen
 23825  							if int32(*(*prg.mem[prg.curPen].hh()).lh()) == memMin {
 23826  								prg.tossPen(prg.curPen)
 23827  							} else {
 23828  								*(*prg.mem[prg.curPen].hh()).lh() = uint16(int32(*(*prg.mem[prg.curPen].hh()).lh()) - 1)
 23829  							}
 23830  							prg.curPen = uint16(prg.curExp)
 23831  						}
 23832  					}
 23833  				}
 23834  
 23835  				// Complete the contour filling operation
 23836  				prg.findEdgesVar(lhs)
 23837  				if int32(prg.curEdges) == memMin {
 23838  					prg.tossKnotList(rhs)
 23839  				} else {
 23840  					lhs = uint16(memMin)
 23841  					prg.curPathType = addToType
 23842  					if int32(*(*prg.mem[rhs].hh()).b0()) == endpoint {
 23843  						if int32(prg.curPathType) == doublePathCode {
 23844  							if int32(*(*prg.mem[rhs].hh()).rh()) == int32(rhs) {
 23845  								*prg.mem[int32(rhs)+5].int() = *prg.mem[int32(rhs)+1].int()
 23846  								*prg.mem[int32(rhs)+6].int() = *prg.mem[int32(rhs)+2].int()
 23847  								*prg.mem[int32(rhs)+3].int() = *prg.mem[int32(rhs)+1].int()
 23848  								*prg.mem[int32(rhs)+4].int() = *prg.mem[int32(rhs)+2].int()
 23849  								*(*prg.mem[rhs].hh()).b0() = byte(explicit)
 23850  								*(*prg.mem[rhs].hh()).b1() = byte(explicit)
 23851  							} else {
 23852  								p = prg.htapYpoc(rhs)
 23853  								q = *(*prg.mem[p].hh()).rh()
 23854  
 23855  								*prg.mem[int32(prg.pathTail)+5].int() = *prg.mem[int32(q)+5].int()
 23856  								*prg.mem[int32(prg.pathTail)+6].int() = *prg.mem[int32(q)+6].int()
 23857  								*(*prg.mem[prg.pathTail].hh()).b1() = *(*prg.mem[q].hh()).b1()
 23858  								*(*prg.mem[prg.pathTail].hh()).rh() = *(*prg.mem[q].hh()).rh()
 23859  								prg.freeNode(q, halfword(knotNodeSize))
 23860  
 23861  								*prg.mem[int32(p)+5].int() = *prg.mem[int32(rhs)+5].int()
 23862  								*prg.mem[int32(p)+6].int() = *prg.mem[int32(rhs)+6].int()
 23863  								*(*prg.mem[p].hh()).b1() = *(*prg.mem[rhs].hh()).b1()
 23864  								*(*prg.mem[p].hh()).rh() = *(*prg.mem[rhs].hh()).rh()
 23865  								prg.freeNode(rhs, halfword(knotNodeSize))
 23866  
 23867  								rhs = p
 23868  							}
 23869  						} else {
 23870  							// Complain about non-cycle and |goto not_found|
 23871  							{
 23872  								if int32(prg.interaction) == errorStopMode {
 23873  								}
 23874  								prg.printNl(strNumber( /* "! " */ 261))
 23875  								prg.print( /* "Not a cycle" */ 978) /* \xref[!\relax]  */
 23876  							}
 23877  							// \xref[Not a cycle]
 23878  							{
 23879  								prg.helpPtr = 2
 23880  								prg.helpLine[1] = /* "That contour should have ended with `..cycle' or `&cycle'." */ 979
 23881  								prg.helpLine[0] = /* "So I'll not change anything just now." */ 970
 23882  							}
 23883  							prg.putGetError()
 23884  							prg.tossKnotList(rhs)
 23885  							goto notFound
 23886  						}
 23887  					} else if int32(prg.curPathType) == doublePathCode {
 23888  						lhs = prg.htapYpoc(rhs)
 23889  					}
 23890  					prg.curWt = w
 23891  					rhs = prg.makeSpec(rhs, *prg.mem[int32(prg.curPen)+9].int(), prg.internal[tracingSpecs-1])
 23892  
 23893  					// Check the turning number
 23894  					if prg.turningNumber <= 0 {
 23895  						if int32(prg.curPathType) != doublePathCode {
 23896  							if prg.internal[turningCheck-1] > 0 {
 23897  								if prg.turningNumber < 0 && int32(*(*prg.mem[prg.curPen].hh()).rh()) == memMin {
 23898  									prg.curWt = -prg.curWt
 23899  								} else {
 23900  									if prg.turningNumber == 0 {
 23901  										if prg.internal[turningCheck-1] <= 0200000 && int32(*(*prg.mem[prg.curPen].hh()).rh()) == memMin {
 23902  											goto done
 23903  										} else {
 23904  											prg.printStrange(strNumber( /* "Strange path (turning number is zero)" */ 980))
 23905  										}
 23906  									} else {
 23907  										prg.printStrange(strNumber( /* "Backwards path (turning number is negative)" */ 981))
 23908  									}
 23909  									// \xref[Backwards path...]
 23910  									{
 23911  										prg.helpPtr = 3
 23912  										prg.helpLine[2] = /* "The path doesn't have a counterclockwise orientation," */ 982
 23913  										prg.helpLine[1] = /* "so I'll probably have trouble drawing it." */ 983
 23914  										prg.helpLine[0] = /* "(See Chapter 27 of The METAFONTbook for more help.)" */ 984
 23915  									}
 23916  									// \xref[METAFONTbook][\sl The [\logos METAFONT\/]book]
 23917  									prg.putGetError()
 23918  								}
 23919  							}
 23920  						}
 23921  					}
 23922  
 23923  				done:
 23924  					;
 23925  					if *prg.mem[int32(prg.curPen)+9].int() == 0 {
 23926  						prg.fillSpec(rhs)
 23927  					} else {
 23928  						prg.fillEnvelope(rhs)
 23929  					}
 23930  					if int32(lhs) != memMin {
 23931  						prg.revTurns = true
 23932  						lhs = prg.makeSpec(lhs, *prg.mem[int32(prg.curPen)+9].int(), prg.internal[tracingSpecs-1])
 23933  						prg.revTurns = false
 23934  						if *prg.mem[int32(prg.curPen)+9].int() == 0 {
 23935  							prg.fillSpec(lhs)
 23936  						} else {
 23937  							prg.fillEnvelope(lhs)
 23938  						}
 23939  					}
 23940  
 23941  				notFound:
 23942  				}
 23943  				if int32(*(*prg.mem[prg.curPen].hh()).lh()) == memMin {
 23944  					prg.tossPen(prg.curPen)
 23945  				} else {
 23946  					*(*prg.mem[prg.curPen].hh()).lh() = uint16(int32(*(*prg.mem[prg.curPen].hh()).lh()) - 1)
 23947  				}
 23948  			}
 23949  		}
 23950  	}
 23951  }
 23952  
 23953  // \4
 23954  // Declare the function called |tfm_check|
 23955  func (prg *prg) tfmCheck(m smallNumber) (r scaled) {
 23956  	if abs(prg.internal[m-1]) >= 01000000000 {
 23957  		{
 23958  			if int32(prg.interaction) == errorStopMode {
 23959  			}
 23960  			prg.printNl(strNumber( /* "! " */ 261))
 23961  			prg.print( /* "Enormous " */ 1001) /* \xref[!\relax]  */
 23962  		}
 23963  		prg.print(int32(prg.intName[m-1]))
 23964  		// \xref[Enormous charwd...]
 23965  		// \xref[Enormous chardp...]
 23966  		// \xref[Enormous charht...]
 23967  		// \xref[Enormous charic...]
 23968  		// \xref[Enormous designsize...]
 23969  		prg.print( /* " has been reduced" */ 1002)
 23970  		{
 23971  			prg.helpPtr = 1
 23972  			prg.helpLine[0] = /* "Font metric dimensions must be less than 2048pt." */ 1003
 23973  		}
 23974  		prg.putGetError()
 23975  		if prg.internal[m-1] > 0 {
 23976  			r = 01000000000 - 1
 23977  		} else {
 23978  			r = 1 - 01000000000
 23979  		}
 23980  	} else {
 23981  		r = prg.internal[m-1]
 23982  	}
 23983  	return r
 23984  }
 23985  
 23986  func (prg *prg) doShipOut() {
 23987  	var (
 23988  		c int32 // the character code
 23989  	)
 23990  	prg.getXNext()
 23991  	prg.varFlag = byte(semicolon)
 23992  	prg.scanExpression()
 23993  	if int32(prg.curType) != tokenList {
 23994  		if int32(prg.curType) == pictureType {
 23995  			prg.curEdges = uint16(prg.curExp)
 23996  		} else {
 23997  			{
 23998  				prg.dispErr(halfword(memMin), strNumber( /* "Not a suitable variable" */ 971))
 23999  				// \xref[Not a suitable variable]
 24000  				{
 24001  					prg.helpPtr = 4
 24002  					prg.helpLine[3] = /* "At this point I needed to see the name of a picture variable." */ 972
 24003  					prg.helpLine[2] = /* "(Or perhaps you have indeed presented me with one; I might" */ 973
 24004  					prg.helpLine[1] = /* "have missed it, if it wasn't followed by the proper token.)" */ 974
 24005  					prg.helpLine[0] = /* "So I'll not change anything just now." */ 970
 24006  				}
 24007  				prg.putGetFlushError(scaled(0))
 24008  			}
 24009  
 24010  			goto exit
 24011  		}
 24012  	} else {
 24013  		prg.findEdgesVar(halfword(prg.curExp))
 24014  		prg.curType = byte(vacuous)
 24015  	}
 24016  	if int32(prg.curEdges) != memMin {
 24017  		c = prg.roundUnscaled(prg.internal[charCode-1]) % 256
 24018  		if c < 0 {
 24019  			c = c + 256
 24020  		}
 24021  
 24022  		// Store the width information for character code~|c|
 24023  		if c < int32(prg.bc) {
 24024  			prg.bc = byte(c)
 24025  		}
 24026  		if c > int32(prg.ec) {
 24027  			prg.ec = byte(c)
 24028  		}
 24029  		prg.charExists[c] = true
 24030  		prg.gfDx[c] = prg.internal[charDx-1]
 24031  		prg.gfDy[c] = prg.internal[charDy-1]
 24032  		prg.tfmWidth[c] = prg.tfmCheck(smallNumber(charWd))
 24033  		prg.tfmHeight[c] = prg.tfmCheck(smallNumber(charHt))
 24034  		prg.tfmDepth[c] = prg.tfmCheck(smallNumber(charDp))
 24035  		prg.tfmItalCorr[c] = prg.tfmCheck(smallNumber(charIc))
 24036  		if prg.internal[proofing-1] >= 0 {
 24037  			prg.shipOut(eightBits(c))
 24038  		}
 24039  	}
 24040  	prg.flushCurExp(scaled(0))
 24041  
 24042  exit:
 24043  }
 24044  
 24045  func (prg *prg) doDisplay() {
 24046  	var (
 24047  		e halfword // token list for a picture variable
 24048  	)
 24049  	prg.getXNext()
 24050  	prg.varFlag = byte(inWindow)
 24051  	prg.scanPrimary()
 24052  	if int32(prg.curType) != tokenList {
 24053  		prg.dispErr(halfword(memMin), strNumber( /* "Not a suitable variable" */ 971))
 24054  		// \xref[Not a suitable variable]
 24055  		{
 24056  			prg.helpPtr = 4
 24057  			prg.helpLine[3] = /* "At this point I needed to see the name of a picture variable." */ 972
 24058  			prg.helpLine[2] = /* "(Or perhaps you have indeed presented me with one; I might" */ 973
 24059  			prg.helpLine[1] = /* "have missed it, if it wasn't followed by the proper token.)" */ 974
 24060  			prg.helpLine[0] = /* "So I'll not change anything just now." */ 970
 24061  		}
 24062  		prg.putGetFlushError(scaled(0))
 24063  	} else {
 24064  		e = uint16(prg.curExp)
 24065  		prg.curType = byte(vacuous)
 24066  		prg.getXNext()
 24067  		prg.scanExpression()
 24068  		if int32(prg.curType) != known {
 24069  			goto commonEnding
 24070  		}
 24071  		prg.curExp = prg.roundUnscaled(prg.curExp)
 24072  		if prg.curExp < 0 {
 24073  			goto notFound
 24074  		}
 24075  		if prg.curExp > 15 {
 24076  			goto notFound
 24077  		}
 24078  		if !prg.windowOpen[prg.curExp] {
 24079  			goto notFound
 24080  		}
 24081  		prg.findEdgesVar(e)
 24082  		if int32(prg.curEdges) != memMin {
 24083  			prg.dispEdges(windowNumber(prg.curExp))
 24084  		}
 24085  
 24086  		goto exit
 24087  
 24088  	notFound:
 24089  		prg.curExp = prg.curExp * 0200000
 24090  
 24091  	commonEnding:
 24092  		prg.dispErr(halfword(memMin), strNumber( /* "Bad window number" */ 985))
 24093  		// \xref[Bad window number]
 24094  		{
 24095  			prg.helpPtr = 1
 24096  			prg.helpLine[0] = /* "It should be the number of an open window." */ 986
 24097  		}
 24098  		prg.putGetFlushError(scaled(0))
 24099  		prg.flushTokenList(e)
 24100  	}
 24101  
 24102  exit:
 24103  }
 24104  
 24105  func (prg *prg) getPair(c commandCode) (r bool) {
 24106  	var (
 24107  		p halfword // a pair of values that are known (we hope)
 24108  		b bool     // did we find such a pair?
 24109  	)
 24110  	if int32(prg.curCmd) != int32(c) {
 24111  		r = false
 24112  	} else {
 24113  		prg.getXNext()
 24114  		prg.scanExpression()
 24115  		if prg.nicePair(prg.curExp, prg.curType) {
 24116  			p = uint16(*prg.mem[prg.curExp+1].int())
 24117  			prg.curX = *prg.mem[int32(p)+1].int()
 24118  			prg.curY = *prg.mem[int32(p)+2+1].int()
 24119  			b = true
 24120  		} else {
 24121  			b = false
 24122  		}
 24123  		prg.flushCurExp(scaled(0))
 24124  		r = b
 24125  	}
 24126  	return r
 24127  }
 24128  
 24129  func (prg *prg) doOpenWindow() {
 24130  	var (
 24131  		k               int32  // the window number in question
 24132  		r0, c0, r11, c1 scaled // window coordinates
 24133  	)
 24134  	prg.getXNext()
 24135  	prg.scanExpression()
 24136  	if int32(prg.curType) != known {
 24137  		goto notFound
 24138  	}
 24139  	k = prg.roundUnscaled(prg.curExp)
 24140  	if k < 0 {
 24141  		goto notFound
 24142  	}
 24143  	if k > 15 {
 24144  		goto notFound
 24145  	}
 24146  	if !prg.getPair(commandCode(fromToken)) {
 24147  		goto notFound
 24148  	}
 24149  	r0 = prg.curX
 24150  	c0 = prg.curY
 24151  	if !prg.getPair(commandCode(toToken)) {
 24152  		goto notFound
 24153  	}
 24154  	r11 = prg.curX
 24155  	c1 = prg.curY
 24156  	if !prg.getPair(commandCode(atToken)) {
 24157  		goto notFound
 24158  	}
 24159  	prg.openAWindow(windowNumber(k), r0, c0, r11, c1, prg.curX, prg.curY)
 24160  	goto exit
 24161  
 24162  notFound:
 24163  	{
 24164  		if int32(prg.interaction) == errorStopMode {
 24165  		}
 24166  		prg.printNl(strNumber( /* "! " */ 261))
 24167  		prg.print( /* "Improper `openwindow'" */ 987) /* \xref[!\relax]  */
 24168  	}
 24169  	// \xref[Improper `openwindow']
 24170  	{
 24171  		prg.helpPtr = 2
 24172  		prg.helpLine[1] = /* "Say `openwindow k from (r0,c0) to (r1,c1) at (x,y)'," */ 988
 24173  		prg.helpLine[0] = /* "where all quantities are known and k is between 0 and 15." */ 989
 24174  	}
 24175  	prg.putGetError()
 24176  
 24177  exit:
 24178  }
 24179  
 24180  func (prg *prg) doCull() {
 24181  	var (
 24182  		e                                    halfword // token list for a picture variable
 24183  		keeping/* dropCode..keepCode */ byte          // modifier of |cull_op|
 24184  		w, wIn, wOut                         int32    // culling weights
 24185  	)
 24186  	w = 1
 24187  	prg.getXNext()
 24188  	prg.varFlag = byte(cullOp)
 24189  	prg.scanPrimary()
 24190  	if int32(prg.curType) != tokenList {
 24191  		prg.dispErr(halfword(memMin), strNumber( /* "Not a suitable variable" */ 971))
 24192  		// \xref[Not a suitable variable]
 24193  		{
 24194  			prg.helpPtr = 4
 24195  			prg.helpLine[3] = /* "At this point I needed to see the name of a picture variable." */ 972
 24196  			prg.helpLine[2] = /* "(Or perhaps you have indeed presented me with one; I might" */ 973
 24197  			prg.helpLine[1] = /* "have missed it, if it wasn't followed by the proper token.)" */ 974
 24198  			prg.helpLine[0] = /* "So I'll not change anything just now." */ 970
 24199  		}
 24200  		prg.putGetFlushError(scaled(0))
 24201  	} else {
 24202  		e = uint16(prg.curExp)
 24203  		prg.curType = byte(vacuous)
 24204  		keeping = byte(prg.curMod)
 24205  		if !prg.getPair(commandCode(cullOp)) {
 24206  			goto notFound
 24207  		}
 24208  		for int32(prg.curCmd) == withOption && prg.curMod == known {
 24209  			if prg.scanWith() {
 24210  				w = prg.curExp
 24211  			}
 24212  		}
 24213  
 24214  		// Set up the culling weights, or |goto not_found| if the thresholds are bad
 24215  		if prg.curX > prg.curY {
 24216  			goto notFound
 24217  		}
 24218  		if int32(keeping) == dropCode {
 24219  			if prg.curX > 0 || prg.curY < 0 {
 24220  				goto notFound
 24221  			}
 24222  			wOut = w
 24223  			wIn = 0
 24224  		} else {
 24225  			if prg.curX <= 0 && prg.curY >= 0 {
 24226  				goto notFound
 24227  			}
 24228  			wOut = 0
 24229  			wIn = w
 24230  		}
 24231  		prg.findEdgesVar(e)
 24232  		if int32(prg.curEdges) != memMin {
 24233  			prg.cullEdges(prg.floorUnscaled(prg.curX+0200000-1), prg.floorUnscaled(prg.curY), wOut, wIn)
 24234  		}
 24235  
 24236  		goto exit
 24237  
 24238  	notFound:
 24239  		{
 24240  			if int32(prg.interaction) == errorStopMode {
 24241  			}
 24242  			prg.printNl(strNumber( /* "! " */ 261))
 24243  			prg.print( /* "Bad culling amounts" */ 990) /* \xref[!\relax]  */
 24244  		}
 24245  		// \xref[Bad culling amounts]
 24246  		{
 24247  			prg.helpPtr = 1
 24248  			prg.helpLine[0] = /* "Always cull by known amounts that exclude 0." */ 991
 24249  		}
 24250  		prg.putGetError()
 24251  		prg.flushTokenList(e)
 24252  	}
 24253  
 24254  exit:
 24255  }
 24256  
 24257  func (prg *prg) doMessage() {
 24258  	var (
 24259  		m /* messageCode..errHelpCode */ byte // the type of message
 24260  	)
 24261  	m = byte(prg.curMod)
 24262  	prg.getXNext()
 24263  	prg.scanExpression()
 24264  	if int32(prg.curType) != stringType {
 24265  		prg.dispErr(halfword(memMin), strNumber( /* "Not a string" */ 699))
 24266  		// \xref[Not a string]
 24267  		{
 24268  			prg.helpPtr = 1
 24269  			prg.helpLine[0] = /* "A message should be a known string expression." */ 995
 24270  		}
 24271  		prg.putGetError()
 24272  	} else {
 24273  		switch m {
 24274  		case messageCode:
 24275  			prg.printNl(strNumber( /* "" */ 285))
 24276  			prg.slowPrint(prg.curExp)
 24277  
 24278  		case errMessageCode:
 24279  			// Print string |cur_exp| as an error message
 24280  			{
 24281  				if int32(prg.interaction) == errorStopMode {
 24282  				}
 24283  				prg.printNl(strNumber( /* "! " */ 261))
 24284  				prg.print( /* "" */ 285) /* \xref[!\relax]  */
 24285  			}
 24286  			prg.slowPrint(prg.curExp)
 24287  			if int32(prg.errHelp) != 0 {
 24288  				prg.useErrHelp = true
 24289  			} else if prg.longHelpSeen {
 24290  				prg.helpPtr = 1
 24291  				prg.helpLine[0] = /* "(That was another `errmessage'.)" */ 996
 24292  			} else {
 24293  				if int32(prg.interaction) < errorStopMode {
 24294  					prg.longHelpSeen = true
 24295  				}
 24296  				{
 24297  					prg.helpPtr = 4
 24298  					prg.helpLine[3] = /* "This error message was generated by an `errmessage'" */ 997
 24299  					prg.helpLine[2] = /* "command, so I can't give any explicit help." */ 998
 24300  					prg.helpLine[1] = /* "Pretend that you're Miss Marple: Examine all clues," */ 999
 24301  					prg.helpLine[0] = /* "and deduce the truth by inspired guesses." */ 1000
 24302  				}
 24303  			}
 24304  			prg.putGetError()
 24305  			prg.useErrHelp = false
 24306  
 24307  		case errHelpCode:
 24308  			// Save string |cur_exp| as the |err_help|
 24309  			if int32(prg.errHelp) != 0 {
 24310  				if int32(prg.strRef[prg.errHelp]) < maxStrRef {
 24311  					if int32(prg.strRef[prg.errHelp]) > 1 {
 24312  						prg.strRef[prg.errHelp] = byte(int32(prg.strRef[prg.errHelp]) - 1)
 24313  					} else {
 24314  						prg.flushString(prg.errHelp)
 24315  					}
 24316  				}
 24317  			}
 24318  			if int32(prg.strStart[prg.curExp+1])-int32(prg.strStart[prg.curExp]) == 0 {
 24319  				prg.errHelp = 0
 24320  			} else {
 24321  				prg.errHelp = uint16(prg.curExp)
 24322  				{
 24323  					if int32(prg.strRef[prg.errHelp]) < maxStrRef {
 24324  						prg.strRef[prg.errHelp] = byte(int32(prg.strRef[prg.errHelp]) + 1)
 24325  					}
 24326  				}
 24327  			}
 24328  
 24329  		}
 24330  	} // there are no other cases
 24331  	prg.flushCurExp(scaled(0))
 24332  }
 24333  
 24334  func (prg *prg) getCode() (r eightBits) {
 24335  	var (
 24336  		c int32 // the code value found
 24337  	)
 24338  	prg.getXNext()
 24339  	prg.scanExpression()
 24340  	if int32(prg.curType) == known {
 24341  		c = prg.roundUnscaled(prg.curExp)
 24342  		if c >= 0 {
 24343  			if c < 256 {
 24344  				goto found
 24345  			}
 24346  		}
 24347  	} else if int32(prg.curType) == stringType {
 24348  		if int32(prg.strStart[prg.curExp+1])-int32(prg.strStart[prg.curExp]) == 1 {
 24349  			c = int32(prg.strPool[prg.strStart[prg.curExp]])
 24350  			goto found
 24351  		}
 24352  	}
 24353  	prg.dispErr(halfword(memMin), strNumber( /* "Invalid code has been replaced by 0" */ 1009))
 24354  	// \xref[Invalid code...]
 24355  	{
 24356  		prg.helpPtr = 2
 24357  		prg.helpLine[1] = /* "I was looking for a number between 0 and 255, or for a" */ 1010
 24358  		prg.helpLine[0] = /* "string of length 1. Didn't find it; will use 0 instead." */ 1011
 24359  	}
 24360  	prg.putGetFlushError(scaled(0))
 24361  	c = 0
 24362  
 24363  found:
 24364  	r = byte(c)
 24365  	return r
 24366  }
 24367  
 24368  func (prg *prg) setTag(c halfword, t smallNumber, r1 halfword) {
 24369  	if int32(prg.charTag[c]) == noTag {
 24370  		prg.charTag[c] = t
 24371  		prg.charRemainder[c] = r1
 24372  		if int32(t) == ligTag {
 24373  			prg.labelPtr = uint16(int32(prg.labelPtr) + 1)
 24374  			prg.labelLoc[prg.labelPtr] = int16(r1)
 24375  			prg.labelChar[prg.labelPtr-1] = byte(c)
 24376  		}
 24377  	} else {
 24378  		// Complain about a character tag conflict
 24379  		{
 24380  			if int32(prg.interaction) == errorStopMode {
 24381  			}
 24382  			prg.printNl(strNumber( /* "! " */ 261))
 24383  			prg.print( /* "Character " */ 1012) /* \xref[!\relax]  */
 24384  		}
 24385  		if int32(c) > ' ' && int32(c) < 127 {
 24386  			prg.print(int32(c))
 24387  		} else if int32(c) == 256 {
 24388  			prg.print( /* "||" */ 1013)
 24389  		} else {
 24390  			prg.print( /* "code " */ 1014)
 24391  			prg.printInt(int32(c))
 24392  		}
 24393  		prg.print( /* " is already " */ 1015)
 24394  		// \xref[Character c is already...]
 24395  		switch prg.charTag[c] {
 24396  		case ligTag:
 24397  			prg.print( /* "in a ligtable" */ 1016)
 24398  		case listTag:
 24399  			prg.print( /* "in a charlist" */ 1017)
 24400  		case extTag:
 24401  			prg.print( /* "extensible" */ 1006)
 24402  		} // there are no other cases
 24403  		{
 24404  			prg.helpPtr = 2
 24405  			prg.helpLine[1] = /* "It's not legal to label a character more than once." */ 1018
 24406  			prg.helpLine[0] = /* "So I'll not change anything just now." */ 970
 24407  		}
 24408  		prg.putGetError()
 24409  	}
 24410  }
 24411  
 24412  func (prg *prg) doTfmCommand() {
 24413  	var (
 24414  		c, cc/* 0..256 */ uint16        // character codes
 24415  		k/* 0..maxKerns */ uint16       // index into the |kern| array
 24416  		j                         int32 // index into |header_byte| or |param|
 24417  	)
 24418  	switch prg.curMod {
 24419  	case charListCode:
 24420  		c = uint16(prg.getCode())
 24421  		// we will store a list of character successors
 24422  		for int32(prg.curCmd) == colon {
 24423  			cc = uint16(prg.getCode())
 24424  			prg.setTag(c, smallNumber(listTag), cc)
 24425  			c = cc
 24426  		}
 24427  
 24428  	case ligTableCode:
 24429  		// Store a list of ligature/kern steps
 24430  		prg.lkStarted = false
 24431  
 24432  	continue1:
 24433  		prg.getXNext()
 24434  		if int32(prg.curCmd) == skipTo && prg.lkStarted {
 24435  			c = uint16(prg.getCode())
 24436  			if int32(prg.nl)-int32(prg.skipTable[c]) > 128 {
 24437  				{
 24438  					{
 24439  						if int32(prg.interaction) == errorStopMode {
 24440  						}
 24441  						prg.printNl(strNumber( /* "! " */ 261))
 24442  						prg.print( /* "Too far to skip" */ 1035) /* \xref[!\relax]  */
 24443  					} /* \xref[Too far to skip]  */
 24444  					{
 24445  						prg.helpPtr = 1
 24446  						prg.helpLine[0] = /* "At most 127 lig/kern steps can separate skipto1 from 1::." */ 1036
 24447  					}
 24448  					prg.error1()
 24449  					prg.ll = prg.skipTable[c]
 24450  					for {
 24451  						prg.lll = uint16(int32(prg.ligKern[prg.ll].b0) - minQuarterword)
 24452  						prg.ligKern[prg.ll].b0 = byte(stopFlag)
 24453  						prg.ll = uint16(int32(prg.ll) - int32(prg.lll))
 24454  						if int32(prg.lll) == 0 {
 24455  							break
 24456  						}
 24457  					}
 24458  				}
 24459  				prg.skipTable[c] = uint16(ligTableSize)
 24460  			}
 24461  			if int32(prg.skipTable[c]) == ligTableSize {
 24462  				prg.ligKern[int32(prg.nl)-1].b0 = byte(0 + minQuarterword)
 24463  			} else {
 24464  				prg.ligKern[int32(prg.nl)-1].b0 = byte(int32(prg.nl) - int32(prg.skipTable[c]) - 1 + minQuarterword)
 24465  			}
 24466  			prg.skipTable[c] = uint16(int32(prg.nl) - 1)
 24467  			goto done
 24468  		}
 24469  		if int32(prg.curCmd) == bcharLabel {
 24470  			c = 256
 24471  			prg.curCmd = byte(colon)
 24472  		} else {
 24473  			prg.backInput()
 24474  			c = uint16(prg.getCode())
 24475  		}
 24476  		if int32(prg.curCmd) == colon || int32(prg.curCmd) == doubleColon {
 24477  			if int32(prg.curCmd) == colon {
 24478  				if int32(c) == 256 {
 24479  					prg.bchLabel = prg.nl
 24480  				} else {
 24481  					prg.setTag(c, smallNumber(ligTag), prg.nl)
 24482  				}
 24483  			} else if int32(prg.skipTable[c]) < ligTableSize {
 24484  				prg.ll = prg.skipTable[c]
 24485  				prg.skipTable[c] = uint16(ligTableSize)
 24486  				for {
 24487  					prg.lll = uint16(int32(prg.ligKern[prg.ll].b0) - minQuarterword)
 24488  					if int32(prg.nl)-int32(prg.ll) > 128 {
 24489  						{
 24490  							{
 24491  								if int32(prg.interaction) == errorStopMode {
 24492  								}
 24493  								prg.printNl(strNumber( /* "! " */ 261))
 24494  								prg.print( /* "Too far to skip" */ 1035) /* \xref[!\relax]  */
 24495  							} /* \xref[Too far to skip]  */
 24496  							{
 24497  								prg.helpPtr = 1
 24498  								prg.helpLine[0] = /* "At most 127 lig/kern steps can separate skipto1 from 1::." */ 1036
 24499  							}
 24500  							prg.error1()
 24501  							prg.ll = prg.ll
 24502  							for {
 24503  								prg.lll = uint16(int32(prg.ligKern[prg.ll].b0) - minQuarterword)
 24504  								prg.ligKern[prg.ll].b0 = byte(stopFlag)
 24505  								prg.ll = uint16(int32(prg.ll) - int32(prg.lll))
 24506  								if int32(prg.lll) == 0 {
 24507  									break
 24508  								}
 24509  							}
 24510  						}
 24511  						goto continue1
 24512  					}
 24513  					prg.ligKern[prg.ll].b0 = byte(int32(prg.nl) - int32(prg.ll) - 1 + minQuarterword)
 24514  					prg.ll = uint16(int32(prg.ll) - int32(prg.lll))
 24515  					if int32(prg.lll) == 0 {
 24516  						break
 24517  					}
 24518  				}
 24519  			}
 24520  
 24521  			goto continue1
 24522  		}
 24523  		if int32(prg.curCmd) == ligKernToken {
 24524  			prg.ligKern[prg.nl].b1 = byte(int32(c) + minQuarterword)
 24525  			prg.ligKern[prg.nl].b0 = byte(0 + minQuarterword)
 24526  			if prg.curMod < 128 {
 24527  				prg.ligKern[prg.nl].b2 = byte(prg.curMod + minQuarterword)
 24528  				prg.ligKern[prg.nl].b3 = byte(int32(prg.getCode()) + minQuarterword)
 24529  			} else {
 24530  				prg.getXNext()
 24531  				prg.scanExpression()
 24532  				if int32(prg.curType) != known {
 24533  					prg.dispErr(halfword(memMin), strNumber( /* "Improper kern" */ 1037))
 24534  					// \xref[Improper kern]
 24535  					{
 24536  						prg.helpPtr = 2
 24537  						prg.helpLine[1] = /* "The amount of kern should be a known numeric value." */ 1038
 24538  						prg.helpLine[0] = /* "I'm zeroing this one. Proceed, with fingers crossed." */ 309
 24539  					}
 24540  					prg.putGetFlushError(scaled(0))
 24541  				}
 24542  				prg.kern[prg.nk] = prg.curExp
 24543  				k = 0
 24544  				for prg.kern[k] != prg.curExp {
 24545  					k = uint16(int32(k) + 1)
 24546  				}
 24547  				if int32(k) == int32(prg.nk) {
 24548  					if int32(prg.nk) == maxKerns {
 24549  						prg.overflow(strNumber( /* "kern" */ 1034), maxKerns)
 24550  					}
 24551  					// \xref[METAFONT capacity exceeded kern][\quad kern]
 24552  					prg.nk = uint16(int32(prg.nk) + 1)
 24553  				}
 24554  				prg.ligKern[prg.nl].b2 = byte(kernFlag + int32(k)/256)
 24555  				prg.ligKern[prg.nl].b3 = byte(int32(k)%256 + minQuarterword)
 24556  			}
 24557  			prg.lkStarted = true
 24558  		} else {
 24559  			{
 24560  				if int32(prg.interaction) == errorStopMode {
 24561  				}
 24562  				prg.printNl(strNumber( /* "! " */ 261))
 24563  				prg.print( /* "Illegal ligtable step" */ 1023) /* \xref[!\relax]  */
 24564  			}
 24565  			// \xref[Illegal ligtable step]
 24566  			{
 24567  				prg.helpPtr = 1
 24568  				prg.helpLine[0] = /* "I was looking for `=:' or `kern' here." */ 1024
 24569  			}
 24570  			prg.backError()
 24571  			prg.ligKern[prg.nl].b1 = byte(0 + minQuarterword)
 24572  			prg.ligKern[prg.nl].b2 = byte(0 + minQuarterword)
 24573  			prg.ligKern[prg.nl].b3 = byte(0 + minQuarterword)
 24574  
 24575  			prg.ligKern[prg.nl].b0 = byte(stopFlag + 1) // this specifies an unconditional stop
 24576  		}
 24577  		if int32(prg.nl) == ligTableSize {
 24578  			prg.overflow(strNumber( /* "ligtable size" */ 1025), ligTableSize)
 24579  		}
 24580  		// \xref[METAFONT capacity exceeded ligtable size][\quad ligtable size]
 24581  		prg.nl = uint16(int32(prg.nl) + 1)
 24582  		if int32(prg.curCmd) == comma {
 24583  			goto continue1
 24584  		}
 24585  		if int32(prg.ligKern[int32(prg.nl)-1].b0) < stopFlag {
 24586  			prg.ligKern[int32(prg.nl)-1].b0 = byte(stopFlag)
 24587  		}
 24588  
 24589  	done:
 24590  		;
 24591  
 24592  	case extensibleCode:
 24593  		// Define an extensible recipe
 24594  		if int32(prg.ne) == 256 {
 24595  			prg.overflow(strNumber( /* "extensible" */ 1006), 256)
 24596  		}
 24597  		// \xref[METAFONT capacity exceeded extensible][\quad extensible]
 24598  		c = uint16(prg.getCode())
 24599  		prg.setTag(c, smallNumber(extTag), prg.ne)
 24600  		if int32(prg.curCmd) != colon {
 24601  			prg.missingErr(strNumber(':')) /* \xref[Missing `\char`\#']  */
 24602  			{
 24603  				prg.helpPtr = 1
 24604  				prg.helpLine[0] = /* "I'm processing `extensible c: t,m,b,r'." */ 1039
 24605  			}
 24606  			prg.backError()
 24607  		}
 24608  		prg.exten[prg.ne].b0 = byte(int32(prg.getCode()) + minQuarterword)
 24609  		if int32(prg.curCmd) != comma {
 24610  			prg.missingErr(strNumber(',')) /* \xref[Missing `\char`\#']  */
 24611  			{
 24612  				prg.helpPtr = 1
 24613  				prg.helpLine[0] = /* "I'm processing `extensible c: t,m,b,r'." */ 1039
 24614  			}
 24615  			prg.backError()
 24616  		}
 24617  		prg.exten[prg.ne].b1 = byte(int32(prg.getCode()) + minQuarterword)
 24618  		if int32(prg.curCmd) != comma {
 24619  			prg.missingErr(strNumber(',')) /* \xref[Missing `\char`\#']  */
 24620  			{
 24621  				prg.helpPtr = 1
 24622  				prg.helpLine[0] = /* "I'm processing `extensible c: t,m,b,r'." */ 1039
 24623  			}
 24624  			prg.backError()
 24625  		}
 24626  		prg.exten[prg.ne].b2 = byte(int32(prg.getCode()) + minQuarterword)
 24627  		if int32(prg.curCmd) != comma {
 24628  			prg.missingErr(strNumber(',')) /* \xref[Missing `\char`\#']  */
 24629  			{
 24630  				prg.helpPtr = 1
 24631  				prg.helpLine[0] = /* "I'm processing `extensible c: t,m,b,r'." */ 1039
 24632  			}
 24633  			prg.backError()
 24634  		}
 24635  		prg.exten[prg.ne].b3 = byte(int32(prg.getCode()) + minQuarterword)
 24636  		prg.ne = uint16(int32(prg.ne) + 1)
 24637  
 24638  	case headerByteCode, fontDimenCode:
 24639  		c = uint16(prg.curMod)
 24640  		prg.getXNext()
 24641  		prg.scanExpression()
 24642  		if int32(prg.curType) != known || prg.curExp < 0100000 {
 24643  			prg.dispErr(halfword(memMin), strNumber( /* "Improper location" */ 1019))
 24644  			// \xref[Improper location]
 24645  			{
 24646  				prg.helpPtr = 2
 24647  				prg.helpLine[1] = /* "I was looking for a known, positive number." */ 1020
 24648  				prg.helpLine[0] = /* "For safety's sake I'll ignore the present command." */ 1021
 24649  			}
 24650  			prg.putGetError()
 24651  		} else {
 24652  			j = prg.roundUnscaled(prg.curExp)
 24653  			if int32(prg.curCmd) != colon {
 24654  				prg.missingErr(strNumber(':'))
 24655  				// \xref[Missing `:']
 24656  				{
 24657  					prg.helpPtr = 1
 24658  					prg.helpLine[0] = /* "A colon should follow a headerbyte or fontdimen location." */ 1022
 24659  				}
 24660  				prg.backError()
 24661  			}
 24662  			if int32(c) == headerByteCode {
 24663  				for {
 24664  					if j > headerSize {
 24665  						prg.overflow(strNumber( /* "headerbyte" */ 1007), headerSize)
 24666  					}
 24667  					// \xref[METAFONT capacity exceeded headerbyte][\quad headerbyte]
 24668  					prg.headerByte[j-1] = int16(prg.getCode())
 24669  					j = j + 1
 24670  					if int32(prg.curCmd) != comma {
 24671  						break
 24672  					}
 24673  				}
 24674  			} else {
 24675  				// Store a list of font dimensions
 24676  				for {
 24677  					if j > maxFontDimen {
 24678  						prg.overflow(strNumber( /* "fontdimen" */ 1008), maxFontDimen)
 24679  					}
 24680  					// \xref[METAFONT capacity exceeded fontdimen][\quad fontdimen]
 24681  					for j > int32(prg.np) {
 24682  						prg.np = byte(int32(prg.np) + 1)
 24683  						prg.param[prg.np-1] = 0
 24684  					}
 24685  					prg.getXNext()
 24686  					prg.scanExpression()
 24687  					if int32(prg.curType) != known {
 24688  						prg.dispErr(halfword(memMin), strNumber( /* "Improper font parameter" */ 1040))
 24689  						// \xref[Improper font parameter]
 24690  						{
 24691  							prg.helpPtr = 1
 24692  							prg.helpLine[0] = /* "I'm zeroing this one. Proceed, with fingers crossed." */ 309
 24693  						}
 24694  						prg.putGetFlushError(scaled(0))
 24695  					}
 24696  					prg.param[j-1] = prg.curExp
 24697  					j = j + 1
 24698  					if int32(prg.curCmd) != comma {
 24699  						break
 24700  					}
 24701  				}
 24702  			}
 24703  		}
 24704  
 24705  	} // there are no other cases
 24706  }
 24707  
 24708  func (prg *prg) doSpecial() {
 24709  	var (
 24710  		m smallNumber // either |string_type| or |known|
 24711  	)
 24712  	m = byte(prg.curMod)
 24713  	prg.getXNext()
 24714  	prg.scanExpression()
 24715  	if prg.internal[proofing-1] >= 0 {
 24716  		if int32(prg.curType) != int32(m) {
 24717  			prg.dispErr(halfword(memMin), strNumber( /* "Unsuitable expression" */ 1060))
 24718  			// \xref[Unsuitable expression]
 24719  			{
 24720  				prg.helpPtr = 1
 24721  				prg.helpLine[0] = /* "The expression shown above has the wrong type to be output." */ 1061
 24722  			}
 24723  			prg.putGetError()
 24724  		} else {
 24725  			if int32(prg.outputFileName) == 0 {
 24726  				prg.initGf()
 24727  			}
 24728  			if int32(m) == stringType {
 24729  				prg.gfString(strNumber(prg.curExp), strNumber(0))
 24730  			} else {
 24731  				{
 24732  					prg.gfBuf[prg.gfPtr] = byte(yyy)
 24733  					prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 24734  					if int32(prg.gfPtr) == int32(prg.gfLimit) {
 24735  						prg.gfSwap()
 24736  					}
 24737  				}
 24738  				prg.gfFour(prg.curExp)
 24739  			}
 24740  		}
 24741  	}
 24742  	prg.flushCurExp(scaled(0))
 24743  }
 24744  
 24745  func (prg *prg) storeBaseFile() {
 24746  	var (
 24747  		k    int32        // all-purpose index
 24748  		p, q halfword     // all-purpose pointers
 24749  		x    int32        // something to dump
 24750  		w    fourQuarters // four ASCII codes
 24751  	)
 24752  	prg.selector = byte(newString)
 24753  	prg.print( /* " (preloaded base=" */ 1071)
 24754  	prg.print(int32(prg.jobName))
 24755  	prg.printChar(asciiCode(' '))
 24756  	prg.printInt(prg.roundUnscaled(prg.internal[year-1]))
 24757  	prg.printChar(asciiCode('.'))
 24758  	prg.printInt(prg.roundUnscaled(prg.internal[month-1]))
 24759  	prg.printChar(asciiCode('.'))
 24760  	prg.printInt(prg.roundUnscaled(prg.internal[day-1]))
 24761  	prg.printChar(asciiCode(')'))
 24762  	if int32(prg.interaction) == batchMode {
 24763  		prg.selector = byte(logOnly)
 24764  	} else {
 24765  		prg.selector = byte(termAndLog)
 24766  	}
 24767  	{
 24768  		if int32(prg.poolPtr)+1 > int32(prg.maxPoolPtr) {
 24769  			if int32(prg.poolPtr)+1 > poolSize {
 24770  				prg.overflow(strNumber( /* "pool size" */ 257), poolSize-int32(prg.initPoolPtr))
 24771  			} /* \xref[METAFONT capacity exceeded pool size][\quad pool size]  */
 24772  			prg.maxPoolPtr = uint16(int32(prg.poolPtr) + 1)
 24773  		}
 24774  	}
 24775  	prg.baseIdent = prg.makeString()
 24776  	prg.strRef[prg.baseIdent] = byte(maxStrRef)
 24777  
 24778  	prg.packJobName(strNumber(baseExtension))
 24779  	for !prg.wOpenOut(prg.baseFile) {
 24780  		prg.promptFileName(strNumber( /* "base file name" */ 1072), strNumber(baseExtension))
 24781  	}
 24782  	prg.printNl(strNumber( /* "Beginning to dump on file " */ 1073))
 24783  	// \xref[Beginning to dump...]
 24784  	prg.slowPrint(int32(prg.wMakeNameString(prg.baseFile)))
 24785  	prg.flushString(strNumber(int32(prg.strPtr) - 1))
 24786  	prg.printNl(strNumber( /* "" */ 285))
 24787  	prg.slowPrint(int32(prg.baseIdent))
 24788  
 24789  	// Dump constants for consistency check
 24790  	{
 24791  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = 461259239
 24792  		prg.baseFile.Put()
 24793  	}
 24794  
 24795  	{
 24796  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = memMin
 24797  		prg.baseFile.Put()
 24798  	}
 24799  
 24800  	{
 24801  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = 3000
 24802  		prg.baseFile.Put()
 24803  	}
 24804  
 24805  	{
 24806  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = hashSize
 24807  		prg.baseFile.Put()
 24808  	}
 24809  
 24810  	{
 24811  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = hashPrime
 24812  		prg.baseFile.Put()
 24813  	}
 24814  
 24815  	{
 24816  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = maxInOpen
 24817  		prg.baseFile.Put()
 24818  	}
 24819  
 24820  	// Dump the string pool
 24821  	{
 24822  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = int32(prg.poolPtr)
 24823  		prg.baseFile.Put()
 24824  	}
 24825  	{
 24826  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = int32(prg.strPtr)
 24827  		prg.baseFile.Put()
 24828  	}
 24829  	for ii := int32(0); ii <= int32(prg.strPtr); ii++ {
 24830  		k = ii
 24831  		_ = k
 24832  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = int32(prg.strStart[k])
 24833  		prg.baseFile.Put()
 24834  	}
 24835  	k = 0
 24836  	for k+4 < int32(prg.poolPtr) {
 24837  		w.b0 = byte(int32(prg.strPool[k]) + minQuarterword)
 24838  		w.b1 = byte(int32(prg.strPool[k+1]) + minQuarterword)
 24839  		w.b2 = byte(int32(prg.strPool[k+2]) + minQuarterword)
 24840  		w.b3 = byte(int32(prg.strPool[k+3]) + minQuarterword)
 24841  		{
 24842  			*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).qqqq() = w
 24843  			prg.baseFile.Put()
 24844  		}
 24845  		k = k + 4
 24846  	}
 24847  	k = int32(prg.poolPtr) - 4
 24848  	w.b0 = byte(int32(prg.strPool[k]) + minQuarterword)
 24849  	w.b1 = byte(int32(prg.strPool[k+1]) + minQuarterword)
 24850  	w.b2 = byte(int32(prg.strPool[k+2]) + minQuarterword)
 24851  	w.b3 = byte(int32(prg.strPool[k+3]) + minQuarterword)
 24852  	{
 24853  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).qqqq() = w
 24854  		prg.baseFile.Put()
 24855  	}
 24856  	prg.printLn()
 24857  	prg.printInt(int32(prg.strPtr))
 24858  	prg.print( /* " strings of total length " */ 1068)
 24859  	prg.printInt(int32(prg.poolPtr))
 24860  
 24861  	// Dump the dynamic memory
 24862  	prg.sortAvail()
 24863  	prg.varUsed = 0
 24864  	{
 24865  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = int32(prg.loMemMax)
 24866  		prg.baseFile.Put()
 24867  	}
 24868  	{
 24869  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = int32(prg.rover)
 24870  		prg.baseFile.Put()
 24871  	}
 24872  	p = uint16(memMin)
 24873  	q = prg.rover
 24874  	x = 0
 24875  	for {
 24876  		for ii := int32(p); ii <= int32(q)+1; ii++ {
 24877  			k = ii
 24878  			_ = k
 24879  			*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P())) = prg.mem[k]
 24880  			prg.baseFile.Put()
 24881  		}
 24882  		x = x + int32(q) + 2 - int32(p)
 24883  		prg.varUsed = prg.varUsed + int32(q) - int32(p)
 24884  		p = uint16(int32(q) + int32(*(*prg.mem[q].hh()).lh()))
 24885  		q = *(*prg.mem[int32(q)+1].hh()).rh()
 24886  		if int32(q) == int32(prg.rover) {
 24887  			break
 24888  		}
 24889  	}
 24890  	prg.varUsed = prg.varUsed + int32(prg.loMemMax) - int32(p)
 24891  	prg.dynUsed = int32(prg.memEnd) + 1 - int32(prg.hiMemMin)
 24892  
 24893  	for ii := int32(p); ii <= int32(prg.loMemMax); ii++ {
 24894  		k = ii
 24895  		_ = k
 24896  		*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P())) = prg.mem[k]
 24897  		prg.baseFile.Put()
 24898  	}
 24899  	x = x + int32(prg.loMemMax) + 1 - int32(p)
 24900  	{
 24901  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = int32(prg.hiMemMin)
 24902  		prg.baseFile.Put()
 24903  	}
 24904  	{
 24905  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = int32(prg.avail)
 24906  		prg.baseFile.Put()
 24907  	}
 24908  	for ii := int32(prg.hiMemMin); ii <= int32(prg.memEnd); ii++ {
 24909  		k = ii
 24910  		_ = k
 24911  		*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P())) = prg.mem[k]
 24912  		prg.baseFile.Put()
 24913  	}
 24914  	x = x + int32(prg.memEnd) + 1 - int32(prg.hiMemMin)
 24915  	p = prg.avail
 24916  	for int32(p) != memMin {
 24917  		prg.dynUsed = prg.dynUsed - 1
 24918  		p = *(*prg.mem[p].hh()).rh()
 24919  	}
 24920  	{
 24921  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = prg.varUsed
 24922  		prg.baseFile.Put()
 24923  	}
 24924  	{
 24925  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = prg.dynUsed
 24926  		prg.baseFile.Put()
 24927  	}
 24928  	prg.printLn()
 24929  	prg.printInt(x)
 24930  	prg.print( /* " memory locations dumped; current usage is " */ 1069)
 24931  	prg.printInt(prg.varUsed)
 24932  	prg.printChar(asciiCode('&'))
 24933  	prg.printInt(prg.dynUsed)
 24934  
 24935  	// Dump the table of equivalents and the hash table
 24936  	{
 24937  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = int32(prg.hashUsed)
 24938  		prg.baseFile.Put()
 24939  	}
 24940  	prg.stCount = hashBase + hashSize - 1 - int32(prg.hashUsed)
 24941  	for ii := int32(1); ii <= int32(prg.hashUsed); ii++ {
 24942  		p = halfword(ii)
 24943  		_ = p
 24944  		if int32(*prg.hash[p-1].rh()) != 0 {
 24945  			{
 24946  				*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = int32(p)
 24947  				prg.baseFile.Put()
 24948  			}
 24949  			{
 24950  				*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).hh() = prg.hash[p-1]
 24951  				prg.baseFile.Put()
 24952  			}
 24953  			{
 24954  				*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).hh() = prg.eqtb[p-1]
 24955  				prg.baseFile.Put()
 24956  			}
 24957  			prg.stCount = prg.stCount + 1
 24958  		}
 24959  	}
 24960  	for ii := int32(prg.hashUsed) + 1; ii <= hashBase+hashSize+12; ii++ {
 24961  		p = halfword(ii)
 24962  		_ = p
 24963  		{
 24964  			*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).hh() = prg.hash[p-1]
 24965  			prg.baseFile.Put()
 24966  		}
 24967  		{
 24968  			*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).hh() = prg.eqtb[p-1]
 24969  			prg.baseFile.Put()
 24970  		}
 24971  	}
 24972  	{
 24973  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = prg.stCount
 24974  		prg.baseFile.Put()
 24975  	}
 24976  
 24977  	prg.printLn()
 24978  	prg.printInt(prg.stCount)
 24979  	prg.print( /* " symbolic tokens" */ 1070)
 24980  
 24981  	// Dump a few more things and the closing check word
 24982  	{
 24983  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = int32(prg.intPtr)
 24984  		prg.baseFile.Put()
 24985  	}
 24986  	for ii := int32(1); ii <= int32(prg.intPtr); ii++ {
 24987  		k = ii
 24988  		_ = k
 24989  		{
 24990  			*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = prg.internal[k-1]
 24991  			prg.baseFile.Put()
 24992  		}
 24993  		{
 24994  			*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = int32(prg.intName[k-1])
 24995  			prg.baseFile.Put()
 24996  		}
 24997  	}
 24998  	{
 24999  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = int32(prg.startSym)
 25000  		prg.baseFile.Put()
 25001  	}
 25002  	{
 25003  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = int32(prg.interaction)
 25004  		prg.baseFile.Put()
 25005  	}
 25006  	{
 25007  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = int32(prg.baseIdent)
 25008  		prg.baseFile.Put()
 25009  	}
 25010  	{
 25011  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = int32(prg.bgLoc)
 25012  		prg.baseFile.Put()
 25013  	}
 25014  	{
 25015  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = int32(prg.egLoc)
 25016  		prg.baseFile.Put()
 25017  	}
 25018  	{
 25019  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = prg.serialNo
 25020  		prg.baseFile.Put()
 25021  	}
 25022  	{
 25023  		*(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int() = 69069
 25024  		prg.baseFile.Put()
 25025  	}
 25026  	prg.internal[tracingStats-1] = 0
 25027  
 25028  	// Close the base file
 25029  	prg.wClose(prg.baseFile)
 25030  }
 25031  
 25032  func (prg *prg) doStatement() {
 25033  	prg.curType = byte(vacuous)
 25034  	prg.getXNext()
 25035  	if int32(prg.curCmd) > maxPrimaryCommand {
 25036  		if int32(prg.curCmd) < semicolon {
 25037  			{
 25038  				if int32(prg.interaction) == errorStopMode {
 25039  				}
 25040  				prg.printNl(strNumber( /* "! " */ 261))
 25041  				prg.print( /* "A statement can't begin with `" */ 869) /* \xref[!\relax]  */
 25042  			}
 25043  			// \xref[A statement can't begin with x]
 25044  			prg.printCmdMod(int32(prg.curCmd), prg.curMod)
 25045  			prg.printChar(asciiCode('\''))
 25046  			{
 25047  				prg.helpPtr = 5
 25048  				prg.helpLine[4] = /* "I was looking for the beginning of a new statement." */ 870
 25049  				prg.helpLine[3] = /* "If you just proceed without changing anything, I'll ignore" */ 871
 25050  				prg.helpLine[2] = /* "everything up to the next `;'. Please insert a semicolon" */ 872
 25051  				prg.helpLine[1] = /* "now in front of anything that you don't want me to delete." */ 873
 25052  				prg.helpLine[0] = /* "(See Chapter 27 of The METAFONTbook for an example.)" */ 874
 25053  			}
 25054  
 25055  			// \xref[METAFONTbook][\sl The [\logos METAFONT\/]book]
 25056  			prg.backError()
 25057  			prg.getXNext()
 25058  		}
 25059  	} else if int32(prg.curCmd) > maxStatementCommand {
 25060  		prg.varFlag = byte(assignment)
 25061  		prg.scanExpression()
 25062  		if int32(prg.curCmd) < endGroup {
 25063  			if int32(prg.curCmd) == equals {
 25064  				prg.doEquation()
 25065  			} else if int32(prg.curCmd) == assignment {
 25066  				prg.doAssignment()
 25067  			} else if int32(prg.curType) == stringType {
 25068  				if prg.internal[tracingTitles-1] > 0 {
 25069  					prg.printNl(strNumber( /* "" */ 285))
 25070  					prg.slowPrint(prg.curExp)
 25071  				}
 25072  				if prg.internal[proofing-1] > 0 {
 25073  					if int32(prg.outputFileName) == 0 {
 25074  						prg.initGf()
 25075  					}
 25076  					prg.gfString(strNumber( /* "title " */ 1062), strNumber(prg.curExp))
 25077  					// \xref[title]
 25078  				}
 25079  			} else if int32(prg.curType) != vacuous {
 25080  				prg.dispErr(halfword(memMin), strNumber( /* "Isolated expression" */ 879))
 25081  				// \xref[Isolated expression]
 25082  				{
 25083  					prg.helpPtr = 3
 25084  					prg.helpLine[2] = /* "I couldn't find an `=' or `:=' after the" */ 880
 25085  					prg.helpLine[1] = /* "expression that is shown above this error message," */ 881
 25086  					prg.helpLine[0] = /* "so I guess I'll just ignore it and carry on." */ 882
 25087  				}
 25088  				prg.putGetError()
 25089  			}
 25090  			prg.flushCurExp(scaled(0))
 25091  			prg.curType = byte(vacuous)
 25092  		}
 25093  	} else {
 25094  		// Do a statement that doesn't begin with an expression
 25095  		if prg.internal[tracingCommands-1] > 0 {
 25096  			prg.showCmdMod(int32(prg.curCmd), prg.curMod)
 25097  		}
 25098  		switch prg.curCmd {
 25099  		case typeName:
 25100  			prg.doTypeDeclaration()
 25101  		case macroDef:
 25102  			if prg.curMod > varDef {
 25103  				prg.makeOpDef()
 25104  			} else if prg.curMod > endDef {
 25105  				prg.scanDef()
 25106  			}
 25107  		// \4
 25108  		// Cases of |do_statement| that invoke particular commands
 25109  		case randomSeed:
 25110  			prg.doRandomSeed()
 25111  
 25112  		case modeCommand:
 25113  			prg.printLn()
 25114  			prg.interaction = byte(prg.curMod)
 25115  
 25116  			// Initialize the print |selector| based on |interaction|
 25117  			if int32(prg.interaction) == batchMode {
 25118  				prg.selector = byte(noPrint)
 25119  			} else {
 25120  				prg.selector = byte(termOnly)
 25121  			}
 25122  			if prg.logOpened {
 25123  				prg.selector = byte(int32(prg.selector) + 2)
 25124  			}
 25125  			prg.getXNext()
 25126  
 25127  		case protectionCommand:
 25128  			prg.doProtection()
 25129  
 25130  		case delimiters:
 25131  			prg.defDelims()
 25132  
 25133  		case saveCommand:
 25134  			for {
 25135  				prg.getSymbol()
 25136  				prg.saveVariable(prg.curSym)
 25137  				prg.getXNext()
 25138  				if int32(prg.curCmd) != comma {
 25139  					break
 25140  				}
 25141  			}
 25142  		case interimCommand:
 25143  			prg.doInterim()
 25144  		case letCommand:
 25145  			prg.doLet()
 25146  		case newInternal:
 25147  			prg.doNewInternal()
 25148  
 25149  		case showCommand:
 25150  			prg.doShowWhatever()
 25151  
 25152  		case addToCommand:
 25153  			prg.doAddTo()
 25154  
 25155  		case shipOutCommand:
 25156  			prg.doShipOut()
 25157  		case displayCommand:
 25158  			prg.doDisplay()
 25159  		case openWindow:
 25160  			prg.doOpenWindow()
 25161  		case cullCommand:
 25162  			prg.doCull()
 25163  
 25164  		case everyJobCommand:
 25165  			prg.getSymbol()
 25166  			prg.startSym = prg.curSym
 25167  			prg.getXNext()
 25168  
 25169  		case messageCommand:
 25170  			prg.doMessage()
 25171  
 25172  		case tfmCommand:
 25173  			prg.doTfmCommand()
 25174  
 25175  		case specialCommand:
 25176  			prg.doSpecial()
 25177  
 25178  		} // there are no other cases
 25179  		prg.curType = byte(vacuous)
 25180  	}
 25181  	if int32(prg.curCmd) < semicolon {
 25182  		{
 25183  			if int32(prg.interaction) == errorStopMode {
 25184  			}
 25185  			prg.printNl(strNumber( /* "! " */ 261))
 25186  			prg.print( /* "Extra tokens will be flushed" */ 875) /* \xref[!\relax]  */
 25187  		}
 25188  		// \xref[Extra tokens will be flushed]
 25189  		{
 25190  			prg.helpPtr = 6
 25191  			prg.helpLine[5] = /* "I've just read as much of that statement as I could fathom," */ 876
 25192  			prg.helpLine[4] = /* "so a semicolon should have been next. It's very puzzling..." */ 877
 25193  			prg.helpLine[3] = /* "but I'll try to get myself back together, by ignoring" */ 878
 25194  			prg.helpLine[2] = /* "everything up to the next `;'. Please insert a semicolon" */ 872
 25195  			prg.helpLine[1] = /* "now in front of anything that you don't want me to delete." */ 873
 25196  			prg.helpLine[0] = /* "(See Chapter 27 of The METAFONTbook for an example.)" */ 874
 25197  		}
 25198  
 25199  		// \xref[METAFONTbook][\sl The [\logos METAFONT\/]book]
 25200  		prg.backError()
 25201  		prg.scannerStatus = byte(flushing)
 25202  		for {
 25203  			prg.getNext()
 25204  
 25205  			// Decrease the string reference count...
 25206  			if int32(prg.curCmd) == stringToken {
 25207  				if int32(prg.strRef[prg.curMod]) < maxStrRef {
 25208  					if int32(prg.strRef[prg.curMod]) > 1 {
 25209  						prg.strRef[prg.curMod] = byte(int32(prg.strRef[prg.curMod]) - 1)
 25210  					} else {
 25211  						prg.flushString(strNumber(prg.curMod))
 25212  					}
 25213  				}
 25214  			}
 25215  			if int32(prg.curCmd) > comma {
 25216  				break
 25217  			}
 25218  		} // |cur_cmd=semicolon|, |end_group|, or |stop|
 25219  		prg.scannerStatus = byte(normal)
 25220  	}
 25221  	prg.errorCount = 0
 25222  }
 25223  
 25224  // 1017.
 25225  
 25226  // tangle:pos ../../mf.web:19802:3:
 25227  
 25228  // \MF's |main_control| procedure just calls |do_statement| repeatedly
 25229  // until coming to the end of the user's program.
 25230  // Each execution of |do_statement| concludes with
 25231  // |cur_cmd=semicolon|, |end_group|, or |stop|.
 25232  func (prg *prg) mainControl() {
 25233  	for {
 25234  		prg.doStatement()
 25235  		if int32(prg.curCmd) == endGroup {
 25236  			{
 25237  				if int32(prg.interaction) == errorStopMode {
 25238  				}
 25239  				prg.printNl(strNumber( /* "! " */ 261))
 25240  				prg.print( /* "Extra `endgroup'" */ 910) /* \xref[!\relax]  */
 25241  			}
 25242  			// \xref[Extra `endgroup']
 25243  			{
 25244  				prg.helpPtr = 2
 25245  				prg.helpLine[1] = /* "I'm not currently working on a `begingroup'," */ 911
 25246  				prg.helpLine[0] = /* "so I had better not try to end anything." */ 689
 25247  			}
 25248  			prg.flushError(scaled(0))
 25249  		}
 25250  		if int32(prg.curCmd) == stop {
 25251  			break
 25252  		}
 25253  	}
 25254  }
 25255  
 25256  // 1088.
 25257  
 25258  // tangle:pos ../../mf.web:20697:3:
 25259  
 25260  // The first 24 bytes (6 words) of a \.[TFM] file contain twelve 16-bit
 25261  // integers that give the lengths of the various subsequent portions
 25262  // of the file. These twelve integers are, in order:
 25263  // $$\vbox[\halign[\hfil#&$\null=\null$#\hfil\cr
 25264  // |lf|&length of the entire file, in words;\cr
 25265  // |lh|&length of the header data, in words;\cr
 25266  // |bc|&smallest character code in the font;\cr
 25267  // |ec|&largest character code in the font;\cr
 25268  // |nw|&number of words in the width table;\cr
 25269  // |nh|&number of words in the height table;\cr
 25270  // |nd|&number of words in the depth table;\cr
 25271  // |ni|&number of words in the italic correction table;\cr
 25272  // |nl|&number of words in the lig/kern table;\cr
 25273  // |nk|&number of words in the kern table;\cr
 25274  // |ne|&number of words in the extensible character table;\cr
 25275  // |np|&number of font parameter words.\cr]]$$
 25276  // They are all nonnegative and less than $2^[15]$. We must have |bc-1<=ec<=255|,
 25277  // |ne<=256|, and
 25278  // $$\hbox[|lf=6+lh+(ec-bc+1)+nw+nh+nd+ni+nl+nk+ne+np|.]$$
 25279  // Note that a font may contain as many as 256 characters (if |bc=0| and |ec=255|),
 25280  // and as few as 0 characters (if |bc=ec+1|).
 25281  //
 25282  // Incidentally, when two or more 8-bit bytes are combined to form an integer of
 25283  // 16 or more bits, the most significant bytes appear first in the file.
 25284  // This is called BigEndian order.
 25285  //  \xref[BigEndian order]
 25286  
 25287  // 1089.
 25288  
 25289  // tangle:pos ../../mf.web:20724:3:
 25290  
 25291  // The rest of the \.[TFM] file may be regarded as a sequence of ten data
 25292  // arrays having the informal specification
 25293  // $$\def\arr$[#1]#2$[\&[array] $[#1]$ \&[of] #2]
 25294  // \tabskip\centering
 25295  // \halign to\displaywidth[\hfil\\[#]\tabskip=0pt&$\,:\,$\arr#\hfil
 25296  //  \tabskip\centering\cr
 25297  // header&|[0..lh-1]\\[stuff]|\cr
 25298  // char\_info&|[bc..ec]char_info_word|\cr
 25299  // width&|[0..nw-1]fix_word|\cr
 25300  // height&|[0..nh-1]fix_word|\cr
 25301  // depth&|[0..nd-1]fix_word|\cr
 25302  // italic&|[0..ni-1]fix_word|\cr
 25303  // lig\_kern&|[0..nl-1]lig_kern_command|\cr
 25304  // kern&|[0..nk-1]fix_word|\cr
 25305  // exten&|[0..ne-1]extensible_recipe|\cr
 25306  // param&|[1..np]fix_word|\cr]$$
 25307  // The most important data type used here is a | fix_word|, which is
 25308  // a 32-bit representation of a binary fraction. A |fix_word| is a signed
 25309  // quantity, with the two's complement of the entire word used to represent
 25310  // negation. Of the 32 bits in a |fix_word|, exactly 12 are to the left of the
 25311  // binary point; thus, the largest |fix_word| value is $2048-2^[-20]$, and
 25312  // the smallest is $-2048$. We will see below, however, that all but two of
 25313  // the |fix_word| values must lie between $-16$ and $+16$.
 25314  
 25315  // 1090.
 25316  
 25317  // tangle:pos ../../mf.web:20748:3:
 25318  
 25319  // The first data array is a block of header information, which contains
 25320  // general facts about the font. The header must contain at least two words,
 25321  // |header[0]| and |header[1]|, whose meaning is explained below.  Additional
 25322  // header information of use to other software routines might also be
 25323  // included, and \MF\ will generate it if the \.[headerbyte] command occurs.
 25324  // For example, 16 more words of header information are in use at the Xerox
 25325  // Palo Alto Research Center; the first ten specify the character coding
 25326  // scheme used (e.g., `\.[XEROX TEXT]' or `\.[TEX MATHSY]'), the next five
 25327  // give the font family name (e.g., `\.[HELVETICA]' or `\.[CMSY]'), and the
 25328  // last gives the ``face byte.''
 25329  //
 25330  // \yskip\hang|header[0]| is a 32-bit check sum that \MF\ will copy into
 25331  // the \.[GF] output file. This helps ensure consistency between files,
 25332  // since \TeX\ records the check sums from the \.[TFM]'s it reads, and these
 25333  // should match the check sums on actual fonts that are used.  The actual
 25334  // relation between this check sum and the rest of the \.[TFM] file is not
 25335  // important; the check sum is simply an identification number with the
 25336  // property that incompatible fonts almost always have distinct check sums.
 25337  // \xref[check sum]
 25338  //
 25339  // \yskip\hang|header[1]| is a |fix_word| containing the design size of the
 25340  // font, in units of \TeX\ points. This number must be at least 1.0; it is
 25341  // fairly arbitrary, but usually the design size is 10.0 for a ``10 point''
 25342  // font, i.e., a font that was designed to look best at a 10-point size,
 25343  // whatever that really means. When a \TeX\ user asks for a font `\.[at]
 25344  // $\delta$ \.[pt]', the effect is to override the design size and replace it
 25345  // by $\delta$, and to multiply the $x$ and~$y$ coordinates of the points in
 25346  // the font image by a factor of $\delta$ divided by the design size.  [\sl
 25347  // All other dimensions in the\/ \.[TFM] file are |fix_word|\kern-1pt\
 25348  // numbers in design-size units.] Thus, for example, the value of |param[6]|,
 25349  // which defines the \.[em] unit, is often the |fix_word| value $2^[20]=1.0$,
 25350  // since many fonts have a design size equal to one em.  The other dimensions
 25351  // must be less than 16 design-size units in absolute value; thus,
 25352  // |header[1]| and |param[1]| are the only |fix_word| entries in the whole
 25353  // \.[TFM] file whose first byte might be something besides 0 or 255.
 25354  // \xref[design size]
 25355  
 25356  // 1091.
 25357  
 25358  // tangle:pos ../../mf.web:20785:3:
 25359  
 25360  // Next comes the |char_info| array, which contains one | char_info_word|
 25361  // per character. Each word in this part of the file contains six fields
 25362  // packed into four bytes as follows.
 25363  //
 25364  // \yskip\hang first byte: | width_index| (8 bits)\par
 25365  // \hang second byte: | height_index| (4 bits) times 16, plus | depth_index|
 25366  //   (4~bits)\par
 25367  // \hang third byte: | italic_index| (6 bits) times 4, plus | tag|
 25368  //   (2~bits)\par
 25369  // \hang fourth byte: | remainder| (8 bits)\par
 25370  // \yskip\noindent
 25371  // The actual width of a character is \\[width]|[width_index]|, in design-size
 25372  // units; this is a device for compressing information, since many characters
 25373  // have the same width. Since it is quite common for many characters
 25374  // to have the same height, depth, or italic correction, the \.[TFM] format
 25375  // imposes a limit of 16 different heights, 16 different depths, and
 25376  // 64 different italic corrections.
 25377  //
 25378  // Incidentally, the relation $\\[width][0]=\\[height][0]=\\[depth][0]=
 25379  // \\[italic][0]=0$ should always hold, so that an index of zero implies a
 25380  // value of zero.  The |width_index| should never be zero unless the
 25381  // character does not exist in the font, since a character is valid if and
 25382  // only if it lies between |bc| and |ec| and has a nonzero |width_index|.
 25383  
 25384  // 1092.
 25385  
 25386  // tangle:pos ../../mf.web:20809:3:
 25387  
 25388  // The |tag| field in a |char_info_word| has four values that explain how to
 25389  // interpret the |remainder| field.
 25390  //
 25391  // \def\hangg#1 [\hang\hbox[#1 ]]
 25392  // \yskip\hangg|tag=0| (|no_tag|) means that |remainder| is unused.\par
 25393  // \hangg|tag=1| (|lig_tag|) means that this character has a ligature/kerning
 25394  // program starting at location |remainder| in the |lig_kern| array.\par
 25395  // \hangg|tag=2| (|list_tag|) means that this character is part of a chain of
 25396  // characters of ascending sizes, and not the largest in the chain.  The
 25397  // |remainder| field gives the character code of the next larger character.\par
 25398  // \hangg|tag=3| (|ext_tag|) means that this character code represents an
 25399  // extensible character, i.e., a character that is built up of smaller pieces
 25400  // so that it can be made arbitrarily large. The pieces are specified in
 25401  // | exten[remainder]|.\par
 25402  // \yskip\noindent
 25403  // Characters with |tag=2| and |tag=3| are treated as characters with |tag=0|
 25404  // unless they are used in special circumstances in math formulas. For example,
 25405  // \TeX's \.[\\sum] operation looks for a |list_tag|, and the \.[\\left]
 25406  // operation looks for both |list_tag| and |ext_tag|.
 25407  
 25408  // 1093.
 25409  
 25410  // tangle:pos ../../mf.web:20834:3:
 25411  
 25412  // The |lig_kern| array contains instructions in a simple programming language
 25413  // that explains what to do for special letter pairs. Each word in this array is a
 25414  // | lig_kern_command| of four bytes.
 25415  //
 25416  // \yskip\hang first byte: |skip_byte|, indicates that this is the final program
 25417  //   step if the byte is 128 or more, otherwise the next step is obtained by
 25418  //   skipping this number of intervening steps.\par
 25419  // \hang second byte: |next_char|, ``if |next_char| follows the current character,
 25420  //   then perform the operation and stop, otherwise continue.''\par
 25421  // \hang third byte: |op_byte|, indicates a ligature step if less than~128,
 25422  //   a kern step otherwise.\par
 25423  // \hang fourth byte: |remainder|.\par
 25424  // \yskip\noindent
 25425  // In a kern step, an
 25426  // additional space equal to |kern[256*(op_byte-128)+remainder]| is inserted
 25427  // between the current character and |next_char|. This amount is
 25428  // often negative, so that the characters are brought closer together
 25429  // by kerning; but it might be positive.
 25430  //
 25431  // There are eight kinds of ligature steps, having |op_byte| codes $4a+2b+c$ where
 25432  // $0\le a\le b+c$ and $0\le b,c\le1$. The character whose code is
 25433  // |remainder| is inserted between the current character and |next_char|;
 25434  // then the current character is deleted if $b=0$, and |next_char| is
 25435  // deleted if $c=0$; then we pass over $a$~characters to reach the next
 25436  // current character (which may have a ligature/kerning program of its own).
 25437  //
 25438  // If the very first instruction of the |lig_kern| array has |skip_byte=255|,
 25439  // the |next_char| byte is the so-called boundary character of this font;
 25440  // the value of |next_char| need not lie between |bc| and~|ec|.
 25441  // If the very last instruction of the |lig_kern| array has |skip_byte=255|,
 25442  // there is a special ligature/kerning program for a boundary character at the
 25443  // left, beginning at location |256*op_byte+remainder|.
 25444  // The interpretation is that \TeX\ puts implicit boundary characters
 25445  // before and after each consecutive string of characters from the same font.
 25446  // These implicit characters do not appear in the output, but they can affect
 25447  // ligatures and kerning.
 25448  //
 25449  // If the very first instruction of a character's |lig_kern| program has
 25450  // |skip_byte>128|, the program actually begins in location
 25451  // |256*op_byte+remainder|. This feature allows access to large |lig_kern|
 25452  // arrays, because the first instruction must otherwise
 25453  // appear in a location |<=255|.
 25454  //
 25455  // Any instruction with |skip_byte>128| in the |lig_kern| array must satisfy
 25456  // the condition
 25457  // $$\hbox[|256*op_byte+remainder<nl|.]$$
 25458  // If such an instruction is encountered during
 25459  // normal program execution, it denotes an unconditional halt; no ligature
 25460  // or kerning command is performed.
 25461  
 25462  // 1094.
 25463  
 25464  // tangle:pos ../../mf.web:20892:3:
 25465  
 25466  // Extensible characters are specified by an | extensible_recipe|, which
 25467  // consists of four bytes called | top|, | mid|, | bot|, and | rep| (in this
 25468  // order). These bytes are the character codes of individual pieces used to
 25469  // build up a large symbol.  If |top|, |mid|, or |bot| are zero, they are not
 25470  // present in the built-up result. For example, an extensible vertical line is
 25471  // like an extensible bracket, except that the top and bottom pieces are missing.
 25472  //
 25473  // Let $T$, $M$, $B$, and $R$ denote the respective pieces, or an empty box
 25474  // if the piece isn't present. Then the extensible characters have the form
 25475  // $TR^kMR^kB$ from top to bottom, for some |k>=0|, unless $M$ is absent;
 25476  // in the latter case we can have $TR^kB$ for both even and odd values of~|k|.
 25477  // The width of the extensible character is the width of $R$; and the
 25478  // height-plus-depth is the sum of the individual height-plus-depths of the
 25479  // components used, since the pieces are butted together in a vertical list.
 25480  
 25481  // 1095.
 25482  
 25483  // tangle:pos ../../mf.web:20912:3:
 25484  
 25485  // The final portion of a \.[TFM] file is the |param| array, which is another
 25486  // sequence of |fix_word| values.
 25487  //
 25488  // \yskip\hang|param[1]=slant| is the amount of italic slant, which is used
 25489  // to help position accents. For example, |slant=.25| means that when you go
 25490  // up one unit, you also go .25 units to the right. The |slant| is a pure
 25491  // number; it is the only |fix_word| other than the design size itself that is
 25492  // not scaled by the design size.
 25493  // \xref[design size]
 25494  //
 25495  // \hang|param[2]=space| is the normal spacing between words in text.
 25496  // Note that character @'40 in the font need not have anything to do with
 25497  // blank spaces.
 25498  //
 25499  // \hang|param[3]=space_stretch| is the amount of glue stretching between words.
 25500  //
 25501  // \hang|param[4]=space_shrink| is the amount of glue shrinking between words.
 25502  //
 25503  // \hang|param[5]=x_height| is the size of one ex in the font; it is also
 25504  // the height of letters for which accents don't have to be raised or lowered.
 25505  //
 25506  // \hang|param[6]=quad| is the size of one em in the font.
 25507  //
 25508  // \hang|param[7]=extra_space| is the amount added to |param[2]| at the
 25509  // ends of sentences.
 25510  //
 25511  // \yskip\noindent
 25512  // If fewer than seven parameters are present, \TeX\ sets the missing parameters
 25513  // to zero.
 25514  
 25515  // 1117.
 25516  
 25517  // tangle:pos ../../mf.web:21341:3:
 25518  
 25519  // Straight linear insertion is good enough for sorting, since the lists
 25520  // are usually not terribly long. As we work on the data, the current list
 25521  // will start at |link(temp_head)| and end at |inf_val|; the nodes in this
 25522  // list will be in increasing order of their |value| fields.
 25523  //
 25524  // Given such a list, the |sort_in| function takes a value and returns a pointer
 25525  // to where that value can be found in the list. The value is inserted in
 25526  // the proper place, if necessary.
 25527  //
 25528  // At the time we need to do these operations, most of \MF's work has been
 25529  // completed, so we will have plenty of memory to play with. The value nodes
 25530  // that are allocated for sorting will never be returned to free storage.
 25531  func (prg *prg) sortIn(v scaled) (r halfword) {
 25532  	var (
 25533  		p, q, r1 halfword // list manipulation registers
 25534  	)
 25535  	p = uint16(3000 - 1)
 25536  	for true {
 25537  		q = *(*prg.mem[p].hh()).rh()
 25538  		if v <= *prg.mem[int32(q)+1].int() {
 25539  			goto found
 25540  		}
 25541  		p = q
 25542  	}
 25543  
 25544  found:
 25545  	if v < *prg.mem[int32(q)+1].int() {
 25546  		r1 = prg.getNode(valueNodeSize)
 25547  		*prg.mem[int32(r1)+1].int() = v
 25548  		*(*prg.mem[r1].hh()).rh() = q
 25549  		*(*prg.mem[p].hh()).rh() = r1
 25550  	}
 25551  	r = *(*prg.mem[p].hh()).rh()
 25552  	return r
 25553  }
 25554  
 25555  // 1118.
 25556  
 25557  // tangle:pos ../../mf.web:21370:3:
 25558  
 25559  // Now we come to the interesting part, where we reduce the list if necessary
 25560  // until it has the required size. The |min_cover| routine is basic to this
 25561  // process; it computes the minimum number~|m| such that the values of the
 25562  // current sorted list can be covered by |m|~intervals of width~|d|. It
 25563  // also sets the global value |perturbation| to the smallest value $d'>d$
 25564  // such that the covering found by this algorithm would be different.
 25565  //
 25566  // In particular, |min_cover(0)| returns the number of distinct values in the
 25567  // current list and sets |perturbation| to the minimum distance between
 25568  // adjacent values.
 25569  func (prg *prg) minCover(d scaled) (r int32) {
 25570  	var (
 25571  		p halfword // runs through the current list
 25572  		l scaled   // the least element covered by the current interval
 25573  		m int32    // lower bound on the size of the minimum cover
 25574  	)
 25575  	m = 0
 25576  	p = *(*prg.mem[3000-1].hh()).rh()
 25577  	prg.perturbation = 017777777777
 25578  	for int32(p) != memMin+3+10+2+2+2 {
 25579  		m = m + 1
 25580  		l = *prg.mem[int32(p)+1].int()
 25581  		for {
 25582  			p = *(*prg.mem[p].hh()).rh()
 25583  			if *prg.mem[int32(p)+1].int() > l+d {
 25584  				break
 25585  			}
 25586  		}
 25587  		if *prg.mem[int32(p)+1].int()-l < prg.perturbation {
 25588  			prg.perturbation = *prg.mem[int32(p)+1].int() - l
 25589  		}
 25590  	}
 25591  	r = m
 25592  	return r
 25593  }
 25594  
 25595  // 1120.
 25596  
 25597  // tangle:pos ../../mf.web:21399:3:
 25598  
 25599  // The smallest |d| such that a given list can be covered with |m| intervals
 25600  // is determined by the |threshold| routine, which is sort of an inverse
 25601  // to |min_cover|. The idea is to increase the interval size rapidly until
 25602  // finding the range, then to go sequentially until the exact borderline has
 25603  // been discovered.
 25604  func (prg *prg) threshold(m int32) (r scaled) {
 25605  	var (
 25606  		d scaled // lower bound on the smallest interval size
 25607  	)
 25608  	prg.excess = prg.minCover(scaled(0)) - m
 25609  	if prg.excess <= 0 {
 25610  		r = 0
 25611  	} else {
 25612  		for {
 25613  			d = prg.perturbation
 25614  			if prg.minCover(d+d) <= m {
 25615  				break
 25616  			}
 25617  		}
 25618  		for prg.minCover(d) > m {
 25619  			d = prg.perturbation
 25620  		}
 25621  		r = d
 25622  	}
 25623  	return r
 25624  }
 25625  
 25626  // 1121.
 25627  
 25628  // tangle:pos ../../mf.web:21416:3:
 25629  
 25630  // The |skimp| procedure reduces the current list to at most |m| entries,
 25631  // by changing values if necessary. It also sets |info(p):=k| if |value(p)|
 25632  // is the |k|th distinct value on the resulting list, and it sets
 25633  // |perturbation| to the maximum amount by which a |value| field has
 25634  // been changed. The size of the resulting list is returned as the
 25635  // value of |skimp|.
 25636  func (prg *prg) skimp(m int32) (r int32) {
 25637  	var (
 25638  		d        scaled   // the size of intervals being coalesced
 25639  		p, q, r1 halfword // list manipulation registers
 25640  		l        scaled   // the least value in the current interval
 25641  		v        scaled   // a compromise value
 25642  	)
 25643  	d = prg.threshold(m)
 25644  	prg.perturbation = 0
 25645  	q = uint16(3000 - 1)
 25646  	m = 0
 25647  	p = *(*prg.mem[3000-1].hh()).rh()
 25648  	for int32(p) != memMin+3+10+2+2+2 {
 25649  		m = m + 1
 25650  		l = *prg.mem[int32(p)+1].int()
 25651  		*(*prg.mem[p].hh()).lh() = uint16(m)
 25652  		if *prg.mem[int32(*(*prg.mem[p].hh()).rh())+1].int() <= l+d {
 25653  			for {
 25654  				p = *(*prg.mem[p].hh()).rh()
 25655  				*(*prg.mem[p].hh()).lh() = uint16(m)
 25656  				prg.excess = prg.excess - 1
 25657  				if prg.excess == 0 {
 25658  					d = 0
 25659  				}
 25660  				if *prg.mem[int32(*(*prg.mem[p].hh()).rh())+1].int() > l+d {
 25661  					break
 25662  				}
 25663  			}
 25664  			v = l + (*prg.mem[int32(p)+1].int()-l)/2
 25665  			if *prg.mem[int32(p)+1].int()-v > prg.perturbation {
 25666  				prg.perturbation = *prg.mem[int32(p)+1].int() - v
 25667  			}
 25668  			r1 = q
 25669  			for {
 25670  				r1 = *(*prg.mem[r1].hh()).rh()
 25671  				*prg.mem[int32(r1)+1].int() = v
 25672  				if int32(r1) == int32(p) {
 25673  					break
 25674  				}
 25675  			}
 25676  			*(*prg.mem[q].hh()).rh() = p // remove duplicate values from the current list
 25677  		}
 25678  		q = p
 25679  		p = *(*prg.mem[p].hh()).rh()
 25680  	}
 25681  	r = m
 25682  	return r
 25683  }
 25684  
 25685  // 1123.
 25686  
 25687  // tangle:pos ../../mf.web:21451:3:
 25688  
 25689  // A warning message is issued whenever something is perturbed by
 25690  // more than 1/16\thinspace pt.
 25691  func (prg *prg) tfmWarning(m smallNumber) {
 25692  	prg.printNl(strNumber( /* "(some " */ 1041))
 25693  	prg.print(int32(prg.intName[m-1]))
 25694  	// \xref[some charwds...]
 25695  	// \xref[some chardps...]
 25696  	// \xref[some charhts...]
 25697  	// \xref[some charics...]
 25698  	prg.print( /* " values had to be adjusted by as much as " */ 1042)
 25699  	prg.printScaled(prg.perturbation)
 25700  	prg.print( /* "pt)" */ 1043)
 25701  }
 25702  
 25703  // 1128.
 25704  
 25705  // tangle:pos ../../mf.web:21510:3:
 25706  
 25707  // Bytes 5--8 of the header are set to the design size, unless the user has
 25708  // some crazy reason for specifying them differently.
 25709  // \xref[design size]
 25710  //
 25711  // Error messages are not allowed at the time this procedure is called,
 25712  // so a warning is printed instead.
 25713  //
 25714  // The value of |max_tfm_dimen| is calculated so that
 25715  // $$\hbox[|make_scaled(16*max_tfm_dimen,internal[design_size])|]
 25716  //  < \\[three\_bytes].$$
 25717  func (prg *prg) fixDesignSize() {
 25718  	var (
 25719  		d scaled // the design size
 25720  	)
 25721  	d = prg.internal[designSize-1]
 25722  	if d < 0200000 || d >= 01000000000 {
 25723  		if d != 0 {
 25724  			prg.printNl(strNumber( /* "(illegal design size has been changed to 128pt)" */ 1044))
 25725  		}
 25726  		// \xref[illegal design size...]
 25727  		d = 040000000
 25728  		prg.internal[designSize-1] = d
 25729  	}
 25730  	if int32(prg.headerByte[5-1]) < 0 {
 25731  		if int32(prg.headerByte[6-1]) < 0 {
 25732  			if int32(prg.headerByte[7-1]) < 0 {
 25733  				if int32(prg.headerByte[8-1]) < 0 {
 25734  					prg.headerByte[5-1] = int16(d / 04000000)
 25735  					prg.headerByte[6-1] = int16(d / 4096 % 256)
 25736  					prg.headerByte[7-1] = int16(d / 16 % 256)
 25737  					prg.headerByte[8-1] = int16(d % 16 * 16)
 25738  				}
 25739  			}
 25740  		}
 25741  	}
 25742  	prg.maxTfmDimen = 16*prg.internal[designSize-1] - 1 - prg.internal[designSize-1]/010000000
 25743  	if prg.maxTfmDimen >= 01000000000 {
 25744  		prg.maxTfmDimen = 01000000000 - 1
 25745  	}
 25746  }
 25747  
 25748  // 1129.
 25749  
 25750  // tangle:pos ../../mf.web:21543:3:
 25751  
 25752  // The |dimen_out| procedure computes a |fix_word| relative to the
 25753  // design size. If the data was out of range, it is corrected and the
 25754  // global variable |tfm_changed| is increased by~one.
 25755  func (prg *prg) dimenOut(x scaled) (r int32) {
 25756  	if abs(x) > prg.maxTfmDimen {
 25757  		prg.tfmChanged = prg.tfmChanged + 1
 25758  		if x > 0 {
 25759  			x = prg.maxTfmDimen
 25760  		} else {
 25761  			x = -prg.maxTfmDimen
 25762  		}
 25763  	}
 25764  	x = prg.makeScaled(x*16, prg.internal[designSize-1])
 25765  	r = x
 25766  	return r
 25767  }
 25768  
 25769  // 1131.
 25770  
 25771  // tangle:pos ../../mf.web:21560:3:
 25772  
 25773  // If the user has not specified any of the first four header bytes,
 25774  // the |fix_check_sum| procedure replaces them by a ``check sum'' computed
 25775  // from the |tfm_width| data relative to the design size.
 25776  // \xref[check sum]
 25777  func (prg *prg) fixCheckSum() {
 25778  	var (
 25779  		k              eightBits // runs through character codes
 25780  		b1, b2, b3, b4 eightBits // bytes of the check sum
 25781  		x              int32     // hash value used in check sum computation
 25782  	)
 25783  	if int32(prg.headerByte[1-1]) < 0 {
 25784  		if int32(prg.headerByte[2-1]) < 0 {
 25785  			if int32(prg.headerByte[3-1]) < 0 {
 25786  				if int32(prg.headerByte[4-1]) < 0 {
 25787  					b1 = prg.bc
 25788  					b2 = prg.ec
 25789  					b3 = prg.bc
 25790  					b4 = prg.ec
 25791  					prg.tfmChanged = 0
 25792  					for ii := int32(prg.bc); ii <= int32(prg.ec); ii++ {
 25793  						k = eightBits(ii)
 25794  						_ = k
 25795  						if prg.charExists[k] {
 25796  							x = prg.dimenOut(*prg.mem[prg.tfmWidth[k]+1].int()) + (int32(k)+4)*020000000 // this is positive
 25797  							b1 = byte((int32(b1) + int32(b1) + x) % 255)
 25798  							b2 = byte((int32(b2) + int32(b2) + x) % 253)
 25799  							b3 = byte((int32(b3) + int32(b3) + x) % 251)
 25800  							b4 = byte((int32(b4) + int32(b4) + x) % 247)
 25801  						}
 25802  					}
 25803  					prg.headerByte[1-1] = int16(b1)
 25804  					prg.headerByte[2-1] = int16(b2)
 25805  					prg.headerByte[3-1] = int16(b3)
 25806  					prg.headerByte[4-1] = int16(b4)
 25807  					goto exit
 25808  				}
 25809  			}
 25810  		}
 25811  	}
 25812  	for ii := int32(1); ii <= 4; ii++ {
 25813  		k = eightBits(ii)
 25814  		_ = k
 25815  		if int32(prg.headerByte[k-1]) < 0 {
 25816  			prg.headerByte[k-1] = 0
 25817  		}
 25818  	}
 25819  
 25820  exit:
 25821  }
 25822  
 25823  // 1133.
 25824  
 25825  // tangle:pos ../../mf.web:21589:3:
 25826  
 25827  // Finally we're ready to actually write the \.[TFM] information.
 25828  // Here are some utility routines for this purpose.
 25829  func (prg *prg) tfmTwo(x int32) {
 25830  	prg.tfmFile.Write(x / 256)
 25831  	prg.tfmFile.Write(x % 256)
 25832  }
 25833  
 25834  func (prg *prg) tfmFour(x int32) {
 25835  	if x >= 0 {
 25836  		prg.tfmFile.Write(x / 0100000000)
 25837  	} else {
 25838  		x = x + 010000000000 // use two's complement for negative values
 25839  		x = x + 010000000000
 25840  		prg.tfmFile.Write(x/0100000000 + 128)
 25841  	}
 25842  	x = x % 0100000000
 25843  	prg.tfmFile.Write(x / 0200000)
 25844  	x = x % 0200000
 25845  	prg.tfmFile.Write(x / 0400)
 25846  	prg.tfmFile.Write(x % 0400)
 25847  }
 25848  
 25849  func (prg *prg) tfmQqqq(x fourQuarters) {
 25850  	prg.tfmFile.Write(int32(x.b0) - minQuarterword)
 25851  	prg.tfmFile.Write(int32(x.b1) - minQuarterword)
 25852  	prg.tfmFile.Write(int32(x.b2) - minQuarterword)
 25853  	prg.tfmFile.Write(int32(x.b3) - minQuarterword)
 25854  }
 25855  
 25856  // 1142. \[46] Generic font file format
 25857  
 25858  // tangle:pos ../../mf.web:21761:35:
 25859  
 25860  // The most important output produced by a typical run of \MF\ is the
 25861  // ``generic font'' (\.[GF]) file that specifies the bit patterns of the
 25862  // characters that have been drawn. The term [\sl generic\/] indicates that
 25863  // this file format doesn't match the conventions of any name-brand manufacturer;
 25864  // but it is easy to convert \.[GF] files to the special format required by
 25865  // almost all digital phototypesetting equipment. There's a strong analogy
 25866  // between the \.[DVI] files written by \TeX\ and the \.[GF] files written
 25867  // by \MF; and, in fact, the file formats have a lot in common.
 25868  //
 25869  // A \.[GF] file is a stream of 8-bit bytes that may be
 25870  // regarded as a series of commands in a machine-like language. The first
 25871  // byte of each command is the operation code, and this code is followed by
 25872  // zero or more bytes that provide parameters to the command. The parameters
 25873  // themselves may consist of several consecutive bytes; for example, the
 25874  // `|boc|' (beginning of character) command has six parameters, each of
 25875  // which is four bytes long. Parameters are usually regarded as nonnegative
 25876  // integers; but four-byte-long parameters can be either positive or
 25877  // negative, hence they range in value from $-2^[31]$ to $2^[31]-1$.
 25878  // As in \.[TFM] files, numbers that occupy
 25879  // more than one byte position appear in BigEndian order,
 25880  // and negative numbers appear in two's complement notation.
 25881  //
 25882  // A \.[GF] file consists of a ``preamble,'' followed by a sequence of one or
 25883  // more ``characters,'' followed by a ``postamble.'' The preamble is simply a
 25884  // |pre| command, with its parameters that introduce the file; this must come
 25885  // first.  Each ``character'' consists of a |boc| command, followed by any
 25886  // number of other commands that specify ``black'' pixels,
 25887  // followed by an |eoc| command. The characters appear in the order that \MF\
 25888  // generated them. If we ignore no-op commands (which are allowed between any
 25889  // two commands in the file), each |eoc| command is immediately followed by a
 25890  // |boc| command, or by a |post| command; in the latter case, there are no
 25891  // more characters in the file, and the remaining bytes form the postamble.
 25892  // Further details about the postamble will be explained later.
 25893  //
 25894  // Some parameters in \.[GF] commands are ``pointers.'' These are four-byte
 25895  // quantities that give the location number of some other byte in the file;
 25896  // the first file byte is number~0, then comes number~1, and so on.
 25897  
 25898  // 1143.
 25899  
 25900  // tangle:pos ../../mf.web:21800:3:
 25901  
 25902  // The \.[GF] format is intended to be both compact and easily interpreted
 25903  // by a machine. Compactness is achieved by making most of the information
 25904  // relative instead of absolute. When a \.[GF]-reading program reads the
 25905  // commands for a character, it keeps track of two quantities: (a)~the current
 25906  // column number,~|m|; and (b)~the current row number,~|n|.  These are 32-bit
 25907  // signed integers, although most actual font formats produced from \.[GF]
 25908  // files will need to curtail this vast range because of practical
 25909  // limitations. (\MF\ output will never allow $\vert m\vert$ or $\vert
 25910  // n\vert$ to get extremely large, but the \.[GF] format tries to be more general.)
 25911  //
 25912  // How do \.[GF]'s row and column numbers correspond to the conventions
 25913  // of \TeX\ and \MF? Well, the ``reference point'' of a character, in \TeX's
 25914  // view, is considered to be at the lower left corner of the pixel in row~0
 25915  // and column~0. This point is the intersection of the baseline with the left
 25916  // edge of the type; it corresponds to location $(0,0)$ in \MF\ programs.
 25917  // Thus the pixel in \.[GF] row~0 and column~0 is \MF's unit square, comprising the
 25918  // region of the plane whose coordinates both lie between 0 and~1. The
 25919  // pixel in \.[GF] row~|n| and column~|m| consists of the points whose \MF\
 25920  // coordinates |(x,y)| satisfy |m<=x<=m+1| and |n<=y<=n+1|.  Negative values of
 25921  // |m| and~|x| correspond to columns of pixels [\sl left\/] of the reference
 25922  // point; negative values of |n| and~|y| correspond to rows of pixels [\sl
 25923  // below\/] the baseline.
 25924  //
 25925  // Besides |m| and |n|, there's also a third aspect of the current
 25926  // state, namely the  |paint_switch|, which is always either |black| or
 25927  // |white|. Each \\[paint] command advances |m| by a specified amount~|d|,
 25928  // and blackens the intervening pixels if |paint_switch=black|; then
 25929  // the |paint_switch| changes to the opposite state. \.[GF]'s commands are
 25930  // designed so that |m| will never decrease within a row, and |n| will never
 25931  // increase within a character; hence there is no way to whiten a pixel that
 25932  // has been blackened.
 25933  
 25934  // 1144.
 25935  
 25936  // tangle:pos ../../mf.web:21832:3:
 25937  
 25938  // Here is a list of all the commands that may appear in a \.[GF] file. Each
 25939  // command is specified by its symbolic name (e.g., |boc|), its opcode byte
 25940  // (e.g., 67), and its parameters (if any). The parameters are followed
 25941  // by a bracketed number telling how many bytes they occupy; for example,
 25942  // `|d[2]|' means that parameter |d| is two bytes long.
 25943  //
 25944  // \yskip\hang|paint_0| 0. This is a \\[paint] command with |d=0|; it does
 25945  // nothing but change the |paint_switch| from \\[black] to \\[white] or vice~versa.
 25946  //
 25947  // \yskip\hang\\[paint\_1] through \\[paint\_63] (opcodes 1 to 63).
 25948  // These are \\[paint] commands with |d=1| to~63, defined as follows: If
 25949  // |paint_switch=black|, blacken |d|~pixels of the current row~|n|,
 25950  // in columns |m| through |m+d-1| inclusive. Then, in any case,
 25951  // complement the |paint_switch| and advance |m| by~|d|.
 25952  //
 25953  // \yskip\hang|paint1| 64 |d[1]|. This is a \\[paint] command with a specified
 25954  // value of~|d|; \MF\ uses it to paint when |64<=d<256|.
 25955  //
 25956  // \yskip\hang| paint2| 65 |d[2]|. Same as |paint1|, but |d|~can be as high
 25957  // as~65535.
 25958  //
 25959  // \yskip\hang| paint3| 66 |d[3]|. Same as |paint1|, but |d|~can be as high
 25960  // as $2^[24]-1$. \MF\ never needs this command, and it is hard to imagine
 25961  // anybody making practical use of it; surely a more compact encoding will be
 25962  // desirable when characters can be this large. But the command is there,
 25963  // anyway, just in case.
 25964  //
 25965  // \yskip\hang|boc| 67 |c[4]| |p[4]| |min_m[4]| |max_m[4]| |min_n[4]|
 25966  // |max_n[4]|. Beginning of a character:  Here |c| is the character code, and
 25967  // |p| points to the previous character beginning (if any) for characters having
 25968  // this code number modulo 256.  (The pointer |p| is |-1| if there was no
 25969  // prior character with an equivalent code.) The values of registers |m| and |n|
 25970  // defined by the instructions that follow for this character must
 25971  // satisfy |min_m<=m<=max_m| and |min_n<=n<=max_n|.  (The values of |max_m| and
 25972  // |min_n| need not be the tightest bounds possible.)  When a \.[GF]-reading
 25973  // program sees a |boc|, it can use |min_m|, |max_m|, |min_n|, and |max_n| to
 25974  // initialize the bounds of an array. Then it sets |m:=min_m|, |n:=max_n|, and
 25975  // |paint_switch:=white|.
 25976  //
 25977  // \yskip\hang|boc1| 68 |c[1]| | del_m[1]| |max_m[1]| | del_n[1]| |max_n[1]|.
 25978  // Same as |boc|, but |p| is assumed to be~$-1$; also |del_m=max_m-min_m|
 25979  // and |del_n=max_n-min_n| are given instead of |min_m| and |min_n|.
 25980  // The one-byte parameters must be between 0 and 255, inclusive.
 25981  // \ (This abbreviated |boc| saves 19~bytes per character, in common cases.)
 25982  //
 25983  // \yskip\hang|eoc| 69. End of character: All pixels blackened so far
 25984  // constitute the pattern for this character. In particular, a completely
 25985  // blank character might have |eoc| immediately following |boc|.
 25986  //
 25987  // \yskip\hang|skip0| 70. Decrease |n| by 1 and set |m:=min_m|,
 25988  // |paint_switch:=white|. \ (This finishes one row and begins another,
 25989  // ready to whiten the leftmost pixel in the new row.)
 25990  //
 25991  // \yskip\hang|skip1| 71 |d[1]|. Decrease |n| by |d+1|, set |m:=min_m|, and set
 25992  // |paint_switch:=white|. This is a way to produce |d| all-white rows.
 25993  //
 25994  // \yskip\hang| skip2| 72 |d[2]|. Same as |skip1|, but |d| can be as large
 25995  // as 65535.
 25996  //
 25997  // \yskip\hang| skip3| 73 |d[3]|. Same as |skip1|, but |d| can be as large
 25998  // as $2^[24]-1$. \MF\ obviously never needs this command.
 25999  //
 26000  // \yskip\hang|new_row_0| 74. Decrease |n| by 1 and set |m:=min_m|,
 26001  // |paint_switch:=black|. \ (This finishes one row and begins another,
 26002  // ready to [\sl blacken\/] the leftmost pixel in the new row.)
 26003  //
 26004  // \yskip\hang| new_row_1| through | new_row_164| (opcodes 75 to 238). Same as
 26005  // |new_row_0|, but with |m:=min_m+1| through |min_m+164|, respectively.
 26006  //
 26007  // \yskip\hang|xxx1| 239 |k[1]| |x[k]|. This command is undefined in
 26008  // general; it functions as a $(k+2)$-byte |no_op| unless special \.[GF]-reading
 26009  // programs are being used. \MF\ generates \\[xxx] commands when encountering
 26010  // a \&[special] string; this occurs in the \.[GF] file only between
 26011  // characters, after the preamble, and before the postamble. However,
 26012  // \\[xxx] commands might appear within characters,
 26013  // in \.[GF] files generated by other
 26014  // processors. It is recommended that |x| be a string having the form of a
 26015  // keyword followed by possible parameters relevant to that keyword.
 26016  //
 26017  // \yskip\hang| xxx2| 240 |k[2]| |x[k]|. Like |xxx1|, but |0<=k<65536|.
 26018  //
 26019  // \yskip\hang|xxx3| 241 |k[3]| |x[k]|. Like |xxx1|, but |0<=k<$2^[24]$|.
 26020  // \MF\ uses this when sending a \&[special] string whose length exceeds~255.
 26021  //
 26022  // \yskip\hang| xxx4| 242 |k[4]| |x[k]|. Like |xxx1|, but |k| can be
 26023  // ridiculously large; |k| mustn't be negative.
 26024  //
 26025  // \yskip\hang|yyy| 243 |y[4]|. This command is undefined in general;
 26026  // it functions as a 5-byte |no_op| unless special \.[GF]-reading programs
 26027  // are being used. \MF\ puts |scaled| numbers into |yyy|'s, as a
 26028  // result of \&[numspecial] commands; the intent is to provide numeric
 26029  // parameters to \\[xxx] commands that immediately precede.
 26030  //
 26031  // \yskip\hang| no_op| 244. No operation, do nothing. Any number of |no_op|'s
 26032  // may occur between \.[GF] commands, but a |no_op| cannot be inserted between
 26033  // a command and its parameters or between two parameters.
 26034  //
 26035  // \yskip\hang|char_loc| 245 |c[1]| |dx[4]| |dy[4]| |w[4]| |p[4]|.
 26036  // This command will appear only in the postamble, which will be explained shortly.
 26037  //
 26038  // \yskip\hang| char_loc0| 246 |c[1]| | dm[1]| |w[4]| |p[4]|.
 26039  // Same as |char_loc|, except that |dy| is assumed to be zero, and the value
 26040  // of~|dx| is taken to be |65536*dm|, where |0<=dm<256|.
 26041  //
 26042  // \yskip\hang|pre| 247 |i[1]| |k[1]| |x[k]|.
 26043  // Beginning of the preamble; this must come at the very beginning of the
 26044  // file. Parameter |i| is an identifying number for \.[GF] format, currently
 26045  // 131. The other information is merely commentary; it is not given
 26046  // special interpretation like \\[xxx] commands are. (Note that \\[xxx]
 26047  // commands may immediately follow the preamble, before the first |boc|.)
 26048  //
 26049  // \yskip\hang|post| 248. Beginning of the postamble, see below.
 26050  //
 26051  // \yskip\hang|post_post| 249. Ending of the postamble, see below.
 26052  //
 26053  // \yskip\noindent Commands 250--255 are undefined at the present time.
 26054  
 26055  // 1145.
 26056  
 26057  // tangle:pos ../../mf.web:21951:3:
 26058  
 26059  // \MF\ refers to the following opcodes explicitly.
 26060  
 26061  // 1146.
 26062  
 26063  // tangle:pos ../../mf.web:21971:3:
 26064  
 26065  // The last character in a \.[GF] file is followed by `|post|'; this command
 26066  // introduces the postamble, which summarizes important facts that \MF\ has
 26067  // accumulated. The postamble has the form
 26068  // $$\vbox[\halign[\hbox[#\hfil]\cr
 26069  //   |post| |p[4]| | ds[4]| | cs[4]| | hppp[4]| | vppp[4]|
 26070  //    | min_m[4]| | max_m[4]| | min_n[4]| | max_n[4]|\cr
 26071  //   $\langle\,$character locators$\,\rangle$\cr
 26072  //   |post_post| |q[4]| |i[1]| 223's$[[\G]4]$\cr]]$$
 26073  // Here |p| is a pointer to the byte following the final |eoc| in the file
 26074  // (or to the byte following the preamble, if there are no characters);
 26075  // it can be used to locate the beginning of \\[xxx] commands
 26076  // that might have preceded the postamble. The |ds| and |cs| parameters
 26077  // \xref[design size] \xref[check sum]
 26078  // give the design size and check sum, respectively, which are exactly the
 26079  // values put into the header of the \.[TFM] file that \MF\ produces (or
 26080  // would produce) on this run. Parameters |hppp| and |vppp| are the ratios of
 26081  // pixels per point, horizontally and vertically, expressed as |scaled| integers
 26082  // (i.e., multiplied by $2^[16]$); they can be used to correlate the font
 26083  // with specific device resolutions, magnifications, and ``at sizes.''  Then
 26084  // come |min_m|, |max_m|, |min_n|, and |max_n|, which bound the values that
 26085  // registers |m| and~|n| assume in all characters in this \.[GF] file.
 26086  // (These bounds need not be the best possible; |max_m| and |min_n| may, on the
 26087  // other hand, be tighter than the similar bounds in |boc| commands. For
 26088  // example, some character may have |min_n=-100| in its |boc|, but it might
 26089  // turn out that |n| never gets lower than |-50| in any character; then
 26090  // |min_n| can have any value |<=-50|. If there are no characters in the file,
 26091  // it's possible to have |min_m>max_m| and/or |min_n>max_n|.)
 26092  
 26093  // 1147.
 26094  
 26095  // tangle:pos ../../mf.web:21999:3:
 26096  
 26097  // Character locators are introduced by |char_loc| commands,
 26098  // which specify a character residue~|c|, character escapements (|dx,dy|),
 26099  // a character width~|w|, and a pointer~|p|
 26100  // to the beginning of that character. (If two or more characters have the
 26101  // same code~|c| modulo 256, only the last will be indicated; the others can be
 26102  // located by following backpointers. Characters whose codes differ by a
 26103  // multiple of 256 are assumed to share the same font metric information,
 26104  // hence the \.[TFM] file contains only residues of character codes modulo~256.
 26105  // This convention is intended for oriental languages, when there are many
 26106  // character shapes but few distinct widths.)
 26107  // \xref[oriental characters]\xref[Chinese characters]\xref[Japanese characters]
 26108  //
 26109  // The character escapements (|dx,dy|) are the values of \MF's \&[chardx]
 26110  // and \&[chardy] parameters; they are in units of |scaled| pixels;
 26111  // i.e., |dx| is in horizontal pixel units times $2^[16]$, and |dy| is in
 26112  // vertical pixel units times $2^[16]$.  This is the intended amount of
 26113  // displacement after typesetting the character; for \.[DVI] files, |dy|
 26114  // should be zero, but other document file formats allow nonzero vertical
 26115  // escapement.
 26116  //
 26117  // The character width~|w| duplicates the information in the \.[TFM] file; it
 26118  // is a |fix_word| value relative to the design size, and it should be
 26119  // independent of magnification.
 26120  //
 26121  // The backpointer |p| points to the character's |boc|, or to the first of
 26122  // a sequence of consecutive \\[xxx] or |yyy| or |no_op| commands that
 26123  // immediately precede the |boc|, if such commands exist; such ``special''
 26124  // commands essentially belong to the characters, while the special commands
 26125  // after the final character belong to the postamble (i.e., to the font
 26126  // as a whole). This convention about |p| applies also to the backpointers
 26127  // in |boc| commands, even though it wasn't explained in the description
 26128  // of~|boc|. \xref[backpointers]
 26129  //
 26130  // Pointer |p| might be |-1| if the character exists in the \.[TFM] file
 26131  // but not in the \.[GF] file. This unusual situation can arise in \MF\ output
 26132  // if the user had |proofing<0| when the character was being shipped out,
 26133  // but then made |proofing>=0| in order to get a \.[GF] file.
 26134  
 26135  // 1148.
 26136  
 26137  // tangle:pos ../../mf.web:22037:3:
 26138  
 26139  // The last part of the postamble, following the |post_post| byte that
 26140  // signifies the end of the character locators, contains |q|, a pointer to the
 26141  // |post| command that started the postamble.  An identification byte, |i|,
 26142  // comes next; this currently equals~131, as in the preamble.
 26143  //
 26144  // The |i| byte is followed by four or more bytes that are all equal to
 26145  // the decimal number 223 (i.e., @'337 in octal). \MF\ puts out four to seven of
 26146  // these trailing bytes, until the total length of the file is a multiple of
 26147  // four bytes, since this works out best on machines that pack four bytes per
 26148  // word; but any number of 223's is allowed, as long as there are at least four
 26149  // of them. In effect, 223 is a sort of signature that is added at the very end.
 26150  // \xref[Fuchs, David Raymond]
 26151  //
 26152  // This curious way to finish off a \.[GF] file makes it feasible for
 26153  // \.[GF]-reading programs to find the postamble first, on most computers,
 26154  // even though \MF\ wants to write the postamble last. Most operating
 26155  // systems permit random access to individual words or bytes of a file, so
 26156  // the \.[GF] reader can start at the end and skip backwards over the 223's
 26157  // until finding the identification byte. Then it can back up four bytes, read
 26158  // |q|, and move to byte |q| of the file. This byte should, of course,
 26159  // contain the value 248 (|post|); now the postamble can be read, so the
 26160  // \.[GF] reader can discover all the information needed for individual characters.
 26161  //
 26162  // Unfortunately, however, standard \PASCAL\ does not include the ability to
 26163  // \xref[system dependencies]
 26164  // access a random position in a file, or even to determine the length of a file.
 26165  // Almost all systems nowadays provide the necessary capabilities, so \.[GF]
 26166  // format has been designed to work most efficiently with modern operating systems.
 26167  // But if \.[GF] files have to be processed under the restrictions of standard
 26168  // \PASCAL, one can simply read them from front to back. This will
 26169  // be adequate for most applications. However, the postamble-first approach
 26170  // would facilitate a program that merges two \.[GF] files, replacing data
 26171  // from one that is overridden by corresponding data in the other.
 26172  
 26173  // 1187.
 26174  
 26175  // tangle:pos ../../mf.web:22552:3:
 26176  
 26177  // Corresponding to the procedure that dumps a base file, we also have a function
 26178  // that reads~one~in. The function returns |false| if the dumped base is
 26179  // incompatible with the present \MF\ table sizes, etc.
 26180  // \4
 26181  // Declare the function called |open_base_file|
 26182  func (prg *prg) openBaseFile() (r bool) {
 26183  	var (
 26184  		j /* 0..bufSize */ uint16 // the first space after the file name
 26185  	)
 26186  	j = prg.curInput.locField
 26187  	if int32(prg.buffer[prg.curInput.locField]) == '&' {
 26188  		prg.curInput.locField = uint16(int32(prg.curInput.locField) + 1)
 26189  		j = prg.curInput.locField
 26190  		prg.buffer[prg.last] = ' '
 26191  		for int32(prg.buffer[j]) != ' ' {
 26192  			j = uint16(int32(j) + 1)
 26193  		}
 26194  		prg.packBufferedName(smallNumber(0), int32(prg.curInput.locField), int32(j)-1) // try first without the system file area
 26195  		if prg.wOpenIn(prg.baseFile) {
 26196  			goto found
 26197  		}
 26198  		prg.packBufferedName(smallNumber(baseAreaLength), int32(prg.curInput.locField), int32(j)-1)
 26199  		// now try the system base file area
 26200  		if prg.wOpenIn(prg.baseFile) {
 26201  			goto found
 26202  		}
 26203  
 26204  		prg.termOut.Writeln("Sorry, I can't find that base;", " will try PLAIN.")
 26205  		// \xref[Sorry, I can't find...]
 26206  
 26207  	}
 26208  	// now pull out all the stops: try for the system \.[plain] file
 26209  	prg.packBufferedName(smallNumber(baseDefaultLength-baseExtLength), 1, 0)
 26210  	if !prg.wOpenIn(prg.baseFile) {
 26211  		prg.termOut.Writeln("I can't find the PLAIN base file!")
 26212  		// \xref[I can't find PLAIN...]
 26213  		// \xref[plain]
 26214  		r = false
 26215  		goto exit
 26216  	}
 26217  
 26218  found:
 26219  	prg.curInput.locField = j
 26220  	r = true
 26221  
 26222  exit:
 26223  	;
 26224  	return r
 26225  }
 26226  
 26227  func (prg *prg) loadBaseFile() (r bool) {
 26228  	var (
 26229  		k    int32        // all-purpose index
 26230  		p, q halfword     // all-purpose pointers
 26231  		x    int32        // something undumped
 26232  		w    fourQuarters // four ASCII codes
 26233  	)
 26234  	x = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26235  	if x != 461259239 {
 26236  		goto offBase
 26237  	} // check that strings are the same
 26238  	{
 26239  		prg.baseFile.Get()
 26240  		x = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26241  	}
 26242  	if x != memMin {
 26243  		goto offBase
 26244  	}
 26245  	{
 26246  		prg.baseFile.Get()
 26247  		x = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26248  	}
 26249  	if x != 3000 {
 26250  		goto offBase
 26251  	}
 26252  	{
 26253  		prg.baseFile.Get()
 26254  		x = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26255  	}
 26256  	if x != hashSize {
 26257  		goto offBase
 26258  	}
 26259  	{
 26260  		prg.baseFile.Get()
 26261  		x = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26262  	}
 26263  	if x != hashPrime {
 26264  		goto offBase
 26265  	}
 26266  	{
 26267  		prg.baseFile.Get()
 26268  		x = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26269  	}
 26270  	if x != maxInOpen {
 26271  		goto offBase
 26272  	}
 26273  
 26274  	// Undump the string pool
 26275  	{
 26276  		{
 26277  			prg.baseFile.Get()
 26278  			x = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26279  		}
 26280  		if x < 0 {
 26281  			goto offBase
 26282  		}
 26283  		if x > poolSize {
 26284  			prg.termOut.Writeln("---! Must increase the ", "string pool size") /* \xref[Must increase the x]  */ /* \xref[Must increase the x]  */
 26285  			goto offBase
 26286  		} else {
 26287  			prg.poolPtr = uint16(x)
 26288  		}
 26289  	}
 26290  	{
 26291  		{
 26292  			prg.baseFile.Get()
 26293  			x = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26294  		}
 26295  		if x < 0 {
 26296  			goto offBase
 26297  		}
 26298  		if x > maxStrings {
 26299  			prg.termOut.Writeln("---! Must increase the ", "max strings") /* \xref[Must increase the x]  */ /* \xref[Must increase the x]  */
 26300  			goto offBase
 26301  		} else {
 26302  			prg.strPtr = uint16(x)
 26303  		}
 26304  	}
 26305  	for ii := int32(0); ii <= int32(prg.strPtr); ii++ {
 26306  		k = ii
 26307  		_ = k
 26308  		{
 26309  			{
 26310  				prg.baseFile.Get()
 26311  				x = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26312  			}
 26313  			if x < 0 || x > int32(prg.poolPtr) {
 26314  				goto offBase
 26315  			} else {
 26316  				prg.strStart[k] = uint16(x)
 26317  			}
 26318  		}
 26319  		prg.strRef[k] = byte(maxStrRef)
 26320  	}
 26321  	k = 0
 26322  	for k+4 < int32(prg.poolPtr) {
 26323  		{
 26324  			prg.baseFile.Get()
 26325  			w = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).qqqq()
 26326  		}
 26327  		prg.strPool[k] = byte(int32(w.b0) - minQuarterword)
 26328  		prg.strPool[k+1] = byte(int32(w.b1) - minQuarterword)
 26329  		prg.strPool[k+2] = byte(int32(w.b2) - minQuarterword)
 26330  		prg.strPool[k+3] = byte(int32(w.b3) - minQuarterword)
 26331  		k = k + 4
 26332  	}
 26333  	k = int32(prg.poolPtr) - 4
 26334  	{
 26335  		prg.baseFile.Get()
 26336  		w = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).qqqq()
 26337  	}
 26338  	prg.strPool[k] = byte(int32(w.b0) - minQuarterword)
 26339  	prg.strPool[k+1] = byte(int32(w.b1) - minQuarterword)
 26340  	prg.strPool[k+2] = byte(int32(w.b2) - minQuarterword)
 26341  	prg.strPool[k+3] = byte(int32(w.b3) - minQuarterword)
 26342  	prg.initStrPtr = prg.strPtr
 26343  	prg.initPoolPtr = prg.poolPtr
 26344  	prg.maxStrPtr = prg.strPtr
 26345  	prg.maxPoolPtr = prg.poolPtr
 26346  
 26347  	// Undump the dynamic memory
 26348  	{
 26349  		{
 26350  			prg.baseFile.Get()
 26351  			x = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26352  		}
 26353  		if x < memMin+3+10+2+2+2+2+1+1000 || x > 3000-2-1 {
 26354  			goto offBase
 26355  		} else {
 26356  			prg.loMemMax = uint16(x)
 26357  		}
 26358  	}
 26359  	{
 26360  		{
 26361  			prg.baseFile.Get()
 26362  			x = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26363  		}
 26364  		if x < memMin+3+10+2+2+2+2+1+1 || x > int32(prg.loMemMax) {
 26365  			goto offBase
 26366  		} else {
 26367  			prg.rover = uint16(x)
 26368  		}
 26369  	}
 26370  	p = uint16(memMin)
 26371  	q = prg.rover
 26372  	for {
 26373  		for ii := int32(p); ii <= int32(q)+1; ii++ {
 26374  			k = ii
 26375  			_ = k
 26376  			prg.baseFile.Get()
 26377  			prg.mem[k] = *(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))
 26378  		}
 26379  		p = uint16(int32(q) + int32(*(*prg.mem[q].hh()).lh()))
 26380  		if int32(p) > int32(prg.loMemMax) || int32(q) >= int32(*(*prg.mem[int32(q)+1].hh()).rh()) && int32(*(*prg.mem[int32(q)+1].hh()).rh()) != int32(prg.rover) {
 26381  			goto offBase
 26382  		}
 26383  		q = *(*prg.mem[int32(q)+1].hh()).rh()
 26384  		if int32(q) == int32(prg.rover) {
 26385  			break
 26386  		}
 26387  	}
 26388  	for ii := int32(p); ii <= int32(prg.loMemMax); ii++ {
 26389  		k = ii
 26390  		_ = k
 26391  		prg.baseFile.Get()
 26392  		prg.mem[k] = *(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))
 26393  	}
 26394  	{
 26395  		{
 26396  			prg.baseFile.Get()
 26397  			x = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26398  		}
 26399  		if x < int32(prg.loMemMax)+1 || x > 3000-2 {
 26400  			goto offBase
 26401  		} else {
 26402  			prg.hiMemMin = uint16(x)
 26403  		}
 26404  	}
 26405  	{
 26406  		{
 26407  			prg.baseFile.Get()
 26408  			x = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26409  		}
 26410  		if x < memMin || x > 3000 {
 26411  			goto offBase
 26412  		} else {
 26413  			prg.avail = uint16(x)
 26414  		}
 26415  	}
 26416  	prg.memEnd = 3000
 26417  	for ii := int32(prg.hiMemMin); ii <= int32(prg.memEnd); ii++ {
 26418  		k = ii
 26419  		_ = k
 26420  		prg.baseFile.Get()
 26421  		prg.mem[k] = *(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))
 26422  	}
 26423  	{
 26424  		prg.baseFile.Get()
 26425  		prg.varUsed = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26426  	}
 26427  	{
 26428  		prg.baseFile.Get()
 26429  		prg.dynUsed = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26430  	}
 26431  
 26432  	// Undump the table of equivalents and the hash table
 26433  	{
 26434  		{
 26435  			prg.baseFile.Get()
 26436  			x = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26437  		}
 26438  		if x < 1 || x > hashBase+hashSize {
 26439  			goto offBase
 26440  		} else {
 26441  			prg.hashUsed = uint16(x)
 26442  		}
 26443  	}
 26444  	p = 0
 26445  	for {
 26446  		{
 26447  			{
 26448  				prg.baseFile.Get()
 26449  				x = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26450  			}
 26451  			if x < int32(p)+1 || x > int32(prg.hashUsed) {
 26452  				goto offBase
 26453  			} else {
 26454  				p = uint16(x)
 26455  			}
 26456  		}
 26457  		{
 26458  			prg.baseFile.Get()
 26459  			prg.hash[p-1] = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).hh()
 26460  		}
 26461  		{
 26462  			prg.baseFile.Get()
 26463  			prg.eqtb[p-1] = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).hh()
 26464  		}
 26465  		if int32(p) == int32(prg.hashUsed) {
 26466  			break
 26467  		}
 26468  	}
 26469  	for ii := int32(prg.hashUsed) + 1; ii <= hashBase+hashSize+12; ii++ {
 26470  		p = halfword(ii)
 26471  		_ = p
 26472  		{
 26473  			prg.baseFile.Get()
 26474  			prg.hash[p-1] = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).hh()
 26475  		}
 26476  		{
 26477  			prg.baseFile.Get()
 26478  			prg.eqtb[p-1] = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).hh()
 26479  		}
 26480  	}
 26481  	{
 26482  		prg.baseFile.Get()
 26483  		prg.stCount = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26484  	}
 26485  
 26486  	// Undump a few more things and the closing check word
 26487  	{
 26488  		{
 26489  			prg.baseFile.Get()
 26490  			x = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26491  		}
 26492  		if x < maxGivenInternal || x > maxInternal {
 26493  			goto offBase
 26494  		} else {
 26495  			prg.intPtr = byte(x)
 26496  		}
 26497  	}
 26498  	for ii := int32(1); ii <= int32(prg.intPtr); ii++ {
 26499  		k = ii
 26500  		_ = k
 26501  		{
 26502  			prg.baseFile.Get()
 26503  			prg.internal[k-1] = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26504  		}
 26505  		{
 26506  			{
 26507  				prg.baseFile.Get()
 26508  				x = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26509  			}
 26510  			if x < 0 || x > int32(prg.strPtr) {
 26511  				goto offBase
 26512  			} else {
 26513  				prg.intName[k-1] = uint16(x)
 26514  			}
 26515  		}
 26516  	}
 26517  	{
 26518  		{
 26519  			prg.baseFile.Get()
 26520  			x = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26521  		}
 26522  		if x < 0 || x > hashBase+hashSize {
 26523  			goto offBase
 26524  		} else {
 26525  			prg.startSym = uint16(x)
 26526  		}
 26527  	}
 26528  	{
 26529  		{
 26530  			prg.baseFile.Get()
 26531  			x = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26532  		}
 26533  		if x < batchMode || x > errorStopMode {
 26534  			goto offBase
 26535  		} else {
 26536  			prg.interaction = byte(x)
 26537  		}
 26538  	}
 26539  	{
 26540  		{
 26541  			prg.baseFile.Get()
 26542  			x = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26543  		}
 26544  		if x < 0 || x > int32(prg.strPtr) {
 26545  			goto offBase
 26546  		} else {
 26547  			prg.baseIdent = uint16(x)
 26548  		}
 26549  	}
 26550  	{
 26551  		{
 26552  			prg.baseFile.Get()
 26553  			x = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26554  		}
 26555  		if x < 1 || x > hashBase+hashSize+12 {
 26556  			goto offBase
 26557  		} else {
 26558  			prg.bgLoc = uint16(x)
 26559  		}
 26560  	}
 26561  	{
 26562  		{
 26563  			prg.baseFile.Get()
 26564  			x = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26565  		}
 26566  		if x < 1 || x > hashBase+hashSize+12 {
 26567  			goto offBase
 26568  		} else {
 26569  			prg.egLoc = uint16(x)
 26570  		}
 26571  	}
 26572  	{
 26573  		prg.baseFile.Get()
 26574  		prg.serialNo = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26575  	}
 26576  
 26577  	{
 26578  		prg.baseFile.Get()
 26579  		x = *(*(*memoryWord)(unsafe.Pointer(prg.baseFile.Data4P()))).int()
 26580  	}
 26581  	if x != 69069 || prg.baseFile.EOF() {
 26582  		goto offBase
 26583  	}
 26584  	r = true
 26585  	goto exit // it worked!
 26586  	// it worked!
 26587  offBase:
 26588  	;
 26589  	prg.termOut.Writeln("(Fatal base file error; I'm stymied)")
 26590  	// \xref[Fatal base file error]
 26591  	r = false
 26592  
 26593  exit:
 26594  	;
 26595  	return r
 26596  }
 26597  
 26598  // 706. \[35] Expanding the next token
 26599  
 26600  // tangle:pos ../../mf.web:14572:35:
 26601  
 26602  // Only a few command codes |<min_command| can possibly be returned by
 26603  // |get_next|; in increasing order, they are
 26604  // |if_test|, |fi_or_else|, |input|, |iteration|, |repeat_loop|,
 26605  // |exit_test|, |relax|, |scan_tokens|, |expand_after|, and |defined_macro|.
 26606  //
 26607  // \MF\ usually gets the next token of input by saying |get_x_next|. This is
 26608  // like |get_next| except that it keeps getting more tokens until
 26609  // finding |cur_cmd>=min_command|. In other words, |get_x_next| expands
 26610  // macros and removes conditionals or iterations or input instructions that
 26611  // might be present.
 26612  //
 26613  // It follows that |get_x_next| might invoke itself recursively. In fact,
 26614  // there is massive recursion, since macro expansion can involve the
 26615  // scanning of arbitrarily complex expressions, which in turn involve
 26616  // macro expansion and conditionals, etc.
 26617  // \xref[recursion]
 26618  //
 26619  // Therefore it's necessary to declare a whole bunch of |forward|
 26620  // procedures at this point, and to insert some other procedures
 26621  // that will be invoked by |get_x_next|.
 26622  func (prg *prg) scanPrimary() {
 26623  	var (
 26624  		p, q, r1                              halfword    // for list manipulation
 26625  		c                                     quarterword // a primitive operation code
 26626  		myVarFlag/* 0..maxCommandCode */ byte             // initial value of |var_flag|
 26627  		lDelim, rDelim                        halfword    // hash addresses of a delimiter pair
 26628  
 26629  		// Other local variables for |scan_primary|
 26630  		groupLine int32 // where a group began
 26631  
 26632  		num, denom scaled // for primaries that are fractions, like `1/2'
 26633  
 26634  		preHead, postHead, tail halfword
 26635  		// prefix and suffix list variables
 26636  		tt       smallNumber // approximation to the type of the variable-so-far
 26637  		t        halfword    // a token
 26638  		macroRef halfword    // reference count for a suffixed macro
 26639  	)
 26640  	myVarFlag = prg.varFlag
 26641  	prg.varFlag = 0
 26642  
 26643  restart:
 26644  	{
 26645  		if prg.arithError {
 26646  			prg.clearArith()
 26647  		}
 26648  	}
 26649  
 26650  	// Supply diagnostic information, if requested
 26651  	//  if panicking then check_mem(false); [  ]
 26652  
 26653  	if prg.interrupt != 0 {
 26654  		if prg.okToInterrupt {
 26655  			prg.backInput()
 26656  			{
 26657  				if prg.interrupt != 0 {
 26658  					prg.pauseForInstructions()
 26659  				}
 26660  			}
 26661  			prg.getXNext()
 26662  		}
 26663  	}
 26664  	switch prg.curCmd {
 26665  	case leftDelimiter:
 26666  		// Scan a delimited primary
 26667  		lDelim = prg.curSym
 26668  		rDelim = uint16(prg.curMod)
 26669  		prg.getXNext()
 26670  		prg.scanExpression()
 26671  		if int32(prg.curCmd) == comma && int32(prg.curType) >= known {
 26672  			p = prg.getNode(valueNodeSize)
 26673  			*(*prg.mem[p].hh()).b0() = byte(pairType)
 26674  			*(*prg.mem[p].hh()).b1() = byte(capsule)
 26675  			prg.initBigNode(p)
 26676  			q = uint16(*prg.mem[int32(p)+1].int())
 26677  			prg.stashIn(q)
 26678  
 26679  			prg.getXNext()
 26680  			prg.scanExpression()
 26681  			if int32(prg.curType) < known {
 26682  				prg.dispErr(halfword(memMin), strNumber( /* "Nonnumeric ypart has been replaced by 0" */ 775))
 26683  				// \xref[Nonnumeric...replaced by 0]
 26684  				{
 26685  					prg.helpPtr = 4
 26686  					prg.helpLine[3] = /* "I thought you were giving me a pair `(x,y)'; but" */ 776
 26687  					prg.helpLine[2] = /* "after finding a nice xpart `x' I found a ypart `y'" */ 777
 26688  					prg.helpLine[1] = /* "that isn't of numeric type. So I've changed y to zero." */ 778
 26689  					prg.helpLine[0] = /* "(The y that I didn't like appears above the error message.)" */ 779
 26690  				}
 26691  				prg.putGetFlushError(scaled(0))
 26692  			}
 26693  			prg.stashIn(halfword(int32(q) + 2))
 26694  			prg.checkDelimiter(lDelim, rDelim)
 26695  			prg.curType = byte(pairType)
 26696  			prg.curExp = int32(p)
 26697  		} else {
 26698  			prg.checkDelimiter(lDelim, rDelim)
 26699  		}
 26700  
 26701  	case beginGroup:
 26702  		// Scan a grouped primary
 26703  		groupLine = prg.line
 26704  		if prg.internal[tracingCommands-1] > 0 {
 26705  			prg.showCmdMod(int32(prg.curCmd), prg.curMod)
 26706  		}
 26707  		{
 26708  			p = prg.getAvail()
 26709  			*(*prg.mem[p].hh()).lh() = 0
 26710  			*(*prg.mem[p].hh()).rh() = prg.savePtr
 26711  			prg.savePtr = p
 26712  		}
 26713  		for {
 26714  			prg.doStatement() // ends with |cur_cmd>=semicolon|
 26715  			if int32(prg.curCmd) != semicolon {
 26716  				break
 26717  			}
 26718  		}
 26719  		if int32(prg.curCmd) != endGroup {
 26720  			{
 26721  				if int32(prg.interaction) == errorStopMode {
 26722  				}
 26723  				prg.printNl(strNumber( /* "! " */ 261))
 26724  				prg.print( /* "A group begun on line " */ 780) /* \xref[!\relax]  */
 26725  			}
 26726  			// \xref[A group...never ended]
 26727  			prg.printInt(groupLine)
 26728  			prg.print( /* " never ended" */ 781)
 26729  			{
 26730  				prg.helpPtr = 2
 26731  				prg.helpLine[1] = /* "I saw a `begingroup' back there that hasn't been matched" */ 782
 26732  				prg.helpLine[0] = /* "by `endgroup'. So I've inserted `endgroup' now." */ 783
 26733  			}
 26734  			prg.backError()
 26735  			prg.curCmd = byte(endGroup)
 26736  		}
 26737  		prg.unsave() // this might change |cur_type|, if independent variables are recycled
 26738  		if prg.internal[tracingCommands-1] > 0 {
 26739  			prg.showCmdMod(int32(prg.curCmd), prg.curMod)
 26740  		}
 26741  
 26742  	case stringToken:
 26743  		// Scan a string constant
 26744  		prg.curType = byte(stringType)
 26745  		prg.curExp = prg.curMod
 26746  
 26747  	case numericToken:
 26748  		// Scan a primary that starts with a numeric token
 26749  		prg.curExp = prg.curMod
 26750  		prg.curType = byte(known)
 26751  		prg.getXNext()
 26752  		if int32(prg.curCmd) != slash {
 26753  			num = 0
 26754  			denom = 0
 26755  		} else {
 26756  			prg.getXNext()
 26757  			if int32(prg.curCmd) != numericToken {
 26758  				prg.backInput()
 26759  				prg.curCmd = byte(slash)
 26760  				prg.curMod = over
 26761  				prg.curSym = uint16(hashBase + hashSize + 4)
 26762  
 26763  				goto done
 26764  			}
 26765  			num = prg.curExp
 26766  			denom = prg.curMod
 26767  			if denom == 0 {
 26768  				{
 26769  					if int32(prg.interaction) == errorStopMode {
 26770  					}
 26771  					prg.printNl(strNumber( /* "! " */ 261))
 26772  					prg.print( /* "Division by zero" */ 784) /* \xref[!\relax]  */
 26773  				}
 26774  				// \xref[Division by zero]
 26775  				{
 26776  					prg.helpPtr = 1
 26777  					prg.helpLine[0] = /* "I'll pretend that you meant to divide by 1." */ 785
 26778  				}
 26779  				prg.error1()
 26780  			} else {
 26781  				prg.curExp = prg.makeScaled(num, denom)
 26782  			}
 26783  			{
 26784  				if prg.arithError {
 26785  					prg.clearArith()
 26786  				}
 26787  			}
 26788  			prg.getXNext()
 26789  		}
 26790  		if int32(prg.curCmd) >= minPrimaryCommand {
 26791  			if int32(prg.curCmd) < numericToken {
 26792  				p = prg.stashCurExp()
 26793  				prg.scanPrimary()
 26794  				if abs(num) >= abs(denom) || int32(prg.curType) < pairType {
 26795  					prg.doBinary(p, quarterword(times))
 26796  				} else {
 26797  					prg.fracMult(num, denom)
 26798  					prg.freeNode(p, halfword(valueNodeSize))
 26799  				}
 26800  			}
 26801  		}
 26802  
 26803  		goto done
 26804  
 26805  	case nullary:
 26806  		// Scan a nullary operation
 26807  		prg.doNullary(quarterword(prg.curMod))
 26808  
 26809  	case unary, typeName, cycle, plusOrMinus:
 26810  		// Scan a unary operation
 26811  		c = byte(prg.curMod)
 26812  		prg.getXNext()
 26813  		prg.scanPrimary()
 26814  		prg.doUnary(c)
 26815  		goto done
 26816  
 26817  	case primaryBinary:
 26818  		// Scan a binary operation with `\&[of]' between its operands
 26819  		c = byte(prg.curMod)
 26820  		prg.getXNext()
 26821  		prg.scanExpression()
 26822  		if int32(prg.curCmd) != ofToken {
 26823  			prg.missingErr(strNumber( /* "of" */ 479))
 26824  			prg.print( /* " for " */ 715)
 26825  			prg.printCmdMod(primaryBinary, int32(c))
 26826  			// \xref[Missing `of']
 26827  			{
 26828  				prg.helpPtr = 1
 26829  				prg.helpLine[0] = /* "I've got the first argument; will look now for the other." */ 716
 26830  			}
 26831  			prg.backError()
 26832  		}
 26833  		p = prg.stashCurExp()
 26834  		prg.getXNext()
 26835  		prg.scanPrimary()
 26836  		prg.doBinary(p, c)
 26837  		goto done
 26838  
 26839  	case strOp:
 26840  		// Convert a suffix to a string
 26841  		prg.getXNext()
 26842  		prg.scanSuffix()
 26843  		prg.oldSetting = prg.selector
 26844  		prg.selector = byte(newString)
 26845  		prg.showTokenList(prg.curExp, memMin, 100000, 0)
 26846  		prg.flushTokenList(halfword(prg.curExp))
 26847  		prg.curExp = int32(prg.makeString())
 26848  		prg.selector = prg.oldSetting
 26849  		prg.curType = byte(stringType)
 26850  
 26851  		goto done
 26852  
 26853  	case internalQuantity:
 26854  		// Scan an internal numeric quantity
 26855  		q = uint16(prg.curMod)
 26856  		if int32(myVarFlag) == assignment {
 26857  			prg.getXNext()
 26858  			if int32(prg.curCmd) == assignment {
 26859  				prg.curExp = int32(prg.getAvail())
 26860  				*(*prg.mem[prg.curExp].hh()).lh() = uint16(int32(q) + hashBase + hashSize + 12)
 26861  				prg.curType = byte(tokenList)
 26862  				goto done
 26863  			}
 26864  			prg.backInput()
 26865  		}
 26866  		prg.curType = byte(known)
 26867  		prg.curExp = prg.internal[q-1]
 26868  
 26869  	case capsuleToken:
 26870  		prg.makeExpCopy(halfword(prg.curMod))
 26871  	case tagToken:
 26872  		// Scan a variable primary; |goto restart| if it turns out to be a macro
 26873  		{
 26874  			preHead = prg.avail
 26875  			if int32(preHead) == memMin {
 26876  				preHead = prg.getAvail()
 26877  			} else {
 26878  				prg.avail = *(*prg.mem[preHead].hh()).rh()
 26879  				*(*prg.mem[preHead].hh()).rh() = uint16(memMin)
 26880  				prg.dynUsed = prg.dynUsed + 1
 26881  			}
 26882  		}
 26883  		tail = preHead
 26884  		postHead = uint16(memMin)
 26885  		tt = byte(vacuous)
 26886  		for true {
 26887  			t = prg.curTok()
 26888  			*(*prg.mem[tail].hh()).rh() = t
 26889  			if int32(tt) != undefined {
 26890  				{
 26891  					p = *(*prg.mem[preHead].hh()).rh()
 26892  					q = *(*prg.mem[p].hh()).lh()
 26893  					tt = byte(undefined)
 26894  					if int32(*prg.eqtb[q-1].lh())%outerTag == tagToken {
 26895  						q = *prg.eqtb[q-1].rh()
 26896  						if int32(q) == memMin {
 26897  							goto done2
 26898  						}
 26899  						for true {
 26900  							p = *(*prg.mem[p].hh()).rh()
 26901  							if int32(p) == memMin {
 26902  								tt = *(*prg.mem[q].hh()).b0()
 26903  								goto done2
 26904  							}
 26905  							if int32(*(*prg.mem[q].hh()).b0()) != structured {
 26906  								goto done2
 26907  							}
 26908  							q = *(*prg.mem[*(*prg.mem[int32(q)+1].hh()).lh()].hh()).rh() // the |collective_subscript| attribute
 26909  							if int32(p) >= int32(prg.hiMemMin) {
 26910  								for {
 26911  									q = *(*prg.mem[q].hh()).rh()
 26912  									if int32(*(*prg.mem[int32(q)+2].hh()).lh()) >= int32(*(*prg.mem[p].hh()).lh()) {
 26913  										break
 26914  									}
 26915  								}
 26916  								if int32(*(*prg.mem[int32(q)+2].hh()).lh()) > int32(*(*prg.mem[p].hh()).lh()) {
 26917  									goto done2
 26918  								}
 26919  							}
 26920  						}
 26921  					}
 26922  
 26923  				done2:
 26924  				}
 26925  				if int32(tt) >= unsuffixedMacro {
 26926  					*(*prg.mem[tail].hh()).rh() = uint16(memMin)
 26927  					if int32(tt) > unsuffixedMacro {
 26928  						postHead = prg.getAvail()
 26929  						tail = postHead
 26930  						*(*prg.mem[tail].hh()).rh() = t
 26931  
 26932  						tt = byte(undefined)
 26933  						macroRef = uint16(*prg.mem[int32(q)+1].int())
 26934  						*(*prg.mem[macroRef].hh()).lh() = uint16(int32(*(*prg.mem[macroRef].hh()).lh()) + 1)
 26935  					} else {
 26936  						// Set up unsuffixed macro call and |goto restart|
 26937  						p = prg.getAvail()
 26938  						*(*prg.mem[preHead].hh()).lh() = *(*prg.mem[preHead].hh()).rh()
 26939  						*(*prg.mem[preHead].hh()).rh() = p
 26940  						*(*prg.mem[p].hh()).lh() = t
 26941  						prg.macroCall(halfword(*prg.mem[int32(q)+1].int()), preHead, halfword(memMin))
 26942  						prg.getXNext()
 26943  						goto restart
 26944  					}
 26945  				}
 26946  			}
 26947  			prg.getXNext()
 26948  			tail = t
 26949  			if int32(prg.curCmd) == leftBracket {
 26950  				prg.getXNext()
 26951  				prg.scanExpression()
 26952  				if int32(prg.curCmd) != rightBracket {
 26953  					prg.backInput() // that was the token following the current expression
 26954  					prg.backExpr()
 26955  					prg.curCmd = byte(leftBracket)
 26956  					prg.curMod = 0
 26957  					prg.curSym = uint16(hashBase + hashSize + 3)
 26958  				} else {
 26959  					if int32(prg.curType) != known {
 26960  						prg.badSubscript()
 26961  					}
 26962  					prg.curCmd = byte(numericToken)
 26963  					prg.curMod = prg.curExp
 26964  					prg.curSym = 0
 26965  				}
 26966  			}
 26967  			if int32(prg.curCmd) > maxSuffixToken {
 26968  				goto done1
 26969  			}
 26970  			if int32(prg.curCmd) < minSuffixToken {
 26971  				goto done1
 26972  			}
 26973  		} // now |cur_cmd| is |internal_quantity|, |tag_token|, or |numeric_token|
 26974  		// now |cur_cmd| is |internal_quantity|, |tag_token|, or |numeric_token|
 26975  	done1:
 26976  		if int32(postHead) != memMin {
 26977  			prg.backInput()
 26978  			p = prg.getAvail()
 26979  			q = *(*prg.mem[postHead].hh()).rh()
 26980  			*(*prg.mem[preHead].hh()).lh() = *(*prg.mem[preHead].hh()).rh()
 26981  			*(*prg.mem[preHead].hh()).rh() = postHead
 26982  			*(*prg.mem[postHead].hh()).lh() = q
 26983  			*(*prg.mem[postHead].hh()).rh() = p
 26984  			*(*prg.mem[p].hh()).lh() = *(*prg.mem[q].hh()).rh()
 26985  			*(*prg.mem[q].hh()).rh() = uint16(memMin)
 26986  			prg.macroCall(macroRef, preHead, halfword(memMin))
 26987  			*(*prg.mem[macroRef].hh()).lh() = uint16(int32(*(*prg.mem[macroRef].hh()).lh()) - 1)
 26988  			prg.getXNext()
 26989  			goto restart
 26990  		}
 26991  		q = *(*prg.mem[preHead].hh()).rh()
 26992  		{
 26993  			*(*prg.mem[preHead].hh()).rh() = prg.avail
 26994  			prg.avail = preHead
 26995  			prg.dynUsed = prg.dynUsed - 1
 26996  		}
 26997  		if int32(prg.curCmd) == int32(myVarFlag) {
 26998  			prg.curType = byte(tokenList)
 26999  			prg.curExp = int32(q)
 27000  			goto done
 27001  		}
 27002  		p = prg.findVariable(q)
 27003  		if int32(p) != memMin {
 27004  			prg.makeExpCopy(p)
 27005  		} else {
 27006  			prg.obliterated(q)
 27007  
 27008  			prg.helpLine[2] = /* "While I was evaluating the suffix of this variable," */ 797
 27009  			prg.helpLine[1] = /* "something was redefined, and it's no longer a variable!" */ 798
 27010  			prg.helpLine[0] = /* "In order to get back on my feet, I've inserted `0' instead." */ 799
 27011  			prg.putGetFlushError(scaled(0))
 27012  		}
 27013  		prg.flushNodeList(q)
 27014  		goto done
 27015  
 27016  	default:
 27017  		prg.badExp(strNumber( /* "A primary" */ 769))
 27018  		goto restart
 27019  		// \xref[A primary expression...]
 27020  
 27021  	}
 27022  
 27023  	prg.getXNext() // the routines |goto done| if they don't want this
 27024  	// the routines |goto done| if they don't want this
 27025  done:
 27026  	if int32(prg.curCmd) == leftBracket {
 27027  		if int32(prg.curType) >= known {
 27028  			p = prg.stashCurExp()
 27029  			prg.getXNext()
 27030  			prg.scanExpression()
 27031  			if int32(prg.curCmd) != comma {
 27032  				{
 27033  					prg.backInput() // that was the token following the current expression
 27034  					prg.backExpr()
 27035  					prg.curCmd = byte(leftBracket)
 27036  					prg.curMod = 0
 27037  					prg.curSym = uint16(hashBase + hashSize + 3)
 27038  				}
 27039  				prg.unstashCurExp(p)
 27040  			} else {
 27041  				q = prg.stashCurExp()
 27042  				prg.getXNext()
 27043  				prg.scanExpression()
 27044  				if int32(prg.curCmd) != rightBracket {
 27045  					prg.missingErr(strNumber(']'))
 27046  
 27047  					// \xref[Missing `]']
 27048  					{
 27049  						prg.helpPtr = 3
 27050  						prg.helpLine[2] = /* "I've scanned an expression of the form `a[b,c'," */ 801
 27051  						prg.helpLine[1] = /* "so a right bracket should have come next." */ 802
 27052  						prg.helpLine[0] = /* "I shall pretend that one was there." */ 697
 27053  					}
 27054  
 27055  					prg.backError()
 27056  				}
 27057  				r1 = prg.stashCurExp()
 27058  				prg.makeExpCopy(q)
 27059  
 27060  				prg.doBinary(r1, quarterword(minus))
 27061  				prg.doBinary(p, quarterword(times))
 27062  				prg.doBinary(q, quarterword(plus))
 27063  				prg.getXNext()
 27064  			}
 27065  		}
 27066  	}
 27067  } // \2
 27068  func (prg *prg) scanSuffix() {
 27069  	var (
 27070  		h, t halfword // head and tail of the list being built
 27071  		p    halfword // temporary register
 27072  	)
 27073  	h = prg.getAvail()
 27074  	t = h
 27075  	for true {
 27076  		if int32(prg.curCmd) == leftBracket {
 27077  			prg.getXNext()
 27078  			prg.scanExpression()
 27079  			if int32(prg.curType) != known {
 27080  				prg.badSubscript()
 27081  			}
 27082  			if int32(prg.curCmd) != rightBracket {
 27083  				prg.missingErr(strNumber(']'))
 27084  
 27085  				// \xref[Missing `]']
 27086  				{
 27087  					prg.helpPtr = 3
 27088  					prg.helpLine[2] = /* "I've seen a `[' and a subscript value, in a suffix," */ 803
 27089  					prg.helpLine[1] = /* "so a right bracket should have come next." */ 802
 27090  					prg.helpLine[0] = /* "I shall pretend that one was there." */ 697
 27091  				}
 27092  
 27093  				prg.backError()
 27094  			}
 27095  			prg.curCmd = byte(numericToken)
 27096  			prg.curMod = prg.curExp
 27097  		}
 27098  		if int32(prg.curCmd) == numericToken {
 27099  			p = prg.newNumTok(prg.curMod)
 27100  		} else if int32(prg.curCmd) == tagToken || int32(prg.curCmd) == internalQuantity {
 27101  			p = prg.getAvail()
 27102  			*(*prg.mem[p].hh()).lh() = prg.curSym
 27103  		} else {
 27104  			goto done
 27105  		}
 27106  		*(*prg.mem[t].hh()).rh() = p
 27107  		t = p
 27108  		prg.getXNext()
 27109  	}
 27110  
 27111  done:
 27112  	prg.curExp = int32(*(*prg.mem[h].hh()).rh())
 27113  	{
 27114  		*(*prg.mem[h].hh()).rh() = prg.avail
 27115  		prg.avail = h
 27116  		prg.dynUsed = prg.dynUsed - 1
 27117  	}
 27118  	prg.curType = byte(tokenList)
 27119  } // \2
 27120  func (prg *prg) scanSecondary() {
 27121  	var (
 27122  		p       halfword // for list manipulation
 27123  		c, d    halfword // operation codes or modifiers
 27124  		macName halfword // token defined with \&[primarydef]
 27125  	)
 27126  restart:
 27127  	if int32(prg.curCmd) < minPrimaryCommand || int32(prg.curCmd) > maxPrimaryCommand {
 27128  		prg.badExp(strNumber( /* "A secondary" */ 804))
 27129  	}
 27130  	// \xref[A secondary expression...]
 27131  	prg.scanPrimary()
 27132  
 27133  continue1:
 27134  	if int32(prg.curCmd) <= maxSecondaryCommand {
 27135  		if int32(prg.curCmd) >= minSecondaryCommand {
 27136  			p = prg.stashCurExp()
 27137  			c = uint16(prg.curMod)
 27138  			d = uint16(prg.curCmd)
 27139  			if int32(d) == secondaryPrimaryMacro {
 27140  				macName = prg.curSym
 27141  				*(*prg.mem[c].hh()).lh() = uint16(int32(*(*prg.mem[c].hh()).lh()) + 1)
 27142  			}
 27143  			prg.getXNext()
 27144  			prg.scanPrimary()
 27145  			if int32(d) != secondaryPrimaryMacro {
 27146  				prg.doBinary(p, quarterword(c))
 27147  			} else {
 27148  				prg.backInput()
 27149  				prg.binaryMac(p, c, macName)
 27150  				*(*prg.mem[c].hh()).lh() = uint16(int32(*(*prg.mem[c].hh()).lh()) - 1)
 27151  				prg.getXNext()
 27152  				goto restart
 27153  			}
 27154  
 27155  			goto continue1
 27156  		}
 27157  	}
 27158  } // \2
 27159  func (prg *prg) scanTertiary() {
 27160  	var (
 27161  		p       halfword // for list manipulation
 27162  		c, d    halfword // operation codes or modifiers
 27163  		macName halfword // token defined with \&[secondarydef]
 27164  	)
 27165  restart:
 27166  	if int32(prg.curCmd) < minPrimaryCommand || int32(prg.curCmd) > maxPrimaryCommand {
 27167  		prg.badExp(strNumber( /* "A tertiary" */ 805))
 27168  	}
 27169  	// \xref[A tertiary expression...]
 27170  	prg.scanSecondary()
 27171  	if int32(prg.curType) == futurePen {
 27172  		prg.materializePen()
 27173  	}
 27174  
 27175  continue1:
 27176  	if int32(prg.curCmd) <= maxTertiaryCommand {
 27177  		if int32(prg.curCmd) >= minTertiaryCommand {
 27178  			p = prg.stashCurExp()
 27179  			c = uint16(prg.curMod)
 27180  			d = uint16(prg.curCmd)
 27181  			if int32(d) == tertiarySecondaryMacro {
 27182  				macName = prg.curSym
 27183  				*(*prg.mem[c].hh()).lh() = uint16(int32(*(*prg.mem[c].hh()).lh()) + 1)
 27184  			}
 27185  			prg.getXNext()
 27186  			prg.scanSecondary()
 27187  			if int32(d) != tertiarySecondaryMacro {
 27188  				prg.doBinary(p, quarterword(c))
 27189  			} else {
 27190  				prg.backInput()
 27191  				prg.binaryMac(p, c, macName)
 27192  				*(*prg.mem[c].hh()).lh() = uint16(int32(*(*prg.mem[c].hh()).lh()) - 1)
 27193  				prg.getXNext()
 27194  				goto restart
 27195  			}
 27196  
 27197  			goto continue1
 27198  		}
 27199  	}
 27200  } // \2
 27201  func (prg *prg) scanExpression() {
 27202  	var (
 27203  		p, q, r1, pp, qq                      halfword // for list manipulation
 27204  		c, d                                  halfword // operation codes or modifiers
 27205  		myVarFlag/* 0..maxCommandCode */ byte          // initial value of |var_flag|
 27206  		macName                               halfword // token defined with \&[tertiarydef]
 27207  		cycleHit                              bool     // did a path expression just end with `\&[cycle]'?
 27208  		x, y                                  scaled   // explicit coordinates or tension at a path join
 27209  		t/* endpoint..open */ byte                     // knot type following a path join
 27210  	)
 27211  	myVarFlag = prg.varFlag
 27212  
 27213  restart:
 27214  	if int32(prg.curCmd) < minPrimaryCommand || int32(prg.curCmd) > maxPrimaryCommand {
 27215  		prg.badExp(strNumber( /* "An" */ 808))
 27216  	}
 27217  	// \xref[An expression...]
 27218  	prg.scanTertiary()
 27219  
 27220  continue1:
 27221  	if int32(prg.curCmd) <= maxExpressionCommand {
 27222  		if int32(prg.curCmd) >= minExpressionCommand {
 27223  			if int32(prg.curCmd) != equals || int32(myVarFlag) != assignment {
 27224  				p = prg.stashCurExp()
 27225  				c = uint16(prg.curMod)
 27226  				d = uint16(prg.curCmd)
 27227  				if int32(d) == expressionTertiaryMacro {
 27228  					macName = prg.curSym
 27229  					*(*prg.mem[c].hh()).lh() = uint16(int32(*(*prg.mem[c].hh()).lh()) + 1)
 27230  				}
 27231  				if int32(d) < ampersand || int32(d) == ampersand && (int32(*(*prg.mem[p].hh()).b0()) == pairType || int32(*(*prg.mem[p].hh()).b0()) == pathType) {
 27232  					cycleHit = false
 27233  
 27234  					// Convert the left operand, |p|, into a partial path ending at~|q|; but |return| if |p| doesn't have a suitable type
 27235  					{
 27236  						prg.unstashCurExp(p)
 27237  						if int32(prg.curType) == pairType {
 27238  							p = prg.newKnot()
 27239  						} else if int32(prg.curType) == pathType {
 27240  							p = uint16(prg.curExp)
 27241  						} else {
 27242  							goto exit
 27243  						}
 27244  						q = p
 27245  						for int32(*(*prg.mem[q].hh()).rh()) != int32(p) {
 27246  							q = *(*prg.mem[q].hh()).rh()
 27247  						}
 27248  						if int32(*(*prg.mem[p].hh()).b0()) != endpoint {
 27249  							r1 = prg.copyKnot(p)
 27250  							*(*prg.mem[q].hh()).rh() = r1
 27251  							q = r1
 27252  						}
 27253  						*(*prg.mem[p].hh()).b0() = byte(open)
 27254  						*(*prg.mem[q].hh()).b1() = byte(open)
 27255  					}
 27256  
 27257  				continuePath:
 27258  					if int32(prg.curCmd) == leftBrace {
 27259  						t = prg.scanDirection()
 27260  						if int32(t) != open {
 27261  							*(*prg.mem[q].hh()).b1() = t
 27262  							*prg.mem[int32(q)+5].int() = prg.curExp
 27263  							if int32(*(*prg.mem[q].hh()).b0()) == open {
 27264  								*(*prg.mem[q].hh()).b0() = t
 27265  								*prg.mem[int32(q)+3].int() = prg.curExp
 27266  							} // note that |left_given(q)=left_curl(q)|
 27267  						}
 27268  					}
 27269  					d = uint16(prg.curCmd)
 27270  					if int32(d) == pathJoin {
 27271  						prg.getXNext()
 27272  						if int32(prg.curCmd) == tension {
 27273  							prg.getXNext()
 27274  							y = int32(prg.curCmd)
 27275  							if int32(prg.curCmd) == atLeast {
 27276  								prg.getXNext()
 27277  							}
 27278  							prg.scanPrimary()
 27279  
 27280  							// Make sure that the current expression is a valid tension setting
 27281  							if int32(prg.curType) != known || prg.curExp < 0140000 {
 27282  								prg.dispErr(halfword(memMin), strNumber( /* "Improper tension has been set to 1" */ 826))
 27283  								// \xref[Improper tension]
 27284  								{
 27285  									prg.helpPtr = 1
 27286  									prg.helpLine[0] = /* "The expression above should have been a number >=3/4." */ 827
 27287  								}
 27288  								prg.putGetFlushError(scaled(0200000))
 27289  							}
 27290  							if y == atLeast {
 27291  								prg.curExp = -prg.curExp
 27292  							}
 27293  							*prg.mem[int32(q)+6].int() = prg.curExp
 27294  							if int32(prg.curCmd) == andCommand {
 27295  								prg.getXNext()
 27296  								y = int32(prg.curCmd)
 27297  								if int32(prg.curCmd) == atLeast {
 27298  									prg.getXNext()
 27299  								}
 27300  								prg.scanPrimary()
 27301  
 27302  								// Make sure that the current expression is a valid tension setting
 27303  								if int32(prg.curType) != known || prg.curExp < 0140000 {
 27304  									prg.dispErr(halfword(memMin), strNumber( /* "Improper tension has been set to 1" */ 826))
 27305  									// \xref[Improper tension]
 27306  									{
 27307  										prg.helpPtr = 1
 27308  										prg.helpLine[0] = /* "The expression above should have been a number >=3/4." */ 827
 27309  									}
 27310  									prg.putGetFlushError(scaled(0200000))
 27311  								}
 27312  								if y == atLeast {
 27313  									prg.curExp = -prg.curExp
 27314  								}
 27315  							}
 27316  							y = prg.curExp
 27317  						} else if int32(prg.curCmd) == controls {
 27318  							*(*prg.mem[q].hh()).b1() = byte(explicit)
 27319  							t = byte(explicit)
 27320  							prg.getXNext()
 27321  							prg.scanPrimary()
 27322  
 27323  							prg.knownPair()
 27324  							*prg.mem[int32(q)+5].int() = prg.curX
 27325  							*prg.mem[int32(q)+6].int() = prg.curY
 27326  							if int32(prg.curCmd) != andCommand {
 27327  								x = *prg.mem[int32(q)+5].int()
 27328  								y = *prg.mem[int32(q)+6].int()
 27329  							} else {
 27330  								prg.getXNext()
 27331  								prg.scanPrimary()
 27332  
 27333  								prg.knownPair()
 27334  								x = prg.curX
 27335  								y = prg.curY
 27336  							}
 27337  						} else {
 27338  							*prg.mem[int32(q)+6].int() = 0200000
 27339  							y = 0200000
 27340  							prg.backInput() // default tension
 27341  							// default tension
 27342  							goto done
 27343  						}
 27344  						if int32(prg.curCmd) != pathJoin {
 27345  							prg.missingErr(strNumber( /* ".." */ 409))
 27346  
 27347  							// \xref[Missing `..']
 27348  							{
 27349  								prg.helpPtr = 1
 27350  								prg.helpLine[0] = /* "A path join command should end with two dots." */ 825
 27351  							}
 27352  							prg.backError()
 27353  						}
 27354  
 27355  					done:
 27356  					} else if int32(d) != ampersand {
 27357  						goto finishPath
 27358  					}
 27359  					prg.getXNext()
 27360  					if int32(prg.curCmd) == leftBrace {
 27361  						t = prg.scanDirection()
 27362  						if int32(*(*prg.mem[q].hh()).b1()) != explicit {
 27363  							x = prg.curExp
 27364  						} else {
 27365  							t = byte(explicit)
 27366  						} // the direction information is superfluous
 27367  					} else if int32(*(*prg.mem[q].hh()).b1()) != explicit {
 27368  						t = byte(open)
 27369  						x = 0
 27370  					}
 27371  					if int32(prg.curCmd) == cycle {
 27372  						cycleHit = true
 27373  						prg.getXNext()
 27374  						pp = p
 27375  						qq = p
 27376  						if int32(d) == ampersand {
 27377  							if int32(p) == int32(q) {
 27378  								d = uint16(pathJoin)
 27379  								*prg.mem[int32(q)+6].int() = 0200000
 27380  								y = 0200000
 27381  							}
 27382  						}
 27383  					} else {
 27384  						prg.scanTertiary()
 27385  
 27386  						// Convert the right operand, |cur_exp|, into a partial path from |pp| to~|qq|
 27387  						{
 27388  							if int32(prg.curType) != pathType {
 27389  								pp = prg.newKnot()
 27390  							} else {
 27391  								pp = uint16(prg.curExp)
 27392  							}
 27393  							qq = pp
 27394  							for int32(*(*prg.mem[qq].hh()).rh()) != int32(pp) {
 27395  								qq = *(*prg.mem[qq].hh()).rh()
 27396  							}
 27397  							if int32(*(*prg.mem[pp].hh()).b0()) != endpoint {
 27398  								r1 = prg.copyKnot(pp)
 27399  								*(*prg.mem[qq].hh()).rh() = r1
 27400  								qq = r1
 27401  							}
 27402  							*(*prg.mem[pp].hh()).b0() = byte(open)
 27403  							*(*prg.mem[qq].hh()).b1() = byte(open)
 27404  						}
 27405  					}
 27406  
 27407  					// Join the partial paths and reset |p| and |q| to the head and tail of the result
 27408  					{
 27409  						if int32(d) == ampersand {
 27410  							if *prg.mem[int32(q)+1].int() != *prg.mem[int32(pp)+1].int() || *prg.mem[int32(q)+2].int() != *prg.mem[int32(pp)+2].int() {
 27411  								{
 27412  									if int32(prg.interaction) == errorStopMode {
 27413  									}
 27414  									prg.printNl(strNumber( /* "! " */ 261))
 27415  									prg.print( /* "Paths don't touch; `&' will be changed to `..'" */ 828) /* \xref[!\relax]  */
 27416  								}
 27417  								// \xref[Paths don't touch]
 27418  								{
 27419  									prg.helpPtr = 3
 27420  									prg.helpLine[2] = /* "When you join paths `p&q', the ending point of p" */ 829
 27421  									prg.helpLine[1] = /* "must be exactly equal to the starting point of q." */ 830
 27422  									prg.helpLine[0] = /* "So I'm going to pretend that you said `p..q' instead." */ 831
 27423  								}
 27424  								prg.putGetError()
 27425  								d = uint16(pathJoin)
 27426  								*prg.mem[int32(q)+6].int() = 0200000
 27427  								y = 0200000
 27428  							}
 27429  						}
 27430  
 27431  						// Plug an opening in |right_type(pp)|, if possible
 27432  						if int32(*(*prg.mem[pp].hh()).b1()) == open {
 27433  							if int32(t) == curl || int32(t) == given {
 27434  								*(*prg.mem[pp].hh()).b1() = t
 27435  								*prg.mem[int32(pp)+5].int() = x
 27436  							}
 27437  						}
 27438  						if int32(d) == ampersand {
 27439  							if int32(*(*prg.mem[q].hh()).b0()) == open {
 27440  								if int32(*(*prg.mem[q].hh()).b1()) == open {
 27441  									*(*prg.mem[q].hh()).b0() = byte(curl)
 27442  									*prg.mem[int32(q)+3].int() = 0200000
 27443  								}
 27444  							}
 27445  							if int32(*(*prg.mem[pp].hh()).b1()) == open {
 27446  								if int32(t) == open {
 27447  									*(*prg.mem[pp].hh()).b1() = byte(curl)
 27448  									*prg.mem[int32(pp)+5].int() = 0200000
 27449  								}
 27450  							}
 27451  							*(*prg.mem[q].hh()).b1() = *(*prg.mem[pp].hh()).b1()
 27452  							*(*prg.mem[q].hh()).rh() = *(*prg.mem[pp].hh()).rh()
 27453  
 27454  							*prg.mem[int32(q)+5].int() = *prg.mem[int32(pp)+5].int()
 27455  							*prg.mem[int32(q)+6].int() = *prg.mem[int32(pp)+6].int()
 27456  							prg.freeNode(pp, halfword(knotNodeSize))
 27457  							if int32(qq) == int32(pp) {
 27458  								qq = q
 27459  							}
 27460  						} else {
 27461  							if int32(*(*prg.mem[q].hh()).b1()) == open {
 27462  								if int32(*(*prg.mem[q].hh()).b0()) == curl || int32(*(*prg.mem[q].hh()).b0()) == given {
 27463  									*(*prg.mem[q].hh()).b1() = *(*prg.mem[q].hh()).b0()
 27464  									*prg.mem[int32(q)+5].int() = *prg.mem[int32(q)+3].int()
 27465  								}
 27466  							}
 27467  							*(*prg.mem[q].hh()).rh() = pp
 27468  							*prg.mem[int32(pp)+4].int() = y
 27469  							if int32(t) != open {
 27470  								*prg.mem[int32(pp)+3].int() = x
 27471  								*(*prg.mem[pp].hh()).b0() = t
 27472  							}
 27473  						}
 27474  						q = qq
 27475  					}
 27476  					if int32(prg.curCmd) >= minExpressionCommand {
 27477  						if int32(prg.curCmd) <= ampersand {
 27478  							if !cycleHit {
 27479  								goto continuePath
 27480  							}
 27481  						}
 27482  					}
 27483  
 27484  				finishPath:
 27485  					if cycleHit {
 27486  						if int32(d) == ampersand {
 27487  							p = q
 27488  						}
 27489  					} else {
 27490  						*(*prg.mem[p].hh()).b0() = byte(endpoint)
 27491  						if int32(*(*prg.mem[p].hh()).b1()) == open {
 27492  							*(*prg.mem[p].hh()).b1() = byte(curl)
 27493  							*prg.mem[int32(p)+5].int() = 0200000
 27494  						}
 27495  						*(*prg.mem[q].hh()).b1() = byte(endpoint)
 27496  						if int32(*(*prg.mem[q].hh()).b0()) == open {
 27497  							*(*prg.mem[q].hh()).b0() = byte(curl)
 27498  							*prg.mem[int32(q)+3].int() = 0200000
 27499  						}
 27500  						*(*prg.mem[q].hh()).rh() = p
 27501  					}
 27502  					prg.makeChoices(p)
 27503  					prg.curType = byte(pathType)
 27504  					prg.curExp = int32(p)
 27505  				} else {
 27506  					prg.getXNext()
 27507  					prg.scanTertiary()
 27508  					if int32(d) != expressionTertiaryMacro {
 27509  						prg.doBinary(p, quarterword(c))
 27510  					} else {
 27511  						prg.backInput()
 27512  						prg.binaryMac(p, c, macName)
 27513  						*(*prg.mem[c].hh()).lh() = uint16(int32(*(*prg.mem[c].hh()).lh()) - 1)
 27514  						prg.getXNext()
 27515  						goto restart
 27516  					}
 27517  				}
 27518  
 27519  				goto continue1
 27520  			}
 27521  		}
 27522  	}
 27523  
 27524  exit:
 27525  }
 27526  
 27527  func (prg *prg) getBoolean() {
 27528  	prg.getXNext()
 27529  	prg.scanExpression()
 27530  	if int32(prg.curType) != booleanType {
 27531  		prg.dispErr(halfword(memMin), strNumber( /* "Undefined condition will be treated as `false'" */ 832))
 27532  		// \xref[Undefined condition...]
 27533  		{
 27534  			prg.helpPtr = 2
 27535  			prg.helpLine[1] = /* "The expression shown above should have had a definite" */ 833
 27536  			prg.helpLine[0] = /* "true-or-false value. I'm changing it to `false'." */ 834
 27537  		}
 27538  
 27539  		prg.putGetFlushError(falseCode)
 27540  		prg.curType = byte(booleanType)
 27541  	}
 27542  }
 27543  
 27544  // 153. \[9] Packed data
 27545  
 27546  // tangle:pos ../../mf.web:3103:21:
 27547  
 27548  // In order to make efficient use of storage space, \MF\ bases its major data
 27549  // structures on a |memory_word|, which contains either a (signed) integer,
 27550  // possibly scaled, or a small number of fields that are one half or one
 27551  // quarter of the size used for storing integers.
 27552  //
 27553  // If |x| is a variable of type |memory_word|, it contains up to four
 27554  // fields that can be referred to as follows:
 27555  // $$\vbox[\halign[\hfil#&#\hfil&#\hfil\cr
 27556  // |x|&.|int|&(an |integer|)\cr
 27557  // |x|&.|sc|\qquad&(a |scaled| integer)\cr
 27558  // |x.hh.lh|, |x.hh|&.|rh|&(two halfword fields)\cr
 27559  // |x.hh.b0|, |x.hh.b1|, |x.hh|&.|rh|&(two quarterword fields, one halfword
 27560  //   field)\cr
 27561  // |x.qqqq.b0|, |x.qqqq.b1|, |x.qqqq|&.|b2|, |x.qqqq.b3|\hskip-100pt
 27562  //   &\qquad\qquad\qquad(four quarterword fields)\cr]]$$
 27563  // This is somewhat cumbersome to write, and not very readable either, but
 27564  // macros will be used to make the notation shorter and more transparent.
 27565  // The \PASCAL\ code below gives a formal definition of |memory_word| and
 27566  // its subsidiary types, using packed variant records. \MF\ makes no
 27567  // assumptions about the relative positions of the fields within a word.
 27568  //
 27569  // Since we are assuming 32-bit integers, a halfword must contain at least
 27570  // 16 bits, and a quarterword must contain at least 8 bits.
 27571  // \xref[system dependencies]
 27572  // But it doesn't hurt to have more bits; for example, with enough 36-bit
 27573  // words you might be able to have |mem_max| as large as 262142.
 27574  //
 27575  // N.B.: Valuable memory space will be dreadfully wasted unless \MF\ is compiled
 27576  // by a \PASCAL\ that packs all of the |memory_word| variants into
 27577  // the space of a single integer. Some \PASCAL\ compilers will pack an
 27578  // integer whose subrange is `|0..255|' into an eight-bit field, but others
 27579  // insist on allocating space for an additional sign bit; on such systems you
 27580  // can get 256 values into a quarterword only if the subrange is `|-128..127|'.
 27581  //
 27582  // The present implementation tries to accommodate as many variations as possible,
 27583  // so it makes few assumptions. If integers having the subrange
 27584  // `|min_quarterword..max_quarterword|' can be packed into a quarterword,
 27585  // and if integers having the subrange `|min_halfword..max_halfword|'
 27586  // can be packed into a halfword, everything should work satisfactorily.
 27587  //
 27588  // It is usually most efficient to have |min_quarterword=min_halfword=0|,
 27589  // so one should try to achieve this unless it causes a severe problem.
 27590  // The values defined here are recommended for most 32-bit computers.
 27591  
 27592  // 155.
 27593  
 27594  // tangle:pos ../../mf.web:3169:3:
 27595  
 27596  // The operation of subtracting |min_halfword| occurs rather frequently in
 27597  // \MF, so it is convenient to abbreviate this operation by using the macro
 27598  // |ho| defined here.  \MF\ will run faster with respect to compilers that
 27599  // don't optimize the expression `|x-0|', if this macro is simplified in the
 27600  // obvious way when |min_halfword=0|. Similarly, |qi| and |qo| are used for
 27601  // input to and output from quarterwords.
 27602  // \xref[system dependencies]
 27603  
 27604  // 157.
 27605  
 27606  // tangle:pos ../../mf.web:3212:3:
 27607  
 27608  // When debugging, we may want to print a |memory_word| without knowing
 27609  // what type it is; so we print it in all modes.
 27610  // \xref[dirty \PASCAL]\xref[debugging]
 27611  //  procedure print_word( w:memory_word);
 27612  //   [prints |w| in all ways]
 27613  // begin print_int(w.int); print_char([" "=]32);
 27614  //
 27615  // print_scaled(w.int ); print_char([" "=]32); print_scaled(w.int  div [010000=]4096); print_ln;
 27616  //
 27617  // print_int(w.hh.lh); print_char(["="=]61); print_int(w.hh.b0); print_char([":"=]58);
 27618  // print_int(w.hh.b1); print_char([";"=]59); print_int(w.hh.rh); print_char([" "=]32);
 27619  //
 27620  // print_int(w.qqqq.b0); print_char([":"=]58); print_int(w.qqqq.b1); print_char([":"=]58);
 27621  // print_int(w.qqqq.b2); print_char([":"=]58); print_int(w.qqqq.b3);
 27622  // end;
 27623  // [  ]
 27624  
 27625  // 158. \[10] Dynamic memory allocation
 27626  
 27627  // tangle:pos ../../mf.web:3227:36:
 27628  
 27629  // The \MF\ system does nearly all of its own memory allocation, so that it
 27630  // can readily be transported into environments that do not have automatic
 27631  // facilities for strings, garbage collection, etc., and so that it can be in
 27632  // control of what error messages the user receives. The dynamic storage
 27633  // requirements of \MF\ are handled by providing a large array |mem| in
 27634  // which consecutive blocks of words are used as nodes by the \MF\ routines.
 27635  //
 27636  // Pointer variables are indices into this array, or into another array
 27637  // called |eqtb| that will be explained later. A pointer variable might
 27638  // also be a special flag that lies outside the bounds of |mem|, so we
 27639  // allow pointers to assume any |halfword| value. The minimum memory
 27640  // index represents a null pointer.
 27641  
 27642  // 162.
 27643  
 27644  // tangle:pos ../../mf.web:3297:3:
 27645  
 27646  // If one-word memory is exhausted, it might mean that the user has forgotten
 27647  // a token like `\&[enddef]' or `\&[endfor]'. We will define some procedures
 27648  // later that try to help pinpoint the trouble.
 27649  // \4
 27650  // Declare the procedure called |show_token_list|
 27651  func (prg *prg) printCapsule() {
 27652  	prg.printChar(asciiCode('('))
 27653  	prg.printExp(prg.gPointer, smallNumber(0))
 27654  	prg.printChar(asciiCode(')'))
 27655  }
 27656  
 27657  // 216.
 27658  
 27659  // tangle:pos ../../mf.web:4772:3:
 27660  
 27661  // A token list is a singly linked list of nodes in |mem|, where
 27662  // each node contains a token and a link.  Here's a subroutine that gets rid
 27663  // of a token list when it is no longer needed.
 27664  func (prg *prg) tokenRecycle() {
 27665  	prg.recycleValue(prg.gPointer)
 27666  } // \2
 27667  
 27668  func (prg *prg) closeFilesAndTerminate() {
 27669  	var (
 27670  		k                           int32    // all-purpose index
 27671  		lh                          int32    // the length of the \.[TFM] header, in words
 27672  		lkOffset/* 0..256 */ uint16          // extra words inserted at beginning of |lig_kern| array
 27673  		p                           halfword // runs through a list of \.[TFM] dimensions
 27674  		x                           scaled   // a |tfm_width| value being output to the \.[GF] file
 27675  	)
 27676  	if prg.internal[tracingStats-1] > 0 {
 27677  		if prg.logOpened {
 27678  			prg.logFile.Writeln(" ")
 27679  			prg.logFile.Writeln("Here is how much of METAFONT's memory", " you used:")
 27680  			// \xref[Here is how much...]
 27681  			prg.logFile.Write(" ", int32(prg.maxStrPtr)-int32(prg.initStrPtr), knuth.WriteWidth(1), " string")
 27682  			if int32(prg.maxStrPtr) != int32(prg.initStrPtr)+1 {
 27683  				prg.logFile.Write("s")
 27684  			}
 27685  			prg.logFile.Writeln(" out of ", maxStrings-int32(prg.initStrPtr), knuth.WriteWidth(1))
 27686  
 27687  			prg.logFile.Writeln(" ", int32(prg.maxPoolPtr)-int32(prg.initPoolPtr), knuth.WriteWidth(1), " string characters out of ", poolSize-int32(prg.initPoolPtr), knuth.WriteWidth(1))
 27688  
 27689  			prg.logFile.Writeln(" ", int32(prg.loMemMax)-memMin+int32(prg.memEnd)-int32(prg.hiMemMin)+2, knuth.WriteWidth(1),
 27690  				" words of memory out of ", int32(prg.memEnd)+1-memMin, knuth.WriteWidth(1))
 27691  
 27692  			prg.logFile.Writeln(" ", prg.stCount, knuth.WriteWidth(1), " symbolic tokens out of ", hashSize, knuth.WriteWidth(1))
 27693  
 27694  			prg.logFile.Writeln(" ", prg.maxInStack, knuth.WriteWidth(1), "i,", prg.intPtr, knuth.WriteWidth(1), "n,", prg.maxRoundingPtr, knuth.WriteWidth(1), "r,", prg.maxParamStack, knuth.WriteWidth(1), "p,", int32(prg.maxBufStack)+1, knuth.WriteWidth(1), "b stack positions out of ", stackSize, knuth.WriteWidth(1), "i,", maxInternal, knuth.WriteWidth(1), "n,", maxWiggle, knuth.WriteWidth(1), "r,", paramSize, knuth.WriteWidth(1), "p,", bufSize, knuth.WriteWidth(1), "b")
 27695  		}
 27696  	}
 27697  
 27698  	// Finish the \.[TFM] and \.[GF] files
 27699  	if prg.gfPrevPtr > 0 || prg.internal[fontmaking-1] > 0 {
 27700  		prg.rover = uint16(memMin + 3 + 10 + 2 + 2 + 2 + 2 + 1 + 1)
 27701  		*(*prg.mem[prg.rover].hh()).rh() = 65535
 27702  		prg.loMemMax = uint16(int32(prg.hiMemMin) - 1)
 27703  		if int32(prg.loMemMax)-int32(prg.rover) > 65535 {
 27704  			prg.loMemMax = uint16(65535 + int32(prg.rover))
 27705  		}
 27706  		*(*prg.mem[prg.rover].hh()).lh() = uint16(int32(prg.loMemMax) - int32(prg.rover))
 27707  		*(*prg.mem[int32(prg.rover)+1].hh()).lh() = prg.rover
 27708  		*(*prg.mem[int32(prg.rover)+1].hh()).rh() = prg.rover
 27709  		*(*prg.mem[prg.loMemMax].hh()).rh() = uint16(memMin)
 27710  		*(*prg.mem[prg.loMemMax].hh()).lh() = uint16(memMin)
 27711  
 27712  		// Massage the \.[TFM] widths
 27713  		*(*prg.mem[3000-1].hh()).rh() = uint16(memMin + 3 + 10 + 2 + 2 + 2)
 27714  		for ii := int32(prg.bc); ii <= int32(prg.ec); ii++ {
 27715  			k = ii
 27716  			_ = k
 27717  			if prg.charExists[k] {
 27718  				prg.tfmWidth[k] = int32(prg.sortIn(prg.tfmWidth[k]))
 27719  			}
 27720  		}
 27721  		prg.nw = uint16(prg.skimp(255) + 1)
 27722  		prg.dimenHead[1-1] = *(*prg.mem[3000-1].hh()).rh()
 27723  		if prg.perturbation >= 010000 {
 27724  			prg.tfmWarning(smallNumber(charWd))
 27725  		}
 27726  		prg.fixDesignSize()
 27727  		prg.fixCheckSum()
 27728  		if prg.internal[fontmaking-1] > 0 {
 27729  			*(*prg.mem[3000-1].hh()).rh() = uint16(memMin + 3 + 10 + 2 + 2 + 2)
 27730  			for ii := int32(prg.bc); ii <= int32(prg.ec); ii++ {
 27731  				k = ii
 27732  				_ = k
 27733  				if prg.charExists[k] {
 27734  					if prg.tfmHeight[k] == 0 {
 27735  						prg.tfmHeight[k] = memMin + 3 + 10 + 2
 27736  					} else {
 27737  						prg.tfmHeight[k] = int32(prg.sortIn(prg.tfmHeight[k]))
 27738  					}
 27739  				}
 27740  			}
 27741  			prg.nh = uint16(prg.skimp(15) + 1)
 27742  			prg.dimenHead[2-1] = *(*prg.mem[3000-1].hh()).rh()
 27743  			if prg.perturbation >= 010000 {
 27744  				prg.tfmWarning(smallNumber(charHt))
 27745  			}
 27746  			*(*prg.mem[3000-1].hh()).rh() = uint16(memMin + 3 + 10 + 2 + 2 + 2)
 27747  			for ii := int32(prg.bc); ii <= int32(prg.ec); ii++ {
 27748  				k = ii
 27749  				_ = k
 27750  				if prg.charExists[k] {
 27751  					if prg.tfmDepth[k] == 0 {
 27752  						prg.tfmDepth[k] = memMin + 3 + 10 + 2
 27753  					} else {
 27754  						prg.tfmDepth[k] = int32(prg.sortIn(prg.tfmDepth[k]))
 27755  					}
 27756  				}
 27757  			}
 27758  			prg.nd = uint16(prg.skimp(15) + 1)
 27759  			prg.dimenHead[3-1] = *(*prg.mem[3000-1].hh()).rh()
 27760  			if prg.perturbation >= 010000 {
 27761  				prg.tfmWarning(smallNumber(charDp))
 27762  			}
 27763  			*(*prg.mem[3000-1].hh()).rh() = uint16(memMin + 3 + 10 + 2 + 2 + 2)
 27764  			for ii := int32(prg.bc); ii <= int32(prg.ec); ii++ {
 27765  				k = ii
 27766  				_ = k
 27767  				if prg.charExists[k] {
 27768  					if prg.tfmItalCorr[k] == 0 {
 27769  						prg.tfmItalCorr[k] = memMin + 3 + 10 + 2
 27770  					} else {
 27771  						prg.tfmItalCorr[k] = int32(prg.sortIn(prg.tfmItalCorr[k]))
 27772  					}
 27773  				}
 27774  			}
 27775  			prg.ni = uint16(prg.skimp(63) + 1)
 27776  			prg.dimenHead[4-1] = *(*prg.mem[3000-1].hh()).rh()
 27777  			if prg.perturbation >= 010000 {
 27778  				prg.tfmWarning(smallNumber(charIc))
 27779  			}
 27780  			prg.internal[fontmaking-1] = 0 // avoid loop in case of fatal error
 27781  
 27782  			// Finish the \.[TFM] file
 27783  			if int32(prg.jobName) == 0 {
 27784  				prg.openLogFile()
 27785  			}
 27786  			prg.packJobName(strNumber( /* ".tfm" */ 1045))
 27787  			for !prg.bOpenOut(prg.tfmFile) {
 27788  				prg.promptFileName(strNumber( /* "file name for font metrics" */ 1046), strNumber( /* ".tfm" */ 1045))
 27789  			}
 27790  			prg.metricFileName = prg.bMakeNameString(prg.tfmFile)
 27791  
 27792  			// Output the subfile sizes and header bytes
 27793  			k = headerSize
 27794  			for int32(prg.headerByte[k-1]) < 0 {
 27795  				k = k - 1
 27796  			}
 27797  			lh = (k + 3) / 4 // this is the number of header words
 27798  			if int32(prg.bc) > int32(prg.ec) {
 27799  				prg.bc = 1
 27800  			} // if there are no characters, |ec=0| and |bc=1|
 27801  
 27802  			// Compute the ligature/kern program offset and implant the left boundary label
 27803  			prg.bchar = prg.roundUnscaled(prg.internal[boundaryChar-1])
 27804  			if prg.bchar < 0 || prg.bchar > 255 {
 27805  				prg.bchar = -1
 27806  				prg.lkStarted = false
 27807  				lkOffset = 0
 27808  			} else {
 27809  				prg.lkStarted = true
 27810  				lkOffset = 1
 27811  			}
 27812  
 27813  			// Find the minimum |lk_offset| and adjust all remainders
 27814  			k = int32(prg.labelPtr) // pointer to the largest unallocated label
 27815  			if int32(prg.labelLoc[k])+int32(lkOffset) > 255 {
 27816  				lkOffset = 0
 27817  				prg.lkStarted = false // location 0 can do double duty
 27818  				for {
 27819  					prg.charRemainder[prg.labelChar[k-1]] = lkOffset
 27820  					for int32(prg.labelLoc[k-1]) == int32(prg.labelLoc[k]) {
 27821  						k = k - 1
 27822  						prg.charRemainder[prg.labelChar[k-1]] = lkOffset
 27823  					}
 27824  					lkOffset = uint16(int32(lkOffset) + 1)
 27825  					k = k - 1
 27826  					if int32(lkOffset)+int32(prg.labelLoc[k]) < 256 {
 27827  						break
 27828  					}
 27829  				}
 27830  				// N.B.: |lk_offset=256| satisfies this when |k=0|
 27831  			}
 27832  			if int32(lkOffset) > 0 {
 27833  				for k > 0 {
 27834  					prg.charRemainder[prg.labelChar[k-1]] = uint16(int32(prg.charRemainder[prg.labelChar[k-1]]) + int32(lkOffset))
 27835  					k = k - 1
 27836  				}
 27837  			}
 27838  			if int32(prg.bchLabel) < ligTableSize {
 27839  				prg.ligKern[prg.nl].b0 = byte(255 + minQuarterword)
 27840  				prg.ligKern[prg.nl].b1 = byte(0 + minQuarterword)
 27841  				prg.ligKern[prg.nl].b2 = byte((int32(prg.bchLabel)+int32(lkOffset))/256 + minQuarterword)
 27842  				prg.ligKern[prg.nl].b3 = byte((int32(prg.bchLabel)+int32(lkOffset))%256 + minQuarterword)
 27843  				prg.nl = uint16(int32(prg.nl) + 1) // possibly |nl=lig_table_size+1|
 27844  			}
 27845  			prg.tfmTwo(6 + lh + (int32(prg.ec) - int32(prg.bc) + 1) + int32(prg.nw) + int32(prg.nh) + int32(prg.nd) + int32(prg.ni) + int32(prg.nl) + int32(lkOffset) + int32(prg.nk) + int32(prg.ne) + int32(prg.np))
 27846  			// this is the total number of file words that will be output
 27847  			prg.tfmTwo(lh)
 27848  			prg.tfmTwo(int32(prg.bc))
 27849  			prg.tfmTwo(int32(prg.ec))
 27850  			prg.tfmTwo(int32(prg.nw))
 27851  			prg.tfmTwo(int32(prg.nh))
 27852  			prg.tfmTwo(int32(prg.nd))
 27853  			prg.tfmTwo(int32(prg.ni))
 27854  			prg.tfmTwo(int32(prg.nl) + int32(lkOffset))
 27855  			prg.tfmTwo(int32(prg.nk))
 27856  			prg.tfmTwo(int32(prg.ne))
 27857  			prg.tfmTwo(int32(prg.np))
 27858  			for ii := int32(1); ii <= 4*lh; ii++ {
 27859  				k = ii
 27860  				_ = k
 27861  				if int32(prg.headerByte[k-1]) < 0 {
 27862  					prg.headerByte[k-1] = 0
 27863  				}
 27864  				prg.tfmFile.Write(prg.headerByte[k-1])
 27865  			}
 27866  
 27867  			// Output the character information bytes, then output the dimensions themselves
 27868  			for ii := int32(prg.bc); ii <= int32(prg.ec); ii++ {
 27869  				k = ii
 27870  				_ = k
 27871  				if !prg.charExists[k] {
 27872  					prg.tfmFour(0)
 27873  				} else {
 27874  					prg.tfmFile.Write(*(*prg.mem[prg.tfmWidth[k]].hh()).lh()) // the width index
 27875  					prg.tfmFile.Write(int32(*(*prg.mem[prg.tfmHeight[k]].hh()).lh())*16 + int32(*(*prg.mem[prg.tfmDepth[k]].hh()).lh()))
 27876  					prg.tfmFile.Write(int32(*(*prg.mem[prg.tfmItalCorr[k]].hh()).lh())*4 + int32(prg.charTag[k]))
 27877  					prg.tfmFile.Write(prg.charRemainder[k])
 27878  				}
 27879  			}
 27880  			prg.tfmChanged = 0
 27881  			for ii := int32(1); ii <= 4; ii++ {
 27882  				k = ii
 27883  				_ = k
 27884  				prg.tfmFour(0)
 27885  				p = prg.dimenHead[k-1]
 27886  				for int32(p) != memMin+3+10+2+2+2 {
 27887  					prg.tfmFour(prg.dimenOut(*prg.mem[int32(p)+1].int()))
 27888  					p = *(*prg.mem[p].hh()).rh()
 27889  				}
 27890  			}
 27891  
 27892  			// Output the ligature/kern program
 27893  			for ii := int32(0); ii <= 255; ii++ {
 27894  				k = ii
 27895  				_ = k
 27896  				if int32(prg.skipTable[k]) < ligTableSize {
 27897  					prg.printNl(strNumber( /* "(local label " */ 1048))
 27898  					prg.printInt(k)
 27899  					prg.print( /* ":: was missing)" */ 1049)
 27900  					// \xref[local label l:: was missing]
 27901  					prg.ll = prg.skipTable[k]
 27902  					for {
 27903  						prg.lll = uint16(int32(prg.ligKern[prg.ll].b0) - minQuarterword)
 27904  						prg.ligKern[prg.ll].b0 = byte(stopFlag)
 27905  						prg.ll = uint16(int32(prg.ll) - int32(prg.lll))
 27906  						if int32(prg.lll) == 0 {
 27907  							break
 27908  						}
 27909  					}
 27910  				}
 27911  			}
 27912  			if prg.lkStarted {
 27913  				prg.tfmFile.Write(255)
 27914  				prg.tfmFile.Write(prg.bchar)
 27915  				prg.tfmTwo(0)
 27916  			} else {
 27917  				for ii := int32(1); ii <= int32(lkOffset); ii++ {
 27918  					k = ii
 27919  					_ = k // output the redirection specs
 27920  					prg.ll = uint16(prg.labelLoc[prg.labelPtr])
 27921  					if prg.bchar < 0 {
 27922  						prg.tfmFile.Write(254)
 27923  						prg.tfmFile.Write(0)
 27924  					} else {
 27925  						prg.tfmFile.Write(255)
 27926  						prg.tfmFile.Write(prg.bchar)
 27927  					}
 27928  					prg.tfmTwo(int32(prg.ll) + int32(lkOffset))
 27929  					for {
 27930  						prg.labelPtr = uint16(int32(prg.labelPtr) - 1)
 27931  						if int32(prg.labelLoc[prg.labelPtr]) < int32(prg.ll) {
 27932  							break
 27933  						}
 27934  					}
 27935  				}
 27936  			}
 27937  			for ii := int32(0); ii <= int32(prg.nl)-1; ii++ {
 27938  				k = ii
 27939  				_ = k
 27940  				prg.tfmQqqq(prg.ligKern[k])
 27941  			}
 27942  			for ii := int32(0); ii <= int32(prg.nk)-1; ii++ {
 27943  				k = ii
 27944  				_ = k
 27945  				prg.tfmFour(prg.dimenOut(prg.kern[k]))
 27946  			}
 27947  
 27948  			// Output the extensible character recipes and the font metric parameters
 27949  			for ii := int32(0); ii <= int32(prg.ne)-1; ii++ {
 27950  				k = ii
 27951  				_ = k
 27952  				prg.tfmQqqq(prg.exten[k])
 27953  			}
 27954  			for ii := int32(1); ii <= int32(prg.np); ii++ {
 27955  				k = ii
 27956  				_ = k
 27957  				if k == 1 {
 27958  					if abs(prg.param[1-1]) < 01000000000 {
 27959  						prg.tfmFour(prg.param[1-1] * 16)
 27960  					} else {
 27961  						prg.tfmChanged = prg.tfmChanged + 1
 27962  						if prg.param[1-1] > 0 {
 27963  							prg.tfmFour(017777777777)
 27964  						} else {
 27965  							prg.tfmFour(-017777777777)
 27966  						}
 27967  					}
 27968  				} else {
 27969  					prg.tfmFour(prg.dimenOut(prg.param[k-1]))
 27970  				}
 27971  			}
 27972  			if prg.tfmChanged > 0 {
 27973  				if prg.tfmChanged == 1 {
 27974  					prg.printNl(strNumber( /* "(a font metric dimension" */ 1050))
 27975  				} else {
 27976  					prg.printNl(strNumber('('))
 27977  					prg.printInt(prg.tfmChanged)
 27978  					// \xref[font metric dimensions...]
 27979  					prg.print( /* " font metric dimensions" */ 1051)
 27980  				}
 27981  				prg.print( /* " had to be decreased)" */ 1052)
 27982  			}
 27983  			if prg.internal[tracingStats-1] > 0 {
 27984  				prg.logFile.Writeln(" ")
 27985  				if int32(prg.bchLabel) < ligTableSize {
 27986  					prg.nl = uint16(int32(prg.nl) - 1)
 27987  				}
 27988  				prg.logFile.Writeln("(You used ", prg.nw, knuth.WriteWidth(1), "w,", prg.nh, knuth.WriteWidth(1), "h,", prg.nd, knuth.WriteWidth(1), "d,", prg.ni, knuth.WriteWidth(1), "i,", prg.nl, knuth.WriteWidth(1), "l,", prg.nk, knuth.WriteWidth(1), "k,", prg.ne, knuth.WriteWidth(1), "e,", prg.np, knuth.WriteWidth(1), "p metric file positions")
 27989  				prg.logFile.Writeln("  out of ", "256w,16h,16d,64i,", ligTableSize, knuth.WriteWidth(1), "l,", maxKerns, knuth.WriteWidth(1), "k,256e,", maxFontDimen, knuth.WriteWidth(1), "p)")
 27990  			}
 27991  
 27992  			prg.printNl(strNumber( /* "Font metrics written on " */ 1047))
 27993  			prg.slowPrint(int32(prg.metricFileName))
 27994  			prg.printChar(asciiCode('.'))
 27995  			// \xref[Font metrics written...]
 27996  			prg.bClose(prg.tfmFile)
 27997  		}
 27998  		if prg.gfPrevPtr > 0 {
 27999  			{
 28000  				prg.gfBuf[prg.gfPtr] = byte(post)
 28001  				prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 28002  				if int32(prg.gfPtr) == int32(prg.gfLimit) {
 28003  					prg.gfSwap()
 28004  				}
 28005  			} // beginning of the postamble
 28006  			prg.gfFour(prg.gfPrevPtr)
 28007  			prg.gfPrevPtr = prg.gfOffset + int32(prg.gfPtr) - 5 // |post| location
 28008  			prg.gfFour(prg.internal[designSize-1] * 16)
 28009  			for ii := int32(1); ii <= 4; ii++ {
 28010  				k = ii
 28011  				_ = k
 28012  				prg.gfBuf[prg.gfPtr] = byte(prg.headerByte[k-1])
 28013  				prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 28014  				if int32(prg.gfPtr) == int32(prg.gfLimit) {
 28015  					prg.gfSwap()
 28016  				}
 28017  			} // the check sum
 28018  			prg.gfFour(prg.internal[hppp-1])
 28019  			prg.gfFour(prg.internal[vppp-1])
 28020  
 28021  			prg.gfFour(prg.gfMinM)
 28022  			prg.gfFour(prg.gfMaxM)
 28023  			prg.gfFour(prg.gfMinN)
 28024  			prg.gfFour(prg.gfMaxN)
 28025  			for ii := int32(0); ii <= 255; ii++ {
 28026  				k = ii
 28027  				_ = k
 28028  				if prg.charExists[k] {
 28029  					x = prg.gfDx[k] / 0200000
 28030  					if prg.gfDy[k] == 0 && x >= 0 && x < 256 && prg.gfDx[k] == x*0200000 {
 28031  						{
 28032  							prg.gfBuf[prg.gfPtr] = byte(charLoc + 1)
 28033  							prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 28034  							if int32(prg.gfPtr) == int32(prg.gfLimit) {
 28035  								prg.gfSwap()
 28036  							}
 28037  						}
 28038  						{
 28039  							prg.gfBuf[prg.gfPtr] = byte(k)
 28040  							prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 28041  							if int32(prg.gfPtr) == int32(prg.gfLimit) {
 28042  								prg.gfSwap()
 28043  							}
 28044  						}
 28045  						{
 28046  							prg.gfBuf[prg.gfPtr] = byte(x)
 28047  							prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 28048  							if int32(prg.gfPtr) == int32(prg.gfLimit) {
 28049  								prg.gfSwap()
 28050  							}
 28051  						}
 28052  					} else {
 28053  						{
 28054  							prg.gfBuf[prg.gfPtr] = byte(charLoc)
 28055  							prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 28056  							if int32(prg.gfPtr) == int32(prg.gfLimit) {
 28057  								prg.gfSwap()
 28058  							}
 28059  						}
 28060  						{
 28061  							prg.gfBuf[prg.gfPtr] = byte(k)
 28062  							prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 28063  							if int32(prg.gfPtr) == int32(prg.gfLimit) {
 28064  								prg.gfSwap()
 28065  							}
 28066  						}
 28067  						prg.gfFour(prg.gfDx[k])
 28068  						prg.gfFour(prg.gfDy[k])
 28069  					}
 28070  					x = *prg.mem[prg.tfmWidth[k]+1].int()
 28071  					if abs(x) > prg.maxTfmDimen {
 28072  						if x > 0 {
 28073  							x = 0100000000 - 1
 28074  						} else {
 28075  							x = 1 - 0100000000
 28076  						}
 28077  					} else {
 28078  						x = prg.makeScaled(x*16, prg.internal[designSize-1])
 28079  					}
 28080  					prg.gfFour(x)
 28081  					prg.gfFour(prg.charPtr[k])
 28082  				}
 28083  			}
 28084  			{
 28085  				prg.gfBuf[prg.gfPtr] = byte(postPost)
 28086  				prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 28087  				if int32(prg.gfPtr) == int32(prg.gfLimit) {
 28088  					prg.gfSwap()
 28089  				}
 28090  			}
 28091  			prg.gfFour(prg.gfPrevPtr)
 28092  			{
 28093  				prg.gfBuf[prg.gfPtr] = byte(gfIdByte)
 28094  				prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 28095  				if int32(prg.gfPtr) == int32(prg.gfLimit) {
 28096  					prg.gfSwap()
 28097  				}
 28098  			}
 28099  
 28100  			k = 4 + (gfBufSize-int32(prg.gfPtr))%4 // the number of 223's
 28101  			for k > 0 {
 28102  				{
 28103  					prg.gfBuf[prg.gfPtr] = 223
 28104  					prg.gfPtr = byte(int32(prg.gfPtr) + 1)
 28105  					if int32(prg.gfPtr) == int32(prg.gfLimit) {
 28106  						prg.gfSwap()
 28107  					}
 28108  				}
 28109  				k = k - 1
 28110  			}
 28111  
 28112  			// Empty the last bytes out of |gf_buf|
 28113  			if int32(prg.gfLimit) == int32(prg.halfBuf) {
 28114  				prg.writeGf(prg.halfBuf, gfIndex(gfBufSize-1))
 28115  			}
 28116  			if int32(prg.gfPtr) > 0 {
 28117  				prg.writeGf(gfIndex(0), gfIndex(int32(prg.gfPtr)-1))
 28118  			}
 28119  			prg.printNl(strNumber( /* "Output written on " */ 1063))
 28120  			prg.slowPrint(int32(prg.outputFileName))
 28121  			// \xref[Output written...]
 28122  			prg.print( /* " (" */ 558)
 28123  			prg.printInt(prg.totalChars)
 28124  			prg.print( /* " character" */ 1064)
 28125  			if prg.totalChars != 1 {
 28126  				prg.printChar(asciiCode('s'))
 28127  			}
 28128  			prg.print( /* ", " */ 1065)
 28129  			prg.printInt(prg.gfOffset + int32(prg.gfPtr))
 28130  			prg.print( /* " bytes)." */ 1066)
 28131  			prg.bClose(prg.gfFile)
 28132  		}
 28133  	}
 28134  	if prg.logOpened {
 28135  		prg.logFile.Writeln()
 28136  		prg.aClose(prg.logFile)
 28137  		prg.selector = byte(int32(prg.selector) - 2)
 28138  		if int32(prg.selector) == termOnly {
 28139  			prg.printNl(strNumber( /* "Transcript written on " */ 1074))
 28140  			// \xref[Transcript written...]
 28141  			prg.slowPrint(int32(prg.logName))
 28142  			prg.printChar(asciiCode('.'))
 28143  		}
 28144  	}
 28145  	prg.termOut.Writeln()
 28146  }
 28147  
 28148  func (prg *prg) finalCleanup() {
 28149  	var (
 28150  		c smallNumber // 0 for \&[end], 1 for \&[dump]
 28151  	)
 28152  	c = byte(prg.curMod)
 28153  	if int32(prg.jobName) == 0 {
 28154  		prg.openLogFile()
 28155  	}
 28156  	for int32(prg.inputPtr) > 0 {
 28157  		if int32(prg.curInput.indexField) > maxInOpen {
 28158  			prg.endTokenList()
 28159  		} else {
 28160  			prg.endFileReading()
 28161  		}
 28162  	}
 28163  	for int32(prg.loopPtr) != memMin {
 28164  		prg.stopIteration()
 28165  	}
 28166  	for int32(prg.openParens) > 0 {
 28167  		prg.print( /* " )" */ 1075)
 28168  		prg.openParens = byte(int32(prg.openParens) - 1)
 28169  	}
 28170  	for int32(prg.condPtr) != memMin {
 28171  		prg.printNl(strNumber( /* "(end occurred when " */ 1076))
 28172  
 28173  		// \xref[end occurred...]
 28174  		prg.printCmdMod(fiOrElse, int32(prg.curIf))
 28175  		// `\.[if]' or `\.[elseif]' or `\.[else]'
 28176  		if prg.ifLine != 0 {
 28177  			prg.print( /* " on line " */ 1077)
 28178  			prg.printInt(prg.ifLine)
 28179  		}
 28180  		prg.print( /* " was incomplete)" */ 1078)
 28181  		prg.ifLine = *prg.mem[int32(prg.condPtr)+1].int()
 28182  		prg.curIf = *(*prg.mem[prg.condPtr].hh()).b1()
 28183  		prg.loopPtr = prg.condPtr
 28184  		prg.condPtr = *(*prg.mem[prg.condPtr].hh()).rh()
 28185  		prg.freeNode(prg.loopPtr, halfword(ifNodeSize))
 28186  	}
 28187  	if int32(prg.history) != spotless {
 28188  		if int32(prg.history) == warningIssued || int32(prg.interaction) < errorStopMode {
 28189  			if int32(prg.selector) == termAndLog {
 28190  				prg.selector = byte(termOnly)
 28191  				prg.printNl(strNumber( /* "(see the transcript file for additional information)" */ 1079))
 28192  				// \xref[see the transcript file...]
 28193  				prg.selector = byte(termAndLog)
 28194  			}
 28195  		}
 28196  	}
 28197  	if int32(c) == 1 {
 28198  		prg.storeBaseFile()
 28199  		goto exit
 28200  
 28201  		prg.printNl(strNumber( /* "(dump is performed only by INIMF)" */ 1080))
 28202  		goto exit
 28203  		// \xref[dump...only by INIMF]
 28204  	}
 28205  
 28206  exit:
 28207  }
 28208  
 28209  func (prg *prg) initPrim() {
 28210  	prg.primitive(strNumber( /* "tracingtitles" */ 410), halfword(internalQuantity), halfword(tracingTitles))
 28211  
 28212  	// \xref[tracingtitles_][\&[tracingtitles] primitive]
 28213  	prg.primitive(strNumber( /* "tracingequations" */ 411), halfword(internalQuantity), halfword(tracingEquations))
 28214  
 28215  	// \xref[tracing_equations_][\&[tracingequations] primitive]
 28216  	prg.primitive(strNumber( /* "tracingcapsules" */ 412), halfword(internalQuantity), halfword(tracingCapsules))
 28217  
 28218  	// \xref[tracing_capsules_][\&[tracingcapsules] primitive]
 28219  	prg.primitive(strNumber( /* "tracingchoices" */ 413), halfword(internalQuantity), halfword(tracingChoices))
 28220  
 28221  	// \xref[tracing_choices_][\&[tracingchoices] primitive]
 28222  	prg.primitive(strNumber( /* "tracingspecs" */ 414), halfword(internalQuantity), halfword(tracingSpecs))
 28223  
 28224  	// \xref[tracing_specs_][\&[tracingspecs] primitive]
 28225  	prg.primitive(strNumber( /* "tracingpens" */ 415), halfword(internalQuantity), halfword(tracingPens))
 28226  
 28227  	// \xref[tracing_pens_][\&[tracingpens] primitive]
 28228  	prg.primitive(strNumber( /* "tracingcommands" */ 416), halfword(internalQuantity), halfword(tracingCommands))
 28229  
 28230  	// \xref[tracing_commands_][\&[tracingcommands] primitive]
 28231  	prg.primitive(strNumber( /* "tracingrestores" */ 417), halfword(internalQuantity), halfword(tracingRestores))
 28232  
 28233  	// \xref[tracing_restores_][\&[tracingrestores] primitive]
 28234  	prg.primitive(strNumber( /* "tracingmacros" */ 418), halfword(internalQuantity), halfword(tracingMacros))
 28235  
 28236  	// \xref[tracing_macros_][\&[tracingmacros] primitive]
 28237  	prg.primitive(strNumber( /* "tracingedges" */ 419), halfword(internalQuantity), halfword(tracingEdges))
 28238  
 28239  	// \xref[tracing_edges_][\&[tracingedges] primitive]
 28240  	prg.primitive(strNumber( /* "tracingoutput" */ 420), halfword(internalQuantity), halfword(tracingOutput))
 28241  
 28242  	// \xref[tracing_output_][\&[tracingoutput] primitive]
 28243  	prg.primitive(strNumber( /* "tracingstats" */ 421), halfword(internalQuantity), halfword(tracingStats))
 28244  
 28245  	// \xref[tracing_stats_][\&[tracingstats] primitive]
 28246  	prg.primitive(strNumber( /* "tracingonline" */ 422), halfword(internalQuantity), halfword(tracingOnline))
 28247  
 28248  	// \xref[tracing_online_][\&[tracingonline] primitive]
 28249  	prg.primitive(strNumber( /* "year" */ 423), halfword(internalQuantity), halfword(year))
 28250  
 28251  	// \xref[year_][\&[year] primitive]
 28252  	prg.primitive(strNumber( /* "month" */ 424), halfword(internalQuantity), halfword(month))
 28253  
 28254  	// \xref[month_][\&[month] primitive]
 28255  	prg.primitive(strNumber( /* "day" */ 425), halfword(internalQuantity), halfword(day))
 28256  
 28257  	// \xref[day_][\&[day] primitive]
 28258  	prg.primitive(strNumber( /* "time" */ 426), halfword(internalQuantity), halfword(time))
 28259  
 28260  	// \xref[time_][\&[time] primitive]
 28261  	prg.primitive(strNumber( /* "charcode" */ 427), halfword(internalQuantity), halfword(charCode))
 28262  
 28263  	// \xref[char_code_][\&[charcode] primitive]
 28264  	prg.primitive(strNumber( /* "charext" */ 428), halfword(internalQuantity), halfword(charExt))
 28265  
 28266  	// \xref[char_ext_][\&[charext] primitive]
 28267  	prg.primitive(strNumber( /* "charwd" */ 429), halfword(internalQuantity), halfword(charWd))
 28268  
 28269  	// \xref[char_wd_][\&[charwd] primitive]
 28270  	prg.primitive(strNumber( /* "charht" */ 430), halfword(internalQuantity), halfword(charHt))
 28271  
 28272  	// \xref[char_ht_][\&[charht] primitive]
 28273  	prg.primitive(strNumber( /* "chardp" */ 431), halfword(internalQuantity), halfword(charDp))
 28274  
 28275  	// \xref[char_dp_][\&[chardp] primitive]
 28276  	prg.primitive(strNumber( /* "charic" */ 432), halfword(internalQuantity), halfword(charIc))
 28277  
 28278  	// \xref[char_ic_][\&[charic] primitive]
 28279  	prg.primitive(strNumber( /* "chardx" */ 433), halfword(internalQuantity), halfword(charDx))
 28280  
 28281  	// \xref[char_dx_][\&[chardx] primitive]
 28282  	prg.primitive(strNumber( /* "chardy" */ 434), halfword(internalQuantity), halfword(charDy))
 28283  
 28284  	// \xref[char_dy_][\&[chardy] primitive]
 28285  	prg.primitive(strNumber( /* "designsize" */ 435), halfword(internalQuantity), halfword(designSize))
 28286  
 28287  	// \xref[design_size_][\&[designsize] primitive]
 28288  	prg.primitive(strNumber( /* "hppp" */ 436), halfword(internalQuantity), halfword(hppp))
 28289  
 28290  	// \xref[hppp_][\&[hppp] primitive]
 28291  	prg.primitive(strNumber( /* "vppp" */ 437), halfword(internalQuantity), halfword(vppp))
 28292  
 28293  	// \xref[vppp_][\&[vppp] primitive]
 28294  	prg.primitive(strNumber( /* "xoffset" */ 438), halfword(internalQuantity), halfword(xOffset))
 28295  
 28296  	// \xref[x_offset_][\&[xoffset] primitive]
 28297  	prg.primitive(strNumber( /* "yoffset" */ 439), halfword(internalQuantity), halfword(yOffset))
 28298  
 28299  	// \xref[y_offset_][\&[yoffset] primitive]
 28300  	prg.primitive(strNumber( /* "pausing" */ 440), halfword(internalQuantity), halfword(pausing))
 28301  
 28302  	// \xref[pausing_][\&[pausing] primitive]
 28303  	prg.primitive(strNumber( /* "showstopping" */ 441), halfword(internalQuantity), halfword(showstopping))
 28304  
 28305  	// \xref[showstopping_][\&[showstopping] primitive]
 28306  	prg.primitive(strNumber( /* "fontmaking" */ 442), halfword(internalQuantity), halfword(fontmaking))
 28307  
 28308  	// \xref[fontmaking_][\&[fontmaking] primitive]
 28309  	prg.primitive(strNumber( /* "proofing" */ 443), halfword(internalQuantity), halfword(proofing))
 28310  
 28311  	// \xref[proofing_][\&[proofing] primitive]
 28312  	prg.primitive(strNumber( /* "smoothing" */ 444), halfword(internalQuantity), halfword(smoothing))
 28313  
 28314  	// \xref[smoothing_][\&[smoothing] primitive]
 28315  	prg.primitive(strNumber( /* "autorounding" */ 445), halfword(internalQuantity), halfword(autorounding))
 28316  
 28317  	// \xref[autorounding_][\&[autorounding] primitive]
 28318  	prg.primitive(strNumber( /* "granularity" */ 446), halfword(internalQuantity), halfword(granularity))
 28319  
 28320  	// \xref[granularity_][\&[granularity] primitive]
 28321  	prg.primitive(strNumber( /* "fillin" */ 447), halfword(internalQuantity), halfword(fillin))
 28322  
 28323  	// \xref[fillin_][\&[fillin] primitive]
 28324  	prg.primitive(strNumber( /* "turningcheck" */ 448), halfword(internalQuantity), halfword(turningCheck))
 28325  
 28326  	// \xref[turning_check_][\&[turningcheck] primitive]
 28327  	prg.primitive(strNumber( /* "warningcheck" */ 449), halfword(internalQuantity), halfword(warningCheck))
 28328  
 28329  	// \xref[warning_check_][\&[warningcheck] primitive]
 28330  	prg.primitive(strNumber( /* "boundarychar" */ 450), halfword(internalQuantity), halfword(boundaryChar))
 28331  
 28332  	// \xref[boundary_char_][\&[boundarychar] primitive]
 28333  
 28334  	prg.primitive(strNumber( /* ".." */ 409), halfword(pathJoin), halfword(0))
 28335  
 28336  	// \xref[.._][\.[..] primitive]
 28337  	prg.primitive(strNumber('['), halfword(leftBracket), halfword(0))
 28338  	prg.eqtb[hashBase+hashSize+3-1] = prg.eqtb[prg.curSym-1]
 28339  
 28340  	// \xref[[ ][\.[[] primitive]
 28341  	prg.primitive(strNumber(']'), halfword(rightBracket), halfword(0))
 28342  
 28343  	// \xref[] ][\.[]] primitive]
 28344  	prg.primitive(strNumber('}'), halfword(rightBrace), halfword(0))
 28345  
 28346  	// \xref[]]][\.[\char`\]] primitive]
 28347  	prg.primitive(strNumber('{'), halfword(leftBrace), halfword(0))
 28348  
 28349  	// \xref[][][\.[\char`\[] primitive]
 28350  	prg.primitive(strNumber(':'), halfword(colon), halfword(0))
 28351  	prg.eqtb[hashBase+hashSize+5-1] = prg.eqtb[prg.curSym-1]
 28352  
 28353  	// \xref[: ][\.[:] primitive]
 28354  	prg.primitive(strNumber( /* "::" */ 459), halfword(doubleColon), halfword(0))
 28355  
 28356  	// \xref[:: ][\.[::] primitive]
 28357  	prg.primitive(strNumber( /* "||:" */ 460), halfword(bcharLabel), halfword(0))
 28358  
 28359  	// \xref[::: ][\.[\char'174\char'174:] primitive]
 28360  	prg.primitive(strNumber( /* ":=" */ 461), halfword(assignment), halfword(0))
 28361  
 28362  	// \xref[:=_][\.[:=] primitive]
 28363  	prg.primitive(strNumber(','), halfword(comma), halfword(0))
 28364  
 28365  	// \xref[, ][\., primitive]
 28366  	prg.primitive(strNumber(';'), halfword(semicolon), halfword(0))
 28367  	prg.eqtb[hashBase+hashSize+6-1] = prg.eqtb[prg.curSym-1]
 28368  
 28369  	// \xref[; ][\.; primitive]
 28370  	prg.primitive(strNumber('\\'), halfword(relax), halfword(0))
 28371  
 28372  	// \xref[]]\\][\.[\char`\\] primitive]
 28373  
 28374  	prg.primitive(strNumber( /* "addto" */ 462), halfword(addToCommand), halfword(0))
 28375  
 28376  	// \xref[add_to_][\&[addto] primitive]
 28377  	prg.primitive(strNumber( /* "at" */ 463), halfword(atToken), halfword(0))
 28378  
 28379  	// \xref[at_][\&[at] primitive]
 28380  	prg.primitive(strNumber( /* "atleast" */ 464), halfword(atLeast), halfword(0))
 28381  
 28382  	// \xref[at_least_][\&[atleast] primitive]
 28383  	prg.primitive(strNumber( /* "begingroup" */ 465), halfword(beginGroup), halfword(0))
 28384  	prg.bgLoc = prg.curSym
 28385  
 28386  	// \xref[begin_group_][\&[begingroup] primitive]
 28387  	prg.primitive(strNumber( /* "controls" */ 466), halfword(controls), halfword(0))
 28388  
 28389  	// \xref[controls_][\&[controls] primitive]
 28390  	prg.primitive(strNumber( /* "cull" */ 467), halfword(cullCommand), halfword(0))
 28391  
 28392  	// \xref[cull_][\&[cull] primitive]
 28393  	prg.primitive(strNumber( /* "curl" */ 468), halfword(curlCommand), halfword(0))
 28394  
 28395  	// \xref[curl_][\&[curl] primitive]
 28396  	prg.primitive(strNumber( /* "delimiters" */ 469), halfword(delimiters), halfword(0))
 28397  
 28398  	// \xref[delimiters_][\&[delimiters] primitive]
 28399  	prg.primitive(strNumber( /* "display" */ 470), halfword(displayCommand), halfword(0))
 28400  
 28401  	// \xref[display_][\&[display] primitive]
 28402  	prg.primitive(strNumber( /* "endgroup" */ 453), halfword(endGroup), halfword(0))
 28403  	prg.eqtb[hashBase+hashSize+10-1] = prg.eqtb[prg.curSym-1]
 28404  	prg.egLoc = prg.curSym
 28405  
 28406  	// \xref[endgroup_][\&[endgroup] primitive]
 28407  	prg.primitive(strNumber( /* "everyjob" */ 471), halfword(everyJobCommand), halfword(0))
 28408  
 28409  	// \xref[every_job_][\&[everyjob] primitive]
 28410  	prg.primitive(strNumber( /* "exitif" */ 472), halfword(exitTest), halfword(0))
 28411  
 28412  	// \xref[exit_if_][\&[exitif] primitive]
 28413  	prg.primitive(strNumber( /* "expandafter" */ 473), halfword(expandAfter), halfword(0))
 28414  
 28415  	// \xref[expand_after_][\&[expandafter] primitive]
 28416  	prg.primitive(strNumber( /* "from" */ 474), halfword(fromToken), halfword(0))
 28417  
 28418  	// \xref[from_][\&[from] primitive]
 28419  	prg.primitive(strNumber( /* "inwindow" */ 475), halfword(inWindow), halfword(0))
 28420  
 28421  	// \xref[in_window_][\&[inwindow] primitive]
 28422  	prg.primitive(strNumber( /* "interim" */ 476), halfword(interimCommand), halfword(0))
 28423  
 28424  	// \xref[interim_][\&[interim] primitive]
 28425  	prg.primitive(strNumber( /* "let" */ 477), halfword(letCommand), halfword(0))
 28426  
 28427  	// \xref[let_][\&[let] primitive]
 28428  	prg.primitive(strNumber( /* "newinternal" */ 478), halfword(newInternal), halfword(0))
 28429  
 28430  	// \xref[new_internal_][\&[newinternal] primitive]
 28431  	prg.primitive(strNumber( /* "of" */ 479), halfword(ofToken), halfword(0))
 28432  
 28433  	// \xref[of_][\&[of] primitive]
 28434  	prg.primitive(strNumber( /* "openwindow" */ 480), halfword(openWindow), halfword(0))
 28435  
 28436  	// \xref[open_window_][\&[openwindow] primitive]
 28437  	prg.primitive(strNumber( /* "randomseed" */ 481), halfword(randomSeed), halfword(0))
 28438  
 28439  	// \xref[random_seed_][\&[randomseed] primitive]
 28440  	prg.primitive(strNumber( /* "save" */ 482), halfword(saveCommand), halfword(0))
 28441  
 28442  	// \xref[save_][\&[save] primitive]
 28443  	prg.primitive(strNumber( /* "scantokens" */ 483), halfword(scanTokens), halfword(0))
 28444  
 28445  	// \xref[scan_tokens_][\&[scantokens] primitive]
 28446  	prg.primitive(strNumber( /* "shipout" */ 484), halfword(shipOutCommand), halfword(0))
 28447  
 28448  	// \xref[ship_out_][\&[shipout] primitive]
 28449  	prg.primitive(strNumber( /* "skipto" */ 485), halfword(skipTo), halfword(0))
 28450  
 28451  	// \xref[skip_to_][\&[skipto] primitive]
 28452  	prg.primitive(strNumber( /* "step" */ 486), halfword(stepToken), halfword(0))
 28453  
 28454  	// \xref[step_][\&[step] primitive]
 28455  	prg.primitive(strNumber( /* "str" */ 487), halfword(strOp), halfword(0))
 28456  
 28457  	// \xref[str_][\&[str] primitive]
 28458  	prg.primitive(strNumber( /* "tension" */ 488), halfword(tension), halfword(0))
 28459  
 28460  	// \xref[tension_][\&[tension] primitive]
 28461  	prg.primitive(strNumber( /* "to" */ 489), halfword(toToken), halfword(0))
 28462  
 28463  	// \xref[to_][\&[to] primitive]
 28464  	prg.primitive(strNumber( /* "until" */ 490), halfword(untilToken), halfword(0))
 28465  
 28466  	// \xref[until_][\&[until] primitive]
 28467  
 28468  	prg.primitive(strNumber( /* "def" */ 654), halfword(macroDef), halfword(startDef))
 28469  
 28470  	// \xref[def_][\&[def] primitive]
 28471  	prg.primitive(strNumber( /* "vardef" */ 655), halfword(macroDef), halfword(varDef))
 28472  
 28473  	// \xref[var_def_][\&[vardef] primitive]
 28474  	prg.primitive(strNumber( /* "primarydef" */ 656), halfword(macroDef), halfword(secondaryPrimaryMacro))
 28475  
 28476  	// \xref[primary_def_][\&[primarydef] primitive]
 28477  	prg.primitive(strNumber( /* "secondarydef" */ 657), halfword(macroDef), halfword(tertiarySecondaryMacro))
 28478  
 28479  	// \xref[secondary_def_][\&[secondarydef] primitive]
 28480  	prg.primitive(strNumber( /* "tertiarydef" */ 658), halfword(macroDef), halfword(expressionTertiaryMacro))
 28481  
 28482  	// \xref[tertiary_def_][\&[tertiarydef] primitive]
 28483  	prg.primitive(strNumber( /* "enddef" */ 454), halfword(macroDef), halfword(endDef))
 28484  	prg.eqtb[hashBase+hashSize+8-1] = prg.eqtb[prg.curSym-1]
 28485  
 28486  	// \xref[end_def_][\&[enddef] primitive]
 28487  
 28488  	prg.primitive(strNumber( /* "for" */ 659), halfword(iteration), halfword(hashBase+hashSize+12+1))
 28489  
 28490  	// \xref[for_][\&[for] primitive]
 28491  	prg.primitive(strNumber( /* "forsuffixes" */ 660), halfword(iteration), halfword(hashBase+hashSize+12+1+paramSize))
 28492  
 28493  	// \xref[for_suffixes_][\&[forsuffixes] primitive]
 28494  	prg.primitive(strNumber( /* "forever" */ 661), halfword(iteration), halfword(startForever))
 28495  
 28496  	// \xref[forever_][\&[forever] primitive]
 28497  	prg.primitive(strNumber( /* "endfor" */ 455), halfword(iteration), halfword(endFor))
 28498  	prg.eqtb[hashBase+hashSize+7-1] = prg.eqtb[prg.curSym-1]
 28499  
 28500  	// \xref[end_for_][\&[endfor] primitive]
 28501  
 28502  	prg.primitive(strNumber( /* "quote" */ 662), halfword(macroSpecial), halfword(quote))
 28503  
 28504  	// \xref[quote_][\&[quote] primitive]
 28505  	prg.primitive(strNumber( /* "#@" */ 663), halfword(macroSpecial), halfword(macroPrefix))
 28506  
 28507  	// \xref[]]]\#\AT!_][\.[\#\AT!] primitive]
 28508  	prg.primitive(strNumber('@'), halfword(macroSpecial), halfword(macroAt))
 28509  
 28510  	// \xref[]]]\AT!_][\.[\AT!] primitive]
 28511  	prg.primitive(strNumber( /* "@#" */ 664), halfword(macroSpecial), halfword(macroSuffix))
 28512  
 28513  	// \xref[]]]\AT!\#_][\.[\AT!\#] primitive]
 28514  
 28515  	prg.primitive(strNumber( /* "expr" */ 675), halfword(paramType), halfword(hashBase+hashSize+12+1))
 28516  
 28517  	// \xref[expr_][\&[expr] primitive]
 28518  	prg.primitive(strNumber( /* "suffix" */ 676), halfword(paramType), halfword(hashBase+hashSize+12+1+paramSize))
 28519  
 28520  	// \xref[suffix_][\&[suffix] primitive]
 28521  	prg.primitive(strNumber( /* "text" */ 677), halfword(paramType), halfword(hashBase+hashSize+12+1+paramSize+paramSize))
 28522  
 28523  	// \xref[text_][\&[text] primitive]
 28524  	prg.primitive(strNumber( /* "primary" */ 678), halfword(paramType), halfword(primaryMacro))
 28525  
 28526  	// \xref[primary_][\&[primary] primitive]
 28527  	prg.primitive(strNumber( /* "secondary" */ 679), halfword(paramType), halfword(secondaryMacro))
 28528  
 28529  	// \xref[secondary_][\&[secondary] primitive]
 28530  	prg.primitive(strNumber( /* "tertiary" */ 680), halfword(paramType), halfword(tertiaryMacro))
 28531  
 28532  	// \xref[tertiary_][\&[tertiary] primitive]
 28533  
 28534  	prg.primitive(strNumber( /* "input" */ 690), halfword(input), halfword(0))
 28535  
 28536  	// \xref[input_][\&[input] primitive]
 28537  	prg.primitive(strNumber( /* "endinput" */ 616), halfword(input), halfword(1))
 28538  
 28539  	// \xref[end_input_][\&[endinput] primitive]
 28540  
 28541  	prg.primitive(strNumber( /* "if" */ 717), halfword(ifTest), halfword(ifCode))
 28542  
 28543  	// \xref[if_][\&[if] primitive]
 28544  	prg.primitive(strNumber( /* "fi" */ 452), halfword(fiOrElse), halfword(fiCode))
 28545  	prg.eqtb[hashBase+hashSize+9-1] = prg.eqtb[prg.curSym-1]
 28546  
 28547  	// \xref[fi_][\&[fi] primitive]
 28548  	prg.primitive(strNumber( /* "else" */ 718), halfword(fiOrElse), halfword(elseCode))
 28549  
 28550  	// \xref[else_][\&[else] primitive]
 28551  	prg.primitive(strNumber( /* "elseif" */ 719), halfword(fiOrElse), halfword(elseIfCode))
 28552  
 28553  	// \xref[else_if_][\&[elseif] primitive]
 28554  
 28555  	prg.primitive(strNumber( /* "true" */ 348), halfword(nullary), halfword(trueCode))
 28556  
 28557  	// \xref[true_][\&[true] primitive]
 28558  	prg.primitive(strNumber( /* "false" */ 349), halfword(nullary), halfword(falseCode))
 28559  
 28560  	// \xref[false_][\&[false] primitive]
 28561  	prg.primitive(strNumber( /* "nullpicture" */ 350), halfword(nullary), halfword(nullPictureCode))
 28562  
 28563  	// \xref[null_picture_][\&[nullpicture] primitive]
 28564  	prg.primitive(strNumber( /* "nullpen" */ 351), halfword(nullary), halfword(nullPenCode))
 28565  
 28566  	// \xref[null_pen_][\&[nullpen] primitive]
 28567  	prg.primitive(strNumber( /* "jobname" */ 352), halfword(nullary), halfword(jobNameOp))
 28568  
 28569  	// \xref[job_name_][\&[jobname] primitive]
 28570  	prg.primitive(strNumber( /* "readstring" */ 353), halfword(nullary), halfword(readStringOp))
 28571  
 28572  	// \xref[read_string_][\&[readstring] primitive]
 28573  	prg.primitive(strNumber( /* "pencircle" */ 354), halfword(nullary), halfword(penCircle))
 28574  
 28575  	// \xref[pen_circle_][\&[pencircle] primitive]
 28576  	prg.primitive(strNumber( /* "normaldeviate" */ 355), halfword(nullary), halfword(normalDeviate))
 28577  
 28578  	// \xref[normal_deviate_][\&[normaldeviate] primitive]
 28579  	prg.primitive(strNumber( /* "odd" */ 356), halfword(unary), halfword(oddOp))
 28580  
 28581  	// \xref[odd_][\&[odd] primitive]
 28582  	prg.primitive(strNumber( /* "known" */ 357), halfword(unary), halfword(knownOp))
 28583  
 28584  	// \xref[known_][\&[known] primitive]
 28585  	prg.primitive(strNumber( /* "unknown" */ 358), halfword(unary), halfword(unknownOp))
 28586  
 28587  	// \xref[unknown_][\&[unknown] primitive]
 28588  	prg.primitive(strNumber( /* "not" */ 359), halfword(unary), halfword(notOp))
 28589  
 28590  	// \xref[not_][\&[not] primitive]
 28591  	prg.primitive(strNumber( /* "decimal" */ 360), halfword(unary), halfword(decimal))
 28592  
 28593  	// \xref[decimal_][\&[decimal] primitive]
 28594  	prg.primitive(strNumber( /* "reverse" */ 361), halfword(unary), halfword(reverse))
 28595  
 28596  	// \xref[reverse_][\&[reverse] primitive]
 28597  	prg.primitive(strNumber( /* "makepath" */ 362), halfword(unary), halfword(makePathOp))
 28598  
 28599  	// \xref[make_path_][\&[makepath] primitive]
 28600  	prg.primitive(strNumber( /* "makepen" */ 363), halfword(unary), halfword(makePenOp))
 28601  
 28602  	// \xref[make_pen_][\&[makepen] primitive]
 28603  	prg.primitive(strNumber( /* "totalweight" */ 364), halfword(unary), halfword(totalWeightOp))
 28604  
 28605  	// \xref[total_weight_][\&[totalweight] primitive]
 28606  	prg.primitive(strNumber( /* "oct" */ 365), halfword(unary), halfword(octOp))
 28607  
 28608  	// \xref[oct_][\&[oct] primitive]
 28609  	prg.primitive(strNumber( /* "hex" */ 366), halfword(unary), halfword(hexOp))
 28610  
 28611  	// \xref[hex_][\&[hex] primitive]
 28612  	prg.primitive(strNumber( /* "ASCII" */ 367), halfword(unary), halfword(asciiOp))
 28613  
 28614  	// \xref[ASCII_][\&[ASCII] primitive]
 28615  	prg.primitive(strNumber( /* "char" */ 368), halfword(unary), halfword(charOp))
 28616  
 28617  	// \xref[char_][\&[char] primitive]
 28618  	prg.primitive(strNumber( /* "length" */ 369), halfword(unary), halfword(lengthOp))
 28619  
 28620  	// \xref[length_][\&[length] primitive]
 28621  	prg.primitive(strNumber( /* "turningnumber" */ 370), halfword(unary), halfword(turningOp))
 28622  
 28623  	// \xref[turning_number_][\&[turningnumber] primitive]
 28624  	prg.primitive(strNumber( /* "xpart" */ 371), halfword(unary), halfword(xPart))
 28625  
 28626  	// \xref[x_part_][\&[xpart] primitive]
 28627  	prg.primitive(strNumber( /* "ypart" */ 372), halfword(unary), halfword(yPart))
 28628  
 28629  	// \xref[y_part_][\&[ypart] primitive]
 28630  	prg.primitive(strNumber( /* "xxpart" */ 373), halfword(unary), halfword(xxPart))
 28631  
 28632  	// \xref[xx_part_][\&[xxpart] primitive]
 28633  	prg.primitive(strNumber( /* "xypart" */ 374), halfword(unary), halfword(xyPart))
 28634  
 28635  	// \xref[xy_part_][\&[xypart] primitive]
 28636  	prg.primitive(strNumber( /* "yxpart" */ 375), halfword(unary), halfword(yxPart))
 28637  
 28638  	// \xref[yx_part_][\&[yxpart] primitive]
 28639  	prg.primitive(strNumber( /* "yypart" */ 376), halfword(unary), halfword(yyPart))
 28640  
 28641  	// \xref[yy_part_][\&[yypart] primitive]
 28642  	prg.primitive(strNumber( /* "sqrt" */ 377), halfword(unary), halfword(sqrtOp))
 28643  
 28644  	// \xref[sqrt_][\&[sqrt] primitive]
 28645  	prg.primitive(strNumber( /* "mexp" */ 378), halfword(unary), halfword(mExpOp))
 28646  
 28647  	// \xref[m_exp_][\&[mexp] primitive]
 28648  	prg.primitive(strNumber( /* "mlog" */ 379), halfword(unary), halfword(mLogOp))
 28649  
 28650  	// \xref[m_log_][\&[mlog] primitive]
 28651  	prg.primitive(strNumber( /* "sind" */ 380), halfword(unary), halfword(sinDOp))
 28652  
 28653  	// \xref[sin_d_][\&[sind] primitive]
 28654  	prg.primitive(strNumber( /* "cosd" */ 381), halfword(unary), halfword(cosDOp))
 28655  
 28656  	// \xref[cos_d_][\&[cosd] primitive]
 28657  	prg.primitive(strNumber( /* "floor" */ 382), halfword(unary), halfword(floorOp))
 28658  
 28659  	// \xref[floor_][\&[floor] primitive]
 28660  	prg.primitive(strNumber( /* "uniformdeviate" */ 383), halfword(unary), halfword(uniformDeviate))
 28661  
 28662  	// \xref[uniform_deviate_][\&[uniformdeviate] primitive]
 28663  	prg.primitive(strNumber( /* "charexists" */ 384), halfword(unary), halfword(charExistsOp))
 28664  
 28665  	// \xref[char_exists_][\&[charexists] primitive]
 28666  	prg.primitive(strNumber( /* "angle" */ 385), halfword(unary), halfword(angleOp))
 28667  
 28668  	// \xref[angle_][\&[angle] primitive]
 28669  	prg.primitive(strNumber( /* "cycle" */ 386), halfword(cycle), halfword(cycleOp))
 28670  
 28671  	// \xref[cycle_][\&[cycle] primitive]
 28672  	prg.primitive(strNumber('+'), halfword(plusOrMinus), halfword(plus))
 28673  
 28674  	// \xref[+ ][\.[+] primitive]
 28675  	prg.primitive(strNumber('-'), halfword(plusOrMinus), halfword(minus))
 28676  
 28677  	// \xref[- ][\.[-] primitive]
 28678  	prg.primitive(strNumber('*'), halfword(secondaryBinary), halfword(times))
 28679  
 28680  	// \xref[* ][\.[*] primitive]
 28681  	prg.primitive(strNumber('/'), halfword(slash), halfword(over))
 28682  	prg.eqtb[hashBase+hashSize+4-1] = prg.eqtb[prg.curSym-1]
 28683  
 28684  	// \xref[/ ][\.[/] primitive]
 28685  	prg.primitive(strNumber( /* "++" */ 387), halfword(tertiaryBinary), halfword(pythagAdd))
 28686  
 28687  	// \xref[++_][\.[++] primitive]
 28688  	prg.primitive(strNumber( /* "+-+" */ 311), halfword(tertiaryBinary), halfword(pythagSub))
 28689  
 28690  	// \xref[+-+_][\.[+-+] primitive]
 28691  	prg.primitive(strNumber( /* "and" */ 389), halfword(andCommand), halfword(andOp))
 28692  
 28693  	// \xref[and_][\&[and] primitive]
 28694  	prg.primitive(strNumber( /* "or" */ 388), halfword(tertiaryBinary), halfword(orOp))
 28695  
 28696  	// \xref[or_][\&[or] primitive]
 28697  	prg.primitive(strNumber('<'), halfword(expressionBinary), halfword(lessThan))
 28698  
 28699  	// \xref[< ][\.[<] primitive]
 28700  	prg.primitive(strNumber( /* "<=" */ 390), halfword(expressionBinary), halfword(lessOrEqual))
 28701  
 28702  	// \xref[<=_][\.[<=] primitive]
 28703  	prg.primitive(strNumber('>'), halfword(expressionBinary), halfword(greaterThan))
 28704  
 28705  	// \xref[> ][\.[>] primitive]
 28706  	prg.primitive(strNumber( /* ">=" */ 391), halfword(expressionBinary), halfword(greaterOrEqual))
 28707  
 28708  	// \xref[>=_][\.[>=] primitive]
 28709  	prg.primitive(strNumber('='), halfword(equals), halfword(equalTo))
 28710  
 28711  	// \xref[= ][\.[=] primitive]
 28712  	prg.primitive(strNumber( /* "<>" */ 392), halfword(expressionBinary), halfword(unequalTo))
 28713  
 28714  	// \xref[<>_][\.[<>] primitive]
 28715  	prg.primitive(strNumber( /* "substring" */ 402), halfword(primaryBinary), halfword(substringOf))
 28716  
 28717  	// \xref[substring_][\&[substring] primitive]
 28718  	prg.primitive(strNumber( /* "subpath" */ 403), halfword(primaryBinary), halfword(subpathOf))
 28719  
 28720  	// \xref[subpath_][\&[subpath] primitive]
 28721  	prg.primitive(strNumber( /* "directiontime" */ 404), halfword(primaryBinary), halfword(directionTimeOf))
 28722  
 28723  	// \xref[direction_time_][\&[directiontime] primitive]
 28724  	prg.primitive(strNumber( /* "point" */ 405), halfword(primaryBinary), halfword(pointOf))
 28725  
 28726  	// \xref[point_][\&[point] primitive]
 28727  	prg.primitive(strNumber( /* "precontrol" */ 406), halfword(primaryBinary), halfword(precontrolOf))
 28728  
 28729  	// \xref[precontrol_][\&[precontrol] primitive]
 28730  	prg.primitive(strNumber( /* "postcontrol" */ 407), halfword(primaryBinary), halfword(postcontrolOf))
 28731  
 28732  	// \xref[postcontrol_][\&[postcontrol] primitive]
 28733  	prg.primitive(strNumber( /* "penoffset" */ 408), halfword(primaryBinary), halfword(penOffsetOf))
 28734  
 28735  	// \xref[pen_offset_][\&[penoffset] primitive]
 28736  	prg.primitive(strNumber('&'), halfword(ampersand), halfword(concatenate))
 28737  
 28738  	// \xref[!!!][\.[\&] primitive]
 28739  	prg.primitive(strNumber( /* "rotated" */ 393), halfword(secondaryBinary), halfword(rotatedBy))
 28740  
 28741  	// \xref[rotated_][\&[rotated] primitive]
 28742  	prg.primitive(strNumber( /* "slanted" */ 394), halfword(secondaryBinary), halfword(slantedBy))
 28743  
 28744  	// \xref[slanted_][\&[slanted] primitive]
 28745  	prg.primitive(strNumber( /* "scaled" */ 395), halfword(secondaryBinary), halfword(scaledBy))
 28746  
 28747  	// \xref[scaled_][\&[scaled] primitive]
 28748  	prg.primitive(strNumber( /* "shifted" */ 396), halfword(secondaryBinary), halfword(shiftedBy))
 28749  
 28750  	// \xref[shifted_][\&[shifted] primitive]
 28751  	prg.primitive(strNumber( /* "transformed" */ 397), halfword(secondaryBinary), halfword(transformedBy))
 28752  
 28753  	// \xref[transformed_][\&[transformed] primitive]
 28754  	prg.primitive(strNumber( /* "xscaled" */ 398), halfword(secondaryBinary), halfword(xScaled))
 28755  
 28756  	// \xref[x_scaled_][\&[xscaled] primitive]
 28757  	prg.primitive(strNumber( /* "yscaled" */ 399), halfword(secondaryBinary), halfword(yScaled))
 28758  
 28759  	// \xref[y_scaled_][\&[yscaled] primitive]
 28760  	prg.primitive(strNumber( /* "zscaled" */ 400), halfword(secondaryBinary), halfword(zScaled))
 28761  
 28762  	// \xref[z_scaled_][\&[zscaled] primitive]
 28763  	prg.primitive(strNumber( /* "intersectiontimes" */ 401), halfword(tertiaryBinary), halfword(intersect))
 28764  
 28765  	// \xref[intersection_times_][\&[intersectiontimes] primitive]
 28766  
 28767  	prg.primitive(strNumber( /* "numeric" */ 341), halfword(typeName), halfword(numericType))
 28768  
 28769  	// \xref[numeric_][\&[numeric] primitive]
 28770  	prg.primitive(strNumber( /* "string" */ 327), halfword(typeName), halfword(stringType))
 28771  
 28772  	// \xref[string_][\&[string] primitive]
 28773  	prg.primitive(strNumber( /* "boolean" */ 325), halfword(typeName), halfword(booleanType))
 28774  
 28775  	// \xref[boolean_][\&[boolean] primitive]
 28776  	prg.primitive(strNumber( /* "path" */ 332), halfword(typeName), halfword(pathType))
 28777  
 28778  	// \xref[path_][\&[path] primitive]
 28779  	prg.primitive(strNumber( /* "pen" */ 329), halfword(typeName), halfword(penType))
 28780  
 28781  	// \xref[pen_][\&[pen] primitive]
 28782  	prg.primitive(strNumber( /* "picture" */ 334), halfword(typeName), halfword(pictureType))
 28783  
 28784  	// \xref[picture_][\&[picture] primitive]
 28785  	prg.primitive(strNumber( /* "transform" */ 336), halfword(typeName), halfword(transformType))
 28786  
 28787  	// \xref[transform_][\&[transform] primitive]
 28788  	prg.primitive(strNumber( /* "pair" */ 337), halfword(typeName), halfword(pairType))
 28789  
 28790  	// \xref[pair_][\&[pair] primitive]
 28791  
 28792  	prg.primitive(strNumber( /* "end" */ 912), halfword(stop), halfword(0))
 28793  
 28794  	// \xref[end_][\&[end] primitive]
 28795  	prg.primitive(strNumber( /* "dump" */ 913), halfword(stop), halfword(1))
 28796  
 28797  	// \xref[dump_][\&[dump] primitive]
 28798  
 28799  	prg.primitive(strNumber( /* "batchmode" */ 273), halfword(modeCommand), halfword(batchMode))
 28800  	// \xref[batch_mode_][\&[batchmode] primitive]
 28801  	prg.primitive(strNumber( /* "nonstopmode" */ 274), halfword(modeCommand), halfword(nonstopMode))
 28802  	// \xref[nonstop_mode_][\&[nonstopmode] primitive]
 28803  	prg.primitive(strNumber( /* "scrollmode" */ 275), halfword(modeCommand), halfword(scrollMode))
 28804  	// \xref[scroll_mode_][\&[scrollmode] primitive]
 28805  	prg.primitive(strNumber( /* "errorstopmode" */ 919), halfword(modeCommand), halfword(errorStopMode))
 28806  	// \xref[error_stop_mode_][\&[errorstopmode] primitive]
 28807  
 28808  	prg.primitive(strNumber( /* "inner" */ 920), halfword(protectionCommand), halfword(0))
 28809  
 28810  	// \xref[inner_][\&[inner] primitive]
 28811  	prg.primitive(strNumber( /* "outer" */ 921), halfword(protectionCommand), halfword(1))
 28812  
 28813  	// \xref[outer_][\&[outer] primitive]
 28814  
 28815  	prg.primitive(strNumber( /* "showtoken" */ 935), halfword(showCommand), halfword(showTokenCode))
 28816  
 28817  	// \xref[show_token_][\&[showtoken] primitive]
 28818  	prg.primitive(strNumber( /* "showstats" */ 936), halfword(showCommand), halfword(showStatsCode))
 28819  
 28820  	// \xref[show_stats_][\&[showstats] primitive]
 28821  	prg.primitive(strNumber( /* "show" */ 937), halfword(showCommand), halfword(showCode))
 28822  
 28823  	// \xref[show_][\&[show] primitive]
 28824  	prg.primitive(strNumber( /* "showvariable" */ 938), halfword(showCommand), halfword(showVarCode))
 28825  
 28826  	// \xref[show_var_][\&[showvariable] primitive]
 28827  	prg.primitive(strNumber( /* "showdependencies" */ 939), halfword(showCommand), halfword(showDependenciesCode))
 28828  
 28829  	// \xref[show_dependencies_][\&[showdependencies] primitive]
 28830  
 28831  	prg.primitive(strNumber( /* "contour" */ 956), halfword(thingToAdd), halfword(contourCode))
 28832  
 28833  	// \xref[contour_][\&[contour] primitive]
 28834  	prg.primitive(strNumber( /* "doublepath" */ 957), halfword(thingToAdd), halfword(doublePathCode))
 28835  
 28836  	// \xref[double_path_][\&[doublepath] primitive]
 28837  	prg.primitive(strNumber( /* "also" */ 958), halfword(thingToAdd), halfword(alsoCode))
 28838  
 28839  	// \xref[also_][\&[also] primitive]
 28840  	prg.primitive(strNumber( /* "withpen" */ 959), halfword(withOption), halfword(penType))
 28841  
 28842  	// \xref[with_pen_][\&[withpen] primitive]
 28843  	prg.primitive(strNumber( /* "withweight" */ 960), halfword(withOption), halfword(known))
 28844  
 28845  	// \xref[with_weight_][\&[withweight] primitive]
 28846  	prg.primitive(strNumber( /* "dropping" */ 961), halfword(cullOp), halfword(dropCode))
 28847  
 28848  	// \xref[dropping_][\&[dropping] primitive]
 28849  	prg.primitive(strNumber( /* "keeping" */ 962), halfword(cullOp), halfword(keepCode))
 28850  
 28851  	// \xref[keeping_][\&[keeping] primitive]
 28852  
 28853  	prg.primitive(strNumber( /* "message" */ 992), halfword(messageCommand), halfword(messageCode))
 28854  
 28855  	// \xref[message_][\&[message] primitive]
 28856  	prg.primitive(strNumber( /* "errmessage" */ 993), halfword(messageCommand), halfword(errMessageCode))
 28857  
 28858  	// \xref[err_message_][\&[errmessage] primitive]
 28859  	prg.primitive(strNumber( /* "errhelp" */ 994), halfword(messageCommand), halfword(errHelpCode))
 28860  
 28861  	// \xref[err_help_][\&[errhelp] primitive]
 28862  
 28863  	prg.primitive(strNumber( /* "charlist" */ 1004), halfword(tfmCommand), halfword(charListCode))
 28864  
 28865  	// \xref[char_list_][\&[charlist] primitive]
 28866  	prg.primitive(strNumber( /* "ligtable" */ 1005), halfword(tfmCommand), halfword(ligTableCode))
 28867  
 28868  	// \xref[lig_table_][\&[ligtable] primitive]
 28869  	prg.primitive(strNumber( /* "extensible" */ 1006), halfword(tfmCommand), halfword(extensibleCode))
 28870  
 28871  	// \xref[extensible_][\&[extensible] primitive]
 28872  	prg.primitive(strNumber( /* "headerbyte" */ 1007), halfword(tfmCommand), halfword(headerByteCode))
 28873  
 28874  	// \xref[header_byte_][\&[headerbyte] primitive]
 28875  	prg.primitive(strNumber( /* "fontdimen" */ 1008), halfword(tfmCommand), halfword(fontDimenCode))
 28876  
 28877  	// \xref[font_dimen_][\&[fontdimen] primitive]
 28878  
 28879  	prg.primitive(strNumber( /* "=:" */ 1026), halfword(ligKernToken), halfword(0))
 28880  	// \xref[=:_][\.[=:] primitive]
 28881  	prg.primitive(strNumber( /* "=:|" */ 1027), halfword(ligKernToken), halfword(1))
 28882  	// \xref[=:/_][\.[=:\char'174] primitive]
 28883  	prg.primitive(strNumber( /* "=:|>" */ 1028), halfword(ligKernToken), halfword(5))
 28884  	// \xref[=:/>_][\.[=:\char'174>] primitive]
 28885  	prg.primitive(strNumber( /* "|=:" */ 1029), halfword(ligKernToken), halfword(2))
 28886  	// \xref[=:/_][\.[\char'174=:] primitive]
 28887  	prg.primitive(strNumber( /* "|=:>" */ 1030), halfword(ligKernToken), halfword(6))
 28888  	// \xref[=:/>_][\.[\char'174=:>] primitive]
 28889  	prg.primitive(strNumber( /* "|=:|" */ 1031), halfword(ligKernToken), halfword(3))
 28890  	// \xref[=:/_][\.[\char'174=:\char'174] primitive]
 28891  	prg.primitive(strNumber( /* "|=:|>" */ 1032), halfword(ligKernToken), halfword(7))
 28892  	// \xref[=:/>_][\.[\char'174=:\char'174>] primitive]
 28893  	prg.primitive(strNumber( /* "|=:|>>" */ 1033), halfword(ligKernToken), halfword(11))
 28894  	// \xref[=:/>_][\.[\char'174=:\char'174>>] primitive]
 28895  	prg.primitive(strNumber( /* "kern" */ 1034), halfword(ligKernToken), halfword(128))
 28896  	// \xref[kern_][\&[kern] primitive]
 28897  
 28898  	prg.primitive(strNumber( /* "special" */ 1058), halfword(specialCommand), halfword(stringType))
 28899  
 28900  	// \xref[special_][\&[special] primitive]
 28901  	prg.primitive(strNumber( /* "numspecial" */ 1059), halfword(specialCommand), halfword(known))
 28902  
 28903  	// \xref[num_special_][\&[numspecial] primitive]
 28904  
 28905  }
 28906  
 28907  func (prg *prg) initTab() { // initialize other tables
 28908  	var (
 28909  		k int32 // all-purpose index
 28910  	)
 28911  	prg.rover = uint16(memMin + 3 + 10 + 2 + 2 + 2 + 2 + 1 + 1) // initialize the dynamic memory
 28912  	*(*prg.mem[prg.rover].hh()).rh() = 65535
 28913  	*(*prg.mem[prg.rover].hh()).lh() = 1000 // which is a 1000-word available node
 28914  	*(*prg.mem[int32(prg.rover)+1].hh()).lh() = prg.rover
 28915  	*(*prg.mem[int32(prg.rover)+1].hh()).rh() = prg.rover
 28916  
 28917  	prg.loMemMax = uint16(int32(prg.rover) + 1000)
 28918  	*(*prg.mem[prg.loMemMax].hh()).rh() = uint16(memMin)
 28919  	*(*prg.mem[prg.loMemMax].hh()).lh() = uint16(memMin)
 28920  
 28921  	for ii := int32(3000 - 2); ii <= 3000; ii++ {
 28922  		k = ii
 28923  		_ = k
 28924  		prg.mem[k] = prg.mem[prg.loMemMax]
 28925  	} // clear list heads
 28926  	prg.avail = uint16(memMin)
 28927  	prg.memEnd = 3000
 28928  	prg.hiMemMin = uint16(3000 - 2) // initialize the one-word memory
 28929  	prg.varUsed = memMin + 3 + 10 + 2 + 2 + 2 + 2 + 1 + 1 - memMin
 28930  	prg.dynUsed = 3000 + 1 - int32(prg.hiMemMin)
 28931  	// initialize statistics
 28932  
 28933  	prg.intName[tracingTitles-1] = /* "tracingtitles" */ 410
 28934  	prg.intName[tracingEquations-1] = /* "tracingequations" */ 411
 28935  	prg.intName[tracingCapsules-1] = /* "tracingcapsules" */ 412
 28936  	prg.intName[tracingChoices-1] = /* "tracingchoices" */ 413
 28937  	prg.intName[tracingSpecs-1] = /* "tracingspecs" */ 414
 28938  	prg.intName[tracingPens-1] = /* "tracingpens" */ 415
 28939  	prg.intName[tracingCommands-1] = /* "tracingcommands" */ 416
 28940  	prg.intName[tracingRestores-1] = /* "tracingrestores" */ 417
 28941  	prg.intName[tracingMacros-1] = /* "tracingmacros" */ 418
 28942  	prg.intName[tracingEdges-1] = /* "tracingedges" */ 419
 28943  	prg.intName[tracingOutput-1] = /* "tracingoutput" */ 420
 28944  	prg.intName[tracingStats-1] = /* "tracingstats" */ 421
 28945  	prg.intName[tracingOnline-1] = /* "tracingonline" */ 422
 28946  	prg.intName[year-1] = /* "year" */ 423
 28947  	prg.intName[month-1] = /* "month" */ 424
 28948  	prg.intName[day-1] = /* "day" */ 425
 28949  	prg.intName[time-1] = /* "time" */ 426
 28950  	prg.intName[charCode-1] = /* "charcode" */ 427
 28951  	prg.intName[charExt-1] = /* "charext" */ 428
 28952  	prg.intName[charWd-1] = /* "charwd" */ 429
 28953  	prg.intName[charHt-1] = /* "charht" */ 430
 28954  	prg.intName[charDp-1] = /* "chardp" */ 431
 28955  	prg.intName[charIc-1] = /* "charic" */ 432
 28956  	prg.intName[charDx-1] = /* "chardx" */ 433
 28957  	prg.intName[charDy-1] = /* "chardy" */ 434
 28958  	prg.intName[designSize-1] = /* "designsize" */ 435
 28959  	prg.intName[hppp-1] = /* "hppp" */ 436
 28960  	prg.intName[vppp-1] = /* "vppp" */ 437
 28961  	prg.intName[xOffset-1] = /* "xoffset" */ 438
 28962  	prg.intName[yOffset-1] = /* "yoffset" */ 439
 28963  	prg.intName[pausing-1] = /* "pausing" */ 440
 28964  	prg.intName[showstopping-1] = /* "showstopping" */ 441
 28965  	prg.intName[fontmaking-1] = /* "fontmaking" */ 442
 28966  	prg.intName[proofing-1] = /* "proofing" */ 443
 28967  	prg.intName[smoothing-1] = /* "smoothing" */ 444
 28968  	prg.intName[autorounding-1] = /* "autorounding" */ 445
 28969  	prg.intName[granularity-1] = /* "granularity" */ 446
 28970  	prg.intName[fillin-1] = /* "fillin" */ 447
 28971  	prg.intName[turningCheck-1] = /* "turningcheck" */ 448
 28972  	prg.intName[warningCheck-1] = /* "warningcheck" */ 449
 28973  	prg.intName[boundaryChar-1] = /* "boundarychar" */ 450
 28974  
 28975  	prg.hashUsed = uint16(hashBase + hashSize) // nothing is used
 28976  	prg.stCount = 0
 28977  
 28978  	*prg.hash[hashBase+hashSize+11-1].rh() = 451
 28979  	*prg.hash[hashBase+hashSize+9-1].rh() = 452
 28980  	*prg.hash[hashBase+hashSize+10-1].rh() = 453
 28981  	*prg.hash[hashBase+hashSize+8-1].rh() = 454
 28982  	*prg.hash[hashBase+hashSize+7-1].rh() = 455
 28983  
 28984  	*prg.hash[hashBase+hashSize+6-1].rh() = ';'
 28985  	*prg.hash[hashBase+hashSize+5-1].rh() = ':'
 28986  	*prg.hash[hashBase+hashSize+4-1].rh() = '/'
 28987  	*prg.hash[hashBase+hashSize+3-1].rh() = '['
 28988  	*prg.hash[hashBase+hashSize+2-1].rh() = ')'
 28989  
 28990  	*prg.hash[hashBase+hashSize-1].rh() = 456
 28991  
 28992  	*prg.eqtb[hashBase+hashSize+2-1].lh() = uint16(rightDelimiter)
 28993  
 28994  	*(*prg.mem[memMin+3+10+2+2+2].hh()).lh() = uint16(hashBase + hashSize + 12 + 1)
 28995  	*(*prg.mem[memMin+3+10+2+2+2].hh()).rh() = uint16(memMin)
 28996  
 28997  	*(*prg.mem[3000].hh()).lh() = 65535 // |link(sentinel)=null|
 28998  
 28999  	*(*prg.mem[memMin+3].hh()).lh() = uint16(memMin)
 29000  	*(*prg.mem[memMin+3].hh()).rh() = uint16(memMin)
 29001  
 29002  	*(*prg.mem[memMin+3+1].hh()).lh() = 1
 29003  	*(*prg.mem[memMin+3+1].hh()).rh() = uint16(memMin)
 29004  	for ii := int32(memMin + 3 + 2); ii <= memMin+3+8; ii++ {
 29005  		k = ii
 29006  		_ = k
 29007  		prg.mem[k] = prg.mem[memMin+3+1]
 29008  	}
 29009  	*prg.mem[memMin+3+9].int() = 0
 29010  
 29011  	*(*prg.mem[memMin].hh()).rh() = uint16(memMin)
 29012  	*(*prg.mem[memMin].hh()).lh() = uint16(memMin)
 29013  
 29014  	*prg.mem[memMin+1].int() = 0
 29015  	*prg.mem[memMin+2].int() = 0
 29016  
 29017  	prg.serialNo = 0
 29018  	*(*prg.mem[memMin+3+10].hh()).rh() = uint16(memMin + 3 + 10)
 29019  	*(*prg.mem[memMin+3+10+1].hh()).lh() = uint16(memMin + 3 + 10)
 29020  	*(*prg.mem[memMin+3+10].hh()).lh() = uint16(memMin)
 29021  	*(*prg.mem[memMin+3+10+1].hh()).rh() = uint16(memMin)
 29022  
 29023  	*(*prg.mem[memMin+3+10+2+2+2+2].hh()).b1() = byte(root)
 29024  	*(*prg.mem[memMin+3+10+2+2+2+2].hh()).rh() = uint16(hashBase + hashSize + 11)
 29025  	*prg.eqtb[hashBase+hashSize+11-1].rh() = uint16(memMin + 3 + 10 + 2 + 2 + 2 + 2)
 29026  	*prg.eqtb[hashBase+hashSize+11-1].lh() = uint16(tagToken)
 29027  
 29028  	*prg.eqtb[hashBase+hashSize+1-1].lh() = uint16(repeatLoop + outerTag)
 29029  	*prg.hash[hashBase+hashSize+1-1].rh() = 734
 29030  
 29031  	*(*prg.mem[memMin+3+10+2+2].hh()).b1() = byte(capsule)
 29032  
 29033  	*prg.mem[memMin+3+10+2+2+2+1].int() = 010000000000
 29034  
 29035  	*prg.mem[memMin+3+10+2+1].int() = 0
 29036  	*(*prg.mem[memMin+3+10+2].hh()).lh() = 0
 29037  
 29038  	prg.baseIdent = /* " (INIMF)" */ 1067
 29039  
 29040  }
 29041  
 29042  //  procedure debug_help; [routine to display various things]
 29043  // label breakpoint,exit;
 29044  // var  k, l, m, n:integer;
 29045  // begin  ;
 29046  //    while true do  begin    ;
 29047  //   print_nl(["debug # (-1 to exit):"=]1081);  ;
 29048  // [ \xref[debug \#] ]
 29049  //   read(term_in,m);
 29050  //   if m<0 then  goto exit
 29051  //   else if m=0 then
 29052  //     begin goto breakpoint;
 29053  //  [go to every declared label at least once]
 29054  //     breakpoint: m:=0; ['BREAKPOINT']
 29055  //
 29056  //     end
 29057  //   else  begin read(term_in,n);
 29058  //     case m of
 29059  //     [ \4 ]
 29060  // [ Numbered cases for |debug_help| ]
 29061  // 1: print_word(mem[n]); [display |mem[n]| in all forms]
 29062  // 2: print_int( mem[ n].hh.lh );
 29063  // 3: print_int( mem[ n].hh.rh );
 29064  // 4: begin print_int( eqtb[ n].lh ); print_char([":"=]58); print_int( eqtb[ n].rh );
 29065  //   end;
 29066  // 5: print_variable_name(n);
 29067  // 6: print_int(internal[n]);
 29068  // 7: do_show_dependencies;
 29069  // 9: show_token_list(n,mem_min ,100000,0);
 29070  // 10: slow_print(n);
 29071  // 11: check_mem(n>0); [check wellformedness; print new busy locations if |n>0|]
 29072  // 12: search_mem(n); [look for pointers to |n|]
 29073  // 13: begin read(term_in,l); print_cmd_mod(n,l);
 29074  //   end;
 29075  // 14: for k:=0 to n do print(buffer[k]);
 29076  // 15: panicking:=not panicking;
 29077  //
 29078  //
 29079  //      else  print(["?"=]63)
 29080  //      end ;
 29081  //     end;
 29082  //   end;
 29083  // exit:end;
 29084  // [  ]
 29085  
 29086  // 1204.
 29087  
 29088  // tangle:pos ../../mf.web:22852:3:
 29089  
 29090  // Now this is really it: \MF\ starts and ends here.
 29091  //
 29092  // The initial test involving |ready_already| should be deleted if the
 29093  // \PASCAL\ runtime system is smart enough to detect such a ``mistake.''
 29094  // \xref[system dependencies]
 29095  func (prg *prg) main() {
 29096  	defer func() {
 29097  		if prg.baseFile != nil {
 29098  			prg.baseFile.Close()
 29099  		}
 29100  		if prg.gfFile != nil {
 29101  			prg.gfFile.Close()
 29102  		}
 29103  		if prg.logFile != nil {
 29104  			prg.logFile.Close()
 29105  		}
 29106  		if prg.poolFile != nil {
 29107  			prg.poolFile.Close()
 29108  		}
 29109  		if prg.stderr != nil {
 29110  			prg.stderr.Close()
 29111  		}
 29112  		if prg.stdin != nil {
 29113  			prg.stdin.Close()
 29114  		}
 29115  		if prg.stdout != nil {
 29116  			prg.stdout.Close()
 29117  		}
 29118  		if prg.termIn != nil {
 29119  			prg.termIn.Close()
 29120  		}
 29121  		if prg.termOut != nil {
 29122  			prg.termOut.Close()
 29123  		}
 29124  		if prg.tfmFile != nil {
 29125  			prg.tfmFile.Close()
 29126  		}
 29127  	}()
 29128  
 29129  	prg.history = byte(fatalErrorStop) // in case we quit during initialization
 29130  	prg.termOut.Rewrite("TTY:", "/O")  // open the terminal for output
 29131  	if prg.readyAlready == 314159 {
 29132  		goto startOfMf
 29133  	}
 29134  
 29135  	// Check the “constant” values...
 29136  	prg.bad = 0
 29137  	if halfErrorLine < 30 || halfErrorLine > errorLine-15 {
 29138  		prg.bad = 1
 29139  	}
 29140  	if maxPrintLine < 60 {
 29141  		prg.bad = 2
 29142  	}
 29143  	if gfBufSize%8 != 0 {
 29144  		prg.bad = 3
 29145  	}
 29146  	if memMin+1100 > 3000 {
 29147  		prg.bad = 4
 29148  	}
 29149  	if hashPrime > hashSize {
 29150  		prg.bad = 5
 29151  	}
 29152  	if headerSize%4 != 0 {
 29153  		prg.bad = 6
 29154  	}
 29155  	if ligTableSize < 255 || ligTableSize > 32510 {
 29156  		prg.bad = 7
 29157  	}
 29158  
 29159  	if memMax != 3000 {
 29160  		prg.bad = 10
 29161  	}
 29162  
 29163  	if memMax < 3000 {
 29164  		prg.bad = 10
 29165  	}
 29166  	if minQuarterword > 0 || maxQuarterword < 127 {
 29167  		prg.bad = 11
 29168  	}
 29169  	if 0 > 0 || 65535 < 32767 {
 29170  		prg.bad = 12
 29171  	}
 29172  	if minQuarterword < 0 || maxQuarterword > 65535 {
 29173  		prg.bad = 13
 29174  	}
 29175  	if memMin < 0 || memMax >= 65535 {
 29176  		prg.bad = 14
 29177  	}
 29178  	if maxStrings > 65535 {
 29179  		prg.bad = 15
 29180  	}
 29181  	if bufSize > 65535 {
 29182  		prg.bad = 16
 29183  	}
 29184  	if maxQuarterword-minQuarterword < 255 || 65535-0 < 65535 {
 29185  		prg.bad = 17
 29186  	}
 29187  
 29188  	if hashBase+hashSize+12+maxInternal > 65535 {
 29189  		prg.bad = 21
 29190  	}
 29191  
 29192  	if hashBase+hashSize+12+1+paramSize+paramSize+paramSize > 65535 {
 29193  		prg.bad = 22
 29194  	}
 29195  
 29196  	if 15*moveIncrement > bistackSize {
 29197  		prg.bad = 31
 29198  	}
 29199  
 29200  	if intPackets+17*intIncrement > bistackSize {
 29201  		prg.bad = 32
 29202  	}
 29203  
 29204  	if baseDefaultLength > fileNameSize {
 29205  		prg.bad = 41
 29206  	}
 29207  
 29208  	if prg.bad > 0 {
 29209  		prg.termOut.Writeln("Ouch---my internal constants have been clobbered!",
 29210  			"---case ", prg.bad, knuth.WriteWidth(1))
 29211  		// \xref[Ouch...clobbered]
 29212  
 29213  		// \xref[Ouch...clobbered]
 29214  		goto finalEnd
 29215  	}
 29216  	prg.initialize() // set global variables to their starting values
 29217  	if !prg.getStringsStarted() {
 29218  		goto finalEnd
 29219  	}
 29220  	prg.initTab()  // initialize the tables
 29221  	prg.initPrim() // call |primitive| for each primitive
 29222  	prg.initStrPtr = prg.strPtr
 29223  	prg.initPoolPtr = prg.poolPtr
 29224  
 29225  	prg.maxStrPtr = prg.strPtr
 29226  	prg.maxPoolPtr = prg.poolPtr
 29227  	prg.fixDateAndTime()
 29228  
 29229  	prg.readyAlready = 314159
 29230  
 29231  startOfMf:
 29232  	prg.selector = byte(termOnly)
 29233  	prg.tally = 0
 29234  	prg.termOffset = 0
 29235  	prg.fileOffset = 0
 29236  
 29237  	prg.termOut.Write("This is METAFONT, Version 2.71828182 (TRAP)")
 29238  	if int32(prg.baseIdent) == 0 {
 29239  		prg.termOut.Writeln(" (no base preloaded)")
 29240  	} else {
 29241  		prg.slowPrint(int32(prg.baseIdent))
 29242  		prg.printLn()
 29243  	}
 29244  
 29245  	prg.jobName = 0
 29246  	prg.logOpened = false
 29247  
 29248  	prg.outputFileName = 0
 29249  
 29250  	// Get the first line of input and prepare to start
 29251  	{
 29252  		{
 29253  			prg.inputPtr = 0
 29254  			prg.maxInStack = 0
 29255  			prg.inOpen = 0
 29256  			prg.openParens = 0
 29257  			prg.maxBufStack = 0
 29258  			prg.paramPtr = 0
 29259  			prg.maxParamStack = 0
 29260  			prg.first = 1
 29261  			prg.curInput.startField = 1
 29262  			prg.curInput.indexField = 0
 29263  			prg.line = 0
 29264  			prg.curInput.nameField = 0
 29265  			prg.forceEof = false
 29266  			if !prg.initTerminal() {
 29267  				goto finalEnd
 29268  			}
 29269  			prg.curInput.limitField = prg.last
 29270  			prg.first = uint16(int32(prg.last) + 1) // |init_terminal| has set |loc| and |last|
 29271  		}
 29272  
 29273  		prg.scannerStatus = byte(normal)
 29274  
 29275  		if int32(prg.baseIdent) == 0 || int32(prg.buffer[prg.curInput.locField]) == '&' {
 29276  			if int32(prg.baseIdent) != 0 {
 29277  				prg.initialize()
 29278  			} // erase preloaded base
 29279  			if !prg.openBaseFile() {
 29280  				goto finalEnd
 29281  			}
 29282  			if !prg.loadBaseFile() {
 29283  				prg.wClose(prg.baseFile)
 29284  				goto finalEnd
 29285  			}
 29286  			prg.wClose(prg.baseFile)
 29287  			for int32(prg.curInput.locField) < int32(prg.curInput.limitField) && int32(prg.buffer[prg.curInput.locField]) == ' ' {
 29288  				prg.curInput.locField = uint16(int32(prg.curInput.locField) + 1)
 29289  			}
 29290  		}
 29291  		prg.buffer[prg.curInput.limitField] = '%'
 29292  
 29293  		prg.fixDateAndTime()
 29294  		prg.initRandoms(prg.sysTime + prg.sysDay*0200000)
 29295  
 29296  		// Initialize the print |selector|...
 29297  		if int32(prg.interaction) == batchMode {
 29298  			prg.selector = byte(noPrint)
 29299  		} else {
 29300  			prg.selector = byte(termOnly)
 29301  		}
 29302  		if int32(prg.curInput.locField) < int32(prg.curInput.limitField) {
 29303  			if int32(prg.buffer[prg.curInput.locField]) != '\\' {
 29304  				prg.startInput()
 29305  			}
 29306  		} // \&[input] assumed
 29307  	}
 29308  	prg.history = byte(spotless) // ready to go!
 29309  	if int32(prg.startSym) > 0 {
 29310  		prg.curSym = prg.startSym
 29311  		prg.backInput()
 29312  	}
 29313  	prg.mainControl()  // come to life
 29314  	prg.finalCleanup() // prepare for death
 29315  	prg.closeFilesAndTerminate()
 29316  
 29317  finalEnd:
 29318  	prg.readyAlready = 0
 29319  }
 29320  
 29321  // 1214. \[51] System-dependent changes
 29322  
 29323  // tangle:pos ../../mf.web:23125:35:
 29324  
 29325  // This section should be replaced, if necessary, by any special
 29326  // modifications of the program
 29327  // that are necessary to make \MF\ work at a particular installation.
 29328  // It is usually best to design your change file so that all changes to
 29329  // previous sections preserve the section numbering; then everybody's version
 29330  // will be consistent with the published program. More extensive changes,
 29331  // which introduce new sections, can be inserted here; then only the index
 29332  // itself will get a new section number.
 29333  // \xref[system dependencies]
 29334  
 29335  // 1215. \[52] Index
 29336  
 29337  // tangle:pos ../../mf.web:23136:16:
 29338  
 29339  // Here is where you can find all uses of each identifier in the program,
 29340  // with underlined entries pointing to where the identifier was defined.
 29341  // If the identifier is only one letter long, however, you get to see only
 29342  // the underlined entries. [\sl All references are to section numbers instead of
 29343  // page numbers.]
 29344  //
 29345  // This index also lists error messages and other aspects of the program
 29346  // that you might want to look up some day. For example, the entry
 29347  // for ``system dependencies'' lists all sections that should receive
 29348  // special attention from people who are installing \MF\ in a new
 29349  // operating environment. A list of various things that can't happen appears
 29350  // under ``this can't happen''.
 29351  // Approximately 25 sections are listed under ``inner loop''; these account
 29352  // for more than 60\pct! of \MF's running time, exclusive of input and output.