1: #ifndef lint 2: static char sccsid[] = "@(#)n3.c 4.4 6/25/87"; 3: #endif lint 4: 5: #include "tdef.h" 6: extern 7: #include "d.h" 8: extern 9: #include "v.h" 10: #ifdef NROFF 11: extern 12: #include "tw.h" 13: #endif 14: #include "sdef.h" 15: 16: /* 17: troff3.c 18: 19: macro and string routines, storage allocation 20: */ 21: 22: unsigned blist[NBLIST]; 23: extern struct s *frame, *stk, *nxf; 24: extern filep ip; 25: extern filep offset; 26: extern filep nextb; 27: extern char *enda; 28: 29: extern int ch; 30: extern int ibf; 31: extern int lgf; 32: extern int copyf; 33: extern int ch0; 34: extern int app; 35: extern int ds; 36: extern int nlflg; 37: extern int *argtop; 38: extern int *ap; 39: extern int nchar; 40: extern int pendt; 41: extern int rchar; 42: extern int dilev; 43: extern int nonumb; 44: extern int lt; 45: extern int nrbits; 46: extern int nform; 47: extern int fmt[]; 48: extern int oldmn; 49: extern int newmn; 50: extern int macerr; 51: extern filep apptr; 52: extern int diflg; 53: extern filep woff; 54: extern filep roff; 55: extern int wbfi; 56: extern int po; 57: extern int *cp; 58: extern int xxx; 59: int pagech = '%'; 60: int strflg; 61: extern struct contab { 62: int rq; 63: union { 64: int (*f)(); 65: unsigned mx; 66: }x; 67: }contab[NM]; 68: #ifndef VMUNIX 69: int wbuf[BLK]; 70: int rbuf[BLK]; 71: #else 72: int *wbuf; 73: int *rbuf; 74: int Buf[NBLIST*BLK + NEV*EVS]; 75: #endif 76: 77: caseig(){ 78: register i; 79: 80: offset = 0; 81: if((i = copyb()) != '.')control(i,1); 82: } 83: casern(){ 84: register i,j; 85: 86: lgf++; 87: skip(); 88: if(((i=getrq())==0) || ((oldmn=findmn(i)) < 0))return; 89: skip(); 90: clrmn(findmn(j=getrq())); 91: if(j)contab[oldmn].rq = (contab[oldmn].rq & MMASK) | j; 92: } 93: caserm(){ 94: lgf++; 95: while(!skip()){ 96: clrmn(findmn(getrq())); 97: } 98: } 99: caseas(){ 100: app++; 101: caseds(); 102: } 103: caseds(){ 104: ds++; 105: casede(); 106: } 107: caseam(){ 108: app++; 109: casede(); 110: } 111: casede(){ 112: register i, req; 113: register filep savoff; 114: extern filep finds(); 115: 116: if(dip != d)wbfl(); 117: req = '.'; 118: lgf++; 119: skip(); 120: if((i=getrq())==0)goto de1; 121: if((offset=finds(i)) == 0)goto de1; 122: if(ds)copys(); 123: else req = copyb(); 124: wbfl(); 125: clrmn(oldmn); 126: if(newmn)contab[newmn].rq = i | MMASK; 127: if(apptr){ 128: savoff = offset; 129: offset = apptr; 130: wbt(IMP); 131: offset = savoff; 132: } 133: offset = dip->op; 134: if(req != '.')control(req,1); 135: de1: 136: ds = app = 0; 137: return; 138: } 139: findmn(i) 140: int i; 141: { 142: register j; 143: 144: for(j=0;j<NM;j++){ 145: if(i == (contab[j].rq & ~MMASK))break; 146: } 147: if(j==NM)j = -1; 148: return(j); 149: } 150: clrmn(i) 151: int i; 152: { 153: extern filep boff(); 154: if(i >= 0){ 155: if(contab[i].rq & MMASK)ffree(((filep)contab[i].x.mx)<<BLKBITS); 156: contab[i].rq = 0; 157: contab[i].x.mx = 0; 158: } 159: } 160: filep finds(mn) 161: int mn; 162: { 163: register i; 164: extern filep boff(); 165: register filep savip; 166: extern filep alloc(); 167: extern filep incoff(); 168: 169: oldmn = findmn(mn); 170: newmn = 0; 171: apptr = (filep)0; 172: if(app && (oldmn >= 0) && (contab[oldmn].rq & MMASK)){ 173: savip = ip; 174: ip = (((filep)contab[oldmn].x.mx)<<BLKBITS); 175: oldmn = -1; 176: while((i=rbf()) != 0); 177: apptr = ip; 178: if(!diflg)ip = incoff(ip); 179: nextb = ip; 180: ip = savip; 181: }else{ 182: for(i=0;i<NM;i++){ 183: if(contab[i].rq == 0)break; 184: } 185: if((i==NM) || 186: (nextb = alloc()) == 0){ 187: app = 0; 188: if(macerr++ > 1)done2(02); 189: prstr("Too many string/macro names.\n"); 190: edone(04); 191: return(offset = 0); 192: } 193: contab[i].x.mx = (unsigned)(nextb>>BLKBITS); 194: if(!diflg){ 195: newmn = i; 196: if(oldmn == -1)contab[i].rq = -1; 197: }else{ 198: contab[i].rq = mn | MMASK; 199: } 200: } 201: 202: app = 0; 203: return(offset = nextb); 204: } 205: skip(){ 206: register i; 207: 208: while(((i=getch()) & CMASK) == ' '); 209: ch=i; 210: return(nlflg); 211: } 212: copyb() 213: { 214: register i, j, k; 215: int ii, req, state; 216: filep savoff; 217: 218: if(skip() || !(j=getrq()))j = '.'; 219: req = j; 220: k = j>>BYTE; 221: j &= BMASK; 222: copyf++; 223: flushi(); 224: nlflg = 0; 225: state = 1; 226: while(1){ 227: i = (ii = getch()) & CMASK; 228: if(state == 3){ 229: if(i == k)break; 230: if(!k){ 231: ch = ii; 232: i = getach(); 233: ch = ii; 234: if(!i)break; 235: } 236: state = 0; 237: goto c0; 238: } 239: if(i == '\n'){ 240: state = 1; 241: nlflg = 0; 242: goto c0; 243: } 244: if((state == 1) && (i == '.')){ 245: state++; 246: savoff = offset; 247: goto c0; 248: } 249: if((state == 2) && (i == j)){ 250: state++; 251: goto c0; 252: } 253: state = 0; 254: c0: 255: if(offset)wbf(ii); 256: } 257: if(offset){ 258: wbfl(); 259: offset = savoff; 260: wbt(0); 261: } 262: copyf--; 263: return(req); 264: } 265: copys() 266: { 267: register i; 268: 269: copyf++; 270: if(skip())goto c0; 271: if(((i=getch()) & CMASK) != '"')wbf(i); 272: while(((i=getch()) & CMASK) != '\n')wbf(i); 273: c0: 274: wbt(0); 275: copyf--; 276: } 277: filep alloc() 278: { 279: register i; 280: extern filep boff(); 281: filep j; 282: 283: for(i=0;i<NBLIST;i++){ 284: if(blist[i] == 0)break; 285: } 286: if(i==NBLIST){ 287: j = 0; 288: }else{ 289: blist[i] = -1; 290: if((j = boff(i)) < NEV*EVS)j = 0; 291: } 292: return(nextb = j); 293: } 294: ffree(i) 295: filep i; 296: { 297: register j; 298: 299: while((blist[j = blisti(i)]) != -1){ 300: i = ((filep)blist[j])<<BLKBITS; 301: blist[j] = 0; 302: } 303: blist[j] = 0; 304: } 305: filep boff(i) 306: int i; 307: { 308: return(((filep)i)*BLK + NEV*EVS); 309: } 310: wbt(i) 311: int i; 312: { 313: wbf(i); 314: wbfl(); 315: } 316: wbf(i) 317: int i; 318: { 319: register j; 320: 321: if(!offset)return; 322: if(!woff){ 323: woff = offset; 324: #ifdef VMUNIX 325: wbuf = &Buf[woff]; 326: #endif 327: wbfi = 0; 328: } 329: wbuf[wbfi++] = i; 330: if(!((++offset) & (BLK-1))){ 331: wbfl(); 332: if(blist[j = blisti(--offset)] == -1){ 333: if(alloc() == 0){ 334: prstr("Out of temp file space.\n"); 335: done2(01); 336: } 337: blist[j] = (unsigned)(nextb>>BLKBITS); 338: } 339: offset = ((filep)blist[j])<<BLKBITS; 340: } 341: if(wbfi >= BLK)wbfl(); 342: } 343: wbfl(){ 344: if(woff == 0)return; 345: #ifndef VMUNIX 346: lseek(ibf, ((long)woff) * sizeof(int), 0); 347: write(ibf, (char *)wbuf, wbfi * sizeof(int)); 348: #endif 349: if((woff & (~(BLK-1))) == (roff & (~(BLK-1))))roff = -1; 350: woff = 0; 351: } 352: blisti(i) 353: filep i; 354: { 355: return((i-NEV*EVS)/(BLK)); 356: } 357: rbf(){ 358: register i; 359: extern filep incoff(); 360: 361: if((i=rbf0(ip)) == 0){ 362: if(!app)i = popi(); 363: }else{ 364: ip = incoff(ip); 365: } 366: return(i); 367: } 368: rbf0(p) 369: filep p; 370: { 371: register filep i; 372: 373: if((i = (p & (~(BLK-1)))) != roff){ 374: roff = i; 375: #ifndef VMUNIX 376: lseek(ibf, ((long)roff) * sizeof(int), 0); 377: if(read(ibf, (char *)rbuf, BLK * sizeof(int)) == 0)return(0); 378: #else 379: rbuf = &Buf[roff]; 380: #endif 381: } 382: return(rbuf[p & (BLK-1)]); 383: } 384: filep incoff(p) 385: filep p; 386: { 387: register i; 388: register filep j; 389: if(!((j = (++p)) & (BLK-1))){ 390: if((i = blist[blisti(--p)]) == -1){ 391: prstr("Bad storage allocation.\n"); 392: done2(-5); 393: } 394: j = ((filep)i)<<BLKBITS; 395: } 396: return(j); 397: } 398: popi(){ 399: register struct s *p; 400: 401: if(frame == stk)return(0); 402: if(strflg)strflg--; 403: p = nxf = frame; 404: p->nargs = 0; 405: frame = p->pframe; 406: ip = p->pip; 407: nchar = p->pnchar; 408: rchar = p->prchar; 409: pendt = p->ppendt; 410: ap = p->pap; 411: cp = p->pcp; 412: ch0 = p->pch0; 413: return(p->pch); 414: } 415: 416: /* 417: * test that the end of the allocation is above a certain location 418: * in memory 419: */ 420: #define SPACETEST(base, size) while ((enda - (size)) <= (char *)(base)){setbrk(DELTA);} 421: 422: pushi(newip) 423: filep newip; 424: { 425: register struct s *p; 426: extern char *setbrk(); 427: 428: SPACETEST(nxf, sizeof(struct s)); 429: p = nxf; 430: p->pframe = frame; 431: p->pip = ip; 432: p->pnchar = nchar; 433: p->prchar = rchar; 434: p->ppendt = pendt; 435: p->pap = ap; 436: p->pcp = cp; 437: p->pch0 = ch0; 438: p->pch = ch; 439: cp = ap = 0; 440: nchar = rchar = pendt = ch0 = ch = 0; 441: frame = nxf; 442: if (nxf->nargs == 0) 443: nxf += 1; 444: else 445: nxf = (struct s *)argtop; 446: return(ip = newip); 447: } 448: 449: 450: char *setbrk(x) 451: int x; 452: { 453: register char *i; 454: char *sbrk(); 455: 456: x += sizeof(int) - 1; 457: x &= ~(sizeof(int) - 1); 458: if ((u_int)(i = sbrk(x)) == -1) { 459: prstrfl("Core limit reached.\n"); 460: edone(0100); 461: } else { 462: enda = i + x; 463: } 464: return(i); 465: } 466: 467: 468: getsn() 469: { 470: register i; 471: 472: if ((i = getach()) == 0) 473: return(0); 474: if (i == '(') 475: return(getrq()); 476: else 477: return(i); 478: } 479: 480: 481: setstr() 482: { 483: register i; 484: 485: lgf++; 486: if ( ((i = getsn()) == 0) 487: || ((i = findmn(i)) == -1) 488: || !(contab[i].rq & MMASK)) { 489: lgf--; 490: return(0); 491: } else { 492: SPACETEST(nxf, sizeof(struct s)); 493: nxf->nargs = 0; 494: strflg++; 495: lgf--; 496: return(pushi(((filep)contab[i].x.mx)<<BLKBITS)); 497: } 498: } 499: 500: typedef int tchar; 501: #define cbits(x) ((x) & CMASK) 502: 503: collect() 504: { 505: register j; 506: tchar i; 507: register tchar *strp; 508: tchar * lim; 509: tchar * *argpp, **argppend; 510: int quote; 511: struct s *savnxf; 512: 513: copyf++; 514: nxf->nargs = 0; 515: savnxf = nxf; 516: if (skip()) 517: goto rtn; 518: 519: { 520: char *memp; 521: memp = (char *)savnxf; 522: /* 523: * 1 s structure for the macro descriptor 524: * APERMAC tchar *'s for pointers into the strings 525: * space for the tchar's themselves 526: */ 527: memp += sizeof(struct s); 528: /* 529: * CPERMAC (the total # of characters for ALL arguments) 530: * to a macros, has been carefully chosen 531: * so that the distance between stack frames is < DELTA 532: */ 533: #define CPERMAC 200 534: #define APERMAC 9 535: memp += APERMAC * sizeof(tchar *); 536: memp += CPERMAC * sizeof(tchar); 537: nxf = (struct s*)memp; 538: } 539: lim = (tchar *)nxf; 540: argpp = (tchar **)(savnxf + 1); 541: argppend = &argpp[APERMAC]; 542: SPACETEST(argppend, sizeof(tchar *)); 543: strp = (tchar *)argppend; 544: /* 545: * Zero out all the string pointers before filling them in. 546: */ 547: for (j = 0; j < APERMAC; j++){ 548: argpp[j] = (tchar *)0; 549: } 550: #if 0 551: fprintf(stderr, "savnxf=0x%x,nxf=0x%x,argpp=0x%x,strp=argppend=0x%x,lim=0x%x,enda=0x%x\n", 552: savnxf, nxf, argpp, strp, lim, enda); 553: #endif 0 554: strflg = 0; 555: while ((argpp != argppend) && (!skip())) { 556: *argpp++ = strp; 557: quote = 0; 558: if (cbits(i = getch()) == '"') 559: quote++; 560: else 561: ch = i; 562: while (1) { 563: i = getch(); 564: if ( nlflg || (!quote && cbits(i) == ' ')) 565: break; 566: if ( quote 567: && (cbits(i) == '"') 568: && (cbits(i = getch()) != '"')) { 569: ch = i; 570: break; 571: } 572: *strp++ = i; 573: if (strflg && (strp >= lim)) { 574: #if 0 575: fprintf(stderr, "strp=0x%x, lim = 0x%x\n", 576: strp, lim); 577: #endif 0 578: prstrfl("Macro argument too long.\n"); 579: copyf--; 580: edone(004); 581: } 582: SPACETEST(strp, 3 * sizeof(tchar)); 583: } 584: *strp++ = 0; 585: } 586: nxf = savnxf; 587: nxf->nargs = argpp - (tchar **)(savnxf + 1); 588: argtop = strp; 589: rtn: 590: copyf--; 591: } 592: 593: 594: seta() 595: { 596: register i; 597: 598: if(((i = (getch() & CMASK) - '0') > 0) && 599: (i <= APERMAC) && (i <= frame->nargs))ap = *((int **)frame + i-1 + (sizeof(struct s)/sizeof(int **))); 600: } 601: caseda(){ 602: app++; 603: casedi(); 604: } 605: casedi(){ 606: register i, j; 607: register *k; 608: 609: lgf++; 610: if(skip() || ((i=getrq()) == 0)){ 611: if(dip != d)wbt(0); 612: if(dilev > 0){ 613: v.dn = dip->dnl; 614: v.dl = dip->maxl; 615: dip = &d[--dilev]; 616: offset = dip->op; 617: } 618: goto rtn; 619: } 620: if(++dilev == NDI){ 621: --dilev; 622: prstr("Cannot divert.\n"); 623: edone(02); 624: } 625: if(dip != d)wbt(0); 626: diflg++; 627: dip = &d[dilev]; 628: dip->op = finds(i); 629: dip->curd = i; 630: clrmn(oldmn); 631: k = (int *)&dip->dnl; 632: for(j=0; j<10; j++)k[j] = 0; /*not op and curd*/ 633: rtn: 634: app = 0; 635: diflg = 0; 636: } 637: casedt(){ 638: lgf++; 639: dip->dimac = dip->ditrap = dip->ditf = 0; 640: skip(); 641: dip->ditrap = vnumb((int *)0); 642: if(nonumb)return; 643: skip(); 644: dip->dimac = getrq(); 645: } 646: casetl(){ 647: register i, j; 648: int w1, w2, w3, delim; 649: filep begin; 650: extern width(), pchar(); 651: 652: dip->nls = 0; 653: skip(); 654: if(dip != d)wbfl(); 655: if((offset = begin = alloc()) == 0)return; 656: if((delim = getch()) & MOT){ 657: ch = delim; 658: delim = '\''; 659: }else delim &= CMASK; 660: if(!nlflg) 661: while(((i = getch()) & CMASK) != '\n'){ 662: if((i & CMASK) == delim)i = IMP; 663: wbf(i); 664: } 665: wbf(IMP);wbf(IMP);wbt(0); 666: 667: w1 = hseg(width,begin); 668: w2 = hseg(width,(filep)0); 669: w3 = hseg(width,(filep)0); 670: offset = dip->op; 671: #ifdef NROFF 672: if(!offset)horiz(po); 673: #endif 674: hseg(pchar,begin); 675: if(w2 || w3)horiz(j=quant((lt - w2)/2-w1,HOR)); 676: hseg(pchar,(filep)0); 677: if(w3){ 678: horiz(lt-w1-w2-w3-j); 679: hseg(pchar,(filep)0); 680: } 681: newline(0); 682: if(dip != d){if(dip->dnl > dip->hnl)dip->hnl = dip->dnl;} 683: else{if(v.nl > dip->hnl)dip->hnl = v.nl;} 684: ffree(begin); 685: } 686: casepc(){ 687: pagech = chget(IMP); 688: } 689: hseg(f,p) 690: int (*f)(); 691: filep p; 692: { 693: register acc, i; 694: static filep q; 695: 696: acc = 0; 697: if(p)q = p; 698: while(1){ 699: i = rbf0(q); 700: q = incoff(q); 701: if(!i || (i == IMP))return(acc); 702: if((i & CMASK) == pagech){ 703: nrbits = i & ~CMASK; 704: nform = fmt[findr('%')]; 705: acc += fnumb(v.pn,f); 706: }else acc += (*f)(i); 707: } 708: } 709: casepm(){ 710: register i, k; 711: register char *p; 712: int xx, cnt, kk, tot; 713: filep j; 714: char *kvt(); 715: char pmline[10]; 716: 717: kk = cnt = 0; 718: tot = !skip(); 719: for(i = 0; i<NM; i++){ 720: if(!((xx = contab[i].rq) & MMASK))continue; 721: p = pmline; 722: j = (((filep)contab[i].x.mx)<<BLKBITS); 723: k = 1; 724: while((j = blist[blisti(j)]) != -1){k++; j <<= BLKBITS;} 725: cnt++; 726: kk += k; 727: if(!tot){ 728: *p++ = xx & 0177; 729: if(!(*p++ = (xx >> BYTE) & 0177))*(p-1) = ' '; 730: *p++ = ' '; 731: kvt(k,p); 732: prstr(pmline); 733: } 734: } 735: if(tot || (cnt > 1)){ 736: kvt(kk,pmline); 737: prstr(pmline); 738: } 739: } 740: char *kvt(k,p) 741: int k; 742: char *p; 743: { 744: if(k>=100)*p++ = k/100 + '0'; 745: if(k>=10)*p++ = (k%100)/10 + '0'; 746: *p++ = k%10 + '0'; 747: *p++ = '\n'; 748: *p = 0; 749: return(p); 750: } 751: dummy(){}