⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ccdecl.c

📁 KCC , a good c compiler, write by Ken Harrenstien
💻 C
📖 第 1 页 / 共 5 页
字号:
**              {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 + -