ref: aea5de4f99d00f5ca4c7f7503be3208f9666e623
dir: /decl.c/
#include <assert.h> #include <stddef.h> #include <string.h> #include "cc.h" #include "tokens.h" #include "types.h" #include "syntax.h" #include "symbol.h" char parser_out_home; static void declarator(void); static struct symbol *newiden(char *s, unsigned char key) { register struct symbol *sym = lookup(yytext, yyhash); if (!sym) sym = install(yytext, yyhash); else if (sym->level == nested_level) error("redeclaration of '%s'", yytext); return sym; } static void dirdcl(void) { if (accept('(')) { declarator(); expect(')'); } else if (yytoken == IDEN) { newiden(yytext, yyhash); next(); } else { error("expected '(' or identifier before of '%s'", yytext); } for (;;) { if (accept('(')) { next(); pushtype(FTN); if (accept(')')) ; /* TODO: k&r function */ else /* TODO: prototyped function */; continue; } else if (accept('[')) { pushtype(ARY); if (accept(']')) ; /* TODO: automatic size array */ else /* TODO: specify size of array */; continue; } else { return; } } } /* * */ static struct type *types[][2] = {{T_VOID, NULL}, {T_SCHAR, T_UCHAR}, {T_SHORT, T_USHORT}, {T_INT, T_UINT}, {T_LONG, T_ULONG}, {T_LLONG, T_ULLONG}, {T_FLOAT, NULL}, {T_DOUBLE, NULL}, {T_LDOUBLE, NULL}}; #define F_VOID 0 #define F_CHAR 1 #define F_SHORT 2 #define F_INT 3 #define F_LONG 4 #define F_LLONG 5 #define F_FLOAT 6 #define F_DOUBLE 7 #define F_LDOUBLE 8 static struct type *specifier(void) { auto unsigned char sign, sclass, tqlf, nt; auto struct type *t; t = NULL; tqlf = sign = sclass = 0; for (;; next()) { switch (yytoken) { case TYPEDEF:case EXTERN:case STATIC:case AUTO:case REGISTER: if (sclass != 0) error("Two or more storage specifier"); sclass = yytoken; continue; case CONST: if (!(tqlf ^= T_CONST)) goto duplicated_qlf; continue; case RESTRICTED: if (!(tqlf ^= T_RESTRICTED)) goto duplicated_qlf; continue; case VOLATILE: if (!(tqlf ^= T_VOLATILE)) goto duplicated_qlf; continue; case VOID: nt = F_VOID; goto check_type; case CHAR: nt = F_CHAR; goto check_type; case SHORT: nt = F_SHORT; goto check_type; case INT: nt = F_INT; goto check_type; case FLOAT: nt = F_FLOAT; goto check_type; case DOUBLE: nt = F_DOUBLE; goto check_type; case LONG: nt = F_LONG; goto check_type; case SIGNED: case UNSIGNED: if (sign != 0) { error((sign != yytoken) ? "signed and unsigned in declaration" : "duplicated %s", yytext); } sign = yytoken; if (t == NULL) continue; /* we don't have type now */ goto check_type; case STRUCT: /* TODO */ case UNION: /* TODO */ case ENUM: /* TODO */ default: if (t) { return t; } else if (tqlf) { if (tqlf & T_CONST) pushtype(CONST); if (tqlf & T_RESTRICTED) pushtype(RESTRICTED); if (tqlf & T_VOLATILE) pushtype(VOLATILE); return decl_type(t); } else if (nested_level == 0 && yytoken == IDEN) { warning_error(user_opt.implicit_int, "type defaults to 'int' " "in declaration of '%s'", yytext); return T_INT; } else if (nested_level == 0) { error("declaration expected"); } return NULL; } check_type: if (nt == F_LONG) { if (t == NULL || t == T_INT || t == T_UINT || t == T_LONG) { /* nothing */; } else if (t == T_LONG || t == T_ULONG) { nt = F_LLONG; } else if (t == T_DOUBLE) { nt = F_LDOUBLE; } else if (t == T_LLONG || t == T_ULLONG) { error("'long long long' is too long"); } else if (t == T_LDOUBLE) { error("'long long double' is too long"); } else { goto two_or_more_btype; } } else if (t != NULL) { goto two_or_more_btype; } if (nt == F_VOID && sign != 0) { goto incorrect_sign; } if (nt == F_CHAR && sign == 0) { t = T_UCHAR; /* char by default is unsigned */ } else if (!(t = types[nt][sign == UNSIGNED])) { goto incorrect_sign; } } duplicated_qlf: error("duplicated '%s'", yytext); two_or_more_btype: error("two or more basic types"); incorrect_sign: error("sign specifier applied to incorrect type"); } #undef F_VOID #undef F_CHAR #undef F_SHORT #undef F_INT #undef F_LONG #undef F_LLong #undef F_FLOAT #undef F_DOUBLE #undef F_LDOUBLE static void declarator(void) { unsigned char qlf[PTRLEVEL_MAX], *bp, *lim; lim = qlf + PTRLEVEL_MAX; for (bp = qlf; yytoken == '*' && bp != lim; ++bp) { *bp = 0; repeat_qlf: next(); switch (yytoken) { case CONST: if (!(*bp ^= T_CONST)) goto duplicated; goto repeat_qlf; case RESTRICTED: if (!(*bp ^= T_RESTRICTED)) goto duplicated; goto repeat_qlf; case VOLATILE: if (!(*bp ^= T_VOLATILE)) goto duplicated; goto repeat_qlf; default: break; } } if (bp == lim) error("Too much indirection levels"); dirdcl(); while (bp-- != qlf) { if (*bp & T_CONST) pushtype(CONST); if (*bp & T_RESTRICTED) pushtype(RESTRICTED); if (*bp & T_VOLATILE) pushtype(VOLATILE); pushtype(PTR); } return; duplicated: error("duplicated '%s'", yytext); } unsigned char decl(void) { auto struct type *tp, *tbase; auto unsigned char nd = 0; if (!(tbase = specifier())) return 0; if (yytoken != ';') { do { declarator(); tp = decl_type(tbase); if (isfunction(tp) && yytoken == '{') { compound(); return 1; } ++nd; } while (accept(',')); } expect(';'); if (nd == 0) { warning_error(user_opt.useless_typename, "useless type name in empty declaration"); } return 1; } void type_name() { }