Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_FS_1_19910112
-
c/old/kcc/ccdecl.c
There are 8 other files named ccdecl.c in the archive. Click here to see a list.
/* <KCC.CC>CCDECL.C.151, 20-Jul-85 15:52:07, Edit by KRONJ */
/* Make normal tsize of pointer zero so can have nonzero tsize */
/* for array coerced to pointer so int x[]; sizeof x; can work */
/* <KCC.CC>CCDECL.C.149, 27-Jun-85 13:22:52, Edit by KRONJ */
/* Don't ignore static in function declaration */
/* <KCC.CC>CCDECL.C.148, 19-Jun-85 10:54:43, Edit by KRONJ */
/* Improve entry statement for #asm in middle, funny ident chars */
/*
** ccdecl - Declaration parser for KCC
** (C) 1981 K.Chen
*/
#include "cc.h"
/* functions from outside used herein */
extern struct SYMBOL *findsym(), *creatsym(), *creatloc(), *newlabel();
extern struct TY *findtype();
extern node expression(), statement(), defnode();
extern int nextoken(), expect();
extern void warn(), error(), outsym(), nl();
/* functions herein exported to the outside */
struct TY *typename(), *typespec();
void extdef(), decllist();
int pconst(), tsize();
/* functions used entirely internally */
void entstmt(), funcdef(), datadef(), decln(), idecllist();
int sdecllist(), sdeclunion(), sdeclstruct(), fldsize(), tmismatch(), pscope();
node izer(), pizer();
struct SYMBOL *declarator();
struct TY *decl0(), *addpp(), *pushtype(), *strspec(), *enumspec();
struct SMEM **sdeclaration();
/* ------------------------------------- */
/* process external definition */
/* ------------------------------------- */
void
extdef()
{
struct SYMBOL *s, tempsym, base, *fn;
struct TY *t;
char *cp;
int sval;
if (!firstime) { /* first time through here? */
while (token == ENTRY) {
s = csymbol; /* get symbol */
if (nextoken() != IDENT) { /* must be followed by ident */
tokpush (ENTRY, 0); /* put ENTRY back on stack */
break; /* stop doing entry statements */
}
entstmt(); /* process entry statements */
}
firstime++; /* don't do this again */
freesym (findsym ("entry")); /* flush "entry" reserved word */
if (token == ENTRY) { /* if we found a bogus entry */
strcpy (ident, "entry"); /* put it back into ident string */
lexident(); /* turn back into IDENT token */
} else if (token == IDENT) for (cp = csymbol->sname; *cp != '\0'; cp++)
if (*cp == '$' || *cp == '%') { /* make sure ident clean */
error (EIDENT); /* not, so complain */
*cp = '\0'; /* break out of loop */
}
if (eof) return; /* go back if no more to do */
}
scope = XTERN; /* default to global */
tempsym.sname[0] = '\0'; /* init symbol */
tempsym.sclass = pscope(); /* parse scope */
tempsym.svalue = 0; /* no val yet */
tempsym.sptr = typespec(); /* parse type */
if (token == SCOLON) { /* just the type (struct)? */
nextoken(); /* yes, skip over final semi */
return; /* and stop doing this def */
}
copysym(&base,&tempsym);
curfnnew = line; /* remember where line started */
if ((s = declarator(&tempsym,0)) == NULL) return;
fn = s; /* remember function symbol */
sval = s->svalue; /* save value for later */
s->svalue = (int) (struct SYMBOL *) NULL; /* no args */
t = s->sptr;
if (t->ttype == FNDEF) { /* parsed "fnname (" */
scope = SARG;
while (1) { /* parameter-list */
if (token != IDENT) break; /* must be parameter */
symcpy(base.sname, csymbol->sname); /* save name */
if (csymbol->sclass == SUNDEF) freesym(csymbol); /* flush global */
s->svalue = (int) creatloc(base.sname); /* get local, chain args */
s = (struct SYMBOL *) s->svalue; /* move on to end of chain */
s->sclass = SARG; /* this is a fun arg */
s->svalue = (int) (struct SYMBOL *) NULL; /* so far its the last */
s->sptr = deftype; /* integer unless declared */
nextoken();
if (token != COMMA) break;
nextoken();
}
expect(RPAREN);
fn->sptr = findtype (FUNCTION, PTRSIZE, fn->sptr->tptr);
} else if (t->ttype != FUNCTION || token == COMMA || token == SCOLON ||
token == ASGN) {
fn->svalue = sval; /* restore saved value */
datadef(s, &base); /* extern fun or variable */
return;
}
s = (struct SYMBOL *) fn->svalue; /* get arglist back */
fn->svalue = sval; /* restore saved value */
funcdef(fn,s); /* internal fun */
}
/* ----------------------------------- */
/* type-name Ref.[1] A.8.7 */
/* ----------------------------------- */
struct TY *
typename()
{
struct SYMBOL s, *t;
s.sname[0] = '\0';
s.sclass = s.svalue = 0;
s.sptr = typespec();
t = declarator(&s, 3);
return t->sptr;
}
/* ----------------------------------------- */
/* parse for a constant expression */
/* ----------------------------------------- */
int
pconst()
{
node e;
e = expression();
if (e->nop != ICONST) {
error(ECONST);
return 0;
}
return e->niconst;
}
/* ----------------------------------------- */
/* declaration-list Ref.[1] A.18.3 */
/* ----------------------------------------- */
void
decllist()
{
int n;
while (csymbol != NULL) {
if ((n = csymbol->sclass) == SRW) {
n = csymbol->skey;
if (n != TYPESPEC && n != SCSPEC && n != SUSPEC) return;
} else if (n != STYPEDEF) return;
decln();
}
}
/* ----------------------- */
/* size of type */
/* ----------------------- */
int
tsize(t)
struct TY *t;
{
int s;
if (t == NULL) return 0; /* izlist => izer0/1 does this, why? */
/* calculate factor for array dimensions */
s = 1; /* nothing multiplied in yet */
while (t->ttype == ARRAY) { /* array has to multiply out ranges */
s *= t->tsize; /* so multiply it in with rest */
t = t->tptr; /* and go to next in chain */
}
/* multiply that by size of base type */
if ((t->ttype == STRUCT || t->ttype == UNION) && t->tsize < 0) {
if (t->tvar.tsym->sclass != STAG)
error (ESTRSIZE, t->tvar.tsym->sname + 1);
s *= t->tvar.tsym->svalue; /* finish up size of tagged struct */
} else if (t->ttype == CHAR) s = (s + NBYTES - 1) / NBYTES; /* chr array */
else if (t->ttype == PTR) s *= PTRSIZE; /* pointer to anything */
else s *= t->tsize; /* or of other type */
return s; /* return final number of words */
}
/* --------------------------------------- */
/* type-specifier Ref[1] A.18.2 */
/* --------------------------------------- */
struct TY *
typespec()
{
int signed, size;
struct TY *t;
t = NULL; /* no type given yet */
signed = 0; /* signed unless marked otherwise */
size = 0; /* no size given */
while (csymbol != NULL) {
switch (csymbol->skey) {
case TYPESPEC:
switch (token) {
case UNSIGNED:
if (signed) error(ETYPCOMB); /* only one of these */
signed = token; /* remember we got one */
break;
case SHORT:
case LONG:
if (size) error(ETYPCOMB); /* only one of these */
size = token; /* remember we got one */
break;
default:
error(ETYPCOMB); /* huh? */
}
nextoken(); /* move to next token */
continue; /* and continue with loop */
case SUSPEC:
if (signed || size) error(ETYPCOMB); /* can't qualify struct */
return strspec(); /* just go do it */
default:
if (t == NULL && token == IDENT && csymbol->sclass == STYPEDEF) {
t = csymbol->sptr; /* get the type */
nextoken(); /* skip over it */
continue; /* on to next */
}
} /* end switch(csymbol->skey) */
break; /* fall out of loop for default case */
} /* end while(csymbol != NULL) */
return (t == NULL)? deftype : t;
}
/* ------------------------------------ */
/* declarator Ref[1] A.18.2 */
/* */
/* tag = 0 normal */
/* = 1 structure tag */
/* = 2 func arguments */
/* = 3 abstract decl */
/* ------------------------------------ */
static struct SYMBOL *
declarator (s, tag)
struct SYMBOL *s;
{
s->sptr = decl0(s, s->sptr, tag);
switch (s->sptr->ttype) {
case ARRAY:
if (tag == 2) /* change array as arg to ptr */
s->sptr = pushtype(PTR, 0, s->sptr->tptr);
break;
case FLOAT:
if (tag == 2) s->sptr = dbltype; /* change float arg to double */
break;
case VOID:
if (tag != 3 && s->sclass != STYPEDEF)
error (EVOID, (tag == 1? s->sname + 1 : s->sname));
break;
}
return s;
}
/* ------------------------------------- */
/* parse type for declarator() */
/* ------------------------------------- */
static struct TY *
decl0 (s, t, tag)
struct SYMBOL *s;
struct TY *t;
{
struct TY *pp;
/* parse stars before main type part */
while (token == MPLY) {
t = pushtype (PTR, 0, t);
nextoken();
}
/* now parse main type part */
switch (token) {
case LPAREN:
nextoken(); /* move over paren */
pp = decl0(s, NULL, tag); /* parse stuff in parens */
expect(RPAREN);
break;
case IDENT:
if (tag == 3) error(SYNTAX); /* cast or sizeof, ident not allowed */
else if (tag == 1) {
symcpy(s->sname, "#"); /* prefix for struct members */
symapp(s->sname, csymbol->sname);
if (csymbol->sclass == SUNDEF) freesym(csymbol);
} else symcpy(s->sname, csymbol->sname);
nextoken();
default:
pp = NULL; /* no paren part */
break;
}
/* function and array specifier part */
while(1) {
switch (token) {
case LPAREN:
nextoken();
switch (token) {
case RPAREN:
nextoken();
pp = addpp(pp, pushtype(FUNCTION, PTRSIZE, NULL));
break;
case IDENT:
return addpp(pp, pushtype (FNDEF, PTRSIZE, t));
/* function declaration with arguments, return pointing */
/* to the first argument still. */
default:
error(SYNTAX);
}
break;
case LBRACK:
nextoken();
pp = addpp(pp, pushtype(ARRAY,
(token == RBRACK)? 0 : pconst(),
NULL));
expect(RBRACK);
break;
default:
/* go back and add paren part, return the result */
return addpp(pp, t);
}
}
}
/* --------------------------------------- */
/* add type to inside of nesting */
/* --------------------------------------- */
static struct TY *
addpp (pp, t)
struct TY *pp, *t;
{
/*
** This takes a base-less type structure in pp, and returns the
** result of replacing the NULL where the base should be with t.
** Thus it is the inverse of pushtype(), adding the new type
** at the base of the structure rather than at the top.
**
** I realize the recursive definition below may look messy,
** but an iterative definition of this function would be worse...
*/
return (pp != NULL)?
pushtype(pp->ttype, pp->tsize, addpp(pp->tptr, t)) :
t;
}
/* ----------------------------------------------------------- */
/* Check for valid type combinations and return type */
/* ----------------------------------------------------------- */
static struct TY *
pushtype(typ, siz, ptr)
struct TY *ptr;
{
/* check for functions returning other functions */
if (ptr != NULL) switch (typ) {
case ARRAY:
switch (ptr->ttype) {
case VOID:
error (EVOID, "array element");
break;
case ARRAY:
if (ptr->tsize != 0) break; /* array[][x] ok, array[x][] not */
case FUNCTION:
case FNDEF:
error(ETYPCOMB);
ptr = NULL;
}
break;
case FUNCTION:
case FNDEF:
switch (ptr->ttype) {
case ARRAY:
case FUNCTION:
case FNDEF:
error(ETYPCOMB);
ptr = NULL;
}
}
/* now hash up the actual type and return the canonicalized version */
return findtype (typ, siz, ptr);
}
/* --------------------------------------- */
/* entry statement Ref[1] A.2.3 */
/* --------------------------------------- */
static void
entstmt()
{
while (1) {
outstr ("\tENTRY\t"); /* make ENTRY statement */
outsym (csymbol->sname); /* before we call expect() */
nl(); /* so #asm in middle won't screw us */
expect (IDENT); /* it better have been a sym */
if (token != COMMA) break; /* repeat while we have more */
nextoken(); /* skip COMMA */
}
expect(SCOLON); /* end with semicolon */
}
/* -------------------------------------------------- */
/* struct-or-union specifier Ref[1] A.18.2 */
/* -------------------------------------------------- */
static struct TY *
strspec()
{
struct SYMBOL s, *tagname;
struct TY *t; /* really either SMEM or SYMBOL */
int typ, siz;
typ = token; /* remember whether struct or union */
nextoken();
if (typ == ENUM) return enumspec(); /* enum, go handle differently */
if (token != IDENT) {
expect(LBRACE); /* gotta have something */
siz = sdecllist(&t, typ == UNION); /* parse unnamed struct */
} else { /* tagged struct */
symcpy(s.sname, "%"); /* tptr points to tag, */
symapp(s.sname, csymbol->sname); /* tag->sptr points to smems */
if (csymbol->sclass == SUNDEF) freesym(csymbol);
if ((tagname = findsym(s.sname)) == NULL) { /* no such struct? */
tagname = creatsym(s.sname); /* make a new tag symbol */
tagname->sclass = SUNDEF; /* but with no defined body */
}
nextoken(); /* skip over ident */
if (token == LBRACE) { /* struct FOO { */
if (tagname->sclass != SUNDEF) /* can't define twice */
error((typ == STRUCT)? EDSTRUC : EDUNION, s.sname + 1);
nextoken(); /* skip over open brace */
tagname->sclass = STAG; /* this is now a defined struct */
tagname->svalue = sdecllist(&tagname->svar.ssmem, typ == UNION);
}
siz = -1; /* special size means tagged */
t = (struct TY *) tagname; /* with the tag we found or made */
}
return findtype(typ, siz, t); /* look up its type */
}
/* ------------------------------------------ */
/* struct-decl-list Ref.[1] A.8.5 */
/* ------------------------------------------ */
static int
sdecllist(smem, isunion)
struct SMEM **smem;
{
if (isunion) return sdeclunion(smem);
return sdeclstruct(smem);
}
static int
sdeclunion(smem)
struct SMEM **smem;
{
int maxsize, offset, boffset;
maxsize = 0;
while (token != RBRACE) {
if (eof) earlyend();
offset = boffset = 0; /* each member starts at zero */
smem = sdeclaration(smem, &offset, &boffset);
if (boffset > 0) offset++; /* round out to full word */
if (offset > maxsize) maxsize = offset; /* find max with old size */
}
nextoken(); /* skip over close brace */
return maxsize; /* largest elt size is union size */
}
static int
sdeclstruct(smem)
struct SMEM **smem;
{
int offset, boffset;
offset = boffset = 0; /* structure starts at zero */
while (token != RBRACE) {
if (eof) earlyend();
smem = sdeclaration(smem, &offset, &boffset);
}
nextoken(); /* skip over close brace */
if (boffset > 0) offset++; /* round offset out to full word */
return offset; /* return as size of struct */
}
/* -------------------------------------------- */
/* struct-declaration Ref.[1] A.8.5 */
/* -------------------------------------------- */
static struct SMEM **
sdeclaration (smem, offset, boffset)
struct SMEM **smem;
int *offset, *boffset;
{
struct SYMBOL base, tempsym, *t, *u;
int s;
base.sname[0] = '\0';
base.sclass = SMEMBER;
base.svalue = 0;
base.sptr = typespec();
while (1) {
if (token == COLON) {
/*
** Colon without declarator before it - specifies space
** left for alignment. Constant expression following
** colon is how much space, or zero to align to a word.
*/
nextoken(); /* skip over colon */
s = fldsize(offset, boffset); /* parse size */
if (s == 0 && *boffset > 0) { /* if rounding to word offset */
*boffset = 0; /* round off bit offset */
(*offset)++; /* and move up to next word bdy */
}
} else {
/*
** Normal declarator. Parse it, then check if there is
** a colon expression after it making it a bit field, or
** if it is a whole word expression.
**
** For bitfields, the offset is encoded as follows:
** s % 07777 - high 12 bits of byte pointer to the field
** s >> 12 - word offset in struct
** and then the whole thing is negated.
**
** Note that we let the bit offset remain at 36 rather
** than folding it to zero - the calculations are easier.
*/
copysym(&tempsym, &base);
t = declarator(&tempsym, 1);
if (token == COLON) { /* bitfield */
nextoken(); /* move over colon */
s = fldsize(offset, boffset);
s = -(((*offset * 64) + 36 - *boffset) * 64 + s);
} else { /* normal size member */
if (*boffset > 0) { /* if we need to go to a word bdy */
*boffset = 0; /* do it */
(*offset)++; /* and move up */
}
s = *offset; /* starts at offset */
*offset += tsize(t->sptr); /* remember size */
}
/*
** Now we have parsed the declarator, and the encoded
** offset is in s. Make a new symbol, or make sure that
** this is the same as the old one.
*/
u = findsym(t->sname); /* look up member name */
if (u == NULL) { /* struct member not seen before */
t->sclass = SMEMBER; /* remember that it is a struct mem */
t->svalue = s; /* with the given offset */
u = creatsym(t->sname); /* make a permanent location */
copysym(u, t); /* store it */
} else if (s != u->svalue || u->sptr != t->sptr) {
u->svalue = AMBIGMEM; /* deglobalize */
}
*smem = &smems[maxsmem++]; /* get new struct mem pointer */
(*smem)->smem = u; /* remember the pointer */
(*smem)->smnext = NULL; /* no pointer */
(*smem)->smoffset = s; /* keep offset locally */
(*smem)->smtype = t->sptr; /* keep type locally */
smem = &(*smem)->smnext; /* but that is where next one goes */
}
if (token != COMMA) break;
nextoken();
}
expect(SCOLON);
return smem; /* return with latest pointer */
}
/* ----------------------------- */
/* parse bitfield size */
/* ----------------------------- */
static int
fldsize(offset, boffset)
int *offset, *boffset;
{
int s;
s = pconst(); /* get num bits */
if (s > 36 || s < 0) error(EBFSIZE); /* range check */
*boffset += s; /* advance by that many bits */
if (*boffset > 36) { /* not enough room */
*boffset = s; /* move bit offset to word bdy */
(*offset)++; /* in next word */
}
return s; /* return with size */
}
/* ------------------------- */
/* enumerated type */
/* ------------------------- */
static struct TY *
enumspec()
{
int val;
struct SYMBOL *s;
if (token == IDENT) { /* ignore enum name */
if (csymbol->sclass == SUNDEF) freesym(csymbol);
nextoken();
}
if (token == LBRACE) { /* is this definition? */
val = 0; /* start at zero */
do {
nextoken(); /* skip comma or brace */
s = csymbol; /* get identifier */
expect (IDENT); /* that better be what it is */
if (token == ASGN) {
nextoken(); /* want specific value for this one */
val = pconst(); /* so set it to given constant */
}
if (s->sclass != SUNDEF) error(EDSYMB, s->sname);
s->sclass = SENUM; /* this is an enum */
s->svalue = val++; /* with this value */
s->sptr = deftype; /* acting like an int */
} while (token == COMMA);
expect(RBRACE); /* done with def, end with right */
}
return deftype; /* treat as integer */
}
/* -------------------------------------------- */
/* function-definition Ref[1] A.18.4 */
/* -------------------------------------------- */
static void
funcdef (s,args)
struct SYMBOL *s, *args;
{
int n, siz;
struct TY *t;
node nnode, header;
struct SYMBOL *s1, *s2, stemp;
s1 = findsym(s->sname);
if (s->sclass == XTERN) {
s->sclass = SEXTERN;
s->svalue = 1;
}
/* remember context for error messages */
curfn = s1;
curfnloc = curfnnew;
/* check for multiple decl */
if (s1->sclass == SUNDEF) ;
else if (s1->sclass != SEXTERN || s1->svalue) error (EDSYMB, s->sname);
else if (tmismatch (s1->sptr, s->sptr)) warn (ETWOTYP, s->sname);
copysym (s1, s); /* fix up symbol to fit new decl */
siz = tsize (s1->sptr->tptr); /* get size of return val for later */
header = defnode(N1, 0);
header->left = defnode(N2, IDENT, s1->sptr, 0, s1);
nnode = defnode(N2, FUNCTION, NULL, 0, header);
/* parse declarations of arguments */
while (token != LBRACE && token != EOF) { /* type-decl-list */
if (token == REGISTER) nextoken(); /* Ignore REGISTER on args */
t = typespec();
while (1) {
stemp.sname[0] = '\0'; /* no symbol given yet */
stemp.sptr = t; /* base is parsed type name */
s1 = declarator(&stemp, 2); /* look up type structure and sym */
if ((s2 = findsym(s1->sname)) == NULL || s2->sclass != SARG)
error(ENOTARG, s1->sname); /* not an arg to this fn */
else s2->sptr = s1->sptr; /* is, set type to what we parsed */
if (token != COMMA) break; /* repeat through list */
nextoken(); /* skipping over commas */
}
expect(SCOLON); /* decl line ends with a semicolon */
}
/* now that types are set, make sizes of local vars */
n = 0; /* set up for first arg */
if (siz > 2) n = siz; /* allow space for struct return */
while (args != NULL) {
s1 = args; /* get arg symbol */
args = (struct SYMBOL *) args->svalue; /* move on */
n += tsize(s1->sptr); /* count off by size */
s1->svalue = n; /* set offset */
}
maxauto = 0; /* no local variables yet */
stackrefs = 0; /* and therefore no refs to them */
scope = SAUTO; /* function-statement */
nnode->right = defnode(N3, STATEMENT, NULL, 0,
defnode(N1, RETURN), statement()); /* parse body */
gencode(nnode); /* emit code for function */
ridauto(); /* flush local variables */
}
/* ----------------------------------------- */
/* sc-type, type-specifier, symbol */
/* Ref[1] A.18.4 */
/* ----------------------------------------- */
static void
datadef (s, base)
struct SYMBOL *s, *base;
{
struct SYMBOL t;
node z;
z = NULL;
while (1) {
z = defnode(N3, DATA, NULL, 0, z, izer(s));
if (token != COMMA) break;
nextoken();
copysym(&t, base);
s = declarator(&t, 0);
}
if (!expect(SCOLON) && token == RBRACE) nextoken();
gencode(z);
}
/* ----------------------- */
/* initializer */
/* Ref.[1] A.8.6 */
/* ----------------------- */
static node
izer (s)
struct SYMBOL *s;
{
struct SYMBOL *t;
struct TY nt, *tp;
node y, z;
int cnt;
char *c;
/* hack null array */
if (s->sclass == XTERN && s->sptr->ttype == ARRAY && s->sptr->tsize == 0 &&
token != ASGN) s->sclass = SEXTERN; /* nothing here, pretend extern */
/* look up ident in symbol table */
t = findsym(c=s->sname); /* look it up in symbol table */
if (s->sptr->ttype == FUNCTION) { /* extern or auto function def? */
if (t->sclass == SUNDEF) { /* seen this function before? */
freesym(t); /* no, get rid of local cell */
t = creatsym(c); /* create an entry in global table */
t->sclass = SEXTERN; /* external unless we see body */
t->svalue = 0; /* mark as a decl (not definition) */
t->sptr = s->sptr; /* copy type definition we had */
} else if (tmismatch (t->sptr, s->sptr)) warn (ETWOTYP, c);
if (s->sclass == SSTATIC) t->sclass = SSTATIC; /* make static */
return NULL; /* function decl doesn't use storage */
}
/* real variable, do things depending on class */
switch (s->sclass) {
case SAUTO: /* local to function */
if (t->sclass == SUNDEF) freesym(t); /* release sym pointer */
t = creatloc(c); /* make cell known to be local */
s->svalue = maxauto; /* remember its stack offset */
maxauto += tsize(s->sptr); /* and count it in to frame size */
if (token == ASGN && (s->sptr->ttype == ARRAY ||
s->sptr->ttype == STRUCT))
error(EBINIT); /* say no good for auto */
break;
case SEXTERN: /* extern, not defined here */
s->svalue = 0;
case STYPEDEF: /* type definition */
if (t->sclass == SUNDEF) {
freesym(t); /* get rid of local symbol */
t = creatsym(c); /* and make a global one */
s->svalue = 0; /* marked as an extern */
copysym(t, s); /* fill in rest of symbol */
} else if (t->sclass != s->sclass) error (EDSYMB, c);
else if (tmismatch (t->sptr, s->sptr)) warn (ETWOTYP, c);
return NULL; /* no initialization or storage */
case XTERN: /* extern, defined here */
s->sclass = SEXTERN; /* make extern for rest of file */
s->svalue = 1; /* mark as INTERN if memory */
if (t->sclass == SEXTERN && t->svalue == 0) {
if (tmismatch (t->sptr, s->sptr)) warn (ETWOTYP, c);
t->sclass = SUNDEF;
}
case SSTATIC: /* extern, not visible as global */
if (scope == SAUTO) { /* "own" variable? */
if (t->sclass == SUNDEF) freesym(t); /* yes, flush glob sym */
t = creatloc(c); /* and make local cell */
s->sclass = SISTATIC; /* internal static */
s->sval.ssym = newlabel (1); /* create handle on object */
break;
} else if (t->sclass == SUNDEF) {
freesym(t); /* no, get rid of local symbol */
t = creatsym(c); /* and make a global one */
} else error (EDSYMB, c);
}
copysym(t, s); /* fill out the symbol */
/* parse initializer */
if (token == ASGN) {
nextoken(); /* skip equal sign */
cnt = 0; /* 0 initializers seen */
z = pizer(&cnt); /* read initializer */
} else z = NULL;
y = defnode(N2, IDENT, t->sptr, 0, t); /* make a node giving its name */
return defnode(N3, IZ, NULL, 0, y, z); /* and what to fill it with */
}
/* --------------------------- */
/* parse initializer */
/* --------------------------- */
static node
pizer(cnt)
int *cnt;
{
node root, n;
if (token != LBRACE) {
return expression(); /* not list, simple init */
}
nextoken(); /* skip open brace */
root = n = defnode(N3, IZLIST, NULL, 0, pizer(0), NULL);
if (cnt)
(*cnt)++;
while (token == COMMA) {
nextoken(); /* skip comma */
if (token == RBRACE) break; /* allow comma at end of initializer */
n = n->right = defnode(N3, IZLIST, NULL, 0, pizer(0), NULL);
if (cnt)
(*cnt)++;
}
expect(RBRACE); /* finish with close brace */
return root; /* return whole thing */
}
/* -------------------------------------- */
/* declaration Ref.[1] A.18.2 */
/* -------------------------------------- */
static void
decln ()
{
struct SYMBOL s;
s.sclass = pscope();
s.sptr = typespec();
s.sname[0] = 0;
idecllist(&s);
expect(SCOLON);
}
/* ------------------------------------------- */
/* check two types for compatibility */
/* ------------------------------------------- */
static int
tmismatch (t1, t2)
struct TY *t1, *t2;
{
if (t1 == t2) return 0;
if (t1->ttype != ARRAY || t2->ttype != ARRAY) return 1;
if (t1->tptr != t2->tptr) return 1;
return (t1->tsize != 0 && t2->tsize != 0);
}
/* --------------------------------------- */
/* parse storage class specifier */
/* --------------------------------------- */
static int
pscope()
{
switch (token) {
case AUTO:
nextoken();
return scope;
case STATIC:
nextoken();
return SSTATIC;
case EXTERN:
nextoken();
return SEXTERN;
case REGISTER:
nextoken();
return scope; /* ignore register decl */
case TYPEDEF:
nextoken();
return STYPEDEF;
}
return scope; /* no storage class, return default */
}
/* ----------------------------------------------- */
/* init-declarator-list Ref.[1] A.18.2 */
/* ----------------------------------------------- */
static void
idecllist(base)
struct SYMBOL *base;
{
struct SYMBOL t;
node z;
int savemax;
if (scope == SAUTO && base->sclass != SSTATIC) z = decls;
else z = NULL;
while (1) {
copysym(&t, base);
z = defnode(N3, DATA, NULL, 0, z, izer(declarator(&t, 0)));
if (token != COMMA) break;
nextoken();
}
if (scope == SAUTO && base->sclass != SSTATIC) decls = z;
else {
savemax = maxnode;
gencode(z);
maxnode = savemax;
}
}