Jacek Caban : vbscript: Added parameterized assign identifier statement support.

Alexandre Julliard julliard at winehq.org
Mon Mar 26 12:29:31 CDT 2012


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

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Mon Mar 26 11:53:41 2012 +0200

vbscript: Added parameterized assign identifier statement support.

---

 dlls/vbscript/interp.c   |  123 ++++++++++++++++++++++++++++++---------------
 dlls/vbscript/vbdisp.c   |    8 +--
 dlls/vbscript/vbscript.h |    2 +-
 3 files changed, 86 insertions(+), 47 deletions(-)

diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c
index 6e4827d..8cfec58 100644
--- a/dlls/vbscript/interp.c
+++ b/dlls/vbscript/interp.c
@@ -315,6 +315,35 @@ static HRESULT stack_pop_val(exec_ctx_t *ctx, variant_val_t *v)
     return S_OK;
 }
 
+static HRESULT stack_assume_val(exec_ctx_t *ctx, unsigned n)
+{
+    VARIANT *v = stack_top(ctx, n);
+    HRESULT hres;
+
+    if(V_VT(v) == (VT_BYREF|VT_VARIANT)) {
+        VARIANT *ref = V_VARIANTREF(v);
+
+        V_VT(v) = VT_EMPTY;
+        hres = VariantCopy(v, ref);
+        if(FAILED(hres))
+            return hres;
+    }
+
+    if(V_VT(v) == VT_DISPATCH) {
+        DISPPARAMS dp = {0};
+        IDispatch *disp;
+
+        disp = V_DISPATCH(v);
+        V_VT(v) = VT_EMPTY;
+        hres = disp_call(ctx->script, disp, DISPID_VALUE, &dp, v);
+        IDispatch_Release(disp);
+        if(FAILED(hres))
+            return hres;
+    }
+
+    return S_OK;
+}
+
 static inline void release_val(variant_val_t *v)
 {
     if(v->owned)
@@ -380,11 +409,13 @@ static inline void instr_jmp(exec_ctx_t *ctx, unsigned addr)
     ctx->instr = ctx->code->instrs + addr;
 }
 
-static void vbstack_to_dp(exec_ctx_t *ctx, unsigned arg_cnt, DISPPARAMS *dp)
+static void vbstack_to_dp(exec_ctx_t *ctx, unsigned arg_cnt, BOOL is_propput, DISPPARAMS *dp)
 {
-    dp->cArgs = arg_cnt;
-    dp->rgdispidNamedArgs = NULL;
-    dp->cNamedArgs = 0;
+    static DISPID propput_dispid = DISPID_PROPERTYPUT;
+
+    dp->cNamedArgs = is_propput ? 1 : 0;
+    dp->cArgs = arg_cnt + dp->cNamedArgs;
+    dp->rgdispidNamedArgs = is_propput ? &propput_dispid : NULL;
 
     if(arg_cnt) {
         VARIANT tmp;
@@ -398,9 +429,9 @@ static void vbstack_to_dp(exec_ctx_t *ctx, unsigned arg_cnt, DISPPARAMS *dp)
             ctx->stack[ctx->top-arg_cnt+i-1] = tmp;
         }
 
-        dp->rgvarg = ctx->stack + ctx->top-arg_cnt;
+        dp->rgvarg = ctx->stack + ctx->top-dp->cArgs;
     }else {
-        dp->rgvarg = NULL;
+        dp->rgvarg = is_propput ? ctx->stack+ctx->top-1 : NULL;
     }
 }
 
@@ -416,7 +447,7 @@ static HRESULT do_icall(exec_ctx_t *ctx, VARIANT *res)
     if(FAILED(hres))
         return hres;
 
-    vbstack_to_dp(ctx, arg_cnt, &dp);
+    vbstack_to_dp(ctx, arg_cnt, FALSE, &dp);
 
     switch(ref.type) {
     case REF_VAR:
@@ -503,7 +534,7 @@ static HRESULT do_mcall(exec_ctx_t *ctx, VARIANT *res)
         return E_FAIL;
     }
 
-    vbstack_to_dp(ctx, arg_cnt, &dp);
+    vbstack_to_dp(ctx, arg_cnt, FALSE, &dp);
 
     hres = disp_get_id(obj, identifier, VBDISP_CALLGET, FALSE, &id);
     if(SUCCEEDED(hres))
@@ -537,7 +568,7 @@ static HRESULT interp_mcallv(exec_ctx_t *ctx)
     return do_mcall(ctx, NULL);
 }
 
-static HRESULT assign_ident(exec_ctx_t *ctx, BSTR name, VARIANT *val, BOOL own_val)
+static HRESULT assign_ident(exec_ctx_t *ctx, BSTR name, DISPPARAMS *dp)
 {
     ref_t ref;
     HRESULT hres;
@@ -550,22 +581,19 @@ static HRESULT assign_ident(exec_ctx_t *ctx, BSTR name, VARIANT *val, BOOL own_v
     case REF_VAR: {
         VARIANT *v = ref.u.v;
 
+        if(arg_cnt(dp)) {
+            FIXME("arg_cnt %d not supported\n", arg_cnt(dp));
+            return E_NOTIMPL;
+        }
+
         if(V_VT(v) == (VT_VARIANT|VT_BYREF))
             v = V_VARIANTREF(v);
 
-        if(own_val) {
-            VariantClear(v);
-            *v = *val;
-            hres = S_OK;
-        }else {
-            hres = VariantCopy(v, val);
-        }
+        hres = VariantCopy(v, dp->rgvarg);
         break;
     }
     case REF_DISP:
-        hres = disp_propput(ctx->script, ref.u.d.disp, ref.u.d.id, val);
-        if(own_val)
-            VariantClear(val);
+        hres = disp_propput(ctx->script, ref.u.d.disp, ref.u.d.id, dp);
         break;
     case REF_FUNC:
         FIXME("functions not implemented\n");
@@ -581,8 +609,13 @@ static HRESULT assign_ident(exec_ctx_t *ctx, BSTR name, VARIANT *val, BOOL own_v
             FIXME("throw exception\n");
             hres = E_FAIL;
         }else {
+            if(arg_cnt(dp)) {
+                FIXME("arg_cnt %d not supported\n", arg_cnt(dp));
+                return E_NOTIMPL;
+            }
+
             TRACE("creating variable %s\n", debugstr_w(name));
-            hres = add_dynamic_var(ctx, name, FALSE, val, own_val);
+            hres = add_dynamic_var(ctx, name, FALSE, dp->rgvarg, FALSE);
         }
     }
 
@@ -593,29 +626,29 @@ static HRESULT interp_assign_ident(exec_ctx_t *ctx)
 {
     const BSTR arg = ctx->instr->arg1.bstr;
     const unsigned arg_cnt = ctx->instr->arg2.uint;
-    variant_val_t v;
+    DISPPARAMS dp;
     HRESULT hres;
 
     TRACE("%s\n", debugstr_w(arg));
 
-    if(arg_cnt) {
-        FIXME("arguments not supported\n");
-        return E_NOTIMPL;
-    }
+    hres = stack_assume_val(ctx, arg_cnt);
+    if(FAILED(hres))
+        return hres;
 
-    hres = stack_pop_val(ctx, &v);
+    vbstack_to_dp(ctx, arg_cnt, TRUE, &dp);
+    hres = assign_ident(ctx, arg, &dp);
     if(FAILED(hres))
         return hres;
 
-    return assign_ident(ctx, arg, v.v, v.owned);
+    stack_popn(ctx, arg_cnt+1);
+    return S_OK;
 }
 
 static HRESULT interp_set_ident(exec_ctx_t *ctx)
 {
     const BSTR arg = ctx->instr->arg1.bstr;
     const unsigned arg_cnt = ctx->instr->arg2.uint;
-    IDispatch *disp;
-    VARIANT v;
+    DISPPARAMS dp;
     HRESULT hres;
 
     TRACE("%s\n", debugstr_w(arg));
@@ -625,21 +658,25 @@ static HRESULT interp_set_ident(exec_ctx_t *ctx)
         return E_NOTIMPL;
     }
 
-    hres = stack_pop_disp(ctx, &disp);
+    hres = stack_assume_disp(ctx, 0, NULL);
     if(FAILED(hres))
         return hres;
 
-    V_VT(&v) = VT_DISPATCH;
-    V_DISPATCH(&v) = disp;
-    return assign_ident(ctx, ctx->instr->arg1.bstr, &v, TRUE);
+    vbstack_to_dp(ctx, 0, TRUE, &dp);
+    hres = assign_ident(ctx, ctx->instr->arg1.bstr, &dp);
+    if(FAILED(hres))
+        return hres;
+
+    stack_popn(ctx, 1);
+    return S_OK;
 }
 
 static HRESULT interp_assign_member(exec_ctx_t *ctx)
 {
     BSTR identifier = ctx->instr->arg1.bstr;
     const unsigned arg_cnt = ctx->instr->arg2.uint;
-    variant_val_t val;
     IDispatch *obj;
+    DISPPARAMS dp;
     DISPID id;
     HRESULT hres;
 
@@ -659,18 +696,19 @@ static HRESULT interp_assign_member(exec_ctx_t *ctx)
         return E_FAIL;
     }
 
-    hres = stack_pop_val(ctx, &val);
+    hres = stack_assume_val(ctx, arg_cnt);
     if(FAILED(hres))
         return hres;
 
     hres = disp_get_id(obj, identifier, VBDISP_LET, FALSE, &id);
-    if(SUCCEEDED(hres))
-        hres = disp_propput(ctx->script, obj, id, val.v);
-    release_val(&val);
+    if(SUCCEEDED(hres)) {
+        vbstack_to_dp(ctx, arg_cnt, TRUE, &dp);
+        hres = disp_propput(ctx->script, obj, id, &dp);
+    }
     if(FAILED(hres))
         return hres;
 
-    stack_popn(ctx, 1);
+    stack_popn(ctx, 2);
     return S_OK;
 }
 
@@ -679,6 +717,7 @@ static HRESULT interp_set_member(exec_ctx_t *ctx)
     BSTR identifier = ctx->instr->arg1.bstr;
     const unsigned arg_cnt = ctx->instr->arg2.uint;
     IDispatch *obj;
+    DISPPARAMS dp;
     DISPID id;
     HRESULT hres;
 
@@ -703,8 +742,10 @@ static HRESULT interp_set_member(exec_ctx_t *ctx)
         return hres;
 
     hres = disp_get_id(obj, identifier, VBDISP_SET, FALSE, &id);
-    if(SUCCEEDED(hres))
-        hres = disp_propput(ctx->script, obj, id, stack_top(ctx, 0));
+    if(SUCCEEDED(hres)) {
+        vbstack_to_dp(ctx, arg_cnt, TRUE, &dp);
+        hres = disp_propput(ctx->script, obj, id, &dp);
+    }
     if(FAILED(hres))
         return hres;
 
diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c
index ab62c9f..1e9245a 100644
--- a/dlls/vbscript/vbdisp.c
+++ b/dlls/vbscript/vbdisp.c
@@ -576,23 +576,21 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, DISPPARAMS *dp,
     return hres;
 }
 
-HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, VARIANT *val)
+HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, DISPPARAMS *dp)
 {
-    DISPID propput_dispid = DISPID_PROPERTYPUT;
-    DISPPARAMS dp  = {val, &propput_dispid, 1, 1};
     IDispatchEx *dispex;
     EXCEPINFO ei = {0};
     HRESULT hres;
 
     hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
     if(SUCCEEDED(hres)) {
-        hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, DISPATCH_PROPERTYPUT, &dp, NULL, &ei, NULL /* FIXME! */);
+        hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, DISPATCH_PROPERTYPUT, dp, NULL, &ei, NULL /* FIXME! */);
         IDispatchEx_Release(dispex);
     }else {
         ULONG err = 0;
 
         TRACE("using IDispatch\n");
-        hres = IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, DISPATCH_PROPERTYPUT, &dp, NULL, &ei, &err);
+        hres = IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, DISPATCH_PROPERTYPUT, dp, NULL, &ei, &err);
     }
 
     return hres;
diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h
index 173b03e..432380d 100644
--- a/dlls/vbscript/vbscript.h
+++ b/dlls/vbscript/vbscript.h
@@ -119,7 +119,7 @@ HRESULT create_vbdisp(const class_desc_t*,vbdisp_t**) DECLSPEC_HIDDEN;
 HRESULT disp_get_id(IDispatch*,BSTR,vbdisp_invoke_type_t,BOOL,DISPID*) DECLSPEC_HIDDEN;
 HRESULT vbdisp_get_id(vbdisp_t*,BSTR,vbdisp_invoke_type_t,BOOL,DISPID*) DECLSPEC_HIDDEN;
 HRESULT disp_call(script_ctx_t*,IDispatch*,DISPID,DISPPARAMS*,VARIANT*) DECLSPEC_HIDDEN;
-HRESULT disp_propput(script_ctx_t*,IDispatch*,DISPID,VARIANT*) DECLSPEC_HIDDEN;
+HRESULT disp_propput(script_ctx_t*,IDispatch*,DISPID,DISPPARAMS*) DECLSPEC_HIDDEN;
 void collect_objects(script_ctx_t*) DECLSPEC_HIDDEN;
 
 static inline unsigned arg_cnt(const DISPPARAMS *dp)




More information about the wine-cvs mailing list