V5/usr/c/c02.c
#
/* C compiler
Copyright 1972 Bell Telephone Laboratories, Inc.
*/
#include "c0h.c"
extdef()
{
register o, width;
int type, elsize, nel;
char *cs;
register struct hshtab *ds;
if(((o=symbol())==EOF) || o==SEMI)
return;
type = 0;
xdflg = FNDEL;
xxx:
if (o==KEYW) {
if (cval==EXTERN) {
o = symbol();
goto xxx;
}
if ((type=cval)>STRUCT)
goto syntax; /* not type */
elsize = 0;
if (type==STRUCT) {
elsize = strdec(&type, 0);
if ((peeksym=symbol())!=KEYW)
blkhed();
}
} else {
if (o!=NAME)
goto syntax;
peeksym = o;
}
do {
defsym = 0;
strflg = 1;
decl1(EXTERN, type&07, 0, elsize);
if ((ds=defsym)==0)
return;
cs = ds->name;
funcsym = ds;
ds->hflag = FNDEL;
printf(".globl _%.8s\n", cs);
xdflg = 0;
type = ds->type;
if ((type&030)==FUNC) {
if ((peeksym=symbol())==LBRACE || peeksym==KEYW)
cfunc(cs);
return;
}
nel = 1;
while ((ds->type&030)==ARRAY) {
nel = dimtab[ds->ssp&0377];
ds->type = decref(ds->type);
}
width = length(ds);
if (ds->type==STRUCT) {
nel =* width/2;
width = 0;
}
ds->type = type;
cinit(cs, type, nel, width);
} while ((o=symbol())==COMMA);
if (o==SEMI)
return;
syntax:
error("External definition syntax");
errflush(o);
statement(0);
}
cfunc(cs)
char *cs;
{
register savdimp;
strflg = 0;
savdimp = dimp;
printf(".text\n_%.8s:\n", cs);
declist(ARG);
regvar = 5;
retlab = isn++;
if ((peeksym = symbol()) != LBRACE)
error("Compound statement required");
statement(1);
printf("L%d:jmp rretrn\n", retlab);
dimp = savdimp;
}
cinit(cs, type, nel, awidth)
char *cs;
{
register o, ninit, width;
if ((width = awidth) == 0)
width = 2;
if ((peeksym=symbol())==COMMA || peeksym==SEMI) {
printf(".comm _%.8s,%o\n", cs, (nel*width+1)&~01);
return;
}
ninit = 0;
printf(".data\n_%.8s=.\n", cs);
if ((o=symbol())==LBRACE) {
do
ninit = cinit1(cs, type, awidth, ninit);
while ((o=symbol())==COMMA);
if (o!=RBRACE)
peeksym = o;
} else {
peeksym = o;
ninit = cinit1(cs, type, awidth, 0);
}
if (ninit<nel)
printf(".=.+%o\n", (nel-ninit)*width);
else
nel = ninit;
if (nel>1 && (type&030)!=ARRAY && (type&07)!=STRUCT)
error("Too many initializers");
if (((nel&width)&01) != 0)
printf(".even\n");
}
cinit1(cs, type, awidth, ninit)
char *cs;
{
float sf;
register struct tnode *s;
register width;
if ((peeksym=symbol())==STRING && type==ARRAY+CHAR) {
peeksym = -1;
if (ninit)
bxdec();
printf(".text\n_%.8s=L%d\n", cs, cval);
return((nchstr+1) & ~01);
}
if (peeksym==RBRACE)
return(ninit);
initflg++;
s = tree();
if ((width = awidth) == 0)
width = length(s);
initflg = 0;
switch(width) {
case 1:
printf(".byte ");
if (s->op != CON)
bxdec();
case 2:
if (s->op==CON) {
printf("%o\n", s->value);
break;
}
rcexpr(block(1,INIT,0,0,s), regtab);
break;
case 4:
sf = fcval;
printf("%o;%o\n", sf);
goto flt;
case 8:
printf("%o;%o;%o;%o\n", fcval);
if (awidth==0)
ninit =+ 3;
flt:
if (s->op==FCON || s->op==SFCON)
break;
default:
bxdec();
}
return(++ninit);
}
bxdec()
{
error("Inconsistent external initialization");
}
statement(d)
{
register o, o1, o2;
int o3, o4;
struct tnode *np;
stmt:
switch(o=symbol()) {
case EOF:
error("Unexpected EOF");
case SEMI:
case RBRACE:
return;
case LBRACE:
if (d) {
o2 = blkhed() - 4;
if (proflg)
o = "jsr\tr5,mrsave;0f;%o\n.bss\n0:.=.+2\n.text\n";
else
o = "jsr r5,rsave; %o\n";
printf(o, o2);
}
while (!eof) {
if ((o=symbol())==RBRACE)
return;
peeksym = o;
statement(0);
}
error("Missing '}'");
return;
case KEYW:
switch(cval) {
case GOTO:
if (o1 = simplegoto())
branch(o1);
else
dogoto();
goto semi;
case RETURN:
doret();
goto semi;
case IF:
np = pexpr();
o2 = 0;
if ((o1=symbol())==KEYW) switch (cval) {
case GOTO:
if (o2=simplegoto())
goto simpif;
cbranch(np, o2=isn++, 0);
dogoto();
label(o2);
goto hardif;
case RETURN:
if (nextchar()==';') {
o2 = retlab;
goto simpif;
}
cbranch(np, o1=isn++, 0);
doret();
label(o1);
o2++;
goto hardif;
case BREAK:
o2 = brklab;
goto simpif;
case CONTIN:
o2 = contlab;
simpif:
chconbrk(o2);
cbranch(np, o2, 1);
hardif:
if ((o=symbol())!=SEMI)
goto syntax;
if ((o1=symbol())==KEYW && cval==ELSE)
goto stmt;
peeksym = o1;
return;
}
peeksym = o1;
cbranch(np, o1=isn++, 0);
statement(0);
if ((o=symbol())==KEYW && cval==ELSE) {
o2 = isn++;
branch(o2);
label(o1);
statement(0);
label(o2);
return;
}
peeksym = o;
label(o1);
return;
case WHILE:
o1 = contlab;
o2 = brklab;
label(contlab = isn++);
cbranch(pexpr(), brklab=isn++, 0);
statement(0);
branch(contlab);
label(brklab);
contlab = o1;
brklab = o2;
return;
case BREAK:
chconbrk(brklab);
branch(brklab);
goto semi;
case CONTIN:
chconbrk(contlab);
branch(contlab);
goto semi;
case DO:
o1 = contlab;
o2 = brklab;
contlab = isn++;
brklab = isn++;
label(o3 = isn++);
statement(0);
label(contlab);
contlab = o1;
if ((o=symbol())==KEYW && cval==WHILE) {
cbranch(tree(), o3, 1);
label(brklab);
brklab = o2;
goto semi;
}
goto syntax;
case CASE:
o1 = conexp();
if ((o=symbol())!=COLON)
goto syntax;
if (swp==0) {
error("Case not in switch");
goto stmt;
}
if(swp>=swtab+swsiz) {
error("Switch table overflow");
} else {
swp->swlab = isn;
(swp++)->swval = o1;
label(isn++);
}
goto stmt;
case SWITCH:
o1 = brklab;
brklab = isn++;
np = pexpr();
chkw(np);
rcexpr(block(1,RFORCE,0,0,np), regtab);
pswitch();
brklab = o1;
return;
case DEFAULT:
if (swp==0)
error("Default not in switch");
if ((o=symbol())!=COLON)
goto syntax;
label(deflab = isn++);
goto stmt;
case FOR:
o1 = contlab;
o2 = brklab;
contlab = isn++;
brklab = isn++;
if (o=forstmt())
goto syntax;
label(brklab);
contlab = o1;
brklab = o2;
return;
}
error("Unknown keyword");
goto syntax;
case NAME:
if (nextchar()==':') {
peekc = 0;
o1 = csym;
if (o1->hclass>0) {
error("Redefinition");
goto stmt;
}
o1->hclass = STATIC;
o1->htype = ARRAY;
if (o1->hoffset==0)
o1->hoffset = isn++;
label(o1->hoffset);
if ((peeksym=symbol())==RBRACE)
return;
goto stmt;
}
}
peeksym = o;
rcexpr(tree(), efftab);
semi:
if ((o=symbol())==SEMI)
return;
syntax:
error("Statement syntax");
errflush(o);
goto stmt;
}
#define forsps 150
forstmt()
{
int l, savxpr[forsps];
int *st, *ss;
register int *sp1, *sp2, o;
if ((o=symbol()) != LPARN)
return(o);
if ((o=symbol()) != SEMI) { /* init part */
peeksym = o;
rcexpr(tree(), efftab);
if ((o=symbol()) != SEMI)
return(o);
}
label(contlab);
if ((o=symbol()) != SEMI) { /* test part */
peeksym = o;
rcexpr(block(1,CBRANCH,tree(),brklab,0), cctab);
if ((o=symbol()) != SEMI)
return(o);
}
if ((peeksym=symbol()) == RPARN) { /* incr part */
peeksym = -1;
statement(0);
branch(contlab);
return(0);
}
l = contlab;
contlab = isn++;
st = tree();
if ((o=symbol()) != RPARN)
return(o);
ss = space;
if (space-treebase > forsps) {
error("Expression too large");
space = &treebase[forsps];
}
sp2 = savxpr;
for (sp1=treebase; sp1<space;)
*sp2++ = *sp1++;
statement(0);
space = ss;
sp2 = savxpr;
for (sp1=treebase; sp1<space;)
*sp1++ = *sp2++;
label(contlab);
rcexpr(st, efftab);
branch(l);
return(0);
}
pexpr()
{
register o, t;
if ((o=symbol())!=LPARN)
goto syntax;
t = tree();
if ((o=symbol())!=RPARN)
goto syntax;
return(t);
syntax:
error("Statement syntax");
errflush(o);
return(0);
}
pswitch()
{
int *sswp, swlab;
register int *swb, *wswp, dl;
swb = sswp = swp;
if (swp==0)
swb = swp = swtab;
branch(swlab=isn++);
dl = deflab;
deflab = 0;
statement(0);
branch(brklab);
label(swlab);
putchar('#'); /* switch is pseudo-expression */
label(brklab);
if (!deflab) {
deflab = isn++;
label(deflab);
}
wswp = swp;
putw(wswp-swb, binbuf);
putw(deflab, binbuf);
putw(4, binbuf); /* table 4 is switch */
putw(line, binbuf);
while (swb < wswp)
putw(*swb++, binbuf);
deflab = dl;
swp = sswp;
}
blkhed()
{
register pl;
register struct hshtab *cs;
autolen = 6;
declist(0);
pl = 4;
while(paraml) {
parame->hoffset = 0;
cs = paraml;
paraml = paraml->hoffset;
if (cs->htype==FLOAT)
cs->htype = DOUBLE;
cs->hoffset = pl;
cs->hclass = AUTO;
if ((cs->htype&030) == ARRAY) {
cs->htype =- 020; /* set ptr */
cs->ssp++; /* pop dims */
}
pl =+ rlength(cs);
}
for (cs=hshtab; cs<hshtab+hshsiz; cs++) {
if (cs->name[0] == '\0')
continue;
/* check tagged structure */
if (cs->hclass>KEYWC && (cs->htype&07)==RSTRUCT) {
cs->lenp = dimtab[cs->lenp&0377]->lenp;
cs->htype = cs->htype&~07 | STRUCT;
}
if (cs->hclass == STRTAG && dimtab[cs->lenp&0377]==0)
error("Undefined structure: %.8s", cs->name);
if (cs->hclass == ARG)
error("Not an argument: %.8s", cs->name);
}
osleft = ossiz;
space = treebase;
rcexpr(block(1, SETREG, regvar), regtab);
return(autolen);
}
blkend() {
register struct hshtab *cs;
for (cs=hshtab; cs<hshtab+hshsiz; cs++) {
if (cs->name[0]) {
if (cs->hclass==0)
error("%.8s undefined", cs->name);
if((cs->hflag&FNDEL)==0) {
cs->name[0] = '\0';
hshused--;
}
}
}
}
errflush(ao)
{
register o;
o = ao;
while(o>RBRACE) /* ; { } */
o = symbol();
peeksym = o;
}
declist(skwd)
{
int o, elsize, ndec;
register offset, tkw, skw;
offset = 0;
loop:
ndec = 0;
tkw = -1;
skw = skwd;
elsize = 0;
while ((o=symbol())==KEYW) switch (cval) {
case AUTO:
case STATIC:
case EXTERN:
case REG:
if (skw)
error("Conflict in storage class");
skw = cval;
ndec++;
if (tkw<0)
continue;
goto list;
case STRUCT:
o = cval;
elsize = strdec(&o, skw==MOS);
cval = o;
case INT:
case CHAR:
case FLOAT:
case DOUBLE:
ndec++;
if (tkw>=0)
error("Type clash");
tkw = cval;
if (skw==0)
continue;
goto list;
default:
goto brk1;
}
brk1:
peeksym = o;
if (ndec==0)
return(offset);
list:
if (tkw<0)
tkw = INT;
if (skw==0)
skw = AUTO;
offset = declare(skw, tkw, offset, elsize);
goto loop;
}
strdec(tkwp, mosf)
int *tkwp;
{
register elsize, o;
register struct hshtab *ssym;
struct hshtab *ds;
mosflg = 1;
ssym = 0;
if ((o=symbol())==NAME) {
ssym = csym;
if (ssym->hclass==0) {
ssym->hclass = STRTAG;
ssym->lenp = dimp;
chkdim();
dimtab[dimp++] = 0;
}
if (ssym->hclass != STRTAG)
redec();
mosflg = mosf;
o = symbol();
}
mosflg = 0;
if (o != LBRACE) {
if (ssym==0) {
syntax:
decsyn(o);
return(0);
}
if (ssym->hclass!=STRTAG)
error("Bad structure name");
if ((elsize = dimtab[ssym->lenp&0377])==0) {
*tkwp = RSTRUCT;
elsize = ssym;
}
peeksym = o;
} else {
ds = defsym;
mosflg = 0;
elsize = declist(MOS);
if (elsize&01)
elsize++;
defsym = ds;
if ((o = symbol()) != RBRACE)
goto syntax;
if (ssym) {
if (dimtab[ssym->lenp&0377])
error("%.8s redeclared", ssym->name);
dimtab[ssym->lenp&0377] = elsize;
}
}
return(elsize);
}
chkdim()
{
if (dimp >= dimsiz) {
error("Dimension/struct table overflow");
exit(1);
}
}