Add original unix v6
This commit is contained in:
+673
@@ -0,0 +1,673 @@
|
||||
#
|
||||
/* C compiler
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "c0h.c"
|
||||
|
||||
/*
|
||||
* Process a single external definition
|
||||
*/
|
||||
extdef()
|
||||
{
|
||||
register o, elsize;
|
||||
int type, sclass;
|
||||
register struct hshtab *ds;
|
||||
|
||||
if(((o=symbol())==EOF) || o==SEMI)
|
||||
return;
|
||||
peeksym = o;
|
||||
type = INT;
|
||||
sclass = EXTERN;
|
||||
xdflg = FNDEL;
|
||||
if ((elsize = getkeywords(&sclass, &type)) == -1 && peeksym!=NAME)
|
||||
goto syntax;
|
||||
if (type==STRUCT)
|
||||
blkhed();
|
||||
do {
|
||||
defsym = 0;
|
||||
decl1(EXTERN, type, 0, elsize);
|
||||
if ((ds=defsym)==0)
|
||||
return;
|
||||
funcsym = ds;
|
||||
ds->hflag =| FNDEL;
|
||||
outcode("BS", SYMDEF, ds->name);
|
||||
xdflg = 0;
|
||||
if ((ds->type&XTYPE)==FUNC) {
|
||||
if ((peeksym=symbol())==LBRACE || peeksym==KEYW) {
|
||||
funcblk.type = decref(ds->type);
|
||||
cfunc(ds->name);
|
||||
return;
|
||||
}
|
||||
} else
|
||||
cinit(ds);
|
||||
} while ((o=symbol())==COMMA);
|
||||
if (o==SEMI)
|
||||
return;
|
||||
syntax:
|
||||
if (o==RBRACE) {
|
||||
error("Too many }'s");
|
||||
peeksym = 0;
|
||||
return;
|
||||
}
|
||||
error("External definition syntax");
|
||||
errflush(o);
|
||||
statement(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a function definition.
|
||||
*/
|
||||
cfunc(cs)
|
||||
char *cs;
|
||||
{
|
||||
register savdimp;
|
||||
|
||||
savdimp = dimp;
|
||||
outcode("BBS", PROG, RLABEL, cs);
|
||||
declist(ARG);
|
||||
regvar = 5;
|
||||
retlab = isn++;
|
||||
if ((peeksym = symbol()) != LBRACE)
|
||||
error("Compound statement required");
|
||||
statement(1);
|
||||
outcode("BNB", LABEL, retlab, RETRN);
|
||||
dimp = savdimp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process the initializers for an external definition.
|
||||
*/
|
||||
cinit(ds)
|
||||
struct hshtab *ds;
|
||||
{
|
||||
register basetype, nel, ninit;
|
||||
int o, width, realwidth;
|
||||
|
||||
nel = 1;
|
||||
basetype = ds->type;
|
||||
/*
|
||||
* If it's an array, find the number of elements.
|
||||
* "basetype" is the type of thing it's an array of.
|
||||
*/
|
||||
while ((basetype&XTYPE)==ARRAY) {
|
||||
if ((nel = dimtab[ds->ssp&0377])==0)
|
||||
nel = 1;
|
||||
basetype = decref(basetype);
|
||||
}
|
||||
realwidth = width = length(ds) / nel;
|
||||
/*
|
||||
* Pretend a structure is kind of an array of integers.
|
||||
* This is a kludge.
|
||||
*/
|
||||
if (basetype==STRUCT) {
|
||||
nel =* realwidth/2;
|
||||
width = 2;
|
||||
}
|
||||
if ((peeksym=symbol())==COMMA || peeksym==SEMI) {
|
||||
outcode("BSN",CSPACE,ds->name,(nel*width+ALIGN)&~ALIGN);
|
||||
return;
|
||||
}
|
||||
ninit = 0;
|
||||
outcode("BBS", DATA, NLABEL, ds->name);
|
||||
if ((o=symbol())==LBRACE) {
|
||||
do
|
||||
ninit = cinit1(ds, basetype, width, ninit, nel);
|
||||
while ((o=symbol())==COMMA);
|
||||
if (o!=RBRACE)
|
||||
peeksym = o;
|
||||
} else {
|
||||
peeksym = o;
|
||||
ninit = cinit1(ds, basetype, width, 0, nel);
|
||||
}
|
||||
/*
|
||||
* Above we pretended that a structure was a bunch of integers.
|
||||
* Readjust in accordance with reality.
|
||||
* First round up partial initializations.
|
||||
*/
|
||||
if (basetype==STRUCT) {
|
||||
if (o = 2*ninit % realwidth)
|
||||
outcode("BN", SSPACE, realwidth-o);
|
||||
ninit = (2*ninit+realwidth-2) / realwidth;
|
||||
nel =/ realwidth/2;
|
||||
}
|
||||
/*
|
||||
* If there are too few initializers, allocate
|
||||
* more storage.
|
||||
* If there are too many initializers, extend
|
||||
* the declared size for benefit of "sizeof"
|
||||
*/
|
||||
if (ninit<nel)
|
||||
outcode("BN", SSPACE, (nel-ninit)*realwidth);
|
||||
else if (ninit>nel) {
|
||||
if ((ds->type&XTYPE)==ARRAY)
|
||||
dimtab[ds->ssp&0377] = ninit;
|
||||
nel = ninit;
|
||||
}
|
||||
/*
|
||||
* If it's not an array, only one initializer is allowed.
|
||||
*/
|
||||
if (ninit>1 && (ds->type&XTYPE)!=ARRAY)
|
||||
error("Too many initializers");
|
||||
if (((nel&width)&ALIGN))
|
||||
outcode("B", EVEN);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a single expression in a sequence of initializers
|
||||
* for an external. Mainly, it's for checking
|
||||
* type compatibility.
|
||||
*/
|
||||
cinit1(ds, type, awidth, aninit, nel)
|
||||
struct hshtab *ds;
|
||||
{
|
||||
float sf;
|
||||
register struct tnode *s;
|
||||
register width, ninit;
|
||||
|
||||
width = awidth;
|
||||
ninit = aninit;
|
||||
if ((peeksym=symbol())==STRING && type==CHAR) {
|
||||
peeksym = -1;
|
||||
if (ninit)
|
||||
bxdec();
|
||||
putstr(0);
|
||||
if (nel>nchstr) {
|
||||
strflg++;
|
||||
outcode("BN", SSPACE, nel-nchstr);
|
||||
strflg = 0;
|
||||
nchstr = nel;
|
||||
}
|
||||
return(nchstr);
|
||||
}
|
||||
if (peeksym==RBRACE)
|
||||
return(ninit);
|
||||
initflg++;
|
||||
s = tree();
|
||||
initflg = 0;
|
||||
switch(width) {
|
||||
|
||||
case 1:
|
||||
if (s->op != CON)
|
||||
goto bad;
|
||||
outcode("B1N0", BDATA, s->value);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (s->op==CON) {
|
||||
outcode("B1N0", WDATA, s->value);
|
||||
break;
|
||||
}
|
||||
if (s->op==FCON || s->op==SFCON) {
|
||||
if (type==STRUCT) {
|
||||
ninit =+ 3;
|
||||
goto prflt;
|
||||
}
|
||||
goto bad;
|
||||
}
|
||||
rcexpr(block(1,INIT,0,0,s));
|
||||
break;
|
||||
|
||||
case 4:
|
||||
sf = fcval;
|
||||
outcode("B1N1N0", WDATA, sf);
|
||||
goto flt;
|
||||
|
||||
case 8:
|
||||
prflt:
|
||||
outcode("B1N1N1N1N0", WDATA, fcval);
|
||||
flt:
|
||||
if (s->op==FCON || s->op==SFCON)
|
||||
break;
|
||||
|
||||
default:
|
||||
bad:
|
||||
bxdec();
|
||||
|
||||
}
|
||||
return(++ninit);
|
||||
}
|
||||
|
||||
bxdec()
|
||||
{
|
||||
error("Inconsistent external initialization");
|
||||
}
|
||||
|
||||
/*
|
||||
* Process one statement in a function.
|
||||
*/
|
||||
statement(d)
|
||||
{
|
||||
register o, o1, o2;
|
||||
int o3, o4;
|
||||
struct tnode *np;
|
||||
|
||||
stmt:
|
||||
switch(o=symbol()) {
|
||||
|
||||
case EOF:
|
||||
error("Unexpected EOF");
|
||||
case SEMI:
|
||||
return;
|
||||
|
||||
case LBRACE:
|
||||
if (d) {
|
||||
if (proflg)
|
||||
outcode("BN", PROFIL, isn++);
|
||||
outcode("BN", SAVE, blkhed());
|
||||
}
|
||||
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, -1);
|
||||
rcexpr(block(1,RFORCE,0,0,np));
|
||||
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);
|
||||
goto stmt;
|
||||
}
|
||||
}
|
||||
peeksym = o;
|
||||
rcexpr(tree());
|
||||
|
||||
semi:
|
||||
if ((o=symbol())==SEMI)
|
||||
return;
|
||||
syntax:
|
||||
error("Statement syntax");
|
||||
errflush(o);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a for statement.
|
||||
*/
|
||||
forstmt()
|
||||
{
|
||||
register int l, o, sline;
|
||||
int sline1, *ss;
|
||||
struct tnode *st;
|
||||
|
||||
if ((o=symbol()) != LPARN)
|
||||
return(o);
|
||||
if ((o=symbol()) != SEMI) { /* init part */
|
||||
peeksym = o;
|
||||
rcexpr(tree());
|
||||
if ((o=symbol()) != SEMI)
|
||||
return(o);
|
||||
}
|
||||
label(contlab);
|
||||
if ((o=symbol()) != SEMI) { /* test part */
|
||||
peeksym = o;
|
||||
rcexpr(block(1,CBRANCH,tree(),brklab,0));
|
||||
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();
|
||||
sline = line;
|
||||
if ((o=symbol()) != RPARN)
|
||||
return(o);
|
||||
ss = treespace;
|
||||
treespace = space;
|
||||
statement(0);
|
||||
sline1 = line;
|
||||
line = sline;
|
||||
label(contlab);
|
||||
rcexpr(st);
|
||||
line = sline1;
|
||||
treespace = ss;
|
||||
branch(l);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* A parenthesized expression,
|
||||
* as after "if".
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* The switch stateent, which involves collecting the
|
||||
* constants and labels for the cases.
|
||||
*/
|
||||
pswitch()
|
||||
{
|
||||
register struct swtab *cswp, *sswp;
|
||||
int dl, swlab;
|
||||
|
||||
cswp = sswp = swp;
|
||||
if (swp==0)
|
||||
cswp = swp = swtab;
|
||||
branch(swlab=isn++);
|
||||
dl = deflab;
|
||||
deflab = 0;
|
||||
statement(0);
|
||||
branch(brklab);
|
||||
label(swlab);
|
||||
if (deflab==0)
|
||||
deflab = brklab;
|
||||
outcode("BNN", SWIT, deflab, line);
|
||||
for (; cswp < swp; cswp++)
|
||||
outcode("NN", cswp->swlab, cswp->swval);
|
||||
outcode("0");
|
||||
label(brklab);
|
||||
deflab = dl;
|
||||
swp = sswp;
|
||||
}
|
||||
|
||||
/*
|
||||
* blkhed is called at the start of each function.
|
||||
* It reads the declarations at the start;
|
||||
* then assigns storage locations for the
|
||||
* parameters (which have been linked into a list,
|
||||
* in order of appearance).
|
||||
* This list is necessary because in
|
||||
* f(a, b) float b; int a; ...
|
||||
* the names are seen before the types.
|
||||
* Also, the routine adjusts structures involved
|
||||
* in some kind of forward-referencing.
|
||||
*/
|
||||
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&XTYPE) == ARRAY) {
|
||||
cs->htype =- (ARRAY-PTR); /* 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&TYPE)==RSTRUCT) {
|
||||
cs->lenp = dimtab[cs->lenp&0377]->lenp;
|
||||
cs->htype = cs->htype&~TYPE | 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);
|
||||
if (stflg)
|
||||
prste(cs);
|
||||
}
|
||||
space = treespace;
|
||||
outcode("BN", SETREG, regvar);
|
||||
return(autolen);
|
||||
}
|
||||
|
||||
/*
|
||||
* After a function definition, delete local
|
||||
* symbols.
|
||||
* Also complain about undefineds.
|
||||
*/
|
||||
blkend() {
|
||||
register struct hshtab *cs;
|
||||
|
||||
for (cs=hshtab; cs<hshtab+hshsiz; cs++) {
|
||||
if (cs->name[0]) {
|
||||
if (cs->hclass==0 && (cs->hflag&FNUND)==0) {
|
||||
error("%.8s undefined", cs->name);
|
||||
cs->hflag =| FNUND;
|
||||
}
|
||||
if((cs->hflag&FNDEL)==0) {
|
||||
cs->name[0] = '\0';
|
||||
hshused--;
|
||||
cs->hflag =& ~(FNUND|FFIELD);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* write out special definitions of local symbols for
|
||||
* benefit of the debugger. None of these are used
|
||||
* by the assembler except to save them.
|
||||
*/
|
||||
prste(acs)
|
||||
{
|
||||
register struct hshtab *cs;
|
||||
register nkind;
|
||||
|
||||
cs = acs;
|
||||
switch (cs->hclass) {
|
||||
case REG:
|
||||
nkind = RNAME;
|
||||
break;
|
||||
|
||||
case AUTO:
|
||||
nkind = ANAME;
|
||||
break;
|
||||
|
||||
case STATIC:
|
||||
nkind = SNAME;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
|
||||
}
|
||||
outcode("BSN", nkind, cs->name, cs->hoffset);
|
||||
}
|
||||
|
||||
/*
|
||||
* In case of error, skip to the next
|
||||
* statement delimiter.
|
||||
*/
|
||||
errflush(ao)
|
||||
{
|
||||
register o;
|
||||
|
||||
o = ao;
|
||||
while(o>RBRACE) /* ; { } */
|
||||
o = symbol();
|
||||
peeksym = o;
|
||||
}
|
||||
Reference in New Issue
Block a user