commit ec0bbf93d441cac0db795007d80b1dcdc32e91d0
parent 7cce9dc9462e67e8ebfd5a507b49707f3a1e1013
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Sat, 15 Mar 2014 14:13:33 +0100
Refactoring of type system
The type system was broken and this commit refactorize all the code,
so it is not an incremental commit, it is a new code.
Diffstat:
M | decl.c | | | 674 | ++++++++++++++++++++++++++++++------------------------------------------------- |
M | expr.c | | | 17 | +++++++---------- |
M | flow.c | | | 52 | +++++++++++++++++----------------------------------- |
M | lex.c | | | 195 | +++++++++++++++++++++++++++++-------------------------------------------------- |
M | main.c | | | 10 | +++------- |
M | symbol.c | | | 144 | +++++++++++++++++++++++++++++++++++-------------------------------------------- |
M | symbol.h | | | 105 | ++++++++++++++++++++++++++++++++++++++----------------------------------------- |
M | syntax.h | | | 7 | ++----- |
M | tokens.h | | | 79 | +++++++++++++++++++++++++++++++++++++++++++++++-------------------------------- |
M | tree.c | | | 1 | + |
M | types.c | | | 310 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------- |
11 files changed, 742 insertions(+), 852 deletions(-)
diff --git a/decl.c b/decl.c
@@ -1,5 +1,6 @@
#include <assert.h>
#include <stddef.h>
+#include <stdint.h>
#include <string.h>
#include "sizes.h"
@@ -8,59 +9,76 @@
#include "syntax.h"
#include "symbol.h"
-char parser_out_home;
-/*
- * Number of nested declarations:
- * Number of nested struct declarations
- * +1 for the function declaration
- * +1 for the field declaration
- */
-static unsigned char nr_tags = NS_TAG;
-static unsigned char nested_tags;
+int8_t forbid_eof;
-static struct symbol *declarator(struct ctype *tp,
- unsigned char ns, unsigned char isfun);
+static struct dcldata
+ *declarator0(struct dcldata *dp, uint8_t ns, int8_t flags);
-static struct symbol *
-directdcl(register struct ctype *tp, unsigned char ns, unsigned char isfun)
+struct dcldata {
+ uint8_t op;
+ union {
+ unsigned short nelem;
+ struct symbol *sym;
+ struct funpars *pars;
+ uint8_t qlf;
+ } u;
+};
+
+static struct dcldata *
+arydcl(struct dcldata *dp)
+{
+ expect('[');
+ expect(']');
+ if (dp->op == 255)
+ error("too much declarators");
+ dp->u.nelem = 0;
+ dp->op = ARY;
+ return dp + 1;
+}
+
+static struct dcldata *
+fundcl(struct dcldata *dp)
+{
+ expect('(');
+ expect(')');;
+ if (dp->op == 255)
+ error("too much declarators");
+ dp->op = FTN;
+ dp->u.pars = NULL;
+ return dp + 1;
+}
+
+static struct dcldata*
+directdcl(struct dcldata *dp, uint8_t ns, int8_t flags)
{
register struct symbol *sym;
- register char *err;
+ char *err;
if (accept('(')) {
- sym = declarator(tp, ns, isfun);
+ dp = declarator0(dp, ns, flags);
expect(')');
- } else if (ns != NS_TYPE) {
- if (yytoken == IDEN) {
+ } else if (flags) {
+ if (yytoken != IDEN) {
+ if (flags > 0)
+ goto expected;
+ sym = install(NULL, ns);
+ } else {
sym = lookup(yytext, ns);
- if (!sym->ctype.type)
- sym->ctx = curctx;
- else if (sym->ctx == curctx)
+ if (sym && sym->ctx == curctx)
goto redeclared;
+ sym = install(yytext, ns);
next();
- } else if (!isfun) {
- goto expected;
}
+ dp->op = IDEN;
+ dp->u.sym = sym;
+ ++dp;
}
for (;;) {
- if (accept('(')) {
- pushtype(FTN);
- if (yytoken != ')')
- ; /* TODO: prototyped function */;
- expect(')');
- } else if (accept('[')) {
- unsigned len = '0';
-
- if (yytoken != ']') {
- expect(CONSTANT);
- len = yyval->i;
- }
- expect(']');
- pushtype(len);
- pushtype(ARY);
- } else {
- return sym;
+ switch (yytoken) {
+ case '(': dp = fundcl(dp); break;
+ case '[': dp = arydcl(dp); break;
+ default: return dp;
}
}
@@ -72,459 +90,272 @@ expected:
error: error(err, yytext);
}
-struct ctype *
-ctype(struct ctype *tp, unsigned char tok)
+static struct dcldata*
+declarator0(struct dcldata *dp, uint8_t ns, int8_t flags)
{
- register unsigned char type;
- static char *err;
-
- type = tp->type;
+ if (accept('*')) {
+ register uint8_t qlf = 0;
+ while (yytoken == TQUALIFIER) {
+ qlf |= yylval.sym->u.c;
+ next();
+ }
+ dp = declarator0(dp, ns, flags);
+ if (dp->op == 255)
+ error("too much declarators");
+ dp->op = PTR;
+ dp->u.qlf = qlf;
+ return dp + 1;
+ } else {
+ return directdcl(dp, ns, TQUALIFIER);
+ }
+}
+static struct symbol *
+declarator(struct ctype *tp, uint8_t ns, int8_t flags)
+{
+ struct dcldata data[NR_DECLARATORS+1];
+ register struct dcldata *bp;
+ struct symbol *sym;
- switch (tok) {
- case VOID: case BOOL: case STRUCT: case UNION: case ENUM: case BITFLD:
- if (type)
- goto two_or_more;;
- type = tok;
- if (tp->c_signed || tp->c_unsigned)
- goto invalid_sign;
- break;
- case CHAR:
- if (type)
- goto two_or_more;
- type = CHAR;
- break;
- case SHORT:
- if (type && type != INT)
- goto two_or_more;
- type = SHORT;
- break;
- case INT:
- switch (type) {
- case 0: type = INT; break;
- case SHORT: type = SHORT; break;
- case LONG: type = LONG; break;
- default: goto two_or_more;
- }
- break;
- case LONG:
- switch (type) {
- case 0:
- case INT: type = LONG; break;
- case LONG: type = LLONG; break;
- case DOUBLE: type = LDOUBLE; break;
- case LLONG:
- case LDOUBLE: error("too much long");
- }
- break;
- case FLOAT:
- if (type)
- goto two_or_more;
- type = FLOAT;
- if (tp->c_signed || tp->c_unsigned)
- goto invalid_sign;
- break;
- case DOUBLE:
- if (type)
- goto two_or_more;
- if (!type)
- type = DOUBLE;
- else if (type == LONG)
- type = LDOUBLE;
- if (tp->c_signed || tp->c_unsigned)
- goto invalid_sign;
- break;
- case UNSIGNED:
- if (tp->c_unsigned)
- goto duplicated;
- if (tp->c_signed)
- goto both_sign;
- tp->c_unsigned = 1;
- goto check_sign;
- case SIGNED:
- if (tp->c_signed)
- goto duplicated;
- if (tp->c_unsigned)
- goto both_sign;
- tp->c_signed = 1;
-
-check_sign: switch (type) {
- case VOID: case BOOL: case FLOAT: case DOUBLE: case LDOUBLE:
- goto invalid_sign;
+ data[NR_DECLARATORS].op = 255;
+ for (bp = declarator0(data, ns, flags); bp >= data; --bp) {
+ switch (bp->op) {
+ case PTR:
+ tp = qualifier(mktype(tp, PTR, NULL, 0), bp->u.qlf);
+ break;
+ case ARY:
+ tp = mktype(tp, ARY, NULL, bp->u.nelem);
+ break;
+ case FTN:
+ tp = mktype(tp, FTN, NULL, 0);
+ break;
+ case IDEN:
+ sym = bp->u.sym;
+ break;
}
- break;
- case TYPENAME:
- assert(!type);
- if (tp->c_signed || tp->c_unsigned)
- goto invalid_sign;
- type = TYPEDEF;
- break;
- default:
- assert(0);
}
- tp->type = type;
- return tp;
-
-both_sign:
- err = "both 'signed' and 'unsigned' in declaration specifiers";
- goto error;
-duplicated:
- err = "duplicated '%s'";
- goto error;
-invalid_sign:
- err = "invalid sign modifier";
- goto error;
-two_or_more:
- err = "two or more basic types";
-error: error(err, yytext);
+ sym->type = tp;
+ return sym;
}
-static void structdcl(register struct ctype *tp);
-static void enumdcl(struct ctype *base);
+static struct ctype *structdcl(void), *enumdcl(void);
-static void
-specifier(register struct ctype *tp, char *store, char *qlf)
+static struct ctype *
+specifier(int8_t *sclass)
{
- unsigned char tok;
+ struct ctype *tp = NULL;
+ int8_t qlf, sign, type, cls, cplex, size;
+
+ qlf = sign = type = cls = size = cplex = 0;
+
+ for (;;) {
+ register uint8_t *p;
+ struct symbol *sym = yylval.sym;
- for (;; next()) {
switch (yytoken) {
+ case SCLASS: p = &cls; break;
case TQUALIFIER:
- if (*qlf && !options.repeat)
- error("duplicated '%s'", yytext);
- if (yyval->c == RESTRICT)
- error("invalid use of restrict");
- *qlf |= yyval->c;
- break;
- case STORAGE:
- if (*store)
- error("two or more storage specifier");
- /* TODO: check bad storage in file-scope */
- *store |= yyval->c;
- break;
+ if ((qlf |= sym->u.c) & RESTRICT)
+ goto invalid_type;
+ goto next_token;
case TYPE:
- tp = ctype(tp, tok = yyval->c);
- switch (tok) {
- case ENUM: case STRUCT: case UNION:
- next();
- if (tok == ENUM)
- enumdcl(tp);
- else
- structdcl(tp);
- return;
+ switch (sym->u.c) {
+ case ENUM:
+ tp = enumdcl(); goto set_type;
+ case STRUCT: case UNION:
+ tp = structdcl(); goto set_type;
case TYPENAME:
- tp->base = &yyval->ctype;
- break;
+ tp = yylval.sym->type;
+ case VOID: case BOOL: case CHAR:
+ case INT: case FLOAT: case DOUBLE:
+set_type: p = &type; break;
+ case SIGNED: case UNSIGNED:
+ p = &sign; break;
+ case LONG:
+ if (size == LONG) {
+ size = LONG+LONG;
+ goto next_token;
+ }
+ case SHORT:
+ p = &size; break;
+ case COMPLEX: case IMAGINARY:
+ p = &cplex; break;
}
break;
default:
- goto check_type;
+ goto check_types;
}
+ if (*p)
+ goto invalid_type;
+ *p = sym->u.c;
+next_token: next();
}
-check_type:
- if (!tp->c_signed && !tp->c_unsigned) {
- switch (tp->type) {
- case CHAR:
- if (!options.charsign) {
- case BOOL: tp->c_unsigned = 1;
- break;
- }
- case INT: case SHORT: case LONG: case LLONG:
- tp->c_signed = 1;
+check_types:
+ if (!type) {
+ if (!sign && !size) {
+ warn(options.implicit,
+ "type defaults to 'int' in declaration");
}
- } else if (!tp->type) {
- tp->type = INT;
+ type = INT;
}
- return;
-}
-
-static struct symbol *
-declarator(struct ctype *tp, unsigned char ns, unsigned char isfun)
-{
- unsigned char qlf[NR_DECLARATORS];
- register unsigned char *bp;
- register unsigned char n = 0;
- struct symbol *sym;
-
- if (yytoken == '*') {
- for (bp = qlf; n < NR_DECLARATORS ; ++n) {
- if (yytoken == '*')
- *bp++ = PTR;
- else if (yytoken == TQUALIFIER)
- *bp++ = yyval->c;
- else
- goto direct;
- }
- error("Too much type declarators");
+ if (sign && type != INT && type != CHAR ||
+ cplex && type != FLOAT && type != DOUBLE ||
+ size == SHORT && type != INT ||
+ size == LONG && type != INT && type != DOUBLE ||
+ size == LONG+LONG && type != INT) {
+ goto invalid_type;
}
-
-direct: sym = directdcl(tp, ns, isfun);
-
- for (bp = qlf; n--; pushtype(*bp++))
- /* nothing */;
- return sym;
+ if (sclass)
+ *sclass = cls;
+ if (!tp)
+ tp = ctype(type, sign, size, cplex);
+ return (qlf) ? qualifier(tp, qlf) : tp;
+
+invalid_type:
+ error("invalid type specification");
}
static struct node *
initializer(register struct ctype *tp)
{
if (accept('{')) {
- struct compound c;
-
- c.tree = NULL;
- addstmt(&c, initializer(tp));
- while (accept(',')) {
- if (accept('}'))
- return c.tree;
- addstmt(&c, initializer(tp));
- }
+ initializer(tp);
expect('}');
- return c.tree;
} else {
- return expr();
+ do {
+ expr();
+ } while (accept(','));
}
}
-static struct node *
-listdcl(struct ctype *base,
- char store, char qlf,
- unsigned char ns, unsigned char isfun)
+static struct ctype *
+structdcl(void)
{
- struct compound c;
- char *err;
-
- c.tree = NULL;
-
- if (yytoken == ';')
- return NULL;
-
- do {
- struct node *np, *aux;
- register struct ctype *tp;
- register struct symbol *sym;
+ uint8_t type = yylval.sym->u.c;
- sym = declarator(base, ns, isfun);
- sym->store = store;
- sym->qlf = qlf;
- sym->ctype = *decl_type(base);
- if (sym->store) {
- sym->tok = TYPE;
- sym->c = TYPENAME;
- }
- tp = &sym->ctype;
- aux = NULL;
-
- switch (tp->type) {
- case FTN:
- if (ns != NS_IDEN)
- goto bad_type;
- if (yytoken == '{') {
- if (curctx != CTX_OUTER)
- goto local_fun;
- aux = function(sym);
- addstmt(&c, node(ODEF, nodesym(sym), aux));
- return c.tree;
- }
- goto add_stmt;
- case INT: case BOOL:
- if (ns != NS_IDEN && accept(':')) {
- expect(CONSTANT);
- tp = ctype(NULL, BITFLD);
- tp->len = yyval->i;
- goto add_stmt;
- }
- goto add_init;
- case STRUCT: case UNION:
- if (tp->forward)
- goto incomplete;
- default:
- add_init:
- if (ns == NS_IDEN) {
- if (accept('='))
- aux = initializer(tp);
- }
- add_stmt:
- addstmt(&c, node(ODEF, nodesym(sym), aux));
- }
- } while (accept(','));
-
- return c.tree;
-
-bad_type:
- err = "incorrect type for field";
- goto error;
-local_fun:
- err = "cannot use local functions";
- goto error;
-incomplete:
- err = "declaration of variable with incomplete type";
-error: error(err);
+ next();
+ if (yytoken == IDEN) {
+ }
+ return NULL;
}
-static unsigned char
-newtag(unsigned char type)
+static struct ctype *
+enumdcl(void)
{
- if (type == ENUM)
- return 0;
- if (nr_tags == NS_TAG + NR_MAXSTRUCTS)
- error("too much structs/unions defined");
- return ++nr_tags;
+ return NULL;
}
-static struct symbol *
-aggregate(register struct ctype *tp)
+struct node *
+decl(void)
{
- struct symbol *sym = NULL;
-
- tp->forward = 1;
- if (yytoken == IDEN) {
- register struct ctype *aux;
-
- sym = lookup(yytext, NS_TAG);
- aux = &sym->ctype;
- if (aux->type) {
- if (aux->type != tp->type)
- goto bad_type;
- *tp = *aux;
- } else {
- tp->tag = sym->name;
- tp->ns = newtag(tp->type);
- sym->ctype = *tp;
- }
- next();
- } else {
- tp->ns = newtag(tp->type);
+ struct ctype *tp;
+ struct symbol *sym;
+ int8_t sclass;
+
+ tp = specifier(&sclass);
+ if (yytoken != ';') {
+ do {
+ sym = declarator(tp, NS_IDEN, 1);
+ /* assign storage class */
+ if (accept('='))
+ initializer(sym->type);
+ } while (accept(','));
}
- return sym;
-
-bad_type:
- error("'%s' defined as wrong kind of tag", yytext);
+ expect(';');
+ return NULL;
}
-static void
-structdcl(register struct ctype *tp)
+static struct symbol *
+fielddcl(void)
{
+ struct ctype *tp;
struct symbol *sym;
- sym = aggregate(tp);
-
- if (!accept('{'))
- return;
-
- if (sym && !sym->ctype.forward)
- error("struct/union already defined");
-
- if (nested_tags == NR_STRUCT_LEVEL)
- error("too much nested structs/unions");
-
- ++nested_tags;
- while (!accept('}')) {
- struct ctype base;
- struct node *np;
- char store = 0, qlf = 0;
-
- initctype(&base);
- specifier(&base, &store, &qlf);
-
- if (store)
- error("storage specifier in a struct/union field declaration");
-
- listdcl(&base, store, qlf, tp->ns, 0);
- expect(';');
+ 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");
}
- --nested_tags;
- if (sym)
- sym->ctype.forward = 0;
- tp->forward = 0;
-}
-
-static void
-enumdcl(struct ctype *base)
-{
- static int val;
-
- aggregate(base);
- if (!accept('{'))
- return;
- val = 0;
-
- do {
- register struct symbol *sym;
- register struct ctype *tp;
-
- if (yytoken != IDEN)
- break;
- sym = lookup(yytext, NS_IDEN);
- tp = &sym->ctype;
- if (tp->type && sym->ctx == curctx)
- error("'%s' redefined", yytext);
- next();
- if (accept('=')) {
- expect(CONSTANT);
- val = yyval->i;
- }
- ctype(tp, INT);
- tp->base = base;
- sym->i = val++;
- } while (accept(','));
-
- expect('}');
-}
-
-struct node *
-decl(unsigned char ns)
-{
- struct ctype base;
- struct node *np;
- char store = 0, qlf = 0;
-
- initctype(&base);
- specifier(&base, &store, &qlf);
-
- if (store && ns != NS_IDEN)
- error("storage specifier in a struct/union field declaration");
+ if (yytoken != ';') {
+ do {
+ sym = declarator(tp, 0, 1);
+ if (accept(':'))
+ ; /* TODO: bitfields */
+ /* TODO: add to the aggregate */
+ } while (accept(','));
+ }
- np = listdcl(&base, store, qlf, ns, 0);
expect(';');
- return np;
+ return NULL;
}
-void
-type_name(struct ctype *tp)
+struct node *
+typename(void)
{
- char store = 0, qlf = 0;
-
- initctype(tp);
- specifier(tp, &store, &qlf);
- declarator(tp, NS_TYPE, 0);
- return;
+ declarator(specifier(NULL), NS_IDEN, -1)->type;
+ return NULL;
}
struct node *
extdecl(void)
{
- struct ctype base;
- struct node *np;
- char store = 0, qlf = 0;
+ struct ctype *tp;
+ int8_t sclass;
+ struct symbol *sym;
+ extern struct symbol *curfun;
- initctype(&base);
+ forbid_eof = 1;
switch (yytoken) {
case IDEN:
warn(options.implicit,
"type defaults to 'int' in declaration");
- base.type = INT;
+ tp = inttype;
+ break;
+ case TYPE: case SCLASS: case TQUALIFIER:
+ tp = specifier(&sclass);
+ if (sclass == REGISTER || sclass == AUTO)
+ error("incorrect storage class for file-scope declaration");
break;
- case TYPE: case STORAGE: case TQUALIFIER:
- specifier(&base, &store, &qlf);
+ case ';':
break;
default:
error("declaration expected");
}
- np = listdcl(&base, store, qlf, 0, 0);
+ if (yytoken != ';') {
+ do {
+ extern void printtype(struct ctype *tp);
+ sym = declarator(tp, NS_IDEN, 1);
+ printtype(sym->type);
+ /* assign storage class */
+ if (isfun(sym)) {
+ if (yytoken == '{') {
+ curfun = sym;
+ context(function);
+ freesyms(NS_LABEL);
+ }
+ } else if (accept('=')) {
+ initializer(sym->type);
+ }
+ } while (accept(','));
+ }
+
+ forbid_eof = 0;
expect(';');
-}
-\ No newline at end of file
+ return NULL;
+}
diff --git a/expr.c b/expr.c
@@ -1,4 +1,5 @@
#include <stddef.h>
+#include <stdint.h>
#include <stdio.h>
#include "cc.h"
@@ -17,14 +18,12 @@ primary(void)
switch (yytoken) {
case IDEN:
- sym = lookup(yytext, NS_IDEN);
- if (!sym->ctype.type)
+ if ((sym = lookup(yytext, NS_IDEN)) == NULL)
error("'%s' undeclared", yytext);
next();
np = nodesym(sym);
break;
case CONSTANT:
- sym = yyval;
next();
np = nodesym(sym);
break;
@@ -92,10 +91,9 @@ unary(void)
case SIZEOF: /* TODO: Implement sizeof */
next();
if (accept('(')) {
- struct ctype type;
switch (yytoken) {
- case STORAGE: case TQUALIFIER: case TYPE:
- type_name(&type);
+ case TQUALIFIER: case TYPE:
+ context(typename);
break;
default:
expr();
@@ -129,13 +127,12 @@ call_unary:
static struct node *
cast(void)
{
- struct ctype type;
-
repeat: if (yytoken == '(') {
switch (ahead()) {
- case STORAGE: case TQUALIFIER: case TYPE:
+ case TQUALIFIER: case TYPE:
next();
- type_name(&type); /* TODO: type_name should return a np*/
+ /* TODO: type_name should return a np*/
+ context(typename);
expect(')');
goto repeat;
default:
diff --git a/flow.c b/flow.c
@@ -1,5 +1,6 @@
#include <assert.h>
+#include <stdint.h>
#include <stdio.h>
#include "cc.h"
@@ -13,7 +14,7 @@ static struct node *stmt(void);
static unsigned char blocks[NR_BLOCK];
static unsigned char *blockp = blocks;
-static struct symbol *curfun;
+struct symbol *curfun;
static void
push(register unsigned char b)
@@ -139,10 +140,8 @@ label(void)
{
register struct symbol *sym = lookup(yytext, NS_LABEL);
- if (sym->label)
- error("label '%s' already defined", yytext);
- insert(sym, CTX_FUNC);
- sym->label = 1;
+ /* TODO: detect repeated labels */
+ /* TODO: install in symbol table */
next(), next(); /* skip IDEN and ':' */
return node(OLABEL, nodesym(sym), stmt());
}
@@ -221,28 +220,19 @@ Default(void)
static struct node *
compound(void)
{
- register struct node *np;
- unsigned char nodecl = 0;
- struct compound c;
-
- c.tree = NULL;
expect('{');
- new_ctx();
- while (!accept('}')) {
- if (np = decl(0)) {
- if (nodecl) {
- warn(options.mixdcls,
- "mixed declarations and code");
- }
- } else {
- np = stmt();
- nodecl = 1;
- }
- addstmt(&c, np);
- }
- del_ctx();
- return c.tree;
+repeat: switch (yytoken) {
+ case TYPE: case SCLASS: case TQUALIFIER:
+ decl();
+ goto repeat;
+ case '}':
+ next();
+ return NULL;
+ default:
+ stmt();
+ goto repeat;
+ }
}
static struct node *
@@ -251,7 +241,7 @@ stmt(void)
register struct node *np;
switch (yytoken) {
- case '{': return compound();
+ case '{': return context(compound);
case SWITCH: return Switch();
case IF: return If();
case FOR: return For();
@@ -271,16 +261,8 @@ stmt(void)
}
struct node *
-function(register struct symbol *sym)
+function(void)
{
- curfun = sym;
return node(OFTN, compound(), NULL);
}
-void
-run(register struct node *np)
-{
- prtree(np);
- putchar('\n');
- freesyms();
-}
diff --git a/lex.c b/lex.c
@@ -1,4 +1,5 @@
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -9,70 +10,39 @@
#include "symbol.h"
#include "sizes.h"
-unsigned char yytoken;
-char yytext[IDENTSIZ + 1];
-static char yybuf[IDENTSIZ + 1];
+static FILE *yyin;
+const char *filename;
unsigned linenum;
unsigned columnum;
-const char *filename;
-struct keyword {
- char *str;
- unsigned char tok;
- unsigned char value;
-};
+uint8_t yytoken, yyntoken;;
+union yystype yylval;
+char yytext[IDENTSIZ + 1];
-static FILE *yyin;
-static struct symbol yysym = {.name = ""}, *yynval = &yysym;
-struct symbol *yyval = &yysym;
+static union yystype yynlval;
+static char yybuf[IDENTSIZ + 1];
-struct symbol *
+static uint8_t
integer(char *s, char base)
{
static struct ctype *tp;
- register struct symbol *sym;
- static long long v;
static char ch;
- tp = initctype(xmalloc(sizeof(*tp)));
+ /* TODO: implement again */
type: switch (ch = toupper(getc(yyin))) {
case 'L':
- tp = ctype(tp, LONG);
goto type;
case 'U':
- tp = ctype(tp, UNSIGNED);
goto type;
default:
ungetc(ch, yyin);
}
- v = strtoll(s, NULL, base);
- sym = lookup(NULL, NS_IDEN);
- sym->tok = CONSTANT;
- sym->ctype = *tp;
-
- switch (tp->type) {
- case INT:
- sym->i = v;
- break;
- case SHORT:
- sym->s = v;
- break;
- case LONG:
- sym->l = xmalloc(sizeof(long));
- *sym->l = v;
- break;
- case LLONG:
- sym->ll = xmalloc(sizeof(long long));
- *sym->ll = v;
- break;
- }
-
- return sym;
+ return CONSTANT;
}
-static struct symbol *
+static uint8_t
number(void)
{
register char *bp, ch;
@@ -118,8 +88,11 @@ end: if (bp == &yybuf[IDENTSIZ])
void
init_keywords(void)
{
- static struct keyword buff[] = {
- {"auto", STORAGE, AUTO},
+ static struct {
+ char *str;
+ uint8_t token, value;
+ } *bp, buff[] = {
+ {"auto", SCLASS, AUTO},
{"break", BREAK, BREAK},
{"_Bool", TYPE, BOOL},
{"_Complex", TYPE, COMPLEX},
@@ -132,7 +105,7 @@ init_keywords(void)
{"double", TYPE, DOUBLE},
{"else", ELSE, ELSE},
{"enum", TYPE, ENUM},
- {"extern", STORAGE, EXTERN},
+ {"extern", SCLASS, EXTERN},
{"float", TYPE, FLOAT},
{"for", FOR, FOR},
{"goto", GOTO, GOTO},
@@ -140,16 +113,16 @@ init_keywords(void)
{"int", TYPE, INT},
{"_Imaginary", TYPE, IMAGINARY},
{"long", TYPE, LONG},
- {"register", STORAGE, REGISTER},
+ {"register", SCLASS, REGISTER},
{"restrict", TQUALIFIER, RESTRICT},
{"return", RETURN, RETURN},
{"short", TYPE, SHORT},
{"signed", TYPE, SIGNED},
{"sizeof", SIZEOF, SIZEOF},
- {"static", STORAGE, STATIC},
+ {"static", SCLASS, STATIC},
{"struct", TYPE, STRUCT},
{"switch", SWITCH, SWITCH},
- {"typedef", STORAGE, TYPEDEF},
+ {"typedef", SCLASS, TYPEDEF},
{"union", TYPE, UNION},
{"unsigned", TYPE, UNSIGNED},
{"void", TYPE, VOID},
@@ -157,61 +130,38 @@ init_keywords(void)
{"while", WHILE, WHILE},
{NULL, 0, 0},
};
- register struct keyword *bp;
register struct symbol *sym;
- for (bp = buff; bp->str; ++bp) {
- sym = lookup(bp->str, NS_IDEN);
- sym->tok = bp->tok;
- sym->c = bp->value;
+ for (bp = buff; bp->str; ++bp) {
+ sym = install(bp->str, NS_KEYWORD);
+ sym->token = bp->token;
+ sym->u.c = bp->value;
}
}
-static struct symbol *
+static uint8_t
iden(void)
{
- register char ch, *bp;
+ register char *bp;
+ register int c;
- for (bp = yybuf; bp < &yybuf[IDENTSIZ]; *bp++ = ch) {
- if (!isalnum(ch = getc(yyin)) && ch != '_')
+ for (bp = yybuf; bp < &yybuf[IDENTSIZ]; *bp++ = c) {
+ if (!isalnum(c = getc(yyin)) && c != '_')
break;
}
if (bp == &yybuf[IDENTSIZ])
error("identifier too long %s", yybuf);
*bp = '\0';
- ungetc(ch, yyin);
-
- return lookup(yybuf, NS_IDEN);
-}
-
-static unsigned char
-skip(void)
-{
- static int c;
- extern char parser_out_home;
-
- if (c != EOF) {
- while (c != EOF && isspace(c = getc(yyin))) {
- switch (c) {
- case '\n': ++linenum, columnum = 1; break;
- case '\t': columnum += 8; break;
- default: ++columnum; break;
- }
- }
- }
- if (c == EOF) {
- if (parser_out_home)
- error("Find EOF while parsing");
- return 0;
- }
ungetc(c, yyin);
- return 1;
+
+ yynlval.sym = lookup(yybuf, NS_IDEN);
+ return (yynlval.sym) ? yynlval.sym->token : IDEN;
}
-static unsigned char
-follow(unsigned char op, unsigned char eq, unsigned char rep)
+static uint8_t
+follow(uint8_t op, uint8_t eq, uint8_t rep)
{
- register char c = getc(yyin);
+ register int c = getc(yyin);
yybuf[1] = c;
yybuf[2] = '\0';
@@ -225,14 +175,14 @@ follow(unsigned char op, unsigned char eq, unsigned char rep)
return op;
}
-static unsigned char
-rel_shift(unsigned char op)
+static uint8_t
+rel_shift(uint8_t op)
{
- static char tokens[2][3] = {
+ static uint8_t tokens[2][3] = {
{GE, SHL, SHL_EQ},
{LE, SHR, SHR_EQ}
};
- register char c = getc(yyin);
+ register int c = getc(yyin);
register char *tp = tokens[op == '>'];
yybuf[1] = c;
@@ -253,7 +203,7 @@ rel_shift(unsigned char op)
return op;
}
-static unsigned char
+static uint8_t
minus(void)
{
register int c = getc(yyin);
@@ -270,10 +220,10 @@ minus(void)
}
}
-static unsigned char
+static uint8_t
operator(void)
{
- register unsigned char c = getc(yyin);
+ register uint8_t c = getc(yyin);
yybuf[0] = c;
yybuf[1] = '\0';
@@ -292,47 +242,46 @@ operator(void)
}
}
-void
+uint8_t
next(void)
{
- register unsigned char c;
+ static int c;
+ extern int8_t forbid_eof;
strcpy(yytext, yybuf);
- yyval = yynval;
- yytoken = yynval->tok;
- yynval = &yysym;
-
- if (!skip()) {
- yysym.tok = EOFTOK;
- } else {
- ungetc(c = getc(yyin), yyin);
- if (isalpha(c) || c == '_')
- yynval = iden();
- else if (isdigit(c))
- yynval = number();
- else
- yysym.tok = operator();
+ yylval = yynlval;
+ if ((yytoken = yyntoken) == EOFTOK) {
+ if (forbid_eof)
+ error("Find EOF while parsing");
+ goto ret;
}
-}
-unsigned char
-ahead(void)
-{
- return yynval->tok;
-}
+ while (isspace(c = getc(yyin))) {
+ switch (c) {
+ case '\n': ++linenum, columnum = 1; break;
+ case '\t': columnum += 8; break;
+ default: ++columnum; break;
+ }
+ }
-char
-accept(register unsigned char tok)
-{
- if (yytoken == tok) {
- next();
- return 1;
+ if (c == EOF) {
+ yyntoken = EOFTOK;
+ goto ret;
}
- return 0;
+
+ ungetc(c, yyin);
+ if (isalpha(c) || c == '_')
+ yyntoken = iden();
+ else if (isdigit(c))
+ yyntoken = number();
+ else
+ yyntoken = operator();
+
+ret: return yytoken;
}
void
-expect(register unsigned char tok)
+expect(register uint8_t tok)
{
if (yytoken != tok)
error("unexpected %s", yytext);
diff --git a/main.c b/main.c
@@ -1,25 +1,21 @@
#include <stddef.h>
+#include <stdint.h>
#include "cc.h"
#include "tokens.h"
#include "syntax.h"
extern void open_file(const char *file);
-extern void run(struct node *np);
struct user_opt options;
-
-
int
main(int argc, char *argv[])
{
- struct node *np;
-
init_keywords();
open_file(NULL);
- for (next(); yytoken != EOFTOK; run(np))
- np = extdecl();
+ for (next(); yytoken != EOFTOK; extdecl());
+ /* nothing */;
return 0;
}
diff --git a/symbol.c b/symbol.c
@@ -1,5 +1,6 @@
-#include <assert.h>
+#include <stdint.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -9,117 +10,100 @@
#define NR_SYM_HASH 32
-unsigned char curctx;
+uint8_t curctx;
+uint8_t namespace = NS_KEYWORD + 1 ;
-static struct symbol *htab[NR_SYM_HASH];
-static struct symbol *head, *headfun;
+static struct symtab {
+ struct symbol *head;
+ struct symbol *htab[NR_SYM_HASH];
+} symtab [NR_NAMESPACES];
-
-unsigned char
+static inline uint8_t
hash(register const char *s)
{
- register unsigned char h, ch;
+ register uint8_t h, ch;
for (h = 0; ch = *s++; h += ch)
/* nothing */;
- return h;
-}
-
-void
-new_ctx(void)
-{
- ++curctx;
+ return h & NR_SYM_HASH - 1;
}
void
-del_ctx(void)
+freesyms(uint8_t ns)
{
- register struct symbol *sym, *next;
- static char *s;
+ static struct symtab *tbl;
+ register struct symbol *sym;
- for (sym = head; sym; sym = next) {
+ tbl = &symtab[ns];
+ for (sym = tbl->head; sym; sym = sym->next) {
if (sym->ctx <= curctx)
break;
- if ((s = sym->name) != NULL)
- htab[hash(s) & NR_SYM_HASH - 1] = sym->hash;
- next = sym->next;
- sym->next = headfun;
- headfun = sym;
+ tbl->htab[hash(sym->name)] = sym->hash;
+ free(sym->name);
+ free(sym);
}
- --curctx;
}
-void
-freesyms(void)
+struct node *
+context(struct node * (*fun)(void))
{
- register struct symbol *sym, *next;
-
- if (curctx == CTX_OUTER) {
- for (sym = headfun; sym; sym = next) {
- next = sym->next;
- free(sym->name);
- free(sym);
- }
- }
+ uint8_t ns;
+ struct node *np;
+
+ ns = namespace;
+ ++curctx;
+ np = fun();
+ --curctx;
+ namespace = ns;
+
+ freesyms(NS_IDEN);
+ freesyms(NS_TAG);
+
+ return np;
}
struct symbol *
-lookup(register const char *s, unsigned char ns)
+lookup(register char *s, uint8_t ns)
{
+ extern union yystype yylval;
+ static struct symtab *tbl;
register struct symbol *sym;
- extern struct symbol *yyval;
- static unsigned char key;
- register char *t;
- if (s == NULL) {
- sym = xcalloc(1, sizeof(*sym));
- sym->next = head;
+ if (ns == NS_IDEN && (sym = yylval.sym) && !strcmp(sym->name, s))
return sym;
- }
- if (yyval->ns == ns && !strcmp(yyval->name, s))
- return yyval;
- key = hash(s) & NR_SYM_HASH - 1;
- for (sym = htab[key]; sym; sym = sym->hash) {
- t = sym->name;
- if (ns == sym->ns && *t == *s && !strcmp(t, s))
+ tbl = &symtab[(ns >= NR_NAMESPACES) ? NS_IDEN : ns];
+ for (sym = tbl->htab[hash(s)]; sym; sym = sym->hash) {
+ register char *t = sym->name;
+ if (sym->ns == ns && t && *t == *s && !strcmp(t, s))
return sym;
}
- sym = xcalloc(1, sizeof(*sym));
- sym->name = xstrdup(s);
- sym->next = head;
- sym->ctx = curctx;
- sym->ns = ns;
- sym->tok = IDEN;
- head = sym;
- sym->hash = htab[key];
- htab[key] = sym;
-
- return sym;
+ return NULL;
}
-void
-insert(struct symbol *sym, unsigned char ctx)
+struct symbol *
+install(char *s, uint8_t ns)
{
- register struct symbol *p, *q;
+ register struct symbol *sym;
+ register struct symbol **t;
+ struct symtab *tbl;
- for (q = p = head; p; q = p, p = p->next) {
- if (p == sym)
- break;
- }
- assert(p); /* sym must be in the list */
- q->next = p->next; /* remove from the list */
+ if (ns == NS_KEYWORD)
+ ns = NS_IDEN;
+ else if (s != NULL)
+ s = xstrdup(s);
- for (q = p = head; p; q = p, p = p->next) {
- if (p->ctx <= ctx)
- break;
- }
- if (q == NULL) {
- head = sym;
- sym->next = NULL;
- } else {
- q->next = sym;
- sym->next = p;
- }
+ sym = xcalloc(1, sizeof(*sym));
+ sym->name = s;
+ sym->ctx = curctx;
+ sym->token = IDEN;
+ 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;
+
+ return sym;
}
diff --git a/symbol.h b/symbol.h
@@ -1,80 +1,77 @@
-#pragma once
#ifndef SYMBOL_H
#define SYMBOL_H
-#if ! __bool_true_false_are_defined
-# include <stdbool.h>
-#endif
-
#define CTX_OUTER 0
#define CTX_FUNC 1
+#define isfun(t) 0
+
enum {
NS_IDEN = 0,
- NS_TYPE,
NS_LABEL,
- NS_TAG
+ NS_TAG,
+ NR_NAMESPACES,
+ NS_KEYWORD,
+ NS_FREE
};
+struct funpars;
+struct symbol;
struct ctype {
- unsigned type : 5;
- bool c_const : 1;
- bool c_restrict : 1;
- bool c_volatile : 1;
- bool c_unsigned : 1;
- bool c_signed : 1;
- bool forward : 1;
- union {
- struct {
- unsigned char ns;
- char *tag;
- };
- unsigned len;
- };
- struct ctype *base;
+ 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 cplex : 1; /* complex specifier */
+ unsigned imag : 1;
+ 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 */
+ struct funpars *pars; /* function parameters */
+};
+
+struct funpars {
+ struct ctype *type;
+ struct funpars *next;
};
struct symbol {
- struct ctype ctype;
- char store;
- char qlf;
- unsigned char ctx;
- unsigned char ns;
char *name;
- unsigned char tok;
- struct {
- union {
- char c; /* numerical constants */
- short s;
- int i;
- long *l;
- long long *ll;
- unsigned char label;
- };
- };
+ struct ctype *type;
+ uint8_t ctx;
+ uint8_t token;
+ uint8_t ns;
+ union {
+ char c;
+ } u;
struct symbol *next;
struct symbol *hash;
};
+extern void freesyms(uint8_t ns);
-extern struct ctype *decl_type(struct ctype *t);
-extern void pushtype(unsigned mod);
-extern struct ctype *ctype(struct ctype *tp, unsigned char tok);
-extern void new_ctx(void);
-extern void del_ctx(void);
-extern void freesyms(void);
-extern struct symbol *lookup(const char *s, unsigned char ns);
-extern void insert(struct symbol *sym, unsigned char ctx);
-extern void delctype(struct ctype *tp);
-extern unsigned char hash(register const char *s);
-extern struct ctype *initctype(register struct ctype *tp);
+extern struct ctype *qualifier(struct ctype *tp, uint8_t qlf),
+ *ctype(int8_t type, int8_t sign, int8_t size, int8_t cplex),
+ *mktype(struct ctype *tp,
+ uint8_t op, struct symbol *tag, uint16_t nelem);
-#ifndef NDEBUG
-extern void ptype(register struct ctype *t);
-#else
-# define ptype(t)
-#endif
+extern struct symbol
+ *lookup(char *s, unsigned char ns),
+ *install(char *s, unsigned char ns);
+
+extern struct node *context(struct node * (*fun)(void));
+
+extern struct ctype *voidtype,
+ *uchartype, *chartype,
+ *uinttype, *inttype,
+ *ushortype, *shortype,
+ *longtype, *ulongtype,
+ *ullongtype, *llongtype,
+ *floattype, *cfloattype, *ifloattype,
+ *doubletype, *cdoubletype, *idoubletype,
+ *ldoubletype, *cldoubletype,*ildoubletype;
#endif
diff --git a/syntax.h b/syntax.h
@@ -28,11 +28,8 @@ struct compound {
struct node_op2 *last;
};
-extern struct node *expr(void);
-extern struct node *extdecl(void);
-extern struct node *decl(unsigned char ns);
-extern void type_name(struct ctype *tp);
-extern struct node *function(struct symbol *sym);
+extern struct node *expr(void), *extdecl(void), *decl(void),
+ *typename(void), *function(void);
extern struct node *node(unsigned char op, struct node *l, struct node *r);
extern struct node *nodesym(struct symbol *sym);
diff --git a/tokens.h b/tokens.h
@@ -5,21 +5,47 @@
# include <stdbool.h>
#endif
+#define FLOAT 1
+#define INT 2
+#define BOOL 3
+#define PTR 4
+#define ARY 5
+#define FTN 6
+
+#define VOID 7
+#define STRUCT 8
+#define UNION 9
+#define ENUM 10
+#define TYPENAME 11
+
+#define CHAR 12
+#define DOUBLE 13
+#define SHORT 14
+#define LONG 15
+
+#define COMPLEX 16
+#define IMAGINARY 17
+#define UNSIGNED 18
+#define SIGNED 19
+
+#define BITFLD 20
+
+#define CONST (1<<0)
+#define VOLATILE (1<<1)
+#define RESTRICT (1<<2)
+
+#define TYPEDEF 1
+#define EXTERN 2
+#define STATIC 3
+#define AUTO 4
+#define REGISTER 5
+
+#define accept(t) ((bool) (yytoken == (t) ? next() : 0))
+#define ahead() yyntoken
-/* Don't change this codification because program used it!!! */
enum tokens {
- /* types */
- INT = 1, CHAR, FLOAT, LONG, LLONG, SHORT, VOID, DOUBLE,
- LDOUBLE, STRUCT, UNION, ENUM, BOOL, ARY, PTR, FTN,
- COMPLEX, IMAGINARY, BITFLD, TYPENAME, TYPE,
- /* type qualifier */
- TQUALIFIER,
- /* sign specifier */
- UNSIGNED, SIGNED,
- /* storage specifier */
- STORAGE,
- /* other tokens */
- IDEN = 128, CONSTANT, SIZEOF,
+ TQUALIFIER = 128, TYPE, IDEN, SCLASS,
+ CONSTANT, SIZEOF,
INDIR, INC, DEC, SHL, SHR,
LE, GE, EQ, NE, AND, OR,
MUL_EQ, DIV_EQ, MOD_EQ, ADD_EQ, SUB_EQ, AND_EQ,
@@ -29,28 +55,17 @@ enum tokens {
CONTINUE, BREAK, RETURN, EOFTOK, NOTOK
};
-#define TYPEDEF (1<<0)
-#define EXTERN (1<<1)
-#define STATIC (1<<2)
-#define AUTO (1<<3)
-#define REGISTER (1<<4)
-
-#define VOLATILE (1<<0)
-#define CONST (1<<1)
-#define RESTRICT (1<<2)
-
struct symbol;
-extern struct symbol *yyval;
+union yystype {
+ struct symbol *sym;
+};
+extern union yystype yylval;
extern char yytext[];
-extern size_t yylen;
-extern unsigned char yytoken;
+extern uint8_t yytoken, yyntoken;
+
+extern void init_lex(void), init_keywords(void), expect(uint8_t tok);
+extern uint8_t next(void);
-extern void init_lex(void);
-extern void next(void);
-extern char accept(unsigned char tok);
-extern void expect(unsigned char tok);
-extern void init_keywords(void);
-extern unsigned char ahead(void);
#endif
diff --git a/tree.c b/tree.c
@@ -1,5 +1,6 @@
#include <assert.h>
+#include <stdint.h>
#include <stdio.h>
#include "cc.h"
diff --git a/types.c b/types.c
@@ -1,5 +1,5 @@
-#include <assert.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -8,112 +8,254 @@
#include "tokens.h"
#include "symbol.h"
+#define NR_TYPE_HASH 16
+#define PTRSIZE 2
+#define CHARSIZE 1
+#define SHORTSIZE 2
+#define INTSIZE 2
+#define LONGSIZE 4
+#define LLONGSIZE 8
+#define FLOATSIZE 4
+#define LFLOATSIZE 8
+#define LLFLOATSIZE 16
-static unsigned char stack[NR_DECLARATORS];
-static unsigned char *stackp = stack;
+struct ctype
+ *voidtype = &(struct ctype) {
+ .op = VOID
+ },
+ *uchartype = &(struct ctype) {
+ .op = INT,
+ .size = CHARSIZE,
+ .sign = 1
+ },
+ *chartype = &(struct ctype) {
+ .op = INT,
+ .size = CHARSIZE,
+ },
+ *uinttype = &(struct ctype) {
+ .op = INT,
+ .size = INTSIZE,
+ .sign = 1
+ },
+ *inttype = &(struct ctype) {
+ .op = INT,
+ .size = INTSIZE,
+ .sign = 1
+ },
+ *ushortype = &(struct ctype) {
+ .op = INT,
+ .size = SHORTSIZE,
+ },
+ *shortype = &(struct ctype) {
+ .op = INT,
+ .size = INTSIZE,
+ },
+ *longtype = &(struct ctype) {
+ .op = INT,
+ .size = LONGSIZE,
+ },
+ *ulongtype = &(struct ctype) {
+ .op = INT,
+ .size = LONGSIZE,
+ .sign = 1
+ },
+ *ullongtype = &(struct ctype) {
+ .op = INT,
+ .size = LLONGSIZE,
+ .sign = 1
+ },
+ *llongtype = &(struct ctype) {
+ .op = INT,
+ .size = LLONGSIZE,
+ },
+ *floattype = &(struct ctype) {
+ .op = FLOAT,
+ .size = FLOATSIZE
+ },
+ *cfloattype = &(struct ctype) {
+ .op = FLOAT,
+ .size = FLOATSIZE,
+ .cplex = 1
+ },
+ *ifloattype = &(struct ctype) {
+ .op = FLOAT,
+ .size = FLOATSIZE,
+ .imag = 1
+ },
+ *doubletype = &(struct ctype) {
+ .op = FLOAT,
+ .size = FLOATSIZE
+ },
+ *cdoubletype = &(struct ctype) {
+ .op = FLOAT,
+ .size = 0,
+ .cplex = 1
+ },
+ *idoubletype = &(struct ctype) {
+ .op = FLOAT,
+ .size = 0,
+ .imag = 1
+ },
+ *ldoubletype = &(struct ctype) {
+ .op = FLOAT,
+ .size = LLFLOATSIZE
+ },
+ *cldoubletype = &(struct ctype) {
+ .op = FLOAT,
+ .size = 0,
+ .cplex = 1
+ },
+ *ildoubletype = &(struct ctype) {
+ .op = FLOAT,
+ .size = 0,
+ .imag = 1
+ };
struct ctype *
-initctype(register struct ctype *tp)
+ctype(int8_t type, int8_t sign, int8_t size, int8_t cplex)
{
- memset(tp, 0, sizeof(*tp));
- tp->forward = 1;
- return tp;
-}
+ if (type == CHAR && !sign)
+ sign = options.charsign;
+ if (sign == SIGNED)
+ sign = 0;
+ if (type == DOUBLE)
+ type = FLOAT, size += LONG;
-void
-delctype(register struct ctype *tp)
-{
- if (!tp)
- return;
- if (tp->base)
- delctype(tp->base);
- free(tp);
+ switch (type) {
+ case VOID: return voidtype;
+ case CHAR: return (sign) ? uchartype : chartype;
+ case INT: switch (size) {
+ case 0: return (sign) ? uinttype : inttype;
+ case SHORT: return (sign) ? ushortype : shortype;
+ case LONG: return (sign) ? longtype : ulongtype;
+ case LONG+LONG: return (sign) ? ullongtype : llongtype;
+ }
+ case FLOAT: switch (size) {
+ case 0: switch (cplex) {
+ case 0: return floattype;
+ case COMPLEX: return cfloattype;
+ case IMAGINARY: return ifloattype;
+ }
+ case LONG: switch (cplex) {
+ case 0: return doubletype;
+ case COMPLEX: return cdoubletype;
+ case IMAGINARY: return ifloattype;
+ }
+ case LONG+LONG: switch (cplex) {
+ case 0: return ldoubletype;
+ case COMPLEX: return cldoubletype;
+ case IMAGINARY: return ildoubletype;
+ }
+ }
+ }
}
-static struct ctype *
-mktype(register struct ctype *tp, unsigned char op)
+struct ctype *
+mktype(struct ctype *tp, uint8_t op,
+ struct symbol *sym, uint16_t nelem)
{
- unsigned len;
+ static struct ctype *typetab[NR_TYPE_HASH], **tbl;
+ static uint8_t t;
+ static unsigned short size;
+ register struct ctype *bp;
- switch (op) {
- case ARY:
- assert(stackp != stack);
- len = *--stackp;
- case PTR: case FTN: {
- register struct ctype *aux = tp;
-
- tp = xmalloc(sizeof(*tp));
- initctype(tp);
- tp->type = op;
- tp->base = aux;
- tp->len = len;
- break;
- }
- case VOLATILE:
- tp->c_volatile = 1;
- break;
- case RESTRICT:
- tp->c_restrict = 1;
- break;
- case CONST:
- tp->c_const = 1;
- break;
- default:
- assert(0);
+ t = (op ^ (uint8_t) ((unsigned short) tp >> 3))
+ & NR_TYPE_HASH-1;
+ tbl = &typetab[t];
+ if (op != FTN) {
+ for (bp = *tbl; bp; bp = bp->next) {
+ if (bp->type == tp && bp->op == op &&
+ bp->sym == sym && bp->nelem == nelem) {
+ return bp;
+ }
+ }
}
- return tp;
-}
-void
-pushtype(unsigned mod)
-{
- if (stackp == stack + NR_DECLARATORS)
- error("Too much type declarators");
- *stackp++ = mod;
+ switch (op) {
+ case PTR: size = PTRSIZE; break;
+ case FTN: size = 0; break;
+ case ARY: size = tp->size * nelem; break;
+ default: size = tp->size; break;
+ }
+ bp = xmalloc(sizeof(*bp));
+ bp->next = *tbl;
+ bp->type = tp;
+ bp->op = op;
+ bp->nelem = nelem;
+ bp->sym = sym;
+ bp->pars = NULL;
+ bp->size = size;
+ return *tbl = bp;
}
struct ctype *
-decl_type(struct ctype *tp)
+qualifier(struct ctype *tp, uint8_t qlf)
{
- struct ctype *new = xmalloc(sizeof(*new));
- *new = *tp;
+ uint8_t q = tp->op;
- while (stackp != stack)
- new = mktype(new, *--stackp);
- return new;
+ if (q & TQUALIFIER) {
+ if (q == qlf)
+ return tp;
+ tp = tp->type;
+ qlf |= q;
+ }
+ return mktype(tp, qlf|TQUALIFIER, NULL, 0);
}
+#include <stdio.h>
+static void
+ptype(struct ctype *tp)
+{
+ uint8_t op;
+ struct funpars *fp;
-#ifndef NDEBUG
-#include <stdio.h>
+ if (!tp)
+ return;
+ op = tp->op;
+ if (op & TQUALIFIER) {
+ if (op & CONST)
+ fputs("const ", stdout);
+ if (op & VOLATILE)
+ fputs("volatile ", stdout);
+ if (op & RESTRICT)
+ fputs("restrict ", stdout);
+ } else {
+ switch (op) {
+ case PTR: fputs("pointer ", stdout); break;
+ case ARY: fputs("array ", stdout); break;
+ case STRUCT: fputs("struct", stdout); break;
+ case UNION: fputs("union", stdout); break;
+ case ENUM: fputs("enum", stdout); break;
+ case BOOL: fputs("bool", stdout); break;
+ case INT:
+ printf("int size=%u sign=%u", tp->size, tp->sign);
+ break;
+ case FLOAT:
+ printf("float size=%u cplex=%u", tp->size, tp->cplex);
+ break;
+ case TYPENAME:
+ printf("typename %s type ", tp->sym->name);
+ break;
+ case FTN:
+ fputs("function(", stdout);
+ for (fp = tp->pars; fp; fp = fp->next) {
+ ptype(tp);
+ if (fp->next)
+ fputs(", ", stdout);
+ }
+ fputs(") ", stdout);
+ break;
+ }
+ }
+ ptype(tp->type);
+}
void
-ptype(register struct ctype *tp)
+printtype(struct ctype *tp)
{
- static const char *strings[] = {
- [0] = "[no type]",
- [ARY] = "array of ",
- [PTR] = "pointer to ",
- [FTN] = "function that returns ",
- [VOLATILE] = "volatile ",
- [RESTRICT] = "restrict ",
- [CONST] = "const ",
- [INT] = "int ",
- [CHAR] = "char ",
- [FLOAT] = "float ",
- [LONG] = "long ",
- [LLONG] = "long long ",
- [SHORT] = "short ",
- [VOID] = "void ",
- [DOUBLE] = "double ",
- [LDOUBLE] = "long double "
- };
- assert(tp);
-
- for (; tp; tp = tp->base)
- fputs(strings[tp->type], stdout);
+ printf("type = %p ", tp);
+ ptype(tp);
putchar('\n');
}
-#endif