Jacek Caban : vbscript: Added support for exit do statement.

Alexandre Julliard julliard at winehq.org
Fri Sep 16 13:28:33 CDT 2011


Module: wine
Branch: master
Commit: 9701bdb563046b1f7fa535882b4629c4b7417b11
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=9701bdb563046b1f7fa535882b4629c4b7417b11

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Fri Sep 16 13:30:20 2011 +0200

vbscript: Added support for exit do statement.

---

 dlls/vbscript/compile.c      |   31 ++++++++++++++++++++++++++++++-
 dlls/vbscript/parse.h        |    1 +
 dlls/vbscript/parser.y       |    1 +
 dlls/vbscript/tests/lang.vbs |    5 +++++
 4 files changed, 37 insertions(+), 1 deletions(-)

diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c
index e29513b..61854e3 100644
--- a/dlls/vbscript/compile.c
+++ b/dlls/vbscript/compile.c
@@ -38,6 +38,7 @@ typedef struct {
     unsigned labels_size;
     unsigned labels_cnt;
 
+    unsigned while_end_label;
     unsigned sub_end_label;
     unsigned func_end_label;
     unsigned prop_end_label;
@@ -485,7 +486,7 @@ static HRESULT compile_if_statement(compile_ctx_t *ctx, if_statement_t *stat)
 
 static HRESULT compile_while_statement(compile_ctx_t *ctx, while_statement_t *stat)
 {
-    unsigned start_addr;
+    unsigned start_addr, prev_label;
     unsigned jmp_end;
     HRESULT hres;
 
@@ -499,6 +500,12 @@ static HRESULT compile_while_statement(compile_ctx_t *ctx, while_statement_t *st
     if(jmp_end == -1)
         return E_OUTOFMEMORY;
 
+    if(stat->stat.type != STAT_WHILE) {
+        prev_label = ctx->while_end_label;
+        if((ctx->while_end_label = alloc_label(ctx)) == -1)
+            return E_OUTOFMEMORY;
+    }
+
     hres = compile_statement(ctx, stat->body);
     if(FAILED(hres))
         return hres;
@@ -508,6 +515,12 @@ static HRESULT compile_while_statement(compile_ctx_t *ctx, while_statement_t *st
         return hres;
 
     instr_ptr(ctx, jmp_end)->arg1.uint = ctx->instr_cnt;
+
+    if(stat->stat.type != STAT_WHILE) {
+        label_set_addr(ctx, ctx->while_end_label);
+        ctx->while_end_label = prev_label;
+    }
+
     return S_OK;
 }
 
@@ -594,6 +607,16 @@ static HRESULT compile_function_statement(compile_ctx_t *ctx, function_statement
     return S_OK;
 }
 
+static HRESULT compile_exitdo_statement(compile_ctx_t *ctx)
+{
+    if(ctx->while_end_label == -1) {
+        FIXME("Exit Do outside Do Loop\n");
+        return E_FAIL;
+    }
+
+    return push_instr_addr(ctx, OP_jmp, ctx->while_end_label);
+}
+
 static HRESULT compile_exitsub_statement(compile_ctx_t *ctx)
 {
     if(ctx->sub_end_label == -1) {
@@ -639,6 +662,9 @@ static HRESULT compile_statement(compile_ctx_t *ctx, statement_t *stat)
         case STAT_DIM:
             hres = compile_dim_statement(ctx, (dim_statement_t*)stat);
             break;
+        case STAT_EXITDO:
+            hres = compile_exitdo_statement(ctx);
+            break;
         case STAT_EXITFUNC:
             hres = compile_exitfunc_statement(ctx);
             break;
@@ -698,6 +724,7 @@ static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *f
 
     func->code_off = ctx->instr_cnt;
 
+    ctx->while_end_label = -1;
     ctx->sub_end_label = -1;
     ctx->func_end_label = -1;
     ctx->prop_end_label = -1;
@@ -732,6 +759,8 @@ static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *f
     if(FAILED(hres))
         return hres;
 
+    assert(ctx->while_end_label == -1);
+
     if(ctx->sub_end_label != -1)
         label_set_addr(ctx, ctx->sub_end_label);
     if(ctx->func_end_label != -1)
diff --git a/dlls/vbscript/parse.h b/dlls/vbscript/parse.h
index ff8c137..5e9c9ae 100644
--- a/dlls/vbscript/parse.h
+++ b/dlls/vbscript/parse.h
@@ -93,6 +93,7 @@ typedef enum {
     STAT_ASSIGN,
     STAT_CALL,
     STAT_DIM,
+    STAT_EXITDO,
     STAT_EXITFUNC,
     STAT_EXITPROP,
     STAT_EXITSUB,
diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y
index c73f368..1bd8f58 100644
--- a/dlls/vbscript/parser.y
+++ b/dlls/vbscript/parser.y
@@ -159,6 +159,7 @@ Statement
     | tDO tWHILE Expression tNL StatementsNl_opt tLOOP
                                             { $$ = new_while_statement(ctx, STAT_WHILELOOP, $3, $5); CHECK_ERROR; }
     | FunctionDecl                          { $$ = new_function_statement(ctx, $1); CHECK_ERROR; }
+    | tEXIT tDO                             { $$ = new_statement(ctx, STAT_EXITDO, 0); CHECK_ERROR; }
     | tEXIT tFUNCTION                       { $$ = new_statement(ctx, STAT_EXITFUNC, 0); CHECK_ERROR; }
     | tEXIT tPROPERTY                       { $$ = new_statement(ctx, STAT_EXITPROP, 0); CHECK_ERROR; }
     | tEXIT tSUB                            { $$ = new_statement(ctx, STAT_EXITSUB, 0); CHECK_ERROR; }
diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs
index da1e5cb..78083e6 100644
--- a/dlls/vbscript/tests/lang.vbs
+++ b/dlls/vbscript/tests/lang.vbs
@@ -225,6 +225,11 @@ call ok((x and y), "x or y is false after while")
 do while false
 loop
 
+do while true
+    exit do
+    ok false, "exit do didn't work"
+loop
+
 if false then
 Sub testsub
     x = true




More information about the wine-cvs mailing list