diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c index 1f1f0410f5f..153e9b0c050 100644 --- a/dlls/vbscript/compile.c +++ b/dlls/vbscript/compile.c @@ -39,6 +39,7 @@ typedef struct { unsigned labels_cnt; unsigned while_end_label; + unsigned for_end_label; unsigned sub_end_label; unsigned func_end_label; unsigned prop_end_label; @@ -617,7 +618,7 @@ static HRESULT compile_dowhile_statement(compile_ctx_t *ctx, while_statement_t * static HRESULT compile_forto_statement(compile_ctx_t *ctx, forto_statement_t *stat) { - unsigned step_instr, instr; + unsigned step_instr, instr, prev_label; BSTR identifier; HRESULT hres; @@ -654,10 +655,16 @@ static HRESULT compile_forto_statement(compile_ctx_t *ctx, forto_statement_t *st return hres; } + prev_label = ctx->for_end_label; + ctx->for_end_label = alloc_label(ctx); + if(ctx->for_end_label == -1) + return E_OUTOFMEMORY; + step_instr = push_instr(ctx, OP_step); if(step_instr == -1) return E_OUTOFMEMORY; instr_ptr(ctx, step_instr)->arg2.bstr = identifier; + instr_ptr(ctx, step_instr)->arg1.uint = ctx->for_end_label; hres = compile_statement(ctx, stat->body); if(FAILED(hres)) @@ -672,7 +679,8 @@ static HRESULT compile_forto_statement(compile_ctx_t *ctx, forto_statement_t *st if(FAILED(hres)) return hres; - instr_ptr(ctx, step_instr)->arg1.uint = ctx->instr_cnt; + label_set_addr(ctx, ctx->for_end_label); + ctx->for_end_label = prev_label; return push_instr_uint(ctx, OP_pop, 2); } @@ -804,6 +812,16 @@ static HRESULT compile_exitdo_statement(compile_ctx_t *ctx) return push_instr_addr(ctx, OP_jmp, ctx->while_end_label); } +static HRESULT compile_exitfor_statement(compile_ctx_t *ctx) +{ + if(ctx->for_end_label == -1) { + FIXME("Exit For outside For Loop\n"); + return E_FAIL; + } + + return push_instr_addr(ctx, OP_jmp, ctx->for_end_label); +} + static HRESULT compile_exitsub_statement(compile_ctx_t *ctx) { if(ctx->sub_end_label == -1) { @@ -864,6 +882,9 @@ static HRESULT compile_statement(compile_ctx_t *ctx, statement_t *stat) case STAT_EXITDO: hres = compile_exitdo_statement(ctx); break; + case STAT_EXITFOR: + hres = compile_exitfor_statement(ctx); + break; case STAT_EXITFUNC: hres = compile_exitfunc_statement(ctx); break; @@ -931,6 +952,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->for_end_label = -1; ctx->sub_end_label = -1; ctx->func_end_label = -1; ctx->prop_end_label = -1; @@ -967,6 +989,7 @@ static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *f return hres; assert(ctx->while_end_label == -1); + assert(ctx->for_end_label == -1); if(ctx->sub_end_label != -1) label_set_addr(ctx, ctx->sub_end_label); diff --git a/dlls/vbscript/parse.h b/dlls/vbscript/parse.h index a5bd5051319..e58e7f33517 100644 --- a/dlls/vbscript/parse.h +++ b/dlls/vbscript/parse.h @@ -103,6 +103,7 @@ typedef enum { STAT_DOUNTIL, STAT_DOWHILE, STAT_EXITDO, + STAT_EXITFOR, STAT_EXITFUNC, STAT_EXITPROP, STAT_EXITSUB, diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y index 3b3005129f7..d6bda55a7ee 100644 --- a/dlls/vbscript/parser.y +++ b/dlls/vbscript/parser.y @@ -178,6 +178,7 @@ SimpleStatement CHECK_ERROR; } | FunctionDecl { $$ = new_function_statement(ctx, $1); CHECK_ERROR; } | tEXIT tDO { $$ = new_statement(ctx, STAT_EXITDO, 0); CHECK_ERROR; } + | tEXIT tFOR { $$ = new_statement(ctx, STAT_EXITFOR, 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 3b3ad508f54..46a03300319 100644 --- a/dlls/vbscript/tests/lang.vbs +++ b/dlls/vbscript/tests/lang.vbs @@ -387,6 +387,15 @@ for x = 5 to 8 next Call ok(y = "for8: 5 7", "y = " & y) +for x = 1.5 to 1 + Call ok(false, "for..to called when unexpected") +next + +for x = 1 to 100 + exit for + Call ok(false, "exit for not escaped the loop?") +next + if false then Sub testsub x = true