Compare commits

..

8 commits

Author SHA1 Message Date
Robert Swierczek
3f098f3ea8 Merge pull request #32 from nubok/patch-2
Avoid undefined behavior - bp is initialized when setting up the stack
2017-08-21 17:39:47 -04:00
Wolfgang Keller
6884cb4de9 Avoid undefined behavior - bp is initialized when setting up the stack 2017-08-21 23:30:09 +02:00
Robert Swierczek
567db57ef2 Merge pull request #27 from chainhelen/master
add a FREE opcode
2017-02-24 06:21:56 -05:00
chainhelen
461f117cda add a FREE opcode 2017-02-24 17:28:35 +08:00
rswier
80db11debf Revert "Added structures"
This reverts commit 32b33ff4f6.
2016-02-26 01:17:04 -05:00
rswier
32b33ff4f6 Added structures
This change adds structures (struct) along with the dot (.) and arrow (->) operators.  It is very silly to add this level of complexity while keeping it just four functions.  But it had to be done :-)
2016-02-25 20:59:44 -05:00
rswier
e78a343e1d Merge pull request #22 from neosilky/fix-compile
Fix a compile error from missing include
2016-01-28 19:52:59 -05:00
Daniel Lockyer
021abbc0b4 Fix a compile error from missing include
open() needs the <fcntl.h> include so this has been added.
2016-01-29 00:28:40 +00:00
2 changed files with 146 additions and 196 deletions

View file

@ -1,7 +1,7 @@
c4 - C in four functions c4 - C in four functions
======================== ========================
An exercise in minimalism. **This branch adds switch statement support.** An exercise in minimalism.
Try the following: Try the following:

340
c4.c
View file

@ -1,15 +1,15 @@
// c4.c - C in four functions // c4.c - C in four functions
// char, int, and pointer types // char, int, and pointer types
// if, while, return, switch, and expression statements // if, while, return, and expression statements
// just enough features to allow self-compilation and a bit more // just enough features to allow self-compilation and a bit more
// Written by Robert Swierczek // Written by Robert Swierczek
#include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <memory.h> #include <memory.h>
#include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
char *p, *lp, // current position in source code char *p, *lp, // current position in source code
@ -18,9 +18,6 @@ char *p, *lp, // current position in source code
int *e, *le, // current position in emitted code int *e, *le, // current position in emitted code
*id, // currently parsed identifier *id, // currently parsed identifier
*sym, // symbol table (simple list of identifiers) *sym, // symbol table (simple list of identifiers)
*cas, // case statement patch-up pointer
*brk, // break statement patch-up pointer
*def, // default statement patch-up pointer
tk, // current token tk, // current token
ival, // current token value ival, // current token value
ty, // current expression type ty, // current expression type
@ -32,14 +29,14 @@ int *e, *le, // current position in emitted code
// tokens and classes (operators last and in precedence order) // tokens and classes (operators last and in precedence order)
enum { enum {
Num = 128, Fun, Sys, Glo, Loc, Id, Num = 128, Fun, Sys, Glo, Loc, Id,
Break, Case, Char, Default, Else, Enum, If, Int, Return, Sizeof, Switch, While, Char, Else, Enum, If, Int, Return, Sizeof, While,
Assign, Cond, Lor, Lan, Or, Xor, And, Eq, Ne, Lt, Gt, Le, Ge, Shl, Shr, Add, Sub, Mul, Div, Mod, Inc, Dec, Brak Assign, Cond, Lor, Lan, Or, Xor, And, Eq, Ne, Lt, Gt, Le, Ge, Shl, Shr, Add, Sub, Mul, Div, Mod, Inc, Dec, Brak
}; };
// opcodes // opcodes
enum { LEA ,IMM ,JMP ,JSR ,BZ ,BNZ ,ENT ,ADJ ,LEV ,LI ,LC ,SI ,SC ,PSH , enum { LEA ,IMM ,JMP ,JSR ,BZ ,BNZ ,ENT ,ADJ ,LEV ,LI ,LC ,SI ,SC ,PSH ,
OR ,XOR ,AND ,EQ ,NE ,LT ,GT ,LE ,GE ,SHL ,SHR ,ADD ,SUB ,MUL ,DIV ,MOD , OR ,XOR ,AND ,EQ ,NE ,LT ,GT ,LE ,GE ,SHL ,SHR ,ADD ,SUB ,MUL ,DIV ,MOD ,
OPEN,READ,CLOS,PRTF,MALC,MSET,MCMP,EXIT }; OPEN,READ,CLOS,PRTF,MALC,FREE,MSET,MCMP,EXIT };
// types // types
enum { CHAR, INT, PTR }; enum { CHAR, INT, PTR };
@ -53,7 +50,23 @@ void next()
while (tk = *p) { while (tk = *p) {
++p; ++p;
if ((tk >= 'a' && tk <= 'z') || (tk >= 'A' && tk <= 'Z') || tk == '_') { if (tk == '\n') {
if (src) {
printf("%d: %.*s", line, p - lp, lp);
lp = p;
while (le < e) {
printf("%8.4s", &"LEA ,IMM ,JMP ,JSR ,BZ ,BNZ ,ENT ,ADJ ,LEV ,LI ,LC ,SI ,SC ,PSH ,"
"OR ,XOR ,AND ,EQ ,NE ,LT ,GT ,LE ,GE ,SHL ,SHR ,ADD ,SUB ,MUL ,DIV ,MOD ,"
"OPEN,READ,CLOS,PRTF,MALC,FREE,MSET,MCMP,EXIT,"[*++le * 5]);
if (*le <= ADJ) printf(" %d\n", *++le); else printf("\n");
}
}
++line;
}
else if (tk == '#') {
while (*p != 0 && *p != '\n') ++p;
}
else if ((tk >= 'a' && tk <= 'z') || (tk >= 'A' && tk <= 'Z') || tk == '_') {
pp = p - 1; pp = p - 1;
while ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || *p == '_') while ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || *p == '_')
tk = tk * 147 + *p++; tk = tk * 147 + *p++;
@ -78,25 +91,7 @@ void next()
tk = Num; tk = Num;
return; return;
} }
switch (tk) { else if (tk == '/') {
case '\n':
if (src) {
printf("%d: %.*s", line, p - lp, lp);
lp = p;
while (le < e) {
printf("%8.4s", &"LEA ,IMM ,JMP ,JSR ,BZ ,BNZ ,ENT ,ADJ ,LEV ,LI ,LC ,SI ,SC ,PSH ,"
"OR ,XOR ,AND ,EQ ,NE ,LT ,GT ,LE ,GE ,SHL ,SHR ,ADD ,SUB ,MUL ,DIV ,MOD ,"
"OPEN,READ,CLOS,PRTF,MALC,MSET,MCMP,EXIT,"[*++le * 5]);
if (*le <= ADJ) printf(" %d\n", *++le); else printf("\n");
}
}
++line;
case ' ': case '\t': case '\v': case '\f': case '\r':
break;
case '#':
while (*p != 0 && *p != '\n') ++p;
break;
case '/':
if (*p == '/') { if (*p == '/') {
++p; ++p;
while (*p != 0 && *p != '\n') ++p; while (*p != 0 && *p != '\n') ++p;
@ -105,40 +100,33 @@ void next()
tk = Div; tk = Div;
return; return;
} }
break; }
case '\'': else if (tk == '\'' || tk == '"') {
case '"':
pp = data; pp = data;
while (*p != 0 && *p != tk) { while (*p != 0 && *p != tk) {
if ((ival = *p++) == '\\') { if ((ival = *p++) == '\\') {
switch (ival = *p++) { if ((ival = *p++) == 'n') ival = '\n';
case 'n': ival = '\n'; break;
case 't': ival = '\t'; break;
case 'v': ival = '\v'; break;
case 'f': ival = '\f'; break;
case 'r': ival = '\r';
}
} }
if (tk == '"') *data++ = ival; if (tk == '"') *data++ = ival;
} }
++p; ++p;
if (tk == '"') ival = (int)pp; else tk = Num; if (tk == '"') ival = (int)pp; else tk = Num;
return; 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;
default: 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;
} }
} }
@ -146,23 +134,22 @@ void expr(int lev)
{ {
int t, *d; int t, *d;
switch (tk) { if (!tk) { printf("%d: unexpected eof in expression\n", line); exit(-1); }
case 0: printf("%d: unexpected eof in expression\n", line); exit(-1); else if (tk == Num) { *++e = IMM; *++e = ival; next(); ty = INT; }
case Num: *++e = IMM; *++e = ival; next(); ty = INT; break; else if (tk == '"') {
case '"':
*++e = IMM; *++e = ival; next(); *++e = IMM; *++e = ival; next();
while (tk == '"') next(); while (tk == '"') next();
data = (char *)((int)data + sizeof(int) & -sizeof(int)); ty = PTR; data = (char *)((int)data + sizeof(int) & -sizeof(int)); ty = PTR;
break; }
case Sizeof: else if (tk == Sizeof) {
next(); if (tk == '(') next(); else { printf("%d: open paren expected in sizeof\n", line); exit(-1); } 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; } ty = INT; if (tk == Int) next(); else if (tk == Char) { next(); ty = CHAR; }
while (tk == Mul) { next(); ty = ty + PTR; } while (tk == Mul) { next(); ty = ty + PTR; }
if (tk == ')') next(); else { printf("%d: close paren expected in sizeof\n", line); exit(-1); } if (tk == ')') next(); else { printf("%d: close paren expected in sizeof\n", line); exit(-1); }
*++e = IMM; *++e = (ty == CHAR) ? sizeof(char) : sizeof(int); *++e = IMM; *++e = (ty == CHAR) ? sizeof(char) : sizeof(int);
ty = INT; ty = INT;
break; }
case Id: else if (tk == Id) {
d = id; next(); d = id; next();
if (tk == '(') { if (tk == '(') {
next(); next();
@ -182,8 +169,8 @@ void expr(int lev)
else { printf("%d: undefined variable\n", line); exit(-1); } else { printf("%d: undefined variable\n", line); exit(-1); }
*++e = ((ty = d[Type]) == CHAR) ? LC : LI; *++e = ((ty = d[Type]) == CHAR) ? LC : LI;
} }
break; }
case '(': else if (tk == '(') {
next(); next();
if (tk == Int || tk == Char) { if (tk == Int || tk == Char) {
t = (tk == Int) ? INT : CHAR; next(); t = (tk == Int) ? INT : CHAR; next();
@ -196,26 +183,26 @@ void expr(int lev)
expr(Assign); expr(Assign);
if (tk == ')') next(); else { printf("%d: close paren expected\n", line); exit(-1); } if (tk == ')') next(); else { printf("%d: close paren expected\n", line); exit(-1); }
} }
break; }
case Mul: else if (tk == Mul) {
next(); expr(Inc); next(); expr(Inc);
if (ty > INT) ty = ty - PTR; else { printf("%d: bad dereference\n", line); exit(-1); } if (ty > INT) ty = ty - PTR; else { printf("%d: bad dereference\n", line); exit(-1); }
*++e = (ty == CHAR) ? LC : LI; *++e = (ty == CHAR) ? LC : LI;
break; }
case And: else if (tk == And) {
next(); expr(Inc); next(); expr(Inc);
if (*e == LC || *e == LI) --e; else { printf("%d: bad address-of\n", line); exit(-1); } if (*e == LC || *e == LI) --e; else { printf("%d: bad address-of\n", line); exit(-1); }
ty = ty + PTR; ty = ty + PTR;
break; }
case '!': next(); expr(Inc); *++e = PSH; *++e = IMM; *++e = 0; *++e = EQ; ty = INT; break; else if (tk == '!') { next(); expr(Inc); *++e = PSH; *++e = IMM; *++e = 0; *++e = EQ; ty = INT; }
case '~': next(); expr(Inc); *++e = PSH; *++e = IMM; *++e = -1; *++e = XOR; ty = INT; break; else if (tk == '~') { next(); expr(Inc); *++e = PSH; *++e = IMM; *++e = -1; *++e = XOR; ty = INT; }
case Add: next(); expr(Inc); ty = INT; break; else if (tk == Add) { next(); expr(Inc); ty = INT; }
case Sub: else if (tk == Sub) {
next(); *++e = IMM; next(); *++e = IMM;
if (tk == Num) { *++e = -ival; next(); } else { *++e = -1; *++e = PSH; expr(Inc); *++e = MUL; } if (tk == Num) { *++e = -ival; next(); } else { *++e = -1; *++e = PSH; expr(Inc); *++e = MUL; }
ty = INT; ty = INT;
break; }
case Inc: case Dec: else if (tk == Inc || tk == Dec) {
t = tk; next(); expr(Inc); t = tk; next(); expr(Inc);
if (*e == LC) { *e = PSH; *++e = LC; } if (*e == LC) { *e = PSH; *++e = LC; }
else if (*e == LI) { *e = PSH; *++e = LI; } else if (*e == LI) { *e = PSH; *++e = LI; }
@ -224,19 +211,17 @@ void expr(int lev)
*++e = IMM; *++e = (ty > PTR) ? sizeof(int) : sizeof(char); *++e = IMM; *++e = (ty > PTR) ? sizeof(int) : sizeof(char);
*++e = (t == Inc) ? ADD : SUB; *++e = (t == Inc) ? ADD : SUB;
*++e = (ty == CHAR) ? SC : SI; *++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 while (tk >= lev) { // "precedence climbing" or "Top Down Operator Precedence" method
t = ty; t = ty;
switch (tk) { if (tk == Assign) {
case Assign:
next(); next();
if (*e == LC || *e == LI) *e = PSH; else { printf("%d: bad lvalue in assignment\n", line); exit(-1); } 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; expr(Assign); *++e = ((ty = t) == CHAR) ? SC : SI;
break; }
case Cond: else if (tk == Cond) {
next(); next();
*++e = BZ; d = ++e; *++e = BZ; d = ++e;
expr(Assign); expr(Assign);
@ -244,35 +229,35 @@ void expr(int lev)
*d = (int)(e + 3); *++e = JMP; d = ++e; *d = (int)(e + 3); *++e = JMP; d = ++e;
expr(Cond); expr(Cond);
*d = (int)(e + 1); *d = (int)(e + 1);
break; }
case Lor: next(); *++e = BNZ; d = ++e; expr(Lan); *d = (int)(e + 1); ty = INT; break; else if (tk == Lor) { next(); *++e = BNZ; d = ++e; expr(Lan); *d = (int)(e + 1); ty = INT; }
case Lan: next(); *++e = BZ; d = ++e; expr(Or); *d = (int)(e + 1); ty = INT; break; else if (tk == Lan) { next(); *++e = BZ; d = ++e; expr(Or); *d = (int)(e + 1); ty = INT; }
case Or: next(); *++e = PSH; expr(Xor); *++e = OR; ty = INT; break; else if (tk == Or) { next(); *++e = PSH; expr(Xor); *++e = OR; ty = INT; }
case Xor: next(); *++e = PSH; expr(And); *++e = XOR; ty = INT; break; else if (tk == Xor) { next(); *++e = PSH; expr(And); *++e = XOR; ty = INT; }
case And: next(); *++e = PSH; expr(Eq); *++e = AND; ty = INT; break; else if (tk == And) { next(); *++e = PSH; expr(Eq); *++e = AND; ty = INT; }
case Eq: next(); *++e = PSH; expr(Lt); *++e = EQ; ty = INT; break; else if (tk == Eq) { next(); *++e = PSH; expr(Lt); *++e = EQ; ty = INT; }
case Ne: next(); *++e = PSH; expr(Lt); *++e = NE; ty = INT; break; else if (tk == Ne) { next(); *++e = PSH; expr(Lt); *++e = NE; ty = INT; }
case Lt: next(); *++e = PSH; expr(Shl); *++e = LT; ty = INT; break; else if (tk == Lt) { next(); *++e = PSH; expr(Shl); *++e = LT; ty = INT; }
case Gt: next(); *++e = PSH; expr(Shl); *++e = GT; ty = INT; break; else if (tk == Gt) { next(); *++e = PSH; expr(Shl); *++e = GT; ty = INT; }
case Le: next(); *++e = PSH; expr(Shl); *++e = LE; ty = INT; break; else if (tk == Le) { next(); *++e = PSH; expr(Shl); *++e = LE; ty = INT; }
case Ge: next(); *++e = PSH; expr(Shl); *++e = GE; ty = INT; break; else if (tk == Ge) { next(); *++e = PSH; expr(Shl); *++e = GE; ty = INT; }
case Shl: next(); *++e = PSH; expr(Add); *++e = SHL; ty = INT; break; else if (tk == Shl) { next(); *++e = PSH; expr(Add); *++e = SHL; ty = INT; }
case Shr: next(); *++e = PSH; expr(Add); *++e = SHR; ty = INT; break; else if (tk == Shr) { next(); *++e = PSH; expr(Add); *++e = SHR; ty = INT; }
case Add: else if (tk == Add) {
next(); *++e = PSH; expr(Mul); next(); *++e = PSH; expr(Mul);
if ((ty = t) > PTR) { *++e = PSH; *++e = IMM; *++e = sizeof(int); *++e = MUL; } if ((ty = t) > PTR) { *++e = PSH; *++e = IMM; *++e = sizeof(int); *++e = MUL; }
*++e = ADD; *++e = ADD;
break; }
case Sub: else if (tk == Sub) {
next(); *++e = PSH; expr(Mul); next(); *++e = PSH; expr(Mul);
if (t > PTR && t == ty) { *++e = SUB; *++e = PSH; *++e = IMM; *++e = sizeof(int); *++e = DIV; ty = INT; } 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 if ((ty = t) > PTR) { *++e = PSH; *++e = IMM; *++e = sizeof(int); *++e = MUL; *++e = SUB; }
else *++e = SUB; else *++e = SUB;
break; }
case Mul: next(); *++e = PSH; expr(Inc); *++e = MUL; ty = INT; break; else if (tk == Mul) { next(); *++e = PSH; expr(Inc); *++e = MUL; ty = INT; }
case Div: next(); *++e = PSH; expr(Inc); *++e = DIV; ty = INT; break; else if (tk == Div) { next(); *++e = PSH; expr(Inc); *++e = DIV; ty = INT; }
case Mod: next(); *++e = PSH; expr(Inc); *++e = MOD; ty = INT; break; else if (tk == Mod) { next(); *++e = PSH; expr(Inc); *++e = MOD; ty = INT; }
case Inc: case Dec: else if (tk == Inc || tk == Dec) {
if (*e == LC) { *e = PSH; *++e = LC; } if (*e == LC) { *e = PSH; *++e = LC; }
else if (*e == LI) { *e = PSH; *++e = LI; } else if (*e == LI) { *e = PSH; *++e = LI; }
else { printf("%d: bad lvalue in post-increment\n", line); exit(-1); } else { printf("%d: bad lvalue in post-increment\n", line); exit(-1); }
@ -282,26 +267,24 @@ void expr(int lev)
*++e = PSH; *++e = IMM; *++e = (ty > PTR) ? sizeof(int) : sizeof(char); *++e = PSH; *++e = IMM; *++e = (ty > PTR) ? sizeof(int) : sizeof(char);
*++e = (tk == Inc) ? SUB : ADD; *++e = (tk == Inc) ? SUB : ADD;
next(); next();
break; }
case Brak: else if (tk == Brak) {
next(); *++e = PSH; expr(Assign); next(); *++e = PSH; expr(Assign);
if (tk == ']') next(); else { printf("%d: close bracket expected\n", line); exit(-1); } 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; } 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); } else if (t < PTR) { printf("%d: pointer type expected\n", line); exit(-1); }
*++e = ADD; *++e = ADD;
*++e = ((ty = t - PTR) == CHAR) ? LC : LI; *++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); }
} }
} }
void stmt() void stmt()
{ {
int *a, *b, *d, i; int *a, *b;
switch (tk) { if (tk == If) {
case If:
next(); next();
if (tk == '(') next(); else { printf("%d: open paren expected\n", line); exit(-1); } if (tk == '(') next(); else { printf("%d: open paren expected\n", line); exit(-1); }
expr(Assign); expr(Assign);
@ -314,8 +297,8 @@ void stmt()
stmt(); stmt();
} }
*b = (int)(e + 1); *b = (int)(e + 1);
return; }
case While: else if (tk == While) {
next(); next();
a = e + 1; a = e + 1;
if (tk == '(') next(); else { printf("%d: open paren expected\n", line); exit(-1); } if (tk == '(') next(); else { printf("%d: open paren expected\n", line); exit(-1); }
@ -325,54 +308,22 @@ void stmt()
stmt(); stmt();
*++e = JMP; *++e = (int)a; *++e = JMP; *++e = (int)a;
*b = (int)(e + 1); *b = (int)(e + 1);
return; }
case Switch: else if (tk == Return) {
next();
if (tk == '(') next(); else { printf("%d: open paren expected\n", line); exit(-1); }
expr(Assign);
if (tk == ')') next(); else { printf("%d: close paren expected\n", line); exit(-1); }
a = cas; *++e = JMP; cas = ++e;
b = brk; d = def; brk = def = 0;
stmt();
*cas = def ? (int)def : (int)(e + 1); cas = a;
while (brk) { a = (int *)*brk; *brk = (int)(e + 1); brk = a; }
brk = b; def = d;
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); }
stmt();
return;
case Break:
next();
if (tk == ';') next(); else { printf("%d: semicolon expected\n", line); exit(-1); }
*++e = JMP; *++e = (int)brk; brk = e;
return;
case Default:
next();
if (tk == ':') next(); else { printf("%d: colon expected\n", line); exit(-1); }
def = e + 1;
stmt();
return;
case Return:
next(); next();
if (tk != ';') expr(Assign); if (tk != ';') expr(Assign);
*++e = LEV; *++e = LEV;
if (tk == ';') next(); else { printf("%d: semicolon expected\n", line); exit(-1); } if (tk == ';') next(); else { printf("%d: semicolon expected\n", line); exit(-1); }
return; }
case '{': else if (tk == '{') {
next(); next();
while (tk != '}') stmt(); while (tk != '}') stmt();
next(); next();
return; }
case ';': else if (tk == ';') {
next(); next();
return; }
default: else {
expr(Assign); expr(Assign);
if (tk == ';') next(); else { printf("%d: semicolon expected\n", line); exit(-1); } if (tk == ';') next(); else { printf("%d: semicolon expected\n", line); exit(-1); }
} }
@ -401,9 +352,9 @@ int main(int argc, char **argv)
memset(e, 0, poolsz); memset(e, 0, poolsz);
memset(data, 0, poolsz); memset(data, 0, poolsz);
p = "break case char default else enum if int return sizeof switch while " p = "char else enum if int return sizeof while "
"open read close printf malloc memset memcmp exit void main"; "open read close printf malloc free memset memcmp exit void main";
i = Break; while (i <= While) { next(); id[Tk] = i++; } // add keywords to symbol table i = Char; while (i <= While) { next(); id[Tk] = i++; } // add keywords to symbol table
i = OPEN; while (i <= EXIT) { next(); id[Class] = Sys; id[Type] = INT; id[Val] = i++; } // add library to symbol table i = OPEN; while (i <= EXIT) { next(); id[Class] = Sys; id[Type] = INT; id[Val] = i++; } // add library to symbol table
next(); id[Tk] = Char; // handle void type next(); id[Tk] = Char; // handle void type
next(); idmain = id; // keep track of main next(); idmain = id; // keep track of main
@ -512,7 +463,7 @@ int main(int argc, char **argv)
if (src) return 0; if (src) return 0;
// setup stack // setup stack
sp = (int *)((int)sp + poolsz); bp = sp = (int *)((int)sp + poolsz);
*--sp = EXIT; // call exit if main returns *--sp = EXIT; // call exit if main returns
*--sp = PSH; t = sp; *--sp = PSH; t = sp;
*--sp = argc; *--sp = argc;
@ -527,51 +478,50 @@ int main(int argc, char **argv)
printf("%d> %.4s", cycle, printf("%d> %.4s", cycle,
&"LEA ,IMM ,JMP ,JSR ,BZ ,BNZ ,ENT ,ADJ ,LEV ,LI ,LC ,SI ,SC ,PSH ," &"LEA ,IMM ,JMP ,JSR ,BZ ,BNZ ,ENT ,ADJ ,LEV ,LI ,LC ,SI ,SC ,PSH ,"
"OR ,XOR ,AND ,EQ ,NE ,LT ,GT ,LE ,GE ,SHL ,SHR ,ADD ,SUB ,MUL ,DIV ,MOD ," "OR ,XOR ,AND ,EQ ,NE ,LT ,GT ,LE ,GE ,SHL ,SHR ,ADD ,SUB ,MUL ,DIV ,MOD ,"
"OPEN,READ,CLOS,PRTF,MALC,MSET,MCMP,EXIT,"[i * 5]); "OPEN,READ,CLOS,PRTF,MALC,FREE,MSET,MCMP,EXIT,"[i * 5]);
if (i <= ADJ) printf(" %d\n", *pc); else printf("\n"); if (i <= ADJ) printf(" %d\n", *pc); else printf("\n");
} }
switch (i) { if (i == LEA) a = (int)(bp + *pc++); // load local address
case LEA: a = (int)(bp + *pc++); break; // load local address else if (i == IMM) a = *pc++; // load global address or immediate
case IMM: a = *pc++; break; // load global address or immediate else if (i == JMP) pc = (int *)*pc; // jump
case JMP: pc = (int *)*pc; break; // jump else if (i == JSR) { *--sp = (int)(pc + 1); pc = (int *)*pc; } // jump to subroutine
case JSR: *--sp = (int)(pc + 1); pc = (int *)*pc; break; // jump to subroutine else if (i == BZ) pc = a ? pc + 1 : (int *)*pc; // branch if zero
case BZ: pc = a ? pc + 1 : (int *)*pc; break; // branch if zero else if (i == BNZ) pc = a ? (int *)*pc : pc + 1; // branch if not zero
case BNZ: pc = a ? (int *)*pc : pc + 1; break; // branch if not zero else if (i == ENT) { *--sp = (int)bp; bp = sp; sp = sp - *pc++; } // enter subroutine
case ENT: *--sp = (int)bp; bp = sp; sp = sp - *pc++; break; // enter subroutine else if (i == ADJ) sp = sp + *pc++; // stack adjust
case ADJ: sp = sp + *pc++; break; // stack adjust else if (i == LEV) { sp = bp; bp = (int *)*sp++; pc = (int *)*sp++; } // leave subroutine
case LEV: sp = bp; bp = (int *)*sp++; pc = (int *)*sp++; break; // leave subroutine else if (i == LI) a = *(int *)a; // load int
case LI: a = *(int *)a; break; // load int else if (i == LC) a = *(char *)a; // load char
case LC: a = *(char *)a; break; // load char else if (i == SI) *(int *)*sp++ = a; // store int
case SI: *(int *)*sp++ = a; break; // store int else if (i == SC) a = *(char *)*sp++ = a; // store char
case SC: a = *(char *)*sp++ = a; break; // store char else if (i == PSH) *--sp = a; // push
case PSH: *--sp = a; break; // push
case OR: a = *sp++ | a; break; else if (i == OR) a = *sp++ | a;
case XOR: a = *sp++ ^ a; break; else if (i == XOR) a = *sp++ ^ a;
case AND: a = *sp++ & a; break; else if (i == AND) a = *sp++ & a;
case EQ: a = *sp++ == a; break; else if (i == EQ) a = *sp++ == a;
case NE: a = *sp++ != a; break; else if (i == NE) a = *sp++ != a;
case LT: a = *sp++ < a; break; else if (i == LT) a = *sp++ < a;
case GT: a = *sp++ > a; break; else if (i == GT) a = *sp++ > a;
case LE: a = *sp++ <= a; break; else if (i == LE) a = *sp++ <= a;
case GE: a = *sp++ >= a; break; else if (i == GE) a = *sp++ >= a;
case SHL: a = *sp++ << a; break; else if (i == SHL) a = *sp++ << a;
case SHR: a = *sp++ >> a; break; else if (i == SHR) a = *sp++ >> a;
case ADD: a = *sp++ + a; break; else if (i == ADD) a = *sp++ + a;
case SUB: a = *sp++ - a; break; else if (i == SUB) a = *sp++ - a;
case MUL: a = *sp++ * a; break; else if (i == MUL) a = *sp++ * a;
case DIV: a = *sp++ / a; break; else if (i == DIV) a = *sp++ / a;
case MOD: a = *sp++ % a; break; else if (i == MOD) a = *sp++ % a;
case OPEN: a = open((char *)sp[1], *sp); break; else if (i == OPEN) a = open((char *)sp[1], *sp);
case READ: a = read(sp[2], (char *)sp[1], *sp); break; else if (i == READ) a = read(sp[2], (char *)sp[1], *sp);
case CLOS: a = close(*sp); break; else if (i == CLOS) a = close(*sp);
case PRTF: t = sp + pc[1]; a = printf((char *)t[-1], t[-2], t[-3], t[-4], t[-5], t[-6]); break; else if (i == PRTF) { t = sp + pc[1]; a = printf((char *)t[-1], t[-2], t[-3], t[-4], t[-5], t[-6]); }
case MALC: a = (int)malloc(*sp); break; else if (i == MALC) a = (int)malloc(*sp);
case MSET: a = (int)memset((char *)sp[2], sp[1], *sp); break; else if (i == FREE) free((void *)*sp);
case MCMP: a = memcmp((char *)sp[2], (char *)sp[1], *sp); break; else if (i == MSET) a = (int)memset((char *)sp[2], sp[1], *sp);
case EXIT: printf("exit(%d) cycle = %d\n", *sp, cycle); return *sp; else if (i == MCMP) a = memcmp((char *)sp[2], (char *)sp[1], *sp);
default: printf("unknown instruction = %d! cycle = %d\n", i, cycle); return -1; 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; }
} }
} }