# To unbundle, sh this file echo unbundling makefile 1>&2 cat >makefile <<'//GO.SYSIN DD *' CFLAGS = -d2 a.out: m4.o m4ext.o m4macs.o m4y.o cc m4.o m4ext.o m4macs.o m4y.o m4.o m4ext.o m4macs.o : m4.h list: pr m4.h m4.c m4ext.c m4macs.c m4y.y makefile gcos: yacc m4y.y mv y.tab.c m4.tab.c fsend m4*.c m4.test* install: a.out strip a.out mv a.out /usr/bin/m4 clean: rm -f a.out *.o //GO.SYSIN DD * echo unbundling m4.c 1>&2 cat >m4.c <<'//GO.SYSIN DD *' #include <stdio.h> #include <signal.h> #include "m4.h" #define match(c,s) (c==*s && (!s[1] || inpmatch(s+1))) char *xcalloc(); main(argc,argv) char **argv; { register t; { static sigs[] = {SIGHUP, SIGINT, SIGPIPE, 0}; for (t=0; sigs[t]; ++t) if (signal(sigs[t], SIG_IGN) != SIG_IGN) signal(sigs[t],catchsig); } tempname = mktemp("/tmp/m4aXXXXXX"); close(creat(tempname,0)); procnam = argv[0]; getflags(&argc,&argv); initalloc(); setfname("-"); if (argc>1) { --argc; ++argv; if (strcmp(argv[0],"-")) { ifile[ifx] = xfopen(argv[0],"r"); setfname(argv[0]); } } for (;;) { token[0] = t = getchr(); token[1] = EOS; if (t==EOF) { if (ifx > 0) { fclose(ifile[ifx]); ipflr = ipstk[--ifx]; continue; } getflags(&argc,&argv); if (argc<=1) if (Wrapstr) { pbstr(Wrapstr); Wrapstr = NULL; continue; } else break; --argc; ++argv; if (ifile[ifx]!=stdin) fclose(ifile[ifx]); if (*argv[0]=='-') ifile[ifx] = stdin; else ifile[ifx] = xfopen(argv[0],"r"); setfname(argv[0]); continue; } if (isalpha(t)) { register char *tp = token+1; register tlim = toksize; while (alphanum(*tp++=getchr())) if (--tlim<=0) error2("more than %d chars in word", toksize); putbak(*--tp); *tp = EOS; if (((struct nlist *)(*((struct nlist **)Ap)=lookup(token)))->def) { if (++Ap >= astklm) { --Ap; error2(astkof,stksize); } if (Cp++==NULL) Cp = callst; Cp->argp = Ap; *Ap++ = op; puttok(token); stkchr(EOS); t = getchr(); putbak(t); if (t!='(') pbstr("()"); else /* try to fix arg count */ *Ap++ = op; Cp->plev = 0; } else { puttok(token); } } else if (match(t,lquote)) { register qlev = 1; for (;;) { token[0] = t = getchr(); token[1] = EOS; if (match(t,rquote)) { if (--qlev > 0) puttok(token); else break; } else if (match(t,lquote)) { ++qlev; puttok(token); } else { if (t==EOF) error("EOF in quote"); putchr(t); } } } else if (match(t,lcom)) { puttok(token); for (;;) { token[0] = t = getchr(); token[1] = EOS; if (match(t,rcom)) { puttok(token); break; } else { if (t==EOF) error("EOF in comment"); putchr(t); } } } else if (Cp==NULL) { putchr(t); } else if (t=='(') { if (Cp->plev) stkchr(t); else { /* skip white before arg */ while (isspace(t=getchr())) ; putbak(t); } ++Cp->plev; } else if (t==')') { --Cp->plev; if (Cp->plev==0) { stkchr(EOS); expand(Cp->argp,Ap-Cp->argp-1); op = *Cp->argp; Ap = Cp->argp-1; if (--Cp < callst) Cp = NULL; } else stkchr(t); } else if (t==',' && Cp->plev<=1) { stkchr(EOS); *Ap = op; if (++Ap >= astklm) { --Ap; error2(astkof,stksize); } while (isspace(t=getchr())) ; putbak(t); } else stkchr(t); } if (Cp!=NULL) error("EOF in argument list"); delexit(OK); } char * inpmatch(s) register char *s; { register char *tp = token+1; while (*s) { *tp = getchr(); if (*tp++ != *s++) { *tp = EOS; pbstr(token+1); return 0; } } *tp = EOS; return token; } getflags(xargc,xargv) register int *xargc; register char ***xargv; { while (*xargc > 1) { register char *arg = (*xargv)[1]; if (arg[0]!='-' || arg[1]==EOS) break; switch (arg[1]) { case 'B': bufsize = atoi(&arg[2]); break; case 'D': { register char *t; char *s[2]; initalloc(); for (t = s[0] = &arg[2]; *t; t++) if (*t=='=') { *t++ = EOS; break; } s[1] = t; dodef(&s[-1],2); break; } case 'H': hshsize = atoi(&arg[2]); break; case 'S': stksize = atoi(&arg[2]); break; case 'T': toksize = atoi(&arg[2]); break; case 'U': { char *s[1]; initalloc(); s[0] = &arg[2]; doundef(&s[-1],1); break; } case 'e': setbuf(stdout,NULL); signal(SIGINT,SIG_IGN); break; case 's': /* turn on line sync */ sflag = 1; break; default: fprintf(stderr,"%s: bad option: %s\n", procnam,arg); delexit(NOT_OK); } (*xargv)++; --(*xargc); } return; } initalloc() { static done = 0; register t; if (done++) return; hshtab = (struct nlist **)xcalloc(hshsize,sizeof(struct nlist *)); callst = (struct call *)xcalloc(stksize/3+1,sizeof(struct call)); Ap = argstk = (char **)xcalloc(stksize+3,sizeof(char *)); ipstk[0] = ipflr = ip = ibuf = xcalloc(bufsize+1,sizeof(char)); op = obuf = xcalloc(bufsize+1,sizeof(char)); token = xcalloc(toksize+1,sizeof(char)); astklm = &argstk[stksize]; ibuflm = &ibuf[bufsize]; obuflm = &obuf[bufsize]; toklm = &token[toksize]; for (t=0; barray[t].bname; ++t) { static char p[2] = {0, EOS}; p[0] = t|~LOW7; install(barray[t].bname,p,NOPUSH); } install("unix",nullstr,NOPUSH); } /*struct nlist * */ install(nam,val,mode) char *nam; register char *val; { register struct nlist *np; register char *cp; int l; if (mode==PUSH) lookup(nam); /* lookup sets hshval */ else while (undef(nam)) /* undef calls lookup */ ; np = (struct nlist *)xcalloc(1,sizeof(*np)); np->name = copy(nam); np->next = hshtab[hshval]; hshtab[hshval] = np; cp = xcalloc((l=strlen(val))+1,sizeof(*val)); np->def = cp; cp = &cp[l]; while (*val) *--cp = *val++; } struct nlist * lookup(str) char *str; { register char *s1, *s2; register struct nlist *np; static struct nlist nodef; s1 = str; for (hshval = 0; *s1; ) hshval += *s1++; hshval %= hshsize; for (np = hshtab[hshval]; np!=NULL; np = np->next) { s1 = str; s2 = np->name; while (*s1++==*s2) if (*s2++==EOS) return(np); } return(&nodef); } expand(a1,c) char **a1; { register char *dp; register struct nlist *sp; sp = (struct nlist *)a1[-1]; if (sp->tflag || trace) { int i; fprintf(stderr,"Trace(%d): %s",Cp-callst,a1[0]); if (c > 0) { fprintf(stderr,"(%s",chkbltin(a1[1])); for (i=2; i<=c; ++i) fprintf(stderr,",%s",chkbltin(a1[i])); fprintf(stderr,")"); } fprintf(stderr,"\n"); } dp = sp->def; for (; *dp; ++dp) { if (*dp&~LOW7) { (*barray[*dp&LOW7].bfunc)(a1,c); } else if (dp[1]=='$') { if (isdigit(*dp)) { register n; if ((n = *dp-'0') <= c) pbstr(a1[n]); ++dp; } else if (*dp=='#') { pbnum((long) c); ++dp; } else if (*dp=='*' || *dp=='@') { register i = c; char **a = a1; if (i > 0) for (;;) { if (*dp=='@') pbstr(rquote); pbstr(a[i--]); if (*dp=='@') pbstr(lquote); if (i <= 0) break; pbstr(","); } ++dp; } else putbak(*dp); } else putbak(*dp); } } setfname(s) register char *s; { strcpy(fname[ifx],s); fname[ifx+1] = fname[ifx]+strlen(s)+1; fline[ifx] = 1; nflag = 1; lnsync(stdout); } lnsync(iop) register FILE *iop; { static int cline = 0; static int cfile = 0; if (!sflag || iop!=stdout) return; if (nflag || ifx!=cfile) { nflag = 0; cfile = ifx; fprintf(iop,"#line %d \"",cline = fline[ifx]); fpath(iop); fprintf(iop,"\"\n"); } else if (++cline != fline[ifx]) fprintf(iop,"#line %d\n",cline = fline[ifx]); } fpath(iop) register FILE *iop; { register i; fprintf(iop,"%s",fname[0]); for (i=1; i<=ifx; ++i) fprintf(iop,":%s",fname[i]); } catchsig() { signal(SIGHUP,SIG_IGN); signal(SIGINT,SIG_IGN); delexit(NOT_OK); } delexit(code) { register i; cf = stdout; /* if (ofx != 0) { /* quitting in middle of diversion */ /* ofx = 0; /* code = NOT_OK; /* } */ ofx = 0; /* ensure that everything comes out */ for (i=1; i<10; i++) undiv(i,code); tempname[7] = 'a'; unlink(tempname); if (code==OK) exit(code); _exit(code); } puttok(tp) register char *tp; { if (Cp) { while (*tp) stkchr(*tp++); } else if (cf) while (*tp) sputchr(*tp++,cf); } pbstr(str) register char *str; { register char *p; p = str; while (*p++) ; --p; while (p > str) putbak(*--p); } undiv(i,code) register i; { register FILE *fp; register c; if (i<1 || i>9 || i==ofx || !ofile[i]) return; fclose(ofile[i]); tempname[7] = 'a'+i; if (code==OK && cf) { fp = xfopen(tempname,"r"); while ((c=getc(fp)) != EOF) sputchr(c,cf); fclose(fp); } unlink(tempname); ofile[i] = NULL; } char *copy(s) register char *s; { register char *p, *s1; p = s1 = xcalloc(strlen(s)+1,1); while (*s1++ = *s++) ; return(p); } pbnum(num) long num; { pbnbr(num,10,1); } pbnbr(nbr,base,len) long nbr; register base, len; { register neg = 0; if (base<=0) return; if (nbr<0) { neg = 1; nbr = -nbr; } while (nbr>0) { int i; if (base>1) { i = nbr%base; nbr /= base; } else { i = 1; --nbr; } putbak(itochr(i)); --len; } while (--len >= 0) putbak('0'); if (neg) putbak('-'); } itochr(i) register i; { if (i>9) return i-10+'A'; else return i+'0'; } long ctol(str) register char *str; { register sign; long num; while (isspace(*str)) ++str; num = 0; if (*str=='-') { sign = -1; ++str; } else sign = 1; while (isdigit(*str)) num = num*10 + *str++ - '0'; return(sign * num); } min(a,b) { if (a>b) return(b); return(a); } FILE * xfopen(name,mode) char *name, *mode; { FILE *fp; if ((fp=fopen(name,mode))==NULL) error(badfile); return fp; } char * xcalloc(nbr,size) { register char *ptr; if ((ptr=calloc(nbr,size)) == NULL) error(nocore); return ptr; } error(str) char *str; { fprintf(stderr,"\n%s:",procnam); fpath(stderr); fprintf(stderr,":%d %s\n",fline[ifx],str); if (Cp) { register struct call *mptr; /* fix limit */ *op = EOS; (Cp+1)->argp = Ap+1; for (mptr=callst; mptr<=Cp; ++mptr) { register char **aptr, **lim; aptr = mptr->argp; lim = (mptr+1)->argp-1; if (mptr==callst) fputs(*aptr,stderr); ++aptr; fputs("(",stderr); if (aptr < lim) for (;;) { fputs(*aptr++,stderr); if (aptr >= lim) break; fputs(",",stderr); } } while (--mptr >= callst) fputs(")",stderr); fputs("\n",stderr); } delexit(NOT_OK); } error2(str,num) char *str; int num; { char buf[500]; fprintf(buf,str,num); error(buf); } char * chkbltin(s) char *s; { static char buf[24]; if (*s&~LOW7) { sprintf(buf,"<%s>",barray[*s&LOW7].bname); return buf; } return s; } //GO.SYSIN DD * echo unbundling m4.h 1>&2 cat >m4.h <<'//GO.SYSIN DD *' #define EOS '\0' #define LOW7 0177 #define MAXSYM 5 #define PUSH 1 #define NOPUSH 0 #define OK 0 #define NOT_OK 1 #define SPACE 1 #define DIG 2 #define ALPH 4 #define isspace(c) (type[c]&SPACE) #define isdigit(c) (type[c]&DIG) #define isalpha(c) (type[c]&ALPH) #define alphanum(c) (type[c]&(ALPH|DIG)) #define getchr() (ip>ipflr?*--ip:\ ((C=(feof(ifile[ifx])?EOF:getc(ifile[ifx])))=='\n'?(fline[ifx]++,C):C)) #define putbak(c) (ip < ibuflm? (*ip++ = (c)): error(pbmsg,bufsize)) #define stkchr(c) (op < obuflm? (*op++ = (c)): error(aofmsg,bufsize)) #define sputchr(c,f) (putc(c,f)=='\n'? lnsync(f): 0) #define putchr(c) (Cp?stkchr(c):cf?(sflag?sputchr(c,cf):putc(c,cf)):0) struct bs { int (*bfunc)(); char *bname; }; struct call { char **argp; int plev; }; struct nlist { char *name; char *def; char tflag; struct nlist *next; }; extern FILE *cf; extern FILE *ifile[]; extern FILE *ofile[]; extern FILE *xfopen(); extern char **Ap; extern char **argstk; extern char *Wrapstr; extern char **astklm; extern char *calloc(); extern char *copy(); extern char *fname[]; extern char *ibuf; extern char *ibuflm; extern char *ip; extern char *ipflr; extern char *ipstk[10]; extern char *obuf; extern char *obuflm; extern char *op; extern char *procnam; extern char *tempname; extern char *token; extern char *toklm; extern char aofmsg[]; extern char astkof[]; extern char badfile[]; extern char fnbuf[]; extern char lcom[]; extern char lquote[]; extern char nocore[]; extern char nullstr[]; extern char pbmsg[]; extern char rcom[]; extern char rquote[]; extern char type[]; extern int C; extern int bufsize; extern int catchsig(); extern int fline[]; extern int hshsize; extern int hshval; extern int ifx; extern int nflag; extern int ofx; extern int pid; extern int sflag; extern int stksize; extern int sysrval; extern int toksize; extern int trace; extern long ctol(); extern struct bs barray[]; extern struct call *Cp; extern struct call *callst; extern struct nlist **hshtab; /*extern struct nlist *install(); */ extern struct nlist *lookup(); extern char *inpmatch(); extern char *chkbltin(); extern char *mktemp(); //GO.SYSIN DD * echo unbundling m4ext.c 1>&2 cat >m4ext.c <<'//GO.SYSIN DD *' #include <stdio.h> #include "m4.h" /* storage params */ int hshsize = 199; /* hash table size (prime) */ int bufsize = 4096; /* pushback & arg text buffers */ int stksize = 100; /* call stack */ int toksize = 512; /* biggest word ([a-z_][a-z0-9_]*) */ /* pushback buffer */ char *ibuf; /* buffer */ char *ibuflm; /* highest buffer addr */ char *ip; /* current position */ char *ipflr; /* buffer floor */ char *ipstk[10]; /* stack for "ipflr"s */ /* arg collection buffer */ char *obuf; /* buffer */ char *obuflm; /* high address */ char *op; /* current position */ /* call stack */ struct call *callst; /* stack */ struct call *Cp = NULL; /* position */ /* token storage */ char *token; /* buffer */ char *toklm; /* high addr */ /* file name and current line storage for line sync and diagnostics */ char fnbuf[200]; /* holds file name strings */ char *fname[11] = {fnbuf}; /* file name ptr stack */ int fline[10]; /* current line nbr stack */ /* input file stuff for "include"s */ FILE *ifile[10] = {stdin}; /* stack */ int ifx; /* stack index */ /* stuff for output diversions */ FILE *cf = stdout; /* current output file */ FILE *ofile[11] = {stdout}; /* output file stack */ int ofx; /* stack index */ /* comment markers */ char lcom[MAXSYM+1] = "#"; char rcom[MAXSYM+1] = "\n"; /* quote markers */ char lquote[MAXSYM+1] = "`"; char rquote[MAXSYM+1] = "'"; /* argument ptr stack */ char **argstk; char **astklm; /* high address */ char **Ap; /* current position */ /* symbol table */ struct nlist **hshtab; /* hash table */ int hshval; /* last hash val */ /* misc */ char *procnam; /* argv[0] */ char *tempname; /* used for diversion files */ char *Wrapstr; /* last pushback string for "m4wrap" */ char nullstr[] = ""; int C; /* see "m4.h" macros */ int nflag = 1; /* name flag, used for line sync code */ int sflag; /* line sync flag */ int sysrval; /* return val from syscmd */ int trace; /* global trace flag */ char aofmsg[] = "more than %d chars of argument text"; char astkof[] = "more than %d items on argument stack"; char badfile[] = "can't open file"; char nocore[] = "out of storage"; char pbmsg[] = "pushed back more than %d chars"; /* char map */ char type[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, SPACE, SPACE, SPACE, SPACE, SPACE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, SPACE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, DIG, DIG, DIG, DIG, DIG, DIG, DIG, DIG, DIG, DIG, 0, 0, 0, 0, 0, 0, 0, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, 0, 0, 0, 0, ALPH, 0, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, 0, 0, 0, 0, 0, }; //GO.SYSIN DD * echo unbundling m4macs.c 1>&2 cat >m4macs.c <<'//GO.SYSIN DD *' #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include "m4.h" #define arg(n) (c<(n)? nullstr: ap[n]) dochcom(ap,c) char **ap; { register char *l = arg(1); register char *r = arg(2); if (strlen(l)>MAXSYM || strlen(r)>MAXSYM) error2("comment marker longer than %d chars",MAXSYM); strcpy(lcom,l); strcpy(rcom,*r?r:"\n"); } docq(ap,c) register char **ap; { register char *l = arg(1); register char *r = arg(2); if (strlen(l)>MAXSYM || strlen(r)>MAXSYM) error2("quote marker longer than %d chars", MAXSYM); if (c<=1 && !*l) { l = "`"; r = "'"; } else if (c==1) { r = l; } strcpy(lquote,l); strcpy(rquote,r); } dodecr(ap,c) char **ap; { pbnum(ctol(arg(1))-1); } dodef(ap,c) char **ap; { def(ap,c,NOPUSH); } def(ap,c,mode) register char **ap; { register char *s; if (c<1) return; s = ap[1]; if (isalpha(*s)) while (alphanum(*++s)) ; if (*s || s==ap[1]) error("bad macro name"); if (strcmp(ap[1],ap[2])==0) error("macro defined as itself"); install(ap[1],arg(2),mode); } dodefn(ap,c) register char **ap; register c; { register char *d; while (c > 0) if ((d = lookup(ap[c--])->def) != NULL) { putbak(*rquote); while (*d) putbak(*d++); putbak(*lquote); } } dodiv(ap,c) register char **ap; { register int f; f = atoi(arg(1)); if (f>=10 || f<0) { cf = NULL; ofx = f; return; } tempname[7] = 'a'+f; if (ofile[f] || (ofile[f]=xfopen(tempname,"w"))) { ofx = f; cf = ofile[f]; } } dodivnum(ap,c) { pbnum((long) ofx); } dodnl(ap,c) char *ap; { register t; while ((t=getchr())!='\n' && t!=EOF) ; } dodump(ap,c) char **ap; { register struct nlist *np; register i; if (c > 0) while (c--) { if ((np = lookup(*++ap))->name != NULL) dump(np->name,np->def); } else for (i=0; i<hshsize; i++) for (np=hshtab[i]; np!=NULL; np=np->next) dump(np->name,np->def); } dump(name,def) register char *name, *def; { register char *s = def; fprintf(stderr,"%s:\t",name); while (*s++) ; --s; while (s>def) if (*--s&~LOW7) fprintf(stderr,"<%s>",barray[*s&LOW7].bname); else fputc(*s,stderr); fputc('\n',stderr); } doerrp(ap,c) char **ap; { if (c > 0) fprintf(stderr,"%s",ap[1]); } long evalval; /* return value from yacc stuff */ char *pe; /* used by grammar */ doeval(ap,c) char **ap; { register base = atoi(arg(2)); register pad = atoi(arg(3)); evalval = 0; if (c > 0) { pe = ap[1]; if (yyparse()!=0) error("invalid expression"); } pbnbr(evalval, base>0?base:10, pad>0?pad:1); } doexit(ap,c) char **ap; { delexit(atoi(arg(1))); } doif(ap,c) register char **ap; { if (c < 3) return; while (c >= 3) { if (strcmp(ap[1],ap[2])==0) { pbstr(ap[3]); return; } c -= 3; ap += 3; } if (c > 0) pbstr(ap[1]); } doifdef(ap,c) char **ap; { if (c < 2) return; while (c >= 2) { if (lookup(ap[1])->name != NULL) { pbstr(ap[2]); return; } c -= 2; ap += 2; } if (c > 0) pbstr(ap[1]); } doincl(ap,c) char **ap; { incl(ap,c,1); } incl(ap,c,noisy) register char **ap; { if (c>0 && strlen(ap[1])>0) { if (ifx >= 9) error("input file nesting too deep (9)"); if ((ifile[++ifx]=fopen(ap[1],"r"))==NULL){ --ifx; if (noisy) error(badfile); } else { ipstk[ifx] = ipflr = ip; setfname(ap[1]); } } } doincr(ap,c) char **ap; { pbnum(ctol(arg(1))+1); } doindex(ap,c) char **ap; { register char *subj = arg(1); register char *obj = arg(2); register i; for (i=0; *subj; ++i) if (leftmatch(subj++,obj)) { pbnum( (long) i ); return; } pbnum( (long) -1 ); } leftmatch(str,substr) register char *str; register char *substr; { while (*substr) if (*str++ != *substr++) return (0); return (1); } dolen(ap,c) char **ap; { pbnum((long) strlen(arg(1))); } domake(ap,c) char **ap; { if (c > 0) pbstr(mktemp(ap[1])); } dopopdef(ap,c) char **ap; { register i; for (i=1; i<=c; ++i) undef(ap[i]); } dopushdef(ap,c) char **ap; { def(ap,c,PUSH); } doshift(ap,c) register char **ap; register c; { if (c <= 1) return; for (;;) { pbstr(rquote); pbstr(ap[c--]); pbstr(lquote); if (c <= 1) break; pbstr(","); } } dosincl(ap,c) char **ap; { incl(ap,c,0); } dosubstr(ap,c) register char **ap; { char *str; int inlen, outlen; register offset, ix; inlen = strlen(str=arg(1)); offset = atoi(arg(2)); if (offset<0 || offset>=inlen) return; outlen = c>=3? atoi(ap[3]): inlen; ix = min(offset+outlen,inlen); while (ix > offset) putbak(str[--ix]); } dosyscmd(ap,c) char **ap; { sysrval = 0; if (c > 0) { fflush(stdout); sysrval = system(ap[1]); } } dosysval(ap,c) char **ap; { pbnum((long) (sysrval>>8)); } dotransl(ap,c) char **ap; { char *sink, *fr, *sto; register char *source, *to; if (c<1) return; sink = ap[1]; fr = arg(2); sto = arg(3); for (source = ap[1]; *source; source++) { register char *i; to = sto; for (i = fr; *i; ++i) { if (*source==*i) break; if (*to) ++to; } if (*i) { if (*to) *sink++ = *to; } else *sink++ = *source; } *sink = EOS; pbstr(ap[1]); } dotroff(ap,c) register char **ap; { register struct nlist *np; trace = 0; while (c > 0) if ((np=lookup(ap[c--]))->name) np->tflag = 0; } dotron(ap,c) register char **ap; { register struct nlist *np; trace = !*arg(1); while (c > 0) if ((np=lookup(ap[c--]))->name) np->tflag = 1; } doundef(ap,c) char **ap; { register i; for (i=1; i<=c; ++i) while (undef(ap[i])) ; } undef(nam) char *nam; { register struct nlist *np, *tnp; if ((np=lookup(nam))->name==NULL) return 0; tnp = hshtab[hshval]; /* lookup sets hshval */ if (tnp==np) /* it's in first place */ hshtab[hshval] = tnp->next; else { while (tnp->next != np) tnp = tnp->next; tnp->next = np->next; } cfree(np->name); cfree(np->def); cfree((char *)np); return 1; } doundiv(ap,c) register char **ap; { register int i; if (c<=0) for (i=1; i<10; i++) undiv(i,OK); else while (--c >= 0) undiv(atoi(*++ap),OK); } dowrap(ap,c) char **ap; { register char *a = arg(1); extern char *xcalloc(); if (Wrapstr) cfree(Wrapstr); Wrapstr = xcalloc(strlen(a)+1,sizeof(char)); strcpy(Wrapstr,a); } struct bs barray[] = { dochcom, "changecom", docq, "changequote", dodecr, "decr", dodef, "define", dodefn, "defn", dodiv, "divert", dodivnum, "divnum", dodnl, "dnl", dodump, "dumpdef", doerrp, "errprint", doeval, "eval", doexit, "m4exit", doif, "ifelse", doifdef, "ifdef", doincl, "include", doincr, "incr", doindex, "index", dolen, "len", domake, "maketemp", dopopdef, "popdef", dopushdef, "pushdef", doshift, "shift", dosincl, "sinclude", dosubstr, "substr", dosyscmd, "syscmd", dosysval, "sysval", dotransl, "translit", dotroff, "traceoff", dotron, "traceon", doundef, "undefine", doundiv, "undivert", dowrap, "m4wrap", 0, 0 }; //GO.SYSIN DD * echo unbundling y.tab.c 1>&2 cat >y.tab.c <<'//GO.SYSIN DD *' # line 2 "m4y.y" extern long evalval; #define YYSTYPE long # define DIGITS 257 # define OROR 258 # define ANDAND 259 # define GT 260 # define GE 261 # define LT 262 # define LE 263 # define NE 264 # define EQ 265 # define POWER 266 # define UMINUS 267 #define yyclearin yychar = -1 #define yyerrok yyerrflag = 0 extern int yychar; extern short yyerrflag; #ifndef YYMAXDEPTH #define YYMAXDEPTH 150 #endif #ifndef YYSTYPE #define YYSTYPE int #endif YYSTYPE yylval, yyval; # define YYERRCODE 256 # line 48 "m4y.y" extern char *pe; yylex() { while (*pe==' ' || *pe=='\t' || *pe=='\n') pe++; switch(*pe) { case '\0': case '+': case '-': case '/': case '%': case '^': case '~': case '(': case ')': return(*pe++); case '*': return(peek('*', POWER, '*')); case '>': return(peek('=', GE, GT)); case '<': return(peek('=', LE, LT)); case '=': return(peek('=', EQ, EQ)); case '|': return(peek('|', OROR, '|')); case '&': return(peek('&', ANDAND, '&')); case '!': return(peek('=', NE, '!')); default: { register base; evalval = 0; if (*pe == '0') { if (*++pe=='x' || *pe=='X') { base = 16; ++pe; } else base = 8; } else base = 10; for (;;) { register c, dig; c = *pe; if (c>='0' && c<='9') dig = c - '0'; else if (c>='a' && c<='f') dig = c - 'a' + 10; else if (c>='A' && c<='F') dig = c - 'A' + 10; else break; evalval = evalval*base + dig; ++pe; } return(DIGITS); } } } peek(c, r1, r2) { if (*++pe != c) return(r2); ++pe; return(r1); } yyerror() {;} short yyexca[] ={ -1, 1, 0, -1, -2, 0, -1, 33, 260, 0, 261, 0, 262, 0, 263, 0, 264, 0, 265, 0, -2, 7, -1, 34, 260, 0, 261, 0, 262, 0, 263, 0, 264, 0, 265, 0, -2, 8, -1, 35, 260, 0, 261, 0, 262, 0, 263, 0, 264, 0, 265, 0, -2, 9, -1, 36, 260, 0, 261, 0, 262, 0, 263, 0, 264, 0, 265, 0, -2, 10, -1, 37, 260, 0, 261, 0, 262, 0, 263, 0, 264, 0, 265, 0, -2, 11, -1, 38, 260, 0, 261, 0, 262, 0, 263, 0, 264, 0, 265, 0, -2, 12, }; # define YYNPROD 26 # define YYLAST 294 short yyact[]={ 24, 18, 25, 1, 48, 22, 20, 0, 21, 0, 23, 24, 18, 0, 0, 0, 22, 20, 0, 21, 0, 23, 24, 18, 0, 0, 24, 22, 20, 0, 21, 22, 23, 24, 18, 0, 23, 0, 22, 20, 0, 21, 0, 23, 24, 18, 0, 0, 0, 22, 20, 0, 21, 24, 23, 0, 0, 19, 22, 20, 0, 21, 0, 23, 24, 0, 3, 0, 19, 22, 20, 0, 21, 5, 23, 0, 7, 0, 6, 19, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 2, 0, 0, 0, 26, 27, 28, 29, 30, 17, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 10, 13, 14, 15, 16, 12, 11, 25, 0, 0, 9, 10, 13, 14, 15, 16, 12, 11, 25, 0, 0, 0, 10, 13, 14, 15, 16, 12, 11, 25, 0, 0, 0, 25, 13, 14, 15, 16, 12, 11, 25, 0, 0, 0, 0, 13, 14, 15, 16, 12, 11, 25, 0, 0, 13, 14, 15, 16, 12, 11, 25, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 25 }; short yypact[]={ 33,-1000, -26, 33, 33, 33, 33, 33,-1000, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 16, 16, -37,-1000, -1000, -15, -4, 27, 27, 27, 27, 27, 27, 7, 16, 7, -11, -11,-264,-264,-264,-264,-1000 }; short yypgo[]={ 0, 3, 111 }; short yyr1[]={ 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; short yyr2[]={ 0, 1, 0, 3, 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1 }; short yychk[]={ -1000, -1, -2, 33, 126, 40, 45, 43, 257, 258, 259, 265, 264, 260, 261, 262, 263, 124, 38, 94, 43, 45, 42, 47, 37, 266, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 41 }; short yydef[]={ 2, -2, 1, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 0, 23, 24, 3, 4, -2, -2, -2, -2, -2, -2, 13, 14, 15, 16, 17, 18, 19, 20, 22, 21 }; # ifdef YYDEBUG # include "y.debug" # endif # define YYFLAG -1000 # define YYERROR goto yyerrlab # define YYACCEPT return(0) # define YYABORT return(1) /* parser for yacc output */ #ifdef YYDEBUG int yydebug = 0; /* 1 for debugging */ #endif YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */ int yychar = -1; /* current input token number */ int yynerrs = 0; /* number of errors */ short yyerrflag = 0; /* error recovery flag */ yyparse() { short yys[YYMAXDEPTH]; int yyj, yym; register YYSTYPE *yypvt; register int yystate, yyn; register short *yyps; register YYSTYPE *yypv; register short *yyxi; yystate = 0; yychar = -1; yynerrs = 0; yyerrflag = 0; yyps= &yys[-1]; yypv= &yyv[-1]; yystack: /* put a state and value onto the stack */ #ifdef YYDEBUG if(yydebug >= 3) if(yychar < 0 || yytoknames[yychar] == 0) printf("char %d in %s", yychar, yystates[yystate]); else printf("%s in %s", yytoknames[yychar], yystates[yystate]); #endif if( ++yyps >= &yys[YYMAXDEPTH] ) { yyerror( "yacc stack overflow" ); return(1); } *yyps = yystate; ++yypv; *yypv = yyval; yynewstate: yyn = yypact[yystate]; if(yyn <= YYFLAG) goto yydefault; /* simple state */ if(yychar<0) { yychar = yylex(); #ifdef YYDEBUG if(yydebug >= 2) { if(yychar <= 0) printf("lex EOF\n"); else if(yytoknames[yychar]) printf("lex %s\n", yytoknames[yychar]); else printf("lex (%c)\n", yychar); } #endif if(yychar < 0) yychar = 0; } if((yyn += yychar) < 0 || yyn >= YYLAST) goto yydefault; if( yychk[ yyn=yyact[ yyn ] ] == yychar ){ /* valid shift */ yychar = -1; yyval = yylval; yystate = yyn; if( yyerrflag > 0 ) --yyerrflag; goto yystack; } yydefault: /* default state action */ if( (yyn=yydef[yystate]) == -2 ) { if(yychar < 0) { yychar = yylex(); #ifdef YYDEBUG if(yydebug >= 2) if(yychar < 0) printf("lex EOF\n"); else printf("lex %s\n", yytoknames[yychar]); #endif if(yychar < 0) yychar = 0; } /* look through exception table */ for(yyxi=yyexca; (*yyxi!= (-1)) || (yyxi[1]!=yystate); yyxi += 2 ) ; /* VOID */ while( *(yyxi+=2) >= 0 ){ if( *yyxi == yychar ) break; } if( (yyn = yyxi[1]) < 0 ) return(0); /* accept */ } if( yyn == 0 ){ /* error */ /* error ... attempt to resume parsing */ switch( yyerrflag ){ case 0: /* brand new error */ #ifdef YYDEBUG yyerror("syntax error\n%s", yystates[yystate]); if(yytoknames[yychar]) yyerror("saw %s\n", yytoknames[yychar]); else if(yychar >= ' ' && yychar < '\177') yyerror("saw `%c'\n", yychar); else if(yychar == 0) yyerror("saw EOF\n"); else yyerror("saw char 0%o\n", yychar); #else yyerror( "syntax error" ); #endif yyerrlab: ++yynerrs; case 1: case 2: /* incompletely recovered error ... try again */ yyerrflag = 3; /* find a state where "error" is a legal shift action */ while ( yyps >= yys ) { yyn = yypact[*yyps] + YYERRCODE; if( yyn>= 0 && yyn < YYLAST && yychk[yyact[yyn]] == YYERRCODE ){ yystate = yyact[yyn]; /* simulate a shift of "error" */ goto yystack; } yyn = yypact[*yyps]; /* the current yyps has no shift onn "error", pop stack */ #ifdef YYDEBUG if( yydebug ) printf( "error recovery pops state %d, uncovers %d\n", *yyps, yyps[-1] ); #endif --yyps; --yypv; } /* there is no state on the stack with an error shift ... abort */ yyabort: return(1); case 3: /* no shift yet; clobber input char */ #ifdef YYDEBUG if( yydebug ) { printf("error recovery discards "); if(yytoknames[yychar]) printf("%s\n", yytoknames[yychar]); else if(yychar >= ' ' && yychar < '\177') printf("`%c'\n", yychar); else if(yychar == 0) printf("EOF\n"); else printf("char 0%o\n", yychar); } #endif if( yychar == 0 ) goto yyabort; /* don't discard EOF, quit */ yychar = -1; goto yynewstate; /* try again in the same state */ } } /* reduction by production yyn */ #ifdef YYDEBUG if(yydebug) { char *s; printf("reduce %d in:\n\t", yyn); for(s = yystates[yystate]; *s; s++) { putchar(*s); if(*s == '\n' && *(s+1)) putchar('\t'); } } #endif yyps -= yyr2[yyn]; yypvt = yypv; yypv -= yyr2[yyn]; yyval = yypv[1]; yym=yyn; /* consult goto table to find next state */ yyn = yyr1[yyn]; yyj = yypgo[yyn] + *yyps + 1; if( yyj>=YYLAST || yychk[ yystate = yyact[yyj] ] != -yyn ) yystate = yyact[yypgo[yyn]]; switch(yym){ case 1: # line 19 "m4y.y" { evalval = yypvt[-0]; } break; case 2: # line 20 "m4y.y" { evalval = 0; } break; case 3: # line 23 "m4y.y" { yyval = (yypvt[-2]!=0 || yypvt[-0]!=0) ? 1 : 0; } break; case 4: # line 24 "m4y.y" { yyval = (yypvt[-2]!=0 && yypvt[-0]!=0) ? 1 : 0; } break; case 5: # line 25 "m4y.y" { yyval = yypvt[-0] == 0; } break; case 6: # line 26 "m4y.y" { yyval = ~yypvt[-0]; } break; case 7: # line 27 "m4y.y" { yyval = yypvt[-2] == yypvt[-0]; } break; case 8: # line 28 "m4y.y" { yyval = yypvt[-2] != yypvt[-0]; } break; case 9: # line 29 "m4y.y" { yyval = yypvt[-2] > yypvt[-0]; } break; case 10: # line 30 "m4y.y" { yyval = yypvt[-2] >= yypvt[-0]; } break; case 11: # line 31 "m4y.y" { yyval = yypvt[-2] < yypvt[-0]; } break; case 12: # line 32 "m4y.y" { yyval = yypvt[-2] <= yypvt[-0]; } break; case 13: # line 33 "m4y.y" { yyval = (yypvt[-2]|yypvt[-0]); } break; case 14: # line 34 "m4y.y" { yyval = (yypvt[-2]&yypvt[-0]); } break; case 15: # line 35 "m4y.y" { yyval = (yypvt[-2]^yypvt[-0]); } break; case 16: # line 36 "m4y.y" { yyval = (yypvt[-2]+yypvt[-0]); } break; case 17: # line 37 "m4y.y" { yyval = (yypvt[-2]-yypvt[-0]); } break; case 18: # line 38 "m4y.y" { yyval = (yypvt[-2]*yypvt[-0]); } break; case 19: # line 39 "m4y.y" { yyval = (yypvt[-2]/yypvt[-0]); } break; case 20: # line 40 "m4y.y" { yyval = (yypvt[-2]%yypvt[-0]); } break; case 21: # line 41 "m4y.y" { yyval = (yypvt[-1]); } break; case 22: # line 42 "m4y.y" { for (yyval=1; yypvt[-0]-->0; yyval *= yypvt[-2]); } break; case 23: # line 43 "m4y.y" { yyval = yypvt[-0]-1; yyval = -yypvt[-0]; } break; case 24: # line 44 "m4y.y" { yyval = yypvt[-0]-1; yyval = yypvt[-0]; } break; case 25: # line 45 "m4y.y" { yyval = evalval; } break; } goto yystack; /* stack new state and value */ } //GO.SYSIN DD *