📄 ccdecl.c
字号:
** {storage-class-specifier}
** {type-specifier}
** {type-qualifier}
*/
static int
isdecl(void)
{
return (csymbol != NULL && (
(tok[token].tktype == TKTY_RWSC || tok[token].tktype == TKTY_RWTYPE)
|| (csymbol->Sclass == SC_TYPEDEF)
));
}
/* PBASE(&sym) - Parse base of declaration (stg class & type)
** Handles either <decl-specs>, if a symbol pointer is given,
** or <spec-qual-list>, if no pointer is given.
**
** [dpANS 3.5, 3.5.1, 3.5.2]
**
** <decl-specs> ::= *[<stg-class-spec> | <type-spec> | <type-qual>]
**
** <spec-qual-list> ::= *[<type-spec> | <type-qual>]
**
** <type-spec> ::= "void" | "char" | etc...
** <type-qual> ::= "const" | "volatile"
** <stg-class-spec> ::=
** "typedef" | "extern" | "static" | "auto" | "register"
*/
/* Flags to remember what we've already seen, for tokens that can combine
** with others in random order.
*/
#define PF_SIGNED 01
#define PF_UNSIGNED 02
#define PF_CHAR 04
#define PF_SHORT 010
#define PF_INT 020
#define PF_LONG 040
#define PF_DOUBLE 0100
static INT
pbase(SYMBOL *symp)
{
static char *errmsg = "Illegal combination of type-specifiers";
int savnsdefs = nsdefs; /* Remember # side-eff defs so far */
TYPE *t = NULL, *nt;
INT nflag, qflags = 0, tflags = 0;
int chrsiz = 0;
if (symp)
{
symp->Sname[0] = '\0'; /* init symbol */
symp->Svalue = 0; /* no val yet */
symp->Sclass = SC_UNDEF; /* no storage class */
symp->Stype = NULL; /* no type yet */
symp->Sflags = 0;
}
/* First find all type-specs, type-quals, or stg-class-specs.
** Stop only when a token is seen that can't be one of these.
*/
for ( ; ; )
{
if (tok[token].tktype == TKTY_RWTYPE)
{
/* Look for reserved word type-qualifiers or type-specifiers */
nt = NULL;
switch (token)
{
case T_FORTRAN:
if( symp->Sflags & (TF_FORTRAN | TF_BLISS) )
error("Duplicate foreign language qualifier!");
symp->Sflags |= TF_FORTRAN;
nextoken();
continue;
case T_BLISS:
if( symp->Sflags & (TF_FORTRAN | TF_BLISS) )
error("Duplicate foreign language qualifier!");
symp->Sflags |= TF_BLISS;
nextoken();
continue;
case T_INTERRUPT: /* FW 2A(52) */
if (symp->Sflags & TF_INTERRUPT)
error ("Duplicate interrupt qualifier");
symp->Sflags |= TF_INTERRUPT;
nextoken ();
continue;
case T_CONST: /* "const" type-qualifier */
if (qflags & TF_CONST)
error("Duplicate \"const\"");
qflags |= TF_CONST;
nextoken();
continue;
case T_VOLATILE: /* "volatile" type-qualifier */
if (qflags & TF_VOLATILE)
error("Duplicate \"volatile\"");
qflags |= TF_VOLATILE;
nextoken();
continue;
case T_VOID:
nt = voidtype;
nflag = 0;
break;
case T_FLOAT:
nt = flttype;
nflag = 0;
break;
case T_STRUCT:
nt = tagspec(TS_STRUCT);
nflag = 1;
break;
case T_UNION:
nt = tagspec(TS_UNION);
nflag = 1;
break;
case T_ENUM:
(void) tagspec(TS_ENUM);
nt = inttype;
nflag = 1;
break;
/* Enums always type "int", but have tags and syms defined. */
case T_SIGNED:
nflag = PF_SIGNED;
break;
case T_UNSIGNED:
nflag = PF_UNSIGNED;
break;
case T_CHAR:
#if _DEF_CHAR8
/* 6/91, chars default to size8
* Note that if(!chrsiz){} below becomes dead code.
*/
chrsiz = 8;
#endif
nflag = PF_CHAR;
break;
case T_SHORT:
nflag = PF_SHORT;
break;
case T_INT:
nflag = PF_INT;
break;
case T_LONG:
nflag = PF_LONG;
break;
case T_DOUBLE:
nflag = PF_DOUBLE;
break;
case T_CHAR6:
nflag = PF_CHAR;
chrsiz = 6;
break;
case T_CHAR7:
nflag = PF_CHAR;
chrsiz = 7;
break;
case T_CHAR8:
nflag = PF_CHAR;
chrsiz = 8;
break;
case T_CHAR9:
nflag = PF_CHAR;
chrsiz = 9;
break;
case T_CHAR18:
nflag = PF_CHAR;
chrsiz = 18;
break;
default:
int_error("pbase: unknown RWTYPE %Q", token);
nextoken(); /* Skip over, get next */
continue;
}
if (nt) /* Was type completely set? */
{
if (t || tflags)
error(errmsg); /* Say bad typespec combo */
t = nt;
tflags = 0;
/* Set flag if any side effects (tag or enum defined) */
if (symp && savnsdefs != nsdefs)
symp->Sflags |= SF_SIDEFF;
if (nflag) /* If tagspec called, */
continue; /* don't do another nextoken! */
}
else /* Nope, nflag must be set */
{
if (t || (tflags&nflag))
error(errmsg); /* Say bad typespec combo */
tflags |= nflag;
}
nextoken(); /* On to next token */
continue;
}
else if (tok[token].tktype == TKTY_RWSC)
{
/* Check storage class */
if (!symp)
error("Storage class specifier not allowed");
else if (symp->Sclass != SC_UNDEF) /* Already have one? */
error("Only one storage class specifier allowed");
else
{
if (t || tflags || qflags)
note("Storage class should come first in declaration");
switch (token)
{
case T_AUTO:
symp->Sclass = SC_AUTO;
break;
case T_STATIC:
symp->Sclass = SC_INTREF;
break;
case T_EXTERN:
symp->Sclass = SC_EXTREF;
break;
case T_REGISTER:
/* Later, have debugger routines in ccsym.c not depend on reg
* values being on the stack. Then remove the debcsi < 1 in if().
*
* HAZARD: This looks screwy in light of the negative values of
* debcsi.
*/
#if REGISTER_VARIABLES
if (use_registers && debcsi < 1)
/* if not using -r or -g=[debug,sprof,fnprof] */
{
symp->Sclass = SC_RAUTO;
symp->Sreg = -1;
}
else
#endif
symp->Sclass = SC_AUTO;
break;
case T_TYPEDEF:
symp->Sclass = SC_TYPEDEF;
break;
default:
int_error("pbase: unknown RWSC %Q", token);
}
}
nextoken();
continue; /* Skip over and get next */
}
/* Not a type-specifier keyword or storage-class, see if typedef,
** but ONLY if we haven't already seen any other type specifiers.
** Note that type qualifiers can be added in! This requires a
** special check for function and array types, which can't have
** their types qualified except by typedefs. But the qualifiers
** may follow the typedef, so we have to check after all's done.
*/
if (!t && !tflags && csymbol && csymbol->Sclass == SC_TYPEDEF)
{
t = csymbol->Stype; /* Get the type */
nextoken();
continue; /* Keep going, sigh */
}
break; /* No matches, stop loop! */
} /* End of moby loop */
/* All specifiers gobbled, now see whether a type resulted. If none,
** but tflags has stuff, we try to decipher the flag combos.
*/
if (!t)
{
switch ((int) tflags)
{
case 0:
if (!qflags && (!symp || symp->Sclass == SC_UNDEF))
return 0; /* Nothing read at all */
t = deftype; /* OK to default to "int" */
break;
/* Chars have special KCC extension case */
case PF_CHAR:
if (!chrsiz)
{
t = chartype;
break;
}
case PF_SIGNED|PF_CHAR:
if (!chrsiz)
{
t = schartype;
break;
}
case PF_UNSIGNED|PF_CHAR:
if (!chrsiz)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -