2 * Copyright 2011 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(vbscript
);
45 typedef HRESULT (*instr_func_t
)(exec_ctx_t
*);
72 static BOOL
lookup_dynamic_vars(dynamic_var_t
*var
, const WCHAR
*name
, ref_t
*ref
)
75 if(!strcmpiW(var
->name
, name
)) {
87 static HRESULT
lookup_identifier(exec_ctx_t
*ctx
, BSTR name
, vbdisp_invoke_type_t invoke_type
, ref_t
*ref
)
95 if(invoke_type
== VBDISP_LET
96 && (ctx
->func
->type
== FUNC_FUNCTION
|| ctx
->func
->type
== FUNC_PROPGET
|| ctx
->func
->type
== FUNC_DEFGET
)
97 && !strcmpiW(name
, ctx
->func
->name
)) {
99 ref
->u
.v
= &ctx
->ret_val
;
103 for(i
=0; i
< ctx
->func
->var_cnt
; i
++) {
104 if(!strcmpiW(ctx
->func
->vars
[i
].name
, name
)) {
106 ref
->u
.v
= ctx
->vars
+i
;
111 for(i
=0; i
< ctx
->func
->arg_cnt
; i
++) {
112 if(!strcmpiW(ctx
->func
->args
[i
].name
, name
)) {
114 ref
->u
.v
= ctx
->args
+i
;
119 hres
= disp_get_id(ctx
->this_obj
, name
, invoke_type
, TRUE
, &id
);
120 if(SUCCEEDED(hres
)) {
121 ref
->type
= REF_DISP
;
122 ref
->u
.d
.disp
= ctx
->this_obj
;
127 if(lookup_dynamic_vars(ctx
->script
->global_vars
, name
, ref
))
130 for(func
= ctx
->script
->global_funcs
; func
; func
= func
->next
) {
131 if(!strcmpiW(func
->name
, name
)) {
132 ref
->type
= REF_FUNC
;
138 LIST_FOR_EACH_ENTRY(item
, &ctx
->script
->named_items
, named_item_t
, entry
) {
139 if((item
->flags
& SCRIPTITEM_GLOBALMEMBERS
) && item
->disp
!= ctx
->this_obj
) {
140 hres
= disp_get_id(item
->disp
, name
, invoke_type
, FALSE
, &id
);
141 if(SUCCEEDED(hres
)) {
142 ref
->type
= REF_DISP
;
143 ref
->u
.d
.disp
= item
->disp
;
150 hres
= vbdisp_get_id(ctx
->script
->global_obj
, name
, invoke_type
, TRUE
, &id
);
151 if(SUCCEEDED(hres
)) {
152 ref
->type
= REF_DISP
;
153 ref
->u
.d
.disp
= (IDispatch
*)&ctx
->script
->global_obj
->IDispatchEx_iface
;
158 if(!ctx
->func
->code_ctx
->option_explicit
)
159 FIXME("create an attempt to set\n");
161 ref
->type
= REF_NONE
;
165 static inline VARIANT
*stack_pop(exec_ctx_t
*ctx
)
168 return ctx
->stack
+ --ctx
->top
;
171 static HRESULT
stack_push(exec_ctx_t
*ctx
, VARIANT
*v
)
173 if(ctx
->stack_size
== ctx
->top
) {
176 new_stack
= heap_realloc(ctx
->stack
, ctx
->stack_size
*2);
179 return E_OUTOFMEMORY
;
182 ctx
->stack
= new_stack
;
183 ctx
->stack_size
*= 2;
186 ctx
->stack
[ctx
->top
++] = *v
;
190 static void stack_popn(exec_ctx_t
*ctx
, unsigned n
)
193 VariantClear(stack_pop(ctx
));
196 static HRESULT
stack_pop_val(exec_ctx_t
*ctx
, variant_val_t
*v
)
200 var
= stack_pop(ctx
);
202 if(V_VT(var
) == (VT_BYREF
|VT_VARIANT
)) {
204 var
= V_VARIANTREF(var
);
209 if(V_VT(var
) == VT_DISPATCH
) {
213 hres
= disp_call(ctx
->script
, V_DISPATCH(var
), DISPID_VALUE
, &dp
, &v
->store
);
215 IDispatch_Release(V_DISPATCH(var
));
228 static inline void release_val(variant_val_t
*v
)
234 static HRESULT
stack_pop_disp(exec_ctx_t
*ctx
, IDispatch
**ret
)
236 VARIANT
*v
= stack_pop(ctx
);
238 if(V_VT(v
) == VT_DISPATCH
) {
239 *ret
= V_DISPATCH(v
);
243 if(V_VT(v
) != (VT_VARIANT
|VT_BYREF
)) {
244 FIXME("not supported type: %s\n", debugstr_variant(v
));
250 if(V_VT(v
) != VT_DISPATCH
) {
251 FIXME("not disp %s\n", debugstr_variant(v
));
256 IDispatch_AddRef(V_DISPATCH(v
));
257 *ret
= V_DISPATCH(v
);
261 static inline void instr_jmp(exec_ctx_t
*ctx
, unsigned addr
)
263 ctx
->instr
= ctx
->code
->instrs
+ addr
;
266 static void vbstack_to_dp(exec_ctx_t
*ctx
, unsigned arg_cnt
, DISPPARAMS
*dp
)
269 dp
->rgdispidNamedArgs
= NULL
;
276 assert(ctx
->top
>= arg_cnt
);
278 for(i
=1; i
*2 <= arg_cnt
; i
++) {
279 tmp
= ctx
->stack
[ctx
->top
-i
];
280 ctx
->stack
[ctx
->top
-i
] = ctx
->stack
[ctx
->top
-arg_cnt
+i
-1];
281 ctx
->stack
[ctx
->top
-arg_cnt
+i
-1] = tmp
;
284 dp
->rgvarg
= ctx
->stack
+ ctx
->top
-arg_cnt
;
290 static HRESULT
do_icall(exec_ctx_t
*ctx
, VARIANT
*res
)
292 BSTR identifier
= ctx
->instr
->arg1
.bstr
;
293 const unsigned arg_cnt
= ctx
->instr
->arg2
.uint
;
298 hres
= lookup_identifier(ctx
, identifier
, VBDISP_CALLGET
, &ref
);
302 vbstack_to_dp(ctx
, arg_cnt
, &dp
);
307 FIXME("REF_VAR no res\n");
312 FIXME("arguments not implemented\n");
316 V_VT(res
) = VT_BYREF
|VT_VARIANT
;
317 V_BYREF(res
) = V_VT(ref
.u
.v
) == (VT_VARIANT
|VT_BYREF
) ? V_VARIANTREF(ref
.u
.v
) : ref
.u
.v
;
320 hres
= disp_call(ctx
->script
, ref
.u
.d
.disp
, ref
.u
.d
.id
, &dp
, res
);
325 hres
= exec_script(ctx
->script
, ref
.u
.f
, NULL
, &dp
, res
);
330 FIXME("%s not found\n", debugstr_w(identifier
));
331 return DISP_E_UNKNOWNNAME
;
334 stack_popn(ctx
, arg_cnt
);
338 static HRESULT
interp_icall(exec_ctx_t
*ctx
)
345 hres
= do_icall(ctx
, &v
);
349 return stack_push(ctx
, &v
);
352 static HRESULT
interp_icallv(exec_ctx_t
*ctx
)
355 return do_icall(ctx
, NULL
);
358 static HRESULT
do_mcall(exec_ctx_t
*ctx
, VARIANT
*res
)
360 const BSTR identifier
= ctx
->instr
->arg1
.bstr
;
361 const unsigned arg_cnt
= ctx
->instr
->arg2
.uint
;
367 hres
= stack_pop_disp(ctx
, &obj
);
376 vbstack_to_dp(ctx
, arg_cnt
, &dp
);
378 hres
= disp_get_id(obj
, identifier
, VBDISP_CALLGET
, FALSE
, &id
);
380 hres
= disp_call(ctx
->script
, obj
, id
, &dp
, res
);
381 IDispatch_Release(obj
);
385 stack_popn(ctx
, arg_cnt
);
389 static HRESULT
interp_mcall(exec_ctx_t
*ctx
)
396 hres
= do_mcall(ctx
, &res
);
400 return stack_push(ctx
, &res
);
403 static HRESULT
interp_mcallv(exec_ctx_t
*ctx
)
407 return do_mcall(ctx
, NULL
);
410 static HRESULT
assign_ident(exec_ctx_t
*ctx
, BSTR name
, VARIANT
*val
, BOOL own_val
)
415 hres
= lookup_identifier(ctx
, name
, VBDISP_LET
, &ref
);
421 VARIANT
*v
= ref
.u
.v
;
423 if(V_VT(v
) == (VT_VARIANT
|VT_BYREF
))
431 hres
= VariantCopy(v
, val
);
436 hres
= disp_propput(ctx
->script
, ref
.u
.d
.disp
, ref
.u
.d
.id
, val
);
441 FIXME("functions not implemented\n");
444 FIXME("%s not found\n", debugstr_w(name
));
447 return DISP_E_UNKNOWNNAME
;
453 static HRESULT
interp_assign_ident(exec_ctx_t
*ctx
)
455 const BSTR arg
= ctx
->instr
->arg1
.bstr
;
459 TRACE("%s\n", debugstr_w(arg
));
461 hres
= stack_pop_val(ctx
, &v
);
465 return assign_ident(ctx
, arg
, v
.v
, v
.owned
);
468 static HRESULT
interp_set_ident(exec_ctx_t
*ctx
)
470 const BSTR arg
= ctx
->instr
->arg1
.bstr
;
475 TRACE("%s\n", debugstr_w(arg
));
477 hres
= stack_pop_disp(ctx
, &disp
);
481 V_VT(&v
) = VT_DISPATCH
;
482 V_DISPATCH(&v
) = disp
;
483 return assign_ident(ctx
, ctx
->instr
->arg1
.bstr
, &v
, TRUE
);
486 static HRESULT
interp_assign_member(exec_ctx_t
*ctx
)
488 BSTR identifier
= ctx
->instr
->arg1
.bstr
;
494 TRACE("%s\n", debugstr_w(identifier
));
496 hres
= stack_pop_disp(ctx
, &obj
);
505 hres
= stack_pop_val(ctx
, &val
);
507 IDispatch_Release(obj
);
511 hres
= disp_get_id(obj
, identifier
, VBDISP_LET
, FALSE
, &id
);
513 hres
= disp_propput(ctx
->script
, obj
, id
, val
.v
);
516 IDispatch_Release(obj
);
520 static HRESULT
interp_set_member(exec_ctx_t
*ctx
)
522 BSTR identifier
= ctx
->instr
->arg1
.bstr
;
523 IDispatch
*obj
, *val
;
527 TRACE("%s\n", debugstr_w(identifier
));
529 hres
= stack_pop_disp(ctx
, &obj
);
538 hres
= stack_pop_disp(ctx
, &val
);
540 IDispatch_Release(obj
);
544 hres
= disp_get_id(obj
, identifier
, VBDISP_SET
, FALSE
, &id
);
545 if(SUCCEEDED(hres
)) {
548 V_VT(&v
) = VT_DISPATCH
;
549 V_DISPATCH(&v
) = val
;
550 hres
= disp_propput(ctx
->script
, obj
, id
, &v
);
554 IDispatch_Release(val
);
555 IDispatch_Release(obj
);
559 static HRESULT
interp_new(exec_ctx_t
*ctx
)
561 const WCHAR
*arg
= ctx
->instr
->arg1
.bstr
;
562 class_desc_t
*class_desc
;
567 TRACE("%s\n", debugstr_w(arg
));
569 for(class_desc
= ctx
->script
->classes
; class_desc
; class_desc
= class_desc
->next
) {
570 if(!strcmpiW(class_desc
->name
, arg
))
574 FIXME("Class %s not found\n", debugstr_w(arg
));
578 hres
= create_vbdisp(class_desc
, &obj
);
582 V_VT(&v
) = VT_DISPATCH
;
583 V_DISPATCH(&v
) = (IDispatch
*)&obj
->IDispatchEx_iface
;
584 return stack_push(ctx
, &v
);
587 static HRESULT
interp_jmp(exec_ctx_t
*ctx
)
589 const unsigned arg
= ctx
->instr
->arg1
.uint
;
597 static HRESULT
interp_jmp_false(exec_ctx_t
*ctx
)
599 const unsigned arg
= ctx
->instr
->arg1
.uint
;
605 hres
= stack_pop_val(ctx
, &val
);
609 if(V_VT(val
.v
) != VT_BOOL
) {
610 FIXME("unsupported for %s\n", debugstr_variant(val
.v
));
618 instr_jmp(ctx
, ctx
->instr
->arg1
.uint
);
622 static HRESULT
interp_jmp_true(exec_ctx_t
*ctx
)
624 const unsigned arg
= ctx
->instr
->arg1
.uint
;
630 hres
= stack_pop_val(ctx
, &val
);
634 if(V_VT(val
.v
) != VT_BOOL
) {
635 FIXME("unsupported for %s\n", debugstr_variant(val
.v
));
641 instr_jmp(ctx
, ctx
->instr
->arg1
.uint
);
647 static HRESULT
interp_ret(exec_ctx_t
*ctx
)
655 static HRESULT
interp_stop(exec_ctx_t
*ctx
)
659 /* NOTE: this should have effect in debugging mode (that we don't support yet) */
663 static HRESULT
interp_bool(exec_ctx_t
*ctx
)
665 const VARIANT_BOOL arg
= ctx
->instr
->arg1
.lng
;
668 TRACE("%s\n", arg
? "true" : "false");
672 return stack_push(ctx
, &v
);
675 static HRESULT
interp_string(exec_ctx_t
*ctx
)
682 V_BSTR(&v
) = SysAllocString(ctx
->instr
->arg1
.str
);
684 return E_OUTOFMEMORY
;
686 return stack_push(ctx
, &v
);
689 static HRESULT
interp_long(exec_ctx_t
*ctx
)
691 const LONG arg
= ctx
->instr
->arg1
.lng
;
698 return stack_push(ctx
, &v
);
701 static HRESULT
interp_short(exec_ctx_t
*ctx
)
703 const LONG arg
= ctx
->instr
->arg1
.lng
;
710 return stack_push(ctx
, &v
);
713 static HRESULT
interp_double(exec_ctx_t
*ctx
)
715 const DOUBLE
*arg
= ctx
->instr
->arg1
.dbl
;
718 TRACE("%lf\n", *arg
);
722 return stack_push(ctx
, &v
);
725 static HRESULT
interp_empty(exec_ctx_t
*ctx
)
732 return stack_push(ctx
, &v
);
735 static HRESULT
interp_null(exec_ctx_t
*ctx
)
742 return stack_push(ctx
, &v
);
745 static HRESULT
interp_nothing(exec_ctx_t
*ctx
)
751 V_VT(&v
) = VT_DISPATCH
;
752 V_DISPATCH(&v
) = NULL
;
753 return stack_push(ctx
, &v
);
756 static HRESULT
interp_not(exec_ctx_t
*ctx
)
764 hres
= stack_pop_val(ctx
, &val
);
768 hres
= VarNot(val
.v
, &v
);
773 return stack_push(ctx
, &v
);
776 static HRESULT
interp_and(exec_ctx_t
*ctx
)
784 hres
= stack_pop_val(ctx
, &r
);
788 hres
= stack_pop_val(ctx
, &l
);
789 if(SUCCEEDED(hres
)) {
790 hres
= VarAnd(l
.v
, r
.v
, &v
);
797 return stack_push(ctx
, &v
);
800 static HRESULT
interp_or(exec_ctx_t
*ctx
)
808 hres
= stack_pop_val(ctx
, &r
);
812 hres
= stack_pop_val(ctx
, &l
);
813 if(SUCCEEDED(hres
)) {
814 hres
= VarOr(l
.v
, r
.v
, &v
);
821 return stack_push(ctx
, &v
);
824 static HRESULT
interp_xor(exec_ctx_t
*ctx
)
832 hres
= stack_pop_val(ctx
, &r
);
836 hres
= stack_pop_val(ctx
, &l
);
837 if(SUCCEEDED(hres
)) {
838 hres
= VarXor(l
.v
, r
.v
, &v
);
845 return stack_push(ctx
, &v
);
848 static HRESULT
interp_eqv(exec_ctx_t
*ctx
)
856 hres
= stack_pop_val(ctx
, &r
);
860 hres
= stack_pop_val(ctx
, &l
);
861 if(SUCCEEDED(hres
)) {
862 hres
= VarEqv(l
.v
, r
.v
, &v
);
869 return stack_push(ctx
, &v
);
872 static HRESULT
interp_imp(exec_ctx_t
*ctx
)
880 hres
= stack_pop_val(ctx
, &r
);
884 hres
= stack_pop_val(ctx
, &l
);
885 if(SUCCEEDED(hres
)) {
886 hres
= VarImp(l
.v
, r
.v
, &v
);
893 return stack_push(ctx
, &v
);
896 static HRESULT
cmp_oper(exec_ctx_t
*ctx
)
901 hres
= stack_pop_val(ctx
, &r
);
905 hres
= stack_pop_val(ctx
, &l
);
906 if(SUCCEEDED(hres
)) {
907 if(V_VT(l
.v
) == VT_NULL
|| V_VT(r
.v
) == VT_NULL
) {
908 FIXME("comparing nulls is not implemented\n");
911 hres
= VarCmp(l
.v
, r
.v
, ctx
->script
->lcid
, 0);
920 static HRESULT
interp_equal(exec_ctx_t
*ctx
)
927 hres
= cmp_oper(ctx
);
932 V_BOOL(&v
) = hres
== VARCMP_EQ
? VARIANT_TRUE
: VARIANT_FALSE
;
933 return stack_push(ctx
, &v
);
936 static HRESULT
interp_nequal(exec_ctx_t
*ctx
)
943 hres
= cmp_oper(ctx
);
948 V_BOOL(&v
) = hres
!= VARCMP_EQ
? VARIANT_TRUE
: VARIANT_FALSE
;
949 return stack_push(ctx
, &v
);
952 static HRESULT
interp_gt(exec_ctx_t
*ctx
)
959 hres
= cmp_oper(ctx
);
964 V_BOOL(&v
) = hres
== VARCMP_GT
? VARIANT_TRUE
: VARIANT_FALSE
;
965 return stack_push(ctx
, &v
);
968 static HRESULT
interp_gteq(exec_ctx_t
*ctx
)
975 hres
= cmp_oper(ctx
);
980 V_BOOL(&v
) = hres
== VARCMP_GT
|| hres
== VARCMP_EQ
? VARIANT_TRUE
: VARIANT_FALSE
;
981 return stack_push(ctx
, &v
);
984 static HRESULT
interp_lt(exec_ctx_t
*ctx
)
991 hres
= cmp_oper(ctx
);
996 V_BOOL(&v
) = hres
== VARCMP_LT
? VARIANT_TRUE
: VARIANT_FALSE
;
997 return stack_push(ctx
, &v
);
1000 static HRESULT
interp_lteq(exec_ctx_t
*ctx
)
1007 hres
= cmp_oper(ctx
);
1012 V_BOOL(&v
) = hres
== VARCMP_LT
|| hres
== VARCMP_EQ
? VARIANT_TRUE
: VARIANT_FALSE
;
1013 return stack_push(ctx
, &v
);
1016 static HRESULT
disp_cmp(IDispatch
*disp1
, IDispatch
*disp2
, VARIANT_BOOL
*ret
)
1018 IObjectIdentity
*identity
;
1019 IUnknown
*unk1
, *unk2
;
1022 if(disp1
== disp2
) {
1023 *ret
= VARIANT_TRUE
;
1027 if(!disp1
|| !disp2
) {
1028 *ret
= VARIANT_FALSE
;
1032 hres
= IDispatch_QueryInterface(disp1
, &IID_IUnknown
, (void**)&unk1
);
1036 hres
= IDispatch_QueryInterface(disp2
, &IID_IUnknown
, (void**)&unk2
);
1038 IUnknown_Release(unk1
);
1043 *ret
= VARIANT_TRUE
;
1045 hres
= IUnknown_QueryInterface(unk1
, &IID_IObjectIdentity
, (void**)&identity
);
1046 if(SUCCEEDED(hres
)) {
1047 hres
= IObjectIdentity_IsEqualObject(identity
, unk2
);
1048 IObjectIdentity_Release(identity
);
1049 *ret
= hres
== S_OK
? VARIANT_TRUE
: VARIANT_FALSE
;
1051 *ret
= VARIANT_FALSE
;
1055 IUnknown_Release(unk1
);
1056 IUnknown_Release(unk2
);
1060 static HRESULT
interp_is(exec_ctx_t
*ctx
)
1068 hres
= stack_pop_disp(ctx
, &r
);
1072 hres
= stack_pop_disp(ctx
, &l
);
1073 if(SUCCEEDED(hres
)) {
1075 hres
= disp_cmp(l
, r
, &V_BOOL(&v
));
1077 IDispatch_Release(l
);
1080 IDispatch_Release(r
);
1084 return stack_push(ctx
, &v
);
1087 static HRESULT
interp_concat(exec_ctx_t
*ctx
)
1095 hres
= stack_pop_val(ctx
, &r
);
1099 hres
= stack_pop_val(ctx
, &l
);
1100 if(SUCCEEDED(hres
)) {
1101 hres
= VarCat(l
.v
, r
.v
, &v
);
1108 return stack_push(ctx
, &v
);
1111 static HRESULT
interp_add(exec_ctx_t
*ctx
)
1119 hres
= stack_pop_val(ctx
, &r
);
1123 hres
= stack_pop_val(ctx
, &l
);
1124 if(SUCCEEDED(hres
)) {
1125 hres
= VarAdd(l
.v
, r
.v
, &v
);
1132 return stack_push(ctx
, &v
);
1135 static HRESULT
interp_sub(exec_ctx_t
*ctx
)
1143 hres
= stack_pop_val(ctx
, &r
);
1147 hres
= stack_pop_val(ctx
, &l
);
1148 if(SUCCEEDED(hres
)) {
1149 hres
= VarSub(l
.v
, r
.v
, &v
);
1156 return stack_push(ctx
, &v
);
1159 static HRESULT
interp_mod(exec_ctx_t
*ctx
)
1167 hres
= stack_pop_val(ctx
, &r
);
1171 hres
= stack_pop_val(ctx
, &l
);
1172 if(SUCCEEDED(hres
)) {
1173 hres
= VarMod(l
.v
, r
.v
, &v
);
1180 return stack_push(ctx
, &v
);
1183 static HRESULT
interp_idiv(exec_ctx_t
*ctx
)
1191 hres
= stack_pop_val(ctx
, &r
);
1195 hres
= stack_pop_val(ctx
, &l
);
1196 if(SUCCEEDED(hres
)) {
1197 hres
= VarIdiv(l
.v
, r
.v
, &v
);
1204 return stack_push(ctx
, &v
);
1207 static HRESULT
interp_div(exec_ctx_t
*ctx
)
1215 hres
= stack_pop_val(ctx
, &r
);
1219 hres
= stack_pop_val(ctx
, &l
);
1220 if(SUCCEEDED(hres
)) {
1221 hres
= VarDiv(l
.v
, r
.v
, &v
);
1228 return stack_push(ctx
, &v
);
1231 static HRESULT
interp_mul(exec_ctx_t
*ctx
)
1239 hres
= stack_pop_val(ctx
, &r
);
1243 hres
= stack_pop_val(ctx
, &l
);
1244 if(SUCCEEDED(hres
)) {
1245 hres
= VarMul(l
.v
, r
.v
, &v
);
1252 return stack_push(ctx
, &v
);
1255 static HRESULT
interp_exp(exec_ctx_t
*ctx
)
1263 hres
= stack_pop_val(ctx
, &r
);
1267 hres
= stack_pop_val(ctx
, &l
);
1268 if(SUCCEEDED(hres
)) {
1269 hres
= VarPow(l
.v
, r
.v
, &v
);
1276 return stack_push(ctx
, &v
);
1279 static HRESULT
interp_neg(exec_ctx_t
*ctx
)
1285 hres
= stack_pop_val(ctx
, &val
);
1289 hres
= VarNeg(val
.v
, &v
);
1294 return stack_push(ctx
, &v
);
1297 static const instr_func_t op_funcs
[] = {
1298 #define X(x,n,a,b) interp_ ## x,
1303 static const unsigned op_move
[] = {
1304 #define X(x,n,a,b) n,
1309 static void release_exec(exec_ctx_t
*ctx
)
1313 VariantClear(&ctx
->ret_val
);
1316 IDispatch_Release(ctx
->this_obj
);
1319 for(i
=0; i
< ctx
->func
->arg_cnt
; i
++)
1320 VariantClear(ctx
->args
+i
);
1324 for(i
=0; i
< ctx
->func
->var_cnt
; i
++)
1325 VariantClear(ctx
->vars
+i
);
1328 heap_free(ctx
->args
);
1329 heap_free(ctx
->vars
);
1330 heap_free(ctx
->stack
);
1333 HRESULT
exec_script(script_ctx_t
*ctx
, function_t
*func
, IDispatch
*this_obj
, DISPPARAMS
*dp
, VARIANT
*res
)
1335 exec_ctx_t exec
= {func
->code_ctx
};
1337 HRESULT hres
= S_OK
;
1339 exec
.code
= func
->code_ctx
;
1341 if(dp
? func
->arg_cnt
!= arg_cnt(dp
) : func
->arg_cnt
) {
1342 FIXME("wrong arg_cnt %d, expected %d\n", dp
? arg_cnt(dp
) : 0, func
->arg_cnt
);
1350 exec
.args
= heap_alloc_zero(func
->arg_cnt
* sizeof(VARIANT
));
1352 release_exec(&exec
);
1353 return E_OUTOFMEMORY
;
1356 for(i
=0; i
< func
->arg_cnt
; i
++) {
1358 if(V_VT(v
) == (VT_VARIANT
|VT_BYREF
)) {
1359 if(func
->args
[i
].by_ref
)
1362 hres
= VariantCopy(exec
.args
+i
, V_VARIANTREF(v
));
1364 hres
= VariantCopy(exec
.args
+i
, v
);
1367 release_exec(&exec
);
1376 exec
.vars
= heap_alloc_zero(func
->var_cnt
* sizeof(VARIANT
));
1378 release_exec(&exec
);
1379 return E_OUTOFMEMORY
;
1385 exec
.stack_size
= 16;
1387 exec
.stack
= heap_alloc(exec
.stack_size
* sizeof(VARIANT
));
1389 release_exec(&exec
);
1390 return E_OUTOFMEMORY
;
1394 exec
.this_obj
= this_obj
;
1395 else if (ctx
->host_global
)
1396 exec
.this_obj
= ctx
->host_global
;
1398 exec
.this_obj
= (IDispatch
*)&ctx
->script_obj
->IDispatchEx_iface
;
1399 IDispatch_AddRef(exec
.this_obj
);
1401 exec
.instr
= exec
.code
->instrs
+ func
->code_off
;
1406 op
= exec
.instr
->op
;
1407 hres
= op_funcs
[op
](&exec
);
1409 FIXME("Failed %08x\n", hres
);
1410 stack_popn(&exec
, exec
.top
);
1414 exec
.instr
+= op_move
[op
];
1418 if(func
->type
!= FUNC_FUNCTION
&& func
->type
!= FUNC_PROPGET
&& func
->type
!= FUNC_DEFGET
)
1419 assert(V_VT(&exec
.ret_val
) == VT_EMPTY
);
1421 if(SUCCEEDED(hres
) && res
) {
1422 *res
= exec
.ret_val
;
1423 V_VT(&exec
.ret_val
) = VT_EMPTY
;
1426 release_exec(&exec
);