modernc.org/knuth@v0.0.4/tex/tex.go (about)

     1  // Code generated by '[/tmp/go-build1534518744/b001/exe/generate]', DO NOT EDIT.
     2  
     3  // % This program is copyright (C) 1982 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 tex.web. (The WEB system provides
     7  // % for alterations via an auxiliary file; the master file should stay intact.)
     8  // % See Appendix H of the WEB manual for hints on how to install this program.
     9  // % And see Appendix A of the TRIP manual for details about how to validate it.
    10  //
    11  // % TeX is a trademark of the American Mathematical Society.
    12  // % METAFONT is a trademark of Addison-Wesley Publishing Company.
    13  //
    14  // % Version 0 was released in September 1982 after it passed a variety of tests.
    15  // % Version 1 was released in November 1983 after thorough testing.
    16  // % Version 1.1 fixed ``disappearing font identifiers'' et alia (July 1984).
    17  // % Version 1.2 allowed `0' in response to an error, et alia (October 1984).
    18  // % Version 1.3 made memory allocation more flexible and local (November 1984).
    19  // % Version 1.4 fixed accents right after line breaks, et alia (April 1985).
    20  // % Version 1.5 fixed \the\toks after other expansion in \edefs (August 1985).
    21  // % Version 2.0 (almost identical to 1.5) corresponds to "Volume B" (April 1986).
    22  // % Version 2.1 corrected anomalies in discretionary breaks (January 1987).
    23  // % Version 2.2 corrected "(Please type...)" with null \endlinechar (April 1987).
    24  // % Version 2.3 avoided incomplete page in premature termination (August 1987).
    25  // % Version 2.4 fixed \noaligned rules in indented displays (August 1987).
    26  // % Version 2.5 saved cur_order when expanding tokens (September 1987).
    27  // % Version 2.6 added 10sp slop when shipping leaders (November 1987).
    28  // % Version 2.7 improved rounding of negative-width characters (November 1987).
    29  // % Version 2.8 fixed weird bug if no \patterns are used (December 1987).
    30  // % Version 2.9 made \csname\endcsname's "relax" local (December 1987).
    31  // % Version 2.91 fixed \outer\def\a0[]\a\a bug (April 1988).
    32  // % Version 2.92 fixed \patterns, also file names with complex macros (May 1988).
    33  // % Version 2.93 fixed negative halving in allocator when mem_min<0 (June 1988).
    34  // % Version 2.94 kept open_log_file from calling fatal_error (November 1988).
    35  // % Version 2.95 solved that problem a better way (December 1988).
    36  // % Version 2.96 corrected bug in "Infinite shrinkage" recovery (January 1989).
    37  // % Version 2.97 corrected blunder in creating 2.95 (February 1989).
    38  // % Version 2.98 omitted save_for_after at outer level (March 1989).
    39  // % Version 2.99 caught $$\begingroup\halign..$$ (June 1989).
    40  // % Version 2.991 caught .5\ifdim.6... (June 1989).
    41  // % Version 2.992 introduced major changes for 8-bit extensions (September 1989).
    42  // % Version 2.993 fixed a save_stack synchronization bug et alia (December 1989).
    43  // % Version 3.0 fixed unusual displays; was more \output robust (March 1990).
    44  // % Version 3.1 fixed nullfont, disabled \write[\the\prevgraf] (September 1990).
    45  // % Version 3.14 fixed unprintable font names and corrected typos (March 1991).
    46  // % Version 3.141 more of same; reconstituted ligatures better (March 1992).
    47  // % Version 3.1415 preserved nonexplicit kerns, tidied up (February 1993).
    48  // % Version 3.14159 allowed fontmemsize to change; bulletproofing (March 1995).
    49  // % Version 3.141592 fixed \xleaders, glueset, weird alignments (December 2002).
    50  // % Version 3.1415926 was a general cleanup with minor fixes (February 2008).
    51  // % Version 3.14159265 was similar (January 2014).
    52  // % Version 3.141592653 was similar but more extensive (January 2021).
    53  //
    54  // % A reward of $327.68 will be paid to the first finder of any remaining bug.
    55  //
    56  // % Although considerable effort has been expended to make the TeX program
    57  // % correct and reliable, no warranty is implied; the author disclaims any
    58  // % obligation or liability for damages, including but not limited to
    59  // % special, indirect, or consequential damages arising out of or in
    60  // % connection with the use or performance of this software. This work has
    61  // % been a ``labor of love'' and the author hopes that users enjoy it.
    62  //
    63  // % Here is TeX material that gets inserted after \input webmac
    64  // \def\hang[\hangindent 3em\noindent\ignorespaces]
    65  // \def\hangg#1 [\hang\hbox[#1 ]]
    66  // \def\textindent#1[\hangindent2.5em\noindent\hbox to2.5em[\hss#1 ]\ignorespaces]
    67  // \font\ninerm=cmr9
    68  // \let\mc=\ninerm % medium caps for names like SAIL
    69  // \def\PASCAL[Pascal]
    70  // \def\ph[\hbox[Pascal-H]]
    71  // \def\pct![[\char`\%]] % percent sign in ordinary text
    72  // \font\logo=logo10 % font used for the METAFONT logo
    73  // \def\MF[[\logo META]\-[\logo FONT]]
    74  // \def\<#1>[$\langle#1\rangle$]
    75  // \def\section[\mathhexbox278]
    76  //
    77  // \def\(#1)[] % this is used to make section names sort themselves better
    78  // \def\9#1[] % this is used for sort keys in the index via @:sort key][entry@>
    79  //
    80  // \outer\def\N#1. \[#2]#3.[\MN#1.\vfil\eject % begin starred section
    81  //   \def\rhead[PART #2:\uppercase[#3]] % define running headline
    82  //   \message[*\modno] % progress report
    83  //   \edef\next[\write\cont[\Z[\?#2]#3][\modno][\the\pageno]]]\next
    84  //   \ifon\startsection[\bf\ignorespaces#3.\quad]\ignorespaces]
    85  // \let\?=\relax % we want to be able to \write a \?
    86  //
    87  // \def\title[\TeX82]
    88  // \def\topofcontents[\hsize 5.5in
    89  //   \vglue 0pt plus 1fil minus 1.5in
    90  //   \def\?##1][\hbox to 1in[\hfil##1.\ ]]
    91  //   ]
    92  // \def\botofcontents[\vskip 0pt plus 1fil minus 1.5in]
    93  // \pageno=3
    94  // \def\glob[13] % this should be the section number of "<Global...>"
    95  // \def\gglob[20, 26] % this should be the next two sections of "<Global...>"
    96  //
    97  //
    98  
    99  // 1. \[1] Introduction
   100  
   101  // tangle:pos tex.web:95:22:
   102  
   103  // This is \TeX, a document compiler intended to produce typesetting of high
   104  // quality.
   105  // The \PASCAL\ program that follows is the definition of \TeX82, a standard
   106  // \xref[PASCAL][\PASCAL]
   107  //  \xref[TeX82][\TeX82]
   108  // version of \TeX\ that is designed to be highly portable so that identical output
   109  // will be obtainable on a great variety of computers.
   110  //
   111  // The main purpose of the following program is to explain the algorithms of \TeX\
   112  // as clearly as possible. As a result, the program will not necessarily be very
   113  // efficient when a particular \PASCAL\ compiler has translated it into a
   114  // particular machine language. However, the program has been written so that it
   115  // can be tuned to run efficiently in a wide variety of operating environments
   116  // by making comparatively few changes. Such flexibility is possible because
   117  // the documentation that follows is written in the \.[WEB] language, which is
   118  // at a higher level than \PASCAL; the preprocessing step that converts \.[WEB]
   119  // to \PASCAL\ is able to introduce most of the necessary refinements.
   120  // Semi-automatic translation to other languages is also feasible, because the
   121  // program below does not make extensive use of features that are peculiar to
   122  // \PASCAL.
   123  //
   124  // A large piece of software like \TeX\ has inherent complexity that cannot
   125  // be reduced below a certain level of difficulty, although each individual
   126  // part is fairly simple by itself. The \.[WEB] language is intended to make
   127  // the algorithms as readable as possible, by reflecting the way the
   128  // individual program pieces fit together and by providing the
   129  // cross-references that connect different parts. Detailed comments about
   130  // what is going on, and about why things were done in certain ways, have
   131  // been liberally sprinkled throughout the program.  These comments explain
   132  // features of the implementation, but they rarely attempt to explain the
   133  // \TeX\ language itself, since the reader is supposed to be familiar with
   134  // [\sl The \TeX book].
   135  // \xref[WEB]
   136  // \xref[TeXbook][\sl The \TeX book]
   137  
   138  // 2.
   139  
   140  // tangle:pos tex.web:131:3:
   141  
   142  // The present implementation has a long ancestry, beginning in the summer
   143  // of~1977, when Michael~F. Plass and Frank~M. Liang designed and coded
   144  // a prototype
   145  // \xref[Plass, Michael Frederick]
   146  // \xref[Liang, Franklin Mark]
   147  // \xref[Knuth, Donald Ervin]
   148  // based on some specifications that the author had made in May of that year.
   149  // This original proto\TeX\ included macro definitions and elementary
   150  // manipulations on boxes and glue, but it did not have line-breaking,
   151  // page-breaking, mathematical formulas, alignment routines, error recovery,
   152  // or the present semantic nest; furthermore,
   153  // it used character lists instead of token lists, so that a control sequence
   154  // like \.[\\halign] was represented by a list of seven characters. A
   155  // complete version of \TeX\ was designed and coded by the author in late
   156  // 1977 and early 1978; that program, like its prototype, was written in the
   157  // [\mc SAIL] language, for which an excellent debugging system was
   158  // available. Preliminary plans to convert the [\mc SAIL] code into a form
   159  // somewhat like the present ``web'' were developed by Luis Trabb~Pardo and
   160  // \xref[Trabb Pardo, Luis Isidoro]
   161  // the author at the beginning of 1979, and a complete implementation was
   162  // created by Ignacio~A. Zabala in 1979 and 1980. The \TeX82 program, which
   163  // \xref[Zabala Salelles, Ignacio Andr\'es]
   164  // was written by the author during the latter part of 1981 and the early
   165  // part of 1982, also incorporates ideas from the 1979 implementation of
   166  // \xref[Guibas, Leonidas Ioannis]
   167  // \xref[Sedgewick, Robert]
   168  // \xref[Wyatt, Douglas Kirk]
   169  // \TeX\ in [\mc MESA] that was written by Leonidas Guibas, Robert Sedgewick,
   170  // and Douglas Wyatt at the Xerox Palo Alto Research Center.  Several hundred
   171  // refinements were introduced into \TeX82 based on the experiences gained with
   172  // the original implementations, so that essentially every part of the system
   173  // has been substantially improved. After the appearance of ``Version 0'' in
   174  // September 1982, this program benefited greatly from the comments of
   175  // many other people, notably David~R. Fuchs and Howard~W. Trickey.
   176  // A final revision in September 1989 extended the input character set to
   177  // eight-bit codes and introduced the ability to hyphenate words from
   178  // different languages, based on some ideas of Michael~J. Ferguson.
   179  // \xref[Fuchs, David Raymond]
   180  // \xref[Trickey, Howard Wellington]
   181  // \xref[Ferguson, Michael John]
   182  //
   183  // No doubt there still is plenty of room for improvement, but the author
   184  // is firmly committed to keeping \TeX82 ``frozen'' from now on; stability
   185  // and reliability are to be its main virtues.
   186  //
   187  // On the other hand, the \.[WEB] description can be extended without changing
   188  // the core of \TeX82 itself, and the program has been designed so that such
   189  // extensions are not extremely difficult to make.
   190  // The |banner| string defined here should be changed whenever \TeX\
   191  // undergoes any modifications, so that it will be clear which version of
   192  // \TeX\ might be the guilty party when a problem arises.
   193  // \xref[extensions to \TeX]
   194  // \xref[system dependencies]
   195  //
   196  // If this program is changed, the resulting system should not be called
   197  // `\TeX'; the official name `\TeX' by itself is reserved
   198  // for software systems that are fully compatible with each other.
   199  // A special test suite called the ``\.[TRIP] test'' is available for
   200  // helping to determine whether a particular implementation deserves to be
   201  // known as `\TeX' [cf.~Stanford Computer Science report CS1027,
   202  // November 1984].
   203  
   204  // 3.
   205  
   206  // tangle:pos tex.web:195:3:
   207  
   208  // Different \PASCAL s have slightly different conventions, and the present
   209  //  \xref[PASCAL H][\ph]
   210  // program expresses \TeX\ in terms of the \PASCAL\ that was
   211  // available to the author in 1982. Constructions that apply to
   212  // this particular compiler, which we shall call \ph, should help the
   213  // reader see how to make an appropriate interface for other systems
   214  // if necessary. (\ph\ is Charles Hedrick's modification of a compiler
   215  // \xref[Hedrick, Charles Locke]
   216  // for the DECsystem-10 that was originally developed at the University of
   217  // Hamburg; cf.\ [\sl Software---Practice and Experience \bf6] (1976),
   218  // 29--42. The \TeX\ program below is intended to be adaptable, without
   219  // extensive changes, to most other versions of \PASCAL, so it does not fully
   220  // use the admirable features of \ph. Indeed, a conscious effort has been
   221  // made here to avoid using several idiosyncratic features of standard
   222  // \PASCAL\ itself, so that most of the code can be translated mechanically
   223  // into other high-level languages. For example, the `\&[with]' and `\\[new]'
   224  // features are not used, nor are pointer types, set types, or enumerated
   225  // scalar types; there are no `\&[var]' parameters, except in the case of files;
   226  // there are no tag fields on variant records; there are no assignments
   227  // |real:=integer|; no procedures are declared local to other procedures.)
   228  //
   229  // The portions of this program that involve system-dependent code, where
   230  // changes might be necessary because of differences between \PASCAL\ compilers
   231  // and/or differences between
   232  // operating systems, can be identified by looking at the sections whose
   233  // numbers are listed under `system dependencies' in the index. Furthermore,
   234  // the index entries for `dirty \PASCAL' list all places where the restrictions
   235  // of \PASCAL\ have not been followed perfectly, for one reason or another.
   236  //  \xref[system dependencies]
   237  //  \xref[dirty \PASCAL]
   238  //
   239  // Incidentally, \PASCAL's standard |round| function can be problematical,
   240  // because it disagrees with the IEEE floating-point standard.
   241  // Many implementors have
   242  // therefore chosen to substitute their own home-grown rounding procedure.
   243  
   244  // 4.
   245  
   246  // tangle:pos tex.web:231:3:
   247  
   248  // The program begins with a normal \PASCAL\ program heading, whose
   249  // components will be filled in later, using the conventions of \.[WEB].
   250  // \xref[WEB]
   251  // For example, the portion of the program called `\X\glob:Global
   252  // variables\X' below will be replaced by a sequence of variable declarations
   253  // that starts in $\section\glob$ of this documentation. In this way, we are able
   254  // to define each individual global variable when we are prepared to
   255  // understand what it means; we do not have to define all of the globals at
   256  // once.  Cross references in $\section\glob$, where it says ``See also
   257  // sections \gglob, \dots,'' also make it possible to look at the set of
   258  // all global variables, if desired.  Similar remarks apply to the other
   259  // portions of the program heading.
   260  //
   261  // Actually the heading shown here is not quite normal: The |program| line
   262  // does not mention any |output| file, because \ph\ would ask the \TeX\ user
   263  // to specify a file name if |output| were specified here.
   264  // \xref[PASCAL H][\ph]
   265  // \xref[system dependencies]
   266  // \4
   267  // Compiler directives
   268  // $C-,A+,D-
   269  // no range check, catch arithmetic overflow, no debug overhead
   270  //  [$C+,D+]  [  ]
   271  // but turn everything on when debugging
   272  
   273  package tex
   274  
   275  import (
   276  	"math"
   277  	"unsafe"
   278  
   279  	"modernc.org/knuth"
   280  )
   281  
   282  var (
   283  	_ = math.MaxInt32
   284  	_ unsafe.Pointer
   285  )
   286  
   287  type (
   288  	char   = byte
   289  	signal int
   290  )
   291  
   292  func strcopy(dst []char, src string) {
   293  	for i := 0; i < len(dst) && i < len(src); i++ {
   294  		dst[i] = src[i]
   295  	}
   296  }
   297  
   298  func arraystr(a []char) string {
   299  	b := make([]byte, len(a))
   300  	for i, c := range a {
   301  		b[i] = c
   302  	}
   303  	return string(b)
   304  }
   305  
   306  func abs(n int32) int32 {
   307  	if n >= 0 {
   308  		return n
   309  	}
   310  
   311  	return -n
   312  }
   313  
   314  func fabs(f float64) float64 {
   315  	if f >= 0 {
   316  		return f
   317  	}
   318  
   319  	return -f
   320  }
   321  
   322  func round(f float64) int32 {
   323  	if f >= 0 {
   324  		return int32(f + 0.5)
   325  	}
   326  
   327  	return int32(f - 0.5)
   328  }
   329  
   330  // key control points
   331  
   332  const (
   333  	startOfTex = 1    /* go here when \TeX's variables are initialized */
   334  	endOfTex   = 9998 /* go here to close files and terminate gracefully */
   335  	finalEnd   = 9999 /* this label marks the ending of the program */
   336  	memBot     = 0    // smallest index in the |mem| array dumped by \.[INITEX];
   337  	//   must not be less than |mem_min|
   338  
   339  	fontBase = 0 // smallest internal font number; must not be less
   340  	//   than |min_quarterword|
   341  
   342  	hashSize = 2100 // maximum number of control sequences; it should be at most
   343  	//   about |(mem_max-mem_min)/10|
   344  
   345  	hashPrime = 1777 /* a prime number equal to about 85\pct! of |hash_size| */
   346  	hyphSize  = 307  // another prime; the number of \.[\\hyphenation] exceptions
   347  	// \xref[system dependencies]
   348  
   349  	exit               = 10          /* go here to leave a procedure */
   350  	restart            = 20          /* go here to start a procedure again */
   351  	reswitch           = 21          /* go here to start a case statement again */
   352  	continue1          = 22          /* go here to resume a loop */
   353  	done               = 30          /* go here to exit a loop */
   354  	done1              = 31          /* like |done|, when there is more than one loop */
   355  	done2              = 32          /* for exiting the second loop in a long block */
   356  	done3              = 33          /* for exiting the third loop in a very long block */
   357  	done4              = 34          /* for exiting the fourth loop in an extremely long block */
   358  	done5              = 35          /* for exiting the fifth loop in an immense block */
   359  	done6              = 36          /* for exiting the sixth loop in a block */
   360  	found              = 40          /* go here when you've found it */
   361  	found1             = 41          /* like |found|, when there's more than one per routine */
   362  	found2             = 42          /* like |found|, when there's more than two per routine */
   363  	notFound           = 45          /* go here when you've found nothing */
   364  	commonEnding       = 50          /* go here when you want to merge with another branch */
   365  	empty              = 0           /* symbolic name for a null constant */
   366  	firstTextChar      = 0           /* ordinal number of the smallest element of |text_char| */
   367  	lastTextChar       = 255         /* ordinal number of the largest element of |text_char| */
   368  	nullCode           = 0           /* ASCII code that might disappear */
   369  	carriageReturn     = 015         /* ASCII code used at end of line */
   370  	invalidCode        = 0177        /* ASCII code that many systems prohibit in text files */
   371  	noPrint            = 16          /* |selector| setting that makes data disappear */
   372  	termOnly           = 17          /* printing is destined for the terminal only */
   373  	logOnly            = 18          /* printing is destined for the transcript file only */
   374  	termAndLog         = 19          /* normal |selector| setting */
   375  	pseudo             = 20          /* special |selector| setting for |show_context| */
   376  	newString          = 21          /* printing is deflected to the string pool */
   377  	maxSelector        = 21          /* highest selector setting */
   378  	batchMode          = 0           /* omits all stops and omits terminal output */
   379  	nonstopMode        = 1           /* omits all stops */
   380  	scrollMode         = 2           /* omits error stops */
   381  	errorStopMode      = 3           /* stops at every opportunity to interact */
   382  	spotless           = 0           /* |history| value when nothing has been amiss yet */
   383  	warningIssued      = 1           /* |history| value when |begin_diagnostic| has been called */
   384  	errorMessageIssued = 2           /* |history| value when |error| has been called */
   385  	fatalErrorStop     = 3           /* |history| value when termination was premature */
   386  	infBad             = 10000       /* infinitely bad value */
   387  	minQuarterword     = 0           /* smallest allowable value in a |quarterword| */
   388  	maxQuarterword     = 255         /* largest allowable value in a |quarterword| */
   389  	hlistNode          = 0           /* |type| of hlist nodes */
   390  	boxNodeSize        = 7           /* number of words to allocate for a box node */
   391  	widthOffset        = 1           /* position of |width| field in a box node */
   392  	depthOffset        = 2           /* position of |depth| field in a box node */
   393  	heightOffset       = 3           /* position of |height| field in a box node */
   394  	listOffset         = 5           /* position of |list_ptr| field in a box node */
   395  	normal             = 0           /* the most common case when several cases are named */
   396  	stretching         = 1           /* glue setting applies to the stretch components */
   397  	shrinking          = 2           /* glue setting applies to the shrink components */
   398  	glueOffset         = 6           /* position of |glue_set| in a box node */
   399  	vlistNode          = 1           /* |type| of vlist nodes */
   400  	ruleNode           = 2           /* |type| of rule nodes */
   401  	ruleNodeSize       = 4           /* number of words to allocate for a rule node */
   402  	insNode            = 3           /* |type| of insertion nodes */
   403  	insNodeSize        = 5           /* number of words to allocate for an insertion */
   404  	markNode           = 4           /* |type| of a mark node */
   405  	smallNodeSize      = 2           /* number of words to allocate for most node types */
   406  	adjustNode         = 5           /* |type| of an adjust node */
   407  	ligatureNode       = 6           /* |type| of a ligature node */
   408  	discNode           = 7           /* |type| of a discretionary node */
   409  	whatsitNode        = 8           /* |type| of special extension nodes */
   410  	mathNode           = 9           /* |type| of a math node */
   411  	before             = 0           /* |subtype| for math node that introduces a formula */
   412  	after              = 1           /* |subtype| for math node that winds up a formula */
   413  	glueNode           = 10          /* |type| of node that points to a glue specification */
   414  	condMathGlue       = 98          /* special |subtype| to suppress glue in the next node */
   415  	muGlue             = 99          /* |subtype| for math glue */
   416  	aLeaders           = 100         /* |subtype| for aligned leaders */
   417  	cLeaders           = 101         /* |subtype| for centered leaders */
   418  	xLeaders           = 102         /* |subtype| for expanded leaders */
   419  	glueSpecSize       = 4           /* number of words to allocate for a glue specification */
   420  	fil                = 1           /* first-order infinity */
   421  	fill               = 2           /* second-order infinity */
   422  	filll              = 3           /* third-order infinity */
   423  	kernNode           = 11          /* |type| of a kern node */
   424  	explicit           = 1           /* |subtype| of kern nodes from \.[\\kern] and \.[\\/] */
   425  	accKern            = 2           /* |subtype| of kern nodes from accents */
   426  	penaltyNode        = 12          /* |type| of a penalty node */
   427  	infPenalty         = infBad      /* ``infinite'' penalty value */
   428  	ejectPenalty       = -infPenalty /* ``negatively infinite'' penalty value */
   429  	unsetNode          = 13          /* |type| for an unset node */
   430  	hiMemStatUsage     = 14          /* the number of one-word nodes always present */
   431  	escape             = 0           // escape delimiter (called \.\\ in [\sl The \TeX book\/])
   432  	// \xref[TeXbook][\sl The \TeX book]
   433  
   434  	relax       = 0  /* do nothing ( \.[\\relax] ) */
   435  	leftBrace   = 1  /* beginning of a group ( \.\[ ) */
   436  	rightBrace  = 2  /* ending of a group ( \.\] ) */
   437  	mathShift   = 3  /* mathematics shift character ( \.\$ ) */
   438  	tabMark     = 4  /* alignment delimiter ( \.\&, \.[\\span] ) */
   439  	carRet      = 5  /* end of line ( |carriage_return|, \.[\\cr], \.[\\crcr] ) */
   440  	outParam    = 5  /* output a macro parameter */
   441  	macParam    = 6  /* macro parameter symbol ( \.\# ) */
   442  	supMark     = 7  /* superscript ( \.[\char'136] ) */
   443  	subMark     = 8  /* subscript ( \.[\char'137] ) */
   444  	ignore      = 9  /* characters to ignore ( \.[\^\^@] ) */
   445  	endv        = 9  /* end of \<v_j> list in alignment template */
   446  	spacer      = 10 /* characters equivalent to blank space ( \.[\ ] ) */
   447  	letter      = 11 /* characters regarded as letters ( \.[A..Z], \.[a..z] ) */
   448  	otherChar   = 12 /* none of the special character types */
   449  	activeChar  = 13 /* characters that invoke macros ( \.[\char`\~] ) */
   450  	parEnd      = 13 /* end of paragraph ( \.[\\par] ) */
   451  	match       = 13 /* match a macro parameter */
   452  	comment     = 14 /* characters that introduce comments ( \.\% ) */
   453  	endMatch    = 14 /* end of parameters to macro */
   454  	stop        = 14 /* end of job ( \.[\\end], \.[\\dump] ) */
   455  	invalidChar = 15 /* characters that shouldn't appear ( \.[\^\^?] ) */
   456  	delimNum    = 15 /* specify delimiter numerically ( \.[\\delimiter] ) */
   457  	maxCharCode = 15 /* largest catcode for individual characters */
   458  	charNum     = 16 /* character specified numerically ( \.[\\char] ) */
   459  	mathCharNum = 17 /* explicit math code ( \.[\\mathchar] ) */
   460  	mark        = 18 /* mark definition ( \.[\\mark] ) */
   461  	xray        = 19 /* peek inside of \TeX\ ( \.[\\show], \.[\\showbox], etc.~) */
   462  	makeBox     = 20 /* make a box ( \.[\\box], \.[\\copy], \.[\\hbox], etc.~) */
   463  	hmove       = 21 /* horizontal motion ( \.[\\moveleft], \.[\\moveright] ) */
   464  	vmove       = 22 /* vertical motion ( \.[\\raise], \.[\\lower] ) */
   465  	unHbox      = 23 /* unglue a box ( \.[\\unhbox], \.[\\unhcopy] ) */
   466  	unVbox      = 24 /* unglue a box ( \.[\\unvbox], \.[\\unvcopy] ) */
   467  	removeItem  = 25 // nullify last item ( \.[\\unpenalty],
   468  	//   \.[\\unkern], \.[\\unskip] )
   469  
   470  	hskip           = 26 /* horizontal glue ( \.[\\hskip], \.[\\hfil], etc.~) */
   471  	vskip           = 27 /* vertical glue ( \.[\\vskip], \.[\\vfil], etc.~) */
   472  	mskip           = 28 /* math glue ( \.[\\mskip] ) */
   473  	kern            = 29 /* fixed space ( \.[\\kern] ) */
   474  	mkern           = 30 /* math kern ( \.[\\mkern] ) */
   475  	leaderShip      = 31 /* use a box ( \.[\\shipout], \.[\\leaders], etc.~) */
   476  	halign          = 32 /* horizontal table alignment ( \.[\\halign] ) */
   477  	valign          = 33 /* vertical table alignment ( \.[\\valign] ) */
   478  	noAlign         = 34 /* temporary escape from alignment ( \.[\\noalign] ) */
   479  	vrule           = 35 /* vertical rule ( \.[\\vrule] ) */
   480  	hrule           = 36 /* horizontal rule ( \.[\\hrule] ) */
   481  	insert          = 37 /* vlist inserted in box ( \.[\\insert] ) */
   482  	vadjust         = 38 /* vlist inserted in enclosing paragraph ( \.[\\vadjust] ) */
   483  	ignoreSpaces    = 39 /* gobble |spacer| tokens ( \.[\\ignorespaces] ) */
   484  	afterAssignment = 40 /* save till assignment is done ( \.[\\afterassignment] ) */
   485  	afterGroup      = 41 /* save till group is done ( \.[\\aftergroup] ) */
   486  	breakPenalty    = 42 /* additional badness ( \.[\\penalty] ) */
   487  	startPar        = 43 /* begin paragraph ( \.[\\indent], \.[\\noindent] ) */
   488  	italCorr        = 44 /* italic correction ( \.[\\/] ) */
   489  	accent          = 45 /* attach accent in text ( \.[\\accent] ) */
   490  	mathAccent      = 46 /* attach accent in math ( \.[\\mathaccent] ) */
   491  	discretionary   = 47 /* discretionary texts ( \.[\\-], \.[\\discretionary] ) */
   492  	eqNo            = 48 /* equation number ( \.[\\eqno], \.[\\leqno] ) */
   493  	leftRight       = 49 /* variable delimiter ( \.[\\left], \.[\\right] ) */
   494  	mathComp        = 50 /* component of formula ( \.[\\mathbin], etc.~) */
   495  	limitSwitch     = 51 /* diddle limit conventions ( \.[\\displaylimits], etc.~) */
   496  	above           = 52 /* generalized fraction ( \.[\\above], \.[\\atop], etc.~) */
   497  	mathStyle       = 53 /* style specification ( \.[\\displaystyle], etc.~) */
   498  	mathChoice      = 54 /* choice specification ( \.[\\mathchoice] ) */
   499  	nonScript       = 55 /* conditional math glue ( \.[\\nonscript] ) */
   500  	vcenter         = 56 /* vertically center a vbox ( \.[\\vcenter] ) */
   501  	caseShift       = 57 /* force specific case ( \.[\\lowercase], \.[\\uppercase]~) */
   502  	message         = 58 /* send to user ( \.[\\message], \.[\\errmessage] ) */
   503  	extension       = 59 /* extensions to \TeX\ ( \.[\\write], \.[\\special], etc.~) */
   504  	inStream        = 60 /* files for reading ( \.[\\openin], \.[\\closein] ) */
   505  	beginGroup      = 61 /* begin local grouping ( \.[\\begingroup] ) */
   506  	endGroup        = 62 /* end local grouping ( \.[\\endgroup] ) */
   507  	omit            = 63 /* omit alignment template ( \.[\\omit] ) */
   508  	exSpace         = 64 /* explicit space ( \.[\\\ ] ) */
   509  	noBoundary      = 65 /* suppress boundary ligatures ( \.[\\noboundary] ) */
   510  	radical         = 66 /* square root and similar signs ( \.[\\radical] ) */
   511  	endCsName       = 67 /* end control sequence ( \.[\\endcsname] ) */
   512  	minInternal     = 68 /* the smallest code that can follow \.[\\the] */
   513  	charGiven       = 68 /* character code defined by \.[\\chardef] */
   514  	mathGiven       = 69 /* math code defined by \.[\\mathchardef] */
   515  	lastItem        = 70 // most recent item ( \.[\\lastpenalty],
   516  	//   \.[\\lastkern], \.[\\lastskip] )
   517  
   518  	maxNonPrefixedCommand = 70 /* largest command code that can't be \.[\\global] */
   519  	toksRegister          = 71 /* token list register ( \.[\\toks] ) */
   520  	assignToks            = 72 /* special token list ( \.[\\output], \.[\\everypar], etc.~) */
   521  	assignInt             = 73 /* user-defined integer ( \.[\\tolerance], \.[\\day], etc.~) */
   522  	assignDimen           = 74 /* user-defined length ( \.[\\hsize], etc.~) */
   523  	assignGlue            = 75 /* user-defined glue ( \.[\\baselineskip], etc.~) */
   524  	assignMuGlue          = 76 /* user-defined muglue ( \.[\\thinmuskip], etc.~) */
   525  	assignFontDimen       = 77 /* user-defined font dimension ( \.[\\fontdimen] ) */
   526  	assignFontInt         = 78 // user-defined font integer ( \.[\\hyphenchar],
   527  	//   \.[\\skewchar] )
   528  
   529  	setAux       = 79 /* specify state info ( \.[\\spacefactor], \.[\\prevdepth] ) */
   530  	setPrevGraf  = 80 /* specify state info ( \.[\\prevgraf] ) */
   531  	setPageDimen = 81 /* specify state info ( \.[\\pagegoal], etc.~) */
   532  	setPageInt   = 82 // specify state info ( \.[\\deadcycles],
   533  	//   \.[\\insertpenalties] )
   534  
   535  	setBoxDimen           = 83                        /* change dimension of box ( \.[\\wd], \.[\\ht], \.[\\dp] ) */
   536  	setShape              = 84                        /* specify fancy paragraph shape ( \.[\\parshape] ) */
   537  	defCode               = 85                        /* define a character code ( \.[\\catcode], etc.~) */
   538  	defFamily             = 86                        /* declare math fonts ( \.[\\textfont], etc.~) */
   539  	setFont               = 87                        /* set current font ( font identifiers ) */
   540  	defFont               = 88                        /* define a font file ( \.[\\font] ) */
   541  	register              = 89                        /* internal register ( \.[\\count], \.[\\dimen], etc.~) */
   542  	maxInternal           = 89                        /* the largest code that can follow \.[\\the] */
   543  	advance               = 90                        /* advance a register or parameter ( \.[\\advance] ) */
   544  	multiply              = 91                        /* multiply a register or parameter ( \.[\\multiply] ) */
   545  	divide                = 92                        /* divide a register or parameter ( \.[\\divide] ) */
   546  	prefix                = 93                        /* qualify a definition ( \.[\\global], \.[\\long], \.[\\outer] ) */
   547  	let                   = 94                        /* assign a command code ( \.[\\let], \.[\\futurelet] ) */
   548  	shorthandDef          = 95                        /* code definition ( \.[\\chardef], \.[\\countdef], etc.~) */
   549  	readToCs              = 96                        /* read into a control sequence ( \.[\\read] ) */
   550  	def                   = 97                        /* macro definition ( \.[\\def], \.[\\gdef], \.[\\xdef], \.[\\edef] ) */
   551  	setBox                = 98                        /* set a box ( \.[\\setbox] ) */
   552  	hyphData              = 99                        /* hyphenation data ( \.[\\hyphenation], \.[\\patterns] ) */
   553  	setInteraction        = 100                       /* define level of interaction ( \.[\\batchmode], etc.~) */
   554  	maxCommand            = 100                       /* the largest command code seen at |big_switch| */
   555  	undefinedCs           = maxCommand + 1            /* initial state of most |eq_type| fields */
   556  	expandAfter           = maxCommand + 2            /* special expansion ( \.[\\expandafter] ) */
   557  	noExpand              = maxCommand + 3            /* special nonexpansion ( \.[\\noexpand] ) */
   558  	input                 = maxCommand + 4            /* input a source file ( \.[\\input], \.[\\endinput] ) */
   559  	ifTest                = maxCommand + 5            /* conditional text ( \.[\\if], \.[\\ifcase], etc.~) */
   560  	fiOrElse              = maxCommand + 6            /* delimiters for conditionals ( \.[\\else], etc.~) */
   561  	csName                = maxCommand + 7            /* make a control sequence from tokens ( \.[\\csname] ) */
   562  	convert               = maxCommand + 8            /* convert to text ( \.[\\number], \.[\\string], etc.~) */
   563  	the                   = maxCommand + 9            /* expand an internal quantity ( \.[\\the] ) */
   564  	topBotMark            = maxCommand + 10           /* inserted mark ( \.[\\topmark], etc.~) */
   565  	call                  = maxCommand + 11           /* non-long, non-outer control sequence */
   566  	longCall              = maxCommand + 12           /* long, non-outer control sequence */
   567  	outerCall             = maxCommand + 13           /* non-long, outer control sequence */
   568  	longOuterCall         = maxCommand + 14           /* long, outer control sequence */
   569  	endTemplate           = maxCommand + 15           /* end of an alignment template */
   570  	dontExpand            = maxCommand + 16           /* the following token was marked by \.[\\noexpand] */
   571  	glueRef               = maxCommand + 17           /* the equivalent points to a glue specification */
   572  	shapeRef              = maxCommand + 18           /* the equivalent points to a parshape specification */
   573  	boxRef                = maxCommand + 19           /* the equivalent points to a box node, or is |null| */
   574  	data                  = maxCommand + 20           /* the equivalent is simply a halfword number */
   575  	vmode                 = 1                         /* vertical mode */
   576  	hmode                 = vmode + maxCommand + 1    /* horizontal mode */
   577  	mmode                 = hmode + maxCommand + 1    /* math mode */
   578  	levelZero             = minQuarterword            /* level for undefined quantities */
   579  	levelOne              = levelZero + 1             /* outermost level for defined quantities */
   580  	activeBase            = 1                         /* beginning of region 1, for active character equivalents */
   581  	singleBase            = activeBase + 256          /* equivalents of one-character control sequences */
   582  	nullCs                = singleBase + 256          /* equivalent of \.[\\csname\\endcsname] */
   583  	hashBase              = nullCs + 1                /* beginning of region 2, for the hash table */
   584  	frozenControlSequence = hashBase + hashSize       /* for error recovery */
   585  	frozenProtection      = frozenControlSequence     /* inaccessible but definable */
   586  	frozenCr              = frozenControlSequence + 1 /* permanent `\.[\\cr]' */
   587  	frozenEndGroup        = frozenControlSequence + 2 /* permanent `\.[\\endgroup]' */
   588  	frozenRight           = frozenControlSequence + 3 /* permanent `\.[\\right]' */
   589  	frozenFi              = frozenControlSequence + 4 /* permanent `\.[\\fi]' */
   590  	frozenEndTemplate     = frozenControlSequence + 5 /* permanent `\.[\\endtemplate]' */
   591  	frozenEndv            = frozenControlSequence + 6 /* second permanent `\.[\\endtemplate]' */
   592  	frozenRelax           = frozenControlSequence + 7 /* permanent `\.[\\relax]' */
   593  	endWrite              = frozenControlSequence + 8 /* permanent `\.[\\endwrite]' */
   594  	frozenDontExpand      = frozenControlSequence + 9
   595  	/* permanent `\.[\\notexpanded:]' */
   596  	frozenNullFont = frozenControlSequence + 10
   597  	/* permanent `\.[\\nullfont]' */
   598  	fontIdBase = frozenNullFont - fontBase
   599  	/* begins table of 257 permanent font identifiers */
   600  	undefinedControlSequence  = frozenNullFont + 257         /* dummy location */
   601  	glueBase                  = undefinedControlSequence + 1 /* beginning of region 3 */
   602  	lineSkipCode              = 0                            /* interline glue if |baseline_skip| is infeasible */
   603  	baselineSkipCode          = 1                            /* desired glue between baselines */
   604  	parSkipCode               = 2                            /* extra glue just above a paragraph */
   605  	aboveDisplaySkipCode      = 3                            /* extra glue just above displayed math */
   606  	belowDisplaySkipCode      = 4                            /* extra glue just below displayed math */
   607  	aboveDisplayShortSkipCode = 5
   608  	/* glue above displayed math following short lines */
   609  	belowDisplayShortSkipCode = 6
   610  	/* glue below displayed math following short lines */
   611  	leftSkipCode     = 7                   /* glue at left of justified lines */
   612  	rightSkipCode    = 8                   /* glue at right of justified lines */
   613  	topSkipCode      = 9                   /* glue at top of main pages */
   614  	splitTopSkipCode = 10                  /* glue at top of split pages */
   615  	tabSkipCode      = 11                  /* glue between aligned entries */
   616  	spaceSkipCode    = 12                  /* glue between words (if not |zero_glue|) */
   617  	xspaceSkipCode   = 13                  /* glue after sentences (if not |zero_glue|) */
   618  	parFillSkipCode  = 14                  /* glue on last line of paragraph */
   619  	thinMuSkipCode   = 15                  /* thin space in math formula */
   620  	medMuSkipCode    = 16                  /* medium space in math formula */
   621  	thickMuSkipCode  = 17                  /* thick space in math formula */
   622  	gluePars         = 18                  /* total number of glue parameters */
   623  	skipBase         = glueBase + gluePars /* table of 256 ``skip'' registers */
   624  	muSkipBase       = skipBase + 256      /* table of 256 ``muskip'' registers */
   625  	localBase        = muSkipBase + 256    /* beginning of region 4 */
   626  	parShapeLoc      = localBase           /* specifies paragraph shape */
   627  	outputRoutineLoc = localBase + 1       /* points to token list for \.[\\output] */
   628  	everyParLoc      = localBase + 2       /* points to token list for \.[\\everypar] */
   629  	everyMathLoc     = localBase + 3       /* points to token list for \.[\\everymath] */
   630  	everyDisplayLoc  = localBase + 4       /* points to token list for \.[\\everydisplay] */
   631  	everyHboxLoc     = localBase + 5       /* points to token list for \.[\\everyhbox] */
   632  	everyVboxLoc     = localBase + 6       /* points to token list for \.[\\everyvbox] */
   633  	everyJobLoc      = localBase + 7       /* points to token list for \.[\\everyjob] */
   634  	everyCrLoc       = localBase + 8       /* points to token list for \.[\\everycr] */
   635  	errHelpLoc       = localBase + 9       /* points to token list for \.[\\errhelp] */
   636  	toksBase         = localBase + 10      /* table of 256 token list registers */
   637  	boxBase          = toksBase + 256      /* table of 256 box registers */
   638  	curFontLoc       = boxBase + 256       /* internal font number outside math mode */
   639  	mathFontBase     = curFontLoc + 1      /* table of 48 math font numbers */
   640  	catCodeBase      = mathFontBase + 48
   641  	/* table of 256 command codes (the ``catcodes'') */
   642  	lcCodeBase              = catCodeBase + 256  /* table of 256 lowercase mappings */
   643  	ucCodeBase              = lcCodeBase + 256   /* table of 256 uppercase mappings */
   644  	sfCodeBase              = ucCodeBase + 256   /* table of 256 spacefactor mappings */
   645  	mathCodeBase            = sfCodeBase + 256   /* table of 256 math mode mappings */
   646  	intBase                 = mathCodeBase + 256 /* beginning of region 5 */
   647  	pretoleranceCode        = 0                  /* badness tolerance before hyphenation */
   648  	toleranceCode           = 1                  /* badness tolerance after hyphenation */
   649  	linePenaltyCode         = 2                  /* added to the badness of every line */
   650  	hyphenPenaltyCode       = 3                  /* penalty for break after discretionary hyphen */
   651  	exHyphenPenaltyCode     = 4                  /* penalty for break after explicit hyphen */
   652  	clubPenaltyCode         = 5                  /* penalty for creating a club line */
   653  	widowPenaltyCode        = 6                  /* penalty for creating a widow line */
   654  	displayWidowPenaltyCode = 7                  /* ditto, just before a display */
   655  	brokenPenaltyCode       = 8                  /* penalty for breaking a page at a broken line */
   656  	binOpPenaltyCode        = 9                  /* penalty for breaking after a binary operation */
   657  	relPenaltyCode          = 10                 /* penalty for breaking after a relation */
   658  	preDisplayPenaltyCode   = 11
   659  	/* penalty for breaking just before a displayed formula */
   660  	postDisplayPenaltyCode = 12
   661  	/* penalty for breaking just after a displayed formula */
   662  	interLinePenaltyCode     = 13                /* additional penalty between lines */
   663  	doubleHyphenDemeritsCode = 14                /* demerits for double hyphen break */
   664  	finalHyphenDemeritsCode  = 15                /* demerits for final hyphen break */
   665  	adjDemeritsCode          = 16                /* demerits for adjacent incompatible lines */
   666  	magCode                  = 17                /* magnification ratio */
   667  	delimiterFactorCode      = 18                /* ratio for variable-size delimiters */
   668  	loosenessCode            = 19                /* change in number of lines for a paragraph */
   669  	timeCode                 = 20                /* current time of day */
   670  	dayCode                  = 21                /* current day of the month */
   671  	monthCode                = 22                /* current month of the year */
   672  	yearCode                 = 23                /* current year of our Lord */
   673  	showBoxBreadthCode       = 24                /* nodes per level in |show_box| */
   674  	showBoxDepthCode         = 25                /* maximum level in |show_box| */
   675  	hbadnessCode             = 26                /* hboxes exceeding this badness will be shown by |hpack| */
   676  	vbadnessCode             = 27                /* vboxes exceeding this badness will be shown by |vpack| */
   677  	pausingCode              = 28                /* pause after each line is read from a file */
   678  	tracingOnlineCode        = 29                /* show diagnostic output on terminal */
   679  	tracingMacrosCode        = 30                /* show macros as they are being expanded */
   680  	tracingStatsCode         = 31                /* show memory usage if \TeX\ knows it */
   681  	tracingParagraphsCode    = 32                /* show line-break calculations */
   682  	tracingPagesCode         = 33                /* show page-break calculations */
   683  	tracingOutputCode        = 34                /* show boxes when they are shipped out */
   684  	tracingLostCharsCode     = 35                /* show characters that aren't in the font */
   685  	tracingCommandsCode      = 36                /* show command codes at |big_switch| */
   686  	tracingRestoresCode      = 37                /* show equivalents when they are restored */
   687  	ucHyphCode               = 38                /* hyphenate words beginning with a capital letter */
   688  	outputPenaltyCode        = 39                /* penalty found at current page break */
   689  	maxDeadCyclesCode        = 40                /* bound on consecutive dead cycles of output */
   690  	hangAfterCode            = 41                /* hanging indentation changes after this many lines */
   691  	floatingPenaltyCode      = 42                /* penalty for insertions held over after a split */
   692  	globalDefsCode           = 43                /* override \.[\\global] specifications */
   693  	curFamCode               = 44                /* current family */
   694  	escapeCharCode           = 45                /* escape character for token output */
   695  	defaultHyphenCharCode    = 46                /* value of \.[\\hyphenchar] when a font is loaded */
   696  	defaultSkewCharCode      = 47                /* value of \.[\\skewchar] when a font is loaded */
   697  	endLineCharCode          = 48                /* character placed at the right end of the buffer */
   698  	newLineCharCode          = 49                /* character that prints as |print_ln| */
   699  	languageCode             = 50                /* current hyphenation table */
   700  	leftHyphenMinCode        = 51                /* minimum left hyphenation fragment size */
   701  	rightHyphenMinCode       = 52                /* minimum right hyphenation fragment size */
   702  	holdingInsertsCode       = 53                /* do not remove insertion nodes from \.[\\box255] */
   703  	errorContextLinesCode    = 54                /* maximum intermediate line pairs shown */
   704  	intPars                  = 55                /* total number of integer parameters */
   705  	countBase                = intBase + intPars /* 256 user \.[\\count] registers */
   706  	delCodeBase              = countBase + 256   /* 256 delimiter code mappings */
   707  	dimenBase                = delCodeBase + 256 /* beginning of region 6 */
   708  	parIndentCode            = 0                 /* indentation of paragraphs */
   709  	mathSurroundCode         = 1                 /* space around math in text */
   710  	lineSkipLimitCode        = 2                 /* threshold for |line_skip| instead of |baseline_skip| */
   711  	hsizeCode                = 3                 /* line width in horizontal mode */
   712  	vsizeCode                = 4                 /* page height in vertical mode */
   713  	maxDepthCode             = 5                 /* maximum depth of boxes on main pages */
   714  	splitMaxDepthCode        = 6                 /* maximum depth of boxes on split pages */
   715  	boxMaxDepthCode          = 7                 /* maximum depth of explicit vboxes */
   716  	hfuzzCode                = 8                 /* tolerance for overfull hbox messages */
   717  	vfuzzCode                = 9                 /* tolerance for overfull vbox messages */
   718  	delimiterShortfallCode   = 10                /* maximum amount uncovered by variable delimiters */
   719  	nullDelimiterSpaceCode   = 11                /* blank space in null delimiters */
   720  	scriptSpaceCode          = 12                /* extra space after subscript or superscript */
   721  	preDisplaySizeCode       = 13                /* length of text preceding a display */
   722  	displayWidthCode         = 14                /* length of line for displayed equation */
   723  	displayIndentCode        = 15                /* indentation of line for displayed equation */
   724  	overfullRuleCode         = 16                /* width of rule that identifies overfull hboxes */
   725  	hangIndentCode           = 17                /* amount of hanging indentation */
   726  	hOffsetCode              = 18                /* amount of horizontal offset when shipping pages out */
   727  	vOffsetCode              = 19                /* amount of vertical offset when shipping pages out */
   728  	emergencyStretchCode     = 20                /* reduces badnesses on final pass of line-breaking */
   729  	dimenPars                = 21                /* total number of dimension parameters */
   730  	scaledBase               = dimenBase + dimenPars
   731  	/* table of 256 user-defined \.[\\dimen] registers */
   732  	eqtbSize              = scaledBase + 255 /* largest subscript of |eqtb| */
   733  	restoreOldValue       = 0                /* |save_type| when a value should be restored later */
   734  	restoreZero           = 1                /* |save_type| when an undefined entry should be restored */
   735  	insertToken           = 2                /* |save_type| when a token is being saved for later use */
   736  	levelBoundary         = 3                /* |save_type| corresponding to beginning of group */
   737  	bottomLevel           = 0                /* group code for the outside world */
   738  	simpleGroup           = 1                /* group code for local structure only */
   739  	hboxGroup             = 2                /* code for `\.[\\hbox]\grp' */
   740  	adjustedHboxGroup     = 3                /* code for `\.[\\hbox]\grp' in vertical mode */
   741  	vboxGroup             = 4                /* code for `\.[\\vbox]\grp' */
   742  	vtopGroup             = 5                /* code for `\.[\\vtop]\grp' */
   743  	alignGroup            = 6                /* code for `\.[\\halign]\grp', `\.[\\valign]\grp' */
   744  	noAlignGroup          = 7                /* code for `\.[\\noalign]\grp' */
   745  	outputGroup           = 8                /* code for output routine */
   746  	mathGroup             = 9                /* code for, e.g., `\.[\char'136]\grp' */
   747  	discGroup             = 10               /* code for `\.[\\discretionary]\grp\grp\grp' */
   748  	insertGroup           = 11               /* code for `\.[\\insert]\grp', `\.[\\vadjust]\grp' */
   749  	vcenterGroup          = 12               /* code for `\.[\\vcenter]\grp' */
   750  	mathChoiceGroup       = 13               /* code for `\.[\\mathchoice]\grp\grp\grp\grp' */
   751  	semiSimpleGroup       = 14               /* code for `\.[\\begingroup...\\endgroup]' */
   752  	mathShiftGroup        = 15               /* code for `\.[\$...\$]' */
   753  	mathLeftGroup         = 16               /* code for `\.[\\left...\\right]' */
   754  	maxGroupCode          = 16
   755  	leftBraceToken        = 0400                          /* $2^8\cdot|left_brace|$ */
   756  	leftBraceLimit        = 01000                         /* $2^8\cdot(|left_brace|+1)$ */
   757  	rightBraceToken       = 01000                         /* $2^8\cdot|right_brace|$ */
   758  	rightBraceLimit       = 01400                         /* $2^8\cdot(|right_brace|+1)$ */
   759  	mathShiftToken        = 01400                         /* $2^8\cdot|math_shift|$ */
   760  	tabToken              = 02000                         /* $2^8\cdot|tab_mark|$ */
   761  	outParamToken         = 02400                         /* $2^8\cdot|out_param|$ */
   762  	spaceToken            = 05040                         /* $2^8\cdot|spacer|+|" "|$ */
   763  	letterToken           = 05400                         /* $2^8\cdot|letter|$ */
   764  	otherToken            = 06000                         /* $2^8\cdot|other_char|$ */
   765  	matchToken            = 06400                         /* $2^8\cdot|match|$ */
   766  	endMatchToken         = 07000                         /* $2^8\cdot|end_match|$ */
   767  	midLine               = 1                             /* |state| code when scanning a line of characters */
   768  	skipBlanks            = 2 + maxCharCode               /* |state| code when ignoring blanks */
   769  	newLine               = 3 + maxCharCode + maxCharCode /* |state| code at start of line */
   770  	skipping              = 1                             /* |scanner_status| when passing conditional text */
   771  	defining              = 2                             /* |scanner_status| when reading a macro definition */
   772  	matching              = 3                             /* |scanner_status| when reading macro arguments */
   773  	aligning              = 4                             /* |scanner_status| when reading an alignment preamble */
   774  	absorbing             = 5                             /* |scanner_status| when reading a balanced text */
   775  	tokenList             = 0                             /* |state| code when scanning a token list */
   776  	parameter             = 0                             /* |token_type| code for parameter */
   777  	uTemplate             = 1                             /* |token_type| code for \<u_j> template */
   778  	vTemplate             = 2                             /* |token_type| code for \<v_j> template */
   779  	backedUp              = 3                             /* |token_type| code for text to be reread */
   780  	inserted              = 4                             /* |token_type| code for inserted texts */
   781  	macro                 = 5                             /* |token_type| code for defined control sequences */
   782  	outputText            = 6                             /* |token_type| code for output routines */
   783  	everyParText          = 7                             /* |token_type| code for \.[\\everypar] */
   784  	everyMathText         = 8                             /* |token_type| code for \.[\\everymath] */
   785  	everyDisplayText      = 9                             /* |token_type| code for \.[\\everydisplay] */
   786  	everyHboxText         = 10                            /* |token_type| code for \.[\\everyhbox] */
   787  	everyVboxText         = 11                            /* |token_type| code for \.[\\everyvbox] */
   788  	everyJobText          = 12                            /* |token_type| code for \.[\\everyjob] */
   789  	everyCrText           = 13                            /* |token_type| code for \.[\\everycr] */
   790  	markText              = 14                            /* |token_type| code for \.[\\topmark], etc. */
   791  	writeText             = 15                            /* |token_type| code for \.[\\write] */
   792  	switch1               = 25                            /* a label in |get_next| */
   793  	startCs               = 26                            /* another */
   794  	noExpandFlag          = 257                           /* this characterizes a special variant of |relax| */
   795  	topMarkCode           = 0                             /* the mark in effect at the previous page break */
   796  	firstMarkCode         = 1                             /* the first mark between |top_mark| and |bot_mark| */
   797  	botMarkCode           = 2                             /* the mark in effect at the current page break */
   798  	splitFirstMarkCode    = 3                             /* the first mark found by \.[\\vsplit] */
   799  	splitBotMarkCode      = 4                             /* the last mark found by \.[\\vsplit] */
   800  	intVal                = 0                             /* integer values */
   801  	dimenVal              = 1                             /* dimension values */
   802  	glueVal               = 2                             /* glue specifications */
   803  	muVal                 = 3                             /* math glue specifications */
   804  	identVal              = 4                             /* font identifier */
   805  	tokVal                = 5                             /* token lists */
   806  	inputLineNoCode       = glueVal + 1                   /* code for \.[\\inputlineno] */
   807  	badnessCode           = glueVal + 2                   /* code for \.[\\badness] */
   808  	octalToken            = otherToken + '\''             /* apostrophe, indicates an octal constant */
   809  	hexToken              = otherToken + '"'              /* double quote, indicates a hex constant */
   810  	alphaToken            = otherToken + '`'              /* reverse apostrophe, precedes alpha constants */
   811  	pointToken            = otherToken + '.'              /* decimal point */
   812  	continentalPointToken = otherToken + ','              /* decimal point, Eurostyle */
   813  	zeroToken             = otherToken + '0'              /* zero, the smallest digit */
   814  	aToken                = letterToken + 'A'             /* the smallest special hex digit */
   815  	otherAToken           = otherToken + 'A'              /* special hex digit of type |other_char| */
   816  	attachFraction        = 88                            /* go here to pack |cur_val| and |f| into |cur_val| */
   817  	attachSign            = 89                            /* go here when |cur_val| is correct except perhaps for sign */
   818  	defaultRule           = 26214                         /* 0.4\thinspace pt */
   819  	numberCode            = 0                             /* command code for \.[\\number] */
   820  	romanNumeralCode      = 1                             /* command code for \.[\\romannumeral] */
   821  	stringCode            = 2                             /* command code for \.[\\string] */
   822  	meaningCode           = 3                             /* command code for \.[\\meaning] */
   823  	fontNameCode          = 4                             /* command code for \.[\\fontname] */
   824  	jobNameCode           = 5                             /* command code for \.[\\jobname] */
   825  	closed                = 2                             /* not open, or at end of file */
   826  	justOpen              = 1                             /* newly opened, first line not yet read */
   827  	ifCharCode            = 0                             /* `\.[\\if]'  */
   828  	ifCatCode             = 1                             /* `\.[\\ifcat]'  */
   829  	ifIntCode             = 2                             /* `\.[\\ifnum]'  */
   830  	ifDimCode             = 3                             /* `\.[\\ifdim]'  */
   831  	ifOddCode             = 4                             /* `\.[\\ifodd]'  */
   832  	ifVmodeCode           = 5                             /* `\.[\\ifvmode]'  */
   833  	ifHmodeCode           = 6                             /* `\.[\\ifhmode]'  */
   834  	ifMmodeCode           = 7                             /* `\.[\\ifmmode]'  */
   835  	ifInnerCode           = 8                             /* `\.[\\ifinner]'  */
   836  	ifVoidCode            = 9                             /* `\.[\\ifvoid]'  */
   837  	ifHboxCode            = 10                            /* `\.[\\ifhbox]'  */
   838  	ifVboxCode            = 11                            /* `\.[\\ifvbox]'  */
   839  	ifxCode               = 12                            /* `\.[\\ifx]'  */
   840  	ifEofCode             = 13                            /* `\.[\\ifeof]'  */
   841  	ifTrueCode            = 14                            /* `\.[\\iftrue]'  */
   842  	ifFalseCode           = 15                            /* `\.[\\iffalse]'  */
   843  	ifCaseCode            = 16                            /* `\.[\\ifcase]'  */
   844  	ifNodeSize            = 2                             /* number of words in stack entry for conditionals */
   845  	ifCode                = 1                             /* code for \.[\\if...] being evaluated */
   846  	fiCode                = 2                             /* code for \.[\\fi] */
   847  	elseCode              = 3                             /* code for \.[\\else] */
   848  	orCode                = 4                             /* code for \.[\\or] */
   849  	formatDefaultLength   = 20                            /* length of the |TEX_format_default| string */
   850  	formatAreaLength      = 11                            /* length of its area part */
   851  	formatExtLength       = 4                             /* length of its `\.[.fmt]' part */
   852  	formatExtension       = /* ".fmt" */ 786              /* the extension, as a \.[WEB] constant */
   853  	noTag                 = 0                             /* vanilla character */
   854  	ligTag                = 1                             /* character has a ligature/kerning program */
   855  	listTag               = 2                             /* character has a successor in a charlist */
   856  	extTag                = 3                             /* character is extensible */
   857  	slantCode             = 1
   858  	spaceCode             = 2
   859  	spaceStretchCode      = 3
   860  	spaceShrinkCode       = 4
   861  	xHeightCode           = 5
   862  	quadCode              = 6
   863  	extraSpaceCode        = 7
   864  	nonAddress            = 0                /* a spurious |bchar_label| */
   865  	badTfm                = 11               /* label for |read_font_info| */
   866  	setChar0              = 0                /* typeset character 0 and move right */
   867  	set1                  = 128              /* typeset a character and move right */
   868  	setRule               = 132              /* typeset a rule and move right */
   869  	putRule               = 137              /* typeset a rule */
   870  	nop                   = 138              /* no operation */
   871  	bop                   = 139              /* beginning of page */
   872  	eop                   = 140              /* ending of page */
   873  	push                  = 141              /* save the current positions */
   874  	pop                   = 142              /* restore previous positions */
   875  	right1                = 143              /* move right */
   876  	w0                    = 147              /* move right by |w| */
   877  	w1                    = 148              /* move right and set |w| */
   878  	x0                    = 152              /* move right by |x| */
   879  	x1                    = 153              /* move right and set |x| */
   880  	down1                 = 157              /* move down */
   881  	y0                    = 161              /* move down by |y| */
   882  	y1                    = 162              /* move down and set |y| */
   883  	z0                    = 166              /* move down by |z| */
   884  	z1                    = 167              /* move down and set |z| */
   885  	fntNum0               = 171              /* set current font to 0 */
   886  	fnt1                  = 235              /* set current font */
   887  	xxx1                  = 239              /* extension to \.[DVI] primitives */
   888  	xxx4                  = 242              /* potentially long extension to \.[DVI] primitives */
   889  	fntDef1               = 243              /* define the meaning of a font number */
   890  	pre                   = 247              /* preamble */
   891  	post                  = 248              /* postamble beginning */
   892  	postPost              = 249              /* postamble ending */
   893  	idByte                = 2                /* identifies the kind of \.[DVI] files described here */
   894  	movementNodeSize      = 3                /* number of words per entry in the down and right stacks */
   895  	yHere                 = 1                /* |info| when the movement entry points to a |y| command */
   896  	zHere                 = 2                /* |info| when the movement entry points to a |z| command */
   897  	yzOk                  = 3                /* |info| corresponding to an unconstrained \\[down] command */
   898  	yOk                   = 4                /* |info| corresponding to a \\[down] that can't become a |z| */
   899  	zOk                   = 5                /* |info| corresponding to a \\[down] that can't become a |y| */
   900  	dFixed                = 6                /* |info| corresponding to a \\[down] that can't change */
   901  	noneSeen              = 0                /* no |y_here| or |z_here| nodes have been encountered yet */
   902  	ySeen                 = 6                /* we have seen |y_here| but not |z_here| */
   903  	zSeen                 = 12               /* we have seen |z_here| but not |y_here| */
   904  	movePast              = 13               /* go to this label when advancing past glue or a rule */
   905  	finRule               = 14               /* go to this label to finish processing a rule */
   906  	nextP                 = 15               /* go to this label when finished with node |p| */
   907  	exactly               = 0                /* a box dimension is pre-specified */
   908  	additional            = 1                /* a box dimension is increased from the natural one */
   909  	noadSize              = 4                /* number of words in a normal noad */
   910  	mathChar              = 1                /* |math_type| when the attribute is simple */
   911  	subBox                = 2                /* |math_type| when the attribute is a box */
   912  	subMlist              = 3                /* |math_type| when the attribute is a formula */
   913  	mathTextChar          = 4                /* |math_type| when italic correction is dubious */
   914  	ordNoad               = unsetNode + 3    /* |type| of a noad classified Ord */
   915  	opNoad                = ordNoad + 1      /* |type| of a noad classified Op */
   916  	binNoad               = ordNoad + 2      /* |type| of a noad classified Bin */
   917  	relNoad               = ordNoad + 3      /* |type| of a noad classified Rel */
   918  	openNoad              = ordNoad + 4      /* |type| of a noad classified Open */
   919  	closeNoad             = ordNoad + 5      /* |type| of a noad classified Close */
   920  	punctNoad             = ordNoad + 6      /* |type| of a noad classified Punct */
   921  	innerNoad             = ordNoad + 7      /* |type| of a noad classified Inner */
   922  	limits                = 1                /* |subtype| of |op_noad| whose scripts are to be above, below */
   923  	noLimits              = 2                /* |subtype| of |op_noad| whose scripts are to be normal */
   924  	radicalNoad           = innerNoad + 1    /* |type| of a noad for square roots */
   925  	radicalNoadSize       = 5                /* number of |mem| words in a radical noad */
   926  	fractionNoad          = radicalNoad + 1  /* |type| of a noad for generalized fractions */
   927  	fractionNoadSize      = 6                /* number of |mem| words in a fraction noad */
   928  	underNoad             = fractionNoad + 1 /* |type| of a noad for underlining */
   929  	overNoad              = underNoad + 1    /* |type| of a noad for overlining */
   930  	accentNoad            = overNoad + 1     /* |type| of a noad for accented subformulas */
   931  	accentNoadSize        = 5                /* number of |mem| words in an accent noad */
   932  	vcenterNoad           = accentNoad + 1   /* |type| of a noad for \.[\\vcenter] */
   933  	leftNoad              = vcenterNoad + 1  /* |type| of a noad for \.[\\left] */
   934  	rightNoad             = leftNoad + 1     /* |type| of a noad for \.[\\right] */
   935  	styleNode             = unsetNode + 1    /* |type| of a style node */
   936  	styleNodeSize         = 3                /* number of words in a style node */
   937  	displayStyle          = 0                /* |subtype| for \.[\\displaystyle] */
   938  	textStyle             = 2                /* |subtype| for \.[\\textstyle] */
   939  	scriptStyle           = 4                /* |subtype| for \.[\\scriptstyle] */
   940  	scriptScriptStyle     = 6                /* |subtype| for \.[\\scriptscriptstyle] */
   941  	cramped               = 1                /* add this to an uncramped style if you want to cramp it */
   942  	choiceNode            = unsetNode + 2    /* |type| of a choice node */
   943  	textSize              = 0                /* size code for the largest size in a family */
   944  	scriptSize            = 16               /* size code for the medium size in a family */
   945  	scriptScriptSize      = 32               /* size code for the smallest size in a family */
   946  	totalMathsyParams     = 22
   947  	totalMathexParams     = 13
   948  	doneWithNoad          = 80 /* go here when a noad has been fully translated */
   949  	doneWithNode          = 81 /* go here when a node has been fully converted */
   950  	checkDimensions       = 82 /* go here to update |max_h| and |max_d| */
   951  	deleteQ               = 83 /* go here to delete |q| and move to the next node */
   952  	mathSpacing           =
   953  
   954  	// \hskip-35pt
   955  	/* "0234000122*4000133**3**344*0400400*000000234000111*1111112341011" */ 892
   956  	/* $ \hskip-35pt$  */
   957  	alignStackNodeSize = 5          /* number of |mem| words to save alignment states */
   958  	spanCode           = 256        /* distinct from any character */
   959  	crCode             = 257        /* distinct from |span_code| and from any character */
   960  	crCrCode           = crCode + 1 /* this distinguishes \.[\\crcr] from \.[\\cr] */
   961  	spanNodeSize       = 2          /* number of |mem| words for a span node */
   962  	tightFit           = 3          // fitness classification for lines shrinking 0.5 to 1.0 of their
   963  	//   shrinkability
   964  
   965  	looseFit = 1 // fitness classification for lines stretching 0.5 to 1.0 of their
   966  	//   stretchability
   967  
   968  	veryLooseFit = 0 // fitness classification for lines stretching more than
   969  	//   their stretchability
   970  
   971  	decentFit       = 2  /* fitness classification for all other lines */
   972  	activeNodeSize  = 3  /* number of words in active nodes */
   973  	unhyphenated    = 0  /* the |type| of a normal active break node */
   974  	hyphenated      = 1  /* the |type| of an active node that breaks at a |disc_node| */
   975  	passiveNodeSize = 2  /* number of words in passive nodes */
   976  	deltaNodeSize   = 7  /* number of words in a delta node */
   977  	deltaNode       = 2  /* |type| field in a delta node */
   978  	deactivate      = 60 /* go here when node |r| should be deactivated */
   979  	updateHeights   = 90 /* go here to record glue in the |active_height| table */
   980  	insertsOnly     = 1
   981  	/* |page_contents| when an insert node has been contributed, but no boxes */
   982  	boxThere          = 2    /* |page_contents| when a box or rule has been contributed */
   983  	pageInsNodeSize   = 4    /* number of words for a page insertion node */
   984  	inserting         = 0    /* an insertion class that has not yet overflowed */
   985  	splitUp           = 1    /* an overflowed insertion class */
   986  	contribute        = 80   /* go here to link a node into the current page */
   987  	bigSwitch         = 60   /* go here to branch on the next token of input */
   988  	mainLoop          = 70   /* go here to typeset a string of consecutive characters */
   989  	mainLoopWrapup    = 80   /* go here to finish a character or ligature */
   990  	mainLoopMove      = 90   /* go here to advance the ligature cursor */
   991  	mainLoopMoveLig   = 95   /* same, when advancing past a generated ligature */
   992  	mainLoopLookahead = 100  /* go here to bring in another character, if any */
   993  	mainLigLoop       = 110  /* go here to check for ligatures or kerning */
   994  	appendNormalSpace = 120  /* go here to append a normal space between words */
   995  	filCode           = 0    /* identifies \.[\\hfil] and \.[\\vfil] */
   996  	fillCode          = 1    /* identifies \.[\\hfill] and \.[\\vfill] */
   997  	ssCode            = 2    /* identifies \.[\\hss] and \.[\\vss] */
   998  	filNegCode        = 3    /* identifies \.[\\hfilneg] and \.[\\vfilneg] */
   999  	skipCode          = 4    /* identifies \.[\\hskip] and \.[\\vskip] */
  1000  	mskipCode         = 5    /* identifies \.[\\mskip] */
  1001  	boxCode           = 0    /* |chr_code| for `\.[\\box]' */
  1002  	copyCode          = 1    /* |chr_code| for `\.[\\copy]' */
  1003  	lastBoxCode       = 2    /* |chr_code| for `\.[\\lastbox]' */
  1004  	vsplitCode        = 3    /* |chr_code| for `\.[\\vsplit]' */
  1005  	vtopCode          = 4    /* |chr_code| for `\.[\\vtop]' */
  1006  	aboveCode         = 0    /* `\.[\\above]'  */
  1007  	overCode          = 1    /* `\.[\\over]'  */
  1008  	atopCode          = 2    /* `\.[\\atop]'  */
  1009  	delimitedCode     = 3    /* `\.[\\abovewithdelims]', etc. */
  1010  	charDefCode       = 0    /* |shorthand_def| for \.[\\chardef] */
  1011  	mathCharDefCode   = 1    /* |shorthand_def| for \.[\\mathchardef] */
  1012  	countDefCode      = 2    /* |shorthand_def| for \.[\\countdef] */
  1013  	dimenDefCode      = 3    /* |shorthand_def| for \.[\\dimendef] */
  1014  	skipDefCode       = 4    /* |shorthand_def| for \.[\\skipdef] */
  1015  	muSkipDefCode     = 5    /* |shorthand_def| for \.[\\muskipdef] */
  1016  	toksDefCode       = 6    /* |shorthand_def| for \.[\\toksdef] */
  1017  	showCode          = 0    /* \.[\\show]  */
  1018  	showBoxCode       = 1    /* \.[\\showbox]  */
  1019  	showTheCode       = 2    /* \.[\\showthe]  */
  1020  	showListsCode     = 3    /* \.[\\showlists]  */
  1021  	badFmt            = 6666 /* go here if the format file is unacceptable */
  1022  	breakpoint        = 888  /* place where a breakpoint is desirable */
  1023  	writeNodeSize     = 2    /* number of words in a write/whatsit node */
  1024  	openNodeSize      = 3    /* number of words in an open/whatsit node */
  1025  	openNode          = 0    /* |subtype| in whatsits that represent files to \.[\\openout] */
  1026  	writeNode         = 1    /* |subtype| in whatsits that represent things to \.[\\write] */
  1027  	closeNode         = 2    /* |subtype| in whatsits that represent streams to \.[\\closeout] */
  1028  	specialNode       = 3    /* |subtype| in whatsits that represent \.[\\special] things */
  1029  	languageNode      = 4    /* |subtype| in whatsits that change the current language */
  1030  	immediateCode     = 4    /* command modifier for \.[\\immediate] */
  1031  	setLanguageCode   = 5    /* command modifier for \.[\\setlanguage] */
  1032  
  1033  	// Constants in the outer block
  1034  	memMax = 30000 // greatest index in \TeX's internal |mem| array;
  1035  	//   must be strictly less than |max_halfword|;
  1036  	//   must be equal to |mem_top| in \.[INITEX], otherwise |>=mem_top|
  1037  
  1038  	memMin = 0 // smallest index in \TeX's internal |mem| array;
  1039  	//   must be |min_halfword| or more;
  1040  	//   must be equal to |mem_bot| in \.[INITEX], otherwise |<=mem_bot|
  1041  
  1042  	bufSize = 500 // maximum number of characters simultaneously present in
  1043  	//   current lines of open files and in control sequences between
  1044  	//   \.[\\csname] and \.[\\endcsname]; must not exceed |max_halfword|
  1045  
  1046  	errorLine     = 72 // width of context lines on terminal error messages
  1047  	halfErrorLine = 42 // width of first lines of contexts in terminal
  1048  	//   error messages; should be between 30 and |error_line-15|
  1049  
  1050  	maxPrintLine = 79  // width of longest text lines output; should be at least 60
  1051  	stackSize    = 200 // maximum number of simultaneous input sources
  1052  	maxInOpen    = 6   // maximum number of input files and error insertions that
  1053  	//   can be going on simultaneously
  1054  
  1055  	fontMax = 75 // maximum internal font number; must not exceed |max_quarterword|
  1056  	//   and must be at most |font_base+256|
  1057  
  1058  	fontMemSize     = 20000 // number of words of |font_info| for all fonts
  1059  	paramSize       = 60    // maximum number of simultaneous macro parameters
  1060  	nestSize        = 40    // maximum number of semantic levels simultaneously active
  1061  	maxStrings      = 3000  // maximum number of strings; must not exceed |max_halfword|
  1062  	stringVacancies = 8000  // the minimum number of characters that should be
  1063  	//   available for the user's control sequences and font names,
  1064  	//   after \TeX's own error messages are stored
  1065  
  1066  	poolSize = 32000 // maximum number of characters in strings, including all
  1067  	//   error messages and help texts, and the names of all fonts and
  1068  	//   control sequences; must exceed |string_vacancies| by the total
  1069  	//   length of \TeX's own strings, which is currently about 23000
  1070  
  1071  	saveSize = 600 // space for saving values outside of current group; must be
  1072  	//   at most |max_halfword|
  1073  
  1074  	trieSize = 8000 // space for hyphenation patterns; should be larger for
  1075  	//   \.[INITEX] than it is in production versions of \TeX
  1076  
  1077  	trieOpSize   = 500 // space for ``opcodes'' in the hyphenation patterns
  1078  	dviBufSize   = 800 // size of the output buffer; must be a multiple of 8
  1079  	fileNameSize = 40  // file names shouldn't be longer than this
  1080  	poolName     = "TeXformats:TEX.POOL                     "
  1081  
  1082  // string of length |file_name_size|; tells where the string pool appears
  1083  // \xref[TeXformats]
  1084  )
  1085  
  1086  type (
  1087  	// Types in the outer block
  1088  	asciiCode = /* 0..255 */ byte // eight-bit numbers
  1089  
  1090  	eightBits = /* 0..255 */ byte // unsigned one-byte quantity
  1091  	alphaFile = knuth.File        // files that contain textual data
  1092  	byteFile  = knuth.File        // files that contain binary data
  1093  
  1094  	poolPointer     = /* 0..poolSize */ uint16   // for variables that point into |str_pool|
  1095  	strNumber       = /* 0..maxStrings */ uint16 // for variables that point into |str_start|
  1096  	packedAsciiCode = /* 0..255 */ byte          // elements of |str_pool| array
  1097  
  1098  	scaled             = int32                        // this type is used for scaled integers
  1099  	nonnegativeInteger = /* 0..017777777777 */ uint32 // $0\L x<2^[31]$
  1100  	smallNumber        = /* 0..63 */ byte             // this type is self-explanatory
  1101  
  1102  	glueRatio = float64 // one-word representation of a glue expansion factor
  1103  
  1104  	quarterword  = /* minQuarterword..maxQuarterword */ byte // 1/4 of a word
  1105  	halfword     = /* 0..65535 */ uint16                     // 1/2 of a word
  1106  	twoChoices   = /* 1..2 */ byte                           // used when there are two variants in a record
  1107  	fourChoices  = /* 1..4 */ byte                           // used when there are four variants in a record
  1108  	twoHalves    struct{ data uint32 }
  1109  	fourQuarters = struct {
  1110  		b0 quarterword
  1111  		b1 quarterword
  1112  		b2 quarterword
  1113  		b3 quarterword
  1114  	}
  1115  	memoryWord struct{ data uint32 }
  1116  	wordFile   = knuth.File
  1117  
  1118  	glueOrd = /* normal..filll */ byte // infinity to the 0, 1, 2, or 3 power
  1119  
  1120  	listStateRecord = struct {
  1121  		modeField            int16
  1122  		headField, tailField halfword
  1123  		pgField, mlField     int32
  1124  		auxField             memoryWord
  1125  	}
  1126  
  1127  	groupCode = /* 0..maxGroupCode */ byte // |save_level| for a level boundary
  1128  
  1129  	inStateRecord = struct {
  1130  		stateField, indexField                      quarterword
  1131  		startField, locField, limitField, nameField halfword
  1132  	}
  1133  
  1134  	internalFontNumber = /* fontBase..fontMax */ byte // |font| in a |char_node|
  1135  	fontIndex          = /* 0..fontMemSize */ uint16  // index into |font_info|
  1136  
  1137  	dviIndex = /* 0..dviBufSize */ uint16 // an index into the output buffer
  1138  
  1139  	triePointer = /* 0..trieSize */ uint16 // an index into |trie|
  1140  
  1141  	hyphPointer = /* 0..hyphSize */ uint16 // an index into the ordered hash table
  1142  )
  1143  
  1144  func (r *memoryWord) gr() *float32 {
  1145  	return (*float32)(unsafe.Add(unsafe.Pointer(&r.data), 0))
  1146  }
  1147  
  1148  func (r *memoryWord) hh() *twoHalves {
  1149  	return (*twoHalves)(unsafe.Add(unsafe.Pointer(&r.data), 0))
  1150  }
  1151  
  1152  func (r *memoryWord) int() *int32 {
  1153  	return (*int32)(unsafe.Add(unsafe.Pointer(&r.data), 0))
  1154  }
  1155  
  1156  func (r *memoryWord) qqqq() *fourQuarters {
  1157  	return (*fourQuarters)(unsafe.Add(unsafe.Pointer(&r.data), 0))
  1158  }
  1159  
  1160  func (r *twoHalves) b0() *quarterword {
  1161  	return (*quarterword)(unsafe.Add(unsafe.Pointer(&r.data), 2))
  1162  }
  1163  
  1164  func (r *twoHalves) b1() *quarterword {
  1165  	return (*quarterword)(unsafe.Add(unsafe.Pointer(&r.data), 3))
  1166  }
  1167  
  1168  func (r *twoHalves) lh() *halfword {
  1169  	return (*halfword)(unsafe.Add(unsafe.Pointer(&r.data), 2))
  1170  }
  1171  
  1172  func (r *twoHalves) rh() *halfword {
  1173  	return (*halfword)(unsafe.Add(unsafe.Pointer(&r.data), 0))
  1174  }
  1175  
  1176  type prg struct {
  1177  	stdin, stdout, stderr knuth.File
  1178  	// Global variables
  1179  	bad int32 // is some ``constant'' wrong?
  1180  
  1181  	xord [256]asciiCode
  1182  	// specifies conversion of input characters
  1183  	xchr [256]char
  1184  	// specifies conversion of output characters
  1185  
  1186  	nameOfFile [40]char
  1187  
  1188  	// on some systems this may be a \&[record] variable
  1189  	nameLength/* 0..fileNameSize */ byte
  1190  	// this many characters are actually
  1191  	//   relevant in |name_of_file| (the rest are blank)
  1192  
  1193  	buffer                             [501]asciiCode // lines of characters being read
  1194  	first/* 0..bufSize */ uint16       // the first unused position in |buffer|
  1195  	last/* 0..bufSize */ uint16        // end of the line just input to |buffer|
  1196  	maxBufStack/* 0..bufSize */ uint16 // largest index used in |buffer|
  1197  
  1198  	termIn  alphaFile // the terminal as an input file
  1199  	termOut alphaFile // the terminal as an output file
  1200  
  1201  	strPool     [32001]packedAsciiCode // the characters
  1202  	strStart    [3001]poolPointer      // the starting pointers
  1203  	poolPtr     poolPointer            // first unused position in |str_pool|
  1204  	strPtr      strNumber              // number of the current string being created
  1205  	initPoolPtr poolPointer            // the starting value of |pool_ptr|
  1206  	initStrPtr  strNumber              // the starting value of |str_ptr|
  1207  
  1208  	poolFile alphaFile // the string-pool file output by \.[TANGLE]
  1209  
  1210  	logFile                           alphaFile // transcript of \TeX\ session
  1211  	selector/* 0..maxSelector */ byte // where to print a message
  1212  	dig                               [23] /* 0..15 */ byte // digits in a number being output
  1213  	tally                             int32                 // the number of characters recently printed
  1214  	termOffset/* 0..maxPrintLine */ byte
  1215  	// the number of characters on the current terminal line
  1216  	fileOffset/* 0..maxPrintLine */ byte
  1217  	// the number of characters on the current file line
  1218  	trickBuf [73]asciiCode // circular buffer for
  1219  	//   pseudoprinting
  1220  
  1221  	trickCount int32 // threshold for pseudoprinting, explained later
  1222  	firstCount int32 // another variable for pseudoprinting
  1223  
  1224  	interaction/* batchMode..errorStopMode */ byte // current level of interaction
  1225  
  1226  	deletionsAllowed                           bool // is it safe for |error| to call |get_token|?
  1227  	setBoxAllowed                              bool // is it safe to do a \.[\\setbox] assignment?
  1228  	history/* spotless..fatalErrorStop */ byte // has the source input been clean so far?
  1229  	errorCount/*  -1..100 */ int8              // the number of scrolled errors since the
  1230  	//   last paragraph ended
  1231  
  1232  	helpLine               [6]strNumber // helps for the next |error|
  1233  	helpPtr/* 0..6 */ byte // the number of help lines present
  1234  	useErrHelp             bool // should the |err_help| list be shown?
  1235  
  1236  	interrupt     int32 // should \TeX\ pause for instructions?
  1237  	okToInterrupt bool  // should interrupts be observed?
  1238  
  1239  	arithError bool   // has arithmetic overflow occurred recently?
  1240  	remainder  scaled // amount subtracted to get an exact division
  1241  
  1242  	tempPtr halfword // a pointer variable for occasional emergency use
  1243  
  1244  	mem      [30001]memoryWord // the big dynamic storage area
  1245  	loMemMax halfword          // the largest location of variable-size memory in use
  1246  	hiMemMin halfword          // the smallest location of one-word memory in use
  1247  
  1248  	varUsed, dynUsed int32 // how much memory is in use
  1249  
  1250  	avail  halfword // head of the list of available one-word nodes
  1251  	memEnd halfword // the last one-word node used in |mem|
  1252  
  1253  	rover halfword // points to some node in the list of empties
  1254  
  1255  	//   free: packed array [mem_min..mem_max] of boolean; [free cells]
  1256  	// [ \hskip10pt ] was_free: packed array [mem_min..mem_max] of boolean;
  1257  	//   [previously free cells]
  1258  	// [ \hskip10pt ] was_mem_end, was_lo_max, was_hi_min: halfword ;
  1259  	//   [previous |mem_end|, |lo_mem_max|, and |hi_mem_min|]
  1260  	// [ \hskip10pt ] panicking:boolean; [do we want to check memory constantly?]
  1261  	// [  ]
  1262  
  1263  	fontInShortDisplay int32 // an internal font number
  1264  
  1265  	depthThreshold int32 // maximum nesting depth in box displays
  1266  	breadthMax     int32 // maximum number of items shown at the same list level
  1267  
  1268  	nest                                [41]listStateRecord
  1269  	nestPtr/* 0..nestSize */ byte       // first unused location of |nest|
  1270  	maxNestStack/* 0..nestSize */ byte  // maximum of |nest_ptr| when pushing
  1271  	curList                             listStateRecord // the ``top'' semantic state
  1272  	shownMode/*  -mmode..mmode */ int16 // most recent mode shown by \.[\\tracingcommands]
  1273  
  1274  	oldSetting/* 0..maxSelector */ byte
  1275  	sysTime, sysDay, sysMonth, sysYear int32
  1276  	// date and time supplied by external system
  1277  
  1278  	eqtb     [6106]memoryWord
  1279  	xeqLevel [844]quarterword
  1280  
  1281  	hash [2367]twoHalves
  1282  	// the hash table
  1283  	hashUsed             halfword // allocation pointer for |hash|
  1284  	noNewControlSequence bool     // are new identifiers legal?
  1285  	csCount              int32    // total number of known identifiers
  1286  
  1287  	saveStack                            [601]memoryWord
  1288  	savePtr/* 0..saveSize */ uint16      // first unused entry on |save_stack|
  1289  	maxSaveStack/* 0..saveSize */ uint16 // maximum usage of save stack
  1290  	curLevel                             quarterword // current nesting level for groups
  1291  	curGroup                             groupCode   // current group type
  1292  	curBoundary/* 0..saveSize */ uint16  // where the current level begins
  1293  
  1294  	magSet int32 // if nonzero, this magnification should be used henceforth
  1295  
  1296  	curCmd eightBits // current command set by |get_next|
  1297  	curChr halfword  // operand of current command
  1298  	curCs  halfword  // control sequence found here, zero if none found
  1299  	curTok halfword  // packed representative of |cur_cmd| and |cur_chr|
  1300  
  1301  	inputStack                        [201]inStateRecord
  1302  	inputPtr/* 0..stackSize */ byte   // first unused location of |input_stack|
  1303  	maxInStack/* 0..stackSize */ byte // largest value of |input_ptr| when pushing
  1304  	curInput                          inStateRecord
  1305  	// the ``top'' input state, according to convention (1)
  1306  
  1307  	inOpen/* 0..maxInOpen */ byte     // the number of lines in the buffer, less one
  1308  	openParens/* 0..maxInOpen */ byte // the number of open text files
  1309  	inputFile                         [6]alphaFile
  1310  	line                              int32 // current line number in the current source file
  1311  	lineStack                         [6]int32
  1312  
  1313  	scannerStatus/* normal..absorbing */ byte // can a subfile end now?
  1314  	warningIndex                              halfword // identifier relevant to non-|normal| scanner status
  1315  	defRef                                    halfword // reference count of token list being defined
  1316  
  1317  	paramStack [61]halfword
  1318  	// token list pointers for parameters
  1319  	paramPtr/* 0..paramSize */ byte // first unused entry in |param_stack|
  1320  	maxParamStack                   int32
  1321  	// largest value of |param_ptr|, will be |<=param_size+9|
  1322  
  1323  	alignState int32 // group level with respect to current alignment
  1324  
  1325  	basePtr/* 0..stackSize */ byte // shallowest level shown by |show_context|
  1326  
  1327  	parLoc   halfword // location of `\.[\\par]' in |eqtb|
  1328  	parToken halfword // token representing `\.[\\par]'
  1329  
  1330  	forceEof bool // should the next \.[\\input] be aborted early?
  1331  
  1332  	curMark [5]halfword
  1333  	// token lists for marks
  1334  
  1335  	longState/* call..longOuterCall */ byte // governs the acceptance of \.[\\par]
  1336  
  1337  	pstack [9]halfword // arguments supplied to a macro
  1338  
  1339  	curVal                               int32 // value returned by numeric scanners
  1340  	curValLevel/* intVal..tokVal */ byte // the ``level'' of this value
  1341  
  1342  	radix smallNumber // |scan_int| sets this to 8, 10, 16, or zero
  1343  
  1344  	curOrder glueOrd // order of infinity found by |scan_dimen|
  1345  
  1346  	readFile [16]alphaFile                  // used for \.[\\read]
  1347  	readOpen [17] /* normal..closed */ byte // state of |read_file[n]|
  1348  
  1349  	condPtr                          halfword // top of the condition stack
  1350  	ifLimit/* normal..orCode */ byte // upper bound on |fi_or_else| codes
  1351  	curIf                            smallNumber // type of conditional being worked on
  1352  	ifLine                           int32       // line where that conditional began
  1353  
  1354  	skipLine int32 // skipping began here
  1355  
  1356  	curName strNumber // name of file just scanned
  1357  	curArea strNumber // file area just scanned, or \.[""]
  1358  	curExt  strNumber // file extension just scanned, or \.[""]
  1359  
  1360  	areaDelimiter poolPointer // the most recent `\.>' or `\.:', if any
  1361  	extDelimiter  poolPointer // the relevant `\..', if any
  1362  
  1363  	texFormatDefault [20]char
  1364  
  1365  	nameInProgress bool      // is a file name being scanned?
  1366  	jobName        strNumber // principal file name
  1367  	logOpened      bool      // has the transcript file been opened?
  1368  
  1369  	dviFile        byteFile  // the device-independent output goes here
  1370  	outputFileName strNumber // full name of the output file
  1371  	logName        strNumber // full name of the log file
  1372  
  1373  	tfmFile byteFile
  1374  	buf     eightBits
  1375  
  1376  	fontInfo [20001]memoryWord
  1377  	// the big collection of font data
  1378  	fmemPtr    fontIndex          // first unused word of |font_info|
  1379  	fontPtr    internalFontNumber // largest internal font number in use
  1380  	fontCheck  [76]fourQuarters   // check sum
  1381  	fontSize   [76]scaled         // ``at'' size
  1382  	fontDsize  [76]scaled         // ``design'' size
  1383  	fontParams [76]fontIndex      // how many font
  1384  	//   parameters are present
  1385  
  1386  	fontName [76]strNumber // name of the font
  1387  	fontArea [76]strNumber // area of the font
  1388  	fontBc   [76]eightBits
  1389  	// beginning (smallest) character code
  1390  	fontEc [76]eightBits
  1391  	// ending (largest) character code
  1392  	fontGlue [76]halfword
  1393  	// glue specification for interword space, |null| if not allocated
  1394  	fontUsed [76]bool
  1395  	// has a character from this font actually appeared in the output?
  1396  	hyphenChar [76]int32
  1397  	// current \.[\\hyphenchar] values
  1398  	skewChar [76]int32
  1399  	// current \.[\\skewchar] values
  1400  	bcharLabel [76]fontIndex
  1401  	// start of |lig_kern| program for left boundary character,
  1402  	//   |non_address| if there is none
  1403  
  1404  	fontBchar [76] /* minQuarterword..256+minQuarterword */ uint16
  1405  	// boundary character, |non_char| if there is none
  1406  	fontFalseBchar [76] /* minQuarterword..256+minQuarterword */ uint16
  1407  	// |font_bchar| if it doesn't exist in the font, otherwise |non_char|
  1408  
  1409  	charBase [76]int32
  1410  	// base addresses for |char_info|
  1411  	widthBase [76]int32
  1412  	// base addresses for widths
  1413  	heightBase [76]int32
  1414  	// base addresses for heights
  1415  	depthBase [76]int32
  1416  	// base addresses for depths
  1417  	italicBase [76]int32
  1418  	// base addresses for italic corrections
  1419  	ligKernBase [76]int32
  1420  	// base addresses for ligature/kerning programs
  1421  	kernBase [76]int32
  1422  	// base addresses for kerns
  1423  	extenBase [76]int32
  1424  	// base addresses for extensible recipes
  1425  	paramBase [76]int32
  1426  	// base addresses for font parameters
  1427  
  1428  	nullCharacter fourQuarters // nonexistent character information
  1429  
  1430  	totalPages   int32  // the number of pages that have been shipped out
  1431  	maxV         scaled // maximum height-plus-depth of pages shipped so far
  1432  	maxH         scaled // maximum width of pages shipped so far
  1433  	maxPush      int32  // deepest nesting of |push| commands encountered so far
  1434  	lastBop      int32  // location of previous |bop| in the \.[DVI] output
  1435  	deadCycles   int32  // recent outputs that didn't ship anything out
  1436  	doingLeaders bool   // are we inside a leader box?
  1437  
  1438  	c, f                   quarterword // character and font in current |char_node|
  1439  	ruleHt, ruleDp, ruleWd scaled      // size of current rule being output
  1440  	g                      halfword    // current glue specification
  1441  	lq, lr                 int32       // quantities used in calculations for leaders
  1442  
  1443  	dviBuf    [801]eightBits // buffer for \.[DVI] output
  1444  	halfBuf   dviIndex       // half of |dvi_buf_size|
  1445  	dviLimit  dviIndex       // end of the current half buffer
  1446  	dviPtr    dviIndex       // the next available buffer address
  1447  	dviOffset int32          // |dvi_buf_size| times the number of times the
  1448  	//   output buffer has been fully emptied
  1449  
  1450  	dviGone int32 // the number of bytes already output to |dvi_file|
  1451  
  1452  	downPtr, rightPtr halfword // heads of the down and right stacks
  1453  
  1454  	dviH, dviV scaled             // a \.[DVI] reader program thinks we are here
  1455  	curH, curV scaled             // \TeX\ thinks we are here
  1456  	dviF       internalFontNumber // the current font
  1457  	curS       int32              // current depth of output box nesting, initially $-1$
  1458  
  1459  	totalStretch, totalShrink [4]scaled
  1460  	// glue found by |hpack| or |vpack|
  1461  	lastBadness int32 // badness of the most recently packaged box
  1462  
  1463  	adjustTail halfword // tail of adjustment list
  1464  
  1465  	packBeginLine int32 // source file line where the current paragraph
  1466  	//   or alignment began; a negative value denotes alignment
  1467  
  1468  	emptyField    twoHalves
  1469  	nullDelimiter fourQuarters
  1470  
  1471  	curMlist       halfword    // beginning of mlist to be translated
  1472  	curStyle       smallNumber // style code at current place in the list
  1473  	curSize        smallNumber // size code corresponding to |cur_style|
  1474  	curMu          scaled      // the math unit width corresponding to |cur_size|
  1475  	mlistPenalties bool        // should |mlist_to_hlist| insert penalties?
  1476  
  1477  	curF internalFontNumber // the |font| field of a |math_char|
  1478  	curC quarterword        // the |character| field of a |math_char|
  1479  	curI fourQuarters       // the |char_info| of a |math_char|,
  1480  	//   or a lig/kern instruction
  1481  
  1482  	magicOffset int32 // used to find inter-element spacing
  1483  
  1484  	curAlign         halfword // current position in preamble list
  1485  	curSpan          halfword // start of currently spanned columns in preamble list
  1486  	curLoop          halfword // place to copy when extending a periodic preamble
  1487  	alignPtr         halfword // most recently pushed-down alignment stack node
  1488  	curHead, curTail halfword // adjustment list pointers
  1489  
  1490  	justBox halfword // the |hlist_node| for the last line of the new paragraph
  1491  
  1492  	passive     halfword // most recent node on passive list
  1493  	printedNode halfword // most recent node that has been printed
  1494  	passNumber  halfword // the number of passive nodes allocated on this pass
  1495  
  1496  	activeWidth [6]scaled
  1497  	// distance from first active node to~|cur_p|
  1498  	curActiveWidth [6]scaled // distance from current active node
  1499  	background     [6]scaled // length of an ``empty'' line
  1500  	breakWidth     [6]scaled // length being computed after current break
  1501  
  1502  	noShrinkErrorYet bool // have we complained about infinite shrinkage?
  1503  
  1504  	curP       halfword // the current breakpoint under consideration
  1505  	secondPass bool     // is this our second attempt to break this paragraph?
  1506  	finalPass  bool     // is this our final attempt to break this paragraph?
  1507  	threshold  int32    // maximum badness on feasible lines
  1508  
  1509  	minimalDemerits [4]int32 // best total
  1510  	//   demerits known for current line class and position, given the fitness
  1511  
  1512  	minimumDemerits int32 // best total demerits known for current line class
  1513  	//   and position
  1514  
  1515  	bestPlace [4]halfword // how to achieve
  1516  	//   |minimal_demerits|
  1517  
  1518  	bestPlLine [4]halfword // corresponding
  1519  	//   line number
  1520  
  1521  	discWidth scaled // the length of discretionary material preceding a break
  1522  
  1523  	easyLine        halfword // line numbers |>easy_line| are equivalent in break nodes
  1524  	lastSpecialLine halfword // line numbers |>last_special_line| all have
  1525  	//   the same width
  1526  
  1527  	firstWidth scaled // the width of all lines |<=last_special_line|, if
  1528  	//   no \.[\\parshape] has been specified
  1529  
  1530  	secondWidth  scaled // the width of all lines |>last_special_line|
  1531  	firstIndent  scaled // left margin to go with |first_width|
  1532  	secondIndent scaled // left margin to go with |second_width|
  1533  
  1534  	bestBet         halfword // use this passive node and its predecessors
  1535  	fewestDemerits  int32    // the demerits associated with |best_bet|
  1536  	bestLine        halfword // line number following the last line of the new paragraph
  1537  	actualLooseness int32    // the difference between |line_number(best_bet)|
  1538  	//   and the optimum |best_line|
  1539  
  1540  	lineDiff int32 // the difference between the current line number and
  1541  	//   the optimum |best_line|
  1542  
  1543  	hc                 [66] /* 0..256 */ uint16 // word to be hyphenated
  1544  	hn/* 0..64 */ byte // the number of positions occupied in |hc|;
  1545  	//                                   not always a |small_number|
  1546  
  1547  	ha, hb                         halfword                 // nodes |ha..hb| should be replaced by the hyphenated result
  1548  	hf                             internalFontNumber       // font number of the letters in |hc|
  1549  	hu                             [64] /* 0..256 */ uint16 // like |hc|, before conversion to lowercase
  1550  	hyfChar                        int32                    // hyphen character of the relevant font
  1551  	curLang, initCurLang           asciiCode                // current hyphenation table of interest
  1552  	lHyf, rHyf, initLHyf, initRHyf int32                    // limits on fragment sizes
  1553  	hyfBchar                       halfword                 // boundary character after $c_n$
  1554  
  1555  	hyf      [65] /* 0..9 */ byte // odd values indicate discretionary hyphens
  1556  	initList halfword             // list of punctuation characters preceding the word
  1557  	initLig  bool                 // does |init_list| represent a ligature?
  1558  	initLft  bool                 // if so, did the ligature involve a left boundary?
  1559  
  1560  	hyphenPassed smallNumber // first hyphen in a ligature, if any
  1561  
  1562  	curL, curR      halfword // characters before and after the cursor
  1563  	curQ            halfword // where a ligature should be detached
  1564  	ligStack        halfword // unfinished business to the right of the cursor
  1565  	ligaturePresent bool     // should a ligature node be made for |cur_l|?
  1566  	lftHit, rtHit   bool     // did we hit a ligature with a boundary character?
  1567  
  1568  	trie        [8001]twoHalves                  // |trie_link|, |trie_char|, |trie_op|
  1569  	hyfDistance [500]smallNumber                 // position |k-j| of $n_j$
  1570  	hyfNum      [500]smallNumber                 // value of $n_j$
  1571  	hyfNext     [500]quarterword                 // continuation code
  1572  	opStart     [256] /* 0..trieOpSize */ uint16 // offset for current language
  1573  
  1574  	hyphWord  [308]strNumber // exception words
  1575  	hyphList  [308]halfword  // lists of hyphen positions
  1576  	hyphCount hyphPointer    // the number of words in the exception dictionary
  1577  
  1578  	trieOpHash [1001] /* 0..trieOpSize */ uint16
  1579  	// trie op codes for quadruples
  1580  	trieUsed [256]quarterword
  1581  	// largest opcode used so far for this language
  1582  	trieOpLang [500]asciiCode
  1583  	// language part of a hashed quadruple
  1584  	trieOpVal [500]quarterword
  1585  	// opcode corresponding to a hashed quadruple
  1586  	trieOpPtr/* 0..trieOpSize */ uint16 // number of stored ops so far
  1587  
  1588  	trieC [8001]packedAsciiCode
  1589  	// characters to match
  1590  	// \hskip10pt
  1591  	trieO [8001]quarterword
  1592  	// operations to perform
  1593  	// \hskip10pt
  1594  	trieL [8001]triePointer
  1595  	// left subtrie links
  1596  	// \hskip10pt
  1597  	trieR [8001]triePointer
  1598  	// right subtrie links
  1599  	// \hskip10pt
  1600  	triePtr triePointer // the number of nodes in the trie
  1601  	// \hskip10pt
  1602  	trieHash [8001]triePointer
  1603  	// used to identify equivalent subtries
  1604  
  1605  	trieTaken [8000]bool
  1606  	// does a family start here?
  1607  	// \hskip10pt
  1608  	trieMin [256]triePointer
  1609  	// the first possible slot for each character
  1610  	// \hskip10pt
  1611  	trieMax triePointer // largest location used in |trie|
  1612  	// \hskip10pt
  1613  	trieNotReady bool // is the trie still in linked form?
  1614  
  1615  	bestHeightPlusDepth scaled // height of the best box, without stretching or
  1616  	//   shrinking
  1617  
  1618  	pageTail                               halfword // the final node on the current page
  1619  	pageContents/* empty..boxThere */ byte // what is on the current page so far?
  1620  	pageMaxDepth                           scaled   // maximum box depth on page being built
  1621  	bestPageBreak                          halfword // break here to get the best page known so far
  1622  	leastPageCost                          int32    // the score for this currently best page
  1623  	bestSize                               scaled   // its |page_goal|
  1624  
  1625  	pageSoFar       [8]scaled // height and glue of the current page
  1626  	lastGlue        halfword  // used to implement \.[\\lastskip]
  1627  	lastPenalty     int32     // used to implement \.[\\lastpenalty]
  1628  	lastKern        scaled    // used to implement \.[\\lastkern]
  1629  	insertPenalties int32     // sum of the penalties for insertions
  1630  	//   that were held over
  1631  
  1632  	outputActive bool // are we in the midst of an output routine?
  1633  
  1634  	mainF          internalFontNumber // the current font
  1635  	mainI          fourQuarters       // character information bytes for |cur_l|
  1636  	mainJ          fourQuarters       // ligature/kern command
  1637  	mainK          fontIndex          // index into |font_info|
  1638  	mainP          halfword           // temporary register for list manipulation
  1639  	mainS          int32              // space factor value
  1640  	bchar          halfword           // boundary character of current font, or |non_char|
  1641  	falseBchar     halfword           // nonexistent character matching |bchar|, or |non_char|
  1642  	cancelBoundary bool               // should the left boundary be ignored?
  1643  	insDisc        bool               // should we insert a discretionary node?
  1644  
  1645  	curBox halfword // box to be placed into its context
  1646  
  1647  	afterToken halfword // zero, or a saved token
  1648  
  1649  	longHelpSeen bool // has the long \.[\\errmessage] help been used?
  1650  
  1651  	formatIdent strNumber
  1652  
  1653  	fmtFile wordFile // for input or output of format information
  1654  
  1655  	readyAlready int32 // a sacrifice of purity for economy
  1656  
  1657  	writeFile [16]alphaFile
  1658  	writeOpen [18]bool
  1659  
  1660  	writeLoc halfword // |eqtb| address of \.[\\write]
  1661  }
  1662  
  1663  func (prg *prg) initialize() { // this procedure gets things started properly
  1664  	var (
  1665  		// Local variables for initialization
  1666  		i int32
  1667  
  1668  		k int32 // index into |mem|, |eqtb|, etc.
  1669  
  1670  		z hyphPointer // runs through the exception dictionary
  1671  	)
  1672  	prg.xchr[040] = ' '
  1673  	prg.xchr[041] = '!'
  1674  	prg.xchr[042] = '"'
  1675  	prg.xchr[043] = '#'
  1676  	prg.xchr[044] = '$'
  1677  	prg.xchr[045] = '%'
  1678  	prg.xchr[046] = '&'
  1679  	prg.xchr[047] = '\''
  1680  
  1681  	prg.xchr[050] = '('
  1682  	prg.xchr[051] = ')'
  1683  	prg.xchr[052] = '*'
  1684  	prg.xchr[053] = '+'
  1685  	prg.xchr[054] = ','
  1686  	prg.xchr[055] = '-'
  1687  	prg.xchr[056] = '.'
  1688  	prg.xchr[057] = '/'
  1689  
  1690  	prg.xchr[060] = '0'
  1691  	prg.xchr[061] = '1'
  1692  	prg.xchr[062] = '2'
  1693  	prg.xchr[063] = '3'
  1694  	prg.xchr[064] = '4'
  1695  	prg.xchr[065] = '5'
  1696  	prg.xchr[066] = '6'
  1697  	prg.xchr[067] = '7'
  1698  
  1699  	prg.xchr[070] = '8'
  1700  	prg.xchr[071] = '9'
  1701  	prg.xchr[072] = ':'
  1702  	prg.xchr[073] = ';'
  1703  	prg.xchr[074] = '<'
  1704  	prg.xchr[075] = '='
  1705  	prg.xchr[076] = '>'
  1706  	prg.xchr[077] = '?'
  1707  
  1708  	prg.xchr[0100] = '@'
  1709  	prg.xchr[0101] = 'A'
  1710  	prg.xchr[0102] = 'B'
  1711  	prg.xchr[0103] = 'C'
  1712  	prg.xchr[0104] = 'D'
  1713  	prg.xchr[0105] = 'E'
  1714  	prg.xchr[0106] = 'F'
  1715  	prg.xchr[0107] = 'G'
  1716  
  1717  	prg.xchr[0110] = 'H'
  1718  	prg.xchr[0111] = 'I'
  1719  	prg.xchr[0112] = 'J'
  1720  	prg.xchr[0113] = 'K'
  1721  	prg.xchr[0114] = 'L'
  1722  	prg.xchr[0115] = 'M'
  1723  	prg.xchr[0116] = 'N'
  1724  	prg.xchr[0117] = 'O'
  1725  
  1726  	prg.xchr[0120] = 'P'
  1727  	prg.xchr[0121] = 'Q'
  1728  	prg.xchr[0122] = 'R'
  1729  	prg.xchr[0123] = 'S'
  1730  	prg.xchr[0124] = 'T'
  1731  	prg.xchr[0125] = 'U'
  1732  	prg.xchr[0126] = 'V'
  1733  	prg.xchr[0127] = 'W'
  1734  
  1735  	prg.xchr[0130] = 'X'
  1736  	prg.xchr[0131] = 'Y'
  1737  	prg.xchr[0132] = 'Z'
  1738  	prg.xchr[0133] = '['
  1739  	prg.xchr[0134] = '\\'
  1740  	prg.xchr[0135] = ']'
  1741  	prg.xchr[0136] = '^'
  1742  	prg.xchr[0137] = '_'
  1743  
  1744  	prg.xchr[0140] = '`'
  1745  	prg.xchr[0141] = 'a'
  1746  	prg.xchr[0142] = 'b'
  1747  	prg.xchr[0143] = 'c'
  1748  	prg.xchr[0144] = 'd'
  1749  	prg.xchr[0145] = 'e'
  1750  	prg.xchr[0146] = 'f'
  1751  	prg.xchr[0147] = 'g'
  1752  
  1753  	prg.xchr[0150] = 'h'
  1754  	prg.xchr[0151] = 'i'
  1755  	prg.xchr[0152] = 'j'
  1756  	prg.xchr[0153] = 'k'
  1757  	prg.xchr[0154] = 'l'
  1758  	prg.xchr[0155] = 'm'
  1759  	prg.xchr[0156] = 'n'
  1760  	prg.xchr[0157] = 'o'
  1761  
  1762  	prg.xchr[0160] = 'p'
  1763  	prg.xchr[0161] = 'q'
  1764  	prg.xchr[0162] = 'r'
  1765  	prg.xchr[0163] = 's'
  1766  	prg.xchr[0164] = 't'
  1767  	prg.xchr[0165] = 'u'
  1768  	prg.xchr[0166] = 'v'
  1769  	prg.xchr[0167] = 'w'
  1770  
  1771  	prg.xchr[0170] = 'x'
  1772  	prg.xchr[0171] = 'y'
  1773  	prg.xchr[0172] = 'z'
  1774  	prg.xchr[0173] = '{'
  1775  	prg.xchr[0174] = '|'
  1776  	prg.xchr[0175] = '}'
  1777  	prg.xchr[0176] = '~'
  1778  
  1779  	for ii := int32(0); ii <= 037; ii++ {
  1780  		i = ii
  1781  		_ = i
  1782  		prg.xchr[i] = ' '
  1783  	}
  1784  	for ii := int32(0177); ii <= 0377; ii++ {
  1785  		i = ii
  1786  		_ = i
  1787  		prg.xchr[i] = ' '
  1788  	}
  1789  
  1790  	for ii := int32(firstTextChar); ii <= lastTextChar; ii++ {
  1791  		i = ii
  1792  		_ = i
  1793  		prg.xord[char(i)] = byte(invalidCode)
  1794  	}
  1795  	for ii := int32(0200); ii <= 0377; ii++ {
  1796  		i = ii
  1797  		_ = i
  1798  		prg.xord[prg.xchr[i]] = byte(i)
  1799  	}
  1800  	for ii := int32(0); ii <= 0176; ii++ {
  1801  		i = ii
  1802  		_ = i
  1803  		prg.xord[prg.xchr[i]] = byte(i)
  1804  	}
  1805  
  1806  	prg.interaction = byte(errorStopMode)
  1807  
  1808  	prg.deletionsAllowed = true
  1809  	prg.setBoxAllowed = true
  1810  	prg.errorCount = 0 // |history| is initialized elsewhere
  1811  
  1812  	prg.helpPtr = 0
  1813  	prg.useErrHelp = false
  1814  
  1815  	prg.interrupt = 0
  1816  	prg.okToInterrupt = true
  1817  
  1818  	//  was_mem_end:=mem_min; [indicate that everything was previously free]
  1819  	// was_lo_max:=mem_min; was_hi_min:=mem_max;
  1820  	// panicking:=false;
  1821  	// [  ]
  1822  
  1823  	prg.nestPtr = 0
  1824  	prg.maxNestStack = 0
  1825  	prg.curList.modeField = int16(vmode)
  1826  	prg.curList.headField = uint16(30000 - 1)
  1827  	prg.curList.tailField = uint16(30000 - 1)
  1828  	*prg.curList.auxField.int() = -65536000
  1829  	prg.curList.mlField = 0
  1830  	prg.curList.pgField = 0
  1831  	prg.shownMode = 0
  1832  
  1833  	// Start a new current page
  1834  	prg.pageContents = byte(empty)
  1835  	prg.pageTail = uint16(30000 - 2)
  1836  	*(*prg.mem[30000-2].hh()).rh() = 0
  1837  
  1838  	prg.lastGlue = 65535
  1839  	prg.lastPenalty = 0
  1840  	prg.lastKern = 0
  1841  	prg.pageSoFar[7] = 0
  1842  	prg.pageMaxDepth = 0
  1843  
  1844  	for ii := int32(intBase); ii <= eqtbSize; ii++ {
  1845  		k = ii
  1846  		_ = k
  1847  		prg.xeqLevel[k-5263] = byte(levelOne)
  1848  	}
  1849  
  1850  	prg.noNewControlSequence = true // new identifiers are usually forbidden
  1851  	*prg.hash[hashBase-514].lh() = 0
  1852  	*prg.hash[hashBase-514].rh() = 0
  1853  	for ii := int32(hashBase + 1); ii <= undefinedControlSequence-1; ii++ {
  1854  		k = ii
  1855  		_ = k
  1856  		prg.hash[k-514] = prg.hash[hashBase-514]
  1857  	}
  1858  
  1859  	prg.savePtr = 0
  1860  	prg.curLevel = byte(levelOne)
  1861  	prg.curGroup = byte(bottomLevel)
  1862  	prg.curBoundary = 0
  1863  	prg.maxSaveStack = 0
  1864  
  1865  	prg.magSet = 0
  1866  
  1867  	prg.curMark[topMarkCode] = 0
  1868  	prg.curMark[firstMarkCode] = 0
  1869  	prg.curMark[botMarkCode] = 0
  1870  	prg.curMark[splitFirstMarkCode] = 0
  1871  	prg.curMark[splitBotMarkCode] = 0
  1872  
  1873  	prg.curVal = 0
  1874  	prg.curValLevel = byte(intVal)
  1875  	prg.radix = 0
  1876  	prg.curOrder = byte(normal)
  1877  
  1878  	for ii := int32(0); ii <= 16; ii++ {
  1879  		k = ii
  1880  		_ = k
  1881  		prg.readOpen[k] = byte(closed)
  1882  	}
  1883  
  1884  	prg.condPtr = 0
  1885  	prg.ifLimit = byte(normal)
  1886  	prg.curIf = 0
  1887  	prg.ifLine = 0
  1888  
  1889  	strcopy(prg.texFormatDefault[:], "TeXformats:plain.fmt")
  1890  	// \xref[TeXformats]
  1891  	// \xref[plain]
  1892  	// \xref[system dependencies]
  1893  
  1894  	for ii := int32(fontBase); ii <= fontMax; ii++ {
  1895  		k = ii
  1896  		_ = k
  1897  		prg.fontUsed[k] = false
  1898  	}
  1899  
  1900  	prg.nullCharacter.b0 = byte(minQuarterword)
  1901  	prg.nullCharacter.b1 = byte(minQuarterword)
  1902  	prg.nullCharacter.b2 = byte(minQuarterword)
  1903  	prg.nullCharacter.b3 = byte(minQuarterword)
  1904  
  1905  	prg.totalPages = 0
  1906  	prg.maxV = 0
  1907  	prg.maxH = 0
  1908  	prg.maxPush = 0
  1909  	prg.lastBop = -1
  1910  	prg.doingLeaders = false
  1911  	prg.deadCycles = 0
  1912  	prg.curS = -1
  1913  
  1914  	prg.halfBuf = uint16(dviBufSize / 2)
  1915  	prg.dviLimit = uint16(dviBufSize)
  1916  	prg.dviPtr = 0
  1917  	prg.dviOffset = 0
  1918  	prg.dviGone = 0
  1919  
  1920  	prg.downPtr = 0
  1921  	prg.rightPtr = 0
  1922  
  1923  	prg.adjustTail = 0
  1924  	prg.lastBadness = 0
  1925  
  1926  	prg.packBeginLine = 0
  1927  
  1928  	*prg.emptyField.rh() = uint16(empty)
  1929  	*prg.emptyField.lh() = 0
  1930  
  1931  	prg.nullDelimiter.b0 = 0
  1932  	prg.nullDelimiter.b1 = byte(minQuarterword)
  1933  
  1934  	prg.nullDelimiter.b2 = 0
  1935  	prg.nullDelimiter.b3 = byte(minQuarterword)
  1936  
  1937  	prg.alignPtr = 0
  1938  	prg.curAlign = 0
  1939  	prg.curSpan = 0
  1940  	prg.curLoop = 0
  1941  	prg.curHead = 0
  1942  	prg.curTail = 0
  1943  
  1944  	for ii := int32(0); ii <= hyphSize; ii++ {
  1945  		z = hyphPointer(ii)
  1946  		_ = z
  1947  		prg.hyphWord[z] = 0
  1948  		prg.hyphList[z] = 0
  1949  	}
  1950  	prg.hyphCount = 0
  1951  
  1952  	prg.outputActive = false
  1953  	prg.insertPenalties = 0
  1954  
  1955  	prg.ligaturePresent = false
  1956  	prg.cancelBoundary = false
  1957  	prg.lftHit = false
  1958  	prg.rtHit = false
  1959  	prg.insDisc = false
  1960  
  1961  	prg.afterToken = 0
  1962  
  1963  	prg.longHelpSeen = false
  1964  
  1965  	prg.formatIdent = 0
  1966  
  1967  	for ii := int32(0); ii <= 17; ii++ {
  1968  		k = ii
  1969  		_ = k
  1970  		prg.writeOpen[k] = false
  1971  	}
  1972  
  1973  	// Initialize table entries (done by \.[INITEX] only)
  1974  	for ii := int32(memBot + 1); ii <= memBot+glueSpecSize+glueSpecSize+glueSpecSize+glueSpecSize+glueSpecSize-1; ii++ {
  1975  		k = ii
  1976  		_ = k
  1977  		*prg.mem[k].int() = 0
  1978  	}
  1979  	// all glue dimensions are zeroed
  1980  	// \xref[data structure assumptions]
  1981  	k = memBot
  1982  	for k <= memBot+glueSpecSize+glueSpecSize+glueSpecSize+glueSpecSize+glueSpecSize-1 {
  1983  		// set first words of glue specifications
  1984  		*(*prg.mem[k].hh()).rh() = uint16(0 + 1)
  1985  		*(*prg.mem[k].hh()).b0() = byte(normal)
  1986  		*(*prg.mem[k].hh()).b1() = byte(normal)
  1987  		k = k + glueSpecSize
  1988  	}
  1989  	*prg.mem[memBot+glueSpecSize+2].int() = 0200000
  1990  	*(*prg.mem[memBot+glueSpecSize].hh()).b0() = byte(fil)
  1991  
  1992  	*prg.mem[memBot+glueSpecSize+glueSpecSize+2].int() = 0200000
  1993  	*(*prg.mem[memBot+glueSpecSize+glueSpecSize].hh()).b0() = byte(fill)
  1994  
  1995  	*prg.mem[memBot+glueSpecSize+glueSpecSize+glueSpecSize+2].int() = 0200000
  1996  	*(*prg.mem[memBot+glueSpecSize+glueSpecSize+glueSpecSize].hh()).b0() = byte(fil)
  1997  
  1998  	*prg.mem[memBot+glueSpecSize+glueSpecSize+glueSpecSize+3].int() = 0200000
  1999  	*(*prg.mem[memBot+glueSpecSize+glueSpecSize+glueSpecSize].hh()).b1() = byte(fil)
  2000  
  2001  	*prg.mem[memBot+glueSpecSize+glueSpecSize+glueSpecSize+glueSpecSize+2].int() = -0200000
  2002  	*(*prg.mem[memBot+glueSpecSize+glueSpecSize+glueSpecSize+glueSpecSize].hh()).b0() = byte(fil)
  2003  
  2004  	prg.rover = uint16(memBot + glueSpecSize + glueSpecSize + glueSpecSize + glueSpecSize + glueSpecSize - 1 + 1)
  2005  	*(*prg.mem[prg.rover].hh()).rh() = 65535 // now initialize the dynamic memory
  2006  	*(*prg.mem[prg.rover].hh()).lh() = 1000  // which is a 1000-word available node
  2007  	*(*prg.mem[int32(prg.rover)+1].hh()).lh() = prg.rover
  2008  	*(*prg.mem[int32(prg.rover)+1].hh()).rh() = prg.rover
  2009  
  2010  	prg.loMemMax = uint16(int32(prg.rover) + 1000)
  2011  	*(*prg.mem[prg.loMemMax].hh()).rh() = 0
  2012  	*(*prg.mem[prg.loMemMax].hh()).lh() = 0
  2013  
  2014  	for ii := int32(30000 - 13); ii <= 30000; ii++ {
  2015  		k = ii
  2016  		_ = k
  2017  		prg.mem[k] = prg.mem[prg.loMemMax]
  2018  	} // clear list heads
  2019  
  2020  	// Initialize the special list heads and constant nodes
  2021  	*(*prg.mem[30000-10].hh()).lh() = uint16(07777 + frozenEndTemplate) // |link(omit_template)=null|
  2022  
  2023  	*(*prg.mem[30000-9].hh()).rh() = uint16(maxQuarterword + 1)
  2024  	*(*prg.mem[30000-9].hh()).lh() = 0
  2025  
  2026  	*(*prg.mem[30000-7].hh()).b0() = byte(hyphenated)
  2027  	*(*prg.mem[30000-7+1].hh()).lh() = 65535
  2028  	*(*prg.mem[30000-7].hh()).b1() = 0 // the |subtype| is never examined by the algorithm
  2029  
  2030  	*(*prg.mem[30000].hh()).b1() = byte(255 + minQuarterword)
  2031  	*(*prg.mem[30000].hh()).b0() = byte(splitUp)
  2032  	*(*prg.mem[30000].hh()).rh() = 30000
  2033  
  2034  	*(*prg.mem[30000-2].hh()).b0() = byte(glueNode)
  2035  	*(*prg.mem[30000-2].hh()).b1() = byte(normal)
  2036  
  2037  	prg.avail = 0
  2038  	prg.memEnd = 30000
  2039  	prg.hiMemMin = uint16(30000 - 13) // initialize the one-word memory
  2040  	prg.varUsed = memBot + glueSpecSize + glueSpecSize + glueSpecSize + glueSpecSize + glueSpecSize - 1 + 1 - memBot
  2041  	prg.dynUsed = hiMemStatUsage
  2042  	// initialize statistics
  2043  
  2044  	*(*prg.eqtb[undefinedControlSequence-1].hh()).b0() = byte(undefinedCs)
  2045  	*(*prg.eqtb[undefinedControlSequence-1].hh()).rh() = 0
  2046  	*(*prg.eqtb[undefinedControlSequence-1].hh()).b1() = byte(levelZero)
  2047  	for ii := int32(activeBase); ii <= undefinedControlSequence-1; ii++ {
  2048  		k = ii
  2049  		_ = k
  2050  		prg.eqtb[k-1] = prg.eqtb[undefinedControlSequence-1]
  2051  	}
  2052  
  2053  	*(*prg.eqtb[glueBase-1].hh()).rh() = uint16(memBot)
  2054  	*(*prg.eqtb[glueBase-1].hh()).b1() = byte(levelOne)
  2055  	*(*prg.eqtb[glueBase-1].hh()).b0() = byte(glueRef)
  2056  	for ii := int32(glueBase + 1); ii <= localBase-1; ii++ {
  2057  		k = ii
  2058  		_ = k
  2059  		prg.eqtb[k-1] = prg.eqtb[glueBase-1]
  2060  	}
  2061  	*(*prg.mem[memBot].hh()).rh() = uint16(int32(*(*prg.mem[memBot].hh()).rh()) + localBase - glueBase)
  2062  
  2063  	*(*prg.eqtb[parShapeLoc-1].hh()).rh() = 0
  2064  	*(*prg.eqtb[parShapeLoc-1].hh()).b0() = byte(shapeRef)
  2065  	*(*prg.eqtb[parShapeLoc-1].hh()).b1() = byte(levelOne)
  2066  
  2067  	for ii := int32(outputRoutineLoc); ii <= toksBase+255; ii++ {
  2068  		k = ii
  2069  		_ = k
  2070  		prg.eqtb[k-1] = prg.eqtb[undefinedControlSequence-1]
  2071  	}
  2072  	*(*prg.eqtb[boxBase+0-1].hh()).rh() = 0
  2073  	*(*prg.eqtb[boxBase-1].hh()).b0() = byte(boxRef)
  2074  	*(*prg.eqtb[boxBase-1].hh()).b1() = byte(levelOne)
  2075  	for ii := int32(boxBase + 1); ii <= boxBase+255; ii++ {
  2076  		k = ii
  2077  		_ = k
  2078  		prg.eqtb[k-1] = prg.eqtb[boxBase-1]
  2079  	}
  2080  	*(*prg.eqtb[curFontLoc-1].hh()).rh() = uint16(fontBase)
  2081  	*(*prg.eqtb[curFontLoc-1].hh()).b0() = byte(data)
  2082  	*(*prg.eqtb[curFontLoc-1].hh()).b1() = byte(levelOne)
  2083  
  2084  	for ii := int32(mathFontBase); ii <= mathFontBase+47; ii++ {
  2085  		k = ii
  2086  		_ = k
  2087  		prg.eqtb[k-1] = prg.eqtb[curFontLoc-1]
  2088  	}
  2089  	*(*prg.eqtb[catCodeBase-1].hh()).rh() = 0
  2090  	*(*prg.eqtb[catCodeBase-1].hh()).b0() = byte(data)
  2091  	*(*prg.eqtb[catCodeBase-1].hh()).b1() = byte(levelOne)
  2092  
  2093  	for ii := int32(catCodeBase + 1); ii <= intBase-1; ii++ {
  2094  		k = ii
  2095  		_ = k
  2096  		prg.eqtb[k-1] = prg.eqtb[catCodeBase-1]
  2097  	}
  2098  	for ii := int32(0); ii <= 255; ii++ {
  2099  		k = ii
  2100  		_ = k
  2101  		*(*prg.eqtb[catCodeBase+k-1].hh()).rh() = uint16(otherChar)
  2102  		*(*prg.eqtb[mathCodeBase+k-1].hh()).rh() = uint16(k + 0)
  2103  		*(*prg.eqtb[sfCodeBase+k-1].hh()).rh() = 1000
  2104  	}
  2105  	*(*prg.eqtb[catCodeBase+carriageReturn-1].hh()).rh() = uint16(carRet)
  2106  	*(*prg.eqtb[catCodeBase+' '-1].hh()).rh() = uint16(spacer)
  2107  	*(*prg.eqtb[catCodeBase+'\\'-1].hh()).rh() = uint16(escape)
  2108  	*(*prg.eqtb[catCodeBase+'%'-1].hh()).rh() = uint16(comment)
  2109  	*(*prg.eqtb[catCodeBase+invalidCode-1].hh()).rh() = uint16(invalidChar)
  2110  	*(*prg.eqtb[catCodeBase+nullCode-1].hh()).rh() = uint16(ignore)
  2111  	for ii := int32('0'); ii <= '9'; ii++ {
  2112  		k = ii
  2113  		_ = k
  2114  		*(*prg.eqtb[mathCodeBase+k-1].hh()).rh() = uint16(k + 070000 + 0)
  2115  	}
  2116  	for ii := int32('A'); ii <= 'Z'; ii++ {
  2117  		k = ii
  2118  		_ = k
  2119  		*(*prg.eqtb[catCodeBase+k-1].hh()).rh() = uint16(letter)
  2120  		*(*prg.eqtb[catCodeBase+k+'a'-'A'-1].hh()).rh() = uint16(letter)
  2121  
  2122  		*(*prg.eqtb[mathCodeBase+k-1].hh()).rh() = uint16(k + 070000 + 0400 + 0)
  2123  		*(*prg.eqtb[mathCodeBase+k+'a'-'A'-1].hh()).rh() = uint16(k + 'a' - 'A' + 070000 + 0400 + 0)
  2124  
  2125  		*(*prg.eqtb[lcCodeBase+k-1].hh()).rh() = uint16(k + 'a' - 'A')
  2126  		*(*prg.eqtb[lcCodeBase+k+'a'-'A'-1].hh()).rh() = uint16(k + 'a' - 'A')
  2127  
  2128  		*(*prg.eqtb[ucCodeBase+k-1].hh()).rh() = uint16(k)
  2129  		*(*prg.eqtb[ucCodeBase+k+'a'-'A'-1].hh()).rh() = uint16(k)
  2130  
  2131  		*(*prg.eqtb[sfCodeBase+k-1].hh()).rh() = 999
  2132  	}
  2133  
  2134  	for ii := int32(intBase); ii <= delCodeBase-1; ii++ {
  2135  		k = ii
  2136  		_ = k
  2137  		*prg.eqtb[k-1].int() = 0
  2138  	}
  2139  	*prg.eqtb[intBase+magCode-1].int() = 1000
  2140  	*prg.eqtb[intBase+toleranceCode-1].int() = 10000
  2141  	*prg.eqtb[intBase+hangAfterCode-1].int() = 1
  2142  	*prg.eqtb[intBase+maxDeadCyclesCode-1].int() = 25
  2143  	*prg.eqtb[intBase+escapeCharCode-1].int() = '\\'
  2144  	*prg.eqtb[intBase+endLineCharCode-1].int() = carriageReturn
  2145  	for ii := int32(0); ii <= 255; ii++ {
  2146  		k = ii
  2147  		_ = k
  2148  		*prg.eqtb[delCodeBase+k-1].int() = -1
  2149  	}
  2150  	*prg.eqtb[delCodeBase+'.'-1].int() = 0 // this null delimiter is used in error recovery
  2151  
  2152  	for ii := int32(dimenBase); ii <= eqtbSize; ii++ {
  2153  		k = ii
  2154  		_ = k
  2155  		*prg.eqtb[k-1].int() = 0
  2156  	}
  2157  
  2158  	prg.hashUsed = uint16(frozenControlSequence) // nothing is used
  2159  	prg.csCount = 0
  2160  	*(*prg.eqtb[frozenDontExpand-1].hh()).b0() = byte(dontExpand)
  2161  	*prg.hash[frozenDontExpand-514].rh() = 502
  2162  	// \xref[notexpanded:]
  2163  
  2164  	prg.fontPtr = byte(fontBase)
  2165  	prg.fmemPtr = 7
  2166  	prg.fontName[fontBase] = /* "nullfont" */ 801
  2167  	prg.fontArea[fontBase] = /* "" */ 338
  2168  	prg.hyphenChar[fontBase] = '-'
  2169  	prg.skewChar[fontBase] = -1
  2170  	prg.bcharLabel[fontBase] = uint16(nonAddress)
  2171  	prg.fontBchar[fontBase] = uint16(256 + minQuarterword)
  2172  	prg.fontFalseBchar[fontBase] = uint16(256 + minQuarterword)
  2173  	prg.fontBc[fontBase] = 1
  2174  	prg.fontEc[fontBase] = 0
  2175  	prg.fontSize[fontBase] = 0
  2176  	prg.fontDsize[fontBase] = 0
  2177  	prg.charBase[fontBase] = 0
  2178  	prg.widthBase[fontBase] = 0
  2179  	prg.heightBase[fontBase] = 0
  2180  	prg.depthBase[fontBase] = 0
  2181  	prg.italicBase[fontBase] = 0
  2182  	prg.ligKernBase[fontBase] = 0
  2183  	prg.kernBase[fontBase] = 0
  2184  	prg.extenBase[fontBase] = 0
  2185  	prg.fontGlue[fontBase] = 0
  2186  	prg.fontParams[fontBase] = 7
  2187  	prg.paramBase[fontBase] = -1
  2188  	for ii := int32(0); ii <= 6; ii++ {
  2189  		k = ii
  2190  		_ = k
  2191  		*prg.fontInfo[k].int() = 0
  2192  	}
  2193  
  2194  	for ii := int32(-trieOpSize); ii <= trieOpSize; ii++ {
  2195  		k = ii
  2196  		_ = k
  2197  		prg.trieOpHash[k+500] = 0
  2198  	}
  2199  	for ii := int32(0); ii <= 255; ii++ {
  2200  		k = ii
  2201  		_ = k
  2202  		prg.trieUsed[k] = byte(minQuarterword)
  2203  	}
  2204  	prg.trieOpPtr = 0
  2205  
  2206  	prg.trieNotReady = true
  2207  	prg.trieL[0] = 0
  2208  	prg.trieC[0] = 0
  2209  	prg.triePtr = 0
  2210  
  2211  	*prg.hash[frozenProtection-514].rh() = 1190
  2212  	// \xref[inaccessible]
  2213  
  2214  	prg.formatIdent = /* " (INITEX)" */ 1257
  2215  
  2216  	*prg.hash[endWrite-514].rh() = 1296
  2217  	*(*prg.eqtb[endWrite-1].hh()).b1() = byte(levelOne)
  2218  	*(*prg.eqtb[endWrite-1].hh()).b0() = byte(outerCall)
  2219  	*(*prg.eqtb[endWrite-1].hh()).rh() = 0
  2220  
  2221  }
  2222  
  2223  // \4
  2224  // Basic printing procedures
  2225  func (prg *prg) printLn() {
  2226  	switch prg.selector {
  2227  	case termAndLog:
  2228  		prg.termOut.Writeln()
  2229  		prg.logFile.Writeln()
  2230  		prg.termOffset = 0
  2231  		prg.fileOffset = 0
  2232  
  2233  	case logOnly:
  2234  		prg.logFile.Writeln()
  2235  		prg.fileOffset = 0
  2236  
  2237  	case termOnly:
  2238  		prg.termOut.Writeln()
  2239  		prg.termOffset = 0
  2240  
  2241  	case noPrint, pseudo, newString:
  2242  
  2243  	default:
  2244  		prg.writeFile[prg.selector].Writeln()
  2245  	}
  2246  
  2247  } // |tally| is not affected
  2248  
  2249  func (prg *prg) printChar(s asciiCode) {
  2250  	if int32(s) == *prg.eqtb[intBase+newLineCharCode-1].int() {
  2251  		// Character |s| is the current new-line character
  2252  		if int32(prg.selector) < pseudo {
  2253  			prg.printLn()
  2254  			goto exit
  2255  		}
  2256  	}
  2257  	switch prg.selector {
  2258  	case termAndLog:
  2259  		prg.termOut.Write(string(rune(prg.xchr[s])))
  2260  		prg.logFile.Write(string(rune(prg.xchr[s])))
  2261  		prg.termOffset = byte(int32(prg.termOffset) + 1)
  2262  		prg.fileOffset = byte(int32(prg.fileOffset) + 1)
  2263  		if int32(prg.termOffset) == maxPrintLine {
  2264  			prg.termOut.Writeln()
  2265  			prg.termOffset = 0
  2266  		}
  2267  		if int32(prg.fileOffset) == maxPrintLine {
  2268  			prg.logFile.Writeln()
  2269  			prg.fileOffset = 0
  2270  		}
  2271  
  2272  	case logOnly:
  2273  		prg.logFile.Write(string(rune(prg.xchr[s])))
  2274  		prg.fileOffset = byte(int32(prg.fileOffset) + 1)
  2275  		if int32(prg.fileOffset) == maxPrintLine {
  2276  			prg.printLn()
  2277  		}
  2278  
  2279  	case termOnly:
  2280  		prg.termOut.Write(string(rune(prg.xchr[s])))
  2281  		prg.termOffset = byte(int32(prg.termOffset) + 1)
  2282  		if int32(prg.termOffset) == maxPrintLine {
  2283  			prg.printLn()
  2284  		}
  2285  
  2286  	case noPrint:
  2287  	case pseudo:
  2288  		if prg.tally < prg.trickCount {
  2289  			prg.trickBuf[prg.tally%errorLine] = s
  2290  		}
  2291  	case newString:
  2292  		if int32(prg.poolPtr) < poolSize {
  2293  			prg.strPool[prg.poolPtr] = s
  2294  			prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  2295  		}
  2296  
  2297  		// we drop characters if the string space is full
  2298  	default:
  2299  		prg.writeFile[prg.selector].Write(string(rune(prg.xchr[s])))
  2300  	}
  2301  
  2302  	prg.tally = prg.tally + 1
  2303  
  2304  exit:
  2305  }
  2306  
  2307  func (prg *prg) print(s int32) {
  2308  	var (
  2309  		j  poolPointer // current character code position
  2310  		nl int32       // new-line character to restore
  2311  	)
  2312  	if s >= int32(prg.strPtr) {
  2313  		s = /* "???" */ 259
  2314  	} else if s < 256 {
  2315  		if s < 0 {
  2316  			s = /* "???" */ 259
  2317  		} else {
  2318  			if int32(prg.selector) > pseudo {
  2319  				prg.printChar(asciiCode(s))
  2320  				goto exit // internal strings are not expanded
  2321  			}
  2322  			if s == *prg.eqtb[intBase+newLineCharCode-1].int() {
  2323  				if int32(prg.selector) < pseudo {
  2324  					prg.printLn()
  2325  					goto exit
  2326  				}
  2327  			}
  2328  			nl = *prg.eqtb[intBase+newLineCharCode-1].int()
  2329  			*prg.eqtb[intBase+newLineCharCode-1].int() = -1
  2330  			// temporarily disable new-line character
  2331  			j = prg.strStart[s]
  2332  			for int32(j) < int32(prg.strStart[s+1]) {
  2333  				prg.printChar(prg.strPool[j])
  2334  				j = uint16(int32(j) + 1)
  2335  			}
  2336  			*prg.eqtb[intBase+newLineCharCode-1].int() = nl
  2337  			goto exit
  2338  		}
  2339  	}
  2340  	j = prg.strStart[s]
  2341  	for int32(j) < int32(prg.strStart[s+1]) {
  2342  		prg.printChar(prg.strPool[j])
  2343  		j = uint16(int32(j) + 1)
  2344  	}
  2345  
  2346  exit:
  2347  }
  2348  
  2349  func (prg *prg) slowPrint(s int32) { // prints string |s|
  2350  	var (
  2351  		j poolPointer // current character code position
  2352  	)
  2353  	if s >= int32(prg.strPtr) || s < 256 {
  2354  		prg.print(s)
  2355  	} else {
  2356  		j = prg.strStart[s]
  2357  		for int32(j) < int32(prg.strStart[s+1]) {
  2358  			prg.print(int32(prg.strPool[j]))
  2359  			j = uint16(int32(j) + 1)
  2360  		}
  2361  	}
  2362  }
  2363  
  2364  func (prg *prg) printNl(s strNumber) {
  2365  	if int32(prg.termOffset) > 0 && prg.selector&1 != 0 || int32(prg.fileOffset) > 0 && int32(prg.selector) >= logOnly {
  2366  		prg.printLn()
  2367  	}
  2368  	prg.print(int32(s))
  2369  }
  2370  
  2371  func (prg *prg) printEsc(s strNumber) { // prints escape character, then |s|
  2372  	var (
  2373  		c int32 // the escape character code
  2374  	)
  2375  	c = *prg.eqtb[intBase+escapeCharCode-1].int()
  2376  	if c >= 0 {
  2377  		if c < 256 {
  2378  			prg.print(c)
  2379  		}
  2380  	}
  2381  	prg.slowPrint(int32(s))
  2382  }
  2383  
  2384  func (prg *prg) printTheDigs(k eightBits) {
  2385  	for int32(k) > 0 {
  2386  		k = byte(int32(k) - 1)
  2387  		if int32(prg.dig[k]) < 10 {
  2388  			prg.printChar(asciiCode('0' + int32(prg.dig[k])))
  2389  		} else {
  2390  			prg.printChar(asciiCode('A' - 10 + int32(prg.dig[k])))
  2391  		}
  2392  	}
  2393  }
  2394  
  2395  func (prg *prg) printInt(n int32) { // prints an integer in decimal form
  2396  	var (
  2397  		k/* 0..23 */ byte       // index to current digit; we assume that $\vert n\vert<10^[23]$
  2398  		m                 int32 // used to negate |n| in possibly dangerous cases
  2399  	)
  2400  	k = 0
  2401  	if n < 0 {
  2402  		prg.printChar(asciiCode('-'))
  2403  		if n > -100000000 {
  2404  			n = -n
  2405  		} else {
  2406  			m = -1 - n
  2407  			n = m / 10
  2408  			m = m%10 + 1
  2409  			k = 1
  2410  			if m < 10 {
  2411  				prg.dig[0] = byte(m)
  2412  			} else {
  2413  				prg.dig[0] = 0
  2414  				n = n + 1
  2415  			}
  2416  		}
  2417  	}
  2418  	for {
  2419  		prg.dig[k] = byte(n % 10)
  2420  		n = n / 10
  2421  		k = byte(int32(k) + 1)
  2422  		if n == 0 {
  2423  			break
  2424  		}
  2425  	}
  2426  	prg.printTheDigs(k)
  2427  }
  2428  
  2429  func (prg *prg) printCs(p int32) {
  2430  	if p < hashBase {
  2431  		if p >= singleBase {
  2432  			if p == nullCs {
  2433  				prg.printEsc(strNumber( /* "csname" */ 504))
  2434  				prg.printEsc(strNumber( /* "endcsname" */ 505))
  2435  				prg.printChar(asciiCode(' '))
  2436  			} else {
  2437  				prg.printEsc(strNumber(p - singleBase))
  2438  				if int32(*(*prg.eqtb[catCodeBase+p-singleBase-1].hh()).rh()) == letter {
  2439  					prg.printChar(asciiCode(' '))
  2440  				}
  2441  			}
  2442  		} else if p < activeBase {
  2443  			prg.printEsc(strNumber( /* "IMPOSSIBLE." */ 506))
  2444  		} else {
  2445  			prg.print(p - activeBase)
  2446  		}
  2447  	} else if p >= undefinedControlSequence {
  2448  		prg.printEsc(strNumber( /* "IMPOSSIBLE." */ 506))
  2449  	} else if int32(*prg.hash[p-514].rh()) < 0 || int32(*prg.hash[p-514].rh()) >= int32(prg.strPtr) {
  2450  		prg.printEsc(strNumber( /* "NONEXISTENT." */ 507))
  2451  	} else {
  2452  		prg.printEsc(*prg.hash[p-514].rh())
  2453  		prg.printChar(asciiCode(' '))
  2454  	}
  2455  }
  2456  
  2457  func (prg *prg) sprintCs(p halfword) {
  2458  	if int32(p) < hashBase {
  2459  		if int32(p) < singleBase {
  2460  			prg.print(int32(p) - activeBase)
  2461  		} else if int32(p) < nullCs {
  2462  			prg.printEsc(strNumber(int32(p) - singleBase))
  2463  		} else {
  2464  			prg.printEsc(strNumber( /* "csname" */ 504))
  2465  			prg.printEsc(strNumber( /* "endcsname" */ 505))
  2466  		}
  2467  	} else {
  2468  		prg.printEsc(*prg.hash[p-514].rh())
  2469  	}
  2470  }
  2471  
  2472  func (prg *prg) printFileName(n, a, e int32) {
  2473  	prg.slowPrint(a)
  2474  	prg.slowPrint(n)
  2475  	prg.slowPrint(e)
  2476  }
  2477  
  2478  func (prg *prg) printSize(s int32) {
  2479  	if s == textSize {
  2480  		prg.printEsc(strNumber( /* "textfont" */ 412))
  2481  	} else if s == scriptSize {
  2482  		prg.printEsc(strNumber( /* "scriptfont" */ 413))
  2483  	} else {
  2484  		prg.printEsc(strNumber( /* "scriptscriptfont" */ 414))
  2485  	}
  2486  }
  2487  
  2488  func (prg *prg) printWriteWhatsit(s strNumber, p halfword) {
  2489  	prg.printEsc(s)
  2490  	if int32(*(*prg.mem[int32(p)+1].hh()).lh()) < 16 {
  2491  		prg.printInt(int32(*(*prg.mem[int32(p)+1].hh()).lh()))
  2492  	} else if int32(*(*prg.mem[int32(p)+1].hh()).lh()) == 16 {
  2493  		prg.printChar(asciiCode('*'))
  2494  	} else {
  2495  		prg.printChar(asciiCode('-'))
  2496  	}
  2497  } // \2
  2498  
  2499  // \4\hskip-\fontdimen2\font
  2500  //  procedure debug_help;
  2501  //   forward;  [  ]
  2502  
  2503  func (prg *prg) jumpOut() {
  2504  	panic(signal(endOfTex))
  2505  }
  2506  
  2507  func (prg *prg) error1() {
  2508  	var (
  2509  		c              asciiCode // what the user types
  2510  		s1, s2, s3, s4 int32
  2511  	// used to save global variables when deleting tokens
  2512  	)
  2513  	if int32(prg.history) < errorMessageIssued {
  2514  		prg.history = byte(errorMessageIssued)
  2515  	}
  2516  	prg.printChar(asciiCode('.'))
  2517  	prg.showContext()
  2518  	if int32(prg.interaction) == errorStopMode {
  2519  		for true {
  2520  		continue1:
  2521  			if int32(prg.interaction) != errorStopMode {
  2522  				goto exit
  2523  			}
  2524  			prg.clearForErrorPrompt()
  2525  			{
  2526  				prg.print( /* "? " */ 264)
  2527  				prg.termInput()
  2528  			}
  2529  			// \xref[?\relax]
  2530  			if int32(prg.last) == int32(prg.first) {
  2531  				goto exit
  2532  			}
  2533  			c = prg.buffer[prg.first]
  2534  			if int32(c) >= 'a' {
  2535  				c = byte(int32(c) + 'A' - 'a')
  2536  			} // convert to uppercase
  2537  
  2538  			// Interpret code |c| and |return| if done
  2539  			switch c {
  2540  			case '0', '1', '2', '3',
  2541  				'4', '5', '6', '7',
  2542  				'8', '9':
  2543  				if prg.deletionsAllowed {
  2544  					s1 = int32(prg.curTok)
  2545  					s2 = int32(prg.curCmd)
  2546  					s3 = int32(prg.curChr)
  2547  					s4 = prg.alignState
  2548  					prg.alignState = 1000000
  2549  					prg.okToInterrupt = false
  2550  					if int32(prg.last) > int32(prg.first)+1 && int32(prg.buffer[int32(prg.first)+1]) >= '0' && int32(prg.buffer[int32(prg.first)+1]) <= '9' {
  2551  						c = byte(int32(c)*10 + int32(prg.buffer[int32(prg.first)+1]) - '0'*11)
  2552  					} else {
  2553  						c = byte(int32(c) - '0')
  2554  					}
  2555  					for int32(c) > 0 {
  2556  						prg.getToken() // one-level recursive call of |error| is possible
  2557  						c = byte(int32(c) - 1)
  2558  					}
  2559  					prg.curTok = uint16(s1)
  2560  					prg.curCmd = byte(s2)
  2561  					prg.curChr = uint16(s3)
  2562  					prg.alignState = s4
  2563  					prg.okToInterrupt = true
  2564  					{
  2565  						prg.helpPtr = 2
  2566  						prg.helpLine[1] = /* "I have just deleted some text, as you asked." */ 279
  2567  						prg.helpLine[0] = /* "You can now delete more, or insert, or whatever." */ 280
  2568  					}
  2569  					prg.showContext()
  2570  					goto continue1
  2571  				}
  2572  
  2573  			// \4\4
  2574  			//  ["D"=]68: begin debug_help; goto continue; end; [  ]
  2575  
  2576  			// "E"=
  2577  			case 'E':
  2578  				if int32(prg.basePtr) > 0 {
  2579  					if int32(prg.inputStack[prg.basePtr].nameField) >= 256 {
  2580  						prg.printNl(strNumber( /* "You want to edit file " */ 265))
  2581  						// \xref[You want to edit file x]
  2582  						prg.slowPrint(int32(prg.inputStack[prg.basePtr].nameField))
  2583  						prg.print( /* " at line " */ 266)
  2584  						prg.printInt(prg.line)
  2585  						prg.interaction = byte(scrollMode)
  2586  						prg.jumpOut()
  2587  					}
  2588  				}
  2589  			// "H"=
  2590  			case 'H':
  2591  				// Print the help information and |goto continue|
  2592  				if prg.useErrHelp {
  2593  					prg.giveErrHelp()
  2594  					prg.useErrHelp = false
  2595  				} else {
  2596  					if int32(prg.helpPtr) == 0 {
  2597  						prg.helpPtr = 2
  2598  						prg.helpLine[1] = /* "Sorry, I don't know how to help in this situation." */ 281
  2599  						prg.helpLine[0] = /* "Maybe you should try asking a human?" */ 282
  2600  					}
  2601  					for {
  2602  						prg.helpPtr = byte(int32(prg.helpPtr) - 1)
  2603  						prg.print(int32(prg.helpLine[prg.helpPtr]))
  2604  						prg.printLn()
  2605  						if int32(prg.helpPtr) == 0 {
  2606  							break
  2607  						}
  2608  					}
  2609  				}
  2610  				{
  2611  					prg.helpPtr = 4
  2612  					prg.helpLine[3] = /* "Sorry, I already gave what help I could..." */ 283
  2613  					prg.helpLine[2] = /* "Maybe you should try asking a human?" */ 282
  2614  					prg.helpLine[1] = /* "An error might have occurred before I noticed any problems." */ 284
  2615  					prg.helpLine[0] = /* "``If all else fails, read the instructions.''" */ 285
  2616  				}
  2617  
  2618  				goto continue1
  2619  
  2620  			// "I"=
  2621  			case 'I':
  2622  				// Introduce new material from the terminal and |return|
  2623  				prg.beginFileReading() // enter a new syntactic level for terminal input
  2624  				// now |state=mid_line|, so an initial blank space will count as a blank
  2625  				if int32(prg.last) > int32(prg.first)+1 {
  2626  					prg.curInput.locField = uint16(int32(prg.first) + 1)
  2627  					prg.buffer[prg.first] = ' '
  2628  				} else {
  2629  					{
  2630  						prg.print( /* "insert>" */ 278)
  2631  						prg.termInput()
  2632  					}
  2633  					prg.curInput.locField = prg.first
  2634  					// \xref[insert>]
  2635  				}
  2636  				prg.first = prg.last
  2637  				prg.curInput.limitField = uint16(int32(prg.last) - 1) // no |end_line_char| ends this line
  2638  				// no |end_line_char| ends this line
  2639  				goto exit
  2640  
  2641  			// "Q"=
  2642  			case 'Q', 'R', 'S':
  2643  				// Change the interaction level and |return|
  2644  				prg.errorCount = 0
  2645  				prg.interaction = byte(batchMode + int32(c) - 'Q')
  2646  				prg.print( /* "OK, entering " */ 273)
  2647  				switch c {
  2648  				case 'Q':
  2649  					prg.printEsc(strNumber( /* "batchmode" */ 274))
  2650  					prg.selector = byte(int32(prg.selector) - 1)
  2651  
  2652  				// "R"=
  2653  				case 'R':
  2654  					prg.printEsc(strNumber( /* "nonstopmode" */ 275))
  2655  				// "S"=
  2656  				case 'S':
  2657  					prg.printEsc(strNumber( /* "scrollmode" */ 276))
  2658  				} // there are no other cases
  2659  				prg.print( /* "..." */ 277)
  2660  				prg.printLn()
  2661  				goto exit
  2662  
  2663  			// "X"=
  2664  			case 'X':
  2665  				prg.interaction = byte(scrollMode)
  2666  				prg.jumpOut()
  2667  
  2668  			default:
  2669  			}
  2670  
  2671  			// Print the menu of available options
  2672  			{
  2673  				prg.print( /* "Type <return> to proceed, S to scroll future error messages," */ 267)
  2674  
  2675  				// \xref[Type <return> to proceed...]
  2676  				prg.printNl(strNumber( /* "R to run without stopping, Q to run quietly," */ 268))
  2677  
  2678  				prg.printNl(strNumber( /* "I to insert something, " */ 269))
  2679  				if int32(prg.basePtr) > 0 {
  2680  					if int32(prg.inputStack[prg.basePtr].nameField) >= 256 {
  2681  						prg.print( /* "E to edit your file," */ 270)
  2682  					}
  2683  				}
  2684  				if prg.deletionsAllowed {
  2685  					prg.printNl(strNumber( /* "1 or ... or 9 to ignore the next 1 to 9 tokens of input," */ 271))
  2686  				}
  2687  				prg.printNl(strNumber( /* "H for help, X to quit." */ 272))
  2688  			}
  2689  		}
  2690  	}
  2691  	prg.errorCount = int8(int32(prg.errorCount) + 1)
  2692  	if int32(prg.errorCount) == 100 {
  2693  		prg.printNl(strNumber( /* "(That makes 100 errors; please try again.)" */ 263))
  2694  		// \xref[That makes 100 errors...]
  2695  		prg.history = byte(fatalErrorStop)
  2696  		prg.jumpOut()
  2697  	}
  2698  
  2699  	// Put help message on the transcript file
  2700  	if int32(prg.interaction) > batchMode {
  2701  		prg.selector = byte(int32(prg.selector) - 1)
  2702  	} // avoid terminal output
  2703  	if prg.useErrHelp {
  2704  		prg.printLn()
  2705  		prg.giveErrHelp()
  2706  	} else {
  2707  		for int32(prg.helpPtr) > 0 {
  2708  			prg.helpPtr = byte(int32(prg.helpPtr) - 1)
  2709  			prg.printNl(prg.helpLine[prg.helpPtr])
  2710  		}
  2711  	}
  2712  	prg.printLn()
  2713  	if int32(prg.interaction) > batchMode {
  2714  		prg.selector = byte(int32(prg.selector) + 1)
  2715  	} // re-enable terminal output
  2716  	prg.printLn()
  2717  
  2718  exit:
  2719  }
  2720  
  2721  func (prg *prg) fatalError(s strNumber) {
  2722  	prg.normalizeSelector()
  2723  
  2724  	{
  2725  		if int32(prg.interaction) == errorStopMode {
  2726  		}
  2727  		prg.printNl(strNumber( /* "! " */ 262))
  2728  		prg.print( /* "Emergency stop" */ 287)
  2729  	}
  2730  	{
  2731  		prg.helpPtr = 1
  2732  		prg.helpLine[0] = s
  2733  	}
  2734  	{
  2735  		if int32(prg.interaction) == errorStopMode {
  2736  			prg.interaction = byte(scrollMode)
  2737  		}
  2738  		if prg.logOpened {
  2739  			prg.error1()
  2740  		} /*  if interaction>batch_mode then debug_help; [  ] */
  2741  		prg.history = byte(fatalErrorStop)
  2742  		prg.jumpOut()
  2743  	}
  2744  	// \xref[Emergency stop]
  2745  }
  2746  
  2747  func (prg *prg) overflow(s strNumber, n int32) {
  2748  	prg.normalizeSelector()
  2749  	{
  2750  		if int32(prg.interaction) == errorStopMode {
  2751  		}
  2752  		prg.printNl(strNumber( /* "! " */ 262))
  2753  		prg.print( /* "TeX capacity exceeded, sorry [" */ 288)
  2754  	}
  2755  	// \xref[TeX capacity exceeded ...]
  2756  	prg.print(int32(s))
  2757  	prg.printChar(asciiCode('='))
  2758  	prg.printInt(n)
  2759  	prg.printChar(asciiCode(']'))
  2760  	{
  2761  		prg.helpPtr = 2
  2762  		prg.helpLine[1] = /* "If you really absolutely need more capacity," */ 289
  2763  		prg.helpLine[0] = /* "you can ask a wizard to enlarge me." */ 290
  2764  	}
  2765  	{
  2766  		if int32(prg.interaction) == errorStopMode {
  2767  			prg.interaction = byte(scrollMode)
  2768  		}
  2769  		if prg.logOpened {
  2770  			prg.error1()
  2771  		} /*  if interaction>batch_mode then debug_help; [  ] */
  2772  		prg.history = byte(fatalErrorStop)
  2773  		prg.jumpOut()
  2774  	}
  2775  }
  2776  
  2777  func (prg *prg) confusion(s strNumber) {
  2778  	prg.normalizeSelector()
  2779  	if int32(prg.history) < errorMessageIssued {
  2780  		{
  2781  			if int32(prg.interaction) == errorStopMode {
  2782  			}
  2783  			prg.printNl(strNumber( /* "! " */ 262))
  2784  			prg.print( /* "This can't happen (" */ 291)
  2785  		}
  2786  		prg.print(int32(s))
  2787  		prg.printChar(asciiCode(')'))
  2788  		// \xref[This can't happen]
  2789  		{
  2790  			prg.helpPtr = 1
  2791  			prg.helpLine[0] = /* "I'm broken. Please show this to someone who can fix can fix" */ 292
  2792  		}
  2793  	} else {
  2794  		{
  2795  			if int32(prg.interaction) == errorStopMode {
  2796  			}
  2797  			prg.printNl(strNumber( /* "! " */ 262))
  2798  			prg.print( /* "I can't go on meeting you like this" */ 293)
  2799  		}
  2800  		// \xref[I can't go on...]
  2801  		{
  2802  			prg.helpPtr = 2
  2803  			prg.helpLine[1] = /* "One of your faux pas seems to have wounded me deeply..." */ 294
  2804  			prg.helpLine[0] = /* "in fact, I'm barely conscious. Please fix it and try again." */ 295
  2805  		}
  2806  	}
  2807  	{
  2808  		if int32(prg.interaction) == errorStopMode {
  2809  			prg.interaction = byte(scrollMode)
  2810  		}
  2811  		if prg.logOpened {
  2812  			prg.error1()
  2813  		} /*  if interaction>batch_mode then debug_help; [  ] */
  2814  		prg.history = byte(fatalErrorStop)
  2815  		prg.jumpOut()
  2816  	}
  2817  }
  2818  
  2819  // 5.
  2820  
  2821  // tangle:pos tex.web:268:3:
  2822  
  2823  // The overall \TeX\ program begins with the heading just shown, after which
  2824  // comes a bunch of procedure declarations and function declarations.
  2825  // Finally we will get to the main program, which begins with the
  2826  // comment `|start_here|'. If you want to skip down to the
  2827  // main program now, you can look up `|start_here|' in the index.
  2828  // But the author suggests that the best way to understand this program
  2829  // is to follow pretty much the order of \TeX's components as they appear in the
  2830  // \.[WEB] description you are now reading, since the present ordering is
  2831  // intended to combine the advantages of the ``bottom up'' and ``top down''
  2832  // approaches to the problem of understanding a somewhat complicated system.
  2833  
  2834  // 7.
  2835  
  2836  // tangle:pos tex.web:290:3:
  2837  
  2838  // Some of the code below is intended to be used only when diagnosing the
  2839  // strange behavior that sometimes occurs when \TeX\ is being installed or
  2840  // when system wizards are fooling around with \TeX\ without quite knowing
  2841  // what they are doing. Such code will not normally be compiled; it is
  2842  // delimited by the codewords `$|debug|\ldots|gubed|$', with apologies
  2843  // to people who wish to preserve the purity of English.
  2844  //
  2845  // Similarly, there is some conditional code delimited by
  2846  // `$|stat|\ldots|tats|$' that is intended for use when statistics are to be
  2847  // kept about \TeX's memory usage.  The |stat| $\ldots$ |tats| code also
  2848  // implements diagnostic information for \.[\\tracingparagraphs],
  2849  // \.[\\tracingpages], and \.[\\tracingrestores].
  2850  // \xref[debugging]
  2851  
  2852  // 10.
  2853  
  2854  // tangle:pos tex.web:348:3:
  2855  
  2856  // This \TeX\ implementation conforms to the rules of the [\sl Pascal User
  2857  // \xref[PASCAL][\PASCAL]
  2858  // \xref[system dependencies]
  2859  // Manual] published by Jensen and Wirth in 1975, except where system-dependent
  2860  // \xref[Wirth, Niklaus]
  2861  // \xref[Jensen, Kathleen]
  2862  // code is necessary to make a useful system program, and except in another
  2863  // respect where such conformity would unnecessarily obscure the meaning
  2864  // and clutter up the code: We assume that |case| statements may include a
  2865  // default case that applies if no matching label is found. Thus, we shall use
  2866  // constructions like
  2867  // $$\vbox[\halign[\ignorespaces#\hfil\cr
  2868  // |case x of|\cr
  2869  // 1: $\langle\,$code for $x=1\,\rangle$;\cr
  2870  // 3: $\langle\,$code for $x=3\,\rangle$;\cr
  2871  // |othercases| $\langle\,$code for |x<>1| and |x<>3|$\,\rangle$\cr
  2872  // |endcases|\cr]]$$
  2873  // since most \PASCAL\ compilers have plugged this hole in the language by
  2874  // incorporating some sort of default mechanism. For example, the \ph\
  2875  // compiler allows `|others|:' as a default label, and other \PASCAL s allow
  2876  // syntaxes like `\&[else]' or `\&[otherwise]' or `\\[otherwise]:', etc. The
  2877  // definitions of |othercases| and |endcases| should be changed to agree with
  2878  // local conventions.  Note that no semicolon appears before |endcases| in
  2879  // this program, so the definition of |endcases| should include a semicolon
  2880  // if the compiler wants one. (Of course, if no default mechanism is
  2881  // available, the |case| statements of \TeX\ will have to be laboriously
  2882  // extended by listing all remaining cases. People who are stuck with such
  2883  // \PASCAL s have, in fact, done this, successfully but not happily!)
  2884  // \xref[PASCAL H][\ph]
  2885  
  2886  // 12.
  2887  
  2888  // tangle:pos tex.web:430:3:
  2889  
  2890  // Like the preceding parameters, the following quantities can be changed
  2891  // at compile time to extend or reduce \TeX's capacity. But if they are changed,
  2892  // it is necessary to rerun the initialization program \.[INITEX]
  2893  // \xref[INITEX]
  2894  // to generate new tables for the production \TeX\ program.
  2895  // One can't simply make helter-skelter changes to the following constants,
  2896  // since certain rather complex initialization
  2897  // numbers are computed from them. They are defined here using
  2898  // \.[WEB] macros, instead of being put into \PASCAL's |const| list, in order to
  2899  // emphasize this distinction.
  2900  
  2901  // 15.
  2902  
  2903  // tangle:pos tex.web:476:3:
  2904  
  2905  // Labels are given symbolic names by the following definitions, so that
  2906  // occasional |goto| statements will be meaningful. We insert the label
  2907  // `|exit|' just before the `\ignorespaces|end|\unskip' of a procedure in
  2908  // which we have used the `|return|' statement defined below; the label
  2909  // `|restart|' is occasionally used at the very beginning of a procedure; and
  2910  // the label `|reswitch|' is occasionally used just prior to a |case|
  2911  // statement in which some cases change the conditions and we wish to branch
  2912  // to the newly applicable case.  Loops that are set up with the |loop|
  2913  // construction defined below are commonly exited by going to `|done|' or to
  2914  // `|found|' or to `|not_found|', and they are sometimes repeated by going to
  2915  // `|continue|'.  If two or more parts of a subroutine start differently but
  2916  // end up the same, the shared code may be gathered together at
  2917  // `|common_ending|'.
  2918  //
  2919  // Incidentally, this program never declares a label that isn't actually used,
  2920  // because some fussy \PASCAL\ compilers will complain about redundant labels.
  2921  
  2922  // 16.
  2923  
  2924  // tangle:pos tex.web:510:3:
  2925  
  2926  // Here are some macros for common programming idioms.
  2927  
  2928  // 17. \[2] The character set
  2929  
  2930  // tangle:pos tex.web:523:27:
  2931  
  2932  // In order to make \TeX\ readily portable to a wide variety of
  2933  // computers, all of its input text is converted to an internal eight-bit
  2934  // code that includes standard ASCII, the ``American Standard Code for
  2935  // Information Interchange.''  This conversion is done immediately when each
  2936  // character is read in. Conversely, characters are converted from ASCII to
  2937  // the user's external representation just before they are output to a
  2938  // text file.
  2939  //
  2940  // Such an internal code is relevant to users of \TeX\ primarily because it
  2941  // governs the positions of characters in the fonts. For example, the
  2942  // character `\.A' has ASCII code $65=@'101$, and when \TeX\ typesets
  2943  // this letter it specifies character number 65 in the current font.
  2944  // If that font actually has `\.A' in a different position, \TeX\ doesn't
  2945  // know what the real position is; the program that does the actual printing from
  2946  // \TeX's device-independent files is responsible for converting from ASCII to
  2947  // a particular font encoding.
  2948  // \xref[ASCII code]
  2949  //
  2950  // \TeX's internal code also defines the value of constants
  2951  // that begin with a reverse apostrophe; and it provides an index to the
  2952  // \.[\\catcode], \.[\\mathcode], \.[\\uccode], \.[\\lccode], and \.[\\delcode]
  2953  // tables.
  2954  
  2955  // 22.
  2956  
  2957  // tangle:pos tex.web:702:3:
  2958  
  2959  // Some of the ASCII codes without visible characters have been given symbolic
  2960  // names in this program because they are used with a special meaning.
  2961  
  2962  // 27.
  2963  
  2964  // tangle:pos tex.web:808:3:
  2965  
  2966  // The \ph\ compiler with which the present version of \TeX\ was prepared has
  2967  // extended the rules of \PASCAL\ in a very convenient way. To open file~|f|,
  2968  // we can write
  2969  // $$\vbox[\halign[#\hfil\qquad&#\hfil\cr
  2970  // |reset(f,\\[name],'/O')|&for input;\cr
  2971  // |rewrite(f,\\[name],'/O')|&for output.\cr]]$$
  2972  // The `\\[name]' parameter, which is of type `[\bf packed array
  2973  // $[\langle\\[any]\rangle]$ of \\[char]]', stands for the name of
  2974  // the external file that is being opened for input or output.
  2975  // Blank spaces that might appear in \\[name] are ignored.
  2976  //
  2977  // The `\.[/O]' parameter tells the operating system not to issue its own
  2978  // error messages if something goes wrong. If a file of the specified name
  2979  // cannot be found, or if such a file cannot be opened for some other reason
  2980  // (e.g., someone may already be trying to write the same file), we will have
  2981  // | erstat(f)<>0| after an unsuccessful |reset| or |rewrite|.  This allows
  2982  // \TeX\ to undertake appropriate corrective action.
  2983  // \xref[PASCAL H][\ph]
  2984  // \xref[system dependencies]
  2985  //
  2986  // \TeX's file-opening procedures return |false| if no file identified by
  2987  // |name_of_file| could be opened.
  2988  func (prg *prg) aOpenIn(f alphaFile) (r bool) {
  2989  	f.Reset(arraystr(prg.nameOfFile[:]), "/O")
  2990  	r = f.ErStat() == 0
  2991  	return r
  2992  }
  2993  
  2994  func (prg *prg) aOpenOut(f alphaFile) (r bool) {
  2995  	f.Rewrite(arraystr(prg.nameOfFile[:]), "/O")
  2996  	r = f.ErStat() == 0
  2997  	return r
  2998  }
  2999  
  3000  func (prg *prg) bOpenIn(f byteFile) (r bool) {
  3001  	f.Reset(arraystr(prg.nameOfFile[:]), "/O")
  3002  	r = f.ErStat() == 0
  3003  	return r
  3004  }
  3005  
  3006  func (prg *prg) bOpenOut(f byteFile) (r bool) {
  3007  	f.Rewrite(arraystr(prg.nameOfFile[:]), "/O")
  3008  	r = f.ErStat() == 0
  3009  	return r
  3010  }
  3011  
  3012  func (prg *prg) wOpenIn(f wordFile) (r bool) {
  3013  	f.Reset(arraystr(prg.nameOfFile[:]), "/O")
  3014  	r = f.ErStat() == 0
  3015  	return r
  3016  }
  3017  
  3018  func (prg *prg) wOpenOut(f wordFile) (r bool) {
  3019  	f.Rewrite(arraystr(prg.nameOfFile[:]), "/O")
  3020  	r = f.ErStat() == 0
  3021  	return r
  3022  }
  3023  
  3024  // 28.
  3025  
  3026  // tangle:pos tex.web:864:3:
  3027  
  3028  // Files can be closed with the \ph\ routine `|close(f)|', which
  3029  // \xref[PASCAL H][\ph]
  3030  // \xref[system dependencies]
  3031  // should be used when all input or output with respect to |f| has been completed.
  3032  // This makes |f| available to be opened again, if desired; and if |f| was used for
  3033  // output, the |close| operation makes the corresponding external file appear
  3034  // on the user's area, ready to be read.
  3035  //
  3036  // These procedures should not generate error messages if a file is
  3037  // being closed before it has been successfully opened.
  3038  func (prg *prg) aClose(f alphaFile) {
  3039  	f.Close()
  3040  }
  3041  
  3042  func (prg *prg) bClose(f byteFile) {
  3043  	f.Close()
  3044  }
  3045  
  3046  func (prg *prg) wClose(f wordFile) {
  3047  	f.Close()
  3048  }
  3049  
  3050  // 29.
  3051  
  3052  // tangle:pos tex.web:887:3:
  3053  
  3054  // Binary input and output are done with \PASCAL's ordinary |get| and |put|
  3055  // procedures, so we don't have to make any other special arrangements for
  3056  // binary~I/O. Text output is also easy to do with standard \PASCAL\ routines.
  3057  // The treatment of text input is more difficult, however, because
  3058  // of the necessary translation to |ASCII_code| values.
  3059  // \TeX's conventions should be efficient, and they should
  3060  // blend nicely with the user's operating environment.
  3061  
  3062  // 31.
  3063  
  3064  // tangle:pos tex.web:908:3:
  3065  
  3066  // The |input_ln| function brings the next line of input from the specified
  3067  // file into available positions of the buffer array and returns the value
  3068  // |true|, unless the file has already been entirely read, in which case it
  3069  // returns |false| and sets |last:=first|.  In general, the |ASCII_code|
  3070  // numbers that represent the next line of the file are input into
  3071  // |buffer[first]|, |buffer[first+1]|, \dots, |buffer[last-1]|; and the
  3072  // global variable |last| is set equal to |first| plus the length of the
  3073  // line. Trailing blanks are removed from the line; thus, either |last=first|
  3074  // (in which case the line was entirely blank) or |buffer[last-1]<>" "|.
  3075  //
  3076  // An overflow error is given, however, if the normal actions of |input_ln|
  3077  // would make |last>=buf_size|; this is done so that other parts of \TeX\
  3078  // can safely look at the contents of |buffer[last+1]| without overstepping
  3079  // the bounds of the |buffer| array. Upon entry to |input_ln|, the condition
  3080  // |first<buf_size| will always hold, so that there is always room for an
  3081  // ``empty'' line.
  3082  //
  3083  // The variable |max_buf_stack|, which is used to keep track of how large
  3084  // the |buf_size| parameter must be to accommodate the present job, is
  3085  // also kept up to date by |input_ln|.
  3086  //
  3087  // If the |bypass_eoln| parameter is |true|, |input_ln| will do a |get|
  3088  // before looking at the first character of the line; this skips over
  3089  // an |eoln| that was in |f^|. The procedure does not do a |get| when it
  3090  // reaches the end of the line; therefore it can be used to acquire input
  3091  // from the user's terminal as well as from ordinary text files.
  3092  //
  3093  // Standard \PASCAL\ says that a file should have |eoln| immediately
  3094  // before |eof|, but \TeX\ needs only a weaker restriction: If |eof|
  3095  // occurs in the middle of a line, the system function |eoln| should return
  3096  // a |true| result (even though |f^| will be undefined).
  3097  //
  3098  // Since the inner loop of |input_ln| is part of \TeX's ``inner loop''---each
  3099  // character of input comes in at this place---it is wise to reduce system
  3100  // overhead by making use of special routines that read in an entire array
  3101  // of characters at once, if such routines are available. The following
  3102  // code uses standard \PASCAL\ to illustrate what needs to be done, but
  3103  // finer tuning is often possible at well-developed \PASCAL\ sites.
  3104  // \xref[inner loop]
  3105  func (prg *prg) inputLn(f alphaFile, bypassEoln bool) (r bool) {
  3106  	// inputs the next line or returns |false|
  3107  	var (
  3108  		lastNonblank /* 0..bufSize */ uint16 // |last| with trailing blanks removed
  3109  	)
  3110  	if bypassEoln {
  3111  		if !f.EOF() && f.EOLN() {
  3112  			f.Get()
  3113  		}
  3114  	}
  3115  	// input the first character of the line into |f^|
  3116  	prg.last = prg.first // cf.\ Matthew 19\thinspace:\thinspace30
  3117  	if f.EOF() {
  3118  		r = false
  3119  	} else {
  3120  		lastNonblank = prg.first
  3121  		for !f.EOLN() {
  3122  			if int32(prg.last) >= int32(prg.maxBufStack) {
  3123  				prg.maxBufStack = uint16(int32(prg.last) + 1)
  3124  				if int32(prg.maxBufStack) == bufSize {
  3125  					if int32(prg.formatIdent) == 0 {
  3126  						prg.termOut.Writeln("Buffer size exceeded!")
  3127  						panic(signal(finalEnd))
  3128  						// \xref[Buffer size exceeded]
  3129  					} else {
  3130  						prg.curInput.locField = prg.first
  3131  						prg.curInput.limitField = uint16(int32(prg.last) - 1)
  3132  						prg.overflow(strNumber( /* "buffer size" */ 256), bufSize)
  3133  						// \xref[TeX capacity exceeded buffer size][\quad buffer size]
  3134  					}
  3135  				}
  3136  			}
  3137  			prg.buffer[prg.last] = prg.xord[*f.ByteP()]
  3138  			f.Get()
  3139  			prg.last = uint16(int32(prg.last) + 1)
  3140  			if int32(prg.buffer[int32(prg.last)-1]) != ' ' {
  3141  				lastNonblank = prg.last
  3142  			}
  3143  		}
  3144  		prg.last = lastNonblank
  3145  		r = true
  3146  	}
  3147  	return r
  3148  }
  3149  
  3150  // 33.
  3151  
  3152  // tangle:pos tex.web:979:3:
  3153  
  3154  // Here is how to open the terminal files
  3155  // in \ph. The `\.[/I]' switch suppresses the first |get|.
  3156  // \xref[PASCAL H][\ph]
  3157  // \xref[system dependencies]
  3158  
  3159  // 34.
  3160  
  3161  // tangle:pos tex.web:987:3:
  3162  
  3163  // Sometimes it is necessary to synchronize the input/output mixture that
  3164  // happens on the user's terminal, and three system-dependent
  3165  // procedures are used for this
  3166  // purpose. The first of these, |update_terminal|, is called when we want
  3167  // to make sure that everything we have output to the terminal so far has
  3168  // actually left the computer's internal buffers and been sent.
  3169  // The second, |clear_terminal|, is called when we wish to cancel any
  3170  // input that the user may have typed ahead (since we are about to
  3171  // issue an unexpected error message). The third, |wake_up_terminal|,
  3172  // is supposed to revive the terminal if the user has disabled it by
  3173  // some instruction to the operating system.  The following macros show how
  3174  // these operations can be specified in \ph:
  3175  // \xref[PASCAL H][\ph]
  3176  // \xref[system dependencies]
  3177  
  3178  // 36.
  3179  
  3180  // tangle:pos tex.web:1044:3:
  3181  
  3182  // Different systems have different ways to get started. But regardless of
  3183  // what conventions are adopted, the routine that initializes the terminal
  3184  // should satisfy the following specifications:
  3185  //
  3186  // \yskip\textindent[1)]It should open file |term_in| for input from the
  3187  //   terminal. (The file |term_out| will already be open for output to the
  3188  //   terminal.)
  3189  //
  3190  // \textindent[2)]If the user has given a command line, this line should be
  3191  //   considered the first line of terminal input. Otherwise the
  3192  //   user should be prompted with `\.[**]', and the first line of input
  3193  //   should be whatever is typed in response.
  3194  //
  3195  // \textindent[3)]The first line of input, which might or might not be a
  3196  //   command line, should appear in locations |first| to |last-1| of the
  3197  //   |buffer| array.
  3198  //
  3199  // \textindent[4)]The global variable |loc| should be set so that the
  3200  //   character to be read next by \TeX\ is in |buffer[loc]|. This
  3201  //   character should not be blank, and we should have |loc<last|.
  3202  //
  3203  // \yskip\noindent(It may be necessary to prompt the user several times
  3204  // before a non-blank line comes in. The prompt is `\.[**]' instead of the
  3205  // later `\.*' because the meaning is slightly different: `\.[\\input]' need
  3206  // not be typed immediately after~`\.[**]'.)
  3207  
  3208  // 37.
  3209  
  3210  // tangle:pos tex.web:1072:3:
  3211  
  3212  // The following program does the required initialization
  3213  // without retrieving a possible command line.
  3214  // It should be clear how to modify this routine to deal with command lines,
  3215  // if the system permits them.
  3216  // \xref[system dependencies]
  3217  func (prg *prg) initTerminal() (r bool) {
  3218  	prg.termIn.Reset("TTY:", "/O/I")
  3219  	for true {
  3220  		prg.termOut.Write("**")
  3221  		// \xref[**]
  3222  		if !prg.inputLn(prg.termIn, true) {
  3223  			prg.termOut.Writeln()
  3224  			prg.termOut.Writeln("! End of file on the terminal... why?")
  3225  			// \xref[End of file on the terminal]
  3226  			r = false
  3227  			goto exit
  3228  		}
  3229  		prg.curInput.locField = prg.first
  3230  		for int32(prg.curInput.locField) < int32(prg.last) && int32(prg.buffer[prg.curInput.locField]) == ' ' {
  3231  			prg.curInput.locField = uint16(int32(prg.curInput.locField) + 1)
  3232  		}
  3233  		if int32(prg.curInput.locField) < int32(prg.last) {
  3234  			r = true
  3235  
  3236  			goto exit // return unless the line was all blank
  3237  		}
  3238  		prg.termOut.Writeln("Please type the name of your input file.")
  3239  	}
  3240  
  3241  exit:
  3242  	;
  3243  	return r
  3244  }
  3245  
  3246  // 40.
  3247  
  3248  // tangle:pos tex.web:1156:3:
  3249  
  3250  // Several of the elementary string operations are performed using \.[WEB]
  3251  // macros instead of \PASCAL\ procedures, because many of the
  3252  // operations are done quite frequently and we want to avoid the
  3253  // overhead of procedure calls. For example, here is
  3254  // a simple macro that computes the length of a string.
  3255  // \xref[WEB]
  3256  
  3257  // 41.
  3258  
  3259  // tangle:pos tex.web:1166:3:
  3260  
  3261  // The length of the current string is called |cur_length|:
  3262  
  3263  // 42.
  3264  
  3265  // tangle:pos tex.web:1170:3:
  3266  
  3267  // Strings are created by appending character codes to |str_pool|.
  3268  // The |append_char| macro, defined here, does not check to see if the
  3269  // value of |pool_ptr| has gotten too high; this test is supposed to be
  3270  // made before |append_char| is used. There is also a |flush_char|
  3271  // macro, which erases the last character appended.
  3272  //
  3273  // To test if there is room to append |l| more characters to |str_pool|,
  3274  // we shall write |str_room(l)|, which aborts \TeX\ and gives an
  3275  // apologetic error message if there isn't enough room.
  3276  
  3277  // 43.
  3278  
  3279  // tangle:pos tex.web:1190:3:
  3280  
  3281  // Once a sequence of characters has been appended to |str_pool|, it
  3282  // officially becomes a string when the function |make_string| is called.
  3283  // This function returns the identification number of the new string as its
  3284  // value.
  3285  func (prg *prg) makeString() (r strNumber) {
  3286  	if int32(prg.strPtr) == maxStrings {
  3287  		prg.overflow(strNumber( /* "number of strings" */ 258), maxStrings-int32(prg.initStrPtr))
  3288  	}
  3289  	// \xref[TeX capacity exceeded number of strings][\quad number of strings]
  3290  	prg.strPtr = uint16(int32(prg.strPtr) + 1)
  3291  	prg.strStart[prg.strPtr] = prg.poolPtr
  3292  	r = uint16(int32(prg.strPtr) - 1)
  3293  	return r
  3294  }
  3295  
  3296  // 44.
  3297  
  3298  // tangle:pos tex.web:1203:3:
  3299  
  3300  // To destroy the most recently made string, we say |flush_string|.
  3301  
  3302  // 45.
  3303  
  3304  // tangle:pos tex.web:1208:3:
  3305  
  3306  // The following subroutine compares string |s| with another string of the
  3307  // same length that appears in |buffer| starting at position |k|;
  3308  // the result is |true| if and only if the strings are equal.
  3309  // Empirical tests indicate that |str_eq_buf| is used in such a way that
  3310  // it tends to return |true| about 80 percent of the time.
  3311  func (prg *prg) strEqBuf(s strNumber, k int32) (r bool) { // loop exit
  3312  	var (
  3313  		j      poolPointer // running index
  3314  		result bool        // result of comparison
  3315  	)
  3316  	j = prg.strStart[s]
  3317  	for int32(j) < int32(prg.strStart[int32(s)+1]) {
  3318  		if int32(prg.strPool[j]) != int32(prg.buffer[k]) {
  3319  			result = false
  3320  			goto notFound
  3321  		}
  3322  		j = uint16(int32(j) + 1)
  3323  		k = k + 1
  3324  	}
  3325  	result = true
  3326  
  3327  notFound:
  3328  	r = result
  3329  	return r
  3330  }
  3331  
  3332  // 46.
  3333  
  3334  // tangle:pos tex.web:1230:3:
  3335  
  3336  // Here is a similar routine, but it compares two strings in the string pool,
  3337  // and it does not assume that they have the same length.
  3338  func (prg *prg) strEqStr(s, t strNumber) (r bool) { // loop exit
  3339  	var (
  3340  		j, k   poolPointer // running indices
  3341  		result bool        // result of comparison
  3342  	)
  3343  	result = false
  3344  	if int32(prg.strStart[int32(s)+1])-int32(prg.strStart[s]) != int32(prg.strStart[int32(t)+1])-int32(prg.strStart[t]) {
  3345  		goto notFound
  3346  	}
  3347  	j = prg.strStart[s]
  3348  	k = prg.strStart[t]
  3349  	for int32(j) < int32(prg.strStart[int32(s)+1]) {
  3350  		if int32(prg.strPool[j]) != int32(prg.strPool[k]) {
  3351  			goto notFound
  3352  		}
  3353  		j = uint16(int32(j) + 1)
  3354  		k = uint16(int32(k) + 1)
  3355  	}
  3356  	result = true
  3357  
  3358  notFound:
  3359  	r = result
  3360  	return r
  3361  }
  3362  
  3363  // 47.
  3364  
  3365  // tangle:pos tex.web:1249:3:
  3366  
  3367  // The initial values of |str_pool|, |str_start|, |pool_ptr|,
  3368  // and |str_ptr| are computed by the \.[INITEX] program, based in part
  3369  // on the information that \.[WEB] has output while processing \TeX.
  3370  // \xref[INITEX]
  3371  // \xref[string pool]
  3372  func (prg *prg) getStringsStarted() (r bool) {
  3373  	var (
  3374  		k, l/* 0..255 */ byte           // small indices or counters
  3375  		m, n                  char      // characters input from |pool_file|
  3376  		g                     strNumber // garbage
  3377  		a                     int32     // accumulator for check sum
  3378  		c                     bool      // check sum has been checked
  3379  	)
  3380  	if int32(g) == 0 {
  3381  	}
  3382  	prg.poolPtr = 0
  3383  	prg.strPtr = 0
  3384  	prg.strStart[0] = 0
  3385  
  3386  	// Make the first 256 strings
  3387  	for ii := int32(0); ii <= 255; ii++ {
  3388  		k = byte(ii)
  3389  		_ = k
  3390  		if int32(k) < ' ' || int32(k) > '~' {
  3391  			{
  3392  				prg.strPool[prg.poolPtr] = '^'
  3393  				prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  3394  			}
  3395  			{
  3396  				prg.strPool[prg.poolPtr] = '^'
  3397  				prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  3398  			}
  3399  			if int32(k) < 0100 {
  3400  				prg.strPool[prg.poolPtr] = byte(int32(k) + 0100)
  3401  				prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  3402  			} else if int32(k) < 0200 {
  3403  				prg.strPool[prg.poolPtr] = byte(int32(k) - 0100)
  3404  				prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  3405  			} else {
  3406  				l = byte(int32(k) / 16)
  3407  				if int32(l) < 10 {
  3408  					prg.strPool[prg.poolPtr] = byte(int32(l) + '0')
  3409  					prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  3410  				} else {
  3411  					prg.strPool[prg.poolPtr] = byte(int32(l) - 10 + 'a')
  3412  					prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  3413  				}
  3414  				l = byte(int32(k) % 16)
  3415  				if int32(l) < 10 {
  3416  					prg.strPool[prg.poolPtr] = byte(int32(l) + '0')
  3417  					prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  3418  				} else {
  3419  					prg.strPool[prg.poolPtr] = byte(int32(l) - 10 + 'a')
  3420  					prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  3421  				}
  3422  			}
  3423  		} else {
  3424  			prg.strPool[prg.poolPtr] = k
  3425  			prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  3426  		}
  3427  		g = prg.makeString()
  3428  	}
  3429  
  3430  	// Read the other strings from the \.[TEX.POOL] file and return |true|, or give an error message and return |false|
  3431  	strcopy(prg.nameOfFile[:], "TeXformats:TEX.POOL                     ") // we needn't set |name_length|
  3432  	if prg.aOpenIn(prg.poolFile) {
  3433  		c = false
  3434  		for {
  3435  			// Read one string, but return |false| if the string memory space is getting too tight for comfort
  3436  			{
  3437  				if prg.poolFile.EOF() {
  3438  					prg.termOut.Writeln("! TEX.POOL has no check sum.")
  3439  					prg.aClose(prg.poolFile)
  3440  					r = false
  3441  					goto exit
  3442  				}
  3443  				// \xref[TEX.POOL has no check sum]
  3444  				prg.poolFile.Read(&m, &n) // read two digits of string length
  3445  				if int32(m) == '*' {
  3446  					a = 0
  3447  					k = 1
  3448  					for true {
  3449  						if int32(prg.xord[n]) < '0' || int32(prg.xord[n]) > '9' {
  3450  							prg.termOut.Writeln("! TEX.POOL check sum doesn't have nine digits.")
  3451  							prg.aClose(prg.poolFile)
  3452  							r = false
  3453  							goto exit
  3454  						}
  3455  						// \xref[TEX.POOL check sum...]
  3456  						a = 10*a + int32(prg.xord[n]) - '0'
  3457  						if int32(k) == 9 {
  3458  							goto done
  3459  						}
  3460  						k = byte(int32(k) + 1)
  3461  						prg.poolFile.Read(&n)
  3462  					}
  3463  
  3464  				done:
  3465  					if a != 504454778 {
  3466  						prg.termOut.Writeln("! TEX.POOL doesn't match; TANGLE me again.")
  3467  						prg.aClose(prg.poolFile)
  3468  						r = false
  3469  						goto exit
  3470  					}
  3471  					// \xref[TEX.POOL doesn't match]
  3472  					c = true
  3473  				} else {
  3474  					if int32(prg.xord[m]) < '0' || int32(prg.xord[m]) > '9' || int32(prg.xord[n]) < '0' || int32(prg.xord[n]) > '9' {
  3475  						prg.termOut.Writeln("! TEX.POOL line doesn't begin with two digits.")
  3476  						prg.aClose(prg.poolFile)
  3477  						r = false
  3478  						goto exit
  3479  					}
  3480  					// \xref[TEX.POOL line doesn't...]
  3481  					l = byte(int32(prg.xord[m])*10 + int32(prg.xord[n]) - '0'*11) // compute the length
  3482  					if int32(prg.poolPtr)+int32(l)+stringVacancies > poolSize {
  3483  						prg.termOut.Writeln("! You have to increase POOLSIZE.")
  3484  						prg.aClose(prg.poolFile)
  3485  						r = false
  3486  						goto exit
  3487  					}
  3488  					// \xref[You have to increase POOLSIZE]
  3489  					for ii := int32(1); ii <= int32(l); ii++ {
  3490  						k = byte(ii)
  3491  						_ = k
  3492  						if prg.poolFile.EOLN() {
  3493  							m = ' '
  3494  						} else {
  3495  							prg.poolFile.Read(&m)
  3496  						}
  3497  						{
  3498  							prg.strPool[prg.poolPtr] = prg.xord[m]
  3499  							prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  3500  						}
  3501  					}
  3502  					prg.poolFile.Readln()
  3503  					g = prg.makeString()
  3504  				}
  3505  			}
  3506  			if c {
  3507  				break
  3508  			}
  3509  		}
  3510  		prg.aClose(prg.poolFile)
  3511  		r = true
  3512  	} else {
  3513  		prg.termOut.Writeln("! I can't read TEX.POOL.")
  3514  		prg.aClose(prg.poolFile)
  3515  		r = false
  3516  		goto exit
  3517  	}
  3518  
  3519  exit:
  3520  	;
  3521  	return r
  3522  }
  3523  
  3524  // 56.
  3525  
  3526  // tangle:pos tex.web:1448:3:
  3527  
  3528  // Macro abbreviations for output to the terminal and to the log file are
  3529  // defined here for convenience. Some systems need special conventions
  3530  // for terminal output, and it is possible to adhere to those conventions
  3531  // by changing |wterm|, |wterm_ln|, and |wterm_cr| in this section.
  3532  // \xref[system dependencies]
  3533  
  3534  // 66.
  3535  
  3536  // tangle:pos tex.web:1638:3:
  3537  
  3538  // Here is a trivial procedure to print two digits; it is usually called with
  3539  // a parameter in the range |0<=n<=99|.
  3540  func (prg *prg) printTwo(n int32) {
  3541  	n = abs(n) % 100
  3542  	prg.printChar(asciiCode('0' + n/10))
  3543  	prg.printChar(asciiCode('0' + n%10))
  3544  }
  3545  
  3546  // 67.
  3547  
  3548  // tangle:pos tex.web:1646:3:
  3549  
  3550  // Hexadecimal printing of nonnegative integers is accomplished by |print_hex|.
  3551  func (prg *prg) printHex(n int32) {
  3552  	// prints a positive integer in hexadecimal form
  3553  	var (
  3554  		k /* 0..22 */ byte // index to current digit; we assume that $0\L n<16^[22]$
  3555  	)
  3556  	k = 0
  3557  	prg.printChar(asciiCode('"'))
  3558  	for {
  3559  		prg.dig[k] = byte(n % 16)
  3560  		n = n / 16
  3561  		k = byte(int32(k) + 1)
  3562  		if n == 0 {
  3563  			break
  3564  		}
  3565  	}
  3566  	prg.printTheDigs(k)
  3567  }
  3568  
  3569  // 68.
  3570  
  3571  // tangle:pos tex.web:1657:3:
  3572  
  3573  // Old versions of \TeX\ needed a procedure called |print_ASCII| whose function
  3574  // is now subsumed by |print|. We retain the old name here as a possible aid to
  3575  // future software arch\ae ologists.
  3576  
  3577  // 69.
  3578  
  3579  // tangle:pos tex.web:1663:3:
  3580  
  3581  // Roman numerals are produced by the |print_roman_int| routine.  Readers
  3582  // who like puzzles might enjoy trying to figure out how this tricky code
  3583  // works; therefore no explanation will be given. Notice that 1990 yields
  3584  // \.[mcmxc], not \.[mxm].
  3585  func (prg *prg) printRomanInt(n int32) {
  3586  	var (
  3587  		j, k poolPointer        // mysterious indices into |str_pool|
  3588  		u, v nonnegativeInteger // mysterious numbers
  3589  	)
  3590  	j = prg.strStart[ /* "m2d5c2l5x2v5i" */ 260]
  3591  	v = 1000
  3592  	for true {
  3593  		for n >= int32(v) {
  3594  			prg.printChar(prg.strPool[j])
  3595  			n = n - int32(v)
  3596  		}
  3597  		if n <= 0 {
  3598  			goto exit
  3599  		} // nonpositive input produces no output
  3600  		k = uint16(int32(j) + 2)
  3601  		u = uint32(int32(v) / (int32(prg.strPool[int32(k)-1]) - '0'))
  3602  		if int32(prg.strPool[int32(k)-1]) == '2' {
  3603  			k = uint16(int32(k) + 2)
  3604  			u = uint32(int32(u) / (int32(prg.strPool[int32(k)-1]) - '0'))
  3605  		}
  3606  		if n+int32(u) >= int32(v) {
  3607  			prg.printChar(prg.strPool[k])
  3608  			n = n + int32(u)
  3609  		} else {
  3610  			j = uint16(int32(j) + 2)
  3611  			v = uint32(int32(v) / (int32(prg.strPool[int32(j)-1]) - '0'))
  3612  		}
  3613  	}
  3614  
  3615  exit:
  3616  }
  3617  
  3618  // 70.
  3619  
  3620  // tangle:pos tex.web:1689:3:
  3621  
  3622  // The |print| subroutine will not print a string that is still being
  3623  // created. The following procedure will.
  3624  func (prg *prg) printCurrentString() { // prints a yet-unmade string
  3625  	var (
  3626  		j poolPointer // points to current character code
  3627  	)
  3628  	j = prg.strStart[prg.strPtr]
  3629  	for int32(j) < int32(prg.poolPtr) {
  3630  		prg.printChar(prg.strPool[j])
  3631  		j = uint16(int32(j) + 1)
  3632  	}
  3633  } // \2
  3634  
  3635  func (prg *prg) termInput() { // gets a line from the terminal
  3636  	var (
  3637  		k /* 0..bufSize */ uint16 // index into |buffer|
  3638  	) // now the user sees the prompt for sure
  3639  	if !prg.inputLn(prg.termIn, true) {
  3640  		prg.fatalError(strNumber( /* "End of file on the terminal!" */ 261))
  3641  	}
  3642  	// \xref[End of file on the terminal]
  3643  	prg.termOffset = 0                           // the user's line ended with \<\rm return>
  3644  	prg.selector = byte(int32(prg.selector) - 1) // prepare to echo the input
  3645  	if int32(prg.last) != int32(prg.first) {
  3646  		for ii := int32(prg.first); ii <= int32(prg.last)-1; ii++ {
  3647  			k = uint16(ii)
  3648  			_ = k
  3649  			prg.print(int32(prg.buffer[k]))
  3650  		}
  3651  	}
  3652  	prg.printLn()
  3653  	prg.selector = byte(int32(prg.selector) + 1) // restore previous status
  3654  }
  3655  
  3656  // 72. \[6] Reporting errors
  3657  
  3658  // tangle:pos tex.web:1721:26:
  3659  
  3660  // When something anomalous is detected, \TeX\ typically does something like this:
  3661  // $$\vbox[\halign[#\hfil\cr
  3662  // |print_err("Something anomalous has been detected");|\cr
  3663  // |help3("This is the first line of my offer to help.")|\cr
  3664  // |("This is the second line. I'm trying to")|\cr
  3665  // |("explain the best way for you to proceed.");|\cr
  3666  // |error;|\cr]]$$
  3667  // A two-line help message would be given using |help2|, etc.; these informal
  3668  // helps should use simple vocabulary that complements the words used in the
  3669  // official error message that was printed. (Outside the U.S.A., the help
  3670  // messages should preferably be translated into the local vernacular. Each
  3671  // line of help is at most 60 characters long, in the present implementation,
  3672  // so that |max_print_line| will not be exceeded.)
  3673  //
  3674  // The |print_err| procedure supplies a `\.!' before the official message,
  3675  // and makes sure that the terminal is awake if a stop is going to occur.
  3676  // The |error| procedure supplies a `\..' after the official message, then it
  3677  // shows the location of the error; and if |interaction=error_stop_mode|,
  3678  // it also enters into a dialog with the user, during which time the help
  3679  // message may be printed.
  3680  // \xref[system dependencies]
  3681  
  3682  // 91.
  3683  
  3684  // tangle:pos tex.web:2034:3:
  3685  
  3686  // A dozen or so error messages end with a parenthesized integer, so we
  3687  // save a teeny bit of program space by declaring the following procedure:
  3688  func (prg *prg) intError(n int32) {
  3689  	prg.print( /* " (" */ 286)
  3690  	prg.printInt(n)
  3691  	prg.printChar(asciiCode(')'))
  3692  	prg.error1()
  3693  }
  3694  
  3695  // \4
  3696  // Error handling procedures
  3697  func (prg *prg) normalizeSelector() {
  3698  	if prg.logOpened {
  3699  		prg.selector = byte(termAndLog)
  3700  	} else {
  3701  		prg.selector = byte(termOnly)
  3702  	}
  3703  	if int32(prg.jobName) == 0 {
  3704  		prg.openLogFile()
  3705  	}
  3706  	if int32(prg.interaction) == batchMode {
  3707  		prg.selector = byte(int32(prg.selector) - 1)
  3708  	}
  3709  }
  3710  
  3711  // 98.
  3712  
  3713  // tangle:pos tex.web:2124:3:
  3714  
  3715  // When an interrupt has been detected, the program goes into its
  3716  // highest interaction level and lets the user have nearly the full flexibility of
  3717  // the |error| routine.  \TeX\ checks for interrupts only at times when it is
  3718  // safe to do this.
  3719  func (prg *prg) pauseForInstructions() {
  3720  	if prg.okToInterrupt {
  3721  		prg.interaction = byte(errorStopMode)
  3722  		if int32(prg.selector) == logOnly || int32(prg.selector) == noPrint {
  3723  			prg.selector = byte(int32(prg.selector) + 1)
  3724  		}
  3725  		{
  3726  			if int32(prg.interaction) == errorStopMode {
  3727  			}
  3728  			prg.printNl(strNumber( /* "! " */ 262))
  3729  			prg.print( /* "Interruption" */ 296)
  3730  		}
  3731  		// \xref[Interruption]
  3732  		{
  3733  			prg.helpPtr = 3
  3734  			prg.helpLine[2] = /* "You rang?" */ 297
  3735  			prg.helpLine[1] = /* "Try to insert an instruction for me (e.g., `I\\showlists')," */ 298
  3736  			prg.helpLine[0] = /* "unless you just want to quit by typing `X'." */ 299
  3737  		}
  3738  		prg.deletionsAllowed = false
  3739  		prg.error1()
  3740  		prg.deletionsAllowed = true
  3741  		prg.interrupt = 0
  3742  	}
  3743  }
  3744  
  3745  // 99. \[7] Arithmetic with scaled dimensions
  3746  
  3747  // tangle:pos tex.web:2144:43:
  3748  
  3749  // The principal computations performed by \TeX\ are done entirely in terms of
  3750  // integers less than $2^[31]$ in magnitude; and divisions are done only when both
  3751  // dividend and divisor are nonnegative. Thus, the arithmetic specified in this
  3752  // program can be carried out in exactly the same way on a wide variety of
  3753  // computers, including some small ones. Why? Because the arithmetic
  3754  // calculations need to be spelled out precisely in order to guarantee that
  3755  // \TeX\ will produce identical output on different machines. If some
  3756  // quantities were rounded differently in different implementations, we would
  3757  // find that line breaks and even page breaks might occur in different places.
  3758  // Hence the arithmetic of \TeX\ has been designed with care, and systems that
  3759  // claim to be implementations of \TeX82 should follow precisely the
  3760  // \xref[TeX82][\TeX82]
  3761  // calculations as they appear in the present program.
  3762  //
  3763  // (Actually there are three places where \TeX\ uses |div| with a possibly negative
  3764  // numerator. These are harmless; see |div| in the index. Also if the user
  3765  // sets the \.[\\time] or the \.[\\year] to a negative value, some diagnostic
  3766  // information will involve negative-numerator division. The same remarks
  3767  // apply for |mod| as well as for |div|.)
  3768  
  3769  // 100.
  3770  
  3771  // tangle:pos tex.web:2165:3:
  3772  
  3773  // Here is a routine that calculates half of an integer, using an
  3774  // unambiguous convention with respect to signed odd numbers.
  3775  func (prg *prg) half(x int32) (r int32) {
  3776  	if x&1 != 0 {
  3777  		r = (x + 1) / 2
  3778  	} else {
  3779  		r = x / 2
  3780  	}
  3781  	return r
  3782  }
  3783  
  3784  // 102.
  3785  
  3786  // tangle:pos tex.web:2185:3:
  3787  
  3788  // The following function is used to create a scaled integer from a given decimal
  3789  // fraction $(.d_0d_1\ldots d_[k-1])$, where |0<=k<=17|. The digit $d_i$ is
  3790  // given in |dig[i]|, and the calculation produces a correctly rounded result.
  3791  func (prg *prg) roundDecimals(k smallNumber) (r scaled) {
  3792  	// converts a decimal fraction
  3793  	var (
  3794  		a int32 // the accumulator
  3795  	)
  3796  	a = 0
  3797  	for int32(k) > 0 {
  3798  		k = byte(int32(k) - 1)
  3799  		a = (a + int32(prg.dig[k])*0400000) / 10
  3800  	}
  3801  	r = (a + 1) / 2
  3802  	return r
  3803  }
  3804  
  3805  // 103.
  3806  
  3807  // tangle:pos tex.web:2199:3:
  3808  
  3809  // Conversely, here is a procedure analogous to |print_int|. If the output
  3810  // of this procedure is subsequently read by \TeX\ and converted by the
  3811  // |round_decimals| routine above, it turns out that the original value will
  3812  // be reproduced exactly; the ``simplest'' such decimal number is output,
  3813  // but there is always at least one digit following the decimal point.
  3814  //
  3815  // The invariant relation in the \&[repeat] loop is that a sequence of
  3816  // decimal digits yet to be printed will yield the original number if and only if
  3817  // they form a fraction~$f$ in the range $s-\delta\L10\cdot2^[16]f<s$.
  3818  // We can stop if and only if $f=0$ satisfies this condition; the loop will
  3819  // terminate before $s$ can possibly become zero.
  3820  func (prg *prg) printScaled(s scaled) { // prints scaled real, rounded to five
  3821  	//   digits
  3822  
  3823  	var (
  3824  		delta scaled // amount of allowable inaccuracy
  3825  	)
  3826  	if s < 0 {
  3827  		prg.printChar(asciiCode('-'))
  3828  		s = -s // print the sign, if negative
  3829  	}
  3830  	prg.printInt(s / 0200000) // print the integer part
  3831  	prg.printChar(asciiCode('.'))
  3832  	s = 10*(s%0200000) + 5
  3833  	delta = 10
  3834  	for {
  3835  		if delta > 0200000 {
  3836  			s = s + 0100000 - 50000
  3837  		} // round the last digit
  3838  		prg.printChar(asciiCode('0' + s/0200000))
  3839  		s = 10 * (s % 0200000)
  3840  		delta = delta * 10
  3841  		if s <= delta {
  3842  			break
  3843  		}
  3844  	}
  3845  }
  3846  
  3847  // 105.
  3848  
  3849  // tangle:pos tex.web:2254:3:
  3850  
  3851  // The first arithmetical subroutine we need computes $nx+y$, where |x|
  3852  // and~|y| are |scaled| and |n| is an integer. We will also use it to
  3853  // multiply integers.
  3854  func (prg *prg) multAndAdd(n int32, x, y, maxAnswer scaled) (r scaled) {
  3855  	if n < 0 {
  3856  		x = -x
  3857  		n = -n
  3858  	}
  3859  	if n == 0 {
  3860  		r = y
  3861  	} else if x <= (maxAnswer-y)/n && -x <= (maxAnswer+y)/n {
  3862  		r = n*x + y
  3863  	} else {
  3864  		prg.arithError = true
  3865  		r = 0
  3866  	}
  3867  	return r
  3868  }
  3869  
  3870  // 106.
  3871  
  3872  // tangle:pos tex.web:2272:3:
  3873  
  3874  // We also need to divide scaled dimensions by integers.
  3875  func (prg *prg) xOverN(x scaled, n int32) (r scaled) {
  3876  	var (
  3877  		negative bool // should |remainder| be negated?
  3878  	)
  3879  	negative = false
  3880  	if n == 0 {
  3881  		prg.arithError = true
  3882  		r = 0
  3883  		prg.remainder = x
  3884  	} else {
  3885  		if n < 0 {
  3886  			x = -x
  3887  			n = -n
  3888  			negative = true
  3889  		}
  3890  		if x >= 0 {
  3891  			r = x / n
  3892  			prg.remainder = x % n
  3893  		} else {
  3894  			r = -(-x / n)
  3895  			prg.remainder = -(-x % n)
  3896  		}
  3897  	}
  3898  	if negative {
  3899  		prg.remainder = -prg.remainder
  3900  	}
  3901  	return r
  3902  }
  3903  
  3904  // 107.
  3905  
  3906  // tangle:pos tex.web:2292:3:
  3907  
  3908  // Then comes the multiplication of a scaled number by a fraction |n/d|,
  3909  // where |n| and |d| are nonnegative integers |<=$2^[16]$| and |d| is
  3910  // positive. It would be too dangerous to multiply by~|n| and then divide
  3911  // by~|d|, in separate operations, since overflow might well occur; and it
  3912  // would be too inaccurate to divide by |d| and then multiply by |n|. Hence
  3913  // this subroutine simulates 1.5-precision arithmetic.
  3914  func (prg *prg) xnOverD(x scaled, n, d int32) (r scaled) {
  3915  	var (
  3916  		positive bool               // was |x>=0|?
  3917  		t, u, v  nonnegativeInteger // intermediate quantities
  3918  	)
  3919  	if x >= 0 {
  3920  		positive = true
  3921  	} else {
  3922  		x = -x
  3923  		positive = false
  3924  	}
  3925  	t = uint32(x % 0100000 * n)
  3926  	u = uint32(x/0100000*n + int32(t)/0100000)
  3927  	v = uint32(int32(u)%d*0100000 + int32(t)%0100000)
  3928  	if int32(u)/d >= 0100000 {
  3929  		prg.arithError = true
  3930  	} else {
  3931  		u = uint32(0100000*(int32(u)/d) + int32(v)/d)
  3932  	}
  3933  	if positive {
  3934  		r = int32(u)
  3935  		prg.remainder = int32(v) % d
  3936  	} else {
  3937  		r = -int32(u)
  3938  		prg.remainder = -(int32(v) % d)
  3939  	}
  3940  	return r
  3941  }
  3942  
  3943  // 108.
  3944  
  3945  // tangle:pos tex.web:2317:3:
  3946  
  3947  // The next subroutine is used to compute the ``badness'' of glue, when a
  3948  // total~|t| is supposed to be made from amounts that sum to~|s|.  According
  3949  // to [\sl The \TeX book], the badness of this situation is $100(t/s)^3$;
  3950  // however, badness is simply a heuristic, so we need not squeeze out the
  3951  // last drop of accuracy when computing it. All we really want is an
  3952  // approximation that has similar properties.
  3953  // \xref[TeXbook][\sl The \TeX book]
  3954  //
  3955  // The actual method used to compute the badness is easier to read from the
  3956  // program than to describe in words. It produces an integer value that is a
  3957  // reasonably close approximation to $100(t/s)^3$, and all implementations
  3958  // of \TeX\ should use precisely this method. Any badness of $2^[13]$ or more is
  3959  // treated as infinitely bad, and represented by 10000.
  3960  //
  3961  // It is not difficult to prove that $$\hbox[|badness(t+1,s)>=badness(t,s)
  3962  // >=badness(t,s+1)|].$$ The badness function defined here is capable of
  3963  // computing at most 1095 distinct values, but that is plenty.
  3964  func (prg *prg) badness(t, s scaled) (r halfword) { // compute badness, given |t>=0|
  3965  	var (
  3966  		r1 int32 // approximation to $\alpha t/s$, where $\alpha^3\approx
  3967  	// 100\cdot2^[18]$
  3968  	)
  3969  	if t == 0 {
  3970  		r = 0
  3971  	} else if s <= 0 {
  3972  		r = uint16(infBad)
  3973  	} else {
  3974  		if t <= 7230584 {
  3975  			r1 = t * 297 / s
  3976  		} else if s >= 1663497 {
  3977  			r1 = t / (s / 297)
  3978  		} else {
  3979  			r1 = t
  3980  		}
  3981  		if r1 > 1290 {
  3982  			r = uint16(infBad)
  3983  		} else {
  3984  			r = uint16((r1*r1*r1 + 0400000) / 01000000)
  3985  		}
  3986  	} // that was $r^3/2^[18]$, rounded to the nearest integer
  3987  	return r
  3988  }
  3989  
  3990  // 110. \[8] Packed data
  3991  
  3992  // tangle:pos tex.web:2375:21:
  3993  
  3994  // In order to make efficient use of storage space, \TeX\ bases its major data
  3995  // structures on a |memory_word|, which contains either a (signed) integer,
  3996  // possibly scaled, or a (signed) |glue_ratio|, or a small number of
  3997  // fields that are one half or one quarter of the size used for storing
  3998  // integers.
  3999  //
  4000  // If |x| is a variable of type |memory_word|, it contains up to four
  4001  // fields that can be referred to as follows:
  4002  // $$\vbox[\halign[\hfil#&#\hfil&#\hfil\cr
  4003  // |x|&.|int|&(an |integer|)\cr
  4004  // |x|&.|sc|\qquad&(a |scaled| integer)\cr
  4005  // |x|&.|gr|&(a |glue_ratio|)\cr
  4006  // |x.hh.lh|, |x.hh|&.|rh|&(two halfword fields)\cr
  4007  // |x.hh.b0|, |x.hh.b1|, |x.hh|&.|rh|&(two quarterword fields, one halfword
  4008  //   field)\cr
  4009  // |x.qqqq.b0|, |x.qqqq.b1|, |x.qqqq|&.|b2|, |x.qqqq.b3|\hskip-100pt
  4010  //   &\qquad\qquad\qquad(four quarterword fields)\cr]]$$
  4011  // This is somewhat cumbersome to write, and not very readable either, but
  4012  // macros will be used to make the notation shorter and more transparent.
  4013  // The \PASCAL\ code below gives a formal definition of |memory_word| and
  4014  // its subsidiary types, using packed variant records. \TeX\ makes no
  4015  // assumptions about the relative positions of the fields within a word.
  4016  //
  4017  // Since we are assuming 32-bit integers, a halfword must contain at least
  4018  // 16 bits, and a quarterword must contain at least 8 bits.
  4019  // \xref[system dependencies]
  4020  // But it doesn't hurt to have more bits; for example, with enough 36-bit
  4021  // words you might be able to have |mem_max| as large as 262142, which is
  4022  // eight times as much memory as anybody had during the first four years of
  4023  // \TeX's existence.
  4024  //
  4025  // N.B.: Valuable memory space will be dreadfully wasted unless \TeX\ is compiled
  4026  // by a \PASCAL\ that packs all of the |memory_word| variants into
  4027  // the space of a single integer. This means, for example, that |glue_ratio|
  4028  // words should be |short_real| instead of |real| on some computers. Some
  4029  // \PASCAL\ compilers will pack an integer whose subrange is `|0..255|' into
  4030  // an eight-bit field, but others insist on allocating space for an additional
  4031  // sign bit; on such systems you can get 256 values into a quarterword only
  4032  // if the subrange is `|-128..127|'.
  4033  //
  4034  // The present implementation tries to accommodate as many variations as possible,
  4035  // so it makes few assumptions. If integers having the subrange
  4036  // `|min_quarterword..max_quarterword|' can be packed into a quarterword,
  4037  // and if integers having the subrange `|min_halfword..max_halfword|'
  4038  // can be packed into a halfword, everything should work satisfactorily.
  4039  //
  4040  // It is usually most efficient to have |min_quarterword=min_halfword=0|,
  4041  // so one should try to achieve this unless it causes a severe problem.
  4042  // The values defined here are recommended for most 32-bit computers.
  4043  
  4044  // 112.
  4045  
  4046  // tangle:pos tex.web:2449:3:
  4047  
  4048  // The operation of adding or subtracting |min_quarterword| occurs quite
  4049  // frequently in \TeX, so it is convenient to abbreviate this operation
  4050  // by using the macros |qi| and |qo| for input and output to and from
  4051  // quarterword format.
  4052  //
  4053  // The inner loop of \TeX\ will run faster with respect to compilers
  4054  // that don't optimize expressions like `|x+0|' and `|x-0|', if these
  4055  // macros are simplified in the obvious way when |min_quarterword=0|.
  4056  // \xref[inner loop]\xref[system dependencies]
  4057  
  4058  // 114.
  4059  
  4060  // tangle:pos tex.web:2499:3:
  4061  
  4062  // When debugging, we may want to print a |memory_word| without knowing
  4063  // what type it is; so we print it in all modes.
  4064  // \xref[dirty \PASCAL]\xref[debugging]
  4065  //  procedure print_word( w:memory_word);
  4066  //   [prints |w| in all ways]
  4067  // begin print_int(w.int); print_char([" "=]32);
  4068  //
  4069  // print_scaled(w.int ); print_char([" "=]32);
  4070  //
  4071  // print_scaled(round( [0200000=]65536 *  w. gr )); print_ln;
  4072  //
  4073  // [ \xref[real multiplication] ]
  4074  // print_int(w.hh.lh); print_char(["="=]61); print_int(w.hh.b0); print_char([":"=]58);
  4075  // print_int(w.hh.b1); print_char([";"=]59); print_int(w.hh.rh); print_char([" "=]32);
  4076  //
  4077  // print_int(w.qqqq.b0); print_char([":"=]58); print_int(w.qqqq.b1); print_char([":"=]58);
  4078  // print_int(w.qqqq.b2); print_char([":"=]58); print_int(w.qqqq.b3);
  4079  // end;
  4080  // [  ]
  4081  
  4082  // 119.
  4083  
  4084  // tangle:pos tex.web:2596:3:
  4085  
  4086  // If memory is exhausted, it might mean that the user has forgotten
  4087  // a right brace. We will define some procedures later that try to help
  4088  // pinpoint the trouble.
  4089  
  4090  // Declare the procedure called |show_token_list|
  4091  func (prg *prg) showTokenList(p, q int32, l int32) {
  4092  	var (
  4093  		m, c     int32     // pieces of a token
  4094  		matchChr asciiCode // character used in a `|match|'
  4095  		n        asciiCode // the highest parameter number, as an ASCII digit
  4096  	)
  4097  	matchChr = '#'
  4098  	n = '0'
  4099  	prg.tally = 0
  4100  	for p != 0 && prg.tally < l {
  4101  		if p == q {
  4102  			prg.firstCount = prg.tally
  4103  			prg.trickCount = prg.tally + 1 + errorLine - halfErrorLine
  4104  			if prg.trickCount < errorLine {
  4105  				prg.trickCount = errorLine
  4106  			}
  4107  		}
  4108  
  4109  		// Display token |p|, and |return| if there are problems
  4110  		if p < int32(prg.hiMemMin) || p > int32(prg.memEnd) {
  4111  			prg.printEsc(strNumber( /* "CLOBBERED." */ 309))
  4112  			goto exit
  4113  			// \xref[CLOBBERED]
  4114  		}
  4115  		if int32(*(*prg.mem[p].hh()).lh()) >= 07777 {
  4116  			prg.printCs(int32(*(*prg.mem[p].hh()).lh()) - 07777)
  4117  		} else {
  4118  			m = int32(*(*prg.mem[p].hh()).lh()) / 0400
  4119  			c = int32(*(*prg.mem[p].hh()).lh()) % 0400
  4120  			if int32(*(*prg.mem[p].hh()).lh()) < 0 {
  4121  				prg.printEsc(strNumber( /* "BAD." */ 555))
  4122  			} else {
  4123  				// Display the token $(|m|,|c|)$
  4124  				switch m {
  4125  				case leftBrace, rightBrace, mathShift, tabMark,
  4126  					supMark, subMark, spacer, letter,
  4127  					otherChar:
  4128  					prg.print(c)
  4129  				case macParam:
  4130  					prg.print(c)
  4131  					prg.print(c)
  4132  
  4133  				case outParam:
  4134  					prg.print(int32(matchChr))
  4135  					if c <= 9 {
  4136  						prg.printChar(asciiCode(c + '0'))
  4137  					} else {
  4138  						prg.printChar(asciiCode('!'))
  4139  						goto exit
  4140  					}
  4141  
  4142  				case match:
  4143  					matchChr = byte(c)
  4144  					prg.print(c)
  4145  					n = byte(int32(n) + 1)
  4146  					prg.printChar(n)
  4147  					if int32(n) > '9' {
  4148  						goto exit
  4149  					}
  4150  
  4151  				case endMatch:
  4152  					prg.print( /* "->" */ 556)
  4153  
  4154  				// \xref[->]
  4155  				default:
  4156  					prg.printEsc(strNumber( /* "BAD." */ 555))
  4157  					// \xref[BAD]
  4158  				}
  4159  			}
  4160  		}
  4161  		p = int32(*(*prg.mem[p].hh()).rh())
  4162  	}
  4163  	if p != 0 {
  4164  		prg.printEsc(strNumber( /* "ETC." */ 554))
  4165  	}
  4166  	// \xref[ETC]
  4167  
  4168  	// \xref[ETC]
  4169  exit:
  4170  }
  4171  
  4172  // Declare the procedure called |runaway|
  4173  func (prg *prg) runaway() {
  4174  	var (
  4175  		p halfword // head of runaway list
  4176  	)
  4177  	if int32(prg.scannerStatus) > skipping {
  4178  		prg.printNl(strNumber( /* "Runaway " */ 569))
  4179  		// \xref[Runaway...]
  4180  		switch prg.scannerStatus {
  4181  		case defining:
  4182  			prg.print( /* "definition" */ 570)
  4183  			p = prg.defRef
  4184  
  4185  		case matching:
  4186  			prg.print( /* "argument" */ 571)
  4187  			p = uint16(30000 - 3)
  4188  
  4189  		case aligning:
  4190  			prg.print( /* "preamble" */ 572)
  4191  			p = uint16(30000 - 4)
  4192  
  4193  		case absorbing:
  4194  			prg.print( /* "text" */ 573)
  4195  			p = prg.defRef
  4196  
  4197  		} // there are no other cases
  4198  		prg.printChar(asciiCode('?'))
  4199  		prg.printLn()
  4200  		prg.showTokenList(int32(*(*prg.mem[p].hh()).rh()), 0, errorLine-10)
  4201  	}
  4202  }
  4203  
  4204  // 120.
  4205  
  4206  // tangle:pos tex.web:2603:3:
  4207  
  4208  // The function |get_avail| returns a pointer to a new one-word node whose
  4209  // |link| field is null. However, \TeX\ will halt if there is no more room left.
  4210  // \xref[inner loop]
  4211  //
  4212  // If the available-space list is empty, i.e., if |avail=null|,
  4213  // we try first to increase |mem_end|. If that cannot be done, i.e., if
  4214  // |mem_end=mem_max|, we try to decrease |hi_mem_min|. If that cannot be
  4215  // done, i.e., if |hi_mem_min=lo_mem_max+1|, we have to quit.
  4216  func (prg *prg) getAvail() (r halfword) { // single-word node allocation
  4217  	var (
  4218  		p halfword // the new node being got
  4219  	)
  4220  	p = prg.avail // get top location in the |avail| stack
  4221  	if int32(p) != 0 {
  4222  		prg.avail = *(*prg.mem[prg.avail].hh()).rh()
  4223  	} else if int32(prg.memEnd) < memMax {
  4224  		prg.memEnd = uint16(int32(prg.memEnd) + 1)
  4225  		p = prg.memEnd
  4226  	} else {
  4227  		prg.hiMemMin = uint16(int32(prg.hiMemMin) - 1)
  4228  		p = prg.hiMemMin
  4229  		if int32(prg.hiMemMin) <= int32(prg.loMemMax) {
  4230  			prg.runaway() // if memory is exhausted, display possible runaway text
  4231  			prg.overflow(strNumber( /* "main memory size" */ 300), memMax+1-memMin)
  4232  			// quit; all one-word nodes are busy
  4233  			// \xref[TeX capacity exceeded main memory size][\quad main memory size]
  4234  		}
  4235  	}
  4236  	*(*prg.mem[p].hh()).rh() = 0 // provide an oft-desired initialization of the new node
  4237  	//	dyn_used:= dyn_used+1 ; [  ]
  4238  	//
  4239  	// maintain statistics
  4240  	r = p
  4241  	return r
  4242  }
  4243  
  4244  // 121.
  4245  
  4246  // tangle:pos tex.web:2632:3:
  4247  
  4248  // Conversely, a one-word node is recycled by calling |free_avail|.
  4249  // This routine is part of \TeX's ``inner loop,'' so we want it to be fast.
  4250  // \xref[inner loop]
  4251  
  4252  // 122.
  4253  
  4254  // tangle:pos tex.web:2641:3:
  4255  
  4256  // There's also a |fast_get_avail| routine, which saves the procedure-call
  4257  // overhead at the expense of extra programming. This routine is used in
  4258  // the places that would otherwise account for the most calls of |get_avail|.
  4259  // \xref[inner loop]
  4260  
  4261  // 123.
  4262  
  4263  // tangle:pos tex.web:2654:3:
  4264  
  4265  // The procedure |flush_list(p)| frees an entire linked list of
  4266  // one-word nodes that starts at position |p|.
  4267  // \xref[inner loop]
  4268  func (prg *prg) flushList(p halfword) { // makes list of single-word nodes
  4269  	//   available
  4270  
  4271  	var (
  4272  		q, r1 halfword // list traversers
  4273  	)
  4274  	if int32(p) != 0 {
  4275  		r1 = p
  4276  		for {
  4277  			q = r1
  4278  			r1 = *(*prg.mem[r1].hh()).rh() //    dyn_used:= dyn_used-1 ; [  ]
  4279  
  4280  			if int32(r1) == 0 {
  4281  				break
  4282  			}
  4283  		} // now |q| is the last node on the list
  4284  		*(*prg.mem[q].hh()).rh() = prg.avail
  4285  		prg.avail = p
  4286  	}
  4287  }
  4288  
  4289  // 125.
  4290  
  4291  // tangle:pos tex.web:2694:3:
  4292  
  4293  // A call to |get_node| with argument |s| returns a pointer to a new node
  4294  // of size~|s|, which must be 2~or more. The |link| field of the first word
  4295  // of this new node is set to null. An overflow stop occurs if no suitable
  4296  // space exists.
  4297  //
  4298  // If |get_node| is called with $s=2^[30]$, it simply merges adjacent free
  4299  // areas and returns the value |max_halfword|.
  4300  func (prg *prg) getNode(s int32) (r halfword) {
  4301  	var (
  4302  		p  halfword // the node currently under inspection
  4303  		q  halfword // the node physically after node |p|
  4304  		r1 int32    // the newly allocated node, or a candidate for this honor
  4305  		t  int32    // temporary register
  4306  	)
  4307  restart:
  4308  	p = prg.rover // start at some free node in the ring
  4309  	for {
  4310  		// Try to allocate within node |p| and its physical successors, and |goto found| if allocation was possible
  4311  		q = uint16(int32(p) + int32(*(*prg.mem[p].hh()).lh())) // find the physical successor
  4312  		// \xref[inner loop]
  4313  		for int32(*(*prg.mem[q].hh()).rh()) == 65535 { // merge node |p| with node |q|
  4314  			t = int32(*(*prg.mem[int32(q)+1].hh()).rh())
  4315  			if int32(q) == int32(prg.rover) {
  4316  				prg.rover = uint16(t)
  4317  			}
  4318  			*(*prg.mem[t+1].hh()).lh() = *(*prg.mem[int32(q)+1].hh()).lh()
  4319  			*(*prg.mem[int32(*(*prg.mem[int32(q)+1].hh()).lh())+1].hh()).rh() = uint16(t)
  4320  
  4321  			q = uint16(int32(q) + int32(*(*prg.mem[q].hh()).lh()))
  4322  		}
  4323  		r1 = int32(q) - s
  4324  		if r1 > int32(p)+1 {
  4325  			*(*prg.mem[p].hh()).lh() = uint16(r1 - int32(p)) // store the remaining size
  4326  			// \xref[inner loop]
  4327  			prg.rover = p // start searching here next time
  4328  			// start searching here next time
  4329  			goto found
  4330  		}
  4331  		if r1 == int32(p) {
  4332  			if int32(*(*prg.mem[int32(p)+1].hh()).rh()) != int32(p) {
  4333  				prg.rover = *(*prg.mem[int32(p)+1].hh()).rh()
  4334  				t = int32(*(*prg.mem[int32(p)+1].hh()).lh())
  4335  				*(*prg.mem[int32(prg.rover)+1].hh()).lh() = uint16(t)
  4336  				*(*prg.mem[t+1].hh()).rh() = prg.rover
  4337  
  4338  				goto found
  4339  			}
  4340  		}
  4341  		*(*prg.mem[p].hh()).lh() = uint16(int32(q) - int32(p))
  4342  		// \xref[inner loop]
  4343  		p = *(*prg.mem[int32(p)+1].hh()).rh() // move to the next node in the ring
  4344  		if int32(p) == int32(prg.rover) {
  4345  			break
  4346  		}
  4347  	} // repeat until the whole list has been traversed
  4348  	if s == 010000000000 {
  4349  		r = 65535
  4350  		goto exit
  4351  	}
  4352  	if int32(prg.loMemMax)+2 < int32(prg.hiMemMin) {
  4353  		if int32(prg.loMemMax)+2 <= memBot+65535 {
  4354  			if int32(prg.hiMemMin)-int32(prg.loMemMax) >= 1998 {
  4355  				t = int32(prg.loMemMax) + 1000
  4356  			} else {
  4357  				t = int32(prg.loMemMax) + 1 + (int32(prg.hiMemMin)-int32(prg.loMemMax))/2
  4358  			}
  4359  			// |lo_mem_max+2<=t<hi_mem_min|
  4360  			p = *(*prg.mem[int32(prg.rover)+1].hh()).lh()
  4361  			q = prg.loMemMax
  4362  			*(*prg.mem[int32(p)+1].hh()).rh() = q
  4363  			*(*prg.mem[int32(prg.rover)+1].hh()).lh() = q
  4364  
  4365  			if t > memBot+65535 {
  4366  				t = memBot + 65535
  4367  			}
  4368  			*(*prg.mem[int32(q)+1].hh()).rh() = prg.rover
  4369  			*(*prg.mem[int32(q)+1].hh()).lh() = p
  4370  			*(*prg.mem[q].hh()).rh() = 65535
  4371  			*(*prg.mem[q].hh()).lh() = uint16(t - int32(prg.loMemMax))
  4372  
  4373  			prg.loMemMax = uint16(t)
  4374  			*(*prg.mem[prg.loMemMax].hh()).rh() = 0
  4375  			*(*prg.mem[prg.loMemMax].hh()).lh() = 0
  4376  			prg.rover = q
  4377  			goto restart
  4378  		}
  4379  	}
  4380  	prg.overflow(strNumber( /* "main memory size" */ 300), memMax+1-memMin)
  4381  	// sorry, nothing satisfactory is left
  4382  	// \xref[TeX capacity exceeded main memory size][\quad main memory size]
  4383  
  4384  	// sorry, nothing satisfactory is left
  4385  	// \xref[TeX capacity exceeded main memory size][\quad main memory size]
  4386  found:
  4387  	*(*prg.mem[r1].hh()).rh() = 0 // this node is now nonempty
  4388  	//  var_used:=var_used+s; [maintain usage statistics]
  4389  	// [  ]
  4390  
  4391  	r = uint16(r1)
  4392  
  4393  exit:
  4394  	;
  4395  	return r
  4396  }
  4397  
  4398  // 130.
  4399  
  4400  // tangle:pos tex.web:2780:3:
  4401  
  4402  // Conversely, when some variable-size node |p| of size |s| is no longer needed,
  4403  // the operation |free_node(p,s)| will make its words available, by inserting
  4404  // |p| as a new empty node just before where |rover| now points.
  4405  // \xref[inner loop]
  4406  func (prg *prg) freeNode(p halfword, s halfword) { // variable-size node
  4407  	//   liberation
  4408  
  4409  	var (
  4410  		q halfword // |llink(rover)|
  4411  	)
  4412  	*(*prg.mem[p].hh()).lh() = s
  4413  	*(*prg.mem[p].hh()).rh() = 65535
  4414  	q = *(*prg.mem[int32(prg.rover)+1].hh()).lh()
  4415  	*(*prg.mem[int32(p)+1].hh()).lh() = q
  4416  	*(*prg.mem[int32(p)+1].hh()).rh() = prg.rover // set both links
  4417  	*(*prg.mem[int32(prg.rover)+1].hh()).lh() = p
  4418  	*(*prg.mem[int32(q)+1].hh()).rh() = p // insert |p| into the ring
  4419  	//  var_used:=var_used-s; [  ]
  4420  	// maintain statistics
  4421  }
  4422  
  4423  // 131.
  4424  
  4425  // tangle:pos tex.web:2794:3:
  4426  
  4427  // Just before \.[INITEX] writes out the memory, it sorts the doubly linked
  4428  // available space list. The list is probably very short at such times, so a
  4429  // simple insertion sort is used. The smallest available location will be
  4430  // pointed to by |rover|, the next-smallest by |rlink(rover)|, etc.
  4431  func (prg *prg) sortAvail() { // sorts the available variable-size nodes
  4432  	//   by location
  4433  
  4434  	var (
  4435  		p, q, r1 halfword // indices into |mem|
  4436  		oldRover halfword // initial |rover| setting
  4437  	)
  4438  	p = prg.getNode(010000000000) // merge adjacent free areas
  4439  	p = *(*prg.mem[int32(prg.rover)+1].hh()).rh()
  4440  	*(*prg.mem[int32(prg.rover)+1].hh()).rh() = 65535
  4441  	oldRover = prg.rover
  4442  	for int32(p) != int32(oldRover) {
  4443  		// Sort \(p)|p| into the list starting at |rover| and advance |p| to |rlink(p)|
  4444  		if int32(p) < int32(prg.rover) {
  4445  			q = p
  4446  			p = *(*prg.mem[int32(q)+1].hh()).rh()
  4447  			*(*prg.mem[int32(q)+1].hh()).rh() = prg.rover
  4448  			prg.rover = q
  4449  		} else {
  4450  			q = prg.rover
  4451  			for int32(*(*prg.mem[int32(q)+1].hh()).rh()) < int32(p) {
  4452  				q = *(*prg.mem[int32(q)+1].hh()).rh()
  4453  			}
  4454  			r1 = *(*prg.mem[int32(p)+1].hh()).rh()
  4455  			*(*prg.mem[int32(p)+1].hh()).rh() = *(*prg.mem[int32(q)+1].hh()).rh()
  4456  			*(*prg.mem[int32(q)+1].hh()).rh() = p
  4457  			p = r1
  4458  		}
  4459  	}
  4460  	p = prg.rover
  4461  	for int32(*(*prg.mem[int32(p)+1].hh()).rh()) != 65535 {
  4462  		*(*prg.mem[int32(*(*prg.mem[int32(p)+1].hh()).rh())+1].hh()).lh() = p
  4463  		p = *(*prg.mem[int32(p)+1].hh()).rh()
  4464  	}
  4465  	*(*prg.mem[int32(p)+1].hh()).rh() = prg.rover
  4466  	*(*prg.mem[int32(prg.rover)+1].hh()).lh() = p
  4467  }
  4468  
  4469  // 133. \[10] Data structures for boxes and their friends
  4470  
  4471  // tangle:pos tex.web:2828:54:
  4472  
  4473  // From the computer's standpoint, \TeX's chief mission is to create
  4474  // horizontal and vertical lists. We shall now investigate how the elements
  4475  // of these lists are represented internally as nodes in the dynamic memory.
  4476  //
  4477  // A horizontal or vertical list is linked together by |link| fields in
  4478  // the first word of each node. Individual nodes represent boxes, glue,
  4479  // penalties, or special things like discretionary hyphens; because of this
  4480  // variety, some nodes are longer than others, and we must distinguish different
  4481  // kinds of nodes. We do this by putting a `|type|' field in the first word,
  4482  // together with the link and an optional `|subtype|'.
  4483  
  4484  // 134.
  4485  
  4486  // tangle:pos tex.web:2843:3:
  4487  
  4488  // A | char_node|, which represents a single character, is the most important
  4489  // kind of node because it accounts for the vast majority of all boxes.
  4490  // Special precautions are therefore taken to ensure that a |char_node| does
  4491  // not take up much memory space. Every such node is one word long, and in fact
  4492  // it is identifiable by this property, since other kinds of nodes have at least
  4493  // two words, and they appear in |mem| locations less than |hi_mem_min|.
  4494  // This makes it possible to omit the |type| field in a |char_node|, leaving
  4495  // us room for two bytes that identify a |font| and a |character| within
  4496  // that font.
  4497  //
  4498  // Note that the format of a |char_node| allows for up to 256 different
  4499  // fonts and up to 256 characters per font; but most implementations will
  4500  // probably limit the total number of fonts to fewer than 75 per job,
  4501  // and most fonts will stick to characters whose codes are
  4502  // less than 128 (since higher codes
  4503  // are more difficult to access on most keyboards).
  4504  //
  4505  // Extensions of \TeX\ intended for oriental languages will need even more
  4506  // than $256\times256$ possible characters, when we consider different sizes
  4507  // \xref[oriental characters]\xref[Chinese characters]\xref[Japanese characters]
  4508  // and styles of type.  It is suggested that Chinese and Japanese fonts be
  4509  // handled by representing such characters in two consecutive |char_node|
  4510  // entries: The first of these has |font=font_base|, and its |link| points
  4511  // to the second;
  4512  // the second identifies the font and the character dimensions.
  4513  // The saving feature about oriental characters is that most of them have
  4514  // the same box dimensions. The |character| field of the first |char_node|
  4515  // is a ``\\[charext]'' that distinguishes between graphic symbols whose
  4516  // dimensions are identical for typesetting purposes. (See the \MF\ manual.)
  4517  // Such an extension of \TeX\ would not be difficult; further details are
  4518  // left to the reader.
  4519  //
  4520  // In order to make sure that the |character| code fits in a quarterword,
  4521  // \TeX\ adds the quantity |min_quarterword| to the actual code.
  4522  //
  4523  // Character nodes appear only in horizontal lists, never in vertical lists.
  4524  
  4525  // 135.
  4526  
  4527  // tangle:pos tex.web:2885:3:
  4528  
  4529  // An |hlist_node| stands for a box that was made from a horizontal list.
  4530  // Each |hlist_node| is seven words long, and contains the following fields
  4531  // (in addition to the mandatory |type| and |link|, which we shall not
  4532  // mention explicitly when discussing the other node types): The |height| and
  4533  // |width| and |depth| are scaled integers denoting the dimensions of the
  4534  // box.  There is also a |shift_amount| field, a scaled integer indicating
  4535  // how much this box should be lowered (if it appears in a horizontal list),
  4536  // or how much it should be moved to the right (if it appears in a vertical
  4537  // list). There is a |list_ptr| field, which points to the beginning of the
  4538  // list from which this box was fabricated; if |list_ptr| is |null|, the box
  4539  // is empty. Finally, there are three fields that represent the setting of
  4540  // the glue:  |glue_set(p)| is a word of type |glue_ratio| that represents
  4541  // the proportionality constant for glue setting; |glue_sign(p)| is
  4542  // |stretching| or |shrinking| or |normal| depending on whether or not the
  4543  // glue should stretch or shrink or remain rigid; and |glue_order(p)|
  4544  // specifies the order of infinity to which glue setting applies (|normal|,
  4545  // |fil|, |fill|, or |filll|). The |subtype| field is not used.
  4546  
  4547  // 136.
  4548  
  4549  // tangle:pos tex.web:2923:3:
  4550  
  4551  // The |new_null_box| function returns a pointer to an |hlist_node| in
  4552  // which all subfields have the values corresponding to `\.[\\hbox\[\]]'.
  4553  // (The |subtype| field is set to |min_quarterword|, for historic reasons
  4554  // that are no longer relevant.)
  4555  func (prg *prg) newNullBox() (r halfword) { // creates a new box node
  4556  	var (
  4557  		p halfword // the new node
  4558  	)
  4559  	p = prg.getNode(boxNodeSize)
  4560  	*(*prg.mem[p].hh()).b0() = byte(hlistNode)
  4561  	*(*prg.mem[p].hh()).b1() = byte(minQuarterword)
  4562  	*prg.mem[int32(p)+widthOffset].int() = 0
  4563  	*prg.mem[int32(p)+depthOffset].int() = 0
  4564  	*prg.mem[int32(p)+heightOffset].int() = 0
  4565  	*prg.mem[int32(p)+4].int() = 0
  4566  	*(*prg.mem[int32(p)+listOffset].hh()).rh() = 0
  4567  	*(*prg.mem[int32(p)+listOffset].hh()).b0() = byte(normal)
  4568  	*(*prg.mem[int32(p)+listOffset].hh()).b1() = byte(normal)
  4569  	*prg.mem[int32(p)+glueOffset].gr() = float32(0.0)
  4570  	r = p
  4571  	return r
  4572  }
  4573  
  4574  // 137.
  4575  
  4576  // tangle:pos tex.web:2937:3:
  4577  
  4578  // A |vlist_node| is like an |hlist_node| in all respects except that it
  4579  // contains a vertical list.
  4580  
  4581  // 138.
  4582  
  4583  // tangle:pos tex.web:2942:3:
  4584  
  4585  // A |rule_node| stands for a solid black rectangle; it has |width|,
  4586  // |depth|, and |height| fields just as in an |hlist_node|. However, if
  4587  // any of these dimensions is $-2^[30]$, the actual value will be determined
  4588  // by running the rule up to the boundary of the innermost enclosing box.
  4589  // This is called a ``running dimension.'' The |width| is never running in
  4590  // an hlist; the |height| and |depth| are never running in a~vlist.
  4591  
  4592  // 139.
  4593  
  4594  // tangle:pos tex.web:2954:3:
  4595  
  4596  // A new rule node is delivered by the |new_rule| function. It
  4597  // makes all the dimensions ``running,'' so you have to change the
  4598  // ones that are not allowed to run.
  4599  func (prg *prg) newRule() (r halfword) {
  4600  	var (
  4601  		p halfword // the new node
  4602  	)
  4603  	p = prg.getNode(ruleNodeSize)
  4604  	*(*prg.mem[p].hh()).b0() = byte(ruleNode)
  4605  	*(*prg.mem[p].hh()).b1() = 0 // the |subtype| is not used
  4606  	*prg.mem[int32(p)+widthOffset].int() = -010000000000
  4607  	*prg.mem[int32(p)+depthOffset].int() = -010000000000
  4608  	*prg.mem[int32(p)+heightOffset].int() = -010000000000
  4609  	r = p
  4610  	return r
  4611  }
  4612  
  4613  // 140.
  4614  
  4615  // tangle:pos tex.web:2966:3:
  4616  
  4617  // Insertions are represented by |ins_node| records, where the |subtype|
  4618  // indicates the corresponding box number. For example, `\.[\\insert 250]'
  4619  // leads to an |ins_node| whose |subtype| is |250+min_quarterword|.
  4620  // The |height| field of an |ins_node| is slightly misnamed; it actually holds
  4621  // the natural height plus depth of the vertical list being inserted.
  4622  // The |depth| field holds the |split_max_depth| to be used in case this
  4623  // insertion is split, and the |split_top_ptr| points to the corresponding
  4624  // |split_top_skip|. The |float_cost| field holds the |floating_penalty| that
  4625  // will be used if this insertion floats to a subsequent page after a
  4626  // split insertion of the same class.  There is one more field, the
  4627  // |ins_ptr|, which points to the beginning of the vlist for the insertion.
  4628  
  4629  // 141.
  4630  
  4631  // tangle:pos tex.web:2984:3:
  4632  
  4633  // A |mark_node| has a |mark_ptr| field that points to the reference count
  4634  // of a token list that contains the user's \.[\\mark] text.
  4635  // This field occupies a full word instead of a halfword, because
  4636  // there's nothing to put in the other halfword; it is easier in \PASCAL\ to
  4637  // use the full word than to risk leaving garbage in the unused half.
  4638  
  4639  // 142.
  4640  
  4641  // tangle:pos tex.web:2994:3:
  4642  
  4643  // An |adjust_node|, which occurs only in horizontal lists,
  4644  // specifies material that will be moved out into the surrounding
  4645  // vertical list; i.e., it is used to implement \TeX's `\.[\\vadjust]'
  4646  // operation.  The |adjust_ptr| field points to the vlist containing this
  4647  // material.
  4648  
  4649  // 143.
  4650  
  4651  // tangle:pos tex.web:3003:3:
  4652  
  4653  // A |ligature_node|, which occurs only in horizontal lists, specifies
  4654  // a character that was fabricated from the interaction of two or more
  4655  // actual characters.  The second word of the node, which is called the
  4656  // |lig_char| word, contains |font| and |character| fields just as in a
  4657  // |char_node|. The characters that generated the ligature have not been
  4658  // forgotten, since they are needed for diagnostic messages and for
  4659  // hyphenation; the |lig_ptr| field points to a linked list of character
  4660  // nodes for all original characters that have been deleted. (This list
  4661  // might be empty if the characters that generated the ligature were
  4662  // retained in other nodes.)
  4663  //
  4664  // The |subtype| field is 0, plus 2 and/or 1 if the original source of the
  4665  // ligature included implicit left and/or right boundaries.
  4666  
  4667  // 144.
  4668  
  4669  // tangle:pos tex.web:3021:3:
  4670  
  4671  // The |new_ligature| function creates a ligature node having given
  4672  // contents of the |font|, |character|, and |lig_ptr| fields. We also have
  4673  // a |new_lig_item| function, which returns a two-word node having a given
  4674  // |character| field. Such nodes are used for temporary processing as ligatures
  4675  // are being created.
  4676  func (prg *prg) newLigature(f, c quarterword, q halfword) (r halfword) {
  4677  	var (
  4678  		p halfword // the new node
  4679  	)
  4680  	p = prg.getNode(smallNodeSize)
  4681  	*(*prg.mem[p].hh()).b0() = byte(ligatureNode)
  4682  	*(*prg.mem[int32(p)+1].hh()).b0() = f
  4683  	*(*prg.mem[int32(p)+1].hh()).b1() = c
  4684  	*(*prg.mem[int32(p)+1].hh()).rh() = q
  4685  	*(*prg.mem[p].hh()).b1() = 0
  4686  	r = p
  4687  	return r
  4688  }
  4689  
  4690  func (prg *prg) newLigItem(c quarterword) (r halfword) {
  4691  	var (
  4692  		p halfword // the new node
  4693  	)
  4694  	p = prg.getNode(smallNodeSize)
  4695  	*(*prg.mem[p].hh()).b1() = c
  4696  	*(*prg.mem[int32(p)+1].hh()).rh() = 0
  4697  	r = p
  4698  	return r
  4699  }
  4700  
  4701  // 145.
  4702  
  4703  // tangle:pos tex.web:3040:3:
  4704  
  4705  // A |disc_node|, which occurs only in horizontal lists, specifies a
  4706  // ``dis\-cretion\-ary'' line break. If such a break occurs at node |p|, the text
  4707  // that starts at |pre_break(p)| will precede the break, the text that starts at
  4708  // |post_break(p)| will follow the break, and text that appears in the next
  4709  // |replace_count(p)| nodes will be ignored. For example, an ordinary
  4710  // discretionary hyphen, indicated by `\.[\\-]', yields a |disc_node| with
  4711  // |pre_break| pointing to a |char_node| containing a hyphen, |post_break=null|,
  4712  // and |replace_count=0|. All three of the discretionary texts must be
  4713  // lists that consist entirely of character, kern, box, rule, and ligature nodes.
  4714  //
  4715  // If |pre_break(p)=null|, the |ex_hyphen_penalty| will be charged for this
  4716  // break.  Otherwise the |hyphen_penalty| will be charged.  The texts will
  4717  // actually be substituted into the list by the line-breaking algorithm if it
  4718  // decides to make the break, and the discretionary node will disappear at
  4719  // that time; thus, the output routine sees only discretionaries that were
  4720  // not chosen.
  4721  func (prg *prg) newDisc() (r halfword) { // creates an empty |disc_node|
  4722  	var (
  4723  		p halfword // the new node
  4724  	)
  4725  	p = prg.getNode(smallNodeSize)
  4726  	*(*prg.mem[p].hh()).b0() = byte(discNode)
  4727  	*(*prg.mem[p].hh()).b1() = 0
  4728  	*(*prg.mem[int32(p)+1].hh()).lh() = 0
  4729  	*(*prg.mem[int32(p)+1].hh()).rh() = 0
  4730  	r = p
  4731  	return r
  4732  }
  4733  
  4734  // 146.
  4735  
  4736  // tangle:pos tex.web:3069:3:
  4737  
  4738  // A |whatsit_node| is a wild card reserved for extensions to \TeX. The
  4739  // |subtype| field in its first word says what `\\[whatsit]' it is, and
  4740  // implicitly determines the node size (which must be 2 or more) and the
  4741  // format of the remaining words. When a |whatsit_node| is encountered
  4742  // in a list, special actions are invoked; knowledgeable people who are
  4743  // careful not to mess up the rest of \TeX\ are able to make \TeX\ do new
  4744  // things by adding code at the end of the program. For example, there
  4745  // might be a `\TeX nicolor' extension to specify different colors of ink,
  4746  // \xref[extensions to \TeX]
  4747  // and the whatsit node might contain the desired parameters.
  4748  //
  4749  // The present implementation of \TeX\ treats the features associated with
  4750  // `\.[\\write]' and `\.[\\special]' as if they were extensions, in order to
  4751  // illustrate how such routines might be coded. We shall defer further
  4752  // discussion of extensions until the end of this program.
  4753  
  4754  // 147.
  4755  
  4756  // tangle:pos tex.web:3087:3:
  4757  
  4758  // A |math_node|, which occurs only in horizontal lists, appears before and
  4759  // after mathematical formulas. The |subtype| field is |before| before the
  4760  // formula and |after| after it. There is a |width| field, which represents
  4761  // the amount of surrounding space inserted by \.[\\mathsurround].
  4762  func (prg *prg) newMath(w scaled, s smallNumber) (r halfword) {
  4763  	var (
  4764  		p halfword // the new node
  4765  	)
  4766  	p = prg.getNode(smallNodeSize)
  4767  	*(*prg.mem[p].hh()).b0() = byte(mathNode)
  4768  	*(*prg.mem[p].hh()).b1() = s
  4769  	*prg.mem[int32(p)+widthOffset].int() = w
  4770  	r = p
  4771  	return r
  4772  }
  4773  
  4774  // 148.
  4775  
  4776  // tangle:pos tex.web:3102:3:
  4777  
  4778  // \TeX\ makes use of the fact that |hlist_node|, |vlist_node|,
  4779  // |rule_node|, |ins_node|, |mark_node|, |adjust_node|, |ligature_node|,
  4780  // |disc_node|, |whatsit_node|, and |math_node| are at the low end of the
  4781  // type codes, by permitting a break at glue in a list if and only if the
  4782  // |type| of the previous node is less than |math_node|. Furthermore, a
  4783  // node is discarded after a break if its type is |math_node| or~more.
  4784  
  4785  // 149.
  4786  
  4787  // tangle:pos tex.web:3112:3:
  4788  
  4789  // A |glue_node| represents glue in a list. However, it is really only
  4790  // a pointer to a separate glue specification, since \TeX\ makes use of the
  4791  // fact that many essentially identical nodes of glue are usually present.
  4792  // If |p| points to a |glue_node|, |glue_ptr(p)| points to
  4793  // another packet of words that specify the stretch and shrink components, etc.
  4794  //
  4795  // Glue nodes also serve to represent leaders; the |subtype| is used to
  4796  // distinguish between ordinary glue (which is called |normal|) and the three
  4797  // kinds of leaders (which are called |a_leaders|, |c_leaders|, and |x_leaders|).
  4798  // The |leader_ptr| field points to a rule node or to a box node containing the
  4799  // leaders; it is set to |null| in ordinary glue nodes.
  4800  //
  4801  // Many kinds of glue are computed from \TeX's ``skip'' parameters, and
  4802  // it is helpful to know which parameter has led to a particular glue node.
  4803  // Therefore the |subtype| is set to indicate the source of glue, whenever
  4804  // it originated as a parameter. We will be defining symbolic names for the
  4805  // parameter numbers later (e.g., |line_skip_code=0|, |baseline_skip_code=1|,
  4806  // etc.); it suffices for now to say that the |subtype| of parametric glue
  4807  // will be the same as the parameter number, plus~one.
  4808  //
  4809  // In math formulas there are two more possibilities for the |subtype| in a
  4810  // glue node: |mu_glue| denotes an \.[\\mskip] (where the units are scaled \.[mu]
  4811  // instead of scaled \.[pt]); and |cond_math_glue| denotes the `\.[\\nonscript]'
  4812  // feature that cancels the glue node immediately following if it appears
  4813  // in a subscript.
  4814  
  4815  // 151.
  4816  
  4817  // tangle:pos tex.web:3174:3:
  4818  
  4819  // Here is a function that returns a pointer to a copy of a glue spec.
  4820  // The reference count in the copy is |null|, because there is assumed
  4821  // to be exactly one reference to the new specification.
  4822  func (prg *prg) newSpec(p halfword) (r halfword) { // duplicates a glue specification
  4823  	var (
  4824  		q halfword // the new spec
  4825  	)
  4826  	q = prg.getNode(glueSpecSize)
  4827  
  4828  	prg.mem[q] = prg.mem[p]
  4829  	*(*prg.mem[q].hh()).rh() = 0
  4830  
  4831  	*prg.mem[int32(q)+widthOffset].int() = *prg.mem[int32(p)+widthOffset].int()
  4832  	*prg.mem[int32(q)+2].int() = *prg.mem[int32(p)+2].int()
  4833  	*prg.mem[int32(q)+3].int() = *prg.mem[int32(p)+3].int()
  4834  	r = q
  4835  	return r
  4836  }
  4837  
  4838  // 152.
  4839  
  4840  // tangle:pos tex.web:3186:3:
  4841  
  4842  // And here's a function that creates a glue node for a given parameter
  4843  // identified by its code number; for example,
  4844  // |new_param_glue(line_skip_code)| returns a pointer to a glue node for the
  4845  // current \.[\\lineskip].
  4846  func (prg *prg) newParamGlue(n smallNumber) (r halfword) {
  4847  	var (
  4848  		p halfword // the new node
  4849  		q halfword // the glue specification
  4850  	)
  4851  	p = prg.getNode(smallNodeSize)
  4852  	*(*prg.mem[p].hh()).b0() = byte(glueNode)
  4853  	*(*prg.mem[p].hh()).b1() = byte(int32(n) + 1)
  4854  	*(*prg.mem[int32(p)+1].hh()).rh() = 0
  4855  
  4856  	q = *(*prg.eqtb[glueBase+int32(n)-1].hh()).rh()
  4857  	*(*prg.mem[int32(p)+1].hh()).lh() = q
  4858  	*(*prg.mem[q].hh()).rh() = uint16(int32(*(*prg.mem[q].hh()).rh()) + 1)
  4859  	r = p
  4860  	return r
  4861  }
  4862  
  4863  // 153.
  4864  
  4865  // tangle:pos tex.web:3201:3:
  4866  
  4867  // Glue nodes that are more or less anonymous are created by |new_glue|,
  4868  // whose argument points to a glue specification.
  4869  func (prg *prg) newGlue(q halfword) (r halfword) {
  4870  	var (
  4871  		p halfword // the new node
  4872  	)
  4873  	p = prg.getNode(smallNodeSize)
  4874  	*(*prg.mem[p].hh()).b0() = byte(glueNode)
  4875  	*(*prg.mem[p].hh()).b1() = byte(normal)
  4876  	*(*prg.mem[int32(p)+1].hh()).rh() = 0
  4877  	*(*prg.mem[int32(p)+1].hh()).lh() = q
  4878  	*(*prg.mem[q].hh()).rh() = uint16(int32(*(*prg.mem[q].hh()).rh()) + 1)
  4879  	r = p
  4880  	return r
  4881  }
  4882  
  4883  // 154.
  4884  
  4885  // tangle:pos tex.web:3211:3:
  4886  
  4887  // Still another subroutine is needed: This one is sort of a combination
  4888  // of |new_param_glue| and |new_glue|. It creates a glue node for one of
  4889  // the current glue parameters, but it makes a fresh copy of the glue
  4890  // specification, since that specification will probably be subject to change,
  4891  // while the parameter will stay put. The global variable |temp_ptr| is
  4892  // set to the address of the new spec.
  4893  func (prg *prg) newSkipParam(n smallNumber) (r halfword) {
  4894  	var (
  4895  		p halfword // the new node
  4896  	)
  4897  	prg.tempPtr = prg.newSpec(*(*prg.eqtb[glueBase+int32(n)-1].hh()).rh())
  4898  	p = prg.newGlue(prg.tempPtr)
  4899  	*(*prg.mem[prg.tempPtr].hh()).rh() = 0
  4900  	*(*prg.mem[p].hh()).b1() = byte(int32(n) + 1)
  4901  	r = p
  4902  	return r
  4903  }
  4904  
  4905  // 155.
  4906  
  4907  // tangle:pos tex.web:3225:3:
  4908  
  4909  // A |kern_node| has a |width| field to specify a (normally negative)
  4910  // amount of spacing. This spacing correction appears in horizontal lists
  4911  // between letters like A and V when the font designer said that it looks
  4912  // better to move them closer together or further apart. A kern node can
  4913  // also appear in a vertical list, when its `|width|' denotes additional
  4914  // spacing in the vertical direction. The |subtype| is either |normal| (for
  4915  // kerns inserted from font information or math mode calculations) or |explicit|
  4916  // (for kerns inserted from \.[\\kern] and \.[\\/] commands) or |acc_kern|
  4917  // (for kerns inserted from non-math accents) or |mu_glue| (for kerns
  4918  // inserted from \.[\\mkern] specifications in math formulas).
  4919  
  4920  // 156.
  4921  
  4922  // tangle:pos tex.web:3240:3:
  4923  
  4924  // The |new_kern| function creates a kern node having a given width.
  4925  func (prg *prg) newKern(w scaled) (r halfword) {
  4926  	var (
  4927  		p halfword // the new node
  4928  	)
  4929  	p = prg.getNode(smallNodeSize)
  4930  	*(*prg.mem[p].hh()).b0() = byte(kernNode)
  4931  	*(*prg.mem[p].hh()).b1() = byte(normal)
  4932  	*prg.mem[int32(p)+widthOffset].int() = w
  4933  	r = p
  4934  	return r
  4935  }
  4936  
  4937  // 157.
  4938  
  4939  // tangle:pos tex.web:3250:3:
  4940  
  4941  // A |penalty_node| specifies the penalty associated with line or page
  4942  // breaking, in its |penalty| field. This field is a fullword integer, but
  4943  // the full range of integer values is not used: Any penalty |>=10000| is
  4944  // treated as infinity, and no break will be allowed for such high values.
  4945  // Similarly, any penalty |<=-10000| is treated as negative infinity, and a
  4946  // break will be forced.
  4947  
  4948  // 158.
  4949  
  4950  // tangle:pos tex.web:3262:3:
  4951  
  4952  // Anyone who has been reading the last few sections of the program will
  4953  // be able to guess what comes next.
  4954  func (prg *prg) newPenalty(m int32) (r halfword) {
  4955  	var (
  4956  		p halfword // the new node
  4957  	)
  4958  	p = prg.getNode(smallNodeSize)
  4959  	*(*prg.mem[p].hh()).b0() = byte(penaltyNode)
  4960  	*(*prg.mem[p].hh()).b1() = 0 // the |subtype| is not used
  4961  	*prg.mem[int32(p)+1].int() = m
  4962  	r = p
  4963  	return r
  4964  }
  4965  
  4966  // 159.
  4967  
  4968  // tangle:pos tex.web:3272:3:
  4969  
  4970  // You might think that we have introduced enough node types by now. Well,
  4971  // almost, but there is one more: An |unset_node| has nearly the same format
  4972  // as an |hlist_node| or |vlist_node|; it is used for entries in \.[\\halign]
  4973  // or \.[\\valign] that are not yet in their final form, since the box
  4974  // dimensions are their ``natural'' sizes before any glue adjustment has been
  4975  // made. The |glue_set| word is not present; instead, we have a |glue_stretch|
  4976  // field, which contains the total stretch of order |glue_order| that is
  4977  // present in the hlist or vlist being boxed.
  4978  // Similarly, the |shift_amount| field is replaced by a |glue_shrink| field,
  4979  // containing the total shrink of order |glue_sign| that is present.
  4980  // The |subtype| field is called |span_count|; an unset box typically
  4981  // contains the data for |qo(span_count)+1| columns.
  4982  // Unset nodes will be changed to box nodes when alignment is completed.
  4983  
  4984  // 160.
  4985  
  4986  // tangle:pos tex.web:3291:3:
  4987  
  4988  // In fact, there are still more types coming. When we get to math formula
  4989  // processing we will see that a |style_node| has |type=14|; and a number
  4990  // of larger type codes will also be defined, for use in math mode only.
  4991  
  4992  // 161.
  4993  
  4994  // tangle:pos tex.web:3295:3:
  4995  
  4996  // Warning: If any changes are made to these data structure layouts, such as
  4997  // changing any of the node sizes or even reordering the words of nodes,
  4998  // the |copy_node_list| procedure and the memory initialization code
  4999  // below may have to be changed. Such potentially dangerous parts of the
  5000  // program are listed in the index under `data structure assumptions'.
  5001  //  \xref[data structure assumptions]
  5002  // However, other references to the nodes are made symbolically in terms of
  5003  // the \.[WEB] macro definitions above, so that format changes will leave
  5004  // \TeX's other algorithms intact.
  5005  // \xref[system dependencies]
  5006  
  5007  // 162. \[11] Memory layout
  5008  
  5009  // tangle:pos tex.web:3306:24:
  5010  
  5011  // Some areas of |mem| are dedicated to fixed usage, since static allocation is
  5012  // more efficient than dynamic allocation when we can get away with it. For
  5013  // example, locations |mem_bot| to |mem_bot+3| are always used to store the
  5014  // specification for glue that is `\.[0pt plus 0pt minus 0pt]'. The
  5015  // following macro definitions accomplish the static allocation by giving
  5016  // symbolic names to the fixed positions. Static variable-size nodes appear
  5017  // in locations |mem_bot| through |lo_mem_stat_max|, and static single-word nodes
  5018  // appear in locations |hi_mem_stat_min| through |mem_top|, inclusive. It is
  5019  // harmless to let |lig_trick| and |garbage| share the same location of |mem|.
  5020  
  5021  // 167.
  5022  
  5023  // tangle:pos tex.web:3402:3:
  5024  
  5025  // Procedure |check_mem| makes sure that the available space lists of
  5026  // |mem| are well formed, and it optionally prints out all locations
  5027  // that are reserved now but were free the last time this procedure was called.
  5028  //  procedure check_mem( print_locs : boolean);
  5029  // label done1,done2; [loop exits]
  5030  // var p, q:halfword ; [current locations of interest in |mem|]
  5031  //  clobbered:boolean; [is something amiss?]
  5032  // begin for p:=mem_min to lo_mem_max do free[p]:=false; [you can probably
  5033  //   do this faster]
  5034  // for p:=hi_mem_min to mem_end do free[p]:=false; [ditto]
  5035  //
  5036  // [ Check single-word |avail| list ]
  5037  // p:=avail; q:=0  ; clobbered:=false;
  5038  // while p<>0   do
  5039  //   begin if (p>mem_end)or(p<hi_mem_min) then clobbered:=true
  5040  //   else if free[p] then clobbered:=true;
  5041  //   if clobbered then
  5042  //     begin print_nl(["AVAIL list clobbered at "=]301);
  5043  // [ \xref[AVAIL list clobbered...] ]
  5044  //     print_int(q); goto done1;
  5045  //     end;
  5046  //   free[p]:=true; q:=p; p:= mem[ q].hh.rh ;
  5047  //   end;
  5048  // done1:
  5049  //
  5050  // ;
  5051  //
  5052  // [ Check variable-size |avail| list ]
  5053  // p:=rover; q:=0  ; clobbered:=false;
  5054  // repeat if (p>=lo_mem_max)or(p<mem_min) then clobbered:=true
  5055  //   else if (  mem[  p+ 1].hh.rh  >=lo_mem_max)or(  mem[  p+ 1].hh.rh  <mem_min) then clobbered:=true
  5056  //   else if  not( ( mem[  p].hh.rh = 65535  ) )or(  mem[ p].hh.lh <2)or
  5057  //    (p+  mem[ p].hh.lh >lo_mem_max)or  (  mem[    mem[    p+ 1].hh.rh  + 1].hh.lh  <>p) then clobbered:=true;
  5058  //   if clobbered then
  5059  //   begin print_nl(["Double-AVAIL list clobbered at "=]302);
  5060  //   print_int(q); goto done2;
  5061  //   end;
  5062  // for q:=p to p+  mem[ p].hh.lh -1 do [mark all locations free]
  5063  //   begin if free[q] then
  5064  //     begin print_nl(["Doubly free location at "=]303);
  5065  // [ \xref[Doubly free location...] ]
  5066  //     print_int(q); goto done2;
  5067  //     end;
  5068  //   free[q]:=true;
  5069  //   end;
  5070  // q:=p; p:=  mem[  p+ 1].hh.rh  ;
  5071  // until p=rover;
  5072  // done2:
  5073  //
  5074  // ;
  5075  //
  5076  // [ Check flags of unavailable nodes ]
  5077  // p:=mem_min;
  5078  // while p<=lo_mem_max do [node |p| should not be empty]
  5079  //   begin if  ( mem[  p].hh.rh = 65535  )  then
  5080  //     begin print_nl(["Bad flag at "=]304); print_int(p);
  5081  // [ \xref[Bad flag...] ]
  5082  //     end;
  5083  //   while (p<=lo_mem_max) and not free[p] do   p:= p+1 ;
  5084  //   while (p<=lo_mem_max) and free[p] do   p:= p+1 ;
  5085  //   end
  5086  //
  5087  // ;
  5088  // if print_locs then
  5089  // [ Print newly busy locations ]
  5090  // begin print_nl(["New busy locs:"=]305);
  5091  // for p:=mem_min to lo_mem_max do
  5092  //   if not free[p] and ((p>was_lo_max) or was_free[p]) then
  5093  //     begin print_char([" "=]32); print_int(p);
  5094  //     end;
  5095  // for p:=hi_mem_min to mem_end do
  5096  //   if not free[p] and
  5097  //    ((p<was_hi_min) or (p>was_mem_end) or was_free[p]) then
  5098  //     begin print_char([" "=]32); print_int(p);
  5099  //     end;
  5100  // end
  5101  //
  5102  // ;
  5103  // for p:=mem_min to lo_mem_max do was_free[p]:=free[p];
  5104  // for p:=hi_mem_min to mem_end do was_free[p]:=free[p];
  5105  //   [|was_free:=free| might be faster]
  5106  // was_mem_end:=mem_end; was_lo_max:=lo_mem_max; was_hi_min:=hi_mem_min;
  5107  // end;
  5108  // [  ]
  5109  
  5110  // 172.
  5111  
  5112  // tangle:pos tex.web:3484:3:
  5113  
  5114  // The |search_mem| procedure attempts to answer the question ``Who points
  5115  // to node~|p|?'' In doing so, it fetches |link| and |info| fields of |mem|
  5116  // that might not be of type |two_halves|. Strictly speaking, this is
  5117  // \xref[dirty \PASCAL]
  5118  // undefined in \PASCAL, and it can lead to ``false drops'' (words that seem to
  5119  // point to |p| purely by coincidence). But for debugging purposes, we want
  5120  // to rule out the places that do [\sl not\/] point to |p|, so a few false
  5121  // drops are tolerable.
  5122  //  procedure search_mem( p:halfword ); [look for pointers to |p|]
  5123  // var q:integer; [current position being searched]
  5124  // begin for q:=mem_min to lo_mem_max do
  5125  //   begin if  mem[ q].hh.rh =p then
  5126  //     begin print_nl(["LINK("=]306); print_int(q); print_char([")"=]41);
  5127  //     end;
  5128  //   if  mem[ q].hh.lh =p then
  5129  //     begin print_nl(["INFO("=]307); print_int(q); print_char([")"=]41);
  5130  //     end;
  5131  //   end;
  5132  // for q:=hi_mem_min to mem_end do
  5133  //   begin if  mem[ q].hh.rh =p then
  5134  //     begin print_nl(["LINK("=]306); print_int(q); print_char([")"=]41);
  5135  //     end;
  5136  //   if  mem[ q].hh.lh =p then
  5137  //     begin print_nl(["INFO("=]307); print_int(q); print_char([")"=]41);
  5138  //     end;
  5139  //   end;
  5140  //
  5141  // [ Search |eqtb| for equivalents equal to |p| ]
  5142  // for q:=active_base to box_base+255 do
  5143  //   begin if  eqtb[  q].hh.rh  =p then
  5144  //     begin print_nl(["EQUIV("=]501); print_int(q); print_char([")"=]41);
  5145  //     end;
  5146  //   end
  5147  //
  5148  // ;
  5149  //
  5150  // [ Search |save_stack| for equivalents that point to |p| ]
  5151  // if save_ptr>0 then for q:=0 to save_ptr-1 do
  5152  //   begin if  save_stack[ q].hh.rh =p then
  5153  //     begin print_nl(["SAVE("=]546); print_int(q); print_char([")"=]41);
  5154  //     end;
  5155  //   end
  5156  //
  5157  // ;
  5158  //
  5159  // [ Search |hyph_list| for pointers to |p| ]
  5160  // for q:=0 to hyph_size do
  5161  //   begin if hyph_list[q]=p then
  5162  //     begin print_nl(["HYPH("=]940); print_int(q); print_char([")"=]41);
  5163  //     end;
  5164  //   end
  5165  //
  5166  // ;
  5167  // end;
  5168  // [  ]
  5169  
  5170  // 174.
  5171  
  5172  // tangle:pos tex.web:3538:3:
  5173  
  5174  // Boxes, rules, inserts, whatsits, marks, and things in general that are
  5175  // sort of ``complicated'' are indicated only by printing `\.[[]]'.
  5176  func (prg *prg) shortDisplay(p int32) { // prints highlights of list |p|
  5177  	var (
  5178  		n int32 // for replacement counts
  5179  	)
  5180  	for p > memMin {
  5181  		if p >= int32(prg.hiMemMin) {
  5182  			if p <= int32(prg.memEnd) {
  5183  				if int32(*(*prg.mem[p].hh()).b0()) != prg.fontInShortDisplay {
  5184  					if int32(*(*prg.mem[p].hh()).b0()) < fontBase || int32(*(*prg.mem[p].hh()).b0()) > fontMax {
  5185  						prg.printChar(asciiCode('*'))
  5186  					} else {
  5187  						// Print the font identifier for |font(p)|
  5188  						prg.printEsc(*prg.hash[fontIdBase+int32(*(*prg.mem[p].hh()).b0())-514].rh())
  5189  					}
  5190  					prg.printChar(asciiCode(' '))
  5191  					prg.fontInShortDisplay = int32(*(*prg.mem[p].hh()).b0())
  5192  				}
  5193  				prg.print(int32(*(*prg.mem[p].hh()).b1()) - minQuarterword)
  5194  			}
  5195  		} else {
  5196  			// Print a short indication of the contents of node |p|
  5197  			switch *(*prg.mem[p].hh()).b0() {
  5198  			case hlistNode, vlistNode, insNode, whatsitNode,
  5199  				markNode, adjustNode, unsetNode:
  5200  				prg.print( /* "[]" */ 308)
  5201  			case ruleNode:
  5202  				prg.printChar(asciiCode('|'))
  5203  			case glueNode:
  5204  				if int32(*(*prg.mem[p+1].hh()).lh()) != memBot {
  5205  					prg.printChar(asciiCode(' '))
  5206  				}
  5207  			case mathNode:
  5208  				prg.printChar(asciiCode('$'))
  5209  			case ligatureNode:
  5210  				prg.shortDisplay(int32(*(*prg.mem[p+1].hh()).rh()))
  5211  			case discNode:
  5212  				prg.shortDisplay(int32(*(*prg.mem[p+1].hh()).lh()))
  5213  				prg.shortDisplay(int32(*(*prg.mem[p+1].hh()).rh()))
  5214  
  5215  				n = int32(*(*prg.mem[p].hh()).b1())
  5216  				for n > 0 {
  5217  					if int32(*(*prg.mem[p].hh()).rh()) != 0 {
  5218  						p = int32(*(*prg.mem[p].hh()).rh())
  5219  					}
  5220  					n = n - 1
  5221  				}
  5222  
  5223  			default:
  5224  			}
  5225  		}
  5226  		p = int32(*(*prg.mem[p].hh()).rh())
  5227  	}
  5228  }
  5229  
  5230  // 176.
  5231  
  5232  // tangle:pos tex.web:3580:3:
  5233  
  5234  // The |show_node_list| routine requires some auxiliary subroutines: one to
  5235  // print a font-and-character combination, one to print a token list without
  5236  // its reference count, and one to print a rule dimension.
  5237  func (prg *prg) printFontAndChar(p int32) {
  5238  	if p > int32(prg.memEnd) {
  5239  		prg.printEsc(strNumber( /* "CLOBBERED." */ 309))
  5240  	} else {
  5241  		if int32(*(*prg.mem[p].hh()).b0()) < fontBase || int32(*(*prg.mem[p].hh()).b0()) > fontMax {
  5242  			prg.printChar(asciiCode('*'))
  5243  		} else {
  5244  			// Print the font identifier for |font(p)|
  5245  			prg.printEsc(*prg.hash[fontIdBase+int32(*(*prg.mem[p].hh()).b0())-514].rh())
  5246  		}
  5247  		prg.printChar(asciiCode(' '))
  5248  		prg.print(int32(*(*prg.mem[p].hh()).b1()) - minQuarterword)
  5249  	}
  5250  }
  5251  
  5252  func (prg *prg) printMark(p int32) {
  5253  	prg.printChar(asciiCode('{'))
  5254  	if p < int32(prg.hiMemMin) || p > int32(prg.memEnd) {
  5255  		prg.printEsc(strNumber( /* "CLOBBERED." */ 309))
  5256  	} else {
  5257  		prg.showTokenList(int32(*(*prg.mem[p].hh()).rh()), 0, maxPrintLine-10)
  5258  	}
  5259  	prg.printChar(asciiCode('}'))
  5260  }
  5261  
  5262  func (prg *prg) printRuleDimen(d scaled) {
  5263  	if d == -010000000000 {
  5264  		prg.printChar(asciiCode('*'))
  5265  	} else {
  5266  		prg.printScaled(d)
  5267  	}
  5268  	// \xref[*\relax]
  5269  }
  5270  
  5271  // 177.
  5272  
  5273  // tangle:pos tex.web:3605:3:
  5274  
  5275  // Then there is a subroutine that prints glue stretch and shrink, possibly
  5276  // followed by the name of finite units:
  5277  func (prg *prg) printGlue(d scaled, order int32, s strNumber) {
  5278  	prg.printScaled(d)
  5279  	if order < normal || order > filll {
  5280  		prg.print( /* "foul" */ 310)
  5281  	} else if order > normal {
  5282  		prg.print( /* "fil" */ 311)
  5283  		for order > fil {
  5284  			prg.printChar(asciiCode('l'))
  5285  			order = order - 1
  5286  		}
  5287  	} else if int32(s) != 0 {
  5288  		prg.print(int32(s))
  5289  	}
  5290  }
  5291  
  5292  // 178.
  5293  
  5294  // tangle:pos tex.web:3621:3:
  5295  
  5296  // The next subroutine prints a whole glue specification.
  5297  func (prg *prg) printSpec(p int32, s strNumber) {
  5298  	if p < memMin || p >= int32(prg.loMemMax) {
  5299  		prg.printChar(asciiCode('*'))
  5300  	} else {
  5301  		prg.printScaled(*prg.mem[p+widthOffset].int())
  5302  		if int32(s) != 0 {
  5303  			prg.print(int32(s))
  5304  		}
  5305  		if *prg.mem[p+2].int() != 0 {
  5306  			prg.print( /* " plus " */ 312)
  5307  			prg.printGlue(*prg.mem[p+2].int(), int32(*(*prg.mem[p].hh()).b0()), s)
  5308  		}
  5309  		if *prg.mem[p+3].int() != 0 {
  5310  			prg.print( /* " minus " */ 313)
  5311  			prg.printGlue(*prg.mem[p+3].int(), int32(*(*prg.mem[p].hh()).b1()), s)
  5312  		}
  5313  	}
  5314  }
  5315  
  5316  // 179.
  5317  
  5318  // tangle:pos tex.web:3638:3:
  5319  
  5320  // We also need to declare some procedures that appear later in this
  5321  // documentation.
  5322  
  5323  // Declare procedures needed for displaying the elements of mlists
  5324  func (prg *prg) printFamAndChar(p halfword) {
  5325  	prg.printEsc(strNumber( /* "fam" */ 464))
  5326  	prg.printInt(int32(*(*prg.mem[p].hh()).b0()))
  5327  	prg.printChar(asciiCode(' '))
  5328  	prg.print(int32(*(*prg.mem[p].hh()).b1()) - minQuarterword)
  5329  }
  5330  
  5331  func (prg *prg) printDelimiter(p halfword) { // prints a delimiter as 24-bit hex value
  5332  	var (
  5333  		a int32 // accumulator
  5334  	)
  5335  	a = int32((*prg.mem[p].qqqq()).b0)*256 + int32((*prg.mem[p].qqqq()).b1) - minQuarterword
  5336  	a = a*010000 + int32((*prg.mem[p].qqqq()).b2)*256 + int32((*prg.mem[p].qqqq()).b3) - minQuarterword
  5337  	if a < 0 {
  5338  		prg.printInt(a)
  5339  	} else {
  5340  		prg.printHex(a)
  5341  	}
  5342  } // \2
  5343  // |show_node_list(info(temp_ptr))|
  5344  func (prg *prg) printSubsidiaryData(p halfword, c asciiCode) {
  5345  	if int32(prg.poolPtr)-int32(prg.strStart[prg.strPtr]) >= prg.depthThreshold {
  5346  		if int32(*(*prg.mem[p].hh()).rh()) != empty {
  5347  			prg.print( /* " []" */ 314)
  5348  		}
  5349  	} else {
  5350  		{
  5351  			prg.strPool[prg.poolPtr] = c
  5352  			prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  5353  		} // include |c| in the recursion history
  5354  		prg.tempPtr = p // prepare for |show_info| if recursion is needed
  5355  		switch *(*prg.mem[p].hh()).rh() {
  5356  		case mathChar:
  5357  			prg.printLn()
  5358  			prg.printCurrentString()
  5359  			prg.printFamAndChar(p)
  5360  
  5361  		case subBox:
  5362  			prg.showInfo() // recursive call
  5363  		case subMlist:
  5364  			if int32(*(*prg.mem[p].hh()).lh()) == 0 {
  5365  				prg.printLn()
  5366  				prg.printCurrentString()
  5367  				prg.print( /* "[]" */ 860)
  5368  			} else {
  5369  				prg.showInfo()
  5370  			}
  5371  			// recursive call
  5372  		default: // |empty|
  5373  		}
  5374  
  5375  		prg.poolPtr = uint16(int32(prg.poolPtr) - 1) // remove |c| from the recursion history
  5376  	}
  5377  }
  5378  
  5379  func (prg *prg) printStyle(c int32) {
  5380  	switch c / 2 {
  5381  	case 0:
  5382  		prg.printEsc(strNumber( /* "displaystyle" */ 861)) // |display_style=0|
  5383  	case 1:
  5384  		prg.printEsc(strNumber( /* "textstyle" */ 862)) // |text_style=2|
  5385  	case 2:
  5386  		prg.printEsc(strNumber( /* "scriptstyle" */ 863)) // |script_style=4|
  5387  	case 3:
  5388  		prg.printEsc(strNumber( /* "scriptscriptstyle" */ 864))
  5389  		// |script_script_style=6|
  5390  	default:
  5391  		prg.print( /* "Unknown style!" */ 865)
  5392  	}
  5393  }
  5394  
  5395  // Declare the procedure called |print_skip_param|
  5396  func (prg *prg) printSkipParam(n int32) {
  5397  	switch n {
  5398  	case lineSkipCode:
  5399  		prg.printEsc(strNumber( /* "lineskip" */ 376))
  5400  	case baselineSkipCode:
  5401  		prg.printEsc(strNumber( /* "baselineskip" */ 377))
  5402  	case parSkipCode:
  5403  		prg.printEsc(strNumber( /* "parskip" */ 378))
  5404  	case aboveDisplaySkipCode:
  5405  		prg.printEsc(strNumber( /* "abovedisplayskip" */ 379))
  5406  	case belowDisplaySkipCode:
  5407  		prg.printEsc(strNumber( /* "belowdisplayskip" */ 380))
  5408  	case aboveDisplayShortSkipCode:
  5409  		prg.printEsc(strNumber( /* "abovedisplayshortskip" */ 381))
  5410  	case belowDisplayShortSkipCode:
  5411  		prg.printEsc(strNumber( /* "belowdisplayshortskip" */ 382))
  5412  	case leftSkipCode:
  5413  		prg.printEsc(strNumber( /* "leftskip" */ 383))
  5414  	case rightSkipCode:
  5415  		prg.printEsc(strNumber( /* "rightskip" */ 384))
  5416  	case topSkipCode:
  5417  		prg.printEsc(strNumber( /* "topskip" */ 385))
  5418  	case splitTopSkipCode:
  5419  		prg.printEsc(strNumber( /* "splittopskip" */ 386))
  5420  	case tabSkipCode:
  5421  		prg.printEsc(strNumber( /* "tabskip" */ 387))
  5422  	case spaceSkipCode:
  5423  		prg.printEsc(strNumber( /* "spaceskip" */ 388))
  5424  	case xspaceSkipCode:
  5425  		prg.printEsc(strNumber( /* "xspaceskip" */ 389))
  5426  	case parFillSkipCode:
  5427  		prg.printEsc(strNumber( /* "parfillskip" */ 390))
  5428  	case thinMuSkipCode:
  5429  		prg.printEsc(strNumber( /* "thinmuskip" */ 391))
  5430  	case medMuSkipCode:
  5431  		prg.printEsc(strNumber( /* "medmuskip" */ 392))
  5432  	case thickMuSkipCode:
  5433  		prg.printEsc(strNumber( /* "thickmuskip" */ 393))
  5434  
  5435  	default:
  5436  		prg.print( /* "[unknown glue parameter!]" */ 394)
  5437  	}
  5438  }
  5439  
  5440  // 180.
  5441  
  5442  // tangle:pos tex.web:3644:3:
  5443  
  5444  // Since boxes can be inside of boxes, |show_node_list| is inherently recursive,
  5445  // \xref[recursion]
  5446  // up to a given maximum number of levels.  The history of nesting is indicated
  5447  // by the current string, which will be printed at the beginning of each line;
  5448  // the length of this string, namely |cur_length|, is the depth of nesting.
  5449  //
  5450  // Recursive calls on |show_node_list| therefore use the following pattern:
  5451  
  5452  // 182.
  5453  
  5454  // tangle:pos tex.web:3667:3:
  5455  
  5456  // Now we are ready for |show_node_list| itself. This procedure has been
  5457  // written to be ``extra robust'' in the sense that it should not crash or get
  5458  // into a loop even if the data structures have been messed up by bugs in
  5459  // the rest of the program. You can safely call its parent routine
  5460  // |show_box(p)| for arbitrary values of |p| when you are debugging \TeX.
  5461  // However, in the presence of bad data, the procedure may
  5462  // \xref[dirty \PASCAL]\xref[debugging]
  5463  // fetch a |memory_word| whose variant is different from the way it was stored;
  5464  // for example, it might try to read |mem[p].hh| when |mem[p]|
  5465  // contains a scaled integer, if |p| is a pointer that has been
  5466  // clobbered or chosen at random.
  5467  func (prg *prg) showNodeList(p int32) {
  5468  	var (
  5469  		n int32   // the number of items already printed at this level
  5470  		g float64 // a glue ratio, as a floating point number
  5471  	)
  5472  	if int32(prg.poolPtr)-int32(prg.strStart[prg.strPtr]) > prg.depthThreshold {
  5473  		if p > 0 {
  5474  			prg.print( /* " []" */ 314)
  5475  		}
  5476  		// indicate that there's been some truncation
  5477  
  5478  		// indicate that there's been some truncation
  5479  		goto exit
  5480  	}
  5481  	n = 0
  5482  	for p > memMin {
  5483  		prg.printLn()
  5484  		prg.printCurrentString() // display the nesting history
  5485  		if p > int32(prg.memEnd) {
  5486  			prg.print( /* "Bad link, display aborted." */ 315)
  5487  			goto exit
  5488  			// \xref[Bad link...]
  5489  		}
  5490  		n = n + 1
  5491  		if n > prg.breadthMax {
  5492  			prg.print( /* "etc." */ 316)
  5493  			goto exit
  5494  			// \xref[etc]
  5495  		}
  5496  
  5497  		// Display node |p|
  5498  		if p >= int32(prg.hiMemMin) {
  5499  			prg.printFontAndChar(p)
  5500  		} else {
  5501  			switch *(*prg.mem[p].hh()).b0() {
  5502  			case hlistNode, vlistNode, unsetNode:
  5503  				// Display box |p|
  5504  				if int32(*(*prg.mem[p].hh()).b0()) == hlistNode {
  5505  					prg.printEsc(strNumber('h'))
  5506  				} else if int32(*(*prg.mem[p].hh()).b0()) == vlistNode {
  5507  					prg.printEsc(strNumber('v'))
  5508  				} else {
  5509  					prg.printEsc(strNumber( /* "unset" */ 318))
  5510  				}
  5511  				prg.print( /* "box(" */ 319)
  5512  				prg.printScaled(*prg.mem[p+heightOffset].int())
  5513  				prg.printChar(asciiCode('+'))
  5514  				prg.printScaled(*prg.mem[p+depthOffset].int())
  5515  				prg.print( /* ")x" */ 320)
  5516  				prg.printScaled(*prg.mem[p+widthOffset].int())
  5517  				if int32(*(*prg.mem[p].hh()).b0()) == unsetNode {
  5518  					if int32(*(*prg.mem[p].hh()).b1()) != minQuarterword {
  5519  						prg.print( /* " (" */ 286)
  5520  						prg.printInt(int32(*(*prg.mem[p].hh()).b1()) - minQuarterword + 1)
  5521  						prg.print( /* " columns)" */ 322)
  5522  					}
  5523  					if *prg.mem[p+glueOffset].int() != 0 {
  5524  						prg.print( /* ", stretch " */ 323)
  5525  						prg.printGlue(*prg.mem[p+glueOffset].int(), int32(*(*prg.mem[p+listOffset].hh()).b1()), strNumber(0))
  5526  					}
  5527  					if *prg.mem[p+4].int() != 0 {
  5528  						prg.print( /* ", shrink " */ 324)
  5529  						prg.printGlue(*prg.mem[p+4].int(), int32(*(*prg.mem[p+listOffset].hh()).b0()), strNumber(0))
  5530  					}
  5531  				} else {
  5532  					g = float64(*prg.mem[p+glueOffset].gr())
  5533  					if g != 0.0 && int32(*(*prg.mem[p+listOffset].hh()).b0()) != normal {
  5534  						prg.print( /* ", glue set " */ 325)
  5535  						if int32(*(*prg.mem[p+listOffset].hh()).b0()) == shrinking {
  5536  							prg.print( /* "- " */ 326)
  5537  						}
  5538  						if abs(*prg.mem[p+glueOffset].int()) < 04000000 {
  5539  							prg.print( /* "?.?" */ 327)
  5540  						} else if fabs(g) > 20000.0 {
  5541  							if g > 0.0 {
  5542  								prg.printChar(asciiCode('>'))
  5543  							} else {
  5544  								prg.print( /* "< -" */ 328)
  5545  							}
  5546  							prg.printGlue(20000*0200000, int32(*(*prg.mem[p+listOffset].hh()).b1()), strNumber(0))
  5547  						} else {
  5548  							prg.printGlue(round(float64(0200000)*g), int32(*(*prg.mem[p+listOffset].hh()).b1()), strNumber(0))
  5549  						}
  5550  						// \xref[real multiplication]
  5551  					}
  5552  					if *prg.mem[p+4].int() != 0 {
  5553  						prg.print( /* ", shifted " */ 321)
  5554  						prg.printScaled(*prg.mem[p+4].int())
  5555  					}
  5556  				}
  5557  				{
  5558  					{
  5559  						prg.strPool[prg.poolPtr] = '.'
  5560  						prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  5561  					}
  5562  					prg.showNodeList(int32(*(*prg.mem[p+listOffset].hh()).rh()))
  5563  					prg.poolPtr = uint16(int32(prg.poolPtr) - 1)
  5564  				} // recursive call
  5565  
  5566  			case ruleNode:
  5567  				// Display rule |p|
  5568  				prg.printEsc(strNumber( /* "rule(" */ 329))
  5569  				prg.printRuleDimen(*prg.mem[p+heightOffset].int())
  5570  				prg.printChar(asciiCode('+'))
  5571  				prg.printRuleDimen(*prg.mem[p+depthOffset].int())
  5572  				prg.print( /* ")x" */ 320)
  5573  				prg.printRuleDimen(*prg.mem[p+widthOffset].int())
  5574  
  5575  			case insNode:
  5576  				// Display insertion |p|
  5577  				prg.printEsc(strNumber( /* "insert" */ 330))
  5578  				prg.printInt(int32(*(*prg.mem[p].hh()).b1()) - minQuarterword)
  5579  				prg.print( /* ", natural size " */ 331)
  5580  				prg.printScaled(*prg.mem[p+heightOffset].int())
  5581  				prg.print( /* "; split(" */ 332)
  5582  				prg.printSpec(int32(*(*prg.mem[p+4].hh()).rh()), strNumber(0))
  5583  				prg.printChar(asciiCode(','))
  5584  				prg.printScaled(*prg.mem[p+depthOffset].int())
  5585  				prg.print( /* "); float cost " */ 333)
  5586  				prg.printInt(*prg.mem[p+1].int())
  5587  				{
  5588  					{
  5589  						prg.strPool[prg.poolPtr] = '.'
  5590  						prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  5591  					}
  5592  					prg.showNodeList(int32(*(*prg.mem[p+4].hh()).lh()))
  5593  					prg.poolPtr = uint16(int32(prg.poolPtr) - 1)
  5594  				} // recursive call
  5595  
  5596  			case whatsitNode:
  5597  				// Display the whatsit node |p|
  5598  				switch *(*prg.mem[p].hh()).b1() {
  5599  				case openNode:
  5600  					prg.printWriteWhatsit(strNumber( /* "openout" */ 1285), halfword(p))
  5601  					prg.printChar(asciiCode('='))
  5602  					prg.printFileName(int32(*(*prg.mem[p+1].hh()).rh()), int32(*(*prg.mem[p+2].hh()).lh()), int32(*(*prg.mem[p+2].hh()).rh()))
  5603  
  5604  				case writeNode:
  5605  					prg.printWriteWhatsit(strNumber( /* "write" */ 594), halfword(p))
  5606  					prg.printMark(int32(*(*prg.mem[p+1].hh()).rh()))
  5607  
  5608  				case closeNode:
  5609  					prg.printWriteWhatsit(strNumber( /* "closeout" */ 1286), halfword(p))
  5610  				case specialNode:
  5611  					prg.printEsc(strNumber( /* "special" */ 1287))
  5612  					prg.printMark(int32(*(*prg.mem[p+1].hh()).rh()))
  5613  
  5614  				case languageNode:
  5615  					prg.printEsc(strNumber( /* "setlanguage" */ 1289))
  5616  					prg.printInt(int32(*(*prg.mem[p+1].hh()).rh()))
  5617  					prg.print( /* " (hyphenmin " */ 1292)
  5618  					prg.printInt(int32(*(*prg.mem[p+1].hh()).b0()))
  5619  					prg.printChar(asciiCode(','))
  5620  					prg.printInt(int32(*(*prg.mem[p+1].hh()).b1()))
  5621  					prg.printChar(asciiCode(')'))
  5622  
  5623  				default:
  5624  					prg.print( /* "whatsit?" */ 1293)
  5625  				}
  5626  
  5627  			case glueNode:
  5628  				// Display glue |p|
  5629  				if int32(*(*prg.mem[p].hh()).b1()) >= aLeaders {
  5630  					prg.printEsc(strNumber( /* "" */ 338))
  5631  					if int32(*(*prg.mem[p].hh()).b1()) == cLeaders {
  5632  						prg.printChar(asciiCode('c'))
  5633  					} else if int32(*(*prg.mem[p].hh()).b1()) == xLeaders {
  5634  						prg.printChar(asciiCode('x'))
  5635  					}
  5636  					prg.print( /* "leaders " */ 339)
  5637  					prg.printSpec(int32(*(*prg.mem[p+1].hh()).lh()), strNumber(0))
  5638  					{
  5639  						{
  5640  							prg.strPool[prg.poolPtr] = '.'
  5641  							prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  5642  						}
  5643  						prg.showNodeList(int32(*(*prg.mem[p+1].hh()).rh()))
  5644  						prg.poolPtr = uint16(int32(prg.poolPtr) - 1)
  5645  					} // recursive call
  5646  				} else {
  5647  					prg.printEsc(strNumber( /* "glue" */ 334))
  5648  					if int32(*(*prg.mem[p].hh()).b1()) != normal {
  5649  						prg.printChar(asciiCode('('))
  5650  						if int32(*(*prg.mem[p].hh()).b1()) < condMathGlue {
  5651  							prg.printSkipParam(int32(*(*prg.mem[p].hh()).b1()) - 1)
  5652  						} else if int32(*(*prg.mem[p].hh()).b1()) == condMathGlue {
  5653  							prg.printEsc(strNumber( /* "nonscript" */ 335))
  5654  						} else {
  5655  							prg.printEsc(strNumber( /* "mskip" */ 336))
  5656  						}
  5657  						prg.printChar(asciiCode(')'))
  5658  					}
  5659  					if int32(*(*prg.mem[p].hh()).b1()) != condMathGlue {
  5660  						prg.printChar(asciiCode(' '))
  5661  						if int32(*(*prg.mem[p].hh()).b1()) < condMathGlue {
  5662  							prg.printSpec(int32(*(*prg.mem[p+1].hh()).lh()), strNumber(0))
  5663  						} else {
  5664  							prg.printSpec(int32(*(*prg.mem[p+1].hh()).lh()), strNumber( /* "mu" */ 337))
  5665  						}
  5666  					}
  5667  				}
  5668  
  5669  			case kernNode:
  5670  				// Display kern |p|
  5671  				if int32(*(*prg.mem[p].hh()).b1()) != muGlue {
  5672  					prg.printEsc(strNumber( /* "kern" */ 340))
  5673  					if int32(*(*prg.mem[p].hh()).b1()) != normal {
  5674  						prg.printChar(asciiCode(' '))
  5675  					}
  5676  					prg.printScaled(*prg.mem[p+widthOffset].int())
  5677  					if int32(*(*prg.mem[p].hh()).b1()) == accKern {
  5678  						prg.print( /* " (for accent)" */ 341)
  5679  					}
  5680  					// \xref[for accent]
  5681  				} else {
  5682  					prg.printEsc(strNumber( /* "mkern" */ 342))
  5683  					prg.printScaled(*prg.mem[p+widthOffset].int())
  5684  					prg.print( /* "mu" */ 337)
  5685  				}
  5686  
  5687  			case mathNode:
  5688  				// Display math node |p|
  5689  				prg.printEsc(strNumber( /* "math" */ 343))
  5690  				if int32(*(*prg.mem[p].hh()).b1()) == before {
  5691  					prg.print( /* "on" */ 344)
  5692  				} else {
  5693  					prg.print( /* "off" */ 345)
  5694  				}
  5695  				if *prg.mem[p+widthOffset].int() != 0 {
  5696  					prg.print( /* ", surrounded " */ 346)
  5697  					prg.printScaled(*prg.mem[p+widthOffset].int())
  5698  				}
  5699  
  5700  			case ligatureNode:
  5701  				// Display ligature |p|
  5702  				prg.printFontAndChar(p + 1)
  5703  				prg.print( /* " (ligature " */ 347)
  5704  				if int32(*(*prg.mem[p].hh()).b1()) > 1 {
  5705  					prg.printChar(asciiCode('|'))
  5706  				}
  5707  				prg.fontInShortDisplay = int32(*(*prg.mem[p+1].hh()).b0())
  5708  				prg.shortDisplay(int32(*(*prg.mem[p+1].hh()).rh()))
  5709  				if *(*prg.mem[p].hh()).b1()&1 != 0 {
  5710  					prg.printChar(asciiCode('|'))
  5711  				}
  5712  				prg.printChar(asciiCode(')'))
  5713  
  5714  			case penaltyNode:
  5715  				// Display penalty |p|
  5716  				prg.printEsc(strNumber( /* "penalty " */ 348))
  5717  				prg.printInt(*prg.mem[p+1].int())
  5718  
  5719  			case discNode:
  5720  				// Display discretionary |p|
  5721  				prg.printEsc(strNumber( /* "discretionary" */ 349))
  5722  				if int32(*(*prg.mem[p].hh()).b1()) > 0 {
  5723  					prg.print( /* " replacing " */ 350)
  5724  					prg.printInt(int32(*(*prg.mem[p].hh()).b1()))
  5725  				}
  5726  				{
  5727  					{
  5728  						prg.strPool[prg.poolPtr] = '.'
  5729  						prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  5730  					}
  5731  					prg.showNodeList(int32(*(*prg.mem[p+1].hh()).lh()))
  5732  					prg.poolPtr = uint16(int32(prg.poolPtr) - 1)
  5733  				} // recursive call
  5734  				{
  5735  					prg.strPool[prg.poolPtr] = '|'
  5736  					prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  5737  				}
  5738  				prg.showNodeList(int32(*(*prg.mem[p+1].hh()).rh()))
  5739  				prg.poolPtr = uint16(int32(prg.poolPtr) - 1) // recursive call
  5740  
  5741  			case markNode:
  5742  				// Display mark |p|
  5743  				prg.printEsc(strNumber( /* "mark" */ 351))
  5744  				prg.printMark(*prg.mem[p+1].int())
  5745  
  5746  			case adjustNode:
  5747  				// Display adjustment |p|
  5748  				prg.printEsc(strNumber( /* "vadjust" */ 352))
  5749  				{
  5750  					{
  5751  						prg.strPool[prg.poolPtr] = '.'
  5752  						prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  5753  					}
  5754  					prg.showNodeList(*prg.mem[p+1].int())
  5755  					prg.poolPtr = uint16(int32(prg.poolPtr) - 1)
  5756  				} // recursive call
  5757  
  5758  			// \4
  5759  			// Cases of |show_node_list| that arise in mlists only
  5760  			case styleNode:
  5761  				prg.printStyle(int32(*(*prg.mem[p].hh()).b1()))
  5762  			case choiceNode:
  5763  				// Display choice node |p|
  5764  				prg.printEsc(strNumber( /* "mathchoice" */ 525))
  5765  				{
  5766  					prg.strPool[prg.poolPtr] = 'D'
  5767  					prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  5768  				}
  5769  				prg.showNodeList(int32(*(*prg.mem[p+1].hh()).lh()))
  5770  				prg.poolPtr = uint16(int32(prg.poolPtr) - 1)
  5771  				{
  5772  					prg.strPool[prg.poolPtr] = 'T'
  5773  					prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  5774  				}
  5775  				prg.showNodeList(int32(*(*prg.mem[p+1].hh()).rh()))
  5776  				prg.poolPtr = uint16(int32(prg.poolPtr) - 1)
  5777  				{
  5778  					prg.strPool[prg.poolPtr] = 'S'
  5779  					prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  5780  				}
  5781  				prg.showNodeList(int32(*(*prg.mem[p+2].hh()).lh()))
  5782  				prg.poolPtr = uint16(int32(prg.poolPtr) - 1)
  5783  				{
  5784  					prg.strPool[prg.poolPtr] = 's'
  5785  					prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  5786  				}
  5787  				prg.showNodeList(int32(*(*prg.mem[p+2].hh()).rh()))
  5788  				prg.poolPtr = uint16(int32(prg.poolPtr) - 1)
  5789  
  5790  			case ordNoad, opNoad, binNoad, relNoad,
  5791  				openNoad, closeNoad, punctNoad, innerNoad,
  5792  				radicalNoad, overNoad, underNoad, vcenterNoad,
  5793  				accentNoad, leftNoad, rightNoad:
  5794  				// Display normal noad |p|
  5795  				switch *(*prg.mem[p].hh()).b0() {
  5796  				case ordNoad:
  5797  					prg.printEsc(strNumber( /* "mathord" */ 866))
  5798  				case opNoad:
  5799  					prg.printEsc(strNumber( /* "mathop" */ 867))
  5800  				case binNoad:
  5801  					prg.printEsc(strNumber( /* "mathbin" */ 868))
  5802  				case relNoad:
  5803  					prg.printEsc(strNumber( /* "mathrel" */ 869))
  5804  				case openNoad:
  5805  					prg.printEsc(strNumber( /* "mathopen" */ 870))
  5806  				case closeNoad:
  5807  					prg.printEsc(strNumber( /* "mathclose" */ 871))
  5808  				case punctNoad:
  5809  					prg.printEsc(strNumber( /* "mathpunct" */ 872))
  5810  				case innerNoad:
  5811  					prg.printEsc(strNumber( /* "mathinner" */ 873))
  5812  				case overNoad:
  5813  					prg.printEsc(strNumber( /* "overline" */ 874))
  5814  				case underNoad:
  5815  					prg.printEsc(strNumber( /* "underline" */ 875))
  5816  				case vcenterNoad:
  5817  					prg.printEsc(strNumber( /* "vcenter" */ 539))
  5818  				case radicalNoad:
  5819  					prg.printEsc(strNumber( /* "radical" */ 533))
  5820  					prg.printDelimiter(halfword(p + 4))
  5821  
  5822  				case accentNoad:
  5823  					prg.printEsc(strNumber( /* "accent" */ 508))
  5824  					prg.printFamAndChar(halfword(p + 4))
  5825  
  5826  				case leftNoad:
  5827  					prg.printEsc(strNumber( /* "left" */ 876))
  5828  					prg.printDelimiter(halfword(p + 1))
  5829  
  5830  				case rightNoad:
  5831  					prg.printEsc(strNumber( /* "right" */ 877))
  5832  					prg.printDelimiter(halfword(p + 1))
  5833  
  5834  				}
  5835  				if int32(*(*prg.mem[p].hh()).b1()) != normal {
  5836  					if int32(*(*prg.mem[p].hh()).b1()) == limits {
  5837  						prg.printEsc(strNumber( /* "limits" */ 878))
  5838  					} else {
  5839  						prg.printEsc(strNumber( /* "nolimits" */ 879))
  5840  					}
  5841  				}
  5842  				if int32(*(*prg.mem[p].hh()).b0()) < leftNoad {
  5843  					prg.printSubsidiaryData(halfword(p+1), asciiCode('.'))
  5844  				}
  5845  				prg.printSubsidiaryData(halfword(p+2), asciiCode('^'))
  5846  				prg.printSubsidiaryData(halfword(p+3), asciiCode('_'))
  5847  
  5848  			case fractionNoad:
  5849  				// Display fraction noad |p|
  5850  				prg.printEsc(strNumber( /* "fraction, thickness " */ 880))
  5851  				if *prg.mem[p+widthOffset].int() == 010000000000 {
  5852  					prg.print( /* "= default" */ 881)
  5853  				} else {
  5854  					prg.printScaled(*prg.mem[p+widthOffset].int())
  5855  				}
  5856  				if int32((*prg.mem[p+4].qqqq()).b0) != 0 || int32((*prg.mem[p+4].qqqq()).b1) != minQuarterword || int32((*prg.mem[p+4].qqqq()).b2) != 0 || int32((*prg.mem[p+4].qqqq()).b3) != minQuarterword {
  5857  					prg.print( /* ", left-delimiter " */ 882)
  5858  					prg.printDelimiter(halfword(p + 4))
  5859  				}
  5860  				if int32((*prg.mem[p+5].qqqq()).b0) != 0 || int32((*prg.mem[p+5].qqqq()).b1) != minQuarterword || int32((*prg.mem[p+5].qqqq()).b2) != 0 || int32((*prg.mem[p+5].qqqq()).b3) != minQuarterword {
  5861  					prg.print( /* ", right-delimiter " */ 883)
  5862  					prg.printDelimiter(halfword(p + 5))
  5863  				}
  5864  				prg.printSubsidiaryData(halfword(p+2), asciiCode('\\'))
  5865  				prg.printSubsidiaryData(halfword(p+3), asciiCode('/'))
  5866  
  5867  			default:
  5868  				prg.print( /* "Unknown node type!" */ 317)
  5869  			}
  5870  		}
  5871  		p = int32(*(*prg.mem[p].hh()).rh())
  5872  	}
  5873  
  5874  exit:
  5875  }
  5876  
  5877  // 198.
  5878  
  5879  // tangle:pos tex.web:3872:3:
  5880  
  5881  // The recursive machinery is started by calling |show_box|.
  5882  // \xref[recursion]
  5883  func (prg *prg) showBox(p halfword) {
  5884  	prg.depthThreshold = *prg.eqtb[intBase+showBoxDepthCode-1].int()
  5885  	prg.breadthMax = *prg.eqtb[intBase+showBoxBreadthCode-1].int()
  5886  	if prg.breadthMax <= 0 {
  5887  		prg.breadthMax = 5
  5888  	}
  5889  	if int32(prg.poolPtr)+prg.depthThreshold >= poolSize {
  5890  		prg.depthThreshold = poolSize - int32(prg.poolPtr) - 1
  5891  	}
  5892  	// now there's enough room for prefix string
  5893  	prg.showNodeList(int32(p)) // the show starts at |p|
  5894  	prg.printLn()
  5895  }
  5896  
  5897  // 199. \[13] Destroying boxes
  5898  
  5899  // tangle:pos tex.web:3886:27:
  5900  
  5901  // When we are done with a node list, we are obliged to return it to free
  5902  // storage, including all of its sublists. The recursive procedure
  5903  // |flush_node_list| does this for us.
  5904  
  5905  // 200.
  5906  
  5907  // tangle:pos tex.web:3891:3:
  5908  
  5909  // First, however, we shall consider two non-recursive procedures that do
  5910  // simpler tasks. The first of these, |delete_token_ref|, is called when
  5911  // a pointer to a token list's reference count is being removed. This means
  5912  // that the token list should disappear if the reference count was |null|,
  5913  // otherwise the count should be decreased by one.
  5914  // \xref[reference counts]
  5915  func (prg *prg) deleteTokenRef(p halfword) {
  5916  	if int32(*(*prg.mem[p].hh()).lh()) == 0 {
  5917  		prg.flushList(p)
  5918  	} else {
  5919  		*(*prg.mem[p].hh()).lh() = uint16(int32(*(*prg.mem[p].hh()).lh()) - 1)
  5920  	}
  5921  }
  5922  
  5923  // 201.
  5924  
  5925  // tangle:pos tex.web:3906:3:
  5926  
  5927  // Similarly, |delete_glue_ref| is called when a pointer to a glue
  5928  // specification is being withdrawn.
  5929  // \xref[reference counts]
  5930  func (prg *prg) deleteGlueRef(p halfword) {
  5931  	if int32(*(*prg.mem[p].hh()).rh()) == 0 {
  5932  		prg.freeNode(p, halfword(glueSpecSize))
  5933  	} else {
  5934  		*(*prg.mem[p].hh()).rh() = uint16(int32(*(*prg.mem[p].hh()).rh()) - 1)
  5935  	}
  5936  }
  5937  
  5938  // 202.
  5939  
  5940  // tangle:pos tex.web:3917:3:
  5941  
  5942  // Now we are ready to delete any node list, recursively.
  5943  // In practice, the nodes deleted are usually charnodes (about 2/3 of the time),
  5944  // and they are glue nodes in about half of the remaining cases.
  5945  // \xref[recursion]
  5946  func (prg *prg) flushNodeList(p halfword) { // go here when node |p| has been freed
  5947  	var (
  5948  		q halfword // successor to node |p|
  5949  	)
  5950  	for int32(p) != 0 {
  5951  		// \xref[inner loop]
  5952  		q = *(*prg.mem[p].hh()).rh()
  5953  		if int32(p) >= int32(prg.hiMemMin) {
  5954  			*(*prg.mem[p].hh()).rh() = prg.avail
  5955  			prg.avail = p /*    dyn_used:= dyn_used-1 ; [  ] */
  5956  		} else {
  5957  			switch *(*prg.mem[p].hh()).b0() {
  5958  			case hlistNode, vlistNode, unsetNode:
  5959  				prg.flushNodeList(*(*prg.mem[int32(p)+listOffset].hh()).rh())
  5960  				prg.freeNode(p, halfword(boxNodeSize))
  5961  				goto done
  5962  
  5963  			case ruleNode:
  5964  				prg.freeNode(p, halfword(ruleNodeSize))
  5965  				goto done
  5966  
  5967  			case insNode:
  5968  				prg.flushNodeList(*(*prg.mem[int32(p)+4].hh()).lh())
  5969  				prg.deleteGlueRef(*(*prg.mem[int32(p)+4].hh()).rh())
  5970  				prg.freeNode(p, halfword(insNodeSize))
  5971  				goto done
  5972  
  5973  			case whatsitNode:
  5974  				// Wipe out the whatsit node |p| and |goto done|
  5975  				switch *(*prg.mem[p].hh()).b1() {
  5976  				case openNode:
  5977  					prg.freeNode(p, halfword(openNodeSize))
  5978  				case writeNode, specialNode:
  5979  					prg.deleteTokenRef(*(*prg.mem[int32(p)+1].hh()).rh())
  5980  					prg.freeNode(p, halfword(writeNodeSize))
  5981  					goto done
  5982  
  5983  				case closeNode, languageNode:
  5984  					prg.freeNode(p, halfword(smallNodeSize))
  5985  
  5986  				default:
  5987  					prg.confusion(strNumber( /* "ext3" */ 1295))
  5988  					// \xref[this can't happen ext3][\quad ext3]
  5989  				}
  5990  
  5991  				goto done
  5992  
  5993  			case glueNode:
  5994  				{
  5995  					if int32(*(*prg.mem[*(*prg.mem[int32(p)+1].hh()).lh()].hh()).rh()) == 0 {
  5996  						prg.freeNode(*(*prg.mem[int32(p)+1].hh()).lh(), halfword(glueSpecSize))
  5997  					} else {
  5998  						*(*prg.mem[*(*prg.mem[int32(p)+1].hh()).lh()].hh()).rh() = uint16(int32(*(*prg.mem[*(*prg.mem[int32(p)+1].hh()).lh()].hh()).rh()) - 1)
  5999  					}
  6000  				}
  6001  				if int32(*(*prg.mem[int32(p)+1].hh()).rh()) != 0 {
  6002  					prg.flushNodeList(*(*prg.mem[int32(p)+1].hh()).rh())
  6003  				}
  6004  
  6005  			case kernNode, mathNode, penaltyNode:
  6006  			case ligatureNode:
  6007  				prg.flushNodeList(*(*prg.mem[int32(p)+1].hh()).rh())
  6008  			case markNode:
  6009  				prg.deleteTokenRef(halfword(*prg.mem[int32(p)+1].int()))
  6010  			case discNode:
  6011  				prg.flushNodeList(*(*prg.mem[int32(p)+1].hh()).lh())
  6012  				prg.flushNodeList(*(*prg.mem[int32(p)+1].hh()).rh())
  6013  
  6014  			case adjustNode:
  6015  				prg.flushNodeList(halfword(*prg.mem[int32(p)+1].int()))
  6016  			// \4
  6017  			// Cases of |flush_node_list| that arise in mlists only
  6018  			case styleNode:
  6019  				prg.freeNode(p, halfword(styleNodeSize))
  6020  				goto done
  6021  
  6022  			case choiceNode:
  6023  				prg.flushNodeList(*(*prg.mem[int32(p)+1].hh()).lh())
  6024  				prg.flushNodeList(*(*prg.mem[int32(p)+1].hh()).rh())
  6025  				prg.flushNodeList(*(*prg.mem[int32(p)+2].hh()).lh())
  6026  				prg.flushNodeList(*(*prg.mem[int32(p)+2].hh()).rh())
  6027  				prg.freeNode(p, halfword(styleNodeSize))
  6028  				goto done
  6029  
  6030  			case ordNoad, opNoad, binNoad, relNoad,
  6031  				openNoad, closeNoad, punctNoad, innerNoad,
  6032  				radicalNoad, overNoad, underNoad, vcenterNoad,
  6033  				accentNoad: //
  6034  
  6035  				if int32(*(*prg.mem[int32(p)+1].hh()).rh()) >= subBox {
  6036  					prg.flushNodeList(*(*prg.mem[int32(p)+1].hh()).lh())
  6037  				}
  6038  				if int32(*(*prg.mem[int32(p)+2].hh()).rh()) >= subBox {
  6039  					prg.flushNodeList(*(*prg.mem[int32(p)+2].hh()).lh())
  6040  				}
  6041  				if int32(*(*prg.mem[int32(p)+3].hh()).rh()) >= subBox {
  6042  					prg.flushNodeList(*(*prg.mem[int32(p)+3].hh()).lh())
  6043  				}
  6044  				if int32(*(*prg.mem[p].hh()).b0()) == radicalNoad {
  6045  					prg.freeNode(p, halfword(radicalNoadSize))
  6046  				} else if int32(*(*prg.mem[p].hh()).b0()) == accentNoad {
  6047  					prg.freeNode(p, halfword(accentNoadSize))
  6048  				} else {
  6049  					prg.freeNode(p, halfword(noadSize))
  6050  				}
  6051  
  6052  				goto done
  6053  
  6054  			case leftNoad, rightNoad:
  6055  				prg.freeNode(p, halfword(noadSize))
  6056  				goto done
  6057  
  6058  			case fractionNoad:
  6059  				prg.flushNodeList(*(*prg.mem[int32(p)+2].hh()).lh())
  6060  				prg.flushNodeList(*(*prg.mem[int32(p)+3].hh()).lh())
  6061  				prg.freeNode(p, halfword(fractionNoadSize))
  6062  				goto done
  6063  
  6064  			default:
  6065  				prg.confusion(strNumber( /* "flushing" */ 353))
  6066  				// \xref[this can't happen flushing][\quad flushing]
  6067  			}
  6068  
  6069  			prg.freeNode(p, halfword(smallNodeSize))
  6070  
  6071  		done:
  6072  		}
  6073  		p = q
  6074  	}
  6075  }
  6076  
  6077  // 203. \[14] Copying boxes
  6078  
  6079  // tangle:pos tex.web:3960:24:
  6080  
  6081  // Another recursive operation that acts on boxes is sometimes needed: The
  6082  // procedure |copy_node_list| returns a pointer to another node list that has
  6083  // the same structure and meaning as the original. Note that since glue
  6084  // specifications and token lists have reference counts, we need not make
  6085  // copies of them. Reference counts can never get too large to fit in a
  6086  // halfword, since each pointer to a node is in a different memory address,
  6087  // and the total number of memory addresses fits in a halfword.
  6088  // \xref[recursion]
  6089  // \xref[reference counts]
  6090  //
  6091  // (Well, there actually are also references from outside |mem|; if the
  6092  // |save_stack| is made arbitrarily large, it would theoretically be possible
  6093  // to break \TeX\ by overflowing a reference count. But who would want to do that?)
  6094  
  6095  // 204.
  6096  
  6097  // tangle:pos tex.web:3978:3:
  6098  
  6099  // The copying procedure copies words en masse without bothering
  6100  // to look at their individual fields. If the node format changes---for
  6101  // example, if the size is altered, or if some link field is moved to another
  6102  // relative position---then this code may need to be changed too.
  6103  // \xref[data structure assumptions]
  6104  func (prg *prg) copyNodeList(p halfword) (r halfword) { // makes a duplicate of the
  6105  	//   node list that starts at |p| and returns a pointer to the new list
  6106  
  6107  	var (
  6108  		h                    halfword // temporary head of copied list
  6109  		q                    halfword // previous position in new list
  6110  		r1                   halfword // current node being fabricated for new list
  6111  		words/* 0..5 */ byte          // number of words remaining to be copied
  6112  	)
  6113  	h = prg.getAvail()
  6114  	q = h
  6115  	for int32(p) != 0 {
  6116  		words = 1 // this setting occurs in more branches than any other
  6117  		if int32(p) >= int32(prg.hiMemMin) {
  6118  			r1 = prg.getAvail()
  6119  		} else {
  6120  			// Case statement to copy different types and set |words| to the number of initial words not yet copied
  6121  			switch *(*prg.mem[p].hh()).b0() {
  6122  			case hlistNode, vlistNode, unsetNode:
  6123  				r1 = prg.getNode(boxNodeSize)
  6124  				prg.mem[int32(r1)+6] = prg.mem[int32(p)+6]
  6125  				prg.mem[int32(r1)+5] = prg.mem[int32(p)+5]                                                                 // copy the last two words
  6126  				*(*prg.mem[int32(r1)+listOffset].hh()).rh() = prg.copyNodeList(*(*prg.mem[int32(p)+listOffset].hh()).rh()) // this affects |mem[r+5]|
  6127  				words = 5
  6128  
  6129  			case ruleNode:
  6130  				r1 = prg.getNode(ruleNodeSize)
  6131  				words = byte(ruleNodeSize)
  6132  
  6133  			case insNode:
  6134  				r1 = prg.getNode(insNodeSize)
  6135  				prg.mem[int32(r1)+4] = prg.mem[int32(p)+4]
  6136  				*(*prg.mem[*(*prg.mem[int32(p)+4].hh()).rh()].hh()).rh() = uint16(int32(*(*prg.mem[*(*prg.mem[int32(p)+4].hh()).rh()].hh()).rh()) + 1)
  6137  				*(*prg.mem[int32(r1)+4].hh()).lh() = prg.copyNodeList(*(*prg.mem[int32(p)+4].hh()).lh()) // this affects |mem[r+4]|
  6138  				words = byte(insNodeSize - 1)
  6139  
  6140  			case whatsitNode:
  6141  				// Make a partial copy of the whatsit node |p| and make |r| point to it; set |words| to the number of initial words not yet copied
  6142  				switch *(*prg.mem[p].hh()).b1() {
  6143  				case openNode:
  6144  					r1 = prg.getNode(openNodeSize)
  6145  					words = byte(openNodeSize)
  6146  
  6147  				case writeNode, specialNode:
  6148  					r1 = prg.getNode(writeNodeSize)
  6149  					*(*prg.mem[*(*prg.mem[int32(p)+1].hh()).rh()].hh()).lh() = uint16(int32(*(*prg.mem[*(*prg.mem[int32(p)+1].hh()).rh()].hh()).lh()) + 1)
  6150  					words = byte(writeNodeSize)
  6151  
  6152  				case closeNode, languageNode:
  6153  					r1 = prg.getNode(smallNodeSize)
  6154  					words = byte(smallNodeSize)
  6155  
  6156  				default:
  6157  					prg.confusion(strNumber( /* "ext2" */ 1294))
  6158  					// \xref[this can't happen ext2][\quad ext2]
  6159  				}
  6160  
  6161  			case glueNode:
  6162  				r1 = prg.getNode(smallNodeSize)
  6163  				*(*prg.mem[*(*prg.mem[int32(p)+1].hh()).lh()].hh()).rh() = uint16(int32(*(*prg.mem[*(*prg.mem[int32(p)+1].hh()).lh()].hh()).rh()) + 1)
  6164  				*(*prg.mem[int32(r1)+1].hh()).lh() = *(*prg.mem[int32(p)+1].hh()).lh()
  6165  				*(*prg.mem[int32(r1)+1].hh()).rh() = prg.copyNodeList(*(*prg.mem[int32(p)+1].hh()).rh())
  6166  
  6167  			case kernNode, mathNode, penaltyNode:
  6168  				r1 = prg.getNode(smallNodeSize)
  6169  				words = byte(smallNodeSize)
  6170  
  6171  			case ligatureNode:
  6172  				r1 = prg.getNode(smallNodeSize)
  6173  				prg.mem[int32(r1)+1] = prg.mem[int32(p)+1] // copy |font| and |character|
  6174  				*(*prg.mem[int32(r1)+1].hh()).rh() = prg.copyNodeList(*(*prg.mem[int32(p)+1].hh()).rh())
  6175  
  6176  			case discNode:
  6177  				r1 = prg.getNode(smallNodeSize)
  6178  				*(*prg.mem[int32(r1)+1].hh()).lh() = prg.copyNodeList(*(*prg.mem[int32(p)+1].hh()).lh())
  6179  				*(*prg.mem[int32(r1)+1].hh()).rh() = prg.copyNodeList(*(*prg.mem[int32(p)+1].hh()).rh())
  6180  
  6181  			case markNode:
  6182  				r1 = prg.getNode(smallNodeSize)
  6183  				*(*prg.mem[*prg.mem[int32(p)+1].int()].hh()).lh() = uint16(int32(*(*prg.mem[*prg.mem[int32(p)+1].int()].hh()).lh()) + 1)
  6184  				words = byte(smallNodeSize)
  6185  
  6186  			case adjustNode:
  6187  				r1 = prg.getNode(smallNodeSize)
  6188  				*prg.mem[int32(r1)+1].int() = int32(prg.copyNodeList(halfword(*prg.mem[int32(p)+1].int())))
  6189  
  6190  				// |words=1=small_node_size-1|
  6191  			default:
  6192  				prg.confusion(strNumber( /* "copying" */ 354))
  6193  				// \xref[this can't happen copying][\quad copying]
  6194  			}
  6195  		}
  6196  		for int32(words) > 0 {
  6197  			words = byte(int32(words) - 1)
  6198  			prg.mem[int32(r1)+int32(words)] = prg.mem[int32(p)+int32(words)]
  6199  		}
  6200  		*(*prg.mem[q].hh()).rh() = r1
  6201  		q = r1
  6202  		p = *(*prg.mem[p].hh()).rh()
  6203  	}
  6204  	*(*prg.mem[q].hh()).rh() = 0
  6205  	q = *(*prg.mem[h].hh()).rh()
  6206  	{
  6207  		*(*prg.mem[h].hh()).rh() = prg.avail
  6208  		prg.avail = h /*    dyn_used:= dyn_used-1 ; [  ] */
  6209  	}
  6210  	r = q
  6211  	return r
  6212  }
  6213  
  6214  // 207. \[15] The command codes
  6215  
  6216  // tangle:pos tex.web:4048:28:
  6217  
  6218  // Before we can go any further, we need to define symbolic names for the internal
  6219  // code numbers that represent the various commands obeyed by \TeX. These codes
  6220  // are somewhat arbitrary, but not completely so. For example, the command
  6221  // codes for character types are fixed by the language, since a user says,
  6222  // e.g., `\.[\\catcode \`\\\$[] = 3]' to make \.[\char'44] a math delimiter,
  6223  // and the command code |math_shift| is equal to~3. Some other codes have
  6224  // been made adjacent so that |case| statements in the program need not consider
  6225  // cases that are widely spaced, or so that |case| statements can be replaced
  6226  // by |if| statements.
  6227  //
  6228  // At any rate, here is the list, for future reference. First come the
  6229  // ``catcode'' commands, several of which share their numeric codes with
  6230  // ordinary commands when the catcode cannot emerge from \TeX's scanning routine.
  6231  
  6232  // 208.
  6233  
  6234  // tangle:pos tex.web:4090:3:
  6235  
  6236  // Next are the ordinary run-of-the-mill command codes.  Codes that are
  6237  // |min_internal| or more represent internal quantities that might be
  6238  // expanded by `\.[\\the]'.
  6239  
  6240  // 209.
  6241  
  6242  // tangle:pos tex.web:4154:3:
  6243  
  6244  // The next codes are special; they all relate to mode-independent
  6245  // assignment of values to \TeX's internal registers or tables.
  6246  // Codes that are |max_internal| or less represent internal quantities
  6247  // that might be expanded by `\.[\\the]'.
  6248  
  6249  // 210.
  6250  
  6251  // tangle:pos tex.web:4194:3:
  6252  
  6253  // The remaining command codes are extra special, since they cannot get through
  6254  // \TeX's scanner to the main control routine. They have been given values higher
  6255  // than |max_command| so that their special nature is easily discernible.
  6256  // The ``expandable'' commands come first.
  6257  
  6258  // 211. \[16] The semantic nest
  6259  
  6260  // tangle:pos tex.web:4220:28:
  6261  
  6262  // \TeX\ is typically in the midst of building many lists at once. For example,
  6263  // when a math formula is being processed, \TeX\ is in math mode and
  6264  // working on an mlist; this formula has temporarily interrupted \TeX\ from
  6265  // being in horizontal mode and building the hlist of a paragraph; and this
  6266  // paragraph has temporarily interrupted \TeX\ from being in vertical mode
  6267  // and building the vlist for the next page of a document. Similarly, when a
  6268  // \.[\\vbox] occurs inside of an \.[\\hbox], \TeX\ is temporarily
  6269  // interrupted from working in restricted horizontal mode, and it enters
  6270  // internal vertical mode.  The ``semantic nest'' is a stack that
  6271  // keeps track of what lists and modes are currently suspended.
  6272  //
  6273  // At each level of processing we are in one of six modes:
  6274  //
  6275  // \yskip\hang|vmode| stands for vertical mode (the page builder);
  6276  //
  6277  // \hang|hmode| stands for horizontal mode (the paragraph builder);
  6278  //
  6279  // \hang|mmode| stands for displayed formula mode;
  6280  //
  6281  // \hang|-vmode| stands for internal vertical mode (e.g., in a \.[\\vbox]);
  6282  //
  6283  // \hang|-hmode| stands for restricted horizontal mode (e.g., in an \.[\\hbox]);
  6284  //
  6285  // \hang|-mmode| stands for math formula mode (not displayed).
  6286  //
  6287  // \yskip\noindent The mode is temporarily set to zero while processing \.[\\write]
  6288  // texts.
  6289  //
  6290  // Numeric values are assigned to |vmode|, |hmode|, and |mmode| so that
  6291  // \TeX's ``big semantic switch'' can select the appropriate thing to
  6292  // do by computing the value |abs(mode)+cur_cmd|, where |mode| is the current
  6293  // mode and |cur_cmd| is the current command code.
  6294  func (prg *prg) printMode(m int32) {
  6295  	if m > 0 {
  6296  		switch m / (maxCommand + 1) {
  6297  		case 0:
  6298  			prg.print( /* "vertical" */ 355)
  6299  		case 1:
  6300  			prg.print( /* "horizontal" */ 356)
  6301  		case 2:
  6302  			prg.print( /* "display math" */ 357)
  6303  		}
  6304  	} else if m == 0 {
  6305  		prg.print( /* "no" */ 358)
  6306  	} else {
  6307  		switch -m / (maxCommand + 1) {
  6308  		case 0:
  6309  			prg.print( /* "internal vertical" */ 359)
  6310  		case 1:
  6311  			prg.print( /* "restricted horizontal" */ 360)
  6312  		case 2:
  6313  			prg.print( /* "math" */ 343)
  6314  		}
  6315  	}
  6316  	prg.print( /* " mode" */ 361)
  6317  }
  6318  
  6319  // 214.
  6320  
  6321  // tangle:pos tex.web:4348:3:
  6322  
  6323  // Here is a common way to make the current list grow:
  6324  
  6325  // 216.
  6326  
  6327  // tangle:pos tex.web:4368:3:
  6328  
  6329  // When \TeX's work on one level is interrupted, the state is saved by
  6330  // calling |push_nest|. This routine changes |head| and |tail| so that
  6331  // a new (empty) list is begun; it does not change |mode| or |aux|.
  6332  func (prg *prg) pushNest() {
  6333  	if int32(prg.nestPtr) > int32(prg.maxNestStack) {
  6334  		prg.maxNestStack = prg.nestPtr
  6335  		if int32(prg.nestPtr) == nestSize {
  6336  			prg.overflow(strNumber( /* "semantic nest size" */ 362), nestSize)
  6337  		}
  6338  		// \xref[TeX capacity exceeded semantic nest size][\quad semantic nest size]
  6339  	}
  6340  	prg.nest[prg.nestPtr] = prg.curList // stack the record
  6341  	prg.nestPtr = byte(int32(prg.nestPtr) + 1)
  6342  	prg.curList.headField = prg.getAvail()
  6343  	prg.curList.tailField = prg.curList.headField
  6344  	prg.curList.pgField = 0
  6345  	prg.curList.mlField = prg.line
  6346  }
  6347  
  6348  // 217.
  6349  
  6350  // tangle:pos tex.web:4382:3:
  6351  
  6352  // Conversely, when \TeX\ is finished on the current level, the former
  6353  // state is restored by calling |pop_nest|. This routine will never be
  6354  // called at the lowest semantic level, nor will it be called unless |head|
  6355  // is a node that should be returned to free memory.
  6356  func (prg *prg) popNest() {
  6357  	{
  6358  		*(*prg.mem[prg.curList.headField].hh()).rh() = prg.avail
  6359  		prg.avail = prg.curList.headField /*    dyn_used:= dyn_used-1 ; [  ] */
  6360  	}
  6361  	prg.nestPtr = byte(int32(prg.nestPtr) - 1)
  6362  	prg.curList = prg.nest[prg.nestPtr]
  6363  } // \2
  6364  func (prg *prg) showActivities() {
  6365  	var (
  6366  		p/* 0..nestSize */ byte                // index into |nest|
  6367  		m/*  -mmode..mmode */ int16            // mode
  6368  		a                           memoryWord // auxiliary
  6369  		q, r1                       halfword   // for showing the current page
  6370  		t                           int32      // ditto
  6371  	)
  6372  	prg.nest[prg.nestPtr] = prg.curList // put the top level into the array
  6373  	prg.printNl(strNumber( /* "" */ 338))
  6374  	prg.printLn()
  6375  	for ii := int32(prg.nestPtr); ii >= 0; ii-- {
  6376  		p = byte(ii)
  6377  		_ = p
  6378  		m = prg.nest[p].modeField
  6379  		a = prg.nest[p].auxField
  6380  		prg.printNl(strNumber( /* "### " */ 363))
  6381  		prg.printMode(int32(m))
  6382  		prg.print( /* " entered at line " */ 364)
  6383  		prg.printInt(abs(prg.nest[p].mlField))
  6384  		if int32(m) == hmode {
  6385  			if prg.nest[p].pgField != 040600000 {
  6386  				prg.print( /* " (language" */ 365)
  6387  				prg.printInt(prg.nest[p].pgField % 0200000)
  6388  				prg.print( /* ":hyphenmin" */ 366)
  6389  				prg.printInt(prg.nest[p].pgField / 020000000)
  6390  				prg.printChar(asciiCode(','))
  6391  				prg.printInt(prg.nest[p].pgField / 0200000 % 0100)
  6392  				prg.printChar(asciiCode(')'))
  6393  			}
  6394  		}
  6395  		if prg.nest[p].mlField < 0 {
  6396  			prg.print( /* " (\\output routine)" */ 367)
  6397  		}
  6398  		if int32(p) == 0 {
  6399  			if 30000-2 != int32(prg.pageTail) {
  6400  				prg.printNl(strNumber( /* "### current page:" */ 980))
  6401  				if prg.outputActive {
  6402  					prg.print( /* " (held over for next output)" */ 981)
  6403  				}
  6404  				// \xref[held over for next output]
  6405  				prg.showBox(*(*prg.mem[30000-2].hh()).rh())
  6406  				if int32(prg.pageContents) > empty {
  6407  					prg.printNl(strNumber( /* "total height " */ 982))
  6408  					prg.printTotals()
  6409  					// \xref[total_height][\.[total height]]
  6410  					prg.printNl(strNumber( /* " goal height " */ 983))
  6411  					prg.printScaled(prg.pageSoFar[0])
  6412  					// \xref[goal height]
  6413  					r1 = *(*prg.mem[30000].hh()).rh()
  6414  					for int32(r1) != 30000 {
  6415  						prg.printLn()
  6416  						prg.printEsc(strNumber( /* "insert" */ 330))
  6417  						t = int32(*(*prg.mem[r1].hh()).b1()) - minQuarterword
  6418  						prg.printInt(t)
  6419  						prg.print( /* " adds " */ 984)
  6420  						if *prg.eqtb[countBase+t-1].int() == 1000 {
  6421  							t = *prg.mem[int32(r1)+heightOffset].int()
  6422  						} else {
  6423  							t = prg.xOverN(*prg.mem[int32(r1)+heightOffset].int(), 1000) * *prg.eqtb[countBase+t-1].int()
  6424  						}
  6425  						prg.printScaled(t)
  6426  						if int32(*(*prg.mem[r1].hh()).b0()) == splitUp {
  6427  							q = uint16(30000 - 2)
  6428  							t = 0
  6429  							for {
  6430  								q = *(*prg.mem[q].hh()).rh()
  6431  								if int32(*(*prg.mem[q].hh()).b0()) == insNode && int32(*(*prg.mem[q].hh()).b1()) == int32(*(*prg.mem[r1].hh()).b1()) {
  6432  									t = t + 1
  6433  								}
  6434  								if int32(q) == int32(*(*prg.mem[int32(r1)+1].hh()).lh()) {
  6435  									break
  6436  								}
  6437  							}
  6438  							prg.print( /* ", #" */ 985)
  6439  							prg.printInt(t)
  6440  							prg.print( /* " might split" */ 986)
  6441  						}
  6442  						r1 = *(*prg.mem[r1].hh()).rh()
  6443  					}
  6444  				}
  6445  			}
  6446  			if int32(*(*prg.mem[30000-1].hh()).rh()) != 0 {
  6447  				prg.printNl(strNumber( /* "### recent contributions:" */ 368))
  6448  			}
  6449  		}
  6450  		prg.showBox(*(*prg.mem[prg.nest[p].headField].hh()).rh())
  6451  
  6452  		// Show the auxiliary field, |a|
  6453  		switch abs(int32(m)) / (maxCommand + 1) {
  6454  		case 0:
  6455  			prg.printNl(strNumber( /* "prevdepth " */ 369))
  6456  			if *a.int() <= -65536000 {
  6457  				prg.print( /* "ignored" */ 370)
  6458  			} else {
  6459  				prg.printScaled(*a.int())
  6460  			}
  6461  			if prg.nest[p].pgField != 0 {
  6462  				prg.print( /* ", prevgraf " */ 371)
  6463  				prg.printInt(prg.nest[p].pgField)
  6464  				prg.print( /* " line" */ 372)
  6465  				if prg.nest[p].pgField != 1 {
  6466  					prg.printChar(asciiCode('s'))
  6467  				}
  6468  			}
  6469  
  6470  		case 1:
  6471  			prg.printNl(strNumber( /* "spacefactor " */ 373))
  6472  			prg.printInt(int32(*(*a.hh()).lh()))
  6473  			if int32(m) > 0 {
  6474  				if int32(*(*a.hh()).rh()) > 0 {
  6475  					prg.print( /* ", current language " */ 374)
  6476  					prg.printInt(int32(*(*a.hh()).rh()))
  6477  				}
  6478  			}
  6479  
  6480  		case 2:
  6481  			if *a.int() != 0 {
  6482  				prg.print( /* "this will begin denominator of:" */ 375)
  6483  				prg.showBox(halfword(*a.int()))
  6484  			}
  6485  		}
  6486  	}
  6487  }
  6488  
  6489  // 220. \[17] The table of equivalents
  6490  
  6491  // tangle:pos tex.web:4444:35:
  6492  
  6493  // Now that we have studied the data structures for \TeX's semantic routines,
  6494  // we ought to consider the data structures used by its syntactic routines. In
  6495  // other words, our next concern will be
  6496  // the tables that \TeX\ looks at when it is scanning
  6497  // what the user has written.
  6498  //
  6499  // The biggest and most important such table is called |eqtb|. It holds the
  6500  // current ``equivalents'' of things; i.e., it explains what things mean
  6501  // or what their current values are, for all quantities that are subject to
  6502  // the nesting structure provided by \TeX's grouping mechanism. There are six
  6503  // parts to |eqtb|:
  6504  //
  6505  // \yskip\hangg 1) |eqtb[active_base..(hash_base-1)]| holds the current
  6506  // equivalents of single-character control sequences.
  6507  //
  6508  // \yskip\hangg 2) |eqtb[hash_base..(glue_base-1)]| holds the current
  6509  // equivalents of multiletter control sequences.
  6510  //
  6511  // \yskip\hangg 3) |eqtb[glue_base..(local_base-1)]| holds the current
  6512  // equivalents of glue parameters like the current baselineskip.
  6513  //
  6514  // \yskip\hangg 4) |eqtb[local_base..(int_base-1)]| holds the current
  6515  // equivalents of local halfword quantities like the current box registers,
  6516  // the current ``catcodes,'' the current font, and a pointer to the current
  6517  // paragraph shape.
  6518  //
  6519  // \yskip\hangg 5) |eqtb[int_base..(dimen_base-1)]| holds the current
  6520  // equivalents of fullword integer parameters like the current hyphenation
  6521  // penalty.
  6522  //
  6523  // \yskip\hangg 6) |eqtb[dimen_base..eqtb_size]| holds the current equivalents
  6524  // of fullword dimension parameters like the current hsize or amount of
  6525  // hanging indentation.
  6526  //
  6527  // \yskip\noindent Note that, for example, the current amount of
  6528  // baselineskip glue is determined by the setting of a particular location
  6529  // in region~3 of |eqtb|, while the current meaning of the control sequence
  6530  // `\.[\\baselineskip]' (which might have been changed by \.[\\def] or
  6531  // \.[\\let]) appears in region~2.
  6532  
  6533  // 221.
  6534  
  6535  // tangle:pos tex.web:4485:3:
  6536  
  6537  // Each entry in |eqtb| is a |memory_word|. Most of these words are of type
  6538  // |two_halves|, and subdivided into three fields:
  6539  //
  6540  // \yskip\hangg 1) The |eq_level| (a quarterword) is the level of grouping at
  6541  // which this equivalent was defined. If the level is |level_zero|, the
  6542  // equivalent has never been defined; |level_one| refers to the outer level
  6543  // (outside of all groups), and this level is also used for global
  6544  // definitions that never go away. Higher levels are for equivalents that
  6545  // will disappear at the end of their group.  \xref[global definitions]
  6546  //
  6547  // \yskip\hangg 2) The |eq_type| (another quarterword) specifies what kind of
  6548  // entry this is. There are many types, since each \TeX\ primitive like
  6549  // \.[\\hbox], \.[\\def], etc., has its own special code. The list of
  6550  // command codes above includes all possible settings of the |eq_type| field.
  6551  //
  6552  // \yskip\hangg 3) The |equiv| (a halfword) is the current equivalent value.
  6553  // This may be a font number, a pointer into |mem|, or a variety of other
  6554  // things.
  6555  
  6556  // 237.
  6557  
  6558  // tangle:pos tex.web:5043:3:
  6559  
  6560  // We can print the symbolic name of an integer parameter as follows.
  6561  func (prg *prg) printParam(n int32) {
  6562  	switch n {
  6563  	case pretoleranceCode:
  6564  		prg.printEsc(strNumber( /* "pretolerance" */ 420))
  6565  	case toleranceCode:
  6566  		prg.printEsc(strNumber( /* "tolerance" */ 421))
  6567  	case linePenaltyCode:
  6568  		prg.printEsc(strNumber( /* "linepenalty" */ 422))
  6569  	case hyphenPenaltyCode:
  6570  		prg.printEsc(strNumber( /* "hyphenpenalty" */ 423))
  6571  	case exHyphenPenaltyCode:
  6572  		prg.printEsc(strNumber( /* "exhyphenpenalty" */ 424))
  6573  	case clubPenaltyCode:
  6574  		prg.printEsc(strNumber( /* "clubpenalty" */ 425))
  6575  	case widowPenaltyCode:
  6576  		prg.printEsc(strNumber( /* "widowpenalty" */ 426))
  6577  	case displayWidowPenaltyCode:
  6578  		prg.printEsc(strNumber( /* "displaywidowpenalty" */ 427))
  6579  	case brokenPenaltyCode:
  6580  		prg.printEsc(strNumber( /* "brokenpenalty" */ 428))
  6581  	case binOpPenaltyCode:
  6582  		prg.printEsc(strNumber( /* "binoppenalty" */ 429))
  6583  	case relPenaltyCode:
  6584  		prg.printEsc(strNumber( /* "relpenalty" */ 430))
  6585  	case preDisplayPenaltyCode:
  6586  		prg.printEsc(strNumber( /* "predisplaypenalty" */ 431))
  6587  	case postDisplayPenaltyCode:
  6588  		prg.printEsc(strNumber( /* "postdisplaypenalty" */ 432))
  6589  	case interLinePenaltyCode:
  6590  		prg.printEsc(strNumber( /* "interlinepenalty" */ 433))
  6591  	case doubleHyphenDemeritsCode:
  6592  		prg.printEsc(strNumber( /* "doublehyphendemerits" */ 434))
  6593  	case finalHyphenDemeritsCode:
  6594  		prg.printEsc(strNumber( /* "finalhyphendemerits" */ 435))
  6595  	case adjDemeritsCode:
  6596  		prg.printEsc(strNumber( /* "adjdemerits" */ 436))
  6597  	case magCode:
  6598  		prg.printEsc(strNumber( /* "mag" */ 437))
  6599  	case delimiterFactorCode:
  6600  		prg.printEsc(strNumber( /* "delimiterfactor" */ 438))
  6601  	case loosenessCode:
  6602  		prg.printEsc(strNumber( /* "looseness" */ 439))
  6603  	case timeCode:
  6604  		prg.printEsc(strNumber( /* "time" */ 440))
  6605  	case dayCode:
  6606  		prg.printEsc(strNumber( /* "day" */ 441))
  6607  	case monthCode:
  6608  		prg.printEsc(strNumber( /* "month" */ 442))
  6609  	case yearCode:
  6610  		prg.printEsc(strNumber( /* "year" */ 443))
  6611  	case showBoxBreadthCode:
  6612  		prg.printEsc(strNumber( /* "showboxbreadth" */ 444))
  6613  	case showBoxDepthCode:
  6614  		prg.printEsc(strNumber( /* "showboxdepth" */ 445))
  6615  	case hbadnessCode:
  6616  		prg.printEsc(strNumber( /* "hbadness" */ 446))
  6617  	case vbadnessCode:
  6618  		prg.printEsc(strNumber( /* "vbadness" */ 447))
  6619  	case pausingCode:
  6620  		prg.printEsc(strNumber( /* "pausing" */ 448))
  6621  	case tracingOnlineCode:
  6622  		prg.printEsc(strNumber( /* "tracingonline" */ 449))
  6623  	case tracingMacrosCode:
  6624  		prg.printEsc(strNumber( /* "tracingmacros" */ 450))
  6625  	case tracingStatsCode:
  6626  		prg.printEsc(strNumber( /* "tracingstats" */ 451))
  6627  	case tracingParagraphsCode:
  6628  		prg.printEsc(strNumber( /* "tracingparagraphs" */ 452))
  6629  	case tracingPagesCode:
  6630  		prg.printEsc(strNumber( /* "tracingpages" */ 453))
  6631  	case tracingOutputCode:
  6632  		prg.printEsc(strNumber( /* "tracingoutput" */ 454))
  6633  	case tracingLostCharsCode:
  6634  		prg.printEsc(strNumber( /* "tracinglostchars" */ 455))
  6635  	case tracingCommandsCode:
  6636  		prg.printEsc(strNumber( /* "tracingcommands" */ 456))
  6637  	case tracingRestoresCode:
  6638  		prg.printEsc(strNumber( /* "tracingrestores" */ 457))
  6639  	case ucHyphCode:
  6640  		prg.printEsc(strNumber( /* "uchyph" */ 458))
  6641  	case outputPenaltyCode:
  6642  		prg.printEsc(strNumber( /* "outputpenalty" */ 459))
  6643  	case maxDeadCyclesCode:
  6644  		prg.printEsc(strNumber( /* "maxdeadcycles" */ 460))
  6645  	case hangAfterCode:
  6646  		prg.printEsc(strNumber( /* "hangafter" */ 461))
  6647  	case floatingPenaltyCode:
  6648  		prg.printEsc(strNumber( /* "floatingpenalty" */ 462))
  6649  	case globalDefsCode:
  6650  		prg.printEsc(strNumber( /* "globaldefs" */ 463))
  6651  	case curFamCode:
  6652  		prg.printEsc(strNumber( /* "fam" */ 464))
  6653  	case escapeCharCode:
  6654  		prg.printEsc(strNumber( /* "escapechar" */ 465))
  6655  	case defaultHyphenCharCode:
  6656  		prg.printEsc(strNumber( /* "defaulthyphenchar" */ 466))
  6657  	case defaultSkewCharCode:
  6658  		prg.printEsc(strNumber( /* "defaultskewchar" */ 467))
  6659  	case endLineCharCode:
  6660  		prg.printEsc(strNumber( /* "endlinechar" */ 468))
  6661  	case newLineCharCode:
  6662  		prg.printEsc(strNumber( /* "newlinechar" */ 469))
  6663  	case languageCode:
  6664  		prg.printEsc(strNumber( /* "language" */ 470))
  6665  	case leftHyphenMinCode:
  6666  		prg.printEsc(strNumber( /* "lefthyphenmin" */ 471))
  6667  	case rightHyphenMinCode:
  6668  		prg.printEsc(strNumber( /* "righthyphenmin" */ 472))
  6669  	case holdingInsertsCode:
  6670  		prg.printEsc(strNumber( /* "holdinginserts" */ 473))
  6671  	case errorContextLinesCode:
  6672  		prg.printEsc(strNumber( /* "errorcontextlines" */ 474))
  6673  
  6674  	default:
  6675  		prg.print( /* "[unknown integer parameter!]" */ 475)
  6676  	}
  6677  }
  6678  
  6679  // 241.
  6680  
  6681  // tangle:pos tex.web:5240:3:
  6682  
  6683  // The following procedure, which is called just before \TeX\ initializes its
  6684  // input and output, establishes the initial values of the date and time.
  6685  // \xref[system dependencies]
  6686  // Since standard \PASCAL\ cannot provide such information, something special
  6687  // is needed. The program here simply assumes that suitable values appear in
  6688  // the global variables \\[sys\_time], \\[sys\_day], \\[sys\_month], and
  6689  // \\[sys\_year] (which are initialized to noon on 4 July 1776,
  6690  // in case the implementor is careless).
  6691  func (prg *prg) fixDateAndTime() {
  6692  	prg.sysTime = 12 * 60
  6693  	prg.sysDay = 4
  6694  	prg.sysMonth = 7
  6695  	prg.sysYear = 1776                                  // self-evident truths
  6696  	*prg.eqtb[intBase+timeCode-1].int() = prg.sysTime   // minutes since midnight
  6697  	*prg.eqtb[intBase+dayCode-1].int() = prg.sysDay     // day of the month
  6698  	*prg.eqtb[intBase+monthCode-1].int() = prg.sysMonth // month of the year
  6699  	*prg.eqtb[intBase+yearCode-1].int() = prg.sysYear   // Anno Domini
  6700  }
  6701  
  6702  // 245.
  6703  
  6704  // tangle:pos tex.web:5272:3:
  6705  
  6706  // \TeX\ is occasionally supposed to print diagnostic information that
  6707  // goes only into the transcript file, unless |tracing_online| is positive.
  6708  // Here are two routines that adjust the destination of print commands:
  6709  func (prg *prg) beginDiagnostic() {
  6710  	prg.oldSetting = prg.selector
  6711  	if *prg.eqtb[intBase+tracingOnlineCode-1].int() <= 0 && int32(prg.selector) == termAndLog {
  6712  		prg.selector = byte(int32(prg.selector) - 1)
  6713  		if int32(prg.history) == spotless {
  6714  			prg.history = byte(warningIssued)
  6715  		}
  6716  	}
  6717  }
  6718  
  6719  func (prg *prg) endDiagnostic(blankLine bool) {
  6720  	prg.printNl(strNumber( /* "" */ 338))
  6721  	if blankLine {
  6722  		prg.printLn()
  6723  	}
  6724  	prg.selector = prg.oldSetting
  6725  }
  6726  
  6727  // 247.
  6728  
  6729  // tangle:pos tex.web:5299:3:
  6730  
  6731  // The final region of |eqtb| contains the dimension parameters defined
  6732  // here, and the 256 \.[\\dimen] registers.
  6733  func (prg *prg) printLengthParam(n int32) {
  6734  	switch n {
  6735  	case parIndentCode:
  6736  		prg.printEsc(strNumber( /* "parindent" */ 478))
  6737  	case mathSurroundCode:
  6738  		prg.printEsc(strNumber( /* "mathsurround" */ 479))
  6739  	case lineSkipLimitCode:
  6740  		prg.printEsc(strNumber( /* "lineskiplimit" */ 480))
  6741  	case hsizeCode:
  6742  		prg.printEsc(strNumber( /* "hsize" */ 481))
  6743  	case vsizeCode:
  6744  		prg.printEsc(strNumber( /* "vsize" */ 482))
  6745  	case maxDepthCode:
  6746  		prg.printEsc(strNumber( /* "maxdepth" */ 483))
  6747  	case splitMaxDepthCode:
  6748  		prg.printEsc(strNumber( /* "splitmaxdepth" */ 484))
  6749  	case boxMaxDepthCode:
  6750  		prg.printEsc(strNumber( /* "boxmaxdepth" */ 485))
  6751  	case hfuzzCode:
  6752  		prg.printEsc(strNumber( /* "hfuzz" */ 486))
  6753  	case vfuzzCode:
  6754  		prg.printEsc(strNumber( /* "vfuzz" */ 487))
  6755  	case delimiterShortfallCode:
  6756  		prg.printEsc(strNumber( /* "delimitershortfall" */ 488))
  6757  	case nullDelimiterSpaceCode:
  6758  		prg.printEsc(strNumber( /* "nulldelimiterspace" */ 489))
  6759  	case scriptSpaceCode:
  6760  		prg.printEsc(strNumber( /* "scriptspace" */ 490))
  6761  	case preDisplaySizeCode:
  6762  		prg.printEsc(strNumber( /* "predisplaysize" */ 491))
  6763  	case displayWidthCode:
  6764  		prg.printEsc(strNumber( /* "displaywidth" */ 492))
  6765  	case displayIndentCode:
  6766  		prg.printEsc(strNumber( /* "displayindent" */ 493))
  6767  	case overfullRuleCode:
  6768  		prg.printEsc(strNumber( /* "overfullrule" */ 494))
  6769  	case hangIndentCode:
  6770  		prg.printEsc(strNumber( /* "hangindent" */ 495))
  6771  	case hOffsetCode:
  6772  		prg.printEsc(strNumber( /* "hoffset" */ 496))
  6773  	case vOffsetCode:
  6774  		prg.printEsc(strNumber( /* "voffset" */ 497))
  6775  	case emergencyStretchCode:
  6776  		prg.printEsc(strNumber( /* "emergencystretch" */ 498))
  6777  
  6778  	default:
  6779  		prg.print( /* "[unknown dimen parameter!]" */ 499)
  6780  	}
  6781  }
  6782  
  6783  // 252.
  6784  
  6785  // tangle:pos tex.web:5441:3:
  6786  
  6787  // Here is a procedure that displays the contents of |eqtb[n]|
  6788  // symbolically.
  6789  // \4
  6790  // Declare the procedure called |print_cmd_chr|
  6791  func (prg *prg) printCmdChr(cmd quarterword, chrCode halfword) {
  6792  	switch cmd {
  6793  	case leftBrace:
  6794  		prg.print( /* "begin-group character " */ 557)
  6795  		prg.print(int32(chrCode))
  6796  	case rightBrace:
  6797  		prg.print( /* "end-group character " */ 558)
  6798  		prg.print(int32(chrCode))
  6799  	case mathShift:
  6800  		prg.print( /* "math shift character " */ 559)
  6801  		prg.print(int32(chrCode))
  6802  	case macParam:
  6803  		prg.print( /* "macro parameter character " */ 560)
  6804  		prg.print(int32(chrCode))
  6805  	case supMark:
  6806  		prg.print( /* "superscript character " */ 561)
  6807  		prg.print(int32(chrCode))
  6808  	case subMark:
  6809  		prg.print( /* "subscript character " */ 562)
  6810  		prg.print(int32(chrCode))
  6811  	case endv:
  6812  		prg.print( /* "end of alignment template" */ 563)
  6813  	case spacer:
  6814  		prg.print( /* "blank space " */ 564)
  6815  		prg.print(int32(chrCode))
  6816  	case letter:
  6817  		prg.print( /* "the letter " */ 565)
  6818  		prg.print(int32(chrCode))
  6819  	case otherChar:
  6820  		prg.print( /* "the character " */ 566)
  6821  		prg.print(int32(chrCode))
  6822  	// \4
  6823  	// Cases of |print_cmd_chr| for symbolic printing of primitives
  6824  	case assignGlue, assignMuGlue:
  6825  		if int32(chrCode) < skipBase {
  6826  			prg.printSkipParam(int32(chrCode) - glueBase)
  6827  		} else if int32(chrCode) < muSkipBase {
  6828  			prg.printEsc(strNumber( /* "skip" */ 395))
  6829  			prg.printInt(int32(chrCode) - skipBase)
  6830  		} else {
  6831  			prg.printEsc(strNumber( /* "muskip" */ 396))
  6832  			prg.printInt(int32(chrCode) - muSkipBase)
  6833  		}
  6834  
  6835  	case assignToks:
  6836  		if int32(chrCode) >= toksBase {
  6837  			prg.printEsc(strNumber( /* "toks" */ 407))
  6838  			prg.printInt(int32(chrCode) - toksBase)
  6839  		} else {
  6840  			switch chrCode {
  6841  			case outputRoutineLoc:
  6842  				prg.printEsc(strNumber( /* "output" */ 398))
  6843  			case everyParLoc:
  6844  				prg.printEsc(strNumber( /* "everypar" */ 399))
  6845  			case everyMathLoc:
  6846  				prg.printEsc(strNumber( /* "everymath" */ 400))
  6847  			case everyDisplayLoc:
  6848  				prg.printEsc(strNumber( /* "everydisplay" */ 401))
  6849  			case everyHboxLoc:
  6850  				prg.printEsc(strNumber( /* "everyhbox" */ 402))
  6851  			case everyVboxLoc:
  6852  				prg.printEsc(strNumber( /* "everyvbox" */ 403))
  6853  			case everyJobLoc:
  6854  				prg.printEsc(strNumber( /* "everyjob" */ 404))
  6855  			case everyCrLoc:
  6856  				prg.printEsc(strNumber( /* "everycr" */ 405))
  6857  
  6858  			default:
  6859  				prg.printEsc(strNumber( /* "errhelp" */ 406))
  6860  			}
  6861  		}
  6862  
  6863  	case assignInt:
  6864  		if int32(chrCode) < countBase {
  6865  			prg.printParam(int32(chrCode) - intBase)
  6866  		} else {
  6867  			prg.printEsc(strNumber( /* "count" */ 476))
  6868  			prg.printInt(int32(chrCode) - countBase)
  6869  		}
  6870  
  6871  	case assignDimen:
  6872  		if int32(chrCode) < scaledBase {
  6873  			prg.printLengthParam(int32(chrCode) - dimenBase)
  6874  		} else {
  6875  			prg.printEsc(strNumber( /* "dimen" */ 500))
  6876  			prg.printInt(int32(chrCode) - scaledBase)
  6877  		}
  6878  
  6879  	case accent:
  6880  		prg.printEsc(strNumber( /* "accent" */ 508))
  6881  	case advance:
  6882  		prg.printEsc(strNumber( /* "advance" */ 509))
  6883  	case afterAssignment:
  6884  		prg.printEsc(strNumber( /* "afterassignment" */ 510))
  6885  	case afterGroup:
  6886  		prg.printEsc(strNumber( /* "aftergroup" */ 511))
  6887  	case assignFontDimen:
  6888  		prg.printEsc(strNumber( /* "fontdimen" */ 519))
  6889  	case beginGroup:
  6890  		prg.printEsc(strNumber( /* "begingroup" */ 512))
  6891  	case breakPenalty:
  6892  		prg.printEsc(strNumber( /* "penalty" */ 531))
  6893  	case charNum:
  6894  		prg.printEsc(strNumber( /* "char" */ 513))
  6895  	case csName:
  6896  		prg.printEsc(strNumber( /* "csname" */ 504))
  6897  	case defFont:
  6898  		prg.printEsc(strNumber( /* "font" */ 518))
  6899  	case delimNum:
  6900  		prg.printEsc(strNumber( /* "delimiter" */ 514))
  6901  	case divide:
  6902  		prg.printEsc(strNumber( /* "divide" */ 515))
  6903  	case endCsName:
  6904  		prg.printEsc(strNumber( /* "endcsname" */ 505))
  6905  	case endGroup:
  6906  		prg.printEsc(strNumber( /* "endgroup" */ 516))
  6907  	case exSpace:
  6908  		prg.printEsc(strNumber(' '))
  6909  	case expandAfter:
  6910  		prg.printEsc(strNumber( /* "expandafter" */ 517))
  6911  	case halign:
  6912  		prg.printEsc(strNumber( /* "halign" */ 520))
  6913  	case hrule:
  6914  		prg.printEsc(strNumber( /* "hrule" */ 521))
  6915  	case ignoreSpaces:
  6916  		prg.printEsc(strNumber( /* "ignorespaces" */ 522))
  6917  	case insert:
  6918  		prg.printEsc(strNumber( /* "insert" */ 330))
  6919  	case italCorr:
  6920  		prg.printEsc(strNumber('/'))
  6921  	case mark:
  6922  		prg.printEsc(strNumber( /* "mark" */ 351))
  6923  	case mathAccent:
  6924  		prg.printEsc(strNumber( /* "mathaccent" */ 523))
  6925  	case mathCharNum:
  6926  		prg.printEsc(strNumber( /* "mathchar" */ 524))
  6927  	case mathChoice:
  6928  		prg.printEsc(strNumber( /* "mathchoice" */ 525))
  6929  	case multiply:
  6930  		prg.printEsc(strNumber( /* "multiply" */ 526))
  6931  	case noAlign:
  6932  		prg.printEsc(strNumber( /* "noalign" */ 527))
  6933  	case noBoundary:
  6934  		prg.printEsc(strNumber( /* "noboundary" */ 528))
  6935  	case noExpand:
  6936  		prg.printEsc(strNumber( /* "noexpand" */ 529))
  6937  	case nonScript:
  6938  		prg.printEsc(strNumber( /* "nonscript" */ 335))
  6939  	case omit:
  6940  		prg.printEsc(strNumber( /* "omit" */ 530))
  6941  	case radical:
  6942  		prg.printEsc(strNumber( /* "radical" */ 533))
  6943  	case readToCs:
  6944  		prg.printEsc(strNumber( /* "read" */ 534))
  6945  	case relax:
  6946  		prg.printEsc(strNumber( /* "relax" */ 535))
  6947  	case setBox:
  6948  		prg.printEsc(strNumber( /* "setbox" */ 536))
  6949  	case setPrevGraf:
  6950  		prg.printEsc(strNumber( /* "prevgraf" */ 532))
  6951  	case setShape:
  6952  		prg.printEsc(strNumber( /* "parshape" */ 408))
  6953  	case the:
  6954  		prg.printEsc(strNumber( /* "the" */ 537))
  6955  	case toksRegister:
  6956  		prg.printEsc(strNumber( /* "toks" */ 407))
  6957  	case vadjust:
  6958  		prg.printEsc(strNumber( /* "vadjust" */ 352))
  6959  	case valign:
  6960  		prg.printEsc(strNumber( /* "valign" */ 538))
  6961  	case vcenter:
  6962  		prg.printEsc(strNumber( /* "vcenter" */ 539))
  6963  	case vrule:
  6964  		prg.printEsc(strNumber( /* "vrule" */ 540))
  6965  
  6966  	case parEnd:
  6967  		prg.printEsc(strNumber( /* "par" */ 597))
  6968  
  6969  	case input:
  6970  		if int32(chrCode) == 0 {
  6971  			prg.printEsc(strNumber( /* "input" */ 629))
  6972  		} else {
  6973  			prg.printEsc(strNumber( /* "endinput" */ 630))
  6974  		}
  6975  
  6976  	case topBotMark:
  6977  		switch chrCode {
  6978  		case firstMarkCode:
  6979  			prg.printEsc(strNumber( /* "firstmark" */ 632))
  6980  		case botMarkCode:
  6981  			prg.printEsc(strNumber( /* "botmark" */ 633))
  6982  		case splitFirstMarkCode:
  6983  			prg.printEsc(strNumber( /* "splitfirstmark" */ 634))
  6984  		case splitBotMarkCode:
  6985  			prg.printEsc(strNumber( /* "splitbotmark" */ 635))
  6986  
  6987  		default:
  6988  			prg.printEsc(strNumber( /* "topmark" */ 631))
  6989  		}
  6990  
  6991  	case register:
  6992  		if int32(chrCode) == intVal {
  6993  			prg.printEsc(strNumber( /* "count" */ 476))
  6994  		} else if int32(chrCode) == dimenVal {
  6995  			prg.printEsc(strNumber( /* "dimen" */ 500))
  6996  		} else if int32(chrCode) == glueVal {
  6997  			prg.printEsc(strNumber( /* "skip" */ 395))
  6998  		} else {
  6999  			prg.printEsc(strNumber( /* "muskip" */ 396))
  7000  		}
  7001  
  7002  	case setAux:
  7003  		if int32(chrCode) == vmode {
  7004  			prg.printEsc(strNumber( /* "prevdepth" */ 669))
  7005  		} else {
  7006  			prg.printEsc(strNumber( /* "spacefactor" */ 668))
  7007  		}
  7008  	case setPageInt:
  7009  		if int32(chrCode) == 0 {
  7010  			prg.printEsc(strNumber( /* "deadcycles" */ 670))
  7011  		} else {
  7012  			prg.printEsc(strNumber( /* "insertpenalties" */ 671))
  7013  		}
  7014  	case setBoxDimen:
  7015  		if int32(chrCode) == widthOffset {
  7016  			prg.printEsc(strNumber( /* "wd" */ 672))
  7017  		} else if int32(chrCode) == heightOffset {
  7018  			prg.printEsc(strNumber( /* "ht" */ 673))
  7019  		} else {
  7020  			prg.printEsc(strNumber( /* "dp" */ 674))
  7021  		}
  7022  	case lastItem:
  7023  		switch chrCode {
  7024  		case intVal:
  7025  			prg.printEsc(strNumber( /* "lastpenalty" */ 675))
  7026  		case dimenVal:
  7027  			prg.printEsc(strNumber( /* "lastkern" */ 676))
  7028  		case glueVal:
  7029  			prg.printEsc(strNumber( /* "lastskip" */ 677))
  7030  		case inputLineNoCode:
  7031  			prg.printEsc(strNumber( /* "inputlineno" */ 678))
  7032  
  7033  		default:
  7034  			prg.printEsc(strNumber( /* "badness" */ 679))
  7035  		}
  7036  
  7037  	case convert:
  7038  		switch chrCode {
  7039  		case numberCode:
  7040  			prg.printEsc(strNumber( /* "number" */ 735))
  7041  		case romanNumeralCode:
  7042  			prg.printEsc(strNumber( /* "romannumeral" */ 736))
  7043  		case stringCode:
  7044  			prg.printEsc(strNumber( /* "string" */ 737))
  7045  		case meaningCode:
  7046  			prg.printEsc(strNumber( /* "meaning" */ 738))
  7047  		case fontNameCode:
  7048  			prg.printEsc(strNumber( /* "fontname" */ 739))
  7049  
  7050  		default:
  7051  			prg.printEsc(strNumber( /* "jobname" */ 740))
  7052  		}
  7053  
  7054  	case ifTest:
  7055  		switch chrCode {
  7056  		case ifCatCode:
  7057  			prg.printEsc(strNumber( /* "ifcat" */ 758))
  7058  		case ifIntCode:
  7059  			prg.printEsc(strNumber( /* "ifnum" */ 759))
  7060  		case ifDimCode:
  7061  			prg.printEsc(strNumber( /* "ifdim" */ 760))
  7062  		case ifOddCode:
  7063  			prg.printEsc(strNumber( /* "ifodd" */ 761))
  7064  		case ifVmodeCode:
  7065  			prg.printEsc(strNumber( /* "ifvmode" */ 762))
  7066  		case ifHmodeCode:
  7067  			prg.printEsc(strNumber( /* "ifhmode" */ 763))
  7068  		case ifMmodeCode:
  7069  			prg.printEsc(strNumber( /* "ifmmode" */ 764))
  7070  		case ifInnerCode:
  7071  			prg.printEsc(strNumber( /* "ifinner" */ 765))
  7072  		case ifVoidCode:
  7073  			prg.printEsc(strNumber( /* "ifvoid" */ 766))
  7074  		case ifHboxCode:
  7075  			prg.printEsc(strNumber( /* "ifhbox" */ 767))
  7076  		case ifVboxCode:
  7077  			prg.printEsc(strNumber( /* "ifvbox" */ 768))
  7078  		case ifxCode:
  7079  			prg.printEsc(strNumber( /* "ifx" */ 769))
  7080  		case ifEofCode:
  7081  			prg.printEsc(strNumber( /* "ifeof" */ 770))
  7082  		case ifTrueCode:
  7083  			prg.printEsc(strNumber( /* "iftrue" */ 771))
  7084  		case ifFalseCode:
  7085  			prg.printEsc(strNumber( /* "iffalse" */ 772))
  7086  		case ifCaseCode:
  7087  			prg.printEsc(strNumber( /* "ifcase" */ 773))
  7088  
  7089  		default:
  7090  			prg.printEsc(strNumber( /* "if" */ 757))
  7091  		}
  7092  
  7093  	case fiOrElse:
  7094  		if int32(chrCode) == fiCode {
  7095  			prg.printEsc(strNumber( /* "fi" */ 774))
  7096  		} else if int32(chrCode) == orCode {
  7097  			prg.printEsc(strNumber( /* "or" */ 775))
  7098  		} else {
  7099  			prg.printEsc(strNumber( /* "else" */ 776))
  7100  		}
  7101  
  7102  	case tabMark:
  7103  		if int32(chrCode) == spanCode {
  7104  			prg.printEsc(strNumber( /* "span" */ 898))
  7105  		} else {
  7106  			prg.print( /* "alignment tab character " */ 902)
  7107  			prg.print(int32(chrCode))
  7108  		}
  7109  	case carRet:
  7110  		if int32(chrCode) == crCode {
  7111  			prg.printEsc(strNumber( /* "cr" */ 899))
  7112  		} else {
  7113  			prg.printEsc(strNumber( /* "crcr" */ 900))
  7114  		}
  7115  
  7116  	case setPageDimen:
  7117  		switch chrCode {
  7118  		case 0:
  7119  			prg.printEsc(strNumber( /* "pagegoal" */ 970))
  7120  		case 1:
  7121  			prg.printEsc(strNumber( /* "pagetotal" */ 971))
  7122  		case 2:
  7123  			prg.printEsc(strNumber( /* "pagestretch" */ 972))
  7124  		case 3:
  7125  			prg.printEsc(strNumber( /* "pagefilstretch" */ 973))
  7126  		case 4:
  7127  			prg.printEsc(strNumber( /* "pagefillstretch" */ 974))
  7128  		case 5:
  7129  			prg.printEsc(strNumber( /* "pagefilllstretch" */ 975))
  7130  		case 6:
  7131  			prg.printEsc(strNumber( /* "pageshrink" */ 976))
  7132  
  7133  		default:
  7134  			prg.printEsc(strNumber( /* "pagedepth" */ 977))
  7135  		}
  7136  
  7137  	case stop:
  7138  		if int32(chrCode) == 1 {
  7139  			prg.printEsc(strNumber( /* "dump" */ 1026))
  7140  		} else {
  7141  			prg.printEsc(strNumber( /* "end" */ 1025))
  7142  		}
  7143  
  7144  	case hskip:
  7145  		switch chrCode {
  7146  		case skipCode:
  7147  			prg.printEsc(strNumber( /* "hskip" */ 1027))
  7148  		case filCode:
  7149  			prg.printEsc(strNumber( /* "hfil" */ 1028))
  7150  		case fillCode:
  7151  			prg.printEsc(strNumber( /* "hfill" */ 1029))
  7152  		case ssCode:
  7153  			prg.printEsc(strNumber( /* "hss" */ 1030))
  7154  
  7155  		default:
  7156  			prg.printEsc(strNumber( /* "hfilneg" */ 1031))
  7157  		}
  7158  	case vskip:
  7159  		switch chrCode {
  7160  		case skipCode:
  7161  			prg.printEsc(strNumber( /* "vskip" */ 1032))
  7162  		case filCode:
  7163  			prg.printEsc(strNumber( /* "vfil" */ 1033))
  7164  		case fillCode:
  7165  			prg.printEsc(strNumber( /* "vfill" */ 1034))
  7166  		case ssCode:
  7167  			prg.printEsc(strNumber( /* "vss" */ 1035))
  7168  
  7169  		default:
  7170  			prg.printEsc(strNumber( /* "vfilneg" */ 1036))
  7171  		}
  7172  	case mskip:
  7173  		prg.printEsc(strNumber( /* "mskip" */ 336))
  7174  	case kern:
  7175  		prg.printEsc(strNumber( /* "kern" */ 340))
  7176  	case mkern:
  7177  		prg.printEsc(strNumber( /* "mkern" */ 342))
  7178  
  7179  	case hmove:
  7180  		if int32(chrCode) == 1 {
  7181  			prg.printEsc(strNumber( /* "moveleft" */ 1054))
  7182  		} else {
  7183  			prg.printEsc(strNumber( /* "moveright" */ 1055))
  7184  		}
  7185  	case vmove:
  7186  		if int32(chrCode) == 1 {
  7187  			prg.printEsc(strNumber( /* "raise" */ 1056))
  7188  		} else {
  7189  			prg.printEsc(strNumber( /* "lower" */ 1057))
  7190  		}
  7191  	case makeBox:
  7192  		switch chrCode {
  7193  		case boxCode:
  7194  			prg.printEsc(strNumber( /* "box" */ 409))
  7195  		case copyCode:
  7196  			prg.printEsc(strNumber( /* "copy" */ 1058))
  7197  		case lastBoxCode:
  7198  			prg.printEsc(strNumber( /* "lastbox" */ 1059))
  7199  		case vsplitCode:
  7200  			prg.printEsc(strNumber( /* "vsplit" */ 965))
  7201  		case vtopCode:
  7202  			prg.printEsc(strNumber( /* "vtop" */ 1060))
  7203  		case vtopCode + 1:
  7204  			prg.printEsc(strNumber( /* "vbox" */ 967))
  7205  
  7206  		default:
  7207  			prg.printEsc(strNumber( /* "hbox" */ 1061))
  7208  		}
  7209  	case leaderShip:
  7210  		if int32(chrCode) == aLeaders {
  7211  			prg.printEsc(strNumber( /* "leaders" */ 1063))
  7212  		} else if int32(chrCode) == cLeaders {
  7213  			prg.printEsc(strNumber( /* "cleaders" */ 1064))
  7214  		} else if int32(chrCode) == xLeaders {
  7215  			prg.printEsc(strNumber( /* "xleaders" */ 1065))
  7216  		} else {
  7217  			prg.printEsc(strNumber( /* "shipout" */ 1062))
  7218  		}
  7219  
  7220  	case startPar:
  7221  		if int32(chrCode) == 0 {
  7222  			prg.printEsc(strNumber( /* "noindent" */ 1081))
  7223  		} else {
  7224  			prg.printEsc(strNumber( /* "indent" */ 1080))
  7225  		}
  7226  
  7227  	case removeItem:
  7228  		if int32(chrCode) == glueNode {
  7229  			prg.printEsc(strNumber( /* "unskip" */ 1092))
  7230  		} else if int32(chrCode) == kernNode {
  7231  			prg.printEsc(strNumber( /* "unkern" */ 1091))
  7232  		} else {
  7233  			prg.printEsc(strNumber( /* "unpenalty" */ 1090))
  7234  		}
  7235  	case unHbox:
  7236  		if int32(chrCode) == copyCode {
  7237  			prg.printEsc(strNumber( /* "unhcopy" */ 1094))
  7238  		} else {
  7239  			prg.printEsc(strNumber( /* "unhbox" */ 1093))
  7240  		}
  7241  	case unVbox:
  7242  		if int32(chrCode) == copyCode {
  7243  			prg.printEsc(strNumber( /* "unvcopy" */ 1096))
  7244  		} else {
  7245  			prg.printEsc(strNumber( /* "unvbox" */ 1095))
  7246  		}
  7247  
  7248  	case discretionary:
  7249  		if int32(chrCode) == 1 {
  7250  			prg.printEsc(strNumber('-'))
  7251  		} else {
  7252  			prg.printEsc(strNumber( /* "discretionary" */ 349))
  7253  		}
  7254  
  7255  	case eqNo:
  7256  		if int32(chrCode) == 1 {
  7257  			prg.printEsc(strNumber( /* "leqno" */ 1128))
  7258  		} else {
  7259  			prg.printEsc(strNumber( /* "eqno" */ 1127))
  7260  		}
  7261  
  7262  	case mathComp:
  7263  		switch chrCode {
  7264  		case ordNoad:
  7265  			prg.printEsc(strNumber( /* "mathord" */ 866))
  7266  		case opNoad:
  7267  			prg.printEsc(strNumber( /* "mathop" */ 867))
  7268  		case binNoad:
  7269  			prg.printEsc(strNumber( /* "mathbin" */ 868))
  7270  		case relNoad:
  7271  			prg.printEsc(strNumber( /* "mathrel" */ 869))
  7272  		case openNoad:
  7273  			prg.printEsc(strNumber( /* "mathopen" */ 870))
  7274  		case closeNoad:
  7275  			prg.printEsc(strNumber( /* "mathclose" */ 871))
  7276  		case punctNoad:
  7277  			prg.printEsc(strNumber( /* "mathpunct" */ 872))
  7278  		case innerNoad:
  7279  			prg.printEsc(strNumber( /* "mathinner" */ 873))
  7280  		case underNoad:
  7281  			prg.printEsc(strNumber( /* "underline" */ 875))
  7282  
  7283  		default:
  7284  			prg.printEsc(strNumber( /* "overline" */ 874))
  7285  		}
  7286  	case limitSwitch:
  7287  		if int32(chrCode) == limits {
  7288  			prg.printEsc(strNumber( /* "limits" */ 878))
  7289  		} else if int32(chrCode) == noLimits {
  7290  			prg.printEsc(strNumber( /* "nolimits" */ 879))
  7291  		} else {
  7292  			prg.printEsc(strNumber( /* "displaylimits" */ 1129))
  7293  		}
  7294  
  7295  	case mathStyle:
  7296  		prg.printStyle(int32(chrCode))
  7297  
  7298  	case above:
  7299  		switch chrCode {
  7300  		case overCode:
  7301  			prg.printEsc(strNumber( /* "over" */ 1148))
  7302  		case atopCode:
  7303  			prg.printEsc(strNumber( /* "atop" */ 1149))
  7304  		case delimitedCode + 0:
  7305  			prg.printEsc(strNumber( /* "abovewithdelims" */ 1150))
  7306  		case delimitedCode + 1:
  7307  			prg.printEsc(strNumber( /* "overwithdelims" */ 1151))
  7308  		case delimitedCode + 2:
  7309  			prg.printEsc(strNumber( /* "atopwithdelims" */ 1152))
  7310  
  7311  		default:
  7312  			prg.printEsc(strNumber( /* "above" */ 1147))
  7313  		}
  7314  
  7315  	case leftRight:
  7316  		if int32(chrCode) == leftNoad {
  7317  			prg.printEsc(strNumber( /* "left" */ 876))
  7318  		} else {
  7319  			prg.printEsc(strNumber( /* "right" */ 877))
  7320  		}
  7321  
  7322  	case prefix:
  7323  		if int32(chrCode) == 1 {
  7324  			prg.printEsc(strNumber( /* "long" */ 1171))
  7325  		} else if int32(chrCode) == 2 {
  7326  			prg.printEsc(strNumber( /* "outer" */ 1172))
  7327  		} else {
  7328  			prg.printEsc(strNumber( /* "global" */ 1173))
  7329  		}
  7330  	case def:
  7331  		if int32(chrCode) == 0 {
  7332  			prg.printEsc(strNumber( /* "def" */ 1174))
  7333  		} else if int32(chrCode) == 1 {
  7334  			prg.printEsc(strNumber( /* "gdef" */ 1175))
  7335  		} else if int32(chrCode) == 2 {
  7336  			prg.printEsc(strNumber( /* "edef" */ 1176))
  7337  		} else {
  7338  			prg.printEsc(strNumber( /* "xdef" */ 1177))
  7339  		}
  7340  
  7341  	case let:
  7342  		if int32(chrCode) != normal {
  7343  			prg.printEsc(strNumber( /* "futurelet" */ 1192))
  7344  		} else {
  7345  			prg.printEsc(strNumber( /* "let" */ 1191))
  7346  		}
  7347  
  7348  	case shorthandDef:
  7349  		switch chrCode {
  7350  		case charDefCode:
  7351  			prg.printEsc(strNumber( /* "chardef" */ 1193))
  7352  		case mathCharDefCode:
  7353  			prg.printEsc(strNumber( /* "mathchardef" */ 1194))
  7354  		case countDefCode:
  7355  			prg.printEsc(strNumber( /* "countdef" */ 1195))
  7356  		case dimenDefCode:
  7357  			prg.printEsc(strNumber( /* "dimendef" */ 1196))
  7358  		case skipDefCode:
  7359  			prg.printEsc(strNumber( /* "skipdef" */ 1197))
  7360  		case muSkipDefCode:
  7361  			prg.printEsc(strNumber( /* "muskipdef" */ 1198))
  7362  
  7363  		default:
  7364  			prg.printEsc(strNumber( /* "toksdef" */ 1199))
  7365  		}
  7366  	case charGiven:
  7367  		prg.printEsc(strNumber( /* "char" */ 513))
  7368  		prg.printHex(int32(chrCode))
  7369  
  7370  	case mathGiven:
  7371  		prg.printEsc(strNumber( /* "mathchar" */ 524))
  7372  		prg.printHex(int32(chrCode))
  7373  
  7374  	case defCode:
  7375  		if int32(chrCode) == catCodeBase {
  7376  			prg.printEsc(strNumber( /* "catcode" */ 415))
  7377  		} else if int32(chrCode) == mathCodeBase {
  7378  			prg.printEsc(strNumber( /* "mathcode" */ 419))
  7379  		} else if int32(chrCode) == lcCodeBase {
  7380  			prg.printEsc(strNumber( /* "lccode" */ 416))
  7381  		} else if int32(chrCode) == ucCodeBase {
  7382  			prg.printEsc(strNumber( /* "uccode" */ 417))
  7383  		} else if int32(chrCode) == sfCodeBase {
  7384  			prg.printEsc(strNumber( /* "sfcode" */ 418))
  7385  		} else {
  7386  			prg.printEsc(strNumber( /* "delcode" */ 477))
  7387  		}
  7388  	case defFamily:
  7389  		prg.printSize(int32(chrCode) - mathFontBase)
  7390  
  7391  	case hyphData:
  7392  		if int32(chrCode) == 1 {
  7393  			prg.printEsc(strNumber( /* "patterns" */ 953))
  7394  		} else {
  7395  			prg.printEsc(strNumber( /* "hyphenation" */ 941))
  7396  		}
  7397  
  7398  	case assignFontInt:
  7399  		if int32(chrCode) == 0 {
  7400  			prg.printEsc(strNumber( /* "hyphenchar" */ 1217))
  7401  		} else {
  7402  			prg.printEsc(strNumber( /* "skewchar" */ 1218))
  7403  		}
  7404  
  7405  	case setFont:
  7406  		prg.print( /* "select font " */ 1226)
  7407  		prg.slowPrint(int32(prg.fontName[chrCode]))
  7408  		if prg.fontSize[chrCode] != prg.fontDsize[chrCode] {
  7409  			prg.print( /* " at " */ 741)
  7410  			prg.printScaled(prg.fontSize[chrCode])
  7411  			prg.print( /* "pt" */ 397)
  7412  		}
  7413  
  7414  	case setInteraction:
  7415  		switch chrCode {
  7416  		case batchMode:
  7417  			prg.printEsc(strNumber( /* "batchmode" */ 274))
  7418  		case nonstopMode:
  7419  			prg.printEsc(strNumber( /* "nonstopmode" */ 275))
  7420  		case scrollMode:
  7421  			prg.printEsc(strNumber( /* "scrollmode" */ 276))
  7422  
  7423  		default:
  7424  			prg.printEsc(strNumber( /* "errorstopmode" */ 1227))
  7425  		}
  7426  
  7427  	case inStream:
  7428  		if int32(chrCode) == 0 {
  7429  			prg.printEsc(strNumber( /* "closein" */ 1229))
  7430  		} else {
  7431  			prg.printEsc(strNumber( /* "openin" */ 1228))
  7432  		}
  7433  
  7434  	case message:
  7435  		if int32(chrCode) == 0 {
  7436  			prg.printEsc(strNumber( /* "message" */ 1230))
  7437  		} else {
  7438  			prg.printEsc(strNumber( /* "errmessage" */ 1231))
  7439  		}
  7440  
  7441  	case caseShift:
  7442  		if int32(chrCode) == lcCodeBase {
  7443  			prg.printEsc(strNumber( /* "lowercase" */ 1237))
  7444  		} else {
  7445  			prg.printEsc(strNumber( /* "uppercase" */ 1238))
  7446  		}
  7447  
  7448  	case xray:
  7449  		switch chrCode {
  7450  		case showBoxCode:
  7451  			prg.printEsc(strNumber( /* "showbox" */ 1240))
  7452  		case showTheCode:
  7453  			prg.printEsc(strNumber( /* "showthe" */ 1241))
  7454  		case showListsCode:
  7455  			prg.printEsc(strNumber( /* "showlists" */ 1242))
  7456  
  7457  		default:
  7458  			prg.printEsc(strNumber( /* "show" */ 1239))
  7459  		}
  7460  
  7461  	case undefinedCs:
  7462  		prg.print( /* "undefined" */ 1249)
  7463  	case call:
  7464  		prg.print( /* "macro" */ 1250)
  7465  	case longCall:
  7466  		prg.printEsc(strNumber( /* "long macro" */ 1251))
  7467  	case outerCall:
  7468  		prg.printEsc(strNumber( /* "outer macro" */ 1252))
  7469  	case longOuterCall:
  7470  		prg.printEsc(strNumber( /* "long" */ 1171))
  7471  		prg.printEsc(strNumber( /* "outer macro" */ 1252))
  7472  
  7473  	case endTemplate:
  7474  		prg.printEsc(strNumber( /* "outer endtemplate" */ 1253))
  7475  
  7476  	case extension:
  7477  		switch chrCode {
  7478  		case openNode:
  7479  			prg.printEsc(strNumber( /* "openout" */ 1285))
  7480  		case writeNode:
  7481  			prg.printEsc(strNumber( /* "write" */ 594))
  7482  		case closeNode:
  7483  			prg.printEsc(strNumber( /* "closeout" */ 1286))
  7484  		case specialNode:
  7485  			prg.printEsc(strNumber( /* "special" */ 1287))
  7486  		case immediateCode:
  7487  			prg.printEsc(strNumber( /* "immediate" */ 1288))
  7488  		case setLanguageCode:
  7489  			prg.printEsc(strNumber( /* "setlanguage" */ 1289))
  7490  
  7491  		default:
  7492  			prg.print( /* "[unknown extension!]" */ 1290)
  7493  		}
  7494  
  7495  	default:
  7496  		prg.print( /* "[unknown command code!]" */ 567)
  7497  	}
  7498  }
  7499  
  7500  //  procedure show_eqtb( n:halfword );
  7501  // begin if n<active_base then print_char(["?"=]63) [this can't happen]
  7502  // else if n<glue_base then
  7503  // [ Show equivalent |n|, in region 1 or 2 ]
  7504  // begin sprint_cs(n); print_char(["="=]61); print_cmd_chr( eqtb[  n].hh.b0  , eqtb[  n].hh.rh  );
  7505  // if  eqtb[  n].hh.b0  >=call then
  7506  //   begin print_char([":"=]58); show_token_list( mem[  eqtb[   n].hh.rh  ].hh.rh ,0  ,32);
  7507  //   end;
  7508  // end
  7509  //
  7510  // else if n<local_base then
  7511  // [ Show equivalent |n|, in region 3 ]
  7512  // if n<skip_base then
  7513  //   begin print_skip_param(n-glue_base); print_char(["="=]61);
  7514  //   if n<glue_base+thin_mu_skip_code then print_spec( eqtb[  n].hh.rh  ,["pt"=]397)
  7515  //   else print_spec( eqtb[  n].hh.rh  ,["mu"=]337);
  7516  //   end
  7517  // else if n<mu_skip_base then
  7518  //   begin print_esc(["skip"=]395); print_int(n-skip_base); print_char(["="=]61);
  7519  //   print_spec( eqtb[  n].hh.rh  ,["pt"=]397);
  7520  //   end
  7521  // else  begin print_esc(["muskip"=]396); print_int(n-mu_skip_base); print_char(["="=]61);
  7522  //   print_spec( eqtb[  n].hh.rh  ,["mu"=]337);
  7523  //   end
  7524  //
  7525  // else if n<int_base then
  7526  // [ Show equivalent |n|, in region 4 ]
  7527  // if n=par_shape_loc then
  7528  //   begin print_esc(["parshape"=]408); print_char(["="=]61);
  7529  //   if  eqtb[  par_shape_loc].hh.rh   =0   then print_char(["0"=]48)
  7530  //   else print_int( mem[  eqtb[  par_shape_loc].hh.rh   ].hh.lh );
  7531  //   end
  7532  // else if n<toks_base then
  7533  //   begin print_cmd_chr(assign_toks,n); print_char(["="=]61);
  7534  //   if  eqtb[  n].hh.rh  <>0   then show_token_list( mem[  eqtb[   n].hh.rh  ].hh.rh ,0  ,32);
  7535  //   end
  7536  // else if n<box_base then
  7537  //   begin print_esc(["toks"=]407); print_int(n-toks_base); print_char(["="=]61);
  7538  //   if  eqtb[  n].hh.rh  <>0   then show_token_list( mem[  eqtb[   n].hh.rh  ].hh.rh ,0  ,32);
  7539  //   end
  7540  // else if n<cur_font_loc then
  7541  //   begin print_esc(["box"=]409); print_int(n-box_base); print_char(["="=]61);
  7542  //   if  eqtb[  n].hh.rh  =0   then print(["void"=]410)
  7543  //   else  begin depth_threshold:=0; breadth_max:=1; show_node_list( eqtb[  n].hh.rh  );
  7544  //     end;
  7545  //   end
  7546  // else if n<cat_code_base then
  7547  // [ Show the font identifier in |eqtb[n]| ]
  7548  // begin if n=cur_font_loc then print(["current font"=]411)
  7549  // else if n<math_font_base+16 then
  7550  //   begin print_esc(["textfont"=]412); print_int(n-math_font_base);
  7551  //   end
  7552  // else if n<math_font_base+32 then
  7553  //   begin print_esc(["scriptfont"=]413); print_int(n-math_font_base-16);
  7554  //   end
  7555  // else  begin print_esc(["scriptscriptfont"=]414); print_int(n-math_font_base-32);
  7556  //   end;
  7557  // print_char(["="=]61);
  7558  //
  7559  // print_esc(hash[font_id_base+ eqtb[  n].hh.rh  ].rh);
  7560  //   [that's |font_id_text(equiv(n))|]
  7561  // end
  7562  //
  7563  // else
  7564  // [ Show the halfword code in |eqtb[n]| ]
  7565  // if n<math_code_base then
  7566  //   begin if n<lc_code_base then
  7567  //     begin print_esc(["catcode"=]415); print_int(n-cat_code_base);
  7568  //     end
  7569  //   else if n<uc_code_base then
  7570  //     begin print_esc(["lccode"=]416); print_int(n-lc_code_base);
  7571  //     end
  7572  //   else if n<sf_code_base then
  7573  //     begin print_esc(["uccode"=]417); print_int(n-uc_code_base);
  7574  //     end
  7575  //   else  begin print_esc(["sfcode"=]418); print_int(n-sf_code_base);
  7576  //     end;
  7577  //   print_char(["="=]61); print_int( eqtb[  n].hh.rh  );
  7578  //   end
  7579  // else  begin print_esc(["mathcode"=]419); print_int(n-math_code_base);
  7580  //   print_char(["="=]61); print_int(  eqtb[   n].hh.rh  -0  );
  7581  //   end
  7582  //
  7583  // else if n<dimen_base then
  7584  // [ Show equivalent |n|, in region 5 ]
  7585  // begin if n<count_base then print_param(n-int_base)
  7586  // else if  n<del_code_base then
  7587  //   begin print_esc(["count"=]476); print_int(n-count_base);
  7588  //   end
  7589  // else  begin print_esc(["delcode"=]477); print_int(n-del_code_base);
  7590  //   end;
  7591  // print_char(["="=]61); print_int(eqtb[n].int);
  7592  // end
  7593  //
  7594  // else if n<=eqtb_size then
  7595  // [ Show equivalent |n|, in region 6 ]
  7596  // begin if n<scaled_base then print_length_param(n-dimen_base)
  7597  // else  begin print_esc(["dimen"=]500); print_int(n-scaled_base);
  7598  //   end;
  7599  // print_char(["="=]61); print_scaled(eqtb[n].int ); print(["pt"=]397);
  7600  // end
  7601  //
  7602  // else print_char(["?"=]63); [this can't happen either]
  7603  // end;
  7604  // [  ]
  7605  
  7606  // 259.
  7607  
  7608  // tangle:pos tex.web:5528:3:
  7609  
  7610  // Here is the subroutine that searches the hash table for an identifier
  7611  // that matches a given string of length |l>1| appearing in |buffer[j..
  7612  // (j+l-1)]|. If the identifier is found, the corresponding hash table address
  7613  // is returned. Otherwise, if the global variable |no_new_control_sequence|
  7614  // is |true|, the dummy address |undefined_control_sequence| is returned.
  7615  // Otherwise the identifier is inserted into the hash table and its location
  7616  // is returned.
  7617  func (prg *prg) idLookup(j, l int32) (r halfword) { // go here if you found it
  7618  	var (
  7619  		h int32    // hash code
  7620  		d int32    // number of characters in incomplete current string
  7621  		p halfword // index in |hash| array
  7622  		k halfword // index in |buffer| array
  7623  	)
  7624  	h = int32(prg.buffer[j])
  7625  	for ii := j + 1; ii <= j+l-1; ii++ {
  7626  		k = halfword(ii)
  7627  		_ = k
  7628  		h = h + h + int32(prg.buffer[k])
  7629  		for h >= hashPrime {
  7630  			h = h - hashPrime
  7631  		}
  7632  	}
  7633  	p = uint16(h + hashBase) // we start searching here; note that |0<=h<hash_prime|
  7634  	for true {
  7635  		if int32(*prg.hash[p-514].rh()) > 0 {
  7636  			if int32(prg.strStart[int32(*prg.hash[p-514].rh())+1])-int32(prg.strStart[*prg.hash[p-514].rh()]) == l {
  7637  				if prg.strEqBuf(*prg.hash[p-514].rh(), j) {
  7638  					goto found
  7639  				}
  7640  			}
  7641  		}
  7642  		if int32(*prg.hash[p-514].lh()) == 0 {
  7643  			if prg.noNewControlSequence {
  7644  				p = uint16(undefinedControlSequence)
  7645  			} else {
  7646  				// Insert a new control sequence after |p|, then make |p| point to it
  7647  				if int32(*prg.hash[p-514].rh()) > 0 {
  7648  					for {
  7649  						if int32(prg.hashUsed) == hashBase {
  7650  							prg.overflow(strNumber( /* "hash size" */ 503), hashSize)
  7651  						}
  7652  						// \xref[TeX capacity exceeded hash size][\quad hash size]
  7653  						prg.hashUsed = uint16(int32(prg.hashUsed) - 1)
  7654  						if int32(*prg.hash[prg.hashUsed-514].rh()) == 0 {
  7655  							break
  7656  						}
  7657  					} // search for an empty location in |hash|
  7658  					*prg.hash[p-514].lh() = prg.hashUsed
  7659  					p = prg.hashUsed
  7660  				}
  7661  				{
  7662  					if int32(prg.poolPtr)+l > poolSize {
  7663  						prg.overflow(strNumber( /* "pool size" */ 257), poolSize-int32(prg.initPoolPtr))
  7664  					} /* \xref[TeX capacity exceeded pool size][\quad pool size]  */
  7665  				}
  7666  				d = int32(prg.poolPtr) - int32(prg.strStart[prg.strPtr])
  7667  				for int32(prg.poolPtr) > int32(prg.strStart[prg.strPtr]) {
  7668  					prg.poolPtr = uint16(int32(prg.poolPtr) - 1)
  7669  					prg.strPool[int32(prg.poolPtr)+l] = prg.strPool[prg.poolPtr]
  7670  				} // move current string up to make room for another
  7671  				for ii := j; ii <= j+l-1; ii++ {
  7672  					k = halfword(ii)
  7673  					_ = k
  7674  					prg.strPool[prg.poolPtr] = prg.buffer[k]
  7675  					prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
  7676  				}
  7677  				*prg.hash[p-514].rh() = prg.makeString()
  7678  				prg.poolPtr = uint16(int32(prg.poolPtr) + d)
  7679  				//    cs_count:= cs_count+1 ; [  ]
  7680  
  7681  			}
  7682  
  7683  			goto found
  7684  		}
  7685  		p = *prg.hash[p-514].lh()
  7686  	}
  7687  
  7688  found:
  7689  	r = p
  7690  	return r
  7691  }
  7692  
  7693  // 264.
  7694  
  7695  // tangle:pos tex.web:5631:3:
  7696  
  7697  // We need to put \TeX's ``primitive'' control sequences into the hash
  7698  // table, together with their command code (which will be the |eq_type|)
  7699  // and an operand (which will be the |equiv|). The |primitive| procedure
  7700  // does this, in a way that no \TeX\ user can. The global value |cur_val|
  7701  // contains the new |eqtb| pointer after |primitive| has acted.
  7702  func (prg *prg) primitive(s strNumber, c quarterword, o halfword) {
  7703  	var (
  7704  		k poolPointer // index into |str_pool|
  7705  		j smallNumber // index into |buffer|
  7706  		l smallNumber // length of the string
  7707  	)
  7708  	if int32(s) < 256 {
  7709  		prg.curVal = int32(s) + singleBase
  7710  	} else {
  7711  		k = prg.strStart[s]
  7712  		l = byte(int32(prg.strStart[int32(s)+1]) - int32(k))
  7713  		// we will move |s| into the (empty) |buffer|
  7714  		for ii := int32(0); ii <= int32(l)-1; ii++ {
  7715  			j = smallNumber(ii)
  7716  			_ = j
  7717  			prg.buffer[j] = prg.strPool[int32(k)+int32(j)]
  7718  		}
  7719  		prg.curVal = int32(prg.idLookup(0, int32(l))) // |no_new_control_sequence| is |false|
  7720  		{
  7721  			prg.strPtr = uint16(int32(prg.strPtr) - 1)
  7722  			prg.poolPtr = prg.strStart[prg.strPtr]
  7723  		}
  7724  		*prg.hash[prg.curVal-514].rh() = s // we don't want to have the string twice
  7725  	}
  7726  	*(*prg.eqtb[prg.curVal-1].hh()).b1() = byte(levelOne)
  7727  	*(*prg.eqtb[prg.curVal-1].hh()).b0() = c
  7728  	*(*prg.eqtb[prg.curVal-1].hh()).rh() = o
  7729  }
  7730  
  7731  // 268. \[19] Saving and restoring equivalents
  7732  
  7733  // tangle:pos tex.web:5813:43:
  7734  
  7735  // The nested structure provided by `$\.[\char'173]\ldots\.[\char'175]$' groups
  7736  // in \TeX\ means that |eqtb| entries valid in outer groups should be saved
  7737  // and restored later if they are overridden inside the braces. When a new |eqtb|
  7738  // value is being assigned, the program therefore checks to see if the previous
  7739  // entry belongs to an outer level. In such a case, the old value is placed
  7740  // on the |save_stack| just before the new value enters |eqtb|. At the
  7741  // end of a grouping level, i.e., when the right brace is sensed, the
  7742  // |save_stack| is used to restore the outer values, and the inner ones are
  7743  // destroyed.
  7744  //
  7745  // Entries on the |save_stack| are of type |memory_word|. The top item on
  7746  // this stack is |save_stack[p]|, where |p=save_ptr-1|; it contains three
  7747  // fields called |save_type|, |save_level|, and |save_index|, and it is
  7748  // interpreted in one of four ways:
  7749  //
  7750  // \yskip\hangg 1) If |save_type(p)=restore_old_value|, then
  7751  // |save_index(p)| is a location in |eqtb| whose current value should
  7752  // be destroyed at the end of the current group and replaced by |save_stack[p-1]|.
  7753  // Furthermore if |save_index(p)>=int_base|, then |save_level(p)|
  7754  // should replace the corresponding entry in |xeq_level|.
  7755  //
  7756  // \yskip\hangg 2) If |save_type(p)=restore_zero|, then |save_index(p)|
  7757  // is a location in |eqtb| whose current value should be destroyed at the end
  7758  // of the current group, when it should be
  7759  // replaced by the value of |eqtb[undefined_control_sequence]|.
  7760  //
  7761  // \yskip\hangg 3) If |save_type(p)=insert_token|, then |save_index(p)|
  7762  // is a token that should be inserted into \TeX's input when the current
  7763  // group ends.
  7764  //
  7765  // \yskip\hangg 4) If |save_type(p)=level_boundary|, then |save_level(p)|
  7766  // is a code explaining what kind of group we were previously in, and
  7767  // |save_index(p)| points to the level boundary word at the bottom of
  7768  // the entries for that group.
  7769  
  7770  // 270.
  7771  
  7772  // tangle:pos tex.web:5892:3:
  7773  
  7774  // The global variable |cur_group| keeps track of what sort of group we are
  7775  // currently in. Another global variable, |cur_boundary|, points to the
  7776  // topmost |level_boundary| word.  And |cur_level| is the current depth of
  7777  // nesting. The routines are designed to preserve the condition that no entry
  7778  // in the |save_stack| or in |eqtb| ever has a level greater than |cur_level|.
  7779  
  7780  // 273.
  7781  
  7782  // tangle:pos tex.web:5915:3:
  7783  
  7784  // The following macro is used to test if there is room for up to six more
  7785  // entries on |save_stack|. By making a conservative test like this, we can
  7786  // get by with testing for overflow in only a few places.
  7787  
  7788  // 274.
  7789  
  7790  // tangle:pos tex.web:5925:3:
  7791  
  7792  // Procedure |new_save_level| is called when a group begins. The
  7793  // argument is a group identification code like `|hbox_group|'. After
  7794  // calling this routine, it is safe to put five more entries on |save_stack|.
  7795  //
  7796  // In some cases integer-valued items are placed onto the
  7797  // |save_stack| just below a |level_boundary| word, because this is a
  7798  // convenient place to keep information that is supposed to ``pop up'' just
  7799  // when the group has finished.
  7800  // For example, when `\.[\\hbox to 100pt]\grp' is being treated, the 100pt
  7801  // dimension is stored on |save_stack| just before |new_save_level| is
  7802  // called.
  7803  //
  7804  // We use the notation |saved(k)| to stand for an integer item that
  7805  // appears in location |save_ptr+k| of the save stack.
  7806  func (prg *prg) newSaveLevel(c groupCode) {
  7807  	if int32(prg.savePtr) > int32(prg.maxSaveStack) {
  7808  		prg.maxSaveStack = prg.savePtr
  7809  		if int32(prg.maxSaveStack) > saveSize-6 {
  7810  			prg.overflow(strNumber( /* "save size" */ 541), saveSize)
  7811  		} /* \xref[TeX capacity exceeded save size][\quad save size]  */
  7812  	}
  7813  	*(*prg.saveStack[prg.savePtr].hh()).b0() = byte(levelBoundary)
  7814  	*(*prg.saveStack[prg.savePtr].hh()).b1() = prg.curGroup
  7815  	*(*prg.saveStack[prg.savePtr].hh()).rh() = prg.curBoundary
  7816  	if int32(prg.curLevel) == maxQuarterword {
  7817  		prg.overflow(strNumber( /* "grouping levels" */ 542), maxQuarterword-minQuarterword)
  7818  	}
  7819  	// quit if |(cur_level+1)| is too big to be stored in |eqtb|
  7820  	prg.curBoundary = prg.savePtr
  7821  	prg.curLevel = byte(int32(prg.curLevel) + 1)
  7822  	prg.savePtr = uint16(int32(prg.savePtr) + 1)
  7823  	prg.curGroup = c
  7824  }
  7825  
  7826  // 275.
  7827  
  7828  // tangle:pos tex.web:5953:3:
  7829  
  7830  // Just before an entry of |eqtb| is changed, the following procedure should
  7831  // be called to update the other data structures properly. It is important
  7832  // to keep in mind that reference counts in |mem| include references from
  7833  // within |save_stack|, so these counts must be handled carefully.
  7834  // \xref[reference counts]
  7835  func (prg *prg) eqDestroy(w memoryWord) { // gets ready to forget |w|
  7836  	var (
  7837  		q halfword // |equiv| field of |w|
  7838  	)
  7839  	switch *(*w.hh()).b0() {
  7840  	case call, longCall, outerCall, longOuterCall:
  7841  		prg.deleteTokenRef(*(*w.hh()).rh())
  7842  	case glueRef:
  7843  		prg.deleteGlueRef(*(*w.hh()).rh())
  7844  	case shapeRef:
  7845  		q = *(*w.hh()).rh() // we need to free a \.[\\parshape] block
  7846  		if int32(q) != 0 {
  7847  			prg.freeNode(q, halfword(int32(*(*prg.mem[q].hh()).lh())+int32(*(*prg.mem[q].hh()).lh())+1))
  7848  		}
  7849  		// such a block is |2n+1| words long, where |n=info(q)|
  7850  	case boxRef:
  7851  		prg.flushNodeList(*(*w.hh()).rh())
  7852  
  7853  	default:
  7854  	}
  7855  }
  7856  
  7857  // 276.
  7858  
  7859  // tangle:pos tex.web:5972:3:
  7860  
  7861  // To save a value of |eqtb[p]| that was established at level |l|, we
  7862  // can use the following subroutine.
  7863  func (prg *prg) eqSave(p halfword, l quarterword) {
  7864  	if int32(prg.savePtr) > int32(prg.maxSaveStack) {
  7865  		prg.maxSaveStack = prg.savePtr
  7866  		if int32(prg.maxSaveStack) > saveSize-6 {
  7867  			prg.overflow(strNumber( /* "save size" */ 541), saveSize)
  7868  		} /* \xref[TeX capacity exceeded save size][\quad save size]  */
  7869  	}
  7870  	if int32(l) == levelZero {
  7871  		*(*prg.saveStack[prg.savePtr].hh()).b0() = byte(restoreZero)
  7872  	} else {
  7873  		prg.saveStack[prg.savePtr] = prg.eqtb[p-1]
  7874  		prg.savePtr = uint16(int32(prg.savePtr) + 1)
  7875  		*(*prg.saveStack[prg.savePtr].hh()).b0() = byte(restoreOldValue)
  7876  	}
  7877  	*(*prg.saveStack[prg.savePtr].hh()).b1() = l
  7878  	*(*prg.saveStack[prg.savePtr].hh()).rh() = p
  7879  	prg.savePtr = uint16(int32(prg.savePtr) + 1)
  7880  }
  7881  
  7882  // 277.
  7883  
  7884  // tangle:pos tex.web:5984:3:
  7885  
  7886  // The procedure |eq_define| defines an |eqtb| entry having specified
  7887  // |eq_type| and |equiv| fields, and saves the former value if appropriate.
  7888  // This procedure is used only for entries in the first four regions of |eqtb|,
  7889  // i.e., only for entries that have |eq_type| and |equiv| fields.
  7890  // After calling this routine, it is safe to put four more entries on
  7891  // |save_stack|, provided that there was room for four more entries before
  7892  // the call, since |eq_save| makes the necessary test.
  7893  func (prg *prg) eqDefine(p halfword, t quarterword, e halfword) {
  7894  	if int32(*(*prg.eqtb[p-1].hh()).b1()) == int32(prg.curLevel) {
  7895  		prg.eqDestroy(prg.eqtb[p-1])
  7896  	} else if int32(prg.curLevel) > levelOne {
  7897  		prg.eqSave(p, *(*prg.eqtb[p-1].hh()).b1())
  7898  	}
  7899  	*(*prg.eqtb[p-1].hh()).b1() = prg.curLevel
  7900  	*(*prg.eqtb[p-1].hh()).b0() = t
  7901  	*(*prg.eqtb[p-1].hh()).rh() = e
  7902  }
  7903  
  7904  // 278.
  7905  
  7906  // tangle:pos tex.web:5999:3:
  7907  
  7908  // The counterpart of |eq_define| for the remaining (fullword) positions in
  7909  // |eqtb| is called |eq_word_define|. Since |xeq_level[p]>=level_one| for all
  7910  // |p|, a `|restore_zero|' will never be used in this case.
  7911  func (prg *prg) eqWordDefine(p halfword, w int32) {
  7912  	if int32(prg.xeqLevel[p-5263]) != int32(prg.curLevel) {
  7913  		prg.eqSave(p, prg.xeqLevel[p-5263])
  7914  		prg.xeqLevel[p-5263] = prg.curLevel
  7915  	}
  7916  	*prg.eqtb[p-1].int() = w
  7917  }
  7918  
  7919  // 279.
  7920  
  7921  // tangle:pos tex.web:6010:3:
  7922  
  7923  // The |eq_define| and |eq_word_define| routines take care of local definitions.
  7924  // \xref[global definitions]
  7925  // Global definitions are done in almost the same way, but there is no need
  7926  // to save old values, and the new value is associated with |level_one|.
  7927  func (prg *prg) geqDefine(p halfword, t quarterword, e halfword) {
  7928  	prg.eqDestroy(prg.eqtb[p-1])
  7929  	*(*prg.eqtb[p-1].hh()).b1() = byte(levelOne)
  7930  	*(*prg.eqtb[p-1].hh()).b0() = t
  7931  	*(*prg.eqtb[p-1].hh()).rh() = e
  7932  }
  7933  
  7934  func (prg *prg) geqWordDefine(p halfword, w int32) {
  7935  	*prg.eqtb[p-1].int() = w
  7936  	prg.xeqLevel[p-5263] = byte(levelOne)
  7937  }
  7938  
  7939  // 280.
  7940  
  7941  // tangle:pos tex.web:6025:3:
  7942  
  7943  // Subroutine |save_for_after| puts a token on the stack for save-keeping.
  7944  func (prg *prg) saveForAfter(t halfword) {
  7945  	if int32(prg.curLevel) > levelOne {
  7946  		if int32(prg.savePtr) > int32(prg.maxSaveStack) {
  7947  			prg.maxSaveStack = prg.savePtr
  7948  			if int32(prg.maxSaveStack) > saveSize-6 {
  7949  				prg.overflow(strNumber( /* "save size" */ 541), saveSize)
  7950  			} /* \xref[TeX capacity exceeded save size][\quad save size]  */
  7951  		}
  7952  		*(*prg.saveStack[prg.savePtr].hh()).b0() = byte(insertToken)
  7953  		*(*prg.saveStack[prg.savePtr].hh()).b1() = byte(levelZero)
  7954  		*(*prg.saveStack[prg.savePtr].hh()).rh() = t
  7955  		prg.savePtr = uint16(int32(prg.savePtr) + 1)
  7956  	}
  7957  } // \2
  7958  func (prg *prg) unsave() {
  7959  	var (
  7960  		p halfword    // position to be restored
  7961  		l quarterword // saved level, if in fullword regions of |eqtb|
  7962  		t halfword    // saved value of |cur_tok|
  7963  	)
  7964  	if int32(prg.curLevel) > levelOne {
  7965  		prg.curLevel = byte(int32(prg.curLevel) - 1)
  7966  
  7967  		// Clear off top level from |save_stack|
  7968  		for true {
  7969  			prg.savePtr = uint16(int32(prg.savePtr) - 1)
  7970  			if int32(*(*prg.saveStack[prg.savePtr].hh()).b0()) == levelBoundary {
  7971  				goto done
  7972  			}
  7973  			p = *(*prg.saveStack[prg.savePtr].hh()).rh()
  7974  			if int32(*(*prg.saveStack[prg.savePtr].hh()).b0()) == insertToken {
  7975  				t = prg.curTok
  7976  				prg.curTok = p
  7977  				prg.backInput()
  7978  				prg.curTok = t
  7979  			} else {
  7980  				if int32(*(*prg.saveStack[prg.savePtr].hh()).b0()) == restoreOldValue {
  7981  					l = *(*prg.saveStack[prg.savePtr].hh()).b1()
  7982  					prg.savePtr = uint16(int32(prg.savePtr) - 1)
  7983  				} else {
  7984  					prg.saveStack[prg.savePtr] = prg.eqtb[undefinedControlSequence-1]
  7985  				}
  7986  
  7987  				// Store \(s)|save_stack[save_ptr]| in |eqtb[p]|, unless |eqtb[p]| holds a global value
  7988  				if int32(p) < intBase {
  7989  					if int32(*(*prg.eqtb[p-1].hh()).b1()) == levelOne {
  7990  						prg.eqDestroy(prg.saveStack[prg.savePtr]) // destroy the saved value
  7991  						//  if eqtb[int_base+ tracing_restores_code].int  >0 then restore_trace(p,["retaining"=]544); [  ]
  7992  
  7993  					} else {
  7994  						prg.eqDestroy(prg.eqtb[p-1])               // destroy the current value
  7995  						prg.eqtb[p-1] = prg.saveStack[prg.savePtr] // restore the saved value
  7996  						//  if eqtb[int_base+ tracing_restores_code].int  >0 then restore_trace(p,["restoring"=]545); [  ]
  7997  
  7998  					}
  7999  				} else if int32(prg.xeqLevel[p-5263]) != levelOne {
  8000  					prg.eqtb[p-1] = prg.saveStack[prg.savePtr]
  8001  					prg.xeqLevel[p-5263] = l
  8002  					//  if eqtb[int_base+ tracing_restores_code].int  >0 then restore_trace(p,["restoring"=]545); [  ]
  8003  
  8004  				} else {
  8005  				}
  8006  			}
  8007  		}
  8008  
  8009  	done:
  8010  		prg.curGroup = *(*prg.saveStack[prg.savePtr].hh()).b1()
  8011  		prg.curBoundary = *(*prg.saveStack[prg.savePtr].hh()).rh()
  8012  	} else {
  8013  		prg.confusion(strNumber( /* "curlevel" */ 543))
  8014  	} // |unsave| is not used when |cur_group=bottom_level|
  8015  	// \xref[this can't happen curlevel][\quad curlevel]
  8016  }
  8017  
  8018  // 288.
  8019  
  8020  // tangle:pos tex.web:6129:3:
  8021  
  8022  // The |prepare_mag| subroutine is called whenever \TeX\ wants to use |mag|
  8023  // for magnification.
  8024  func (prg *prg) prepareMag() {
  8025  	if prg.magSet > 0 && *prg.eqtb[intBase+magCode-1].int() != prg.magSet {
  8026  		{
  8027  			if int32(prg.interaction) == errorStopMode {
  8028  			}
  8029  			prg.printNl(strNumber( /* "! " */ 262))
  8030  			prg.print( /* "Incompatible magnification (" */ 547)
  8031  		}
  8032  		prg.printInt(*prg.eqtb[intBase+magCode-1].int())
  8033  		// \xref[Incompatible magnification]
  8034  		prg.print( /* ");" */ 548)
  8035  		prg.printNl(strNumber( /* " the previous value will be retained" */ 549))
  8036  		{
  8037  			prg.helpPtr = 2
  8038  			prg.helpLine[1] = /* "I can handle only one magnification ratio per job. So I've" */ 550
  8039  			prg.helpLine[0] = /* "reverted to the magnification you used earlier on this run." */ 551
  8040  		}
  8041  
  8042  		prg.intError(prg.magSet)
  8043  		prg.geqWordDefine(halfword(intBase+magCode), prg.magSet) // |mag:=mag_set|
  8044  	}
  8045  	if *prg.eqtb[intBase+magCode-1].int() <= 0 || *prg.eqtb[intBase+magCode-1].int() > 32768 {
  8046  		{
  8047  			if int32(prg.interaction) == errorStopMode {
  8048  			}
  8049  			prg.printNl(strNumber( /* "! " */ 262))
  8050  			prg.print( /* "Illegal magnification has been changed to 1000" */ 552)
  8051  		}
  8052  
  8053  		// \xref[Illegal magnification...]
  8054  		{
  8055  			prg.helpPtr = 1
  8056  			prg.helpLine[0] = /* "The magnification ratio must be between 1 and 32768." */ 553
  8057  		}
  8058  		prg.intError(*prg.eqtb[intBase+magCode-1].int())
  8059  		prg.geqWordDefine(halfword(intBase+magCode), 1000)
  8060  	}
  8061  	prg.magSet = *prg.eqtb[intBase+magCode-1].int()
  8062  }
  8063  
  8064  // 289. \[20] Token lists
  8065  
  8066  // tangle:pos tex.web:6151:22:
  8067  
  8068  // A \TeX\ token is either a character or a control sequence, and it is
  8069  // \xref[token]
  8070  // represented internally in one of two ways: (1)~A character whose ASCII
  8071  // code number is |c| and whose command code is |m| is represented as the
  8072  // number $2^8m+c$; the command code is in the range |1<=m<=14|. (2)~A control
  8073  // sequence whose |eqtb| address is |p| is represented as the number
  8074  // |cs_token_flag+p|. Here |cs_token_flag=$2^[12]-1$| is larger than
  8075  // $2^8m+c$, yet it is small enough that |cs_token_flag+p< max_halfword|;
  8076  // thus, a token fits comfortably in a halfword.
  8077  //
  8078  // A token |t| represents a |left_brace| command if and only if
  8079  // |t<left_brace_limit|; it represents a |right_brace| command if and only if
  8080  // we have |left_brace_limit<=t<right_brace_limit|; and it represents a |match| or
  8081  // |end_match| command if and only if |match_token<=t<=end_match_token|.
  8082  // The following definitions take care of these token-oriented constants
  8083  // and a few others.
  8084  
  8085  // 291.
  8086  
  8087  // tangle:pos tex.web:6187:3:
  8088  
  8089  // A token list is a singly linked list of one-word nodes in |mem|, where
  8090  // each word contains a token and a link. Macro definitions, output-routine
  8091  // definitions, marks, \.[\\write] texts, and a few other things
  8092  // are remembered by \TeX\ in the form
  8093  // of token lists, usually preceded by a node with a reference count in its
  8094  // |token_ref_count| field. The token stored in location |p| is called
  8095  // |info(p)|.
  8096  //
  8097  // Three special commands appear in the token lists of macro definitions.
  8098  // When |m=match|, it means that \TeX\ should scan a parameter
  8099  // for the current macro; when |m=end_match|, it means that parameter
  8100  // matching should end and \TeX\ should start reading the macro text; and
  8101  // when |m=out_param|, it means that \TeX\ should insert parameter
  8102  // number |c| into the text at this point.
  8103  //
  8104  // The enclosing \.[\char'173] and \.[\char'175] characters of a macro
  8105  // definition are omitted, but an output routine
  8106  // will be enclosed in braces.
  8107  //
  8108  // Here is an example macro definition that illustrates these conventions.
  8109  // After \TeX\ processes the text
  8110  // $$\.[\\def\\mac a\#1\#2 \\b \[\#1\\-a \#\#1\#2 \#2\]]$$
  8111  // the definition of \.[\\mac] is represented as a token list containing
  8112  // $$\def\,[\hskip2pt]
  8113  // \vbox[\halign[\hfil#\hfil\cr
  8114  // (reference count), |letter|\,\.a, |match|\,\#, |match|\,\#, |spacer|\,\.\ ,
  8115  // \.[\\b], |end_match|,\cr
  8116  // |out_param|\,1, \.[\\-], |letter|\,\.a, |spacer|\,\.\ , |mac_param|\,\#,
  8117  // |other_char|\,\.1,\cr
  8118  // |out_param|\,2, |spacer|\,\.\ , |out_param|\,2.\cr]]$$
  8119  // The procedure |scan_toks| builds such token lists, and |macro_call|
  8120  // does the parameter matching.
  8121  // \xref[reference counts]
  8122  //
  8123  // Examples such as
  8124  // $$\.[\\def\\m\[\\def\\m\[a\]\ b\]]$$
  8125  // explain why reference counts would be needed even if \TeX\ had no \.[\\let]
  8126  // operation: When the token list for \.[\\m] is being read, the redefinition of
  8127  // \.[\\m] changes the |eqtb| entry before the token list has been fully
  8128  // consumed, so we dare not simply destroy a token list when its
  8129  // control sequence is being redefined.
  8130  //
  8131  // If the parameter-matching part of a definition ends with `\.[\#\[]',
  8132  // the corresponding token list will have `\.\[' just before the `|end_match|'
  8133  // and also at the very end. The first `\.\[' is used to delimit the parameter; the
  8134  // second one keeps the first from disappearing.
  8135  
  8136  // 295.
  8137  
  8138  // tangle:pos tex.web:6313:3:
  8139  
  8140  // Here's the way we sometimes want to display a token list, given a pointer
  8141  // to its reference count; the pointer may be null.
  8142  func (prg *prg) tokenShow(p halfword) {
  8143  	if int32(p) != 0 {
  8144  		prg.showTokenList(int32(*(*prg.mem[p].hh()).rh()), 0, 10000000)
  8145  	}
  8146  }
  8147  
  8148  // 296.
  8149  
  8150  // tangle:pos tex.web:6320:3:
  8151  
  8152  // The |print_meaning| subroutine displays |cur_cmd| and |cur_chr| in
  8153  // symbolic form, including the expansion of a macro or mark.
  8154  func (prg *prg) printMeaning() {
  8155  	prg.printCmdChr(prg.curCmd, prg.curChr)
  8156  	if int32(prg.curCmd) >= call {
  8157  		prg.printChar(asciiCode(':'))
  8158  		prg.printLn()
  8159  		prg.tokenShow(prg.curChr)
  8160  	} else if int32(prg.curCmd) == topBotMark {
  8161  		prg.printChar(asciiCode(':'))
  8162  		prg.printLn()
  8163  		prg.tokenShow(prg.curMark[prg.curChr])
  8164  	}
  8165  }
  8166  
  8167  // 299.
  8168  
  8169  // tangle:pos tex.web:6419:3:
  8170  
  8171  // Here is a procedure that displays the current command.
  8172  func (prg *prg) showCurCmdChr() {
  8173  	prg.beginDiagnostic()
  8174  	prg.printNl(strNumber('{'))
  8175  	if int32(prg.curList.modeField) != int32(prg.shownMode) {
  8176  		prg.printMode(int32(prg.curList.modeField))
  8177  		prg.print( /* ": " */ 568)
  8178  		prg.shownMode = prg.curList.modeField
  8179  	}
  8180  	prg.printCmdChr(prg.curCmd, prg.curChr)
  8181  	prg.printChar(asciiCode('}'))
  8182  	prg.endDiagnostic(false)
  8183  } // \2
  8184  
  8185  func (prg *prg) showContext() {
  8186  	var (
  8187  		oldSetting/* 0..maxSelector */ byte       // saved |selector| setting
  8188  		nn                                  int32 // number of contexts shown so far, less one
  8189  		bottomLine                          bool  // have we reached the final context to be shown?
  8190  
  8191  		// Local variables for formatting calculations
  8192  		i/* 0..bufSize */ uint16           // index into |buffer|
  8193  		j/* 0..bufSize */ uint16           // end of current line in |buffer|
  8194  		l/* 0..halfErrorLine */ byte       // length of descriptive information on line 1
  8195  		m                            int32 // context information gathered for line 2
  8196  		n/* 0..errorLine */ byte           // length of line 1
  8197  		p                            int32 // starting or ending place in |trick_buf|
  8198  		q                            int32 // temporary index
  8199  	)
  8200  	prg.basePtr = prg.inputPtr
  8201  	prg.inputStack[prg.basePtr] = prg.curInput
  8202  	// store current state
  8203  	nn = -1
  8204  	bottomLine = false
  8205  	for true {
  8206  		prg.curInput = prg.inputStack[prg.basePtr] // enter into the context
  8207  		if int32(prg.curInput.stateField) != tokenList {
  8208  			if int32(prg.curInput.nameField) > 17 || int32(prg.basePtr) == 0 {
  8209  				bottomLine = true
  8210  			}
  8211  		}
  8212  		if int32(prg.basePtr) == int32(prg.inputPtr) || bottomLine || nn < *prg.eqtb[intBase+errorContextLinesCode-1].int() {
  8213  			if int32(prg.basePtr) == int32(prg.inputPtr) || int32(prg.curInput.stateField) != tokenList || int32(prg.curInput.indexField) != backedUp || int32(prg.curInput.locField) != 0 {
  8214  				prg.tally = 0 // get ready to count characters
  8215  				oldSetting = prg.selector
  8216  				if int32(prg.curInput.stateField) != tokenList {
  8217  					if int32(prg.curInput.nameField) <= 17 {
  8218  						if int32(prg.curInput.nameField) == 0 {
  8219  							if int32(prg.basePtr) == 0 {
  8220  								prg.printNl(strNumber( /* "<*>" */ 574))
  8221  							} else {
  8222  								prg.printNl(strNumber( /* "<insert> " */ 575))
  8223  							}
  8224  						} else {
  8225  							prg.printNl(strNumber( /* "<read " */ 576))
  8226  							if int32(prg.curInput.nameField) == 17 {
  8227  								prg.printChar(asciiCode('*'))
  8228  							} else {
  8229  								prg.printInt(int32(prg.curInput.nameField) - 1)
  8230  							}
  8231  							// \xref[*\relax]
  8232  							prg.printChar(asciiCode('>'))
  8233  						}
  8234  					} else {
  8235  						prg.printNl(strNumber( /* "l." */ 577))
  8236  						prg.printInt(prg.line)
  8237  					}
  8238  					prg.printChar(asciiCode(' '))
  8239  
  8240  					// Pseudoprint the line
  8241  					{
  8242  						l = byte(prg.tally)
  8243  						prg.tally = 0
  8244  						prg.selector = byte(pseudo)
  8245  						prg.trickCount = 1000000
  8246  					}
  8247  					if int32(prg.buffer[prg.curInput.limitField]) == *prg.eqtb[intBase+endLineCharCode-1].int() {
  8248  						j = prg.curInput.limitField
  8249  					} else {
  8250  						j = uint16(int32(prg.curInput.limitField) + 1)
  8251  					} // determine the effective end of the line
  8252  					if int32(j) > 0 {
  8253  						for ii := int32(prg.curInput.startField); ii <= int32(j)-1; ii++ {
  8254  							i = uint16(ii)
  8255  							_ = i
  8256  							if int32(i) == int32(prg.curInput.locField) {
  8257  								prg.firstCount = prg.tally
  8258  								prg.trickCount = prg.tally + 1 + errorLine - halfErrorLine
  8259  								if prg.trickCount < errorLine {
  8260  									prg.trickCount = errorLine
  8261  								}
  8262  							}
  8263  							prg.print(int32(prg.buffer[i]))
  8264  						}
  8265  					}
  8266  				} else {
  8267  					switch prg.curInput.indexField {
  8268  					case parameter:
  8269  						prg.printNl(strNumber( /* "<argument> " */ 578))
  8270  					case uTemplate, vTemplate:
  8271  						prg.printNl(strNumber( /* "<template> " */ 579))
  8272  					case backedUp:
  8273  						if int32(prg.curInput.locField) == 0 {
  8274  							prg.printNl(strNumber( /* "<recently read> " */ 580))
  8275  						} else {
  8276  							prg.printNl(strNumber( /* "<to be read again> " */ 581))
  8277  						}
  8278  					case inserted:
  8279  						prg.printNl(strNumber( /* "<inserted text> " */ 582))
  8280  					case macro:
  8281  						prg.printLn()
  8282  						prg.printCs(int32(prg.curInput.nameField))
  8283  
  8284  					case outputText:
  8285  						prg.printNl(strNumber( /* "<output> " */ 583))
  8286  					case everyParText:
  8287  						prg.printNl(strNumber( /* "<everypar> " */ 584))
  8288  					case everyMathText:
  8289  						prg.printNl(strNumber( /* "<everymath> " */ 585))
  8290  					case everyDisplayText:
  8291  						prg.printNl(strNumber( /* "<everydisplay> " */ 586))
  8292  					case everyHboxText:
  8293  						prg.printNl(strNumber( /* "<everyhbox> " */ 587))
  8294  					case everyVboxText:
  8295  						prg.printNl(strNumber( /* "<everyvbox> " */ 588))
  8296  					case everyJobText:
  8297  						prg.printNl(strNumber( /* "<everyjob> " */ 589))
  8298  					case everyCrText:
  8299  						prg.printNl(strNumber( /* "<everycr> " */ 590))
  8300  					case markText:
  8301  						prg.printNl(strNumber( /* "<mark> " */ 591))
  8302  					case writeText:
  8303  						prg.printNl(strNumber( /* "<write> " */ 592))
  8304  
  8305  					default:
  8306  						prg.printNl(strNumber('?')) // this should never happen
  8307  					}
  8308  
  8309  					// Pseudoprint the token list
  8310  					{
  8311  						l = byte(prg.tally)
  8312  						prg.tally = 0
  8313  						prg.selector = byte(pseudo)
  8314  						prg.trickCount = 1000000
  8315  					}
  8316  					if int32(prg.curInput.indexField) < macro {
  8317  						prg.showTokenList(int32(prg.curInput.startField), int32(prg.curInput.locField), 100000)
  8318  					} else {
  8319  						prg.showTokenList(int32(*(*prg.mem[prg.curInput.startField].hh()).rh()), int32(prg.curInput.locField), 100000)
  8320  					}
  8321  				}
  8322  				prg.selector = oldSetting // stop pseudoprinting
  8323  
  8324  				// Print two lines using the tricky pseudoprinted information
  8325  				if prg.trickCount == 1000000 {
  8326  					prg.firstCount = prg.tally
  8327  					prg.trickCount = prg.tally + 1 + errorLine - halfErrorLine
  8328  					if prg.trickCount < errorLine {
  8329  						prg.trickCount = errorLine
  8330  					}
  8331  				}
  8332  				// |set_trick_count| must be performed
  8333  				if prg.tally < prg.trickCount {
  8334  					m = prg.tally - prg.firstCount
  8335  				} else {
  8336  					m = prg.trickCount - prg.firstCount
  8337  				} // context on line 2
  8338  				if int32(l)+prg.firstCount <= halfErrorLine {
  8339  					p = 0
  8340  					n = byte(int32(l) + prg.firstCount)
  8341  				} else {
  8342  					prg.print( /* "..." */ 277)
  8343  					p = int32(l) + prg.firstCount - halfErrorLine + 3
  8344  					n = byte(halfErrorLine)
  8345  				}
  8346  				for ii := p; ii <= prg.firstCount-1; ii++ {
  8347  					q = ii
  8348  					_ = q
  8349  					prg.printChar(prg.trickBuf[q%errorLine])
  8350  				}
  8351  				prg.printLn()
  8352  				for ii := int32(1); ii <= int32(n); ii++ {
  8353  					q = ii
  8354  					_ = q
  8355  					prg.printChar(asciiCode(' '))
  8356  				} // print |n| spaces to begin line~2
  8357  				if m+int32(n) <= errorLine {
  8358  					p = prg.firstCount + m
  8359  				} else {
  8360  					p = prg.firstCount + (errorLine - int32(n) - 3)
  8361  				}
  8362  				for ii := prg.firstCount; ii <= p-1; ii++ {
  8363  					q = ii
  8364  					_ = q
  8365  					prg.printChar(prg.trickBuf[q%errorLine])
  8366  				}
  8367  				if m+int32(n) > errorLine {
  8368  					prg.print( /* "..." */ 277)
  8369  				}
  8370  				nn = nn + 1
  8371  			}
  8372  		} else if nn == *prg.eqtb[intBase+errorContextLinesCode-1].int() {
  8373  			prg.printNl(strNumber( /* "..." */ 277))
  8374  			nn = nn + 1 // omitted if |error_context_lines<0|
  8375  		}
  8376  		if bottomLine {
  8377  			goto done
  8378  		}
  8379  		prg.basePtr = byte(int32(prg.basePtr) - 1)
  8380  	}
  8381  
  8382  done:
  8383  	prg.curInput = prg.inputStack[prg.inputPtr] // restore original state
  8384  }
  8385  
  8386  // 316.
  8387  
  8388  // tangle:pos tex.web:6886:3:
  8389  
  8390  // The following code sets up the print routines so that they will gather
  8391  // the desired information.
  8392  
  8393  // 321. \[23] Maintaining the input stacks
  8394  
  8395  // tangle:pos tex.web:6942:39:
  8396  
  8397  // The following subroutines change the input status in commonly needed ways.
  8398  //
  8399  // First comes |push_input|, which stores the current state and creates a
  8400  // new level (having, initially, the same properties as the old).
  8401  
  8402  // 322.
  8403  
  8404  // tangle:pos tex.web:6958:3:
  8405  
  8406  // And of course what goes up must come down.
  8407  
  8408  // 323.
  8409  
  8410  // tangle:pos tex.web:6964:3:
  8411  
  8412  // Here is a procedure that starts a new level of token-list input, given
  8413  // a token list |p| and its type |t|. If |t=macro|, the calling routine should
  8414  // set |name| and |loc|.
  8415  func (prg *prg) beginTokenList(p halfword, t quarterword) {
  8416  	{
  8417  		if int32(prg.inputPtr) > int32(prg.maxInStack) {
  8418  			prg.maxInStack = prg.inputPtr
  8419  			if int32(prg.inputPtr) == stackSize {
  8420  				prg.overflow(strNumber( /* "input stack size" */ 593), stackSize)
  8421  			} /* \xref[TeX capacity exceeded input stack size][\quad input stack size]  */
  8422  		}
  8423  		prg.inputStack[prg.inputPtr] = prg.curInput
  8424  		prg.inputPtr = byte(int32(prg.inputPtr) + 1)
  8425  	}
  8426  	prg.curInput.stateField = byte(tokenList)
  8427  	prg.curInput.startField = p
  8428  	prg.curInput.indexField = t
  8429  	if int32(t) >= macro {
  8430  		*(*prg.mem[p].hh()).lh() = uint16(int32(*(*prg.mem[p].hh()).lh()) + 1)
  8431  		if int32(t) == macro {
  8432  			prg.curInput.limitField = uint16(prg.paramPtr)
  8433  		} else {
  8434  			prg.curInput.locField = *(*prg.mem[p].hh()).rh()
  8435  			if *prg.eqtb[intBase+tracingMacrosCode-1].int() > 1 {
  8436  				prg.beginDiagnostic()
  8437  				prg.printNl(strNumber( /* "" */ 338))
  8438  				switch t {
  8439  				case markText:
  8440  					prg.printEsc(strNumber( /* "mark" */ 351))
  8441  				case writeText:
  8442  					prg.printEsc(strNumber( /* "write" */ 594))
  8443  
  8444  				default:
  8445  					prg.printCmdChr(quarterword(assignToks), halfword(int32(t)-outputText+outputRoutineLoc))
  8446  				}
  8447  
  8448  				prg.print( /* "->" */ 556)
  8449  				prg.tokenShow(p)
  8450  				prg.endDiagnostic(false)
  8451  			}
  8452  		}
  8453  	} else {
  8454  		prg.curInput.locField = p
  8455  	}
  8456  }
  8457  
  8458  // 324.
  8459  
  8460  // tangle:pos tex.web:6991:3:
  8461  
  8462  // When a token list has been fully scanned, the following computations
  8463  // should be done as we leave that level of input. The |token_type| tends
  8464  // to be equal to either |backed_up| or |inserted| about 2/3 of the time.
  8465  // \xref[inner loop]
  8466  func (prg *prg) endTokenList() {
  8467  	if int32(prg.curInput.indexField) >= backedUp {
  8468  		if int32(prg.curInput.indexField) <= inserted {
  8469  			prg.flushList(prg.curInput.startField)
  8470  		} else {
  8471  			prg.deleteTokenRef(prg.curInput.startField) // update reference count
  8472  			if int32(prg.curInput.indexField) == macro {
  8473  				for int32(prg.paramPtr) > int32(prg.curInput.limitField) {
  8474  					prg.paramPtr = byte(int32(prg.paramPtr) - 1)
  8475  					prg.flushList(prg.paramStack[prg.paramPtr])
  8476  				}
  8477  			}
  8478  		}
  8479  	} else if int32(prg.curInput.indexField) == uTemplate {
  8480  		if prg.alignState > 500000 {
  8481  			prg.alignState = 0
  8482  		} else {
  8483  			prg.fatalError(strNumber( /* "(interwoven alignment preambles are not allowed)" */ 595))
  8484  		}
  8485  	}
  8486  	// \xref[interwoven alignment preambles...]
  8487  	//
  8488  	{
  8489  		prg.inputPtr = byte(int32(prg.inputPtr) - 1)
  8490  		prg.curInput = prg.inputStack[prg.inputPtr]
  8491  	}
  8492  	{
  8493  		if prg.interrupt != 0 {
  8494  			prg.pauseForInstructions()
  8495  		}
  8496  	}
  8497  }
  8498  
  8499  // 281.
  8500  
  8501  // tangle:pos tex.web:6035:3:
  8502  
  8503  // The |unsave| routine goes the other way, taking items off of |save_stack|.
  8504  // This routine takes care of restoration when a level ends; everything
  8505  // belonging to the topmost group is cleared off of the save stack.
  8506  // \4
  8507  // Declare the procedure called |restore_trace|
  8508  //  procedure restore_trace( p:halfword ; s:str_number);
  8509  //   [|eqtb[p]| has just been restored or retained]
  8510  // begin begin_diagnostic; print_char(["["=]123); print(s); print_char([" "=]32);
  8511  // show_eqtb(p); print_char(["]"=]125);
  8512  // end_diagnostic(false);
  8513  // end;
  8514  // [  ]
  8515  
  8516  func (prg *prg) backInput() { // undoes one token of input
  8517  	var (
  8518  		p halfword // a token list of length one
  8519  	)
  8520  	for int32(prg.curInput.stateField) == tokenList && int32(prg.curInput.locField) == 0 && int32(prg.curInput.indexField) != vTemplate {
  8521  		prg.endTokenList()
  8522  	} // conserve stack space
  8523  	p = prg.getAvail()
  8524  	*(*prg.mem[p].hh()).lh() = prg.curTok
  8525  	if int32(prg.curTok) < rightBraceLimit {
  8526  		if int32(prg.curTok) < leftBraceLimit {
  8527  			prg.alignState = prg.alignState - 1
  8528  		} else {
  8529  			prg.alignState = prg.alignState + 1
  8530  		}
  8531  	}
  8532  	/*   */ {
  8533  		if int32(prg.inputPtr) > int32(prg.maxInStack) {
  8534  			prg.maxInStack = prg.inputPtr
  8535  			if int32(prg.inputPtr) == stackSize {
  8536  				prg.overflow(strNumber( /* "input stack size" */ 593), stackSize)
  8537  			} /* \xref[TeX capacity exceeded input stack size][\quad input stack size]  */
  8538  		}
  8539  		prg.inputStack[prg.inputPtr] = prg.curInput
  8540  		prg.inputPtr = byte(int32(prg.inputPtr) + 1)
  8541  	}
  8542  	prg.curInput.stateField = byte(tokenList)
  8543  	prg.curInput.startField = p
  8544  	prg.curInput.indexField = byte(backedUp)
  8545  	prg.curInput.locField = p // that was |back_list(p)|, without procedure overhead
  8546  }
  8547  
  8548  // 327.
  8549  
  8550  // tangle:pos tex.web:7039:3:
  8551  
  8552  // The |back_error| routine is used when we want to replace an offending token
  8553  // just before issuing an error message. This routine, like |back_input|,
  8554  // requires that |cur_tok| has been set. We disable interrupts during the
  8555  // call of |back_input| so that the help message won't be lost.
  8556  func (prg *prg) backError() {
  8557  	prg.okToInterrupt = false
  8558  	prg.backInput()
  8559  	prg.okToInterrupt = true
  8560  	prg.error1()
  8561  }
  8562  
  8563  func (prg *prg) insError() {
  8564  	prg.okToInterrupt = false
  8565  	prg.backInput()
  8566  	prg.curInput.indexField = byte(inserted)
  8567  	prg.okToInterrupt = true
  8568  	prg.error1()
  8569  } // \2
  8570  
  8571  func (prg *prg) beginFileReading() {
  8572  	if int32(prg.inOpen) == maxInOpen {
  8573  		prg.overflow(strNumber( /* "text input levels" */ 596), maxInOpen)
  8574  	}
  8575  	// \xref[TeX capacity exceeded text input levels][\quad text input levels]
  8576  	if int32(prg.first) == bufSize {
  8577  		prg.overflow(strNumber( /* "buffer size" */ 256), bufSize)
  8578  	}
  8579  	// \xref[TeX capacity exceeded buffer size][\quad buffer size]
  8580  	prg.inOpen = byte(int32(prg.inOpen) + 1) /*   */
  8581  	{
  8582  		if int32(prg.inputPtr) > int32(prg.maxInStack) {
  8583  			prg.maxInStack = prg.inputPtr
  8584  			if int32(prg.inputPtr) == stackSize {
  8585  				prg.overflow(strNumber( /* "input stack size" */ 593), stackSize)
  8586  			} /* \xref[TeX capacity exceeded input stack size][\quad input stack size]  */
  8587  		}
  8588  		prg.inputStack[prg.inputPtr] = prg.curInput
  8589  		prg.inputPtr = byte(int32(prg.inputPtr) + 1)
  8590  	}
  8591  	prg.curInput.indexField = prg.inOpen
  8592  	prg.lineStack[prg.curInput.indexField-1] = prg.line
  8593  	prg.curInput.startField = prg.first
  8594  	prg.curInput.stateField = byte(midLine)
  8595  	prg.curInput.nameField = 0 // |terminal_input| is now |true|
  8596  }
  8597  
  8598  // 329.
  8599  
  8600  // tangle:pos tex.web:7069:3:
  8601  
  8602  // Conversely, the variables must be downdated when such a level of input
  8603  // is finished:
  8604  func (prg *prg) endFileReading() {
  8605  	prg.first = prg.curInput.startField
  8606  	prg.line = prg.lineStack[prg.curInput.indexField-1]
  8607  	if int32(prg.curInput.nameField) > 17 {
  8608  		prg.aClose(prg.inputFile[prg.curInput.indexField-1])
  8609  	} // forget it
  8610  	//
  8611  	{
  8612  		prg.inputPtr = byte(int32(prg.inputPtr) - 1)
  8613  		prg.curInput = prg.inputStack[prg.inputPtr]
  8614  	}
  8615  	prg.inOpen = byte(int32(prg.inOpen) - 1)
  8616  } // \2
  8617  
  8618  func (prg *prg) clearForErrorPrompt() {
  8619  	for int32(prg.curInput.stateField) != tokenList && int32(prg.curInput.nameField) == 0 && int32(prg.inputPtr) > 0 && int32(prg.curInput.locField) > int32(prg.curInput.limitField) {
  8620  		prg.endFileReading()
  8621  	}
  8622  	prg.printLn()
  8623  }
  8624  
  8625  // 332. \[24] Getting the next token
  8626  
  8627  // tangle:pos tex.web:7104:33:
  8628  
  8629  // The heart of \TeX's input mechanism is the |get_next| procedure, which
  8630  // we shall develop in the next few sections of the program. Perhaps we
  8631  // shouldn't actually call it the ``heart,'' however, because it really acts
  8632  // as \TeX's eyes and mouth, reading the source files and gobbling them up.
  8633  // And it also helps \TeX\ to regurgitate stored token lists that are to be
  8634  // processed again.
  8635  // \xref[eyes and mouth]
  8636  //
  8637  // The main duty of |get_next| is to input one token and to set |cur_cmd|
  8638  // and |cur_chr| to that token's command code and modifier. Furthermore, if
  8639  // the input token is a control sequence, the |eqtb| location of that control
  8640  // sequence is stored in |cur_cs|; otherwise |cur_cs| is set to zero.
  8641  //
  8642  // Underlying this simple description is a certain amount of complexity
  8643  // because of all the cases that need to be handled.
  8644  // However, the inner loop of |get_next| is reasonably short and fast.
  8645  //
  8646  // When |get_next| is asked to get the next token of a \.[\\read] line,
  8647  // it sets |cur_cmd=cur_chr=cur_cs=0| in the case that no more tokens
  8648  // appear on that line. (There might not be any tokens at all, if the
  8649  // |end_line_char| has |ignore| as its catcode.)
  8650  
  8651  // 336.
  8652  
  8653  // tangle:pos tex.web:7144:3:
  8654  
  8655  // Before getting into |get_next|, let's consider the subroutine that
  8656  // is called when an `\.[\\outer]' control sequence has been scanned or
  8657  // when the end of a file has been reached. These two cases are distinguished
  8658  // by |cur_cs|, which is zero at the end of a file.
  8659  func (prg *prg) checkOuterValidity() {
  8660  	var (
  8661  		p halfword // points to inserted token list
  8662  		q halfword // auxiliary pointer
  8663  	)
  8664  	if int32(prg.scannerStatus) != normal {
  8665  		prg.deletionsAllowed = false
  8666  
  8667  		// Back up an outer control sequence so that it can be reread
  8668  		if int32(prg.curCs) != 0 {
  8669  			if int32(prg.curInput.stateField) == tokenList || int32(prg.curInput.nameField) < 1 || int32(prg.curInput.nameField) > 17 {
  8670  				p = prg.getAvail()
  8671  				*(*prg.mem[p].hh()).lh() = uint16(07777 + int32(prg.curCs))
  8672  				prg.beginTokenList(p, quarterword(backedUp)) // prepare to read the control sequence again
  8673  			}
  8674  			prg.curCmd = byte(spacer)
  8675  			prg.curChr = ' ' // replace it by a space
  8676  		}
  8677  		if int32(prg.scannerStatus) > skipping {
  8678  			prg.runaway() // print a definition, argument, or preamble
  8679  			if int32(prg.curCs) == 0 {
  8680  				if int32(prg.interaction) == errorStopMode {
  8681  				}
  8682  				prg.printNl(strNumber( /* "! " */ 262))
  8683  				prg.print( /* "File ended" */ 604)
  8684  			} else {
  8685  				prg.curCs = 0
  8686  				{
  8687  					if int32(prg.interaction) == errorStopMode {
  8688  					}
  8689  					prg.printNl(strNumber( /* "! " */ 262))
  8690  					prg.print( /* "Forbidden control sequence found" */ 605)
  8691  				}
  8692  				// \xref[Forbidden control sequence...]
  8693  			}
  8694  			prg.print( /* " while scanning " */ 606)
  8695  
  8696  			// Print either `\.[definition]' or `\.[use]' or `\.[preamble]' or `\.[text]', and insert tokens that should lead to recovery
  8697  			p = prg.getAvail()
  8698  			switch prg.scannerStatus {
  8699  			case defining:
  8700  				prg.print( /* "definition" */ 570)
  8701  				*(*prg.mem[p].hh()).lh() = uint16(rightBraceToken + '}')
  8702  
  8703  			case matching:
  8704  				prg.print( /* "use" */ 612)
  8705  				*(*prg.mem[p].hh()).lh() = prg.parToken
  8706  				prg.longState = byte(outerCall)
  8707  
  8708  			case aligning:
  8709  				prg.print( /* "preamble" */ 572)
  8710  				*(*prg.mem[p].hh()).lh() = uint16(rightBraceToken + '}')
  8711  				q = p
  8712  				p = prg.getAvail()
  8713  				*(*prg.mem[p].hh()).rh() = q
  8714  				*(*prg.mem[p].hh()).lh() = uint16(07777 + frozenCr)
  8715  				prg.alignState = -1000000
  8716  
  8717  			case absorbing:
  8718  				prg.print( /* "text" */ 573)
  8719  				*(*prg.mem[p].hh()).lh() = uint16(rightBraceToken + '}')
  8720  
  8721  			} // there are no other cases
  8722  			prg.beginTokenList(p, quarterword(inserted))
  8723  			prg.print( /* " of " */ 607)
  8724  			prg.sprintCs(prg.warningIndex)
  8725  			{
  8726  				prg.helpPtr = 4
  8727  				prg.helpLine[3] = /* "I suspect you have forgotten a `]', causing me" */ 608
  8728  				prg.helpLine[2] = /* "to read past where you wanted me to stop." */ 609
  8729  				prg.helpLine[1] = /* "I'll try to recover; but if the error is serious," */ 610
  8730  				prg.helpLine[0] = /* "you'd better type `E' or `X' now and fix your file." */ 611
  8731  			}
  8732  
  8733  			prg.error1()
  8734  		} else {
  8735  			{
  8736  				if int32(prg.interaction) == errorStopMode {
  8737  				}
  8738  				prg.printNl(strNumber( /* "! " */ 262))
  8739  				prg.print( /* "Incomplete " */ 598)
  8740  			}
  8741  			prg.printCmdChr(quarterword(ifTest), halfword(prg.curIf))
  8742  			// \xref[Incomplete \\if...]
  8743  			prg.print( /* "; all text was ignored after line " */ 599)
  8744  			prg.printInt(prg.skipLine)
  8745  			{
  8746  				prg.helpPtr = 3
  8747  				prg.helpLine[2] = /* "A forbidden control sequence occurred in skipped text." */ 600
  8748  				prg.helpLine[1] = /* "This kind of error happens when you say `\\if...' and forget" */ 601
  8749  				prg.helpLine[0] = /* "the matching `\\fi'. I've inserted a `\\fi'; this might work." */ 602
  8750  			}
  8751  			if int32(prg.curCs) != 0 {
  8752  				prg.curCs = 0
  8753  			} else {
  8754  				prg.helpLine[2] =
  8755  					/* "The file ended while I was skipping conditional text." */ 603
  8756  			}
  8757  			prg.curTok = uint16(07777 + frozenFi)
  8758  			prg.insError()
  8759  		}
  8760  		prg.deletionsAllowed = true
  8761  	}
  8762  }
  8763  
  8764  // 341.
  8765  
  8766  // tangle:pos tex.web:7230:3:
  8767  
  8768  // Now we're ready to take the plunge into |get_next| itself. Parts of
  8769  // this routine are executed more often than any other instructions of \TeX.
  8770  // \xref[mastication]\xref[inner loop]
  8771  func (prg *prg) getNext() { // go here when the next input token has been got
  8772  	var (
  8773  		k/* 0..bufSize */ uint16               // an index into |buffer|
  8774  		t                            halfword  // a token
  8775  		cat/* 0..maxCharCode */ byte           // |cat_code(cur_chr)|, usually
  8776  		c, cc                        asciiCode // constituents of a possible expanded code
  8777  		d/* 2..3 */ byte                       // number of excess characters in an expanded code
  8778  	)
  8779  restart:
  8780  	prg.curCs = 0
  8781  	if int32(prg.curInput.stateField) != tokenList {
  8782  	switch1:
  8783  		if int32(prg.curInput.locField) <= int32(prg.curInput.limitField) {
  8784  			prg.curChr = uint16(prg.buffer[prg.curInput.locField])
  8785  			prg.curInput.locField = uint16(int32(prg.curInput.locField) + 1)
  8786  
  8787  		reswitch:
  8788  			prg.curCmd = byte(*(*prg.eqtb[catCodeBase+int32(prg.curChr)-1].hh()).rh())
  8789  
  8790  			// Change state if necessary, and |goto switch| if the current character should be ignored, or |goto reswitch| if the current character changes to another
  8791  			switch int32(prg.curInput.stateField) + int32(prg.curCmd) {
  8792  			case midLine + 9, skipBlanks + 9, newLine + 9, skipBlanks + 10,
  8793  				newLine + 10:
  8794  				goto switch1
  8795  			case midLine + 0, skipBlanks + 0, newLine + 0:
  8796  				// Scan a control sequence and set |state:=skip_blanks| or |mid_line|
  8797  				if int32(prg.curInput.locField) > int32(prg.curInput.limitField) {
  8798  					prg.curCs = uint16(nullCs)
  8799  				} else {
  8800  				startCs:
  8801  					k = prg.curInput.locField
  8802  					prg.curChr = uint16(prg.buffer[k])
  8803  					cat = byte(*(*prg.eqtb[catCodeBase+int32(prg.curChr)-1].hh()).rh())
  8804  					k = uint16(int32(k) + 1)
  8805  					if int32(cat) == letter {
  8806  						prg.curInput.stateField = byte(skipBlanks)
  8807  					} else if int32(cat) == spacer {
  8808  						prg.curInput.stateField = byte(skipBlanks)
  8809  					} else {
  8810  						prg.curInput.stateField = byte(midLine)
  8811  					}
  8812  					if int32(cat) == letter && int32(k) <= int32(prg.curInput.limitField) {
  8813  						for {
  8814  							prg.curChr = uint16(prg.buffer[k])
  8815  							cat = byte(*(*prg.eqtb[catCodeBase+int32(prg.curChr)-1].hh()).rh())
  8816  							k = uint16(int32(k) + 1)
  8817  							if int32(cat) != letter || int32(k) > int32(prg.curInput.limitField) {
  8818  								break
  8819  							}
  8820  						}
  8821  
  8822  						// If an expanded...
  8823  						{
  8824  							if int32(prg.buffer[k]) == int32(prg.curChr) {
  8825  								if int32(cat) == supMark {
  8826  									if int32(k) < int32(prg.curInput.limitField) {
  8827  										c = prg.buffer[int32(k)+1]
  8828  										if int32(c) < 0200 {
  8829  											d = 2
  8830  											if int32(c) >= '0' && int32(c) <= '9' || int32(c) >= 'a' && int32(c) <= 'f' {
  8831  												if int32(k)+2 <= int32(prg.curInput.limitField) {
  8832  													cc = prg.buffer[int32(k)+2]
  8833  													if int32(cc) >= '0' && int32(cc) <= '9' || int32(cc) >= 'a' && int32(cc) <= 'f' {
  8834  														d = byte(int32(d) + 1)
  8835  													}
  8836  												}
  8837  											}
  8838  											if int32(d) > 2 {
  8839  												if int32(c) <= '9' {
  8840  													prg.curChr = uint16(int32(c) - '0')
  8841  												} else {
  8842  													prg.curChr = uint16(int32(c) - 'a' + 10)
  8843  												}
  8844  												if int32(cc) <= '9' {
  8845  													prg.curChr = uint16(16*int32(prg.curChr) + int32(cc) - '0')
  8846  												} else {
  8847  													prg.curChr = uint16(16*int32(prg.curChr) + int32(cc) - 'a' + 10)
  8848  												}
  8849  												prg.buffer[int32(k)-1] = byte(prg.curChr)
  8850  											} else if int32(c) < 0100 {
  8851  												prg.buffer[int32(k)-1] = byte(int32(c) + 0100)
  8852  											} else {
  8853  												prg.buffer[int32(k)-1] = byte(int32(c) - 0100)
  8854  											}
  8855  											prg.curInput.limitField = uint16(int32(prg.curInput.limitField) - int32(d))
  8856  											prg.first = uint16(int32(prg.first) - int32(d))
  8857  											for int32(k) <= int32(prg.curInput.limitField) {
  8858  												prg.buffer[k] = prg.buffer[int32(k)+int32(d)]
  8859  												k = uint16(int32(k) + 1)
  8860  											}
  8861  
  8862  											goto startCs
  8863  										}
  8864  									}
  8865  								}
  8866  							}
  8867  						}
  8868  						if int32(cat) != letter {
  8869  							k = uint16(int32(k) - 1)
  8870  						}
  8871  						// now |k| points to first nonletter
  8872  						if int32(k) > int32(prg.curInput.locField)+1 {
  8873  							prg.curCs = prg.idLookup(int32(prg.curInput.locField), int32(k)-int32(prg.curInput.locField))
  8874  							prg.curInput.locField = k
  8875  							goto found
  8876  						}
  8877  					} else {
  8878  						// If an expanded code is present, reduce it and |goto start_cs|
  8879  						if int32(prg.buffer[k]) == int32(prg.curChr) {
  8880  							if int32(cat) == supMark {
  8881  								if int32(k) < int32(prg.curInput.limitField) {
  8882  									c = prg.buffer[int32(k)+1]
  8883  									if int32(c) < 0200 {
  8884  										d = 2
  8885  										if int32(c) >= '0' && int32(c) <= '9' || int32(c) >= 'a' && int32(c) <= 'f' {
  8886  											if int32(k)+2 <= int32(prg.curInput.limitField) {
  8887  												cc = prg.buffer[int32(k)+2]
  8888  												if int32(cc) >= '0' && int32(cc) <= '9' || int32(cc) >= 'a' && int32(cc) <= 'f' {
  8889  													d = byte(int32(d) + 1)
  8890  												}
  8891  											}
  8892  										}
  8893  										if int32(d) > 2 {
  8894  											if int32(c) <= '9' {
  8895  												prg.curChr = uint16(int32(c) - '0')
  8896  											} else {
  8897  												prg.curChr = uint16(int32(c) - 'a' + 10)
  8898  											}
  8899  											if int32(cc) <= '9' {
  8900  												prg.curChr = uint16(16*int32(prg.curChr) + int32(cc) - '0')
  8901  											} else {
  8902  												prg.curChr = uint16(16*int32(prg.curChr) + int32(cc) - 'a' + 10)
  8903  											}
  8904  											prg.buffer[int32(k)-1] = byte(prg.curChr)
  8905  										} else if int32(c) < 0100 {
  8906  											prg.buffer[int32(k)-1] = byte(int32(c) + 0100)
  8907  										} else {
  8908  											prg.buffer[int32(k)-1] = byte(int32(c) - 0100)
  8909  										}
  8910  										prg.curInput.limitField = uint16(int32(prg.curInput.limitField) - int32(d))
  8911  										prg.first = uint16(int32(prg.first) - int32(d))
  8912  										for int32(k) <= int32(prg.curInput.limitField) {
  8913  											prg.buffer[k] = prg.buffer[int32(k)+int32(d)]
  8914  											k = uint16(int32(k) + 1)
  8915  										}
  8916  
  8917  										goto startCs
  8918  									}
  8919  								}
  8920  							}
  8921  						}
  8922  					}
  8923  					prg.curCs = uint16(singleBase + int32(prg.buffer[prg.curInput.locField]))
  8924  					prg.curInput.locField = uint16(int32(prg.curInput.locField) + 1)
  8925  				}
  8926  
  8927  			found:
  8928  				prg.curCmd = *(*prg.eqtb[prg.curCs-1].hh()).b0()
  8929  				prg.curChr = *(*prg.eqtb[prg.curCs-1].hh()).rh()
  8930  				if int32(prg.curCmd) >= outerCall {
  8931  					prg.checkOuterValidity()
  8932  				}
  8933  
  8934  			case midLine + 13, skipBlanks + 13, newLine + 13:
  8935  				// Process an active-character control sequence and set |state:=mid_line|
  8936  				prg.curCs = uint16(int32(prg.curChr) + activeBase)
  8937  				prg.curCmd = *(*prg.eqtb[prg.curCs-1].hh()).b0()
  8938  				prg.curChr = *(*prg.eqtb[prg.curCs-1].hh()).rh()
  8939  				prg.curInput.stateField = byte(midLine)
  8940  				if int32(prg.curCmd) >= outerCall {
  8941  					prg.checkOuterValidity()
  8942  				}
  8943  
  8944  			case midLine + 7, skipBlanks + 7, newLine + 7:
  8945  				// If this |sup_mark| starts an expanded character like~\.[\^\^A] or~\.[\^\^df], then |goto reswitch|, otherwise set |state:=mid_line|
  8946  				if int32(prg.curChr) == int32(prg.buffer[prg.curInput.locField]) {
  8947  					if int32(prg.curInput.locField) < int32(prg.curInput.limitField) {
  8948  						c = prg.buffer[int32(prg.curInput.locField)+1]
  8949  						if int32(c) < 0200 {
  8950  							prg.curInput.locField = uint16(int32(prg.curInput.locField) + 2)
  8951  							if int32(c) >= '0' && int32(c) <= '9' || int32(c) >= 'a' && int32(c) <= 'f' {
  8952  								if int32(prg.curInput.locField) <= int32(prg.curInput.limitField) {
  8953  									cc = prg.buffer[prg.curInput.locField]
  8954  									if int32(cc) >= '0' && int32(cc) <= '9' || int32(cc) >= 'a' && int32(cc) <= 'f' {
  8955  										prg.curInput.locField = uint16(int32(prg.curInput.locField) + 1)
  8956  										if int32(c) <= '9' {
  8957  											prg.curChr = uint16(int32(c) - '0')
  8958  										} else {
  8959  											prg.curChr = uint16(int32(c) - 'a' + 10)
  8960  										}
  8961  										if int32(cc) <= '9' {
  8962  											prg.curChr = uint16(16*int32(prg.curChr) + int32(cc) - '0')
  8963  										} else {
  8964  											prg.curChr = uint16(16*int32(prg.curChr) + int32(cc) - 'a' + 10)
  8965  										}
  8966  										goto reswitch
  8967  									}
  8968  								}
  8969  							}
  8970  							if int32(c) < 0100 {
  8971  								prg.curChr = uint16(int32(c) + 0100)
  8972  							} else {
  8973  								prg.curChr = uint16(int32(c) - 0100)
  8974  							}
  8975  
  8976  							goto reswitch
  8977  						}
  8978  					}
  8979  				}
  8980  				prg.curInput.stateField = byte(midLine)
  8981  
  8982  			case midLine + 15, skipBlanks + 15, newLine + 15:
  8983  				// Decry the invalid character and |goto restart|
  8984  				{
  8985  					if int32(prg.interaction) == errorStopMode {
  8986  					}
  8987  					prg.printNl(strNumber( /* "! " */ 262))
  8988  					prg.print( /* "Text line contains an invalid character" */ 613)
  8989  				}
  8990  				// \xref[Text line contains...]
  8991  				{
  8992  					prg.helpPtr = 2
  8993  					prg.helpLine[1] = /* "A funny symbol that I can't read has just been input." */ 614
  8994  					prg.helpLine[0] = /* "Continue, and I'll forget that it ever happened." */ 615
  8995  				}
  8996  
  8997  				prg.deletionsAllowed = false
  8998  				prg.error1()
  8999  				prg.deletionsAllowed = true
  9000  
  9001  				goto restart
  9002  
  9003  			// \4
  9004  			// Handle situations involving spaces, braces, changes of state
  9005  			case midLine + 10:
  9006  				// Enter |skip_blanks| state, emit a space
  9007  				prg.curInput.stateField = byte(skipBlanks)
  9008  				prg.curChr = ' '
  9009  
  9010  			case midLine + 5:
  9011  				// Finish line, emit a space
  9012  				prg.curInput.locField = uint16(int32(prg.curInput.limitField) + 1)
  9013  				prg.curCmd = byte(spacer)
  9014  				prg.curChr = ' '
  9015  
  9016  			case skipBlanks + 5, midLine + 14, skipBlanks + 14, newLine + 14:
  9017  
  9018  				// Finish line, |goto switch|
  9019  				prg.curInput.locField = uint16(int32(prg.curInput.limitField) + 1)
  9020  				goto switch1
  9021  
  9022  			case newLine + 5:
  9023  				// Finish line, emit a \.[\\par]
  9024  				prg.curInput.locField = uint16(int32(prg.curInput.limitField) + 1)
  9025  				prg.curCs = prg.parLoc
  9026  				prg.curCmd = *(*prg.eqtb[prg.curCs-1].hh()).b0()
  9027  				prg.curChr = *(*prg.eqtb[prg.curCs-1].hh()).rh()
  9028  				if int32(prg.curCmd) >= outerCall {
  9029  					prg.checkOuterValidity()
  9030  				}
  9031  
  9032  			case midLine + 1:
  9033  				prg.alignState = prg.alignState + 1
  9034  			case skipBlanks + 1, newLine + 1:
  9035  				prg.curInput.stateField = byte(midLine)
  9036  				prg.alignState = prg.alignState + 1
  9037  
  9038  			case midLine + 2:
  9039  				prg.alignState = prg.alignState - 1
  9040  			case skipBlanks + 2, newLine + 2:
  9041  				prg.curInput.stateField = byte(midLine)
  9042  				prg.alignState = prg.alignState - 1
  9043  
  9044  			case skipBlanks + 3, skipBlanks + 4, skipBlanks + 6, skipBlanks + 8,
  9045  				skipBlanks + 11, skipBlanks + 12, newLine + 3, newLine + 4,
  9046  				newLine + 6, newLine + 8, newLine + 11, newLine + 12:
  9047  				prg.curInput.stateField = byte(midLine)
  9048  
  9049  			default:
  9050  			}
  9051  		} else {
  9052  			prg.curInput.stateField = byte(newLine)
  9053  
  9054  			// Move to next line of file, or |goto restart| if there is no next line, or |return| if a \.[\\read] line has finished
  9055  			if int32(prg.curInput.nameField) > 17 {
  9056  				prg.line = prg.line + 1
  9057  				prg.first = prg.curInput.startField
  9058  				if !prg.forceEof {
  9059  					if prg.inputLn(prg.inputFile[prg.curInput.indexField-1], true) {
  9060  						prg.firmUpTheLine()
  9061  					} else {
  9062  						prg.forceEof = true
  9063  					}
  9064  				}
  9065  				if prg.forceEof {
  9066  					prg.printChar(asciiCode(')'))
  9067  					prg.openParens = byte(int32(prg.openParens) - 1)
  9068  					// show user that file has been read
  9069  					prg.forceEof = false
  9070  					prg.endFileReading() // resume previous level
  9071  					prg.checkOuterValidity()
  9072  					goto restart
  9073  				}
  9074  				if *prg.eqtb[intBase+endLineCharCode-1].int() < 0 || *prg.eqtb[intBase+endLineCharCode-1].int() > 255 {
  9075  					prg.curInput.limitField = uint16(int32(prg.curInput.limitField) - 1)
  9076  				} else {
  9077  					prg.buffer[prg.curInput.limitField] = byte(*prg.eqtb[intBase+endLineCharCode-1].int())
  9078  				}
  9079  				prg.first = uint16(int32(prg.curInput.limitField) + 1)
  9080  				prg.curInput.locField = prg.curInput.startField // ready to read
  9081  			} else {
  9082  				if !(int32(prg.curInput.nameField) == 0) {
  9083  					prg.curCmd = 0
  9084  					prg.curChr = 0
  9085  					goto exit
  9086  				}
  9087  				if int32(prg.inputPtr) > 0 {
  9088  					prg.endFileReading()
  9089  					goto restart // resume previous level
  9090  				}
  9091  				if int32(prg.selector) < logOnly {
  9092  					prg.openLogFile()
  9093  				}
  9094  				if int32(prg.interaction) > nonstopMode {
  9095  					if *prg.eqtb[intBase+endLineCharCode-1].int() < 0 || *prg.eqtb[intBase+endLineCharCode-1].int() > 255 {
  9096  						prg.curInput.limitField = uint16(int32(prg.curInput.limitField) + 1)
  9097  					}
  9098  					if int32(prg.curInput.limitField) == int32(prg.curInput.startField) {
  9099  						prg.printNl(strNumber( /* "(Please type a command or say `\\end')" */ 616))
  9100  					}
  9101  					// \xref[Please type...]
  9102  					prg.printLn()
  9103  					prg.first = prg.curInput.startField
  9104  					{
  9105  						prg.print('*')
  9106  						prg.termInput()
  9107  					} // input on-line into |buffer|
  9108  					// \xref[*\relax]
  9109  					prg.curInput.limitField = prg.last
  9110  					if *prg.eqtb[intBase+endLineCharCode-1].int() < 0 || *prg.eqtb[intBase+endLineCharCode-1].int() > 255 {
  9111  						prg.curInput.limitField = uint16(int32(prg.curInput.limitField) - 1)
  9112  					} else {
  9113  						prg.buffer[prg.curInput.limitField] = byte(*prg.eqtb[intBase+endLineCharCode-1].int())
  9114  					}
  9115  					prg.first = uint16(int32(prg.curInput.limitField) + 1)
  9116  					prg.curInput.locField = prg.curInput.startField
  9117  				} else {
  9118  					prg.fatalError(strNumber( /* "*** (job aborted, no legal \\end found)" */ 617))
  9119  				}
  9120  				// \xref[job aborted]
  9121  				// nonstop mode, which is intended for overnight batch processing,
  9122  				//     never waits for on-line input
  9123  
  9124  			}
  9125  			{
  9126  				if prg.interrupt != 0 {
  9127  					prg.pauseForInstructions()
  9128  				}
  9129  			}
  9130  
  9131  			goto switch1
  9132  		}
  9133  	} else if int32(prg.curInput.locField) != 0 {
  9134  		t = *(*prg.mem[prg.curInput.locField].hh()).lh()
  9135  		prg.curInput.locField = *(*prg.mem[prg.curInput.locField].hh()).rh() // move to next
  9136  		if int32(t) >= 07777 {
  9137  			prg.curCs = uint16(int32(t) - 07777)
  9138  			prg.curCmd = *(*prg.eqtb[prg.curCs-1].hh()).b0()
  9139  			prg.curChr = *(*prg.eqtb[prg.curCs-1].hh()).rh()
  9140  			if int32(prg.curCmd) >= outerCall {
  9141  				if int32(prg.curCmd) == dontExpand {
  9142  					prg.curCs = uint16(int32(*(*prg.mem[prg.curInput.locField].hh()).lh()) - 07777)
  9143  					prg.curInput.locField = 0
  9144  
  9145  					prg.curCmd = *(*prg.eqtb[prg.curCs-1].hh()).b0()
  9146  					prg.curChr = *(*prg.eqtb[prg.curCs-1].hh()).rh()
  9147  					if int32(prg.curCmd) > maxCommand {
  9148  						prg.curCmd = byte(relax)
  9149  						prg.curChr = uint16(noExpandFlag)
  9150  					}
  9151  				} else {
  9152  					prg.checkOuterValidity()
  9153  				}
  9154  			}
  9155  		} else {
  9156  			prg.curCmd = byte(int32(t) / 0400)
  9157  			prg.curChr = uint16(int32(t) % 0400)
  9158  			switch prg.curCmd {
  9159  			case leftBrace:
  9160  				prg.alignState = prg.alignState + 1
  9161  			case rightBrace:
  9162  				prg.alignState = prg.alignState - 1
  9163  			case outParam:
  9164  				// Insert macro parameter and |goto restart|
  9165  				prg.beginTokenList(prg.paramStack[int32(prg.curInput.limitField)+int32(prg.curChr)-1], quarterword(parameter))
  9166  
  9167  				goto restart
  9168  
  9169  			default:
  9170  			}
  9171  		}
  9172  	} else {
  9173  		prg.endTokenList()
  9174  		goto restart // resume previous level
  9175  	}
  9176  
  9177  	// If an alignment entry has just ended, take appropriate action
  9178  	if int32(prg.curCmd) <= carRet {
  9179  		if int32(prg.curCmd) >= tabMark {
  9180  			if prg.alignState == 0 {
  9181  				if int32(prg.scannerStatus) == aligning || int32(prg.curAlign) == 0 {
  9182  					prg.fatalError(strNumber( /* "(interwoven alignment preambles are not allowed)" */ 595))
  9183  				}
  9184  				// \xref[interwoven alignment preambles...]
  9185  				prg.curCmd = byte(*(*prg.mem[int32(prg.curAlign)+listOffset].hh()).lh())
  9186  				*(*prg.mem[int32(prg.curAlign)+listOffset].hh()).lh() = prg.curChr
  9187  				if int32(prg.curCmd) == omit {
  9188  					prg.beginTokenList(halfword(30000-10), quarterword(vTemplate))
  9189  				} else {
  9190  					prg.beginTokenList(halfword(*prg.mem[int32(prg.curAlign)+depthOffset].int()), quarterword(vTemplate))
  9191  				}
  9192  				prg.alignState = 1000000
  9193  				goto restart
  9194  			}
  9195  		}
  9196  	}
  9197  
  9198  exit:
  9199  }
  9200  
  9201  // 340.
  9202  
  9203  // tangle:pos tex.web:7226:3:
  9204  
  9205  // We need to mention a procedure here that may be called by |get_next|.
  9206  func (prg *prg) firmUpTheLine() {
  9207  	var (
  9208  		k /* 0..bufSize */ uint16 // an index into |buffer|
  9209  	)
  9210  	prg.curInput.limitField = prg.last
  9211  	if *prg.eqtb[intBase+pausingCode-1].int() > 0 {
  9212  		if int32(prg.interaction) > nonstopMode {
  9213  			prg.printLn()
  9214  			if int32(prg.curInput.startField) < int32(prg.curInput.limitField) {
  9215  				for ii := int32(prg.curInput.startField); ii <= int32(prg.curInput.limitField)-1; ii++ {
  9216  					k = uint16(ii)
  9217  					_ = k
  9218  					prg.print(int32(prg.buffer[k]))
  9219  				}
  9220  			}
  9221  			prg.first = prg.curInput.limitField
  9222  			{
  9223  				prg.print( /* "=>" */ 618)
  9224  				prg.termInput()
  9225  			} // wait for user response
  9226  			// \xref[=>]
  9227  			if int32(prg.last) > int32(prg.first) {
  9228  				for ii := int32(prg.first); ii <= int32(prg.last)-1; ii++ {
  9229  					k = uint16(ii)
  9230  					_ = k // move line down in buffer
  9231  					prg.buffer[int32(k)+int32(prg.curInput.startField)-int32(prg.first)] = prg.buffer[k]
  9232  				}
  9233  				prg.curInput.limitField = uint16(int32(prg.curInput.startField) + int32(prg.last) - int32(prg.first))
  9234  			}
  9235  		}
  9236  	}
  9237  } // \2
  9238  
  9239  func (prg *prg) getToken() {
  9240  	prg.noNewControlSequence = false
  9241  	prg.getNext()
  9242  	prg.noNewControlSequence = true
  9243  	// \xref[inner loop]
  9244  	if int32(prg.curCs) == 0 {
  9245  		prg.curTok = uint16(int32(prg.curCmd)*0400 + int32(prg.curChr))
  9246  	} else {
  9247  		prg.curTok = uint16(07777 + int32(prg.curCs))
  9248  	}
  9249  }
  9250  
  9251  // 366. \[25] Expanding the next token
  9252  
  9253  // tangle:pos tex.web:7636:33:
  9254  
  9255  // Only a dozen or so command codes |>max_command| can possibly be returned by
  9256  // |get_next|; in increasing order, they are |undefined_cs|, |expand_after|,
  9257  // |no_expand|, |input|, |if_test|, |fi_or_else|, |cs_name|, |convert|, |the|,
  9258  // |top_bot_mark|, |call|, |long_call|, |outer_call|, |long_outer_call|, and
  9259  // |end_template|.[\emergencystretch=40pt\par]
  9260  //
  9261  // The |expand| subroutine is used when |cur_cmd>max_command|. It removes a
  9262  // “call” or a conditional or one of the other special operations just
  9263  // listed.  It follows that |expand| might invoke itself recursively. In all
  9264  // cases, |expand| destroys the current token, but it sets things up so that
  9265  // the next |get_next| will deliver the appropriate next token. The value of
  9266  // |cur_tok| need not be known when |expand| is called.
  9267  //
  9268  // Since several of the basic scanning routines communicate via global variables,
  9269  // their values are saved as local variables of |expand| so that
  9270  // recursive calls don't invalidate them.
  9271  // \xref[recursion]
  9272  // \4
  9273  // Declare the procedure called |macro_call|
  9274  func (prg *prg) macroCall() {
  9275  	var (
  9276  		r1                halfword    // current node in the macro's token list
  9277  		p                 halfword    // current node in parameter token list being built
  9278  		q                 halfword    // new node being put into the token list
  9279  		s                 halfword    // backup pointer for parameter matching
  9280  		t                 halfword    // cycle pointer for backup recovery
  9281  		u, v              halfword    // auxiliary pointers for backup recovery
  9282  		rbracePtr         halfword    // one step before the last |right_brace| token
  9283  		n                 smallNumber // the number of parameters scanned
  9284  		unbalance         halfword    // unmatched left braces in current parameter
  9285  		m                 halfword    // the number of tokens or groups (usually)
  9286  		refCount          halfword    // start of the token list
  9287  		saveScannerStatus smallNumber // |scanner_status| upon entry
  9288  		saveWarningIndex  halfword    // |warning_index| upon entry
  9289  		matchChr          asciiCode   // character used in parameter
  9290  	)
  9291  	saveScannerStatus = prg.scannerStatus
  9292  	saveWarningIndex = prg.warningIndex
  9293  	prg.warningIndex = prg.curCs
  9294  	refCount = prg.curChr
  9295  	r1 = *(*prg.mem[refCount].hh()).rh()
  9296  	n = 0
  9297  	if *prg.eqtb[intBase+tracingMacrosCode-1].int() > 0 {
  9298  		prg.beginDiagnostic()
  9299  		prg.printLn()
  9300  		prg.printCs(int32(prg.warningIndex))
  9301  		prg.tokenShow(refCount)
  9302  		prg.endDiagnostic(false)
  9303  	}
  9304  	if int32(*(*prg.mem[r1].hh()).lh()) != endMatchToken {
  9305  		prg.scannerStatus = byte(matching)
  9306  		unbalance = 0
  9307  		prg.longState = *(*prg.eqtb[prg.curCs-1].hh()).b0()
  9308  		if int32(prg.longState) >= outerCall {
  9309  			prg.longState = byte(int32(prg.longState) - 2)
  9310  		}
  9311  		for {
  9312  			*(*prg.mem[30000-3].hh()).rh() = 0
  9313  			if int32(*(*prg.mem[r1].hh()).lh()) > matchToken+255 || int32(*(*prg.mem[r1].hh()).lh()) < matchToken {
  9314  				s = 0
  9315  			} else {
  9316  				matchChr = byte(int32(*(*prg.mem[r1].hh()).lh()) - matchToken)
  9317  				s = *(*prg.mem[r1].hh()).rh()
  9318  				r1 = s
  9319  				p = uint16(30000 - 3)
  9320  				m = 0
  9321  			}
  9322  
  9323  			// Scan a parameter until its delimiter string has been found; or, if |s=null|, simply scan the delimiter string
  9324  
  9325  			// Scan a parameter until its delimiter string has been found; or, if |s=null|, simply scan the delimiter string
  9326  		continue1:
  9327  			prg.getToken() // set |cur_tok| to the next token of input
  9328  			if int32(prg.curTok) == int32(*(*prg.mem[r1].hh()).lh()) {
  9329  				r1 = *(*prg.mem[r1].hh()).rh()
  9330  				if int32(*(*prg.mem[r1].hh()).lh()) >= matchToken && int32(*(*prg.mem[r1].hh()).lh()) <= endMatchToken {
  9331  					if int32(prg.curTok) < leftBraceLimit {
  9332  						prg.alignState = prg.alignState - 1
  9333  					}
  9334  
  9335  					goto found
  9336  				} else {
  9337  					goto continue1
  9338  				}
  9339  			}
  9340  
  9341  			// Contribute the recently matched tokens to the current parameter, and |goto continue| if a partial match is still in effect; but abort if |s=null|
  9342  			if int32(s) != int32(r1) {
  9343  				if int32(s) == 0 {
  9344  					{
  9345  						if int32(prg.interaction) == errorStopMode {
  9346  						}
  9347  						prg.printNl(strNumber( /* "! " */ 262))
  9348  						prg.print( /* "Use of " */ 650)
  9349  					}
  9350  					prg.sprintCs(prg.warningIndex)
  9351  					// \xref[Use of x doesn't match...]
  9352  					prg.print( /* " doesn't match its definition" */ 651)
  9353  					{
  9354  						prg.helpPtr = 4
  9355  						prg.helpLine[3] = /* "If you say, e.g., `\\def\\a1[...]', then you must always" */ 652
  9356  						prg.helpLine[2] = /* "put `1' after `\\a', since control sequence names are" */ 653
  9357  						prg.helpLine[1] = /* "made up of letters only. The macro here has not been" */ 654
  9358  						prg.helpLine[0] = /* "followed by the required stuff, so I'm ignoring it." */ 655
  9359  					}
  9360  					prg.error1()
  9361  					goto exit
  9362  				} else {
  9363  					t = s
  9364  					for {
  9365  						{
  9366  							q = prg.getAvail()
  9367  							*(*prg.mem[p].hh()).rh() = q
  9368  							*(*prg.mem[q].hh()).lh() = *(*prg.mem[t].hh()).lh()
  9369  							p = q
  9370  						}
  9371  						m = uint16(int32(m) + 1)
  9372  						u = *(*prg.mem[t].hh()).rh()
  9373  						v = s
  9374  						for true {
  9375  							if int32(u) == int32(r1) {
  9376  								if int32(prg.curTok) != int32(*(*prg.mem[v].hh()).lh()) {
  9377  									goto done
  9378  								} else {
  9379  									r1 = *(*prg.mem[v].hh()).rh()
  9380  									goto continue1
  9381  								}
  9382  							}
  9383  							if int32(*(*prg.mem[u].hh()).lh()) != int32(*(*prg.mem[v].hh()).lh()) {
  9384  								goto done
  9385  							}
  9386  							u = *(*prg.mem[u].hh()).rh()
  9387  							v = *(*prg.mem[v].hh()).rh()
  9388  						}
  9389  
  9390  					done:
  9391  						t = *(*prg.mem[t].hh()).rh()
  9392  						if int32(t) == int32(r1) {
  9393  							break
  9394  						}
  9395  					}
  9396  					r1 = s // at this point, no tokens are recently matched
  9397  				}
  9398  			}
  9399  			if int32(prg.curTok) == int32(prg.parToken) {
  9400  				if int32(prg.longState) != longCall {
  9401  					if int32(prg.longState) == call {
  9402  						prg.runaway()
  9403  						{
  9404  							if int32(prg.interaction) == errorStopMode {
  9405  							}
  9406  							prg.printNl(strNumber( /* "! " */ 262))
  9407  							prg.print( /* "Paragraph ended before " */ 645)
  9408  						}
  9409  						// \xref[Paragraph ended before...]
  9410  						prg.sprintCs(prg.warningIndex)
  9411  						prg.print( /* " was complete" */ 646)
  9412  						{
  9413  							prg.helpPtr = 3
  9414  							prg.helpLine[2] = /* "I suspect you've forgotten a `]', causing me to apply this" */ 647
  9415  							prg.helpLine[1] = /* "control sequence to too much text. How can we recover?" */ 648
  9416  							prg.helpLine[0] = /* "My plan is to forget the whole thing and hope for the best." */ 649
  9417  						}
  9418  						prg.backError()
  9419  					}
  9420  					prg.pstack[n] = *(*prg.mem[30000-3].hh()).rh()
  9421  					prg.alignState = prg.alignState - int32(unbalance)
  9422  					for ii := int32(0); ii <= int32(n); ii++ {
  9423  						m = halfword(ii)
  9424  						_ = m
  9425  						prg.flushList(prg.pstack[m])
  9426  					}
  9427  
  9428  					goto exit
  9429  				}
  9430  			}
  9431  			if int32(prg.curTok) < rightBraceLimit {
  9432  				if int32(prg.curTok) < leftBraceLimit {
  9433  					unbalance = 1
  9434  					// \xref[inner loop]
  9435  					for true {
  9436  						{
  9437  							{
  9438  								q = prg.avail
  9439  								if int32(q) == 0 {
  9440  									q = prg.getAvail()
  9441  								} else {
  9442  									prg.avail = *(*prg.mem[q].hh()).rh()
  9443  									*(*prg.mem[q].hh()).rh() = 0 /*    dyn_used:= dyn_used+1 ; [  ] */
  9444  								}
  9445  							}
  9446  							*(*prg.mem[p].hh()).rh() = q
  9447  							*(*prg.mem[q].hh()).lh() = prg.curTok
  9448  							p = q
  9449  						}
  9450  						prg.getToken()
  9451  						if int32(prg.curTok) == int32(prg.parToken) {
  9452  							if int32(prg.longState) != longCall {
  9453  								if int32(prg.longState) == call {
  9454  									prg.runaway()
  9455  									{
  9456  										if int32(prg.interaction) == errorStopMode {
  9457  										}
  9458  										prg.printNl(strNumber( /* "! " */ 262))
  9459  										prg.print( /* "Paragraph ended before " */ 645)
  9460  									}
  9461  									// \xref[Paragraph ended before...]
  9462  									prg.sprintCs(prg.warningIndex)
  9463  									prg.print( /* " was complete" */ 646)
  9464  									{
  9465  										prg.helpPtr = 3
  9466  										prg.helpLine[2] = /* "I suspect you've forgotten a `]', causing me to apply this" */ 647
  9467  										prg.helpLine[1] = /* "control sequence to too much text. How can we recover?" */ 648
  9468  										prg.helpLine[0] = /* "My plan is to forget the whole thing and hope for the best." */ 649
  9469  									}
  9470  									prg.backError()
  9471  								}
  9472  								prg.pstack[n] = *(*prg.mem[30000-3].hh()).rh()
  9473  								prg.alignState = prg.alignState - int32(unbalance)
  9474  								for ii := int32(0); ii <= int32(n); ii++ {
  9475  									m = halfword(ii)
  9476  									_ = m
  9477  									prg.flushList(prg.pstack[m])
  9478  								}
  9479  
  9480  								goto exit
  9481  							}
  9482  						}
  9483  						if int32(prg.curTok) < rightBraceLimit {
  9484  							if int32(prg.curTok) < leftBraceLimit {
  9485  								unbalance = uint16(int32(unbalance) + 1)
  9486  							} else {
  9487  								unbalance = uint16(int32(unbalance) - 1)
  9488  								if int32(unbalance) == 0 {
  9489  									goto done1
  9490  								}
  9491  							}
  9492  						}
  9493  					}
  9494  
  9495  				done1:
  9496  					rbracePtr = p
  9497  					{
  9498  						q = prg.getAvail()
  9499  						*(*prg.mem[p].hh()).rh() = q
  9500  						*(*prg.mem[q].hh()).lh() = prg.curTok
  9501  						p = q
  9502  					}
  9503  				} else {
  9504  					// Report an extra right brace and |goto continue|
  9505  					prg.backInput()
  9506  					{
  9507  						if int32(prg.interaction) == errorStopMode {
  9508  						}
  9509  						prg.printNl(strNumber( /* "! " */ 262))
  9510  						prg.print( /* "Argument of " */ 637)
  9511  					}
  9512  					prg.sprintCs(prg.warningIndex)
  9513  					// \xref[Argument of \\x has...]
  9514  					prg.print( /* " has an extra ]" */ 638)
  9515  					{
  9516  						prg.helpPtr = 6
  9517  						prg.helpLine[5] = /* "I've run across a `]' that doesn't seem to match anything." */ 639
  9518  						prg.helpLine[4] = /* "For example, `\\def\\a#1[...]' and `\\a]' would produce" */ 640
  9519  						prg.helpLine[3] = /* "this error. If you simply proceed now, the `\\par' that" */ 641
  9520  						prg.helpLine[2] = /* "I've just inserted will cause me to report a runaway" */ 642
  9521  						prg.helpLine[1] = /* "argument that might be the root of the problem. But if" */ 643
  9522  						prg.helpLine[0] = /* "your `]' was spurious, just type `2' and it will go away." */ 644
  9523  					}
  9524  					prg.alignState = prg.alignState + 1
  9525  					prg.longState = byte(call)
  9526  					prg.curTok = prg.parToken
  9527  					prg.insError()
  9528  
  9529  					goto continue1
  9530  				}
  9531  			} else {
  9532  				// Store the current token, but |goto continue| if it is a blank space that would become an undelimited parameter
  9533  				if int32(prg.curTok) == spaceToken {
  9534  					if int32(*(*prg.mem[r1].hh()).lh()) <= endMatchToken {
  9535  						if int32(*(*prg.mem[r1].hh()).lh()) >= matchToken {
  9536  							goto continue1
  9537  						}
  9538  					}
  9539  				}
  9540  				{
  9541  					q = prg.getAvail()
  9542  					*(*prg.mem[p].hh()).rh() = q
  9543  					*(*prg.mem[q].hh()).lh() = prg.curTok
  9544  					p = q
  9545  				}
  9546  			}
  9547  			m = uint16(int32(m) + 1)
  9548  			if int32(*(*prg.mem[r1].hh()).lh()) > endMatchToken {
  9549  				goto continue1
  9550  			}
  9551  			if int32(*(*prg.mem[r1].hh()).lh()) < matchToken {
  9552  				goto continue1
  9553  			}
  9554  
  9555  		found:
  9556  			if int32(s) != 0 {
  9557  				if int32(m) == 1 && int32(*(*prg.mem[p].hh()).lh()) < rightBraceLimit {
  9558  					*(*prg.mem[rbracePtr].hh()).rh() = 0
  9559  					{
  9560  						*(*prg.mem[p].hh()).rh() = prg.avail
  9561  						prg.avail = p /*    dyn_used:= dyn_used-1 ; [  ] */
  9562  					}
  9563  					p = *(*prg.mem[30000-3].hh()).rh()
  9564  					prg.pstack[n] = *(*prg.mem[p].hh()).rh()
  9565  					{
  9566  						*(*prg.mem[p].hh()).rh() = prg.avail
  9567  						prg.avail = p /*    dyn_used:= dyn_used-1 ; [  ] */
  9568  					}
  9569  				} else {
  9570  					prg.pstack[n] = *(*prg.mem[30000-3].hh()).rh()
  9571  				}
  9572  				n = byte(int32(n) + 1)
  9573  				if *prg.eqtb[intBase+tracingMacrosCode-1].int() > 0 {
  9574  					prg.beginDiagnostic()
  9575  					prg.printNl(strNumber(matchChr))
  9576  					prg.printInt(int32(n))
  9577  					prg.print( /* "<-" */ 656)
  9578  					prg.showTokenList(int32(prg.pstack[int32(n)-1]), 0, 1000)
  9579  					prg.endDiagnostic(false)
  9580  				}
  9581  			}
  9582  
  9583  			// now |info(r)| is a token whose command code is either |match| or |end_match|
  9584  			if int32(*(*prg.mem[r1].hh()).lh()) == endMatchToken {
  9585  				break
  9586  			}
  9587  		}
  9588  	}
  9589  
  9590  	// Feed the macro body and its parameters to the scanner
  9591  	for int32(prg.curInput.stateField) == tokenList && int32(prg.curInput.locField) == 0 && int32(prg.curInput.indexField) != vTemplate {
  9592  		prg.endTokenList()
  9593  	} // conserve stack space
  9594  	prg.beginTokenList(refCount, quarterword(macro))
  9595  	prg.curInput.nameField = prg.warningIndex
  9596  	prg.curInput.locField = *(*prg.mem[r1].hh()).rh()
  9597  	if int32(n) > 0 {
  9598  		if int32(prg.paramPtr)+int32(n) > prg.maxParamStack {
  9599  			prg.maxParamStack = int32(prg.paramPtr) + int32(n)
  9600  			if prg.maxParamStack > paramSize {
  9601  				prg.overflow(strNumber( /* "parameter stack size" */ 636), paramSize)
  9602  			}
  9603  			// \xref[TeX capacity exceeded parameter stack size][\quad parameter stack size]
  9604  		}
  9605  		for ii := int32(0); ii <= int32(n)-1; ii++ {
  9606  			m = halfword(ii)
  9607  			_ = m
  9608  			prg.paramStack[int32(prg.paramPtr)+int32(m)] = prg.pstack[m]
  9609  		}
  9610  		prg.paramPtr = byte(int32(prg.paramPtr) + int32(n))
  9611  	}
  9612  
  9613  exit:
  9614  	prg.scannerStatus = saveScannerStatus
  9615  	prg.warningIndex = saveWarningIndex
  9616  }
  9617  
  9618  // \4
  9619  // Declare the procedure called |insert_relax|
  9620  func (prg *prg) insertRelax() {
  9621  	prg.curTok = uint16(07777 + int32(prg.curCs))
  9622  	prg.backInput()
  9623  	prg.curTok = uint16(07777 + frozenRelax)
  9624  	prg.backInput()
  9625  	prg.curInput.indexField = byte(inserted)
  9626  } // \2
  9627  func (prg *prg) expand() {
  9628  	var (
  9629  		t                                halfword // token that is being ``expanded after''
  9630  		p, q, r1                         halfword // for list manipulation
  9631  		j/* 0..bufSize */ uint16                  // index into |buffer|
  9632  		cvBackup                         int32    // to save the global quantity |cur_val|
  9633  		cvlBackup, radixBackup, coBackup smallNumber
  9634  		// to save |cur_val_level|, etc.
  9635  		backupBackup      halfword    // to save |link(backup_head)|
  9636  		saveScannerStatus smallNumber // temporary storage of |scanner_status|
  9637  	)
  9638  	cvBackup = prg.curVal
  9639  	cvlBackup = prg.curValLevel
  9640  	radixBackup = prg.radix
  9641  	coBackup = prg.curOrder
  9642  	backupBackup = *(*prg.mem[30000-13].hh()).rh()
  9643  	if int32(prg.curCmd) < call {
  9644  		if *prg.eqtb[intBase+tracingCommandsCode-1].int() > 1 {
  9645  			prg.showCurCmdChr()
  9646  		}
  9647  		switch prg.curCmd {
  9648  		case topBotMark:
  9649  			// Insert the \(a)appropriate mark text into the scanner
  9650  			if int32(prg.curMark[prg.curChr]) != 0 {
  9651  				prg.beginTokenList(prg.curMark[prg.curChr], quarterword(markText))
  9652  			}
  9653  
  9654  		case expandAfter:
  9655  			// Expand the token after the next token
  9656  			prg.getToken()
  9657  			t = prg.curTok
  9658  			prg.getToken()
  9659  			if int32(prg.curCmd) > maxCommand {
  9660  				prg.expand()
  9661  			} else {
  9662  				prg.backInput()
  9663  			}
  9664  			prg.curTok = t
  9665  			prg.backInput()
  9666  
  9667  		case noExpand:
  9668  			// Suppress expansion of the next token
  9669  			saveScannerStatus = prg.scannerStatus
  9670  			prg.scannerStatus = byte(normal)
  9671  			prg.getToken()
  9672  			prg.scannerStatus = saveScannerStatus
  9673  			t = prg.curTok
  9674  			prg.backInput() // now |start| and |loc| point to the backed-up token |t|
  9675  			if int32(t) >= 07777 {
  9676  				p = prg.getAvail()
  9677  				*(*prg.mem[p].hh()).lh() = uint16(07777 + frozenDontExpand)
  9678  				*(*prg.mem[p].hh()).rh() = prg.curInput.locField
  9679  				prg.curInput.startField = p
  9680  				prg.curInput.locField = p
  9681  			}
  9682  
  9683  		case csName:
  9684  			// Manufacture a control sequence name
  9685  			r1 = prg.getAvail()
  9686  			p = r1 // head of the list of characters
  9687  			for {
  9688  				prg.getXToken()
  9689  				if int32(prg.curCs) == 0 {
  9690  					q = prg.getAvail()
  9691  					*(*prg.mem[p].hh()).rh() = q
  9692  					*(*prg.mem[q].hh()).lh() = prg.curTok
  9693  					p = q
  9694  				}
  9695  				if int32(prg.curCs) != 0 {
  9696  					break
  9697  				}
  9698  			}
  9699  			if int32(prg.curCmd) != endCsName {
  9700  				{
  9701  					if int32(prg.interaction) == errorStopMode {
  9702  					}
  9703  					prg.printNl(strNumber( /* "! " */ 262))
  9704  					prg.print( /* "Missing " */ 625)
  9705  				}
  9706  				prg.printEsc(strNumber( /* "endcsname" */ 505))
  9707  				prg.print( /* " inserted" */ 626)
  9708  				// \xref[Missing \\endcsname...]
  9709  				{
  9710  					prg.helpPtr = 2
  9711  					prg.helpLine[1] = /* "The control sequence marked <to be read again> should" */ 627
  9712  					prg.helpLine[0] = /* "not appear between \\csname and \\endcsname." */ 628
  9713  				}
  9714  				prg.backError()
  9715  			}
  9716  
  9717  			// Look up the characters of list |r| in the hash table, and set |cur_cs|
  9718  			j = prg.first
  9719  			p = *(*prg.mem[r1].hh()).rh()
  9720  			for int32(p) != 0 {
  9721  				if int32(j) >= int32(prg.maxBufStack) {
  9722  					prg.maxBufStack = uint16(int32(j) + 1)
  9723  					if int32(prg.maxBufStack) == bufSize {
  9724  						prg.overflow(strNumber( /* "buffer size" */ 256), bufSize)
  9725  					}
  9726  					// \xref[TeX capacity exceeded buffer size][\quad buffer size]
  9727  				}
  9728  				prg.buffer[j] = byte(int32(*(*prg.mem[p].hh()).lh()) % 0400)
  9729  				j = uint16(int32(j) + 1)
  9730  				p = *(*prg.mem[p].hh()).rh()
  9731  			}
  9732  			if int32(j) > int32(prg.first)+1 {
  9733  				prg.noNewControlSequence = false
  9734  				prg.curCs = prg.idLookup(int32(prg.first), int32(j)-int32(prg.first))
  9735  				prg.noNewControlSequence = true
  9736  			} else if int32(j) == int32(prg.first) {
  9737  				prg.curCs = uint16(nullCs)
  9738  			} else {
  9739  				prg.curCs = uint16(singleBase + int32(prg.buffer[prg.first]))
  9740  			}
  9741  			prg.flushList(r1)
  9742  			if int32(*(*prg.eqtb[prg.curCs-1].hh()).b0()) == undefinedCs {
  9743  				prg.eqDefine(prg.curCs, quarterword(relax), halfword(256)) // N.B.: The |save_stack| might change
  9744  			} // the control sequence will now match `\.[\\relax]'
  9745  			prg.curTok = uint16(int32(prg.curCs) + 07777)
  9746  			prg.backInput()
  9747  
  9748  		case convert:
  9749  			prg.convToks() // this procedure is discussed in Part 27 below
  9750  		case the:
  9751  			prg.insTheToks() // this procedure is discussed in Part 27 below
  9752  		case ifTest:
  9753  			prg.conditional() // this procedure is discussed in Part 28 below
  9754  		case fiOrElse:
  9755  			// Terminate the current conditional and skip to \.[\\fi]
  9756  			if int32(prg.curChr) > int32(prg.ifLimit) {
  9757  				if int32(prg.ifLimit) == ifCode {
  9758  					prg.insertRelax()
  9759  				} else {
  9760  					{
  9761  						if int32(prg.interaction) == errorStopMode {
  9762  						}
  9763  						prg.printNl(strNumber( /* "! " */ 262))
  9764  						prg.print( /* "Extra " */ 777)
  9765  					}
  9766  					prg.printCmdChr(quarterword(fiOrElse), prg.curChr)
  9767  					// \xref[Extra \\or]
  9768  					// \xref[Extra \\else]
  9769  					// \xref[Extra \\fi]
  9770  					{
  9771  						prg.helpPtr = 1
  9772  						prg.helpLine[0] = /* "I'm ignoring this; it doesn't match any \\if." */ 778
  9773  					}
  9774  					prg.error1()
  9775  				}
  9776  			} else {
  9777  				for int32(prg.curChr) != fiCode {
  9778  					prg.passText()
  9779  				} // skip to \.[\\fi]
  9780  
  9781  				// Pop the condition stack
  9782  				{
  9783  					p = prg.condPtr
  9784  					prg.ifLine = *prg.mem[int32(p)+1].int()
  9785  					prg.curIf = *(*prg.mem[p].hh()).b1()
  9786  					prg.ifLimit = *(*prg.mem[p].hh()).b0()
  9787  					prg.condPtr = *(*prg.mem[p].hh()).rh()
  9788  					prg.freeNode(p, halfword(ifNodeSize))
  9789  				}
  9790  			}
  9791  
  9792  		case input:
  9793  			// Initiate or terminate input from a file
  9794  			if int32(prg.curChr) > 0 {
  9795  				prg.forceEof = true
  9796  			} else if prg.nameInProgress {
  9797  				prg.insertRelax()
  9798  			} else {
  9799  				prg.startInput()
  9800  			}
  9801  
  9802  		default:
  9803  			{
  9804  				if int32(prg.interaction) == errorStopMode {
  9805  				}
  9806  				prg.printNl(strNumber( /* "! " */ 262))
  9807  				prg.print( /* "Undefined control sequence" */ 619)
  9808  			}
  9809  			// \xref[Undefined control sequence]
  9810  			{
  9811  				prg.helpPtr = 5
  9812  				prg.helpLine[4] = /* "The control sequence at the end of the top line" */ 620
  9813  				prg.helpLine[3] = /* "of your error message was never \\def'ed. If you have" */ 621
  9814  				prg.helpLine[2] = /* "misspelled it (e.g., `\\hobx'), type `I' and the correct" */ 622
  9815  				prg.helpLine[1] = /* "spelling (e.g., `I\\hbox'). Otherwise just continue," */ 623
  9816  				prg.helpLine[0] = /* "and I'll forget about whatever was undefined." */ 624
  9817  			}
  9818  			prg.error1()
  9819  
  9820  		}
  9821  	} else if int32(prg.curCmd) < endTemplate {
  9822  		prg.macroCall()
  9823  	} else {
  9824  		// Insert a token containing |frozen_endv|
  9825  		prg.curTok = uint16(07777 + frozenEndv)
  9826  		prg.backInput()
  9827  	}
  9828  	prg.curVal = cvBackup
  9829  	prg.curValLevel = cvlBackup
  9830  	prg.radix = radixBackup
  9831  	prg.curOrder = coBackup
  9832  	*(*prg.mem[30000-13].hh()).rh() = backupBackup
  9833  } // \2
  9834  func (prg *prg) getXToken() {
  9835  restart:
  9836  	prg.getNext()
  9837  	// \xref[inner loop]
  9838  	if int32(prg.curCmd) <= maxCommand {
  9839  		goto done
  9840  	}
  9841  	if int32(prg.curCmd) >= call {
  9842  		if int32(prg.curCmd) < endTemplate {
  9843  			prg.macroCall()
  9844  		} else {
  9845  			prg.curCs = uint16(frozenEndv)
  9846  			prg.curCmd = byte(endv)
  9847  
  9848  			goto done // |cur_chr=null_list|
  9849  		}
  9850  	} else {
  9851  		prg.expand()
  9852  	}
  9853  
  9854  	goto restart
  9855  
  9856  done:
  9857  	if int32(prg.curCs) == 0 {
  9858  		prg.curTok = uint16(int32(prg.curCmd)*0400 + int32(prg.curChr))
  9859  	} else {
  9860  		prg.curTok = uint16(07777 + int32(prg.curCs))
  9861  	}
  9862  }
  9863  
  9864  // 381.
  9865  
  9866  // tangle:pos tex.web:7842:1:
  9867  
  9868  // The |get_x_token| procedure is essentially equivalent to two consecutive
  9869  // procedure calls: |get_next; x_token|.
  9870  func (prg *prg) xToken() {
  9871  	for int32(prg.curCmd) > maxCommand {
  9872  		prg.expand()
  9873  		prg.getNext()
  9874  	}
  9875  	if int32(prg.curCs) == 0 {
  9876  		prg.curTok = uint16(int32(prg.curCmd)*0400 + int32(prg.curChr))
  9877  	} else {
  9878  		prg.curTok = uint16(07777 + int32(prg.curCs))
  9879  	}
  9880  }
  9881  
  9882  // 402. \[26] Basic scanning subroutines
  9883  
  9884  // tangle:pos tex.web:8181:35:
  9885  
  9886  // Let's turn now to some procedures that \TeX\ calls upon frequently to digest
  9887  // certain kinds of patterns in the input. Most of these are quite simple;
  9888  // some are quite elaborate. Almost all of the routines call |get_x_token|,
  9889  // which can cause them to be invoked recursively.
  9890  // \xref[stomach]
  9891  // \xref[recursion]
  9892  
  9893  // 403.
  9894  
  9895  // tangle:pos tex.web:8189:1:
  9896  
  9897  // The |scan_left_brace| routine is called when a left brace is supposed to be
  9898  // the next non-blank token. (The term ``left brace'' means, more precisely,
  9899  // a character whose catcode is |left_brace|.) \TeX\ allows \.[\\relax] to
  9900  // appear before the |left_brace|.
  9901  func (prg *prg) scanLeftBrace() {
  9902  	for {
  9903  		prg.getXToken()
  9904  		if int32(prg.curCmd) != spacer && int32(prg.curCmd) != relax {
  9905  			break
  9906  		}
  9907  	}
  9908  	if int32(prg.curCmd) != leftBrace {
  9909  		{
  9910  			if int32(prg.interaction) == errorStopMode {
  9911  			}
  9912  			prg.printNl(strNumber( /* "! " */ 262))
  9913  			prg.print( /* "Missing [ inserted" */ 657)
  9914  		}
  9915  		// \xref[Missing \[ inserted]
  9916  		{
  9917  			prg.helpPtr = 4
  9918  			prg.helpLine[3] = /* "A left brace was mandatory here, so I've put one in." */ 658
  9919  			prg.helpLine[2] = /* "You might want to delete and/or insert some corrections" */ 659
  9920  			prg.helpLine[1] = /* "so that I will find a matching right brace soon." */ 660
  9921  			prg.helpLine[0] = /* "(If you're confused by all this, try typing `I]' now.)" */ 661
  9922  		}
  9923  		prg.backError()
  9924  		prg.curTok = uint16(leftBraceToken + '{')
  9925  		prg.curCmd = byte(leftBrace)
  9926  		prg.curChr = '{'
  9927  		prg.alignState = prg.alignState + 1
  9928  	}
  9929  }
  9930  
  9931  // 405.
  9932  
  9933  // tangle:pos tex.web:8212:1:
  9934  
  9935  // The |scan_optional_equals| routine looks for an optional `\.=' sign preceded
  9936  // by optional spaces; `\.[\\relax]' is not ignored here.
  9937  func (prg *prg) scanOptionalEquals() {
  9938  	for {
  9939  		prg.getXToken()
  9940  		if int32(prg.curCmd) != spacer {
  9941  			break
  9942  		}
  9943  	}
  9944  	if int32(prg.curTok) != otherToken+'=' {
  9945  		prg.backInput()
  9946  	}
  9947  }
  9948  
  9949  // 407.
  9950  
  9951  // tangle:pos tex.web:8224:1:
  9952  
  9953  // In case you are getting bored, here is a slightly less trivial routine:
  9954  // Given a string of lowercase letters, like `\.[pt]' or `\.[plus]' or
  9955  // `\.[width]', the |scan_keyword| routine checks to see whether the next
  9956  // tokens of input match this string. The match must be exact, except that
  9957  // uppercase letters will match their lowercase counterparts; uppercase
  9958  // equivalents are determined by subtracting |"a"-"A"|, rather than using the
  9959  // |uc_code| table, since \TeX\ uses this routine only for its own limited
  9960  // set of keywords.
  9961  //
  9962  // If a match is found, the characters are effectively removed from the input
  9963  // and |true| is returned. Otherwise |false| is returned, and the input
  9964  // is left essentially unchanged (except for the fact that some macros
  9965  // may have been expanded, etc.).
  9966  // \xref[inner loop]
  9967  func (prg *prg) scanKeyword(s strNumber) (r bool) {
  9968  	var (
  9969  		p halfword    // tail of the backup list
  9970  		q halfword    // new node being added to the token list via |store_new_token|
  9971  		k poolPointer // index into |str_pool|
  9972  	)
  9973  	p = uint16(30000 - 13)
  9974  	*(*prg.mem[p].hh()).rh() = 0
  9975  	k = prg.strStart[s]
  9976  	for int32(k) < int32(prg.strStart[int32(s)+1]) {
  9977  		prg.getXToken() // recursion is possible here
  9978  		// \xref[recursion]
  9979  		if int32(prg.curCs) == 0 && (int32(prg.curChr) == int32(prg.strPool[k]) || int32(prg.curChr) == int32(prg.strPool[k])-'a'+'A') {
  9980  			{
  9981  				q = prg.getAvail()
  9982  				*(*prg.mem[p].hh()).rh() = q
  9983  				*(*prg.mem[q].hh()).lh() = prg.curTok
  9984  				p = q
  9985  			}
  9986  			k = uint16(int32(k) + 1)
  9987  		} else if int32(prg.curCmd) != spacer || int32(p) != 30000-13 {
  9988  			prg.backInput()
  9989  			if int32(p) != 30000-13 {
  9990  				prg.beginTokenList(*(*prg.mem[30000-13].hh()).rh(), quarterword(backedUp))
  9991  			}
  9992  			r = false
  9993  			goto exit
  9994  		}
  9995  	}
  9996  	prg.flushList(*(*prg.mem[30000-13].hh()).rh())
  9997  	r = true
  9998  
  9999  exit:
 10000  	;
 10001  	return r
 10002  }
 10003  
 10004  // 408.
 10005  
 10006  // tangle:pos tex.web:8261:1:
 10007  
 10008  // Here is a procedure that sounds an alarm when mu and non-mu units
 10009  // are being switched.
 10010  func (prg *prg) muError() {
 10011  	{
 10012  		if int32(prg.interaction) == errorStopMode {
 10013  		}
 10014  		prg.printNl(strNumber( /* "! " */ 262))
 10015  		prg.print( /* "Incompatible glue units" */ 662)
 10016  	}
 10017  	// \xref[Incompatible glue units]
 10018  	{
 10019  		prg.helpPtr = 1
 10020  		prg.helpLine[0] = /* "I'm going to assume that 1mu=1pt when they're mixed." */ 663
 10021  	}
 10022  	prg.error1()
 10023  } // scans an integer value
 10024  // \4\4
 10025  // Declare procedures that scan restricted classes of integers
 10026  func (prg *prg) scanEightBitInt() {
 10027  	prg.scanInt()
 10028  	if prg.curVal < 0 || prg.curVal > 255 {
 10029  		{
 10030  			if int32(prg.interaction) == errorStopMode {
 10031  			}
 10032  			prg.printNl(strNumber( /* "! " */ 262))
 10033  			prg.print( /* "Bad register code" */ 687)
 10034  		}
 10035  		// \xref[Bad register code]
 10036  		{
 10037  			prg.helpPtr = 2
 10038  			prg.helpLine[1] = /* "A register number must be between 0 and 255." */ 688
 10039  			prg.helpLine[0] = /* "I changed this one to zero." */ 689
 10040  		}
 10041  		prg.intError(prg.curVal)
 10042  		prg.curVal = 0
 10043  	}
 10044  }
 10045  
 10046  func (prg *prg) scanCharNum() {
 10047  	prg.scanInt()
 10048  	if prg.curVal < 0 || prg.curVal > 255 {
 10049  		{
 10050  			if int32(prg.interaction) == errorStopMode {
 10051  			}
 10052  			prg.printNl(strNumber( /* "! " */ 262))
 10053  			prg.print( /* "Bad character code" */ 690)
 10054  		}
 10055  		// \xref[Bad character code]
 10056  		{
 10057  			prg.helpPtr = 2
 10058  			prg.helpLine[1] = /* "A character number must be between 0 and 255." */ 691
 10059  			prg.helpLine[0] = /* "I changed this one to zero." */ 689
 10060  		}
 10061  		prg.intError(prg.curVal)
 10062  		prg.curVal = 0
 10063  	}
 10064  }
 10065  
 10066  func (prg *prg) scanFourBitInt() {
 10067  	prg.scanInt()
 10068  	if prg.curVal < 0 || prg.curVal > 15 {
 10069  		{
 10070  			if int32(prg.interaction) == errorStopMode {
 10071  			}
 10072  			prg.printNl(strNumber( /* "! " */ 262))
 10073  			prg.print( /* "Bad number" */ 692)
 10074  		}
 10075  		// \xref[Bad number]
 10076  		{
 10077  			prg.helpPtr = 2
 10078  			prg.helpLine[1] = /* "Since I expected to read a number between 0 and 15," */ 693
 10079  			prg.helpLine[0] = /* "I changed this one to zero." */ 689
 10080  		}
 10081  		prg.intError(prg.curVal)
 10082  		prg.curVal = 0
 10083  	}
 10084  }
 10085  
 10086  func (prg *prg) scanFifteenBitInt() {
 10087  	prg.scanInt()
 10088  	if prg.curVal < 0 || prg.curVal > 077777 {
 10089  		{
 10090  			if int32(prg.interaction) == errorStopMode {
 10091  			}
 10092  			prg.printNl(strNumber( /* "! " */ 262))
 10093  			prg.print( /* "Bad mathchar" */ 694)
 10094  		}
 10095  		// \xref[Bad mathchar]
 10096  		{
 10097  			prg.helpPtr = 2
 10098  			prg.helpLine[1] = /* "A mathchar number must be between 0 and 32767." */ 695
 10099  			prg.helpLine[0] = /* "I changed this one to zero." */ 689
 10100  		}
 10101  		prg.intError(prg.curVal)
 10102  		prg.curVal = 0
 10103  	}
 10104  }
 10105  
 10106  func (prg *prg) scanTwentySevenBitInt() {
 10107  	prg.scanInt()
 10108  	if prg.curVal < 0 || prg.curVal > 0777777777 {
 10109  		{
 10110  			if int32(prg.interaction) == errorStopMode {
 10111  			}
 10112  			prg.printNl(strNumber( /* "! " */ 262))
 10113  			prg.print( /* "Bad delimiter code" */ 696)
 10114  		}
 10115  		// \xref[Bad delimiter code]
 10116  		{
 10117  			prg.helpPtr = 2
 10118  			prg.helpLine[1] = /* "A numeric delimiter code must be between 0 and 2^[27]-1." */ 697
 10119  			prg.helpLine[0] = /* "I changed this one to zero." */ 689
 10120  		}
 10121  		prg.intError(prg.curVal)
 10122  		prg.curVal = 0
 10123  	}
 10124  }
 10125  
 10126  // \4\4
 10127  // Declare procedures that scan font-related stuff
 10128  func (prg *prg) scanFontIdent() {
 10129  	var (
 10130  		f internalFontNumber
 10131  		m halfword
 10132  	)
 10133  	for {
 10134  		prg.getXToken()
 10135  		if int32(prg.curCmd) != spacer {
 10136  			break
 10137  		}
 10138  	}
 10139  	if int32(prg.curCmd) == defFont {
 10140  		f = byte(*(*prg.eqtb[curFontLoc-1].hh()).rh())
 10141  	} else if int32(prg.curCmd) == setFont {
 10142  		f = byte(prg.curChr)
 10143  	} else if int32(prg.curCmd) == defFamily {
 10144  		m = prg.curChr
 10145  		prg.scanFourBitInt()
 10146  		f = byte(*(*prg.eqtb[int32(m)+prg.curVal-1].hh()).rh())
 10147  	} else {
 10148  		{
 10149  			if int32(prg.interaction) == errorStopMode {
 10150  			}
 10151  			prg.printNl(strNumber( /* "! " */ 262))
 10152  			prg.print( /* "Missing font identifier" */ 817)
 10153  		}
 10154  		// \xref[Missing font identifier]
 10155  		{
 10156  			prg.helpPtr = 2
 10157  			prg.helpLine[1] = /* "I was looking for a control sequence whose" */ 818
 10158  			prg.helpLine[0] = /* "current meaning has been defined by \\font." */ 819
 10159  		}
 10160  		prg.backError()
 10161  		f = byte(fontBase)
 10162  	}
 10163  	prg.curVal = int32(f)
 10164  }
 10165  
 10166  func (prg *prg) findFontDimen(writing bool) {
 10167  	// sets |cur_val| to |font_info| location
 10168  	var (
 10169  		f internalFontNumber
 10170  		n int32 // the parameter number
 10171  	)
 10172  	prg.scanInt()
 10173  	n = prg.curVal
 10174  	prg.scanFontIdent()
 10175  	f = byte(prg.curVal)
 10176  	if n <= 0 {
 10177  		prg.curVal = int32(prg.fmemPtr)
 10178  	} else {
 10179  		if writing && n <= spaceShrinkCode && n >= spaceCode && int32(prg.fontGlue[f]) != 0 {
 10180  			prg.deleteGlueRef(prg.fontGlue[f])
 10181  			prg.fontGlue[f] = 0
 10182  		}
 10183  		if n > int32(prg.fontParams[f]) {
 10184  			if int32(f) < int32(prg.fontPtr) {
 10185  				prg.curVal = int32(prg.fmemPtr)
 10186  			} else {
 10187  				// Increase the number of parameters in the last font
 10188  				for {
 10189  					if int32(prg.fmemPtr) == fontMemSize {
 10190  						prg.overflow(strNumber( /* "font memory" */ 824), fontMemSize)
 10191  					}
 10192  					// \xref[TeX capacity exceeded font memory][\quad font memory]
 10193  					*prg.fontInfo[prg.fmemPtr].int() = 0
 10194  					prg.fmemPtr = uint16(int32(prg.fmemPtr) + 1)
 10195  					prg.fontParams[f] = uint16(int32(prg.fontParams[f]) + 1)
 10196  					if n == int32(prg.fontParams[f]) {
 10197  						break
 10198  					}
 10199  				}
 10200  				prg.curVal = int32(prg.fmemPtr) - 1 // this equals |param_base[f]+font_params[f]|
 10201  			}
 10202  		} else {
 10203  			prg.curVal = n + prg.paramBase[f]
 10204  		}
 10205  	}
 10206  
 10207  	// Issue an error message if |cur_val=fmem_ptr|
 10208  	if prg.curVal == int32(prg.fmemPtr) {
 10209  		{
 10210  			if int32(prg.interaction) == errorStopMode {
 10211  			}
 10212  			prg.printNl(strNumber( /* "! " */ 262))
 10213  			prg.print( /* "Font " */ 802)
 10214  		}
 10215  		prg.printEsc(*prg.hash[fontIdBase+int32(f)-514].rh())
 10216  		prg.print( /* " has only " */ 820)
 10217  		prg.printInt(int32(prg.fontParams[f]))
 10218  		prg.print( /* " fontdimen parameters" */ 821)
 10219  		// \xref[Font x has only...]
 10220  		{
 10221  			prg.helpPtr = 2
 10222  			prg.helpLine[1] = /* "To increase the number of font parameters, you must" */ 822
 10223  			prg.helpLine[0] = /* "use \\fontdimen immediately after the \\font is loaded." */ 823
 10224  		}
 10225  		prg.error1()
 10226  	}
 10227  }
 10228  
 10229  // 413.
 10230  
 10231  // tangle:pos tex.web:8345:1:
 10232  
 10233  // OK, we're ready for |scan_something_internal| itself. A second parameter,
 10234  // |negative|, is set |true| if the value that is found should be negated.
 10235  // It is assumed that |cur_cmd| and |cur_chr| represent the first token of
 10236  // the internal quantity to be scanned; an error will be signalled if
 10237  // |cur_cmd<min_internal| or |cur_cmd>max_internal|.
 10238  func (prg *prg) scanSomethingInternal(level smallNumber, negative bool) {
 10239  	// fetch an internal parameter
 10240  	var (
 10241  		m                       halfword // |chr_code| part of the operand token
 10242  		p/* 0..nestSize */ byte          // index into |nest|
 10243  	)
 10244  	m = prg.curChr
 10245  	switch prg.curCmd {
 10246  	case defCode:
 10247  		// Fetch a character code from some table
 10248  		prg.scanCharNum()
 10249  		if int32(m) == mathCodeBase {
 10250  			prg.curVal = int32(*(*prg.eqtb[mathCodeBase+prg.curVal-1].hh()).rh()) - 0
 10251  			prg.curValLevel = byte(intVal)
 10252  		} else if int32(m) < mathCodeBase {
 10253  			prg.curVal = int32(*(*prg.eqtb[int32(m)+prg.curVal-1].hh()).rh())
 10254  			prg.curValLevel = byte(intVal)
 10255  		} else {
 10256  			prg.curVal = *prg.eqtb[int32(m)+prg.curVal-1].int()
 10257  			prg.curValLevel = byte(intVal)
 10258  		}
 10259  
 10260  	case toksRegister, assignToks, defFamily, setFont,
 10261  		defFont:
 10262  		// Fetch a token list or font identifier, provided that |level=tok_val|
 10263  		if int32(level) != tokVal {
 10264  			{
 10265  				if int32(prg.interaction) == errorStopMode {
 10266  				}
 10267  				prg.printNl(strNumber( /* "! " */ 262))
 10268  				prg.print( /* "Missing number, treated as zero" */ 664)
 10269  			}
 10270  			// \xref[Missing number...]
 10271  			{
 10272  				prg.helpPtr = 3
 10273  				prg.helpLine[2] = /* "A number should have been here; I inserted `0'." */ 665
 10274  				prg.helpLine[1] = /* "(If you can't figure out why I needed to see a number," */ 666
 10275  				prg.helpLine[0] = /* "look up `weird error' in the index to The TeXbook.)" */ 667
 10276  			}
 10277  			// \xref[TeXbook][\sl The \TeX book]
 10278  			prg.backError()
 10279  			{
 10280  				prg.curVal = 0
 10281  				prg.curValLevel = byte(dimenVal)
 10282  			}
 10283  		} else if int32(prg.curCmd) <= assignToks {
 10284  			if int32(prg.curCmd) < assignToks {
 10285  				prg.scanEightBitInt()
 10286  				m = uint16(toksBase + prg.curVal)
 10287  			}
 10288  			{
 10289  				prg.curVal = int32(*(*prg.eqtb[m-1].hh()).rh())
 10290  				prg.curValLevel = byte(tokVal)
 10291  			}
 10292  		} else {
 10293  			prg.backInput()
 10294  			prg.scanFontIdent()
 10295  			{
 10296  				prg.curVal = fontIdBase + prg.curVal
 10297  				prg.curValLevel = byte(identVal)
 10298  			}
 10299  		}
 10300  
 10301  	case assignInt:
 10302  		prg.curVal = *prg.eqtb[m-1].int()
 10303  		prg.curValLevel = byte(intVal)
 10304  	case assignDimen:
 10305  		prg.curVal = *prg.eqtb[m-1].int()
 10306  		prg.curValLevel = byte(dimenVal)
 10307  	case assignGlue:
 10308  		prg.curVal = int32(*(*prg.eqtb[m-1].hh()).rh())
 10309  		prg.curValLevel = byte(glueVal)
 10310  	case assignMuGlue:
 10311  		prg.curVal = int32(*(*prg.eqtb[m-1].hh()).rh())
 10312  		prg.curValLevel = byte(muVal)
 10313  	case setAux:
 10314  		// Fetch the |space_factor| or the |prev_depth|
 10315  		if abs(int32(prg.curList.modeField)) != int32(m) {
 10316  			{
 10317  				if int32(prg.interaction) == errorStopMode {
 10318  				}
 10319  				prg.printNl(strNumber( /* "! " */ 262))
 10320  				prg.print( /* "Improper " */ 680)
 10321  			}
 10322  			prg.printCmdChr(quarterword(setAux), m)
 10323  			// \xref[Improper \\spacefactor]
 10324  			// \xref[Improper \\prevdepth]
 10325  			{
 10326  				prg.helpPtr = 4
 10327  				prg.helpLine[3] = /* "You can refer to \\spacefactor only in horizontal mode;" */ 681
 10328  				prg.helpLine[2] = /* "you can refer to \\prevdepth only in vertical mode; and" */ 682
 10329  				prg.helpLine[1] = /* "neither of these is meaningful inside \\write. So" */ 683
 10330  				prg.helpLine[0] = /* "I'm forgetting what you said and using zero instead." */ 684
 10331  			}
 10332  			prg.error1()
 10333  			if int32(level) != tokVal {
 10334  				prg.curVal = 0
 10335  				prg.curValLevel = byte(dimenVal)
 10336  			} else {
 10337  				prg.curVal = 0
 10338  				prg.curValLevel = byte(intVal)
 10339  			}
 10340  		} else if int32(m) == vmode {
 10341  			prg.curVal = *prg.curList.auxField.int()
 10342  			prg.curValLevel = byte(dimenVal)
 10343  		} else {
 10344  			prg.curVal = int32(*(*prg.curList.auxField.hh()).lh())
 10345  			prg.curValLevel = byte(intVal)
 10346  		}
 10347  
 10348  	case setPrevGraf:
 10349  		// Fetch the |prev_graf|
 10350  		if int32(prg.curList.modeField) == 0 {
 10351  			prg.curVal = 0
 10352  			prg.curValLevel = byte(intVal)
 10353  		} else {
 10354  			prg.nest[prg.nestPtr] = prg.curList
 10355  			p = prg.nestPtr
 10356  			for abs(int32(prg.nest[p].modeField)) != vmode {
 10357  				p = byte(int32(p) - 1)
 10358  			}
 10359  			{
 10360  				prg.curVal = prg.nest[p].pgField
 10361  				prg.curValLevel = byte(intVal)
 10362  			}
 10363  		}
 10364  
 10365  	case setPageInt:
 10366  		// Fetch the |dead_cycles| or the |insert_penalties|
 10367  		if int32(m) == 0 {
 10368  			prg.curVal = prg.deadCycles
 10369  		} else {
 10370  			prg.curVal = prg.insertPenalties
 10371  		}
 10372  		prg.curValLevel = byte(intVal)
 10373  
 10374  	case setPageDimen:
 10375  		// Fetch something on the |page_so_far|
 10376  		if int32(prg.pageContents) == empty && !prg.outputActive {
 10377  			if int32(m) == 0 {
 10378  				prg.curVal = 07777777777
 10379  			} else {
 10380  				prg.curVal = 0
 10381  			}
 10382  		} else {
 10383  			prg.curVal = prg.pageSoFar[m]
 10384  		}
 10385  		prg.curValLevel = byte(dimenVal)
 10386  
 10387  	case setShape:
 10388  		// Fetch the |par_shape| size
 10389  		if int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh()) == 0 {
 10390  			prg.curVal = 0
 10391  		} else {
 10392  			prg.curVal = int32(*(*prg.mem[*(*prg.eqtb[parShapeLoc-1].hh()).rh()].hh()).lh())
 10393  		}
 10394  		prg.curValLevel = byte(intVal)
 10395  
 10396  	case setBoxDimen:
 10397  		// Fetch a box dimension
 10398  		prg.scanEightBitInt()
 10399  		if int32(*(*prg.eqtb[boxBase+prg.curVal-1].hh()).rh()) == 0 {
 10400  			prg.curVal = 0
 10401  		} else {
 10402  			prg.curVal = *prg.mem[int32(*(*prg.eqtb[boxBase+prg.curVal-1].hh()).rh())+int32(m)].int()
 10403  		}
 10404  		prg.curValLevel = byte(dimenVal)
 10405  
 10406  	case charGiven, mathGiven:
 10407  		prg.curVal = int32(prg.curChr)
 10408  		prg.curValLevel = byte(intVal)
 10409  	case assignFontDimen:
 10410  		// Fetch a font dimension
 10411  		prg.findFontDimen(false)
 10412  		*prg.fontInfo[prg.fmemPtr].int() = 0
 10413  		{
 10414  			prg.curVal = *prg.fontInfo[prg.curVal].int()
 10415  			prg.curValLevel = byte(dimenVal)
 10416  		}
 10417  
 10418  	case assignFontInt:
 10419  		// Fetch a font integer
 10420  		prg.scanFontIdent()
 10421  		if int32(m) == 0 {
 10422  			prg.curVal = prg.hyphenChar[prg.curVal]
 10423  			prg.curValLevel = byte(intVal)
 10424  		} else {
 10425  			prg.curVal = prg.skewChar[prg.curVal]
 10426  			prg.curValLevel = byte(intVal)
 10427  		}
 10428  
 10429  	case register:
 10430  		// Fetch a register
 10431  		prg.scanEightBitInt()
 10432  		switch m {
 10433  		case intVal:
 10434  			prg.curVal = *prg.eqtb[countBase+prg.curVal-1].int()
 10435  		case dimenVal:
 10436  			prg.curVal = *prg.eqtb[scaledBase+prg.curVal-1].int()
 10437  		case glueVal:
 10438  			prg.curVal = int32(*(*prg.eqtb[skipBase+prg.curVal-1].hh()).rh())
 10439  		case muVal:
 10440  			prg.curVal = int32(*(*prg.eqtb[muSkipBase+prg.curVal-1].hh()).rh())
 10441  		} // there are no other cases
 10442  		prg.curValLevel = byte(m)
 10443  
 10444  	case lastItem:
 10445  		// Fetch an item in the current node, if appropriate
 10446  		if int32(prg.curChr) > glueVal {
 10447  			if int32(prg.curChr) == inputLineNoCode {
 10448  				prg.curVal = prg.line
 10449  			} else {
 10450  				prg.curVal = prg.lastBadness
 10451  			} // |cur_chr=badness_code|
 10452  			prg.curValLevel = byte(intVal)
 10453  		} else {
 10454  			if int32(prg.curChr) == glueVal {
 10455  				prg.curVal = memBot
 10456  			} else {
 10457  				prg.curVal = 0
 10458  			}
 10459  			prg.curValLevel = byte(prg.curChr)
 10460  			if !(int32(prg.curList.tailField) >= int32(prg.hiMemMin)) && int32(prg.curList.modeField) != 0 {
 10461  				switch prg.curChr {
 10462  				case intVal:
 10463  					if int32(*(*prg.mem[prg.curList.tailField].hh()).b0()) == penaltyNode {
 10464  						prg.curVal = *prg.mem[int32(prg.curList.tailField)+1].int()
 10465  					}
 10466  				case dimenVal:
 10467  					if int32(*(*prg.mem[prg.curList.tailField].hh()).b0()) == kernNode {
 10468  						prg.curVal = *prg.mem[int32(prg.curList.tailField)+widthOffset].int()
 10469  					}
 10470  				case glueVal:
 10471  					if int32(*(*prg.mem[prg.curList.tailField].hh()).b0()) == glueNode {
 10472  						prg.curVal = int32(*(*prg.mem[int32(prg.curList.tailField)+1].hh()).lh())
 10473  						if int32(*(*prg.mem[prg.curList.tailField].hh()).b1()) == muGlue {
 10474  							prg.curValLevel = byte(muVal)
 10475  						}
 10476  					}
 10477  				}
 10478  			} else if int32(prg.curList.modeField) == vmode && int32(prg.curList.tailField) == int32(prg.curList.headField) {
 10479  				switch prg.curChr {
 10480  				case intVal:
 10481  					prg.curVal = prg.lastPenalty
 10482  				case dimenVal:
 10483  					prg.curVal = prg.lastKern
 10484  				case glueVal:
 10485  					if int32(prg.lastGlue) != 65535 {
 10486  						prg.curVal = int32(prg.lastGlue)
 10487  					}
 10488  				}
 10489  			} // there are no other cases
 10490  		}
 10491  
 10492  	default:
 10493  		{
 10494  			if int32(prg.interaction) == errorStopMode {
 10495  			}
 10496  			prg.printNl(strNumber( /* "! " */ 262))
 10497  			prg.print( /* "You can't use `" */ 685)
 10498  		}
 10499  		prg.printCmdChr(prg.curCmd, prg.curChr)
 10500  		// \xref[You can't use x after ...]
 10501  		prg.print( /* "' after " */ 686)
 10502  		prg.printEsc(strNumber( /* "the" */ 537))
 10503  		{
 10504  			prg.helpPtr = 1
 10505  			prg.helpLine[0] = /* "I'm forgetting what you said and using zero instead." */ 684
 10506  		}
 10507  		prg.error1()
 10508  		if int32(level) != tokVal {
 10509  			prg.curVal = 0
 10510  			prg.curValLevel = byte(dimenVal)
 10511  		} else {
 10512  			prg.curVal = 0
 10513  			prg.curValLevel = byte(intVal)
 10514  		}
 10515  
 10516  	}
 10517  
 10518  	for int32(prg.curValLevel) > int32(level) {
 10519  		// Convert \(c)|cur_val| to a lower level
 10520  		if int32(prg.curValLevel) == glueVal {
 10521  			prg.curVal = *prg.mem[prg.curVal+widthOffset].int()
 10522  		} else if int32(prg.curValLevel) == muVal {
 10523  			prg.muError()
 10524  		}
 10525  		prg.curValLevel = byte(int32(prg.curValLevel) - 1)
 10526  	}
 10527  
 10528  	// Fix the reference count, if any, and negate |cur_val| if |negative|
 10529  	if negative {
 10530  		if int32(prg.curValLevel) >= glueVal {
 10531  			prg.curVal = int32(prg.newSpec(halfword(prg.curVal)))
 10532  
 10533  			// Negate all three glue components of |cur_val|
 10534  			{
 10535  				*prg.mem[prg.curVal+widthOffset].int() = -*prg.mem[prg.curVal+widthOffset].int()
 10536  				*prg.mem[prg.curVal+2].int() = -*prg.mem[prg.curVal+2].int()
 10537  				*prg.mem[prg.curVal+3].int() = -*prg.mem[prg.curVal+3].int()
 10538  			}
 10539  		} else {
 10540  			prg.curVal = -prg.curVal
 10541  		}
 10542  	} else if int32(prg.curValLevel) >= glueVal && int32(prg.curValLevel) <= muVal {
 10543  		*(*prg.mem[prg.curVal].hh()).rh() = uint16(int32(*(*prg.mem[prg.curVal].hh()).rh()) + 1)
 10544  	}
 10545  }
 10546  
 10547  // 409.
 10548  
 10549  // tangle:pos tex.web:8271:1:
 10550  
 10551  // The next routine `|scan_something_internal|' is used to fetch internal
 10552  // numeric quantities like `\.[\\hsize]', and also to handle the `\.[\\the]'
 10553  // when expanding constructions like `\.[\\the\\toks0]' and
 10554  // `\.[\\the\\baselineskip]'. Soon we will be considering the |scan_int|
 10555  // procedure, which calls |scan_something_internal|; on the other hand,
 10556  // |scan_something_internal| also calls |scan_int|, for constructions like
 10557  // `\.[\\catcode\`\\\$]' or `\.[\\fontdimen] \.3 \.[\\ff]'. So we
 10558  // have to declare |scan_int| as a |forward| procedure. A few other
 10559  // procedures are also declared at this point.
 10560  func (prg *prg) scanInt() {
 10561  	var (
 10562  		negative bool        // should the answer be negated?
 10563  		m        int32       // |$2^[31]$ div radix|, the threshold of danger
 10564  		d        smallNumber // the digit just scanned
 10565  		vacuous  bool        // have no digits appeared?
 10566  		okSoFar  bool        // has an error message been issued?
 10567  	)
 10568  	prg.radix = 0
 10569  	okSoFar = true
 10570  
 10571  	// Get the next non-blank non-sign token; set |negative| appropriately
 10572  	negative = false
 10573  	for {
 10574  		// Get the next non-blank non-call token
 10575  		for {
 10576  			prg.getXToken()
 10577  			if int32(prg.curCmd) != spacer {
 10578  				break
 10579  			}
 10580  		}
 10581  		if int32(prg.curTok) == otherToken+'-' {
 10582  			negative = !negative
 10583  			prg.curTok = uint16(otherToken + '+')
 10584  		}
 10585  		if int32(prg.curTok) != otherToken+'+' {
 10586  			break
 10587  		}
 10588  	}
 10589  	if int32(prg.curTok) == alphaToken {
 10590  		prg.getToken() // suppress macro expansion
 10591  		if int32(prg.curTok) < 07777 {
 10592  			prg.curVal = int32(prg.curChr)
 10593  			if int32(prg.curCmd) <= rightBrace {
 10594  				if int32(prg.curCmd) == rightBrace {
 10595  					prg.alignState = prg.alignState + 1
 10596  				} else {
 10597  					prg.alignState = prg.alignState - 1
 10598  				}
 10599  			}
 10600  		} else if int32(prg.curTok) < 07777+singleBase {
 10601  			prg.curVal = int32(prg.curTok) - 07777 - activeBase
 10602  		} else {
 10603  			prg.curVal = int32(prg.curTok) - 07777 - singleBase
 10604  		}
 10605  		if prg.curVal > 255 {
 10606  			{
 10607  				if int32(prg.interaction) == errorStopMode {
 10608  				}
 10609  				prg.printNl(strNumber( /* "! " */ 262))
 10610  				prg.print( /* "Improper alphabetic constant" */ 698)
 10611  			}
 10612  			// \xref[Improper alphabetic constant]
 10613  			{
 10614  				prg.helpPtr = 2
 10615  				prg.helpLine[1] = /* "A one-character control sequence belongs after a ` mark." */ 699
 10616  				prg.helpLine[0] = /* "So I'm essentially inserting \\0 here." */ 700
 10617  			}
 10618  			prg.curVal = '0'
 10619  			prg.backError()
 10620  		} else {
 10621  			// Scan an optional space
 10622  			prg.getXToken()
 10623  			if int32(prg.curCmd) != spacer {
 10624  				prg.backInput()
 10625  			}
 10626  		}
 10627  	} else if int32(prg.curCmd) >= minInternal && int32(prg.curCmd) <= maxInternal {
 10628  		prg.scanSomethingInternal(smallNumber(intVal), false)
 10629  	} else {
 10630  		// Scan a numeric constant
 10631  		prg.radix = 10
 10632  		m = 214748364
 10633  		if int32(prg.curTok) == octalToken {
 10634  			prg.radix = 8
 10635  			m = 02000000000
 10636  			prg.getXToken()
 10637  		} else if int32(prg.curTok) == hexToken {
 10638  			prg.radix = 16
 10639  			m = 01000000000
 10640  			prg.getXToken()
 10641  		}
 10642  		vacuous = true
 10643  		prg.curVal = 0
 10644  
 10645  		// Accumulate the constant until |cur_tok| is not a suitable digit
 10646  		for true {
 10647  			if int32(prg.curTok) < zeroToken+int32(prg.radix) && int32(prg.curTok) >= zeroToken && int32(prg.curTok) <= zeroToken+9 {
 10648  				d = byte(int32(prg.curTok) - zeroToken)
 10649  			} else if int32(prg.radix) == 16 {
 10650  				if int32(prg.curTok) <= aToken+5 && int32(prg.curTok) >= aToken {
 10651  					d = byte(int32(prg.curTok) - aToken + 10)
 10652  				} else if int32(prg.curTok) <= otherAToken+5 && int32(prg.curTok) >= otherAToken {
 10653  					d = byte(int32(prg.curTok) - otherAToken + 10)
 10654  				} else {
 10655  					goto done
 10656  				}
 10657  			} else {
 10658  				goto done
 10659  			}
 10660  			vacuous = false
 10661  			if prg.curVal >= m && (prg.curVal > m || int32(d) > 7 || int32(prg.radix) != 10) {
 10662  				if okSoFar {
 10663  					{
 10664  						if int32(prg.interaction) == errorStopMode {
 10665  						}
 10666  						prg.printNl(strNumber( /* "! " */ 262))
 10667  						prg.print( /* "Number too big" */ 701)
 10668  					}
 10669  					// \xref[Number too big]
 10670  					{
 10671  						prg.helpPtr = 2
 10672  						prg.helpLine[1] = /* "I can only go up to 2147483647='17777777777=\"7FFFFFFF," */ 702
 10673  						prg.helpLine[0] = /* "so I'm using that number instead of yours." */ 703
 10674  					}
 10675  					prg.error1()
 10676  					prg.curVal = 017777777777
 10677  					okSoFar = false
 10678  				}
 10679  			} else {
 10680  				prg.curVal = prg.curVal*int32(prg.radix) + int32(d)
 10681  			}
 10682  			prg.getXToken()
 10683  		}
 10684  
 10685  	done:
 10686  		;
 10687  		if vacuous {
 10688  			{
 10689  				if int32(prg.interaction) == errorStopMode {
 10690  				}
 10691  				prg.printNl(strNumber( /* "! " */ 262))
 10692  				prg.print( /* "Missing number, treated as zero" */ 664)
 10693  			}
 10694  			// \xref[Missing number...]
 10695  			{
 10696  				prg.helpPtr = 3
 10697  				prg.helpLine[2] = /* "A number should have been here; I inserted `0'." */ 665
 10698  				prg.helpLine[1] = /* "(If you can't figure out why I needed to see a number," */ 666
 10699  				prg.helpLine[0] = /* "look up `weird error' in the index to The TeXbook.)" */ 667
 10700  			}
 10701  			// \xref[TeXbook][\sl The \TeX book]
 10702  			prg.backError()
 10703  		} else if int32(prg.curCmd) != spacer {
 10704  			prg.backInput()
 10705  		}
 10706  	}
 10707  	if negative {
 10708  		prg.curVal = -prg.curVal
 10709  	}
 10710  }
 10711  
 10712  // 448.
 10713  
 10714  // tangle:pos tex.web:8829:1:
 10715  
 10716  // Constructions like `\.[-\'77 pt]' are legal dimensions, so |scan_dimen|
 10717  // may begin with |scan_int|. This explains why it is convenient to use
 10718  // |scan_int| also for the integer part of a decimal fraction.
 10719  //
 10720  // Several branches of |scan_dimen| work with |cur_val| as an integer and
 10721  // with an auxiliary fraction |f|, so that the actual quantity of interest is
 10722  // $|cur_val|+|f|/2^[16]$. At the end of the routine, this ``unpacked''
 10723  // representation is put into the single word |cur_val|, which suddenly
 10724  // switches significance from |integer| to |scaled|.
 10725  func (prg *prg) scanDimen(mu, inf, shortcut bool) {
 10726  	var (
 10727  		negative bool  // should the answer be negated?
 10728  		f        int32 // numerator of a fraction whose denominator is $2^[16]$
 10729  
 10730  		// Local variables for dimension calculations
 10731  		num, denom/* 1..65536 */ uint32             // conversion ratio for the scanned units
 10732  		k, kk                           smallNumber // number of digits in a decimal fraction
 10733  		p, q                            halfword    // top of decimal digit stack
 10734  		v                               scaled      // an internal dimension
 10735  		saveCurVal                      int32       // temporary storage of |cur_val|
 10736  	)
 10737  	f = 0
 10738  	prg.arithError = false
 10739  	prg.curOrder = byte(normal)
 10740  	negative = false
 10741  	if !shortcut {
 10742  		negative = false
 10743  		for {
 10744  			// Get the next non-blank non-call token
 10745  			for {
 10746  				prg.getXToken()
 10747  				if int32(prg.curCmd) != spacer {
 10748  					break
 10749  				}
 10750  			}
 10751  			if int32(prg.curTok) == otherToken+'-' {
 10752  				negative = !negative
 10753  				prg.curTok = uint16(otherToken + '+')
 10754  			}
 10755  			if int32(prg.curTok) != otherToken+'+' {
 10756  				break
 10757  			}
 10758  		}
 10759  		if int32(prg.curCmd) >= minInternal && int32(prg.curCmd) <= maxInternal {
 10760  			if mu {
 10761  				prg.scanSomethingInternal(smallNumber(muVal), false)
 10762  
 10763  				// Coerce glue to a dimension
 10764  				if int32(prg.curValLevel) >= glueVal {
 10765  					v = *prg.mem[prg.curVal+widthOffset].int()
 10766  					prg.deleteGlueRef(halfword(prg.curVal))
 10767  					prg.curVal = v
 10768  				}
 10769  				if int32(prg.curValLevel) == muVal {
 10770  					goto attachSign
 10771  				}
 10772  				if int32(prg.curValLevel) != intVal {
 10773  					prg.muError()
 10774  				}
 10775  			} else {
 10776  				prg.scanSomethingInternal(smallNumber(dimenVal), false)
 10777  				if int32(prg.curValLevel) == dimenVal {
 10778  					goto attachSign
 10779  				}
 10780  			}
 10781  		} else {
 10782  			prg.backInput()
 10783  			if int32(prg.curTok) == continentalPointToken {
 10784  				prg.curTok = uint16(pointToken)
 10785  			}
 10786  			if int32(prg.curTok) != pointToken {
 10787  				prg.scanInt()
 10788  			} else {
 10789  				prg.radix = 10
 10790  				prg.curVal = 0
 10791  			}
 10792  			if int32(prg.curTok) == continentalPointToken {
 10793  				prg.curTok = uint16(pointToken)
 10794  			}
 10795  			if int32(prg.radix) == 10 && int32(prg.curTok) == pointToken {
 10796  				k = 0
 10797  				p = 0
 10798  				prg.getToken() // |point_token| is being re-scanned
 10799  				for true {
 10800  					prg.getXToken()
 10801  					if int32(prg.curTok) > zeroToken+9 || int32(prg.curTok) < zeroToken {
 10802  						goto done1
 10803  					}
 10804  					if int32(k) < 17 {
 10805  						q = prg.getAvail()
 10806  						*(*prg.mem[q].hh()).rh() = p
 10807  						*(*prg.mem[q].hh()).lh() = uint16(int32(prg.curTok) - zeroToken)
 10808  						p = q
 10809  						k = byte(int32(k) + 1)
 10810  					}
 10811  				}
 10812  
 10813  			done1:
 10814  				for ii := int32(k); ii >= 1; ii-- {
 10815  					kk = smallNumber(ii)
 10816  					_ = kk
 10817  					prg.dig[int32(kk)-1] = byte(*(*prg.mem[p].hh()).lh())
 10818  					q = p
 10819  					p = *(*prg.mem[p].hh()).rh()
 10820  					{
 10821  						*(*prg.mem[q].hh()).rh() = prg.avail
 10822  						prg.avail = q /*    dyn_used:= dyn_used-1 ; [  ] */
 10823  					}
 10824  				}
 10825  				f = prg.roundDecimals(k)
 10826  				if int32(prg.curCmd) != spacer {
 10827  					prg.backInput()
 10828  				}
 10829  			}
 10830  		}
 10831  	}
 10832  	if prg.curVal < 0 {
 10833  		negative = !negative
 10834  		prg.curVal = -prg.curVal
 10835  	}
 10836  
 10837  	// Scan units and set |cur_val| to $x\cdot(|cur_val|+f/2^[16])$, where there are |x| sp per unit; |goto attach_sign| if the units are internal
 10838  	if inf {
 10839  		if prg.scanKeyword(strNumber( /* "fil" */ 311)) {
 10840  			prg.curOrder = byte(fil)
 10841  			for prg.scanKeyword(strNumber('l')) {
 10842  				if int32(prg.curOrder) == filll {
 10843  					{
 10844  						if int32(prg.interaction) == errorStopMode {
 10845  						}
 10846  						prg.printNl(strNumber( /* "! " */ 262))
 10847  						prg.print( /* "Illegal unit of measure (" */ 705)
 10848  					}
 10849  					// \xref[Illegal unit of measure]
 10850  					prg.print( /* "replaced by filll)" */ 706)
 10851  					{
 10852  						prg.helpPtr = 1
 10853  						prg.helpLine[0] = /* "I dddon't go any higher than filll." */ 707
 10854  					}
 10855  					prg.error1()
 10856  				} else {
 10857  					prg.curOrder = byte(int32(prg.curOrder) + 1)
 10858  				}
 10859  			}
 10860  
 10861  			goto attachFraction
 10862  		}
 10863  	}
 10864  
 10865  	// Scan for \(u)units that are internal dimensions; |goto attach_sign| with |cur_val| set if found
 10866  	saveCurVal = prg.curVal
 10867  
 10868  	// Get the next non-blank non-call...
 10869  	for {
 10870  		prg.getXToken()
 10871  		if int32(prg.curCmd) != spacer {
 10872  			break
 10873  		}
 10874  	}
 10875  	if int32(prg.curCmd) < minInternal || int32(prg.curCmd) > maxInternal {
 10876  		prg.backInput()
 10877  	} else {
 10878  		if mu {
 10879  			prg.scanSomethingInternal(smallNumber(muVal), false)
 10880  			// Coerce glue...
 10881  			if int32(prg.curValLevel) >= glueVal {
 10882  				v = *prg.mem[prg.curVal+widthOffset].int()
 10883  				prg.deleteGlueRef(halfword(prg.curVal))
 10884  				prg.curVal = v
 10885  			}
 10886  			if int32(prg.curValLevel) != muVal {
 10887  				prg.muError()
 10888  			}
 10889  		} else {
 10890  			prg.scanSomethingInternal(smallNumber(dimenVal), false)
 10891  		}
 10892  		v = prg.curVal
 10893  		goto found
 10894  	}
 10895  	if mu {
 10896  		goto notFound
 10897  	}
 10898  	if prg.scanKeyword(strNumber( /* "em" */ 708)) {
 10899  		v = *prg.fontInfo[quadCode+prg.paramBase[*(*prg.eqtb[curFontLoc-1].hh()).rh()]].int()
 10900  	} else if prg.scanKeyword(strNumber( /* "ex" */ 709)) {
 10901  		v = *prg.fontInfo[xHeightCode+prg.paramBase[*(*prg.eqtb[curFontLoc-1].hh()).rh()]].int()
 10902  	} else {
 10903  		goto notFound
 10904  	}
 10905  
 10906  	// Scan an optional space
 10907  	{
 10908  		prg.getXToken()
 10909  		if int32(prg.curCmd) != spacer {
 10910  			prg.backInput()
 10911  		}
 10912  	}
 10913  
 10914  found:
 10915  	prg.curVal = prg.multAndAdd(saveCurVal, v, prg.xnOverD(v, f, 0200000), scaled(07777777777))
 10916  
 10917  	goto attachSign
 10918  
 10919  notFound:
 10920  	;
 10921  	if mu {
 10922  		if prg.scanKeyword(strNumber( /* "mu" */ 337)) {
 10923  			goto attachFraction
 10924  		} else {
 10925  			{
 10926  				if int32(prg.interaction) == errorStopMode {
 10927  				}
 10928  				prg.printNl(strNumber( /* "! " */ 262))
 10929  				prg.print( /* "Illegal unit of measure (" */ 705)
 10930  			}
 10931  			prg.print( /* "mu inserted)" */ 710)
 10932  			// \xref[Illegal unit of measure]
 10933  			{
 10934  				prg.helpPtr = 4
 10935  				prg.helpLine[3] = /* "The unit of measurement in math glue must be mu." */ 711
 10936  				prg.helpLine[2] = /* "To recover gracefully from this error, it's best to" */ 712
 10937  				prg.helpLine[1] = /* "delete the erroneous units; e.g., type `2' to delete" */ 713
 10938  				prg.helpLine[0] = /* "two letters. (See Chapter 27 of The TeXbook.)" */ 714
 10939  			}
 10940  			// \xref[TeXbook][\sl The \TeX book]
 10941  			prg.error1()
 10942  			goto attachFraction
 10943  		}
 10944  	}
 10945  	if prg.scanKeyword(strNumber( /* "true" */ 704)) {
 10946  		prg.prepareMag()
 10947  		if *prg.eqtb[intBase+magCode-1].int() != 1000 {
 10948  			prg.curVal = prg.xnOverD(prg.curVal, 1000, *prg.eqtb[intBase+magCode-1].int())
 10949  			f = (1000*f + 0200000*prg.remainder) / *prg.eqtb[intBase+magCode-1].int()
 10950  			prg.curVal = prg.curVal + f/0200000
 10951  			f = f % 0200000
 10952  		}
 10953  	}
 10954  	// \xref[true]
 10955  	if prg.scanKeyword(strNumber( /* "pt" */ 397)) {
 10956  		goto attachFraction
 10957  	} // the easy case
 10958  	// \xref[pt]
 10959  
 10960  	// Scan for \(a)all other units and adjust |cur_val| and |f| accordingly; |goto done| in the case of scaled points
 10961  	if prg.scanKeyword(strNumber( /* "in" */ 715)) {
 10962  		num = 7227
 10963  		denom = 100
 10964  	} else if prg.scanKeyword(strNumber( /* "pc" */ 716)) {
 10965  		num = 12
 10966  		denom = 1
 10967  	} else if prg.scanKeyword(strNumber( /* "cm" */ 717)) {
 10968  		num = 7227
 10969  		denom = 254
 10970  	} else if prg.scanKeyword(strNumber( /* "mm" */ 718)) {
 10971  		num = 7227
 10972  		denom = 2540
 10973  	} else if prg.scanKeyword(strNumber( /* "bp" */ 719)) {
 10974  		num = 7227
 10975  		denom = 7200
 10976  	} else if prg.scanKeyword(strNumber( /* "dd" */ 720)) {
 10977  		num = 1238
 10978  		denom = 1157
 10979  	} else if prg.scanKeyword(strNumber( /* "cc" */ 721)) {
 10980  		num = 14856
 10981  		denom = 1157
 10982  	} else if prg.scanKeyword(strNumber( /* "sp" */ 722)) {
 10983  		goto done
 10984  	} else {
 10985  		// Complain about unknown unit and |goto done2|
 10986  		{
 10987  			if int32(prg.interaction) == errorStopMode {
 10988  			}
 10989  			prg.printNl(strNumber( /* "! " */ 262))
 10990  			prg.print( /* "Illegal unit of measure (" */ 705)
 10991  		}
 10992  		prg.print( /* "pt inserted)" */ 723)
 10993  		// \xref[Illegal unit of measure]
 10994  		{
 10995  			prg.helpPtr = 6
 10996  			prg.helpLine[5] = /* "Dimensions can be in units of em, ex, in, pt, pc," */ 724
 10997  			prg.helpLine[4] = /* "cm, mm, dd, cc, bp, or sp; but yours is a new one!" */ 725
 10998  			prg.helpLine[3] = /* "I'll assume that you meant to say pt, for printer's points." */ 726
 10999  			prg.helpLine[2] = /* "To recover gracefully from this error, it's best to" */ 712
 11000  			prg.helpLine[1] = /* "delete the erroneous units; e.g., type `2' to delete" */ 713
 11001  			prg.helpLine[0] = /* "two letters. (See Chapter 27 of The TeXbook.)" */ 714
 11002  		}
 11003  		// \xref[TeXbook][\sl The \TeX book]
 11004  		prg.error1()
 11005  		goto done2
 11006  	}
 11007  	prg.curVal = prg.xnOverD(prg.curVal, int32(num), int32(denom))
 11008  	f = (int32(num)*f + 0200000*prg.remainder) / int32(denom)
 11009  
 11010  	prg.curVal = prg.curVal + f/0200000
 11011  	f = f % 0200000
 11012  
 11013  done2:
 11014  	;
 11015  
 11016  attachFraction:
 11017  	if prg.curVal >= 040000 {
 11018  		prg.arithError = true
 11019  	} else {
 11020  		prg.curVal = prg.curVal*0200000 + f
 11021  	}
 11022  
 11023  done:
 11024  	;
 11025  
 11026  	// Scan an optional space
 11027  	{
 11028  		prg.getXToken()
 11029  		if int32(prg.curCmd) != spacer {
 11030  			prg.backInput()
 11031  		}
 11032  	}
 11033  
 11034  attachSign:
 11035  	if prg.arithError || abs(prg.curVal) >= 010000000000 {
 11036  		{
 11037  			if int32(prg.interaction) == errorStopMode {
 11038  			}
 11039  			prg.printNl(strNumber( /* "! " */ 262))
 11040  			prg.print( /* "Dimension too large" */ 727)
 11041  		}
 11042  		// \xref[Dimension too large]
 11043  		{
 11044  			prg.helpPtr = 2
 11045  			prg.helpLine[1] = /* "I can't work with sizes bigger than about 19 feet." */ 728
 11046  			prg.helpLine[0] = /* "Continue and I'll use the largest value I can." */ 729
 11047  		}
 11048  
 11049  		prg.error1()
 11050  		prg.curVal = 07777777777
 11051  		prg.arithError = false
 11052  	}
 11053  	if negative {
 11054  		prg.curVal = -prg.curVal
 11055  	}
 11056  }
 11057  
 11058  // 461.
 11059  
 11060  // tangle:pos tex.web:9064:1:
 11061  
 11062  // The final member of \TeX's value-scanning trio is |scan_glue|, which
 11063  // makes |cur_val| point to a glue specification. The reference count of that
 11064  // glue spec will take account of the fact that |cur_val| is pointing to~it.
 11065  //
 11066  // The |level| parameter should be either |glue_val| or |mu_val|.
 11067  //
 11068  // Since |scan_dimen| was so much more complex than |scan_int|, we might expect
 11069  // |scan_glue| to be even worse. But fortunately, it is very simple, since
 11070  // most of the work has already been done.
 11071  func (prg *prg) scanGlue(level smallNumber) {
 11072  	var (
 11073  		negative bool     // should the answer be negated?
 11074  		q        halfword // new glue specification
 11075  		mu       bool     // does |level=mu_val|?
 11076  	)
 11077  	mu = int32(level) == muVal
 11078  	// Get the next non-blank non-sign...
 11079  	negative = false
 11080  	for {
 11081  		// Get the next non-blank non-call token
 11082  		for {
 11083  			prg.getXToken()
 11084  			if int32(prg.curCmd) != spacer {
 11085  				break
 11086  			}
 11087  		}
 11088  		if int32(prg.curTok) == otherToken+'-' {
 11089  			negative = !negative
 11090  			prg.curTok = uint16(otherToken + '+')
 11091  		}
 11092  		if int32(prg.curTok) != otherToken+'+' {
 11093  			break
 11094  		}
 11095  	}
 11096  	if int32(prg.curCmd) >= minInternal && int32(prg.curCmd) <= maxInternal {
 11097  		prg.scanSomethingInternal(level, negative)
 11098  		if int32(prg.curValLevel) >= glueVal {
 11099  			if int32(prg.curValLevel) != int32(level) {
 11100  				prg.muError()
 11101  			}
 11102  
 11103  			goto exit
 11104  		}
 11105  		if int32(prg.curValLevel) == intVal {
 11106  			prg.scanDimen(mu, false, true)
 11107  		} else if int32(level) == muVal {
 11108  			prg.muError()
 11109  		}
 11110  	} else {
 11111  		prg.backInput()
 11112  		prg.scanDimen(mu, false, false)
 11113  		if negative {
 11114  			prg.curVal = -prg.curVal
 11115  		}
 11116  	}
 11117  
 11118  	// Create a new glue specification whose width is |cur_val|; scan for its stretch and shrink components
 11119  	q = prg.newSpec(halfword(memBot))
 11120  	*prg.mem[int32(q)+widthOffset].int() = prg.curVal
 11121  	if prg.scanKeyword(strNumber( /* "plus" */ 730)) {
 11122  		prg.scanDimen(mu, true, false)
 11123  		*prg.mem[int32(q)+2].int() = prg.curVal
 11124  		*(*prg.mem[q].hh()).b0() = prg.curOrder
 11125  	}
 11126  	if prg.scanKeyword(strNumber( /* "minus" */ 731)) {
 11127  		prg.scanDimen(mu, true, false)
 11128  		*prg.mem[int32(q)+3].int() = prg.curVal
 11129  		*(*prg.mem[q].hh()).b1() = prg.curOrder
 11130  	}
 11131  	prg.curVal = int32(q)
 11132  
 11133  exit:
 11134  }
 11135  
 11136  // 463.
 11137  
 11138  // tangle:pos tex.web:9111:1:
 11139  
 11140  // Here's a similar procedure that returns a pointer to a rule node. This
 11141  // routine is called just after \TeX\ has seen \.[\\hrule] or \.[\\vrule];
 11142  // therefore |cur_cmd| will be either |hrule| or |vrule|. The idea is to store
 11143  // the default rule dimensions in the node, then to override them if
 11144  // `\.[height]' or `\.[width]' or `\.[depth]' specifications are
 11145  // found (in any order).
 11146  func (prg *prg) scanRuleSpec() (r halfword) {
 11147  	var (
 11148  		q halfword // the rule node being created
 11149  	)
 11150  	q = prg.newRule() // |width|, |depth|, and |height| all equal |null_flag| now
 11151  	if int32(prg.curCmd) == vrule {
 11152  		*prg.mem[int32(q)+widthOffset].int() = defaultRule
 11153  	} else {
 11154  		*prg.mem[int32(q)+heightOffset].int() = defaultRule
 11155  		*prg.mem[int32(q)+depthOffset].int() = 0
 11156  	}
 11157  
 11158  reswitch:
 11159  	if prg.scanKeyword(strNumber( /* "width" */ 732)) {
 11160  		prg.scanDimen(false, false, false)
 11161  		*prg.mem[int32(q)+widthOffset].int() = prg.curVal
 11162  		goto reswitch
 11163  	}
 11164  	if prg.scanKeyword(strNumber( /* "height" */ 733)) {
 11165  		prg.scanDimen(false, false, false)
 11166  		*prg.mem[int32(q)+heightOffset].int() = prg.curVal
 11167  		goto reswitch
 11168  	}
 11169  	if prg.scanKeyword(strNumber( /* "depth" */ 734)) {
 11170  		prg.scanDimen(false, false, false)
 11171  		*prg.mem[int32(q)+depthOffset].int() = prg.curVal
 11172  		goto reswitch
 11173  	}
 11174  	r = q
 11175  	return r
 11176  }
 11177  
 11178  // 464. \[27] Building token lists
 11179  
 11180  // tangle:pos tex.web:9142:29:
 11181  
 11182  // The token lists for macros and for other things like \.[\\mark] and \.[\\output]
 11183  // and \.[\\write] are produced by a procedure called |scan_toks|.
 11184  //
 11185  // Before we get into the details of |scan_toks|, let's consider a much
 11186  // simpler task, that of converting the current string into a token list.
 11187  // The |str_toks| function does this; it classifies spaces as type |spacer|
 11188  // and everything else as type |other_char|.
 11189  //
 11190  // The token list created by |str_toks| begins at |link(temp_head)| and ends
 11191  // at the value |p| that is returned. (If |p=temp_head|, the list is empty.)
 11192  func (prg *prg) strToks(b poolPointer) (r halfword) {
 11193  	// converts |str_pool[b..pool_ptr-1]| to a token list
 11194  	var (
 11195  		p halfword    // tail of the token list
 11196  		q halfword    // new node being added to the token list via |store_new_token|
 11197  		t halfword    // token being appended
 11198  		k poolPointer // index into |str_pool|
 11199  	)
 11200  	{
 11201  		if int32(prg.poolPtr)+1 > poolSize {
 11202  			prg.overflow(strNumber( /* "pool size" */ 257), poolSize-int32(prg.initPoolPtr))
 11203  		} /* \xref[TeX capacity exceeded pool size][\quad pool size]  */
 11204  	}
 11205  	p = uint16(30000 - 3)
 11206  	*(*prg.mem[p].hh()).rh() = 0
 11207  	k = b
 11208  	for int32(k) < int32(prg.poolPtr) {
 11209  		t = uint16(prg.strPool[k])
 11210  		if int32(t) == ' ' {
 11211  			t = uint16(spaceToken)
 11212  		} else {
 11213  			t = uint16(otherToken + int32(t))
 11214  		}
 11215  		{
 11216  			{
 11217  				q = prg.avail
 11218  				if int32(q) == 0 {
 11219  					q = prg.getAvail()
 11220  				} else {
 11221  					prg.avail = *(*prg.mem[q].hh()).rh()
 11222  					*(*prg.mem[q].hh()).rh() = 0 /*    dyn_used:= dyn_used+1 ; [  ] */
 11223  				}
 11224  			}
 11225  			*(*prg.mem[p].hh()).rh() = q
 11226  			*(*prg.mem[q].hh()).lh() = t
 11227  			p = q
 11228  		}
 11229  		k = uint16(int32(k) + 1)
 11230  	}
 11231  	prg.poolPtr = b
 11232  	r = p
 11233  	return r
 11234  }
 11235  
 11236  // 465.
 11237  
 11238  // tangle:pos tex.web:9172:1:
 11239  
 11240  // The main reason for wanting |str_toks| is the next function,
 11241  // |the_toks|, which has similar input/output characteristics.
 11242  //
 11243  // This procedure is supposed to scan something like `\.[\\skip\\count12]',
 11244  // i.e., whatever can follow `\.[\\the]', and it constructs a token list
 11245  // containing something like `\.[-3.0pt minus 0.5fill]'.
 11246  func (prg *prg) theToks() (r halfword) {
 11247  	var (
 11248  		oldSetting/* 0..maxSelector */ byte             // holds |selector| setting
 11249  		p, q, r1                            halfword    // used for copying a token list
 11250  		b                                   poolPointer // base of temporary string
 11251  	)
 11252  	prg.getXToken()
 11253  	prg.scanSomethingInternal(smallNumber(tokVal), false)
 11254  	if int32(prg.curValLevel) >= identVal {
 11255  		p = uint16(30000 - 3)
 11256  		*(*prg.mem[p].hh()).rh() = 0
 11257  		if int32(prg.curValLevel) == identVal {
 11258  			q = prg.getAvail()
 11259  			*(*prg.mem[p].hh()).rh() = q
 11260  			*(*prg.mem[q].hh()).lh() = uint16(07777 + prg.curVal)
 11261  			p = q
 11262  		} else if prg.curVal != 0 {
 11263  			r1 = *(*prg.mem[prg.curVal].hh()).rh() // do not copy the reference count
 11264  			for int32(r1) != 0 {
 11265  				{
 11266  					{
 11267  						q = prg.avail
 11268  						if int32(q) == 0 {
 11269  							q = prg.getAvail()
 11270  						} else {
 11271  							prg.avail = *(*prg.mem[q].hh()).rh()
 11272  							*(*prg.mem[q].hh()).rh() = 0 /*    dyn_used:= dyn_used+1 ; [  ] */
 11273  						}
 11274  					}
 11275  					*(*prg.mem[p].hh()).rh() = q
 11276  					*(*prg.mem[q].hh()).lh() = *(*prg.mem[r1].hh()).lh()
 11277  					p = q
 11278  				}
 11279  				r1 = *(*prg.mem[r1].hh()).rh()
 11280  			}
 11281  		}
 11282  		r = p
 11283  	} else {
 11284  		oldSetting = prg.selector
 11285  		prg.selector = byte(newString)
 11286  		b = prg.poolPtr
 11287  		switch prg.curValLevel {
 11288  		case intVal:
 11289  			prg.printInt(prg.curVal)
 11290  		case dimenVal:
 11291  			prg.printScaled(prg.curVal)
 11292  			prg.print( /* "pt" */ 397)
 11293  
 11294  		case glueVal:
 11295  			prg.printSpec(prg.curVal, strNumber( /* "pt" */ 397))
 11296  			prg.deleteGlueRef(halfword(prg.curVal))
 11297  
 11298  		case muVal:
 11299  			prg.printSpec(prg.curVal, strNumber( /* "mu" */ 337))
 11300  			prg.deleteGlueRef(halfword(prg.curVal))
 11301  
 11302  		} // there are no other cases
 11303  		prg.selector = oldSetting
 11304  		r = prg.strToks(b)
 11305  	}
 11306  	return r
 11307  } // \2
 11308  func (prg *prg) insTheToks() {
 11309  	*(*prg.mem[30000-12].hh()).rh() = prg.theToks()
 11310  	prg.beginTokenList(*(*prg.mem[30000-3].hh()).rh(), quarterword(inserted))
 11311  } // \2
 11312  func (prg *prg) convToks() {
 11313  	var (
 11314  		oldSetting/* 0..maxSelector */ byte             // holds |selector| setting
 11315  		c/* numberCode..jobNameCode */ byte             // desired type of conversion
 11316  		saveScannerStatus                   smallNumber // |scanner_status| upon entry
 11317  		b                                   poolPointer // base of temporary string
 11318  	)
 11319  	c = byte(prg.curChr)
 11320  	// Scan the argument for command |c|
 11321  	switch c {
 11322  	case numberCode, romanNumeralCode:
 11323  		prg.scanInt()
 11324  	case stringCode, meaningCode:
 11325  		saveScannerStatus = prg.scannerStatus
 11326  		prg.scannerStatus = byte(normal)
 11327  		prg.getToken()
 11328  		prg.scannerStatus = saveScannerStatus
 11329  
 11330  	case fontNameCode:
 11331  		prg.scanFontIdent()
 11332  	case jobNameCode:
 11333  		if int32(prg.jobName) == 0 {
 11334  			prg.openLogFile()
 11335  		}
 11336  	}
 11337  	oldSetting = prg.selector
 11338  	prg.selector = byte(newString)
 11339  	b = prg.poolPtr
 11340  
 11341  	// Print the result of command |c|
 11342  	switch c {
 11343  	case numberCode:
 11344  		prg.printInt(prg.curVal)
 11345  	case romanNumeralCode:
 11346  		prg.printRomanInt(prg.curVal)
 11347  	case stringCode:
 11348  		if int32(prg.curCs) != 0 {
 11349  			prg.sprintCs(prg.curCs)
 11350  		} else {
 11351  			prg.printChar(asciiCode(prg.curChr))
 11352  		}
 11353  	case meaningCode:
 11354  		prg.printMeaning()
 11355  	case fontNameCode:
 11356  		prg.print(int32(prg.fontName[prg.curVal]))
 11357  		if prg.fontSize[prg.curVal] != prg.fontDsize[prg.curVal] {
 11358  			prg.print( /* " at " */ 741)
 11359  			prg.printScaled(prg.fontSize[prg.curVal])
 11360  			prg.print( /* "pt" */ 397)
 11361  		}
 11362  
 11363  	case jobNameCode:
 11364  		prg.print(int32(prg.jobName))
 11365  	}
 11366  	prg.selector = oldSetting
 11367  	*(*prg.mem[30000-12].hh()).rh() = prg.strToks(b)
 11368  	prg.beginTokenList(*(*prg.mem[30000-3].hh()).rh(), quarterword(inserted))
 11369  }
 11370  
 11371  // 473.
 11372  
 11373  // tangle:pos tex.web:9292:1:
 11374  
 11375  // Now we can't postpone the difficulties any longer; we must bravely tackle
 11376  // |scan_toks|. This function returns a pointer to the tail of a new token
 11377  // list, and it also makes |def_ref| point to the reference count at the
 11378  // head of that list.
 11379  //
 11380  // There are two boolean parameters, |macro_def| and |xpand|. If |macro_def|
 11381  // is true, the goal is to create the token list for a macro definition;
 11382  // otherwise the goal is to create the token list for some other \TeX\
 11383  // primitive: \.[\\mark], \.[\\output], \.[\\everypar], \.[\\lowercase],
 11384  // \.[\\uppercase], \.[\\message], \.[\\errmessage], \.[\\write], or
 11385  // \.[\\special]. In the latter cases a left brace must be scanned next; this
 11386  // left brace will not be part of the token list, nor will the matching right
 11387  // brace that comes at the end. If |xpand| is false, the token list will
 11388  // simply be copied from the input using |get_token|. Otherwise all expandable
 11389  // tokens will be expanded until unexpandable tokens are left, except that
 11390  // the results of expanding `\.[\\the]' are not expanded further.
 11391  // If both |macro_def| and |xpand| are true, the expansion applies
 11392  // only to the macro body (i.e., to the material following the first
 11393  // |left_brace| character).
 11394  //
 11395  // The value of |cur_cs| when |scan_toks| begins should be the |eqtb|
 11396  // address of the control sequence to display in ``runaway'' error
 11397  // messages.
 11398  func (prg *prg) scanToks(macroDef, xpand bool) (r halfword) {
 11399  	var (
 11400  		t         halfword // token representing the highest parameter number
 11401  		s         halfword // saved token
 11402  		p         halfword // tail of the token list being built
 11403  		q         halfword // new node being added to the token list via |store_new_token|
 11404  		unbalance halfword // number of unmatched left braces
 11405  		hashBrace halfword // possible `\.[\#\[]' token
 11406  	)
 11407  	if macroDef {
 11408  		prg.scannerStatus = byte(defining)
 11409  	} else {
 11410  		prg.scannerStatus = byte(absorbing)
 11411  	}
 11412  	prg.warningIndex = prg.curCs
 11413  	prg.defRef = prg.getAvail()
 11414  	*(*prg.mem[prg.defRef].hh()).lh() = 0
 11415  	p = prg.defRef
 11416  	hashBrace = 0
 11417  	t = uint16(zeroToken)
 11418  	if macroDef {
 11419  		for true {
 11420  		continue1:
 11421  			prg.getToken() // set |cur_cmd|, |cur_chr|, |cur_tok|
 11422  			if int32(prg.curTok) < rightBraceLimit {
 11423  				goto done1
 11424  			}
 11425  			if int32(prg.curCmd) == macParam {
 11426  				s = uint16(matchToken + int32(prg.curChr))
 11427  				prg.getToken()
 11428  				if int32(prg.curTok) < leftBraceLimit {
 11429  					hashBrace = prg.curTok
 11430  					{
 11431  						q = prg.getAvail()
 11432  						*(*prg.mem[p].hh()).rh() = q
 11433  						*(*prg.mem[q].hh()).lh() = prg.curTok
 11434  						p = q
 11435  					}
 11436  					{
 11437  						q = prg.getAvail()
 11438  						*(*prg.mem[p].hh()).rh() = q
 11439  						*(*prg.mem[q].hh()).lh() = uint16(endMatchToken)
 11440  						p = q
 11441  					}
 11442  
 11443  					goto done
 11444  				}
 11445  				if int32(t) == zeroToken+9 {
 11446  					{
 11447  						if int32(prg.interaction) == errorStopMode {
 11448  						}
 11449  						prg.printNl(strNumber( /* "! " */ 262))
 11450  						prg.print( /* "You already have nine parameters" */ 744)
 11451  					}
 11452  					// \xref[You already have nine...]
 11453  					{
 11454  						prg.helpPtr = 2
 11455  						prg.helpLine[1] = /* "I'm going to ignore the # sign you just used," */ 745
 11456  						prg.helpLine[0] = /* "as well as the token that followed it." */ 746
 11457  					}
 11458  					prg.error1()
 11459  					goto continue1
 11460  				} else {
 11461  					t = uint16(int32(t) + 1)
 11462  					if int32(prg.curTok) != int32(t) {
 11463  						{
 11464  							if int32(prg.interaction) == errorStopMode {
 11465  							}
 11466  							prg.printNl(strNumber( /* "! " */ 262))
 11467  							prg.print( /* "Parameters must be numbered consecutively" */ 747)
 11468  						}
 11469  						// \xref[Parameters...consecutively]
 11470  						{
 11471  							prg.helpPtr = 2
 11472  							prg.helpLine[1] = /* "I've inserted the digit you should have used after the #." */ 748
 11473  							prg.helpLine[0] = /* "Type `1' to delete what you did use." */ 749
 11474  						}
 11475  						prg.backError()
 11476  					}
 11477  					prg.curTok = s
 11478  				}
 11479  			}
 11480  			{
 11481  				q = prg.getAvail()
 11482  				*(*prg.mem[p].hh()).rh() = q
 11483  				*(*prg.mem[q].hh()).lh() = prg.curTok
 11484  				p = q
 11485  			}
 11486  		}
 11487  
 11488  	done1:
 11489  		{
 11490  			q = prg.getAvail()
 11491  			*(*prg.mem[p].hh()).rh() = q
 11492  			*(*prg.mem[q].hh()).lh() = uint16(endMatchToken)
 11493  			p = q
 11494  		}
 11495  		if int32(prg.curCmd) == rightBrace {
 11496  			{
 11497  				if int32(prg.interaction) == errorStopMode {
 11498  				}
 11499  				prg.printNl(strNumber( /* "! " */ 262))
 11500  				prg.print( /* "Missing [ inserted" */ 657)
 11501  			}
 11502  			prg.alignState = prg.alignState + 1
 11503  			// \xref[Missing \[ inserted]
 11504  			{
 11505  				prg.helpPtr = 2
 11506  				prg.helpLine[1] = /* "Where was the left brace? You said something like `\\def\\a]'," */ 742
 11507  				prg.helpLine[0] = /* "which I'm going to interpret as `\\def\\a[]'." */ 743
 11508  			}
 11509  			prg.error1()
 11510  			goto found
 11511  		}
 11512  
 11513  	done:
 11514  	} else {
 11515  		prg.scanLeftBrace()
 11516  	} // remove the compulsory left brace
 11517  
 11518  	// Scan and build the body of the token list; |goto found| when finished
 11519  	unbalance = 1
 11520  	for true {
 11521  		if xpand {
 11522  			for true {
 11523  				prg.getNext()
 11524  				if int32(prg.curCmd) <= maxCommand {
 11525  					goto done2
 11526  				}
 11527  				if int32(prg.curCmd) != the {
 11528  					prg.expand()
 11529  				} else {
 11530  					q = prg.theToks()
 11531  					if int32(*(*prg.mem[30000-3].hh()).rh()) != 0 {
 11532  						*(*prg.mem[p].hh()).rh() = *(*prg.mem[30000-3].hh()).rh()
 11533  						p = q
 11534  					}
 11535  				}
 11536  			}
 11537  
 11538  		done2:
 11539  			prg.xToken()
 11540  		} else {
 11541  			prg.getToken()
 11542  		}
 11543  		if int32(prg.curTok) < rightBraceLimit {
 11544  			if int32(prg.curCmd) < rightBrace {
 11545  				unbalance = uint16(int32(unbalance) + 1)
 11546  			} else {
 11547  				unbalance = uint16(int32(unbalance) - 1)
 11548  				if int32(unbalance) == 0 {
 11549  					goto found
 11550  				}
 11551  			}
 11552  		} else if int32(prg.curCmd) == macParam {
 11553  			if macroDef {
 11554  				s = prg.curTok
 11555  				if xpand {
 11556  					prg.getXToken()
 11557  				} else {
 11558  					prg.getToken()
 11559  				}
 11560  				if int32(prg.curCmd) != macParam {
 11561  					if int32(prg.curTok) <= zeroToken || int32(prg.curTok) > int32(t) {
 11562  						{
 11563  							if int32(prg.interaction) == errorStopMode {
 11564  							}
 11565  							prg.printNl(strNumber( /* "! " */ 262))
 11566  							prg.print( /* "Illegal parameter number in definition of " */ 750)
 11567  						}
 11568  						// \xref[Illegal parameter number...]
 11569  						prg.sprintCs(prg.warningIndex)
 11570  						{
 11571  							prg.helpPtr = 3
 11572  							prg.helpLine[2] = /* "You meant to type ## instead of #, right?" */ 751
 11573  							prg.helpLine[1] = /* "Or maybe a ] was forgotten somewhere earlier, and things" */ 752
 11574  							prg.helpLine[0] = /* "are all screwed up? I'm going to assume that you meant ##." */ 753
 11575  						}
 11576  						prg.backError()
 11577  						prg.curTok = s
 11578  					} else {
 11579  						prg.curTok = uint16(outParamToken - '0' + int32(prg.curChr))
 11580  					}
 11581  				}
 11582  			}
 11583  		}
 11584  		{
 11585  			q = prg.getAvail()
 11586  			*(*prg.mem[p].hh()).rh() = q
 11587  			*(*prg.mem[q].hh()).lh() = prg.curTok
 11588  			p = q
 11589  		}
 11590  	}
 11591  
 11592  found:
 11593  	prg.scannerStatus = byte(normal)
 11594  	if int32(hashBrace) != 0 {
 11595  		q = prg.getAvail()
 11596  		*(*prg.mem[p].hh()).rh() = q
 11597  		*(*prg.mem[q].hh()).lh() = hashBrace
 11598  		p = q
 11599  	}
 11600  	r = p
 11601  	return r
 11602  }
 11603  
 11604  // 482.
 11605  
 11606  // tangle:pos tex.web:9444:1:
 11607  
 11608  // The |read_toks| procedure constructs a token list like that for any
 11609  // macro definition, and makes |cur_val| point to it. Parameter |r| points
 11610  // to the control sequence that will receive this token list.
 11611  func (prg *prg) readToks(n int32, r1 halfword) {
 11612  	var (
 11613  		p halfword    // tail of the token list
 11614  		q halfword    // new node being added to the token list via |store_new_token|
 11615  		s int32       // saved value of |align_state|
 11616  		m smallNumber // stream number
 11617  	)
 11618  	prg.scannerStatus = byte(defining)
 11619  	prg.warningIndex = r1
 11620  	prg.defRef = prg.getAvail()
 11621  	*(*prg.mem[prg.defRef].hh()).lh() = 0
 11622  	p = prg.defRef // the reference count
 11623  	{
 11624  		q = prg.getAvail()
 11625  		*(*prg.mem[p].hh()).rh() = q
 11626  		*(*prg.mem[q].hh()).lh() = uint16(endMatchToken)
 11627  		p = q
 11628  	}
 11629  	if n < 0 || n > 15 {
 11630  		m = 16
 11631  	} else {
 11632  		m = byte(n)
 11633  	}
 11634  	s = prg.alignState
 11635  	prg.alignState = 1000000 // disable tab marks, etc.
 11636  	for {
 11637  		// Input and store tokens from the next line of the file
 11638  		prg.beginFileReading()
 11639  		prg.curInput.nameField = uint16(int32(m) + 1)
 11640  		if int32(prg.readOpen[m]) == closed {
 11641  			if int32(prg.interaction) > nonstopMode {
 11642  				if n < 0 {
 11643  					prg.print( /* "" */ 338)
 11644  					prg.termInput()
 11645  				} else {
 11646  					prg.printLn()
 11647  					prg.sprintCs(r1)
 11648  					{
 11649  						prg.print('=')
 11650  						prg.termInput()
 11651  					}
 11652  					n = -1
 11653  				}
 11654  			} else {
 11655  				prg.fatalError(strNumber( /* "*** (cannot \\read from terminal in nonstop modes)" */ 754))
 11656  			}
 11657  		} else if int32(prg.readOpen[m]) == justOpen {
 11658  			if prg.inputLn(prg.readFile[m], false) {
 11659  				prg.readOpen[m] = byte(normal)
 11660  			} else {
 11661  				prg.aClose(prg.readFile[m])
 11662  				prg.readOpen[m] = byte(closed)
 11663  			}
 11664  		} else {
 11665  			// Input the next line of |read_file[m]|
 11666  			if !prg.inputLn(prg.readFile[m], true) {
 11667  				prg.aClose(prg.readFile[m])
 11668  				prg.readOpen[m] = byte(closed)
 11669  				if prg.alignState != 1000000 {
 11670  					prg.runaway()
 11671  					{
 11672  						if int32(prg.interaction) == errorStopMode {
 11673  						}
 11674  						prg.printNl(strNumber( /* "! " */ 262))
 11675  						prg.print( /* "File ended within " */ 755)
 11676  					}
 11677  					prg.printEsc(strNumber( /* "read" */ 534))
 11678  					// \xref[File ended within \\read]
 11679  					{
 11680  						prg.helpPtr = 1
 11681  						prg.helpLine[0] = /* "This \\read has unbalanced braces." */ 756
 11682  					}
 11683  					prg.alignState = 1000000
 11684  					prg.curInput.limitField = 0
 11685  					prg.error1()
 11686  				}
 11687  			}
 11688  		}
 11689  		prg.curInput.limitField = prg.last
 11690  		if *prg.eqtb[intBase+endLineCharCode-1].int() < 0 || *prg.eqtb[intBase+endLineCharCode-1].int() > 255 {
 11691  			prg.curInput.limitField = uint16(int32(prg.curInput.limitField) - 1)
 11692  		} else {
 11693  			prg.buffer[prg.curInput.limitField] = byte(*prg.eqtb[intBase+endLineCharCode-1].int())
 11694  		}
 11695  		prg.first = uint16(int32(prg.curInput.limitField) + 1)
 11696  		prg.curInput.locField = prg.curInput.startField
 11697  		prg.curInput.stateField = byte(newLine)
 11698  
 11699  		for true {
 11700  			prg.getToken()
 11701  			if int32(prg.curTok) == 0 {
 11702  				goto done
 11703  			}
 11704  			// |cur_cmd=cur_chr=0| will occur at the end of the line
 11705  			if prg.alignState < 1000000 {
 11706  				for {
 11707  					prg.getToken()
 11708  					if int32(prg.curTok) == 0 {
 11709  						break
 11710  					}
 11711  				}
 11712  				prg.alignState = 1000000
 11713  				goto done
 11714  			}
 11715  			{
 11716  				q = prg.getAvail()
 11717  				*(*prg.mem[p].hh()).rh() = q
 11718  				*(*prg.mem[q].hh()).lh() = prg.curTok
 11719  				p = q
 11720  			}
 11721  		}
 11722  
 11723  	done:
 11724  		prg.endFileReading()
 11725  		if prg.alignState == 1000000 {
 11726  			break
 11727  		}
 11728  	}
 11729  	prg.curVal = int32(prg.defRef)
 11730  	prg.scannerStatus = byte(normal)
 11731  	prg.alignState = s
 11732  }
 11733  
 11734  func (prg *prg) passText() {
 11735  	var (
 11736  		l                 int32       // level of $\.[\\if]\ldots\.[\\fi]$ nesting
 11737  		saveScannerStatus smallNumber // |scanner_status| upon entry
 11738  	)
 11739  	saveScannerStatus = prg.scannerStatus
 11740  	prg.scannerStatus = byte(skipping)
 11741  	l = 0
 11742  	prg.skipLine = prg.line
 11743  	for true {
 11744  		prg.getNext()
 11745  		if int32(prg.curCmd) == fiOrElse {
 11746  			if l == 0 {
 11747  				goto done
 11748  			}
 11749  			if int32(prg.curChr) == fiCode {
 11750  				l = l - 1
 11751  			}
 11752  		} else if int32(prg.curCmd) == ifTest {
 11753  			l = l + 1
 11754  		}
 11755  	}
 11756  
 11757  done:
 11758  	prg.scannerStatus = saveScannerStatus
 11759  }
 11760  
 11761  // 497.
 11762  
 11763  // tangle:pos tex.web:9693:1:
 11764  
 11765  // Here's a procedure that changes the |if_limit| code corresponding to
 11766  // a given value of |cond_ptr|.
 11767  func (prg *prg) changeIfLimit(l smallNumber, p halfword) {
 11768  	var (
 11769  		q halfword
 11770  	)
 11771  	if int32(p) == int32(prg.condPtr) {
 11772  		prg.ifLimit = l
 11773  	} else {
 11774  		q = prg.condPtr
 11775  		for true {
 11776  			if int32(q) == 0 {
 11777  				prg.confusion(strNumber( /* "if" */ 757))
 11778  			}
 11779  			// \xref[this can't happen if][\quad if]
 11780  			if int32(*(*prg.mem[q].hh()).rh()) == int32(p) {
 11781  				*(*prg.mem[q].hh()).b0() = l
 11782  				goto exit
 11783  			}
 11784  			q = *(*prg.mem[q].hh()).rh()
 11785  		}
 11786  	}
 11787  
 11788  exit:
 11789  } // \2
 11790  func (prg *prg) conditional() {
 11791  	var (
 11792  		b                     bool        // is the condition true?
 11793  		r1/* '<'..'>' */ byte             // relation to be evaluated
 11794  		m, n                  int32       // to be tested against the second operand
 11795  		p, q                  halfword    // for traversing token lists in \.[\\ifx] tests
 11796  		saveScannerStatus     smallNumber // |scanner_status| upon entry
 11797  		saveCondPtr           halfword    // |cond_ptr| corresponding to this conditional
 11798  		thisIf                smallNumber // type of this conditional
 11799  	)
 11800  	{
 11801  		p = prg.getNode(ifNodeSize)
 11802  		*(*prg.mem[p].hh()).rh() = prg.condPtr
 11803  		*(*prg.mem[p].hh()).b0() = prg.ifLimit
 11804  		*(*prg.mem[p].hh()).b1() = prg.curIf
 11805  		*prg.mem[int32(p)+1].int() = prg.ifLine
 11806  		prg.condPtr = p
 11807  		prg.curIf = byte(prg.curChr)
 11808  		prg.ifLimit = byte(ifCode)
 11809  		prg.ifLine = prg.line
 11810  	}
 11811  	saveCondPtr = prg.condPtr
 11812  	thisIf = byte(prg.curChr)
 11813  
 11814  	// Either process \.[\\ifcase] or set |b| to the value of a boolean condition
 11815  	switch thisIf {
 11816  	case ifCharCode, ifCatCode:
 11817  		// Test if two characters match
 11818  		{
 11819  			prg.getXToken()
 11820  			if int32(prg.curCmd) == relax {
 11821  				if int32(prg.curChr) == noExpandFlag {
 11822  					prg.curCmd = byte(activeChar)
 11823  					prg.curChr = uint16(int32(prg.curTok) - 07777 - activeBase)
 11824  				}
 11825  			}
 11826  		}
 11827  		if int32(prg.curCmd) > activeChar || int32(prg.curChr) > 255 {
 11828  			m = relax
 11829  			n = 256
 11830  		} else {
 11831  			m = int32(prg.curCmd)
 11832  			n = int32(prg.curChr)
 11833  		}
 11834  		/*   */ {
 11835  			prg.getXToken()
 11836  			if int32(prg.curCmd) == relax {
 11837  				if int32(prg.curChr) == noExpandFlag {
 11838  					prg.curCmd = byte(activeChar)
 11839  					prg.curChr = uint16(int32(prg.curTok) - 07777 - activeBase)
 11840  				}
 11841  			}
 11842  		}
 11843  		if int32(prg.curCmd) > activeChar || int32(prg.curChr) > 255 {
 11844  			prg.curCmd = byte(relax)
 11845  			prg.curChr = 256
 11846  		}
 11847  		if int32(thisIf) == ifCharCode {
 11848  			b = n == int32(prg.curChr)
 11849  		} else {
 11850  			b = m == int32(prg.curCmd)
 11851  		}
 11852  
 11853  	case ifIntCode, ifDimCode:
 11854  		// Test relation between integers or dimensions
 11855  		if int32(thisIf) == ifIntCode {
 11856  			prg.scanInt()
 11857  		} else {
 11858  			prg.scanDimen(false, false, false)
 11859  		}
 11860  		n = prg.curVal
 11861  		// Get the next non-blank non-call...
 11862  		for {
 11863  			prg.getXToken()
 11864  			if int32(prg.curCmd) != spacer {
 11865  				break
 11866  			}
 11867  		}
 11868  		if int32(prg.curTok) >= otherToken+'<' && int32(prg.curTok) <= otherToken+'>' {
 11869  			r1 = byte(int32(prg.curTok) - otherToken)
 11870  		} else {
 11871  			{
 11872  				if int32(prg.interaction) == errorStopMode {
 11873  				}
 11874  				prg.printNl(strNumber( /* "! " */ 262))
 11875  				prg.print( /* "Missing = inserted for " */ 781)
 11876  			}
 11877  			// \xref[Missing = inserted]
 11878  			prg.printCmdChr(quarterword(ifTest), halfword(thisIf))
 11879  			{
 11880  				prg.helpPtr = 1
 11881  				prg.helpLine[0] = /* "I was expecting to see `<', `=', or `>'. Didn't." */ 782
 11882  			}
 11883  			prg.backError()
 11884  			r1 = '='
 11885  		}
 11886  		if int32(thisIf) == ifIntCode {
 11887  			prg.scanInt()
 11888  		} else {
 11889  			prg.scanDimen(false, false, false)
 11890  		}
 11891  		switch r1 {
 11892  		case '<':
 11893  			b = n < prg.curVal
 11894  		// "="=
 11895  		case '=':
 11896  			b = n == prg.curVal
 11897  		// ">"=
 11898  		case '>':
 11899  			b = n > prg.curVal
 11900  		}
 11901  
 11902  	case ifOddCode:
 11903  		// Test if an integer is odd
 11904  		prg.scanInt()
 11905  		b = prg.curVal&1 != 0
 11906  
 11907  	case ifVmodeCode:
 11908  		b = abs(int32(prg.curList.modeField)) == vmode
 11909  	case ifHmodeCode:
 11910  		b = abs(int32(prg.curList.modeField)) == hmode
 11911  	case ifMmodeCode:
 11912  		b = abs(int32(prg.curList.modeField)) == mmode
 11913  	case ifInnerCode:
 11914  		b = int32(prg.curList.modeField) < 0
 11915  	case ifVoidCode, ifHboxCode, ifVboxCode:
 11916  		// Test box register status
 11917  		prg.scanEightBitInt()
 11918  		p = *(*prg.eqtb[boxBase+prg.curVal-1].hh()).rh()
 11919  		if int32(thisIf) == ifVoidCode {
 11920  			b = int32(p) == 0
 11921  		} else if int32(p) == 0 {
 11922  			b = false
 11923  		} else if int32(thisIf) == ifHboxCode {
 11924  			b = int32(*(*prg.mem[p].hh()).b0()) == hlistNode
 11925  		} else {
 11926  			b = int32(*(*prg.mem[p].hh()).b0()) == vlistNode
 11927  		}
 11928  
 11929  	case ifxCode:
 11930  		// Test if two tokens match
 11931  		saveScannerStatus = prg.scannerStatus
 11932  		prg.scannerStatus = byte(normal)
 11933  		prg.getNext()
 11934  		n = int32(prg.curCs)
 11935  		p = uint16(prg.curCmd)
 11936  		q = prg.curChr
 11937  		prg.getNext()
 11938  		if int32(prg.curCmd) != int32(p) {
 11939  			b = false
 11940  		} else if int32(prg.curCmd) < call {
 11941  			b = int32(prg.curChr) == int32(q)
 11942  		} else {
 11943  			// Test if two macro texts match
 11944  			p = *(*prg.mem[prg.curChr].hh()).rh()
 11945  			q = *(*prg.mem[*(*prg.eqtb[n-1].hh()).rh()].hh()).rh() // omit reference counts
 11946  			if int32(p) == int32(q) {
 11947  				b = true
 11948  			} else {
 11949  				for int32(p) != 0 && int32(q) != 0 {
 11950  					if int32(*(*prg.mem[p].hh()).lh()) != int32(*(*prg.mem[q].hh()).lh()) {
 11951  						p = 0
 11952  					} else {
 11953  						p = *(*prg.mem[p].hh()).rh()
 11954  						q = *(*prg.mem[q].hh()).rh()
 11955  					}
 11956  				}
 11957  				b = int32(p) == 0 && int32(q) == 0
 11958  			}
 11959  		}
 11960  		prg.scannerStatus = saveScannerStatus
 11961  
 11962  	case ifEofCode:
 11963  		prg.scanFourBitInt()
 11964  		b = int32(prg.readOpen[prg.curVal]) == closed
 11965  
 11966  	case ifTrueCode:
 11967  		b = true
 11968  	case ifFalseCode:
 11969  		b = false
 11970  	case ifCaseCode:
 11971  		// Select the appropriate case and |return| or |goto common_ending|
 11972  		prg.scanInt()
 11973  		n = prg.curVal // |n| is the number of cases to pass
 11974  		if *prg.eqtb[intBase+tracingCommandsCode-1].int() > 1 {
 11975  			prg.beginDiagnostic()
 11976  			prg.print( /* "[case " */ 783)
 11977  			prg.printInt(n)
 11978  			prg.printChar(asciiCode('}'))
 11979  			prg.endDiagnostic(false)
 11980  		}
 11981  		for n != 0 {
 11982  			prg.passText()
 11983  			if int32(prg.condPtr) == int32(saveCondPtr) {
 11984  				if int32(prg.curChr) == orCode {
 11985  					n = n - 1
 11986  				} else {
 11987  					goto commonEnding
 11988  				}
 11989  			} else if int32(prg.curChr) == fiCode {
 11990  				p = prg.condPtr
 11991  				prg.ifLine = *prg.mem[int32(p)+1].int()
 11992  				prg.curIf = *(*prg.mem[p].hh()).b1()
 11993  				prg.ifLimit = *(*prg.mem[p].hh()).b0()
 11994  				prg.condPtr = *(*prg.mem[p].hh()).rh()
 11995  				prg.freeNode(p, halfword(ifNodeSize))
 11996  			}
 11997  		}
 11998  		prg.changeIfLimit(smallNumber(orCode), saveCondPtr)
 11999  
 12000  		goto exit // wait for \.[\\or], \.[\\else], or \.[\\fi]
 12001  
 12002  	}
 12003  	if *prg.eqtb[intBase+tracingCommandsCode-1].int() > 1 {
 12004  		prg.beginDiagnostic()
 12005  		if b {
 12006  			prg.print( /* "[true]" */ 779)
 12007  		} else {
 12008  			prg.print( /* "[false]" */ 780)
 12009  		}
 12010  		prg.endDiagnostic(false)
 12011  	}
 12012  	if b {
 12013  		prg.changeIfLimit(smallNumber(elseCode), saveCondPtr)
 12014  
 12015  		goto exit // wait for \.[\\else] or \.[\\fi]
 12016  	}
 12017  
 12018  	// Skip to \.[\\else] or \.[\\fi], then |goto common_ending|
 12019  	for true {
 12020  		prg.passText()
 12021  		if int32(prg.condPtr) == int32(saveCondPtr) {
 12022  			if int32(prg.curChr) != orCode {
 12023  				goto commonEnding
 12024  			}
 12025  			{
 12026  				if int32(prg.interaction) == errorStopMode {
 12027  				}
 12028  				prg.printNl(strNumber( /* "! " */ 262))
 12029  				prg.print( /* "Extra " */ 777)
 12030  			}
 12031  			prg.printEsc(strNumber( /* "or" */ 775))
 12032  			// \xref[Extra \\or]
 12033  			{
 12034  				prg.helpPtr = 1
 12035  				prg.helpLine[0] = /* "I'm ignoring this; it doesn't match any \\if." */ 778
 12036  			}
 12037  			prg.error1()
 12038  		} else if int32(prg.curChr) == fiCode {
 12039  			p = prg.condPtr
 12040  			prg.ifLine = *prg.mem[int32(p)+1].int()
 12041  			prg.curIf = *(*prg.mem[p].hh()).b1()
 12042  			prg.ifLimit = *(*prg.mem[p].hh()).b0()
 12043  			prg.condPtr = *(*prg.mem[p].hh()).rh()
 12044  			prg.freeNode(p, halfword(ifNodeSize))
 12045  		}
 12046  	}
 12047  
 12048  commonEnding:
 12049  	if int32(prg.curChr) == fiCode {
 12050  		p = prg.condPtr
 12051  		prg.ifLine = *prg.mem[int32(p)+1].int()
 12052  		prg.curIf = *(*prg.mem[p].hh()).b1()
 12053  		prg.ifLimit = *(*prg.mem[p].hh()).b0()
 12054  		prg.condPtr = *(*prg.mem[p].hh()).rh()
 12055  		prg.freeNode(p, halfword(ifNodeSize))
 12056  	} else {
 12057  		prg.ifLimit = byte(fiCode)
 12058  	} // wait for \.[\\fi]
 12059  	// wait for \.[\\fi]
 12060  exit:
 12061  }
 12062  
 12063  // 499.
 12064  
 12065  // tangle:pos tex.web:9737:1:
 12066  
 12067  // In a construction like `\.[\\if\\iftrue abc\\else d\\fi]', the first
 12068  // \.[\\else] that we come to after learning that the \.[\\if] is false is
 12069  // not the \.[\\else] we're looking for. Hence the following curious
 12070  // logic is needed.
 12071  
 12072  // 511. \[29] File names
 12073  
 12074  // tangle:pos tex.web:9910:19:
 12075  
 12076  // It's time now to fret about file names.  Besides the fact that different
 12077  // operating systems treat files in different ways, we must cope with the
 12078  // fact that completely different naming conventions are used by different
 12079  // groups of people. The following programs show what is required for one
 12080  // particular operating system; similar routines for other systems are not
 12081  // difficult to devise.
 12082  // \xref[fingers]
 12083  // \xref[system dependencies]
 12084  //
 12085  // \TeX\ assumes that a file name has three parts: the name proper; its
 12086  // ``extension''; and a ``file area'' where it is found in an external file
 12087  // system.  The extension of an input file or a write file is assumed to be
 12088  // `\.[.tex]' unless otherwise specified; it is `\.[.log]' on the
 12089  // transcript file that records each run of \TeX; it is `\.[.tfm]' on the font
 12090  // metric files that describe characters in the fonts \TeX\ uses; it is
 12091  // `\.[.dvi]' on the output files that specify typesetting information; and it
 12092  // is `\.[.fmt]' on the format files written by \.[INITEX] to initialize \TeX.
 12093  // The file area can be arbitrary on input files, but files are usually
 12094  // output to the user's current area.  If an input file cannot be
 12095  // found on the specified area, \TeX\ will look for it on a special system
 12096  // area; this special area is intended for commonly used input files like
 12097  // \.[webmac.tex].
 12098  //
 12099  // Simple uses of \TeX\ refer only to file names that have no explicit
 12100  // extension or area. For example, a person usually says `\.[\\input] \.[paper]'
 12101  // or `\.[\\font\\tenrm] \.= \.[helvetica]' instead of `\.[\\input]
 12102  // \.[paper.new]' or `\.[\\font\\tenrm] \.= \.[<csd.knuth>test]'. Simple file
 12103  // names are best, because they make the \TeX\ source files portable;
 12104  // whenever a file name consists entirely of letters and digits, it should be
 12105  // treated in the same way by all implementations of \TeX. However, users
 12106  // need the ability to refer to other files in their environment, especially
 12107  // when responding to error messages concerning unopenable files; therefore
 12108  // we want to let them use the syntax that appears in their favorite
 12109  // operating system.
 12110  //
 12111  // The following procedures don't allow spaces to be part of
 12112  // file names; but some users seem to like names that are spaced-out.
 12113  // System-dependent changes to allow such things should probably
 12114  // be made with reluctance, and only when an entire file name that
 12115  // includes spaces is ``quoted'' somehow.
 12116  
 12117  // 514.
 12118  
 12119  // tangle:pos tex.web:9998:1:
 12120  
 12121  // Input files that can't be found in the user's area may appear in a standard
 12122  // system area called |TEX_area|. Font metric files whose areas are not given
 12123  // explicitly are assumed to appear in a standard system area called
 12124  // |TEX_font_area|.  These system area names will, of course, vary from place
 12125  // to place.
 12126  // \xref[system dependencies]
 12127  
 12128  // 515.
 12129  
 12130  // tangle:pos tex.web:10010:1:
 12131  
 12132  // Here now is the first of the system-dependent routines for file name scanning.
 12133  // \xref[system dependencies]
 12134  func (prg *prg) beginName() {
 12135  	prg.areaDelimiter = 0
 12136  	prg.extDelimiter = 0
 12137  }
 12138  
 12139  // 516.
 12140  
 12141  // tangle:pos tex.web:10017:1:
 12142  
 12143  // And here's the second. The string pool might change as the file name is
 12144  // being scanned, since a new \.[\\csname] might be entered; therefore we keep
 12145  // |area_delimiter| and |ext_delimiter| relative to the beginning of the current
 12146  // string, instead of assigning an absolute address like |pool_ptr| to them.
 12147  // \xref[system dependencies]
 12148  func (prg *prg) moreName(c asciiCode) (r bool) {
 12149  	if int32(c) == ' ' {
 12150  		r = false
 12151  	} else {
 12152  		{
 12153  			if int32(prg.poolPtr)+1 > poolSize {
 12154  				prg.overflow(strNumber( /* "pool size" */ 257), poolSize-int32(prg.initPoolPtr))
 12155  			} /* \xref[TeX capacity exceeded pool size][\quad pool size]  */
 12156  		}
 12157  		{
 12158  			prg.strPool[prg.poolPtr] = c
 12159  			prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
 12160  		} // contribute |c| to the current string
 12161  		if int32(c) == '>' || int32(c) == ':' {
 12162  			prg.areaDelimiter = uint16(int32(prg.poolPtr) - int32(prg.strStart[prg.strPtr]))
 12163  			prg.extDelimiter = 0
 12164  		} else if int32(c) == '.' && int32(prg.extDelimiter) == 0 {
 12165  			prg.extDelimiter = uint16(int32(prg.poolPtr) - int32(prg.strStart[prg.strPtr]))
 12166  		}
 12167  		r = true
 12168  	}
 12169  	return r
 12170  }
 12171  
 12172  // 517.
 12173  
 12174  // tangle:pos tex.web:10034:1:
 12175  
 12176  // The third.
 12177  // \xref[system dependencies]
 12178  func (prg *prg) endName() {
 12179  	if int32(prg.strPtr)+3 > maxStrings {
 12180  		prg.overflow(strNumber( /* "number of strings" */ 258), maxStrings-int32(prg.initStrPtr))
 12181  	}
 12182  	// \xref[TeX capacity exceeded number of strings][\quad number of strings]
 12183  	if int32(prg.areaDelimiter) == 0 {
 12184  		prg.curArea = /* "" */ 338
 12185  	} else {
 12186  		prg.curArea = prg.strPtr
 12187  		prg.strStart[int32(prg.strPtr)+1] = uint16(int32(prg.strStart[prg.strPtr]) + int32(prg.areaDelimiter))
 12188  		prg.strPtr = uint16(int32(prg.strPtr) + 1)
 12189  	}
 12190  	if int32(prg.extDelimiter) == 0 {
 12191  		prg.curExt = /* "" */ 338
 12192  		prg.curName = prg.makeString()
 12193  	} else {
 12194  		prg.curName = prg.strPtr
 12195  		prg.strStart[int32(prg.strPtr)+1] = uint16(int32(prg.strStart[prg.strPtr]) + int32(prg.extDelimiter) - int32(prg.areaDelimiter) - 1)
 12196  		prg.strPtr = uint16(int32(prg.strPtr) + 1)
 12197  		prg.curExt = prg.makeString()
 12198  	}
 12199  }
 12200  
 12201  // 519.
 12202  
 12203  // tangle:pos tex.web:10064:1:
 12204  
 12205  // Another system-dependent routine is needed to convert three internal
 12206  // \TeX\ strings
 12207  // into the |name_of_file| value that is used to open files. The present code
 12208  // allows both lowercase and uppercase letters in the file name.
 12209  // \xref[system dependencies]
 12210  func (prg *prg) packFileName(n, a, e strNumber) {
 12211  	var (
 12212  		k int32       // number of positions filled in |name_of_file|
 12213  		c asciiCode   // character being packed
 12214  		j poolPointer // index into |str_pool|
 12215  	)
 12216  	k = 0
 12217  	for ii := int32(prg.strStart[a]); ii <= int32(prg.strStart[int32(a)+1])-1; ii++ {
 12218  		j = poolPointer(ii)
 12219  		_ = j
 12220  		c = prg.strPool[j]
 12221  		k = k + 1
 12222  		if k <= fileNameSize {
 12223  			prg.nameOfFile[k-1] = prg.xchr[c]
 12224  		}
 12225  	}
 12226  	for ii := int32(prg.strStart[n]); ii <= int32(prg.strStart[int32(n)+1])-1; ii++ {
 12227  		j = poolPointer(ii)
 12228  		_ = j
 12229  		c = prg.strPool[j]
 12230  		k = k + 1
 12231  		if k <= fileNameSize {
 12232  			prg.nameOfFile[k-1] = prg.xchr[c]
 12233  		}
 12234  	}
 12235  	for ii := int32(prg.strStart[e]); ii <= int32(prg.strStart[int32(e)+1])-1; ii++ {
 12236  		j = poolPointer(ii)
 12237  		_ = j
 12238  		c = prg.strPool[j]
 12239  		k = k + 1
 12240  		if k <= fileNameSize {
 12241  			prg.nameOfFile[k-1] = prg.xchr[c]
 12242  		}
 12243  	}
 12244  	if k <= fileNameSize {
 12245  		prg.nameLength = byte(k)
 12246  	} else {
 12247  		prg.nameLength = byte(fileNameSize)
 12248  	}
 12249  	for ii := int32(prg.nameLength) + 1; ii <= fileNameSize; ii++ {
 12250  		k = ii
 12251  		_ = k
 12252  		prg.nameOfFile[k-1] = ' '
 12253  	}
 12254  }
 12255  
 12256  // 523.
 12257  
 12258  // tangle:pos tex.web:10109:1:
 12259  
 12260  // Here is the messy routine that was just mentioned. It sets |name_of_file|
 12261  // from the first |n| characters of |TEX_format_default|, followed by
 12262  // |buffer[a..b]|, followed by the last |format_ext_length| characters of
 12263  // |TEX_format_default|.
 12264  //
 12265  // We dare not give error messages here, since \TeX\ calls this routine before
 12266  // the |error| routine is ready to roll. Instead, we simply drop excess characters,
 12267  // since the error will be detected in another way when a strange file name
 12268  // isn't found.
 12269  // \xref[system dependencies]
 12270  func (prg *prg) packBufferedName(n smallNumber, a, b int32) {
 12271  	var (
 12272  		k int32     // number of positions filled in |name_of_file|
 12273  		c asciiCode // character being packed
 12274  		j int32     // index into |buffer| or |TEX_format_default|
 12275  	)
 12276  	if int32(n)+b-a+1+formatExtLength > fileNameSize {
 12277  		b = a + fileNameSize - int32(n) - 1 - formatExtLength
 12278  	}
 12279  	k = 0
 12280  	for ii := int32(1); ii <= int32(n); ii++ {
 12281  		j = ii
 12282  		_ = j
 12283  		c = prg.xord[prg.texFormatDefault[j-1]]
 12284  		k = k + 1
 12285  		if k <= fileNameSize {
 12286  			prg.nameOfFile[k-1] = prg.xchr[c]
 12287  		}
 12288  	}
 12289  	for ii := a; ii <= b; ii++ {
 12290  		j = ii
 12291  		_ = j
 12292  		c = prg.buffer[j]
 12293  		k = k + 1
 12294  		if k <= fileNameSize {
 12295  			prg.nameOfFile[k-1] = prg.xchr[c]
 12296  		}
 12297  	}
 12298  	for ii := int32(formatDefaultLength - formatExtLength + 1); ii <= formatDefaultLength; ii++ {
 12299  		j = ii
 12300  		_ = j
 12301  		c = prg.xord[prg.texFormatDefault[j-1]]
 12302  		k = k + 1
 12303  		if k <= fileNameSize {
 12304  			prg.nameOfFile[k-1] = prg.xchr[c]
 12305  		}
 12306  	}
 12307  	if k <= fileNameSize {
 12308  		prg.nameLength = byte(k)
 12309  	} else {
 12310  		prg.nameLength = byte(fileNameSize)
 12311  	}
 12312  	for ii := int32(prg.nameLength) + 1; ii <= fileNameSize; ii++ {
 12313  		k = ii
 12314  		_ = k
 12315  		prg.nameOfFile[k-1] = ' '
 12316  	}
 12317  }
 12318  
 12319  // 525.
 12320  
 12321  // tangle:pos tex.web:10172:1:
 12322  
 12323  // Operating systems often make it possible to determine the exact name (and
 12324  // possible version number) of a file that has been opened. The following routine,
 12325  // which simply makes a \TeX\ string from the value of |name_of_file|, should
 12326  // ideally be changed to deduce the full name of file~|f|, which is the file
 12327  // most recently opened, if it is possible to do this in a \PASCAL\ program.
 12328  // \xref[system dependencies]
 12329  //
 12330  // This routine might be called after string memory has overflowed, hence
 12331  // we dare not use `|str_room|'.
 12332  func (prg *prg) makeNameString() (r strNumber) {
 12333  	var (
 12334  		k /* 1..fileNameSize */ byte // index into |name_of_file|
 12335  	)
 12336  	if int32(prg.poolPtr)+int32(prg.nameLength) > poolSize || int32(prg.strPtr) == maxStrings || int32(prg.poolPtr)-int32(prg.strStart[prg.strPtr]) > 0 {
 12337  		r = '?'
 12338  	} else {
 12339  		for ii := int32(1); ii <= int32(prg.nameLength); ii++ {
 12340  			k = byte(ii)
 12341  			_ = k
 12342  			prg.strPool[prg.poolPtr] = prg.xord[prg.nameOfFile[k-1]]
 12343  			prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
 12344  		}
 12345  		r = prg.makeString()
 12346  	}
 12347  	return r
 12348  }
 12349  func (prg *prg) aMakeNameString(f alphaFile) (r strNumber) {
 12350  	r = prg.makeNameString()
 12351  	return r
 12352  }
 12353  func (prg *prg) bMakeNameString(f byteFile) (r strNumber) {
 12354  	r = prg.makeNameString()
 12355  	return r
 12356  }
 12357  func (prg *prg) wMakeNameString(f wordFile) (r strNumber) {
 12358  	r = prg.makeNameString()
 12359  	return r
 12360  }
 12361  
 12362  // 526.
 12363  
 12364  // tangle:pos tex.web:10201:1:
 12365  
 12366  // Now let's consider the ``driver''
 12367  // routines by which \TeX\ deals with file names
 12368  // in a system-independent manner.  First comes a procedure that looks for a
 12369  // file name in the input by calling |get_x_token| for the information.
 12370  func (prg *prg) scanFileName() {
 12371  	prg.nameInProgress = true
 12372  	prg.beginName()
 12373  
 12374  	// Get the next non-blank non-call...
 12375  	for {
 12376  		prg.getXToken()
 12377  		if int32(prg.curCmd) != spacer {
 12378  			break
 12379  		}
 12380  	}
 12381  	for true {
 12382  		if int32(prg.curCmd) > otherChar || int32(prg.curChr) > 255 {
 12383  			prg.backInput()
 12384  			goto done
 12385  		}
 12386  		if !prg.moreName(asciiCode(prg.curChr)) {
 12387  			goto done
 12388  		}
 12389  		prg.getXToken()
 12390  	}
 12391  
 12392  done:
 12393  	prg.endName()
 12394  	prg.nameInProgress = false
 12395  }
 12396  
 12397  // 529.
 12398  
 12399  // tangle:pos tex.web:10243:1:
 12400  
 12401  // Here is a routine that manufactures the output file names, assuming that
 12402  // |job_name<>0|. It ignores and changes the current settings of |cur_area|
 12403  // and |cur_ext|.
 12404  func (prg *prg) packJobName(s strNumber) {
 12405  	prg.curArea = /* "" */ 338
 12406  	prg.curExt = s
 12407  	prg.curName = prg.jobName
 12408  	prg.packFileName(prg.curName, prg.curArea, prg.curExt)
 12409  }
 12410  
 12411  // 530.
 12412  
 12413  // tangle:pos tex.web:10255:1:
 12414  
 12415  // If some trouble arises when \TeX\ tries to open a file, the following
 12416  // routine calls upon the user to supply another file name. Parameter~|s|
 12417  // is used in the error message to identify the type of file; parameter~|e|
 12418  // is the default extension if none is given. Upon exit from the routine,
 12419  // variables |cur_name|, |cur_area|, |cur_ext|, and |name_of_file| are
 12420  // ready for another attempt at file opening.
 12421  func (prg *prg) promptFileName(s, e strNumber) {
 12422  	var (
 12423  		k /* 0..bufSize */ uint16 // index into |buffer|
 12424  	)
 12425  	if int32(prg.interaction) == scrollMode {
 12426  	}
 12427  	if int32(s) == 787 {
 12428  		if int32(prg.interaction) == errorStopMode {
 12429  		}
 12430  		prg.printNl(strNumber( /* "! " */ 262))
 12431  		prg.print( /* "I can't find file `" */ 788)
 12432  	} else {
 12433  		if int32(prg.interaction) == errorStopMode {
 12434  		}
 12435  		prg.printNl(strNumber( /* "! " */ 262))
 12436  		prg.print( /* "I can't write on file `" */ 789)
 12437  	}
 12438  	// \xref[I can't write on file x]
 12439  	prg.printFileName(int32(prg.curName), int32(prg.curArea), int32(prg.curExt))
 12440  	prg.print( /* "'." */ 790)
 12441  	if int32(e) == 791 {
 12442  		prg.showContext()
 12443  	}
 12444  	prg.printNl(strNumber( /* "Please type another " */ 792))
 12445  	prg.print(int32(s))
 12446  	// \xref[Please type...]
 12447  	if int32(prg.interaction) < scrollMode {
 12448  		prg.fatalError(strNumber( /* "*** (job aborted, file error in nonstop mode)" */ 793))
 12449  	}
 12450  	// \xref[job aborted, file error...]
 12451  	{
 12452  		prg.print( /* ": " */ 568)
 12453  		prg.termInput()
 12454  	}
 12455  	// Scan file name in the buffer
 12456  	{
 12457  		prg.beginName()
 12458  		k = prg.first
 12459  		for int32(prg.buffer[k]) == ' ' && int32(k) < int32(prg.last) {
 12460  			k = uint16(int32(k) + 1)
 12461  		}
 12462  		for true {
 12463  			if int32(k) == int32(prg.last) {
 12464  				goto done
 12465  			}
 12466  			if !prg.moreName(prg.buffer[k]) {
 12467  				goto done
 12468  			}
 12469  			k = uint16(int32(k) + 1)
 12470  		}
 12471  
 12472  	done:
 12473  		prg.endName()
 12474  	}
 12475  	if int32(prg.curExt) == 338 {
 12476  		prg.curExt = e
 12477  	}
 12478  	prg.packFileName(prg.curName, prg.curArea, prg.curExt)
 12479  } // \2
 12480  
 12481  func (prg *prg) openLogFile() {
 12482  	var (
 12483  		oldSetting/* 0..maxSelector */ byte          // previous |selector| setting
 12484  		k/* 0..bufSize */ uint16                     // index into |months| and |buffer|
 12485  		l/* 0..bufSize */ uint16                     // end of first input line
 12486  		months                              [36]char // abbreviations of month names
 12487  	)
 12488  	oldSetting = prg.selector
 12489  	if int32(prg.jobName) == 0 {
 12490  		prg.jobName = /* "texput" */ 796
 12491  	}
 12492  	// \xref[texput]
 12493  	prg.packJobName(strNumber( /* ".log" */ 797))
 12494  	for !prg.aOpenOut(prg.logFile) {
 12495  		// Try to get a different log file name
 12496  		prg.selector = byte(termOnly)
 12497  		prg.promptFileName(strNumber( /* "transcript file name" */ 799), strNumber( /* ".log" */ 797))
 12498  	}
 12499  	prg.logName = prg.aMakeNameString(prg.logFile)
 12500  	prg.selector = byte(logOnly)
 12501  	prg.logOpened = true
 12502  
 12503  	// Print the banner line, including the date and time
 12504  	{
 12505  		prg.logFile.Write("This is TeX, Version 3.141592653 (gotex v0.0-prerelease)")
 12506  		prg.slowPrint(int32(prg.formatIdent))
 12507  		prg.print( /* "  " */ 800)
 12508  		prg.printInt(prg.sysDay)
 12509  		prg.printChar(asciiCode(' '))
 12510  		strcopy(months[:], "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC")
 12511  		for ii := 3*prg.sysMonth - 2; ii <= 3*prg.sysMonth; ii++ {
 12512  			k = uint16(ii)
 12513  			_ = k
 12514  			prg.logFile.Write(string(rune(months[k-1])))
 12515  		}
 12516  		prg.printChar(asciiCode(' '))
 12517  		prg.printInt(prg.sysYear)
 12518  		prg.printChar(asciiCode(' '))
 12519  		prg.printTwo(prg.sysTime / 60)
 12520  		prg.printChar(asciiCode(':'))
 12521  		prg.printTwo(prg.sysTime % 60)
 12522  	}
 12523  	prg.inputStack[prg.inputPtr] = prg.curInput // make sure bottom level is in memory
 12524  	prg.printNl(strNumber( /* "**" */ 798))
 12525  	// \xref[**]
 12526  	l = prg.inputStack[0].limitField // last position of first line
 12527  	if int32(prg.buffer[l]) == *prg.eqtb[intBase+endLineCharCode-1].int() {
 12528  		l = uint16(int32(l) - 1)
 12529  	}
 12530  	for ii := int32(1); ii <= int32(l); ii++ {
 12531  		k = uint16(ii)
 12532  		_ = k
 12533  		prg.print(int32(prg.buffer[k]))
 12534  	}
 12535  	prg.printLn()                              // now the transcript file contains the first line of input
 12536  	prg.selector = byte(int32(oldSetting) + 2) // |log_only| or |term_and_log|
 12537  } // \2
 12538  func (prg *prg) startInput() {
 12539  	prg.scanFileName() // set |cur_name| to desired file name
 12540  	if int32(prg.curExt) == 338 {
 12541  		prg.curExt = /* ".tex" */ 791
 12542  	}
 12543  	prg.packFileName(prg.curName, prg.curArea, prg.curExt)
 12544  	for true {
 12545  		prg.beginFileReading() // set up |cur_file| and new level of input
 12546  		if prg.aOpenIn(prg.inputFile[prg.curInput.indexField-1]) {
 12547  			goto done
 12548  		}
 12549  		if int32(prg.curArea) == 338 {
 12550  			prg.packFileName(prg.curName, strNumber( /* "TeXinputs:" */ 784), prg.curExt)
 12551  			if prg.aOpenIn(prg.inputFile[prg.curInput.indexField-1]) {
 12552  				goto done
 12553  			}
 12554  		}
 12555  		prg.endFileReading() // remove the level that didn't work
 12556  		prg.promptFileName(strNumber( /* "input file name" */ 787), strNumber( /* ".tex" */ 791))
 12557  	}
 12558  
 12559  done:
 12560  	prg.curInput.nameField = prg.aMakeNameString(prg.inputFile[prg.curInput.indexField-1])
 12561  	if int32(prg.jobName) == 0 {
 12562  		prg.jobName = prg.curName
 12563  		prg.openLogFile()
 12564  	} // |open_log_file| doesn't |show_context|, so |limit|
 12565  	//     and |loc| needn't be set to meaningful values yet
 12566  
 12567  	if int32(prg.termOffset)+(int32(prg.strStart[int32(prg.curInput.nameField)+1])-int32(prg.strStart[prg.curInput.nameField])) > maxPrintLine-2 {
 12568  		prg.printLn()
 12569  	} else if int32(prg.termOffset) > 0 || int32(prg.fileOffset) > 0 {
 12570  		prg.printChar(asciiCode(' '))
 12571  	}
 12572  	prg.printChar(asciiCode('('))
 12573  	prg.openParens = byte(int32(prg.openParens) + 1)
 12574  	prg.slowPrint(int32(prg.curInput.nameField))
 12575  	prg.curInput.stateField = byte(newLine)
 12576  	if int32(prg.curInput.nameField) == int32(prg.strPtr)-1 {
 12577  		{
 12578  			prg.strPtr = uint16(int32(prg.strPtr) - 1)
 12579  			prg.poolPtr = prg.strStart[prg.strPtr]
 12580  		}
 12581  		prg.curInput.nameField = prg.curName
 12582  	}
 12583  
 12584  	// Read the first line of the new file
 12585  	{
 12586  		prg.line = 1
 12587  		if prg.inputLn(prg.inputFile[prg.curInput.indexField-1], false) {
 12588  		}
 12589  		prg.firmUpTheLine()
 12590  		if *prg.eqtb[intBase+endLineCharCode-1].int() < 0 || *prg.eqtb[intBase+endLineCharCode-1].int() > 255 {
 12591  			prg.curInput.limitField = uint16(int32(prg.curInput.limitField) - 1)
 12592  		} else {
 12593  			prg.buffer[prg.curInput.limitField] = byte(*prg.eqtb[intBase+endLineCharCode-1].int())
 12594  		}
 12595  		prg.first = uint16(int32(prg.curInput.limitField) + 1)
 12596  		prg.curInput.locField = prg.curInput.startField
 12597  	}
 12598  }
 12599  
 12600  // 540.
 12601  
 12602  // tangle:pos tex.web:10433:1:
 12603  
 12604  // The first 24 bytes (6 words) of a \.[TFM] file contain twelve 16-bit
 12605  // integers that give the lengths of the various subsequent portions
 12606  // of the file. These twelve integers are, in order:
 12607  // $$\vbox[\halign[\hfil#&$\null=\null$#\hfil\cr
 12608  // |lf|&length of the entire file, in words;\cr
 12609  // |lh|&length of the header data, in words;\cr
 12610  // |bc|&smallest character code in the font;\cr
 12611  // |ec|&largest character code in the font;\cr
 12612  // |nw|&number of words in the width table;\cr
 12613  // |nh|&number of words in the height table;\cr
 12614  // |nd|&number of words in the depth table;\cr
 12615  // |ni|&number of words in the italic correction table;\cr
 12616  // |nl|&number of words in the lig/kern table;\cr
 12617  // |nk|&number of words in the kern table;\cr
 12618  // |ne|&number of words in the extensible character table;\cr
 12619  // |np|&number of font parameter words.\cr]]$$
 12620  // They are all nonnegative and less than $2^[15]$. We must have |bc-1<=ec<=255|,
 12621  // and
 12622  // $$\hbox[|lf=6+lh+(ec-bc+1)+nw+nh+nd+ni+nl+nk+ne+np|.]$$
 12623  // Note that a font may contain as many as 256 characters (if |bc=0| and |ec=255|),
 12624  // and as few as 0 characters (if |bc=ec+1|).
 12625  //
 12626  // Incidentally, when two or more 8-bit bytes are combined to form an integer of
 12627  // 16 or more bits, the most significant bytes appear first in the file.
 12628  // This is called BigEndian order.
 12629  //  \xref[BigEndian order]
 12630  
 12631  // 541.
 12632  
 12633  // tangle:pos tex.web:10460:1:
 12634  
 12635  // The rest of the \.[TFM] file may be regarded as a sequence of ten data
 12636  // arrays having the informal specification
 12637  // $$\def\arr$[#1]#2$[\&[array] $[#1]$ \&[of] #2]
 12638  // \vbox[\halign[\hfil\\[#]&$\,:\,$\arr#\hfil\cr
 12639  // header&|[0..lh-1]\\[stuff]|\cr
 12640  // char\_info&|[bc..ec]char_info_word|\cr
 12641  // width&|[0..nw-1]fix_word|\cr
 12642  // height&|[0..nh-1]fix_word|\cr
 12643  // depth&|[0..nd-1]fix_word|\cr
 12644  // italic&|[0..ni-1]fix_word|\cr
 12645  // lig\_kern&|[0..nl-1]lig_kern_command|\cr
 12646  // kern&|[0..nk-1]fix_word|\cr
 12647  // exten&|[0..ne-1]extensible_recipe|\cr
 12648  // param&|[1..np]fix_word|\cr]]$$
 12649  // The most important data type used here is a | fix_word|, which is
 12650  // a 32-bit representation of a binary fraction. A |fix_word| is a signed
 12651  // quantity, with the two's complement of the entire word used to represent
 12652  // negation. Of the 32 bits in a |fix_word|, exactly 12 are to the left of the
 12653  // binary point; thus, the largest |fix_word| value is $2048-2^[-20]$, and
 12654  // the smallest is $-2048$. We will see below, however, that all but two of
 12655  // the |fix_word| values must lie between $-16$ and $+16$.
 12656  
 12657  // 542.
 12658  
 12659  // tangle:pos tex.web:10482:1:
 12660  
 12661  // The first data array is a block of header information, which contains
 12662  // general facts about the font. The header must contain at least two words,
 12663  // |header[0]| and |header[1]|, whose meaning is explained below.
 12664  // Additional header information of use to other software routines might
 12665  // also be included, but \TeX82 does not need to know about such details.
 12666  // For example, 16 more words of header information are in use at the Xerox
 12667  // Palo Alto Research Center; the first ten specify the character coding
 12668  // scheme used (e.g., `\.[XEROX text]' or `\.[TeX math symbols]'), the next five
 12669  // give the font identifier (e.g., `\.[HELVETICA]' or `\.[CMSY]'), and the
 12670  // last gives the ``face byte.'' The program that converts \.[DVI] files
 12671  // to Xerox printing format gets this information by looking at the \.[TFM]
 12672  // file, which it needs to read anyway because of other information that
 12673  // is not explicitly repeated in \.[DVI]~format.
 12674  //
 12675  // \yskip\hang|header[0]| is a 32-bit check sum that \TeX\ will copy into
 12676  // the \.[DVI] output file. Later on when the \.[DVI] file is printed,
 12677  // possibly on another computer, the actual font that gets used is supposed
 12678  // to have a check sum that agrees with the one in the \.[TFM] file used by
 12679  // \TeX. In this way, users will be warned about potential incompatibilities.
 12680  // (However, if the check sum is zero in either the font file or the \.[TFM]
 12681  // file, no check is made.)  The actual relation between this check sum and
 12682  // the rest of the \.[TFM] file is not important; the check sum is simply an
 12683  // identification number with the property that incompatible fonts almost
 12684  // always have distinct check sums.
 12685  // \xref[check sum]
 12686  //
 12687  // \yskip\hang|header[1]| is a |fix_word| containing the design size of
 12688  // the font, in units of \TeX\ points. This number must be at least 1.0; it is
 12689  // fairly arbitrary, but usually the design size is 10.0 for a ``10 point''
 12690  // font, i.e., a font that was designed to look best at a 10-point size,
 12691  // whatever that really means. When a \TeX\ user asks for a font
 12692  // `\.[at] $\delta$ \.[pt]', the effect is to override the design size
 12693  // and replace it by $\delta$, and to multiply the $x$ and~$y$ coordinates
 12694  // of the points in the font image by a factor of $\delta$ divided by the
 12695  // design size.  [\sl All other dimensions in the\/ \.[TFM] file are
 12696  // |fix_word|\kern-1pt\ numbers in design-size units], with the exception of
 12697  // |param[1]| (which denotes the slant ratio). Thus, for example, the value
 12698  // of |param[6]|, which defines the \.[em] unit, is often the |fix_word| value
 12699  // $2^[20]=1.0$, since many fonts have a design size equal to one em.
 12700  // The other dimensions must be less than 16 design-size units in absolute
 12701  // value; thus, |header[1]| and |param[1]| are the only |fix_word|
 12702  // entries in the whole \.[TFM] file whose first byte might be something
 12703  // besides 0 or 255.
 12704  
 12705  // 543.
 12706  
 12707  // tangle:pos tex.web:10526:1:
 12708  
 12709  // Next comes the |char_info| array, which contains one | char_info_word|
 12710  // per character. Each word in this part of the file contains six fields
 12711  // packed into four bytes as follows.
 12712  //
 12713  // \yskip\hang first byte: | width_index| (8 bits)\par
 12714  // \hang second byte: | height_index| (4 bits) times 16, plus | depth_index|
 12715  //   (4~bits)\par
 12716  // \hang third byte: | italic_index| (6 bits) times 4, plus | tag|
 12717  //   (2~bits)\par
 12718  // \hang fourth byte: | remainder| (8 bits)\par
 12719  // \yskip\noindent
 12720  // The actual width of a character is \\[width]|[width_index]|, in design-size
 12721  // units; this is a device for compressing information, since many characters
 12722  // have the same width. Since it is quite common for many characters
 12723  // to have the same height, depth, or italic correction, the \.[TFM] format
 12724  // imposes a limit of 16 different heights, 16 different depths, and
 12725  // 64 different italic corrections.
 12726  //
 12727  //  \xref[italic correction]
 12728  // The italic correction of a character has two different uses.
 12729  // (a)~In ordinary text, the italic correction is added to the width only if
 12730  // the \TeX\ user specifies `\.[\\/]' after the character.
 12731  // (b)~In math formulas, the italic correction is always added to the width,
 12732  // except with respect to the positioning of subscripts.
 12733  //
 12734  // Incidentally, the relation $\\[width][0]=\\[height][0]=\\[depth][0]=
 12735  // \\[italic][0]=0$ should always hold, so that an index of zero implies a
 12736  // value of zero.  The |width_index| should never be zero unless the
 12737  // character does not exist in the font, since a character is valid if and
 12738  // only if it lies between |bc| and |ec| and has a nonzero |width_index|.
 12739  
 12740  // 544.
 12741  
 12742  // tangle:pos tex.web:10557:1:
 12743  
 12744  // The |tag| field in a |char_info_word| has four values that explain how to
 12745  // interpret the |remainder| field.
 12746  //
 12747  // \yskip\hangg|tag=0| (|no_tag|) means that |remainder| is unused.\par
 12748  // \hangg|tag=1| (|lig_tag|) means that this character has a ligature/kerning
 12749  // program starting at position |remainder| in the |lig_kern| array.\par
 12750  // \hangg|tag=2| (|list_tag|) means that this character is part of a chain of
 12751  // characters of ascending sizes, and not the largest in the chain.  The
 12752  // |remainder| field gives the character code of the next larger character.\par
 12753  // \hangg|tag=3| (|ext_tag|) means that this character code represents an
 12754  // extensible character, i.e., a character that is built up of smaller pieces
 12755  // so that it can be made arbitrarily large. The pieces are specified in
 12756  // | exten[remainder]|.\par
 12757  // \yskip\noindent
 12758  // Characters with |tag=2| and |tag=3| are treated as characters with |tag=0|
 12759  // unless they are used in special circumstances in math formulas. For example,
 12760  // the \.[\\sum] operation looks for a |list_tag|, and the \.[\\left]
 12761  // operation looks for both |list_tag| and |ext_tag|.
 12762  
 12763  // 545.
 12764  
 12765  // tangle:pos tex.web:10581:1:
 12766  
 12767  // The |lig_kern| array contains instructions in a simple programming language
 12768  // that explains what to do for special letter pairs. Each word in this array is a
 12769  // | lig_kern_command| of four bytes.
 12770  //
 12771  // \yskip\hang first byte: |skip_byte|, indicates that this is the final program
 12772  //   step if the byte is 128 or more, otherwise the next step is obtained by
 12773  //   skipping this number of intervening steps.\par
 12774  // \hang second byte: |next_char|, ``if |next_char| follows the current character,
 12775  //   then perform the operation and stop, otherwise continue.''\par
 12776  // \hang third byte: |op_byte|, indicates a ligature step if less than~128,
 12777  //   a kern step otherwise.\par
 12778  // \hang fourth byte: |remainder|.\par
 12779  // \yskip\noindent
 12780  // In a kern step, an
 12781  // additional space equal to |kern[256*(op_byte-128)+remainder]| is inserted
 12782  // between the current character and |next_char|. This amount is
 12783  // often negative, so that the characters are brought closer together
 12784  // by kerning; but it might be positive.
 12785  //
 12786  // There are eight kinds of ligature steps, having |op_byte| codes $4a+2b+c$ where
 12787  // $0\le a\le b+c$ and $0\le b,c\le1$. The character whose code is
 12788  // |remainder| is inserted between the current character and |next_char|;
 12789  // then the current character is deleted if $b=0$, and |next_char| is
 12790  // deleted if $c=0$; then we pass over $a$~characters to reach the next
 12791  // current character (which may have a ligature/kerning program of its own).
 12792  //
 12793  // If the very first instruction of the |lig_kern| array has |skip_byte=255|,
 12794  // the |next_char| byte is the so-called boundary character of this font;
 12795  // the value of |next_char| need not lie between |bc| and~|ec|.
 12796  // If the very last instruction of the |lig_kern| array has |skip_byte=255|,
 12797  // there is a special ligature/kerning program for a boundary character at the
 12798  // left, beginning at location |256*op_byte+remainder|.
 12799  // The interpretation is that \TeX\ puts implicit boundary characters
 12800  // before and after each consecutive string of characters from the same font.
 12801  // These implicit characters do not appear in the output, but they can affect
 12802  // ligatures and kerning.
 12803  //
 12804  // If the very first instruction of a character's |lig_kern| program has
 12805  // |skip_byte>128|, the program actually begins in location
 12806  // |256*op_byte+remainder|. This feature allows access to large |lig_kern|
 12807  // arrays, because the first instruction must otherwise
 12808  // appear in a location |<=255|.
 12809  //
 12810  // Any instruction with |skip_byte>128| in the |lig_kern| array must satisfy
 12811  // the condition
 12812  // $$\hbox[|256*op_byte+remainder<nl|.]$$
 12813  // If such an instruction is encountered during
 12814  // normal program execution, it denotes an unconditional halt; no ligature
 12815  // or kerning command is performed.
 12816  
 12817  // 546.
 12818  
 12819  // tangle:pos tex.web:10638:1:
 12820  
 12821  // Extensible characters are specified by an | extensible_recipe|, which
 12822  // consists of four bytes called | top|, | mid|, | bot|, and | rep| (in this
 12823  // order). These bytes are the character codes of individual pieces used to
 12824  // build up a large symbol.  If |top|, |mid|, or |bot| are zero, they are not
 12825  // present in the built-up result. For example, an extensible vertical line is
 12826  // like an extensible bracket, except that the top and bottom pieces are missing.
 12827  //
 12828  // Let $T$, $M$, $B$, and $R$ denote the respective pieces, or an empty box
 12829  // if the piece isn't present. Then the extensible characters have the form
 12830  // $TR^kMR^kB$ from top to bottom, for some |k>=0|, unless $M$ is absent;
 12831  // in the latter case we can have $TR^kB$ for both even and odd values of~|k|.
 12832  // The width of the extensible character is the width of $R$; and the
 12833  // height-plus-depth is the sum of the individual height-plus-depths of the
 12834  // components used, since the pieces are butted together in a vertical list.
 12835  
 12836  // 547.
 12837  
 12838  // tangle:pos tex.web:10658:1:
 12839  
 12840  // The final portion of a \.[TFM] file is the |param| array, which is another
 12841  // sequence of |fix_word| values.
 12842  //
 12843  // \yskip\hang|param[1]=slant| is the amount of italic slant, which is used
 12844  // to help position accents. For example, |slant=.25| means that when you go
 12845  // up one unit, you also go .25 units to the right. The |slant| is a pure
 12846  // number; it's the only |fix_word| other than the design size itself that is
 12847  // not scaled by the design size.
 12848  //
 12849  // \hang|param[2]=space| is the normal spacing between words in text.
 12850  // Note that character |" "| in the font need not have anything to do with
 12851  // blank spaces.
 12852  //
 12853  // \hang|param[3]=space_stretch| is the amount of glue stretching between words.
 12854  //
 12855  // \hang|param[4]=space_shrink| is the amount of glue shrinking between words.
 12856  //
 12857  // \hang|param[5]=x_height| is the size of one ex in the font; it is also
 12858  // the height of letters for which accents don't have to be raised or lowered.
 12859  //
 12860  // \hang|param[6]=quad| is the size of one em in the font.
 12861  //
 12862  // \hang|param[7]=extra_space| is the amount added to |param[2]| at the
 12863  // ends of sentences.
 12864  //
 12865  // \yskip\noindent
 12866  // If fewer than seven parameters are present, \TeX\ sets the missing parameters
 12867  // to zero. Fonts used for math symbols are required to have
 12868  // additional parameter information, which is explained later.
 12869  
 12870  // 554.
 12871  
 12872  // tangle:pos tex.web:10804:1:
 12873  
 12874  // Of course we want to define macros that suppress the detail of how font
 12875  // information is actually packed, so that we don't have to write things like
 12876  // $$\hbox[|font_info[width_base[f]+font_info[char_base[f]+c].qqqq.b0].sc|]$$
 12877  // too often. The \.[WEB] definitions here make |char_info(f)(c)| the
 12878  // |four_quarters| word of font information corresponding to character
 12879  // |c| of font |f|. If |q| is such a word, |char_width(f)(q)| will be
 12880  // the character's width; hence the long formula above is at least
 12881  // abbreviated to
 12882  // $$\hbox[|char_width(f)(char_info(f)(c))|.]$$
 12883  // Usually, of course, we will fetch |q| first and look at several of its
 12884  // fields at the same time.
 12885  //
 12886  // The italic correction of a character will be denoted by
 12887  // |char_italic(f)(q)|, so it is analogous to |char_width|.  But we will get
 12888  // at the height and depth in a slightly different way, since we usually want
 12889  // to compute both height and depth if we want either one.  The value of
 12890  // |height_depth(q)| will be the 8-bit quantity
 12891  // $$b=|height_index|\times16+|depth_index|,$$ and if |b| is such a byte we
 12892  // will write |char_height(f)(b)| and |char_depth(f)(b)| for the height and
 12893  // depth of the character |c| for which |q=char_info(f)(c)|. Got that?
 12894  //
 12895  // The tag field will be called |char_tag(q)|; the remainder byte will be
 12896  // called |rem_byte(q)|, using a macro that we have already defined above.
 12897  //
 12898  // Access to a character's |width|, |height|, |depth|, and |tag| fields is
 12899  // part of \TeX's inner loop, so we want these macros to produce code that is
 12900  // as fast as possible under the circumstances.
 12901  // \xref[inner loop]
 12902  
 12903  // 557.
 12904  
 12905  // tangle:pos tex.web:10858:1:
 12906  
 12907  // Here are some macros that help process ligatures and kerns.
 12908  // We write |char_kern(f)(j)| to find the amount of kerning specified by
 12909  // kerning command~|j| in font~|f|. If |j| is the |char_info| for a character
 12910  // with a ligature/kern program, the first instruction of that program is either
 12911  // |i=font_info[lig_kern_start(f)(j)]| or |font_info[lig_kern_restart(f)(i)]|,
 12912  // depending on whether or not |skip_byte(i)<=stop_flag|.
 12913  //
 12914  // The constant |kern_base_offset| should be simplified, for \PASCAL\ compilers
 12915  // that do not do local optimization.
 12916  // \xref[system dependencies]
 12917  
 12918  // 560.
 12919  
 12920  // tangle:pos tex.web:10892:1:
 12921  
 12922  // \TeX\ checks the information of a \.[TFM] file for validity as the
 12923  // file is being read in, so that no further checks will be needed when
 12924  // typesetting is going on. The somewhat tedious subroutine that does this
 12925  // is called |read_font_info|. It has four parameters: the user font
 12926  // identifier~|u|, the file name and area strings |nom| and |aire|, and the
 12927  // ``at'' size~|s|. If |s|~is negative, it's the negative of a scale factor
 12928  // to be applied to the design size; |s=-1000| is the normal case.
 12929  // Otherwise |s| will be substituted for the design size; in this
 12930  // case, |s| must be positive and less than $2048\rm\,pt$
 12931  // (i.e., it must be less than $2^[27]$ when considered as an integer).
 12932  //
 12933  // The subroutine opens and closes a global file variable called |tfm_file|.
 12934  // It returns the value of the internal font number that was just loaded.
 12935  // If an error is detected, an error message is issued and no font
 12936  // information is stored; |null_font| is returned in this case.
 12937  func (prg *prg) readFontInfo(u halfword, nom, aire strNumber,
 12938  	s scaled) (r internalFontNumber) {
 12939  	var (
 12940  		k                                              fontIndex // index into |font_info|
 12941  		fileOpened                                     bool      // was |tfm_file| successfully opened?
 12942  		lf, lh, bc, ec, nw, nh, nd, ni, nl, nk, ne, np halfword
 12943  		// sizes of subfiles
 12944  		f                        internalFontNumber // the new font's number
 12945  		g                        internalFontNumber // the number to return
 12946  		a, b, c, d               eightBits          // byte variables
 12947  		qw                       fourQuarters
 12948  		sw                       scaled // accumulators
 12949  		bchLabel                 int32  // left boundary start location, or infinity
 12950  		bchar/* 0..256 */ uint16        // boundary character, or 256
 12951  		z                        scaled // the design size or the ``at'' size
 12952  		alpha                    int32
 12953  		beta/* 1..16 */ byte
 12954  	// auxiliary quantities used in fixed-point multiplication
 12955  	)
 12956  	g = byte(fontBase)
 12957  
 12958  	// Read and check the font data; |abort| if the \.[TFM] file is malformed; if there's no room for this font, say so and |goto done|; otherwise |incr(font_ptr)| and |goto done|
 12959  
 12960  	// Open |tfm_file| for input
 12961  	fileOpened = false
 12962  	if int32(aire) == 338 {
 12963  		prg.packFileName(nom, strNumber( /* "TeXfonts:" */ 785), strNumber( /* ".tfm" */ 811))
 12964  	} else {
 12965  		prg.packFileName(nom, aire, strNumber( /* ".tfm" */ 811))
 12966  	}
 12967  	if !prg.bOpenIn(prg.tfmFile) {
 12968  		goto badTfm
 12969  	}
 12970  	fileOpened = true
 12971  
 12972  	// Read the [\.[TFM]] size fields
 12973  	{
 12974  		{
 12975  			lf = uint16(*prg.tfmFile.ByteP())
 12976  			if int32(lf) > 127 {
 12977  				goto badTfm
 12978  			}
 12979  			prg.tfmFile.Get()
 12980  			lf = uint16(int32(lf)*0400 + int32(*prg.tfmFile.ByteP()))
 12981  		}
 12982  		prg.tfmFile.Get()
 12983  		{
 12984  			lh = uint16(*prg.tfmFile.ByteP())
 12985  			if int32(lh) > 127 {
 12986  				goto badTfm
 12987  			}
 12988  			prg.tfmFile.Get()
 12989  			lh = uint16(int32(lh)*0400 + int32(*prg.tfmFile.ByteP()))
 12990  		}
 12991  		prg.tfmFile.Get()
 12992  		{
 12993  			bc = uint16(*prg.tfmFile.ByteP())
 12994  			if int32(bc) > 127 {
 12995  				goto badTfm
 12996  			}
 12997  			prg.tfmFile.Get()
 12998  			bc = uint16(int32(bc)*0400 + int32(*prg.tfmFile.ByteP()))
 12999  		}
 13000  		prg.tfmFile.Get()
 13001  		{
 13002  			ec = uint16(*prg.tfmFile.ByteP())
 13003  			if int32(ec) > 127 {
 13004  				goto badTfm
 13005  			}
 13006  			prg.tfmFile.Get()
 13007  			ec = uint16(int32(ec)*0400 + int32(*prg.tfmFile.ByteP()))
 13008  		}
 13009  		if int32(bc) > int32(ec)+1 || int32(ec) > 255 {
 13010  			goto badTfm
 13011  		}
 13012  		if int32(bc) > 255 {
 13013  			bc = 1
 13014  			ec = 0
 13015  		}
 13016  		prg.tfmFile.Get()
 13017  		{
 13018  			nw = uint16(*prg.tfmFile.ByteP())
 13019  			if int32(nw) > 127 {
 13020  				goto badTfm
 13021  			}
 13022  			prg.tfmFile.Get()
 13023  			nw = uint16(int32(nw)*0400 + int32(*prg.tfmFile.ByteP()))
 13024  		}
 13025  		prg.tfmFile.Get()
 13026  		{
 13027  			nh = uint16(*prg.tfmFile.ByteP())
 13028  			if int32(nh) > 127 {
 13029  				goto badTfm
 13030  			}
 13031  			prg.tfmFile.Get()
 13032  			nh = uint16(int32(nh)*0400 + int32(*prg.tfmFile.ByteP()))
 13033  		}
 13034  		prg.tfmFile.Get()
 13035  		{
 13036  			nd = uint16(*prg.tfmFile.ByteP())
 13037  			if int32(nd) > 127 {
 13038  				goto badTfm
 13039  			}
 13040  			prg.tfmFile.Get()
 13041  			nd = uint16(int32(nd)*0400 + int32(*prg.tfmFile.ByteP()))
 13042  		}
 13043  		prg.tfmFile.Get()
 13044  		{
 13045  			ni = uint16(*prg.tfmFile.ByteP())
 13046  			if int32(ni) > 127 {
 13047  				goto badTfm
 13048  			}
 13049  			prg.tfmFile.Get()
 13050  			ni = uint16(int32(ni)*0400 + int32(*prg.tfmFile.ByteP()))
 13051  		}
 13052  		prg.tfmFile.Get()
 13053  		{
 13054  			nl = uint16(*prg.tfmFile.ByteP())
 13055  			if int32(nl) > 127 {
 13056  				goto badTfm
 13057  			}
 13058  			prg.tfmFile.Get()
 13059  			nl = uint16(int32(nl)*0400 + int32(*prg.tfmFile.ByteP()))
 13060  		}
 13061  		prg.tfmFile.Get()
 13062  		{
 13063  			nk = uint16(*prg.tfmFile.ByteP())
 13064  			if int32(nk) > 127 {
 13065  				goto badTfm
 13066  			}
 13067  			prg.tfmFile.Get()
 13068  			nk = uint16(int32(nk)*0400 + int32(*prg.tfmFile.ByteP()))
 13069  		}
 13070  		prg.tfmFile.Get()
 13071  		{
 13072  			ne = uint16(*prg.tfmFile.ByteP())
 13073  			if int32(ne) > 127 {
 13074  				goto badTfm
 13075  			}
 13076  			prg.tfmFile.Get()
 13077  			ne = uint16(int32(ne)*0400 + int32(*prg.tfmFile.ByteP()))
 13078  		}
 13079  		prg.tfmFile.Get()
 13080  		{
 13081  			np = uint16(*prg.tfmFile.ByteP())
 13082  			if int32(np) > 127 {
 13083  				goto badTfm
 13084  			}
 13085  			prg.tfmFile.Get()
 13086  			np = uint16(int32(np)*0400 + int32(*prg.tfmFile.ByteP()))
 13087  		}
 13088  		if int32(lf) != 6+int32(lh)+(int32(ec)-int32(bc)+1)+int32(nw)+int32(nh)+int32(nd)+int32(ni)+int32(nl)+int32(nk)+int32(ne)+int32(np) {
 13089  			goto badTfm
 13090  		}
 13091  		if int32(nw) == 0 || int32(nh) == 0 || int32(nd) == 0 || int32(ni) == 0 {
 13092  			goto badTfm
 13093  		}
 13094  	}
 13095  
 13096  	// Use size fields to allocate font information
 13097  	lf = uint16(int32(lf) - 6 - int32(lh)) // |lf| words should be loaded into |font_info|
 13098  	if int32(np) < 7 {
 13099  		lf = uint16(int32(lf) + 7 - int32(np))
 13100  	} // at least seven parameters will appear
 13101  	if int32(prg.fontPtr) == fontMax || int32(prg.fmemPtr)+int32(lf) > fontMemSize {
 13102  		{
 13103  			if int32(prg.interaction) == errorStopMode {
 13104  			}
 13105  			prg.printNl(strNumber( /* "! " */ 262))
 13106  			prg.print( /* "Font " */ 802)
 13107  		}
 13108  		prg.sprintCs(u)
 13109  		prg.printChar(asciiCode('='))
 13110  		prg.printFileName(int32(nom), int32(aire) /* "" */, 338)
 13111  		if s >= 0 {
 13112  			prg.print( /* " at " */ 741)
 13113  			prg.printScaled(s)
 13114  			prg.print( /* "pt" */ 397)
 13115  		} else if s != -1000 {
 13116  			prg.print( /* " scaled " */ 803)
 13117  			prg.printInt(-s)
 13118  		}
 13119  		prg.print( /* " not loaded: Not enough room left" */ 812)
 13120  		// \xref[Font x=xx not loaded...]
 13121  		{
 13122  			prg.helpPtr = 4
 13123  			prg.helpLine[3] = /* "I'm afraid I won't be able to make use of this font," */ 813
 13124  			prg.helpLine[2] = /* "because my memory for character-size data is too small." */ 814
 13125  			prg.helpLine[1] = /* "If you're really stuck, ask a wizard to enlarge me." */ 815
 13126  			prg.helpLine[0] = /* "Or maybe try `I\\font<same font id>=<name of loaded font>'." */ 816
 13127  		}
 13128  		prg.error1()
 13129  		goto done
 13130  	}
 13131  	f = byte(int32(prg.fontPtr) + 1)
 13132  	prg.charBase[f] = int32(prg.fmemPtr) - int32(bc)
 13133  	prg.widthBase[f] = prg.charBase[f] + int32(ec) + 1
 13134  	prg.heightBase[f] = prg.widthBase[f] + int32(nw)
 13135  	prg.depthBase[f] = prg.heightBase[f] + int32(nh)
 13136  	prg.italicBase[f] = prg.depthBase[f] + int32(nd)
 13137  	prg.ligKernBase[f] = prg.italicBase[f] + int32(ni)
 13138  	prg.kernBase[f] = prg.ligKernBase[f] + int32(nl) - 256*(128+minQuarterword)
 13139  	prg.extenBase[f] = prg.kernBase[f] + 256*(128+minQuarterword) + int32(nk)
 13140  	prg.paramBase[f] = prg.extenBase[f] + int32(ne)
 13141  
 13142  	// Read the [\.[TFM]] header
 13143  	{
 13144  		if int32(lh) < 2 {
 13145  			goto badTfm
 13146  		}
 13147  		{
 13148  			prg.tfmFile.Get()
 13149  			a = *prg.tfmFile.ByteP()
 13150  			qw.b0 = byte(int32(a) + minQuarterword)
 13151  			prg.tfmFile.Get()
 13152  			b = *prg.tfmFile.ByteP()
 13153  			qw.b1 = byte(int32(b) + minQuarterword)
 13154  			prg.tfmFile.Get()
 13155  			c = *prg.tfmFile.ByteP()
 13156  			qw.b2 = byte(int32(c) + minQuarterword)
 13157  			prg.tfmFile.Get()
 13158  			d = *prg.tfmFile.ByteP()
 13159  			qw.b3 = byte(int32(d) + minQuarterword)
 13160  			prg.fontCheck[f] = qw
 13161  		}
 13162  		prg.tfmFile.Get()
 13163  		{
 13164  			z = int32(*prg.tfmFile.ByteP())
 13165  			if z > 127 {
 13166  				goto badTfm
 13167  			}
 13168  			prg.tfmFile.Get()
 13169  			z = z*0400 + int32(*prg.tfmFile.ByteP())
 13170  		} // this rejects a negative design size
 13171  		prg.tfmFile.Get()
 13172  		z = z*0400 + int32(*prg.tfmFile.ByteP())
 13173  		prg.tfmFile.Get()
 13174  		z = z*020 + int32(*prg.tfmFile.ByteP())/020
 13175  		if z < 0200000 {
 13176  			goto badTfm
 13177  		}
 13178  		for int32(lh) > 2 {
 13179  			prg.tfmFile.Get()
 13180  			prg.tfmFile.Get()
 13181  			prg.tfmFile.Get()
 13182  			prg.tfmFile.Get()
 13183  			lh = uint16(int32(lh) - 1) // ignore the rest of the header
 13184  		}
 13185  		prg.fontDsize[f] = z
 13186  		if s != -1000 {
 13187  			if s >= 0 {
 13188  				z = s
 13189  			} else {
 13190  				z = prg.xnOverD(z, -s, 1000)
 13191  			}
 13192  		}
 13193  		prg.fontSize[f] = z
 13194  	}
 13195  
 13196  	// Read character data
 13197  	for ii := int32(prg.fmemPtr); ii <= prg.widthBase[f]-1; ii++ {
 13198  		k = fontIndex(ii)
 13199  		_ = k
 13200  		{
 13201  			prg.tfmFile.Get()
 13202  			a = *prg.tfmFile.ByteP()
 13203  			qw.b0 = byte(int32(a) + minQuarterword)
 13204  			prg.tfmFile.Get()
 13205  			b = *prg.tfmFile.ByteP()
 13206  			qw.b1 = byte(int32(b) + minQuarterword)
 13207  			prg.tfmFile.Get()
 13208  			c = *prg.tfmFile.ByteP()
 13209  			qw.b2 = byte(int32(c) + minQuarterword)
 13210  			prg.tfmFile.Get()
 13211  			d = *prg.tfmFile.ByteP()
 13212  			qw.b3 = byte(int32(d) + minQuarterword)
 13213  			*prg.fontInfo[k].qqqq() = qw
 13214  		}
 13215  		if int32(a) >= int32(nw) || int32(b)/020 >= int32(nh) || int32(b)%020 >= int32(nd) || int32(c)/4 >= int32(ni) {
 13216  			goto badTfm
 13217  		}
 13218  		switch int32(c) % 4 {
 13219  		case ligTag:
 13220  			if int32(d) >= int32(nl) {
 13221  				goto badTfm
 13222  			}
 13223  		case extTag:
 13224  			if int32(d) >= int32(ne) {
 13225  				goto badTfm
 13226  			}
 13227  		case listTag:
 13228  			// Check for charlist cycle
 13229  			{
 13230  				if int32(d) < int32(bc) || int32(d) > int32(ec) {
 13231  					goto badTfm
 13232  				}
 13233  			}
 13234  			for int32(d) < int32(k)+int32(bc)-int32(prg.fmemPtr) {
 13235  				qw = *prg.fontInfo[prg.charBase[f]+int32(d)].qqqq()
 13236  				// N.B.: not |qi(d)|, since |char_base[f]| hasn't been adjusted yet
 13237  				if (int32(qw.b2)-minQuarterword)%4 != listTag {
 13238  					goto notFound
 13239  				}
 13240  				d = byte(int32(qw.b3) - minQuarterword) // next character on the list
 13241  			}
 13242  			if int32(d) == int32(k)+int32(bc)-int32(prg.fmemPtr) {
 13243  				goto badTfm
 13244  			} // yes, there's a cycle
 13245  			// yes, there's a cycle
 13246  		notFound:
 13247  			;
 13248  
 13249  		default: // |no_tag|
 13250  		}
 13251  	}
 13252  
 13253  	// Read box dimensions
 13254  	{
 13255  		{
 13256  			alpha = 16
 13257  			for z >= 040000000 {
 13258  				z = z / 2
 13259  				alpha = alpha + alpha
 13260  			}
 13261  			beta = byte(256 / alpha)
 13262  			alpha = alpha * z
 13263  		}
 13264  		for ii := prg.widthBase[f]; ii <= prg.ligKernBase[f]-1; ii++ {
 13265  			k = fontIndex(ii)
 13266  			_ = k
 13267  			prg.tfmFile.Get()
 13268  			a = *prg.tfmFile.ByteP()
 13269  			prg.tfmFile.Get()
 13270  			b = *prg.tfmFile.ByteP()
 13271  			prg.tfmFile.Get()
 13272  			c = *prg.tfmFile.ByteP()
 13273  			prg.tfmFile.Get()
 13274  			d = *prg.tfmFile.ByteP()
 13275  			sw = ((int32(d)*z/0400+int32(c)*z)/0400 + int32(b)*z) / int32(beta)
 13276  			if int32(a) == 0 {
 13277  				*prg.fontInfo[k].int() = sw
 13278  			} else if int32(a) == 255 {
 13279  				*prg.fontInfo[k].int() = sw - alpha
 13280  			} else {
 13281  				goto badTfm
 13282  			}
 13283  		}
 13284  		if *prg.fontInfo[prg.widthBase[f]].int() != 0 {
 13285  			goto badTfm
 13286  		} // \\[width][0] must be zero
 13287  		if *prg.fontInfo[prg.heightBase[f]].int() != 0 {
 13288  			goto badTfm
 13289  		} // \\[height][0] must be zero
 13290  		if *prg.fontInfo[prg.depthBase[f]].int() != 0 {
 13291  			goto badTfm
 13292  		} // \\[depth][0] must be zero
 13293  		if *prg.fontInfo[prg.italicBase[f]].int() != 0 {
 13294  			goto badTfm
 13295  		} // \\[italic][0] must be zero
 13296  	}
 13297  
 13298  	// Read ligature/kern program
 13299  	bchLabel = 077777
 13300  	bchar = 256
 13301  	if int32(nl) > 0 {
 13302  		for ii := prg.ligKernBase[f]; ii <= prg.kernBase[f]+256*(128+minQuarterword)-1; ii++ {
 13303  			k = fontIndex(ii)
 13304  			_ = k
 13305  			{
 13306  				prg.tfmFile.Get()
 13307  				a = *prg.tfmFile.ByteP()
 13308  				qw.b0 = byte(int32(a) + minQuarterword)
 13309  				prg.tfmFile.Get()
 13310  				b = *prg.tfmFile.ByteP()
 13311  				qw.b1 = byte(int32(b) + minQuarterword)
 13312  				prg.tfmFile.Get()
 13313  				c = *prg.tfmFile.ByteP()
 13314  				qw.b2 = byte(int32(c) + minQuarterword)
 13315  				prg.tfmFile.Get()
 13316  				d = *prg.tfmFile.ByteP()
 13317  				qw.b3 = byte(int32(d) + minQuarterword)
 13318  				*prg.fontInfo[k].qqqq() = qw
 13319  			}
 13320  			if int32(a) > 128 {
 13321  				if 256*int32(c)+int32(d) >= int32(nl) {
 13322  					goto badTfm
 13323  				}
 13324  				if int32(a) == 255 {
 13325  					if int32(k) == prg.ligKernBase[f] {
 13326  						bchar = uint16(b)
 13327  					}
 13328  				}
 13329  			} else {
 13330  				if int32(b) != int32(bchar) {
 13331  					{
 13332  						if int32(b) < int32(bc) || int32(b) > int32(ec) {
 13333  							goto badTfm
 13334  						}
 13335  					}
 13336  					qw = *prg.fontInfo[prg.charBase[f]+int32(b)].qqqq()
 13337  					if !(int32(qw.b0) > minQuarterword) {
 13338  						goto badTfm
 13339  					}
 13340  				}
 13341  				if int32(c) < 128 {
 13342  					{
 13343  						if int32(d) < int32(bc) || int32(d) > int32(ec) {
 13344  							goto badTfm
 13345  						}
 13346  					}
 13347  					qw = *prg.fontInfo[prg.charBase[f]+int32(d)].qqqq()
 13348  					if !(int32(qw.b0) > minQuarterword) {
 13349  						goto badTfm
 13350  					}
 13351  				} else if 256*(int32(c)-128)+int32(d) >= int32(nk) {
 13352  					goto badTfm
 13353  				} // check kern
 13354  				if int32(a) < 128 {
 13355  					if int32(k)-prg.ligKernBase[f]+int32(a)+1 >= int32(nl) {
 13356  						goto badTfm
 13357  					}
 13358  				}
 13359  			}
 13360  		}
 13361  		if int32(a) == 255 {
 13362  			bchLabel = 256*int32(c) + int32(d)
 13363  		}
 13364  	}
 13365  	for ii := prg.kernBase[f] + 256*(128+minQuarterword); ii <= prg.extenBase[f]-1; ii++ {
 13366  		k = fontIndex(ii)
 13367  		_ = k
 13368  		prg.tfmFile.Get()
 13369  		a = *prg.tfmFile.ByteP()
 13370  		prg.tfmFile.Get()
 13371  		b = *prg.tfmFile.ByteP()
 13372  		prg.tfmFile.Get()
 13373  		c = *prg.tfmFile.ByteP()
 13374  		prg.tfmFile.Get()
 13375  		d = *prg.tfmFile.ByteP()
 13376  		sw = ((int32(d)*z/0400+int32(c)*z)/0400 + int32(b)*z) / int32(beta)
 13377  		if int32(a) == 0 {
 13378  			*prg.fontInfo[k].int() = sw
 13379  		} else if int32(a) == 255 {
 13380  			*prg.fontInfo[k].int() = sw - alpha
 13381  		} else {
 13382  			goto badTfm
 13383  		}
 13384  	}
 13385  
 13386  	// Read extensible character recipes
 13387  	for ii := prg.extenBase[f]; ii <= prg.paramBase[f]-1; ii++ {
 13388  		k = fontIndex(ii)
 13389  		_ = k
 13390  		{
 13391  			prg.tfmFile.Get()
 13392  			a = *prg.tfmFile.ByteP()
 13393  			qw.b0 = byte(int32(a) + minQuarterword)
 13394  			prg.tfmFile.Get()
 13395  			b = *prg.tfmFile.ByteP()
 13396  			qw.b1 = byte(int32(b) + minQuarterword)
 13397  			prg.tfmFile.Get()
 13398  			c = *prg.tfmFile.ByteP()
 13399  			qw.b2 = byte(int32(c) + minQuarterword)
 13400  			prg.tfmFile.Get()
 13401  			d = *prg.tfmFile.ByteP()
 13402  			qw.b3 = byte(int32(d) + minQuarterword)
 13403  			*prg.fontInfo[k].qqqq() = qw
 13404  		}
 13405  		if int32(a) != 0 {
 13406  			{
 13407  				if int32(a) < int32(bc) || int32(a) > int32(ec) {
 13408  					goto badTfm
 13409  				}
 13410  			}
 13411  			qw = *prg.fontInfo[prg.charBase[f]+int32(a)].qqqq()
 13412  			if !(int32(qw.b0) > minQuarterword) {
 13413  				goto badTfm
 13414  			}
 13415  		}
 13416  		if int32(b) != 0 {
 13417  			{
 13418  				if int32(b) < int32(bc) || int32(b) > int32(ec) {
 13419  					goto badTfm
 13420  				}
 13421  			}
 13422  			qw = *prg.fontInfo[prg.charBase[f]+int32(b)].qqqq()
 13423  			if !(int32(qw.b0) > minQuarterword) {
 13424  				goto badTfm
 13425  			}
 13426  		}
 13427  		if int32(c) != 0 {
 13428  			{
 13429  				if int32(c) < int32(bc) || int32(c) > int32(ec) {
 13430  					goto badTfm
 13431  				}
 13432  			}
 13433  			qw = *prg.fontInfo[prg.charBase[f]+int32(c)].qqqq()
 13434  			if !(int32(qw.b0) > minQuarterword) {
 13435  				goto badTfm
 13436  			}
 13437  		}
 13438  		/*   */ {
 13439  			{
 13440  				if int32(d) < int32(bc) || int32(d) > int32(ec) {
 13441  					goto badTfm
 13442  				}
 13443  			}
 13444  			qw = *prg.fontInfo[prg.charBase[f]+int32(d)].qqqq()
 13445  			if !(int32(qw.b0) > minQuarterword) {
 13446  				goto badTfm
 13447  			}
 13448  		}
 13449  	}
 13450  
 13451  	// Read font parameters
 13452  	{
 13453  		for ii := int32(1); ii <= int32(np); ii++ {
 13454  			k = fontIndex(ii)
 13455  			_ = k
 13456  			if int32(k) == 1 {
 13457  				prg.tfmFile.Get()
 13458  				sw = int32(*prg.tfmFile.ByteP())
 13459  				if sw > 127 {
 13460  					sw = sw - 256
 13461  				}
 13462  				prg.tfmFile.Get()
 13463  				sw = sw*0400 + int32(*prg.tfmFile.ByteP())
 13464  				prg.tfmFile.Get()
 13465  				sw = sw*0400 + int32(*prg.tfmFile.ByteP())
 13466  				prg.tfmFile.Get()
 13467  				*prg.fontInfo[prg.paramBase[f]].int() = sw*020 + int32(*prg.tfmFile.ByteP())/020
 13468  			} else {
 13469  				prg.tfmFile.Get()
 13470  				a = *prg.tfmFile.ByteP()
 13471  				prg.tfmFile.Get()
 13472  				b = *prg.tfmFile.ByteP()
 13473  				prg.tfmFile.Get()
 13474  				c = *prg.tfmFile.ByteP()
 13475  				prg.tfmFile.Get()
 13476  				d = *prg.tfmFile.ByteP()
 13477  				sw = ((int32(d)*z/0400+int32(c)*z)/0400 + int32(b)*z) / int32(beta)
 13478  				if int32(a) == 0 {
 13479  					*prg.fontInfo[prg.paramBase[f]+int32(k)-1].int() = sw
 13480  				} else if int32(a) == 255 {
 13481  					*prg.fontInfo[prg.paramBase[f]+int32(k)-1].int() = sw - alpha
 13482  				} else {
 13483  					goto badTfm
 13484  				}
 13485  			}
 13486  		}
 13487  		if prg.tfmFile.EOF() {
 13488  			goto badTfm
 13489  		}
 13490  		for ii := int32(np) + 1; ii <= 7; ii++ {
 13491  			k = fontIndex(ii)
 13492  			_ = k
 13493  			*prg.fontInfo[prg.paramBase[f]+int32(k)-1].int() = 0
 13494  		}
 13495  	}
 13496  
 13497  	// Make final adjustments and |goto done|
 13498  	if int32(np) >= 7 {
 13499  		prg.fontParams[f] = np
 13500  	} else {
 13501  		prg.fontParams[f] = 7
 13502  	}
 13503  	prg.hyphenChar[f] = *prg.eqtb[intBase+defaultHyphenCharCode-1].int()
 13504  	prg.skewChar[f] = *prg.eqtb[intBase+defaultSkewCharCode-1].int()
 13505  	if bchLabel < int32(nl) {
 13506  		prg.bcharLabel[f] = uint16(bchLabel + prg.ligKernBase[f])
 13507  	} else {
 13508  		prg.bcharLabel[f] = uint16(nonAddress)
 13509  	}
 13510  	prg.fontBchar[f] = uint16(int32(bchar) + minQuarterword)
 13511  	prg.fontFalseBchar[f] = uint16(int32(bchar) + minQuarterword)
 13512  	if int32(bchar) <= int32(ec) {
 13513  		if int32(bchar) >= int32(bc) {
 13514  			qw = *prg.fontInfo[prg.charBase[f]+int32(bchar)].qqqq() // N.B.: not |qi(bchar)|
 13515  			if int32(qw.b0) > minQuarterword {
 13516  				prg.fontFalseBchar[f] = uint16(256 + minQuarterword)
 13517  			}
 13518  		}
 13519  	}
 13520  	prg.fontName[f] = nom
 13521  	prg.fontArea[f] = aire
 13522  	prg.fontBc[f] = byte(bc)
 13523  	prg.fontEc[f] = byte(ec)
 13524  	prg.fontGlue[f] = 0
 13525  	prg.charBase[f] = prg.charBase[f] - minQuarterword
 13526  	prg.widthBase[f] = prg.widthBase[f] - minQuarterword
 13527  	prg.ligKernBase[f] = prg.ligKernBase[f] - minQuarterword
 13528  	prg.kernBase[f] = prg.kernBase[f] - minQuarterword
 13529  	prg.extenBase[f] = prg.extenBase[f] - minQuarterword
 13530  	prg.paramBase[f] = prg.paramBase[f] - 1
 13531  	prg.fmemPtr = uint16(int32(prg.fmemPtr) + int32(lf))
 13532  	prg.fontPtr = f
 13533  	g = f
 13534  	goto done
 13535  
 13536  badTfm:
 13537  	{
 13538  		if int32(prg.interaction) == errorStopMode {
 13539  		}
 13540  		prg.printNl(strNumber( /* "! " */ 262))
 13541  		prg.print( /* "Font " */ 802)
 13542  	}
 13543  	prg.sprintCs(u)
 13544  	prg.printChar(asciiCode('='))
 13545  	prg.printFileName(int32(nom), int32(aire) /* "" */, 338)
 13546  	if s >= 0 {
 13547  		prg.print( /* " at " */ 741)
 13548  		prg.printScaled(s)
 13549  		prg.print( /* "pt" */ 397)
 13550  	} else if s != -1000 {
 13551  		prg.print( /* " scaled " */ 803)
 13552  		prg.printInt(-s)
 13553  	}
 13554  	// \xref[Font x=xx not loadable...]
 13555  	if fileOpened {
 13556  		prg.print( /* " not loadable: Bad metric (TFM) file" */ 804)
 13557  	} else {
 13558  		prg.print( /* " not loadable: Metric (TFM) file not found" */ 805)
 13559  	}
 13560  	{
 13561  		prg.helpPtr = 5
 13562  		prg.helpLine[4] = /* "I wasn't able to read the size data for this font," */ 806
 13563  		prg.helpLine[3] = /* "so I will ignore the font specification." */ 807
 13564  		prg.helpLine[2] = /* "[Wizards can fix TFM files using TFtoPL/PLtoTF.]" */ 808
 13565  		prg.helpLine[1] = /* "You might try inserting a different font spec;" */ 809
 13566  		prg.helpLine[0] = /* "e.g., type `I\\font<same font id>=<substitute font name>'." */ 810
 13567  	}
 13568  	prg.error1()
 13569  
 13570  done:
 13571  	if fileOpened {
 13572  		prg.bClose(prg.tfmFile)
 13573  	}
 13574  	r = g
 13575  	return r
 13576  }
 13577  
 13578  // 564.
 13579  
 13580  // tangle:pos tex.web:10983:1:
 13581  
 13582  // Note: A malformed \.[TFM] file might be shorter than it claims to be;
 13583  // thus |eof(tfm_file)| might be true when |read_font_info| refers to
 13584  // |tfm_file^| or when it says |get(tfm_file)|. If such circumstances
 13585  // cause system error messages, you will have to defeat them somehow,
 13586  // for example by defining |fget| to be `\ignorespaces|begin get(tfm_file);|
 13587  // |if eof(tfm_file) then abort; end|\unskip'.
 13588  // \xref[system dependencies]
 13589  
 13590  // 581.
 13591  
 13592  // tangle:pos tex.web:11293:1:
 13593  
 13594  // When \TeX\ wants to typeset a character that doesn't exist, the
 13595  // character node is not created; thus the output routine can assume
 13596  // that characters exist when it sees them. The following procedure
 13597  // prints a warning message unless the user has suppressed it.
 13598  func (prg *prg) charWarning(f internalFontNumber, c eightBits) {
 13599  	if *prg.eqtb[intBase+tracingLostCharsCode-1].int() > 0 {
 13600  		prg.beginDiagnostic()
 13601  		prg.printNl(strNumber( /* "Missing character: There is no " */ 825))
 13602  		// \xref[Missing character]
 13603  		prg.print(int32(c))
 13604  		prg.print( /* " in font " */ 826)
 13605  		prg.slowPrint(int32(prg.fontName[f]))
 13606  		prg.printChar(asciiCode('!'))
 13607  		prg.endDiagnostic(false)
 13608  	}
 13609  }
 13610  
 13611  // 582.
 13612  
 13613  // tangle:pos tex.web:11308:1:
 13614  
 13615  // Here is a function that returns a pointer to a character node for a
 13616  // given character in a given font. If that character doesn't exist,
 13617  // |null| is returned instead.
 13618  func (prg *prg) newCharacter(f internalFontNumber, c eightBits) (r halfword) {
 13619  	var (
 13620  		p halfword // newly allocated node
 13621  	)
 13622  	if int32(prg.fontBc[f]) <= int32(c) {
 13623  		if int32(prg.fontEc[f]) >= int32(c) {
 13624  			if int32((*prg.fontInfo[prg.charBase[f]+int32(c)+minQuarterword].qqqq()).b0) > minQuarterword {
 13625  				p = prg.getAvail()
 13626  				*(*prg.mem[p].hh()).b0() = f
 13627  				*(*prg.mem[p].hh()).b1() = byte(int32(c) + minQuarterword)
 13628  				r = p
 13629  				goto exit
 13630  			}
 13631  		}
 13632  	}
 13633  	prg.charWarning(f, c)
 13634  	r = 0
 13635  
 13636  exit:
 13637  	;
 13638  	return r
 13639  }
 13640  
 13641  // 583. \[31] Device-independent file format
 13642  
 13643  // tangle:pos tex.web:11324:39:
 13644  
 13645  // The most important output produced by a run of \TeX\ is the ``device
 13646  // independent'' (\.[DVI]) file that specifies where characters and rules
 13647  // are to appear on printed pages. The form of these files was designed by
 13648  // David R. Fuchs in 1979. Almost any reasonable typesetting device can be
 13649  // \xref[Fuchs, David Raymond]
 13650  // \xref[DVI_files][\.[DVI] files]
 13651  // driven by a program that takes \.[DVI] files as input, and dozens of such
 13652  // \.[DVI]-to-whatever programs have been written. Thus, it is possible to
 13653  // print the output of \TeX\ on many different kinds of equipment, using \TeX\
 13654  // as a device-independent ``front end.''
 13655  //
 13656  // A \.[DVI] file is a stream of 8-bit bytes, which may be regarded as a
 13657  // series of commands in a machine-like language. The first byte of each command
 13658  // is the operation code, and this code is followed by zero or more bytes
 13659  // that provide parameters to the command. The parameters themselves may consist
 13660  // of several consecutive bytes; for example, the `|set_rule|' command has two
 13661  // parameters, each of which is four bytes long. Parameters are usually
 13662  // regarded as nonnegative integers; but four-byte-long parameters,
 13663  // and shorter parameters that denote distances, can be
 13664  // either positive or negative. Such parameters are given in two's complement
 13665  // notation. For example, a two-byte-long distance parameter has a value between
 13666  // $-2^[15]$ and $2^[15]-1$. As in \.[TFM] files, numbers that occupy
 13667  // more than one byte position appear in BigEndian order.
 13668  //
 13669  // A \.[DVI] file consists of a ``preamble,'' followed by a sequence of one
 13670  // or more ``pages,'' followed by a ``postamble.'' The preamble is simply a
 13671  // |pre| command, with its parameters that define the dimensions used in the
 13672  // file; this must come first.  Each ``page'' consists of a |bop| command,
 13673  // followed by any number of other commands that tell where characters are to
 13674  // be placed on a physical page, followed by an |eop| command. The pages
 13675  // appear in the order that \TeX\ generated them. If we ignore |nop| commands
 13676  // and \\[fnt\_def] commands (which are allowed between any two commands in
 13677  // the file), each |eop| command is immediately followed by a |bop| command,
 13678  // or by a |post| command; in the latter case, there are no more pages in the
 13679  // file, and the remaining bytes form the postamble.  Further details about
 13680  // the postamble will be explained later.
 13681  //
 13682  // Some parameters in \.[DVI] commands are ``pointers.'' These are four-byte
 13683  // quantities that give the location number of some other byte in the file;
 13684  // the first byte is number~0, then comes number~1, and so on. For example,
 13685  // one of the parameters of a |bop| command points to the previous |bop|;
 13686  // this makes it feasible to read the pages in backwards order, in case the
 13687  // results are being directed to a device that stacks its output face up.
 13688  // Suppose the preamble of a \.[DVI] file occupies bytes 0 to 99. Now if the
 13689  // first page occupies bytes 100 to 999, say, and if the second
 13690  // page occupies bytes 1000 to 1999, then the |bop| that starts in byte 1000
 13691  // points to 100 and the |bop| that starts in byte 2000 points to 1000. (The
 13692  // very first |bop|, i.e., the one starting in byte 100, has a pointer of~$-1$.)
 13693  
 13694  // 584.
 13695  
 13696  // tangle:pos tex.web:11374:1:
 13697  
 13698  // The \.[DVI] format is intended to be both compact and easily interpreted
 13699  // by a machine. Compactness is achieved by making most of the information
 13700  // implicit instead of explicit. When a \.[DVI]-reading program reads the
 13701  // commands for a page, it keeps track of several quantities: (a)~The current
 13702  // font |f| is an integer; this value is changed only
 13703  // by \\[fnt] and \\[fnt\_num] commands. (b)~The current position on the page
 13704  // is given by two numbers called the horizontal and vertical coordinates,
 13705  // |h| and |v|. Both coordinates are zero at the upper left corner of the page;
 13706  // moving to the right corresponds to increasing the horizontal coordinate, and
 13707  // moving down corresponds to increasing the vertical coordinate. Thus, the
 13708  // coordinates are essentially Cartesian, except that vertical directions are
 13709  // flipped; the Cartesian version of |(h,v)| would be |(h,-v)|.  (c)~The
 13710  // current spacing amounts are given by four numbers |w|, |x|, |y|, and |z|,
 13711  // where |w| and~|x| are used for horizontal spacing and where |y| and~|z|
 13712  // are used for vertical spacing. (d)~There is a stack containing
 13713  // |(h,v,w,x,y,z)| values; the \.[DVI] commands |push| and |pop| are used to
 13714  // change the current level of operation. Note that the current font~|f| is
 13715  // not pushed and popped; the stack contains only information about
 13716  // positioning.
 13717  //
 13718  // The values of |h|, |v|, |w|, |x|, |y|, and |z| are signed integers having up
 13719  // to 32 bits, including the sign. Since they represent physical distances,
 13720  // there is a small unit of measurement such that increasing |h| by~1 means
 13721  // moving a certain tiny distance to the right. The actual unit of
 13722  // measurement is variable, as explained below; \TeX\ sets things up so that
 13723  // its \.[DVI] output is in sp units, i.e., scaled points, in agreement with
 13724  // all the |scaled| dimensions in \TeX's data structures.
 13725  
 13726  // 585.
 13727  
 13728  // tangle:pos tex.web:11402:1:
 13729  
 13730  // Here is a list of all the commands that may appear in a \.[DVI] file. Each
 13731  // command is specified by its symbolic name (e.g., |bop|), its opcode byte
 13732  // (e.g., 139), and its parameters (if any). The parameters are followed
 13733  // by a bracketed number telling how many bytes they occupy; for example,
 13734  // `|p[4]|' means that parameter |p| is four bytes long.
 13735  //
 13736  // \yskip\hang|set_char_0| 0. Typeset character number~0 from font~|f|
 13737  // such that the reference point of the character is at |(h,v)|. Then
 13738  // increase |h| by the width of that character. Note that a character may
 13739  // have zero or negative width, so one cannot be sure that |h| will advance
 13740  // after this command; but |h| usually does increase.
 13741  //
 13742  // \yskip\hang\\[set\_char\_1] through \\[set\_char\_127] (opcodes 1 to 127).
 13743  // Do the operations of |set_char_0|; but use the character whose number
 13744  // matches the opcode, instead of character~0.
 13745  //
 13746  // \yskip\hang|set1| 128 |c[1]|. Same as |set_char_0|, except that character
 13747  // number~|c| is typeset. \TeX82 uses this command for characters in the
 13748  // range |128<=c<256|.
 13749  //
 13750  // \yskip\hang| set2| 129 |c[2]|. Same as |set1|, except that |c|~is two
 13751  // bytes long, so it is in the range |0<=c<65536|. \TeX82 never uses this
 13752  // command, but it should come in handy for extensions of \TeX\ that deal
 13753  // with oriental languages.
 13754  // \xref[oriental characters]\xref[Chinese characters]\xref[Japanese characters]
 13755  //
 13756  // \yskip\hang| set3| 130 |c[3]|. Same as |set1|, except that |c|~is three
 13757  // bytes long, so it can be as large as $2^[24]-1$. Not even the Chinese
 13758  // language has this many characters, but this command might prove useful
 13759  // in some yet unforeseen extension.
 13760  //
 13761  // \yskip\hang| set4| 131 |c[4]|. Same as |set1|, except that |c|~is four
 13762  // bytes long. Imagine that.
 13763  //
 13764  // \yskip\hang|set_rule| 132 |a[4]| |b[4]|. Typeset a solid black rectangle
 13765  // of height~|a| and width~|b|, with its bottom left corner at |(h,v)|. Then
 13766  // set |h:=h+b|. If either |a<=0| or |b<=0|, nothing should be typeset. Note
 13767  // that if |b<0|, the value of |h| will decrease even though nothing else happens.
 13768  // See below for details about how to typeset rules so that consistency with
 13769  // \MF\ is guaranteed.
 13770  //
 13771  // \yskip\hang| put1| 133 |c[1]|. Typeset character number~|c| from font~|f|
 13772  // such that the reference point of the character is at |(h,v)|. (The `put'
 13773  // commands are exactly like the `set' commands, except that they simply put out a
 13774  // character or a rule without moving the reference point afterwards.)
 13775  //
 13776  // \yskip\hang| put2| 134 |c[2]|. Same as |set2|, except that |h| is not changed.
 13777  //
 13778  // \yskip\hang| put3| 135 |c[3]|. Same as |set3|, except that |h| is not changed.
 13779  //
 13780  // \yskip\hang| put4| 136 |c[4]|. Same as |set4|, except that |h| is not changed.
 13781  //
 13782  // \yskip\hang|put_rule| 137 |a[4]| |b[4]|. Same as |set_rule|, except that
 13783  // |h| is not changed.
 13784  //
 13785  // \yskip\hang|nop| 138. No operation, do nothing. Any number of |nop|'s
 13786  // may occur between \.[DVI] commands, but a |nop| cannot be inserted between
 13787  // a command and its parameters or between two parameters.
 13788  //
 13789  // \yskip\hang|bop| 139 $c_0[4]$ $c_1[4]$ $\ldots$ $c_9[4]$ $p[4]$. Beginning
 13790  // of a page: Set |(h,v,w,x,y,z):=(0,0,0,0,0,0)| and set the stack empty. Set
 13791  // the current font |f| to an undefined value.  The ten $c_i$ parameters hold
 13792  // the values of \.[\\count0] $\ldots$ \.[\\count9] in \TeX\ at the time
 13793  // \.[\\shipout] was invoked for this page; they can be used to identify
 13794  // pages, if a user wants to print only part of a \.[DVI] file. The parameter
 13795  // |p| points to the previous |bop| in the file; the first
 13796  // |bop| has $p=-1$.
 13797  //
 13798  // \yskip\hang|eop| 140.  End of page: Print what you have read since the
 13799  // previous |bop|. At this point the stack should be empty. (The \.[DVI]-reading
 13800  // programs that drive most output devices will have kept a buffer of the
 13801  // material that appears on the page that has just ended. This material is
 13802  // largely, but not entirely, in order by |v| coordinate and (for fixed |v|) by
 13803  // |h|~coordinate; so it usually needs to be sorted into some order that is
 13804  // appropriate for the device in question.)
 13805  //
 13806  // \yskip\hang|push| 141. Push the current values of |(h,v,w,x,y,z)| onto the
 13807  // top of the stack; do not change any of these values. Note that |f| is
 13808  // not pushed.
 13809  //
 13810  // \yskip\hang|pop| 142. Pop the top six values off of the stack and assign
 13811  // them respectively to |(h,v,w,x,y,z)|. The number of pops should never
 13812  // exceed the number of pushes, since it would be highly embarrassing if the
 13813  // stack were empty at the time of a |pop| command.
 13814  //
 13815  // \yskip\hang|right1| 143 |b[1]|. Set |h:=h+b|, i.e., move right |b| units.
 13816  // The parameter is a signed number in two's complement notation, |-128<=b<128|;
 13817  // if |b<0|, the reference point moves left.
 13818  //
 13819  // \yskip\hang| right2| 144 |b[2]|. Same as |right1|, except that |b| is a
 13820  // two-byte quantity in the range |-32768<=b<32768|.
 13821  //
 13822  // \yskip\hang| right3| 145 |b[3]|. Same as |right1|, except that |b| is a
 13823  // three-byte quantity in the range |$-2^[23]$<=b<$2^[23]$|.
 13824  //
 13825  // \yskip\hang| right4| 146 |b[4]|. Same as |right1|, except that |b| is a
 13826  // four-byte quantity in the range |$-2^[31]$<=b<$2^[31]$|.
 13827  //
 13828  // \yskip\hang|w0| 147. Set |h:=h+w|; i.e., move right |w| units. With luck,
 13829  // this parameterless command will usually suffice, because the same kind of motion
 13830  // will occur several times in succession; the following commands explain how
 13831  // |w| gets particular values.
 13832  //
 13833  // \yskip\hang|w1| 148 |b[1]|. Set |w:=b| and |h:=h+b|. The value of |b| is a
 13834  // signed quantity in two's complement notation, |-128<=b<128|. This command
 13835  // changes the current |w|~spacing and moves right by |b|.
 13836  //
 13837  // \yskip\hang| w2| 149 |b[2]|. Same as |w1|, but |b| is two bytes long,
 13838  // |-32768<=b<32768|.
 13839  //
 13840  // \yskip\hang| w3| 150 |b[3]|. Same as |w1|, but |b| is three bytes long,
 13841  // |$-2^[23]$<=b<$2^[23]$|.
 13842  //
 13843  // \yskip\hang| w4| 151 |b[4]|. Same as |w1|, but |b| is four bytes long,
 13844  // |$-2^[31]$<=b<$2^[31]$|.
 13845  //
 13846  // \yskip\hang|x0| 152. Set |h:=h+x|; i.e., move right |x| units. The `|x|'
 13847  // commands are like the `|w|' commands except that they involve |x| instead
 13848  // of |w|.
 13849  //
 13850  // \yskip\hang|x1| 153 |b[1]|. Set |x:=b| and |h:=h+b|. The value of |b| is a
 13851  // signed quantity in two's complement notation, |-128<=b<128|. This command
 13852  // changes the current |x|~spacing and moves right by |b|.
 13853  //
 13854  // \yskip\hang| x2| 154 |b[2]|. Same as |x1|, but |b| is two bytes long,
 13855  // |-32768<=b<32768|.
 13856  //
 13857  // \yskip\hang| x3| 155 |b[3]|. Same as |x1|, but |b| is three bytes long,
 13858  // |$-2^[23]$<=b<$2^[23]$|.
 13859  //
 13860  // \yskip\hang| x4| 156 |b[4]|. Same as |x1|, but |b| is four bytes long,
 13861  // |$-2^[31]$<=b<$2^[31]$|.
 13862  //
 13863  // \yskip\hang|down1| 157 |a[1]|. Set |v:=v+a|, i.e., move down |a| units.
 13864  // The parameter is a signed number in two's complement notation, |-128<=a<128|;
 13865  // if |a<0|, the reference point moves up.
 13866  //
 13867  // \yskip\hang| down2| 158 |a[2]|. Same as |down1|, except that |a| is a
 13868  // two-byte quantity in the range |-32768<=a<32768|.
 13869  //
 13870  // \yskip\hang| down3| 159 |a[3]|. Same as |down1|, except that |a| is a
 13871  // three-byte quantity in the range |$-2^[23]$<=a<$2^[23]$|.
 13872  //
 13873  // \yskip\hang| down4| 160 |a[4]|. Same as |down1|, except that |a| is a
 13874  // four-byte quantity in the range |$-2^[31]$<=a<$2^[31]$|.
 13875  //
 13876  // \yskip\hang|y0| 161. Set |v:=v+y|; i.e., move down |y| units. With luck,
 13877  // this parameterless command will usually suffice, because the same kind of motion
 13878  // will occur several times in succession; the following commands explain how
 13879  // |y| gets particular values.
 13880  //
 13881  // \yskip\hang|y1| 162 |a[1]|. Set |y:=a| and |v:=v+a|. The value of |a| is a
 13882  // signed quantity in two's complement notation, |-128<=a<128|. This command
 13883  // changes the current |y|~spacing and moves down by |a|.
 13884  //
 13885  // \yskip\hang| y2| 163 |a[2]|. Same as |y1|, but |a| is two bytes long,
 13886  // |-32768<=a<32768|.
 13887  //
 13888  // \yskip\hang| y3| 164 |a[3]|. Same as |y1|, but |a| is three bytes long,
 13889  // |$-2^[23]$<=a<$2^[23]$|.
 13890  //
 13891  // \yskip\hang| y4| 165 |a[4]|. Same as |y1|, but |a| is four bytes long,
 13892  // |$-2^[31]$<=a<$2^[31]$|.
 13893  //
 13894  // \yskip\hang|z0| 166. Set |v:=v+z|; i.e., move down |z| units. The `|z|' commands
 13895  // are like the `|y|' commands except that they involve |z| instead of |y|.
 13896  //
 13897  // \yskip\hang|z1| 167 |a[1]|. Set |z:=a| and |v:=v+a|. The value of |a| is a
 13898  // signed quantity in two's complement notation, |-128<=a<128|. This command
 13899  // changes the current |z|~spacing and moves down by |a|.
 13900  //
 13901  // \yskip\hang| z2| 168 |a[2]|. Same as |z1|, but |a| is two bytes long,
 13902  // |-32768<=a<32768|.
 13903  //
 13904  // \yskip\hang| z3| 169 |a[3]|. Same as |z1|, but |a| is three bytes long,
 13905  // |$-2^[23]$<=a<$2^[23]$|.
 13906  //
 13907  // \yskip\hang| z4| 170 |a[4]|. Same as |z1|, but |a| is four bytes long,
 13908  // |$-2^[31]$<=a<$2^[31]$|.
 13909  //
 13910  // \yskip\hang|fnt_num_0| 171. Set |f:=0|. Font 0 must previously have been
 13911  // defined by a \\[fnt\_def] instruction, as explained below.
 13912  //
 13913  // \yskip\hang\\[fnt\_num\_1] through \\[fnt\_num\_63] (opcodes 172 to 234). Set
 13914  // |f:=1|, \dots, \hbox[|f:=63|], respectively.
 13915  //
 13916  // \yskip\hang|fnt1| 235 |k[1]|. Set |f:=k|. \TeX82 uses this command for font
 13917  // numbers in the range |64<=k<256|.
 13918  //
 13919  // \yskip\hang| fnt2| 236 |k[2]|. Same as |fnt1|, except that |k|~is two
 13920  // bytes long, so it is in the range |0<=k<65536|. \TeX82 never generates this
 13921  // command, but large font numbers may prove useful for specifications of
 13922  // color or texture, or they may be used for special fonts that have fixed
 13923  // numbers in some external coding scheme.
 13924  //
 13925  // \yskip\hang| fnt3| 237 |k[3]|. Same as |fnt1|, except that |k|~is three
 13926  // bytes long, so it can be as large as $2^[24]-1$.
 13927  //
 13928  // \yskip\hang| fnt4| 238 |k[4]|. Same as |fnt1|, except that |k|~is four
 13929  // bytes long; this is for the really big font numbers (and for the negative ones).
 13930  //
 13931  // \yskip\hang|xxx1| 239 |k[1]| |x[k]|. This command is undefined in
 13932  // general; it functions as a $(k+2)$-byte |nop| unless special \.[DVI]-reading
 13933  // programs are being used. \TeX82 generates |xxx1| when a short enough
 13934  // \.[\\special] appears, setting |k| to the number of bytes being sent. It
 13935  // is recommended that |x| be a string having the form of a keyword followed
 13936  // by possible parameters relevant to that keyword.
 13937  //
 13938  // \yskip\hang| xxx2| 240 |k[2]| |x[k]|. Like |xxx1|, but |0<=k<65536|.
 13939  //
 13940  // \yskip\hang| xxx3| 241 |k[3]| |x[k]|. Like |xxx1|, but |0<=k<$2^[24]$|.
 13941  //
 13942  // \yskip\hang|xxx4| 242 |k[4]| |x[k]|. Like |xxx1|, but |k| can be ridiculously
 13943  // large. \TeX82 uses |xxx4| when sending a string of length 256 or more.
 13944  //
 13945  // \yskip\hang|fnt_def1| 243 |k[1]| |c[4]| |s[4]| |d[4]| |a[1]| |l[1]| |n[a+l]|.
 13946  // Define font |k|, where |0<=k<256|; font definitions will be explained shortly.
 13947  //
 13948  // \yskip\hang| fnt_def2| 244 |k[2]| |c[4]| |s[4]| |d[4]| |a[1]| |l[1]| |n[a+l]|.
 13949  // Define font |k|, where |0<=k<65536|.
 13950  //
 13951  // \yskip\hang| fnt_def3| 245 |k[3]| |c[4]| |s[4]| |d[4]| |a[1]| |l[1]| |n[a+l]|.
 13952  // Define font |k|, where |0<=k<$2^[24]$|.
 13953  //
 13954  // \yskip\hang| fnt_def4| 246 |k[4]| |c[4]| |s[4]| |d[4]| |a[1]| |l[1]| |n[a+l]|.
 13955  // Define font |k|, where |$-2^[31]$<=k<$2^[31]$|.
 13956  //
 13957  // \yskip\hang|pre| 247 |i[1]| |num[4]| |den[4]| |mag[4]| |k[1]| |x[k]|.
 13958  // Beginning of the preamble; this must come at the very beginning of the
 13959  // file. Parameters |i|, |num|, |den|, |mag|, |k|, and |x| are explained below.
 13960  //
 13961  // \yskip\hang|post| 248. Beginning of the postamble, see below.
 13962  //
 13963  // \yskip\hang|post_post| 249. Ending of the postamble, see below.
 13964  //
 13965  // \yskip\noindent Commands 250--255 are undefined at the present time.
 13966  
 13967  // 586.
 13968  
 13969  // 587.
 13970  
 13971  // tangle:pos tex.web:11667:1:
 13972  
 13973  // The preamble contains basic information about the file as a whole. As
 13974  // stated above, there are six parameters:
 13975  // $$\hbox[| i[1]| | num[4]| | den[4]| | mag[4]| | k[1]| | x[k]|.]$$
 13976  // The |i| byte identifies \.[DVI] format; currently this byte is always set
 13977  // to~2. (The value |i=3| is currently used for an extended format that
 13978  // allows a mixture of right-to-left and left-to-right typesetting.
 13979  // Some day we will set |i=4|, when \.[DVI] format makes another
 13980  // incompatible change---perhaps in the year 2048.)
 13981  //
 13982  // The next two parameters, |num| and |den|, are positive integers that define
 13983  // the units of measurement; they are the numerator and denominator of a
 13984  // fraction by which all dimensions in the \.[DVI] file could be multiplied
 13985  // in order to get lengths in units of $10^[-7]$ meters. Since $\rm 7227[pt] =
 13986  // 254[cm]$, and since \TeX\ works with scaled points where there are $2^[16]$
 13987  // sp in a point, \TeX\ sets
 13988  // $|num|/|den|=(254\cdot10^5)/(7227\cdot2^[16])=25400000/473628672$.
 13989  // \xref[sp]
 13990  //
 13991  // The |mag| parameter is what \TeX\ calls \.[\\mag], i.e., 1000 times the
 13992  // desired magnification. The actual fraction by which dimensions are
 13993  // multiplied is therefore $|mag|\cdot|num|/1000|den|$. Note that if a \TeX\
 13994  // source document does not call for any `\.[true]' dimensions, and if you
 13995  // change it only by specifying a different \.[\\mag] setting, the \.[DVI]
 13996  // file that \TeX\ creates will be completely unchanged except for the value
 13997  // of |mag| in the preamble and postamble. (Fancy \.[DVI]-reading programs allow
 13998  // users to override the |mag|~setting when a \.[DVI] file is being printed.)
 13999  //
 14000  // Finally, |k| and |x| allow the \.[DVI] writer to include a comment, which is not
 14001  // interpreted further. The length of comment |x| is |k|, where |0<=k<256|.
 14002  
 14003  // 588.
 14004  
 14005  // tangle:pos tex.web:11699:1:
 14006  
 14007  // Font definitions for a given font number |k| contain further parameters
 14008  // $$\hbox[|c[4]| |s[4]| |d[4]| |a[1]| |l[1]| |n[a+l]|.]$$
 14009  // The four-byte value |c| is the check sum that \TeX\ found in the \.[TFM]
 14010  // file for this font; |c| should match the check sum of the font found by
 14011  // programs that read this \.[DVI] file.
 14012  // \xref[check sum]
 14013  //
 14014  // Parameter |s| contains a fixed-point scale factor that is applied to
 14015  // the character widths in font |k|; font dimensions in \.[TFM] files and
 14016  // other font files are relative to this quantity, which is called the
 14017  // ``at size'' elsewhere in this documentation. The value of |s| is
 14018  // always positive and less than $2^[27]$. It is given in the same units
 14019  // as the other \.[DVI] dimensions, i.e., in sp when \TeX82 has made the
 14020  // file.  Parameter |d| is similar to |s|; it is the ``design size,'' and
 14021  // (like~|s|) it is given in \.[DVI] units. Thus, font |k| is to be used
 14022  // at $|mag|\cdot s/1000d$ times its normal size.
 14023  //
 14024  // The remaining part of a font definition gives the external name of the font,
 14025  // which is an ASCII string of length |a+l|. The number |a| is the length
 14026  // of the ``area'' or directory, and |l| is the length of the font name itself;
 14027  // the standard local system font area is supposed to be used when |a=0|.
 14028  // The |n| field contains the area in its first |a| bytes.
 14029  //
 14030  // Font definitions must appear before the first use of a particular font number.
 14031  // Once font |k| is defined, it must not be defined again; however, we
 14032  // shall see below that font definitions appear in the postamble as well as
 14033  // in the pages, so in this sense each font number is defined exactly twice,
 14034  // if at all. Like |nop| commands, font definitions can
 14035  // appear before the first |bop|, or between an |eop| and a |bop|.
 14036  
 14037  // 589.
 14038  
 14039  // tangle:pos tex.web:11729:1:
 14040  
 14041  // Sometimes it is desirable to make horizontal or vertical rules line up
 14042  // precisely with certain features in characters of a font. It is possible to
 14043  // guarantee the correct matching between \.[DVI] output and the characters
 14044  // generated by \MF\ by adhering to the following principles: (1)~The \MF\
 14045  // characters should be positioned so that a bottom edge or left edge that is
 14046  // supposed to line up with the bottom or left edge of a rule appears at the
 14047  // reference point, i.e., in row~0 and column~0 of the \MF\ raster. This
 14048  // ensures that the position of the rule will not be rounded differently when
 14049  // the pixel size is not a perfect multiple of the units of measurement in
 14050  // the \.[DVI] file. (2)~A typeset rule of height $a>0$ and width $b>0$
 14051  // should be equivalent to a \MF-generated character having black pixels in
 14052  // precisely those raster positions whose \MF\ coordinates satisfy
 14053  // |0<=x<$\alpha$b| and |0<=y<$\alpha$a|, where $\alpha$ is the number
 14054  // of pixels per \.[DVI] unit.
 14055  // \xref[METAFONT][\MF]
 14056  // \xref[alignment of rules with characters]
 14057  // \xref[rules aligning with characters]
 14058  
 14059  // 590.
 14060  
 14061  // tangle:pos tex.web:11747:1:
 14062  
 14063  // The last page in a \.[DVI] file is followed by `|post|'; this command
 14064  // introduces the postamble, which summarizes important facts that \TeX\ has
 14065  // accumulated about the file, making it possible to print subsets of the data
 14066  // with reasonable efficiency. The postamble has the form
 14067  // $$\vbox[\halign[\hbox[#\hfil]\cr
 14068  //   |post| |p[4]| |num[4]| |den[4]| |mag[4]| |l[4]| |u[4]| |s[2]| |t[2]|\cr
 14069  //   $\langle\,$font definitions$\,\rangle$\cr
 14070  //   |post_post| |q[4]| |i[1]| 223's$[[\G]4]$\cr]]$$
 14071  // Here |p| is a pointer to the final |bop| in the file. The next three
 14072  // parameters, |num|, |den|, and |mag|, are duplicates of the quantities that
 14073  // appeared in the preamble.
 14074  //
 14075  // Parameters |l| and |u| give respectively the height-plus-depth of the tallest
 14076  // page and the width of the widest page, in the same units as other dimensions
 14077  // of the file. These numbers might be used by a \.[DVI]-reading program to
 14078  // position individual ``pages'' on large sheets of film or paper; however,
 14079  // the standard convention for output on normal size paper is to position each
 14080  // page so that the upper left-hand corner is exactly one inch from the left
 14081  // and the top. Experience has shown that it is unwise to design \.[DVI]-to-printer
 14082  // software that attempts cleverly to center the output; a fixed position of
 14083  // the upper left corner is easiest for users to understand and to work with.
 14084  // Therefore |l| and~|u| are often ignored.
 14085  //
 14086  // Parameter |s| is the maximum stack depth (i.e., the largest excess of
 14087  // |push| commands over |pop| commands) needed to process this file. Then
 14088  // comes |t|, the total number of pages (|bop| commands) present.
 14089  //
 14090  // The postamble continues with font definitions, which are any number of
 14091  // \\[fnt\_def] commands as described above, possibly interspersed with |nop|
 14092  // commands. Each font number that is used in the \.[DVI] file must be defined
 14093  // exactly twice: Once before it is first selected by a \\[fnt] command, and once
 14094  // in the postamble.
 14095  
 14096  // 591.
 14097  
 14098  // tangle:pos tex.web:11780:1:
 14099  
 14100  // The last part of the postamble, following the |post_post| byte that
 14101  // signifies the end of the font definitions, contains |q|, a pointer to the
 14102  // |post| command that started the postamble.  An identification byte, |i|,
 14103  // comes next; this currently equals~2, as in the preamble.
 14104  //
 14105  // The |i| byte is followed by four or more bytes that are all equal to
 14106  // the decimal number 223 (i.e., @'337 in octal). \TeX\ puts out four to seven of
 14107  // these trailing bytes, until the total length of the file is a multiple of
 14108  // four bytes, since this works out best on machines that pack four bytes per
 14109  // word; but any number of 223's is allowed, as long as there are at least four
 14110  // of them. In effect, 223 is a sort of signature that is added at the very end.
 14111  // \xref[Fuchs, David Raymond]
 14112  //
 14113  // This curious way to finish off a \.[DVI] file makes it feasible for
 14114  // \.[DVI]-reading programs to find the postamble first, on most computers,
 14115  // even though \TeX\ wants to write the postamble last. Most operating
 14116  // systems permit random access to individual words or bytes of a file, so
 14117  // the \.[DVI] reader can start at the end and skip backwards over the 223's
 14118  // until finding the identification byte. Then it can back up four bytes, read
 14119  // |q|, and move to byte |q| of the file. This byte should, of course,
 14120  // contain the value 248 (|post|); now the postamble can be read, so the
 14121  // \.[DVI] reader can discover all the information needed for typesetting the
 14122  // pages. Note that it is also possible to skip through the \.[DVI] file at
 14123  // reasonably high speed to locate a particular page, if that proves
 14124  // desirable. This saves a lot of time, since \.[DVI] files used in production
 14125  // jobs tend to be large.
 14126  //
 14127  // Unfortunately, however, standard \PASCAL\ does not include the ability to
 14128  // \xref[system dependencies]
 14129  // access a random position in a file, or even to determine the length of a file.
 14130  // Almost all systems nowadays provide the necessary capabilities, so \.[DVI]
 14131  // format has been designed to work most efficiently with modern operating systems.
 14132  // But if \.[DVI] files have to be processed under the restrictions of standard
 14133  // \PASCAL, one can simply read them from front to back, since the necessary
 14134  // header information is present in the preamble and in the font definitions.
 14135  // (The |l| and |u| and |s| and |t| parameters, which appear only in the
 14136  // postamble, are ``frills'' that are handy but not absolutely necessary.)
 14137  
 14138  // 597.
 14139  
 14140  // tangle:pos tex.web:11911:1:
 14141  
 14142  // The actual output of |dvi_buf[a..b]| to |dvi_file| is performed by calling
 14143  // |write_dvi(a,b)|. For best results, this procedure should be optimized to
 14144  // run as fast as possible on each particular system, since it is part of
 14145  // \TeX's inner loop. It is safe to assume that |a| and |b+1| will both be
 14146  // multiples of 4 when |write_dvi(a,b)| is called; therefore it is possible on
 14147  // many machines to use efficient methods to pack four bytes per word and to
 14148  // output an array of words with one system call.
 14149  // \xref[system dependencies]
 14150  // \xref[inner loop]
 14151  // \xref[defecation]
 14152  func (prg *prg) writeDvi(a, b dviIndex) {
 14153  	var (
 14154  		k dviIndex
 14155  	)
 14156  	for ii := int32(a); ii <= int32(b); ii++ {
 14157  		k = dviIndex(ii)
 14158  		_ = k
 14159  		prg.dviFile.Write(prg.dviBuf[k])
 14160  	}
 14161  }
 14162  
 14163  // 598.
 14164  
 14165  // tangle:pos tex.web:11927:1:
 14166  
 14167  // To put a byte in the buffer without paying the cost of invoking a procedure
 14168  // each time, we use the macro |dvi_out|.
 14169  func (prg *prg) dviSwap() {
 14170  	if int32(prg.dviLimit) == dviBufSize {
 14171  		prg.writeDvi(dviIndex(0), dviIndex(int32(prg.halfBuf)-1))
 14172  		prg.dviLimit = prg.halfBuf
 14173  		prg.dviOffset = prg.dviOffset + dviBufSize
 14174  		prg.dviPtr = 0
 14175  	} else {
 14176  		prg.writeDvi(prg.halfBuf, dviIndex(dviBufSize-1))
 14177  		prg.dviLimit = uint16(dviBufSize)
 14178  	}
 14179  	prg.dviGone = prg.dviGone + int32(prg.halfBuf)
 14180  }
 14181  
 14182  // 600.
 14183  
 14184  // tangle:pos tex.web:11951:1:
 14185  
 14186  // The |dvi_four| procedure outputs four bytes in two's complement notation,
 14187  // without risking arithmetic overflow.
 14188  func (prg *prg) dviFour(x int32) {
 14189  	if x >= 0 {
 14190  		prg.dviBuf[prg.dviPtr] = byte(x / 0100000000)
 14191  		prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14192  		if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14193  			prg.dviSwap()
 14194  		}
 14195  	} else {
 14196  		x = x + 010000000000
 14197  		x = x + 010000000000
 14198  		{
 14199  			prg.dviBuf[prg.dviPtr] = byte(x/0100000000 + 128)
 14200  			prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14201  			if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14202  				prg.dviSwap()
 14203  			}
 14204  		}
 14205  	}
 14206  	x = x % 0100000000
 14207  	{
 14208  		prg.dviBuf[prg.dviPtr] = byte(x / 0200000)
 14209  		prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14210  		if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14211  			prg.dviSwap()
 14212  		}
 14213  	}
 14214  	x = x % 0200000
 14215  	{
 14216  		prg.dviBuf[prg.dviPtr] = byte(x / 0400)
 14217  		prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14218  		if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14219  			prg.dviSwap()
 14220  		}
 14221  	}
 14222  	{
 14223  		prg.dviBuf[prg.dviPtr] = byte(x % 0400)
 14224  		prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14225  		if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14226  			prg.dviSwap()
 14227  		}
 14228  	}
 14229  }
 14230  
 14231  // 601.
 14232  
 14233  // tangle:pos tex.web:11965:1:
 14234  
 14235  // A mild optimization of the output is performed by the |dvi_pop|
 14236  // routine, which issues a |pop| unless it is possible to cancel a
 14237  // `|push| |pop|' pair. The parameter to |dvi_pop| is the byte address
 14238  // following the old |push| that matches the new |pop|.
 14239  func (prg *prg) dviPop(l int32) {
 14240  	if l == prg.dviOffset+int32(prg.dviPtr) && int32(prg.dviPtr) > 0 {
 14241  		prg.dviPtr = uint16(int32(prg.dviPtr) - 1)
 14242  	} else {
 14243  		prg.dviBuf[prg.dviPtr] = byte(pop)
 14244  		prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14245  		if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14246  			prg.dviSwap()
 14247  		}
 14248  	}
 14249  }
 14250  
 14251  // 602.
 14252  
 14253  // tangle:pos tex.web:11975:1:
 14254  
 14255  // Here's a procedure that outputs a font definition. Since \TeX82 uses at
 14256  // most 256 different fonts per job, |fnt_def1| is always used as the command code.
 14257  func (prg *prg) dviFontDef(f internalFontNumber) {
 14258  	var (
 14259  		k poolPointer // index into |str_pool|
 14260  	)
 14261  	{
 14262  		prg.dviBuf[prg.dviPtr] = byte(fntDef1)
 14263  		prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14264  		if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14265  			prg.dviSwap()
 14266  		}
 14267  	}
 14268  	{
 14269  		prg.dviBuf[prg.dviPtr] = byte(int32(f) - fontBase - 1)
 14270  		prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14271  		if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14272  			prg.dviSwap()
 14273  		}
 14274  	}
 14275  
 14276  	{
 14277  		prg.dviBuf[prg.dviPtr] = byte(int32(prg.fontCheck[f].b0) - minQuarterword)
 14278  		prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14279  		if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14280  			prg.dviSwap()
 14281  		}
 14282  	}
 14283  	{
 14284  		prg.dviBuf[prg.dviPtr] = byte(int32(prg.fontCheck[f].b1) - minQuarterword)
 14285  		prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14286  		if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14287  			prg.dviSwap()
 14288  		}
 14289  	}
 14290  	{
 14291  		prg.dviBuf[prg.dviPtr] = byte(int32(prg.fontCheck[f].b2) - minQuarterword)
 14292  		prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14293  		if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14294  			prg.dviSwap()
 14295  		}
 14296  	}
 14297  	{
 14298  		prg.dviBuf[prg.dviPtr] = byte(int32(prg.fontCheck[f].b3) - minQuarterword)
 14299  		prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14300  		if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14301  			prg.dviSwap()
 14302  		}
 14303  	}
 14304  
 14305  	prg.dviFour(prg.fontSize[f])
 14306  	prg.dviFour(prg.fontDsize[f])
 14307  
 14308  	{
 14309  		prg.dviBuf[prg.dviPtr] = byte(int32(prg.strStart[int32(prg.fontArea[f])+1]) - int32(prg.strStart[prg.fontArea[f]]))
 14310  		prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14311  		if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14312  			prg.dviSwap()
 14313  		}
 14314  	}
 14315  	{
 14316  		prg.dviBuf[prg.dviPtr] = byte(int32(prg.strStart[int32(prg.fontName[f])+1]) - int32(prg.strStart[prg.fontName[f]]))
 14317  		prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14318  		if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14319  			prg.dviSwap()
 14320  		}
 14321  	}
 14322  
 14323  	// Output the font name whose internal number is |f|
 14324  	for ii := int32(prg.strStart[prg.fontArea[f]]); ii <= int32(prg.strStart[int32(prg.fontArea[f])+1])-1; ii++ {
 14325  		k = poolPointer(ii)
 14326  		_ = k
 14327  		prg.dviBuf[prg.dviPtr] = prg.strPool[k]
 14328  		prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14329  		if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14330  			prg.dviSwap()
 14331  		}
 14332  	}
 14333  	for ii := int32(prg.strStart[prg.fontName[f]]); ii <= int32(prg.strStart[int32(prg.fontName[f])+1])-1; ii++ {
 14334  		k = poolPointer(ii)
 14335  		_ = k
 14336  		prg.dviBuf[prg.dviPtr] = prg.strPool[k]
 14337  		prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14338  		if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14339  			prg.dviSwap()
 14340  		}
 14341  	}
 14342  }
 14343  
 14344  // 604.
 14345  
 14346  // tangle:pos tex.web:11999:1:
 14347  
 14348  // Versions of \TeX\ intended for small computers might well choose to omit
 14349  // the ideas in the next few parts of this program, since it is not really
 14350  // necessary to optimize the \.[DVI] code by making use of the |w0|, |x0|,
 14351  // |y0|, and |z0| commands. Furthermore, the algorithm that we are about to
 14352  // describe does not pretend to give an optimum reduction in the length
 14353  // of the \.[DVI] code; after all, speed is more important than compactness.
 14354  // But the method is surprisingly effective, and it takes comparatively little
 14355  // time.
 14356  //
 14357  // We can best understand the basic idea by first considering a simpler problem
 14358  // that has the same essential characteristics. Given a sequence of digits,
 14359  // say $3\,1\,4\,1\,5\,9\,2\,6\,5\,3\,5\,8\,9$, we want to assign subscripts
 14360  // $d$, $y$, or $z$ to each digit so as to maximize the number of ``$y$-hits''
 14361  // and ``$z$-hits''; a $y$-hit is an instance of two appearances of the same
 14362  // digit with the subscript $y$, where no $y$'s intervene between the two
 14363  // appearances, and a $z$-hit is defined similarly. For example, the sequence
 14364  // above could be decorated with subscripts as follows:
 14365  // $$3_z\,1_y\,4_d\,1_y\,5_y\,9_d\,2_d\,6_d\,5_y\,3_z\,5_y\,8_d\,9_d.$$
 14366  // There are three $y$-hits ($1_y\ldots1_y$ and $5_y\ldots5_y\ldots5_y$) and
 14367  // one $z$-hit ($3_z\ldots3_z$); there are no $d$-hits, since the two appearances
 14368  // of $9_d$ have $d$'s between them, but we don't count $d$-hits so it doesn't
 14369  // matter how many there are. These subscripts are analogous to the \.[DVI]
 14370  // commands called \\[down], $y$, and $z$, and the digits are analogous to
 14371  // different amounts of vertical motion; a $y$-hit or $z$-hit corresponds to
 14372  // the opportunity to use the one-byte commands |y0| or |z0| in a \.[DVI] file.
 14373  //
 14374  // \TeX's method of assigning subscripts works like this: Append a new digit,
 14375  // say $\delta$, to the right of the sequence. Now look back through the
 14376  // sequence until one of the following things happens: (a)~You see
 14377  // $\delta_y$ or $\delta_z$, and this was the first time you encountered a
 14378  // $y$ or $z$ subscript, respectively.  Then assign $y$ or $z$ to the new
 14379  // $\delta$; you have scored a hit. (b)~You see $\delta_d$, and no $y$
 14380  // subscripts have been encountered so far during this search.  Then change
 14381  // the previous $\delta_d$ to $\delta_y$ (this corresponds to changing a
 14382  // command in the output buffer), and assign $y$ to the new $\delta$; it's
 14383  // another hit.  (c)~You see $\delta_d$, and a $y$ subscript has been seen
 14384  // but not a $z$.  Change the previous $\delta_d$ to $\delta_z$ and assign
 14385  // $z$ to the new $\delta$. (d)~You encounter both $y$ and $z$ subscripts
 14386  // before encountering a suitable $\delta$, or you scan all the way to the
 14387  // front of the sequence. Assign $d$ to the new $\delta$; this assignment may
 14388  // be changed later.
 14389  //
 14390  // The subscripts $3_z\,1_y\,4_d\ldots\,$ in the example above were, in fact,
 14391  // produced by this procedure, as the reader can verify. (Go ahead and try it.)
 14392  
 14393  // 607.
 14394  
 14395  // tangle:pos tex.web:12066:1:
 14396  
 14397  // Here is a subroutine that produces a \.[DVI] command for some specified
 14398  // downward or rightward motion. It has two parameters: |w| is the amount
 14399  // of motion, and |o| is either |down1| or |right1|. We use the fact that
 14400  // the command codes have convenient arithmetic properties: |y1-down1=w1-right1|
 14401  // and |z1-down1=x1-right1|.
 14402  func (prg *prg) movement(w scaled, o eightBits) {
 14403  	var (
 14404  		mstate smallNumber // have we seen a |y| or |z|?
 14405  		p, q   halfword    // current and top nodes on the stack
 14406  		k      int32       // index into |dvi_buf|, modulo |dvi_buf_size|
 14407  	)
 14408  	q = prg.getNode(movementNodeSize) // new node for the top of the stack
 14409  	*prg.mem[int32(q)+widthOffset].int() = w
 14410  	*prg.mem[int32(q)+2].int() = prg.dviOffset + int32(prg.dviPtr)
 14411  	if int32(o) == down1 {
 14412  		*(*prg.mem[q].hh()).rh() = prg.downPtr
 14413  		prg.downPtr = q
 14414  	} else {
 14415  		*(*prg.mem[q].hh()).rh() = prg.rightPtr
 14416  		prg.rightPtr = q
 14417  	}
 14418  
 14419  	// Look at the other stack entries until deciding what sort of \.[DVI] command to generate; |goto found| if node |p| is a “hit”
 14420  	p = *(*prg.mem[q].hh()).rh()
 14421  	mstate = byte(noneSeen)
 14422  	for int32(p) != 0 {
 14423  		if *prg.mem[int32(p)+widthOffset].int() == w {
 14424  			switch int32(mstate) + int32(*(*prg.mem[p].hh()).lh()) {
 14425  			case noneSeen + 3, noneSeen + 4, zSeen + 3, zSeen + 4: //
 14426  
 14427  				if *prg.mem[int32(p)+2].int() < prg.dviGone {
 14428  					goto notFound
 14429  				} else {
 14430  					// Change buffered instruction to |y| or |w| and |goto found|
 14431  					k = *prg.mem[int32(p)+2].int() - prg.dviOffset
 14432  					if k < 0 {
 14433  						k = k + dviBufSize
 14434  					}
 14435  					prg.dviBuf[k] = byte(int32(prg.dviBuf[k]) + y1 - down1)
 14436  					*(*prg.mem[p].hh()).lh() = uint16(yHere)
 14437  					goto found
 14438  				}
 14439  
 14440  			case noneSeen + 5, ySeen + 3, ySeen + 5: //
 14441  
 14442  				if *prg.mem[int32(p)+2].int() < prg.dviGone {
 14443  					goto notFound
 14444  				} else {
 14445  					// Change buffered instruction to |z| or |x| and |goto found|
 14446  					k = *prg.mem[int32(p)+2].int() - prg.dviOffset
 14447  					if k < 0 {
 14448  						k = k + dviBufSize
 14449  					}
 14450  					prg.dviBuf[k] = byte(int32(prg.dviBuf[k]) + z1 - down1)
 14451  					*(*prg.mem[p].hh()).lh() = uint16(zHere)
 14452  					goto found
 14453  				}
 14454  
 14455  			case noneSeen + 1, noneSeen + 2, ySeen + 2, zSeen + 1:
 14456  				goto found
 14457  
 14458  			default:
 14459  			}
 14460  		} else {
 14461  			switch int32(mstate) + int32(*(*prg.mem[p].hh()).lh()) {
 14462  			case noneSeen + 1:
 14463  				mstate = byte(ySeen)
 14464  			case noneSeen + 2:
 14465  				mstate = byte(zSeen)
 14466  			case ySeen + 2, zSeen + 1:
 14467  				goto notFound
 14468  
 14469  			default:
 14470  			}
 14471  		}
 14472  		p = *(*prg.mem[p].hh()).rh()
 14473  	}
 14474  
 14475  notFound:
 14476  	;
 14477  
 14478  	// Generate a |down| or |right| command for |w| and |return|
 14479  	*(*prg.mem[q].hh()).lh() = uint16(yzOk)
 14480  	if abs(w) >= 040000000 {
 14481  		{
 14482  			prg.dviBuf[prg.dviPtr] = byte(int32(o) + 3)
 14483  			prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14484  			if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14485  				prg.dviSwap()
 14486  			}
 14487  		} // |down4| or |right4|
 14488  		prg.dviFour(w)
 14489  		goto exit
 14490  	}
 14491  	if abs(w) >= 0100000 {
 14492  		{
 14493  			prg.dviBuf[prg.dviPtr] = byte(int32(o) + 2)
 14494  			prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14495  			if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14496  				prg.dviSwap()
 14497  			}
 14498  		} // |down3| or |right3|
 14499  		if w < 0 {
 14500  			w = w + 0100000000
 14501  		}
 14502  		{
 14503  			prg.dviBuf[prg.dviPtr] = byte(w / 0200000)
 14504  			prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14505  			if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14506  				prg.dviSwap()
 14507  			}
 14508  		}
 14509  		w = w % 0200000
 14510  		goto _2
 14511  	}
 14512  	if abs(w) >= 0200 {
 14513  		{
 14514  			prg.dviBuf[prg.dviPtr] = byte(int32(o) + 1)
 14515  			prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14516  			if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14517  				prg.dviSwap()
 14518  			}
 14519  		} // |down2| or |right2|
 14520  		if w < 0 {
 14521  			w = w + 0200000
 14522  		}
 14523  
 14524  		goto _2
 14525  	}
 14526  	{
 14527  		prg.dviBuf[prg.dviPtr] = o
 14528  		prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14529  		if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14530  			prg.dviSwap()
 14531  		}
 14532  	} // |down1| or |right1|
 14533  	if w < 0 {
 14534  		w = w + 0400
 14535  	}
 14536  
 14537  	goto _1
 14538  _2:
 14539  	{
 14540  		prg.dviBuf[prg.dviPtr] = byte(w / 0400)
 14541  		prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14542  		if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14543  			prg.dviSwap()
 14544  		}
 14545  	}
 14546  _1:
 14547  	{
 14548  		prg.dviBuf[prg.dviPtr] = byte(w % 0400)
 14549  		prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14550  		if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14551  			prg.dviSwap()
 14552  		}
 14553  	}
 14554  	goto exit
 14555  
 14556  found:
 14557  	*(*prg.mem[q].hh()).lh() = *(*prg.mem[p].hh()).lh()
 14558  	if int32(*(*prg.mem[q].hh()).lh()) == yHere {
 14559  		{
 14560  			prg.dviBuf[prg.dviPtr] = byte(int32(o) + y0 - down1)
 14561  			prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14562  			if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14563  				prg.dviSwap()
 14564  			}
 14565  		} // |y0| or |w0|
 14566  		for int32(*(*prg.mem[q].hh()).rh()) != int32(p) {
 14567  			q = *(*prg.mem[q].hh()).rh()
 14568  			switch *(*prg.mem[q].hh()).lh() {
 14569  			case yzOk:
 14570  				*(*prg.mem[q].hh()).lh() = uint16(zOk)
 14571  			case yOk:
 14572  				*(*prg.mem[q].hh()).lh() = uint16(dFixed)
 14573  
 14574  			default:
 14575  			}
 14576  		}
 14577  	} else {
 14578  		{
 14579  			prg.dviBuf[prg.dviPtr] = byte(int32(o) + z0 - down1)
 14580  			prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14581  			if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14582  				prg.dviSwap()
 14583  			}
 14584  		} // |z0| or |x0|
 14585  		for int32(*(*prg.mem[q].hh()).rh()) != int32(p) {
 14586  			q = *(*prg.mem[q].hh()).rh()
 14587  			switch *(*prg.mem[q].hh()).lh() {
 14588  			case yzOk:
 14589  				*(*prg.mem[q].hh()).lh() = uint16(yOk)
 14590  			case zOk:
 14591  				*(*prg.mem[q].hh()).lh() = uint16(dFixed)
 14592  
 14593  			default:
 14594  			}
 14595  		}
 14596  	}
 14597  
 14598  exit:
 14599  }
 14600  
 14601  // 608.
 14602  
 14603  // tangle:pos tex.web:12091:1:
 14604  
 14605  // The |info| fields in the entries of the down stack or the right stack
 14606  // have six possible settings: |y_here| or |z_here| mean that the \.[DVI]
 14607  // command refers to |y| or |z|, respectively (or to |w| or |x|, in the
 14608  // case of horizontal motion); |yz_OK| means that the \.[DVI] command is
 14609  // \\[down] (or \\[right]) but can be changed to either |y| or |z| (or
 14610  // to either |w| or |x|); |y_OK| means that it is \\[down] and can be changed
 14611  // to |y| but not |z|; |z_OK| is similar; and |d_fixed| means it must stay
 14612  // \\[down].
 14613  //
 14614  // The four settings |yz_OK|, |y_OK|, |z_OK|, |d_fixed| would not need to
 14615  // be distinguished from each other if we were simply solving the
 14616  // digit-subscripting problem mentioned above. But in \TeX's case there is
 14617  // a complication because of the nested structure of |push| and |pop|
 14618  // commands. Suppose we add parentheses to the digit-subscripting problem,
 14619  // redefining hits so that $\delta_y\ldots \delta_y$ is a hit if all $y$'s between
 14620  // the $\delta$'s are enclosed in properly nested parentheses, and if the
 14621  // parenthesis level of the right-hand $\delta_y$ is deeper than or equal to
 14622  // that of the left-hand one. Thus, `(' and `)' correspond to `|push|'
 14623  // and `|pop|'. Now if we want to assign a subscript to the final 1 in the
 14624  // sequence
 14625  // $$2_y\,7_d\,1_d\,(\,8_z\,2_y\,8_z\,)\,1$$
 14626  // we cannot change the previous $1_d$ to $1_y$, since that would invalidate
 14627  // the $2_y\ldots2_y$ hit. But we can change it to $1_z$, scoring a hit
 14628  // since the intervening $8_z$'s are enclosed in parentheses.
 14629  //
 14630  // The program below removes movement nodes that are introduced after a |push|,
 14631  // before it outputs the corresponding |pop|.
 14632  
 14633  // 615.
 14634  
 14635  // tangle:pos tex.web:12233:1:
 14636  
 14637  // In case you are wondering when all the movement nodes are removed from
 14638  // \TeX's memory, the answer is that they are recycled just before
 14639  // |hlist_out| and |vlist_out| finish outputting a box. This restores the
 14640  // down and right stacks to the state they were in before the box was output,
 14641  // except that some |info|'s may have become more restrictive.
 14642  func (prg *prg) pruneMovements(l int32) {
 14643  	var (
 14644  		p halfword // node being deleted
 14645  	)
 14646  	for int32(prg.downPtr) != 0 {
 14647  		if *prg.mem[int32(prg.downPtr)+2].int() < l {
 14648  			goto done
 14649  		}
 14650  		p = prg.downPtr
 14651  		prg.downPtr = *(*prg.mem[p].hh()).rh()
 14652  		prg.freeNode(p, halfword(movementNodeSize))
 14653  	}
 14654  
 14655  done:
 14656  	for int32(prg.rightPtr) != 0 {
 14657  		if *prg.mem[int32(prg.rightPtr)+2].int() < l {
 14658  			goto exit
 14659  		}
 14660  		p = prg.rightPtr
 14661  		prg.rightPtr = *(*prg.mem[p].hh()).rh()
 14662  		prg.freeNode(p, halfword(movementNodeSize))
 14663  	}
 14664  
 14665  exit:
 14666  } // |hlist_out| and |vlist_out| are mutually
 14667  //   recursive
 14668  
 14669  // 619.
 14670  
 14671  // tangle:pos tex.web:12319:1:
 14672  
 14673  // The recursive procedures |hlist_out| and |vlist_out| each have local variables
 14674  // |save_h| and |save_v| to hold the values of |dvi_h| and |dvi_v| just before
 14675  // entering a new level of recursion.  In effect, the values of |save_h| and
 14676  // |save_v| on \TeX's run-time stack correspond to the values of |h| and |v|
 14677  // that a \.[DVI]-reading program will push onto its coordinate stack.
 14678  // \4
 14679  // Declare procedures needed in |hlist_out|, |vlist_out|
 14680  func (prg *prg) specialOut(p halfword) {
 14681  	var (
 14682  		oldSetting/* 0..maxSelector */ byte             // holds print |selector|
 14683  		k                                   poolPointer // index into |str_pool|
 14684  	)
 14685  	if prg.curH != prg.dviH {
 14686  		prg.movement(prg.curH-prg.dviH, eightBits(right1))
 14687  		prg.dviH = prg.curH
 14688  	}
 14689  	if prg.curV != prg.dviV {
 14690  		prg.movement(prg.curV-prg.dviV, eightBits(down1))
 14691  		prg.dviV = prg.curV
 14692  	}
 14693  
 14694  	oldSetting = prg.selector
 14695  	prg.selector = byte(newString)
 14696  	prg.showTokenList(int32(*(*prg.mem[*(*prg.mem[int32(p)+1].hh()).rh()].hh()).rh()), 0, poolSize-int32(prg.poolPtr))
 14697  	prg.selector = oldSetting
 14698  	{
 14699  		if int32(prg.poolPtr)+1 > poolSize {
 14700  			prg.overflow(strNumber( /* "pool size" */ 257), poolSize-int32(prg.initPoolPtr))
 14701  		} /* \xref[TeX capacity exceeded pool size][\quad pool size]  */
 14702  	}
 14703  	if int32(prg.poolPtr)-int32(prg.strStart[prg.strPtr]) < 256 {
 14704  		{
 14705  			prg.dviBuf[prg.dviPtr] = byte(xxx1)
 14706  			prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14707  			if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14708  				prg.dviSwap()
 14709  			}
 14710  		}
 14711  		{
 14712  			prg.dviBuf[prg.dviPtr] = byte(int32(prg.poolPtr) - int32(prg.strStart[prg.strPtr]))
 14713  			prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14714  			if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14715  				prg.dviSwap()
 14716  			}
 14717  		}
 14718  	} else {
 14719  		{
 14720  			prg.dviBuf[prg.dviPtr] = byte(xxx4)
 14721  			prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14722  			if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14723  				prg.dviSwap()
 14724  			}
 14725  		}
 14726  		prg.dviFour(int32(prg.poolPtr) - int32(prg.strStart[prg.strPtr]))
 14727  	}
 14728  	for ii := int32(prg.strStart[prg.strPtr]); ii <= int32(prg.poolPtr)-1; ii++ {
 14729  		k = poolPointer(ii)
 14730  		_ = k
 14731  		prg.dviBuf[prg.dviPtr] = prg.strPool[k]
 14732  		prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14733  		if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14734  			prg.dviSwap()
 14735  		}
 14736  	}
 14737  	prg.poolPtr = prg.strStart[prg.strPtr] // erase the string
 14738  }
 14739  
 14740  func (prg *prg) writeOut(p halfword) {
 14741  	var (
 14742  		oldSetting/* 0..maxSelector */ byte             // holds print |selector|
 14743  		oldMode                             int32       // saved |mode|
 14744  		j                                   smallNumber // write stream number
 14745  		q, r1                               halfword    // temporary variables for list manipulation
 14746  	)
 14747  	q = prg.getAvail()
 14748  	*(*prg.mem[q].hh()).lh() = uint16(rightBraceToken + '}')
 14749  
 14750  	r1 = prg.getAvail()
 14751  	*(*prg.mem[q].hh()).rh() = r1
 14752  	*(*prg.mem[r1].hh()).lh() = uint16(07777 + endWrite)
 14753  	prg.beginTokenList(q, quarterword(inserted))
 14754  
 14755  	prg.beginTokenList(*(*prg.mem[int32(p)+1].hh()).rh(), quarterword(writeText))
 14756  
 14757  	q = prg.getAvail()
 14758  	*(*prg.mem[q].hh()).lh() = uint16(leftBraceToken + '{')
 14759  	prg.beginTokenList(q, quarterword(inserted))
 14760  	// now we're ready to scan
 14761  	//   `\.\[$\langle\,$token list$\,\rangle$\.[\] \\endwrite]'
 14762  
 14763  	oldMode = int32(prg.curList.modeField)
 14764  	prg.curList.modeField = 0
 14765  	// disable \.[\\prevdepth], \.[\\spacefactor], \.[\\lastskip], \.[\\prevgraf]
 14766  	prg.curCs = prg.writeLoc
 14767  	q = prg.scanToks(false, true) // expand macros, etc.
 14768  	prg.getToken()
 14769  	if int32(prg.curTok) != 07777+endWrite {
 14770  		{
 14771  			if int32(prg.interaction) == errorStopMode {
 14772  			}
 14773  			prg.printNl(strNumber( /* "! " */ 262))
 14774  			prg.print( /* "Unbalanced write command" */ 1297)
 14775  		}
 14776  		// \xref[Unbalanced write...]
 14777  		{
 14778  			prg.helpPtr = 2
 14779  			prg.helpLine[1] = /* "On this page there's a \\write with fewer real ['s than ]'s." */ 1298
 14780  			prg.helpLine[0] = /* "I can't handle that very well; good luck." */ 1012
 14781  		}
 14782  		prg.error1()
 14783  		for {
 14784  			prg.getToken()
 14785  			if int32(prg.curTok) == 07777+endWrite {
 14786  				break
 14787  			}
 14788  		}
 14789  	}
 14790  	prg.curList.modeField = int16(oldMode)
 14791  	prg.endTokenList()
 14792  	oldSetting = prg.selector
 14793  	j = byte(*(*prg.mem[int32(p)+1].hh()).lh())
 14794  	if prg.writeOpen[j] {
 14795  		prg.selector = j
 14796  	} else {
 14797  		if int32(j) == 17 && int32(prg.selector) == termAndLog {
 14798  			prg.selector = byte(logOnly)
 14799  		}
 14800  		prg.printNl(strNumber( /* "" */ 338))
 14801  	}
 14802  	prg.tokenShow(prg.defRef)
 14803  	prg.printLn()
 14804  	prg.flushList(prg.defRef)
 14805  	prg.selector = oldSetting
 14806  }
 14807  
 14808  func (prg *prg) outWhat(p halfword) {
 14809  	var (
 14810  		j smallNumber // write stream number
 14811  	)
 14812  	switch *(*prg.mem[p].hh()).b1() {
 14813  	case openNode, writeNode, closeNode:
 14814  		// Do some work that has been queued up for \.[\\write]
 14815  		if !prg.doingLeaders {
 14816  			j = byte(*(*prg.mem[int32(p)+1].hh()).lh())
 14817  			if int32(*(*prg.mem[p].hh()).b1()) == writeNode {
 14818  				prg.writeOut(p)
 14819  			} else {
 14820  				if prg.writeOpen[j] {
 14821  					prg.aClose(prg.writeFile[j])
 14822  				}
 14823  				if int32(*(*prg.mem[p].hh()).b1()) == closeNode {
 14824  					prg.writeOpen[j] = false
 14825  				} else if int32(j) < 16 {
 14826  					prg.curName = *(*prg.mem[int32(p)+1].hh()).rh()
 14827  					prg.curArea = *(*prg.mem[int32(p)+2].hh()).lh()
 14828  					prg.curExt = *(*prg.mem[int32(p)+2].hh()).rh()
 14829  					if int32(prg.curExt) == 338 {
 14830  						prg.curExt = /* ".tex" */ 791
 14831  					}
 14832  					prg.packFileName(prg.curName, prg.curArea, prg.curExt)
 14833  					for !prg.aOpenOut(prg.writeFile[j]) {
 14834  						prg.promptFileName(strNumber( /* "output file name" */ 1300), strNumber( /* ".tex" */ 791))
 14835  					}
 14836  					prg.writeOpen[j] = true
 14837  				}
 14838  			}
 14839  		}
 14840  
 14841  	case specialNode:
 14842  		prg.specialOut(p)
 14843  	case languageNode:
 14844  
 14845  	default:
 14846  		prg.confusion(strNumber( /* "ext4" */ 1299))
 14847  		// \xref[this can't happen ext4][\quad ext4]
 14848  	}
 14849  }
 14850  
 14851  //
 14852  
 14853  func (prg *prg) hlistOut() {
 14854  	var (
 14855  		baseLine                          scaled   // the baseline coordinate for this box
 14856  		leftEdge                          scaled   // the left coordinate for this box
 14857  		saveH, saveV                      scaled   // what |dvi_h| and |dvi_v| should pop to
 14858  		thisBox                           halfword // pointer to containing box
 14859  		gOrder                            glueOrd  // applicable order of infinity for glue
 14860  		gSign/* normal..shrinking */ byte          // selects type of glue
 14861  		p                                 halfword // current position in the hlist
 14862  		saveLoc                           int32    // \.[DVI] byte location upon entry
 14863  		leaderBox                         halfword // the leader box being replicated
 14864  		leaderWd                          scaled   // width of leader box being replicated
 14865  		lx                                scaled   // extra space between leader boxes
 14866  		outerDoingLeaders                 bool     // were we doing leaders?
 14867  		edge                              scaled   // left edge of sub-box, or right edge of leader space
 14868  		glueTemp                          float64  // glue value before rounding
 14869  		curGlue                           float64  // glue seen so far
 14870  		curG                              scaled   // rounded equivalent of |cur_glue| times the glue ratio
 14871  	)
 14872  	curG = 0
 14873  	curGlue = 0.0
 14874  	thisBox = prg.tempPtr
 14875  	gOrder = *(*prg.mem[int32(thisBox)+listOffset].hh()).b1()
 14876  	gSign = *(*prg.mem[int32(thisBox)+listOffset].hh()).b0()
 14877  	p = *(*prg.mem[int32(thisBox)+listOffset].hh()).rh()
 14878  	prg.curS = prg.curS + 1
 14879  	if prg.curS > 0 {
 14880  		prg.dviBuf[prg.dviPtr] = byte(push)
 14881  		prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14882  		if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14883  			prg.dviSwap()
 14884  		}
 14885  	}
 14886  	if prg.curS > prg.maxPush {
 14887  		prg.maxPush = prg.curS
 14888  	}
 14889  	saveLoc = prg.dviOffset + int32(prg.dviPtr)
 14890  	baseLine = prg.curV
 14891  	leftEdge = prg.curH
 14892  	for int32(p) != 0 {
 14893  		// Output node |p| for |hlist_out| and move to the next node, maintaining the condition |cur_v=base_line|
 14894  
 14895  		// Output node |p| for |hlist_out| and move to the next node, maintaining the condition |cur_v=base_line|
 14896  	reswitch:
 14897  		if int32(p) >= int32(prg.hiMemMin) {
 14898  			if prg.curH != prg.dviH {
 14899  				prg.movement(prg.curH-prg.dviH, eightBits(right1))
 14900  				prg.dviH = prg.curH
 14901  			}
 14902  			if prg.curV != prg.dviV {
 14903  				prg.movement(prg.curV-prg.dviV, eightBits(down1))
 14904  				prg.dviV = prg.curV
 14905  			}
 14906  			for {
 14907  				prg.f = *(*prg.mem[p].hh()).b0()
 14908  				prg.c = *(*prg.mem[p].hh()).b1()
 14909  				if int32(prg.f) != int32(prg.dviF) {
 14910  					if !prg.fontUsed[prg.f] {
 14911  						prg.dviFontDef(prg.f)
 14912  						prg.fontUsed[prg.f] = true
 14913  					}
 14914  					if int32(prg.f) <= 64+fontBase {
 14915  						prg.dviBuf[prg.dviPtr] = byte(int32(prg.f) - fontBase - 1 + fntNum0)
 14916  						prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14917  						if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14918  							prg.dviSwap()
 14919  						}
 14920  					} else {
 14921  						{
 14922  							prg.dviBuf[prg.dviPtr] = byte(fnt1)
 14923  							prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14924  							if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14925  								prg.dviSwap()
 14926  							}
 14927  						}
 14928  						{
 14929  							prg.dviBuf[prg.dviPtr] = byte(int32(prg.f) - fontBase - 1)
 14930  							prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14931  							if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14932  								prg.dviSwap()
 14933  							}
 14934  						}
 14935  					}
 14936  					prg.dviF = prg.f
 14937  				}
 14938  				if int32(prg.c) >= 128+minQuarterword {
 14939  					prg.dviBuf[prg.dviPtr] = byte(set1)
 14940  					prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14941  					if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14942  						prg.dviSwap()
 14943  					}
 14944  				}
 14945  				{
 14946  					prg.dviBuf[prg.dviPtr] = byte(int32(prg.c) - minQuarterword)
 14947  					prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 14948  					if int32(prg.dviPtr) == int32(prg.dviLimit) {
 14949  						prg.dviSwap()
 14950  					}
 14951  				}
 14952  
 14953  				prg.curH = prg.curH + *prg.fontInfo[prg.widthBase[prg.f]+int32((*prg.fontInfo[prg.charBase[prg.f]+int32(prg.c)].qqqq()).b0)].int()
 14954  				p = *(*prg.mem[p].hh()).rh()
 14955  				if !(int32(p) >= int32(prg.hiMemMin)) {
 14956  					break
 14957  				}
 14958  			}
 14959  			prg.dviH = prg.curH
 14960  		} else {
 14961  			// Output the non-|char_node| |p| for |hlist_out| and move to the next node
 14962  			switch *(*prg.mem[p].hh()).b0() {
 14963  			case hlistNode, vlistNode:
 14964  				// Output a box in an hlist
 14965  				if int32(*(*prg.mem[int32(p)+listOffset].hh()).rh()) == 0 {
 14966  					prg.curH = prg.curH + *prg.mem[int32(p)+widthOffset].int()
 14967  				} else {
 14968  					saveH = prg.dviH
 14969  					saveV = prg.dviV
 14970  					prg.curV = baseLine + *prg.mem[int32(p)+4].int() // shift the box down
 14971  					prg.tempPtr = p
 14972  					edge = prg.curH
 14973  					if int32(*(*prg.mem[p].hh()).b0()) == vlistNode {
 14974  						prg.vlistOut()
 14975  					} else {
 14976  						prg.hlistOut()
 14977  					}
 14978  					prg.dviH = saveH
 14979  					prg.dviV = saveV
 14980  					prg.curH = edge + *prg.mem[int32(p)+widthOffset].int()
 14981  					prg.curV = baseLine
 14982  				}
 14983  
 14984  			case ruleNode:
 14985  				prg.ruleHt = *prg.mem[int32(p)+heightOffset].int()
 14986  				prg.ruleDp = *prg.mem[int32(p)+depthOffset].int()
 14987  				prg.ruleWd = *prg.mem[int32(p)+widthOffset].int()
 14988  
 14989  				goto finRule
 14990  
 14991  			case whatsitNode:
 14992  				// Output the whatsit node |p| in an hlist
 14993  				prg.outWhat(p)
 14994  
 14995  			case glueNode:
 14996  				// Move right or output leaders
 14997  				prg.g = *(*prg.mem[int32(p)+1].hh()).lh()
 14998  				prg.ruleWd = *prg.mem[int32(prg.g)+widthOffset].int() - curG
 14999  				if int32(gSign) != normal {
 15000  					if int32(gSign) == stretching {
 15001  						if int32(*(*prg.mem[prg.g].hh()).b0()) == int32(gOrder) {
 15002  							curGlue = curGlue + float64(*prg.mem[int32(prg.g)+2].int())
 15003  							glueTemp = float64(*prg.mem[int32(thisBox)+glueOffset].gr()) * curGlue
 15004  							if glueTemp > 1000000000.0 {
 15005  								glueTemp = 1000000000.0
 15006  							} else if glueTemp < -1000000000.0 {
 15007  								glueTemp = -1000000000.0
 15008  							}
 15009  							// \xref[real multiplication]
 15010  							curG = round(glueTemp)
 15011  						}
 15012  					} else if int32(*(*prg.mem[prg.g].hh()).b1()) == int32(gOrder) {
 15013  						curGlue = curGlue - float64(*prg.mem[int32(prg.g)+3].int())
 15014  						glueTemp = float64(*prg.mem[int32(thisBox)+glueOffset].gr()) * curGlue
 15015  						if glueTemp > 1000000000.0 {
 15016  							glueTemp = 1000000000.0
 15017  						} else if glueTemp < -1000000000.0 {
 15018  							glueTemp = -1000000000.0
 15019  						}
 15020  						curG = round(glueTemp)
 15021  					}
 15022  				}
 15023  				prg.ruleWd = prg.ruleWd + curG
 15024  				if int32(*(*prg.mem[p].hh()).b1()) >= aLeaders {
 15025  					leaderBox = *(*prg.mem[int32(p)+1].hh()).rh()
 15026  					if int32(*(*prg.mem[leaderBox].hh()).b0()) == ruleNode {
 15027  						prg.ruleHt = *prg.mem[int32(leaderBox)+heightOffset].int()
 15028  						prg.ruleDp = *prg.mem[int32(leaderBox)+depthOffset].int()
 15029  
 15030  						goto finRule
 15031  					}
 15032  					leaderWd = *prg.mem[int32(leaderBox)+widthOffset].int()
 15033  					if leaderWd > 0 && prg.ruleWd > 0 {
 15034  						prg.ruleWd = prg.ruleWd + 10 // compensate for floating-point rounding
 15035  						edge = prg.curH + prg.ruleWd
 15036  						lx = 0
 15037  
 15038  						// Let |cur_h| be the position of the first box, and set |leader_wd+lx| to the spacing between corresponding parts of boxes
 15039  						if int32(*(*prg.mem[p].hh()).b1()) == aLeaders {
 15040  							saveH = prg.curH
 15041  							prg.curH = leftEdge + leaderWd*((prg.curH-leftEdge)/leaderWd)
 15042  							if prg.curH < saveH {
 15043  								prg.curH = prg.curH + leaderWd
 15044  							}
 15045  						} else {
 15046  							prg.lq = prg.ruleWd / leaderWd // the number of box copies
 15047  							prg.lr = prg.ruleWd % leaderWd // the remaining space
 15048  							if int32(*(*prg.mem[p].hh()).b1()) == cLeaders {
 15049  								prg.curH = prg.curH + prg.lr/2
 15050  							} else {
 15051  								lx = prg.lr / (prg.lq + 1)
 15052  								prg.curH = prg.curH + (prg.lr-(prg.lq-1)*lx)/2
 15053  							}
 15054  						}
 15055  						for prg.curH+leaderWd <= edge {
 15056  
 15057  							// Output a leader box at |cur_h|, then advance |cur_h| by |leader_wd+lx|
 15058  							prg.curV = baseLine + *prg.mem[int32(leaderBox)+4].int()
 15059  							if prg.curV != prg.dviV {
 15060  								prg.movement(prg.curV-prg.dviV, eightBits(down1))
 15061  								prg.dviV = prg.curV
 15062  							}
 15063  							saveV = prg.dviV
 15064  
 15065  							if prg.curH != prg.dviH {
 15066  								prg.movement(prg.curH-prg.dviH, eightBits(right1))
 15067  								prg.dviH = prg.curH
 15068  							}
 15069  							saveH = prg.dviH
 15070  							prg.tempPtr = leaderBox
 15071  							outerDoingLeaders = prg.doingLeaders
 15072  							prg.doingLeaders = true
 15073  							if int32(*(*prg.mem[leaderBox].hh()).b0()) == vlistNode {
 15074  								prg.vlistOut()
 15075  							} else {
 15076  								prg.hlistOut()
 15077  							}
 15078  							prg.doingLeaders = outerDoingLeaders
 15079  							prg.dviV = saveV
 15080  							prg.dviH = saveH
 15081  							prg.curV = baseLine
 15082  							prg.curH = saveH + leaderWd + lx
 15083  						}
 15084  						prg.curH = edge - 10
 15085  						goto nextP
 15086  					}
 15087  				}
 15088  
 15089  				goto movePast
 15090  
 15091  			case kernNode, mathNode:
 15092  				prg.curH = prg.curH + *prg.mem[int32(p)+widthOffset].int()
 15093  			case ligatureNode:
 15094  				// Make node |p| look like a |char_node| and |goto reswitch|
 15095  				prg.mem[30000-12] = prg.mem[int32(p)+1]
 15096  				*(*prg.mem[30000-12].hh()).rh() = *(*prg.mem[p].hh()).rh()
 15097  				p = uint16(30000 - 12)
 15098  				goto reswitch
 15099  
 15100  			default:
 15101  			}
 15102  
 15103  			goto nextP
 15104  
 15105  		finRule:
 15106  			if prg.ruleHt == -010000000000 {
 15107  				prg.ruleHt = *prg.mem[int32(thisBox)+heightOffset].int()
 15108  			}
 15109  			if prg.ruleDp == -010000000000 {
 15110  				prg.ruleDp = *prg.mem[int32(thisBox)+depthOffset].int()
 15111  			}
 15112  			prg.ruleHt = prg.ruleHt + prg.ruleDp // this is the rule thickness
 15113  			if prg.ruleHt > 0 && prg.ruleWd > 0 {
 15114  				if prg.curH != prg.dviH {
 15115  					prg.movement(prg.curH-prg.dviH, eightBits(right1))
 15116  					prg.dviH = prg.curH
 15117  				}
 15118  				prg.curV = baseLine + prg.ruleDp
 15119  				if prg.curV != prg.dviV {
 15120  					prg.movement(prg.curV-prg.dviV, eightBits(down1))
 15121  					prg.dviV = prg.curV
 15122  				}
 15123  				{
 15124  					prg.dviBuf[prg.dviPtr] = byte(setRule)
 15125  					prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 15126  					if int32(prg.dviPtr) == int32(prg.dviLimit) {
 15127  						prg.dviSwap()
 15128  					}
 15129  				}
 15130  				prg.dviFour(prg.ruleHt)
 15131  				prg.dviFour(prg.ruleWd)
 15132  				prg.curV = baseLine
 15133  				prg.dviH = prg.dviH + prg.ruleWd
 15134  			}
 15135  
 15136  		movePast:
 15137  			prg.curH = prg.curH + prg.ruleWd
 15138  
 15139  		nextP:
 15140  			p = *(*prg.mem[p].hh()).rh()
 15141  		}
 15142  	}
 15143  	prg.pruneMovements(saveLoc)
 15144  	if prg.curS > 0 {
 15145  		prg.dviPop(saveLoc)
 15146  	}
 15147  	prg.curS = prg.curS - 1
 15148  }
 15149  
 15150  // 618.
 15151  
 15152  // tangle:pos tex.web:12307:1:
 15153  
 15154  // When |hlist_out| is called, its duty is to output the box represented
 15155  // by the |hlist_node| pointed to by |temp_ptr|. The reference point of that
 15156  // box has coordinates |(cur_h,cur_v)|.
 15157  //
 15158  // Similarly, when |vlist_out| is called, its duty is to output the box represented
 15159  // by the |vlist_node| pointed to by |temp_ptr|. The reference point of that
 15160  // box has coordinates |(cur_h,cur_v)|.
 15161  // \xref[recursion]
 15162  func (prg *prg) vlistOut() {
 15163  	var (
 15164  		leftEdge                          scaled   // the left coordinate for this box
 15165  		topEdge                           scaled   // the top coordinate for this box
 15166  		saveH, saveV                      scaled   // what |dvi_h| and |dvi_v| should pop to
 15167  		thisBox                           halfword // pointer to containing box
 15168  		gOrder                            glueOrd  // applicable order of infinity for glue
 15169  		gSign/* normal..shrinking */ byte          // selects type of glue
 15170  		p                                 halfword // current position in the vlist
 15171  		saveLoc                           int32    // \.[DVI] byte location upon entry
 15172  		leaderBox                         halfword // the leader box being replicated
 15173  		leaderHt                          scaled   // height of leader box being replicated
 15174  		lx                                scaled   // extra space between leader boxes
 15175  		outerDoingLeaders                 bool     // were we doing leaders?
 15176  		edge                              scaled   // bottom boundary of leader space
 15177  		glueTemp                          float64  // glue value before rounding
 15178  		curGlue                           float64  // glue seen so far
 15179  		curG                              scaled   // rounded equivalent of |cur_glue| times the glue ratio
 15180  	)
 15181  	curG = 0
 15182  	curGlue = 0.0
 15183  	thisBox = prg.tempPtr
 15184  	gOrder = *(*prg.mem[int32(thisBox)+listOffset].hh()).b1()
 15185  	gSign = *(*prg.mem[int32(thisBox)+listOffset].hh()).b0()
 15186  	p = *(*prg.mem[int32(thisBox)+listOffset].hh()).rh()
 15187  	prg.curS = prg.curS + 1
 15188  	if prg.curS > 0 {
 15189  		prg.dviBuf[prg.dviPtr] = byte(push)
 15190  		prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 15191  		if int32(prg.dviPtr) == int32(prg.dviLimit) {
 15192  			prg.dviSwap()
 15193  		}
 15194  	}
 15195  	if prg.curS > prg.maxPush {
 15196  		prg.maxPush = prg.curS
 15197  	}
 15198  	saveLoc = prg.dviOffset + int32(prg.dviPtr)
 15199  	leftEdge = prg.curH
 15200  	prg.curV = prg.curV - *prg.mem[int32(thisBox)+heightOffset].int()
 15201  	topEdge = prg.curV
 15202  	for int32(p) != 0 {
 15203  		// Output node |p| for |vlist_out| and move to the next node, maintaining the condition |cur_h=left_edge|
 15204  		if int32(p) >= int32(prg.hiMemMin) {
 15205  			prg.confusion(strNumber( /* "vlistout" */ 828))
 15206  		} else {
 15207  			// Output the non-|char_node| |p| for |vlist_out|
 15208  			switch *(*prg.mem[p].hh()).b0() {
 15209  			case hlistNode, vlistNode:
 15210  				// Output a box in a vlist
 15211  				if int32(*(*prg.mem[int32(p)+listOffset].hh()).rh()) == 0 {
 15212  					prg.curV = prg.curV + *prg.mem[int32(p)+heightOffset].int() + *prg.mem[int32(p)+depthOffset].int()
 15213  				} else {
 15214  					prg.curV = prg.curV + *prg.mem[int32(p)+heightOffset].int()
 15215  					if prg.curV != prg.dviV {
 15216  						prg.movement(prg.curV-prg.dviV, eightBits(down1))
 15217  						prg.dviV = prg.curV
 15218  					}
 15219  					saveH = prg.dviH
 15220  					saveV = prg.dviV
 15221  					prg.curH = leftEdge + *prg.mem[int32(p)+4].int() // shift the box right
 15222  					prg.tempPtr = p
 15223  					if int32(*(*prg.mem[p].hh()).b0()) == vlistNode {
 15224  						prg.vlistOut()
 15225  					} else {
 15226  						prg.hlistOut()
 15227  					}
 15228  					prg.dviH = saveH
 15229  					prg.dviV = saveV
 15230  					prg.curV = saveV + *prg.mem[int32(p)+depthOffset].int()
 15231  					prg.curH = leftEdge
 15232  				}
 15233  
 15234  			case ruleNode:
 15235  				prg.ruleHt = *prg.mem[int32(p)+heightOffset].int()
 15236  				prg.ruleDp = *prg.mem[int32(p)+depthOffset].int()
 15237  				prg.ruleWd = *prg.mem[int32(p)+widthOffset].int()
 15238  
 15239  				goto finRule
 15240  
 15241  			case whatsitNode:
 15242  				// Output the whatsit node |p| in a vlist
 15243  				prg.outWhat(p)
 15244  
 15245  			case glueNode:
 15246  				// Move down or output leaders
 15247  				prg.g = *(*prg.mem[int32(p)+1].hh()).lh()
 15248  				prg.ruleHt = *prg.mem[int32(prg.g)+widthOffset].int() - curG
 15249  				if int32(gSign) != normal {
 15250  					if int32(gSign) == stretching {
 15251  						if int32(*(*prg.mem[prg.g].hh()).b0()) == int32(gOrder) {
 15252  							curGlue = curGlue + float64(*prg.mem[int32(prg.g)+2].int())
 15253  							glueTemp = float64(*prg.mem[int32(thisBox)+glueOffset].gr()) * curGlue
 15254  							if glueTemp > 1000000000.0 {
 15255  								glueTemp = 1000000000.0
 15256  							} else if glueTemp < -1000000000.0 {
 15257  								glueTemp = -1000000000.0
 15258  							}
 15259  							// \xref[real multiplication]
 15260  							curG = round(glueTemp)
 15261  						}
 15262  					} else if int32(*(*prg.mem[prg.g].hh()).b1()) == int32(gOrder) {
 15263  						curGlue = curGlue - float64(*prg.mem[int32(prg.g)+3].int())
 15264  						glueTemp = float64(*prg.mem[int32(thisBox)+glueOffset].gr()) * curGlue
 15265  						if glueTemp > 1000000000.0 {
 15266  							glueTemp = 1000000000.0
 15267  						} else if glueTemp < -1000000000.0 {
 15268  							glueTemp = -1000000000.0
 15269  						}
 15270  						curG = round(glueTemp)
 15271  					}
 15272  				}
 15273  				prg.ruleHt = prg.ruleHt + curG
 15274  				if int32(*(*prg.mem[p].hh()).b1()) >= aLeaders {
 15275  					leaderBox = *(*prg.mem[int32(p)+1].hh()).rh()
 15276  					if int32(*(*prg.mem[leaderBox].hh()).b0()) == ruleNode {
 15277  						prg.ruleWd = *prg.mem[int32(leaderBox)+widthOffset].int()
 15278  						prg.ruleDp = 0
 15279  
 15280  						goto finRule
 15281  					}
 15282  					leaderHt = *prg.mem[int32(leaderBox)+heightOffset].int() + *prg.mem[int32(leaderBox)+depthOffset].int()
 15283  					if leaderHt > 0 && prg.ruleHt > 0 {
 15284  						prg.ruleHt = prg.ruleHt + 10 // compensate for floating-point rounding
 15285  						edge = prg.curV + prg.ruleHt
 15286  						lx = 0
 15287  
 15288  						// Let |cur_v| be the position of the first box, and set |leader_ht+lx| to the spacing between corresponding parts of boxes
 15289  						if int32(*(*prg.mem[p].hh()).b1()) == aLeaders {
 15290  							saveV = prg.curV
 15291  							prg.curV = topEdge + leaderHt*((prg.curV-topEdge)/leaderHt)
 15292  							if prg.curV < saveV {
 15293  								prg.curV = prg.curV + leaderHt
 15294  							}
 15295  						} else {
 15296  							prg.lq = prg.ruleHt / leaderHt // the number of box copies
 15297  							prg.lr = prg.ruleHt % leaderHt // the remaining space
 15298  							if int32(*(*prg.mem[p].hh()).b1()) == cLeaders {
 15299  								prg.curV = prg.curV + prg.lr/2
 15300  							} else {
 15301  								lx = prg.lr / (prg.lq + 1)
 15302  								prg.curV = prg.curV + (prg.lr-(prg.lq-1)*lx)/2
 15303  							}
 15304  						}
 15305  						for prg.curV+leaderHt <= edge {
 15306  
 15307  							// Output a leader box at |cur_v|, then advance |cur_v| by |leader_ht+lx|
 15308  							prg.curH = leftEdge + *prg.mem[int32(leaderBox)+4].int()
 15309  							if prg.curH != prg.dviH {
 15310  								prg.movement(prg.curH-prg.dviH, eightBits(right1))
 15311  								prg.dviH = prg.curH
 15312  							}
 15313  							saveH = prg.dviH
 15314  
 15315  							prg.curV = prg.curV + *prg.mem[int32(leaderBox)+heightOffset].int()
 15316  							if prg.curV != prg.dviV {
 15317  								prg.movement(prg.curV-prg.dviV, eightBits(down1))
 15318  								prg.dviV = prg.curV
 15319  							}
 15320  							saveV = prg.dviV
 15321  							prg.tempPtr = leaderBox
 15322  							outerDoingLeaders = prg.doingLeaders
 15323  							prg.doingLeaders = true
 15324  							if int32(*(*prg.mem[leaderBox].hh()).b0()) == vlistNode {
 15325  								prg.vlistOut()
 15326  							} else {
 15327  								prg.hlistOut()
 15328  							}
 15329  							prg.doingLeaders = outerDoingLeaders
 15330  							prg.dviV = saveV
 15331  							prg.dviH = saveH
 15332  							prg.curH = leftEdge
 15333  							prg.curV = saveV - *prg.mem[int32(leaderBox)+heightOffset].int() + leaderHt + lx
 15334  						}
 15335  						prg.curV = edge - 10
 15336  						goto nextP
 15337  					}
 15338  				}
 15339  
 15340  				goto movePast
 15341  
 15342  			case kernNode:
 15343  				prg.curV = prg.curV + *prg.mem[int32(p)+widthOffset].int()
 15344  
 15345  			default:
 15346  			}
 15347  
 15348  			goto nextP
 15349  
 15350  		finRule:
 15351  			if prg.ruleWd == -010000000000 {
 15352  				prg.ruleWd = *prg.mem[int32(thisBox)+widthOffset].int()
 15353  			}
 15354  			prg.ruleHt = prg.ruleHt + prg.ruleDp // this is the rule thickness
 15355  			prg.curV = prg.curV + prg.ruleHt
 15356  			if prg.ruleHt > 0 && prg.ruleWd > 0 {
 15357  				if prg.curH != prg.dviH {
 15358  					prg.movement(prg.curH-prg.dviH, eightBits(right1))
 15359  					prg.dviH = prg.curH
 15360  				}
 15361  				if prg.curV != prg.dviV {
 15362  					prg.movement(prg.curV-prg.dviV, eightBits(down1))
 15363  					prg.dviV = prg.curV
 15364  				}
 15365  				{
 15366  					prg.dviBuf[prg.dviPtr] = byte(putRule)
 15367  					prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 15368  					if int32(prg.dviPtr) == int32(prg.dviLimit) {
 15369  						prg.dviSwap()
 15370  					}
 15371  				}
 15372  				prg.dviFour(prg.ruleHt)
 15373  				prg.dviFour(prg.ruleWd)
 15374  			}
 15375  
 15376  			goto nextP
 15377  
 15378  		movePast:
 15379  			prg.curV = prg.curV + prg.ruleHt
 15380  		}
 15381  
 15382  	nextP:
 15383  		p = *(*prg.mem[p].hh()).rh()
 15384  	}
 15385  	prg.pruneMovements(saveLoc)
 15386  	if prg.curS > 0 {
 15387  		prg.dviPop(saveLoc)
 15388  	}
 15389  	prg.curS = prg.curS - 1
 15390  }
 15391  
 15392  // 638.
 15393  
 15394  // tangle:pos tex.web:12678:1:
 15395  
 15396  // The |hlist_out| and |vlist_out| procedures are now complete, so we are
 15397  // ready for the |ship_out| routine that gets them started in the first place.
 15398  func (prg *prg) shipOut(p halfword) {
 15399  	var (
 15400  		pageLoc                             int32       // location of the current |bop|
 15401  		j, k/* 0..9 */ byte                             // indices to first ten count registers
 15402  		s                                   poolPointer // index into |str_pool|
 15403  		oldSetting/* 0..maxSelector */ byte             // saved |selector| setting
 15404  	)
 15405  	if *prg.eqtb[intBase+tracingOutputCode-1].int() > 0 {
 15406  		prg.printNl(strNumber( /* "" */ 338))
 15407  		prg.printLn()
 15408  		prg.print( /* "Completed box being shipped out" */ 829)
 15409  		// \xref[Completed box...]
 15410  	}
 15411  	if int32(prg.termOffset) > maxPrintLine-9 {
 15412  		prg.printLn()
 15413  	} else if int32(prg.termOffset) > 0 || int32(prg.fileOffset) > 0 {
 15414  		prg.printChar(asciiCode(' '))
 15415  	}
 15416  	prg.printChar(asciiCode('['))
 15417  	j = 9
 15418  	for *prg.eqtb[countBase+int32(j)-1].int() == 0 && int32(j) > 0 {
 15419  		j = byte(int32(j) - 1)
 15420  	}
 15421  	for ii := int32(0); ii <= int32(j); ii++ {
 15422  		k = byte(ii)
 15423  		_ = k
 15424  		prg.printInt(*prg.eqtb[countBase+int32(k)-1].int())
 15425  		if int32(k) < int32(j) {
 15426  			prg.printChar(asciiCode('.'))
 15427  		}
 15428  	}
 15429  
 15430  	if *prg.eqtb[intBase+tracingOutputCode-1].int() > 0 {
 15431  		prg.printChar(asciiCode(']'))
 15432  		prg.beginDiagnostic()
 15433  		prg.showBox(p)
 15434  		prg.endDiagnostic(true)
 15435  	}
 15436  
 15437  	// Ship box |p| out
 15438  
 15439  	// Update the values of |max_h| and |max_v|; but if the page is too large, |goto done|
 15440  	if *prg.mem[int32(p)+heightOffset].int() > 07777777777 || *prg.mem[int32(p)+depthOffset].int() > 07777777777 || *prg.mem[int32(p)+heightOffset].int()+*prg.mem[int32(p)+depthOffset].int()+*prg.eqtb[dimenBase+vOffsetCode-1].int() > 07777777777 || *prg.mem[int32(p)+widthOffset].int()+*prg.eqtb[dimenBase+hOffsetCode-1].int() > 07777777777 {
 15441  		{
 15442  			if int32(prg.interaction) == errorStopMode {
 15443  			}
 15444  			prg.printNl(strNumber( /* "! " */ 262))
 15445  			prg.print( /* "Huge page cannot be shipped out" */ 833)
 15446  		}
 15447  		// \xref[Huge page...]
 15448  		{
 15449  			prg.helpPtr = 2
 15450  			prg.helpLine[1] = /* "The page just created is more than 18 feet tall or" */ 834
 15451  			prg.helpLine[0] = /* "more than 18 feet wide, so I suspect something went wrong." */ 835
 15452  		}
 15453  		prg.error1()
 15454  		if *prg.eqtb[intBase+tracingOutputCode-1].int() <= 0 {
 15455  			prg.beginDiagnostic()
 15456  			prg.printNl(strNumber( /* "The following box has been deleted:" */ 836))
 15457  			// \xref[The following...deleted]
 15458  			prg.showBox(p)
 15459  			prg.endDiagnostic(true)
 15460  		}
 15461  
 15462  		goto done
 15463  	}
 15464  	if *prg.mem[int32(p)+heightOffset].int()+*prg.mem[int32(p)+depthOffset].int()+*prg.eqtb[dimenBase+vOffsetCode-1].int() > prg.maxV {
 15465  		prg.maxV = *prg.mem[int32(p)+heightOffset].int() + *prg.mem[int32(p)+depthOffset].int() + *prg.eqtb[dimenBase+vOffsetCode-1].int()
 15466  	}
 15467  	if *prg.mem[int32(p)+widthOffset].int()+*prg.eqtb[dimenBase+hOffsetCode-1].int() > prg.maxH {
 15468  		prg.maxH = *prg.mem[int32(p)+widthOffset].int() + *prg.eqtb[dimenBase+hOffsetCode-1].int()
 15469  	}
 15470  
 15471  	// Initialize variables as |ship_out| begins
 15472  	prg.dviH = 0
 15473  	prg.dviV = 0
 15474  	prg.curH = *prg.eqtb[dimenBase+hOffsetCode-1].int()
 15475  	prg.dviF = byte(fontBase)
 15476  	if int32(prg.outputFileName) == 0 {
 15477  		if int32(prg.jobName) == 0 {
 15478  			prg.openLogFile()
 15479  		}
 15480  		prg.packJobName(strNumber( /* ".dvi" */ 794))
 15481  		for !prg.bOpenOut(prg.dviFile) {
 15482  			prg.promptFileName(strNumber( /* "file name for output" */ 795), strNumber( /* ".dvi" */ 794))
 15483  		}
 15484  		prg.outputFileName = prg.bMakeNameString(prg.dviFile)
 15485  	}
 15486  	if prg.totalPages == 0 {
 15487  		{
 15488  			prg.dviBuf[prg.dviPtr] = byte(pre)
 15489  			prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 15490  			if int32(prg.dviPtr) == int32(prg.dviLimit) {
 15491  				prg.dviSwap()
 15492  			}
 15493  		}
 15494  		{
 15495  			prg.dviBuf[prg.dviPtr] = byte(idByte)
 15496  			prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 15497  			if int32(prg.dviPtr) == int32(prg.dviLimit) {
 15498  				prg.dviSwap()
 15499  			}
 15500  		} // output the preamble
 15501  		// \xref[preamble of \.[DVI] file]
 15502  		prg.dviFour(25400000)
 15503  		prg.dviFour(473628672) // conversion ratio for sp
 15504  		prg.prepareMag()
 15505  		prg.dviFour(*prg.eqtb[intBase+magCode-1].int()) // magnification factor is frozen
 15506  		oldSetting = prg.selector
 15507  		prg.selector = byte(newString)
 15508  		prg.print( /* " TeX output " */ 827)
 15509  		prg.printInt(*prg.eqtb[intBase+yearCode-1].int())
 15510  		prg.printChar(asciiCode('.'))
 15511  		prg.printTwo(*prg.eqtb[intBase+monthCode-1].int())
 15512  		prg.printChar(asciiCode('.'))
 15513  		prg.printTwo(*prg.eqtb[intBase+dayCode-1].int())
 15514  		prg.printChar(asciiCode(':'))
 15515  		prg.printTwo(*prg.eqtb[intBase+timeCode-1].int() / 60)
 15516  		prg.printTwo(*prg.eqtb[intBase+timeCode-1].int() % 60)
 15517  		prg.selector = oldSetting
 15518  		{
 15519  			prg.dviBuf[prg.dviPtr] = byte(int32(prg.poolPtr) - int32(prg.strStart[prg.strPtr]))
 15520  			prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 15521  			if int32(prg.dviPtr) == int32(prg.dviLimit) {
 15522  				prg.dviSwap()
 15523  			}
 15524  		}
 15525  		for ii := int32(prg.strStart[prg.strPtr]); ii <= int32(prg.poolPtr)-1; ii++ {
 15526  			s = poolPointer(ii)
 15527  			_ = s
 15528  			prg.dviBuf[prg.dviPtr] = prg.strPool[s]
 15529  			prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 15530  			if int32(prg.dviPtr) == int32(prg.dviLimit) {
 15531  				prg.dviSwap()
 15532  			}
 15533  		}
 15534  		prg.poolPtr = prg.strStart[prg.strPtr] // flush the current string
 15535  	}
 15536  	pageLoc = prg.dviOffset + int32(prg.dviPtr)
 15537  	{
 15538  		prg.dviBuf[prg.dviPtr] = byte(bop)
 15539  		prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 15540  		if int32(prg.dviPtr) == int32(prg.dviLimit) {
 15541  			prg.dviSwap()
 15542  		}
 15543  	}
 15544  	for ii := int32(0); ii <= 9; ii++ {
 15545  		k = byte(ii)
 15546  		_ = k
 15547  		prg.dviFour(*prg.eqtb[countBase+int32(k)-1].int())
 15548  	}
 15549  	prg.dviFour(prg.lastBop)
 15550  	prg.lastBop = pageLoc
 15551  	prg.curV = *prg.mem[int32(p)+heightOffset].int() + *prg.eqtb[dimenBase+vOffsetCode-1].int()
 15552  	prg.tempPtr = p
 15553  	if int32(*(*prg.mem[p].hh()).b0()) == vlistNode {
 15554  		prg.vlistOut()
 15555  	} else {
 15556  		prg.hlistOut()
 15557  	}
 15558  	{
 15559  		prg.dviBuf[prg.dviPtr] = byte(eop)
 15560  		prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 15561  		if int32(prg.dviPtr) == int32(prg.dviLimit) {
 15562  			prg.dviSwap()
 15563  		}
 15564  	}
 15565  	prg.totalPages = prg.totalPages + 1
 15566  	prg.curS = -1
 15567  
 15568  done:
 15569  	;
 15570  	if *prg.eqtb[intBase+tracingOutputCode-1].int() <= 0 {
 15571  		prg.printChar(asciiCode(']'))
 15572  	}
 15573  	prg.deadCycles = 0
 15574  	// progress report
 15575  
 15576  	// Flush the box from memory, showing statistics if requested
 15577  	//  if eqtb[int_base+ tracing_stats_code].int  >1 then
 15578  	//   begin print_nl(["Memory usage before: "=]830);
 15579  	// [ \xref[Memory usage...] ]
 15580  	//   print_int(var_used); print_char(["&"=]38);
 15581  	//   print_int(dyn_used); print_char([";"=]59);
 15582  	//   end;
 15583  	// [  ]
 15584  
 15585  	prg.flushNodeList(p)
 15586  	//  if eqtb[int_base+ tracing_stats_code].int  >1 then
 15587  	//   begin print([" after: "=]831);
 15588  	//   print_int(var_used); print_char(["&"=]38);
 15589  	//   print_int(dyn_used); print(["; still untouched: "=]832);
 15590  	//   print_int(hi_mem_min-lo_mem_max-1); print_ln;
 15591  	//   end;
 15592  	// [  ]
 15593  
 15594  }
 15595  
 15596  // 644. \[33] Packaging
 15597  
 15598  // tangle:pos tex.web:12811:18:
 15599  
 15600  // We're essentially done with the parts of \TeX\ that are concerned with
 15601  // the input (|get_next|) and the output (|ship_out|). So it's time to
 15602  // get heavily into the remaining part, which does the real work of typesetting.
 15603  //
 15604  // After lists are constructed, \TeX\ wraps them up and puts them into boxes.
 15605  // Two major subroutines are given the responsibility for this task: |hpack|
 15606  // applies to horizontal lists (hlists) and |vpack| applies to vertical lists
 15607  // (vlists). The main duty of |hpack| and |vpack| is to compute the dimensions
 15608  // of the resulting boxes, and to adjust the glue if one of those dimensions
 15609  // is pre-specified. The computed sizes normally enclose all of the material
 15610  // inside the new box; but some items may stick out if negative glue is used,
 15611  // if the box is overfull, or if a \.[\\vbox] includes other boxes that have
 15612  // been shifted left.
 15613  //
 15614  // The subroutine call |hpack(p,w,m)| returns a pointer to an |hlist_node|
 15615  // for a box containing the hlist that starts at |p|. Parameter |w| specifies
 15616  // a width; and parameter |m| is either `|exactly|' or `|additional|'.  Thus,
 15617  // |hpack(p,w,exactly)| produces a box whose width is exactly |w|, while
 15618  // |hpack(p,w,additional)| yields a box whose width is the natural width plus
 15619  // |w|.  It is convenient to define a macro called `|natural|' to cover the
 15620  // most common case, so that we can say |hpack(p,natural)| to get a box that
 15621  // has the natural width of list |p|.
 15622  //
 15623  // Similarly, |vpack(p,w,m)| returns a pointer to a |vlist_node| for a
 15624  // box containing the vlist that starts at |p|. In this case |w| represents
 15625  // a height instead of a width; the parameter |m| is interpreted as in |hpack|.
 15626  
 15627  // 645.
 15628  
 15629  // tangle:pos tex.web:12843:1:
 15630  
 15631  // The parameters to |hpack| and |vpack| correspond to \TeX's primitives
 15632  // like `\.[\\hbox] \.[to] \.[300pt]', `\.[\\hbox] \.[spread] \.[10pt]'; note
 15633  // that `\.[\\hbox]' with no dimension following it is equivalent to
 15634  // `\.[\\hbox] \.[spread] \.[0pt]'.  The |scan_spec| subroutine scans such
 15635  // constructions in the user's input, including the mandatory left brace that
 15636  // follows them, and it puts the specification onto |save_stack| so that the
 15637  // desired box can later be obtained by executing the following code:
 15638  // $$\vbox[\halign[#\hfil\cr
 15639  // |save_ptr:=save_ptr-2;|\cr
 15640  // |hpack(p,saved(1),saved(0)).|\cr]]$$
 15641  // Special care is necessary to ensure that the special |save_stack| codes
 15642  // are placed just below the new group code, because scanning can change
 15643  // |save_stack| when \.[\\csname] appears.
 15644  func (prg *prg) scanSpec(c groupCode, threeCodes bool) {
 15645  	var (
 15646  		s int32 // temporarily saved value
 15647  		specCode/* exactly..additional */ byte
 15648  	)
 15649  	if threeCodes {
 15650  		s = *prg.saveStack[int32(prg.savePtr)+0].int()
 15651  	}
 15652  	if prg.scanKeyword(strNumber( /* "to" */ 842)) {
 15653  		specCode = byte(exactly)
 15654  	} else if prg.scanKeyword(strNumber( /* "spread" */ 843)) {
 15655  		specCode = byte(additional)
 15656  	} else {
 15657  		specCode = byte(additional)
 15658  		prg.curVal = 0
 15659  
 15660  		goto found
 15661  	}
 15662  	prg.scanDimen(false, false, false)
 15663  
 15664  found:
 15665  	if threeCodes {
 15666  		*prg.saveStack[int32(prg.savePtr)+0].int() = s
 15667  		prg.savePtr = uint16(int32(prg.savePtr) + 1)
 15668  	}
 15669  	*prg.saveStack[int32(prg.savePtr)+0].int() = int32(specCode)
 15670  	*prg.saveStack[int32(prg.savePtr)+1].int() = prg.curVal
 15671  	prg.savePtr = uint16(int32(prg.savePtr) + 2)
 15672  	prg.newSaveLevel(c)
 15673  	prg.scanLeftBrace()
 15674  }
 15675  
 15676  // 649.
 15677  
 15678  // tangle:pos tex.web:12910:1:
 15679  
 15680  // Here now is |hpack|, which contains few if any surprises.
 15681  func (prg *prg) hpack(p halfword, w scaled, m smallNumber) (r halfword) {
 15682  	var (
 15683  		r1      halfword           // the box node that will be returned
 15684  		q       halfword           // trails behind |p|
 15685  		h, d, x scaled             // height, depth, and natural width
 15686  		s       scaled             // shift amount
 15687  		g       halfword           // points to a glue specification
 15688  		o       glueOrd            // order of infinity
 15689  		f       internalFontNumber // the font in a |char_node|
 15690  		i       fourQuarters       // font information about a |char_node|
 15691  		hd      eightBits          // height and depth indices for a character
 15692  	)
 15693  	prg.lastBadness = 0
 15694  	r1 = prg.getNode(boxNodeSize)
 15695  	*(*prg.mem[r1].hh()).b0() = byte(hlistNode)
 15696  	*(*prg.mem[r1].hh()).b1() = byte(minQuarterword)
 15697  	*prg.mem[int32(r1)+4].int() = 0
 15698  	q = uint16(int32(r1) + listOffset)
 15699  	*(*prg.mem[q].hh()).rh() = p
 15700  
 15701  	h = 0
 15702  	// Clear dimensions to zero
 15703  	d = 0
 15704  	x = 0
 15705  	prg.totalStretch[normal] = 0
 15706  	prg.totalShrink[normal] = 0
 15707  	prg.totalStretch[fil] = 0
 15708  	prg.totalShrink[fil] = 0
 15709  	prg.totalStretch[fill] = 0
 15710  	prg.totalShrink[fill] = 0
 15711  	prg.totalStretch[filll] = 0
 15712  	prg.totalShrink[filll] = 0
 15713  	for int32(p) != 0 {
 15714  		// Examine node |p| in the hlist, taking account of its effect on the dimensions of the new box, or moving it to the adjustment list; then advance |p| to the next node
 15715  		// \xref[inner loop]
 15716  	reswitch:
 15717  		for int32(p) >= int32(prg.hiMemMin) {
 15718  
 15719  			// Incorporate character dimensions into the dimensions of the hbox that will contain~it, then move to the next node
 15720  			f = *(*prg.mem[p].hh()).b0()
 15721  			i = *prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[p].hh()).b1())].qqqq()
 15722  			hd = byte(int32(i.b1) - minQuarterword)
 15723  			x = x + *prg.fontInfo[prg.widthBase[f]+int32(i.b0)].int()
 15724  
 15725  			s = *prg.fontInfo[prg.heightBase[f]+int32(hd)/16].int()
 15726  			if s > h {
 15727  				h = s
 15728  			}
 15729  			s = *prg.fontInfo[prg.depthBase[f]+int32(hd)%16].int()
 15730  			if s > d {
 15731  				d = s
 15732  			}
 15733  			p = *(*prg.mem[p].hh()).rh()
 15734  		}
 15735  		if int32(p) != 0 {
 15736  			switch *(*prg.mem[p].hh()).b0() {
 15737  			case hlistNode, vlistNode, ruleNode, unsetNode:
 15738  
 15739  				// Incorporate box dimensions into the dimensions of the hbox that will contain~it
 15740  				x = x + *prg.mem[int32(p)+widthOffset].int()
 15741  				if int32(*(*prg.mem[p].hh()).b0()) >= ruleNode {
 15742  					s = 0
 15743  				} else {
 15744  					s = *prg.mem[int32(p)+4].int()
 15745  				}
 15746  				if *prg.mem[int32(p)+heightOffset].int()-s > h {
 15747  					h = *prg.mem[int32(p)+heightOffset].int() - s
 15748  				}
 15749  				if *prg.mem[int32(p)+depthOffset].int()+s > d {
 15750  					d = *prg.mem[int32(p)+depthOffset].int() + s
 15751  				}
 15752  
 15753  			case insNode, markNode, adjustNode:
 15754  				if int32(prg.adjustTail) != 0 {
 15755  					for int32(*(*prg.mem[q].hh()).rh()) != int32(p) {
 15756  						q = *(*prg.mem[q].hh()).rh()
 15757  					}
 15758  					if int32(*(*prg.mem[p].hh()).b0()) == adjustNode {
 15759  						*(*prg.mem[prg.adjustTail].hh()).rh() = uint16(*prg.mem[int32(p)+1].int())
 15760  						for int32(*(*prg.mem[prg.adjustTail].hh()).rh()) != 0 {
 15761  							prg.adjustTail = *(*prg.mem[prg.adjustTail].hh()).rh()
 15762  						}
 15763  						p = *(*prg.mem[p].hh()).rh()
 15764  						prg.freeNode(*(*prg.mem[q].hh()).rh(), halfword(smallNodeSize))
 15765  					} else {
 15766  						*(*prg.mem[prg.adjustTail].hh()).rh() = p
 15767  						prg.adjustTail = p
 15768  						p = *(*prg.mem[p].hh()).rh()
 15769  					}
 15770  					*(*prg.mem[q].hh()).rh() = p
 15771  					p = q
 15772  				}
 15773  
 15774  			case whatsitNode:
 15775  			// Incorporate a whatsit node into an hbox
 15776  
 15777  			// Incorporate a whatsit node into an hbox
 15778  
 15779  			case glueNode:
 15780  				// Incorporate glue into the horizontal totals
 15781  				g = *(*prg.mem[int32(p)+1].hh()).lh()
 15782  				x = x + *prg.mem[int32(g)+widthOffset].int()
 15783  
 15784  				o = *(*prg.mem[g].hh()).b0()
 15785  				prg.totalStretch[o] = prg.totalStretch[o] + *prg.mem[int32(g)+2].int()
 15786  				o = *(*prg.mem[g].hh()).b1()
 15787  				prg.totalShrink[o] = prg.totalShrink[o] + *prg.mem[int32(g)+3].int()
 15788  				if int32(*(*prg.mem[p].hh()).b1()) >= aLeaders {
 15789  					g = *(*prg.mem[int32(p)+1].hh()).rh()
 15790  					if *prg.mem[int32(g)+heightOffset].int() > h {
 15791  						h = *prg.mem[int32(g)+heightOffset].int()
 15792  					}
 15793  					if *prg.mem[int32(g)+depthOffset].int() > d {
 15794  						d = *prg.mem[int32(g)+depthOffset].int()
 15795  					}
 15796  				}
 15797  
 15798  			case kernNode, mathNode:
 15799  				x = x + *prg.mem[int32(p)+widthOffset].int()
 15800  			case ligatureNode:
 15801  				// Make node |p| look like a |char_node| and |goto reswitch|
 15802  				prg.mem[30000-12] = prg.mem[int32(p)+1]
 15803  				*(*prg.mem[30000-12].hh()).rh() = *(*prg.mem[p].hh()).rh()
 15804  				p = uint16(30000 - 12)
 15805  				goto reswitch
 15806  
 15807  			default:
 15808  			}
 15809  
 15810  			p = *(*prg.mem[p].hh()).rh()
 15811  		}
 15812  	}
 15813  	if int32(prg.adjustTail) != 0 {
 15814  		*(*prg.mem[prg.adjustTail].hh()).rh() = 0
 15815  	}
 15816  	*prg.mem[int32(r1)+heightOffset].int() = h
 15817  	*prg.mem[int32(r1)+depthOffset].int() = d
 15818  
 15819  	// Determine the value of |width(r)| and the appropriate glue setting; then |return| or |goto common_ending|
 15820  	if int32(m) == additional {
 15821  		w = x + w
 15822  	}
 15823  	*prg.mem[int32(r1)+widthOffset].int() = w
 15824  	x = w - x // now |x| is the excess to be made up
 15825  	if x == 0 {
 15826  		*(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(normal)
 15827  		*(*prg.mem[int32(r1)+listOffset].hh()).b1() = byte(normal)
 15828  		*prg.mem[int32(r1)+glueOffset].gr() = float32(0.0)
 15829  
 15830  		goto exit
 15831  	} else if x > 0 {
 15832  		if prg.totalStretch[filll] != 0 {
 15833  			o = byte(filll)
 15834  		} else if prg.totalStretch[fill] != 0 {
 15835  			o = byte(fill)
 15836  		} else if prg.totalStretch[fil] != 0 {
 15837  			o = byte(fil)
 15838  		} else {
 15839  			o = byte(normal)
 15840  		}
 15841  		*(*prg.mem[int32(r1)+listOffset].hh()).b1() = o
 15842  		*(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(stretching)
 15843  		if prg.totalStretch[o] != 0 {
 15844  			*prg.mem[int32(r1)+glueOffset].gr() = float32(float64(x) / float64(prg.totalStretch[o]))
 15845  		} else {
 15846  			*(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(normal)
 15847  			*prg.mem[int32(r1)+glueOffset].gr() = float32(0.0) // there's nothing to stretch
 15848  		}
 15849  		if int32(o) == normal {
 15850  			if int32(*(*prg.mem[int32(r1)+listOffset].hh()).rh()) != 0 {
 15851  				prg.lastBadness = int32(prg.badness(x, prg.totalStretch[normal]))
 15852  				if prg.lastBadness > *prg.eqtb[intBase+hbadnessCode-1].int() {
 15853  					prg.printLn()
 15854  					if prg.lastBadness > 100 {
 15855  						prg.printNl(strNumber( /* "Underfull" */ 844))
 15856  					} else {
 15857  						prg.printNl(strNumber( /* "Loose" */ 845))
 15858  					}
 15859  					prg.print( /* " \\hbox (badness " */ 846)
 15860  					prg.printInt(prg.lastBadness)
 15861  					// \xref[Underfull \\hbox...]
 15862  					// \xref[Loose \\hbox...]
 15863  
 15864  					// \xref[Underfull \\hbox...]
 15865  					// \xref[Loose \\hbox...]
 15866  					goto commonEnding
 15867  				}
 15868  			}
 15869  		}
 15870  
 15871  		goto exit
 15872  	} else {
 15873  		// Determine horizontal glue shrink setting, then |return| or \hbox[|goto common_ending|]
 15874  		if prg.totalShrink[filll] != 0 {
 15875  			o = byte(filll)
 15876  		} else if prg.totalShrink[fill] != 0 {
 15877  			o = byte(fill)
 15878  		} else if prg.totalShrink[fil] != 0 {
 15879  			o = byte(fil)
 15880  		} else {
 15881  			o = byte(normal)
 15882  		}
 15883  		*(*prg.mem[int32(r1)+listOffset].hh()).b1() = o
 15884  		*(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(shrinking)
 15885  		if prg.totalShrink[o] != 0 {
 15886  			*prg.mem[int32(r1)+glueOffset].gr() = float32(float64(-x) / float64(prg.totalShrink[o]))
 15887  		} else {
 15888  			*(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(normal)
 15889  			*prg.mem[int32(r1)+glueOffset].gr() = float32(0.0) // there's nothing to shrink
 15890  		}
 15891  		if prg.totalShrink[o] < -x && int32(o) == normal && int32(*(*prg.mem[int32(r1)+listOffset].hh()).rh()) != 0 {
 15892  			prg.lastBadness = 1000000
 15893  			*prg.mem[int32(r1)+glueOffset].gr() = float32(1.0) // use the maximum shrinkage
 15894  
 15895  			// Report an overfull hbox and |goto common_ending|, if this box is sufficiently bad
 15896  			if -x-prg.totalShrink[normal] > *prg.eqtb[dimenBase+hfuzzCode-1].int() || *prg.eqtb[intBase+hbadnessCode-1].int() < 100 {
 15897  				if *prg.eqtb[dimenBase+overfullRuleCode-1].int() > 0 && -x-prg.totalShrink[normal] > *prg.eqtb[dimenBase+hfuzzCode-1].int() {
 15898  					for int32(*(*prg.mem[q].hh()).rh()) != 0 {
 15899  						q = *(*prg.mem[q].hh()).rh()
 15900  					}
 15901  					*(*prg.mem[q].hh()).rh() = prg.newRule()
 15902  					*prg.mem[int32(*(*prg.mem[q].hh()).rh())+widthOffset].int() = *prg.eqtb[dimenBase+overfullRuleCode-1].int()
 15903  				}
 15904  				prg.printLn()
 15905  				prg.printNl(strNumber( /* "Overfull \\hbox (" */ 852))
 15906  				// \xref[Overfull \\hbox...]
 15907  				prg.printScaled(-x - prg.totalShrink[normal])
 15908  				prg.print( /* "pt too wide" */ 853)
 15909  
 15910  				goto commonEnding
 15911  			}
 15912  		} else if int32(o) == normal {
 15913  			if int32(*(*prg.mem[int32(r1)+listOffset].hh()).rh()) != 0 {
 15914  				prg.lastBadness = int32(prg.badness(-x, prg.totalShrink[normal]))
 15915  				if prg.lastBadness > *prg.eqtb[intBase+hbadnessCode-1].int() {
 15916  					prg.printLn()
 15917  					prg.printNl(strNumber( /* "Tight \\hbox (badness " */ 854))
 15918  					prg.printInt(prg.lastBadness)
 15919  					// \xref[Tight \\hbox...]
 15920  
 15921  					// \xref[Tight \\hbox...]
 15922  					goto commonEnding
 15923  				}
 15924  			}
 15925  		}
 15926  
 15927  		goto exit
 15928  	}
 15929  
 15930  commonEnding:
 15931  	if prg.outputActive {
 15932  		prg.print( /* ") has occurred while \\output is active" */ 847)
 15933  	} else {
 15934  		if prg.packBeginLine != 0 {
 15935  			if prg.packBeginLine > 0 {
 15936  				prg.print( /* ") in paragraph at lines " */ 848)
 15937  			} else {
 15938  				prg.print( /* ") in alignment at lines " */ 849)
 15939  			}
 15940  			prg.printInt(abs(prg.packBeginLine))
 15941  			prg.print( /* "--" */ 850)
 15942  		} else {
 15943  			prg.print( /* ") detected at line " */ 851)
 15944  		}
 15945  		prg.printInt(prg.line)
 15946  	}
 15947  	prg.printLn()
 15948  
 15949  	prg.fontInShortDisplay = fontBase
 15950  	prg.shortDisplay(int32(*(*prg.mem[int32(r1)+listOffset].hh()).rh()))
 15951  	prg.printLn()
 15952  
 15953  	prg.beginDiagnostic()
 15954  	prg.showBox(r1)
 15955  	prg.endDiagnostic(true)
 15956  
 15957  exit:
 15958  	r = r1
 15959  	return r
 15960  }
 15961  
 15962  // 668.
 15963  
 15964  // tangle:pos tex.web:13152:1:
 15965  
 15966  // The |vpack| subroutine is actually a special case of a slightly more
 15967  // general routine called |vpackage|, which has four parameters. The fourth
 15968  // parameter, which is |max_dimen| in the case of |vpack|, specifies the
 15969  // maximum depth of the page box that is constructed. The depth is first
 15970  // computed by the normal rules; if it exceeds this limit, the reference
 15971  // point is simply moved down until the limiting depth is attained.
 15972  func (prg *prg) vpackage(p halfword, h scaled, m smallNumber, l scaled) (r halfword) {
 15973  	var (
 15974  		r1      halfword // the box node that will be returned
 15975  		w, d, x scaled   // width, depth, and natural height
 15976  		s       scaled   // shift amount
 15977  		g       halfword // points to a glue specification
 15978  		o       glueOrd  // order of infinity
 15979  	)
 15980  	prg.lastBadness = 0
 15981  	r1 = prg.getNode(boxNodeSize)
 15982  	*(*prg.mem[r1].hh()).b0() = byte(vlistNode)
 15983  	*(*prg.mem[r1].hh()).b1() = byte(minQuarterword)
 15984  	*prg.mem[int32(r1)+4].int() = 0
 15985  	*(*prg.mem[int32(r1)+listOffset].hh()).rh() = p
 15986  
 15987  	w = 0
 15988  	// Clear dimensions to zero
 15989  	d = 0
 15990  	x = 0
 15991  	prg.totalStretch[normal] = 0
 15992  	prg.totalShrink[normal] = 0
 15993  	prg.totalStretch[fil] = 0
 15994  	prg.totalShrink[fil] = 0
 15995  	prg.totalStretch[fill] = 0
 15996  	prg.totalShrink[fill] = 0
 15997  	prg.totalStretch[filll] = 0
 15998  	prg.totalShrink[filll] = 0
 15999  	for int32(p) != 0 {
 16000  		// Examine node |p| in the vlist, taking account of its effect on the dimensions of the new box; then advance |p| to the next node
 16001  		if int32(p) >= int32(prg.hiMemMin) {
 16002  			prg.confusion(strNumber( /* "vpack" */ 855))
 16003  		} else {
 16004  			switch *(*prg.mem[p].hh()).b0() {
 16005  			case hlistNode, vlistNode, ruleNode, unsetNode:
 16006  
 16007  				// Incorporate box dimensions into the dimensions of the vbox that will contain~it
 16008  				x = x + d + *prg.mem[int32(p)+heightOffset].int()
 16009  				d = *prg.mem[int32(p)+depthOffset].int()
 16010  				if int32(*(*prg.mem[p].hh()).b0()) >= ruleNode {
 16011  					s = 0
 16012  				} else {
 16013  					s = *prg.mem[int32(p)+4].int()
 16014  				}
 16015  				if *prg.mem[int32(p)+widthOffset].int()+s > w {
 16016  					w = *prg.mem[int32(p)+widthOffset].int() + s
 16017  				}
 16018  
 16019  			case whatsitNode:
 16020  			// Incorporate a whatsit node into a vbox
 16021  
 16022  			// Incorporate a whatsit node into a vbox
 16023  
 16024  			case glueNode:
 16025  				// Incorporate glue into the vertical totals
 16026  				x = x + d
 16027  				d = 0
 16028  
 16029  				g = *(*prg.mem[int32(p)+1].hh()).lh()
 16030  				x = x + *prg.mem[int32(g)+widthOffset].int()
 16031  
 16032  				o = *(*prg.mem[g].hh()).b0()
 16033  				prg.totalStretch[o] = prg.totalStretch[o] + *prg.mem[int32(g)+2].int()
 16034  				o = *(*prg.mem[g].hh()).b1()
 16035  				prg.totalShrink[o] = prg.totalShrink[o] + *prg.mem[int32(g)+3].int()
 16036  				if int32(*(*prg.mem[p].hh()).b1()) >= aLeaders {
 16037  					g = *(*prg.mem[int32(p)+1].hh()).rh()
 16038  					if *prg.mem[int32(g)+widthOffset].int() > w {
 16039  						w = *prg.mem[int32(g)+widthOffset].int()
 16040  					}
 16041  				}
 16042  
 16043  			case kernNode:
 16044  				x = x + d + *prg.mem[int32(p)+widthOffset].int()
 16045  				d = 0
 16046  
 16047  			default:
 16048  			}
 16049  		}
 16050  		p = *(*prg.mem[p].hh()).rh()
 16051  	}
 16052  	*prg.mem[int32(r1)+widthOffset].int() = w
 16053  	if d > l {
 16054  		x = x + d - l
 16055  		*prg.mem[int32(r1)+depthOffset].int() = l
 16056  	} else {
 16057  		*prg.mem[int32(r1)+depthOffset].int() = d
 16058  	}
 16059  
 16060  	// Determine the value of |height(r)| and the appropriate glue setting; then |return| or |goto common_ending|
 16061  	if int32(m) == additional {
 16062  		h = x + h
 16063  	}
 16064  	*prg.mem[int32(r1)+heightOffset].int() = h
 16065  	x = h - x // now |x| is the excess to be made up
 16066  	if x == 0 {
 16067  		*(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(normal)
 16068  		*(*prg.mem[int32(r1)+listOffset].hh()).b1() = byte(normal)
 16069  		*prg.mem[int32(r1)+glueOffset].gr() = float32(0.0)
 16070  
 16071  		goto exit
 16072  	} else if x > 0 {
 16073  		if prg.totalStretch[filll] != 0 {
 16074  			o = byte(filll)
 16075  		} else if prg.totalStretch[fill] != 0 {
 16076  			o = byte(fill)
 16077  		} else if prg.totalStretch[fil] != 0 {
 16078  			o = byte(fil)
 16079  		} else {
 16080  			o = byte(normal)
 16081  		}
 16082  		*(*prg.mem[int32(r1)+listOffset].hh()).b1() = o
 16083  		*(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(stretching)
 16084  		if prg.totalStretch[o] != 0 {
 16085  			*prg.mem[int32(r1)+glueOffset].gr() = float32(float64(x) / float64(prg.totalStretch[o]))
 16086  		} else {
 16087  			*(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(normal)
 16088  			*prg.mem[int32(r1)+glueOffset].gr() = float32(0.0) // there's nothing to stretch
 16089  		}
 16090  		if int32(o) == normal {
 16091  			if int32(*(*prg.mem[int32(r1)+listOffset].hh()).rh()) != 0 {
 16092  				prg.lastBadness = int32(prg.badness(x, prg.totalStretch[normal]))
 16093  				if prg.lastBadness > *prg.eqtb[intBase+vbadnessCode-1].int() {
 16094  					prg.printLn()
 16095  					if prg.lastBadness > 100 {
 16096  						prg.printNl(strNumber( /* "Underfull" */ 844))
 16097  					} else {
 16098  						prg.printNl(strNumber( /* "Loose" */ 845))
 16099  					}
 16100  					prg.print( /* " \\vbox (badness " */ 856)
 16101  					prg.printInt(prg.lastBadness)
 16102  					// \xref[Underfull \\vbox...]
 16103  					// \xref[Loose \\vbox...]
 16104  
 16105  					// \xref[Underfull \\vbox...]
 16106  					// \xref[Loose \\vbox...]
 16107  					goto commonEnding
 16108  				}
 16109  			}
 16110  		}
 16111  
 16112  		goto exit
 16113  	} else {
 16114  		// Determine vertical glue shrink setting, then |return| or \hbox[|goto common_ending|]
 16115  		if prg.totalShrink[filll] != 0 {
 16116  			o = byte(filll)
 16117  		} else if prg.totalShrink[fill] != 0 {
 16118  			o = byte(fill)
 16119  		} else if prg.totalShrink[fil] != 0 {
 16120  			o = byte(fil)
 16121  		} else {
 16122  			o = byte(normal)
 16123  		}
 16124  		*(*prg.mem[int32(r1)+listOffset].hh()).b1() = o
 16125  		*(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(shrinking)
 16126  		if prg.totalShrink[o] != 0 {
 16127  			*prg.mem[int32(r1)+glueOffset].gr() = float32(float64(-x) / float64(prg.totalShrink[o]))
 16128  		} else {
 16129  			*(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(normal)
 16130  			*prg.mem[int32(r1)+glueOffset].gr() = float32(0.0) // there's nothing to shrink
 16131  		}
 16132  		if prg.totalShrink[o] < -x && int32(o) == normal && int32(*(*prg.mem[int32(r1)+listOffset].hh()).rh()) != 0 {
 16133  			prg.lastBadness = 1000000
 16134  			*prg.mem[int32(r1)+glueOffset].gr() = float32(1.0) // use the maximum shrinkage
 16135  
 16136  			// Report an overfull vbox and |goto common_ending|, if this box is sufficiently bad
 16137  			if -x-prg.totalShrink[normal] > *prg.eqtb[dimenBase+vfuzzCode-1].int() || *prg.eqtb[intBase+vbadnessCode-1].int() < 100 {
 16138  				prg.printLn()
 16139  				prg.printNl(strNumber( /* "Overfull \\vbox (" */ 857))
 16140  				// \xref[Overfull \\vbox...]
 16141  				prg.printScaled(-x - prg.totalShrink[normal])
 16142  				prg.print( /* "pt too high" */ 858)
 16143  
 16144  				goto commonEnding
 16145  			}
 16146  		} else if int32(o) == normal {
 16147  			if int32(*(*prg.mem[int32(r1)+listOffset].hh()).rh()) != 0 {
 16148  				prg.lastBadness = int32(prg.badness(-x, prg.totalShrink[normal]))
 16149  				if prg.lastBadness > *prg.eqtb[intBase+vbadnessCode-1].int() {
 16150  					prg.printLn()
 16151  					prg.printNl(strNumber( /* "Tight \\vbox (badness " */ 859))
 16152  					prg.printInt(prg.lastBadness)
 16153  					// \xref[Tight \\vbox...]
 16154  
 16155  					// \xref[Tight \\vbox...]
 16156  					goto commonEnding
 16157  				}
 16158  			}
 16159  		}
 16160  
 16161  		goto exit
 16162  	}
 16163  
 16164  commonEnding:
 16165  	if prg.outputActive {
 16166  		prg.print( /* ") has occurred while \\output is active" */ 847)
 16167  	} else {
 16168  		if prg.packBeginLine != 0 {
 16169  			prg.print( /* ") in alignment at lines " */ 849)
 16170  			prg.printInt(abs(prg.packBeginLine))
 16171  			prg.print( /* "--" */ 850)
 16172  		} else {
 16173  			prg.print( /* ") detected at line " */ 851)
 16174  		}
 16175  		prg.printInt(prg.line)
 16176  		prg.printLn()
 16177  
 16178  	}
 16179  	prg.beginDiagnostic()
 16180  	prg.showBox(r1)
 16181  	prg.endDiagnostic(true)
 16182  
 16183  exit:
 16184  	r = r1
 16185  	return r
 16186  }
 16187  
 16188  // 679.
 16189  
 16190  // tangle:pos tex.web:13312:1:
 16191  
 16192  // When a box is being appended to the current vertical list, the
 16193  // baselineskip calculation is handled by the |append_to_vlist| routine.
 16194  func (prg *prg) appendToVlist(b halfword) {
 16195  	var (
 16196  		d scaled   // deficiency of space between baselines
 16197  		p halfword // a new glue node
 16198  	)
 16199  	if *prg.curList.auxField.int() > -65536000 {
 16200  		d = *prg.mem[int32(*(*prg.eqtb[glueBase+baselineSkipCode-1].hh()).rh())+widthOffset].int() - *prg.curList.auxField.int() - *prg.mem[int32(b)+heightOffset].int()
 16201  		if d < *prg.eqtb[dimenBase+lineSkipLimitCode-1].int() {
 16202  			p = prg.newParamGlue(smallNumber(lineSkipCode))
 16203  		} else {
 16204  			p = prg.newSkipParam(smallNumber(baselineSkipCode))
 16205  			*prg.mem[int32(prg.tempPtr)+widthOffset].int() = d // |temp_ptr=glue_ptr(p)|
 16206  		}
 16207  		*(*prg.mem[prg.curList.tailField].hh()).rh() = p
 16208  		prg.curList.tailField = p
 16209  	}
 16210  	*(*prg.mem[prg.curList.tailField].hh()).rh() = b
 16211  	prg.curList.tailField = b
 16212  	*prg.curList.auxField.int() = *prg.mem[int32(b)+depthOffset].int()
 16213  }
 16214  
 16215  // 680. \[34] Data structures for math mode
 16216  
 16217  // tangle:pos tex.web:13329:38:
 16218  
 16219  // When \TeX\ reads a formula that is enclosed between \.\$'s, it constructs an
 16220  // [\sl mlist], which is essentially a tree structure representing that
 16221  // formula.  An mlist is a linear sequence of items, but we can regard it as
 16222  // a tree structure because mlists can appear within mlists. For example, many
 16223  // of the entries can be subscripted or superscripted, and such ``scripts''
 16224  // are mlists in their own right.
 16225  //
 16226  // An entire formula is parsed into such a tree before any of the actual
 16227  // typesetting is done, because the current style of type is usually not
 16228  // known until the formula has been fully scanned. For example, when the
 16229  // formula `\.[\$a+b \\over c+d\$]' is being read, there is no way to tell
 16230  // that `\.[a+b]' will be in script size until `\.[\\over]' has appeared.
 16231  //
 16232  // During the scanning process, each element of the mlist being built is
 16233  // classified as a relation, a binary operator, an open parenthesis, etc.,
 16234  // or as a construct like `\.[\\sqrt]' that must be built up. This classification
 16235  // appears in the mlist data structure.
 16236  //
 16237  // After a formula has been fully scanned, the mlist is converted to an hlist
 16238  // so that it can be incorporated into the surrounding text. This conversion is
 16239  // controlled by a recursive procedure that decides all of the appropriate
 16240  // styles by a ``top-down'' process starting at the outermost level and working
 16241  // in towards the subformulas. The formula is ultimately pasted together using
 16242  // combinations of horizontal and vertical boxes, with glue and penalty nodes
 16243  // inserted as necessary.
 16244  //
 16245  // An mlist is represented internally as a linked list consisting chiefly
 16246  // of ``noads'' (pronounced ``no-adds''), to distinguish them from the somewhat
 16247  // similar ``nodes'' in hlists and vlists. Certain kinds of ordinary nodes are
 16248  // allowed to appear in mlists together with the noads; \TeX\ tells the difference
 16249  // by means of the |type| field, since a noad's |type| is always greater than
 16250  // that of a node. An mlist does not contain character nodes, hlist nodes, vlist
 16251  // nodes, math nodes, ligature nodes,
 16252  // or unset nodes; in particular, each mlist item appears in the
 16253  // variable-size part of |mem|, so the |type| field is always present.
 16254  
 16255  // 681.
 16256  
 16257  // tangle:pos tex.web:13366:1:
 16258  
 16259  // Each noad is four or more words long. The first word contains the |type|
 16260  // and |subtype| and |link| fields that are already so familiar to us; the
 16261  // second, third, and fourth words are called the noad's |nucleus|, |subscr|,
 16262  // and |supscr| fields.
 16263  //
 16264  // Consider, for example, the simple formula `\.[\$x\^2\$]', which would be
 16265  // parsed into an mlist containing a single element called an |ord_noad|.
 16266  // The |nucleus| of this noad is a representation of `\.x', the |subscr| is
 16267  // empty, and the |supscr| is a representation of `\.2'.
 16268  //
 16269  // The |nucleus|, |subscr|, and |supscr| fields are further broken into
 16270  // subfields. If |p| points to a noad, and if |q| is one of its principal
 16271  // fields (e.g., |q=subscr(p)|), there are several possibilities for the
 16272  // subfields, depending on the |math_type| of |q|.
 16273  //
 16274  // \yskip\hang|math_type(q)=math_char| means that |fam(q)| refers to one of
 16275  // the sixteen font families, and |character(q)| is the number of a character
 16276  // within a font of that family, as in a character node.
 16277  //
 16278  // \yskip\hang|math_type(q)=math_text_char| is similar, but the character is
 16279  // unsubscripted and unsuperscripted and it is followed immediately by another
 16280  // character from the same font. (This |math_type| setting appears only
 16281  // briefly during the processing; it is used to suppress unwanted italic
 16282  // corrections.)
 16283  //
 16284  // \yskip\hang|math_type(q)=empty| indicates a field with no value (the
 16285  // corresponding attribute of noad |p| is not present).
 16286  //
 16287  // \yskip\hang|math_type(q)=sub_box| means that |info(q)| points to a box
 16288  // node (either an |hlist_node| or a |vlist_node|) that should be used as the
 16289  // value of the field.  The |shift_amount| in the subsidiary box node is the
 16290  // amount by which that box will be shifted downward.
 16291  //
 16292  // \yskip\hang|math_type(q)=sub_mlist| means that |info(q)| points to
 16293  // an mlist; the mlist must be converted to an hlist in order to obtain
 16294  // the value of this field.
 16295  //
 16296  // \yskip\noindent In the latter case, we might have |info(q)=null|. This
 16297  // is not the same as |math_type(q)=empty|; for example, `\.[\$P\_\[\]\$]'
 16298  // and `\.[\$P\$]' produce different results (the former will not have the
 16299  // ``italic correction'' added to the width of |P|, but the ``script skip''
 16300  // will be added).
 16301  //
 16302  // The definitions of subfields given here are evidently wasteful of space,
 16303  // since a halfword is being used for the |math_type| although only three
 16304  // bits would be needed. However, there are hardly ever many noads present at
 16305  // once, since they are soon converted to nodes that take up even more space,
 16306  // so we can afford to represent them in whatever way simplifies the
 16307  // programming.
 16308  
 16309  // 682.
 16310  
 16311  // tangle:pos tex.web:13427:1:
 16312  
 16313  // Each portion of a formula is classified as Ord, Op, Bin, Rel, Open,
 16314  // Close, Punct, or Inner, for purposes of spacing and line breaking. An
 16315  // |ord_noad|, |op_noad|, |bin_noad|, |rel_noad|, |open_noad|, |close_noad|,
 16316  // |punct_noad|, or |inner_noad| is used to represent portions of the various
 16317  // types. For example, an `\.=' sign in a formula leads to the creation of a
 16318  // |rel_noad| whose |nucleus| field is a representation of an equals sign
 16319  // (usually |fam=0|, |character=@'75|).  A formula preceded by \.[\\mathrel]
 16320  // also results in a |rel_noad|.  When a |rel_noad| is followed by an
 16321  // |op_noad|, say, and possibly separated by one or more ordinary nodes (not
 16322  // noads), \TeX\ will insert a penalty node (with the current |rel_penalty|)
 16323  // just after the formula that corresponds to the |rel_noad|, unless there
 16324  // already was a penalty immediately following; and a ``thick space'' will be
 16325  // inserted just before the formula that corresponds to the |op_noad|.
 16326  //
 16327  // A noad of type |ord_noad|, |op_noad|, \dots, |inner_noad| usually
 16328  // has a |subtype=normal|. The only exception is that an |op_noad| might
 16329  // have |subtype=limits| or |no_limits|, if the normal positioning of
 16330  // limits has been overridden for this operator.
 16331  
 16332  // 683.
 16333  
 16334  // tangle:pos tex.web:13457:1:
 16335  
 16336  // A |radical_noad| is five words long; the fifth word is the |left_delimiter|
 16337  // field, which usually represents a square root sign.
 16338  //
 16339  // A |fraction_noad| is six words long; it has a |right_delimiter| field
 16340  // as well as a |left_delimiter|.
 16341  //
 16342  // Delimiter fields are of type |four_quarters|, and they have four subfields
 16343  // called |small_fam|, |small_char|, |large_fam|, |large_char|. These subfields
 16344  // represent variable-size delimiters by giving the ``small'' and ``large''
 16345  // starting characters, as explained in Chapter~17 of [\sl The \TeX book].
 16346  // \xref[TeXbook][\sl The \TeX book]
 16347  //
 16348  // A |fraction_noad| is actually quite different from all other noads. Not
 16349  // only does it have six words, it has |thickness|, |denominator|, and
 16350  // |numerator| fields instead of |nucleus|, |subscr|, and |supscr|. The
 16351  // |thickness| is a scaled value that tells how thick to make a fraction
 16352  // rule; however, the special value |default_code| is used to stand for the
 16353  // |default_rule_thickness| of the current size. The |numerator| and
 16354  // |denominator| point to mlists that define a fraction; we always have
 16355  // $$\hbox[|math_type(numerator)=math_type(denominator)=sub_mlist|].$$ The
 16356  // |left_delimiter| and |right_delimiter| fields specify delimiters that will
 16357  // be placed at the left and right of the fraction. In this way, a
 16358  // |fraction_noad| is able to represent all of \TeX's operators \.[\\over],
 16359  // \.[\\atop], \.[\\above], \.[\\overwithdelims], \.[\\atopwithdelims], and
 16360  //  \.[\\abovewithdelims].
 16361  
 16362  // 686.
 16363  
 16364  // tangle:pos tex.web:13511:1:
 16365  
 16366  // The |new_noad| function creates an |ord_noad| that is completely null.
 16367  func (prg *prg) newNoad() (r halfword) {
 16368  	var (
 16369  		p halfword
 16370  	)
 16371  	p = prg.getNode(noadSize)
 16372  	*(*prg.mem[p].hh()).b0() = byte(ordNoad)
 16373  	*(*prg.mem[p].hh()).b1() = byte(normal)
 16374  	*prg.mem[int32(p)+1].hh() = prg.emptyField
 16375  	*prg.mem[int32(p)+3].hh() = prg.emptyField
 16376  	*prg.mem[int32(p)+2].hh() = prg.emptyField
 16377  	r = p
 16378  	return r
 16379  }
 16380  
 16381  // 687.
 16382  
 16383  // tangle:pos tex.web:13523:1:
 16384  
 16385  // A few more kinds of noads will complete the set: An |under_noad| has its
 16386  // nucleus underlined; an |over_noad| has it overlined. An |accent_noad| places
 16387  // an accent over its nucleus; the accent character appears as
 16388  // |fam(accent_chr(p))| and |character(accent_chr(p))|. A |vcenter_noad|
 16389  // centers its nucleus vertically with respect to the axis of the formula;
 16390  // in such noads we always have |math_type(nucleus(p))=sub_box|.
 16391  //
 16392  // And finally, we have |left_noad| and |right_noad| types, to implement
 16393  // \TeX's \.[\\left] and \.[\\right]. The |nucleus| of such noads is
 16394  // replaced by a |delimiter| field; thus, for example, `\.[\\left(]' produces
 16395  // a |left_noad| such that |delimiter(p)| holds the family and character
 16396  // codes for all left parentheses. A |left_noad| never appears in an mlist
 16397  // except as the first element, and a |right_noad| never appears in an mlist
 16398  // except as the last element; furthermore, we either have both a |left_noad|
 16399  // and a |right_noad|, or neither one is present. The |subscr| and |supscr|
 16400  // fields are always |empty| in a |left_noad| and a |right_noad|.
 16401  
 16402  // 688.
 16403  
 16404  // tangle:pos tex.web:13551:1:
 16405  
 16406  // Math formulas can also contain instructions like \.[\\textstyle] that
 16407  // override \TeX's normal style rules. A |style_node| is inserted into the
 16408  // data structure to record such instructions; it is three words long, so it
 16409  // is considered a node instead of a noad. The |subtype| is either |display_style|
 16410  // or |text_style| or |script_style| or |script_script_style|. The
 16411  // second and third words of a |style_node| are not used, but they are
 16412  // present because a |choice_node| is converted to a |style_node|.
 16413  //
 16414  // \TeX\ uses even numbers 0, 2, 4, 6 to encode the basic styles
 16415  // |display_style|, \dots, |script_script_style|, and adds~1 to get the
 16416  // ``cramped'' versions of these styles. This gives a numerical order that
 16417  // is backwards from the convention of Appendix~G in [\sl The \TeX book\/];
 16418  // i.e., a smaller style has a larger numerical value.
 16419  // \xref[TeXbook][\sl The \TeX book]
 16420  func (prg *prg) newStyle(s smallNumber) (r halfword) { // create a style node
 16421  	var (
 16422  		p halfword // the new node
 16423  	)
 16424  	p = prg.getNode(styleNodeSize)
 16425  	*(*prg.mem[p].hh()).b0() = byte(styleNode)
 16426  	*(*prg.mem[p].hh()).b1() = s
 16427  	*prg.mem[int32(p)+widthOffset].int() = 0
 16428  	*prg.mem[int32(p)+depthOffset].int() = 0 // the |width| and |depth| are not used
 16429  	r = p
 16430  	return r
 16431  }
 16432  
 16433  // 689.
 16434  
 16435  // tangle:pos tex.web:13581:1:
 16436  
 16437  // Finally, the \.[\\mathchoice] primitive creates a |choice_node|, which
 16438  // has special subfields |display_mlist|, |text_mlist|, |script_mlist|,
 16439  // and |script_script_mlist| pointing to the mlists for each style.
 16440  func (prg *prg) newChoice() (r halfword) { // create a choice node
 16441  	var (
 16442  		p halfword // the new node
 16443  	)
 16444  	p = prg.getNode(styleNodeSize)
 16445  	*(*prg.mem[p].hh()).b0() = byte(choiceNode)
 16446  	*(*prg.mem[p].hh()).b1() = 0 // the |subtype| is not used
 16447  	*(*prg.mem[int32(p)+1].hh()).lh() = 0
 16448  	*(*prg.mem[int32(p)+1].hh()).rh() = 0
 16449  	*(*prg.mem[int32(p)+2].hh()).lh() = 0
 16450  	*(*prg.mem[int32(p)+2].hh()).rh() = 0
 16451  	r = p
 16452  	return r
 16453  }
 16454  
 16455  func (prg *prg) showInfo() {
 16456  	prg.showNodeList(int32(*(*prg.mem[prg.tempPtr].hh()).lh()))
 16457  }
 16458  
 16459  // 700.
 16460  
 16461  // tangle:pos tex.web:13804:1:
 16462  
 16463  // Before an mlist is converted to an hlist, \TeX\ makes sure that
 16464  // the fonts in family~2 have enough parameters to be math-symbol
 16465  // fonts, and that the fonts in family~3 have enough parameters to be
 16466  // math-extension fonts. The math-symbol parameters are referred to by using the
 16467  // following macros, which take a size code as their parameter; for example,
 16468  // |num1(cur_size)| gives the value of the |num1| parameter for the current size.
 16469  // \xref[parameters for symbols]
 16470  // \xref[font parameters]
 16471  
 16472  // 701.
 16473  
 16474  // tangle:pos tex.web:13835:1:
 16475  
 16476  // The math-extension parameters have similar macros, but the size code is
 16477  // omitted (since it is always |cur_size| when we refer to such parameters).
 16478  // \xref[parameters for symbols]
 16479  // \xref[font parameters]
 16480  
 16481  // 702.
 16482  
 16483  // tangle:pos tex.web:13849:1:
 16484  
 16485  // We also need to compute the change in style between mlists and their
 16486  // subsidiaries. The following macros define the subsidiary style for
 16487  // an overlined nucleus (|cramped_style|), for a subscript or a superscript
 16488  // (|sub_style| or |sup_style|), or for a numerator or denominator (|num_style|
 16489  // or |denom_style|).
 16490  
 16491  // 704.
 16492  
 16493  // tangle:pos tex.web:13870:1:
 16494  
 16495  // Here is a function that returns a pointer to a rule node having a given
 16496  // thickness |t|. The rule will extend horizontally to the boundary of the vlist
 16497  // that eventually contains it.
 16498  func (prg *prg) fractionRule(t scaled) (r halfword) {
 16499  	// construct the bar for a fraction
 16500  	var (
 16501  		p halfword // the new node
 16502  	)
 16503  	p = prg.newRule()
 16504  	*prg.mem[int32(p)+heightOffset].int() = t
 16505  	*prg.mem[int32(p)+depthOffset].int() = 0
 16506  	r = p
 16507  	return r
 16508  }
 16509  
 16510  // 705.
 16511  
 16512  // tangle:pos tex.web:13880:1:
 16513  
 16514  // The |overbar| function returns a pointer to a vlist box that consists of
 16515  // a given box |b|, above which has been placed a kern of height |k| under a
 16516  // fraction rule of thickness |t| under additional space of height |t|.
 16517  func (prg *prg) overbar(b halfword, k, t scaled) (r halfword) {
 16518  	var (
 16519  		p, q halfword // nodes being constructed
 16520  	)
 16521  	p = prg.newKern(k)
 16522  	*(*prg.mem[p].hh()).rh() = b
 16523  	q = prg.fractionRule(t)
 16524  	*(*prg.mem[q].hh()).rh() = p
 16525  	p = prg.newKern(t)
 16526  	*(*prg.mem[p].hh()).rh() = q
 16527  	r = prg.vpackage(p, scaled(0), smallNumber(additional), scaled(07777777777))
 16528  	return r
 16529  }
 16530  
 16531  // 706.
 16532  
 16533  // tangle:pos tex.web:13890:1:
 16534  
 16535  // The |var_delimiter| function, which finds or constructs a sufficiently
 16536  // large delimiter, is the most interesting of the auxiliary functions that
 16537  // currently concern us. Given a pointer |d| to a delimiter field in some noad,
 16538  // together with a size code |s| and a vertical distance |v|, this function
 16539  // returns a pointer to a box that contains the smallest variant of |d| whose
 16540  // height plus depth is |v| or more. (And if no variant is large enough, it
 16541  // returns the largest available variant.) In particular, this routine will
 16542  // construct arbitrarily large delimiters from extensible components, if
 16543  // |d| leads to such characters.
 16544  //
 16545  // The value returned is a box whose |shift_amount| has been set so that
 16546  // the box is vertically centered with respect to the axis in the given size.
 16547  // If a built-up symbol is returned, the height of the box before shifting
 16548  // will be the height of its topmost component.
 16549  // \4
 16550  // Declare subprocedures for |var_delimiter|
 16551  func (prg *prg) charBox(f internalFontNumber, c quarterword) (r halfword) {
 16552  	var (
 16553  		q    fourQuarters
 16554  		hd   eightBits // |height_depth| byte
 16555  		b, p halfword  // the new box and its character node
 16556  	)
 16557  	q = *prg.fontInfo[prg.charBase[f]+int32(c)].qqqq()
 16558  	hd = byte(int32(q.b1) - minQuarterword)
 16559  	b = prg.newNullBox()
 16560  	*prg.mem[int32(b)+widthOffset].int() = *prg.fontInfo[prg.widthBase[f]+int32(q.b0)].int() + *prg.fontInfo[prg.italicBase[f]+(int32(q.b2)-minQuarterword)/4].int()
 16561  	*prg.mem[int32(b)+heightOffset].int() = *prg.fontInfo[prg.heightBase[f]+int32(hd)/16].int()
 16562  	*prg.mem[int32(b)+depthOffset].int() = *prg.fontInfo[prg.depthBase[f]+int32(hd)%16].int()
 16563  	p = prg.getAvail()
 16564  	*(*prg.mem[p].hh()).b1() = c
 16565  	*(*prg.mem[p].hh()).b0() = f
 16566  	*(*prg.mem[int32(b)+listOffset].hh()).rh() = p
 16567  	r = b
 16568  	return r
 16569  }
 16570  
 16571  func (prg *prg) stackIntoBox(b halfword, f internalFontNumber,
 16572  	c quarterword) {
 16573  	var (
 16574  		p halfword // new node placed into |b|
 16575  	)
 16576  	p = prg.charBox(f, c)
 16577  	*(*prg.mem[p].hh()).rh() = *(*prg.mem[int32(b)+listOffset].hh()).rh()
 16578  	*(*prg.mem[int32(b)+listOffset].hh()).rh() = p
 16579  	*prg.mem[int32(b)+heightOffset].int() = *prg.mem[int32(p)+heightOffset].int()
 16580  }
 16581  
 16582  func (prg *prg) heightPlusDepth(f internalFontNumber, c quarterword) (r scaled) {
 16583  	var (
 16584  		q  fourQuarters
 16585  		hd eightBits // |height_depth| byte
 16586  	)
 16587  	q = *prg.fontInfo[prg.charBase[f]+int32(c)].qqqq()
 16588  	hd = byte(int32(q.b1) - minQuarterword)
 16589  	r = *prg.fontInfo[prg.heightBase[f]+int32(hd)/16].int() + *prg.fontInfo[prg.depthBase[f]+int32(hd)%16].int()
 16590  	return r
 16591  }
 16592  
 16593  func (prg *prg) varDelimiter(d halfword, s smallNumber, v scaled) (r halfword) {
 16594  	var (
 16595  		b            halfword           // the box that will be constructed
 16596  		f, g         internalFontNumber // best-so-far and tentative font codes
 16597  		c, x, y      quarterword        // best-so-far and tentative character codes
 16598  		m, n         int32              // the number of extensible pieces
 16599  		u            scaled             // height-plus-depth of a tentative character
 16600  		w            scaled             // largest height-plus-depth so far
 16601  		q            fourQuarters       // character info
 16602  		hd           eightBits          // height-depth byte
 16603  		r1           fourQuarters       // extensible pieces
 16604  		z            smallNumber        // runs through font family members
 16605  		largeAttempt bool               // are we trying the ``large'' variant?
 16606  	)
 16607  	f = byte(fontBase)
 16608  	w = 0
 16609  	largeAttempt = false
 16610  	z = (*prg.mem[d].qqqq()).b0
 16611  	x = (*prg.mem[d].qqqq()).b1
 16612  	for true {
 16613  		if int32(z) != 0 || int32(x) != minQuarterword {
 16614  			z = byte(int32(z) + int32(s) + 16)
 16615  			for {
 16616  				z = byte(int32(z) - 16)
 16617  				g = byte(*(*prg.eqtb[mathFontBase+int32(z)-1].hh()).rh())
 16618  				if int32(g) != fontBase {
 16619  					y = x
 16620  					if int32(y)-minQuarterword >= int32(prg.fontBc[g]) && int32(y)-minQuarterword <= int32(prg.fontEc[g]) {
 16621  					continue1:
 16622  						q = *prg.fontInfo[prg.charBase[g]+int32(y)].qqqq()
 16623  						if int32(q.b0) > minQuarterword {
 16624  							if (int32(q.b2)-minQuarterword)%4 == extTag {
 16625  								f = g
 16626  								c = y
 16627  								goto found
 16628  							}
 16629  							hd = byte(int32(q.b1) - minQuarterword)
 16630  							u = *prg.fontInfo[prg.heightBase[g]+int32(hd)/16].int() + *prg.fontInfo[prg.depthBase[g]+int32(hd)%16].int()
 16631  							if u > w {
 16632  								f = g
 16633  								c = y
 16634  								w = u
 16635  								if u >= v {
 16636  									goto found
 16637  								}
 16638  							}
 16639  							if (int32(q.b2)-minQuarterword)%4 == listTag {
 16640  								y = q.b3
 16641  								goto continue1
 16642  							}
 16643  						}
 16644  					}
 16645  				}
 16646  				if int32(z) < 16 {
 16647  					break
 16648  				}
 16649  			}
 16650  		}
 16651  		if largeAttempt {
 16652  			goto found
 16653  		} // there were none large enough
 16654  		largeAttempt = true
 16655  		z = (*prg.mem[d].qqqq()).b2
 16656  		x = (*prg.mem[d].qqqq()).b3
 16657  	}
 16658  
 16659  found:
 16660  	if int32(f) != fontBase {
 16661  		if (int32(q.b2)-minQuarterword)%4 == extTag {
 16662  			b = prg.newNullBox()
 16663  			*(*prg.mem[b].hh()).b0() = byte(vlistNode)
 16664  			r1 = *prg.fontInfo[prg.extenBase[f]+int32(q.b3)].qqqq()
 16665  
 16666  			// Compute the minimum suitable height, |w|, and the corresponding number of extension steps, |n|; also set |width(b)|
 16667  			c = r1.b3
 16668  			u = prg.heightPlusDepth(f, c)
 16669  			w = 0
 16670  			q = *prg.fontInfo[prg.charBase[f]+int32(c)].qqqq()
 16671  			*prg.mem[int32(b)+widthOffset].int() = *prg.fontInfo[prg.widthBase[f]+int32(q.b0)].int() + *prg.fontInfo[prg.italicBase[f]+(int32(q.b2)-minQuarterword)/4].int()
 16672  
 16673  			c = r1.b2
 16674  			if int32(c) != minQuarterword {
 16675  				w = w + prg.heightPlusDepth(f, c)
 16676  			}
 16677  			c = r1.b1
 16678  			if int32(c) != minQuarterword {
 16679  				w = w + prg.heightPlusDepth(f, c)
 16680  			}
 16681  			c = r1.b0
 16682  			if int32(c) != minQuarterword {
 16683  				w = w + prg.heightPlusDepth(f, c)
 16684  			}
 16685  			n = 0
 16686  			if u > 0 {
 16687  				for w < v {
 16688  					w = w + u
 16689  					n = n + 1
 16690  					if int32(r1.b1) != minQuarterword {
 16691  						w = w + u
 16692  					}
 16693  				}
 16694  			}
 16695  			c = r1.b2
 16696  			if int32(c) != minQuarterword {
 16697  				prg.stackIntoBox(b, f, c)
 16698  			}
 16699  			c = r1.b3
 16700  			for ii := int32(1); ii <= n; ii++ {
 16701  				m = ii
 16702  				_ = m
 16703  				prg.stackIntoBox(b, f, c)
 16704  			}
 16705  			c = r1.b1
 16706  			if int32(c) != minQuarterword {
 16707  				prg.stackIntoBox(b, f, c)
 16708  				c = r1.b3
 16709  				for ii := int32(1); ii <= n; ii++ {
 16710  					m = ii
 16711  					_ = m
 16712  					prg.stackIntoBox(b, f, c)
 16713  				}
 16714  			}
 16715  			c = r1.b0
 16716  			if int32(c) != minQuarterword {
 16717  				prg.stackIntoBox(b, f, c)
 16718  			}
 16719  			*prg.mem[int32(b)+depthOffset].int() = w - *prg.mem[int32(b)+heightOffset].int()
 16720  		} else {
 16721  			b = prg.charBox(f, c)
 16722  		}
 16723  	} else {
 16724  		b = prg.newNullBox()
 16725  		*prg.mem[int32(b)+widthOffset].int() = *prg.eqtb[dimenBase+nullDelimiterSpaceCode-1].int() // use this width if no delimiter was found
 16726  	}
 16727  	*prg.mem[int32(b)+4].int() = prg.half(*prg.mem[int32(b)+heightOffset].int()-*prg.mem[int32(b)+depthOffset].int()) - *prg.fontInfo[22+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(s)-1].hh()).rh()]].int()
 16728  	r = b
 16729  	return r
 16730  }
 16731  
 16732  // 715.
 16733  
 16734  // tangle:pos tex.web:14059:1:
 16735  
 16736  // The next subroutine is much simpler; it is used for numerators and
 16737  // denominators of fractions as well as for displayed operators and
 16738  // their limits above and below. It takes a given box~|b| and
 16739  // changes it so that the new box is centered in a box of width~|w|.
 16740  // The centering is done by putting \.[\\hss] glue at the left and right
 16741  // of the list inside |b|, then packaging the new box; thus, the
 16742  // actual box might not really be centered, if it already contains
 16743  // infinite glue.
 16744  //
 16745  // The given box might contain a single character whose italic correction
 16746  // has been added to the width of the box; in this case a compensating
 16747  // kern is inserted.
 16748  func (prg *prg) rebox(b halfword, w scaled) (r halfword) {
 16749  	var (
 16750  		p halfword           // temporary register for list manipulation
 16751  		f internalFontNumber // font in a one-character box
 16752  		v scaled             // width of a character without italic correction
 16753  	)
 16754  	if *prg.mem[int32(b)+widthOffset].int() != w && int32(*(*prg.mem[int32(b)+listOffset].hh()).rh()) != 0 {
 16755  		if int32(*(*prg.mem[b].hh()).b0()) == vlistNode {
 16756  			b = prg.hpack(b, scaled(0), smallNumber(additional))
 16757  		}
 16758  		p = *(*prg.mem[int32(b)+listOffset].hh()).rh()
 16759  		if int32(p) >= int32(prg.hiMemMin) && int32(*(*prg.mem[p].hh()).rh()) == 0 {
 16760  			f = *(*prg.mem[p].hh()).b0()
 16761  			v = *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[p].hh()).b1())].qqqq()).b0)].int()
 16762  			if v != *prg.mem[int32(b)+widthOffset].int() {
 16763  				*(*prg.mem[p].hh()).rh() = prg.newKern(*prg.mem[int32(b)+widthOffset].int() - v)
 16764  			}
 16765  		}
 16766  		prg.freeNode(b, halfword(boxNodeSize))
 16767  		b = prg.newGlue(halfword(memBot + glueSpecSize + glueSpecSize + glueSpecSize))
 16768  		*(*prg.mem[b].hh()).rh() = p
 16769  		for int32(*(*prg.mem[p].hh()).rh()) != 0 {
 16770  			p = *(*prg.mem[p].hh()).rh()
 16771  		}
 16772  		*(*prg.mem[p].hh()).rh() = prg.newGlue(halfword(memBot + glueSpecSize + glueSpecSize + glueSpecSize))
 16773  		r = prg.hpack(b, w, smallNumber(exactly))
 16774  	} else {
 16775  		*prg.mem[int32(b)+widthOffset].int() = w
 16776  		r = b
 16777  	}
 16778  	return r
 16779  }
 16780  
 16781  // 716.
 16782  
 16783  // tangle:pos tex.web:14093:1:
 16784  
 16785  // Here is a subroutine that creates a new glue specification from another
 16786  // one that is expressed in `\.[mu]', given the value of the math unit.
 16787  func (prg *prg) mathGlue(g halfword, m scaled) (r halfword) {
 16788  	var (
 16789  		p halfword // the new glue specification
 16790  		n int32    // integer part of |m|
 16791  		f scaled   // fraction part of |m|
 16792  	)
 16793  	n = prg.xOverN(m, 0200000)
 16794  	f = prg.remainder
 16795  
 16796  	if f < 0 {
 16797  		n = n - 1
 16798  		f = f + 0200000
 16799  	}
 16800  	p = prg.getNode(glueSpecSize)
 16801  	*prg.mem[int32(p)+widthOffset].int() = prg.multAndAdd(n, *prg.mem[int32(g)+widthOffset].int(), prg.xnOverD(*prg.mem[int32(g)+widthOffset].int(), f, 0200000), scaled(07777777777)) // convert \.[mu] to \.[pt]
 16802  	*(*prg.mem[p].hh()).b0() = *(*prg.mem[g].hh()).b0()
 16803  	if int32(*(*prg.mem[p].hh()).b0()) == normal {
 16804  		*prg.mem[int32(p)+2].int() = prg.multAndAdd(n, *prg.mem[int32(g)+2].int(), prg.xnOverD(*prg.mem[int32(g)+2].int(), f, 0200000), scaled(07777777777))
 16805  	} else {
 16806  		*prg.mem[int32(p)+2].int() = *prg.mem[int32(g)+2].int()
 16807  	}
 16808  	*(*prg.mem[p].hh()).b1() = *(*prg.mem[g].hh()).b1()
 16809  	if int32(*(*prg.mem[p].hh()).b1()) == normal {
 16810  		*prg.mem[int32(p)+3].int() = prg.multAndAdd(n, *prg.mem[int32(g)+3].int(), prg.xnOverD(*prg.mem[int32(g)+3].int(), f, 0200000), scaled(07777777777))
 16811  	} else {
 16812  		*prg.mem[int32(p)+3].int() = *prg.mem[int32(g)+3].int()
 16813  	}
 16814  	r = p
 16815  	return r
 16816  }
 16817  
 16818  // 717.
 16819  
 16820  // tangle:pos tex.web:14117:1:
 16821  
 16822  // The |math_kern| subroutine removes |mu_glue| from a kern node, given
 16823  // the value of the math unit.
 16824  func (prg *prg) mathKern(p halfword, m scaled) {
 16825  	var (
 16826  		n int32  // integer part of |m|
 16827  		f scaled // fraction part of |m|
 16828  	)
 16829  	if int32(*(*prg.mem[p].hh()).b1()) == muGlue {
 16830  		n = prg.xOverN(m, 0200000)
 16831  		f = prg.remainder
 16832  
 16833  		if f < 0 {
 16834  			n = n - 1
 16835  			f = f + 0200000
 16836  		}
 16837  		*prg.mem[int32(p)+widthOffset].int() = prg.multAndAdd(n, *prg.mem[int32(p)+widthOffset].int(), prg.xnOverD(*prg.mem[int32(p)+widthOffset].int(), f, 0200000), scaled(07777777777))
 16838  		*(*prg.mem[p].hh()).b1() = byte(explicit)
 16839  	}
 16840  }
 16841  
 16842  // 718.
 16843  
 16844  // tangle:pos tex.web:14132:1:
 16845  
 16846  // Sometimes it is necessary to destroy an mlist. The following
 16847  // subroutine empties the current list, assuming that |abs(mode)=mmode|.
 16848  func (prg *prg) flushMath() {
 16849  	prg.flushNodeList(*(*prg.mem[prg.curList.headField].hh()).rh())
 16850  	prg.flushNodeList(halfword(*prg.curList.auxField.int()))
 16851  	*(*prg.mem[prg.curList.headField].hh()).rh() = 0
 16852  	prg.curList.tailField = prg.curList.headField
 16853  	*prg.curList.auxField.int() = 0
 16854  } // \2
 16855  
 16856  func (prg *prg) cleanBox(p halfword, s smallNumber) (r halfword) {
 16857  	var (
 16858  		q         halfword    // beginning of a list to be boxed
 16859  		saveStyle smallNumber // |cur_style| to be restored
 16860  		x         halfword    // box to be returned
 16861  		r1        halfword    // temporary pointer
 16862  	)
 16863  	switch *(*prg.mem[p].hh()).rh() {
 16864  	case mathChar:
 16865  		prg.curMlist = prg.newNoad()
 16866  		prg.mem[int32(prg.curMlist)+1] = prg.mem[p]
 16867  
 16868  	case subBox:
 16869  		q = *(*prg.mem[p].hh()).lh()
 16870  		goto found
 16871  
 16872  	case subMlist:
 16873  		prg.curMlist = *(*prg.mem[p].hh()).lh()
 16874  
 16875  	default:
 16876  		q = prg.newNullBox()
 16877  		goto found
 16878  
 16879  	}
 16880  
 16881  	saveStyle = prg.curStyle
 16882  	prg.curStyle = s
 16883  	prg.mlistPenalties = false
 16884  
 16885  	prg.mlistToHlist()
 16886  	q = *(*prg.mem[30000-3].hh()).rh() // recursive call
 16887  	prg.curStyle = saveStyle           // restore the style
 16888  
 16889  	// Set up the values of |cur_size| and |cur_mu|, based on |cur_style|
 16890  	{
 16891  		if int32(prg.curStyle) < scriptStyle {
 16892  			prg.curSize = byte(textSize)
 16893  		} else {
 16894  			prg.curSize = byte(16 * ((int32(prg.curStyle) - textStyle) / 2))
 16895  		}
 16896  		prg.curMu = prg.xOverN(*prg.fontInfo[6+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int(), 18)
 16897  	}
 16898  
 16899  found:
 16900  	if int32(q) >= int32(prg.hiMemMin) || int32(q) == 0 {
 16901  		x = prg.hpack(q, scaled(0), smallNumber(additional))
 16902  	} else if int32(*(*prg.mem[q].hh()).rh()) == 0 && int32(*(*prg.mem[q].hh()).b0()) <= vlistNode && *prg.mem[int32(q)+4].int() == 0 {
 16903  		x = q
 16904  	} else {
 16905  		x = prg.hpack(q, scaled(0), smallNumber(additional))
 16906  	}
 16907  
 16908  	// Simplify a trivial box
 16909  	q = *(*prg.mem[int32(x)+listOffset].hh()).rh()
 16910  	if int32(q) >= int32(prg.hiMemMin) {
 16911  		r1 = *(*prg.mem[q].hh()).rh()
 16912  		if int32(r1) != 0 {
 16913  			if int32(*(*prg.mem[r1].hh()).rh()) == 0 {
 16914  				if !(int32(r1) >= int32(prg.hiMemMin)) {
 16915  					if int32(*(*prg.mem[r1].hh()).b0()) == kernNode {
 16916  						prg.freeNode(r1, halfword(smallNodeSize))
 16917  						*(*prg.mem[q].hh()).rh() = 0
 16918  					}
 16919  				}
 16920  			}
 16921  		}
 16922  	}
 16923  	r = x
 16924  	return r
 16925  }
 16926  
 16927  // 722.
 16928  
 16929  // tangle:pos tex.web:14212:1:
 16930  
 16931  // It is convenient to have a procedure that converts a |math_char|
 16932  // field to an ``unpacked'' form. The |fetch| routine sets |cur_f|, |cur_c|,
 16933  // and |cur_i| to the font code, character code, and character information bytes of
 16934  // a given noad field. It also takes care of issuing error messages for
 16935  // nonexistent characters; in such cases, |char_exists(cur_i)| will be |false|
 16936  // after |fetch| has acted, and the field will also have been reset to |empty|.
 16937  func (prg *prg) fetch(a halfword) {
 16938  	prg.curC = *(*prg.mem[a].hh()).b1()
 16939  	prg.curF = byte(*(*prg.eqtb[mathFontBase+int32(*(*prg.mem[a].hh()).b0())+int32(prg.curSize)-1].hh()).rh())
 16940  	if int32(prg.curF) == fontBase {
 16941  		{
 16942  			if int32(prg.interaction) == errorStopMode {
 16943  			}
 16944  			prg.printNl(strNumber( /* "! " */ 262))
 16945  			prg.print( /* "" */ 338)
 16946  		}
 16947  		prg.printSize(int32(prg.curSize))
 16948  		prg.printChar(asciiCode(' '))
 16949  		prg.printInt(int32(*(*prg.mem[a].hh()).b0()))
 16950  		prg.print( /* " is undefined (character " */ 884)
 16951  		prg.print(int32(prg.curC) - minQuarterword)
 16952  		prg.printChar(asciiCode(')'))
 16953  		{
 16954  			prg.helpPtr = 4
 16955  			prg.helpLine[3] = /* "Somewhere in the math formula just ended, you used the" */ 885
 16956  			prg.helpLine[2] = /* "stated character from an undefined font family. For example," */ 886
 16957  			prg.helpLine[1] = /* "plain TeX doesn't allow \\it or \\sl in subscripts. Proceed," */ 887
 16958  			prg.helpLine[0] = /* "and I'll try to forget that I needed that character." */ 888
 16959  		}
 16960  		prg.error1()
 16961  		prg.curI = prg.nullCharacter
 16962  		*(*prg.mem[a].hh()).rh() = uint16(empty)
 16963  	} else {
 16964  		if int32(prg.curC)-minQuarterword >= int32(prg.fontBc[prg.curF]) && int32(prg.curC)-minQuarterword <= int32(prg.fontEc[prg.curF]) {
 16965  			prg.curI = *prg.fontInfo[prg.charBase[prg.curF]+int32(prg.curC)].qqqq()
 16966  		} else {
 16967  			prg.curI = prg.nullCharacter
 16968  		}
 16969  		if !(int32(prg.curI.b0) > minQuarterword) {
 16970  			prg.charWarning(prg.curF, eightBits(int32(prg.curC)-minQuarterword))
 16971  			*(*prg.mem[a].hh()).rh() = uint16(empty)
 16972  			prg.curI = prg.nullCharacter
 16973  		}
 16974  	}
 16975  }
 16976  
 16977  // 725.
 16978  
 16979  // tangle:pos tex.web:14252:1:
 16980  
 16981  // We need to do a lot of different things, so |mlist_to_hlist| makes two
 16982  // passes over the given mlist.
 16983  //
 16984  // The first pass does most of the processing: It removes ``mu'' spacing from
 16985  // glue, it recursively evaluates all subsidiary mlists so that only the
 16986  // top-level mlist remains to be handled, it puts fractions and square roots
 16987  // and such things into boxes, it attaches subscripts and superscripts, and
 16988  // it computes the overall height and depth of the top-level mlist so that
 16989  // the size of delimiters for a |left_noad| and a |right_noad| will be known.
 16990  // The hlist resulting from each noad is recorded in that noad's |new_hlist|
 16991  // field, an integer field that replaces the |nucleus| or |thickness|.
 16992  // \xref[recursion]
 16993  //
 16994  // The second pass eliminates all noads and inserts the correct glue and
 16995  // penalties between nodes.
 16996  
 16997  // 726.
 16998  
 16999  // tangle:pos tex.web:14270:1:
 17000  
 17001  // Here is the overall plan of |mlist_to_hlist|, and the list of its
 17002  // local variables.
 17003  // \4
 17004  // Declare math construction procedures
 17005  func (prg *prg) makeOver(q halfword) {
 17006  	*(*prg.mem[int32(q)+1].hh()).lh() = prg.overbar(prg.cleanBox(halfword(int32(q)+1), smallNumber(2*(int32(prg.curStyle)/2)+cramped)),
 17007  		3**prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int(), *prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int())
 17008  	*(*prg.mem[int32(q)+1].hh()).rh() = uint16(subBox)
 17009  }
 17010  
 17011  func (prg *prg) makeUnder(q halfword) {
 17012  	var (
 17013  		p, x, y halfword // temporary registers for box construction
 17014  		delta   scaled   // overall height plus depth
 17015  	)
 17016  	x = prg.cleanBox(halfword(int32(q)+1), prg.curStyle)
 17017  	p = prg.newKern(3 * *prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int())
 17018  	*(*prg.mem[x].hh()).rh() = p
 17019  	*(*prg.mem[p].hh()).rh() = prg.fractionRule(*prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int())
 17020  	y = prg.vpackage(x, scaled(0), smallNumber(additional), scaled(07777777777))
 17021  	delta = *prg.mem[int32(y)+heightOffset].int() + *prg.mem[int32(y)+depthOffset].int() + *prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int()
 17022  	*prg.mem[int32(y)+heightOffset].int() = *prg.mem[int32(x)+heightOffset].int()
 17023  	*prg.mem[int32(y)+depthOffset].int() = delta - *prg.mem[int32(y)+heightOffset].int()
 17024  	*(*prg.mem[int32(q)+1].hh()).lh() = y
 17025  	*(*prg.mem[int32(q)+1].hh()).rh() = uint16(subBox)
 17026  }
 17027  
 17028  func (prg *prg) makeVcenter(q halfword) {
 17029  	var (
 17030  		v     halfword // the box that should be centered vertically
 17031  		delta scaled   // its height plus depth
 17032  	)
 17033  	v = *(*prg.mem[int32(q)+1].hh()).lh()
 17034  	if int32(*(*prg.mem[v].hh()).b0()) != vlistNode {
 17035  		prg.confusion(strNumber( /* "vcenter" */ 539))
 17036  	}
 17037  	// \xref[this can't happen vcenter][\quad vcenter]
 17038  	delta = *prg.mem[int32(v)+heightOffset].int() + *prg.mem[int32(v)+depthOffset].int()
 17039  	*prg.mem[int32(v)+heightOffset].int() = *prg.fontInfo[22+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int() + prg.half(delta)
 17040  	*prg.mem[int32(v)+depthOffset].int() = delta - *prg.mem[int32(v)+heightOffset].int()
 17041  }
 17042  
 17043  func (prg *prg) makeRadical(q halfword) {
 17044  	var (
 17045  		x, y       halfword // temporary registers for box construction
 17046  		delta, clr scaled   // dimensions involved in the calculation
 17047  	)
 17048  	x = prg.cleanBox(halfword(int32(q)+1), smallNumber(2*(int32(prg.curStyle)/2)+cramped))
 17049  	if int32(prg.curStyle) < textStyle {
 17050  		clr = *prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int() + abs(*prg.fontInfo[5+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int())/4
 17051  	} else {
 17052  		clr = *prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int()
 17053  		clr = clr + abs(clr)/4
 17054  	}
 17055  	y = prg.varDelimiter(halfword(int32(q)+4), prg.curSize, *prg.mem[int32(x)+heightOffset].int()+*prg.mem[int32(x)+depthOffset].int()+clr+*prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int())
 17056  	delta = *prg.mem[int32(y)+depthOffset].int() - (*prg.mem[int32(x)+heightOffset].int() + *prg.mem[int32(x)+depthOffset].int() + clr)
 17057  	if delta > 0 {
 17058  		clr = clr + prg.half(delta)
 17059  	} // increase the actual clearance
 17060  	*prg.mem[int32(y)+4].int() = -(*prg.mem[int32(x)+heightOffset].int() + clr)
 17061  	*(*prg.mem[y].hh()).rh() = prg.overbar(x, clr, *prg.mem[int32(y)+heightOffset].int())
 17062  	*(*prg.mem[int32(q)+1].hh()).lh() = prg.hpack(y, scaled(0), smallNumber(additional))
 17063  	*(*prg.mem[int32(q)+1].hh()).rh() = uint16(subBox)
 17064  }
 17065  
 17066  func (prg *prg) makeMathAccent(q halfword) {
 17067  	var (
 17068  		p, x, y halfword           // temporary registers for box construction
 17069  		a       int32              // address of lig/kern instruction
 17070  		c       quarterword        // accent character
 17071  		f       internalFontNumber // its font
 17072  		i       fourQuarters       // its |char_info|
 17073  		s       scaled             // amount to skew the accent to the right
 17074  		h       scaled             // height of character being accented
 17075  		delta   scaled             // space to remove between accent and accentee
 17076  		w       scaled             // width of the accentee, not including sub/superscripts
 17077  	)
 17078  	prg.fetch(halfword(int32(q) + 4))
 17079  	if int32(prg.curI.b0) > minQuarterword {
 17080  		i = prg.curI
 17081  		c = prg.curC
 17082  		f = prg.curF
 17083  
 17084  		// Compute the amount of skew
 17085  		s = 0
 17086  		if int32(*(*prg.mem[int32(q)+1].hh()).rh()) == mathChar {
 17087  			prg.fetch(halfword(int32(q) + 1))
 17088  			if (int32(prg.curI.b2)-minQuarterword)%4 == ligTag {
 17089  				a = prg.ligKernBase[prg.curF] + int32(prg.curI.b3)
 17090  				prg.curI = *prg.fontInfo[a].qqqq()
 17091  				if int32(prg.curI.b0) > 128+minQuarterword {
 17092  					a = prg.ligKernBase[prg.curF] + 256*int32(prg.curI.b2) + int32(prg.curI.b3) + 32768 - 256*(128+minQuarterword)
 17093  					prg.curI = *prg.fontInfo[a].qqqq()
 17094  				}
 17095  				for true {
 17096  					if int32(prg.curI.b1)-minQuarterword == prg.skewChar[prg.curF] {
 17097  						if int32(prg.curI.b2) >= 128+minQuarterword {
 17098  							if int32(prg.curI.b0) <= 128+minQuarterword {
 17099  								s = *prg.fontInfo[prg.kernBase[prg.curF]+256*int32(prg.curI.b2)+int32(prg.curI.b3)].int()
 17100  							}
 17101  						}
 17102  
 17103  						goto done1
 17104  					}
 17105  					if int32(prg.curI.b0) >= 128+minQuarterword {
 17106  						goto done1
 17107  					}
 17108  					a = a + int32(prg.curI.b0) - minQuarterword + 1
 17109  					prg.curI = *prg.fontInfo[a].qqqq()
 17110  				}
 17111  			}
 17112  		}
 17113  
 17114  	done1:
 17115  		;
 17116  		x = prg.cleanBox(halfword(int32(q)+1), smallNumber(2*(int32(prg.curStyle)/2)+cramped))
 17117  		w = *prg.mem[int32(x)+widthOffset].int()
 17118  		h = *prg.mem[int32(x)+heightOffset].int()
 17119  
 17120  		// Switch to a larger accent if available and appropriate
 17121  		for true {
 17122  			if (int32(i.b2)-minQuarterword)%4 != listTag {
 17123  				goto done
 17124  			}
 17125  			y = uint16(i.b3)
 17126  			i = *prg.fontInfo[prg.charBase[f]+int32(y)].qqqq()
 17127  			if !(int32(i.b0) > minQuarterword) {
 17128  				goto done
 17129  			}
 17130  			if *prg.fontInfo[prg.widthBase[f]+int32(i.b0)].int() > w {
 17131  				goto done
 17132  			}
 17133  			c = byte(y)
 17134  		}
 17135  
 17136  	done:
 17137  		;
 17138  		if h < *prg.fontInfo[xHeightCode+prg.paramBase[f]].int() {
 17139  			delta = h
 17140  		} else {
 17141  			delta = *prg.fontInfo[xHeightCode+prg.paramBase[f]].int()
 17142  		}
 17143  		if int32(*(*prg.mem[int32(q)+2].hh()).rh()) != empty || int32(*(*prg.mem[int32(q)+3].hh()).rh()) != empty {
 17144  			if int32(*(*prg.mem[int32(q)+1].hh()).rh()) == mathChar {
 17145  				prg.flushNodeList(x)
 17146  				x = prg.newNoad()
 17147  				prg.mem[int32(x)+1] = prg.mem[int32(q)+1]
 17148  				prg.mem[int32(x)+2] = prg.mem[int32(q)+2]
 17149  				prg.mem[int32(x)+3] = prg.mem[int32(q)+3]
 17150  
 17151  				*prg.mem[int32(q)+2].hh() = prg.emptyField
 17152  				*prg.mem[int32(q)+3].hh() = prg.emptyField
 17153  
 17154  				*(*prg.mem[int32(q)+1].hh()).rh() = uint16(subMlist)
 17155  				*(*prg.mem[int32(q)+1].hh()).lh() = x
 17156  				x = prg.cleanBox(halfword(int32(q)+1), prg.curStyle)
 17157  				delta = delta + *prg.mem[int32(x)+heightOffset].int() - h
 17158  				h = *prg.mem[int32(x)+heightOffset].int()
 17159  			}
 17160  		}
 17161  		y = prg.charBox(f, c)
 17162  		*prg.mem[int32(y)+4].int() = s + prg.half(w-*prg.mem[int32(y)+widthOffset].int())
 17163  		*prg.mem[int32(y)+widthOffset].int() = 0
 17164  		p = prg.newKern(-delta)
 17165  		*(*prg.mem[p].hh()).rh() = x
 17166  		*(*prg.mem[y].hh()).rh() = p
 17167  		y = prg.vpackage(y, scaled(0), smallNumber(additional), scaled(07777777777))
 17168  		*prg.mem[int32(y)+widthOffset].int() = *prg.mem[int32(x)+widthOffset].int()
 17169  		if *prg.mem[int32(y)+heightOffset].int() < h {
 17170  			p = prg.newKern(h - *prg.mem[int32(y)+heightOffset].int())
 17171  			*(*prg.mem[p].hh()).rh() = *(*prg.mem[int32(y)+listOffset].hh()).rh()
 17172  			*(*prg.mem[int32(y)+listOffset].hh()).rh() = p
 17173  			*prg.mem[int32(y)+heightOffset].int() = h
 17174  		}
 17175  		*(*prg.mem[int32(q)+1].hh()).lh() = y
 17176  		*(*prg.mem[int32(q)+1].hh()).rh() = uint16(subBox)
 17177  	}
 17178  }
 17179  
 17180  func (prg *prg) makeFraction(q halfword) {
 17181  	var (
 17182  		p, v, x, y, z                                  halfword // temporary registers for box construction
 17183  		delta, delta1, delta2, shiftUp, shiftDown, clr scaled
 17184  	// dimensions for box calculations
 17185  	)
 17186  	if *prg.mem[int32(q)+widthOffset].int() == 010000000000 {
 17187  		*prg.mem[int32(q)+widthOffset].int() = *prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int()
 17188  	}
 17189  
 17190  	// Create equal-width boxes |x| and |z| for the numerator and denominator, and compute the default amounts |shift_up| and |shift_down| by which they are displaced from the baseline
 17191  	x = prg.cleanBox(halfword(int32(q)+2), smallNumber(int32(prg.curStyle)+2-2*(int32(prg.curStyle)/6)))
 17192  	z = prg.cleanBox(halfword(int32(q)+3), smallNumber(2*(int32(prg.curStyle)/2)+cramped+2-2*(int32(prg.curStyle)/6)))
 17193  	if *prg.mem[int32(x)+widthOffset].int() < *prg.mem[int32(z)+widthOffset].int() {
 17194  		x = prg.rebox(x, *prg.mem[int32(z)+widthOffset].int())
 17195  	} else {
 17196  		z = prg.rebox(z, *prg.mem[int32(x)+widthOffset].int())
 17197  	}
 17198  	if int32(prg.curStyle) < textStyle {
 17199  		shiftUp = *prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
 17200  		shiftDown = *prg.fontInfo[11+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
 17201  	} else {
 17202  		shiftDown = *prg.fontInfo[12+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
 17203  		if *prg.mem[int32(q)+widthOffset].int() != 0 {
 17204  			shiftUp = *prg.fontInfo[9+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
 17205  		} else {
 17206  			shiftUp = *prg.fontInfo[10+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
 17207  		}
 17208  	}
 17209  	if *prg.mem[int32(q)+widthOffset].int() == 0 {
 17210  		if int32(prg.curStyle) < textStyle {
 17211  			clr = 7 * *prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int()
 17212  		} else {
 17213  			clr = 3 * *prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int()
 17214  		}
 17215  		delta = prg.half(clr - (shiftUp - *prg.mem[int32(x)+depthOffset].int() - (*prg.mem[int32(z)+heightOffset].int() - shiftDown)))
 17216  		if delta > 0 {
 17217  			shiftUp = shiftUp + delta
 17218  			shiftDown = shiftDown + delta
 17219  		}
 17220  	} else {
 17221  		// Adjust \(s)|shift_up| and |shift_down| for the case of a fraction line
 17222  		if int32(prg.curStyle) < textStyle {
 17223  			clr = 3 * *prg.mem[int32(q)+widthOffset].int()
 17224  		} else {
 17225  			clr = *prg.mem[int32(q)+widthOffset].int()
 17226  		}
 17227  		delta = prg.half(*prg.mem[int32(q)+widthOffset].int())
 17228  		delta1 = clr - (shiftUp - *prg.mem[int32(x)+depthOffset].int() - (*prg.fontInfo[22+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int() + delta))
 17229  		delta2 = clr - (*prg.fontInfo[22+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int() - delta - (*prg.mem[int32(z)+heightOffset].int() - shiftDown))
 17230  		if delta1 > 0 {
 17231  			shiftUp = shiftUp + delta1
 17232  		}
 17233  		if delta2 > 0 {
 17234  			shiftDown = shiftDown + delta2
 17235  		}
 17236  	}
 17237  
 17238  	// Construct a vlist box for the fraction, according to |shift_up| and |shift_down|
 17239  	v = prg.newNullBox()
 17240  	*(*prg.mem[v].hh()).b0() = byte(vlistNode)
 17241  	*prg.mem[int32(v)+heightOffset].int() = shiftUp + *prg.mem[int32(x)+heightOffset].int()
 17242  	*prg.mem[int32(v)+depthOffset].int() = *prg.mem[int32(z)+depthOffset].int() + shiftDown
 17243  	*prg.mem[int32(v)+widthOffset].int() = *prg.mem[int32(x)+widthOffset].int() // this also equals |width(z)|
 17244  	if *prg.mem[int32(q)+widthOffset].int() == 0 {
 17245  		p = prg.newKern(shiftUp - *prg.mem[int32(x)+depthOffset].int() - (*prg.mem[int32(z)+heightOffset].int() - shiftDown))
 17246  		*(*prg.mem[p].hh()).rh() = z
 17247  	} else {
 17248  		y = prg.fractionRule(*prg.mem[int32(q)+widthOffset].int())
 17249  
 17250  		p = prg.newKern(*prg.fontInfo[22+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int() - delta - (*prg.mem[int32(z)+heightOffset].int() - shiftDown))
 17251  
 17252  		*(*prg.mem[y].hh()).rh() = p
 17253  		*(*prg.mem[p].hh()).rh() = z
 17254  
 17255  		p = prg.newKern(shiftUp - *prg.mem[int32(x)+depthOffset].int() - (*prg.fontInfo[22+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int() + delta))
 17256  		*(*prg.mem[p].hh()).rh() = y
 17257  	}
 17258  	*(*prg.mem[x].hh()).rh() = p
 17259  	*(*prg.mem[int32(v)+listOffset].hh()).rh() = x
 17260  
 17261  	// Put the \(f)fraction into a box with its delimiters, and make |new_hlist(q)| point to it
 17262  	if int32(prg.curStyle) < textStyle {
 17263  		delta = *prg.fontInfo[20+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
 17264  	} else {
 17265  		delta = *prg.fontInfo[21+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
 17266  	}
 17267  	x = prg.varDelimiter(halfword(int32(q)+4), prg.curSize, delta)
 17268  	*(*prg.mem[x].hh()).rh() = v
 17269  
 17270  	z = prg.varDelimiter(halfword(int32(q)+5), prg.curSize, delta)
 17271  	*(*prg.mem[v].hh()).rh() = z
 17272  
 17273  	*prg.mem[int32(q)+1].int() = int32(prg.hpack(x, scaled(0), smallNumber(additional)))
 17274  }
 17275  
 17276  func (prg *prg) makeOp(q halfword) (r scaled) {
 17277  	var (
 17278  		delta              scaled   // offset between subscript and superscript
 17279  		p, v, x, y, z      halfword // temporary registers for box construction
 17280  		c                  quarterword
 17281  		i                  fourQuarters // registers for character examination
 17282  		shiftUp, shiftDown scaled       // dimensions for box calculation
 17283  	)
 17284  	if int32(*(*prg.mem[q].hh()).b1()) == normal && int32(prg.curStyle) < textStyle {
 17285  		*(*prg.mem[q].hh()).b1() = byte(limits)
 17286  	}
 17287  	if int32(*(*prg.mem[int32(q)+1].hh()).rh()) == mathChar {
 17288  		prg.fetch(halfword(int32(q) + 1))
 17289  		if int32(prg.curStyle) < textStyle && (int32(prg.curI.b2)-minQuarterword)%4 == listTag {
 17290  			c = prg.curI.b3
 17291  			i = *prg.fontInfo[prg.charBase[prg.curF]+int32(c)].qqqq()
 17292  			if int32(i.b0) > minQuarterword {
 17293  				prg.curC = c
 17294  				prg.curI = i
 17295  				*(*prg.mem[int32(q)+1].hh()).b1() = c
 17296  			}
 17297  		}
 17298  		delta = *prg.fontInfo[prg.italicBase[prg.curF]+(int32(prg.curI.b2)-minQuarterword)/4].int()
 17299  		x = prg.cleanBox(halfword(int32(q)+1), prg.curStyle)
 17300  		if int32(*(*prg.mem[int32(q)+3].hh()).rh()) != empty && int32(*(*prg.mem[q].hh()).b1()) != limits {
 17301  			*prg.mem[int32(x)+widthOffset].int() = *prg.mem[int32(x)+widthOffset].int() - delta
 17302  		} // remove italic correction
 17303  		*prg.mem[int32(x)+4].int() = prg.half(*prg.mem[int32(x)+heightOffset].int()-*prg.mem[int32(x)+depthOffset].int()) - *prg.fontInfo[22+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
 17304  		// center vertically
 17305  		*(*prg.mem[int32(q)+1].hh()).rh() = uint16(subBox)
 17306  		*(*prg.mem[int32(q)+1].hh()).lh() = x
 17307  	} else {
 17308  		delta = 0
 17309  	}
 17310  	if int32(*(*prg.mem[q].hh()).b1()) == limits {
 17311  		x = prg.cleanBox(halfword(int32(q)+2), smallNumber(2*(int32(prg.curStyle)/4)+scriptStyle+int32(prg.curStyle)%2))
 17312  		y = prg.cleanBox(halfword(int32(q)+1), prg.curStyle)
 17313  		z = prg.cleanBox(halfword(int32(q)+3), smallNumber(2*(int32(prg.curStyle)/4)+scriptStyle+cramped))
 17314  		v = prg.newNullBox()
 17315  		*(*prg.mem[v].hh()).b0() = byte(vlistNode)
 17316  		*prg.mem[int32(v)+widthOffset].int() = *prg.mem[int32(y)+widthOffset].int()
 17317  		if *prg.mem[int32(x)+widthOffset].int() > *prg.mem[int32(v)+widthOffset].int() {
 17318  			*prg.mem[int32(v)+widthOffset].int() = *prg.mem[int32(x)+widthOffset].int()
 17319  		}
 17320  		if *prg.mem[int32(z)+widthOffset].int() > *prg.mem[int32(v)+widthOffset].int() {
 17321  			*prg.mem[int32(v)+widthOffset].int() = *prg.mem[int32(z)+widthOffset].int()
 17322  		}
 17323  		x = prg.rebox(x, *prg.mem[int32(v)+widthOffset].int())
 17324  		y = prg.rebox(y, *prg.mem[int32(v)+widthOffset].int())
 17325  		z = prg.rebox(z, *prg.mem[int32(v)+widthOffset].int())
 17326  
 17327  		*prg.mem[int32(x)+4].int() = prg.half(delta)
 17328  		*prg.mem[int32(z)+4].int() = -*prg.mem[int32(x)+4].int()
 17329  		*prg.mem[int32(v)+heightOffset].int() = *prg.mem[int32(y)+heightOffset].int()
 17330  		*prg.mem[int32(v)+depthOffset].int() = *prg.mem[int32(y)+depthOffset].int()
 17331  
 17332  		// Attach the limits to |y| and adjust |height(v)|, |depth(v)| to account for their presence
 17333  		if int32(*(*prg.mem[int32(q)+2].hh()).rh()) == empty {
 17334  			prg.freeNode(x, halfword(boxNodeSize))
 17335  			*(*prg.mem[int32(v)+listOffset].hh()).rh() = y
 17336  		} else {
 17337  			shiftUp = *prg.fontInfo[11+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int() - *prg.mem[int32(x)+depthOffset].int()
 17338  			if shiftUp < *prg.fontInfo[9+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int() {
 17339  				shiftUp = *prg.fontInfo[9+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int()
 17340  			}
 17341  			p = prg.newKern(shiftUp)
 17342  			*(*prg.mem[p].hh()).rh() = y
 17343  			*(*prg.mem[x].hh()).rh() = p
 17344  
 17345  			p = prg.newKern(*prg.fontInfo[13+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int())
 17346  			*(*prg.mem[p].hh()).rh() = x
 17347  			*(*prg.mem[int32(v)+listOffset].hh()).rh() = p
 17348  			*prg.mem[int32(v)+heightOffset].int() = *prg.mem[int32(v)+heightOffset].int() + *prg.fontInfo[13+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int() + *prg.mem[int32(x)+heightOffset].int() + *prg.mem[int32(x)+depthOffset].int() + shiftUp
 17349  		}
 17350  		if int32(*(*prg.mem[int32(q)+3].hh()).rh()) == empty {
 17351  			prg.freeNode(z, halfword(boxNodeSize))
 17352  		} else {
 17353  			shiftDown = *prg.fontInfo[12+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int() - *prg.mem[int32(z)+heightOffset].int()
 17354  			if shiftDown < *prg.fontInfo[10+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int() {
 17355  				shiftDown = *prg.fontInfo[10+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int()
 17356  			}
 17357  			p = prg.newKern(shiftDown)
 17358  			*(*prg.mem[y].hh()).rh() = p
 17359  			*(*prg.mem[p].hh()).rh() = z
 17360  
 17361  			p = prg.newKern(*prg.fontInfo[13+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int())
 17362  			*(*prg.mem[z].hh()).rh() = p
 17363  			*prg.mem[int32(v)+depthOffset].int() = *prg.mem[int32(v)+depthOffset].int() + *prg.fontInfo[13+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int() + *prg.mem[int32(z)+heightOffset].int() + *prg.mem[int32(z)+depthOffset].int() + shiftDown
 17364  		}
 17365  		*prg.mem[int32(q)+1].int() = int32(v)
 17366  	}
 17367  	r = delta
 17368  	return r
 17369  }
 17370  
 17371  func (prg *prg) makeOrd(q halfword) {
 17372  	var (
 17373  		a     int32    // address of lig/kern instruction
 17374  		p, r1 halfword // temporary registers for list manipulation
 17375  	)
 17376  restart:
 17377  	if int32(*(*prg.mem[int32(q)+3].hh()).rh()) == empty {
 17378  		if int32(*(*prg.mem[int32(q)+2].hh()).rh()) == empty {
 17379  			if int32(*(*prg.mem[int32(q)+1].hh()).rh()) == mathChar {
 17380  				p = *(*prg.mem[q].hh()).rh()
 17381  				if int32(p) != 0 {
 17382  					if int32(*(*prg.mem[p].hh()).b0()) >= ordNoad && int32(*(*prg.mem[p].hh()).b0()) <= punctNoad {
 17383  						if int32(*(*prg.mem[int32(p)+1].hh()).rh()) == mathChar {
 17384  							if int32(*(*prg.mem[int32(p)+1].hh()).b0()) == int32(*(*prg.mem[int32(q)+1].hh()).b0()) {
 17385  								*(*prg.mem[int32(q)+1].hh()).rh() = uint16(mathTextChar)
 17386  								prg.fetch(halfword(int32(q) + 1))
 17387  								if (int32(prg.curI.b2)-minQuarterword)%4 == ligTag {
 17388  									a = prg.ligKernBase[prg.curF] + int32(prg.curI.b3)
 17389  									prg.curC = *(*prg.mem[int32(p)+1].hh()).b1()
 17390  									prg.curI = *prg.fontInfo[a].qqqq()
 17391  									if int32(prg.curI.b0) > 128+minQuarterword {
 17392  										a = prg.ligKernBase[prg.curF] + 256*int32(prg.curI.b2) + int32(prg.curI.b3) + 32768 - 256*(128+minQuarterword)
 17393  										prg.curI = *prg.fontInfo[a].qqqq()
 17394  									}
 17395  									for true {
 17396  										if int32(prg.curI.b1) == int32(prg.curC) {
 17397  											if int32(prg.curI.b0) <= 128+minQuarterword {
 17398  												if int32(prg.curI.b2) >= 128+minQuarterword {
 17399  													p = prg.newKern(*prg.fontInfo[prg.kernBase[prg.curF]+256*int32(prg.curI.b2)+int32(prg.curI.b3)].int())
 17400  													*(*prg.mem[p].hh()).rh() = *(*prg.mem[q].hh()).rh()
 17401  													*(*prg.mem[q].hh()).rh() = p
 17402  													goto exit
 17403  												} else {
 17404  													{
 17405  														if prg.interrupt != 0 {
 17406  															prg.pauseForInstructions()
 17407  														}
 17408  													} // allow a way out of infinite ligature loop
 17409  													switch prg.curI.b2 {
 17410  													case 1 + minQuarterword, 5 + minQuarterword:
 17411  														*(*prg.mem[int32(q)+1].hh()).b1() = prg.curI.b3 // \.[=:\?], \.[=:\?>]
 17412  													case 2 + minQuarterword, 6 + minQuarterword:
 17413  														*(*prg.mem[int32(p)+1].hh()).b1() = prg.curI.b3 // \.[\?=:], \.[\?=:>]
 17414  													case 3 + minQuarterword, 7 + minQuarterword, 11 + minQuarterword:
 17415  														r1 = prg.newNoad() // \.[\?=:\?], \.[\?=:\?>], \.[\?=:\?>>]
 17416  														*(*prg.mem[int32(r1)+1].hh()).b1() = prg.curI.b3
 17417  														*(*prg.mem[int32(r1)+1].hh()).b0() = *(*prg.mem[int32(q)+1].hh()).b0()
 17418  
 17419  														*(*prg.mem[q].hh()).rh() = r1
 17420  														*(*prg.mem[r1].hh()).rh() = p
 17421  														if int32(prg.curI.b2) < 11+minQuarterword {
 17422  															*(*prg.mem[int32(r1)+1].hh()).rh() = uint16(mathChar)
 17423  														} else {
 17424  															*(*prg.mem[int32(r1)+1].hh()).rh() = uint16(mathTextChar)
 17425  														} // prevent combination
 17426  
 17427  													default:
 17428  														*(*prg.mem[q].hh()).rh() = *(*prg.mem[p].hh()).rh()
 17429  														*(*prg.mem[int32(q)+1].hh()).b1() = prg.curI.b3 // \.[=:]
 17430  														prg.mem[int32(q)+3] = prg.mem[int32(p)+3]
 17431  														prg.mem[int32(q)+2] = prg.mem[int32(p)+2]
 17432  
 17433  														prg.freeNode(p, halfword(noadSize))
 17434  
 17435  													}
 17436  													if int32(prg.curI.b2) > 3+minQuarterword {
 17437  														goto exit
 17438  													}
 17439  													*(*prg.mem[int32(q)+1].hh()).rh() = uint16(mathChar)
 17440  													goto restart
 17441  												}
 17442  											}
 17443  										}
 17444  										if int32(prg.curI.b0) >= 128+minQuarterword {
 17445  											goto exit
 17446  										}
 17447  										a = a + int32(prg.curI.b0) - minQuarterword + 1
 17448  										prg.curI = *prg.fontInfo[a].qqqq()
 17449  									}
 17450  								}
 17451  							}
 17452  						}
 17453  					}
 17454  				}
 17455  			}
 17456  		}
 17457  	}
 17458  
 17459  exit:
 17460  }
 17461  
 17462  func (prg *prg) makeScripts(q halfword, delta scaled) {
 17463  	var (
 17464  		p, x, y, z              halfword    // temporary registers for box construction
 17465  		shiftUp, shiftDown, clr scaled      // dimensions in the calculation
 17466  		t                       smallNumber // subsidiary size code
 17467  	)
 17468  	p = uint16(*prg.mem[int32(q)+1].int())
 17469  	if int32(p) >= int32(prg.hiMemMin) {
 17470  		shiftUp = 0
 17471  		shiftDown = 0
 17472  	} else {
 17473  		z = prg.hpack(p, scaled(0), smallNumber(additional))
 17474  		if int32(prg.curStyle) < scriptStyle {
 17475  			t = byte(scriptSize)
 17476  		} else {
 17477  			t = byte(scriptScriptSize)
 17478  		}
 17479  		shiftUp = *prg.mem[int32(z)+heightOffset].int() - *prg.fontInfo[18+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(t)-1].hh()).rh()]].int()
 17480  		shiftDown = *prg.mem[int32(z)+depthOffset].int() + *prg.fontInfo[19+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(t)-1].hh()).rh()]].int()
 17481  		prg.freeNode(z, halfword(boxNodeSize))
 17482  	}
 17483  	if int32(*(*prg.mem[int32(q)+2].hh()).rh()) == empty {
 17484  		x = prg.cleanBox(halfword(int32(q)+3), smallNumber(2*(int32(prg.curStyle)/4)+scriptStyle+cramped))
 17485  		*prg.mem[int32(x)+widthOffset].int() = *prg.mem[int32(x)+widthOffset].int() + *prg.eqtb[dimenBase+scriptSpaceCode-1].int()
 17486  		if shiftDown < *prg.fontInfo[16+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int() {
 17487  			shiftDown = *prg.fontInfo[16+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
 17488  		}
 17489  		clr = *prg.mem[int32(x)+heightOffset].int() - abs(*prg.fontInfo[5+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()*4)/5
 17490  		if shiftDown < clr {
 17491  			shiftDown = clr
 17492  		}
 17493  		*prg.mem[int32(x)+4].int() = shiftDown
 17494  	} else {
 17495  		{
 17496  			x = prg.cleanBox(halfword(int32(q)+2), smallNumber(2*(int32(prg.curStyle)/4)+scriptStyle+int32(prg.curStyle)%2))
 17497  			*prg.mem[int32(x)+widthOffset].int() = *prg.mem[int32(x)+widthOffset].int() + *prg.eqtb[dimenBase+scriptSpaceCode-1].int()
 17498  			if prg.curStyle&1 != 0 {
 17499  				clr = *prg.fontInfo[15+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
 17500  			} else if int32(prg.curStyle) < textStyle {
 17501  				clr = *prg.fontInfo[13+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
 17502  			} else {
 17503  				clr = *prg.fontInfo[14+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
 17504  			}
 17505  			if shiftUp < clr {
 17506  				shiftUp = clr
 17507  			}
 17508  			clr = *prg.mem[int32(x)+depthOffset].int() + abs(*prg.fontInfo[5+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int())/4
 17509  			if shiftUp < clr {
 17510  				shiftUp = clr
 17511  			}
 17512  		}
 17513  		if int32(*(*prg.mem[int32(q)+3].hh()).rh()) == empty {
 17514  			*prg.mem[int32(x)+4].int() = -shiftUp
 17515  		} else {
 17516  			// Construct a sub/superscript combination box |x|, with the superscript offset by |delta|
 17517  			y = prg.cleanBox(halfword(int32(q)+3), smallNumber(2*(int32(prg.curStyle)/4)+scriptStyle+cramped))
 17518  			*prg.mem[int32(y)+widthOffset].int() = *prg.mem[int32(y)+widthOffset].int() + *prg.eqtb[dimenBase+scriptSpaceCode-1].int()
 17519  			if shiftDown < *prg.fontInfo[17+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int() {
 17520  				shiftDown = *prg.fontInfo[17+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
 17521  			}
 17522  			clr = 4**prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int() - (shiftUp - *prg.mem[int32(x)+depthOffset].int() - (*prg.mem[int32(y)+heightOffset].int() - shiftDown))
 17523  			if clr > 0 {
 17524  				shiftDown = shiftDown + clr
 17525  				clr = abs(*prg.fontInfo[5+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()*4)/5 - (shiftUp - *prg.mem[int32(x)+depthOffset].int())
 17526  				if clr > 0 {
 17527  					shiftUp = shiftUp + clr
 17528  					shiftDown = shiftDown - clr
 17529  				}
 17530  			}
 17531  			*prg.mem[int32(x)+4].int() = delta // superscript is |delta| to the right of the subscript
 17532  			p = prg.newKern(shiftUp - *prg.mem[int32(x)+depthOffset].int() - (*prg.mem[int32(y)+heightOffset].int() - shiftDown))
 17533  			*(*prg.mem[x].hh()).rh() = p
 17534  			*(*prg.mem[p].hh()).rh() = y
 17535  			x = prg.vpackage(x, scaled(0), smallNumber(additional), scaled(07777777777))
 17536  			*prg.mem[int32(x)+4].int() = shiftDown
 17537  		}
 17538  	}
 17539  	if *prg.mem[int32(q)+1].int() == 0 {
 17540  		*prg.mem[int32(q)+1].int() = int32(x)
 17541  	} else {
 17542  		p = uint16(*prg.mem[int32(q)+1].int())
 17543  		for int32(*(*prg.mem[p].hh()).rh()) != 0 {
 17544  			p = *(*prg.mem[p].hh()).rh()
 17545  		}
 17546  		*(*prg.mem[p].hh()).rh() = x
 17547  	}
 17548  }
 17549  
 17550  func (prg *prg) makeLeftRight(q halfword, style smallNumber,
 17551  	maxD, maxH scaled) (r smallNumber) {
 17552  	var (
 17553  		delta, delta1, delta2 scaled // dimensions used in the calculation
 17554  	)
 17555  	if int32(style) < scriptStyle {
 17556  		prg.curSize = byte(textSize)
 17557  	} else {
 17558  		prg.curSize = byte(16 * ((int32(style) - textStyle) / 2))
 17559  	}
 17560  	delta2 = maxD + *prg.fontInfo[22+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
 17561  	delta1 = maxH + maxD - delta2
 17562  	if delta2 > delta1 {
 17563  		delta1 = delta2
 17564  	} // |delta1| is max distance from axis
 17565  	delta = delta1 / 500 * *prg.eqtb[intBase+delimiterFactorCode-1].int()
 17566  	delta2 = delta1 + delta1 - *prg.eqtb[dimenBase+delimiterShortfallCode-1].int()
 17567  	if delta < delta2 {
 17568  		delta = delta2
 17569  	}
 17570  	*prg.mem[int32(q)+1].int() = int32(prg.varDelimiter(halfword(int32(q)+1), prg.curSize, delta))
 17571  	r = byte(int32(*(*prg.mem[q].hh()).b0()) - (leftNoad - openNoad)) // |open_noad| or |close_noad|
 17572  	return r
 17573  }
 17574  
 17575  // 720.
 17576  
 17577  // tangle:pos tex.web:14163:1:
 17578  
 17579  // The recursion in |mlist_to_hlist| is due primarily to a subroutine
 17580  // called |clean_box| that puts a given noad field into a box using a given
 17581  // math style; |mlist_to_hlist| can call |clean_box|, which can call
 17582  // |mlist_to_hlist|.
 17583  // \xref[recursion]
 17584  //
 17585  // The box returned by |clean_box| is ``clean'' in the
 17586  // sense that its |shift_amount| is zero.
 17587  func (prg *prg) mlistToHlist() {
 17588  	var (
 17589  		mlist      halfword    // beginning of the given list
 17590  		penalties  bool        // should penalty nodes be inserted?
 17591  		style      smallNumber // the given style
 17592  		saveStyle  smallNumber // holds |cur_style| during recursion
 17593  		q          halfword    // runs through the mlist
 17594  		r1         halfword    // the most recent noad preceding |q|
 17595  		rType      smallNumber // the |type| of noad |r|, or |op_noad| if |r=null|
 17596  		t          smallNumber // the effective |type| of noad |q| during the second pass
 17597  		p, x, y, z halfword    // temporary registers for list construction
 17598  		pen        int32       // a penalty to be inserted
 17599  		s          smallNumber // the size of a noad to be deleted
 17600  		maxH, maxD scaled      // maximum height and depth of the list translated so far
 17601  		delta      scaled      // offset between subscript and superscript
 17602  	)
 17603  	mlist = prg.curMlist
 17604  	penalties = prg.mlistPenalties
 17605  	style = prg.curStyle // tuck global parameters away as local variables
 17606  	q = mlist
 17607  	r1 = 0
 17608  	rType = byte(opNoad)
 17609  	maxH = 0
 17610  	maxD = 0
 17611  
 17612  	// Set up the values of |cur_size| and |cur_mu|, based on |cur_style|
 17613  	{
 17614  		if int32(prg.curStyle) < scriptStyle {
 17615  			prg.curSize = byte(textSize)
 17616  		} else {
 17617  			prg.curSize = byte(16 * ((int32(prg.curStyle) - textStyle) / 2))
 17618  		}
 17619  		prg.curMu = prg.xOverN(*prg.fontInfo[6+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int(), 18)
 17620  	}
 17621  	for int32(q) != 0 {
 17622  		// Process node-or-noad |q| as much as possible in preparation for the second pass of |mlist_to_hlist|, then move to the next item in the mlist
 17623  
 17624  		// Do first-pass processing based on |type(q)|; |goto done_with_noad| if a noad has been fully processed, |goto check_dimensions| if it has been translated into |new_hlist(q)|, or |goto done_with_node| if a node has been fully processed
 17625  	reswitch:
 17626  		delta = 0
 17627  		switch *(*prg.mem[q].hh()).b0() {
 17628  		case binNoad:
 17629  			switch rType {
 17630  			case binNoad, opNoad, relNoad, openNoad,
 17631  				punctNoad, leftNoad:
 17632  				*(*prg.mem[q].hh()).b0() = byte(ordNoad)
 17633  				goto reswitch
 17634  
 17635  			default:
 17636  			}
 17637  		case relNoad, closeNoad, punctNoad, rightNoad:
 17638  			if int32(rType) == binNoad {
 17639  				*(*prg.mem[r1].hh()).b0() = byte(ordNoad)
 17640  			}
 17641  			if int32(*(*prg.mem[q].hh()).b0()) == rightNoad {
 17642  				goto doneWithNoad
 17643  			}
 17644  
 17645  		// \4
 17646  		// Cases for noads that can follow a |bin_noad|
 17647  		case leftNoad:
 17648  			goto doneWithNoad
 17649  		case fractionNoad:
 17650  			prg.makeFraction(q)
 17651  			goto checkDimensions
 17652  
 17653  		case opNoad:
 17654  			delta = prg.makeOp(q)
 17655  			if int32(*(*prg.mem[q].hh()).b1()) == limits {
 17656  				goto checkDimensions
 17657  			}
 17658  
 17659  		case ordNoad:
 17660  			prg.makeOrd(q)
 17661  		case openNoad, innerNoad:
 17662  		case radicalNoad:
 17663  			prg.makeRadical(q)
 17664  		case overNoad:
 17665  			prg.makeOver(q)
 17666  		case underNoad:
 17667  			prg.makeUnder(q)
 17668  		case accentNoad:
 17669  			prg.makeMathAccent(q)
 17670  		case vcenterNoad:
 17671  			prg.makeVcenter(q)
 17672  
 17673  		// \4
 17674  		// Cases for nodes that can appear in an mlist, after which we |goto done_with_node|
 17675  		case styleNode:
 17676  			prg.curStyle = *(*prg.mem[q].hh()).b1()
 17677  
 17678  			// Set up the values of |cur_size| and |cur_mu|, based on |cur_style|
 17679  			{
 17680  				if int32(prg.curStyle) < scriptStyle {
 17681  					prg.curSize = byte(textSize)
 17682  				} else {
 17683  					prg.curSize = byte(16 * ((int32(prg.curStyle) - textStyle) / 2))
 17684  				}
 17685  				prg.curMu = prg.xOverN(*prg.fontInfo[6+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int(), 18)
 17686  			}
 17687  
 17688  			goto doneWithNode
 17689  
 17690  		case choiceNode:
 17691  			// Change this node to a style node followed by the correct choice, then |goto done_with_node|
 17692  			switch int32(prg.curStyle) / 2 {
 17693  			case 0:
 17694  				p = *(*prg.mem[int32(q)+1].hh()).lh()
 17695  				*(*prg.mem[int32(q)+1].hh()).lh() = 0 // |display_style=0|
 17696  			case 1:
 17697  				p = *(*prg.mem[int32(q)+1].hh()).rh()
 17698  				*(*prg.mem[int32(q)+1].hh()).rh() = 0 // |text_style=2|
 17699  			case 2:
 17700  				p = *(*prg.mem[int32(q)+2].hh()).lh()
 17701  				*(*prg.mem[int32(q)+2].hh()).lh() = 0 // |script_style=4|
 17702  			case 3:
 17703  				p = *(*prg.mem[int32(q)+2].hh()).rh()
 17704  				*(*prg.mem[int32(q)+2].hh()).rh() = 0 // |script_script_style=6|
 17705  			} // there are no other cases
 17706  			prg.flushNodeList(*(*prg.mem[int32(q)+1].hh()).lh())
 17707  			prg.flushNodeList(*(*prg.mem[int32(q)+1].hh()).rh())
 17708  			prg.flushNodeList(*(*prg.mem[int32(q)+2].hh()).lh())
 17709  			prg.flushNodeList(*(*prg.mem[int32(q)+2].hh()).rh())
 17710  
 17711  			*(*prg.mem[q].hh()).b0() = byte(styleNode)
 17712  			*(*prg.mem[q].hh()).b1() = prg.curStyle
 17713  			*prg.mem[int32(q)+widthOffset].int() = 0
 17714  			*prg.mem[int32(q)+depthOffset].int() = 0
 17715  			if int32(p) != 0 {
 17716  				z = *(*prg.mem[q].hh()).rh()
 17717  				*(*prg.mem[q].hh()).rh() = p
 17718  				for int32(*(*prg.mem[p].hh()).rh()) != 0 {
 17719  					p = *(*prg.mem[p].hh()).rh()
 17720  				}
 17721  				*(*prg.mem[p].hh()).rh() = z
 17722  			}
 17723  
 17724  			goto doneWithNode
 17725  
 17726  		case insNode, markNode, adjustNode, whatsitNode,
 17727  			penaltyNode, discNode:
 17728  			goto doneWithNode
 17729  		case ruleNode:
 17730  			if *prg.mem[int32(q)+heightOffset].int() > maxH {
 17731  				maxH = *prg.mem[int32(q)+heightOffset].int()
 17732  			}
 17733  			if *prg.mem[int32(q)+depthOffset].int() > maxD {
 17734  				maxD = *prg.mem[int32(q)+depthOffset].int()
 17735  			}
 17736  			goto doneWithNode
 17737  
 17738  		case glueNode:
 17739  			if int32(*(*prg.mem[q].hh()).b1()) == muGlue {
 17740  				x = *(*prg.mem[int32(q)+1].hh()).lh()
 17741  				y = prg.mathGlue(x, prg.curMu)
 17742  				prg.deleteGlueRef(x)
 17743  				*(*prg.mem[int32(q)+1].hh()).lh() = y
 17744  				*(*prg.mem[q].hh()).b1() = byte(normal)
 17745  			} else if int32(prg.curSize) != textSize && int32(*(*prg.mem[q].hh()).b1()) == condMathGlue {
 17746  				p = *(*prg.mem[q].hh()).rh()
 17747  				if int32(p) != 0 {
 17748  					if int32(*(*prg.mem[p].hh()).b0()) == glueNode || int32(*(*prg.mem[p].hh()).b0()) == kernNode {
 17749  						*(*prg.mem[q].hh()).rh() = *(*prg.mem[p].hh()).rh()
 17750  						*(*prg.mem[p].hh()).rh() = 0
 17751  						prg.flushNodeList(p)
 17752  					}
 17753  				}
 17754  			}
 17755  
 17756  			goto doneWithNode
 17757  
 17758  		case kernNode:
 17759  			prg.mathKern(q, prg.curMu)
 17760  			goto doneWithNode
 17761  
 17762  		default:
 17763  			prg.confusion(strNumber( /* "mlist1" */ 889))
 17764  			// \xref[this can't happen mlist1][\quad mlist1]
 17765  		}
 17766  
 17767  		// Convert \(n)|nucleus(q)| to an hlist and attach the sub/superscripts
 17768  		switch *(*prg.mem[int32(q)+1].hh()).rh() {
 17769  		case mathChar, mathTextChar:
 17770  
 17771  			// Create a character node |p| for |nucleus(q)|, possibly followed by a kern node for the italic correction, and set |delta| to the italic correction if a subscript is present
 17772  			prg.fetch(halfword(int32(q) + 1))
 17773  			if int32(prg.curI.b0) > minQuarterword {
 17774  				delta = *prg.fontInfo[prg.italicBase[prg.curF]+(int32(prg.curI.b2)-minQuarterword)/4].int()
 17775  				p = prg.newCharacter(prg.curF, eightBits(int32(prg.curC)-minQuarterword))
 17776  				if int32(*(*prg.mem[int32(q)+1].hh()).rh()) == mathTextChar && *prg.fontInfo[spaceCode+prg.paramBase[prg.curF]].int() != 0 {
 17777  					delta = 0
 17778  				} // no italic correction in mid-word of text font
 17779  				if int32(*(*prg.mem[int32(q)+3].hh()).rh()) == empty && delta != 0 {
 17780  					*(*prg.mem[p].hh()).rh() = prg.newKern(delta)
 17781  					delta = 0
 17782  				}
 17783  			} else {
 17784  				p = 0
 17785  			}
 17786  
 17787  		case empty:
 17788  			p = 0
 17789  		case subBox:
 17790  			p = *(*prg.mem[int32(q)+1].hh()).lh()
 17791  		case subMlist:
 17792  			prg.curMlist = *(*prg.mem[int32(q)+1].hh()).lh()
 17793  			saveStyle = prg.curStyle
 17794  			prg.mlistPenalties = false
 17795  			prg.mlistToHlist() // recursive call
 17796  			// \xref[recursion]
 17797  			prg.curStyle = saveStyle
 17798  			// Set up the values...
 17799  			{
 17800  				if int32(prg.curStyle) < scriptStyle {
 17801  					prg.curSize = byte(textSize)
 17802  				} else {
 17803  					prg.curSize = byte(16 * ((int32(prg.curStyle) - textStyle) / 2))
 17804  				}
 17805  				prg.curMu = prg.xOverN(*prg.fontInfo[6+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int(), 18)
 17806  			}
 17807  			p = prg.hpack(*(*prg.mem[30000-3].hh()).rh(), scaled(0), smallNumber(additional))
 17808  
 17809  		default:
 17810  			prg.confusion(strNumber( /* "mlist2" */ 890))
 17811  			// \xref[this can't happen mlist2][\quad mlist2]
 17812  		}
 17813  
 17814  		*prg.mem[int32(q)+1].int() = int32(p)
 17815  		if int32(*(*prg.mem[int32(q)+3].hh()).rh()) == empty && int32(*(*prg.mem[int32(q)+2].hh()).rh()) == empty {
 17816  			goto checkDimensions
 17817  		}
 17818  		prg.makeScripts(q, delta)
 17819  
 17820  	checkDimensions:
 17821  		z = prg.hpack(halfword(*prg.mem[int32(q)+1].int()), scaled(0), smallNumber(additional))
 17822  		if *prg.mem[int32(z)+heightOffset].int() > maxH {
 17823  			maxH = *prg.mem[int32(z)+heightOffset].int()
 17824  		}
 17825  		if *prg.mem[int32(z)+depthOffset].int() > maxD {
 17826  			maxD = *prg.mem[int32(z)+depthOffset].int()
 17827  		}
 17828  		prg.freeNode(z, halfword(boxNodeSize))
 17829  
 17830  	doneWithNoad:
 17831  		r1 = q
 17832  		rType = *(*prg.mem[r1].hh()).b0()
 17833  
 17834  	doneWithNode:
 17835  		q = *(*prg.mem[q].hh()).rh()
 17836  	}
 17837  
 17838  	// Convert \(a)a final |bin_noad| to an |ord_noad|
 17839  	if int32(rType) == binNoad {
 17840  		*(*prg.mem[r1].hh()).b0() = byte(ordNoad)
 17841  	}
 17842  
 17843  	// Make a second pass over the mlist, removing all noads and inserting the proper spacing and penalties
 17844  	p = uint16(30000 - 3)
 17845  	*(*prg.mem[p].hh()).rh() = 0
 17846  	q = mlist
 17847  	rType = 0
 17848  	prg.curStyle = style
 17849  
 17850  	// Set up the values of |cur_size| and |cur_mu|, based on |cur_style|
 17851  	{
 17852  		if int32(prg.curStyle) < scriptStyle {
 17853  			prg.curSize = byte(textSize)
 17854  		} else {
 17855  			prg.curSize = byte(16 * ((int32(prg.curStyle) - textStyle) / 2))
 17856  		}
 17857  		prg.curMu = prg.xOverN(*prg.fontInfo[6+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int(), 18)
 17858  	}
 17859  	for int32(q) != 0 {
 17860  		t = byte(ordNoad)
 17861  		s = byte(noadSize)
 17862  		pen = infPenalty
 17863  		switch *(*prg.mem[q].hh()).b0() {
 17864  		case opNoad, openNoad, closeNoad, punctNoad,
 17865  			innerNoad:
 17866  			t = *(*prg.mem[q].hh()).b0()
 17867  		case binNoad:
 17868  			t = byte(binNoad)
 17869  			pen = *prg.eqtb[intBase+binOpPenaltyCode-1].int()
 17870  
 17871  		case relNoad:
 17872  			t = byte(relNoad)
 17873  			pen = *prg.eqtb[intBase+relPenaltyCode-1].int()
 17874  
 17875  		case ordNoad, vcenterNoad, overNoad, underNoad:
 17876  		case radicalNoad:
 17877  			s = byte(radicalNoadSize)
 17878  		case accentNoad:
 17879  			s = byte(accentNoadSize)
 17880  		case fractionNoad:
 17881  			s = byte(fractionNoadSize)
 17882  		case leftNoad, rightNoad:
 17883  			t = prg.makeLeftRight(q, style, maxD, maxH)
 17884  		case styleNode:
 17885  			// Change the current style and |goto delete_q|
 17886  			prg.curStyle = *(*prg.mem[q].hh()).b1()
 17887  			s = byte(styleNodeSize)
 17888  
 17889  			// Set up the values of |cur_size| and |cur_mu|, based on |cur_style|
 17890  			{
 17891  				if int32(prg.curStyle) < scriptStyle {
 17892  					prg.curSize = byte(textSize)
 17893  				} else {
 17894  					prg.curSize = byte(16 * ((int32(prg.curStyle) - textStyle) / 2))
 17895  				}
 17896  				prg.curMu = prg.xOverN(*prg.fontInfo[6+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int(), 18)
 17897  			}
 17898  
 17899  			goto deleteQ
 17900  
 17901  		case whatsitNode, penaltyNode, ruleNode, discNode,
 17902  			adjustNode, insNode, markNode, glueNode,
 17903  			kernNode: //
 17904  
 17905  			*(*prg.mem[p].hh()).rh() = q
 17906  			p = q
 17907  			q = *(*prg.mem[q].hh()).rh()
 17908  			*(*prg.mem[p].hh()).rh() = 0
 17909  			goto done
 17910  
 17911  		default:
 17912  			prg.confusion(strNumber( /* "mlist3" */ 891))
 17913  			// \xref[this can't happen mlist3][\quad mlist3]
 17914  		}
 17915  
 17916  		// Append inter-element spacing based on |r_type| and |t|
 17917  		if int32(rType) > 0 {
 17918  			switch prg.strPool[int32(rType)*8+int32(t)+prg.magicOffset] {
 17919  			case '0':
 17920  				x = 0
 17921  			// "1"=
 17922  			case '1':
 17923  				if int32(prg.curStyle) < scriptStyle {
 17924  					x = uint16(thinMuSkipCode)
 17925  				} else {
 17926  					x = 0
 17927  				}
 17928  			// "2"=
 17929  			case '2':
 17930  				x = uint16(thinMuSkipCode)
 17931  			// "3"=
 17932  			case '3':
 17933  				if int32(prg.curStyle) < scriptStyle {
 17934  					x = uint16(medMuSkipCode)
 17935  				} else {
 17936  					x = 0
 17937  				}
 17938  			// "4"=
 17939  			case '4':
 17940  				if int32(prg.curStyle) < scriptStyle {
 17941  					x = uint16(thickMuSkipCode)
 17942  				} else {
 17943  					x = 0
 17944  				}
 17945  
 17946  			default:
 17947  				prg.confusion(strNumber( /* "mlist4" */ 893))
 17948  				// \xref[this can't happen mlist4][\quad mlist4]
 17949  			}
 17950  			if int32(x) != 0 {
 17951  				y = prg.mathGlue(*(*prg.eqtb[glueBase+int32(x)-1].hh()).rh(), prg.curMu)
 17952  				z = prg.newGlue(y)
 17953  				*(*prg.mem[y].hh()).rh() = 0
 17954  				*(*prg.mem[p].hh()).rh() = z
 17955  				p = z
 17956  
 17957  				*(*prg.mem[z].hh()).b1() = byte(int32(x) + 1) // store a symbolic subtype
 17958  			}
 17959  		}
 17960  
 17961  		// Append any |new_hlist| entries for |q|, and any appropriate penalties
 17962  		if *prg.mem[int32(q)+1].int() != 0 {
 17963  			*(*prg.mem[p].hh()).rh() = uint16(*prg.mem[int32(q)+1].int())
 17964  			for {
 17965  				p = *(*prg.mem[p].hh()).rh()
 17966  				if int32(*(*prg.mem[p].hh()).rh()) == 0 {
 17967  					break
 17968  				}
 17969  			}
 17970  		}
 17971  		if penalties {
 17972  			if int32(*(*prg.mem[q].hh()).rh()) != 0 {
 17973  				if pen < infPenalty {
 17974  					rType = *(*prg.mem[*(*prg.mem[q].hh()).rh()].hh()).b0()
 17975  					if int32(rType) != penaltyNode {
 17976  						if int32(rType) != relNoad {
 17977  							z = prg.newPenalty(pen)
 17978  							*(*prg.mem[p].hh()).rh() = z
 17979  							p = z
 17980  						}
 17981  					}
 17982  				}
 17983  			}
 17984  		}
 17985  		rType = t
 17986  
 17987  	deleteQ:
 17988  		r1 = q
 17989  		q = *(*prg.mem[q].hh()).rh()
 17990  		prg.freeNode(r1, halfword(s))
 17991  
 17992  	done:
 17993  	}
 17994  }
 17995  
 17996  // 768. \[37] Alignment
 17997  
 17998  // tangle:pos tex.web:15108:18:
 17999  
 18000  // It's sort of a miracle whenever \.[\\halign] and \.[\\valign] work, because
 18001  // they cut across so many of the control structures of \TeX.
 18002  //
 18003  // Therefore the
 18004  // present page is probably not the best place for a beginner to start reading
 18005  // this program; it is better to master everything else first.
 18006  //
 18007  // Let us focus our thoughts on an example of what the input might be, in order
 18008  // to get some idea about how the alignment miracle happens. The example doesn't
 18009  // do anything useful, but it is sufficiently general to indicate all of the
 18010  // special cases that must be dealt with; please do not be disturbed by its
 18011  // apparent complexity and meaninglessness.
 18012  // $$\vbox[\halign[\.[#]\hfil\cr
 18013  // []\\tabskip 2pt plus 3pt\cr
 18014  // []\\halign to 300pt\[u1\#v1\&\cr
 18015  // \hskip 50pt\\tabskip 1pt plus 1fil u2\#v2\&\cr
 18016  // \hskip 50pt u3\#v3\\cr\cr
 18017  // \hskip 25pt a1\&\\omit a2\&\\vrule\\cr\cr
 18018  // \hskip 25pt \\noalign\[\\vskip 3pt\]\cr
 18019  // \hskip 25pt b1\\span b2\\cr\cr
 18020  // \hskip 25pt \\omit\&c2\\span\\omit\\cr\]\cr]]$$
 18021  // Here's what happens:
 18022  //
 18023  // \yskip
 18024  // (0) When `\.[\\halign to 300pt\[]' is scanned, the |scan_spec| routine
 18025  // places the 300pt dimension onto the |save_stack|, and an |align_group|
 18026  // code is placed above it. This will make it possible to complete the alignment
 18027  // when the matching `\.\]' is found.
 18028  //
 18029  // (1) The preamble is scanned next. Macros in the preamble are not expanded,
 18030  // \xref[preamble]
 18031  // except as part of a tabskip specification. For example, if \.[u2] had been
 18032  // a macro in the preamble above, it would have been expanded, since \TeX\
 18033  // must look for `\.[minus...]' as part of the tabskip glue. A ``preamble list''
 18034  // is constructed based on the user's preamble; in our case it contains the
 18035  // following seven items:
 18036  // $$\vbox[\halign[\.[#]\hfil\qquad&(#)\hfil\cr
 18037  // []\\glue 2pt plus 3pt&the tabskip preceding column 1\cr
 18038  // []\\alignrecord, width $-\infty$&preamble info for column 1\cr
 18039  // []\\glue 2pt plus 3pt&the tabskip between columns 1 and 2\cr
 18040  // []\\alignrecord, width $-\infty$&preamble info for column 2\cr
 18041  // []\\glue 1pt plus 1fil&the tabskip between columns 2 and 3\cr
 18042  // []\\alignrecord, width $-\infty$&preamble info for column 3\cr
 18043  // []\\glue 1pt plus 1fil&the tabskip following column 3\cr]]$$
 18044  // These ``alignrecord'' entries have the same size as an |unset_node|,
 18045  // since they will later be converted into such nodes. However, at the
 18046  // moment they have no |type| or |subtype| fields; they have |info| fields
 18047  // instead, and these |info| fields are initially set to the value |end_span|,
 18048  // for reasons explained below. Furthermore, the alignrecord nodes have no
 18049  // |height| or |depth| fields; these are renamed |u_part| and |v_part|,
 18050  // and they point to token lists for the templates of the alignment.
 18051  // For example, the |u_part| field in the first alignrecord points to the
 18052  // token list `\.[u1]', i.e., the template preceding the `\.\#' for column~1.
 18053  //
 18054  // (2) \TeX\ now looks at what follows the \.[\\cr] that ended the preamble.
 18055  // It is not `\.[\\noalign]' or `\.[\\omit]', so this input is put back to
 18056  // be read again, and the template `\.[u1]' is fed to the scanner. Just
 18057  // before reading `\.[u1]', \TeX\ goes into restricted horizontal mode.
 18058  // Just after reading `\.[u1]', \TeX\ will see `\.[a1]', and then (when the
 18059  // [\.\&] is sensed) \TeX\ will see `\.[v1]'. Then \TeX\ scans an |endv|
 18060  // token, indicating the end of a column. At this point an |unset_node| is
 18061  // created, containing the contents of the current hlist (i.e., `\.[u1a1v1]').
 18062  // The natural width of this unset node replaces the |width| field of the
 18063  // alignrecord for column~1; in general, the alignrecords will record the
 18064  // maximum natural width that has occurred so far in a given column.
 18065  //
 18066  // (3) Since `\.[\\omit]' follows the `\.\&', the templates for column~2
 18067  // are now bypassed. Again \TeX\ goes into restricted horizontal mode and
 18068  // makes an |unset_node| from the resulting hlist; but this time the
 18069  // hlist contains simply `\.[a2]'. The natural width of the new unset box
 18070  // is remembered in the |width| field of the alignrecord for column~2.
 18071  //
 18072  // (4) A third |unset_node| is created for column 3, using essentially the
 18073  // mechanism that worked for column~1; this unset box contains `\.[u3\\vrule
 18074  // v3]'. The vertical rule in this case has running dimensions that will later
 18075  // extend to the height and depth of the whole first row, since each |unset_node|
 18076  // in a row will eventually inherit the height and depth of its enclosing box.
 18077  //
 18078  // (5) The first row has now ended; it is made into a single unset box
 18079  // comprising the following seven items:
 18080  // $$\vbox[\halign[\hbox to 325pt[\qquad\.[#]\hfil]\cr
 18081  // []\\glue 2pt plus 3pt\cr
 18082  // []\\unsetbox for 1 column: u1a1v1\cr
 18083  // []\\glue 2pt plus 3pt\cr
 18084  // []\\unsetbox for 1 column: a2\cr
 18085  // []\\glue 1pt plus 1fil\cr
 18086  // []\\unsetbox for 1 column: u3\\vrule v3\cr
 18087  // []\\glue 1pt plus 1fil\cr]]$$
 18088  // The width of this unset row is unimportant, but it has the correct height
 18089  // and depth, so the correct baselineskip glue will be computed as the row
 18090  // is inserted into a vertical list.
 18091  //
 18092  // (6) Since `\.[\\noalign]' follows the current \.[\\cr], \TeX\ appends
 18093  // additional material (in this case \.[\\vskip 3pt]) to the vertical list.
 18094  // While processing this material, \TeX\ will be in internal vertical
 18095  // mode, and |no_align_group| will be on |save_stack|.
 18096  //
 18097  // (7) The next row produces an unset box that looks like this:
 18098  // $$\vbox[\halign[\hbox to 325pt[\qquad\.[#]\hfil]\cr
 18099  // []\\glue 2pt plus 3pt\cr
 18100  // []\\unsetbox for 2 columns: u1b1v1u2b2v2\cr
 18101  // []\\glue 1pt plus 1fil\cr
 18102  // []\\unsetbox for 1 column: [\rm(empty)]\cr
 18103  // []\\glue 1pt plus 1fil\cr]]$$
 18104  // The natural width of the unset box that spans columns 1~and~2 is stored
 18105  // in a ``span node,'' which we will explain later; the |info| field of the
 18106  // alignrecord for column~1 now points to the new span node, and the |info|
 18107  // of the span node points to |end_span|.
 18108  //
 18109  // (8) The final row produces the unset box
 18110  // $$\vbox[\halign[\hbox to 325pt[\qquad\.[#]\hfil]\cr
 18111  // []\\glue 2pt plus 3pt\cr
 18112  // []\\unsetbox for 1 column: [\rm(empty)]\cr
 18113  // []\\glue 2pt plus 3pt\cr
 18114  // []\\unsetbox for 2 columns: u2c2v2\cr
 18115  // []\\glue 1pt plus 1fil\cr]]$$
 18116  // A new span node is attached to the alignrecord for column 2.
 18117  //
 18118  // (9) The last step is to compute the true column widths and to change all the
 18119  // unset boxes to hboxes, appending the whole works to the vertical list that
 18120  // encloses the \.[\\halign]. The rules for deciding on the final widths of
 18121  // each unset column box will be explained below.
 18122  //
 18123  // \yskip\noindent
 18124  // Note that as \.[\\halign] is being processed, we fearlessly give up control
 18125  // to the rest of \TeX. At critical junctures, an alignment routine is
 18126  // called upon to step in and do some little action, but most of the time
 18127  // these routines just lurk in the background. It's something like
 18128  // post-hypnotic suggestion.
 18129  
 18130  // 769.
 18131  
 18132  // tangle:pos tex.web:15239:1:
 18133  
 18134  // We have mentioned that alignrecords contain no |height| or |depth| fields.
 18135  // Their |glue_sign| and |glue_order| are pre-empted as well, since it
 18136  // is necessary to store information about what to do when a template ends.
 18137  // This information is called the |extra_info| field.
 18138  
 18139  // 772.
 18140  
 18141  // tangle:pos tex.web:15281:1:
 18142  
 18143  // Alignment stack maintenance is handled by a pair of trivial routines
 18144  // called |push_alignment| and |pop_alignment|.
 18145  func (prg *prg) pushAlignment() {
 18146  	var (
 18147  		p halfword // the new alignment stack node
 18148  	)
 18149  	p = prg.getNode(alignStackNodeSize)
 18150  	*(*prg.mem[p].hh()).rh() = prg.alignPtr
 18151  	*(*prg.mem[p].hh()).lh() = prg.curAlign
 18152  	*(*prg.mem[int32(p)+1].hh()).lh() = *(*prg.mem[30000-8].hh()).rh()
 18153  	*(*prg.mem[int32(p)+1].hh()).rh() = prg.curSpan
 18154  	*prg.mem[int32(p)+2].int() = int32(prg.curLoop)
 18155  	*prg.mem[int32(p)+3].int() = prg.alignState
 18156  	*(*prg.mem[int32(p)+4].hh()).lh() = prg.curHead
 18157  	*(*prg.mem[int32(p)+4].hh()).rh() = prg.curTail
 18158  	prg.alignPtr = p
 18159  	prg.curHead = prg.getAvail()
 18160  }
 18161  
 18162  func (prg *prg) popAlignment() {
 18163  	var (
 18164  		p halfword // the top alignment stack node
 18165  	)
 18166  	{
 18167  		*(*prg.mem[prg.curHead].hh()).rh() = prg.avail
 18168  		prg.avail = prg.curHead /*    dyn_used:= dyn_used-1 ; [  ] */
 18169  	}
 18170  	p = prg.alignPtr
 18171  	prg.curTail = *(*prg.mem[int32(p)+4].hh()).rh()
 18172  	prg.curHead = *(*prg.mem[int32(p)+4].hh()).lh()
 18173  	prg.alignState = *prg.mem[int32(p)+3].int()
 18174  	prg.curLoop = uint16(*prg.mem[int32(p)+2].int())
 18175  	prg.curSpan = *(*prg.mem[int32(p)+1].hh()).rh()
 18176  	*(*prg.mem[30000-8].hh()).rh() = *(*prg.mem[int32(p)+1].hh()).lh()
 18177  	prg.curAlign = *(*prg.mem[p].hh()).lh()
 18178  	prg.alignPtr = *(*prg.mem[p].hh()).rh()
 18179  	prg.freeNode(p, halfword(alignStackNodeSize))
 18180  }
 18181  
 18182  // 773.
 18183  
 18184  // tangle:pos tex.web:15306:1:
 18185  
 18186  // \TeX\ has eight procedures that govern alignments: |init_align| and
 18187  // |fin_align| are used at the very beginning and the very end; |init_row| and
 18188  // |fin_row| are used at the beginning and end of individual rows; |init_span|
 18189  // is used at the beginning of a sequence of spanned columns (possibly involving
 18190  // only one column); |init_col| and |fin_col| are used at the beginning and
 18191  // end of individual columns; and |align_peek| is used after \.[\\cr] to see
 18192  // whether the next item is \.[\\noalign].
 18193  //
 18194  // We shall consider these routines in the order they are first used during
 18195  // the course of a complete \.[\\halign], namely |init_align|, |align_peek|,
 18196  // |init_row|, |init_span|, |init_col|, |fin_col|, |fin_row|, |fin_align|.
 18197  
 18198  // 774.
 18199  
 18200  // tangle:pos tex.web:15318:1:
 18201  
 18202  // When \.[\\halign] or \.[\\valign] has been scanned in an appropriate
 18203  // mode, \TeX\ calls |init_align|, whose task is to get everything off to a
 18204  // good start. This mostly involves scanning the preamble and putting its
 18205  // information into the preamble list.
 18206  // \xref[preamble]
 18207  // \4
 18208  // Declare the procedure called |get_preamble_token|
 18209  func (prg *prg) getPreambleToken() {
 18210  restart:
 18211  	prg.getToken()
 18212  	for int32(prg.curChr) == spanCode && int32(prg.curCmd) == tabMark {
 18213  		prg.getToken() // this token will be expanded once
 18214  		if int32(prg.curCmd) > maxCommand {
 18215  			prg.expand()
 18216  			prg.getToken()
 18217  		}
 18218  	}
 18219  	if int32(prg.curCmd) == endv {
 18220  		prg.fatalError(strNumber( /* "(interwoven alignment preambles are not allowed)" */ 595))
 18221  	}
 18222  	// \xref[interwoven alignment preambles...]
 18223  	if int32(prg.curCmd) == assignGlue && int32(prg.curChr) == glueBase+tabSkipCode {
 18224  		prg.scanOptionalEquals()
 18225  		prg.scanGlue(smallNumber(glueVal))
 18226  		if *prg.eqtb[intBase+globalDefsCode-1].int() > 0 {
 18227  			prg.geqDefine(halfword(glueBase+tabSkipCode), quarterword(glueRef), halfword(prg.curVal))
 18228  		} else {
 18229  			prg.eqDefine(halfword(glueBase+tabSkipCode), quarterword(glueRef), halfword(prg.curVal))
 18230  		}
 18231  
 18232  		goto restart
 18233  	}
 18234  } // \2
 18235  
 18236  func (prg *prg) initAlign() {
 18237  	var (
 18238  		saveCsPtr halfword // |warning_index| value for error messages
 18239  		p         halfword // for short-term temporary use
 18240  	)
 18241  	saveCsPtr = prg.curCs // \.[\\halign] or \.[\\valign], usually
 18242  	prg.pushAlignment()
 18243  	prg.alignState = -1000000 // enter a new alignment level
 18244  
 18245  	// Check for improper alignment in displayed math
 18246  	if int32(prg.curList.modeField) == mmode && (int32(prg.curList.tailField) != int32(prg.curList.headField) || *prg.curList.auxField.int() != 0) {
 18247  		{
 18248  			if int32(prg.interaction) == errorStopMode {
 18249  			}
 18250  			prg.printNl(strNumber( /* "! " */ 262))
 18251  			prg.print( /* "Improper " */ 680)
 18252  		}
 18253  		prg.printEsc(strNumber( /* "halign" */ 520))
 18254  		prg.print( /* " inside $$'s" */ 894)
 18255  		// \xref[Improper \\halign...]
 18256  		{
 18257  			prg.helpPtr = 3
 18258  			prg.helpLine[2] = /* "Displays can use special alignments (like \\eqalignno)" */ 895
 18259  			prg.helpLine[1] = /* "only if nothing but the alignment itself is between $$'s." */ 896
 18260  			prg.helpLine[0] = /* "So I've deleted the formulas that preceded this alignment." */ 897
 18261  		}
 18262  		prg.error1()
 18263  		prg.flushMath()
 18264  	}
 18265  	prg.pushNest() // enter a new semantic level
 18266  
 18267  	// Change current mode to |-vmode| for \.[\\halign], |-hmode| for \.[\\valign]
 18268  	if int32(prg.curList.modeField) == mmode {
 18269  		prg.curList.modeField = int16(-vmode)
 18270  		*prg.curList.auxField.int() = *prg.nest[int32(prg.nestPtr)-2].auxField.int()
 18271  	} else if int32(prg.curList.modeField) > 0 {
 18272  		prg.curList.modeField = -prg.curList.modeField
 18273  	}
 18274  	prg.scanSpec(groupCode(alignGroup), false)
 18275  
 18276  	// Scan the preamble and record it in the |preamble| list
 18277  	*(*prg.mem[30000-8].hh()).rh() = 0
 18278  	prg.curAlign = uint16(30000 - 8)
 18279  	prg.curLoop = 0
 18280  	prg.scannerStatus = byte(aligning)
 18281  	prg.warningIndex = saveCsPtr
 18282  	prg.alignState = -1000000
 18283  	// at this point, |cur_cmd=left_brace|
 18284  	for true {
 18285  		*(*prg.mem[prg.curAlign].hh()).rh() = prg.newParamGlue(smallNumber(tabSkipCode))
 18286  		prg.curAlign = *(*prg.mem[prg.curAlign].hh()).rh()
 18287  		if int32(prg.curCmd) == carRet {
 18288  			goto done
 18289  		} // \.[\\cr] ends the preamble
 18290  
 18291  		// Scan preamble text until |cur_cmd| is |tab_mark| or |car_ret|, looking for changes in the tabskip glue; append an alignrecord to the preamble list
 18292  
 18293  		// Scan the template \<u_j>, putting the resulting token list in |hold_head|
 18294  		p = uint16(30000 - 4)
 18295  		*(*prg.mem[p].hh()).rh() = 0
 18296  		for true {
 18297  			prg.getPreambleToken()
 18298  			if int32(prg.curCmd) == macParam {
 18299  				goto done1
 18300  			}
 18301  			if int32(prg.curCmd) <= carRet && int32(prg.curCmd) >= tabMark && prg.alignState == -1000000 {
 18302  				if int32(p) == 30000-4 && int32(prg.curLoop) == 0 && int32(prg.curCmd) == tabMark {
 18303  					prg.curLoop = prg.curAlign
 18304  				} else {
 18305  					{
 18306  						if int32(prg.interaction) == errorStopMode {
 18307  						}
 18308  						prg.printNl(strNumber( /* "! " */ 262))
 18309  						prg.print( /* "Missing # inserted in alignment preamble" */ 903)
 18310  					}
 18311  					// \xref[Missing \# inserted...]
 18312  					{
 18313  						prg.helpPtr = 3
 18314  						prg.helpLine[2] = /* "There should be exactly one # between &'s, when an" */ 904
 18315  						prg.helpLine[1] = /* "\\halign or \\valign is being set up. In this case you had" */ 905
 18316  						prg.helpLine[0] = /* "none, so I've put one in; maybe that will work." */ 906
 18317  					}
 18318  					prg.backError()
 18319  					goto done1
 18320  				}
 18321  			} else if int32(prg.curCmd) != spacer || int32(p) != 30000-4 {
 18322  				*(*prg.mem[p].hh()).rh() = prg.getAvail()
 18323  				p = *(*prg.mem[p].hh()).rh()
 18324  				*(*prg.mem[p].hh()).lh() = prg.curTok
 18325  			}
 18326  		}
 18327  
 18328  	done1:
 18329  		;
 18330  		*(*prg.mem[prg.curAlign].hh()).rh() = prg.newNullBox()
 18331  		prg.curAlign = *(*prg.mem[prg.curAlign].hh()).rh() // a new alignrecord
 18332  		*(*prg.mem[prg.curAlign].hh()).lh() = uint16(30000 - 9)
 18333  		*prg.mem[int32(prg.curAlign)+widthOffset].int() = -010000000000
 18334  		*prg.mem[int32(prg.curAlign)+heightOffset].int() = int32(*(*prg.mem[30000-4].hh()).rh())
 18335  
 18336  		// Scan the template \<v_j>, putting the resulting token list in |hold_head|
 18337  		p = uint16(30000 - 4)
 18338  		*(*prg.mem[p].hh()).rh() = 0
 18339  		for true {
 18340  		continue1:
 18341  			prg.getPreambleToken()
 18342  			if int32(prg.curCmd) <= carRet && int32(prg.curCmd) >= tabMark && prg.alignState == -1000000 {
 18343  				goto done2
 18344  			}
 18345  			if int32(prg.curCmd) == macParam {
 18346  				{
 18347  					if int32(prg.interaction) == errorStopMode {
 18348  					}
 18349  					prg.printNl(strNumber( /* "! " */ 262))
 18350  					prg.print( /* "Only one # is allowed per tab" */ 907)
 18351  				}
 18352  				// \xref[Only one \# is allowed...]
 18353  				{
 18354  					prg.helpPtr = 3
 18355  					prg.helpLine[2] = /* "There should be exactly one # between &'s, when an" */ 904
 18356  					prg.helpLine[1] = /* "\\halign or \\valign is being set up. In this case you had" */ 905
 18357  					prg.helpLine[0] = /* "more than one, so I'm ignoring all but the first." */ 908
 18358  				}
 18359  				prg.error1()
 18360  				goto continue1
 18361  			}
 18362  			*(*prg.mem[p].hh()).rh() = prg.getAvail()
 18363  			p = *(*prg.mem[p].hh()).rh()
 18364  			*(*prg.mem[p].hh()).lh() = prg.curTok
 18365  		}
 18366  
 18367  	done2:
 18368  		*(*prg.mem[p].hh()).rh() = prg.getAvail()
 18369  		p = *(*prg.mem[p].hh()).rh()
 18370  		*(*prg.mem[p].hh()).lh() = uint16(07777 + frozenEndTemplate)
 18371  		*prg.mem[int32(prg.curAlign)+depthOffset].int() = int32(*(*prg.mem[30000-4].hh()).rh())
 18372  	}
 18373  
 18374  done:
 18375  	prg.scannerStatus = byte(normal)
 18376  	prg.newSaveLevel(groupCode(alignGroup))
 18377  	if int32(*(*prg.eqtb[everyCrLoc-1].hh()).rh()) != 0 {
 18378  		prg.beginTokenList(*(*prg.eqtb[everyCrLoc-1].hh()).rh(), quarterword(everyCrText))
 18379  	}
 18380  	prg.alignPeek() // look for \.[\\noalign] or \.[\\omit]
 18381  }
 18382  
 18383  // 786.
 18384  
 18385  // tangle:pos tex.web:15525:1:
 18386  
 18387  // To start a row (i.e., a `row' that rhymes with `dough' but not with `bough'),
 18388  // we enter a new semantic level, copy the first tabskip glue, and change
 18389  // from internal vertical mode to restricted horizontal mode or vice versa.
 18390  // The |space_factor| and |prev_depth| are not used on this semantic level,
 18391  // but we clear them to zero just to be tidy.
 18392  // \4
 18393  // Declare the procedure called |init_span|
 18394  func (prg *prg) initSpan(p halfword) {
 18395  	prg.pushNest()
 18396  	if int32(prg.curList.modeField) == -hmode {
 18397  		*(*prg.curList.auxField.hh()).lh() = 1000
 18398  	} else {
 18399  		*prg.curList.auxField.int() = -65536000
 18400  		prg.normalParagraph()
 18401  	}
 18402  	prg.curSpan = p
 18403  }
 18404  
 18405  //
 18406  
 18407  func (prg *prg) initRow() {
 18408  	prg.pushNest()
 18409  	prg.curList.modeField = int16(-hmode - vmode - int32(prg.curList.modeField))
 18410  	if int32(prg.curList.modeField) == -hmode {
 18411  		*(*prg.curList.auxField.hh()).lh() = 0
 18412  	} else {
 18413  		*prg.curList.auxField.int() = 0
 18414  	}
 18415  	{
 18416  		*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newGlue(*(*prg.mem[int32(*(*prg.mem[30000-8].hh()).rh())+1].hh()).lh())
 18417  		prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 18418  	}
 18419  	*(*prg.mem[prg.curList.tailField].hh()).b1() = byte(tabSkipCode + 1)
 18420  
 18421  	prg.curAlign = *(*prg.mem[*(*prg.mem[30000-8].hh()).rh()].hh()).rh()
 18422  	prg.curTail = prg.curHead
 18423  	prg.initSpan(prg.curAlign)
 18424  }
 18425  
 18426  // 788.
 18427  
 18428  // tangle:pos tex.web:15553:1:
 18429  
 18430  // When a column begins, we assume that |cur_cmd| is either |omit| or else
 18431  // the current token should be put back into the input until the \<u_j>
 18432  // template has been scanned.  (Note that |cur_cmd| might be |tab_mark| or
 18433  // |car_ret|.)  We also assume that |align_state| is approximately 1000000 at
 18434  // this time.  We remain in the same mode, and start the template if it is
 18435  // called for.
 18436  func (prg *prg) initCol() {
 18437  	*(*prg.mem[int32(prg.curAlign)+listOffset].hh()).lh() = uint16(prg.curCmd)
 18438  	if int32(prg.curCmd) == omit {
 18439  		prg.alignState = 0
 18440  	} else {
 18441  		prg.backInput()
 18442  		prg.beginTokenList(halfword(*prg.mem[int32(prg.curAlign)+heightOffset].int()), quarterword(uTemplate))
 18443  	} // now |align_state=1000000|
 18444  }
 18445  
 18446  // 791.
 18447  
 18448  // tangle:pos tex.web:15592:1:
 18449  
 18450  // When the |endv| command at the end of a \<v_j> template comes through the
 18451  // scanner, things really start to happen; and it is the |fin_col| routine
 18452  // that makes them happen. This routine returns |true| if a row as well as a
 18453  // column has been finished.
 18454  func (prg *prg) finCol() (r bool) {
 18455  	var (
 18456  		p     halfword // the alignrecord after the current one
 18457  		q, r1 halfword // temporary pointers for list manipulation
 18458  		s     halfword // a new span node
 18459  		u     halfword // a new unset box
 18460  		w     scaled   // natural width
 18461  		o     glueOrd  // order of infinity
 18462  		n     halfword // span counter
 18463  	)
 18464  	if int32(prg.curAlign) == 0 {
 18465  		prg.confusion(strNumber( /* "endv" */ 909))
 18466  	}
 18467  	q = *(*prg.mem[prg.curAlign].hh()).rh()
 18468  	if int32(q) == 0 {
 18469  		prg.confusion(strNumber( /* "endv" */ 909))
 18470  	}
 18471  	// \xref[this can't happen endv][\quad endv]
 18472  	if prg.alignState < 500000 {
 18473  		prg.fatalError(strNumber( /* "(interwoven alignment preambles are not allowed)" */ 595))
 18474  	}
 18475  	// \xref[interwoven alignment preambles...]
 18476  	p = *(*prg.mem[q].hh()).rh()
 18477  
 18478  	// If the preamble list has been traversed, check that the row has ended
 18479  	if int32(p) == 0 && int32(*(*prg.mem[int32(prg.curAlign)+listOffset].hh()).lh()) < crCode {
 18480  		if int32(prg.curLoop) != 0 {
 18481  			*(*prg.mem[q].hh()).rh() = prg.newNullBox()
 18482  			p = *(*prg.mem[q].hh()).rh() // a new alignrecord
 18483  			*(*prg.mem[p].hh()).lh() = uint16(30000 - 9)
 18484  			*prg.mem[int32(p)+widthOffset].int() = -010000000000
 18485  			prg.curLoop = *(*prg.mem[prg.curLoop].hh()).rh()
 18486  
 18487  			// Copy the templates from node |cur_loop| into node |p|
 18488  			q = uint16(30000 - 4)
 18489  			r1 = uint16(*prg.mem[int32(prg.curLoop)+heightOffset].int())
 18490  			for int32(r1) != 0 {
 18491  				*(*prg.mem[q].hh()).rh() = prg.getAvail()
 18492  				q = *(*prg.mem[q].hh()).rh()
 18493  				*(*prg.mem[q].hh()).lh() = *(*prg.mem[r1].hh()).lh()
 18494  				r1 = *(*prg.mem[r1].hh()).rh()
 18495  			}
 18496  			*(*prg.mem[q].hh()).rh() = 0
 18497  			*prg.mem[int32(p)+heightOffset].int() = int32(*(*prg.mem[30000-4].hh()).rh())
 18498  			q = uint16(30000 - 4)
 18499  			r1 = uint16(*prg.mem[int32(prg.curLoop)+depthOffset].int())
 18500  			for int32(r1) != 0 {
 18501  				*(*prg.mem[q].hh()).rh() = prg.getAvail()
 18502  				q = *(*prg.mem[q].hh()).rh()
 18503  				*(*prg.mem[q].hh()).lh() = *(*prg.mem[r1].hh()).lh()
 18504  				r1 = *(*prg.mem[r1].hh()).rh()
 18505  			}
 18506  			*(*prg.mem[q].hh()).rh() = 0
 18507  			*prg.mem[int32(p)+depthOffset].int() = int32(*(*prg.mem[30000-4].hh()).rh())
 18508  			prg.curLoop = *(*prg.mem[prg.curLoop].hh()).rh()
 18509  			*(*prg.mem[p].hh()).rh() = prg.newGlue(*(*prg.mem[int32(prg.curLoop)+1].hh()).lh())
 18510  			*(*prg.mem[*(*prg.mem[p].hh()).rh()].hh()).b1() = byte(tabSkipCode + 1)
 18511  		} else {
 18512  			{
 18513  				if int32(prg.interaction) == errorStopMode {
 18514  				}
 18515  				prg.printNl(strNumber( /* "! " */ 262))
 18516  				prg.print( /* "Extra alignment tab has been changed to " */ 910)
 18517  			}
 18518  			// \xref[Extra alignment tab...]
 18519  			prg.printEsc(strNumber( /* "cr" */ 899))
 18520  			{
 18521  				prg.helpPtr = 3
 18522  				prg.helpLine[2] = /* "You have given more \\span or & marks than there were" */ 911
 18523  				prg.helpLine[1] = /* "in the preamble to the \\halign or \\valign now in progress." */ 912
 18524  				prg.helpLine[0] = /* "So I'll assume that you meant to type \\cr instead." */ 913
 18525  			}
 18526  			*(*prg.mem[int32(prg.curAlign)+listOffset].hh()).lh() = uint16(crCode)
 18527  			prg.error1()
 18528  		}
 18529  	}
 18530  	if int32(*(*prg.mem[int32(prg.curAlign)+listOffset].hh()).lh()) != spanCode {
 18531  		prg.unsave()
 18532  		prg.newSaveLevel(groupCode(alignGroup))
 18533  
 18534  		// Package an unset box for the current column and record its width
 18535  		{
 18536  			if int32(prg.curList.modeField) == -hmode {
 18537  				prg.adjustTail = prg.curTail
 18538  				u = prg.hpack(*(*prg.mem[prg.curList.headField].hh()).rh(), scaled(0), smallNumber(additional))
 18539  				w = *prg.mem[int32(u)+widthOffset].int()
 18540  				prg.curTail = prg.adjustTail
 18541  				prg.adjustTail = 0
 18542  			} else {
 18543  				u = prg.vpackage(*(*prg.mem[prg.curList.headField].hh()).rh(), scaled(0), smallNumber(additional), scaled(0))
 18544  				w = *prg.mem[int32(u)+heightOffset].int()
 18545  			}
 18546  			n = uint16(minQuarterword) // this represents a span count of 1
 18547  			if int32(prg.curSpan) != int32(prg.curAlign) {
 18548  				q = prg.curSpan
 18549  				for {
 18550  					n = uint16(int32(n) + 1)
 18551  					q = *(*prg.mem[*(*prg.mem[q].hh()).rh()].hh()).rh()
 18552  					if int32(q) == int32(prg.curAlign) {
 18553  						break
 18554  					}
 18555  				}
 18556  				if int32(n) > maxQuarterword {
 18557  					prg.confusion(strNumber( /* "256 spans" */ 914))
 18558  				} // this can happen, but won't
 18559  				// \xref[system dependencies]
 18560  				// \xref[this can't happen 256 spans][\quad 256 spans]
 18561  				q = prg.curSpan
 18562  				for int32(*(*prg.mem[*(*prg.mem[q].hh()).lh()].hh()).rh()) < int32(n) {
 18563  					q = *(*prg.mem[q].hh()).lh()
 18564  				}
 18565  				if int32(*(*prg.mem[*(*prg.mem[q].hh()).lh()].hh()).rh()) > int32(n) {
 18566  					s = prg.getNode(spanNodeSize)
 18567  					*(*prg.mem[s].hh()).lh() = *(*prg.mem[q].hh()).lh()
 18568  					*(*prg.mem[s].hh()).rh() = n
 18569  					*(*prg.mem[q].hh()).lh() = s
 18570  					*prg.mem[int32(s)+widthOffset].int() = w
 18571  				} else if *prg.mem[int32(*(*prg.mem[q].hh()).lh())+widthOffset].int() < w {
 18572  					*prg.mem[int32(*(*prg.mem[q].hh()).lh())+widthOffset].int() = w
 18573  				}
 18574  			} else if w > *prg.mem[int32(prg.curAlign)+widthOffset].int() {
 18575  				*prg.mem[int32(prg.curAlign)+widthOffset].int() = w
 18576  			}
 18577  			*(*prg.mem[u].hh()).b0() = byte(unsetNode)
 18578  			*(*prg.mem[u].hh()).b1() = byte(n)
 18579  
 18580  			// Determine the stretch order
 18581  			if prg.totalStretch[filll] != 0 {
 18582  				o = byte(filll)
 18583  			} else if prg.totalStretch[fill] != 0 {
 18584  				o = byte(fill)
 18585  			} else if prg.totalStretch[fil] != 0 {
 18586  				o = byte(fil)
 18587  			} else {
 18588  				o = byte(normal)
 18589  			}
 18590  			*(*prg.mem[int32(u)+listOffset].hh()).b1() = o
 18591  			*prg.mem[int32(u)+glueOffset].int() = prg.totalStretch[o]
 18592  
 18593  			// Determine the shrink order
 18594  			if prg.totalShrink[filll] != 0 {
 18595  				o = byte(filll)
 18596  			} else if prg.totalShrink[fill] != 0 {
 18597  				o = byte(fill)
 18598  			} else if prg.totalShrink[fil] != 0 {
 18599  				o = byte(fil)
 18600  			} else {
 18601  				o = byte(normal)
 18602  			}
 18603  			*(*prg.mem[int32(u)+listOffset].hh()).b0() = o
 18604  			*prg.mem[int32(u)+4].int() = prg.totalShrink[o]
 18605  
 18606  			prg.popNest()
 18607  			*(*prg.mem[prg.curList.tailField].hh()).rh() = u
 18608  			prg.curList.tailField = u
 18609  		}
 18610  
 18611  		// Copy the tabskip glue between columns
 18612  		{
 18613  			*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newGlue(*(*prg.mem[int32(*(*prg.mem[prg.curAlign].hh()).rh())+1].hh()).lh())
 18614  			prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 18615  		}
 18616  		*(*prg.mem[prg.curList.tailField].hh()).b1() = byte(tabSkipCode + 1)
 18617  		if int32(*(*prg.mem[int32(prg.curAlign)+listOffset].hh()).lh()) >= crCode {
 18618  			r = true
 18619  			goto exit
 18620  		}
 18621  		prg.initSpan(p)
 18622  	}
 18623  	prg.alignState = 1000000
 18624  	// Get the next non-blank non-call token
 18625  	for {
 18626  		prg.getXToken()
 18627  		if int32(prg.curCmd) != spacer {
 18628  			break
 18629  		}
 18630  	}
 18631  	prg.curAlign = p
 18632  	prg.initCol()
 18633  	r = false
 18634  
 18635  exit:
 18636  	;
 18637  	return r
 18638  }
 18639  
 18640  // 799.
 18641  
 18642  // tangle:pos tex.web:15714:1:
 18643  
 18644  // At the end of a row, we append an unset box to the current vlist (for
 18645  // \.[\\halign]) or the current hlist (for \.[\\valign]). This unset box
 18646  // contains the unset boxes for the columns, separated by the tabskip glue.
 18647  // Everything will be set later.
 18648  func (prg *prg) finRow() {
 18649  	var (
 18650  		p halfword // the new unset box
 18651  	)
 18652  	if int32(prg.curList.modeField) == -hmode {
 18653  		p = prg.hpack(*(*prg.mem[prg.curList.headField].hh()).rh(), scaled(0), smallNumber(additional))
 18654  		prg.popNest()
 18655  		prg.appendToVlist(p)
 18656  		if int32(prg.curHead) != int32(prg.curTail) {
 18657  			*(*prg.mem[prg.curList.tailField].hh()).rh() = *(*prg.mem[prg.curHead].hh()).rh()
 18658  			prg.curList.tailField = prg.curTail
 18659  		}
 18660  	} else {
 18661  		p = prg.vpackage(*(*prg.mem[prg.curList.headField].hh()).rh(), scaled(0), smallNumber(additional), scaled(07777777777))
 18662  		prg.popNest()
 18663  		*(*prg.mem[prg.curList.tailField].hh()).rh() = p
 18664  		prg.curList.tailField = p
 18665  		*(*prg.curList.auxField.hh()).lh() = 1000
 18666  	}
 18667  	*(*prg.mem[p].hh()).b0() = byte(unsetNode)
 18668  	*prg.mem[int32(p)+glueOffset].int() = 0
 18669  	if int32(*(*prg.eqtb[everyCrLoc-1].hh()).rh()) != 0 {
 18670  		prg.beginTokenList(*(*prg.eqtb[everyCrLoc-1].hh()).rh(), quarterword(everyCrText))
 18671  	}
 18672  	prg.alignPeek()
 18673  } // \2
 18674  
 18675  func (prg *prg) finAlign() {
 18676  	var (
 18677  		p, q, r1, s, u, v halfword   // registers for the list operations
 18678  		t, w              scaled     // width of column
 18679  		o                 scaled     // shift offset for unset boxes
 18680  		n                 halfword   // matching span amount
 18681  		ruleSave          scaled     // temporary storage for |overfull_rule|
 18682  		auxSave           memoryWord // temporary storage for |aux|
 18683  	)
 18684  	if int32(prg.curGroup) != alignGroup {
 18685  		prg.confusion(strNumber( /* "align1" */ 915))
 18686  	}
 18687  	// \xref[this can't happen align][\quad align]
 18688  	prg.unsave() // that |align_group| was for individual entries
 18689  	if int32(prg.curGroup) != alignGroup {
 18690  		prg.confusion(strNumber( /* "align0" */ 916))
 18691  	}
 18692  	prg.unsave() // that |align_group| was for the whole alignment
 18693  	if int32(prg.nest[int32(prg.nestPtr)-1].modeField) == mmode {
 18694  		o = *prg.eqtb[dimenBase+displayIndentCode-1].int()
 18695  	} else {
 18696  		o = 0
 18697  	}
 18698  
 18699  	// Go through the preamble list, determining the column widths and changing the alignrecords to dummy unset boxes
 18700  	q = *(*prg.mem[*(*prg.mem[30000-8].hh()).rh()].hh()).rh()
 18701  	for {
 18702  		prg.flushList(halfword(*prg.mem[int32(q)+heightOffset].int()))
 18703  		prg.flushList(halfword(*prg.mem[int32(q)+depthOffset].int()))
 18704  		p = *(*prg.mem[*(*prg.mem[q].hh()).rh()].hh()).rh()
 18705  		if *prg.mem[int32(q)+widthOffset].int() == -010000000000 {
 18706  			*prg.mem[int32(q)+widthOffset].int() = 0
 18707  			r1 = *(*prg.mem[q].hh()).rh()
 18708  			s = *(*prg.mem[int32(r1)+1].hh()).lh()
 18709  			if int32(s) != memBot {
 18710  				*(*prg.mem[memBot].hh()).rh() = uint16(int32(*(*prg.mem[memBot].hh()).rh()) + 1)
 18711  				prg.deleteGlueRef(s)
 18712  				*(*prg.mem[int32(r1)+1].hh()).lh() = uint16(memBot)
 18713  			}
 18714  		}
 18715  		if int32(*(*prg.mem[q].hh()).lh()) != 30000-9 {
 18716  			t = *prg.mem[int32(q)+widthOffset].int() + *prg.mem[int32(*(*prg.mem[int32(*(*prg.mem[q].hh()).rh())+1].hh()).lh())+widthOffset].int()
 18717  			r1 = *(*prg.mem[q].hh()).lh()
 18718  			s = uint16(30000 - 9)
 18719  			*(*prg.mem[s].hh()).lh() = p
 18720  			n = uint16(minQuarterword + 1)
 18721  			for {
 18722  				*prg.mem[int32(r1)+widthOffset].int() = *prg.mem[int32(r1)+widthOffset].int() - t
 18723  				u = *(*prg.mem[r1].hh()).lh()
 18724  				for int32(*(*prg.mem[r1].hh()).rh()) > int32(n) {
 18725  					s = *(*prg.mem[s].hh()).lh()
 18726  					n = uint16(int32(*(*prg.mem[*(*prg.mem[s].hh()).lh()].hh()).rh()) + 1)
 18727  				}
 18728  				if int32(*(*prg.mem[r1].hh()).rh()) < int32(n) {
 18729  					*(*prg.mem[r1].hh()).lh() = *(*prg.mem[s].hh()).lh()
 18730  					*(*prg.mem[s].hh()).lh() = r1
 18731  					*(*prg.mem[r1].hh()).rh() = uint16(int32(*(*prg.mem[r1].hh()).rh()) - 1)
 18732  					s = r1
 18733  				} else {
 18734  					if *prg.mem[int32(r1)+widthOffset].int() > *prg.mem[int32(*(*prg.mem[s].hh()).lh())+widthOffset].int() {
 18735  						*prg.mem[int32(*(*prg.mem[s].hh()).lh())+widthOffset].int() = *prg.mem[int32(r1)+widthOffset].int()
 18736  					}
 18737  					prg.freeNode(r1, halfword(spanNodeSize))
 18738  				}
 18739  				r1 = u
 18740  				if int32(r1) == 30000-9 {
 18741  					break
 18742  				}
 18743  			}
 18744  		}
 18745  		*(*prg.mem[q].hh()).b0() = byte(unsetNode)
 18746  		*(*prg.mem[q].hh()).b1() = byte(minQuarterword)
 18747  		*prg.mem[int32(q)+heightOffset].int() = 0
 18748  		*prg.mem[int32(q)+depthOffset].int() = 0
 18749  		*(*prg.mem[int32(q)+listOffset].hh()).b1() = byte(normal)
 18750  		*(*prg.mem[int32(q)+listOffset].hh()).b0() = byte(normal)
 18751  		*prg.mem[int32(q)+glueOffset].int() = 0
 18752  		*prg.mem[int32(q)+4].int() = 0
 18753  		q = p
 18754  		if int32(q) == 0 {
 18755  			break
 18756  		}
 18757  	}
 18758  
 18759  	// Package the preamble list, to determine the actual tabskip glue amounts, and let |p| point to this prototype box
 18760  	prg.savePtr = uint16(int32(prg.savePtr) - 2)
 18761  	prg.packBeginLine = -prg.curList.mlField
 18762  	if int32(prg.curList.modeField) == -vmode {
 18763  		ruleSave = *prg.eqtb[dimenBase+overfullRuleCode-1].int()
 18764  		*prg.eqtb[dimenBase+overfullRuleCode-1].int() = 0 // prevent rule from being packaged
 18765  		p = prg.hpack(*(*prg.mem[30000-8].hh()).rh(), *prg.saveStack[int32(prg.savePtr)+1].int(), smallNumber(*prg.saveStack[int32(prg.savePtr)+0].int()))
 18766  		*prg.eqtb[dimenBase+overfullRuleCode-1].int() = ruleSave
 18767  	} else {
 18768  		q = *(*prg.mem[*(*prg.mem[30000-8].hh()).rh()].hh()).rh()
 18769  		for {
 18770  			*prg.mem[int32(q)+heightOffset].int() = *prg.mem[int32(q)+widthOffset].int()
 18771  			*prg.mem[int32(q)+widthOffset].int() = 0
 18772  			q = *(*prg.mem[*(*prg.mem[q].hh()).rh()].hh()).rh()
 18773  			if int32(q) == 0 {
 18774  				break
 18775  			}
 18776  		}
 18777  		p = prg.vpackage(*(*prg.mem[30000-8].hh()).rh(), *prg.saveStack[int32(prg.savePtr)+1].int(), smallNumber(*prg.saveStack[int32(prg.savePtr)+0].int()), scaled(07777777777))
 18778  		q = *(*prg.mem[*(*prg.mem[30000-8].hh()).rh()].hh()).rh()
 18779  		for {
 18780  			*prg.mem[int32(q)+widthOffset].int() = *prg.mem[int32(q)+heightOffset].int()
 18781  			*prg.mem[int32(q)+heightOffset].int() = 0
 18782  			q = *(*prg.mem[*(*prg.mem[q].hh()).rh()].hh()).rh()
 18783  			if int32(q) == 0 {
 18784  				break
 18785  			}
 18786  		}
 18787  	}
 18788  	prg.packBeginLine = 0
 18789  
 18790  	// Set the glue in all the unset boxes of the current list
 18791  	q = *(*prg.mem[prg.curList.headField].hh()).rh()
 18792  	s = prg.curList.headField
 18793  	for int32(q) != 0 {
 18794  		if !(int32(q) >= int32(prg.hiMemMin)) {
 18795  			if int32(*(*prg.mem[q].hh()).b0()) == unsetNode {
 18796  				if int32(prg.curList.modeField) == -vmode {
 18797  					*(*prg.mem[q].hh()).b0() = byte(hlistNode)
 18798  					*prg.mem[int32(q)+widthOffset].int() = *prg.mem[int32(p)+widthOffset].int()
 18799  				} else {
 18800  					*(*prg.mem[q].hh()).b0() = byte(vlistNode)
 18801  					*prg.mem[int32(q)+heightOffset].int() = *prg.mem[int32(p)+heightOffset].int()
 18802  				}
 18803  				*(*prg.mem[int32(q)+listOffset].hh()).b1() = *(*prg.mem[int32(p)+listOffset].hh()).b1()
 18804  				*(*prg.mem[int32(q)+listOffset].hh()).b0() = *(*prg.mem[int32(p)+listOffset].hh()).b0()
 18805  				*prg.mem[int32(q)+glueOffset].gr() = *prg.mem[int32(p)+glueOffset].gr()
 18806  				*prg.mem[int32(q)+4].int() = o
 18807  				r1 = *(*prg.mem[*(*prg.mem[int32(q)+listOffset].hh()).rh()].hh()).rh()
 18808  				s = *(*prg.mem[*(*prg.mem[int32(p)+listOffset].hh()).rh()].hh()).rh()
 18809  				for {
 18810  					// Set the glue in node |r| and change it from an unset node
 18811  					n = uint16(*(*prg.mem[r1].hh()).b1())
 18812  					t = *prg.mem[int32(s)+widthOffset].int()
 18813  					w = t
 18814  					u = uint16(30000 - 4)
 18815  					for int32(n) > minQuarterword {
 18816  						n = uint16(int32(n) - 1)
 18817  
 18818  						// Append tabskip glue and an empty box to list |u|, and update |s| and |t| as the prototype nodes are passed
 18819  						s = *(*prg.mem[s].hh()).rh()
 18820  						v = *(*prg.mem[int32(s)+1].hh()).lh()
 18821  						*(*prg.mem[u].hh()).rh() = prg.newGlue(v)
 18822  						u = *(*prg.mem[u].hh()).rh()
 18823  						*(*prg.mem[u].hh()).b1() = byte(tabSkipCode + 1)
 18824  						t = t + *prg.mem[int32(v)+widthOffset].int()
 18825  						if int32(*(*prg.mem[int32(p)+listOffset].hh()).b0()) == stretching {
 18826  							if int32(*(*prg.mem[v].hh()).b0()) == int32(*(*prg.mem[int32(p)+listOffset].hh()).b1()) {
 18827  								t = t + round(float64(*prg.mem[int32(p)+glueOffset].gr())*float64(*prg.mem[int32(v)+2].int()))
 18828  							}
 18829  							// \xref[real multiplication]
 18830  						} else if int32(*(*prg.mem[int32(p)+listOffset].hh()).b0()) == shrinking {
 18831  							if int32(*(*prg.mem[v].hh()).b1()) == int32(*(*prg.mem[int32(p)+listOffset].hh()).b1()) {
 18832  								t = t - round(float64(*prg.mem[int32(p)+glueOffset].gr())*float64(*prg.mem[int32(v)+3].int()))
 18833  							}
 18834  						}
 18835  						s = *(*prg.mem[s].hh()).rh()
 18836  						*(*prg.mem[u].hh()).rh() = prg.newNullBox()
 18837  						u = *(*prg.mem[u].hh()).rh()
 18838  						t = t + *prg.mem[int32(s)+widthOffset].int()
 18839  						if int32(prg.curList.modeField) == -vmode {
 18840  							*prg.mem[int32(u)+widthOffset].int() = *prg.mem[int32(s)+widthOffset].int()
 18841  						} else {
 18842  							*(*prg.mem[u].hh()).b0() = byte(vlistNode)
 18843  							*prg.mem[int32(u)+heightOffset].int() = *prg.mem[int32(s)+widthOffset].int()
 18844  						}
 18845  					}
 18846  					if int32(prg.curList.modeField) == -vmode {
 18847  						*prg.mem[int32(r1)+heightOffset].int() = *prg.mem[int32(q)+heightOffset].int()
 18848  						*prg.mem[int32(r1)+depthOffset].int() = *prg.mem[int32(q)+depthOffset].int()
 18849  						if t == *prg.mem[int32(r1)+widthOffset].int() {
 18850  							*(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(normal)
 18851  							*(*prg.mem[int32(r1)+listOffset].hh()).b1() = byte(normal)
 18852  							*prg.mem[int32(r1)+glueOffset].gr() = float32(0.0)
 18853  						} else if t > *prg.mem[int32(r1)+widthOffset].int() {
 18854  							*(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(stretching)
 18855  							if *prg.mem[int32(r1)+glueOffset].int() == 0 {
 18856  								*prg.mem[int32(r1)+glueOffset].gr() = float32(0.0)
 18857  							} else {
 18858  								*prg.mem[int32(r1)+glueOffset].gr() = float32(float64(t-*prg.mem[int32(r1)+widthOffset].int()) / float64(*prg.mem[int32(r1)+glueOffset].int()))
 18859  							}
 18860  							// \xref[real division]
 18861  						} else {
 18862  							*(*prg.mem[int32(r1)+listOffset].hh()).b1() = *(*prg.mem[int32(r1)+listOffset].hh()).b0()
 18863  							*(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(shrinking)
 18864  							if *prg.mem[int32(r1)+4].int() == 0 {
 18865  								*prg.mem[int32(r1)+glueOffset].gr() = float32(0.0)
 18866  							} else if int32(*(*prg.mem[int32(r1)+listOffset].hh()).b1()) == normal && *prg.mem[int32(r1)+widthOffset].int()-t > *prg.mem[int32(r1)+4].int() {
 18867  								*prg.mem[int32(r1)+glueOffset].gr() = float32(1.0)
 18868  							} else {
 18869  								*prg.mem[int32(r1)+glueOffset].gr() = float32(float64(*prg.mem[int32(r1)+widthOffset].int()-t) / float64(*prg.mem[int32(r1)+4].int()))
 18870  							}
 18871  						}
 18872  						*prg.mem[int32(r1)+widthOffset].int() = w
 18873  						*(*prg.mem[r1].hh()).b0() = byte(hlistNode)
 18874  					} else {
 18875  						// Make the unset node |r| into a |vlist_node| of height |w|, setting the glue as if the height were |t|
 18876  						*prg.mem[int32(r1)+widthOffset].int() = *prg.mem[int32(q)+widthOffset].int()
 18877  						if t == *prg.mem[int32(r1)+heightOffset].int() {
 18878  							*(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(normal)
 18879  							*(*prg.mem[int32(r1)+listOffset].hh()).b1() = byte(normal)
 18880  							*prg.mem[int32(r1)+glueOffset].gr() = float32(0.0)
 18881  						} else if t > *prg.mem[int32(r1)+heightOffset].int() {
 18882  							*(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(stretching)
 18883  							if *prg.mem[int32(r1)+glueOffset].int() == 0 {
 18884  								*prg.mem[int32(r1)+glueOffset].gr() = float32(0.0)
 18885  							} else {
 18886  								*prg.mem[int32(r1)+glueOffset].gr() = float32(float64(t-*prg.mem[int32(r1)+heightOffset].int()) / float64(*prg.mem[int32(r1)+glueOffset].int()))
 18887  							}
 18888  							// \xref[real division]
 18889  						} else {
 18890  							*(*prg.mem[int32(r1)+listOffset].hh()).b1() = *(*prg.mem[int32(r1)+listOffset].hh()).b0()
 18891  							*(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(shrinking)
 18892  							if *prg.mem[int32(r1)+4].int() == 0 {
 18893  								*prg.mem[int32(r1)+glueOffset].gr() = float32(0.0)
 18894  							} else if int32(*(*prg.mem[int32(r1)+listOffset].hh()).b1()) == normal && *prg.mem[int32(r1)+heightOffset].int()-t > *prg.mem[int32(r1)+4].int() {
 18895  								*prg.mem[int32(r1)+glueOffset].gr() = float32(1.0)
 18896  							} else {
 18897  								*prg.mem[int32(r1)+glueOffset].gr() = float32(float64(*prg.mem[int32(r1)+heightOffset].int()-t) / float64(*prg.mem[int32(r1)+4].int()))
 18898  							}
 18899  						}
 18900  						*prg.mem[int32(r1)+heightOffset].int() = w
 18901  						*(*prg.mem[r1].hh()).b0() = byte(vlistNode)
 18902  					}
 18903  					*prg.mem[int32(r1)+4].int() = 0
 18904  					if int32(u) != 30000-4 {
 18905  						*(*prg.mem[u].hh()).rh() = *(*prg.mem[r1].hh()).rh()
 18906  						*(*prg.mem[r1].hh()).rh() = *(*prg.mem[30000-4].hh()).rh()
 18907  						r1 = u
 18908  					}
 18909  					r1 = *(*prg.mem[*(*prg.mem[r1].hh()).rh()].hh()).rh()
 18910  					s = *(*prg.mem[*(*prg.mem[s].hh()).rh()].hh()).rh()
 18911  					if int32(r1) == 0 {
 18912  						break
 18913  					}
 18914  				}
 18915  			} else if int32(*(*prg.mem[q].hh()).b0()) == ruleNode {
 18916  				if *prg.mem[int32(q)+widthOffset].int() == -010000000000 {
 18917  					*prg.mem[int32(q)+widthOffset].int() = *prg.mem[int32(p)+widthOffset].int()
 18918  				}
 18919  				if *prg.mem[int32(q)+heightOffset].int() == -010000000000 {
 18920  					*prg.mem[int32(q)+heightOffset].int() = *prg.mem[int32(p)+heightOffset].int()
 18921  				}
 18922  				if *prg.mem[int32(q)+depthOffset].int() == -010000000000 {
 18923  					*prg.mem[int32(q)+depthOffset].int() = *prg.mem[int32(p)+depthOffset].int()
 18924  				}
 18925  				if o != 0 {
 18926  					r1 = *(*prg.mem[q].hh()).rh()
 18927  					*(*prg.mem[q].hh()).rh() = 0
 18928  					q = prg.hpack(q, scaled(0), smallNumber(additional))
 18929  					*prg.mem[int32(q)+4].int() = o
 18930  					*(*prg.mem[q].hh()).rh() = r1
 18931  					*(*prg.mem[s].hh()).rh() = q
 18932  				}
 18933  			}
 18934  		}
 18935  		s = q
 18936  		q = *(*prg.mem[q].hh()).rh()
 18937  	}
 18938  	prg.flushNodeList(p)
 18939  	prg.popAlignment()
 18940  
 18941  	// Insert the \(c)current list into its environment
 18942  	auxSave = prg.curList.auxField
 18943  	p = *(*prg.mem[prg.curList.headField].hh()).rh()
 18944  	q = prg.curList.tailField
 18945  	prg.popNest()
 18946  	if int32(prg.curList.modeField) == mmode {
 18947  		prg.doAssignments()
 18948  		if int32(prg.curCmd) != mathShift {
 18949  			{
 18950  				if int32(prg.interaction) == errorStopMode {
 18951  				}
 18952  				prg.printNl(strNumber( /* "! " */ 262))
 18953  				prg.print( /* "Missing $$ inserted" */ 1170)
 18954  			}
 18955  			// \xref[Missing [\$\$] inserted]
 18956  			{
 18957  				prg.helpPtr = 2
 18958  				prg.helpLine[1] = /* "Displays can use special alignments (like \\eqalignno)" */ 895
 18959  				prg.helpLine[0] = /* "only if nothing but the alignment itself is between $$'s." */ 896
 18960  			}
 18961  			prg.backError()
 18962  		} else {
 18963  			// Check that another \.\$ follows
 18964  			prg.getXToken()
 18965  			if int32(prg.curCmd) != mathShift {
 18966  				{
 18967  					if int32(prg.interaction) == errorStopMode {
 18968  					}
 18969  					prg.printNl(strNumber( /* "! " */ 262))
 18970  					prg.print( /* "Display math should end with $$" */ 1166)
 18971  				}
 18972  				// \xref[Display math...with \$\$]
 18973  				{
 18974  					prg.helpPtr = 2
 18975  					prg.helpLine[1] = /* "The `$' that I just saw supposedly matches a previous `$$'." */ 1167
 18976  					prg.helpLine[0] = /* "So I shall assume that you typed `$$' both times." */ 1168
 18977  				}
 18978  				prg.backError()
 18979  			}
 18980  		}
 18981  		prg.popNest()
 18982  		{
 18983  			*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newPenalty(*prg.eqtb[intBase+preDisplayPenaltyCode-1].int())
 18984  			prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 18985  		}
 18986  		{
 18987  			*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newParamGlue(smallNumber(aboveDisplaySkipCode))
 18988  			prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 18989  		}
 18990  		*(*prg.mem[prg.curList.tailField].hh()).rh() = p
 18991  		if int32(p) != 0 {
 18992  			prg.curList.tailField = q
 18993  		}
 18994  		{
 18995  			*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newPenalty(*prg.eqtb[intBase+postDisplayPenaltyCode-1].int())
 18996  			prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 18997  		}
 18998  		{
 18999  			*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newParamGlue(smallNumber(belowDisplaySkipCode))
 19000  			prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 19001  		}
 19002  		*prg.curList.auxField.int() = *auxSave.int()
 19003  		prg.resumeAfterDisplay()
 19004  	} else {
 19005  		prg.curList.auxField = auxSave
 19006  		*(*prg.mem[prg.curList.tailField].hh()).rh() = p
 19007  		if int32(p) != 0 {
 19008  			prg.curList.tailField = q
 19009  		}
 19010  		if int32(prg.curList.modeField) == vmode {
 19011  			prg.buildPage()
 19012  		}
 19013  	}
 19014  }
 19015  
 19016  //
 19017  
 19018  func (prg *prg) alignPeek() {
 19019  restart:
 19020  	prg.alignState = 1000000
 19021  	// Get the next non-blank non-call token
 19022  	for {
 19023  		prg.getXToken()
 19024  		if int32(prg.curCmd) != spacer {
 19025  			break
 19026  		}
 19027  	}
 19028  	if int32(prg.curCmd) == noAlign {
 19029  		prg.scanLeftBrace()
 19030  		prg.newSaveLevel(groupCode(noAlignGroup))
 19031  		if int32(prg.curList.modeField) == -vmode {
 19032  			prg.normalParagraph()
 19033  		}
 19034  	} else if int32(prg.curCmd) == rightBrace {
 19035  		prg.finAlign()
 19036  	} else if int32(prg.curCmd) == carRet && int32(prg.curChr) == crCrCode {
 19037  		goto restart
 19038  	} else {
 19039  		prg.initRow() // start a new row
 19040  		prg.initCol() // start a new column and replace what we peeked at
 19041  	}
 19042  }
 19043  
 19044  // 813. \[38] Breaking paragraphs into lines
 19045  
 19046  // tangle:pos tex.web:15997:39:
 19047  
 19048  // We come now to what is probably the most interesting algorithm of \TeX:
 19049  // the mechanism for choosing the ``best possible'' breakpoints that yield
 19050  // the individual lines of a paragraph. \TeX's line-breaking algorithm takes
 19051  // a given horizontal list and converts it to a sequence of boxes that are
 19052  // appended to the current vertical list. In the course of doing this, it
 19053  // creates a special data structure containing three kinds of records that are
 19054  // not used elsewhere in \TeX. Such nodes are created while a paragraph is
 19055  // being processed, and they are destroyed afterwards; thus, the other parts
 19056  // of \TeX\ do not need to know anything about how line-breaking is done.
 19057  //
 19058  // The method used here is based on an approach devised by Michael F. Plass and
 19059  // \xref[Plass, Michael Frederick]
 19060  // \xref[Knuth, Donald Ervin]
 19061  // the author in 1977, subsequently generalized and improved by the same two
 19062  // people in 1980. A detailed discussion appears in [\sl Software---Practice
 19063  // and Experience \bf11] (1981), 1119--1184, where it is shown that the
 19064  // line-breaking problem can be regarded as a special case of the problem of
 19065  // computing the shortest path in an acyclic network. The cited paper includes
 19066  // numerous examples and describes the history of line breaking as it has been
 19067  // practiced by printers through the ages. The present implementation adds two
 19068  // new ideas to the algorithm of 1980: Memory space requirements are considerably
 19069  // reduced by using smaller records for inactive nodes than for active ones,
 19070  // and arithmetic overflow is avoided by using ``delta distances'' instead of
 19071  // keeping track of the total distance from the beginning of the paragraph to the
 19072  // current point.
 19073  
 19074  // 815.
 19075  
 19076  // tangle:pos tex.web:16048:1:
 19077  
 19078  // Since |line_break| is a rather lengthy procedure---sort of a small world unto
 19079  // itself---we must build it up little by little, somewhat more cautiously
 19080  // than we have done with the simpler procedures of \TeX. Here is the
 19081  // general outline.
 19082  // \4
 19083  // Declare subprocedures for |line_break|
 19084  func (prg *prg) finiteShrink(p halfword) (r halfword) { // recovers from infinite shrinkage
 19085  	var (
 19086  		q halfword // new glue specification
 19087  	)
 19088  	if prg.noShrinkErrorYet {
 19089  		prg.noShrinkErrorYet = false
 19090  		// if eqtb[int_base+ tracing_paragraphs_code].int  >0 then end_diagnostic(true); [  ]
 19091  		{
 19092  			if int32(prg.interaction) == errorStopMode {
 19093  			}
 19094  			prg.printNl(strNumber( /* "! " */ 262))
 19095  			prg.print( /* "Infinite glue shrinkage found in a paragraph" */ 917)
 19096  		}
 19097  		// \xref[Infinite glue shrinkage...]
 19098  		{
 19099  			prg.helpPtr = 5
 19100  			prg.helpLine[4] = /* "The paragraph just ended includes some glue that has" */ 918
 19101  			prg.helpLine[3] = /* "infinite shrinkability, e.g., `\\hskip 0pt minus 1fil'." */ 919
 19102  			prg.helpLine[2] = /* "Such glue doesn't belong there---it allows a paragraph" */ 920
 19103  			prg.helpLine[1] = /* "of any length to fit on one line. But it's safe to proceed," */ 921
 19104  			prg.helpLine[0] = /* "since the offensive shrinkability has been made finite." */ 922
 19105  		}
 19106  		prg.error1()
 19107  		//  if eqtb[int_base+ tracing_paragraphs_code].int  >0 then begin_diagnostic; [  ]
 19108  	}
 19109  	q = prg.newSpec(p)
 19110  	*(*prg.mem[q].hh()).b1() = byte(normal)
 19111  	prg.deleteGlueRef(p)
 19112  	r = q
 19113  	return r
 19114  }
 19115  
 19116  func (prg *prg) tryBreak(pi int32, breakType smallNumber) {
 19117  	var (
 19118  		r1         halfword // runs through the active list
 19119  		prevR      halfword // stays a step behind |r|
 19120  		oldL       halfword // maximum line number in current equivalence class of lines
 19121  		noBreakYet bool     // have we found a feasible break at |cur_p|?
 19122  
 19123  		// Other local variables for |try_break|
 19124  		prevPrevR                                 halfword           // a step behind |prev_r|, if |type(prev_r)=delta_node|
 19125  		s                                         halfword           // runs through nodes ahead of |cur_p|
 19126  		q                                         halfword           // points to a new node being created
 19127  		v                                         halfword           // points to a glue specification or a node ahead of |cur_p|
 19128  		t                                         int32              // node count, if |cur_p| is a discretionary node
 19129  		f                                         internalFontNumber // used in character width calculation
 19130  		l                                         halfword           // line number of current active node
 19131  		nodeRStaysActive                          bool               // should node |r| remain in the active list?
 19132  		lineWidth                                 scaled             // the current line will be justified to this width
 19133  		fitClass/* veryLooseFit..tightFit */ byte                    // possible fitness class of test line
 19134  		b                                         halfword           // badness of test line
 19135  		d                                         int32              // demerits of test line
 19136  		artificialDemerits                        bool               // has |d| been forced to zero?
 19137  		shortfall                                 scaled             // used in badness calculations
 19138  	)
 19139  	if abs(pi) >= infPenalty {
 19140  		if pi > 0 {
 19141  			goto exit
 19142  		} else {
 19143  			pi = ejectPenalty
 19144  		}
 19145  	}
 19146  	noBreakYet = true
 19147  	prevR = uint16(30000 - 7)
 19148  	oldL = 0
 19149  	prg.curActiveWidth[1-1] = prg.activeWidth[1-1]
 19150  	prg.curActiveWidth[2-1] = prg.activeWidth[2-1]
 19151  	prg.curActiveWidth[3-1] = prg.activeWidth[3-1]
 19152  	prg.curActiveWidth[4-1] = prg.activeWidth[4-1]
 19153  	prg.curActiveWidth[5-1] = prg.activeWidth[5-1]
 19154  	prg.curActiveWidth[6-1] = prg.activeWidth[6-1]
 19155  	for true {
 19156  	continue1:
 19157  		r1 = *(*prg.mem[prevR].hh()).rh()
 19158  
 19159  		// If node |r| is of type |delta_node|, update |cur_active_width|, set |prev_r| and |prev_prev_r|, then |goto continue|
 19160  		// \xref[inner loop]
 19161  		if int32(*(*prg.mem[r1].hh()).b0()) == deltaNode {
 19162  			prg.curActiveWidth[1-1] = prg.curActiveWidth[1-1] + *prg.mem[int32(r1)+1].int()
 19163  			prg.curActiveWidth[2-1] = prg.curActiveWidth[2-1] + *prg.mem[int32(r1)+2].int()
 19164  			prg.curActiveWidth[3-1] = prg.curActiveWidth[3-1] + *prg.mem[int32(r1)+3].int()
 19165  			prg.curActiveWidth[4-1] = prg.curActiveWidth[4-1] + *prg.mem[int32(r1)+4].int()
 19166  			prg.curActiveWidth[5-1] = prg.curActiveWidth[5-1] + *prg.mem[int32(r1)+5].int()
 19167  			prg.curActiveWidth[6-1] = prg.curActiveWidth[6-1] + *prg.mem[int32(r1)+6].int()
 19168  			prevPrevR = prevR
 19169  			prevR = r1
 19170  			goto continue1
 19171  		}
 19172  
 19173  		// If a line number class has ended, create new active nodes for the best feasible breaks in that class; then |return| if |r=last_active|, otherwise compute the new |line_width|
 19174  		{
 19175  			l = *(*prg.mem[int32(r1)+1].hh()).lh()
 19176  			if int32(l) > int32(oldL) {
 19177  				if prg.minimumDemerits < 07777777777 && (int32(oldL) != int32(prg.easyLine) || int32(r1) == 30000-7) {
 19178  					if noBreakYet {
 19179  						noBreakYet = false
 19180  						prg.breakWidth[1-1] = prg.background[1-1]
 19181  						prg.breakWidth[2-1] = prg.background[2-1]
 19182  						prg.breakWidth[3-1] = prg.background[3-1]
 19183  						prg.breakWidth[4-1] = prg.background[4-1]
 19184  						prg.breakWidth[5-1] = prg.background[5-1]
 19185  						prg.breakWidth[6-1] = prg.background[6-1]
 19186  						s = prg.curP
 19187  						if int32(breakType) > unhyphenated {
 19188  							if int32(prg.curP) != 0 {
 19189  								t = int32(*(*prg.mem[prg.curP].hh()).b1())
 19190  								v = prg.curP
 19191  								s = *(*prg.mem[int32(prg.curP)+1].hh()).rh()
 19192  								for t > 0 {
 19193  									t = t - 1
 19194  									v = *(*prg.mem[v].hh()).rh()
 19195  
 19196  									// Subtract the width of node |v| from |break_width|
 19197  									if int32(v) >= int32(prg.hiMemMin) {
 19198  										f = *(*prg.mem[v].hh()).b0()
 19199  										prg.breakWidth[1-1] = prg.breakWidth[1-1] - *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[v].hh()).b1())].qqqq()).b0)].int()
 19200  									} else {
 19201  										switch *(*prg.mem[v].hh()).b0() {
 19202  										case ligatureNode:
 19203  											f = *(*prg.mem[int32(v)+1].hh()).b0()
 19204  
 19205  											prg.breakWidth[1-1] = prg.breakWidth[1-1] - *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[int32(v)+1].hh()).b1())].qqqq()).b0)].int()
 19206  
 19207  										case hlistNode, vlistNode, ruleNode, kernNode:
 19208  											prg.breakWidth[1-1] = prg.breakWidth[1-1] - *prg.mem[int32(v)+widthOffset].int()
 19209  
 19210  										default:
 19211  											prg.confusion(strNumber( /* "disc1" */ 923))
 19212  											// \xref[this can't happen disc1][\quad disc1]
 19213  										}
 19214  									}
 19215  								}
 19216  								for int32(s) != 0 {
 19217  									if int32(s) >= int32(prg.hiMemMin) {
 19218  										f = *(*prg.mem[s].hh()).b0()
 19219  										prg.breakWidth[1-1] = prg.breakWidth[1-1] + *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[s].hh()).b1())].qqqq()).b0)].int()
 19220  									} else {
 19221  										switch *(*prg.mem[s].hh()).b0() {
 19222  										case ligatureNode:
 19223  											f = *(*prg.mem[int32(s)+1].hh()).b0()
 19224  											prg.breakWidth[1-1] = prg.breakWidth[1-1] + *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[int32(s)+1].hh()).b1())].qqqq()).b0)].int()
 19225  
 19226  										case hlistNode, vlistNode, ruleNode, kernNode:
 19227  											prg.breakWidth[1-1] = prg.breakWidth[1-1] + *prg.mem[int32(s)+widthOffset].int()
 19228  
 19229  										default:
 19230  											prg.confusion(strNumber( /* "disc2" */ 924))
 19231  											// \xref[this can't happen disc2][\quad disc2]
 19232  										}
 19233  									}
 19234  									s = *(*prg.mem[s].hh()).rh()
 19235  								}
 19236  								prg.breakWidth[1-1] = prg.breakWidth[1-1] + prg.discWidth
 19237  								if int32(*(*prg.mem[int32(prg.curP)+1].hh()).rh()) == 0 {
 19238  									s = *(*prg.mem[v].hh()).rh()
 19239  								}
 19240  								// nodes may be discardable after the break
 19241  							}
 19242  						}
 19243  						for int32(s) != 0 {
 19244  							if int32(s) >= int32(prg.hiMemMin) {
 19245  								goto done
 19246  							}
 19247  							switch *(*prg.mem[s].hh()).b0() {
 19248  							case glueNode:
 19249  								// Subtract glue from |break_width|
 19250  								v = *(*prg.mem[int32(s)+1].hh()).lh()
 19251  								prg.breakWidth[1-1] = prg.breakWidth[1-1] - *prg.mem[int32(v)+widthOffset].int()
 19252  								prg.breakWidth[2+int32(*(*prg.mem[v].hh()).b0())-1] = prg.breakWidth[2+int32(*(*prg.mem[v].hh()).b0())-1] - *prg.mem[int32(v)+2].int()
 19253  								prg.breakWidth[6-1] = prg.breakWidth[6-1] - *prg.mem[int32(v)+3].int()
 19254  
 19255  							case penaltyNode:
 19256  							case mathNode:
 19257  								prg.breakWidth[1-1] = prg.breakWidth[1-1] - *prg.mem[int32(s)+widthOffset].int()
 19258  							case kernNode:
 19259  								if int32(*(*prg.mem[s].hh()).b1()) != explicit {
 19260  									goto done
 19261  								} else {
 19262  									prg.breakWidth[1-1] = prg.breakWidth[1-1] - *prg.mem[int32(s)+widthOffset].int()
 19263  								}
 19264  
 19265  							default:
 19266  								goto done
 19267  							}
 19268  
 19269  							s = *(*prg.mem[s].hh()).rh()
 19270  						}
 19271  
 19272  					done:
 19273  					}
 19274  
 19275  					// Insert a delta node to prepare for breaks at |cur_p|
 19276  					if int32(*(*prg.mem[prevR].hh()).b0()) == deltaNode {
 19277  						*prg.mem[int32(prevR)+1].int() = *prg.mem[int32(prevR)+1].int() - prg.curActiveWidth[1-1] + prg.breakWidth[1-1]
 19278  						*prg.mem[int32(prevR)+2].int() = *prg.mem[int32(prevR)+2].int() - prg.curActiveWidth[2-1] + prg.breakWidth[2-1]
 19279  						*prg.mem[int32(prevR)+3].int() = *prg.mem[int32(prevR)+3].int() - prg.curActiveWidth[3-1] + prg.breakWidth[3-1]
 19280  						*prg.mem[int32(prevR)+4].int() = *prg.mem[int32(prevR)+4].int() - prg.curActiveWidth[4-1] + prg.breakWidth[4-1]
 19281  						*prg.mem[int32(prevR)+5].int() = *prg.mem[int32(prevR)+5].int() - prg.curActiveWidth[5-1] + prg.breakWidth[5-1]
 19282  						*prg.mem[int32(prevR)+6].int() = *prg.mem[int32(prevR)+6].int() - prg.curActiveWidth[6-1] + prg.breakWidth[6-1]
 19283  					} else if int32(prevR) == 30000-7 {
 19284  						prg.activeWidth[1-1] = prg.breakWidth[1-1]
 19285  						prg.activeWidth[2-1] = prg.breakWidth[2-1]
 19286  						prg.activeWidth[3-1] = prg.breakWidth[3-1]
 19287  						prg.activeWidth[4-1] = prg.breakWidth[4-1]
 19288  						prg.activeWidth[5-1] = prg.breakWidth[5-1]
 19289  						prg.activeWidth[6-1] = prg.breakWidth[6-1]
 19290  					} else {
 19291  						q = prg.getNode(deltaNodeSize)
 19292  						*(*prg.mem[q].hh()).rh() = r1
 19293  						*(*prg.mem[q].hh()).b0() = byte(deltaNode)
 19294  
 19295  						*(*prg.mem[q].hh()).b1() = 0 // the |subtype| is not used
 19296  						*prg.mem[int32(q)+1].int() = prg.breakWidth[1-1] - prg.curActiveWidth[1-1]
 19297  						*prg.mem[int32(q)+2].int() = prg.breakWidth[2-1] - prg.curActiveWidth[2-1]
 19298  						*prg.mem[int32(q)+3].int() = prg.breakWidth[3-1] - prg.curActiveWidth[3-1]
 19299  						*prg.mem[int32(q)+4].int() = prg.breakWidth[4-1] - prg.curActiveWidth[4-1]
 19300  						*prg.mem[int32(q)+5].int() = prg.breakWidth[5-1] - prg.curActiveWidth[5-1]
 19301  						*prg.mem[int32(q)+6].int() = prg.breakWidth[6-1] - prg.curActiveWidth[6-1]
 19302  						*(*prg.mem[prevR].hh()).rh() = q
 19303  						prevPrevR = prevR
 19304  						prevR = q
 19305  					}
 19306  					if abs(*prg.eqtb[intBase+adjDemeritsCode-1].int()) >= 07777777777-prg.minimumDemerits {
 19307  						prg.minimumDemerits = 07777777777 - 1
 19308  					} else {
 19309  						prg.minimumDemerits = prg.minimumDemerits + abs(*prg.eqtb[intBase+adjDemeritsCode-1].int())
 19310  					}
 19311  					for ii := int32(veryLooseFit); ii <= tightFit; ii++ {
 19312  						fitClass = byte(ii)
 19313  						_ = fitClass
 19314  						if prg.minimalDemerits[fitClass] <= prg.minimumDemerits {
 19315  							q = prg.getNode(passiveNodeSize)
 19316  							*(*prg.mem[q].hh()).rh() = prg.passive
 19317  							prg.passive = q
 19318  							*(*prg.mem[int32(q)+1].hh()).rh() = prg.curP
 19319  							//    pass_number:= pass_number+1 ;  mem[ q].hh.lh :=pass_number; [  ]
 19320  
 19321  							*(*prg.mem[int32(q)+1].hh()).lh() = prg.bestPlace[fitClass]
 19322  
 19323  							q = prg.getNode(activeNodeSize)
 19324  							*(*prg.mem[int32(q)+1].hh()).rh() = prg.passive
 19325  							*(*prg.mem[int32(q)+1].hh()).lh() = uint16(int32(prg.bestPlLine[fitClass]) + 1)
 19326  							*(*prg.mem[q].hh()).b1() = fitClass
 19327  							*(*prg.mem[q].hh()).b0() = breakType
 19328  							*prg.mem[int32(q)+2].int() = prg.minimalDemerits[fitClass]
 19329  							*(*prg.mem[q].hh()).rh() = r1
 19330  							*(*prg.mem[prevR].hh()).rh() = q
 19331  							prevR = q
 19332  							//  if eqtb[int_base+ tracing_paragraphs_code].int  >0 then
 19333  							//
 19334  							// [ Print a symbolic description of the new break node ]
 19335  							// begin print_nl(["@@"=]925); print_int( mem[ passive].hh.lh );
 19336  							// [ \xref[\AT!\AT!] ]
 19337  							// print([": line "=]926); print_int(  mem[  q+ 1].hh.lh  -1);
 19338  							// print_char(["."=]46); print_int(fit_class);
 19339  							// if break_type=hyphenated then print_char(["-"=]45);
 19340  							// print([" t="=]927); print_int(mem[ q+2].int );
 19341  							// print([" -> @@"=]928);
 19342  							// if   mem[  passive+ 1].hh.lh  =0   then print_char(["0"=]48)
 19343  							// else print_int( mem[   mem[   passive+ 1].hh.lh  ].hh.lh );
 19344  							// end
 19345  							//
 19346  							// ;
 19347  							// [  ]
 19348  
 19349  						}
 19350  						prg.minimalDemerits[fitClass] = 07777777777
 19351  					}
 19352  					prg.minimumDemerits = 07777777777
 19353  
 19354  					// Insert a delta node to prepare for the next active node
 19355  					if int32(r1) != 30000-7 {
 19356  						q = prg.getNode(deltaNodeSize)
 19357  						*(*prg.mem[q].hh()).rh() = r1
 19358  						*(*prg.mem[q].hh()).b0() = byte(deltaNode)
 19359  
 19360  						*(*prg.mem[q].hh()).b1() = 0 // the |subtype| is not used
 19361  						*prg.mem[int32(q)+1].int() = prg.curActiveWidth[1-1] - prg.breakWidth[1-1]
 19362  						*prg.mem[int32(q)+2].int() = prg.curActiveWidth[2-1] - prg.breakWidth[2-1]
 19363  						*prg.mem[int32(q)+3].int() = prg.curActiveWidth[3-1] - prg.breakWidth[3-1]
 19364  						*prg.mem[int32(q)+4].int() = prg.curActiveWidth[4-1] - prg.breakWidth[4-1]
 19365  						*prg.mem[int32(q)+5].int() = prg.curActiveWidth[5-1] - prg.breakWidth[5-1]
 19366  						*prg.mem[int32(q)+6].int() = prg.curActiveWidth[6-1] - prg.breakWidth[6-1]
 19367  						*(*prg.mem[prevR].hh()).rh() = q
 19368  						prevPrevR = prevR
 19369  						prevR = q
 19370  					}
 19371  				}
 19372  				if int32(r1) == 30000-7 {
 19373  					goto exit
 19374  				}
 19375  
 19376  				// Compute the new line width
 19377  				if int32(l) > int32(prg.easyLine) {
 19378  					lineWidth = prg.secondWidth
 19379  					oldL = uint16(65535 - 1)
 19380  				} else {
 19381  					oldL = l
 19382  					if int32(l) > int32(prg.lastSpecialLine) {
 19383  						lineWidth = prg.secondWidth
 19384  					} else if int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh()) == 0 {
 19385  						lineWidth = prg.firstWidth
 19386  					} else {
 19387  						lineWidth = *prg.mem[int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh())+2*int32(l)].int()
 19388  					}
 19389  				}
 19390  			}
 19391  		}
 19392  
 19393  		// Consider the demerits for a line from |r| to |cur_p|; deactivate node |r| if it should no longer be active; then |goto continue| if a line from |r| to |cur_p| is infeasible, otherwise record a new feasible break
 19394  		{
 19395  			artificialDemerits = false
 19396  
 19397  			// \xref[inner loop]
 19398  			shortfall = lineWidth - prg.curActiveWidth[1-1] // we're this much too short
 19399  			if shortfall > 0 {
 19400  				if prg.curActiveWidth[3-1] != 0 || prg.curActiveWidth[4-1] != 0 || prg.curActiveWidth[5-1] != 0 {
 19401  					b = 0
 19402  					fitClass = byte(decentFit) // infinite stretch
 19403  				} else {
 19404  					if shortfall > 7230584 {
 19405  						if prg.curActiveWidth[2-1] < 1663497 {
 19406  							b = uint16(infBad)
 19407  							fitClass = byte(veryLooseFit)
 19408  							goto done1
 19409  						}
 19410  					}
 19411  					b = prg.badness(shortfall, prg.curActiveWidth[2-1])
 19412  					if int32(b) > 12 {
 19413  						if int32(b) > 99 {
 19414  							fitClass = byte(veryLooseFit)
 19415  						} else {
 19416  							fitClass = byte(looseFit)
 19417  						}
 19418  					} else {
 19419  						fitClass = byte(decentFit)
 19420  					}
 19421  
 19422  				done1:
 19423  				}
 19424  			} else {
 19425  				// Set the value of |b| to the badness for shrinking the line, and compute the corresponding |fit_class|
 19426  				if -shortfall > prg.curActiveWidth[6-1] {
 19427  					b = uint16(infBad + 1)
 19428  				} else {
 19429  					b = prg.badness(-shortfall, prg.curActiveWidth[6-1])
 19430  				}
 19431  				if int32(b) > 12 {
 19432  					fitClass = byte(tightFit)
 19433  				} else {
 19434  					fitClass = byte(decentFit)
 19435  				}
 19436  			}
 19437  			if int32(b) > infBad || pi == ejectPenalty {
 19438  				if prg.finalPass && prg.minimumDemerits == 07777777777 && int32(*(*prg.mem[r1].hh()).rh()) == 30000-7 && int32(prevR) == 30000-7 {
 19439  					artificialDemerits = true
 19440  				} else if int32(b) > prg.threshold {
 19441  					goto deactivate
 19442  				}
 19443  				nodeRStaysActive = false
 19444  			} else {
 19445  				prevR = r1
 19446  				if int32(b) > prg.threshold {
 19447  					goto continue1
 19448  				}
 19449  				nodeRStaysActive = true
 19450  			}
 19451  
 19452  			// Record a new feasible break
 19453  			if artificialDemerits {
 19454  				d = 0
 19455  			} else {
 19456  				// Compute the demerits, |d|, from |r| to |cur_p|
 19457  				d = *prg.eqtb[intBase+linePenaltyCode-1].int() + int32(b)
 19458  				if abs(d) >= 10000 {
 19459  					d = 100000000
 19460  				} else {
 19461  					d = d * d
 19462  				}
 19463  				if pi != 0 {
 19464  					if pi > 0 {
 19465  						d = d + pi*pi
 19466  					} else if pi > ejectPenalty {
 19467  						d = d - pi*pi
 19468  					}
 19469  				}
 19470  				if int32(breakType) == hyphenated && int32(*(*prg.mem[r1].hh()).b0()) == hyphenated {
 19471  					if int32(prg.curP) != 0 {
 19472  						d = d + *prg.eqtb[intBase+doubleHyphenDemeritsCode-1].int()
 19473  					} else {
 19474  						d = d + *prg.eqtb[intBase+finalHyphenDemeritsCode-1].int()
 19475  					}
 19476  				}
 19477  				if abs(int32(fitClass)-int32(*(*prg.mem[r1].hh()).b1())) > 1 {
 19478  					d = d + *prg.eqtb[intBase+adjDemeritsCode-1].int()
 19479  				}
 19480  			}
 19481  			//  if eqtb[int_base+ tracing_paragraphs_code].int  >0 then
 19482  			//
 19483  			// [ Print a symbolic description of this feasible break ]
 19484  			// begin if printed_node<>cur_p then
 19485  			//
 19486  			// [ Print the list between |printed_node| and |cur_p|, then set |printed_node:=cur_p| ]
 19487  			// begin print_nl([""=]338);
 19488  			// if cur_p=0   then short_display( mem[ printed_node].hh.rh )
 19489  			// else  begin save_link:= mem[ cur_p].hh.rh ;
 19490  			//    mem[ cur_p].hh.rh :=0  ; print_nl([""=]338); short_display( mem[ printed_node].hh.rh );
 19491  			//    mem[ cur_p].hh.rh :=save_link;
 19492  			//   end;
 19493  			// printed_node:=cur_p;
 19494  			// end
 19495  			//
 19496  			// ;
 19497  			// print_nl(["@"=]64);
 19498  			// [ \xref[\AT!] ]
 19499  			// if cur_p=0   then print_esc(["par"=]597)
 19500  			// else if  mem[ cur_p].hh.b0 <>glue_node then
 19501  			//   begin if  mem[ cur_p].hh.b0 =penalty_node then print_esc(["penalty"=]531)
 19502  			//   else if  mem[ cur_p].hh.b0 =disc_node then print_esc(["discretionary"=]349)
 19503  			//   else if  mem[ cur_p].hh.b0 =kern_node then print_esc(["kern"=]340)
 19504  			//   else print_esc(["math"=]343);
 19505  			//   end;
 19506  			// print([" via @@"=]929);
 19507  			// if   mem[  r+ 1].hh.rh  =0   then print_char(["0"=]48)
 19508  			// else print_int( mem[   mem[   r+ 1].hh.rh  ].hh.lh );
 19509  			// print([" b="=]930);
 19510  			// if b>inf_bad then print_char(["*"=]42) else print_int(b);
 19511  			// [ \xref[*\relax] ]
 19512  			// print([" p="=]931); print_int(pi); print([" d="=]932);
 19513  			// if artificial_demerits then print_char(["*"=]42) else print_int(d);
 19514  			// end
 19515  			//
 19516  			// ;
 19517  			// [  ]
 19518  
 19519  			d = d + *prg.mem[int32(r1)+2].int() // this is the minimum total demerits
 19520  			//   from the beginning to |cur_p| via |r|
 19521  
 19522  			if d <= prg.minimalDemerits[fitClass] {
 19523  				prg.minimalDemerits[fitClass] = d
 19524  				prg.bestPlace[fitClass] = *(*prg.mem[int32(r1)+1].hh()).rh()
 19525  				prg.bestPlLine[fitClass] = l
 19526  				if d < prg.minimumDemerits {
 19527  					prg.minimumDemerits = d
 19528  				}
 19529  			}
 19530  			if nodeRStaysActive {
 19531  				goto continue1
 19532  			} // |prev_r| has been set to |r|
 19533  			// |prev_r| has been set to |r|
 19534  		deactivate:
 19535  			*(*prg.mem[prevR].hh()).rh() = *(*prg.mem[r1].hh()).rh()
 19536  			prg.freeNode(r1, halfword(activeNodeSize))
 19537  			if int32(prevR) == 30000-7 {
 19538  				r1 = *(*prg.mem[30000-7].hh()).rh()
 19539  				if int32(*(*prg.mem[r1].hh()).b0()) == deltaNode {
 19540  					prg.activeWidth[1-1] = prg.activeWidth[1-1] + *prg.mem[int32(r1)+1].int()
 19541  					prg.activeWidth[2-1] = prg.activeWidth[2-1] + *prg.mem[int32(r1)+2].int()
 19542  					prg.activeWidth[3-1] = prg.activeWidth[3-1] + *prg.mem[int32(r1)+3].int()
 19543  					prg.activeWidth[4-1] = prg.activeWidth[4-1] + *prg.mem[int32(r1)+4].int()
 19544  					prg.activeWidth[5-1] = prg.activeWidth[5-1] + *prg.mem[int32(r1)+5].int()
 19545  					prg.activeWidth[6-1] = prg.activeWidth[6-1] + *prg.mem[int32(r1)+6].int()
 19546  					prg.curActiveWidth[1-1] = prg.activeWidth[1-1]
 19547  					prg.curActiveWidth[2-1] = prg.activeWidth[2-1]
 19548  					prg.curActiveWidth[3-1] = prg.activeWidth[3-1]
 19549  					prg.curActiveWidth[4-1] = prg.activeWidth[4-1]
 19550  					prg.curActiveWidth[5-1] = prg.activeWidth[5-1]
 19551  					prg.curActiveWidth[6-1] = prg.activeWidth[6-1]
 19552  					*(*prg.mem[30000-7].hh()).rh() = *(*prg.mem[r1].hh()).rh()
 19553  					prg.freeNode(r1, halfword(deltaNodeSize))
 19554  				}
 19555  			} else if int32(*(*prg.mem[prevR].hh()).b0()) == deltaNode {
 19556  				r1 = *(*prg.mem[prevR].hh()).rh()
 19557  				if int32(r1) == 30000-7 {
 19558  					prg.curActiveWidth[1-1] = prg.curActiveWidth[1-1] - *prg.mem[int32(prevR)+1].int()
 19559  					prg.curActiveWidth[2-1] = prg.curActiveWidth[2-1] - *prg.mem[int32(prevR)+2].int()
 19560  					prg.curActiveWidth[3-1] = prg.curActiveWidth[3-1] - *prg.mem[int32(prevR)+3].int()
 19561  					prg.curActiveWidth[4-1] = prg.curActiveWidth[4-1] - *prg.mem[int32(prevR)+4].int()
 19562  					prg.curActiveWidth[5-1] = prg.curActiveWidth[5-1] - *prg.mem[int32(prevR)+5].int()
 19563  					prg.curActiveWidth[6-1] = prg.curActiveWidth[6-1] - *prg.mem[int32(prevR)+6].int()
 19564  					*(*prg.mem[prevPrevR].hh()).rh() = uint16(30000 - 7)
 19565  					prg.freeNode(prevR, halfword(deltaNodeSize))
 19566  					prevR = prevPrevR
 19567  				} else if int32(*(*prg.mem[r1].hh()).b0()) == deltaNode {
 19568  					prg.curActiveWidth[1-1] = prg.curActiveWidth[1-1] + *prg.mem[int32(r1)+1].int()
 19569  					prg.curActiveWidth[2-1] = prg.curActiveWidth[2-1] + *prg.mem[int32(r1)+2].int()
 19570  					prg.curActiveWidth[3-1] = prg.curActiveWidth[3-1] + *prg.mem[int32(r1)+3].int()
 19571  					prg.curActiveWidth[4-1] = prg.curActiveWidth[4-1] + *prg.mem[int32(r1)+4].int()
 19572  					prg.curActiveWidth[5-1] = prg.curActiveWidth[5-1] + *prg.mem[int32(r1)+5].int()
 19573  					prg.curActiveWidth[6-1] = prg.curActiveWidth[6-1] + *prg.mem[int32(r1)+6].int()
 19574  					*prg.mem[int32(prevR)+1].int() = *prg.mem[int32(prevR)+1].int() + *prg.mem[int32(r1)+1].int()
 19575  					*prg.mem[int32(prevR)+2].int() = *prg.mem[int32(prevR)+2].int() + *prg.mem[int32(r1)+2].int()
 19576  					*prg.mem[int32(prevR)+3].int() = *prg.mem[int32(prevR)+3].int() + *prg.mem[int32(r1)+3].int()
 19577  					*prg.mem[int32(prevR)+4].int() = *prg.mem[int32(prevR)+4].int() + *prg.mem[int32(r1)+4].int()
 19578  					*prg.mem[int32(prevR)+5].int() = *prg.mem[int32(prevR)+5].int() + *prg.mem[int32(r1)+5].int()
 19579  					*prg.mem[int32(prevR)+6].int() = *prg.mem[int32(prevR)+6].int() + *prg.mem[int32(r1)+6].int()
 19580  					*(*prg.mem[prevR].hh()).rh() = *(*prg.mem[r1].hh()).rh()
 19581  					prg.freeNode(r1, halfword(deltaNodeSize))
 19582  				}
 19583  			}
 19584  		}
 19585  	}
 19586  
 19587  exit:
 19588  }
 19589  
 19590  func (prg *prg) postLineBreak(finalWidowPenalty int32) {
 19591  	var (
 19592  		q, r1, s      halfword    // temporary registers for list manipulation
 19593  		discBreak     bool        // was the current break at a discretionary node?
 19594  		postDiscBreak bool        // and did it have a nonempty post-break part?
 19595  		curWidth      scaled      // width of line number |cur_line|
 19596  		curIndent     scaled      // left margin of line number |cur_line|
 19597  		t             quarterword // used for replacement counts in discretionary nodes
 19598  		pen           int32       // use when calculating penalties between lines
 19599  		curLine       halfword    // the current line number being justified
 19600  	)
 19601  	q = *(*prg.mem[int32(prg.bestBet)+1].hh()).rh()
 19602  	prg.curP = 0
 19603  	for {
 19604  		r1 = q
 19605  		q = *(*prg.mem[int32(q)+1].hh()).lh()
 19606  		*(*prg.mem[int32(r1)+1].hh()).lh() = prg.curP
 19607  		prg.curP = r1
 19608  		if int32(q) == 0 {
 19609  			break
 19610  		}
 19611  	}
 19612  	curLine = uint16(prg.curList.pgField + 1)
 19613  	for {
 19614  		// Justify the line ending at breakpoint |cur_p|, and append it to the current vertical list, together with associated penalties and other insertions
 19615  
 19616  		// Modify the end of the line to reflect the nature of the break and to include \.[\\rightskip]; also set the proper value of |disc_break|
 19617  		q = *(*prg.mem[int32(prg.curP)+1].hh()).rh()
 19618  		discBreak = false
 19619  		postDiscBreak = false
 19620  		if int32(q) != 0 {
 19621  			if int32(*(*prg.mem[q].hh()).b0()) == glueNode {
 19622  				prg.deleteGlueRef(*(*prg.mem[int32(q)+1].hh()).lh())
 19623  				*(*prg.mem[int32(q)+1].hh()).lh() = *(*prg.eqtb[glueBase+rightSkipCode-1].hh()).rh()
 19624  				*(*prg.mem[q].hh()).b1() = byte(rightSkipCode + 1)
 19625  				*(*prg.mem[*(*prg.eqtb[glueBase+rightSkipCode-1].hh()).rh()].hh()).rh() = uint16(int32(*(*prg.mem[*(*prg.eqtb[glueBase+rightSkipCode-1].hh()).rh()].hh()).rh()) + 1)
 19626  
 19627  				goto done
 19628  			} else {
 19629  				if int32(*(*prg.mem[q].hh()).b0()) == discNode {
 19630  					t = *(*prg.mem[q].hh()).b1()
 19631  
 19632  					// Destroy the |t| nodes following |q|, and make |r| point to the following node
 19633  					if int32(t) == 0 {
 19634  						r1 = *(*prg.mem[q].hh()).rh()
 19635  					} else {
 19636  						r1 = q
 19637  						for int32(t) > 1 {
 19638  							r1 = *(*prg.mem[r1].hh()).rh()
 19639  							t = byte(int32(t) - 1)
 19640  						}
 19641  						s = *(*prg.mem[r1].hh()).rh()
 19642  						r1 = *(*prg.mem[s].hh()).rh()
 19643  						*(*prg.mem[s].hh()).rh() = 0
 19644  						prg.flushNodeList(*(*prg.mem[q].hh()).rh())
 19645  						*(*prg.mem[q].hh()).b1() = 0
 19646  					}
 19647  					if int32(*(*prg.mem[int32(q)+1].hh()).rh()) != 0 {
 19648  						s = *(*prg.mem[int32(q)+1].hh()).rh()
 19649  						for int32(*(*prg.mem[s].hh()).rh()) != 0 {
 19650  							s = *(*prg.mem[s].hh()).rh()
 19651  						}
 19652  						*(*prg.mem[s].hh()).rh() = r1
 19653  						r1 = *(*prg.mem[int32(q)+1].hh()).rh()
 19654  						*(*prg.mem[int32(q)+1].hh()).rh() = 0
 19655  						postDiscBreak = true
 19656  					}
 19657  					if int32(*(*prg.mem[int32(q)+1].hh()).lh()) != 0 {
 19658  						s = *(*prg.mem[int32(q)+1].hh()).lh()
 19659  						*(*prg.mem[q].hh()).rh() = s
 19660  						for int32(*(*prg.mem[s].hh()).rh()) != 0 {
 19661  							s = *(*prg.mem[s].hh()).rh()
 19662  						}
 19663  						*(*prg.mem[int32(q)+1].hh()).lh() = 0
 19664  						q = s
 19665  					}
 19666  					*(*prg.mem[q].hh()).rh() = r1
 19667  					discBreak = true
 19668  				} else if int32(*(*prg.mem[q].hh()).b0()) == mathNode || int32(*(*prg.mem[q].hh()).b0()) == kernNode {
 19669  					*prg.mem[int32(q)+widthOffset].int() = 0
 19670  				}
 19671  			}
 19672  		} else {
 19673  			q = uint16(30000 - 3)
 19674  			for int32(*(*prg.mem[q].hh()).rh()) != 0 {
 19675  				q = *(*prg.mem[q].hh()).rh()
 19676  			}
 19677  		}
 19678  
 19679  		// Put the \(r)\.[\\rightskip] glue after node |q|
 19680  		r1 = prg.newParamGlue(smallNumber(rightSkipCode))
 19681  		*(*prg.mem[r1].hh()).rh() = *(*prg.mem[q].hh()).rh()
 19682  		*(*prg.mem[q].hh()).rh() = r1
 19683  		q = r1
 19684  
 19685  	done:
 19686  		;
 19687  
 19688  		// Put the \(l)\.[\\leftskip] glue at the left and detach this line
 19689  		r1 = *(*prg.mem[q].hh()).rh()
 19690  		*(*prg.mem[q].hh()).rh() = 0
 19691  		q = *(*prg.mem[30000-3].hh()).rh()
 19692  		*(*prg.mem[30000-3].hh()).rh() = r1
 19693  		if int32(*(*prg.eqtb[glueBase+leftSkipCode-1].hh()).rh()) != memBot {
 19694  			r1 = prg.newParamGlue(smallNumber(leftSkipCode))
 19695  			*(*prg.mem[r1].hh()).rh() = q
 19696  			q = r1
 19697  		}
 19698  
 19699  		// Call the packaging subroutine, setting |just_box| to the justified box
 19700  		if int32(curLine) > int32(prg.lastSpecialLine) {
 19701  			curWidth = prg.secondWidth
 19702  			curIndent = prg.secondIndent
 19703  		} else if int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh()) == 0 {
 19704  			curWidth = prg.firstWidth
 19705  			curIndent = prg.firstIndent
 19706  		} else {
 19707  			curWidth = *prg.mem[int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh())+2*int32(curLine)].int()
 19708  			curIndent = *prg.mem[int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh())+2*int32(curLine)-1].int()
 19709  		}
 19710  		prg.adjustTail = uint16(30000 - 5)
 19711  		prg.justBox = prg.hpack(q, curWidth, smallNumber(exactly))
 19712  		*prg.mem[int32(prg.justBox)+4].int() = curIndent
 19713  
 19714  		// Append the new box to the current vertical list, followed by the list of special nodes taken out of the box by the packager
 19715  		prg.appendToVlist(prg.justBox)
 19716  		if 30000-5 != int32(prg.adjustTail) {
 19717  			*(*prg.mem[prg.curList.tailField].hh()).rh() = *(*prg.mem[30000-5].hh()).rh()
 19718  			prg.curList.tailField = prg.adjustTail
 19719  		}
 19720  		prg.adjustTail = 0
 19721  
 19722  		// Append a penalty node, if a nonzero penalty is appropriate
 19723  		if int32(curLine)+1 != int32(prg.bestLine) {
 19724  			pen = *prg.eqtb[intBase+interLinePenaltyCode-1].int()
 19725  			if int32(curLine) == prg.curList.pgField+1 {
 19726  				pen = pen + *prg.eqtb[intBase+clubPenaltyCode-1].int()
 19727  			}
 19728  			if int32(curLine)+2 == int32(prg.bestLine) {
 19729  				pen = pen + finalWidowPenalty
 19730  			}
 19731  			if discBreak {
 19732  				pen = pen + *prg.eqtb[intBase+brokenPenaltyCode-1].int()
 19733  			}
 19734  			if pen != 0 {
 19735  				r1 = prg.newPenalty(pen)
 19736  				*(*prg.mem[prg.curList.tailField].hh()).rh() = r1
 19737  				prg.curList.tailField = r1
 19738  			}
 19739  		}
 19740  		curLine = uint16(int32(curLine) + 1)
 19741  		prg.curP = *(*prg.mem[int32(prg.curP)+1].hh()).lh()
 19742  		if int32(prg.curP) != 0 {
 19743  			if !postDiscBreak {
 19744  				r1 = uint16(30000 - 3)
 19745  				for true {
 19746  					q = *(*prg.mem[r1].hh()).rh()
 19747  					if int32(q) == int32(*(*prg.mem[int32(prg.curP)+1].hh()).rh()) {
 19748  						goto done1
 19749  					}
 19750  					// |cur_break(cur_p)| is the next breakpoint
 19751  					// now |q| cannot be |null|
 19752  					if int32(q) >= int32(prg.hiMemMin) {
 19753  						goto done1
 19754  					}
 19755  					if int32(*(*prg.mem[q].hh()).b0()) < mathNode {
 19756  						goto done1
 19757  					}
 19758  					if int32(*(*prg.mem[q].hh()).b0()) == kernNode {
 19759  						if int32(*(*prg.mem[q].hh()).b1()) != explicit {
 19760  							goto done1
 19761  						}
 19762  					}
 19763  					r1 = q // now |type(q)=glue_node|, |kern_node|, |math_node|, or |penalty_node|
 19764  				}
 19765  
 19766  			done1:
 19767  				if int32(r1) != 30000-3 {
 19768  					*(*prg.mem[r1].hh()).rh() = 0
 19769  					prg.flushNodeList(*(*prg.mem[30000-3].hh()).rh())
 19770  					*(*prg.mem[30000-3].hh()).rh() = q
 19771  				}
 19772  			}
 19773  		}
 19774  		if int32(prg.curP) == 0 {
 19775  			break
 19776  		}
 19777  	}
 19778  	if int32(curLine) != int32(prg.bestLine) || int32(*(*prg.mem[30000-3].hh()).rh()) != 0 {
 19779  		prg.confusion(strNumber( /* "line breaking" */ 939))
 19780  	}
 19781  	// \xref[this can't happen line breaking][\quad line breaking]
 19782  	prg.curList.pgField = int32(prg.bestLine) - 1
 19783  }
 19784  
 19785  // \4
 19786  // Declare the function called |reconstitute|
 19787  func (prg *prg) reconstitute(j, n smallNumber, bchar, hchar halfword) (r smallNumber) {
 19788  	var (
 19789  		p        halfword     // temporary register for list manipulation
 19790  		t        halfword     // a node being appended to
 19791  		q        fourQuarters // character information or a lig/kern instruction
 19792  		curRh    halfword     // hyphen character for ligature testing
 19793  		testChar halfword     // hyphen or other character for ligature testing
 19794  		w        scaled       // amount of kerning
 19795  		k        fontIndex    // position of current lig/kern instruction
 19796  	)
 19797  	prg.hyphenPassed = 0
 19798  	t = uint16(30000 - 4)
 19799  	w = 0
 19800  	*(*prg.mem[30000-4].hh()).rh() = 0
 19801  	// at this point |ligature_present=lft_hit=rt_hit=false|
 19802  
 19803  	// Set up data structures with the cursor following position |j|
 19804  	prg.curL = uint16(int32(prg.hu[j]) + minQuarterword)
 19805  	prg.curQ = t
 19806  	if int32(j) == 0 {
 19807  		prg.ligaturePresent = prg.initLig
 19808  		p = prg.initList
 19809  		if prg.ligaturePresent {
 19810  			prg.lftHit = prg.initLft
 19811  		}
 19812  		for int32(p) > 0 {
 19813  			{
 19814  				*(*prg.mem[t].hh()).rh() = prg.getAvail()
 19815  				t = *(*prg.mem[t].hh()).rh()
 19816  				*(*prg.mem[t].hh()).b0() = prg.hf
 19817  				*(*prg.mem[t].hh()).b1() = *(*prg.mem[p].hh()).b1()
 19818  			}
 19819  			p = *(*prg.mem[p].hh()).rh()
 19820  		}
 19821  	} else if int32(prg.curL) < 256+minQuarterword {
 19822  		*(*prg.mem[t].hh()).rh() = prg.getAvail()
 19823  		t = *(*prg.mem[t].hh()).rh()
 19824  		*(*prg.mem[t].hh()).b0() = prg.hf
 19825  		*(*prg.mem[t].hh()).b1() = byte(prg.curL)
 19826  	}
 19827  	prg.ligStack = 0
 19828  	{
 19829  		if int32(j) < int32(n) {
 19830  			prg.curR = uint16(int32(prg.hu[int32(j)+1]) + minQuarterword)
 19831  		} else {
 19832  			prg.curR = bchar
 19833  		}
 19834  		if prg.hyf[j]&1 != 0 {
 19835  			curRh = hchar
 19836  		} else {
 19837  			curRh = uint16(256 + minQuarterword)
 19838  		}
 19839  	}
 19840  
 19841  continue1:
 19842  	if int32(prg.curL) == 256+minQuarterword {
 19843  		k = prg.bcharLabel[prg.hf]
 19844  		if int32(k) == nonAddress {
 19845  			goto done
 19846  		} else {
 19847  			q = *prg.fontInfo[k].qqqq()
 19848  		}
 19849  	} else {
 19850  		q = *prg.fontInfo[prg.charBase[prg.hf]+int32(prg.curL)].qqqq()
 19851  		if (int32(q.b2)-minQuarterword)%4 != ligTag {
 19852  			goto done
 19853  		}
 19854  		k = uint16(prg.ligKernBase[prg.hf] + int32(q.b3))
 19855  		q = *prg.fontInfo[k].qqqq()
 19856  		if int32(q.b0) > 128+minQuarterword {
 19857  			k = uint16(prg.ligKernBase[prg.hf] + 256*int32(q.b2) + int32(q.b3) + 32768 - 256*(128+minQuarterword))
 19858  			q = *prg.fontInfo[k].qqqq()
 19859  		}
 19860  	} // now |k| is the starting address of the lig/kern program
 19861  	if int32(curRh) < 256+minQuarterword {
 19862  		testChar = curRh
 19863  	} else {
 19864  		testChar = prg.curR
 19865  	}
 19866  	for true {
 19867  		if int32(q.b1) == int32(testChar) {
 19868  			if int32(q.b0) <= 128+minQuarterword {
 19869  				if int32(curRh) < 256+minQuarterword {
 19870  					prg.hyphenPassed = j
 19871  					hchar = uint16(256 + minQuarterword)
 19872  					curRh = uint16(256 + minQuarterword)
 19873  
 19874  					goto continue1
 19875  				} else {
 19876  					if int32(hchar) < 256+minQuarterword {
 19877  						if prg.hyf[j]&1 != 0 {
 19878  							prg.hyphenPassed = j
 19879  							hchar = uint16(256 + minQuarterword)
 19880  						}
 19881  					}
 19882  					if int32(q.b2) < 128+minQuarterword {
 19883  						if int32(prg.curL) == 256+minQuarterword {
 19884  							prg.lftHit = true
 19885  						}
 19886  						if int32(j) == int32(n) {
 19887  							if int32(prg.ligStack) == 0 {
 19888  								prg.rtHit = true
 19889  							}
 19890  						}
 19891  						{
 19892  							if prg.interrupt != 0 {
 19893  								prg.pauseForInstructions()
 19894  							}
 19895  						} // allow a way out in case there's an infinite ligature loop
 19896  						switch q.b2 {
 19897  						case 1 + minQuarterword, 5 + minQuarterword:
 19898  							prg.curL = uint16(q.b3) // \.[=:\?], \.[=:\?>]
 19899  							prg.ligaturePresent = true
 19900  
 19901  						case 2 + minQuarterword, 6 + minQuarterword:
 19902  							prg.curR = uint16(q.b3) // \.[\?=:], \.[\?=:>]
 19903  							if int32(prg.ligStack) > 0 {
 19904  								*(*prg.mem[prg.ligStack].hh()).b1() = byte(prg.curR)
 19905  							} else {
 19906  								prg.ligStack = prg.newLigItem(quarterword(prg.curR))
 19907  								if int32(j) == int32(n) {
 19908  									bchar = uint16(256 + minQuarterword)
 19909  								} else {
 19910  									p = prg.getAvail()
 19911  									*(*prg.mem[int32(prg.ligStack)+1].hh()).rh() = p
 19912  									*(*prg.mem[p].hh()).b1() = byte(int32(prg.hu[int32(j)+1]) + minQuarterword)
 19913  									*(*prg.mem[p].hh()).b0() = prg.hf
 19914  								}
 19915  							}
 19916  
 19917  						case 3 + minQuarterword:
 19918  							prg.curR = uint16(q.b3) // \.[\?=:\?]
 19919  							p = prg.ligStack
 19920  							prg.ligStack = prg.newLigItem(quarterword(prg.curR))
 19921  							*(*prg.mem[prg.ligStack].hh()).rh() = p
 19922  
 19923  						case 7 + minQuarterword, 11 + minQuarterword:
 19924  							if prg.ligaturePresent {
 19925  								p = prg.newLigature(prg.hf, quarterword(prg.curL), *(*prg.mem[prg.curQ].hh()).rh())
 19926  								if prg.lftHit {
 19927  									*(*prg.mem[p].hh()).b1() = 2
 19928  									prg.lftHit = false
 19929  								}
 19930  								if false {
 19931  									if int32(prg.ligStack) == 0 {
 19932  										*(*prg.mem[p].hh()).b1() = byte(int32(*(*prg.mem[p].hh()).b1()) + 1)
 19933  										prg.rtHit = false
 19934  									}
 19935  								}
 19936  								*(*prg.mem[prg.curQ].hh()).rh() = p
 19937  								t = p
 19938  								prg.ligaturePresent = false
 19939  							} // \.[\?=:\?>], \.[\?=:\?>>]
 19940  							prg.curQ = t
 19941  							prg.curL = uint16(q.b3)
 19942  							prg.ligaturePresent = true
 19943  
 19944  						default:
 19945  							prg.curL = uint16(q.b3)
 19946  							prg.ligaturePresent = true // \.[=:]
 19947  							if int32(prg.ligStack) > 0 {
 19948  								if int32(*(*prg.mem[int32(prg.ligStack)+1].hh()).rh()) > 0 {
 19949  									*(*prg.mem[t].hh()).rh() = *(*prg.mem[int32(prg.ligStack)+1].hh()).rh()
 19950  									t = *(*prg.mem[t].hh()).rh()
 19951  									j = byte(int32(j) + 1)
 19952  								}
 19953  								p = prg.ligStack
 19954  								prg.ligStack = *(*prg.mem[p].hh()).rh()
 19955  								prg.freeNode(p, halfword(smallNodeSize))
 19956  								if int32(prg.ligStack) == 0 {
 19957  									if int32(j) < int32(n) {
 19958  										prg.curR = uint16(int32(prg.hu[int32(j)+1]) + minQuarterword)
 19959  									} else {
 19960  										prg.curR = bchar
 19961  									}
 19962  									if prg.hyf[j]&1 != 0 {
 19963  										curRh = hchar
 19964  									} else {
 19965  										curRh = uint16(256 + minQuarterword)
 19966  									}
 19967  								} else {
 19968  									prg.curR = uint16(*(*prg.mem[prg.ligStack].hh()).b1())
 19969  								}
 19970  							} else if int32(j) == int32(n) {
 19971  								goto done
 19972  							} else {
 19973  								{
 19974  									*(*prg.mem[t].hh()).rh() = prg.getAvail()
 19975  									t = *(*prg.mem[t].hh()).rh()
 19976  									*(*prg.mem[t].hh()).b0() = prg.hf
 19977  									*(*prg.mem[t].hh()).b1() = byte(prg.curR)
 19978  								}
 19979  								j = byte(int32(j) + 1)
 19980  								{
 19981  									if int32(j) < int32(n) {
 19982  										prg.curR = uint16(int32(prg.hu[int32(j)+1]) + minQuarterword)
 19983  									} else {
 19984  										prg.curR = bchar
 19985  									}
 19986  									if prg.hyf[j]&1 != 0 {
 19987  										curRh = hchar
 19988  									} else {
 19989  										curRh = uint16(256 + minQuarterword)
 19990  									}
 19991  								}
 19992  							}
 19993  
 19994  						}
 19995  						if int32(q.b2) > 4+minQuarterword {
 19996  							if int32(q.b2) != 7+minQuarterword {
 19997  								goto done
 19998  							}
 19999  						}
 20000  
 20001  						goto continue1
 20002  					}
 20003  					w = *prg.fontInfo[prg.kernBase[prg.hf]+256*int32(q.b2)+int32(q.b3)].int()
 20004  					goto done // this kern will be inserted below
 20005  				}
 20006  			}
 20007  		}
 20008  		if int32(q.b0) >= 128+minQuarterword {
 20009  			if int32(curRh) == 256+minQuarterword {
 20010  				goto done
 20011  			} else {
 20012  				curRh = uint16(256 + minQuarterword)
 20013  				goto continue1
 20014  			}
 20015  		}
 20016  		k = uint16(int32(k) + int32(q.b0) - minQuarterword + 1)
 20017  		q = *prg.fontInfo[k].qqqq()
 20018  	}
 20019  
 20020  done:
 20021  	;
 20022  
 20023  	// Append a ligature and/or kern to the translation; |goto continue| if the stack of inserted ligatures is nonempty
 20024  	if prg.ligaturePresent {
 20025  		p = prg.newLigature(prg.hf, quarterword(prg.curL), *(*prg.mem[prg.curQ].hh()).rh())
 20026  		if prg.lftHit {
 20027  			*(*prg.mem[p].hh()).b1() = 2
 20028  			prg.lftHit = false
 20029  		}
 20030  		if prg.rtHit {
 20031  			if int32(prg.ligStack) == 0 {
 20032  				*(*prg.mem[p].hh()).b1() = byte(int32(*(*prg.mem[p].hh()).b1()) + 1)
 20033  				prg.rtHit = false
 20034  			}
 20035  		}
 20036  		*(*prg.mem[prg.curQ].hh()).rh() = p
 20037  		t = p
 20038  		prg.ligaturePresent = false
 20039  	}
 20040  	if w != 0 {
 20041  		*(*prg.mem[t].hh()).rh() = prg.newKern(w)
 20042  		t = *(*prg.mem[t].hh()).rh()
 20043  		w = 0
 20044  	}
 20045  	if int32(prg.ligStack) > 0 {
 20046  		prg.curQ = t
 20047  		prg.curL = uint16(*(*prg.mem[prg.ligStack].hh()).b1())
 20048  		prg.ligaturePresent = true
 20049  		{
 20050  			if int32(*(*prg.mem[int32(prg.ligStack)+1].hh()).rh()) > 0 {
 20051  				*(*prg.mem[t].hh()).rh() = *(*prg.mem[int32(prg.ligStack)+1].hh()).rh()
 20052  				t = *(*prg.mem[t].hh()).rh()
 20053  				j = byte(int32(j) + 1)
 20054  			}
 20055  			p = prg.ligStack
 20056  			prg.ligStack = *(*prg.mem[p].hh()).rh()
 20057  			prg.freeNode(p, halfword(smallNodeSize))
 20058  			if int32(prg.ligStack) == 0 {
 20059  				if int32(j) < int32(n) {
 20060  					prg.curR = uint16(int32(prg.hu[int32(j)+1]) + minQuarterword)
 20061  				} else {
 20062  					prg.curR = bchar
 20063  				}
 20064  				if prg.hyf[j]&1 != 0 {
 20065  					curRh = hchar
 20066  				} else {
 20067  					curRh = uint16(256 + minQuarterword)
 20068  				}
 20069  			} else {
 20070  				prg.curR = uint16(*(*prg.mem[prg.ligStack].hh()).b1())
 20071  			}
 20072  		}
 20073  		goto continue1
 20074  	}
 20075  	r = j
 20076  	return r
 20077  }
 20078  
 20079  func (prg *prg) hyphenate() {
 20080  	var (
 20081  		// Local variables for hyphenation
 20082  		i, j, l/* 0..65 */ byte          // indices into |hc| or |hu|
 20083  		q, r1, s                halfword // temporary registers for list manipulation
 20084  		bchar                   halfword // boundary character of hyphenated word, or |non_char|
 20085  
 20086  		majorTail, minorTail halfword // the end of lists in the main and
 20087  		//   discretionary branches being reconstructed
 20088  
 20089  		c                    asciiCode // character temporarily replaced by a hyphen
 20090  		cLoc/* 0..63 */ byte           // where that character came from
 20091  		rCount               int32     // replacement count for discretionary
 20092  		hyfNode              halfword  // the hyphen, if it exists
 20093  
 20094  		z triePointer // an index into |trie|
 20095  		v int32       // an index into |hyf_distance|, etc.
 20096  
 20097  		h hyphPointer // an index into |hyph_word| and |hyph_list|
 20098  		k strNumber   // an index into |str_start|
 20099  		u poolPointer // an index into |str_pool|
 20100  	)
 20101  	for ii := int32(0); ii <= int32(prg.hn); ii++ {
 20102  		j = byte(ii)
 20103  		_ = j
 20104  		prg.hyf[j] = 0
 20105  	}
 20106  
 20107  	// Look for the word |hc[1..hn]| in the exception table, and |goto found| (with |hyf| containing the hyphens) if an entry is found
 20108  	h = prg.hc[1]
 20109  	prg.hn = byte(int32(prg.hn) + 1)
 20110  	prg.hc[prg.hn] = uint16(prg.curLang)
 20111  	for ii := int32(2); ii <= int32(prg.hn); ii++ {
 20112  		j = byte(ii)
 20113  		_ = j
 20114  		h = uint16((int32(h) + int32(h) + int32(prg.hc[j])) % hyphSize)
 20115  	}
 20116  	for true {
 20117  		k = prg.hyphWord[h]
 20118  		if int32(k) == 0 {
 20119  			goto notFound
 20120  		}
 20121  		if int32(prg.strStart[int32(k)+1])-int32(prg.strStart[k]) < int32(prg.hn) {
 20122  			goto notFound
 20123  		}
 20124  		if int32(prg.strStart[int32(k)+1])-int32(prg.strStart[k]) == int32(prg.hn) {
 20125  			j = 1
 20126  			u = prg.strStart[k]
 20127  			for {
 20128  				if int32(prg.strPool[u]) < int32(prg.hc[j]) {
 20129  					goto notFound
 20130  				}
 20131  				if int32(prg.strPool[u]) > int32(prg.hc[j]) {
 20132  					goto done
 20133  				}
 20134  				j = byte(int32(j) + 1)
 20135  				u = uint16(int32(u) + 1)
 20136  				if int32(j) > int32(prg.hn) {
 20137  					break
 20138  				}
 20139  			}
 20140  
 20141  			// Insert hyphens as specified in |hyph_list[h]|
 20142  			s = prg.hyphList[h]
 20143  			for int32(s) != 0 {
 20144  				prg.hyf[*(*prg.mem[s].hh()).lh()] = 1
 20145  				s = *(*prg.mem[s].hh()).rh()
 20146  			}
 20147  			prg.hn = byte(int32(prg.hn) - 1)
 20148  			goto found
 20149  		}
 20150  
 20151  	done:
 20152  		;
 20153  		if int32(h) > 0 {
 20154  			h = uint16(int32(h) - 1)
 20155  		} else {
 20156  			h = uint16(hyphSize)
 20157  		}
 20158  	}
 20159  
 20160  notFound:
 20161  	prg.hn = byte(int32(prg.hn) - 1)
 20162  	if int32(*prg.trie[int32(prg.curLang)+1].b1()) != int32(prg.curLang)+minQuarterword {
 20163  		goto exit
 20164  	} // no patterns for |cur_lang|
 20165  	prg.hc[0] = 0
 20166  	prg.hc[int32(prg.hn)+1] = 0
 20167  	prg.hc[int32(prg.hn)+2] = 256 // insert delimiters
 20168  	for ii := int32(0); ii <= int32(prg.hn)-prg.rHyf+1; ii++ {
 20169  		j = byte(ii)
 20170  		_ = j
 20171  		z = uint16(int32(*prg.trie[int32(prg.curLang)+1].rh()) + int32(prg.hc[j]))
 20172  		l = j
 20173  		for int32(prg.hc[l]) == int32(*prg.trie[z].b1())-minQuarterword {
 20174  			if int32(*prg.trie[z].b0()) != minQuarterword {
 20175  				v = int32(*prg.trie[z].b0())
 20176  				for {
 20177  					v = v + int32(prg.opStart[prg.curLang])
 20178  					i = byte(int32(l) - int32(prg.hyfDistance[v-1]))
 20179  					if int32(prg.hyfNum[v-1]) > int32(prg.hyf[i]) {
 20180  						prg.hyf[i] = prg.hyfNum[v-1]
 20181  					}
 20182  					v = int32(prg.hyfNext[v-1])
 20183  					if v == minQuarterword {
 20184  						break
 20185  					}
 20186  				}
 20187  			}
 20188  			l = byte(int32(l) + 1)
 20189  			z = uint16(int32(*prg.trie[z].rh()) + int32(prg.hc[l]))
 20190  		}
 20191  	}
 20192  
 20193  found:
 20194  	for ii := int32(0); ii <= prg.lHyf-1; ii++ {
 20195  		j = byte(ii)
 20196  		_ = j
 20197  		prg.hyf[j] = 0
 20198  	}
 20199  	for ii := int32(0); ii <= prg.rHyf-1; ii++ {
 20200  		j = byte(ii)
 20201  		_ = j
 20202  		prg.hyf[int32(prg.hn)-int32(j)] = 0
 20203  	}
 20204  
 20205  	// If no hyphens were found, |return|
 20206  	for ii := prg.lHyf; ii <= int32(prg.hn)-prg.rHyf; ii++ {
 20207  		j = byte(ii)
 20208  		_ = j
 20209  		if prg.hyf[j]&1 != 0 {
 20210  			goto found1
 20211  		}
 20212  	}
 20213  
 20214  	goto exit
 20215  
 20216  found1:
 20217  	;
 20218  
 20219  	// Replace nodes |ha..hb| by a sequence of nodes that includes the discretionary hyphens
 20220  	q = *(*prg.mem[prg.hb].hh()).rh()
 20221  	*(*prg.mem[prg.hb].hh()).rh() = 0
 20222  	r1 = *(*prg.mem[prg.ha].hh()).rh()
 20223  	*(*prg.mem[prg.ha].hh()).rh() = 0
 20224  	bchar = prg.hyfBchar
 20225  	if int32(prg.ha) >= int32(prg.hiMemMin) {
 20226  		if int32(*(*prg.mem[prg.ha].hh()).b0()) != int32(prg.hf) {
 20227  			goto found2
 20228  		} else {
 20229  			prg.initList = prg.ha
 20230  			prg.initLig = false
 20231  			prg.hu[0] = uint16(int32(*(*prg.mem[prg.ha].hh()).b1()) - minQuarterword)
 20232  		}
 20233  	} else if int32(*(*prg.mem[prg.ha].hh()).b0()) == ligatureNode {
 20234  		if int32(*(*prg.mem[int32(prg.ha)+1].hh()).b0()) != int32(prg.hf) {
 20235  			goto found2
 20236  		} else {
 20237  			prg.initList = *(*prg.mem[int32(prg.ha)+1].hh()).rh()
 20238  			prg.initLig = true
 20239  			prg.initLft = int32(*(*prg.mem[prg.ha].hh()).b1()) > 1
 20240  			prg.hu[0] = uint16(int32(*(*prg.mem[int32(prg.ha)+1].hh()).b1()) - minQuarterword)
 20241  			if int32(prg.initList) == 0 {
 20242  				if prg.initLft {
 20243  					prg.hu[0] = 256
 20244  					prg.initLig = false
 20245  				}
 20246  			} // in this case a ligature will be reconstructed from scratch
 20247  			prg.freeNode(prg.ha, halfword(smallNodeSize))
 20248  		}
 20249  	} else {
 20250  		if !(int32(r1) >= int32(prg.hiMemMin)) {
 20251  			if int32(*(*prg.mem[r1].hh()).b0()) == ligatureNode {
 20252  				if int32(*(*prg.mem[r1].hh()).b1()) > 1 {
 20253  					goto found2
 20254  				}
 20255  			}
 20256  		}
 20257  		j = 1
 20258  		s = prg.ha
 20259  		prg.initList = 0
 20260  		goto commonEnding
 20261  	}
 20262  	s = prg.curP // we have |cur_p<>ha| because |type(cur_p)=glue_node|
 20263  	for int32(*(*prg.mem[s].hh()).rh()) != int32(prg.ha) {
 20264  		s = *(*prg.mem[s].hh()).rh()
 20265  	}
 20266  	j = 0
 20267  	goto commonEnding
 20268  
 20269  found2:
 20270  	s = prg.ha
 20271  	j = 0
 20272  	prg.hu[0] = 256
 20273  	prg.initLig = false
 20274  	prg.initList = 0
 20275  
 20276  commonEnding:
 20277  	prg.flushNodeList(r1)
 20278  
 20279  	// Reconstitute nodes for the hyphenated word, inserting discretionary hyphens
 20280  	for {
 20281  		l = j
 20282  		j = byte(int32(prg.reconstitute(j, prg.hn, bchar, halfword(prg.hyfChar+minQuarterword))) + 1)
 20283  		if int32(prg.hyphenPassed) == 0 {
 20284  			*(*prg.mem[s].hh()).rh() = *(*prg.mem[30000-4].hh()).rh()
 20285  			for int32(*(*prg.mem[s].hh()).rh()) > 0 {
 20286  				s = *(*prg.mem[s].hh()).rh()
 20287  			}
 20288  			if prg.hyf[int32(j)-1]&1 != 0 {
 20289  				l = j
 20290  				prg.hyphenPassed = byte(int32(j) - 1)
 20291  				*(*prg.mem[30000-4].hh()).rh() = 0
 20292  			}
 20293  		}
 20294  		if int32(prg.hyphenPassed) > 0 {
 20295  			for {
 20296  				r1 = prg.getNode(smallNodeSize)
 20297  				*(*prg.mem[r1].hh()).rh() = *(*prg.mem[30000-4].hh()).rh()
 20298  				*(*prg.mem[r1].hh()).b0() = byte(discNode)
 20299  				majorTail = r1
 20300  				rCount = 0
 20301  				for int32(*(*prg.mem[majorTail].hh()).rh()) > 0 {
 20302  					majorTail = *(*prg.mem[majorTail].hh()).rh()
 20303  					rCount = rCount + 1
 20304  				}
 20305  				i = prg.hyphenPassed
 20306  				prg.hyf[i] = 0
 20307  
 20308  				// Put the \(c)characters |hu[l..i]| and a hyphen into |pre_break(r)|
 20309  				minorTail = 0
 20310  				*(*prg.mem[int32(r1)+1].hh()).lh() = 0
 20311  				hyfNode = prg.newCharacter(prg.hf, eightBits(prg.hyfChar))
 20312  				if int32(hyfNode) != 0 {
 20313  					i = byte(int32(i) + 1)
 20314  					c = byte(prg.hu[i])
 20315  					prg.hu[i] = uint16(prg.hyfChar)
 20316  					{
 20317  						*(*prg.mem[hyfNode].hh()).rh() = prg.avail
 20318  						prg.avail = hyfNode /*    dyn_used:= dyn_used-1 ; [  ] */
 20319  					}
 20320  				}
 20321  				for int32(l) <= int32(i) {
 20322  					l = byte(int32(prg.reconstitute(l, i, prg.fontBchar[prg.hf], halfword(256+minQuarterword))) + 1)
 20323  					if int32(*(*prg.mem[30000-4].hh()).rh()) > 0 {
 20324  						if int32(minorTail) == 0 {
 20325  							*(*prg.mem[int32(r1)+1].hh()).lh() = *(*prg.mem[30000-4].hh()).rh()
 20326  						} else {
 20327  							*(*prg.mem[minorTail].hh()).rh() = *(*prg.mem[30000-4].hh()).rh()
 20328  						}
 20329  						minorTail = *(*prg.mem[30000-4].hh()).rh()
 20330  						for int32(*(*prg.mem[minorTail].hh()).rh()) > 0 {
 20331  							minorTail = *(*prg.mem[minorTail].hh()).rh()
 20332  						}
 20333  					}
 20334  				}
 20335  				if int32(hyfNode) != 0 {
 20336  					prg.hu[i] = uint16(c) // restore the character in the hyphen position
 20337  					l = i
 20338  					i = byte(int32(i) - 1)
 20339  				}
 20340  
 20341  				// Put the \(c)characters |hu[i+1..@,]| into |post_break(r)|, appending to this list and to |major_tail| until synchronization has been achieved
 20342  				minorTail = 0
 20343  				*(*prg.mem[int32(r1)+1].hh()).rh() = 0
 20344  				cLoc = 0
 20345  				if int32(prg.bcharLabel[prg.hf]) != nonAddress {
 20346  					l = byte(int32(l) - 1)
 20347  					c = byte(prg.hu[l])
 20348  					cLoc = l
 20349  					prg.hu[l] = 256
 20350  				}
 20351  				for int32(l) < int32(j) {
 20352  					for {
 20353  						l = byte(int32(prg.reconstitute(l, prg.hn, bchar, halfword(256+minQuarterword))) + 1)
 20354  						if int32(cLoc) > 0 {
 20355  							prg.hu[cLoc] = uint16(c)
 20356  							cLoc = 0
 20357  						}
 20358  						if int32(*(*prg.mem[30000-4].hh()).rh()) > 0 {
 20359  							if int32(minorTail) == 0 {
 20360  								*(*prg.mem[int32(r1)+1].hh()).rh() = *(*prg.mem[30000-4].hh()).rh()
 20361  							} else {
 20362  								*(*prg.mem[minorTail].hh()).rh() = *(*prg.mem[30000-4].hh()).rh()
 20363  							}
 20364  							minorTail = *(*prg.mem[30000-4].hh()).rh()
 20365  							for int32(*(*prg.mem[minorTail].hh()).rh()) > 0 {
 20366  								minorTail = *(*prg.mem[minorTail].hh()).rh()
 20367  							}
 20368  						}
 20369  						if int32(l) >= int32(j) {
 20370  							break
 20371  						}
 20372  					}
 20373  					for int32(l) > int32(j) {
 20374  
 20375  						// Append characters of |hu[j..@,]| to |major_tail|, advancing~|j|
 20376  						j = byte(int32(prg.reconstitute(j, prg.hn, bchar, halfword(256+minQuarterword))) + 1)
 20377  						*(*prg.mem[majorTail].hh()).rh() = *(*prg.mem[30000-4].hh()).rh()
 20378  						for int32(*(*prg.mem[majorTail].hh()).rh()) > 0 {
 20379  							majorTail = *(*prg.mem[majorTail].hh()).rh()
 20380  							rCount = rCount + 1
 20381  						}
 20382  					}
 20383  				}
 20384  
 20385  				// Move pointer |s| to the end of the current list, and set |replace_count(r)| appropriately
 20386  				if rCount > 127 {
 20387  					*(*prg.mem[s].hh()).rh() = *(*prg.mem[r1].hh()).rh()
 20388  					*(*prg.mem[r1].hh()).rh() = 0
 20389  					prg.flushNodeList(r1)
 20390  				} else {
 20391  					*(*prg.mem[s].hh()).rh() = r1
 20392  					*(*prg.mem[r1].hh()).b1() = byte(rCount)
 20393  				}
 20394  				s = majorTail
 20395  				prg.hyphenPassed = byte(int32(j) - 1)
 20396  				*(*prg.mem[30000-4].hh()).rh() = 0
 20397  				if !(prg.hyf[int32(j)-1]&1 != 0) {
 20398  					break
 20399  				}
 20400  			}
 20401  		}
 20402  		if int32(j) > int32(prg.hn) {
 20403  			break
 20404  		}
 20405  	}
 20406  	*(*prg.mem[s].hh()).rh() = q
 20407  	prg.flushList(prg.initList)
 20408  
 20409  exit:
 20410  }
 20411  
 20412  // Declare procedures for preprocessing hyphenation patterns
 20413  func (prg *prg) newTrieOp(d, n smallNumber, v quarterword) (r quarterword) {
 20414  	var (
 20415  		h/*  -trieOpSize..trieOpSize */ int16             // trial hash location
 20416  		u                                     quarterword // trial op code
 20417  		l/* 0..trieOpSize */ uint16                       // pointer to stored data
 20418  	)
 20419  	h = int16(abs(int32(n)+313*int32(d)+361*int32(v)+1009*int32(prg.curLang))%(trieOpSize+trieOpSize) - trieOpSize)
 20420  	for true {
 20421  		l = prg.trieOpHash[h+500]
 20422  		if int32(l) == 0 {
 20423  			if int32(prg.trieOpPtr) == trieOpSize {
 20424  				prg.overflow(strNumber( /* "pattern memory ops" */ 949), trieOpSize)
 20425  			}
 20426  			u = prg.trieUsed[prg.curLang]
 20427  			if int32(u) == maxQuarterword {
 20428  				prg.overflow(strNumber( /* "pattern memory ops per language" */ 950), maxQuarterword-minQuarterword)
 20429  			}
 20430  			prg.trieOpPtr = uint16(int32(prg.trieOpPtr) + 1)
 20431  			u = byte(int32(u) + 1)
 20432  			prg.trieUsed[prg.curLang] = u
 20433  			prg.hyfDistance[prg.trieOpPtr-1] = d
 20434  			prg.hyfNum[prg.trieOpPtr-1] = n
 20435  			prg.hyfNext[prg.trieOpPtr-1] = v
 20436  			prg.trieOpLang[prg.trieOpPtr-1] = prg.curLang
 20437  			prg.trieOpHash[h+500] = prg.trieOpPtr
 20438  			prg.trieOpVal[prg.trieOpPtr-1] = u
 20439  			r = u
 20440  			goto exit
 20441  		}
 20442  		if int32(prg.hyfDistance[l-1]) == int32(d) && int32(prg.hyfNum[l-1]) == int32(n) && int32(prg.hyfNext[l-1]) == int32(v) && int32(prg.trieOpLang[l-1]) == int32(prg.curLang) {
 20443  			r = prg.trieOpVal[l-1]
 20444  			goto exit
 20445  		}
 20446  		if int32(h) > -trieOpSize {
 20447  			h = int16(int32(h) - 1)
 20448  		} else {
 20449  			h = int16(trieOpSize)
 20450  		}
 20451  	}
 20452  
 20453  exit:
 20454  	;
 20455  	return r
 20456  }
 20457  
 20458  func (prg *prg) trieNode(p triePointer) (r triePointer) {
 20459  	var (
 20460  		h triePointer // trial hash location
 20461  		q triePointer // trial trie node
 20462  	)
 20463  	h = uint16(abs(int32(prg.trieC[p])+1009*int32(prg.trieO[p])+
 20464  		2718*int32(prg.trieL[p])+3142*int32(prg.trieR[p])) % trieSize)
 20465  	for true {
 20466  		q = prg.trieHash[h]
 20467  		if int32(q) == 0 {
 20468  			prg.trieHash[h] = p
 20469  			r = p
 20470  			goto exit
 20471  		}
 20472  		if int32(prg.trieC[q]) == int32(prg.trieC[p]) && int32(prg.trieO[q]) == int32(prg.trieO[p]) && int32(prg.trieL[q]) == int32(prg.trieL[p]) && int32(prg.trieR[q]) == int32(prg.trieR[p]) {
 20473  			r = q
 20474  			goto exit
 20475  		}
 20476  		if int32(h) > 0 {
 20477  			h = uint16(int32(h) - 1)
 20478  		} else {
 20479  			h = uint16(trieSize)
 20480  		}
 20481  	}
 20482  
 20483  exit:
 20484  	;
 20485  	return r
 20486  }
 20487  
 20488  func (prg *prg) compressTrie(p triePointer) (r triePointer) {
 20489  	if int32(p) == 0 {
 20490  		r = 0
 20491  	} else {
 20492  		prg.trieL[p] = prg.compressTrie(prg.trieL[p])
 20493  		prg.trieR[p] = prg.compressTrie(prg.trieR[p])
 20494  		r = prg.trieNode(p)
 20495  	}
 20496  	return r
 20497  }
 20498  
 20499  func (prg *prg) firstFit(p triePointer) {
 20500  	var (
 20501  		h                     triePointer // candidate for |trie_ref[p]|
 20502  		z                     triePointer // runs through holes
 20503  		q                     triePointer // runs through the family starting at |p|
 20504  		c                     asciiCode   // smallest character in the family
 20505  		l, r1                 triePointer // left and right neighbors
 20506  		ll/* 1..256 */ uint16             // upper limit of |trie_min| updating
 20507  	)
 20508  	c = prg.trieC[p]
 20509  	z = prg.trieMin[c] // get the first conceivably good hole
 20510  	for true {
 20511  		h = uint16(int32(z) - int32(c))
 20512  
 20513  		// Ensure that |trie_max>=h+256|
 20514  		if int32(prg.trieMax) < int32(h)+256 {
 20515  			if trieSize <= int32(h)+256 {
 20516  				prg.overflow(strNumber( /* "pattern memory" */ 951), trieSize)
 20517  			}
 20518  			// \xref[TeX capacity exceeded pattern memory][\quad pattern memory]
 20519  			for {
 20520  				prg.trieMax = uint16(int32(prg.trieMax) + 1)
 20521  				prg.trieTaken[prg.trieMax-1] = false
 20522  				*prg.trie[prg.trieMax].rh() = uint16(int32(prg.trieMax) + 1)
 20523  				*prg.trie[prg.trieMax].lh() = uint16(int32(prg.trieMax) - 1)
 20524  				if int32(prg.trieMax) == int32(h)+256 {
 20525  					break
 20526  				}
 20527  			}
 20528  		}
 20529  		if prg.trieTaken[h-1] {
 20530  			goto notFound
 20531  		}
 20532  
 20533  		// If all characters of the family fit relative to |h|, then |goto found|,\30\ otherwise |goto not_found|
 20534  		q = prg.trieR[p]
 20535  		for int32(q) > 0 {
 20536  			if int32(*prg.trie[int32(h)+int32(prg.trieC[q])].rh()) == 0 {
 20537  				goto notFound
 20538  			}
 20539  			q = prg.trieR[q]
 20540  		}
 20541  
 20542  		goto found
 20543  
 20544  	notFound:
 20545  		z = *prg.trie[z].rh() // move to the next hole
 20546  	}
 20547  
 20548  found:
 20549  	prg.trieTaken[h-1] = true
 20550  	prg.trieHash[p] = h
 20551  	q = p
 20552  	for {
 20553  		z = uint16(int32(h) + int32(prg.trieC[q]))
 20554  		l = *prg.trie[z].lh()
 20555  		r1 = *prg.trie[z].rh()
 20556  		*prg.trie[r1].lh() = l
 20557  		*prg.trie[l].rh() = r1
 20558  		*prg.trie[z].rh() = 0
 20559  		if int32(l) < 256 {
 20560  			if int32(z) < 256 {
 20561  				ll = z
 20562  			} else {
 20563  				ll = 256
 20564  			}
 20565  			for {
 20566  				prg.trieMin[l] = r1
 20567  				l = uint16(int32(l) + 1)
 20568  				if int32(l) == int32(ll) {
 20569  					break
 20570  				}
 20571  			}
 20572  		}
 20573  		q = prg.trieR[q]
 20574  		if int32(q) == 0 {
 20575  			break
 20576  		}
 20577  	}
 20578  }
 20579  
 20580  func (prg *prg) triePack(p triePointer) { // pack subtries of a family
 20581  	var (
 20582  		q triePointer // a local variable that need not be saved on recursive calls
 20583  	)
 20584  	for {
 20585  		q = prg.trieL[p]
 20586  		if int32(q) > 0 && int32(prg.trieHash[q]) == 0 {
 20587  			prg.firstFit(q)
 20588  			prg.triePack(q)
 20589  		}
 20590  		p = prg.trieR[p]
 20591  		if int32(p) == 0 {
 20592  			break
 20593  		}
 20594  	}
 20595  }
 20596  
 20597  func (prg *prg) trieFix(p triePointer) { // moves |p| and its siblings into |trie|
 20598  	var (
 20599  		q triePointer // a local variable that need not be saved on recursive calls
 20600  		c asciiCode   // another one that need not be saved
 20601  		z triePointer // |trie| reference; this local variable must be saved
 20602  	)
 20603  	z = prg.trieHash[p]
 20604  	for {
 20605  		q = prg.trieL[p]
 20606  		c = prg.trieC[p]
 20607  		*prg.trie[int32(z)+int32(c)].rh() = prg.trieHash[q]
 20608  		*prg.trie[int32(z)+int32(c)].b1() = byte(int32(c) + minQuarterword)
 20609  		*prg.trie[int32(z)+int32(c)].b0() = prg.trieO[p]
 20610  		if int32(q) > 0 {
 20611  			prg.trieFix(q)
 20612  		}
 20613  		p = prg.trieR[p]
 20614  		if int32(p) == 0 {
 20615  			break
 20616  		}
 20617  	}
 20618  }
 20619  
 20620  func (prg *prg) newPatterns() {
 20621  	var (
 20622  		k, l/* 0..64 */ byte // indices into |hc| and |hyf|;
 20623  		//                   not always in |small_number| range
 20624  
 20625  		digitSensed bool        // should the next digit be treated as a letter?
 20626  		v           quarterword // trie op code
 20627  		p, q        triePointer // nodes of trie traversed during insertion
 20628  		firstChild  bool        // is |p=trie_l[q]|?
 20629  		c           asciiCode   // character being inserted
 20630  	)
 20631  	if prg.trieNotReady {
 20632  		if *prg.eqtb[intBase+languageCode-1].int() <= 0 {
 20633  			prg.curLang = 0
 20634  		} else if *prg.eqtb[intBase+languageCode-1].int() > 255 {
 20635  			prg.curLang = 0
 20636  		} else {
 20637  			prg.curLang = byte(*prg.eqtb[intBase+languageCode-1].int())
 20638  		}
 20639  		prg.scanLeftBrace() // a left brace must follow \.[\\patterns]
 20640  
 20641  		// Enter all of the patterns into a linked trie, until coming to a right brace
 20642  		k = 0
 20643  		prg.hyf[0] = 0
 20644  		digitSensed = false
 20645  		for true {
 20646  			prg.getXToken()
 20647  			switch prg.curCmd {
 20648  			case letter, otherChar:
 20649  				// Append a new letter or a hyphen level
 20650  				if digitSensed || int32(prg.curChr) < '0' || int32(prg.curChr) > '9' {
 20651  					if int32(prg.curChr) == '.' {
 20652  						prg.curChr = 0
 20653  					} else {
 20654  						prg.curChr = *(*prg.eqtb[lcCodeBase+int32(prg.curChr)-1].hh()).rh()
 20655  						if int32(prg.curChr) == 0 {
 20656  							{
 20657  								if int32(prg.interaction) == errorStopMode {
 20658  								}
 20659  								prg.printNl(strNumber( /* "! " */ 262))
 20660  								prg.print( /* "Nonletter" */ 957)
 20661  							}
 20662  							// \xref[Nonletter]
 20663  							{
 20664  								prg.helpPtr = 1
 20665  								prg.helpLine[0] = /* "(See Appendix H.)" */ 956
 20666  							}
 20667  							prg.error1()
 20668  						}
 20669  					}
 20670  					if int32(k) < 63 {
 20671  						k = byte(int32(k) + 1)
 20672  						prg.hc[k] = prg.curChr
 20673  						prg.hyf[k] = 0
 20674  						digitSensed = false
 20675  					}
 20676  				} else if int32(k) < 63 {
 20677  					prg.hyf[k] = byte(int32(prg.curChr) - '0')
 20678  					digitSensed = true
 20679  				}
 20680  
 20681  			case spacer, rightBrace:
 20682  				if int32(k) > 0 {
 20683  					if int32(prg.hc[1]) == 0 {
 20684  						prg.hyf[0] = 0
 20685  					}
 20686  					if int32(prg.hc[k]) == 0 {
 20687  						prg.hyf[k] = 0
 20688  					}
 20689  					l = k
 20690  					v = byte(minQuarterword)
 20691  					for true {
 20692  						if int32(prg.hyf[l]) != 0 {
 20693  							v = prg.newTrieOp(smallNumber(int32(k)-int32(l)), prg.hyf[l], v)
 20694  						}
 20695  						if int32(l) > 0 {
 20696  							l = byte(int32(l) - 1)
 20697  						} else {
 20698  							goto done1
 20699  						}
 20700  					}
 20701  
 20702  				done1:
 20703  					;
 20704  					q = 0
 20705  					prg.hc[0] = uint16(prg.curLang)
 20706  					for int32(l) <= int32(k) {
 20707  						c = byte(prg.hc[l])
 20708  						l = byte(int32(l) + 1)
 20709  						p = prg.trieL[q]
 20710  						firstChild = true
 20711  						for int32(p) > 0 && int32(c) > int32(prg.trieC[p]) {
 20712  							q = p
 20713  							p = prg.trieR[q]
 20714  							firstChild = false
 20715  						}
 20716  						if int32(p) == 0 || int32(c) < int32(prg.trieC[p]) {
 20717  							if int32(prg.triePtr) == trieSize {
 20718  								prg.overflow(strNumber( /* "pattern memory" */ 951), trieSize)
 20719  							}
 20720  							// \xref[TeX capacity exceeded pattern memory][\quad pattern memory]
 20721  							prg.triePtr = uint16(int32(prg.triePtr) + 1)
 20722  							prg.trieR[prg.triePtr] = p
 20723  							p = prg.triePtr
 20724  							prg.trieL[p] = 0
 20725  							if firstChild {
 20726  								prg.trieL[q] = p
 20727  							} else {
 20728  								prg.trieR[q] = p
 20729  							}
 20730  							prg.trieC[p] = c
 20731  							prg.trieO[p] = byte(minQuarterword)
 20732  						}
 20733  						q = p // now node |q| represents $p_1\ldots p_[l-1]$
 20734  					}
 20735  					if int32(prg.trieO[q]) != minQuarterword {
 20736  						{
 20737  							if int32(prg.interaction) == errorStopMode {
 20738  							}
 20739  							prg.printNl(strNumber( /* "! " */ 262))
 20740  							prg.print( /* "Duplicate pattern" */ 958)
 20741  						}
 20742  						// \xref[Duplicate pattern]
 20743  						{
 20744  							prg.helpPtr = 1
 20745  							prg.helpLine[0] = /* "(See Appendix H.)" */ 956
 20746  						}
 20747  						prg.error1()
 20748  					}
 20749  					prg.trieO[q] = v
 20750  				}
 20751  				if int32(prg.curCmd) == rightBrace {
 20752  					goto done
 20753  				}
 20754  				k = 0
 20755  				prg.hyf[0] = 0
 20756  				digitSensed = false
 20757  
 20758  			default:
 20759  				{
 20760  					if int32(prg.interaction) == errorStopMode {
 20761  					}
 20762  					prg.printNl(strNumber( /* "! " */ 262))
 20763  					prg.print( /* "Bad " */ 955)
 20764  				}
 20765  				prg.printEsc(strNumber( /* "patterns" */ 953))
 20766  				// \xref[Bad \\patterns]
 20767  				{
 20768  					prg.helpPtr = 1
 20769  					prg.helpLine[0] = /* "(See Appendix H.)" */ 956
 20770  				}
 20771  				prg.error1()
 20772  
 20773  			}
 20774  		}
 20775  
 20776  	done:
 20777  	} else {
 20778  		{
 20779  			if int32(prg.interaction) == errorStopMode {
 20780  			}
 20781  			prg.printNl(strNumber( /* "! " */ 262))
 20782  			prg.print( /* "Too late for " */ 952)
 20783  		}
 20784  		prg.printEsc(strNumber( /* "patterns" */ 953))
 20785  		{
 20786  			prg.helpPtr = 1
 20787  			prg.helpLine[0] = /* "All patterns must be given before typesetting begins." */ 954
 20788  		}
 20789  		prg.error1()
 20790  		*(*prg.mem[30000-12].hh()).rh() = prg.scanToks(false, false)
 20791  		prg.flushList(prg.defRef)
 20792  	}
 20793  }
 20794  
 20795  func (prg *prg) initTrie() {
 20796  	var (
 20797  		p       triePointer // pointer for initialization
 20798  		j, k, t int32       // all-purpose registers for initialization
 20799  		r1, s   triePointer // used to clean up the packed |trie|
 20800  		h       twoHalves   // template used to zero out |trie|'s holes
 20801  	)
 20802  	prg.opStart[0] = uint16(-minQuarterword)
 20803  	for ii := int32(1); ii <= 255; ii++ {
 20804  		j = ii
 20805  		_ = j
 20806  		prg.opStart[j] = uint16(int32(prg.opStart[j-1]) + int32(prg.trieUsed[j-1]) - minQuarterword)
 20807  	}
 20808  	for ii := int32(1); ii <= int32(prg.trieOpPtr); ii++ {
 20809  		j = ii
 20810  		_ = j
 20811  		prg.trieOpHash[j+500] = uint16(int32(prg.opStart[prg.trieOpLang[j-1]]) + int32(prg.trieOpVal[j-1]))
 20812  	} // destination
 20813  	for ii := int32(1); ii <= int32(prg.trieOpPtr); ii++ {
 20814  		j = ii
 20815  		_ = j
 20816  		for int32(prg.trieOpHash[j+500]) > j {
 20817  			k = int32(prg.trieOpHash[j+500])
 20818  
 20819  			t = int32(prg.hyfDistance[k-1])
 20820  			prg.hyfDistance[k-1] = prg.hyfDistance[j-1]
 20821  			prg.hyfDistance[j-1] = byte(t)
 20822  
 20823  			t = int32(prg.hyfNum[k-1])
 20824  			prg.hyfNum[k-1] = prg.hyfNum[j-1]
 20825  			prg.hyfNum[j-1] = byte(t)
 20826  
 20827  			t = int32(prg.hyfNext[k-1])
 20828  			prg.hyfNext[k-1] = prg.hyfNext[j-1]
 20829  			prg.hyfNext[j-1] = byte(t)
 20830  
 20831  			prg.trieOpHash[j+500] = prg.trieOpHash[k+500]
 20832  			prg.trieOpHash[k+500] = uint16(k)
 20833  		}
 20834  	}
 20835  	for ii := int32(0); ii <= trieSize; ii++ {
 20836  		p = triePointer(ii)
 20837  		_ = p
 20838  		prg.trieHash[p] = 0
 20839  	}
 20840  	prg.trieL[0] = prg.compressTrie(prg.trieL[0]) // identify equivalent subtries
 20841  	for ii := int32(0); ii <= int32(prg.triePtr); ii++ {
 20842  		p = triePointer(ii)
 20843  		_ = p
 20844  		prg.trieHash[p] = 0
 20845  	}
 20846  	for ii := int32(0); ii <= 255; ii++ {
 20847  		p = triePointer(ii)
 20848  		_ = p
 20849  		prg.trieMin[p] = uint16(int32(p) + 1)
 20850  	}
 20851  	*prg.trie[0].rh() = 1
 20852  	prg.trieMax = 0
 20853  	if int32(prg.trieL[0]) != 0 {
 20854  		prg.firstFit(prg.trieL[0])
 20855  		prg.triePack(prg.trieL[0])
 20856  	}
 20857  
 20858  	// Move the data into |trie|
 20859  	*h.rh() = 0
 20860  	*h.b0() = byte(minQuarterword)
 20861  	*h.b1() = byte(minQuarterword) // |trie_link:=0|,
 20862  	//   |trie_op:=min_quarterword|, |trie_char:=qi(0)|
 20863  
 20864  	if int32(prg.trieL[0]) == 0 {
 20865  		for ii := int32(0); ii <= 256; ii++ {
 20866  			r1 = triePointer(ii)
 20867  			_ = r1
 20868  			prg.trie[r1] = h
 20869  		}
 20870  		prg.trieMax = 256
 20871  	} else {
 20872  		prg.trieFix(prg.trieL[0]) // this fixes the non-holes in |trie|
 20873  		r1 = 0                    // now we will zero out all the holes
 20874  		for {
 20875  			s = *prg.trie[r1].rh()
 20876  			prg.trie[r1] = h
 20877  			r1 = s
 20878  			if int32(r1) > int32(prg.trieMax) {
 20879  				break
 20880  			}
 20881  		}
 20882  	}
 20883  	*prg.trie[0].b1() = byte('?' + minQuarterword) // make |trie_char(c)<>c| for all |c|
 20884  
 20885  	prg.trieNotReady = false
 20886  }
 20887  
 20888  func (prg *prg) lineBreak(finalWidowPenalty int32) {
 20889  	var (
 20890  		// Local variables for line breaking
 20891  		autoBreaking    bool               // is node |cur_p| outside a formula?
 20892  		prevP           halfword           // helps to determine when glue nodes are breakpoints
 20893  		q, r1, s, prevS halfword           // miscellaneous nodes of temporary interest
 20894  		f               internalFontNumber // used when calculating character widths
 20895  
 20896  		j                  smallNumber // an index into |hc| or |hu|
 20897  		c/* 0..255 */ byte             // character being considered for hyphenation
 20898  	)
 20899  	prg.packBeginLine = prg.curList.mlField // this is for over/underfull box messages
 20900  
 20901  	// Get ready to start line breaking
 20902  	*(*prg.mem[30000-3].hh()).rh() = *(*prg.mem[prg.curList.headField].hh()).rh()
 20903  	if int32(prg.curList.tailField) >= int32(prg.hiMemMin) {
 20904  		*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newPenalty(infPenalty)
 20905  		prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 20906  	} else if int32(*(*prg.mem[prg.curList.tailField].hh()).b0()) != glueNode {
 20907  		*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newPenalty(infPenalty)
 20908  		prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 20909  	} else {
 20910  		*(*prg.mem[prg.curList.tailField].hh()).b0() = byte(penaltyNode)
 20911  		prg.deleteGlueRef(*(*prg.mem[int32(prg.curList.tailField)+1].hh()).lh())
 20912  		prg.flushNodeList(*(*prg.mem[int32(prg.curList.tailField)+1].hh()).rh())
 20913  		*prg.mem[int32(prg.curList.tailField)+1].int() = infPenalty
 20914  	}
 20915  	*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newParamGlue(smallNumber(parFillSkipCode))
 20916  	prg.initCurLang = byte(prg.curList.pgField % 0200000)
 20917  	prg.initLHyf = prg.curList.pgField / 020000000
 20918  	prg.initRHyf = prg.curList.pgField / 0200000 % 0100
 20919  	prg.popNest()
 20920  
 20921  	prg.noShrinkErrorYet = true
 20922  
 20923  	if int32(*(*prg.mem[*(*prg.eqtb[glueBase+leftSkipCode-1].hh()).rh()].hh()).b1()) != normal && *prg.mem[int32(*(*prg.eqtb[glueBase+leftSkipCode-1].hh()).rh())+3].int() != 0 {
 20924  		*(*prg.eqtb[glueBase+leftSkipCode-1].hh()).rh() = prg.finiteShrink(*(*prg.eqtb[glueBase+leftSkipCode-1].hh()).rh())
 20925  	}
 20926  	if int32(*(*prg.mem[*(*prg.eqtb[glueBase+rightSkipCode-1].hh()).rh()].hh()).b1()) != normal && *prg.mem[int32(*(*prg.eqtb[glueBase+rightSkipCode-1].hh()).rh())+3].int() != 0 {
 20927  		*(*prg.eqtb[glueBase+rightSkipCode-1].hh()).rh() = prg.finiteShrink(*(*prg.eqtb[glueBase+rightSkipCode-1].hh()).rh())
 20928  	}
 20929  
 20930  	q = *(*prg.eqtb[glueBase+leftSkipCode-1].hh()).rh()
 20931  	r1 = *(*prg.eqtb[glueBase+rightSkipCode-1].hh()).rh()
 20932  	prg.background[1-1] = *prg.mem[int32(q)+widthOffset].int() + *prg.mem[int32(r1)+widthOffset].int()
 20933  
 20934  	prg.background[2-1] = 0
 20935  	prg.background[3-1] = 0
 20936  	prg.background[4-1] = 0
 20937  	prg.background[5-1] = 0
 20938  
 20939  	prg.background[2+int32(*(*prg.mem[q].hh()).b0())-1] = *prg.mem[int32(q)+2].int()
 20940  
 20941  	prg.background[2+int32(*(*prg.mem[r1].hh()).b0())-1] = prg.background[2+int32(*(*prg.mem[r1].hh()).b0())-1] + *prg.mem[int32(r1)+2].int()
 20942  
 20943  	prg.background[6-1] = *prg.mem[int32(q)+3].int() + *prg.mem[int32(r1)+3].int()
 20944  
 20945  	prg.minimumDemerits = 07777777777
 20946  	prg.minimalDemerits[tightFit] = 07777777777
 20947  	prg.minimalDemerits[decentFit] = 07777777777
 20948  	prg.minimalDemerits[looseFit] = 07777777777
 20949  	prg.minimalDemerits[veryLooseFit] = 07777777777
 20950  
 20951  	if int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh()) == 0 {
 20952  		if *prg.eqtb[dimenBase+hangIndentCode-1].int() == 0 {
 20953  			prg.lastSpecialLine = 0
 20954  			prg.secondWidth = *prg.eqtb[dimenBase+hsizeCode-1].int()
 20955  			prg.secondIndent = 0
 20956  		} else {
 20957  			// Set line length parameters in preparation for hanging indentation
 20958  			prg.lastSpecialLine = uint16(abs(*prg.eqtb[intBase+hangAfterCode-1].int()))
 20959  			if *prg.eqtb[intBase+hangAfterCode-1].int() < 0 {
 20960  				prg.firstWidth = *prg.eqtb[dimenBase+hsizeCode-1].int() - abs(*prg.eqtb[dimenBase+hangIndentCode-1].int())
 20961  				if *prg.eqtb[dimenBase+hangIndentCode-1].int() >= 0 {
 20962  					prg.firstIndent = *prg.eqtb[dimenBase+hangIndentCode-1].int()
 20963  				} else {
 20964  					prg.firstIndent = 0
 20965  				}
 20966  				prg.secondWidth = *prg.eqtb[dimenBase+hsizeCode-1].int()
 20967  				prg.secondIndent = 0
 20968  			} else {
 20969  				prg.firstWidth = *prg.eqtb[dimenBase+hsizeCode-1].int()
 20970  				prg.firstIndent = 0
 20971  				prg.secondWidth = *prg.eqtb[dimenBase+hsizeCode-1].int() - abs(*prg.eqtb[dimenBase+hangIndentCode-1].int())
 20972  				if *prg.eqtb[dimenBase+hangIndentCode-1].int() >= 0 {
 20973  					prg.secondIndent = *prg.eqtb[dimenBase+hangIndentCode-1].int()
 20974  				} else {
 20975  					prg.secondIndent = 0
 20976  				}
 20977  			}
 20978  		}
 20979  	} else {
 20980  		prg.lastSpecialLine = uint16(int32(*(*prg.mem[*(*prg.eqtb[parShapeLoc-1].hh()).rh()].hh()).lh()) - 1)
 20981  		prg.secondWidth = *prg.mem[int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh())+2*(int32(prg.lastSpecialLine)+1)].int()
 20982  		prg.secondIndent = *prg.mem[int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh())+2*int32(prg.lastSpecialLine)+1].int()
 20983  	}
 20984  	if *prg.eqtb[intBase+loosenessCode-1].int() == 0 {
 20985  		prg.easyLine = prg.lastSpecialLine
 20986  	} else {
 20987  		prg.easyLine = 65535
 20988  	}
 20989  
 20990  	// Find optimal breakpoints
 20991  	prg.threshold = *prg.eqtb[intBase+pretoleranceCode-1].int()
 20992  	if prg.threshold >= 0 {
 20993  		prg.secondPass = false
 20994  		prg.finalPass = false
 20995  	} else {
 20996  		prg.threshold = *prg.eqtb[intBase+toleranceCode-1].int()
 20997  		prg.secondPass = true
 20998  		prg.finalPass = *prg.eqtb[dimenBase+emergencyStretchCode-1].int() <= 0
 20999  		//  if eqtb[int_base+ tracing_paragraphs_code].int  >0 then begin_diagnostic; [  ]
 21000  	}
 21001  	for true {
 21002  		if prg.threshold > infBad {
 21003  			prg.threshold = infBad
 21004  		}
 21005  		if prg.secondPass {
 21006  			if prg.trieNotReady {
 21007  				prg.initTrie()
 21008  			}
 21009  
 21010  			prg.curLang = prg.initCurLang
 21011  			prg.lHyf = prg.initLHyf
 21012  			prg.rHyf = prg.initRHyf
 21013  		}
 21014  
 21015  		// Create an active breakpoint representing the beginning of the paragraph
 21016  		q = prg.getNode(activeNodeSize)
 21017  		*(*prg.mem[q].hh()).b0() = byte(unhyphenated)
 21018  		*(*prg.mem[q].hh()).b1() = byte(decentFit)
 21019  		*(*prg.mem[q].hh()).rh() = uint16(30000 - 7)
 21020  		*(*prg.mem[int32(q)+1].hh()).rh() = 0
 21021  		*(*prg.mem[int32(q)+1].hh()).lh() = uint16(prg.curList.pgField + 1)
 21022  		*prg.mem[int32(q)+2].int() = 0
 21023  		*(*prg.mem[30000-7].hh()).rh() = q
 21024  		prg.activeWidth[1-1] = prg.background[1-1]
 21025  		prg.activeWidth[2-1] = prg.background[2-1]
 21026  		prg.activeWidth[3-1] = prg.background[3-1]
 21027  		prg.activeWidth[4-1] = prg.background[4-1]
 21028  		prg.activeWidth[5-1] = prg.background[5-1]
 21029  		prg.activeWidth[6-1] = prg.background[6-1]
 21030  
 21031  		prg.passive = 0
 21032  		prg.printedNode = uint16(30000 - 3)
 21033  		prg.passNumber = 0
 21034  		prg.fontInShortDisplay = fontBase
 21035  		prg.curP = *(*prg.mem[30000-3].hh()).rh()
 21036  		autoBreaking = true
 21037  
 21038  		prevP = prg.curP // glue at beginning is not a legal breakpoint
 21039  		for int32(prg.curP) != 0 && int32(*(*prg.mem[30000-7].hh()).rh()) != 30000-7 {
 21040  
 21041  			// Call |try_break| if |cur_p| is a legal breakpoint; on the second pass, also try to hyphenate the next word, if |cur_p| is a glue node; then advance |cur_p| to the next node of the paragraph that could possibly be a legal breakpoint
 21042  			if int32(prg.curP) >= int32(prg.hiMemMin) {
 21043  				prevP = prg.curP
 21044  				for {
 21045  					f = *(*prg.mem[prg.curP].hh()).b0()
 21046  					prg.activeWidth[1-1] = prg.activeWidth[1-1] + *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[prg.curP].hh()).b1())].qqqq()).b0)].int()
 21047  					prg.curP = *(*prg.mem[prg.curP].hh()).rh()
 21048  					if !(int32(prg.curP) >= int32(prg.hiMemMin)) {
 21049  						break
 21050  					}
 21051  				}
 21052  			}
 21053  			switch *(*prg.mem[prg.curP].hh()).b0() {
 21054  			case hlistNode, vlistNode, ruleNode:
 21055  				prg.activeWidth[1-1] = prg.activeWidth[1-1] + *prg.mem[int32(prg.curP)+widthOffset].int()
 21056  			case whatsitNode:
 21057  				// Advance \(p)past a whatsit node in the \(l)|line_break| loop
 21058  				if int32(*(*prg.mem[prg.curP].hh()).b1()) == languageNode {
 21059  					prg.curLang = byte(*(*prg.mem[int32(prg.curP)+1].hh()).rh())
 21060  					prg.lHyf = int32(*(*prg.mem[int32(prg.curP)+1].hh()).b0())
 21061  					prg.rHyf = int32(*(*prg.mem[int32(prg.curP)+1].hh()).b1())
 21062  				}
 21063  
 21064  			case glueNode:
 21065  				if autoBreaking {
 21066  					if int32(prevP) >= int32(prg.hiMemMin) {
 21067  						prg.tryBreak(0, smallNumber(unhyphenated))
 21068  					} else if int32(*(*prg.mem[prevP].hh()).b0()) < mathNode {
 21069  						prg.tryBreak(0, smallNumber(unhyphenated))
 21070  					} else if int32(*(*prg.mem[prevP].hh()).b0()) == kernNode && int32(*(*prg.mem[prevP].hh()).b1()) != explicit {
 21071  						prg.tryBreak(0, smallNumber(unhyphenated))
 21072  					}
 21073  				}
 21074  				if int32(*(*prg.mem[*(*prg.mem[int32(prg.curP)+1].hh()).lh()].hh()).b1()) != normal && *prg.mem[int32(*(*prg.mem[int32(prg.curP)+1].hh()).lh())+3].int() != 0 {
 21075  					*(*prg.mem[int32(prg.curP)+1].hh()).lh() = prg.finiteShrink(*(*prg.mem[int32(prg.curP)+1].hh()).lh())
 21076  				}
 21077  				q = *(*prg.mem[int32(prg.curP)+1].hh()).lh()
 21078  				prg.activeWidth[1-1] = prg.activeWidth[1-1] + *prg.mem[int32(q)+widthOffset].int()
 21079  				prg.activeWidth[2+int32(*(*prg.mem[q].hh()).b0())-1] = prg.activeWidth[2+int32(*(*prg.mem[q].hh()).b0())-1] + *prg.mem[int32(q)+2].int()
 21080  
 21081  				prg.activeWidth[6-1] = prg.activeWidth[6-1] + *prg.mem[int32(q)+3].int()
 21082  				if prg.secondPass && autoBreaking {
 21083  					prevS = prg.curP
 21084  					s = *(*prg.mem[prevS].hh()).rh()
 21085  					if int32(s) != 0 {
 21086  						for true {
 21087  							if int32(s) >= int32(prg.hiMemMin) {
 21088  								c = byte(int32(*(*prg.mem[s].hh()).b1()) - minQuarterword)
 21089  								prg.hf = *(*prg.mem[s].hh()).b0()
 21090  							} else if int32(*(*prg.mem[s].hh()).b0()) == ligatureNode {
 21091  								if int32(*(*prg.mem[int32(s)+1].hh()).rh()) == 0 {
 21092  									goto continue1
 21093  								} else {
 21094  									q = *(*prg.mem[int32(s)+1].hh()).rh()
 21095  									c = byte(int32(*(*prg.mem[q].hh()).b1()) - minQuarterword)
 21096  									prg.hf = *(*prg.mem[q].hh()).b0()
 21097  								}
 21098  							} else if int32(*(*prg.mem[s].hh()).b0()) == kernNode && int32(*(*prg.mem[s].hh()).b1()) == normal {
 21099  								goto continue1
 21100  							} else if int32(*(*prg.mem[s].hh()).b0()) == whatsitNode {
 21101  								if int32(*(*prg.mem[s].hh()).b1()) == languageNode {
 21102  									prg.curLang = byte(*(*prg.mem[int32(s)+1].hh()).rh())
 21103  									prg.lHyf = int32(*(*prg.mem[int32(s)+1].hh()).b0())
 21104  									prg.rHyf = int32(*(*prg.mem[int32(s)+1].hh()).b1())
 21105  								}
 21106  
 21107  								goto continue1
 21108  							} else {
 21109  								goto done1
 21110  							}
 21111  							if int32(*(*prg.eqtb[lcCodeBase+int32(c)-1].hh()).rh()) != 0 {
 21112  								if int32(*(*prg.eqtb[lcCodeBase+int32(c)-1].hh()).rh()) == int32(c) || *prg.eqtb[intBase+ucHyphCode-1].int() > 0 {
 21113  									goto done2
 21114  								} else {
 21115  									goto done1
 21116  								}
 21117  							}
 21118  
 21119  						continue1:
 21120  							prevS = s
 21121  							s = *(*prg.mem[prevS].hh()).rh()
 21122  						}
 21123  
 21124  					done2:
 21125  						prg.hyfChar = prg.hyphenChar[prg.hf]
 21126  						if prg.hyfChar < 0 {
 21127  							goto done1
 21128  						}
 21129  						if prg.hyfChar > 255 {
 21130  							goto done1
 21131  						}
 21132  						prg.ha = prevS
 21133  						if prg.lHyf+prg.rHyf > 63 {
 21134  							goto done1
 21135  						}
 21136  
 21137  						// Skip to node |hb|, putting letters into |hu| and |hc|
 21138  						prg.hn = 0
 21139  						for true {
 21140  							if int32(s) >= int32(prg.hiMemMin) {
 21141  								if int32(*(*prg.mem[s].hh()).b0()) != int32(prg.hf) {
 21142  									goto done3
 21143  								}
 21144  								prg.hyfBchar = uint16(*(*prg.mem[s].hh()).b1())
 21145  								c = byte(int32(prg.hyfBchar) - minQuarterword)
 21146  								if int32(*(*prg.eqtb[lcCodeBase+int32(c)-1].hh()).rh()) == 0 {
 21147  									goto done3
 21148  								}
 21149  								if int32(prg.hn) == 63 {
 21150  									goto done3
 21151  								}
 21152  								prg.hb = s
 21153  								prg.hn = byte(int32(prg.hn) + 1)
 21154  								prg.hu[prg.hn] = uint16(c)
 21155  								prg.hc[prg.hn] = *(*prg.eqtb[lcCodeBase+int32(c)-1].hh()).rh()
 21156  								prg.hyfBchar = uint16(256 + minQuarterword)
 21157  							} else if int32(*(*prg.mem[s].hh()).b0()) == ligatureNode {
 21158  								if int32(*(*prg.mem[int32(s)+1].hh()).b0()) != int32(prg.hf) {
 21159  									goto done3
 21160  								}
 21161  								j = prg.hn
 21162  								q = *(*prg.mem[int32(s)+1].hh()).rh()
 21163  								if int32(q) > 0 {
 21164  									prg.hyfBchar = uint16(*(*prg.mem[q].hh()).b1())
 21165  								}
 21166  								for int32(q) > 0 {
 21167  									c = byte(int32(*(*prg.mem[q].hh()).b1()) - minQuarterword)
 21168  									if int32(*(*prg.eqtb[lcCodeBase+int32(c)-1].hh()).rh()) == 0 {
 21169  										goto done3
 21170  									}
 21171  									if int32(j) == 63 {
 21172  										goto done3
 21173  									}
 21174  									j = byte(int32(j) + 1)
 21175  									prg.hu[j] = uint16(c)
 21176  									prg.hc[j] = *(*prg.eqtb[lcCodeBase+int32(c)-1].hh()).rh()
 21177  
 21178  									q = *(*prg.mem[q].hh()).rh()
 21179  								}
 21180  								prg.hb = s
 21181  								prg.hn = j
 21182  								if *(*prg.mem[s].hh()).b1()&1 != 0 {
 21183  									prg.hyfBchar = prg.fontBchar[prg.hf]
 21184  								} else {
 21185  									prg.hyfBchar = uint16(256 + minQuarterword)
 21186  								}
 21187  							} else if int32(*(*prg.mem[s].hh()).b0()) == kernNode && int32(*(*prg.mem[s].hh()).b1()) == normal {
 21188  								prg.hb = s
 21189  								prg.hyfBchar = prg.fontBchar[prg.hf]
 21190  							} else {
 21191  								goto done3
 21192  							}
 21193  							s = *(*prg.mem[s].hh()).rh()
 21194  						}
 21195  
 21196  					done3:
 21197  						;
 21198  
 21199  						// Check that the nodes following |hb| permit hyphenation and that at least |l_hyf+r_hyf| letters have been found, otherwise |goto done1|
 21200  						if int32(prg.hn) < prg.lHyf+prg.rHyf {
 21201  							goto done1
 21202  						} // |l_hyf| and |r_hyf| are |>=1|
 21203  						for true {
 21204  							if !(int32(s) >= int32(prg.hiMemMin)) {
 21205  								switch *(*prg.mem[s].hh()).b0() {
 21206  								case ligatureNode:
 21207  								case kernNode:
 21208  									if int32(*(*prg.mem[s].hh()).b1()) != normal {
 21209  										goto done4
 21210  									}
 21211  								case whatsitNode, glueNode, penaltyNode, insNode,
 21212  									adjustNode, markNode:
 21213  
 21214  									goto done4
 21215  
 21216  								default:
 21217  									goto done1
 21218  								}
 21219  							}
 21220  							s = *(*prg.mem[s].hh()).rh()
 21221  						}
 21222  
 21223  					done4:
 21224  						;
 21225  						prg.hyphenate()
 21226  					}
 21227  
 21228  				done1:
 21229  				}
 21230  
 21231  			case kernNode:
 21232  				if int32(*(*prg.mem[prg.curP].hh()).b1()) == explicit {
 21233  					if !(int32(*(*prg.mem[prg.curP].hh()).rh()) >= int32(prg.hiMemMin)) && autoBreaking {
 21234  						if int32(*(*prg.mem[*(*prg.mem[prg.curP].hh()).rh()].hh()).b0()) == glueNode {
 21235  							prg.tryBreak(0, smallNumber(unhyphenated))
 21236  						}
 21237  					}
 21238  					prg.activeWidth[1-1] = prg.activeWidth[1-1] + *prg.mem[int32(prg.curP)+widthOffset].int()
 21239  				} else {
 21240  					prg.activeWidth[1-1] = prg.activeWidth[1-1] + *prg.mem[int32(prg.curP)+widthOffset].int()
 21241  				}
 21242  			case ligatureNode:
 21243  				f = *(*prg.mem[int32(prg.curP)+1].hh()).b0()
 21244  				prg.activeWidth[1-1] = prg.activeWidth[1-1] + *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[int32(prg.curP)+1].hh()).b1())].qqqq()).b0)].int()
 21245  
 21246  			case discNode:
 21247  				// Try to break after a discretionary fragment, then |goto done5|
 21248  				s = *(*prg.mem[int32(prg.curP)+1].hh()).lh()
 21249  				prg.discWidth = 0
 21250  				if int32(s) == 0 {
 21251  					prg.tryBreak(*prg.eqtb[intBase+exHyphenPenaltyCode-1].int(), smallNumber(hyphenated))
 21252  				} else {
 21253  					for {
 21254  						// Add the width of node |s| to |disc_width|
 21255  						if int32(s) >= int32(prg.hiMemMin) {
 21256  							f = *(*prg.mem[s].hh()).b0()
 21257  							prg.discWidth = prg.discWidth + *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[s].hh()).b1())].qqqq()).b0)].int()
 21258  						} else {
 21259  							switch *(*prg.mem[s].hh()).b0() {
 21260  							case ligatureNode:
 21261  								f = *(*prg.mem[int32(s)+1].hh()).b0()
 21262  								prg.discWidth = prg.discWidth + *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[int32(s)+1].hh()).b1())].qqqq()).b0)].int()
 21263  
 21264  							case hlistNode, vlistNode, ruleNode, kernNode:
 21265  								prg.discWidth = prg.discWidth + *prg.mem[int32(s)+widthOffset].int()
 21266  
 21267  							default:
 21268  								prg.confusion(strNumber( /* "disc3" */ 937))
 21269  								// \xref[this can't happen disc3][\quad disc3]
 21270  							}
 21271  						}
 21272  						s = *(*prg.mem[s].hh()).rh()
 21273  						if int32(s) == 0 {
 21274  							break
 21275  						}
 21276  					}
 21277  					prg.activeWidth[1-1] = prg.activeWidth[1-1] + prg.discWidth
 21278  					prg.tryBreak(*prg.eqtb[intBase+hyphenPenaltyCode-1].int(), smallNumber(hyphenated))
 21279  					prg.activeWidth[1-1] = prg.activeWidth[1-1] - prg.discWidth
 21280  				}
 21281  				r1 = uint16(*(*prg.mem[prg.curP].hh()).b1())
 21282  				s = *(*prg.mem[prg.curP].hh()).rh()
 21283  				for int32(r1) > 0 {
 21284  					if int32(s) >= int32(prg.hiMemMin) {
 21285  						f = *(*prg.mem[s].hh()).b0()
 21286  						prg.activeWidth[1-1] = prg.activeWidth[1-1] + *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[s].hh()).b1())].qqqq()).b0)].int()
 21287  					} else {
 21288  						switch *(*prg.mem[s].hh()).b0() {
 21289  						case ligatureNode:
 21290  							f = *(*prg.mem[int32(s)+1].hh()).b0()
 21291  							prg.activeWidth[1-1] = prg.activeWidth[1-1] + *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[int32(s)+1].hh()).b1())].qqqq()).b0)].int()
 21292  
 21293  						case hlistNode, vlistNode, ruleNode, kernNode:
 21294  							prg.activeWidth[1-1] = prg.activeWidth[1-1] + *prg.mem[int32(s)+widthOffset].int()
 21295  
 21296  						default:
 21297  							prg.confusion(strNumber( /* "disc4" */ 938))
 21298  							// \xref[this can't happen disc4][\quad disc4]
 21299  						}
 21300  					}
 21301  					r1 = uint16(int32(r1) - 1)
 21302  					s = *(*prg.mem[s].hh()).rh()
 21303  				}
 21304  				prevP = prg.curP
 21305  				prg.curP = s
 21306  				goto done5
 21307  
 21308  			case mathNode:
 21309  				autoBreaking = int32(*(*prg.mem[prg.curP].hh()).b1()) == after
 21310  				{
 21311  					if !(int32(*(*prg.mem[prg.curP].hh()).rh()) >= int32(prg.hiMemMin)) && autoBreaking {
 21312  						if int32(*(*prg.mem[*(*prg.mem[prg.curP].hh()).rh()].hh()).b0()) == glueNode {
 21313  							prg.tryBreak(0, smallNumber(unhyphenated))
 21314  						}
 21315  					}
 21316  					prg.activeWidth[1-1] = prg.activeWidth[1-1] + *prg.mem[int32(prg.curP)+widthOffset].int()
 21317  				}
 21318  
 21319  			case penaltyNode:
 21320  				prg.tryBreak(*prg.mem[int32(prg.curP)+1].int(), smallNumber(unhyphenated))
 21321  			case markNode, insNode, adjustNode:
 21322  
 21323  			default:
 21324  				prg.confusion(strNumber( /* "paragraph" */ 936))
 21325  				// \xref[this can't happen paragraph][\quad paragraph]
 21326  			}
 21327  
 21328  			prevP = prg.curP
 21329  			prg.curP = *(*prg.mem[prg.curP].hh()).rh()
 21330  
 21331  		done5:
 21332  		}
 21333  		if int32(prg.curP) == 0 {
 21334  			prg.tryBreak(ejectPenalty, smallNumber(hyphenated))
 21335  			if int32(*(*prg.mem[30000-7].hh()).rh()) != 30000-7 {
 21336  				r1 = *(*prg.mem[30000-7].hh()).rh()
 21337  				prg.fewestDemerits = 07777777777
 21338  				for {
 21339  					if int32(*(*prg.mem[r1].hh()).b0()) != deltaNode {
 21340  						if *prg.mem[int32(r1)+2].int() < prg.fewestDemerits {
 21341  							prg.fewestDemerits = *prg.mem[int32(r1)+2].int()
 21342  							prg.bestBet = r1
 21343  						}
 21344  					}
 21345  					r1 = *(*prg.mem[r1].hh()).rh()
 21346  					if int32(r1) == 30000-7 {
 21347  						break
 21348  					}
 21349  				}
 21350  				prg.bestLine = *(*prg.mem[int32(prg.bestBet)+1].hh()).lh()
 21351  				if *prg.eqtb[intBase+loosenessCode-1].int() == 0 {
 21352  					goto done
 21353  				}
 21354  
 21355  				// Find the best active node for the desired looseness
 21356  				{
 21357  					r1 = *(*prg.mem[30000-7].hh()).rh()
 21358  					prg.actualLooseness = 0
 21359  					for {
 21360  						if int32(*(*prg.mem[r1].hh()).b0()) != deltaNode {
 21361  							prg.lineDiff = int32(*(*prg.mem[int32(r1)+1].hh()).lh()) - int32(prg.bestLine)
 21362  							if prg.lineDiff < prg.actualLooseness && *prg.eqtb[intBase+loosenessCode-1].int() <= prg.lineDiff || prg.lineDiff > prg.actualLooseness && *prg.eqtb[intBase+loosenessCode-1].int() >= prg.lineDiff {
 21363  								prg.bestBet = r1
 21364  								prg.actualLooseness = prg.lineDiff
 21365  								prg.fewestDemerits = *prg.mem[int32(r1)+2].int()
 21366  							} else if prg.lineDiff == prg.actualLooseness && *prg.mem[int32(r1)+2].int() < prg.fewestDemerits {
 21367  								prg.bestBet = r1
 21368  								prg.fewestDemerits = *prg.mem[int32(r1)+2].int()
 21369  							}
 21370  						}
 21371  						r1 = *(*prg.mem[r1].hh()).rh()
 21372  						if int32(r1) == 30000-7 {
 21373  							break
 21374  						}
 21375  					}
 21376  					prg.bestLine = *(*prg.mem[int32(prg.bestBet)+1].hh()).lh()
 21377  				}
 21378  				if prg.actualLooseness == *prg.eqtb[intBase+loosenessCode-1].int() || prg.finalPass {
 21379  					goto done
 21380  				}
 21381  			}
 21382  		}
 21383  
 21384  		// Clean up the memory by removing the break nodes
 21385  		q = *(*prg.mem[30000-7].hh()).rh()
 21386  		for int32(q) != 30000-7 {
 21387  			prg.curP = *(*prg.mem[q].hh()).rh()
 21388  			if int32(*(*prg.mem[q].hh()).b0()) == deltaNode {
 21389  				prg.freeNode(q, halfword(deltaNodeSize))
 21390  			} else {
 21391  				prg.freeNode(q, halfword(activeNodeSize))
 21392  			}
 21393  			q = prg.curP
 21394  		}
 21395  		q = prg.passive
 21396  		for int32(q) != 0 {
 21397  			prg.curP = *(*prg.mem[q].hh()).rh()
 21398  			prg.freeNode(q, halfword(passiveNodeSize))
 21399  			q = prg.curP
 21400  		}
 21401  		if !prg.secondPass {
 21402  			prg.threshold = *prg.eqtb[intBase+toleranceCode-1].int()
 21403  			prg.secondPass = true
 21404  			prg.finalPass = *prg.eqtb[dimenBase+emergencyStretchCode-1].int() <= 0
 21405  		} else {
 21406  			prg.background[2-1] = prg.background[2-1] + *prg.eqtb[dimenBase+emergencyStretchCode-1].int()
 21407  			prg.finalPass = true
 21408  		}
 21409  	}
 21410  
 21411  done:
 21412  	;
 21413  
 21414  	// Break the paragraph at the chosen breakpoints, justify the resulting lines to the correct widths, and append them to the current vertical list
 21415  	prg.postLineBreak(finalWidowPenalty)
 21416  
 21417  	// Clean up the memory by removing the break nodes
 21418  	q = *(*prg.mem[30000-7].hh()).rh()
 21419  	for int32(q) != 30000-7 {
 21420  		prg.curP = *(*prg.mem[q].hh()).rh()
 21421  		if int32(*(*prg.mem[q].hh()).b0()) == deltaNode {
 21422  			prg.freeNode(q, halfword(deltaNodeSize))
 21423  		} else {
 21424  			prg.freeNode(q, halfword(activeNodeSize))
 21425  		}
 21426  		q = prg.curP
 21427  	}
 21428  	q = prg.passive
 21429  	for int32(q) != 0 {
 21430  		prg.curP = *(*prg.mem[q].hh()).rh()
 21431  		prg.freeNode(q, halfword(passiveNodeSize))
 21432  		q = prg.curP
 21433  	}
 21434  	prg.packBeginLine = 0
 21435  }
 21436  
 21437  // 817.
 21438  
 21439  // tangle:pos tex.web:16090:1:
 21440  
 21441  // When looking for optimal line breaks, \TeX\ creates a ``break node'' for
 21442  // each break that is [\sl feasible], in the sense that there is a way to end
 21443  // a line at the given place without requiring any line to stretch more than
 21444  // a given tolerance. A break node is characterized by three things: the position
 21445  // of the break (which is a pointer to a |glue_node|, |math_node|, |penalty_node|,
 21446  // or |disc_node|); the ordinal number of the line that will follow this
 21447  // breakpoint; and the fitness classification of the line that has just
 21448  // ended, i.e., |tight_fit|, |decent_fit|, |loose_fit|, or |very_loose_fit|.
 21449  
 21450  // 818.
 21451  
 21452  // tangle:pos tex.web:16107:1:
 21453  
 21454  // The algorithm essentially determines the best possible way to achieve
 21455  // each feasible combination of position, line, and fitness. Thus, it answers
 21456  // questions like, ``What is the best way to break the opening part of the
 21457  // paragraph so that the fourth line is a tight line ending at such-and-such
 21458  // a place?'' However, the fact that all lines are to be the same length
 21459  // after a certain point makes it possible to regard all sufficiently large
 21460  // line numbers as equivalent, when the looseness parameter is zero, and this
 21461  // makes it possible for the algorithm to save space and time.
 21462  //
 21463  // An ``active node'' and a ``passive node'' are created in |mem| for each
 21464  // feasible breakpoint that needs to be considered. Active nodes are three
 21465  // words long and passive nodes are two words long. We need active nodes only
 21466  // for breakpoints near the place in the paragraph that is currently being
 21467  // examined, so they are recycled within a comparatively short time after
 21468  // they are created.
 21469  
 21470  // 819.
 21471  
 21472  // tangle:pos tex.web:16123:1:
 21473  
 21474  // An active node for a given breakpoint contains six fields:
 21475  //
 21476  // \yskip\hang|link| points to the next node in the list of active nodes; the
 21477  // last active node has |link=last_active|.
 21478  //
 21479  // \yskip\hang|break_node| points to the passive node associated with this
 21480  // breakpoint.
 21481  //
 21482  // \yskip\hang|line_number| is the number of the line that follows this
 21483  // breakpoint.
 21484  //
 21485  // \yskip\hang|fitness| is the fitness classification of the line ending at this
 21486  // breakpoint.
 21487  //
 21488  // \yskip\hang|type| is either |hyphenated| or |unhyphenated|, depending on
 21489  // whether this breakpoint is a |disc_node|.
 21490  //
 21491  // \yskip\hang|total_demerits| is the minimum possible sum of demerits over all
 21492  // lines leading from the beginning of the paragraph to this breakpoint.
 21493  //
 21494  // \yskip\noindent
 21495  // The value of |link(active)| points to the first active node on a linked list
 21496  // of all currently active nodes. This list is in order by |line_number|,
 21497  // except that nodes with |line_number>easy_line| may be in any order relative
 21498  // to each other.
 21499  
 21500  // 822.
 21501  
 21502  // tangle:pos tex.web:16193:1:
 21503  
 21504  // The active list also contains ``delta'' nodes that help the algorithm
 21505  // compute the badness of individual lines. Such nodes appear only between two
 21506  // active nodes, and they have |type=delta_node|. If |p| and |r| are active nodes
 21507  // and if |q| is a delta node between them, so that |link(p)=q| and |link(q)=r|,
 21508  // then |q| tells the space difference between lines in the horizontal list that
 21509  // start after breakpoint |p| and lines that start after breakpoint |r|. In
 21510  // other words, if we know the length of the line that starts after |p| and
 21511  // ends at our current position, then the corresponding length of the line that
 21512  // starts after |r| is obtained by adding the amounts in node~|q|. A delta node
 21513  // contains six scaled numbers, since it must record the net change in glue
 21514  // stretchability with respect to all orders of infinity. The natural width
 21515  // difference appears in |mem[q+1].sc|; the stretch differences in units of
 21516  // pt, fil, fill, and filll appear in |mem[q+2..q+5].sc|; and the shrink difference
 21517  // appears in |mem[q+6].sc|. The |subtype| field of a delta node is not used.
 21518  
 21519  // 824.
 21520  
 21521  // tangle:pos tex.web:16234:1:
 21522  
 21523  // Let's state the principles of the delta nodes more precisely and concisely,
 21524  // so that the following programs will be less obscure. For each legal
 21525  // breakpoint~|p| in the paragraph, we define two quantities $\alpha(p)$ and
 21526  // $\beta(p)$ such that the length of material in a line from breakpoint~|p|
 21527  // to breakpoint~|q| is $\gamma+\beta(q)-\alpha(p)$, for some fixed $\gamma$.
 21528  // Intuitively, $\alpha(p)$ and $\beta(q)$ are the total length of material from
 21529  // the beginning of the paragraph to a point ``after'' a break at |p| and to a
 21530  // point ``before'' a break at |q|; and $\gamma$ is the width of an empty line,
 21531  // namely the length contributed by \.[\\leftskip] and \.[\\rightskip].
 21532  //
 21533  // Suppose, for example, that the paragraph consists entirely of alternating
 21534  // boxes and glue skips; let the boxes have widths $x_1\ldots x_n$ and
 21535  // let the skips have widths $y_1\ldots y_n$, so that the paragraph can be
 21536  // represented by $x_1y_1\ldots x_ny_n$. Let $p_i$ be the legal breakpoint
 21537  // at $y_i$; then $\alpha(p_i)=x_1+y_1+\cdots+x_i+y_i$, and $\beta(p_i)=
 21538  // x_1+y_1+\cdots+x_i$. To check this, note that the length of material from
 21539  // $p_2$ to $p_5$, say, is $\gamma+x_3+y_3+x_4+y_4+x_5=\gamma+\beta(p_5)
 21540  // -\alpha(p_2)$.
 21541  //
 21542  // The quantities $\alpha$, $\beta$, $\gamma$ involve glue stretchability and
 21543  // shrinkability as well as a natural width. If we were to compute $\alpha(p)$
 21544  // and $\beta(p)$ for each |p|, we would need multiple precision arithmetic, and
 21545  // the multiprecise numbers would have to be kept in the active nodes.
 21546  // \TeX\ avoids this problem by working entirely with relative differences
 21547  // or ``deltas.'' Suppose, for example, that the active list contains
 21548  // $a_1\,\delta_1\,a_2\,\delta_2\,a_3$, where the |a|'s are active breakpoints
 21549  // and the $\delta$'s are delta nodes. Then $\delta_1=\alpha(a_1)-\alpha(a_2)$
 21550  // and $\delta_2=\alpha(a_2)-\alpha(a_3)$. If the line breaking algorithm is
 21551  // currently positioned at some other breakpoint |p|, the |active_width| array
 21552  // contains the value $\gamma+\beta(p)-\alpha(a_1)$. If we are scanning through
 21553  // the list of active nodes and considering a tentative line that runs from
 21554  // $a_2$ to~|p|, say, the |cur_active_width| array will contain the value
 21555  // $\gamma+\beta(p)-\alpha(a_2)$. Thus, when we move from $a_2$ to $a_3$,
 21556  // we want to add $\alpha(a_2)-\alpha(a_3)$ to |cur_active_width|; and this
 21557  // is just $\delta_2$, which appears in the active list between $a_2$ and
 21558  // $a_3$. The |background| array contains $\gamma$. The |break_width| array
 21559  // will be used to calculate values of new delta nodes when the active
 21560  // list is being updated.
 21561  
 21562  // 904.
 21563  
 21564  // tangle:pos tex.web:17720:1:
 21565  
 21566  // We must now face the fact that the battle is not over, even though the
 21567  // [\def\![\kern-1pt]%
 21568  // hyphens have been found: The process of reconstituting a word can be nontrivial
 21569  // because ligatures might change when a hyphen is present. [\sl The \TeX book\/]
 21570  // discusses the difficulties of the word ``difficult'', and
 21571  // the discretionary material surrounding a
 21572  // hyphen can be considerably more complex than that. Suppose
 21573  // \.[abcdef] is a word in a font for which the only ligatures are \.[b\!c],
 21574  // \.[c\!d], \.[d\!e], and \.[e\!f]. If this word permits hyphenation
 21575  // between \.b and \.c, the two patterns with and without hyphenation are
 21576  // $\.a\,\.b\,\.-\,\.[c\!d]\,\.[e\!f]$ and $\.a\,\.[b\!c]\,\.[d\!e]\,\.f$.
 21577  // Thus the insertion of a hyphen might cause effects to ripple arbitrarily
 21578  // far into the rest of the word. A further complication arises if additional
 21579  // hyphens appear together with such rippling, e.g., if the word in the
 21580  // example just given could also be hyphenated between \.c and \.d; \TeX\
 21581  // avoids this by simply ignoring the additional hyphens in such weird cases.]
 21582  //
 21583  // Still further complications arise in the presence of ligatures that do not
 21584  // delete the original characters. When punctuation precedes the word being
 21585  // hyphenated, \TeX's method is not perfect under all possible scenarios,
 21586  // because punctuation marks and letters can propagate information back and forth.
 21587  // For example, suppose the original pre-hyphenation pair
 21588  // \.[*a] changes to \.[*y] via a \.[\?=:] ligature, which changes to \.[xy]
 21589  // via a \.[=:\?] ligature; if $p_[a-1]=\.x$ and $p_a=\.y$, the reconstitution
 21590  // procedure isn't smart enough to obtain \.[xy] again. In such cases the
 21591  // font designer should include a ligature that goes from \.[xa] to \.[xy].
 21592  
 21593  // 919. \[42] Hyphenation
 21594  
 21595  // tangle:pos tex.web:18072:19:
 21596  
 21597  // When a word |hc[1..hn]| has been set up to contain a candidate for hyphenation,
 21598  // \TeX\ first looks to see if it is in the user's exception dictionary. If not,
 21599  // hyphens are inserted based on patterns that appear within the given word,
 21600  // using an algorithm due to Frank~M. Liang.
 21601  // \xref[Liang, Franklin Mark]
 21602  //
 21603  // Let's consider Liang's method first, since it is much more interesting than the
 21604  // exception-lookup routine.  The algorithm begins by setting |hyf[j]| to zero
 21605  // for all |j|, and invalid characters are inserted into |hc[0]|
 21606  // and |hc[hn+1]| to serve as delimiters. Then a reasonably fast method is
 21607  // used to see which of a given set of patterns occurs in the word
 21608  // |hc[0..(hn+1)]|. Each pattern $p_1\ldots p_k$ of length |k| has an associated
 21609  // sequence of |k+1| numbers $n_0\ldots n_k$; and if the pattern occurs in
 21610  // |hc[(j+1)..(j+k)]|, \TeX\ will set |hyf[j+i]:=max(hyf[j+i],$n_i$)| for
 21611  // |0<=i<=k|. After this has been done for each pattern that occurs, a
 21612  // discretionary hyphen will be inserted between |hc[j]| and |hc[j+1]| when
 21613  // |hyf[j]| is odd, as we have already seen.
 21614  //
 21615  // The set of patterns $p_1\ldots p_k$ and associated numbers $n_0\ldots n_k$
 21616  // depends, of course, on the language whose words are being hyphenated, and
 21617  // on the degree of hyphenation that is desired. A method for finding
 21618  // appropriate |p|'s and |n|'s, from a given dictionary of words and acceptable
 21619  // hyphenations, is discussed in Liang's Ph.D. thesis (Stanford University,
 21620  // 1983); \TeX\ simply starts with the patterns and works from there.
 21621  
 21622  // 934.
 21623  
 21624  // tangle:pos tex.web:18253:1:
 21625  
 21626  // We have now completed the hyphenation routine, so the |line_break| procedure
 21627  // is finished at last. Since the hyphenation exception table is fresh in our
 21628  // minds, it's a good time to deal with the routine that adds new entries to it.
 21629  //
 21630  // When \TeX\ has scanned `\.[\\hyphenation]', it calls on a procedure named
 21631  // |new_hyph_exceptions| to do the right thing.
 21632  func (prg *prg) newHyphExceptions() {
 21633  	var (
 21634  		n/* 0..64 */ byte             // length of current word; not always a |small_number|
 21635  		j/* 0..64 */ byte             // an index into |hc|
 21636  		h                 hyphPointer // an index into |hyph_word| and |hyph_list|
 21637  		k                 strNumber   // an index into |str_start|
 21638  		p                 halfword    // head of a list of hyphen positions
 21639  		q                 halfword    // used when creating a new node for list |p|
 21640  		s, t              strNumber   // strings being compared or stored
 21641  		u, v              poolPointer // indices into |str_pool|
 21642  	)
 21643  	prg.scanLeftBrace() // a left brace must follow \.[\\hyphenation]
 21644  	if *prg.eqtb[intBase+languageCode-1].int() <= 0 {
 21645  		prg.curLang = 0
 21646  	} else if *prg.eqtb[intBase+languageCode-1].int() > 255 {
 21647  		prg.curLang = 0
 21648  	} else {
 21649  		prg.curLang = byte(*prg.eqtb[intBase+languageCode-1].int())
 21650  	}
 21651  
 21652  	// Enter as many hyphenation exceptions as are listed, until coming to a right brace; then |return|
 21653  	n = 0
 21654  	p = 0
 21655  	for true {
 21656  		prg.getXToken()
 21657  
 21658  	reswitch:
 21659  		switch prg.curCmd {
 21660  		case letter, otherChar, charGiven:
 21661  			// Append a new letter or hyphen
 21662  			if int32(prg.curChr) == '-' {
 21663  				if int32(n) < 63 {
 21664  					q = prg.getAvail()
 21665  					*(*prg.mem[q].hh()).rh() = p
 21666  					*(*prg.mem[q].hh()).lh() = uint16(n)
 21667  					p = q
 21668  				}
 21669  			} else {
 21670  				if int32(*(*prg.eqtb[lcCodeBase+int32(prg.curChr)-1].hh()).rh()) == 0 {
 21671  					{
 21672  						if int32(prg.interaction) == errorStopMode {
 21673  						}
 21674  						prg.printNl(strNumber( /* "! " */ 262))
 21675  						prg.print( /* "Not a letter" */ 945)
 21676  					}
 21677  					// \xref[Not a letter]
 21678  					{
 21679  						prg.helpPtr = 2
 21680  						prg.helpLine[1] = /* "Letters in \\hyphenation words must have \\lccode>0." */ 946
 21681  						prg.helpLine[0] = /* "Proceed; I'll ignore the character I just read." */ 947
 21682  					}
 21683  					prg.error1()
 21684  				} else if int32(n) < 63 {
 21685  					n = byte(int32(n) + 1)
 21686  					prg.hc[n] = *(*prg.eqtb[lcCodeBase+int32(prg.curChr)-1].hh()).rh()
 21687  				}
 21688  			}
 21689  
 21690  		case charNum:
 21691  			prg.scanCharNum()
 21692  			prg.curChr = uint16(prg.curVal)
 21693  			prg.curCmd = byte(charGiven)
 21694  
 21695  			goto reswitch
 21696  
 21697  		case spacer, rightBrace:
 21698  			if int32(n) > 1 {
 21699  				n = byte(int32(n) + 1)
 21700  				prg.hc[n] = uint16(prg.curLang)
 21701  				{
 21702  					if int32(prg.poolPtr)+int32(n) > poolSize {
 21703  						prg.overflow(strNumber( /* "pool size" */ 257), poolSize-int32(prg.initPoolPtr))
 21704  					} /* \xref[TeX capacity exceeded pool size][\quad pool size]  */
 21705  				}
 21706  				h = 0
 21707  				for ii := int32(1); ii <= int32(n); ii++ {
 21708  					j = byte(ii)
 21709  					_ = j
 21710  					h = uint16((int32(h) + int32(h) + int32(prg.hc[j])) % hyphSize)
 21711  					{
 21712  						prg.strPool[prg.poolPtr] = byte(prg.hc[j])
 21713  						prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
 21714  					}
 21715  				}
 21716  				s = prg.makeString()
 21717  
 21718  				// Insert the \(p)pair |(s,p)| into the exception table
 21719  				if int32(prg.hyphCount) == hyphSize {
 21720  					prg.overflow(strNumber( /* "exception dictionary" */ 948), hyphSize)
 21721  				}
 21722  				// \xref[TeX capacity exceeded exception dictionary][\quad exception dictionary]
 21723  				prg.hyphCount = uint16(int32(prg.hyphCount) + 1)
 21724  				for int32(prg.hyphWord[h]) != 0 {
 21725  					k = prg.hyphWord[h]
 21726  					if int32(prg.strStart[int32(k)+1])-int32(prg.strStart[k]) < int32(prg.strStart[int32(s)+1])-int32(prg.strStart[s]) {
 21727  						goto found
 21728  					}
 21729  					if int32(prg.strStart[int32(k)+1])-int32(prg.strStart[k]) > int32(prg.strStart[int32(s)+1])-int32(prg.strStart[s]) {
 21730  						goto notFound
 21731  					}
 21732  					u = prg.strStart[k]
 21733  					v = prg.strStart[s]
 21734  					for {
 21735  						if int32(prg.strPool[u]) < int32(prg.strPool[v]) {
 21736  							goto found
 21737  						}
 21738  						if int32(prg.strPool[u]) > int32(prg.strPool[v]) {
 21739  							goto notFound
 21740  						}
 21741  						u = uint16(int32(u) + 1)
 21742  						v = uint16(int32(v) + 1)
 21743  						if int32(u) == int32(prg.strStart[int32(k)+1]) {
 21744  							break
 21745  						}
 21746  					}
 21747  
 21748  				found:
 21749  					q = prg.hyphList[h]
 21750  					prg.hyphList[h] = p
 21751  					p = q
 21752  
 21753  					t = prg.hyphWord[h]
 21754  					prg.hyphWord[h] = s
 21755  					s = t
 21756  
 21757  				notFound:
 21758  					;
 21759  					if int32(h) > 0 {
 21760  						h = uint16(int32(h) - 1)
 21761  					} else {
 21762  						h = uint16(hyphSize)
 21763  					}
 21764  				}
 21765  				prg.hyphWord[h] = s
 21766  				prg.hyphList[h] = p
 21767  			}
 21768  			if int32(prg.curCmd) == rightBrace {
 21769  				goto exit
 21770  			}
 21771  			n = 0
 21772  			p = 0
 21773  
 21774  		default:
 21775  			{
 21776  				if int32(prg.interaction) == errorStopMode {
 21777  				}
 21778  				prg.printNl(strNumber( /* "! " */ 262))
 21779  				prg.print( /* "Improper " */ 680)
 21780  			}
 21781  			prg.printEsc(strNumber( /* "hyphenation" */ 941))
 21782  			// \xref[Improper \\hyphenation...]
 21783  			prg.print( /* " will be flushed" */ 942)
 21784  			{
 21785  				prg.helpPtr = 2
 21786  				prg.helpLine[1] = /* "Hyphenation exceptions must contain only letters" */ 943
 21787  				prg.helpLine[0] = /* "and hyphens. But continue; I'll forgive and forget." */ 944
 21788  			}
 21789  			prg.error1()
 21790  
 21791  		}
 21792  	}
 21793  
 21794  exit:
 21795  }
 21796  
 21797  // 967. \[44] Breaking vertical lists into pages
 21798  
 21799  // tangle:pos tex.web:18850:42:
 21800  
 21801  // The |vsplit| procedure, which implements \TeX's \.[\\vsplit] operation,
 21802  // is considerably simpler than |line_break| because it doesn't have to
 21803  // worry about hyphenation, and because its mission is to discover a single
 21804  // break instead of an optimum sequence of breakpoints.  But before we get
 21805  // into the details of |vsplit|, we need to consider a few more basic things.
 21806  
 21807  // 968.
 21808  
 21809  // tangle:pos tex.web:18856:1:
 21810  
 21811  // A subroutine called |prune_page_top| takes a pointer to a vlist and
 21812  // returns a pointer to a modified vlist in which all glue, kern, and penalty nodes
 21813  // have been deleted before the first box or rule node. However, the first
 21814  // box or rule is actually preceded by a newly created glue node designed so that
 21815  // the topmost baseline will be at distance |split_top_skip| from the top,
 21816  // whenever this is possible without backspacing.
 21817  //
 21818  // In this routine and those that follow, we make use of the fact that a
 21819  // vertical list contains no character nodes, hence the |type| field exists
 21820  // for each node in the list.
 21821  // \xref[data structure assumptions]
 21822  func (prg *prg) prunePageTop(p halfword) (r halfword) { // adjust top after page break
 21823  	var (
 21824  		prevP halfword // lags one step behind |p|
 21825  		q     halfword // temporary variable for list manipulation
 21826  	)
 21827  	prevP = uint16(30000 - 3)
 21828  	*(*prg.mem[30000-3].hh()).rh() = p
 21829  	for int32(p) != 0 {
 21830  		switch *(*prg.mem[p].hh()).b0() {
 21831  		case hlistNode, vlistNode, ruleNode:
 21832  			// Insert glue for |split_top_skip| and set~|p:=null|
 21833  			q = prg.newSkipParam(smallNumber(splitTopSkipCode))
 21834  			*(*prg.mem[prevP].hh()).rh() = q
 21835  			*(*prg.mem[q].hh()).rh() = p
 21836  			// now |temp_ptr=glue_ptr(q)|
 21837  			if *prg.mem[int32(prg.tempPtr)+widthOffset].int() > *prg.mem[int32(p)+heightOffset].int() {
 21838  				*prg.mem[int32(prg.tempPtr)+widthOffset].int() = *prg.mem[int32(prg.tempPtr)+widthOffset].int() - *prg.mem[int32(p)+heightOffset].int()
 21839  			} else {
 21840  				*prg.mem[int32(prg.tempPtr)+widthOffset].int() = 0
 21841  			}
 21842  			p = 0
 21843  
 21844  		case whatsitNode, markNode, insNode:
 21845  			prevP = p
 21846  			p = *(*prg.mem[prevP].hh()).rh()
 21847  
 21848  		case glueNode, kernNode, penaltyNode:
 21849  			q = p
 21850  			p = *(*prg.mem[q].hh()).rh()
 21851  			*(*prg.mem[q].hh()).rh() = 0
 21852  			*(*prg.mem[prevP].hh()).rh() = p
 21853  			prg.flushNodeList(q)
 21854  
 21855  		default:
 21856  			prg.confusion(strNumber( /* "pruning" */ 959))
 21857  			// \xref[this can't happen pruning][\quad pruning]
 21858  		}
 21859  	}
 21860  	r = *(*prg.mem[30000-3].hh()).rh()
 21861  	return r
 21862  }
 21863  
 21864  // 970.
 21865  
 21866  // tangle:pos tex.web:18895:1:
 21867  
 21868  // The next subroutine finds the best place to break a given vertical list
 21869  // so as to obtain a box of height~|h|, with maximum depth~|d|.
 21870  // A pointer to the beginning of the vertical list is given,
 21871  // and a pointer to the optimum breakpoint is returned. The list is effectively
 21872  // followed by a forced break, i.e., a penalty node with the |eject_penalty|;
 21873  // if the best break occurs at this artificial node, the value |null| is returned.
 21874  //
 21875  // An array of six |scaled| distances is used to keep track of the height
 21876  // from the beginning of the list to the current place, just as in |line_break|.
 21877  // In fact, we use one of the same arrays, only changing its name to reflect
 21878  // its new significance.
 21879  func (prg *prg) vertBreak(p halfword, h, d scaled) (r halfword) {
 21880  	var (
 21881  		prevP halfword // if |p| is a glue node, |type(prev_p)| determines
 21882  		//   whether |p| is a legal breakpoint
 21883  
 21884  		q, r1     halfword    // glue specifications
 21885  		pi        int32       // penalty value
 21886  		b         int32       // badness at a trial breakpoint
 21887  		leastCost int32       // the smallest badness plus penalties found so far
 21888  		bestPlace halfword    // the most recent break that leads to |least_cost|
 21889  		prevDp    scaled      // depth of previous box in the list
 21890  		t         smallNumber // |type| of the node following a kern
 21891  	)
 21892  	prevP = p // an initial glue node is not a legal breakpoint
 21893  	leastCost = 07777777777
 21894  	prg.activeWidth[1-1] = 0
 21895  	prg.activeWidth[2-1] = 0
 21896  	prg.activeWidth[3-1] = 0
 21897  	prg.activeWidth[4-1] = 0
 21898  	prg.activeWidth[5-1] = 0
 21899  	prg.activeWidth[6-1] = 0
 21900  	prevDp = 0
 21901  	for true {
 21902  		if int32(p) == 0 {
 21903  			pi = ejectPenalty
 21904  		} else {
 21905  			// Use node |p| to update the current height and depth measurements; if this node is not a legal breakpoint, |goto not_found| or |update_heights|, otherwise set |pi| to the associated penalty at the break
 21906  			switch *(*prg.mem[p].hh()).b0() {
 21907  			case hlistNode, vlistNode, ruleNode:
 21908  				prg.activeWidth[1-1] = prg.activeWidth[1-1] + prevDp + *prg.mem[int32(p)+heightOffset].int()
 21909  				prevDp = *prg.mem[int32(p)+depthOffset].int()
 21910  
 21911  				goto notFound
 21912  
 21913  			case whatsitNode:
 21914  				// Process whatsit |p| in |vert_break| loop, |goto not_found|
 21915  
 21916  				// Process whatsit |p| in |vert_break| loop, |goto not_found|
 21917  				goto notFound
 21918  
 21919  			case glueNode:
 21920  				if int32(*(*prg.mem[prevP].hh()).b0()) < mathNode {
 21921  					pi = 0
 21922  				} else {
 21923  					goto updateHeights
 21924  				}
 21925  			case kernNode:
 21926  				if int32(*(*prg.mem[p].hh()).rh()) == 0 {
 21927  					t = byte(penaltyNode)
 21928  				} else {
 21929  					t = *(*prg.mem[*(*prg.mem[p].hh()).rh()].hh()).b0()
 21930  				}
 21931  				if int32(t) == glueNode {
 21932  					pi = 0
 21933  				} else {
 21934  					goto updateHeights
 21935  				}
 21936  
 21937  			case penaltyNode:
 21938  				pi = *prg.mem[int32(p)+1].int()
 21939  			case markNode, insNode:
 21940  				goto notFound
 21941  
 21942  			default:
 21943  				prg.confusion(strNumber( /* "vertbreak" */ 960))
 21944  				// \xref[this can't happen vertbreak][\quad vertbreak]
 21945  			}
 21946  		}
 21947  
 21948  		// Check if node |p| is a new champion breakpoint; then \(go)|goto done| if |p| is a forced break or if the page-so-far is already too full
 21949  		if pi < infPenalty {
 21950  			if prg.activeWidth[1-1] < h {
 21951  				if prg.activeWidth[3-1] != 0 || prg.activeWidth[4-1] != 0 || prg.activeWidth[5-1] != 0 {
 21952  					b = 0
 21953  				} else {
 21954  					b = int32(prg.badness(h-prg.activeWidth[1-1], prg.activeWidth[2-1]))
 21955  				}
 21956  			} else if prg.activeWidth[1-1]-h > prg.activeWidth[6-1] {
 21957  				b = 07777777777
 21958  			} else {
 21959  				b = int32(prg.badness(prg.activeWidth[1-1]-h, prg.activeWidth[6-1]))
 21960  			}
 21961  			if b < 07777777777 {
 21962  				if pi <= ejectPenalty {
 21963  					b = pi
 21964  				} else if b < infBad {
 21965  					b = b + pi
 21966  				} else {
 21967  					b = 100000
 21968  				}
 21969  			}
 21970  			if b <= leastCost {
 21971  				bestPlace = p
 21972  				leastCost = b
 21973  				prg.bestHeightPlusDepth = prg.activeWidth[1-1] + prevDp
 21974  			}
 21975  			if b == 07777777777 || pi <= ejectPenalty {
 21976  				goto done
 21977  			}
 21978  		}
 21979  		if int32(*(*prg.mem[p].hh()).b0()) < glueNode || int32(*(*prg.mem[p].hh()).b0()) > kernNode {
 21980  			goto notFound
 21981  		}
 21982  
 21983  	updateHeights:
 21984  		if int32(*(*prg.mem[p].hh()).b0()) == kernNode {
 21985  			q = p
 21986  		} else {
 21987  			q = *(*prg.mem[int32(p)+1].hh()).lh()
 21988  			prg.activeWidth[2+int32(*(*prg.mem[q].hh()).b0())-1] = prg.activeWidth[2+int32(*(*prg.mem[q].hh()).b0())-1] + *prg.mem[int32(q)+2].int()
 21989  
 21990  			prg.activeWidth[6-1] = prg.activeWidth[6-1] + *prg.mem[int32(q)+3].int()
 21991  			if int32(*(*prg.mem[q].hh()).b1()) != normal && *prg.mem[int32(q)+3].int() != 0 {
 21992  				{
 21993  					if int32(prg.interaction) == errorStopMode {
 21994  					}
 21995  					prg.printNl(strNumber( /* "! " */ 262))
 21996  					prg.print( /* "Infinite glue shrinkage found in box being split" */ 961)
 21997  				}
 21998  
 21999  				// \xref[Infinite glue shrinkage...]
 22000  				{
 22001  					prg.helpPtr = 4
 22002  					prg.helpLine[3] = /* "The box you are \\vsplitting contains some infinitely" */ 962
 22003  					prg.helpLine[2] = /* "shrinkable glue, e.g., `\\vss' or `\\vskip 0pt minus 1fil'." */ 963
 22004  					prg.helpLine[1] = /* "Such glue doesn't belong there; but you can safely proceed," */ 964
 22005  					prg.helpLine[0] = /* "since the offensive shrinkability has been made finite." */ 922
 22006  				}
 22007  				prg.error1()
 22008  				r1 = prg.newSpec(q)
 22009  				*(*prg.mem[r1].hh()).b1() = byte(normal)
 22010  				prg.deleteGlueRef(q)
 22011  				*(*prg.mem[int32(p)+1].hh()).lh() = r1
 22012  				q = r1
 22013  			}
 22014  		}
 22015  		prg.activeWidth[1-1] = prg.activeWidth[1-1] + prevDp + *prg.mem[int32(q)+widthOffset].int()
 22016  		prevDp = 0
 22017  
 22018  	notFound:
 22019  		if prevDp > d {
 22020  			prg.activeWidth[1-1] = prg.activeWidth[1-1] + prevDp - d
 22021  			prevDp = d
 22022  		}
 22023  
 22024  		prevP = p
 22025  		p = *(*prg.mem[prevP].hh()).rh()
 22026  	}
 22027  
 22028  done:
 22029  	r = bestPlace
 22030  	return r
 22031  }
 22032  
 22033  // 977.
 22034  
 22035  // tangle:pos tex.web:19031:1:
 22036  
 22037  // Now we are ready to consider |vsplit| itself. Most of
 22038  // its work is accomplished by the two subroutines that we have just considered.
 22039  //
 22040  // Given the number of a vlist box |n|, and given a desired page height |h|,
 22041  // the |vsplit| function finds the best initial segment of the vlist and
 22042  // returns a box for a page of height~|h|. The remainder of the vlist, if
 22043  // any, replaces the original box, after removing glue and penalties and
 22044  // adjusting for |split_top_skip|. Mark nodes in the split-off box are used to
 22045  // set the values of |split_first_mark| and |split_bot_mark|; we use the
 22046  // fact that |split_first_mark=null| if and only if |split_bot_mark=null|.
 22047  //
 22048  // The original box becomes ``void'' if and only if it has been entirely
 22049  // extracted.  The extracted box is ``void'' if and only if the original
 22050  // box was void (or if it was, erroneously, an hlist box).
 22051  func (prg *prg) vsplit(n eightBits, h scaled) (r halfword) {
 22052  	var (
 22053  		v halfword // the box to be split
 22054  		p halfword // runs through the vlist
 22055  		q halfword // points to where the break occurs
 22056  	)
 22057  	v = *(*prg.eqtb[boxBase+int32(n)-1].hh()).rh()
 22058  	if int32(prg.curMark[splitFirstMarkCode]) != 0 {
 22059  		prg.deleteTokenRef(prg.curMark[splitFirstMarkCode])
 22060  		prg.curMark[splitFirstMarkCode] = 0
 22061  		prg.deleteTokenRef(prg.curMark[splitBotMarkCode])
 22062  		prg.curMark[splitBotMarkCode] = 0
 22063  	}
 22064  
 22065  	// Dispense with trivial cases of void or bad boxes
 22066  	if int32(v) == 0 {
 22067  		r = 0
 22068  		goto exit
 22069  	}
 22070  	if int32(*(*prg.mem[v].hh()).b0()) != vlistNode {
 22071  		{
 22072  			if int32(prg.interaction) == errorStopMode {
 22073  			}
 22074  			prg.printNl(strNumber( /* "! " */ 262))
 22075  			prg.print( /* "" */ 338)
 22076  		}
 22077  		prg.printEsc(strNumber( /* "vsplit" */ 965))
 22078  		prg.print( /* " needs a " */ 966)
 22079  		prg.printEsc(strNumber( /* "vbox" */ 967))
 22080  		// \xref[vsplit_][\.[\\vsplit needs a \\vbox]]
 22081  		{
 22082  			prg.helpPtr = 2
 22083  			prg.helpLine[1] = /* "The box you are trying to split is an \\hbox." */ 968
 22084  			prg.helpLine[0] = /* "I can't split such a box, so I'll leave it alone." */ 969
 22085  		}
 22086  		prg.error1()
 22087  		r = 0
 22088  		goto exit
 22089  	}
 22090  	q = prg.vertBreak(*(*prg.mem[int32(v)+listOffset].hh()).rh(), h, *prg.eqtb[dimenBase+splitMaxDepthCode-1].int())
 22091  
 22092  	// Look at all the marks in nodes before the break, and set the final link to |null| at the break
 22093  	p = *(*prg.mem[int32(v)+listOffset].hh()).rh()
 22094  	if int32(p) == int32(q) {
 22095  		*(*prg.mem[int32(v)+listOffset].hh()).rh() = 0
 22096  	} else {
 22097  		for true {
 22098  			if int32(*(*prg.mem[p].hh()).b0()) == markNode {
 22099  				if int32(prg.curMark[splitFirstMarkCode]) == 0 {
 22100  					prg.curMark[splitFirstMarkCode] = uint16(*prg.mem[int32(p)+1].int())
 22101  					prg.curMark[splitBotMarkCode] = prg.curMark[splitFirstMarkCode]
 22102  					*(*prg.mem[prg.curMark[splitFirstMarkCode]].hh()).lh() = uint16(int32(*(*prg.mem[prg.curMark[splitFirstMarkCode]].hh()).lh()) + 2)
 22103  				} else {
 22104  					prg.deleteTokenRef(prg.curMark[splitBotMarkCode])
 22105  					prg.curMark[splitBotMarkCode] = uint16(*prg.mem[int32(p)+1].int())
 22106  					*(*prg.mem[prg.curMark[splitBotMarkCode]].hh()).lh() = uint16(int32(*(*prg.mem[prg.curMark[splitBotMarkCode]].hh()).lh()) + 1)
 22107  				}
 22108  			}
 22109  			if int32(*(*prg.mem[p].hh()).rh()) == int32(q) {
 22110  				*(*prg.mem[p].hh()).rh() = 0
 22111  				goto done
 22112  			}
 22113  			p = *(*prg.mem[p].hh()).rh()
 22114  		}
 22115  	}
 22116  
 22117  done:
 22118  	;
 22119  	q = prg.prunePageTop(q)
 22120  	p = *(*prg.mem[int32(v)+listOffset].hh()).rh()
 22121  	prg.freeNode(v, halfword(boxNodeSize))
 22122  	if int32(q) == 0 {
 22123  		*(*prg.eqtb[boxBase+int32(n)-1].hh()).rh() = 0
 22124  	} else {
 22125  		*(*prg.eqtb[boxBase+int32(n)-1].hh()).rh() = prg.vpackage(q, scaled(0), smallNumber(additional), scaled(07777777777))
 22126  	}
 22127  	r = prg.vpackage(p, h, smallNumber(exactly), *prg.eqtb[dimenBase+splitMaxDepthCode-1].int())
 22128  
 22129  exit:
 22130  	;
 22131  	return r
 22132  }
 22133  
 22134  // 218.
 22135  
 22136  // tangle:pos tex.web:4391:3:
 22137  
 22138  // Here is a procedure that displays what \TeX\ is working on, at all levels.
 22139  func (prg *prg) printTotals() {
 22140  	prg.printScaled(prg.pageSoFar[1])
 22141  	if prg.pageSoFar[2] != 0 {
 22142  		prg.print( /* " plus " */ 312)
 22143  		prg.printScaled(prg.pageSoFar[2])
 22144  		prg.print( /* "" */ 338)
 22145  	}
 22146  	if prg.pageSoFar[3] != 0 {
 22147  		prg.print( /* " plus " */ 312)
 22148  		prg.printScaled(prg.pageSoFar[3])
 22149  		prg.print( /* "fil" */ 311)
 22150  	}
 22151  	if prg.pageSoFar[4] != 0 {
 22152  		prg.print( /* " plus " */ 312)
 22153  		prg.printScaled(prg.pageSoFar[4])
 22154  		prg.print( /* "fill" */ 978)
 22155  	}
 22156  	if prg.pageSoFar[5] != 0 {
 22157  		prg.print( /* " plus " */ 312)
 22158  		prg.printScaled(prg.pageSoFar[5])
 22159  		prg.print( /* "filll" */ 979)
 22160  	}
 22161  	if prg.pageSoFar[6] != 0 {
 22162  		prg.print( /* " minus " */ 313)
 22163  		prg.printScaled(prg.pageSoFar[6])
 22164  	}
 22165  }
 22166  
 22167  // 987.
 22168  
 22169  // tangle:pos tex.web:19313:1:
 22170  
 22171  // Here is a procedure that is called when the |page_contents| is changing
 22172  // from |empty| to |inserts_only| or |box_there|.
 22173  func (prg *prg) freezePageSpecs(s smallNumber) {
 22174  	prg.pageContents = s
 22175  	prg.pageSoFar[0] = *prg.eqtb[dimenBase+vsizeCode-1].int()
 22176  	prg.pageMaxDepth = *prg.eqtb[dimenBase+maxDepthCode-1].int()
 22177  	prg.pageSoFar[7] = 0
 22178  	prg.pageSoFar[1] = 0
 22179  	prg.pageSoFar[2] = 0
 22180  	prg.pageSoFar[3] = 0
 22181  	prg.pageSoFar[4] = 0
 22182  	prg.pageSoFar[5] = 0
 22183  	prg.pageSoFar[6] = 0
 22184  	prg.leastPageCost = 07777777777
 22185  	//  if eqtb[int_base+ tracing_pages_code].int  >0 then
 22186  	//   begin begin_diagnostic;
 22187  	//   print_nl(["%% goal height="=]987); print_scaled(page_so_far[0] );
 22188  	// [ \xref[goal height] ]
 22189  	//   print([", max depth="=]988); print_scaled(page_max_depth);
 22190  	//   end_diagnostic(false);
 22191  	//   end;  [  ]
 22192  
 22193  }
 22194  
 22195  // 992.
 22196  
 22197  // tangle:pos tex.web:19377:1:
 22198  
 22199  // At certain times box 255 is supposed to be void (i.e., |null|),
 22200  // or an insertion box is supposed to be ready to accept a vertical list.
 22201  // If not, an error message is printed, and the following subroutine
 22202  // flushes the unwanted contents, reporting them to the user.
 22203  func (prg *prg) boxError(n eightBits) {
 22204  	prg.error1()
 22205  	prg.beginDiagnostic()
 22206  	prg.printNl(strNumber( /* "The following box has been deleted:" */ 836))
 22207  	// \xref[The following...deleted]
 22208  	prg.showBox(*(*prg.eqtb[boxBase+int32(n)-1].hh()).rh())
 22209  	prg.endDiagnostic(true)
 22210  	prg.flushNodeList(*(*prg.eqtb[boxBase+int32(n)-1].hh()).rh())
 22211  	*(*prg.eqtb[boxBase+int32(n)-1].hh()).rh() = 0
 22212  }
 22213  
 22214  // 993.
 22215  
 22216  // tangle:pos tex.web:19390:1:
 22217  
 22218  // The following procedure guarantees that a given box register
 22219  // does not contain an \.[\\hbox].
 22220  func (prg *prg) ensureVbox(n eightBits) {
 22221  	var (
 22222  		p halfword // the box register contents
 22223  	)
 22224  	p = *(*prg.eqtb[boxBase+int32(n)-1].hh()).rh()
 22225  	if int32(p) != 0 {
 22226  		if int32(*(*prg.mem[p].hh()).b0()) == hlistNode {
 22227  			{
 22228  				if int32(prg.interaction) == errorStopMode {
 22229  				}
 22230  				prg.printNl(strNumber( /* "! " */ 262))
 22231  				prg.print( /* "Insertions can only be added to a vbox" */ 989)
 22232  			}
 22233  			// \xref[Insertions can only...]
 22234  			{
 22235  				prg.helpPtr = 3
 22236  				prg.helpLine[2] = /* "Tut tut: You're trying to \\insert into a" */ 990
 22237  				prg.helpLine[1] = /* "\\box register that now contains an \\hbox." */ 991
 22238  				prg.helpLine[0] = /* "Proceed, and I'll discard its present contents." */ 992
 22239  			}
 22240  			prg.boxError(n)
 22241  		}
 22242  	}
 22243  }
 22244  
 22245  // 994.
 22246  
 22247  // tangle:pos tex.web:19406:1:
 22248  
 22249  // \TeX\ is not always in vertical mode at the time |build_page|
 22250  // is called; the current mode reflects what \TeX\ should return to, after
 22251  // the contribution list has been emptied. A call on |build_page| should
 22252  // be immediately followed by `|goto big_switch|', which is \TeX's central
 22253  // control point.
 22254  // \4
 22255  // Declare the procedure called |fire_up|
 22256  func (prg *prg) fireUp(c halfword) {
 22257  	var (
 22258  		p, q, r1, s                     halfword // nodes being examined and/or changed
 22259  		prevP                           halfword // predecessor of |p|
 22260  		n/* minQuarterword..255 */ byte          // insertion box number
 22261  		wait                            bool     // should the present insertion be held over?
 22262  		saveVbadness                    int32    // saved value of |vbadness|
 22263  		saveVfuzz                       scaled   // saved value of |vfuzz|
 22264  		saveSplitTopSkip                halfword // saved value of |split_top_skip|
 22265  	)
 22266  	if int32(*(*prg.mem[prg.bestPageBreak].hh()).b0()) == penaltyNode {
 22267  		prg.geqWordDefine(halfword(intBase+outputPenaltyCode), *prg.mem[int32(prg.bestPageBreak)+1].int())
 22268  		*prg.mem[int32(prg.bestPageBreak)+1].int() = infPenalty
 22269  	} else {
 22270  		prg.geqWordDefine(halfword(intBase+outputPenaltyCode), infPenalty)
 22271  	}
 22272  	if int32(prg.curMark[botMarkCode]) != 0 {
 22273  		if int32(prg.curMark[topMarkCode]) != 0 {
 22274  			prg.deleteTokenRef(prg.curMark[topMarkCode])
 22275  		}
 22276  		prg.curMark[topMarkCode] = prg.curMark[botMarkCode]
 22277  		*(*prg.mem[prg.curMark[topMarkCode]].hh()).lh() = uint16(int32(*(*prg.mem[prg.curMark[topMarkCode]].hh()).lh()) + 1)
 22278  		prg.deleteTokenRef(prg.curMark[firstMarkCode])
 22279  		prg.curMark[firstMarkCode] = 0
 22280  	}
 22281  
 22282  	// Put the \(o)optimal current page into box 255, update |first_mark| and |bot_mark|, append insertions to their boxes, and put the remaining nodes back on the contribution list
 22283  	if int32(c) == int32(prg.bestPageBreak) {
 22284  		prg.bestPageBreak = 0
 22285  	} // |c| not yet linked in
 22286  
 22287  	// Ensure that box 255 is empty before output
 22288  	if int32(*(*prg.eqtb[boxBase+255-1].hh()).rh()) != 0 {
 22289  		{
 22290  			if int32(prg.interaction) == errorStopMode {
 22291  			}
 22292  			prg.printNl(strNumber( /* "! " */ 262))
 22293  			prg.print( /* "" */ 338)
 22294  		}
 22295  		prg.printEsc(strNumber( /* "box" */ 409))
 22296  		prg.print( /* "255 is not void" */ 1003)
 22297  		// \xref[box255][\.[\\box255 is not void]]
 22298  		{
 22299  			prg.helpPtr = 2
 22300  			prg.helpLine[1] = /* "You shouldn't use \\box255 except in \\output routines." */ 1004
 22301  			prg.helpLine[0] = /* "Proceed, and I'll discard its present contents." */ 992
 22302  		}
 22303  		prg.boxError(eightBits(255))
 22304  	}
 22305  	prg.insertPenalties = 0 // this will count the number of insertions held over
 22306  	saveSplitTopSkip = *(*prg.eqtb[glueBase+splitTopSkipCode-1].hh()).rh()
 22307  	if *prg.eqtb[intBase+holdingInsertsCode-1].int() <= 0 {
 22308  		r1 = *(*prg.mem[30000].hh()).rh()
 22309  		for int32(r1) != 30000 {
 22310  			if int32(*(*prg.mem[int32(r1)+2].hh()).lh()) != 0 {
 22311  				n = byte(int32(*(*prg.mem[r1].hh()).b1()) - minQuarterword)
 22312  				prg.ensureVbox(n)
 22313  				if int32(*(*prg.eqtb[boxBase+int32(n)-1].hh()).rh()) == 0 {
 22314  					*(*prg.eqtb[boxBase+int32(n)-1].hh()).rh() = prg.newNullBox()
 22315  				}
 22316  				p = uint16(int32(*(*prg.eqtb[boxBase+int32(n)-1].hh()).rh()) + listOffset)
 22317  				for int32(*(*prg.mem[p].hh()).rh()) != 0 {
 22318  					p = *(*prg.mem[p].hh()).rh()
 22319  				}
 22320  				*(*prg.mem[int32(r1)+2].hh()).rh() = p
 22321  			}
 22322  			r1 = *(*prg.mem[r1].hh()).rh()
 22323  		}
 22324  	}
 22325  	q = uint16(30000 - 4)
 22326  	*(*prg.mem[q].hh()).rh() = 0
 22327  	prevP = uint16(30000 - 2)
 22328  	p = *(*prg.mem[prevP].hh()).rh()
 22329  	for int32(p) != int32(prg.bestPageBreak) {
 22330  		if int32(*(*prg.mem[p].hh()).b0()) == insNode {
 22331  			if *prg.eqtb[intBase+holdingInsertsCode-1].int() <= 0 {
 22332  				r1 = *(*prg.mem[30000].hh()).rh()
 22333  				for int32(*(*prg.mem[r1].hh()).b1()) != int32(*(*prg.mem[p].hh()).b1()) {
 22334  					r1 = *(*prg.mem[r1].hh()).rh()
 22335  				}
 22336  				if int32(*(*prg.mem[int32(r1)+2].hh()).lh()) == 0 {
 22337  					wait = true
 22338  				} else {
 22339  					wait = false
 22340  					s = *(*prg.mem[int32(r1)+2].hh()).rh()
 22341  					*(*prg.mem[s].hh()).rh() = *(*prg.mem[int32(p)+4].hh()).lh()
 22342  					if int32(*(*prg.mem[int32(r1)+2].hh()).lh()) == int32(p) {
 22343  						if int32(*(*prg.mem[r1].hh()).b0()) == splitUp {
 22344  							if int32(*(*prg.mem[int32(r1)+1].hh()).lh()) == int32(p) && int32(*(*prg.mem[int32(r1)+1].hh()).rh()) != 0 {
 22345  								for int32(*(*prg.mem[s].hh()).rh()) != int32(*(*prg.mem[int32(r1)+1].hh()).rh()) {
 22346  									s = *(*prg.mem[s].hh()).rh()
 22347  								}
 22348  								*(*prg.mem[s].hh()).rh() = 0
 22349  								*(*prg.eqtb[glueBase+splitTopSkipCode-1].hh()).rh() = *(*prg.mem[int32(p)+4].hh()).rh()
 22350  								*(*prg.mem[int32(p)+4].hh()).lh() = prg.prunePageTop(*(*prg.mem[int32(r1)+1].hh()).rh())
 22351  								if int32(*(*prg.mem[int32(p)+4].hh()).lh()) != 0 {
 22352  									prg.tempPtr = prg.vpackage(*(*prg.mem[int32(p)+4].hh()).lh(), scaled(0), smallNumber(additional), scaled(07777777777))
 22353  									*prg.mem[int32(p)+heightOffset].int() = *prg.mem[int32(prg.tempPtr)+heightOffset].int() + *prg.mem[int32(prg.tempPtr)+depthOffset].int()
 22354  									prg.freeNode(prg.tempPtr, halfword(boxNodeSize))
 22355  									wait = true
 22356  								}
 22357  							}
 22358  						}
 22359  						*(*prg.mem[int32(r1)+2].hh()).lh() = 0
 22360  						n = byte(int32(*(*prg.mem[r1].hh()).b1()) - minQuarterword)
 22361  						prg.tempPtr = *(*prg.mem[int32(*(*prg.eqtb[boxBase+int32(n)-1].hh()).rh())+listOffset].hh()).rh()
 22362  						prg.freeNode(*(*prg.eqtb[boxBase+int32(n)-1].hh()).rh(), halfword(boxNodeSize))
 22363  						*(*prg.eqtb[boxBase+int32(n)-1].hh()).rh() = prg.vpackage(prg.tempPtr, scaled(0), smallNumber(additional), scaled(07777777777))
 22364  					} else {
 22365  						for int32(*(*prg.mem[s].hh()).rh()) != 0 {
 22366  							s = *(*prg.mem[s].hh()).rh()
 22367  						}
 22368  						*(*prg.mem[int32(r1)+2].hh()).rh() = s
 22369  					}
 22370  				}
 22371  
 22372  				// Either append the insertion node |p| after node |q|, and remove it from the current page, or delete |node(p)|
 22373  				*(*prg.mem[prevP].hh()).rh() = *(*prg.mem[p].hh()).rh()
 22374  				*(*prg.mem[p].hh()).rh() = 0
 22375  				if wait {
 22376  					*(*prg.mem[q].hh()).rh() = p
 22377  					q = p
 22378  					prg.insertPenalties = prg.insertPenalties + 1
 22379  				} else {
 22380  					prg.deleteGlueRef(*(*prg.mem[int32(p)+4].hh()).rh())
 22381  					prg.freeNode(p, halfword(insNodeSize))
 22382  				}
 22383  				p = prevP
 22384  			}
 22385  		} else if int32(*(*prg.mem[p].hh()).b0()) == markNode {
 22386  			if int32(prg.curMark[firstMarkCode]) == 0 {
 22387  				prg.curMark[firstMarkCode] = uint16(*prg.mem[int32(p)+1].int())
 22388  				*(*prg.mem[prg.curMark[firstMarkCode]].hh()).lh() = uint16(int32(*(*prg.mem[prg.curMark[firstMarkCode]].hh()).lh()) + 1)
 22389  			}
 22390  			if int32(prg.curMark[botMarkCode]) != 0 {
 22391  				prg.deleteTokenRef(prg.curMark[botMarkCode])
 22392  			}
 22393  			prg.curMark[botMarkCode] = uint16(*prg.mem[int32(p)+1].int())
 22394  			*(*prg.mem[prg.curMark[botMarkCode]].hh()).lh() = uint16(int32(*(*prg.mem[prg.curMark[botMarkCode]].hh()).lh()) + 1)
 22395  		}
 22396  		prevP = p
 22397  		p = *(*prg.mem[prevP].hh()).rh()
 22398  	}
 22399  	*(*prg.eqtb[glueBase+splitTopSkipCode-1].hh()).rh() = saveSplitTopSkip
 22400  
 22401  	// Break the current page at node |p|, put it in box~255, and put the remaining nodes on the contribution list
 22402  	if int32(p) != 0 {
 22403  		if int32(*(*prg.mem[30000-1].hh()).rh()) == 0 {
 22404  			if int32(prg.nestPtr) == 0 {
 22405  				prg.curList.tailField = prg.pageTail
 22406  			} else {
 22407  				prg.nest[0].tailField = prg.pageTail
 22408  			}
 22409  		}
 22410  		*(*prg.mem[prg.pageTail].hh()).rh() = *(*prg.mem[30000-1].hh()).rh()
 22411  		*(*prg.mem[30000-1].hh()).rh() = p
 22412  		*(*prg.mem[prevP].hh()).rh() = 0
 22413  	}
 22414  	saveVbadness = *prg.eqtb[intBase+vbadnessCode-1].int()
 22415  	*prg.eqtb[intBase+vbadnessCode-1].int() = infBad
 22416  	saveVfuzz = *prg.eqtb[dimenBase+vfuzzCode-1].int()
 22417  	*prg.eqtb[dimenBase+vfuzzCode-1].int() = 07777777777 // inhibit error messages
 22418  	*(*prg.eqtb[boxBase+255-1].hh()).rh() = prg.vpackage(*(*prg.mem[30000-2].hh()).rh(), prg.bestSize, smallNumber(exactly), prg.pageMaxDepth)
 22419  	*prg.eqtb[intBase+vbadnessCode-1].int() = saveVbadness
 22420  	*prg.eqtb[dimenBase+vfuzzCode-1].int() = saveVfuzz
 22421  	if int32(prg.lastGlue) != 65535 {
 22422  		prg.deleteGlueRef(prg.lastGlue)
 22423  	}
 22424  
 22425  	// Start a new current page
 22426  	prg.pageContents = byte(empty)
 22427  	prg.pageTail = uint16(30000 - 2)
 22428  	*(*prg.mem[30000-2].hh()).rh() = 0
 22429  
 22430  	prg.lastGlue = 65535
 22431  	prg.lastPenalty = 0
 22432  	prg.lastKern = 0
 22433  	prg.pageSoFar[7] = 0
 22434  	prg.pageMaxDepth = 0 // this sets |last_glue:=max_halfword|
 22435  	if int32(q) != 30000-4 {
 22436  		*(*prg.mem[30000-2].hh()).rh() = *(*prg.mem[30000-4].hh()).rh()
 22437  		prg.pageTail = q
 22438  	}
 22439  
 22440  	// Delete \(t)the page-insertion nodes
 22441  	r1 = *(*prg.mem[30000].hh()).rh()
 22442  	for int32(r1) != 30000 {
 22443  		q = *(*prg.mem[r1].hh()).rh()
 22444  		prg.freeNode(r1, halfword(pageInsNodeSize))
 22445  		r1 = q
 22446  	}
 22447  	*(*prg.mem[30000].hh()).rh() = 30000
 22448  	if int32(prg.curMark[topMarkCode]) != 0 && int32(prg.curMark[firstMarkCode]) == 0 {
 22449  		prg.curMark[firstMarkCode] = prg.curMark[topMarkCode]
 22450  		*(*prg.mem[prg.curMark[topMarkCode]].hh()).lh() = uint16(int32(*(*prg.mem[prg.curMark[topMarkCode]].hh()).lh()) + 1)
 22451  	}
 22452  	if int32(*(*prg.eqtb[outputRoutineLoc-1].hh()).rh()) != 0 {
 22453  		if prg.deadCycles >= *prg.eqtb[intBase+maxDeadCyclesCode-1].int() {
 22454  			{
 22455  				if int32(prg.interaction) == errorStopMode {
 22456  				}
 22457  				prg.printNl(strNumber( /* "! " */ 262))
 22458  				prg.print( /* "Output loop---" */ 1005)
 22459  			}
 22460  			prg.printInt(prg.deadCycles)
 22461  			// \xref[Output loop...]
 22462  			prg.print( /* " consecutive dead cycles" */ 1006)
 22463  			{
 22464  				prg.helpPtr = 3
 22465  				prg.helpLine[2] = /* "I've concluded that your \\output is awry; it never does a" */ 1007
 22466  				prg.helpLine[1] = /* "\\shipout, so I'm shipping \\box255 out myself. Next time" */ 1008
 22467  				prg.helpLine[0] = /* "increase \\maxdeadcycles if you want me to be more patient!" */ 1009
 22468  			}
 22469  			prg.error1()
 22470  		} else {
 22471  			// Fire up the user's output routine and |return|
 22472  			prg.outputActive = true
 22473  			prg.deadCycles = prg.deadCycles + 1
 22474  			prg.pushNest()
 22475  			prg.curList.modeField = int16(-vmode)
 22476  			*prg.curList.auxField.int() = -65536000
 22477  			prg.curList.mlField = -prg.line
 22478  			prg.beginTokenList(*(*prg.eqtb[outputRoutineLoc-1].hh()).rh(), quarterword(outputText))
 22479  			prg.newSaveLevel(groupCode(outputGroup))
 22480  			prg.normalParagraph()
 22481  			prg.scanLeftBrace()
 22482  
 22483  			goto exit
 22484  		}
 22485  	}
 22486  
 22487  	// Perform the default output routine
 22488  	{
 22489  		if int32(*(*prg.mem[30000-2].hh()).rh()) != 0 {
 22490  			if int32(*(*prg.mem[30000-1].hh()).rh()) == 0 {
 22491  				if int32(prg.nestPtr) == 0 {
 22492  					prg.curList.tailField = prg.pageTail
 22493  				} else {
 22494  					prg.nest[0].tailField = prg.pageTail
 22495  				}
 22496  			} else {
 22497  				*(*prg.mem[prg.pageTail].hh()).rh() = *(*prg.mem[30000-1].hh()).rh()
 22498  			}
 22499  			*(*prg.mem[30000-1].hh()).rh() = *(*prg.mem[30000-2].hh()).rh()
 22500  			*(*prg.mem[30000-2].hh()).rh() = 0
 22501  			prg.pageTail = uint16(30000 - 2)
 22502  		}
 22503  		prg.shipOut(*(*prg.eqtb[boxBase+255-1].hh()).rh())
 22504  		*(*prg.eqtb[boxBase+255-1].hh()).rh() = 0
 22505  	}
 22506  
 22507  exit:
 22508  } // \2
 22509  
 22510  func (prg *prg) buildPage() {
 22511  	var (
 22512  		p                               halfword // the node being appended
 22513  		q, r1                           halfword // nodes being examined
 22514  		b, c                            int32    // badness and cost of current page
 22515  		pi                              int32    // penalty to be added to the badness
 22516  		n/* minQuarterword..255 */ byte          // insertion box number
 22517  		delta, h, w                     scaled   // sizes used for insertion calculations
 22518  	)
 22519  	if int32(*(*prg.mem[30000-1].hh()).rh()) == 0 || prg.outputActive {
 22520  		goto exit
 22521  	}
 22522  	for {
 22523  	continue1:
 22524  		p = *(*prg.mem[30000-1].hh()).rh()
 22525  
 22526  		// Update the values of |last_glue|, |last_penalty|, and |last_kern|
 22527  		if int32(prg.lastGlue) != 65535 {
 22528  			prg.deleteGlueRef(prg.lastGlue)
 22529  		}
 22530  		prg.lastPenalty = 0
 22531  		prg.lastKern = 0
 22532  		if int32(*(*prg.mem[p].hh()).b0()) == glueNode {
 22533  			prg.lastGlue = *(*prg.mem[int32(p)+1].hh()).lh()
 22534  			*(*prg.mem[prg.lastGlue].hh()).rh() = uint16(int32(*(*prg.mem[prg.lastGlue].hh()).rh()) + 1)
 22535  		} else {
 22536  			prg.lastGlue = 65535
 22537  			if int32(*(*prg.mem[p].hh()).b0()) == penaltyNode {
 22538  				prg.lastPenalty = *prg.mem[int32(p)+1].int()
 22539  			} else if int32(*(*prg.mem[p].hh()).b0()) == kernNode {
 22540  				prg.lastKern = *prg.mem[int32(p)+widthOffset].int()
 22541  			}
 22542  		}
 22543  
 22544  		// Move node |p| to the current page; if it is time for a page break, put the nodes following the break back onto the contribution list, and |return| to the user's output routine if there is one
 22545  
 22546  		// If the current page is empty and node |p| is to be deleted, |goto done1|; otherwise use node |p| to update the state of the current page; if this node is an insertion, |goto contribute|; otherwise if this node is not a legal breakpoint, |goto contribute| or |update_heights|; otherwise set |pi| to the penalty associated with this breakpoint
 22547  		switch *(*prg.mem[p].hh()).b0() {
 22548  		case hlistNode, vlistNode, ruleNode:
 22549  			if int32(prg.pageContents) < boxThere {
 22550  				if int32(prg.pageContents) == empty {
 22551  					prg.freezePageSpecs(smallNumber(boxThere))
 22552  				} else {
 22553  					prg.pageContents = byte(boxThere)
 22554  				}
 22555  				q = prg.newSkipParam(smallNumber(topSkipCode)) // now |temp_ptr=glue_ptr(q)|
 22556  				if *prg.mem[int32(prg.tempPtr)+widthOffset].int() > *prg.mem[int32(p)+heightOffset].int() {
 22557  					*prg.mem[int32(prg.tempPtr)+widthOffset].int() = *prg.mem[int32(prg.tempPtr)+widthOffset].int() - *prg.mem[int32(p)+heightOffset].int()
 22558  				} else {
 22559  					*prg.mem[int32(prg.tempPtr)+widthOffset].int() = 0
 22560  				}
 22561  				*(*prg.mem[q].hh()).rh() = p
 22562  				*(*prg.mem[30000-1].hh()).rh() = q
 22563  				goto continue1
 22564  			} else {
 22565  				// Prepare to move a box or rule node to the current page, then |goto contribute|
 22566  				prg.pageSoFar[1] = prg.pageSoFar[1] + prg.pageSoFar[7] + *prg.mem[int32(p)+heightOffset].int()
 22567  				prg.pageSoFar[7] = *prg.mem[int32(p)+depthOffset].int()
 22568  
 22569  				goto contribute
 22570  			}
 22571  
 22572  		case whatsitNode:
 22573  			// Prepare to move whatsit |p| to the current page, then |goto contribute|
 22574  
 22575  			// Prepare to move whatsit |p| to the current page, then |goto contribute|
 22576  			goto contribute
 22577  
 22578  		case glueNode:
 22579  			if int32(prg.pageContents) < boxThere {
 22580  				goto done1
 22581  			} else if int32(*(*prg.mem[prg.pageTail].hh()).b0()) < mathNode {
 22582  				pi = 0
 22583  			} else {
 22584  				goto updateHeights
 22585  			}
 22586  		case kernNode:
 22587  			if int32(prg.pageContents) < boxThere {
 22588  				goto done1
 22589  			} else if int32(*(*prg.mem[p].hh()).rh()) == 0 {
 22590  				goto exit
 22591  			} else if int32(*(*prg.mem[*(*prg.mem[p].hh()).rh()].hh()).b0()) == glueNode {
 22592  				pi = 0
 22593  			} else {
 22594  				goto updateHeights
 22595  			}
 22596  		case penaltyNode:
 22597  			if int32(prg.pageContents) < boxThere {
 22598  				goto done1
 22599  			} else {
 22600  				pi = *prg.mem[int32(p)+1].int()
 22601  			}
 22602  		case markNode:
 22603  			goto contribute
 22604  		case insNode:
 22605  			// Append an insertion to the current page and |goto contribute|
 22606  			if int32(prg.pageContents) == empty {
 22607  				prg.freezePageSpecs(smallNumber(insertsOnly))
 22608  			}
 22609  			n = *(*prg.mem[p].hh()).b1()
 22610  			r1 = 30000
 22611  			for int32(n) >= int32(*(*prg.mem[*(*prg.mem[r1].hh()).rh()].hh()).b1()) {
 22612  				r1 = *(*prg.mem[r1].hh()).rh()
 22613  			}
 22614  			n = byte(int32(n) - minQuarterword)
 22615  			if int32(*(*prg.mem[r1].hh()).b1()) != int32(n)+minQuarterword {
 22616  				q = prg.getNode(pageInsNodeSize)
 22617  				*(*prg.mem[q].hh()).rh() = *(*prg.mem[r1].hh()).rh()
 22618  				*(*prg.mem[r1].hh()).rh() = q
 22619  				r1 = q
 22620  				*(*prg.mem[r1].hh()).b1() = byte(int32(n) + minQuarterword)
 22621  				*(*prg.mem[r1].hh()).b0() = byte(inserting)
 22622  				prg.ensureVbox(n)
 22623  				if int32(*(*prg.eqtb[boxBase+int32(n)-1].hh()).rh()) == 0 {
 22624  					*prg.mem[int32(r1)+heightOffset].int() = 0
 22625  				} else {
 22626  					*prg.mem[int32(r1)+heightOffset].int() = *prg.mem[int32(*(*prg.eqtb[boxBase+int32(n)-1].hh()).rh())+heightOffset].int() + *prg.mem[int32(*(*prg.eqtb[boxBase+int32(n)-1].hh()).rh())+depthOffset].int()
 22627  				}
 22628  				*(*prg.mem[int32(r1)+2].hh()).lh() = 0
 22629  
 22630  				q = *(*prg.eqtb[skipBase+int32(n)-1].hh()).rh()
 22631  				if *prg.eqtb[countBase+int32(n)-1].int() == 1000 {
 22632  					h = *prg.mem[int32(r1)+heightOffset].int()
 22633  				} else {
 22634  					h = prg.xOverN(*prg.mem[int32(r1)+heightOffset].int(), 1000) * *prg.eqtb[countBase+int32(n)-1].int()
 22635  				}
 22636  				prg.pageSoFar[0] = prg.pageSoFar[0] - h - *prg.mem[int32(q)+widthOffset].int()
 22637  
 22638  				prg.pageSoFar[2+int32(*(*prg.mem[q].hh()).b0())] = prg.pageSoFar[2+int32(*(*prg.mem[q].hh()).b0())] + *prg.mem[int32(q)+2].int()
 22639  
 22640  				prg.pageSoFar[6] = prg.pageSoFar[6] + *prg.mem[int32(q)+3].int()
 22641  				if int32(*(*prg.mem[q].hh()).b1()) != normal && *prg.mem[int32(q)+3].int() != 0 {
 22642  					{
 22643  						if int32(prg.interaction) == errorStopMode {
 22644  						}
 22645  						prg.printNl(strNumber( /* "! " */ 262))
 22646  						prg.print( /* "Infinite glue shrinkage inserted from " */ 998)
 22647  					}
 22648  					prg.printEsc(strNumber( /* "skip" */ 395))
 22649  					// \xref[Infinite glue shrinkage...]
 22650  					prg.printInt(int32(n))
 22651  					{
 22652  						prg.helpPtr = 3
 22653  						prg.helpLine[2] = /* "The correction glue for page breaking with insertions" */ 999
 22654  						prg.helpLine[1] = /* "must have finite shrinkability. But you may proceed," */ 1000
 22655  						prg.helpLine[0] = /* "since the offensive shrinkability has been made finite." */ 922
 22656  					}
 22657  					prg.error1()
 22658  				}
 22659  			}
 22660  			if int32(*(*prg.mem[r1].hh()).b0()) == splitUp {
 22661  				prg.insertPenalties = prg.insertPenalties + *prg.mem[int32(p)+1].int()
 22662  			} else {
 22663  				*(*prg.mem[int32(r1)+2].hh()).rh() = p
 22664  				delta = prg.pageSoFar[0] - prg.pageSoFar[1] - prg.pageSoFar[7] + prg.pageSoFar[6]
 22665  				// this much room is left if we shrink the maximum
 22666  				if *prg.eqtb[countBase+int32(n)-1].int() == 1000 {
 22667  					h = *prg.mem[int32(p)+heightOffset].int()
 22668  				} else {
 22669  					h = prg.xOverN(*prg.mem[int32(p)+heightOffset].int(), 1000) * *prg.eqtb[countBase+int32(n)-1].int()
 22670  				} // this much room is needed
 22671  				if (h <= 0 || h <= delta) && *prg.mem[int32(p)+heightOffset].int()+*prg.mem[int32(r1)+heightOffset].int() <= *prg.eqtb[scaledBase+int32(n)-1].int() {
 22672  					prg.pageSoFar[0] = prg.pageSoFar[0] - h
 22673  					*prg.mem[int32(r1)+heightOffset].int() = *prg.mem[int32(r1)+heightOffset].int() + *prg.mem[int32(p)+heightOffset].int()
 22674  				} else {
 22675  					// Find the best way to split the insertion, and change |type(r)| to |split_up|
 22676  					if *prg.eqtb[countBase+int32(n)-1].int() <= 0 {
 22677  						w = 07777777777
 22678  					} else {
 22679  						w = prg.pageSoFar[0] - prg.pageSoFar[1] - prg.pageSoFar[7]
 22680  						if *prg.eqtb[countBase+int32(n)-1].int() != 1000 {
 22681  							w = prg.xOverN(w, *prg.eqtb[countBase+int32(n)-1].int()) * 1000
 22682  						}
 22683  					}
 22684  					if w > *prg.eqtb[scaledBase+int32(n)-1].int()-*prg.mem[int32(r1)+heightOffset].int() {
 22685  						w = *prg.eqtb[scaledBase+int32(n)-1].int() - *prg.mem[int32(r1)+heightOffset].int()
 22686  					}
 22687  					q = prg.vertBreak(*(*prg.mem[int32(p)+4].hh()).lh(), w, *prg.mem[int32(p)+depthOffset].int())
 22688  					*prg.mem[int32(r1)+heightOffset].int() = *prg.mem[int32(r1)+heightOffset].int() + prg.bestHeightPlusDepth
 22689  					//  if eqtb[int_base+ tracing_pages_code].int  >0 then
 22690  					// [ Display the insertion split cost ]
 22691  					// begin begin_diagnostic; print_nl(["% split"=]1001); print_int(n);
 22692  					// [ \xref[split] ]
 22693  					// print([" to "=]1002); print_scaled(w);
 22694  					// print_char([","=]44); print_scaled(best_height_plus_depth);
 22695  					//
 22696  					// print([" p="=]931);
 22697  					// if q=0   then print_int(eject_penalty)
 22698  					// else if  mem[ q].hh.b0 =penalty_node then print_int( mem[ q+1].int )
 22699  					// else print_char(["0"=]48);
 22700  					// end_diagnostic(false);
 22701  					// end
 22702  					//
 22703  					// ; [  ]
 22704  
 22705  					if *prg.eqtb[countBase+int32(n)-1].int() != 1000 {
 22706  						prg.bestHeightPlusDepth = prg.xOverN(prg.bestHeightPlusDepth, 1000) * *prg.eqtb[countBase+int32(n)-1].int()
 22707  					}
 22708  					prg.pageSoFar[0] = prg.pageSoFar[0] - prg.bestHeightPlusDepth
 22709  					*(*prg.mem[r1].hh()).b0() = byte(splitUp)
 22710  					*(*prg.mem[int32(r1)+1].hh()).rh() = q
 22711  					*(*prg.mem[int32(r1)+1].hh()).lh() = p
 22712  					if int32(q) == 0 {
 22713  						prg.insertPenalties = prg.insertPenalties + ejectPenalty
 22714  					} else if int32(*(*prg.mem[q].hh()).b0()) == penaltyNode {
 22715  						prg.insertPenalties = prg.insertPenalties + *prg.mem[int32(q)+1].int()
 22716  					}
 22717  				}
 22718  			}
 22719  
 22720  			goto contribute
 22721  
 22722  		default:
 22723  			prg.confusion(strNumber( /* "page" */ 993))
 22724  			// \xref[this can't happen page][\quad page]
 22725  		}
 22726  
 22727  		// Check if node |p| is a new champion breakpoint; then \(if)if it is time for a page break, prepare for output, and either fire up the user's output routine and |return| or ship out the page and |goto done|
 22728  		if pi < infPenalty {
 22729  			if prg.pageSoFar[1] < prg.pageSoFar[0] {
 22730  				if prg.pageSoFar[3] != 0 || prg.pageSoFar[4] != 0 || prg.pageSoFar[5] != 0 {
 22731  					b = 0
 22732  				} else {
 22733  					b = int32(prg.badness(prg.pageSoFar[0]-prg.pageSoFar[1], prg.pageSoFar[2]))
 22734  				}
 22735  			} else if prg.pageSoFar[1]-prg.pageSoFar[0] > prg.pageSoFar[6] {
 22736  				b = 07777777777
 22737  			} else {
 22738  				b = int32(prg.badness(prg.pageSoFar[1]-prg.pageSoFar[0], prg.pageSoFar[6]))
 22739  			}
 22740  			if b < 07777777777 {
 22741  				if pi <= ejectPenalty {
 22742  					c = pi
 22743  				} else if b < infBad {
 22744  					c = b + pi + prg.insertPenalties
 22745  				} else {
 22746  					c = 100000
 22747  				}
 22748  			} else {
 22749  				c = b
 22750  			}
 22751  			if prg.insertPenalties >= 10000 {
 22752  				c = 07777777777
 22753  			}
 22754  			//  if eqtb[int_base+ tracing_pages_code].int  >0 then
 22755  			// [ Display the page break cost ]
 22756  			// begin begin_diagnostic; print_nl(["%"=]37);
 22757  			// print([" t="=]927); print_totals;
 22758  			//
 22759  			// print([" g="=]996); print_scaled(page_so_far[0] );
 22760  			//
 22761  			// print([" b="=]930);
 22762  			// if b=[07777777777=]1073741823  then print_char(["*"=]42) else print_int(b);
 22763  			// [ \xref[*\relax] ]
 22764  			// print([" p="=]931); print_int(pi);
 22765  			// print([" c="=]997);
 22766  			// if c=[07777777777=]1073741823  then print_char(["*"=]42) else print_int(c);
 22767  			// if c<=least_page_cost then print_char(["#"=]35);
 22768  			// end_diagnostic(false);
 22769  			// end
 22770  			//
 22771  			// ; [  ]
 22772  
 22773  			if c <= prg.leastPageCost {
 22774  				prg.bestPageBreak = p
 22775  				prg.bestSize = prg.pageSoFar[0]
 22776  				prg.leastPageCost = c
 22777  				r1 = *(*prg.mem[30000].hh()).rh()
 22778  				for int32(r1) != 30000 {
 22779  					*(*prg.mem[int32(r1)+2].hh()).lh() = *(*prg.mem[int32(r1)+2].hh()).rh()
 22780  					r1 = *(*prg.mem[r1].hh()).rh()
 22781  				}
 22782  			}
 22783  			if c == 07777777777 || pi <= ejectPenalty {
 22784  				prg.fireUp(p) // output the current page at the best place
 22785  				if prg.outputActive {
 22786  					goto exit
 22787  				} // user's output routine will act
 22788  				// user's output routine will act
 22789  				goto done // the page has been shipped out by default output routine
 22790  			}
 22791  		}
 22792  		if int32(*(*prg.mem[p].hh()).b0()) < glueNode || int32(*(*prg.mem[p].hh()).b0()) > kernNode {
 22793  			goto contribute
 22794  		}
 22795  
 22796  	updateHeights:
 22797  		if int32(*(*prg.mem[p].hh()).b0()) == kernNode {
 22798  			q = p
 22799  		} else {
 22800  			q = *(*prg.mem[int32(p)+1].hh()).lh()
 22801  			prg.pageSoFar[2+int32(*(*prg.mem[q].hh()).b0())] = prg.pageSoFar[2+int32(*(*prg.mem[q].hh()).b0())] + *prg.mem[int32(q)+2].int()
 22802  
 22803  			prg.pageSoFar[6] = prg.pageSoFar[6] + *prg.mem[int32(q)+3].int()
 22804  			if int32(*(*prg.mem[q].hh()).b1()) != normal && *prg.mem[int32(q)+3].int() != 0 {
 22805  				{
 22806  					if int32(prg.interaction) == errorStopMode {
 22807  					}
 22808  					prg.printNl(strNumber( /* "! " */ 262))
 22809  					prg.print( /* "Infinite glue shrinkage found on current page" */ 994)
 22810  				}
 22811  
 22812  				// \xref[Infinite glue shrinkage...]
 22813  				{
 22814  					prg.helpPtr = 4
 22815  					prg.helpLine[3] = /* "The page about to be output contains some infinitely" */ 995
 22816  					prg.helpLine[2] = /* "shrinkable glue, e.g., `\\vss' or `\\vskip 0pt minus 1fil'." */ 963
 22817  					prg.helpLine[1] = /* "Such glue doesn't belong there; but you can safely proceed," */ 964
 22818  					prg.helpLine[0] = /* "since the offensive shrinkability has been made finite." */ 922
 22819  				}
 22820  				prg.error1()
 22821  				r1 = prg.newSpec(q)
 22822  				*(*prg.mem[r1].hh()).b1() = byte(normal)
 22823  				prg.deleteGlueRef(q)
 22824  				*(*prg.mem[int32(p)+1].hh()).lh() = r1
 22825  				q = r1
 22826  			}
 22827  		}
 22828  		prg.pageSoFar[1] = prg.pageSoFar[1] + prg.pageSoFar[7] + *prg.mem[int32(q)+widthOffset].int()
 22829  		prg.pageSoFar[7] = 0
 22830  
 22831  	contribute:
 22832  		if prg.pageSoFar[7] > prg.pageMaxDepth {
 22833  			prg.pageSoFar[1] = prg.pageSoFar[1] + prg.pageSoFar[7] - prg.pageMaxDepth
 22834  
 22835  			prg.pageSoFar[7] = prg.pageMaxDepth
 22836  		}
 22837  
 22838  		// Link node |p| into the current page and |goto done|
 22839  		*(*prg.mem[prg.pageTail].hh()).rh() = p
 22840  		prg.pageTail = p
 22841  		*(*prg.mem[30000-1].hh()).rh() = *(*prg.mem[p].hh()).rh()
 22842  		*(*prg.mem[p].hh()).rh() = 0
 22843  		goto done
 22844  
 22845  	done1:
 22846  		*(*prg.mem[30000-1].hh()).rh() = *(*prg.mem[p].hh()).rh()
 22847  		*(*prg.mem[p].hh()).rh() = 0
 22848  		prg.flushNodeList(p)
 22849  
 22850  	done:
 22851  		;
 22852  		if int32(*(*prg.mem[30000-1].hh()).rh()) == 0 {
 22853  			break
 22854  		}
 22855  	}
 22856  
 22857  	// Make the contribution list empty by setting its tail to |contrib_head|
 22858  	if int32(prg.nestPtr) == 0 {
 22859  		prg.curList.tailField = uint16(30000 - 1)
 22860  	} else {
 22861  		prg.nest[0].tailField = uint16(30000 - 1)
 22862  	}
 22863  
 22864  exit:
 22865  }
 22866  
 22867  // 1029. \[46] The chief executive
 22868  
 22869  // tangle:pos tex.web:19977:26:
 22870  
 22871  // We come now to the |main_control| routine, which contains the master
 22872  // switch that causes all the various pieces of \TeX\ to do their things,
 22873  // in the right order.
 22874  //
 22875  // In a sense, this is the grand climax of the program: It applies all the
 22876  // tools that we have worked so hard to construct. In another sense, this is
 22877  // the messiest part of the program: It necessarily refers to other pieces
 22878  // of code all over the place, so that a person can't fully understand what is
 22879  // going on without paging back and forth to be reminded of conventions that
 22880  // are defined elsewhere. We are now at the hub of the web, the central nervous
 22881  // system that touches most of the other parts and ties them together.
 22882  // \xref[brain]
 22883  //
 22884  // The structure of |main_control| itself is quite simple. There's a label
 22885  // called |big_switch|, at which point the next token of input is fetched
 22886  // using |get_x_token|. Then the program branches at high speed into one of
 22887  // about 100 possible directions, based on the value of the current
 22888  // mode and the newly fetched command code; the sum |abs(mode)+cur_cmd|
 22889  // indicates what to do next. For example, the case `|vmode+letter|' arises
 22890  // when a letter occurs in vertical mode (or internal vertical mode); this
 22891  // case leads to instructions that initialize a new paragraph and enter
 22892  // horizontal mode.
 22893  //
 22894  // The big |case| statement that contains this multiway switch has been labeled
 22895  // |reswitch|, so that the program can |goto reswitch| when the next token
 22896  // has already been fetched. Most of the cases are quite short; they call
 22897  // an ``action procedure'' that does the work for that case, and then they
 22898  // either |goto reswitch| or they ``fall through'' to the end of the |case|
 22899  // statement, which returns control back to |big_switch|. Thus, |main_control|
 22900  // is not an extremely large procedure, in spite of the multiplicity of things
 22901  // it must do; it is small enough to be handled by \PASCAL\ compilers that put
 22902  // severe restrictions on procedure size.
 22903  //  \xref[action procedure]
 22904  //
 22905  // One case is singled out for special treatment, because it accounts for most
 22906  // of \TeX's activities in typical applications. The process of reading simple
 22907  // text and converting it into |char_node| records, while looking for ligatures
 22908  // and kerns, is part of \TeX's ``inner loop''; the whole program runs
 22909  // efficiently when its inner loop is fast, so this part has been written
 22910  // with particular care.
 22911  
 22912  // 1030.
 22913  
 22914  // tangle:pos tex.web:20017:22:
 22915  
 22916  // We shall concentrate first on the inner loop of |main_control|, deferring
 22917  // consideration of the other cases until later.
 22918  // \xref[inner loop]
 22919  // \4
 22920  // Declare action procedures for use by |main_control|
 22921  func (prg *prg) appSpace() { // handle spaces when |space_factor<>1000|
 22922  	var (
 22923  		q halfword // glue node
 22924  	)
 22925  	if int32(*(*prg.curList.auxField.hh()).lh()) >= 2000 && int32(*(*prg.eqtb[glueBase+xspaceSkipCode-1].hh()).rh()) != memBot {
 22926  		q = prg.newParamGlue(smallNumber(xspaceSkipCode))
 22927  	} else {
 22928  		if int32(*(*prg.eqtb[glueBase+spaceSkipCode-1].hh()).rh()) != memBot {
 22929  			prg.mainP = *(*prg.eqtb[glueBase+spaceSkipCode-1].hh()).rh()
 22930  		} else {
 22931  			// Find the glue specification...
 22932  			prg.mainP = prg.fontGlue[*(*prg.eqtb[curFontLoc-1].hh()).rh()]
 22933  			if int32(prg.mainP) == 0 {
 22934  				prg.mainP = prg.newSpec(halfword(memBot))
 22935  				prg.mainK = uint16(prg.paramBase[*(*prg.eqtb[curFontLoc-1].hh()).rh()] + spaceCode)
 22936  				*prg.mem[int32(prg.mainP)+widthOffset].int() = *prg.fontInfo[prg.mainK].int() // that's |space(cur_font)|
 22937  				*prg.mem[int32(prg.mainP)+2].int() = *prg.fontInfo[int32(prg.mainK)+1].int()  // and |space_stretch(cur_font)|
 22938  				*prg.mem[int32(prg.mainP)+3].int() = *prg.fontInfo[int32(prg.mainK)+2].int()  // and |space_shrink(cur_font)|
 22939  				prg.fontGlue[*(*prg.eqtb[curFontLoc-1].hh()).rh()] = prg.mainP
 22940  			}
 22941  		}
 22942  		prg.mainP = prg.newSpec(prg.mainP)
 22943  
 22944  		// Modify the glue specification in |main_p| according to the space factor
 22945  		if int32(*(*prg.curList.auxField.hh()).lh()) >= 2000 {
 22946  			*prg.mem[int32(prg.mainP)+widthOffset].int() = *prg.mem[int32(prg.mainP)+widthOffset].int() + *prg.fontInfo[extraSpaceCode+prg.paramBase[*(*prg.eqtb[curFontLoc-1].hh()).rh()]].int()
 22947  		}
 22948  		*prg.mem[int32(prg.mainP)+2].int() = prg.xnOverD(*prg.mem[int32(prg.mainP)+2].int(), int32(*(*prg.curList.auxField.hh()).lh()), 1000)
 22949  		*prg.mem[int32(prg.mainP)+3].int() = prg.xnOverD(*prg.mem[int32(prg.mainP)+3].int(), 1000, int32(*(*prg.curList.auxField.hh()).lh()))
 22950  		q = prg.newGlue(prg.mainP)
 22951  		*(*prg.mem[prg.mainP].hh()).rh() = 0
 22952  	}
 22953  	*(*prg.mem[prg.curList.tailField].hh()).rh() = q
 22954  	prg.curList.tailField = q
 22955  }
 22956  
 22957  func (prg *prg) insertDollarSign() {
 22958  	prg.backInput()
 22959  	prg.curTok = uint16(mathShiftToken + '$')
 22960  	{
 22961  		if int32(prg.interaction) == errorStopMode {
 22962  		}
 22963  		prg.printNl(strNumber( /* "! " */ 262))
 22964  		prg.print( /* "Missing $ inserted" */ 1017)
 22965  	}
 22966  	// \xref[Missing \$ inserted]
 22967  	{
 22968  		prg.helpPtr = 2
 22969  		prg.helpLine[1] = /* "I've inserted a begin-math/end-math symbol since I think" */ 1018
 22970  		prg.helpLine[0] = /* "you left one out. Proceed, with fingers crossed." */ 1019
 22971  	}
 22972  	prg.insError()
 22973  }
 22974  
 22975  func (prg *prg) youCant() {
 22976  	{
 22977  		if int32(prg.interaction) == errorStopMode {
 22978  		}
 22979  		prg.printNl(strNumber( /* "! " */ 262))
 22980  		prg.print( /* "You can't use `" */ 685)
 22981  	}
 22982  	// \xref[You can't use x in y mode]
 22983  	prg.printCmdChr(prg.curCmd, prg.curChr)
 22984  	prg.print( /* "' in " */ 1020)
 22985  	prg.printMode(int32(prg.curList.modeField))
 22986  }
 22987  
 22988  func (prg *prg) reportIllegalCase() {
 22989  	prg.youCant()
 22990  	{
 22991  		prg.helpPtr = 4
 22992  		prg.helpLine[3] = /* "Sorry, but I'm not programmed to handle this case;" */ 1021
 22993  		prg.helpLine[2] = /* "I'll just pretend that you didn't ask for it." */ 1022
 22994  		prg.helpLine[1] = /* "If you're in the wrong mode, you might be able to" */ 1023
 22995  		prg.helpLine[0] = /* "return to the right one by typing `I]' or `I$' or `I\\par'." */ 1024
 22996  	}
 22997  
 22998  	prg.error1()
 22999  }
 23000  
 23001  func (prg *prg) privileged() (r bool) {
 23002  	if int32(prg.curList.modeField) > 0 {
 23003  		r = true
 23004  	} else {
 23005  		prg.reportIllegalCase()
 23006  		r = false
 23007  	}
 23008  	return r
 23009  }
 23010  
 23011  func (prg *prg) itsAllOver() (r bool) {
 23012  	if prg.privileged() {
 23013  		if 30000-2 == int32(prg.pageTail) && int32(prg.curList.headField) == int32(prg.curList.tailField) && prg.deadCycles == 0 {
 23014  			r = true
 23015  			goto exit
 23016  		}
 23017  		prg.backInput() // we will try to end again after ejecting residual material
 23018  		{
 23019  			*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newNullBox()
 23020  			prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 23021  		}
 23022  		*prg.mem[int32(prg.curList.tailField)+widthOffset].int() = *prg.eqtb[dimenBase+hsizeCode-1].int()
 23023  		{
 23024  			*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newGlue(halfword(memBot + glueSpecSize + glueSpecSize))
 23025  			prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 23026  		}
 23027  		{
 23028  			*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newPenalty(-010000000000)
 23029  			prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 23030  		}
 23031  
 23032  		prg.buildPage() // append \.[\\hbox to \\hsize\[\]\\vfill\\penalty-'10000000000]
 23033  	}
 23034  	r = false
 23035  
 23036  exit:
 23037  	;
 23038  	return r
 23039  }
 23040  
 23041  func (prg *prg) appendGlue() {
 23042  	var (
 23043  		s smallNumber // modifier of skip command
 23044  	)
 23045  	s = byte(prg.curChr)
 23046  	switch s {
 23047  	case filCode:
 23048  		prg.curVal = memBot + glueSpecSize
 23049  	case fillCode:
 23050  		prg.curVal = memBot + glueSpecSize + glueSpecSize
 23051  	case ssCode:
 23052  		prg.curVal = memBot + glueSpecSize + glueSpecSize + glueSpecSize
 23053  	case filNegCode:
 23054  		prg.curVal = memBot + glueSpecSize + glueSpecSize + glueSpecSize + glueSpecSize
 23055  	case skipCode:
 23056  		prg.scanGlue(smallNumber(glueVal))
 23057  	case mskipCode:
 23058  		prg.scanGlue(smallNumber(muVal))
 23059  	} // now |cur_val| points to the glue specification
 23060  	{
 23061  		*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newGlue(halfword(prg.curVal))
 23062  		prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 23063  	}
 23064  	if int32(s) >= skipCode {
 23065  		*(*prg.mem[prg.curVal].hh()).rh() = uint16(int32(*(*prg.mem[prg.curVal].hh()).rh()) - 1)
 23066  		if int32(s) > skipCode {
 23067  			*(*prg.mem[prg.curList.tailField].hh()).b1() = byte(muGlue)
 23068  		}
 23069  	}
 23070  }
 23071  
 23072  func (prg *prg) appendKern() {
 23073  	var (
 23074  		s quarterword // |subtype| of the kern node
 23075  	)
 23076  	s = byte(prg.curChr)
 23077  	prg.scanDimen(int32(s) == muGlue, false, false)
 23078  	{
 23079  		*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newKern(prg.curVal)
 23080  		prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 23081  	}
 23082  	*(*prg.mem[prg.curList.tailField].hh()).b1() = s
 23083  }
 23084  
 23085  func (prg *prg) offSave() {
 23086  	var (
 23087  		p halfword // inserted token
 23088  	)
 23089  	if int32(prg.curGroup) == bottomLevel {
 23090  		{
 23091  			if int32(prg.interaction) == errorStopMode {
 23092  			}
 23093  			prg.printNl(strNumber( /* "! " */ 262))
 23094  			prg.print( /* "Extra " */ 777)
 23095  		}
 23096  		prg.printCmdChr(prg.curCmd, prg.curChr)
 23097  		// \xref[Extra x]
 23098  		{
 23099  			prg.helpPtr = 1
 23100  			prg.helpLine[0] = /* "Things are pretty mixed up, but I think the worst is over." */ 1043
 23101  		}
 23102  
 23103  		prg.error1()
 23104  	} else {
 23105  		prg.backInput()
 23106  		p = prg.getAvail()
 23107  		*(*prg.mem[30000-3].hh()).rh() = p
 23108  		{
 23109  			if int32(prg.interaction) == errorStopMode {
 23110  			}
 23111  			prg.printNl(strNumber( /* "! " */ 262))
 23112  			prg.print( /* "Missing " */ 625)
 23113  		}
 23114  
 23115  		// Prepare to insert a token that matches |cur_group|, and print what it is
 23116  		switch prg.curGroup {
 23117  		case semiSimpleGroup:
 23118  			*(*prg.mem[p].hh()).lh() = uint16(07777 + frozenEndGroup)
 23119  			prg.printEsc(strNumber( /* "endgroup" */ 516))
 23120  		// \xref[Missing \\endgroup inserted]
 23121  
 23122  		case mathShiftGroup:
 23123  			*(*prg.mem[p].hh()).lh() = uint16(mathShiftToken + '$')
 23124  			prg.printChar(asciiCode('$'))
 23125  		// \xref[Missing \$ inserted]
 23126  
 23127  		case mathLeftGroup:
 23128  			*(*prg.mem[p].hh()).lh() = uint16(07777 + frozenRight)
 23129  			*(*prg.mem[p].hh()).rh() = prg.getAvail()
 23130  			p = *(*prg.mem[p].hh()).rh()
 23131  			*(*prg.mem[p].hh()).lh() = uint16(otherToken + '.')
 23132  			prg.printEsc(strNumber( /* "right." */ 1042))
 23133  		// \xref[Missing \\right\hbox[.] inserted]
 23134  		// \xref[null delimiter]
 23135  
 23136  		default:
 23137  			*(*prg.mem[p].hh()).lh() = uint16(rightBraceToken + '}')
 23138  			prg.printChar(asciiCode('}'))
 23139  			// \xref[Missing \] inserted]
 23140  
 23141  		}
 23142  		prg.print( /* " inserted" */ 626)
 23143  		prg.beginTokenList(*(*prg.mem[30000-3].hh()).rh(), quarterword(inserted))
 23144  		{
 23145  			prg.helpPtr = 5
 23146  			prg.helpLine[4] = /* "I've inserted something that you may have forgotten." */ 1037
 23147  			prg.helpLine[3] = /* "(See the <inserted text> above.)" */ 1038
 23148  			prg.helpLine[2] = /* "With luck, this will get me unwedged. But if you" */ 1039
 23149  			prg.helpLine[1] = /* "really didn't forget anything, try typing `2' now; then" */ 1040
 23150  			prg.helpLine[0] = /* "my insertion and my current dilemma will both disappear." */ 1041
 23151  		}
 23152  		prg.error1()
 23153  	}
 23154  }
 23155  
 23156  func (prg *prg) extraRightBrace() {
 23157  	{
 23158  		if int32(prg.interaction) == errorStopMode {
 23159  		}
 23160  		prg.printNl(strNumber( /* "! " */ 262))
 23161  		prg.print( /* "Extra ], or forgotten " */ 1048)
 23162  	}
 23163  	// \xref[Extra \], or forgotten x]
 23164  	switch prg.curGroup {
 23165  	case semiSimpleGroup:
 23166  		prg.printEsc(strNumber( /* "endgroup" */ 516))
 23167  	case mathShiftGroup:
 23168  		prg.printChar(asciiCode('$'))
 23169  	case mathLeftGroup:
 23170  		prg.printEsc(strNumber( /* "right" */ 877))
 23171  	}
 23172  
 23173  	{
 23174  		prg.helpPtr = 5
 23175  		prg.helpLine[4] = /* "I've deleted a group-closing symbol because it seems to be" */ 1049
 23176  		prg.helpLine[3] = /* "spurious, as in `$x]$'. But perhaps the ] is legitimate and" */ 1050
 23177  		prg.helpLine[2] = /* "you forgot something else, as in `\\hbox[$x]'. In such cases" */ 1051
 23178  		prg.helpLine[1] = /* "the way to recover is to insert both the forgotten and the" */ 1052
 23179  		prg.helpLine[0] = /* "deleted material, e.g., by typing `I$]'." */ 1053
 23180  	}
 23181  	prg.error1()
 23182  	prg.alignState = prg.alignState + 1
 23183  } // \2
 23184  
 23185  func (prg *prg) normalParagraph() {
 23186  	if *prg.eqtb[intBase+loosenessCode-1].int() != 0 {
 23187  		prg.eqWordDefine(halfword(intBase+loosenessCode), 0)
 23188  	}
 23189  	if *prg.eqtb[dimenBase+hangIndentCode-1].int() != 0 {
 23190  		prg.eqWordDefine(halfword(dimenBase+hangIndentCode), 0)
 23191  	}
 23192  	if *prg.eqtb[intBase+hangAfterCode-1].int() != 1 {
 23193  		prg.eqWordDefine(halfword(intBase+hangAfterCode), 1)
 23194  	}
 23195  	if int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh()) != 0 {
 23196  		prg.eqDefine(halfword(parShapeLoc), quarterword(shapeRef), halfword(0))
 23197  	}
 23198  }
 23199  
 23200  func (prg *prg) boxEnd(boxContext int32) {
 23201  	var (
 23202  		p halfword // |ord_noad| for new box in math mode
 23203  	)
 23204  	if boxContext < 010000000000 {
 23205  		if int32(prg.curBox) != 0 {
 23206  			*prg.mem[int32(prg.curBox)+4].int() = boxContext
 23207  			if abs(int32(prg.curList.modeField)) == vmode {
 23208  				prg.appendToVlist(prg.curBox)
 23209  				if int32(prg.adjustTail) != 0 {
 23210  					if 30000-5 != int32(prg.adjustTail) {
 23211  						*(*prg.mem[prg.curList.tailField].hh()).rh() = *(*prg.mem[30000-5].hh()).rh()
 23212  						prg.curList.tailField = prg.adjustTail
 23213  					}
 23214  					prg.adjustTail = 0
 23215  				}
 23216  				if int32(prg.curList.modeField) > 0 {
 23217  					prg.buildPage()
 23218  				}
 23219  			} else {
 23220  				if abs(int32(prg.curList.modeField)) == hmode {
 23221  					*(*prg.curList.auxField.hh()).lh() = 1000
 23222  				} else {
 23223  					p = prg.newNoad()
 23224  					*(*prg.mem[int32(p)+1].hh()).rh() = uint16(subBox)
 23225  					*(*prg.mem[int32(p)+1].hh()).lh() = prg.curBox
 23226  					prg.curBox = p
 23227  				}
 23228  				*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.curBox
 23229  				prg.curList.tailField = prg.curBox
 23230  			}
 23231  		}
 23232  	} else if boxContext < 010000000000+512 {
 23233  		if boxContext < 010000000000+256 {
 23234  			prg.eqDefine(halfword(boxBase-010000000000+boxContext), quarterword(boxRef), prg.curBox)
 23235  		} else {
 23236  			prg.geqDefine(halfword(boxBase-010000000000-256+boxContext), quarterword(boxRef), prg.curBox)
 23237  		}
 23238  	} else if int32(prg.curBox) != 0 {
 23239  		if boxContext > 010000000000+512 {
 23240  			for {
 23241  				prg.getXToken()
 23242  				if int32(prg.curCmd) != spacer && int32(prg.curCmd) != relax {
 23243  					break
 23244  				}
 23245  			}
 23246  			if int32(prg.curCmd) == hskip && abs(int32(prg.curList.modeField)) != vmode || int32(prg.curCmd) == vskip && abs(int32(prg.curList.modeField)) == vmode {
 23247  				prg.appendGlue()
 23248  				*(*prg.mem[prg.curList.tailField].hh()).b1() = byte(boxContext - (010000000000 + 513 - aLeaders))
 23249  				*(*prg.mem[int32(prg.curList.tailField)+1].hh()).rh() = prg.curBox
 23250  			} else {
 23251  				{
 23252  					if int32(prg.interaction) == errorStopMode {
 23253  					}
 23254  					prg.printNl(strNumber( /* "! " */ 262))
 23255  					prg.print( /* "Leaders not followed by proper glue" */ 1066)
 23256  				}
 23257  				// \xref[Leaders not followed by...]
 23258  				{
 23259  					prg.helpPtr = 3
 23260  					prg.helpLine[2] = /* "You should say `\\leaders <box or rule><hskip or vskip>'." */ 1067
 23261  					prg.helpLine[1] = /* "I found the <box or rule>, but there's no suitable" */ 1068
 23262  					prg.helpLine[0] = /* "<hskip or vskip>, so I'm ignoring these leaders." */ 1069
 23263  				}
 23264  				prg.backError()
 23265  				prg.flushNodeList(prg.curBox)
 23266  			}
 23267  		} else {
 23268  			prg.shipOut(prg.curBox)
 23269  		}
 23270  	}
 23271  }
 23272  
 23273  func (prg *prg) beginBox(boxContext int32) {
 23274  	var (
 23275  		p, q halfword    // run through the current list
 23276  		m    quarterword // the length of a replacement list
 23277  		k    halfword    // 0 or |vmode| or |hmode|
 23278  		n    eightBits   // a box number
 23279  	)
 23280  	switch prg.curChr {
 23281  	case boxCode:
 23282  		prg.scanEightBitInt()
 23283  		prg.curBox = *(*prg.eqtb[boxBase+prg.curVal-1].hh()).rh()
 23284  		*(*prg.eqtb[boxBase+prg.curVal-1].hh()).rh() = 0 // the box becomes void, at the same level
 23285  
 23286  	case copyCode:
 23287  		prg.scanEightBitInt()
 23288  		prg.curBox = prg.copyNodeList(*(*prg.eqtb[boxBase+prg.curVal-1].hh()).rh())
 23289  
 23290  	case lastBoxCode:
 23291  		// If the current list ends with a box node, delete it from the list and make |cur_box| point to it; otherwise set |cur_box:=null|
 23292  		prg.curBox = 0
 23293  		if abs(int32(prg.curList.modeField)) == mmode {
 23294  			prg.youCant()
 23295  			{
 23296  				prg.helpPtr = 1
 23297  				prg.helpLine[0] = /* "Sorry; this \\lastbox will be void." */ 1070
 23298  			}
 23299  			prg.error1()
 23300  		} else if int32(prg.curList.modeField) == vmode && int32(prg.curList.headField) == int32(prg.curList.tailField) {
 23301  			prg.youCant()
 23302  			{
 23303  				prg.helpPtr = 2
 23304  				prg.helpLine[1] = /* "Sorry...I usually can't take things from the current page." */ 1071
 23305  				prg.helpLine[0] = /* "This \\lastbox will therefore be void." */ 1072
 23306  			}
 23307  			prg.error1()
 23308  		} else {
 23309  			if !(int32(prg.curList.tailField) >= int32(prg.hiMemMin)) {
 23310  				if int32(*(*prg.mem[prg.curList.tailField].hh()).b0()) == hlistNode || int32(*(*prg.mem[prg.curList.tailField].hh()).b0()) == vlistNode {
 23311  					q = prg.curList.headField
 23312  					for {
 23313  						p = q
 23314  						if !(int32(q) >= int32(prg.hiMemMin)) {
 23315  							if int32(*(*prg.mem[q].hh()).b0()) == discNode {
 23316  								for ii := int32(1); ii <= int32(*(*prg.mem[q].hh()).b1()); ii++ {
 23317  									m = quarterword(ii)
 23318  									_ = m
 23319  									p = *(*prg.mem[p].hh()).rh()
 23320  								}
 23321  								if int32(p) == int32(prg.curList.tailField) {
 23322  									goto done
 23323  								}
 23324  							}
 23325  						}
 23326  						q = *(*prg.mem[p].hh()).rh()
 23327  						if int32(q) == int32(prg.curList.tailField) {
 23328  							break
 23329  						}
 23330  					}
 23331  					prg.curBox = prg.curList.tailField
 23332  					*prg.mem[int32(prg.curBox)+4].int() = 0
 23333  					prg.curList.tailField = p
 23334  					*(*prg.mem[p].hh()).rh() = 0
 23335  
 23336  				done:
 23337  				}
 23338  			}
 23339  		}
 23340  
 23341  	case vsplitCode:
 23342  		// Split off part of a vertical box, make |cur_box| point to it
 23343  		prg.scanEightBitInt()
 23344  		n = byte(prg.curVal)
 23345  		if !prg.scanKeyword(strNumber(842)) {
 23346  			{
 23347  				if int32(prg.interaction) == errorStopMode {
 23348  				}
 23349  				prg.printNl(strNumber( /* "! " */ 262))
 23350  				prg.print( /* "Missing `to' inserted" */ 1073)
 23351  			}
 23352  			// \xref[Missing `to' inserted]
 23353  			{
 23354  				prg.helpPtr = 2
 23355  				prg.helpLine[1] = /* "I'm working on `\\vsplit<box number> to <dimen>';" */ 1074
 23356  				prg.helpLine[0] = /* "will look for the <dimen> next." */ 1075
 23357  			}
 23358  			prg.error1()
 23359  		}
 23360  		prg.scanDimen(false, false, false)
 23361  		prg.curBox = prg.vsplit(n, prg.curVal)
 23362  
 23363  	default:
 23364  		k = uint16(int32(prg.curChr) - vtopCode)
 23365  		*prg.saveStack[int32(prg.savePtr)+0].int() = boxContext
 23366  		if int32(k) == hmode {
 23367  			if boxContext < 010000000000 && abs(int32(prg.curList.modeField)) == vmode {
 23368  				prg.scanSpec(groupCode(adjustedHboxGroup), true)
 23369  			} else {
 23370  				prg.scanSpec(groupCode(hboxGroup), true)
 23371  			}
 23372  		} else {
 23373  			if int32(k) == vmode {
 23374  				prg.scanSpec(groupCode(vboxGroup), true)
 23375  			} else {
 23376  				prg.scanSpec(groupCode(vtopGroup), true)
 23377  				k = uint16(vmode)
 23378  			}
 23379  			prg.normalParagraph()
 23380  		}
 23381  		prg.pushNest()
 23382  		prg.curList.modeField = int16(-int32(k))
 23383  		if int32(k) == vmode {
 23384  			*prg.curList.auxField.int() = -65536000
 23385  			if int32(*(*prg.eqtb[everyVboxLoc-1].hh()).rh()) != 0 {
 23386  				prg.beginTokenList(*(*prg.eqtb[everyVboxLoc-1].hh()).rh(), quarterword(everyVboxText))
 23387  			}
 23388  		} else {
 23389  			*(*prg.curList.auxField.hh()).lh() = 1000
 23390  			if int32(*(*prg.eqtb[everyHboxLoc-1].hh()).rh()) != 0 {
 23391  				prg.beginTokenList(*(*prg.eqtb[everyHboxLoc-1].hh()).rh(), quarterword(everyHboxText))
 23392  			}
 23393  		}
 23394  
 23395  		goto exit
 23396  
 23397  	}
 23398  
 23399  	prg.boxEnd(boxContext) // in simple cases, we use the box immediately
 23400  	// in simple cases, we use the box immediately
 23401  exit:
 23402  }
 23403  
 23404  func (prg *prg) scanBox(boxContext int32) {
 23405  	for {
 23406  		prg.getXToken()
 23407  		if int32(prg.curCmd) != spacer && int32(prg.curCmd) != relax {
 23408  			break
 23409  		}
 23410  	}
 23411  	if int32(prg.curCmd) == makeBox {
 23412  		prg.beginBox(boxContext)
 23413  	} else if boxContext >= 010000000000+513 && (int32(prg.curCmd) == hrule || int32(prg.curCmd) == vrule) {
 23414  		prg.curBox = prg.scanRuleSpec()
 23415  		prg.boxEnd(boxContext)
 23416  	} else {
 23417  		{
 23418  			if int32(prg.interaction) == errorStopMode {
 23419  			}
 23420  			prg.printNl(strNumber( /* "! " */ 262))
 23421  			prg.print( /* "A <box> was supposed to be here" */ 1076)
 23422  		}
 23423  
 23424  		// \xref[A <box> was supposed to...]
 23425  		{
 23426  			prg.helpPtr = 3
 23427  			prg.helpLine[2] = /* "I was expecting to see \\hbox or \\vbox or \\copy or \\box or" */ 1077
 23428  			prg.helpLine[1] = /* "something like that. So you might find something missing in" */ 1078
 23429  			prg.helpLine[0] = /* "your output. But keep trying; you can fix this later." */ 1079
 23430  		}
 23431  		prg.backError()
 23432  	}
 23433  }
 23434  
 23435  func (prg *prg) package1(c smallNumber) {
 23436  	var (
 23437  		h scaled   // height of box
 23438  		p halfword // first node in a box
 23439  		d scaled   // max depth
 23440  	)
 23441  	d = *prg.eqtb[dimenBase+boxMaxDepthCode-1].int()
 23442  	prg.unsave()
 23443  	prg.savePtr = uint16(int32(prg.savePtr) - 3)
 23444  	if int32(prg.curList.modeField) == -hmode {
 23445  		prg.curBox = prg.hpack(*(*prg.mem[prg.curList.headField].hh()).rh(), *prg.saveStack[int32(prg.savePtr)+2].int(), smallNumber(*prg.saveStack[int32(prg.savePtr)+1].int()))
 23446  	} else {
 23447  		prg.curBox = prg.vpackage(*(*prg.mem[prg.curList.headField].hh()).rh(), *prg.saveStack[int32(prg.savePtr)+2].int(), smallNumber(*prg.saveStack[int32(prg.savePtr)+1].int()), d)
 23448  		if int32(c) == vtopCode {
 23449  			h = 0
 23450  			p = *(*prg.mem[int32(prg.curBox)+listOffset].hh()).rh()
 23451  			if int32(p) != 0 {
 23452  				if int32(*(*prg.mem[p].hh()).b0()) <= ruleNode {
 23453  					h = *prg.mem[int32(p)+heightOffset].int()
 23454  				}
 23455  			}
 23456  			*prg.mem[int32(prg.curBox)+depthOffset].int() = *prg.mem[int32(prg.curBox)+depthOffset].int() - h + *prg.mem[int32(prg.curBox)+heightOffset].int()
 23457  			*prg.mem[int32(prg.curBox)+heightOffset].int() = h
 23458  		}
 23459  	}
 23460  	prg.popNest()
 23461  	prg.boxEnd(*prg.saveStack[int32(prg.savePtr)+0].int())
 23462  }
 23463  
 23464  func (prg *prg) normMin(h int32) (r smallNumber) {
 23465  	if h <= 0 {
 23466  		r = 1
 23467  	} else if h >= 63 {
 23468  		r = 63
 23469  	} else {
 23470  		r = byte(h)
 23471  	}
 23472  	return r
 23473  }
 23474  
 23475  func (prg *prg) newGraf(indented bool) {
 23476  	prg.curList.pgField = 0
 23477  	if int32(prg.curList.modeField) == vmode || int32(prg.curList.headField) != int32(prg.curList.tailField) {
 23478  		*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newParamGlue(smallNumber(parSkipCode))
 23479  		prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 23480  	}
 23481  	prg.pushNest()
 23482  	prg.curList.modeField = int16(hmode)
 23483  	*(*prg.curList.auxField.hh()).lh() = 1000
 23484  	if *prg.eqtb[intBase+languageCode-1].int() <= 0 {
 23485  		prg.curLang = 0
 23486  	} else if *prg.eqtb[intBase+languageCode-1].int() > 255 {
 23487  		prg.curLang = 0
 23488  	} else {
 23489  		prg.curLang = byte(*prg.eqtb[intBase+languageCode-1].int())
 23490  	}
 23491  	*(*prg.curList.auxField.hh()).rh() = uint16(prg.curLang)
 23492  	prg.curList.pgField = (int32(prg.normMin(*prg.eqtb[intBase+leftHyphenMinCode-1].int()))*0100+int32(prg.normMin(*prg.eqtb[intBase+rightHyphenMinCode-1].int())))*0200000 + int32(prg.curLang)
 23493  	if indented {
 23494  		prg.curList.tailField = prg.newNullBox()
 23495  		*(*prg.mem[prg.curList.headField].hh()).rh() = prg.curList.tailField
 23496  		*prg.mem[int32(prg.curList.tailField)+widthOffset].int() = *prg.eqtb[dimenBase+parIndentCode-1].int()
 23497  	}
 23498  	if int32(*(*prg.eqtb[everyParLoc-1].hh()).rh()) != 0 {
 23499  		prg.beginTokenList(*(*prg.eqtb[everyParLoc-1].hh()).rh(), quarterword(everyParText))
 23500  	}
 23501  	if int32(prg.nestPtr) == 1 {
 23502  		prg.buildPage()
 23503  	} // put |par_skip| glue on current page
 23504  }
 23505  
 23506  func (prg *prg) indentInHmode() {
 23507  	var (
 23508  		p, q halfword
 23509  	)
 23510  	if int32(prg.curChr) > 0 {
 23511  		p = prg.newNullBox()
 23512  		*prg.mem[int32(p)+widthOffset].int() = *prg.eqtb[dimenBase+parIndentCode-1].int()
 23513  		if abs(int32(prg.curList.modeField)) == hmode {
 23514  			*(*prg.curList.auxField.hh()).lh() = 1000
 23515  		} else {
 23516  			q = prg.newNoad()
 23517  			*(*prg.mem[int32(q)+1].hh()).rh() = uint16(subBox)
 23518  			*(*prg.mem[int32(q)+1].hh()).lh() = p
 23519  			p = q
 23520  		}
 23521  		{
 23522  			*(*prg.mem[prg.curList.tailField].hh()).rh() = p
 23523  			prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 23524  		}
 23525  	}
 23526  }
 23527  
 23528  func (prg *prg) headForVmode() {
 23529  	if int32(prg.curList.modeField) < 0 {
 23530  		if int32(prg.curCmd) != hrule {
 23531  			prg.offSave()
 23532  		} else {
 23533  			{
 23534  				if int32(prg.interaction) == errorStopMode {
 23535  				}
 23536  				prg.printNl(strNumber( /* "! " */ 262))
 23537  				prg.print( /* "You can't use `" */ 685)
 23538  			}
 23539  			prg.printEsc(strNumber( /* "hrule" */ 521))
 23540  			prg.print( /* "' here except with leaders" */ 1082)
 23541  			// \xref[You can't use \\hrule...]
 23542  			{
 23543  				prg.helpPtr = 2
 23544  				prg.helpLine[1] = /* "To put a horizontal rule in an hbox or an alignment," */ 1083
 23545  				prg.helpLine[0] = /* "you should use \\leaders or \\hrulefill (see The TeXbook)." */ 1084
 23546  			}
 23547  			prg.error1()
 23548  		}
 23549  	} else {
 23550  		prg.backInput()
 23551  		prg.curTok = prg.parToken
 23552  		prg.backInput()
 23553  		prg.curInput.indexField = byte(inserted)
 23554  	}
 23555  }
 23556  
 23557  func (prg *prg) endGraf() {
 23558  	if int32(prg.curList.modeField) == hmode {
 23559  		if int32(prg.curList.headField) == int32(prg.curList.tailField) {
 23560  			prg.popNest()
 23561  		} else {
 23562  			prg.lineBreak(*prg.eqtb[intBase+widowPenaltyCode-1].int())
 23563  		}
 23564  		prg.normalParagraph()
 23565  		prg.errorCount = 0
 23566  	}
 23567  }
 23568  
 23569  func (prg *prg) beginInsertOrAdjust() {
 23570  	if int32(prg.curCmd) == vadjust {
 23571  		prg.curVal = 255
 23572  	} else {
 23573  		prg.scanEightBitInt()
 23574  		if prg.curVal == 255 {
 23575  			{
 23576  				if int32(prg.interaction) == errorStopMode {
 23577  				}
 23578  				prg.printNl(strNumber( /* "! " */ 262))
 23579  				prg.print( /* "You can't " */ 1085)
 23580  			}
 23581  			prg.printEsc(strNumber( /* "insert" */ 330))
 23582  			prg.printInt(255)
 23583  			// \xref[You can't \\insert255]
 23584  			{
 23585  				prg.helpPtr = 1
 23586  				prg.helpLine[0] = /* "I'm changing to \\insert0; box 255 is special." */ 1086
 23587  			}
 23588  			prg.error1()
 23589  			prg.curVal = 0
 23590  		}
 23591  	}
 23592  	*prg.saveStack[int32(prg.savePtr)+0].int() = prg.curVal
 23593  	prg.savePtr = uint16(int32(prg.savePtr) + 1)
 23594  	prg.newSaveLevel(groupCode(insertGroup))
 23595  	prg.scanLeftBrace()
 23596  	prg.normalParagraph()
 23597  	prg.pushNest()
 23598  	prg.curList.modeField = int16(-vmode)
 23599  	*prg.curList.auxField.int() = -65536000
 23600  }
 23601  
 23602  func (prg *prg) makeMark() {
 23603  	var (
 23604  		p halfword // new node
 23605  	)
 23606  	p = prg.scanToks(false, true)
 23607  	p = prg.getNode(smallNodeSize)
 23608  	*(*prg.mem[p].hh()).b0() = byte(markNode)
 23609  	*(*prg.mem[p].hh()).b1() = 0 // the |subtype| is not used
 23610  	*prg.mem[int32(p)+1].int() = int32(prg.defRef)
 23611  	*(*prg.mem[prg.curList.tailField].hh()).rh() = p
 23612  	prg.curList.tailField = p
 23613  }
 23614  
 23615  func (prg *prg) appendPenalty() {
 23616  	prg.scanInt()
 23617  	{
 23618  		*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newPenalty(prg.curVal)
 23619  		prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 23620  	}
 23621  	if int32(prg.curList.modeField) == vmode {
 23622  		prg.buildPage()
 23623  	}
 23624  }
 23625  
 23626  func (prg *prg) deleteLast() {
 23627  	var (
 23628  		p, q halfword    // run through the current list
 23629  		m    quarterword // the length of a replacement list
 23630  	)
 23631  	if int32(prg.curList.modeField) == vmode && int32(prg.curList.tailField) == int32(prg.curList.headField) {
 23632  		if int32(prg.curChr) != glueNode || int32(prg.lastGlue) != 65535 {
 23633  			prg.youCant()
 23634  			{
 23635  				prg.helpPtr = 2
 23636  				prg.helpLine[1] = /* "Sorry...I usually can't take things from the current page." */ 1071
 23637  				prg.helpLine[0] = /* "Try `I\\vskip-\\lastskip' instead." */ 1087
 23638  			}
 23639  			if int32(prg.curChr) == kernNode {
 23640  				prg.helpLine[0] = uint16(1088)
 23641  			} else if int32(prg.curChr) != glueNode {
 23642  				prg.helpLine[0] = uint16(1089)
 23643  			}
 23644  			prg.error1()
 23645  		}
 23646  	} else {
 23647  		if !(int32(prg.curList.tailField) >= int32(prg.hiMemMin)) {
 23648  			if int32(*(*prg.mem[prg.curList.tailField].hh()).b0()) == int32(prg.curChr) {
 23649  				q = prg.curList.headField
 23650  				for {
 23651  					p = q
 23652  					if !(int32(q) >= int32(prg.hiMemMin)) {
 23653  						if int32(*(*prg.mem[q].hh()).b0()) == discNode {
 23654  							for ii := int32(1); ii <= int32(*(*prg.mem[q].hh()).b1()); ii++ {
 23655  								m = quarterword(ii)
 23656  								_ = m
 23657  								p = *(*prg.mem[p].hh()).rh()
 23658  							}
 23659  							if int32(p) == int32(prg.curList.tailField) {
 23660  								goto exit
 23661  							}
 23662  						}
 23663  					}
 23664  					q = *(*prg.mem[p].hh()).rh()
 23665  					if int32(q) == int32(prg.curList.tailField) {
 23666  						break
 23667  					}
 23668  				}
 23669  				*(*prg.mem[p].hh()).rh() = 0
 23670  				prg.flushNodeList(prg.curList.tailField)
 23671  				prg.curList.tailField = p
 23672  			}
 23673  		}
 23674  	}
 23675  
 23676  exit:
 23677  }
 23678  
 23679  func (prg *prg) unpackage() {
 23680  	var (
 23681  		p                             halfword // the box
 23682  		c/* boxCode..copyCode */ byte          // should we copy?
 23683  	)
 23684  	c = byte(prg.curChr)
 23685  	prg.scanEightBitInt()
 23686  	p = *(*prg.eqtb[boxBase+prg.curVal-1].hh()).rh()
 23687  	if int32(p) == 0 {
 23688  		goto exit
 23689  	}
 23690  	if abs(int32(prg.curList.modeField)) == mmode || abs(int32(prg.curList.modeField)) == vmode && int32(*(*prg.mem[p].hh()).b0()) != vlistNode || abs(int32(prg.curList.modeField)) == hmode && int32(*(*prg.mem[p].hh()).b0()) != hlistNode {
 23691  		{
 23692  			if int32(prg.interaction) == errorStopMode {
 23693  			}
 23694  			prg.printNl(strNumber( /* "! " */ 262))
 23695  			prg.print( /* "Incompatible list can't be unboxed" */ 1097)
 23696  		}
 23697  		// \xref[Incompatible list...]
 23698  		{
 23699  			prg.helpPtr = 3
 23700  			prg.helpLine[2] = /* "Sorry, Pandora. (You sneaky devil.)" */ 1098
 23701  			prg.helpLine[1] = /* "I refuse to unbox an \\hbox in vertical mode or vice versa." */ 1099
 23702  			prg.helpLine[0] = /* "And I can't open any boxes in math mode." */ 1100
 23703  		}
 23704  
 23705  		prg.error1()
 23706  		goto exit
 23707  	}
 23708  	if int32(c) == copyCode {
 23709  		*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.copyNodeList(*(*prg.mem[int32(p)+listOffset].hh()).rh())
 23710  	} else {
 23711  		*(*prg.mem[prg.curList.tailField].hh()).rh() = *(*prg.mem[int32(p)+listOffset].hh()).rh()
 23712  		*(*prg.eqtb[boxBase+prg.curVal-1].hh()).rh() = 0
 23713  		prg.freeNode(p, halfword(boxNodeSize))
 23714  	}
 23715  	for int32(*(*prg.mem[prg.curList.tailField].hh()).rh()) != 0 {
 23716  		prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 23717  	}
 23718  
 23719  exit:
 23720  }
 23721  
 23722  func (prg *prg) appendItalicCorrection() {
 23723  	var (
 23724  		p halfword           // |char_node| at the tail of the current list
 23725  		f internalFontNumber // the font in the |char_node|
 23726  	)
 23727  	if int32(prg.curList.tailField) != int32(prg.curList.headField) {
 23728  		if int32(prg.curList.tailField) >= int32(prg.hiMemMin) {
 23729  			p = prg.curList.tailField
 23730  		} else if int32(*(*prg.mem[prg.curList.tailField].hh()).b0()) == ligatureNode {
 23731  			p = uint16(int32(prg.curList.tailField) + 1)
 23732  		} else {
 23733  			goto exit
 23734  		}
 23735  		f = *(*prg.mem[p].hh()).b0()
 23736  		{
 23737  			*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newKern(*prg.fontInfo[prg.italicBase[f]+(int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[p].hh()).b1())].qqqq()).b2)-minQuarterword)/4].int())
 23738  			prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 23739  		}
 23740  		*(*prg.mem[prg.curList.tailField].hh()).b1() = byte(explicit)
 23741  	}
 23742  
 23743  exit:
 23744  }
 23745  
 23746  func (prg *prg) appendDiscretionary() {
 23747  	var (
 23748  		c int32 // hyphen character
 23749  	)
 23750  	{
 23751  		*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newDisc()
 23752  		prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 23753  	}
 23754  	if int32(prg.curChr) == 1 {
 23755  		c = prg.hyphenChar[*(*prg.eqtb[curFontLoc-1].hh()).rh()]
 23756  		if c >= 0 {
 23757  			if c < 256 {
 23758  				*(*prg.mem[int32(prg.curList.tailField)+1].hh()).lh() = prg.newCharacter(internalFontNumber(*(*prg.eqtb[curFontLoc-1].hh()).rh()), eightBits(c))
 23759  			}
 23760  		}
 23761  	} else {
 23762  		prg.savePtr = uint16(int32(prg.savePtr) + 1)
 23763  		*prg.saveStack[int32(prg.savePtr)+-1].int() = 0
 23764  		prg.newSaveLevel(groupCode(discGroup))
 23765  		prg.scanLeftBrace()
 23766  		prg.pushNest()
 23767  		prg.curList.modeField = int16(-hmode)
 23768  		*(*prg.curList.auxField.hh()).lh() = 1000
 23769  	}
 23770  }
 23771  
 23772  func (prg *prg) buildDiscretionary() {
 23773  	var (
 23774  		p, q halfword // for link manipulation
 23775  		n    int32    // length of discretionary list
 23776  	)
 23777  	prg.unsave()
 23778  
 23779  	// Prune the current list, if necessary, until it contains only |char_node|, |kern_node|, |hlist_node|, |vlist_node|, |rule_node|, and |ligature_node| items; set |n| to the length of the list, and set |q| to the list's tail
 23780  	q = prg.curList.headField
 23781  	p = *(*prg.mem[q].hh()).rh()
 23782  	n = 0
 23783  	for int32(p) != 0 {
 23784  		if !(int32(p) >= int32(prg.hiMemMin)) {
 23785  			if int32(*(*prg.mem[p].hh()).b0()) > ruleNode {
 23786  				if int32(*(*prg.mem[p].hh()).b0()) != kernNode {
 23787  					if int32(*(*prg.mem[p].hh()).b0()) != ligatureNode {
 23788  						{
 23789  							if int32(prg.interaction) == errorStopMode {
 23790  							}
 23791  							prg.printNl(strNumber( /* "! " */ 262))
 23792  							prg.print( /* "Improper discretionary list" */ 1107)
 23793  						}
 23794  						// \xref[Improper discretionary list]
 23795  						{
 23796  							prg.helpPtr = 1
 23797  							prg.helpLine[0] = /* "Discretionary lists must contain only boxes and kerns." */ 1108
 23798  						}
 23799  
 23800  						prg.error1()
 23801  						prg.beginDiagnostic()
 23802  						prg.printNl(strNumber( /* "The following discretionary sublist has been deleted:" */ 1109))
 23803  						// \xref[The following...deleted]
 23804  						prg.showBox(p)
 23805  						prg.endDiagnostic(true)
 23806  						prg.flushNodeList(p)
 23807  						*(*prg.mem[q].hh()).rh() = 0
 23808  						goto done
 23809  					}
 23810  				}
 23811  			}
 23812  		}
 23813  		q = p
 23814  		p = *(*prg.mem[q].hh()).rh()
 23815  		n = n + 1
 23816  	}
 23817  
 23818  done:
 23819  	;
 23820  	p = *(*prg.mem[prg.curList.headField].hh()).rh()
 23821  	prg.popNest()
 23822  	switch *prg.saveStack[int32(prg.savePtr)+-1].int() {
 23823  	case 0:
 23824  		*(*prg.mem[int32(prg.curList.tailField)+1].hh()).lh() = p
 23825  	case 1:
 23826  		*(*prg.mem[int32(prg.curList.tailField)+1].hh()).rh() = p
 23827  	case 2:
 23828  		// Attach list |p| to the current list, and record its length; then finish up and |return|
 23829  		if n > 0 && abs(int32(prg.curList.modeField)) == mmode {
 23830  			{
 23831  				if int32(prg.interaction) == errorStopMode {
 23832  				}
 23833  				prg.printNl(strNumber( /* "! " */ 262))
 23834  				prg.print( /* "Illegal math " */ 1101)
 23835  			}
 23836  			prg.printEsc(strNumber( /* "discretionary" */ 349))
 23837  			// \xref[Illegal math \\disc...]
 23838  			{
 23839  				prg.helpPtr = 2
 23840  				prg.helpLine[1] = /* "Sorry: The third part of a discretionary break must be" */ 1102
 23841  				prg.helpLine[0] = /* "empty, in math formulas. I had to delete your third part." */ 1103
 23842  			}
 23843  			prg.flushNodeList(p)
 23844  			n = 0
 23845  			prg.error1()
 23846  		} else {
 23847  			*(*prg.mem[prg.curList.tailField].hh()).rh() = p
 23848  		}
 23849  		if n <= maxQuarterword {
 23850  			*(*prg.mem[prg.curList.tailField].hh()).b1() = byte(n)
 23851  		} else {
 23852  			{
 23853  				if int32(prg.interaction) == errorStopMode {
 23854  				}
 23855  				prg.printNl(strNumber( /* "! " */ 262))
 23856  				prg.print( /* "Discretionary list is too long" */ 1104)
 23857  			}
 23858  			// \xref[Discretionary list is too long]
 23859  			{
 23860  				prg.helpPtr = 2
 23861  				prg.helpLine[1] = /* "Wow---I never thought anybody would tweak me here." */ 1105
 23862  				prg.helpLine[0] = /* "You can't seriously need such a huge discretionary list?" */ 1106
 23863  			}
 23864  			prg.error1()
 23865  		}
 23866  		if n > 0 {
 23867  			prg.curList.tailField = q
 23868  		}
 23869  		prg.savePtr = uint16(int32(prg.savePtr) - 1)
 23870  		goto exit
 23871  
 23872  	} // there are no other cases
 23873  	*prg.saveStack[int32(prg.savePtr)+-1].int() = *prg.saveStack[int32(prg.savePtr)+-1].int() + 1
 23874  	prg.newSaveLevel(groupCode(discGroup))
 23875  	prg.scanLeftBrace()
 23876  	prg.pushNest()
 23877  	prg.curList.modeField = int16(-hmode)
 23878  	*(*prg.curList.auxField.hh()).lh() = 1000
 23879  
 23880  exit:
 23881  }
 23882  
 23883  func (prg *prg) makeAccent() {
 23884  	var (
 23885  		s, t              float64            // amount of slant
 23886  		p, q, r1          halfword           // character, box, and kern nodes
 23887  		f                 internalFontNumber // relevant font
 23888  		a, h, x, w, delta scaled             // heights and widths, as explained above
 23889  		i                 fourQuarters       // character information
 23890  	)
 23891  	prg.scanCharNum()
 23892  	f = byte(*(*prg.eqtb[curFontLoc-1].hh()).rh())
 23893  	p = prg.newCharacter(f, eightBits(prg.curVal))
 23894  	if int32(p) != 0 {
 23895  		x = *prg.fontInfo[xHeightCode+prg.paramBase[f]].int()
 23896  		s = float64(*prg.fontInfo[slantCode+prg.paramBase[f]].int()) / 65536.0
 23897  		// \xref[real division]
 23898  		a = *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[p].hh()).b1())].qqqq()).b0)].int()
 23899  
 23900  		prg.doAssignments()
 23901  
 23902  		// Create a character node |q| for the next character, but set |q:=null| if problems arise
 23903  		q = 0
 23904  		f = byte(*(*prg.eqtb[curFontLoc-1].hh()).rh())
 23905  		if int32(prg.curCmd) == letter || int32(prg.curCmd) == otherChar || int32(prg.curCmd) == charGiven {
 23906  			q = prg.newCharacter(f, eightBits(prg.curChr))
 23907  		} else if int32(prg.curCmd) == charNum {
 23908  			prg.scanCharNum()
 23909  			q = prg.newCharacter(f, eightBits(prg.curVal))
 23910  		} else {
 23911  			prg.backInput()
 23912  		}
 23913  		if int32(q) != 0 {
 23914  			t = float64(*prg.fontInfo[slantCode+prg.paramBase[f]].int()) / 65536.0
 23915  			// \xref[real division]
 23916  			i = *prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[q].hh()).b1())].qqqq()
 23917  			w = *prg.fontInfo[prg.widthBase[f]+int32(i.b0)].int()
 23918  			h = *prg.fontInfo[prg.heightBase[f]+(int32(i.b1)-minQuarterword)/16].int()
 23919  			if h != x {
 23920  				p = prg.hpack(p, scaled(0), smallNumber(additional))
 23921  				*prg.mem[int32(p)+4].int() = x - h
 23922  			}
 23923  			delta = round(float64(w-a)/2.0 + float64(h)*t - float64(x)*s)
 23924  			// \xref[real multiplication]
 23925  			// \xref[real addition]
 23926  			r1 = prg.newKern(delta)
 23927  			*(*prg.mem[r1].hh()).b1() = byte(accKern)
 23928  			*(*prg.mem[prg.curList.tailField].hh()).rh() = r1
 23929  			*(*prg.mem[r1].hh()).rh() = p
 23930  			prg.curList.tailField = prg.newKern(-a - delta)
 23931  			*(*prg.mem[prg.curList.tailField].hh()).b1() = byte(accKern)
 23932  			*(*prg.mem[p].hh()).rh() = prg.curList.tailField
 23933  			p = q
 23934  		}
 23935  		*(*prg.mem[prg.curList.tailField].hh()).rh() = p
 23936  		prg.curList.tailField = p
 23937  		*(*prg.curList.auxField.hh()).lh() = 1000
 23938  	}
 23939  }
 23940  
 23941  func (prg *prg) alignError() {
 23942  	if abs(prg.alignState) > 2 {
 23943  		{
 23944  			if int32(prg.interaction) == errorStopMode {
 23945  			}
 23946  			prg.printNl(strNumber( /* "! " */ 262))
 23947  			prg.print( /* "Misplaced " */ 1114)
 23948  		}
 23949  		prg.printCmdChr(prg.curCmd, prg.curChr)
 23950  		// \xref[Misplaced \&]
 23951  		// \xref[Misplaced \\span]
 23952  		// \xref[Misplaced \\cr]
 23953  		if int32(prg.curTok) == tabToken+'&' {
 23954  			{
 23955  				prg.helpPtr = 6
 23956  				prg.helpLine[5] = /* "I can't figure out why you would want to use a tab mark" */ 1115
 23957  				prg.helpLine[4] = /* "here. If you just want an ampersand, the remedy is" */ 1116
 23958  				prg.helpLine[3] = /* "simple: Just type `I\\&' now. But if some right brace" */ 1117
 23959  				prg.helpLine[2] = /* "up above has ended a previous alignment prematurely," */ 1118
 23960  				prg.helpLine[1] = /* "you're probably due for more error messages, and you" */ 1119
 23961  				prg.helpLine[0] = /* "might try typing `S' now just to see what is salvageable." */ 1120
 23962  			}
 23963  		} else {
 23964  			{
 23965  				prg.helpPtr = 5
 23966  				prg.helpLine[4] = /* "I can't figure out why you would want to use a tab mark" */ 1115
 23967  				prg.helpLine[3] = /* "or \\cr or \\span just now. If something like a right brace" */ 1121
 23968  				prg.helpLine[2] = /* "up above has ended a previous alignment prematurely," */ 1118
 23969  				prg.helpLine[1] = /* "you're probably due for more error messages, and you" */ 1119
 23970  				prg.helpLine[0] = /* "might try typing `S' now just to see what is salvageable." */ 1120
 23971  			}
 23972  		}
 23973  		prg.error1()
 23974  	} else {
 23975  		prg.backInput()
 23976  		if prg.alignState < 0 {
 23977  			{
 23978  				if int32(prg.interaction) == errorStopMode {
 23979  				}
 23980  				prg.printNl(strNumber( /* "! " */ 262))
 23981  				prg.print( /* "Missing [ inserted" */ 657)
 23982  			}
 23983  			// \xref[Missing \[ inserted]
 23984  			prg.alignState = prg.alignState + 1
 23985  			prg.curTok = uint16(leftBraceToken + '{')
 23986  		} else {
 23987  			{
 23988  				if int32(prg.interaction) == errorStopMode {
 23989  				}
 23990  				prg.printNl(strNumber( /* "! " */ 262))
 23991  				prg.print( /* "Missing ] inserted" */ 1110)
 23992  			}
 23993  			// \xref[Missing \] inserted]
 23994  			prg.alignState = prg.alignState - 1
 23995  			prg.curTok = uint16(rightBraceToken + '}')
 23996  		}
 23997  		{
 23998  			prg.helpPtr = 3
 23999  			prg.helpLine[2] = /* "I've put in what seems to be necessary to fix" */ 1111
 24000  			prg.helpLine[1] = /* "the current column of the current alignment." */ 1112
 24001  			prg.helpLine[0] = /* "Try to go on, since this might almost work." */ 1113
 24002  		}
 24003  		prg.insError()
 24004  	}
 24005  }
 24006  
 24007  func (prg *prg) noAlignError() {
 24008  	{
 24009  		if int32(prg.interaction) == errorStopMode {
 24010  		}
 24011  		prg.printNl(strNumber( /* "! " */ 262))
 24012  		prg.print( /* "Misplaced " */ 1114)
 24013  	}
 24014  	prg.printEsc(strNumber( /* "noalign" */ 527))
 24015  	// \xref[Misplaced \\noalign]
 24016  	{
 24017  		prg.helpPtr = 2
 24018  		prg.helpLine[1] = /* "I expect to see \\noalign only after the \\cr of" */ 1122
 24019  		prg.helpLine[0] = /* "an alignment. Proceed, and I'll ignore this case." */ 1123
 24020  	}
 24021  	prg.error1()
 24022  }
 24023  func (prg *prg) omitError() {
 24024  	{
 24025  		if int32(prg.interaction) == errorStopMode {
 24026  		}
 24027  		prg.printNl(strNumber( /* "! " */ 262))
 24028  		prg.print( /* "Misplaced " */ 1114)
 24029  	}
 24030  	prg.printEsc(strNumber( /* "omit" */ 530))
 24031  	// \xref[Misplaced \\omit]
 24032  	{
 24033  		prg.helpPtr = 2
 24034  		prg.helpLine[1] = /* "I expect to see \\omit only after tab marks or the \\cr of" */ 1124
 24035  		prg.helpLine[0] = /* "an alignment. Proceed, and I'll ignore this case." */ 1123
 24036  	}
 24037  	prg.error1()
 24038  }
 24039  
 24040  func (prg *prg) doEndv() {
 24041  	prg.basePtr = prg.inputPtr
 24042  	prg.inputStack[prg.basePtr] = prg.curInput
 24043  	for int32(prg.inputStack[prg.basePtr].indexField) != vTemplate && int32(prg.inputStack[prg.basePtr].locField) == 0 && int32(prg.inputStack[prg.basePtr].stateField) == tokenList {
 24044  		prg.basePtr = byte(int32(prg.basePtr) - 1)
 24045  	}
 24046  	if int32(prg.inputStack[prg.basePtr].indexField) != vTemplate || int32(prg.inputStack[prg.basePtr].locField) != 0 || int32(prg.inputStack[prg.basePtr].stateField) != tokenList {
 24047  		prg.fatalError(strNumber( /* "(interwoven alignment preambles are not allowed)" */ 595))
 24048  	}
 24049  	// \xref[interwoven alignment preambles...]
 24050  	if int32(prg.curGroup) == alignGroup {
 24051  		prg.endGraf()
 24052  		if prg.finCol() {
 24053  			prg.finRow()
 24054  		}
 24055  	} else {
 24056  		prg.offSave()
 24057  	}
 24058  }
 24059  
 24060  func (prg *prg) csError() {
 24061  	{
 24062  		if int32(prg.interaction) == errorStopMode {
 24063  		}
 24064  		prg.printNl(strNumber( /* "! " */ 262))
 24065  		prg.print( /* "Extra " */ 777)
 24066  	}
 24067  	prg.printEsc(strNumber( /* "endcsname" */ 505))
 24068  	// \xref[Extra \\endcsname]
 24069  	{
 24070  		prg.helpPtr = 1
 24071  		prg.helpLine[0] = /* "I'm ignoring this, since I wasn't doing a \\csname." */ 1126
 24072  	}
 24073  	prg.error1()
 24074  }
 24075  
 24076  func (prg *prg) pushMath(c groupCode) {
 24077  	prg.pushNest()
 24078  	prg.curList.modeField = int16(-mmode)
 24079  	*prg.curList.auxField.int() = 0
 24080  	prg.newSaveLevel(c)
 24081  }
 24082  
 24083  func (prg *prg) initMath() {
 24084  	var (
 24085  		w scaled             // new or partial |pre_display_size|
 24086  		l scaled             // new |display_width|
 24087  		s scaled             // new |display_indent|
 24088  		p halfword           // current node when calculating |pre_display_size|
 24089  		q halfword           // glue specification when calculating |pre_display_size|
 24090  		f internalFontNumber // font in current |char_node|
 24091  		n int32              // scope of paragraph shape specification
 24092  		v scaled             // |w| plus possible glue amount
 24093  		d scaled             // increment to |v|
 24094  	)
 24095  	prg.getToken() // |get_x_token| would fail on \.[\\ifmmode]\thinspace!
 24096  	if int32(prg.curCmd) == mathShift && int32(prg.curList.modeField) > 0 {
 24097  		if int32(prg.curList.headField) == int32(prg.curList.tailField) {
 24098  			prg.popNest()
 24099  			w = -07777777777
 24100  		} else {
 24101  			prg.lineBreak(*prg.eqtb[intBase+displayWidowPenaltyCode-1].int())
 24102  
 24103  			// Calculate the natural width, |w|, by which the characters of the final line extend to the right of the reference point, plus two ems; or set |w:=max_dimen| if the non-blank information on that line is affected by stretching or shrinking
 24104  			v = *prg.mem[int32(prg.justBox)+4].int() + 2**prg.fontInfo[quadCode+prg.paramBase[*(*prg.eqtb[curFontLoc-1].hh()).rh()]].int()
 24105  			w = -07777777777
 24106  			p = *(*prg.mem[int32(prg.justBox)+listOffset].hh()).rh()
 24107  			for int32(p) != 0 {
 24108  
 24109  				// Let |d| be the natural width of node |p|; if the node is “visible,” |goto found|; if the node is glue that stretches or shrinks, set |v:=max_dimen|
 24110  			reswitch:
 24111  				if int32(p) >= int32(prg.hiMemMin) {
 24112  					f = *(*prg.mem[p].hh()).b0()
 24113  					d = *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[p].hh()).b1())].qqqq()).b0)].int()
 24114  
 24115  					goto found
 24116  				}
 24117  				switch *(*prg.mem[p].hh()).b0() {
 24118  				case hlistNode, vlistNode, ruleNode:
 24119  					d = *prg.mem[int32(p)+widthOffset].int()
 24120  					goto found
 24121  
 24122  				case ligatureNode:
 24123  					// Make node |p| look like a |char_node|...
 24124  					prg.mem[30000-12] = prg.mem[int32(p)+1]
 24125  					*(*prg.mem[30000-12].hh()).rh() = *(*prg.mem[p].hh()).rh()
 24126  					p = uint16(30000 - 12)
 24127  					goto reswitch
 24128  
 24129  				case kernNode, mathNode:
 24130  					d = *prg.mem[int32(p)+widthOffset].int()
 24131  				case glueNode:
 24132  					// Let |d| be the natural width of this glue; if stretching or shrinking, set |v:=max_dimen|; |goto found| in the case of leaders
 24133  					q = *(*prg.mem[int32(p)+1].hh()).lh()
 24134  					d = *prg.mem[int32(q)+widthOffset].int()
 24135  					if int32(*(*prg.mem[int32(prg.justBox)+listOffset].hh()).b0()) == stretching {
 24136  						if int32(*(*prg.mem[int32(prg.justBox)+listOffset].hh()).b1()) == int32(*(*prg.mem[q].hh()).b0()) && *prg.mem[int32(q)+2].int() != 0 {
 24137  							v = 07777777777
 24138  						}
 24139  					} else if int32(*(*prg.mem[int32(prg.justBox)+listOffset].hh()).b0()) == shrinking {
 24140  						if int32(*(*prg.mem[int32(prg.justBox)+listOffset].hh()).b1()) == int32(*(*prg.mem[q].hh()).b1()) && *prg.mem[int32(q)+3].int() != 0 {
 24141  							v = 07777777777
 24142  						}
 24143  					}
 24144  					if int32(*(*prg.mem[p].hh()).b1()) >= aLeaders {
 24145  						goto found
 24146  					}
 24147  
 24148  				case whatsitNode:
 24149  					// Let |d| be the width of the whatsit |p|
 24150  					d = 0
 24151  
 24152  				default:
 24153  					d = 0
 24154  				}
 24155  				if v < 07777777777 {
 24156  					v = v + d
 24157  				}
 24158  
 24159  				goto notFound
 24160  
 24161  			found:
 24162  				if v < 07777777777 {
 24163  					v = v + d
 24164  					w = v
 24165  				} else {
 24166  					w = 07777777777
 24167  					goto done
 24168  				}
 24169  
 24170  			notFound:
 24171  				p = *(*prg.mem[p].hh()).rh()
 24172  			}
 24173  
 24174  		done:
 24175  		}
 24176  		// now we are in vertical mode, working on the list that will contain the display
 24177  
 24178  		// Calculate the length, |l|, and the shift amount, |s|, of the display lines
 24179  		if int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh()) == 0 {
 24180  			if *prg.eqtb[dimenBase+hangIndentCode-1].int() != 0 && (*prg.eqtb[intBase+hangAfterCode-1].int() >= 0 && prg.curList.pgField+2 > *prg.eqtb[intBase+hangAfterCode-1].int() || prg.curList.pgField+1 < -*prg.eqtb[intBase+hangAfterCode-1].int()) {
 24181  				l = *prg.eqtb[dimenBase+hsizeCode-1].int() - abs(*prg.eqtb[dimenBase+hangIndentCode-1].int())
 24182  				if *prg.eqtb[dimenBase+hangIndentCode-1].int() > 0 {
 24183  					s = *prg.eqtb[dimenBase+hangIndentCode-1].int()
 24184  				} else {
 24185  					s = 0
 24186  				}
 24187  			} else {
 24188  				l = *prg.eqtb[dimenBase+hsizeCode-1].int()
 24189  				s = 0
 24190  			}
 24191  		} else {
 24192  			n = int32(*(*prg.mem[*(*prg.eqtb[parShapeLoc-1].hh()).rh()].hh()).lh())
 24193  			if prg.curList.pgField+2 >= n {
 24194  				p = uint16(int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh()) + 2*n)
 24195  			} else {
 24196  				p = uint16(int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh()) + 2*(prg.curList.pgField+2))
 24197  			}
 24198  			s = *prg.mem[int32(p)-1].int()
 24199  			l = *prg.mem[p].int()
 24200  		}
 24201  		prg.pushMath(groupCode(mathShiftGroup))
 24202  		prg.curList.modeField = int16(mmode)
 24203  		prg.eqWordDefine(halfword(intBase+curFamCode), -1)
 24204  
 24205  		prg.eqWordDefine(halfword(dimenBase+preDisplaySizeCode), w)
 24206  		prg.eqWordDefine(halfword(dimenBase+displayWidthCode), l)
 24207  		prg.eqWordDefine(halfword(dimenBase+displayIndentCode), s)
 24208  		if int32(*(*prg.eqtb[everyDisplayLoc-1].hh()).rh()) != 0 {
 24209  			prg.beginTokenList(*(*prg.eqtb[everyDisplayLoc-1].hh()).rh(), quarterword(everyDisplayText))
 24210  		}
 24211  		if int32(prg.nestPtr) == 1 {
 24212  			prg.buildPage()
 24213  		}
 24214  	} else {
 24215  		prg.backInput()
 24216  		// Go into ordinary math mode
 24217  		{
 24218  			prg.pushMath(groupCode(mathShiftGroup))
 24219  			prg.eqWordDefine(halfword(intBase+curFamCode), -1)
 24220  			if int32(*(*prg.eqtb[everyMathLoc-1].hh()).rh()) != 0 {
 24221  				prg.beginTokenList(*(*prg.eqtb[everyMathLoc-1].hh()).rh(), quarterword(everyMathText))
 24222  			}
 24223  		}
 24224  	}
 24225  }
 24226  
 24227  func (prg *prg) startEqNo() {
 24228  	*prg.saveStack[int32(prg.savePtr)+0].int() = int32(prg.curChr)
 24229  	prg.savePtr = uint16(int32(prg.savePtr) + 1)
 24230  
 24231  	// Go into ordinary math mode
 24232  	{
 24233  		prg.pushMath(groupCode(mathShiftGroup))
 24234  		prg.eqWordDefine(halfword(intBase+curFamCode), -1)
 24235  		if int32(*(*prg.eqtb[everyMathLoc-1].hh()).rh()) != 0 {
 24236  			prg.beginTokenList(*(*prg.eqtb[everyMathLoc-1].hh()).rh(), quarterword(everyMathText))
 24237  		}
 24238  	}
 24239  }
 24240  
 24241  func (prg *prg) scanMath(p halfword) {
 24242  	var (
 24243  		c int32 // math character code
 24244  	)
 24245  restart:
 24246  	for {
 24247  		prg.getXToken()
 24248  		if int32(prg.curCmd) != spacer && int32(prg.curCmd) != relax {
 24249  			break
 24250  		}
 24251  	}
 24252  
 24253  reswitch:
 24254  	switch prg.curCmd {
 24255  	case letter, otherChar, charGiven:
 24256  		c = int32(*(*prg.eqtb[mathCodeBase+int32(prg.curChr)-1].hh()).rh()) - 0
 24257  		if c == 0100000 {
 24258  			{
 24259  				prg.curCs = uint16(int32(prg.curChr) + activeBase)
 24260  				prg.curCmd = *(*prg.eqtb[prg.curCs-1].hh()).b0()
 24261  				prg.curChr = *(*prg.eqtb[prg.curCs-1].hh()).rh()
 24262  				prg.xToken()
 24263  				prg.backInput()
 24264  			}
 24265  
 24266  			goto restart
 24267  		}
 24268  
 24269  	case charNum:
 24270  		prg.scanCharNum()
 24271  		prg.curChr = uint16(prg.curVal)
 24272  		prg.curCmd = byte(charGiven)
 24273  
 24274  		goto reswitch
 24275  
 24276  	case mathCharNum:
 24277  		prg.scanFifteenBitInt()
 24278  		c = prg.curVal
 24279  
 24280  	case mathGiven:
 24281  		c = int32(prg.curChr)
 24282  	case delimNum:
 24283  		prg.scanTwentySevenBitInt()
 24284  		c = prg.curVal / 010000
 24285  
 24286  	default:
 24287  		prg.backInput()
 24288  		prg.scanLeftBrace()
 24289  
 24290  		*prg.saveStack[int32(prg.savePtr)+0].int() = int32(p)
 24291  		prg.savePtr = uint16(int32(prg.savePtr) + 1)
 24292  		prg.pushMath(groupCode(mathGroup))
 24293  		goto exit
 24294  
 24295  	}
 24296  
 24297  	*(*prg.mem[p].hh()).rh() = uint16(mathChar)
 24298  	*(*prg.mem[p].hh()).b1() = byte(c%256 + minQuarterword)
 24299  	if c >= 070000 && (*prg.eqtb[intBase+curFamCode-1].int() >= 0 && *prg.eqtb[intBase+curFamCode-1].int() < 16) {
 24300  		*(*prg.mem[p].hh()).b0() = byte(*prg.eqtb[intBase+curFamCode-1].int())
 24301  	} else {
 24302  		*(*prg.mem[p].hh()).b0() = byte(c / 256 % 16)
 24303  	}
 24304  
 24305  exit:
 24306  }
 24307  
 24308  func (prg *prg) setMathChar(c int32) {
 24309  	var (
 24310  		p halfword // the new noad
 24311  	)
 24312  	if c >= 0100000 {
 24313  		prg.curCs = uint16(int32(prg.curChr) + activeBase)
 24314  		prg.curCmd = *(*prg.eqtb[prg.curCs-1].hh()).b0()
 24315  		prg.curChr = *(*prg.eqtb[prg.curCs-1].hh()).rh()
 24316  		prg.xToken()
 24317  		prg.backInput()
 24318  	} else {
 24319  		p = prg.newNoad()
 24320  		*(*prg.mem[int32(p)+1].hh()).rh() = uint16(mathChar)
 24321  		*(*prg.mem[int32(p)+1].hh()).b1() = byte(c%256 + minQuarterword)
 24322  		*(*prg.mem[int32(p)+1].hh()).b0() = byte(c / 256 % 16)
 24323  		if c >= 070000 {
 24324  			if *prg.eqtb[intBase+curFamCode-1].int() >= 0 && *prg.eqtb[intBase+curFamCode-1].int() < 16 {
 24325  				*(*prg.mem[int32(p)+1].hh()).b0() = byte(*prg.eqtb[intBase+curFamCode-1].int())
 24326  			}
 24327  			*(*prg.mem[p].hh()).b0() = byte(ordNoad)
 24328  		} else {
 24329  			*(*prg.mem[p].hh()).b0() = byte(ordNoad + c/010000)
 24330  		}
 24331  		*(*prg.mem[prg.curList.tailField].hh()).rh() = p
 24332  		prg.curList.tailField = p
 24333  	}
 24334  }
 24335  
 24336  func (prg *prg) mathLimitSwitch() {
 24337  	if int32(prg.curList.headField) != int32(prg.curList.tailField) {
 24338  		if int32(*(*prg.mem[prg.curList.tailField].hh()).b0()) == opNoad {
 24339  			*(*prg.mem[prg.curList.tailField].hh()).b1() = byte(prg.curChr)
 24340  			goto exit
 24341  		}
 24342  	}
 24343  	{
 24344  		if int32(prg.interaction) == errorStopMode {
 24345  		}
 24346  		prg.printNl(strNumber( /* "! " */ 262))
 24347  		prg.print( /* "Limit controls must follow a math operator" */ 1130)
 24348  	}
 24349  	// \xref[Limit controls must follow...]
 24350  	{
 24351  		prg.helpPtr = 1
 24352  		prg.helpLine[0] = /* "I'm ignoring this misplaced \\limits or \\nolimits command." */ 1131
 24353  	}
 24354  	prg.error1()
 24355  
 24356  exit:
 24357  }
 24358  
 24359  func (prg *prg) scanDelimiter(p halfword, r1 bool) {
 24360  	if r1 {
 24361  		prg.scanTwentySevenBitInt()
 24362  	} else {
 24363  		for {
 24364  			prg.getXToken()
 24365  			if int32(prg.curCmd) != spacer && int32(prg.curCmd) != relax {
 24366  				break
 24367  			}
 24368  		}
 24369  		switch prg.curCmd {
 24370  		case letter, otherChar:
 24371  			prg.curVal = *prg.eqtb[delCodeBase+int32(prg.curChr)-1].int()
 24372  		case delimNum:
 24373  			prg.scanTwentySevenBitInt()
 24374  
 24375  		default:
 24376  			prg.curVal = -1
 24377  		}
 24378  	}
 24379  	if prg.curVal < 0 {
 24380  		{
 24381  			if int32(prg.interaction) == errorStopMode {
 24382  			}
 24383  			prg.printNl(strNumber( /* "! " */ 262))
 24384  			prg.print( /* "Missing delimiter (. inserted)" */ 1132)
 24385  		}
 24386  		// \xref[Missing delimiter...]
 24387  		{
 24388  			prg.helpPtr = 6
 24389  			prg.helpLine[5] = /* "I was expecting to see something like `(' or `\\[' or" */ 1133
 24390  			prg.helpLine[4] = /* "`\\]' here. If you typed, e.g., `[' instead of `\\[', you" */ 1134
 24391  			prg.helpLine[3] = /* "should probably delete the `[' by typing `1' now, so that" */ 1135
 24392  			prg.helpLine[2] = /* "braces don't get unbalanced. Otherwise just proceed." */ 1136
 24393  			prg.helpLine[1] = /* "Acceptable delimiters are characters whose \\delcode is" */ 1137
 24394  			prg.helpLine[0] = /* "nonnegative, or you can use `\\delimiter <delimiter code>'." */ 1138
 24395  		}
 24396  		prg.backError()
 24397  		prg.curVal = 0
 24398  	}
 24399  	(*prg.mem[p].qqqq()).b0 = byte(prg.curVal / 04000000 % 16)
 24400  	(*prg.mem[p].qqqq()).b1 = byte(prg.curVal/010000%256 + minQuarterword)
 24401  	(*prg.mem[p].qqqq()).b2 = byte(prg.curVal / 256 % 16)
 24402  	(*prg.mem[p].qqqq()).b3 = byte(prg.curVal%256 + minQuarterword)
 24403  }
 24404  
 24405  func (prg *prg) mathRadical() {
 24406  	{
 24407  		*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.getNode(radicalNoadSize)
 24408  		prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 24409  	}
 24410  	*(*prg.mem[prg.curList.tailField].hh()).b0() = byte(radicalNoad)
 24411  	*(*prg.mem[prg.curList.tailField].hh()).b1() = byte(normal)
 24412  	*prg.mem[int32(prg.curList.tailField)+1].hh() = prg.emptyField
 24413  	*prg.mem[int32(prg.curList.tailField)+3].hh() = prg.emptyField
 24414  	*prg.mem[int32(prg.curList.tailField)+2].hh() = prg.emptyField
 24415  	prg.scanDelimiter(halfword(int32(prg.curList.tailField)+4), true)
 24416  	prg.scanMath(halfword(int32(prg.curList.tailField) + 1))
 24417  }
 24418  
 24419  func (prg *prg) mathAc() {
 24420  	if int32(prg.curCmd) == accent {
 24421  		{
 24422  			if int32(prg.interaction) == errorStopMode {
 24423  			}
 24424  			prg.printNl(strNumber( /* "! " */ 262))
 24425  			prg.print( /* "Please use " */ 1139)
 24426  		}
 24427  		prg.printEsc(strNumber( /* "mathaccent" */ 523))
 24428  		prg.print( /* " for accents in math mode" */ 1140)
 24429  		// \xref[Please use \\mathaccent...]
 24430  		{
 24431  			prg.helpPtr = 2
 24432  			prg.helpLine[1] = /* "I'm changing \\accent to \\mathaccent here; wish me luck." */ 1141
 24433  			prg.helpLine[0] = /* "(Accents are not the same in formulas as they are in text.)" */ 1142
 24434  		}
 24435  		prg.error1()
 24436  	}
 24437  	{
 24438  		*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.getNode(accentNoadSize)
 24439  		prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 24440  	}
 24441  	*(*prg.mem[prg.curList.tailField].hh()).b0() = byte(accentNoad)
 24442  	*(*prg.mem[prg.curList.tailField].hh()).b1() = byte(normal)
 24443  	*prg.mem[int32(prg.curList.tailField)+1].hh() = prg.emptyField
 24444  	*prg.mem[int32(prg.curList.tailField)+3].hh() = prg.emptyField
 24445  	*prg.mem[int32(prg.curList.tailField)+2].hh() = prg.emptyField
 24446  	*(*prg.mem[int32(prg.curList.tailField)+4].hh()).rh() = uint16(mathChar)
 24447  	prg.scanFifteenBitInt()
 24448  	*(*prg.mem[int32(prg.curList.tailField)+4].hh()).b1() = byte(prg.curVal%256 + minQuarterword)
 24449  	if prg.curVal >= 070000 && (*prg.eqtb[intBase+curFamCode-1].int() >= 0 && *prg.eqtb[intBase+curFamCode-1].int() < 16) {
 24450  		*(*prg.mem[int32(prg.curList.tailField)+4].hh()).b0() = byte(*prg.eqtb[intBase+curFamCode-1].int())
 24451  	} else {
 24452  		*(*prg.mem[int32(prg.curList.tailField)+4].hh()).b0() = byte(prg.curVal / 256 % 16)
 24453  	}
 24454  	prg.scanMath(halfword(int32(prg.curList.tailField) + 1))
 24455  }
 24456  
 24457  func (prg *prg) appendChoices() {
 24458  	{
 24459  		*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newChoice()
 24460  		prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 24461  	}
 24462  	prg.savePtr = uint16(int32(prg.savePtr) + 1)
 24463  	*prg.saveStack[int32(prg.savePtr)+-1].int() = 0
 24464  	prg.pushMath(groupCode(mathChoiceGroup))
 24465  	prg.scanLeftBrace()
 24466  }
 24467  
 24468  // \4
 24469  // Declare the function called |fin_mlist|
 24470  func (prg *prg) finMlist(p halfword) (r halfword) {
 24471  	var (
 24472  		q halfword // the mlist to return
 24473  	)
 24474  	if *prg.curList.auxField.int() != 0 {
 24475  		*(*prg.mem[*prg.curList.auxField.int()+3].hh()).rh() = uint16(subMlist)
 24476  		*(*prg.mem[*prg.curList.auxField.int()+3].hh()).lh() = *(*prg.mem[prg.curList.headField].hh()).rh()
 24477  		if int32(p) == 0 {
 24478  			q = uint16(*prg.curList.auxField.int())
 24479  		} else {
 24480  			q = *(*prg.mem[*prg.curList.auxField.int()+2].hh()).lh()
 24481  			if int32(*(*prg.mem[q].hh()).b0()) != leftNoad {
 24482  				prg.confusion(strNumber( /* "right" */ 877))
 24483  			}
 24484  			// \xref[this can't happen right][\quad right]
 24485  			*(*prg.mem[*prg.curList.auxField.int()+2].hh()).lh() = *(*prg.mem[q].hh()).rh()
 24486  			*(*prg.mem[q].hh()).rh() = uint16(*prg.curList.auxField.int())
 24487  			*(*prg.mem[*prg.curList.auxField.int()].hh()).rh() = p
 24488  		}
 24489  	} else {
 24490  		*(*prg.mem[prg.curList.tailField].hh()).rh() = p
 24491  		q = *(*prg.mem[prg.curList.headField].hh()).rh()
 24492  	}
 24493  	prg.popNest()
 24494  	r = q
 24495  	return r
 24496  }
 24497  
 24498  //
 24499  
 24500  func (prg *prg) buildChoices() {
 24501  	var (
 24502  		p halfword // the current mlist
 24503  	)
 24504  	prg.unsave()
 24505  	p = prg.finMlist(halfword(0))
 24506  	switch *prg.saveStack[int32(prg.savePtr)+-1].int() {
 24507  	case 0:
 24508  		*(*prg.mem[int32(prg.curList.tailField)+1].hh()).lh() = p
 24509  	case 1:
 24510  		*(*prg.mem[int32(prg.curList.tailField)+1].hh()).rh() = p
 24511  	case 2:
 24512  		*(*prg.mem[int32(prg.curList.tailField)+2].hh()).lh() = p
 24513  	case 3:
 24514  		*(*prg.mem[int32(prg.curList.tailField)+2].hh()).rh() = p
 24515  		prg.savePtr = uint16(int32(prg.savePtr) - 1)
 24516  		goto exit
 24517  
 24518  	} // there are no other cases
 24519  	*prg.saveStack[int32(prg.savePtr)+-1].int() = *prg.saveStack[int32(prg.savePtr)+-1].int() + 1
 24520  	prg.pushMath(groupCode(mathChoiceGroup))
 24521  	prg.scanLeftBrace()
 24522  
 24523  exit:
 24524  }
 24525  
 24526  func (prg *prg) subSup() {
 24527  	var (
 24528  		t smallNumber // type of previous sub/superscript
 24529  		p halfword    // field to be filled by |scan_math|
 24530  	)
 24531  	t = byte(empty)
 24532  	p = 0
 24533  	if int32(prg.curList.tailField) != int32(prg.curList.headField) {
 24534  		if int32(*(*prg.mem[prg.curList.tailField].hh()).b0()) >= ordNoad && int32(*(*prg.mem[prg.curList.tailField].hh()).b0()) < leftNoad {
 24535  			p = uint16(int32(prg.curList.tailField) + 2 + int32(prg.curCmd) - supMark) // |supscr| or |subscr|
 24536  			t = byte(*(*prg.mem[p].hh()).rh())
 24537  		}
 24538  	}
 24539  	if int32(p) == 0 || int32(t) != empty {
 24540  		{
 24541  			*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newNoad()
 24542  			prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 24543  		}
 24544  		p = uint16(int32(prg.curList.tailField) + 2 + int32(prg.curCmd) - supMark) // |supscr| or |subscr|
 24545  		if int32(t) != empty {
 24546  			if int32(prg.curCmd) == supMark {
 24547  				{
 24548  					if int32(prg.interaction) == errorStopMode {
 24549  					}
 24550  					prg.printNl(strNumber( /* "! " */ 262))
 24551  					prg.print( /* "Double superscript" */ 1143)
 24552  				}
 24553  				// \xref[Double superscript]
 24554  				{
 24555  					prg.helpPtr = 1
 24556  					prg.helpLine[0] = /* "I treat `x^1^2' essentially like `x^1[]^2'." */ 1144
 24557  				}
 24558  			} else {
 24559  				{
 24560  					if int32(prg.interaction) == errorStopMode {
 24561  					}
 24562  					prg.printNl(strNumber( /* "! " */ 262))
 24563  					prg.print( /* "Double subscript" */ 1145)
 24564  				}
 24565  				// \xref[Double subscript]
 24566  				{
 24567  					prg.helpPtr = 1
 24568  					prg.helpLine[0] = /* "I treat `x_1_2' essentially like `x_1[]_2'." */ 1146
 24569  				}
 24570  			}
 24571  			prg.error1()
 24572  		}
 24573  	}
 24574  	prg.scanMath(p)
 24575  }
 24576  
 24577  func (prg *prg) mathFraction() {
 24578  	var (
 24579  		c smallNumber // the type of generalized fraction we are scanning
 24580  	)
 24581  	c = byte(prg.curChr)
 24582  	if *prg.curList.auxField.int() != 0 {
 24583  		if int32(c) >= delimitedCode {
 24584  			prg.scanDelimiter(halfword(30000-12), false)
 24585  			prg.scanDelimiter(halfword(30000-12), false)
 24586  		}
 24587  		if int32(c)%delimitedCode == aboveCode {
 24588  			prg.scanDimen(false, false, false)
 24589  		}
 24590  		{
 24591  			if int32(prg.interaction) == errorStopMode {
 24592  			}
 24593  			prg.printNl(strNumber( /* "! " */ 262))
 24594  			prg.print( /* "Ambiguous; you need another [ and ]" */ 1153)
 24595  		}
 24596  		// \xref[Ambiguous...]
 24597  		{
 24598  			prg.helpPtr = 3
 24599  			prg.helpLine[2] = /* "I'm ignoring this fraction specification, since I don't" */ 1154
 24600  			prg.helpLine[1] = /* "know whether a construction like `x \\over y \\over z'" */ 1155
 24601  			prg.helpLine[0] = /* "means `[x \\over y] \\over z' or `x \\over [y \\over z]'." */ 1156
 24602  		}
 24603  		prg.error1()
 24604  	} else {
 24605  		*prg.curList.auxField.int() = int32(prg.getNode(fractionNoadSize))
 24606  		*(*prg.mem[*prg.curList.auxField.int()].hh()).b0() = byte(fractionNoad)
 24607  		*(*prg.mem[*prg.curList.auxField.int()].hh()).b1() = byte(normal)
 24608  		*(*prg.mem[*prg.curList.auxField.int()+2].hh()).rh() = uint16(subMlist)
 24609  		*(*prg.mem[*prg.curList.auxField.int()+2].hh()).lh() = *(*prg.mem[prg.curList.headField].hh()).rh()
 24610  		*prg.mem[*prg.curList.auxField.int()+3].hh() = prg.emptyField
 24611  		*prg.mem[*prg.curList.auxField.int()+4].qqqq() = prg.nullDelimiter
 24612  		*prg.mem[*prg.curList.auxField.int()+5].qqqq() = prg.nullDelimiter
 24613  
 24614  		*(*prg.mem[prg.curList.headField].hh()).rh() = 0
 24615  		prg.curList.tailField = prg.curList.headField
 24616  
 24617  		// Use code |c| to distinguish between generalized fractions
 24618  		if int32(c) >= delimitedCode {
 24619  			prg.scanDelimiter(halfword(*prg.curList.auxField.int()+4), false)
 24620  			prg.scanDelimiter(halfword(*prg.curList.auxField.int()+5), false)
 24621  		}
 24622  		switch int32(c) % delimitedCode {
 24623  		case aboveCode:
 24624  			prg.scanDimen(false, false, false)
 24625  			*prg.mem[*prg.curList.auxField.int()+widthOffset].int() = prg.curVal
 24626  
 24627  		case overCode:
 24628  			*prg.mem[*prg.curList.auxField.int()+widthOffset].int() = 010000000000
 24629  		case atopCode:
 24630  			*prg.mem[*prg.curList.auxField.int()+widthOffset].int() = 0
 24631  		}
 24632  	}
 24633  }
 24634  
 24635  func (prg *prg) mathLeftRight() {
 24636  	var (
 24637  		t smallNumber // |left_noad| or |right_noad|
 24638  		p halfword    // new noad
 24639  	)
 24640  	t = byte(prg.curChr)
 24641  	if int32(t) == rightNoad && int32(prg.curGroup) != mathLeftGroup {
 24642  		if int32(prg.curGroup) == mathShiftGroup {
 24643  			prg.scanDelimiter(halfword(30000-12), false)
 24644  			{
 24645  				if int32(prg.interaction) == errorStopMode {
 24646  				}
 24647  				prg.printNl(strNumber( /* "! " */ 262))
 24648  				prg.print( /* "Extra " */ 777)
 24649  			}
 24650  			prg.printEsc(strNumber( /* "right" */ 877))
 24651  			// \xref[Extra \\right.]
 24652  			{
 24653  				prg.helpPtr = 1
 24654  				prg.helpLine[0] = /* "I'm ignoring a \\right that had no matching \\left." */ 1157
 24655  			}
 24656  			prg.error1()
 24657  		} else {
 24658  			prg.offSave()
 24659  		}
 24660  	} else {
 24661  		p = prg.newNoad()
 24662  		*(*prg.mem[p].hh()).b0() = t
 24663  		prg.scanDelimiter(halfword(int32(p)+1), false)
 24664  		if int32(t) == leftNoad {
 24665  			prg.pushMath(groupCode(mathLeftGroup))
 24666  			*(*prg.mem[prg.curList.headField].hh()).rh() = p
 24667  			prg.curList.tailField = p
 24668  		} else {
 24669  			p = prg.finMlist(p)
 24670  			prg.unsave() // end of |math_left_group|
 24671  			{
 24672  				*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newNoad()
 24673  				prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 24674  			}
 24675  			*(*prg.mem[prg.curList.tailField].hh()).b0() = byte(innerNoad)
 24676  			*(*prg.mem[int32(prg.curList.tailField)+1].hh()).rh() = uint16(subMlist)
 24677  			*(*prg.mem[int32(prg.curList.tailField)+1].hh()).lh() = p
 24678  		}
 24679  	}
 24680  }
 24681  
 24682  func (prg *prg) afterMath() {
 24683  	var (
 24684  		l      bool     // `\.[\\leqno]' instead of `\.[\\eqno]'
 24685  		danger bool     // not enough symbol fonts are present
 24686  		m      int32    // |mmode| or |-mmode|
 24687  		p      halfword // the formula
 24688  		a      halfword // box containing equation number
 24689  
 24690  		// Local variables for finishing a displayed formula
 24691  		b      halfword    // box containing the equation
 24692  		w      scaled      // width of the equation
 24693  		z      scaled      // width of the line
 24694  		e      scaled      // width of equation number
 24695  		q      scaled      // width of equation number plus space to separate from equation
 24696  		d      scaled      // displacement of equation in the line
 24697  		s      scaled      // move the line right this much
 24698  		g1, g2 smallNumber // glue parameter codes for before and after
 24699  		r1     halfword    // kern node used to position the display
 24700  		t      halfword    // tail of adjustment list
 24701  	)
 24702  	danger = false
 24703  
 24704  	// Check that the necessary fonts for math symbols are present; if not, flush the current math lists and set |danger:=true|
 24705  	if int32(prg.fontParams[*(*prg.eqtb[mathFontBase+2+textSize-1].hh()).rh()]) < totalMathsyParams || int32(prg.fontParams[*(*prg.eqtb[mathFontBase+2+scriptSize-1].hh()).rh()]) < totalMathsyParams || int32(prg.fontParams[*(*prg.eqtb[mathFontBase+2+scriptScriptSize-1].hh()).rh()]) < totalMathsyParams {
 24706  		{
 24707  			if int32(prg.interaction) == errorStopMode {
 24708  			}
 24709  			prg.printNl(strNumber( /* "! " */ 262))
 24710  			prg.print( /* "Math formula deleted: Insufficient symbol fonts" */ 1158)
 24711  		}
 24712  
 24713  		// \xref[Math formula deleted...]
 24714  		{
 24715  			prg.helpPtr = 3
 24716  			prg.helpLine[2] = /* "Sorry, but I can't typeset math unless \\textfont 2" */ 1159
 24717  			prg.helpLine[1] = /* "and \\scriptfont 2 and \\scriptscriptfont 2 have all" */ 1160
 24718  			prg.helpLine[0] = /* "the \\fontdimen values needed in math symbol fonts." */ 1161
 24719  		}
 24720  		prg.error1()
 24721  		prg.flushMath()
 24722  		danger = true
 24723  	} else if int32(prg.fontParams[*(*prg.eqtb[mathFontBase+3+textSize-1].hh()).rh()]) < totalMathexParams || int32(prg.fontParams[*(*prg.eqtb[mathFontBase+3+scriptSize-1].hh()).rh()]) < totalMathexParams || int32(prg.fontParams[*(*prg.eqtb[mathFontBase+3+scriptScriptSize-1].hh()).rh()]) < totalMathexParams {
 24724  		{
 24725  			if int32(prg.interaction) == errorStopMode {
 24726  			}
 24727  			prg.printNl(strNumber( /* "! " */ 262))
 24728  			prg.print( /* "Math formula deleted: Insufficient extension fonts" */ 1162)
 24729  		}
 24730  
 24731  		{
 24732  			prg.helpPtr = 3
 24733  			prg.helpLine[2] = /* "Sorry, but I can't typeset math unless \\textfont 3" */ 1163
 24734  			prg.helpLine[1] = /* "and \\scriptfont 3 and \\scriptscriptfont 3 have all" */ 1164
 24735  			prg.helpLine[0] = /* "the \\fontdimen values needed in math extension fonts." */ 1165
 24736  		}
 24737  		prg.error1()
 24738  		prg.flushMath()
 24739  		danger = true
 24740  	}
 24741  	m = int32(prg.curList.modeField)
 24742  	l = false
 24743  	p = prg.finMlist(halfword(0)) // this pops the nest
 24744  	if int32(prg.curList.modeField) == -m {
 24745  		{
 24746  			prg.getXToken()
 24747  			if int32(prg.curCmd) != mathShift {
 24748  				{
 24749  					if int32(prg.interaction) == errorStopMode {
 24750  					}
 24751  					prg.printNl(strNumber( /* "! " */ 262))
 24752  					prg.print( /* "Display math should end with $$" */ 1166)
 24753  				}
 24754  				// \xref[Display math...with \$\$]
 24755  				{
 24756  					prg.helpPtr = 2
 24757  					prg.helpLine[1] = /* "The `$' that I just saw supposedly matches a previous `$$'." */ 1167
 24758  					prg.helpLine[0] = /* "So I shall assume that you typed `$$' both times." */ 1168
 24759  				}
 24760  				prg.backError()
 24761  			}
 24762  		}
 24763  		prg.curMlist = p
 24764  		prg.curStyle = byte(textStyle)
 24765  		prg.mlistPenalties = false
 24766  		prg.mlistToHlist()
 24767  		a = prg.hpack(*(*prg.mem[30000-3].hh()).rh(), scaled(0), smallNumber(additional))
 24768  		prg.unsave()
 24769  		prg.savePtr = uint16(int32(prg.savePtr) - 1) // now |cur_group=math_shift_group|
 24770  		if *prg.saveStack[int32(prg.savePtr)+0].int() == 1 {
 24771  			l = true
 24772  		}
 24773  		danger = false
 24774  
 24775  		// Check that the necessary fonts for math symbols are present; if not, flush the current math lists and set |danger:=true|
 24776  		if int32(prg.fontParams[*(*prg.eqtb[mathFontBase+2+textSize-1].hh()).rh()]) < totalMathsyParams || int32(prg.fontParams[*(*prg.eqtb[mathFontBase+2+scriptSize-1].hh()).rh()]) < totalMathsyParams || int32(prg.fontParams[*(*prg.eqtb[mathFontBase+2+scriptScriptSize-1].hh()).rh()]) < totalMathsyParams {
 24777  			{
 24778  				if int32(prg.interaction) == errorStopMode {
 24779  				}
 24780  				prg.printNl(strNumber( /* "! " */ 262))
 24781  				prg.print( /* "Math formula deleted: Insufficient symbol fonts" */ 1158)
 24782  			}
 24783  
 24784  			// \xref[Math formula deleted...]
 24785  			{
 24786  				prg.helpPtr = 3
 24787  				prg.helpLine[2] = /* "Sorry, but I can't typeset math unless \\textfont 2" */ 1159
 24788  				prg.helpLine[1] = /* "and \\scriptfont 2 and \\scriptscriptfont 2 have all" */ 1160
 24789  				prg.helpLine[0] = /* "the \\fontdimen values needed in math symbol fonts." */ 1161
 24790  			}
 24791  			prg.error1()
 24792  			prg.flushMath()
 24793  			danger = true
 24794  		} else if int32(prg.fontParams[*(*prg.eqtb[mathFontBase+3+textSize-1].hh()).rh()]) < totalMathexParams || int32(prg.fontParams[*(*prg.eqtb[mathFontBase+3+scriptSize-1].hh()).rh()]) < totalMathexParams || int32(prg.fontParams[*(*prg.eqtb[mathFontBase+3+scriptScriptSize-1].hh()).rh()]) < totalMathexParams {
 24795  			{
 24796  				if int32(prg.interaction) == errorStopMode {
 24797  				}
 24798  				prg.printNl(strNumber( /* "! " */ 262))
 24799  				prg.print( /* "Math formula deleted: Insufficient extension fonts" */ 1162)
 24800  			}
 24801  
 24802  			{
 24803  				prg.helpPtr = 3
 24804  				prg.helpLine[2] = /* "Sorry, but I can't typeset math unless \\textfont 3" */ 1163
 24805  				prg.helpLine[1] = /* "and \\scriptfont 3 and \\scriptscriptfont 3 have all" */ 1164
 24806  				prg.helpLine[0] = /* "the \\fontdimen values needed in math extension fonts." */ 1165
 24807  			}
 24808  			prg.error1()
 24809  			prg.flushMath()
 24810  			danger = true
 24811  		}
 24812  		m = int32(prg.curList.modeField)
 24813  		p = prg.finMlist(halfword(0))
 24814  	} else {
 24815  		a = 0
 24816  	}
 24817  	if m < 0 {
 24818  		{
 24819  			*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newMath(*prg.eqtb[dimenBase+mathSurroundCode-1].int(), smallNumber(before))
 24820  			prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 24821  		}
 24822  		prg.curMlist = p
 24823  		prg.curStyle = byte(textStyle)
 24824  		prg.mlistPenalties = int32(prg.curList.modeField) > 0
 24825  		prg.mlistToHlist()
 24826  		*(*prg.mem[prg.curList.tailField].hh()).rh() = *(*prg.mem[30000-3].hh()).rh()
 24827  		for int32(*(*prg.mem[prg.curList.tailField].hh()).rh()) != 0 {
 24828  			prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 24829  		}
 24830  		{
 24831  			*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newMath(*prg.eqtb[dimenBase+mathSurroundCode-1].int(), smallNumber(after))
 24832  			prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 24833  		}
 24834  		*(*prg.curList.auxField.hh()).lh() = 1000
 24835  		prg.unsave()
 24836  	} else {
 24837  		if int32(a) == 0 {
 24838  			prg.getXToken()
 24839  			if int32(prg.curCmd) != mathShift {
 24840  				{
 24841  					if int32(prg.interaction) == errorStopMode {
 24842  					}
 24843  					prg.printNl(strNumber( /* "! " */ 262))
 24844  					prg.print( /* "Display math should end with $$" */ 1166)
 24845  				}
 24846  				// \xref[Display math...with \$\$]
 24847  				{
 24848  					prg.helpPtr = 2
 24849  					prg.helpLine[1] = /* "The `$' that I just saw supposedly matches a previous `$$'." */ 1167
 24850  					prg.helpLine[0] = /* "So I shall assume that you typed `$$' both times." */ 1168
 24851  				}
 24852  				prg.backError()
 24853  			}
 24854  		}
 24855  
 24856  		// Finish displayed math
 24857  		prg.curMlist = p
 24858  		prg.curStyle = byte(displayStyle)
 24859  		prg.mlistPenalties = false
 24860  		prg.mlistToHlist()
 24861  		p = *(*prg.mem[30000-3].hh()).rh()
 24862  
 24863  		prg.adjustTail = uint16(30000 - 5)
 24864  		b = prg.hpack(p, scaled(0), smallNumber(additional))
 24865  		p = *(*prg.mem[int32(b)+listOffset].hh()).rh()
 24866  		t = prg.adjustTail
 24867  		prg.adjustTail = 0
 24868  
 24869  		w = *prg.mem[int32(b)+widthOffset].int()
 24870  		z = *prg.eqtb[dimenBase+displayWidthCode-1].int()
 24871  		s = *prg.eqtb[dimenBase+displayIndentCode-1].int()
 24872  		if int32(a) == 0 || danger {
 24873  			e = 0
 24874  			q = 0
 24875  		} else {
 24876  			e = *prg.mem[int32(a)+widthOffset].int()
 24877  			q = e + *prg.fontInfo[6+prg.paramBase[*(*prg.eqtb[mathFontBase+2+textSize-1].hh()).rh()]].int()
 24878  		}
 24879  		if w+q > z {
 24880  			if e != 0 && (w-prg.totalShrink[normal]+q <= z || prg.totalShrink[fil] != 0 || prg.totalShrink[fill] != 0 || prg.totalShrink[filll] != 0) {
 24881  				prg.freeNode(b, halfword(boxNodeSize))
 24882  				b = prg.hpack(p, z-q, smallNumber(exactly))
 24883  			} else {
 24884  				e = 0
 24885  				if w > z {
 24886  					prg.freeNode(b, halfword(boxNodeSize))
 24887  					b = prg.hpack(p, z, smallNumber(exactly))
 24888  				}
 24889  			}
 24890  			w = *prg.mem[int32(b)+widthOffset].int()
 24891  		}
 24892  
 24893  		// Determine the displacement, |d|, of the left edge of the equation, with respect to the line size |z|, assuming that |l=false|
 24894  		d = prg.half(z - w)
 24895  		if e > 0 && d < 2*e {
 24896  			d = prg.half(z - w - e)
 24897  			if int32(p) != 0 {
 24898  				if !(int32(p) >= int32(prg.hiMemMin)) {
 24899  					if int32(*(*prg.mem[p].hh()).b0()) == glueNode {
 24900  						d = 0
 24901  					}
 24902  				}
 24903  			}
 24904  		}
 24905  
 24906  		// Append the glue or equation number preceding the display
 24907  		{
 24908  			*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newPenalty(*prg.eqtb[intBase+preDisplayPenaltyCode-1].int())
 24909  			prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 24910  		}
 24911  
 24912  		if d+s <= *prg.eqtb[dimenBase+preDisplaySizeCode-1].int() || l {
 24913  			g1 = byte(aboveDisplaySkipCode)
 24914  			g2 = byte(belowDisplaySkipCode)
 24915  		} else {
 24916  			g1 = byte(aboveDisplayShortSkipCode)
 24917  			g2 = byte(belowDisplayShortSkipCode)
 24918  		}
 24919  		if l && e == 0 {
 24920  			*prg.mem[int32(a)+4].int() = s
 24921  			prg.appendToVlist(a)
 24922  			{
 24923  				*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newPenalty(infPenalty)
 24924  				prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 24925  			}
 24926  		} else {
 24927  			*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newParamGlue(g1)
 24928  			prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 24929  		}
 24930  
 24931  		// Append the display and perhaps also the equation number
 24932  		if e != 0 {
 24933  			r1 = prg.newKern(z - w - e - d)
 24934  			if l {
 24935  				*(*prg.mem[a].hh()).rh() = r1
 24936  				*(*prg.mem[r1].hh()).rh() = b
 24937  				b = a
 24938  				d = 0
 24939  			} else {
 24940  				*(*prg.mem[b].hh()).rh() = r1
 24941  				*(*prg.mem[r1].hh()).rh() = a
 24942  			}
 24943  			b = prg.hpack(b, scaled(0), smallNumber(additional))
 24944  		}
 24945  		*prg.mem[int32(b)+4].int() = s + d
 24946  		prg.appendToVlist(b)
 24947  
 24948  		// Append the glue or equation number following the display
 24949  		if int32(a) != 0 && e == 0 && !l {
 24950  			{
 24951  				*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newPenalty(infPenalty)
 24952  				prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 24953  			}
 24954  			*prg.mem[int32(a)+4].int() = s + z - *prg.mem[int32(a)+widthOffset].int()
 24955  			prg.appendToVlist(a)
 24956  			g2 = 0
 24957  		}
 24958  		if int32(t) != 30000-5 {
 24959  			*(*prg.mem[prg.curList.tailField].hh()).rh() = *(*prg.mem[30000-5].hh()).rh()
 24960  			prg.curList.tailField = t
 24961  		}
 24962  		{
 24963  			*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newPenalty(*prg.eqtb[intBase+postDisplayPenaltyCode-1].int())
 24964  			prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 24965  		}
 24966  		if int32(g2) > 0 {
 24967  			*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newParamGlue(g2)
 24968  			prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 24969  		}
 24970  		prg.resumeAfterDisplay()
 24971  	}
 24972  } // \2
 24973  
 24974  func (prg *prg) resumeAfterDisplay() {
 24975  	if int32(prg.curGroup) != mathShiftGroup {
 24976  		prg.confusion(strNumber( /* "display" */ 1169))
 24977  	}
 24978  	// \xref[this can't happen display][\quad display]
 24979  	prg.unsave()
 24980  	prg.curList.pgField = prg.curList.pgField + 3
 24981  	prg.pushNest()
 24982  	prg.curList.modeField = int16(hmode)
 24983  	*(*prg.curList.auxField.hh()).lh() = 1000
 24984  	if *prg.eqtb[intBase+languageCode-1].int() <= 0 {
 24985  		prg.curLang = 0
 24986  	} else if *prg.eqtb[intBase+languageCode-1].int() > 255 {
 24987  		prg.curLang = 0
 24988  	} else {
 24989  		prg.curLang = byte(*prg.eqtb[intBase+languageCode-1].int())
 24990  	}
 24991  	*(*prg.curList.auxField.hh()).rh() = uint16(prg.curLang)
 24992  	prg.curList.pgField = (int32(prg.normMin(*prg.eqtb[intBase+leftHyphenMinCode-1].int()))*0100+int32(prg.normMin(*prg.eqtb[intBase+rightHyphenMinCode-1].int())))*0200000 + int32(prg.curLang)
 24993  
 24994  	// Scan an optional space
 24995  	{
 24996  		prg.getXToken()
 24997  		if int32(prg.curCmd) != spacer {
 24998  			prg.backInput()
 24999  		}
 25000  	}
 25001  	if int32(prg.nestPtr) == 1 {
 25002  		prg.buildPage()
 25003  	}
 25004  }
 25005  
 25006  // \4
 25007  // Declare subprocedures for |prefixed_command|
 25008  func (prg *prg) getRToken() {
 25009  restart:
 25010  	for {
 25011  		prg.getToken()
 25012  		if int32(prg.curTok) != spaceToken {
 25013  			break
 25014  		}
 25015  	}
 25016  	if int32(prg.curCs) == 0 || int32(prg.curCs) > frozenControlSequence {
 25017  		{
 25018  			if int32(prg.interaction) == errorStopMode {
 25019  			}
 25020  			prg.printNl(strNumber( /* "! " */ 262))
 25021  			prg.print( /* "Missing control sequence inserted" */ 1184)
 25022  		}
 25023  		// \xref[Missing control...]
 25024  		{
 25025  			prg.helpPtr = 5
 25026  			prg.helpLine[4] = /* "Please don't say `\\def cs[...]', say `\\def\\cs[...]'." */ 1185
 25027  			prg.helpLine[3] = /* "I've inserted an inaccessible control sequence so that your" */ 1186
 25028  			prg.helpLine[2] = /* "definition will be completed without mixing me up too badly." */ 1187
 25029  			prg.helpLine[1] = /* "You can recover graciously from this error, if you're" */ 1188
 25030  			prg.helpLine[0] = /* "careful; see exercise 27.2 in The TeXbook." */ 1189
 25031  		}
 25032  		// \xref[TeXbook][\sl The \TeX book]
 25033  		if int32(prg.curCs) == 0 {
 25034  			prg.backInput()
 25035  		}
 25036  		prg.curTok = uint16(07777 + frozenProtection)
 25037  		prg.insError()
 25038  		goto restart
 25039  	}
 25040  }
 25041  
 25042  func (prg *prg) trapZeroGlue() {
 25043  	if *prg.mem[prg.curVal+widthOffset].int() == 0 && *prg.mem[prg.curVal+2].int() == 0 && *prg.mem[prg.curVal+3].int() == 0 {
 25044  		*(*prg.mem[memBot].hh()).rh() = uint16(int32(*(*prg.mem[memBot].hh()).rh()) + 1)
 25045  		prg.deleteGlueRef(halfword(prg.curVal))
 25046  		prg.curVal = memBot
 25047  	}
 25048  }
 25049  
 25050  func (prg *prg) doRegisterCommand(a smallNumber) {
 25051  	var (
 25052  		l, q, r1, s               halfword // for list manipulation
 25053  		p/* intVal..muVal */ byte          // type of register involved
 25054  	)
 25055  	q = uint16(prg.curCmd)
 25056  
 25057  	// Compute the register location |l| and its type |p|; but |return| if invalid
 25058  	{
 25059  		if int32(q) != register {
 25060  			prg.getXToken()
 25061  			if int32(prg.curCmd) >= assignInt && int32(prg.curCmd) <= assignMuGlue {
 25062  				l = prg.curChr
 25063  				p = byte(int32(prg.curCmd) - assignInt)
 25064  				goto found
 25065  			}
 25066  			if int32(prg.curCmd) != register {
 25067  				{
 25068  					if int32(prg.interaction) == errorStopMode {
 25069  					}
 25070  					prg.printNl(strNumber( /* "! " */ 262))
 25071  					prg.print( /* "You can't use `" */ 685)
 25072  				}
 25073  				prg.printCmdChr(prg.curCmd, prg.curChr)
 25074  				// \xref[You can't use x after ...]
 25075  				prg.print( /* "' after " */ 686)
 25076  				prg.printCmdChr(quarterword(q), halfword(0))
 25077  				{
 25078  					prg.helpPtr = 1
 25079  					prg.helpLine[0] = /* "I'm forgetting what you said and not changing anything." */ 1210
 25080  				}
 25081  				prg.error1()
 25082  				goto exit
 25083  			}
 25084  		}
 25085  		p = byte(prg.curChr)
 25086  		prg.scanEightBitInt()
 25087  		switch p {
 25088  		case intVal:
 25089  			l = uint16(prg.curVal + countBase)
 25090  		case dimenVal:
 25091  			l = uint16(prg.curVal + scaledBase)
 25092  		case glueVal:
 25093  			l = uint16(prg.curVal + skipBase)
 25094  		case muVal:
 25095  			l = uint16(prg.curVal + muSkipBase)
 25096  		} // there are no other cases
 25097  	}
 25098  
 25099  found:
 25100  	;
 25101  	if int32(q) == register {
 25102  		prg.scanOptionalEquals()
 25103  	} else if prg.scanKeyword(strNumber( /* "by" */ 1206)) {
 25104  	} // optional `\.[by]'
 25105  	// \xref[by]
 25106  	prg.arithError = false
 25107  	if int32(q) < multiply {
 25108  		if int32(p) < glueVal {
 25109  			if int32(p) == intVal {
 25110  				prg.scanInt()
 25111  			} else {
 25112  				prg.scanDimen(false, false, false)
 25113  			}
 25114  			if int32(q) == advance {
 25115  				prg.curVal = prg.curVal + *prg.eqtb[l-1].int()
 25116  			}
 25117  		} else {
 25118  			prg.scanGlue(p)
 25119  			if int32(q) == advance {
 25120  				q = prg.newSpec(halfword(prg.curVal))
 25121  				r1 = *(*prg.eqtb[l-1].hh()).rh()
 25122  				prg.deleteGlueRef(halfword(prg.curVal))
 25123  				*prg.mem[int32(q)+widthOffset].int() = *prg.mem[int32(q)+widthOffset].int() + *prg.mem[int32(r1)+widthOffset].int()
 25124  				if *prg.mem[int32(q)+2].int() == 0 {
 25125  					*(*prg.mem[q].hh()).b0() = byte(normal)
 25126  				}
 25127  				if int32(*(*prg.mem[q].hh()).b0()) == int32(*(*prg.mem[r1].hh()).b0()) {
 25128  					*prg.mem[int32(q)+2].int() = *prg.mem[int32(q)+2].int() + *prg.mem[int32(r1)+2].int()
 25129  				} else if int32(*(*prg.mem[q].hh()).b0()) < int32(*(*prg.mem[r1].hh()).b0()) && *prg.mem[int32(r1)+2].int() != 0 {
 25130  					*prg.mem[int32(q)+2].int() = *prg.mem[int32(r1)+2].int()
 25131  					*(*prg.mem[q].hh()).b0() = *(*prg.mem[r1].hh()).b0()
 25132  				}
 25133  				if *prg.mem[int32(q)+3].int() == 0 {
 25134  					*(*prg.mem[q].hh()).b1() = byte(normal)
 25135  				}
 25136  				if int32(*(*prg.mem[q].hh()).b1()) == int32(*(*prg.mem[r1].hh()).b1()) {
 25137  					*prg.mem[int32(q)+3].int() = *prg.mem[int32(q)+3].int() + *prg.mem[int32(r1)+3].int()
 25138  				} else if int32(*(*prg.mem[q].hh()).b1()) < int32(*(*prg.mem[r1].hh()).b1()) && *prg.mem[int32(r1)+3].int() != 0 {
 25139  					*prg.mem[int32(q)+3].int() = *prg.mem[int32(r1)+3].int()
 25140  					*(*prg.mem[q].hh()).b1() = *(*prg.mem[r1].hh()).b1()
 25141  				}
 25142  				prg.curVal = int32(q)
 25143  			}
 25144  		}
 25145  	} else {
 25146  		// Compute result of |multiply| or |divide|, put it in |cur_val|
 25147  		prg.scanInt()
 25148  		if int32(p) < glueVal {
 25149  			if int32(q) == multiply {
 25150  				if int32(p) == intVal {
 25151  					prg.curVal = prg.multAndAdd(*prg.eqtb[l-1].int(), prg.curVal, scaled(0), scaled(017777777777))
 25152  				} else {
 25153  					prg.curVal = prg.multAndAdd(*prg.eqtb[l-1].int(), prg.curVal, scaled(0), scaled(07777777777))
 25154  				}
 25155  			} else {
 25156  				prg.curVal = prg.xOverN(*prg.eqtb[l-1].int(), prg.curVal)
 25157  			}
 25158  		} else {
 25159  			s = *(*prg.eqtb[l-1].hh()).rh()
 25160  			r1 = prg.newSpec(s)
 25161  			if int32(q) == multiply {
 25162  				*prg.mem[int32(r1)+widthOffset].int() = prg.multAndAdd(*prg.mem[int32(s)+widthOffset].int(), prg.curVal, scaled(0), scaled(07777777777))
 25163  				*prg.mem[int32(r1)+2].int() = prg.multAndAdd(*prg.mem[int32(s)+2].int(), prg.curVal, scaled(0), scaled(07777777777))
 25164  				*prg.mem[int32(r1)+3].int() = prg.multAndAdd(*prg.mem[int32(s)+3].int(), prg.curVal, scaled(0), scaled(07777777777))
 25165  			} else {
 25166  				*prg.mem[int32(r1)+widthOffset].int() = prg.xOverN(*prg.mem[int32(s)+widthOffset].int(), prg.curVal)
 25167  				*prg.mem[int32(r1)+2].int() = prg.xOverN(*prg.mem[int32(s)+2].int(), prg.curVal)
 25168  				*prg.mem[int32(r1)+3].int() = prg.xOverN(*prg.mem[int32(s)+3].int(), prg.curVal)
 25169  			}
 25170  			prg.curVal = int32(r1)
 25171  		}
 25172  	}
 25173  	if prg.arithError {
 25174  		{
 25175  			if int32(prg.interaction) == errorStopMode {
 25176  			}
 25177  			prg.printNl(strNumber( /* "! " */ 262))
 25178  			prg.print( /* "Arithmetic overflow" */ 1207)
 25179  		}
 25180  		// \xref[Arithmetic overflow]
 25181  		{
 25182  			prg.helpPtr = 2
 25183  			prg.helpLine[1] = /* "I can't carry out that multiplication or division," */ 1208
 25184  			prg.helpLine[0] = /* "since the result is out of range." */ 1209
 25185  		}
 25186  		if int32(p) >= glueVal {
 25187  			prg.deleteGlueRef(halfword(prg.curVal))
 25188  		}
 25189  		prg.error1()
 25190  		goto exit
 25191  	}
 25192  	if int32(p) < glueVal {
 25193  		if int32(a) >= 4 {
 25194  			prg.geqWordDefine(l, prg.curVal)
 25195  		} else {
 25196  			prg.eqWordDefine(l, prg.curVal)
 25197  		}
 25198  	} else {
 25199  		prg.trapZeroGlue()
 25200  		if int32(a) >= 4 {
 25201  			prg.geqDefine(l, quarterword(glueRef), halfword(prg.curVal))
 25202  		} else {
 25203  			prg.eqDefine(l, quarterword(glueRef), halfword(prg.curVal))
 25204  		}
 25205  	}
 25206  
 25207  exit:
 25208  }
 25209  
 25210  func (prg *prg) alterAux() {
 25211  	var (
 25212  		c halfword // |hmode| or |vmode|
 25213  	)
 25214  	if int32(prg.curChr) != abs(int32(prg.curList.modeField)) {
 25215  		prg.reportIllegalCase()
 25216  	} else {
 25217  		c = prg.curChr
 25218  		prg.scanOptionalEquals()
 25219  		if int32(c) == vmode {
 25220  			prg.scanDimen(false, false, false)
 25221  			*prg.curList.auxField.int() = prg.curVal
 25222  		} else {
 25223  			prg.scanInt()
 25224  			if prg.curVal <= 0 || prg.curVal > 32767 {
 25225  				{
 25226  					if int32(prg.interaction) == errorStopMode {
 25227  					}
 25228  					prg.printNl(strNumber( /* "! " */ 262))
 25229  					prg.print( /* "Bad space factor" */ 1213)
 25230  				}
 25231  				// \xref[Bad space factor]
 25232  				{
 25233  					prg.helpPtr = 1
 25234  					prg.helpLine[0] = /* "I allow only values in the range 1..32767 here." */ 1214
 25235  				}
 25236  				prg.intError(prg.curVal)
 25237  			} else {
 25238  				*(*prg.curList.auxField.hh()).lh() = uint16(prg.curVal)
 25239  			}
 25240  		}
 25241  	}
 25242  }
 25243  
 25244  func (prg *prg) alterPrevGraf() {
 25245  	var (
 25246  		p /* 0..nestSize */ byte // index into |nest|
 25247  	)
 25248  	prg.nest[prg.nestPtr] = prg.curList
 25249  	p = prg.nestPtr
 25250  	for abs(int32(prg.nest[p].modeField)) != vmode {
 25251  		p = byte(int32(p) - 1)
 25252  	}
 25253  	prg.scanOptionalEquals()
 25254  	prg.scanInt()
 25255  	if prg.curVal < 0 {
 25256  		{
 25257  			if int32(prg.interaction) == errorStopMode {
 25258  			}
 25259  			prg.printNl(strNumber( /* "! " */ 262))
 25260  			prg.print( /* "Bad " */ 955)
 25261  		}
 25262  		prg.printEsc(strNumber( /* "prevgraf" */ 532))
 25263  		// \xref[Bad \\prevgraf]
 25264  		{
 25265  			prg.helpPtr = 1
 25266  			prg.helpLine[0] = /* "I allow only nonnegative values here." */ 1215
 25267  		}
 25268  		prg.intError(prg.curVal)
 25269  	} else {
 25270  		prg.nest[p].pgField = prg.curVal
 25271  		prg.curList = prg.nest[prg.nestPtr]
 25272  	}
 25273  }
 25274  
 25275  func (prg *prg) alterPageSoFar() {
 25276  	var (
 25277  		c /* 0..7 */ byte // index into |page_so_far|
 25278  	)
 25279  	c = byte(prg.curChr)
 25280  	prg.scanOptionalEquals()
 25281  	prg.scanDimen(false, false, false)
 25282  	prg.pageSoFar[c] = prg.curVal
 25283  }
 25284  
 25285  func (prg *prg) alterInteger() {
 25286  	var (
 25287  		c /* 0..1 */ byte // 0 for \.[\\deadcycles], 1 for \.[\\insertpenalties]
 25288  	)
 25289  	c = byte(prg.curChr)
 25290  	prg.scanOptionalEquals()
 25291  	prg.scanInt()
 25292  	if int32(c) == 0 {
 25293  		prg.deadCycles = prg.curVal
 25294  	} else {
 25295  		prg.insertPenalties = prg.curVal
 25296  	}
 25297  }
 25298  
 25299  func (prg *prg) alterBoxDimen() {
 25300  	var (
 25301  		c smallNumber // |width_offset| or |height_offset| or |depth_offset|
 25302  		b eightBits   // box number
 25303  	)
 25304  	c = byte(prg.curChr)
 25305  	prg.scanEightBitInt()
 25306  	b = byte(prg.curVal)
 25307  	prg.scanOptionalEquals()
 25308  	prg.scanDimen(false, false, false)
 25309  	if int32(*(*prg.eqtb[boxBase+int32(b)-1].hh()).rh()) != 0 {
 25310  		*prg.mem[int32(*(*prg.eqtb[boxBase+int32(b)-1].hh()).rh())+int32(c)].int() = prg.curVal
 25311  	}
 25312  }
 25313  
 25314  func (prg *prg) newFont(a smallNumber) {
 25315  	var (
 25316  		u                                   halfword           // user's font identifier
 25317  		s                                   scaled             // stated ``at'' size, or negative of scaled magnification
 25318  		f                                   internalFontNumber // runs through existing fonts
 25319  		t                                   strNumber          // name for the frozen font identifier
 25320  		oldSetting/* 0..maxSelector */ byte                    // holds |selector| setting
 25321  		flushableString                     strNumber          // string not yet referenced
 25322  	)
 25323  	if int32(prg.jobName) == 0 {
 25324  		prg.openLogFile()
 25325  	}
 25326  	// avoid confusing \.[texput] with the font name
 25327  	// \xref[texput]
 25328  	prg.getRToken()
 25329  	u = prg.curCs
 25330  	if int32(u) >= hashBase {
 25331  		t = *prg.hash[u-514].rh()
 25332  	} else if int32(u) >= singleBase {
 25333  		if int32(u) == nullCs {
 25334  			t = /* "FONT" */ 1219
 25335  		} else {
 25336  			t = uint16(int32(u) - singleBase)
 25337  		}
 25338  	} else {
 25339  		oldSetting = prg.selector
 25340  		prg.selector = byte(newString)
 25341  		prg.print( /* "FONT" */ 1219)
 25342  		prg.print(int32(u) - activeBase)
 25343  		prg.selector = oldSetting
 25344  		// \xref[FONTx]
 25345  		{
 25346  			if int32(prg.poolPtr)+1 > poolSize {
 25347  				prg.overflow(strNumber( /* "pool size" */ 257), poolSize-int32(prg.initPoolPtr))
 25348  			} /* \xref[TeX capacity exceeded pool size][\quad pool size]  */
 25349  		}
 25350  		t = prg.makeString()
 25351  	}
 25352  	if int32(a) >= 4 {
 25353  		prg.geqDefine(u, quarterword(setFont), halfword(fontBase))
 25354  	} else {
 25355  		prg.eqDefine(u, quarterword(setFont), halfword(fontBase))
 25356  	}
 25357  	prg.scanOptionalEquals()
 25358  	prg.scanFileName()
 25359  
 25360  	// Scan the font size specification
 25361  	prg.nameInProgress = true // this keeps |cur_name| from being changed
 25362  	if prg.scanKeyword(strNumber( /* "at" */ 1220)) {
 25363  		prg.scanDimen(false, false, false)
 25364  		s = prg.curVal
 25365  		if s <= 0 || s >= 01000000000 {
 25366  			{
 25367  				if int32(prg.interaction) == errorStopMode {
 25368  				}
 25369  				prg.printNl(strNumber( /* "! " */ 262))
 25370  				prg.print( /* "Improper `at' size (" */ 1222)
 25371  			}
 25372  			prg.printScaled(s)
 25373  			prg.print( /* "pt), replaced by 10pt" */ 1223)
 25374  			// \xref[Improper `at' size...]
 25375  			{
 25376  				prg.helpPtr = 2
 25377  				prg.helpLine[1] = /* "I can only handle fonts at positive sizes that are" */ 1224
 25378  				prg.helpLine[0] = /* "less than 2048pt, so I've changed what you said to 10pt." */ 1225
 25379  			}
 25380  			prg.error1()
 25381  			s = 10 * 0200000
 25382  		}
 25383  	} else if prg.scanKeyword(strNumber( /* "scaled" */ 1221)) {
 25384  		prg.scanInt()
 25385  		s = -prg.curVal
 25386  		if prg.curVal <= 0 || prg.curVal > 32768 {
 25387  			{
 25388  				if int32(prg.interaction) == errorStopMode {
 25389  				}
 25390  				prg.printNl(strNumber( /* "! " */ 262))
 25391  				prg.print( /* "Illegal magnification has been changed to 1000" */ 552)
 25392  			}
 25393  
 25394  			// \xref[Illegal magnification...]
 25395  			{
 25396  				prg.helpPtr = 1
 25397  				prg.helpLine[0] = /* "The magnification ratio must be between 1 and 32768." */ 553
 25398  			}
 25399  			prg.intError(prg.curVal)
 25400  			s = -1000
 25401  		}
 25402  	} else {
 25403  		s = -1000
 25404  	}
 25405  	prg.nameInProgress = false
 25406  
 25407  	// If this font has already been loaded, set |f| to the internal font number and |goto common_ending|
 25408  	flushableString = uint16(int32(prg.strPtr) - 1)
 25409  	for ii := int32(fontBase + 1); ii <= int32(prg.fontPtr); ii++ {
 25410  		f = internalFontNumber(ii)
 25411  		_ = f
 25412  		if prg.strEqStr(prg.fontName[f], prg.curName) && prg.strEqStr(prg.fontArea[f], prg.curArea) {
 25413  			if int32(prg.curName) == int32(flushableString) {
 25414  				{
 25415  					prg.strPtr = uint16(int32(prg.strPtr) - 1)
 25416  					prg.poolPtr = prg.strStart[prg.strPtr]
 25417  				}
 25418  				prg.curName = prg.fontName[f]
 25419  			}
 25420  			if s > 0 {
 25421  				if s == prg.fontSize[f] {
 25422  					goto commonEnding
 25423  				}
 25424  			} else if prg.fontSize[f] == prg.xnOverD(prg.fontDsize[f], -s, 1000) {
 25425  				goto commonEnding
 25426  			}
 25427  		}
 25428  	}
 25429  	f = prg.readFontInfo(u, prg.curName, prg.curArea, s)
 25430  
 25431  commonEnding:
 25432  	*(*prg.eqtb[u-1].hh()).rh() = uint16(f)
 25433  	prg.eqtb[fontIdBase+int32(f)-1] = prg.eqtb[u-1]
 25434  	*prg.hash[fontIdBase+int32(f)-514].rh() = t
 25435  }
 25436  
 25437  func (prg *prg) newInteraction() {
 25438  	prg.printLn()
 25439  	prg.interaction = byte(prg.curChr)
 25440  
 25441  	// Initialize the print |selector| based on |interaction|
 25442  	if int32(prg.interaction) == batchMode {
 25443  		prg.selector = byte(noPrint)
 25444  	} else {
 25445  		prg.selector = byte(termOnly)
 25446  	}
 25447  	if prg.logOpened {
 25448  		prg.selector = byte(int32(prg.selector) + 2)
 25449  	}
 25450  }
 25451  
 25452  //
 25453  
 25454  func (prg *prg) prefixedCommand() {
 25455  	var (
 25456  		a    smallNumber        // accumulated prefix codes so far
 25457  		f    internalFontNumber // identifies a font
 25458  		j    halfword           // index into a \.[\\parshape] specification
 25459  		k    fontIndex          // index into |font_info|
 25460  		p, q halfword           // for temporary short-term use
 25461  		n    int32              // ditto
 25462  		e    bool               // should a definition be expanded? or was \.[\\let] not done?
 25463  	)
 25464  	a = 0
 25465  	for int32(prg.curCmd) == prefix {
 25466  		if !(int32(a)/int32(prg.curChr)&1 != 0) {
 25467  			a = byte(int32(a) + int32(prg.curChr))
 25468  		}
 25469  
 25470  		// Get the next non-blank non-relax...
 25471  		for {
 25472  			prg.getXToken()
 25473  			if int32(prg.curCmd) != spacer && int32(prg.curCmd) != relax {
 25474  				break
 25475  			}
 25476  		}
 25477  		if int32(prg.curCmd) <= maxNonPrefixedCommand {
 25478  			{
 25479  				if int32(prg.interaction) == errorStopMode {
 25480  				}
 25481  				prg.printNl(strNumber( /* "! " */ 262))
 25482  				prg.print( /* "You can't use a prefix with `" */ 1179)
 25483  			}
 25484  			// \xref[You can't use a prefix with x]
 25485  			prg.printCmdChr(prg.curCmd, prg.curChr)
 25486  			prg.printChar(asciiCode('\''))
 25487  			{
 25488  				prg.helpPtr = 1
 25489  				prg.helpLine[0] = /* "I'll pretend you didn't say \\long or \\outer or \\global." */ 1180
 25490  			}
 25491  			prg.backError()
 25492  			goto exit
 25493  		}
 25494  	}
 25495  
 25496  	// Discard the prefixes \.[\\long] and \.[\\outer] if they are irrelevant
 25497  	if int32(prg.curCmd) != def && int32(a)%4 != 0 {
 25498  		{
 25499  			if int32(prg.interaction) == errorStopMode {
 25500  			}
 25501  			prg.printNl(strNumber( /* "! " */ 262))
 25502  			prg.print( /* "You can't use `" */ 685)
 25503  		}
 25504  		prg.printEsc(strNumber( /* "long" */ 1171))
 25505  		prg.print( /* "' or `" */ 1181)
 25506  		prg.printEsc(strNumber( /* "outer" */ 1172))
 25507  		prg.print( /* "' with `" */ 1182)
 25508  		// \xref[You can't use \\long...]
 25509  		prg.printCmdChr(prg.curCmd, prg.curChr)
 25510  		prg.printChar(asciiCode('\''))
 25511  		{
 25512  			prg.helpPtr = 1
 25513  			prg.helpLine[0] = /* "I'll pretend you didn't say \\long or \\outer here." */ 1183
 25514  		}
 25515  		prg.error1()
 25516  	}
 25517  
 25518  	// Adjust \(f)for the setting of \.[\\globaldefs]
 25519  	if *prg.eqtb[intBase+globalDefsCode-1].int() != 0 {
 25520  		if *prg.eqtb[intBase+globalDefsCode-1].int() < 0 {
 25521  			if int32(a) >= 4 {
 25522  				a = byte(int32(a) - 4)
 25523  			}
 25524  		} else {
 25525  			if !(int32(a) >= 4) {
 25526  				a = byte(int32(a) + 4)
 25527  			}
 25528  		}
 25529  	}
 25530  	switch prg.curCmd {
 25531  	case setFont:
 25532  		if int32(a) >= 4 {
 25533  			prg.geqDefine(halfword(curFontLoc), quarterword(data), prg.curChr)
 25534  		} else {
 25535  			prg.eqDefine(halfword(curFontLoc), quarterword(data), prg.curChr)
 25536  		}
 25537  
 25538  	case def:
 25539  		if prg.curChr&1 != 0 && !(int32(a) >= 4) && *prg.eqtb[intBase+globalDefsCode-1].int() >= 0 {
 25540  			a = byte(int32(a) + 4)
 25541  		}
 25542  		e = int32(prg.curChr) >= 2
 25543  		prg.getRToken()
 25544  		p = prg.curCs
 25545  		q = prg.scanToks(true, e)
 25546  		if int32(a) >= 4 {
 25547  			prg.geqDefine(p, quarterword(call+int32(a)%4), prg.defRef)
 25548  		} else {
 25549  			prg.eqDefine(p, quarterword(call+int32(a)%4), prg.defRef)
 25550  		}
 25551  
 25552  	case let:
 25553  		n = int32(prg.curChr)
 25554  		prg.getRToken()
 25555  		p = prg.curCs
 25556  		if n == normal {
 25557  			for {
 25558  				prg.getToken()
 25559  				if int32(prg.curCmd) != spacer {
 25560  					break
 25561  				}
 25562  			}
 25563  			if int32(prg.curTok) == otherToken+'=' {
 25564  				prg.getToken()
 25565  				if int32(prg.curCmd) == spacer {
 25566  					prg.getToken()
 25567  				}
 25568  			}
 25569  		} else {
 25570  			prg.getToken()
 25571  			q = prg.curTok
 25572  			prg.getToken()
 25573  			prg.backInput()
 25574  			prg.curTok = q
 25575  			prg.backInput() // look ahead, then back up
 25576  		} // note that |back_input| doesn't affect |cur_cmd|, |cur_chr|
 25577  		if int32(prg.curCmd) >= call {
 25578  			*(*prg.mem[prg.curChr].hh()).lh() = uint16(int32(*(*prg.mem[prg.curChr].hh()).lh()) + 1)
 25579  		}
 25580  		if int32(a) >= 4 {
 25581  			prg.geqDefine(p, prg.curCmd, prg.curChr)
 25582  		} else {
 25583  			prg.eqDefine(p, prg.curCmd, prg.curChr)
 25584  		}
 25585  
 25586  	case shorthandDef:
 25587  		n = int32(prg.curChr)
 25588  		prg.getRToken()
 25589  		p = prg.curCs
 25590  		if int32(a) >= 4 {
 25591  			prg.geqDefine(p, quarterword(relax), halfword(256))
 25592  		} else {
 25593  			prg.eqDefine(p, quarterword(relax), halfword(256))
 25594  		}
 25595  		prg.scanOptionalEquals()
 25596  		switch n {
 25597  		case charDefCode:
 25598  			prg.scanCharNum()
 25599  			if int32(a) >= 4 {
 25600  				prg.geqDefine(p, quarterword(charGiven), halfword(prg.curVal))
 25601  			} else {
 25602  				prg.eqDefine(p, quarterword(charGiven), halfword(prg.curVal))
 25603  			}
 25604  
 25605  		case mathCharDefCode:
 25606  			prg.scanFifteenBitInt()
 25607  			if int32(a) >= 4 {
 25608  				prg.geqDefine(p, quarterword(mathGiven), halfword(prg.curVal))
 25609  			} else {
 25610  				prg.eqDefine(p, quarterword(mathGiven), halfword(prg.curVal))
 25611  			}
 25612  
 25613  		default:
 25614  			prg.scanEightBitInt()
 25615  			switch n {
 25616  			case countDefCode:
 25617  				if int32(a) >= 4 {
 25618  					prg.geqDefine(p, quarterword(assignInt), halfword(countBase+prg.curVal))
 25619  				} else {
 25620  					prg.eqDefine(p, quarterword(assignInt), halfword(countBase+prg.curVal))
 25621  				}
 25622  			case dimenDefCode:
 25623  				if int32(a) >= 4 {
 25624  					prg.geqDefine(p, quarterword(assignDimen), halfword(scaledBase+prg.curVal))
 25625  				} else {
 25626  					prg.eqDefine(p, quarterword(assignDimen), halfword(scaledBase+prg.curVal))
 25627  				}
 25628  			case skipDefCode:
 25629  				if int32(a) >= 4 {
 25630  					prg.geqDefine(p, quarterword(assignGlue), halfword(skipBase+prg.curVal))
 25631  				} else {
 25632  					prg.eqDefine(p, quarterword(assignGlue), halfword(skipBase+prg.curVal))
 25633  				}
 25634  			case muSkipDefCode:
 25635  				if int32(a) >= 4 {
 25636  					prg.geqDefine(p, quarterword(assignMuGlue), halfword(muSkipBase+prg.curVal))
 25637  				} else {
 25638  					prg.eqDefine(p, quarterword(assignMuGlue), halfword(muSkipBase+prg.curVal))
 25639  				}
 25640  			case toksDefCode:
 25641  				if int32(a) >= 4 {
 25642  					prg.geqDefine(p, quarterword(assignToks), halfword(toksBase+prg.curVal))
 25643  				} else {
 25644  					prg.eqDefine(p, quarterword(assignToks), halfword(toksBase+prg.curVal))
 25645  				}
 25646  			} // there are no other cases
 25647  
 25648  		}
 25649  
 25650  	case readToCs:
 25651  		prg.scanInt()
 25652  		n = prg.curVal
 25653  		if !prg.scanKeyword(strNumber(842)) {
 25654  			{
 25655  				if int32(prg.interaction) == errorStopMode {
 25656  				}
 25657  				prg.printNl(strNumber( /* "! " */ 262))
 25658  				prg.print( /* "Missing `to' inserted" */ 1073)
 25659  			}
 25660  			// \xref[Missing `to'...]
 25661  			{
 25662  				prg.helpPtr = 2
 25663  				prg.helpLine[1] = /* "You should have said `\\read<number> to \\cs'." */ 1200
 25664  				prg.helpLine[0] = /* "I'm going to look for the \\cs now." */ 1201
 25665  			}
 25666  			prg.error1()
 25667  		}
 25668  		prg.getRToken()
 25669  		p = prg.curCs
 25670  		prg.readToks(n, p)
 25671  		if int32(a) >= 4 {
 25672  			prg.geqDefine(p, quarterword(call), halfword(prg.curVal))
 25673  		} else {
 25674  			prg.eqDefine(p, quarterword(call), halfword(prg.curVal))
 25675  		}
 25676  
 25677  	case toksRegister, assignToks:
 25678  		q = prg.curCs
 25679  		if int32(prg.curCmd) == toksRegister {
 25680  			prg.scanEightBitInt()
 25681  			p = uint16(toksBase + prg.curVal)
 25682  		} else {
 25683  			p = prg.curChr
 25684  		} // |p=every_par_loc| or |output_routine_loc| or \dots
 25685  		prg.scanOptionalEquals()
 25686  
 25687  		// Get the next non-blank non-relax non-call token
 25688  		for {
 25689  			prg.getXToken()
 25690  			if int32(prg.curCmd) != spacer && int32(prg.curCmd) != relax {
 25691  				break
 25692  			}
 25693  		}
 25694  		if int32(prg.curCmd) != leftBrace {
 25695  			if int32(prg.curCmd) == toksRegister {
 25696  				prg.scanEightBitInt()
 25697  				prg.curCmd = byte(assignToks)
 25698  				prg.curChr = uint16(toksBase + prg.curVal)
 25699  			}
 25700  			if int32(prg.curCmd) == assignToks {
 25701  				q = *(*prg.eqtb[prg.curChr-1].hh()).rh()
 25702  				if int32(q) == 0 {
 25703  					if int32(a) >= 4 {
 25704  						prg.geqDefine(p, quarterword(undefinedCs), halfword(0))
 25705  					} else {
 25706  						prg.eqDefine(p, quarterword(undefinedCs), halfword(0))
 25707  					}
 25708  				} else {
 25709  					*(*prg.mem[q].hh()).lh() = uint16(int32(*(*prg.mem[q].hh()).lh()) + 1)
 25710  					if int32(a) >= 4 {
 25711  						prg.geqDefine(p, quarterword(call), q)
 25712  					} else {
 25713  						prg.eqDefine(p, quarterword(call), q)
 25714  					}
 25715  				}
 25716  
 25717  				goto done
 25718  			}
 25719  		}
 25720  		prg.backInput()
 25721  		prg.curCs = q
 25722  		q = prg.scanToks(false, false)
 25723  		if int32(*(*prg.mem[prg.defRef].hh()).rh()) == 0 {
 25724  			if int32(a) >= 4 {
 25725  				prg.geqDefine(p, quarterword(undefinedCs), halfword(0))
 25726  			} else {
 25727  				prg.eqDefine(p, quarterword(undefinedCs), halfword(0))
 25728  			}
 25729  			{
 25730  				*(*prg.mem[prg.defRef].hh()).rh() = prg.avail
 25731  				prg.avail = prg.defRef /*    dyn_used:= dyn_used-1 ; [  ] */
 25732  			}
 25733  		} else {
 25734  			if int32(p) == outputRoutineLoc {
 25735  				*(*prg.mem[q].hh()).rh() = prg.getAvail()
 25736  				q = *(*prg.mem[q].hh()).rh()
 25737  				*(*prg.mem[q].hh()).lh() = uint16(rightBraceToken + '}')
 25738  				q = prg.getAvail()
 25739  				*(*prg.mem[q].hh()).lh() = uint16(leftBraceToken + '{')
 25740  				*(*prg.mem[q].hh()).rh() = *(*prg.mem[prg.defRef].hh()).rh()
 25741  				*(*prg.mem[prg.defRef].hh()).rh() = q
 25742  			}
 25743  			if int32(a) >= 4 {
 25744  				prg.geqDefine(p, quarterword(call), prg.defRef)
 25745  			} else {
 25746  				prg.eqDefine(p, quarterword(call), prg.defRef)
 25747  			}
 25748  		}
 25749  
 25750  	case assignInt:
 25751  		p = prg.curChr
 25752  		prg.scanOptionalEquals()
 25753  		prg.scanInt()
 25754  		if int32(a) >= 4 {
 25755  			prg.geqWordDefine(p, prg.curVal)
 25756  		} else {
 25757  			prg.eqWordDefine(p, prg.curVal)
 25758  		}
 25759  
 25760  	case assignDimen:
 25761  		p = prg.curChr
 25762  		prg.scanOptionalEquals()
 25763  		prg.scanDimen(false, false, false)
 25764  		if int32(a) >= 4 {
 25765  			prg.geqWordDefine(p, prg.curVal)
 25766  		} else {
 25767  			prg.eqWordDefine(p, prg.curVal)
 25768  		}
 25769  
 25770  	case assignGlue, assignMuGlue:
 25771  		p = prg.curChr
 25772  		n = int32(prg.curCmd)
 25773  		prg.scanOptionalEquals()
 25774  		if n == assignMuGlue {
 25775  			prg.scanGlue(smallNumber(muVal))
 25776  		} else {
 25777  			prg.scanGlue(smallNumber(glueVal))
 25778  		}
 25779  		prg.trapZeroGlue()
 25780  		if int32(a) >= 4 {
 25781  			prg.geqDefine(p, quarterword(glueRef), halfword(prg.curVal))
 25782  		} else {
 25783  			prg.eqDefine(p, quarterword(glueRef), halfword(prg.curVal))
 25784  		}
 25785  
 25786  	case defCode:
 25787  		if int32(prg.curChr) == catCodeBase {
 25788  			n = maxCharCode
 25789  		} else if int32(prg.curChr) == mathCodeBase {
 25790  			n = 0100000
 25791  		} else if int32(prg.curChr) == sfCodeBase {
 25792  			n = 077777
 25793  		} else if int32(prg.curChr) == delCodeBase {
 25794  			n = 077777777
 25795  		} else {
 25796  			n = 255
 25797  		}
 25798  		p = prg.curChr
 25799  		prg.scanCharNum()
 25800  		p = uint16(int32(p) + prg.curVal)
 25801  		prg.scanOptionalEquals()
 25802  		prg.scanInt()
 25803  		if prg.curVal < 0 && int32(p) < delCodeBase || prg.curVal > n {
 25804  			{
 25805  				if int32(prg.interaction) == errorStopMode {
 25806  				}
 25807  				prg.printNl(strNumber( /* "! " */ 262))
 25808  				prg.print( /* "Invalid code (" */ 1202)
 25809  			}
 25810  			prg.printInt(prg.curVal)
 25811  			// \xref[Invalid code]
 25812  			if int32(p) < delCodeBase {
 25813  				prg.print( /* "), should be in the range 0.." */ 1203)
 25814  			} else {
 25815  				prg.print( /* "), should be at most " */ 1204)
 25816  			}
 25817  			prg.printInt(n)
 25818  			{
 25819  				prg.helpPtr = 1
 25820  				prg.helpLine[0] = /* "I'm going to use 0 instead of that illegal code value." */ 1205
 25821  			}
 25822  
 25823  			prg.error1()
 25824  			prg.curVal = 0
 25825  		}
 25826  		if int32(p) < mathCodeBase {
 25827  			if int32(a) >= 4 {
 25828  				prg.geqDefine(p, quarterword(data), halfword(prg.curVal))
 25829  			} else {
 25830  				prg.eqDefine(p, quarterword(data), halfword(prg.curVal))
 25831  			}
 25832  		} else if int32(p) < delCodeBase {
 25833  			if int32(a) >= 4 {
 25834  				prg.geqDefine(p, quarterword(data), halfword(prg.curVal+0))
 25835  			} else {
 25836  				prg.eqDefine(p, quarterword(data), halfword(prg.curVal+0))
 25837  			}
 25838  		} else if int32(a) >= 4 {
 25839  			prg.geqWordDefine(p, prg.curVal)
 25840  		} else {
 25841  			prg.eqWordDefine(p, prg.curVal)
 25842  		}
 25843  
 25844  	case defFamily:
 25845  		p = prg.curChr
 25846  		prg.scanFourBitInt()
 25847  		p = uint16(int32(p) + prg.curVal)
 25848  		prg.scanOptionalEquals()
 25849  		prg.scanFontIdent()
 25850  		if int32(a) >= 4 {
 25851  			prg.geqDefine(p, quarterword(data), halfword(prg.curVal))
 25852  		} else {
 25853  			prg.eqDefine(p, quarterword(data), halfword(prg.curVal))
 25854  		}
 25855  
 25856  	case register, advance, multiply, divide:
 25857  		prg.doRegisterCommand(a)
 25858  
 25859  	case setBox:
 25860  		prg.scanEightBitInt()
 25861  		if int32(a) >= 4 {
 25862  			n = 256 + prg.curVal
 25863  		} else {
 25864  			n = prg.curVal
 25865  		}
 25866  		prg.scanOptionalEquals()
 25867  		if prg.setBoxAllowed {
 25868  			prg.scanBox(010000000000 + n)
 25869  		} else {
 25870  			{
 25871  				if int32(prg.interaction) == errorStopMode {
 25872  				}
 25873  				prg.printNl(strNumber( /* "! " */ 262))
 25874  				prg.print( /* "Improper " */ 680)
 25875  			}
 25876  			prg.printEsc(strNumber( /* "setbox" */ 536))
 25877  			// \xref[Improper \\setbox]
 25878  			{
 25879  				prg.helpPtr = 2
 25880  				prg.helpLine[1] = /* "Sorry, \\setbox is not allowed after \\halign in a display," */ 1211
 25881  				prg.helpLine[0] = /* "or between \\accent and an accented character." */ 1212
 25882  			}
 25883  			prg.error1()
 25884  		}
 25885  
 25886  	case setAux:
 25887  		prg.alterAux()
 25888  	case setPrevGraf:
 25889  		prg.alterPrevGraf()
 25890  	case setPageDimen:
 25891  		prg.alterPageSoFar()
 25892  	case setPageInt:
 25893  		prg.alterInteger()
 25894  	case setBoxDimen:
 25895  		prg.alterBoxDimen()
 25896  
 25897  	case setShape:
 25898  		prg.scanOptionalEquals()
 25899  		prg.scanInt()
 25900  		n = prg.curVal
 25901  		if n <= 0 {
 25902  			p = 0
 25903  		} else {
 25904  			p = prg.getNode(2*n + 1)
 25905  			*(*prg.mem[p].hh()).lh() = uint16(n)
 25906  			for ii := int32(1); ii <= n; ii++ {
 25907  				j = halfword(ii)
 25908  				_ = j
 25909  				prg.scanDimen(false, false, false)
 25910  				*prg.mem[int32(p)+2*int32(j)-1].int() = prg.curVal // indentation
 25911  				prg.scanDimen(false, false, false)
 25912  				*prg.mem[int32(p)+2*int32(j)].int() = prg.curVal // width
 25913  			}
 25914  		}
 25915  		if int32(a) >= 4 {
 25916  			prg.geqDefine(halfword(parShapeLoc), quarterword(shapeRef), p)
 25917  		} else {
 25918  			prg.eqDefine(halfword(parShapeLoc), quarterword(shapeRef), p)
 25919  		}
 25920  
 25921  	case hyphData:
 25922  		if int32(prg.curChr) == 1 {
 25923  			prg.newPatterns()
 25924  			goto done
 25925  
 25926  			{
 25927  				if int32(prg.interaction) == errorStopMode {
 25928  				}
 25929  				prg.printNl(strNumber( /* "! " */ 262))
 25930  				prg.print( /* "Patterns can be loaded only by INITEX" */ 1216)
 25931  			}
 25932  			// \xref[Patterns can be...]
 25933  			prg.helpPtr = 0
 25934  			prg.error1()
 25935  			for {
 25936  				prg.getToken()
 25937  				if int32(prg.curCmd) == rightBrace {
 25938  					break
 25939  				}
 25940  			} // flush the patterns
 25941  			// flush the patterns
 25942  			goto exit
 25943  		} else {
 25944  			prg.newHyphExceptions()
 25945  			goto done
 25946  		}
 25947  
 25948  	case assignFontDimen:
 25949  		prg.findFontDimen(true)
 25950  		k = uint16(prg.curVal)
 25951  		prg.scanOptionalEquals()
 25952  		prg.scanDimen(false, false, false)
 25953  		*prg.fontInfo[k].int() = prg.curVal
 25954  
 25955  	case assignFontInt:
 25956  		n = int32(prg.curChr)
 25957  		prg.scanFontIdent()
 25958  		f = byte(prg.curVal)
 25959  		prg.scanOptionalEquals()
 25960  		prg.scanInt()
 25961  		if n == 0 {
 25962  			prg.hyphenChar[f] = prg.curVal
 25963  		} else {
 25964  			prg.skewChar[f] = prg.curVal
 25965  		}
 25966  
 25967  	case defFont:
 25968  		prg.newFont(a)
 25969  
 25970  	case setInteraction:
 25971  		prg.newInteraction()
 25972  
 25973  	default:
 25974  		prg.confusion(strNumber( /* "prefix" */ 1178))
 25975  		// \xref[this can't happen prefix][\quad prefix]
 25976  	}
 25977  
 25978  done:
 25979  	if int32(prg.afterToken) != 0 {
 25980  		prg.curTok = prg.afterToken
 25981  		prg.backInput()
 25982  		prg.afterToken = 0
 25983  	}
 25984  
 25985  exit:
 25986  } // note that |glue_shrink(p)=0| since |glue_shrink==shift_amount|
 25987  
 25988  // 800.
 25989  
 25990  // tangle:pos tex.web:15736:1:
 25991  
 25992  // Finally, we will reach the end of the alignment, and we can breathe a
 25993  // sigh of relief that memory hasn't overflowed. All the unset boxes will now be
 25994  // set so that the columns line up, taking due account of spanned columns.
 25995  func (prg *prg) doAssignments() {
 25996  	for true {
 25997  		for {
 25998  			prg.getXToken()
 25999  			if int32(prg.curCmd) != spacer && int32(prg.curCmd) != relax {
 26000  				break
 26001  			}
 26002  		}
 26003  		if int32(prg.curCmd) <= maxNonPrefixedCommand {
 26004  			goto exit
 26005  		}
 26006  		prg.setBoxAllowed = false
 26007  		prg.prefixedCommand()
 26008  		prg.setBoxAllowed = true
 26009  	}
 26010  
 26011  exit:
 26012  }
 26013  
 26014  func (prg *prg) openOrCloseIn() {
 26015  	var (
 26016  		c/* 0..1 */ byte  // 1 for \.[\\openin], 0 for \.[\\closein]
 26017  		n/* 0..15 */ byte // stream number
 26018  	)
 26019  	c = byte(prg.curChr)
 26020  	prg.scanFourBitInt()
 26021  	n = byte(prg.curVal)
 26022  	if int32(prg.readOpen[n]) != closed {
 26023  		prg.aClose(prg.readFile[n])
 26024  		prg.readOpen[n] = byte(closed)
 26025  	}
 26026  	if int32(c) != 0 {
 26027  		prg.scanOptionalEquals()
 26028  		prg.scanFileName()
 26029  		if int32(prg.curExt) == 338 {
 26030  			prg.curExt = /* ".tex" */ 791
 26031  		}
 26032  		prg.packFileName(prg.curName, prg.curArea, prg.curExt)
 26033  		if prg.aOpenIn(prg.readFile[n]) {
 26034  			prg.readOpen[n] = byte(justOpen)
 26035  		}
 26036  	}
 26037  }
 26038  
 26039  func (prg *prg) issueMessage() {
 26040  	var (
 26041  		oldSetting/* 0..maxSelector */ byte           // holds |selector| setting
 26042  		c/* 0..1 */ byte                              // identifies \.[\\message] and \.[\\errmessage]
 26043  		s                                   strNumber // the message
 26044  	)
 26045  	c = byte(prg.curChr)
 26046  	*(*prg.mem[30000-12].hh()).rh() = prg.scanToks(false, true)
 26047  	oldSetting = prg.selector
 26048  	prg.selector = byte(newString)
 26049  	prg.tokenShow(prg.defRef)
 26050  	prg.selector = oldSetting
 26051  	prg.flushList(prg.defRef)
 26052  	{
 26053  		if int32(prg.poolPtr)+1 > poolSize {
 26054  			prg.overflow(strNumber( /* "pool size" */ 257), poolSize-int32(prg.initPoolPtr))
 26055  		} /* \xref[TeX capacity exceeded pool size][\quad pool size]  */
 26056  	}
 26057  	s = prg.makeString()
 26058  	if int32(c) == 0 {
 26059  		if int32(prg.termOffset)+(int32(prg.strStart[int32(s)+1])-int32(prg.strStart[s])) > maxPrintLine-2 {
 26060  			prg.printLn()
 26061  		} else if int32(prg.termOffset) > 0 || int32(prg.fileOffset) > 0 {
 26062  			prg.printChar(asciiCode(' '))
 26063  		}
 26064  		prg.slowPrint(int32(s))
 26065  	} else {
 26066  		// Print string |s| as an error message
 26067  		{
 26068  			if int32(prg.interaction) == errorStopMode {
 26069  			}
 26070  			prg.printNl(strNumber( /* "! " */ 262))
 26071  			prg.print( /* "" */ 338)
 26072  		}
 26073  		prg.slowPrint(int32(s))
 26074  		if int32(*(*prg.eqtb[errHelpLoc-1].hh()).rh()) != 0 {
 26075  			prg.useErrHelp = true
 26076  		} else if prg.longHelpSeen {
 26077  			prg.helpPtr = 1
 26078  			prg.helpLine[0] = /* "(That was another \\errmessage.)" */ 1232
 26079  		} else {
 26080  			if int32(prg.interaction) < errorStopMode {
 26081  				prg.longHelpSeen = true
 26082  			}
 26083  			{
 26084  				prg.helpPtr = 4
 26085  				prg.helpLine[3] = /* "This error message was generated by an \\errmessage" */ 1233
 26086  				prg.helpLine[2] = /* "command, so I can't give any explicit help." */ 1234
 26087  				prg.helpLine[1] = /* "Pretend that you're Hercule Poirot: Examine all clues," */ 1235
 26088  				prg.helpLine[0] = /* "and deduce the truth by order and method." */ 1236
 26089  			}
 26090  		}
 26091  		prg.error1()
 26092  		prg.useErrHelp = false
 26093  	}
 26094  	{
 26095  		prg.strPtr = uint16(int32(prg.strPtr) - 1)
 26096  		prg.poolPtr = prg.strStart[prg.strPtr]
 26097  	}
 26098  }
 26099  
 26100  func (prg *prg) shiftCase() {
 26101  	var (
 26102  		b halfword  // |lc_code_base| or |uc_code_base|
 26103  		p halfword  // runs through the token list
 26104  		t halfword  // token
 26105  		c eightBits // character code
 26106  	)
 26107  	b = prg.curChr
 26108  	p = prg.scanToks(false, false)
 26109  	p = *(*prg.mem[prg.defRef].hh()).rh()
 26110  	for int32(p) != 0 {
 26111  		t = *(*prg.mem[p].hh()).lh()
 26112  		if int32(t) < 07777+singleBase {
 26113  			c = byte(int32(t) % 256)
 26114  			if int32(*(*prg.eqtb[int32(b)+int32(c)-1].hh()).rh()) != 0 {
 26115  				*(*prg.mem[p].hh()).lh() = uint16(int32(t) - int32(c) + int32(*(*prg.eqtb[int32(b)+int32(c)-1].hh()).rh()))
 26116  			}
 26117  		}
 26118  		p = *(*prg.mem[p].hh()).rh()
 26119  	}
 26120  	prg.beginTokenList(*(*prg.mem[prg.defRef].hh()).rh(), quarterword(backedUp))
 26121  	{
 26122  		*(*prg.mem[prg.defRef].hh()).rh() = prg.avail
 26123  		prg.avail = prg.defRef /*    dyn_used:= dyn_used-1 ; [  ] */
 26124  	} // omit reference count
 26125  }
 26126  
 26127  func (prg *prg) showWhatever() {
 26128  	var (
 26129  		p halfword // tail of a token list to show
 26130  	)
 26131  	if int32(p) == 0 {
 26132  	}
 26133  	switch prg.curChr {
 26134  	case showListsCode:
 26135  		prg.beginDiagnostic()
 26136  		prg.showActivities()
 26137  
 26138  	case showBoxCode:
 26139  		// Show the current contents of a box
 26140  		prg.scanEightBitInt()
 26141  		prg.beginDiagnostic()
 26142  		prg.printNl(strNumber( /* "> \\box" */ 1254))
 26143  		prg.printInt(prg.curVal)
 26144  		prg.printChar(asciiCode('='))
 26145  		if int32(*(*prg.eqtb[boxBase+prg.curVal-1].hh()).rh()) == 0 {
 26146  			prg.print( /* "void" */ 410)
 26147  		} else {
 26148  			prg.showBox(*(*prg.eqtb[boxBase+prg.curVal-1].hh()).rh())
 26149  		}
 26150  
 26151  	case showCode:
 26152  		// Show the current meaning of a token, then |goto common_ending|
 26153  		prg.getToken()
 26154  		if int32(prg.interaction) == errorStopMode {
 26155  		}
 26156  		prg.printNl(strNumber( /* "> " */ 1248))
 26157  		if int32(prg.curCs) != 0 {
 26158  			prg.sprintCs(prg.curCs)
 26159  			prg.printChar(asciiCode('='))
 26160  		}
 26161  		prg.printMeaning()
 26162  		goto commonEnding
 26163  
 26164  	default:
 26165  		p = prg.theToks()
 26166  		if int32(prg.interaction) == errorStopMode {
 26167  		}
 26168  		prg.printNl(strNumber( /* "> " */ 1248))
 26169  		prg.tokenShow(halfword(30000 - 3))
 26170  		prg.flushList(*(*prg.mem[30000-3].hh()).rh())
 26171  		goto commonEnding
 26172  
 26173  	}
 26174  
 26175  	// Complete a potentially long \.[\\show] command
 26176  	prg.endDiagnostic(true)
 26177  	{
 26178  		if int32(prg.interaction) == errorStopMode {
 26179  		}
 26180  		prg.printNl(strNumber( /* "! " */ 262))
 26181  		prg.print( /* "OK" */ 1255)
 26182  	}
 26183  	// \xref[OK]
 26184  	if int32(prg.selector) == termAndLog {
 26185  		if *prg.eqtb[intBase+tracingOnlineCode-1].int() <= 0 {
 26186  			prg.selector = byte(termOnly)
 26187  			prg.print( /* " (see the transcript file)" */ 1256)
 26188  			prg.selector = byte(termAndLog)
 26189  		}
 26190  	}
 26191  
 26192  commonEnding:
 26193  	if int32(prg.interaction) < errorStopMode {
 26194  		prg.helpPtr = 0
 26195  		prg.errorCount = int8(int32(prg.errorCount) - 1)
 26196  	} else if *prg.eqtb[intBase+tracingOnlineCode-1].int() > 0 {
 26197  		{
 26198  			prg.helpPtr = 3
 26199  			prg.helpLine[2] = /* "This isn't an error message; I'm just \\showing something." */ 1243
 26200  			prg.helpLine[1] = /* "Type `I\\show...' to show more (e.g., \\show\\cs," */ 1244
 26201  			prg.helpLine[0] = /* "\\showthe\\count10, \\showbox255, \\showlists)." */ 1245
 26202  		}
 26203  	} else {
 26204  		{
 26205  			prg.helpPtr = 5
 26206  			prg.helpLine[4] = /* "This isn't an error message; I'm just \\showing something." */ 1243
 26207  			prg.helpLine[3] = /* "Type `I\\show...' to show more (e.g., \\show\\cs," */ 1244
 26208  			prg.helpLine[2] = /* "\\showthe\\count10, \\showbox255, \\showlists)." */ 1245
 26209  			prg.helpLine[1] = /* "And type `I\\tracingonline=1\\show...' to show boxes and" */ 1246
 26210  			prg.helpLine[0] = /* "lists on your terminal as well as in the transcript file." */ 1247
 26211  		}
 26212  	}
 26213  	prg.error1()
 26214  }
 26215  
 26216  func (prg *prg) storeFmtFile() {
 26217  	var (
 26218  		j, k, l int32        // all-purpose indices
 26219  		p, q    halfword     // all-purpose pointers
 26220  		x       int32        // something to dump
 26221  		w       fourQuarters // four ASCII codes
 26222  	)
 26223  	if int32(prg.savePtr) != 0 {
 26224  		{
 26225  			if int32(prg.interaction) == errorStopMode {
 26226  			}
 26227  			prg.printNl(strNumber( /* "! " */ 262))
 26228  			prg.print( /* "You can't dump inside a group" */ 1258)
 26229  		}
 26230  		// \xref[You can't dump...]
 26231  		{
 26232  			prg.helpPtr = 1
 26233  			prg.helpLine[0] = /* "`[...\\dump]' is a no-no." */ 1259
 26234  		}
 26235  		{
 26236  			if int32(prg.interaction) == errorStopMode {
 26237  				prg.interaction = byte(scrollMode)
 26238  			}
 26239  			if prg.logOpened {
 26240  				prg.error1()
 26241  			} /*  if interaction>batch_mode then debug_help; [  ] */
 26242  			prg.history = byte(fatalErrorStop)
 26243  			prg.jumpOut()
 26244  		}
 26245  	}
 26246  
 26247  	// Create the |format_ident|, open the format file, and inform the user that dumping has begun
 26248  	prg.selector = byte(newString)
 26249  	prg.print( /* " (preloaded format=" */ 1272)
 26250  	prg.print(int32(prg.jobName))
 26251  	prg.printChar(asciiCode(' '))
 26252  	prg.printInt(*prg.eqtb[intBase+yearCode-1].int())
 26253  	prg.printChar(asciiCode('.'))
 26254  	prg.printInt(*prg.eqtb[intBase+monthCode-1].int())
 26255  	prg.printChar(asciiCode('.'))
 26256  	prg.printInt(*prg.eqtb[intBase+dayCode-1].int())
 26257  	prg.printChar(asciiCode(')'))
 26258  	if int32(prg.interaction) == batchMode {
 26259  		prg.selector = byte(logOnly)
 26260  	} else {
 26261  		prg.selector = byte(termAndLog)
 26262  	}
 26263  	{
 26264  		if int32(prg.poolPtr)+1 > poolSize {
 26265  			prg.overflow(strNumber( /* "pool size" */ 257), poolSize-int32(prg.initPoolPtr))
 26266  		} /* \xref[TeX capacity exceeded pool size][\quad pool size]  */
 26267  	}
 26268  	prg.formatIdent = prg.makeString()
 26269  	prg.packJobName(strNumber(formatExtension))
 26270  	for !prg.wOpenOut(prg.fmtFile) {
 26271  		prg.promptFileName(strNumber( /* "format file name" */ 1273), strNumber(formatExtension))
 26272  	}
 26273  	prg.printNl(strNumber( /* "Beginning to dump on file " */ 1274))
 26274  	// \xref[Beginning to dump...]
 26275  	prg.slowPrint(int32(prg.wMakeNameString(prg.fmtFile)))
 26276  	{
 26277  		prg.strPtr = uint16(int32(prg.strPtr) - 1)
 26278  		prg.poolPtr = prg.strStart[prg.strPtr]
 26279  	}
 26280  	prg.printNl(strNumber( /* "" */ 338))
 26281  	prg.slowPrint(int32(prg.formatIdent))
 26282  
 26283  	// Dump constants for consistency check
 26284  	{
 26285  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = 504454778
 26286  		prg.fmtFile.Put()
 26287  	}
 26288  
 26289  	{
 26290  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = memBot
 26291  		prg.fmtFile.Put()
 26292  	}
 26293  
 26294  	{
 26295  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = 30000
 26296  		prg.fmtFile.Put()
 26297  	}
 26298  
 26299  	{
 26300  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = eqtbSize
 26301  		prg.fmtFile.Put()
 26302  	}
 26303  
 26304  	{
 26305  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = hashPrime
 26306  		prg.fmtFile.Put()
 26307  	}
 26308  
 26309  	{
 26310  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = hyphSize
 26311  		prg.fmtFile.Put()
 26312  	}
 26313  
 26314  	// Dump the string pool
 26315  	{
 26316  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.poolPtr)
 26317  		prg.fmtFile.Put()
 26318  	}
 26319  	{
 26320  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.strPtr)
 26321  		prg.fmtFile.Put()
 26322  	}
 26323  	for ii := int32(0); ii <= int32(prg.strPtr); ii++ {
 26324  		k = ii
 26325  		_ = k
 26326  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.strStart[k])
 26327  		prg.fmtFile.Put()
 26328  	}
 26329  	k = 0
 26330  	for k+4 < int32(prg.poolPtr) {
 26331  		w.b0 = byte(int32(prg.strPool[k]) + minQuarterword)
 26332  		w.b1 = byte(int32(prg.strPool[k+1]) + minQuarterword)
 26333  		w.b2 = byte(int32(prg.strPool[k+2]) + minQuarterword)
 26334  		w.b3 = byte(int32(prg.strPool[k+3]) + minQuarterword)
 26335  		{
 26336  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).qqqq() = w
 26337  			prg.fmtFile.Put()
 26338  		}
 26339  		k = k + 4
 26340  	}
 26341  	k = int32(prg.poolPtr) - 4
 26342  	w.b0 = byte(int32(prg.strPool[k]) + minQuarterword)
 26343  	w.b1 = byte(int32(prg.strPool[k+1]) + minQuarterword)
 26344  	w.b2 = byte(int32(prg.strPool[k+2]) + minQuarterword)
 26345  	w.b3 = byte(int32(prg.strPool[k+3]) + minQuarterword)
 26346  	{
 26347  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).qqqq() = w
 26348  		prg.fmtFile.Put()
 26349  	}
 26350  	prg.printLn()
 26351  	prg.printInt(int32(prg.strPtr))
 26352  	prg.print( /* " strings of total length " */ 1260)
 26353  	prg.printInt(int32(prg.poolPtr))
 26354  
 26355  	// Dump the dynamic memory
 26356  	prg.sortAvail()
 26357  	prg.varUsed = 0
 26358  	{
 26359  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.loMemMax)
 26360  		prg.fmtFile.Put()
 26361  	}
 26362  	{
 26363  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.rover)
 26364  		prg.fmtFile.Put()
 26365  	}
 26366  	p = uint16(memBot)
 26367  	q = prg.rover
 26368  	x = 0
 26369  	for {
 26370  		for ii := int32(p); ii <= int32(q)+1; ii++ {
 26371  			k = ii
 26372  			_ = k
 26373  			*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P())) = prg.mem[k]
 26374  			prg.fmtFile.Put()
 26375  		}
 26376  		x = x + int32(q) + 2 - int32(p)
 26377  		prg.varUsed = prg.varUsed + int32(q) - int32(p)
 26378  		p = uint16(int32(q) + int32(*(*prg.mem[q].hh()).lh()))
 26379  		q = *(*prg.mem[int32(q)+1].hh()).rh()
 26380  		if int32(q) == int32(prg.rover) {
 26381  			break
 26382  		}
 26383  	}
 26384  	prg.varUsed = prg.varUsed + int32(prg.loMemMax) - int32(p)
 26385  	prg.dynUsed = int32(prg.memEnd) + 1 - int32(prg.hiMemMin)
 26386  
 26387  	for ii := int32(p); ii <= int32(prg.loMemMax); ii++ {
 26388  		k = ii
 26389  		_ = k
 26390  		*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P())) = prg.mem[k]
 26391  		prg.fmtFile.Put()
 26392  	}
 26393  	x = x + int32(prg.loMemMax) + 1 - int32(p)
 26394  	{
 26395  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.hiMemMin)
 26396  		prg.fmtFile.Put()
 26397  	}
 26398  	{
 26399  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.avail)
 26400  		prg.fmtFile.Put()
 26401  	}
 26402  	for ii := int32(prg.hiMemMin); ii <= int32(prg.memEnd); ii++ {
 26403  		k = ii
 26404  		_ = k
 26405  		*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P())) = prg.mem[k]
 26406  		prg.fmtFile.Put()
 26407  	}
 26408  	x = x + int32(prg.memEnd) + 1 - int32(prg.hiMemMin)
 26409  	p = prg.avail
 26410  	for int32(p) != 0 {
 26411  		prg.dynUsed = prg.dynUsed - 1
 26412  		p = *(*prg.mem[p].hh()).rh()
 26413  	}
 26414  	{
 26415  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.varUsed
 26416  		prg.fmtFile.Put()
 26417  	}
 26418  	{
 26419  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.dynUsed
 26420  		prg.fmtFile.Put()
 26421  	}
 26422  	prg.printLn()
 26423  	prg.printInt(x)
 26424  	prg.print( /* " memory locations dumped; current usage is " */ 1261)
 26425  	prg.printInt(prg.varUsed)
 26426  	prg.printChar(asciiCode('&'))
 26427  	prg.printInt(prg.dynUsed)
 26428  
 26429  	// Dump the table of equivalents
 26430  
 26431  	// Dump regions 1 to 4 of |eqtb|
 26432  	k = activeBase
 26433  	for {
 26434  		j = k
 26435  		for j < intBase-1 {
 26436  			if int32(*(*prg.eqtb[j-1].hh()).rh()) == int32(*(*prg.eqtb[j+1-1].hh()).rh()) && int32(*(*prg.eqtb[j-1].hh()).b0()) == int32(*(*prg.eqtb[j+1-1].hh()).b0()) && int32(*(*prg.eqtb[j-1].hh()).b1()) == int32(*(*prg.eqtb[j+1-1].hh()).b1()) {
 26437  				goto found1
 26438  			}
 26439  			j = j + 1
 26440  		}
 26441  		l = intBase
 26442  		goto done1 // |j=int_base-1|
 26443  		// |j=int_base-1|
 26444  	found1:
 26445  		j = j + 1
 26446  		l = j
 26447  		for j < intBase-1 {
 26448  			if int32(*(*prg.eqtb[j-1].hh()).rh()) != int32(*(*prg.eqtb[j+1-1].hh()).rh()) || int32(*(*prg.eqtb[j-1].hh()).b0()) != int32(*(*prg.eqtb[j+1-1].hh()).b0()) || int32(*(*prg.eqtb[j-1].hh()).b1()) != int32(*(*prg.eqtb[j+1-1].hh()).b1()) {
 26449  				goto done1
 26450  			}
 26451  			j = j + 1
 26452  		}
 26453  
 26454  	done1:
 26455  		{
 26456  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = l - k
 26457  			prg.fmtFile.Put()
 26458  		}
 26459  		for k < l {
 26460  			{
 26461  				*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P())) = prg.eqtb[k-1]
 26462  				prg.fmtFile.Put()
 26463  			}
 26464  			k = k + 1
 26465  		}
 26466  		k = j + 1
 26467  		{
 26468  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = k - l
 26469  			prg.fmtFile.Put()
 26470  		}
 26471  		if k == intBase {
 26472  			break
 26473  		}
 26474  	}
 26475  
 26476  	// Dump regions 5 and 6 of |eqtb|
 26477  	for {
 26478  		j = k
 26479  		for j < eqtbSize {
 26480  			if *prg.eqtb[j-1].int() == *prg.eqtb[j+1-1].int() {
 26481  				goto found2
 26482  			}
 26483  			j = j + 1
 26484  		}
 26485  		l = eqtbSize + 1
 26486  		goto done2 // |j=eqtb_size|
 26487  		// |j=eqtb_size|
 26488  	found2:
 26489  		j = j + 1
 26490  		l = j
 26491  		for j < eqtbSize {
 26492  			if *prg.eqtb[j-1].int() != *prg.eqtb[j+1-1].int() {
 26493  				goto done2
 26494  			}
 26495  			j = j + 1
 26496  		}
 26497  
 26498  	done2:
 26499  		{
 26500  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = l - k
 26501  			prg.fmtFile.Put()
 26502  		}
 26503  		for k < l {
 26504  			{
 26505  				*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P())) = prg.eqtb[k-1]
 26506  				prg.fmtFile.Put()
 26507  			}
 26508  			k = k + 1
 26509  		}
 26510  		k = j + 1
 26511  		{
 26512  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = k - l
 26513  			prg.fmtFile.Put()
 26514  		}
 26515  		if k > eqtbSize {
 26516  			break
 26517  		}
 26518  	}
 26519  	{
 26520  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.parLoc)
 26521  		prg.fmtFile.Put()
 26522  	}
 26523  	{
 26524  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.writeLoc)
 26525  		prg.fmtFile.Put()
 26526  	}
 26527  
 26528  	// Dump the hash table
 26529  	{
 26530  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.hashUsed)
 26531  		prg.fmtFile.Put()
 26532  	}
 26533  	prg.csCount = frozenControlSequence - 1 - int32(prg.hashUsed)
 26534  	for ii := int32(hashBase); ii <= int32(prg.hashUsed); ii++ {
 26535  		p = halfword(ii)
 26536  		_ = p
 26537  		if int32(*prg.hash[p-514].rh()) != 0 {
 26538  			{
 26539  				*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(p)
 26540  				prg.fmtFile.Put()
 26541  			}
 26542  			{
 26543  				*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).hh() = prg.hash[p-514]
 26544  				prg.fmtFile.Put()
 26545  			}
 26546  			prg.csCount = prg.csCount + 1
 26547  		}
 26548  	}
 26549  	for ii := int32(prg.hashUsed) + 1; ii <= undefinedControlSequence-1; ii++ {
 26550  		p = halfword(ii)
 26551  		_ = p
 26552  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).hh() = prg.hash[p-514]
 26553  		prg.fmtFile.Put()
 26554  	}
 26555  	{
 26556  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.csCount
 26557  		prg.fmtFile.Put()
 26558  	}
 26559  
 26560  	prg.printLn()
 26561  	prg.printInt(prg.csCount)
 26562  	prg.print( /* " multiletter control sequences" */ 1262)
 26563  
 26564  	// Dump the font information
 26565  	{
 26566  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.fmemPtr)
 26567  		prg.fmtFile.Put()
 26568  	}
 26569  	for ii := int32(0); ii <= int32(prg.fmemPtr)-1; ii++ {
 26570  		k = ii
 26571  		_ = k
 26572  		*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P())) = prg.fontInfo[k]
 26573  		prg.fmtFile.Put()
 26574  	}
 26575  	{
 26576  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.fontPtr)
 26577  		prg.fmtFile.Put()
 26578  	}
 26579  	for ii := int32(fontBase); ii <= int32(prg.fontPtr); ii++ {
 26580  		k = ii
 26581  		_ = k
 26582  
 26583  		// Dump the array info for internal font number |k|
 26584  		{
 26585  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).qqqq() = prg.fontCheck[k]
 26586  			prg.fmtFile.Put()
 26587  		}
 26588  		{
 26589  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.fontSize[k]
 26590  			prg.fmtFile.Put()
 26591  		}
 26592  		{
 26593  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.fontDsize[k]
 26594  			prg.fmtFile.Put()
 26595  		}
 26596  		{
 26597  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.fontParams[k])
 26598  			prg.fmtFile.Put()
 26599  		}
 26600  
 26601  		{
 26602  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.hyphenChar[k]
 26603  			prg.fmtFile.Put()
 26604  		}
 26605  		{
 26606  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.skewChar[k]
 26607  			prg.fmtFile.Put()
 26608  		}
 26609  
 26610  		{
 26611  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.fontName[k])
 26612  			prg.fmtFile.Put()
 26613  		}
 26614  		{
 26615  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.fontArea[k])
 26616  			prg.fmtFile.Put()
 26617  		}
 26618  
 26619  		{
 26620  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.fontBc[k])
 26621  			prg.fmtFile.Put()
 26622  		}
 26623  		{
 26624  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.fontEc[k])
 26625  			prg.fmtFile.Put()
 26626  		}
 26627  
 26628  		{
 26629  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.charBase[k]
 26630  			prg.fmtFile.Put()
 26631  		}
 26632  		{
 26633  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.widthBase[k]
 26634  			prg.fmtFile.Put()
 26635  		}
 26636  		{
 26637  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.heightBase[k]
 26638  			prg.fmtFile.Put()
 26639  		}
 26640  
 26641  		{
 26642  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.depthBase[k]
 26643  			prg.fmtFile.Put()
 26644  		}
 26645  		{
 26646  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.italicBase[k]
 26647  			prg.fmtFile.Put()
 26648  		}
 26649  		{
 26650  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.ligKernBase[k]
 26651  			prg.fmtFile.Put()
 26652  		}
 26653  
 26654  		{
 26655  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.kernBase[k]
 26656  			prg.fmtFile.Put()
 26657  		}
 26658  		{
 26659  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.extenBase[k]
 26660  			prg.fmtFile.Put()
 26661  		}
 26662  		{
 26663  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.paramBase[k]
 26664  			prg.fmtFile.Put()
 26665  		}
 26666  
 26667  		{
 26668  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.fontGlue[k])
 26669  			prg.fmtFile.Put()
 26670  		}
 26671  
 26672  		{
 26673  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.bcharLabel[k])
 26674  			prg.fmtFile.Put()
 26675  		}
 26676  		{
 26677  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.fontBchar[k])
 26678  			prg.fmtFile.Put()
 26679  		}
 26680  		{
 26681  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.fontFalseBchar[k])
 26682  			prg.fmtFile.Put()
 26683  		}
 26684  
 26685  		prg.printNl(strNumber( /* "\\font" */ 1265))
 26686  		prg.printEsc(*prg.hash[fontIdBase+k-514].rh())
 26687  		prg.printChar(asciiCode('='))
 26688  		prg.printFileName(int32(prg.fontName[k]), int32(prg.fontArea[k]) /* "" */, 338)
 26689  		if prg.fontSize[k] != prg.fontDsize[k] {
 26690  			prg.print( /* " at " */ 741)
 26691  			prg.printScaled(prg.fontSize[k])
 26692  			prg.print( /* "pt" */ 397)
 26693  		}
 26694  	}
 26695  	prg.printLn()
 26696  	prg.printInt(int32(prg.fmemPtr) - 7)
 26697  	prg.print( /* " words of font info for " */ 1263)
 26698  	prg.printInt(int32(prg.fontPtr) - fontBase)
 26699  	prg.print( /* " preloaded font" */ 1264)
 26700  	if int32(prg.fontPtr) != fontBase+1 {
 26701  		prg.printChar(asciiCode('s'))
 26702  	}
 26703  
 26704  	// Dump the hyphenation tables
 26705  	{
 26706  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.hyphCount)
 26707  		prg.fmtFile.Put()
 26708  	}
 26709  	for ii := int32(0); ii <= hyphSize; ii++ {
 26710  		k = ii
 26711  		_ = k
 26712  		if int32(prg.hyphWord[k]) != 0 {
 26713  			{
 26714  				*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = k
 26715  				prg.fmtFile.Put()
 26716  			}
 26717  			{
 26718  				*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.hyphWord[k])
 26719  				prg.fmtFile.Put()
 26720  			}
 26721  			{
 26722  				*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.hyphList[k])
 26723  				prg.fmtFile.Put()
 26724  			}
 26725  		}
 26726  	}
 26727  	prg.printLn()
 26728  	prg.printInt(int32(prg.hyphCount))
 26729  	prg.print( /* " hyphenation exception" */ 1266)
 26730  	if int32(prg.hyphCount) != 1 {
 26731  		prg.printChar(asciiCode('s'))
 26732  	}
 26733  	if prg.trieNotReady {
 26734  		prg.initTrie()
 26735  	}
 26736  	{
 26737  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.trieMax)
 26738  		prg.fmtFile.Put()
 26739  	}
 26740  	for ii := int32(0); ii <= int32(prg.trieMax); ii++ {
 26741  		k = ii
 26742  		_ = k
 26743  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).hh() = prg.trie[k]
 26744  		prg.fmtFile.Put()
 26745  	}
 26746  	{
 26747  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.trieOpPtr)
 26748  		prg.fmtFile.Put()
 26749  	}
 26750  	for ii := int32(1); ii <= int32(prg.trieOpPtr); ii++ {
 26751  		k = ii
 26752  		_ = k
 26753  		{
 26754  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.hyfDistance[k-1])
 26755  			prg.fmtFile.Put()
 26756  		}
 26757  		{
 26758  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.hyfNum[k-1])
 26759  			prg.fmtFile.Put()
 26760  		}
 26761  		{
 26762  			*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.hyfNext[k-1])
 26763  			prg.fmtFile.Put()
 26764  		}
 26765  	}
 26766  	prg.printNl(strNumber( /* "Hyphenation trie of length " */ 1267))
 26767  	prg.printInt(int32(prg.trieMax))
 26768  	// \xref[Hyphenation trie...]
 26769  	prg.print( /* " has " */ 1268)
 26770  	prg.printInt(int32(prg.trieOpPtr))
 26771  	prg.print( /* " op" */ 1269)
 26772  	if int32(prg.trieOpPtr) != 1 {
 26773  		prg.printChar(asciiCode('s'))
 26774  	}
 26775  	prg.print( /* " out of " */ 1270)
 26776  	prg.printInt(trieOpSize)
 26777  	for ii := int32(255); ii >= 0; ii-- {
 26778  		k = ii
 26779  		_ = k
 26780  		if int32(prg.trieUsed[k]) > minQuarterword {
 26781  			prg.printNl(strNumber( /* "  " */ 800))
 26782  			prg.printInt(int32(prg.trieUsed[k]) - minQuarterword)
 26783  			prg.print( /* " for language " */ 1271)
 26784  			prg.printInt(k)
 26785  			{
 26786  				*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = k
 26787  				prg.fmtFile.Put()
 26788  			}
 26789  			{
 26790  				*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.trieUsed[k]) - minQuarterword
 26791  				prg.fmtFile.Put()
 26792  			}
 26793  		}
 26794  	}
 26795  
 26796  	// Dump a couple more things and the closing check word
 26797  	{
 26798  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.interaction)
 26799  		prg.fmtFile.Put()
 26800  	}
 26801  	{
 26802  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.formatIdent)
 26803  		prg.fmtFile.Put()
 26804  	}
 26805  	{
 26806  		*(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = 69069
 26807  		prg.fmtFile.Put()
 26808  	}
 26809  	*prg.eqtb[intBase+tracingStatsCode-1].int() = 0
 26810  
 26811  	// Close the format file
 26812  	prg.wClose(prg.fmtFile)
 26813  }
 26814  
 26815  // \4
 26816  // Declare procedures needed in |do_extension|
 26817  func (prg *prg) newWhatsit(s smallNumber, w smallNumber) {
 26818  	var (
 26819  		p halfword // the new node
 26820  	)
 26821  	p = prg.getNode(int32(w))
 26822  	*(*prg.mem[p].hh()).b0() = byte(whatsitNode)
 26823  	*(*prg.mem[p].hh()).b1() = s
 26824  	*(*prg.mem[prg.curList.tailField].hh()).rh() = p
 26825  	prg.curList.tailField = p
 26826  }
 26827  
 26828  func (prg *prg) newWriteWhatsit(w smallNumber) {
 26829  	prg.newWhatsit(smallNumber(prg.curChr), w)
 26830  	if int32(w) != writeNodeSize {
 26831  		prg.scanFourBitInt()
 26832  	} else {
 26833  		prg.scanInt()
 26834  		if prg.curVal < 0 {
 26835  			prg.curVal = 17
 26836  		} else if prg.curVal > 15 {
 26837  			prg.curVal = 16
 26838  		}
 26839  	}
 26840  	*(*prg.mem[int32(prg.curList.tailField)+1].hh()).lh() = uint16(prg.curVal)
 26841  }
 26842  
 26843  func (prg *prg) doExtension() {
 26844  	var (
 26845  		k int32    // all-purpose integers
 26846  		p halfword // all-purpose pointers
 26847  	)
 26848  	switch prg.curChr {
 26849  	case openNode:
 26850  		// Implement \.[\\openout]
 26851  		prg.newWriteWhatsit(smallNumber(openNodeSize))
 26852  		prg.scanOptionalEquals()
 26853  		prg.scanFileName()
 26854  
 26855  		*(*prg.mem[int32(prg.curList.tailField)+1].hh()).rh() = prg.curName
 26856  		*(*prg.mem[int32(prg.curList.tailField)+2].hh()).lh() = prg.curArea
 26857  		*(*prg.mem[int32(prg.curList.tailField)+2].hh()).rh() = prg.curExt
 26858  
 26859  	case writeNode:
 26860  		// Implement \.[\\write]
 26861  		k = int32(prg.curCs)
 26862  		prg.newWriteWhatsit(smallNumber(writeNodeSize))
 26863  
 26864  		prg.curCs = uint16(k)
 26865  		p = prg.scanToks(false, false)
 26866  		*(*prg.mem[int32(prg.curList.tailField)+1].hh()).rh() = prg.defRef
 26867  
 26868  	case closeNode:
 26869  		// Implement \.[\\closeout]
 26870  		prg.newWriteWhatsit(smallNumber(writeNodeSize))
 26871  		*(*prg.mem[int32(prg.curList.tailField)+1].hh()).rh() = 0
 26872  
 26873  	case specialNode:
 26874  		// Implement \.[\\special]
 26875  		prg.newWhatsit(smallNumber(specialNode), smallNumber(writeNodeSize))
 26876  		*(*prg.mem[int32(prg.curList.tailField)+1].hh()).lh() = 0
 26877  		p = prg.scanToks(false, true)
 26878  		*(*prg.mem[int32(prg.curList.tailField)+1].hh()).rh() = prg.defRef
 26879  
 26880  	case immediateCode:
 26881  		// Implement \.[\\immediate]
 26882  		prg.getXToken()
 26883  		if int32(prg.curCmd) == extension && int32(prg.curChr) <= closeNode {
 26884  			p = prg.curList.tailField
 26885  			prg.doExtension()                  // append a whatsit node
 26886  			prg.outWhat(prg.curList.tailField) // do the action immediately
 26887  			prg.flushNodeList(prg.curList.tailField)
 26888  			prg.curList.tailField = p
 26889  			*(*prg.mem[p].hh()).rh() = 0
 26890  		} else {
 26891  			prg.backInput()
 26892  		}
 26893  
 26894  	case setLanguageCode:
 26895  		// Implement \.[\\setlanguage]
 26896  		if abs(int32(prg.curList.modeField)) != hmode {
 26897  			prg.reportIllegalCase()
 26898  		} else {
 26899  			prg.newWhatsit(smallNumber(languageNode), smallNumber(smallNodeSize))
 26900  			prg.scanInt()
 26901  			if prg.curVal <= 0 {
 26902  				*(*prg.curList.auxField.hh()).rh() = 0
 26903  			} else if prg.curVal > 255 {
 26904  				*(*prg.curList.auxField.hh()).rh() = 0
 26905  			} else {
 26906  				*(*prg.curList.auxField.hh()).rh() = uint16(prg.curVal)
 26907  			}
 26908  			*(*prg.mem[int32(prg.curList.tailField)+1].hh()).rh() = *(*prg.curList.auxField.hh()).rh()
 26909  			*(*prg.mem[int32(prg.curList.tailField)+1].hh()).b0() = prg.normMin(*prg.eqtb[intBase+leftHyphenMinCode-1].int())
 26910  			*(*prg.mem[int32(prg.curList.tailField)+1].hh()).b1() = prg.normMin(*prg.eqtb[intBase+rightHyphenMinCode-1].int())
 26911  		}
 26912  
 26913  	default:
 26914  		prg.confusion(strNumber( /* "ext1" */ 1291))
 26915  		// \xref[this can't happen ext1][\quad ext1]
 26916  	}
 26917  }
 26918  
 26919  func (prg *prg) fixLanguage() {
 26920  	var (
 26921  		l asciiCode // the new current language
 26922  	)
 26923  	if *prg.eqtb[intBase+languageCode-1].int() <= 0 {
 26924  		l = 0
 26925  	} else if *prg.eqtb[intBase+languageCode-1].int() > 255 {
 26926  		l = 0
 26927  	} else {
 26928  		l = byte(*prg.eqtb[intBase+languageCode-1].int())
 26929  	}
 26930  	if int32(l) != int32(*(*prg.curList.auxField.hh()).rh()) {
 26931  		prg.newWhatsit(smallNumber(languageNode), smallNumber(smallNodeSize))
 26932  		*(*prg.mem[int32(prg.curList.tailField)+1].hh()).rh() = uint16(l)
 26933  		*(*prg.curList.auxField.hh()).rh() = uint16(l)
 26934  
 26935  		*(*prg.mem[int32(prg.curList.tailField)+1].hh()).b0() = prg.normMin(*prg.eqtb[intBase+leftHyphenMinCode-1].int())
 26936  		*(*prg.mem[int32(prg.curList.tailField)+1].hh()).b1() = prg.normMin(*prg.eqtb[intBase+rightHyphenMinCode-1].int())
 26937  	}
 26938  }
 26939  
 26940  // \4
 26941  // Declare the procedure called |handle_right_brace|
 26942  func (prg *prg) handleRightBrace() {
 26943  	var (
 26944  		p, q halfword // for short-term use
 26945  		d    scaled   // holds |split_max_depth| in |insert_group|
 26946  		f    int32    // holds |floating_penalty| in |insert_group|
 26947  	)
 26948  	switch prg.curGroup {
 26949  	case simpleGroup:
 26950  		prg.unsave()
 26951  	case bottomLevel:
 26952  		{
 26953  			if int32(prg.interaction) == errorStopMode {
 26954  			}
 26955  			prg.printNl(strNumber( /* "! " */ 262))
 26956  			prg.print( /* "Too many ]'s" */ 1044)
 26957  		}
 26958  		// \xref[Too many \]'s]
 26959  		{
 26960  			prg.helpPtr = 2
 26961  			prg.helpLine[1] = /* "You've closed more groups than you opened." */ 1045
 26962  			prg.helpLine[0] = /* "Such booboos are generally harmless, so keep going." */ 1046
 26963  		}
 26964  		prg.error1()
 26965  
 26966  	case semiSimpleGroup, mathShiftGroup, mathLeftGroup:
 26967  		prg.extraRightBrace()
 26968  	// \4
 26969  	// Cases of |handle_right_brace| where a |right_brace| triggers a delayed action
 26970  	case hboxGroup:
 26971  		prg.package1(smallNumber(0))
 26972  	case adjustedHboxGroup:
 26973  		prg.adjustTail = uint16(30000 - 5)
 26974  		prg.package1(smallNumber(0))
 26975  
 26976  	case vboxGroup:
 26977  		prg.endGraf()
 26978  		prg.package1(smallNumber(0))
 26979  
 26980  	case vtopGroup:
 26981  		prg.endGraf()
 26982  		prg.package1(smallNumber(vtopCode))
 26983  
 26984  	case insertGroup:
 26985  		prg.endGraf()
 26986  		q = *(*prg.eqtb[glueBase+splitTopSkipCode-1].hh()).rh()
 26987  		*(*prg.mem[q].hh()).rh() = uint16(int32(*(*prg.mem[q].hh()).rh()) + 1)
 26988  		d = *prg.eqtb[dimenBase+splitMaxDepthCode-1].int()
 26989  		f = *prg.eqtb[intBase+floatingPenaltyCode-1].int()
 26990  		prg.unsave()
 26991  		prg.savePtr = uint16(int32(prg.savePtr) - 1)
 26992  		// now |saved(0)| is the insertion number, or 255 for |vadjust|
 26993  		p = prg.vpackage(*(*prg.mem[prg.curList.headField].hh()).rh(), scaled(0), smallNumber(additional), scaled(07777777777))
 26994  		prg.popNest()
 26995  		if *prg.saveStack[int32(prg.savePtr)+0].int() < 255 {
 26996  			{
 26997  				*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.getNode(insNodeSize)
 26998  				prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 26999  			}
 27000  			*(*prg.mem[prg.curList.tailField].hh()).b0() = byte(insNode)
 27001  			*(*prg.mem[prg.curList.tailField].hh()).b1() = byte(*prg.saveStack[int32(prg.savePtr)+0].int() + minQuarterword)
 27002  			*prg.mem[int32(prg.curList.tailField)+heightOffset].int() = *prg.mem[int32(p)+heightOffset].int() + *prg.mem[int32(p)+depthOffset].int()
 27003  			*(*prg.mem[int32(prg.curList.tailField)+4].hh()).lh() = *(*prg.mem[int32(p)+listOffset].hh()).rh()
 27004  			*(*prg.mem[int32(prg.curList.tailField)+4].hh()).rh() = q
 27005  			*prg.mem[int32(prg.curList.tailField)+depthOffset].int() = d
 27006  			*prg.mem[int32(prg.curList.tailField)+1].int() = f
 27007  		} else {
 27008  			{
 27009  				*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.getNode(smallNodeSize)
 27010  				prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 27011  			}
 27012  			*(*prg.mem[prg.curList.tailField].hh()).b0() = byte(adjustNode)
 27013  
 27014  			*(*prg.mem[prg.curList.tailField].hh()).b1() = 0 // the |subtype| is not used
 27015  			*prg.mem[int32(prg.curList.tailField)+1].int() = int32(*(*prg.mem[int32(p)+listOffset].hh()).rh())
 27016  			prg.deleteGlueRef(q)
 27017  		}
 27018  		prg.freeNode(p, halfword(boxNodeSize))
 27019  		if int32(prg.nestPtr) == 0 {
 27020  			prg.buildPage()
 27021  		}
 27022  
 27023  	case outputGroup:
 27024  		// Resume the page builder...
 27025  		if int32(prg.curInput.locField) != 0 || int32(prg.curInput.indexField) != outputText && int32(prg.curInput.indexField) != backedUp {
 27026  			{
 27027  				if int32(prg.interaction) == errorStopMode {
 27028  				}
 27029  				prg.printNl(strNumber( /* "! " */ 262))
 27030  				prg.print( /* "Unbalanced output routine" */ 1010)
 27031  			}
 27032  			// \xref[Unbalanced output routine]
 27033  			{
 27034  				prg.helpPtr = 2
 27035  				prg.helpLine[1] = /* "Your sneaky output routine has problematic ['s and/or ]'s." */ 1011
 27036  				prg.helpLine[0] = /* "I can't handle that very well; good luck." */ 1012
 27037  			}
 27038  			prg.error1()
 27039  			for {
 27040  				prg.getToken()
 27041  				if int32(prg.curInput.locField) == 0 {
 27042  					break
 27043  				}
 27044  			}
 27045  		}
 27046  		prg.endTokenList() // conserve stack space in case more outputs are triggered
 27047  		prg.endGraf()
 27048  		prg.unsave()
 27049  		prg.outputActive = false
 27050  		prg.insertPenalties = 0
 27051  
 27052  		// Ensure that box 255 is empty after output
 27053  		if int32(*(*prg.eqtb[boxBase+255-1].hh()).rh()) != 0 {
 27054  			{
 27055  				if int32(prg.interaction) == errorStopMode {
 27056  				}
 27057  				prg.printNl(strNumber( /* "! " */ 262))
 27058  				prg.print( /* "Output routine didn't use all of " */ 1013)
 27059  			}
 27060  			prg.printEsc(strNumber( /* "box" */ 409))
 27061  			prg.printInt(255)
 27062  			// \xref[Output routine didn't use...]
 27063  			{
 27064  				prg.helpPtr = 3
 27065  				prg.helpLine[2] = /* "Your \\output commands should empty \\box255," */ 1014
 27066  				prg.helpLine[1] = /* "e.g., by saying `\\shipout\\box255'." */ 1015
 27067  				prg.helpLine[0] = /* "Proceed; I'll discard its present contents." */ 1016
 27068  			}
 27069  			prg.boxError(eightBits(255))
 27070  		}
 27071  		if int32(prg.curList.tailField) != int32(prg.curList.headField) {
 27072  			*(*prg.mem[prg.pageTail].hh()).rh() = *(*prg.mem[prg.curList.headField].hh()).rh()
 27073  			prg.pageTail = prg.curList.tailField
 27074  		}
 27075  		if int32(*(*prg.mem[30000-2].hh()).rh()) != 0 {
 27076  			if int32(*(*prg.mem[30000-1].hh()).rh()) == 0 {
 27077  				prg.nest[0].tailField = prg.pageTail
 27078  			}
 27079  			*(*prg.mem[prg.pageTail].hh()).rh() = *(*prg.mem[30000-1].hh()).rh()
 27080  			*(*prg.mem[30000-1].hh()).rh() = *(*prg.mem[30000-2].hh()).rh()
 27081  			*(*prg.mem[30000-2].hh()).rh() = 0
 27082  			prg.pageTail = uint16(30000 - 2)
 27083  		}
 27084  		prg.popNest()
 27085  		prg.buildPage()
 27086  
 27087  	case discGroup:
 27088  		prg.buildDiscretionary()
 27089  
 27090  	case alignGroup:
 27091  		prg.backInput()
 27092  		prg.curTok = uint16(07777 + frozenCr)
 27093  		{
 27094  			if int32(prg.interaction) == errorStopMode {
 27095  			}
 27096  			prg.printNl(strNumber( /* "! " */ 262))
 27097  			prg.print( /* "Missing " */ 625)
 27098  		}
 27099  		prg.printEsc(strNumber( /* "cr" */ 899))
 27100  		prg.print( /* " inserted" */ 626)
 27101  		// \xref[Missing \\cr inserted]
 27102  		{
 27103  			prg.helpPtr = 1
 27104  			prg.helpLine[0] = /* "I'm guessing that you meant to end an alignment here." */ 1125
 27105  		}
 27106  		prg.insError()
 27107  
 27108  	case noAlignGroup:
 27109  		prg.endGraf()
 27110  		prg.unsave()
 27111  		prg.alignPeek()
 27112  
 27113  	case vcenterGroup:
 27114  		prg.endGraf()
 27115  		prg.unsave()
 27116  		prg.savePtr = uint16(int32(prg.savePtr) - 2)
 27117  		p = prg.vpackage(*(*prg.mem[prg.curList.headField].hh()).rh(), *prg.saveStack[int32(prg.savePtr)+1].int(), smallNumber(*prg.saveStack[int32(prg.savePtr)+0].int()), scaled(07777777777))
 27118  		prg.popNest()
 27119  		{
 27120  			*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newNoad()
 27121  			prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 27122  		}
 27123  		*(*prg.mem[prg.curList.tailField].hh()).b0() = byte(vcenterNoad)
 27124  		*(*prg.mem[int32(prg.curList.tailField)+1].hh()).rh() = uint16(subBox)
 27125  		*(*prg.mem[int32(prg.curList.tailField)+1].hh()).lh() = p
 27126  
 27127  	case mathChoiceGroup:
 27128  		prg.buildChoices()
 27129  
 27130  	case mathGroup:
 27131  		prg.unsave()
 27132  		prg.savePtr = uint16(int32(prg.savePtr) - 1)
 27133  
 27134  		*(*prg.mem[*prg.saveStack[int32(prg.savePtr)+0].int()].hh()).rh() = uint16(subMlist)
 27135  		p = prg.finMlist(halfword(0))
 27136  		*(*prg.mem[*prg.saveStack[int32(prg.savePtr)+0].int()].hh()).lh() = p
 27137  		if int32(p) != 0 {
 27138  			if int32(*(*prg.mem[p].hh()).rh()) == 0 {
 27139  				if int32(*(*prg.mem[p].hh()).b0()) == ordNoad {
 27140  					if int32(*(*prg.mem[int32(p)+3].hh()).rh()) == empty {
 27141  						if int32(*(*prg.mem[int32(p)+2].hh()).rh()) == empty {
 27142  							*prg.mem[*prg.saveStack[int32(prg.savePtr)+0].int()].hh() = *prg.mem[int32(p)+1].hh()
 27143  							prg.freeNode(p, halfword(noadSize))
 27144  						}
 27145  					}
 27146  				} else if int32(*(*prg.mem[p].hh()).b0()) == accentNoad {
 27147  					if *prg.saveStack[int32(prg.savePtr)+0].int() == int32(prg.curList.tailField)+1 {
 27148  						if int32(*(*prg.mem[prg.curList.tailField].hh()).b0()) == ordNoad {
 27149  							q = prg.curList.headField
 27150  							for int32(*(*prg.mem[q].hh()).rh()) != int32(prg.curList.tailField) {
 27151  								q = *(*prg.mem[q].hh()).rh()
 27152  							}
 27153  							*(*prg.mem[q].hh()).rh() = p
 27154  							prg.freeNode(prg.curList.tailField, halfword(noadSize))
 27155  							prg.curList.tailField = p
 27156  						}
 27157  					}
 27158  				}
 27159  			}
 27160  		}
 27161  
 27162  	default:
 27163  		prg.confusion(strNumber( /* "rightbrace" */ 1047))
 27164  		// \xref[this can't happen rightbrace][\quad rightbrace]
 27165  	}
 27166  }
 27167  
 27168  func (prg *prg) mainControl() {
 27169  	var (
 27170  		t int32 // general-purpose temporary variable
 27171  	)
 27172  	if int32(*(*prg.eqtb[everyJobLoc-1].hh()).rh()) != 0 {
 27173  		prg.beginTokenList(*(*prg.eqtb[everyJobLoc-1].hh()).rh(), quarterword(everyJobText))
 27174  	}
 27175  
 27176  bigSwitch:
 27177  	prg.getXToken()
 27178  
 27179  reswitch:
 27180  	if prg.interrupt != 0 {
 27181  		if prg.okToInterrupt {
 27182  			prg.backInput()
 27183  			{
 27184  				if prg.interrupt != 0 {
 27185  					prg.pauseForInstructions()
 27186  				}
 27187  			}
 27188  			goto bigSwitch
 27189  		}
 27190  	}
 27191  	// if panicking then check_mem(false);   [  ]
 27192  	if *prg.eqtb[intBase+tracingCommandsCode-1].int() > 0 {
 27193  		prg.showCurCmdChr()
 27194  	}
 27195  	switch abs(int32(prg.curList.modeField)) + int32(prg.curCmd) {
 27196  	case hmode + 11, hmode + 12, hmode + 68:
 27197  		goto mainLoop
 27198  	case hmode + 16:
 27199  		prg.scanCharNum()
 27200  		prg.curChr = uint16(prg.curVal)
 27201  		goto mainLoop
 27202  	case hmode + 65:
 27203  		prg.getXToken()
 27204  		if int32(prg.curCmd) == letter || int32(prg.curCmd) == otherChar || int32(prg.curCmd) == charGiven || int32(prg.curCmd) == charNum {
 27205  			prg.cancelBoundary = true
 27206  		}
 27207  
 27208  		goto reswitch
 27209  
 27210  	case hmode + 10:
 27211  		if int32(*(*prg.curList.auxField.hh()).lh()) == 1000 {
 27212  			goto appendNormalSpace
 27213  		} else {
 27214  			prg.appSpace()
 27215  		}
 27216  	case hmode + 64, mmode + 64:
 27217  		goto appendNormalSpace
 27218  	// \4
 27219  	// Cases of |main_control| that are not part of the inner loop
 27220  	case vmode + 0, hmode + 0, mmode + 0, vmode + 10,
 27221  		mmode + 10, mmode + 65:
 27222  	case vmode + 39, hmode + 39, mmode + 39:
 27223  		for {
 27224  			prg.getXToken()
 27225  			if int32(prg.curCmd) != spacer {
 27226  				break
 27227  			}
 27228  		}
 27229  
 27230  		goto reswitch
 27231  
 27232  	case vmode + 14:
 27233  		if prg.itsAllOver() {
 27234  			goto exit
 27235  		} // this is the only way out
 27236  	// \4
 27237  	// Forbidden cases detected in |main_control|
 27238  	case vmode + 22, hmode + 21, mmode + 21, vmode + 70,
 27239  		hmode + 70, mmode + 70, vmode + 38, vmode + 44,
 27240  		vmode + 48, hmode + 48, vmode + 6, hmode + 6,
 27241  		mmode + 6:
 27242  		prg.reportIllegalCase()
 27243  
 27244  	// Math-only cases in non-math modes, or vice versa
 27245  	case vmode + 7, hmode + 7, vmode + 8, hmode + 8,
 27246  		vmode + 17, hmode + 17, vmode + 69, hmode + 69,
 27247  		vmode + 50, hmode + 50, vmode + 15, hmode + 15,
 27248  		vmode + 49, hmode + 49, vmode + 52, hmode + 52,
 27249  		vmode + 66, hmode + 66, vmode + 53, hmode + 53,
 27250  		vmode + 54, hmode + 54, vmode + 56, hmode + 56,
 27251  		vmode + 55, hmode + 55, vmode + 30, hmode + 30,
 27252  		vmode + 51, hmode + 51, vmode + 28, hmode + 28,
 27253  		vmode + 46, hmode + 46, mmode + 9, mmode + 13,
 27254  		mmode + 14, mmode + 27, mmode + 24, mmode + 33,
 27255  		mmode + 36:
 27256  		prg.insertDollarSign()
 27257  	// \4
 27258  	// Cases of |main_control| that build boxes and lists
 27259  	case vmode + 36, hmode + 35, mmode + 35:
 27260  		{
 27261  			*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.scanRuleSpec()
 27262  			prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 27263  		}
 27264  		if abs(int32(prg.curList.modeField)) == vmode {
 27265  			*prg.curList.auxField.int() = -65536000
 27266  		} else if abs(int32(prg.curList.modeField)) == hmode {
 27267  			*(*prg.curList.auxField.hh()).lh() = 1000
 27268  		}
 27269  
 27270  	case vmode + 27, hmode + 26, mmode + 26, mmode + 28:
 27271  		prg.appendGlue()
 27272  	case vmode + 29, hmode + 29, mmode + 29, mmode + 30:
 27273  		prg.appendKern()
 27274  
 27275  	case vmode + 1, hmode + 1:
 27276  		prg.newSaveLevel(groupCode(simpleGroup))
 27277  	case vmode + 61, hmode + 61, mmode + 61:
 27278  		prg.newSaveLevel(groupCode(semiSimpleGroup))
 27279  	case vmode + 62, hmode + 62, mmode + 62:
 27280  		if int32(prg.curGroup) == semiSimpleGroup {
 27281  			prg.unsave()
 27282  		} else {
 27283  			prg.offSave()
 27284  		}
 27285  
 27286  	case vmode + 2, hmode + 2, mmode + 2:
 27287  		prg.handleRightBrace()
 27288  
 27289  	case vmode + 21, hmode + 22, mmode + 22:
 27290  		t = int32(prg.curChr)
 27291  		prg.scanDimen(false, false, false)
 27292  		if t == 0 {
 27293  			prg.scanBox(prg.curVal)
 27294  		} else {
 27295  			prg.scanBox(-prg.curVal)
 27296  		}
 27297  
 27298  	case vmode + 31, hmode + 31, mmode + 31:
 27299  		prg.scanBox(010000000000 + 513 - aLeaders + int32(prg.curChr))
 27300  	case vmode + 20, hmode + 20, mmode + 20:
 27301  		prg.beginBox(0)
 27302  
 27303  	case vmode + 43:
 27304  		prg.newGraf(int32(prg.curChr) > 0)
 27305  	case vmode + 11, vmode + 12, vmode + 16, vmode + 68,
 27306  		vmode + 3, vmode + 23, vmode + 35, vmode + 45,
 27307  		vmode + 47, vmode + 26, vmode + 33, vmode + 64,
 27308  		vmode + 65: //
 27309  
 27310  		prg.backInput()
 27311  		prg.newGraf(true)
 27312  
 27313  	case hmode + 43, mmode + 43:
 27314  		prg.indentInHmode()
 27315  
 27316  	case vmode + 13:
 27317  		prg.normalParagraph()
 27318  		if int32(prg.curList.modeField) > 0 {
 27319  			prg.buildPage()
 27320  		}
 27321  
 27322  	case hmode + 13:
 27323  		if prg.alignState < 0 {
 27324  			prg.offSave()
 27325  		} // this tries to
 27326  		//     recover from an alignment that didn't end properly
 27327  
 27328  		prg.endGraf() // this takes us to the enclosing mode, if |mode>0|
 27329  		if int32(prg.curList.modeField) == vmode {
 27330  			prg.buildPage()
 27331  		}
 27332  
 27333  	case hmode + 14, hmode + 27, hmode + 36, hmode + 24,
 27334  		hmode + 32:
 27335  		prg.headForVmode()
 27336  
 27337  	case vmode + 37, hmode + 37, mmode + 37, hmode + 38,
 27338  		mmode + 38:
 27339  		prg.beginInsertOrAdjust()
 27340  	case vmode + 18, hmode + 18, mmode + 18:
 27341  		prg.makeMark()
 27342  
 27343  	case vmode + 42, hmode + 42, mmode + 42:
 27344  		prg.appendPenalty()
 27345  
 27346  	case vmode + 25, hmode + 25, mmode + 25:
 27347  		prg.deleteLast()
 27348  
 27349  	case vmode + 24, hmode + 23, mmode + 23:
 27350  		prg.unpackage()
 27351  
 27352  	case hmode + 44:
 27353  		prg.appendItalicCorrection()
 27354  	case mmode + 44:
 27355  		*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newKern(scaled(0))
 27356  		prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 27357  
 27358  	case hmode + 47, mmode + 47:
 27359  		prg.appendDiscretionary()
 27360  
 27361  	case hmode + 45:
 27362  		prg.makeAccent()
 27363  
 27364  	case vmode + 5, hmode + 5, mmode + 5, vmode + 4,
 27365  		hmode + 4, mmode + 4:
 27366  		prg.alignError()
 27367  	case vmode + 34, hmode + 34, mmode + 34:
 27368  		prg.noAlignError()
 27369  	case vmode + 63, hmode + 63, mmode + 63:
 27370  		prg.omitError()
 27371  
 27372  	case vmode + 32, hmode + 33:
 27373  		prg.initAlign()
 27374  	case mmode + 32:
 27375  		if prg.privileged() {
 27376  			if int32(prg.curGroup) == mathShiftGroup {
 27377  				prg.initAlign()
 27378  			} else {
 27379  				prg.offSave()
 27380  			}
 27381  		}
 27382  	case vmode + 9, hmode + 9:
 27383  		prg.doEndv()
 27384  
 27385  	case vmode + 67, hmode + 67, mmode + 67:
 27386  		prg.csError()
 27387  
 27388  	case hmode + 3:
 27389  		prg.initMath()
 27390  
 27391  	case mmode + 48:
 27392  		if prg.privileged() {
 27393  			if int32(prg.curGroup) == mathShiftGroup {
 27394  				prg.startEqNo()
 27395  			} else {
 27396  				prg.offSave()
 27397  			}
 27398  		}
 27399  
 27400  	case mmode + 1:
 27401  		{
 27402  			*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newNoad()
 27403  			prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 27404  		}
 27405  		prg.backInput()
 27406  		prg.scanMath(halfword(int32(prg.curList.tailField) + 1))
 27407  
 27408  	case mmode + 11, mmode + 12, mmode + 68:
 27409  		prg.setMathChar(int32(*(*prg.eqtb[mathCodeBase+int32(prg.curChr)-1].hh()).rh()) - 0)
 27410  	case mmode + 16:
 27411  		prg.scanCharNum()
 27412  		prg.curChr = uint16(prg.curVal)
 27413  		prg.setMathChar(int32(*(*prg.eqtb[mathCodeBase+int32(prg.curChr)-1].hh()).rh()) - 0)
 27414  
 27415  	case mmode + 17:
 27416  		prg.scanFifteenBitInt()
 27417  		prg.setMathChar(prg.curVal)
 27418  
 27419  	case mmode + 69:
 27420  		prg.setMathChar(int32(prg.curChr))
 27421  	case mmode + 15:
 27422  		prg.scanTwentySevenBitInt()
 27423  		prg.setMathChar(prg.curVal / 010000)
 27424  
 27425  	case mmode + 50:
 27426  		{
 27427  			*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newNoad()
 27428  			prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 27429  		}
 27430  		*(*prg.mem[prg.curList.tailField].hh()).b0() = byte(prg.curChr)
 27431  		prg.scanMath(halfword(int32(prg.curList.tailField) + 1))
 27432  
 27433  	case mmode + 51:
 27434  		prg.mathLimitSwitch()
 27435  
 27436  	case mmode + 66:
 27437  		prg.mathRadical()
 27438  
 27439  	case mmode + 45, mmode + 46:
 27440  		prg.mathAc()
 27441  
 27442  	case mmode + 56:
 27443  		prg.scanSpec(groupCode(vcenterGroup), false)
 27444  		prg.normalParagraph()
 27445  		prg.pushNest()
 27446  		prg.curList.modeField = int16(-vmode)
 27447  		*prg.curList.auxField.int() = -65536000
 27448  		if int32(*(*prg.eqtb[everyVboxLoc-1].hh()).rh()) != 0 {
 27449  			prg.beginTokenList(*(*prg.eqtb[everyVboxLoc-1].hh()).rh(), quarterword(everyVboxText))
 27450  		}
 27451  
 27452  	case mmode + 53:
 27453  		*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newStyle(smallNumber(prg.curChr))
 27454  		prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 27455  	case mmode + 55:
 27456  		{
 27457  			*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newGlue(halfword(memBot))
 27458  			prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 27459  		}
 27460  		*(*prg.mem[prg.curList.tailField].hh()).b1() = byte(condMathGlue)
 27461  
 27462  	case mmode + 54:
 27463  		prg.appendChoices()
 27464  
 27465  	case mmode + 8, mmode + 7:
 27466  		prg.subSup()
 27467  
 27468  	case mmode + 52:
 27469  		prg.mathFraction()
 27470  
 27471  	case mmode + 49:
 27472  		prg.mathLeftRight()
 27473  
 27474  	case mmode + 3:
 27475  		if int32(prg.curGroup) == mathShiftGroup {
 27476  			prg.afterMath()
 27477  		} else {
 27478  			prg.offSave()
 27479  		}
 27480  
 27481  	// \4
 27482  	// Cases of |main_control| that don't depend on |mode|
 27483  	case vmode + 71, hmode + 71, mmode + 71, vmode + 72,
 27484  		hmode + 72, mmode + 72, vmode + 73, hmode + 73,
 27485  		mmode + 73, vmode + 74, hmode + 74, mmode + 74,
 27486  		vmode + 75, hmode + 75, mmode + 75, vmode + 76,
 27487  		hmode + 76, mmode + 76, vmode + 77, hmode + 77,
 27488  		mmode + 77, vmode + 78, hmode + 78, mmode + 78,
 27489  		vmode + 79, hmode + 79, mmode + 79, vmode + 80,
 27490  		hmode + 80, mmode + 80, vmode + 81, hmode + 81,
 27491  		mmode + 81, vmode + 82, hmode + 82, mmode + 82,
 27492  		vmode + 83, hmode + 83, mmode + 83, vmode + 84,
 27493  		hmode + 84, mmode + 84, vmode + 85, hmode + 85,
 27494  		mmode + 85, vmode + 86, hmode + 86, mmode + 86,
 27495  		vmode + 87, hmode + 87, mmode + 87, vmode + 88,
 27496  		hmode + 88, mmode + 88, vmode + 89, hmode + 89,
 27497  		mmode + 89, vmode + 90, hmode + 90, mmode + 90,
 27498  		vmode + 91, hmode + 91, mmode + 91, vmode + 92,
 27499  		hmode + 92, mmode + 92, vmode + 93, hmode + 93,
 27500  		mmode + 93, vmode + 94, hmode + 94, mmode + 94,
 27501  		vmode + 95, hmode + 95, mmode + 95, vmode + 96,
 27502  		hmode + 96, mmode + 96, vmode + 97, hmode + 97,
 27503  		mmode + 97, vmode + 98, hmode + 98, mmode + 98,
 27504  		vmode + 99, hmode + 99, mmode + 99, vmode + 100,
 27505  		hmode + 100, mmode + 100:
 27506  		prg.prefixedCommand()
 27507  
 27508  	case vmode + 40, hmode + 40, mmode + 40:
 27509  		prg.getToken()
 27510  		prg.afterToken = prg.curTok
 27511  
 27512  	case vmode + 41, hmode + 41, mmode + 41:
 27513  		prg.getToken()
 27514  		prg.saveForAfter(prg.curTok)
 27515  
 27516  	case vmode + 60, hmode + 60, mmode + 60:
 27517  		prg.openOrCloseIn()
 27518  
 27519  	case vmode + 58, hmode + 58, mmode + 58:
 27520  		prg.issueMessage()
 27521  
 27522  	case vmode + 57, hmode + 57, mmode + 57:
 27523  		prg.shiftCase()
 27524  
 27525  	case vmode + 19, hmode + 19, mmode + 19:
 27526  		prg.showWhatever()
 27527  
 27528  	// \4
 27529  	// Cases of |main_control| that are for extensions to \TeX
 27530  	case vmode + 59, hmode + 59, mmode + 59:
 27531  		prg.doExtension()
 27532  
 27533  	} // of the big |case| statement
 27534  	// of the big |case| statement
 27535  	goto bigSwitch
 27536  
 27537  mainLoop:
 27538  	prg.mainS = int32(*(*prg.eqtb[sfCodeBase+int32(prg.curChr)-1].hh()).rh())
 27539  	if prg.mainS == 1000 {
 27540  		*(*prg.curList.auxField.hh()).lh() = 1000
 27541  	} else if prg.mainS < 1000 {
 27542  		if prg.mainS > 0 {
 27543  			*(*prg.curList.auxField.hh()).lh() = uint16(prg.mainS)
 27544  		}
 27545  	} else if int32(*(*prg.curList.auxField.hh()).lh()) < 1000 {
 27546  		*(*prg.curList.auxField.hh()).lh() = 1000
 27547  	} else {
 27548  		*(*prg.curList.auxField.hh()).lh() = uint16(prg.mainS)
 27549  	}
 27550  
 27551  	prg.mainF = byte(*(*prg.eqtb[curFontLoc-1].hh()).rh())
 27552  	prg.bchar = prg.fontBchar[prg.mainF]
 27553  	prg.falseBchar = prg.fontFalseBchar[prg.mainF]
 27554  	if int32(prg.curList.modeField) > 0 {
 27555  		if *prg.eqtb[intBase+languageCode-1].int() != int32(*(*prg.curList.auxField.hh()).rh()) {
 27556  			prg.fixLanguage()
 27557  		}
 27558  	}
 27559  	/*   */ {
 27560  		prg.ligStack = prg.avail
 27561  		if int32(prg.ligStack) == 0 {
 27562  			prg.ligStack = prg.getAvail()
 27563  		} else {
 27564  			prg.avail = *(*prg.mem[prg.ligStack].hh()).rh()
 27565  			*(*prg.mem[prg.ligStack].hh()).rh() = 0 /*    dyn_used:= dyn_used+1 ; [  ] */
 27566  		}
 27567  	}
 27568  	*(*prg.mem[prg.ligStack].hh()).b0() = prg.mainF
 27569  	prg.curL = uint16(int32(prg.curChr) + minQuarterword)
 27570  	*(*prg.mem[prg.ligStack].hh()).b1() = byte(prg.curL)
 27571  
 27572  	prg.curQ = prg.curList.tailField
 27573  	if prg.cancelBoundary {
 27574  		prg.cancelBoundary = false
 27575  		prg.mainK = uint16(nonAddress)
 27576  	} else {
 27577  		prg.mainK = prg.bcharLabel[prg.mainF]
 27578  	}
 27579  	if int32(prg.mainK) == nonAddress {
 27580  		goto mainLoopMove_plus_2
 27581  	} // no left boundary processing
 27582  	prg.curR = prg.curL
 27583  	prg.curL = uint16(256 + minQuarterword)
 27584  
 27585  	goto mainLigLoop_plus_1 // begin with cursor after left boundary
 27586  
 27587  	// begin with cursor after left boundary
 27588  
 27589  mainLoopWrapup:
 27590  	if int32(prg.curL) < 256+minQuarterword {
 27591  		if int32(*(*prg.mem[prg.curQ].hh()).rh()) > 0 {
 27592  			if int32(*(*prg.mem[prg.curList.tailField].hh()).b1()) == prg.hyphenChar[prg.mainF]+minQuarterword {
 27593  				prg.insDisc = true
 27594  			}
 27595  		}
 27596  		if prg.ligaturePresent {
 27597  			prg.mainP = prg.newLigature(prg.mainF, quarterword(prg.curL), *(*prg.mem[prg.curQ].hh()).rh())
 27598  			if prg.lftHit {
 27599  				*(*prg.mem[prg.mainP].hh()).b1() = 2
 27600  				prg.lftHit = false
 27601  			}
 27602  			if prg.rtHit {
 27603  				if int32(prg.ligStack) == 0 {
 27604  					*(*prg.mem[prg.mainP].hh()).b1() = byte(int32(*(*prg.mem[prg.mainP].hh()).b1()) + 1)
 27605  					prg.rtHit = false
 27606  				}
 27607  			}
 27608  			*(*prg.mem[prg.curQ].hh()).rh() = prg.mainP
 27609  			prg.curList.tailField = prg.mainP
 27610  			prg.ligaturePresent = false
 27611  		}
 27612  		if prg.insDisc {
 27613  			prg.insDisc = false
 27614  			if int32(prg.curList.modeField) > 0 {
 27615  				*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newDisc()
 27616  				prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 27617  			}
 27618  		}
 27619  	}
 27620  
 27621  mainLoopMove:
 27622  	if int32(prg.ligStack) == 0 {
 27623  		goto reswitch
 27624  	}
 27625  	prg.curQ = prg.curList.tailField
 27626  	prg.curL = uint16(*(*prg.mem[prg.ligStack].hh()).b1())
 27627  
 27628  mainLoopMove_plus_1:
 27629  	if !(int32(prg.ligStack) >= int32(prg.hiMemMin)) {
 27630  		goto mainLoopMoveLig
 27631  	}
 27632  
 27633  mainLoopMove_plus_2:
 27634  	if int32(prg.curChr) < int32(prg.fontBc[prg.mainF]) || int32(prg.curChr) > int32(prg.fontEc[prg.mainF]) {
 27635  		prg.charWarning(prg.mainF, eightBits(prg.curChr))
 27636  		{
 27637  			*(*prg.mem[prg.ligStack].hh()).rh() = prg.avail
 27638  			prg.avail = prg.ligStack /*    dyn_used:= dyn_used-1 ; [  ] */
 27639  		}
 27640  		goto bigSwitch
 27641  	}
 27642  	prg.mainI = *prg.fontInfo[prg.charBase[prg.mainF]+int32(prg.curL)].qqqq()
 27643  	if !(int32(prg.mainI.b0) > minQuarterword) {
 27644  		prg.charWarning(prg.mainF, eightBits(prg.curChr))
 27645  		{
 27646  			*(*prg.mem[prg.ligStack].hh()).rh() = prg.avail
 27647  			prg.avail = prg.ligStack /*    dyn_used:= dyn_used-1 ; [  ] */
 27648  		}
 27649  		goto bigSwitch
 27650  	}
 27651  	*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.ligStack
 27652  	prg.curList.tailField = prg.ligStack
 27653  
 27654  mainLoopLookahead:
 27655  	prg.getNext() // set only |cur_cmd| and |cur_chr|, for speed
 27656  	if int32(prg.curCmd) == letter {
 27657  		goto mainLoopLookahead_plus_1
 27658  	}
 27659  	if int32(prg.curCmd) == otherChar {
 27660  		goto mainLoopLookahead_plus_1
 27661  	}
 27662  	if int32(prg.curCmd) == charGiven {
 27663  		goto mainLoopLookahead_plus_1
 27664  	}
 27665  	prg.xToken() // now expand and set |cur_cmd|, |cur_chr|, |cur_tok|
 27666  	if int32(prg.curCmd) == letter {
 27667  		goto mainLoopLookahead_plus_1
 27668  	}
 27669  	if int32(prg.curCmd) == otherChar {
 27670  		goto mainLoopLookahead_plus_1
 27671  	}
 27672  	if int32(prg.curCmd) == charGiven {
 27673  		goto mainLoopLookahead_plus_1
 27674  	}
 27675  	if int32(prg.curCmd) == charNum {
 27676  		prg.scanCharNum()
 27677  		prg.curChr = uint16(prg.curVal)
 27678  		goto mainLoopLookahead_plus_1
 27679  	}
 27680  	if int32(prg.curCmd) == noBoundary {
 27681  		prg.bchar = uint16(256 + minQuarterword)
 27682  	}
 27683  	prg.curR = prg.bchar
 27684  	prg.ligStack = 0
 27685  	goto mainLigLoop
 27686  
 27687  mainLoopLookahead_plus_1:
 27688  	prg.mainS = int32(*(*prg.eqtb[sfCodeBase+int32(prg.curChr)-1].hh()).rh())
 27689  	if prg.mainS == 1000 {
 27690  		*(*prg.curList.auxField.hh()).lh() = 1000
 27691  	} else if prg.mainS < 1000 {
 27692  		if prg.mainS > 0 {
 27693  			*(*prg.curList.auxField.hh()).lh() = uint16(prg.mainS)
 27694  		}
 27695  	} else if int32(*(*prg.curList.auxField.hh()).lh()) < 1000 {
 27696  		*(*prg.curList.auxField.hh()).lh() = 1000
 27697  	} else {
 27698  		*(*prg.curList.auxField.hh()).lh() = uint16(prg.mainS)
 27699  	}
 27700  	/*   */ {
 27701  		prg.ligStack = prg.avail
 27702  		if int32(prg.ligStack) == 0 {
 27703  			prg.ligStack = prg.getAvail()
 27704  		} else {
 27705  			prg.avail = *(*prg.mem[prg.ligStack].hh()).rh()
 27706  			*(*prg.mem[prg.ligStack].hh()).rh() = 0 /*    dyn_used:= dyn_used+1 ; [  ] */
 27707  		}
 27708  	}
 27709  	*(*prg.mem[prg.ligStack].hh()).b0() = prg.mainF
 27710  	prg.curR = uint16(int32(prg.curChr) + minQuarterword)
 27711  	*(*prg.mem[prg.ligStack].hh()).b1() = byte(prg.curR)
 27712  	if int32(prg.curR) == int32(prg.falseBchar) {
 27713  		prg.curR = uint16(256 + minQuarterword)
 27714  	}
 27715  
 27716  mainLigLoop:
 27717  	if (int32(prg.mainI.b2)-minQuarterword)%4 != ligTag {
 27718  		goto mainLoopWrapup
 27719  	}
 27720  	if int32(prg.curR) == 256+minQuarterword {
 27721  		goto mainLoopWrapup
 27722  	}
 27723  	prg.mainK = uint16(prg.ligKernBase[prg.mainF] + int32(prg.mainI.b3))
 27724  	prg.mainJ = *prg.fontInfo[prg.mainK].qqqq()
 27725  	if int32(prg.mainJ.b0) <= 128+minQuarterword {
 27726  		goto mainLigLoop_plus_2
 27727  	}
 27728  	prg.mainK = uint16(prg.ligKernBase[prg.mainF] + 256*int32(prg.mainJ.b2) + int32(prg.mainJ.b3) + 32768 - 256*(128+minQuarterword))
 27729  
 27730  mainLigLoop_plus_1:
 27731  	prg.mainJ = *prg.fontInfo[prg.mainK].qqqq()
 27732  
 27733  mainLigLoop_plus_2:
 27734  	if int32(prg.mainJ.b1) == int32(prg.curR) {
 27735  		if int32(prg.mainJ.b0) <= 128+minQuarterword {
 27736  			if int32(prg.mainJ.b2) >= 128+minQuarterword {
 27737  				if int32(prg.curL) < 256+minQuarterword {
 27738  					if int32(*(*prg.mem[prg.curQ].hh()).rh()) > 0 {
 27739  						if int32(*(*prg.mem[prg.curList.tailField].hh()).b1()) == prg.hyphenChar[prg.mainF]+minQuarterword {
 27740  							prg.insDisc = true
 27741  						}
 27742  					}
 27743  					if prg.ligaturePresent {
 27744  						prg.mainP = prg.newLigature(prg.mainF, quarterword(prg.curL), *(*prg.mem[prg.curQ].hh()).rh())
 27745  						if prg.lftHit {
 27746  							*(*prg.mem[prg.mainP].hh()).b1() = 2
 27747  							prg.lftHit = false
 27748  						}
 27749  						if prg.rtHit {
 27750  							if int32(prg.ligStack) == 0 {
 27751  								*(*prg.mem[prg.mainP].hh()).b1() = byte(int32(*(*prg.mem[prg.mainP].hh()).b1()) + 1)
 27752  								prg.rtHit = false
 27753  							}
 27754  						}
 27755  						*(*prg.mem[prg.curQ].hh()).rh() = prg.mainP
 27756  						prg.curList.tailField = prg.mainP
 27757  						prg.ligaturePresent = false
 27758  					}
 27759  					if prg.insDisc {
 27760  						prg.insDisc = false
 27761  						if int32(prg.curList.modeField) > 0 {
 27762  							*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newDisc()
 27763  							prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 27764  						}
 27765  					}
 27766  				}
 27767  				{
 27768  					*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newKern(*prg.fontInfo[prg.kernBase[prg.mainF]+256*int32(prg.mainJ.b2)+int32(prg.mainJ.b3)].int())
 27769  					prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 27770  				}
 27771  				goto mainLoopMove
 27772  			}
 27773  			if int32(prg.curL) == 256+minQuarterword {
 27774  				prg.lftHit = true
 27775  			} else if int32(prg.ligStack) == 0 {
 27776  				prg.rtHit = true
 27777  			}
 27778  			{
 27779  				if prg.interrupt != 0 {
 27780  					prg.pauseForInstructions()
 27781  				}
 27782  			} // allow a way out in case there's an infinite ligature loop
 27783  			switch prg.mainJ.b2 {
 27784  			case 1 + minQuarterword, 5 + minQuarterword:
 27785  				prg.curL = uint16(prg.mainJ.b3) // \.[=:\?], \.[=:\?>]
 27786  				prg.mainI = *prg.fontInfo[prg.charBase[prg.mainF]+int32(prg.curL)].qqqq()
 27787  				prg.ligaturePresent = true
 27788  
 27789  			case 2 + minQuarterword, 6 + minQuarterword:
 27790  				prg.curR = uint16(prg.mainJ.b3) // \.[\?=:], \.[\?=:>]
 27791  				if int32(prg.ligStack) == 0 {
 27792  					prg.ligStack = prg.newLigItem(quarterword(prg.curR))
 27793  					prg.bchar = uint16(256 + minQuarterword)
 27794  				} else if int32(prg.ligStack) >= int32(prg.hiMemMin) {
 27795  					prg.mainP = prg.ligStack
 27796  					prg.ligStack = prg.newLigItem(quarterword(prg.curR))
 27797  					*(*prg.mem[int32(prg.ligStack)+1].hh()).rh() = prg.mainP
 27798  				} else {
 27799  					*(*prg.mem[prg.ligStack].hh()).b1() = byte(prg.curR)
 27800  				}
 27801  
 27802  			case 3 + minQuarterword:
 27803  				prg.curR = uint16(prg.mainJ.b3) // \.[\?=:\?]
 27804  				prg.mainP = prg.ligStack
 27805  				prg.ligStack = prg.newLigItem(quarterword(prg.curR))
 27806  				*(*prg.mem[prg.ligStack].hh()).rh() = prg.mainP
 27807  
 27808  			case 7 + minQuarterword, 11 + minQuarterword:
 27809  				if int32(prg.curL) < 256+minQuarterword {
 27810  					if int32(*(*prg.mem[prg.curQ].hh()).rh()) > 0 {
 27811  						if int32(*(*prg.mem[prg.curList.tailField].hh()).b1()) == prg.hyphenChar[prg.mainF]+minQuarterword {
 27812  							prg.insDisc = true
 27813  						}
 27814  					}
 27815  					if prg.ligaturePresent {
 27816  						prg.mainP = prg.newLigature(prg.mainF, quarterword(prg.curL), *(*prg.mem[prg.curQ].hh()).rh())
 27817  						if prg.lftHit {
 27818  							*(*prg.mem[prg.mainP].hh()).b1() = 2
 27819  							prg.lftHit = false
 27820  						}
 27821  						if false {
 27822  							if int32(prg.ligStack) == 0 {
 27823  								*(*prg.mem[prg.mainP].hh()).b1() = byte(int32(*(*prg.mem[prg.mainP].hh()).b1()) + 1)
 27824  								prg.rtHit = false
 27825  							}
 27826  						}
 27827  						*(*prg.mem[prg.curQ].hh()).rh() = prg.mainP
 27828  						prg.curList.tailField = prg.mainP
 27829  						prg.ligaturePresent = false
 27830  					}
 27831  					if prg.insDisc {
 27832  						prg.insDisc = false
 27833  						if int32(prg.curList.modeField) > 0 {
 27834  							*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newDisc()
 27835  							prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 27836  						}
 27837  					}
 27838  				} // \.[\?=:\?>], \.[\?=:\?>>]
 27839  				prg.curQ = prg.curList.tailField
 27840  				prg.curL = uint16(prg.mainJ.b3)
 27841  				prg.mainI = *prg.fontInfo[prg.charBase[prg.mainF]+int32(prg.curL)].qqqq()
 27842  				prg.ligaturePresent = true
 27843  
 27844  			default:
 27845  				prg.curL = uint16(prg.mainJ.b3)
 27846  				prg.ligaturePresent = true // \.[=:]
 27847  				if int32(prg.ligStack) == 0 {
 27848  					goto mainLoopWrapup
 27849  				} else {
 27850  					goto mainLoopMove_plus_1
 27851  				}
 27852  
 27853  			}
 27854  			if int32(prg.mainJ.b2) > 4+minQuarterword {
 27855  				if int32(prg.mainJ.b2) != 7+minQuarterword {
 27856  					goto mainLoopWrapup
 27857  				}
 27858  			}
 27859  			if int32(prg.curL) < 256+minQuarterword {
 27860  				goto mainLigLoop
 27861  			}
 27862  			prg.mainK = prg.bcharLabel[prg.mainF]
 27863  			goto mainLigLoop_plus_1
 27864  		}
 27865  	}
 27866  	if int32(prg.mainJ.b0) == 0+minQuarterword {
 27867  		prg.mainK = uint16(int32(prg.mainK) + 1)
 27868  	} else {
 27869  		if int32(prg.mainJ.b0) >= 128+minQuarterword {
 27870  			goto mainLoopWrapup
 27871  		}
 27872  		prg.mainK = uint16(int32(prg.mainK) + int32(prg.mainJ.b0) - minQuarterword + 1)
 27873  	}
 27874  
 27875  	goto mainLigLoop_plus_1
 27876  
 27877  mainLoopMoveLig:
 27878  	prg.mainP = *(*prg.mem[int32(prg.ligStack)+1].hh()).rh()
 27879  	if int32(prg.mainP) > 0 {
 27880  		*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.mainP
 27881  		prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
 27882  	} // append a single character
 27883  	prg.tempPtr = prg.ligStack
 27884  	prg.ligStack = *(*prg.mem[prg.tempPtr].hh()).rh()
 27885  	prg.freeNode(prg.tempPtr, halfword(smallNodeSize))
 27886  	prg.mainI = *prg.fontInfo[prg.charBase[prg.mainF]+int32(prg.curL)].qqqq()
 27887  	prg.ligaturePresent = true
 27888  	if int32(prg.ligStack) == 0 {
 27889  		if int32(prg.mainP) > 0 {
 27890  			goto mainLoopLookahead
 27891  		} else {
 27892  			prg.curR = prg.bchar
 27893  		}
 27894  	} else {
 27895  		prg.curR = uint16(*(*prg.mem[prg.ligStack].hh()).b1())
 27896  	}
 27897  
 27898  	goto mainLigLoop
 27899  
 27900  appendNormalSpace:
 27901  	if int32(*(*prg.eqtb[glueBase+spaceSkipCode-1].hh()).rh()) == memBot {
 27902  		{
 27903  			prg.mainP = prg.fontGlue[*(*prg.eqtb[curFontLoc-1].hh()).rh()]
 27904  			if int32(prg.mainP) == 0 {
 27905  				prg.mainP = prg.newSpec(halfword(memBot))
 27906  				prg.mainK = uint16(prg.paramBase[*(*prg.eqtb[curFontLoc-1].hh()).rh()] + spaceCode)
 27907  				*prg.mem[int32(prg.mainP)+widthOffset].int() = *prg.fontInfo[prg.mainK].int() // that's |space(cur_font)|
 27908  				*prg.mem[int32(prg.mainP)+2].int() = *prg.fontInfo[int32(prg.mainK)+1].int()  // and |space_stretch(cur_font)|
 27909  				*prg.mem[int32(prg.mainP)+3].int() = *prg.fontInfo[int32(prg.mainK)+2].int()  // and |space_shrink(cur_font)|
 27910  				prg.fontGlue[*(*prg.eqtb[curFontLoc-1].hh()).rh()] = prg.mainP
 27911  			}
 27912  		}
 27913  		prg.tempPtr = prg.newGlue(prg.mainP)
 27914  	} else {
 27915  		prg.tempPtr = prg.newParamGlue(smallNumber(spaceSkipCode))
 27916  	}
 27917  	*(*prg.mem[prg.curList.tailField].hh()).rh() = prg.tempPtr
 27918  	prg.curList.tailField = prg.tempPtr
 27919  
 27920  	goto bigSwitch
 27921  
 27922  exit:
 27923  } // \2
 27924  
 27925  func (prg *prg) giveErrHelp() {
 27926  	prg.tokenShow(*(*prg.eqtb[errHelpLoc-1].hh()).rh())
 27927  }
 27928  
 27929  // 1303.
 27930  
 27931  // tangle:pos tex.web:23781:5:
 27932  
 27933  // Corresponding to the procedure that dumps a format file, we have a function
 27934  // that reads one in. The function returns |false| if the dumped format is
 27935  // incompatible with the present \TeX\ table sizes, etc.
 27936  // \4
 27937  // Declare the function called |open_fmt_file|
 27938  func (prg *prg) openFmtFile() (r bool) {
 27939  	var (
 27940  		j /* 0..bufSize */ uint16 // the first space after the format file name
 27941  	)
 27942  	j = prg.curInput.locField
 27943  	if int32(prg.buffer[prg.curInput.locField]) == '&' {
 27944  		prg.curInput.locField = uint16(int32(prg.curInput.locField) + 1)
 27945  		j = prg.curInput.locField
 27946  		prg.buffer[prg.last] = ' '
 27947  		for int32(prg.buffer[j]) != ' ' {
 27948  			j = uint16(int32(j) + 1)
 27949  		}
 27950  		prg.packBufferedName(smallNumber(0), int32(prg.curInput.locField), int32(j)-1) // try first without the system file area
 27951  		if prg.wOpenIn(prg.fmtFile) {
 27952  			goto found
 27953  		}
 27954  		prg.packBufferedName(smallNumber(formatAreaLength), int32(prg.curInput.locField), int32(j)-1)
 27955  		// now try the system format file area
 27956  		if prg.wOpenIn(prg.fmtFile) {
 27957  			goto found
 27958  		}
 27959  
 27960  		prg.termOut.Writeln("Sorry, I can't find that format;", " will try PLAIN.")
 27961  		// \xref[Sorry, I can't find...]
 27962  
 27963  	}
 27964  	// now pull out all the stops: try for the system \.[plain] file
 27965  	prg.packBufferedName(smallNumber(formatDefaultLength-formatExtLength), 1, 0)
 27966  	if !prg.wOpenIn(prg.fmtFile) {
 27967  		prg.termOut.Writeln("I can't find the PLAIN format file!")
 27968  		// \xref[I can't find PLAIN...]
 27969  		// \xref[plain]
 27970  		r = false
 27971  		goto exit
 27972  	}
 27973  
 27974  found:
 27975  	prg.curInput.locField = j
 27976  	r = true
 27977  
 27978  exit:
 27979  	;
 27980  	return r
 27981  }
 27982  
 27983  func (prg *prg) loadFmtFile() (r bool) {
 27984  	var (
 27985  		j, k int32        // all-purpose indices
 27986  		p, q halfword     // all-purpose pointers
 27987  		x    int32        // something undumped
 27988  		w    fourQuarters // four ASCII codes
 27989  	)
 27990  	x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 27991  	if x != 504454778 {
 27992  		goto badFmt
 27993  	} // check that strings are the same
 27994  	{
 27995  		prg.fmtFile.Get()
 27996  		x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 27997  	}
 27998  	if x != memBot {
 27999  		goto badFmt
 28000  	}
 28001  	{
 28002  		prg.fmtFile.Get()
 28003  		x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28004  	}
 28005  	if x != 30000 {
 28006  		goto badFmt
 28007  	}
 28008  	{
 28009  		prg.fmtFile.Get()
 28010  		x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28011  	}
 28012  	if x != eqtbSize {
 28013  		goto badFmt
 28014  	}
 28015  	{
 28016  		prg.fmtFile.Get()
 28017  		x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28018  	}
 28019  	if x != hashPrime {
 28020  		goto badFmt
 28021  	}
 28022  	{
 28023  		prg.fmtFile.Get()
 28024  		x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28025  	}
 28026  	if x != hyphSize {
 28027  		goto badFmt
 28028  	}
 28029  
 28030  	// Undump the string pool
 28031  	{
 28032  		{
 28033  			prg.fmtFile.Get()
 28034  			x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28035  		}
 28036  		if x < 0 {
 28037  			goto badFmt
 28038  		}
 28039  		if x > poolSize {
 28040  			prg.termOut.Writeln("---! Must increase the ", "string pool size") /* \xref[Must increase the x]  */ /* \xref[Must increase the x]  */
 28041  			goto badFmt
 28042  		} else {
 28043  			prg.poolPtr = uint16(x)
 28044  		}
 28045  	}
 28046  	{
 28047  		{
 28048  			prg.fmtFile.Get()
 28049  			x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28050  		}
 28051  		if x < 0 {
 28052  			goto badFmt
 28053  		}
 28054  		if x > maxStrings {
 28055  			prg.termOut.Writeln("---! Must increase the ", "max strings") /* \xref[Must increase the x]  */ /* \xref[Must increase the x]  */
 28056  			goto badFmt
 28057  		} else {
 28058  			prg.strPtr = uint16(x)
 28059  		}
 28060  	}
 28061  	for ii := int32(0); ii <= int32(prg.strPtr); ii++ {
 28062  		k = ii
 28063  		_ = k
 28064  		{
 28065  			prg.fmtFile.Get()
 28066  			x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28067  		}
 28068  		if x < 0 || x > int32(prg.poolPtr) {
 28069  			goto badFmt
 28070  		} else {
 28071  			prg.strStart[k] = uint16(x)
 28072  		}
 28073  	}
 28074  	k = 0
 28075  	for k+4 < int32(prg.poolPtr) {
 28076  		{
 28077  			prg.fmtFile.Get()
 28078  			w = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).qqqq()
 28079  		}
 28080  		prg.strPool[k] = byte(int32(w.b0) - minQuarterword)
 28081  		prg.strPool[k+1] = byte(int32(w.b1) - minQuarterword)
 28082  		prg.strPool[k+2] = byte(int32(w.b2) - minQuarterword)
 28083  		prg.strPool[k+3] = byte(int32(w.b3) - minQuarterword)
 28084  		k = k + 4
 28085  	}
 28086  	k = int32(prg.poolPtr) - 4
 28087  	{
 28088  		prg.fmtFile.Get()
 28089  		w = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).qqqq()
 28090  	}
 28091  	prg.strPool[k] = byte(int32(w.b0) - minQuarterword)
 28092  	prg.strPool[k+1] = byte(int32(w.b1) - minQuarterword)
 28093  	prg.strPool[k+2] = byte(int32(w.b2) - minQuarterword)
 28094  	prg.strPool[k+3] = byte(int32(w.b3) - minQuarterword)
 28095  	prg.initStrPtr = prg.strPtr
 28096  	prg.initPoolPtr = prg.poolPtr
 28097  
 28098  	// Undump the dynamic memory
 28099  	{
 28100  		{
 28101  			prg.fmtFile.Get()
 28102  			x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28103  		}
 28104  		if x < memBot+glueSpecSize+glueSpecSize+glueSpecSize+glueSpecSize+glueSpecSize-1+1000 || x > 30000-13-1 {
 28105  			goto badFmt
 28106  		} else {
 28107  			prg.loMemMax = uint16(x)
 28108  		}
 28109  	}
 28110  	{
 28111  		{
 28112  			prg.fmtFile.Get()
 28113  			x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28114  		}
 28115  		if x < memBot+glueSpecSize+glueSpecSize+glueSpecSize+glueSpecSize+glueSpecSize-1+1 || x > int32(prg.loMemMax) {
 28116  			goto badFmt
 28117  		} else {
 28118  			prg.rover = uint16(x)
 28119  		}
 28120  	}
 28121  	p = uint16(memBot)
 28122  	q = prg.rover
 28123  	for {
 28124  		for ii := int32(p); ii <= int32(q)+1; ii++ {
 28125  			k = ii
 28126  			_ = k
 28127  			prg.fmtFile.Get()
 28128  			prg.mem[k] = *(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))
 28129  		}
 28130  		p = uint16(int32(q) + int32(*(*prg.mem[q].hh()).lh()))
 28131  		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) {
 28132  			goto badFmt
 28133  		}
 28134  		q = *(*prg.mem[int32(q)+1].hh()).rh()
 28135  		if int32(q) == int32(prg.rover) {
 28136  			break
 28137  		}
 28138  	}
 28139  	for ii := int32(p); ii <= int32(prg.loMemMax); ii++ {
 28140  		k = ii
 28141  		_ = k
 28142  		prg.fmtFile.Get()
 28143  		prg.mem[k] = *(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))
 28144  	}
 28145  	if memMin < memBot-2 {
 28146  		p = *(*prg.mem[int32(prg.rover)+1].hh()).lh()
 28147  		q = uint16(memMin + 1)
 28148  		*(*prg.mem[memMin].hh()).rh() = 0
 28149  		*(*prg.mem[memMin].hh()).lh() = 0 // we don't use the bottom word
 28150  		*(*prg.mem[int32(p)+1].hh()).rh() = q
 28151  		*(*prg.mem[int32(prg.rover)+1].hh()).lh() = q
 28152  
 28153  		*(*prg.mem[int32(q)+1].hh()).rh() = prg.rover
 28154  		*(*prg.mem[int32(q)+1].hh()).lh() = p
 28155  		*(*prg.mem[q].hh()).rh() = 65535
 28156  		*(*prg.mem[q].hh()).lh() = uint16(memBot - int32(q))
 28157  	}
 28158  	{
 28159  		{
 28160  			prg.fmtFile.Get()
 28161  			x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28162  		}
 28163  		if x < int32(prg.loMemMax)+1 || x > 30000-13 {
 28164  			goto badFmt
 28165  		} else {
 28166  			prg.hiMemMin = uint16(x)
 28167  		}
 28168  	}
 28169  	{
 28170  		{
 28171  			prg.fmtFile.Get()
 28172  			x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28173  		}
 28174  		if x < 0 || x > 30000 {
 28175  			goto badFmt
 28176  		} else {
 28177  			prg.avail = uint16(x)
 28178  		}
 28179  	}
 28180  	prg.memEnd = 30000
 28181  	for ii := int32(prg.hiMemMin); ii <= int32(prg.memEnd); ii++ {
 28182  		k = ii
 28183  		_ = k
 28184  		prg.fmtFile.Get()
 28185  		prg.mem[k] = *(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))
 28186  	}
 28187  	{
 28188  		prg.fmtFile.Get()
 28189  		prg.varUsed = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28190  	}
 28191  	{
 28192  		prg.fmtFile.Get()
 28193  		prg.dynUsed = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28194  	}
 28195  
 28196  	// Undump the table of equivalents
 28197  
 28198  	// Undump regions 1 to 6 of |eqtb|
 28199  	k = activeBase
 28200  	for {
 28201  		{
 28202  			prg.fmtFile.Get()
 28203  			x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28204  		}
 28205  		if x < 1 || k+x > eqtbSize+1 {
 28206  			goto badFmt
 28207  		}
 28208  		for ii := k; ii <= k+x-1; ii++ {
 28209  			j = ii
 28210  			_ = j
 28211  			prg.fmtFile.Get()
 28212  			prg.eqtb[j-1] = *(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))
 28213  		}
 28214  		k = k + x
 28215  		{
 28216  			prg.fmtFile.Get()
 28217  			x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28218  		}
 28219  		if x < 0 || k+x > eqtbSize+1 {
 28220  			goto badFmt
 28221  		}
 28222  		for ii := k; ii <= k+x-1; ii++ {
 28223  			j = ii
 28224  			_ = j
 28225  			prg.eqtb[j-1] = prg.eqtb[k-1-1]
 28226  		}
 28227  		k = k + x
 28228  		if k > eqtbSize {
 28229  			break
 28230  		}
 28231  	}
 28232  	{
 28233  		{
 28234  			prg.fmtFile.Get()
 28235  			x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28236  		}
 28237  		if x < hashBase || x > frozenControlSequence {
 28238  			goto badFmt
 28239  		} else {
 28240  			prg.parLoc = uint16(x)
 28241  		}
 28242  	}
 28243  	prg.parToken = uint16(07777 + int32(prg.parLoc))
 28244  
 28245  	{
 28246  		{
 28247  			prg.fmtFile.Get()
 28248  			x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28249  		}
 28250  		if x < hashBase || x > frozenControlSequence {
 28251  			goto badFmt
 28252  		} else {
 28253  			prg.writeLoc = uint16(x)
 28254  		}
 28255  	}
 28256  
 28257  	// Undump the hash table
 28258  	{
 28259  		{
 28260  			prg.fmtFile.Get()
 28261  			x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28262  		}
 28263  		if x < hashBase || x > frozenControlSequence {
 28264  			goto badFmt
 28265  		} else {
 28266  			prg.hashUsed = uint16(x)
 28267  		}
 28268  	}
 28269  	p = uint16(hashBase - 1)
 28270  	for {
 28271  		{
 28272  			{
 28273  				prg.fmtFile.Get()
 28274  				x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28275  			}
 28276  			if x < int32(p)+1 || x > int32(prg.hashUsed) {
 28277  				goto badFmt
 28278  			} else {
 28279  				p = uint16(x)
 28280  			}
 28281  		}
 28282  		{
 28283  			prg.fmtFile.Get()
 28284  			prg.hash[p-514] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).hh()
 28285  		}
 28286  		if int32(p) == int32(prg.hashUsed) {
 28287  			break
 28288  		}
 28289  	}
 28290  	for ii := int32(prg.hashUsed) + 1; ii <= undefinedControlSequence-1; ii++ {
 28291  		p = halfword(ii)
 28292  		_ = p
 28293  		prg.fmtFile.Get()
 28294  		prg.hash[p-514] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).hh()
 28295  	}
 28296  	{
 28297  		prg.fmtFile.Get()
 28298  		prg.csCount = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28299  	}
 28300  
 28301  	// Undump the font information
 28302  	{
 28303  		{
 28304  			prg.fmtFile.Get()
 28305  			x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28306  		}
 28307  		if x < 7 {
 28308  			goto badFmt
 28309  		}
 28310  		if x > fontMemSize {
 28311  			prg.termOut.Writeln("---! Must increase the ", "font mem size") /* \xref[Must increase the x]  */ /* \xref[Must increase the x]  */
 28312  			goto badFmt
 28313  		} else {
 28314  			prg.fmemPtr = uint16(x)
 28315  		}
 28316  	}
 28317  	for ii := int32(0); ii <= int32(prg.fmemPtr)-1; ii++ {
 28318  		k = ii
 28319  		_ = k
 28320  		prg.fmtFile.Get()
 28321  		prg.fontInfo[k] = *(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))
 28322  	}
 28323  	{
 28324  		{
 28325  			prg.fmtFile.Get()
 28326  			x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28327  		}
 28328  		if x < fontBase {
 28329  			goto badFmt
 28330  		}
 28331  		if x > fontMax {
 28332  			prg.termOut.Writeln("---! Must increase the ", "font max") /* \xref[Must increase the x]  */ /* \xref[Must increase the x]  */
 28333  			goto badFmt
 28334  		} else {
 28335  			prg.fontPtr = byte(x)
 28336  		}
 28337  	}
 28338  	for ii := int32(fontBase); ii <= int32(prg.fontPtr); ii++ {
 28339  		k = ii
 28340  		_ = k
 28341  
 28342  		// Undump the array info for internal font number |k|
 28343  		{
 28344  			prg.fmtFile.Get()
 28345  			prg.fontCheck[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).qqqq()
 28346  		}
 28347  
 28348  		{
 28349  			prg.fmtFile.Get()
 28350  			prg.fontSize[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28351  		}
 28352  		{
 28353  			prg.fmtFile.Get()
 28354  			prg.fontDsize[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28355  		}
 28356  		{
 28357  			{
 28358  				prg.fmtFile.Get()
 28359  				x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28360  			}
 28361  			if x < 0 || x > 65535 {
 28362  				goto badFmt
 28363  			} else {
 28364  				prg.fontParams[k] = uint16(x)
 28365  			}
 28366  		}
 28367  
 28368  		{
 28369  			prg.fmtFile.Get()
 28370  			prg.hyphenChar[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28371  		}
 28372  		{
 28373  			prg.fmtFile.Get()
 28374  			prg.skewChar[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28375  		}
 28376  
 28377  		{
 28378  			{
 28379  				prg.fmtFile.Get()
 28380  				x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28381  			}
 28382  			if x < 0 || x > int32(prg.strPtr) {
 28383  				goto badFmt
 28384  			} else {
 28385  				prg.fontName[k] = uint16(x)
 28386  			}
 28387  		}
 28388  		{
 28389  			{
 28390  				prg.fmtFile.Get()
 28391  				x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28392  			}
 28393  			if x < 0 || x > int32(prg.strPtr) {
 28394  				goto badFmt
 28395  			} else {
 28396  				prg.fontArea[k] = uint16(x)
 28397  			}
 28398  		}
 28399  
 28400  		{
 28401  			{
 28402  				prg.fmtFile.Get()
 28403  				x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28404  			}
 28405  			if x < 0 || x > 255 {
 28406  				goto badFmt
 28407  			} else {
 28408  				prg.fontBc[k] = byte(x)
 28409  			}
 28410  		}
 28411  		{
 28412  			{
 28413  				prg.fmtFile.Get()
 28414  				x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28415  			}
 28416  			if x < 0 || x > 255 {
 28417  				goto badFmt
 28418  			} else {
 28419  				prg.fontEc[k] = byte(x)
 28420  			}
 28421  		}
 28422  
 28423  		{
 28424  			prg.fmtFile.Get()
 28425  			prg.charBase[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28426  		}
 28427  		{
 28428  			prg.fmtFile.Get()
 28429  			prg.widthBase[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28430  		}
 28431  		{
 28432  			prg.fmtFile.Get()
 28433  			prg.heightBase[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28434  		}
 28435  
 28436  		{
 28437  			prg.fmtFile.Get()
 28438  			prg.depthBase[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28439  		}
 28440  		{
 28441  			prg.fmtFile.Get()
 28442  			prg.italicBase[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28443  		}
 28444  		{
 28445  			prg.fmtFile.Get()
 28446  			prg.ligKernBase[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28447  		}
 28448  
 28449  		{
 28450  			prg.fmtFile.Get()
 28451  			prg.kernBase[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28452  		}
 28453  		{
 28454  			prg.fmtFile.Get()
 28455  			prg.extenBase[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28456  		}
 28457  		{
 28458  			prg.fmtFile.Get()
 28459  			prg.paramBase[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28460  		}
 28461  
 28462  		{
 28463  			{
 28464  				prg.fmtFile.Get()
 28465  				x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28466  			}
 28467  			if x < 0 || x > int32(prg.loMemMax) {
 28468  				goto badFmt
 28469  			} else {
 28470  				prg.fontGlue[k] = uint16(x)
 28471  			}
 28472  		}
 28473  
 28474  		{
 28475  			{
 28476  				prg.fmtFile.Get()
 28477  				x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28478  			}
 28479  			if x < 0 || x > int32(prg.fmemPtr)-1 {
 28480  				goto badFmt
 28481  			} else {
 28482  				prg.bcharLabel[k] = uint16(x)
 28483  			}
 28484  		}
 28485  		{
 28486  			{
 28487  				prg.fmtFile.Get()
 28488  				x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28489  			}
 28490  			if x < minQuarterword || x > 256+minQuarterword {
 28491  				goto badFmt
 28492  			} else {
 28493  				prg.fontBchar[k] = uint16(x)
 28494  			}
 28495  		}
 28496  		{
 28497  			{
 28498  				prg.fmtFile.Get()
 28499  				x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28500  			}
 28501  			if x < minQuarterword || x > 256+minQuarterword {
 28502  				goto badFmt
 28503  			} else {
 28504  				prg.fontFalseBchar[k] = uint16(x)
 28505  			}
 28506  		}
 28507  	}
 28508  
 28509  	// Undump the hyphenation tables
 28510  	{
 28511  		{
 28512  			prg.fmtFile.Get()
 28513  			x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28514  		}
 28515  		if x < 0 || x > hyphSize {
 28516  			goto badFmt
 28517  		} else {
 28518  			prg.hyphCount = uint16(x)
 28519  		}
 28520  	}
 28521  	for ii := int32(1); ii <= int32(prg.hyphCount); ii++ {
 28522  		k = ii
 28523  		_ = k
 28524  		{
 28525  			{
 28526  				prg.fmtFile.Get()
 28527  				x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28528  			}
 28529  			if x < 0 || x > hyphSize {
 28530  				goto badFmt
 28531  			} else {
 28532  				j = x
 28533  			}
 28534  		}
 28535  		{
 28536  			{
 28537  				prg.fmtFile.Get()
 28538  				x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28539  			}
 28540  			if x < 0 || x > int32(prg.strPtr) {
 28541  				goto badFmt
 28542  			} else {
 28543  				prg.hyphWord[j] = uint16(x)
 28544  			}
 28545  		}
 28546  		{
 28547  			{
 28548  				prg.fmtFile.Get()
 28549  				x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28550  			}
 28551  			if x < 0 || x > 65535 {
 28552  				goto badFmt
 28553  			} else {
 28554  				prg.hyphList[j] = uint16(x)
 28555  			}
 28556  		}
 28557  	}
 28558  	{
 28559  		{
 28560  			prg.fmtFile.Get()
 28561  			x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28562  		}
 28563  		if x < 0 {
 28564  			goto badFmt
 28565  		}
 28566  		if x > trieSize {
 28567  			prg.termOut.Writeln("---! Must increase the ", "trie size") /* \xref[Must increase the x]  */ /* \xref[Must increase the x]  */
 28568  			goto badFmt
 28569  		} else {
 28570  			j = x
 28571  		}
 28572  	}
 28573  	prg.trieMax = uint16(j)
 28574  	for ii := int32(0); ii <= j; ii++ {
 28575  		k = ii
 28576  		_ = k
 28577  		prg.fmtFile.Get()
 28578  		prg.trie[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).hh()
 28579  	}
 28580  	{
 28581  		{
 28582  			prg.fmtFile.Get()
 28583  			x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28584  		}
 28585  		if x < 0 {
 28586  			goto badFmt
 28587  		}
 28588  		if x > trieOpSize {
 28589  			prg.termOut.Writeln("---! Must increase the ", "trie op size") /* \xref[Must increase the x]  */ /* \xref[Must increase the x]  */
 28590  			goto badFmt
 28591  		} else {
 28592  			j = x
 28593  		}
 28594  	}
 28595  	prg.trieOpPtr = uint16(j)
 28596  	for ii := int32(1); ii <= j; ii++ {
 28597  		k = ii
 28598  		_ = k
 28599  		{
 28600  			{
 28601  				prg.fmtFile.Get()
 28602  				x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28603  			}
 28604  			if x < 0 || x > 63 {
 28605  				goto badFmt
 28606  			} else {
 28607  				prg.hyfDistance[k-1] = byte(x)
 28608  			}
 28609  		} // a |small_number|
 28610  		{
 28611  			{
 28612  				prg.fmtFile.Get()
 28613  				x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28614  			}
 28615  			if x < 0 || x > 63 {
 28616  				goto badFmt
 28617  			} else {
 28618  				prg.hyfNum[k-1] = byte(x)
 28619  			}
 28620  		}
 28621  		{
 28622  			{
 28623  				prg.fmtFile.Get()
 28624  				x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28625  			}
 28626  			if x < minQuarterword || x > maxQuarterword {
 28627  				goto badFmt
 28628  			} else {
 28629  				prg.hyfNext[k-1] = byte(x)
 28630  			}
 28631  		}
 28632  	}
 28633  	for ii := int32(0); ii <= 255; ii++ {
 28634  		k = ii
 28635  		_ = k
 28636  		prg.trieUsed[k] = byte(minQuarterword)
 28637  	}
 28638  
 28639  	k = 256
 28640  	for j > 0 {
 28641  		{
 28642  			{
 28643  				prg.fmtFile.Get()
 28644  				x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28645  			}
 28646  			if x < 0 || x > k-1 {
 28647  				goto badFmt
 28648  			} else {
 28649  				k = x
 28650  			}
 28651  		}
 28652  		{
 28653  			{
 28654  				prg.fmtFile.Get()
 28655  				x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28656  			}
 28657  			if x < 1 || x > j {
 28658  				goto badFmt
 28659  			} else {
 28660  				x = x
 28661  			}
 28662  		}
 28663  		prg.trieUsed[k] = byte(x + minQuarterword)
 28664  
 28665  		j = j - x
 28666  		prg.opStart[k] = uint16(j - minQuarterword)
 28667  	}
 28668  	prg.trieNotReady = false
 28669  
 28670  	// Undump a couple more things and the closing check word
 28671  	{
 28672  		{
 28673  			prg.fmtFile.Get()
 28674  			x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28675  		}
 28676  		if x < batchMode || x > errorStopMode {
 28677  			goto badFmt
 28678  		} else {
 28679  			prg.interaction = byte(x)
 28680  		}
 28681  	}
 28682  	{
 28683  		{
 28684  			prg.fmtFile.Get()
 28685  			x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28686  		}
 28687  		if x < 0 || x > int32(prg.strPtr) {
 28688  			goto badFmt
 28689  		} else {
 28690  			prg.formatIdent = uint16(x)
 28691  		}
 28692  	}
 28693  	{
 28694  		prg.fmtFile.Get()
 28695  		x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
 28696  	}
 28697  	if x != 69069 || prg.fmtFile.EOF() {
 28698  		goto badFmt
 28699  	}
 28700  	r = true
 28701  	goto exit // it worked!
 28702  	// it worked!
 28703  badFmt:
 28704  	;
 28705  	prg.termOut.Writeln("(Fatal format file error; I'm stymied)")
 28706  	// \xref[Fatal format file error]
 28707  	r = false
 28708  
 28709  exit:
 28710  	;
 28711  	return r
 28712  } // \2
 28713  
 28714  func (prg *prg) closeFilesAndTerminate() {
 28715  	var (
 28716  		k int32 // all-purpose index
 28717  	)
 28718  	for ii := int32(0); ii <= 15; ii++ {
 28719  		k = ii
 28720  		_ = k
 28721  		if prg.writeOpen[k] {
 28722  			prg.aClose(prg.writeFile[k])
 28723  		}
 28724  	}
 28725  	*prg.eqtb[intBase+newLineCharCode-1].int() = -1
 28726  	//  if eqtb[int_base+ tracing_stats_code].int  >0 then
 28727  	// [ Output statistics about this job ]
 28728  	// if log_opened then
 28729  	//   begin writeln( log_file,' ')  ;
 28730  	//   writeln( log_file,'Here is how much of TeX''s memory',' you used:')  ;
 28731  	// [ \xref[Here is how much...] ]
 28732  	//   write(log_file,' ', str_ptr- init_str_ptr: 1,' string') ;
 28733  	//   if str_ptr<>init_str_ptr+1 then write(log_file,'s') ;
 28734  	//   writeln( log_file,' out of ',   max_strings-  init_str_ptr:  1)  ;
 28735  	//
 28736  	//   writeln( log_file,' ',  pool_ptr-  init_pool_ptr:  1,' string characters out of ',
 28737  	//       pool_size-  init_pool_ptr:  1)  ;
 28738  	//
 28739  	//   writeln( log_file,' ',  lo_mem_max-  mem_min+  mem_end-  hi_mem_min+  2:  1,
 28740  	//     ' words of memory out of ',  mem_end+  1-  mem_min:  1)  ;
 28741  	//
 28742  	//   writeln( log_file,' ',  cs_count:  1,' multiletter control sequences out of ',
 28743  	//       hash_size:  1)  ;
 28744  	//
 28745  	//   write(log_file,' ', fmem_ptr: 1,' words of font info for ',
 28746  	//      font_ptr- font_base: 1,' font') ;
 28747  	//   if font_ptr<>font_base+1 then write(log_file,'s') ;
 28748  	//   writeln( log_file,', out of ',  font_mem_size:  1,' for ',  font_max-  font_base:  1)  ;
 28749  	//
 28750  	//   write(log_file,' ', hyph_count: 1,' hyphenation exception') ;
 28751  	//   if hyph_count<>1 then write(log_file,'s') ;
 28752  	//   writeln( log_file,' out of ',  hyph_size:  1)  ;
 28753  	//
 28754  	//   writeln( log_file,' ',  max_in_stack:  1,'i,',  max_nest_stack:  1,'n,',
 28755  	//       max_param_stack:  1,'p,',
 28756  	//       max_buf_stack+  1:  1,'b,',
 28757  	//       max_save_stack+  6:  1,'s stack positions out of ',
 28758  	//       stack_size:  1,'i,',
 28759  	//       nest_size:  1,'n,',
 28760  	//       param_size:  1,'p,',
 28761  	//       buf_size:  1,'b,',
 28762  	//       save_size:  1,'s')  ;
 28763  	//   end
 28764  	//
 28765  	// ;  [  ]
 28766  
 28767  	// Finish the \.[DVI] file
 28768  	for prg.curS > -1 {
 28769  		if prg.curS > 0 {
 28770  			prg.dviBuf[prg.dviPtr] = byte(pop)
 28771  			prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 28772  			if int32(prg.dviPtr) == int32(prg.dviLimit) {
 28773  				prg.dviSwap()
 28774  			}
 28775  		} else {
 28776  			{
 28777  				prg.dviBuf[prg.dviPtr] = byte(eop)
 28778  				prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 28779  				if int32(prg.dviPtr) == int32(prg.dviLimit) {
 28780  					prg.dviSwap()
 28781  				}
 28782  			}
 28783  			prg.totalPages = prg.totalPages + 1
 28784  		}
 28785  		prg.curS = prg.curS - 1
 28786  	}
 28787  	if prg.totalPages == 0 {
 28788  		prg.printNl(strNumber( /* "No pages of output." */ 837))
 28789  	} else {
 28790  		{
 28791  			prg.dviBuf[prg.dviPtr] = byte(post)
 28792  			prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 28793  			if int32(prg.dviPtr) == int32(prg.dviLimit) {
 28794  				prg.dviSwap()
 28795  			}
 28796  		} // beginning of the postamble
 28797  		prg.dviFour(prg.lastBop)
 28798  		prg.lastBop = prg.dviOffset + int32(prg.dviPtr) - 5 // |post| location
 28799  		prg.dviFour(25400000)
 28800  		prg.dviFour(473628672) // conversion ratio for sp
 28801  		prg.prepareMag()
 28802  		prg.dviFour(*prg.eqtb[intBase+magCode-1].int()) // magnification factor
 28803  		prg.dviFour(prg.maxV)
 28804  		prg.dviFour(prg.maxH)
 28805  
 28806  		{
 28807  			prg.dviBuf[prg.dviPtr] = byte(prg.maxPush / 256)
 28808  			prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 28809  			if int32(prg.dviPtr) == int32(prg.dviLimit) {
 28810  				prg.dviSwap()
 28811  			}
 28812  		}
 28813  		{
 28814  			prg.dviBuf[prg.dviPtr] = byte(prg.maxPush % 256)
 28815  			prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 28816  			if int32(prg.dviPtr) == int32(prg.dviLimit) {
 28817  				prg.dviSwap()
 28818  			}
 28819  		}
 28820  
 28821  		{
 28822  			prg.dviBuf[prg.dviPtr] = byte(prg.totalPages / 256 % 256)
 28823  			prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 28824  			if int32(prg.dviPtr) == int32(prg.dviLimit) {
 28825  				prg.dviSwap()
 28826  			}
 28827  		}
 28828  		{
 28829  			prg.dviBuf[prg.dviPtr] = byte(prg.totalPages % 256)
 28830  			prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 28831  			if int32(prg.dviPtr) == int32(prg.dviLimit) {
 28832  				prg.dviSwap()
 28833  			}
 28834  		}
 28835  
 28836  		// Output the font definitions for all fonts that were used
 28837  		for int32(prg.fontPtr) > fontBase {
 28838  			if prg.fontUsed[prg.fontPtr] {
 28839  				prg.dviFontDef(prg.fontPtr)
 28840  			}
 28841  			prg.fontPtr = byte(int32(prg.fontPtr) - 1)
 28842  		}
 28843  		{
 28844  			prg.dviBuf[prg.dviPtr] = byte(postPost)
 28845  			prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 28846  			if int32(prg.dviPtr) == int32(prg.dviLimit) {
 28847  				prg.dviSwap()
 28848  			}
 28849  		}
 28850  		prg.dviFour(prg.lastBop)
 28851  		{
 28852  			prg.dviBuf[prg.dviPtr] = byte(idByte)
 28853  			prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 28854  			if int32(prg.dviPtr) == int32(prg.dviLimit) {
 28855  				prg.dviSwap()
 28856  			}
 28857  		}
 28858  
 28859  		k = 4 + (dviBufSize-int32(prg.dviPtr))%4 // the number of 223's
 28860  		for k > 0 {
 28861  			{
 28862  				prg.dviBuf[prg.dviPtr] = 223
 28863  				prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
 28864  				if int32(prg.dviPtr) == int32(prg.dviLimit) {
 28865  					prg.dviSwap()
 28866  				}
 28867  			}
 28868  			k = k - 1
 28869  		}
 28870  
 28871  		// Empty the last bytes out of |dvi_buf|
 28872  		if int32(prg.dviLimit) == int32(prg.halfBuf) {
 28873  			prg.writeDvi(prg.halfBuf, dviIndex(dviBufSize-1))
 28874  		}
 28875  		if int32(prg.dviPtr) > 0 {
 28876  			prg.writeDvi(dviIndex(0), dviIndex(int32(prg.dviPtr)-1))
 28877  		}
 28878  		prg.printNl(strNumber( /* "Output written on " */ 838))
 28879  		prg.slowPrint(int32(prg.outputFileName))
 28880  		// \xref[Output written on x]
 28881  		prg.print( /* " (" */ 286)
 28882  		prg.printInt(prg.totalPages)
 28883  		prg.print( /* " page" */ 839)
 28884  		if prg.totalPages != 1 {
 28885  			prg.printChar(asciiCode('s'))
 28886  		}
 28887  		prg.print( /* ", " */ 840)
 28888  		prg.printInt(prg.dviOffset + int32(prg.dviPtr))
 28889  		prg.print( /* " bytes)." */ 841)
 28890  		prg.bClose(prg.dviFile)
 28891  	}
 28892  	if prg.logOpened {
 28893  		prg.logFile.Writeln()
 28894  		prg.aClose(prg.logFile)
 28895  		prg.selector = byte(int32(prg.selector) - 2)
 28896  		if int32(prg.selector) == termOnly {
 28897  			prg.printNl(strNumber( /* "Transcript written on " */ 1275))
 28898  			// \xref[Transcript written...]
 28899  			prg.slowPrint(int32(prg.logName))
 28900  			prg.printChar(asciiCode('.'))
 28901  		}
 28902  	}
 28903  	prg.termOut.Writeln()
 28904  }
 28905  
 28906  func (prg *prg) finalCleanup() {
 28907  	var (
 28908  		c smallNumber // 0 for \.[\\end], 1 for \.[\\dump]
 28909  	)
 28910  	c = byte(prg.curChr)
 28911  	if int32(c) != 1 {
 28912  		*prg.eqtb[intBase+newLineCharCode-1].int() = -1
 28913  	}
 28914  	if int32(prg.jobName) == 0 {
 28915  		prg.openLogFile()
 28916  	}
 28917  	for int32(prg.inputPtr) > 0 {
 28918  		if int32(prg.curInput.stateField) == tokenList {
 28919  			prg.endTokenList()
 28920  		} else {
 28921  			prg.endFileReading()
 28922  		}
 28923  	}
 28924  	for int32(prg.openParens) > 0 {
 28925  		prg.print( /* " )" */ 1276)
 28926  		prg.openParens = byte(int32(prg.openParens) - 1)
 28927  	}
 28928  	if int32(prg.curLevel) > levelOne {
 28929  		prg.printNl(strNumber('('))
 28930  		prg.printEsc(strNumber( /* "end occurred " */ 1277))
 28931  		prg.print( /* "inside a group at level " */ 1278)
 28932  		// \xref[end_][\.[(\\end occurred...)]]
 28933  		prg.printInt(int32(prg.curLevel) - levelOne)
 28934  		prg.printChar(asciiCode(')'))
 28935  	}
 28936  	for int32(prg.condPtr) != 0 {
 28937  		prg.printNl(strNumber('('))
 28938  		prg.printEsc(strNumber( /* "end occurred " */ 1277))
 28939  		prg.print( /* "when " */ 1279)
 28940  		prg.printCmdChr(quarterword(ifTest), halfword(prg.curIf))
 28941  		if prg.ifLine != 0 {
 28942  			prg.print( /* " on line " */ 1280)
 28943  			prg.printInt(prg.ifLine)
 28944  		}
 28945  		prg.print( /* " was incomplete)" */ 1281)
 28946  		prg.ifLine = *prg.mem[int32(prg.condPtr)+1].int()
 28947  		prg.curIf = *(*prg.mem[prg.condPtr].hh()).b1()
 28948  		prg.tempPtr = prg.condPtr
 28949  		prg.condPtr = *(*prg.mem[prg.condPtr].hh()).rh()
 28950  		prg.freeNode(prg.tempPtr, halfword(ifNodeSize))
 28951  	}
 28952  	if int32(prg.history) != spotless {
 28953  		if int32(prg.history) == warningIssued || int32(prg.interaction) < errorStopMode {
 28954  			if int32(prg.selector) == termAndLog {
 28955  				prg.selector = byte(termOnly)
 28956  				prg.printNl(strNumber( /* "(see the transcript file for additional information)" */ 1282))
 28957  				// \xref[see the transcript file...]
 28958  				prg.selector = byte(termAndLog)
 28959  			}
 28960  		}
 28961  	}
 28962  	if int32(c) == 1 {
 28963  		for ii := int32(topMarkCode); ii <= splitBotMarkCode; ii++ {
 28964  			c = smallNumber(ii)
 28965  			_ = c
 28966  			if int32(prg.curMark[c]) != 0 {
 28967  				prg.deleteTokenRef(prg.curMark[c])
 28968  			}
 28969  		}
 28970  		if int32(prg.lastGlue) != 65535 {
 28971  			prg.deleteGlueRef(prg.lastGlue)
 28972  		}
 28973  		prg.storeFmtFile()
 28974  		goto exit
 28975  
 28976  		prg.printNl(strNumber( /* "(\\dump is performed only by INITEX)" */ 1283))
 28977  		goto exit
 28978  		// \xref[dump_][\.[\\dump...only by INITEX]]
 28979  	}
 28980  
 28981  exit:
 28982  }
 28983  
 28984  func (prg *prg) initPrim() {
 28985  	prg.noNewControlSequence = false
 28986  
 28987  	// Put each...
 28988  	prg.primitive(strNumber( /* "lineskip" */ 376), quarterword(assignGlue), halfword(glueBase+lineSkipCode))
 28989  
 28990  	// \xref[line_skip_][\.[\\lineskip] primitive]
 28991  	prg.primitive(strNumber( /* "baselineskip" */ 377), quarterword(assignGlue), halfword(glueBase+baselineSkipCode))
 28992  
 28993  	// \xref[baseline_skip_][\.[\\baselineskip] primitive]
 28994  	prg.primitive(strNumber( /* "parskip" */ 378), quarterword(assignGlue), halfword(glueBase+parSkipCode))
 28995  
 28996  	// \xref[par_skip_][\.[\\parskip] primitive]
 28997  	prg.primitive(strNumber( /* "abovedisplayskip" */ 379), quarterword(assignGlue), halfword(glueBase+aboveDisplaySkipCode))
 28998  
 28999  	// \xref[above_display_skip_][\.[\\abovedisplayskip] primitive]
 29000  	prg.primitive(strNumber( /* "belowdisplayskip" */ 380), quarterword(assignGlue), halfword(glueBase+belowDisplaySkipCode))
 29001  
 29002  	// \xref[below_display_skip_][\.[\\belowdisplayskip] primitive]
 29003  	prg.primitive(strNumber( /* "abovedisplayshortskip" */ 381), quarterword(assignGlue), halfword(glueBase+aboveDisplayShortSkipCode))
 29004  
 29005  	// \xref[above_display_short_skip_][\.[\\abovedisplayshortskip] primitive]
 29006  	prg.primitive(strNumber( /* "belowdisplayshortskip" */ 382), quarterword(assignGlue), halfword(glueBase+belowDisplayShortSkipCode))
 29007  
 29008  	// \xref[below_display_short_skip_][\.[\\belowdisplayshortskip] primitive]
 29009  	prg.primitive(strNumber( /* "leftskip" */ 383), quarterword(assignGlue), halfword(glueBase+leftSkipCode))
 29010  
 29011  	// \xref[left_skip_][\.[\\leftskip] primitive]
 29012  	prg.primitive(strNumber( /* "rightskip" */ 384), quarterword(assignGlue), halfword(glueBase+rightSkipCode))
 29013  
 29014  	// \xref[right_skip_][\.[\\rightskip] primitive]
 29015  	prg.primitive(strNumber( /* "topskip" */ 385), quarterword(assignGlue), halfword(glueBase+topSkipCode))
 29016  
 29017  	// \xref[top_skip_][\.[\\topskip] primitive]
 29018  	prg.primitive(strNumber( /* "splittopskip" */ 386), quarterword(assignGlue), halfword(glueBase+splitTopSkipCode))
 29019  
 29020  	// \xref[split_top_skip_][\.[\\splittopskip] primitive]
 29021  	prg.primitive(strNumber( /* "tabskip" */ 387), quarterword(assignGlue), halfword(glueBase+tabSkipCode))
 29022  
 29023  	// \xref[tab_skip_][\.[\\tabskip] primitive]
 29024  	prg.primitive(strNumber( /* "spaceskip" */ 388), quarterword(assignGlue), halfword(glueBase+spaceSkipCode))
 29025  
 29026  	// \xref[space_skip_][\.[\\spaceskip] primitive]
 29027  	prg.primitive(strNumber( /* "xspaceskip" */ 389), quarterword(assignGlue), halfword(glueBase+xspaceSkipCode))
 29028  
 29029  	// \xref[xspace_skip_][\.[\\xspaceskip] primitive]
 29030  	prg.primitive(strNumber( /* "parfillskip" */ 390), quarterword(assignGlue), halfword(glueBase+parFillSkipCode))
 29031  
 29032  	// \xref[par_fill_skip_][\.[\\parfillskip] primitive]
 29033  	prg.primitive(strNumber( /* "thinmuskip" */ 391), quarterword(assignMuGlue), halfword(glueBase+thinMuSkipCode))
 29034  
 29035  	// \xref[thin_mu_skip_][\.[\\thinmuskip] primitive]
 29036  	prg.primitive(strNumber( /* "medmuskip" */ 392), quarterword(assignMuGlue), halfword(glueBase+medMuSkipCode))
 29037  
 29038  	// \xref[med_mu_skip_][\.[\\medmuskip] primitive]
 29039  	prg.primitive(strNumber( /* "thickmuskip" */ 393), quarterword(assignMuGlue), halfword(glueBase+thickMuSkipCode))
 29040  
 29041  	// \xref[thick_mu_skip_][\.[\\thickmuskip] primitive]
 29042  
 29043  	prg.primitive(strNumber( /* "output" */ 398), quarterword(assignToks), halfword(outputRoutineLoc))
 29044  	// \xref[output_][\.[\\output] primitive]
 29045  	prg.primitive(strNumber( /* "everypar" */ 399), quarterword(assignToks), halfword(everyParLoc))
 29046  	// \xref[every_par_][\.[\\everypar] primitive]
 29047  	prg.primitive(strNumber( /* "everymath" */ 400), quarterword(assignToks), halfword(everyMathLoc))
 29048  	// \xref[every_math_][\.[\\everymath] primitive]
 29049  	prg.primitive(strNumber( /* "everydisplay" */ 401), quarterword(assignToks), halfword(everyDisplayLoc))
 29050  	// \xref[every_display_][\.[\\everydisplay] primitive]
 29051  	prg.primitive(strNumber( /* "everyhbox" */ 402), quarterword(assignToks), halfword(everyHboxLoc))
 29052  	// \xref[every_hbox_][\.[\\everyhbox] primitive]
 29053  	prg.primitive(strNumber( /* "everyvbox" */ 403), quarterword(assignToks), halfword(everyVboxLoc))
 29054  	// \xref[every_vbox_][\.[\\everyvbox] primitive]
 29055  	prg.primitive(strNumber( /* "everyjob" */ 404), quarterword(assignToks), halfword(everyJobLoc))
 29056  	// \xref[every_job_][\.[\\everyjob] primitive]
 29057  	prg.primitive(strNumber( /* "everycr" */ 405), quarterword(assignToks), halfword(everyCrLoc))
 29058  	// \xref[every_cr_][\.[\\everycr] primitive]
 29059  	prg.primitive(strNumber( /* "errhelp" */ 406), quarterword(assignToks), halfword(errHelpLoc))
 29060  	// \xref[err_help_][\.[\\errhelp] primitive]
 29061  
 29062  	prg.primitive(strNumber( /* "pretolerance" */ 420), quarterword(assignInt), halfword(intBase+pretoleranceCode))
 29063  
 29064  	// \xref[pretolerance_][\.[\\pretolerance] primitive]
 29065  	prg.primitive(strNumber( /* "tolerance" */ 421), quarterword(assignInt), halfword(intBase+toleranceCode))
 29066  
 29067  	// \xref[tolerance_][\.[\\tolerance] primitive]
 29068  	prg.primitive(strNumber( /* "linepenalty" */ 422), quarterword(assignInt), halfword(intBase+linePenaltyCode))
 29069  
 29070  	// \xref[line_penalty_][\.[\\linepenalty] primitive]
 29071  	prg.primitive(strNumber( /* "hyphenpenalty" */ 423), quarterword(assignInt), halfword(intBase+hyphenPenaltyCode))
 29072  
 29073  	// \xref[hyphen_penalty_][\.[\\hyphenpenalty] primitive]
 29074  	prg.primitive(strNumber( /* "exhyphenpenalty" */ 424), quarterword(assignInt), halfword(intBase+exHyphenPenaltyCode))
 29075  
 29076  	// \xref[ex_hyphen_penalty_][\.[\\exhyphenpenalty] primitive]
 29077  	prg.primitive(strNumber( /* "clubpenalty" */ 425), quarterword(assignInt), halfword(intBase+clubPenaltyCode))
 29078  
 29079  	// \xref[club_penalty_][\.[\\clubpenalty] primitive]
 29080  	prg.primitive(strNumber( /* "widowpenalty" */ 426), quarterword(assignInt), halfword(intBase+widowPenaltyCode))
 29081  
 29082  	// \xref[widow_penalty_][\.[\\widowpenalty] primitive]
 29083  	prg.primitive(strNumber( /* "displaywidowpenalty" */ 427), quarterword(assignInt), halfword(intBase+displayWidowPenaltyCode))
 29084  
 29085  	// \xref[display_widow_penalty_][\.[\\displaywidowpenalty] primitive]
 29086  	prg.primitive(strNumber( /* "brokenpenalty" */ 428), quarterword(assignInt), halfword(intBase+brokenPenaltyCode))
 29087  
 29088  	// \xref[broken_penalty_][\.[\\brokenpenalty] primitive]
 29089  	prg.primitive(strNumber( /* "binoppenalty" */ 429), quarterword(assignInt), halfword(intBase+binOpPenaltyCode))
 29090  
 29091  	// \xref[bin_op_penalty_][\.[\\binoppenalty] primitive]
 29092  	prg.primitive(strNumber( /* "relpenalty" */ 430), quarterword(assignInt), halfword(intBase+relPenaltyCode))
 29093  
 29094  	// \xref[rel_penalty_][\.[\\relpenalty] primitive]
 29095  	prg.primitive(strNumber( /* "predisplaypenalty" */ 431), quarterword(assignInt), halfword(intBase+preDisplayPenaltyCode))
 29096  
 29097  	// \xref[pre_display_penalty_][\.[\\predisplaypenalty] primitive]
 29098  	prg.primitive(strNumber( /* "postdisplaypenalty" */ 432), quarterword(assignInt), halfword(intBase+postDisplayPenaltyCode))
 29099  
 29100  	// \xref[post_display_penalty_][\.[\\postdisplaypenalty] primitive]
 29101  	prg.primitive(strNumber( /* "interlinepenalty" */ 433), quarterword(assignInt), halfword(intBase+interLinePenaltyCode))
 29102  
 29103  	// \xref[inter_line_penalty_][\.[\\interlinepenalty] primitive]
 29104  	prg.primitive(strNumber( /* "doublehyphendemerits" */ 434), quarterword(assignInt), halfword(intBase+doubleHyphenDemeritsCode))
 29105  
 29106  	// \xref[double_hyphen_demerits_][\.[\\doublehyphendemerits] primitive]
 29107  	prg.primitive(strNumber( /* "finalhyphendemerits" */ 435), quarterword(assignInt), halfword(intBase+finalHyphenDemeritsCode))
 29108  
 29109  	// \xref[final_hyphen_demerits_][\.[\\finalhyphendemerits] primitive]
 29110  	prg.primitive(strNumber( /* "adjdemerits" */ 436), quarterword(assignInt), halfword(intBase+adjDemeritsCode))
 29111  
 29112  	// \xref[adj_demerits_][\.[\\adjdemerits] primitive]
 29113  	prg.primitive(strNumber( /* "mag" */ 437), quarterword(assignInt), halfword(intBase+magCode))
 29114  
 29115  	// \xref[mag_][\.[\\mag] primitive]
 29116  	prg.primitive(strNumber( /* "delimiterfactor" */ 438), quarterword(assignInt), halfword(intBase+delimiterFactorCode))
 29117  
 29118  	// \xref[delimiter_factor_][\.[\\delimiterfactor] primitive]
 29119  	prg.primitive(strNumber( /* "looseness" */ 439), quarterword(assignInt), halfword(intBase+loosenessCode))
 29120  
 29121  	// \xref[looseness_][\.[\\looseness] primitive]
 29122  	prg.primitive(strNumber( /* "time" */ 440), quarterword(assignInt), halfword(intBase+timeCode))
 29123  
 29124  	// \xref[time_][\.[\\time] primitive]
 29125  	prg.primitive(strNumber( /* "day" */ 441), quarterword(assignInt), halfword(intBase+dayCode))
 29126  
 29127  	// \xref[day_][\.[\\day] primitive]
 29128  	prg.primitive(strNumber( /* "month" */ 442), quarterword(assignInt), halfword(intBase+monthCode))
 29129  
 29130  	// \xref[month_][\.[\\month] primitive]
 29131  	prg.primitive(strNumber( /* "year" */ 443), quarterword(assignInt), halfword(intBase+yearCode))
 29132  
 29133  	// \xref[year_][\.[\\year] primitive]
 29134  	prg.primitive(strNumber( /* "showboxbreadth" */ 444), quarterword(assignInt), halfword(intBase+showBoxBreadthCode))
 29135  
 29136  	// \xref[show_box_breadth_][\.[\\showboxbreadth] primitive]
 29137  	prg.primitive(strNumber( /* "showboxdepth" */ 445), quarterword(assignInt), halfword(intBase+showBoxDepthCode))
 29138  
 29139  	// \xref[show_box_depth_][\.[\\showboxdepth] primitive]
 29140  	prg.primitive(strNumber( /* "hbadness" */ 446), quarterword(assignInt), halfword(intBase+hbadnessCode))
 29141  
 29142  	// \xref[hbadness_][\.[\\hbadness] primitive]
 29143  	prg.primitive(strNumber( /* "vbadness" */ 447), quarterword(assignInt), halfword(intBase+vbadnessCode))
 29144  
 29145  	// \xref[vbadness_][\.[\\vbadness] primitive]
 29146  	prg.primitive(strNumber( /* "pausing" */ 448), quarterword(assignInt), halfword(intBase+pausingCode))
 29147  
 29148  	// \xref[pausing_][\.[\\pausing] primitive]
 29149  	prg.primitive(strNumber( /* "tracingonline" */ 449), quarterword(assignInt), halfword(intBase+tracingOnlineCode))
 29150  
 29151  	// \xref[tracing_online_][\.[\\tracingonline] primitive]
 29152  	prg.primitive(strNumber( /* "tracingmacros" */ 450), quarterword(assignInt), halfword(intBase+tracingMacrosCode))
 29153  
 29154  	// \xref[tracing_macros_][\.[\\tracingmacros] primitive]
 29155  	prg.primitive(strNumber( /* "tracingstats" */ 451), quarterword(assignInt), halfword(intBase+tracingStatsCode))
 29156  
 29157  	// \xref[tracing_stats_][\.[\\tracingstats] primitive]
 29158  	prg.primitive(strNumber( /* "tracingparagraphs" */ 452), quarterword(assignInt), halfword(intBase+tracingParagraphsCode))
 29159  
 29160  	// \xref[tracing_paragraphs_][\.[\\tracingparagraphs] primitive]
 29161  	prg.primitive(strNumber( /* "tracingpages" */ 453), quarterword(assignInt), halfword(intBase+tracingPagesCode))
 29162  
 29163  	// \xref[tracing_pages_][\.[\\tracingpages] primitive]
 29164  	prg.primitive(strNumber( /* "tracingoutput" */ 454), quarterword(assignInt), halfword(intBase+tracingOutputCode))
 29165  
 29166  	// \xref[tracing_output_][\.[\\tracingoutput] primitive]
 29167  	prg.primitive(strNumber( /* "tracinglostchars" */ 455), quarterword(assignInt), halfword(intBase+tracingLostCharsCode))
 29168  
 29169  	// \xref[tracing_lost_chars_][\.[\\tracinglostchars] primitive]
 29170  	prg.primitive(strNumber( /* "tracingcommands" */ 456), quarterword(assignInt), halfword(intBase+tracingCommandsCode))
 29171  
 29172  	// \xref[tracing_commands_][\.[\\tracingcommands] primitive]
 29173  	prg.primitive(strNumber( /* "tracingrestores" */ 457), quarterword(assignInt), halfword(intBase+tracingRestoresCode))
 29174  
 29175  	// \xref[tracing_restores_][\.[\\tracingrestores] primitive]
 29176  	prg.primitive(strNumber( /* "uchyph" */ 458), quarterword(assignInt), halfword(intBase+ucHyphCode))
 29177  
 29178  	// \xref[uc_hyph_][\.[\\uchyph] primitive]
 29179  	prg.primitive(strNumber( /* "outputpenalty" */ 459), quarterword(assignInt), halfword(intBase+outputPenaltyCode))
 29180  
 29181  	// \xref[output_penalty_][\.[\\outputpenalty] primitive]
 29182  	prg.primitive(strNumber( /* "maxdeadcycles" */ 460), quarterword(assignInt), halfword(intBase+maxDeadCyclesCode))
 29183  
 29184  	// \xref[max_dead_cycles_][\.[\\maxdeadcycles] primitive]
 29185  	prg.primitive(strNumber( /* "hangafter" */ 461), quarterword(assignInt), halfword(intBase+hangAfterCode))
 29186  
 29187  	// \xref[hang_after_][\.[\\hangafter] primitive]
 29188  	prg.primitive(strNumber( /* "floatingpenalty" */ 462), quarterword(assignInt), halfword(intBase+floatingPenaltyCode))
 29189  
 29190  	// \xref[floating_penalty_][\.[\\floatingpenalty] primitive]
 29191  	prg.primitive(strNumber( /* "globaldefs" */ 463), quarterword(assignInt), halfword(intBase+globalDefsCode))
 29192  
 29193  	// \xref[global_defs_][\.[\\globaldefs] primitive]
 29194  	prg.primitive(strNumber( /* "fam" */ 464), quarterword(assignInt), halfword(intBase+curFamCode))
 29195  
 29196  	// \xref[fam_][\.[\\fam] primitive]
 29197  	prg.primitive(strNumber( /* "escapechar" */ 465), quarterword(assignInt), halfword(intBase+escapeCharCode))
 29198  
 29199  	// \xref[escape_char_][\.[\\escapechar] primitive]
 29200  	prg.primitive(strNumber( /* "defaulthyphenchar" */ 466), quarterword(assignInt), halfword(intBase+defaultHyphenCharCode))
 29201  
 29202  	// \xref[default_hyphen_char_][\.[\\defaulthyphenchar] primitive]
 29203  	prg.primitive(strNumber( /* "defaultskewchar" */ 467), quarterword(assignInt), halfword(intBase+defaultSkewCharCode))
 29204  
 29205  	// \xref[default_skew_char_][\.[\\defaultskewchar] primitive]
 29206  	prg.primitive(strNumber( /* "endlinechar" */ 468), quarterword(assignInt), halfword(intBase+endLineCharCode))
 29207  
 29208  	// \xref[end_line_char_][\.[\\endlinechar] primitive]
 29209  	prg.primitive(strNumber( /* "newlinechar" */ 469), quarterword(assignInt), halfword(intBase+newLineCharCode))
 29210  
 29211  	// \xref[new_line_char_][\.[\\newlinechar] primitive]
 29212  	prg.primitive(strNumber( /* "language" */ 470), quarterword(assignInt), halfword(intBase+languageCode))
 29213  
 29214  	// \xref[language_][\.[\\language] primitive]
 29215  	prg.primitive(strNumber( /* "lefthyphenmin" */ 471), quarterword(assignInt), halfword(intBase+leftHyphenMinCode))
 29216  
 29217  	// \xref[left_hyphen_min_][\.[\\lefthyphenmin] primitive]
 29218  	prg.primitive(strNumber( /* "righthyphenmin" */ 472), quarterword(assignInt), halfword(intBase+rightHyphenMinCode))
 29219  
 29220  	// \xref[right_hyphen_min_][\.[\\righthyphenmin] primitive]
 29221  	prg.primitive(strNumber( /* "holdinginserts" */ 473), quarterword(assignInt), halfword(intBase+holdingInsertsCode))
 29222  
 29223  	// \xref[holding_inserts_][\.[\\holdinginserts] primitive]
 29224  	prg.primitive(strNumber( /* "errorcontextlines" */ 474), quarterword(assignInt), halfword(intBase+errorContextLinesCode))
 29225  
 29226  	// \xref[error_context_lines_][\.[\\errorcontextlines] primitive]
 29227  
 29228  	prg.primitive(strNumber( /* "parindent" */ 478), quarterword(assignDimen), halfword(dimenBase+parIndentCode))
 29229  
 29230  	// \xref[par_indent_][\.[\\parindent] primitive]
 29231  	prg.primitive(strNumber( /* "mathsurround" */ 479), quarterword(assignDimen), halfword(dimenBase+mathSurroundCode))
 29232  
 29233  	// \xref[math_surround_][\.[\\mathsurround] primitive]
 29234  	prg.primitive(strNumber( /* "lineskiplimit" */ 480), quarterword(assignDimen), halfword(dimenBase+lineSkipLimitCode))
 29235  
 29236  	// \xref[line_skip_limit_][\.[\\lineskiplimit] primitive]
 29237  	prg.primitive(strNumber( /* "hsize" */ 481), quarterword(assignDimen), halfword(dimenBase+hsizeCode))
 29238  
 29239  	// \xref[hsize_][\.[\\hsize] primitive]
 29240  	prg.primitive(strNumber( /* "vsize" */ 482), quarterword(assignDimen), halfword(dimenBase+vsizeCode))
 29241  
 29242  	// \xref[vsize_][\.[\\vsize] primitive]
 29243  	prg.primitive(strNumber( /* "maxdepth" */ 483), quarterword(assignDimen), halfword(dimenBase+maxDepthCode))
 29244  
 29245  	// \xref[max_depth_][\.[\\maxdepth] primitive]
 29246  	prg.primitive(strNumber( /* "splitmaxdepth" */ 484), quarterword(assignDimen), halfword(dimenBase+splitMaxDepthCode))
 29247  
 29248  	// \xref[split_max_depth_][\.[\\splitmaxdepth] primitive]
 29249  	prg.primitive(strNumber( /* "boxmaxdepth" */ 485), quarterword(assignDimen), halfword(dimenBase+boxMaxDepthCode))
 29250  
 29251  	// \xref[box_max_depth_][\.[\\boxmaxdepth] primitive]
 29252  	prg.primitive(strNumber( /* "hfuzz" */ 486), quarterword(assignDimen), halfword(dimenBase+hfuzzCode))
 29253  
 29254  	// \xref[hfuzz_][\.[\\hfuzz] primitive]
 29255  	prg.primitive(strNumber( /* "vfuzz" */ 487), quarterword(assignDimen), halfword(dimenBase+vfuzzCode))
 29256  
 29257  	// \xref[vfuzz_][\.[\\vfuzz] primitive]
 29258  	prg.primitive(strNumber( /* "delimitershortfall" */ 488), quarterword(assignDimen), halfword(dimenBase+delimiterShortfallCode))
 29259  
 29260  	// \xref[delimiter_shortfall_][\.[\\delimitershortfall] primitive]
 29261  	prg.primitive(strNumber( /* "nulldelimiterspace" */ 489), quarterword(assignDimen), halfword(dimenBase+nullDelimiterSpaceCode))
 29262  
 29263  	// \xref[null_delimiter_space_][\.[\\nulldelimiterspace] primitive]
 29264  	prg.primitive(strNumber( /* "scriptspace" */ 490), quarterword(assignDimen), halfword(dimenBase+scriptSpaceCode))
 29265  
 29266  	// \xref[script_space_][\.[\\scriptspace] primitive]
 29267  	prg.primitive(strNumber( /* "predisplaysize" */ 491), quarterword(assignDimen), halfword(dimenBase+preDisplaySizeCode))
 29268  
 29269  	// \xref[pre_display_size_][\.[\\predisplaysize] primitive]
 29270  	prg.primitive(strNumber( /* "displaywidth" */ 492), quarterword(assignDimen), halfword(dimenBase+displayWidthCode))
 29271  
 29272  	// \xref[display_width_][\.[\\displaywidth] primitive]
 29273  	prg.primitive(strNumber( /* "displayindent" */ 493), quarterword(assignDimen), halfword(dimenBase+displayIndentCode))
 29274  
 29275  	// \xref[display_indent_][\.[\\displayindent] primitive]
 29276  	prg.primitive(strNumber( /* "overfullrule" */ 494), quarterword(assignDimen), halfword(dimenBase+overfullRuleCode))
 29277  
 29278  	// \xref[overfull_rule_][\.[\\overfullrule] primitive]
 29279  	prg.primitive(strNumber( /* "hangindent" */ 495), quarterword(assignDimen), halfword(dimenBase+hangIndentCode))
 29280  
 29281  	// \xref[hang_indent_][\.[\\hangindent] primitive]
 29282  	prg.primitive(strNumber( /* "hoffset" */ 496), quarterword(assignDimen), halfword(dimenBase+hOffsetCode))
 29283  
 29284  	// \xref[h_offset_][\.[\\hoffset] primitive]
 29285  	prg.primitive(strNumber( /* "voffset" */ 497), quarterword(assignDimen), halfword(dimenBase+vOffsetCode))
 29286  
 29287  	// \xref[v_offset_][\.[\\voffset] primitive]
 29288  	prg.primitive(strNumber( /* "emergencystretch" */ 498), quarterword(assignDimen), halfword(dimenBase+emergencyStretchCode))
 29289  
 29290  	// \xref[emergency_stretch_][\.[\\emergencystretch] primitive]
 29291  
 29292  	prg.primitive(strNumber(' '), quarterword(exSpace), halfword(0))
 29293  
 29294  	// \xref[Single-character primitives /][\quad\.[\\\ ]]
 29295  	prg.primitive(strNumber('/'), quarterword(italCorr), halfword(0))
 29296  
 29297  	// \xref[Single-character primitives /][\quad\.[\\/]]
 29298  	prg.primitive(strNumber( /* "accent" */ 508), quarterword(accent), halfword(0))
 29299  
 29300  	// \xref[accent_][\.[\\accent] primitive]
 29301  	prg.primitive(strNumber( /* "advance" */ 509), quarterword(advance), halfword(0))
 29302  
 29303  	// \xref[advance_][\.[\\advance] primitive]
 29304  	prg.primitive(strNumber( /* "afterassignment" */ 510), quarterword(afterAssignment), halfword(0))
 29305  
 29306  	// \xref[after_assignment_][\.[\\afterassignment] primitive]
 29307  	prg.primitive(strNumber( /* "aftergroup" */ 511), quarterword(afterGroup), halfword(0))
 29308  
 29309  	// \xref[after_group_][\.[\\aftergroup] primitive]
 29310  	prg.primitive(strNumber( /* "begingroup" */ 512), quarterword(beginGroup), halfword(0))
 29311  
 29312  	// \xref[begin_group_][\.[\\begingroup] primitive]
 29313  	prg.primitive(strNumber( /* "char" */ 513), quarterword(charNum), halfword(0))
 29314  
 29315  	// \xref[char_][\.[\\char] primitive]
 29316  	prg.primitive(strNumber( /* "csname" */ 504), quarterword(csName), halfword(0))
 29317  
 29318  	// \xref[cs_name_][\.[\\csname] primitive]
 29319  	prg.primitive(strNumber( /* "delimiter" */ 514), quarterword(delimNum), halfword(0))
 29320  
 29321  	// \xref[delimiter_][\.[\\delimiter] primitive]
 29322  	prg.primitive(strNumber( /* "divide" */ 515), quarterword(divide), halfword(0))
 29323  
 29324  	// \xref[divide_][\.[\\divide] primitive]
 29325  	prg.primitive(strNumber( /* "endcsname" */ 505), quarterword(endCsName), halfword(0))
 29326  
 29327  	// \xref[end_cs_name_][\.[\\endcsname] primitive]
 29328  	prg.primitive(strNumber( /* "endgroup" */ 516), quarterword(endGroup), halfword(0))
 29329  	// \xref[end_group_][\.[\\endgroup] primitive]
 29330  	*prg.hash[frozenEndGroup-514].rh() = 516
 29331  	prg.eqtb[frozenEndGroup-1] = prg.eqtb[prg.curVal-1]
 29332  
 29333  	prg.primitive(strNumber( /* "expandafter" */ 517), quarterword(expandAfter), halfword(0))
 29334  
 29335  	// \xref[expand_after_][\.[\\expandafter] primitive]
 29336  	prg.primitive(strNumber( /* "font" */ 518), quarterword(defFont), halfword(0))
 29337  
 29338  	// \xref[font_][\.[\\font] primitive]
 29339  	prg.primitive(strNumber( /* "fontdimen" */ 519), quarterword(assignFontDimen), halfword(0))
 29340  
 29341  	// \xref[font_dimen_][\.[\\fontdimen] primitive]
 29342  	prg.primitive(strNumber( /* "halign" */ 520), quarterword(halign), halfword(0))
 29343  
 29344  	// \xref[halign_][\.[\\halign] primitive]
 29345  	prg.primitive(strNumber( /* "hrule" */ 521), quarterword(hrule), halfword(0))
 29346  
 29347  	// \xref[hrule_][\.[\\hrule] primitive]
 29348  	prg.primitive(strNumber( /* "ignorespaces" */ 522), quarterword(ignoreSpaces), halfword(0))
 29349  
 29350  	// \xref[ignore_spaces_][\.[\\ignorespaces] primitive]
 29351  	prg.primitive(strNumber( /* "insert" */ 330), quarterword(insert), halfword(0))
 29352  
 29353  	// \xref[insert_][\.[\\insert] primitive]
 29354  	prg.primitive(strNumber( /* "mark" */ 351), quarterword(mark), halfword(0))
 29355  
 29356  	// \xref[mark_][\.[\\mark] primitive]
 29357  	prg.primitive(strNumber( /* "mathaccent" */ 523), quarterword(mathAccent), halfword(0))
 29358  
 29359  	// \xref[math_accent_][\.[\\mathaccent] primitive]
 29360  	prg.primitive(strNumber( /* "mathchar" */ 524), quarterword(mathCharNum), halfword(0))
 29361  
 29362  	// \xref[math_char_][\.[\\mathchar] primitive]
 29363  	prg.primitive(strNumber( /* "mathchoice" */ 525), quarterword(mathChoice), halfword(0))
 29364  
 29365  	// \xref[math_choice_][\.[\\mathchoice] primitive]
 29366  	prg.primitive(strNumber( /* "multiply" */ 526), quarterword(multiply), halfword(0))
 29367  
 29368  	// \xref[multiply_][\.[\\multiply] primitive]
 29369  	prg.primitive(strNumber( /* "noalign" */ 527), quarterword(noAlign), halfword(0))
 29370  
 29371  	// \xref[no_align_][\.[\\noalign] primitive]
 29372  	prg.primitive(strNumber( /* "noboundary" */ 528), quarterword(noBoundary), halfword(0))
 29373  
 29374  	// \xref[no_boundary_][\.[\\noboundary] primitive]
 29375  	prg.primitive(strNumber( /* "noexpand" */ 529), quarterword(noExpand), halfword(0))
 29376  
 29377  	// \xref[no_expand_][\.[\\noexpand] primitive]
 29378  	prg.primitive(strNumber( /* "nonscript" */ 335), quarterword(nonScript), halfword(0))
 29379  
 29380  	// \xref[non_script_][\.[\\nonscript] primitive]
 29381  	prg.primitive(strNumber( /* "omit" */ 530), quarterword(omit), halfword(0))
 29382  
 29383  	// \xref[omit_][\.[\\omit] primitive]
 29384  	prg.primitive(strNumber( /* "parshape" */ 408), quarterword(setShape), halfword(0))
 29385  
 29386  	// \xref[par_shape_][\.[\\parshape] primitive]
 29387  	prg.primitive(strNumber( /* "penalty" */ 531), quarterword(breakPenalty), halfword(0))
 29388  
 29389  	// \xref[penalty_][\.[\\penalty] primitive]
 29390  	prg.primitive(strNumber( /* "prevgraf" */ 532), quarterword(setPrevGraf), halfword(0))
 29391  
 29392  	// \xref[prev_graf_][\.[\\prevgraf] primitive]
 29393  	prg.primitive(strNumber( /* "radical" */ 533), quarterword(radical), halfword(0))
 29394  
 29395  	// \xref[radical_][\.[\\radical] primitive]
 29396  	prg.primitive(strNumber( /* "read" */ 534), quarterword(readToCs), halfword(0))
 29397  
 29398  	// \xref[read_][\.[\\read] primitive]
 29399  	prg.primitive(strNumber( /* "relax" */ 535), quarterword(relax), halfword(256)) // cf.\ |scan_file_name|
 29400  	// \xref[relax_][\.[\\relax] primitive]
 29401  	*prg.hash[frozenRelax-514].rh() = 535
 29402  	prg.eqtb[frozenRelax-1] = prg.eqtb[prg.curVal-1]
 29403  
 29404  	prg.primitive(strNumber( /* "setbox" */ 536), quarterword(setBox), halfword(0))
 29405  
 29406  	// \xref[set_box_][\.[\\setbox] primitive]
 29407  	prg.primitive(strNumber( /* "the" */ 537), quarterword(the), halfword(0))
 29408  
 29409  	// \xref[the_][\.[\\the] primitive]
 29410  	prg.primitive(strNumber( /* "toks" */ 407), quarterword(toksRegister), halfword(0))
 29411  
 29412  	// \xref[toks_][\.[\\toks] primitive]
 29413  	prg.primitive(strNumber( /* "vadjust" */ 352), quarterword(vadjust), halfword(0))
 29414  
 29415  	// \xref[vadjust_][\.[\\vadjust] primitive]
 29416  	prg.primitive(strNumber( /* "valign" */ 538), quarterword(valign), halfword(0))
 29417  
 29418  	// \xref[valign_][\.[\\valign] primitive]
 29419  	prg.primitive(strNumber( /* "vcenter" */ 539), quarterword(vcenter), halfword(0))
 29420  
 29421  	// \xref[vcenter_][\.[\\vcenter] primitive]
 29422  	prg.primitive(strNumber( /* "vrule" */ 540), quarterword(vrule), halfword(0))
 29423  
 29424  	// \xref[vrule_][\.[\\vrule] primitive]
 29425  
 29426  	prg.primitive(strNumber( /* "par" */ 597), quarterword(parEnd), halfword(256)) // cf.\ |scan_file_name|
 29427  	// \xref[par_][\.[\\par] primitive]
 29428  	prg.parLoc = uint16(prg.curVal)
 29429  	prg.parToken = uint16(07777 + int32(prg.parLoc))
 29430  
 29431  	prg.primitive(strNumber( /* "input" */ 629), quarterword(input), halfword(0))
 29432  
 29433  	// \xref[input_][\.[\\input] primitive]
 29434  	prg.primitive(strNumber( /* "endinput" */ 630), quarterword(input), halfword(1))
 29435  
 29436  	// \xref[end_input_][\.[\\endinput] primitive]
 29437  
 29438  	prg.primitive(strNumber( /* "topmark" */ 631), quarterword(topBotMark), halfword(topMarkCode))
 29439  	// \xref[top_mark_][\.[\\topmark] primitive]
 29440  	prg.primitive(strNumber( /* "firstmark" */ 632), quarterword(topBotMark), halfword(firstMarkCode))
 29441  	// \xref[first_mark_][\.[\\firstmark] primitive]
 29442  	prg.primitive(strNumber( /* "botmark" */ 633), quarterword(topBotMark), halfword(botMarkCode))
 29443  	// \xref[bot_mark_][\.[\\botmark] primitive]
 29444  	prg.primitive(strNumber( /* "splitfirstmark" */ 634), quarterword(topBotMark), halfword(splitFirstMarkCode))
 29445  	// \xref[split_first_mark_][\.[\\splitfirstmark] primitive]
 29446  	prg.primitive(strNumber( /* "splitbotmark" */ 635), quarterword(topBotMark), halfword(splitBotMarkCode))
 29447  	// \xref[split_bot_mark_][\.[\\splitbotmark] primitive]
 29448  
 29449  	prg.primitive(strNumber( /* "count" */ 476), quarterword(register), halfword(intVal))
 29450  	// \xref[count_][\.[\\count] primitive]
 29451  	prg.primitive(strNumber( /* "dimen" */ 500), quarterword(register), halfword(dimenVal))
 29452  	// \xref[dimen_][\.[\\dimen] primitive]
 29453  	prg.primitive(strNumber( /* "skip" */ 395), quarterword(register), halfword(glueVal))
 29454  	// \xref[skip_][\.[\\skip] primitive]
 29455  	prg.primitive(strNumber( /* "muskip" */ 396), quarterword(register), halfword(muVal))
 29456  	// \xref[mu_skip_][\.[\\muskip] primitive]
 29457  
 29458  	prg.primitive(strNumber( /* "spacefactor" */ 668), quarterword(setAux), halfword(hmode))
 29459  	// \xref[space_factor_][\.[\\spacefactor] primitive]
 29460  	prg.primitive(strNumber( /* "prevdepth" */ 669), quarterword(setAux), halfword(vmode))
 29461  
 29462  	// \xref[prev_depth_][\.[\\prevdepth] primitive]
 29463  	prg.primitive(strNumber( /* "deadcycles" */ 670), quarterword(setPageInt), halfword(0))
 29464  	// \xref[dead_cycles_][\.[\\deadcycles] primitive]
 29465  	prg.primitive(strNumber( /* "insertpenalties" */ 671), quarterword(setPageInt), halfword(1))
 29466  	// \xref[insert_penalties_][\.[\\insertpenalties] primitive]
 29467  	prg.primitive(strNumber( /* "wd" */ 672), quarterword(setBoxDimen), halfword(widthOffset))
 29468  	// \xref[wd_][\.[\\wd] primitive]
 29469  	prg.primitive(strNumber( /* "ht" */ 673), quarterword(setBoxDimen), halfword(heightOffset))
 29470  	// \xref[ht_][\.[\\ht] primitive]
 29471  	prg.primitive(strNumber( /* "dp" */ 674), quarterword(setBoxDimen), halfword(depthOffset))
 29472  	// \xref[dp_][\.[\\dp] primitive]
 29473  	prg.primitive(strNumber( /* "lastpenalty" */ 675), quarterword(lastItem), halfword(intVal))
 29474  	// \xref[last_penalty_][\.[\\lastpenalty] primitive]
 29475  	prg.primitive(strNumber( /* "lastkern" */ 676), quarterword(lastItem), halfword(dimenVal))
 29476  	// \xref[last_kern_][\.[\\lastkern] primitive]
 29477  	prg.primitive(strNumber( /* "lastskip" */ 677), quarterword(lastItem), halfword(glueVal))
 29478  	// \xref[last_skip_][\.[\\lastskip] primitive]
 29479  	prg.primitive(strNumber( /* "inputlineno" */ 678), quarterword(lastItem), halfword(inputLineNoCode))
 29480  	// \xref[input_line_no_][\.[\\inputlineno] primitive]
 29481  	prg.primitive(strNumber( /* "badness" */ 679), quarterword(lastItem), halfword(badnessCode))
 29482  	// \xref[badness_][\.[\\badness] primitive]
 29483  
 29484  	prg.primitive(strNumber( /* "number" */ 735), quarterword(convert), halfword(numberCode))
 29485  
 29486  	// \xref[number_][\.[\\number] primitive]
 29487  	prg.primitive(strNumber( /* "romannumeral" */ 736), quarterword(convert), halfword(romanNumeralCode))
 29488  
 29489  	// \xref[roman_numeral_][\.[\\romannumeral] primitive]
 29490  	prg.primitive(strNumber( /* "string" */ 737), quarterword(convert), halfword(stringCode))
 29491  
 29492  	// \xref[string_][\.[\\string] primitive]
 29493  	prg.primitive(strNumber( /* "meaning" */ 738), quarterword(convert), halfword(meaningCode))
 29494  
 29495  	// \xref[meaning_][\.[\\meaning] primitive]
 29496  	prg.primitive(strNumber( /* "fontname" */ 739), quarterword(convert), halfword(fontNameCode))
 29497  
 29498  	// \xref[font_name_][\.[\\fontname] primitive]
 29499  	prg.primitive(strNumber( /* "jobname" */ 740), quarterword(convert), halfword(jobNameCode))
 29500  
 29501  	// \xref[job_name_][\.[\\jobname] primitive]
 29502  
 29503  	prg.primitive(strNumber( /* "if" */ 757), quarterword(ifTest), halfword(ifCharCode))
 29504  	// \xref[if_char_][\.[\\if] primitive]
 29505  	prg.primitive(strNumber( /* "ifcat" */ 758), quarterword(ifTest), halfword(ifCatCode))
 29506  	// \xref[if_cat_code_][\.[\\ifcat] primitive]
 29507  	prg.primitive(strNumber( /* "ifnum" */ 759), quarterword(ifTest), halfword(ifIntCode))
 29508  	// \xref[if_int_][\.[\\ifnum] primitive]
 29509  	prg.primitive(strNumber( /* "ifdim" */ 760), quarterword(ifTest), halfword(ifDimCode))
 29510  	// \xref[if_dim_][\.[\\ifdim] primitive]
 29511  	prg.primitive(strNumber( /* "ifodd" */ 761), quarterword(ifTest), halfword(ifOddCode))
 29512  	// \xref[if_odd_][\.[\\ifodd] primitive]
 29513  	prg.primitive(strNumber( /* "ifvmode" */ 762), quarterword(ifTest), halfword(ifVmodeCode))
 29514  	// \xref[if_vmode_][\.[\\ifvmode] primitive]
 29515  	prg.primitive(strNumber( /* "ifhmode" */ 763), quarterword(ifTest), halfword(ifHmodeCode))
 29516  	// \xref[if_hmode_][\.[\\ifhmode] primitive]
 29517  	prg.primitive(strNumber( /* "ifmmode" */ 764), quarterword(ifTest), halfword(ifMmodeCode))
 29518  	// \xref[if_mmode_][\.[\\ifmmode] primitive]
 29519  	prg.primitive(strNumber( /* "ifinner" */ 765), quarterword(ifTest), halfword(ifInnerCode))
 29520  	// \xref[if_inner_][\.[\\ifinner] primitive]
 29521  	prg.primitive(strNumber( /* "ifvoid" */ 766), quarterword(ifTest), halfword(ifVoidCode))
 29522  	// \xref[if_void_][\.[\\ifvoid] primitive]
 29523  	prg.primitive(strNumber( /* "ifhbox" */ 767), quarterword(ifTest), halfword(ifHboxCode))
 29524  	// \xref[if_hbox_][\.[\\ifhbox] primitive]
 29525  	prg.primitive(strNumber( /* "ifvbox" */ 768), quarterword(ifTest), halfword(ifVboxCode))
 29526  	// \xref[if_vbox_][\.[\\ifvbox] primitive]
 29527  	prg.primitive(strNumber( /* "ifx" */ 769), quarterword(ifTest), halfword(ifxCode))
 29528  	// \xref[ifx_][\.[\\ifx] primitive]
 29529  	prg.primitive(strNumber( /* "ifeof" */ 770), quarterword(ifTest), halfword(ifEofCode))
 29530  	// \xref[if_eof_][\.[\\ifeof] primitive]
 29531  	prg.primitive(strNumber( /* "iftrue" */ 771), quarterword(ifTest), halfword(ifTrueCode))
 29532  	// \xref[if_true_][\.[\\iftrue] primitive]
 29533  	prg.primitive(strNumber( /* "iffalse" */ 772), quarterword(ifTest), halfword(ifFalseCode))
 29534  	// \xref[if_false_][\.[\\iffalse] primitive]
 29535  	prg.primitive(strNumber( /* "ifcase" */ 773), quarterword(ifTest), halfword(ifCaseCode))
 29536  	// \xref[if_case_][\.[\\ifcase] primitive]
 29537  
 29538  	prg.primitive(strNumber( /* "fi" */ 774), quarterword(fiOrElse), halfword(fiCode))
 29539  	// \xref[fi_][\.[\\fi] primitive]
 29540  	*prg.hash[frozenFi-514].rh() = 774
 29541  	prg.eqtb[frozenFi-1] = prg.eqtb[prg.curVal-1]
 29542  	prg.primitive(strNumber( /* "or" */ 775), quarterword(fiOrElse), halfword(orCode))
 29543  	// \xref[or_][\.[\\or] primitive]
 29544  	prg.primitive(strNumber( /* "else" */ 776), quarterword(fiOrElse), halfword(elseCode))
 29545  	// \xref[else_][\.[\\else] primitive]
 29546  
 29547  	prg.primitive(strNumber( /* "nullfont" */ 801), quarterword(setFont), halfword(fontBase))
 29548  	// \xref[null_font_][\.[\\nullfont] primitive]
 29549  	*prg.hash[frozenNullFont-514].rh() = 801
 29550  	prg.eqtb[frozenNullFont-1] = prg.eqtb[prg.curVal-1]
 29551  
 29552  	prg.primitive(strNumber( /* "span" */ 898), quarterword(tabMark), halfword(spanCode))
 29553  
 29554  	// \xref[span_][\.[\\span] primitive]
 29555  	prg.primitive(strNumber( /* "cr" */ 899), quarterword(carRet), halfword(crCode))
 29556  	// \xref[cr_][\.[\\cr] primitive]
 29557  	*prg.hash[frozenCr-514].rh() = 899
 29558  	prg.eqtb[frozenCr-1] = prg.eqtb[prg.curVal-1]
 29559  
 29560  	prg.primitive(strNumber( /* "crcr" */ 900), quarterword(carRet), halfword(crCrCode))
 29561  	// \xref[cr_cr_][\.[\\crcr] primitive]
 29562  	*prg.hash[frozenEndTemplate-514].rh() = 901
 29563  	*prg.hash[frozenEndv-514].rh() = 901
 29564  	// \xref[endtemplate]
 29565  	*(*prg.eqtb[frozenEndv-1].hh()).b0() = byte(endv)
 29566  	*(*prg.eqtb[frozenEndv-1].hh()).rh() = uint16(30000 - 11)
 29567  	*(*prg.eqtb[frozenEndv-1].hh()).b1() = byte(levelOne)
 29568  
 29569  	prg.eqtb[frozenEndTemplate-1] = prg.eqtb[frozenEndv-1]
 29570  	*(*prg.eqtb[frozenEndTemplate-1].hh()).b0() = byte(endTemplate)
 29571  
 29572  	prg.primitive(strNumber( /* "pagegoal" */ 970), quarterword(setPageDimen), halfword(0))
 29573  	// \xref[page_goal_][\.[\\pagegoal] primitive]
 29574  	prg.primitive(strNumber( /* "pagetotal" */ 971), quarterword(setPageDimen), halfword(1))
 29575  	// \xref[page_total_][\.[\\pagetotal] primitive]
 29576  	prg.primitive(strNumber( /* "pagestretch" */ 972), quarterword(setPageDimen), halfword(2))
 29577  	// \xref[page_stretch_][\.[\\pagestretch] primitive]
 29578  	prg.primitive(strNumber( /* "pagefilstretch" */ 973), quarterword(setPageDimen), halfword(3))
 29579  	// \xref[page_fil_stretch_][\.[\\pagefilstretch] primitive]
 29580  	prg.primitive(strNumber( /* "pagefillstretch" */ 974), quarterword(setPageDimen), halfword(4))
 29581  	// \xref[page_fill_stretch_][\.[\\pagefillstretch] primitive]
 29582  	prg.primitive(strNumber( /* "pagefilllstretch" */ 975), quarterword(setPageDimen), halfword(5))
 29583  	// \xref[page_filll_stretch_][\.[\\pagefilllstretch] primitive]
 29584  	prg.primitive(strNumber( /* "pageshrink" */ 976), quarterword(setPageDimen), halfword(6))
 29585  	// \xref[page_shrink_][\.[\\pageshrink] primitive]
 29586  	prg.primitive(strNumber( /* "pagedepth" */ 977), quarterword(setPageDimen), halfword(7))
 29587  	// \xref[page_depth_][\.[\\pagedepth] primitive]
 29588  
 29589  	prg.primitive(strNumber( /* "end" */ 1025), quarterword(stop), halfword(0))
 29590  
 29591  	// \xref[end_][\.[\\end] primitive]
 29592  	prg.primitive(strNumber( /* "dump" */ 1026), quarterword(stop), halfword(1))
 29593  
 29594  	// \xref[dump_][\.[\\dump] primitive]
 29595  
 29596  	prg.primitive(strNumber( /* "hskip" */ 1027), quarterword(hskip), halfword(skipCode))
 29597  
 29598  	// \xref[hskip_][\.[\\hskip] primitive]
 29599  	prg.primitive(strNumber( /* "hfil" */ 1028), quarterword(hskip), halfword(filCode))
 29600  	// \xref[hfil_][\.[\\hfil] primitive]
 29601  	prg.primitive(strNumber( /* "hfill" */ 1029), quarterword(hskip), halfword(fillCode))
 29602  
 29603  	// \xref[hfill_][\.[\\hfill] primitive]
 29604  	prg.primitive(strNumber( /* "hss" */ 1030), quarterword(hskip), halfword(ssCode))
 29605  	// \xref[hss_][\.[\\hss] primitive]
 29606  	prg.primitive(strNumber( /* "hfilneg" */ 1031), quarterword(hskip), halfword(filNegCode))
 29607  
 29608  	// \xref[hfil_neg_][\.[\\hfilneg] primitive]
 29609  	prg.primitive(strNumber( /* "vskip" */ 1032), quarterword(vskip), halfword(skipCode))
 29610  
 29611  	// \xref[vskip_][\.[\\vskip] primitive]
 29612  	prg.primitive(strNumber( /* "vfil" */ 1033), quarterword(vskip), halfword(filCode))
 29613  	// \xref[vfil_][\.[\\vfil] primitive]
 29614  	prg.primitive(strNumber( /* "vfill" */ 1034), quarterword(vskip), halfword(fillCode))
 29615  
 29616  	// \xref[vfill_][\.[\\vfill] primitive]
 29617  	prg.primitive(strNumber( /* "vss" */ 1035), quarterword(vskip), halfword(ssCode))
 29618  	// \xref[vss_][\.[\\vss] primitive]
 29619  	prg.primitive(strNumber( /* "vfilneg" */ 1036), quarterword(vskip), halfword(filNegCode))
 29620  
 29621  	// \xref[vfil_neg_][\.[\\vfilneg] primitive]
 29622  	prg.primitive(strNumber( /* "mskip" */ 336), quarterword(mskip), halfword(mskipCode))
 29623  
 29624  	// \xref[mskip_][\.[\\mskip] primitive]
 29625  	prg.primitive(strNumber( /* "kern" */ 340), quarterword(kern), halfword(explicit))
 29626  	// \xref[kern_][\.[\\kern] primitive]
 29627  	prg.primitive(strNumber( /* "mkern" */ 342), quarterword(mkern), halfword(muGlue))
 29628  
 29629  	// \xref[mkern_][\.[\\mkern] primitive]
 29630  
 29631  	prg.primitive(strNumber( /* "moveleft" */ 1054), quarterword(hmove), halfword(1))
 29632  	// \xref[move_left_][\.[\\moveleft] primitive]
 29633  	prg.primitive(strNumber( /* "moveright" */ 1055), quarterword(hmove), halfword(0))
 29634  
 29635  	// \xref[move_right_][\.[\\moveright] primitive]
 29636  	prg.primitive(strNumber( /* "raise" */ 1056), quarterword(vmove), halfword(1))
 29637  	// \xref[raise_][\.[\\raise] primitive]
 29638  	prg.primitive(strNumber( /* "lower" */ 1057), quarterword(vmove), halfword(0))
 29639  	// \xref[lower_][\.[\\lower] primitive]
 29640  
 29641  	prg.primitive(strNumber( /* "box" */ 409), quarterword(makeBox), halfword(boxCode))
 29642  	// \xref[box_][\.[\\box] primitive]
 29643  	prg.primitive(strNumber( /* "copy" */ 1058), quarterword(makeBox), halfword(copyCode))
 29644  	// \xref[copy_][\.[\\copy] primitive]
 29645  	prg.primitive(strNumber( /* "lastbox" */ 1059), quarterword(makeBox), halfword(lastBoxCode))
 29646  	// \xref[last_box_][\.[\\lastbox] primitive]
 29647  	prg.primitive(strNumber( /* "vsplit" */ 965), quarterword(makeBox), halfword(vsplitCode))
 29648  	// \xref[vsplit_][\.[\\vsplit] primitive]
 29649  	prg.primitive(strNumber( /* "vtop" */ 1060), quarterword(makeBox), halfword(vtopCode))
 29650  
 29651  	// \xref[vtop_][\.[\\vtop] primitive]
 29652  	prg.primitive(strNumber( /* "vbox" */ 967), quarterword(makeBox), halfword(vtopCode+vmode))
 29653  	// \xref[vbox_][\.[\\vbox] primitive]
 29654  	prg.primitive(strNumber( /* "hbox" */ 1061), quarterword(makeBox), halfword(vtopCode+hmode))
 29655  
 29656  	// \xref[hbox_][\.[\\hbox] primitive]
 29657  	prg.primitive(strNumber( /* "shipout" */ 1062), quarterword(leaderShip), halfword(aLeaders-1)) // |ship_out_flag=leader_flag-1|
 29658  	// \xref[ship_out_][\.[\\shipout] primitive]
 29659  	prg.primitive(strNumber( /* "leaders" */ 1063), quarterword(leaderShip), halfword(aLeaders))
 29660  	// \xref[leaders_][\.[\\leaders] primitive]
 29661  	prg.primitive(strNumber( /* "cleaders" */ 1064), quarterword(leaderShip), halfword(cLeaders))
 29662  	// \xref[c_leaders_][\.[\\cleaders] primitive]
 29663  	prg.primitive(strNumber( /* "xleaders" */ 1065), quarterword(leaderShip), halfword(xLeaders))
 29664  	// \xref[x_leaders_][\.[\\xleaders] primitive]
 29665  
 29666  	prg.primitive(strNumber( /* "indent" */ 1080), quarterword(startPar), halfword(1))
 29667  	// \xref[indent_][\.[\\indent] primitive]
 29668  	prg.primitive(strNumber( /* "noindent" */ 1081), quarterword(startPar), halfword(0))
 29669  	// \xref[no_indent_][\.[\\noindent] primitive]
 29670  
 29671  	prg.primitive(strNumber( /* "unpenalty" */ 1090), quarterword(removeItem), halfword(penaltyNode))
 29672  
 29673  	// \xref[un_penalty_][\.[\\unpenalty] primitive]
 29674  	prg.primitive(strNumber( /* "unkern" */ 1091), quarterword(removeItem), halfword(kernNode))
 29675  
 29676  	// \xref[un_kern_][\.[\\unkern] primitive]
 29677  	prg.primitive(strNumber( /* "unskip" */ 1092), quarterword(removeItem), halfword(glueNode))
 29678  
 29679  	// \xref[un_skip_][\.[\\unskip] primitive]
 29680  	prg.primitive(strNumber( /* "unhbox" */ 1093), quarterword(unHbox), halfword(boxCode))
 29681  
 29682  	// \xref[un_hbox_][\.[\\unhbox] primitive]
 29683  	prg.primitive(strNumber( /* "unhcopy" */ 1094), quarterword(unHbox), halfword(copyCode))
 29684  
 29685  	// \xref[un_hcopy_][\.[\\unhcopy] primitive]
 29686  	prg.primitive(strNumber( /* "unvbox" */ 1095), quarterword(unVbox), halfword(boxCode))
 29687  
 29688  	// \xref[un_vbox_][\.[\\unvbox] primitive]
 29689  	prg.primitive(strNumber( /* "unvcopy" */ 1096), quarterword(unVbox), halfword(copyCode))
 29690  
 29691  	// \xref[un_vcopy_][\.[\\unvcopy] primitive]
 29692  
 29693  	prg.primitive(strNumber('-'), quarterword(discretionary), halfword(1))
 29694  	// \xref[Single-character primitives -][\quad\.[\\-]]
 29695  	prg.primitive(strNumber( /* "discretionary" */ 349), quarterword(discretionary), halfword(0))
 29696  	// \xref[discretionary_][\.[\\discretionary] primitive]
 29697  
 29698  	prg.primitive(strNumber( /* "eqno" */ 1127), quarterword(eqNo), halfword(0))
 29699  	// \xref[eq_no_][\.[\\eqno] primitive]
 29700  	prg.primitive(strNumber( /* "leqno" */ 1128), quarterword(eqNo), halfword(1))
 29701  	// \xref[leq_no_][\.[\\leqno] primitive]
 29702  
 29703  	prg.primitive(strNumber( /* "mathord" */ 866), quarterword(mathComp), halfword(ordNoad))
 29704  	// \xref[math_ord_][\.[\\mathord] primitive]
 29705  	prg.primitive(strNumber( /* "mathop" */ 867), quarterword(mathComp), halfword(opNoad))
 29706  	// \xref[math_op_][\.[\\mathop] primitive]
 29707  	prg.primitive(strNumber( /* "mathbin" */ 868), quarterword(mathComp), halfword(binNoad))
 29708  	// \xref[math_bin_][\.[\\mathbin] primitive]
 29709  	prg.primitive(strNumber( /* "mathrel" */ 869), quarterword(mathComp), halfword(relNoad))
 29710  	// \xref[math_rel_][\.[\\mathrel] primitive]
 29711  	prg.primitive(strNumber( /* "mathopen" */ 870), quarterword(mathComp), halfword(openNoad))
 29712  	// \xref[math_open_][\.[\\mathopen] primitive]
 29713  	prg.primitive(strNumber( /* "mathclose" */ 871), quarterword(mathComp), halfword(closeNoad))
 29714  	// \xref[math_close_][\.[\\mathclose] primitive]
 29715  	prg.primitive(strNumber( /* "mathpunct" */ 872), quarterword(mathComp), halfword(punctNoad))
 29716  	// \xref[math_punct_][\.[\\mathpunct] primitive]
 29717  	prg.primitive(strNumber( /* "mathinner" */ 873), quarterword(mathComp), halfword(innerNoad))
 29718  	// \xref[math_inner_][\.[\\mathinner] primitive]
 29719  	prg.primitive(strNumber( /* "underline" */ 875), quarterword(mathComp), halfword(underNoad))
 29720  	// \xref[underline_][\.[\\underline] primitive]
 29721  	prg.primitive(strNumber( /* "overline" */ 874), quarterword(mathComp), halfword(overNoad))
 29722  
 29723  	// \xref[overline_][\.[\\overline] primitive]
 29724  	prg.primitive(strNumber( /* "displaylimits" */ 1129), quarterword(limitSwitch), halfword(normal))
 29725  	// \xref[display_limits_][\.[\\displaylimits] primitive]
 29726  	prg.primitive(strNumber( /* "limits" */ 878), quarterword(limitSwitch), halfword(limits))
 29727  	// \xref[limits_][\.[\\limits] primitive]
 29728  	prg.primitive(strNumber( /* "nolimits" */ 879), quarterword(limitSwitch), halfword(noLimits))
 29729  	// \xref[no_limits_][\.[\\nolimits] primitive]
 29730  
 29731  	prg.primitive(strNumber( /* "displaystyle" */ 861), quarterword(mathStyle), halfword(displayStyle))
 29732  	// \xref[display_style_][\.[\\displaystyle] primitive]
 29733  	prg.primitive(strNumber( /* "textstyle" */ 862), quarterword(mathStyle), halfword(textStyle))
 29734  	// \xref[text_style_][\.[\\textstyle] primitive]
 29735  	prg.primitive(strNumber( /* "scriptstyle" */ 863), quarterword(mathStyle), halfword(scriptStyle))
 29736  	// \xref[script_style_][\.[\\scriptstyle] primitive]
 29737  	prg.primitive(strNumber( /* "scriptscriptstyle" */ 864), quarterword(mathStyle), halfword(scriptScriptStyle))
 29738  	// \xref[script_script_style_][\.[\\scriptscriptstyle] primitive]
 29739  
 29740  	prg.primitive(strNumber( /* "above" */ 1147), quarterword(above), halfword(aboveCode))
 29741  
 29742  	// \xref[above_][\.[\\above] primitive]
 29743  	prg.primitive(strNumber( /* "over" */ 1148), quarterword(above), halfword(overCode))
 29744  
 29745  	// \xref[over_][\.[\\over] primitive]
 29746  	prg.primitive(strNumber( /* "atop" */ 1149), quarterword(above), halfword(atopCode))
 29747  
 29748  	// \xref[atop_][\.[\\atop] primitive]
 29749  	prg.primitive(strNumber( /* "abovewithdelims" */ 1150), quarterword(above), halfword(delimitedCode+aboveCode))
 29750  
 29751  	// \xref[above_with_delims_][\.[\\abovewithdelims] primitive]
 29752  	prg.primitive(strNumber( /* "overwithdelims" */ 1151), quarterword(above), halfword(delimitedCode+overCode))
 29753  
 29754  	// \xref[over_with_delims_][\.[\\overwithdelims] primitive]
 29755  	prg.primitive(strNumber( /* "atopwithdelims" */ 1152), quarterword(above), halfword(delimitedCode+atopCode))
 29756  	// \xref[atop_with_delims_][\.[\\atopwithdelims] primitive]
 29757  
 29758  	prg.primitive(strNumber( /* "left" */ 876), quarterword(leftRight), halfword(leftNoad))
 29759  	// \xref[left_][\.[\\left] primitive]
 29760  	prg.primitive(strNumber( /* "right" */ 877), quarterword(leftRight), halfword(rightNoad))
 29761  	// \xref[right_][\.[\\right] primitive]
 29762  	*prg.hash[frozenRight-514].rh() = 877
 29763  	prg.eqtb[frozenRight-1] = prg.eqtb[prg.curVal-1]
 29764  
 29765  	prg.primitive(strNumber( /* "long" */ 1171), quarterword(prefix), halfword(1))
 29766  	// \xref[long_][\.[\\long] primitive]
 29767  	prg.primitive(strNumber( /* "outer" */ 1172), quarterword(prefix), halfword(2))
 29768  	// \xref[outer_][\.[\\outer] primitive]
 29769  	prg.primitive(strNumber( /* "global" */ 1173), quarterword(prefix), halfword(4))
 29770  	// \xref[global_][\.[\\global] primitive]
 29771  	prg.primitive(strNumber( /* "def" */ 1174), quarterword(def), halfword(0))
 29772  	// \xref[def_][\.[\\def] primitive]
 29773  	prg.primitive(strNumber( /* "gdef" */ 1175), quarterword(def), halfword(1))
 29774  	// \xref[gdef_][\.[\\gdef] primitive]
 29775  	prg.primitive(strNumber( /* "edef" */ 1176), quarterword(def), halfword(2))
 29776  	// \xref[edef_][\.[\\edef] primitive]
 29777  	prg.primitive(strNumber( /* "xdef" */ 1177), quarterword(def), halfword(3))
 29778  	// \xref[xdef_][\.[\\xdef] primitive]
 29779  
 29780  	prg.primitive(strNumber( /* "let" */ 1191), quarterword(let), halfword(normal))
 29781  
 29782  	// \xref[let_][\.[\\let] primitive]
 29783  	prg.primitive(strNumber( /* "futurelet" */ 1192), quarterword(let), halfword(normal+1))
 29784  
 29785  	// \xref[future_let_][\.[\\futurelet] primitive]
 29786  
 29787  	prg.primitive(strNumber( /* "chardef" */ 1193), quarterword(shorthandDef), halfword(charDefCode))
 29788  
 29789  	// \xref[char_def_][\.[\\chardef] primitive]
 29790  	prg.primitive(strNumber( /* "mathchardef" */ 1194), quarterword(shorthandDef), halfword(mathCharDefCode))
 29791  
 29792  	// \xref[math_char_def_][\.[\\mathchardef] primitive]
 29793  	prg.primitive(strNumber( /* "countdef" */ 1195), quarterword(shorthandDef), halfword(countDefCode))
 29794  
 29795  	// \xref[count_def_][\.[\\countdef] primitive]
 29796  	prg.primitive(strNumber( /* "dimendef" */ 1196), quarterword(shorthandDef), halfword(dimenDefCode))
 29797  
 29798  	// \xref[dimen_def_][\.[\\dimendef] primitive]
 29799  	prg.primitive(strNumber( /* "skipdef" */ 1197), quarterword(shorthandDef), halfword(skipDefCode))
 29800  
 29801  	// \xref[skip_def_][\.[\\skipdef] primitive]
 29802  	prg.primitive(strNumber( /* "muskipdef" */ 1198), quarterword(shorthandDef), halfword(muSkipDefCode))
 29803  
 29804  	// \xref[mu_skip_def_][\.[\\muskipdef] primitive]
 29805  	prg.primitive(strNumber( /* "toksdef" */ 1199), quarterword(shorthandDef), halfword(toksDefCode))
 29806  
 29807  	// \xref[toks_def_][\.[\\toksdef] primitive]
 29808  
 29809  	prg.primitive(strNumber( /* "catcode" */ 415), quarterword(defCode), halfword(catCodeBase))
 29810  	// \xref[cat_code_][\.[\\catcode] primitive]
 29811  	prg.primitive(strNumber( /* "mathcode" */ 419), quarterword(defCode), halfword(mathCodeBase))
 29812  	// \xref[math_code_][\.[\\mathcode] primitive]
 29813  	prg.primitive(strNumber( /* "lccode" */ 416), quarterword(defCode), halfword(lcCodeBase))
 29814  	// \xref[lc_code_][\.[\\lccode] primitive]
 29815  	prg.primitive(strNumber( /* "uccode" */ 417), quarterword(defCode), halfword(ucCodeBase))
 29816  	// \xref[uc_code_][\.[\\uccode] primitive]
 29817  	prg.primitive(strNumber( /* "sfcode" */ 418), quarterword(defCode), halfword(sfCodeBase))
 29818  	// \xref[sf_code_][\.[\\sfcode] primitive]
 29819  	prg.primitive(strNumber( /* "delcode" */ 477), quarterword(defCode), halfword(delCodeBase))
 29820  	// \xref[del_code_][\.[\\delcode] primitive]
 29821  	prg.primitive(strNumber( /* "textfont" */ 412), quarterword(defFamily), halfword(mathFontBase))
 29822  	// \xref[text_font_][\.[\\textfont] primitive]
 29823  	prg.primitive(strNumber( /* "scriptfont" */ 413), quarterword(defFamily), halfword(mathFontBase+scriptSize))
 29824  	// \xref[script_font_][\.[\\scriptfont] primitive]
 29825  	prg.primitive(strNumber( /* "scriptscriptfont" */ 414), quarterword(defFamily), halfword(mathFontBase+scriptScriptSize))
 29826  	// \xref[script_script_font_][\.[\\scriptscriptfont] primitive]
 29827  
 29828  	prg.primitive(strNumber( /* "hyphenation" */ 941), quarterword(hyphData), halfword(0))
 29829  	// \xref[hyphenation_][\.[\\hyphenation] primitive]
 29830  	prg.primitive(strNumber( /* "patterns" */ 953), quarterword(hyphData), halfword(1))
 29831  	// \xref[patterns_][\.[\\patterns] primitive]
 29832  
 29833  	prg.primitive(strNumber( /* "hyphenchar" */ 1217), quarterword(assignFontInt), halfword(0))
 29834  	// \xref[hyphen_char_][\.[\\hyphenchar] primitive]
 29835  	prg.primitive(strNumber( /* "skewchar" */ 1218), quarterword(assignFontInt), halfword(1))
 29836  	// \xref[skew_char_][\.[\\skewchar] primitive]
 29837  
 29838  	prg.primitive(strNumber( /* "batchmode" */ 274), quarterword(setInteraction), halfword(batchMode))
 29839  	// \xref[batch_mode_][\.[\\batchmode] primitive]
 29840  	prg.primitive(strNumber( /* "nonstopmode" */ 275), quarterword(setInteraction), halfword(nonstopMode))
 29841  	// \xref[nonstop_mode_][\.[\\nonstopmode] primitive]
 29842  	prg.primitive(strNumber( /* "scrollmode" */ 276), quarterword(setInteraction), halfword(scrollMode))
 29843  	// \xref[scroll_mode_][\.[\\scrollmode] primitive]
 29844  	prg.primitive(strNumber( /* "errorstopmode" */ 1227), quarterword(setInteraction), halfword(errorStopMode))
 29845  	// \xref[error_stop_mode_][\.[\\errorstopmode] primitive]
 29846  
 29847  	prg.primitive(strNumber( /* "openin" */ 1228), quarterword(inStream), halfword(1))
 29848  	// \xref[open_in_][\.[\\openin] primitive]
 29849  	prg.primitive(strNumber( /* "closein" */ 1229), quarterword(inStream), halfword(0))
 29850  	// \xref[close_in_][\.[\\closein] primitive]
 29851  
 29852  	prg.primitive(strNumber( /* "message" */ 1230), quarterword(message), halfword(0))
 29853  	// \xref[message_][\.[\\message] primitive]
 29854  	prg.primitive(strNumber( /* "errmessage" */ 1231), quarterword(message), halfword(1))
 29855  	// \xref[err_message_][\.[\\errmessage] primitive]
 29856  
 29857  	prg.primitive(strNumber( /* "lowercase" */ 1237), quarterword(caseShift), halfword(lcCodeBase))
 29858  	// \xref[lowercase_][\.[\\lowercase] primitive]
 29859  	prg.primitive(strNumber( /* "uppercase" */ 1238), quarterword(caseShift), halfword(ucCodeBase))
 29860  	// \xref[uppercase_][\.[\\uppercase] primitive]
 29861  
 29862  	prg.primitive(strNumber( /* "show" */ 1239), quarterword(xray), halfword(showCode))
 29863  	// \xref[show_][\.[\\show] primitive]
 29864  	prg.primitive(strNumber( /* "showbox" */ 1240), quarterword(xray), halfword(showBoxCode))
 29865  	// \xref[show_box_][\.[\\showbox] primitive]
 29866  	prg.primitive(strNumber( /* "showthe" */ 1241), quarterword(xray), halfword(showTheCode))
 29867  	// \xref[show_the_][\.[\\showthe] primitive]
 29868  	prg.primitive(strNumber( /* "showlists" */ 1242), quarterword(xray), halfword(showListsCode))
 29869  	// \xref[show_lists_code_][\.[\\showlists] primitive]
 29870  
 29871  	prg.primitive(strNumber( /* "openout" */ 1285), quarterword(extension), halfword(openNode))
 29872  
 29873  	// \xref[open_out_][\.[\\openout] primitive]
 29874  	prg.primitive(strNumber( /* "write" */ 594), quarterword(extension), halfword(writeNode))
 29875  	prg.writeLoc = uint16(prg.curVal)
 29876  
 29877  	// \xref[write_][\.[\\write] primitive]
 29878  	prg.primitive(strNumber( /* "closeout" */ 1286), quarterword(extension), halfword(closeNode))
 29879  
 29880  	// \xref[close_out_][\.[\\closeout] primitive]
 29881  	prg.primitive(strNumber( /* "special" */ 1287), quarterword(extension), halfword(specialNode))
 29882  
 29883  	// \xref[special_][\.[\\special] primitive]
 29884  	prg.primitive(strNumber( /* "immediate" */ 1288), quarterword(extension), halfword(immediateCode))
 29885  
 29886  	// \xref[immediate_][\.[\\immediate] primitive]
 29887  	prg.primitive(strNumber( /* "setlanguage" */ 1289), quarterword(extension), halfword(setLanguageCode))
 29888  
 29889  	// \xref[set_language_][\.[\\setlanguage] primitive]
 29890  
 29891  	prg.noNewControlSequence = true
 29892  }
 29893  
 29894  //  procedure debug_help; [routine to display various things]
 29895  // label breakpoint,exit;
 29896  // var k, l, m, n:integer;
 29897  // begin  ;
 29898  //    while true do  begin    ;
 29899  //   print_nl(["debug # (-1 to exit):"=]1284);  ;
 29900  // [ \xref[debug \#] ]
 29901  //   read(term_in,m);
 29902  //   if m<0 then  goto exit
 29903  //   else if m=0 then
 29904  //     begin goto breakpoint;
 29905  //  [go to every declared label at least once]
 29906  //     breakpoint: m:=0; ['BREAKPOINT']
 29907  //
 29908  //     end
 29909  //   else  begin read(term_in,n);
 29910  //     case m of
 29911  //     [ \4 ]
 29912  // [ Numbered cases for |debug_help| ]
 29913  // 1: print_word(mem[n]); [display |mem[n]| in all forms]
 29914  // 2: print_int( mem[ n].hh.lh );
 29915  // 3: print_int( mem[ n].hh.rh );
 29916  // 4: print_word(eqtb[n]);
 29917  // 5: print_word(font_info[n]);
 29918  // 6: print_word(save_stack[n]);
 29919  // 7: show_box(n);
 29920  //   [show a box, abbreviated by |show_box_depth| and |show_box_breadth|]
 29921  // 8: begin breadth_max:=10000; depth_threshold:=pool_size-pool_ptr-10;
 29922  //   show_node_list(n); [show a box in its entirety]
 29923  //   end;
 29924  // 9: show_token_list(n,0  ,1000);
 29925  // 10: slow_print(n);
 29926  // 11: check_mem(n>0); [check wellformedness; print new busy locations if |n>0|]
 29927  // 12: search_mem(n); [look for pointers to |n|]
 29928  // 13: begin read(term_in,l); print_cmd_chr(n,l);
 29929  //   end;
 29930  // 14: for k:=0 to n do print(buffer[k]);
 29931  // 15: begin font_in_short_display:=font_base ; short_display(n);
 29932  //   end;
 29933  // 16: panicking:=not panicking;
 29934  //
 29935  //
 29936  //      else  print(["?"=]63)
 29937  //      end ;
 29938  //     end;
 29939  //   end;
 29940  // exit:end;
 29941  // [  ]
 29942  
 29943  // 1332.
 29944  
 29945  // tangle:pos tex.web:24275:61:
 29946  
 29947  // Now this is really it: \TeX\ starts and ends here.
 29948  //
 29949  // The initial test involving |ready_already| should be deleted if the
 29950  // \PASCAL\ runtime system is smart enough to detect such a ``mistake.''
 29951  // \xref[system dependencies]
 29952  func (prg *prg) main() {
 29953  	defer func() {
 29954  		if prg.dviFile != nil {
 29955  			prg.dviFile.Close()
 29956  		}
 29957  		if prg.fmtFile != nil {
 29958  			prg.fmtFile.Close()
 29959  		}
 29960  		if prg.logFile != nil {
 29961  			prg.logFile.Close()
 29962  		}
 29963  		if prg.poolFile != nil {
 29964  			prg.poolFile.Close()
 29965  		}
 29966  		if prg.stderr != nil {
 29967  			prg.stderr.Close()
 29968  		}
 29969  		if prg.stdin != nil {
 29970  			prg.stdin.Close()
 29971  		}
 29972  		if prg.stdout != nil {
 29973  			prg.stdout.Close()
 29974  		}
 29975  		if prg.termIn != nil {
 29976  			prg.termIn.Close()
 29977  		}
 29978  		if prg.termOut != nil {
 29979  			prg.termOut.Close()
 29980  		}
 29981  		if prg.tfmFile != nil {
 29982  			prg.tfmFile.Close()
 29983  		}
 29984  	}()
 29985  
 29986  	prg.history = byte(fatalErrorStop) // in case we quit during initialization
 29987  	prg.termOut.Rewrite("TTY:", "/O")  // open the terminal for output
 29988  	if prg.readyAlready == 314159 {
 29989  		goto startOfTex
 29990  	}
 29991  
 29992  	// Check the “constant” values...
 29993  	prg.bad = 0
 29994  	if halfErrorLine < 30 || halfErrorLine > errorLine-15 {
 29995  		prg.bad = 1
 29996  	}
 29997  	if maxPrintLine < 60 {
 29998  		prg.bad = 2
 29999  	}
 30000  	if dviBufSize%8 != 0 {
 30001  		prg.bad = 3
 30002  	}
 30003  	if memBot+1100 > 30000 {
 30004  		prg.bad = 4
 30005  	}
 30006  	if hashPrime > hashSize {
 30007  		prg.bad = 5
 30008  	}
 30009  	if maxInOpen >= 128 {
 30010  		prg.bad = 6
 30011  	}
 30012  	if 30000 < 256+11 {
 30013  		prg.bad = 7
 30014  	} // we will want |null_list>255|
 30015  
 30016  	if memMin != memBot || memMax != 30000 {
 30017  		prg.bad = 10
 30018  	}
 30019  
 30020  	if memMin > memBot || memMax < 30000 {
 30021  		prg.bad = 10
 30022  	}
 30023  	if minQuarterword > 0 || maxQuarterword < 127 {
 30024  		prg.bad = 11
 30025  	}
 30026  	if 0 > 0 || 65535 < 32767 {
 30027  		prg.bad = 12
 30028  	}
 30029  	if minQuarterword < 0 || maxQuarterword > 65535 {
 30030  		prg.bad = 13
 30031  	}
 30032  	if memMin < 0 || memMax >= 65535 || memBot-memMin > 65535+1 {
 30033  		prg.bad = 14
 30034  	}
 30035  	if fontBase < minQuarterword || fontMax > maxQuarterword {
 30036  		prg.bad = 15
 30037  	}
 30038  	if fontMax > fontBase+256 {
 30039  		prg.bad = 16
 30040  	}
 30041  	if saveSize > 65535 || maxStrings > 65535 {
 30042  		prg.bad = 17
 30043  	}
 30044  	if bufSize > 65535 {
 30045  		prg.bad = 18
 30046  	}
 30047  	if maxQuarterword-minQuarterword < 255 {
 30048  		prg.bad = 19
 30049  	}
 30050  
 30051  	if 07777+undefinedControlSequence > 65535 { // 07777=
 30052  		prg.bad = 21
 30053  	}
 30054  
 30055  	if formatDefaultLength > fileNameSize {
 30056  		prg.bad = 31
 30057  	}
 30058  
 30059  	if 2*65535 < 30000-memMin {
 30060  		prg.bad = 41
 30061  	}
 30062  
 30063  	if prg.bad > 0 {
 30064  		prg.termOut.Writeln("Ouch---my internal constants have been clobbered!",
 30065  			"---case ", prg.bad, knuth.WriteWidth(1))
 30066  		// \xref[Ouch...clobbered]
 30067  
 30068  		// \xref[Ouch...clobbered]
 30069  		goto finalEnd
 30070  	}
 30071  	prg.initialize() // set global variables to their starting values
 30072  	if !prg.getStringsStarted() {
 30073  		goto finalEnd
 30074  	}
 30075  	prg.initPrim() // call |primitive| for each primitive
 30076  	prg.initStrPtr = prg.strPtr
 30077  	prg.initPoolPtr = prg.poolPtr
 30078  	prg.fixDateAndTime()
 30079  
 30080  	prg.readyAlready = 314159
 30081  
 30082  startOfTex:
 30083  	prg.selector = byte(termOnly)
 30084  	prg.tally = 0
 30085  	prg.termOffset = 0
 30086  	prg.fileOffset = 0
 30087  
 30088  	prg.termOut.Write("This is TeX, Version 3.141592653 (gotex v0.0-prerelease)")
 30089  	if int32(prg.formatIdent) == 0 {
 30090  		prg.termOut.Writeln(" (no format preloaded)")
 30091  	} else {
 30092  		prg.slowPrint(int32(prg.formatIdent))
 30093  		prg.printLn()
 30094  	}
 30095  
 30096  	prg.jobName = 0
 30097  	prg.nameInProgress = false
 30098  	prg.logOpened = false
 30099  
 30100  	prg.outputFileName = 0
 30101  
 30102  	// Get the first line of input and prepare to start
 30103  	{
 30104  		{
 30105  			prg.inputPtr = 0
 30106  			prg.maxInStack = 0
 30107  			prg.inOpen = 0
 30108  			prg.openParens = 0
 30109  			prg.maxBufStack = 0
 30110  			prg.paramPtr = 0
 30111  			prg.maxParamStack = 0
 30112  			prg.first = uint16(bufSize)
 30113  			for {
 30114  				prg.buffer[prg.first] = 0
 30115  				prg.first = uint16(int32(prg.first) - 1)
 30116  				if int32(prg.first) == 0 {
 30117  					break
 30118  				}
 30119  			}
 30120  			prg.scannerStatus = byte(normal)
 30121  			prg.warningIndex = 0
 30122  			prg.first = 1
 30123  			prg.curInput.stateField = byte(newLine)
 30124  			prg.curInput.startField = 1
 30125  			prg.curInput.indexField = 0
 30126  			prg.line = 0
 30127  			prg.curInput.nameField = 0
 30128  			prg.forceEof = false
 30129  			prg.alignState = 1000000
 30130  
 30131  			if !prg.initTerminal() {
 30132  				goto finalEnd
 30133  			}
 30134  			prg.curInput.limitField = prg.last
 30135  			prg.first = uint16(int32(prg.last) + 1) // |init_terminal| has set |loc| and |last|
 30136  		}
 30137  		if int32(prg.formatIdent) == 0 || int32(prg.buffer[prg.curInput.locField]) == '&' {
 30138  			if int32(prg.formatIdent) != 0 {
 30139  				prg.initialize()
 30140  			} // erase preloaded format
 30141  			if !prg.openFmtFile() {
 30142  				goto finalEnd
 30143  			}
 30144  			if !prg.loadFmtFile() {
 30145  				prg.wClose(prg.fmtFile)
 30146  				goto finalEnd
 30147  			}
 30148  			prg.wClose(prg.fmtFile)
 30149  			for int32(prg.curInput.locField) < int32(prg.curInput.limitField) && int32(prg.buffer[prg.curInput.locField]) == ' ' {
 30150  				prg.curInput.locField = uint16(int32(prg.curInput.locField) + 1)
 30151  			}
 30152  		}
 30153  		if *prg.eqtb[intBase+endLineCharCode-1].int() < 0 || *prg.eqtb[intBase+endLineCharCode-1].int() > 255 {
 30154  			prg.curInput.limitField = uint16(int32(prg.curInput.limitField) - 1)
 30155  		} else {
 30156  			prg.buffer[prg.curInput.limitField] = byte(*prg.eqtb[intBase+endLineCharCode-1].int())
 30157  		}
 30158  		prg.fixDateAndTime()
 30159  
 30160  		// Compute the magic offset
 30161  		prg.magicOffset = int32(prg.strStart[mathSpacing]) - 9*ordNoad
 30162  
 30163  		// Initialize the print |selector|...
 30164  		if int32(prg.interaction) == batchMode {
 30165  			prg.selector = byte(noPrint)
 30166  		} else {
 30167  			prg.selector = byte(termOnly)
 30168  		}
 30169  		if int32(prg.curInput.locField) < int32(prg.curInput.limitField) && int32(*(*prg.eqtb[catCodeBase+int32(prg.buffer[prg.curInput.locField])-1].hh()).rh()) != escape {
 30170  			prg.startInput()
 30171  		}
 30172  		// \.[\\input] assumed
 30173  	}
 30174  	prg.history = byte(spotless) // ready to go!
 30175  	prg.mainControl()            // come to life
 30176  	prg.finalCleanup()           // prepare for death
 30177  	prg.closeFilesAndTerminate()
 30178  
 30179  finalEnd:
 30180  	prg.readyAlready = 0
 30181  }
 30182  
 30183  // 1340. \[53] Extensions
 30184  
 30185  // tangle:pos tex.web:24529:17:
 30186  
 30187  // The program above includes a bunch of ``hooks'' that allow further
 30188  // capabilities to be added without upsetting \TeX's basic structure.
 30189  // Most of these hooks are concerned with ``whatsit'' nodes, which are
 30190  // intended to be used for special purposes; whenever a new extension to
 30191  // \TeX\ involves a new kind of whatsit node, a corresponding change needs
 30192  // to be made to the routines below that deal with such nodes,
 30193  // but it will usually be unnecessary to make many changes to the
 30194  // other parts of this program.
 30195  //
 30196  // In order to demonstrate how extensions can be made, we shall treat
 30197  // `\.[\\write]', `\.[\\openout]', `\.[\\closeout]', `\.[\\immediate]',
 30198  // `\.[\\special]', and `\.[\\setlanguage]' as if they were extensions.
 30199  // These commands are actually primitives of \TeX, and they should
 30200  // appear in all implementations of the system; but let's try to imagine
 30201  // that they aren't. Then the program below illustrates how a person
 30202  // could add them.
 30203  //
 30204  // Sometimes, of course, an extension will require changes to \TeX\ itself;
 30205  // no system of hooks could be complete enough for all conceivable extensions.
 30206  // The features associated with `\.[\\write]' are almost all confined to the
 30207  // following paragraphs, but there are small parts of the |print_ln| and
 30208  // |print_char| procedures that were introduced specifically to \.[\\write]
 30209  // characters. Furthermore one of the token lists recognized by the scanner
 30210  // is a |write_text|; and there are a few other miscellaneous places where we
 30211  // have already provided for some aspect of \.[\\write].  The goal of a \TeX\
 30212  // extender should be to minimize alterations to the standard parts of the
 30213  // program, and to avoid them completely if possible. He or she should also
 30214  // be quite sure that there's no easy way to accomplish the desired goals
 30215  // with the standard features that \TeX\ already has. ``Think thrice before
 30216  // extending,'' because that may save a lot of work, and it will also keep
 30217  // incompatible extensions of \TeX\ from proliferating.
 30218  // \xref[system dependencies]
 30219  // \xref[extensions to \TeX]
 30220  
 30221  // 1341.
 30222  
 30223  // tangle:pos tex.web:24562:23:
 30224  
 30225  // First let's consider the format of whatsit nodes that are used to represent
 30226  // the data associated with \.[\\write] and its relatives. Recall that a whatsit
 30227  // has |type=whatsit_node|, and the |subtype| is supposed to distinguish
 30228  // different kinds of whatsits. Each node occupies two or more words; the
 30229  // exact number is immaterial, as long as it is readily determined from the
 30230  // |subtype| or other data.
 30231  //
 30232  // We shall introduce five |subtype| values here, corresponding to the
 30233  // control sequences \.[\\openout], \.[\\write], \.[\\closeout], \.[\\special], and
 30234  // \.[\\setlanguage]. The second word of I/O whatsits has a |write_stream| field
 30235  // that identifies the write-stream number (0 to 15, or 16 for out-of-range and
 30236  // positive, or 17 for out-of-range and negative).
 30237  // In the case of \.[\\write] and \.[\\special], there is also a field that
 30238  // points to the reference count of a token list that should be sent. In the
 30239  // case of \.[\\openout], we need three words and three auxiliary subfields
 30240  // to hold the string numbers for name, area, and extension.
 30241  
 30242  // 1379. \[54] System-dependent changes
 30243  
 30244  // tangle:pos tex.web:24985:31:
 30245  
 30246  // This section should be replaced, if necessary, by any special
 30247  // modifications of the program
 30248  // that are necessary to make \TeX\ work at a particular installation.
 30249  // It is usually best to design your change file so that all changes to
 30250  // previous sections preserve the section numbering; then everybody's version
 30251  // will be consistent with the published program. More extensive changes,
 30252  // which introduce new sections, can be inserted here; then only the index
 30253  // itself will get a new section number.
 30254  // \xref[system dependencies]
 30255  
 30256  // 1380. \[55] Index
 30257  
 30258  // tangle:pos tex.web:24996:12:
 30259  
 30260  // Here is where you can find all uses of each identifier in the program,
 30261  // with underlined entries pointing to where the identifier was defined.
 30262  // If the identifier is only one letter long, however, you get to see only
 30263  // the underlined entries. [\sl All references are to section numbers instead of
 30264  // page numbers.]
 30265  //
 30266  // This index also lists error messages and other aspects of the program
 30267  // that you might want to look up some day. For example, the entry
 30268  // for ``system dependencies'' lists all sections that should receive
 30269  // special attention from people who are installing \TeX\ in a new
 30270  // operating environment. A list of various things that can't happen appears
 30271  // under ``this can't happen''. Approximately 40 sections are listed under
 30272  // ``inner loop''; these account for about 60\pct! of \TeX's running time,
 30273  // exclusive of input and output.