# /* * C compiler, phase 1 * * * Handles processing of declarations, * except for top-level processing of * externals. */ #include "c0h.c" /* * Process a sequence of declaration statements */ declist(sclass) { register sc, elsize, offset; int type; offset = 0; sc = sclass; while ((elsize = getkeywords(&sclass, &type)) != -1) { offset = declare(sclass, type, offset, elsize); sclass = sc; } return(offset+align(INT, offset, 0)); } /* * Read the keywords introducing a declaration statement */ getkeywords(scptr, tptr) int *scptr, *tptr; { register skw, tkw, longf; int o, elsize, isadecl, ismos; isadecl = 0; longf = 0; tkw = -1; skw = *scptr; elsize = 0; ismos = skw==MOS; for (;;) { mosflg = ismos; switch ((o=symbol())==KEYW? cval: -1) { case AUTO: case STATIC: case EXTERN: case REG: if (skw && skw!=cval) error("Conflict in storage class"); skw = cval; break; case LONG: longf++; break; case STRUCT: o = STRUCT; elsize = strdec(&o, ismos); cval = o; case INT: case CHAR: case FLOAT: case DOUBLE: if (tkw>=0) error("Type clash"); tkw = cval; break; default: peeksym = o; if (isadecl==0) return(-1); if (tkw<0) tkw = INT; if (skw==0) skw = AUTO; if (longf) { if (tkw==FLOAT) tkw = DOUBLE; else if (tkw==INT) tkw = LONG; else error("Misplaced 'long'"); } *scptr = skw; *tptr = tkw; return(elsize); } isadecl++; } } /* * Process a structure declaration; a subroutine * of getkeywords. */ strdec(tkwp, mosf) int *tkwp; { register elsize, o; register struct hshtab *ssym; int savebits; 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; savebits = bitoffs; bitoffs = 0; elsize = declist(MOS); bitoffs = savebits; 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); } /* * Check that the dimension table has not overflowed */ chkdim() { if (dimp >= dimsiz) { error("Dimension/struct table overflow"); exit(1); } } /* * Process a comma-separated list of declarators */ declare(askw, tkw, offset, elsize) { register int o; register int skw; skw = askw; do { offset =+ decl1(skw, tkw, offset, elsize); } while ((o=symbol()) == COMMA); if (o==SEMI || o==RPARN && skw==ARG1) return(offset); decsyn(o); } /* * Process a single declarator */ decl1(askw, tkw, offset, elsize) { int t1, chkoff, a; register int type, skw; register struct hshtab *dsym; skw = askw; chkoff = 0; mosflg = skw==MOS; if ((peeksym=symbol())==SEMI || peeksym==RPARN) return(0); /* * Filler field */ if (peeksym==COLON && skw==MOS) { peeksym = -1; t1 = conexp(); elsize = align(tkw, offset, t1); bitoffs =+ t1; return(elsize); } if ((t1=getype()) < 0) goto syntax; type = 0; do type = type<>TYLEN) & XTYPE)!=0); type =| tkw; dsym = defsym; if (!(dsym->hclass==0 || (skw==ARG && dsym->hclass==ARG1) || (skw==EXTERN && dsym->hclass==EXTERN && dsym->htype==type))) if (skw==MOS && dsym->hclass==MOS && dsym->htype==type) chkoff = 1; else { redec(); goto syntax; } dsym->htype = type; if (skw) dsym->hclass = skw; if (skw==ARG1) { if (paraml==0) paraml = dsym; else parame->hoffset = dsym; parame = dsym; } if (elsize && ((type&TYPE)==RSTRUCT || (type&TYPE)==STRUCT)) { dsym->lenp = dimp; chkdim(); dimtab[dimp++] = elsize; } elsize = 0; if (skw==MOS) { elsize = length(dsym); t1 = 0; if ((peeksym = symbol())==COLON) { elsize = 0; peeksym = -1; t1 = conexp(); dsym->hflag =| FFIELD; } a = align(type, offset, t1); elsize =+ a; offset =+ a; if (t1) { if (chkoff && (dsym->bitoffs!=bitoffs || dsym->flen!=t1)) redec(); dsym->bitoffs = bitoffs; dsym->flen = t1; bitoffs =+ t1; } if (chkoff && dsym->hoffset != offset) redec(); dsym->hoffset = offset; } if ((dsym->htype&XTYPE)==FUNC) { if (dsym->hclass!=EXTERN && dsym->hclass!=AUTO) error("Bad function"); dsym->hclass = EXTERN; } if (dsym->hclass==AUTO) { autolen =+ rlength(dsym); dsym->hoffset = -autolen; } else if (dsym->hclass==STATIC) { dsym->hoffset = isn; outcode("BBNBNB", BSS, LABEL, isn++, SSPACE, rlength(dsym), PROG); } else if (dsym->hclass==REG) { if ((type&TYPE)>CHAR && (type&XTYPE)==0 || (type&XTYPE)>PTR || regvar<3) error("Bad register %o", type); dsym->hoffset = --regvar; } syntax: return(elsize); } /* * Read a declarator and get the implied type */ getype() { register int o, type; register struct hshtab *ds; switch(o=symbol()) { case TIMES: return(getype()<ssp = dimp; getf: switch(o=symbol()) { case LPARN: if (xdflg) { xdflg = 0; ds = defsym; declare(ARG1, 0, 0, 0); defsym = ds; xdflg++; } else if ((o=symbol()) != RPARN) goto syntax; type = type<ssp&0377; ooffset) bitoffs = 0; } if (flen) { if (type==INT) { if (flen > NBPW) error(ftl); if (flen+bitoffs > NBPW) { bitoffs = 0; a =+ NCPW; } } else if (type==CHAR) { if (flen > NBPC) error(ftl); if (flen+bitoffs > NCPW) { bitoffs = 0; a =+ 1; } } else error("Bad type for field"); } return(a-offset); } /* * Complain about syntax error in declaration */ decsyn(o) { error("Declaration syntax"); errflush(o); } /* * Complain about a redeclaration */ redec() { error("%.8s redeclared", defsym->name); }