ref: e0b2f47525a1dc50a5089d2f472f1b51fbb0b483
parent: 87f8ea372e925ddb1ab531130bfd3e989e73c5b5
author: Roberto E. Vargas Caballero <[email protected]>
date: Fri Apr 25 06:33:28 EDT 2014
Create directory cc1 We are going to begin with the backend of the compiler so it is a good idea to have two different directories.
--- a/.gitignore
+++ /dev/null
@@ -1,4 +1,0 @@
-*.o
-makefile
-cc1
-TODO
--- a/Makefile
+++ /dev/null
@@ -1,21 +1,0 @@
-
-OBJS = types.o decl.o lex.o error.o symbol.o main.o expr.o \
- wrapper.o code.o stmt.o
-
-
-all: cc1
-
-$(OBJS) : cc1.h
-
-cc1: $(OBJS)
- $(CC) $(LDFLAGS) $(CFLAGS) $(LIBS) $(OBJS) -o $@
-
-clean:
- rm -f $(OBJS)
- rm -f cc1
-
-distclean: clean
- rm -f *~
- rm -f tags
- rm -f cscope.*
- rm -f makefile
--- a/cc1.h
+++ /dev/null
@@ -1,259 +1,0 @@
-#ifndef CC_H
-#define CC_H
-
-#ifndef __bool_true_and_false_defined
-#include <stdbool.h>
-#endif
-
-
-struct user_opt {
- unsigned char implicit;
- unsigned char mixdcls;
- unsigned char npromote;
- unsigned char useless;
- unsigned char charsign;
- unsigned char pcompare;
-};
-
-extern struct user_opt options;
-
-extern void error(const char *fmt, ...);
-extern void die(const char *fmt, ...);
-extern void warn(signed char flag, const char *fmt, ...);
-extern void *xmalloc(size_t size);
-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_FREE
-};
-
-struct funpars;
-struct symbol;
-
-#define RANK_BOOL 0
-#define RANK_SCHAR 1
-#define RANK_UCHAR 2
-#define RANK_SHORT 3
-#define RANK_USHORT 4
-#define RANK_INT 5
-#define RANK_UINT 6
-#define RANK_LONG 7
-#define RANK_ULONG 8
-#define RANK_LLONG 9
-#define RANK_ULLONG 10
-#define RANK_FLOAT 11
-#define RANK_DOUBLE 12
-#define RANK_LDOUBLE 13
-
-struct ctype {
- uint8_t op; /* type builder operator */
- char letter; /* letter of the type */
- bool defined : 1; /* type defined (is not a forward reference) */
- bool 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 {
- unsigned char rank; /* convertion rank */
- short nelem; /* number of elements in arrays */
- 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 */
-
-
-
-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;
- bool isdefined : 1;
- } s;
- union {
- int i;
- char *s;
- struct symbol *sym;
- uint8_t ns, token;
- } 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);
-
-typedef struct caselist Caselist;
-typedef void Ctxfun(Symbol *, Symbol *, Caselist *);
-
-extern Ctxfun compound;
-extern void context(Ctxfun *fun,
- Symbol *lbreak, Symbol *lcont, Caselist *lswitch);
-
-extern Type *typename(void);
-
-extern Type *voidtype, *pvoidtype, *booltype,
- *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 isqual(op) ((op) & TQUALIFIER)
-#define isconst(op) (((op) & (TQUALIFIER|CONST)) == \
- (TQUALIFIER|CONST))
-
-
-enum {
- FTN = 1, ENUM, TYPENAME, VOID, FLOAT, INT, BOOL,
- STRUCT, UNION, PTR, ARY, CHAR, DOUBLE, SHORT,
- LONG, COMPLEX, UNSIGNED, SIGNED
-};
-
-#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, STRING,
- 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;
- Type *utype;
- uint8_t typeop;
- struct {
- bool lvalue : 1;
- bool symbol: 1;
- bool constant : 1;
- } b;
- union unode {
- Symbol *sym;
- Type *type;
- char op;
- } u;
- struct node *childs[];
-} Node;
-
-enum {
- OCAST = 1, OPTR, OADD, OARY, OSIZE, OMUL, OSUB,
- OINC, ODEC, ODIV, OMOD, OSHL, OSHR,
- OBAND, OBXOR, OBOR, OASSIGN, OA_MUL, OA_DIV,
- OA_MOD, OA_ADD, OA_SUB, OA_SHL, OA_SHR,
- OA_AND, OA_XOR, OA_OR, OADDR,ONEG, OCPL, OEXC,
- OCOMMA,
- /*
- * Complementary relational operators only differ in less
- * significant bit
- */
- OEQ = 0x40, ONE, OLT, OGE, OLE, OGT, OAND, OOR
-};
-
-extern void
- emitdcl(Symbol *), emitsframe(Symbol *), emiteframe(Symbol *),
- emitsym(Node *), emitunary(Node *),
- emitbin(Node *), emitexp(Node *),
- emitprint(Node *), emitlabel(Symbol *), emitjump(Symbol *, Node *),
- emitbloop(void), emiteloop(void),
- emitswitch(short, Node *), emitcase(Symbol *, Node *),
- emitdefault(Symbol *);
-
-extern Node
- *node(void (*code)(Node *),
- 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),
- *ternarycode(Node *cond, Node *ifyes, Node *ifno),
- *symcode(Symbol *sym);
-
-#define SYM(s) ((union unode) {.sym = s})
-#define OP(s) ((union unode) {.op = s})
-#define TYP(s) ((union unode) {.type = s})
-#define NEGATE(n, v) ((n)->u.op ^= (v))
-/* TODO: remove some of these ugly macros */
-#define ISNODEBIN(n) ((n)->code == emitbin)
-#define ISNODECMP(n) (ISNODEBIN(n) && (n)->u.op & 0x40)
-
-extern Node *expr(void);
-extern void extdecl(void), decl(void);
-
-#endif
--- /dev/null
+++ b/cc1/.gitignore
@@ -1,0 +1,4 @@
+*.o
+makefile
+cc1
+TODO
--- /dev/null
+++ b/cc1/Makefile
@@ -1,0 +1,22 @@
+
+OBJS = types.o decl.o lex.o error.o symbol.o main.o expr.o \
+ wrapper.o code.o stmt.o
+
+CFLAGS += -fno-diagnostics-show-caret -g
+
+all: cc1
+
+$(OBJS) : cc1.h
+
+cc1: $(OBJS)
+ $(CC) $(LDFLAGS) $(CFLAGS) $(LIBS) $(OBJS) -o $@
+
+clean:
+ rm -f $(OBJS)
+ rm -f cc1
+
+distclean: clean
+ rm -f *~
+ rm -f tags
+ rm -f cscope.*
+ rm -f makefile
--- /dev/null
+++ b/cc1/cc1.h
@@ -1,0 +1,259 @@
+#ifndef CC_H
+#define CC_H
+
+#ifndef __bool_true_and_false_defined
+#include <stdbool.h>
+#endif
+
+
+struct user_opt {
+ unsigned char implicit;
+ unsigned char mixdcls;
+ unsigned char npromote;
+ unsigned char useless;
+ unsigned char charsign;
+ unsigned char pcompare;
+};
+
+extern struct user_opt options;
+
+extern void error(const char *fmt, ...);
+extern void die(const char *fmt, ...);
+extern void warn(signed char flag, const char *fmt, ...);
+extern void *xmalloc(size_t size);
+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_FREE
+};
+
+struct funpars;
+struct symbol;
+
+#define RANK_BOOL 0
+#define RANK_SCHAR 1
+#define RANK_UCHAR 2
+#define RANK_SHORT 3
+#define RANK_USHORT 4
+#define RANK_INT 5
+#define RANK_UINT 6
+#define RANK_LONG 7
+#define RANK_ULONG 8
+#define RANK_LLONG 9
+#define RANK_ULLONG 10
+#define RANK_FLOAT 11
+#define RANK_DOUBLE 12
+#define RANK_LDOUBLE 13
+
+struct ctype {
+ uint8_t op; /* type builder operator */
+ char letter; /* letter of the type */
+ bool defined : 1; /* type defined (is not a forward reference) */
+ bool 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 {
+ unsigned char rank; /* convertion rank */
+ short nelem; /* number of elements in arrays */
+ 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 */
+
+
+
+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;
+ bool isdefined : 1;
+ } s;
+ union {
+ int i;
+ char *s;
+ struct symbol *sym;
+ uint8_t ns, token;
+ } 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);
+
+typedef struct caselist Caselist;
+typedef void Ctxfun(Symbol *, Symbol *, Caselist *);
+
+extern Ctxfun compound;
+extern void context(Ctxfun *fun,
+ Symbol *lbreak, Symbol *lcont, Caselist *lswitch);
+
+extern Type *typename(void);
+
+extern Type *voidtype, *pvoidtype, *booltype,
+ *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 isqual(op) ((op) & TQUALIFIER)
+#define isconst(op) (((op) & (TQUALIFIER|CONST)) == \
+ (TQUALIFIER|CONST))
+
+
+enum {
+ FTN = 1, ENUM, TYPENAME, VOID, FLOAT, INT, BOOL,
+ STRUCT, UNION, PTR, ARY, CHAR, DOUBLE, SHORT,
+ LONG, COMPLEX, UNSIGNED, SIGNED
+};
+
+#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, STRING,
+ 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;
+ Type *utype;
+ uint8_t typeop;
+ struct {
+ bool lvalue : 1;
+ bool symbol: 1;
+ bool constant : 1;
+ } b;
+ union unode {
+ Symbol *sym;
+ Type *type;
+ char op;
+ } u;
+ struct node *childs[];
+} Node;
+
+enum {
+ OCAST = 1, OPTR, OADD, OARY, OSIZE, OMUL, OSUB,
+ OINC, ODEC, ODIV, OMOD, OSHL, OSHR,
+ OBAND, OBXOR, OBOR, OASSIGN, OA_MUL, OA_DIV,
+ OA_MOD, OA_ADD, OA_SUB, OA_SHL, OA_SHR,
+ OA_AND, OA_XOR, OA_OR, OADDR,ONEG, OCPL, OEXC,
+ OCOMMA,
+ /*
+ * Complementary relational operators only differ in less
+ * significant bit
+ */
+ OEQ = 0x40, ONE, OLT, OGE, OLE, OGT, OAND, OOR
+};
+
+extern void
+ emitdcl(Symbol *), emitsframe(Symbol *), emiteframe(Symbol *),
+ emitsym(Node *), emitunary(Node *),
+ emitbin(Node *), emitexp(Node *),
+ emitprint(Node *), emitlabel(Symbol *), emitjump(Symbol *, Node *),
+ emitbloop(void), emiteloop(void),
+ emitswitch(short, Node *), emitcase(Symbol *, Node *),
+ emitdefault(Symbol *);
+
+extern Node
+ *node(void (*code)(Node *),
+ 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),
+ *ternarycode(Node *cond, Node *ifyes, Node *ifno),
+ *symcode(Symbol *sym);
+
+#define SYM(s) ((union unode) {.sym = s})
+#define OP(s) ((union unode) {.op = s})
+#define TYP(s) ((union unode) {.type = s})
+#define NEGATE(n, v) ((n)->u.op ^= (v))
+/* TODO: remove some of these ugly macros */
+#define ISNODEBIN(n) ((n)->code == emitbin)
+#define ISNODECMP(n) (ISNODEBIN(n) && (n)->u.op & 0x40)
+
+extern Node *expr(void);
+extern void extdecl(void), decl(void);
+
+#endif
--- /dev/null
+++ b/cc1/code.c
@@ -1,0 +1,313 @@
+
+#include <stdint.h>
+#include <stdio.h>
+
+#include "cc1.h"
+
+char *opcodes[] = {
+ [OADD] = "+",
+ [OSUB] = "-",
+ [OMUL] = "*",
+ [OARY] = "'",
+ [OINC] = ";+",
+ [ODEC] = ";=",
+ [OSIZE] = "#",
+ [OPTR] = "@",
+ [OMOD] = "*",
+ [ODIV] = "/",
+ [OSHL] = "l",
+ [OSHR] = "r",
+ [OLT] = "<",
+ [OGT] = ">",
+ [OGE] = "]",
+ [OLE] = "[",
+ [OEQ] = "=",
+ [ONE] = "!",
+ [OBAND] = "&",
+ [OBXOR] = "^",
+ [OBOR] = "|",
+ [OASSIGN] = ":",
+ [OA_MUL] = ":*",
+ [OA_DIV] = ":/",
+ [OA_MOD] = ":%",
+ [OA_ADD] = ":+",
+ [OA_SUB] = ":-",
+ [OA_SHL] = ":l",
+ [OA_SHR] = ":r",
+ [OA_AND] = ":&",
+ [OA_XOR] = ":^",
+ [OA_OR] = ":|",
+ [OADDR] = "a",
+ [ONEG] = "_",
+ [OCPL] = "~",
+ [OAND] = "m",
+ [OOR] = "s",
+ [OCOMMA] = ","
+};
+
+Node *
+node(void (*code)(Node *), Type *tp, union unode u, uint8_t nchilds)
+{
+ Node *np = xmalloc(sizeof(*np) + nchilds * sizeof(np));
+
+ np->code = code;
+ np->type = tp;
+ np->utype = UNQUAL(tp);
+ np->typeop = np->utype->op;
+ np->u = u;
+ np->b.symbol = np->b.lvalue = 0;
+
+ return np;
+}
+
+static void
+emitsym2(Symbol *sym)
+{
+ char c;
+
+ if (sym->s.isglobal)
+ c = 'G';
+ else if (sym->s.isstatic)
+ c = 'T';
+ else if (sym->s.isregister)
+ c = 'Q';
+ else
+ c = 'A';
+ printf("%c%d", c, sym->id);
+}
+
+static void
+emitconst(Node *np)
+{
+ register char *bp, c;
+ Symbol *sym = np->u.sym;
+
+ if (np->type == inttype) {
+ printf("#%x", sym->u.i);
+ } else {
+ putchar('"');
+ for (bp = sym->u.s; c = *bp; ++bp)
+ printf("%02x", (unsigned) c);
+ }
+}
+
+void
+emitsym(Node *np)
+{
+ putchar('\t');
+ (np->b.constant) ? emitconst(np) : emitsym2(np->u.sym);
+}
+
+static void
+emittype(Type *tp)
+{
+ putchar(tp->letter);
+}
+
+void
+emitdcl(Symbol *sym)
+{
+ emitsym2(sym);
+ putchar('\t');
+ emittype(sym->type);
+ putchar('\n');
+}
+
+void
+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
+emitternary(Node *np)
+{
+ Node *cond, *ifyes, *ifno;
+
+ cond = np->childs[0];
+ ifyes = np->childs[1];
+ ifno = np->childs[2];
+ (*cond->code)(cond);
+ (*ifyes->code)(ifyes);
+ (*ifno->code)(ifno);
+ printf("\t?%c", np->type->letter);
+}
+
+void
+emitsizeof(Node *np)
+{
+ printf("\t#%c", np->u.type->letter);
+}
+
+void
+emitexp(Node *np)
+{
+ if (np)
+ (*np->code)(np);
+ putchar('\n');
+}
+
+void
+emitprint(Node *np)
+{
+ (*np->code)(np);
+ printf("\tk%c\n", np->type->letter);
+}
+
+void
+emitfun(Symbol *sym)
+{
+ printf("%c%d\tn%s\n",
+ sym->s.isglobal ? 'X' : 'Y', sym->id, sym->name);
+}
+
+void
+emitsframe(Symbol *sym)
+{
+ puts("{");
+}
+
+void
+emiteframe(Symbol *sym)
+{
+ puts("}");
+}
+
+void
+emitret(Type *tp)
+{
+ fputs("\ty", stdout);
+ emittype(tp);
+}
+
+void
+emitlabel(Symbol *sym)
+{
+ printf("L%d\n", sym->id);
+}
+
+void
+emitbloop(void)
+{
+ puts("\td");
+}
+
+void
+emiteloop(void)
+{
+ puts("\tb");
+}
+
+void
+emitjump(Symbol *sym, Node *np)
+{
+ printf("\tj\tL%d", sym->id);
+ if (!np)
+ putchar('\n');
+ else
+ emitexp(np);
+}
+
+void
+emitswitch(short nr, Node *np)
+{
+ printf("\teI\t#%0x", nr);
+ emitexp(np);
+}
+
+void
+emitcase(Symbol *sym, Node *np)
+{
+ fputs("\tw\t", stdout);
+ printf("L%d", sym->id);
+ emitexp(np);
+}
+
+void
+emitdefault(Symbol *sym)
+{
+ fputs("\tf\t", stdout);
+ emitlabel(sym);
+}
+
+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)
+{
+ if (!tp->defined)
+ error("invalid use of indefined type");
+ return node(emitsizeof, inttype, TYP(tp), 0);
+}
+
+Node *
+ternarycode(Node *cond, Node *ifyes, Node *ifno)
+{
+ Node *np= node(emitternary, ifyes->type, OP(0), 3);
+ np->childs[0] = cond;
+ np->childs[1] = ifyes;
+ np->childs[2] = ifno;
+ return np;
+}
+
+Node *
+symcode(Symbol *sym)
+{
+ Node *np;
+
+ np = node(emitsym, sym->type, SYM(sym), 0);
+ np->b.symbol = 1;
+ np->b.constant = 1;
+ return np;
+}
--- /dev/null
+++ b/cc1/decl.c
@@ -1,0 +1,536 @@
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "sizes.h"
+#include "cc1.h"
+
+#define ID_EXPECTED 1
+#define ID_ACCEPTED 2
+
+int8_t forbid_eof;
+
+struct dcldata {
+ uint8_t op;
+ union {
+ unsigned short nelem;
+ Symbol *sym;
+ struct funpars *pars;
+ uint8_t qlf;
+ } u;
+};
+
+static struct dcldata
+ *declarator0(struct dcldata *dp, uint8_t ns, int8_t flags);
+
+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 Symbol *
+newiden(uint8_t ns)
+{
+ Symbol *sym;
+ extern uint8_t curctx;
+
+ if (yylval.sym && yylval.sym->ctx == curctx)
+ error("redeclaration of '%s'", yytext);
+ sym = install(yytext, ns);
+ next();
+ return sym;
+}
+
+static struct dcldata *
+directdcl(struct dcldata *dp, uint8_t ns, int8_t flags)
+{
+ register Symbol *sym;
+ char *err;
+
+ if (accept('(')) {
+ dp = declarator0(dp, ns, flags);
+ expect(')');
+ } else if (flags) {
+ if (yytoken != IDEN) {
+ if (flags & ID_EXPECTED)
+ goto expected;
+ sym = install("", ns);
+ } else {
+ sym = newiden(ns);
+ }
+ dp->op = IDEN;
+ dp->u.sym = sym;
+ ++dp;
+ }
+
+ for (;;) {
+ switch (yytoken) {
+ case '(': dp = fundcl(dp); break;
+ case '[': dp = arydcl(dp); break;
+ default: return dp;
+ }
+ }
+
+expected:
+ error("expected '(' or identifier before of '%s'" , yytext);
+}
+
+static struct dcldata*
+declarator0(struct dcldata *dp, uint8_t ns, int8_t flags)
+{
+ uint8_t buffer[NR_DECLARATORS];
+ register uint8_t *bp, n, qlf;
+
+ bp = buffer;
+ for (n = 0; accept('*'); ++n) {
+ if (n == NR_DECLARATORS)
+ goto too_much_declarators;
+ qlf = 0;
+ if (yytoken == TQUALIFIER) {
+ qlf |= yylval.token;
+ next();
+ }
+ *bp++ = qlf;
+ }
+
+ dp = directdcl(dp, ns, flags);
+
+ bp = buffer;
+ while (n--) {
+ if (dp->op == 255)
+ goto too_much_declarators;
+ dp->op = PTR;
+ dp->u.qlf = *bp++;
+ ++dp;
+ }
+
+ return dp;
+
+too_much_declarators:
+ error("too much declarators");
+}
+
+static Symbol *
+declarator(Type *tp, uint8_t ns, int8_t flags)
+{
+ struct dcldata data[NR_DECLARATORS+1];
+ register struct dcldata *bp;
+ Symbol *sym = NULL;
+ static Symbol dummy;
+
+ memset(data, 0, sizeof(data));
+ 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;
+ }
+ }
+ if (!sym)
+ sym = &dummy;
+ sym->type = tp;
+ return sym;
+}
+
+static Type *structdcl(void), *enumdcl(void);
+
+static Type *
+specifier(int8_t *sclass)
+{
+ Type *tp = NULL;
+ int8_t qlf, sign, type, cls, size, t;
+
+ qlf = sign = type = cls = size = 0;
+
+ for (;;) {
+ register uint8_t *p;
+ Type *(*dcl)(void) = NULL;
+
+ switch (yytoken) {
+ case SCLASS: p = &cls; break;
+ case TQUALIFIER:
+ if ((qlf |= yylval.token) & RESTRICT)
+ goto invalid_type;
+ next();
+ continue;
+ case TYPE:
+ switch (yylval.token) {
+ case ENUM:
+ dcl = enumdcl; p = &type; break;
+ case STRUCT: case UNION:
+ dcl = structdcl; p = &type; break;
+ case TYPENAME:
+ tp = yylval.sym->type;
+ case VOID: case BOOL: case CHAR:
+ case INT: case FLOAT: case DOUBLE:
+ p = &type; break;
+ case SIGNED: case UNSIGNED:
+ p = &sign; break;
+ case LONG:
+ if (size == LONG) {
+ size = LONG+LONG;
+ break;
+ }
+ case SHORT:
+ p = &size; break;
+ }
+ break;
+ default:
+ goto check_types;
+ }
+ if (*p)
+ goto invalid_type;
+ *p = yylval.token;
+ if (dcl)
+ tp = dcl();
+ else
+ next();
+ }
+
+check_types:
+ if (!type) {
+ if (!sign && !size) {
+ warn(options.implicit,
+ "type defaults to 'int' in declaration");
+ }
+ type = INT;
+ }
+ if (sign && type != INT && type != CHAR ||
+ 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);
+ return (qlf) ? qualifier(tp, qlf) : tp;
+
+invalid_type:
+ error("invalid type specification");
+}
+
+static struct node *
+initializer(register Type *tp)
+{
+ if (accept('{')) {
+ initializer(tp);
+ expect('}');
+ } else {
+ do {
+ expr();
+ } while (accept(','));
+ }
+}
+
+/* TODO: bitfields */
+
+static void
+newfield(Type *tp, Symbol *sym)
+{
+ register struct field *p, *q;
+ register char *s, *t;
+ static uint8_t op;
+ static char *err;
+
+ s = sym->name;
+ op = tp->op;
+ for (q = p = tp->u.fields; p; q = p, p = p->next) {
+ t = p->sym->name;
+ if (*s == *t && !strcmp(s, t))
+ goto duplicated_name;
+ if (op == ENUM && sym->u.i == p->sym->u.i)
+ goto duplicated_value;
+ }
+
+ p = xmalloc(sizeof(*p));
+ p->next = NULL;
+ p->sym = sym;
+ if (!q)
+ tp->u.fields = p;
+ else
+ q->next = p;
+
+ return;
+
+duplicated_name:
+ err = "duplicated fields '%s' and '%s'";
+ goto error;
+duplicated_value:
+ err = "duplicated enumeration fields '%s' and '%s'";
+error:
+ error(err, s, t);
+}
+
+static void
+fielddcl(Type *base, uint8_t ns)
+{
+ Type *tp;
+ Symbol *sym;
+ char *err;
+
+ switch (yytoken) {
+ case SCLASS:
+ goto bad_storage;
+ case IDEN: case TYPE: case TQUALIFIER:
+ tp = specifier(NULL);
+ case ';':
+ break;
+ default:
+ goto dcl_expected;
+ }
+
+ if (yytoken != ';') {
+ do {
+ sym = declarator(tp, ns, ID_EXPECTED);
+ newfield(tp, sym);
+ } while (accept(','));
+ }
+
+ expect(';');
+ return;
+
+bad_storage:
+ err = "storage class '%s' in struct/union field";
+ goto error;
+dcl_expected:
+ err = "declaration expected";
+error:
+ error(err, yytext);
+}
+
+static Type *
+newtag(uint8_t tag)
+{
+ register Symbol *sym;
+ Type *tp;
+ extern uint8_t namespace;
+
+ if (yytoken == IDEN) {
+ sym = lookup(yytext, NS_TAG);
+ if (sym) {
+ if (sym->type->op != tag)
+ goto bad_tag;
+ } else {
+ sym = install(yytext, NS_TAG);
+ }
+ next();
+ } else {
+ sym = install("", NS_TAG);
+ }
+ tp = sym->type = mktype(NULL, tag, NULL, 0);
+ sym->u.ns = ++namespace;
+ tp->sym = sym;
+ return tp;
+
+bad_tag:
+ error("'%s' defined as wrong kind of tag", yytext);
+}
+
+static Type *
+structdcl(void)
+{
+ Type *tp;
+ uint8_t ns, tag;
+
+ tag = yylval.token;
+ next();
+ tp = newtag(tag);
+ tp->u.fields = NULL;
+ ns = tp->sym->u.ns;
+ if (accept('{')) {
+ if (tp->defined)
+ goto redefined;
+ tp->defined = 1;
+ while (!accept('}'))
+ fielddcl(tp, ns);
+ }
+
+ return tp;
+
+redefined:
+ error("redefinition of struct/union '%s'", yytext);
+}
+
+static Type *
+enumdcl(void)
+{
+ register Type *tp;
+ Symbol *sym;
+ int val = 0;
+ char *err;
+
+ next();
+ tp = newtag(ENUM);
+ if (yytoken != ';') {
+ expect('{');
+ if (tp->defined)
+ goto redefined;
+ tp->defined = 1;
+ while (yytoken != '}') {
+ if (yytoken != IDEN)
+ goto iden_expected;
+ sym = newiden(NS_IDEN);
+ sym->type = inttype;
+ if (accept('='))
+ initializer(inttype);
+ sym->u.i = val++;
+ newfield(tp, sym);
+ if (!accept(','))
+ break;
+ }
+ expect('}');
+ }
+
+ return tp;
+
+redefined:
+ err = "redefinition of enumeration '%s'";
+ goto error;
+iden_expected:
+ err = "identifier expected";
+error:
+ error(err, yytext);
+}
+
+void
+decl(void)
+{
+ Type *tp;
+ Symbol *sym;
+ int8_t sclass;
+
+ tp = specifier(&sclass);
+ if (yytoken != ';') {
+ do {
+ sym = declarator(tp, NS_IDEN, ID_EXPECTED);
+ switch (sclass) {
+ case REGISTER: sym->s.isregister = 1; break;
+ case STATIC: sym->s.isstatic = 1; break;
+ case EXTERN: /* TODO: */; break;
+ case TYPEDEF: /* TODO: */;break;
+ case AUTO: default: sym->s.isauto = 1;
+ }
+ if (accept('='))
+ initializer(sym->type); /* TODO: emit initializer */
+ emitdcl(sym);
+ } while (accept(','));
+ }
+ expect(';');
+}
+
+Type *
+typename(void)
+{
+ uint8_t sclass;
+ Type *tp;
+ Symbol *sym;
+
+ tp = specifier(&sclass);
+ if (sclass)
+ error("class storage in type name");
+ sym = declarator(tp, NS_IDEN, 0);
+ return sym->type;
+}
+
+void
+extdecl(void)
+{
+ Type *base;
+ int8_t sclass;
+ Symbol *sym;
+ char *err;
+
+ forbid_eof = 0; /* TODO: Fix when find EOF */
+
+ switch (yytoken) {
+ case IDEN: case TYPE: case SCLASS: case TQUALIFIER:
+ base = specifier(&sclass);
+ if (sclass == REGISTER || sclass == AUTO)
+ goto bad_storage;
+ case ';':
+ break;
+ case '@':
+ next();
+ emitprint(expr());
+ goto semicolon;
+ default:
+ goto dcl_expected;
+ }
+
+ if (yytoken != ';') {
+ do {
+ Type *tp;
+
+ sym = declarator(base, NS_IDEN, ID_EXPECTED);
+ tp = sym->type;
+
+ if (!(sclass & STATIC))
+ sym->s.isglobal = 1;
+ if (BTYPE(tp) == FTN) {
+ if (yytoken == '{') {
+ extern Symbol *curfun;
+
+ curfun = sym;
+ emitfun(sym);
+ emitsframe(sym);
+ context(compound, NULL, NULL, NULL);
+ emiteframe(sym); /* FIX: sym is not used */
+ freesyms(NS_LABEL);
+ return;
+ }
+ } else {
+ sym->s.isstatic = 1;
+ if (sclass & EXTERN)
+ ; /* TODO: handle extern */
+ else if (accept('='))
+ initializer(tp);
+ emitdcl(sym);
+
+ }
+ } while (accept(','));
+ }
+
+semicolon:
+ expect(';');
+ return;
+
+bad_storage:
+ err = "incorrect storage class for file-scope declaration";
+ goto error;
+dcl_expected:
+ err = "declaration expected";
+error:
+ error(err);
+}
--- /dev/null
+++ b/cc1/error.c
@@ -1,0 +1,52 @@
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "cc1.h"
+
+extern unsigned linenum;
+extern unsigned columnum;
+extern const char *filename;
+
+static void
+warn_helper(signed char flag, const char *fmt, va_list va)
+{
+ if (!flag)
+ return;
+ fprintf(stderr, "%s:%s:%u: ",
+ (!flag) ? "warning" : "error", filename, linenum);
+ vfprintf(stderr, fmt, va);
+ putc('\n', stderr);
+ if (flag < 0)
+ exit(EXIT_FAILURE); /* TODO: uhmmmm */
+}
+
+void
+warn(signed char flag, const char *fmt, ...)
+{
+ va_list va;
+ va_start(va, fmt);
+ warn_helper(flag, fmt, va);
+ va_end(va);
+}
+
+void
+error(const char *fmt, ...)
+{
+ va_list va;
+ va_start(va, fmt);
+ warn_helper(-1, fmt, va);
+ va_end(va);
+}
+
+void
+die(const char *fmt, ...)
+{
+ va_list va;
+ va_start(va, fmt);
+ fprintf(stderr, fmt, va);
+ va_end(va);
+ exit(EXIT_FAILURE);
+}
--- /dev/null
+++ b/cc1/expr.c
@@ -1,0 +1,758 @@
+#include <stdint.h>
+#include <stdio.h>
+
+#include "cc1.h"
+
+static Symbol *zero, *one;
+
+Node *expr(void);
+
+void
+init_expr(void)
+{
+ static Symbol dummy0, dummy1;
+
+ dummy0.type = dummy1.type = inttype;
+ dummy0.u.i = 0;
+ dummy1.u.i = 1;
+ zero = &dummy0;
+ one = &dummy1;
+}
+
+static Node *
+promote(Node *np)
+{
+ Type *tp;
+ uint8_t r;
+
+ if (options.npromote)
+ return np;
+ tp = np->utype;
+ r = tp->u.rank;
+ if (r > RANK_UINT || tp == inttype || tp == uinttype)
+ return np;
+ return castcode(np, (r == RANK_UINT) ? uinttype : inttype);
+}
+
+static void
+typeconv(Node **p1, Node **p2)
+{
+ Type *tp1, *tp2;
+ Node *np1, *np2;
+ int8_t n;
+
+ np1 = promote(*p1);
+ np2 = promote(*p2);
+
+ tp1 = np1->utype;
+ tp2 = np2->utype;
+ if (tp1 != tp2) {
+ if ((n = tp1->u.rank - tp2->u.rank) > 0)
+ np2 = castcode(np2, tp1);
+ else if (n < 0)
+ np1 = castcode(np1, tp2);
+ }
+ *p1 = np1;
+ *p2 = np2;
+}
+
+Node *
+eval(Node *np)
+{
+ if (!ISNODECMP(np))
+ return np;
+ return ternarycode(np, symcode(one), symcode(zero));
+}
+
+static Node *
+integerop(char op, Node *np1, Node *np2)
+{
+ np1 = eval(np1);
+ np2 = eval(np2);
+ if (np1->typeop != INT || np2->typeop != INT)
+ error("operator requires integer operands");
+ typeconv(&np1, &np2);
+ return bincode(op, np1->type, np1, np2);
+}
+
+static Node *
+integeruop(char op, Node *np)
+{
+ np = eval(np);
+ if (np->typeop != INT)
+ error("unary operator requires integer operand");
+ return unarycode(op, np->type, np);
+}
+
+static Node *
+addr2ptr(Node *np)
+{
+ Type *tp;
+
+ tp = mktype(np->utype->type, PTR, NULL, 0);
+ return unarycode(OADDR, tp, np);
+}
+
+/*
+ * Convert a Node to a type
+ */
+Node *
+convert(Node *np, Type *tp, char iscast)
+{
+ Type *utp;
+ uint8_t t;
+
+ if (np->type == tp)
+ return np;
+
+ utp = UNQUAL(tp);
+ t = utp->op;
+
+ switch (np->typeop) {
+ case ENUM: case INT: case FLOAT:
+ switch (t) {
+ case PTR:
+ if (!iscast || np->typeop == FLOAT)
+ return NULL;
+ case INT: case FLOAT: case ENUM: case VOID:
+ break;
+ default:
+ return NULL;
+ }
+ break;
+ case PTR:
+ switch (t) {
+ case ENUM: case INT: case VOID: /* TODO: allow p = 0 */
+ if (!iscast)
+ return NULL;;
+ break;
+ case ARY: case FTN:
+ np = addr2ptr(np);
+ case PTR:
+ if (iscast ||
+ utp == pvoidtype ||
+ np->utype == pvoidtype) {
+ /* TODO:
+ * we assume conversion between pointers
+ * do not need any operation, but due to
+ * alignment problems that may be false
+ */
+ np->type = tp;
+ np->utype = utp;
+ return np;
+ }
+ default:
+ return NULL;
+ }
+ default:
+ return NULL;
+ }
+ return castcode(np, tp);
+}
+
+static Node *
+parithmetic(char op, Node *np1, Node *np2)
+{
+ Type *tp;
+ Node *size;
+ char *err;
+
+ tp = np1->utype;
+ size = sizeofcode(tp->type);
+ if (np2->typeop == ARY)
+ np2 = addr2ptr(np2);
+
+ if (op == OSUB && np2->typeop == PTR) {
+ if (tp != np2->utype)
+ goto incorrect;
+ np1 = bincode(OSUB, inttype, np1, np2);
+ return bincode(ODIV, inttype, np1, size);
+ }
+ if (np2->typeop != INT)
+ goto incorrect;
+ np2 = castcode(promote(np2), tp);
+ np2 = bincode(OMUL, tp, np2, size);
+ return bincode(op, tp, np1, np2);
+
+incorrect:
+ error("incorrect arithmetic operands");
+}
+
+static Node *
+arithmetic(char op, Node *np1, Node *np2)
+{
+ np1 = eval(np1);
+ np2 = eval(np2);
+ switch (np1->typeop) {
+ case INT: case FLOAT:
+ switch (np2->typeop) {
+ case INT: case FLOAT:
+ typeconv(&np1, &np2);
+ break;
+ case ARY:
+ np2 = addr2ptr(np2);
+ case PTR:
+ if (op == OADD || op == OSUB)
+ return parithmetic(op, np2, np1);
+ default:
+ goto incorrect;
+ }
+ break;
+ case ARY:
+ np1 = addr2ptr(np1);
+ case PTR:
+ return parithmetic(op, np1, np2);
+ default:
+ incorrect:
+ error("incorrect arithmetic operands");
+ }
+
+ return bincode(op, np1->type, np1, np2);
+}
+
+/*
+ * FIXME:
+ * Pointers to the same basic type after removing type qualifiers
+ * can be compared. It means that utype pointer must be a field
+ * of the type, not of the Node, because in other case is
+ * hard doing this check
+ */
+static Node *
+pcompare(char op, Node *np1, Node *np2)
+{
+ if (np2->typeop == INT && np2->b.symbol && np2->u.sym->u.i == 0) {
+ np2 = castcode(np2, pvoidtype);
+ } else if (np2->typeop != PTR) {
+ error("incompatibles type in comparision");
+ } else {
+ warn(options.pcompare,
+ "comparision between different pointer types");
+ }
+
+ return bincode(op, np1->type, np1, np2);
+}
+
+static Node *
+compare(char op, Node *np1, Node *np2)
+{
+ np1 = eval(np1);
+ np2 = eval(np2);
+ switch (np1->typeop) {
+ case INT: case FLOAT:
+ switch (np1->typeop) {
+ case INT: case FLOAT:
+ typeconv(&np1, &np2);
+ break;
+ case ARY: case FTN:
+ np2 = addr2ptr(np2);
+ case PTR:
+ return pcompare(op, np2, np1);
+ default:
+ goto nocompat;
+ }
+ break;
+ case ARY: case FTN:
+ np1 = addr2ptr(np1);
+ case PTR:
+ return pcompare(op, np1, np2);
+ default:
+ nocompat:
+ error("incompatibles type in comparision");
+ }
+
+ return bincode(op, inttype, np1, np2);
+}
+
+static Node *
+exp2cond(Node *np, char neg)
+{
+ if (ISNODECMP(np)) {
+ NEGATE(np, neg);
+ return np;
+ }
+
+ return compare(ONE ^ neg, np, symcode(zero));
+}
+
+static Node *
+logic(char op, Node *np1, Node *np2)
+{
+ np1 = exp2cond(np1, 0);
+ np2 = exp2cond(np2, 0);
+ return bincode(op, inttype, np1, np2);
+}
+
+static Node *
+array(Node *np1, Node *np2)
+{
+ Type *tp;
+ char *err;
+
+ if (np1->typeop != INT && np2->typeop != INT)
+ goto bad_subs;
+ np1 = arithmetic(OADD, np1, np2);
+ tp = np1->type;
+ if (tp->op != PTR)
+ goto bad_vector;
+ np1 = unarycode(OARY, tp->type , np1);
+ np1->b.lvalue = 1;
+ return 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);
+}
+
+Node *
+iszero(Node *np)
+{
+ if (ISNODECMP(np))
+ return np;
+ return compare(ONE, np, symcode(zero));
+}
+
+static Node *
+assignop(char op, Node *np1, Node *np2)
+{
+ if ((np2 = convert(np2, np1->type, 0)) == NULL)
+ error("incompatible types when assigning");
+ return bincode(op, np1->type, np1, np2);
+}
+
+static Node *
+incdec(Node *np, char op)
+{
+ char *err;
+ Type *tp = np->utype;
+
+ if (!np->b.lvalue)
+ goto nolvalue;
+ if (np->utype == voidtype)
+ goto voidassign;
+ if (isconst(tp->op))
+ goto const_mod;
+
+ switch (np->typeop) {
+ case PTR:
+ if (!tp->defined)
+ goto nocomplete;
+ case INT: case FLOAT:
+ return arithmetic(op, np, symcode(one));
+ default:
+ goto bad_type;
+ }
+
+voidassign:
+ err = "invalid use of void expression";
+ goto error;
+nolvalue:
+ err = "lvalue required in operation";
+ goto error;
+nocomplete:
+ err = "invalid use of indefined type";
+ goto error;
+bad_type:
+ err = "incorrect type in arithmetic operation";
+ goto error;
+const_mod:
+ err = "const value modified";
+error:
+ error(err);
+}
+
+static Node *
+address(char op, Node *np)
+{
+ char *err;
+
+ if (!np->b.lvalue)
+ goto no_lvalue;
+ if (np->b.symbol && np->u.sym->s.isregister)
+ goto reg_address;
+ return unarycode(op, mktype(np->type, PTR, NULL, 0), np);
+
+no_lvalue:
+ err = "lvalue required in unary expression";
+ goto error;
+reg_address:
+ err = "address of register variable '%s' requested";
+error:
+ error(err);
+}
+
+static Node *
+content(char op, Node *np)
+{
+ switch (np->typeop) {
+ case ARY: case FTN:
+ np = addr2ptr(np);
+ case PTR:
+ np = unarycode(op, np->utype->type, np);
+ np->b.lvalue = 1;
+ return np;
+ default:
+ error("invalid argument of unary '*'");
+ }
+}
+
+static Node *
+negation(char op, Node *np)
+{
+ switch (np->typeop) {
+ case FTN: case ARY:
+ np = addr2ptr(np);
+ case INT: case FLOAT: case PTR:
+ return exp2cond(np, 1);
+ default:
+ error("invalid argument of unary '!'");
+ }
+}
+
+/*************************************************************
+ * grammar functions *
+ *************************************************************/
+static Node *
+primary(void)
+{
+ Node *np;
+ Symbol *sym;
+
+ switch (yytoken) {
+ case STRING: case CONSTANT: case IDEN:
+ if ((sym = yylval.sym) == NULL)
+ error("'%s' undeclared", yytext);
+ np = symcode(yylval.sym);
+ if (yytoken == IDEN) {
+ np->b.lvalue = 1;
+ np->b.constant = 0;
+ }
+ next();
+ break;
+ case '(':
+ next();
+ np = expr();
+ expect(')');
+ break;
+ default:
+ error("unexpected '%s'", yytext);
+ }
+ return np;
+}
+
+static Node *
+postfix(void)
+{
+ register Node *np1, *np2;
+
+ np1 = primary();
+ for (;;) {
+ switch (yytoken) {
+ case '[':
+ next();
+ np2 = expr();
+ np1 = array(np1, np2);
+ expect(']');
+ break;
+ case DEC: case INC:
+ np1 = incdec(np1, (yytoken == INC) ? OINC : ODEC);
+ next();
+ break;
+ /* TODO: case '.': */
+ /* TODO: case INDIR: */
+ /* TODO: case '(' */
+ default:
+ return np1;
+ }
+ }
+}
+
+static Node *cast(void);
+
+static Node *
+unary(void)
+{
+ register Node *(*fun)(char, Node *);
+ register char op;
+ Type *tp;
+ char *err;
+
+ switch (yytoken) {
+ case SIZEOF:
+ next();
+ if (yytoken == '(' && ahead() == TYPE) {
+ next();
+ tp = typename();
+ expect(')');
+ } else {
+ tp = unary()->type;
+ /* TODO: Free memory */
+ }
+ return sizeofcode(tp);
+ case INC: case DEC:
+ op = (yytoken == INC) ? OA_ADD : OA_SUB;
+ next();
+ return incdec(unary(), op);
+ case '!': op = 0; fun = negation; break;
+ case '+': op = OADD; fun = integeruop; break;
+ case '-': op = OSUB; fun = integeruop; break;
+ case '~': op = ONEG; fun = integeruop; break;
+ case '&': op = OADDR; fun = address; break;
+ case '*': op = OPTR; fun = content; break;
+ default: return postfix();
+ }
+
+ next();
+ return (*fun)(op, cast());
+}
+
+static Node *
+cast(void)
+{
+ Type *tp;
+ register Node *np1, *np2;
+
+ if (yytoken == '(') {
+ switch(ahead()) {
+ case TQUALIFIER: case TYPE:
+ next();
+ tp = typename();
+ expect(')');
+ np1 = eval(cast());
+ if ((np2 = convert(np1, tp, 1)) == NULL)
+ error("bad type convertion requested");
+ np2->b.lvalue = np1->b.lvalue;
+ return np2;
+ default:
+ break;
+ }
+ }
+
+ return unary();
+}
+
+static Node *
+mul(void)
+{
+ register Node *np, *(*fun)(char, Node *, Node *);
+ register char op;
+
+ np = cast();
+ for (;;) {
+ switch (yytoken) {
+ case '*': op = OMUL; fun = arithmetic; break;
+ case '/': op = ODIV; fun = arithmetic; break;
+ case '%': op = OMOD; fun = integerop; break;
+ default: return np;
+ }
+ next();
+ np = (*fun)(op, np, cast());
+ }
+}
+
+static Node *
+add(void)
+{
+ register char op;
+ register Node *np;
+
+ np = mul();
+ for (;;) {
+ switch (yytoken) {
+ case '+': op = OADD; break;
+ case '-': op = OSUB; break;
+ default: return np;
+ }
+ next();
+ np = arithmetic(op, np, mul());
+ }
+}
+
+static Node *
+shift(void)
+{
+ register char op;
+ register Node *np;
+
+ np = add();
+ for (;;) {
+ switch (yytoken) {
+ case SHL: op = OSHL; break;
+ case SHR: op = OSHR; break;
+ default: return np;
+ }
+ next();
+ np = integerop(op, np, add());
+ }
+}
+
+static Node *
+relational(void)
+{
+ register char op;
+ register Node *np;
+
+ np = shift();
+ for (;;) {
+ switch (yytoken) {
+ case '<': op = OLT; break;
+ case '>': op = OGT; break;
+ case GE: op = OGE; break;
+ case LE: op = OLE; break;
+ default: return np;
+ }
+ next();
+ np = compare(op, np, shift());
+ }
+}
+
+static Node *
+eq(void)
+{
+ register char op;
+ register Node *np;
+
+ np = relational();
+ for (;;) {
+ switch (yytoken) {
+ case EQ: op = OEQ; break;
+ case NE: op = ONE; break;
+ default: return np;
+ }
+ next();
+ np = compare(op, np, relational());
+ }
+}
+
+static Node *
+bit_and(void)
+{
+ register Node *np;
+
+ np = eq();
+ while (accept('&'))
+ np = integerop(OBAND, np, eq());
+ return np;
+}
+
+static Node *
+bit_xor(void)
+{
+ register Node *np;
+
+ np = bit_and();
+ while (accept('^'))
+ np = integerop(OBXOR, np, bit_and());
+ return np;
+}
+
+static Node *
+bit_or(void)
+{
+ register Node *np;
+
+ np = bit_xor();
+ while (accept('|'))
+ np = integerop(OBOR, np, bit_xor());
+ return np;
+}
+
+static Node *
+and(void)
+{
+ register Node *np;
+
+ np = bit_or();
+ while (accept(AND))
+ np = logic(OAND, np, bit_or());
+ return np;
+}
+
+static Node *
+or(void)
+{
+ register Node *np;
+
+ np = and();
+ while (accept(OR))
+ np = logic(OOR, np, and());
+ return np;
+}
+
+static Node *
+ternary(void)
+{
+ Node *np, *ifyes, *ifno;
+
+ np = or();
+ while (accept('?')) {
+ ifyes = promote(expr());
+ expect(':');
+ ifno = promote(ternary());
+ typeconv(&ifyes, &ifno);
+ np = ternarycode(iszero(np), ifyes, ifno);
+ }
+ return np;
+}
+
+static Node *
+assign(void)
+{
+ register Node *np, *(*fun)(char , Node *, Node *);
+ register char op;
+ char *err;
+
+ np = ternary();
+ for (;;) {
+ switch (yytoken) {
+ case '=': op = OASSIGN; fun = assignop; break;
+ case MUL_EQ: op = OA_MUL; fun = arithmetic; break;
+ case DIV_EQ: op = OA_DIV; fun = arithmetic; break;
+ case MOD_EQ: op = OA_MOD; fun = integerop; break;
+ case ADD_EQ: op = OA_ADD; fun = arithmetic; break;
+ case SUB_EQ: op = OA_SUB; fun = arithmetic; break;
+ case SHL_EQ: op = OA_SHL; fun = integerop; break;
+ case SHR_EQ: op = OA_SHR; fun = integerop; break;
+ case AND_EQ: op = OA_AND; fun = integerop; break;
+ case XOR_EQ: op = OA_XOR; fun = integerop; break;
+ case OR_EQ: op = OA_OR; fun = integerop; break;
+ default: return np;
+ }
+ if (!np->b.lvalue)
+ goto nolvalue;
+ if (np->utype == voidtype)
+ goto voidassign;
+ if (isconst(np->type->op))
+ goto const_mod;
+ next();
+ np = (fun)(op, np, eval(assign()));
+ }
+voidassign:
+ err = "invalid use of void expression";
+ goto error;
+const_mod:
+ err = "const value modified";
+ goto error;
+nolvalue:
+ err = "lvalue required as left operand of assignment";
+ goto error;
+error:
+ error(err);
+}
+
+Node *
+expr(void)
+{
+ register Node *np1, *np2;
+
+ np1 = assign();
+ while (accept(',')) {
+ np2 = assign();
+ np1 = bincode(OCOMMA, np2->type, np1, np2);
+ }
+
+ return np1;
+}
--- /dev/null
+++ b/cc1/lex.c
@@ -1,0 +1,438 @@
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "cc1.h"
+#include "sizes.h"
+
+static FILE *yyin;
+const char *filename;
+unsigned linenum;
+
+uint8_t yytoken, yyntoken;;
+union yystype yylval;
+char yytext[IDENTSIZ + 1];
+
+static union yystype yynlval;
+static char yybuf[IDENTSIZ + 1];
+
+static uint8_t
+integer(char *s, char base)
+{
+ static Type *tp;
+ static Symbol *sym;
+ static char ch, size, sign;
+ static long v;
+
+ size = sign = 0;
+type:
+ switch (ch = toupper(getc(yyin))) {
+ case 'L':
+ if (size == LONG + LONG)
+ goto wrong_type;
+ size += LONG;
+ goto type;
+ case 'U':
+ if (sign == UNSIGNED)
+ goto wrong_type;
+ goto type;
+ default:
+ ungetc(ch, yyin);
+ tp = ctype(INT, sign, size);
+ break;
+ wrong_type:
+ error("invalid suffix in integer constant");
+ }
+
+ sym = install("", NS_IDEN);
+ sym->type = tp;
+ v = strtol(yybuf, NULL, base);
+ if (tp == inttype)
+ sym->u.i = v;
+ yynlval.sym = sym;
+ return CONSTANT;
+}
+
+static uint8_t
+number(void)
+{
+ register char ch, *bp;
+ static char base;
+
+ if ((ch = getc(yyin)) == '0') {
+ if (toupper(ch = getc(yyin)) == 'X') {
+ base = 16;
+ } else {
+ base = 8;
+ ungetc(ch, yyin);
+ }
+ } else {
+ base = 10;
+ ungetc(ch, yyin);
+ }
+
+ for (bp = yybuf ; bp < &yybuf[IDENTSIZ]; *bp++ = ch) {
+ ch = getc(yyin);
+ switch (base) {
+ case 8:
+ if (ch >= '7')
+ goto end;
+ /* passthru */
+ case 10:
+ if (!isdigit(ch))
+ goto end;
+ break;
+ case 16:
+ if (!isxdigit(ch))
+ goto end;
+ break;
+ }
+ }
+
+end:
+ if (bp == &yybuf[IDENTSIZ])
+ error("identifier too long %s", yybuf);
+ *bp = '\0';
+ ungetc(ch, yyin);
+ return integer(yybuf, base);
+}
+
+static char *
+escape(char *s)
+{
+ char c;
+
+repeat:
+ switch (getc(yyin)) {
+ case '\\': c = '\''; break;
+ case 'a': c = '\a'; break;
+ case 'f': c = '\f'; break;
+ case 'n': c = '\n'; break;
+ case 'r': c = '\r'; break;
+ case 't': c = '\t'; break;
+ case 'v': c = '\v'; break;
+ case '\'': c = '\\'; break;
+ case '"': c ='"'; break;
+ case '?': c = '?'; break;
+ case 'x': /* TODO: */
+ case '0': /* TODO: */
+ case 'u': /* TODO: */
+ case '\n':
+ ++linenum;
+ if ((c = getc(yyin)) == '\\')
+ goto repeat;
+ break;
+ default:
+ warn(1, "unknown escape sequence");
+ return s;
+ }
+
+ *s = c;
+ return ++s;
+}
+
+static uint8_t
+character(void)
+{
+ static char c;
+ register Symbol *sym;
+
+ getc(yyin); /* discard the initial ' */
+ c = getc(yyin);
+ if (c == '\\')
+ escape(&c);
+ if (getc(yyin) != '\'')
+ error("invalid character constant");
+ sym = install("", NS_IDEN);
+ sym->u.i = c;
+ sym->type = inttype;
+ yynlval.sym = sym;
+ return CONSTANT;
+}
+
+static uint8_t
+string(void)
+{
+ static char buf[STRINGSIZ+1];
+ register char *bp;
+ register int c;
+ static Symbol *sym;
+
+ getc(yyin); /* discard the initial " */
+
+ for (bp = buf; bp < &buf[STRINGSIZ]; ) {
+ switch (c = getc(yyin)) {
+ case EOF:
+ error("found EOF while parsing");
+ case '"':
+ goto end_string;
+ case '\\':
+ bp = escape(bp);
+ break;
+ default:
+ *bp++ = c;
+ }
+ }
+
+end_string:
+ if (bp == &buf[IDENTSIZ])
+ error("string too long");
+ *bp = '\0';
+ sym = install("", NS_IDEN);
+ sym->u.s = xstrdup(buf);
+ sym->type = mktype(chartype, PTR, NULL, 0);
+ yynlval.sym = sym;
+ return STRING;
+}
+
+void
+init_keywords(void)
+{
+ static struct {
+ char *str;
+ uint8_t token, value;
+ } *bp, buff[] = {
+ {"auto", SCLASS, AUTO},
+ {"break", BREAK, BREAK},
+ {"_Bool", TYPE, BOOL},
+ {"case", CASE, CASE},
+ {"char", TYPE, CHAR},
+ {"const", TQUALIFIER, CONST},
+ {"continue", CONTINUE, CONTINUE},
+ {"default", DEFAULT, DEFAULT},
+ {"do", DO, DO},
+ {"double", TYPE, DOUBLE},
+ {"else", ELSE, ELSE},
+ {"enum", TYPE, ENUM},
+ {"extern", SCLASS, EXTERN},
+ {"float", TYPE, FLOAT},
+ {"for", FOR, FOR},
+ {"goto", GOTO, GOTO},
+ {"if", IF, IF},
+ {"int", TYPE, INT},
+ {"long", TYPE, LONG},
+ {"register", SCLASS, REGISTER},
+ {"restrict", TQUALIFIER, RESTRICT},
+ {"return", RETURN, RETURN},
+ {"short", TYPE, SHORT},
+ {"signed", TYPE, SIGNED},
+ {"sizeof", SIZEOF, SIZEOF},
+ {"static", SCLASS, STATIC},
+ {"struct", TYPE, STRUCT},
+ {"switch", SWITCH, SWITCH},
+ {"typedef", SCLASS, TYPEDEF},
+ {"union", TYPE, UNION},
+ {"unsigned", TYPE, UNSIGNED},
+ {"void", TYPE, VOID},
+ {"volatile", TQUALIFIER, VOLATILE},
+ {"while", WHILE, WHILE},
+ {NULL, 0, 0},
+ };
+ register Symbol *sym;
+ extern short symid;
+
+ for (bp = buff; bp->str; ++bp) {
+ sym = install(bp->str, NS_IDEN);
+ sym->token = bp->token;
+ sym->u.token = bp->value;
+ }
+ symid = 0;
+}
+
+static uint8_t
+iden(void)
+{
+ register char *bp;
+ register int c;
+ Symbol *sym;
+
+ 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(c, yyin);
+
+ sym = lookup(yybuf, NS_IDEN);
+ if (!sym || sym->token == IDEN) {
+ yynlval.sym = sym;
+ return IDEN;
+ }
+ yynlval.token = sym->u.token;
+ return sym->token;
+}
+
+static uint8_t
+follow(int expect, int ifyes, int ifno)
+{
+ register int c = getc(yyin);
+
+ if (c == expect) {
+ yybuf[1] = c;
+ yybuf[2] = 0;
+ return ifyes;
+ }
+ ungetc(c, yyin);
+ return ifno;
+}
+
+static uint8_t
+minus(void)
+{
+ register int c = getc(yyin);
+
+ yybuf[1] = c;
+ yybuf[2] = '\0';
+ switch (c) {
+ case '-': return DEC;
+ case '>': return INDIR;
+ case '=': return SUB_EQ;
+ default:
+ yybuf[1] = '\0';
+ ungetc(c, yyin);
+ return '-';
+ }
+}
+
+static uint8_t
+plus(void)
+{
+ register int c = getc(yyin);
+
+ yybuf[1] = c;
+ yybuf[2] = '\0';
+ switch (c) {
+ case '+': return INC;
+ case '=': return ADD_EQ;
+ default:
+ yybuf[1] = '\0';
+ ungetc(c, yyin);
+ return '+';
+ }
+}
+
+static uint8_t
+relational(uint8_t op, uint8_t equal, uint8_t shift, uint8_t assig)
+{
+ register int c = getc(yyin);
+
+ yybuf[1] = c;
+ yybuf[2] = '\0';
+
+ if (c == '=')
+ return equal;
+ if (c == op)
+ return follow('=', assig, shift);
+ ungetc(c, yyin);
+ yybuf[1] = '\0';
+ return op;
+}
+
+static uint8_t
+logic(uint8_t op, uint8_t equal, uint8_t logic)
+{
+ register int c = getc(yyin);
+
+ yybuf[1] = c;
+ yybuf[2] = '\0';
+
+ if (c == '=')
+ return equal;
+ if (c == op)
+ return logic;
+ ungetc(c, yyin);
+ yybuf[1] = '\0';
+ return op;
+}
+
+static uint8_t
+operator(void)
+{
+ register uint8_t c = getc(yyin);
+
+ yybuf[0] = c;
+ yybuf[1] = '\0';
+ switch (c) {
+ case '<': return relational('<', LE, SHL, SHL_EQ);
+ case '>': return relational('>', GE, SHR, SHR_EQ);
+ case '&': return logic('&', AND_EQ, AND);
+ case '|': return logic('|', OR_EQ, OR);
+ case '=': return follow('=', EQ, '=');
+ case '^': return follow('=', XOR_EQ, '^');
+ case '*': return follow('=', MUL_EQ, '*');
+ case '/': return follow('=', DIV_EQ, '/');
+ case '!': return follow('=', NE, '!');
+ case '-': return minus();
+ case '+': return plus();
+ default: return c;
+ }
+}
+
+uint8_t
+next(void)
+{
+ static int c;
+ extern int8_t forbid_eof;
+
+ strcpy(yytext, yybuf);
+ yylval = yynlval;
+ if ((yytoken = yyntoken) == EOFTOK) {
+ if (forbid_eof)
+ error("Find EOF while parsing");
+ goto ret;
+ }
+
+ while (isspace(c = getc(yyin))) {
+ if (c == '\n')
+ ++linenum;
+ }
+
+ if (c == EOF) {
+ yyntoken = EOFTOK;
+ goto ret;
+ }
+
+ ungetc(c, yyin);
+ if (isalpha(c) || c == '_')
+ yyntoken = iden();
+ else if (isdigit(c))
+ yyntoken = number();
+ else if (c == '"')
+ yyntoken = string();
+ else if (c == '\'')
+ yyntoken = character();
+ else
+ yyntoken = operator();
+
+ret: return yytoken;
+}
+
+void
+expect(register uint8_t tok)
+{
+ if (yytoken != tok)
+ error("unexpected %s", yytext);
+ next();
+}
+
+void
+open_file(register const char *file)
+{
+ if (yyin != NULL)
+ fclose(yyin);
+ if (file == NULL) {
+ yyin = stdin;
+ filename = "(stdin)";
+ } else {
+ if ((yyin = fopen(file, "r")) == NULL)
+ die("file '%s' not found", file);
+ filename = file;
+ }
+ linenum = 1;
+ next(); /* prefetch first token */
+}
--- /dev/null
+++ b/cc1/main.c
@@ -1,0 +1,25 @@
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "cc1.h"
+
+extern void init_keywords(void),
+ open_file(const char *file), init_expr(void);
+
+struct user_opt options;
+
+int
+main(int argc, char *argv[])
+{
+ //setvbuf(stdin, NULL, _IONBF, 0);
+ //setvbuf(stdout, NULL, _IONBF, 0);
+ init_keywords();
+ init_expr();
+ open_file(NULL);
+ for (next(); yytoken != EOFTOK; extdecl());
+ /* nothing */;
+
+ return 0;
+}
--- /dev/null
+++ b/cc1/opcode.txt
@@ -1,0 +1,133 @@
+Ax -> automatic variable number x
+Tx -> static variable number x
+Gx -> global variable with name x
+Xx -> global function with name x
+Yx -> static function with name x
+Lx -> label number x
+Px -> parameter number x
+Mx -> member number x
+
+@ -> content of variable
+#x -> size of type x (R, I, C, W, N, Z, Q, H, Sx, Ux)
+#x -> integer constant of value x
+##x -> float constant of value x
+#%x -> long constant of value x
+" -> begin of string, each element is coded in decimal and comma (better in hexa!!)
+a -> take address
+:x -> assign of type x
++x -> sum of type x
+-x -> substraction of type x
+*x -> multiplication of type x
+/x -> division of type x
+; -> used in post operators (A2++ -> A2 #1 ;+I)
+: -> used in pre operators (++A2 -> A2 #1 :+I)
+. -> struct field
+_x -> sign negation of type x
+~x -> logic negation of type x
+%x -> modulo of type x
+lx -> left shift of type x
+rx -> right shift of type x
+>x -> greater than of type x
+<x -> less than of type x
+[x -> less or equal of type x
+]x -> greater or equal of type x
+=x -> equal of type x
+!x -> not equal of type x
+&x -> logical and of type x
+|x -> logical or of type x
+^x -> logical exor of type x
+m -> and (last two stack values)
+s -> or (last two stack values)
+` -> index array (*(val1 + val2))
+:yx -> operation y and assign of type x
+:x -> assign of type x
+?x -> ternary of type x (cond val1 val2)
+cx -> call to function of type x
+px -> pass parameter to function of type x
+Fx -> x number of parameters passed in a function call
+, -> comma operator (last two stack values)
+d -> begin of loop
+b -> end of loop
+j -> jump (next stack value is the label)
+yx -> return of type x
+ex -> switch of type x
+w -> case (next stack value is label and next is value)
+n -> no operation (it is used in ! and in for conditions)
+E -> no operation (it is used to mark end of function declaration)
+
+Conversions:
+----------
+Sx -> struct number x
+Ux -> union number x
+Vx -> vector number x
+R -> pointer
+I -> integer
+C -> char
+W -> long
+N -> unsigned
+Z -> unsigned long
+Q -> float
+H -> double
+F -> function
+
+
+xy -> conversion from y to x
+
+
+Examples:
+---------
+
+int
+main()
+{
+ int i;
+ float v = 3.0;
+
+ i = i != v;
+}
+
+->
+
+Xmain I F E
+{
+A1 I
+A2 I
+A3 Q
+ A3 ##4130000 QH :Q
+ A1 A1 QI A3 !Q #1 #0 ?I :I
+}
+
+-------------------------------------------
+
+struct pepe {
+ int i, j;
+ struct p2 {
+ int k;
+ } k;
+};
+
+int
+main()
+{
+ int i;
+ struct pepe p;
+
+ i += p.i + p.k.k;
+}
+
+->
+
+S4 (
+M5 I
+)
+S1 (
+M2 I
+M3 I
+M6 S4
+)
+Xmain I F E
+{
+A7 I
+A8 S1
+ A7 A8 M2 . A8 M6 . M5 . +I :+I
+}
--- /dev/null
+++ b/cc1/sizes.h
@@ -1,0 +1,88 @@
+#ifndef SIZES_H
+#define SIZES_H
+
+/*
+ * 15 nesting levels of compound statements, iteration control
+ * structures, and selection control structures
+ */
+#define NR_BLOCK 15
+/*
+ * 8 nesting levels of conditional inclusion
+ */
+#define NR_COND 8
+/*
+ * number of defined structs/unions in one translation unit
+ */
+#define NR_MAXSTRUCTS 127
+/*
+ * 12 pointer, array, and function declarators (in any combinations)
+ * modifying an arithmetic, a structure, a union, or an incomplete type
+ * in a declaration
+ */
+#define NR_DECLARATORS 12
+/*
+ * 31 declarators nested by parentheses within a full declarator.
+ */
+#define NR_SUBTYPE 31
+/*
+ * 32 expressions nested by parentheses within a full expression
+ */
+#define NR_SUBEXPR 32
+/*
+ * 31 significant initial characters in an internal identifier or a
+ * macro name
+ */
+#define IDENTSIZ 31
+/*
+ * 511 external identifiers in one translation unit
+ */
+#define NR_EXT_IDENT 511
+/*
+ * 127 identifiers with block scope declared in one block
+ */
+#define NR_INT_IDENT 127
+/*
+ * 31 parameters in one function definition * 6 significant initial
+ * characters in an external identifier.
+ */
+#define NR_FUNPARAM 31
+/*
+ * 31 parameters in one macro definition
+ */
+#define NR_MACROARG 31
+/*
+ * 509 characters in a logical source line.
+ */
+#define LINESIZ 509
+/*
+ * 509 characters in a character string literal or wide string literal
+ * (after concatenation)
+ */
+#define STRINGSIZ 509
+/*
+ * 8 nesting levels for #include'd files
+ */
+#define NR_INCLUDE 9
+/*
+ * 257 case labels for a switch statement (excluding those for any
+ * nested switch statements)
+ */
+#define NR_SWITCH 257
+/*
+ * 127 members in a single structure or union
+ */
+#define NR_FIELDS 127
+/*
+ * 127 enumeration constants in a single enumeration
+ */
+#define NR_ENUM_CTES 127
+/*
+ * 15 levels of nested structure or union definitions in a single
+ * struct-declaration-list
+ */
+#define NR_STRUCT_LEVEL 15
+/*
+ * 32767 bytes in an object (in a hosted environment only)
+ */
+#define OBJECTSIZ 32767
+#endif
--- /dev/null
+++ b/cc1/stmt.c
@@ -1,0 +1,329 @@
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "cc1.h"
+
+struct scase {
+ Symbol *label;
+ Node *expr;
+ struct scase *next;
+};
+
+struct caselist {
+ short nr;
+ Symbol *deflabel;
+ struct scase *head;
+};
+
+Symbol *curfun;
+
+extern Node *convert(Node *np, Type *tp1, char iscast);
+extern Node *iszero(Node *np), *eval(Node *np);
+static void stmt(Symbol *lbreak, Symbol *lcont, Caselist *lswitch);
+
+static Symbol *
+label(char *s, char define)
+{
+ Symbol *sym;
+
+ if (s) {
+ if ((sym = lookup(s, NS_LABEL)) != NULL) {
+ if (define && sym->s.isdefined)
+ error("label '%s' already defined", s);
+ else
+ sym->s.isdefined = 1;
+ return sym;
+ }
+ } else {
+ s = "";
+ }
+
+ sym = install(s, NS_LABEL);
+ sym->s.isdefined = define;
+ return sym;
+}
+
+static void
+stmtexp(void)
+{
+ if (accept(';'))
+ return;
+ emitexp(expr());
+ expect(';');
+}
+
+static Node *
+condition(void)
+{
+ Node *np;
+
+ expect('(');
+ np = iszero(expr());
+ expect(')');
+ return np;
+}
+
+static void
+While(Caselist *lswitch)
+{
+ Symbol *begin, *cond, *end;
+ Node *np;
+
+ begin = label(NULL, 1);
+ end = label(NULL, 1);
+ cond = label(NULL, 1);
+
+ expect(WHILE);
+ np = condition();
+ emitjump(cond, NULL);
+ emitbloop();
+ emitlabel(begin);
+ stmt(end, begin, lswitch);
+ emitlabel(cond);
+ emitjump(begin, np);
+ emiteloop();
+ emitlabel(end);
+}
+
+static void
+For(Caselist *lswitch)
+{
+ Symbol *begin, *cond, *end;
+ Node *econd = NULL, *einc = NULL;
+
+ begin = label(NULL, 1);
+ end = label(NULL, 1);
+ cond = label(NULL, 1);
+
+ expect(FOR);
+ expect('(');
+ stmtexp();
+
+ if (yytoken != ';')
+ econd = expr();
+ expect(';');
+ if (yytoken != ')')
+ einc = expr();
+ expect(')');
+
+ emitjump(cond, NULL);
+ emitbloop();
+ emitlabel(begin);
+ stmt(end, begin, lswitch);
+ if (einc)
+ emitexp(einc);
+ emitlabel(cond);
+ emitjump(begin, econd);
+ emiteloop();
+ emitlabel(end);
+}
+
+static void
+Dowhile(Caselist *lswitch)
+{
+ Symbol *begin= label(NULL, 1), *end = label(NULL, 1);
+
+
+ expect(DO);
+ emitbloop();
+ emitlabel(begin);
+ stmt(end, begin, lswitch);
+ expect(WHILE);
+ emitjump(begin, condition());
+ emiteloop();
+ emitlabel(end);
+}
+
+static void
+Return(void)
+{
+ Node *np;
+ Type *tp = curfun->type->type;
+
+ expect(RETURN);
+ np = (yytoken == ';') ? NULL : eval(expr());
+ expect(';');
+ if (!np) {
+ if (tp != voidtype)
+ warn(1, "function returning non void returns no value");
+ tp = voidtype;
+ } else if (np->type != tp) {
+ if (tp == voidtype)
+ warn(1, "function returning void returns a value");
+ else if ((np = convert(np, tp, 0)) == NULL)
+ error("incorrect type in return");
+ }
+ emitret(tp);
+ emitexp(np);
+}
+
+static void
+Break(Symbol *lbreak)
+{
+ expect(BREAK);
+ if (!lbreak)
+ error("break statement not within loop or switch");
+ emitjump(lbreak, NULL);
+ expect(';');
+}
+
+static void
+Label(void)
+{
+ emitlabel(label(yytext, 1));
+
+ expect(IDEN);
+ expect(':');
+}
+
+static void
+Continue(Symbol *lcont)
+{
+ expect(CONTINUE);
+ if (!lcont)
+ error("continue statement not within loop");
+ emitjump(lcont, NULL);
+ expect(';');
+}
+
+static void
+Goto(void)
+{
+ expect(GOTO);
+
+ if (yytoken != IDEN)
+ error("unexpected '%s'", yytext);
+ emitjump(label(yytext, 0), NULL);
+ next();
+ expect(';');
+}
+
+static void
+Switch(Symbol *lcont)
+{
+ Caselist lcase = {.nr = 0, .head = NULL, .deflabel = NULL};
+ struct scase *p;
+ Symbol *lbreak = label(NULL, 1), *lcond = label(NULL, 1);
+ Node *cond;
+
+ expect(SWITCH);
+ expect ('(');
+ cond = eval(expr());
+ expect (')');
+ /* TODO: check integer type */
+ emitjump(lcond, NULL);
+ stmt(lbreak, lcont, &lcase);
+ emitlabel(lcond);
+ emitswitch(lcase.nr, cond);
+ for (p = lcase.head; p; p = p->next)
+ emitcase(p->label, p->expr);
+ if (lcase.deflabel)
+ emitdefault(lcase.deflabel);
+ emitlabel(lbreak);
+ /* TODO: free memory */
+}
+
+static void
+Case(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
+{
+ Node *np;
+ Symbol *lcase = label(NULL, 1);
+ struct scase *pcase;
+
+ if (!lswitch)
+ error("case label not within a switch statement");
+ expect(CASE);
+ if (yytoken == ':')
+ error("expected expression before ':'");
+ np = eval(expr());
+ /* TODO: check integer type */
+ expect(':');
+ emitlabel(lcase);
+ pcase = xmalloc(sizeof(*pcase));
+ pcase->expr = np;
+ pcase->label = lcase;
+ pcase->next = lswitch->head;
+ lswitch->head = pcase;
+ ++lswitch->nr;
+}
+
+static void
+Default(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
+{
+ Symbol *ldefault = label(NULL, 1);
+
+ expect(DEFAULT);
+ expect(':');
+ emitlabel(ldefault);
+ lswitch->deflabel = ldefault;
+}
+
+static void
+If(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
+{
+ Symbol *end, *lelse = label(NULL, 1);
+ Node *np;
+
+ expect(IF);
+ np = condition();
+ NEGATE(np, 1);
+ emitjump(lelse, np);
+ stmt(lbreak, lcont, lswitch);
+ if (accept(ELSE)) {
+ end = label(NULL, 1);
+ emitjump(end, NULL);
+ emitlabel(lelse);
+ stmt(lbreak, lcont, lswitch);
+ emitlabel(end);
+ } else {
+ emitlabel(lelse);
+ }
+}
+
+void
+compound(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
+{
+ expect('{');
+ for (;;) {
+ switch (yytoken) {
+ case '}':
+ next();
+ return;
+ case TYPE: case SCLASS: case TQUALIFIER:
+ decl();
+ break;
+ default:
+ stmt(lbreak, lcont, lswitch);
+ }
+ }
+}
+
+static void
+stmt(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
+{
+
+repeat:
+ switch (yytoken) {
+ case '{': compound(lbreak, lcont, lswitch); break;
+ case RETURN: Return(); break;
+ case WHILE: While(lswitch); break;
+ case FOR: For(lswitch); break;
+ case DO: Dowhile(lswitch); break;
+ case IF: If(lbreak, lcont, lswitch); break;
+ case BREAK: Break(lbreak); break;
+ case CONTINUE: Continue(lcont); break;
+ case GOTO: Goto(); break;
+ case SWITCH: Switch(lcont); break;
+ case CASE: Case(lbreak, lcont, lswitch); break;
+ case DEFAULT: Default(lbreak, lcont, lswitch); break;
+ case IDEN:
+ if (ahead() == ':') {
+ Label();
+ goto repeat;
+ }
+ default: stmtexp(); break;
+ }
+}
+
--- /dev/null
+++ b/cc1/symbol.c
@@ -1,0 +1,103 @@
+
+#include <stdint.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "cc1.h"
+
+#define NR_SYM_HASH 32
+
+uint8_t curctx;
+uint8_t namespace = NS_FREE + 1;
+short symid;
+
+static struct symtab {
+ Symbol *head;
+ Symbol *htab[NR_SYM_HASH];
+} symtab [NR_NAMESPACES];
+
+static inline uint8_t
+hash(register const char *s)
+{
+ register uint8_t h, ch;
+
+ for (h = 0; ch = *s++; h += ch)
+ /* nothing */;
+ return h & NR_SYM_HASH - 1;
+}
+
+void
+freesyms(uint8_t ns)
+{
+ static struct symtab *tbl;
+ register Symbol *sym, *next;
+
+ tbl = &symtab[(ns >= NR_NAMESPACES) ? NS_IDEN : ns];
+ for (sym = tbl->head; sym; sym = next) {
+ if (sym->ctx <= curctx)
+ break;
+ if (ns == NS_LABEL && !sym->s.isdefined)
+ error("label '%s' is not defined", sym->name);
+ tbl->htab[hash(sym->name)] = sym->hash;
+ next = tbl->head = sym->next;
+ free(sym->name);
+ free(sym);
+ }
+}
+
+void
+context(Ctxfun *fun, Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
+{
+ uint8_t ns;
+
+ ns = namespace;
+ ++curctx;
+ (*fun)(lbreak, lcont, lswitch);
+ --curctx;
+ namespace = ns;
+
+ freesyms(NS_IDEN);
+ freesyms(NS_TAG);
+}
+
+Symbol *
+lookup(register char *s, uint8_t ns)
+{
+ extern union yystype yylval;
+ static struct symtab *tbl;
+ register Symbol *sym;
+
+ 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;
+ }
+
+ return NULL;
+}
+
+Symbol *
+install(char *s, uint8_t ns)
+{
+ register Symbol *sym, **t;
+ struct symtab *tbl;
+
+ sym = xcalloc(1, sizeof(*sym));
+ sym->name = xstrdup(s);
+ sym->ctx = curctx;
+ sym->token = IDEN;
+ sym->ns = ns;
+ sym->id = symid++;
+ 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;
+}
--- /dev/null
+++ b/cc1/types.c
@@ -1,0 +1,198 @@
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "sizes.h"
+#include "cc1.h"
+
+#define NR_TYPE_HASH 16
+
+Type
+ *voidtype = &(Type) {
+ .op = VOID,
+ .letter = 'W'
+ },
+ *pvoidtype = &(Type) {
+ .op = PTR,
+ .letter = 'R'
+ },
+ *booltype = &(Type) {
+ .op = INT,
+ .letter = 'B',
+ .defined = 1,
+ .u.rank = RANK_BOOL
+ },
+ *schartype = &(Type) {
+ .op = INT,
+ .letter = 'C',
+ .defined = 1,
+ .u.rank = RANK_SCHAR
+ },
+ *uchartype = &(Type) {
+ .op = INT,
+ .letter = 'M',
+ .sign = 1,
+ .defined = 1,
+ .u.rank = RANK_UCHAR
+ },
+ *chartype = &(Type) {
+ .op = INT,
+ .letter = 'M',
+ .sign = 1,
+ .defined = 1,
+ .u.rank = RANK_UCHAR
+ },
+ *ushortype = &(Type) {
+ .op = INT,
+ .letter = 'E',
+ .defined = 1,
+ .u.rank = RANK_USHORT
+ },
+ *shortype = &(Type) {
+ .op = INT,
+ .letter = 'K',
+ .defined = 1,
+ .u.rank = RANK_SHORT
+ },
+ *uinttype = &(Type) {
+ .op = INT,
+ .letter = 'U',
+ .sign = 1,
+ .defined = 1,
+ .u.rank = RANK_UINT
+ },
+ *inttype = &(Type) {
+ .op = INT,
+ .letter = 'I',
+ .defined = 1,
+ .u.rank = RANK_INT
+ },
+ *longtype = &(Type) {
+ .op = INT,
+ .letter = 'L',
+ .defined = 1,
+ .u.rank = RANK_LONG
+ },
+ *ulongtype = &(Type) {
+ .op = INT,
+ .letter = 'Z',
+ .sign = 1,
+ .defined = 1,
+ .u.rank = RANK_ULONG
+ },
+ *ullongtype = &(Type) {
+ .op = INT,
+ .letter = 'O',
+ .sign = 1,
+ .defined = 1,
+ .u.rank = RANK_ULLONG
+ },
+ *llongtype = &(Type) {
+ .op = INT,
+ .letter = 'J',
+ .defined = 1,
+ .u.rank = RANK_LLONG
+ },
+ *floattype = &(Type) {
+ .op = FLOAT,
+ .letter = 'F',
+ .defined = 1,
+ .u.rank = RANK_FLOAT
+ },
+ *doubletype = &(Type) {
+ .op = FLOAT,
+ .letter = 'D',
+ .defined = 1,
+ .u.rank = RANK_DOUBLE
+ },
+ *ldoubletype = &(Type) {
+ .op = FLOAT,
+ .letter = 'H',
+ .defined = 1,
+ .u.rank = RANK_LDOUBLE
+ };
+
+Type *
+ctype(int8_t type, int8_t sign, int8_t size)
+{
+ if (type == DOUBLE)
+ type = FLOAT, size += LONG;
+
+ switch (type) {
+ case CHAR: if (sign == 0)
+ return chartype;
+ return (sign == UNSIGNED) ? uchartype : schartype;
+ case VOID: return voidtype;
+ case BOOL: return booltype;
+ case INT: switch (size) {
+ case 0: return (sign == UNSIGNED) ? uinttype : inttype;
+ case SHORT: return (sign == UNSIGNED) ? ushortype : shortype;
+ case LONG: return (sign == UNSIGNED) ? ulongtype : longtype;
+ case LONG+LONG: return (sign == UNSIGNED) ? ullongtype : llongtype;
+ }
+ case FLOAT: switch (size) {
+ case 0: return floattype;
+ case LONG: return doubletype;
+ case LONG+LONG: return ldoubletype;
+ }
+ }
+}
+
+Type *
+mktype(Type *tp, uint8_t op,
+ Symbol *sym, uint16_t nelem)
+{
+ static Type *typetab[NR_TYPE_HASH], **tbl;
+ static uint8_t t;
+ register Type *bp;
+ char letter;
+
+ if (op == PTR && tp == voidtype)
+ return pvoidtype;
+ t = (op ^ (uint8_t) ((unsigned short) tp >> 3))
+ & NR_TYPE_HASH-1;
+ tbl = &typetab[t];
+ if (op != FTN || op != STRUCT || op != UNION || op != ENUM) {
+ for (bp = *tbl; bp; bp = bp->next) {
+ if (bp->type == tp && bp->op == op &&
+ bp->sym == sym && bp->u.nelem == nelem) {
+ return bp;
+ }
+ }
+ }
+
+ switch (op) {
+ 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: letter = tp->letter;
+ }
+ bp = xmalloc(sizeof(*bp));
+ bp->next = *tbl;
+ bp->type = tp;
+ bp->op = op;
+ bp->u.nelem = nelem;
+ bp->sym = sym;
+ bp->letter = letter;
+ return *tbl = bp;
+}
+
+Type *
+qualifier(Type *tp, uint8_t qlf)
+{
+ uint8_t q = tp->op;
+
+ if (!qlf)
+ return tp;
+ if (q & TQUALIFIER) {
+ if (q == qlf)
+ return tp;
+ tp = tp->type;
+ qlf |= q;
+ }
+ return mktype(tp, qlf|TQUALIFIER, NULL, 0);
+}
+
--- /dev/null
+++ b/cc1/wrapper.c
@@ -1,0 +1,53 @@
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <stdint.h>
+
+#include "cc1.h"
+
+
+static void
+out_of_memory(void)
+{
+ /* TODO: deal with out of memory errors */
+ error("out of memory");
+}
+
+void *
+xmalloc(size_t size)
+{
+ register void *p = malloc(size);
+
+ if (!p)
+ out_of_memory();
+ return p;
+}
+
+void *
+xcalloc(size_t nmemb, size_t size)
+{
+ register size_t nbytes = nmemb * size;
+ register void *p = xmalloc(nbytes);
+
+ return memset(p, nbytes, 0);
+}
+
+char *
+xstrdup(const char *s)
+{
+ register size_t len = strlen(s) + 1;
+ register char *p = xmalloc(len);
+
+ return memcpy(p, s, len);
+}
+
+void *
+xrealloc(void *buff, register size_t size)
+{
+ register void *p = realloc(buff, size);
+
+ if (!p)
+ out_of_memory();
+ return p;
+}
--- a/code.c
+++ /dev/null
@@ -1,313 +1,0 @@
-
-#include <stdint.h>
-#include <stdio.h>
-
-#include "cc1.h"
-
-char *opcodes[] = {
- [OADD] = "+",
- [OSUB] = "-",
- [OMUL] = "*",
- [OARY] = "'",
- [OINC] = ";+",
- [ODEC] = ";=",
- [OSIZE] = "#",
- [OPTR] = "@",
- [OMOD] = "*",
- [ODIV] = "/",
- [OSHL] = "l",
- [OSHR] = "r",
- [OLT] = "<",
- [OGT] = ">",
- [OGE] = "]",
- [OLE] = "[",
- [OEQ] = "=",
- [ONE] = "!",
- [OBAND] = "&",
- [OBXOR] = "^",
- [OBOR] = "|",
- [OASSIGN] = ":",
- [OA_MUL] = ":*",
- [OA_DIV] = ":/",
- [OA_MOD] = ":%",
- [OA_ADD] = ":+",
- [OA_SUB] = ":-",
- [OA_SHL] = ":l",
- [OA_SHR] = ":r",
- [OA_AND] = ":&",
- [OA_XOR] = ":^",
- [OA_OR] = ":|",
- [OADDR] = "a",
- [ONEG] = "_",
- [OCPL] = "~",
- [OAND] = "m",
- [OOR] = "s",
- [OCOMMA] = ","
-};
-
-Node *
-node(void (*code)(Node *), Type *tp, union unode u, uint8_t nchilds)
-{
- Node *np = xmalloc(sizeof(*np) + nchilds * sizeof(np));
-
- np->code = code;
- np->type = tp;
- np->utype = UNQUAL(tp);
- np->typeop = np->utype->op;
- np->u = u;
- np->b.symbol = np->b.lvalue = 0;
-
- return np;
-}
-
-static void
-emitsym2(Symbol *sym)
-{
- char c;
-
- if (sym->s.isglobal)
- c = 'G';
- else if (sym->s.isstatic)
- c = 'T';
- else if (sym->s.isregister)
- c = 'Q';
- else
- c = 'A';
- printf("%c%d", c, sym->id);
-}
-
-static void
-emitconst(Node *np)
-{
- register char *bp, c;
- Symbol *sym = np->u.sym;
-
- if (np->type == inttype) {
- printf("#%x", sym->u.i);
- } else {
- putchar('"');
- for (bp = sym->u.s; c = *bp; ++bp)
- printf("%02x", (unsigned) c);
- }
-}
-
-void
-emitsym(Node *np)
-{
- putchar('\t');
- (np->b.constant) ? emitconst(np) : emitsym2(np->u.sym);
-}
-
-static void
-emittype(Type *tp)
-{
- putchar(tp->letter);
-}
-
-void
-emitdcl(Symbol *sym)
-{
- emitsym2(sym);
- putchar('\t');
- emittype(sym->type);
- putchar('\n');
-}
-
-void
-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
-emitternary(Node *np)
-{
- Node *cond, *ifyes, *ifno;
-
- cond = np->childs[0];
- ifyes = np->childs[1];
- ifno = np->childs[2];
- (*cond->code)(cond);
- (*ifyes->code)(ifyes);
- (*ifno->code)(ifno);
- printf("\t?%c", np->type->letter);
-}
-
-void
-emitsizeof(Node *np)
-{
- printf("\t#%c", np->u.type->letter);
-}
-
-void
-emitexp(Node *np)
-{
- if (np)
- (*np->code)(np);
- putchar('\n');
-}
-
-void
-emitprint(Node *np)
-{
- (*np->code)(np);
- printf("\tk%c\n", np->type->letter);
-}
-
-void
-emitfun(Symbol *sym)
-{
- printf("%c%d\tn%s\n",
- sym->s.isglobal ? 'X' : 'Y', sym->id, sym->name);
-}
-
-void
-emitsframe(Symbol *sym)
-{
- puts("{");
-}
-
-void
-emiteframe(Symbol *sym)
-{
- puts("}");
-}
-
-void
-emitret(Type *tp)
-{
- fputs("\ty", stdout);
- emittype(tp);
-}
-
-void
-emitlabel(Symbol *sym)
-{
- printf("L%d\n", sym->id);
-}
-
-void
-emitbloop(void)
-{
- puts("\td");
-}
-
-void
-emiteloop(void)
-{
- puts("\tb");
-}
-
-void
-emitjump(Symbol *sym, Node *np)
-{
- printf("\tj\tL%d", sym->id);
- if (!np)
- putchar('\n');
- else
- emitexp(np);
-}
-
-void
-emitswitch(short nr, Node *np)
-{
- printf("\teI\t#%0x", nr);
- emitexp(np);
-}
-
-void
-emitcase(Symbol *sym, Node *np)
-{
- fputs("\tw\t", stdout);
- printf("L%d", sym->id);
- emitexp(np);
-}
-
-void
-emitdefault(Symbol *sym)
-{
- fputs("\tf\t", stdout);
- emitlabel(sym);
-}
-
-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)
-{
- if (!tp->defined)
- error("invalid use of indefined type");
- return node(emitsizeof, inttype, TYP(tp), 0);
-}
-
-Node *
-ternarycode(Node *cond, Node *ifyes, Node *ifno)
-{
- Node *np= node(emitternary, ifyes->type, OP(0), 3);
- np->childs[0] = cond;
- np->childs[1] = ifyes;
- np->childs[2] = ifno;
- return np;
-}
-
-Node *
-symcode(Symbol *sym)
-{
- Node *np;
-
- np = node(emitsym, sym->type, SYM(sym), 0);
- np->b.symbol = 1;
- np->b.constant = 1;
- return np;
-}
--- a/decl.c
+++ /dev/null
@@ -1,536 +1,0 @@
-#include <assert.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-
-#include "sizes.h"
-#include "cc1.h"
-
-#define ID_EXPECTED 1
-#define ID_ACCEPTED 2
-
-int8_t forbid_eof;
-
-struct dcldata {
- uint8_t op;
- union {
- unsigned short nelem;
- Symbol *sym;
- struct funpars *pars;
- uint8_t qlf;
- } u;
-};
-
-static struct dcldata
- *declarator0(struct dcldata *dp, uint8_t ns, int8_t flags);
-
-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 Symbol *
-newiden(uint8_t ns)
-{
- Symbol *sym;
- extern uint8_t curctx;
-
- if (yylval.sym && yylval.sym->ctx == curctx)
- error("redeclaration of '%s'", yytext);
- sym = install(yytext, ns);
- next();
- return sym;
-}
-
-static struct dcldata *
-directdcl(struct dcldata *dp, uint8_t ns, int8_t flags)
-{
- register Symbol *sym;
- char *err;
-
- if (accept('(')) {
- dp = declarator0(dp, ns, flags);
- expect(')');
- } else if (flags) {
- if (yytoken != IDEN) {
- if (flags & ID_EXPECTED)
- goto expected;
- sym = install("", ns);
- } else {
- sym = newiden(ns);
- }
- dp->op = IDEN;
- dp->u.sym = sym;
- ++dp;
- }
-
- for (;;) {
- switch (yytoken) {
- case '(': dp = fundcl(dp); break;
- case '[': dp = arydcl(dp); break;
- default: return dp;
- }
- }
-
-expected:
- error("expected '(' or identifier before of '%s'" , yytext);
-}
-
-static struct dcldata*
-declarator0(struct dcldata *dp, uint8_t ns, int8_t flags)
-{
- uint8_t buffer[NR_DECLARATORS];
- register uint8_t *bp, n, qlf;
-
- bp = buffer;
- for (n = 0; accept('*'); ++n) {
- if (n == NR_DECLARATORS)
- goto too_much_declarators;
- qlf = 0;
- if (yytoken == TQUALIFIER) {
- qlf |= yylval.token;
- next();
- }
- *bp++ = qlf;
- }
-
- dp = directdcl(dp, ns, flags);
-
- bp = buffer;
- while (n--) {
- if (dp->op == 255)
- goto too_much_declarators;
- dp->op = PTR;
- dp->u.qlf = *bp++;
- ++dp;
- }
-
- return dp;
-
-too_much_declarators:
- error("too much declarators");
-}
-
-static Symbol *
-declarator(Type *tp, uint8_t ns, int8_t flags)
-{
- struct dcldata data[NR_DECLARATORS+1];
- register struct dcldata *bp;
- Symbol *sym = NULL;
- static Symbol dummy;
-
- memset(data, 0, sizeof(data));
- 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;
- }
- }
- if (!sym)
- sym = &dummy;
- sym->type = tp;
- return sym;
-}
-
-static Type *structdcl(void), *enumdcl(void);
-
-static Type *
-specifier(int8_t *sclass)
-{
- Type *tp = NULL;
- int8_t qlf, sign, type, cls, size, t;
-
- qlf = sign = type = cls = size = 0;
-
- for (;;) {
- register uint8_t *p;
- Type *(*dcl)(void) = NULL;
-
- switch (yytoken) {
- case SCLASS: p = &cls; break;
- case TQUALIFIER:
- if ((qlf |= yylval.token) & RESTRICT)
- goto invalid_type;
- next();
- continue;
- case TYPE:
- switch (yylval.token) {
- case ENUM:
- dcl = enumdcl; p = &type; break;
- case STRUCT: case UNION:
- dcl = structdcl; p = &type; break;
- case TYPENAME:
- tp = yylval.sym->type;
- case VOID: case BOOL: case CHAR:
- case INT: case FLOAT: case DOUBLE:
- p = &type; break;
- case SIGNED: case UNSIGNED:
- p = &sign; break;
- case LONG:
- if (size == LONG) {
- size = LONG+LONG;
- break;
- }
- case SHORT:
- p = &size; break;
- }
- break;
- default:
- goto check_types;
- }
- if (*p)
- goto invalid_type;
- *p = yylval.token;
- if (dcl)
- tp = dcl();
- else
- next();
- }
-
-check_types:
- if (!type) {
- if (!sign && !size) {
- warn(options.implicit,
- "type defaults to 'int' in declaration");
- }
- type = INT;
- }
- if (sign && type != INT && type != CHAR ||
- 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);
- return (qlf) ? qualifier(tp, qlf) : tp;
-
-invalid_type:
- error("invalid type specification");
-}
-
-static struct node *
-initializer(register Type *tp)
-{
- if (accept('{')) {
- initializer(tp);
- expect('}');
- } else {
- do {
- expr();
- } while (accept(','));
- }
-}
-
-/* TODO: bitfields */
-
-static void
-newfield(Type *tp, Symbol *sym)
-{
- register struct field *p, *q;
- register char *s, *t;
- static uint8_t op;
- static char *err;
-
- s = sym->name;
- op = tp->op;
- for (q = p = tp->u.fields; p; q = p, p = p->next) {
- t = p->sym->name;
- if (*s == *t && !strcmp(s, t))
- goto duplicated_name;
- if (op == ENUM && sym->u.i == p->sym->u.i)
- goto duplicated_value;
- }
-
- p = xmalloc(sizeof(*p));
- p->next = NULL;
- p->sym = sym;
- if (!q)
- tp->u.fields = p;
- else
- q->next = p;
-
- return;
-
-duplicated_name:
- err = "duplicated fields '%s' and '%s'";
- goto error;
-duplicated_value:
- err = "duplicated enumeration fields '%s' and '%s'";
-error:
- error(err, s, t);
-}
-
-static void
-fielddcl(Type *base, uint8_t ns)
-{
- Type *tp;
- Symbol *sym;
- char *err;
-
- switch (yytoken) {
- case SCLASS:
- goto bad_storage;
- case IDEN: case TYPE: case TQUALIFIER:
- tp = specifier(NULL);
- case ';':
- break;
- default:
- goto dcl_expected;
- }
-
- if (yytoken != ';') {
- do {
- sym = declarator(tp, ns, ID_EXPECTED);
- newfield(tp, sym);
- } while (accept(','));
- }
-
- expect(';');
- return;
-
-bad_storage:
- err = "storage class '%s' in struct/union field";
- goto error;
-dcl_expected:
- err = "declaration expected";
-error:
- error(err, yytext);
-}
-
-static Type *
-newtag(uint8_t tag)
-{
- register Symbol *sym;
- Type *tp;
- extern uint8_t namespace;
-
- if (yytoken == IDEN) {
- sym = lookup(yytext, NS_TAG);
- if (sym) {
- if (sym->type->op != tag)
- goto bad_tag;
- } else {
- sym = install(yytext, NS_TAG);
- }
- next();
- } else {
- sym = install("", NS_TAG);
- }
- tp = sym->type = mktype(NULL, tag, NULL, 0);
- sym->u.ns = ++namespace;
- tp->sym = sym;
- return tp;
-
-bad_tag:
- error("'%s' defined as wrong kind of tag", yytext);
-}
-
-static Type *
-structdcl(void)
-{
- Type *tp;
- uint8_t ns, tag;
-
- tag = yylval.token;
- next();
- tp = newtag(tag);
- tp->u.fields = NULL;
- ns = tp->sym->u.ns;
- if (accept('{')) {
- if (tp->defined)
- goto redefined;
- tp->defined = 1;
- while (!accept('}'))
- fielddcl(tp, ns);
- }
-
- return tp;
-
-redefined:
- error("redefinition of struct/union '%s'", yytext);
-}
-
-static Type *
-enumdcl(void)
-{
- register Type *tp;
- Symbol *sym;
- int val = 0;
- char *err;
-
- next();
- tp = newtag(ENUM);
- if (yytoken != ';') {
- expect('{');
- if (tp->defined)
- goto redefined;
- tp->defined = 1;
- while (yytoken != '}') {
- if (yytoken != IDEN)
- goto iden_expected;
- sym = newiden(NS_IDEN);
- sym->type = inttype;
- if (accept('='))
- initializer(inttype);
- sym->u.i = val++;
- newfield(tp, sym);
- if (!accept(','))
- break;
- }
- expect('}');
- }
-
- return tp;
-
-redefined:
- err = "redefinition of enumeration '%s'";
- goto error;
-iden_expected:
- err = "identifier expected";
-error:
- error(err, yytext);
-}
-
-void
-decl(void)
-{
- Type *tp;
- Symbol *sym;
- int8_t sclass;
-
- tp = specifier(&sclass);
- if (yytoken != ';') {
- do {
- sym = declarator(tp, NS_IDEN, ID_EXPECTED);
- switch (sclass) {
- case REGISTER: sym->s.isregister = 1; break;
- case STATIC: sym->s.isstatic = 1; break;
- case EXTERN: /* TODO: */; break;
- case TYPEDEF: /* TODO: */;break;
- case AUTO: default: sym->s.isauto = 1;
- }
- if (accept('='))
- initializer(sym->type); /* TODO: emit initializer */
- emitdcl(sym);
- } while (accept(','));
- }
- expect(';');
-}
-
-Type *
-typename(void)
-{
- uint8_t sclass;
- Type *tp;
- Symbol *sym;
-
- tp = specifier(&sclass);
- if (sclass)
- error("class storage in type name");
- sym = declarator(tp, NS_IDEN, 0);
- return sym->type;
-}
-
-void
-extdecl(void)
-{
- Type *base;
- int8_t sclass;
- Symbol *sym;
- char *err;
-
- forbid_eof = 0; /* TODO: Fix when find EOF */
-
- switch (yytoken) {
- case IDEN: case TYPE: case SCLASS: case TQUALIFIER:
- base = specifier(&sclass);
- if (sclass == REGISTER || sclass == AUTO)
- goto bad_storage;
- case ';':
- break;
- case '@':
- next();
- emitprint(expr());
- goto semicolon;
- default:
- goto dcl_expected;
- }
-
- if (yytoken != ';') {
- do {
- Type *tp;
-
- sym = declarator(base, NS_IDEN, ID_EXPECTED);
- tp = sym->type;
-
- if (!(sclass & STATIC))
- sym->s.isglobal = 1;
- if (BTYPE(tp) == FTN) {
- if (yytoken == '{') {
- extern Symbol *curfun;
-
- curfun = sym;
- emitfun(sym);
- emitsframe(sym);
- context(compound, NULL, NULL, NULL);
- emiteframe(sym); /* FIX: sym is not used */
- freesyms(NS_LABEL);
- return;
- }
- } else {
- sym->s.isstatic = 1;
- if (sclass & EXTERN)
- ; /* TODO: handle extern */
- else if (accept('='))
- initializer(tp);
- emitdcl(sym);
-
- }
- } while (accept(','));
- }
-
-semicolon:
- expect(';');
- return;
-
-bad_storage:
- err = "incorrect storage class for file-scope declaration";
- goto error;
-dcl_expected:
- err = "declaration expected";
-error:
- error(err);
-}
--- a/error.c
+++ /dev/null
@@ -1,52 +1,0 @@
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdio.h>
-
-#include "cc1.h"
-
-extern unsigned linenum;
-extern unsigned columnum;
-extern const char *filename;
-
-static void
-warn_helper(signed char flag, const char *fmt, va_list va)
-{
- if (!flag)
- return;
- fprintf(stderr, "%s:%s:%u: ",
- (!flag) ? "warning" : "error", filename, linenum);
- vfprintf(stderr, fmt, va);
- putc('\n', stderr);
- if (flag < 0)
- exit(EXIT_FAILURE); /* TODO: uhmmmm */
-}
-
-void
-warn(signed char flag, const char *fmt, ...)
-{
- va_list va;
- va_start(va, fmt);
- warn_helper(flag, fmt, va);
- va_end(va);
-}
-
-void
-error(const char *fmt, ...)
-{
- va_list va;
- va_start(va, fmt);
- warn_helper(-1, fmt, va);
- va_end(va);
-}
-
-void
-die(const char *fmt, ...)
-{
- va_list va;
- va_start(va, fmt);
- fprintf(stderr, fmt, va);
- va_end(va);
- exit(EXIT_FAILURE);
-}
--- a/expr.c
+++ /dev/null
@@ -1,758 +1,0 @@
-#include <stdint.h>
-#include <stdio.h>
-
-#include "cc1.h"
-
-static Symbol *zero, *one;
-
-Node *expr(void);
-
-void
-init_expr(void)
-{
- static Symbol dummy0, dummy1;
-
- dummy0.type = dummy1.type = inttype;
- dummy0.u.i = 0;
- dummy1.u.i = 1;
- zero = &dummy0;
- one = &dummy1;
-}
-
-static Node *
-promote(Node *np)
-{
- Type *tp;
- uint8_t r;
-
- if (options.npromote)
- return np;
- tp = np->utype;
- r = tp->u.rank;
- if (r > RANK_UINT || tp == inttype || tp == uinttype)
- return np;
- return castcode(np, (r == RANK_UINT) ? uinttype : inttype);
-}
-
-static void
-typeconv(Node **p1, Node **p2)
-{
- Type *tp1, *tp2;
- Node *np1, *np2;
- int8_t n;
-
- np1 = promote(*p1);
- np2 = promote(*p2);
-
- tp1 = np1->utype;
- tp2 = np2->utype;
- if (tp1 != tp2) {
- if ((n = tp1->u.rank - tp2->u.rank) > 0)
- np2 = castcode(np2, tp1);
- else if (n < 0)
- np1 = castcode(np1, tp2);
- }
- *p1 = np1;
- *p2 = np2;
-}
-
-Node *
-eval(Node *np)
-{
- if (!ISNODECMP(np))
- return np;
- return ternarycode(np, symcode(one), symcode(zero));
-}
-
-static Node *
-integerop(char op, Node *np1, Node *np2)
-{
- np1 = eval(np1);
- np2 = eval(np2);
- if (np1->typeop != INT || np2->typeop != INT)
- error("operator requires integer operands");
- typeconv(&np1, &np2);
- return bincode(op, np1->type, np1, np2);
-}
-
-static Node *
-integeruop(char op, Node *np)
-{
- np = eval(np);
- if (np->typeop != INT)
- error("unary operator requires integer operand");
- return unarycode(op, np->type, np);
-}
-
-static Node *
-addr2ptr(Node *np)
-{
- Type *tp;
-
- tp = mktype(np->utype->type, PTR, NULL, 0);
- return unarycode(OADDR, tp, np);
-}
-
-/*
- * Convert a Node to a type
- */
-Node *
-convert(Node *np, Type *tp, char iscast)
-{
- Type *utp;
- uint8_t t;
-
- if (np->type == tp)
- return np;
-
- utp = UNQUAL(tp);
- t = utp->op;
-
- switch (np->typeop) {
- case ENUM: case INT: case FLOAT:
- switch (t) {
- case PTR:
- if (!iscast || np->typeop == FLOAT)
- return NULL;
- case INT: case FLOAT: case ENUM: case VOID:
- break;
- default:
- return NULL;
- }
- break;
- case PTR:
- switch (t) {
- case ENUM: case INT: case VOID: /* TODO: allow p = 0 */
- if (!iscast)
- return NULL;;
- break;
- case ARY: case FTN:
- np = addr2ptr(np);
- case PTR:
- if (iscast ||
- utp == pvoidtype ||
- np->utype == pvoidtype) {
- /* TODO:
- * we assume conversion between pointers
- * do not need any operation, but due to
- * alignment problems that may be false
- */
- np->type = tp;
- np->utype = utp;
- return np;
- }
- default:
- return NULL;
- }
- default:
- return NULL;
- }
- return castcode(np, tp);
-}
-
-static Node *
-parithmetic(char op, Node *np1, Node *np2)
-{
- Type *tp;
- Node *size;
- char *err;
-
- tp = np1->utype;
- size = sizeofcode(tp->type);
- if (np2->typeop == ARY)
- np2 = addr2ptr(np2);
-
- if (op == OSUB && np2->typeop == PTR) {
- if (tp != np2->utype)
- goto incorrect;
- np1 = bincode(OSUB, inttype, np1, np2);
- return bincode(ODIV, inttype, np1, size);
- }
- if (np2->typeop != INT)
- goto incorrect;
- np2 = castcode(promote(np2), tp);
- np2 = bincode(OMUL, tp, np2, size);
- return bincode(op, tp, np1, np2);
-
-incorrect:
- error("incorrect arithmetic operands");
-}
-
-static Node *
-arithmetic(char op, Node *np1, Node *np2)
-{
- np1 = eval(np1);
- np2 = eval(np2);
- switch (np1->typeop) {
- case INT: case FLOAT:
- switch (np2->typeop) {
- case INT: case FLOAT:
- typeconv(&np1, &np2);
- break;
- case ARY:
- np2 = addr2ptr(np2);
- case PTR:
- if (op == OADD || op == OSUB)
- return parithmetic(op, np2, np1);
- default:
- goto incorrect;
- }
- break;
- case ARY:
- np1 = addr2ptr(np1);
- case PTR:
- return parithmetic(op, np1, np2);
- default:
- incorrect:
- error("incorrect arithmetic operands");
- }
-
- return bincode(op, np1->type, np1, np2);
-}
-
-/*
- * FIXME:
- * Pointers to the same basic type after removing type qualifiers
- * can be compared. It means that utype pointer must be a field
- * of the type, not of the Node, because in other case is
- * hard doing this check
- */
-static Node *
-pcompare(char op, Node *np1, Node *np2)
-{
- if (np2->typeop == INT && np2->b.symbol && np2->u.sym->u.i == 0) {
- np2 = castcode(np2, pvoidtype);
- } else if (np2->typeop != PTR) {
- error("incompatibles type in comparision");
- } else {
- warn(options.pcompare,
- "comparision between different pointer types");
- }
-
- return bincode(op, np1->type, np1, np2);
-}
-
-static Node *
-compare(char op, Node *np1, Node *np2)
-{
- np1 = eval(np1);
- np2 = eval(np2);
- switch (np1->typeop) {
- case INT: case FLOAT:
- switch (np1->typeop) {
- case INT: case FLOAT:
- typeconv(&np1, &np2);
- break;
- case ARY: case FTN:
- np2 = addr2ptr(np2);
- case PTR:
- return pcompare(op, np2, np1);
- default:
- goto nocompat;
- }
- break;
- case ARY: case FTN:
- np1 = addr2ptr(np1);
- case PTR:
- return pcompare(op, np1, np2);
- default:
- nocompat:
- error("incompatibles type in comparision");
- }
-
- return bincode(op, inttype, np1, np2);
-}
-
-static Node *
-exp2cond(Node *np, char neg)
-{
- if (ISNODECMP(np)) {
- NEGATE(np, neg);
- return np;
- }
-
- return compare(ONE ^ neg, np, symcode(zero));
-}
-
-static Node *
-logic(char op, Node *np1, Node *np2)
-{
- np1 = exp2cond(np1, 0);
- np2 = exp2cond(np2, 0);
- return bincode(op, inttype, np1, np2);
-}
-
-static Node *
-array(Node *np1, Node *np2)
-{
- Type *tp;
- char *err;
-
- if (np1->typeop != INT && np2->typeop != INT)
- goto bad_subs;
- np1 = arithmetic(OADD, np1, np2);
- tp = np1->type;
- if (tp->op != PTR)
- goto bad_vector;
- np1 = unarycode(OARY, tp->type , np1);
- np1->b.lvalue = 1;
- return 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);
-}
-
-Node *
-iszero(Node *np)
-{
- if (ISNODECMP(np))
- return np;
- return compare(ONE, np, symcode(zero));
-}
-
-static Node *
-assignop(char op, Node *np1, Node *np2)
-{
- if ((np2 = convert(np2, np1->type, 0)) == NULL)
- error("incompatible types when assigning");
- return bincode(op, np1->type, np1, np2);
-}
-
-static Node *
-incdec(Node *np, char op)
-{
- char *err;
- Type *tp = np->utype;
-
- if (!np->b.lvalue)
- goto nolvalue;
- if (np->utype == voidtype)
- goto voidassign;
- if (isconst(tp->op))
- goto const_mod;
-
- switch (np->typeop) {
- case PTR:
- if (!tp->defined)
- goto nocomplete;
- case INT: case FLOAT:
- return arithmetic(op, np, symcode(one));
- default:
- goto bad_type;
- }
-
-voidassign:
- err = "invalid use of void expression";
- goto error;
-nolvalue:
- err = "lvalue required in operation";
- goto error;
-nocomplete:
- err = "invalid use of indefined type";
- goto error;
-bad_type:
- err = "incorrect type in arithmetic operation";
- goto error;
-const_mod:
- err = "const value modified";
-error:
- error(err);
-}
-
-static Node *
-address(char op, Node *np)
-{
- char *err;
-
- if (!np->b.lvalue)
- goto no_lvalue;
- if (np->b.symbol && np->u.sym->s.isregister)
- goto reg_address;
- return unarycode(op, mktype(np->type, PTR, NULL, 0), np);
-
-no_lvalue:
- err = "lvalue required in unary expression";
- goto error;
-reg_address:
- err = "address of register variable '%s' requested";
-error:
- error(err);
-}
-
-static Node *
-content(char op, Node *np)
-{
- switch (np->typeop) {
- case ARY: case FTN:
- np = addr2ptr(np);
- case PTR:
- np = unarycode(op, np->utype->type, np);
- np->b.lvalue = 1;
- return np;
- default:
- error("invalid argument of unary '*'");
- }
-}
-
-static Node *
-negation(char op, Node *np)
-{
- switch (np->typeop) {
- case FTN: case ARY:
- np = addr2ptr(np);
- case INT: case FLOAT: case PTR:
- return exp2cond(np, 1);
- default:
- error("invalid argument of unary '!'");
- }
-}
-
-/*************************************************************
- * grammar functions *
- *************************************************************/
-static Node *
-primary(void)
-{
- Node *np;
- Symbol *sym;
-
- switch (yytoken) {
- case STRING: case CONSTANT: case IDEN:
- if ((sym = yylval.sym) == NULL)
- error("'%s' undeclared", yytext);
- np = symcode(yylval.sym);
- if (yytoken == IDEN) {
- np->b.lvalue = 1;
- np->b.constant = 0;
- }
- next();
- break;
- case '(':
- next();
- np = expr();
- expect(')');
- break;
- default:
- error("unexpected '%s'", yytext);
- }
- return np;
-}
-
-static Node *
-postfix(void)
-{
- register Node *np1, *np2;
-
- np1 = primary();
- for (;;) {
- switch (yytoken) {
- case '[':
- next();
- np2 = expr();
- np1 = array(np1, np2);
- expect(']');
- break;
- case DEC: case INC:
- np1 = incdec(np1, (yytoken == INC) ? OINC : ODEC);
- next();
- break;
- /* TODO: case '.': */
- /* TODO: case INDIR: */
- /* TODO: case '(' */
- default:
- return np1;
- }
- }
-}
-
-static Node *cast(void);
-
-static Node *
-unary(void)
-{
- register Node *(*fun)(char, Node *);
- register char op;
- Type *tp;
- char *err;
-
- switch (yytoken) {
- case SIZEOF:
- next();
- if (yytoken == '(' && ahead() == TYPE) {
- next();
- tp = typename();
- expect(')');
- } else {
- tp = unary()->type;
- /* TODO: Free memory */
- }
- return sizeofcode(tp);
- case INC: case DEC:
- op = (yytoken == INC) ? OA_ADD : OA_SUB;
- next();
- return incdec(unary(), op);
- case '!': op = 0; fun = negation; break;
- case '+': op = OADD; fun = integeruop; break;
- case '-': op = OSUB; fun = integeruop; break;
- case '~': op = ONEG; fun = integeruop; break;
- case '&': op = OADDR; fun = address; break;
- case '*': op = OPTR; fun = content; break;
- default: return postfix();
- }
-
- next();
- return (*fun)(op, cast());
-}
-
-static Node *
-cast(void)
-{
- Type *tp;
- register Node *np1, *np2;
-
- if (yytoken == '(') {
- switch(ahead()) {
- case TQUALIFIER: case TYPE:
- next();
- tp = typename();
- expect(')');
- np1 = eval(cast());
- if ((np2 = convert(np1, tp, 1)) == NULL)
- error("bad type convertion requested");
- np2->b.lvalue = np1->b.lvalue;
- return np2;
- default:
- break;
- }
- }
-
- return unary();
-}
-
-static Node *
-mul(void)
-{
- register Node *np, *(*fun)(char, Node *, Node *);
- register char op;
-
- np = cast();
- for (;;) {
- switch (yytoken) {
- case '*': op = OMUL; fun = arithmetic; break;
- case '/': op = ODIV; fun = arithmetic; break;
- case '%': op = OMOD; fun = integerop; break;
- default: return np;
- }
- next();
- np = (*fun)(op, np, cast());
- }
-}
-
-static Node *
-add(void)
-{
- register char op;
- register Node *np;
-
- np = mul();
- for (;;) {
- switch (yytoken) {
- case '+': op = OADD; break;
- case '-': op = OSUB; break;
- default: return np;
- }
- next();
- np = arithmetic(op, np, mul());
- }
-}
-
-static Node *
-shift(void)
-{
- register char op;
- register Node *np;
-
- np = add();
- for (;;) {
- switch (yytoken) {
- case SHL: op = OSHL; break;
- case SHR: op = OSHR; break;
- default: return np;
- }
- next();
- np = integerop(op, np, add());
- }
-}
-
-static Node *
-relational(void)
-{
- register char op;
- register Node *np;
-
- np = shift();
- for (;;) {
- switch (yytoken) {
- case '<': op = OLT; break;
- case '>': op = OGT; break;
- case GE: op = OGE; break;
- case LE: op = OLE; break;
- default: return np;
- }
- next();
- np = compare(op, np, shift());
- }
-}
-
-static Node *
-eq(void)
-{
- register char op;
- register Node *np;
-
- np = relational();
- for (;;) {
- switch (yytoken) {
- case EQ: op = OEQ; break;
- case NE: op = ONE; break;
- default: return np;
- }
- next();
- np = compare(op, np, relational());
- }
-}
-
-static Node *
-bit_and(void)
-{
- register Node *np;
-
- np = eq();
- while (accept('&'))
- np = integerop(OBAND, np, eq());
- return np;
-}
-
-static Node *
-bit_xor(void)
-{
- register Node *np;
-
- np = bit_and();
- while (accept('^'))
- np = integerop(OBXOR, np, bit_and());
- return np;
-}
-
-static Node *
-bit_or(void)
-{
- register Node *np;
-
- np = bit_xor();
- while (accept('|'))
- np = integerop(OBOR, np, bit_xor());
- return np;
-}
-
-static Node *
-and(void)
-{
- register Node *np;
-
- np = bit_or();
- while (accept(AND))
- np = logic(OAND, np, bit_or());
- return np;
-}
-
-static Node *
-or(void)
-{
- register Node *np;
-
- np = and();
- while (accept(OR))
- np = logic(OOR, np, and());
- return np;
-}
-
-static Node *
-ternary(void)
-{
- Node *np, *ifyes, *ifno;
-
- np = or();
- while (accept('?')) {
- ifyes = promote(expr());
- expect(':');
- ifno = promote(ternary());
- typeconv(&ifyes, &ifno);
- np = ternarycode(iszero(np), ifyes, ifno);
- }
- return np;
-}
-
-static Node *
-assign(void)
-{
- register Node *np, *(*fun)(char , Node *, Node *);
- register char op;
- char *err;
-
- np = ternary();
- for (;;) {
- switch (yytoken) {
- case '=': op = OASSIGN; fun = assignop; break;
- case MUL_EQ: op = OA_MUL; fun = arithmetic; break;
- case DIV_EQ: op = OA_DIV; fun = arithmetic; break;
- case MOD_EQ: op = OA_MOD; fun = integerop; break;
- case ADD_EQ: op = OA_ADD; fun = arithmetic; break;
- case SUB_EQ: op = OA_SUB; fun = arithmetic; break;
- case SHL_EQ: op = OA_SHL; fun = integerop; break;
- case SHR_EQ: op = OA_SHR; fun = integerop; break;
- case AND_EQ: op = OA_AND; fun = integerop; break;
- case XOR_EQ: op = OA_XOR; fun = integerop; break;
- case OR_EQ: op = OA_OR; fun = integerop; break;
- default: return np;
- }
- if (!np->b.lvalue)
- goto nolvalue;
- if (np->utype == voidtype)
- goto voidassign;
- if (isconst(np->type->op))
- goto const_mod;
- next();
- np = (fun)(op, np, eval(assign()));
- }
-voidassign:
- err = "invalid use of void expression";
- goto error;
-const_mod:
- err = "const value modified";
- goto error;
-nolvalue:
- err = "lvalue required as left operand of assignment";
- goto error;
-error:
- error(err);
-}
-
-Node *
-expr(void)
-{
- register Node *np1, *np2;
-
- np1 = assign();
- while (accept(',')) {
- np2 = assign();
- np1 = bincode(OCOMMA, np2->type, np1, np2);
- }
-
- return np1;
-}
--- a/lex.c
+++ /dev/null
@@ -1,438 +1,0 @@
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "cc1.h"
-#include "sizes.h"
-
-static FILE *yyin;
-const char *filename;
-unsigned linenum;
-
-uint8_t yytoken, yyntoken;;
-union yystype yylval;
-char yytext[IDENTSIZ + 1];
-
-static union yystype yynlval;
-static char yybuf[IDENTSIZ + 1];
-
-static uint8_t
-integer(char *s, char base)
-{
- static Type *tp;
- static Symbol *sym;
- static char ch, size, sign;
- static long v;
-
- size = sign = 0;
-type:
- switch (ch = toupper(getc(yyin))) {
- case 'L':
- if (size == LONG + LONG)
- goto wrong_type;
- size += LONG;
- goto type;
- case 'U':
- if (sign == UNSIGNED)
- goto wrong_type;
- goto type;
- default:
- ungetc(ch, yyin);
- tp = ctype(INT, sign, size);
- break;
- wrong_type:
- error("invalid suffix in integer constant");
- }
-
- sym = install("", NS_IDEN);
- sym->type = tp;
- v = strtol(yybuf, NULL, base);
- if (tp == inttype)
- sym->u.i = v;
- yynlval.sym = sym;
- return CONSTANT;
-}
-
-static uint8_t
-number(void)
-{
- register char ch, *bp;
- static char base;
-
- if ((ch = getc(yyin)) == '0') {
- if (toupper(ch = getc(yyin)) == 'X') {
- base = 16;
- } else {
- base = 8;
- ungetc(ch, yyin);
- }
- } else {
- base = 10;
- ungetc(ch, yyin);
- }
-
- for (bp = yybuf ; bp < &yybuf[IDENTSIZ]; *bp++ = ch) {
- ch = getc(yyin);
- switch (base) {
- case 8:
- if (ch >= '7')
- goto end;
- /* passthru */
- case 10:
- if (!isdigit(ch))
- goto end;
- break;
- case 16:
- if (!isxdigit(ch))
- goto end;
- break;
- }
- }
-
-end:
- if (bp == &yybuf[IDENTSIZ])
- error("identifier too long %s", yybuf);
- *bp = '\0';
- ungetc(ch, yyin);
- return integer(yybuf, base);
-}
-
-static char *
-escape(char *s)
-{
- char c;
-
-repeat:
- switch (getc(yyin)) {
- case '\\': c = '\''; break;
- case 'a': c = '\a'; break;
- case 'f': c = '\f'; break;
- case 'n': c = '\n'; break;
- case 'r': c = '\r'; break;
- case 't': c = '\t'; break;
- case 'v': c = '\v'; break;
- case '\'': c = '\\'; break;
- case '"': c ='"'; break;
- case '?': c = '?'; break;
- case 'x': /* TODO: */
- case '0': /* TODO: */
- case 'u': /* TODO: */
- case '\n':
- ++linenum;
- if ((c = getc(yyin)) == '\\')
- goto repeat;
- break;
- default:
- warn(1, "unknown escape sequence");
- return s;
- }
-
- *s = c;
- return ++s;
-}
-
-static uint8_t
-character(void)
-{
- static char c;
- register Symbol *sym;
-
- getc(yyin); /* discard the initial ' */
- c = getc(yyin);
- if (c == '\\')
- escape(&c);
- if (getc(yyin) != '\'')
- error("invalid character constant");
- sym = install("", NS_IDEN);
- sym->u.i = c;
- sym->type = inttype;
- yynlval.sym = sym;
- return CONSTANT;
-}
-
-static uint8_t
-string(void)
-{
- static char buf[STRINGSIZ+1];
- register char *bp;
- register int c;
- static Symbol *sym;
-
- getc(yyin); /* discard the initial " */
-
- for (bp = buf; bp < &buf[STRINGSIZ]; ) {
- switch (c = getc(yyin)) {
- case EOF:
- error("found EOF while parsing");
- case '"':
- goto end_string;
- case '\\':
- bp = escape(bp);
- break;
- default:
- *bp++ = c;
- }
- }
-
-end_string:
- if (bp == &buf[IDENTSIZ])
- error("string too long");
- *bp = '\0';
- sym = install("", NS_IDEN);
- sym->u.s = xstrdup(buf);
- sym->type = mktype(chartype, PTR, NULL, 0);
- yynlval.sym = sym;
- return STRING;
-}
-
-void
-init_keywords(void)
-{
- static struct {
- char *str;
- uint8_t token, value;
- } *bp, buff[] = {
- {"auto", SCLASS, AUTO},
- {"break", BREAK, BREAK},
- {"_Bool", TYPE, BOOL},
- {"case", CASE, CASE},
- {"char", TYPE, CHAR},
- {"const", TQUALIFIER, CONST},
- {"continue", CONTINUE, CONTINUE},
- {"default", DEFAULT, DEFAULT},
- {"do", DO, DO},
- {"double", TYPE, DOUBLE},
- {"else", ELSE, ELSE},
- {"enum", TYPE, ENUM},
- {"extern", SCLASS, EXTERN},
- {"float", TYPE, FLOAT},
- {"for", FOR, FOR},
- {"goto", GOTO, GOTO},
- {"if", IF, IF},
- {"int", TYPE, INT},
- {"long", TYPE, LONG},
- {"register", SCLASS, REGISTER},
- {"restrict", TQUALIFIER, RESTRICT},
- {"return", RETURN, RETURN},
- {"short", TYPE, SHORT},
- {"signed", TYPE, SIGNED},
- {"sizeof", SIZEOF, SIZEOF},
- {"static", SCLASS, STATIC},
- {"struct", TYPE, STRUCT},
- {"switch", SWITCH, SWITCH},
- {"typedef", SCLASS, TYPEDEF},
- {"union", TYPE, UNION},
- {"unsigned", TYPE, UNSIGNED},
- {"void", TYPE, VOID},
- {"volatile", TQUALIFIER, VOLATILE},
- {"while", WHILE, WHILE},
- {NULL, 0, 0},
- };
- register Symbol *sym;
- extern short symid;
-
- for (bp = buff; bp->str; ++bp) {
- sym = install(bp->str, NS_IDEN);
- sym->token = bp->token;
- sym->u.token = bp->value;
- }
- symid = 0;
-}
-
-static uint8_t
-iden(void)
-{
- register char *bp;
- register int c;
- Symbol *sym;
-
- 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(c, yyin);
-
- sym = lookup(yybuf, NS_IDEN);
- if (!sym || sym->token == IDEN) {
- yynlval.sym = sym;
- return IDEN;
- }
- yynlval.token = sym->u.token;
- return sym->token;
-}
-
-static uint8_t
-follow(int expect, int ifyes, int ifno)
-{
- register int c = getc(yyin);
-
- if (c == expect) {
- yybuf[1] = c;
- yybuf[2] = 0;
- return ifyes;
- }
- ungetc(c, yyin);
- return ifno;
-}
-
-static uint8_t
-minus(void)
-{
- register int c = getc(yyin);
-
- yybuf[1] = c;
- yybuf[2] = '\0';
- switch (c) {
- case '-': return DEC;
- case '>': return INDIR;
- case '=': return SUB_EQ;
- default:
- yybuf[1] = '\0';
- ungetc(c, yyin);
- return '-';
- }
-}
-
-static uint8_t
-plus(void)
-{
- register int c = getc(yyin);
-
- yybuf[1] = c;
- yybuf[2] = '\0';
- switch (c) {
- case '+': return INC;
- case '=': return ADD_EQ;
- default:
- yybuf[1] = '\0';
- ungetc(c, yyin);
- return '+';
- }
-}
-
-static uint8_t
-relational(uint8_t op, uint8_t equal, uint8_t shift, uint8_t assig)
-{
- register int c = getc(yyin);
-
- yybuf[1] = c;
- yybuf[2] = '\0';
-
- if (c == '=')
- return equal;
- if (c == op)
- return follow('=', assig, shift);
- ungetc(c, yyin);
- yybuf[1] = '\0';
- return op;
-}
-
-static uint8_t
-logic(uint8_t op, uint8_t equal, uint8_t logic)
-{
- register int c = getc(yyin);
-
- yybuf[1] = c;
- yybuf[2] = '\0';
-
- if (c == '=')
- return equal;
- if (c == op)
- return logic;
- ungetc(c, yyin);
- yybuf[1] = '\0';
- return op;
-}
-
-static uint8_t
-operator(void)
-{
- register uint8_t c = getc(yyin);
-
- yybuf[0] = c;
- yybuf[1] = '\0';
- switch (c) {
- case '<': return relational('<', LE, SHL, SHL_EQ);
- case '>': return relational('>', GE, SHR, SHR_EQ);
- case '&': return logic('&', AND_EQ, AND);
- case '|': return logic('|', OR_EQ, OR);
- case '=': return follow('=', EQ, '=');
- case '^': return follow('=', XOR_EQ, '^');
- case '*': return follow('=', MUL_EQ, '*');
- case '/': return follow('=', DIV_EQ, '/');
- case '!': return follow('=', NE, '!');
- case '-': return minus();
- case '+': return plus();
- default: return c;
- }
-}
-
-uint8_t
-next(void)
-{
- static int c;
- extern int8_t forbid_eof;
-
- strcpy(yytext, yybuf);
- yylval = yynlval;
- if ((yytoken = yyntoken) == EOFTOK) {
- if (forbid_eof)
- error("Find EOF while parsing");
- goto ret;
- }
-
- while (isspace(c = getc(yyin))) {
- if (c == '\n')
- ++linenum;
- }
-
- if (c == EOF) {
- yyntoken = EOFTOK;
- goto ret;
- }
-
- ungetc(c, yyin);
- if (isalpha(c) || c == '_')
- yyntoken = iden();
- else if (isdigit(c))
- yyntoken = number();
- else if (c == '"')
- yyntoken = string();
- else if (c == '\'')
- yyntoken = character();
- else
- yyntoken = operator();
-
-ret: return yytoken;
-}
-
-void
-expect(register uint8_t tok)
-{
- if (yytoken != tok)
- error("unexpected %s", yytext);
- next();
-}
-
-void
-open_file(register const char *file)
-{
- if (yyin != NULL)
- fclose(yyin);
- if (file == NULL) {
- yyin = stdin;
- filename = "(stdin)";
- } else {
- if ((yyin = fopen(file, "r")) == NULL)
- die("file '%s' not found", file);
- filename = file;
- }
- linenum = 1;
- next(); /* prefetch first token */
-}
--- a/main.c
+++ /dev/null
@@ -1,25 +1,0 @@
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-
-#include "cc1.h"
-
-extern void init_keywords(void),
- open_file(const char *file), init_expr(void);
-
-struct user_opt options;
-
-int
-main(int argc, char *argv[])
-{
- setvbuf(stdin, NULL, _IONBF, 0);
- setvbuf(stdout, NULL, _IONBF, 0);
- init_keywords();
- init_expr();
- open_file(NULL);
- for (next(); yytoken != EOFTOK; extdecl());
- /* nothing */;
-
- return 0;
-}
--- a/opcode.txt
+++ /dev/null
@@ -1,133 +1,0 @@
-Ax -> automatic variable number x
-Tx -> static variable number x
-Gx -> global variable with name x
-Xx -> global function with name x
-Yx -> static function with name x
-Lx -> label number x
-Px -> parameter number x
-Mx -> member number x
-
-@ -> content of variable
-#x -> size of type x (R, I, C, W, N, Z, Q, H, Sx, Ux)
-#x -> integer constant of value x
-##x -> float constant of value x
-#%x -> long constant of value x
-" -> begin of string, each element is coded in decimal and comma (better in hexa!!)
-a -> take address
-:x -> assign of type x
-+x -> sum of type x
--x -> substraction of type x
-*x -> multiplication of type x
-/x -> division of type x
-; -> used in post operators (A2++ -> A2 #1 ;+I)
-: -> used in pre operators (++A2 -> A2 #1 :+I)
-. -> struct field
-_x -> sign negation of type x
-~x -> logic negation of type x
-%x -> modulo of type x
-lx -> left shift of type x
-rx -> right shift of type x
->x -> greater than of type x
-<x -> less than of type x
-[x -> less or equal of type x
-]x -> greater or equal of type x
-=x -> equal of type x
-!x -> not equal of type x
-&x -> logical and of type x
-|x -> logical or of type x
-^x -> logical exor of type x
-m -> and (last two stack values)
-s -> or (last two stack values)
-` -> index array (*(val1 + val2))
-:yx -> operation y and assign of type x
-:x -> assign of type x
-?x -> ternary of type x (cond val1 val2)
-cx -> call to function of type x
-px -> pass parameter to function of type x
-Fx -> x number of parameters passed in a function call
-, -> comma operator (last two stack values)
-d -> begin of loop
-b -> end of loop
-j -> jump (next stack value is the label)
-yx -> return of type x
-ex -> switch of type x
-w -> case (next stack value is label and next is value)
-n -> no operation (it is used in ! and in for conditions)
-E -> no operation (it is used to mark end of function declaration)
-
-Conversions:
-----------
-Sx -> struct number x
-Ux -> union number x
-Vx -> vector number x
-R -> pointer
-I -> integer
-C -> char
-W -> long
-N -> unsigned
-Z -> unsigned long
-Q -> float
-H -> double
-F -> function
-
-
-xy -> conversion from y to x
-
-
-Examples:
----------
-
-int
-main()
-{
- int i;
- float v = 3.0;
-
- i = i != v;
-}
-
-->
-
-Xmain I F E
-{
-A1 I
-A2 I
-A3 Q
- A3 ##4130000 QH :Q
- A1 A1 QI A3 !Q #1 #0 ?I :I
-}
-
--------------------------------------------
-
-struct pepe {
- int i, j;
- struct p2 {
- int k;
- } k;
-};
-
-int
-main()
-{
- int i;
- struct pepe p;
-
- i += p.i + p.k.k;
-}
-
-->
-
-S4 (
-M5 I
-)
-S1 (
-M2 I
-M3 I
-M6 S4
-)
-Xmain I F E
-{
-A7 I
-A8 S1
- A7 A8 M2 . A8 M6 . M5 . +I :+I
-}
--- a/sizes.h
+++ /dev/null
@@ -1,88 +1,0 @@
-#ifndef SIZES_H
-#define SIZES_H
-
-/*
- * 15 nesting levels of compound statements, iteration control
- * structures, and selection control structures
- */
-#define NR_BLOCK 15
-/*
- * 8 nesting levels of conditional inclusion
- */
-#define NR_COND 8
-/*
- * number of defined structs/unions in one translation unit
- */
-#define NR_MAXSTRUCTS 127
-/*
- * 12 pointer, array, and function declarators (in any combinations)
- * modifying an arithmetic, a structure, a union, or an incomplete type
- * in a declaration
- */
-#define NR_DECLARATORS 12
-/*
- * 31 declarators nested by parentheses within a full declarator.
- */
-#define NR_SUBTYPE 31
-/*
- * 32 expressions nested by parentheses within a full expression
- */
-#define NR_SUBEXPR 32
-/*
- * 31 significant initial characters in an internal identifier or a
- * macro name
- */
-#define IDENTSIZ 31
-/*
- * 511 external identifiers in one translation unit
- */
-#define NR_EXT_IDENT 511
-/*
- * 127 identifiers with block scope declared in one block
- */
-#define NR_INT_IDENT 127
-/*
- * 31 parameters in one function definition * 6 significant initial
- * characters in an external identifier.
- */
-#define NR_FUNPARAM 31
-/*
- * 31 parameters in one macro definition
- */
-#define NR_MACROARG 31
-/*
- * 509 characters in a logical source line.
- */
-#define LINESIZ 509
-/*
- * 509 characters in a character string literal or wide string literal
- * (after concatenation)
- */
-#define STRINGSIZ 509
-/*
- * 8 nesting levels for #include'd files
- */
-#define NR_INCLUDE 9
-/*
- * 257 case labels for a switch statement (excluding those for any
- * nested switch statements)
- */
-#define NR_SWITCH 257
-/*
- * 127 members in a single structure or union
- */
-#define NR_FIELDS 127
-/*
- * 127 enumeration constants in a single enumeration
- */
-#define NR_ENUM_CTES 127
-/*
- * 15 levels of nested structure or union definitions in a single
- * struct-declaration-list
- */
-#define NR_STRUCT_LEVEL 15
-/*
- * 32767 bytes in an object (in a hosted environment only)
- */
-#define OBJECTSIZ 32767
-#endif
--- a/stmt.c
+++ /dev/null
@@ -1,329 +1,0 @@
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-
-#include "cc1.h"
-
-struct scase {
- Symbol *label;
- Node *expr;
- struct scase *next;
-};
-
-struct caselist {
- short nr;
- Symbol *deflabel;
- struct scase *head;
-};
-
-Symbol *curfun;
-
-extern Node *convert(Node *np, Type *tp1, char iscast);
-extern Node *iszero(Node *np), *eval(Node *np);
-static void stmt(Symbol *lbreak, Symbol *lcont, Caselist *lswitch);
-
-static Symbol *
-label(char *s, char define)
-{
- Symbol *sym;
-
- if (s) {
- if ((sym = lookup(s, NS_LABEL)) != NULL) {
- if (define && sym->s.isdefined)
- error("label '%s' already defined", s);
- else
- sym->s.isdefined = 1;
- return sym;
- }
- } else {
- s = "";
- }
-
- sym = install(s, NS_LABEL);
- sym->s.isdefined = define;
- return sym;
-}
-
-static void
-stmtexp(void)
-{
- if (accept(';'))
- return;
- emitexp(expr());
- expect(';');
-}
-
-static Node *
-condition(void)
-{
- Node *np;
-
- expect('(');
- np = iszero(expr());
- expect(')');
- return np;
-}
-
-static void
-While(Caselist *lswitch)
-{
- Symbol *begin, *cond, *end;
- Node *np;
-
- begin = label(NULL, 1);
- end = label(NULL, 1);
- cond = label(NULL, 1);
-
- expect(WHILE);
- np = condition();
- emitjump(cond, NULL);
- emitbloop();
- emitlabel(begin);
- stmt(end, begin, lswitch);
- emitlabel(cond);
- emitjump(begin, np);
- emiteloop();
- emitlabel(end);
-}
-
-static void
-For(Caselist *lswitch)
-{
- Symbol *begin, *cond, *end;
- Node *econd = NULL, *einc = NULL;
-
- begin = label(NULL, 1);
- end = label(NULL, 1);
- cond = label(NULL, 1);
-
- expect(FOR);
- expect('(');
- stmtexp();
-
- if (yytoken != ';')
- econd = expr();
- expect(';');
- if (yytoken != ')')
- einc = expr();
- expect(')');
-
- emitjump(cond, NULL);
- emitbloop();
- emitlabel(begin);
- stmt(end, begin, lswitch);
- if (einc)
- emitexp(einc);
- emitlabel(cond);
- emitjump(begin, econd);
- emiteloop();
- emitlabel(end);
-}
-
-static void
-Dowhile(Caselist *lswitch)
-{
- Symbol *begin= label(NULL, 1), *end = label(NULL, 1);
-
-
- expect(DO);
- emitbloop();
- emitlabel(begin);
- stmt(end, begin, lswitch);
- expect(WHILE);
- emitjump(begin, condition());
- emiteloop();
- emitlabel(end);
-}
-
-static void
-Return(void)
-{
- Node *np;
- Type *tp = curfun->type->type;
-
- expect(RETURN);
- np = (yytoken == ';') ? NULL : eval(expr());
- expect(';');
- if (!np) {
- if (tp != voidtype)
- warn(1, "function returning non void returns no value");
- tp = voidtype;
- } else if (np->type != tp) {
- if (tp == voidtype)
- warn(1, "function returning void returns a value");
- else if ((np = convert(np, tp, 0)) == NULL)
- error("incorrect type in return");
- }
- emitret(tp);
- emitexp(np);
-}
-
-static void
-Break(Symbol *lbreak)
-{
- expect(BREAK);
- if (!lbreak)
- error("break statement not within loop or switch");
- emitjump(lbreak, NULL);
- expect(';');
-}
-
-static void
-Label(void)
-{
- emitlabel(label(yytext, 1));
-
- expect(IDEN);
- expect(':');
-}
-
-static void
-Continue(Symbol *lcont)
-{
- expect(CONTINUE);
- if (!lcont)
- error("continue statement not within loop");
- emitjump(lcont, NULL);
- expect(';');
-}
-
-static void
-Goto(void)
-{
- expect(GOTO);
-
- if (yytoken != IDEN)
- error("unexpected '%s'", yytext);
- emitjump(label(yytext, 0), NULL);
- next();
- expect(';');
-}
-
-static void
-Switch(Symbol *lcont)
-{
- Caselist lcase = {.nr = 0, .head = NULL, .deflabel = NULL};
- struct scase *p;
- Symbol *lbreak = label(NULL, 1), *lcond = label(NULL, 1);
- Node *cond;
-
- expect(SWITCH);
- expect ('(');
- cond = eval(expr());
- expect (')');
- /* TODO: check integer type */
- emitjump(lcond, NULL);
- stmt(lbreak, lcont, &lcase);
- emitlabel(lcond);
- emitswitch(lcase.nr, cond);
- for (p = lcase.head; p; p = p->next)
- emitcase(p->label, p->expr);
- if (lcase.deflabel)
- emitdefault(lcase.deflabel);
- emitlabel(lbreak);
- /* TODO: free memory */
-}
-
-static void
-Case(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
-{
- Node *np;
- Symbol *lcase = label(NULL, 1);
- struct scase *pcase;
-
- if (!lswitch)
- error("case label not within a switch statement");
- expect(CASE);
- if (yytoken == ':')
- error("expected expression before ':'");
- np = eval(expr());
- /* TODO: check integer type */
- expect(':');
- emitlabel(lcase);
- pcase = xmalloc(sizeof(*pcase));
- pcase->expr = np;
- pcase->label = lcase;
- pcase->next = lswitch->head;
- lswitch->head = pcase;
- ++lswitch->nr;
-}
-
-static void
-Default(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
-{
- Symbol *ldefault = label(NULL, 1);
-
- expect(DEFAULT);
- expect(':');
- emitlabel(ldefault);
- lswitch->deflabel = ldefault;
-}
-
-static void
-If(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
-{
- Symbol *end, *lelse = label(NULL, 1);
- Node *np;
-
- expect(IF);
- np = condition();
- NEGATE(np, 1);
- emitjump(lelse, np);
- stmt(lbreak, lcont, lswitch);
- if (accept(ELSE)) {
- end = label(NULL, 1);
- emitjump(end, NULL);
- emitlabel(lelse);
- stmt(lbreak, lcont, lswitch);
- emitlabel(end);
- } else {
- emitlabel(lelse);
- }
-}
-
-void
-compound(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
-{
- expect('{');
- for (;;) {
- switch (yytoken) {
- case '}':
- next();
- return;
- case TYPE: case SCLASS: case TQUALIFIER:
- decl();
- break;
- default:
- stmt(lbreak, lcont, lswitch);
- }
- }
-}
-
-static void
-stmt(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
-{
-
-repeat:
- switch (yytoken) {
- case '{': compound(lbreak, lcont, lswitch); break;
- case RETURN: Return(); break;
- case WHILE: While(lswitch); break;
- case FOR: For(lswitch); break;
- case DO: Dowhile(lswitch); break;
- case IF: If(lbreak, lcont, lswitch); break;
- case BREAK: Break(lbreak); break;
- case CONTINUE: Continue(lcont); break;
- case GOTO: Goto(); break;
- case SWITCH: Switch(lcont); break;
- case CASE: Case(lbreak, lcont, lswitch); break;
- case DEFAULT: Default(lbreak, lcont, lswitch); break;
- case IDEN:
- if (ahead() == ':') {
- Label();
- goto repeat;
- }
- default: stmtexp(); break;
- }
-}
-
--- a/symbol.c
+++ /dev/null
@@ -1,103 +1,0 @@
-
-#include <stdint.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "cc1.h"
-
-#define NR_SYM_HASH 32
-
-uint8_t curctx;
-uint8_t namespace = NS_FREE + 1;
-short symid;
-
-static struct symtab {
- Symbol *head;
- Symbol *htab[NR_SYM_HASH];
-} symtab [NR_NAMESPACES];
-
-static inline uint8_t
-hash(register const char *s)
-{
- register uint8_t h, ch;
-
- for (h = 0; ch = *s++; h += ch)
- /* nothing */;
- return h & NR_SYM_HASH - 1;
-}
-
-void
-freesyms(uint8_t ns)
-{
- static struct symtab *tbl;
- register Symbol *sym, *next;
-
- tbl = &symtab[(ns >= NR_NAMESPACES) ? NS_IDEN : ns];
- for (sym = tbl->head; sym; sym = next) {
- if (sym->ctx <= curctx)
- break;
- if (ns == NS_LABEL && !sym->s.isdefined)
- error("label '%s' is not defined", sym->name);
- tbl->htab[hash(sym->name)] = sym->hash;
- next = tbl->head = sym->next;
- free(sym->name);
- free(sym);
- }
-}
-
-void
-context(Ctxfun *fun, Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
-{
- uint8_t ns;
-
- ns = namespace;
- ++curctx;
- (*fun)(lbreak, lcont, lswitch);
- --curctx;
- namespace = ns;
-
- freesyms(NS_IDEN);
- freesyms(NS_TAG);
-}
-
-Symbol *
-lookup(register char *s, uint8_t ns)
-{
- extern union yystype yylval;
- static struct symtab *tbl;
- register Symbol *sym;
-
- 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;
- }
-
- return NULL;
-}
-
-Symbol *
-install(char *s, uint8_t ns)
-{
- register Symbol *sym, **t;
- struct symtab *tbl;
-
- sym = xcalloc(1, sizeof(*sym));
- sym->name = xstrdup(s);
- sym->ctx = curctx;
- sym->token = IDEN;
- sym->ns = ns;
- sym->id = symid++;
- 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/types.c
+++ /dev/null
@@ -1,198 +1,0 @@
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "sizes.h"
-#include "cc1.h"
-
-#define NR_TYPE_HASH 16
-
-Type
- *voidtype = &(Type) {
- .op = VOID,
- .letter = 'W'
- },
- *pvoidtype = &(Type) {
- .op = PTR,
- .letter = 'R'
- },
- *booltype = &(Type) {
- .op = INT,
- .letter = 'B',
- .defined = 1,
- .u.rank = RANK_BOOL
- },
- *schartype = &(Type) {
- .op = INT,
- .letter = 'C',
- .defined = 1,
- .u.rank = RANK_SCHAR
- },
- *uchartype = &(Type) {
- .op = INT,
- .letter = 'M',
- .sign = 1,
- .defined = 1,
- .u.rank = RANK_UCHAR
- },
- *chartype = &(Type) {
- .op = INT,
- .letter = 'M',
- .sign = 1,
- .defined = 1,
- .u.rank = RANK_UCHAR
- },
- *ushortype = &(Type) {
- .op = INT,
- .letter = 'E',
- .defined = 1,
- .u.rank = RANK_USHORT
- },
- *shortype = &(Type) {
- .op = INT,
- .letter = 'K',
- .defined = 1,
- .u.rank = RANK_SHORT
- },
- *uinttype = &(Type) {
- .op = INT,
- .letter = 'U',
- .sign = 1,
- .defined = 1,
- .u.rank = RANK_UINT
- },
- *inttype = &(Type) {
- .op = INT,
- .letter = 'I',
- .defined = 1,
- .u.rank = RANK_INT
- },
- *longtype = &(Type) {
- .op = INT,
- .letter = 'L',
- .defined = 1,
- .u.rank = RANK_LONG
- },
- *ulongtype = &(Type) {
- .op = INT,
- .letter = 'Z',
- .sign = 1,
- .defined = 1,
- .u.rank = RANK_ULONG
- },
- *ullongtype = &(Type) {
- .op = INT,
- .letter = 'O',
- .sign = 1,
- .defined = 1,
- .u.rank = RANK_ULLONG
- },
- *llongtype = &(Type) {
- .op = INT,
- .letter = 'J',
- .defined = 1,
- .u.rank = RANK_LLONG
- },
- *floattype = &(Type) {
- .op = FLOAT,
- .letter = 'F',
- .defined = 1,
- .u.rank = RANK_FLOAT
- },
- *doubletype = &(Type) {
- .op = FLOAT,
- .letter = 'D',
- .defined = 1,
- .u.rank = RANK_DOUBLE
- },
- *ldoubletype = &(Type) {
- .op = FLOAT,
- .letter = 'H',
- .defined = 1,
- .u.rank = RANK_LDOUBLE
- };
-
-Type *
-ctype(int8_t type, int8_t sign, int8_t size)
-{
- if (type == DOUBLE)
- type = FLOAT, size += LONG;
-
- switch (type) {
- case CHAR: if (sign == 0)
- return chartype;
- return (sign == UNSIGNED) ? uchartype : schartype;
- case VOID: return voidtype;
- case BOOL: return booltype;
- case INT: switch (size) {
- case 0: return (sign == UNSIGNED) ? uinttype : inttype;
- case SHORT: return (sign == UNSIGNED) ? ushortype : shortype;
- case LONG: return (sign == UNSIGNED) ? ulongtype : longtype;
- case LONG+LONG: return (sign == UNSIGNED) ? ullongtype : llongtype;
- }
- case FLOAT: switch (size) {
- case 0: return floattype;
- case LONG: return doubletype;
- case LONG+LONG: return ldoubletype;
- }
- }
-}
-
-Type *
-mktype(Type *tp, uint8_t op,
- Symbol *sym, uint16_t nelem)
-{
- static Type *typetab[NR_TYPE_HASH], **tbl;
- static uint8_t t;
- register Type *bp;
- char letter;
-
- if (op == PTR && tp == voidtype)
- return pvoidtype;
- t = (op ^ (uint8_t) ((unsigned short) tp >> 3))
- & NR_TYPE_HASH-1;
- tbl = &typetab[t];
- if (op != FTN || op != STRUCT || op != UNION || op != ENUM) {
- for (bp = *tbl; bp; bp = bp->next) {
- if (bp->type == tp && bp->op == op &&
- bp->sym == sym && bp->u.nelem == nelem) {
- return bp;
- }
- }
- }
-
- switch (op) {
- 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: letter = tp->letter;
- }
- bp = xmalloc(sizeof(*bp));
- bp->next = *tbl;
- bp->type = tp;
- bp->op = op;
- bp->u.nelem = nelem;
- bp->sym = sym;
- bp->letter = letter;
- return *tbl = bp;
-}
-
-Type *
-qualifier(Type *tp, uint8_t qlf)
-{
- uint8_t q = tp->op;
-
- if (!qlf)
- return tp;
- if (q & TQUALIFIER) {
- if (q == qlf)
- return tp;
- tp = tp->type;
- qlf |= q;
- }
- return mktype(tp, qlf|TQUALIFIER, NULL, 0);
-}
-
--- a/wrapper.c
+++ /dev/null
@@ -1,53 +1,0 @@
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <stdint.h>
-
-#include "cc1.h"
-
-
-static void
-out_of_memory(void)
-{
- /* TODO: deal with out of memory errors */
- error("out of memory");
-}
-
-void *
-xmalloc(size_t size)
-{
- register void *p = malloc(size);
-
- if (!p)
- out_of_memory();
- return p;
-}
-
-void *
-xcalloc(size_t nmemb, size_t size)
-{
- register size_t nbytes = nmemb * size;
- register void *p = xmalloc(nbytes);
-
- return memset(p, nbytes, 0);
-}
-
-char *
-xstrdup(const char *s)
-{
- register size_t len = strlen(s) + 1;
- register char *p = xmalloc(len);
-
- return memcpy(p, s, len);
-}
-
-void *
-xrealloc(void *buff, register size_t size)
-{
- register void *p = realloc(buff, size);
-
- if (!p)
- out_of_memory();
- return p;
-}