Module: wine Branch: master Commit: 004210f1fb4abe85fd62a37a915696b66502a372 URL: http://source.winehq.org/git/wine.git/?a=commit;h=004210f1fb4abe85fd62a37a91...
Author: Jacek Caban jacek@codeweavers.com Date: Fri Sep 16 13:30:39 2011 +0200
vbscript: Added do..while and do..until statements implementation.
---
dlls/vbscript/compile.c | 34 +++++++++++++++++++++++++++++++++- dlls/vbscript/parse.h | 2 ++ dlls/vbscript/parser.y | 3 +++ dlls/vbscript/tests/lang.vbs | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 1 deletions(-)
diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c index 5737676..1ff3c40 100644 --- a/dlls/vbscript/compile.c +++ b/dlls/vbscript/compile.c @@ -211,7 +211,7 @@ static BSTR alloc_bstr_arg(compile_ctx_t *ctx, const WCHAR *str) return NULL; ctx->code->bstr_pool_size = 8; }else if(ctx->code->bstr_pool_size == ctx->code->bstr_cnt) { - BSTR *new_pool; + BSTR *new_pool;
new_pool = heap_realloc(ctx->code->bstr_pool, ctx->code->bstr_pool_size*2*sizeof(BSTR)); if(!new_pool) @@ -524,6 +524,34 @@ static HRESULT compile_while_statement(compile_ctx_t *ctx, while_statement_t *st return S_OK; }
+static HRESULT compile_dowhile_statement(compile_ctx_t *ctx, while_statement_t *stat) +{ + unsigned start_addr, prev_label; + HRESULT hres; + + start_addr = ctx->instr_cnt; + + 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; + + hres = compile_expression(ctx, stat->expr); + if(FAILED(hres)) + return hres; + + hres = push_instr_addr(ctx, stat->stat.type == STAT_DOUNTIL ? OP_jmp_false : OP_jmp_true, start_addr); + if(FAILED(hres)) + return hres; + + label_set_addr(ctx, ctx->while_end_label); + ctx->while_end_label = prev_label; + return S_OK; +} + static HRESULT compile_assign_statement(compile_ctx_t *ctx, assign_statement_t *stat, BOOL is_set) { HRESULT hres; @@ -662,6 +690,10 @@ 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_DOWHILE: + case STAT_DOUNTIL: + hres = compile_dowhile_statement(ctx, (while_statement_t*)stat); + break; case STAT_EXITDO: hres = compile_exitdo_statement(ctx); break; diff --git a/dlls/vbscript/parse.h b/dlls/vbscript/parse.h index 624e49f..d121b72 100644 --- a/dlls/vbscript/parse.h +++ b/dlls/vbscript/parse.h @@ -93,6 +93,8 @@ typedef enum { STAT_ASSIGN, STAT_CALL, STAT_DIM, + STAT_DOUNTIL, + STAT_DOWHILE, STAT_EXITDO, STAT_EXITFUNC, STAT_EXITPROP, diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y index 820ae6c..b1b385b 100644 --- a/dlls/vbscript/parser.y +++ b/dlls/vbscript/parser.y @@ -159,6 +159,9 @@ Statement | tDO DoType Expression tNL StatementsNl_opt tLOOP { $$ = new_while_statement(ctx, $2 ? STAT_WHILELOOP : STAT_UNTIL, $3, $5); CHECK_ERROR; } + | tDO tNL StatementsNl_opt tLOOP DoType Expression + { $$ = new_while_statement(ctx, $5 ? STAT_DOWHILE : STAT_DOUNTIL, $6, $3); + 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; } diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs index 8b1d1c3..c62f17f 100644 --- a/dlls/vbscript/tests/lang.vbs +++ b/dlls/vbscript/tests/lang.vbs @@ -248,6 +248,42 @@ do until false ok false, "exit do didn't work" loop
+x = false +y = false +do + if x then + y = true + end if + x = true +loop until x and y +call ok((x and y), "x or y is false after while") + +do +loop until true + +do + exit do + ok false, "exit do didn't work" +loop until false + +x = false +y = false +do + if x then + y = true + end if + x = true +loop while not (x and y) +call ok((x and y), "x or y is false after while") + +do +loop while false + +do + exit do + ok false, "exit do didn't work" +loop while true + if false then Sub testsub x = true