📄 ccdecl.c
字号:
** more closely so can give helpful error message (or barf at ourselves
** if necessary)
*/
if (t1 && t1->Tspec != TS_PARVOID && t2 && t2->Tspec != TS_PARVOID)
for (n = 1; t1 && t2; t1 = t1->Tproto, t2 = t2->Tproto, ++n)
if (t1->Tspec != t2->Tspec
|| (t1->Tspec == TS_PARAM && !cmputype(t1->Tsubt, t2->Tsubt)))
{
if (flag)
warn("Type of param #%d conflicts with prior def", n);
else
error("Type of parameter #%d conflicts with prior prototype", n);
return;
}
if (t1 != t2)
{
if (flag)
warn("Number of params conflicts with prior def");
else
error("Number of params conflicts with prior prototype");
}
else
int_warn("plcmpare: proto mismatch not found");
}
/* PLCMPOLD - Compare old-style parameter sym types against a
** prototype parameter list.
*/
static void
plcmpold(SYMBOL *s, TYPE *nt, TYPE *ot)
{
if (nt == ot)
return;
/* Prototypes don't match, try to give clever error msg */
for (; s; s = s->Spmnext, nt = nt->Tproto, ot = ot->Tproto)
if (!nt || !ot || nt->Tspec != ot->Tspec || nt->Tsubt != ot->Tsubt)
{
error("Type of parameter \"%s\" conflicts with prior prototype",
s->Sname);
return;
}
if (nt || ot)
error("Number of params conflicts with prior prototype");
else
int_warn("plcmpold: proto mismatch not found");
}
/* PLCHECK - Check a prototype parameter list to ensure that all types
** are compatible with default argument promotions. Note that use
** of an ellipsis param (TS_PARINF) is illegal in this context.
*/
static void
plcheck(TYPE *t)
{
if (t->Tspec == TS_PARVOID)
{
if (t->Tproto)
int_error("plcheck: void param");
}
else
for (; t; t = t->Tproto)
if (t->Tspec != TS_PARAM || !cmputype(t->Tsubt,convfparam(t->Tsubt)))
{
error("Conflict between prototype and default type reference");
break;
}
}
/* PDECLLIST - Parse the <decl-list> for an old-style function definition.
** [dpANS 3.7.1, 3.6.2]
**
** <decl-list> ::= *[<declaration>]
**
** The only storage-class spec allowed is "register". No initializations
** are permitted.
*/
static void
pdecllist(void)
{
TYPE *t;
SYMBOL *s1, argbase, stemp;
while (token != T_LBRACE && token != T_EOF) /* type-decl-list */
{
pbase(&argbase); /* Parse storage class and type specifier */
copysym(&stemp, &argbase);
switch (stemp.Sclass) /* Check storage class */
{
case SC_AUTO:
#if REGISTER_VARIABLES
if (!use_registers)
{
#endif
stemp.Sclass = SC_ARG;
break;
#if REGISTER_VARIABLES
}
/* else drop thru to error */
#endif
default:
error("Illegal storage class for function parameter");
case SC_UNDEF: /* Default becomes this. */
stemp.Sclass = SC_ARG;
break;
case SC_RAUTO: /* If "register" seen, */
stemp.Sclass = SC_RARG; /* use right symbol class */
break;
}
if ((t = stemp.Stype) == NULL) /* Check type-specifier */
{
if (argbase.Sclass == SC_UNDEF)
error("No type-specifier for parameter decl, assuming int");
t = deftype;
}
/* Have <decl-specs> base, now parse each <declor> */
while (1)
{
stemp.Sname[0] = '\0'; /* no symbol given yet */
stemp.Stype = t; /* Reset base type */
for(;;)
{
if ((s1 = declarator(&stemp)) != NULL) /* Get sym and rest of type */
break;
if (token == T_COMMA)
{
error("Null parameter declarator");
nextoken();
continue;
}
if (token == T_SCOLON)
{
nextoken();
break;
}
error("Bad parameter declaration token");
while (token != T_EOF && token != T_SCOLON && token != T_RBRACE)
nextoken(); /* Flush to probable end of stmt */
break; /* Will get two err msgs, but so what */
}
if (s1 == NULL)
error("Null parameter declaration, expecting ident");
else if (s1->Sclass != SC_ARG && s1->Sclass != SC_RARG)
{
error("Identifier \"%s\" not in function parameter list",
s1->Sname); /* not an arg to this fn */
if (s1->Sclass == SC_UNDEF)
freesym(s1); /* Clean up if boo-boo */
}
else if (s1->Sflags & SF_PARAMDECL)
{
error("Duplicate parameter declaration: \"%s\"",s1->Sname);
}
else /* Is arg, set type to what we parsed */
{
s1->Sclass = stemp.Sclass; /* Maybe indicate register */
s1->Sflags |= SF_PARAMDECL; /* Say decl seen for arg */
s1->Stype = convfparam(stemp.Stype); /* Get right type */
Set_Register(s1, SC_RARG, SC_ARG);
}
if (token != T_COMMA)
break; /* repeat through list */
nextoken(); /* skipping over commas */
}
expect(T_SCOLON); /* decl line ends with a semicolon */
}
}
/* MKPROTO - Make a prototype param type list out of a parameter symbol list.
** Must be recursive for same reason that paramlist() is.
** Note special handling for case of no symbols on list.
*/
static TYPE *
mkproto(SYMBOL *s)
{
return s ? mkprox(s) : findptype(TS_PARVOID, (TYPE *)NULL, (TYPE *)NULL);
}
static TYPE *
mkprox(SYMBOL *s)
{
return s ? findptype(TS_PARAM, mkprox(s->Spmnext), s->Stype) : NULL;
}
/* DATADEF - Parse top-level declaration that isn't a function definition.
** [dpANS 3.5, 3.7.2]
**
** <decl> ::= <decl-specs> {init-decl-list} ';'
**
** <init-decl-list> ::= {init-decl-list ','} <init-declor>
** <init-declor> ::= <declor> {'=' izer}
**
** Invoked by extdef() after determining that a declaration is not
** a function definition, to parse the rest of a top-level data declaration
** or function reference.
** Current token is the first one after the first <declor>.
*/
static NODE *
datadef(SYMBOL *base, SYMBOL *s, SYMBOL *syment)
/* Parsed <decl-specs>
* Default <decl-specs> and 1st <declor>
* Symtab entry of identifier for 1st <declor>
*/
{
SYMBOL defbase;
NODE *root = NULL, *tail = NULL;
/* Check out the storage class and type
** specifications. At top level, some storage class or type specifier
** must have been given.
*/
defbase.Scontents = base->Scontents; /* Copy contents of base */
switch (defbase.Sclass)
{
case SC_UNDEF:
defbase.Sclass = s->Sclass; /* Copy whatever default was */
if (defbase.Stype == NULL)
{
error("Declaration without storage class or type-spec");
}
break;
case SC_EXTREF: /* "extern" */
case SC_INTREF: /* "static" */
case SC_TYPEDEF: /* "typedef" */
break;
default:
error("Illegal top-level storage class");
s->Sclass = defbase.Sclass = SC_EXLINK; /* Use default */
break;
}
if (defbase.Stype == NULL)
defbase.Stype = s->Stype; /* Copy whatever default was */
decllist(base, &defbase, s, syment, &root, &tail);
if (!expect(T_SCOLON) && token == T_RBRACE)
nextoken();
return (root);
}
/* LDECLLIST() - Parse local block declaration list
** [dpANS 3.6.2, 3.5]
**
** <decl-list> ::= <decl> {decl-list}
**
** This is only called by CCSTMT's compound() to parse the
** optional declaration-list at the start of a compound statement.
** Makes entries in the symbol and type tables, and returns a node
** pointer to a list of initializations that must be done.
** Current token is the first of a possible <decl>. If it is not
** a valid first token for a declaration, nothing is done and NULL is returned.
*/
NODE *
ldecllist(void)
{
SYMBOL base, defbase;
NODE *autodecls, *autotail; /* Pointers to list of inits for decls
** within a block */
if (!isdecl())
return NULL; /* Most common case -- no decls */
autodecls = autotail = NULL;
do
{
/* If current token is start of a declaration, handle it. */
pbase(&base); /* Parse base storage-class and type */
/* Note all classes are OK */
copysym(&defbase, &base);
if (defbase.Sclass == SC_UNDEF)
defbase.Sclass = SC_AUTO; /* Default class is AUTO */
if (defbase.Stype == NULL)
defbase.Stype = deftype;
/* Handle the local declaration, adding defs to the right list. */
if (defbase.Sclass == SC_INTREF) /* "static" */
decllist(&base, &defbase, (SYMBOL *)NULL, (SYMBOL *)NULL,
&statdecls, &stattail);
else
decllist(&base, &defbase, (SYMBOL *)NULL, (SYMBOL *)NULL,
&autodecls, &autotail);
expect(T_SCOLON);
}
while (isdecl())
;
return(autodecls);
}
/* DECLLIST - Parse declarator list for a declaration, with possible izers.
** [dpANS 3.5]
**
** <init-decl-list> ::= <init-declor> {',' init-decl-list}
** <init-declor> ::= <declor> {'=' izer}
**
** This is called by datadef() for top-level declarations and
** by ldecllist() for block-level declarations.
** Note the provision for having already parsed the first declarator.
*/
static void
decllist(SYMBOL *base, SYMBOL *defbase, SYMBOL *d, SYMBOL *s,
NODE **root, NODE **tail)
/* SYMBOL *base, Base storage class & type-spec furnished
* *defbase, Same but completely defaulted as necessary
* *d, First parsed declarator (NULL if none)
* *s; Symbol table entry for d's ident
* NODE **root, Addr of Root of declaration parse tree, if any
* **tail; Addr of Tail of parse tree, if any
*/
{
SYMBOL tempsym;
NODE *n, *z;
if (d == NULL) /* Already parsed first declarator? */
{
d = &tempsym; /* No, so do first one here. */
copysym(d, defbase);
s = declarator(d);
if (s == NULL && token == T_SCOLON && (base->Sflags&SF_SIDEFF))
return; /* No declarators but have side-effect */
}
while (1)
{
if (s == NULL)
error("Null declarator, expecting ident");
else if ((n = dodecl(base->Sclass, d, s)) != NULL)
{
z = ndefl(N_DATA, n);
if (*tail == NULL) /* Add parse result to tree */
*root = *tail = z; /* Either as 1st node */
else
*tail = (*tail)->Nright = z; /* or at end of current tree */
}
if (token != T_COMMA)
break;
nextoken();
copysym(d, defbase);
s = declarator(d);
}
return;
}
/* ISDECL() - returns TRUE if current token is the start of a declaration,
** i.e. the start of {declaration-specifiers}, one of:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -