scc

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

commit e0b2f47525a1dc50a5089d2f472f1b51fbb0b483
parent 87f8ea372e925ddb1ab531130bfd3e989e73c5b5
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Fri, 25 Apr 2014 10:33:28 +0200

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.

Diffstat:
.gitignore | 4----
Makefile | 21---------------------
cc1.h | 259-------------------------------------------------------------------------------
cc1/.gitignore | 4++++
cc1/Makefile | 22++++++++++++++++++++++
cc1/cc1.h | 259+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cc1/code.c | 313+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cc1/decl.c | 536+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cc1/error.c | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
cc1/expr.c | 758+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cc1/lex.c | 438+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cc1/main.c | 25+++++++++++++++++++++++++
cc1/opcode.txt | 133+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cc1/sizes.h | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cc1/stmt.c | 329+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cc1/symbol.c | 103+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cc1/types.c | 198+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cc1/wrapper.c | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
code.c | 313-------------------------------------------------------------------------------
decl.c | 536-------------------------------------------------------------------------------
error.c | 52----------------------------------------------------
expr.c | 758-------------------------------------------------------------------------------
lex.c | 438-------------------------------------------------------------------------------
main.c | 25-------------------------
opcode.txt | 133-------------------------------------------------------------------------------
sizes.h | 88-------------------------------------------------------------------------------
stmt.c | 329-------------------------------------------------------------------------------
symbol.c | 103-------------------------------------------------------------------------------
types.c | 198-------------------------------------------------------------------------------
wrapper.c | 53-----------------------------------------------------
30 files changed, 3311 insertions(+), 3310 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1,4 +0,0 @@ -*.o -makefile -cc1 -TODO diff --git a/Makefile b/Makefile @@ -1,21 +0,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 diff --git a/cc1.h b/cc1.h @@ -1,259 +0,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 diff --git a/cc1/.gitignore b/cc1/.gitignore @@ -0,0 +1,4 @@ +*.o +makefile +cc1 +TODO diff --git a/cc1/Makefile b/cc1/Makefile @@ -0,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 diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -0,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 diff --git a/cc1/code.c b/cc1/code.c @@ -0,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; +} diff --git a/cc1/decl.c b/cc1/decl.c @@ -0,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); +} diff --git a/cc1/error.c b/cc1/error.c @@ -0,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); +} diff --git a/cc1/expr.c b/cc1/expr.c @@ -0,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; +} diff --git a/cc1/lex.c b/cc1/lex.c @@ -0,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 */ +} diff --git a/cc1/main.c b/cc1/main.c @@ -0,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; +} diff --git a/cc1/opcode.txt b/cc1/opcode.txt @@ -0,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 +} diff --git a/cc1/sizes.h b/cc1/sizes.h @@ -0,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 diff --git a/cc1/stmt.c b/cc1/stmt.c @@ -0,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; + } +} + diff --git a/cc1/symbol.c b/cc1/symbol.c @@ -0,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; +} diff --git a/cc1/types.c b/cc1/types.c @@ -0,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); +} + diff --git a/cc1/wrapper.c b/cc1/wrapper.c @@ -0,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; +} diff --git a/code.c b/code.c @@ -1,313 +0,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; -} diff --git a/decl.c b/decl.c @@ -1,536 +0,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); -} diff --git a/error.c b/error.c @@ -1,52 +0,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); -} diff --git a/expr.c b/expr.c @@ -1,758 +0,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; -} diff --git a/lex.c b/lex.c @@ -1,438 +0,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 */ -} diff --git a/main.c b/main.c @@ -1,25 +0,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; -} diff --git a/opcode.txt b/opcode.txt @@ -1,133 +0,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 -} diff --git a/sizes.h b/sizes.h @@ -1,88 +0,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 diff --git a/stmt.c b/stmt.c @@ -1,329 +0,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; - } -} - diff --git a/symbol.c b/symbol.c @@ -1,103 +0,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; -} diff --git a/types.c b/types.c @@ -1,198 +0,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); -} - diff --git a/wrapper.c b/wrapper.c @@ -1,53 +0,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; -}