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

📄 ccdecl.c

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