|
|
1.1 root 1: #include "stdio.h"
2: #include "signal.h"
3: #include "m4.h"
4:
5: #define match(c,s) (c==*s && (!s[1] || inpmatch(s+1)))
6:
7: char *xcalloc(), *mktemp();
8:
9:
10: main(argc,argv)
11: char **argv;
12: {
13: register t;
14:
15: #ifdef gcos
16: tempname = "m4.tempa";
17: #endif
18:
19: #ifdef unix
20: {
21: static sigs[] = {SIGHUP, SIGINT, SIGPIPE, 0};
22: for (t=0; sigs[t]; ++t)
23: if (signal(sigs[t], SIG_IGN) != SIG_IGN)
24: signal(sigs[t],catchsig);
25: }
26:
27: tempname = mktemp("/tmp/m4aXXXXX");
28: close(creat(tempname,0));
29: #endif
30:
31: procnam = argv[0];
32: getflags(&argc,&argv);
33: initalloc();
34:
35: setfname("-");
36: if (argc>1) {
37: --argc;
38: ++argv;
39: if (strcmp(argv[0],"-")) {
40: ifile[ifx] = xfopen(argv[0],"r");
41: setfname(argv[0]);
42: }
43: }
44:
45: for (;;) {
46: token[0] = t = getchr();
47: token[1] = EOS;
48:
49: if (t==EOF) {
50: if (ifx > 0) {
51: fclose(ifile[ifx]);
52: ipflr = ipstk[--ifx];
53: continue;
54: }
55:
56: getflags(&argc,&argv);
57:
58: if (argc<=1)
59: if (Wrapstr) {
60: pbstr(Wrapstr);
61: Wrapstr = NULL;
62: continue;
63: } else
64: break;
65:
66: --argc;
67: ++argv;
68:
69: if (ifile[ifx]!=stdin)
70: fclose(ifile[ifx]);
71:
72: if (*argv[0]=='-')
73: ifile[ifx] = stdin;
74: else
75: ifile[ifx] = xfopen(argv[0],"r");
76:
77: setfname(argv[0]);
78: continue;
79: }
80:
81: if (isalpha(t)) {
82: register char *tp = token+1;
83: register tlim = toksize;
84:
85: while (alphanum(*tp++=getchr()))
86: if (--tlim<=0)
87: error2("more than %d chars in word",
88: toksize);
89:
90: putbak(*--tp);
91: *tp = EOS;
92:
93: if (((struct nlist *)(*Ap=lookup(token)))->def) {
94: if (++Ap >= astklm) {
95: --Ap;
96: error2(astkof,stksize);
97: }
98:
99: if (Cp++==NULL)
100: Cp = callst;
101:
102: Cp->argp = Ap;
103: *Ap++ = op;
104: puttok(token);
105: stkchr(EOS);
106: t = getchr();
107: putbak(t);
108:
109: if (t!='(')
110: pbstr("()");
111: else /* try to fix arg count */
112: *Ap++ = op;
113:
114: Cp->plev = 0;
115: } else {
116: puttok(token);
117: }
118: } else if (match(t,lquote)) {
119: register qlev = 1;
120:
121: for (;;) {
122: token[0] = t = getchr();
123: token[1] = EOS;
124:
125: if (match(t,rquote)) {
126: if (--qlev > 0)
127: puttok(token);
128: else
129: break;
130: } else if (match(t,lquote)) {
131: ++qlev;
132: puttok(token);
133: } else {
134: if (t==EOF)
135: error("EOF in quote");
136:
137: putchr(t);
138: }
139: }
140: } else if (match(t,lcom)) {
141: puttok(token);
142:
143: for (;;) {
144: token[0] = t = getchr();
145: token[1] = EOS;
146:
147: if (match(t,rcom)) {
148: puttok(token);
149: break;
150: } else {
151: if (t==EOF)
152: error("EOF in comment");
153: putchr(t);
154: }
155: }
156: } else if (Cp==NULL) {
157: putchr(t);
158: } else if (t=='(') {
159: if (Cp->plev)
160: stkchr(t);
161: else {
162: /* skip white before arg */
163: while (isspace(t=getchr()))
164: ;
165:
166: putbak(t);
167: }
168:
169: ++Cp->plev;
170: } else if (t==')') {
171: --Cp->plev;
172:
173: if (Cp->plev==0) {
174: stkchr(EOS);
175: expand(Cp->argp,Ap-Cp->argp-1);
176: op = *Cp->argp;
177: Ap = Cp->argp-1;
178:
179: if (--Cp < callst)
180: Cp = NULL;
181: } else
182: stkchr(t);
183: } else if (t==',' && Cp->plev<=1) {
184: stkchr(EOS);
185: *Ap = op;
186:
187: if (++Ap >= astklm) {
188: --Ap;
189: error2(astkof,stksize);
190: }
191:
192: while (isspace(t=getchr()))
193: ;
194:
195: putbak(t);
196: } else
197: stkchr(t);
198: }
199:
200: if (Cp!=NULL)
201: error("EOF in argument list");
202:
203: delexit(OK);
204: }
205:
206: inpmatch(s)
207: register char *s;
208: {
209: register char *tp = token+1;
210:
211: while (*s) {
212: *tp = getchr();
213:
214: if (*tp++ != *s++) {
215: *tp = EOS;
216: pbstr(token+1);
217: return 0;
218: }
219: }
220:
221: *tp = EOS;
222: return token;
223: }
224:
225: getflags(xargc,xargv)
226: register int *xargc;
227: register char ***xargv;
228: {
229: while (*xargc > 1) {
230: register char *arg = (*xargv)[1];
231:
232: if (arg[0]!='-' || arg[1]==EOS)
233: break;
234:
235: switch (arg[1]) {
236: case 'B':
237: bufsize = atoi(&arg[2]);
238: break;
239: case 'D':
240: {
241: register char *t;
242: char *s[2];
243:
244: initalloc();
245:
246: for (t = s[0] = &arg[2]; *t; t++)
247: if (*t=='=') {
248: *t++ = EOS;
249: break;
250: }
251:
252: s[1] = t;
253: dodef(&s[-1],2);
254: break;
255: }
256: case 'H':
257: hshsize = atoi(&arg[2]);
258: break;
259: case 'S':
260: stksize = atoi(&arg[2]);
261: break;
262: case 'T':
263: toksize = atoi(&arg[2]);
264: break;
265: case 'U':
266: {
267: char *s[1];
268:
269: initalloc();
270: s[0] = &arg[2];
271: doundef(&s[-1],1);
272: break;
273: }
274: case 'e':
275: #ifdef unix
276: setbuf(stdout,NULL);
277: signal(SIGINT,SIG_IGN);
278: #endif
279: break;
280: case 's':
281: /* turn on line sync */
282: sflag = 1;
283: break;
284: default:
285: fprintf(stderr,"%s: bad option: %s\n",
286: procnam,arg);
287: delexit(NOT_OK);
288: }
289:
290: (*xargv)++;
291: --(*xargc);
292: }
293:
294: return;
295: }
296:
297: initalloc()
298: {
299: static done = 0;
300: register t;
301:
302: if (done++)
303: return;
304:
305: hshtab = (struct nlist **)xcalloc(hshsize,sizeof(struct nlist *));
306: callst = (struct call *)xcalloc(stksize/3+1,sizeof(struct call));
307: Ap = argstk = (char **)xcalloc(stksize+3,sizeof(char *));
308: ipstk[0] = ipflr = ip = ibuf = xcalloc(bufsize+1,sizeof(char));
309: op = obuf = xcalloc(bufsize+1,sizeof(char));
310: token = xcalloc(toksize+1,sizeof(char));
311:
312: astklm = &argstk[stksize];
313: ibuflm = &ibuf[bufsize];
314: obuflm = &obuf[bufsize];
315: toklm = &token[toksize];
316:
317: for (t=0; barray[t].bname; ++t) {
318: static char p[2] = {0, EOS};
319:
320: p[0] = t|~LOW7;
321: install(barray[t].bname,p,NOPUSH);
322: }
323:
324: #ifdef unix
325: install("unix",nullstr,NOPUSH);
326: #endif
327:
328: #ifdef gcos
329: install("gcos",nullstr,NOPUSH);
330: #endif
331: }
332:
333: struct nlist *
334: install(nam,val,mode)
335: char *nam;
336: register char *val;
337: {
338: register struct nlist *np;
339: register char *cp;
340: int l;
341:
342: if (mode==PUSH)
343: lookup(nam); /* lookup sets hshval */
344: else
345: while (undef(nam)) /* undef calls lookup */
346: ;
347:
348: np = (struct nlist *)xcalloc(1,sizeof(*np));
349: np->name = copy(nam);
350: np->next = hshtab[hshval];
351: hshtab[hshval] = np;
352:
353: cp = xcalloc((l=strlen(val))+1,sizeof(*val));
354: np->def = cp;
355: cp = &cp[l];
356:
357: while (*val)
358: *--cp = *val++;
359: }
360:
361: struct nlist *
362: lookup(str)
363: char *str;
364: {
365: register char *s1, *s2;
366: register struct nlist *np;
367: static struct nlist nodef;
368:
369: s1 = str;
370:
371: for (hshval = 0; *s1; )
372: hshval += *s1++;
373:
374: hshval %= hshsize;
375:
376: for (np = hshtab[hshval]; np!=NULL; np = np->next) {
377: s1 = str;
378: s2 = np->name;
379: while (*s1++==*s2)
380: if (*s2++==EOS)
381: return(np);
382: }
383:
384: return(&nodef);
385: }
386:
387: expand(a1,c)
388: char **a1;
389: {
390: register char *dp;
391: register struct nlist *sp;
392:
393: sp = a1[-1];
394:
395: if (sp->tflag || trace) {
396: int i;
397:
398: fprintf(stderr,"Trace(%d): %s",Cp-callst,a1[0]);
399:
400: if (c > 0) {
401: fprintf(stderr,"(%s",chkbltin(a1[1]));
402: for (i=2; i<=c; ++i)
403: fprintf(stderr,",%s",chkbltin(a1[i]));
404: fprintf(stderr,")");
405: }
406:
407: fprintf(stderr,"\n");
408: }
409:
410: dp = sp->def;
411:
412: for (; *dp; ++dp) {
413: if (*dp&~LOW7) {
414: (*barray[*dp&LOW7].bfunc)(a1,c);
415: } else if (dp[1]=='$') {
416: if (isdigit(*dp)) {
417: register n;
418: if ((n = *dp-'0') <= c)
419: pbstr(a1[n]);
420: ++dp;
421: } else if (*dp=='#') {
422: pbnum((long) c);
423: ++dp;
424: } else if (*dp=='*' || *dp=='@') {
425: register i = c;
426: char **a = a1;
427:
428: if (i > 0)
429: for (;;) {
430: if (*dp=='@')
431: pbstr(rquote);
432:
433: pbstr(a[i--]);
434:
435: if (*dp=='@')
436: pbstr(lquote);
437:
438: if (i <= 0)
439: break;
440:
441: pbstr(",");
442: }
443: ++dp;
444: } else
445: putbak(*dp);
446: } else
447: putbak(*dp);
448: }
449: }
450:
451: setfname(s)
452: register char *s;
453: {
454: strcpy(fname[ifx],s);
455: fname[ifx+1] = fname[ifx]+strlen(s)+1;
456: fline[ifx] = 1;
457: nflag = 1;
458: lnsync(stdout);
459: }
460:
461: lnsync(iop)
462: register FILE *iop;
463: {
464: static int cline = 0;
465: static int cfile = 0;
466:
467: if (!sflag || iop!=stdout)
468: return;
469:
470: if (nflag || ifx!=cfile) {
471: nflag = 0;
472: cfile = ifx;
473: fprintf(iop,"#line %d \"",cline = fline[ifx]);
474: fpath(iop);
475: fprintf(iop,"\"\n");
476: } else if (++cline != fline[ifx])
477: fprintf(iop,"#line %d\n",cline = fline[ifx]);
478: }
479:
480: fpath(iop)
481: register FILE *iop;
482: {
483: register i;
484:
485: fprintf(iop,"%s",fname[0]);
486:
487: for (i=1; i<=ifx; ++i)
488: fprintf(iop,":%s",fname[i]);
489: }
490:
491: catchsig()
492: {
493: #ifdef unix
494: signal(SIGHUP,SIG_IGN);
495: signal(SIGINT,SIG_IGN);
496: #endif
497:
498: delexit(NOT_OK);
499: }
500:
501: delexit(code)
502: {
503: register i;
504:
505: cf = stdout;
506:
507: /* if (ofx != 0) { /* quitting in middle of diversion */
508: /* ofx = 0;
509: /* code = NOT_OK;
510: /* }
511: */
512: ofx = 0; /* ensure that everything comes out */
513: for (i=1; i<10; i++)
514: undiv(i,code);
515:
516: tempname[7] = 'a';
517: unlink(tempname);
518:
519: if (code==OK)
520: exit(code);
521:
522: _exit(code);
523: }
524:
525: puttok(tp)
526: register char *tp;
527: {
528: if (Cp) {
529: while (*tp)
530: stkchr(*tp++);
531: } else if (cf)
532: while (*tp)
533: sputchr(*tp++,cf);
534: }
535:
536: pbstr(str)
537: register char *str;
538: {
539: register char *p;
540:
541: p = str;
542:
543: while (*p++)
544: ;
545:
546: --p;
547:
548: while (p > str)
549: putbak(*--p);
550: }
551:
552: undiv(i,code)
553: register i;
554: {
555: register FILE *fp;
556: register c;
557:
558: if (i<1 || i>9 || i==ofx || !ofile[i])
559: return;
560:
561: fclose(ofile[i]);
562: tempname[7] = 'a'+i;
563:
564: if (code==OK && cf) {
565: fp = xfopen(tempname,"r");
566:
567: while ((c=getc(fp)) != EOF)
568: sputchr(c,cf);
569:
570: fclose(fp);
571: }
572:
573: unlink(tempname);
574: ofile[i] = NULL;
575: }
576:
577: char *copy(s)
578: register char *s;
579: {
580: register char *p, *s1;
581:
582: p = s1 = xcalloc(strlen(s)+1,1);
583:
584: while (*s1++ = *s++)
585: ;
586:
587: return(p);
588: }
589:
590: pbnum(num)
591: long num;
592: {
593: pbnbr(num,10,1);
594: }
595:
596: pbnbr(nbr,base,len)
597: long nbr;
598: register base, len;
599: {
600: register neg = 0;
601:
602: if (base<=0)
603: return;
604:
605: if (nbr<0) {
606: neg = 1;
607: nbr = -nbr;
608: }
609:
610: while (nbr>0) {
611: int i;
612: if (base>1) {
613: i = nbr%base;
614: nbr /= base;
615: } else {
616: i = 1;
617: --nbr;
618: }
619: putbak(itochr(i));
620: --len;
621: }
622:
623: while (--len >= 0)
624: putbak('0');
625:
626: if (neg)
627: putbak('-');
628: }
629:
630: itochr(i)
631: register i;
632: {
633: if (i>9)
634: return i-10+'A';
635: else
636: return i+'0';
637: }
638:
639: long ctol(str)
640: register char *str;
641: {
642: register sign;
643: long num;
644:
645: while (isspace(*str))
646: ++str;
647: num = 0;
648: if (*str=='-') {
649: sign = -1;
650: ++str;
651: }
652: else
653: sign = 1;
654: while (isdigit(*str))
655: num = num*10 + *str++ - '0';
656: return(sign * num);
657: }
658:
659: min(a,b)
660: {
661: if (a>b)
662: return(b);
663: return(a);
664: }
665:
666: FILE *
667: xfopen(name,mode)
668: char *name,
669: *mode;
670: {
671: FILE *fp;
672:
673: if ((fp=fopen(name,mode))==NULL)
674: error(badfile);
675:
676: return fp;
677: }
678:
679: char *
680: xcalloc(nbr,size)
681: {
682: register char *ptr;
683:
684: if ((ptr=calloc(nbr,size)) == NULL)
685: error(nocore);
686:
687: return ptr;
688: }
689:
690: error(str)
691: char *str;
692: {
693: fprintf(stderr,"\n%s:",procnam);
694: fpath(stderr);
695: fprintf(stderr,":%d %s\n",fline[ifx],str);
696: if (Cp) {
697: register struct call *mptr;
698:
699: /* fix limit */
700: *op = EOS;
701: (Cp+1)->argp = Ap+1;
702:
703: for (mptr=callst; mptr<=Cp; ++mptr) {
704: register char **aptr, **lim;
705:
706: aptr = mptr->argp;
707: lim = (mptr+1)->argp-1;
708: if (mptr==callst)
709: fputs(*aptr,stderr);
710: ++aptr;
711: fputs("(",stderr);
712: if (aptr < lim)
713: for (;;) {
714: fputs(*aptr++,stderr);
715: if (aptr >= lim)
716: break;
717: fputs(",",stderr);
718: }
719: }
720: while (--mptr >= callst)
721: fputs(")",stderr);
722:
723: fputs("\n",stderr);
724: }
725: delexit(NOT_OK);
726: }
727:
728: error2(str,num)
729: char *str;
730: int num;
731: {
732: char buf[500];
733:
734: fprintf(buf,str,num);
735: error(buf);
736: }
737:
738: chkbltin(s)
739: char *s;
740: {
741: static char buf[24];
742:
743: if (*s&~LOW7)
744: return sprintf(buf,"<%s>",barray[*s&LOW7].bname);
745:
746: return s;
747: }
748:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.