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
);
38 dynamic_var_t
*dynamic_vars
;
48 typedef HRESULT (*instr_func_t
)(exec_ctx_t
*);
77 static BOOL
lookup_dynamic_vars(dynamic_var_t
*var
, const WCHAR
*name
, ref_t
*ref
)
80 if(!strcmpiW(var
->name
, name
)) {
92 static HRESULT
lookup_identifier(exec_ctx_t
*ctx
, BSTR name
, vbdisp_invoke_type_t invoke_type
, ref_t
*ref
)
100 static const WCHAR errW
[] = {'e','r','r',0};
102 if(invoke_type
== VBDISP_LET
103 && (ctx
->func
->type
== FUNC_FUNCTION
|| ctx
->func
->type
== FUNC_PROPGET
|| ctx
->func
->type
== FUNC_DEFGET
)
104 && !strcmpiW(name
, ctx
->func
->name
)) {
106 ref
->u
.v
= &ctx
->ret_val
;
110 for(i
=0; i
< ctx
->func
->var_cnt
; i
++) {
111 if(!strcmpiW(ctx
->func
->vars
[i
].name
, name
)) {
113 ref
->u
.v
= ctx
->vars
+i
;
118 for(i
=0; i
< ctx
->func
->arg_cnt
; i
++) {
119 if(!strcmpiW(ctx
->func
->args
[i
].name
, name
)) {
121 ref
->u
.v
= ctx
->args
+i
;
126 if(lookup_dynamic_vars(ctx
->func
->type
== FUNC_GLOBAL
? ctx
->script
->global_vars
: ctx
->dynamic_vars
, name
, ref
))
129 hres
= disp_get_id(ctx
->this_obj
, name
, invoke_type
, TRUE
, &id
);
130 if(SUCCEEDED(hres
)) {
131 ref
->type
= REF_DISP
;
132 ref
->u
.d
.disp
= ctx
->this_obj
;
137 if(ctx
->func
->type
!= FUNC_GLOBAL
&& lookup_dynamic_vars(ctx
->script
->global_vars
, name
, ref
))
140 for(func
= ctx
->script
->global_funcs
; func
; func
= func
->next
) {
141 if(!strcmpiW(func
->name
, name
)) {
142 ref
->type
= REF_FUNC
;
148 LIST_FOR_EACH_ENTRY(item
, &ctx
->script
->named_items
, named_item_t
, entry
) {
149 if((item
->flags
& SCRIPTITEM_GLOBALMEMBERS
) && item
->disp
!= ctx
->this_obj
) {
150 hres
= disp_get_id(item
->disp
, name
, invoke_type
, FALSE
, &id
);
151 if(SUCCEEDED(hres
)) {
152 ref
->type
= REF_DISP
;
153 ref
->u
.d
.disp
= item
->disp
;
159 if((item
->flags
& SCRIPTITEM_ISVISIBLE
) && !strcmpiW(item
->name
, name
)) {
163 hres
= IActiveScriptSite_GetItemInfo(ctx
->script
->site
, name
, SCRIPTINFO_IUNKNOWN
, &unk
, NULL
);
165 WARN("GetItemInfo failed: %08x\n", hres
);
169 hres
= IUnknown_QueryInterface(unk
, &IID_IDispatch
, (void**)&item
->disp
);
170 IUnknown_Release(unk
);
172 WARN("object does not implement IDispatch\n");
178 ref
->u
.obj
= item
->disp
;
183 if(!strcmpiW(name
, errW
)) {
185 ref
->u
.obj
= (IDispatch
*)&ctx
->script
->err_obj
->IDispatchEx_iface
;
189 hres
= vbdisp_get_id(ctx
->script
->global_obj
, name
, invoke_type
, TRUE
, &id
);
190 if(SUCCEEDED(hres
)) {
191 ref
->type
= REF_DISP
;
192 ref
->u
.d
.disp
= (IDispatch
*)&ctx
->script
->global_obj
->IDispatchEx_iface
;
197 ref
->type
= REF_NONE
;
201 static HRESULT
add_dynamic_var(exec_ctx_t
*ctx
, const WCHAR
*name
, VARIANT
*val
, BOOL own_val
)
203 dynamic_var_t
*new_var
;
209 heap
= ctx
->func
->type
== FUNC_GLOBAL
? &ctx
->script
->heap
: &ctx
->heap
;
211 new_var
= vbsheap_alloc(heap
, sizeof(*new_var
));
213 return E_OUTOFMEMORY
;
215 size
= (strlenW(name
)+1)*sizeof(WCHAR
);
216 str
= vbsheap_alloc(heap
, size
);
218 return E_OUTOFMEMORY
;
219 memcpy(str
, name
, size
);
225 hres
= VariantCopy(&new_var
->v
, val
);
230 if(ctx
->func
->type
== FUNC_GLOBAL
) {
231 new_var
->next
= ctx
->script
->global_vars
;
232 ctx
->script
->global_vars
= new_var
;
234 new_var
->next
= ctx
->dynamic_vars
;
235 ctx
->dynamic_vars
= new_var
;
241 static inline VARIANT
*stack_pop(exec_ctx_t
*ctx
)
244 return ctx
->stack
+ --ctx
->top
;
247 static HRESULT
stack_push(exec_ctx_t
*ctx
, VARIANT
*v
)
249 if(ctx
->stack_size
== ctx
->top
) {
252 new_stack
= heap_realloc(ctx
->stack
, ctx
->stack_size
*2);
255 return E_OUTOFMEMORY
;
258 ctx
->stack
= new_stack
;
259 ctx
->stack_size
*= 2;
262 ctx
->stack
[ctx
->top
++] = *v
;
266 static void stack_popn(exec_ctx_t
*ctx
, unsigned n
)
269 VariantClear(stack_pop(ctx
));
272 static HRESULT
stack_pop_val(exec_ctx_t
*ctx
, variant_val_t
*v
)
276 var
= stack_pop(ctx
);
278 if(V_VT(var
) == (VT_BYREF
|VT_VARIANT
)) {
280 var
= V_VARIANTREF(var
);
285 if(V_VT(var
) == VT_DISPATCH
) {
289 hres
= disp_call(ctx
->script
, V_DISPATCH(var
), DISPID_VALUE
, &dp
, &v
->store
);
291 IDispatch_Release(V_DISPATCH(var
));
304 static inline void release_val(variant_val_t
*v
)
310 static HRESULT
stack_pop_disp(exec_ctx_t
*ctx
, IDispatch
**ret
)
312 VARIANT
*v
= stack_pop(ctx
);
314 if(V_VT(v
) == VT_DISPATCH
) {
315 *ret
= V_DISPATCH(v
);
319 if(V_VT(v
) != (VT_VARIANT
|VT_BYREF
)) {
320 FIXME("not supported type: %s\n", debugstr_variant(v
));
326 if(V_VT(v
) != VT_DISPATCH
) {
327 FIXME("not disp %s\n", debugstr_variant(v
));
332 IDispatch_AddRef(V_DISPATCH(v
));
333 *ret
= V_DISPATCH(v
);
337 static inline void instr_jmp(exec_ctx_t
*ctx
, unsigned addr
)
339 ctx
->instr
= ctx
->code
->instrs
+ addr
;
342 static void vbstack_to_dp(exec_ctx_t
*ctx
, unsigned arg_cnt
, DISPPARAMS
*dp
)
345 dp
->rgdispidNamedArgs
= NULL
;
352 assert(ctx
->top
>= arg_cnt
);
354 for(i
=1; i
*2 <= arg_cnt
; i
++) {
355 tmp
= ctx
->stack
[ctx
->top
-i
];
356 ctx
->stack
[ctx
->top
-i
] = ctx
->stack
[ctx
->top
-arg_cnt
+i
-1];
357 ctx
->stack
[ctx
->top
-arg_cnt
+i
-1] = tmp
;
360 dp
->rgvarg
= ctx
->stack
+ ctx
->top
-arg_cnt
;
366 static HRESULT
do_icall(exec_ctx_t
*ctx
, VARIANT
*res
)
368 BSTR identifier
= ctx
->instr
->arg1
.bstr
;
369 const unsigned arg_cnt
= ctx
->instr
->arg2
.uint
;
374 hres
= lookup_identifier(ctx
, identifier
, VBDISP_CALLGET
, &ref
);
378 vbstack_to_dp(ctx
, arg_cnt
, &dp
);
383 FIXME("REF_VAR no res\n");
388 FIXME("arguments not implemented\n");
392 V_VT(res
) = VT_BYREF
|VT_VARIANT
;
393 V_BYREF(res
) = V_VT(ref
.u
.v
) == (VT_VARIANT
|VT_BYREF
) ? V_VARIANTREF(ref
.u
.v
) : ref
.u
.v
;
396 hres
= disp_call(ctx
->script
, ref
.u
.d
.disp
, ref
.u
.d
.id
, &dp
, res
);
401 hres
= exec_script(ctx
->script
, ref
.u
.f
, NULL
, &dp
, res
);
407 FIXME("arguments on object\n");
412 IDispatch_AddRef(ref
.u
.obj
);
413 V_VT(res
) = VT_DISPATCH
;
414 V_DISPATCH(res
) = ref
.u
.obj
;
418 FIXME("%s not found\n", debugstr_w(identifier
));
419 return DISP_E_UNKNOWNNAME
;
422 stack_popn(ctx
, arg_cnt
);
426 static HRESULT
interp_icall(exec_ctx_t
*ctx
)
433 hres
= do_icall(ctx
, &v
);
437 return stack_push(ctx
, &v
);
440 static HRESULT
interp_icallv(exec_ctx_t
*ctx
)
443 return do_icall(ctx
, NULL
);
446 static HRESULT
do_mcall(exec_ctx_t
*ctx
, VARIANT
*res
)
448 const BSTR identifier
= ctx
->instr
->arg1
.bstr
;
449 const unsigned arg_cnt
= ctx
->instr
->arg2
.uint
;
455 hres
= stack_pop_disp(ctx
, &obj
);
464 vbstack_to_dp(ctx
, arg_cnt
, &dp
);
466 hres
= disp_get_id(obj
, identifier
, VBDISP_CALLGET
, FALSE
, &id
);
468 hres
= disp_call(ctx
->script
, obj
, id
, &dp
, res
);
469 IDispatch_Release(obj
);
473 stack_popn(ctx
, arg_cnt
);
477 static HRESULT
interp_mcall(exec_ctx_t
*ctx
)
484 hres
= do_mcall(ctx
, &res
);
488 return stack_push(ctx
, &res
);
491 static HRESULT
interp_mcallv(exec_ctx_t
*ctx
)
495 return do_mcall(ctx
, NULL
);
498 static HRESULT
assign_ident(exec_ctx_t
*ctx
, BSTR name
, VARIANT
*val
, BOOL own_val
)
503 hres
= lookup_identifier(ctx
, name
, VBDISP_LET
, &ref
);
509 VARIANT
*v
= ref
.u
.v
;
511 if(V_VT(v
) == (VT_VARIANT
|VT_BYREF
))
519 hres
= VariantCopy(v
, val
);
524 hres
= disp_propput(ctx
->script
, ref
.u
.d
.disp
, ref
.u
.d
.id
, val
);
529 FIXME("functions not implemented\n");
535 if(ctx
->func
->code_ctx
->option_explicit
) {
536 FIXME("throw exception\n");
539 TRACE("creating variable %s\n", debugstr_w(name
));
540 hres
= add_dynamic_var(ctx
, name
, val
, own_val
);
547 static HRESULT
interp_assign_ident(exec_ctx_t
*ctx
)
549 const BSTR arg
= ctx
->instr
->arg1
.bstr
;
553 TRACE("%s\n", debugstr_w(arg
));
555 hres
= stack_pop_val(ctx
, &v
);
559 return assign_ident(ctx
, arg
, v
.v
, v
.owned
);
562 static HRESULT
interp_set_ident(exec_ctx_t
*ctx
)
564 const BSTR arg
= ctx
->instr
->arg1
.bstr
;
569 TRACE("%s\n", debugstr_w(arg
));
571 hres
= stack_pop_disp(ctx
, &disp
);
575 V_VT(&v
) = VT_DISPATCH
;
576 V_DISPATCH(&v
) = disp
;
577 return assign_ident(ctx
, ctx
->instr
->arg1
.bstr
, &v
, TRUE
);
580 static HRESULT
interp_assign_member(exec_ctx_t
*ctx
)
582 BSTR identifier
= ctx
->instr
->arg1
.bstr
;
588 TRACE("%s\n", debugstr_w(identifier
));
590 hres
= stack_pop_disp(ctx
, &obj
);
599 hres
= stack_pop_val(ctx
, &val
);
601 IDispatch_Release(obj
);
605 hres
= disp_get_id(obj
, identifier
, VBDISP_LET
, FALSE
, &id
);
607 hres
= disp_propput(ctx
->script
, obj
, id
, val
.v
);
610 IDispatch_Release(obj
);
614 static HRESULT
interp_set_member(exec_ctx_t
*ctx
)
616 BSTR identifier
= ctx
->instr
->arg1
.bstr
;
617 IDispatch
*obj
, *val
;
621 TRACE("%s\n", debugstr_w(identifier
));
623 hres
= stack_pop_disp(ctx
, &obj
);
632 hres
= stack_pop_disp(ctx
, &val
);
634 IDispatch_Release(obj
);
638 hres
= disp_get_id(obj
, identifier
, VBDISP_SET
, FALSE
, &id
);
639 if(SUCCEEDED(hres
)) {
642 V_VT(&v
) = VT_DISPATCH
;
643 V_DISPATCH(&v
) = val
;
644 hres
= disp_propput(ctx
->script
, obj
, id
, &v
);
648 IDispatch_Release(val
);
649 IDispatch_Release(obj
);
653 static HRESULT
interp_const(exec_ctx_t
*ctx
)
655 BSTR arg
= ctx
->instr
->arg1
.bstr
;
656 FIXME("%s\n", debugstr_w(arg
));
660 static HRESULT
interp_new(exec_ctx_t
*ctx
)
662 const WCHAR
*arg
= ctx
->instr
->arg1
.bstr
;
663 class_desc_t
*class_desc
;
668 TRACE("%s\n", debugstr_w(arg
));
670 for(class_desc
= ctx
->script
->classes
; class_desc
; class_desc
= class_desc
->next
) {
671 if(!strcmpiW(class_desc
->name
, arg
))
675 FIXME("Class %s not found\n", debugstr_w(arg
));
679 hres
= create_vbdisp(class_desc
, &obj
);
683 V_VT(&v
) = VT_DISPATCH
;
684 V_DISPATCH(&v
) = (IDispatch
*)&obj
->IDispatchEx_iface
;
685 return stack_push(ctx
, &v
);
688 static HRESULT
interp_jmp(exec_ctx_t
*ctx
)
690 const unsigned arg
= ctx
->instr
->arg1
.uint
;
698 static HRESULT
interp_jmp_false(exec_ctx_t
*ctx
)
700 const unsigned arg
= ctx
->instr
->arg1
.uint
;
706 hres
= stack_pop_val(ctx
, &val
);
710 if(V_VT(val
.v
) != VT_BOOL
) {
711 FIXME("unsupported for %s\n", debugstr_variant(val
.v
));
719 instr_jmp(ctx
, ctx
->instr
->arg1
.uint
);
723 static HRESULT
interp_jmp_true(exec_ctx_t
*ctx
)
725 const unsigned arg
= ctx
->instr
->arg1
.uint
;
731 hres
= stack_pop_val(ctx
, &val
);
735 if(V_VT(val
.v
) != VT_BOOL
) {
736 FIXME("unsupported for %s\n", debugstr_variant(val
.v
));
742 instr_jmp(ctx
, ctx
->instr
->arg1
.uint
);
748 static HRESULT
interp_ret(exec_ctx_t
*ctx
)
756 static HRESULT
interp_stop(exec_ctx_t
*ctx
)
760 /* NOTE: this should have effect in debugging mode (that we don't support yet) */
764 static HRESULT
interp_me(exec_ctx_t
*ctx
)
770 IDispatch_AddRef(ctx
->this_obj
);
771 V_VT(&v
) = VT_DISPATCH
;
772 V_DISPATCH(&v
) = ctx
->this_obj
;
773 return stack_push(ctx
, &v
);
776 static HRESULT
interp_bool(exec_ctx_t
*ctx
)
778 const VARIANT_BOOL arg
= ctx
->instr
->arg1
.lng
;
781 TRACE("%s\n", arg
? "true" : "false");
785 return stack_push(ctx
, &v
);
788 static HRESULT
interp_errmode(exec_ctx_t
*ctx
)
790 const int err_mode
= ctx
->instr
->arg1
.uint
;
791 FIXME("%d\n", err_mode
);
795 static HRESULT
interp_string(exec_ctx_t
*ctx
)
802 V_BSTR(&v
) = SysAllocString(ctx
->instr
->arg1
.str
);
804 return E_OUTOFMEMORY
;
806 return stack_push(ctx
, &v
);
809 static HRESULT
interp_long(exec_ctx_t
*ctx
)
811 const LONG arg
= ctx
->instr
->arg1
.lng
;
818 return stack_push(ctx
, &v
);
821 static HRESULT
interp_short(exec_ctx_t
*ctx
)
823 const LONG arg
= ctx
->instr
->arg1
.lng
;
830 return stack_push(ctx
, &v
);
833 static HRESULT
interp_double(exec_ctx_t
*ctx
)
835 const DOUBLE
*arg
= ctx
->instr
->arg1
.dbl
;
838 TRACE("%lf\n", *arg
);
842 return stack_push(ctx
, &v
);
845 static HRESULT
interp_empty(exec_ctx_t
*ctx
)
852 return stack_push(ctx
, &v
);
855 static HRESULT
interp_null(exec_ctx_t
*ctx
)
862 return stack_push(ctx
, &v
);
865 static HRESULT
interp_nothing(exec_ctx_t
*ctx
)
871 V_VT(&v
) = VT_DISPATCH
;
872 V_DISPATCH(&v
) = NULL
;
873 return stack_push(ctx
, &v
);
876 static HRESULT
interp_not(exec_ctx_t
*ctx
)
884 hres
= stack_pop_val(ctx
, &val
);
888 hres
= VarNot(val
.v
, &v
);
893 return stack_push(ctx
, &v
);
896 static HRESULT
interp_and(exec_ctx_t
*ctx
)
904 hres
= stack_pop_val(ctx
, &r
);
908 hres
= stack_pop_val(ctx
, &l
);
909 if(SUCCEEDED(hres
)) {
910 hres
= VarAnd(l
.v
, r
.v
, &v
);
917 return stack_push(ctx
, &v
);
920 static HRESULT
interp_or(exec_ctx_t
*ctx
)
928 hres
= stack_pop_val(ctx
, &r
);
932 hres
= stack_pop_val(ctx
, &l
);
933 if(SUCCEEDED(hres
)) {
934 hres
= VarOr(l
.v
, r
.v
, &v
);
941 return stack_push(ctx
, &v
);
944 static HRESULT
interp_xor(exec_ctx_t
*ctx
)
952 hres
= stack_pop_val(ctx
, &r
);
956 hres
= stack_pop_val(ctx
, &l
);
957 if(SUCCEEDED(hres
)) {
958 hres
= VarXor(l
.v
, r
.v
, &v
);
965 return stack_push(ctx
, &v
);
968 static HRESULT
interp_eqv(exec_ctx_t
*ctx
)
976 hres
= stack_pop_val(ctx
, &r
);
980 hres
= stack_pop_val(ctx
, &l
);
981 if(SUCCEEDED(hres
)) {
982 hres
= VarEqv(l
.v
, r
.v
, &v
);
989 return stack_push(ctx
, &v
);
992 static HRESULT
interp_imp(exec_ctx_t
*ctx
)
1000 hres
= stack_pop_val(ctx
, &r
);
1004 hres
= stack_pop_val(ctx
, &l
);
1005 if(SUCCEEDED(hres
)) {
1006 hres
= VarImp(l
.v
, r
.v
, &v
);
1013 return stack_push(ctx
, &v
);
1016 static HRESULT
cmp_oper(exec_ctx_t
*ctx
)
1021 hres
= stack_pop_val(ctx
, &r
);
1025 hres
= stack_pop_val(ctx
, &l
);
1026 if(SUCCEEDED(hres
)) {
1027 if(V_VT(l
.v
) == VT_NULL
|| V_VT(r
.v
) == VT_NULL
) {
1028 FIXME("comparing nulls is not implemented\n");
1031 hres
= VarCmp(l
.v
, r
.v
, ctx
->script
->lcid
, 0);
1040 static HRESULT
interp_equal(exec_ctx_t
*ctx
)
1047 hres
= cmp_oper(ctx
);
1052 V_BOOL(&v
) = hres
== VARCMP_EQ
? VARIANT_TRUE
: VARIANT_FALSE
;
1053 return stack_push(ctx
, &v
);
1056 static HRESULT
interp_nequal(exec_ctx_t
*ctx
)
1063 hres
= cmp_oper(ctx
);
1068 V_BOOL(&v
) = hres
!= VARCMP_EQ
? VARIANT_TRUE
: VARIANT_FALSE
;
1069 return stack_push(ctx
, &v
);
1072 static HRESULT
interp_gt(exec_ctx_t
*ctx
)
1079 hres
= cmp_oper(ctx
);
1084 V_BOOL(&v
) = hres
== VARCMP_GT
? VARIANT_TRUE
: VARIANT_FALSE
;
1085 return stack_push(ctx
, &v
);
1088 static HRESULT
interp_gteq(exec_ctx_t
*ctx
)
1095 hres
= cmp_oper(ctx
);
1100 V_BOOL(&v
) = hres
== VARCMP_GT
|| hres
== VARCMP_EQ
? VARIANT_TRUE
: VARIANT_FALSE
;
1101 return stack_push(ctx
, &v
);
1104 static HRESULT
interp_lt(exec_ctx_t
*ctx
)
1111 hres
= cmp_oper(ctx
);
1116 V_BOOL(&v
) = hres
== VARCMP_LT
? VARIANT_TRUE
: VARIANT_FALSE
;
1117 return stack_push(ctx
, &v
);
1120 static HRESULT
interp_lteq(exec_ctx_t
*ctx
)
1127 hres
= cmp_oper(ctx
);
1132 V_BOOL(&v
) = hres
== VARCMP_LT
|| hres
== VARCMP_EQ
? VARIANT_TRUE
: VARIANT_FALSE
;
1133 return stack_push(ctx
, &v
);
1136 static HRESULT
disp_cmp(IDispatch
*disp1
, IDispatch
*disp2
, VARIANT_BOOL
*ret
)
1138 IObjectIdentity
*identity
;
1139 IUnknown
*unk1
, *unk2
;
1142 if(disp1
== disp2
) {
1143 *ret
= VARIANT_TRUE
;
1147 if(!disp1
|| !disp2
) {
1148 *ret
= VARIANT_FALSE
;
1152 hres
= IDispatch_QueryInterface(disp1
, &IID_IUnknown
, (void**)&unk1
);
1156 hres
= IDispatch_QueryInterface(disp2
, &IID_IUnknown
, (void**)&unk2
);
1158 IUnknown_Release(unk1
);
1163 *ret
= VARIANT_TRUE
;
1165 hres
= IUnknown_QueryInterface(unk1
, &IID_IObjectIdentity
, (void**)&identity
);
1166 if(SUCCEEDED(hres
)) {
1167 hres
= IObjectIdentity_IsEqualObject(identity
, unk2
);
1168 IObjectIdentity_Release(identity
);
1169 *ret
= hres
== S_OK
? VARIANT_TRUE
: VARIANT_FALSE
;
1171 *ret
= VARIANT_FALSE
;
1175 IUnknown_Release(unk1
);
1176 IUnknown_Release(unk2
);
1180 static HRESULT
interp_is(exec_ctx_t
*ctx
)
1188 hres
= stack_pop_disp(ctx
, &r
);
1192 hres
= stack_pop_disp(ctx
, &l
);
1193 if(SUCCEEDED(hres
)) {
1195 hres
= disp_cmp(l
, r
, &V_BOOL(&v
));
1197 IDispatch_Release(l
);
1200 IDispatch_Release(r
);
1204 return stack_push(ctx
, &v
);
1207 static HRESULT
interp_concat(exec_ctx_t
*ctx
)
1215 hres
= stack_pop_val(ctx
, &r
);
1219 hres
= stack_pop_val(ctx
, &l
);
1220 if(SUCCEEDED(hres
)) {
1221 hres
= VarCat(l
.v
, r
.v
, &v
);
1228 return stack_push(ctx
, &v
);
1231 static HRESULT
interp_add(exec_ctx_t
*ctx
)
1239 hres
= stack_pop_val(ctx
, &r
);
1243 hres
= stack_pop_val(ctx
, &l
);
1244 if(SUCCEEDED(hres
)) {
1245 hres
= VarAdd(l
.v
, r
.v
, &v
);
1252 return stack_push(ctx
, &v
);
1255 static HRESULT
interp_sub(exec_ctx_t
*ctx
)
1263 hres
= stack_pop_val(ctx
, &r
);
1267 hres
= stack_pop_val(ctx
, &l
);
1268 if(SUCCEEDED(hres
)) {
1269 hres
= VarSub(l
.v
, r
.v
, &v
);
1276 return stack_push(ctx
, &v
);
1279 static HRESULT
interp_mod(exec_ctx_t
*ctx
)
1287 hres
= stack_pop_val(ctx
, &r
);
1291 hres
= stack_pop_val(ctx
, &l
);
1292 if(SUCCEEDED(hres
)) {
1293 hres
= VarMod(l
.v
, r
.v
, &v
);
1300 return stack_push(ctx
, &v
);
1303 static HRESULT
interp_idiv(exec_ctx_t
*ctx
)
1311 hres
= stack_pop_val(ctx
, &r
);
1315 hres
= stack_pop_val(ctx
, &l
);
1316 if(SUCCEEDED(hres
)) {
1317 hres
= VarIdiv(l
.v
, r
.v
, &v
);
1324 return stack_push(ctx
, &v
);
1327 static HRESULT
interp_div(exec_ctx_t
*ctx
)
1335 hres
= stack_pop_val(ctx
, &r
);
1339 hres
= stack_pop_val(ctx
, &l
);
1340 if(SUCCEEDED(hres
)) {
1341 hres
= VarDiv(l
.v
, r
.v
, &v
);
1348 return stack_push(ctx
, &v
);
1351 static HRESULT
interp_mul(exec_ctx_t
*ctx
)
1359 hres
= stack_pop_val(ctx
, &r
);
1363 hres
= stack_pop_val(ctx
, &l
);
1364 if(SUCCEEDED(hres
)) {
1365 hres
= VarMul(l
.v
, r
.v
, &v
);
1372 return stack_push(ctx
, &v
);
1375 static HRESULT
interp_exp(exec_ctx_t
*ctx
)
1383 hres
= stack_pop_val(ctx
, &r
);
1387 hres
= stack_pop_val(ctx
, &l
);
1388 if(SUCCEEDED(hres
)) {
1389 hres
= VarPow(l
.v
, r
.v
, &v
);
1396 return stack_push(ctx
, &v
);
1399 static HRESULT
interp_neg(exec_ctx_t
*ctx
)
1405 hres
= stack_pop_val(ctx
, &val
);
1409 hres
= VarNeg(val
.v
, &v
);
1414 return stack_push(ctx
, &v
);
1417 static const instr_func_t op_funcs
[] = {
1418 #define X(x,n,a,b) interp_ ## x,
1423 static const unsigned op_move
[] = {
1424 #define X(x,n,a,b) n,
1429 static void release_exec(exec_ctx_t
*ctx
)
1433 VariantClear(&ctx
->ret_val
);
1436 IDispatch_Release(ctx
->this_obj
);
1439 for(i
=0; i
< ctx
->func
->arg_cnt
; i
++)
1440 VariantClear(ctx
->args
+i
);
1444 for(i
=0; i
< ctx
->func
->var_cnt
; i
++)
1445 VariantClear(ctx
->vars
+i
);
1448 vbsheap_free(&ctx
->heap
);
1449 heap_free(ctx
->args
);
1450 heap_free(ctx
->vars
);
1451 heap_free(ctx
->stack
);
1454 HRESULT
exec_script(script_ctx_t
*ctx
, function_t
*func
, IDispatch
*this_obj
, DISPPARAMS
*dp
, VARIANT
*res
)
1456 exec_ctx_t exec
= {func
->code_ctx
};
1458 HRESULT hres
= S_OK
;
1460 exec
.code
= func
->code_ctx
;
1462 if(dp
? func
->arg_cnt
!= arg_cnt(dp
) : func
->arg_cnt
) {
1463 FIXME("wrong arg_cnt %d, expected %d\n", dp
? arg_cnt(dp
) : 0, func
->arg_cnt
);
1467 vbsheap_init(&exec
.heap
);
1473 exec
.args
= heap_alloc_zero(func
->arg_cnt
* sizeof(VARIANT
));
1475 release_exec(&exec
);
1476 return E_OUTOFMEMORY
;
1479 for(i
=0; i
< func
->arg_cnt
; i
++) {
1481 if(V_VT(v
) == (VT_VARIANT
|VT_BYREF
)) {
1482 if(func
->args
[i
].by_ref
)
1485 hres
= VariantCopy(exec
.args
+i
, V_VARIANTREF(v
));
1487 hres
= VariantCopy(exec
.args
+i
, v
);
1490 release_exec(&exec
);
1499 exec
.vars
= heap_alloc_zero(func
->var_cnt
* sizeof(VARIANT
));
1501 release_exec(&exec
);
1502 return E_OUTOFMEMORY
;
1508 exec
.stack_size
= 16;
1510 exec
.stack
= heap_alloc(exec
.stack_size
* sizeof(VARIANT
));
1512 release_exec(&exec
);
1513 return E_OUTOFMEMORY
;
1517 exec
.this_obj
= this_obj
;
1518 else if (ctx
->host_global
)
1519 exec
.this_obj
= ctx
->host_global
;
1521 exec
.this_obj
= (IDispatch
*)&ctx
->script_obj
->IDispatchEx_iface
;
1522 IDispatch_AddRef(exec
.this_obj
);
1524 exec
.instr
= exec
.code
->instrs
+ func
->code_off
;
1529 op
= exec
.instr
->op
;
1530 hres
= op_funcs
[op
](&exec
);
1532 FIXME("Failed %08x\n", hres
);
1533 stack_popn(&exec
, exec
.top
);
1537 exec
.instr
+= op_move
[op
];
1541 if(func
->type
!= FUNC_FUNCTION
&& func
->type
!= FUNC_PROPGET
&& func
->type
!= FUNC_DEFGET
)
1542 assert(V_VT(&exec
.ret_val
) == VT_EMPTY
);
1544 if(SUCCEEDED(hres
) && res
) {
1545 *res
= exec
.ret_val
;
1546 V_VT(&exec
.ret_val
) = VT_EMPTY
;
1549 release_exec(&exec
);