modernc.org/knuth@v0.0.4/vptovf/vptovf.go (about) 1 // Code generated by '[/tmp/go-build2255657050/b001/exe/generate]', DO NOT EDIT. 2 3 // % This program by D. E. Knuth is not copyrighted and can be used freely. 4 // % Version 1 was implemented in December 1989. 5 // % Version 1.1 fixed some for-loop indices for stricter Pascal (April 1990). 6 // % Version 1.2 fixed `nonexistent char 0' bug, and a bit more (September 1990). 7 // % Version 1.3 has more robust `out_scaled' (March 1991). 8 // % Version 1.4 (March 1995) initialized lk_step_ended (Armin K\"ollner). 9 // % Version 1.5 (August 1998) corrected vf_fix(0) (Wayne Sullivan). 10 // % Version 1.6 (January 2014) corrected possible end-of-line glitch (Ken Nakano), 11 // % and get_fix now treats -- as + (Peter Breitenlohner). 12 // 13 // % Here is TeX material that gets inserted after \input webmac 14 // \def\hang[\hangindent 3em\indent\ignorespaces] 15 // \font\ninerm=cmr9 16 // \let\mc=\ninerm % medium caps for names like SAIL 17 // \def\PASCAL[Pascal] 18 // \font\logo=logo10 % for the METAFONT logo 19 // \def\MF[[\logo METAFONT]] 20 // 21 // \def\(#1)[] % this is used to make section names sort themselves better 22 // \def\9#1[] % this is used for sort keys in the index 23 // 24 // \def\title[VP\lowercase[to]VF] 25 // \def\contentspagenumber[201] 26 // \def\topofcontents[\null 27 // \titlefalse % include headline on the contents page 28 // \def\rheader[\mainfont\hfil \contentspagenumber] 29 // \vfill 30 // \centerline[\titlefont The [\ttitlefont VPtoVF] processor] 31 // \vskip 15pt 32 // \centerline[(Version 1.6, January 2014)] 33 // \vfill] 34 // \def\botofcontents[\vfill 35 // \centerline[\hsize 5in\baselineskip9pt 36 // \vbox[\ninerm\noindent 37 // The preparation of this program 38 // was supported in part by the National Science 39 // Foundation and by the System Development Foundation. `\TeX' is a 40 // trademark of the American Mathematical Society.]]] 41 // \pageno=\contentspagenumber \advance\pageno by 1 42 // 43 // 44 45 // 1. Introduction 46 47 // tangle:pos vptovf.web:41:14: 48 49 // The \.[VPtoVF] utility program converts virtual-property-list (``\.[VPL]'') 50 // files into an equivalent pair of files called a virtual font (``\.[VF]'') file 51 // and a \TeX\ font metric (``\.[TFM]'') file. It also makes a thorough check 52 // of the given \.[VPL] file, so that the \.[VF] file should be acceptable to 53 // device drivers and the \.[TFM] file should be acceptable to \TeX. 54 // 55 // \indent\.[VPtoVF] is an extended version of the program \.[PLtoTF], which 56 // is part of the standard \TeX ware library. 57 // The idea of a virtual font was inspired by the work of David R. Fuchs 58 // \xref[Fuchs, David Raymond] 59 // who designed a similar set of conventions in 1984 while developing a 60 // device driver for ArborText, Inc. He wrote a somewhat similar program 61 // called \.[PLFONT]. 62 // 63 // The |banner| string defined here should be changed whenever \.[VPtoVF] 64 // gets modified. 65 66 // 2. 67 68 // tangle:pos vptovf.web:59:75: 69 70 // This program is written entirely in standard \PASCAL, except that 71 // it has to do some slightly system-dependent character code conversion 72 // on input. Furthermore, lower case letters are used in error messages; 73 // they could be converted to upper case if necessary. The input is read 74 // from |vpl_file|, and the output is written on |vf_file| and |tfm_file|; 75 // error messages and 76 // other remarks are written on the |output| file, which the user may 77 // choose to assign to the terminal if the system permits it. 78 // \xref[system dependencies] 79 // 80 // The term |print| is used instead of |write| when this program writes on 81 // the |output| file, so that all such output can be easily deflected. 82 83 package vptovf 84 85 import ( 86 "math" 87 "unsafe" 88 89 "modernc.org/knuth" 90 ) 91 92 var ( 93 _ = math.MaxInt32 94 _ unsafe.Pointer 95 ) 96 97 type ( 98 char = byte 99 signal int 100 ) 101 102 func strcopy(dst []char, src string) { 103 for i := 0; i < len(dst) && i < len(src); i++ { 104 dst[i] = src[i] 105 } 106 } 107 108 func arraystr(a []char) string { 109 b := make([]byte, len(a)) 110 for i, c := range a { 111 b[i] = c 112 } 113 return string(b) 114 } 115 116 func abs(n int32) int32 { 117 if n >= 0 { 118 return n 119 } 120 121 return -n 122 } 123 124 func fabs(f float64) float64 { 125 if f >= 0 { 126 return f 127 } 128 129 return -f 130 } 131 132 func round(f float64) int32 { 133 if f >= 0 { 134 return int32(f + 0.5) 135 } 136 137 return int32(f - 0.5) 138 } 139 140 const ( 141 firstOrd = 0 /* ordinal number of the smallest element of |char| */ 142 lastOrd = 127 /* ordinal number of the largest element of |char| */ 143 invalidCode = 0177 /* code deserving an error message */ 144 maxNameIndex = 100 /* upper bound on the number of keywords */ 145 maxLetters = 666 /* upper bound on the total length of all keywords */ 146 longestName = 20 /* length of \.[DEFAULTRULETHICKNESS] */ 147 hashPrime = 141 /* size of the hash table */ 148 commentCode = 0 149 checkSumCode = 1 150 designSizeCode = 2 151 designUnitsCode = 3 152 codingSchemeCode = 4 153 familyCode = 5 154 faceCode = 6 155 sevenBitSafeFlagCode = 7 156 headerCode = 8 157 fontDimenCode = 9 158 ligTableCode = 10 159 boundaryCharCode = 11 160 virtualTitleCode = 12 161 mapFontCode = 13 162 characterCode = 14 163 fontNameCode = 20 164 fontAreaCode = 21 165 fontChecksumCode = 22 166 fontAtCode = 23 167 fontDsizeCode = 24 168 parameterCode = 30 169 charInfoCode = 60 170 width = 1 171 height = 2 172 depth = 3 173 italic = 4 174 charWdCode = charInfoCode + width 175 charHtCode = charInfoCode + height 176 charDpCode = charInfoCode + depth 177 charIcCode = charInfoCode + italic 178 nextLargerCode = 65 179 mapCode = 66 180 varCharCode = 67 181 selectFontCode = 80 182 setCharCode = 81 183 setRuleCode = 82 184 moveRightCode = 83 185 moveDownCode = 85 186 pushCode = 87 187 popCode = 88 188 specialCode = 89 189 specialHexCode = 90 190 labelCode = 100 191 stopCode = 101 192 skipCode = 102 193 krnCode = 103 194 ligCode = 104 195 checkSumLoc = 0 196 designSizeLoc = 4 197 codingSchemeLoc = 8 198 familyLoc = codingSchemeLoc + 40 199 sevenFlagLoc = familyLoc + 20 200 faceLoc = sevenFlagLoc + 3 201 memSize = 1028 + 4 /* number of nonzero memory addresses */ 202 noTag = 0 /* vanilla character */ 203 ligTag = 1 /* character has a ligature/kerning program */ 204 listTag = 2 /* character has a successor in a charlist */ 205 extTag = 3 /* character is extensible */ 206 stopFlag = 128 /* value indicating `\.[STOP]' in a lig/kern program */ 207 kernFlag = 128 /* op code for a kern step */ 208 setChar0 = 0 /* \.[DVI] command to typeset character 0 and move right */ 209 set1 = 128 /* typeset a character and move right */ 210 setRule = 132 /* typeset a rule and move right */ 211 push = 141 /* save the current positions */ 212 pop = 142 /* restore previous positions */ 213 right1 = 143 /* move right */ 214 w0 = 147 /* move right by |w| */ 215 w1 = 148 /* move right and set |w| */ 216 x0 = 152 /* move right by |x| */ 217 x1 = 153 /* move right and set |x| */ 218 down1 = 157 /* move down */ 219 y0 = 161 /* move down by |y| */ 220 y1 = 162 /* move down and set |y| */ 221 z0 = 166 /* move down by |z| */ 222 z1 = 167 /* move down and set |z| */ 223 fntNum0 = 171 /* set current font to 0 */ 224 fnt1 = 235 /* set current font */ 225 xxx1 = 239 /* extension to \.[DVI] primitives */ 226 xxx4 = 242 /* potentially long extension to \.[DVI] primitives */ 227 fntDef1 = 243 /* define the meaning of a font number */ 228 pre = 247 /* preamble */ 229 post = 248 /* postamble beginning */ 230 simple = 0 /* $f(x,y)=z$ */ 231 leftZ = 1 /* $f(x,y)=f(z,y)$ */ 232 rightZ = 2 /* $f(x,y)=f(x,z)$ */ 233 bothZ = 3 /* $f(x,y)=f(f(x,z),y)$ */ 234 pending = 4 /* $f(x,y)$ is being evaluated */ 235 idByte = 202 /* current version of \.[VF] format */ 236 237 // Constants in the outer block 238 bufSize = 60 // length of lines displayed in error messages 239 maxHeaderBytes = 100 // four times the maximum number of words allowed in 240 // the \.[TFM] file header block, must be 1024 or less 241 242 vfSize = 10000 // maximum length of |vf| data, in bytes 243 maxStack = 100 // maximum depth of simulated \.[DVI] stack 244 maxParamWords = 30 // the maximum number of \.[fontdimen] parameters allowed 245 maxLigSteps = 5000 246 // maximum length of ligature program, must be at most $32767-257=32510$ 247 maxKerns = 500 // the maximum number of distinct kern values 248 hashSize = 5003 // preferably a prime number, a bit larger than the number 249 // of character pairs in lig/kern steps 250 ) 251 252 type ( 253 // Types in the outer block 254 // byte = /* 0..255 */ byte // unsigned eight-bit quantity 255 asciiCode = /* 040..0177 */ byte // standard ASCII code numbers 256 257 fourBytes = struct { 258 b0 byte 259 b1 byte 260 b2 byte 261 b3 byte 262 } 263 264 fixWord = int32 // a scaled real value with 20 bits of fraction 265 266 headerIndex = /* 0..maxHeaderBytes */ byte 267 indx = /* 0..077777 */ uint16 268 269 pointer = /* 0..memSize */ uint16 // an index into memory 270 ) 271 272 type prg struct { 273 stdin, stdout, stderr knuth.File 274 // Globals in the outer block 275 vplFile/* text */ knuth.File 276 277 vfFile knuth.File 278 tfmFile knuth.File 279 280 xord [256]asciiCode // conversion table 281 282 line int32 // the number of the current line 283 goodIndent int32 // the number of lines since the last bad indentation 284 indent int32 // the number of spaces per open parenthesis, zero if unknown 285 level int32 // the current number of open parentheses 286 287 leftLn, rightLn bool // are the left and right ends of the buffer 288 // at end-of-line marks? 289 290 limit/* 0..bufSize */ byte // position of the last character present in the buffer 291 loc/* 0..bufSize */ byte // position of the last character read in the buffer 292 buffer [60]char 293 inputHasEnded bool // there is no more input to read 294 295 charsOnLine/* 0..8 */ byte // the number of characters printed on the current line 296 297 curChar asciiCode // we have just read this 298 299 start [100] /* 0..maxLetters */ uint16 300 dictionary [667]asciiCode 301 startPtr/* 0..maxNameIndex */ byte // the first available place in |start| 302 dictPtr/* 0..maxLetters */ uint16 // the first available place in |dictionary| 303 304 curName [20]asciiCode // a name to look up 305 nameLength/* 0..longestName */ byte // its length 306 namePtr/* 0..maxNameIndex */ byte // its ordinal number in the dictionary 307 308 nhash [141] /* 0..maxNameIndex */ byte 309 curHash/* 0..hashPrime-1 */ byte // current position in the hash table 310 311 equiv [101]byte 312 curCode byte // equivalent most recently found in |equiv| 313 314 curBytes fourBytes // a four-byte accumulator 315 zeroBytes fourBytes // four bytes all zero 316 317 fractionDigits [7]int32 // $2^[21]$ times $d_j$ 318 319 headerBytes [101]byte // the header block 320 headerPtr headerIndex // the number of header bytes in use 321 designSize fixWord // the design size 322 designUnits fixWord // reciprocal of the scaling factor 323 frozenDu bool // have we used |design_units| irrevocably? 324 sevenBitSafeFlag bool // does the file claim to be seven-bit-safe? 325 ligKern [5001]fourBytes // the ligature program 326 nl/* 0..32767 */ uint16 // the number of ligature/kern instructions so far 327 minNl/* 0..32767 */ uint16 // the final value of |nl| must be at least this 328 kern [501]fixWord // the distinct kerning amounts 329 nk/* 0..maxKerns */ uint16 // the number of entries of |kern| 330 exten [256]fourBytes // extensible character specs 331 ne/* 0..256 */ uint16 // the number of extensible characters 332 param [30]fixWord // \.[FONTDIMEN] parameters 333 np/* 0..maxParamWords */ byte // the largest parameter set nonzero 334 checkSumSpecified bool // did the user name the check sum? 335 bchar/* 0..256 */ uint16 // the right boundary character, or 256 if unspecified 336 vf [10001]byte // stored bytes for \.[VF] file 337 vfPtr/* 0..vfSize */ uint16 // first unused location in |vf| 338 vtitleStart/* 0..vfSize */ uint16 // starting location of \.[VTITLE] string 339 vtitleLength byte // length of \.[VTITLE] string 340 packetStart [256] /* 0..vfSize */ uint16 341 // beginning location of character packet 342 packetLength [256]int32 // length of character packet 343 fontPtr/* 0..256 */ uint16 // number of distinct local fonts seen 344 curFont/* 0..256 */ uint16 // number of the current local font 345 fnameStart [256] /* 0..vfSize */ uint16 // beginning of local font name 346 fnameLength [256]byte // length of local font name 347 fareaStart [256] /* 0..vfSize */ uint16 // beginning of local font area 348 fareaLength [256]byte // length of local font area 349 fontChecksum [256]fourBytes // local font checksum 350 fontNumber [257]fourBytes // local font id number 351 fontAt [256]fixWord // local font ``at size'' 352 fontDsize [256]fixWord // local font design size 353 354 memory [1033]fixWord // character dimensions and kerns 355 memPtr pointer // largest |memory| word in use 356 link [1033]pointer // to make lists of |memory| items 357 charWd [256]pointer // pointers to the widths 358 charHt [256]pointer // pointers to the heights 359 charDp [256]pointer // pointers to the depths 360 charIc [256]pointer // pointers to italic corrections 361 charTag [256] /* noTag..extTag */ byte // character tags 362 charRemainder [257] /* 0..65535 */ uint16 // pointers to ligature labels, 363 // next larger characters, or extensible characters 364 365 nextD fixWord // the next larger interval that is worth trying 366 367 index [1033]byte 368 excess byte // number of words to remove, if list is being shortened 369 370 c byte // the current character or byte being processed 371 x fixWord // current dimension of interest 372 k int32 // general-purpose index 373 374 lkStepEnded bool 375 // was the last \.[LIGTABLE] property \.[LIG] or \.[KRN]? 376 krnPtr/* 0..maxKerns */ uint16 // an index into |kern| 377 378 hstack [101] /* 0..2 */ byte // number of known horizontal movements 379 vstack [101] /* 0..2 */ byte // number of known vertical movements 380 wstack, xstack, ystack, zstack [101]fixWord 381 stackPtr/* 0..maxStack */ byte 382 383 sevenUnsafe bool // do seven-bit characters generate eight-bit ones? 384 385 delta fixWord // size of the intervals needed for rounding 386 387 ligPtr/* 0..maxLigSteps */ uint16 // an index into |lig_kern| 388 hash [5004] /* 0..66048 */ uint32 // $256x+y+1$ for $x\le257$ and $y\le255$ 389 class [5004] /* simple..pending */ byte 390 ligZ [5004] /* 0..257 */ uint16 391 hashPtr/* 0..hashSize */ uint16 // the number of nonzero entries in |hash| 392 hashList [5004] /* 0..hashSize */ uint16 // list of those nonzero entries 393 h, hh/* 0..hashSize */ uint16 // indices into the hash table 394 tt indx // temporary register 395 xLigCycle, yLigCycle/* 0..256 */ uint16 // problematic ligature pair 396 397 bc byte // the smallest character code in the font 398 ec byte // the largest character code in the font 399 lh byte // the number of words in the header block 400 lf/* 0..32767 */ uint16 // the number of words in the entire \.[TFM] file 401 notFound bool // has a font character been found? 402 tempWidth fixWord // width being used to compute a check sum 403 404 j/* 0..maxHeaderBytes */ byte // index into |header_bytes| 405 p pointer // index into |memory| 406 q/* width..italic */ byte // runs through the list heads for dimensions 407 parPtr/* 0..maxParamWords */ byte // runs through the parameters 408 409 labelTable [257]struct { 410 rr int16 // sorted label values 411 cc byte // associated characters 412 } 413 labelPtr/* 0..256 */ uint16 // index of highest entry in |label_table| 414 sortPtr/* 0..256 */ uint16 // index into |label_table| 415 lkOffset/* 0..256 */ uint16 // smallest offset value that might work 416 t/* 0..077777 */ uint16 // label value that is being redirected 417 extraLocNeeded bool // do we need a special word for |bchar|? 418 419 vcount int32 // number of bytes written to |vf_file| 420 } 421 422 func (prg *prg) initialize() { // this procedure gets things started properly 423 var ( 424 // Local variables for initialization 425 k int32 // all-purpose initialization index 426 427 h/* 0..hashPrime-1 */ byte // runs through the hash table 428 429 d headerIndex // an index into |header_bytes| 430 431 c byte // runs through all character codes 432 ) 433 prg.stdout.Writeln("This is VPtoVF, Version 1.6 (govptovf v0.0-prerelease)") 434 435 // Set initial values 436 prg.vplFile.Reset() 437 438 prg.vfFile.Rewrite() 439 prg.tfmFile.Rewrite() 440 441 for ii := int32(firstOrd); ii <= lastOrd; ii++ { 442 k = ii 443 _ = k 444 prg.xord[char(k)] = byte(invalidCode) 445 } 446 prg.xord[' '] = ' ' 447 prg.xord['!'] = '!' 448 prg.xord['"'] = '"' 449 prg.xord['#'] = '#' 450 prg.xord['$'] = '$' 451 prg.xord['%'] = '%' 452 prg.xord['&'] = '&' 453 prg.xord['\''] = '\'' 454 prg.xord['('] = '(' 455 prg.xord[')'] = ')' 456 prg.xord['*'] = '*' 457 prg.xord['+'] = '+' 458 prg.xord[','] = ',' 459 prg.xord['-'] = '-' 460 prg.xord['.'] = '.' 461 prg.xord['/'] = '/' 462 prg.xord['0'] = '0' 463 prg.xord['1'] = '1' 464 prg.xord['2'] = '2' 465 prg.xord['3'] = '3' 466 prg.xord['4'] = '4' 467 prg.xord['5'] = '5' 468 prg.xord['6'] = '6' 469 prg.xord['7'] = '7' 470 prg.xord['8'] = '8' 471 prg.xord['9'] = '9' 472 prg.xord[':'] = ':' 473 prg.xord[';'] = ';' 474 prg.xord['<'] = '<' 475 prg.xord['='] = '=' 476 prg.xord['>'] = '>' 477 prg.xord['?'] = '?' 478 prg.xord['@'] = '@' 479 prg.xord['A'] = 'A' 480 prg.xord['B'] = 'B' 481 prg.xord['C'] = 'C' 482 prg.xord['D'] = 'D' 483 prg.xord['E'] = 'E' 484 prg.xord['F'] = 'F' 485 prg.xord['G'] = 'G' 486 prg.xord['H'] = 'H' 487 prg.xord['I'] = 'I' 488 prg.xord['J'] = 'J' 489 prg.xord['K'] = 'K' 490 prg.xord['L'] = 'L' 491 prg.xord['M'] = 'M' 492 prg.xord['N'] = 'N' 493 prg.xord['O'] = 'O' 494 prg.xord['P'] = 'P' 495 prg.xord['Q'] = 'Q' 496 prg.xord['R'] = 'R' 497 prg.xord['S'] = 'S' 498 prg.xord['T'] = 'T' 499 prg.xord['U'] = 'U' 500 prg.xord['V'] = 'V' 501 prg.xord['W'] = 'W' 502 prg.xord['X'] = 'X' 503 prg.xord['Y'] = 'Y' 504 prg.xord['Z'] = 'Z' 505 prg.xord['['] = '[' 506 prg.xord['\\'] = '\\' 507 prg.xord[']'] = ']' 508 prg.xord['^'] = '^' 509 prg.xord['_'] = '_' 510 prg.xord['`'] = '`' 511 prg.xord['a'] = 'a' 512 prg.xord['b'] = 'b' 513 prg.xord['c'] = 'c' 514 prg.xord['d'] = 'd' 515 prg.xord['e'] = 'e' 516 prg.xord['f'] = 'f' 517 prg.xord['g'] = 'g' 518 prg.xord['h'] = 'h' 519 prg.xord['i'] = 'i' 520 prg.xord['j'] = 'j' 521 prg.xord['k'] = 'k' 522 prg.xord['l'] = 'l' 523 prg.xord['m'] = 'm' 524 prg.xord['n'] = 'n' 525 prg.xord['o'] = 'o' 526 prg.xord['p'] = 'p' 527 prg.xord['q'] = 'q' 528 prg.xord['r'] = 'r' 529 prg.xord['s'] = 's' 530 prg.xord['t'] = 't' 531 prg.xord['u'] = 'u' 532 prg.xord['v'] = 'v' 533 prg.xord['w'] = 'w' 534 prg.xord['x'] = 'x' 535 prg.xord['y'] = 'y' 536 prg.xord['z'] = 'z' 537 prg.xord['{'] = '{' 538 prg.xord['|'] = '|' 539 prg.xord['}'] = '}' 540 prg.xord['~'] = '~' 541 542 prg.line = 0 543 prg.goodIndent = 0 544 prg.indent = 0 545 prg.level = 0 546 547 prg.limit = 0 548 prg.loc = 0 549 prg.leftLn = true 550 prg.rightLn = true 551 prg.inputHasEnded = false 552 553 prg.charsOnLine = 0 554 555 prg.startPtr = 1 556 prg.start[1-1] = 0 557 prg.dictPtr = 0 558 559 for ii := int32(0); ii <= hashPrime-1; ii++ { 560 h = byte(ii) 561 _ = h 562 prg.nhash[h] = 0 563 } 564 565 prg.zeroBytes.b0 = 0 566 prg.zeroBytes.b1 = 0 567 prg.zeroBytes.b2 = 0 568 prg.zeroBytes.b3 = 0 569 570 for ii := int32(0); ii <= 18*4-1; ii++ { 571 d = headerIndex(ii) 572 _ = d 573 prg.headerBytes[d] = 0 574 } 575 prg.headerBytes[8] = 11 576 prg.headerBytes[9] = 'U' 577 prg.headerBytes[10] = 'N' 578 prg.headerBytes[11] = 'S' 579 prg.headerBytes[12] = 'P' 580 prg.headerBytes[13] = 'E' 581 prg.headerBytes[14] = 'C' 582 prg.headerBytes[15] = 'I' 583 prg.headerBytes[16] = 'F' 584 prg.headerBytes[17] = 'I' 585 prg.headerBytes[18] = 'E' 586 prg.headerBytes[19] = 'D' 587 // \xref[UNSPECIFIED] 588 for ii := int32(familyLoc); ii <= familyLoc+11; ii++ { 589 d = headerIndex(ii) 590 _ = d 591 prg.headerBytes[d] = prg.headerBytes[int32(d)-40] 592 } 593 prg.designSize = 10 * 04000000 594 prg.designUnits = 04000000 595 prg.frozenDu = false 596 prg.sevenBitSafeFlag = false 597 598 prg.headerPtr = byte(18 * 4) 599 prg.nl = 0 600 prg.minNl = 0 601 prg.nk = 0 602 prg.ne = 0 603 prg.np = 0 604 605 prg.checkSumSpecified = false 606 prg.bchar = 256 607 608 prg.vfPtr = 0 609 prg.vtitleStart = 0 610 prg.vtitleLength = 0 611 prg.fontPtr = 0 612 for ii := int32(0); ii <= 255; ii++ { 613 k = ii 614 _ = k 615 prg.packetStart[k] = uint16(vfSize) 616 } 617 for ii := int32(0); ii <= 127; ii++ { 618 k = ii 619 _ = k 620 prg.packetLength[k] = 1 621 } 622 for ii := int32(128); ii <= 255; ii++ { 623 k = ii 624 _ = k 625 prg.packetLength[k] = 2 626 } 627 628 prg.charRemainder[256] = 077777 629 for ii := int32(0); ii <= 255; ii++ { 630 c = byte(ii) 631 _ = c 632 prg.charWd[c] = 0 633 prg.charHt[c] = 0 634 prg.charDp[c] = 0 635 prg.charIc[c] = 0 636 637 prg.charTag[c] = byte(noTag) 638 prg.charRemainder[c] = 0 639 } 640 prg.memory[0] = 017777777777 // an ``infinite'' element at the end of the lists 641 prg.memory[width] = 0 642 prg.link[width] = 0 // width list is empty 643 prg.memory[height] = 0 644 prg.link[height] = 0 // height list is empty 645 prg.memory[depth] = 0 646 prg.link[depth] = 0 // depth list is empty 647 prg.memory[italic] = 0 648 prg.link[italic] = 0 // italic list is empty 649 prg.memPtr = uint16(italic) 650 651 prg.hashPtr = 0 652 prg.yLigCycle = 256 653 for ii := int32(0); ii <= hashSize; ii++ { 654 k = ii 655 _ = k 656 prg.hash[k] = 0 657 } 658 659 } 660 661 // 4. 662 663 // tangle:pos vptovf.web:101:40: 664 665 // Here are some macros for common programming idioms. 666 667 // 7. 668 669 // tangle:pos vptovf.web:133:17: 670 671 // A \.[VPL] file is like a \.[PL] file with a few extra features, so we 672 // can begin to define it by reviewing the definition of \.[PL] files. The 673 // material in the next few sections is copied from the program \.[PLtoTF]. 674 // 675 // A \.[PL] file is a list of entries of the form 676 // $$\.[(PROPERTYNAME VALUE)]$$ 677 // where the property name is one of a finite set of names understood by 678 // this program, and the value may itself in turn be a property list. 679 // The idea is best understood by looking at an example, so let's consider 680 // a fragment of the \.[PL] file for a hypothetical font. 681 // $$\vbox[\halign[\.[#]\hfil\cr 682 // (FAMILY NOVA)\cr 683 // (FACE F MIE)\cr 684 // (CODINGSCHEME ASCII)\cr 685 // (DESIGNSIZE D 10)\cr 686 // (DESIGNUNITS D 18)\cr 687 // (COMMENT A COMMENT IS IGNORED)\cr 688 // (COMMENT (EXCEPT THIS ONE ISN'T))\cr 689 // (COMMENT (ACTUALLY IT IS, EVEN THOUGH\cr 690 // \qquad\qquad IT SAYS IT ISN'T))\cr 691 // (FONTDIMEN\cr 692 // \qquad (SLANT R -.25)\cr 693 // \qquad (SPACE D 6)\cr 694 // \qquad (SHRINK D 2)\cr 695 // \qquad (STRETCH D 3)\cr 696 // \qquad (XHEIGHT R 10.55)\cr 697 // \qquad (QUAD D 18)\cr 698 // \qquad )\cr 699 // (LIGTABLE\cr 700 // \qquad (LABEL C f)\cr 701 // \qquad (LIG C f O 200)\cr 702 // \qquad (SKIP D 1)\cr 703 // \qquad (LABEL O 200)\cr 704 // \qquad (LIG C i O 201)\cr 705 // \qquad (KRN O 51 R 1.5)\cr 706 // \qquad (/LIG C ? C f)\cr 707 // \qquad (STOP)\cr 708 // \qquad )\cr 709 // (CHARACTER C f\cr 710 // \qquad (CHARWD D 6)\cr 711 // \qquad (CHARHT R 13.5)\cr 712 // \qquad (CHARIC R 1.5)\cr 713 // \qquad )\cr]]$$ 714 // This example says that the font whose metric information is being described 715 // belongs to the hypothetical 716 // \.[NOVA] family; its face code is medium italic extended; 717 // and the characters appear in ASCII code positions. The design size is 10 points, 718 // and all other sizes in this \.[PL] file are given in units such that 18 units 719 // equals the design size. The font is slanted with a slope of $-.25$ (hence the 720 // letters actually slant backward---perhaps that is why the family name is 721 // \.[NOVA]). The normal space between words is 6 units (i.e., one third of 722 // the 18-unit design size), with glue that shrinks by 2 units or stretches by 3. 723 // The letters for which accents don't need to be raised or lowered are 10.55 724 // units high, and one em equals 18 units. 725 // 726 // The example ligature table is a bit trickier. It specifies that the 727 // letter \.f followed by another \.f is changed to code @'200, while 728 // code @'200 followed by \.i is changed to @'201; presumably codes @'200 729 // and @'201 represent the ligatures `ff' and `ffi'. Moreover, in both cases 730 // \.f and @'200, if the following character is the code @'51 (which is a 731 // right parenthesis), an additional 1.5 units of space should be inserted 732 // before the @'51. (The `\.[SKIP]~\.D~\.1' skips over one \.[LIG] or 733 // \.[KRN] command, which in this case is the second \.[LIG]; in this way 734 // two different ligature/kern programs can come together.) 735 // Finally, if either \.f or @'200 is followed by a question mark, 736 // the question mark is replaced by \.f and the ligature program is 737 // started over. (Thus, the character pair `\.[f?]' would actually become 738 // the ligature `ff', and `\.[ff?]' or `\.[f?f]' would become `fff'. To 739 // avoid this restart procedure, the \.[/LIG] command could be replaced 740 // by \.[/LIG>]; then `\.[f?]' would become `f\kern0ptf' and `\.[f?f]' 741 // would become `f\kern0ptff'.) 742 // 743 // Character \.f itself is 6 units wide and 13.5 units tall, in this example. 744 // Its depth is zero (since \.[CHARDP] is not given), and its italic correction 745 // is 1.5 units. 746 747 // 8. 748 749 // tangle:pos vptovf.web:209:14: 750 751 // The example above illustrates most of the features found in \.[PL] files. 752 // Note that some property names, like \.[FAMILY] or \.[COMMENT], take a 753 // string as their value; this string continues until the first unmatched 754 // right parenthesis. But most property names, like \.[DESIGNSIZE] and \.[SLANT] 755 // and \.[LABEL], take a number as their value. This number can be expressed in 756 // a variety of ways, indicated by a prefixed code; \.D stands for decimal, 757 // \.H for hexadecimal, \.O for octal, \.R for real, \.C for character, and 758 // \.F for ``face.'' Other property names, like \.[LIG], take two numbers as 759 // their value. And still other names, like \.[FONTDIMEN] and \.[LIGTABLE] and 760 // \.[CHARACTER], have more complicated values that involve property lists. 761 // 762 // A property name is supposed to be used only in an appropriate property 763 // list. For example, \.[CHARWD] shouldn't occur on the outer level or 764 // within \.[FONTDIMEN]. 765 // 766 // The individual property-and-value pairs in a property list can appear in 767 // any order. For instance, `\.[SHRINK]' precedes `\.[STRETCH]' in the example 768 // above, although the \.[TFM] file always puts the stretch parameter first. 769 // One could even give the information about characters like `\.f' before 770 // specifying the number of units in the design size, or before specifying the 771 // ligature and kerning table. However, the \.[LIGTABLE] itself is an exception 772 // to this rule; the individual elements of the \.[LIGTABLE] property list 773 // can be reordered only to a certain extent without changing the meaning 774 // of that table. 775 // 776 // If property-and-value pairs are omitted, a default value is used. For example, 777 // we have already noted that the default for \.[CHARDP] is zero. The default 778 // for [\sl every\/] numeric value is, in fact, zero, unless otherwise stated 779 // below. 780 // 781 // If the same property name is used more than once, \.[VPtoVF] will not notice 782 // the discrepancy; it simply uses the final value given. Once again, however, the 783 // \.[LIGTABLE] is an exception to this rule; \.[VPtoVF] will complain if there 784 // is more than one label for some character. And of course many of the 785 // entries in the \.[LIGTABLE] property list have the same property name. 786 787 // 9. 788 789 // tangle:pos vptovf.web:245:71: 790 791 // A \.[VPL] file also includes information about how to create each character, 792 // by typesetting characters from other fonts and/or by drawing lines, etc. 793 // Such information is the value of the `\.[MAP]' property, which can be 794 // illustrated as follows: 795 // $$\vbox[\halign[\.[#]\hfil\cr 796 // (MAPFONT D 0 (FONTNAME Times-Roman))\cr 797 // (MAPFONT D 1 (FONTNAME Symbol))\cr 798 // (MAPFONT D 2 (FONTNAME cmr10)(FONTAT D 20))\cr 799 // (CHARACTER O 0 (MAP (SELECTFONT D 1)(SETCHAR C G)))\cr 800 // (CHARACTER O 76 (MAP (SETCHAR O 277)))\cr 801 // (CHARACTER D 197 (MAP\cr 802 // \qquad(PUSH)(SETCHAR C A)(POP)\cr 803 // \qquad(MOVEUP R 0.937)(MOVERIGHT R 1.5)(SETCHAR O 312)))\cr 804 // (CHARACTER O 200 (MAP (MOVEDOWN R 2.1)(SETRULE R 1 R 8)))\cr 805 // (CHARACTER O 201 (MAP\cr 806 // \qquad (SPECIAL ps: /SaveGray currentgray def .5 setgray)\cr 807 // \qquad (SELECTFONT D 2)(SETCHAR C A)\cr 808 // \qquad (SPECIAL ps: SaveGray setgray)))\cr 809 // ]]$$ 810 // (These specifications appear in addition to the conventional \.[PL] 811 // information. The \.[MAP] attribute can be mixed in with other attributes 812 // like \.[CHARWD] or it can be given separately.) 813 // 814 // In this example, the virtual font is composed of characters that can be 815 // fabricated from three actual fonts, `\.[Times-Roman]', 816 // `\.[Symbol]', and `\.[cmr10] \.[at] \.[20\\u]' (where \.[\\u] 817 // is the unit size in this \.[VPL] file). Character |@'0| is typeset as 818 // a `G' from the symbol font. Character |@'76| is typeset as character |@'277| 819 // from the ordinary Times font. (If no other font is selected, font 820 // number~0 is the default. If no \.[MAP] attribute is given, the default map 821 // is a character of the same number in the default font.) 822 // 823 // Character 197 (decimal) is more interesting: First an A is typeset (in the 824 // default font Times), and this is enclosed by \.[PUSH] and \.[POP] so that 825 // the original position is restored. Then the accent character |@'312| is 826 // typeset, after moving up .937 units and right 1.5 units. 827 // 828 // To typeset character |@'200| in this virtual font, we move down 2.1 units, 829 // then typeset a rule that is 1 unit high and 8 units wide. 830 // 831 // Finally, to typeset character |@'201|, we do something that requires a 832 // special ability to interpret PostScript commands; this example 833 // sets the PostScript ``color'' to 50\char`\%\ gray and typesets an `A' 834 // from \.[cmr10] \.[at] \.[20\\u] in that color. 835 // 836 // In general, the \.[MAP] attribute of a virtual character can be any sequence 837 // of typesetting commands that might appear in a page of a \.[DVI] file. 838 // A single character might map into an entire page. 839 840 // 10. 841 842 // tangle:pos vptovf.web:294:50: 843 844 // But instead of relying on a hypothetical example, let's consider a complete 845 // grammar for \.[VPL] files, beginning with the (unchanged) grammatical rules 846 // for \.[PL] files. At the outer level, the following property names 847 // are valid in any \.[PL] file: 848 // 849 // \yskip\hang\.[CHECKSUM] (four-byte value). The value, which should be a 850 // nonnegative integer less than $2^[32]$, is used to identify a particular 851 // version of a font; it should match the check sum value stored with the font 852 // itself. An explicit check sum of zero is used to bypass 853 // check sum testing. If no checksum is specified in the \.[VPL] file, 854 // \.[VPtoVF] will compute the checksum that \MF\ would compute from the 855 // same data. 856 // 857 // \yskip\hang\.[DESIGNSIZE] (numeric value, default is 10). The value, which 858 // should be a real number in the range |1.0<=x<2048|, represents the default 859 // amount by which all quantities will be scaled if the font is not loaded 860 // with an `\.[at]' specification. For example, if one says 861 // `\.[\\font\\A=cmr10 at 15pt]' in \TeX\ language, the design size in the \.[TFM] 862 // file is ignored and effectively replaced by 15 points; but if one simply 863 // says `\.[\\font\\A=cmr10]' the stated design size is used. This quantity is 864 // always in units of printer's points. 865 // 866 // \yskip\hang\.[DESIGNUNITS] (numeric value, default is 1). The value 867 // should be a positive real number; it says how many units equals the design 868 // size (or the eventual `\.[at]' size, if the font is being scaled). For 869 // example, suppose you have a font that has been digitized with 600 pixels per 870 // em, and the design size is one em; then you could say `\.[(DESIGNUNITS R 600)]' 871 // if you wanted to give all of your measurements in units of pixels. 872 // 873 // \yskip\hang\.[CODINGSCHEME] (string value, default is `\.[UNSPECIFIED]'). 874 // The string should not contain parentheses, and its length must be less than 40. 875 // It identifies the correspondence between the numeric codes and font characters. 876 // (\TeX\ ignores this information, but other software programs make use of it.) 877 // 878 // \yskip\hang\.[FAMILY] (string value, default is `\.[UNSPECIFIED]'). 879 // The string should not contain parentheses, and its length must be less than 20. 880 // It identifies the name of the family to which this font belongs, e.g., 881 // `\.[HELVETICA]'. (\TeX\ ignores this information; but it is needed, for 882 // example, when converting \.[DVI] files to \.[PRESS] files for Xerox 883 // equipment.) 884 // 885 // \yskip\hang\.[FACE] (one-byte value). This number, which must lie between 886 // 0 and 255 inclusive, is a subsidiary ident\-ifi\-ca\-tion of the font within its 887 // family. For example, bold italic condensed fonts might have the same family name 888 // as light roman extended fonts, differing only in their face byte. (\TeX\ 889 // ignores this information; but it is needed, for example, when converting 890 // \.[DVI] files to \.[PRESS] files for Xerox equipment.) 891 // 892 // \yskip\hang\.[SEVENBITSAFEFLAG] (string value, default is `\.[FALSE]'). The 893 // value should start with either `\.T' (true) or `\.F' (false). If true, character 894 // codes less than 128 cannot lead to codes of 128 or more via ligatures or 895 // charlists or extensible characters. (\TeX82 ignores this flag, but older 896 // versions of \TeX\ would only accept \.[TFM] files that were seven-bit safe.) 897 // \.[VPtoVF] computes the correct value of this flag and gives an error message 898 // only if a claimed ``true'' value is incorrect. 899 // 900 // \yskip\hang\.[HEADER] (a one-byte value followed by a four-byte value). 901 // The one-byte value should be between 18 and a maximum limit that can be 902 // raised or lowered depending on the compile-time setting of |max_header_bytes|. 903 // The four-byte value goes into the header word whose index is the one-byte 904 // value; for example, to set |header[18]:=1|, one may write 905 // `\.[(HEADER D 18 O 1)]'. This notation is used for header information that 906 // is presently unnamed. (\TeX\ ignores it.) 907 // 908 // \yskip\hang\.[FONTDIMEN] (property list value). See below for the names 909 // allowed in this property list. 910 // 911 // \yskip\hang\.[LIGTABLE] (property list value). See below for the rules 912 // about this special kind of property list. 913 // 914 // \yskip\hang\.[BOUNDARYCHAR] (one-byte value). If this character appears in 915 // a \.[LIGTABLE] command, it matches ``end of word'' as well as itself. 916 // If no boundary character is given and no \.[LABEL] \.[BOUNDARYCHAR] occurs 917 // within \.[LIGTABLE], word boundaries will not affect ligatures or kerning. 918 // 919 // \yskip\hang\.[CHARACTER]. The value is a one-byte integer followed by 920 // a property list. The integer represents the number of a character that is 921 // present in the font; the property list of a character is defined below. 922 // The default is an empty property list. 923 924 // 11. 925 926 // tangle:pos vptovf.web:374:39: 927 928 // Numeric property list values can be given in various forms identified by 929 // a prefixed letter. 930 // 931 // \yskip\hang\.C denotes an ASCII character, which should be a standard visible 932 // character that is not a parenthesis. The numeric value will therefore be 933 // between @'41 and @'176 but not @'50 or @'51. 934 // 935 // \yskip\hang\.D denotes an unsigned decimal integer, which must be 936 // less than $2^[32]$, i.e., at most `\.[D 4294967295]'. 937 // 938 // \yskip\hang\.F denotes a three-letter Xerox face code; the admissible codes 939 // are \.[MRR], \.[MIR], \.[BRR], \.[BIR], \.[LRR], \.[LIR], \.[MRC], \.[MIC], 940 // \.[BRC], \.[BIC], \.[LRC], \.[LIC], \.[MRE], \.[MIE], \.[BRE], \.[BIE], 941 // \.[LRE], and \.[LIE], denoting the integers 0 to 17, respectively. 942 // 943 // \yskip\hang\.O denotes an unsigned octal integer, which must be less than 944 // $2^[32]$, i.e., at most `\.[O 37777777777]'. 945 // 946 // \yskip\hang\.H denotes an unsigned hexadecimal integer, which must be less than 947 // $2^[32]$, i.e., at most `\.[H FFFFFFFF]'. 948 // 949 // \yskip\hang\.R denotes a real number in decimal notation, optionally preceded 950 // by a `\.+' or `\.-' sign, and optionally including a decimal point. The 951 // absolute value must be less than 2048. 952 953 // 12. 954 955 // tangle:pos vptovf.web:399:39: 956 957 // The property names allowed in a \.[FONTDIMEN] property list correspond to 958 // various \TeX\ parameters, each of which has a (real) numeric value. All 959 // of the parameters except \.[SLANT] are in design units. The admissible 960 // names are \.[SLANT], \.[SPACE], \.[STRETCH], \.[SHRINK], \.[XHEIGHT], 961 // \.[QUAD], \.[EXTRASPACE], \.[NUM1], \.[NUM2], \.[NUM3], \.[DENOM1], 962 // \.[DENOM2], \.[SUP1], \.[SUP2], \.[SUP3], \.[SUB1], \.[SUB2], \.[SUPDROP], 963 // \.[SUBDROP], \.[DELIM1], \.[DELIM2], and \.[AXISHEIGHT], for parameters 964 // 1~to~22. The alternate names \.[DEFAULTRULETHICKNESS], 965 // \.[BIGOPSPACING1], \.[BIGOPSPACING2], \.[BIGOPSPACING3], 966 // \.[BIGOPSPACING4], and \.[BIGOPSPACING5], may also be used for parameters 967 // 8 to 13. 968 // 969 // The notation `\.[PARAMETER] $n$' provides another way to specify the 970 // $n$th parameter; for example, `\.[(PARAMETER] \.[D 1 R -.25)]' is another way 971 // to specify that the \.[SLANT] is $-0.25$. The value of $n$ must be positive 972 // and less than |max_param_words|. 973 974 // 13. 975 976 // tangle:pos vptovf.web:416:33: 977 978 // The elements of a \.[CHARACTER] property list can be of six different types. 979 // 980 // \yskip\hang\.[CHARWD] (real value) denotes the character's width in 981 // design units. 982 // 983 // \yskip\hang\.[CHARHT] (real value) denotes the character's height in 984 // design units. 985 // 986 // \yskip\hang\.[CHARDP] (real value) denotes the character's depth in 987 // design units. 988 // 989 // \yskip\hang\.[CHARIC] (real value) denotes the character's italic correction in 990 // design units. 991 // 992 // \yskip\hang\.[NEXTLARGER] (one-byte value), specifies the character that 993 // follows the present one in a ``charlist.'' The value must be the number of a 994 // character in the font, and there must be no infinite cycles of supposedly 995 // larger and larger characters. 996 // 997 // \yskip\hang\.[VARCHAR] (property list value), specifies an extensible character. 998 // This option and \.[NEXTLARGER] are mutually exclusive; i.e., they cannot 999 // both be used within the same \.[CHARACTER] list. 1000 // 1001 // \yskip\noindent 1002 // The elements of a \.[VARCHAR] property list are either \.[TOP], \.[MID], 1003 // \.[BOT], or \.[REP]; the values are integers, which must be zero or the number 1004 // of a character in the font. A zero value for \.[TOP], \.[MID], or \.[BOT] means 1005 // that the corresponding piece of the extensible character is absent. A nonzero 1006 // value, or a \.[REP] value of zero, denotes the character code used to make 1007 // up the top, middle, bottom, or replicated piece of an extensible character. 1008 1009 // 14. 1010 1011 // tangle:pos vptovf.web:447:76: 1012 1013 // A \.[LIGTABLE] property list contains elements of four kinds, specifying a 1014 // program in a simple command language that \TeX\ uses for ligatures and kerns. 1015 // If several \.[LIGTABLE] lists appear, they are effectively concatenated into 1016 // a single list. 1017 // 1018 // \yskip\hang\.[LABEL] (one-byte value) means that the program for the 1019 // stated character value starts here. The integer must be the number of a 1020 // character in the font; its \.[CHARACTER] property list must not have a 1021 // \.[NEXTLARGER] or \.[VARCHAR] field. At least one \.[LIG] or \.[KRN] step 1022 // must follow. 1023 // 1024 // \yskip\hang\.[LABEL] \.[BOUNDARYCHAR] means that the program for 1025 // beginning-of-word ligatures starts here. 1026 // 1027 // \yskip\hang\.[LIG] (two one-byte values). The instruction `\.[(LIG] $c$ $r$\.)' 1028 // means, ``If the next character is $c$, then insert character~$r$ and 1029 // possibly delete the current character and/or~$c$; 1030 // otherwise go on to the next instruction.'' 1031 // Characters $r$ and $c$ must be present in the font. \.[LIG] may be immediately 1032 // preceded or followed by a slash, and then immediately followed by \.> 1033 // characters not exceeding the number of slashes. Thus there are eight 1034 // possible forms: 1035 // $$\hbox to .8\hsize[\.[LIG]\hfil\.[/LIG]\hfil\.[/LIG>]\hfil 1036 // \.[LIG/]\hfil\.[LIG/>]\hfil\.[/LIG/]\hfil\.[/LIG/>]\hfil\.[/LIG/>>]]$$ 1037 // The slashes specify retention of the left or right original character; the 1038 // \.> signs specify passing over the result without further ligature processing. 1039 // 1040 // \yskip\hang\.[KRN] (a one-byte value and a real value). The instruction 1041 // `\.[(KRN] $c$ $r$\.)' means, ``If the next character is $c$, then insert 1042 // a blank space of width $r$ between the current character and $c$; 1043 // otherwise go on to the next instruction.'' The value of $r$, which is in 1044 // design units, is often negative. Character code $c$ must exist 1045 // in the font. 1046 // 1047 // \yskip\hang\.[STOP] (no value). This instruction ends a ligature/kern program. 1048 // It must follow either a \.[LIG] or \.[KRN] instruction, not a \.[LABEL] 1049 // or \.[STOP] or \.[SKIP]. 1050 // 1051 // \yskip\hang\.[SKIP] (value in the range |0..127|). This instruction specifies 1052 // continuation of a ligature/kern program after the specified number of \.[LIG] 1053 // or \.[KRN] steps has been skipped over. The number of subsequent \.[LIG] and 1054 // \.[KRN] instructions must therefore exceed this specified amount. 1055 1056 // 15. 1057 1058 // tangle:pos vptovf.web:490:66: 1059 1060 // In addition to all these possibilities, the property name \.[COMMENT] is 1061 // allowed in any property list. Such comments are ignored. 1062 1063 // 16. 1064 1065 // tangle:pos vptovf.web:493:57: 1066 1067 // So that is what \.[PL] files hold. In a \.[VPL] file additional 1068 // properties are recognized; two of these are valid on the outermost level: 1069 // 1070 // \yskip\hang\.[VTITLE] (string value, default is empty). The value will be 1071 // reproduced at the beginning of the \.[VF] file (and printed on the terminal 1072 // by \.[VFtoVP] when it examines that file). 1073 // 1074 // \yskip\hang\.[MAPFONT]. The value is a nonnegative integer followed by 1075 // a property list. The integer represents an identifying number for fonts 1076 // used in \.[MAP] attributes. The property list, which identifies the font and 1077 // relative size, is defined below. 1078 // 1079 // \yskip\noindent 1080 // And one additional ``virtual property'' is valid within a \.[CHARACTER]: 1081 // 1082 // \yskip\hang\.[MAP]. The value is a property list consisting of typesetting 1083 // commands. Default is the single command \.[SETCHAR]~$c$, where $c$ is 1084 // the current character number. 1085 1086 // 17. 1087 1088 // tangle:pos vptovf.web:512:30: 1089 1090 // The elements of a \.[MAPFONT] property list can be of the following types. 1091 // 1092 // \yskip\hang\.[FONTNAME] (string value, default is \.[NULL]). 1093 // This is the font's identifying name. 1094 // 1095 // \yskip\hang\.[FONTAREA] (string value, default is empty). If the font appears 1096 // in a nonstandard directory, according to local conventions, the directory 1097 // name is given here. (This is system dependent, just as in \.[DVI] files.) 1098 // 1099 // \yskip\hang\.[FONTCHECKSUM] (four-byte value, default is zero). This value, 1100 // which should be a nonnegative integer less than $2^[32]$, can be used to 1101 // check that the font being referred to matches the intended font. If nonzero, 1102 // it should equal the \.[CHECKSUM] parameter in that font. 1103 // 1104 // \yskip\hang\.[FONTAT] (numeric value, default is the \.[DESIGNUNITS] of the 1105 // present virtual font). This value is relative to the design units of 1106 // the present virtual font, hence it will be scaled when the virtual 1107 // font is magnified or reduced. It represents the value that will 1108 // effectively replace the design size of the font being referred to, 1109 // so that all characters will be scaled appropriately. 1110 // 1111 // \yskip\hang\.[FONTDSIZE] (numeric value, default is 10). This value is 1112 // absolute, in units of printer's points. It should equal the \.[DESIGNSIZE] 1113 // parameter in the font being referred to. 1114 // 1115 // \yskip\noindent 1116 // If any of the 1117 // string values contain parentheses, the parentheses must be balanced. Leading 1118 // blanks are removed from the strings, but trailing blanks are not. 1119 1120 // 18. 1121 1122 // tangle:pos vptovf.web:542:66: 1123 1124 // Finally, the elements of a \.[MAP] property list are an ordered sequence 1125 // of typesetting commands chosen from among the following: 1126 // 1127 // \yskip\hang\.[SELECTFONT] (four-byte integer value). The value must be the 1128 // number of a previously defined \.[MAPFONT]. This font (or more precisely, the 1129 // final font that is mapped to that code number, if two \.[MAPFONT] properties 1130 // happen to specify the same code) will be used in subsequent \.[SETCHAR] 1131 // instructions until overridden by another \.[SELECTFONT]. The first-specified 1132 // \.[MAPFONT] is implicitly selected before the first \.[SELECTFONT] in every 1133 // character's map. 1134 // 1135 // \yskip\hang\.[SETCHAR] (one-byte integer value). There must be a character of 1136 // this number in the currently selected font. (\.[VPtoVF] doesn't check that 1137 // the character is valid, but \.[VFtoVP] does.) That character is typeset at the 1138 // current position, and the typesetter moves right by the \.[CHARWD] in 1139 // that character's \.[TFM] file. 1140 // 1141 // \yskip\hang\.[SETRULE] (two real values). The first value specifies height, 1142 // the second specifies width, in design units. If both height and width are 1143 // positive, a rule is typeset at the current position. Then the typesetter 1144 // moves right, by the specified width. 1145 // 1146 // \yskip\hang\.[MOVERIGHT], \.[MOVELEFT], \.[MOVEUP], \.[MOVEDOWN] (real 1147 // value). The typesetter moves its current position 1148 // by the number of design units specified. 1149 // 1150 // \yskip\hang\.[PUSH]. The current typesetter position is remembered, to 1151 // be restored on a subsequent \.[POP]. 1152 // 1153 // \yskip\hang\.[POP]. The current typesetter position is reset to where it 1154 // was on the most recent unmatched \.[PUSH]. The \.[PUSH] and \.[POP] 1155 // commands in any \.[MAP] must be properly nested like balanced parentheses. 1156 // 1157 // \yskip\hang\.[SPECIAL] (string value). The subsequent characters, starting 1158 // with the first nonblank and ending just before the first `\.)' that has no 1159 // matching `\.(', are interpreted according to local conventions with the 1160 // same system-dependent meaning as a `special' (\\[xxx]) command 1161 // in a \.[DVI] file. 1162 // 1163 // \yskip\hang\.[SPECIALHEX] (hexadecimal string value). The subsequent 1164 // nonblank characters before the next `\.)' must consist entirely of 1165 // hexadecimal digits, and they must contain an even number of such digits. 1166 // Each pair of hex digits specifies a byte, and this string of bytes is 1167 // treated just as the value of a \.[SPECIAL]. (This convention permits 1168 // arbitrary byte strings to be represented in an ordinary text file.) 1169 1170 // 19. 1171 1172 // tangle:pos vptovf.web:588:68: 1173 1174 // Virtual font mapping is a recursive process, like macro expansion. 1175 // Thus, a \.[MAPFONT] might 1176 // specify another virtual font, whose characters are themselves mapped to 1177 // other fonts. As an example of this possibility, consider the 1178 // following curious file called \.[recurse.vpl], which defines a 1179 // virtual font that is self-contained and self-referential: 1180 // $$\vbox[\halign[\.[#]\cr 1181 // (VTITLE Example of recursion)\cr 1182 // (MAPFONT D 0 (FONTNAME recurse)(FONTAT D 2))\cr 1183 // (CHARACTER C A (CHARWD D 1)(CHARHT D 1)(MAP (SETRULE D 1 D 1)))\cr 1184 // (CHARACTER C B (CHARWD D 2)(CHARHT D 2)(MAP (SETCHAR C A)))\cr 1185 // (CHARACTER C C (CHARWD D 4)(CHARHT D 4)(MAP (SETCHAR C B)))\cr 1186 // ]]$$ 1187 // The design size is 10 points (the default), hence the character \.A 1188 // in font \.[recurse] is a $10\times10$ point black square. Character \.B 1189 // is typeset as character \.A in \.[recurse] [scaled] [2000], hence it 1190 // is a $20\times20$ point black square. And character \.C is typeset as 1191 // character \.[B] in \.[recurse] [scaled] [2000], hence its size is 1192 // $40\times40$. 1193 // 1194 // Users are responsible for making sure that infinite recursion doesn't happen. 1195 1196 // 20. 1197 1198 // tangle:pos vptovf.web:610:78: 1199 1200 // So that is what \.[VPL] files hold. From these rules, 1201 // you can guess (correctly) that \.[VPtoVF] operates in four main stages. 1202 // First it assigns the default values to all properties; then it scans 1203 // through the \.[VPL] file, changing property values as new ones are seen; then 1204 // it checks the information and corrects any problems; and finally it outputs 1205 // the \.[VF] and \.[TFM] files. 1206 1207 // 33. 1208 1209 // tangle:pos vptovf.web:742:18: 1210 1211 // The following routine prints an error message and an indication of 1212 // where the error was detected. The error message should not include any 1213 // final punctuation, since this procedure supplies its own. 1214 func (prg *prg) showErrorContext() { // prints the current scanner location 1215 var ( 1216 k /* 0..bufSize */ byte // an index into |buffer| 1217 ) 1218 prg.stdout.Writeln(" (line ", prg.line, knuth.WriteWidth(1), ").") 1219 if !prg.leftLn { 1220 prg.stdout.Write("...") 1221 } 1222 for ii := int32(1); ii <= int32(prg.loc); ii++ { 1223 k = byte(ii) 1224 _ = k 1225 prg.stdout.Write(string(rune(prg.buffer[k-1]))) 1226 } // print the characters already scanned 1227 prg.stdout.Writeln(" ") 1228 if !prg.leftLn { 1229 prg.stdout.Write(" ") 1230 } 1231 for ii := int32(1); ii <= int32(prg.loc); ii++ { 1232 k = byte(ii) 1233 _ = k 1234 prg.stdout.Write(" ") 1235 } // space out the second line 1236 for ii := int32(prg.loc) + 1; ii <= int32(prg.limit); ii++ { 1237 k = byte(ii) 1238 _ = k 1239 prg.stdout.Write(string(rune(prg.buffer[k-1]))) 1240 } // print the characters yet unseen 1241 if prg.rightLn { 1242 prg.stdout.Writeln(" ") 1243 } else { 1244 prg.stdout.Writeln("...") 1245 } 1246 prg.charsOnLine = 0 1247 } 1248 1249 // 34. 1250 1251 // tangle:pos vptovf.web:763:5: 1252 1253 // Here is a procedure that does the right thing when we are done 1254 // reading the present contents of the buffer. It keeps |buffer[buf_size]| 1255 // empty, in order to avoid range errors on certain \PASCAL\ compilers. 1256 // 1257 // An infinite sequence of right parentheses is placed at the end of the 1258 // file, so that the program is sure to get out of whatever level of nesting 1259 // it is in. 1260 // 1261 // On some systems it is desirable to modify this code so that tab marks 1262 // in the buffer are replaced by blank spaces. (Simply setting 1263 // |xord[chr(@'11)]:=" "| would not work; for example, two-line 1264 // error messages would not come out properly aligned.) 1265 // \xref[system dependencies] 1266 func (prg *prg) fillBuffer() { 1267 prg.leftLn = prg.rightLn 1268 prg.limit = 0 1269 prg.loc = 0 1270 if prg.leftLn { 1271 if prg.line > 0 { 1272 prg.vplFile.Readln() 1273 } 1274 prg.line = prg.line + 1 1275 } 1276 if prg.vplFile.EOF() { 1277 prg.limit = 1 1278 prg.buffer[1-1] = ')' 1279 prg.rightLn = false 1280 prg.inputHasEnded = true 1281 } else { 1282 for int32(prg.limit) < bufSize-2 && !prg.vplFile.EOLN() { 1283 prg.limit = byte(int32(prg.limit) + 1) 1284 prg.vplFile.Read(&prg.buffer[prg.limit-1]) 1285 } 1286 prg.buffer[int32(prg.limit)+1-1] = ' ' 1287 prg.rightLn = prg.vplFile.EOLN() 1288 if prg.rightLn { 1289 prg.limit = byte(int32(prg.limit) + 1) 1290 prg.buffer[int32(prg.limit)+1-1] = ' ' 1291 } 1292 if prg.leftLn { 1293 for int32(prg.loc) < int32(prg.limit) && int32(prg.buffer[int32(prg.loc)+1-1]) == ' ' { 1294 prg.loc = byte(int32(prg.loc) + 1) 1295 } 1296 if int32(prg.loc) < int32(prg.limit) { 1297 if prg.level == 0 { 1298 if int32(prg.loc) == 0 { 1299 prg.goodIndent = prg.goodIndent + 1 1300 } else { 1301 if prg.goodIndent >= 10 { 1302 if int32(prg.charsOnLine) > 0 { 1303 prg.stdout.Writeln(" ") 1304 } 1305 prg.stdout.Write("Warning: Indented line occurred at level zero") 1306 prg.showErrorContext() 1307 } 1308 prg.goodIndent = 0 1309 prg.indent = 0 1310 } 1311 } else if prg.indent == 0 { 1312 if int32(prg.loc)%prg.level == 0 { 1313 prg.indent = int32(prg.loc) / prg.level 1314 prg.goodIndent = 1 1315 } else { 1316 prg.goodIndent = 0 1317 } 1318 } else if prg.indent*prg.level == int32(prg.loc) { 1319 prg.goodIndent = prg.goodIndent + 1 1320 } else { 1321 if prg.goodIndent >= 10 { 1322 if int32(prg.charsOnLine) > 0 { 1323 prg.stdout.Writeln(" ") 1324 } 1325 prg.stdout.Write("Warning: Inconsistent indentation; ", 1326 // \xref[Warning: Inconsistent indentation...] 1327 "you are at parenthesis level ", prg.level, knuth.WriteWidth(1)) 1328 prg.showErrorContext() 1329 } 1330 prg.goodIndent = 0 1331 prg.indent = 0 1332 } 1333 } 1334 } 1335 } 1336 } 1337 1338 // 37. 1339 1340 // tangle:pos vptovf.web:831:48: 1341 1342 // Here is a procedure that sets |cur_char| to an ASCII code for the 1343 // next character of input, if that character is a letter or digit or slash 1344 // or \.>. Otherwise 1345 // it sets |cur_char:=" "|, and the input system will be poised to reread the 1346 // character that was rejected, whether or not it was a space. 1347 // Lower case letters are converted to upper case. 1348 func (prg *prg) getKeywordChar() { 1349 for int32(prg.loc) == int32(prg.limit) && !prg.rightLn { 1350 prg.fillBuffer() 1351 } 1352 if int32(prg.loc) == int32(prg.limit) { 1353 prg.curChar = ' ' 1354 } else { 1355 prg.curChar = prg.xord[prg.buffer[int32(prg.loc)+1-1]] 1356 if int32(prg.curChar) >= 'a' { 1357 prg.curChar = byte(int32(prg.curChar) - 040) 1358 } 1359 if int32(prg.curChar) >= '0' && int32(prg.curChar) <= '9' { 1360 prg.loc = byte(int32(prg.loc) + 1) 1361 } else if int32(prg.curChar) >= 'A' && int32(prg.curChar) <= 'Z' { 1362 prg.loc = byte(int32(prg.loc) + 1) 1363 } else if int32(prg.curChar) == '/' { 1364 prg.loc = byte(int32(prg.loc) + 1) 1365 } else if int32(prg.curChar) == '>' { 1366 prg.loc = byte(int32(prg.loc) + 1) 1367 } else { 1368 prg.curChar = ' ' 1369 } 1370 } 1371 } 1372 1373 // 38. 1374 1375 // tangle:pos vptovf.web:851:5: 1376 1377 // The following procedure sets |cur_char| to the next character code, 1378 // and converts lower case to upper case. If the character is a left or 1379 // right parenthesis, it will not be ``digested''; the character will 1380 // be read again and again, until the calling routine does something 1381 // like `|incr(loc)|' to get past it. Such special treatment of parentheses 1382 // insures that the structural information they contain won't be lost in 1383 // the midst of other error recovery operations. 1384 func (prg *prg) getNext() { 1385 for int32(prg.loc) == int32(prg.limit) { 1386 prg.fillBuffer() 1387 } 1388 prg.loc = byte(int32(prg.loc) + 1) 1389 prg.curChar = prg.xord[prg.buffer[prg.loc-1]] 1390 if int32(prg.curChar) >= 'a' { 1391 if int32(prg.curChar) <= 'z' { 1392 prg.curChar = byte(int32(prg.curChar) - 040) 1393 } else { 1394 if int32(prg.curChar) == invalidCode { 1395 { 1396 if int32(prg.charsOnLine) > 0 { 1397 prg.stdout.Writeln(" ") 1398 } 1399 prg.stdout.Write("Illegal character in the file") 1400 prg.showErrorContext() 1401 } 1402 // \xref[Illegal character...] 1403 prg.curChar = '?' 1404 } 1405 } 1406 } else if int32(prg.curChar) <= ')' && int32(prg.curChar) >= '(' { 1407 prg.loc = byte(int32(prg.loc) - 1) 1408 } 1409 } 1410 1411 // 39. 1412 1413 // tangle:pos vptovf.web:876:5: 1414 1415 // Here's a procedure that scans a hexadecimal digit or a right parenthesis. 1416 func (prg *prg) getHex() (r byte) { 1417 var ( 1418 a int32 // partial result 1419 ) 1420 for { 1421 prg.getNext() 1422 if int32(prg.curChar) != ' ' { 1423 break 1424 } 1425 } 1426 a = int32(prg.curChar) - ')' 1427 if a > 0 { 1428 a = int32(prg.curChar) - '0' 1429 if int32(prg.curChar) > '9' { 1430 if int32(prg.curChar) < 'A' { 1431 a = -1 1432 } else { 1433 a = int32(prg.curChar) - 'A' + 10 1434 } 1435 } 1436 } 1437 if a < 0 || a > 15 { 1438 { 1439 if int32(prg.charsOnLine) > 0 { 1440 prg.stdout.Writeln(" ") 1441 } 1442 prg.stdout.Write("Illegal hexadecimal digit") 1443 prg.showErrorContext() 1444 } 1445 r = 0 1446 // \xref[Illegal hexadecimal digit] 1447 } else { 1448 r = byte(a) 1449 } 1450 return r 1451 } 1452 1453 // 40. 1454 1455 // tangle:pos vptovf.web:895:5: 1456 1457 // The next procedure is used to ignore the text of a comment, or to pass over 1458 // erroneous material. As such, it has the privilege of passing parentheses. 1459 // It stops after the first right parenthesis that drops the level below 1460 // the level in force when the procedure was called. 1461 func (prg *prg) skipToEndOfItem() { 1462 var ( 1463 l int32 // initial value of |level| 1464 ) 1465 l = prg.level 1466 for prg.level >= l { 1467 for int32(prg.loc) == int32(prg.limit) { 1468 prg.fillBuffer() 1469 } 1470 prg.loc = byte(int32(prg.loc) + 1) 1471 if int32(prg.buffer[prg.loc-1]) == ')' { 1472 prg.level = prg.level - 1 1473 } else if int32(prg.buffer[prg.loc-1]) == '(' { 1474 prg.level = prg.level + 1 1475 } 1476 } 1477 if prg.inputHasEnded { 1478 if int32(prg.charsOnLine) > 0 { 1479 prg.stdout.Writeln(" ") 1480 } 1481 prg.stdout.Write("File ended unexpectedly: No closing \")\"") 1482 prg.showErrorContext() 1483 } 1484 // \xref[File ended unexpectedly...] 1485 prg.curChar = ' ' // now the right parenthesis has been read and digested 1486 } 1487 1488 // 41. 1489 1490 // tangle:pos vptovf.web:914:5: 1491 1492 // A similar procedure copies the bytes remaining in an item. The copied bytes 1493 // go into an array |vf| that we'll declare later. Leading blanks are ignored. 1494 func (prg *prg) copyToEndOfItem() { 1495 var ( 1496 l int32 // initial value of |level| 1497 nonblankFound bool // have we seen a nonblank character yet? 1498 ) 1499 l = prg.level 1500 nonblankFound = false 1501 for true { 1502 for int32(prg.loc) == int32(prg.limit) { 1503 prg.fillBuffer() 1504 } 1505 if int32(prg.buffer[int32(prg.loc)+1-1]) == ')' { 1506 if prg.level == l { 1507 goto _30 1508 } else { 1509 prg.level = prg.level - 1 1510 } 1511 } 1512 prg.loc = byte(int32(prg.loc) + 1) 1513 if int32(prg.buffer[prg.loc-1]) == '(' { 1514 prg.level = prg.level + 1 1515 } 1516 if int32(prg.buffer[prg.loc-1]) != ' ' { 1517 nonblankFound = true 1518 } 1519 if nonblankFound { 1520 if int32(prg.xord[prg.buffer[prg.loc-1]]) == invalidCode { 1521 { 1522 if int32(prg.charsOnLine) > 0 { 1523 prg.stdout.Writeln(" ") 1524 } 1525 prg.stdout.Write("Illegal character in the file") 1526 prg.showErrorContext() 1527 } 1528 // \xref[Illegal character...] 1529 { 1530 prg.vf[prg.vfPtr] = '?' 1531 if int32(prg.vfPtr) == vfSize { 1532 if int32(prg.charsOnLine) > 0 { 1533 prg.stdout.Writeln(" ") 1534 } 1535 prg.stdout.Write("I'm out of memory---increase my vfsize!") 1536 prg.showErrorContext() 1537 } else { 1538 prg.vfPtr = uint16(int32(prg.vfPtr) + 1) 1539 } 1540 } 1541 } else { 1542 prg.vf[prg.vfPtr] = prg.xord[prg.buffer[prg.loc-1]] 1543 if int32(prg.vfPtr) == vfSize { 1544 if int32(prg.charsOnLine) > 0 { 1545 prg.stdout.Writeln(" ") 1546 } 1547 prg.stdout.Write("I'm out of memory---increase my vfsize!") 1548 prg.showErrorContext() 1549 } else { 1550 prg.vfPtr = uint16(int32(prg.vfPtr) + 1) 1551 } 1552 } 1553 } 1554 } 1555 _30: 1556 } 1557 1558 // 42. 1559 1560 // tangle:pos vptovf.web:946:8: 1561 1562 // Sometimes we merely want to skip past characters in the input until we 1563 // reach a left or a right parenthesis. For example, we do this whenever we 1564 // have finished scanning a property value and we hope that a right parenthesis 1565 // is next (except for possible blank spaces). 1566 1567 // 43. 1568 1569 // tangle:pos vptovf.web:957:69: 1570 1571 // After a property value has been scanned, we want to move just past the 1572 // right parenthesis that should come next in the input (except for possible 1573 // blank spaces). 1574 func (prg *prg) finishTheProperty() { 1575 for int32(prg.curChar) == ' ' { 1576 prg.getNext() 1577 } 1578 if int32(prg.curChar) != ')' { 1579 if int32(prg.charsOnLine) > 0 { 1580 prg.stdout.Writeln(" ") 1581 } 1582 prg.stdout.Write("Junk after property value will be ignored") 1583 prg.showErrorContext() 1584 } 1585 // \xref[Junk after property value...] 1586 prg.skipToEndOfItem() 1587 } 1588 1589 // 50. 1590 1591 // tangle:pos vptovf.web:1014:41: 1592 1593 // Since there is no chance of the hash table overflowing, the procedure 1594 // is very simple. After |lookup| has done its work, |cur_hash| will point 1595 // to the place where the given name was found, or where it should be inserted. 1596 func (prg *prg) lookup() { // finds |cur_name| in the dictionary 1597 var ( 1598 k/* 0..longestName */ byte // index into |cur_name| 1599 j/* 0..maxLetters */ uint16 // index into |dictionary| 1600 notFound bool // clumsy thing necessary to avoid |goto| statement 1601 ) 1602 prg.curHash = prg.curName[1-1] 1603 for ii := int32(2); ii <= int32(prg.nameLength); ii++ { 1604 k = byte(ii) 1605 _ = k 1606 prg.curHash = byte((int32(prg.curHash) + int32(prg.curHash) + int32(prg.curName[k-1])) % hashPrime) 1607 } 1608 notFound = true 1609 for notFound { 1610 if int32(prg.curHash) == 0 { 1611 prg.curHash = byte(hashPrime - 1) 1612 } else { 1613 prg.curHash = byte(int32(prg.curHash) - 1) 1614 } 1615 if int32(prg.nhash[prg.curHash]) == 0 { 1616 notFound = false 1617 } else { 1618 j = prg.start[prg.nhash[prg.curHash]-1] 1619 if int32(prg.start[int32(prg.nhash[prg.curHash])+1-1]) == int32(j)+int32(prg.nameLength) { 1620 notFound = false 1621 for ii := int32(1); ii <= int32(prg.nameLength); ii++ { 1622 k = byte(ii) 1623 _ = k 1624 if int32(prg.dictionary[int32(j)+int32(k)-1]) != int32(prg.curName[k-1]) { 1625 notFound = true 1626 } 1627 } 1628 } 1629 } 1630 } 1631 prg.namePtr = prg.nhash[prg.curHash] 1632 } 1633 1634 // 53. 1635 1636 // tangle:pos vptovf.web:1099:61: 1637 1638 // We have to get the keywords into the hash table and into the dictionary in 1639 // the first place (sigh). The procedure that does this has the desired 1640 // |equiv| code as a parameter. In order to facilitate \.[WEB] macro writing 1641 // for the initialization, the keyword being initialized is placed into the 1642 // last positions of |cur_name|, instead of the first positions. 1643 func (prg *prg) enterName(v byte) { // |cur_name| goes into the dictionary 1644 var ( 1645 k /* 0..longestName */ byte 1646 ) 1647 for ii := int32(1); ii <= int32(prg.nameLength); ii++ { 1648 k = byte(ii) 1649 _ = k 1650 prg.curName[k-1] = prg.curName[int32(k)+longestName-int32(prg.nameLength)-1] 1651 } 1652 // now the name has been shifted into the correct position 1653 prg.lookup() // this sets |cur_hash| to the proper insertion place 1654 prg.nhash[prg.curHash] = prg.startPtr 1655 prg.equiv[prg.startPtr] = v 1656 for ii := int32(1); ii <= int32(prg.nameLength); ii++ { 1657 k = byte(ii) 1658 _ = k 1659 prg.dictionary[prg.dictPtr] = prg.curName[k-1] 1660 prg.dictPtr = uint16(int32(prg.dictPtr) + 1) 1661 } 1662 prg.startPtr = byte(int32(prg.startPtr) + 1) 1663 prg.start[prg.startPtr-1] = prg.dictPtr 1664 } 1665 1666 // 54. 1667 1668 // tangle:pos vptovf.web:1118:5: 1669 1670 // Here are the macros to load a name of up to 20 letters into the 1671 // dictionary. For example, the macro |load5| is used for five-letter keywords. 1672 1673 // 58. 1674 1675 // tangle:pos vptovf.web:1269:65: 1676 1677 // When a left parenthesis has been scanned, the following routine 1678 // is used to interpret the keyword that follows, and to store the 1679 // equivalent value in |cur_code|. 1680 func (prg *prg) getName() { 1681 prg.loc = byte(int32(prg.loc) + 1) 1682 prg.level = prg.level + 1 // pass the left parenthesis 1683 prg.curChar = ' ' 1684 for int32(prg.curChar) == ' ' { 1685 prg.getNext() 1686 } 1687 if int32(prg.curChar) > ')' || int32(prg.curChar) < '(' { 1688 prg.loc = byte(int32(prg.loc) - 1) 1689 } // back up one character 1690 prg.nameLength = 0 1691 prg.getKeywordChar() // prepare to scan the name 1692 for int32(prg.curChar) != ' ' { 1693 if int32(prg.nameLength) == longestName { 1694 prg.curName[1-1] = 'X' 1695 } else { 1696 prg.nameLength = byte(int32(prg.nameLength) + 1) 1697 } 1698 prg.curName[prg.nameLength-1] = prg.curChar 1699 prg.getKeywordChar() 1700 } 1701 prg.lookup() 1702 if int32(prg.namePtr) == 0 { 1703 if int32(prg.charsOnLine) > 0 { 1704 prg.stdout.Writeln(" ") 1705 } 1706 prg.stdout.Write("Sorry, I don't know that property name") 1707 prg.showErrorContext() 1708 } 1709 // \xref[Sorry, I don't know...] 1710 prg.curCode = prg.equiv[prg.namePtr] 1711 } 1712 1713 // 59. Scanning numeric data 1714 1715 // tangle:pos vptovf.web:1293:22: 1716 1717 // The next thing we need is a trio of subroutines to read the one-byte, 1718 // four-byte, and real numbers that may appear as property values. 1719 // These subroutines are careful to stick to numbers between $-2^[31]$ 1720 // and $2^[31]-1$, inclusive, so that a computer with two's complement 1721 // 32-bit arithmetic will not be interrupted by overflow. 1722 1723 // 60. 1724 1725 // tangle:pos vptovf.web:1298:55: 1726 1727 // The first number scanner, which returns a one-byte value, surely has 1728 // no problems of arithmetic overflow. 1729 func (prg *prg) getByte() (r byte) { // scans a one-byte property value 1730 var ( 1731 acc int32 // an accumulator 1732 t asciiCode // the type of value to be scanned 1733 ) 1734 for { 1735 prg.getNext() 1736 if int32(prg.curChar) != ' ' { 1737 break 1738 } 1739 } // skip the blanks before the type code 1740 t = prg.curChar 1741 acc = 0 1742 for { 1743 prg.getNext() 1744 if int32(prg.curChar) != ' ' { 1745 break 1746 } 1747 } // skip the blanks after the type code 1748 if int32(t) == 'C' { 1749 if int32(prg.curChar) >= 041 && int32(prg.curChar) <= 0176 && (int32(prg.curChar) < '(' || int32(prg.curChar) > ')') { 1750 acc = int32(prg.xord[prg.buffer[prg.loc-1]]) 1751 } else { 1752 { 1753 if int32(prg.charsOnLine) > 0 { 1754 prg.stdout.Writeln(" ") 1755 } 1756 prg.stdout.Write("\"C\" value must be standard ASCII and not a paren") 1757 prg.showErrorContext() 1758 } 1759 for { 1760 prg.getNext() 1761 if int32(prg.curChar) == '(' || int32(prg.curChar) == ')' { 1762 break 1763 } 1764 } 1765 } 1766 } else if int32(t) == 'D' { 1767 for int32(prg.curChar) >= '0' && int32(prg.curChar) <= '9' { 1768 acc = acc*10 + int32(prg.curChar) - '0' 1769 if acc > 255 { 1770 { 1771 { 1772 if int32(prg.charsOnLine) > 0 { 1773 prg.stdout.Writeln(" ") 1774 } 1775 prg.stdout.Write("This value shouldn't exceed 255") 1776 prg.showErrorContext() 1777 } 1778 for { 1779 prg.getNext() 1780 if int32(prg.curChar) == '(' || int32(prg.curChar) == ')' { 1781 break 1782 } 1783 } 1784 } 1785 // \xref[This value shouldn't...] 1786 acc = 0 1787 prg.curChar = ' ' 1788 } else { 1789 prg.getNext() 1790 } 1791 } 1792 { 1793 if int32(prg.curChar) > ')' || int32(prg.curChar) < '(' { 1794 prg.loc = byte(int32(prg.loc) - 1) 1795 } 1796 } 1797 } else if int32(t) == 'O' { 1798 for int32(prg.curChar) >= '0' && int32(prg.curChar) <= '7' { 1799 acc = acc*8 + int32(prg.curChar) - '0' 1800 if acc > 255 { 1801 { 1802 { 1803 if int32(prg.charsOnLine) > 0 { 1804 prg.stdout.Writeln(" ") 1805 } 1806 prg.stdout.Write("This value shouldn't exceed '377") 1807 prg.showErrorContext() 1808 } 1809 for { 1810 prg.getNext() 1811 if int32(prg.curChar) == '(' || int32(prg.curChar) == ')' { 1812 break 1813 } 1814 } 1815 } 1816 // \xref[This value shouldn't...] 1817 acc = 0 1818 prg.curChar = ' ' 1819 } else { 1820 prg.getNext() 1821 } 1822 } 1823 { 1824 if int32(prg.curChar) > ')' || int32(prg.curChar) < '(' { 1825 prg.loc = byte(int32(prg.loc) - 1) 1826 } 1827 } 1828 } else if int32(t) == 'H' { 1829 for int32(prg.curChar) >= '0' && int32(prg.curChar) <= '9' || int32(prg.curChar) >= 'A' && int32(prg.curChar) <= 'F' { 1830 if int32(prg.curChar) >= 'A' { 1831 prg.curChar = byte(int32(prg.curChar) + '0' + 10 - 'A') 1832 } 1833 acc = acc*16 + int32(prg.curChar) - '0' 1834 if acc > 255 { 1835 { 1836 { 1837 if int32(prg.charsOnLine) > 0 { 1838 prg.stdout.Writeln(" ") 1839 } 1840 prg.stdout.Write("This value shouldn't exceed \"FF") 1841 prg.showErrorContext() 1842 } 1843 for { 1844 prg.getNext() 1845 if int32(prg.curChar) == '(' || int32(prg.curChar) == ')' { 1846 break 1847 } 1848 } 1849 } 1850 // \xref[This value shouldn't...] 1851 acc = 0 1852 prg.curChar = ' ' 1853 } else { 1854 prg.getNext() 1855 } 1856 } 1857 { 1858 if int32(prg.curChar) > ')' || int32(prg.curChar) < '(' { 1859 prg.loc = byte(int32(prg.loc) - 1) 1860 } 1861 } 1862 } else if int32(t) == 'F' { 1863 if int32(prg.curChar) == 'B' { 1864 acc = 2 1865 } else if int32(prg.curChar) == 'L' { 1866 acc = 4 1867 } else if int32(prg.curChar) != 'M' { 1868 acc = 18 1869 } 1870 prg.getNext() 1871 if int32(prg.curChar) == 'I' { 1872 acc = acc + 1 1873 } else if int32(prg.curChar) != 'R' { 1874 acc = 18 1875 } 1876 prg.getNext() 1877 if int32(prg.curChar) == 'C' { 1878 acc = acc + 6 1879 } else if int32(prg.curChar) == 'E' { 1880 acc = acc + 12 1881 } else if int32(prg.curChar) != 'R' { 1882 acc = 18 1883 } 1884 if acc >= 18 { 1885 { 1886 { 1887 if int32(prg.charsOnLine) > 0 { 1888 prg.stdout.Writeln(" ") 1889 } 1890 prg.stdout.Write("Illegal face code, I changed it to MRR") 1891 prg.showErrorContext() 1892 } 1893 for { 1894 prg.getNext() 1895 if int32(prg.curChar) == '(' || int32(prg.curChar) == ')' { 1896 break 1897 } 1898 } 1899 } 1900 // \xref[Illegal face code...] 1901 acc = 0 1902 } 1903 } else { 1904 { 1905 if int32(prg.charsOnLine) > 0 { 1906 prg.stdout.Writeln(" ") 1907 } 1908 prg.stdout.Write("You need \"C\" or \"D\" or \"O\" or \"H\" or \"F\" here") 1909 prg.showErrorContext() 1910 } 1911 for { 1912 prg.getNext() 1913 if int32(prg.curChar) == '(' || int32(prg.curChar) == ')' { 1914 break 1915 } 1916 } 1917 } 1918 // \xref[You need "C" or "D" ...here] 1919 prg.curChar = ' ' 1920 r = byte(acc) 1921 return r 1922 } 1923 1924 // 69. 1925 1926 // tangle:pos vptovf.web:1406:72: 1927 1928 // Since the |get_four_bytes| routine is used very infrequently, no attempt 1929 // has been made to make it fast; we only want it to work. 1930 func (prg *prg) getFourBytes() { // scans an unsigned constant and sets |four_bytes| 1931 var ( 1932 c int32 // local two-byte accumulator 1933 r1 int32 // radix 1934 ) 1935 for { 1936 prg.getNext() 1937 if int32(prg.curChar) != ' ' { 1938 break 1939 } 1940 } // skip the blanks before the type code 1941 r1 = 0 1942 prg.curBytes = prg.zeroBytes // start with the accumulator zero 1943 if int32(prg.curChar) == 'H' { 1944 r1 = 16 1945 } else if int32(prg.curChar) == 'O' { 1946 r1 = 8 1947 } else if int32(prg.curChar) == 'D' { 1948 r1 = 10 1949 } else { 1950 { 1951 if int32(prg.charsOnLine) > 0 { 1952 prg.stdout.Writeln(" ") 1953 } 1954 prg.stdout.Write("Decimal (\"D\"), octal (\"O\"), or hex (\"H\") value needed here") 1955 prg.showErrorContext() 1956 } 1957 for { 1958 prg.getNext() 1959 if int32(prg.curChar) == '(' || int32(prg.curChar) == ')' { 1960 break 1961 } 1962 } 1963 } 1964 // \xref[Decimal ("D"), octal ("O"), or hex...] 1965 if r1 > 0 { 1966 for { 1967 prg.getNext() 1968 if int32(prg.curChar) != ' ' { 1969 break 1970 } 1971 } // skip the blanks after the type code 1972 for int32(prg.curChar) >= '0' && int32(prg.curChar) <= '9' || int32(prg.curChar) >= 'A' && int32(prg.curChar) <= 'F' { 1973 1974 // Multiply by |r|, add |cur_char-"0"|, and |get_next| 1975 if int32(prg.curChar) >= 'A' { 1976 prg.curChar = byte(int32(prg.curChar) + '0' + 10 - 'A') 1977 } 1978 if int32(prg.curChar) >= '0'+r1 { 1979 { 1980 if int32(prg.charsOnLine) > 0 { 1981 prg.stdout.Writeln(" ") 1982 } 1983 prg.stdout.Write("Illegal digit") 1984 prg.showErrorContext() 1985 } 1986 for { 1987 prg.getNext() 1988 if int32(prg.curChar) == '(' || int32(prg.curChar) == ')' { 1989 break 1990 } 1991 } 1992 } else { 1993 c = int32(prg.curBytes.b3)*r1 + int32(prg.curChar) - '0' 1994 prg.curBytes.b3 = byte(c % 256) 1995 1996 c = int32(prg.curBytes.b2)*r1 + c/256 1997 prg.curBytes.b2 = byte(c % 256) 1998 1999 c = int32(prg.curBytes.b1)*r1 + c/256 2000 prg.curBytes.b1 = byte(c % 256) 2001 2002 c = int32(prg.curBytes.b0)*r1 + c/256 2003 if c < 256 { 2004 prg.curBytes.b0 = byte(c) 2005 } else { 2006 prg.curBytes = prg.zeroBytes 2007 if r1 == 8 { 2008 { 2009 if int32(prg.charsOnLine) > 0 { 2010 prg.stdout.Writeln(" ") 2011 } 2012 prg.stdout.Write("Sorry, the maximum octal value is O 37777777777") 2013 prg.showErrorContext() 2014 } 2015 for { 2016 prg.getNext() 2017 if int32(prg.curChar) == '(' || int32(prg.curChar) == ')' { 2018 break 2019 } 2020 } 2021 } else if r1 == 10 { 2022 { 2023 if int32(prg.charsOnLine) > 0 { 2024 prg.stdout.Writeln(" ") 2025 } 2026 prg.stdout.Write("Sorry, the maximum decimal value is D 4294967295") 2027 prg.showErrorContext() 2028 } 2029 for { 2030 prg.getNext() 2031 if int32(prg.curChar) == '(' || int32(prg.curChar) == ')' { 2032 break 2033 } 2034 } 2035 } else { 2036 { 2037 if int32(prg.charsOnLine) > 0 { 2038 prg.stdout.Writeln(" ") 2039 } 2040 prg.stdout.Write("Sorry, the maximum hex value is H FFFFFFFF") 2041 prg.showErrorContext() 2042 } 2043 for { 2044 prg.getNext() 2045 if int32(prg.curChar) == '(' || int32(prg.curChar) == ')' { 2046 break 2047 } 2048 } 2049 } 2050 } 2051 prg.getNext() 2052 } 2053 } 2054 } 2055 } 2056 2057 // 72. 2058 2059 // tangle:pos vptovf.web:1461:67: 2060 2061 // When a real value is desired, we might as well treat `\.D' and `\.R' 2062 // formats as if they were identical. 2063 func (prg *prg) getFix() (r fixWord) { // scans a real property value 2064 var ( 2065 negative bool // was there a minus sign? 2066 acc int32 // an accumulator 2067 intPart int32 // the integer part 2068 j/* 0..7 */ byte // the number of decimal places stored 2069 ) 2070 for { 2071 prg.getNext() 2072 if int32(prg.curChar) != ' ' { 2073 break 2074 } 2075 } // skip the blanks before the type code 2076 negative = false 2077 acc = 0 // start with the accumulators zero 2078 if int32(prg.curChar) != 'R' && int32(prg.curChar) != 'D' { 2079 { 2080 if int32(prg.charsOnLine) > 0 { 2081 prg.stdout.Writeln(" ") 2082 } 2083 prg.stdout.Write("An \"R\" or \"D\" value is needed here") 2084 prg.showErrorContext() 2085 } 2086 for { 2087 prg.getNext() 2088 if int32(prg.curChar) == '(' || int32(prg.curChar) == ')' { 2089 break 2090 } 2091 } 2092 } else { 2093 for { 2094 prg.getNext() 2095 if int32(prg.curChar) == '-' { 2096 prg.curChar = ' ' 2097 negative = !negative 2098 } else if int32(prg.curChar) == '+' { 2099 prg.curChar = ' ' 2100 } 2101 if int32(prg.curChar) != ' ' { 2102 break 2103 } 2104 } 2105 for int32(prg.curChar) >= '0' && int32(prg.curChar) <= '9' { 2106 2107 // Multiply by 10, add |cur_char-"0"|, and |get_next| 2108 acc = acc*10 + int32(prg.curChar) - '0' 2109 if acc >= 2048 { 2110 { 2111 { 2112 if int32(prg.charsOnLine) > 0 { 2113 prg.stdout.Writeln(" ") 2114 } 2115 prg.stdout.Write("Real constants must be less than 2048") 2116 prg.showErrorContext() 2117 } 2118 for { 2119 prg.getNext() 2120 if int32(prg.curChar) == '(' || int32(prg.curChar) == ')' { 2121 break 2122 } 2123 } 2124 } 2125 // \xref[Real constants must be...] 2126 acc = 0 2127 prg.curChar = ' ' 2128 } else { 2129 prg.getNext() 2130 } 2131 } 2132 intPart = acc 2133 acc = 0 2134 if int32(prg.curChar) == '.' { 2135 j = 0 2136 prg.getNext() 2137 for int32(prg.curChar) >= '0' && int32(prg.curChar) <= '9' { 2138 if int32(j) < 7 { 2139 j = byte(int32(j) + 1) 2140 prg.fractionDigits[j-1] = 010000000 * (int32(prg.curChar) - '0') 2141 } 2142 prg.getNext() 2143 } 2144 acc = 0 2145 for int32(j) > 0 { 2146 acc = prg.fractionDigits[j-1] + acc/10 2147 j = byte(int32(j) - 1) 2148 } 2149 acc = (acc + 10) / 20 2150 } 2151 if acc >= 04000000 && intPart == 2047 { 2152 { 2153 if int32(prg.charsOnLine) > 0 { 2154 prg.stdout.Writeln(" ") 2155 } 2156 prg.stdout.Write("Real constants must be less than 2048") 2157 prg.showErrorContext() 2158 } 2159 for { 2160 prg.getNext() 2161 if int32(prg.curChar) == '(' || int32(prg.curChar) == ')' { 2162 break 2163 } 2164 } 2165 } else { 2166 acc = intPart*04000000 + acc 2167 } 2168 } 2169 if negative { 2170 r = -acc 2171 } else { 2172 r = acc 2173 } 2174 return r 2175 } 2176 2177 // 85. 2178 2179 // tangle:pos vptovf.web:1680:17: 2180 2181 // As an example of these data structures, let us consider the simple 2182 // routine that inserts a potentially new element into one of the dimension 2183 // lists. The first parameter indicates the list head (i.e., |h=width| for 2184 // the width list, etc.); the second parameter is the value that is to be 2185 // inserted into the list if it is not already present. The procedure 2186 // returns the value of the location where the dimension appears in |memory|. 2187 // The fact that |memory[0]| is larger than any legal dimension makes the 2188 // algorithm particularly short. 2189 // 2190 // We do have to handle two somewhat subtle situations. A width of zero must be 2191 // put into the list, so that a zero-width character in the font will not appear 2192 // to be nonexistent (i.e., so that its |char_wd| index will not be zero), but 2193 // this does not need to be done for heights, depths, or italic corrections. 2194 // Furthermore, it is necessary to test for memory overflow even though we 2195 // have provided room for the maximum number of different dimensions in any 2196 // legal font, since the \.[VPL] file might foolishly give any number of 2197 // different sizes to the same character. 2198 func (prg *prg) sortIn(h pointer, d fixWord) (r pointer) { // inserts into list 2199 var ( 2200 p pointer // the current node of interest 2201 ) 2202 if d == 0 && int32(h) != width { 2203 r = 0 2204 } else { 2205 p = h 2206 for d >= prg.memory[prg.link[p]] { 2207 p = prg.link[p] 2208 } 2209 if d == prg.memory[p] && int32(p) != int32(h) { 2210 r = p 2211 } else if int32(prg.memPtr) == memSize { 2212 { 2213 if int32(prg.charsOnLine) > 0 { 2214 prg.stdout.Writeln(" ") 2215 } 2216 prg.stdout.Write("Memory overflow: more than 1028 widths, etc") 2217 prg.showErrorContext() 2218 } 2219 // \xref[Memory overflow...] 2220 prg.stdout.Writeln("Congratulations! It's hard to make this error.") 2221 r = p 2222 } else { 2223 prg.memPtr = uint16(int32(prg.memPtr) + 1) 2224 prg.memory[prg.memPtr] = d 2225 prg.link[prg.memPtr] = prg.link[p] 2226 prg.link[p] = prg.memPtr 2227 prg.memory[h] = prg.memory[h] + 1 2228 r = prg.memPtr 2229 } 2230 } 2231 return r 2232 } 2233 2234 // 87. 2235 2236 // tangle:pos vptovf.web:1733:67: 2237 2238 // Once again we can make good use of the fact that |memory[0]| is ``infinite.'' 2239 func (prg *prg) minCover(h pointer, d fixWord) (r int32) { 2240 var ( 2241 p pointer // the current node of interest 2242 l fixWord // the least element covered by the current interval 2243 m int32 // the current size of the cover being generated 2244 ) 2245 m = 0 2246 p = prg.link[h] 2247 prg.nextD = prg.memory[0] 2248 for int32(p) != 0 { 2249 m = m + 1 2250 l = prg.memory[p] 2251 for prg.memory[prg.link[p]] <= l+d { 2252 p = prg.link[p] 2253 } 2254 p = prg.link[p] 2255 if prg.memory[p]-l < prg.nextD { 2256 prg.nextD = prg.memory[p] - l 2257 } 2258 } 2259 r = m 2260 return r 2261 } 2262 2263 // 88. 2264 2265 // tangle:pos vptovf.web:1749:5: 2266 2267 // The following procedure uses |min_cover| to determine the smallest $d$ 2268 // such that a given list can be covered with at most a given number of 2269 // intervals. 2270 func (prg *prg) shorten(h pointer, m int32) (r fixWord) { // finds best way to round 2271 var ( 2272 d fixWord // the current trial interval length 2273 k int32 // the size of a minimum cover 2274 ) 2275 if prg.memory[h] > m { 2276 prg.excess = byte(prg.memory[h] - m) 2277 k = prg.minCover(h, fixWord(0)) 2278 d = prg.nextD // now the answer is at least |d| 2279 for { 2280 d = d + d 2281 k = prg.minCover(h, d) 2282 if k <= m { 2283 break 2284 } 2285 } // first we ascend rapidly until finding the range 2286 d = d / 2 2287 k = prg.minCover(h, d) // now we run through the feasible steps 2288 for k > m { 2289 d = prg.nextD 2290 k = prg.minCover(h, d) 2291 } 2292 r = d 2293 } else { 2294 r = 0 2295 } 2296 return r 2297 } 2298 2299 // 90. 2300 2301 // tangle:pos vptovf.web:1778:71: 2302 2303 // Here is the procedure that sets the |index| values. It also shortens 2304 // the list so that there is only one element per covering interval; 2305 // the remaining elements are the midpoints of their clusters. 2306 func (prg *prg) setIndices(h pointer, d fixWord) { // reduces and indexes a list 2307 var ( 2308 p pointer // the current node of interest 2309 q pointer // trails one step behind |p| 2310 m byte // index number of nodes in the current interval 2311 l fixWord // least value in the current interval 2312 ) 2313 q = h 2314 p = prg.link[q] 2315 m = 0 2316 for int32(p) != 0 { 2317 m = byte(int32(m) + 1) 2318 l = prg.memory[p] 2319 prg.index[p] = m 2320 for prg.memory[prg.link[p]] <= l+d { 2321 p = prg.link[p] 2322 prg.index[p] = m 2323 prg.excess = byte(int32(prg.excess) - 1) 2324 if int32(prg.excess) == 0 { 2325 d = 0 2326 } 2327 } 2328 prg.link[q] = p 2329 prg.memory[p] = l + (prg.memory[p]-l)/2 2330 q = p 2331 p = prg.link[p] 2332 } 2333 prg.memory[h] = int32(m) 2334 } 2335 2336 // 93. 2337 2338 // tangle:pos vptovf.web:1820:22: 2339 2340 // The |junk_error| routine just referred to is called when something 2341 // appears in the forbidden area between properties of a property list. 2342 func (prg *prg) junkError() { 2343 { 2344 if int32(prg.charsOnLine) > 0 { 2345 prg.stdout.Writeln(" ") 2346 } 2347 prg.stdout.Write("There's junk here that is not in parentheses") 2348 prg.showErrorContext() 2349 } 2350 // \xref[There's junk here...] 2351 for { 2352 prg.getNext() 2353 if int32(prg.curChar) == '(' || int32(prg.curChar) == ')' { 2354 break 2355 } 2356 } 2357 } 2358 2359 // 96. 2360 2361 // tangle:pos vptovf.web:1870:4: 2362 2363 // The |case| statement just given makes use of three subroutines that we 2364 // haven't defined yet. The first of these puts a 32-bit octal quantity 2365 // into four specified bytes of the header block. 2366 func (prg *prg) readFourBytes(l headerIndex) { 2367 prg.getFourBytes() 2368 prg.headerBytes[l] = prg.curBytes.b0 2369 prg.headerBytes[int32(l)+1] = prg.curBytes.b1 2370 prg.headerBytes[int32(l)+2] = prg.curBytes.b2 2371 prg.headerBytes[int32(l)+3] = prg.curBytes.b3 2372 } 2373 2374 // 97. 2375 2376 // tangle:pos vptovf.web:1882:5: 2377 2378 // The second little procedure is used to scan a string and to store it in 2379 // the ``[\mc BCPL] format'' required by \.[TFM] files. The string is supposed 2380 // to contain at most |n| bytes, including the first byte (which holds the 2381 // length of the rest of the string). 2382 func (prg *prg) readBcpl(l headerIndex, n byte) { 2383 var ( 2384 k headerIndex 2385 ) 2386 k = l 2387 for int32(prg.curChar) == ' ' { 2388 prg.getNext() 2389 } 2390 for int32(prg.curChar) != '(' && int32(prg.curChar) != ')' { 2391 if int32(k) < int32(l)+int32(n) { 2392 k = byte(int32(k) + 1) 2393 } 2394 if int32(k) < int32(l)+int32(n) { 2395 prg.headerBytes[k] = prg.curChar 2396 } 2397 prg.getNext() 2398 } 2399 if int32(k) == int32(l)+int32(n) { 2400 { 2401 if int32(prg.charsOnLine) > 0 { 2402 prg.stdout.Writeln(" ") 2403 } 2404 prg.stdout.Write("String is too long; its first ", int32(n)-1, knuth.WriteWidth(1), 2405 // \xref[String is too long...] 2406 " characters will be kept") 2407 prg.showErrorContext() 2408 } 2409 k = byte(int32(k) - 1) 2410 } 2411 prg.headerBytes[l] = byte(int32(k) - int32(l)) 2412 for int32(k) < int32(l)+int32(n)-1 { // tidy up the remaining bytes by setting them to nulls 2413 k = byte(int32(k) + 1) 2414 prg.headerBytes[k] = 0 2415 } 2416 } 2417 2418 // 111. 2419 2420 // tangle:pos vptovf.web:2091:4: 2421 2422 // When a character is about to be tagged, we call the following 2423 // procedure so that an error message is given in case of multiple tags. 2424 func (prg *prg) checkTag(c byte) { 2425 switch prg.charTag[c] { 2426 case noTag: 2427 case ligTag: 2428 if int32(prg.charsOnLine) > 0 { 2429 prg.stdout.Writeln(" ") 2430 } 2431 prg.stdout.Write("This character already appeared in a LIGTABLE LABEL") 2432 prg.showErrorContext() 2433 // \xref[This character already...] 2434 case listTag: 2435 if int32(prg.charsOnLine) > 0 { 2436 prg.stdout.Writeln(" ") 2437 } 2438 prg.stdout.Write("This character already has a NEXTLARGER spec") 2439 prg.showErrorContext() 2440 case extTag: 2441 if int32(prg.charsOnLine) > 0 { 2442 prg.stdout.Writeln(" ") 2443 } 2444 prg.stdout.Write("This character already has a VARCHAR spec") 2445 prg.showErrorContext() 2446 } 2447 } 2448 2449 // 122. Assembling the mappings 2450 2451 // tangle:pos vptovf.web:2251:24: 2452 2453 // Each \.[MAP] property is a sequence of \.[DVI] instructions, for which 2454 // we need to know some of the opcodes. 2455 2456 // 124. 2457 2458 // tangle:pos vptovf.web:2285:26: 2459 2460 // The packet is built by straightforward assembly of \.[DVI] instructions. 2461 // Declare the |vf_fix| procedure 2462 func (prg *prg) vfFix(opcode byte, x fixWord) { 2463 var ( 2464 negative bool 2465 k/* 0..4 */ byte // number of bytes to typeset 2466 t int32 // threshold 2467 ) 2468 prg.frozenDu = true 2469 if prg.designUnits != 04000000 { 2470 x = round(float64(x) / float64(prg.designUnits) * 1048576.0) 2471 } 2472 if x >= 0 { 2473 negative = false 2474 } else { 2475 negative = true 2476 x = -1 - x 2477 } 2478 if int32(opcode) == 0 { 2479 k = 4 2480 t = 0100000000 2481 } else { 2482 t = 127 2483 k = 1 2484 for x > t { 2485 t = 256*t + 255 2486 k = byte(int32(k) + 1) 2487 } 2488 { 2489 prg.vf[prg.vfPtr] = byte(int32(opcode) + int32(k) - 1) 2490 if int32(prg.vfPtr) == vfSize { 2491 if int32(prg.charsOnLine) > 0 { 2492 prg.stdout.Writeln(" ") 2493 } 2494 prg.stdout.Write("I'm out of memory---increase my vfsize!") 2495 prg.showErrorContext() 2496 } else { 2497 prg.vfPtr = uint16(int32(prg.vfPtr) + 1) 2498 } 2499 } 2500 t = t/128 + 1 2501 } 2502 for { 2503 if negative { 2504 { 2505 prg.vf[prg.vfPtr] = byte(255 - x/t) 2506 if int32(prg.vfPtr) == vfSize { 2507 if int32(prg.charsOnLine) > 0 { 2508 prg.stdout.Writeln(" ") 2509 } 2510 prg.stdout.Write("I'm out of memory---increase my vfsize!") 2511 prg.showErrorContext() 2512 } else { 2513 prg.vfPtr = uint16(int32(prg.vfPtr) + 1) 2514 } 2515 } 2516 negative = false 2517 x = x/t*t + t - 1 - x 2518 } else { 2519 prg.vf[prg.vfPtr] = byte(x / t % 256) 2520 if int32(prg.vfPtr) == vfSize { 2521 if int32(prg.charsOnLine) > 0 { 2522 prg.stdout.Writeln(" ") 2523 } 2524 prg.stdout.Write("I'm out of memory---increase my vfsize!") 2525 prg.showErrorContext() 2526 } else { 2527 prg.vfPtr = uint16(int32(prg.vfPtr) + 1) 2528 } 2529 } 2530 k = byte(int32(k) - 1) 2531 t = t / 256 2532 if int32(k) == 0 { 2533 break 2534 } 2535 } 2536 } 2537 2538 func (prg *prg) readPacket(c byte) { 2539 var ( 2540 cc byte // character being typeset 2541 x fixWord // movement 2542 h, v/* 0..2 */ byte // top of |hstack| and |vstack| 2543 specialStart/* 0..vfSize */ uint16 // location of |xxx1| command 2544 k/* 0..vfSize */ uint16 // loop index 2545 ) 2546 prg.packetStart[c] = prg.vfPtr 2547 prg.stackPtr = 0 2548 h = 0 2549 v = 0 2550 prg.curFont = 0 2551 for prg.level == 2 { 2552 for int32(prg.curChar) == ' ' { 2553 prg.getNext() 2554 } 2555 if int32(prg.curChar) == '(' { 2556 prg.getName() 2557 if int32(prg.curCode) == commentCode { 2558 prg.skipToEndOfItem() 2559 } else if int32(prg.curCode) < selectFontCode || int32(prg.curCode) > specialHexCode { 2560 { 2561 if int32(prg.charsOnLine) > 0 { 2562 prg.stdout.Writeln(" ") 2563 } 2564 prg.stdout.Write("This property name doesn't belong in a MAP list") 2565 prg.showErrorContext() 2566 } 2567 prg.skipToEndOfItem() 2568 } else { 2569 switch prg.curCode { 2570 case selectFontCode: 2571 // Assemble a font selection 2572 prg.getFourBytes() 2573 prg.fontNumber[prg.fontPtr] = prg.curBytes 2574 prg.curFont = 0 2575 for int32(prg.fontNumber[prg.curFont].b3) != int32(prg.fontNumber[prg.fontPtr].b3) || int32(prg.fontNumber[prg.curFont].b2) != int32(prg.fontNumber[prg.fontPtr].b2) || int32(prg.fontNumber[prg.curFont].b1) != int32(prg.fontNumber[prg.fontPtr].b1) || int32(prg.fontNumber[prg.curFont].b0) != int32(prg.fontNumber[prg.fontPtr].b0) { 2576 prg.curFont = uint16(int32(prg.curFont) + 1) 2577 } 2578 if int32(prg.curFont) == int32(prg.fontPtr) { 2579 if int32(prg.charsOnLine) > 0 { 2580 prg.stdout.Writeln(" ") 2581 } 2582 prg.stdout.Write("Undefined MAPFONT cannot be selected") 2583 prg.showErrorContext() 2584 } else if int32(prg.curFont) < 64 { 2585 prg.vf[prg.vfPtr] = byte(fntNum0 + int32(prg.curFont)) 2586 if int32(prg.vfPtr) == vfSize { 2587 if int32(prg.charsOnLine) > 0 { 2588 prg.stdout.Writeln(" ") 2589 } 2590 prg.stdout.Write("I'm out of memory---increase my vfsize!") 2591 prg.showErrorContext() 2592 } else { 2593 prg.vfPtr = uint16(int32(prg.vfPtr) + 1) 2594 } 2595 } else { 2596 { 2597 prg.vf[prg.vfPtr] = byte(fnt1) 2598 if int32(prg.vfPtr) == vfSize { 2599 if int32(prg.charsOnLine) > 0 { 2600 prg.stdout.Writeln(" ") 2601 } 2602 prg.stdout.Write("I'm out of memory---increase my vfsize!") 2603 prg.showErrorContext() 2604 } else { 2605 prg.vfPtr = uint16(int32(prg.vfPtr) + 1) 2606 } 2607 } 2608 { 2609 prg.vf[prg.vfPtr] = byte(prg.curFont) 2610 if int32(prg.vfPtr) == vfSize { 2611 if int32(prg.charsOnLine) > 0 { 2612 prg.stdout.Writeln(" ") 2613 } 2614 prg.stdout.Write("I'm out of memory---increase my vfsize!") 2615 prg.showErrorContext() 2616 } else { 2617 prg.vfPtr = uint16(int32(prg.vfPtr) + 1) 2618 } 2619 } 2620 } 2621 2622 case setCharCode: 2623 // Assemble a typesetting instruction 2624 if int32(prg.curFont) == int32(prg.fontPtr) { 2625 if int32(prg.charsOnLine) > 0 { 2626 prg.stdout.Writeln(" ") 2627 } 2628 prg.stdout.Write("Character cannot be typeset in undefined font") 2629 prg.showErrorContext() 2630 } else { 2631 cc = prg.getByte() 2632 if int32(cc) >= 128 { 2633 prg.vf[prg.vfPtr] = byte(set1) 2634 if int32(prg.vfPtr) == vfSize { 2635 if int32(prg.charsOnLine) > 0 { 2636 prg.stdout.Writeln(" ") 2637 } 2638 prg.stdout.Write("I'm out of memory---increase my vfsize!") 2639 prg.showErrorContext() 2640 } else { 2641 prg.vfPtr = uint16(int32(prg.vfPtr) + 1) 2642 } 2643 } 2644 { 2645 prg.vf[prg.vfPtr] = cc 2646 if int32(prg.vfPtr) == vfSize { 2647 if int32(prg.charsOnLine) > 0 { 2648 prg.stdout.Writeln(" ") 2649 } 2650 prg.stdout.Write("I'm out of memory---increase my vfsize!") 2651 prg.showErrorContext() 2652 } else { 2653 prg.vfPtr = uint16(int32(prg.vfPtr) + 1) 2654 } 2655 } 2656 } 2657 2658 case setRuleCode: 2659 // Assemble a rulesetting instruction 2660 { 2661 prg.vf[prg.vfPtr] = byte(setRule) 2662 if int32(prg.vfPtr) == vfSize { 2663 if int32(prg.charsOnLine) > 0 { 2664 prg.stdout.Writeln(" ") 2665 } 2666 prg.stdout.Write("I'm out of memory---increase my vfsize!") 2667 prg.showErrorContext() 2668 } else { 2669 prg.vfPtr = uint16(int32(prg.vfPtr) + 1) 2670 } 2671 } 2672 prg.vfFix(byte(0), prg.getFix()) 2673 prg.vfFix(byte(0), prg.getFix()) 2674 2675 case moveRightCode, moveRightCode + 1: 2676 // Assemble a horizontal movement 2677 if int32(prg.curCode) == moveRightCode { 2678 x = prg.getFix() 2679 } else { 2680 x = -prg.getFix() 2681 } 2682 if int32(h) == 0 { 2683 prg.wstack[prg.stackPtr] = x 2684 h = 1 2685 prg.vfFix(byte(w1), x) 2686 } else if x == prg.wstack[prg.stackPtr] { 2687 prg.vf[prg.vfPtr] = byte(w0) 2688 if int32(prg.vfPtr) == vfSize { 2689 if int32(prg.charsOnLine) > 0 { 2690 prg.stdout.Writeln(" ") 2691 } 2692 prg.stdout.Write("I'm out of memory---increase my vfsize!") 2693 prg.showErrorContext() 2694 } else { 2695 prg.vfPtr = uint16(int32(prg.vfPtr) + 1) 2696 } 2697 } else if int32(h) == 1 { 2698 prg.xstack[prg.stackPtr] = x 2699 h = 2 2700 prg.vfFix(byte(x1), x) 2701 } else if x == prg.xstack[prg.stackPtr] { 2702 prg.vf[prg.vfPtr] = byte(x0) 2703 if int32(prg.vfPtr) == vfSize { 2704 if int32(prg.charsOnLine) > 0 { 2705 prg.stdout.Writeln(" ") 2706 } 2707 prg.stdout.Write("I'm out of memory---increase my vfsize!") 2708 prg.showErrorContext() 2709 } else { 2710 prg.vfPtr = uint16(int32(prg.vfPtr) + 1) 2711 } 2712 } else { 2713 prg.vfFix(byte(right1), x) 2714 } 2715 2716 case moveDownCode, moveDownCode + 1: 2717 // Assemble a vertical movement 2718 if int32(prg.curCode) == moveDownCode { 2719 x = prg.getFix() 2720 } else { 2721 x = -prg.getFix() 2722 } 2723 if int32(v) == 0 { 2724 prg.ystack[prg.stackPtr] = x 2725 v = 1 2726 prg.vfFix(byte(y1), x) 2727 } else if x == prg.ystack[prg.stackPtr] { 2728 prg.vf[prg.vfPtr] = byte(y0) 2729 if int32(prg.vfPtr) == vfSize { 2730 if int32(prg.charsOnLine) > 0 { 2731 prg.stdout.Writeln(" ") 2732 } 2733 prg.stdout.Write("I'm out of memory---increase my vfsize!") 2734 prg.showErrorContext() 2735 } else { 2736 prg.vfPtr = uint16(int32(prg.vfPtr) + 1) 2737 } 2738 } else if int32(v) == 1 { 2739 prg.zstack[prg.stackPtr] = x 2740 v = 2 2741 prg.vfFix(byte(z1), x) 2742 } else if x == prg.zstack[prg.stackPtr] { 2743 prg.vf[prg.vfPtr] = byte(z0) 2744 if int32(prg.vfPtr) == vfSize { 2745 if int32(prg.charsOnLine) > 0 { 2746 prg.stdout.Writeln(" ") 2747 } 2748 prg.stdout.Write("I'm out of memory---increase my vfsize!") 2749 prg.showErrorContext() 2750 } else { 2751 prg.vfPtr = uint16(int32(prg.vfPtr) + 1) 2752 } 2753 } else { 2754 prg.vfFix(byte(down1), x) 2755 } 2756 2757 case pushCode: 2758 // Assemble a stack push 2759 if int32(prg.stackPtr) == maxStack { 2760 if int32(prg.charsOnLine) > 0 { 2761 prg.stdout.Writeln(" ") 2762 } 2763 prg.stdout.Write("Don't push so much---stack is full!") 2764 prg.showErrorContext() 2765 } else { 2766 { 2767 prg.vf[prg.vfPtr] = byte(push) 2768 if int32(prg.vfPtr) == vfSize { 2769 if int32(prg.charsOnLine) > 0 { 2770 prg.stdout.Writeln(" ") 2771 } 2772 prg.stdout.Write("I'm out of memory---increase my vfsize!") 2773 prg.showErrorContext() 2774 } else { 2775 prg.vfPtr = uint16(int32(prg.vfPtr) + 1) 2776 } 2777 } 2778 prg.hstack[prg.stackPtr] = h 2779 prg.vstack[prg.stackPtr] = v 2780 prg.stackPtr = byte(int32(prg.stackPtr) + 1) 2781 h = 0 2782 v = 0 2783 } 2784 2785 case popCode: 2786 // Assemble a stack pop 2787 if int32(prg.stackPtr) == 0 { 2788 if int32(prg.charsOnLine) > 0 { 2789 prg.stdout.Writeln(" ") 2790 } 2791 prg.stdout.Write("Empty stack cannot be popped") 2792 prg.showErrorContext() 2793 } else { 2794 { 2795 prg.vf[prg.vfPtr] = byte(pop) 2796 if int32(prg.vfPtr) == vfSize { 2797 if int32(prg.charsOnLine) > 0 { 2798 prg.stdout.Writeln(" ") 2799 } 2800 prg.stdout.Write("I'm out of memory---increase my vfsize!") 2801 prg.showErrorContext() 2802 } else { 2803 prg.vfPtr = uint16(int32(prg.vfPtr) + 1) 2804 } 2805 } 2806 prg.stackPtr = byte(int32(prg.stackPtr) - 1) 2807 h = prg.hstack[prg.stackPtr] 2808 v = prg.vstack[prg.stackPtr] 2809 } 2810 2811 case specialCode, specialHexCode: 2812 // Assemble a special command 2813 { 2814 prg.vf[prg.vfPtr] = byte(xxx1) 2815 if int32(prg.vfPtr) == vfSize { 2816 if int32(prg.charsOnLine) > 0 { 2817 prg.stdout.Writeln(" ") 2818 } 2819 prg.stdout.Write("I'm out of memory---increase my vfsize!") 2820 prg.showErrorContext() 2821 } else { 2822 prg.vfPtr = uint16(int32(prg.vfPtr) + 1) 2823 } 2824 } 2825 { 2826 prg.vf[prg.vfPtr] = 0 2827 if int32(prg.vfPtr) == vfSize { 2828 if int32(prg.charsOnLine) > 0 { 2829 prg.stdout.Writeln(" ") 2830 } 2831 prg.stdout.Write("I'm out of memory---increase my vfsize!") 2832 prg.showErrorContext() 2833 } else { 2834 prg.vfPtr = uint16(int32(prg.vfPtr) + 1) 2835 } 2836 } // dummy length 2837 specialStart = prg.vfPtr 2838 if int32(prg.curCode) == specialCode { 2839 prg.copyToEndOfItem() 2840 } else { 2841 for { 2842 x = int32(prg.getHex()) 2843 if int32(prg.curChar) > ')' { 2844 prg.vf[prg.vfPtr] = byte(x*16 + int32(prg.getHex())) 2845 if int32(prg.vfPtr) == vfSize { 2846 if int32(prg.charsOnLine) > 0 { 2847 prg.stdout.Writeln(" ") 2848 } 2849 prg.stdout.Write("I'm out of memory---increase my vfsize!") 2850 prg.showErrorContext() 2851 } else { 2852 prg.vfPtr = uint16(int32(prg.vfPtr) + 1) 2853 } 2854 } 2855 if int32(prg.curChar) <= ')' { 2856 break 2857 } 2858 } 2859 } 2860 if int32(prg.vfPtr)-int32(specialStart) > 255 { 2861 if int32(prg.vfPtr)+3 > vfSize { 2862 { 2863 if int32(prg.charsOnLine) > 0 { 2864 prg.stdout.Writeln(" ") 2865 } 2866 prg.stdout.Write("Special command being clipped---no room left!") 2867 prg.showErrorContext() 2868 } 2869 // \xref[Special command being clipped...] 2870 prg.vfPtr = uint16(int32(specialStart) + 255) 2871 prg.vf[int32(specialStart)-1] = 255 2872 } else { 2873 for ii := int32(prg.vfPtr); ii >= int32(specialStart); ii-- { 2874 k = uint16(ii) 2875 _ = k 2876 prg.vf[int32(k)+3] = prg.vf[k] 2877 } 2878 x = int32(prg.vfPtr) - int32(specialStart) 2879 prg.vfPtr = uint16(int32(prg.vfPtr) + 3) 2880 prg.vf[int32(specialStart)-2] = byte(xxx4) 2881 prg.vf[int32(specialStart)-1] = byte(x / 0100000000) 2882 prg.vf[specialStart] = byte(x / 0200000 % 256) 2883 prg.vf[int32(specialStart)+1] = byte(x / 0400 % 256) 2884 prg.vf[int32(specialStart)+2] = byte(x % 256) 2885 } 2886 } else { 2887 prg.vf[int32(specialStart)-1] = byte(int32(prg.vfPtr) - int32(specialStart)) 2888 } 2889 2890 } 2891 2892 prg.finishTheProperty() 2893 } 2894 } else if int32(prg.curChar) == ')' { 2895 prg.skipToEndOfItem() 2896 } else { 2897 prg.junkError() 2898 } 2899 } 2900 for int32(prg.stackPtr) > 0 { 2901 { 2902 if int32(prg.charsOnLine) > 0 { 2903 prg.stdout.Writeln(" ") 2904 } 2905 prg.stdout.Write("Missing POP supplied") 2906 prg.showErrorContext() 2907 } 2908 // \xref[Missing POP supplied] 2909 { 2910 prg.vf[prg.vfPtr] = byte(pop) 2911 if int32(prg.vfPtr) == vfSize { 2912 if int32(prg.charsOnLine) > 0 { 2913 prg.stdout.Writeln(" ") 2914 } 2915 prg.stdout.Write("I'm out of memory---increase my vfsize!") 2916 prg.showErrorContext() 2917 } else { 2918 prg.vfPtr = uint16(int32(prg.vfPtr) + 1) 2919 } 2920 } 2921 prg.stackPtr = byte(int32(prg.stackPtr) - 1) 2922 } 2923 prg.packetLength[c] = int32(prg.vfPtr) - int32(prg.packetStart[c]) 2924 { 2925 prg.loc = byte(int32(prg.loc) - 1) 2926 prg.level = prg.level + 1 2927 prg.curChar = ')' 2928 } 2929 } 2930 2931 // 136. 2932 2933 // tangle:pos vptovf.web:2449:6: 2934 2935 // The input routine is now complete except for the following code, 2936 // which prints a progress report as the file is being read. 2937 func (prg *prg) printOctal(c byte) { 2938 prg.stdout.Write("'", int32(c)/64, knuth.WriteWidth(1), int32(c)/8%8, knuth.WriteWidth(1), int32(c)%8, knuth.WriteWidth(1)) 2939 } 2940 2941 // 146. 2942 2943 // tangle:pos vptovf.web:2579:4: 2944 2945 // It's not trivial to check for infinite loops generated by repeated 2946 // insertion of ligature characters. But fortunately there is a nice 2947 // algorithm for such testing, copied here from the program \.[TFtoPL] 2948 // where it is explained further. 2949 2950 // 150. 2951 2952 // tangle:pos vptovf.web:2630:4: 2953 2954 // The |hash_input| procedure is copied from \.[TFtoPL], but it is made 2955 // into a boolean function that returns |false| if the ligature command 2956 // was masked by a previous one. 2957 func (prg *prg) hashInput(p, c indx) (r bool) { // go here for a quick exit 2958 var ( 2959 cc/* simple..bothZ */ byte // class of data being entered 2960 zz/* 0..255 */ byte // function value or ligature character being entered 2961 y/* 0..255 */ byte // the character after the cursor 2962 key int32 // value to be stored in |hash| 2963 t int32 // temporary register for swapping 2964 ) 2965 if int32(prg.hashPtr) == hashSize { 2966 r = false 2967 goto _30 2968 } 2969 2970 // Compute the command parameters |y|, |cc|, and |zz| 2971 y = prg.ligKern[p].b1 2972 t = int32(prg.ligKern[p].b2) 2973 cc = byte(simple) 2974 zz = prg.ligKern[p].b3 2975 if t >= kernFlag { 2976 zz = y 2977 } else { 2978 switch t { 2979 case 0, 6: // \.[LIG],\.[/LIG>] 2980 case 5, 11: 2981 zz = y // \.[LIG/>], \.[/LIG/>>] 2982 case 1, 7: 2983 cc = byte(leftZ) // \.[LIG/], \.[/LIG/>] 2984 case 2: 2985 cc = byte(rightZ) // \.[/LIG] 2986 case 3: 2987 cc = byte(bothZ) // \.[/LIG/] 2988 } // there are no other cases 2989 } 2990 key = 256*int32(c) + int32(y) + 1 2991 prg.h = uint16(1009 * key % hashSize) 2992 for int32(prg.hash[prg.h]) > 0 { 2993 if int32(prg.hash[prg.h]) <= key { 2994 if int32(prg.hash[prg.h]) == key { 2995 r = false 2996 goto _30 // unused ligature command 2997 } 2998 t = int32(prg.hash[prg.h]) 2999 prg.hash[prg.h] = uint32(key) 3000 key = t // do ordered-hash-table insertion 3001 t = int32(prg.class[prg.h]) 3002 prg.class[prg.h] = cc 3003 cc = byte(t) // namely, do a swap 3004 t = int32(prg.ligZ[prg.h]) 3005 prg.ligZ[prg.h] = uint16(zz) 3006 zz = byte(t) 3007 } 3008 if int32(prg.h) > 0 { 3009 prg.h = uint16(int32(prg.h) - 1) 3010 } else { 3011 prg.h = uint16(hashSize) 3012 } 3013 } 3014 prg.hash[prg.h] = uint32(key) 3015 prg.class[prg.h] = cc 3016 prg.ligZ[prg.h] = uint16(zz) 3017 prg.hashPtr = uint16(int32(prg.hashPtr) + 1) 3018 prg.hashList[prg.hashPtr] = prg.h 3019 r = true 3020 _30: 3021 ; 3022 return r 3023 } // \2 3024 // compute $f$ for arguments known to be in |hash[h]| 3025 func (prg *prg) eval(x, y indx) (r indx) { // compute $f(x,y)$ with hashtable lookup 3026 var ( 3027 key int32 // value sought in hash table 3028 ) 3029 key = 256*int32(x) + int32(y) + 1 3030 prg.h = uint16(1009 * key % hashSize) 3031 for int32(prg.hash[prg.h]) > key { 3032 if int32(prg.h) > 0 { 3033 prg.h = uint16(int32(prg.h) - 1) 3034 } else { 3035 prg.h = uint16(hashSize) 3036 } 3037 } 3038 if int32(prg.hash[prg.h]) < key { 3039 r = y 3040 } else { 3041 r = prg.f(prg.h, x, y) 3042 } 3043 return r 3044 } 3045 3046 // 152. 3047 3048 // tangle:pos vptovf.web:2675:6: 3049 3050 // (More good stuff from \.[TFtoPL].) 3051 func (prg *prg) f(h, x, y indx) (r indx) { 3052 switch prg.class[h] { 3053 case simple: 3054 case leftZ: 3055 prg.class[h] = byte(pending) 3056 prg.ligZ[h] = prg.eval(prg.ligZ[h], y) 3057 prg.class[h] = byte(simple) 3058 3059 case rightZ: 3060 prg.class[h] = byte(pending) 3061 prg.ligZ[h] = prg.eval(x, prg.ligZ[h]) 3062 prg.class[h] = byte(simple) 3063 3064 case bothZ: 3065 prg.class[h] = byte(pending) 3066 prg.ligZ[h] = prg.eval(prg.eval(x, prg.ligZ[h]), y) 3067 prg.class[h] = byte(simple) 3068 3069 case pending: 3070 prg.xLigCycle = x 3071 prg.yLigCycle = y 3072 prg.ligZ[h] = 257 3073 prg.class[h] = byte(simple) 3074 // the value 257 will break all cycles, since it's not in |hash| 3075 } // there are no other cases 3076 r = prg.ligZ[h] 3077 return r 3078 } 3079 3080 // 156. The TFM output phase 3081 3082 // tangle:pos vptovf.web:2771:21: 3083 3084 // Now that we know how to get all of the font data correctly stored in 3085 // \.[VPtoVF]'s memory, it only remains to write the answers out. 3086 // 3087 // First of all, it is convenient to have an abbreviation for output to the 3088 // \.[TFM] file: 3089 3090 // 165. 3091 3092 // tangle:pos vptovf.web:2885:6: 3093 3094 // When a scaled quantity is output, we may need to divide it by |design_units|. 3095 // The following subroutine takes care of this, using floating point arithmetic 3096 // only if |design_units<>1.0|. 3097 func (prg *prg) outScaled(x fixWord) { // outputs a scaled |fix_word| 3098 var ( 3099 n byte // the first byte after the sign 3100 m/* 0..65535 */ uint16 // the two least significant bytes 3101 ) 3102 if fabs(float64(x)/float64(prg.designUnits)) >= 16.0 { 3103 prg.stdout.Writeln("The relative dimension ", float64(x)/float64(04000000), knuth.WriteWidth(1), knuth.WriteWidth(3), 3104 " is too large.") 3105 // \xref[The relative dimension...] 3106 prg.stdout.Write(" (Must be less than 16*designsize") 3107 if prg.designUnits != 04000000 { 3108 prg.stdout.Write(" =", float64(prg.designUnits)/float64(0200000), knuth.WriteWidth(1), knuth.WriteWidth(3), 3109 " designunits") 3110 } 3111 prg.stdout.Writeln(")") 3112 x = 0 3113 } 3114 if prg.designUnits != 04000000 { 3115 x = round(float64(x) / float64(prg.designUnits) * 1048576.0) 3116 } 3117 if x < 0 { 3118 prg.tfmFile.Write(255) 3119 x = x + 0100000000 3120 if x <= 0 { 3121 x = 1 3122 } 3123 } else { 3124 prg.tfmFile.Write(0) 3125 if x >= 0100000000 { 3126 x = 077777777 3127 } 3128 } 3129 n = byte(x / 0200000) 3130 m = uint16(x % 0200000) 3131 prg.tfmFile.Write(n) 3132 prg.tfmFile.Write(int32(m) / 256) 3133 prg.tfmFile.Write(int32(m) % 256) 3134 } 3135 3136 // 176. 3137 3138 // tangle:pos vptovf.web:3049:57: 3139 3140 // We need a routine to output integers as four bytes. Negative values 3141 // will never be less than $-2^[24]$. 3142 func (prg *prg) voutInt(x int32) { 3143 if x >= 0 { 3144 prg.vfFile.Write(x / 0100000000) 3145 } else { 3146 prg.vfFile.Write(255) 3147 x = x + 0100000000 3148 } 3149 prg.vfFile.Write(x / 0200000 % 256) 3150 prg.vfFile.Write(x / 0400 % 256) 3151 prg.vfFile.Write(x % 256) 3152 } 3153 3154 // 180. The main program 3155 3156 // tangle:pos vptovf.web:3109:17: 3157 3158 // The routines sketched out so far need to be packaged into separate procedures, 3159 // on some systems, since some \PASCAL\ compilers place a strict limit on the 3160 // size of a routine. The packaging is done here in an attempt to avoid some 3161 // system-dependent changes. 3162 func (prg *prg) paramEnter() { 3163 prg.nameLength = 5 3164 prg.curName[16-1] = 'S' 3165 prg.curName[17-1] = 'L' 3166 prg.curName[18-1] = 'A' 3167 prg.curName[19-1] = 'N' 3168 prg.curName[20-1] = 'T' 3169 prg.enterName(byte(parameterCode + 1)) 3170 3171 prg.nameLength = 5 3172 prg.curName[16-1] = 'S' 3173 prg.curName[17-1] = 'P' 3174 prg.curName[18-1] = 'A' 3175 prg.curName[19-1] = 'C' 3176 prg.curName[20-1] = 'E' 3177 prg.enterName(byte(parameterCode + 2)) 3178 3179 prg.nameLength = 7 3180 prg.curName[14-1] = 'S' 3181 prg.curName[15-1] = 'T' 3182 prg.curName[16-1] = 'R' 3183 prg.curName[17-1] = 'E' 3184 prg.curName[18-1] = 'T' 3185 prg.curName[19-1] = 'C' 3186 prg.curName[20-1] = 'H' 3187 prg.enterName(byte(parameterCode + 3)) 3188 3189 prg.nameLength = 6 3190 prg.curName[15-1] = 'S' 3191 prg.curName[16-1] = 'H' 3192 prg.curName[17-1] = 'R' 3193 prg.curName[18-1] = 'I' 3194 prg.curName[19-1] = 'N' 3195 prg.curName[20-1] = 'K' 3196 prg.enterName(byte(parameterCode + 4)) 3197 3198 prg.nameLength = 7 3199 prg.curName[14-1] = 'X' 3200 prg.curName[15-1] = 'H' 3201 prg.curName[16-1] = 'E' 3202 prg.curName[17-1] = 'I' 3203 prg.curName[18-1] = 'G' 3204 prg.curName[19-1] = 'H' 3205 prg.curName[20-1] = 'T' 3206 prg.enterName(byte(parameterCode + 5)) 3207 3208 prg.nameLength = 4 3209 prg.curName[17-1] = 'Q' 3210 prg.curName[18-1] = 'U' 3211 prg.curName[19-1] = 'A' 3212 prg.curName[20-1] = 'D' 3213 prg.enterName(byte(parameterCode + 6)) 3214 3215 prg.nameLength = 10 3216 prg.curName[11-1] = 'E' 3217 prg.curName[12-1] = 'X' 3218 prg.curName[13-1] = 'T' 3219 prg.curName[14-1] = 'R' 3220 prg.curName[15-1] = 'A' 3221 prg.curName[16-1] = 'S' 3222 prg.curName[17-1] = 'P' 3223 prg.curName[18-1] = 'A' 3224 prg.curName[19-1] = 'C' 3225 prg.curName[20-1] = 'E' 3226 prg.enterName(byte(parameterCode + 7)) 3227 3228 prg.nameLength = 4 3229 prg.curName[17-1] = 'N' 3230 prg.curName[18-1] = 'U' 3231 prg.curName[19-1] = 'M' 3232 prg.curName[20-1] = '1' 3233 prg.enterName(byte(parameterCode + 8)) 3234 3235 prg.nameLength = 4 3236 prg.curName[17-1] = 'N' 3237 prg.curName[18-1] = 'U' 3238 prg.curName[19-1] = 'M' 3239 prg.curName[20-1] = '2' 3240 prg.enterName(byte(parameterCode + 9)) 3241 3242 prg.nameLength = 4 3243 prg.curName[17-1] = 'N' 3244 prg.curName[18-1] = 'U' 3245 prg.curName[19-1] = 'M' 3246 prg.curName[20-1] = '3' 3247 prg.enterName(byte(parameterCode + 10)) 3248 3249 prg.nameLength = 6 3250 prg.curName[15-1] = 'D' 3251 prg.curName[16-1] = 'E' 3252 prg.curName[17-1] = 'N' 3253 prg.curName[18-1] = 'O' 3254 prg.curName[19-1] = 'M' 3255 prg.curName[20-1] = '1' 3256 prg.enterName(byte(parameterCode + 11)) 3257 3258 prg.nameLength = 6 3259 prg.curName[15-1] = 'D' 3260 prg.curName[16-1] = 'E' 3261 prg.curName[17-1] = 'N' 3262 prg.curName[18-1] = 'O' 3263 prg.curName[19-1] = 'M' 3264 prg.curName[20-1] = '2' 3265 prg.enterName(byte(parameterCode + 12)) 3266 3267 prg.nameLength = 4 3268 prg.curName[17-1] = 'S' 3269 prg.curName[18-1] = 'U' 3270 prg.curName[19-1] = 'P' 3271 prg.curName[20-1] = '1' 3272 prg.enterName(byte(parameterCode + 13)) 3273 3274 prg.nameLength = 4 3275 prg.curName[17-1] = 'S' 3276 prg.curName[18-1] = 'U' 3277 prg.curName[19-1] = 'P' 3278 prg.curName[20-1] = '2' 3279 prg.enterName(byte(parameterCode + 14)) 3280 3281 prg.nameLength = 4 3282 prg.curName[17-1] = 'S' 3283 prg.curName[18-1] = 'U' 3284 prg.curName[19-1] = 'P' 3285 prg.curName[20-1] = '3' 3286 prg.enterName(byte(parameterCode + 15)) 3287 3288 prg.nameLength = 4 3289 prg.curName[17-1] = 'S' 3290 prg.curName[18-1] = 'U' 3291 prg.curName[19-1] = 'B' 3292 prg.curName[20-1] = '1' 3293 prg.enterName(byte(parameterCode + 16)) 3294 3295 prg.nameLength = 4 3296 prg.curName[17-1] = 'S' 3297 prg.curName[18-1] = 'U' 3298 prg.curName[19-1] = 'B' 3299 prg.curName[20-1] = '2' 3300 prg.enterName(byte(parameterCode + 17)) 3301 3302 prg.nameLength = 7 3303 prg.curName[14-1] = 'S' 3304 prg.curName[15-1] = 'U' 3305 prg.curName[16-1] = 'P' 3306 prg.curName[17-1] = 'D' 3307 prg.curName[18-1] = 'R' 3308 prg.curName[19-1] = 'O' 3309 prg.curName[20-1] = 'P' 3310 prg.enterName(byte(parameterCode + 18)) 3311 3312 prg.nameLength = 7 3313 prg.curName[14-1] = 'S' 3314 prg.curName[15-1] = 'U' 3315 prg.curName[16-1] = 'B' 3316 prg.curName[17-1] = 'D' 3317 prg.curName[18-1] = 'R' 3318 prg.curName[19-1] = 'O' 3319 prg.curName[20-1] = 'P' 3320 prg.enterName(byte(parameterCode + 19)) 3321 3322 prg.nameLength = 6 3323 prg.curName[15-1] = 'D' 3324 prg.curName[16-1] = 'E' 3325 prg.curName[17-1] = 'L' 3326 prg.curName[18-1] = 'I' 3327 prg.curName[19-1] = 'M' 3328 prg.curName[20-1] = '1' 3329 prg.enterName(byte(parameterCode + 20)) 3330 3331 prg.nameLength = 6 3332 prg.curName[15-1] = 'D' 3333 prg.curName[16-1] = 'E' 3334 prg.curName[17-1] = 'L' 3335 prg.curName[18-1] = 'I' 3336 prg.curName[19-1] = 'M' 3337 prg.curName[20-1] = '2' 3338 prg.enterName(byte(parameterCode + 21)) 3339 3340 prg.nameLength = 10 3341 prg.curName[11-1] = 'A' 3342 prg.curName[12-1] = 'X' 3343 prg.curName[13-1] = 'I' 3344 prg.curName[14-1] = 'S' 3345 prg.curName[15-1] = 'H' 3346 prg.curName[16-1] = 'E' 3347 prg.curName[17-1] = 'I' 3348 prg.curName[18-1] = 'G' 3349 prg.curName[19-1] = 'H' 3350 prg.curName[20-1] = 'T' 3351 prg.enterName(byte(parameterCode + 22)) 3352 3353 prg.nameLength = 20 3354 prg.curName[1-1] = 'D' 3355 prg.curName[2-1] = 'E' 3356 prg.curName[3-1] = 'F' 3357 prg.curName[4-1] = 'A' 3358 prg.curName[5-1] = 'U' 3359 prg.curName[6-1] = 'L' 3360 prg.curName[7-1] = 'T' 3361 prg.curName[8-1] = 'R' 3362 prg.curName[9-1] = 'U' 3363 prg.curName[10-1] = 'L' 3364 prg.curName[11-1] = 'E' 3365 prg.curName[12-1] = 'T' 3366 prg.curName[13-1] = 'H' 3367 prg.curName[14-1] = 'I' 3368 prg.curName[15-1] = 'C' 3369 prg.curName[16-1] = 'K' 3370 prg.curName[17-1] = 'N' 3371 prg.curName[18-1] = 'E' 3372 prg.curName[19-1] = 'S' 3373 prg.curName[20-1] = 'S' 3374 prg.enterName(byte(parameterCode + 8)) 3375 3376 prg.nameLength = 13 3377 prg.curName[8-1] = 'B' 3378 prg.curName[9-1] = 'I' 3379 prg.curName[10-1] = 'G' 3380 prg.curName[11-1] = 'O' 3381 prg.curName[12-1] = 'P' 3382 prg.curName[13-1] = 'S' 3383 prg.curName[14-1] = 'P' 3384 prg.curName[15-1] = 'A' 3385 prg.curName[16-1] = 'C' 3386 prg.curName[17-1] = 'I' 3387 prg.curName[18-1] = 'N' 3388 prg.curName[19-1] = 'G' 3389 prg.curName[20-1] = '1' 3390 prg.enterName(byte(parameterCode + 9)) 3391 3392 prg.nameLength = 13 3393 prg.curName[8-1] = 'B' 3394 prg.curName[9-1] = 'I' 3395 prg.curName[10-1] = 'G' 3396 prg.curName[11-1] = 'O' 3397 prg.curName[12-1] = 'P' 3398 prg.curName[13-1] = 'S' 3399 prg.curName[14-1] = 'P' 3400 prg.curName[15-1] = 'A' 3401 prg.curName[16-1] = 'C' 3402 prg.curName[17-1] = 'I' 3403 prg.curName[18-1] = 'N' 3404 prg.curName[19-1] = 'G' 3405 prg.curName[20-1] = '2' 3406 prg.enterName(byte(parameterCode + 10)) 3407 3408 prg.nameLength = 13 3409 prg.curName[8-1] = 'B' 3410 prg.curName[9-1] = 'I' 3411 prg.curName[10-1] = 'G' 3412 prg.curName[11-1] = 'O' 3413 prg.curName[12-1] = 'P' 3414 prg.curName[13-1] = 'S' 3415 prg.curName[14-1] = 'P' 3416 prg.curName[15-1] = 'A' 3417 prg.curName[16-1] = 'C' 3418 prg.curName[17-1] = 'I' 3419 prg.curName[18-1] = 'N' 3420 prg.curName[19-1] = 'G' 3421 prg.curName[20-1] = '3' 3422 prg.enterName(byte(parameterCode + 11)) 3423 3424 prg.nameLength = 13 3425 prg.curName[8-1] = 'B' 3426 prg.curName[9-1] = 'I' 3427 prg.curName[10-1] = 'G' 3428 prg.curName[11-1] = 'O' 3429 prg.curName[12-1] = 'P' 3430 prg.curName[13-1] = 'S' 3431 prg.curName[14-1] = 'P' 3432 prg.curName[15-1] = 'A' 3433 prg.curName[16-1] = 'C' 3434 prg.curName[17-1] = 'I' 3435 prg.curName[18-1] = 'N' 3436 prg.curName[19-1] = 'G' 3437 prg.curName[20-1] = '4' 3438 prg.enterName(byte(parameterCode + 12)) 3439 3440 prg.nameLength = 13 3441 prg.curName[8-1] = 'B' 3442 prg.curName[9-1] = 'I' 3443 prg.curName[10-1] = 'G' 3444 prg.curName[11-1] = 'O' 3445 prg.curName[12-1] = 'P' 3446 prg.curName[13-1] = 'S' 3447 prg.curName[14-1] = 'P' 3448 prg.curName[15-1] = 'A' 3449 prg.curName[16-1] = 'C' 3450 prg.curName[17-1] = 'I' 3451 prg.curName[18-1] = 'N' 3452 prg.curName[19-1] = 'G' 3453 prg.curName[20-1] = '5' 3454 prg.enterName(byte(parameterCode + 13)) 3455 3456 } 3457 3458 func (prg *prg) vplEnter() { 3459 prg.nameLength = 6 3460 prg.curName[15-1] = 'V' 3461 prg.curName[16-1] = 'T' 3462 prg.curName[17-1] = 'I' 3463 prg.curName[18-1] = 'T' 3464 prg.curName[19-1] = 'L' 3465 prg.curName[20-1] = 'E' 3466 prg.enterName(byte(virtualTitleCode)) 3467 3468 prg.nameLength = 7 3469 prg.curName[14-1] = 'M' 3470 prg.curName[15-1] = 'A' 3471 prg.curName[16-1] = 'P' 3472 prg.curName[17-1] = 'F' 3473 prg.curName[18-1] = 'O' 3474 prg.curName[19-1] = 'N' 3475 prg.curName[20-1] = 'T' 3476 prg.enterName(byte(mapFontCode)) 3477 3478 prg.nameLength = 3 3479 prg.curName[18-1] = 'M' 3480 prg.curName[19-1] = 'A' 3481 prg.curName[20-1] = 'P' 3482 prg.enterName(byte(mapCode)) 3483 3484 prg.nameLength = 8 3485 prg.curName[13-1] = 'F' 3486 prg.curName[14-1] = 'O' 3487 prg.curName[15-1] = 'N' 3488 prg.curName[16-1] = 'T' 3489 prg.curName[17-1] = 'N' 3490 prg.curName[18-1] = 'A' 3491 prg.curName[19-1] = 'M' 3492 prg.curName[20-1] = 'E' 3493 prg.enterName(byte(fontNameCode)) 3494 3495 prg.nameLength = 8 3496 prg.curName[13-1] = 'F' 3497 prg.curName[14-1] = 'O' 3498 prg.curName[15-1] = 'N' 3499 prg.curName[16-1] = 'T' 3500 prg.curName[17-1] = 'A' 3501 prg.curName[18-1] = 'R' 3502 prg.curName[19-1] = 'E' 3503 prg.curName[20-1] = 'A' 3504 prg.enterName(byte(fontAreaCode)) 3505 3506 prg.nameLength = 12 3507 prg.curName[9-1] = 'F' 3508 prg.curName[10-1] = 'O' 3509 prg.curName[11-1] = 'N' 3510 prg.curName[12-1] = 'T' 3511 prg.curName[13-1] = 'C' 3512 prg.curName[14-1] = 'H' 3513 prg.curName[15-1] = 'E' 3514 prg.curName[16-1] = 'C' 3515 prg.curName[17-1] = 'K' 3516 prg.curName[18-1] = 'S' 3517 prg.curName[19-1] = 'U' 3518 prg.curName[20-1] = 'M' 3519 prg.enterName(byte(fontChecksumCode)) 3520 3521 prg.nameLength = 6 3522 prg.curName[15-1] = 'F' 3523 prg.curName[16-1] = 'O' 3524 prg.curName[17-1] = 'N' 3525 prg.curName[18-1] = 'T' 3526 prg.curName[19-1] = 'A' 3527 prg.curName[20-1] = 'T' 3528 prg.enterName(byte(fontAtCode)) 3529 3530 prg.nameLength = 9 3531 prg.curName[12-1] = 'F' 3532 prg.curName[13-1] = 'O' 3533 prg.curName[14-1] = 'N' 3534 prg.curName[15-1] = 'T' 3535 prg.curName[16-1] = 'D' 3536 prg.curName[17-1] = 'S' 3537 prg.curName[18-1] = 'I' 3538 prg.curName[19-1] = 'Z' 3539 prg.curName[20-1] = 'E' 3540 prg.enterName(byte(fontDsizeCode)) 3541 3542 prg.nameLength = 10 3543 prg.curName[11-1] = 'S' 3544 prg.curName[12-1] = 'E' 3545 prg.curName[13-1] = 'L' 3546 prg.curName[14-1] = 'E' 3547 prg.curName[15-1] = 'C' 3548 prg.curName[16-1] = 'T' 3549 prg.curName[17-1] = 'F' 3550 prg.curName[18-1] = 'O' 3551 prg.curName[19-1] = 'N' 3552 prg.curName[20-1] = 'T' 3553 prg.enterName(byte(selectFontCode)) 3554 3555 prg.nameLength = 7 3556 prg.curName[14-1] = 'S' 3557 prg.curName[15-1] = 'E' 3558 prg.curName[16-1] = 'T' 3559 prg.curName[17-1] = 'C' 3560 prg.curName[18-1] = 'H' 3561 prg.curName[19-1] = 'A' 3562 prg.curName[20-1] = 'R' 3563 prg.enterName(byte(setCharCode)) 3564 3565 prg.nameLength = 7 3566 prg.curName[14-1] = 'S' 3567 prg.curName[15-1] = 'E' 3568 prg.curName[16-1] = 'T' 3569 prg.curName[17-1] = 'R' 3570 prg.curName[18-1] = 'U' 3571 prg.curName[19-1] = 'L' 3572 prg.curName[20-1] = 'E' 3573 prg.enterName(byte(setRuleCode)) 3574 3575 prg.nameLength = 9 3576 prg.curName[12-1] = 'M' 3577 prg.curName[13-1] = 'O' 3578 prg.curName[14-1] = 'V' 3579 prg.curName[15-1] = 'E' 3580 prg.curName[16-1] = 'R' 3581 prg.curName[17-1] = 'I' 3582 prg.curName[18-1] = 'G' 3583 prg.curName[19-1] = 'H' 3584 prg.curName[20-1] = 'T' 3585 prg.enterName(byte(moveRightCode)) 3586 3587 prg.nameLength = 8 3588 prg.curName[13-1] = 'M' 3589 prg.curName[14-1] = 'O' 3590 prg.curName[15-1] = 'V' 3591 prg.curName[16-1] = 'E' 3592 prg.curName[17-1] = 'L' 3593 prg.curName[18-1] = 'E' 3594 prg.curName[19-1] = 'F' 3595 prg.curName[20-1] = 'T' 3596 prg.enterName(byte(moveRightCode + 1)) 3597 3598 prg.nameLength = 8 3599 prg.curName[13-1] = 'M' 3600 prg.curName[14-1] = 'O' 3601 prg.curName[15-1] = 'V' 3602 prg.curName[16-1] = 'E' 3603 prg.curName[17-1] = 'D' 3604 prg.curName[18-1] = 'O' 3605 prg.curName[19-1] = 'W' 3606 prg.curName[20-1] = 'N' 3607 prg.enterName(byte(moveDownCode)) 3608 3609 prg.nameLength = 6 3610 prg.curName[15-1] = 'M' 3611 prg.curName[16-1] = 'O' 3612 prg.curName[17-1] = 'V' 3613 prg.curName[18-1] = 'E' 3614 prg.curName[19-1] = 'U' 3615 prg.curName[20-1] = 'P' 3616 prg.enterName(byte(moveDownCode + 1)) 3617 3618 prg.nameLength = 4 3619 prg.curName[17-1] = 'P' 3620 prg.curName[18-1] = 'U' 3621 prg.curName[19-1] = 'S' 3622 prg.curName[20-1] = 'H' 3623 prg.enterName(byte(pushCode)) 3624 3625 prg.nameLength = 3 3626 prg.curName[18-1] = 'P' 3627 prg.curName[19-1] = 'O' 3628 prg.curName[20-1] = 'P' 3629 prg.enterName(byte(popCode)) 3630 3631 prg.nameLength = 7 3632 prg.curName[14-1] = 'S' 3633 prg.curName[15-1] = 'P' 3634 prg.curName[16-1] = 'E' 3635 prg.curName[17-1] = 'C' 3636 prg.curName[18-1] = 'I' 3637 prg.curName[19-1] = 'A' 3638 prg.curName[20-1] = 'L' 3639 prg.enterName(byte(specialCode)) 3640 3641 prg.nameLength = 10 3642 prg.curName[11-1] = 'S' 3643 prg.curName[12-1] = 'P' 3644 prg.curName[13-1] = 'E' 3645 prg.curName[14-1] = 'C' 3646 prg.curName[15-1] = 'I' 3647 prg.curName[16-1] = 'A' 3648 prg.curName[17-1] = 'L' 3649 prg.curName[18-1] = 'H' 3650 prg.curName[19-1] = 'E' 3651 prg.curName[20-1] = 'X' 3652 prg.enterName(byte(specialHexCode)) 3653 3654 } 3655 3656 func (prg *prg) nameEnter() { 3657 prg.equiv[0] = byte(commentCode) // this is used after unknown keywords 3658 prg.nameLength = 8 3659 prg.curName[13-1] = 'C' 3660 prg.curName[14-1] = 'H' 3661 prg.curName[15-1] = 'E' 3662 prg.curName[16-1] = 'C' 3663 prg.curName[17-1] = 'K' 3664 prg.curName[18-1] = 'S' 3665 prg.curName[19-1] = 'U' 3666 prg.curName[20-1] = 'M' 3667 prg.enterName(byte(checkSumCode)) 3668 3669 prg.nameLength = 10 3670 prg.curName[11-1] = 'D' 3671 prg.curName[12-1] = 'E' 3672 prg.curName[13-1] = 'S' 3673 prg.curName[14-1] = 'I' 3674 prg.curName[15-1] = 'G' 3675 prg.curName[16-1] = 'N' 3676 prg.curName[17-1] = 'S' 3677 prg.curName[18-1] = 'I' 3678 prg.curName[19-1] = 'Z' 3679 prg.curName[20-1] = 'E' 3680 prg.enterName(byte(designSizeCode)) 3681 3682 prg.nameLength = 11 3683 prg.curName[10-1] = 'D' 3684 prg.curName[11-1] = 'E' 3685 prg.curName[12-1] = 'S' 3686 prg.curName[13-1] = 'I' 3687 prg.curName[14-1] = 'G' 3688 prg.curName[15-1] = 'N' 3689 prg.curName[16-1] = 'U' 3690 prg.curName[17-1] = 'N' 3691 prg.curName[18-1] = 'I' 3692 prg.curName[19-1] = 'T' 3693 prg.curName[20-1] = 'S' 3694 prg.enterName(byte(designUnitsCode)) 3695 3696 prg.nameLength = 12 3697 prg.curName[9-1] = 'C' 3698 prg.curName[10-1] = 'O' 3699 prg.curName[11-1] = 'D' 3700 prg.curName[12-1] = 'I' 3701 prg.curName[13-1] = 'N' 3702 prg.curName[14-1] = 'G' 3703 prg.curName[15-1] = 'S' 3704 prg.curName[16-1] = 'C' 3705 prg.curName[17-1] = 'H' 3706 prg.curName[18-1] = 'E' 3707 prg.curName[19-1] = 'M' 3708 prg.curName[20-1] = 'E' 3709 prg.enterName(byte(codingSchemeCode)) 3710 3711 prg.nameLength = 6 3712 prg.curName[15-1] = 'F' 3713 prg.curName[16-1] = 'A' 3714 prg.curName[17-1] = 'M' 3715 prg.curName[18-1] = 'I' 3716 prg.curName[19-1] = 'L' 3717 prg.curName[20-1] = 'Y' 3718 prg.enterName(byte(familyCode)) 3719 3720 prg.nameLength = 4 3721 prg.curName[17-1] = 'F' 3722 prg.curName[18-1] = 'A' 3723 prg.curName[19-1] = 'C' 3724 prg.curName[20-1] = 'E' 3725 prg.enterName(byte(faceCode)) 3726 3727 prg.nameLength = 16 3728 prg.curName[5-1] = 'S' 3729 prg.curName[6-1] = 'E' 3730 prg.curName[7-1] = 'V' 3731 prg.curName[8-1] = 'E' 3732 prg.curName[9-1] = 'N' 3733 prg.curName[10-1] = 'B' 3734 prg.curName[11-1] = 'I' 3735 prg.curName[12-1] = 'T' 3736 prg.curName[13-1] = 'S' 3737 prg.curName[14-1] = 'A' 3738 prg.curName[15-1] = 'F' 3739 prg.curName[16-1] = 'E' 3740 prg.curName[17-1] = 'F' 3741 prg.curName[18-1] = 'L' 3742 prg.curName[19-1] = 'A' 3743 prg.curName[20-1] = 'G' 3744 prg.enterName(byte(sevenBitSafeFlagCode)) 3745 3746 prg.nameLength = 6 3747 prg.curName[15-1] = 'H' 3748 prg.curName[16-1] = 'E' 3749 prg.curName[17-1] = 'A' 3750 prg.curName[18-1] = 'D' 3751 prg.curName[19-1] = 'E' 3752 prg.curName[20-1] = 'R' 3753 prg.enterName(byte(headerCode)) 3754 3755 prg.nameLength = 9 3756 prg.curName[12-1] = 'F' 3757 prg.curName[13-1] = 'O' 3758 prg.curName[14-1] = 'N' 3759 prg.curName[15-1] = 'T' 3760 prg.curName[16-1] = 'D' 3761 prg.curName[17-1] = 'I' 3762 prg.curName[18-1] = 'M' 3763 prg.curName[19-1] = 'E' 3764 prg.curName[20-1] = 'N' 3765 prg.enterName(byte(fontDimenCode)) 3766 3767 prg.nameLength = 8 3768 prg.curName[13-1] = 'L' 3769 prg.curName[14-1] = 'I' 3770 prg.curName[15-1] = 'G' 3771 prg.curName[16-1] = 'T' 3772 prg.curName[17-1] = 'A' 3773 prg.curName[18-1] = 'B' 3774 prg.curName[19-1] = 'L' 3775 prg.curName[20-1] = 'E' 3776 prg.enterName(byte(ligTableCode)) 3777 3778 prg.nameLength = 12 3779 prg.curName[9-1] = 'B' 3780 prg.curName[10-1] = 'O' 3781 prg.curName[11-1] = 'U' 3782 prg.curName[12-1] = 'N' 3783 prg.curName[13-1] = 'D' 3784 prg.curName[14-1] = 'A' 3785 prg.curName[15-1] = 'R' 3786 prg.curName[16-1] = 'Y' 3787 prg.curName[17-1] = 'C' 3788 prg.curName[18-1] = 'H' 3789 prg.curName[19-1] = 'A' 3790 prg.curName[20-1] = 'R' 3791 prg.enterName(byte(boundaryCharCode)) 3792 3793 prg.nameLength = 9 3794 prg.curName[12-1] = 'C' 3795 prg.curName[13-1] = 'H' 3796 prg.curName[14-1] = 'A' 3797 prg.curName[15-1] = 'R' 3798 prg.curName[16-1] = 'A' 3799 prg.curName[17-1] = 'C' 3800 prg.curName[18-1] = 'T' 3801 prg.curName[19-1] = 'E' 3802 prg.curName[20-1] = 'R' 3803 prg.enterName(byte(characterCode)) 3804 3805 prg.nameLength = 9 3806 prg.curName[12-1] = 'P' 3807 prg.curName[13-1] = 'A' 3808 prg.curName[14-1] = 'R' 3809 prg.curName[15-1] = 'A' 3810 prg.curName[16-1] = 'M' 3811 prg.curName[17-1] = 'E' 3812 prg.curName[18-1] = 'T' 3813 prg.curName[19-1] = 'E' 3814 prg.curName[20-1] = 'R' 3815 prg.enterName(byte(parameterCode)) 3816 3817 prg.nameLength = 6 3818 prg.curName[15-1] = 'C' 3819 prg.curName[16-1] = 'H' 3820 prg.curName[17-1] = 'A' 3821 prg.curName[18-1] = 'R' 3822 prg.curName[19-1] = 'W' 3823 prg.curName[20-1] = 'D' 3824 prg.enterName(byte(charWdCode)) 3825 3826 prg.nameLength = 6 3827 prg.curName[15-1] = 'C' 3828 prg.curName[16-1] = 'H' 3829 prg.curName[17-1] = 'A' 3830 prg.curName[18-1] = 'R' 3831 prg.curName[19-1] = 'H' 3832 prg.curName[20-1] = 'T' 3833 prg.enterName(byte(charHtCode)) 3834 3835 prg.nameLength = 6 3836 prg.curName[15-1] = 'C' 3837 prg.curName[16-1] = 'H' 3838 prg.curName[17-1] = 'A' 3839 prg.curName[18-1] = 'R' 3840 prg.curName[19-1] = 'D' 3841 prg.curName[20-1] = 'P' 3842 prg.enterName(byte(charDpCode)) 3843 3844 prg.nameLength = 6 3845 prg.curName[15-1] = 'C' 3846 prg.curName[16-1] = 'H' 3847 prg.curName[17-1] = 'A' 3848 prg.curName[18-1] = 'R' 3849 prg.curName[19-1] = 'I' 3850 prg.curName[20-1] = 'C' 3851 prg.enterName(byte(charIcCode)) 3852 3853 prg.nameLength = 10 3854 prg.curName[11-1] = 'N' 3855 prg.curName[12-1] = 'E' 3856 prg.curName[13-1] = 'X' 3857 prg.curName[14-1] = 'T' 3858 prg.curName[15-1] = 'L' 3859 prg.curName[16-1] = 'A' 3860 prg.curName[17-1] = 'R' 3861 prg.curName[18-1] = 'G' 3862 prg.curName[19-1] = 'E' 3863 prg.curName[20-1] = 'R' 3864 prg.enterName(byte(nextLargerCode)) 3865 3866 prg.nameLength = 7 3867 prg.curName[14-1] = 'V' 3868 prg.curName[15-1] = 'A' 3869 prg.curName[16-1] = 'R' 3870 prg.curName[17-1] = 'C' 3871 prg.curName[18-1] = 'H' 3872 prg.curName[19-1] = 'A' 3873 prg.curName[20-1] = 'R' 3874 prg.enterName(byte(varCharCode)) 3875 3876 prg.nameLength = 3 3877 prg.curName[18-1] = 'T' 3878 prg.curName[19-1] = 'O' 3879 prg.curName[20-1] = 'P' 3880 prg.enterName(byte(varCharCode + 1)) 3881 3882 prg.nameLength = 3 3883 prg.curName[18-1] = 'M' 3884 prg.curName[19-1] = 'I' 3885 prg.curName[20-1] = 'D' 3886 prg.enterName(byte(varCharCode + 2)) 3887 3888 prg.nameLength = 3 3889 prg.curName[18-1] = 'B' 3890 prg.curName[19-1] = 'O' 3891 prg.curName[20-1] = 'T' 3892 prg.enterName(byte(varCharCode + 3)) 3893 3894 prg.nameLength = 3 3895 prg.curName[18-1] = 'R' 3896 prg.curName[19-1] = 'E' 3897 prg.curName[20-1] = 'P' 3898 prg.enterName(byte(varCharCode + 4)) 3899 3900 prg.nameLength = 3 3901 prg.curName[18-1] = 'E' 3902 prg.curName[19-1] = 'X' 3903 prg.curName[20-1] = 'T' 3904 prg.enterName(byte(varCharCode + 4)) // compatibility with older \.[PL] format 3905 prg.nameLength = 7 3906 prg.curName[14-1] = 'C' 3907 prg.curName[15-1] = 'O' 3908 prg.curName[16-1] = 'M' 3909 prg.curName[17-1] = 'M' 3910 prg.curName[18-1] = 'E' 3911 prg.curName[19-1] = 'N' 3912 prg.curName[20-1] = 'T' 3913 prg.enterName(byte(commentCode)) 3914 3915 prg.nameLength = 5 3916 prg.curName[16-1] = 'L' 3917 prg.curName[17-1] = 'A' 3918 prg.curName[18-1] = 'B' 3919 prg.curName[19-1] = 'E' 3920 prg.curName[20-1] = 'L' 3921 prg.enterName(byte(labelCode)) 3922 3923 prg.nameLength = 4 3924 prg.curName[17-1] = 'S' 3925 prg.curName[18-1] = 'T' 3926 prg.curName[19-1] = 'O' 3927 prg.curName[20-1] = 'P' 3928 prg.enterName(byte(stopCode)) 3929 3930 prg.nameLength = 4 3931 prg.curName[17-1] = 'S' 3932 prg.curName[18-1] = 'K' 3933 prg.curName[19-1] = 'I' 3934 prg.curName[20-1] = 'P' 3935 prg.enterName(byte(skipCode)) 3936 3937 prg.nameLength = 3 3938 prg.curName[18-1] = 'K' 3939 prg.curName[19-1] = 'R' 3940 prg.curName[20-1] = 'N' 3941 prg.enterName(byte(krnCode)) 3942 3943 prg.nameLength = 3 3944 prg.curName[18-1] = 'L' 3945 prg.curName[19-1] = 'I' 3946 prg.curName[20-1] = 'G' 3947 prg.enterName(byte(ligCode)) 3948 3949 prg.nameLength = 4 3950 prg.curName[17-1] = '/' 3951 prg.curName[18-1] = 'L' 3952 prg.curName[19-1] = 'I' 3953 prg.curName[20-1] = 'G' 3954 prg.enterName(byte(ligCode + 2)) 3955 3956 prg.nameLength = 5 3957 prg.curName[16-1] = '/' 3958 prg.curName[17-1] = 'L' 3959 prg.curName[18-1] = 'I' 3960 prg.curName[19-1] = 'G' 3961 prg.curName[20-1] = '>' 3962 prg.enterName(byte(ligCode + 6)) 3963 3964 prg.nameLength = 4 3965 prg.curName[17-1] = 'L' 3966 prg.curName[18-1] = 'I' 3967 prg.curName[19-1] = 'G' 3968 prg.curName[20-1] = '/' 3969 prg.enterName(byte(ligCode + 1)) 3970 3971 prg.nameLength = 5 3972 prg.curName[16-1] = 'L' 3973 prg.curName[17-1] = 'I' 3974 prg.curName[18-1] = 'G' 3975 prg.curName[19-1] = '/' 3976 prg.curName[20-1] = '>' 3977 prg.enterName(byte(ligCode + 5)) 3978 3979 prg.nameLength = 5 3980 prg.curName[16-1] = '/' 3981 prg.curName[17-1] = 'L' 3982 prg.curName[18-1] = 'I' 3983 prg.curName[19-1] = 'G' 3984 prg.curName[20-1] = '/' 3985 prg.enterName(byte(ligCode + 3)) 3986 3987 prg.nameLength = 6 3988 prg.curName[15-1] = '/' 3989 prg.curName[16-1] = 'L' 3990 prg.curName[17-1] = 'I' 3991 prg.curName[18-1] = 'G' 3992 prg.curName[19-1] = '/' 3993 prg.curName[20-1] = '>' 3994 prg.enterName(byte(ligCode + 7)) 3995 3996 prg.nameLength = 7 3997 prg.curName[14-1] = '/' 3998 prg.curName[15-1] = 'L' 3999 prg.curName[16-1] = 'I' 4000 prg.curName[17-1] = 'G' 4001 prg.curName[18-1] = '/' 4002 prg.curName[19-1] = '>' 4003 prg.curName[20-1] = '>' 4004 prg.enterName(byte(ligCode + 11)) 4005 4006 prg.vplEnter() 4007 prg.paramEnter() 4008 } 4009 4010 func (prg *prg) readLigKern() { 4011 var ( 4012 krnPtr/* 0..maxKerns */ uint16 // an index into |kern| 4013 c byte // runs through all character codes 4014 ) 4015 { 4016 prg.lkStepEnded = false 4017 for prg.level == 1 { 4018 for int32(prg.curChar) == ' ' { 4019 prg.getNext() 4020 } 4021 if int32(prg.curChar) == '(' { 4022 prg.getName() 4023 if int32(prg.curCode) == commentCode { 4024 prg.skipToEndOfItem() 4025 } else if int32(prg.curCode) < labelCode { 4026 { 4027 if int32(prg.charsOnLine) > 0 { 4028 prg.stdout.Writeln(" ") 4029 } 4030 prg.stdout.Write("This property name doesn't belong in a LIGTABLE list") 4031 prg.showErrorContext() 4032 } 4033 prg.skipToEndOfItem() 4034 } else { 4035 switch prg.curCode { 4036 case labelCode: 4037 // Read a label step 4038 for int32(prg.curChar) == ' ' { 4039 prg.getNext() 4040 } 4041 if int32(prg.curChar) == 'B' { 4042 prg.charRemainder[256] = prg.nl 4043 for { 4044 prg.getNext() 4045 if int32(prg.curChar) == '(' || int32(prg.curChar) == ')' { 4046 break 4047 } 4048 } // \.[LABEL BOUNDARYCHAR] 4049 } else { 4050 { 4051 if int32(prg.curChar) > ')' || int32(prg.curChar) < '(' { 4052 prg.loc = byte(int32(prg.loc) - 1) 4053 } 4054 } 4055 c = prg.getByte() 4056 prg.checkTag(c) 4057 prg.charTag[c] = byte(ligTag) 4058 prg.charRemainder[c] = prg.nl 4059 } 4060 if int32(prg.minNl) <= int32(prg.nl) { 4061 prg.minNl = uint16(int32(prg.nl) + 1) 4062 } 4063 prg.lkStepEnded = false 4064 4065 case stopCode: 4066 // Read a stop step 4067 if !prg.lkStepEnded { 4068 if int32(prg.charsOnLine) > 0 { 4069 prg.stdout.Writeln(" ") 4070 } 4071 prg.stdout.Write("STOP must follow LIG or KRN") 4072 prg.showErrorContext() 4073 } else { 4074 prg.ligKern[int32(prg.nl)-1].b0 = byte(stopFlag) 4075 prg.lkStepEnded = false 4076 } 4077 4078 case skipCode: 4079 // Read a skip step 4080 if !prg.lkStepEnded { 4081 if int32(prg.charsOnLine) > 0 { 4082 prg.stdout.Writeln(" ") 4083 } 4084 prg.stdout.Write("SKIP must follow LIG or KRN") 4085 prg.showErrorContext() 4086 } else { 4087 c = prg.getByte() 4088 if int32(c) >= 128 { 4089 if int32(prg.charsOnLine) > 0 { 4090 prg.stdout.Writeln(" ") 4091 } 4092 prg.stdout.Write("Maximum SKIP amount is 127") 4093 prg.showErrorContext() 4094 } else if int32(prg.nl)+int32(c) >= maxLigSteps { 4095 if int32(prg.charsOnLine) > 0 { 4096 prg.stdout.Writeln(" ") 4097 } 4098 prg.stdout.Write("Sorry, LIGTABLE too long for me to handle") 4099 prg.showErrorContext() 4100 } else { 4101 prg.ligKern[int32(prg.nl)-1].b0 = c 4102 if int32(prg.minNl) <= int32(prg.nl)+int32(c) { 4103 prg.minNl = uint16(int32(prg.nl) + int32(c) + 1) 4104 } 4105 } 4106 prg.lkStepEnded = false 4107 } 4108 4109 case krnCode: 4110 // Read a kerning step 4111 prg.ligKern[prg.nl].b0 = 0 4112 prg.ligKern[prg.nl].b1 = prg.getByte() 4113 prg.kern[prg.nk] = prg.getFix() 4114 krnPtr = 0 4115 for prg.kern[krnPtr] != prg.kern[prg.nk] { 4116 krnPtr = uint16(int32(krnPtr) + 1) 4117 } 4118 if int32(krnPtr) == int32(prg.nk) { 4119 if int32(prg.nk) < maxKerns { 4120 prg.nk = uint16(int32(prg.nk) + 1) 4121 } else { 4122 { 4123 if int32(prg.charsOnLine) > 0 { 4124 prg.stdout.Writeln(" ") 4125 } 4126 prg.stdout.Write("Sorry, too many different kerns for me to handle") 4127 prg.showErrorContext() 4128 } 4129 // \xref[Sorry, too many different kerns...] 4130 krnPtr = uint16(int32(krnPtr) - 1) 4131 } 4132 } 4133 prg.ligKern[prg.nl].b2 = byte(kernFlag + int32(krnPtr)/256) 4134 prg.ligKern[prg.nl].b3 = byte(int32(krnPtr) % 256) 4135 if int32(prg.nl) >= maxLigSteps-1 { 4136 if int32(prg.charsOnLine) > 0 { 4137 prg.stdout.Writeln(" ") 4138 } 4139 prg.stdout.Write("Sorry, LIGTABLE too long for me to handle") 4140 prg.showErrorContext() 4141 } else { 4142 prg.nl = uint16(int32(prg.nl) + 1) 4143 } 4144 prg.lkStepEnded = true 4145 4146 case ligCode, ligCode + 1, ligCode + 2, ligCode + 3, 4147 ligCode + 5, ligCode + 6, ligCode + 7, ligCode + 11: 4148 // Read a ligature step 4149 prg.ligKern[prg.nl].b0 = 0 4150 prg.ligKern[prg.nl].b2 = byte(int32(prg.curCode) - ligCode) 4151 prg.ligKern[prg.nl].b1 = prg.getByte() 4152 prg.ligKern[prg.nl].b3 = prg.getByte() 4153 if int32(prg.nl) >= maxLigSteps-1 { 4154 if int32(prg.charsOnLine) > 0 { 4155 prg.stdout.Writeln(" ") 4156 } 4157 prg.stdout.Write("Sorry, LIGTABLE too long for me to handle") 4158 prg.showErrorContext() 4159 } else { 4160 prg.nl = uint16(int32(prg.nl) + 1) 4161 } 4162 prg.lkStepEnded = true 4163 4164 } // there are no other cases |>=label_code| 4165 prg.finishTheProperty() 4166 } 4167 } else if int32(prg.curChar) == ')' { 4168 prg.skipToEndOfItem() 4169 } else { 4170 prg.junkError() 4171 } 4172 } 4173 { 4174 prg.loc = byte(int32(prg.loc) - 1) 4175 prg.level = prg.level + 1 4176 prg.curChar = ')' 4177 } 4178 } 4179 } 4180 4181 func (prg *prg) readCharInfo() { 4182 var ( 4183 c byte // the char 4184 ) 4185 { 4186 c = prg.getByte() // read the character code that is being specified 4187 4188 // Print |c| in octal notation 4189 { 4190 if int32(prg.charsOnLine) == 8 { 4191 prg.stdout.Writeln(" ") 4192 prg.charsOnLine = 1 4193 } else { 4194 if int32(prg.charsOnLine) > 0 { 4195 prg.stdout.Write(" ") 4196 } 4197 prg.charsOnLine = byte(int32(prg.charsOnLine) + 1) 4198 } 4199 prg.printOctal(c) // progress report 4200 } 4201 for prg.level == 1 { 4202 for int32(prg.curChar) == ' ' { 4203 prg.getNext() 4204 } 4205 if int32(prg.curChar) == '(' { 4206 prg.getName() 4207 if int32(prg.curCode) == commentCode { 4208 prg.skipToEndOfItem() 4209 } else if int32(prg.curCode) < charWdCode || int32(prg.curCode) > varCharCode { 4210 { 4211 if int32(prg.charsOnLine) > 0 { 4212 prg.stdout.Writeln(" ") 4213 } 4214 prg.stdout.Write("This property name doesn't belong in a CHARACTER list") 4215 prg.showErrorContext() 4216 } 4217 prg.skipToEndOfItem() 4218 } else { 4219 switch prg.curCode { 4220 case charWdCode: 4221 prg.charWd[c] = prg.sortIn(pointer(width), prg.getFix()) 4222 case charHtCode: 4223 prg.charHt[c] = prg.sortIn(pointer(height), prg.getFix()) 4224 case charDpCode: 4225 prg.charDp[c] = prg.sortIn(pointer(depth), prg.getFix()) 4226 case charIcCode: 4227 prg.charIc[c] = prg.sortIn(pointer(italic), prg.getFix()) 4228 case nextLargerCode: 4229 prg.checkTag(c) 4230 prg.charTag[c] = byte(listTag) 4231 prg.charRemainder[c] = uint16(prg.getByte()) 4232 4233 case mapCode: 4234 prg.readPacket(c) 4235 case varCharCode: 4236 // Read an extensible recipe for |c| 4237 if int32(prg.ne) == 256 { 4238 if int32(prg.charsOnLine) > 0 { 4239 prg.stdout.Writeln(" ") 4240 } 4241 prg.stdout.Write("At most 256 VARCHAR specs are allowed") 4242 prg.showErrorContext() 4243 } else { 4244 prg.checkTag(c) 4245 prg.charTag[c] = byte(extTag) 4246 prg.charRemainder[c] = prg.ne 4247 4248 prg.exten[prg.ne] = prg.zeroBytes 4249 for prg.level == 2 { 4250 for int32(prg.curChar) == ' ' { 4251 prg.getNext() 4252 } 4253 if int32(prg.curChar) == '(' { 4254 prg.getName() 4255 if int32(prg.curCode) == commentCode { 4256 prg.skipToEndOfItem() 4257 } else if int32(prg.curCode) < varCharCode+1 || int32(prg.curCode) > varCharCode+4 { 4258 { 4259 if int32(prg.charsOnLine) > 0 { 4260 prg.stdout.Writeln(" ") 4261 } 4262 prg.stdout.Write("This property name doesn't belong in a VARCHAR list") 4263 prg.showErrorContext() 4264 } 4265 prg.skipToEndOfItem() 4266 } else { 4267 switch int32(prg.curCode) - (varCharCode + 1) { 4268 case 0: 4269 prg.exten[prg.ne].b0 = prg.getByte() 4270 case 1: 4271 prg.exten[prg.ne].b1 = prg.getByte() 4272 case 2: 4273 prg.exten[prg.ne].b2 = prg.getByte() 4274 case 3: 4275 prg.exten[prg.ne].b3 = prg.getByte() 4276 } 4277 4278 prg.finishTheProperty() 4279 } 4280 } else if int32(prg.curChar) == ')' { 4281 prg.skipToEndOfItem() 4282 } else { 4283 prg.junkError() 4284 } 4285 } 4286 prg.ne = uint16(int32(prg.ne) + 1) 4287 { 4288 prg.loc = byte(int32(prg.loc) - 1) 4289 prg.level = prg.level + 1 4290 prg.curChar = ')' 4291 } 4292 } 4293 4294 } 4295 4296 prg.finishTheProperty() 4297 } 4298 } else if int32(prg.curChar) == ')' { 4299 prg.skipToEndOfItem() 4300 } else { 4301 prg.junkError() 4302 } 4303 } 4304 if int32(prg.charWd[c]) == 0 { 4305 prg.charWd[c] = prg.sortIn(pointer(width), fixWord(0)) 4306 } // legitimatize |c| 4307 { 4308 prg.loc = byte(int32(prg.loc) - 1) 4309 prg.level = prg.level + 1 4310 prg.curChar = ')' 4311 } 4312 } 4313 } 4314 4315 func (prg *prg) readInput() { 4316 var ( 4317 c byte // header or parameter index 4318 ) 4319 prg.curChar = ' ' 4320 for { 4321 for int32(prg.curChar) == ' ' { 4322 prg.getNext() 4323 } 4324 if int32(prg.curChar) == '(' { 4325 prg.getName() 4326 if int32(prg.curCode) == commentCode { 4327 prg.skipToEndOfItem() 4328 } else if int32(prg.curCode) > characterCode { 4329 { 4330 if int32(prg.charsOnLine) > 0 { 4331 prg.stdout.Writeln(" ") 4332 } 4333 prg.stdout.Write("This property name doesn't belong on the outer level") 4334 prg.showErrorContext() 4335 } 4336 prg.skipToEndOfItem() 4337 } else { 4338 switch prg.curCode { 4339 case checkSumCode: 4340 prg.checkSumSpecified = true 4341 prg.readFourBytes(headerIndex(checkSumLoc)) 4342 4343 case designSizeCode: 4344 // Read the design size 4345 prg.nextD = prg.getFix() 4346 if prg.nextD < 04000000 { 4347 if int32(prg.charsOnLine) > 0 { 4348 prg.stdout.Writeln(" ") 4349 } 4350 prg.stdout.Write("The design size must be at least 1") 4351 prg.showErrorContext() 4352 } else { 4353 prg.designSize = prg.nextD 4354 } 4355 4356 case designUnitsCode: 4357 // Read the design units 4358 prg.nextD = prg.getFix() 4359 if prg.nextD <= 0 { 4360 if int32(prg.charsOnLine) > 0 { 4361 prg.stdout.Writeln(" ") 4362 } 4363 prg.stdout.Write("The number of units per design size must be positive") 4364 prg.showErrorContext() 4365 } else if prg.frozenDu { 4366 if int32(prg.charsOnLine) > 0 { 4367 prg.stdout.Writeln(" ") 4368 } 4369 prg.stdout.Write("Sorry, it's too late to change the design units") 4370 prg.showErrorContext() 4371 } else { 4372 prg.designUnits = prg.nextD 4373 } 4374 4375 case codingSchemeCode: 4376 prg.readBcpl(headerIndex(codingSchemeLoc), byte(40)) 4377 case familyCode: 4378 prg.readBcpl(headerIndex(familyLoc), byte(20)) 4379 case faceCode: 4380 prg.headerBytes[faceLoc] = prg.getByte() 4381 case sevenBitSafeFlagCode: 4382 // Read the seven-bit-safe flag 4383 for int32(prg.curChar) == ' ' { 4384 prg.getNext() 4385 } 4386 if int32(prg.curChar) == 'T' { 4387 prg.sevenBitSafeFlag = true 4388 } else if int32(prg.curChar) == 'F' { 4389 prg.sevenBitSafeFlag = false 4390 } else { 4391 if int32(prg.charsOnLine) > 0 { 4392 prg.stdout.Writeln(" ") 4393 } 4394 prg.stdout.Write("The flag value should be \"TRUE\" or \"FALSE\"") 4395 prg.showErrorContext() 4396 } 4397 // \xref[The flag value should be...] 4398 for { 4399 prg.getNext() 4400 if int32(prg.curChar) == '(' || int32(prg.curChar) == ')' { 4401 break 4402 } 4403 } 4404 4405 case headerCode: 4406 // Read an indexed header word 4407 c = prg.getByte() 4408 if int32(c) < 18 { 4409 { 4410 if int32(prg.charsOnLine) > 0 { 4411 prg.stdout.Writeln(" ") 4412 } 4413 prg.stdout.Write("HEADER indices should be 18 or more") 4414 prg.showErrorContext() 4415 } 4416 for { 4417 prg.getNext() 4418 if int32(prg.curChar) == '(' || int32(prg.curChar) == ')' { 4419 break 4420 } 4421 } 4422 } else if 4*int32(c)+4 > maxHeaderBytes { 4423 { 4424 if int32(prg.charsOnLine) > 0 { 4425 prg.stdout.Writeln(" ") 4426 } 4427 prg.stdout.Write("This HEADER index is too big for my present table size") 4428 prg.showErrorContext() 4429 } 4430 for { 4431 prg.getNext() 4432 if int32(prg.curChar) == '(' || int32(prg.curChar) == ')' { 4433 break 4434 } 4435 } 4436 } else { 4437 for int32(prg.headerPtr) < 4*int32(c)+4 { 4438 prg.headerBytes[prg.headerPtr] = 0 4439 prg.headerPtr = byte(int32(prg.headerPtr) + 1) 4440 } 4441 prg.readFourBytes(headerIndex(4 * int32(c))) 4442 } 4443 4444 case fontDimenCode: 4445 // Read font parameter list 4446 for prg.level == 1 { 4447 for int32(prg.curChar) == ' ' { 4448 prg.getNext() 4449 } 4450 if int32(prg.curChar) == '(' { 4451 prg.getName() 4452 if int32(prg.curCode) == commentCode { 4453 prg.skipToEndOfItem() 4454 } else if int32(prg.curCode) < parameterCode || int32(prg.curCode) >= charWdCode { 4455 { 4456 if int32(prg.charsOnLine) > 0 { 4457 prg.stdout.Writeln(" ") 4458 } 4459 prg.stdout.Write("This property name doesn't belong in a FONTDIMEN list") 4460 prg.showErrorContext() 4461 } 4462 prg.skipToEndOfItem() 4463 } else { 4464 if int32(prg.curCode) == parameterCode { 4465 c = prg.getByte() 4466 } else { 4467 c = byte(int32(prg.curCode) - parameterCode) 4468 } 4469 if int32(c) == 0 { 4470 { 4471 if int32(prg.charsOnLine) > 0 { 4472 prg.stdout.Writeln(" ") 4473 } 4474 prg.stdout.Write("PARAMETER index must not be zero") 4475 prg.showErrorContext() 4476 } 4477 prg.skipToEndOfItem() 4478 } else if int32(c) > maxParamWords { 4479 { 4480 if int32(prg.charsOnLine) > 0 { 4481 prg.stdout.Writeln(" ") 4482 } 4483 prg.stdout.Write("This PARAMETER index is too big for my present table size") 4484 prg.showErrorContext() 4485 } 4486 prg.skipToEndOfItem() 4487 } else { 4488 for int32(prg.np) < int32(c) { 4489 prg.np = byte(int32(prg.np) + 1) 4490 prg.param[prg.np-1] = 0 4491 } 4492 prg.param[c-1] = prg.getFix() 4493 prg.finishTheProperty() 4494 } 4495 } 4496 } else if int32(prg.curChar) == ')' { 4497 prg.skipToEndOfItem() 4498 } else { 4499 prg.junkError() 4500 } 4501 } 4502 { 4503 prg.loc = byte(int32(prg.loc) - 1) 4504 prg.level = prg.level + 1 4505 prg.curChar = ')' 4506 } 4507 4508 case ligTableCode: 4509 prg.readLigKern() 4510 case boundaryCharCode: 4511 prg.bchar = uint16(prg.getByte()) 4512 case virtualTitleCode: 4513 prg.vtitleStart = prg.vfPtr 4514 prg.copyToEndOfItem() 4515 if int32(prg.vfPtr) > int32(prg.vtitleStart)+255 { 4516 { 4517 if int32(prg.charsOnLine) > 0 { 4518 prg.stdout.Writeln(" ") 4519 } 4520 prg.stdout.Write("VTITLE clipped to 255 characters") 4521 prg.showErrorContext() 4522 } 4523 prg.vtitleLength = 255 4524 // \xref[VTITLE clipped...] 4525 } else { 4526 prg.vtitleLength = byte(int32(prg.vfPtr) - int32(prg.vtitleStart)) 4527 } 4528 4529 case mapFontCode: 4530 // Read a local font list 4531 prg.getFourBytes() 4532 prg.fontNumber[prg.fontPtr] = prg.curBytes 4533 prg.curFont = 0 4534 for int32(prg.fontNumber[prg.curFont].b3) != int32(prg.fontNumber[prg.fontPtr].b3) || int32(prg.fontNumber[prg.curFont].b2) != int32(prg.fontNumber[prg.fontPtr].b2) || int32(prg.fontNumber[prg.curFont].b1) != int32(prg.fontNumber[prg.fontPtr].b1) || int32(prg.fontNumber[prg.curFont].b0) != int32(prg.fontNumber[prg.fontPtr].b0) { 4535 prg.curFont = uint16(int32(prg.curFont) + 1) 4536 } 4537 if int32(prg.curFont) == int32(prg.fontPtr) { 4538 if int32(prg.fontPtr) < 256 { 4539 prg.fontPtr = uint16(int32(prg.fontPtr) + 1) 4540 prg.fnameStart[prg.curFont] = uint16(vfSize) 4541 prg.fnameLength[prg.curFont] = 4 // \.[NULL] 4542 prg.fareaStart[prg.curFont] = uint16(vfSize) 4543 prg.fareaLength[prg.curFont] = 0 4544 prg.fontChecksum[prg.curFont] = prg.zeroBytes 4545 prg.fontAt[prg.curFont] = 04000000 // denotes design size of this virtual font 4546 prg.fontDsize[prg.curFont] = 050000000 // the |fix_word| for 10 4547 } else { 4548 if int32(prg.charsOnLine) > 0 { 4549 prg.stdout.Writeln(" ") 4550 } 4551 prg.stdout.Write("I can handle only 256 different mapfonts") 4552 prg.showErrorContext() 4553 } 4554 } 4555 // \xref[I can handle only 256...] 4556 if int32(prg.curFont) == int32(prg.fontPtr) { 4557 prg.skipToEndOfItem() 4558 } else { 4559 for prg.level == 1 { 4560 for int32(prg.curChar) == ' ' { 4561 prg.getNext() 4562 } 4563 if int32(prg.curChar) == '(' { 4564 prg.getName() 4565 if int32(prg.curCode) == commentCode { 4566 prg.skipToEndOfItem() 4567 } else if int32(prg.curCode) < fontNameCode || int32(prg.curCode) > fontDsizeCode { 4568 { 4569 if int32(prg.charsOnLine) > 0 { 4570 prg.stdout.Writeln(" ") 4571 } 4572 prg.stdout.Write("This property name doesn't belong in a MAPFONT list") 4573 prg.showErrorContext() 4574 } 4575 prg.skipToEndOfItem() 4576 } else { 4577 switch prg.curCode { 4578 case fontNameCode: 4579 // Read a local font name 4580 prg.fnameStart[prg.curFont] = prg.vfPtr 4581 prg.copyToEndOfItem() 4582 if int32(prg.vfPtr) > int32(prg.fnameStart[prg.curFont])+255 { 4583 { 4584 if int32(prg.charsOnLine) > 0 { 4585 prg.stdout.Writeln(" ") 4586 } 4587 prg.stdout.Write("FONTNAME clipped to 255 characters") 4588 prg.showErrorContext() 4589 } 4590 // \xref[FONTNAME clipped...] 4591 prg.fnameLength[prg.curFont] = 255 4592 } else { 4593 prg.fnameLength[prg.curFont] = byte(int32(prg.vfPtr) - int32(prg.fnameStart[prg.curFont])) 4594 } 4595 4596 case fontAreaCode: 4597 // Read a local font area 4598 prg.fareaStart[prg.curFont] = prg.vfPtr 4599 prg.copyToEndOfItem() 4600 if int32(prg.vfPtr) > int32(prg.fareaStart[prg.curFont])+255 { 4601 { 4602 if int32(prg.charsOnLine) > 0 { 4603 prg.stdout.Writeln(" ") 4604 } 4605 prg.stdout.Write("FONTAREA clipped to 255 characters") 4606 prg.showErrorContext() 4607 } 4608 // \xref[FONTAREA clipped...] 4609 prg.fareaLength[prg.curFont] = 255 4610 } else { 4611 prg.fareaLength[prg.curFont] = byte(int32(prg.vfPtr) - int32(prg.fareaStart[prg.curFont])) 4612 } 4613 4614 case fontChecksumCode: 4615 prg.getFourBytes() 4616 prg.fontChecksum[prg.curFont] = prg.curBytes 4617 4618 case fontAtCode: 4619 prg.frozenDu = true 4620 if prg.designUnits == 04000000 { 4621 prg.fontAt[prg.curFont] = prg.getFix() 4622 } else { 4623 prg.fontAt[prg.curFont] = round(float64(prg.getFix()) / float64(prg.designUnits) * 1048576.0) 4624 } 4625 4626 case fontDsizeCode: 4627 prg.fontDsize[prg.curFont] = prg.getFix() 4628 } // there are no other cases 4629 prg.finishTheProperty() 4630 } 4631 } else if int32(prg.curChar) == ')' { 4632 prg.skipToEndOfItem() 4633 } else { 4634 prg.junkError() 4635 } 4636 } 4637 } 4638 { 4639 prg.loc = byte(int32(prg.loc) - 1) 4640 prg.level = prg.level + 1 4641 prg.curChar = ')' 4642 } 4643 4644 case characterCode: 4645 prg.readCharInfo() 4646 } 4647 prg.finishTheProperty() 4648 } 4649 } else if int32(prg.curChar) == ')' && !prg.inputHasEnded { 4650 { 4651 if int32(prg.charsOnLine) > 0 { 4652 prg.stdout.Writeln(" ") 4653 } 4654 prg.stdout.Write("Extra right parenthesis") 4655 prg.showErrorContext() 4656 } 4657 prg.loc = byte(int32(prg.loc) + 1) 4658 prg.curChar = ' ' 4659 } else if !prg.inputHasEnded { 4660 prg.junkError() 4661 } 4662 if prg.inputHasEnded { 4663 break 4664 } 4665 } 4666 } 4667 4668 func (prg *prg) corrAndCheck() { 4669 var ( 4670 c/* 0..256 */ uint16 // runs through all character codes 4671 hh/* 0..hashSize */ uint16 // an index into |hash_list| 4672 ligPtr/* 0..maxLigSteps */ uint16 // an index into |lig_kern| 4673 g byte // a character generated by the current character |c| 4674 ) 4675 if int32(prg.nl) > 0 { 4676 if int32(prg.charRemainder[256]) < 077777 { 4677 prg.ligKern[prg.nl].b0 = 255 4678 prg.ligKern[prg.nl].b1 = 0 4679 prg.ligKern[prg.nl].b2 = 0 4680 prg.ligKern[prg.nl].b3 = 0 4681 prg.nl = uint16(int32(prg.nl) + 1) 4682 } // |bchar_label| will be stored later 4683 for int32(prg.minNl) > int32(prg.nl) { 4684 prg.ligKern[prg.nl].b0 = 255 4685 prg.ligKern[prg.nl].b1 = 0 4686 prg.ligKern[prg.nl].b2 = 0 4687 prg.ligKern[prg.nl].b3 = 0 4688 prg.nl = uint16(int32(prg.nl) + 1) 4689 } 4690 if int32(prg.ligKern[int32(prg.nl)-1].b0) == 0 { 4691 prg.ligKern[int32(prg.nl)-1].b0 = byte(stopFlag) 4692 } 4693 } 4694 prg.sevenUnsafe = false 4695 for ii := int32(0); ii <= 255; ii++ { 4696 c = uint16(ii) 4697 _ = c 4698 if int32(prg.charWd[c]) != 0 { 4699 switch prg.charTag[c] { 4700 case noTag: 4701 case ligTag: 4702 // Check ligature program of |c| 4703 ligPtr = prg.charRemainder[c] 4704 for { 4705 if prg.hashInput(ligPtr, c) { 4706 if int32(prg.ligKern[ligPtr].b2) < kernFlag { 4707 if int32(prg.ligKern[ligPtr].b1) != int32(prg.bchar) { 4708 g = prg.ligKern[ligPtr].b1 4709 if int32(prg.charWd[g]) == 0 { 4710 prg.charWd[g] = prg.sortIn(pointer(width), fixWord(0)) 4711 prg.stdout.Write("LIG character examined by", " ") 4712 prg.printOctal(byte(c)) 4713 prg.stdout.Writeln(" had no CHARACTER spec.") 4714 } 4715 } 4716 // \xref[LIG character examined...] 4717 { 4718 g = prg.ligKern[ligPtr].b3 4719 if int32(prg.charWd[g]) == 0 { 4720 prg.charWd[g] = prg.sortIn(pointer(width), fixWord(0)) 4721 prg.stdout.Write("LIG character generated by", " ") 4722 prg.printOctal(byte(c)) 4723 prg.stdout.Writeln(" had no CHARACTER spec.") 4724 } 4725 } 4726 // \xref[LIG character generated...] 4727 if int32(prg.ligKern[ligPtr].b3) >= 128 { 4728 if int32(c) < 128 || int32(c) == 256 { 4729 if int32(prg.ligKern[ligPtr].b1) < 128 || int32(prg.ligKern[ligPtr].b1) == int32(prg.bchar) { 4730 prg.sevenUnsafe = true 4731 } 4732 } 4733 } 4734 } else if int32(prg.ligKern[ligPtr].b1) != int32(prg.bchar) { 4735 g = prg.ligKern[ligPtr].b1 4736 if int32(prg.charWd[g]) == 0 { 4737 prg.charWd[g] = prg.sortIn(pointer(width), fixWord(0)) 4738 prg.stdout.Write("KRN character examined by", " ") 4739 prg.printOctal(byte(c)) 4740 prg.stdout.Writeln(" had no CHARACTER spec.") 4741 } 4742 } 4743 // \xref[KRN character examined...] 4744 } 4745 if int32(prg.ligKern[ligPtr].b0) >= stopFlag { 4746 ligPtr = prg.nl 4747 } else { 4748 ligPtr = uint16(int32(ligPtr) + 1 + int32(prg.ligKern[ligPtr].b0)) 4749 } 4750 if int32(ligPtr) >= int32(prg.nl) { 4751 break 4752 } 4753 } 4754 4755 case listTag: 4756 g = byte(prg.charRemainder[c]) 4757 if int32(g) >= 128 && int32(c) < 128 { 4758 prg.sevenUnsafe = true 4759 } 4760 if int32(prg.charWd[g]) == 0 { 4761 prg.charWd[g] = prg.sortIn(pointer(width), fixWord(0)) 4762 prg.stdout.Write("The character NEXTLARGER than", " ") 4763 prg.printOctal(byte(c)) 4764 prg.stdout.Writeln(" had no CHARACTER spec.") 4765 } 4766 // \xref[The character NEXTLARGER...] 4767 case extTag: 4768 // Check the pieces of |exten[c]| 4769 if int32(prg.exten[prg.charRemainder[c]].b0) > 0 { 4770 g = prg.exten[prg.charRemainder[c]].b0 4771 if int32(g) >= 128 && int32(c) < 128 { 4772 prg.sevenUnsafe = true 4773 } 4774 if int32(prg.charWd[g]) == 0 { 4775 prg.charWd[g] = prg.sortIn(pointer(width), fixWord(0)) 4776 prg.stdout.Write("TOP piece of character", " ") 4777 prg.printOctal(byte(c)) 4778 prg.stdout.Writeln(" had no CHARACTER spec.") 4779 } 4780 } 4781 // \xref[TOP piece of character...] 4782 if int32(prg.exten[prg.charRemainder[c]].b1) > 0 { 4783 g = prg.exten[prg.charRemainder[c]].b1 4784 if int32(g) >= 128 && int32(c) < 128 { 4785 prg.sevenUnsafe = true 4786 } 4787 if int32(prg.charWd[g]) == 0 { 4788 prg.charWd[g] = prg.sortIn(pointer(width), fixWord(0)) 4789 prg.stdout.Write("MID piece of character", " ") 4790 prg.printOctal(byte(c)) 4791 prg.stdout.Writeln(" had no CHARACTER spec.") 4792 } 4793 } 4794 // \xref[MID piece of character...] 4795 if int32(prg.exten[prg.charRemainder[c]].b2) > 0 { 4796 g = prg.exten[prg.charRemainder[c]].b2 4797 if int32(g) >= 128 && int32(c) < 128 { 4798 prg.sevenUnsafe = true 4799 } 4800 if int32(prg.charWd[g]) == 0 { 4801 prg.charWd[g] = prg.sortIn(pointer(width), fixWord(0)) 4802 prg.stdout.Write("BOT piece of character", " ") 4803 prg.printOctal(byte(c)) 4804 prg.stdout.Writeln(" had no CHARACTER spec.") 4805 } 4806 } 4807 // \xref[BOT piece of character...] 4808 { 4809 g = prg.exten[prg.charRemainder[c]].b3 4810 if int32(g) >= 128 && int32(c) < 128 { 4811 prg.sevenUnsafe = true 4812 } 4813 if int32(prg.charWd[g]) == 0 { 4814 prg.charWd[g] = prg.sortIn(pointer(width), fixWord(0)) 4815 prg.stdout.Write("REP piece of character", " ") 4816 prg.printOctal(byte(c)) 4817 prg.stdout.Writeln(" had no CHARACTER spec.") 4818 } 4819 } 4820 // \xref[REP piece of character...] 4821 4822 } 4823 } 4824 } 4825 if int32(prg.charRemainder[256]) < 077777 { 4826 c = 256 4827 // Check ligature program of |c| 4828 { 4829 ligPtr = prg.charRemainder[c] 4830 for { 4831 if prg.hashInput(ligPtr, c) { 4832 if int32(prg.ligKern[ligPtr].b2) < kernFlag { 4833 if int32(prg.ligKern[ligPtr].b1) != int32(prg.bchar) { 4834 g = prg.ligKern[ligPtr].b1 4835 if int32(prg.charWd[g]) == 0 { 4836 prg.charWd[g] = prg.sortIn(pointer(width), fixWord(0)) 4837 prg.stdout.Write("LIG character examined by", " ") 4838 prg.printOctal(byte(c)) 4839 prg.stdout.Writeln(" had no CHARACTER spec.") 4840 } 4841 } 4842 // \xref[LIG character examined...] 4843 { 4844 g = prg.ligKern[ligPtr].b3 4845 if int32(prg.charWd[g]) == 0 { 4846 prg.charWd[g] = prg.sortIn(pointer(width), fixWord(0)) 4847 prg.stdout.Write("LIG character generated by", " ") 4848 prg.printOctal(byte(c)) 4849 prg.stdout.Writeln(" had no CHARACTER spec.") 4850 } 4851 } 4852 // \xref[LIG character generated...] 4853 if int32(prg.ligKern[ligPtr].b3) >= 128 { 4854 if int32(c) < 128 || int32(c) == 256 { 4855 if int32(prg.ligKern[ligPtr].b1) < 128 || int32(prg.ligKern[ligPtr].b1) == int32(prg.bchar) { 4856 prg.sevenUnsafe = true 4857 } 4858 } 4859 } 4860 } else if int32(prg.ligKern[ligPtr].b1) != int32(prg.bchar) { 4861 g = prg.ligKern[ligPtr].b1 4862 if int32(prg.charWd[g]) == 0 { 4863 prg.charWd[g] = prg.sortIn(pointer(width), fixWord(0)) 4864 prg.stdout.Write("KRN character examined by", " ") 4865 prg.printOctal(byte(c)) 4866 prg.stdout.Writeln(" had no CHARACTER spec.") 4867 } 4868 } 4869 // \xref[KRN character examined...] 4870 } 4871 if int32(prg.ligKern[ligPtr].b0) >= stopFlag { 4872 ligPtr = prg.nl 4873 } else { 4874 ligPtr = uint16(int32(ligPtr) + 1 + int32(prg.ligKern[ligPtr].b0)) 4875 } 4876 if int32(ligPtr) >= int32(prg.nl) { 4877 break 4878 } 4879 } 4880 } 4881 } 4882 if prg.sevenBitSafeFlag && prg.sevenUnsafe { 4883 prg.stdout.Writeln("The font is not really seven-bit-safe!") 4884 } 4885 // \xref[The font is not...safe] 4886 4887 // Check for infinite ligature loops 4888 if int32(prg.hashPtr) < hashSize { 4889 for ii := int32(1); ii <= int32(prg.hashPtr); ii++ { 4890 hh = uint16(ii) 4891 _ = hh 4892 prg.tt = prg.hashList[hh] 4893 if int32(prg.class[prg.tt]) > simple { 4894 prg.tt = prg.f(prg.tt, indx((int32(prg.hash[prg.tt])-1)/256), indx((int32(prg.hash[prg.tt])-1)%256)) 4895 } 4896 } 4897 } 4898 if int32(prg.hashPtr) == hashSize || int32(prg.yLigCycle) < 256 { 4899 if int32(prg.hashPtr) < hashSize { 4900 prg.stdout.Write("Infinite ligature loop starting with ") 4901 // \xref[Infinite ligature loop...] 4902 if int32(prg.xLigCycle) == 256 { 4903 prg.stdout.Write("boundary") 4904 } else { 4905 prg.printOctal(byte(prg.xLigCycle)) 4906 } 4907 prg.stdout.Write(" and ") 4908 prg.printOctal(byte(prg.yLigCycle)) 4909 prg.stdout.Writeln("!") 4910 } else { 4911 prg.stdout.Writeln("Sorry, I haven't room for so many ligature/kern pairs!") 4912 } 4913 // \xref[Sorry, I haven't room...] 4914 prg.stdout.Writeln("All ligatures will be cleared.") 4915 for ii := int32(0); ii <= 255; ii++ { 4916 c = uint16(ii) 4917 _ = c 4918 if int32(prg.charTag[c]) == ligTag { 4919 prg.charTag[c] = byte(noTag) 4920 prg.charRemainder[c] = 0 4921 } 4922 } 4923 prg.nl = 0 4924 prg.bchar = 256 4925 prg.charRemainder[256] = 077777 4926 } 4927 4928 // Doublecheck the lig/kern commands and the extensible recipes 4929 if int32(prg.nl) > 0 { 4930 for ii := int32(0); ii <= int32(prg.nl)-1; ii++ { 4931 ligPtr = uint16(ii) 4932 _ = ligPtr 4933 if int32(prg.ligKern[ligPtr].b2) < kernFlag { 4934 if int32(prg.ligKern[ligPtr].b0) < 255 { 4935 { 4936 c = uint16(prg.ligKern[ligPtr].b1) 4937 if int32(prg.charWd[c]) == 0 { 4938 if int32(c) != int32(prg.bchar) { 4939 prg.ligKern[ligPtr].b1 = 0 // \1 4940 if int32(prg.charWd[0]) == 0 { 4941 prg.charWd[0] = prg.sortIn(pointer(width), fixWord(0)) 4942 } 4943 prg.stdout.Write("Unused ", "LIG step", " refers to nonexistent character ") 4944 prg.printOctal(byte(c)) 4945 prg.stdout.Writeln("!") 4946 } 4947 } 4948 } 4949 { 4950 c = uint16(prg.ligKern[ligPtr].b3) 4951 if int32(prg.charWd[c]) == 0 { 4952 if int32(c) != int32(prg.bchar) { 4953 prg.ligKern[ligPtr].b3 = 0 // \1 4954 if int32(prg.charWd[0]) == 0 { 4955 prg.charWd[0] = prg.sortIn(pointer(width), fixWord(0)) 4956 } 4957 prg.stdout.Write("Unused ", "LIG step", " refers to nonexistent character ") 4958 prg.printOctal(byte(c)) 4959 prg.stdout.Writeln("!") 4960 } 4961 } 4962 } 4963 } 4964 } else { 4965 c = uint16(prg.ligKern[ligPtr].b1) 4966 if int32(prg.charWd[c]) == 0 { 4967 if int32(c) != int32(prg.bchar) { 4968 prg.ligKern[ligPtr].b1 = 0 // \1 4969 if int32(prg.charWd[0]) == 0 { 4970 prg.charWd[0] = prg.sortIn(pointer(width), fixWord(0)) 4971 } 4972 prg.stdout.Write("Unused ", "KRN step", " refers to nonexistent character ") 4973 prg.printOctal(byte(c)) 4974 prg.stdout.Writeln("!") 4975 } 4976 } 4977 } 4978 } 4979 } 4980 // \xref[Unused LIG step...] 4981 // \xref[Unused KRN step...] 4982 if int32(prg.ne) > 0 { 4983 for ii := int32(0); ii <= int32(prg.ne)-1; ii++ { 4984 g = byte(ii) 4985 _ = g 4986 { 4987 c = uint16(prg.exten[g].b0) 4988 if int32(c) > 0 { 4989 if int32(prg.charWd[c]) == 0 { 4990 prg.exten[g].b0 = 0 // \1 4991 if int32(prg.charWd[0]) == 0 { 4992 prg.charWd[0] = prg.sortIn(pointer(width), fixWord(0)) 4993 } 4994 prg.stdout.Write("Unused ", "VARCHAR TOP", " refers to nonexistent character ") 4995 prg.printOctal(byte(c)) 4996 prg.stdout.Writeln("!") 4997 } 4998 } 4999 } 5000 { 5001 c = uint16(prg.exten[g].b1) 5002 if int32(c) > 0 { 5003 if int32(prg.charWd[c]) == 0 { 5004 prg.exten[g].b1 = 0 // \1 5005 if int32(prg.charWd[0]) == 0 { 5006 prg.charWd[0] = prg.sortIn(pointer(width), fixWord(0)) 5007 } 5008 prg.stdout.Write("Unused ", "VARCHAR MID", " refers to nonexistent character ") 5009 prg.printOctal(byte(c)) 5010 prg.stdout.Writeln("!") 5011 } 5012 } 5013 } 5014 { 5015 c = uint16(prg.exten[g].b2) 5016 if int32(c) > 0 { 5017 if int32(prg.charWd[c]) == 0 { 5018 prg.exten[g].b2 = 0 // \1 5019 if int32(prg.charWd[0]) == 0 { 5020 prg.charWd[0] = prg.sortIn(pointer(width), fixWord(0)) 5021 } 5022 prg.stdout.Write("Unused ", "VARCHAR BOT", " refers to nonexistent character ") 5023 prg.printOctal(byte(c)) 5024 prg.stdout.Writeln("!") 5025 } 5026 } 5027 } 5028 { 5029 c = uint16(prg.exten[g].b3) 5030 if int32(prg.charWd[c]) == 0 { 5031 prg.exten[g].b3 = 0 // \1 5032 if int32(prg.charWd[0]) == 0 { 5033 prg.charWd[0] = prg.sortIn(pointer(width), fixWord(0)) 5034 } 5035 prg.stdout.Write("Unused ", "VARCHAR REP", " refers to nonexistent character ") 5036 prg.printOctal(byte(c)) 5037 prg.stdout.Writeln("!") 5038 } 5039 } 5040 // \xref[Unused VARCHAR...] 5041 } 5042 } 5043 for ii := int32(0); ii <= 255; ii++ { 5044 c = uint16(ii) 5045 _ = c 5046 5047 // Make sure that |c| is not the largest element of a charlist cycle 5048 if int32(prg.charTag[c]) == listTag { 5049 g = byte(prg.charRemainder[c]) 5050 for int32(g) < int32(c) && int32(prg.charTag[g]) == listTag { 5051 g = byte(prg.charRemainder[g]) 5052 } 5053 if int32(g) == int32(c) { 5054 prg.charTag[c] = byte(noTag) 5055 prg.stdout.Write("A cycle of NEXTLARGER characters has been broken at ") 5056 // \xref[A cycle of NEXTLARGER...] 5057 prg.printOctal(byte(c)) 5058 prg.stdout.Writeln(".") 5059 } 5060 } 5061 } 5062 5063 // Put the width, height, depth, and italic lists into final form 5064 prg.delta = prg.shorten(pointer(width), 255) 5065 prg.setIndices(pointer(width), prg.delta) 5066 if prg.delta > 0 { 5067 prg.stdout.Writeln("I had to round some " /* \xref[I had to round...] */, "width", "s by ", float64((prg.delta+1)/2)/float64(04000000), knuth.WriteWidth(1), knuth.WriteWidth(7), " units.") 5068 } 5069 5070 prg.delta = prg.shorten(pointer(height), 15) 5071 prg.setIndices(pointer(height), prg.delta) 5072 if prg.delta > 0 { 5073 prg.stdout.Writeln("I had to round some " /* \xref[I had to round...] */, "height", "s by ", float64((prg.delta+1)/2)/float64(04000000), knuth.WriteWidth(1), knuth.WriteWidth(7), " units.") 5074 } 5075 5076 prg.delta = prg.shorten(pointer(depth), 15) 5077 prg.setIndices(pointer(depth), prg.delta) 5078 if prg.delta > 0 { 5079 prg.stdout.Writeln("I had to round some " /* \xref[I had to round...] */, "depth", "s by ", float64((prg.delta+1)/2)/float64(04000000), knuth.WriteWidth(1), knuth.WriteWidth(7), " units.") 5080 } 5081 5082 prg.delta = prg.shorten(pointer(italic), 63) 5083 prg.setIndices(pointer(italic), prg.delta) 5084 if prg.delta > 0 { 5085 prg.stdout.Writeln("I had to round some " /* \xref[I had to round...] */, "italic correction", "s by ", float64((prg.delta+1)/2)/float64(04000000), knuth.WriteWidth(1), knuth.WriteWidth(7), " units.") 5086 } 5087 5088 } 5089 5090 func (prg *prg) vfOutput() { 5091 var ( 5092 c byte // runs through all character codes 5093 curFont/* 0..256 */ uint16 // runs through all local fonts 5094 k int32 // loop index 5095 ) 5096 prg.vfFile.Write(pre) 5097 prg.vfFile.Write(idByte) 5098 prg.vfFile.Write(prg.vtitleLength) 5099 for ii := int32(0); ii <= int32(prg.vtitleLength)-1; ii++ { 5100 k = ii 5101 _ = k 5102 prg.vfFile.Write(prg.vf[int32(prg.vtitleStart)+k]) 5103 } 5104 for ii := int32(checkSumLoc); ii <= designSizeLoc+3; ii++ { 5105 k = ii 5106 _ = k 5107 prg.vfFile.Write(prg.headerBytes[k]) 5108 } 5109 prg.vcount = int32(prg.vtitleLength) + 11 5110 for ii := int32(0); ii <= int32(prg.fontPtr)-1; ii++ { 5111 curFont = uint16(ii) 5112 _ = curFont 5113 // Output a local font definition 5114 prg.vfFile.Write(fntDef1) 5115 prg.vfFile.Write(curFont) 5116 5117 prg.vfFile.Write(prg.fontChecksum[curFont].b0) 5118 prg.vfFile.Write(prg.fontChecksum[curFont].b1) 5119 prg.vfFile.Write(prg.fontChecksum[curFont].b2) 5120 prg.vfFile.Write(prg.fontChecksum[curFont].b3) 5121 prg.voutInt(prg.fontAt[curFont]) 5122 prg.voutInt(prg.fontDsize[curFont]) 5123 prg.vfFile.Write(prg.fareaLength[curFont]) 5124 prg.vfFile.Write(prg.fnameLength[curFont]) 5125 for ii := int32(0); ii <= int32(prg.fareaLength[curFont])-1; ii++ { 5126 k = ii 5127 _ = k 5128 prg.vfFile.Write(prg.vf[int32(prg.fareaStart[curFont])+k]) 5129 } 5130 if int32(prg.fnameStart[curFont]) == vfSize { 5131 prg.vfFile.Write('N') 5132 prg.vfFile.Write('U') 5133 prg.vfFile.Write('L') 5134 prg.vfFile.Write('L') 5135 } else { 5136 for ii := int32(0); ii <= int32(prg.fnameLength[curFont])-1; ii++ { 5137 k = ii 5138 _ = k 5139 prg.vfFile.Write(prg.vf[int32(prg.fnameStart[curFont])+k]) 5140 } 5141 } 5142 prg.vcount = prg.vcount + 12 + int32(prg.fareaLength[curFont]) + int32(prg.fnameLength[curFont]) 5143 } 5144 for ii := int32(prg.bc); ii <= int32(prg.ec); ii++ { 5145 c = byte(ii) 5146 _ = c 5147 if int32(prg.charWd[c]) > 0 { 5148 prg.x = prg.memory[prg.charWd[c]] 5149 if prg.designUnits != 04000000 { 5150 prg.x = round(float64(prg.x) / float64(prg.designUnits) * 1048576.0) 5151 } 5152 if prg.packetLength[c] > 241 || prg.x < 0 || prg.x >= 0100000000 { 5153 prg.vfFile.Write(242) 5154 prg.voutInt(prg.packetLength[c]) 5155 prg.voutInt(int32(c)) 5156 prg.voutInt(prg.x) 5157 prg.vcount = prg.vcount + 13 + prg.packetLength[c] 5158 } else { 5159 prg.vfFile.Write(prg.packetLength[c]) 5160 prg.vfFile.Write(c) 5161 prg.vfFile.Write(prg.x / 0200000) 5162 prg.vfFile.Write(prg.x / 0400 % 256) 5163 prg.vfFile.Write(prg.x % 256) 5164 prg.vcount = prg.vcount + 5 + prg.packetLength[c] 5165 } 5166 if int32(prg.packetStart[c]) == vfSize { 5167 if int32(c) >= 128 { 5168 prg.vfFile.Write(set1) 5169 } 5170 prg.vfFile.Write(c) 5171 } else { 5172 for ii := int32(0); ii <= prg.packetLength[c]-1; ii++ { 5173 k = ii 5174 _ = k 5175 prg.vfFile.Write(prg.vf[int32(prg.packetStart[c])+k]) 5176 } 5177 } 5178 } 5179 } 5180 for { 5181 prg.vfFile.Write(post) 5182 prg.vcount = prg.vcount + 1 5183 if prg.vcount%4 == 0 { 5184 break 5185 } 5186 } 5187 } 5188 5189 // 181. 5190 5191 // tangle:pos vptovf.web:3157:5: 5192 5193 // Here is where \.[VPtoVF] begins and ends. 5194 func (prg *prg) main() { 5195 defer func() { 5196 if prg.stderr != nil { 5197 prg.stderr.Close() 5198 } 5199 if prg.stdin != nil { 5200 prg.stdin.Close() 5201 } 5202 if prg.stdout != nil { 5203 prg.stdout.Close() 5204 } 5205 if prg.tfmFile != nil { 5206 prg.tfmFile.Close() 5207 } 5208 if prg.vfFile != nil { 5209 prg.vfFile.Close() 5210 } 5211 if prg.vplFile != nil { 5212 prg.vplFile.Close() 5213 } 5214 }() 5215 5216 prg.initialize() 5217 5218 prg.nameEnter() 5219 5220 prg.readInput() 5221 prg.stdout.Writeln(".") 5222 5223 prg.corrAndCheck() 5224 5225 // Do the \.[TFM] output 5226 5227 // Compute the twelve subfile sizes 5228 prg.lh = byte(int32(prg.headerPtr) / 4) 5229 5230 prg.notFound = true 5231 prg.bc = 0 5232 for prg.notFound { 5233 if int32(prg.charWd[prg.bc]) > 0 || int32(prg.bc) == 255 { 5234 prg.notFound = false 5235 } else { 5236 prg.bc = byte(int32(prg.bc) + 1) 5237 } 5238 } 5239 prg.notFound = true 5240 prg.ec = 255 5241 for prg.notFound { 5242 if int32(prg.charWd[prg.ec]) > 0 || int32(prg.ec) == 0 { 5243 prg.notFound = false 5244 } else { 5245 prg.ec = byte(int32(prg.ec) - 1) 5246 } 5247 } 5248 if int32(prg.bc) > int32(prg.ec) { 5249 prg.bc = 1 5250 } 5251 prg.memory[width] = prg.memory[width] + 1 5252 prg.memory[height] = prg.memory[height] + 1 5253 prg.memory[depth] = prg.memory[depth] + 1 5254 prg.memory[italic] = prg.memory[italic] + 1 5255 5256 // Compute the ligature/kern program offset 5257 5258 // Insert all labels into |label_table| 5259 prg.labelPtr = 0 5260 prg.labelTable[0].rr = int16(-1) // sentinel 5261 for ii := int32(prg.bc); ii <= int32(prg.ec); ii++ { 5262 prg.c = byte(ii) 5263 _ = prg.c 5264 if int32(prg.charTag[prg.c]) == ligTag { 5265 prg.sortPtr = prg.labelPtr // there's a hole at position |sort_ptr+1| 5266 for int32(prg.labelTable[prg.sortPtr].rr) > int32(prg.charRemainder[prg.c]) { 5267 prg.labelTable[int32(prg.sortPtr)+1] = prg.labelTable[prg.sortPtr] 5268 prg.sortPtr = uint16(int32(prg.sortPtr) - 1) // move the hole 5269 } 5270 prg.labelTable[int32(prg.sortPtr)+1].cc = prg.c 5271 prg.labelTable[int32(prg.sortPtr)+1].rr = int16(prg.charRemainder[prg.c]) 5272 prg.labelPtr = uint16(int32(prg.labelPtr) + 1) 5273 } 5274 } 5275 if int32(prg.bchar) < 256 { 5276 prg.extraLocNeeded = true 5277 prg.lkOffset = 1 5278 } else { 5279 prg.extraLocNeeded = false 5280 prg.lkOffset = 0 5281 } 5282 5283 // Find the minimum |lk_offset| and adjust all remainders 5284 { 5285 prg.sortPtr = prg.labelPtr // the largest unallocated label 5286 if int32(prg.labelTable[prg.sortPtr].rr)+int32(prg.lkOffset) > 255 { 5287 prg.lkOffset = 0 5288 prg.extraLocNeeded = false // location 0 can do double duty 5289 for { 5290 prg.charRemainder[prg.labelTable[prg.sortPtr].cc] = prg.lkOffset 5291 for int32(prg.labelTable[int32(prg.sortPtr)-1].rr) == int32(prg.labelTable[prg.sortPtr].rr) { 5292 prg.sortPtr = uint16(int32(prg.sortPtr) - 1) 5293 prg.charRemainder[prg.labelTable[prg.sortPtr].cc] = prg.lkOffset 5294 } 5295 prg.lkOffset = uint16(int32(prg.lkOffset) + 1) 5296 prg.sortPtr = uint16(int32(prg.sortPtr) - 1) 5297 if int32(prg.lkOffset)+int32(prg.labelTable[prg.sortPtr].rr) < 256 { 5298 break 5299 } 5300 } 5301 // N.B.: |lk_offset=256| satisfies this when |sort_ptr=0| 5302 } 5303 if int32(prg.lkOffset) > 0 { 5304 for int32(prg.sortPtr) > 0 { 5305 prg.charRemainder[prg.labelTable[prg.sortPtr].cc] = uint16(int32(prg.charRemainder[prg.labelTable[prg.sortPtr].cc]) + int32(prg.lkOffset)) 5306 prg.sortPtr = uint16(int32(prg.sortPtr) - 1) 5307 } 5308 } 5309 } 5310 if int32(prg.charRemainder[256]) < 077777 { 5311 prg.ligKern[int32(prg.nl)-1].b2 = byte((int32(prg.charRemainder[256]) + int32(prg.lkOffset)) / 256) 5312 prg.ligKern[int32(prg.nl)-1].b3 = byte((int32(prg.charRemainder[256]) + int32(prg.lkOffset)) % 256) 5313 } 5314 prg.lf = uint16(6 + int32(prg.lh) + (int32(prg.ec) - int32(prg.bc) + 1) + prg.memory[width] + prg.memory[height] + prg.memory[depth] + prg.memory[italic] + int32(prg.nl) + int32(prg.lkOffset) + int32(prg.nk) + int32(prg.ne) + int32(prg.np)) 5315 5316 // Output the twelve subfile sizes 5317 prg.tfmFile.Write(int32(prg.lf) / 256) 5318 prg.tfmFile.Write(int32(prg.lf) % 256) 5319 prg.tfmFile.Write(int32(prg.lh) / 256) 5320 prg.tfmFile.Write(int32(prg.lh) % 256) 5321 prg.tfmFile.Write(int32(prg.bc) / 256) 5322 prg.tfmFile.Write(int32(prg.bc) % 256) 5323 prg.tfmFile.Write(int32(prg.ec) / 256) 5324 prg.tfmFile.Write(int32(prg.ec) % 256) 5325 prg.tfmFile.Write(prg.memory[width] / 256) 5326 prg.tfmFile.Write(prg.memory[width] % 256) 5327 prg.tfmFile.Write(prg.memory[height] / 256) 5328 prg.tfmFile.Write(prg.memory[height] % 256) 5329 prg.tfmFile.Write(prg.memory[depth] / 256) 5330 prg.tfmFile.Write(prg.memory[depth] % 256) 5331 prg.tfmFile.Write(prg.memory[italic] / 256) 5332 prg.tfmFile.Write(prg.memory[italic] % 256) 5333 prg.tfmFile.Write((int32(prg.nl) + int32(prg.lkOffset)) / 256) 5334 prg.tfmFile.Write((int32(prg.nl) + int32(prg.lkOffset)) % 256) 5335 prg.tfmFile.Write(int32(prg.nk) / 256) 5336 prg.tfmFile.Write(int32(prg.nk) % 256) 5337 prg.tfmFile.Write(int32(prg.ne) / 256) 5338 prg.tfmFile.Write(int32(prg.ne) % 256) 5339 prg.tfmFile.Write(int32(prg.np) / 256) 5340 prg.tfmFile.Write(int32(prg.np) % 256) 5341 5342 // Output the header block 5343 if !prg.checkSumSpecified { 5344 prg.curBytes.b0 = prg.bc 5345 prg.curBytes.b1 = prg.ec 5346 prg.curBytes.b2 = prg.bc 5347 prg.curBytes.b3 = prg.ec 5348 for ii := int32(prg.bc); ii <= int32(prg.ec); ii++ { 5349 prg.c = byte(ii) 5350 _ = prg.c 5351 if int32(prg.charWd[prg.c]) > 0 { 5352 prg.tempWidth = prg.memory[prg.charWd[prg.c]] 5353 if prg.designUnits != 04000000 { 5354 prg.tempWidth = round(float64(prg.tempWidth) / float64(prg.designUnits) * 1048576.0) 5355 } 5356 prg.tempWidth = prg.tempWidth + (int32(prg.c)+4)*020000000 // this should be positive 5357 prg.curBytes.b0 = byte((int32(prg.curBytes.b0) + int32(prg.curBytes.b0) + prg.tempWidth) % 255) 5358 prg.curBytes.b1 = byte((int32(prg.curBytes.b1) + int32(prg.curBytes.b1) + prg.tempWidth) % 253) 5359 prg.curBytes.b2 = byte((int32(prg.curBytes.b2) + int32(prg.curBytes.b2) + prg.tempWidth) % 251) 5360 prg.curBytes.b3 = byte((int32(prg.curBytes.b3) + int32(prg.curBytes.b3) + prg.tempWidth) % 247) 5361 } 5362 } 5363 prg.headerBytes[checkSumLoc] = prg.curBytes.b0 5364 prg.headerBytes[checkSumLoc+1] = prg.curBytes.b1 5365 prg.headerBytes[checkSumLoc+2] = prg.curBytes.b2 5366 prg.headerBytes[checkSumLoc+3] = prg.curBytes.b3 5367 } 5368 prg.headerBytes[designSizeLoc] = byte(prg.designSize / 0100000000) 5369 // this works since |design_size>0| 5370 prg.headerBytes[designSizeLoc+1] = byte(prg.designSize / 0200000 % 256) 5371 prg.headerBytes[designSizeLoc+2] = byte(prg.designSize / 256 % 256) 5372 prg.headerBytes[designSizeLoc+3] = byte(prg.designSize % 256) 5373 if !prg.sevenUnsafe { 5374 prg.headerBytes[sevenFlagLoc] = 128 5375 } 5376 for ii := int32(0); ii <= int32(prg.headerPtr)-1; ii++ { 5377 prg.j = byte(ii) 5378 _ = prg.j 5379 prg.tfmFile.Write(prg.headerBytes[prg.j]) 5380 } 5381 5382 // Output the character info 5383 prg.index[0] = 0 5384 for ii := int32(prg.bc); ii <= int32(prg.ec); ii++ { 5385 prg.c = byte(ii) 5386 _ = prg.c 5387 prg.tfmFile.Write(prg.index[prg.charWd[prg.c]]) 5388 prg.tfmFile.Write(int32(prg.index[prg.charHt[prg.c]])*16 + int32(prg.index[prg.charDp[prg.c]])) 5389 prg.tfmFile.Write(int32(prg.index[prg.charIc[prg.c]])*4 + int32(prg.charTag[prg.c])) 5390 prg.tfmFile.Write(prg.charRemainder[prg.c]) 5391 } 5392 5393 // Output the dimensions themselves 5394 for ii := int32(width); ii <= italic; ii++ { 5395 prg.q = byte(ii) 5396 _ = prg.q 5397 prg.tfmFile.Write(0) 5398 prg.tfmFile.Write(0) 5399 prg.tfmFile.Write(0) 5400 prg.tfmFile.Write(0) // output the zero word 5401 prg.p = prg.link[prg.q] // head of list 5402 for int32(prg.p) > 0 { 5403 prg.outScaled(prg.memory[prg.p]) 5404 prg.p = prg.link[prg.p] 5405 } 5406 } 5407 5408 // Output the ligature/kern program 5409 if prg.extraLocNeeded { 5410 prg.tfmFile.Write(255) 5411 prg.tfmFile.Write(prg.bchar) 5412 prg.tfmFile.Write(0) 5413 prg.tfmFile.Write(0) 5414 } else { 5415 for ii := int32(1); ii <= int32(prg.lkOffset); ii++ { 5416 prg.sortPtr = uint16(ii) 5417 _ = prg.sortPtr // output the redirection specs 5418 prg.t = uint16(prg.labelTable[prg.labelPtr].rr) 5419 if int32(prg.bchar) < 256 { 5420 prg.tfmFile.Write(255) 5421 prg.tfmFile.Write(prg.bchar) 5422 } else { 5423 prg.tfmFile.Write(254) 5424 prg.tfmFile.Write(0) 5425 } 5426 prg.tfmFile.Write((int32(prg.t) + int32(prg.lkOffset)) / 256) 5427 prg.tfmFile.Write((int32(prg.t) + int32(prg.lkOffset)) % 256) 5428 for { 5429 prg.labelPtr = uint16(int32(prg.labelPtr) - 1) 5430 if int32(prg.labelTable[prg.labelPtr].rr) < int32(prg.t) { 5431 break 5432 } 5433 } 5434 } 5435 } 5436 if int32(prg.nl) > 0 { 5437 for ii := int32(0); ii <= int32(prg.nl)-1; ii++ { 5438 prg.ligPtr = uint16(ii) 5439 _ = prg.ligPtr 5440 prg.tfmFile.Write(prg.ligKern[prg.ligPtr].b0) 5441 prg.tfmFile.Write(prg.ligKern[prg.ligPtr].b1) 5442 prg.tfmFile.Write(prg.ligKern[prg.ligPtr].b2) 5443 prg.tfmFile.Write(prg.ligKern[prg.ligPtr].b3) 5444 } 5445 } 5446 if int32(prg.nk) > 0 { 5447 for ii := int32(0); ii <= int32(prg.nk)-1; ii++ { 5448 prg.krnPtr = uint16(ii) 5449 _ = prg.krnPtr 5450 prg.outScaled(prg.kern[prg.krnPtr]) 5451 } 5452 } 5453 5454 // Output the extensible character recipes 5455 if int32(prg.ne) > 0 { 5456 for ii := int32(0); ii <= int32(prg.ne)-1; ii++ { 5457 prg.c = byte(ii) 5458 _ = prg.c 5459 prg.tfmFile.Write(prg.exten[prg.c].b0) 5460 prg.tfmFile.Write(prg.exten[prg.c].b1) 5461 prg.tfmFile.Write(prg.exten[prg.c].b2) 5462 prg.tfmFile.Write(prg.exten[prg.c].b3) 5463 } 5464 } 5465 5466 // Output the parameters 5467 for ii := int32(1); ii <= int32(prg.np); ii++ { 5468 prg.parPtr = byte(ii) 5469 _ = prg.parPtr 5470 if int32(prg.parPtr) == 1 { 5471 if prg.param[1-1] < 0 { 5472 prg.param[1-1] = prg.param[1-1] + 010000000000 5473 prg.tfmFile.Write(prg.param[1-1]/0100000000 + 256 - 64) 5474 } else { 5475 prg.tfmFile.Write(prg.param[1-1] / 0100000000) 5476 } 5477 prg.tfmFile.Write(prg.param[1-1] / 0200000 % 256) 5478 prg.tfmFile.Write(prg.param[1-1] / 256 % 256) 5479 prg.tfmFile.Write(prg.param[1-1] % 256) 5480 } else { 5481 prg.outScaled(prg.param[prg.parPtr-1]) 5482 } 5483 } 5484 prg.vfOutput() 5485 } 5486 5487 // 182. System-dependent changes 5488 5489 // tangle:pos vptovf.web:3169:25: 5490 5491 // This section should be replaced, if necessary, by changes to the program 5492 // that are necessary to make \.[VPtoVF] work at a particular installation. 5493 // It is usually best to design your change file so that all changes to 5494 // previous sections preserve the section numbering; then everybody's version 5495 // will be consistent with the printed program. More extensive changes, 5496 // which introduce new sections, can be inserted here; then only the index 5497 // itself will get a new section number. 5498 // \xref[system dependencies] 5499 5500 // 183. Index 5501 5502 // tangle:pos vptovf.web:3179:6: 5503 5504 // Pointers to error messages appear here together with the section numbers 5505 // where each ident\-i\-fier is used.