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

📄 ccdecl.c

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