summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--miniany/c4.c50
-rw-r--r--miniany/cc.c143
-rwxr-xr-xminiany/torture.sh12
3 files changed, 141 insertions, 64 deletions
diff --git a/miniany/c4.c b/miniany/c4.c
index a36fb4a..9acba4e 100644
--- a/miniany/c4.c
+++ b/miniany/c4.c
@@ -18,6 +18,9 @@ char *p, *lp, // current position in source code
*data; // data/bss pointer
int *e, *le, // current position in emitted code
+ *cas, // case statement patch-up pointer
+ *brak, // break statement patch-up pointer
+ *def, // default statement patch-up pointer
*id, // currently parsed identifier
*sym, // symbol table (simple list of identifiers)
tk, // current token
@@ -31,7 +34,7 @@ int *e, *le, // current position in emitted code
// tokens and classes (operators last and in precedence order)
enum {
Num = 128, Fun, Sys, Glo, Loc, Id,
- Char, Else, Enum, If, Int, Return, Sizeof, Do, While,
+ Break, Case, Char, Default, Else, Enum, If, Int, Return, Sizeof, Do, Switch, While,
Assign, Cond, Lor, Lan, Or, Xor, And, Eq, Ne, Lt, Gt, Le, Ge, Shl, Shr, Add, Sub, Mul, Div, Mod, Inc, Dec, Brak
};
@@ -59,7 +62,7 @@ void next()
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,GETC,PUTS,PUTN,PUTC,PUTI,ISPC,IDGT,IANU.IALP,SCMP,EXIT,"[*++le * 5]);
+ "OPEN,READ,CLOS,PRTF,MALC,FREE,MSET,MCMP,GETC,PUTS,PUTN,PUTC,PUTI,ISPC,IDGT,IANU,IALP,SCMP,EXIT,"[*++le * 5]);
if (*le <= ADJ) printf(" %d\n", *++le); else printf("\n");
}
}
@@ -293,7 +296,7 @@ void expr(int lev)
void stmt()
{
- int *a, *b;
+ int *a, *b, *d, i;
if (tk == If) {
next();
@@ -333,6 +336,43 @@ void stmt()
*++e = JMP; *++e = (int)a;
*b = (int)(e + 1);
}
+ else if (tk == Switch) {
+ 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 = brak; d = def; brak = def = 0;
+ 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) {
+ *++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();
+ }
+ else if (tk == 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) {
+ next();
+ if (tk == ':') next(); else { printf("%d: colon expected\n", line); exit(-1); }
+ def = e + 1;
+ stmt();
+ }
else if (tk == Return) {
next();
if (tk != ';') expr(Assign);
@@ -376,10 +416,10 @@ int main(int argc, char **argv)
memset(e, 0, poolsz);
memset(data, 0, poolsz);
- p = "char else enum if int return sizeof do while "
+ p = "break case char default else enum if int return sizeof do switch while "
"EOF EXIT_SUCCESS EXIT_FAILURE NULL "
"open read close printf malloc free memset memcmp getchar putstring putnl putchar putint isspace isdigit isalnum isalpha strcmp exit void main";
- i = Char; while (i <= While) { next(); id[Tk] = i++; } // add keywords to symbol table
+ i = Break; while (i <= While) { next(); id[Tk] = i++; } // add keywords to symbol table
// add library constants
next(); id[Class] = Num; id[Type] = INT; id[Val] = -1;
next(); id[Class] = Num; id[Type] = INT; id[Val] = 0;
diff --git a/miniany/cc.c b/miniany/cc.c
index e5b30c7..ba7ead2 100644
--- a/miniany/cc.c
+++ b/miniany/cc.c
@@ -114,15 +114,17 @@ void scanIdent( int c )
int keyword( char *ident )
{
- if( *ident == 'i' ) {
- if( strcmp( ident, "int" ) == 0 ) {
- return S_INT;
- } else {
- return 0;
- }
+ switch( ident[0] ) {
+ case 'i':
+ if( strcmp( ident, "int" ) == 0 ) {
+ return S_INT;
+ } else {
+ return 0;
+ }
+ break;
+ default:
+ return 0;
}
-
- return 0;
}
int getToken( )
@@ -132,55 +134,76 @@ int getToken( )
c = skipWhite( );
- if( c == EOF ) {
- t = S_EOI;
- } else if( c == '+' ) {
- t = S_PLUS;
- } else if( c == '-' ) {
- t = S_MINUS;
- } else if( c == '*' ) {
- t = S_STAR;
- } else if ( c == '/' ) {
- c = getChar( );
- if( c == '/' ) {
- while( c != '\n' ) {
- c = getChar( );
- }
- t = getToken( );
- } else if( c == '*' ) {
- do {
- while( c != '*' ) {
+ switch( c ) {
+ case EOF:
+ t = S_EOI;
+ break;
+ case '+':
+ t = S_PLUS;
+ break;
+ case '-':
+ t = S_MINUS;
+ break;
+ case '*':
+ t = S_STAR;
+ break;
+ case '/':
+ c = getChar( );
+ if( c == '/' ) {
+ while( c != '\n' ) {
c = getChar( );
}
+ t = getToken( );
+ } else if( c == '*' ) {
+ do {
+ while( c != '*' ) {
+ c = getChar( );
+ }
+ c = getChar( );
+ } while( c != '/' );
c = getChar( );
- } while( c != '/' );
- c = getChar( );
- t = getToken( );
- } else {
- pushBack( c );
- t = S_SLASH;
- }
- } else if( c == ';' ) {
- t = S_SEMICOLON;
- } else if( c == '=' ) {
- t = S_EQUALS;
- } else if( isdigit( c ) ) {
- scanNumber( c );
- t = S_NUM;
- } else if( c >= 'a' && c <= 'z' ) {
- scanIdent( c );
- if( ( t = keyword( ident ) ) ) {
- } else {
- t = S_IDENT;
- }
- } else {
- t = S_ERR;
- printErrorHeader( );
- putstring( "unknown token '" );
- putchar( c );
- putstring( "'" );
- putnl( );
- exit( EXIT_FAILURE );
+ t = getToken( );
+ } else {
+ pushBack( c );
+ t = S_SLASH;
+ }
+ break;
+ case ';':
+ t = S_SEMICOLON;
+ break;
+ case '=':
+ t = S_EQUALS;
+ break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ scanNumber( c );
+ t = S_NUM;
+ 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 '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 '_':
+ scanIdent( c );
+ if( ( t = keyword( ident ) ) ) {
+ } else {
+ t = S_IDENT;
+ }
+ break;
+ default:
+ t = S_ERR;
+ printErrorHeader( );
+ putstring( "unknown token '" );
+ putchar( c );
+ putstring( "'" );
+ putnl( );
+ exit( EXIT_FAILURE );
}
if( DEBUG_SCANNER ) {
@@ -253,11 +276,13 @@ void parseExpression( )
}
}
-//~ struct Symbol {
- //~ char *name;
-//~ };
+/*
+struct Symbol {
+ char *name;
+};
-//~ struct Symbol *symbol;
+struct Symbol *symbol;
+*/
void newSymbol( char *s )
{
@@ -298,7 +323,7 @@ int main( int argc, char **argv )
row = 1;
pushback = 0;
DEBUG_SCANNER = 1;
- //~ symbol = NULL;
+ /* symbol = NULL; */
ident = "12345678901234567890";
token = getToken( );
diff --git a/miniany/torture.sh b/miniany/torture.sh
new file mode 100755
index 0000000..06c41c4
--- /dev/null
+++ b/miniany/torture.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+
+for COMPILER in gcc clang pcc tcc; do
+ $COMPILER -m32 -o c4 c4.c
+ for MODE in freestanding hosted; do
+ for LEVEL in 0; do
+ ./build.sh cc $COMPILER $MODE $LEVEL
+ ./cc < cc.c
+ done
+ done
+done