scc

Simple C99 Compiler
Log | Files | Refs | README | LICENSE

commit eaf8259846c2b6d77467cddf8fe143c6cce568dd
parent b2fc11b3d2e07e84e2868f5aab8319612257855c
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Mon, 17 Mar 2014 16:39:17 +0100

Add definitions for struct and enums

Diffstat:
decl.c | 142++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
symbol.c | 9++++++---
symbol.h | 5+++--
syntax.h | 1+
types.c | 4+++-
5 files changed, 99 insertions(+), 62 deletions(-)

diff --git a/decl.c b/decl.c @@ -11,9 +11,6 @@ int8_t forbid_eof; -static struct dcldata - *declarator0(struct dcldata *dp, uint8_t ns, int8_t flags); - struct dcldata { uint8_t op; union { @@ -24,6 +21,9 @@ struct dcldata { } u; }; +static struct dcldata + *declarator0(struct dcldata *dp, uint8_t ns, int8_t flags); + static struct dcldata * arydcl(struct dcldata *dp) { @@ -90,8 +90,6 @@ expected: error: error(err, yytext); } -/* TODO: Add a token2 field in yylval to avoid yylval.sym->u.c */ - static struct dcldata* declarator0(struct dcldata *dp, uint8_t ns, int8_t flags) { @@ -155,13 +153,13 @@ declarator(struct ctype *tp, uint8_t ns, int8_t flags) return sym; } -static struct ctype *structdcl(void), *enumdcl(void); +static struct ctype *structdcl(uint8_t tag), *enumdcl(uint8_t tag); static struct ctype * specifier(int8_t *sclass) { struct ctype *tp = NULL; - int8_t qlf, sign, type, cls, cplex, size; + int8_t qlf, sign, type, cls, cplex, size, t; qlf = sign = type = cls = size = cplex = 0; @@ -177,15 +175,16 @@ specifier(int8_t *sclass) goto next_token; case TYPE: switch (sym->u.c) { - case ENUM: - tp = enumdcl(); goto set_type; - case STRUCT: case UNION: - tp = structdcl(); goto set_type; + case ENUM: case STRUCT: case UNION: + t = sym->u.c; + tp = (t == UNION) ? enumdcl(t) : structdcl(t); + p = &type; + goto check_spec; case TYPENAME: tp = yylval.sym->type; case VOID: case BOOL: case CHAR: case INT: case FLOAT: case DOUBLE: -set_type: p = &type; break; + p = &type; goto next_token; case SIGNED: case UNSIGNED: p = &sign; break; case LONG: @@ -194,18 +193,18 @@ set_type: p = &type; break; goto next_token; } case SHORT: - p = &size; break; + p = &size; goto next_token; case COMPLEX: case IMAGINARY: - p = &cplex; break; + p = &cplex; goto next_token; } break; default: goto check_types; } - if (*p) +next_token: next(); +check_spec: if (*p) goto invalid_type; *p = sym->u.c; -next_token: next(); } check_types: @@ -246,19 +245,86 @@ initializer(register struct ctype *tp) } } +/* TODO: add define for the 3 parameter of declarator */ +/* TODO: bitfields */ +static short +fielddcl(uint8_t ns, uint8_t type) +{ + struct ctype *tp; + struct symbol *sym; + short offset = 0; + + switch (yytoken) { + case IDEN: + warn(options.implicit, + "type defaults to 'int' in declaration"); + tp = inttype; + break; + case SCLASS: + error("storage class '%s' in struct/union field", yytext); + case TYPE: case TQUALIFIER: + tp = specifier(NULL); + break; + case ';': + break; + default: + error("declaration expected"); + } + + if (yytoken != ';') { + do { + sym = declarator(tp, ns, 1); + sym->u.offset = offset; + if (type == STRUCT) + offset += sym->type->size; + } while (accept(',')); + } + + expect(';'); + return offset; +} + static struct ctype * -structdcl(void) +structdcl(uint8_t tag) { - uint8_t type = yylval.sym->u.c; + register struct symbol *sym; + struct ctype *tp; + short size; + extern uint8_t namespace; next(); if (yytoken == IDEN) { + sym = lookup(yytext, NS_TAG); + if (sym) { + if (sym->type->op != tag) + goto bad_tag; + } else { + sym = install(yytext, NS_TAG); + } + next(); + } else { + sym = install(NULL, NS_TAG); } - return NULL; + sym->type = tp = mktype(NULL, tag, NULL, 0); + ++namespace; + + if (yytoken != ';') { + expect('{'); + while (!accept('}')) + size = fielddcl(namespace, tag); + } else { + size = 0; + } + tp->size = size; + + return tp; + +bad_tag: + error("error '%s' defined as wrong kind of tag", yytext); } static struct ctype * -enumdcl(void) +enumdcl(uint8_t token) { return NULL; } @@ -284,42 +350,6 @@ decl(void) return NULL; } -static struct symbol * -fielddcl(void) -{ - struct ctype *tp; - struct symbol *sym; - - switch (yytoken) { - case IDEN: - warn(options.implicit, - "type defaults to 'int' in declaration"); - tp = inttype; - break; - case SCLASS: - error("storage class '%s' in struct/union field", yytext); - case TYPE: case TQUALIFIER: - tp = specifier(NULL); - break; - case ';': - break; - default: - error("declaration expected"); - } - - if (yytoken != ';') { - do { - sym = declarator(tp, 0, 1); - if (accept(':')) - ; /* TODO: bitfields */ - /* TODO: add to the aggregate */ - } while (accept(',')); - } - - expect(';'); - return NULL; -} - struct node * typename(void) { diff --git a/symbol.c b/symbol.c @@ -101,9 +101,12 @@ install(char *s, uint8_t ns) tbl = &symtab[(ns >= NR_NAMESPACES) ? NS_IDEN : ns]; sym->next = tbl->head; tbl->head = sym; - t = &tbl->htab[hash(s)]; - sym->hash = *t; - *t = sym; + + if (s != NULL) { + t = &tbl->htab[hash(s)]; + sym->hash = *t; + *t = sym; + } return sym; } diff --git a/symbol.h b/symbol.h @@ -23,10 +23,10 @@ struct ctype { uint8_t op; /* type builder operator */ uint8_t size; /* size of variables */ uint16_t nelem; /* number of elements in arrays */ - unsigned forward : 1; /* forward type */ + unsigned forward : 1; /* forward type */ unsigned cplex : 1; /* complex specifier */ unsigned imag : 1; - unsigned sign : 1; /* sign type */ + unsigned sign : 1; /* sign type */ struct symbol *sym; /* symbol of the tag identifier */ struct ctype *type; /* base type */ struct ctype *next; /* next element in the hash */ @@ -46,6 +46,7 @@ struct symbol { uint8_t ns; union { char c; + short offset; } u; struct symbol *next; struct symbol *hash; diff --git a/syntax.h b/syntax.h @@ -6,6 +6,7 @@ #endif extern unsigned char curctx; +extern uint8_t namespace; enum opcode { OARY, OCALL, OFIELD, OPTR, OPOSTINC, OPOSTDEC, diff --git a/types.c b/types.c @@ -162,7 +162,7 @@ mktype(struct ctype *tp, uint8_t op, t = (op ^ (uint8_t) ((unsigned short) tp >> 3)) & NR_TYPE_HASH-1; tbl = &typetab[t]; - if (op != FTN) { + if (op != FTN || op != STRUCT || op != UNION || op != ENUM) { for (bp = *tbl; bp; bp = bp->next) { if (bp->type == tp && bp->op == op && bp->sym == sym && bp->nelem == nelem) { @@ -175,6 +175,8 @@ mktype(struct ctype *tp, uint8_t op, case PTR: size = PTRSIZE; break; case FTN: size = 0; break; case ARY: size = tp->size * nelem; break; + case ENUM: size = INTSIZE; + case STRUCT: case UNION: size = 0; break; default: size = tp->size; break; } bp = xmalloc(sizeof(*bp));