diff options
Diffstat (limited to 'bcc/declare.c')
-rw-r--r-- | bcc/declare.c | 1124 |
1 files changed, 1124 insertions, 0 deletions
diff --git a/bcc/declare.c b/bcc/declare.c new file mode 100644 index 0000000..1dd1314 --- /dev/null +++ b/bcc/declare.c @@ -0,0 +1,1124 @@ +/* declare.c - declaration routines for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#include "const.h" +#include "types.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 */ + +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 && + gvarsc != TYPEDEFDECL && gvarsc != EXTERNDECL) + 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; + while (sym != SEMICOLON && sym != EOFSYM) + { + gvartype = basetype; + declarator(); + 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 ntype; + unsigned nunsigned; + + gvarsc = NULLDECL; + gvartype = itype; + 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 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 UNSIGNDECL: + ++nunsigned; + nextsym(); + break; + default: + goto break2; + } + } +break2: + if (nunsigned > 0) + { + if (ntype == 0) + { + gvartype = uitype; + ntype = 1; + } + gvartype = tounsigned(gvartype); + if (nunsigned > 1) + 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; + + strcpy(funcname, gvarname); + if (gvarsymptr == NULL) + gvarsymptr = addglb(gvarname, gvartype); + 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])) + { + /* 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 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 */ + } + lbrace(); + compound(); + 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; + } + if (sym == ASSIGNOP) + { + if (gvarsymptr->flags & INITIALIZED) + multidecl(gvarname); + 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; + } + } + } + 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() +{ + if (orig_cppmode) + cppscan(); + else + { + 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() +{ + 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; +} |