home *** CD-ROM | disk | FTP | other *** search
- #
- /* 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;
- }
-