scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit 0af5513b097a22fa8cb181e4d11f671f2f02ab26
parent 08b0f2a554d8e1d8b651ae0d25947104604e5df9
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Fri, 29 Jun 2012 09:53:06 +0200

Refactoring of specifier function

The code was really ugly and it was impossible use the type logic in other
part (for example in type name rules). In first step we split the type
qualifiers and modifiers in a different struct, and let the base type as a
tree, which is generated using only the 3 type compound operators: [], ()
and *.

So we will have 2 different structs now, ctype which holds the
modifiers (and it will form part of the symbol) and btype, which will be
built using the type operators.

Diffstat:
Mcc.h | 1+
Mdecl.c | 223++++++++++++++++++++-----------------------------------------------------------
Msymbol.c | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msymbol.h | 13++++++++-----
Mtypes.c | 100++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
Mtypes.h | 30+++++++++++-------------------
6 files changed, 215 insertions(+), 217 deletions(-)

diff --git a/cc.h b/cc.h @@ -10,6 +10,7 @@ struct user_opt { unsigned char implicit_int; unsigned char c99; unsigned char useless_typename; + unsigned char typeqlf_repeat; }; diff --git a/decl.c b/decl.c @@ -2,6 +2,7 @@ #include <stddef.h> #include <string.h> +#include "sizes.h" #include "cc.h" #include "tokens.h" #include "types.h" @@ -58,209 +59,97 @@ static void dirdcl(void) } } - - - - -/* - * - */ - -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) +static unsigned char spec(register struct ctype *cp) { - auto unsigned char sign, sclass, tqlf, nt; - auto struct type *t; + register unsigned char sign, n; - t = NULL; - tqlf = sign = sclass = 0; - for (;; next()) { + for (n = sign = 0; ; ++n, 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 RESTRICT: - 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); - } + case TYPEDEF: case EXTERN: case STATIC: case AUTO: + case REGISTER: case CONST: case VOLATILE: + ctype(cp, yytoken); + break; + case UNSIGNED: case SIGNED: + if (sign == yytoken) + goto duplicated; + if (sign) + goto signed_and_unsigned; sign = yytoken; - if (t == NULL) - continue; /* we don't have type now */ - goto check_type; - case STRUCT: /* TODO */ + case VOID: case CHAR: case SHORT: case INT: case FLOAT: + case DOUBLE: case LONG: case BOOL: + cp->base = btype(cp->base, yytoken); + break; + 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(RESTRICT); - 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; + if (!cp->base && sign) + cp->base = T_INT; + return n; } } -duplicated_qlf: +duplicated: error("duplicated '%s'", yytext); -two_or_more_btype: - error("two or more basic types"); -incorrect_sign: - error("sign specifier applied to incorrect type"); +signed_and_unsigned: + error("both 'signed' and 'unsigned' in declaration specifiers"); } - -#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; + unsigned char qlf[NR_DECLARATORS], *bp, *lim; - lim = qlf + PTRLEVEL_MAX; + lim = &qlf[NR_DECLARATORS]; 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 RESTRICT: - if (!(*bp ^= T_RESTRICTED)) - goto duplicated; - goto repeat_qlf; - case VOLATILE: - if (!(*bp ^= T_VOLATILE)) - goto duplicated; - goto repeat_qlf; - default: - break; + *bp++ = PTR; + for (;;) { + next(); + switch (yytoken) { + case CONST: case VOLATILE: case RESTRICT: + *bp++ = yytoken; + default: + break; + } } } - if (bp == lim) - error("Too much indirection levels"); + error("Too much type declarators"); dirdcl(); - while (bp-- != qlf) { - if (*bp & T_CONST) pushtype(CONST); - if (*bp & T_RESTRICTED) pushtype(RESTRICT); - if (*bp & T_VOLATILE) pushtype(VOLATILE); - pushtype(PTR); - } - - return; - -duplicated: - error("duplicated '%s'", yytext); + while (bp-- != qlf) + pushtype(*bp); } unsigned char decl(void) { - auto struct type *tp, *tbase; + auto struct ctype ctype; + auto struct type *tp; auto unsigned char nd = 0; - if (!(tbase = specifier())) - return 0; + if (accept(';')) + return 1; + if (!spec(&ctype)) { + if (nested_level == 0) + warning("data definition has no type or storage class"); + else + return 0; + } if (yytoken != ';') { do { declarator(); - tp = decl_type(tbase); - if (isfunction(tp) && yytoken == '{') { + tp = decl_type(ctype.base); + if (!tp) { + warning_error(user_opt.implicit_int, + "type defaults to 'int' in declaration of '%s'", + yytext); + } + if (tp->op == FTN && yytoken == '{') { compound(); - return 1; + return; } ++nd; } while (accept(',')); } - expect(';'); if (nd == 0) { warning_error(user_opt.useless_typename, diff --git a/symbol.c b/symbol.c @@ -2,7 +2,9 @@ #include <stdlib.h> #include <string.h> +#include "cc.h" #include "symbol.h" +#include "tokens.h" #define xmalloc malloc #define xstrdup strdup @@ -100,3 +102,66 @@ unsigned char hashfun(register const char *s) /* nothing */; return h; } + +void ctype(struct ctype *cp, unsigned char mod) +{ + extern unsigned char nested_level; + + switch (mod) { + case TYPEDEF: + if (cp->c_type) + goto duplicated; + if (cp->c_extrn | cp->c_auto | cp->c_reg | cp->c_static) + goto two_storage; + cp->c_type = 1; + return; + case EXTERN: + if (cp->c_extrn) + goto duplicated; + if (cp->c_type | cp->c_auto | cp->c_reg | cp->c_static) + goto two_storage; + cp->c_extrn = 1; + return; + case STATIC: + if (cp->c_static) + goto duplicated; + if (cp->c_type | cp->c_extrn | cp->c_auto | cp->c_reg) + goto two_storage; + cp->c_static = 1; + return; + case AUTO: + if (nested_level != 0) + goto bad_file_scope_storage; + if (cp->c_type | cp->c_extrn | cp->c_static | cp->c_reg) + goto two_storage; + if (cp->c_auto) + goto duplicated; + cp->c_static = 1; + return; + case REGISTER: + if (nested_level != 0) + goto bad_file_scope_storage; + if (cp->c_type | cp->c_extrn | cp->c_auto | cp->c_static) + goto two_storage; + if (cp->c_reg) + goto duplicated; + cp->c_reg = 1; + return; + case CONST: + if (user_opt.typeqlf_repeat && cp->c_reg) + goto duplicated; + cp->c_const = 1; + return; + case VOLATILE: + if (user_opt.typeqlf_repeat && cp->c_vol) + goto duplicated; + cp->c_vol = 1; + return; + } +bad_file_scope_storage: + error("file-scope declaration specifies ā€˜%sā€™", yytext); +two_storage: + error("Two or more storage specifier"); +duplicated: + error("duplicated '%s'", yytext); +} diff --git a/symbol.h b/symbol.h @@ -16,17 +16,18 @@ enum namespace { }; struct type; -struct symbol; struct ctype { - bool c_typedef : 1; - bool c_extern : 1; + bool c_type : 1; + bool c_extrn : 1; bool c_static : 1; bool c_auto : 1; - bool c_register : 1; + bool c_reg : 1; bool c_const : 1; - bool c_volatile : 1; + bool c_vol : 1; struct type *base; + unsigned char len; + char *iden; }; struct symbol { @@ -56,5 +57,7 @@ extern void del_ctx(void); extern struct symbol *install(const char *s, unsigned char key); extern struct symbol *lookup(char *s, unsigned char key); extern unsigned char hashfun(register const char *s); +extern void ctype(struct ctype *cp, unsigned char mod); + #endif diff --git a/types.c b/types.c @@ -2,6 +2,7 @@ #include <assert.h> #include <stdlib.h> +#include "sizes.h" #include "cc.h" #include "tokens.h" #include "types.h" @@ -9,33 +10,80 @@ /* TODO: create wrapper file */ #define xcalloc calloc -struct type tschar = {.btype = CHAR, .sign = 1}; -struct type tuchar = {.btype = CHAR, .sign = 0}; -struct type tshort = {.btype = SHORT, .sign = 1}; -struct type tushort = {.btype = SHORT, .sign = 0}; -struct type tint = {.btype = INT, .sign = 1}; -struct type tuint = {.btype = SHORT, .sign = 0}; -struct type tfloat = {.btype = FLOAT, .sign = 1}; -struct type tdouble = {.btype = DOUBLE, .sign = 1}; -struct type tldouble = {.btype = LDOUBLE, .sign = 1}; -struct type tlong = {.btype = LONG, .sign = 1}; -struct type tulong = {.btype = LONG, .sign = 0}; -struct type tllong = {.btype = LLONG, .sign = 1}; -struct type tullong = {.btype = LLONG, .sign = 0}; -struct type tvoid = {.btype = VOID, .sign = 0}; -struct type tkeyword; - -#define TYPEOP_MAX PTRLEVEL_MAX /* TODO: take a look of the ANSI standard */ - -static unsigned char stack[TYPEOP_MAX]; +struct type tschar = {.btype = CHAR}; +struct type tshort = {.btype = SHORT}; +struct type tint = {.btype = INT}; +struct type tfloat = {.btype = FLOAT}; +struct type tdouble = {.btype = DOUBLE}; +struct type tldouble = {.btype = LDOUBLE}; +struct type tlong = {.btype = LONG}; +struct type tllong = {.btype = LLONG}; +struct type tvoid = {.btype = VOID}; +struct type tbool = {.btype = BOOL}; + +static unsigned char stack[NR_DECLARATORS]; static unsigned char *stackp = stack; +struct type *btype(struct type *tp, unsigned char tok) +{ + switch (tok) { + case VOID: + if (tp == NULL) + return T_VOID; + break; + case BOOL: + if (tp == NULL) + return T_BOOL; + break; + case CHAR: + if (tp == NULL) + return T_CHAR; + break; + case SHORT: + if (tp == NULL || tp == T_INT) + return T_SHORT; + break; + case INT: + if (tp == NULL) + return T_INT; + if (tp == T_SHORT) + return T_SHORT; + if (tp == T_LONG) + return T_LONG; + break; + case LONG: + if (tp == NULL || tp == T_INT) + return T_LONG; + if (tp == T_LONG) + return T_LLONG; + if (tp == T_DOUBLE) + return T_LDOUBLE; + if (tp == T_LLONG) + error("'long long long' is too long"); + if (tp == T_LDOUBLE) + error("'long long double' is too long"); + break; + case FLOAT: + if (tp == NULL) + return T_FLOAT; + break; + case DOUBLE: + if (tp == NULL) + return T_DOUBLE; + if (tp == T_LONG) + return T_LDOUBLE; + break; + default: + abort(); + } + error("two or more basic types"); +} -void pushtype(char op) +void pushtype(unsigned char mod) { - if (stackp == stack + TYPEOP_MAX) - error("Too much type modifiers"); - *stackp++ = op; + if (stackp == stack + NR_DECLARATORS) + error("Too much type declarators"); + *stackp++ = mod; } struct type *decl_type(struct type *t) @@ -107,7 +155,7 @@ void ptype(register struct type *t) break; break; case RESTRICT: - fputs("restricted ", stdout); + fputs("restrict ", stdout); break; case CONST: fputs("const ", stdout); @@ -115,7 +163,7 @@ void ptype(register struct type *t) default: { static char *type, *sign; - sign = (t->sign) ? "signed" : "unsigned"; + /* sign = (t->sign) ? "signed" : "unsigned"; */ switch (t->btype) { case INT: type = "int"; break; case CHAR: type = "char"; break; @@ -129,7 +177,7 @@ void ptype(register struct type *t) default: abort(); } - printf("%s %s", sign, type); + /* printf("%s %s", sign, type); */ } } } diff --git a/types.h b/types.h @@ -1,6 +1,11 @@ #ifndef TYPES_H_ #define TYPES_H_ +#ifndef __bool_true_false_are_defined +# include <stdbool.h> +#endif + +struct ctype; struct type { unsigned op : 5; @@ -15,49 +20,35 @@ struct type { union { struct { unsigned btype : 4; - unsigned sign : 1; }; size_t nelem; /* size of array */ }; }; -extern struct type tschar, tuchar, tshort, tushort, tint, tuint; +extern struct type tchar, tshort, tint, tulong, tllong, tvoid, tkeyword; extern struct type tfloat, tdouble, tldouble, tlong; -extern struct type tulong, tllong, tullong, tvoid, tkeyword; -#define T_SCHAR (&tschar) -#define T_UCHAR (&tuchar) +#define T_CHAR (&tschar) #define T_SHORT (&tshort) -#define T_USHORT (&tushort) #define T_INT (&tint) -#define T_UINT (&tuint) #define T_FLOAT (&tfloat) #define T_DOUBLE (&tdouble) #define T_LDOUBLE (&tdouble) #define T_LONG (&tlong) -#define T_ULONG (&tulong) #define T_LLONG (&tllong) -#define T_ULLONG (&tullong) #define T_VOID (&tvoid) -#define T_KWD (&tkeyword) +#define T_BOOL (&tbool) + #define ARY 1 #define PTR 2 #define FTN 3 -#define T_CONST 1 -#define T_RESTRICTED 2 -#define T_VOLATILE 4 - -#define QLF(x) (VOLATILE - x + 1) - struct type *mktype(register struct type *base, unsigned char op); -/* ANSI C says minimum maximum for indirection level is 12 */ -#define PTRLEVEL_MAX 12 extern struct type *decl_type(struct type *t); -extern void pushtype(char op); +void pushtype(unsigned char mod); #ifndef NDEBUG extern void ptype(register struct type *t); @@ -67,5 +58,6 @@ extern void ptype(register struct type *t); extern unsigned char isfunction(struct type *t); +extern struct type *btype(struct type *tp, unsigned char tok); #endif