From: Francis De Brabandere <francisdb@gmail.com> When a statement and its closing keyword appear on the same line without a separator (newline or colon), Windows returns specific error codes: - 1042 (Must be first statement on the line) for End If, End Select - 1024 (Expected statement) for End While, End Class, Else End If - 1025 (Expected end of statement) for Wend, Loop Wine was returning generic E_FAIL (16389) for all of these. Add targeted error productions in the parser grammar to detect block-closing keywords following a statement without a separator, and set the appropriate VBScript error code before aborting. --- dlls/vbscript/parser.y | 9 +++++++++ dlls/vbscript/tests/run.c | 24 ++++++++++++------------ 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y index c1a5b944268..45651c956f5 100644 --- a/dlls/vbscript/parser.y +++ b/dlls/vbscript/parser.y @@ -201,6 +201,13 @@ StatementsNl_opt StatementsNl : SimpleStatement StSep { $$ = $1; } | SimpleStatement StSep StatementsNl { $$ = link_statements($1, $3); } + | SimpleStatement tEND tIF { ctx->error_loc = @2; ctx->hres = MAKE_VBSERROR(VBSE_MUST_BE_FIRST_STATEMENT); YYABORT; } + | SimpleStatement tEND tSELECT { ctx->error_loc = @2; ctx->hres = MAKE_VBSERROR(VBSE_MUST_BE_FIRST_STATEMENT); YYABORT; } + | SimpleStatement tEND tWHILE { ctx->error_loc = @2; ctx->hres = MAKE_VBSERROR(VBSE_EXPECTED_STATEMENT); YYABORT; } + | SimpleStatement tWEND { ctx->error_loc = @2; ctx->hres = MAKE_VBSERROR(VBSE_EXPECTED_END_OF_STATEMENT); YYABORT; } + | SimpleStatement tLOOP DoType Expression + { ctx->error_loc = @2; ctx->hres = MAKE_VBSERROR(VBSE_EXPECTED_END_OF_STATEMENT); YYABORT; } + | SimpleStatement tLOOP { ctx->error_loc = @2; ctx->hres = MAKE_VBSERROR(VBSE_EXPECTED_END_OF_STATEMENT); YYABORT; } StatementNl : Statement tNL { $$ = $1; } @@ -339,6 +346,7 @@ Else_opt : /* empty */ { $$ = NULL; } | tELSE StSep StatementsBody_opt { $$ = $3; } | tELSE StatementsBody { $$ = $2; } + | tELSE tEND tIF { ctx->error_loc = @2; ctx->hres = MAKE_VBSERROR(VBSE_EXPECTED_STATEMENT); YYABORT; } StatementsBody_opt : /* empty */ { $$ = NULL; } @@ -478,6 +486,7 @@ PrimaryExpression ClassDeclaration : tCLASS Identifier StSep ClassBody tEND tCLASS StSep { $4->name = $2; $$ = $4; } + | tCLASS Identifier tEND tCLASS { ctx->error_loc = @3; ctx->hres = MAKE_VBSERROR(VBSE_EXPECTED_STATEMENT); YYABORT; } ClassBody : /* empty */ { $$ = new_class_decl(ctx); } diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c index d3aebff098a..8192c58fd20 100644 --- a/dlls/vbscript/tests/run.c +++ b/dlls/vbscript/tests/run.c @@ -2723,7 +2723,7 @@ static void test_parse_errors(void) L"If 0 > 1 Then\n" " x = 0 End If\n", 1, 10, - L" x = 0 End If", S_OK, -1042 + L" x = 0 End If", S_OK, 1042 }, { /* ElseIf...End If */ @@ -2732,7 +2732,7 @@ static void test_parse_errors(void) "ElseIf True Then\n" " x = 1 End If\n", 3, 10, - L" x = 1 End If", S_OK, -1042 + L" x = 1 End If", S_OK, 1042 }, { /* Else End If (no separator) */ @@ -2740,49 +2740,49 @@ static void test_parse_errors(void) " x = 0\n" "Else End If\n", 2, 5, - L"Else End If", S_OK, -1024 + L"Else End If", S_OK, 1024 }, { /* While...End While */ L"While False\n" " x = 0 End While\n", 1, 10, - L" x = 0 End While", S_OK, -1024 + L" x = 0 End While", S_OK, 1024 }, { /* While...Wend */ L"While False\n" " x = 0 Wend\n", 1, 10, - L" x = 0 Wend", S_OK, -1025 + L" x = 0 Wend", S_OK, 1025 }, { /* Do While...Loop */ L"Do While False\n" " x = 0 Loop\n", 1, 10, - L" x = 0 Loop", S_OK, -1025 + L" x = 0 Loop", S_OK, 1025 }, { /* Do Until...Loop */ L"Do Until True\n" " x = 0 Loop\n", 1, 10, - L" x = 0 Loop", S_OK, -1025 + L" x = 0 Loop", S_OK, 1025 }, { /* Do...Loop While */ L"Do\n" " x = 0 Loop While False\n", 1, 10, - L" x = 0 Loop While False", S_OK, -1025 + L" x = 0 Loop While False", S_OK, 1025 }, { /* Do...Loop Until */ L"Do\n" " x = 0 Loop Until True\n", 1, 10, - L" x = 0 Loop Until True", S_OK, -1025 + L" x = 0 Loop Until True", S_OK, 1025 }, { /* Select...End Select */ @@ -2794,19 +2794,19 @@ static void test_parse_errors(void) " x = True End Select\n" "Call ok(x, \"wrong case\")\n", 5, 17, - L" x = True End Select", S_OK, -1042 + L" x = True End Select", S_OK, 1042 }, { /* Class...End Class (empty) */ L"Class C End Class", 0, 8, - L"Class C End Class", S_OK, -1024 + L"Class C End Class", S_OK, 1024 }, { /* Class...End Class (empty) */ L"Class C _\nEnd Class", 1, 0, - L"End Class", S_OK, -1024 + L"End Class", S_OK, 1024 }, { /* invalid use of parentheses for call statement */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10498