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