Jacek Caban : vbscript: Allow omitting optional function parameters in call expressions.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Jan 28 15:45:34 CST 2015


Module: wine
Branch: master
Commit: 3873c938911c1775acf909385c3d56827d1f1c83
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=3873c938911c1775acf909385c3d56827d1f1c83

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Wed Jan 28 19:28:17 2015 +0100

vbscript: Allow omitting optional function parameters in call expressions.

---

 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 <expression> NotExpression UnaryExpression AndExpression OrExpression XorExpression EqvExpression
 %type <expression> ConstExpression NumericLiteralExpression
 %type <member> MemberExpression
-%type <expression> Arguments_opt ArgumentList_opt Step_opt ExpressionList
+%type <expression> Arguments_opt ArgumentList ArgumentList_opt Step_opt ExpressionList
 %type <boolean> OptionExplicit_opt DoType
 %type <arg_decl> ArgumentsDecl_opt ArgumentDeclList ArgumentDecl
 %type <func_decl> 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)          \




More information about the wine-cvs mailing list