/* declare.c - declaration routines for bcc */ /* Copyright (C) 1992 Bruce Evans */ #ifndef VERY_SMALL_MEMORY #include #endif #include "bcc.h" #include "align.h" #include "byteord.h" #include "gencode.h" #include "input.h" /* just for orig_cppmode */ #include "reg.h" #include "sc.h" #include "scan.h" #include "sizes.h" #include "table.h" #include "type.h" #undef EXTERN #define EXTERN #include "parse.h" PRIVATE bool_t argsallowed; /* nonzero to allow args in declarator */ PRIVATE sym_t gvarsc; /* sc flags of last identifier declared */ PRIVATE char gvar2name[2 + NAMESIZE]; /* space for structure keys and .. */ #define gvarname (gvar2name + 2) /* last identifier declared */ PRIVATE struct typestruct *gvartype; /* type of last identifier declared */ PRIVATE bool_t initlistflag; /* remembers whether initializer is a list */ #ifndef VERY_SMALL_MEMORY PRIVATE int anons = 0; /* number of anonymous structures/unions seen */ #endif FORWARD struct typestruct *chainprefix P((struct typestruct *pretype, struct typestruct *sufftype)); FORWARD void declaf P((void)); FORWARD void declarator P((void)); FORWARD void declarg P((void)); FORWARD struct typestruct *declenum P((void)); FORWARD void declfunc P((void)); FORWARD void declselt P((struct typestruct *structype, offset_T *psoffset, struct typelist ** ptypelist)); FORWARD bool_pt declspec P((void)); FORWARD struct typestruct *declsu P((void)); FORWARD void idecllist P((void)); FORWARD void initarray P((struct typestruct *type)); FORWARD void inititem P((struct typestruct *type)); FORWARD void initstruct P((struct typestruct *type)); FORWARD void lbrace P((void)); FORWARD void multidecl P((char *sname)); FORWARD void need P((int charneeded)); FORWARD void rdeclarator P((void)); FORWARD bool_pt regdecl P((void)); PRIVATE struct typestruct *chainprefix(pretype, sufftype) struct typestruct *pretype; struct typestruct *sufftype; { if (pretype->nexttype != NULL) { sufftype = chainprefix(pretype->nexttype, sufftype); if (pretype->constructor != ARRAY) return prefix(pretype->constructor, pretype->typesize, sufftype); else return prefix(ARRAY, pretype->typesize / pretype->nexttype->typesize * sufftype->typesize, sufftype); } return sufftype; } PUBLIC void colon() { if (sym != COLON) need(':'); else nextsym(); } /* decllist() - list of local declarations */ /* this does the non-terminal symbols declaration-list, type-declaration */ /* list and declaration */ /* the different cases are and ";" at the end are decided by idecllist() */ PUBLIC void decllist() { while (declspec()) { if (gvarsc == NULLDECL) gvarsc = AUTODECL; idecllist(); } } PRIVATE void declaf() { uoffset_T asize; bool_t levelnew; #ifdef TESTING_PROTOTYPES char ogvarname[NAMESIZE]; sym_t ogvarsc; struct symstruct *ogvarsymptr; struct typestruct *ogvartype; #endif if (sym == LPAREN) /* function */ { nextsym(); if (argsallowed && level == GLBLEVEL) { newlevel(); levelnew = TRUE; } else levelnew = FALSE; #ifdef TESTING_PROTOTYPES strcpy(ogvarname, gvarname); ogvarsc = gvarsc; ogvarsymptr = gvarsymptr; ogvartype = gvartype; if (declspec()) { if (level == ARGLEVEL) outstr(gvarname); outbyte('('); do { declarator(); dbtype(gvartype); outbyte(' '); #if 0 if (gvarname[0] != 0 && gsymptr != NULL && gsymptr->level == level) error("repeated argument"); #endif outstr(gvarname); if (levelnew) addloc(gsname, gvartype); /* adjust offsets later */ if (sym != COMMA) break; outcomma(); nextsym(); } while (declspec()); if (sym == STRUCELTOP) { /* ... should be lexed. */ nextsym(); if (sym == STRUCELTOP) { nextsym(); if (sym == STRUCELTOP) { nextsym(); outstr(" ..."); } } } outbyte(')'); if (level == ARGLEVEL) outnl(); } else { #endif /* TESTING_PROTOTYPES */ while (sym == IDENT) { if (gsymptr != NULL && gsymptr->level == level) error("repeated argument"); if (levelnew) addloc(gsname, itype); /* adjust types and offsets later */ nextsym(); if (sym != COMMA) break; nextsym(); } #ifdef TESTING_PROTOTYPES } strcpy(gvarname, ogvarname); gvarsc = ogvarsc; gvarsymptr = ogvarsymptr; gvartype = ogvartype; #endif /* TESTING_PROTOTYPES */ rparen(); declaf(); switch (gvartype->constructor) { case ARRAY: error("function returning array is illegal"); break; case FUNCTION: error("function returning function is illegal"); break; } gvartype = prefix(FUNCTION, ftypesize, gvartype); } else if (sym == LBRACKET) { nextsym(); if (sym == RBRACKET) asize = 0; else asize = constexpression() & intmaskto; /* FIXME: warn overflow */ rbracket(); declaf(); if (gvartype->typesize == 0) switch (gvartype->constructor) { case FUNCTION: error("array of functions is illegal"); break; case STRUCTU: error("undefined structure"); break; default: /* array */ error("null dimension"); gvartype->typesize = 1; } gvartype = prefix(ARRAY, asize * gvartype->typesize, gvartype); } } PRIVATE void declarator() { rdeclarator(); if (gvartype->constructor == STRUCTU && gvartype->typesize == 0 && /* We don't do the anonymous union/structure trickery on low mem machines */ #ifdef VERY_SMALL_MEMORY gvarsc != TYPEDEFDECL && gvarsc != EXTERNDECL) #else gvarsc != TYPEDEFDECL && gvarsc != EXTERNDECL && gvarsc != NULLDECL) #endif error("undefined structure"); } PRIVATE void declarg() { if (gvarsymptr->level != ARGLEVEL) error2error(gvarname, " not in argument list"); else if (gvarsymptr->flags & INITIALIZED && gvarsymptr->type != gvartype) multidecl(gvarname); else { gvarsymptr->flags = INITIALIZED; /* flag otherwise unused for locals */ if (gvartype->constructor & (ARRAY | POINTER)) gvartype = pointype(gvartype->nexttype); gvarsymptr->type = gvartype; if (gvarsc == REGDECL && regdecl()) regarg = TRUE; } } /* enum-specifier = "enum" [identifier] "{" enumerator {, enumerator} "}" | "enum" identifier. enumerator = identifier | identifier = constant-expression. */ PRIVATE struct typestruct *declenum() { register struct symstruct *esymptr; register struct typestruct *enumtype; offset_T ordinal; nextsym(); if (sym != IDENT && sym != TYPEDEFNAME) enumtype = addstruct(""); else if ((esymptr = findstruct(gsname)) == NULL) { enumtype = addstruct(gsname); nextsym(); } else { nextsym(); enumtype = esymptr->type; if (sym != LBRACE) return enumtype; if (esymptr->level != level) enumtype = addstruct(esymptr->name.namea); } lbrace(); if (enumtype->typesize != 0) multidecl(enumtype->tname); else { enumtype->typesize = itypesize; enumtype->alignmask = itype->alignmask; } if (sym != IDENT) error("empty enumerator list"); ordinal = 0; while (sym == IDENT) { if ((esymptr = gsymptr) != NULL && esymptr->level == level) multidecl(gsname); else { (esymptr = addlorg(gsname, itype))->storage = CONSTANT; esymptr->indcount = 0; } nextsym(); if (sym == ASSIGNOP) { nextsym(); ordinal = constexpression() & intmaskto; /* FIXME: warn ovflo */ if (ordinal > maxintto) ordinal -= (maxuintto + 1); } if (esymptr->storage == CONSTANT) esymptr->offset.offv = ordinal++; if (sym != COMMA) break; nextsym(); } rbrace(); return enumtype; } /* declselt - get list of declarations for a structure/union member */ PRIVATE void declselt(structype, psoffset, ptypelist) struct typestruct *structype; offset_T *psoffset; struct typelist **ptypelist; { struct typestruct *basetype; value_t fieldwidth; value_t fwidth; offset_T offset; scalar_t scalar=0; offset = *psoffset; declspec(); if (gvarsc != NULLDECL) error("illegal type name"); basetype = gvartype; #ifndef VERY_SMALL_MEMORY if (sym == SEMICOLON || sym == EOFSYM) { /* Generate a fake structure if none specified... */ anonstruct (); /* ....and pretend it was regularly present in source */ goto anonstr; } #endif while (sym != SEMICOLON && sym != EOFSYM) { gvartype = basetype; declarator(); anonstr: fieldwidth = -1; if (sym == COLON) { scalar = gvartype->scalar; if (!(scalar & ISCALAR)) error("bitfield has non-integral type"); nextsym(); fwidth = constexpression(); if (fwidth < 0) error("bitfield has negative width"); else if (fwidth > INT32BITSTO) /* XXX */ error("bitfield is too wide"); else fieldwidth = fwidth; } if (gvarname[0] == 0) { if (fieldwidth == 0) offset = (offset + ~gvartype->alignmask) & gvartype->alignmask; else /* XXX - should really align to fieldwidth'th bit. */ offset = (offset + ~gvartype->alignmask) & gvartype->alignmask; } else { if (fieldwidth == 0) error("bitfield has zero width"); else if (fieldwidth > 0 && scalar & ISCALAR) { if (fieldwidth <= CHBITSTO) /* XXX! */ gvartype = ctype; else if (fieldwidth <= INT32BITSTO) /* XXX */ gvartype = itype; else gvartype = ltype; if (scalar & UNSIGNED) gvartype = tounsigned(gvartype); } gvar2name[0] = structype->structkey[0]; gvar2name[1] = structype->structkey[1]; /* key provides unique name space */ if (findlorg(gvar2name) != NULL) multidecl(gvarname); else { (gvarsymptr = addlorg(gvar2name, gvartype))->storage = NOSTORAGE; structype->alignmask &= gvartype->alignmask; offset = (gvarsymptr->offset.offi = (offset+ ~gvartype->alignmask) & gvartype->alignmask) + gvartype->typesize; { register struct typelist *newtypelist; newtypelist = qmalloc(sizeof *newtypelist); #ifdef TS ++ts_n_newtypelist; ts_s_newtypelist += sizeof *newtypelist; #endif newtypelist->tlnext = NULL; newtypelist->tltype = gvartype; if (*ptypelist == NULL) structype->listtype = newtypelist; else (*ptypelist)->tlnext = newtypelist; *ptypelist = newtypelist; } } } if (sym != COMMA) break; nextsym(); } semicolon(); *psoffset = offset; } PRIVATE bool_pt declspec() { unsigned nsc; unsigned nsigned; unsigned ntype; unsigned nunsigned; gvarsc = NULLDECL; gvartype = itype; nsigned = nunsigned = ntype = nsc = 0; while (TRUE) { switch (sym) { case AUTODECL: ++nsc; gvarsc = sym; nextsym(); break; case ENUMDECL: ++ntype; declenum(); gvartype = itype; /* kludge - ignore type of enum */ break; case EXTERNDECL: ++nsc; gvarsc = sym; nextsym(); break; case REGDECL: ++nsc; gvarsc = sym; nextsym(); break; case STATICDECL: ++nsc; gvarsc = sym; nextsym(); break; case STRUCTDECL: case UNIONDECL: ++ntype; gvartype = declsu(); break; case TYPEDECL: if (ntype == 1) { /* allow short int and long int */ if (gvartype == itype && (gsymptr->type == stype || gsymptr->type == ltype)) ntype = 0; /* Allow long double and long float */ if (gvartype == ltype && (gsymptr->type == fltype || gsymptr->type == dtype)) { gvartype = dtype; nextsym(); break; } /* allow int short and int long, blech */ if (gsymptr->type == itype && (gvartype == stype || gvartype == ltype)) { nextsym(); break; } } ++ntype; gvartype = gsymptr->type; nextsym(); break; case TYPEDEFDECL: ++nsc; gvarsc = sym; nextsym(); break; case TYPEDEFNAME: if (ntype != 0) goto break2; ++ntype; gvartype = gsymptr->type; nextsym(); break; case SIGNDECL: ++nsigned; nextsym(); break; case UNSIGNDECL: ++nunsigned; nextsym(); break; case ASMSYM: nextsym(); doasm(); break; default: goto break2; } } break2: if (nsigned > 0) { if (ntype == 0) { gvartype = itype; ntype = 1; } gvartype = tosigned(gvartype); if (nsigned > 1 || nunsigned > 0) ntype = 2; } if (nunsigned > 0) { if (ntype == 0) { gvartype = uitype; ntype = 1; } gvartype = tounsigned(gvartype); if (nunsigned > 1 || nsigned > 0) ntype = 2; } if (nsc > 0) { if (ntype == 0) ntype = 1; if (nsc > 1) error("multiple storage classes in declaration"); } if (ntype > 1) error("multiple types in declaration"); return nsc > 0 || ntype > 0; } /* declsu - get structure or union name and/or declaration, return type */ PRIVATE struct typestruct *declsu() { sym_t ogvarsc; offset_T soffset; offset_T struclength; sym_t susym; struct typelist *typelist; struct typestruct *structype; susym = sym; nextsym(); if (sym != IDENT && sym != TYPEDEFNAME) structype = addstruct(""); else if ((gvarsymptr = findstruct(gsname)) == NULL) { structype = addstruct(gsname); nextsym(); } else { nextsym(); if (sym == LBRACE && gvarsymptr->level != level) structype = addstruct(gvarsymptr->name.namea); else structype = gvarsymptr->type; } if (sym != LBRACE) return structype; if (structype->typesize != 0) multidecl(structype->tname); nextsym(); ogvarsc = gvarsc; struclength = soffset = 0; typelist = NULL; while (sym != RBRACE && sym != EOFSYM) { declselt(structype, &soffset, &typelist); if (susym == STRUCTDECL) struclength = soffset; else { if (struclength < soffset) struclength = soffset; soffset = 0; } } structype->typesize = (struclength + ~structype->alignmask) & structype->alignmask; rbrace(); gvarsc = ogvarsc; return structype; } /* declfunc() - function name and parameter list */ PRIVATE void declfunc() { offset_T argsp; uoffset_T argsize; struct symstruct *symptr; int main_flag = 0; strcpy(funcname, gvarname); if( strcmp(funcname, "main") != 0 ) main_flag = -1; if (gvarsymptr == NULL) gvarsymptr = addglb(gvarname, gvartype); /* No ancient switch on small memory systems */ #ifndef VERY_SMALL_MEMORY else if (ancient) {} /* Full declaration type different from the prior implicit * one. Even gcc allows this, just comes up with a warning */ #endif else if (gvarsymptr->type != gvartype || (gvarsymptr->flags & INITIALIZED)) multidecl(gvarname); /* different type or full declare */ gvarsymptr->flags = INITIALIZED; /* show full declare */ cseg(); if (gvarsc == STATICDECL) private(gvarname); /* don't need to put STATIC in flags */ else public(gvarname); callee1mask = calleemask; #ifdef FRAMEPOINTER frame1list = framelist; #endif func1saveregsize = funcsaveregsize; #if 0 if ((returntype = gvartype->nexttype)->scalar & RSCALAR) #else if ((returntype = gvartype->nexttype)->scalar & DOUBLE) #endif { callee1mask &= ~doublreturnregs; #ifdef FRAMEPOINTER frame1list &= ~doublreturnregs; #endif func1saveregsize = funcdsaveregsize; } arg1size = /* would already be 0 unless last function empty */ #ifdef FRAMEPOINTER framep = stackarg = #endif reguse = 0; /* would already be 0 unless last f had reg vars */ decllist(); argsp = returnadrsize; if (returntype->constructor & STRUCTU) argsp += ptypesize; softsp = -func1saveregsize; for (symptr = &locsyms[0]; symptr < locptr && symptr->flags != STRUCTNAME && *symptr->name.namea >= 'A'; symptr = (struct symstruct *) align(&symptr->name.namea[strlen(symptr->name.namea) + 1])) { if( main_flag >= 0 ) main_flag++; /* convert arg sizes to offsets */ if (symptr->type == fltype) symptr->type = dtype; argsize = symptr->type->typesize; #ifdef FRAMEPOINTER if (!arg1inreg || symptr != &locsyms[0] || symptr->flags != REGVAR) stackarg = TRUE; #endif if (arg1inreg && symptr == &locsyms[0] && symptr->flags != REGVAR) { if ((arg1size = argsize) < itypesize) arg1size = itypesize; argsp = softsp -= arg1size; } #if INT_BIG_ENDIAN if (argsize < itypesize) argsp += itypesize - argsize; symptr->offset.offi = argsp; argsp += argsize; #else symptr->offset.offi = argsp; if (argsize > itypesize) argsp += argsize; else argsp += itypesize; #endif if (arg1inreg && symptr == &locsyms[0]) argsp = returnadrsize; /* skip return adr after 1st arg */ } if( main_flag > 0 ) { globl("__mkargv"); if( main_flag > 2 ) globl("environ"); } #ifdef I8088 regfuse = 0; #endif lbrace(); compound(); #ifdef I8088 if (regfuse & (callee1mask | INDREG0)) { outstr("! Register"); if (regfuse & INDREG0 ) outstr(" BX"); if (regfuse & INDREG1 & callee1mask) outstr(" SI"); if (regfuse & INDREG2 & callee1mask) outstr(" DI"); if (regfuse & LOCAL & callee1mask) outstr(" BP"); outstr(" used in function "); outnstr(funcname); if (optimise && !callersaves) { outstr(funcname); outnstr(".off = 0"); } } else if (optimise && !callersaves) { outstr(funcname); outstr(".off = "); #ifndef I80386 outnhex(4); #else outnhex(i386_32?12:4); #endif } #endif clearfunclabels(); } /* idecllist() - list of init-declarations with a given base type */ /* this does the non-terminal symbols list( init-declarator ) ";" */ /* and list( type-declaration ) ";" */ /* and complete declarations of functions */ PRIVATE void idecllist() { struct typestruct *basetype; struct typestruct *inittype; scopelev_t levelmark; uoffset_T newoffset; argsallowed = level == GLBLEVEL; levelmark = level; basetype = gvartype; while (sym != SEMICOLON) { gvartype = basetype; declarator(); if (gvarname[0] == 0) needvarname(); if (gvartype->constructor == FUNCTION) { if (sym != COMMA && sym != SEMICOLON) { if (level == ARGLEVEL && gvarsc != TYPEDEFDECL) declfunc(); else error("illegal non-external function"); if (level != levelmark) { oldlevel(); locptr = &locsyms[0]; } argsallowed = FALSE; return; } } if (level != levelmark) { oldlevel(); locptr = &locsyms[0]; } argsallowed = FALSE; if (level == ARGLEVEL) { if (gvarsymptr == NULL) gvarsymptr = addglb(gvarname, gvartype); /* error soon */ declarg(); } else if (gvarsymptr != NULL && (gvarsymptr->level == level || gvartype->constructor == FUNCTION || (gvarsc == EXTERNDECL && gvarsymptr->level == GLBLEVEL))) { if (gvarsymptr->level != GLBLEVEL || gvarsymptr->flags == KEYWORD) multidecl(gvarname); else if (gvarsymptr->type != gvartype) { if (gvartype->constructor != ARRAY || gvarsymptr->type->constructor != ARRAY || gvartype->nexttype != gvarsymptr->type->nexttype || (gvartype->typesize != 0 && gvarsymptr->type->typesize != 0)) multidecl(gvarname); else if (gvartype->typesize != 0) gvarsymptr->type = gvartype; } if (gvarsc == NULLDECL) gvarsymptr->flags &= ~EXTERNAL; } else if (level == GLBLEVEL || gvartype->constructor == FUNCTION || gvarsc == EXTERNDECL) { gvarsymptr = addglb(gvarname, gvartype); #ifdef DIRECTPAGE /* make all global scalar and pointer variables DIRECTPAGE */ if (!(gvartype->constructor & ~POINTER)) gvarsymptr->flags = DIRECTPAGE; #endif if (gvarsc == EXTERNDECL) gvarsymptr->flags |= EXTERNAL; } else { gvarsymptr = addloc(gvarname, gvartype); if ((gvarsc != REGDECL || !regdecl()) && gvartype->constructor != FUNCTION && gvarsc != STATICDECL && gvarsc != TYPEDEFDECL) gvarsymptr->offset.offi = softsp = (softsp & gvartype->alignmask) - gvartype->typesize; } if (gvarsc == STATICDECL) { gvarsymptr->flags &= ~EXTERNAL; gvarsymptr->flags |= STATIC; if (gvarsymptr->level != GLBLEVEL) { gvarsymptr->storage = GLOBAL; gvarsymptr->offset.offlabel = getlabel(); /* must leave gvarsymptr->name.label alone */ /* since name is required for findlorg() */ /* label is activated by expression() */ } } if (gvarsc == TYPEDEFDECL) { gvarsymptr->flags = KEYWORD; gvarsymptr->offset.offsym = TYPEDEFNAME; } #ifndef VERY_SMALL_MEMORY if (sym == ASSIGNOP || (ancient && sym == LBRACE)) #else if (sym == ASSIGNOP) #endif { /* This is always false for low-memory environments given */ /* there's no ancient switch there. */ int oldstyle = (sym == LBRACE); if (gvarsymptr->flags & INITIALIZED) multidecl(gvarname); /* If we're initializing an array, let's pretend there */ /* was a new-fashioned initializer with an equal sign */ if (oldstyle && gvartype->constructor == ARRAY) oldstyle = 0; else nextsym(); if (level == GLBLEVEL || gvarsc == STATICDECL) { #ifndef DIRECTPAGE dseg(); #else if (gvarsymptr->flags & DIRECTPAGE) dpseg(); else dseg(); #endif if ((inittype = gvartype)->constructor == ARRAY) inittype = inittype->nexttype; newoffset = (dataoffset + ~inittype->alignmask) & inittype->alignmask; defnulls(newoffset - dataoffset); dataoffset = newoffset; if (gvarsc == STATICDECL) { if (level == GLBLEVEL) private(gvarname); else outnlabel(gvarsymptr->offset.offlabel); } else public(gvarname); initlistflag = TRUE; if (sym != LBRACE) initlistflag = FALSE; inititem(gvartype); dataoffset += (gvarsymptr->type = gvartype)->typesize; if (gvarsymptr->level == GLBLEVEL) gvarsymptr->flags |= INITIALIZED; if (level != GLBLEVEL) cseg(); } else { if (gvarsc == EXTERNDECL) error("initialization of externs is illegal"); switch (gvartype->constructor) { case ARRAY: error("initialization of auto arrays is illegal"); break; case FUNCTION: error("initialization of functions is illegal"); break; default: initexpression(gvartype); break; } } if (oldstyle) rbrace(); } else if (level != GLBLEVEL && gvarsc == STATICDECL && gvartype->constructor != FUNCTION) { #ifndef DIRECTPAGE bssseg(); #else if (gvarsymptr->flags & DIRECTPAGE) dpseg(); else dseg(); #endif lcommlab(gvarsymptr->offset.offlabel); outnhex(gvartype->typesize); cseg(); } if (sym != COMMA) break; nextsym(); } semicolon(); argsallowed = FALSE; } PRIVATE void initarray(type) struct typestruct *type; { uoffset_T basesize; struct typestruct *basetype; uoffset_T dimension; char *stringend; uoffset_T stringlength; uoffset_T remaining; if ((basesize = (basetype = type->nexttype)->typesize) == 0) dimension = remaining = 0; else dimension = remaining = type->typesize / basesize; if (sym == STRINGCONST && (basetype->scalar & CHAR)) { stringlength = (stringend = charptr) - constant.value.s; if (remaining != 0 && stringlength >= remaining) /* same dim should be allowed but defstr always nullterms */ { error("string longer than dimension"); stringend = constant.value.s + (/* size_t */ unsigned) (stringlength = remaining - 1); } defstr(constant.value.s, stringend, TRUE); remaining -= (stringlength + 1); nextsym(); } else do inititem(basetype); while (--remaining != 0 && sym == COMMA && initlistflag && (nextsym(), sym != RBRACE)); if (dimension == 0) { if (type == gvartype) gvartype = prefix(ARRAY, -remaining * basesize, basetype); } else defnulls(remaining * basesize); } PRIVATE void inititem(type) struct typestruct *type; { sym_t startsym; if ((startsym = sym) == LBRACE) nextsym(); switch (type->constructor) { case ARRAY: initarray(type); break; case STRUCTU: initstruct(type); break; case FUNCTION: error("initialization of functions is illegal"); break; default: initexpression(type); } if (startsym == LBRACE) { if (sym == COMMA) { nextsym(); if (sym != RBRACE) error("too many initializers"); } rbrace(); } } PRIVATE void initstruct(type) struct typestruct *type; { struct typestruct *memtype; uoffset_T newoffset; uoffset_T offset; struct typelist *typelist; offset = 0; if ((typelist = type->listtype) != NULL) do { memtype = typelist->tltype; newoffset = (offset + ~memtype->alignmask) & memtype->alignmask; defnulls(newoffset - offset); offset = newoffset + memtype->typesize; inititem(memtype); } while ((typelist = typelist->tlnext) != NULL && sym == COMMA && initlistflag && (nextsym(), sym != RBRACE)); /* eof here will break next time */ defnulls(type->typesize - offset); } PRIVATE void lbrace() { if (sym != LBRACE) need('{'); else nextsym(); } PUBLIC void lparen() { if (sym != LPAREN) need('('); else nextsym(); } PRIVATE void multidecl(sname) char *sname; { error2error(sname, " already declared"); } PRIVATE void need(charneeded) int charneeded; { static char message[] = "need 'x'"; message[6] = charneeded; error(message); } PUBLIC void needvarname() { error("need variable name"); nextsym(); } PUBLIC void program() { #ifdef BUILTIN_CPP if (orig_cppmode) cppscan(0); else #endif { nextsym(); while (sym != EOFSYM) { declspec(); idecllist(); } } } PUBLIC void rbrace() { if (sym != RBRACE) need('}'); else nextsym(); } PUBLIC void rbracket() { if (sym != RBRACKET) need(']'); else nextsym(); } PRIVATE void rdeclarator() { while (sym == STAR) { nextsym(); gvartype = pointype(gvartype); } if (sym == LPAREN) { struct typestruct *pretype; struct typestruct *sufftype; nextsym(); sufftype = gvartype; gvartype = ctype; rdeclarator(); rparen(); pretype = gvartype; gvartype = sufftype; declaf(); gvartype = chainprefix(pretype, gvartype); } else if (sym == IDENT || sym == TYPEDEFNAME) { strcpy(gvarname, gsname); gvarsymptr = gsymptr; nextsym(); } else { gvarname[0] = 0; gvarsymptr = NULL; } declaf(); } PRIVATE bool_pt regdecl() { store_t regavail; #if !NOTFINISHED if (gvarsymptr->type->constructor != POINTER) return FALSE; #endif #ifdef MC6809 if (gvarsymptr->type->constructor != POINTER) return FALSE; #endif if (!(regavail = regregs & ~reguse)) return FALSE; gvarsymptr->flags = REGVAR; gvarsymptr->indcount = 0; #define LOWBITMASK(bits) (bits - (bits & (bits - 1))) /* & chops low bit */ reguse |= gvarsymptr->storage = LOWBITMASK(regavail); return TRUE; } PUBLIC void rparen() { if (sym != RPAREN) need(')'); else nextsym(); } PUBLIC void semicolon() { outnstr("!BCC_EOS"); if (sym != SEMICOLON) need(';'); else nextsym(); } PUBLIC struct typestruct *typename() { char ogvarname[NAMESIZE]; sym_t ogvarsc; struct symstruct *ogvarsymptr; struct typestruct *ogvartype; struct typestruct *type; /* the global variable data must be preserved */ /* although this is only called for casts and sizeof, */ /* the casts can be in initialisers */ /* and the sizeof in an array size expression */ strcpy(ogvarname, gvarname); ogvarsc = gvarsc; ogvarsymptr = gvarsymptr; ogvartype = gvartype; if (declspec()) { declarator(); if (gvarsc != NULLDECL || gvarname[0] != 0) error("illegal type name"); type = gvartype; } else type = NULL; strcpy(gvarname, ogvarname); gvarsc = ogvarsc; gvarsymptr = ogvarsymptr; gvartype = ogvartype; return type; } #ifndef VERY_SMALL_MEMORY PUBLIC int lastanon() { return anons; } PUBLIC void anonname(name, i) char *name; int i; { if (i == 0xfff) fatalerror("Too many anonymous structs/unions"); sprintf (name, "__an%03x", i); } PUBLIC void anonstruct() { anonname (gvarname, anons++); } #endif