📄 m4.c
字号:
/* @(#)m4.c 4.2 ULTRIX 8/13/90 *//* Based on AT&T version: *//* @(#)m4.c 1.3 */#include <stdio.h>#include <signal.h>#include "m4.h"#define match(c,s) (c==*s && (!s[1] || inpmatch(s+1)))main(argc,argv)char **argv;{ register t;#ifdef gcos tempfile = "m4*tempa";#endif#ifdef unix { static sigs[] = {SIGHUP, SIGINT, SIGPIPE, 0}; for (t=0; sigs[t]; ++t) if (signal(sigs[t], SIG_IGN) != SIG_IGN) signal(sigs[t],catchsig); } tempfile = mktemp("/tmp/m4aXXXXX"); close(creat(tempfile,0));#endif/* WARNING: the following depends on the implementation of the ctype macros! */ (_pctype+1)['_'] |= _L; /* makes '_' a real live letter *//* end of warning */ 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; struct nlist *macadd; /* temp variable */ while (isalnum(*tp++ = getchr())) if (--tlim<=0) error2("more than %d chars in word", toksize); putbak(*--tp); *tp = EOS; macadd = lookup(token); *Ap = (char *) macadd; if (macadd->def) { if ((char *) (++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 ((char *) (++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':#ifdef unix setbuf(stdout,(char *) NULL); signal(SIGINT,SIG_IGN);#endif 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 = (char *) (&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); }#ifdef unix install("unix",nullstr,NOPUSH);#endif#ifdef gcos install("gcos",nullstr,NOPUSH);#endif}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; 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) { if (!strcmp(str, np->name)) 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(){#ifdef unix signal(SIGHUP,SIG_IGN); signal(SIGINT,SIG_IGN);#endif 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); tempfile[7] = 'a'; unlink(tempfile); 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; for (p = str + strlen(str); --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]); tempfile[7] = 'a'+i; if (code==OK && cf) { fp = xfopen(tempfile,"r"); while ((c=getc(fp)) != EOF) sputchr(c,cf); fclose(fp); } unlink(tempfile); ofile[i] = NULL;}char *copy(s)register char *s;{ register char *p; p = xcalloc(strlen(s)+1,sizeof(char)); strcpy(p, 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; else nbr = -nbr; while (nbr<0) { register int i; if (base>1) { i = nbr%base; nbr /= base;# if (-3 % 2) != -1 while (i > 0) { i -= base; ++nbr; }# endif i = -i; } 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((unsigned) nbr,(unsigned) size)) == NULL) error(nocore); return ptr;}error2(str,num) char *str; int num;{ char buf[500]; sprintf(buf,str,num); error(buf);}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);}char *chkbltin(s)char *s;{ static char buf[24]; if (*s&~LOW7){ sprintf(buf,"<%s>",barray[*s&LOW7].bname); return buf; } return s;}int getchr(){ if (ip > ipflr) return (*--ip); C = feof(ifile[ifx]) ? EOF : getc(ifile[ifx]); if (C =='\n') fline[ifx]++; return (C);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -