812 lines
13 KiB
C
812 lines
13 KiB
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);
|
|
}
|