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.