shithub: scc

Download patch

ref: ec0bbf93d441cac0db795007d80b1dcdc32e91d0
parent: 7cce9dc9462e67e8ebfd5a507b49707f3a1e1013
author: Roberto E. Vargas Caballero <[email protected]>
date: Sat Mar 15 10:13:33 EDT 2014

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.

--- 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 dcldata
+	*declarator0(struct dcldata *dp, uint8_t ns, int8_t flags);
 
-static struct symbol *declarator(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 symbol *
-directdcl(register struct ctype *tp, unsigned char ns, unsigned char isfun)
+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,198 +90,130 @@
 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;
+	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);
+	}
+}
 
-	type = tp->type;
+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;
+	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 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;
-		}
-		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;
 
-	for (;; next()) {
+	qlf = sign = type = cls = size = cplex = 0;
+
+	for (;;) {
+		register uint8_t *p;
+		struct symbol *sym = yylval.sym;
+
 		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;
 	}
+	if (sclass)
+		*sclass = cls;
+	if (!tp)
+		tp = ctype(type, sign, size, cplex);
+	return (qlf) ? qualifier(tp, qlf) : tp;
 
-direct:	sym = directdcl(tp, ns, isfun);
-
-	for (bp = qlf; n--; pushtype(*bp++))
-		/* nothing */;
-	return sym;
+invalid_type:
+	error("invalid type specification");
 }
 
 static struct node *
@@ -270,261 +220,142 @@
 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;
+	uint8_t type = yylval.sym->u.c;
 
-	c.tree = NULL;
-
-	if (yytoken == ';')
-		return NULL;
-
-	do {
-		struct node *np, *aux;
-		register struct ctype *tp;
-		register struct symbol *sym;
-
-		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;
+	struct ctype *tp;
+	struct symbol *sym;
+	int8_t sclass;
 
-	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);
+	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);
+	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 (!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(';');
+	if (yytoken != ';') {
+		do {
+			sym = declarator(tp, 0, 1);
+			if (accept(':'))
+				; /* TODO: bitfields */
+			/* TODO: add to the aggregate */
+		} while (accept(','));
 	}
-	--nested_tags;
 
-	if (sym)
-		sym->ctype.forward = 0;
-	tp->forward = 0;
+	expect(';');
+	return NULL;
 }
 
-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)
+typename(void)
 {
-	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");
-
-	np = listdcl(&base, store, qlf, ns, 0);
-	expect(';');
-	return np;
+	declarator(specifier(NULL), NS_IDEN, -1)->type;
+	return  NULL;
 }
 
-void
-type_name(struct ctype *tp)
-{
-	char store = 0, qlf = 0;
-
-	initctype(tp);
-	specifier(tp, &store, &qlf);
-	declarator(tp, NS_TYPE, 0);
-	return;
-}
-
 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 STORAGE: case TQUALIFIER:
-		specifier(&base, &store, &qlf);
+	case TYPE: case SCLASS: case TQUALIFIER:
+		tp = specifier(&sclass);
+		if (sclass == REGISTER || sclass == AUTO)
+			error("incorrect storage class for file-scope declaration");
 		break;
+	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;
+}
--- 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 @@
 
 	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 @@
 	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 @@
 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:
--- 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 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 @@
 {
 	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 @@
 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 @@
 	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 @@
 }
 
 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();
-}
--- 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 @@
 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 @@
 		{"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 @@
 		{"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,62 +130,39 @@
 		{"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);
+	ungetc(c, yyin);
 
-	return lookup(yybuf, NS_IDEN);
+	yynlval.sym = lookup(yybuf, NS_IDEN);
+	return (yynlval.sym) ? yynlval.sym->token : IDEN;
 }
 
-static unsigned char
-skip(void)
+static uint8_t
+follow(uint8_t op, uint8_t eq, uint8_t rep)
 {
-	static int c;
-	extern char parser_out_home;
+	register int c = getc(yyin);
 
-	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;
-}
-
-static unsigned char
-follow(unsigned char op, unsigned char eq, unsigned char rep)
-{
-	register char c = getc(yyin);
-
 	yybuf[1] = c;
 	yybuf[2] = '\0';
 	if (c == '=')
@@ -225,14 +175,14 @@
 	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 @@
 	return op;
 }
 
-static unsigned char
+static uint8_t
 minus(void)
 {
 	register int c = getc(yyin);
@@ -270,10 +220,10 @@
 	}
 }
 
-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 @@
 	}
 }
 
-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;
+	yylval = yynlval;
+	if ((yytoken = yyntoken) == EOFTOK) {
+		if (forbid_eof)
+			error("Find EOF while parsing");
+		goto ret;
+	}
 
-	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();
+	while (isspace(c = getc(yyin))) {
+		switch (c) {
+		case '\n': ++linenum, columnum = 1; break;
+		case '\t': columnum += 8;	    break;
+		default:   ++columnum;		    break;
+		}
 	}
-}
 
-unsigned char
-ahead(void)
-{
-	return yynval->tok;
-}
-
-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);
--- a/main.c
+++ b/main.c
@@ -1,5 +1,6 @@
 
 #include <stddef.h>
+#include <stdint.h>
 
 #include "cc.h"
 #include "tokens.h"
@@ -6,20 +7,15 @@
 #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;
 }
--- 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;
+	return h & NR_SYM_HASH - 1;
 }
 
 void
-new_ctx(void)
+freesyms(uint8_t ns)
 {
-	++curctx;
-}
+	static struct symtab *tbl;
+	register struct symbol *sym;
 
-void
-del_ctx(void)
-{
-	register struct symbol *sym, *next;
-	static char *s;
-
-	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;
+	uint8_t ns;
+	struct node *np;
 
-	if (curctx == CTX_OUTER) {
-		for (sym = headfun; sym; sym = next) {
-			next = sym->next;
-			free(sym->name);
-			free(sym);
-		}
-	}
+	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;
 }
--- 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
--- a/syntax.h
+++ b/syntax.h
@@ -28,11 +28,8 @@
 	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);
--- 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
 
-/* Don't change this codification because program used it!!! */
+#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
+
 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 @@
 	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);
-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);
+extern void init_lex(void), init_keywords(void), expect(uint8_t tok);
+extern uint8_t next(void);
+
 #endif
--- a/tree.c
+++ b/tree.c
@@ -1,5 +1,6 @@
 
 #include <assert.h>
+#include <stdint.h>
 #include <stdio.h>
 
 #include "cc.h"
--- 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;
+	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;
+			}
+		}
+	}
 
-		tp = xmalloc(sizeof(*tp));
-		initctype(tp);
-		tp->type = op;
-		tp->base = aux;
-		tp->len = len;
-		break;
+	switch (op) {
+	case PTR: size = PTRSIZE; break;
+	case FTN: size = 0; break;
+	case ARY: size = tp->size * nelem; break;
+	default:  size = tp->size; 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);
-	}
-	return tp;
+	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;
 }
 
-void
-pushtype(unsigned mod)
-{
-	if (stackp == stack + NR_DECLARATORS)
-		error("Too much type declarators");
-	*stackp++ = mod;
-}
-
 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