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:
M | decl.c | | | 34 | ++++++++++++++++++---------------- |
M | symbol.h | | | 5 | ++--- |
M | types.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);