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