📄 ccdecl.c
字号:
t = uchartype;
break;
}
/* Special extension, drop thru to handle */
t = findctype((tflags&PF_SIGNED) ? TS_CHAR : TS_UCHAR,
qflags | chrsiz, 1, (TYPE *)NULL);
qflags = 0; /* Don't re-do these */
break;
case PF_SHORT:
case PF_SIGNED|PF_SHORT:
case PF_SHORT|PF_INT:
case PF_SIGNED|PF_SHORT|PF_INT:
t = shrttype;
break;
case PF_UNSIGNED|PF_SHORT:
case PF_UNSIGNED|PF_SHORT|PF_INT:
t = ushrttype;
break;
case PF_INT:
case PF_SIGNED:
case PF_SIGNED|PF_INT:
t = inttype;
break;
case PF_UNSIGNED:
case PF_UNSIGNED|PF_INT:
t = uinttype;
break;
case PF_LONG:
case PF_SIGNED|PF_LONG:
case PF_LONG|PF_INT:
case PF_SIGNED|PF_LONG|PF_INT:
t = longtype;
break;
case PF_UNSIGNED|PF_LONG:
case PF_UNSIGNED|PF_LONG|PF_INT:
t = ulongtype;
break;
case PF_DOUBLE:
t = dbltype;
break;
case PF_LONG|PF_DOUBLE:
t = lngdbltype;
break;
default:
error(errmsg); /* Say bad typespec combo */
if (nt == flttype || (tflags&PF_DOUBLE))
t = dbltype;
else
t = inttype;
}
}
if (qflags) /* Add qualifiers to the basic type */
{
INT oflag = 0;
if (t->Tspec == TS_FUNCT) /* See typedef comments */
advise ("Ignoring type-qualifiers for function type");
else if (t->Tspec == TS_ARRAY)
{
/*
* FEW, 2A(40), 5-August-92
*
* There was a problem with assigning qualifiers to typedef'ed
* arrays. The old code inadvertently attached the qualifier
* to the typedef itself as well as to the instance of it.
* The cure is qualarray (), a new recursive function that
* creates a new chain of types as deep as necessary.
*/
t = qualarray (t, qflags, &oflag);
}
else
t = findctype (t->Tspec, qflags | (oflag = t->Tflag),
t->Tsize, t->Tsubt);
if ((oflag &= qflags) != 0)
{
if (clevel >= CLEV_STRICT)
error("Redundant type qualifier \"%s\"",
(oflag&TF_CONST) ? "const" : "volatile");
else
warn("Redundant type qualifier \"%s\"",
(oflag&TF_CONST) ? "const" : "volatile");
}
}
if (symp)
symp->Stype = t;
return (INT) t;
}
static
TYPE*
qualarray (TYPE* type, int flags, int* oldflags)
{
/*
* FEW 2A(40) 5-August-92
*
* This is magic--not quite pure white, but a reasonably light grey.
* The problem is that, when we are trying to apply qualifiers to the
* base type of an n-dimensional array, we need to create n + 1 new
* types: a new base type, plus a new parent type for each dimension
* of the array. Since we do not know what the base type is going to
* be until we reach the bottom of the chain, we have to recurse.
*/
TYPE* subtype = type->Tsubt;
int findflags = flags;
if (type->Tspec == TS_ARRAY)
{
subtype = qualarray (subtype, flags, oldflags);
findflags = 0;
}
return findctype (type->Tspec, findflags | (*oldflags = type->Tflag),
type->Tsize, subtype);
}
/* TAGSPEC - Handles tag for struct/union/enum
*/
static TYPE *
tagspec(int typ) /* TS_STRUCT, TS_UNION, or TS_ENUM */
{
SYMBOL s, *tagsym, *osym;
int tok;
switch (nextoken())
{
case Q_IDENT: /* Have tag ident */
tagsym = symftag(osym = csymbol); /* Get existing tag if any */
if ((tok = nextoken()) == T_LBRACE)
nsdefs++; /* Defining, say decl has side effs */
/* (Note this clobbers csymbol) */
if (tok == T_SCOLON) /* new incomplete definition */
{
tagsym = NULL; /* Discard old tag, make new later */
nsdefs++;
}
break;
case T_LBRACE: /* No tag given, will have to make up internal one. */
tagsym = osym = NULL;
break;
default:
error("struct/union/enum not followed by tag or definition");
while (1)
switch (nextoken())
{
case T_EOF:
case T_RBRACE:
case T_SCOLON:
return NULL;
}
}
/* If a tag symbol already exists, check it to see whether we can use
** that one or need to create a new one. This also checks for
** duplicate definitions.
** Note that if this is a reference (not a definition) then we always
** just use whatever tagsym is.
*/
if (tagsym && token == T_LBRACE) /* If this will be a definition */
{
if (tagsym->Sclass == SC_TAG) /* Tag already defined? */
{
if (isdupsym(tagsym)) /* Dup def? */
error("Duplicate tag definition: %S", tagsym);
tagsym = NULL; /* Force a new definition */
}
else if (tagsym->Sclass == SC_UTAG) /* A ref already exists? */
{
if (!isdupsym(tagsym)) /* If not in same block, */
tagsym = NULL; /* don't satisfy the ref! */
}
}
if (tagsym && tagsym->Stype->Tspec != typ)
{
error("Tag redefined with different type: %S", tagsym);
tagsym = NULL;
}
/* If no tag (specified or internal) exists, make one and pretend it
** was seen as a forward reference (which it may well be).
*/
if (tagsym == NULL) /* Need tag symbol? */
{
if (osym) /* If already have an identifer, */
tagsym = symqcreat(osym); /* use that for quick sym setup! */
else /* No existing tag, invent one. */
/* Note (safe) assumption that ident string is big enough */
{
sprintf(s.Sname, "%c%d", SPC_TAG, ++itags);
tagsym = creatsym(s.Sname); /* Make symbol of right scope */
}
tagsym->Sflags |= SF_TAG;
tagsym->Sclass = SC_UTAG; /* but with no defined body */
tagsym->Ssmnext = NULL; /* No members yet */
tagsym->Srefs++; /* This creation is a reference too */
if (inproto) /* If created within fn prototype, */
tagsym->Sflags |= SF_PROTOTAG; /* flag it for ridlsym */
/* Create new type for it */
tagsym->Stype = findtype(typ, (TYPE *)tagsym);
tagsym->Stype->Tsmtag = tagsym; /* Make sure type points to tag */
}
if (osym && osym->Sclass == SC_UNDEF)
freesym(osym); /* Can flush orig sym now if unused */
if (token != T_LBRACE) /* If no definition, just return */
return tagsym->Stype;
/* Define the structure. */
nextoken(); /* Flush the left brace */
if (typ == TS_ENUM)
sdeclenum(tagsym);
else
tagsym->Stype->Tsize = sdeclstruct(tagsym, typ);
if (eof)
error("Unexpected EOF in declaration");
else
expect(T_RBRACE); /* Now flush the right brace */
tagsym->Sclass = SC_TAG; /* Struct is now defined */
return tagsym->Stype;
}
/* SDECLENUM - define enumeration type
*/
static void
sdeclenum(SYMBOL *tag)
{
INT val;
SYMBOL *s, *last;
s = NULL;
val = -1; /* start at zero (after pre-incrementing) */
last = tag;
for (;; nextoken())
{
if (token == T_RBRACE)
{
if (!s)
if (clevel >= CLEV_STRICT)
error("Empty enum definition list");
else
warn("Empty enum definition list");
break;
}
if (token != Q_IDENT)
{
error("Identifier expected as enum constant");
continue;
}
nsdefs++; /* Enum constant def as "side effect" */
s = csymbol; /* get identifier */
if (isdupsym(s))
errdupsym(s);
s = uniqsym(s); /* Create or re-use symbol as needed */
s->Sclass = SC_ENUM; /* this is an enum constant */
s->Stype = inttype; /* acting like an int */
s->Ssmtag = tag; /* Remember tag defined within */
s->Ssmnext = NULL;
last->Ssmnext = s; /* Link onto list of enum members */
last = s; /* MVS: fixed broken linked list! */
if (nextoken() == Q_ASGN)
{
nextoken(); /* want specific value for this one */
val = pconst(); /* so set it to given constant */
s->Svalue = val;
}
else
{
if (val == INT_MAX)
if (clevel >= CLEV_STRICT)
error("ENUM value will exceed INT_MAX");
else
warn("ENUM value will exceed INT_MAX");
s->Svalue = ++val;
}
if (token != T_COMMA)
break;
}
/* Current token should now be T_RBRACE. Caller will check. */
}
/* SDECLSTRUCT - Parse struct/union member list.
** Returns size in words of the struct/union.
*/
static INT
sdeclstruct(SYMBOL *tag, int typ)
{
SYMBOL *lastmem = tag;
INT maxsize = 0, offset = 0;
int boffset = 0, inbitf = 0;
int savpok = paramok;
paramok = 0; /* Not OK to collect param syms */
while (!eof && token != T_RBRACE)
{
lastmem = sdeclaration(tag, lastmem, &offset, &boffset, &inbitf);
if (typ == TS_STRUCT)
continue;
/* For union, each member starts over at beginning */
if (boffset > 0)
offset++; /* Round out to full word */
if (offset > maxsize) /* Remember size of largest element */
maxsize = offset;
offset = boffset = inbitf = 0; /* Start over with zero offset */
}
paramok = savpok; /* Restore saved paramok */
/* Return either total size (struct) or largest element size (union) */
if (typ == TS_STRUCT)
{
if (boffset > 0)
offset++; /* Round offset up to full word */
maxsize = offset; /* Total size is current offset */
}
if (maxsize == 0)
error("Empty %s declaration", typ == TS_STRUCT ? "struct" : "union");
return maxsize;
}
/* SDECLARATION - declare members of a struct or union
*/
static SYMBOL *
sdeclaration(SYMBOL *tag, SYMBOL *prevsmem, INT *offset, int *boffset,
int *inbitf)
{
SYMBOL base, tempsym, *u, *s;
INT offcode, bsiz;
int ts;
pbase(&base); /* Parse base storage-class and type
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -