10859a5e0Ssam #ifndef lint
2*972e762aSbostic static char sccsid[] = "@(#)m4.c 1.5 (Berkeley) 05/10/89";
30859a5e0Ssam #endif
40859a5e0Ssam
59a34925cSclemc #include <stdio.h>
69a34925cSclemc #include <signal.h>
7*972e762aSbostic #include "pathnames.h"
89a34925cSclemc
99a34925cSclemc #define ERROR NULL
109a34925cSclemc #define READ "r"
119a34925cSclemc #define WRITE "w"
129a34925cSclemc
139a34925cSclemc #define EOS 0
149a34925cSclemc int lpar = '(';
159a34925cSclemc #define LPAR lpar
169a34925cSclemc #define RPAR ')'
179a34925cSclemc #define COMMA ','
189a34925cSclemc #define GRAVE '`'
199a34925cSclemc #define ACUTE '\''
209a34925cSclemc #define LBRAK '['
219a34925cSclemc #define RBRAK ']'
229a34925cSclemc #ifdef M4
239a34925cSclemc char lquote LBRAK;
249a34925cSclemc char rquote RBRAK;
259a34925cSclemc #endif
269a34925cSclemc #ifndef M4
279a34925cSclemc char lquote = GRAVE;
289a34925cSclemc char rquote = ACUTE;
299a34925cSclemc #endif
309a34925cSclemc #define COMMENT '#'
319a34925cSclemc #define ALPH 1
329a34925cSclemc #define DIG 2
339a34925cSclemc
349a34925cSclemc #define HSHSIZ 199 /* prime */
359a34925cSclemc #define STACKS 50
369a34925cSclemc #define SAVS 4096
379a34925cSclemc #define TOKS 128
389a34925cSclemc
399a34925cSclemc #define putbak(c) *ip++ = c;
409a34925cSclemc #define getchr() (ip>cur_ip?*--ip: getc(infile[infptr]))
419a34925cSclemc #define putchr(c) if (cp==NULL) {if (curfile)putc(c,curfile);} else *op++ = c
429a34925cSclemc char type[] = {
439a34925cSclemc 0, 0, 0, 0, 0, 0, 0, 0,
449a34925cSclemc 0, 0, 0, 0, 0, 0, 0, 0,
459a34925cSclemc 0, 0, 0, 0, 0, 0, 0, 0,
469a34925cSclemc 0, 0, 0, 0, 0, 0, 0, 0,
479a34925cSclemc 0, 0, 0, 0, 0, 0, 0, 0,
489a34925cSclemc 0, 0, 0, 0, 0, 0, 0, 0,
499a34925cSclemc DIG, DIG, DIG, DIG, DIG, DIG, DIG, DIG,
509a34925cSclemc DIG, DIG, 0, 0, 0, 0, 0, 0,
519a34925cSclemc 0, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH,
529a34925cSclemc ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH,
539a34925cSclemc ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH,
549a34925cSclemc ALPH, ALPH, ALPH, 0, 0, 0, 0, ALPH,
559a34925cSclemc 0, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH,
569a34925cSclemc ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH,
579a34925cSclemc ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH,
589a34925cSclemc ALPH, ALPH, ALPH, 0, 0, 0, 0, 0,
599a34925cSclemc };
609a34925cSclemc
619a34925cSclemc char token[TOKS];
629a34925cSclemc char eoa[] = "\0";
63733d808dSclemc
64733d808dSclemc #define RESERVED 01 /* This is a reserved word with side action */
659a34925cSclemc struct nlist {
669a34925cSclemc char *name;
679a34925cSclemc char *def;
68733d808dSclemc char flag;
699a34925cSclemc struct nlist *next;
709a34925cSclemc };
719a34925cSclemc
729a34925cSclemc struct nlist *hshtab[HSHSIZ];
739a34925cSclemc char ibuf[SAVS+TOKS];
749a34925cSclemc char obuf[SAVS+TOKS];
759a34925cSclemc char *op = obuf;
769a34925cSclemc char *ip = ibuf;
779a34925cSclemc char *ip_stk[10] = {ibuf};
789a34925cSclemc char *cur_ip = ibuf;
799a34925cSclemc struct call {
809a34925cSclemc char **argp;
819a34925cSclemc int plev;
829a34925cSclemc };
839a34925cSclemc struct call *cp = NULL;
849a34925cSclemc
859a34925cSclemc char *makeloc;
869a34925cSclemc char *ifdefloc;
879a34925cSclemc char *lenloc;
889a34925cSclemc char *undefloc;
899a34925cSclemc char *shiftloc;
909a34925cSclemc char *cqloc;
919a34925cSclemc char *defloc;
929a34925cSclemc char *evaloc;
939a34925cSclemc char *incrloc;
949a34925cSclemc char *substrloc;
959a34925cSclemc char *indexloc;
969a34925cSclemc char *transloc;
979a34925cSclemc char *ifloc;
989a34925cSclemc char *divloc;
999a34925cSclemc char *divnumloc;
1009a34925cSclemc char *undivloc;
1019a34925cSclemc char *dnlloc;
1029a34925cSclemc char *inclloc;
1039a34925cSclemc char *sinclloc;
1049a34925cSclemc char *syscmdloc;
1059a34925cSclemc char *dumploc;
1069a34925cSclemc char *errploc;
1079a34925cSclemc
108*972e762aSbostic char tempname[] = _PATH_TMP;
1099a34925cSclemc struct nlist *lookup();
1109a34925cSclemc char *install();
1119a34925cSclemc char *malloc();
1129a34925cSclemc char *mktemp();
1139a34925cSclemc char *copy();
1149a34925cSclemc long ctol();
1159a34925cSclemc int hshval;
1169a34925cSclemc FILE *olist[11] = { stdout };
1179a34925cSclemc int okret;
1189a34925cSclemc int curout = 0;
1199a34925cSclemc FILE *curfile = { stdout };
1209a34925cSclemc FILE *infile[10] = { stdin };
1219a34925cSclemc int infptr = 0;
1229a34925cSclemc
main(argc,argv)1239a34925cSclemc main(argc, argv)
1249a34925cSclemc char **argv;
1259a34925cSclemc {
1269a34925cSclemc char *argstk[STACKS+10];
1279a34925cSclemc struct call callst[STACKS];
1289a34925cSclemc register char *tp, **ap;
1299a34925cSclemc int delexit(), catchsig();
1309a34925cSclemc register t;
1319a34925cSclemc int i;
1329a34925cSclemc
1339a34925cSclemc #ifdef gcos
1349a34925cSclemc #ifdef M4
135733d808dSclemc install("GCOS", eoa, 0);
1369a34925cSclemc #endif
1379a34925cSclemc #ifndef M4
138733d808dSclemc install("gcos", eoa, 0);
1399a34925cSclemc #endif
1409a34925cSclemc #endif
1419a34925cSclemc #ifdef unix
1429a34925cSclemc #ifdef M4
143733d808dSclemc install("UNIX", eoa, 0);
1449a34925cSclemc #endif
1459a34925cSclemc #ifndef M4
146733d808dSclemc install("unix", eoa, 0);
1479a34925cSclemc #endif
1489a34925cSclemc #endif
1499a34925cSclemc
1509a34925cSclemc #ifdef M4
151733d808dSclemc makeloc = install("MAKETEMP", eoa, RESERVED);
152733d808dSclemc ifdefloc = install("IFDEF", eoa, RESERVED);
153733d808dSclemc lenloc = install("LEN", eoa, RESERVED);
154733d808dSclemc undefloc = install("UNDEFINE", eoa, RESERVED);
155733d808dSclemc shiftloc = install("SHIFT", eoa, RESERVED);
156733d808dSclemc cqloc = install("CHANGEQUOTE", eoa, RESERVED);
157733d808dSclemc defloc = install("DEFINE", eoa, RESERVED);
158733d808dSclemc evaloc = install("EVAL", eoa, RESERVED);
159733d808dSclemc inclloc = install("INCLUDE", eoa, RESERVED);
160733d808dSclemc sinclloc = install("SINCLUDE", eoa, RESERVED);
161733d808dSclemc syscmdloc = install("SYSCMD", eoa, RESERVED);
162733d808dSclemc dumploc = install("DUMPDEF", eoa, RESERVED);
163733d808dSclemc errploc = install("ERRPRINT", eoa, RESERVED);
164733d808dSclemc incrloc = install("INCR", eoa, RESERVED);
165733d808dSclemc substrloc = install("SUBSTR", eoa, RESERVED);
166733d808dSclemc indexloc = install("INDEX", eoa, RESERVED);
167733d808dSclemc transloc = install("TRANSLIT", eoa, RESERVED);
168733d808dSclemc ifloc = install("IFELSE", eoa, RESERVED);
169733d808dSclemc divloc = install("DIVERT", eoa, RESERVED);
170733d808dSclemc divnumloc = install("DIVNUM", eoa, RESERVED);
171733d808dSclemc undivloc = install("UNDIVERT", eoa, RESERVED);
172733d808dSclemc dnlloc = install("DNL", eoa, RESERVED);
1739a34925cSclemc #endif
1749a34925cSclemc
1759a34925cSclemc #ifndef M4
176733d808dSclemc makeloc = install("maketemp", eoa, RESERVED);
177733d808dSclemc ifdefloc = install("ifdef", eoa, RESERVED);
178733d808dSclemc lenloc = install("len", eoa, RESERVED);
179733d808dSclemc undefloc = install("undefine", eoa, RESERVED);
180733d808dSclemc shiftloc = install("shift", eoa, RESERVED);
181733d808dSclemc cqloc = install("changequote", eoa, RESERVED);
182733d808dSclemc defloc = install("define", eoa, RESERVED);
183733d808dSclemc evaloc = install("eval", eoa, RESERVED);
184733d808dSclemc inclloc = install("include", eoa, RESERVED);
185733d808dSclemc sinclloc = install("sinclude", eoa, RESERVED);
186733d808dSclemc syscmdloc = install("syscmd", eoa, RESERVED);
187733d808dSclemc dumploc = install("dumpdef", eoa, RESERVED);
188733d808dSclemc errploc = install("errprint", eoa, RESERVED);
189733d808dSclemc incrloc = install("incr", eoa, RESERVED);
190733d808dSclemc substrloc = install("substr", eoa, RESERVED);
191733d808dSclemc indexloc = install("index", eoa, RESERVED);
192733d808dSclemc transloc = install("translit", eoa, RESERVED);
193733d808dSclemc ifloc = install("ifelse", eoa, RESERVED);
194733d808dSclemc divloc = install("divert", eoa, RESERVED);
195733d808dSclemc divnumloc = install("divnum", eoa, RESERVED);
196733d808dSclemc undivloc = install("undivert", eoa, RESERVED);
197733d808dSclemc dnlloc = install("dnl", eoa, RESERVED);
1989a34925cSclemc #endif
1999a34925cSclemc ap = argstk;
2009a34925cSclemc #ifndef gcos
2019a34925cSclemc if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
2029a34925cSclemc signal(SIGHUP, catchsig);
2039a34925cSclemc if (signal(SIGINT, SIG_IGN) != SIG_IGN)
2049a34925cSclemc signal(SIGINT, catchsig);
20501f249f8Sbostic mktemp(tempname);
2069a34925cSclemc close(creat(tempname, 0));
2079a34925cSclemc #endif
2089a34925cSclemc #ifdef gcos
2099a34925cSclemc tempname = "m4.tempa";
2109a34925cSclemc #endif
2119a34925cSclemc if (argc>1)
2129a34925cSclemc putbak(0);
2139a34925cSclemc for (;;) {
2149a34925cSclemc tp = token;
2159a34925cSclemc *tp++ = t = getchr();
2169a34925cSclemc *tp = EOS;
2179a34925cSclemc if (t<=0) {
2189a34925cSclemc if (infptr > 0) {
2199a34925cSclemc fclose(infile[infptr]);
2209a34925cSclemc infptr--;
2219a34925cSclemc cur_ip = ip_stk[infptr];
2229a34925cSclemc continue;
2239a34925cSclemc }
2249a34925cSclemc if (argc<=1)
2259a34925cSclemc break;
2269a34925cSclemc argc--;
2279a34925cSclemc argv++;
2289a34925cSclemc if (infile[infptr]!=stdin)
2299a34925cSclemc fclose(infile[infptr]);
2309a34925cSclemc if (**argv=='-')
2319a34925cSclemc infile[infptr] = stdin;
2329a34925cSclemc else if ((infile[infptr]=fopen(argv[0], READ))==ERROR) {
2339a34925cSclemc fprintf(stderr, "m4: file not found: %s\n", argv[0]);
2349a34925cSclemc delexit();
2359a34925cSclemc }
2369a34925cSclemc continue;
2379a34925cSclemc }
2389a34925cSclemc if (type[t]==ALPH) {
2399a34925cSclemc while ((t=type[*tp++=getchr()])==ALPH||t==DIG);
2409a34925cSclemc putbak(*--tp);
2419a34925cSclemc *tp = EOS;
2429a34925cSclemc if (*ap = lookup(token)->def) {
2439a34925cSclemc if (++ap >= &argstk[STACKS]) {
2449a34925cSclemc fprintf(stderr, "m4: arg stack overflow\n");
2459a34925cSclemc delexit();
2469a34925cSclemc }
2479a34925cSclemc if (cp==NULL)
2489a34925cSclemc cp = callst;
2499a34925cSclemc else if (++cp > &callst[STACKS]) {
2509a34925cSclemc fprintf(stderr, "m4: call stack overflow\n");
2519a34925cSclemc delexit();
2529a34925cSclemc }
2539a34925cSclemc cp->argp = ap;
2549a34925cSclemc *ap++ = op;
2559a34925cSclemc puttok();
2569a34925cSclemc *op++ = '\0';
2579a34925cSclemc t = getchr();
2589a34925cSclemc putbak(t);
2599a34925cSclemc if (t!=LPAR) {
2609a34925cSclemc /* if (t!=' ' && t!='\t') */
2619a34925cSclemc putbak(')');
2629a34925cSclemc putbak('(');
2639a34925cSclemc }
2649a34925cSclemc else /* try to fix arg count */
2659a34925cSclemc *ap++ = op;
2669a34925cSclemc cp->plev = 0;
2679a34925cSclemc } else
2689a34925cSclemc puttok();
2699a34925cSclemc } else if (t==lquote) {
2709a34925cSclemc i = 1;
2719a34925cSclemc for (;;) {
2729a34925cSclemc t = getchr();
2739a34925cSclemc if (t==rquote) {
2749a34925cSclemc i--;
2759a34925cSclemc if (i==0)
2769a34925cSclemc break;
2779a34925cSclemc } else if (t==lquote)
2789a34925cSclemc i++;
2799a34925cSclemc else if (t<0) {
2809a34925cSclemc fprintf(stderr, "m4: EOF in string\n");
2819a34925cSclemc delexit();
2829a34925cSclemc }
2839a34925cSclemc putchr(t);
2849a34925cSclemc }
2859a34925cSclemc } else if (t==COMMENT) {
2869a34925cSclemc putbak(t);
2879a34925cSclemc while ((t = getchr())!='\n'&& t>=0)
2889a34925cSclemc if (cp==NULL)
2899a34925cSclemc putchr(t);
2909a34925cSclemc putbak(t);
2919a34925cSclemc } else if (cp==NULL) {
2929a34925cSclemc puttok();
2939a34925cSclemc } else if (t==LPAR) {
2949a34925cSclemc if (cp->plev)
2959a34925cSclemc *op++ = t;
2969a34925cSclemc cp->plev++;
2979a34925cSclemc while ( (t=getchr())==' ' || t=='\t' || t=='\n')
2989a34925cSclemc ; /* skip leading white space during arg collection */
2999a34925cSclemc putbak(t);
3009a34925cSclemc /*
3019a34925cSclemc } else if (t==' ' || t=='\t' || t=='\n') {
3029a34925cSclemc continue;
3039a34925cSclemc */
3049a34925cSclemc } else if (t==RPAR) {
3059a34925cSclemc cp->plev--;
3069a34925cSclemc if (cp->plev==0) {
3079a34925cSclemc *op++ = '\0';
3089a34925cSclemc expand(cp->argp, ap-cp->argp-1);
3099a34925cSclemc op = *cp->argp;
3109a34925cSclemc ap = cp->argp-1;
3119a34925cSclemc cp--;
3129a34925cSclemc if (cp < callst)
3139a34925cSclemc cp = NULL;
3149a34925cSclemc } else
3159a34925cSclemc *op++ = t;
3169a34925cSclemc } else if (t==COMMA && cp->plev<=1) {
3179a34925cSclemc *op++ = '\0';
3189a34925cSclemc *ap++ = op;
3199a34925cSclemc while ((t=getchr())==' ' || t=='\t' || t=='\n')
3209a34925cSclemc ; /* skip leading white space during arg collection */
3219a34925cSclemc putbak(t);
3229a34925cSclemc } else
3239a34925cSclemc *op++ = t;
3249a34925cSclemc }
3259a34925cSclemc if (cp!=NULL) {
3269a34925cSclemc fprintf(stderr, "m4: unexpected EOF\n");
3279a34925cSclemc delexit();
3289a34925cSclemc }
3299a34925cSclemc okret = 1;
3309a34925cSclemc delexit();
3319a34925cSclemc }
3329a34925cSclemc
catchsig()3339a34925cSclemc catchsig()
3349a34925cSclemc {
3359a34925cSclemc okret = 0;
3369a34925cSclemc delexit();
3379a34925cSclemc }
3389a34925cSclemc
delexit()3399a34925cSclemc delexit()
3409a34925cSclemc {
3419a34925cSclemc register FILE *fp;
3429a34925cSclemc register i, c;
3439a34925cSclemc
3449a34925cSclemc if (!okret) {
3459a34925cSclemc signal(SIGHUP, SIG_IGN);
3469a34925cSclemc signal(SIGINT, SIG_IGN);
3479a34925cSclemc }
3489a34925cSclemc for (i=1; i<10; i++) {
3499a34925cSclemc if (olist[i]==NULL)
3509a34925cSclemc continue;
3519a34925cSclemc fclose(olist[i]);
3529a34925cSclemc tempname[7] = 'a'+i;
3539a34925cSclemc if (okret) {
3549a34925cSclemc fp = fopen(tempname, READ);
3559a34925cSclemc while ((c = getc(fp)) > 0)
3569a34925cSclemc putchar(c);
3579a34925cSclemc fclose(fp);
3589a34925cSclemc }
3599a34925cSclemc unlink(tempname);
3609a34925cSclemc }
3619a34925cSclemc tempname[7] = 'a';
3629a34925cSclemc unlink(tempname);
3639a34925cSclemc exit(1-okret);
3649a34925cSclemc }
3659a34925cSclemc
puttok()3669a34925cSclemc puttok()
3679a34925cSclemc {
3689a34925cSclemc register char *tp;
3699a34925cSclemc
3709a34925cSclemc tp = token;
3719a34925cSclemc if (cp) {
3729a34925cSclemc if (op >= &obuf[SAVS]) {
3739a34925cSclemc fprintf(stderr, "m4: argument overflow\n");
3749a34925cSclemc delexit();
3759a34925cSclemc }
3769a34925cSclemc while (*tp)
3779a34925cSclemc *op++ = *tp++;
3789a34925cSclemc } else if (curfile)
3799a34925cSclemc while (*tp)
3809a34925cSclemc putc(*tp++, curfile);
3819a34925cSclemc }
3829a34925cSclemc
pbstr(str)3839a34925cSclemc pbstr(str)
3849a34925cSclemc register char *str;
3859a34925cSclemc {
3869a34925cSclemc register char *p;
3879a34925cSclemc
3889a34925cSclemc p = str;
3899a34925cSclemc while (*p++);
3909a34925cSclemc --p;
3919a34925cSclemc if (ip >= &ibuf[SAVS]) {
3929a34925cSclemc fprintf(stderr, "m4: pushback overflow\n");
3939a34925cSclemc delexit();
3949a34925cSclemc }
3959a34925cSclemc while (p > str)
3969a34925cSclemc putbak(*--p);
3979a34925cSclemc }
3989a34925cSclemc
expand(a1,c)3999a34925cSclemc expand(a1, c)
4009a34925cSclemc register char **a1;
4019a34925cSclemc {
4029a34925cSclemc register char *dp;
4039a34925cSclemc register n;
4049a34925cSclemc
4059a34925cSclemc dp = a1[-1];
4069a34925cSclemc if (dp==defloc)
4079a34925cSclemc dodef(a1, c);
4089a34925cSclemc else if (dp==evaloc)
4099a34925cSclemc doeval(a1, c);
4109a34925cSclemc else if (dp==inclloc)
4119a34925cSclemc doincl(a1, c, 1);
4129a34925cSclemc else if (dp==sinclloc)
4139a34925cSclemc doincl(a1, c, 0);
4149a34925cSclemc else if (dp==makeloc)
4159a34925cSclemc domake(a1, c);
4169a34925cSclemc else if (dp==syscmdloc)
4179a34925cSclemc dosyscmd(a1, c);
4189a34925cSclemc else if (dp==incrloc)
4199a34925cSclemc doincr(a1, c);
4209a34925cSclemc else if (dp==substrloc)
4219a34925cSclemc dosubstr(a1, c);
4229a34925cSclemc else if (dp==indexloc)
4239a34925cSclemc doindex(a1, c);
4249a34925cSclemc else if (dp==transloc)
4259a34925cSclemc dotransl(a1, c);
4269a34925cSclemc else if (dp==ifloc)
4279a34925cSclemc doif(a1, c);
4289a34925cSclemc else if (dp==divloc)
4299a34925cSclemc dodiv(a1, c);
4309a34925cSclemc else if (dp==divnumloc)
4319a34925cSclemc dodivnum(a1, c);
4329a34925cSclemc else if (dp==undivloc)
4339a34925cSclemc doundiv(a1, c);
4349a34925cSclemc else if (dp==dnlloc)
4359a34925cSclemc dodnl(a1, c);
4369a34925cSclemc else if (dp==dumploc)
4379a34925cSclemc dodump(a1, c);
4389a34925cSclemc else if (dp==errploc)
4399a34925cSclemc doerrp(a1, c);
4409a34925cSclemc else if (dp==lenloc)
4419a34925cSclemc dolen(a1, c);
4429a34925cSclemc else if (dp==ifdefloc)
4439a34925cSclemc doifdef(a1, c);
4449a34925cSclemc else if (dp==undefloc)
4459a34925cSclemc doundef(a1, c);
4469a34925cSclemc else if (dp==shiftloc)
4479a34925cSclemc doshift(a1, c);
4489a34925cSclemc else if (dp==cqloc)
4499a34925cSclemc docq(a1, c);
4509a34925cSclemc else {
4519a34925cSclemc while (*dp++);
4529a34925cSclemc for (dp--; dp>a1[-1]; ) {
4539a34925cSclemc if (--dp>a1[-1] && dp[-1]=='$') {
4549a34925cSclemc n = *dp-'0';
4559a34925cSclemc if (n>=0 && n<=9) {
4569a34925cSclemc if (n <= c)
4579a34925cSclemc pbstr(a1[n]);
4589a34925cSclemc dp--;
4599a34925cSclemc } else
4609a34925cSclemc putbak(*dp);
4619a34925cSclemc } else
4629a34925cSclemc putbak(*dp);
4639a34925cSclemc }
4649a34925cSclemc }
4659a34925cSclemc }
4669a34925cSclemc
lookup(str)4679a34925cSclemc struct nlist *lookup(str)
4689a34925cSclemc char *str;
4699a34925cSclemc {
4709a34925cSclemc register char *s1, *s2;
4719a34925cSclemc register struct nlist *np;
4729a34925cSclemc static struct nlist nodef;
4739a34925cSclemc
4749a34925cSclemc s1 = str;
4759a34925cSclemc for (hshval = 0; *s1; )
4769a34925cSclemc hshval += *s1++;
4779a34925cSclemc hshval %= HSHSIZ;
4789a34925cSclemc for (np = hshtab[hshval]; np!=NULL; np = np->next) {
4799a34925cSclemc s1 = str;
4809a34925cSclemc s2 = np->name;
4819a34925cSclemc while (*s1++ == *s2)
4829a34925cSclemc if (*s2++ == EOS)
4839a34925cSclemc return(np);
4849a34925cSclemc }
4859a34925cSclemc return(&nodef);
4869a34925cSclemc }
4879a34925cSclemc
install(nam,val,flag)488733d808dSclemc char *install(nam, val, flag)
4899a34925cSclemc char *nam, *val;
490733d808dSclemc char flag;
4919a34925cSclemc {
4929a34925cSclemc register struct nlist *np;
4939a34925cSclemc
4949a34925cSclemc if ((np = lookup(nam))->name == NULL) {
4959a34925cSclemc np = (struct nlist *)malloc(sizeof(*np));
4969a34925cSclemc if (np == NULL) {
4979a34925cSclemc fprintf(stderr, "m4: no space for alloc\n");
4989a34925cSclemc exit(1);
4999a34925cSclemc }
5009a34925cSclemc np->name = copy(nam);
5019a34925cSclemc np->def = copy(val);
5029a34925cSclemc np->next = hshtab[hshval];
503733d808dSclemc np->flag = flag;
5049a34925cSclemc hshtab[hshval] = np;
5059a34925cSclemc return(np->def);
5069a34925cSclemc }
5079a34925cSclemc free(np->def);
508733d808dSclemc np->flag = flag;
5099a34925cSclemc np->def = copy(val);
5109a34925cSclemc return(np->def);
5119a34925cSclemc }
5129a34925cSclemc
doundef(ap,c)5139a34925cSclemc doundef(ap, c)
5149a34925cSclemc char **ap;
5159a34925cSclemc {
5169a34925cSclemc register struct nlist *np, *tnp;
5179a34925cSclemc
5189a34925cSclemc if (c < 1 || (np = lookup(ap[1]))->name == NULL)
5199a34925cSclemc return;
5209a34925cSclemc tnp = hshtab[hshval]; /* lookup sets hshval */
5219a34925cSclemc if (tnp == np) /* it's in first place */
5229a34925cSclemc hshtab[hshval] = np->next;
5239a34925cSclemc else {
5249a34925cSclemc for ( ; tnp->next != np; tnp = tnp->next)
5259a34925cSclemc ;
5269a34925cSclemc tnp->next = np->next;
5279a34925cSclemc }
528733d808dSclemc /*
529733d808dSclemc * If this is a reserved word, it has been removed from the
530733d808dSclemc * hastable. We do not want to actually free the space because
531733d808dSclemc * of the code in expand. Expand wants to to pointer compairs
532733d808dSclemc * to tell if this is a reserved word (e.g a special action
533733d808dSclemc * needs to take place). Thus if we do not free the space,
534733d808dSclemc * expand will still work, but the name will never be found
535733d808dSclemc * because it out of the symbol table!
536733d808dSclemc */
537733d808dSclemc if (np->flag&RESERVED == 0) { /* If not reserved free it */
5389a34925cSclemc free(np->name);
5399a34925cSclemc free(np->def);
5409a34925cSclemc free((char *)np);
5419a34925cSclemc }
542733d808dSclemc }
5439a34925cSclemc
copy(s)5449a34925cSclemc char *copy(s)
5459a34925cSclemc register char *s;
5469a34925cSclemc {
5479a34925cSclemc register char *p, *s1;
5489a34925cSclemc
5499a34925cSclemc p = s1 = malloc((unsigned)strlen(s)+1);
5509a34925cSclemc if (p == NULL) {
5519a34925cSclemc fprintf(stderr, "m4: no space for alloc\n");
5529a34925cSclemc exit(1);
5539a34925cSclemc }
5549a34925cSclemc while (*s1++ = *s++);
5559a34925cSclemc return(p);
5569a34925cSclemc }
5579a34925cSclemc
dodef(ap,c)5589a34925cSclemc dodef(ap, c)
5599a34925cSclemc char **ap;
5609a34925cSclemc {
5619a34925cSclemc if (c >= 2) {
5629a34925cSclemc if (strcmp(ap[1], ap[2]) == 0) {
5639a34925cSclemc fprintf(stderr, "m4: %s defined as itself\n", ap[1]);
5649a34925cSclemc delexit();
5659a34925cSclemc }
566733d808dSclemc install(ap[1], ap[2], 0);
5679a34925cSclemc }
5689a34925cSclemc else if (c == 1)
569733d808dSclemc install(ap[1], "", 0);
5709a34925cSclemc }
5719a34925cSclemc
doifdef(ap,c)5729a34925cSclemc doifdef(ap, c)
5739a34925cSclemc char **ap;
5749a34925cSclemc {
5759a34925cSclemc register struct nlist *np;
5769a34925cSclemc
5779a34925cSclemc if (c < 2)
5789a34925cSclemc return;
5799a34925cSclemc if (lookup(ap[1])->name != NULL)
5809a34925cSclemc pbstr(ap[2]);
5819a34925cSclemc else if (c >= 3)
5829a34925cSclemc pbstr(ap[3]);
5839a34925cSclemc }
5849a34925cSclemc
dolen(ap,c)5859a34925cSclemc dolen(ap, c)
5869a34925cSclemc char **ap;
5879a34925cSclemc {
5889a34925cSclemc putnum((long) strlen(ap[1]));
5899a34925cSclemc }
5909a34925cSclemc
docq(ap,c)5919a34925cSclemc docq(ap, c)
5929a34925cSclemc char **ap;
5939a34925cSclemc {
5949a34925cSclemc if (c > 1) {
5959a34925cSclemc lquote = *ap[1];
5969a34925cSclemc rquote = *ap[2];
5979a34925cSclemc } else if (c == 1) {
5989a34925cSclemc lquote = rquote = *ap[1];
5999a34925cSclemc } else {
6009a34925cSclemc #ifndef M4
6019a34925cSclemc lquote = GRAVE;
6029a34925cSclemc rquote = ACUTE;
6039a34925cSclemc #endif
6049a34925cSclemc #ifdef M4
6059a34925cSclemc lquote = LBRAK;
6069a34925cSclemc rquote = RBRAK;
6079a34925cSclemc #endif
6089a34925cSclemc }
6099a34925cSclemc }
6109a34925cSclemc
doshift(ap,c)6119a34925cSclemc doshift(ap, c)
6129a34925cSclemc char **ap;
6139a34925cSclemc {
6149a34925cSclemc fprintf(stderr, "m4: shift not yet implemented\n");
6159a34925cSclemc }
6169a34925cSclemc
dodump(ap,c)6179a34925cSclemc dodump(ap, c)
6189a34925cSclemc char **ap;
6199a34925cSclemc {
6209a34925cSclemc int i;
6219a34925cSclemc register struct nlist *np;
6229a34925cSclemc
6239a34925cSclemc if (c > 0)
6249a34925cSclemc while (c--) {
6259a34925cSclemc if ((np = lookup(*++ap))->name != NULL)
6269a34925cSclemc fprintf(stderr, "`%s' `%s'\n", np->name, np->def);
6279a34925cSclemc }
6289a34925cSclemc else
6299a34925cSclemc for (i=0; i<HSHSIZ; i++)
6309a34925cSclemc for (np=hshtab[i]; np!=NULL; np=np->next)
6319a34925cSclemc fprintf(stderr, "`%s' `%s'\n", np->name, np->def);
6329a34925cSclemc }
6339a34925cSclemc
doerrp(ap,c)6349a34925cSclemc doerrp(ap, c)
6359a34925cSclemc char **ap;
6369a34925cSclemc {
6379a34925cSclemc if (c > 0) {
6389a34925cSclemc fprintf(stderr, ap[1], ap[2], ap[3], ap[4], ap[5], ap[6]);
6399a34925cSclemc fprintf(stderr, "\n");
6409a34925cSclemc }
6419a34925cSclemc }
6429a34925cSclemc
6439a34925cSclemc
6449a34925cSclemc long evalval; /* return value from yacc stuff */
6459a34925cSclemc char *pe; /* used by grammar */
6469a34925cSclemc
doeval(ap,c)6479a34925cSclemc doeval(ap, c)
6489a34925cSclemc char **ap;
6499a34925cSclemc {
6509a34925cSclemc
6519a34925cSclemc if (c > 0) {
6529a34925cSclemc pe = ap[1];
6539a34925cSclemc if (yyparse() == 0)
6549a34925cSclemc putnum(evalval);
6559a34925cSclemc else
6569a34925cSclemc fprintf(stderr, "m4: invalid expression in eval: %s\n", ap[1]);
6579a34925cSclemc }
6589a34925cSclemc }
6599a34925cSclemc
doincl(ap,c,noisy)6609a34925cSclemc doincl(ap, c, noisy)
6619a34925cSclemc char **ap;
6629a34925cSclemc {
6639a34925cSclemc if (c > 0 && strlen(ap[1]) > 0) {
6649a34925cSclemc infptr++;
6659a34925cSclemc ip_stk[infptr] = cur_ip = ip;
6669a34925cSclemc if ((infile[infptr] = fopen(ap[1], READ))==ERROR) {
6679a34925cSclemc if (noisy) {
6689a34925cSclemc fprintf(stderr, "m4: file not found: %s\n", ap[1]);
6699a34925cSclemc delexit();
6709a34925cSclemc }
6719a34925cSclemc else
6729a34925cSclemc infptr--;
6739a34925cSclemc }
6749a34925cSclemc }
6759a34925cSclemc }
6769a34925cSclemc
dosyscmd(ap,c)6779a34925cSclemc dosyscmd(ap, c)
6789a34925cSclemc char **ap;
6799a34925cSclemc {
6809a34925cSclemc if (c > 0)
6819a34925cSclemc system(ap[1]);
6829a34925cSclemc }
6839a34925cSclemc
domake(ap,c)6849a34925cSclemc domake(ap, c)
6859a34925cSclemc char **ap;
6869a34925cSclemc {
6879a34925cSclemc if (c > 0)
6889a34925cSclemc pbstr(mktemp(ap[1]));
6899a34925cSclemc }
6909a34925cSclemc
doincr(ap,c)6919a34925cSclemc doincr(ap, c)
6929a34925cSclemc char **ap;
6939a34925cSclemc {
6949a34925cSclemc if (c >= 1)
6959a34925cSclemc putnum(ctol(ap[1])+1);
6969a34925cSclemc }
6979a34925cSclemc
putnum(num)6989a34925cSclemc putnum(num)
6999a34925cSclemc long num;
7009a34925cSclemc {
7019a34925cSclemc register sign;
7029a34925cSclemc
7039a34925cSclemc sign = (num < 0) ? '-' : '\0';
7049a34925cSclemc if (num < 0)
7059a34925cSclemc num = -num;
7069a34925cSclemc do {
7079a34925cSclemc putbak(num%10+'0');
7089a34925cSclemc num = num/10;
7099a34925cSclemc } while (num!=0);
7109a34925cSclemc if (sign == '-')
7119a34925cSclemc putbak('-');
7129a34925cSclemc }
7139a34925cSclemc
dosubstr(ap,c)7149a34925cSclemc dosubstr(ap, c)
7159a34925cSclemc char **ap;
7169a34925cSclemc {
7179a34925cSclemc int nc;
7189a34925cSclemc register char *sp, *fc;
7199a34925cSclemc
7209a34925cSclemc if (c<2)
7219a34925cSclemc return;
7229a34925cSclemc if (c<3)
7239a34925cSclemc nc = TOKS;
7249a34925cSclemc else
7259a34925cSclemc nc = ctoi(ap[3]);
7269a34925cSclemc fc = ap[1] + max(0, min(ctoi(ap[2]), strlen(ap[1])));
7279a34925cSclemc sp = fc + min(nc, strlen(fc));
7289a34925cSclemc while (sp > fc)
7299a34925cSclemc putbak(*--sp);
7309a34925cSclemc }
7319a34925cSclemc
doindex(ap,c)7329a34925cSclemc doindex(ap, c)
7339a34925cSclemc char **ap;
7349a34925cSclemc {
7359a34925cSclemc if (c >= 2)
7369a34925cSclemc putnum((long) strindex(ap[1], ap[2]));
7379a34925cSclemc }
7389a34925cSclemc
strindex(p1,p2)7399a34925cSclemc strindex(p1, p2)
7409a34925cSclemc char *p1, *p2;
7419a34925cSclemc {
7429a34925cSclemc register m;
7439a34925cSclemc register char *s, *t, *p;
7449a34925cSclemc
7459a34925cSclemc for (p=p1; *p; p++) {
7469a34925cSclemc s = p;
7479a34925cSclemc m = 1;
7489a34925cSclemc for (t=p2; *t; )
7499a34925cSclemc if (*t++ != *s++)
7509a34925cSclemc m = 0;
7519a34925cSclemc if (m == 1)
7529a34925cSclemc return(p-p1);
7539a34925cSclemc }
7549a34925cSclemc return(-1);
7559a34925cSclemc }
7569a34925cSclemc
dotransl(ap,c)7579a34925cSclemc dotransl(ap, c)
7589a34925cSclemc char **ap;
7599a34925cSclemc {
7609a34925cSclemc register char *s, *fr, *to;
7619a34925cSclemc
7629a34925cSclemc if (c <= 1) return;
7639a34925cSclemc
7649a34925cSclemc if (c == 2) {
7659a34925cSclemc register int i;
7669a34925cSclemc to = ap[1];
7679a34925cSclemc for (s = ap[1]; *s; s++) {
7689a34925cSclemc i = 0;
7699a34925cSclemc for (fr = ap[2]; *fr; fr++)
7709a34925cSclemc if (*s == *fr) {
7719a34925cSclemc i++;
7729a34925cSclemc break;
7739a34925cSclemc }
7749a34925cSclemc if (i == 0)
7759a34925cSclemc *to++ = *s;
7769a34925cSclemc }
7779a34925cSclemc *to = '\0';
7789a34925cSclemc }
7799a34925cSclemc
7809a34925cSclemc if (c >= 3) {
7819a34925cSclemc for (s = ap[1]; *s; s++)
7829a34925cSclemc for (fr = ap[2], to = ap[3]; *fr && *to; fr++, to++)
7839a34925cSclemc if (*s == *fr)
7849a34925cSclemc *s = *to;
7859a34925cSclemc }
7869a34925cSclemc
7879a34925cSclemc pbstr(ap[1]);
7889a34925cSclemc }
7899a34925cSclemc
doif(ap,c)7909a34925cSclemc doif(ap, c)
7919a34925cSclemc register char **ap;
7929a34925cSclemc {
7939a34925cSclemc if (c < 3)
7949a34925cSclemc return;
7959a34925cSclemc while (c >= 3) {
7969a34925cSclemc if (strcmp(ap[1], ap[2]) == 0) {
7979a34925cSclemc pbstr(ap[3]);
7989a34925cSclemc return;
7999a34925cSclemc }
8009a34925cSclemc c -= 3;
8019a34925cSclemc ap += 3;
8029a34925cSclemc }
8039a34925cSclemc if (c > 0)
8049a34925cSclemc pbstr(ap[1]);
8059a34925cSclemc }
8069a34925cSclemc
dodiv(ap,c)8079a34925cSclemc dodiv(ap, c)
8089a34925cSclemc register char **ap;
8099a34925cSclemc {
8109a34925cSclemc register int f;
8119a34925cSclemc
8129a34925cSclemc if (c<1)
8139a34925cSclemc f = 0;
8149a34925cSclemc else
8159a34925cSclemc f = ctoi(ap[1]);
8169a34925cSclemc if (f>=10 || f<0) {
8179a34925cSclemc curfile = NULL;
8189a34925cSclemc return;
8199a34925cSclemc }
8209a34925cSclemc tempname[7] = 'a' + f;
8219a34925cSclemc if (olist[f] || (olist[f]=fopen(tempname, WRITE))) {
8229a34925cSclemc curout = f;
8239a34925cSclemc curfile = olist[f];
8249a34925cSclemc }
8259a34925cSclemc }
8269a34925cSclemc
doundiv(ap,c)8279a34925cSclemc doundiv(ap, c)
8289a34925cSclemc char **ap;
8299a34925cSclemc {
8309a34925cSclemc register FILE *fp;
8319a34925cSclemc register int i, ch;
8329a34925cSclemc int j;
8339a34925cSclemc
8349a34925cSclemc if (c == 0) {
8359a34925cSclemc for (i=1; i<10; i++) {
8369a34925cSclemc if (i==curout || olist[i]==NULL)
8379a34925cSclemc continue;
8389a34925cSclemc fclose(olist[i]);
8399a34925cSclemc tempname[7] = 'a'+i;
8409a34925cSclemc fp = fopen(tempname, READ);
8419a34925cSclemc if (curfile != NULL)
8429a34925cSclemc while ((ch = getc(fp)) > 0)
8439a34925cSclemc putc(ch, curfile);
8449a34925cSclemc fclose(fp);
8459a34925cSclemc unlink(tempname);
8469a34925cSclemc olist[i] = NULL;
8479a34925cSclemc }
8489a34925cSclemc
8499a34925cSclemc }
8509a34925cSclemc else {
8519a34925cSclemc for (j = 1; j <= c; j++) {
8529a34925cSclemc i = ctoi(*++ap);
8539a34925cSclemc if (i<1 || i>9 || i==curout || olist[i]==NULL)
8549a34925cSclemc continue;
8559a34925cSclemc fclose(olist[i]);
8569a34925cSclemc tempname[7] = 'a'+i;
8579a34925cSclemc fp = fopen(tempname, READ);
8589a34925cSclemc if (curfile != NULL)
8599a34925cSclemc while ((ch = getc(fp)) > 0)
8609a34925cSclemc putc(ch, curfile);
8619a34925cSclemc fclose(fp);
8629a34925cSclemc unlink(tempname);
8639a34925cSclemc olist[i] = NULL;
8649a34925cSclemc }
8659a34925cSclemc }
8669a34925cSclemc }
8679a34925cSclemc
dodivnum(ap,c)8689a34925cSclemc dodivnum(ap, c)
8699a34925cSclemc char **ap;
8709a34925cSclemc {
8719a34925cSclemc putnum((long) curout);
8729a34925cSclemc }
8739a34925cSclemc
dodnl(ap,c)8749a34925cSclemc dodnl(ap, c)
8759a34925cSclemc char **ap;
8769a34925cSclemc {
8779a34925cSclemc register t;
8789a34925cSclemc
8799a34925cSclemc while ((t=getchr())!='\n' && t>=0)
8809a34925cSclemc ;
8819a34925cSclemc }
8829a34925cSclemc
ctol(str)8839a34925cSclemc long ctol(str)
8849a34925cSclemc register char *str;
8859a34925cSclemc {
8869a34925cSclemc register sign;
8879a34925cSclemc long num;
8889a34925cSclemc
8899a34925cSclemc while (*str==' ' || *str=='\t' || *str=='\n')
8909a34925cSclemc str++;
8919a34925cSclemc num = 0;
8929a34925cSclemc if (*str == '-') {
8939a34925cSclemc sign = -1;
8949a34925cSclemc str++;
8959a34925cSclemc }
8969a34925cSclemc else
8979a34925cSclemc sign = 1;
8989a34925cSclemc while (*str>='0' && *str<='9')
8999a34925cSclemc num = num*10 + *str++ - '0';
9009a34925cSclemc return(sign * num);
9019a34925cSclemc }
9029a34925cSclemc
ctoi(s)9039a34925cSclemc ctoi(s)
9049a34925cSclemc char *s;
9059a34925cSclemc {
9069a34925cSclemc return(ctol(s));
9079a34925cSclemc }
9089a34925cSclemc
min(a,b)9099a34925cSclemc min(a, b)
9109a34925cSclemc {
9119a34925cSclemc if (a>b)
9129a34925cSclemc return(b);
9139a34925cSclemc return(a);
9149a34925cSclemc }
9159a34925cSclemc
max(a,b)9169a34925cSclemc max(a, b)
9179a34925cSclemc {
9189a34925cSclemc if (a>b)
9199a34925cSclemc return(a);
9209a34925cSclemc return(b);
9219a34925cSclemc }
922