From 4e92bac0703f0dc55789aa67556433cac26b3c11 Mon Sep 17 00:00:00 2001
From: bellard <bellard>
Date: Tue, 30 Oct 2001 20:27:54 +0000
Subject: [PATCH] added do while continue - simplify break/continue handling

---
 tcc.c | 93 ++++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 63 insertions(+), 30 deletions(-)

diff --git a/tcc.c b/tcc.c
index 98d35e31..d95257ed 100644
--- a/tcc.c
+++ b/tcc.c
@@ -11,12 +11,11 @@
    glo : global variable index
    parm : parameter variable index
    ind : output code ptr
-   lsym: loop symbol stack
    rsym: return symbol
    prog: output code
    astk: arg position stack
 */
-int tok, *vac, *vat, *lsym, rsym, 
+int tok, *vac, *vat, rsym, 
     prog, ind, loc, glo, file, vt, 
     vc, *macro_stack, *macro_stack_ptr, line_num;
 char *idtable, *idptr, *filename;
@@ -87,17 +86,21 @@ char *idtable, *idptr, *filename;
 #define TOK_CASE     274
 
 /* ignored types Must have contiguous values */
-#define TOK_CONST    271
-#define TOK_LONG     276
-#define TOK_REGISTER 277
-#define TOK_SIGNED   278
+#define TOK_CONST    275
+#define TOK_VOLATILE 276
+#define TOK_LONG     277
+#define TOK_REGISTER 278
+#define TOK_SIGNED   279
 
 /* unsupported types. Must have contiguous values */
-#define TOK_FLOAT    279
-#define TOK_DOUBLE   280
-#define TOK_STRUCT   281
-#define TOK_UNION    282
-#define TOK_TYPEDEF  283
+#define TOK_FLOAT    280
+#define TOK_DOUBLE   281
+#define TOK_STRUCT   282
+#define TOK_UNION    283
+#define TOK_TYPEDEF  284
+
+#define TOK_DEFAULT  285
+#define TOK_ENUM     286
 
 #define TOK_EQ 0x94 /* warning: depend on asm code */
 #define TOK_NE 0x95 /* warning: depend on asm code */
@@ -336,16 +339,21 @@ void o(c)
 }
 
 /* output a symbol and patch all calls to it */
-void gsym(t)
+void gsym_addr(t, a)
 {
     int n;
     while (t) {
         n = *(int *)t; /* next value */
-        *(int *)t = ind - t - 4;
+        *(int *)t = a - t - 4;
         t = n;
     }
 }
 
+void gsym(t)
+{
+    gsym_addr(t, ind);
+}
+
 /* psym is used to put an instruction with a data field which is a
    reference to a symbol. It is in fact the same as oad ! */
 #define psym oad
@@ -1022,9 +1030,9 @@ void expr()
 
 #endif
 
-void block()
+void block(int *bsym, int *csym)
 {
-    int a, c, d;
+    int a, b, c, d;
 
     if (tok == TOK_IF) {
         /* if test */
@@ -1033,13 +1041,13 @@ void block()
         expr();
         skip(')');
         a = gtst(1, 0);
-        block();
+        block(bsym, csym);
         c = tok;
         if (c == TOK_ELSE) {
             next();
             d = psym(0xe9, 0); /* jmp */
             gsym(a);
-            block();
+            block(bsym, csym);
             gsym(d); /* patch else jmp */
         } else
             gsym(a);
@@ -1049,16 +1057,18 @@ void block()
         skip('(');
         expr();
         skip(')');
-        *++lsym = gtst(1, 0);
-        block();
+        a = gtst(1, 0);
+        b = 0;
+        block(&a, &b);
         oad(0xe9, d - ind - 5); /* jmp */
-        gsym(*lsym--);
+        gsym(a);
+        gsym_addr(b, d);
     } else if (tok == '{') {
         next();
         /* declarations */
         decl(VT_LOCAL);
         while (tok != '}')
-            block();
+            block(bsym, csym);
         next();
     } else if (tok == TOK_RETURN) {
         next();
@@ -1070,7 +1080,16 @@ void block()
         rsym = psym(0xe9, rsym); /* jmp */
     } else if (tok == TOK_BREAK) {
         /* compute jump */
-        *lsym = psym(0xe9, *lsym);
+        if (!bsym)
+            error("cannot break");
+        *bsym = psym(0xe9, *bsym);
+        next();
+        skip(';');
+    } else if (tok == TOK_CONTINUE) {
+        /* compute jump */
+        if (!csym)
+            error("cannot continue");
+        *csym = psym(0xe9, *csym);
         next();
         skip(';');
     } else 
@@ -1085,11 +1104,11 @@ void block()
         d = ind;
         c = ind;
         a = 0;
+        b = 0;
         if (tok != ';') {
             expr();
             a = gtst(1, 0);
         }
-        *++lsym = a;
         skip(';');
         if (tok != ')') {
             e = psym(0xe9, 0);
@@ -1099,10 +1118,26 @@ void block()
             gsym(e);
         }
         skip(')');
-        block();
+        block(&a, &b);
         oad(0xe9, c - ind - 5); /* jmp */
-        gsym(*lsym--);
+        gsym(a);
+        gsym_addr(b, c);
     } else 
+    if (tok == TOK_DO) {
+        next();
+        a = 0;
+        b = 0;
+        d = ind;
+        block(&a, &b);
+        skip(TOK_WHILE);
+        skip('(');
+        gsym(b);
+        expr();
+        c = gtst(0, 0);
+        gsym_addr(c, d);
+        skip(')');
+        gsym(a);
+    } else
 #endif
     {
         if (tok != ';')
@@ -1131,7 +1166,7 @@ void decl(l)
                 o(0xe58955); /* push   %ebp, mov    %esp, %ebp */
                 a = oad(0xec81, 0); /* sub $xxx, %esp */
                 rsym = 0;
-                block();
+                block(0, 0);
                 gsym(rsym);
                 o(0xc3c9); /* leave, ret */
                 *a = (-loc + 3) & -4; /* align local size to word & 
@@ -1207,15 +1242,13 @@ int main(int c, char **v)
     idptr = idtable + 53;
 #else
     memcpy(idtable, 
-           "int\0void\0char\0if\0else\0while\0break\0return\0define\0main\0for\0extern\0static\0unsigned\0goto\0do\0continue\0switch\0case\0const\0long\0register\0signed\0float\0double\0struct\0union\0typedef", 170);
-
-    idptr = idtable + 170;
+           "int\0void\0char\0if\0else\0while\0break\0return\0define\0main\0for\0extern\0static\0unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0register\0signed\0float\0double\0struct\0union\0typedef\0default\0enum", 192);
+    idptr = idtable + 192;
 #endif
     glo = malloc(DATA_SIZE);
     prog = malloc(TEXT_SIZE);
     vac = malloc(VAR_TABLE_SIZE);
     vat = malloc(VAR_TABLE_SIZE);
-    lsym = malloc(256);
     macro_stack = malloc(256);
     macro_stack_ptr = macro_stack;
     ind = prog;