From bfda462bca5db1693b2fa1c2845c8f4242d33782 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Thu, 19 Aug 2021 16:36:59 +0000 Subject: c4: use cases --- miniany/README | 19 ++- miniany/REQUIREMENTS | 12 +- miniany/TODOS | 10 +- miniany/c4.c | 437 ++++++++++++++++++++++++++------------------------- miniany/cc.c | 6 +- 5 files changed, 257 insertions(+), 227 deletions(-) diff --git a/miniany/README b/miniany/README index 851db39..f22c5f7 100644 --- a/miniany/README +++ b/miniany/README @@ -14,6 +14,23 @@ tcc -O0 -g -o c4 c4.c ./c4 c4.c c4.c cc.c < hello.c ``` +# Local version of c4 + +This local version of c4 is used to guarantee that our own bootstrapped +cc.c can also run on c4. This makes sure we are not integrating too +complex things into our own compiler. + +* currently integrated: + - switch statement from switch-and-structs, adapted c4 to use switch + statements instead of ifs (as in switch-and-structs) +* my own changes: + - constants like EOF, EXIT_SUCCESS, NULL + - standard C block comments along to c++ end of line ones + - negative enum initializers + - do/while loops + - more C functions like isspace, getc, strcmp + - some simplified functions for printing like putstring, putint, putnl + # Acknoledgments and references * c4 @@ -22,7 +39,7 @@ tcc -O0 -g -o c4 c4.c minimalistic C compiler running on an emulator on the IR, inspiration for this project * https://github.com/rswier/c4/blob/switch-and-structs/c4.c: - c4 adaptions to provide switch and structs: + c4 adaptions to provide switch and structs * https://github.com/EarlGray/c4: a X86 JIT version of c4 * https://github.com/jserv/amacc: based on C4, JIT or native code, for ARM, quite well documented, also very nice list of compiler diff --git a/miniany/REQUIREMENTS b/miniany/REQUIREMENTS index cd6ffcf..9274af4 100644 --- a/miniany/REQUIREMENTS +++ b/miniany/REQUIREMENTS @@ -10,10 +10,14 @@ implementing: not implementing: - libc - - printf - - format string only, as replacement for puts - - vararg required in compiler - - not type-safe + - variadic functions are not type-safe, do we need them? + - printf -> putint, putchar, etc. + - format string only, as replacement for puts + - vararg required in compiler + - not type-safe + - snprintf no option, strcat, strstr etc also not really + - newer formating functions and logging: strfmon, error, warn, syslog + - syscall - puts - requires stdout, which is a FILE structure - print_char diff --git a/miniany/TODOS b/miniany/TODOS index ed6e09e..07a0c81 100644 --- a/miniany/TODOS +++ b/miniany/TODOS @@ -1,12 +1,8 @@ +- c4 + - global char array declarations + - void parameter - avoid inline assembler, have more a inline bytecode adder explicit opcodes, e.g. nop -> .byte 0x90 -- read -1 problem is the c4.c as interpreter reading behaving wrongly - because -1 is wrongly handled in integer parsing -- variadic functions are not type-safe, do we need them? - - printf -> putint, putchar, etc. - - snprintf no option, strcat, strstr etc also not really - - newer formating functions and logging: strfmon, error, warn, syslog - - syscall diff --git a/miniany/c4.c b/miniany/c4.c index 9acba4e..990c527 100644 --- a/miniany/c4.c +++ b/miniany/c4.c @@ -1,7 +1,7 @@ // c4.c - C in four functions // char, int, and pointer types -// if, while, return, and expression statements +// if, while, do, return, switch and expression statements // just enough features to allow self-compilation and a bit more // Written by Robert Swierczek @@ -55,7 +55,8 @@ void next() while (tk = *p) { ++p; - if (tk == '\n') { + switch (tk) { + case '\n': if (src) { printf("%d: %.*s", line, p - lp, lp); lp = p; @@ -67,11 +68,23 @@ void next() } } ++line; - } - else if (tk == '#') { + break; + case '#': while (*p != 0 && *p != '\n') ++p; - } - else if ((tk >= 'a' && tk <= 'z') || (tk >= 'A' && tk <= 'Z') || tk == '_') { + break; + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': + case 'z': + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': + case 'Z': + case '_': pp = p - 1; while ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || *p == '_') tk = tk * 147 + *p++; @@ -85,8 +98,8 @@ void next() id[Hash] = tk; tk = id[Tk] = Id; return; - } - else if (tk >= '0' && tk <= '9') { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': if (ival = tk - '0') { while (*p >= '0' && *p <= '9') ival = ival * 10 + *p++ - '0'; } else if (*p == 'x' || *p == 'X') { while ((tk = *++p) && ((tk >= '0' && tk <= '9') || (tk >= 'a' && tk <= 'f') || (tk >= 'A' && tk <= 'F'))) @@ -95,8 +108,9 @@ void next() else { while (*p >= '0' && *p <= '7') ival = ival * 8 + *p++ - '0'; } tk = Num; return; - } - else if (tk == '/') { + case ' ': case '\t': + break; + case '/': if (*p == '/') { ++p; while (*p != 0 && *p != '\n') ++p; @@ -114,33 +128,39 @@ void next() tk = Div; return; } - } - else if (tk == '\'' || tk == '"') { + break; + case '\'': case '"': pp = data; while (*p != 0 && *p != tk) { if ((ival = *p++) == '\\') { - if ((ival = *p++) == 'n') ival = '\n'; + switch (ival = *p++) { + case 'n': ival = '\n'; break; + case 't': ival = '\t'; break; + } } if (tk == '"') *data++ = ival; } ++p; if (tk == '"') ival = (int)pp; else tk = Num; return; + case '=': if (*p == '=') { ++p; tk = Eq; } else tk = Assign; return; + case '+': if (*p == '+') { ++p; tk = Inc; } else tk = Add; return; + case '-': if (*p == '-') { ++p; tk = Dec; } else tk = Sub; return; + case '!': if (*p == '=') { ++p; tk = Ne; } return; + case '<': if (*p == '=') { ++p; tk = Le; } else if (*p == '<') { ++p; tk = Shl; } else tk = Lt; return; + case '>': if (*p == '=') { ++p; tk = Ge; } else if (*p == '>') { ++p; tk = Shr; } else tk = Gt; return; + case '|': if (*p == '|') { ++p; tk = Lor; } else tk = Or; return; + case '&': if (*p == '&') { ++p; tk = Lan; } else tk = And; return; + case '^': tk = Xor; return; + case '%': tk = Mod; return; + case '*': tk = Mul; return; + case '[': tk = Brak; return; + case '?': tk = Cond; return; + case '~': case ';': case '{': case '}': + case '(': case ')': case ']': case ',': + case ':': + return; } - else if (tk == '=') { if (*p == '=') { ++p; tk = Eq; } else tk = Assign; return; } - else if (tk == '+') { if (*p == '+') { ++p; tk = Inc; } else tk = Add; return; } - else if (tk == '-') { if (*p == '-') { ++p; tk = Dec; } else tk = Sub; return; } - else if (tk == '!') { if (*p == '=') { ++p; tk = Ne; } return; } - else if (tk == '<') { if (*p == '=') { ++p; tk = Le; } else if (*p == '<') { ++p; tk = Shl; } else tk = Lt; return; } - else if (tk == '>') { if (*p == '=') { ++p; tk = Ge; } else if (*p == '>') { ++p; tk = Shr; } else tk = Gt; return; } - else if (tk == '|') { if (*p == '|') { ++p; tk = Lor; } else tk = Or; return; } - else if (tk == '&') { if (*p == '&') { ++p; tk = Lan; } else tk = And; return; } - else if (tk == '^') { tk = Xor; return; } - else if (tk == '%') { tk = Mod; return; } - else if (tk == '*') { tk = Mul; return; } - else if (tk == '[') { tk = Brak; return; } - else if (tk == '?') { tk = Cond; return; } - else if (tk == '~' || tk == ';' || tk == '{' || tk == '}' || tk == '(' || tk == ')' || tk == ']' || tk == ',' || tk == ':') return; } } @@ -148,22 +168,23 @@ void expr(int lev) { int t, *d; - if (!tk) { printf("%d: unexpected eof in expression\n", line); exit(-1); } - else if (tk == Num) { *++e = IMM; *++e = ival; next(); ty = INT; } - else if (tk == '"') { + switch (tk) { + case 0: printf("%d: unexpected eof in expression\n", line); exit(-1); + case Num: *++e = IMM; *++e = ival; next(); ty = INT; break; + case '"': *++e = IMM; *++e = ival; next(); while (tk == '"') next(); data = (char *)((int)data + sizeof(int) & -sizeof(int)); ty = PTR; - } - else if (tk == Sizeof) { + break; + case Sizeof: next(); if (tk == '(') next(); else { printf("%d: open paren expected in sizeof\n", line); exit(-1); } ty = INT; if (tk == Int) next(); else if (tk == Char) { next(); ty = CHAR; } while (tk == Mul) { next(); ty = ty + PTR; } if (tk == ')') next(); else { printf("%d: close paren expected in sizeof\n", line); exit(-1); } *++e = IMM; *++e = (ty == CHAR) ? sizeof(char) : sizeof(int); ty = INT; - } - else if (tk == Id) { + break; + case Id: d = id; next(); if (tk == '(') { next(); @@ -183,8 +204,8 @@ void expr(int lev) else { printf("%d: undefined variable\n", line); exit(-1); } *++e = ((ty = d[Type]) == CHAR) ? LC : LI; } - } - else if (tk == '(') { + break; + case '(': next(); if (tk == Int || tk == Char) { t = (tk == Int) ? INT : CHAR; next(); @@ -197,26 +218,27 @@ void expr(int lev) expr(Assign); if (tk == ')') next(); else { printf("%d: close paren expected\n", line); exit(-1); } } - } - else if (tk == Mul) { + break; + case Mul: next(); expr(Inc); if (ty > INT) ty = ty - PTR; else { printf("%d: bad dereference\n", line); exit(-1); } *++e = (ty == CHAR) ? LC : LI; - } - else if (tk == And) { + break; + case And: next(); expr(Inc); if (*e == LC || *e == LI) --e; else { printf("%d: bad address-of\n", line); exit(-1); } ty = ty + PTR; - } - else if (tk == '!') { next(); expr(Inc); *++e = PSH; *++e = IMM; *++e = 0; *++e = EQ; ty = INT; } - else if (tk == '~') { next(); expr(Inc); *++e = PSH; *++e = IMM; *++e = -1; *++e = XOR; ty = INT; } - else if (tk == Add) { next(); expr(Inc); ty = INT; } - else if (tk == Sub) { + break; + case '!': next(); expr(Inc); *++e = PSH; *++e = IMM; *++e = 0; *++e = EQ; ty = INT; break; + case '~': next(); expr(Inc); *++e = PSH; *++e = IMM; *++e = -1; *++e = XOR; ty = INT; break; + case Add: next(); expr(Inc); ty = INT; break; + case Sub: next(); *++e = IMM; if (tk == Num) { *++e = -ival; next(); } else { *++e = -1; *++e = PSH; expr(Inc); *++e = MUL; } ty = INT; - } - else if (tk == Inc || tk == Dec) { + break; + case Inc: + case Dec: t = tk; next(); expr(Inc); if (*e == LC) { *e = PSH; *++e = LC; } else if (*e == LI) { *e = PSH; *++e = LI; } @@ -225,17 +247,19 @@ void expr(int lev) *++e = IMM; *++e = (ty > PTR) ? sizeof(int) : sizeof(char); *++e = (t == Inc) ? ADD : SUB; *++e = (ty == CHAR) ? SC : SI; + break; + default: printf("%d: bad expression\n", line); exit(-1); } - else { printf("%d: bad expression\n", line); exit(-1); } while (tk >= lev) { // "precedence climbing" or "Top Down Operator Precedence" method t = ty; - if (tk == Assign) { + switch (tk) { + case Assign: next(); if (*e == LC || *e == LI) *e = PSH; else { printf("%d: bad lvalue in assignment\n", line); exit(-1); } expr(Assign); *++e = ((ty = t) == CHAR) ? SC : SI; - } - else if (tk == Cond) { + break; + case Cond: next(); *++e = BZ; d = ++e; expr(Assign); @@ -243,35 +267,36 @@ void expr(int lev) *d = (int)(e + 3); *++e = JMP; d = ++e; expr(Cond); *d = (int)(e + 1); - } - else if (tk == Lor) { next(); *++e = BNZ; d = ++e; expr(Lan); *d = (int)(e + 1); ty = INT; } - else if (tk == Lan) { next(); *++e = BZ; d = ++e; expr(Or); *d = (int)(e + 1); ty = INT; } - else if (tk == Or) { next(); *++e = PSH; expr(Xor); *++e = OR; ty = INT; } - else if (tk == Xor) { next(); *++e = PSH; expr(And); *++e = XOR; ty = INT; } - else if (tk == And) { next(); *++e = PSH; expr(Eq); *++e = AND; ty = INT; } - else if (tk == Eq) { next(); *++e = PSH; expr(Lt); *++e = EQ; ty = INT; } - else if (tk == Ne) { next(); *++e = PSH; expr(Lt); *++e = NE; ty = INT; } - else if (tk == Lt) { next(); *++e = PSH; expr(Shl); *++e = LT; ty = INT; } - else if (tk == Gt) { next(); *++e = PSH; expr(Shl); *++e = GT; ty = INT; } - else if (tk == Le) { next(); *++e = PSH; expr(Shl); *++e = LE; ty = INT; } - else if (tk == Ge) { next(); *++e = PSH; expr(Shl); *++e = GE; ty = INT; } - else if (tk == Shl) { next(); *++e = PSH; expr(Add); *++e = SHL; ty = INT; } - else if (tk == Shr) { next(); *++e = PSH; expr(Add); *++e = SHR; ty = INT; } - else if (tk == Add) { + break; + case Lor: next(); *++e = BNZ; d = ++e; expr(Lan); *d = (int)(e + 1); ty = INT; break; + case Lan: next(); *++e = BZ; d = ++e; expr(Or); *d = (int)(e + 1); ty = INT; break; + case Or: next(); *++e = PSH; expr(Xor); *++e = OR; ty = INT; break; + case Xor: next(); *++e = PSH; expr(And); *++e = XOR; ty = INT; break; + case And: next(); *++e = PSH; expr(Eq); *++e = AND; ty = INT; break; + case Eq: next(); *++e = PSH; expr(Lt); *++e = EQ; ty = INT; break; + case Ne: next(); *++e = PSH; expr(Lt); *++e = NE; ty = INT; break; + case Lt: next(); *++e = PSH; expr(Shl); *++e = LT; ty = INT; break; + case Gt: next(); *++e = PSH; expr(Shl); *++e = GT; ty = INT; break; + case Le: next(); *++e = PSH; expr(Shl); *++e = LE; ty = INT; break; + case Ge: next(); *++e = PSH; expr(Shl); *++e = GE; ty = INT; break; + case Shl: next(); *++e = PSH; expr(Add); *++e = SHL; ty = INT; break; + case Shr: next(); *++e = PSH; expr(Add); *++e = SHR; ty = INT; break; + case Add: next(); *++e = PSH; expr(Mul); if ((ty = t) > PTR) { *++e = PSH; *++e = IMM; *++e = sizeof(int); *++e = MUL; } *++e = ADD; - } - else if (tk == Sub) { + break; + case Sub: next(); *++e = PSH; expr(Mul); if (t > PTR && t == ty) { *++e = SUB; *++e = PSH; *++e = IMM; *++e = sizeof(int); *++e = DIV; ty = INT; } else if ((ty = t) > PTR) { *++e = PSH; *++e = IMM; *++e = sizeof(int); *++e = MUL; *++e = SUB; } else *++e = SUB; - } - else if (tk == Mul) { next(); *++e = PSH; expr(Inc); *++e = MUL; ty = INT; } - else if (tk == Div) { next(); *++e = PSH; expr(Inc); *++e = DIV; ty = INT; } - else if (tk == Mod) { next(); *++e = PSH; expr(Inc); *++e = MOD; ty = INT; } - else if (tk == Inc || tk == Dec) { + break; + case Mul: next(); *++e = PSH; expr(Inc); *++e = MUL; ty = INT; break; + case Div: next(); *++e = PSH; expr(Inc); *++e = DIV; ty = INT; break; + case Mod: next(); *++e = PSH; expr(Inc); *++e = MOD; ty = INT; break; + case Inc: + case Dec: if (*e == LC) { *e = PSH; *++e = LC; } else if (*e == LI) { *e = PSH; *++e = LI; } else { printf("%d: bad lvalue in post-increment\n", line); exit(-1); } @@ -281,16 +306,17 @@ void expr(int lev) *++e = PSH; *++e = IMM; *++e = (ty > PTR) ? sizeof(int) : sizeof(char); *++e = (tk == Inc) ? SUB : ADD; next(); - } - else if (tk == Brak) { + break; + case Brak: next(); *++e = PSH; expr(Assign); if (tk == ']') next(); else { printf("%d: close bracket expected\n", line); exit(-1); } if (t > PTR) { *++e = PSH; *++e = IMM; *++e = sizeof(int); *++e = MUL; } else if (t < PTR) { printf("%d: pointer type expected\n", line); exit(-1); } *++e = ADD; *++e = ((ty = t - PTR) == CHAR) ? LC : LI; + break; + default: printf("%d: compiler error tk=%d\n", line, tk); exit(-1); } - else { printf("%d: compiler error tk=%d\n", line, tk); exit(-1); } } } @@ -298,7 +324,8 @@ void stmt() { int *a, *b, *d, i; - if (tk == If) { + switch (tk) { + case If: next(); if (tk == '(') next(); else { printf("%d: open paren expected\n", line); exit(-1); } expr(Assign); @@ -311,8 +338,8 @@ void stmt() stmt(); } *b = (int)(e + 1); - } - else if (tk == Do) { + return; + case Do: next(); a = e + 1; stmt(); @@ -324,8 +351,8 @@ void stmt() *++e = BZ; b = ++e; *++e = JMP; *++e = (int)a; *b = (int)(e + 1); - } - else if (tk == While) { + return; + case While: next(); a = e + 1; if (tk == '(') next(); else { printf("%d: open paren expected\n", line); exit(-1); } @@ -335,8 +362,8 @@ void stmt() stmt(); *++e = JMP; *++e = (int)a; *b = (int)(e + 1); - } - else if (tk == Switch) { + return; + case Switch: next(); if (tk == '(') next(); else { printf("%d: open paren expected\n", line); exit(-1); } expr(Assign); @@ -347,47 +374,42 @@ void stmt() *cas = def ? (int)def : (int)(e + 1); cas = a; while (brak) { a = (int *)*brak; *brak = (int)(e + 1); brak = a; } brak = b; def = d; - } - else if (tk == Case) { + return; + case Case: *++e = JMP; ++e; *e = (int)(e + 7); *++e = PSH; i = *cas; *cas = (int)e; next(); expr(Or); if (e[-1] != IMM) { printf("%d: bad case immediate\n", line); exit(-1); } *e = *e - i; *++e = SUB; *++e = BNZ; cas = ++e; *e = i + e[-3]; - if (tk == ':') { - next(); - } - else { - printf("%d: colon expected\n", line); exit(-1); - } + if (tk == ':') next(); else { printf("%d: colon expected\n", line); exit(-1); } stmt(); - } - else if (tk == Break) { + return; + case Break: next(); if (tk == ';') next(); else { printf("%d: semicolon expected\n", line); exit(-1); } *++e = JMP; *++e = (int)brak; brak = e; - } - else if (tk == Default) { + return; + case Default: next(); if (tk == ':') next(); else { printf("%d: colon expected\n", line); exit(-1); } def = e + 1; stmt(); - } - else if (tk == Return) { + return; + case Return: next(); if (tk != ';') expr(Assign); *++e = LEV; if (tk == ';') next(); else { printf("%d: semicolon expected\n", line); exit(-1); } - } - else if (tk == '{') { + return; + case '{': next(); while (tk != '}') stmt(); next(); - } - else if (tk == ';') { + return; + case ';': next(); - } - else { + return; + default: expr(Assign); if (tk == ';') next(); else { printf("%d: semicolon expected\n", line); exit(-1); } } @@ -470,78 +492,65 @@ int main(int argc, char **argv) while (tk != ';' && tk != '}') { ty = bt; while (tk == Mul) { next(); ty = ty + PTR; } - if (tk == Brak) { + if (tk != Id) { printf("%d: bad global declaration\n", line); return -1; } + if (id[Class]) { printf("%d: duplicate global definition\n", line); return -1; } + next(); + id[Type] = ty; + if (tk == '(') { // function + id[Class] = Fun; + id[Val] = (int)(e + 1); + next(); i = 0; + while (tk != ')') { + ty = INT; + if (tk == Int) next(); + else if (tk == Char) { next(); ty = CHAR; } + while (tk == Mul) { next(); ty = ty + PTR; } + if (tk != Id) { printf("%d: bad parameter declaration\n", line); return -1; } + if (id[Class] == Loc) { printf("%d: duplicate parameter definition\n", line); return -1; } + id[HClass] = id[Class]; id[Class] = Loc; + id[HType] = id[Type]; id[Type] = ty; + id[HVal] = id[Val]; id[Val] = i++; + next(); + if (tk == ',') next(); + } next(); - if (tk == Num) next(); - else { printf("%d: integer as dimensions of array expected\n", line); return -1; } - if (tk == ']') next(); - else { printf("%d: ] expected\n", line); return -1; } - id[Type] = ty + PTR; - id[Class] = Glo; - id[Val] = (int)data; - data = data + ival * sizeof(char); - } - else { - if (tk != Id) { printf("%d: bad global declaration\n", line); return -1; } - if (id[Class]) { printf("%d: duplicate global definition\n", line); return -1; } + if (tk != '{') { printf("%d: bad function definition\n", line); return -1; } + loc = ++i; next(); - id[Type] = ty; - if (tk == '(') { // function - id[Class] = Fun; - id[Val] = (int)(e + 1); - next(); i = 0; - while (tk != ')') { - ty = INT; - if (tk == Int) next(); - else if (tk == Char) { next(); ty = CHAR; } + while (tk == Int || tk == Char) { + bt = (tk == Int) ? INT : CHAR; + next(); + while (tk != ';') { + ty = bt; while (tk == Mul) { next(); ty = ty + PTR; } - if (tk != Id) { printf("%d: bad parameter declaration\n", line); return -1; } - if (id[Class] == Loc) { printf("%d: duplicate parameter definition\n", line); return -1; } + if (tk != Id) { printf("%d: bad local declaration\n", line); return -1; } + if (id[Class] == Loc) { printf("%d: duplicate local definition\n", line); return -1; } id[HClass] = id[Class]; id[Class] = Loc; id[HType] = id[Type]; id[Type] = ty; - id[HVal] = id[Val]; id[Val] = i++; + id[HVal] = id[Val]; id[Val] = ++i; next(); if (tk == ',') next(); } next(); - if (tk != '{') { printf("%d: bad function definition\n", line); return -1; } - loc = ++i; - next(); - while (tk == Int || tk == Char) { - bt = (tk == Int) ? INT : CHAR; - next(); - while (tk != ';') { - ty = bt; - while (tk == Mul) { next(); ty = ty + PTR; } - if (tk != Id) { printf("%d: bad local declaration\n", line); return -1; } - if (id[Class] == Loc) { printf("%d: duplicate local definition\n", line); return -1; } - id[HClass] = id[Class]; id[Class] = Loc; - id[HType] = id[Type]; id[Type] = ty; - id[HVal] = id[Val]; id[Val] = ++i; - next(); - if (tk == ',') next(); - } - next(); - } - *++e = ENT; *++e = i - loc; - while (tk != '}') stmt(); - *++e = LEV; - id = sym; // unwind symbol table locals - while (id[Tk]) { - if (id[Class] == Loc) { - id[Class] = id[HClass]; - id[Type] = id[HType]; - id[Val] = id[HVal]; - } - id = id + Idsz; - } } - else { - id[Class] = Glo; - id[Val] = (int)data; - data = data + sizeof(int); + *++e = ENT; *++e = i - loc; + while (tk != '}') stmt(); + *++e = LEV; + id = sym; // unwind symbol table locals + while (id[Tk]) { + if (id[Class] == Loc) { + id[Class] = id[HClass]; + id[Type] = id[HType]; + id[Val] = id[HVal]; + } + id = id + Idsz; } } + else { + id[Class] = Glo; + id[Val] = (int)data; + data = data + sizeof(int); + } if (tk == ',') next(); } next(); @@ -569,57 +578,59 @@ int main(int argc, char **argv) "OPEN,READ,CLOS,PRTF,MALC,FREE,MSET,MCMP,GETC,PUTS,PUTN,PUTC,PUTI,ISPC,IDGT,IANU.IALP,SCMP,EXIT,"[i * 5]); if (i <= ADJ) printf(" %d\n", *pc); else printf("\n"); } - if (i == LEA) a = (int)(bp + *pc++); // load local address - else if (i == IMM) a = *pc++; // load global address or immediate - else if (i == JMP) pc = (int *)*pc; // jump - else if (i == JSR) { *--sp = (int)(pc + 1); pc = (int *)*pc; } // jump to subroutine - else if (i == BZ) pc = a ? pc + 1 : (int *)*pc; // branch if zero - else if (i == BNZ) pc = a ? (int *)*pc : pc + 1; // branch if not zero - else if (i == ENT) { *--sp = (int)bp; bp = sp; sp = sp - *pc++; } // enter subroutine - else if (i == ADJ) sp = sp + *pc++; // stack adjust - else if (i == LEV) { sp = bp; bp = (int *)*sp++; pc = (int *)*sp++; } // leave subroutine - else if (i == LI) a = *(int *)a; // load int - else if (i == LC) a = *(char *)a; // load char - else if (i == SI) *(int *)*sp++ = a; // store int - else if (i == SC) a = *(char *)*sp++ = a; // store char - else if (i == PSH) *--sp = a; // push + switch (i) { + case LEA: a = (int)(bp + *pc++); break; // load local address + case IMM: a = *pc++; break; // load global address or immediate + case JMP: pc = (int *)*pc; break; // jump + case JSR: *--sp = (int)(pc + 1); pc = (int *)*pc; break; // jump to subroutine + case BZ: pc = a ? pc + 1 : (int *)*pc; break; // branch if zero + case BNZ: pc = a ? (int *)*pc : pc + 1; break; // branch if not zero + case ENT: *--sp = (int)bp; bp = sp; sp = sp - *pc++; break; // enter subroutine + case ADJ: sp = sp + *pc++; break; // stack adjust + case LEV: sp = bp; bp = (int *)*sp++; pc = (int *)*sp++; break; // leave subroutine + case LI: a = *(int *)a; break; // load int + case LC: a = *(char *)a; break; // load char + case SI: *(int *)*sp++ = a; break; // store int + case SC: a = *(char *)*sp++ = a; break; // store char + case PSH: *--sp = a; break; // push - else if (i == OR) a = *sp++ | a; - else if (i == XOR) a = *sp++ ^ a; - else if (i == AND) a = *sp++ & a; - else if (i == EQ) a = *sp++ == a; - else if (i == NE) a = *sp++ != a; - else if (i == LT) a = *sp++ < a; - else if (i == GT) a = *sp++ > a; - else if (i == LE) a = *sp++ <= a; - else if (i == GE) a = *sp++ >= a; - else if (i == SHL) a = *sp++ << a; - else if (i == SHR) a = *sp++ >> a; - else if (i == ADD) a = *sp++ + a; - else if (i == SUB) a = *sp++ - a; - else if (i == MUL) a = *sp++ * a; - else if (i == DIV) a = *sp++ / a; - else if (i == MOD) a = *sp++ % a; + case OR: a = *sp++ | a; break; + case XOR: a = *sp++ ^ a; break; + case AND: a = *sp++ & a; break; + case EQ: a = *sp++ == a; break; + case NE: a = *sp++ != a; break; + case LT: a = *sp++ < a; break; + case GT: a = *sp++ > a; break; + case LE: a = *sp++ <= a; break; + case GE: a = *sp++ >= a; break; + case SHL: a = *sp++ << a; break; + case SHR: a = *sp++ >> a; break; + case ADD: a = *sp++ + a; break; + case SUB: a = *sp++ - a; break; + case MUL: a = *sp++ * a; break; + case DIV: a = *sp++ / a; break; + case MOD: a = *sp++ % a; break; - else if (i == OPEN) a = open((char *)sp[1], *sp); - else if (i == READ) a = read(sp[2], (char *)sp[1], *sp); - else if (i == CLOS) a = close(*sp); - else if (i == PRTF) { t = sp + pc[1]; a = printf((char *)t[-1], t[-2], t[-3], t[-4], t[-5], t[-6]); } - else if (i == MALC) a = (int)malloc(*sp); - else if (i == FREE) free((void *)*sp); - else if (i == MSET) a = (int)memset((char *)sp[2], sp[1], *sp); - else if (i == MCMP) a = memcmp((char *)sp[2], (char *)sp[1], *sp); - else if (i == GETC) a = getchar(); - else if (i == PUTS) { t = sp + pc[1]; a = printf("%s", (char *)t[-1]); } - else if (i == PUTN) a = printf("\n"); - else if (i == PUTC) a = putchar(*sp); - else if (i == PUTI) { t = sp + pc[1]; a = printf("%d", (int)t[-1]); } - else if (i == ISPC) { t = sp + pc[1]; a = isspace( (int)t[-1]); } - else if (i == IDGT) { t = sp + pc[1]; a = isdigit( (int)t[-1]); } - else if (i == IANU) { t = sp + pc[1]; a = isalnum( (int)t[-1]); } - else if (i == IALP) { t = sp + pc[1]; a = isalpha( (int)t[-1]); } - else if (i == SCMP) { t = sp + pc[1]; a = strcmp((char *)t[-1], (char *)t[-2]); } - else if (i == EXIT) { printf("exit(%d) cycle = %d\n", *sp, cycle); return *sp; } - else { printf("unknown instruction = %d! cycle = %d\n", i, cycle); return -1; } + case OPEN: a = open((char *)sp[1], *sp); break; + case READ: a = read(sp[2], (char *)sp[1], *sp); break; + case CLOS: a = close(*sp); break; + case PRTF: t = sp + pc[1]; a = printf((char *)t[-1], t[-2], t[-3], t[-4], t[-5], t[-6]); break; + case MALC: a = (int)malloc(*sp); break; + case FREE: free((void *)*sp); break; + case MSET: a = (int)memset((char *)sp[2], sp[1], *sp); break; + case MCMP: a = memcmp((char *)sp[2], (char *)sp[1], *sp); break; + case GETC: a = getchar(); break; + case PUTS: t = sp + pc[1]; a = printf("%s", (char *)t[-1]); break; + case PUTN: a = printf("\n"); break; + case PUTC: a = putchar(*sp); break; + case PUTI: t = sp + pc[1]; a = printf("%d", (int)t[-1]); break; + case ISPC: t = sp + pc[1]; a = isspace( (int)t[-1]); break; + case IDGT: t = sp + pc[1]; a = isdigit( (int)t[-1]); break; + case IANU: t = sp + pc[1]; a = isalnum( (int)t[-1]); break; + case IALP: t = sp + pc[1]; a = isalpha( (int)t[-1]); break; + case SCMP: t = sp + pc[1]; a = strcmp((char *)t[-1], (char *)t[-2]); break; + case EXIT: printf("exit(%d) cycle = %d\n", *sp, cycle); return *sp; + default: printf("unknown instruction = %d! cycle = %d\n", i, cycle); return -1; + } } } diff --git a/miniany/cc.c b/miniany/cc.c index ba7ead2..cf4f880 100644 --- a/miniany/cc.c +++ b/miniany/cc.c @@ -183,12 +183,14 @@ int getToken( ) case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': - case 'u': case 'v': case 'w': case 'y': case 'z': + case 'u': case 'v': case 'w': case 'x': case 'y': + case 'z': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': - case 'U': case 'V': case 'W': case 'Y': case 'Z': + case 'U': case 'V': case 'W': case 'X': case 'Y': + case 'Z': case '_': scanIdent( c ); if( ( t = keyword( ident ) ) ) { -- cgit v1.2.3-54-g00ecf