diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c index 5737676be77..1ff3c409f81 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 624e49f2722..d121b727cf8 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 820ae6c19be..b1b385b21ec 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 8b1d1c3d03a..c62f17f973d 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