[PATCH v12 0/4] MR10386: vbscript: Return proper error codes for compile errors.
Add error_code field to parse error tests, using negative values for codes that Wine does not yet return correctly (todo_wine), matching the existing pattern for error_char. Return MAKE_VBSERROR with proper error codes instead of E_FAIL for name redefinition, invalid exit statements, and invalid parenthesized call statements. -- v12: vbscript: Improve some error codes in the parser. vbscript: Improve some error codes in the lexer. vbscript: Improve some error codes in the compiler. vbscript/tests: Add error code tests for compile errors. https://gitlab.winehq.org/wine/wine/-/merge_requests/10386
From: Francis De Brabandere <francisdb@gmail.com> Add error_code field to parse error tests, using negative values for codes that Wine does not yet return correctly (todo_wine), matching the existing pattern for error_char. --- dlls/vbscript/tests/run.c | 169 +++++++++++++++++++++++++++++++--- dlls/vbscript/vbscript.rc | 32 +++++++ dlls/vbscript/vbscript_defs.h | 32 +++++++ 3 files changed, 220 insertions(+), 13 deletions(-) diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c index 80cd3a34bd2..a641214b038 100644 --- a/dlls/vbscript/tests/run.c +++ b/dlls/vbscript/tests/run.c @@ -2007,6 +2007,7 @@ static HRESULT WINAPI ActiveScriptSite_OnStateChange(IActiveScriptSite *iface, S static IActiveScriptError **store_script_error; static ULONG error_line; static LONG error_char; +static USHORT error_code; static HRESULT WINAPI ActiveScriptSite_OnScriptError(IActiveScriptSite *iface, IActiveScriptError *pscripterror) { @@ -2023,6 +2024,15 @@ static HRESULT WINAPI ActiveScriptSite_OnScriptError(IActiveScriptSite *iface, I trace("Error in line %lu: %x %s\n", error_line + 1, info.wCode, wine_dbgstr_w(info.bstrDescription)); }else { IDispatchEx *dispex; + EXCEPINFO info; + + hres = IActiveScriptError_GetExceptionInfo(pscripterror, &info); + if(SUCCEEDED(hres)) { + error_code = HRESULT_CODE(info.scode); + SysFreeString(info.bstrSource); + SysFreeString(info.bstrDescription); + SysFreeString(info.bstrHelpFile); + } hres = IActiveScriptError_QueryInterface(pscripterror, &IID_IDispatchEx, (void**)&dispex); ok(hres == E_NOINTERFACE, "QI(IDispatchEx) returned: %08lx\n", hres); @@ -2696,6 +2706,7 @@ static void test_parse_errors(void) const WCHAR *src; unsigned error_line; int error_char; + int error_code; } invalid_scripts[] = { @@ -2703,7 +2714,7 @@ static void test_parse_errors(void) /* If...End If */ L"If 0 > 1 Then\n" " x = 0 End If\n", - 1, 10 + 1, 10, -1042 }, { /* ElseIf...End If */ @@ -2711,50 +2722,50 @@ static void test_parse_errors(void) " x = 0\n" "ElseIf True Then\n" " x = 1 End If\n", - 3, 10 + 3, 10, -1042 }, { /* Else End If (no separator) */ L"If False Then\n" " x = 0\n" "Else End If\n", - 2, 5 + 2, 5, -1024 }, { /* While...End While */ L"While False\n" " x = 0 End While\n", - 1, 10 + 1, 10, -1024 }, { /* While...Wend */ L"While False\n" " x = 0 Wend\n", - 1, 10 + 1, 10, -1025 }, { /* Do While...Loop */ L"Do While False\n" " x = 0 Loop\n", - 1, 10 + 1, 10, -1025 }, { /* Do Until...Loop */ L"Do Until True\n" " x = 0 Loop\n", - 1, 10 + 1, 10, -1025 }, { /* Do...Loop While */ L"Do\n" " x = 0 Loop While False\n", - 1, 10 + 1, 10, -1025 }, { /* Do...Loop Until */ L"Do\n" " x = 0 Loop Until True\n", - 1, 10 + 1, 10, -1025 }, { /* Select...End Select */ @@ -2765,22 +2776,22 @@ static void test_parse_errors(void) " Case 42\n" " x = True End Select\n" "Call ok(x, \"wrong case\")\n", - 5, 17 + 5, 17, -1042 }, { /* Class...End Class (empty) */ L"Class C End Class", - 0, 8 + 0, 8, -1024 }, { /* Class...End Class (empty) */ L"Class C _\nEnd Class", - 1, 0 + 1, 0, -1024 }, { /* invalid use of parentheses for call statement */ L"strcomp(\"x\", \"y\")", - 0, 17 + 0, 17, -1044 }, { L"\n\n\n cint _\n throwInt(&h80001234&)", @@ -2829,6 +2840,133 @@ static void test_parse_errors(void) " throwInt &h87001234&\n" "end if\n", 2, 1 + }, + { + /* Unterminated string constant - error 1033 */ + L"x = \"hello\n", + 0, -10, -1033 + }, + { + /* Expected 'End' - error 1014 */ + L"If True Then\nx = 1\n", + 2, 0, -1014 + }, + { + /* Name redefined - error 1041 */ + L"Dim a\nDim a\n", + 1, -4, -1041 + }, + { + /* Expected identifier - error 1010 */ + L"Dim If\n", + 0, 4, -1010 + }, + { + /* Invalid character - error 1032 */ + L"x = @invalid\n", + 0, 4, -1032 + }, + { + /* Expected literal constant - error 1045 */ + L"Const x = 1 + \"a\"\n", + 0, -17, -1045 + }, + { + /* Expected '(' - error 1005 */ + L"Sub x)\nEnd Sub\n", + 0, 5, -1005 + }, + { + /* Expected '=' - error 1011 */ + L"Const x\n", + 0, 7, -1011 + }, + { + /* Expected 'To' - error 1013 */ + L"For i = 1 x 10\nNext\n", + 0, 10, -1013 + }, + { + /* Expected 'Then' - error 1017 */ + L"If True\nEnd If\n", + 0, 7, -1017 + }, + { + /* Expected 'Wend' - error 1018 */ + L"While True\nx = 1\n", + 2, 0, -1018 + }, + { + /* Expected 'Loop' - error 1019 */ + L"Do\nx = 1\n", + 2, 0, -1019 + }, + { + /* Expected 'Next' - error 1020 */ + L"For i = 1 To 10\nx = 1\n", + 2, 0, -1020 + }, + { + /* Expected 'Case' - error 1021 */ + L"Select x\nEnd Select\n", + 0, 7, -1021 + }, + { + /* Expected integer constant - error 1026 */ + L"Dim x(\"a\")\n", + 0, 6, -1026 + }, + { + /* Invalid number - error 1031 */ + L"x = 1e999\n", + 0, -9, -1031 + }, + { + /* 'loop' without 'do' - error 1038 */ + L"Loop\n", + 0, 0, -1038 + }, + { + /* Invalid 'exit' statement - error 1039 */ + L"Exit Do\n", + 0, -5, -1039 + }, + { + /* Expected 'In' - error 1046 */ + L"For Each x = arr\nNext\n", + 0, 11, -1046 + }, + { + /* Must be defined inside a Class - error 1048 */ + L"Property Get x\nEnd Property\n", + 0, 9, -1048 + }, + { + /* Expected Let or Set or Get - error 1049 */ + L"Class C\nProperty x\nEnd Property\nEnd Class\n", + 1, 9, -1049 + }, + /* TODO: Wine allows arguments on Class_Initialize/Class_Terminate + { + Class initialize/terminate no arguments - error 1053 + L"Class C\nSub Class_Initialize(x)\nEnd Sub\nEnd Class\n", + 1, 20, 1053 + }, + */ + { + /* Property Let/Set needs at least one argument - error 1054 */ + L"Class C\nProperty Let x\nEnd Property\nEnd Class\n", + 1, 14, -1054 + }, + { + /* Unexpected 'Next' - error 1055 */ + L"Next\n", + 0, 0, -1055 + }, + { + /* 'Default' must also specify 'Public' - error 1057 */ + L"Class C\nDefault Private Function f()\nf = 1\nEnd Function\nEnd Class\n", + 1, 0, -1057 } }; HRESULT hres; @@ -2838,6 +2976,7 @@ static void test_parse_errors(void) { error_line = ~0; error_char = -1; + error_code = 0; onerror_hres = S_OK; SET_EXPECT(OnScriptError); @@ -2850,6 +2989,10 @@ static void test_parse_errors(void) todo_wine_if(invalid_scripts[i].error_char < 0) ok(error_char == abs(invalid_scripts[i].error_char), "[%u] error char %ld expected %d\n", i, error_char, invalid_scripts[i].error_char); + if(invalid_scripts[i].error_code) + todo_wine_if(invalid_scripts[i].error_code < 0) + ok(error_code == abs(invalid_scripts[i].error_code), "[%u] error code %u expected %u\n", + i, error_code, abs(invalid_scripts[i].error_code)); } } diff --git a/dlls/vbscript/vbscript.rc b/dlls/vbscript/vbscript.rc index b9a1c3ad5c3..a0f7381bcf0 100644 --- a/dlls/vbscript/vbscript.rc +++ b/dlls/vbscript/vbscript.rc @@ -59,6 +59,38 @@ STRINGTABLE VBSE_INVALID_TYPELIB_VARIABLE "Variable uses an Automation type not supported in VBScript" VBSE_SERVER_NOT_FOUND "The remote server machine does not exist or is unavailable" VBSE_UNQUALIFIED_REFERENCE "Invalid or unqualified reference" + VBSE_SYNTAX_ERROR "Syntax error" + VBSE_EXPECTED_LPAREN "Expected '('" + VBSE_EXPECTED_IDENTIFIER "Expected identifier" + VBSE_EXPECTED_ASSIGN "Expected '='" + VBSE_EXPECTED_TO "Expected 'To'" + VBSE_EXPECTED_END "Expected 'End'" + VBSE_EXPECTED_THEN "Expected 'Then'" + VBSE_EXPECTED_WEND "Expected 'Wend'" + VBSE_EXPECTED_LOOP "Expected 'Loop'" + VBSE_EXPECTED_NEXT "Expected 'Next'" + VBSE_EXPECTED_CASE "Expected 'Case'" + VBSE_EXPECTED_STATEMENT "Expected statement" + VBSE_EXPECTED_END_OF_STATEMENT "Expected end of statement" + VBSE_EXPECTED_INTEGER_CONSTANT "Expected integer constant" + VBSE_EXPECTED_WHILE_UNTIL_EOS "Expected 'While', 'Until' or end of statement" + VBSE_INVALID_NUMBER "Invalid number" + VBSE_INVALID_CHAR "Invalid character" + VBSE_UNTERMINATED_STRING "Unterminated string constant" + VBSE_LOOP_WITHOUT_DO "'loop' without 'do'" + VBSE_INVALID_EXIT "Invalid 'exit' statement" + VBSE_NAME_REDEFINED "Name redefined" + VBSE_MUST_BE_FIRST_STATEMENT "Must be first statement on the line" + VBSE_CANNOT_USE_PARENS_CALLING_SUB "Cannot use parentheses when calling a Sub" + VBSE_EXPECTED_LITERAL_CONSTANT "Expected literal constant" + VBSE_EXPECTED_IN "Expected 'In'" + VBSE_EXPECTED_CLASS "Expected 'Class'" + VBSE_MUST_BE_INSIDE_CLASS "Must be defined inside a Class" + VBSE_EXPECTED_LET_SET_GET "Expected Let or Set or Get in property declaration" + VBSE_CLASS_INIT_NO_ARGS "Class initialize or terminate do not have arguments" + VBSE_PROPERTY_LET_SET_NEEDS_ARG "Property set or let must have at least one argument" + VBSE_UNEXPECTED_NEXT "Unexpected 'Next'" + VBSE_DEFAULT_MUST_BE_PUBLIC "'Default' specification must also specify 'Public'" VBS_COMPILE_ERROR "Microsoft VBScript compilation error" VBS_RUNTIME_ERROR "Microsoft VBScript runtime error" diff --git a/dlls/vbscript/vbscript_defs.h b/dlls/vbscript/vbscript_defs.h index e0e9d1cac94..06d3b8990fb 100644 --- a/dlls/vbscript/vbscript_defs.h +++ b/dlls/vbscript/vbscript_defs.h @@ -270,6 +270,38 @@ #define VBSE_INVALID_TYPELIB_VARIABLE 458 #define VBSE_SERVER_NOT_FOUND 462 #define VBSE_UNQUALIFIED_REFERENCE 505 +#define VBSE_SYNTAX_ERROR 1002 +#define VBSE_EXPECTED_LPAREN 1005 +#define VBSE_EXPECTED_IDENTIFIER 1010 +#define VBSE_EXPECTED_ASSIGN 1011 +#define VBSE_EXPECTED_TO 1013 +#define VBSE_EXPECTED_END 1014 +#define VBSE_EXPECTED_THEN 1017 +#define VBSE_EXPECTED_WEND 1018 +#define VBSE_EXPECTED_LOOP 1019 +#define VBSE_EXPECTED_NEXT 1020 +#define VBSE_EXPECTED_CASE 1021 +#define VBSE_EXPECTED_STATEMENT 1024 +#define VBSE_EXPECTED_END_OF_STATEMENT 1025 +#define VBSE_EXPECTED_INTEGER_CONSTANT 1026 +#define VBSE_EXPECTED_WHILE_UNTIL_EOS 1028 +#define VBSE_INVALID_NUMBER 1031 +#define VBSE_INVALID_CHAR 1032 +#define VBSE_UNTERMINATED_STRING 1033 +#define VBSE_LOOP_WITHOUT_DO 1038 +#define VBSE_INVALID_EXIT 1039 +#define VBSE_NAME_REDEFINED 1041 +#define VBSE_MUST_BE_FIRST_STATEMENT 1042 +#define VBSE_CANNOT_USE_PARENS_CALLING_SUB 1044 +#define VBSE_EXPECTED_LITERAL_CONSTANT 1045 +#define VBSE_EXPECTED_IN 1046 +#define VBSE_EXPECTED_CLASS 1047 +#define VBSE_MUST_BE_INSIDE_CLASS 1048 +#define VBSE_EXPECTED_LET_SET_GET 1049 +#define VBSE_CLASS_INIT_NO_ARGS 1053 +#define VBSE_PROPERTY_LET_SET_NEEDS_ARG 1054 +#define VBSE_UNEXPECTED_NEXT 1055 +#define VBSE_DEFAULT_MUST_BE_PUBLIC 1057 #define VBS_COMPILE_ERROR 4096 #define VBS_RUNTIME_ERROR 4097 -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10386
From: Francis De Brabandere <francisdb@gmail.com> Return MAKE_VBSERROR with proper error codes instead of E_FAIL for name redefinition and invalid exit statements in the compiler. --- dlls/vbscript/compile.c | 39 +++++++++++++-------------------------- dlls/vbscript/tests/run.c | 4 ++-- 2 files changed, 15 insertions(+), 28 deletions(-) diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c index a3fedc950a1..0a22d116642 100644 --- a/dlls/vbscript/compile.c +++ b/dlls/vbscript/compile.c @@ -1138,8 +1138,7 @@ static HRESULT compile_dim_statement(compile_ctx_t *ctx, dim_statement_t *stat) while(1) { if(lookup_dim_decls(ctx, dim_decl->name) || lookup_args_name(ctx, dim_decl->name) || lookup_const_decls(ctx, dim_decl->name, FALSE)) { - FIXME("dim %s name redefined\n", debugstr_w(dim_decl->name)); - return E_FAIL; + return MAKE_VBSERROR(VBSE_NAME_REDEFINED); } ctx->func->var_cnt++; @@ -1201,8 +1200,7 @@ static HRESULT compile_const_statement(compile_ctx_t *ctx, const_statement_t *st if(!lookup_const_decls(ctx, decl->name, FALSE)) { if(lookup_args_name(ctx, decl->name) || lookup_dim_decls(ctx, decl->name)) { - FIXME("%s redefined\n", debugstr_w(decl->name)); - return E_FAIL; + return MAKE_VBSERROR(VBSE_NAME_REDEFINED); } } @@ -1254,8 +1252,7 @@ static HRESULT compile_exitdo_statement(compile_ctx_t *ctx) break; } if(!iter) { - FIXME("Exit Do outside Do Loop\n"); - return E_FAIL; + return MAKE_VBSERROR(VBSE_INVALID_EXIT); } if(pop_cnt) { @@ -1280,8 +1277,7 @@ static HRESULT compile_exitfor_statement(compile_ctx_t *ctx) break; } if(!iter) { - FIXME("Exit For outside For loop\n"); - return E_FAIL; + return MAKE_VBSERROR(VBSE_INVALID_EXIT); } if(pop_cnt) { @@ -1313,8 +1309,7 @@ static HRESULT exit_label(compile_ctx_t *ctx, unsigned jmp_label) static HRESULT compile_exitsub_statement(compile_ctx_t *ctx) { if(!ctx->sub_end_label) { - FIXME("Exit Sub outside Sub?\n"); - return E_FAIL; + return MAKE_VBSERROR(VBSE_INVALID_EXIT); } return exit_label(ctx, ctx->sub_end_label); @@ -1323,8 +1318,7 @@ static HRESULT compile_exitsub_statement(compile_ctx_t *ctx) static HRESULT compile_exitfunc_statement(compile_ctx_t *ctx) { if(!ctx->func_end_label) { - FIXME("Exit Function outside Function?\n"); - return E_FAIL; + return MAKE_VBSERROR(VBSE_INVALID_EXIT); } return exit_label(ctx, ctx->func_end_label); @@ -1333,8 +1327,7 @@ static HRESULT compile_exitfunc_statement(compile_ctx_t *ctx) static HRESULT compile_exitprop_statement(compile_ctx_t *ctx) { if(!ctx->prop_end_label) { - FIXME("Exit Property outside Property?\n"); - return E_FAIL; + return MAKE_VBSERROR(VBSE_INVALID_EXIT); } return exit_label(ctx, ctx->prop_end_label); @@ -1377,8 +1370,7 @@ static HRESULT collect_const_decls(compile_ctx_t *ctx, statement_t *stat) break; /* already collected */ if(lookup_args_name(ctx, decl->name) || lookup_dim_decls(ctx, decl->name)) { - FIXME("%s redefined\n", debugstr_w(decl->name)); - return E_FAIL; + return MAKE_VBSERROR(VBSE_NAME_REDEFINED); } new_decl = compiler_alloc(ctx->code, sizeof(*new_decl)); @@ -1712,8 +1704,7 @@ static HRESULT create_function(compile_ctx_t *ctx, function_decl_t *decl, functi HRESULT hres; if(lookup_dim_decls(ctx, decl->name) || lookup_const_decls(ctx, decl->name, FALSE)) { - FIXME("%s: redefinition\n", debugstr_w(decl->name)); - return E_FAIL; + return MAKE_VBSERROR(VBSE_NAME_REDEFINED); } func = compiler_alloc(ctx->code, sizeof(*func)); @@ -1835,8 +1826,7 @@ static HRESULT compile_class(compile_ctx_t *ctx, class_decl_t *class_decl) if(lookup_dim_decls(ctx, class_decl->name) || lookup_funcs_name(ctx, class_decl->name) || lookup_const_decls(ctx, class_decl->name, FALSE) || lookup_class_name(ctx, class_decl->name)) { - FIXME("%s: redefinition\n", debugstr_w(class_decl->name)); - return E_FAIL; + return MAKE_VBSERROR(VBSE_NAME_REDEFINED); } class_desc = compiler_alloc_zero(ctx->code, sizeof(*class_desc)); @@ -1908,8 +1898,7 @@ static HRESULT compile_class(compile_ctx_t *ctx, class_decl_t *class_decl) for(prop_decl = class_decl->props, i=0; prop_decl; prop_decl = prop_decl->next, i++) { if(lookup_class_funcs(class_desc, prop_decl->name)) { - FIXME("Property %s redefined\n", debugstr_w(prop_decl->name)); - return E_FAIL; + return MAKE_VBSERROR(VBSE_NAME_REDEFINED); } class_desc->props[i].name = compiler_alloc_string(ctx->code, prop_decl->name); @@ -2006,15 +1995,13 @@ static HRESULT check_script_collisions(compile_ctx_t *ctx, script_ctx_t *script) for(i = 0; i < var_cnt; i++) { if(lookup_script_identifier(ctx, script, vars[i].name)) { - FIXME("%s: redefined\n", debugstr_w(vars[i].name)); - return E_FAIL; + return MAKE_VBSERROR(VBSE_NAME_REDEFINED); } } for(class = ctx->code->classes; class; class = class->next) { if(lookup_script_identifier(ctx, script, class->name)) { - FIXME("%s: redefined\n", debugstr_w(class->name)); - return E_FAIL; + return MAKE_VBSERROR(VBSE_NAME_REDEFINED); } } diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c index a641214b038..7f7d70c8ea0 100644 --- a/dlls/vbscript/tests/run.c +++ b/dlls/vbscript/tests/run.c @@ -2854,7 +2854,7 @@ static void test_parse_errors(void) { /* Name redefined - error 1041 */ L"Dim a\nDim a\n", - 1, -4, -1041 + 1, -4, 1041 }, { /* Expected identifier - error 1010 */ @@ -2929,7 +2929,7 @@ static void test_parse_errors(void) { /* Invalid 'exit' statement - error 1039 */ L"Exit Do\n", - 0, -5, -1039 + 0, -5, 1039 }, { /* Expected 'In' - error 1046 */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10386
From: Francis De Brabandere <francisdb@gmail.com> Add lex_error() helper that sets both the error code and position. Return MAKE_VBSERROR with proper error codes instead of FIXME/return 0 for unterminated strings, invalid numbers, and invalid characters. --- dlls/vbscript/lex.c | 24 +++++++++++++----------- dlls/vbscript/tests/run.c | 6 +++--- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/dlls/vbscript/lex.c b/dlls/vbscript/lex.c index 75838ac586a..7e571eaa31a 100644 --- a/dlls/vbscript/lex.c +++ b/dlls/vbscript/lex.c @@ -28,6 +28,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(vbscript); +static int lex_error(parser_ctx_t *ctx, HRESULT hres) +{ + ctx->hres = hres; + ctx->error_loc = ctx->ptr - ctx->code; + return 0; +} + static const struct { const WCHAR *word; int token; @@ -169,8 +176,7 @@ static int parse_string_literal(parser_ctx_t *ctx, const WCHAR **ret) while(ctx->ptr < ctx->end) { if(*ctx->ptr == '\n' || *ctx->ptr == '\r') { - FIXME("newline inside string literal\n"); - return 0; + return lex_error(ctx, MAKE_VBSERROR(VBSE_UNTERMINATED_STRING)); } if(*ctx->ptr == '"') { @@ -183,8 +189,7 @@ static int parse_string_literal(parser_ctx_t *ctx, const WCHAR **ret) } if(ctx->ptr == ctx->end) { - FIXME("unterminated string literal\n"); - return 0; + return lex_error(ctx, MAKE_VBSERROR(VBSE_UNTERMINATED_STRING)); } len += ctx->ptr-ptr; @@ -298,8 +303,7 @@ static int parse_numeric_literal(parser_ctx_t *ctx, void **ret) } if(!is_digit(*ctx->ptr)) { - FIXME("Invalid numeric literal\n"); - return 0; + return lex_error(ctx, MAKE_VBSERROR(VBSE_INVALID_NUMBER)); } use_int = FALSE; @@ -315,8 +319,7 @@ static int parse_numeric_literal(parser_ctx_t *ctx, void **ret) } if(sign*e + exp > INT_MAX/100) { - FIXME("Invalid numeric literal\n"); - return 0; + return lex_error(ctx, MAKE_VBSERROR(VBSE_INVALID_NUMBER)); } } while(is_digit(*ctx->ptr)); @@ -330,8 +333,7 @@ static int parse_numeric_literal(parser_ctx_t *ctx, void **ret) r = exp>=0 ? d*pow(10, exp) : d/pow(10, -exp); if(isinf(r)) { - FIXME("Invalid numeric literal\n"); - return 0; + return lex_error(ctx, MAKE_VBSERROR(VBSE_INVALID_NUMBER)); } *(double*)ret = r; @@ -510,7 +512,7 @@ static int parse_next_token(void *lval, unsigned *loc, parser_ctx_t *ctx) } return '>'; default: - FIXME("Unhandled char %c in %s\n", *ctx->ptr, debugstr_w(ctx->ptr)); + return lex_error(ctx, MAKE_VBSERROR(VBSE_INVALID_CHAR)); } return 0; diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c index 7f7d70c8ea0..97eede9c906 100644 --- a/dlls/vbscript/tests/run.c +++ b/dlls/vbscript/tests/run.c @@ -2844,7 +2844,7 @@ static void test_parse_errors(void) { /* Unterminated string constant - error 1033 */ L"x = \"hello\n", - 0, -10, -1033 + 0, 10, 1033 }, { /* Expected 'End' - error 1014 */ @@ -2864,7 +2864,7 @@ static void test_parse_errors(void) { /* Invalid character - error 1032 */ L"x = @invalid\n", - 0, 4, -1032 + 0, 4, 1032 }, { /* Expected literal constant - error 1045 */ @@ -2919,7 +2919,7 @@ static void test_parse_errors(void) { /* Invalid number - error 1031 */ L"x = 1e999\n", - 0, -9, -1031 + 0, 9, 1031 }, { /* 'loop' without 'do' - error 1038 */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10386
From: Francis De Brabandere <francisdb@gmail.com> Return MAKE_VBSERROR with proper error codes instead of E_FAIL for invalid parenthesized call statements, class function redefinition, and Default Private declarations. --- dlls/vbscript/parser.y | 10 ++++------ dlls/vbscript/tests/run.c | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y index 4977358b333..ecd6cc7502f 100644 --- a/dlls/vbscript/parser.y +++ b/dlls/vbscript/parser.y @@ -514,6 +514,7 @@ Storage_opt Storage : tPUBLIC tDEFAULT { $$ = STORAGE_IS_DEFAULT; } + | tDEFAULT tPRIVATE { ctx->error_loc = @1; ctx->hres = MAKE_VBSERROR(VBSE_DEFAULT_MUST_BE_PUBLIC); CHECK_ERROR; } | tPUBLIC { $$ = 0; } | tPRIVATE { $$ = STORAGE_IS_PRIVATE; } @@ -760,8 +761,7 @@ static call_expression_t *make_call_expression(parser_ctx_t *ctx, expression_t * } if(call_expr->args->next) { - FIXME("Invalid syntax: invalid use of parentheses for arguments\n"); - ctx->hres = E_FAIL; + ctx->hres = MAKE_VBSERROR(VBSE_CANNOT_USE_PARENS_CALLING_SUB); ctx->error_loc = ctx->ptr - ctx->code; return NULL; } @@ -1136,15 +1136,13 @@ static class_decl_t *add_class_function(parser_ctx_t *ctx, class_decl_t *class_d for(iter = class_decl->funcs; iter; iter = iter->next) { if(!wcsicmp(iter->name, decl->name)) { if(decl->type == FUNC_SUB || decl->type == FUNC_FUNCTION) { - FIXME("Redefinition of %s::%s\n", debugstr_w(class_decl->name), debugstr_w(decl->name)); - ctx->hres = E_FAIL; + ctx->hres = MAKE_VBSERROR(VBSE_NAME_REDEFINED); return NULL; } while(1) { if(iter->type == decl->type) { - FIXME("Redefinition of %s::%s\n", debugstr_w(class_decl->name), debugstr_w(decl->name)); - ctx->hres = E_FAIL; + ctx->hres = MAKE_VBSERROR(VBSE_NAME_REDEFINED); return NULL; } if(!iter->next_prop_func) diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c index 97eede9c906..027f94a3560 100644 --- a/dlls/vbscript/tests/run.c +++ b/dlls/vbscript/tests/run.c @@ -2791,7 +2791,7 @@ static void test_parse_errors(void) { /* invalid use of parentheses for call statement */ L"strcomp(\"x\", \"y\")", - 0, 17, -1044 + 0, 17, 1044 }, { L"\n\n\n cint _\n throwInt(&h80001234&)", @@ -2966,7 +2966,7 @@ static void test_parse_errors(void) { /* 'Default' must also specify 'Public' - error 1057 */ L"Class C\nDefault Private Function f()\nf = 1\nEnd Function\nEnd Class\n", - 1, 0, -1057 + 1, 0, 1057 } }; HRESULT hres; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10386
On Tue Mar 24 19:59:12 2026 +0000, Jacek Caban wrote:
The code looks fine, but please split it up a bit. I would suggest having the first commit add tests marked as todo_wine (as before), followed by separate commits for the compiler, lexer and parser fixes, each marking the appropriate tests as passing. Good like this?
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10386#note_133570
participants (2)
-
Francis De Brabandere -
Francis De Brabandere (@francisdb)