From: Jacek Caban Subject: vbscript: Allow omitting optional function parameters in call expressions. Message-Id: <54C92A41.3030102@codeweavers.com> Date: Wed, 28 Jan 2015 19:28:17 +0100 --- dlls/vbscript/compile.c | 2 ++ dlls/vbscript/interp.c | 12 ++++++++++++ dlls/vbscript/parse.h | 1 + dlls/vbscript/parser.y | 11 ++++++++--- dlls/vbscript/tests/run.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- dlls/vbscript/vbscript.h | 1 + 6 files changed, 68 insertions(+), 4 deletions(-) diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c index 73f0615..c8189d6 100644 --- a/dlls/vbscript/compile.c +++ b/dlls/vbscript/compile.c @@ -522,6 +522,8 @@ static HRESULT compile_expression(compile_ctx_t *ctx, expression_t *expr) return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_nequal); case EXPR_NEW: return push_instr_str(ctx, OP_new, ((string_expression_t*)expr)->value); + case EXPR_NOARG: + return push_instr_int(ctx, OP_hres, DISP_E_PARAMNOTFOUND); case EXPR_NOT: return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_not); case EXPR_NOTHING: diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c index 7c66096..4b45006 100644 --- a/dlls/vbscript/interp.c +++ b/dlls/vbscript/interp.c @@ -1366,6 +1366,18 @@ static HRESULT interp_nothing(exec_ctx_t *ctx) return stack_push(ctx, &v); } +static HRESULT interp_hres(exec_ctx_t *ctx) +{ + const unsigned arg = ctx->instr->arg1.uint; + VARIANT v; + + TRACE("%d\n", arg); + + V_VT(&v) = VT_ERROR; + V_ERROR(&v) = arg; + return stack_push(ctx, &v); +} + static HRESULT interp_not(exec_ctx_t *ctx) { variant_val_t val; diff --git a/dlls/vbscript/parse.h b/dlls/vbscript/parse.h index 2a49703..f0479b5 100644 --- a/dlls/vbscript/parse.h +++ b/dlls/vbscript/parse.h @@ -42,6 +42,7 @@ typedef enum { EXPR_NEG, EXPR_NEQUAL, EXPR_NEW, + EXPR_NOARG, /* not a real expression */ EXPR_NOT, EXPR_NOTHING, EXPR_NULL, diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y index fb95dfb..9606592 100644 --- a/dlls/vbscript/parser.y +++ b/dlls/vbscript/parser.y @@ -128,7 +128,7 @@ static const WCHAR propertyW[] = {'p','r','o','p','e','r','t','y',0}; %type NotExpression UnaryExpression AndExpression OrExpression XorExpression EqvExpression %type ConstExpression NumericLiteralExpression %type MemberExpression -%type Arguments_opt ArgumentList_opt Step_opt ExpressionList +%type Arguments_opt ArgumentList ArgumentList_opt Step_opt ExpressionList %type OptionExplicit_opt DoType %type ArgumentsDecl_opt ArgumentDeclList ArgumentDecl %type FunctionDecl PropertyDecl @@ -279,11 +279,16 @@ CaseClausules Arguments_opt : EmptyBrackets_opt { $$ = NULL; } - | '(' ExpressionList ')' { $$ = $2; } + | '(' ArgumentList ')' { $$ = $2; } ArgumentList_opt : EmptyBrackets_opt { $$ = NULL; } - | ExpressionList { $$ = $1; } + | ArgumentList { $$ = $1; } + +ArgumentList + : Expression { $$ = $1; } + | Expression ',' ArgumentList { $1->next = $3; $$ = $1; } + | ',' ArgumentList { $$ = new_expression(ctx, EXPR_NOARG, 0); CHECK_ERROR; $$->next = $2; } EmptyBrackets_opt : /* empty */ diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c index 33cf0cd..c916382 100644 --- a/dlls/vbscript/tests/run.c +++ b/dlls/vbscript/tests/run.c @@ -92,6 +92,7 @@ DEFINE_EXPECT(global_propargput_d); DEFINE_EXPECT(global_propargput_i); DEFINE_EXPECT(global_propargput1_d); DEFINE_EXPECT(global_propargput1_i); +DEFINE_EXPECT(global_testoptionalarg_i); DEFINE_EXPECT(collectionobj_newenum_i); DEFINE_EXPECT(Next); DEFINE_EXPECT(GetWindow); @@ -115,6 +116,7 @@ DEFINE_EXPECT(EnableModeless); #define DISPID_GLOBAL_DOUBLEASSTRING 1014 #define DISPID_GLOBAL_TESTARRAY 1015 #define DISPID_GLOBAL_THROWINT 1016 +#define DISPID_GLOBAL_TESTOPTIONALARG 1017 #define DISPID_TESTOBJ_PROPGET 2000 #define DISPID_TESTOBJ_PROPPUT 2001 @@ -1007,6 +1009,11 @@ static HRESULT WINAPI Global_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD *pid = DISPID_GLOBAL_THROWINT; return S_OK; } + if(!strcmp_wa(bstrName, "testOptionalArg")) { + test_grfdex(grfdex, fdexNameCaseInsensitive); + *pid = DISPID_GLOBAL_TESTOPTIONALARG; + return S_OK; + } if(strict_dispid_check && strcmp_wa(bstrName, "x")) ok(0, "unexpected call %s %x\n", wine_dbgstr_w(bstrName), grfdex); @@ -1044,7 +1051,7 @@ static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, return S_OK; } - case DISPID_GLOBAL_TRACE: + case DISPID_GLOBAL_TRACE: ok(wFlags == INVOKE_FUNC, "wFlags = %x\n", wFlags); ok(pdp != NULL, "pdp == NULL\n"); ok(pdp->rgvarg != NULL, "rgvarg == NULL\n"); @@ -1320,6 +1327,30 @@ static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, return hres; } + + case DISPID_GLOBAL_TESTOPTIONALARG: { + VARIANT *v; + int opt; + + CHECK_EXPECT(global_testoptionalarg_i); + + ok(wFlags == INVOKE_FUNC, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(pdp->rgvarg != NULL, "rgvarg == NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(pdp->cArgs == 3, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(!pvarRes, "pvarRes != NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + + ok(V_VT(pdp->rgvarg) == VT_I2, "V_VT(pdp->rgvarg) = %d\n", V_VT(pdp->rgvarg)); + opt = V_I2(pdp->rgvarg); + ok(opt == 1 || opt == 2, "opt = %d\n", opt); + v = pdp->rgvarg+pdp->cArgs-opt; + ok(V_VT(v) == VT_ERROR, "V_VT(v) = %d\n", V_VT(v)); + ok(V_ERROR(v) == DISP_E_PARAMNOTFOUND, "V_ERROR(v) = %08x\n", V_ERROR(v)); + return S_OK; + } } ok(0, "unexpected call %d\n", id); @@ -2075,6 +2106,18 @@ static void run_tests(void) hres = parse_script_ar("throwInt(&h80004001&)"); ok(hres == MAKE_VBSERROR(445), "hres = %08x\n", hres); + SET_EXPECT(global_testoptionalarg_i); + parse_script_a("call testOptionalArg(1,,2)"); + CHECK_CALLED(global_testoptionalarg_i); + + SET_EXPECT(global_testoptionalarg_i); + parse_script_a("call testOptionalArg(,1,1)"); + CHECK_CALLED(global_testoptionalarg_i); + + SET_EXPECT(global_testoptionalarg_i); + parse_script_a("testOptionalArg 1,,2"); + CHECK_CALLED(global_testoptionalarg_i); + strict_dispid_check = FALSE; SET_EXPECT(testobj_value_i); diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index d21e80a..d1f35be 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -234,6 +234,7 @@ typedef enum { X(empty, 1, 0, 0) \ X(enumnext, 0, ARG_ADDR, ARG_BSTR) \ X(equal, 1, 0, 0) \ + X(hres, 1, ARG_UINT, 0) \ X(errmode, 1, ARG_INT, 0) \ X(eqv, 1, 0, 0) \ X(exp, 1, 0, 0) \