|
|
1.1 root 1: #include "tdef.hd"
2: #include "strs.hd"
3: #ifdef NROFF
4: #include "tw.hd"
5: extern struct ttable t;
6: #endif
7:
8: /*
9: troff3.c
10:
11: macro and string routines, storage allocation
12: */
13:
14: extern struct s *frame, *stk, *nxf;
15: extern struct tmpfaddr ip;
16: extern struct tmpfaddr offset;
17: extern struct tmpfaddr nextb;
18: extern struct d d[NDI], *dip;
19: #ifndef INCORE
20: extern struct envblock eblock;
21: #else
22: extern struct envblock eblock[NEV];
23: extern int ev;
24: extern char *malloc();
25: #include "stdio.h"
26: #endif
27: extern struct datablock dblock;
28: typedef unsigned short tint; /* type of characters stored in tmp file */
29:
30: extern char *enda;
31:
32: extern int vflag;
33: extern int tch[];
34: extern int *cstk[], cstkl;
35: extern int ch_CMASK;
36: extern int ch;
37: extern int ibf;
38: extern int lgf;
39: extern int copyf;
40: extern int app;
41: extern int ds;
42: extern int nlflg;
43: extern int *argtop;
44: extern int dilev;
45: extern int nonumb;
46: extern int nrbits;
47: extern int nform;
48: extern int oldmn;
49: extern int newmn;
50: extern int macerr;
51: extern struct tmpfaddr apptr;
52: extern int diflg;
53: extern struct tmpfaddr woff;
54: extern int wbfi;
55: extern int po;
56: int **argpp;
57: int umaccp=0;
58: int rmaccp=0; /* use and real macro cache buffer pointer */
59: int macbcnt=0; /* macro block read count */
60: int pagech = '%';
61: int strflg;
62: union {
63: tint wnt[BLK];
64: char wp[BLK*(sizeof(tint)/sizeof(char))];
65: } wbuf; /* output buffer */
66: union {
67: tint rnt[NB][BLK];
68: char rp[NB][BLK*(sizeof(tint)/sizeof(char))];
69: } rbuf; /* macro input buffer cache */
70: int roff[NB]; /* block names for buffers resident in the cache */
71: int maclev=0; /* depth of macro (or string or diversion) calls */
72: extern int regcnt;
73: int freenslot = -1;
74: #ifdef INCORE
75: tint *memblist[NBLIST]; /* incore tmp file mem pointers */
76: int *argstrs[NMACS]; /* macro arg strings */
77: int argstrp = 0; /* index into argstrs */
78: int *argsp; /* pointer to latest collected args */
79: int *sstrp;
80: #endif
81: caseig(){
82: register i;
83:
84: offset.b = 0;
85: if((i = copyb()) != '.')control(i,1);
86: }
87: casern(){
88: register i,j;
89:
90: lgf++;
91: skip();
92: if ((oldmn = frmname(getrq())) < 0) return;
93: skip();
94: drmname(i = frmname(j = getrq()));
95: if (j) {
96: if (freenslot == -1) {
97: if (i == -1) {
98: prstr("too many names for rn");
99: ferrex(); }
100: freenslot = i; }
101:
102: nametab[freenslot].ename = (nametab[oldmn].ename & TAGSMASK) | j;
103: nametab[freenslot].vv.val = nametab[oldmn].vv.val;
104: nametab[oldmn].ename = -1; }
105: }
106: caserm(){
107: lgf++;
108: while(!skip()){
109: drmname(frmname(getrq()));
110: }
111: }
112: caseas(){
113: app++;
114: caseds();
115: }
116: caseds(){
117: ds++;
118: casede();
119: }
120: caseam(){
121: app++;
122: casede();
123: }
124: casede(){
125: register i, req;
126: register struct tmpfaddr savoff;
127: extern filep finds();
128:
129: if (dilev > 0) wbfl();
130: req = '.';
131: lgf++;
132: skip();
133: if ((i = getrq()) && finds(i)) {
134: if(ds)copys();
135: else req = copyb();
136: wbfl();
137: drmname(oldmn);
138: if (newmn >= 0) nametab[newmn].ename = i | MMASK;
139: if(apptr.b){
140: cptmpfaddr(savoff,offset);
141: cptmpfaddr(offset,apptr);
142: wbt(IMP);
143: cptmpfaddr(offset,savoff);
144: }
145: cptmpfaddr(offset,dip->op);
146: if(req != '.')control(req,1); }
147: ds = app = 0;
148: return;
149: }
150: frmname(name)
151: /* find name in hashed request/macro/string table */
152: int name;
153: {
154: register int hname, toff, htoff;
155:
156: if (!name) return -1;
157: freenslot = -1; /* pos of first free name slot */
158: hname = name & NAMEMASK;
159: htoff = toff = abs(HASH(name,NM)); /* save orig value */
160:
161: while (nametab[toff].ename) { /* check next entry */
162: if ((nametab[toff].ename & NAMEMASK) == hname) return toff;
163: if ((nametab[toff].ename == -1) && (freenslot == -1))
164: freenslot = toff;
165: toff = (toff + 1) % NM;
166: if (toff == htoff) return -1; }
167: if (freenslot == -1) freenslot = toff;
168: return -1; /* not found */
169: }
170: fnrname(name) /* find a name in the hashed number register table */
171: int name;
172: {
173: register int hname, toff, htoff;
174:
175: if (!name) return -1;
176: freenslot = -1; /* mark first free slot pos */
177: hname = name & NAMEMASK;
178: htoff = toff = abs(HASH(name,NN));
179:
180: while (r[toff]) { /* check next slot */
181: if ((r[toff] & NAMEMASK) == hname) return toff;
182: if ((r[toff] == -1) && (freenslot == -1)) freenslot = toff;
183: toff = (toff + 1) % NN;
184: if (toff == htoff) return -1; }
185: if (freenslot == -1) freenslot = toff;
186: return -1; /* not found */
187: }
188: drmname(toff) /* remove name from request, macro table */
189: register int toff;
190: {
191: if (toff == -1) return;
192: if (nametab[toff].ename & MMASK) /* free macro storage */
193: ffree((filep)nametab[toff].vv.val);
194: nametab[toff].ename = -1; /* free hashed entry */
195: }
196: filep finds(mn)
197: int mn;
198: {
199: register i, j;
200: register struct tmpfaddr tip;
201: int savmacbcnt;
202: extern filep alloc();
203:
204: oldmn = frmname(mn); /* get macro name */
205: newmn = -1;
206: apptr.b = (filep)0;
207: if(app && (oldmn >= 0) && (nametab[oldmn].ename & MMASK)){
208: maclev++;
209: savmacbcnt = macbcnt;
210: tip.b = (filep)nametab[oldmn].vv.val;
211: tip.o = 0;
212: macbcnt = 0;
213: oldmn = -1;
214: while (rbf0(&tip)) incoff(tip);
215: cptmpfaddr(apptr,tip);
216: if (!diflg) incoff(tip);
217: cptmpfaddr(nextb,tip);
218: macbcnt = savmacbcnt;
219: maclev--;
220: }else{
221: if (((i = freenslot) == -1) && (oldmn >= 0))
222: for (j=(oldmn+1)%NM; j!=oldmn; j=((j+1)%NM))
223: if ((nametab[j].ename == -1) || (!nametab[j].ename))
224: { i = j; break; }
225: if ((i == -1) || (i == oldmn) || !alloc()) {
226: app = 0;
227: if(macerr++ > 1)done2(02);
228: prstr("Too many string/macro names.\n");
229: edone(04);
230: offset.o = 0;
231: return(offset.b = 0);
232: }
233: nametab[i].vv.val = (filep)nextb.b;
234: if(!diflg){
235: newmn = i;
236: if(oldmn == -1)nametab[i].ename = -1; }
237: else nametab[i].ename = mn | MMASK;
238: offset.o = 0;
239: }
240:
241: app = 0;
242: cptmpfaddr(offset,nextb);
243: return (offset.b);
244: }
245: skip(){
246: register i;
247:
248: do i = getch();
249: while (ch_CMASK == ' ');
250: ch=i;
251: return(nlflg);
252: }
253: copyb()
254: {
255: register ii, j, k;
256: int i, req;
257: int tbuf[3];
258:
259: if(skip() || !(j=getrq()))j = '.';
260: req = j;
261: k = j>>BYTE;
262: j &= BMASK;
263: copyf++;
264: flushi();
265:
266: while (1) { /* read body of macro */
267: nlflg = 0;
268: ii = 0;
269: if ((tbuf[ii++] = getch()) &&
270: ((ch_CMASK == cc) || (ch_CMASK == c2))) {
271:
272: do tbuf[ii] = getch(); /* skip leading blanks */
273: while ((ch_CMASK == ' ') || (ch_CMASK == '\t'));
274: ii++;
275:
276: if (ch_CMASK == j) { /* first terminating char? */
277: if ((tbuf[ii++] = getch()) && (ch_CMASK == k))
278: goto found;
279:
280: if (!k) { /* single letter call? */
281: ch = tbuf[ii-1];
282: i = getach();
283: ch = tbuf[ii-1];
284: if (!i) goto found; }}}
285:
286: for (i=0; i<ii; i++) /* copy early part of line */
287: wbf(tbuf[i]);
288:
289: if (tbuf[ii-1] != '\n')
290: do wbf(i = getch());
291: while (i != '\n'); } /* copy to end of line */
292:
293: found:
294: wbt(0);
295: copyf--;
296: return(req);
297: }
298: copys()
299: {
300: register i;
301:
302: copyf++;
303: if(skip())goto c0;
304: if(((i=getch()) & CMASK) != '"')wbf(i);
305: while(((i=getch()) & CMASK) != '\n')wbf(i);
306: c0:
307: wbt(0);
308: copyf--;
309: }
310: filep alloc()
311: {
312: register filep i;
313:
314: for(i=1; i<=NBLIST; i++)
315: if(blist[i] == 0)break;
316: if (i == NBLIST+1) i = 0;
317: else { blist[i] = -1;
318: #ifdef INCORE
319: if ((memblist[i] =
320: (tint *)malloc(BLK*sizeof(tint))) == NULL) {
321: prstr("out of memory for store");
322: exit(1); }
323: #endif
324: }
325: nextb.o = 0;
326: return (nextb.b = i);
327: }
328: ffree(i)
329: register filep i;
330: {
331: register j;
332:
333: while((blist[j = i]) != (filep)-1){
334: #ifdef INCORE
335: free(memblist[i]);
336: #endif
337: i = blist[i];
338: blist[j] = 0;
339: }
340: blist[j] = 0;
341: }
342: wbt(i)
343: int i;
344: {
345: wbf(i);
346: wbfl();
347: }
348: wbf(i)
349: int i;
350: {
351: if(!offset.b)return;
352: if(!woff.b){
353: cptmpfaddr(woff,offset);
354: wbfi = 0;
355: }
356: wbuf.wnt[wbfi++] = (tint)i;
357: if (!(offset.o = ++offset.o & (BLK - 1))) {
358: wbfl();
359: if(blist[offset.b] == (filep)-1){
360: if(alloc() == 0){
361: prstr("Out of temp file space.\n");
362: done2(01); }
363: blist[offset.b] = (filep) nextb.b; }
364: offset.b = (filep) blist[offset.b]; }
365: if(wbfi >= BLK)wbfl();
366: }
367: wbfl(){
368: register int i, j;
369: #ifdef INCORE
370: register tint *bp;
371: #endif
372:
373: if (!woff.b) return;
374: #ifndef INCORE
375: lseek(ibf, (long)(boff(woff.b) + woff.o) * sizeof(tint), 0);
376: write(ibf, wbuf.wp, (int)(wbfi * sizeof(tint)));
377: #else
378: bp = memblist[woff.b] + woff.o;
379: for (i=0; i<wbfi; i++)
380: *bp++ = wbuf.wnt[i]; /* save block */
381: #endif
382: for (i=0; i<NB; i++)
383: if (woff.b == roff[i]) {
384: for (j=0; j<wbfi; j++)
385: rbuf.rnt[i][woff.o+j] = wbuf.wnt[j]; /* fix up read buffer */
386: break; }
387: woff.b = 0;
388: }
389: rbf(){
390: register i;
391:
392: if (!(i = rbf0(&ip))) {
393: i = popi();
394: if (maclev) rmaccp = (!rmaccp) ? NB-1 : rmaccp-1; }
395: else incoff(ip);
396: return(i);
397: }
398: rbf0(fp)
399: struct tmpfaddr *fp;
400: {
401: register filep i;
402:
403: if ((fp->b == (filep)-1) || (fp->b == (filep)-2)) return -1;
404:
405: if (fp->b != roff[umaccp]) { /* test if buffer in cache */
406: for (i=0; i<NB; i++)
407: if (fp->b == roff[i]) break; /* found */
408: umaccp = (i == NB) ? getblk(fp->b) : i; }
409:
410: #ifndef tso
411: return (int)rbuf.rnt[umaccp][fp->o];
412: #else
413: return (((int)rbuf.rnt[umaccp][fp->o]) & 0177777);
414: #endif
415: }
416: getblk(blk)
417: filep blk; /* find a place in the cache and get a block */
418: {
419: register int i;
420: #ifdef INCORE
421: register int j;
422: register tint *bp;
423: #endif
424:
425: i = (!rmaccp) ? NB-1 : rmaccp-1;
426: if (!macbcnt || (!(umaccp == i))) {
427: i = rmaccp;
428: rmaccp = (rmaccp + 1) % NB; }
429: macbcnt++;
430: #ifndef INCORE
431: lseek(ibf, (long)boff(blk) * sizeof(tint), 0);
432: if (read(ibf, rbuf.rp[i], BLK * sizeof(tint)) == 0) {
433: prstr("Macro read failed\n");
434: ferrex(); }
435: #else
436: bp = memblist[blk];
437: for (j=0; j<BLK; j++)
438: rbuf.rnt[i][j] = *bp++; /* get buffer */
439: #endif
440: roff[i] = blk;
441: return i;
442: }
443: errbsa()
444: {
445: prstr("Bad storage allocation\n");
446: done2(-5);
447: }
448: popi(){
449: register struct s *p;
450:
451: if(frame == stk)return(0);
452: if(strflg)strflg--;
453: #ifdef INCORE
454: free(nxf);
455: #endif
456: p = nxf = frame;
457: p->nargs = 0;
458: frame = p->pframe;
459: cptmpfaddr(ip,p->pip);
460: macbcnt = p->macbcnt;
461: pendt = p->ppendt;
462: if (tch[0] = p->pCH0) cstk[CH0] = tch;
463: cstkl = p->pcstkl;
464: cstk[RP] = p->pRP;
465: cstk[AP] = p->pAP;
466: cstk[CP] = p->pCP;
467: #ifdef INCORE
468: if ((argstrp > 0) && (argsp)) free(argsp); /* args */
469: argsp = argstrs[--argstrp];
470: #endif
471: maclev--;
472: return(p->pch);
473: }
474: pushi(newip)
475: filep newip;
476: {
477: register struct s *p;
478: #ifndef INCORE
479: extern char *setbrk();
480: #endif
481:
482: p = nxf;
483: #ifndef INCORE
484: if((enda - sizeof(struct s)) < (char *)nxf)setbrk(DELTA);
485: #else
486: if (argstrp < NMACS)
487: argstrs[argstrp++] = argsp; /* save latest */
488: else {
489: prstr("too many macro calls");
490: exit(1); }
491: argsp = sstrp; /* new args pointer */
492: sstrp = (int *)0;
493: #endif
494: p->pframe = frame;
495: cptmpfaddr(p->pip,ip);
496: p->macbcnt = macbcnt;
497: p->ppendt = pendt;
498: p->pCH0 = tch[0];
499: p->pch = ch;
500: p->pcstkl = cstkl;
501: p->pRP = cstk[RP];
502: p->pAP = cstk[AP];
503: p->pCP = cstk[CP];
504: cstkl = pendt = ch = 0;
505: cstk[RP] = cstk[AP] = cstk[CP] = (int *) 0;
506: frame = nxf;
507: #ifndef INCORE
508: if(nxf->nargs == 0) nxf += 1;
509: else nxf = (struct s *)argtop;
510: #else
511: if ((nxf = (struct s *)malloc(sizeof(struct s))) == NULL) {
512: prstr("out of memory for macro call");
513: exit(1); }
514: #endif
515: maclev++;
516: macbcnt = 0;
517: ip.o = 0;
518: return(ip.b = newip);
519: }
520:
521: #ifndef INCORE
522: char *setbrk(x)
523: int x;
524: {
525: #define ALIGN(addr,grain) ((addr+sizeof(grain)-1) & ~(sizeof(grain)-1))
526: register char *i;
527: char *sbrk();
528:
529: x = ALIGN(x, long);
530:
531: if((i = sbrk(x)) == (char *)-1){
532: prstrfl("Core limit reached.\n");
533: edone(0100); }
534: else enda = i;
535:
536: return((char *)ALIGN((int)i, long));
537: }
538: #endif
539: getsn(){
540: register i;
541:
542: if((i=getach()) == 0)return(0);
543: if(i == '(')return(getrq());
544: else return(i);
545: }
546: setstr(){
547: register i;
548:
549: lgf++;
550: if(((i=getsn()) == 0) ||
551: ((i=frmname(i)) == -1) ||
552: !(nametab[i].ename & MMASK))
553: lgf--;
554: else {
555: #ifndef INCORE
556: if((enda-sizeof(int)) <= (char *)nxf)setbrk(DELTA);
557: #endif
558: nxf->nargs = 0;
559: strflg++;
560: lgf--;
561: pushi((filep)nametab[i].vv.val);
562: }
563: }
564: collect()
565: {
566: register i;
567: register int *strp;
568: int *lim;
569: int quote;
570: struct s *savnxf;
571: union {
572: int **dbl;
573: int *pt;
574: } argppend;
575: #ifdef INCORE
576: int *hsstrp;
577: #endif
578:
579: copyf++;
580: nxf->nargs = 0;
581: if(skip())goto rtn;
582: strflg = 0;
583: savnxf = nxf;
584: #ifndef INCORE
585: lim = (int *)(nxf = savnxf + sizeof(struct s));
586: if((argppend.dbl =
587: (argpp=(int **)savnxf+(sizeof(struct s)/sizeof(int **)))
588: +(sizeof(struct s)-1)) > (int **)enda)setbrk(DELTA);
589: #else
590: if ((argpp = (int **)malloc(MARGL*sizeof(int))) == NULL) {
591: prstr("out of memory for macro call");
592: exit(1); }
593: hsstrp = (int *)argpp;
594: argppend.pt = hsstrp + sizeof(struct s) - 1;
595: lim = hsstrp + (MARGL*sizeof(int)); /* end of buf */
596: #endif
597: strp = argppend.pt;
598: for(i=8; i>=0; i--)argpp[i] = 0;
599: while((argpp != argppend.dbl) && (!skip())){
600: *argpp++ = strp;
601: quote = 0;
602: ch = getch();
603: if (ch_CMASK == '"') {
604: ch = 0;
605: quote++; }
606: while(1){
607: i = getch();
608: if( nlflg ||
609: ((!quote) && (ch_CMASK == ' ')))break;
610: if(quote && (ch_CMASK == '"') &&
611: ((i = getch()) && (ch_CMASK != '"'))) {
612: ch = i;
613: break;
614: }
615: *strp++ = i;
616: if(strflg && (strp >= lim)){
617: prstrfl("Macro argument too long.\n");
618: copyf--;
619: edone(004);
620: }
621: #ifndef INCORE
622: if((enda-(2*sizeof(int))) <= (char *)strp)setbrk(DELTA);
623: #endif
624: }
625: *strp++ = 0;
626: }
627: nxf = savnxf;
628: #ifndef INCORE
629: nxf->nargs = argpp -(int **)(nxf + 1);
630: #else
631: sstrp = hsstrp;
632: nxf->nargs = (int *)argpp - sstrp;
633: #endif
634: argtop = strp;
635: rtn:
636: copyf--;
637: }
638: caseda(){
639: app++;
640: casedi();
641: }
642: casedi(){
643: register i, j;
644: register *k;
645:
646: lgf++;
647: if(skip() || ((i=getrq()) == 0)){
648: if(dilev > 0){
649: wbt(0);
650: v_dn = dip->dnl;
651: v_dl = dip->maxl;
652: dip = &d[--dilev];
653: cptmpfaddr(offset,dip->op);
654: }
655: goto rtn;
656: }
657: if(++dilev == NDI){
658: --dilev;
659: prstr("Cannot divert.\n");
660: edone(02);
661: }
662: if (dilev > 1) wbt(0);
663: diflg++;
664: dip = &d[dilev];
665: dip->op.b = finds(i);
666: dip->op.o = offset.o;
667: dip->curd = i;
668: drmname(oldmn);
669: k = (int *)&dip->dnl;
670: for(j=0; j<10; j++)k[j] = 0; /*not op and curd*/
671: rtn:
672: app = 0;
673: diflg = 0;
674: }
675: casedt(){
676: lgf++;
677: dip->dimac = dip->ditrap = dip->ditf = 0;
678: skip();
679: dip->ditrap = vnumb((int *)0);
680: if(nonumb)return;
681: skip();
682: dip->dimac = getrq();
683: }
684: casetl(){
685: register i, j;
686: int w1, w2, w3, delim;
687: struct tmpfaddr begin;
688: static struct tmpfaddr null = {0,0};
689: extern width(), pchar();
690:
691: dip->nls = 0;
692: skip();
693: if (dilev > 0) wbfl();
694: if((offset.b = begin.b = alloc()) == 0)return;
695: offset.o = begin.o = 0;
696: if((delim = getch()) & MOT){
697: ch = delim;
698: delim = '\'';
699: }else delim = ch_CMASK;
700: if(!nlflg)
701: while(((i = getch()) & CMASK) != '\n'){
702: if(ch_CMASK == delim)i = IMP;
703: wbf(i);
704: }
705: wbf(IMP);wbf(IMP);wbt(0);
706:
707: w1 = hseg(width,&begin);
708: w2 = hseg(width,&null);
709: w3 = hseg(width,&null);
710: cptmpfaddr(offset,dip->op);
711: #ifdef NROFF
712: if(!offset.b)horiz(po);
713: #endif
714: hseg(pchar,&begin);
715: if(w2 || w3)horiz(j=quant((lt - w2)/2-w1,HOR));
716: hseg(pchar,&null);
717: if(w3){
718: horiz(lt-w1-w2-w3-j);
719: hseg(pchar,&null);
720: }
721: newline(0);
722: if(dilev > 0) {if(dip->dnl > dip->hnl)dip->hnl = dip->dnl;}
723: else{if(v_nl > dip->hnl)dip->hnl = v_nl;}
724: ffree(begin.b);
725: }
726: casepc(){
727: pagech = chget(IMP);
728: }
729: hseg(f,p)
730: int (*f)();
731: struct tmpfaddr *p;
732: {
733: register acc, i;
734: static struct tmpfaddr q;
735: int smacbcnt;
736:
737: acc = 0;
738: if(p->b) { q.o = p->o; q.b = p->b; }
739: smacbcnt = macbcnt;
740: macbcnt = 0;
741: while(1){
742: i = rbf0(&q);
743: incoff(q);
744: if(!i || (i == IMP)) {
745: macbcnt = smacbcnt;
746: return (acc); };
747: if((i & CMASK) == pagech){
748: nrbits = i & ~CMASK;
749: nform = fmt[findr('%')];
750: acc += fnumb(v_pn,f);
751: }else acc += (*f)(i);
752: }
753: }
754: casepm(){
755: #ifndef NDIAGS
756: register i, k;
757: register char *p;
758: int xx, cnt, kk, tot;
759: filep j;
760: char *kvt();
761: char pmline[10];
762:
763: kk = cnt = 0;
764: tot = !skip();
765: for(i = 0; i<NM; i++){
766: if (((xx = nametab[i].ename) == -1) || (!(xx & MMASK))) continue;
767: p = pmline;
768: j = (filep)nametab[i].vv.val;
769: k = 1;
770: while((j = blist[j]) != (filep)-1) k++;
771: cnt++;
772: kk += k;
773: if(!tot){
774: *p++ = xx & 0177;
775: if(!(*p++ = (xx >> BYTE) & 0177))*(p-1) = ' ';
776: *p++ = ' ';
777: kvt(k,p);
778: aprstr(pmline);
779: }
780: }
781: if(tot || (cnt > 1)){
782: kvt(kk,pmline);
783: aprstr(pmline);
784: }
785: }
786: char *kvt(k,p)
787: int k;
788: char *p;
789: {
790: if(k>=100)*p++ = k/100 + '0';
791: if(k>=10)*p++ = (k%100)/10 + '0';
792: *p++ = k%10 + '0';
793: *p++ = '\n';
794: *p = 0;
795: #endif
796: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.