1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 /* 34 * University Copyright- Copyright (c) 1982, 1986, 1988 35 * The Regents of the University of California 36 * All Rights Reserved 37 * 38 * University Acknowledgment- Portions of this document are derived from 39 * software developed by the University of California, Berkeley, and its 40 * contributors. 41 */ 42 43 char *xxxvers = "@(#)roff:n1.c 2.13"; 44 /* 45 * n1.c 46 * 47 * consume options, initialization, main loop, 48 * input routines, escape function calling 49 */ 50 51 #include <ctype.h> 52 #include <signal.h> 53 #include <sys/types.h> 54 #include <sys/stat.h> 55 #include <setjmp.h> 56 #include <time.h> 57 #include <stdarg.h> 58 #include <locale.h> 59 #include <fcntl.h> 60 #include <stdlib.h> 61 #include <string.h> 62 #ifdef EUC 63 #ifdef NROFF 64 #include <stddef.h> 65 #include <limits.h> 66 #endif /* NROFF */ 67 #endif /* EUC */ 68 69 #include "tdef.h" 70 #include "ext.h" 71 72 #ifdef NROFF 73 #include "tw.h" 74 #endif 75 76 #define MAX_RECURSION_DEPTH 512 77 78 jmp_buf sjbuf; 79 extern void fdprintf(int, char *, ...); 80 extern char *roff_sprintf(char *, char *, ...); 81 filep ipl[NSO]; 82 long offl[NSO]; 83 long ioff; 84 char *ttyp; 85 char cfname[NSO+1][NS]; /*file name stack*/ 86 int cfline[NSO]; /*input line count stack*/ 87 char *progname; /* program name (troff) */ 88 #ifdef EUC 89 #ifdef NROFF 90 char mbbuf1[MB_LEN_MAX + 1]; 91 char *mbbuf1p = mbbuf1; 92 wchar_t twc = 0; 93 #endif /* NROFF */ 94 #endif /* EUC */ 95 96 #ifdef DEBUG 97 int debug = 0; /*debug flag*/ 98 #endif DEBUG 99 100 main(argc, argv) 101 int argc; 102 char **argv; 103 { 104 register char *p, *q; 105 register j; 106 register tchar i; 107 int eileenct; /*count to test for "Eileen's loop"*/ 108 extern void catch(), kcatch(); 109 char **oargv, *getenv(); 110 111 (void)setlocale(LC_ALL, ""); 112 #if !defined(TEXT_DOMAIN) 113 #define TEXT_DOMAIN "SYS_TEST" 114 #endif 115 (void)textdomain(TEXT_DOMAIN); 116 progname = argv[0]; 117 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) 118 signal(SIGHUP, catch); 119 if (signal(SIGINT, catch) == SIG_IGN) { 120 signal(SIGHUP, SIG_IGN); 121 signal(SIGINT, SIG_IGN); 122 signal(SIGQUIT, SIG_IGN); 123 } 124 signal(SIGPIPE, catch); 125 signal(SIGTERM, kcatch); 126 oargv = argv; 127 strcpy(cfname[0], "<standard input>"); 128 mrehash(); 129 nrehash(); 130 init0(); 131 #ifdef EUC 132 #ifdef NROFF 133 (void)localize(); 134 #endif /* NROFF */ 135 #endif /* EUC */ 136 if ((p = getenv("TYPESETTER")) != 0) 137 strcpy(devname, p); 138 while (--argc > 0 && (++argv)[0][0] == '-') 139 switch (argv[0][1]) { 140 141 case 'F': /* switch font tables from default */ 142 if (argv[0][2] != '\0') { 143 strcpy(termtab, &argv[0][2]); 144 strcpy(fontfile, &argv[0][2]); 145 } else { 146 argv++; argc--; 147 if (argv[0] != '\0') { 148 strcpy(termtab, argv[0]); 149 strcpy(fontfile, argv[0]); 150 } else 151 errprint(gettext("missing the font directory")); 152 } 153 continue; 154 case 0: 155 goto start; 156 case 'i': 157 stdi++; 158 continue; 159 case 'q': 160 #ifdef NROFF 161 quiet++; 162 save_tty(); 163 #else 164 errprint(gettext("-q option ignored in troff")); 165 #endif NROFF 166 continue; 167 case 'n': 168 npn = ctoi(&argv[0][2]); 169 continue; 170 case 'u': /* set emboldening amount */ 171 bdtab[3] = ctoi(&argv[0][2]); 172 if (bdtab[3] < 0 || bdtab[3] > 50) 173 bdtab[3] = 0; 174 continue; 175 case 's': 176 if (!(stop = ctoi(&argv[0][2]))) 177 stop++; 178 continue; 179 case 't': 180 ptid = 1; 181 continue; 182 case 'r': 183 if (&argv[0][2] != '\0' && strlen(&argv[0][2]) >= 2 && &argv[0][3] != '\0') 184 eibuf = roff_sprintf(ibuf+strlen(ibuf), ".nr %c %s\n", 185 argv[0][2], &argv[0][3]); 186 else 187 errprint(gettext("wrong options")); 188 continue; 189 case 'c': 190 case 'm': 191 if (mflg++ >= NMF) { 192 errprint(gettext("Too many macro packages: %s"), 193 argv[0]); 194 continue; 195 } 196 if (argv[0][2] == '\0') { 197 errprint(gettext("No library provided with -m")); 198 done(02); 199 } 200 if (getenv("TROFFMACS") != '\0') { 201 if (tryfile(getenv("TROFFMACS"), &argv[0][2], nmfi)) 202 nmfi++; 203 } else 204 if (tryfile("/usr/share/lib/tmac/", &argv[0][2], nmfi) 205 || tryfile("/usr/share/lib/tmac/tmac.", &argv[0][2], nmfi)) 206 nmfi++; 207 else { 208 errprint(gettext("Cannot find library %s\n"), 209 argv[0]); 210 done(02); 211 } 212 continue; 213 case 'o': 214 getpn(&argv[0][2]); 215 continue; 216 case 'T': 217 strcpy(devname, &argv[0][2]); 218 dotT++; 219 continue; 220 #ifdef NROFF 221 case 'h': 222 hflg++; 223 continue; 224 case 'z': 225 no_out++; 226 continue; 227 case 'e': 228 eqflg++; 229 continue; 230 #endif 231 #ifndef NROFF 232 case 'z': 233 no_out++; 234 case 'a': 235 ascii = 1; 236 nofeed++; 237 continue; 238 case 'f': 239 nofeed++; 240 continue; 241 #endif 242 case '#': 243 #ifdef DEBUG 244 debug = ctoi(&argv[0][2]); 245 #else 246 errprint("DEBUG not enabled"); 247 #endif DEBUG 248 continue; 249 default: 250 errprint(gettext("unknown option %s"), argv[0]); 251 done(02); 252 } 253 254 start: 255 init1(oargv[0][0]); 256 argp = argv; 257 rargc = argc; 258 nmfi = 0; 259 init2(); 260 setjmp(sjbuf); 261 eileenct = 0; /*reset count for "Eileen's loop"*/ 262 loop: 263 copyf = lgf = nb = nflush = nlflg = 0; 264 if (ip && rbf0(ip) == 0 && ejf && frame->pframe <= ejl) { 265 nflush++; 266 trap = 0; 267 eject((struct s *)0); 268 #ifdef DEBUG 269 if (debug & DB_LOOP) 270 fdprintf(stderr, "loop: NL=%d, ejf=%d, lss=%d, eileenct=%d\n", 271 numtab[NL].val, ejf, lss, eileenct); 272 #endif DEBUG 273 if (eileenct > 20) { 274 errprint(gettext("job looping; check abuse of macros")); 275 ejf = 0; /*try to break Eileen's loop*/ 276 eileenct = 0; 277 } else 278 eileenct++; 279 goto loop; 280 } 281 eileenct = 0; /*reset count for "Eileen's loop"*/ 282 i = getch(); 283 if (pendt) 284 goto Lt; 285 if ((j = cbits(i)) == XPAR) { 286 copyf++; 287 tflg++; 288 while (cbits(i) != '\n') 289 pchar(i = getch()); 290 tflg = 0; 291 copyf--; 292 goto loop; 293 } 294 if (j == cc || j == c2) { 295 if (j == c2) 296 nb++; 297 copyf++; 298 while ((j = cbits(i = getch())) == ' ' || j == '\t') 299 ; 300 ch = i; 301 copyf--; 302 control(getrq(), 1); 303 flushi(); 304 goto loop; 305 } 306 Lt: 307 ch = i; 308 text(); 309 if (nlflg) 310 numtab[HP].val = 0; 311 goto loop; 312 } 313 314 315 tryfile(pat, fn, idx) 316 register char *pat, *fn; 317 int idx; 318 { 319 strcpy(mfiles[idx], pat); 320 strcat(mfiles[idx], fn); 321 if (access(mfiles[idx], 4) == -1) 322 return(0); 323 else return(1); 324 } 325 326 void catch() 327 { 328 done3(01); 329 } 330 331 332 void kcatch() 333 { 334 signal(SIGTERM, SIG_IGN); 335 done3(01); 336 } 337 338 339 init0() 340 { 341 eibuf = ibufp = ibuf; 342 ibuf[0] = 0; 343 numtab[NL].val = -1; 344 } 345 346 347 init1(a) 348 char a; 349 { 350 register char *p; 351 register i; 352 353 p = tmp_name; 354 if (a == 'a') 355 p = &p[9]; 356 if ((ibf = mkstemp(p)) == -1) { 357 errprint(gettext("cannot create temp file.")); 358 exit(-1); 359 } 360 unlkp = p; 361 for (i = NTRTAB; --i; ) 362 trtab[i] = i; 363 trtab[UNPAD] = ' '; 364 } 365 366 367 init2() 368 { 369 register i, j; 370 extern char *setbrk(); 371 extern char *ttyname(); 372 373 ttyod = 2; 374 if ((ttyp=ttyname(j=0)) != 0 || (ttyp=ttyname(j=1)) != 0 || (ttyp=ttyname(j=2)) != 0) 375 ; 376 else 377 ttyp = "notty"; 378 iflg = j; 379 if (ascii) 380 mesg(0); 381 obufp = obuf; 382 ptinit(); 383 mchbits(); 384 cvtime(); 385 numtab[PID].val = getpid(); 386 olinep = oline; 387 ioff = 0; 388 numtab[HP].val = init = 0; 389 numtab[NL].val = -1; 390 nfo = 0; 391 ifile = 0; 392 copyf = raw = 0; 393 eibuf = roff_sprintf(ibuf+strlen(ibuf), ".ds .T %s\n", devname); 394 numtab[CD].val = -1; /* compensation */ 395 cpushback(ibuf); 396 ibufp = ibuf; 397 nx = mflg; 398 frame = stk = (struct s *)setbrk(DELTA); 399 dip = &d[0]; 400 nxf = frame + 1; 401 #ifdef INCORE 402 for (i = 0; i < NEV; i++) { 403 extern tchar corebuf[]; 404 *(struct env *)&corebuf[i * sizeof(env)/sizeof(tchar)] = env; 405 } 406 #else 407 for (i = NEV; i--; ) 408 write(ibf, (char *) & env, sizeof(env)); 409 #endif 410 } 411 412 413 cvtime() 414 { 415 time_t tt; 416 register struct tm *tm; 417 418 tt = time((time_t *) 0); 419 tm = localtime(&tt); 420 numtab[DY].val = tm->tm_mday; 421 numtab[DW].val = tm->tm_wday + 1; 422 numtab[YR].val = tm->tm_year; 423 numtab[MO].val = tm->tm_mon + 1; 424 425 } 426 427 428 ctoi(s) 429 register char *s; 430 { 431 register n; 432 433 while (*s == ' ') 434 s++; 435 n = 0; 436 while (isdigit((unsigned char)*s)) 437 n = 10 * n + *s++ - '0'; 438 return n; 439 } 440 441 442 mesg(f) 443 int f; 444 { 445 static int mode; 446 struct stat stbuf; 447 448 if (!f) { 449 stat(ttyp, &stbuf); 450 mode = stbuf.st_mode; 451 chmod(ttyp, mode & ~0122); /* turn off writing for others */ 452 } else { 453 if (ttyp && *ttyp && mode) 454 chmod(ttyp, mode); 455 } 456 } 457 458 errprint(s, s1, s2, s3, s4, s5) /* error message printer */ 459 char *s, *s1, *s2, *s3, *s4, *s5; 460 { 461 fdprintf(stderr, "%s: ", progname); 462 fdprintf(stderr, s, s1, s2, s3, s4, s5); 463 if (numtab[CD].val > 0) 464 fdprintf(stderr, gettext("; line %d, file %s"), numtab[CD].val, 465 cfname[ifi]); 466 fdprintf(stderr, "\n"); 467 stackdump(); 468 #ifdef DEBUG 469 if (debug) 470 abort(); 471 #endif DEBUG 472 } 473 474 475 /* 476 * Scaled down version of C Library printf. 477 * Only %s %u %d (==%u) %o %c %x %D are recognized. 478 */ 479 #undef putchar 480 #define putchar(n) (*pfbp++ = (n)) /* NO CHECKING! */ 481 482 static char pfbuf[NTM]; 483 static char *pfbp = pfbuf; 484 int stderr = 2; /* NOT stdio value */ 485 486 void 487 fdprintf(int fd, char *fmt, ...) 488 { 489 register c; 490 char *s; 491 register i; 492 va_list ap; 493 494 pfbp = pfbuf; 495 va_start(ap, fmt); 496 loop: 497 while ((c = *fmt++) != '%') { 498 if (c == '\0') { 499 if (fd == stderr) 500 write(stderr, pfbuf, pfbp - pfbuf); 501 else { 502 *pfbp = 0; 503 pfbp = pfbuf; 504 while (*pfbp) { 505 *obufp++ = *pfbp++; 506 if (obufp >= &obuf[OBUFSZ]) 507 flusho(); 508 } 509 } 510 va_end(ap); 511 return; 512 } 513 putchar(c); 514 } 515 c = *fmt++; 516 if (c == 'd') { 517 i = va_arg(ap, int); 518 if (i < 0) { 519 putchar('-'); 520 i = -i; 521 } 522 printn((long)i, 10); 523 } else if (c == 'u' || c == 'o' || c == 'x') 524 printn(va_arg(ap, long), c == 'o' ? 8 : (c == 'x' ? 16 : 10)); 525 else if (c == 'c') { 526 if (c > 0177 || c < 040) 527 putchar('\\'); 528 putchar(va_arg(ap, int) & 0177); 529 } else if (c == 's') { 530 s = va_arg(ap, char *); 531 while (c = *s++) 532 putchar(c); 533 } else if (c == 'D') { 534 printn(va_arg(ap, long), 10); 535 } else if (c == 'O') { 536 printn(va_arg(ap, long), 8); 537 } 538 goto loop; 539 } 540 541 542 /* 543 * Print an unsigned integer in base b. 544 */ 545 static printn(n, b) 546 register long n; 547 { 548 register long a; 549 550 if (n < 0) { /* shouldn't happen */ 551 putchar('-'); 552 n = -n; 553 } 554 if (a = n / b) 555 printn(a, b); 556 putchar("0123456789ABCDEF"[(int)(n%b)]); 557 } 558 559 /* scaled down version of library roff_sprintf */ 560 /* same limits as fdprintf */ 561 /* returns pointer to \0 that ends the string */ 562 563 /* VARARGS2 */ 564 char *roff_sprintf(char *str, char *fmt, ...) 565 { 566 register c; 567 char *sprintn(); 568 char *s; 569 register i; 570 va_list ap; 571 572 va_start(ap, fmt); 573 loop: 574 while ((c = *fmt++) != '%') { 575 if (c == '\0') { 576 *str = 0; 577 va_end(ap); 578 return str; 579 } 580 *str++ = c; 581 } 582 c = *fmt++; 583 if (c == 'd') { 584 i = va_arg(ap, int); 585 if (i < 0) { 586 *str++ = '-'; 587 i = -i; 588 } 589 str = sprintn(str, (long)i, 10); 590 } else if (c == 'u' || c == 'o' || c == 'x') 591 str = sprintn(str, va_arg(ap, long), c == 'o' ? 8 : (c == 'x' ? 16 : 10)); 592 else if (c == 'c') { 593 if (c > 0177 || c < 040) 594 *str++ = '\\'; 595 *str++ = va_arg(ap, int) & 0177; 596 } else if (c == 's') { 597 s = va_arg(ap, char *); 598 while (c = *s++) 599 *str++ = c; 600 } else if (c == 'D') { 601 str = sprintn(str, va_arg(ap, long), 10); 602 } else if (c == 'O') { 603 str = sprintn(str, va_arg(ap, unsigned) , 8); 604 } 605 goto loop; 606 } 607 608 /* 609 * Print an unsigned integer in base b. 610 */ 611 static char *sprintn(s, n, b) 612 register char *s; 613 register long n; 614 { 615 register long a; 616 617 if (n < 0) { /* shouldn't happen */ 618 *s++ = '-'; 619 n = -n; 620 } 621 if (a = n / b) 622 s = sprintn(s, a, b); 623 *s++ = "0123456789ABCDEF"[(int)(n%b)]; 624 return s; 625 } 626 627 628 control(a, b) 629 register int a, b; 630 { 631 register int j; 632 633 if (a == 0 || (j = findmn(a)) == -1) 634 return(0); 635 636 /* 637 * Attempt to find endless recursion at runtime. Arbitrary 638 * recursion limit of MAX_RECURSION_DEPTH was chosen as 639 * it is extremely unlikely that a correct nroff/troff 640 * invocation would exceed this value. 641 */ 642 643 if (frame != stk) { 644 int frame_cnt = 0; 645 struct s *p; 646 647 for (p = frame; p != stk; p = p->pframe) 648 frame_cnt++; 649 if (frame_cnt > MAX_RECURSION_DEPTH) { 650 errprint( 651 gettext("Exceeded maximum stack size (%d) when " 652 "executing macro %c%c. Stack dump follows"), 653 MAX_RECURSION_DEPTH, 654 frame->mname & 0177, (frame->mname >> BYTE) & 0177); 655 edone(02); 656 } 657 } 658 659 #ifdef DEBUG 660 if (debug & DB_MAC) 661 fdprintf(stderr, "control: macro %c%c, contab[%d]\n", 662 a&0177, (a>>BYTE)&0177 ? (a>>BYTE)&0177 : ' ', j); 663 #endif DEBUG 664 if (contab[j].f == 0) { 665 nxf->nargs = 0; 666 if (b) 667 collect(); 668 flushi(); 669 return pushi((filep)contab[j].mx, a); 670 } else if (b) 671 return((*contab[j].f)(0)); 672 else 673 return(0); 674 } 675 676 677 getrq() 678 { 679 register i, j; 680 681 if (((i = getach()) == 0) || ((j = getach()) == 0)) 682 goto rtn; 683 i = PAIR(i, j); 684 rtn: 685 return(i); 686 } 687 688 /* 689 * table encodes some special characters, to speed up tests 690 * in getchar, viz FLSS, RPT, f, \b, \n, fc, tabch, ldrch 691 */ 692 693 char 694 gchtab[] = { 695 000,004,000,000,010,000,000,000, /* fc, ldr */ 696 001,002,001,000,001,000,000,000, /* \b, tab, nl, RPT */ 697 000,000,000,000,000,000,000,000, 698 000,001,000,000,000,000,000,000, /* FLSS */ 699 000,000,000,000,000,000,000,000, 700 000,000,000,000,000,000,000,000, 701 000,000,000,000,000,000,000,000, 702 000,000,000,000,000,000,000,000, 703 000,000,000,000,000,000,000,000, 704 000,000,000,000,000,000,000,000, 705 000,000,000,000,000,000,000,000, 706 000,000,000,000,000,000,000,000, 707 000,000,000,000,000,000,001,000, /* f */ 708 000,000,000,000,000,000,000,000, 709 000,000,000,000,000,000,000,000, 710 000,000,000,000,000,000,000,000, 711 }; 712 713 tchar 714 getch() 715 { 716 register int k; 717 register tchar i, j; 718 tchar setht(), setslant(); 719 720 g0: 721 if (i = ch) { 722 #ifdef DEBUG 723 if (debug & DB_GETC) 724 fdprintf(stderr, "getch: ch is %x (%c)\n", 725 ch, (ch&0177) < 040 ? 0177 : ch&0177); 726 #endif DEBUG 727 if (cbits(i) == '\n') 728 nlflg++; 729 ch = 0; 730 return(i); 731 } 732 733 #ifdef DEBUG 734 if (nlflg) 735 if (debug & DB_GETC) 736 fdprintf(stderr,"getch: nlflg is %x\n", nlflg); 737 #endif DEBUG 738 if (nlflg) 739 return('\n'); 740 i = getch0(); 741 #ifdef DEBUG 742 if (debug & DB_GETC) 743 fdprintf(stderr, "getch: getch0 returns %x (%c)\n", 744 i, (i&0177) < 040 ? 0177 : i&0177); 745 #endif DEBUG 746 if (ismot(i)) 747 return(i); 748 k = cbits(i); 749 if (k != ESC) { 750 /* 751 * gchtab[] has only 128 entries 752 * if k is out of the range, it should be 753 * handled as gchtab[k] == 0 754 */ 755 if (!isascii(k) || gchtab[k]==0) 756 return(i); 757 if (k == '\n') { 758 if (cbits(i) == '\n') { 759 nlflg++; 760 if (ip == 0) 761 numtab[CD].val++; /* line number */ 762 } 763 return(k); 764 } 765 if (k == FLSS) { 766 copyf++; 767 raw++; 768 i = getch0(); 769 if (!fi) 770 flss = i; 771 copyf--; 772 raw--; 773 goto g0; 774 } 775 if (k == RPT) { 776 setrpt(); 777 goto g0; 778 } 779 if (!copyf) { 780 if (k == 'f' && lg && !lgf) { 781 i = getlg(i); 782 return(i); 783 } 784 if (k == fc || k == tabch || k == ldrch) { 785 if ((i = setfield(k)) == 0) 786 goto g0; 787 else 788 return(i); 789 } 790 if (k == '\b') { 791 i = makem(-width(' ' | chbits)); 792 return(i); 793 } 794 } 795 return(i); 796 } 797 k = cbits(j = getch0()); 798 if (ismot(j)) 799 return(j); 800 switch (k) { 801 802 case 'X': /* \X'...' for copy through */ 803 setxon(); 804 goto g0; 805 case '\n': /* concealed newline */ 806 goto g0; 807 case 'n': /* number register */ 808 setn(); 809 goto g0; 810 case '*': /* string indicator */ 811 setstr(); 812 goto g0; 813 case '$': /* argument indicator */ 814 seta(); 815 goto g0; 816 case '{': /* LEFT */ 817 i = LEFT; 818 goto gx; 819 case '}': /* RIGHT */ 820 i = RIGHT; 821 goto gx; 822 case '"': /* comment */ 823 while (cbits(i = getch0()) != '\n') 824 ; 825 nlflg++; 826 if (ip == 0) 827 numtab[CD].val++; 828 return(i); 829 case ESC: /* double backslash */ 830 i = eschar; 831 goto gx; 832 case 'e': /* printable version of current eschar */ 833 i = PRESC; 834 goto gx; 835 case ' ': /* unpaddable space */ 836 i = UNPAD; 837 goto gx; 838 case '\'': /* \(aa */ 839 i = ACUTE; 840 goto gx; 841 case '`': /* \(ga */ 842 i = GRAVE; 843 goto gx; 844 case '_': /* \(ul */ 845 i = UNDERLINE; 846 goto gx; 847 case '-': /* current font minus */ 848 i = MINUS; 849 goto gx; 850 case '&': /* filler */ 851 i = FILLER; 852 goto gx; 853 case 'c': /* to be continued */ 854 i = CONT; 855 goto gx; 856 case '!': /* transparent indicator */ 857 i = XPAR; 858 goto gx; 859 case 't': /* tab */ 860 i = '\t'; 861 return(i); 862 case 'a': /* leader (SOH) */ 863 i = LEADER; 864 return(i); 865 case '%': /* ohc */ 866 i = OHC; 867 return(i); 868 case 'g': /* return format of a number register */ 869 setaf(); 870 goto g0; 871 case 'N': /* absolute character number */ 872 i = setabs(); 873 goto gx; 874 case '.': /* . */ 875 i = '.'; 876 gx: 877 setsfbits(i, sfbits(j)); 878 return(i); 879 } 880 if (copyf) { 881 *pbp++ = j; 882 return(eschar); 883 } 884 switch (k) { 885 886 case 'p': /* spread */ 887 spread++; 888 goto g0; 889 case '(': /* special char name */ 890 if ((i = setch()) == 0) 891 goto g0; 892 return(i); 893 case 's': /* size indicator */ 894 setps(); 895 goto g0; 896 case 'H': /* character height */ 897 return(setht()); 898 case 'S': /* slant */ 899 return(setslant()); 900 case 'f': /* font indicator */ 901 setfont(0); 902 goto g0; 903 case 'w': /* width function */ 904 setwd(); 905 goto g0; 906 case 'v': /* vert mot */ 907 if (i = vmot()) 908 return(i); 909 goto g0; 910 case 'h': /* horiz mot */ 911 if (i = hmot()) 912 return(i); 913 goto g0; 914 case 'z': /* zero with char */ 915 return(setz()); 916 case 'l': /* hor line */ 917 setline(); 918 goto g0; 919 case 'L': /* vert line */ 920 setvline(); 921 goto g0; 922 case 'D': /* drawing function */ 923 setdraw(); 924 goto g0; 925 case 'b': /* bracket */ 926 setbra(); 927 goto g0; 928 case 'o': /* overstrike */ 929 setov(); 930 goto g0; 931 case 'k': /* mark hor place */ 932 if ((k = findr(getsn())) != -1) { 933 numtab[k].val = numtab[HP].val; 934 } 935 goto g0; 936 case '0': /* number space */ 937 return(makem(width('0' | chbits))); 938 #ifdef NROFF 939 case '|': 940 case '^': 941 goto g0; 942 #else 943 case '|': /* narrow space */ 944 return(makem((int)(EM)/6)); 945 case '^': /* half narrow space */ 946 return(makem((int)(EM)/12)); 947 #endif 948 case 'x': /* extra line space */ 949 if (i = xlss()) 950 return(i); 951 goto g0; 952 case 'u': /* half em up */ 953 case 'r': /* full em up */ 954 case 'd': /* half em down */ 955 return(sethl(k)); 956 default: 957 return(j); 958 } 959 /* NOTREACHED */ 960 } 961 962 setxon() /* \X'...' for copy through */ 963 { 964 tchar xbuf[NC]; 965 register tchar *i; 966 tchar c; 967 int delim, k; 968 969 if (ismot(c = getch())) 970 return; 971 delim = cbits(c); 972 i = xbuf; 973 *i++ = XON; 974 while ((k = cbits(c = getch())) != delim && k != '\n' && i < xbuf+NC-1) { 975 if (k == ' ') 976 setcbits(c, UNPAD); 977 *i++ = c | ZBIT; 978 } 979 *i++ = XOFF; 980 *i = 0; 981 pushback(xbuf); 982 } 983 984 985 char ifilt[32] = { 986 0, 001, 002, 003, 0, 005, 006, 007, 010, 011, 012}; 987 988 tchar getch0() 989 { 990 register int j; 991 register tchar i; 992 #ifdef EUC 993 #ifdef NROFF 994 register int n; 995 int col_index; 996 #endif /* NROFF */ 997 #endif /* EUC */ 998 999 again: 1000 if (pbp > lastpbp) 1001 i = *--pbp; 1002 else if (ip) { 1003 #ifdef INCORE 1004 extern tchar corebuf[]; 1005 i = corebuf[ip]; 1006 if (i == 0) 1007 i = rbf(); 1008 else { 1009 if ((++ip & (BLK - 1)) == 0) { 1010 --ip; 1011 (void)rbf(); 1012 } 1013 } 1014 #else 1015 i = rbf(); 1016 #endif 1017 } else { 1018 if (donef || ndone) 1019 done(0); 1020 if (nx || ibufp >= eibuf) { 1021 if (nfo==0) { 1022 g0: 1023 if (nextfile()) { 1024 if (ip) 1025 goto again; 1026 if (ibufp < eibuf) 1027 goto g2; 1028 } 1029 } 1030 nx = 0; 1031 if ((j = read(ifile, ibuf, IBUFSZ)) <= 0) 1032 goto g0; 1033 ibufp = ibuf; 1034 eibuf = ibuf + j; 1035 if (ip) 1036 goto again; 1037 } 1038 g2: 1039 #ifndef EUC 1040 i = *ibufp++ & 0177; 1041 ioff++; 1042 if (i >= 040 && i < 0177) 1043 #else 1044 #ifndef NROFF 1045 i = *ibufp++ & 0177; 1046 ioff++; 1047 if (i >= 040 && i < 0177) 1048 #else 1049 i = *ibufp++ & 0377; 1050 *mbbuf1p++ = i; 1051 *mbbuf1p = 0; 1052 if (!multi_locale) { 1053 twc = 0; 1054 mbbuf1p = mbbuf1; 1055 } else if ((n = mbtowc(&twc, mbbuf1, MB_CUR_MAX)) <= 0) { 1056 if (mbbuf1p >= mbbuf1 + MB_CUR_MAX) { 1057 i &= ~(MBMASK | CSMASK); 1058 twc = 0; 1059 mbbuf1p = mbbuf1; 1060 *mbbuf1p = 0; 1061 } else { 1062 i |= (MIDDLEOFMB); 1063 } 1064 } else { 1065 if (n > 1) 1066 i |= (LASTOFMB); 1067 else 1068 i |= (BYTE_CHR); 1069 if (isascii(twc)) { 1070 col_index = 0; 1071 } else { 1072 if ((col_index = wcwidth(twc)) < 0) 1073 col_index = 0; 1074 } 1075 setcsbits(i, col_index); 1076 twc = 0; 1077 mbbuf1p = mbbuf1; 1078 } 1079 ioff++; 1080 if (i >= 040 && i != 0177) 1081 #endif /* NROFF */ 1082 #endif /* EUC */ 1083 goto g4; 1084 if (i != 0177) 1085 i = ifilt[i]; 1086 } 1087 if (cbits(i) == IMP && !raw) 1088 goto again; 1089 if ((i == 0 || i == 0177) && !init && !raw) { 1090 goto again; 1091 } 1092 g4: 1093 #ifndef EUC 1094 if (copyf == 0 && (i & ~BYTEMASK) == 0) 1095 #else 1096 #ifndef NROFF 1097 if (copyf == 0 && (i & ~BYTEMASK) == 0) 1098 #else 1099 if (copyf == 0 && (i & ~CHMASK) == 0) 1100 #endif /* NROFF */ 1101 #endif /* EUC */ 1102 i |= chbits; 1103 #ifdef EUC 1104 #ifdef NROFF 1105 if (multi_locale) 1106 if (i & MBMASK1) 1107 i |= ZBIT; 1108 #endif /* NROFF */ 1109 #endif /* EUC */ 1110 if (cbits(i) == eschar && !raw) 1111 setcbits(i, ESC); 1112 return(i); 1113 } 1114 1115 pushback(b) 1116 register tchar *b; 1117 { 1118 register tchar *ob = b; 1119 1120 while (*b++) 1121 ; 1122 b--; 1123 while (b > ob && pbp < &pbbuf[NC-3]) 1124 *pbp++ = *--b; 1125 if (pbp >= &pbbuf[NC-3]) { 1126 errprint(gettext("pushback overflow")); 1127 done(2); 1128 } 1129 } 1130 1131 cpushback(b) 1132 register char *b; 1133 { 1134 register char *ob = b; 1135 1136 while (*b++) 1137 ; 1138 b--; 1139 while (b > ob && pbp < &pbbuf[NC-3]) 1140 *pbp++ = *--b; 1141 if (pbp >= &pbbuf[NC-3]) { 1142 errprint(gettext("cpushback overflow")); 1143 done(2); 1144 } 1145 } 1146 1147 nextfile() 1148 { 1149 register char *p; 1150 1151 n0: 1152 if (ifile) 1153 close(ifile); 1154 if (nx || nmfi < mflg) { 1155 p = mfiles[nmfi++]; 1156 if (*p != 0) 1157 goto n1; 1158 } 1159 if (ifi > 0) { 1160 if (popf()) 1161 goto n0; /* popf error */ 1162 return(1); /* popf ok */ 1163 } 1164 if (rargc-- <= 0) { 1165 if ((nfo -= mflg) && !stdi) 1166 done(0); 1167 nfo++; 1168 numtab[CD].val = ifile = stdi = mflg = 0; 1169 strcpy(cfname[ifi], "<standard input>"); 1170 ioff = 0; 1171 return(0); 1172 } 1173 p = (argp++)[0]; 1174 n1: 1175 numtab[CD].val = 0; 1176 if (p[0] == '-' && p[1] == 0) { 1177 ifile = 0; 1178 strcpy(cfname[ifi], "<standard input>"); 1179 } else if ((ifile = open(p, 0)) < 0) { 1180 errprint(gettext("cannot open file %s"), p); 1181 nfo -= mflg; 1182 done(02); 1183 } else 1184 strcpy(cfname[ifi],p); 1185 nfo++; 1186 ioff = 0; 1187 return(0); 1188 } 1189 1190 1191 popf() 1192 { 1193 register i; 1194 register char *p, *q; 1195 extern char *ttyname(); 1196 1197 ioff = offl[--ifi]; 1198 numtab[CD].val = cfline[ifi]; /*restore line counter*/ 1199 ip = ipl[ifi]; 1200 if ((ifile = ifl[ifi]) == 0) { 1201 p = xbuf; 1202 q = ibuf; 1203 ibufp = xbufp; 1204 eibuf = xeibuf; 1205 while (q < eibuf) 1206 *q++ = *p++; 1207 return(0); 1208 } 1209 if (lseek(ifile, (long)(ioff & ~(IBUFSZ-1)), 0) == (long) -1 1210 || (i = read(ifile, ibuf, IBUFSZ)) < 0) 1211 return(1); 1212 eibuf = ibuf + i; 1213 ibufp = ibuf; 1214 if (ttyname(ifile) == 0) 1215 /* was >= ... */ 1216 if ((ibufp = ibuf + (int)(ioff & (IBUFSZ - 1))) > eibuf) 1217 return(1); 1218 return(0); 1219 } 1220 1221 1222 flushi() 1223 { 1224 if (nflush) 1225 return; 1226 ch = 0; 1227 copyf++; 1228 while (!nlflg) { 1229 if (donef && (frame == stk)) 1230 break; 1231 getch(); 1232 } 1233 copyf--; 1234 } 1235 1236 1237 getach() 1238 { 1239 register tchar i; 1240 register j; 1241 1242 lgf++; 1243 j = cbits(i = getch()); 1244 #ifndef EUC 1245 if (ismot(i) || j == ' ' || j == '\n' || j & 0200) { 1246 #else 1247 #ifndef NROFF 1248 if (ismot(i) || j == ' ' || j == '\n' || j & 0200) { 1249 #else 1250 if (ismot(i) || j == ' ' || j == '\n' || j > 0200) { 1251 #endif /* NROFF */ 1252 #endif /* EUC */ 1253 1254 ch = i; 1255 j = 0; 1256 } 1257 lgf--; 1258 return(j & 0177); 1259 } 1260 1261 1262 casenx() 1263 { 1264 lgf++; 1265 skip(); 1266 getname(); 1267 nx++; 1268 if (nmfi > 0) 1269 nmfi--; 1270 strcpy(mfiles[nmfi], nextf); 1271 nextfile(); 1272 nlflg++; 1273 ip = 0; 1274 pendt = 0; 1275 frame = stk; 1276 nxf = frame + 1; 1277 } 1278 1279 1280 getname() 1281 { 1282 register int j, k; 1283 tchar i; 1284 1285 lgf++; 1286 for (k = 0; k < (NS - 1); k++) { 1287 #ifndef EUC 1288 if (((j = cbits(i = getch())) <= ' ') || (j > 0176)) 1289 #else 1290 #ifndef NROFF 1291 if (((j = cbits(i = getch())) <= ' ') || (j > 0176)) 1292 #else 1293 if (((j = cbits(i = getch())) <= ' ') || (j == 0177)) 1294 #endif /* NROFF */ 1295 #endif /* EUC */ 1296 break; 1297 nextf[k] = j & BYTEMASK; 1298 } 1299 nextf[k] = 0; 1300 ch = i; 1301 lgf--; 1302 return(nextf[0]); 1303 } 1304 1305 1306 caseso() 1307 { 1308 register i; 1309 register char *p, *q; 1310 1311 lgf++; 1312 nextf[0] = 0; 1313 if (skip() || !getname() || ((i = open(nextf, 0)) < 0) || (ifi >= NSO)) { 1314 errprint(gettext("can't open file %s"), nextf); 1315 done(02); 1316 } 1317 strcpy(cfname[ifi+1], nextf); 1318 cfline[ifi] = numtab[CD].val; /*hold line counter*/ 1319 numtab[CD].val = 0; 1320 flushi(); 1321 ifl[ifi] = ifile; 1322 ifile = i; 1323 offl[ifi] = ioff; 1324 ioff = 0; 1325 ipl[ifi] = ip; 1326 ip = 0; 1327 nx++; 1328 nflush++; 1329 if (!ifl[ifi++]) { 1330 p = ibuf; 1331 q = xbuf; 1332 xbufp = ibufp; 1333 xeibuf = eibuf; 1334 while (p < eibuf) 1335 *q++ = *p++; 1336 } 1337 } 1338 1339 caself() /* set line number and file */ 1340 { 1341 int n; 1342 1343 if (skip()) 1344 return; 1345 n = atoi(); 1346 cfline[ifi] = numtab[CD].val = n - 2; 1347 if (skip()) 1348 return; 1349 if (getname()) 1350 strcpy(cfname[ifi], nextf); 1351 } 1352 1353 1354 casecf() 1355 { /* copy file without change */ 1356 #ifndef NROFF 1357 int fd, n; 1358 char buf[512]; 1359 extern int hpos, esc, po; 1360 nextf[0] = 0; 1361 if (skip() || !getname() || (fd = open(nextf, 0)) < 0) { 1362 errprint(gettext("can't open file %s"), nextf); 1363 done(02); 1364 } 1365 tbreak(); 1366 /* make it into a clean state, be sure that everything is out */ 1367 hpos = po; 1368 esc = un; 1369 ptesc(); 1370 ptlead(); 1371 ptps(); 1372 ptfont(); 1373 flusho(); 1374 while ((n = read(fd, buf, sizeof buf)) > 0) 1375 write(ptid, buf, n); 1376 close(fd); 1377 #endif 1378 } 1379 1380 1381 casesy() /* call system */ 1382 { 1383 char sybuf[NTM]; 1384 int i; 1385 1386 lgf++; 1387 copyf++; 1388 skip(); 1389 for (i = 0; i < NTM - 2; i++) 1390 if ((sybuf[i] = getch()) == '\n') 1391 break; 1392 sybuf[i] = 0; 1393 system(sybuf); 1394 copyf--; 1395 lgf--; 1396 } 1397 1398 1399 getpn(a) 1400 register char *a; 1401 { 1402 register int n, neg; 1403 1404 if (*a == 0) 1405 return; 1406 neg = 0; 1407 for ( ; *a; a++) 1408 switch (*a) { 1409 case '+': 1410 case ',': 1411 continue; 1412 case '-': 1413 neg = 1; 1414 continue; 1415 default: 1416 n = 0; 1417 if (isdigit((unsigned char)*a)) { 1418 do 1419 n = 10 * n + *a++ - '0'; 1420 while (isdigit((unsigned char)*a)); 1421 a--; 1422 } else 1423 n = 9999; 1424 *pnp++ = neg ? -n : n; 1425 neg = 0; 1426 if (pnp >= &pnlist[NPN-2]) { 1427 errprint(gettext("too many page numbers")); 1428 done3(-3); 1429 } 1430 } 1431 if (neg) 1432 *pnp++ = -9999; 1433 *pnp = -32767; 1434 print = 0; 1435 pnp = pnlist; 1436 if (*pnp != -32767) 1437 chkpn(); 1438 } 1439 1440 1441 setrpt() 1442 { 1443 tchar i, j; 1444 1445 copyf++; 1446 raw++; 1447 i = getch0(); 1448 copyf--; 1449 raw--; 1450 if (i < 0 || cbits(j = getch0()) == RPT) 1451 return; 1452 i &= BYTEMASK; 1453 while (i>0 && pbp < &pbbuf[NC-3]) { 1454 i--; 1455 *pbp++ = j; 1456 } 1457 } 1458 1459 1460 casedb() 1461 { 1462 #ifdef DEBUG 1463 debug = 0; 1464 if (skip()) 1465 return; 1466 noscale++; 1467 debug = max(atoi(), 0); 1468 noscale = 0; 1469 #endif DEBUG 1470 } 1471