commit ac28fe221439795f74be808040767bb112017659
parent 40566c3a7324fdb0e23dcee2e207c630f4460098
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Mon, 17 Mar 2014 21:08:07 +0100
Add the enumeration values as fields
Diffstat:
M | decl.c | | | 34 | ++++++++++++++++++++++++++-------- |
1 file changed, 26 insertions(+), 8 deletions(-)
diff --git a/decl.c b/decl.c
@@ -256,15 +256,20 @@ initializer(register struct ctype *tp)
static void
newfield(struct ctype *tp, struct symbol *sym)
{
- struct field *p, *q;
- short size, offset;
- char *s, *t;
+ register struct field *p, *q;
+ register char *s, *t;
+ static short size, offset;
+ static uint8_t op;
+ static char *err;
s = sym->name;
+ op = tp->op;
for (q = p = tp->u.fields; p; q = p, p = p->next) {
t = p->sym->name;
if (*s == *t && !strcmp(s, t))
- error("duplicated field '%s'", s);
+ goto duplicated_name;
+ if (op == ENUM && sym->u.i == p->sym->u.i)
+ goto duplicated_value;
}
p = xmalloc(sizeof(*p));
@@ -273,20 +278,31 @@ newfield(struct ctype *tp, struct symbol *sym)
size = sym->type->size;
if (!q) {
tp->u.fields = p;
- tp->size = size;
- sym->u.offset = 0;
+ if (op != ENUM) {
+ tp->size = size;
+ sym->u.offset = 0;
+ }
} else {
q->next = p;
if (tp->op == STRUCT) {
offset = ALIGN(size, tp->size);
sym->u.offset = offset;
tp->size = offset + size;
- } else {
+ } else if (op == UNION) {
sym->u.offset = 0;
if (tp->size < size)
tp->size = size;
}
}
+
+ return;
+
+duplicated_name:
+ err = "duplicated fields '%s' and '%s'";
+ goto error;
+duplicated_value:
+ err = "duplicated enumeration fields '%s' and '%s'";
+error: error(err, s, t);
}
static void
@@ -391,10 +407,12 @@ enumdcl(uint8_t token)
while (yytoken != '}') {
if (yytoken != IDEN)
goto iden_expected;
- sym = newiden(namespace); /* TODO: check duplicated */
+ sym = newiden(namespace);
+ sym->type = inttype;
if (accept('='))
initializer(inttype);
sym->u.i = val++;
+ newfield(tp, sym);
if (!accept(','))
break;
}