1: #include "sdef.h" 2: #include <sys/types.h> 3: #include <sys/stat.h> 4: #include "d.h" 5: #include "v.h" 6: #include "tw.h" 7: #include "s.h" 8: #include <setjmp.h> 9: jmp_buf sjbuf; 10: /* 11: sroff1.c 12: 13: consume options, initialization, main loop, 14: input routines, escape function calling 15: */ 16: 17: /* 18: * modified by Patrick Orr at NMT to allow printable zero-width strings 19: * that can be used to give escape sequences to the Sanders Media 12/7 20: * printer. patch installed in version 7 by Jeremy Epstein, UNM. 21: * 22: * much modified by Mike Karels, Dept. of Molecular Biology, 23: * University of California, Berkeley 24: */ 25: extern struct s *frame, *stk, *nxf; 26: extern struct s *ejl, *litlev; 27: extern filep ip; 28: extern filep offset; 29: extern filep nextb; 30: 31: 32: extern int stdi; 33: extern int waitf; 34: extern int rollpaper; 35: extern int nroff; 36: extern int draft; 37: extern int quiet; 38: extern int ptid; 39: extern int toolate; 40: extern int npn; 41: extern int xflg; 42: extern char ibuf[IBUFSZ]; 43: extern char xbuf[IBUFSZ]; 44: extern char *ibufp; 45: extern char *xbufp; 46: extern char *eibuf; 47: extern char *xeibuf; 48: extern int cbuf[NC]; 49: extern int *cp; 50: extern int *vlist; 51: extern int nx; 52: extern int mflg; 53: extern int ch; 54: extern int pto; 55: extern int pfrom; 56: extern int cps; 57: extern int chbits; 58: extern int ibf; 59: extern int ttyod; 60: extern struct sgttyb ttys; 61: extern int iflg; 62: extern int init; 63: extern int rargc; 64: extern char **argp; 65: extern char trtab[256]; 66: extern int lgf; 67: extern int copyf; 68: extern int eschar; 69: extern int ch0; 70: extern int cwidth; 71: extern int nlflg; 72: extern int *ap; 73: extern int donef; 74: extern int nflush; 75: extern int nchar; 76: extern int rchar; 77: extern int nfo; 78: extern int ifile; 79: extern int fc; 80: extern int padc; 81: extern int tabc; 82: extern int dotc; 83: extern int raw; 84: extern int tabtab[NTAB]; 85: extern char nextf[]; 86: extern int nfi; 87: extern char fontlib[]; 88: extern int tti; 89: extern int ifl[NSO]; 90: extern int ifi; 91: extern int pendt; 92: extern int flss; 93: extern int fi; 94: extern int lg; 95: extern char ptname[]; 96: extern int print; 97: extern int nonumb; 98: extern int pnlist[]; 99: extern int *pnp; 100: extern int nb; 101: extern int trap; 102: extern int tflg; 103: extern int ejf; 104: extern int lit; 105: extern int cc; 106: extern int c2; 107: extern int spread; 108: extern int oline[]; 109: extern int *olinep; 110: extern int dpn; 111: extern int noscale; 112: extern char *unlkp; 113: extern int level; 114: extern int ttysave; 115: extern int tdelim; 116: extern int dotF; 117: extern int tabch, ldrch; 118: extern no_out; 119: extern int Em; 120: extern char codetab[]; 121: extern int xxx; 122: int stopmesg; 123: filep ipl[NSO]; 124: long offl[NSO]; 125: long ioff; 126: char *ttyp; 127: extern struct contab { 128: int rq; 129: union { 130: int (*f)(); 131: unsigned mx; 132: }x; 133: }contab[NM]; 134: int ms[] = {31,28,31,30,31,30,31,31,30,31,30,31}; 135: 136: main(argc,argv) 137: int argc; 138: char **argv; 139: { 140: char *p, *q; 141: register i, j; 142: extern catch(), fpecatch(), kcatch(); 143: 144: signal(SIGHUP,catch); 145: if(signal(SIGINT,catch) == SIG_IGN){ 146: signal(SIGHUP,SIG_IGN); 147: signal(SIGINT,SIG_IGN); 148: signal(SIGQUIT,SIG_IGN); 149: } 150: signal(SIGFPE,fpecatch); 151: signal(SIGPIPE,catch); 152: signal(SIGTERM,catch); 153: init1(argv[0][0]); 154: options: 155: while(--argc > 0 && (++argv)[0][0]=='-') 156: switch(argv[0][1]){ 157: 158: case 0: 159: goto start; 160: case 'i': 161: stdi++; 162: continue; 163: case 'q': 164: quiet++; 165: if(gtty(0, &ttys) >= 0) 166: ttysave = ttys.sg_flags; 167: continue; 168: case 'n': 169: if (!strcmp(argv[0]+1,"nroff")) 170: nroff++; 171: else 172: npn = cnum(&argv[0][2]); 173: continue; 174: case 'p': 175: xflg = 0; 176: cps = cnum(&argv[0][2]); 177: continue; 178: case 'S': 179: stopmesg++; 180: continue; 181: case 'r': 182: vlist[findr(argv[0][2])] = cnum(&argv[0][3]); 183: continue; 184: case 'm': 185: p = &nextf[nfi]; 186: q = &argv[0][2]; 187: while((*p++ = *q++) != 0); 188: mflg++; 189: continue; 190: case 'o': 191: getpn(&argv[0][2]); 192: continue; 193: case 'z': 194: no_out++; 195: continue; 196: case 'F': 197: p = &fontlib[tti]; 198: q = &argv[0][2]; 199: if(!((*q) & 0177))continue; 200: while((*p++ = *q++) != 0); 201: dotF++; 202: continue; 203: case 't': 204: ptid = 1; 205: continue; 206: case 'w': 207: waitf = 1; 208: continue; 209: case 'b': 210: if(open(ptname,1) < 0)prstr("Busy.\n"); 211: else prstr("Available.\n"); 212: done3(0); 213: case 'c': /* continuous paper */ 214: rollpaper++; 215: continue; 216: case 'd': /* draft mode */ 217: draft++; 218: continue; 219: default: 220: pto = cnum(&argv[0][1]); 221: continue; 222: } 223: 224: if(argv[0][0] == '+'){ 225: pfrom = cnum(&argv[0][1]); 226: print = 0; 227: if(argc > 0)goto options; 228: } 229: 230: start: 231: argp = argv; 232: rargc = argc; 233: init2(); 234: setjmp(sjbuf); 235: loop: 236: copyf = lgf = nb = nflush = nlflg = 0; 237: if(ip && (rbf0(ip)==0) && ejf && (frame->pframe <= ejl)){ 238: nflush++; 239: trap = 0; 240: eject((struct s *)0); 241: goto loop; 242: } 243: i = getch(); 244: if(pendt)goto lt; 245: if(lit && (frame <= litlev)){ 246: lit--; 247: goto lt; 248: } 249: if((j = (i & CMASK)) == XPAR){ 250: copyf++; 251: tflg++; 252: for(;(i & CMASK) != '\n';)pchar(i = getch()); 253: tflg = 0; 254: copyf--; 255: goto loop; 256: } 257: if((j == cc) || (j == c2)){ 258: if(j == c2)nb++; 259: copyf++; 260: while(((j=((i=getch()) & CMASK)) == ' ') || 261: (j == '\t')); 262: ch = i; 263: copyf--; 264: control(getrq(),1); 265: flushi(); 266: goto loop; 267: } 268: lt: 269: ch = i; 270: text(); 271: goto loop; 272: } 273: catch(){ 274: signal(SIGTERM,SIG_IGN); 275: signal(SIGINT,SIG_IGN); 276: #ifndef TTY 277: if (toolate) 278: write(ptid,"\f",1); 279: #endif 280: done3(01); 281: } 282: fpecatch(){ 283: prstrfl("Floating Exception.\n"); 284: signal(SIGFPE,fpecatch); 285: } 286: init1(a) 287: char a; 288: { 289: register char *p; 290: char *mktemp(); 291: register i; 292: 293: p = mktemp("/tmp/taXXXXX"); 294: if(a == 'a')p = &p[5]; 295: if((close(creat(p, 0600))) < 0){ 296: prstr("Cannot create temp file.\n"); 297: exit(-1); 298: } 299: ibf = open(p, 2); 300: for(i=256; --i;)trtab[i]=i; 301: trtab[UNPAD] = ' '; 302: if(a != 'a')unlkp = p; 303: } 304: init2() 305: { 306: register i,j; 307: extern int block; 308: extern char *setbrk(); 309: extern char *ttyname(); 310: 311: ttyod = 2; 312: if(((ttyp=ttyname(j=0)) != (char *)0) || 313: ((ttyp=ttyname(j=1)) != (char *)0) || 314: ((ttyp=ttyname(j=2)) != (char *)0) 315: );else ttyp = "notty"; 316: iflg = j; 317: 318: if((!ptid) && (!waitf)){ 319: if((ptid = open(ptname,1)) < 0){ 320: prstr("Printer busy.\n"); 321: done3(-2); 322: } 323: } 324: olinep = oline; 325: for(i=NEV; i--;)write(ibf, (char *)&block, EVS*sizeof(int)); 326: ibufp = eibuf = ibuf; 327: v.hp = init = 0; 328: ioff = 0; 329: v.nl = -1; 330: cvtime(); 331: frame = stk = (struct s *)setbrk(DELTA); 332: dip = &d[0]; 333: nxf = frame + 1; 334: nx = mflg; 335: /* 336: * do this last as it will start doing output 337: */ 338: ptinit(); 339: } 340: cvtime(){ 341: 342: long tt; 343: register i; 344: 345: time(&tt); 346: tt -= 3600*ZONE; /*5hrs for EST*/ 347: v.dy = (tt/86400L) + 1; 348: v.dw = (v.dy + 3)%7 + 1; 349: for(v.yr=70;; v.yr++){ 350: if((v.yr)%4)ms[1]=28;else ms[1]=29; 351: for(i=0;i<12;){ 352: if(v.dy<=ms[i]){ 353: v.mo = i+1; 354: return; 355: } 356: v.dy -= ms[i++]; 357: } 358: } 359: } 360: cnum(a) 361: char *a; 362: { 363: register i; 364: 365: ibufp = a; 366: eibuf = MAXPTR; 367: i = atoi(); 368: ch = 0; 369: return(i); 370: } 371: prstrfl(s) 372: char *s; 373: { 374: flusho(); 375: prstr(s); 376: } 377: prstr(s) 378: char *s; 379: { 380: register i; 381: register char *j; 382: 383: j = s; 384: for(i=0;*s;i++)s++; 385: write(ttyod,j,i); 386: } 387: control(a,b) 388: int a,b; 389: { 390: register i,j; 391: extern filep boff(); 392: 393: i = a; 394: if((i == 0) || ((j = findmn(i)) == -1))return(0); 395: if(contab[j].rq & MMASK){ 396: nxf->nargs = 0; 397: if(b)collect(); 398: flushi(); 399: return(pushi(((filep)contab[j].x.mx)<<BLKBITS)); 400: }else{ 401: if(!b)return(0); 402: return((*contab[j].x.f)(0)); 403: } 404: } 405: 406: getrq(){ 407: register i,j; 408: 409: if(((i=getach()) == 0) || 410: ((j=getach()) == 0))goto rtn; 411: i = PAIR(i,j); 412: rtn: 413: return(i); 414: } 415: getch(){ 416: register int i, j, k; 417: 418: level++; 419: g0: 420: if(ch){ 421: if(((i = ch) & CMASK) == '\n')nlflg++; 422: ch = 0; 423: level--; 424: return(i); 425: } 426: 427: if(nlflg){ 428: level--; 429: return('\n'); 430: } 431: 432: if((k = (i = getch0()) & CMASK) != ESC){ 433: if(i & MOT)goto g2; 434: if(k == FLSS){ 435: copyf++; raw++; 436: i = getch0(); 437: if(!fi)flss = i; 438: copyf--; raw--; 439: goto g0; 440: } 441: if(k == RPT){ 442: setrpt(); 443: goto g0; 444: } 445: if(!copyf){ 446: if((k == 'f') && lg && !lgf){ 447: i = getlg(i); 448: goto g2; 449: } 450: if((k == fc) || (k == tabch) || (k == ldrch)){ 451: if((i=setfield(k)) == 0)goto g0; else goto g2; 452: } 453: if(k == 010){ 454: i = makem(-width(' ' | chbits)); 455: goto g2; 456: } 457: } 458: goto g2; 459: } 460: k = (j = getch0()) & CMASK; 461: if(j & MOT){ 462: i = j; 463: goto g2; 464: } 465: /* 466: if(k == tdelim){ 467: i = TDELIM; 468: tdelim = IMP; 469: goto g2; 470: } 471: */ 472: switch(k){ 473: 474: case '\n': /*concealed newline*/ 475: goto g0; 476: case 'n': /*number register*/ 477: setn(); 478: goto g0; 479: case '*': /*string indicator*/ 480: setstr(); 481: goto g0; 482: case '$': /*argument indicator*/ 483: seta(); 484: goto g0; 485: case '{': /*LEFT*/ 486: i = LEFT; 487: goto gx; 488: case '}': /*RIGHT*/ 489: i = RIGHT; 490: goto gx; 491: case '"': /*comment*/ 492: while(((i=getch0()) & CMASK ) != '\n'); 493: goto g2; 494: case ESC: /*double backslash*/ 495: i = eschar; 496: goto gx; 497: case 'e': /*printable version of current eschar*/ 498: i = PRESC; 499: goto gx; 500: case ' ': /*unpaddable space*/ 501: i = UNPAD; 502: goto gx; 503: case '|': /*narrow space*/ 504: i = makem(Em/6); 505: goto g2; 506: case '^': /*half of narrow space*/ 507: i = makem(Em/12); 508: goto g2; 509: case '\'': /*\(aa*/ 510: i = 0047; /* stan, 222 to 047 */ 511: goto gx; 512: case '`': /*\(ga*/ 513: i = 0140; /* stan, 223 to 140 */ 514: goto gx; 515: case '_': /*\(ul*/ 516: i = 0137; /* mjk, 0224 to 0137 */ 517: goto gx; 518: case '-': /*current font minus*/ 519: i = 0055; /* stan, 210 to 055 */ 520: goto gx; 521: case '&': /*filler*/ 522: i = FILLER; 523: goto gx; 524: case 'c': /*to be continued*/ 525: i = CONT; 526: goto gx; 527: case ':': /*lem's char*/ 528: i = COLON; 529: goto gx; 530: case '!': /*transparent indicator*/ 531: i = XPAR; 532: goto gx; 533: case 't': /*tab*/ 534: i = '\t'; 535: goto g2; 536: case 'a': /*leader (SOH)*/ 537: i = LEADER; 538: goto g2; 539: case '%': /*ohc*/ 540: i = OHC; 541: goto g2; 542: case '.': /*.*/ 543: i = '.'; 544: gx: 545: i = (j & ~CMASK) | i; 546: goto g2; 547: } 548: if(!copyf) 549: switch(k){ 550: 551: case 'p': /*spread*/ 552: spread++; 553: goto g0; 554: case '(': /*special char name*/ 555: if((i=setch()) == 0)goto g0; 556: break; 557: case 's': /*size indicator*/ 558: setps(); 559: goto g0; 560: case 'f': /*font indicator*/ 561: setfont(0); 562: goto g0; 563: case 'w': /*width function*/ 564: setwd(); 565: goto g0; 566: case 'v': /*vert mot*/ 567: if(i = vmot())break; 568: goto g0; 569: case 'h': /*horiz mot*/ 570: if(i = hmot())break; 571: goto g0; 572: case 'z': /*zero with char*/ 573: i = setz(); 574: break; 575: case 'l': /*hor line*/ 576: setline(); 577: goto g0; 578: case 'L': /*vert line*/ 579: setvline(); 580: goto g0; 581: case 'b': /*bracket*/ 582: setbra(); 583: goto g0; 584: case 'o': /*overstrike*/ 585: setov(); 586: goto g0; 587: case 'k': /*mark hor place*/ 588: if((i=findr(getsn())) == -1)goto g0; 589: vlist[i] = v.hp; 590: goto g0; 591: case 'j': /*mark output hor place*/ 592: if(!(i=getach()))goto g0; 593: i = (i<<BYTE) | JREG; 594: break; 595: case '0': /*number space*/ 596: i = makem(width('0' | chbits)); 597: break; 598: case 'x': /*extra line space*/ 599: if(i = xlss())break; 600: goto g0; 601: case 'u': /*half em up*/ 602: case 'r': /*full em up*/ 603: case 'd': /*half em down*/ 604: i = sethl(k); 605: break; 606: case 'E': /* zero-width string follows, jeremy */ 607: setesc(); 608: goto g0; 609: default: 610: i = j; 611: } 612: else{ 613: ch0 = j; 614: i = eschar; 615: } 616: g2: 617: if((i & CMASK) == '\n'){ 618: nlflg++; 619: v.hp = 0; 620: if(ip == 0)v.cd++; 621: } 622: if(!--level){ 623: j = width(i); 624: v.hp += j; 625: cwidth = j; 626: } 627: return(i); 628: } 629: char ifilt[32] = {0,001,002,003,0,005,006,007,010,011,012}; 630: getch0(){ 631: register int i, j; 632: 633: if(ch0){i=ch0; ch0=0; return(i);} 634: if(nchar){nchar--; return(rchar);} 635: 636: again: 637: if(cp){ 638: if((i = *cp++) == 0){ 639: cp = 0; 640: goto again; 641: } 642: }else if(ap){ 643: if((i = *ap++) == 0){ 644: ap = 0; 645: goto again; 646: } 647: }else if(ip){ 648: if(ip == -1)i = rdtty(); 649: else i = rbf(); 650: }else{ 651: if(donef)done(0); 652: if(nx || ((ibufp >= eibuf) && (ibufp != MAXPTR))){ 653: if(nfo)goto g1; 654: g0: 655: if(nextfile()){ 656: if(ip)goto again; 657: if(ibufp < eibuf)goto g2; 658: } 659: g1: 660: nx = 0; 661: if((j=read(ifile,ibuf,IBUFSZ)) <= 0)goto g0; 662: ibufp = ibuf; 663: eibuf = ibuf + j; 664: if(ip)goto again; 665: } 666: g2: 667: i = *ibufp++ & 0177; 668: ioff++; 669: if(i >= 040)goto g4; else i = ifilt[i]; 670: } 671: if(raw)return(i); 672: if((j = i & CMASK) == IMP)goto again; 673: if((i == 0) && !init)goto again; 674: g4: 675: if((copyf == 0) && ((i & ~BMASK) == 0) && ((i & CMASK) < MAXCHAR)) 676: i |= chbits; 677: if((i & CMASK) == eschar)i = (i & ~CMASK) | ESC; 678: return(i); 679: } 680: nextfile(){ 681: register char *p; 682: 683: n0: 684: if(ifile)close(ifile); 685: if(nx){ 686: p = nextf; 687: if(*p != 0)goto n1; 688: } 689: if(ifi > 0){ 690: if(popf())goto n0; /*popf error*/ 691: return(1); /*popf ok*/ 692: } 693: if(rargc-- <= 0)goto n2; 694: p = (argp++)[0]; 695: n1: 696: if((p[0] == '-') && (p[1] == 0)){ 697: ifile = 0; 698: }else if((ifile=open(p,0)) < 0){ 699: prstr("Cannot open "); 700: prstr(p); 701: prstr("\n"); 702: nfo -= mflg; 703: done(02); 704: } 705: nfo++; 706: v.cd = 0; 707: ioff = 0; 708: return(0); 709: n2: 710: if((nfo -= mflg) && !stdi)done(0); 711: nfo++; 712: v.cd = ifile = stdi = mflg = 0; 713: ioff = 0; 714: return(0); 715: } 716: popf(){ 717: register i; 718: register char *p, *q; 719: extern char *ttyname(); 720: 721: ioff = offl[--ifi]; 722: ip = ipl[ifi]; 723: if((ifile = ifl[ifi]) == 0){ 724: p = xbuf; 725: q = ibuf; 726: ibufp = xbufp; 727: eibuf = xeibuf; 728: while(q < eibuf)*q++ = *p++; 729: return(0); 730: } 731: if((lseek(ifile,(long)(ioff & ~(IBUFSZ-1)),0) < 0) || 732: ((i = read(ifile,ibuf,IBUFSZ)) < 0))return(1); 733: eibuf = ibuf + i; 734: ibufp = ibuf; 735: if(ttyname(ifile) == (char *)0) 736: if((ibufp = ibuf + (int)(ioff & (IBUFSZ-1))) >= eibuf)return(1); 737: return(0); 738: } 739: flushi(){ 740: if(nflush)return; 741: ch = 0; 742: if((ch0 & CMASK) == '\n')nlflg++; 743: ch0 = 0; 744: copyf++; 745: while(!nlflg){ 746: if(donef && (frame == stk))break; 747: getch(); 748: } 749: copyf--; 750: v.hp = 0; 751: } 752: getach(){ 753: register i; 754: 755: lgf++; 756: if(((i = getch()) & MOT) || 757: ((i&CMASK) == ' ') || 758: ((i&CMASK) == '\n')|| 759: (i & 0200)){ 760: ch = i; 761: i = 0; 762: } 763: lgf--; 764: return(i & 0177); 765: } 766: casenx(){ 767: lgf++; 768: skip(); 769: getname(); 770: nx++; 771: nextfile(); 772: nlflg++; 773: ip = 0; 774: ap = 0; 775: nchar = pendt = 0; 776: frame = stk; 777: nxf = frame + 1; 778: } 779: getname(){ 780: register int i, j, k; 781: 782: lgf++; 783: for(k=0; k < (NS-1); k++){ 784: if(((j=(i=getch()) & CMASK) <= ' ') || 785: (j > 0176))break; 786: nextf[k] = j; 787: } 788: nextf[k] = 0; 789: ch = i; 790: lgf--; 791: return(nextf[0]); 792: } 793: caseso(){ 794: register i; 795: register char *p, *q; 796: 797: lgf++; 798: nextf[0] = 0; 799: if(skip() || !getname() || ((i=open(nextf,0)) <0) || (ifi >= NSO)) { 800: prstr("can't open file "); 801: prstr(nextf); 802: prstr("\n"); 803: done(02); 804: } 805: flushi(); 806: ifl[ifi] = ifile; 807: ifile = i; 808: offl[ifi] = ioff; 809: ioff = 0; 810: ipl[ifi] = ip; 811: ip = 0; 812: nx++; 813: nflush++; 814: if(!ifl[ifi++]){ 815: p = ibuf; 816: q = xbuf; 817: xbufp = ibufp; 818: xeibuf = eibuf; 819: while(p < eibuf)*q++ = *p++; 820: } 821: } 822: 823: casecf(){ /* copy file without change */ 824: int fd, i, n; 825: char buf[512]; 826: 827: flusho(); 828: lgf++; 829: nextf[0] = 0; 830: if(skip() || !getname() || ((fd=open(nextf,0)) <0) || (ifi >= NSO)) { 831: prstr("can't open file "); 832: prstr(nextf); 833: prstr("\n"); 834: done(02); 835: } 836: while ((n = read(fd, buf, 512)) > 0) 837: for (i = 0; i < n; i++) 838: oput(buf[i]); 839: flusho(); 840: close(fd); 841: } 842: getpn(a) 843: char *a; 844: { 845: register i, neg; 846: long atoi1(); 847: 848: if((*a & 0177) == 0)return; 849: neg = 0; 850: ibufp = a; 851: eibuf = MAXPTR; 852: noscale++; 853: while((i = getch() & CMASK) != 0)switch(i){ 854: case '+': 855: case ',': 856: continue; 857: case '-': 858: neg = MOT; 859: goto d2; 860: default: 861: ch = i; 862: d2: 863: i = atoi1(); 864: if(nonumb)goto fini; 865: else{ 866: *pnp++ = i | neg; 867: neg = 0; 868: if(pnp >= &pnlist[NPN-2]){ 869: prstr("Too many page numbers\n"); 870: done3(-3); 871: } 872: } 873: } 874: fini: 875: if(neg)*pnp++ = -2; 876: *pnp = -1; 877: ch = noscale = print = 0; 878: pnp = pnlist; 879: if(*pnp != -1)chkpn(); 880: } 881: setrpt(){ 882: register i, j; 883: 884: copyf++;raw++; 885: i = getch0(); 886: copyf--;raw--; 887: if((i < 0) || 888: (((j = getch0()) & CMASK) == RPT))return; 889: rchar = j; 890: nchar = i & BMASK; 891: }