78548: Subject: [PATCH 11/17] vbscript: Added parser support for string literals

buildbot at kegel.com buildbot at kegel.com
Thu Sep 8 09:59:39 CDT 2011


This is an experimental automated build and test service.
Please feel free to ignore this email while we work the kinks out.

The Buildbot has detected a failed build on builder runtests-heaptest while building Wine.
Full details are available at: http://buildbot.kegel.com/builders/runtests-heaptest/builds/43 (though maybe not for long, as I'm still reinstalling the buildbot periodically while experimenting)
BUILD FAILED: failed shell_3


For more info about this message, see http://wiki.winehq.org/BuildBot


-------------- next part --------------
From: Jacek Caban <jacek at codeweavers.com>
Subject: [PATCH 01/17] vbscript: Store call identifier as BSTR
Message-Id: <4E68BAFF.10705 at codeweavers.com>
Date: Thu, 08 Sep 2011 14:54:23 +0200

---
  dlls/vbscript/Makefile.in |    1 +
  dlls/vbscript/compile.c   |   47 
++++++++++++++++++++++++++++++++++++++++++--
  dlls/vbscript/vbscript.h  |   10 +++++++-
  3 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/dlls/vbscript/Makefile.in b/dlls/vbscript/Makefile.in
index 9e27dd4..cd7e18d 100644
--- a/dlls/vbscript/Makefile.in
+++ b/dlls/vbscript/Makefile.in
@@ -1,4 +1,5 @@
 MODULE    = vbscript.dll
+IMPORTS   = oleaut32
 
 C_SRCS = \
 	compile.c \
diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c
index d57abcf..49d933b 100644
--- a/dlls/vbscript/compile.c
+++ b/dlls/vbscript/compile.c
@@ -59,15 +59,45 @@ static unsigned push_instr(compile_ctx_t *ctx, vbsop_t op)
     return ctx->instr_cnt++;
 }
 
-static HRESULT push_instr_str(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg)
+static BSTR alloc_bstr_arg(compile_ctx_t *ctx, const WCHAR *str)
+{
+    if(!ctx->code->bstr_pool_size) {
+        ctx->code->bstr_pool = heap_alloc(8 * sizeof(BSTR));
+        if(!ctx->code->bstr_pool)
+            return NULL;
+        ctx->code->bstr_pool_size = 8;
+    }else if(ctx->code->bstr_pool_size == ctx->code->bstr_cnt) {
+       BSTR *new_pool;
+
+        new_pool = heap_realloc(ctx->code->bstr_pool, ctx->code->bstr_pool_size*2*sizeof(BSTR));
+        if(!new_pool)
+            return NULL;
+
+        ctx->code->bstr_pool = new_pool;
+        ctx->code->bstr_pool_size *= 2;
+    }
+
+    ctx->code->bstr_pool[ctx->code->bstr_cnt] = SysAllocString(str);
+    if(!ctx->code->bstr_pool[ctx->code->bstr_cnt])
+        return NULL;
+
+    return ctx->code->bstr_pool[ctx->code->bstr_cnt++];
+}
+
+static HRESULT push_instr_bstr(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg)
 {
     unsigned instr;
+    BSTR bstr;
+
+    bstr = alloc_bstr_arg(ctx, arg);
+    if(!bstr)
+        return E_OUTOFMEMORY;
 
     instr = push_instr(ctx, op);
     if(instr == -1)
         return E_OUTOFMEMORY;
 
-    instr_ptr(ctx, instr)->arg1.str = arg;
+    instr_ptr(ctx, instr)->arg1.bstr = bstr;
     return S_OK;
 }
 
@@ -84,7 +114,7 @@ static HRESULT compile_member_expression(compile_ctx_t *ctx, member_expression_t
         FIXME("obj_expr not implemented\n");
         hres = E_NOTIMPL;
     }else {
-        hres = push_instr_str(ctx, OP_icallv, expr->identifier);
+        hres = push_instr_bstr(ctx, OP_icallv, expr->identifier);
     }
 
     return hres;
@@ -130,7 +160,14 @@ static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *f
 
 void release_vbscode(vbscode_t *code)
 {
+    unsigned i;
+
     list_remove(&code->entry);
+
+    for(i=0; i < code->bstr_cnt; i++)
+        SysFreeString(code->bstr_pool[i]);
+
+    heap_free(code->bstr_pool);
     heap_free(code->source);
     heap_free(code->instrs);
     heap_free(code);
@@ -159,6 +196,10 @@ static vbscode_t *alloc_vbscode(compile_ctx_t *ctx, const WCHAR *source)
     ctx->instr_cnt = 0;
     ctx->instr_size = 32;
 
+    ret->bstr_pool = NULL;
+    ret->bstr_pool_size = 0;
+    ret->bstr_cnt = 0;
+
     ret->global_code.code_ctx = ret;
 
     list_init(&ret->entry);
diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h
index bca630a..9942ac7 100644
--- a/dlls/vbscript/vbscript.h
+++ b/dlls/vbscript/vbscript.h
@@ -64,11 +64,12 @@ HRESULT init_global(script_ctx_t*);
 
 typedef enum {
     ARG_NONE = 0,
-    ARG_STR
+    ARG_STR,
+    ARG_BSTR
 } instr_arg_type_t;
 
 #define OP_LIST                                   \
-    X(icallv,         1, ARG_STR,     0)          \
+    X(icallv,         1, ARG_BSTR,    0)          \
     X(ret,            0, 0,           0)
 
 typedef enum {
@@ -80,6 +81,7 @@ OP_LIST
 
 typedef union {
     const WCHAR *str;
+    BSTR bstr;
 } instr_arg_t;
 
 typedef struct {
@@ -100,6 +102,10 @@ struct _vbscode_t {
     BOOL global_executed;
     function_t global_code;
 
+    BSTR *bstr_pool;
+    unsigned bstr_pool_size;
+    unsigned bstr_cnt;
+
     struct list entry;
 };
 

From: Jacek Caban <jacek at codeweavers.com>
Subject: [PATCH 02/17] vbscript: Added intep_icallv implementation
Message-Id: <4E68BB0D.2000707 at codeweavers.com>
Date: Thu, 08 Sep 2011 14:54:37 +0200

---
  dlls/vbscript/interp.c        |   67 
+++++++++++++++++++++++++++++++++++++++--
  dlls/vbscript/vbdisp.c        |   43 ++++++++++++++++++++++++++
  dlls/vbscript/vbscript.h      |    8 ++++-
  dlls/vbscript/vbscript_main.c |    2 +
  4 files changed, 115 insertions(+), 5 deletions(-)

diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c
index 3ff6bbd..b309397 100644
--- a/dlls/vbscript/interp.c
+++ b/dlls/vbscript/interp.c
@@ -28,15 +28,75 @@ WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
 typedef struct {
     vbscode_t *code;
     instr_t *instr;
+    script_ctx_t *script;
 } exec_ctx_t;
 
-
 typedef HRESULT (*instr_func_t)(exec_ctx_t*);
 
+typedef enum {
+    REF_NONE,
+    REF_DISP
+} ref_type_t;
+
+typedef struct {
+    ref_type_t type;
+    union {
+        struct {
+            IDispatch *disp;
+            DISPID id;
+        } d;
+    } u;
+} ref_t;
+
+static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, ref_t *ref)
+{
+    named_item_t *item;
+    DISPID id;
+    HRESULT hres;
+
+    LIST_FOR_EACH_ENTRY(item, &ctx->script->named_items, named_item_t, entry) {
+        if(item->flags & SCRIPTITEM_GLOBALMEMBERS) {
+            hres = disp_get_id(item->disp, name, &id);
+            if(SUCCEEDED(hres)) {
+                ref->type = REF_DISP;
+                ref->u.d.disp = item->disp;
+                ref->u.d.id = id;
+                return S_OK;
+            }
+        }
+    }
+
+    FIXME("create if no option explicit\n");
+
+    ref->type = REF_NONE;
+    return S_OK;
+}
+
 static HRESULT interp_icallv(exec_ctx_t *ctx)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    BSTR identifier = ctx->instr->arg1.bstr;
+    DISPPARAMS dp = {0};
+    ref_t ref;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    hres = lookup_identifier(ctx, identifier, &ref);
+    if(FAILED(hres))
+        return hres;
+
+    switch(ref.type) {
+    case REF_DISP:
+        hres = disp_call(ctx->script, ref.u.d.disp, ref.u.d.id, &dp, NULL);
+        if(FAILED(hres))
+            return hres;
+        break;
+    default:
+        FIXME("%s not found\n", debugstr_w(identifier));
+        return DISP_E_UNKNOWNNAME;
+    }
+
+    return S_OK;
 }
 
 static HRESULT interp_ret(exec_ctx_t *ctx)
@@ -67,6 +127,7 @@ HRESULT exec_script(script_ctx_t *ctx, function_t *func)
 
     exec.code = func->code_ctx;
     exec.instr = exec.code->instrs + func->code_off;
+    exec.script = ctx;
 
     while(exec.instr) {
         op = exec.instr->op;
diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c
index 3c81789..c115199 100644
--- a/dlls/vbscript/vbdisp.c
+++ b/dlls/vbscript/vbdisp.c
@@ -203,3 +203,46 @@ HRESULT init_global(script_ctx_t *ctx)
 {
     return create_vbdisp(&ctx->script_obj);
 }
+
+HRESULT disp_get_id(IDispatch *disp, BSTR name, DISPID *id)
+{
+    IDispatchEx *dispex;
+    HRESULT hres;
+
+    if(disp->lpVtbl == (IDispatchVtbl*)&DispatchExVtbl)
+        FIXME("properly handle builtin objects\n");
+
+    hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
+    if(FAILED(hres)) {
+        TRACE("unsing IDispatch\n");
+        return IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, id);
+    }
+
+    hres = IDispatchEx_GetDispID(dispex, name, fdexNameCaseInsensitive, id);
+    IDispatchEx_Release(dispex);
+    return hres;
+}
+
+HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, DISPPARAMS *dp, VARIANT *retv)
+{
+    const WORD flags = DISPATCH_METHOD|(retv ? DISPATCH_PROPERTYGET : 0);
+    IDispatchEx *dispex;
+    EXCEPINFO ei;
+    HRESULT hres;
+
+    memset(&ei, 0, sizeof(ei));
+    if(retv)
+        V_VT(retv) = VT_EMPTY;
+
+    hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
+    if(FAILED(hres)) {
+        UINT err = 0;
+
+        TRACE("using IDispatch\n");
+        return IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, flags, dp, retv, &ei, &err);
+    }
+
+    hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, flags, dp, retv, &ei, NULL /* CALLER_FIXME */);
+    IDispatchEx_Release(dispex);
+    return hres;
+}
diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h
index 9942ac7..8aca01c 100644
--- a/dlls/vbscript/vbscript.h
+++ b/dlls/vbscript/vbscript.h
@@ -33,6 +33,7 @@
 
 typedef struct _function_t function_t;
 typedef struct _vbscode_t vbscode_t;
+typedef struct _script_ctx_t script_ctx_t;
 
 typedef struct named_item_t {
     IDispatch *disp;
@@ -48,7 +49,10 @@ typedef struct {
     LONG ref;
 } vbdisp_t;
 
-typedef struct {
+HRESULT disp_get_id(IDispatch*,BSTR,DISPID*);
+HRESULT disp_call(script_ctx_t*,IDispatch*,DISPID,DISPPARAMS*,VARIANT*);
+
+struct _script_ctx_t {
     IActiveScriptSite *site;
     LCID lcid;
 
@@ -58,7 +62,7 @@ typedef struct {
 
     struct list code_list;
     struct list named_items;
-} script_ctx_t;
+};
 
 HRESULT init_global(script_ctx_t*);
 
diff --git a/dlls/vbscript/vbscript_main.c b/dlls/vbscript/vbscript_main.c
index fc31aed..9d74026 100644
--- a/dlls/vbscript/vbscript_main.c
+++ b/dlls/vbscript/vbscript_main.c
@@ -27,6 +27,8 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
 
+DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
+
 static HINSTANCE vbscript_hinstance;
 
 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)

From: Jacek Caban <jacek at codeweavers.com>
Subject: [PATCH 03/17] vbscript: Added simple call test
Message-Id: <4E68BB1B.8010500 at codeweavers.com>
Date: Thu, 08 Sep 2011 14:54:51 +0200

---
  dlls/vbscript/tests/run.c |    6 ++++++
  1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c
index d61b81f..4f70224 100644
--- a/dlls/vbscript/tests/run.c
+++ b/dlls/vbscript/tests/run.c
@@ -463,6 +463,12 @@ static void run_tests(void)
 
     parse_script_a("");
     parse_script_a("' empty ;");
+
+    SET_EXPECT(global_success_d);
+    SET_EXPECT(global_success_i);
+    parse_script_a("reportSuccess");
+    CHECK_CALLED(global_success_d);
+    CHECK_CALLED(global_success_i);
 }
 
 static BOOL check_vbscript(void)

From: Jacek Caban <jacek at codeweavers.com>
Subject: [PATCH 04/17] vbscript: Added support for a few more characters in lexer
Message-Id: <4E68BB32.60706 at codeweavers.com>
Date: Thu, 08 Sep 2011 14:55:14 +0200

---
  dlls/vbscript/lex.c |   12 ++++++++++++
  1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/dlls/vbscript/lex.c b/dlls/vbscript/lex.c
index d481e6a..d41c582 100644
--- a/dlls/vbscript/lex.c
+++ b/dlls/vbscript/lex.c
@@ -76,6 +76,18 @@ static int parse_next_token(void *lval, parser_ctx_t *ctx)
         else
             ctx->ptr = ctx->end;
         return tNL;
+    case '(':
+    case ')':
+    case ',':
+    case '=':
+    case '+':
+    case '-':
+    case '*':
+    case '/':
+    case '^':
+    case '\\':
+    case '.':
+        return *ctx->ptr++;
     default:
         FIXME("Unhandled char %c in %s\n", *ctx->ptr, debugstr_w(ctx->ptr));
     }

From: Jacek Caban <jacek at codeweavers.com>
Subject: [PATCH 05/17] vbscript: Better function call parsing
Message-Id: <4E68BB47.9080909 at codeweavers.com>
Date: Thu, 08 Sep 2011 14:55:35 +0200

---
  dlls/vbscript/parser.y    |   16 ++++++++++++++--
  dlls/vbscript/tests/run.c |    6 ++++++
  2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y
index 5fb6bd2..d5c7d40 100644
--- a/dlls/vbscript/parser.y
+++ b/dlls/vbscript/parser.y
@@ -39,6 +39,8 @@ static member_expression_t *new_member_expression(parser_ctx_t*,expression_t*,co
 
 static statement_t *new_call_statement(parser_ctx_t*,member_expression_t*);
 
+#define CHECK_ERROR if(((parser_ctx_t*)ctx)->hres != S_OK) YYABORT
+
 %}
 
 %pure_parser
@@ -47,6 +49,7 @@ static statement_t *new_call_statement(parser_ctx_t*,member_expression_t*);
 %union {
     const WCHAR *string;
     statement_t *statement;
+    expression_t *expression;
     member_expression_t *member;
 }
 
@@ -55,6 +58,7 @@ static statement_t *new_call_statement(parser_ctx_t*,member_expression_t*);
 
 %type <statement> Statement StatementNl
 %type <member> MemberExpression
+%type <expression> Arguments_opt ArgumentList_opt
 
 %%
 
@@ -69,12 +73,20 @@ StatementNl
     : Statement tNL                 { $$ = $1; }
 
 Statement
-    : MemberExpression /* FIXME: Arguments_opt */   { $$ = new_call_statement(ctx, $1); }
+    : MemberExpression Arguments_opt    { $1->args = $2; $$ = new_call_statement(ctx, $1); CHECK_ERROR; }
 
 MemberExpression
-    : tIdentifier                   { $$ = new_member_expression(ctx, NULL, $1); }
+    : tIdentifier                   { $$ = new_member_expression(ctx, NULL, $1); CHECK_ERROR; }
     /* FIXME: MemberExpressionArgs '.' tIdentifier */
 
+Arguments_opt
+    : /* empty */                   { $$ = NULL; }
+    | '(' ArgumentList_opt ')'      { $$ = $2; }
+
+ArgumentList_opt
+    : /* empty */                   { $$ = NULL; }
+ /* | ArgumentList                  { $$ = $1; } */
+
 %%
 
 static int parser_error(const char *str)
diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c
index 4f70224..9b1abd4 100644
--- a/dlls/vbscript/tests/run.c
+++ b/dlls/vbscript/tests/run.c
@@ -469,6 +469,12 @@ static void run_tests(void)
     parse_script_a("reportSuccess");
     CHECK_CALLED(global_success_d);
     CHECK_CALLED(global_success_i);
+
+    SET_EXPECT(global_success_d);
+    SET_EXPECT(global_success_i);
+    parse_script_a("reportSuccess()");
+    CHECK_CALLED(global_success_d);
+    CHECK_CALLED(global_success_i);
 }
 
 static BOOL check_vbscript(void)

From: Jacek Caban <jacek at codeweavers.com>
Subject: [PATCH 06/17] vbscript: Added support for call keyword in lexer
Message-Id: <4E68BB57.2070804 at codeweavers.com>
Date: Thu, 08 Sep 2011 14:55:51 +0200

---
  dlls/vbscript/lex.c    |   58 
++++++++++++++++++++++++++++++++++++++++++++++-
  dlls/vbscript/parser.y |    1 +
  2 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/dlls/vbscript/lex.c b/dlls/vbscript/lex.c
index d41c582..af01220 100644
--- a/dlls/vbscript/lex.c
+++ b/dlls/vbscript/lex.c
@@ -26,11 +26,61 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
 
+static const WCHAR callW[] = {'c','a','l','l',0};
+
+static const struct {
+    const WCHAR *word;
+    int token;
+} keywords[] = {
+    {callW, tCALL}
+};
+
 static inline BOOL is_identifier_char(WCHAR c)
 {
     return isalnumW(c) || c == '_';
 }
 
+static int check_keyword(parser_ctx_t *ctx, const WCHAR *word)
+{
+    const WCHAR *p1 = ctx->ptr;
+    const WCHAR *p2 = word;
+    WCHAR c;
+
+    while(p1 < ctx->end && *p2) {
+        c = tolowerW(*p1);
+        if(c != *p2)
+            return c - *p2;
+        p1++;
+        p2++;
+    }
+
+    if(*p2 || (p1 < ctx->end && is_identifier_char(*p1)))
+        return 1;
+
+    ctx->ptr = p1;
+    return 0;
+}
+
+static int check_keywords(parser_ctx_t *ctx)
+{
+    int min = 0, max = sizeof(keywords)/sizeof(keywords[0])-1, r, i;
+
+    while(min <= max) {
+        i = (min+max)/2;
+
+        r = check_keyword(ctx, keywords[i].word);
+        if(!r)
+            return keywords[i].token;
+
+        if(r > 0)
+            min = i+1;
+        else
+            max = i-1;
+    }
+
+    return 0;
+}
+
 static int parse_identifier(parser_ctx_t *ctx, const WCHAR **ret)
 {
     const WCHAR *ptr = ctx->ptr++;
@@ -62,8 +112,12 @@ static int parse_next_token(void *lval, parser_ctx_t *ctx)
 
     c = *ctx->ptr;
 
-    if(isalphaW(c))
-        return parse_identifier(ctx, lval);
+    if(isalphaW(c)) {
+        int ret = check_keywords(ctx);
+        if(!ret)
+            return parse_identifier(ctx, lval);
+        return ret;
+    }
 
     switch(c) {
     case '\n':
diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y
index d5c7d40..447aa12 100644
--- a/dlls/vbscript/parser.y
+++ b/dlls/vbscript/parser.y
@@ -54,6 +54,7 @@ static statement_t *new_call_statement(parser_ctx_t*,member_expression_t*);
 }
 
 %token tEOF tNL blah
+%token tCALL
 %token <string> tIdentifier
 
 %type <statement> Statement StatementNl

From: Jacek Caban <jacek at codeweavers.com>
Subject: [PATCH 07/17] vbscript: Added Call statement implementation
Message-Id: <4E68BB65.2020507 at codeweavers.com>
Date: Thu, 08 Sep 2011 14:56:05 +0200

---
  dlls/vbscript/parser.y    |    3 ++-
  dlls/vbscript/tests/run.c |    6 ++++++
  2 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y
index 447aa12..caf6f49 100644
--- a/dlls/vbscript/parser.y
+++ b/dlls/vbscript/parser.y
@@ -74,7 +74,8 @@ StatementNl
     : Statement tNL                 { $$ = $1; }
 
 Statement
-    : MemberExpression Arguments_opt    { $1->args = $2; $$ = new_call_statement(ctx, $1); CHECK_ERROR; }
+    : MemberExpression Arguments_opt        { $1->args = $2; $$ = new_call_statement(ctx, $1); CHECK_ERROR; }
+    | tCALL MemberExpression Arguments_opt  { $2->args = $3; $$ = new_call_statement(ctx, $2); CHECK_ERROR; }
 
 MemberExpression
     : tIdentifier                   { $$ = new_member_expression(ctx, NULL, $1); CHECK_ERROR; }
diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c
index 9b1abd4..6f1a967 100644
--- a/dlls/vbscript/tests/run.c
+++ b/dlls/vbscript/tests/run.c
@@ -475,6 +475,12 @@ static void run_tests(void)
     parse_script_a("reportSuccess()");
     CHECK_CALLED(global_success_d);
     CHECK_CALLED(global_success_i);
+
+    SET_EXPECT(global_success_d);
+    SET_EXPECT(global_success_i);
+    parse_script_a("Call reportSuccess");
+    CHECK_CALLED(global_success_d);
+    CHECK_CALLED(global_success_i);
 }
 
 static BOOL check_vbscript(void)

From: Jacek Caban <jacek at codeweavers.com>
Subject: [PATCH 08/17] vbscript: Added more keywords to lexer
Message-Id: <4E68BB72.4070008 at codeweavers.com>
Date: Thu, 08 Sep 2011 14:56:18 +0200

---
  dlls/vbscript/lex.c    |   98 
+++++++++++++++++++++++++++++++++++++++++++++++-
  dlls/vbscript/parser.y |   15 ++++++-
  2 files changed, 110 insertions(+), 3 deletions(-)

diff --git a/dlls/vbscript/lex.c b/dlls/vbscript/lex.c
index af01220..04ade1e 100644
--- a/dlls/vbscript/lex.c
+++ b/dlls/vbscript/lex.c
@@ -26,13 +26,109 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
 
+static const WCHAR andW[] = {'a','n','d',0};
+static const WCHAR byrefW[] = {'b','y','r','e','f',0};
+static const WCHAR byvalW[] = {'b','y','v','a','l',0};
 static const WCHAR callW[] = {'c','a','l','l',0};
+static const WCHAR classW[] = {'c','l','a','s','s',0};
+static const WCHAR defaultW[] = {'d','e','f','a','u','l','t',0};
+static const WCHAR dimW[] = {'d','i','m',0};
+static const WCHAR doW[] = {'d','o',0};
+static const WCHAR elseW[] = {'e','l','s','e',0};
+static const WCHAR elseifW[] = {'e','l','s','e','i','f',0};
+static const WCHAR emptyW[] = {'e','m','p','t','y',0};
+static const WCHAR endW[] = {'e','n','d',0};
+static const WCHAR eqvW[] = {'e','q','v',0};
+static const WCHAR errorW[] = {'e','r','r','o','r',0};
+static const WCHAR exitW[] = {'e','x','i','t',0};
+static const WCHAR explicitW[] = {'e','x','p','l','i','c','i','t',0};
+static const WCHAR falseW[] = {'f','a','l','s','e',0};
+static const WCHAR functionW[] = {'f','u','n','c','t','i','o','n',0};
+static const WCHAR getW[] = {'g','e','t',0};
+static const WCHAR gotoW[] = {'g','o','t','o',0};
+static const WCHAR ifW[] = {'i','f',0};
+static const WCHAR impW[] = {'i','m','p',0};
+static const WCHAR isW[] = {'i','s',0};
+static const WCHAR letW[] = {'l','e','t',0};
+static const WCHAR loopW[] = {'l','o','o','p',0};
+static const WCHAR meW[] = {'m','e',0};
+static const WCHAR modW[] = {'m','o','d',0};
+static const WCHAR newW[] = {'n','e','w',0};
+static const WCHAR nextW[] = {'n','e','x','t',0};
+static const WCHAR notW[] = {'n','o','t',0};
+static const WCHAR nothingW[] = {'n','o','t','h','i','n','g',0};
+static const WCHAR nullW[] = {'n','u','l','l',0};
+static const WCHAR onW[] = {'o','n',0};
+static const WCHAR optionW[] = {'o','p','t','i','o','n',0};
+static const WCHAR orW[] = {'o','r',0};
+static const WCHAR privateW[] = {'p','r','i','v','a','t','e',0};
+static const WCHAR propertyW[] = {'p','r','o','p','e','r','t','y',0};
+static const WCHAR publicW[] = {'p','u','b','l','i','c',0};
+static const WCHAR remW[] = {'r','e','m',0};
+static const WCHAR resumeW[] = {'r','e','s','u','m','e',0};
+static const WCHAR setW[] = {'s','e','t',0};
+static const WCHAR stopW[] = {'s','t','o','p',0};
+static const WCHAR subW[] = {'s','u','b',0};
+static const WCHAR thenW[] = {'t','h','e','n',0};
+static const WCHAR trueW[] = {'t','r','u','e',0};
+static const WCHAR untilW[] = {'u','n','t','i','l',0};
+static const WCHAR wendW[] = {'w','e','n','d',0};
+static const WCHAR whileW[] = {'w','h','i','l','e',0};
+static const WCHAR xorW[] = {'x','o','r',0};
 
 static const struct {
     const WCHAR *word;
     int token;
 } keywords[] = {
-    {callW, tCALL}
+    {andW,       tAND},
+    {byrefW,     tBYREF},
+    {byvalW,     tBYVAL},
+    {callW,      tCALL},
+    {classW,     tCLASS},
+    {defaultW,   tDEFAULT},
+    {dimW,       tDIM},
+    {doW,        tDO},
+    {elseW,      tELSE},
+    {elseifW,    tELSEIF},
+    {emptyW,     tEMPTY},
+    {endW,       tEND},
+    {eqvW,       tEQV},
+    {errorW,     tERROR},
+    {exitW,      tEXIT},
+    {explicitW,  tEXPLICIT},
+    {falseW,     tFALSE},
+    {functionW,  tFUNCTION},
+    {getW,       tGET},
+    {gotoW,      tGOTO},
+    {ifW,        tIF},
+    {impW,       tIMP},
+    {isW,        tIS},
+    {letW,       tLET},
+    {loopW,      tLOOP},
+    {meW,        tME},
+    {modW,       tMOD},
+    {newW,       tNEW},
+    {nextW,      tNEXT},
+    {notW,       tNOT},
+    {nothingW,   tNOTHING},
+    {nullW,      tNULL},
+    {onW,        tON},
+    {optionW,    tOPTION},
+    {orW,        tOR},
+    {privateW,   tPRIVATE},
+    {propertyW,  tPROPERTY},
+    {publicW,    tPUBLIC},
+    {remW,       tREM},
+    {resumeW,    tRESUME},
+    {setW,       tSET},
+    {stopW,      tSTOP},
+    {subW,       tSUB},
+    {thenW,      tTHEN},
+    {trueW,      tTRUE},
+    {untilW,     tUNTIL},
+    {wendW,      tWEND},
+    {whileW,     tWHILE},
+    {xorW,       tXOR}
 };
 
 static inline BOOL is_identifier_char(WCHAR c)
diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y
index caf6f49..2fe9bdb 100644
--- a/dlls/vbscript/parser.y
+++ b/dlls/vbscript/parser.y
@@ -53,8 +53,19 @@ static statement_t *new_call_statement(parser_ctx_t*,member_expression_t*);
     member_expression_t *member;
 }
 
-%token tEOF tNL blah
-%token tCALL
+%token tEOF tNL tREM
+%token tTRUE tFALSE
+%token tNOT tAND tOR tXOR tEQV tIMP tNEQ
+%token tIS tLTEQ tGTEQ tMOD
+%token tCALL tDIM tSUB tFUNCTION tPROPERTY tGET tLET
+%token tIF tELSE tELSEIF tEND tTHEN tEXIT
+%token tWHILE tWEND tDO tLOOP tUNTIL
+%token tBYREF tBYVAL
+%token tOPTION tEXPLICIT
+%token tSTOP
+%token tNOTHING tEMPTY tNULL
+%token tCLASS tSET tNEW tPUBLIC tPRIVATE tDEFAULT tME
+%token tERROR tNEXT tON tRESUME tGOTO
 %token <string> tIdentifier
 
 %type <statement> Statement StatementNl

From: Jacek Caban <jacek at codeweavers.com>
Subject: [PATCH 09/17] vbscript: Added bool literals parsing support
Message-Id: <4E68BB84.8010809 at codeweavers.com>
Date: Thu, 08 Sep 2011 14:56:36 +0200

---
  dlls/vbscript/parse.h  |    6 ++++++
  dlls/vbscript/parser.y |   30 ++++++++++++++++++++++++++++--
  2 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/dlls/vbscript/parse.h b/dlls/vbscript/parse.h
index 7c9ab26..df337d2 100644
--- a/dlls/vbscript/parse.h
+++ b/dlls/vbscript/parse.h
@@ -17,6 +17,7 @@
  */
 
 typedef enum {
+    EXPR_BOOL,
     EXPR_MEMBER
 } expression_type_t;
 
@@ -27,6 +28,11 @@ typedef struct _expression_t {
 
 typedef struct {
     expression_t expr;
+    VARIANT_BOOL value;
+} bool_expression_t;
+
+typedef struct {
+    expression_t expr;
     expression_t *obj_expr;
     const WCHAR *identifier;
     expression_t *args;
diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y
index 2fe9bdb..3761b13 100644
--- a/dlls/vbscript/parser.y
+++ b/dlls/vbscript/parser.y
@@ -35,6 +35,8 @@ static void parse_complete(parser_ctx_t*);
 
 static void source_add_statement(parser_ctx_t*,statement_t*);
 
+static expression_t *new_bool_expression(parser_ctx_t*,VARIANT_BOOL);
+
 static member_expression_t *new_member_expression(parser_ctx_t*,expression_t*,const WCHAR*);
 
 static statement_t *new_call_statement(parser_ctx_t*,member_expression_t*);
@@ -69,8 +71,9 @@ static statement_t *new_call_statement(parser_ctx_t*,member_expression_t*);
 %token <string> tIdentifier
 
 %type <statement> Statement StatementNl
+%type <expression> Expression LiteralExpression
 %type <member> MemberExpression
-%type <expression> Arguments_opt ArgumentList_opt
+%type <expression> Arguments_opt ArgumentList_opt ArgumentList
 
 %%
 
@@ -98,7 +101,18 @@ Arguments_opt
 
 ArgumentList_opt
     : /* empty */                   { $$ = NULL; }
- /* | ArgumentList                  { $$ = $1; } */
+    | ArgumentList                  { $$ = $1; }
+
+ArgumentList
+    : Expression                    { $$ = $1; }
+    | Expression ',' ArgumentList   { $1->next = $3; $$ = $1; }
+
+Expression
+    : LiteralExpression /* FIXME */ { $$ = $1; }
+
+LiteralExpression
+    : tTRUE                         { $$ = new_bool_expression(ctx, VARIANT_TRUE); CHECK_ERROR; }
+    | tFALSE                        { $$ = new_bool_expression(ctx, VARIANT_FALSE); CHECK_ERROR; }
 
 %%
 
@@ -135,6 +149,18 @@ static void *new_expression(parser_ctx_t *ctx, expression_type_t type, unsigned
     return expr;
 }
 
+static expression_t *new_bool_expression(parser_ctx_t *ctx, VARIANT_BOOL value)
+{
+    bool_expression_t *expr;
+
+    expr = new_expression(ctx, EXPR_BOOL, sizeof(*expr));
+    if(!expr)
+        return NULL;
+
+    expr->value = value;
+    return &expr->expr;
+}
+
 static member_expression_t *new_member_expression(parser_ctx_t *ctx, expression_t *obj_expr, const WCHAR *identifier)
 {
     member_expression_t *expr;

From: Jacek Caban <jacek at codeweavers.com>
Subject: [PATCH 10/17] vbscript: Added lexer support for string literals
Message-Id: <4E68BB90.1010709 at codeweavers.com>
Date: Thu, 08 Sep 2011 14:56:48 +0200

---
  dlls/vbscript/lex.c    |   45 
+++++++++++++++++++++++++++++++++++++++++++++
  dlls/vbscript/parser.y |    2 +-
  2 files changed, 46 insertions(+), 1 deletions(-)

diff --git a/dlls/vbscript/lex.c b/dlls/vbscript/lex.c
index 04ade1e..2fd51bc 100644
--- a/dlls/vbscript/lex.c
+++ b/dlls/vbscript/lex.c
@@ -197,6 +197,49 @@ static int parse_identifier(parser_ctx_t *ctx, const WCHAR **ret)
     return tIdentifier;
 }
 
+static int parse_string_literal(parser_ctx_t *ctx, const WCHAR **ret)
+{
+    const WCHAR *ptr = ++ctx->ptr;
+    WCHAR *rptr;
+    int len = 0;
+
+    while(ctx->ptr < ctx->end) {
+        if(*ctx->ptr == '\n') {
+            FIXME("newline inside string literal\n");
+            return 0;
+        }
+
+       if(*ctx->ptr == '"') {
+            if(ctx->ptr[1] != '"')
+                break;
+            len--;
+            ctx->ptr++;
+        }
+        ctx->ptr++;
+    }
+
+    if(ctx->ptr == ctx->end) {
+        FIXME("unterminated string literal\n");
+        return 0;
+    }
+
+    len += ctx->ptr-ptr;
+
+    *ret = rptr = parser_alloc(ctx, (len+1)*sizeof(WCHAR));
+    if(!rptr)
+        return 0;
+
+    while(ptr < ctx->ptr) {
+        if(*ptr == '"')
+            ptr++;
+        *rptr++ = *ptr++;
+    }
+
+    *rptr = 0;
+    ctx->ptr++;
+    return tString;
+}
+
 static int parse_next_token(void *lval, parser_ctx_t *ctx)
 {
     WCHAR c;
@@ -238,6 +281,8 @@ static int parse_next_token(void *lval, parser_ctx_t *ctx)
     case '\\':
     case '.':
         return *ctx->ptr++;
+    case '"':
+        return parse_string_literal(ctx, lval);
     default:
         FIXME("Unhandled char %c in %s\n", *ctx->ptr, debugstr_w(ctx->ptr));
     }
diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y
index 3761b13..06a0eb3 100644
--- a/dlls/vbscript/parser.y
+++ b/dlls/vbscript/parser.y
@@ -68,7 +68,7 @@ static statement_t *new_call_statement(parser_ctx_t*,member_expression_t*);
 %token tNOTHING tEMPTY tNULL
 %token tCLASS tSET tNEW tPUBLIC tPRIVATE tDEFAULT tME
 %token tERROR tNEXT tON tRESUME tGOTO
-%token <string> tIdentifier
+%token <string> tIdentifier tString
 
 %type <statement> Statement StatementNl
 %type <expression> Expression LiteralExpression

From: Jacek Caban <jacek at codeweavers.com>
Subject: [PATCH 11/17] vbscript: Added parser support for string literals
Message-Id: <4E68BB9A.3040807 at codeweavers.com>
Date: Thu, 08 Sep 2011 14:56:58 +0200

---
  dlls/vbscript/parse.h  |    8 +++++++-
  dlls/vbscript/parser.y |   14 ++++++++++++++
  2 files changed, 21 insertions(+), 1 deletions(-)

diff --git a/dlls/vbscript/parse.h b/dlls/vbscript/parse.h
index df337d2..a0c7f2c 100644
--- a/dlls/vbscript/parse.h
+++ b/dlls/vbscript/parse.h
@@ -18,7 +18,8 @@
 
 typedef enum {
     EXPR_BOOL,
-    EXPR_MEMBER
+    EXPR_MEMBER,
+    EXPR_STRING
 } expression_type_t;
 
 typedef struct _expression_t {
@@ -33,6 +34,11 @@ typedef struct {
 
 typedef struct {
     expression_t expr;
+    const WCHAR *value;
+} string_expression_t;
+
+typedef struct {
+    expression_t expr;
     expression_t *obj_expr;
     const WCHAR *identifier;
     expression_t *args;
diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y
index 06a0eb3..2d50565 100644
--- a/dlls/vbscript/parser.y
+++ b/dlls/vbscript/parser.y
@@ -36,6 +36,7 @@ static void parse_complete(parser_ctx_t*);
 static void source_add_statement(parser_ctx_t*,statement_t*);
 
 static expression_t *new_bool_expression(parser_ctx_t*,VARIANT_BOOL);
+static expression_t *new_string_expression(parser_ctx_t*,const WCHAR*);
 
 static member_expression_t *new_member_expression(parser_ctx_t*,expression_t*,const WCHAR*);
 
@@ -113,6 +114,7 @@ Expression
 LiteralExpression
     : tTRUE                         { $$ = new_bool_expression(ctx, VARIANT_TRUE); CHECK_ERROR; }
     | tFALSE                        { $$ = new_bool_expression(ctx, VARIANT_FALSE); CHECK_ERROR; }
+    | tString                       { $$ = new_string_expression(ctx, $1); CHECK_ERROR; }
 
 %%
 
@@ -161,6 +163,18 @@ static expression_t *new_bool_expression(parser_ctx_t *ctx, VARIANT_BOOL value)
     return &expr->expr;
 }
 
+static expression_t *new_string_expression(parser_ctx_t *ctx, const WCHAR *value)
+{
+    string_expression_t *expr;
+
+    expr = new_expression(ctx, EXPR_STRING, sizeof(*expr));
+    if(!expr)
+        return NULL;
+
+    expr->value = value;
+    return &expr->expr;
+}
+
 static member_expression_t *new_member_expression(parser_ctx_t *ctx, expression_t *obj_expr, const WCHAR *identifier)
 {
     member_expression_t *expr;



More information about the wine-tests-results mailing list