scc

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

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:
Mdecl.c | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Msizes.h | 4++++
Msymbol.h | 6+++++-
Mtypes.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; }