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