|
|
1.1 ! root 1: /* ! 2: * troff3.c ! 3: * ! 4: * macro and string routines, storage allocation ! 5: */ ! 6: ! 7: ! 8: #include "tdef.h" ! 9: #include "fns.h" ! 10: #include "ext.h" ! 11: ! 12: Tchar *argtop; ! 13: int pagech = '%'; ! 14: int strflg; ! 15: ! 16: #define MHASHSIZE 128 /* must be 2**n */ ! 17: #define MHASH(x) ((x>>6)^x) & (MHASHSIZE-1) ! 18: Contab *mhash[MHASHSIZE]; ! 19: ! 20: ! 21: Blockp *blist; /* allocated blocks for macros and strings */ ! 22: int nblist; /* how many there are */ ! 23: ! 24: void blockinit(void) ! 25: { ! 26: blist = (Blockp *) calloc(NBLIST, sizeof(Blockp)); ! 27: if (blist == NULL) { ! 28: ERROR "not enough room for %d blocks", NBLIST WARN; ! 29: done2(1); ! 30: } ! 31: nblist = NBLIST; ! 32: blist[0].nextoff = blist[1].nextoff = -1; ! 33: blist[0].bp = (Tchar *) calloc(BLK, sizeof(Tchar)); ! 34: blist[1].bp = (Tchar *) calloc(BLK, sizeof(Tchar)); ! 35: /* -1 prevents blist[0] from being used; temporary fix */ ! 36: /* for a design botch: offset==0 is overloaded. */ ! 37: /* blist[1] reserved for .rd indicator -- also unused. */ ! 38: /* but someone unwittingly looks at these, so allocate something */ ! 39: } ! 40: ! 41: ! 42: void caseig(void) ! 43: { ! 44: int i; ! 45: Offset oldoff = offset; ! 46: ! 47: offset = 0; ! 48: i = copyb(); ! 49: offset = oldoff; ! 50: if (i != '.') ! 51: control(i, 1); ! 52: } ! 53: ! 54: ! 55: void casern(void) ! 56: { ! 57: int i, j; ! 58: ! 59: lgf++; ! 60: skip(); ! 61: if ((i = getrq()) == 0 || (oldmn = findmn(i)) < 0) ! 62: return; ! 63: skip(); ! 64: clrmn(findmn(j = getrq())); ! 65: if (j) { ! 66: munhash(&contab[oldmn]); ! 67: contab[oldmn].rq = j; ! 68: maddhash(&contab[oldmn]); ! 69: } ! 70: } ! 71: ! 72: void maddhash(Contab *rp) ! 73: { ! 74: Contab **hp; ! 75: ! 76: if (rp->rq == 0) ! 77: return; ! 78: hp = &mhash[MHASH(rp->rq)]; ! 79: rp->link = *hp; ! 80: *hp = rp; ! 81: } ! 82: ! 83: void munhash(Contab *mp) ! 84: { ! 85: Contab *p; ! 86: Contab **lp; ! 87: ! 88: if (mp->rq == 0) ! 89: return; ! 90: lp = &mhash[MHASH(mp->rq)]; ! 91: p = *lp; ! 92: while (p) { ! 93: if (p == mp) { ! 94: *lp = p->link; ! 95: p->link = 0; ! 96: return; ! 97: } ! 98: lp = &p->link; ! 99: p = p->link; ! 100: } ! 101: } ! 102: ! 103: void mrehash(void) ! 104: { ! 105: Contab *p; ! 106: int i; ! 107: ! 108: for (i=0; i < MHASHSIZE; i++) ! 109: mhash[i] = 0; ! 110: for (p=contab; p < &contab[NM]; p++) ! 111: p->link = 0; ! 112: for (p=contab; p < &contab[NM]; p++) { ! 113: if (p->rq == 0) ! 114: continue; ! 115: i = MHASH(p->rq); ! 116: p->link = mhash[i]; ! 117: mhash[i] = p; ! 118: } ! 119: } ! 120: ! 121: void caserm(void) ! 122: { ! 123: int j; ! 124: ! 125: lgf++; ! 126: while (!skip() && (j = getrq()) != 0) ! 127: clrmn(findmn(j)); ! 128: lgf--; ! 129: } ! 130: ! 131: ! 132: void caseas(void) ! 133: { ! 134: app++; ! 135: caseds(); ! 136: } ! 137: ! 138: ! 139: void caseds(void) ! 140: { ! 141: ds++; ! 142: casede(); ! 143: } ! 144: ! 145: ! 146: void caseam(void) ! 147: { ! 148: app++; ! 149: casede(); ! 150: } ! 151: ! 152: ! 153: void casede(void) ! 154: { ! 155: int i, req; ! 156: Offset savoff; ! 157: ! 158: req = '.'; ! 159: lgf++; ! 160: skip(); ! 161: if ((i = getrq()) == 0) ! 162: goto de1; ! 163: if ((offset = finds(i)) == 0) ! 164: goto de1; ! 165: if (ds) ! 166: copys(); ! 167: else ! 168: req = copyb(); ! 169: clrmn(oldmn); ! 170: if (newmn) { ! 171: if (contab[newmn].rq) ! 172: munhash(&contab[newmn]); ! 173: contab[newmn].rq = i; ! 174: maddhash(&contab[newmn]); ! 175: } ! 176: if (apptr) { ! 177: savoff = offset; ! 178: offset = apptr; ! 179: wbf((Tchar) IMP); ! 180: offset = savoff; ! 181: } ! 182: offset = dip->op; ! 183: if (req != '.') ! 184: control(req, 1); ! 185: de1: ! 186: ds = app = 0; ! 187: } ! 188: ! 189: ! 190: int findmn(int i) ! 191: { ! 192: Contab *p; ! 193: ! 194: for (p = mhash[MHASH(i)]; p; p = p->link) ! 195: if (i == p->rq) ! 196: return(p - contab); ! 197: return(-1); ! 198: } ! 199: ! 200: ! 201: void clrmn(int i) ! 202: { ! 203: if (i >= 0) { ! 204: if (contab[i].mx) ! 205: ffree(contab[i].mx); ! 206: munhash(&contab[i]); ! 207: contab[i].rq = 0; ! 208: contab[i].mx = 0; ! 209: contab[i].f = 0; ! 210: } ! 211: } ! 212: ! 213: ! 214: Offset finds(int mn) ! 215: { ! 216: int i; ! 217: Offset savip; ! 218: ! 219: oldmn = findmn(mn); ! 220: newmn = 0; ! 221: apptr = 0; ! 222: if (app && oldmn >= 0 && contab[oldmn].mx) { ! 223: savip = ip; ! 224: ip = contab[oldmn].mx; ! 225: oldmn = -1; ! 226: while (rbf() != 0) ! 227: ; ! 228: apptr = ip; ! 229: if (!diflg) ! 230: ip = incoff(ip); ! 231: nextb = ip; ! 232: ip = savip; ! 233: } else { ! 234: for (i = 0; i < NM; i++) { ! 235: if (contab[i].rq == 0) ! 236: break; ! 237: } ! 238: if (i == NM || (nextb = alloc()) == -1) { ! 239: app = 0; ! 240: if (macerr++ > 1) ! 241: done2(02); ! 242: if (i == NM) ! 243: ERROR "Too many (%d) string/macro names", NM WARN; ! 244: if (nextb == 0) ! 245: ERROR "Too much space for string/macro names" WARN, abort(); ! 246: edone(04); ! 247: return(offset = 0); ! 248: } ! 249: contab[i].mx = nextb; ! 250: if (!diflg) { ! 251: newmn = i; ! 252: if (oldmn == -1) ! 253: contab[i].rq = -1; ! 254: } else { ! 255: contab[i].rq = mn; ! 256: maddhash(&contab[i]); ! 257: } ! 258: } ! 259: app = 0; ! 260: return(offset = nextb); ! 261: } ! 262: ! 263: ! 264: int skip(void) ! 265: { ! 266: Tchar i; ! 267: ! 268: while (cbits(i = getch()) == ' ') ! 269: ; ! 270: ch = i; ! 271: return(nlflg); ! 272: } ! 273: ! 274: ! 275: int copyb(void) ! 276: { ! 277: int i, j, state; ! 278: Tchar ii; ! 279: int req, k; ! 280: Offset savoff; ! 281: char *p; ! 282: ! 283: if (skip() || !(j = getrq())) ! 284: j = '.'; ! 285: req = j; ! 286: p = unpair(j); ! 287: /* was: k = j >> BYTE; j &= BYTEMASK; */ ! 288: j = p[0]; ! 289: k = p[1]; ! 290: copyf++; ! 291: flushi(); ! 292: nlflg = 0; ! 293: state = 1; ! 294: ! 295: /* state 0 eat up ! 296: * state 1 look for . ! 297: * state 2 look for first char of end macro ! 298: * state 3 look for second char of end macro ! 299: */ ! 300: ! 301: while (1) { ! 302: i = cbits(ii = getch()); ! 303: if (state == 3) { ! 304: if (i == k) ! 305: break; ! 306: if (!k) { ! 307: ch = ii; ! 308: i = getach(); ! 309: ch = ii; ! 310: if (!i) ! 311: break; ! 312: } ! 313: state = 0; ! 314: goto c0; ! 315: } ! 316: if (i == '\n') { ! 317: state = 1; ! 318: nlflg = 0; ! 319: goto c0; ! 320: } ! 321: if (state == 1 && i == '.') { ! 322: state++; ! 323: savoff = offset; ! 324: goto c0; ! 325: } ! 326: if (state == 2 && i == j) { ! 327: state++; ! 328: goto c0; ! 329: } ! 330: state = 0; ! 331: c0: ! 332: if (offset) ! 333: wbf(ii); ! 334: } ! 335: if (offset) { ! 336: offset = savoff; ! 337: wbf((Tchar)0); ! 338: } ! 339: copyf--; ! 340: return(req); ! 341: } ! 342: ! 343: ! 344: void copys(void) ! 345: { ! 346: Tchar i; ! 347: ! 348: copyf++; ! 349: if (skip()) ! 350: goto c0; ! 351: if (cbits(i = getch()) != '"') ! 352: wbf(i); ! 353: while (cbits(i = getch()) != '\n') ! 354: wbf(i); ! 355: c0: ! 356: wbf((Tchar)0); ! 357: copyf--; ! 358: } ! 359: ! 360: ! 361: Offset alloc(void) /* return free Offset in nextb */ ! 362: { ! 363: int i, j; ! 364: ! 365: for (i = 0; i < nblist; i++) ! 366: if (blist[i].nextoff == 0) ! 367: break; ! 368: if (i == nblist) { ! 369: blist = (Blockp *) realloc((char *) blist, 2 * nblist * sizeof(Blockp)); ! 370: if (blist == NULL) { ! 371: ERROR "can't grow blist for string/macro defns" WARN; ! 372: done2(2); ! 373: } ! 374: nblist *= 2; ! 375: for (j = i; j < nblist; j++) { ! 376: blist[j].nextoff = 0; ! 377: blist[j].bp = 0; ! 378: } ! 379: } ! 380: blist[i].nextoff = -1; /* this block is the end */ ! 381: if (blist[i].bp == 0) ! 382: blist[i].bp = (Tchar *) calloc(BLK, sizeof(Tchar)); ! 383: nextb = (Offset) i * BLK; ! 384: return nextb; ! 385: } ! 386: ! 387: ! 388: void ffree(Offset i) /* free list of blocks starting at blist(o) */ ! 389: { /* (doesn't actually free the blocks, just the pointers) */ ! 390: int j; ! 391: ! 392: for ( ; blist[j = bindex(i)].nextoff != -1; ) { ! 393: i = blist[j].nextoff; ! 394: blist[j].nextoff = 0; ! 395: } ! 396: blist[j].nextoff = 0; ! 397: } ! 398: ! 399: ! 400: void wbf(Tchar i) /* store i into offset, get ready for next one */ ! 401: { ! 402: int j, off; ! 403: ! 404: if (!offset) ! 405: return; ! 406: j = bindex(offset); ! 407: off = boffset(offset); ! 408: blist[j].bp[off++] = i; ! 409: offset++; ! 410: if (pastend(offset)) { /* off the end of this block */ ! 411: if (blist[j].nextoff == -1) { ! 412: if ((nextb = alloc()) == -1) { ! 413: ERROR "Out of temp file space" WARN; ! 414: done2(01); ! 415: } ! 416: blist[j].nextoff = nextb; ! 417: } ! 418: offset = blist[j].nextoff; ! 419: } ! 420: } ! 421: ! 422: ! 423: Tchar rbf(void) /* return next char from blist[] block */ ! 424: { ! 425: Tchar i, j; ! 426: ! 427: if (ip == RD_OFFSET) { /* for rdtty */ ! 428: if (j = rdtty()) ! 429: return(j); ! 430: else ! 431: return(popi()); ! 432: } ! 433: ! 434: i = rbf0(ip); ! 435: if (i == 0) { ! 436: if (!app) ! 437: i = popi(); ! 438: return(i); ! 439: } ! 440: ip = incoff(ip); ! 441: return(i); ! 442: } ! 443: ! 444: ! 445: Offset xxxincoff(Offset p) /* get next blist[] block */ ! 446: { ! 447: p++; ! 448: if (pastend(p)) { /* off the end of this block */ ! 449: if ((p = blist[bindex(p-1)].nextoff) == -1) { /* and nothing was allocated after it */ ! 450: ERROR "Bad storage allocation" WARN; ! 451: done2(-5); ! 452: } ! 453: } ! 454: return(p); ! 455: } ! 456: ! 457: ! 458: Tchar popi(void) ! 459: { ! 460: Stack *p; ! 461: ! 462: if (frame == stk) ! 463: return(0); ! 464: if (strflg) ! 465: strflg--; ! 466: p = nxf = frame; ! 467: p->nargs = 0; ! 468: frame = p->pframe; ! 469: ip = p->pip; ! 470: pendt = p->ppendt; ! 471: lastpbp = p->lastpbp; ! 472: return(p->pch); ! 473: } ! 474: ! 475: /* ! 476: * test that the end of the allocation is above a certain location ! 477: * in memory ! 478: */ ! 479: #define SPACETEST(base, size) \ ! 480: if ((char*)base + size >= (char*)stk+STACKSIZE) \ ! 481: ERROR "Stacksize overflow in n3" WARN ! 482: ! 483: Offset pushi(Offset newip, int mname) ! 484: { ! 485: Stack *p; ! 486: ! 487: SPACETEST(nxf, sizeof(Stack)); ! 488: p = nxf; ! 489: p->pframe = frame; ! 490: p->pip = ip; ! 491: p->ppendt = pendt; ! 492: p->pch = ch; ! 493: p->lastpbp = lastpbp; ! 494: p->mname = mname; ! 495: lastpbp = pbp; ! 496: pendt = ch = 0; ! 497: frame = nxf; ! 498: if (nxf->nargs == 0) ! 499: nxf += 1; ! 500: else ! 501: nxf = (Stack *)argtop; ! 502: return(ip = newip); ! 503: } ! 504: ! 505: ! 506: void *setbrk(int x) ! 507: { ! 508: char *i; ! 509: ! 510: if ((i = (char *) calloc(x, 1)) == 0) { ! 511: ERROR "Core limit reached" WARN; ! 512: edone(0100); ! 513: } ! 514: return(i); ! 515: } ! 516: ! 517: ! 518: int getsn(void) ! 519: { ! 520: int i; ! 521: ! 522: if ((i = getach()) == 0) ! 523: return(0); ! 524: if (i == '(') ! 525: return(getrq()); ! 526: else ! 527: return(i); ! 528: } ! 529: ! 530: ! 531: Offset setstr(void) ! 532: { ! 533: int i, j; ! 534: ! 535: lgf++; ! 536: if ((i = getsn()) == 0 || (j = findmn(i)) == -1 || !contab[j].mx) { ! 537: lgf--; ! 538: return(0); ! 539: } else { ! 540: SPACETEST(nxf, sizeof(Stack)); ! 541: nxf->nargs = 0; ! 542: strflg++; ! 543: lgf--; ! 544: return pushi(contab[j].mx, i); ! 545: } ! 546: } ! 547: ! 548: ! 549: ! 550: void collect(void) ! 551: { ! 552: int j; ! 553: Tchar i, *strp, *lim, **argpp, **argppend; ! 554: int quote; ! 555: Stack *savnxf; ! 556: ! 557: copyf++; ! 558: nxf->nargs = 0; ! 559: savnxf = nxf; ! 560: if (skip()) ! 561: goto rtn; ! 562: ! 563: { ! 564: char *memp; ! 565: memp = (char *)savnxf; ! 566: /* ! 567: * 1 s structure for the macro descriptor ! 568: * APERMAC Tchar *'s for pointers into the strings ! 569: * space for the Tchar's themselves ! 570: */ ! 571: memp += sizeof(Stack); ! 572: /* ! 573: * CPERMAC = the total # of characters for ALL arguments ! 574: */ ! 575: #define CPERMAC 200 ! 576: #define APERMAC 9 ! 577: memp += APERMAC * sizeof(Tchar *); ! 578: memp += CPERMAC * sizeof(Tchar); ! 579: nxf = (Stack *)memp; ! 580: } ! 581: lim = (Tchar *)nxf; ! 582: argpp = (Tchar **)(savnxf + 1); ! 583: argppend = &argpp[APERMAC]; ! 584: SPACETEST(argppend, sizeof(Tchar *)); ! 585: strp = (Tchar *)argppend; ! 586: /* ! 587: * Zero out all the string pointers before filling them in. ! 588: */ ! 589: for (j = 0; j < APERMAC; j++) ! 590: argpp[j] = 0; ! 591: /* ERROR "savnxf=0x%x,nxf=0x%x,argpp=0x%x,strp=argppend=0x%x, lim=0x%x", ! 592: * savnxf, nxf, argpp, strp, lim WARN; ! 593: */ ! 594: strflg = 0; ! 595: while (argpp != argppend && !skip()) { ! 596: *argpp++ = strp; ! 597: quote = 0; ! 598: if (cbits(i = getch()) == '"') ! 599: quote++; ! 600: else ! 601: ch = i; ! 602: while (1) { ! 603: i = getch(); ! 604: /* fprintf(stderr, "collect %c %d\n", cbits(i), cbits(i)); */ ! 605: if (nlflg || (!quote && argpp != argppend && cbits(i) == ' ')) ! 606: break; /* collects rest into $9 */ ! 607: if ( quote ! 608: && cbits(i) == '"' ! 609: && cbits(i = getch()) != '"') { ! 610: ch = i; ! 611: break; ! 612: } ! 613: *strp++ = i; ! 614: if (strflg && strp >= lim) { ! 615: /* ERROR "strp=0x%x, lim = 0x%x", strp, lim WARN; */ ! 616: ERROR "Macro argument too long" WARN; ! 617: copyf--; ! 618: edone(004); ! 619: } ! 620: SPACETEST(strp, 3 * sizeof(Tchar)); ! 621: } ! 622: *strp++ = 0; ! 623: } ! 624: nxf = savnxf; ! 625: nxf->nargs = argpp - (Tchar **)(savnxf + 1); ! 626: argtop = strp; ! 627: rtn: ! 628: copyf--; ! 629: } ! 630: ! 631: ! 632: void seta(void) ! 633: { ! 634: int i; ! 635: ! 636: i = cbits(getch()) - '0'; ! 637: if (i > 0 && i <= APERMAC && i <= frame->nargs) ! 638: pushback(*(((Tchar **)(frame + 1)) + i - 1)); ! 639: } ! 640: ! 641: ! 642: void caseda(void) ! 643: { ! 644: app++; ! 645: casedi(); ! 646: } ! 647: ! 648: ! 649: void casedi(void) ! 650: { ! 651: int i, j, *k; ! 652: ! 653: lgf++; ! 654: if (skip() || (i = getrq()) == 0) { ! 655: if (dip != d) ! 656: wbf((Tchar)0); ! 657: if (dilev > 0) { ! 658: numtab[DN].val = dip->dnl; ! 659: numtab[DL].val = dip->maxl; ! 660: dip = &d[--dilev]; ! 661: offset = dip->op; ! 662: } ! 663: goto rtn; ! 664: } ! 665: if (++dilev == NDI) { ! 666: --dilev; ! 667: ERROR "Diversions nested too deep" WARN; ! 668: edone(02); ! 669: } ! 670: if (dip != d) ! 671: wbf((Tchar)0); ! 672: diflg++; ! 673: dip = &d[dilev]; ! 674: dip->op = finds(i); ! 675: dip->curd = i; ! 676: clrmn(oldmn); ! 677: k = (int *) & dip->dnl; ! 678: for (j = 0; j < 10; j++) ! 679: k[j] = 0; /*not op and curd*/ ! 680: rtn: ! 681: app = 0; ! 682: diflg = 0; ! 683: } ! 684: ! 685: ! 686: void casedt(void) ! 687: { ! 688: lgf++; ! 689: dip->dimac = dip->ditrap = dip->ditf = 0; ! 690: skip(); ! 691: dip->ditrap = vnumb((int *)0); ! 692: if (nonumb) ! 693: return; ! 694: skip(); ! 695: dip->dimac = getrq(); ! 696: } ! 697: ! 698: ! 699: void casetl(void) ! 700: { ! 701: int j; ! 702: int w[3]; ! 703: Tchar buf[LNSIZE]; ! 704: Tchar *tp; ! 705: Tchar i, delim; ! 706: ! 707: /* ! 708: * bug fix ! 709: * ! 710: * if .tl is the first thing in the file, the p1 ! 711: * doesn't come out, also the pagenumber will be 0 ! 712: * ! 713: * tends too confuse the device filter (and the user as well) ! 714: */ ! 715: if (dip == d && numtab[NL].val == -1) ! 716: newline(1); ! 717: dip->nls = 0; ! 718: skip(); ! 719: if (ismot(delim = getch())) { ! 720: ch = delim; ! 721: delim = '\''; ! 722: } else ! 723: delim = cbits(delim); ! 724: tp = buf; ! 725: numtab[HP].val = 0; ! 726: w[0] = w[1] = w[2] = 0; ! 727: j = 0; ! 728: while (cbits(i = getch()) != '\n') { ! 729: if (cbits(i) == cbits(delim)) { ! 730: if (j < 3) ! 731: w[j] = numtab[HP].val; ! 732: numtab[HP].val = 0; ! 733: j++; ! 734: *tp++ = 0; ! 735: } else { ! 736: if (cbits(i) == pagech) { ! 737: setn1(numtab[PN].val, numtab[findr('%')].fmt, ! 738: i&SFMASK); ! 739: continue; ! 740: } ! 741: numtab[HP].val += width(i); ! 742: if (tp < &buf[LNSIZE-10]) ! 743: *tp++ = i; ! 744: } ! 745: } ! 746: if (j<3) ! 747: w[j] = numtab[HP].val; ! 748: *tp++ = 0; ! 749: *tp++ = 0; ! 750: *tp = 0; ! 751: tp = buf; ! 752: if (NROFF) ! 753: horiz(po); ! 754: while (i = *tp++) ! 755: pchar(i); ! 756: if (w[1] || w[2]) ! 757: horiz(j = quant((lt - w[1]) / 2 - w[0], HOR)); ! 758: while (i = *tp++) ! 759: pchar(i); ! 760: if (w[2]) { ! 761: horiz(lt - w[0] - w[1] - w[2] - j); ! 762: while (i = *tp++) ! 763: pchar(i); ! 764: } ! 765: newline(0); ! 766: if (dip != d) { ! 767: if (dip->dnl > dip->hnl) ! 768: dip->hnl = dip->dnl; ! 769: } else { ! 770: if (numtab[NL].val > dip->hnl) ! 771: dip->hnl = numtab[NL].val; ! 772: } ! 773: } ! 774: ! 775: ! 776: void casepc(void) ! 777: { ! 778: pagech = chget(IMP); ! 779: } ! 780: ! 781: ! 782: void casepm(void) ! 783: { ! 784: int i, k; ! 785: int xx, cnt, tcnt, kk, tot; ! 786: Offset j; ! 787: ! 788: kk = cnt = tcnt = 0; ! 789: tot = !skip(); ! 790: stackdump(); ! 791: for (i = 0; i < NM; i++) { ! 792: if ((xx = contab[i].rq) == 0 || contab[i].mx == 0) ! 793: continue; ! 794: tcnt++; ! 795: j = contab[i].mx; ! 796: for (k = 1; (j = blist[bindex(j)].nextoff) != -1; ) ! 797: k++; ! 798: cnt++; ! 799: kk += k; ! 800: if (!tot) ! 801: fprintf(stderr, "%-2.2s %d\n", unpair(xx), k); ! 802: } ! 803: fprintf(stderr, "pm: total %d, macros %d, space %d\n", tcnt, cnt, kk); ! 804: } ! 805: ! 806: void stackdump(void) /* dumps stack of macros in process */ ! 807: { ! 808: Stack *p; ! 809: ! 810: if (frame != stk) { ! 811: fprintf(stderr, "stack: "); ! 812: for (p = frame; p != stk; p = p->pframe) ! 813: fprintf(stderr, "%s ", unpair(p->mname)); ! 814: fprintf(stderr, "\n"); ! 815: } ! 816: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.