From: Tom London Date: Mon, 6 Nov 1978 04:31:41 +0000 (-0500) Subject: Bell 32V development X-Git-Tag: Bell-32V~700 X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/commitdiff_plain/3242d0783d3fa62a3a64304af621b579af14548d Bell 32V development Work on file usr/src/cmd/m4/m4.c Work on file usr/src/cmd/m4/m4y.y Co-Authored-By: John Reiser Synthesized-from: 32v --- diff --git a/usr/src/cmd/m4/m4.c b/usr/src/cmd/m4/m4.c new file mode 100644 index 0000000000..3e6ce5bc52 --- /dev/null +++ b/usr/src/cmd/m4/m4.c @@ -0,0 +1,899 @@ +#include +#include + +#define ERROR NULL +#define READ "r" +#define WRITE "w" + +#define EOS 0 +int lpar = '('; +#define LPAR lpar +#define RPAR ')' +#define COMMA ',' +#define GRAVE '`' +#define ACUTE '\'' +#define LBRAK '[' +#define RBRAK ']' +#ifdef M4 +char lquote LBRAK; +char rquote RBRAK; +#endif +#ifndef M4 +char lquote = GRAVE; +char rquote = ACUTE; +#endif +#define COMMENT '#' +#define ALPH 1 +#define DIG 2 + +#define HSHSIZ 199 /* prime */ +#define STACKS 50 +#define SAVS 4096 +#define TOKS 128 + +#define putbak(c) *ip++ = c; +#define getchr() (ip>cur_ip?*--ip: getc(infile[infptr])) +#define putchr(c) if (cp==NULL) {if (curfile)putc(c,curfile);} else *op++ = c +char type[] = { + 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, + 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, +}; + +char token[TOKS]; +char eoa[] = "\0"; +struct nlist { + char *name; + char *def; + struct nlist *next; +}; + +struct nlist *hshtab[HSHSIZ]; +char ibuf[SAVS+TOKS]; +char obuf[SAVS+TOKS]; +char *op = obuf; +char *ip = ibuf; +char *ip_stk[10] = {ibuf}; +char *cur_ip = ibuf; +struct call { + char **argp; + int plev; +}; +struct call *cp = NULL; + +char *makeloc; +char *ifdefloc; +char *lenloc; +char *undefloc; +char *shiftloc; +char *cqloc; +char *defloc; +char *evaloc; +char *incrloc; +char *substrloc; +char *indexloc; +char *transloc; +char *ifloc; +char *divloc; +char *divnumloc; +char *undivloc; +char *dnlloc; +char *inclloc; +char *sinclloc; +char *syscmdloc; +char *dumploc; +char *errploc; + +char *tempname; +struct nlist *lookup(); +char *install(); +char *malloc(); +char *mktemp(); +char *copy(); +long ctol(); +int hshval; +FILE *olist[11] = { stdout }; +int okret; +int curout = 0; +FILE *curfile = { stdout }; +FILE *infile[10] = { stdin }; +int infptr = 0; + +main(argc, argv) +char **argv; +{ + char *argstk[STACKS+10]; + struct call callst[STACKS]; + register char *tp, **ap; + int delexit(), catchsig(); + register t; + int i; + +#ifdef gcos +#ifdef M4 + install("GCOS", eoa); +#endif +#ifndef M4 + install("gcos", eoa); +#endif +#endif +#ifdef unix +#ifdef M4 + install("UNIX", eoa); +#endif +#ifndef M4 + install("unix", eoa); +#endif +#endif + +#ifdef M4 + makeloc = install("MAKETEMP", eoa); + ifdefloc = install("IFDEF", eoa); + lenloc = install("LEN", eoa); + undefloc = install("UNDEFINE", eoa); + shiftloc = install("SHIFT", eoa); + cqloc = install("CHANGEQUOTE", eoa); + defloc = install("DEFINE", eoa); + evaloc = install("EVAL", eoa); + inclloc = install("INCLUDE", eoa); + sinclloc = install("SINCLUDE", eoa); + syscmdloc = install("SYSCMD", eoa); + dumploc = install("DUMPDEF", eoa); + errploc = install("ERRPRINT", eoa); + incrloc = install("INCR", eoa); + substrloc = install("SUBSTR", eoa); + indexloc = install("INDEX", eoa); + transloc = install("TRANSLIT", eoa); + ifloc = install("IFELSE", eoa); + divloc = install("DIVERT", eoa); + divnumloc = install("DIVNUM", eoa); + undivloc = install("UNDIVERT", eoa); + dnlloc = install("DNL", eoa); +#endif + +#ifndef M4 + makeloc = install("maketemp", eoa); + ifdefloc = install("ifdef", eoa); + lenloc = install("len", eoa); + undefloc = install("undefine", eoa); + shiftloc = install("shift", eoa); + cqloc = install("changequote", eoa); + defloc = install("define", eoa); + evaloc = install("eval", eoa); + inclloc = install("include", eoa); + sinclloc = install("sinclude", eoa); + syscmdloc = install("syscmd", eoa); + dumploc = install("dumpdef", eoa); + errploc = install("errprint", eoa); + incrloc = install("incr", eoa); + substrloc = install("substr", eoa); + indexloc = install("index", eoa); + transloc = install("translit", eoa); + ifloc = install("ifelse", eoa); + divloc = install("divert", eoa); + divnumloc = install("divnum", eoa); + undivloc = install("undivert", eoa); + dnlloc = install("dnl", eoa); +#endif + ap = argstk; +#ifndef gcos + if (signal(SIGHUP, SIG_IGN) != SIG_IGN) + signal(SIGHUP, catchsig); + if (signal(SIGINT, SIG_IGN) != SIG_IGN) + signal(SIGINT, catchsig); + tempname = mktemp("/tmp/m4aXXXXX"); + close(creat(tempname, 0)); +#endif +#ifdef gcos + tempname = "m4.tempa"; +#endif + if (argc>1) + putbak(0); + for (;;) { + tp = token; + *tp++ = t = getchr(); + *tp = EOS; + if (t<=0) { + if (infptr > 0) { + fclose(infile[infptr]); + infptr--; + cur_ip = ip_stk[infptr]; + continue; + } + if (argc<=1) + break; + argc--; + argv++; + if (infile[infptr]!=stdin) + fclose(infile[infptr]); + if (**argv=='-') + infile[infptr] = stdin; + else if ((infile[infptr]=fopen(argv[0], READ))==ERROR) { + fprintf(stderr, "m4: file not found: %s\n", argv[0]); + delexit(); + } + continue; + } + if (type[t]==ALPH) { + while ((t=type[*tp++=getchr()])==ALPH||t==DIG); + putbak(*--tp); + *tp = EOS; + if (*ap = lookup(token)->def) { + if (++ap >= &argstk[STACKS]) { + fprintf(stderr, "m4: arg stack overflow\n"); + delexit(); + } + if (cp==NULL) + cp = callst; + else if (++cp > &callst[STACKS]) { + fprintf(stderr, "m4: call stack overflow\n"); + delexit(); + } + cp->argp = ap; + *ap++ = op; + puttok(); + *op++ = '\0'; + t = getchr(); + putbak(t); + if (t!=LPAR) { + /* if (t!=' ' && t!='\t') */ + putbak(')'); + putbak('('); + } + else /* try to fix arg count */ + *ap++ = op; + cp->plev = 0; + } else + puttok(); + } else if (t==lquote) { + i = 1; + for (;;) { + t = getchr(); + if (t==rquote) { + i--; + if (i==0) + break; + } else if (t==lquote) + i++; + else if (t<0) { + fprintf(stderr, "m4: EOF in string\n"); + delexit(); + } + putchr(t); + } + } else if (t==COMMENT) { + putbak(t); + while ((t = getchr())!='\n'&& t>=0) + if (cp==NULL) + putchr(t); + putbak(t); + } else if (cp==NULL) { + puttok(); + } else if (t==LPAR) { + if (cp->plev) + *op++ = t; + cp->plev++; + while ( (t=getchr())==' ' || t=='\t' || t=='\n') + ; /* skip leading white space during arg collection */ + putbak(t); +/* + } else if (t==' ' || t=='\t' || t=='\n') { + continue; +*/ + } else if (t==RPAR) { + cp->plev--; + if (cp->plev==0) { + *op++ = '\0'; + expand(cp->argp, ap-cp->argp-1); + op = *cp->argp; + ap = cp->argp-1; + cp--; + if (cp < callst) + cp = NULL; + } else + *op++ = t; + } else if (t==COMMA && cp->plev<=1) { + *op++ = '\0'; + *ap++ = op; + while ((t=getchr())==' ' || t=='\t' || t=='\n') + ; /* skip leading white space during arg collection */ + putbak(t); + } else + *op++ = t; + } + if (cp!=NULL) { + fprintf(stderr, "m4: unexpected EOF\n"); + delexit(); + } + okret = 1; + delexit(); +} + +catchsig() +{ + okret = 0; + delexit(); +} + +delexit() +{ + register FILE *fp; + register i, c; + + if (!okret) { + signal(SIGHUP, SIG_IGN); + signal(SIGINT, SIG_IGN); + } + for (i=1; i<10; i++) { + if (olist[i]==NULL) + continue; + fclose(olist[i]); + tempname[7] = 'a'+i; + if (okret) { + fp = fopen(tempname, READ); + while ((c = getc(fp)) > 0) + putchar(c); + fclose(fp); + } + unlink(tempname); + } + tempname[7] = 'a'; + unlink(tempname); + exit(1-okret); +} + +puttok() +{ + register char *tp; + + tp = token; + if (cp) { + if (op >= &obuf[SAVS]) { + fprintf(stderr, "m4: argument overflow\n"); + delexit(); + } + while (*tp) + *op++ = *tp++; + } else if (curfile) + while (*tp) + putc(*tp++, curfile); +} + +pbstr(str) +register char *str; +{ + register char *p; + + p = str; + while (*p++); + --p; + if (ip >= &ibuf[SAVS]) { + fprintf(stderr, "m4: pushback overflow\n"); + delexit(); + } + while (p > str) + putbak(*--p); +} + +expand(a1, c) +register char **a1; +{ + register char *dp; + register n; + + dp = a1[-1]; + if (dp==defloc) + dodef(a1, c); + else if (dp==evaloc) + doeval(a1, c); + else if (dp==inclloc) + doincl(a1, c, 1); + else if (dp==sinclloc) + doincl(a1, c, 0); + else if (dp==makeloc) + domake(a1, c); + else if (dp==syscmdloc) + dosyscmd(a1, c); + else if (dp==incrloc) + doincr(a1, c); + else if (dp==substrloc) + dosubstr(a1, c); + else if (dp==indexloc) + doindex(a1, c); + else if (dp==transloc) + dotransl(a1, c); + else if (dp==ifloc) + doif(a1, c); + else if (dp==divloc) + dodiv(a1, c); + else if (dp==divnumloc) + dodivnum(a1, c); + else if (dp==undivloc) + doundiv(a1, c); + else if (dp==dnlloc) + dodnl(a1, c); + else if (dp==dumploc) + dodump(a1, c); + else if (dp==errploc) + doerrp(a1, c); + else if (dp==lenloc) + dolen(a1, c); + else if (dp==ifdefloc) + doifdef(a1, c); + else if (dp==undefloc) + doundef(a1, c); + else if (dp==shiftloc) + doshift(a1, c); + else if (dp==cqloc) + docq(a1, c); + else { + while (*dp++); + for (dp--; dp>a1[-1]; ) { + if (--dp>a1[-1] && dp[-1]=='$') { + n = *dp-'0'; + if (n>=0 && n<=9) { + if (n <= c) + pbstr(a1[n]); + dp--; + } else + putbak(*dp); + } else + putbak(*dp); + } + } +} + +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 %= HSHSIZ; + for (np = hshtab[hshval]; np!=NULL; np = np->next) { + s1 = str; + s2 = np->name; + while (*s1++ == *s2) + if (*s2++ == EOS) + return(np); + } + return(&nodef); +} + +char *install(nam, val) +char *nam, *val; +{ + register struct nlist *np; + + if ((np = lookup(nam))->name == NULL) { + np = (struct nlist *)malloc(sizeof(*np)); + if (np == NULL) { + fprintf(stderr, "m4: no space for alloc\n"); + exit(1); + } + np->name = copy(nam); + np->def = copy(val); + np->next = hshtab[hshval]; + hshtab[hshval] = np; + return(np->def); + } + free(np->def); + np->def = copy(val); + return(np->def); +} + +doundef(ap, c) +char **ap; +{ + register struct nlist *np, *tnp; + + if (c < 1 || (np = lookup(ap[1]))->name == NULL) + return; + tnp = hshtab[hshval]; /* lookup sets hshval */ + if (tnp == np) /* it's in first place */ + hshtab[hshval] = np->next; + else { + for ( ; tnp->next != np; tnp = tnp->next) + ; + tnp->next = np->next; + } + free(np->name); + free(np->def); + free((char *)np); +} + +char *copy(s) +register char *s; +{ + register char *p, *s1; + + p = s1 = malloc((unsigned)strlen(s)+1); + if (p == NULL) { + fprintf(stderr, "m4: no space for alloc\n"); + exit(1); + } + while (*s1++ = *s++); + return(p); +} + +dodef(ap, c) +char **ap; +{ + if (c >= 2) { + if (strcmp(ap[1], ap[2]) == 0) { + fprintf(stderr, "m4: %s defined as itself\n", ap[1]); + delexit(); + } + install(ap[1], ap[2]); + } + else if (c == 1) + install(ap[1], ""); +} + +doifdef(ap, c) +char **ap; +{ + register struct nlist *np; + + if (c < 2) + return; + if (lookup(ap[1])->name != NULL) + pbstr(ap[2]); + else if (c >= 3) + pbstr(ap[3]); +} + +dolen(ap, c) +char **ap; +{ + putnum((long) strlen(ap[1])); +} + +docq(ap, c) +char **ap; +{ + if (c > 1) { + lquote = *ap[1]; + rquote = *ap[2]; + } else if (c == 1) { + lquote = rquote = *ap[1]; + } else { +#ifndef M4 + lquote = GRAVE; + rquote = ACUTE; +#endif +#ifdef M4 + lquote = LBRAK; + rquote = RBRAK; +#endif + } +} + +doshift(ap, c) +char **ap; +{ + fprintf(stderr, "m4: shift not yet implemented\n"); +} + +dodump(ap, c) +char **ap; +{ + int i; + register struct nlist *np; + + if (c > 0) + while (c--) { + if ((np = lookup(*++ap))->name != NULL) + fprintf(stderr, "`%s' `%s'\n", np->name, np->def); + } + else + for (i=0; inext) + fprintf(stderr, "`%s' `%s'\n", np->name, np->def); +} + +doerrp(ap, c) +char **ap; +{ + if (c > 0) { + fprintf(stderr, ap[1], ap[2], ap[3], ap[4], ap[5], ap[6]); + fprintf(stderr, "\n"); + } +} + + +long evalval; /* return value from yacc stuff */ +char *pe; /* used by grammar */ + +doeval(ap, c) +char **ap; +{ + + if (c > 0) { + pe = ap[1]; + if (yyparse() == 0) + putnum(evalval); + else + fprintf(stderr, "m4: invalid expression in eval: %s\n", ap[1]); + } +} + +doincl(ap, c, noisy) +char **ap; +{ + if (c > 0 && strlen(ap[1]) > 0) { + infptr++; + ip_stk[infptr] = cur_ip = ip; + if ((infile[infptr] = fopen(ap[1], READ))==ERROR) { + if (noisy) { + fprintf(stderr, "m4: file not found: %s\n", ap[1]); + delexit(); + } + else + infptr--; + } + } +} + +dosyscmd(ap, c) +char **ap; +{ + if (c > 0) + system(ap[1]); +} + +domake(ap, c) +char **ap; +{ + if (c > 0) + pbstr(mktemp(ap[1])); +} + +doincr(ap, c) +char **ap; +{ + if (c >= 1) + putnum(ctol(ap[1])+1); +} + +putnum(num) +long num; +{ + register sign; + + sign = (num < 0) ? '-' : '\0'; + if (num < 0) + num = -num; + do { + putbak(num%10+'0'); + num = num/10; + } while (num!=0); + if (sign == '-') + putbak('-'); +} + +dosubstr(ap, c) +char **ap; +{ + int nc; + register char *sp, *fc; + + if (c<2) + return; + if (c<3) + nc = TOKS; + else + nc = ctoi(ap[3]); + fc = ap[1] + max(0, min(ctoi(ap[2]), strlen(ap[1]))); + sp = fc + min(nc, strlen(fc)); + while (sp > fc) + putbak(*--sp); +} + +doindex(ap, c) +char **ap; +{ + if (c >= 2) + putnum((long) strindex(ap[1], ap[2])); +} + +strindex(p1, p2) +char *p1, *p2; +{ + register m; + register char *s, *t, *p; + + for (p=p1; *p; p++) { + s = p; + m = 1; + for (t=p2; *t; ) + if (*t++ != *s++) + m = 0; + if (m == 1) + return(p-p1); + } + return(-1); +} + +dotransl(ap, c) +char **ap; +{ + register char *s, *fr, *to; + + if (c <= 1) return; + + if (c == 2) { + register int i; + to = ap[1]; + for (s = ap[1]; *s; s++) { + i = 0; + for (fr = ap[2]; *fr; fr++) + if (*s == *fr) { + i++; + break; + } + if (i == 0) + *to++ = *s; + } + *to = '\0'; + } + + if (c >= 3) { + for (s = ap[1]; *s; s++) + for (fr = ap[2], to = ap[3]; *fr && *to; fr++, to++) + if (*s == *fr) + *s = *to; + } + + pbstr(ap[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]); +} + +dodiv(ap, c) +register char **ap; +{ + register int f; + + if (c<1) + f = 0; + else + f = ctoi(ap[1]); + if (f>=10 || f<0) { + curfile = NULL; + return; + } + tempname[7] = 'a' + f; + if (olist[f] || (olist[f]=fopen(tempname, WRITE))) { + curout = f; + curfile = olist[f]; + } +} + +doundiv(ap, c) +char **ap; +{ + register FILE *fp; + register int i, ch; + int j; + + if (c == 0) { + for (i=1; i<10; i++) { + if (i==curout || olist[i]==NULL) + continue; + fclose(olist[i]); + tempname[7] = 'a'+i; + fp = fopen(tempname, READ); + if (curfile != NULL) + while ((ch = getc(fp)) > 0) + putc(ch, curfile); + fclose(fp); + unlink(tempname); + olist[i] = NULL; + } + + } + else { + for (j = 1; j <= c; j++) { + i = ctoi(*++ap); + if (i<1 || i>9 || i==curout || olist[i]==NULL) + continue; + fclose(olist[i]); + tempname[7] = 'a'+i; + fp = fopen(tempname, READ); + if (curfile != NULL) + while ((ch = getc(fp)) > 0) + putc(ch, curfile); + fclose(fp); + unlink(tempname); + olist[i] = NULL; + } + } +} + +dodivnum(ap, c) +char **ap; +{ + putnum((long) curout); +} + +dodnl(ap, c) +char **ap; +{ + register t; + + while ((t=getchr())!='\n' && t>=0) + ; +} + +long ctol(str) +register char *str; +{ + register sign; + long num; + + while (*str==' ' || *str=='\t' || *str=='\n') + str++; + num = 0; + if (*str == '-') { + sign = -1; + str++; + } + else + sign = 1; + while (*str>='0' && *str<='9') + num = num*10 + *str++ - '0'; + return(sign * num); +} + +ctoi(s) +char *s; +{ + return(ctol(s)); +} + +min(a, b) +{ + if (a>b) + return(b); + return(a); +} + +max(a, b) +{ + if (a>b) + return(a); + return(b); +} diff --git a/usr/src/cmd/m4/m4y.y b/usr/src/cmd/m4/m4y.y new file mode 100644 index 0000000000..40f5a3b787 --- /dev/null +++ b/usr/src/cmd/m4/m4y.y @@ -0,0 +1,94 @@ +%{ +extern long evalval; +#define YYSTYPE long +%} + +%term DIGITS +%left '|' +%left '&' +%right '!' +%nonassoc GT GE LT LE NE EQ +%left '+' '-' +%left '*' '/' '%' +%right POWER +%right UMINUS +%% + +s : e ={ evalval = $1; } + | ={ evalval = 0; } + ; + +e : e '|' e ={ $$ = ($1!=0 || $3!=0) ? 1 : 0; } + | e '&' e ={ $$ = ($1!=0 && $3!=0) ? 1 : 0; } + | '!' e ={ $$ = $2 == 0; } + | e EQ e ={ $$ = $1 == $3; } + | e NE e ={ $$ = $1 != $3; } + | e GT e ={ $$ = $1 > $3; } + | e GE e ={ $$ = $1 >= $3; } + | e LT e ={ $$ = $1 < $3; } + | e LE e ={ $$ = $1 <= $3; } + | e '+' e ={ $$ = ($1+$3); } + | e '-' e ={ $$ = ($1-$3); } + | e '*' e ={ $$ = ($1*$3); } + | e '/' e ={ $$ = ($1/$3); } + | e '%' e ={ $$ = ($1%$3); } + | '(' e ')' ={ $$ = ($2); } + | e POWER e ={ for ($$=1; $3-->0; $$ *= $1); } + | '-' e %prec UMINUS ={ $$ = $2-1; $$ = -$2; } + | '+' e %prec UMINUS ={ $$ = $2-1; $$ = $2; } + | DIGITS ={ $$ = evalval; } + ; + +%% + +yylex() { + extern char *pe; + + while (*pe==' ' || *pe=='\t' || *pe=='\n') + pe++; + switch(*pe) { + case '\0': + case '+': + case '-': + case '/': + case '%': + case '(': + case ')': + return(*pe++); + case '^': + pe++; + return(POWER); + case '*': + return(peek('*', POWER, '*')); + case '>': + return(peek('=', GE, GT)); + case '<': + return(peek('=', LE, LT)); + case '=': + return(peek('=', EQ, EQ)); + case '|': + return(peek('|', '|', '|')); + case '&': + return(peek('&', '&', '&')); + case '!': + return(peek('=', NE, '!')); + default: + evalval = 0; + while (*pe >= '0' && *pe <= '9') + evalval = evalval*10 + *pe++ - '0'; + return(DIGITS); + } +} + +peek(c, r1, r2) +{ + if (*++pe != c) + return(r2); + ++pe; + return(r1); +} + +yyerror(s) +char *s; +{ +}