commit 1340a9b646844af4368ad3c3b275e53904019d83
parent 6363b621d371ca732a5a63212199bd059cd507d0
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Mon, 23 Sep 2013 22:00:58 +0200
Add struct and unions declarators
These declarators are very diferents of the previous due to
they define a new namespace, so the thecniques used previously
cannot be applied here. We have to define a new namespace with
each new struct declared. We defined the first struct namespace
as NS_ANY+1, so we will not have any collision with the anothers
namespaces.
Diffstat:
M | decl.c | | | 84 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- |
M | sizes.h | | | 4 | ++++ |
M | symbol.h | | | 6 | +++++- |
M | types.c | | | 2 | +- |
4 files changed, 90 insertions(+), 6 deletions(-)
diff --git a/decl.c b/decl.c
@@ -11,6 +11,9 @@
char parser_out_home;
static struct symbol *cursym;
+static unsigned char nr_structs = NS_ANY + 1;
+static unsigned char structbuf[NR_STRUCT_LEVEL], *structp = &structbuf[0];
+
static void declarator(struct ctype *tp, unsigned char ns);
static struct symbol *
@@ -79,6 +82,9 @@ dirdcl(register struct ctype *tp, unsigned char ns)
}
}
+
+static struct ctype *struct_spec(register struct ctype *);
+
struct ctype *
spec(void)
{
@@ -95,10 +101,13 @@ spec(void)
case FLOAT: case DOUBLE: case BOOL:
case VOID: case CHAR: case SHORT:
case INT: case ENUM: case LONG:
- case STRUCT: case UNION:
tp = btype(tp, yytoken);
break;
- /* TODO: ENUM, STRUCT, UNION */
+ /* TODO: ENUM */
+ case STRUCT: case UNION:
+ tp = btype(tp, yytoken);
+ next();
+ return struct_spec(tp);
case IDEN:
if (!tp || !tp->type) {
struct symbol *sym;
@@ -138,6 +147,60 @@ spec(void)
}
}
+static struct ctype *
+struct_dcl(unsigned char ns)
+{
+ register struct ctype *tp, *base;
+
+ if (!(base = spec())) {
+ base = newctype();
+ base->type = INT;
+ warning_error(options.implicit,
+ "data definition has no type or storage class");
+ }
+ if (base->c_typedef || base->c_static || base->c_auto ||
+ base->c_register || base->c_extern) {
+ error("storage specifier in a struct/union field declaration");
+ }
+
+ do { /* TODO: detect unnamed structs */
+ declarator(base, ns);
+ tp = decl_type(base);
+ (cursym->ctype = tp)->refcnt++;
+ } while (accept(','));
+
+ expect(';');
+ return tp;
+}
+
+static struct ctype *
+struct_spec(register struct ctype *tp)
+{
+ if (yytoken == IDEN) {
+ (namespace(NS_STRUCT, -1)->ctype = tp)->refcnt++;
+ next();
+ }
+
+ if (nr_structs == NR_MAXSTRUCTS)
+ error("too much structs/unions defined");
+ if (structp == &structbuf[NR_STRUCT_LEVEL])
+ error("too much nested structs/unions");
+ tp->c_struct = *structp++ = nr_structs;
+
+ if (!accept('{'))
+ return tp;
+
+ if (!tp->forward)
+ error("struct/union already defined");
+
+ do
+ struct_dcl(tp->c_struct);
+ while (!accept('}'));
+ tp->forward = 0;
+
+ return tp;
+}
+
static void
declarator(struct ctype *tp, unsigned char ns)
{
@@ -201,6 +264,9 @@ listdcl(struct ctype *base)
declarator(base, base->c_typedef ? NS_TYPEDEF : NS_IDEN);
tp = decl_type(base);
(cursym->ctype = tp)->refcnt++;
+ if ((tp->type == STRUCT || tp->type == UNION) && tp->forward)
+ error("declaration of variable with incomplete type");
+
sp = nodesym(cursym);
if (tp->type == FTN && yytoken == '{') {
np = node2(ODEF, sp, function(cursym));
@@ -227,8 +293,18 @@ repeat: if (!(tp = spec())) {
warning_error(options.implicit,
"data definition has no type or storage class");
} else if (accept(';')) {
- warning_error(options.useless,
- "useless type name in empty declaration");
+ register unsigned char type = tp->type;
+
+ if (type == STRUCT || type == UNION) {
+ if (tp->c_extern || tp->c_static || tp->c_auto ||
+ tp->c_register || tp->c_const || tp->c_volatile) {
+ warning_error(options.useless,
+ "useless storage class specifier in empty declaration");
+ }
+ } else {
+ warning_error(options.useless,
+ "useless type name in empty declaration");
+ }
delctype(tp);
goto repeat;
}
diff --git a/sizes.h b/sizes.h
@@ -11,6 +11,10 @@
*/
#define NR_COND 8
/*
+ * number of defined structs/unions in one translation unit
+ */
+#define NR_MAXSTRUCTS 127
+/*
* 12 pointer, array, and function declarators (in any combinations)
* modifying an arithmetic, a structure, a union, or an incomplete type
* in a declaration
diff --git a/symbol.h b/symbol.h
@@ -32,7 +32,11 @@ struct ctype {
bool c_restrict : 1;
bool c_unsigned : 1;
bool c_signed : 1;
- unsigned len;
+ bool forward : 1;
+ union {
+ unsigned len;
+ unsigned char c_struct;
+ };
struct ctype *base;
unsigned char refcnt;
};
diff --git a/types.c b/types.c
@@ -17,7 +17,7 @@ newctype(void)
{
register struct ctype *tp = xcalloc(sizeof(*tp), 1);
- tp->refcnt = 1;
+ tp->forward = tp->refcnt = 1;
return tp;
}