ref: fd33aabb1f822618a90a1f05ad820f313fff0953
parent: 729bca35c55764bb98afccbd790570e5c94b47ed
author: Roberto E. Vargas Caballero <[email protected]>
date: Sun Jul 1 15:57:06 EDT 2012
Removed type struct The ctype struct supplant the place of the old struct type, because ctype has the information about the type qualifiers needed by pointers. This imply that different variables will share the same ctype struct (pointers will share the same base type), so it is necessary a reference count system. The reference count system is implement using the new functions newctype and delctype.
--- a/decl.c
+++ b/decl.c
@@ -77,16 +77,16 @@
goto signed_and_unsigned;
sign = yytoken;
break;
- case VOID: case CHAR: case SHORT: case INT: case FLOAT:
- case DOUBLE: case LONG: case BOOL:
- cp->base = btype(cp->base, yytoken);
+ case VOID: case CHAR: case SHORT: case INT:
+ case FLOAT: case DOUBLE: case LONG: case BOOL:
+ cp->type = btype(cp->type, yytoken);
break;
case STRUCT: /* TODO */
case UNION: /* TODO */
case ENUM: /* TODO */
default:
- if (!cp->base && sign)
- cp->base = T_INT;
+ if (!cp->type && sign)
+ cp->type = INT;
return n;
}
}
@@ -125,18 +125,18 @@
pushtype(*bp);
}
-static unsigned char listdcl(register struct ctype *cp)
+static unsigned char listdcl(register struct ctype *tp)
{
- register struct type *tp;
-
do {
+ register struct ctype *new;
+
declarator();
- tp = decl_type(cp->base);
- if (!tp) {
+ new = decl_type(tp);
+ if (!new->type) {
warning_error(user_opt.implicit_int,
"type defaults to 'int' in declaration of '%s'",
yytext);
- } else if (tp->op == FTN && yytoken == '{') {
+ } else if (new->type == FTN && yytoken == '{') {
compound();
return 0;
}
@@ -147,12 +147,13 @@
unsigned char decl(void)
{
- auto struct ctype ctype;
+ register struct ctype *tp;
if (accept(';'))
return 1;
- memset(&ctype, 0, sizeof(ctype));
- if (!spec(&ctype)) {
+ tp = newctype();
+
+ if (!spec(tp)) {
if (nested_level != 0)
return 0;
warning("data definition has no type or storage class");
@@ -160,10 +161,11 @@
if (yytoken == ';') {
warning_error(user_opt.useless_typename,
"useless type name in empty declaration");
- } else if (listdcl(&ctype)) { /* in case of not being a function */
+ } else if (listdcl(tp)) { /* in case of not being a function */
expect(';');
}
+ delctype(tp);
return 1;
}
--- a/symbol.h
+++ b/symbol.h
@@ -7,17 +7,6 @@
# include <stdbool.h>
#endif
-#define T_CHAR (&tschar)
-#define T_SHORT (&tshort)
-#define T_INT (&tint)
-#define T_FLOAT (&tfloat)
-#define T_DOUBLE (&tdouble)
-#define T_LDOUBLE (&tdouble)
-#define T_LONG (&tlong)
-#define T_LLONG (&tllong)
-#define T_VOID (&tvoid)
-#define T_BOOL (&tbool)
-
enum namespace {
NS_IDEN,
NS_KEYWORD,
@@ -27,6 +16,7 @@
};
struct ctype {
+ unsigned type : 5;
bool c_type : 1;
bool c_extern : 1;
bool c_static : 1;
@@ -36,18 +26,10 @@
bool c_volatile : 1;
bool c_restrict : 1;
bool c_unsigned : 1;
- struct type *base;
+ struct ctype *base;
+ unsigned char refcnt;
};
-struct type {
- unsigned char op;
- struct type *base;
-
- union {
- size_t nelem; /* size of array */
- };
-};
-
struct symbol {
struct ctype ctype;
unsigned char ns;
@@ -74,9 +56,9 @@
extern struct type tfloat, tdouble, tldouble, tlong;
-extern struct type *decl_type(struct type *t);
+extern struct ctype *decl_type(struct ctype *t);
extern void pushtype(unsigned char mod);
-extern struct type *btype(struct type *tp, unsigned char tok);
+extern unsigned char btype(unsigned char, unsigned char tok);
extern void new_ctx(struct symctx *ctx);
extern void del_ctx(void);
extern struct symbol *install(const char *s, unsigned char key);
@@ -83,9 +65,11 @@
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);
+extern struct ctype *newctype(void);
+extern void delctype(register struct ctype *tp);
#ifndef NDEBUG
-extern void ptype(register struct type *t);
+extern void ptype(register struct ctype *t);
#else
# define ptype(t)
#endif
--- a/types.c
+++ b/types.c
@@ -7,34 +7,58 @@
#include "tokens.h"
#include "symbol.h"
-struct type tschar = {.op = CHAR};
-struct type tshort = {.op = SHORT};
-struct type tint = {.op = INT};
-struct type tfloat = {.op = FLOAT};
-struct type tdouble = {.op = DOUBLE};
-struct type tldouble = {.op = LDOUBLE};
-struct type tlong = {.op = LONG};
-struct type tllong = {.op = LLONG};
-struct type tvoid = {.op = VOID};
-struct type tbool = {.op = BOOL};
static unsigned char stack[NR_DECLARATORS];
static unsigned char *stackp = stack;
-static struct type *
-mktype(register struct type *base, unsigned char op)
+struct ctype *newctype(void)
{
- register struct type *nt;
- assert(op == PTR || op == ARY || op == FTN ||
- op == VOLATILE || op == RESTRICT || op == CONST);
+ register struct ctype *tp = xcalloc(sizeof(tp), 1);
- nt = xcalloc(sizeof(*base), 1);
- nt->op = op;
- nt->base = base;
- return nt;
+ ++tp->refcnt;
+ return tp;
}
+void delctype(register struct ctype *tp)
+{
+ if (--tp->refcnt == 0) {
+ if (tp->base)
+ delctype(tp->base);
+ free(tp);
+ }
+}
+
+static struct ctype *
+mktype(register struct ctype *tp, unsigned char op)
+{
+ switch (op) {
+ case PTR: case ARY: case FTN: {
+ register struct ctype *aux = tp;
+
+ ++tp->refcnt;
+ tp = newctype();
+ tp->type = op;
+ tp->base = aux;
+ break;
+ }
+ case VOLATILE:
+ tp->c_volatile = 1;
+ break;
+ case RESTRICT:
+ tp->c_restrict = 1;
+ break;
+ case CONST:
+ tp->c_const = 1;
+ break;
+#ifndef NDEBUG
+ default:
+ abort();
+#endif
+ }
+ return tp;
+}
+
void pushtype(unsigned char mod)
{
if (stackp == stack + NR_DECLARATORS)
@@ -42,62 +66,57 @@
*stackp++ = mod;
}
-struct type *decl_type(struct type *t)
+struct ctype *decl_type(struct ctype *tp)
{
while (stackp != stack)
- t = mktype(t, *--stackp);
- ptype(t);
- return t;
+ tp = mktype(tp, *--stackp);
+ ptype(tp);
+ return tp;
}
-struct type *btype(struct type *tp, unsigned char tok)
+unsigned char btype(unsigned char type, unsigned char tok)
{
switch (tok) {
case VOID:
- if (tp == NULL)
- return T_VOID;
+ if (!type)
+ return VOID;
break;
case BOOL:
- if (tp == NULL)
- return T_BOOL;
+ if (!type)
+ return BOOL;
break;
case CHAR:
- if (tp == NULL)
- return T_CHAR;
+ if (!type)
+ return CHAR;
break;
case SHORT:
- if (tp == NULL || tp == T_INT)
- return T_SHORT;
+ if (!type || type == INT)
+ return SHORT;
break;
case INT:
- if (tp == NULL)
- return T_INT;
- if (tp == T_SHORT)
- return T_SHORT;
- if (tp == T_LONG)
- return T_LONG;
+ switch (type) {
+ case 0: return INT;
+ case SHORT: return INT;
+ case LONG: return 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");
+ switch (type) {
+ case 0: case INT: return LONG;
+ case LONG: return LLONG;
+ case DOUBLE: return LDOUBLE;
+ case LLONG: case LDOUBLE: error("too much long");
+ }
break;
case FLOAT:
- if (tp == NULL)
- return T_FLOAT;
+ if (!type)
+ return FLOAT;
break;
case DOUBLE:
- if (tp == NULL)
- return T_DOUBLE;
- if (tp == T_LONG)
- return T_LDOUBLE;
+ if (!type)
+ return DOUBLE;
+ if (type == LONG)
+ return LDOUBLE;
break;
default:
abort();
@@ -171,9 +190,10 @@
#ifndef NDEBUG
#include <stdio.h>
-void ptype(register struct type *t)
+void ptype(register struct ctype *tp)
{
static const char *strings[] = {
+ [0] = "[no type]",
[ARY] = "array of ",
[PTR] = "pointer to ",
[FTN] = "function that returns ",
@@ -190,10 +210,10 @@
[DOUBLE] = "double ",
[LDOUBLE] = "long double "
};
- assert(t);
+ assert(tp);
- for (; t; t = t->base)
- fputs(strings[t->op], stdout);
+ for (; tp; tp = tp->base)
+ fputs(strings[tp->type], stdout);
putchar('\n');
}