1: #ifndef lint 2: static char sccsid[] = "@(#)n3.c 4.2 10/28/82"; 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: /* ought to be rounded up by sizeof(int) */ 457: if (x % 2 == 1) 458: x++; 459: if ( (i = sbrk(x)) >= (char *)MAXPTR) { 460: prstrfl("Core limit reached.\n"); 461: edone(0100); 462: } else { 463: enda = i + x; 464: } 465: return(i); 466: } 467: 468: 469: getsn() 470: { 471: register i; 472: 473: if ((i = getach()) == 0) 474: return(0); 475: if (i == '(') 476: return(getrq()); 477: else 478: return(i); 479: } 480: 481: 482: setstr() 483: { 484: register i; 485: 486: lgf++; 487: if ( ((i = getsn()) == 0) 488: || ((i = findmn(i)) == -1) 489: || !(contab[i].rq & MMASK)) { 490: lgf--; 491: return(0); 492: } else { 493: SPACETEST(nxf, sizeof(struct s)); 494: nxf->nargs = 0; 495: strflg++; 496: lgf--; 497: return(pushi(((filep)contab[i].x.mx)<<BLKBITS)); 498: } 499: } 500: 501: typedef int tchar; 502: #define cbits(x) ((x) & CMASK) 503: 504: collect() 505: { 506: register j; 507: tchar i; 508: register tchar *strp; 509: tchar * lim; 510: tchar * *argpp, **argppend; 511: int quote; 512: struct s *savnxf; 513: 514: copyf++; 515: nxf->nargs = 0; 516: savnxf = nxf; 517: if (skip()) 518: goto rtn; 519: 520: { 521: char *memp; 522: memp = (char *)savnxf; 523: /* 524: * 1 s structure for the macro descriptor 525: * APERMAC tchar *'s for pointers into the strings 526: * space for the tchar's themselves 527: */ 528: memp += sizeof(struct s); 529: /* 530: * CPERMAC (the total # of characters for ALL arguments) 531: * to a macros, has been carefully chosen 532: * so that the distance between stack frames is < DELTA 533: */ 534: #define CPERMAC 200 535: #define APERMAC 9 536: memp += APERMAC * sizeof(tchar *); 537: memp += CPERMAC * sizeof(tchar); 538: nxf = (struct s*)memp; 539: } 540: lim = (tchar *)nxf; 541: argpp = (tchar **)(savnxf + 1); 542: argppend = &argpp[APERMAC]; 543: SPACETEST(argppend, sizeof(tchar *)); 544: strp = (tchar *)argppend; 545: /* 546: * Zero out all the string pointers before filling them in. 547: */ 548: for (j = 0; j < APERMAC; j++){ 549: argpp[j] = (tchar *)0; 550: } 551: #if 0 552: fprintf(stderr, "savnxf=0x%x,nxf=0x%x,argpp=0x%x,strp=argppend=0x%x,lim=0x%x,enda=0x%x\n", 553: savnxf, nxf, argpp, strp, lim, enda); 554: #endif 0 555: strflg = 0; 556: while ((argpp != argppend) && (!skip())) { 557: *argpp++ = strp; 558: quote = 0; 559: if (cbits(i = getch()) == '"') 560: quote++; 561: else 562: ch = i; 563: while (1) { 564: i = getch(); 565: if ( nlflg || (!quote && cbits(i) == ' ')) 566: break; 567: if ( quote 568: && (cbits(i) == '"') 569: && (cbits(i = getch()) != '"')) { 570: ch = i; 571: break; 572: } 573: *strp++ = i; 574: if (strflg && (strp >= lim)) { 575: #if 0 576: fprintf(stderr, "strp=0x%x, lim = 0x%x\n", 577: strp, lim); 578: #endif 0 579: prstrfl("Macro argument too long.\n"); 580: copyf--; 581: edone(004); 582: } 583: SPACETEST(strp, 3 * sizeof(tchar)); 584: } 585: *strp++ = 0; 586: } 587: nxf = savnxf; 588: nxf->nargs = argpp - (tchar **)(savnxf + 1); 589: argtop = strp; 590: rtn: 591: copyf--; 592: } 593: 594: 595: seta() 596: { 597: register i; 598: 599: if(((i = (getch() & CMASK) - '0') > 0) && 600: (i <= APERMAC) && (i <= frame->nargs))ap = *((int **)frame + i-1 + (sizeof(struct s)/sizeof(int **))); 601: } 602: caseda(){ 603: app++; 604: casedi(); 605: } 606: casedi(){ 607: register i, j; 608: register *k; 609: 610: lgf++; 611: if(skip() || ((i=getrq()) == 0)){ 612: if(dip != d)wbt(0); 613: if(dilev > 0){ 614: v.dn = dip->dnl; 615: v.dl = dip->maxl; 616: dip = &d[--dilev]; 617: offset = dip->op; 618: } 619: goto rtn; 620: } 621: if(++dilev == NDI){ 622: --dilev; 623: prstr("Cannot divert.\n"); 624: edone(02); 625: } 626: if(dip != d)wbt(0); 627: diflg++; 628: dip = &d[dilev]; 629: dip->op = finds(i); 630: dip->curd = i; 631: clrmn(oldmn); 632: k = (int *)&dip->dnl; 633: for(j=0; j<10; j++)k[j] = 0; /*not op and curd*/ 634: rtn: 635: app = 0; 636: diflg = 0; 637: } 638: casedt(){ 639: lgf++; 640: dip->dimac = dip->ditrap = dip->ditf = 0; 641: skip(); 642: dip->ditrap = vnumb((int *)0); 643: if(nonumb)return; 644: skip(); 645: dip->dimac = getrq(); 646: } 647: casetl(){ 648: register i, j; 649: int w1, w2, w3, delim; 650: filep begin; 651: extern width(), pchar(); 652: 653: dip->nls = 0; 654: skip(); 655: if(dip != d)wbfl(); 656: if((offset = begin = alloc()) == 0)return; 657: if((delim = getch()) & MOT){ 658: ch = delim; 659: delim = '\''; 660: }else delim &= CMASK; 661: if(!nlflg) 662: while(((i = getch()) & CMASK) != '\n'){ 663: if((i & CMASK) == delim)i = IMP; 664: wbf(i); 665: } 666: wbf(IMP);wbf(IMP);wbt(0); 667: 668: w1 = hseg(width,begin); 669: w2 = hseg(width,(filep)0); 670: w3 = hseg(width,(filep)0); 671: offset = dip->op; 672: #ifdef NROFF 673: if(!offset)horiz(po); 674: #endif 675: hseg(pchar,begin); 676: if(w2 || w3)horiz(j=quant((lt - w2)/2-w1,HOR)); 677: hseg(pchar,(filep)0); 678: if(w3){ 679: horiz(lt-w1-w2-w3-j); 680: hseg(pchar,(filep)0); 681: } 682: newline(0); 683: if(dip != d){if(dip->dnl > dip->hnl)dip->hnl = dip->dnl;} 684: else{if(v.nl > dip->hnl)dip->hnl = v.nl;} 685: ffree(begin); 686: } 687: casepc(){ 688: pagech = chget(IMP); 689: } 690: hseg(f,p) 691: int (*f)(); 692: filep p; 693: { 694: register acc, i; 695: static filep q; 696: 697: acc = 0; 698: if(p)q = p; 699: while(1){ 700: i = rbf0(q); 701: q = incoff(q); 702: if(!i || (i == IMP))return(acc); 703: if((i & CMASK) == pagech){ 704: nrbits = i & ~CMASK; 705: nform = fmt[findr('%')]; 706: acc += fnumb(v.pn,f); 707: }else acc += (*f)(i); 708: } 709: } 710: casepm(){ 711: register i, k; 712: register char *p; 713: int xx, cnt, kk, tot; 714: filep j; 715: char *kvt(); 716: char pmline[10]; 717: 718: kk = cnt = 0; 719: tot = !skip(); 720: for(i = 0; i<NM; i++){ 721: if(!((xx = contab[i].rq) & MMASK))continue; 722: p = pmline; 723: j = (((filep)contab[i].x.mx)<<BLKBITS); 724: k = 1; 725: while((j = blist[blisti(j)]) != -1){k++; j <<= BLKBITS;} 726: cnt++; 727: kk += k; 728: if(!tot){ 729: *p++ = xx & 0177; 730: if(!(*p++ = (xx >> BYTE) & 0177))*(p-1) = ' '; 731: *p++ = ' '; 732: kvt(k,p); 733: prstr(pmline); 734: } 735: } 736: if(tot || (cnt > 1)){ 737: kvt(kk,pmline); 738: prstr(pmline); 739: } 740: } 741: char *kvt(k,p) 742: int k; 743: char *p; 744: { 745: if(k>=100)*p++ = k/100 + '0'; 746: if(k>=10)*p++ = (k%100)/10 + '0'; 747: *p++ = k%10 + '0'; 748: *p++ = '\n'; 749: *p = 0; 750: return(p); 751: } 752: dummy(){}