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

📄 ccdecl.c

📁 KCC , a good c compiler, write by Ken Harrenstien
💻 C
📖 第 1 页 / 共 5 页
字号:
/*      CCDECL.C - Declaration Parser
**
**      (c) Copyright Ken Harrenstien 1989
**              All changes after v.371, 28-May-1988
**      (c) Copyright Ken Harrenstien, SRI International 1985, 1986
**              All changes after v.154, 8-Aug-1985
**
**      Original version (C) 1981  K. Chen
*/

#define _DEF_CHAR8      0       /* define this to default char to char8 */

#include <limits.h>             /* for INT_MAX */
#include "cc.h"
int strcmp (const char *, const char *);

extern SYMBOL *lsymhead;        /* CCSYM - var indicating loc sym blk */

/* Imported functions */
extern SYMBOL *symfidstr(char *), *creatsym(char *), *uniqsym(SYMBOL *); /* CCSYM */
extern SYMBOL *findgsym(SYMBOL *);      /* CCSYM */
extern SYMBOL *newlabel(void);  /* CCSYM */
extern SYMBOL *symfxext(SYMBOL *);      /* CCSYM */
extern SYMBOL *symftag(SYMBOL *);       /* CCSYM */
extern SYMBOL *symfmember(SYMBOL *, SYMBOL *);  /* CCSYM */
extern SYMBOL *symqcreat(SYMBOL *);     /* CCSYM */
extern SYMBOL *isdupsym(SYMBOL *);      /* CCSYM */
extern SYMBOL *beglsym(void);   /* CCSYM */
extern TYPE *findctype(int, INT, unsigned INT, TYPE *),
        *findtype(int, TYPE *), /* CCSYM */
        *findftype(TYPE *, TYPE *),                     /* CCSYM */
        *findptype(int, TYPE *, TYPE *);                        /* CCSYM */
extern TYPE *tcomposite(TYPE *, TYPE *);                /* CCSYM */
extern int  cmptype(TYPE *, TYPE *), cmputype(TYPE *, TYPE *);  /* CCSYM */
extern INT  sizetype(TYPE *);                   /* CCSYM */
extern void copysym(SYMBOL *, SYMBOL *), ridlsym(SYMBOL *);     /* CCSYM */
extern void mapintsym(SYMBOL *);                /* CCSYM */
extern int  mapextsym(SYMBOL *);                /* CCSYM */
extern void freesym(SYMBOL *);  /* CCSYM */
extern NODE *evalexpr(NODE *);          /* CCEVAL */
extern NODE *funstmt(void), *asgnexpr(void);    /* CCSTMT */
extern NODE *exprconst(void);           /* CCSTMT */
extern long pconst(void);                       /* CCSTMT */
extern NODE *convasgn(TYPE *, NODE *);          /* CCTYPE */
extern TYPE *convfparam(TYPE *);                /* CCTYPE */
extern int nextoken(void);                      /* CCLEX */
extern int expect (int);                        /* CCERR */

/* Exported functions */
void initpar(void);             /* Called by CC mainline */
NODE *extdef(void);             /* Called by CC mainline */
NODE *tntdef(void);     /* Called by CC mainline */
NODE *ldecllist(void);  /* CCSTMT for inner block declarations */
TYPE *typename(void);   /* CCSTMT for cast and sizeof exprs */
SYMBOL *defauto(char *, TYPE *); /* CCSTMT for invisible struct return obj */
SYMBOL *funchk(int, int, SYMBOL *, SYMBOL *);   /* CCSTMT for calls to undeclared functions */

struct protostate               /* State block for prototype parse */
    {
    int nparams;
    SYMBOL *shead, *stail;      /* Parameter symbol list */
    SYMBOL decl;
    };

/* Internal functions */
static NODE *funcdef(SYMBOL *, SYMBOL *, SYMBOL *),
            *datadef(SYMBOL *, SYMBOL *, SYMBOL *);
static void pdecllist(void), sdeclenum(SYMBOL *),
            decllist(SYMBOL *,SYMBOL *,SYMBOL *,SYMBOL *,NODE **,NODE **);
static INT  sdeclstruct(SYMBOL *, int), fldsize(int, INT *, int *),
            pbase(SYMBOL *);
static TYPE *qualarray (TYPE *type, int flags, int *oldflags);
static int  isdecl(void);
static TYPE *fundecl(SYMBOL *, int),
            *paramlist(struct protostate
*),
*mkproto(SYMBOL *);
static void pidentlist(struct protostate
*);
static void plcmpare(TYPE *, TYPE *, int),
            plcmpold(SYMBOL *, TYPE *, TYPE *), plcheck(TYPE *);
static NODE *dodecl(int, SYMBOL *, SYMBOL *);
static SYMBOL *declarator(SYMBOL *);
static TYPE *addpp(TYPE *, TYPE *), *pushsztype(int, INT, INT, TYPE *),
            *tagspec(int);
static SYMBOL *sdeclaration(SYMBOL *, SYMBOL *, INT *, int *, int *);
static NODE *pizer(SYMBOL *);
static void errtwotyp(SYMBOL *, SYMBOL *), errdupsym(SYMBOL *);
static TYPE *mkprox(SYMBOL *);
static int nsetjmps(void);
static NODE *piztype(TYPE *, int), *chkarith(TYPE *, NODE *, int, int),
            *pizstruct(TYPE *, int, int), *pizarray(TYPE *, int),
        *pexizer(int), *pizlist(void);
static void pizflush(int);
static int isauto(SYMBOL *), nisconst(NODE *);
static void Set_Register(SYMBOL *, int, int);


/* Internal data */

static int paramok;     /* True if OK to parse parameter list for a function
                        ** definition.  Only true when at top
                        ** level and parsing the first declarator.
                        */
static int inproto;     /* True when parsing a function prototype list.
                        ** This is bumped to indicate level.
                        */

static NODE *statdecls, /* Pointer to list of static decls within current fn */
        *stattail;      /* Pointer to tail of statdecls list */
static int nsdefs;      /* # of enum/struct/union side effect definitions seen.
                        ** The exact number doesn't matter; this is only used
                        ** to tell when a type-specifier has had the side
                        ** effect of defining a tag or enum constant.
                        */
static int itags;       /* # of internal tags defined.  This is used only
                        ** to create unique names for internal tags. 
                        */
static int tntcnt;      /* # of tentative defs output.  Only used to initialize
                        ** tntdef(), by setting to -1.
                        */
#if 0
/* Flags returned from pbase(). */
/* These aren't really used yet, maybe should be flushed. */
#define BASEF_SC 01     /* Storage class parsed */
#define BASEF_TS 02     /* Type-specifier parsed */
#define BASEF_TAG 04    /* enum/struct/union tag was defined as side effect */

/* Also not really used yet */
typedef struct
    {
    int Dflags;
    SYMBOL *Dpnext, *Dpsblk;
    SYMBOL s;
    }
declsym;
#define DSname s.Sname
#define DSvalue s.Svalue
#define DSclass s.Sclass
#define DStype s.Stype
#endif

/* INITPAR - Initialize parser
**      Called once for each file compiled.
*/
void
initpar(void)
{
    nodeinit();                 /* No parse-tree nodes used */
    curfn = NULL;               /* Not in any function yet */
    itags = 0;                  /* Reset internal tag count for gensyms */
    nsdefs = 0;                 /* Reset side-effect def count for neatness */
    tntcnt = -1;                /* Reset tntdef() */
}


/* EXTDEF() - Parse top-level declaration or definition
**      [dpANS 3.7, 3.5]
**
**      <external-decl> ::= <function-definition> | <decl>
**
**      <function-definition> ::=
**                      {decl-specs} <declor> {decl-list} <compound-stmt>
**
**      <decl> ::=      <decl-specs> {init-decl-list} ';'
**
**      <init-decl-list> ::= <init-declor> {',' init-decl-list}
**      <init-declor>   ::= <declor> {'=' izer}
**
** This is the main entry to input parser.  Current token is the
** first one of the <external-decl>.  Since both possibilities (function
** def or a decl) can start with <decl-specs>, we parse for that first.
** If there was nothing but <decl-specs>, we can just return.  Otherwise
** the initially parsed "base" needs to be passed on for further parsing.
*/

NODE*
extdef (void)
    {
    SYMBOL*     s;
    SYMBOL      tempsym;
    SYMBOL      base;


    /* Do top level initializations */

    paramok = 1;                /* OK to parse a function parameter list */
    inproto = 0;                /* Not in prototype scope */
    curfnnew = fline;           /* Remember line in file where funct started*/
    _reg_count = 0;             /* Count of "preserved" registers used */
                                /* for register variables */

    pbase(&base);               /* Parse base (storage class & type) */

    if (token == T_SCOLON)      /* Only got a type (struct)? */
        {
        if ((base.Sflags&SF_SIDEFF) == 0)       /* If no side effs, */
            error("Null declaration");

        switch (base.Sclass)
            {
            case SC_UNDEF:
                break;                  /* None given */
            case SC_AUTO:
            case SC_RAUTO:
                error("Illegal storage class");
                break;
            default:
                note("Useless storage class");
                break;
            }
        nextoken();             /* Skip over the semicolon */
        return NULL;            /* and stop doing this def */
        }

    /* Parsed <decl-specs>, now look for <declor> to determine whether
    ** we're doing a function def or not.
    */
    copysym(&tempsym, &base);           /* Copy base storage class & type */
    if (tempsym.Sclass == SC_UNDEF)     /* Set up for defaults */
        tempsym.Sclass = SC_EXLINK;     /* Default stg class: extern */
    if (tempsym.Stype == NULL)
        tempsym.Stype = deftype;        /* Default type: int */
    while ((s = declarator(&tempsym)) == NULL)/* Until we find declarator */
        /* No declarator found, may want to loop. */
        {
        error("Null declarator, expecting ident");
        if (tempsym.Spmnext)            /* Flush param syms if any (in case)*/
            ridlsym((SYMBOL *)NULL);
        if (token == T_COMMA)           /* Only continue if hit comma */
            {
            nextoken();                 /* in which case skip over it */
            continue;                   /* and try again */
            }

        if (token != T_SCOLON)          /* Else give up on it */
            error("Bad syntax for top-level declaration");

        /* 9/91 infinite loop if test for T_RBRACE also (SPR 9579) */
        while (token != T_EOF && token != T_SCOLON)
            nextoken();         /* Flush to probable end of stmt */
        return NULL;
        }

    paramok = 0;                /* No longer OK to parse function param list */

    /* If function type, need to examine more closely to see whether this
    ** is a definition or just a forward-reference declaration.
    ** It is a definition only if the current token is one of:
    **          Left brace (start of function body)
    **          A type-specifier keyword (a function parameter declaration).
    **          The "register" keyword (only permissible storage class for
    **                  function parameter declarations).
    ** We permit any storage class here, for better error diagnostics later.
    */

    if (tempsym.Stype->Tspec == TS_FUNCT)
        {
        if (token == T_LBRACE || isdecl())
            return funcdef(&base, &tempsym, s);  /* Parse funct def */
        }

    /* Not a function definition, so is either a function reference, or a
    ** data definition/reference.
    */
    return datadef(&base, &tempsym, s); /* data def/ref or function ref */
}

/* TNTDEF - Return next remaining tentative definition, if any.
**      This is only invoked by the CC mainline after all input parsing
**      is completed for a file.  It scans for all tentative definitions
**      with internal or external linkage, and for each one returns a
**      node that defines it with a zero initializer.
*/
NODE *
tntdef(void)
{
    static SYMBOL *s;

    if (++tntcnt == 0)          /* If first time, */
        s = symbol;             /* start scanning global sym list */
    while ((s = s->Snext) != NULL)
        {
        switch (s->Sclass)
            {
            default:
                continue;
            case SC_INTREF:             /* Should only exist for functions */
                if (s->Srefs)
                    error("Static function %S not defined", s);
                else
                    note("Static function %S not defined or used", s);
                continue;
            case SC_INTDEF:             /* May be function or object */
                if (s->Srefs == 0)
                    note("Static %s %S never used",
                            (s->Stype->Tspec != TS_FUNCT ? "object" : "function"),
                            s);
                continue;
            case SC_INLINK:
                s->Sclass = SC_INTDEF;
                if (s->Srefs)   /* Ensure internal object was used */
                    break;              /* Yup, go define it */
                note("Static object %S never used, not emitted", s);
                continue;
            case SC_EXLINK:
                s->Sclass = SC_EXTDEF;  /* Always do it if external linkage */
                break;
            }
        /* Set up a Q_IDENT and a null izer definition for it */
        return ndefl(N_DATA, ndefl(N_IZ, ndefident(s)));
        }
    return NULL;
}

/* FUNCDEF() - Parse function definition
**      [dpANS 3.7.1]
**      <function-definition> ::=
**                      {decl-specs} <declor> {decl-list} <compound-stmt>
**
** Only called from extdef() when a function declaration turns out
** to be the start of a definition.  At this point, the current token
** is the first one past the <declor>.
**
** The first two pointer args always point to temporary symbol
** structures not in the symbol table.  However, the parameter list
** symbols ARE in the table, chained as local symbols.
*/

static NODE *
funcdef(SYMBOL *b, SYMBOL *d, SYMBOL *syment)
/* Base, contains parsed <decl-specs>, 
 * Defaulted <decl-specs> plus <declor> type
 * Identifier's symtab entry 
 */
{
    INT n, siz;
    int nsjmps;
    NODE *nnode, *header;
    SYMBOL *s1;
    SYMBOL *args = d->Spmnext;  /*  List of parameter syms */
    int npartypes = (int) d->Svalue;    /* # of params if new-style proto */
    int nparidents = 0;
    NODE *nreg;

    /* "syment" points to the function name's symtab entry.
    ** Lexer will have created the symtab entry with
    ** class SC_UNDEF if it didn't already exist.
    */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -