1 #define _BSD_EXTENSION 2 #define _POSIX_SOURCE 3 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <unistd.h> 7 #include <limits.h> 8 #include <ctype.h> 9 #include <string.h> 10 11 #define NROFF (!TROFF) 12 13 14 /* Site dependent definitions */ 15 16 #ifndef TMACDIR 17 #define TMACDIR "lib/tmac/tmac." 18 #endif 19 #ifndef FONTDIR 20 #define FONTDIR "lib/font" 21 #endif 22 #ifndef NTERMDIR 23 #define NTERMDIR "lib/term/tab." 24 #endif 25 #ifndef TDEVNAME 26 #define TDEVNAME "post" 27 #endif 28 #ifndef NDEVNAME 29 #define NDEVNAME "37" 30 #endif 31 #ifndef TEXHYPHENS 32 #define TEXHYPHENS "/usr/lib/tex/macros/hyphen.tex" 33 #endif 34 #ifndef ALTHYPHENS 35 #define ALTHYPHENS "lib/tmac/hyphen.tex" /* another place to look */ 36 #endif 37 38 typedef unsigned char Uchar; 39 typedef unsigned short Ushort; 40 41 typedef /*unsigned*/ long Tchar; 42 43 typedef struct Blockp Blockp; 44 typedef struct Diver Diver; 45 typedef struct Stack Stack; 46 typedef struct Divsiz Divsiz; 47 typedef struct Contab Contab; 48 typedef struct Numtab Numtab; 49 typedef struct Numerr Numerr; 50 typedef struct Env Env; 51 typedef struct Term Term; 52 typedef struct Chwid Chwid; 53 typedef struct Font Font; 54 typedef struct Spnames Spnames; 55 typedef struct Wcache Wcache; 56 typedef struct Tbuf Tbuf; 57 58 /* this simulates printf into a buffer that gets flushed sporadically */ 59 /* the BSD goo is because SunOS sprintf doesn't return anything useful */ 60 61 #ifdef BSD4_2 62 #define OUT (obufp += strlen(sprintf(obufp, 63 #define PUT ))) > obuf+BUFSIZ ? flusho() : 1 64 #else 65 #define OUT (obufp += sprintf(obufp, 66 #define PUT )) > obuf+BUFSIZ ? flusho() : 1 67 #endif 68 69 #define oputs(a) OUT "%s", a PUT 70 #define oput(c) ( *obufp++ = (c), obufp > obuf+BUFSIZ ? flusho() : 1 ) 71 72 extern char errbuf[]; 73 #define ERROR sprintf(errbuf, 74 #define WARN ), errprint() 75 #define FATAL ), errprint(), exit(1) 76 77 /* starting values for typesetting parameters: */ 78 79 #define PS 10 /* default point size */ 80 #define FT 1 /* default font position */ 81 #define ULFONT 2 /* default underline font */ 82 #define BDFONT 3 /* default emboldening font */ 83 #define BIFONT 4 /* default bold italic font */ 84 #define LL (unsigned) 65*INCH/10 /* line length; 39picas=6.5in */ 85 #define VS ((12*INCH)/72) /* initial vert space */ 86 87 88 #define EMPTS(pts) (((long)Inch*(pts) + 36) / 72) 89 #define EM (TROFF? EMPTS(pts): t.Em) 90 #define INCH (TROFF? Inch: 240) 91 #define HOR (TROFF? Hor: t.Adj) 92 #define VERT (TROFF? Vert: t.Vert) 93 #define PO (TROFF? Inch: 0) 94 #define SPS (TROFF? EMPTS(pts)/3: INCH/10) 95 #define SS (TROFF? 12: INCH/10) 96 #define ICS (TROFF? EMPTS(pts): 2*INCH/10) 97 #define DTAB (TROFF? (INCH/2): 0) 98 99 /* These "characters" are used to encode various internal functions 100 /* Some make use of the fact that most ascii characters between 101 /* 0 and 040 don't have any graphic or other function. 102 /* The few that do have a purpose (e.g., \n, \b, \t, ... 103 /* are avoided by the ad hoc choices here. 104 /* See ifilt[] in n1.c for others -- 1, 2, 3, 5, 6, 7, 010, 011, 012 105 */ 106 107 #define LEADER 001 108 #define IMP 004 /* impossible char; glues things together */ 109 #define TAB 011 110 #define RPT 014 /* next character is to be repeated many times */ 111 #define CHARHT 015 /* size field sets character height */ 112 #define SLANT 016 /* size field sets amount of slant */ 113 #define DRAWFCN 017 /* next several chars describe arb drawing fcns */ 114 # define DRAWLINE 'l' /* line: 'l' dx dy char */ 115 # define DRAWCIRCLE 'c' /* circle: 'c' r */ 116 # define DRAWELLIPSE 'e' /* ellipse: 'e' rx ry */ 117 # define DRAWARC 'a' /* arc: 'a' dx dy dx dy */ 118 # define DRAWSPLINE '~' /* quadratic B spline: '~' dx dy dx dy ... */ 119 /* other splines go thru too */ 120 /* NOTE: the use of ~ is a botch since it's often used in .tr commands */ 121 /* better to use a letter like s, but change it in the postprocessors too */ 122 /* for now, this is taken care of in n9.c and t10.c */ 123 # define DRAWBUILD 'b' /* built-up character (e.g., { */ 124 125 #define LEFT 020 /* \{ */ 126 #define RIGHT 021 /* \} */ 127 #define FILLER 022 /* \& and similar purposes */ 128 #define XON 023 /* \X'...' starts here */ 129 #define OHC 024 /* optional hyphenation character \% */ 130 #define CONT 025 /* \c character */ 131 #define PRESC 026 /* printable escape */ 132 #define UNPAD 027 /* unpaddable blank */ 133 #define XPAR 030 /* transparent mode indicator */ 134 #define FLSS 031 /* next Tchar contains vertical space */ 135 /* used when recalling diverted text */ 136 #define WORDSP 032 /* paddable word space */ 137 #define ESC 033 /* current escape character */ 138 #define XOFF 034 /* \X'...' ends here */ 139 /* matches XON, but they will probably never nest */ 140 /* so could drop this when another control is needed */ 141 #define HX 035 /* next character is value of \x'...' */ 142 #define MOTCH 036 /* this "character" is really motion; used by cbits() */ 143 144 #define HYPHEN c_hyphen 145 #define EMDASH c_emdash /* \(em */ 146 #define RULE c_rule /* \(ru */ 147 #define MINUS c_minus /* minus sign on current font */ 148 #define LIG_FI c_fi /* \(ff */ 149 #define LIG_FL c_fl /* \(fl */ 150 #define LIG_FF c_ff /* \(ff */ 151 #define LIG_FFI c_ffi /* \(Fi */ 152 #define LIG_FFL c_ffl /* \(Fl */ 153 #define ACUTE c_acute /* acute accent \(aa */ 154 #define GRAVE c_grave /* grave accent \(ga */ 155 #define UNDERLINE c_under /* \(ul */ 156 #define ROOTEN c_rooten /* root en \(rn */ 157 #define BOXRULE c_boxrule /* box rule \(br */ 158 #define LEFTHAND c_lefthand /* left hand for word overflow */ 159 #define DAGGER c_dagger /* dagger for end of sentence/footnote */ 160 161 #define HYPHALG 1 /* hyphenation algorithm: 0=>good old troff, 1=>tex */ 162 163 164 /* array sizes, and similar limits: */ 165 166 #define MAXFONTS 99 /* Maximum number of fonts in fontab */ 167 #define NM 90 /* requests + macros */ 168 #define NN NNAMES /* number registers */ 169 #define NNAMES 15 /* predefined reg names */ 170 #define NIF 15 /* if-else nesting */ 171 #define NS 128 /* name buffer */ 172 #define NTM 1024 /* tm buffer */ 173 #define NEV 3 /* environments */ 174 #define EVLSZ 10 /* size of ev stack */ 175 176 #define STACKSIZE (12*1024) /* stack for macros and strings in progress */ 177 #define NHYP 10 /* max hyphens per word */ 178 #define NHEX 512 /* byte size of exception word list */ 179 #define NTAB 100 /* tab stops */ 180 #define NSO 5 /* "so" depth */ 181 #define NMF 5 /* number of -m flags */ 182 #define WDSIZE 500 /* word buffer click size */ 183 #define LNSIZE 4000 /* line buffer click size */ 184 #define OLNSIZE 5000 /* output line buffer click; bigger for 'w', etc. */ 185 #define NDI 5 /* number of diversions */ 186 187 #define ALPHABET alphabet /* number of characters in basic alphabet. */ 188 /* 128 for parochial USA 7-bit ascii, */ 189 /* 256 for "European" mode with e.g., Latin-1 */ 190 191 /* NCHARS must be greater than 192 ALPHABET (ascii stuff) + total number of distinct char names 193 from all fonts that will be run in this job (including 194 unnamed ones and \N's) 195 */ 196 197 #define NCHARS (8*1024) /* maximum size of troff character set*/ 198 199 200 /* However for nroff you want only : 201 1. number of special codes in charset of DESC, which ends up being the 202 value of nchtab and which must be less than 512. 203 2. ALPHABET, which apparently is the size of the portion of the tables reserved 204 for special control symbols 205 Apparently the max N of \N is irrelevant; */ 206 /* to allow \N of up to 254 with up to 338 special characters 207 you need NCHARS of 338 + ALPHABET = 466 */ 208 209 #define NROFFCHARS 1024 /* maximum size of nroff character set */ 210 211 #define NTRTAB NCHARS /* number of items in trtab[] */ 212 #define NWIDCACHE NCHARS /* number of items in widcache[] */ 213 214 #define NTRAP 20 /* number of traps */ 215 #define NPN 20 /* numbers in "-o" */ 216 #define FBUFSZ 512 /* field buf size words */ 217 #define IBUFSZ 4096 /* bytes */ 218 #define NC 1024 /* cbuf size words */ 219 #define NOV 10 /* number of overstrike chars */ 220 #define NPP 10 /* pads per field */ 221 222 /* 223 Internal character representation: 224 Internally, every character is carried around as 225 a 32 bit cookie, called a "Tchar" (typedef long). 226 Bits are numbered 31..0 from left to right. 227 If bit 15 is 1, the character is motion, with 228 if bit 16 it's vertical motion 229 if bit 17 it's negative motion 230 If bit 15 is 0, the character is a real character. 231 if bit 31 zero motion 232 bits 30..24 size 233 bits 23..16 font 234 */ 235 236 /* in the following, "L" should really be a Tchar, but ... */ 237 /* numerology leaves room for 16 bit chars */ 238 239 #define MOT (01uL << 16) /* motion character indicator */ 240 #define VMOT (01uL << 30) /* vertical motion bit */ 241 #define NMOT (01uL << 29) /* negative motion indicator */ 242 /* #define MOTV (MOT|VMOT|NMOT) /* motion flags */ 243 /* #define MAXMOT (~MOTV) /* maximum motion permitted */ 244 #define MAXMOT 0xFFFF 245 246 #define ismot(n) ((n) & MOT) 247 #define isvmot(n) (((n) & (MOT|VMOT)) == (MOT|VMOT)) /* must have tested MOT previously */ 248 #define isnmot(n) (((n) & (MOT|NMOT)) == (MOT|NMOT)) /* ditto */ 249 #define absmot(n) ((n) & 0xFFFF) 250 251 #define ZBIT (01uL << 31) /* zero width char */ 252 #define iszbit(n) ((n) & ZBIT) 253 254 #define FSHIFT 17 255 #define SSHIFT (FSHIFT+7) 256 #define SMASK (0177uL << SSHIFT) /* 128 distinct sizes */ 257 #define FMASK (0177uL << FSHIFT) /* 128 distinct fonts */ 258 #define SFMASK (SMASK|FMASK) /* size and font in a Tchar */ 259 #define sbits(n) (((n) >> SSHIFT) & 0177) 260 #define fbits(n) (((n) >> FSHIFT) & 0177) 261 #define sfbits(n) (((n) & SFMASK) >> FSHIFT) 262 #define cbits(n) ((n) & 0x1FFFF) /* isolate character bits, */ 263 /* but don't include motions */ 264 extern int realcbits(Tchar); 265 266 #define setsbits(n,s) n = (n & ~SMASK) | (Tchar)(s) << SSHIFT 267 #define setfbits(n,f) n = (n & ~FMASK) | (Tchar)(f) << FSHIFT 268 #define setsfbits(n,sf) n = (n & ~SFMASK) | (Tchar)(sf) << FSHIFT 269 #define setcbits(n,c) n = (n & ~0xFFFFuL | (c)) /* set character bits */ 270 271 #define BYTEMASK 0377 272 #define BYTE 8 273 274 #define SHORTMASK 0XFFFF 275 #define SHORT 16 276 277 #define TABMASK ((unsigned) INT_MAX >> 1) 278 #define RTAB ((TABMASK << 1) & ~TABMASK) 279 #define CTAB (RTAB << 1) 280 281 #define TABBIT 02 /* bits in gchtab */ 282 #define LDRBIT 04 283 #define FCBIT 010 284 285 #define PAIR(A,B) (A|(B<<SHORT)) 286 287 288 extern int Inch, Hor, Vert, Unitwidth; 289 290 struct Spnames 291 { 292 int *n; 293 char *v; 294 }; 295 296 extern Spnames spnames[]; 297 298 /* 299 String and macro definitions are stored conceptually in a giant array 300 indexed by type Offset. In olden times, this array was real, and thus 301 both huge and limited in size, leading to the "Out of temp file space" 302 error. In this version, the array is represented by a list of blocks, 303 pointed to by blist[].bp. Each block is of size BLK Tchars, and BLK 304 MUST be a power of 2 for the macros below to work. 305 306 The blocks associated with a particular string or macro are chained 307 together in the array blist[]. Each blist[i].nextoff contains the 308 Offset associated with the next block in the giant array, or -1 if 309 this is the last block in the chain. If .nextoff is 0, the block is 310 free. 311 312 To find the right index in blist for an Offset, divide by BLK. 313 */ 314 315 #define NBLIST 2048 /* starting number of blocks in all definitions */ 316 317 #define BLK 128 /* number of Tchars in a block; must be 2^N with defns below */ 318 319 #define rbf0(o) (blist[bindex(o)].bp[boffset(o)]) 320 #define bindex(o) ((o) / BLK) 321 #define boffset(o) ((o) & (BLK-1)) 322 #define pastend(o) (((o) & (BLK-1)) == 0) 323 /* #define incoff(o) ( (++o & (BLK-1)) ? o : blist[bindex(o-1)].nextoff ) */ 324 #define incoff(o) ( (((o)+1) & (BLK-1)) ? o+1 : blist[bindex(o)].nextoff ) 325 326 #define skipline(f) while (getc(f) != '\n') 327 #define is(s) (strcmp(cmd, s) == 0) 328 #define eq(s1, s2) (strcmp(s1, s2) == 0) 329 330 331 typedef unsigned long Offset; /* an offset in macro/string storage */ 332 333 struct Blockp { /* info about a block: */ 334 Tchar *bp; /* the data */ 335 Offset nextoff; /* offset of next block in a chain */ 336 }; 337 338 extern Blockp *blist; 339 340 #define RD_OFFSET (1 * BLK) /* .rd command uses block 1 */ 341 342 struct Diver { /* diversion */ 343 Offset op; 344 int dnl; 345 int dimac; 346 int ditrap; 347 int ditf; 348 int alss; 349 int blss; 350 int nls; 351 int mkline; 352 int maxl; 353 int hnl; 354 int curd; 355 }; 356 357 struct Stack { /* stack frame */ 358 int nargs; 359 Stack *pframe; 360 Offset pip; 361 int pnchar; 362 Tchar prchar; 363 int ppendt; 364 Tchar pch; 365 Tchar *lastpbp; 366 int mname; 367 }; 368 369 extern Stack s; 370 371 struct Divsiz { 372 int dix; 373 int diy; 374 }; 375 376 struct Contab { /* command or macro */ 377 unsigned int rq; 378 Contab *link; 379 void (*f)(void); 380 Offset mx; 381 Offset emx; 382 Divsiz *divsiz; 383 }; 384 385 #define C(a,b) {a, 0, b, 0, 0} /* how to initialize a contab entry */ 386 387 extern Contab contab[NM]; 388 389 struct Numtab { /* number registers */ 390 unsigned int r; /* name */ 391 int val; 392 short fmt; 393 short inc; 394 Numtab *link; 395 }; 396 397 extern Numtab numtab[NN]; 398 399 #define PN 0 400 #define NL 1 401 #define YR 2 402 #define HP 3 403 #define CT 4 404 #define DN 5 405 #define MO 6 406 #define DY 7 407 #define DW 8 408 #define LN 9 409 #define DL 10 410 #define ST 11 411 #define SB 12 412 #define CD 13 413 #define PID 14 414 415 struct Wcache { /* width cache, indexed by character */ 416 short fontpts; 417 short width; 418 }; 419 420 struct Tbuf { /* growable Tchar buffer */ 421 Tchar *_bufp; 422 unsigned int _size; 423 }; 424 425 /* the infamous environment block */ 426 427 #define ics envp->_ics 428 #define sps envp->_sps 429 #define spacesz envp->_spacesz 430 #define lss envp->_lss 431 #define lss1 envp->_lss1 432 #define ll envp->_ll 433 #define ll1 envp->_ll1 434 #define lt envp->_lt 435 #define lt1 envp->_lt1 436 #define ic envp->_ic 437 #define icf envp->_icf 438 #define chbits envp->_chbits 439 #define spbits envp->_spbits 440 #define nmbits envp->_nmbits 441 #define apts envp->_apts 442 #define apts1 envp->_apts1 443 #define pts envp->_pts 444 #define pts1 envp->_pts1 445 #define font envp->_font 446 #define font1 envp->_font1 447 #define ls envp->_ls 448 #define ls1 envp->_ls1 449 #define ad envp->_ad 450 #define nms envp->_nms 451 #define ndf envp->_ndf 452 #define nmwid envp->_nmwid 453 #define fi envp->_fi 454 #define cc envp->_cc 455 #define c2 envp->_c2 456 #define ohc envp->_ohc 457 #define tdelim envp->_tdelim 458 #define hyf envp->_hyf 459 #define hyoff envp->_hyoff 460 #define hyphalg envp->_hyphalg 461 #define un1 envp->_un1 462 #define tabc envp->_tabc 463 #define dotc envp->_dotc 464 #define adsp envp->_adsp 465 #define adrem envp->_adrem 466 #define lastl envp->_lastl 467 #define nel envp->_nel 468 #define admod envp->_admod 469 #define wordp envp->_wordp 470 #define spflg envp->_spflg 471 #define linep envp->_linep 472 #define wdend envp->_wdend 473 #define wdstart envp->_wdstart 474 #define wne envp->_wne 475 #define ne envp->_ne 476 #define nc envp->_nc 477 #define nb envp->_nb 478 #define lnmod envp->_lnmod 479 #define nwd envp->_nwd 480 #define nn envp->_nn 481 #define ni envp->_ni 482 #define ul envp->_ul 483 #define cu envp->_cu 484 #define ce envp->_ce 485 #define in envp->_in 486 #define in1 envp->_in1 487 #define un envp->_un 488 #define wch envp->_wch 489 #define pendt envp->_pendt 490 #define pendw envp->_pendw 491 #define pendnf envp->_pendnf 492 #define spread envp->_spread 493 #define it envp->_it 494 #define itmac envp->_itmac 495 #define hyptr envp->_hyptr 496 #define tabtab envp->_tabtab 497 #define line envp->_line._bufp 498 #define lnsize envp->_line._size 499 #define word envp->_word._bufp 500 #define wdsize envp->_word._size 501 502 #define oline _oline._bufp 503 #define olnsize _oline._size 504 505 /* 506 * Note: 507 * If this structure changes in ni.c, you must change 508 * this as well, and vice versa. 509 */ 510 511 struct Env { 512 int _ics; 513 int _sps; 514 int _spacesz; 515 int _lss; 516 int _lss1; 517 int _ll; 518 int _ll1; 519 int _lt; 520 int _lt1; 521 Tchar _ic; 522 int _icf; 523 Tchar _chbits; 524 Tchar _spbits; 525 Tchar _nmbits; 526 int _apts; 527 int _apts1; 528 int _pts; 529 int _pts1; 530 int _font; 531 int _font1; 532 int _ls; 533 int _ls1; 534 int _ad; 535 int _nms; 536 int _ndf; 537 int _nmwid; 538 int _fi; 539 int _cc; 540 int _c2; 541 int _ohc; 542 int _tdelim; 543 int _hyf; 544 int _hyoff; 545 int _hyphalg; 546 int _un1; 547 int _tabc; 548 int _dotc; 549 int _adsp; 550 int _adrem; 551 int _lastl; 552 int _nel; 553 int _admod; 554 Tchar *_wordp; 555 int _spflg; 556 Tchar *_linep; 557 Tchar *_wdend; 558 Tchar *_wdstart; 559 int _wne; 560 int _ne; 561 int _nc; 562 int _nb; 563 int _lnmod; 564 int _nwd; 565 int _nn; 566 int _ni; 567 int _ul; 568 int _cu; 569 int _ce; 570 int _in; 571 int _in1; 572 int _un; 573 int _wch; 574 int _pendt; 575 Tchar *_pendw; 576 int _pendnf; 577 int _spread; 578 int _it; 579 int _itmac; 580 Tchar *_hyptr[NHYP]; 581 long _tabtab[NTAB]; 582 Tbuf _line; 583 Tbuf _word; 584 }; 585 586 extern Env env[]; 587 extern Env *envp; 588 589 enum { MBchar = 'U', Troffchar = 'C', Number = 'N', Install = 'i', Lookup = 'l' }; 590 /* U => utf, for instance; C => \(xx, N => \N'...' */ 591 592 593 594 struct Chwid { /* data on one character */ 595 Ushort num; /* character number: 596 0 -> not on this font 597 >= ALPHABET -> its number among all Cxy's */ 598 Ushort code; /* char code for actual device. used for \N */ 599 char *str; /* code string for nroff */ 600 Uchar wid; /* width */ 601 Uchar kern; /* ascender/descender */ 602 }; 603 604 struct Font { /* characteristics of a font */ 605 int name; /* int name, e.g., BI (2 chars) */ 606 char longname[64]; /* long name of this font (e.g., "Bembo" */ 607 char *truename; /* path name of table if not in standard place */ 608 int nchars; /* number of width entries for this font */ 609 char specfont; /* 1 == special font */ 610 int spacewidth; /* width of space on this font */ 611 int defaultwidth; /* default width of characters on this font */ 612 Chwid *wp; /* widths, etc., of the real characters */ 613 char ligfont; /* 1 == ligatures exist on this font */ 614 }; 615 616 /* ligatures, ORed into ligfont */ 617 618 #define LFF 01 619 #define LFI 02 620 #define LFL 04 621 #define LFFI 010 622 #define LFFL 020 623 624 /* tracing modes */ 625 #define TRNARGS 01 /* trace legality of numeric arguments */ 626 #define TRREQ 02 /* trace requests */ 627 #define TRMAC 04 /* trace macros */ 628 #define RQERR 01 /* processing request/macro */ 629 630 /* typewriter driving table structure */ 631 632 633 extern Term t; 634 struct Term { 635 int bset; /* these bits have to be on */ 636 int breset; /* these bits have to be off */ 637 int Hor; /* #units in minimum horiz motion */ 638 int Vert; /* #units in minimum vert motion */ 639 int Newline; /* #units in single line space */ 640 int Char; /* #units in character width */ 641 int Em; /* ditto */ 642 int Halfline; /* half line units */ 643 int Adj; /* minimum units for horizontal adjustment */ 644 char *twinit; /* initialize terminal */ 645 char *twrest; /* reinitialize terminal */ 646 char *twnl; /* terminal sequence for newline */ 647 char *hlr; /* half-line reverse */ 648 char *hlf; /* half-line forward */ 649 char *flr; /* full-line reverse */ 650 char *bdon; /* turn bold mode on */ 651 char *bdoff; /* turn bold mode off */ 652 char *iton; /* turn italic mode on */ 653 char *itoff; /* turn italic mode off */ 654 char *ploton; /* turn plot mode on */ 655 char *plotoff; /* turn plot mode off */ 656 char *up; /* sequence to move up in plot mode */ 657 char *down; /* ditto */ 658 char *right; /* ditto */ 659 char *left; /* ditto */ 660 661 Font tfont; /* widths and other info, as in a troff font */ 662 }; 663 664 extern Term t; 665 666 /* 667 * for error reporting; keep track of escapes/requests with numeric arguments 668 */ 669 struct Numerr { 670 char type; /* request or escape? */ 671 char esc; /* was escape sequence named esc */ 672 char escarg; /* argument of esc's like \D'l' */ 673 unsigned int req; /* was request or macro named req */ 674 }; 675