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