|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)n3.c 4.2 10/28/82";
3: #endif lint
4:
5: #include "tdef.h"
6: extern
7: #include "d.h"
8: extern
9: #include "v.h"
10: #ifdef NROFF
11: extern
12: #include "tw.h"
13: #endif
14: #include "sdef.h"
15:
16: /*
17: troff3.c
18:
19: macro and string routines, storage allocation
20: */
21:
22: unsigned blist[NBLIST];
23: extern struct s *frame, *stk, *nxf;
24: extern filep ip;
25: extern filep offset;
26: extern filep nextb;
27: extern char *enda;
28:
29: extern int ch;
30: extern int ibf;
31: extern int lgf;
32: extern int copyf;
33: extern int ch0;
34: extern int app;
35: extern int ds;
36: extern int nlflg;
37: extern int *argtop;
38: extern int *ap;
39: extern int nchar;
40: extern int pendt;
41: extern int rchar;
42: extern int dilev;
43: extern int nonumb;
44: extern int lt;
45: extern int nrbits;
46: extern int nform;
47: extern int fmt[];
48: extern int oldmn;
49: extern int newmn;
50: extern int macerr;
51: extern filep apptr;
52: extern int diflg;
53: extern filep woff;
54: extern filep roff;
55: extern int wbfi;
56: extern int po;
57: extern int *cp;
58: extern int xxx;
59: int pagech = '%';
60: int strflg;
61: extern struct contab {
62: int rq;
63: union {
64: int (*f)();
65: unsigned mx;
66: }x;
67: }contab[NM];
68: #ifndef VMUNIX
69: int wbuf[BLK];
70: int rbuf[BLK];
71: #else
72: int *wbuf;
73: int *rbuf;
74: int Buf[NBLIST*BLK + NEV*EVS];
75: #endif
76:
77: caseig(){
78: register i;
79:
80: offset = 0;
81: if((i = copyb()) != '.')control(i,1);
82: }
83: casern(){
84: register i,j;
85:
86: lgf++;
87: skip();
88: if(((i=getrq())==0) || ((oldmn=findmn(i)) < 0))return;
89: skip();
90: clrmn(findmn(j=getrq()));
91: if(j)contab[oldmn].rq = (contab[oldmn].rq & MMASK) | j;
92: }
93: caserm(){
94: lgf++;
95: while(!skip()){
96: clrmn(findmn(getrq()));
97: }
98: }
99: caseas(){
100: app++;
101: caseds();
102: }
103: caseds(){
104: ds++;
105: casede();
106: }
107: caseam(){
108: app++;
109: casede();
110: }
111: casede(){
112: register i, req;
113: register filep savoff;
114: extern filep finds();
115:
116: if(dip != d)wbfl();
117: req = '.';
118: lgf++;
119: skip();
120: if((i=getrq())==0)goto de1;
121: if((offset=finds(i)) == 0)goto de1;
122: if(ds)copys();
123: else req = copyb();
124: wbfl();
125: clrmn(oldmn);
126: if(newmn)contab[newmn].rq = i | MMASK;
127: if(apptr){
128: savoff = offset;
129: offset = apptr;
130: wbt(IMP);
131: offset = savoff;
132: }
133: offset = dip->op;
134: if(req != '.')control(req,1);
135: de1:
136: ds = app = 0;
137: return;
138: }
139: findmn(i)
140: int i;
141: {
142: register j;
143:
144: for(j=0;j<NM;j++){
145: if(i == (contab[j].rq & ~MMASK))break;
146: }
147: if(j==NM)j = -1;
148: return(j);
149: }
150: clrmn(i)
151: int i;
152: {
153: extern filep boff();
154: if(i >= 0){
155: if(contab[i].rq & MMASK)ffree(((filep)contab[i].x.mx)<<BLKBITS);
156: contab[i].rq = 0;
157: contab[i].x.mx = 0;
158: }
159: }
160: filep finds(mn)
161: int mn;
162: {
163: register i;
164: extern filep boff();
165: register filep savip;
166: extern filep alloc();
167: extern filep incoff();
168:
169: oldmn = findmn(mn);
170: newmn = 0;
171: apptr = (filep)0;
172: if(app && (oldmn >= 0) && (contab[oldmn].rq & MMASK)){
173: savip = ip;
174: ip = (((filep)contab[oldmn].x.mx)<<BLKBITS);
175: oldmn = -1;
176: while((i=rbf()) != 0);
177: apptr = ip;
178: if(!diflg)ip = incoff(ip);
179: nextb = ip;
180: ip = savip;
181: }else{
182: for(i=0;i<NM;i++){
183: if(contab[i].rq == 0)break;
184: }
185: if((i==NM) ||
186: (nextb = alloc()) == 0){
187: app = 0;
188: if(macerr++ > 1)done2(02);
189: prstr("Too many string/macro names.\n");
190: edone(04);
191: return(offset = 0);
192: }
193: contab[i].x.mx = (unsigned)(nextb>>BLKBITS);
194: if(!diflg){
195: newmn = i;
196: if(oldmn == -1)contab[i].rq = -1;
197: }else{
198: contab[i].rq = mn | MMASK;
199: }
200: }
201:
202: app = 0;
203: return(offset = nextb);
204: }
205: skip(){
206: register i;
207:
208: while(((i=getch()) & CMASK) == ' ');
209: ch=i;
210: return(nlflg);
211: }
212: copyb()
213: {
214: register i, j, k;
215: int ii, req, state;
216: filep savoff;
217:
218: if(skip() || !(j=getrq()))j = '.';
219: req = j;
220: k = j>>BYTE;
221: j &= BMASK;
222: copyf++;
223: flushi();
224: nlflg = 0;
225: state = 1;
226: while(1){
227: i = (ii = getch()) & CMASK;
228: if(state == 3){
229: if(i == k)break;
230: if(!k){
231: ch = ii;
232: i = getach();
233: ch = ii;
234: if(!i)break;
235: }
236: state = 0;
237: goto c0;
238: }
239: if(i == '\n'){
240: state = 1;
241: nlflg = 0;
242: goto c0;
243: }
244: if((state == 1) && (i == '.')){
245: state++;
246: savoff = offset;
247: goto c0;
248: }
249: if((state == 2) && (i == j)){
250: state++;
251: goto c0;
252: }
253: state = 0;
254: c0:
255: if(offset)wbf(ii);
256: }
257: if(offset){
258: wbfl();
259: offset = savoff;
260: wbt(0);
261: }
262: copyf--;
263: return(req);
264: }
265: copys()
266: {
267: register i;
268:
269: copyf++;
270: if(skip())goto c0;
271: if(((i=getch()) & CMASK) != '"')wbf(i);
272: while(((i=getch()) & CMASK) != '\n')wbf(i);
273: c0:
274: wbt(0);
275: copyf--;
276: }
277: filep alloc()
278: {
279: register i;
280: extern filep boff();
281: filep j;
282:
283: for(i=0;i<NBLIST;i++){
284: if(blist[i] == 0)break;
285: }
286: if(i==NBLIST){
287: j = 0;
288: }else{
289: blist[i] = -1;
290: if((j = boff(i)) < NEV*EVS)j = 0;
291: }
292: return(nextb = j);
293: }
294: ffree(i)
295: filep i;
296: {
297: register j;
298:
299: while((blist[j = blisti(i)]) != -1){
300: i = ((filep)blist[j])<<BLKBITS;
301: blist[j] = 0;
302: }
303: blist[j] = 0;
304: }
305: filep boff(i)
306: int i;
307: {
308: return(((filep)i)*BLK + NEV*EVS);
309: }
310: wbt(i)
311: int i;
312: {
313: wbf(i);
314: wbfl();
315: }
316: wbf(i)
317: int i;
318: {
319: register j;
320:
321: if(!offset)return;
322: if(!woff){
323: woff = offset;
324: #ifdef VMUNIX
325: wbuf = &Buf[woff];
326: #endif
327: wbfi = 0;
328: }
329: wbuf[wbfi++] = i;
330: if(!((++offset) & (BLK-1))){
331: wbfl();
332: if(blist[j = blisti(--offset)] == -1){
333: if(alloc() == 0){
334: prstr("Out of temp file space.\n");
335: done2(01);
336: }
337: blist[j] = (unsigned)(nextb>>BLKBITS);
338: }
339: offset = ((filep)blist[j])<<BLKBITS;
340: }
341: if(wbfi >= BLK)wbfl();
342: }
343: wbfl(){
344: if(woff == 0)return;
345: #ifndef VMUNIX
346: lseek(ibf, ((long)woff) * sizeof(int), 0);
347: write(ibf, (char *)wbuf, wbfi * sizeof(int));
348: #endif
349: if((woff & (~(BLK-1))) == (roff & (~(BLK-1))))roff = -1;
350: woff = 0;
351: }
352: blisti(i)
353: filep i;
354: {
355: return((i-NEV*EVS)/(BLK));
356: }
357: rbf(){
358: register i;
359: extern filep incoff();
360:
361: if((i=rbf0(ip)) == 0){
362: if(!app)i = popi();
363: }else{
364: ip = incoff(ip);
365: }
366: return(i);
367: }
368: rbf0(p)
369: filep p;
370: {
371: register filep i;
372:
373: if((i = (p & (~(BLK-1)))) != roff){
374: roff = i;
375: #ifndef VMUNIX
376: lseek(ibf, ((long)roff) * sizeof(int), 0);
377: if(read(ibf, (char *)rbuf, BLK * sizeof(int)) == 0)return(0);
378: #else
379: rbuf = &Buf[roff];
380: #endif
381: }
382: return(rbuf[p & (BLK-1)]);
383: }
384: filep incoff(p)
385: filep p;
386: {
387: register i;
388: register filep j;
389: if(!((j = (++p)) & (BLK-1))){
390: if((i = blist[blisti(--p)]) == -1){
391: prstr("Bad storage allocation.\n");
392: done2(-5);
393: }
394: j = ((filep)i)<<BLKBITS;
395: }
396: return(j);
397: }
398: popi(){
399: register struct s *p;
400:
401: if(frame == stk)return(0);
402: if(strflg)strflg--;
403: p = nxf = frame;
404: p->nargs = 0;
405: frame = p->pframe;
406: ip = p->pip;
407: nchar = p->pnchar;
408: rchar = p->prchar;
409: pendt = p->ppendt;
410: ap = p->pap;
411: cp = p->pcp;
412: ch0 = p->pch0;
413: return(p->pch);
414: }
415:
416: /*
417: * test that the end of the allocation is above a certain location
418: * in memory
419: */
420: #define SPACETEST(base, size) while ((enda - (size)) <= (char *)(base)){setbrk(DELTA);}
421:
422: pushi(newip)
423: filep newip;
424: {
425: register struct s *p;
426: extern char *setbrk();
427:
428: SPACETEST(nxf, sizeof(struct s));
429: p = nxf;
430: p->pframe = frame;
431: p->pip = ip;
432: p->pnchar = nchar;
433: p->prchar = rchar;
434: p->ppendt = pendt;
435: p->pap = ap;
436: p->pcp = cp;
437: p->pch0 = ch0;
438: p->pch = ch;
439: cp = ap = 0;
440: nchar = rchar = pendt = ch0 = ch = 0;
441: frame = nxf;
442: if (nxf->nargs == 0)
443: nxf += 1;
444: else
445: nxf = (struct s *)argtop;
446: return(ip = newip);
447: }
448:
449:
450: char *setbrk(x)
451: int x;
452: {
453: register char *i;
454: char *sbrk();
455:
456: /* ought to be rounded up by sizeof(int) */
457: if (x % 2 == 1)
458: x++;
459: if ( (i = sbrk(x)) >= (char *)MAXPTR) {
460: prstrfl("Core limit reached.\n");
461: edone(0100);
462: } else {
463: enda = i + x;
464: }
465: return(i);
466: }
467:
468:
469: getsn()
470: {
471: register i;
472:
473: if ((i = getach()) == 0)
474: return(0);
475: if (i == '(')
476: return(getrq());
477: else
478: return(i);
479: }
480:
481:
482: setstr()
483: {
484: register i;
485:
486: lgf++;
487: if ( ((i = getsn()) == 0)
488: || ((i = findmn(i)) == -1)
489: || !(contab[i].rq & MMASK)) {
490: lgf--;
491: return(0);
492: } else {
493: SPACETEST(nxf, sizeof(struct s));
494: nxf->nargs = 0;
495: strflg++;
496: lgf--;
497: return(pushi(((filep)contab[i].x.mx)<<BLKBITS));
498: }
499: }
500:
501: typedef int tchar;
502: #define cbits(x) ((x) & CMASK)
503:
504: collect()
505: {
506: register j;
507: tchar i;
508: register tchar *strp;
509: tchar * lim;
510: tchar * *argpp, **argppend;
511: int quote;
512: struct s *savnxf;
513:
514: copyf++;
515: nxf->nargs = 0;
516: savnxf = nxf;
517: if (skip())
518: goto rtn;
519:
520: {
521: char *memp;
522: memp = (char *)savnxf;
523: /*
524: * 1 s structure for the macro descriptor
525: * APERMAC tchar *'s for pointers into the strings
526: * space for the tchar's themselves
527: */
528: memp += sizeof(struct s);
529: /*
530: * CPERMAC (the total # of characters for ALL arguments)
531: * to a macros, has been carefully chosen
532: * so that the distance between stack frames is < DELTA
533: */
534: #define CPERMAC 200
535: #define APERMAC 9
536: memp += APERMAC * sizeof(tchar *);
537: memp += CPERMAC * sizeof(tchar);
538: nxf = (struct s*)memp;
539: }
540: lim = (tchar *)nxf;
541: argpp = (tchar **)(savnxf + 1);
542: argppend = &argpp[APERMAC];
543: SPACETEST(argppend, sizeof(tchar *));
544: strp = (tchar *)argppend;
545: /*
546: * Zero out all the string pointers before filling them in.
547: */
548: for (j = 0; j < APERMAC; j++){
549: argpp[j] = (tchar *)0;
550: }
551: #if 0
552: fprintf(stderr, "savnxf=0x%x,nxf=0x%x,argpp=0x%x,strp=argppend=0x%x,lim=0x%x,enda=0x%x\n",
553: savnxf, nxf, argpp, strp, lim, enda);
554: #endif 0
555: strflg = 0;
556: while ((argpp != argppend) && (!skip())) {
557: *argpp++ = strp;
558: quote = 0;
559: if (cbits(i = getch()) == '"')
560: quote++;
561: else
562: ch = i;
563: while (1) {
564: i = getch();
565: if ( nlflg || (!quote && cbits(i) == ' '))
566: break;
567: if ( quote
568: && (cbits(i) == '"')
569: && (cbits(i = getch()) != '"')) {
570: ch = i;
571: break;
572: }
573: *strp++ = i;
574: if (strflg && (strp >= lim)) {
575: #if 0
576: fprintf(stderr, "strp=0x%x, lim = 0x%x\n",
577: strp, lim);
578: #endif 0
579: prstrfl("Macro argument too long.\n");
580: copyf--;
581: edone(004);
582: }
583: SPACETEST(strp, 3 * sizeof(tchar));
584: }
585: *strp++ = 0;
586: }
587: nxf = savnxf;
588: nxf->nargs = argpp - (tchar **)(savnxf + 1);
589: argtop = strp;
590: rtn:
591: copyf--;
592: }
593:
594:
595: seta()
596: {
597: register i;
598:
599: if(((i = (getch() & CMASK) - '0') > 0) &&
600: (i <= APERMAC) && (i <= frame->nargs))ap = *((int **)frame + i-1 + (sizeof(struct s)/sizeof(int **)));
601: }
602: caseda(){
603: app++;
604: casedi();
605: }
606: casedi(){
607: register i, j;
608: register *k;
609:
610: lgf++;
611: if(skip() || ((i=getrq()) == 0)){
612: if(dip != d)wbt(0);
613: if(dilev > 0){
614: v.dn = dip->dnl;
615: v.dl = dip->maxl;
616: dip = &d[--dilev];
617: offset = dip->op;
618: }
619: goto rtn;
620: }
621: if(++dilev == NDI){
622: --dilev;
623: prstr("Cannot divert.\n");
624: edone(02);
625: }
626: if(dip != d)wbt(0);
627: diflg++;
628: dip = &d[dilev];
629: dip->op = finds(i);
630: dip->curd = i;
631: clrmn(oldmn);
632: k = (int *)&dip->dnl;
633: for(j=0; j<10; j++)k[j] = 0; /*not op and curd*/
634: rtn:
635: app = 0;
636: diflg = 0;
637: }
638: casedt(){
639: lgf++;
640: dip->dimac = dip->ditrap = dip->ditf = 0;
641: skip();
642: dip->ditrap = vnumb((int *)0);
643: if(nonumb)return;
644: skip();
645: dip->dimac = getrq();
646: }
647: casetl(){
648: register i, j;
649: int w1, w2, w3, delim;
650: filep begin;
651: extern width(), pchar();
652:
653: dip->nls = 0;
654: skip();
655: if(dip != d)wbfl();
656: if((offset = begin = alloc()) == 0)return;
657: if((delim = getch()) & MOT){
658: ch = delim;
659: delim = '\'';
660: }else delim &= CMASK;
661: if(!nlflg)
662: while(((i = getch()) & CMASK) != '\n'){
663: if((i & CMASK) == delim)i = IMP;
664: wbf(i);
665: }
666: wbf(IMP);wbf(IMP);wbt(0);
667:
668: w1 = hseg(width,begin);
669: w2 = hseg(width,(filep)0);
670: w3 = hseg(width,(filep)0);
671: offset = dip->op;
672: #ifdef NROFF
673: if(!offset)horiz(po);
674: #endif
675: hseg(pchar,begin);
676: if(w2 || w3)horiz(j=quant((lt - w2)/2-w1,HOR));
677: hseg(pchar,(filep)0);
678: if(w3){
679: horiz(lt-w1-w2-w3-j);
680: hseg(pchar,(filep)0);
681: }
682: newline(0);
683: if(dip != d){if(dip->dnl > dip->hnl)dip->hnl = dip->dnl;}
684: else{if(v.nl > dip->hnl)dip->hnl = v.nl;}
685: ffree(begin);
686: }
687: casepc(){
688: pagech = chget(IMP);
689: }
690: hseg(f,p)
691: int (*f)();
692: filep p;
693: {
694: register acc, i;
695: static filep q;
696:
697: acc = 0;
698: if(p)q = p;
699: while(1){
700: i = rbf0(q);
701: q = incoff(q);
702: if(!i || (i == IMP))return(acc);
703: if((i & CMASK) == pagech){
704: nrbits = i & ~CMASK;
705: nform = fmt[findr('%')];
706: acc += fnumb(v.pn,f);
707: }else acc += (*f)(i);
708: }
709: }
710: casepm(){
711: register i, k;
712: register char *p;
713: int xx, cnt, kk, tot;
714: filep j;
715: char *kvt();
716: char pmline[10];
717:
718: kk = cnt = 0;
719: tot = !skip();
720: for(i = 0; i<NM; i++){
721: if(!((xx = contab[i].rq) & MMASK))continue;
722: p = pmline;
723: j = (((filep)contab[i].x.mx)<<BLKBITS);
724: k = 1;
725: while((j = blist[blisti(j)]) != -1){k++; j <<= BLKBITS;}
726: cnt++;
727: kk += k;
728: if(!tot){
729: *p++ = xx & 0177;
730: if(!(*p++ = (xx >> BYTE) & 0177))*(p-1) = ' ';
731: *p++ = ' ';
732: kvt(k,p);
733: prstr(pmline);
734: }
735: }
736: if(tot || (cnt > 1)){
737: kvt(kk,pmline);
738: prstr(pmline);
739: }
740: }
741: char *kvt(k,p)
742: int k;
743: char *p;
744: {
745: if(k>=100)*p++ = k/100 + '0';
746: if(k>=10)*p++ = (k%100)/10 + '0';
747: *p++ = k%10 + '0';
748: *p++ = '\n';
749: *p = 0;
750: return(p);
751: }
752: dummy(){}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.