MiniUnix/usr/source/s1/cc.c
#define SBSIZE 2000
char sbf[SBSIZE];
/* C command */
char *tmp0;
char *tmp1;
char *tmp2;
char *tmp3;
char *tmp4;
char *tmp5;
char ts[1000];
char *tsp ts;
char *av[50];
char *clist[50];
char *llist[50];
int instring;
int pflag;
int sflag;
int cflag;
int oflag;
int proflag;
int depth;
int *ibuf;
int *ibuf1;
int *ibuf2;
int *obuf;
char *lp;
char *line;
int lineno;
int exfail;
struct symtab {
char name[8];
char *value;
} *symtab;
int symsiz 200;
struct symtab *defloc;
struct symtab *incloc;
struct symtab *eifloc;
struct symtab *ifdloc;
struct symtab *ifnloc;
struct symtab *unxloc;
int trulvl;
int flslvl;
char *stringbuf;
char *pass0 "/lib/c0";
char *pass1 "/lib/c1";
char *pass2 "/lib/c2";
char *pref "/lib/crt0.o";
main(argc, argv)
char *argv[]; {
char *t;
int nc, nl, i, j, c, f20, nxo;
int dexit();
i = nc = nl = f20 = nxo = 0;
while(++i < argc) {
if(*argv[i] == '-')
switch (argv[i][1]) {
default:
goto passa;
case 'S':
sflag++;
cflag++;
break;
case 'O':
oflag++;
break;
case 'p':
proflag++;
pref = "/lib/mcrt0.o";
break;
case 'P':
pflag++;
case 'c':
cflag++;
break;
case 'f':
pref = "/lib/fcrt0.o";
pass0 = "/lib/fc0";
pass1 = "/lib/fc1";
break;
case '2':
if(argv[i][2] == '\0')
pref = "/lib/crt2.o";
else {
pref = "/lib/crt20.o";
f20 = 1;
}
break;
case 't':
if (argv[i][2]=='0')
pass0 = "/usr/c/c0";
if (argv[i][2]=='1')
pass1 = "/usr/c/c1";
if (argv[i][2]=='2')
pass2 = "/usr/c/c2";
break;
}
else {
passa:
t = argv[i];
if(getsuf(t)=='c') {
clist[nc++] = t;
t = setsuf(t, 'o');
}
if (nodup(llist, t)) {
llist[nl++] = t;
if (getsuf(t)=='o')
nxo++;
}
}
}
if(nc==0)
goto nocom;
if (pflag==0) {
tmp0 = copy("/tmp/ctm0a");
while((c=open(tmp0, 0))>=0) {
close(c);
tmp0[9]++;
}
while((creat(tmp0, 0400))<0)
tmp0[9]++;
}
if ((signal(2, 1) & 01) == 0)
signal(2, &dexit);
(tmp1 = copy(tmp0))[8] = '1';
(tmp2 = copy(tmp0))[8] = '2';
(tmp3 = copy(tmp0))[8] = '3';
if (oflag)
(tmp5 = copy(tmp0))[8] = '5';
if (pflag==0)
(tmp4 = copy(tmp0))[8] = '4';
for (i=0; i<nc; i++) {
if (nc>1)
printf("%s:\n", clist[i]);
av[0] = "c0";
if (pflag)
tmp4 = setsuf(clist[i], 'i');
av[1] = expand(clist[i]);
if (pflag || exfail)
continue;
if (av[1] == 0) {
cflag++;
continue;
}
av[2] = tmp1;
av[3] = tmp2;
if (proflag) {
av[4] = "-P";
av[5] = 0;
} else
av[4] = 0;
if (callsys(pass0, av)) {
cflag++;
continue;
}
av[0] = "c1";
av[1] = tmp1;
av[2] = tmp2;
if (sflag)
tmp3 = setsuf(clist[i], 's');
av[3] = tmp3;
if (oflag)
av[3] = tmp5;
av[4] = 0;
if(callsys(pass1, av)) {
cflag++;
continue;
}
if (oflag) {
av[0] = "c2";
av[1] = tmp5;
av[2] = tmp3;
av[3] = 0;
callsys(pass2, av);
unlink(tmp5);
}
if (sflag)
continue;
av[0] = "as";
av[1] = "-";
av[2] = tmp3;
av[3] = 0;
cunlink(tmp1);
cunlink(tmp2);
cunlink(tmp4);
callsys("/bin/as", av);
t = setsuf(clist[i], 'o');
cunlink(t);
if(link("a.out", t) || cunlink("a.out")) {
printf("move failed: %s\n", t);
cflag++;
}
}
nocom:
if (cflag==0 && nl!=0) {
i = 0;
av[0] = "ld";
av[1] = "-X";
av[2] = pref;
j = 3;
while(i<nl)
av[j++] = llist[i++];
if(f20)
av[j++] = "-l2";
else {
av[j++] = "-lc";
av[j++] = "-l";
}
av[j++] = 0;
callsys("/bin/ld", av);
if (nc==1 && nxo==1)
cunlink(setsuf(clist[0], 'o'));
}
dexit();
}
dexit()
{
if (!pflag) {
cunlink(tmp1);
cunlink(tmp2);
if (sflag==0)
cunlink(tmp3);
cunlink(tmp4);
cunlink(tmp5);
cunlink(tmp0);
}
exit();
}
expand(file)
char *file;
{
int ib1[259], ib2[259], ob[259];
struct symtab stab[200];
char ln[196];
register int c;
register char *rlp;
exfail = 0;
ibuf = ibuf1 = ib1;
ibuf2 = ib2;
if (fopen(file, ibuf1)<0)
return(file);
if (getc(ibuf1) != '#') {
close(ibuf1[0]);
return(file);
}
ibuf1[1]++;
ibuf1[2]--;
obuf = ob;
symtab = stab;
for (c=0; c<200; c++) {
stab[c].name[0] = '\0';
stab[c].value = 0;
}
insym(&defloc, "define");
insym(&incloc, "include");
insym(&eifloc, "endif");
insym(&ifdloc, "ifdef");
insym(&ifnloc, "ifndef");
insym(&unxloc, "unix");
stringbuf = sbf;
trulvl = 0;
flslvl = 0;
line = ln;
lineno = 0;
if (fcreat(tmp4, obuf) < 0) {
printf("Can't creat %s\n", tmp4);
dexit();
}
while(getline()) {
if (ibuf==ibuf2 && pflag==0)
putc(001, obuf); /*SOH: insert */
if (ln[0] != '#' && flslvl==0)
for (rlp = line; c = *rlp++;)
putc(c, obuf);
putc('\n', obuf);
}
for(rlp=line; c = *rlp++;)
putc(c,obuf);
fflush(obuf);
close(obuf[0]);
close(ibuf1[0]);
return(tmp4);
}
getline()
{
register int c, sc, state;
struct symtab *np;
char *namep, *filname;
if (ibuf==ibuf1)
lineno++;
lp = line;
*lp = '\0';
state = 0;
if ((c=getch()) == '#')
state = 1;
while (c!='\n' && c!='\0') {
if ('a'<=c && c<='z' || 'A'<=c && c<='Z' || c=='_') {
namep = lp;
sch(c);
while ('a'<=(c=getch()) && c<='z'
||'A'<=c && c<='Z'
||'0'<=c && c<='9'
||c=='_')
sch(c);
sch('\0');
lp--;
if (state>3) {
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!=2 || flslvl==0)
{
ungetc(c);
np = lookup(namep, state);
c = getch();
}
if (state==1) {
if (np==defloc)
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 error("If-less endif");
goto out;
}
else {
error("Undefined control");
while (c!='\n' && c!='\0')
c = getch();
return(c);
}
} else if (state==2) {
if (flslvl)
goto out;
np->value = stringbuf;
savch(c);
while ((c=getch())!='\n' && c!='\0')
savch(c);
savch('\0');
return(1);
}
continue;
} else if ((sc=c)=='\'' || sc=='"') {
sch(sc);
filname = lp;
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 (ibuf==ibuf2)
error("Nested 'include'");
if (fopen(filname, ibuf2)<0)
error("Missing file %s", filname);
else
ibuf = ibuf2;
return(c);
}
}
sch(c);
c = getch();
}
sch('\0');
if (state>1)
error("Control syntax");
return(c);
}
insym(sp, namep)
struct symtab **sp;
char *namep;
{
register struct symtab *np;
*sp = np = lookup(namep, 1);
np->value = np->name;
}
error(s, x)
{
printf("%d: ", lineno);
printf(s, x);
putchar('\n');
exfail++;
cflag++;
}
sch(c)
{
register char *rlp;
rlp = lp;
if (rlp==line+194)
error("Line overflow");
*rlp++ = c;
if (rlp>line+195)
rlp = line+195;
lp = rlp;
}
savch(c)
{
*stringbuf++ = c;
if (stringbuf-sbf < SBSIZE)
return;
error("Too much defining");
dexit();
}
getch()
{
register int c;
loop:
if ((c=getc1())=='/' && !instring) {
if ((c=getc1())!='*')
{
ungetc(c);
return('/');
}
for(;;) {
c = getc1();
cloop:
switch (c) {
case '\0':
return('\0');
case '*':
if ((c=getc1())=='/')
goto loop;
goto cloop;
case '\n':
if (ibuf==ibuf1) {
putc('\n', obuf);
lineno++;
}
continue;
}
}
}
return(c);
}
char pushbuff[300];
char *pushp pushbuff;
ungetc(c)
{
*++pushp = c;
}
getc1()
{
register c;
if (*pushp !=0)
return(*pushp--);
depth=0;
if ((c = getc(ibuf)) < 0 && ibuf==ibuf2) {
close(ibuf2[0]);
ibuf = ibuf1;
putc('\n', obuf);
lineno++;
c = getc1();
}
if (c<0)
return(0);
return(c);
}
lookup(namep, enterf)
char *namep;
{
register char *np, *snp;
register struct symtab *sp;
int i, c, around;
np = namep;
around = i = 0;
while (c = *np++)
i =+ c;
i =% symsiz;
sp = &symtab[i];
while (sp->name[0]) {
snp = sp;
np = namep;
while (*snp++ == *np)
if (*np++ == '\0' || np==namep+8) {
if (!enterf)
subst(namep, sp);
return(sp);
}
if (++sp >= &symtab[symsiz])
if (around++)
{
error("too many defines");
dexit();
}
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];
char *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;
lp = np;
bp = revbuff;
if (depth++>100)
{
error("define recursion loop\n");
return;
}
if ((vp = sp->value) == 0)
return;
/* arrange that define unix unix still
has no effect, avoiding rescanning */
if (streq(sp->name,sp->value))
{
while (*vp)
sch(*vp++);
return;
}
backsch(' ');
if (*vp == '(')
expdef(vp);
else
while (*vp)
backsch(*vp++);
backsch(' ');
while (bp>revbuff)
ungetc(*--bp);
}
getsuf(as)
char as[];
{
register int c;
register char *s;
register int t;
s = as;
c = 0;
while(t = *s++)
if (t=='/')
c = 0;
else
c++;
s =- 3;
if (c<=14 && c>2 && *s++=='.')
return(*s);
return(0);
}
setsuf(as, ch)
char as[];
{
register char *s, *s1;
s = s1 = copy(as);
while(*s)
if (*s++ == '/')
s1 = s;
s[-1] = ch;
return(s1);
}
callsys(f, v)
char f[], *v[]; {
int t, status;
if ((t=fork())==0) {
execv(f, v);
printf("Can't find %s\n", f);
exit(1);
} else
if (t == -1) {
printf("Try again\n");
return(1);
}
while(t!=wait(&status));
if ((t=(status&0377)) != 0 && t!=14) {
if (t!=2) /* interrupt */
printf("Fatal error in %s\n", f);
dexit();
}
return((status>>8) & 0377);
}
copy(as)
char as[];
{
register char *otsp, *s;
otsp = tsp;
s = as;
while(*tsp++ = *s++);
return(otsp);
}
nodup(l, os)
char **l, *os;
{
register char *t, *s;
register int c;
s = os;
if (getsuf(s) != 'o')
return(1);
while(t = *l++) {
while(c = *s++)
if (c != *t++)
break;
if (*t=='\0' && c=='\0')
return(0);
s = os;
}
return(1);
}
cunlink(f)
char *f;
{
if (f==0)
return(0);
return(unlink(f));
}
expdef(proto)
char *proto;
{
char buffer[100], *parg[20], *pval[20], name[20], *cspace, *wp;
char protcop[100], *pr;
int narg, k, i, c;
pr = protcop;
while (*pr++ = *proto++);
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");
return;
}
ungetc(c);
for(k=0; pval[k] = coptok(&cspace); 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(streq(name,parg[k]))
break;
wp = k <narg ? pval[k] : name;
while (*wp) backsch(*wp++);
}
}
}
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");
break;
}
}
return(val);
}
coptok (cpp) char **cpp; {
char *val;
int stc, stop,paren;
paren = 0;
val = *cpp;
if (getch() == ')')
return(0);
while (((stc = getch()) != ',' && stc != ')') || paren > 0)
{
if (stc == '"' || stc == '\'')
{
stop = stc;
if (stop == '\'')
*(*cpp)++ = '\'';
while ( (stc = getch()) != stop)
{
if (stc == '\n')
{
error ("non-terminated string");
break;
}
if (stc == '\\')
if ((stc= getch()) != stop && stc != '\\')
*(*cpp)++ = '\\';
*(*cpp)++ = stc;
}
if (stop == '\'')
*(*cpp)++ = '\'';
}
else if (stc == '\\')
{
stc = getch();
if (stc != '"' && stc != '\\')
*(*cpp)++ = '\\';
*(*cpp)++ = stc;
}
else
{
*(*cpp)++ = stc;
if (stc == '(')
paren++;
if (stc == ')')
paren--;
}
}
*(*cpp)++ = 0;
ungetc(stc);
return(val);
}
letter(c)
{
if ((c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c == '_'))
return (1);
else
return(0);
}
letnum(c)
{
if (letter(c) || (c >= '0' && c <= '9'))
return(1);
else
return(0);
}
streq(s,t) char *s, *t;
{
int c;
while ( (c= *s++) == *t++)
if (c==0) return(1);
return(0);
}