shithub: scc

Download patch

ref: dd604299ecdeb25d1c7d0f4cb77e2478777272ad
parent: b6d551944bd495bb30ba7345f5ab77ccca14c295
parent: 1ab6ca3ad193716d021f635aaf38cfd2e1d07902
author: Roberto E. Vargas Caballero <[email protected]>
date: Tue Apr 1 17:42:12 EDT 2014

Merge branch 'bsc'

--- a/cc.h
+++ b/cc.h
@@ -1,13 +1,12 @@
 #ifndef CC_H
 #define CC_H
 
+#ifndef __bool_true_and_false_defined
+#include <stdbool.h>
+#endif
+
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
 
-extern unsigned linenum;
-extern unsigned columnum;
-extern const char *filename;
-
-
 struct user_opt {
 	unsigned char implicit;
 	unsigned char c99;
@@ -26,4 +25,210 @@
 extern void *xcalloc(size_t nmemb, size_t size);
 extern char *xstrdup(const char *s);
 extern void *xrealloc(void *buff, register size_t size);
+
+/* definitions of types */
+
+#define CTX_OUTER 0
+#define CTX_FUNC  1
+
+enum {
+	NS_IDEN = 0,
+	NS_LABEL,
+	NS_TAG,
+	NR_NAMESPACES,
+	NS_KEYWORD,
+	NS_FREE
+};
+
+struct funpars;
+struct symbol;
+
+struct ctype {
+	uint8_t op;           /* type builder operator */
+	char letter;          /* letter of the type */
+	short nelem;          /* number of elements in arrays */
+	unsigned defined : 1; /* type defined (is not a forward reference) */
+	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 */
+	union {
+		struct funpar *pars;  /* function parameters */
+		struct field *fields; /* aggregate fields */
+	} u;
+};
+
+typedef struct ctype Type;
+
+struct field {
+	struct symbol *sym;
+	struct field *next;
+};
+
+struct funpar {
+	Type *type;
+	struct funpar *next;
+};
+
+/* definition of symbols */
+
+union value {
+	char c;
+	int i;
+	struct symbol *sym;
+	uint8_t ns, token;
+};
+
+struct symbol {
+	char *name;
+	Type *type;
+	short id;
+	uint8_t ctx;
+	uint8_t token;
+	uint8_t ns;
+	struct {
+		bool isglobal : 1;
+		bool isstatic : 1;
+		bool isauto : 1;
+		bool isregister : 1;
+	} s;
+	union value u;
+	struct symbol *next;
+	struct symbol *hash;
+};
+
+typedef struct symbol Symbol;
+
+extern void freesyms(uint8_t ns);
+
+extern Type *qualifier(Type *tp, uint8_t qlf),
+	*ctype(int8_t type, int8_t sign, int8_t size),
+	*mktype(Type *tp,
+	        uint8_t op, Symbol *tag, uint16_t nelem);
+
+extern Symbol
+	*lookup(char *s, unsigned char ns),
+	*install(char *s, unsigned char ns);
+
+extern void context(void (*fun)(void));
+
+extern Type *voidtype,
+	*uchartype,   *chartype,
+	*uinttype,    *inttype,
+	*ushortype,   *shortype,
+	*longtype,    *ulongtype,
+	*ullongtype,  *llongtype,
+	*floattype,   *doubletype,  *ldoubletype;
+
+#define ISQUAL(t)    (isqual((t)->op))
+#define UNQUAL(t)    (ISQUAL(t) ? (t)->type : (t))
+#define BTYPE(t)     (UNQUAL(t)->op)
+#define isarith(op)  ((op) & ARITH)
+#define isaddr(op)   ((op) & POINTER)
+#define isrecord(op) ((op) & RECORD)
+#define isqual(op)   ((op) & TQUALIFIER)
+
+
+#define ARITH         8
+#define RECORD        16
+#define POINTER       32
+#define ATYPE(x)      (ARITH  | (x))
+#define RTYPE(x)      (RECORD | (x))
+#define PTYPE(x)      (POINTER| (x))
+
+#define FTN           1
+#define ENUM          2
+#define TYPENAME      3
+#define VOID          4
+
+#define FLOAT         ATYPE(1)
+#define INT           ATYPE(2)
+#define BOOL          ATYPE(3)
+
+#define STRUCT        RTYPE(1)
+#define UNION         RTYPE(2)
+
+#define PTR           PTYPE(1)
+#define ARY           PTYPE(2)
+
+#define CHAR          (ARY+1)
+#define DOUBLE        (ARY+2)
+#define SHORT         (ARY+3)
+#define LONG          (ARY+4)
+
+#define COMPLEX       (ARY+5)
+#define IMAGINARY     (ARY+6)
+#define UNSIGNED      (ARY+7)
+#define SIGNED        (ARY+8)
+
+#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) ((yytoken == (t)) ? next() : 0)
+#define ahead()   yyntoken
+
+enum tokens {
+	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,
+	XOR_EQ, OR_EQ, SHL_EQ, SHR_EQ,
+	ELLIPSIS,
+	CASE, DEFAULT, IF, ELSE, SWITCH, WHILE, DO, FOR, GOTO,
+	CONTINUE, BREAK, RETURN, EOFTOK, NOTOK
+};
+
+union yystype {
+	Symbol *sym;
+	uint8_t token;
+};
+
+extern union yystype yylval;
+extern char yytext[];
+extern uint8_t yytoken, yyntoken;
+
+extern uint8_t next(void);
+extern void expect(uint8_t tok);
+
+
+typedef struct node {
+	void (*code)(struct node *);
+	Type *type;
+	union unode {
+		Symbol *sym;
+		Type *type;
+		char op;
+	} u;
+	struct node *childs[];
+} Node;
+
+typedef void (*Inst)(Node *);
+
+enum {
+	OCAST, OPTR, OADD, OARY, OSIZE, OMUL
+};
+
+extern void
+	emitsym(Node *), emitunary(Node *),
+	emitbin(Node *), emitexp(Node *);
+
+extern Node
+	*node(Inst code, Type *tp, union unode u, uint8_t nchilds),
+	*unarycode(char op, Type *tp, Node *child),
+	*bincode(char op, Type *tp, Node *np1, Node *np2),
+	*castcode(Node *child, Type *tp),
+	*sizeofcode(Type *tp);
+
+#define SYM(s) ((union unode) {.sym = s})
+#define OP(s) ((union unode) {.op = s})
+#define TYP(s) ((union unode) {.type = s})
+
 #endif
--- a/code.c
+++ b/code.c
@@ -2,11 +2,32 @@
 #include <stdint.h>
 #include <stdio.h>
 
-#include "symbol.h"
+#include "cc.h"
 
+char *opcodes[] = {
+	[OADD] = "+",
+	[OMUL] = "*",
+	[OARY] = "'",
+	[OSIZE] = "#",
+	[OPTR] = "@"
+};
+
+Node *
+node(Inst code, Type *tp, union unode u, uint8_t nchilds)
+{
+	Node *np = xmalloc(sizeof(*np) + nchilds * sizeof(np));
+
+	np->code = code;
+	np->type = tp;
+	np->u = u;
+
+	return np;
+}
+
 void
-emitsym(struct symbol *sym)
+emitsym(Node *np)
 {
+	Symbol *sym = np->u.sym;
 	char c;
 
 	if (sym->s.isglobal)
@@ -14,7 +35,7 @@
 	else if (sym->s.isstatic)
 		c = 'T';
 	else if (sym->s.isregister)
-		c = 'R';
+		c = 'Q';
 	else
 		c = 'A';
 	printf("\t%c%d", c, sym->id);
@@ -21,19 +42,97 @@
 }
 
 void
-emitfun(struct symbol *sym)
+emitcast(Node *np)
 {
+	Node *child = np->childs[0];
+
+	(*child->code)(child);
+	printf("\t%c%c", np->u.type->letter, np->type->letter);
+}
+
+void
+emitunary(Node *np)
+{
+	Node *child;
+	char op, letter;
+
+	letter = np->type->letter;
+	child = np->childs[0];
+	(*child->code)(child);
+	printf("\t%s%c", opcodes[np->u.op], letter);
+}
+
+void
+emitbin(Node *np)
+{
+	Node *child1, *child2;
+
+	child1 = np->childs[0];
+	child2 = np->childs[1];
+	(*child1->code)(child1);
+	(*child2->code)(child2);
+	printf("\t%s%c", opcodes[np->u.op], np->type->letter);
+}
+
+void
+emitsizeof(Node *np)
+{
+	printf("\t#%c", np->u.type->letter);
+}
+
+void
+emitexp(Node *np)
+{
+	(*np->code)(np);
+	putchar('\n');
+}
+
+void
+emitfun(Symbol *sym)
+{
 	printf("X%s\n", sym->name);
 }
 
 void
-emitframe(struct symbol *sym)
+emitframe(Symbol *sym)
 {
 	puts("{");
 }
 
 void
-emitret(struct symbol *sym)
+emitret(Symbol *sym)
 {
 	puts("}");
 }
+
+Node *
+castcode(Node *child, Type *tp)
+{
+	Node *np = node(emitcast, tp, TYP(child->type), 1);
+
+	np->childs[0] = child;
+	return np;
+}
+	
+Node *
+unarycode(char op, Type *tp, Node *child)
+{
+	Node *np = node(emitunary, tp, OP(op), 1);
+	np->childs[0] = child;
+	return np;
+}
+
+Node *
+bincode(char op, Type *tp, Node *np1, Node *np2)
+{
+	Node *np = node(emitbin, tp, OP(op), 2);
+	np->childs[0] = np1;
+	np->childs[1] = np2;
+	return np;
+}
+
+Node *
+sizeofcode(Type *tp)
+{
+	return node(emitsizeof, inttype, TYP(tp), 0);
+}
\ No newline at end of file
--- a/code.h
+++ /dev/null
@@ -1,10 +1,0 @@
-
-#ifndef CODE_H_
-#define CODE_H_
-
-struct symbol;
-
-extern void emitsym(struct symbol *sym),  emitfun(struct symbol *sym),
-	emitframe(struct symbol *sym), emitret(struct symbol *sym);
-
-#endif
--- a/decl.c
+++ b/decl.c
@@ -5,8 +5,6 @@
 
 #include "sizes.h"
 #include "cc.h"
-#include "tokens.h"
-#include "symbol.h"
 #include "machine.h"
 
 #define ID_EXPECTED     1
@@ -18,7 +16,7 @@
 	uint8_t op;
 	union {
 		unsigned short nelem;
-		struct symbol *sym;
+		Symbol *sym;
 		struct funpars *pars;
 		uint8_t qlf;
 	} u;
@@ -51,10 +49,10 @@
 	return dp + 1;
 }
 
-static struct symbol *
+static Symbol *
 newiden(uint8_t ns)
 {
-	struct symbol *sym;
+	Symbol *sym;
 	extern uint8_t curctx;
 
 	if (yylval.sym && yylval.sym->ctx == curctx)
@@ -67,7 +65,7 @@
 static struct dcldata *
 directdcl(struct dcldata *dp, uint8_t ns, int8_t flags)
 {
-	register struct symbol *sym;
+	register Symbol *sym;
 	char *err;
 
 	if (accept('(')) {
@@ -133,12 +131,12 @@
 	error("too much declarators");
 }
 
-static struct symbol *
-declarator(struct ctype *tp, uint8_t ns, int8_t flags)
+static Symbol *
+declarator(Type *tp, uint8_t ns, int8_t flags)
 {
 	struct dcldata data[NR_DECLARATORS+1];
 	register struct dcldata *bp;
-	struct symbol *sym;
+	Symbol *sym;
 
 	memset(data, 0, sizeof(data));
 	data[NR_DECLARATORS].op = 255;
@@ -162,19 +160,19 @@
 	return sym;
 }
 
-static struct ctype *structdcl(void), *enumdcl(void);
+static Type *structdcl(void), *enumdcl(void);
 
-static struct ctype *
+static Type *
 specifier(int8_t *sclass)
 {
-	struct ctype *tp = NULL;
-	int8_t qlf, sign, type, cls, cplex, size, t;
+	Type *tp = NULL;
+	int8_t qlf, sign, type, cls, size, t;
 
-	qlf = sign = type = cls = size = cplex = 0;
+	qlf = sign = type = cls = size = 0;
 
 	for (;;) {
 		register uint8_t *p;
-		struct ctype *(*dcl)(void) = NULL;
+		Type *(*dcl)(void) = NULL;
 
 		switch (yytoken) {
 		case SCLASS: p = &cls; break;
@@ -203,8 +201,6 @@
 				}
 			case SHORT:
 				p = &size; break;
-			case COMPLEX: case IMAGINARY:
-				p = &cplex; break;
 			}
 			break;
 		default:
@@ -228,7 +224,6 @@
 		type = INT;
 	}
 	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) {
@@ -237,7 +232,7 @@
 	if (sclass)
 		*sclass = cls;
 	if (!tp)
-		tp = ctype(type, sign, size, cplex);
+		tp = ctype(type, sign, size);
 	return (qlf) ? qualifier(tp, qlf) : tp;
 
 invalid_type:
@@ -245,7 +240,7 @@
 }
 
 static struct node *
-initializer(register struct ctype *tp)
+initializer(register Type *tp)
 {
 	if (accept('{')) {
 		initializer(tp);
@@ -260,11 +255,10 @@
 /* TODO: bitfields */
 
 static void
-newfield(struct ctype *tp, struct symbol *sym)
+newfield(Type *tp, Symbol *sym)
 {
 	register struct field *p, *q;
 	register char *s, *t;
-	static short size, offset;
 	static uint8_t op;
 	static char *err;
 
@@ -281,25 +275,10 @@
 	p = xmalloc(sizeof(*p));
 	p->next = NULL;
 	p->sym = sym;
-	size = sym->type->size;
-	if (!q) {
+	if (!q)
 		tp->u.fields = p;
-		if (op != ENUM) {
-			tp->size = size;
-			sym->u.offset = 0;
-		}
-	} else {
+	else
 		q->next = p;
-		if (tp->op == STRUCT) {
-			offset = ALIGN(size, tp->size);
-			sym->u.offset = offset;
-			tp->size = offset + size;
-		} else if (op == UNION) {
-			sym->u.offset = 0;
-			if (tp->size < size)
-				tp->size = size;
-		}
-	}
 
 	return;
 
@@ -313,10 +292,10 @@
 }
 
 static void
-fielddcl(struct ctype *base, uint8_t ns)
+fielddcl(Type *base, uint8_t ns)
 {
-	struct ctype *tp;
-	struct symbol *sym;
+	Type *tp;
+	Symbol *sym;
 	char *err;
 
 	switch (yytoken) {
@@ -349,11 +328,11 @@
 	error(err, yytext);
 }
 
-static struct ctype *
+static Type *
 newtag(uint8_t tag)
 {
-	register struct symbol *sym;
-	struct ctype *tp;
+	register Symbol *sym;
+	Type *tp;
 	extern uint8_t namespace;
 
 	if (yytoken == IDEN) {
@@ -377,10 +356,10 @@
 	error("'%s' defined as wrong kind of tag", yytext);
 }
 
-static struct ctype *
+static Type *
 structdcl(void)
 {
-	struct ctype *tp;
+	Type *tp;
 	uint8_t ns, tag;
 
 	tag = yylval.token;
@@ -403,11 +382,11 @@
 	error("redefinition of struct/union '%s'", yytext);
 }
 
-static struct ctype *
+static Type *
 enumdcl(void)
 {
-	register struct ctype *tp;
-	struct symbol *sym;
+	register Type *tp;
+	Symbol *sym;
 	int val = 0;
 	char *err;
 
@@ -447,8 +426,8 @@
 void
 decl(void)
 {
-	struct ctype *tp;
-	struct symbol *sym;
+	Type *tp;
+	Symbol *sym;
 	int8_t sclass;
 
 	tp = specifier(&sclass);
@@ -472,9 +451,9 @@
 void
 extdecl(void)
 {
-	struct ctype *base;
+	Type *base;
 	int8_t sclass;
-	struct symbol *sym;
+	Symbol *sym;
 	char *err;
 	extern void compound(void);
 
@@ -493,7 +472,7 @@
 
 	if (yytoken != ';') {
 		do {
-			struct ctype *tp;
+			Type *tp;
 
 			sym = declarator(base, NS_IDEN, ID_EXPECTED);
 			tp = sym->type;
@@ -500,7 +479,7 @@
 
 			if (!(sclass & STATIC))
 				sym->s.isglobal = 1;
-			if (isfun(BTYPE(tp))) {
+			if (BTYPE(tp) == FTN) {
 				emitfun(sym);
 				if (yytoken == '{') {
 					emitframe(sym);
--- a/error.c
+++ b/error.c
@@ -1,12 +1,14 @@
 
 #include <stdarg.h>
 #include <stdlib.h>
+#include <stdint.h>
 #include <stdio.h>
 
 #include "cc.h"
 
-
-
+extern unsigned linenum;
+extern unsigned columnum;
+extern const char *filename;
 
 static void
 warn_helper(char flag, const char *fmt, va_list va)
--- a/expr.c
+++ b/expr.c
@@ -2,50 +2,22 @@
 #include <stdio.h>
 
 #include "cc.h"
-#include "code.h"
-#include "tokens.h"
-#include "symbol.h"
 
-struct node *expr(void);
+#define SWAP(x1, x2, t) (t = x1, x1 = x2, x2 = t)
 
-enum {
-	OSYM = 1, OARY, OPTR, OADD,
-};
+Node *expr(void);
 
-struct node {
-	uint8_t op;
-	struct ctype *type;
-
-	struct {
-		bool constant : 1;
-	} f;
-	union  {
-		struct symbol *sym;
-	} u;
-	struct node *left, *right;
-};
-
-struct node *
-newnode(uint8_t op, struct ctype *tp)
-{
-	struct node *np = xcalloc(1, sizeof(*np));
-
-	np->op = op;
-	np->type = tp;
-	return np;	
-}
-
-static struct node *
+static Node *
 primary(void)
 {
-	register struct node *np;
+	Node *np;
+	Symbol *sym;
 
 	switch (yytoken) {
 	case IDEN:
-		if (yylval.sym == NULL)
+		if ((sym = yylval.sym) == NULL)
 			error("'%s' undeclared", yytext);
-		np = newnode(OSYM, yylval.sym->type);
-		np->u.sym = yylval.sym;
+		np = node(emitsym, sym->type, SYM(sym), 0);
 		next();
 		break;
 	case CONSTANT:
@@ -58,117 +30,133 @@
 		expect(')');
 		break;
 	default:
-		np = NULL;
+		;
 	}
 	return np;
 }
 
-static struct node *
-int2ptr(struct node *np)
+void
+intconv(Node **np1, Node **np2)
 {
 }
 
-static struct node *
-ptr2vec(struct node *np)
+void
+floatconv(Node **np1, Node **np2)
 {
-	struct ctype *tp = np->type;
-	struct node *p;
-
-	tp = mktype(UNQUAL(tp)->type, ARY, NULL, 0);
-	p = newnode(OPTR, tp);
-	p->left = np;
-	return p;
 }
 
-static struct node *
-ary(struct node *np1)
+static Node *
+add(Node *np1, Node *np2)
 {
-	struct node *np2,  *naux;
-	struct ctype *tp;
+	Node *naux;
+	Type *tp1, *tp2;
 	uint8_t t1, t2, taux;
 
-	/* should be for arrays:   A2 A1 RI #1 *R ` */
-	/* should be for pointers: A2 @ A1 RI #1 *R ` */
-	np2 = expr();
-	expect(']');
-	t1 = BTYPE(np1->type);
-	t2 = BTYPE(np2->type);
+	tp1 = UNQUAL(np1->type), tp2 = UNQUAL(np2->type);
+	t1 = tp1->op, t2 = tp2->op;
 
-	if (!isaddr(t1)) {
-		taux = t1,   t1 = t2,   t2 = taux;
-		naux = np1, np1 = np2, np2 = naux;
+	switch (t1) {
+	case INT:
+		switch (t2) {
+		case INT:
+			if (tp1 != tp2)
+				intconv(&np1, &np2);
+			break;
+		case FLOAT:
+			SWAP(np1, np2, naux);
+			goto int_float;
+		case PTR: case FTN: case ARY:
+			SWAP(np1, np2, naux);
+			SWAP(t1, t2, taux);
+			goto pointer;
+		default:
+			goto incorrect;
+		}
+		break;
+	case FLOAT:
+		switch (t2) {
+		case FLOAT:
+			if (tp1 != tp2)
+				floatconv(&np1, &np2);
+			break;
+		case INT:
+int_float:		np2 = castcode(np2, np1->type);
+			break;
+		default:
+			goto incorrect;
+		}
+		break;
+	case PTR: case FTN: case ARY:
+pointer:	tp3 = tp1->type;
+		if (t1 == ARY)
+			tp1 = mktype(tp1->type, PTR, NULL, 0);
+		if (t2 != INT)
+			goto incorrect;
+		np2 = bincode(OMUL, tp1,
+		              castcode(np2, tp1),
+		              sizeofcode(tp3));
+		break;
+	default:
+		goto incorrect;
 	}
-	if (!isaddr(t1))
-		error("expected array or pointer");
-	if (isptr(t1))
-		np1 = ptr2vec(np1);
-	if (!isarith(t2))
-		error("array subscript is not an integer");
 
-	tp = np1->type;
-	tp = UNQUAL(tp);
-	naux = newnode(OADD, tp);
-	naux->left = np1;
-	naux->right = int2ptr(np2);
-	return naux;
+	return bincode(OADD, tp1, np1, np2);
+
+incorrect:
+	error("incorrect arithmetic operands"); /*TODO: print type names */
 }
 
-static struct node *
+static Node *
+array(Node *np1, Node *np2)
+{
+	Type *tp;
+	uint8_t t1, t2;
+	char *err;
+
+	t1 = BTYPE(np1->type);
+	t2 = BTYPE(np2->type);
+	if (!isaddr(t1) && !isaddr(t2))
+		goto bad_vector;
+	if (t1 != INT && t2 != INT)
+		goto bad_subs;
+	np1 = add(np1, np2);
+	return unarycode(OARY, np1->type->type , np1);
+
+bad_vector:
+	err = "subscripted value is neither array nor pointer nor vector";
+	goto error;
+bad_subs:
+	err = "array subscript is not an integer";
+error:	error(err);
+}
+
+static Node *
 postfix(void)
 {
-	struct node *np;
+	Node *np1, *np2;
 
-	np = primary();
+	np1 = primary();
 	for (;;) {
 		switch (yytoken) {
-		case '[': next(); np = ary(np); break;
-		default: return np;
+		case '[':
+			next();
+			np2 = expr();
+			np1 = array(np1, np2);
+			expect(']');
+			break;
+		default:
+			return np1;
 		}
-	}			
+	}
 }
 
-struct node *
+Node *
 expr(void)
 {
-	register struct node *np;
+	Node *np;
 
 	do
 		np = postfix();
 	while (yytoken == ',');
-
 	return np;
 }
-
-static void
-evalnode(struct node *np)
-{
-	if (!np)
-		return;
-
-	switch (np->op) {
-	case OSYM:
-		emitsym(np->u.sym);
-		break;
-	case OARY:
-		evalnode(np->left);
-		evalnode(np->right);
-		fputs("\t'", stdout);
-		break;
-	case OPTR:
-		evalnode(np->left);
-		fputs("\t@", stdout);
-		break;
-	case OADD:
-		evalnode(np->left);
-		evalnode(np->right);
-		fputs("\t+", stdout);
-		break;
-	}
-}
-
-void
-eval(struct node *np)
-{
-	evalnode(np);
-	putchar('\n');
-}
\ No newline at end of file
--- a/lex.c
+++ b/lex.c
@@ -6,8 +6,6 @@
 #include <ctype.h>
 
 #include "cc.h"
-#include "tokens.h"
-#include "symbol.h"
 #include "sizes.h"
 
 static FILE *yyin;
@@ -25,7 +23,7 @@
 static uint8_t
 integer(char *s, char base)
 {
-	static struct ctype *tp;
+	static Type *tp;
 	static char ch;
 
 	/* TODO: implement again */
@@ -128,7 +126,7 @@
 		{"while", WHILE, WHILE},
 		{NULL, 0, 0},
 	};
-	register struct symbol *sym;
+	register Symbol *sym;
 
 	for (bp = buff; bp->str; ++bp) {
 		sym = install(bp->str, NS_KEYWORD);
@@ -142,7 +140,7 @@
 {
 	register char *bp;
 	register int c;
-	struct symbol *sym;
+	Symbol *sym;
 
 	for (bp = yybuf; bp < &yybuf[IDENTSIZ]; *bp++ = c) {
 		if (!isalnum(c = getc(yyin)) && c != '_')
--- a/main.c
+++ b/main.c
@@ -3,7 +3,6 @@
 #include <stdint.h>
 
 #include "cc.h"
-#include "tokens.h"
 
 extern void extdecl(void), init_keywords(void), open_file(const char *file);
 
--- a/stmt.c
+++ b/stmt.c
@@ -1,15 +1,14 @@
 
+#include <stddef.h>
 #include <stdint.h>
 
-#include "symbol.h"
-#include "tokens.h"
+#include "cc.h"
 
-
 void
 compound(void)
 {
-	extern struct node *expr(void);
 	extern void decl(void);
+	extern Node *expr(void);
 
 	expect('{');
 	while (!accept('}')) {
@@ -18,8 +17,8 @@
 			decl();
 			break;
 		default:
-			eval(expr());
+			emitexp(expr());
 		}
 		expect(';');
 	}
-}
\ No newline at end of file
+}
--- a/symbol.c
+++ b/symbol.c
@@ -5,8 +5,6 @@
 #include <string.h>
 
 #include "cc.h"
-#include "symbol.h"
-#include "tokens.h"
 
 #define NR_SYM_HASH 32
 
@@ -14,8 +12,8 @@
 uint8_t namespace = NS_KEYWORD + 1 ;
 
 static struct symtab {
-	struct symbol *head;
-	struct symbol *htab[NR_SYM_HASH];
+	Symbol *head;
+	Symbol *htab[NR_SYM_HASH];
 } symtab [NR_NAMESPACES];
 
 static inline uint8_t
@@ -32,7 +30,7 @@
 freesyms(uint8_t ns)
 {
 	static struct symtab *tbl;
-	register struct symbol *sym;
+	register Symbol *sym;
 
 	tbl = &symtab[ns];
 	for (sym = tbl->head; sym; sym = sym->next) {
@@ -59,12 +57,12 @@
 	freesyms(NS_TAG);
 }
 
-struct symbol *
+Symbol *
 lookup(register char *s, uint8_t ns)
 {
 	extern union yystype yylval;
 	static struct symtab *tbl;
-	register struct symbol *sym;
+	register Symbol *sym;
 
 	tbl = &symtab[(ns >= NR_NAMESPACES) ? NS_IDEN : ns];
 	for (sym = tbl->htab[hash(s)]; sym; sym = sym->hash) {
@@ -76,11 +74,11 @@
 	return NULL;
 }
 
-struct symbol *
+Symbol *
 install(char *s, uint8_t ns)
 {
-	register struct symbol *sym;
-	register struct symbol **t;
+	register Symbol *sym;
+	register Symbol **t;
 	struct symtab *tbl;
 	static short id;
 
--- a/symbol.h
+++ /dev/null
@@ -1,112 +1,0 @@
-
-#ifndef SYMBOL_H
-#define SYMBOL_H
-
-#if ! __bool_true_and_false_are_defined
-#include <stdbool.h>
-#endif
-
-#define CTX_OUTER 0
-#define CTX_FUNC  1
-
-enum {
-	NS_IDEN = 0,
-	NS_LABEL,
-	NS_TAG,
-	NR_NAMESPACES,
-	NS_KEYWORD,
-	NS_FREE
-};
-
-struct funpars;
-struct symbol;
-
-struct ctype {
-	uint8_t op;           /* type builder operator */
-	short size;           /* size of variables */
-	short nelem;          /* number of elements in arrays */
-	unsigned defined : 1; /* type defined (is not a forward reference) */
-	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 */
-	union {
-		struct funpar *pars;  /* function parameters */
-		struct field *fields; /* aggregate fields */
-	} u;
-};
-
-struct field {
-	struct symbol *sym;
-	struct field *next;
-};
-
-struct funpar {
-	struct ctype *type;
-	struct funpar *next;
-};
-
-union value {
-	char c;
-	int i;
-	struct symbol *sym;
-	uint8_t ns, token;
-	short offset;
-};
-
-struct symbol {
-	char *name;
-	struct ctype *type;
-	short id;
-	uint8_t ctx;
-	uint8_t token;
-	uint8_t ns;
-	struct {
-		bool isglobal : 1;
-		bool isstatic : 1;
-		bool isauto : 1;
-		bool isregister : 1;
-	} s;
-	union value u;
-	struct symbol *next;
-	struct symbol *hash;
-};
-
-extern void freesyms(uint8_t ns);
-
-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);
-
-extern struct symbol
-	*lookup(char *s, unsigned char ns),
-	*install(char *s, unsigned char ns);
-
-extern void context(void (*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;
-
-#define ISQUAL(t)    (isqual((t)->op))
-#define UNQUAL(t)    (ISQUAL(t) ? (t)->type : (t))
-#define BTYPE(t)     (UNQUAL(t)->op)
-#define isfun(op)    ((op) == FTN)
-#define isptr(op)    ((op) == PTR)
-#define isary(op)    ((op) == ARY)
-#define isarith(op)  ((op) & ARITH)
-#define isaddr(op)   ((op) & POINTER)
-#define isrecord(op) ((op) & RECORD)
-#define isqual(op)   ((op) & TQUALIFIER)
-
-
-#endif
--- a/tokens.h
+++ /dev/null
@@ -1,79 +1,0 @@
-#ifndef TOKENS_H
-#define TOKENS_H
-
-#if ! __bool_true_false_are_defined
-# include <stdbool.h>
-#endif
-
-#define ARITH         8
-#define RECORD        16
-#define POINTER       32
-#define ATYPE(x)      (ARITH  | (x))
-#define RTYPE(x)      (RECORD | (x))
-#define PTYPE(x)      (POINTER| (x))
-
-#define FTN           1
-#define ENUM          2
-#define TYPENAME      3
-#define VOID          4
-
-#define FLOAT         ATYPE(1)
-#define INT           ATYPE(2)
-#define BOOL          ATYPE(3)
-
-#define STRUCT        RTYPE(1)
-#define UNION         RTYPE(2)
-
-#define PTR           PTYPE(1)
-#define ARY           PTYPE(2)
-
-#define CHAR          (ARY+1)
-#define DOUBLE        (ARY+2)
-#define SHORT         (ARY+3)
-#define LONG          (ARY+4)
-
-#define COMPLEX       (ARY+5)
-#define IMAGINARY     (ARY+6)
-#define UNSIGNED      (ARY+7)
-#define SIGNED        (ARY+8)
-
-#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 {
-	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,
-	XOR_EQ, OR_EQ, SHL_EQ, SHR_EQ,
-	ELLIPSIS,
-	CASE, DEFAULT, IF, ELSE, SWITCH, WHILE, DO, FOR, GOTO,
-	CONTINUE, BREAK, RETURN, EOFTOK, NOTOK
-};
-
-struct symbol;
-union yystype {
-	struct symbol *sym;
-	uint8_t token;
-};
-
-extern union yystype yylval;
-extern char yytext[];
-extern uint8_t yytoken, yyntoken;
-
-
-extern uint8_t next(void);
-extern void expect(uint8_t tok);
-
-#endif
--- a/types.c
+++ b/types.c
@@ -5,106 +5,78 @@
 
 #include "sizes.h"
 #include "cc.h"
-#include "tokens.h"
-#include "symbol.h"
 #include "machine.h"
 
 #define NR_TYPE_HASH 16
 
-struct ctype
-	*voidtype = &(struct ctype) {
-		.op = VOID
+Type
+	*voidtype = &(Type) {
+		.op = VOID,
+		.letter = 'W'
 	},
-	*uchartype = &(struct ctype) {
+	*booltype = &(Type) {
 		.op = INT,
-		.size = CHARSIZE,
+		.letter = 'B'
+	},
+	*uchartype = &(Type) {
+		.op = INT,
+		.letter = 'M',
 		.sign = 1
 	},
-	*chartype = &(struct ctype) {
+	*chartype = &(Type) {
 		.op = INT,
-		.size = CHARSIZE,
+		.letter = 'C',
 	},
-	*uinttype = &(struct ctype) {
+	*uinttype = &(Type) {
 		.op = INT,
-		.size = INTSIZE,
+		.letter = 'U',
 		.sign = 1
 	},
-	*inttype = &(struct ctype) {
+	*inttype = &(Type) {
 		.op = INT,
-		.size = INTSIZE,
-		.sign = 1
+		.letter = 'I',
 	},
-	*ushortype = &(struct ctype) {
+	*ushortype = &(Type) {
 		.op = INT,
-		.size = SHORTSIZE,
+		.letter = 'E'
 	},
-	*shortype = &(struct ctype) {
+	*shortype = &(Type) {
 		.op = INT,
-		.size = INTSIZE,
+		.letter = 'K',
 	},
-	*longtype = &(struct ctype) {
+	*longtype = &(Type) {
 		.op = INT,
-		.size = LONGSIZE,
+		.letter = 'L'
 	},
-	*ulongtype = &(struct ctype) {
+	*ulongtype = &(Type) {
 		.op = INT,
-		.size = LONGSIZE,
+		.letter = 'Z',
 		.sign = 1
 	},
-	*ullongtype = &(struct ctype) {
+	*ullongtype = &(Type) {
 		.op = INT,
-		.size = LLONGSIZE,
+		.letter = 'O',
 		.sign = 1
 	},
-	*llongtype = &(struct ctype) {
+	*llongtype = &(Type) {
 		.op = INT,
-		.size = LLONGSIZE,
+		.letter = 'G',
 	},
-	*floattype = &(struct ctype) {
+	*floattype = &(Type) {
 		.op = FLOAT,
-		.size = FLOATSIZE
+		.letter = 'F'
 	},
-	*cfloattype = &(struct ctype) {
+	*doubletype = &(Type) {
 		.op = FLOAT,
-		.size = FLOATSIZE,
-		.cplex = 1
+		.letter = 'D'
 	},
-	*ifloattype = &(struct ctype) {
+	*ldoubletype = &(Type) {
 		.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
+		.letter = 'H'
 	};
 
-struct ctype *
-ctype(int8_t type, int8_t sign, int8_t size, int8_t cplex)
+Type *
+ctype(int8_t type, int8_t sign, int8_t size)
 {
 	if (type == CHAR && !sign)
 		sign = options.charsign;
@@ -115,6 +87,7 @@
 
 	switch (type) {
 	case VOID:                      return voidtype;
+	case BOOL:                      return booltype;
 	case CHAR:                      return (sign) ? uchartype  : chartype;
 	case INT: switch (size) {
 		case 0:                 return (sign) ? uinttype   : inttype;
@@ -123,33 +96,21 @@
 		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 0:                 return floattype;
+		case LONG:              return doubletype;
+		case LONG+LONG:         return ldoubletype;
 		}
-		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;
-		}
-		}
 	}
 }
 
-struct ctype *
-mktype(struct ctype *tp, uint8_t op,
-       struct symbol *sym, uint16_t nelem)
+Type *
+mktype(Type *tp, uint8_t op,
+       Symbol *sym, uint16_t nelem)
 {
-	static struct ctype *typetab[NR_TYPE_HASH], **tbl;
+	static Type *typetab[NR_TYPE_HASH], **tbl;
 	static uint8_t t;
-	static unsigned short size;
-	register struct ctype *bp;
+	register Type *bp;
+	char letter;
 
 	t = (op  ^  (uint8_t) ((unsigned short) tp >> 3))
 	         & NR_TYPE_HASH-1;
@@ -164,12 +125,12 @@
 	}
 
 	switch (op) {
-	case PTR: size = PTRSIZE; break;
-	case FTN: size = 0; break;
-	case ARY: size = tp->size * nelem; break;
-	case ENUM: size = INTSIZE;
-	case STRUCT: size = 0; break;
-	default:  size = tp->size; break;
+	case PTR:    letter = 'R'; break;
+	case FTN:    letter = 'F'; break;
+	case ARY:    letter = 'V'; break;
+	case ENUM:   letter = 'E'; break;
+	case STRUCT: letter = 'S'; break;
+	default:     abort();
 	}
 	bp = xmalloc(sizeof(*bp));
 	bp->next = *tbl;
@@ -177,12 +138,12 @@
 	bp->op = op;
 	bp->nelem = nelem;
 	bp->sym = sym;
-	bp->size = size;
+	bp->letter = letter;
 	return *tbl = bp;
 }
 
-struct ctype *
-qualifier(struct ctype *tp, uint8_t qlf)
+Type *
+qualifier(Type *tp, uint8_t qlf)
 {
 	uint8_t q = tp->op;
 
@@ -193,62 +154,5 @@
 		qlf |= q;
 	}
 	return mktype(tp, qlf|TQUALIFIER, NULL, 0);
-}
-
-#include <stdio.h>
-
-static void
-ptype(struct ctype *tp)
-{
-	uint8_t op;
-	struct funpar *fp;
-
-	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->u.pars; fp; fp = fp->next) {
-				ptype(tp);
-				if (fp->next)
-					fputs(", ", stdout);
-			}
-			fputs(") ", stdout);
-			break;
-		}
-	}
-	ptype(tp->type);
-}
-
-void
-printtype(struct ctype *tp)
-{
-	printf("type = %p ", tp);
-	ptype(tp);
-	putchar('\n');
 }
 
--- a/wrapper.c
+++ b/wrapper.c
@@ -2,6 +2,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <stdint.h>
+
 #include "cc.h"