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