scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit 7204b59c338a474645eac83b24a7b37be7eb8b88
parent 1f4d772a7ff6987171acc1c6c5922123b764c110
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Thu,  4 Jul 2013 21:54:02 +0200

Allocate ctype in spec function

spec is the place where we read all the tokens which is going
to define the type, so it is a good place for allocate the
ctype struct.

Diffstat:
Mdecl.c | 34++++++++++++++++++----------------
Msymbol.h | 5++---
Mtypes.c | 131+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
3 files changed, 94 insertions(+), 76 deletions(-)

diff --git a/decl.c b/decl.c @@ -70,20 +70,19 @@ dirdcl(void) } } -static unsigned char -spec(register struct ctype *cp) +struct ctype * +spec(void) { - register unsigned char sign, n; + static unsigned char sign, type; + register struct ctype *tp = NULL; - for (n = sign = 0; ; ++n, next()) { + for (type = sign = 0; ; next()) { switch (yytoken) { case TYPEDEF: case EXTERN: case STATIC: case AUTO: case REGISTER: case CONST: case VOLATILE: - storage(cp, yytoken); + tp = storage(tp, yytoken); break; - case UNSIGNED: - cp->c_unsigned = 1; - case SIGNED: + case UNSIGNED: case SIGNED: if (sign == yytoken) error("duplicated '%s'", yytext); if (sign) @@ -92,22 +91,26 @@ spec(register struct ctype *cp) case FLOAT: case DOUBLE: case LDOUBLE: goto float_sign; } - sign = yytoken; + if (!tp) + tp = newctype(); + if ((type = sign = yytoken) == UNSIGNED) + tp->c_unsigned = 1; break; case FLOAT: case DOUBLE: if (sign) goto float_sign; case VOID: case CHAR: case SHORT: case INT: case LONG: case BOOL: - cp->type = btype(cp->type, yytoken); + tp = btype(tp, yytoken); + type = tp->type; break; case STRUCT: /* TODO */ case UNION: /* TODO */ case ENUM: /* TODO */ default: - if (!cp->type && sign) - cp->type = INT; - return n; + if (tp && !tp->type && sign) + tp->type = INT; + return tp; } } float_sign: @@ -181,7 +184,7 @@ listdcl(struct ctype *base) "type defaults to 'int' in declaration of '%s'", yytext); } - linkctype(tp, cursym); + (cursym->ctype = tp)->refcnt++; sp = nodesym(cursym); if (tp->type == FTN && yytoken == '{') { np = node2(ODEF, sp, function(cursym)); @@ -203,8 +206,7 @@ decl(void) while (accept(';')) /* nothing */; - tp = newctype(); - if (!spec(tp)) { + if (!(tp = spec())) { if (curctx != CTX_OUTER) goto end; warning("data definition has no type or storage class"); diff --git a/symbol.h b/symbol.h @@ -57,17 +57,16 @@ extern struct type tfloat, tdouble, tldouble, tlong; extern struct ctype *decl_type(struct ctype *t); extern void pushtype(unsigned mod); -extern unsigned char btype(unsigned char, unsigned char tok); +extern struct ctype *btype(struct ctype *tp, unsigned char tok); extern void new_ctx(void); extern void del_ctx(void); extern void freesyms(void); extern struct symbol *lookup(const char *s, char ns); extern struct symbol *find(const char *s, char ns); extern void insert(struct symbol *sym, unsigned char ctx); -extern void storage(struct ctype *cp, unsigned char mod); +extern struct ctype *storage(struct ctype *tp, unsigned char mod); extern struct ctype *newctype(void); extern void delctype(struct ctype *tp); -extern void linkctype(struct ctype *tp, struct symbol *sym); #ifndef NDEBUG extern void ptype(register struct ctype *t); diff --git a/types.c b/types.c @@ -22,15 +22,10 @@ newctype(void) } void -linkctype(register struct ctype *tp, register struct symbol *sym) -{ - sym->ctype = tp; - ++tp->refcnt; -} - -void delctype(register struct ctype *tp) { + if (!tp) + return; if (--tp->refcnt == 0) { if (tp->base) delctype(tp->base); @@ -90,114 +85,136 @@ decl_type(struct ctype *tp) return tp; } -unsigned char -btype(unsigned char type, unsigned char tok) +struct ctype * +btype(struct ctype *tp, unsigned char tok) { + register unsigned char type; + + if (!tp) + tp = newctype(); + + type = tp->type; switch (tok) { case VOID: - if (!type) - return VOID; + if (type) + goto two_or_more;; + type = VOID; break; case BOOL: - if (!type) - return BOOL; + if (type) + goto two_or_more; + type = BOOL; break; case CHAR: - if (!type) - return CHAR; + if (type) + goto two_or_more; + type = CHAR; break; case SHORT: - if (!type || type == INT) - return SHORT; + if (type && type != INT) + goto two_or_more; + type = SHORT; break; case INT: switch (type) { - case 0: return INT; - case SHORT: return INT; - case LONG: return LONG; + case 0: type = INT; break; + case SHORT: type = SHORT; break; + case LONG: type = LONG; break; + default: goto two_or_more; } break; case LONG: switch (type) { - case 0: case INT: return LONG; - case LONG: return LLONG; - case DOUBLE: return LDOUBLE; - case LLONG: case LDOUBLE: error("too much long"); + case 0: + case INT: type = LONG; break; + case LONG: type = LLONG; break; + case DOUBLE: type = LDOUBLE; break; + case LLONG: + case LDOUBLE: error("too much long"); } break; case FLOAT: - if (!type) - return FLOAT; + if (type) + goto two_or_more; + type = FLOAT; break; case DOUBLE: + if (type) + goto two_or_more; if (!type) - return DOUBLE; - if (type == LONG) - return LDOUBLE; + type = DOUBLE; + else if (type == LONG) + type = LDOUBLE; break; #ifndef NDEBUG default: abort(); #endif } + tp->type = type; + return tp; + +two_or_more: error("two or more basic types"); } -void -storage(struct ctype *cp, unsigned char mod) +struct ctype * +storage(register struct ctype *tp, unsigned char mod) { extern unsigned char curctx; + if (!tp) + tp = newctype(); switch (mod) { case TYPEDEF: - if (cp->c_type) + if (tp->c_type) goto duplicated; - if (cp->c_extern | cp->c_auto | cp->c_reg | cp->c_static) + if (tp->c_extern | tp->c_auto | tp->c_reg | tp->c_static) goto two_storage; - cp->c_type = 1; - return; + tp->c_type = 1; + return tp; case EXTERN: - if (cp->c_extern) + if (tp->c_extern) goto duplicated; - if (cp->c_type | cp->c_auto | cp->c_reg | cp->c_static) + if (tp->c_type | tp->c_auto | tp->c_reg | tp->c_static) goto two_storage; - cp->c_extern = 1; - return; + tp->c_extern = 1; + return tp; case STATIC: - if (cp->c_static) + if (tp->c_static) goto duplicated; - if (cp->c_type | cp->c_extern | cp->c_auto | cp->c_reg) + if (tp->c_type | tp->c_extern | tp->c_auto | tp->c_reg) goto two_storage; - cp->c_static = 1; - return; + tp->c_static = 1; + return tp; case AUTO: if (curctx != CTX_OUTER) goto bad_file_scope_storage; - if (cp->c_type | cp->c_extern | cp->c_static | cp->c_reg) + if (tp->c_type | tp->c_extern | tp->c_static | tp->c_reg) goto two_storage; - if (cp->c_auto) + if (tp->c_auto) goto duplicated; - cp->c_static = 1; - return; + tp->c_static = 1; + return tp; case REGISTER: if (curctx != CTX_OUTER) goto bad_file_scope_storage; - if (cp->c_type | cp->c_extern | cp->c_auto | cp->c_static) + if (tp->c_type | tp->c_extern | tp->c_auto | tp->c_static) goto two_storage; - if (cp->c_reg) + if (tp->c_reg) goto duplicated; - cp->c_reg = 1; - return; + tp->c_reg = 1; + return tp; case CONST: - if (options.repeat && cp->c_const) + if (options.repeat && tp->c_const) goto duplicated; - cp->c_const = 1; - return; + tp->c_const = 1; + return tp; case VOLATILE: - if (options.repeat && cp->c_volatile) + if (options.repeat && tp->c_volatile) goto duplicated; - cp->c_volatile = 1; - return; + tp->c_volatile = 1; + return tp; } bad_file_scope_storage: error("file-scope declaration specifies '%s'", yytext);