# # include "stdio.h" /* C command */ # define SBSIZE 10000 # define DROP (-2) # define SAME 0 # define MAXINC 10 char sbf[SBSIZE]; # define CHSPACE 1000 char ts[CHSPACE+50]; # define EXPSIZE 500 char *strdex(), *copy(), *calloc(), *token(), *coptok(); char *tsa ts; char *tsp ts; char *fnames[MAXINC]; # define LINELEN 512 FILE *fin; FILE *fout; int instring; char direct[50]; int nd 1; char *dirs[10] {direct, 0}; char nfil[100]; int pflag; int depth; int skipcom; FILE *fins[MAXINC]; int ifno; char *lp; char *line; # define NPREDEF 20 char *prespc[NPREDEF]; char **predef prespc; char *punspc[NPREDEF]; char **prund punspc; char **predp; int lineno[MAXINC]; int exfail; struct symtab { char name[8]; char *value; } *symtab, *lookup(); # define symsiz 400 struct symtab *defloc; struct symtab *udfloc; struct symtab *incloc; struct symtab *ifloc; struct symtab *elsloc; struct symtab *eifloc; struct symtab *ifdloc; struct symtab *ifnloc; struct symtab *sysloc; struct symtab *lneloc; struct symtab *prdloc; int trulvl; int flslvl; char *stringbuf; mainpp(argc,argv) char *argv[]; { int i; # ifdef tgp int ifbrk; # endif char ln[LINELEN]; register int c; register char *rlp; char *sp; static struct symtab stab[symsiz]; fin = stdin; fout = stdout; # ifdef unix fnames[ifno=0] = ""; # endif # ifdef gcos fnames[ifno=0] = "s*"; # endif # ifdef ibm fnames[ifno=0] = ""; # endif for(i=1; i<argc; i++) { switch(argv[i][0]) { case '-': switch(argv[i][1]) { case 'P': pflag++; case 'E': continue; case 'D': if (predef>prespc+NPREDEF) { error("too many -D options, ignoring %s",argv[i]); continue; } *predef++ = argv[i]+2; continue; case 'U': if (prund>punspc+NPREDEF) { error("too many -U options, ignoring %s",argv[i]); continue; } *prund++ = argv[i]+2; continue; case 'I': if (nd>8) error("excessive -I file (%s) ignored",argv[i]); else dirs[nd++] = argv[i]+2; continue; case '\0': continue; default: error("unknown flag %s", argv[i]); continue; } default: if (fin==stdin) { fin = fopen(argv[i], "r"); if (fin==NULL) { error("No source file %s",argv[i]); exit(8); } fnames[ifno]=argv[i]; strcpy(direct, argv[i]); for(sp=direct; *sp; sp++); while (sp>direct && *sp != '/') sp--; # ifdef unix if (sp==direct) *sp++ = '.'; # endif *sp=0; /* direct now has place where source file is */ } else if (fout==stdout) { fout= fopen(argv[i], "w"); if (fout==NULL) { error("Can't write %s", argv[i]); exit(8); } } else error("extraneous name %s", argv[i]); } } fins[ifno]=fin; exfail = 0; /* after user -I files here are the standard include libraries */ # ifdef unix dirs[nd++] = "/usr/include"; # endif # ifdef gcos dirs[nd++] = "cc"; # endif # ifdef ibm dirs[nd++] = "stdio."; # endif /* dirs[nd++] = "/compool"; */ dirs[nd++] = 0; symtab = stab; for (c=0; c<symsiz; c++) { stab[c].name[0] = '\0'; stab[c].value = 0; } insym(&defloc, "define"); insym(&udfloc, "undef"); insym(&incloc, "include"); insym(&elsloc, "else"); insym(&eifloc, "endif"); insym(&ifdloc, "ifdef"); insym(&ifnloc, "ifndef"); insym(&ifloc, "if"); # ifdef unix insym(&sysloc, "unix"); # endif # ifdef gcos insym (&sysloc, "gcos"); # endif # ifdef ibm insym (&sysloc, "ibm"); # endif insym(&lneloc, "line"); predp=predef; while (predp>prespc) if (sp=strdex(*--predp, '=')) { *sp++=0; stsym(*predp, sp); } else insym(&prdloc, *predp); predp=prund; while (predp>punspc) { if (sp=strdex(*--predp, '=')) *sp++=0; lookup(*predp, DROP); } stringbuf = sbf; trulvl = 0; flslvl = 0; line = ln; lineno[0] = 1; if (pflag==0) fprintf(fout, "# 1 \"%s\"\n", fnames[ifno]); while(getline()) { skipcom=0; if (ln[0] != '#' && flslvl==0) { # ifdef tgp ifbrk= checklen(line); # endif for (rlp = line; c = *rlp++;) putc(c, fout); # ifdef tgp if (ifbrk) fprintf(fout,"\n# %d",lineno[ifno]); # endif } putc('\n', fout); } # ifdef tgp checklen(line); # endif for(rlp=line; c = *rlp++;) putc(c,fout); } getline() { register int c, sc, state; struct symtab *np; char *namep, *filname, **dirp; int filok, inctype; lp = line; *lp = '\0'; state = 0; if ((c=getch()) == '#') state = 1; while (c!='\n' && c!='\0') { if (letter(c)) { namep = lp; sch(c); while (letnum(c=getch())) sch(c); sch('\0'); lp--; if (state==6) { lookup(namep, DROP); goto out; } if (state>3 && state <6) { if (flslvl==0 &&(state+!lookup(namep,-1)->name[0])==5) trulvl++; else flslvl++; out: while (c!='\n' && c!= '\0') c = getch(); return(c); } if (state==3) /* include */ if (*namep != '"' && *namep != '<') { error("Bad include syntax", 0); state=1; } if (state!=2 || flslvl==0) { pushback(c); np = lookup(namep, state); c = getch(); } if (state==1) { if (np==defloc) skipcom = state = 2; else if (np==incloc) state = 3; else if (np==ifnloc) state = 4; else if (np==ifdloc) state = 5; else if (np==eifloc) { if (flslvl) --flslvl; else if (trulvl) --trulvl; else errback("If-less endif",0); goto out; } else if (np==elsloc) { if (flslvl) --flslvl? ++flslvl : ++trulvl; else if (trulvl) {++flslvl; --trulvl;} else errback("If-less else",0); goto out; } else if (np==udfloc) { state=6; } else if (np==ifloc) { /* if (flslvl ==0 && yyparse()) */ error("IF not implemented, true assumed",0); if (1) trulvl++; else flslvl++; return('\n'); } else if (np==lneloc) { if(pflag==0) fprintf(fout, "# "); lp=line; for(; c !='\n' && c != '\0'; c=getch()) if (!pflag) sch(c); sch('\0'); return(c); } else { errback("Undefined control",0); while (c!='\n' && c!='\0') c = getch(); return(c); } } else if (state==2) { if (flslvl) goto out; np->value = stringbuf; if (c != '\n' && c != 0) { savch(c); while ((c=getch())!='\n' && c!='\0') { if (c== '\\') { c = getch(); if (c=='\n')continue; savch('\\'); } savch(c); } } savch('\0'); return(1); } continue; } else if ((sc=c) == '\'' || sc== '"' || (state==3 && sc== '<')) { sch(sc); filname = lp; inctype = sc=='<'; if (sc== '<') { /* fprintf(fout==stdout?stderr:stdout, "note: include <> obsolete, use \"\"\n"); */ sc= '>'; } instring++; while ((c=getch())!=sc && c!='\n' && c!='\0') { sch(c); if (c=='\\') sch(getch()); } instring = 0; if (flslvl) goto out; if (state==3) { if (flslvl) goto out; *lp = '\0'; while ((c=getch())!='\n' && c!='\0'); if (ifno+1 >=MAXINC) error("Unreasonable include nesting",0); filok=0; for(dirp=dirs+inctype; *dirp; dirp++) { if (filname[0]=='/' || **dirp=='\0') strcpy(nfil,filname); else { strcpy(nfil,*dirp); # ifdef unix strcat(nfil, "/"); # endif # ifdef gcos strcat(nfil, "/"); # endif # ifdef ibm strcat(nfil, "."); # endif strcat(nfil, filname); } if ( (fins[ifno+1]=fopen(nfil, "r"))!=NULL) { filok=1; fin = fins[++ifno]; break; } } if (filok==0) errback("Can't find include file %s", filname); else { if (pflag==0) fprintf(fout, "\n# 1 \"%s\"", filname); lineno[ifno]=1; fnames[ifno] = copy(filname); } return(c); } } sch(sc=c); c = getch(); if (isdigit(sc)) { for (;isalpha(c) || isdigit(c); c=getch()) sch(c); } } sch('\0'); if (state>1) errback("Control syntax",0); return(c); } insym(sp, namep) struct symtab **sp; char *namep; { register struct symtab *np; *sp = np = lookup(namep, 1); np -> value = np -> name; } stsym(namep, valp) char *namep, *valp; { register struct symtab *np; np = lookup(namep, 1); np->value = valp; } error(s, x) char *s; { FILE *efout; efout = fout==stdout ? stderr : stdout; if (fnames[ifno][0]) fprintf(efout,"%s: %d: ", fnames[ifno], lineno[ifno]); fprintf(efout, s, x); putc('\n',efout); exfail++; } errback(s,x) char *s; { lineno[ifno]--; error(s,x); lineno[ifno]++; } sch(c) { register char *rlp; rlp = lp; if (rlp==line+LINELEN-2) error("Line overflow", 0); *rlp++ = c; if (rlp>line+LINELEN-1) rlp = line+LINELEN-1; lp = rlp; } savch(c) { *stringbuf++ = c; if (stringbuf-sbf < SBSIZE) return; error("Too much defining", 0); exit(exfail); } getch() { register int c, lastst; while ((c=getc1())=='/' && !instring) { if ((c=getc1())!='*') { pushback(c); return('/'); } if (!skipcom) {putc('/',fout); putc('*', fout);} lastst=0; while ( (c = getc1()) != '\0') { if (lastst && c=='/') { if (!skipcom) putc('/', fout); break; } if (c=='\n' || !skipcom) putc(c, fout); lastst = (c=='*'); } if (c=='\0')break; } return(c); } char pushbuff[EXPSIZE]; char *pushp pushbuff; pushback(c) { *++pushp = c; if (pushp>pushbuff+EXPSIZE) { error("too much backup", 0); exit(8); } } getc1() { register c; if (*pushp !=0) return(*pushp--); depth=0; if ((c = getc(fin)) == EOF && ifno>0) { fclose(fin); fin = fins[--ifno]; if (pflag==0) fprintf(fout, "\n# %d \"%s\"\n",lineno[ifno], fnames[ifno]); c = getc1(); if (c=='\n') lineno[ifno]--; } if (c==EOF) return(0); if (c=='\n' ) lineno[ifno]++; return(c); } struct symtab * lookup(namep, enterf) char *namep; { register char *np, *snp; register struct symtab *sp; int i, c, around; np = namep; snp = np+8; around = i = 0; while ( (c = *np++ ) && (np-snp)<0) { i =+ c; } i =% symsiz; sp = &symtab[i]; while (sp->name[0]) { if (sp->name[0] != DROP) { snp = sp->name; np = namep; while (*snp++ == *np) if (*np++ == '\0' || np==namep+8) { if (enterf==DROP) { sp->name[0]= DROP; return(sp); } if (!enterf) subst(namep, sp); return(sp); } } if (++sp >= &symtab[symsiz]) if (around++) { error("too many defines", 0); exit(exfail); } else sp = symtab; } if (enterf>0) { snp = namep; for (np = &sp->name[0]; np < &sp->name[8];) if (*np++ = *snp) snp++; } return(sp); } char revbuff[200], *bp; backsch(c) { if (bp-revbuff > 200) error("Excessive define looping", bp--); *bp++ = c; } subst(np, sp) char *np; struct symtab *sp; { register char *vp; int macflg; lp = np; bp = revbuff; if (depth++>100) { error("define recursion loop on %s", np); return; } if ((vp = sp->value) == 0) return; macflg= (*vp == '('); /* arrange that define unix unix still has no effect, avoiding rescanning */ while (blank(*vp)) vp++; if (strcmp(sp->name,vp) == SAME) { while (*vp) sch(*vp++); return; } if (macflg) expdef(vp); else while (*vp) backsch(*vp++); while (bp>revbuff) pushback(*--bp); } char * copy(as) char as[]; { register char *otsp, *s; int i; otsp = tsp; s = as; while(*tsp++ = *s++); if (tsp >tsa+CHSPACE) { # ifdef unix tsp = tsa = i = calloc(CHSPACE+50,sizeof(char)); if (i== NULL) # endif { error("no space for file names", 0); exit(8); } } return(otsp); } expdef(proto) char *proto; { char buffer[EXPSIZE], *parg[20], *pval[20], name[20], *cspace, *wp; char protcop[EXPSIZE], *pr; int narg, k, c; pr = protcop; while (*pr++ = *proto++) if (pr>=protcop+EXPSIZE){ error("define prototype too big", 0); exit(8); } proto= protcop; for (narg=0; (parg[narg] = token(&proto)) != 0; narg++) ; /* now scan input */ cspace = buffer; while ((c=getch()) == ' '); if (c != '(') { error("defined function requires arguments", 0); return; } pushback(c); for(k=0; pval[k] = coptok(&cspace, buffer+EXPSIZE); k++); if (k!=narg) { error("define argument mismatch"); return; } while (c= *proto++) { if (!letter(c)) backsch(c); else { wp = name; *wp++ = c; while (letnum(*proto)) *wp++ = *proto++; *wp = 0; for (k=0; k<narg; k++) if(strcmp(name,parg[k]) == SAME) break; wp = k <narg ? pval[k] : name; while (*wp) backsch(*wp++); } } } char * token(cpp) char **cpp; { char *val; int stc; stc = **cpp; *(*cpp)++ = '\0'; if (stc==')') return(0); while (**cpp == ' ') (*cpp)++; for (val = *cpp; (stc= **cpp) != ',' && stc!= ')'; (*cpp)++) { if (!letnum(stc) || (val == *cpp && !letter(stc))) { error("define prototype argument error"); return(0); } } return(val); } char * coptok (cpp, clim) char **cpp, *clim; { char *val; int stc, stop,paren; paren = stop = 0; val = *cpp; if (getch() == ')') return(0); while (((stc = getch()) != ',' && stc != ')' ) || paren > 0 || stop >0) { if (stc == '\0') { error("non terminated macro call", 0); val = 0; break; } if (stop == 0 && (stc == '"' || stc == '\'')) stop = stc; else if (stc==stop) stop=0; if ( stc == '\\') { stc = getch(); if (stop>0 || (stc != ',' && stc != '\\')) *(*cpp)++ = '\\'; *(*cpp)++ = stc; } else { *(*cpp)++ = stc; if (stop==0) { if (stc == '(') paren++; if (stc == ')') paren--; } } if (*cpp >= clim) { error("define argument too long",0); exit(8); } } *(*cpp)++ = 0; pushback(stc); return(val); } letter(c) { if (isalpha(c) || c == '_') return (1); else return(0); } letnum(c) { if (letter(c) || isdigit(c)) return(1); else return(0); } blank(c) { return(c==' ' || c== '\t'); } char * strdex(s,c) char *s; { while (*s) if (*s==c) return(s); else s++; return(0); } # ifdef tgp # define MAXOUT 80 checklen(sln) char *sln; { /* for tgp: scans string sln, and puts in newlines for blanks, where it likes, but to make lines less than MAXOUT chars long */ char *p, *s, *st; int stopc, back, ifdone, c; st=s=sln; ifdone=p=stopc=back=0; while (c= *s++) { if (c == '\\') back=2; if (back==0) { if (stopc== c) stopc=0; else if (c == '"' || c == '\'') stopc= c; } if (back>0)back--; if (s-st >MAXOUT && p != 0) { st=p; *p= '\n'; ifdone=1; } if (stopc==0 && back==0) if (c==' ') p=s-1;; } return(ifdone); } # endif main(argc,argv) char *argv[]; { exit(mainpp (argc,argv) ); }