📄 decl.c
字号:
#include "c.h"static char rcsid[] = "$Id: decl.c,v 1.1 2002/08/28 23:12:42 drh Exp $";#define add(x,n) (x > inttype->u.sym->u.limits.max.i-(n) ? (overflow=1,x) : x+(n))#define chkoverflow(x,n) ((void)add(x,n))#define bits2bytes(n) (((n) + 7)/8)static int regcount;static List autos, registers;Symbol cfunc; /* current function */Symbol retv; /* return value location for structs */static void checkref(Symbol, void *);static Symbol dclglobal(int, char *, Type, Coordinate *);static Symbol dcllocal(int, char *, Type, Coordinate *);static Symbol dclparam(int, char *, Type, Coordinate *);static Type dclr(Type, char **, Symbol **, int);static Type dclr1(char **, Symbol **, int);static void decl(Symbol (*)(int, char *, Type, Coordinate *));extern void doconst(Symbol, void *);static void doglobal(Symbol, void *);static void doextern(Symbol, void *);static void exitparams(Symbol []);static void fields(Type);static void funcdefn(int, char *, Type, Symbol [], Coordinate);static void initglobal(Symbol, int);static void oldparam(Symbol, void *);static Symbol *parameters(Type);static Type specifier(int *);static Type structdcl(int);static Type tnode(int, Type);void program(void) { int n; level = GLOBAL; for (n = 0; t != EOI; n++) if (kind[t] == CHAR || kind[t] == STATIC || t == ID || t == '*' || t == '(') { decl(dclglobal); deallocate(STMT); if (!(glevel >= 3 || xref)) deallocate(FUNC); } else if (t == ';') { warning("empty declaration\n"); t = gettok(); } else { error("unrecognized declaration\n"); t = gettok(); } if (n == 0) warning("empty input file\n");}static Type specifier(int *sclass) { int cls, cons, sign, size, type, vol; Type ty = NULL; cls = vol = cons = sign = size = type = 0; if (sclass == NULL) cls = AUTO; for (;;) { int *p, tt = t; switch (t) { case AUTO: case REGISTER: if (level <= GLOBAL && cls == 0) error("invalid use of `%k'\n", t); p = &cls; t = gettok(); break; case STATIC: case EXTERN: case TYPEDEF: p = &cls; t = gettok(); break; case CONST: p = &cons; t = gettok(); break; case VOLATILE: p = &vol; t = gettok(); break; case SIGNED: case UNSIGNED: p = &sign; t = gettok(); break; case LONG: if (size == LONG) { size = 0; tt = LONG+LONG; } p = &size; t = gettok(); break; case SHORT: p = &size; t = gettok(); break; case VOID: case CHAR: case INT: case FLOAT: case DOUBLE: p = &type; ty = tsym->type; t = gettok(); break; case ENUM: p = &type; ty = enumdcl(); break; case STRUCT: case UNION: p = &type; ty = structdcl(t); break; case ID: if (istypename(t, tsym) && type == 0 && sign == 0 && size == 0) { use(tsym, src); ty = tsym->type; if (isqual(ty) && ty->size != ty->type->size) { ty = unqual(ty); if (isconst(tsym->type)) ty = qual(CONST, ty); if (isvolatile(tsym->type)) ty = qual(VOLATILE, ty); tsym->type = ty; } p = &type; t = gettok(); } else p = NULL; break; default: p = NULL; } if (p == NULL) break; if (*p) error("invalid use of `%k'\n", tt); *p = tt; } if (sclass) *sclass = cls; if (type == 0) { type = INT; ty = inttype; } if (size == SHORT && type != INT || size == LONG+LONG && type != INT || size == LONG && type != INT && type != DOUBLE || sign && type != INT && type != CHAR) error("invalid type specification\n"); if (type == CHAR && sign) ty = sign == UNSIGNED ? unsignedchar : signedchar; else if (size == SHORT) ty = sign == UNSIGNED ? unsignedshort : shorttype; else if (size == LONG && type == DOUBLE) ty = longdouble; else if (size == LONG+LONG) { ty = sign == UNSIGNED ? unsignedlonglong : longlong; if (Aflag >= 1) warning("`%t' is a non-ANSI type\n", ty); } else if (size == LONG) ty = sign == UNSIGNED ? unsignedlong : longtype; else if (sign == UNSIGNED && type == INT) ty = unsignedtype; if (cons == CONST) ty = qual(CONST, ty); if (vol == VOLATILE) ty = qual(VOLATILE, ty); return ty;}static void decl(Symbol (*dcl)(int, char *, Type, Coordinate *)) { int sclass; Type ty, ty1; static char stop[] = { CHAR, STATIC, ID, 0 }; ty = specifier(&sclass); if (t == ID || t == '*' || t == '(' || t == '[') { char *id; Coordinate pos; id = NULL; pos = src; if (level == GLOBAL) { Symbol *params = NULL; ty1 = dclr(ty, &id, ¶ms, 0); if (params && id && isfunc(ty1) && (t == '{' || istypename(t, tsym) || (kind[t] == STATIC && t != TYPEDEF))) { if (sclass == TYPEDEF) { error("invalid use of `typedef'\n"); sclass = EXTERN; } if (ty1->u.f.oldstyle) exitscope(); funcdefn(sclass, id, ty1, params, pos); return; } else if (params) exitparams(params); } else ty1 = dclr(ty, &id, NULL, 0); for (;;) { if (Aflag >= 1 && !hasproto(ty1)) warning("missing prototype\n"); if (id == NULL) error("missing identifier\n"); else if (sclass == TYPEDEF) { Symbol p = lookup(id, identifiers); if (p && p->scope == level) error("redeclaration of `%s'\n", id); p = install(id, &identifiers, level, level < LOCAL ? PERM : FUNC); p->type = ty1; p->sclass = TYPEDEF; p->src = pos; } else (void)(*dcl)(sclass, id, ty1, &pos); if (t != ',') break; t = gettok(); id = NULL; pos = src; ty1 = dclr(ty, &id, NULL, 0); } } else if (ty == NULL || !(isenum(ty) || isstruct(ty) && (*unqual(ty)->u.sym->name < '1' || *unqual(ty)->u.sym->name > '9'))) error("empty declaration\n"); test(';', stop);}static Symbol dclglobal(int sclass, char *id, Type ty, Coordinate *pos) { Symbol p; if (sclass == 0) sclass = AUTO; else if (sclass != EXTERN && sclass != STATIC) { error("invalid storage class `%k' for `%t %s'\n", sclass, ty, id); sclass = AUTO; } p = lookup(id, identifiers); if (p && p->scope == GLOBAL) { if (p->sclass != TYPEDEF && eqtype(ty, p->type, 1)) ty = compose(ty, p->type); else error("redeclaration of `%s' previously declared at %w\n", p->name, &p->src); if (!isfunc(ty) && p->defined && t == '=') error("redefinition of `%s' previously defined at %w\n", p->name, &p->src); if (p->sclass == EXTERN && sclass == STATIC || p->sclass == STATIC && sclass == AUTO || p->sclass == AUTO && sclass == STATIC) warning("inconsistent linkage for `%s' previously declared at %w\n", p->name, &p->src); } if (p == NULL || p->scope != GLOBAL) { Symbol q = lookup(id, externals); if (q) { if (sclass == STATIC || !eqtype(ty, q->type, 1)) warning("declaration of `%s' does not match previous declaration at %w\n", id, &q->src); p = relocate(id, externals, globals); p->sclass = sclass; } else { p = install(id, &globals, GLOBAL, PERM); p->sclass = sclass; (*IR->defsymbol)(p); } if (p->sclass != STATIC) { static int nglobals; nglobals++; if (Aflag >= 2 && nglobals == 512) warning("more than 511 external identifiers\n"); } } else if (p->sclass == EXTERN) p->sclass = sclass; p->type = ty; p->src = *pos; if (t == '=' && isfunc(p->type)) { error("illegal initialization for `%s'\n", p->name); t = gettok(); initializer(p->type, 0); } else if (t == '=') { initglobal(p, 0); if (glevel > 0 && IR->stabsym) { (*IR->stabsym)(p); swtoseg(p->u.seg); } } else if (p->sclass == STATIC && !isfunc(p->type) && p->type->size == 0) error("undefined size for `%t %s'\n", p->type, p->name); return p;}static void initglobal(Symbol p, int flag) { Type ty; if (t == '=' || flag) { if (p->sclass == STATIC) { for (ty = p->type; isarray(ty); ty = ty->type) ; defglobal(p, isconst(ty) ? LIT : DATA); } else defglobal(p, DATA); if (t == '=') t = gettok(); ty = initializer(p->type, 0); if (isarray(p->type) && p->type->size == 0) p->type = ty; if (p->sclass == EXTERN) p->sclass = AUTO; }}void defglobal(Symbol p, int seg) { p->u.seg = seg; swtoseg(p->u.seg); if (p->sclass != STATIC) (*IR->export)(p); (*IR->global)(p); p->defined = 1;}static Type dclr(Type basety, char **id, Symbol **params, int abstract) { Type ty = dclr1(id, params, abstract); for ( ; ty; ty = ty->type) switch (ty->op) { case POINTER: basety = ptr(basety); break; case FUNCTION: basety = func(basety, ty->u.f.proto, ty->u.f.oldstyle); break; case ARRAY: basety = array(basety, ty->size, 0); break; case CONST: case VOLATILE: basety = qual(ty->op, basety); break; default: assert(0); } if (Aflag >= 2 && basety->size > 32767) warning("more than 32767 bytes in `%t'\n", basety); return basety;}static Type tnode(int op, Type type) { Type ty; NEW0(ty, STMT); ty->op = op; ty->type = type; return ty;}static Type dclr1(char **id, Symbol **params, int abstract) { Type ty = NULL; switch (t) { case ID: if (id) *id = token; else error("extraneous identifier `%s'\n", token); t = gettok(); break; case '*': t = gettok(); if (t == CONST || t == VOLATILE) { Type ty1; ty1 = ty = tnode(t, NULL); while ((t = gettok()) == CONST || t == VOLATILE) ty1 = tnode(t, ty1); ty->type = dclr1(id, params, abstract); ty = ty1; } else ty = dclr1(id, params, abstract); ty = tnode(POINTER, ty); break; case '(': t = gettok(); if (abstract && (t == REGISTER || istypename(t, tsym) || t == ')')) { Symbol *args; ty = tnode(FUNCTION, ty); enterscope(); if (level > PARAM) enterscope(); args = parameters(ty); exitparams(args); } else { ty = dclr1(id, params, abstract); expect(')'); if (abstract && ty == NULL && (id == NULL || *id == NULL)) return tnode(FUNCTION, NULL); } break; case '[': break; default: return ty; } while (t == '(' || t == '[') switch (t) { case '(': t = gettok(); { Symbol *args; ty = tnode(FUNCTION, ty); enterscope(); if (level > PARAM) enterscope(); args = parameters(ty); if (params && *params == NULL) *params = args; else exitparams(args); } break; case '[': t = gettok(); { int n = 0; if (kind[t] == ID) { n = intexpr(']', 1); if (n <= 0) { error("`%d' is an illegal array size\n", n); n = 1; } } else expect(']'); ty = tnode(ARRAY, ty); ty->size = n; } break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -