Interdata_v6/usr/source/c/cpp.c
#
# 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) );
}