From 9701bdb563046b1f7fa535882b4629c4b7417b11 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Fri, 16 Sep 2011 13:30:20 +0200 Subject: [PATCH] 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 deletion(-) diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c index e29513b2979..61854e33b54 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 ff8c137ad21..5e9c9ae9208 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 c73f368287b..1bd8f582827 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 da1e5cb7dc7..78083e60bd7 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 -- 2.11.4.GIT