|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)n3.c 4.4 6/25/87";
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: x += sizeof(int) - 1;
457: x &= ~(sizeof(int) - 1);
458: if ((u_int)(i = sbrk(x)) == -1) {
459: prstrfl("Core limit reached.\n");
460: edone(0100);
461: } else {
462: enda = i + x;
463: }
464: return(i);
465: }
466:
467:
468: getsn()
469: {
470: register i;
471:
472: if ((i = getach()) == 0)
473: return(0);
474: if (i == '(')
475: return(getrq());
476: else
477: return(i);
478: }
479:
480:
481: setstr()
482: {
483: register i;
484:
485: lgf++;
486: if ( ((i = getsn()) == 0)
487: || ((i = findmn(i)) == -1)
488: || !(contab[i].rq & MMASK)) {
489: lgf--;
490: return(0);
491: } else {
492: SPACETEST(nxf, sizeof(struct s));
493: nxf->nargs = 0;
494: strflg++;
495: lgf--;
496: return(pushi(((filep)contab[i].x.mx)<<BLKBITS));
497: }
498: }
499:
500: typedef int tchar;
501: #define cbits(x) ((x) & CMASK)
502:
503: collect()
504: {
505: register j;
506: tchar i;
507: register tchar *strp;
508: tchar * lim;
509: tchar * *argpp, **argppend;
510: int quote;
511: struct s *savnxf;
512:
513: copyf++;
514: nxf->nargs = 0;
515: savnxf = nxf;
516: if (skip())
517: goto rtn;
518:
519: {
520: char *memp;
521: memp = (char *)savnxf;
522: /*
523: * 1 s structure for the macro descriptor
524: * APERMAC tchar *'s for pointers into the strings
525: * space for the tchar's themselves
526: */
527: memp += sizeof(struct s);
528: /*
529: * CPERMAC (the total # of characters for ALL arguments)
530: * to a macros, has been carefully chosen
531: * so that the distance between stack frames is < DELTA
532: */
533: #define CPERMAC 200
534: #define APERMAC 9
535: memp += APERMAC * sizeof(tchar *);
536: memp += CPERMAC * sizeof(tchar);
537: nxf = (struct s*)memp;
538: }
539: lim = (tchar *)nxf;
540: argpp = (tchar **)(savnxf + 1);
541: argppend = &argpp[APERMAC];
542: SPACETEST(argppend, sizeof(tchar *));
543: strp = (tchar *)argppend;
544: /*
545: * Zero out all the string pointers before filling them in.
546: */
547: for (j = 0; j < APERMAC; j++){
548: argpp[j] = (tchar *)0;
549: }
550: #if 0
551: fprintf(stderr, "savnxf=0x%x,nxf=0x%x,argpp=0x%x,strp=argppend=0x%x,lim=0x%x,enda=0x%x\n",
552: savnxf, nxf, argpp, strp, lim, enda);
553: #endif 0
554: strflg = 0;
555: while ((argpp != argppend) && (!skip())) {
556: *argpp++ = strp;
557: quote = 0;
558: if (cbits(i = getch()) == '"')
559: quote++;
560: else
561: ch = i;
562: while (1) {
563: i = getch();
564: if ( nlflg || (!quote && cbits(i) == ' '))
565: break;
566: if ( quote
567: && (cbits(i) == '"')
568: && (cbits(i = getch()) != '"')) {
569: ch = i;
570: break;
571: }
572: *strp++ = i;
573: if (strflg && (strp >= lim)) {
574: #if 0
575: fprintf(stderr, "strp=0x%x, lim = 0x%x\n",
576: strp, lim);
577: #endif 0
578: prstrfl("Macro argument too long.\n");
579: copyf--;
580: edone(004);
581: }
582: SPACETEST(strp, 3 * sizeof(tchar));
583: }
584: *strp++ = 0;
585: }
586: nxf = savnxf;
587: nxf->nargs = argpp - (tchar **)(savnxf + 1);
588: argtop = strp;
589: rtn:
590: copyf--;
591: }
592:
593:
594: seta()
595: {
596: register i;
597:
598: if(((i = (getch() & CMASK) - '0') > 0) &&
599: (i <= APERMAC) && (i <= frame->nargs))ap = *((int **)frame + i-1 + (sizeof(struct s)/sizeof(int **)));
600: }
601: caseda(){
602: app++;
603: casedi();
604: }
605: casedi(){
606: register i, j;
607: register *k;
608:
609: lgf++;
610: if(skip() || ((i=getrq()) == 0)){
611: if(dip != d)wbt(0);
612: if(dilev > 0){
613: v.dn = dip->dnl;
614: v.dl = dip->maxl;
615: dip = &d[--dilev];
616: offset = dip->op;
617: }
618: goto rtn;
619: }
620: if(++dilev == NDI){
621: --dilev;
622: prstr("Cannot divert.\n");
623: edone(02);
624: }
625: if(dip != d)wbt(0);
626: diflg++;
627: dip = &d[dilev];
628: dip->op = finds(i);
629: dip->curd = i;
630: clrmn(oldmn);
631: k = (int *)&dip->dnl;
632: for(j=0; j<10; j++)k[j] = 0; /*not op and curd*/
633: rtn:
634: app = 0;
635: diflg = 0;
636: }
637: casedt(){
638: lgf++;
639: dip->dimac = dip->ditrap = dip->ditf = 0;
640: skip();
641: dip->ditrap = vnumb((int *)0);
642: if(nonumb)return;
643: skip();
644: dip->dimac = getrq();
645: }
646: casetl(){
647: register i, j;
648: int w1, w2, w3, delim;
649: filep begin;
650: extern width(), pchar();
651:
652: dip->nls = 0;
653: skip();
654: if(dip != d)wbfl();
655: if((offset = begin = alloc()) == 0)return;
656: if((delim = getch()) & MOT){
657: ch = delim;
658: delim = '\'';
659: }else delim &= CMASK;
660: if(!nlflg)
661: while(((i = getch()) & CMASK) != '\n'){
662: if((i & CMASK) == delim)i = IMP;
663: wbf(i);
664: }
665: wbf(IMP);wbf(IMP);wbt(0);
666:
667: w1 = hseg(width,begin);
668: w2 = hseg(width,(filep)0);
669: w3 = hseg(width,(filep)0);
670: offset = dip->op;
671: #ifdef NROFF
672: if(!offset)horiz(po);
673: #endif
674: hseg(pchar,begin);
675: if(w2 || w3)horiz(j=quant((lt - w2)/2-w1,HOR));
676: hseg(pchar,(filep)0);
677: if(w3){
678: horiz(lt-w1-w2-w3-j);
679: hseg(pchar,(filep)0);
680: }
681: newline(0);
682: if(dip != d){if(dip->dnl > dip->hnl)dip->hnl = dip->dnl;}
683: else{if(v.nl > dip->hnl)dip->hnl = v.nl;}
684: ffree(begin);
685: }
686: casepc(){
687: pagech = chget(IMP);
688: }
689: hseg(f,p)
690: int (*f)();
691: filep p;
692: {
693: register acc, i;
694: static filep q;
695:
696: acc = 0;
697: if(p)q = p;
698: while(1){
699: i = rbf0(q);
700: q = incoff(q);
701: if(!i || (i == IMP))return(acc);
702: if((i & CMASK) == pagech){
703: nrbits = i & ~CMASK;
704: nform = fmt[findr('%')];
705: acc += fnumb(v.pn,f);
706: }else acc += (*f)(i);
707: }
708: }
709: casepm(){
710: register i, k;
711: register char *p;
712: int xx, cnt, kk, tot;
713: filep j;
714: char *kvt();
715: char pmline[10];
716:
717: kk = cnt = 0;
718: tot = !skip();
719: for(i = 0; i<NM; i++){
720: if(!((xx = contab[i].rq) & MMASK))continue;
721: p = pmline;
722: j = (((filep)contab[i].x.mx)<<BLKBITS);
723: k = 1;
724: while((j = blist[blisti(j)]) != -1){k++; j <<= BLKBITS;}
725: cnt++;
726: kk += k;
727: if(!tot){
728: *p++ = xx & 0177;
729: if(!(*p++ = (xx >> BYTE) & 0177))*(p-1) = ' ';
730: *p++ = ' ';
731: kvt(k,p);
732: prstr(pmline);
733: }
734: }
735: if(tot || (cnt > 1)){
736: kvt(kk,pmline);
737: prstr(pmline);
738: }
739: }
740: char *kvt(k,p)
741: int k;
742: char *p;
743: {
744: if(k>=100)*p++ = k/100 + '0';
745: if(k>=10)*p++ = (k%100)/10 + '0';
746: *p++ = k%10 + '0';
747: *p++ = '\n';
748: *p = 0;
749: return(p);
750: }
751: dummy(){}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.