Jacek Caban : vbscript: Added interpreter and compiler support for for each loops.

Alexandre Julliard julliard at winehq.org
Tue Jul 3 10:58:27 CDT 2012


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

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Tue Jul  3 17:05:32 2012 +0200

vbscript: Added interpreter and compiler support for for each loops.

---

 dlls/vbscript/compile.c  |   48 +++++++++++++++++++++++++-
 dlls/vbscript/interp.c   |   84 ++++++++++++++++++++++++++++++++++++++++++++-
 dlls/vbscript/vbscript.h |    2 +
 3 files changed, 130 insertions(+), 4 deletions(-)

diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c
index a5a232e..ab76bc7 100644
--- a/dlls/vbscript/compile.c
+++ b/dlls/vbscript/compile.c
@@ -290,6 +290,24 @@ static HRESULT push_instr_bstr_uint(compile_ctx_t *ctx, vbsop_t op, const WCHAR
     return S_OK;
 }
 
+static HRESULT push_instr_uint_bstr(compile_ctx_t *ctx, vbsop_t op, unsigned arg1, const WCHAR *arg2)
+{
+    unsigned instr;
+    BSTR bstr;
+
+    bstr = alloc_bstr_arg(ctx, arg2);
+    if(!bstr)
+        return E_OUTOFMEMORY;
+
+    instr = push_instr(ctx, op);
+    if(!instr)
+        return E_OUTOFMEMORY;
+
+    instr_ptr(ctx, instr)->arg1.uint = arg1;
+    instr_ptr(ctx, instr)->arg2.bstr = bstr;
+    return S_OK;
+}
+
 #define LABEL_FLAG 0x80000000
 
 static unsigned alloc_label(compile_ctx_t *ctx)
@@ -621,8 +639,34 @@ static HRESULT compile_dowhile_statement(compile_ctx_t *ctx, while_statement_t *
 
 static HRESULT compile_foreach_statement(compile_ctx_t *ctx, foreach_statement_t *stat)
 {
-    FIXME("for each loop not implemented\n");
-    return E_NOTIMPL;
+    unsigned loop_start, loop_end;
+    HRESULT hres;
+
+    hres = compile_expression(ctx, stat->group_expr);
+    if(FAILED(hres))
+        return hres;
+
+    if(!push_instr(ctx, OP_newenum))
+        return E_OUTOFMEMORY;
+
+    loop_start = ctx->instr_cnt;
+    if(!(loop_end = alloc_label(ctx)))
+        return E_OUTOFMEMORY;
+
+    hres = push_instr_uint_bstr(ctx, OP_enumnext, loop_end, stat->identifier);
+    if(FAILED(hres))
+        return hres;
+
+    hres = compile_statement(ctx, stat->body);
+    if(FAILED(hres))
+        return hres;
+
+    hres = push_instr_addr(ctx, OP_jmp, loop_start);
+    if(FAILED(hres))
+        return hres;
+
+    label_set_addr(ctx, loop_end);
+    return S_OK;
 }
 
 static HRESULT compile_forto_statement(compile_ctx_t *ctx, forto_statement_t *stat)
diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c
index 3f3e9c8..9a8f97e 100644
--- a/dlls/vbscript/interp.c
+++ b/dlls/vbscript/interp.c
@@ -24,6 +24,8 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
 
+static DISPID propput_dispid = DISPID_PROPERTYPUT;
+
 typedef struct {
     vbscode_t *code;
     instr_t *instr;
@@ -439,8 +441,6 @@ static inline void instr_jmp(exec_ctx_t *ctx, unsigned addr)
 
 static void vbstack_to_dp(exec_ctx_t *ctx, unsigned arg_cnt, BOOL is_propput, DISPPARAMS *dp)
 {
-    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;
@@ -901,6 +901,86 @@ static HRESULT interp_step(exec_ctx_t *ctx)
     return S_OK;
 }
 
+static HRESULT interp_newenum(exec_ctx_t *ctx)
+{
+    VARIANT *v, r;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    v = stack_pop(ctx);
+    switch(V_VT(v)) {
+    case VT_DISPATCH: {
+        IEnumVARIANT *iter;
+        DISPPARAMS dp = {0};
+        VARIANT iterv;
+
+        hres = disp_call(ctx->script, V_DISPATCH(v), DISPID_NEWENUM, &dp, &iterv);
+        VariantClear(v);
+        if(FAILED(hres))
+            return hres;
+
+        if(V_VT(&iterv) != VT_UNKNOWN && V_VT(&iterv) != VT_DISPATCH) {
+            FIXME("Unsupported iterv %s\n", debugstr_variant(&iterv));
+            VariantClear(&iterv);
+            return hres;
+        }
+
+        hres = IUnknown_QueryInterface(V_UNKNOWN(&iterv), &IID_IEnumVARIANT, (void**)&iter);
+        IUnknown_Release(V_UNKNOWN(&iterv));
+        if(FAILED(hres)) {
+            FIXME("Could not get IEnumVARIANT iface: %08x\n", hres);
+            return hres;
+        }
+
+        V_VT(&r) = VT_UNKNOWN;
+        V_UNKNOWN(&r) = (IUnknown*)iter;
+        break;
+    }
+    default:
+        FIXME("Unsupported for %s\n", debugstr_variant(v));
+        VariantClear(v);
+        return E_NOTIMPL;
+    }
+
+    return stack_push(ctx, &r);
+}
+
+static HRESULT interp_enumnext(exec_ctx_t *ctx)
+{
+    const unsigned loop_end = ctx->instr->arg1.uint;
+    const BSTR ident = ctx->instr->arg2.bstr;
+    VARIANT v;
+    DISPPARAMS dp = {&v, &propput_dispid, 1, 1};
+    IEnumVARIANT *iter;
+    BOOL do_continue;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    assert(V_VT(stack_top(ctx, 0)) == VT_UNKNOWN);
+    iter = (IEnumVARIANT*)V_UNKNOWN(stack_top(ctx, 0));
+
+    V_VT(&v) = VT_EMPTY;
+    hres = IEnumVARIANT_Next(iter, 1, &v, NULL);
+    if(FAILED(hres))
+        return hres;
+
+    do_continue = hres == S_OK;
+    hres = assign_ident(ctx, ident, &dp);
+    VariantClear(&v);
+    if(FAILED(hres))
+        return hres;
+
+    if(do_continue) {
+        ctx->instr++;
+    }else {
+        stack_pop(ctx);
+        instr_jmp(ctx, loop_end);
+    }
+    return S_OK;
+}
+
 static HRESULT interp_jmp(exec_ctx_t *ctx)
 {
     const unsigned arg = ctx->instr->arg1.uint;
diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h
index 432380d..a4ae64c 100644
--- a/dlls/vbscript/vbscript.h
+++ b/dlls/vbscript/vbscript.h
@@ -194,6 +194,7 @@ typedef enum {
     X(div,            1, 0,           0)          \
     X(double,         1, ARG_DOUBLE,  0)          \
     X(empty,          1, 0,           0)          \
+    X(enumnext,       0, ARG_ADDR,    ARG_BSTR)   \
     X(equal,          1, 0,           0)          \
     X(errmode,        1, ARG_INT,     0)          \
     X(eqv,            1, 0,           0)          \
@@ -220,6 +221,7 @@ typedef enum {
     X(neg,            1, 0,           0)          \
     X(nequal,         1, 0,           0)          \
     X(new,            1, ARG_STR,     0)          \
+    X(newenum,        1, 0,           0)          \
     X(not,            1, 0,           0)          \
     X(nothing,        1, 0,           0)          \
     X(null,           1, 0,           0)          \




More information about the wine-cvs mailing list