|
|
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.