[JSCRIPT]
authorAmine Khaldi <amine.khaldi@reactos.org>
Fri, 20 Sep 2013 12:14:54 +0000 (12:14 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Fri, 20 Sep 2013 12:14:54 +0000 (12:14 +0000)
* Sync with Wine 1.7.1.
CORE-7469

svn path=/trunk/; revision=60246

23 files changed:
reactos/dll/win32/jscript/CMakeLists.txt
reactos/dll/win32/jscript/activex.c
reactos/dll/win32/jscript/array.c
reactos/dll/win32/jscript/compile.c
reactos/dll/win32/jscript/date.c
reactos/dll/win32/jscript/dispex.c
reactos/dll/win32/jscript/engine.c
reactos/dll/win32/jscript/error.c
reactos/dll/win32/jscript/function.c
reactos/dll/win32/jscript/global.c
reactos/dll/win32/jscript/jscript.h
reactos/dll/win32/jscript/jscript_main.c
reactos/dll/win32/jscript/jsregexp.c
reactos/dll/win32/jscript/jsstr.c
reactos/dll/win32/jscript/jsstr.h
reactos/dll/win32/jscript/jsutils.c
reactos/dll/win32/jscript/number.c
reactos/dll/win32/jscript/object.c
reactos/dll/win32/jscript/parser.tab.c
reactos/dll/win32/jscript/parser.tab.h
reactos/dll/win32/jscript/parser.y
reactos/dll/win32/jscript/string.c
reactos/media/doc/README.WINE

index a6e47ec..4ff3d89 100644 (file)
@@ -1,13 +1,9 @@
 
-remove_definitions(-D_WIN32_WINNT=0x502)
-add_definitions(-D_WIN32_WINNT=0x600)
-
 add_definitions(
     -D__WINESRC__
     -D_USE_MATH_DEFINES)
 
 include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine)
-
 spec2def(jscript.dll jscript.spec)
 
 list(APPEND SOURCE
@@ -37,11 +33,6 @@ list(APPEND SOURCE
     vbarray.c
     ${CMAKE_CURRENT_BINARY_DIR}/jscript.def)
 
-add_library(jscript SHARED ${SOURCE} rsrc.rc)
-add_idl_headers(jscript_idlheader jscript_classes.idl)
-
-add_typelib(jsglobal.idl)
-
 list(APPEND jscript_rc_deps
     ${CMAKE_CURRENT_SOURCE_DIR}/jscript.rgs
     ${CMAKE_CURRENT_SOURCE_DIR}/jscript_classes.rgs
@@ -49,16 +40,10 @@ list(APPEND jscript_rc_deps
 
 set_source_files_properties(rsrc.rc PROPERTIES OBJECT_DEPENDS "${jscript_rc_deps}")
 
-# jsglobal.tlb needs stdole2.tlb
-add_dependencies(jscript jscript_idlheader stdole2)
-
-
-if(NOT MSVC)
-    # FIXME: http://www.cmake.org/Bug/view.php?id=12998
-    #allow_warnings(jscript)
-    set_source_files_properties(${SOURCE} PROPERTIES COMPILE_FLAGS "-Wno-error")
-endif()
-
+add_library(jscript SHARED ${SOURCE} rsrc.rc)
+add_idl_headers(jscript_idlheader jscript_classes.idl)
+add_typelib(jsglobal.idl)
+add_dependencies(jscript jscript_idlheader stdole2) # jsglobal.tlb needs stdole2.tlb
 set_module_type(jscript win32dll)
 target_link_libraries(jscript wine)
 add_importlibs(jscript user32 ole32 oleaut32 advapi32 msvcrt kernel32 ntdll)
index b8e9a71..36f52ba 100644 (file)
@@ -143,7 +143,8 @@ static IUnknown *create_activex_object(script_ctx_t *ctx, const WCHAR *progid)
 static HRESULT ActiveXObject_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
         jsval_t *r)
 {
-    jsstr_t * progid;
+    jsstr_t * progid_str;
+    const WCHAR *progid;
     IDispatch *disp;
     IUnknown *obj;
     HRESULT hres;
@@ -166,12 +167,12 @@ static HRESULT ActiveXObject_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag
         return E_NOTIMPL;
     }
 
-    hres = to_string(ctx, argv[0], &progid);
+    hres = to_flat_string(ctx, argv[0], &progid_str, &progid);
     if(FAILED(hres))
         return hres;
 
-    obj = create_activex_object(ctx, progid->str);
-    jsstr_release(progid);
+    obj = create_activex_object(ctx, progid);
+    jsstr_release(progid_str);
     if(!obj)
         return throw_generic_error(ctx, JS_E_CANNOT_CREATE_OBJ, NULL);
 
index 09b1a01..3b05c1d 100644 (file)
@@ -234,7 +234,7 @@ static HRESULT Array_concat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
 
 static HRESULT array_join(script_ctx_t *ctx, jsdisp_t *array, DWORD length, const WCHAR *sep, jsval_t *r)
 {
-    jsstr_t **str_tab, *ret = NULL;
+    jsstr_t **str_tab, *ret;
     jsval_t val;
     DWORD i;
     HRESULT hres = E_FAIL;
@@ -267,7 +267,6 @@ static HRESULT array_join(script_ctx_t *ctx, jsdisp_t *array, DWORD length, cons
 
     if(SUCCEEDED(hres)) {
         DWORD seplen = 0, len = 0;
-        WCHAR *ptr;
 
         seplen = strlenW(sep);
 
@@ -283,25 +282,26 @@ static HRESULT array_join(script_ctx_t *ctx, jsdisp_t *array, DWORD length, cons
             }
         }
 
-        if(SUCCEEDED(hres))
-            ret = jsstr_alloc_buf(len);
-        if(ret) {
-            ptr = ret->str;
+        if(SUCCEEDED(hres)) {
+            WCHAR *ptr = NULL;
 
-            if(str_tab[0])
-                ptr += jsstr_flush(str_tab[0], ptr);
+            ptr = jsstr_alloc_buf(len, &ret);
+            if(ptr) {
+                if(str_tab[0])
+                    ptr += jsstr_flush(str_tab[0], ptr);
 
-            for(i=1; i < length; i++) {
-                if(seplen) {
-                    memcpy(ptr, sep, seplen*sizeof(WCHAR));
-                    ptr += seplen;
-                }
+                for(i=1; i < length; i++) {
+                    if(seplen) {
+                        memcpy(ptr, sep, seplen*sizeof(WCHAR));
+                        ptr += seplen;
+                    }
 
-                if(str_tab[i])
-                    ptr += jsstr_flush(str_tab[i], ptr);
+                    if(str_tab[i])
+                        ptr += jsstr_flush(str_tab[i], ptr);
+                }
+            }else {
+                hres = E_OUTOFMEMORY;
             }
-        }else {
-            hres = E_OUTOFMEMORY;
         }
     }
 
@@ -337,15 +337,16 @@ static HRESULT Array_join(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigne
         return hres;
 
     if(argc) {
-        jsstr_t *sep;
+        const WCHAR *sep;
+        jsstr_t *sep_str;
 
-        hres = to_string(ctx, argv[0], &sep);
+        hres = to_flat_string(ctx, argv[0], &sep_str, &sep);
         if(FAILED(hres))
             return hres;
 
-        hres = array_join(ctx, jsthis, length, sep->str, r);
+        hres = array_join(ctx, jsthis, length, sep, r);
 
-        jsstr_release(sep);
+        jsstr_release(sep_str);
     }else {
         hres = array_join(ctx, jsthis, length, default_separatorW, r);
     }
index 10bed1c..3d9ad74 100644 (file)
@@ -771,6 +771,7 @@ static HRESULT compile_literal(compiler_ctx_t *ctx, literal_t *literal)
     }
     DEFAULT_UNREACHABLE;
     }
+    return E_FAIL;
 }
 
 static HRESULT literal_as_bstr(compiler_ctx_t *ctx, literal_t *literal, BSTR *str)
index 01db2c9..f48d4e9 100644 (file)
@@ -492,7 +492,7 @@ static inline HRESULT date_to_string(DOUBLE time, BOOL show_offset, int offset,
 
     BOOL formatAD = TRUE;
     WCHAR week[64], month[64];
-    jsstr_t *date_str;
+    jsstr_t *date_jsstr;
     int len, size, year, day;
     DWORD lcid_en;
     WCHAR sign = '-';
@@ -504,6 +504,8 @@ static inline HRESULT date_to_string(DOUBLE time, BOOL show_offset, int offset,
     }
 
     if(r) {
+        WCHAR *date_str;
+
         len = 21;
 
         lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
@@ -544,25 +546,25 @@ static inline HRESULT date_to_string(DOUBLE time, BOOL show_offset, int offset,
             offset = -offset;
         }
 
-        date_str = jsstr_alloc_buf(len);
+        date_str = jsstr_alloc_buf(len, &date_jsstr);
         if(!date_str)
             return E_OUTOFMEMORY;
 
         if(!show_offset)
-            sprintfW(date_str->str, formatNoOffsetW, week, month, day,
+            sprintfW(date_str, formatNoOffsetW, week, month, day,
                     (int)hour_from_time(time), (int)min_from_time(time),
                     (int)sec_from_time(time), year, formatAD?ADW:BCW);
         else if(offset)
-            sprintfW(date_str->str, formatW, week, month, day,
+            sprintfW(date_str, formatW, week, month, day,
                     (int)hour_from_time(time), (int)min_from_time(time),
                     (int)sec_from_time(time), sign, offset/60, offset%60,
                     year, formatAD?ADW:BCW);
         else
-            sprintfW(date_str->str, formatUTCW, week, month, day,
+            sprintfW(date_str, formatUTCW, week, month, day,
                     (int)hour_from_time(time), (int)min_from_time(time),
                     (int)sec_from_time(time), year, formatAD?ADW:BCW);
 
-        *r = jsval_string(date_str);
+        *r = jsval_string(date_jsstr);
     }
     return S_OK;
 }
@@ -618,14 +620,18 @@ static HRESULT Date_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag
         return dateobj_to_string(date, r);
 
     if(r) {
+        WCHAR *ptr;
+
         date_len = GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, NULL, 0);
         time_len = GetTimeFormatW(ctx->lcid, 0, &st, NULL, NULL, 0);
-        date_str = jsstr_alloc_buf(date_len+time_len-1);
+
+        ptr = jsstr_alloc_buf(date_len+time_len-1, &date_str);
         if(!date_str)
             return E_OUTOFMEMORY;
-        GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, date_str->str, date_len);
-        GetTimeFormatW(ctx->lcid, 0, &st, NULL, date_str->str+date_len, time_len);
-        date_str->str[date_len-1] = ' ';
+
+        GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, ptr, date_len);
+        GetTimeFormatW(ctx->lcid, 0, &st, NULL, ptr+date_len, time_len);
+        ptr[date_len-1] = ' ';
 
         *r = jsval_string(date_str);
     }
@@ -681,6 +687,8 @@ static inline HRESULT create_utc_string(script_ctx_t *ctx, vdisp_t *jsthis, jsva
     }
 
     if(r) {
+        WCHAR *ptr;
+
         len = 17;
 
         lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
@@ -713,11 +721,11 @@ static inline HRESULT create_utc_string(script_ctx_t *ctx, vdisp_t *jsthis, jsva
         } while(day);
         day = date_from_time(date->time);
 
-        date_str = jsstr_alloc_buf(len);
+        ptr = jsstr_alloc_buf(len, &date_str);
         if(!date_str)
             return E_OUTOFMEMORY;
 
-        sprintfW(date_str->str, formatAD?formatADW:formatBCW, week, day, month, year,
+        sprintfW(ptr, formatAD?formatADW:formatBCW, week, day, month, year,
                 (int)hour_from_time(date->time), (int)min_from_time(date->time),
                 (int)sec_from_time(date->time));
 
@@ -773,6 +781,8 @@ static HRESULT dateobj_to_date_string(DateInstance *date, jsval_t *r)
     time = local_time(date->time, date);
 
     if(r) {
+        WCHAR *ptr;
+
         len = 5;
 
         lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
@@ -807,10 +817,10 @@ static HRESULT dateobj_to_date_string(DateInstance *date, jsval_t *r)
         } while(day);
         day = date_from_time(time);
 
-        date_str = jsstr_alloc_buf(len);
-        if(!date_str)
+        ptr = jsstr_alloc_buf(len, &date_str);
+        if(!ptr)
             return E_OUTOFMEMORY;
-        sprintfW(date_str->str, formatAD?formatADW:formatBCW, week, month, day, year);
+        sprintfW(ptr, formatAD?formatADW:formatBCW, week, month, day, year);
 
         *r = jsval_string(date_str);
     }
@@ -856,7 +866,9 @@ static HRESULT Date_toTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
     time = local_time(date->time, date);
 
     if(r) {
-        date_str = jsstr_alloc_buf(17);
+        WCHAR *ptr;
+
+        ptr = jsstr_alloc_buf(17, &date_str);
         if(!date_str)
             return E_OUTOFMEMORY;
 
@@ -870,11 +882,11 @@ static HRESULT Date_toTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
         else sign = '-';
 
         if(offset)
-            sprintfW(date_str->str, formatW, (int)hour_from_time(time),
+            sprintfW(ptr, formatW, (int)hour_from_time(time),
                     (int)min_from_time(time), (int)sec_from_time(time),
                     sign, offset/60, offset%60);
         else
-            sprintfW(date_str->str, formatUTCW, (int)hour_from_time(time),
+            sprintfW(ptr, formatUTCW, (int)hour_from_time(time),
                     (int)min_from_time(time), (int)sec_from_time(time));
 
         *r = jsval_string(date_str);
@@ -908,11 +920,13 @@ static HRESULT Date_toLocaleDateString(script_ctx_t *ctx, vdisp_t *jsthis, WORD
         return dateobj_to_date_string(date, r);
 
     if(r) {
+        WCHAR *ptr;
+
         len = GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, NULL, 0);
-        date_str = jsstr_alloc_buf(len);
-        if(!date_str)
+        ptr = jsstr_alloc_buf(len, &date_str);
+        if(!ptr)
             return E_OUTOFMEMORY;
-        GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, date_str->str, len);
+        GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, ptr, len);
 
         *r = jsval_string(date_str);
     }
@@ -945,11 +959,13 @@ static HRESULT Date_toLocaleTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD
         return Date_toTimeString(ctx, jsthis, flags, argc, argv, r);
 
     if(r) {
+        WCHAR *ptr;
+
         len = GetTimeFormatW(ctx->lcid, 0, &st, NULL, NULL, 0);
-        date_str = jsstr_alloc_buf(len);
-        if(!date_str)
+        ptr = jsstr_alloc_buf(len, &date_str);
+        if(!ptr)
             return E_OUTOFMEMORY;
-        GetTimeFormatW(ctx->lcid, 0, &st, NULL, date_str->str, len);
+        GetTimeFormatW(ctx->lcid, 0, &st, NULL, ptr, len);
 
         *r = jsval_string(date_str);
     }
@@ -2038,7 +2054,9 @@ static inline HRESULT date_parse(jsstr_t *input_str, double *ret) {
     DWORD lcid_en;
 
     input_len = jsstr_length(input_str);
-    input = input_str->str;
+    input = jsstr_flatten(input_str);
+    if(!input)
+        return E_OUTOFMEMORY;
 
     for(i=0; i<input_len; i++) {
         if(input[i] == '(') nest_level++;
index 763df13..96280be 100644 (file)
@@ -1524,8 +1524,15 @@ HRESULT disp_delete_name(script_ctx_t *ctx, IDispatch *disp, jsstr_t *name, BOOL
     jsdisp = iface_to_jsdisp((IUnknown*)disp);
     if(jsdisp) {
         dispex_prop_t *prop;
+        const WCHAR *ptr;
+
+        ptr = jsstr_flatten(name);
+        if(!ptr) {
+            jsdisp_release(jsdisp);
+            return E_OUTOFMEMORY;
+        }
 
-        hres = find_prop_name(jsdisp, string_hash(name->str), name->str, &prop);
+        hres = find_prop_name(jsdisp, string_hash(ptr), ptr, &prop);
         if(prop) {
             hres = delete_prop(prop, ret);
         }else {
index bec0d11..c82678f 100644 (file)
@@ -346,7 +346,7 @@ void exec_release(exec_ctx_t *ctx)
     heap_free(ctx);
 }
 
-static HRESULT disp_get_id(script_ctx_t *ctx, IDispatch *disp, WCHAR *name, BSTR name_bstr, DWORD flags, DISPID *id)
+static HRESULT disp_get_id(script_ctx_t *ctx, IDispatch *disp, const WCHAR *name, BSTR name_bstr, DWORD flags, DISPID *id)
 {
     IDispatchEx *dispex;
     jsdisp_t *jsdisp;
@@ -375,7 +375,7 @@ static HRESULT disp_get_id(script_ctx_t *ctx, IDispatch *disp, WCHAR *name, BSTR
         IDispatchEx_Release(dispex);
     }else {
         TRACE("using IDispatch\n");
-        hres = IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, id);
+        hres = IDispatch_GetIDsOfNames(disp, &IID_NULL, &bstr, 1, 0, id);
     }
 
     if(name_bstr != bstr)
@@ -729,10 +729,12 @@ static HRESULT interp_throw_type(exec_ctx_t *ctx)
 {
     const HRESULT hres = get_op_uint(ctx, 0);
     jsstr_t *str = get_op_str(ctx, 1);
+    const WCHAR *ptr;
 
     TRACE("%08x %s\n", hres, debugstr_jsstr(str));
 
-    return throw_type_error(ctx->script, hres, str->str);
+    ptr = jsstr_flatten(str);
+    return ptr ? throw_type_error(ctx->script, hres, ptr) : E_OUTOFMEMORY;
 }
 
 /* ECMA-262 3rd Edition    12.14 */
@@ -828,9 +830,10 @@ static HRESULT interp_func(exec_ctx_t *ctx)
 /* ECMA-262 3rd Edition    11.2.1 */
 static HRESULT interp_array(exec_ctx_t *ctx)
 {
+    jsstr_t *name_str;
+    const WCHAR *name;
     jsval_t v, namev;
     IDispatch *obj;
-    jsstr_t *name;
     DISPID id;
     HRESULT hres;
 
@@ -844,15 +847,15 @@ static HRESULT interp_array(exec_ctx_t *ctx)
         return hres;
     }
 
-    hres = to_string(ctx->script, namev, &name);
+    hres = to_flat_string(ctx->script, namev, &name_str, &name);
     jsval_release(namev);
     if(FAILED(hres)) {
         IDispatch_Release(obj);
         return hres;
     }
 
-    hres = disp_get_id(ctx->script, obj, name->str, NULL, 0, &id);
-    jsstr_release(name);
+    hres = disp_get_id(ctx->script, obj, name, NULL, 0, &id);
+    jsstr_release(name_str);
     if(SUCCEEDED(hres)) {
         hres = disp_propget(ctx->script, obj, id, &v);
     }else if(hres == DISP_E_UNKNOWNNAME) {
@@ -900,8 +903,9 @@ static HRESULT interp_memberid(exec_ctx_t *ctx)
 {
     const unsigned arg = get_op_uint(ctx, 0);
     jsval_t objv, namev;
+    const WCHAR *name;
+    jsstr_t *name_str;
     IDispatch *obj;
-    jsstr_t *name;
     DISPID id;
     HRESULT hres;
 
@@ -913,7 +917,7 @@ static HRESULT interp_memberid(exec_ctx_t *ctx)
     hres = to_object(ctx->script, objv, &obj);
     jsval_release(objv);
     if(SUCCEEDED(hres)) {
-        hres = to_string(ctx->script, namev, &name);
+        hres = to_flat_string(ctx->script, namev, &name_str, &name);
         if(FAILED(hres))
             IDispatch_Release(obj);
     }
@@ -921,8 +925,8 @@ static HRESULT interp_memberid(exec_ctx_t *ctx)
     if(FAILED(hres))
         return hres;
 
-    hres = disp_get_id(ctx->script, obj, name->str, NULL, arg, &id);
-    jsstr_release(name);
+    hres = disp_get_id(ctx->script, obj, name, NULL, arg, &id);
+    jsstr_release(name_str);
     if(FAILED(hres)) {
         IDispatch_Release(obj);
         if(hres == DISP_E_UNKNOWNNAME && !(arg & fdexNameEnsure)) {
@@ -1392,10 +1396,11 @@ static HRESULT interp_instanceof(exec_ctx_t *ctx)
 /* ECMA-262 3rd Edition    11.8.7 */
 static HRESULT interp_in(exec_ctx_t *ctx)
 {
+    const WCHAR *str;
+    jsstr_t *jsstr;
     jsval_t obj, v;
     DISPID id = 0;
     BOOL ret;
-    jsstr_t *str;
     HRESULT hres;
 
     TRACE("\n");
@@ -1407,16 +1412,16 @@ static HRESULT interp_in(exec_ctx_t *ctx)
     }
 
     v = stack_pop(ctx);
-    hres = to_string(ctx->script, v, &str);
+    hres = to_flat_string(ctx->script, v, &jsstr, &str);
     jsval_release(v);
     if(FAILED(hres)) {
         IDispatch_Release(get_object(obj));
         return hres;
     }
 
-    hres = disp_get_id(ctx->script, get_object(obj), str->str, NULL, 0, &id);
+    hres = disp_get_id(ctx->script, get_object(obj), str, NULL, 0, &id);
     IDispatch_Release(get_object(obj));
-    jsstr_release(str);
+    jsstr_release(jsstr);
     if(SUCCEEDED(hres))
         ret = TRUE;
     else if(hres == DISP_E_UNKNOWNNAME)
@@ -2001,11 +2006,11 @@ static HRESULT interp_eq2(exec_ctx_t *ctx)
     BOOL b;
     HRESULT hres;
 
-    TRACE("\n");
-
     r = stack_pop(ctx);
     l = stack_pop(ctx);
 
+    TRACE("%s === %s\n", debugstr_jsval(l), debugstr_jsval(r));
+
     hres = equal2_values(r, l, &b);
     jsval_release(l);
     jsval_release(r);
index 34c26fe..aa5e9d7 100644 (file)
@@ -82,12 +82,16 @@ static HRESULT Error_toString(script_ctx_t *ctx, vdisp_t *vthis, WORD flags,
         unsigned msg_len = msg ? jsstr_length(msg) : 0;
 
         if(name_len && msg_len) {
-            ret = jsstr_alloc_buf(name_len + msg_len + 2);
-            if(ret) {
-                jsstr_flush(name, ret->str);
-                ret->str[name_len] = ':';
-                ret->str[name_len+1] = ' ';
-                jsstr_flush(msg, ret->str+name_len+2);
+            WCHAR *ptr;
+
+            ptr = jsstr_alloc_buf(name_len + msg_len + 2, &ret);
+            if(ptr) {
+                jsstr_flush(name, ptr);
+                ptr[name_len] = ':';
+                ptr[name_len+1] = ' ';
+                jsstr_flush(msg, ptr+name_len+2);
+            }else {
+                hres = E_OUTOFMEMORY;
             }
         }else if(name_len) {
             ret = name;
index fd70a39..9ff7bb8 100644 (file)
@@ -318,15 +318,16 @@ static HRESULT function_to_string(FunctionInstance *function, jsstr_t **ret)
 
     if(function->value_proc) {
         DWORD name_len;
+        WCHAR *ptr;
 
         name_len = strlenW(function->name);
-        str = jsstr_alloc_buf((sizeof(native_prefixW)+sizeof(native_suffixW))/sizeof(WCHAR) + name_len);
-        if(!str)
+        ptr = jsstr_alloc_buf((sizeof(native_prefixW)+sizeof(native_suffixW))/sizeof(WCHAR) + name_len, &str);
+        if(!ptr)
             return E_OUTOFMEMORY;
 
-        memcpy(str->str, native_prefixW, sizeof(native_prefixW));
-        memcpy(str->str + sizeof(native_prefixW)/sizeof(WCHAR), function->name, name_len*sizeof(WCHAR));
-        memcpy(str->str + sizeof(native_prefixW)/sizeof(WCHAR) + name_len, native_suffixW, sizeof(native_suffixW));
+        memcpy(ptr, native_prefixW, sizeof(native_prefixW));
+        memcpy(ptr += sizeof(native_prefixW)/sizeof(WCHAR), function->name, name_len*sizeof(WCHAR));
+        memcpy(ptr + name_len, native_suffixW, sizeof(native_suffixW));
     }else {
         str = jsstr_alloc_len(function->func_code->source, function->func_code->source_len);
         if(!str)
index a444200..160b147 100644 (file)
@@ -278,7 +278,7 @@ static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u
         jsval_t *r)
 {
     jsstr_t *ret_str, *str;
-    const WCHAR *ptr;
+    const WCHAR *ptr, *buf;
     DWORD len = 0;
     WCHAR *ret;
     HRESULT hres;
@@ -291,11 +291,11 @@ static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u
         return S_OK;
     }
 
-    hres = to_string(ctx, argv[0], &str);
+    hres = to_flat_string(ctx, argv[0], &str, &buf);
     if(FAILED(hres))
         return hres;
 
-    for(ptr = str->str; *ptr; ptr++) {
+    for(ptr = buf; *ptr; ptr++) {
         if(*ptr > 0xff)
             len += 6;
         else if(is_ecma_nonblank(*ptr))
@@ -304,15 +304,14 @@ static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u
             len += 3;
     }
 
-    ret_str = jsstr_alloc_buf(len);
-    if(!ret_str) {
+    ret = jsstr_alloc_buf(len, &ret_str);
+    if(!ret) {
         jsstr_release(str);
         return E_OUTOFMEMORY;
     }
 
     len = 0;
-    ret = ret_str->str;
-    for(ptr = str->str; *ptr; ptr++) {
+    for(ptr = buf; *ptr; ptr++) {
         if(*ptr > 0xff) {
             ret[len++] = '%';
             ret[len++] = 'u';
@@ -344,6 +343,7 @@ static HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns
         jsval_t *r)
 {
     bytecode_t *code;
+    const WCHAR *src;
     HRESULT hres;
 
     TRACE("\n");
@@ -365,8 +365,12 @@ static HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns
         return E_UNEXPECTED;
     }
 
+    src = jsstr_flatten(get_string(argv[0]));
+    if(!src)
+        return E_OUTOFMEMORY;
+
     TRACE("parsing %s\n", debugstr_jsval(argv[0]));
-    hres = compile_script(ctx, get_string(argv[0])->str, NULL, NULL, TRUE, FALSE, &code);
+    hres = compile_script(ctx, src, NULL, NULL, TRUE, FALSE, &code);
     if(FAILED(hres)) {
         WARN("parse (%s) failed: %08x\n", debugstr_jsval(argv[0]), hres);
         return throw_syntax_error(ctx, hres, NULL);
@@ -439,10 +443,10 @@ static HRESULT JSGlobal_parseInt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
         jsval_t *r)
 {
     BOOL neg = FALSE, empty = TRUE;
+    const WCHAR *ptr;
     DOUBLE ret = 0.0;
     INT radix=0, i;
     jsstr_t *str;
-    WCHAR *ptr;
     HRESULT hres;
 
     if(!argc) {
@@ -464,11 +468,12 @@ static HRESULT JSGlobal_parseInt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
         }
     }
 
-    hres = to_string(ctx, argv[0], &str);
+    hres = to_flat_string(ctx, argv[0], &str, &ptr);
     if(FAILED(hres))
         return hres;
 
-    for(ptr = str->str; isspaceW(*ptr); ptr++);
+    while(isspaceW(*ptr))
+        ptr++;
 
     switch(*ptr) {
     case '+':
@@ -521,7 +526,7 @@ static HRESULT JSGlobal_parseFloat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag
     LONGLONG d = 0, hlp;
     jsstr_t *val_str;
     int exp = 0;
-    WCHAR *str;
+    const WCHAR *str;
     BOOL ret_nan = TRUE, positive = TRUE;
     HRESULT hres;
 
@@ -531,12 +536,10 @@ static HRESULT JSGlobal_parseFloat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag
         return S_OK;
     }
 
-    hres = to_string(ctx, argv[0], &val_str);
+    hres = to_flat_string(ctx, argv[0], &val_str, &str);
     if(FAILED(hres))
         return hres;
 
-    str = val_str->str;
-
     while(isspaceW(*str)) str++;
 
     if(*str == '+')
@@ -626,7 +629,7 @@ static HRESULT JSGlobal_unescape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
         jsval_t *r)
 {
     jsstr_t *ret_str, *str;
-    const WCHAR *ptr;
+    const WCHAR *ptr, *buf;
     DWORD len = 0;
     WCHAR *ret;
     HRESULT hres;
@@ -639,11 +642,11 @@ static HRESULT JSGlobal_unescape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
         return S_OK;
     }
 
-    hres = to_string(ctx, argv[0], &str);
+    hres = to_flat_string(ctx, argv[0], &str, &buf);
     if(FAILED(hres))
         return hres;
 
-    for(ptr = str->str; *ptr; ptr++) {
+    for(ptr = buf; *ptr; ptr++) {
         if(*ptr == '%') {
             if(hex_to_int(*(ptr+1))!=-1 && hex_to_int(*(ptr+2))!=-1)
                 ptr += 2;
@@ -655,15 +658,14 @@ static HRESULT JSGlobal_unescape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
         len++;
     }
 
-    ret_str = jsstr_alloc_buf(len);
-    if(!ret_str) {
+    ret = jsstr_alloc_buf(len, &ret_str);
+    if(!ret) {
         jsstr_release(str);
         return E_OUTOFMEMORY;
     }
 
-    ret = ret_str->str;
     len = 0;
-    for(ptr = str->str; *ptr; ptr++) {
+    for(ptr = buf; *ptr; ptr++) {
         if(*ptr == '%') {
             if(hex_to_int(*(ptr+1))!=-1 && hex_to_int(*(ptr+2))!=-1) {
                 ret[len] = (hex_to_int(*(ptr+1))<<4) + hex_to_int(*(ptr+2));
@@ -760,8 +762,8 @@ static HRESULT JSGlobal_CollectGarbage(script_ctx_t *ctx, vdisp_t *jsthis, WORD
 static HRESULT JSGlobal_encodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
         jsval_t *r)
 {
+    const WCHAR *ptr, *uri;
     jsstr_t *str, *ret;
-    const WCHAR *ptr;
     DWORD len = 0, i;
     char buf[4];
     WCHAR *rptr;
@@ -775,11 +777,11 @@ static HRESULT JSGlobal_encodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
         return S_OK;
     }
 
-    hres = to_string(ctx, argv[0], &str);
+    hres = to_flat_string(ctx, argv[0], &str, &uri);
     if(FAILED(hres))
         return hres;
 
-    for(ptr = str->str; *ptr; ptr++) {
+    for(ptr = uri; *ptr; ptr++) {
         if(is_uri_unescaped(*ptr) || is_uri_reserved(*ptr) || *ptr == '#') {
             len++;
         }else {
@@ -793,14 +795,13 @@ static HRESULT JSGlobal_encodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
         }
     }
 
-    ret = jsstr_alloc_buf(len);
-    if(!ret) {
+    rptr = jsstr_alloc_buf(len, &ret);
+    if(!rptr) {
         jsstr_release(str);
         return E_OUTOFMEMORY;
     }
-    rptr = ret->str;
 
-    for(ptr = str->str; *ptr; ptr++) {
+    for(ptr = uri; *ptr; ptr++) {
         if(is_uri_unescaped(*ptr) || is_uri_reserved(*ptr) || *ptr == '#') {
             *rptr++ = *ptr;
         }else {
@@ -826,9 +827,11 @@ static HRESULT JSGlobal_encodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
 static HRESULT JSGlobal_decodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
         jsval_t *r)
 {
-    jsstr_t *str, *ret;
-    WCHAR *ptr;
-    int i, len = 0, val, res;
+    const WCHAR *ptr, *uri;
+    jsstr_t *str, *ret_str;
+    unsigned len = 0;
+    int i, val, res;
+    WCHAR *ret;
     char buf[4];
     WCHAR out;
     HRESULT hres;
@@ -841,11 +844,11 @@ static HRESULT JSGlobal_decodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
         return S_OK;
     }
 
-    hres = to_string(ctx, argv[0], &str);
+    hres = to_flat_string(ctx, argv[0], &str, &uri);
     if(FAILED(hres))
         return hres;
 
-    for(ptr = str->str; *ptr; ptr++) {
+    for(ptr = uri; *ptr; ptr++) {
         if(*ptr != '%') {
             len++;
         }else {
@@ -871,17 +874,15 @@ static HRESULT JSGlobal_decodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
         }
     }
 
-    ret = jsstr_alloc_buf(len);
+    ret = jsstr_alloc_buf(len, &ret_str);
     if(!ret) {
         jsstr_release(str);
         return E_OUTOFMEMORY;
     }
 
-    len = 0;
-    for(ptr = str->str; *ptr; ptr++) {
+    for(ptr = uri; *ptr; ptr++) {
         if(*ptr != '%') {
-            ret->str[len] = *ptr;
-            len++;
+            *ret++ = *ptr;
         }else {
             for(i=0; i<4; i++) {
                 if(ptr[i*3]!='%' || hex_to_int(ptr[i*3+1])==-1 || (val=hex_to_int(ptr[i*3+2]))==-1)
@@ -889,33 +890,34 @@ static HRESULT JSGlobal_decodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
                 val += hex_to_int(ptr[i*3+1])<<4;
                 buf[i] = val;
 
-                res = MultiByteToWideChar(CP_UTF8, 0, buf, i+1, ret->str+len, 1);
+                res = MultiByteToWideChar(CP_UTF8, 0, buf, i+1, ret, 1);
                 if(res)
                     break;
             }
 
             ptr += i*3+2;
-            len++;
+            ret++;
         }
     }
 
-    TRACE("%s -> %s\n", debugstr_jsstr(str), debugstr_jsstr(ret));
+    TRACE("%s -> %s\n", debugstr_jsstr(str), debugstr_jsstr(ret_str));
     jsstr_release(str);
 
     if(r)
-        *r = jsval_string(ret);
+        *r = jsval_string(ret_str);
     else
-        jsstr_release(ret);
+        jsstr_release(ret_str);
     return S_OK;
 }
 
 static HRESULT JSGlobal_encodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
         jsval_t *r)
 {
-    jsstr_t *str, *ret;
+    jsstr_t *str, *ret_str;
     char buf[4];
-    const WCHAR *ptr;
+    const WCHAR *ptr, *uri;
     DWORD len = 0, size, i;
+    WCHAR *ret;
     HRESULT hres;
 
     TRACE("\n");
@@ -926,11 +928,11 @@ static HRESULT JSGlobal_encodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W
         return S_OK;
     }
 
-    hres = to_string(ctx, argv[0], &str);
+    hres = to_flat_string(ctx, argv[0], &str, &uri);
     if(FAILED(hres))
         return hres;
 
-    for(ptr = str->str; *ptr; ptr++) {
+    for(ptr = uri; *ptr; ptr++) {
         if(is_uri_unescaped(*ptr))
             len++;
         else {
@@ -943,22 +945,21 @@ static HRESULT JSGlobal_encodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W
         }
     }
 
-    ret = jsstr_alloc_buf(len);
+    ret = jsstr_alloc_buf(len, &ret_str);
     if(!ret) {
         jsstr_release(str);
         return E_OUTOFMEMORY;
     }
 
-    len = 0;
-    for(ptr = str->str; *ptr; ptr++) {
+    for(ptr = uri; *ptr; ptr++) {
         if(is_uri_unescaped(*ptr)) {
-            ret->str[len++] = *ptr;
+            *ret++ = *ptr;
         }else {
             size = WideCharToMultiByte(CP_UTF8, 0, ptr, 1, buf, sizeof(buf), NULL, NULL);
             for(i=0; i<size; i++) {
-                ret->str[len++] = '%';
-                ret->str[len++] = int_to_char((BYTE)buf[i] >> 4);
-                ret->str[len++] = int_to_char(buf[i] & 0x0f);
+                *ret++ = '%';
+                *ret++ = int_to_char((BYTE)buf[i] >> 4);
+                *ret++ = int_to_char(buf[i] & 0x0f);
             }
         }
     }
@@ -966,9 +967,9 @@ static HRESULT JSGlobal_encodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W
     jsstr_release(str);
 
     if(r)
-        *r = jsval_string(ret);
+        *r = jsval_string(ret_str);
     else
-        jsstr_release(ret);
+        jsstr_release(ret_str);
     return S_OK;
 }
 
@@ -976,8 +977,8 @@ static HRESULT JSGlobal_encodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W
 static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
         jsval_t *r)
 {
+    const WCHAR *ptr, *uri;
     jsstr_t *str, *ret;
-    const WCHAR *ptr;
     WCHAR *out_ptr;
     DWORD len = 0;
     HRESULT hres;
@@ -990,11 +991,11 @@ static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W
         return S_OK;
     }
 
-    hres = to_string(ctx, argv[0], &str);
+    hres = to_flat_string(ctx, argv[0], &str, &uri);
     if(FAILED(hres))
         return hres;
 
-    ptr = str->str;
+    ptr = uri;
     while(*ptr) {
         if(*ptr == '%') {
             char octets[4];
@@ -1044,14 +1045,13 @@ static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W
         }
     }
 
-    ret = jsstr_alloc_buf(len);
+    out_ptr = jsstr_alloc_buf(len, &ret);
     if(!ret) {
         jsstr_release(str);
         return E_OUTOFMEMORY;
     }
-    out_ptr = ret->str;
 
-    ptr = str->str;
+    ptr = uri;
     while(*ptr) {
         if(*ptr == '%') {
             char octets[4];
index 4a3a483..787661c 100644 (file)
@@ -326,6 +326,7 @@ HRESULT to_integer(script_ctx_t*,jsval_t,double*) DECLSPEC_HIDDEN;
 HRESULT to_int32(script_ctx_t*,jsval_t,INT*) DECLSPEC_HIDDEN;
 HRESULT to_uint32(script_ctx_t*,jsval_t,UINT32*) DECLSPEC_HIDDEN;
 HRESULT to_string(script_ctx_t*,jsval_t,jsstr_t**) DECLSPEC_HIDDEN;
+HRESULT to_flat_string(script_ctx_t*,jsval_t,jsstr_t**,const WCHAR**) DECLSPEC_HIDDEN;
 HRESULT to_object(script_ctx_t*,jsval_t,IDispatch**) DECLSPEC_HIDDEN;
 
 HRESULT variant_change_type(script_ctx_t*,VARIANT*,VARIANT*,VARTYPE) DECLSPEC_HIDDEN;
index cf07cbf..df7f6a3 100644 (file)
@@ -144,6 +144,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
             return FALSE;
         break;
     case DLL_PROCESS_DETACH:
+        if (lpv) break;
         free_strings();
     }
 
index 09eaa7f..10c4ef2 100644 (file)
@@ -73,12 +73,12 @@ static void set_last_index(RegExpInstance *This, DWORD last_index)
 }
 
 static HRESULT do_regexp_match_next(script_ctx_t *ctx, RegExpInstance *regexp,
-        DWORD rem_flags, jsstr_t *str, match_state_t *ret)
+        DWORD rem_flags, jsstr_t *jsstr, const WCHAR *str, match_state_t *ret)
 {
     HRESULT hres;
 
     hres = regexp_execute(regexp->jsregexp, ctx, &ctx->tmp_heap,
-            str->str, jsstr_length(str), ret);
+            str, jsstr_length(jsstr), ret);
     if(FAILED(hres))
         return hres;
     if(hres == S_FALSE) {
@@ -87,9 +87,9 @@ static HRESULT do_regexp_match_next(script_ctx_t *ctx, RegExpInstance *regexp,
         return S_FALSE;
     }
 
-    if(!(rem_flags & REM_NO_CTX_UPDATE) && ctx->last_match != str) {
+    if(!(rem_flags & REM_NO_CTX_UPDATE) && ctx->last_match != jsstr) {
         jsstr_release(ctx->last_match);
-        ctx->last_match = jsstr_addref(str);
+        ctx->last_match = jsstr_addref(jsstr);
     }
 
     if(!(rem_flags & REM_NO_CTX_UPDATE)) {
@@ -109,10 +109,10 @@ static HRESULT do_regexp_match_next(script_ctx_t *ctx, RegExpInstance *regexp,
             memset(ctx->match_parens+n, 0, sizeof(ctx->match_parens) - n*sizeof(ctx->match_parens[0]));
     }
 
-    set_last_index(regexp, ret->cp-str->str);
+    set_last_index(regexp, ret->cp-str);
 
     if(!(rem_flags & REM_NO_CTX_UPDATE)) {
-        ctx->last_match_index = ret->cp-str->str-ret->match_len;
+        ctx->last_match_index = ret->cp-str-ret->match_len;
         ctx->last_match_length = ret->match_len;
     }
 
@@ -120,11 +120,12 @@ static HRESULT do_regexp_match_next(script_ctx_t *ctx, RegExpInstance *regexp,
 }
 
 HRESULT regexp_match_next(script_ctx_t *ctx, jsdisp_t *dispex,
-        DWORD rem_flags, jsstr_t *str, match_state_t **ret)
+        DWORD rem_flags, jsstr_t *jsstr, match_state_t **ret)
 {
     RegExpInstance *regexp = (RegExpInstance*)dispex;
     match_state_t *match;
     heap_pool_t *mark;
+    const WCHAR *str;
     HRESULT hres;
 
     if((rem_flags & REM_CHECK_GLOBAL) && !(regexp->jsregexp->flags & REG_GLOB)) {
@@ -133,8 +134,12 @@ HRESULT regexp_match_next(script_ctx_t *ctx, jsdisp_t *dispex,
         return S_FALSE;
     }
 
+    str = jsstr_flatten(jsstr);
+    if(!str)
+        return E_OUTOFMEMORY;
+
     if(rem_flags & REM_ALLOC_RESULT) {
-        match = alloc_match_state(regexp->jsregexp, NULL, str->str);
+        match = alloc_match_state(regexp->jsregexp, NULL, str);
         if(!match)
             return E_OUTOFMEMORY;
         *ret = match;
@@ -154,7 +159,7 @@ HRESULT regexp_match_next(script_ctx_t *ctx, jsdisp_t *dispex,
         match = *ret;
     }
 
-    hres = do_regexp_match_next(ctx, regexp, rem_flags, str, match);
+    hres = do_regexp_match_next(ctx, regexp, rem_flags, jsstr, str, match);
 
     if(rem_flags & REM_NO_PARENS) {
         (*ret)->cp = match->cp;
@@ -171,7 +176,7 @@ HRESULT regexp_match_next(script_ctx_t *ctx, jsdisp_t *dispex,
     return hres;
 }
 
-static HRESULT regexp_match(script_ctx_t *ctx, jsdisp_t *dispex, jsstr_t *str, BOOL gflag,
+static HRESULT regexp_match(script_ctx_t *ctx, jsdisp_t *dispex, jsstr_t *jsstr, BOOL gflag,
         match_result_t **match_result, DWORD *result_cnt)
 {
     RegExpInstance *This = (RegExpInstance*)dispex;
@@ -179,18 +184,23 @@ static HRESULT regexp_match(script_ctx_t *ctx, jsdisp_t *dispex, jsstr_t *str, B
     match_state_t *result;
     DWORD i=0, ret_size = 0;
     heap_pool_t *mark;
+    const WCHAR *str;
     HRESULT hres;
 
     mark = heap_pool_mark(&ctx->tmp_heap);
 
-    result = alloc_match_state(This->jsregexp, &ctx->tmp_heap, str->str);
+    str = jsstr_flatten(jsstr);
+    if(!str)
+        return E_OUTOFMEMORY;
+
+    result = alloc_match_state(This->jsregexp, &ctx->tmp_heap, str);
     if(!result) {
         heap_pool_clear(mark);
         return E_OUTOFMEMORY;
     }
 
     while(1) {
-        hres = do_regexp_match_next(ctx, This, 0, str, result);
+        hres = do_regexp_match_next(ctx, This, 0, jsstr, str, result);
         if(hres == S_FALSE) {
             hres = S_OK;
             break;
@@ -215,7 +225,7 @@ static HRESULT regexp_match(script_ctx_t *ctx, jsdisp_t *dispex, jsstr_t *str, B
             }
         }
 
-        ret[i].index = result->cp - str->str - result->match_len;
+        ret[i].index = result->cp - str - result->match_len;
         ret[i++].length = result->match_len;
 
         if(!gflag && !(This->jsregexp->flags & REG_GLOB)) {
@@ -323,13 +333,56 @@ static HRESULT RegExp_lastIndex(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
 static HRESULT RegExp_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
         jsval_t *r)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    RegExpInstance *regexp;
+    unsigned len, f;
+    jsstr_t *ret;
+    WCHAR *ptr;
+
+    TRACE("\n");
+
+    if(!is_vclass(jsthis, JSCLASS_REGEXP)) {
+        FIXME("Not a RegExp\n");
+        return E_NOTIMPL;
+    }
+
+    regexp = regexp_from_vdisp(jsthis);
+
+    if(!r)
+        return S_OK;
+
+    len = jsstr_length(regexp->str) + 2;
+
+    f = regexp->jsregexp->flags;
+    if(f & REG_FOLD)
+        len++;
+    if(f & REG_GLOB)
+        len++;
+    if(f & REG_MULTILINE)
+        len++;
+
+    ptr = jsstr_alloc_buf(len, &ret);
+    if(!ptr)
+        return E_OUTOFMEMORY;
+
+    *ptr++ = '/';
+    ptr += jsstr_flush(regexp->str, ptr);
+    *ptr++ = '/';
+
+    if(f & REG_FOLD)
+        *ptr++ = 'i';
+    if(f & REG_GLOB)
+        *ptr++ = 'g';
+    if(f & REG_MULTILINE)
+        *ptr++ = 'm';
+
+    *r = jsval_string(ret);
+    return S_OK;
 }
 
-static HRESULT create_match_array(script_ctx_t *ctx, jsstr_t *input,
+static HRESULT create_match_array(script_ctx_t *ctx, jsstr_t *input_str,
         const match_state_t *result, IDispatch **ret)
 {
+    const WCHAR *input;
     jsdisp_t *array;
     jsstr_t *str;
     DWORD i;
@@ -340,13 +393,17 @@ static HRESULT create_match_array(script_ctx_t *ctx, jsstr_t *input,
     static const WCHAR lastIndexW[] = {'l','a','s','t','I','n','d','e','x',0};
     static const WCHAR zeroW[] = {'0',0};
 
+    input = jsstr_flatten(input_str);
+    if(!input)
+        return E_OUTOFMEMORY;
+
     hres = create_array(ctx, result->paren_count+1, &array);
     if(FAILED(hres))
         return hres;
 
     for(i=0; i < result->paren_count; i++) {
         if(result->parens[i].index != -1)
-            str = jsstr_substr(input, result->parens[i].index, result->parens[i].length);
+            str = jsstr_substr(input_str, result->parens[i].index, result->parens[i].length);
         else
             str = jsstr_empty();
         if(!str) {
@@ -361,15 +418,15 @@ static HRESULT create_match_array(script_ctx_t *ctx, jsstr_t *input,
     }
 
     while(SUCCEEDED(hres)) {
-        hres = jsdisp_propput_name(array, indexW, jsval_number(result->cp-input->str-result->match_len));
+        hres = jsdisp_propput_name(array, indexW, jsval_number(result->cp-input-result->match_len));
         if(FAILED(hres))
             break;
 
-        hres = jsdisp_propput_name(array, lastIndexW, jsval_number(result->cp-input->str));
+        hres = jsdisp_propput_name(array, lastIndexW, jsval_number(result->cp-input));
         if(FAILED(hres))
             break;
 
-        hres = jsdisp_propput_name(array, inputW, jsval_string(jsstr_addref(input)));
+        hres = jsdisp_propput_name(array, inputW, jsval_string(jsstr_addref(input_str)));
         if(FAILED(hres))
             break;
 
@@ -398,7 +455,8 @@ static HRESULT run_exec(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t arg,
     RegExpInstance *regexp;
     match_state_t *match;
     DWORD last_index = 0;
-    jsstr_t *string;
+    const WCHAR *string;
+    jsstr_t *jsstr;
     HRESULT hres;
 
     if(!is_vclass(jsthis, JSCLASS_REGEXP)) {
@@ -408,13 +466,13 @@ static HRESULT run_exec(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t arg,
 
     regexp = regexp_from_vdisp(jsthis);
 
-    hres = to_string(ctx, arg, &string);
+    hres = to_flat_string(ctx, arg, &jsstr, &string);
     if(FAILED(hres))
         return hres;
 
     if(regexp->jsregexp->flags & REG_GLOB) {
         if(regexp->last_index < 0) {
-            jsstr_release(string);
+            jsstr_release(jsstr);
             set_last_index(regexp, 0);
             *ret = FALSE;
             if(input)
@@ -425,24 +483,24 @@ static HRESULT run_exec(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t arg,
         last_index = regexp->last_index;
     }
 
-    match = alloc_match_state(regexp->jsregexp, &ctx->tmp_heap, string->str+last_index);
+    match = alloc_match_state(regexp->jsregexp, &ctx->tmp_heap, string+last_index);
     if(!match) {
-        jsstr_release(string);
+        jsstr_release(jsstr);
         return E_OUTOFMEMORY;
     }
 
-    hres = regexp_match_next(ctx, &regexp->dispex, REM_RESET_INDEX, string, &match);
+    hres = regexp_match_next(ctx, &regexp->dispex, REM_RESET_INDEX, jsstr, &match);
     if(FAILED(hres)) {
-        jsstr_release(string);
+        jsstr_release(jsstr);
         return hres;
     }
 
     *result = match;
     *ret = hres == S_OK;
     if(input)
-        *input = string;
+        *input = jsstr;
     else
-        jsstr_release(string);
+        jsstr_release(jsstr);
     return S_OK;
 }
 
@@ -596,10 +654,15 @@ static HRESULT alloc_regexp(script_ctx_t *ctx, jsdisp_t *object_prototype, RegEx
 HRESULT create_regexp(script_ctx_t *ctx, jsstr_t *src, DWORD flags, jsdisp_t **ret)
 {
     RegExpInstance *regexp;
+    const WCHAR *str;
     HRESULT hres;
 
     TRACE("%s %x\n", debugstr_jsstr(src), flags);
 
+    str = jsstr_flatten(src);
+    if(!str)
+        return E_OUTOFMEMORY;
+
     hres = alloc_regexp(ctx, NULL, &regexp);
     if(FAILED(hres))
         return hres;
@@ -607,9 +670,8 @@ HRESULT create_regexp(script_ctx_t *ctx, jsstr_t *src, DWORD flags, jsdisp_t **r
     regexp->str = jsstr_addref(src);
     regexp->last_index_val = jsval_number(0);
 
-    regexp->jsregexp = regexp_new(ctx, &ctx->tmp_heap, regexp->str->str,
-            jsstr_length(regexp->str), flags, FALSE);
-    if(FAILED(hres)) {
+    regexp->jsregexp = regexp_new(ctx, &ctx->tmp_heap, str, jsstr_length(regexp->str), flags, FALSE);
+    if(!regexp->jsregexp) {
         WARN("regexp_new failed\n");
         jsdisp_release(&regexp->dispex);
         return E_FAIL;
@@ -621,8 +683,9 @@ HRESULT create_regexp(script_ctx_t *ctx, jsstr_t *src, DWORD flags, jsdisp_t **r
 
 HRESULT create_regexp_var(script_ctx_t *ctx, jsval_t src_arg, jsval_t *flags_arg, jsdisp_t **ret)
 {
-    jsstr_t *src, *opt = NULL;
-    DWORD flags;
+    unsigned flags, opt_len = 0;
+    const WCHAR *opt = NULL;
+    jsstr_t *src;
     HRESULT hres;
 
     if(is_object_instance(src_arg)) {
@@ -650,22 +713,28 @@ HRESULT create_regexp_var(script_ctx_t *ctx, jsval_t src_arg, jsval_t *flags_arg
     src = get_string(src_arg);
 
     if(flags_arg) {
+        jsstr_t *opt_str;
+
         if(!is_string(*flags_arg)) {
             FIXME("unimplemented for %s\n", debugstr_jsval(*flags_arg));
             return E_NOTIMPL;
         }
 
-        opt = get_string(*flags_arg);
+        opt_str = get_string(*flags_arg);
+        opt = jsstr_flatten(opt_str);
+        if(!opt)
+            return E_OUTOFMEMORY;
+        opt_len = jsstr_length(opt_str);
     }
 
-    hres = parse_regexp_flags(opt ? opt->str : NULL, opt ? jsstr_length(opt) : 0, &flags);
+    hres = parse_regexp_flags(opt, opt_len, &flags);
     if(FAILED(hres))
         return hres;
 
     return create_regexp(ctx, src, flags, ret);
 }
 
-HRESULT regexp_string_match(script_ctx_t *ctx, jsdisp_t *re, jsstr_t *str, jsval_t *r)
+HRESULT regexp_string_match(script_ctx_t *ctx, jsdisp_t *re, jsstr_t *jsstr, jsval_t *r)
 {
     static const WCHAR indexW[] = {'i','n','d','e','x',0};
     static const WCHAR inputW[] = {'i','n','p','u','t',0};
@@ -674,21 +743,26 @@ HRESULT regexp_string_match(script_ctx_t *ctx, jsdisp_t *re, jsstr_t *str, jsval
     RegExpInstance *regexp = (RegExpInstance*)re;
     match_result_t *match_result;
     unsigned match_cnt, i;
+    const WCHAR *str;
     jsdisp_t *array;
     HRESULT hres;
 
+    str = jsstr_flatten(jsstr);
+    if(!str)
+        return E_OUTOFMEMORY;
+
     if(!(regexp->jsregexp->flags & REG_GLOB)) {
         match_state_t *match;
         heap_pool_t *mark;
 
         mark = heap_pool_mark(&ctx->tmp_heap);
-        match = alloc_match_state(regexp->jsregexp, &ctx->tmp_heap, str->str);
+        match = alloc_match_state(regexp->jsregexp, &ctx->tmp_heap, str);
         if(!match) {
             heap_pool_clear(mark);
             return E_OUTOFMEMORY;
         }
 
-        hres = regexp_match_next(ctx, &regexp->dispex, 0, str, &match);
+        hres = regexp_match_next(ctx, &regexp->dispex, 0, jsstr, &match);
         if(FAILED(hres)) {
             heap_pool_clear(mark);
             return hres;
@@ -698,7 +772,7 @@ HRESULT regexp_string_match(script_ctx_t *ctx, jsdisp_t *re, jsstr_t *str, jsval
             if(hres == S_OK) {
                 IDispatch *ret;
 
-                hres = create_match_array(ctx, str, match, &ret);
+                hres = create_match_array(ctx, jsstr, match, &ret);
                 if(SUCCEEDED(hres))
                     *r = jsval_disp(ret);
             }else {
@@ -710,7 +784,7 @@ HRESULT regexp_string_match(script_ctx_t *ctx, jsdisp_t *re, jsstr_t *str, jsval
         return S_OK;
     }
 
-    hres = regexp_match(ctx, &regexp->dispex, str, FALSE, &match_result, &match_cnt);
+    hres = regexp_match(ctx, &regexp->dispex, jsstr, FALSE, &match_result, &match_cnt);
     if(FAILED(hres))
         return hres;
 
@@ -729,7 +803,7 @@ HRESULT regexp_string_match(script_ctx_t *ctx, jsdisp_t *re, jsstr_t *str, jsval
     for(i=0; i < match_cnt; i++) {
         jsstr_t *tmp_str;
 
-        tmp_str = jsstr_substr(str, match_result[i].index, match_result[i].length);
+        tmp_str = jsstr_substr(jsstr, match_result[i].index, match_result[i].length);
         if(!tmp_str) {
             hres = E_OUTOFMEMORY;
             break;
@@ -751,7 +825,7 @@ HRESULT regexp_string_match(script_ctx_t *ctx, jsdisp_t *re, jsstr_t *str, jsval
         if(FAILED(hres))
             break;
 
-        hres = jsdisp_propput_name(array, inputW, jsval_string(str));
+        hres = jsdisp_propput_name(array, inputW, jsval_string(jsstr));
         break;
     }
 
index 48adf94..7cb1fce 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include <assert.h>
+
 #include "jscript.h"
 
 #include <wine/debug.h>
 
+/*
+ * This is the length of a string that is considered to be long enough to be
+ * worth the rope to avoid copy.
+ * This probably could be tuned, but keep it low for a while to better test rope's code.
+ */
+#define JSSTR_SHORT_STRING_LENGTH 8
+
+/*
+ * This is the max rope depth. While faster to allocate, ropes may become slow at access.
+ */
+#define JSSTR_MAX_ROPE_DEPTH 100
+
 const char *debugstr_jsstr(jsstr_t *str)
 {
-    return debugstr_wn(str->str, jsstr_length(str));
+    return jsstr_is_inline(str) ? debugstr_wn(jsstr_as_inline(str)->buf, jsstr_length(str))
+        : jsstr_is_heap(str) ? debugstr_wn(jsstr_as_heap(str)->buf, jsstr_length(str))
+        : wine_dbg_sprintf("%s...", debugstr_jsstr(jsstr_as_rope(str)->left));
 }
 
-jsstr_t *jsstr_alloc_buf(unsigned len)
+void jsstr_free(jsstr_t *str)
 {
-    jsstr_t *ret;
+    switch(jsstr_tag(str)) {
+    case JSSTR_HEAP:
+        heap_free(jsstr_as_heap(str)->buf);
+        break;
+    case JSSTR_ROPE: {
+        jsstr_rope_t *rope = jsstr_as_rope(str);
+        jsstr_release(rope->left);
+        jsstr_release(rope->right);
+        break;
+    }
+    case JSSTR_INLINE:
+        break;
+    }
+
+    heap_free(str);
+}
+
+static inline void jsstr_init(jsstr_t *str, unsigned len, jsstr_tag_t tag)
+{
+    str->length_flags = len << JSSTR_LENGTH_SHIFT | tag;
+    str->ref = 1;
+}
+
+WCHAR *jsstr_alloc_buf(unsigned len, jsstr_t **r)
+{
+    jsstr_inline_t *ret;
 
     if(len > JSSTR_MAX_LENGTH)
         return NULL;
 
-    ret = heap_alloc(FIELD_OFFSET(jsstr_t, str[len+1]));
+    ret = heap_alloc(FIELD_OFFSET(jsstr_inline_t, buf[len+1]));
     if(!ret)
         return NULL;
 
-    ret->length_flags = len << JSSTR_LENGTH_SHIFT;
-    ret->ref = 1;
-    ret->str[len] = 0;
-    return ret;
+    jsstr_init(&ret->str, len, JSSTR_INLINE);
+    ret->buf[len] = 0;
+    *r = &ret->str;
+    return ret->buf;
 }
 
 jsstr_t *jsstr_alloc_len(const WCHAR *buf, unsigned len)
 {
     jsstr_t *ret;
+    WCHAR *ptr;
 
-    ret = jsstr_alloc_buf(len);
-    if(ret)
-        memcpy(ret->str, buf, len*sizeof(WCHAR));
+    ptr = jsstr_alloc_buf(len, &ret);
+    if(ptr)
+        memcpy(ptr, buf, len*sizeof(WCHAR));
 
     return ret;
 }
 
+static void jsstr_rope_extract(jsstr_rope_t *str, unsigned off, unsigned len, WCHAR *buf)
+{
+    unsigned left_len = jsstr_length(str->left);
+
+    if(left_len <= off) {
+        jsstr_extract(str->right, off-left_len, len, buf);
+    }else if(left_len >= len+off) {
+        jsstr_extract(str->left, off, len, buf);
+    }else {
+        left_len -= off;
+        jsstr_extract(str->left, off, left_len, buf);
+        jsstr_extract(str->right, 0, len-left_len, buf+left_len);
+    }
+}
+
+void jsstr_extract(jsstr_t *str, unsigned off, unsigned len, WCHAR *buf)
+{
+    switch(jsstr_tag(str)) {
+    case JSSTR_INLINE:
+        memcpy(buf, jsstr_as_inline(str)->buf+off, len*sizeof(WCHAR));
+        return;
+    case JSSTR_HEAP:
+        memcpy(buf, jsstr_as_heap(str)->buf+off, len*sizeof(WCHAR));
+        return;
+    case JSSTR_ROPE:
+        jsstr_rope_extract(jsstr_as_rope(str), off, len, buf);
+        return;
+    }
+}
+
+static int jsstr_cmp_str(jsstr_t *jsstr, const WCHAR *str, unsigned len)
+{
+    int ret;
+
+    switch(jsstr_tag(jsstr)) {
+    case JSSTR_INLINE:
+        ret = memcmp(jsstr_as_inline(jsstr)->buf, str, len*sizeof(WCHAR));
+        return ret || jsstr_length(jsstr) == len ? ret : 1;
+    case JSSTR_HEAP:
+        ret = memcmp(jsstr_as_heap(jsstr)->buf, str, len*sizeof(WCHAR));
+        return ret || jsstr_length(jsstr) == len ? ret : 1;
+    case JSSTR_ROPE: {
+        jsstr_rope_t *rope = jsstr_as_rope(jsstr);
+        unsigned left_len = jsstr_length(rope->left);
+
+        ret = jsstr_cmp_str(rope->left, str, min(len, left_len));
+        if(ret || len <= left_len)
+            return ret;
+        return jsstr_cmp_str(rope->right, str+left_len, len-left_len);
+    }
+    }
+
+    assert(0);
+    return 0;
+}
+
+#define TMP_BUF_SIZE 256
+
+static int ropes_cmp(jsstr_rope_t *left, jsstr_rope_t *right)
+{
+    WCHAR left_buf[TMP_BUF_SIZE], right_buf[TMP_BUF_SIZE];
+    unsigned left_len = jsstr_length(&left->str);
+    unsigned right_len = jsstr_length(&right->str);
+    unsigned cmp_off = 0, cmp_size;
+    int ret;
+
+    /* FIXME: We can avoid temporary buffers here. */
+    while(cmp_off < min(left_len, right_len)) {
+        cmp_size = min(left_len, right_len) - cmp_off;
+        if(cmp_size > TMP_BUF_SIZE)
+            cmp_size = TMP_BUF_SIZE;
+
+        jsstr_rope_extract(left, cmp_off, cmp_size, left_buf);
+        jsstr_rope_extract(right, cmp_off, cmp_size, right_buf);
+        ret = memcmp(left_buf, right_buf, cmp_size);
+        if(ret)
+            return ret;
+
+        cmp_off += cmp_size;
+    }
+
+    return left_len - right_len;
+}
+
+static inline const WCHAR *jsstr_try_flat(jsstr_t *str)
+{
+    return jsstr_is_inline(str) ? jsstr_as_inline(str)->buf
+        : jsstr_is_heap(str) ? jsstr_as_heap(str)->buf
+        : NULL;
+}
+
 int jsstr_cmp(jsstr_t *str1, jsstr_t *str2)
 {
-    int len1 = jsstr_length(str1);
-    int len2 = jsstr_length(str2);
+    unsigned len1 = jsstr_length(str1);
+    unsigned len2 = jsstr_length(str2);
+    const WCHAR *str;
     int ret;
 
-    ret = memcmp(str1->str, str2->str, min(len1, len2)*sizeof(WCHAR));
-    if(!ret)
-        ret = len1 - len2;
+    str = jsstr_try_flat(str2);
+    if(str) {
+        ret = jsstr_cmp_str(str1, str, min(len1, len2));
+        return ret || len1 == len2 ? ret : -1;
+    }
 
-    return ret;
+    str = jsstr_try_flat(str1);
+    if(str) {
+        ret = jsstr_cmp_str(str2, str, min(len1, len2));
+        return ret || len1 == len2 ? -ret : 1;
+    }
+
+    return ropes_cmp(jsstr_as_rope(str1), jsstr_as_rope(str2));
 }
 
 jsstr_t *jsstr_concat(jsstr_t *str1, jsstr_t *str2)
 {
     unsigned len1, len2;
     jsstr_t *ret;
+    WCHAR *ptr;
 
     len1 = jsstr_length(str1);
     if(!len1)
@@ -79,16 +222,63 @@ jsstr_t *jsstr_concat(jsstr_t *str1, jsstr_t *str2)
     if(!len2)
         return jsstr_addref(str1);
 
-    ret = jsstr_alloc_buf(len1+len2);
+    if(len1 + len2 >= JSSTR_SHORT_STRING_LENGTH) {
+        unsigned depth, depth2;
+        jsstr_rope_t *rope;
+
+        depth = jsstr_is_rope(str1) ? jsstr_as_rope(str1)->depth : 0;
+        depth2 = jsstr_is_rope(str2) ? jsstr_as_rope(str2)->depth : 0;
+        if(depth2 > depth)
+            depth = depth2;
+
+        if(depth++ < JSSTR_MAX_ROPE_DEPTH) {
+            if(len1+len2 > JSSTR_MAX_LENGTH)
+                return NULL;
+
+            rope = heap_alloc(sizeof(*rope));
+            if(!rope)
+                return NULL;
+
+            jsstr_init(&rope->str, len1+len2, JSSTR_ROPE);
+            rope->left = jsstr_addref(str1);
+            rope->right = jsstr_addref(str2);
+            rope->depth = depth;
+            return &rope->str;
+        }
+    }
+
+    ptr = jsstr_alloc_buf(len1+len2, &ret);
     if(!ret)
         return NULL;
 
-    jsstr_flush(str1, ret->str);
-    jsstr_flush(str2, ret->str+len1);
+    jsstr_flush(str1, ptr);
+    jsstr_flush(str2, ptr+len1);
     return ret;
+
+}
+
+C_ASSERT(sizeof(jsstr_heap_t) <= sizeof(jsstr_rope_t));
+
+const WCHAR *jsstr_rope_flatten(jsstr_rope_t *str)
+{
+    WCHAR *buf;
+
+    buf = heap_alloc((jsstr_length(&str->str)+1) * sizeof(WCHAR));
+    if(!buf)
+        return NULL;
+
+    jsstr_flush(str->left, buf);
+    jsstr_flush(str->right, buf+jsstr_length(str->left));
+    buf[jsstr_length(&str->str)] = 0;
+
+    /* Trasform to heap string */
+    jsstr_release(str->left);
+    jsstr_release(str->right);
+    str->str.length_flags |= JSSTR_FLAG_FLAT;
+    return jsstr_as_heap(&str->str)->buf = buf;
 }
 
-static jsstr_t *empty_str, *nan_str, *undefined_str;
+static jsstr_t *empty_str, *nan_str, *undefined_str, *null_bstr_str;
 
 jsstr_t *jsstr_nan(void)
 {
@@ -105,23 +295,40 @@ jsstr_t *jsstr_undefined(void)
     return jsstr_addref(undefined_str);
 }
 
+jsstr_t *jsstr_null_bstr(void)
+{
+    return jsstr_addref(null_bstr_str);
+}
+
+BOOL is_null_bstr(jsstr_t *str)
+{
+    return str == null_bstr_str;
+}
+
 BOOL init_strings(void)
 {
     static const WCHAR NaNW[] = { 'N','a','N',0 };
     static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
 
-    if(!(empty_str = jsstr_alloc_buf(0)))
+    if(!jsstr_alloc_buf(0, &empty_str))
         return FALSE;
     if(!(nan_str = jsstr_alloc(NaNW)))
         return FALSE;
     if(!(undefined_str = jsstr_alloc(undefinedW)))
         return FALSE;
-    return TRUE;
+    if(!jsstr_alloc_buf(0, &null_bstr_str))
+        return FALSE;
+     return TRUE;
 }
 
 void free_strings(void)
 {
-    jsstr_release(empty_str);
-    jsstr_release(nan_str);
-    jsstr_release(undefined_str);
+    if(empty_str)
+        jsstr_release(empty_str);
+    if(nan_str)
+        jsstr_release(nan_str);
+    if(undefined_str)
+        jsstr_release(undefined_str);
+    if(null_bstr_str)
+        jsstr_release(null_bstr_str);
 }
index c71cbea..2ad03f1 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+/*
+ * jsstr_t is a common header for all string representations. The exact layout of the string
+ * representation may be:
+ *
+ * - inline string - string bytes directly follow string headers.
+ * - heap string - a structure containing a pointer to buffer on the heap.
+ * - roper string - a product of concatenation of two strings. Instead of copying whole
+ *   buffers, we may store just references to concatenated strings.
+ *
+ * String layout may change over life time of the string. Currently possible transformation
+ * is when a rope string becomes a heap stream. That happens when we need a real, linear
+ * zero-terminated buffer (a flat buffer). At this point the type of the string is changed
+ * and the new buffer is stored in the string, so that subsequent operations requiring
+ * a flat string won't need to flatten it again.
+ *
+ * In the future more layouts and transformations may be added.
+ */
 struct _jsstr_t {
     unsigned length_flags;
     unsigned ref;
-    WCHAR str[1];
 };
 
 #define JSSTR_LENGTH_SHIFT 4
 #define JSSTR_MAX_LENGTH (1 << (32-JSSTR_LENGTH_SHIFT))
 #define JSSTR_FLAGS_MASK ((1 << JSSTR_LENGTH_SHIFT)-1)
 
-#define JSSTR_FLAG_NULLBSTR 1
+#define JSSTR_FLAG_LBIT     1
+#define JSSTR_FLAG_FLAT     2
+#define JSSTR_FLAG_TAG_MASK 3
+
+typedef enum {
+    JSSTR_INLINE = JSSTR_FLAG_FLAT,
+    JSSTR_HEAP   = JSSTR_FLAG_FLAT|JSSTR_FLAG_LBIT,
+    JSSTR_ROPE   = JSSTR_FLAG_LBIT
+} jsstr_tag_t;
 
 static inline unsigned jsstr_length(jsstr_t *str)
 {
     return str->length_flags >> JSSTR_LENGTH_SHIFT;
 }
 
+static inline jsstr_tag_t jsstr_tag(jsstr_t *str)
+{
+    return str->length_flags & JSSTR_FLAG_TAG_MASK;
+}
+
+static inline BOOL jsstr_is_inline(jsstr_t *str)
+{
+    return jsstr_tag(str) == JSSTR_INLINE;
+}
+
+static inline BOOL jsstr_is_heap(jsstr_t *str)
+{
+    return jsstr_tag(str) == JSSTR_HEAP;
+}
+
+static inline BOOL jsstr_is_rope(jsstr_t *str)
+{
+    return jsstr_tag(str) == JSSTR_ROPE;
+}
+
+typedef struct {
+    jsstr_t str;
+    WCHAR buf[1];
+} jsstr_inline_t;
+
+typedef struct {
+    jsstr_t str;
+    WCHAR *buf;
+} jsstr_heap_t;
+
+typedef struct {
+    jsstr_t str;
+    jsstr_t *left;
+    jsstr_t *right;
+    unsigned depth;
+} jsstr_rope_t;
+
 jsstr_t *jsstr_alloc_len(const WCHAR*,unsigned) DECLSPEC_HIDDEN;
-jsstr_t *jsstr_alloc_buf(unsigned) DECLSPEC_HIDDEN;
+WCHAR *jsstr_alloc_buf(unsigned,jsstr_t**) DECLSPEC_HIDDEN;
 
 static inline jsstr_t *jsstr_alloc(const WCHAR *str)
 {
     return jsstr_alloc_len(str, strlenW(str));
 }
 
+void jsstr_free(jsstr_t*) DECLSPEC_HIDDEN;
+
 static inline void jsstr_release(jsstr_t *str)
 {
-    if(!--str->ref)
-        heap_free(str);
+    if(!--str->ref) {
+        if(jsstr_is_inline(str))
+            heap_free(str);
+        else
+            jsstr_free(str);
+    }
 }
 
 static inline jsstr_t *jsstr_addref(jsstr_t *str)
@@ -53,31 +120,74 @@ static inline jsstr_t *jsstr_addref(jsstr_t *str)
     return str;
 }
 
-static inline BOOL jsstr_eq(jsstr_t *str1, jsstr_t *str2)
+static inline jsstr_inline_t *jsstr_as_inline(jsstr_t *str)
+{
+    return CONTAINING_RECORD(str, jsstr_inline_t, str);
+}
+
+static inline jsstr_heap_t *jsstr_as_heap(jsstr_t *str)
 {
-    unsigned len = jsstr_length(str1);
-    return len == jsstr_length(str2) && !memcmp(str1->str, str2->str, len*sizeof(WCHAR));
+    return CONTAINING_RECORD(str, jsstr_heap_t, str);
 }
 
+static inline jsstr_rope_t *jsstr_as_rope(jsstr_t *str)
+{
+    return CONTAINING_RECORD(str, jsstr_rope_t, str);
+}
+
+const WCHAR *jsstr_rope_flatten(jsstr_rope_t*) DECLSPEC_HIDDEN;
+
+static inline const WCHAR *jsstr_flatten(jsstr_t *str)
+{
+    return jsstr_is_inline(str) ? jsstr_as_inline(str)->buf
+        : jsstr_is_heap(str) ? jsstr_as_heap(str)->buf
+        : jsstr_rope_flatten(jsstr_as_rope(str));
+}
+
+void jsstr_extract(jsstr_t*,unsigned,unsigned,WCHAR*) DECLSPEC_HIDDEN;
+
 static inline unsigned jsstr_flush(jsstr_t *str, WCHAR *buf)
 {
     unsigned len = jsstr_length(str);
-    memcpy(buf, str->str, len*sizeof(WCHAR));
+    if(jsstr_is_inline(str)) {
+        memcpy(buf, jsstr_as_inline(str)->buf, len*sizeof(WCHAR));
+    }else if(jsstr_is_heap(str)) {
+        memcpy(buf, jsstr_as_heap(str)->buf, len*sizeof(WCHAR));
+    }else {
+        jsstr_rope_t *rope = jsstr_as_rope(str);
+        jsstr_flush(rope->left, buf);
+        jsstr_flush(rope->right, buf+jsstr_length(rope->left));
+    }
     return len;
 }
 
 static inline jsstr_t *jsstr_substr(jsstr_t *str, unsigned off, unsigned len)
 {
-    return jsstr_alloc_len(str->str+off, len);
+    jsstr_t *ret;
+    WCHAR *ptr;
+
+    ptr = jsstr_alloc_buf(len, &ret);
+    if(ptr)
+        jsstr_extract(str, off, len, ptr);
+    return ret;
 }
 
 int jsstr_cmp(jsstr_t*,jsstr_t*) DECLSPEC_HIDDEN;
+
+static inline BOOL jsstr_eq(jsstr_t *left, jsstr_t *right)
+{
+    return jsstr_length(left) == jsstr_length(right) && !jsstr_cmp(left, right);
+}
+
 jsstr_t *jsstr_concat(jsstr_t*,jsstr_t*) DECLSPEC_HIDDEN;
 
 jsstr_t *jsstr_nan(void) DECLSPEC_HIDDEN;
 jsstr_t *jsstr_empty(void) DECLSPEC_HIDDEN;
 jsstr_t *jsstr_undefined(void) DECLSPEC_HIDDEN;
 
+jsstr_t *jsstr_null_bstr(void) DECLSPEC_HIDDEN;
+BOOL is_null_bstr(jsstr_t*) DECLSPEC_HIDDEN;
+
 BOOL init_strings(void) DECLSPEC_HIDDEN;
 void free_strings(void) DECLSPEC_HIDDEN;
 
index 8b325aa..97fd172 100644 (file)
@@ -294,11 +294,13 @@ HRESULT variant_to_jsval(VARIANT *var, jsval_t *r)
     case VT_BSTR: {
         jsstr_t *str;
 
-        str = jsstr_alloc_len(V_BSTR(var), SysStringLen(V_BSTR(var)));
-        if(!str)
-            return E_OUTOFMEMORY;
-        if(!V_BSTR(var))
-            str->length_flags |= JSSTR_FLAG_NULLBSTR;
+        if(V_BSTR(var)) {
+            str = jsstr_alloc_len(V_BSTR(var), SysStringLen(V_BSTR(var)));
+            if(!str)
+                return E_OUTOFMEMORY;
+        }else {
+            str = jsstr_null_bstr();
+        }
 
         *r = jsval_string(str);
         return S_OK;
@@ -351,7 +353,7 @@ HRESULT jsval_to_variant(jsval_t val, VARIANT *retv)
         jsstr_t *str = get_string(val);
 
         V_VT(retv) = VT_BSTR;
-        if(str->length_flags & JSSTR_FLAG_NULLBSTR) {
+        if(is_null_bstr(str)) {
             V_BSTR(retv) = NULL;
         }else {
             V_BSTR(retv) = SysAllocStringLen(NULL, jsstr_length(str));
@@ -502,16 +504,15 @@ static int hex_to_int(WCHAR c)
 /* ECMA-262 3rd Edition    9.3.1 */
 static HRESULT str_to_number(jsstr_t *str, double *ret)
 {
-    const WCHAR *ptr = str->str;
+    const WCHAR *ptr;
     BOOL neg = FALSE;
     DOUBLE d = 0.0;
 
     static const WCHAR infinityW[] = {'I','n','f','i','n','i','t','y'};
 
-    if(!ptr) {
-        *ret = 0;
-        return S_OK;
-    }
+    ptr = jsstr_flatten(str);
+    if(!ptr)
+        return E_OUTOFMEMORY;
 
     while(isspaceW(*ptr))
         ptr++;
@@ -777,6 +778,23 @@ HRESULT to_string(script_ctx_t *ctx, jsval_t val, jsstr_t **str)
     return *str ? S_OK : E_OUTOFMEMORY;
 }
 
+HRESULT to_flat_string(script_ctx_t *ctx, jsval_t val, jsstr_t **str, const WCHAR **ret_str)
+{
+    HRESULT hres;
+
+    hres = to_string(ctx, val, str);
+    if(FAILED(hres))
+        return hres;
+
+    *ret_str = jsstr_flatten(*str);
+    if(!*ret_str) {
+        jsstr_release(*str);
+        return E_OUTOFMEMORY;
+    }
+
+    return S_OK;
+}
+
 /* ECMA-262 3rd Edition    9.9 */
 HRESULT to_object(script_ctx_t *ctx, jsval_t val, IDispatch **disp)
 {
@@ -897,7 +915,7 @@ HRESULT variant_change_type(script_ctx_t *ctx, VARIANT *dst, VARIANT *src, VARTY
         if(FAILED(hres))
             break;
 
-        if(str->length_flags & JSSTR_FLAG_NULLBSTR) {
+        if(is_null_bstr(str)) {
             V_BSTR(dst) = NULL;
             break;
         }
index e51fdd5..50a7338 100644 (file)
@@ -54,7 +54,7 @@ static inline NumberInstance *number_this(vdisp_t *jsthis)
     return is_vclass(jsthis, JSCLASS_NUMBER) ? number_from_vdisp(jsthis) : NULL;
 }
 
-static inline void dtoa(double d, WCHAR *buf, int size, int *dec_point)
+static inline void number_to_str(double d, WCHAR *buf, int size, int *dec_point)
 {
     ULONGLONG l;
     int i;
@@ -113,7 +113,7 @@ static inline jsstr_t *number_to_fixed(double val, int prec)
     if(buf_size > NUMBER_DTOA_SIZE)
         buf_size = NUMBER_DTOA_SIZE;
 
-    dtoa(val, buf, buf_size, &dec_point);
+    number_to_str(val, buf, buf_size, &dec_point);
     dec_point++;
     size = 0;
     if(neg)
@@ -125,11 +125,10 @@ static inline jsstr_t *number_to_fixed(double val, int prec)
     if(prec)
         size += prec+1;
 
-    ret = jsstr_alloc_buf(size);
+    str = jsstr_alloc_buf(size, &ret);
     if(!ret)
         return NULL;
 
-    str = ret->str;
     size = buf_pos = 0;
     if(neg)
         str[size++] = '-';
@@ -172,7 +171,7 @@ static inline jsstr_t *number_to_exponential(double val, int prec)
     buf_size = prec+2;
     if(buf_size<2 || buf_size>NUMBER_DTOA_SIZE)
         buf_size = NUMBER_DTOA_SIZE;
-    dtoa(val, buf, buf_size, &dec_point);
+    number_to_str(val, buf, buf_size, &dec_point);
     buf_size--;
     if(prec == -1)
         for(; buf_size>1 && buf[buf_size-1]=='0'; buf_size--)
@@ -193,11 +192,10 @@ static inline jsstr_t *number_to_exponential(double val, int prec)
     if(neg)
         size++;
 
-    ret = jsstr_alloc_buf(size);
+    str = jsstr_alloc_buf(size, &ret);
     if(!ret)
         return NULL;
 
-    str = ret->str;
     size = 0;
     pbuf = buf;
     if(neg)
index 25cd17f..4e102e8 100644 (file)
@@ -71,12 +71,13 @@ static HRESULT Object_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u
 
     if(r) {
         jsstr_t *ret;
+        WCHAR *ptr;
 
-        ret = jsstr_alloc_buf(9+strlenW(str));
-        if(!ret)
+        ptr = jsstr_alloc_buf(9+strlenW(str), &ret);
+        if(!ptr)
             return E_OUTOFMEMORY;
 
-        sprintfW(ret->str, formatW, str);
+        sprintfW(ptr, formatW, str);
         *r = jsval_string(ret);
     }
 
@@ -129,9 +130,14 @@ static HRESULT Object_hasOwnProperty(script_ctx_t *ctx, vdisp_t *jsthis, WORD fl
         return hres;
 
     if(is_jsdisp(jsthis)) {
+        const WCHAR *name_str;
         BOOL result;
 
-        hres = jsdisp_is_own_prop(jsthis->u.jsdisp, name->str, &result);
+        name_str = jsstr_flatten(name);
+        if(name_str)
+            hres = jsdisp_is_own_prop(jsthis->u.jsdisp, name_str, &result);
+        else
+            hres = E_OUTOFMEMORY;
         jsstr_release(name);
         if(FAILED(hres))
             return hres;
@@ -163,7 +169,8 @@ static HRESULT Object_hasOwnProperty(script_ctx_t *ctx, vdisp_t *jsthis, WORD fl
 static HRESULT Object_propertyIsEnumerable(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
         jsval_t *r)
 {
-    jsstr_t *name;
+    const WCHAR *name;
+    jsstr_t *name_str;
     BOOL ret;
     HRESULT hres;
 
@@ -179,12 +186,12 @@ static HRESULT Object_propertyIsEnumerable(script_ctx_t *ctx, vdisp_t *jsthis, W
         return E_FAIL;
     }
 
-    hres = to_string(ctx, argv[0], &name);
+    hres = to_flat_string(ctx, argv[0], &name_str, &name);
     if(FAILED(hres))
         return hres;
 
-    hres = jsdisp_is_enumerable(jsthis->u.jsdisp, name->str, &ret);
-    jsstr_release(name);
+    hres = jsdisp_is_enumerable(jsthis->u.jsdisp, name, &ret);
+    jsstr_release(name_str);
     if(FAILED(hres))
         return hres;
 
index 310ab13..6a8ae68 100644 (file)
@@ -1,10 +1,8 @@
+/* A Bison parser, made by GNU Bison 2.5.  */
 
-/* A Bison parser, made by GNU Bison 2.4.1.  */
-
-/* Skeleton implementation for Bison's Yacc-like parsers in C
+/* Bison implementation for Yacc-like parsers in C
    
-      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
+      Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
    
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -46,7 +44,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.4.1"
+#define YYBISON_VERSION "2.5"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -75,7 +73,7 @@
 
 /* Copy the first part of user declarations.  */
 
-/* Line 189 of yacc.c  */
+/* Line 268 of yacc.c  */
 #line 19 "parser.y"
 
 
 
 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
 
-#define YYLEX_PARAM ctx
-#define YYPARSE_PARAM ctx
-
-static int parser_error(const char*);
+static int parser_error(parser_ctx_t*,const char*);
 static void set_error(parser_ctx_t*,UINT);
 static BOOL explicit_error(parser_ctx_t*,void*,WCHAR);
 static BOOL allow_auto_semicolon(parser_ctx_t*);
@@ -200,8 +195,8 @@ static source_elements_t *source_elements_add_statement(source_elements_t*,state
 
 
 
-/* Line 189 of yacc.c  */
-#line 205 "parser.tab.c"
+/* Line 268 of yacc.c  */
+#line 200 "parser.tab.c"
 
 /* Enabling traces.  */
 #ifndef YYDEBUG
@@ -281,8 +276,8 @@ static source_elements_t *source_elements_add_statement(source_elements_t*,state
 typedef union YYSTYPE
 {
 
-/* Line 214 of yacc.c  */
-#line 145 "parser.y"
+/* Line 293 of yacc.c  */
+#line 144 "parser.y"
 
     int                     ival;
     const WCHAR             *srcptr;
@@ -305,8 +300,8 @@ typedef union YYSTYPE
 
 
 
-/* Line 214 of yacc.c  */
-#line 310 "parser.tab.c"
+/* Line 293 of yacc.c  */
+#line 305 "parser.tab.c"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
@@ -317,8 +312,8 @@ typedef union YYSTYPE
 /* Copy the second part of user declarations.  */
 
 
-/* Line 264 of yacc.c  */
-#line 322 "parser.tab.c"
+/* Line 343 of yacc.c  */
+#line 317 "parser.tab.c"
 
 #ifdef short
 # undef short
@@ -368,7 +363,7 @@ typedef short int yytype_int16;
 #define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
 
 #ifndef YY_
-# if YYENABLE_NLS
+# if defined YYENABLE_NLS && YYENABLE_NLS
 #  if ENABLE_NLS
 #   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
 #   define YY_(msgid) dgettext ("bison-runtime", msgid)
@@ -421,11 +416,11 @@ YYID (yyi)
 #    define alloca _alloca
 #   else
 #    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 #     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#     ifndef _STDLIB_H
-#      define _STDLIB_H 1
+#     ifndef EXIT_SUCCESS
+#      define EXIT_SUCCESS 0
 #     endif
 #    endif
 #   endif
@@ -448,24 +443,24 @@ YYID (yyi)
 #  ifndef YYSTACK_ALLOC_MAXIMUM
 #   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
 #  endif
-#  if (defined __cplusplus && ! defined _STDLIB_H \
+#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
        && ! ((defined YYMALLOC || defined malloc) \
             && (defined YYFREE || defined free)))
 #   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   ifndef _STDLIB_H
-#    define _STDLIB_H 1
+#   ifndef EXIT_SUCCESS
+#    define EXIT_SUCCESS 0
 #   endif
 #  endif
 #  ifndef YYMALLOC
 #   define YYMALLOC malloc
-#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+#   if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
 #   endif
 #  endif
 #  ifndef YYFREE
 #   define YYFREE free
-#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+#   if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 void free (void *); /* INFRINGES ON USER NAME SPACE */
 #   endif
@@ -494,23 +489,7 @@ union yyalloc
      ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
       + YYSTACK_GAP_MAXIMUM)
 
-/* Copy COUNT objects from FROM to TO.  The source and destination do
-   not overlap.  */
-# ifndef YYCOPY
-#  if defined __GNUC__ && 1 < __GNUC__
-#   define YYCOPY(To, From, Count) \
-      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-#  else
-#   define YYCOPY(To, From, Count)             \
-      do                                       \
-       {                                       \
-         YYSIZE_T yyi;                         \
-         for (yyi = 0; yyi < (Count); yyi++)   \
-           (To)[yyi] = (From)[yyi];            \
-       }                                       \
-      while (YYID (0))
-#  endif
-# endif
+# define YYCOPY_NEEDED 1
 
 /* Relocate STACK from its old location to the new one.  The
    local variables YYSIZE and YYSTACKSIZE give the old and new number of
@@ -530,6 +509,26 @@ union yyalloc
 
 #endif
 
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)             \
+      do                                       \
+       {                                       \
+         YYSIZE_T yyi;                         \
+         for (yyi = 0; yyi < (Count); yyi++)   \
+           (To)[yyi] = (From)[yyi];            \
+       }                                       \
+      while (YYID (0))
+#  endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  3
 /* YYLAST -- Last index in YYTABLE.  */
@@ -691,28 +690,28 @@ static const yytype_int16 yyrhs[] =
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   252,   252,   256,   257,   261,   262,   267,   271,   275,
-     279,   280,   285,   286,   290,   291,   292,   293,   294,   295,
-     296,   297,   298,   299,   300,   301,   302,   303,   304,   308,
-     309,   314,   315,   319,   320,   324,   329,   330,   335,   337,
-     342,   347,   352,   353,   357,   362,   363,   367,   372,   376,
-     381,   383,   388,   390,   393,   395,   392,   399,   401,   398,
-     404,   406,   411,   416,   421,   426,   431,   436,   441,   443,
-     448,   449,   453,   454,   459,   464,   469,   474,   475,   476,
-     481,   486,   490,   491,   494,   495,   499,   500,   505,   506,
-     510,   512,   516,   517,   521,   522,   524,   529,   531,   533,
-     538,   539,   544,   546,   551,   552,   557,   559,   564,   565,
-     570,   572,   577,   578,   583,   585,   590,   591,   596,   598,
-     603,   604,   609,   611,   616,   617,   622,   623,   628,   629,
-     631,   633,   638,   639,   641,   646,   647,   652,   654,   656,
-     661,   662,   664,   666,   671,   672,   674,   675,   677,   678,
-     679,   680,   681,   682,   686,   688,   690,   696,   697,   701,
-     702,   706,   707,   708,   710,   712,   717,   719,   721,   723,
-     728,   729,   733,   734,   739,   740,   741,   742,   743,   744,
-     748,   749,   750,   751,   756,   758,   763,   764,   768,   769,
-     773,   774,   779,   781,   786,   787,   788,   792,   793,   797,
-     798,   799,   800,   801,   803,   808,   809,   810,   813,   814,
-     817,   818,   821,   822,   825,   826
+       0,   251,   251,   255,   256,   260,   261,   266,   270,   274,
+     278,   279,   284,   285,   289,   290,   291,   292,   293,   294,
+     295,   296,   297,   298,   299,   300,   301,   302,   303,   307,
+     308,   313,   314,   318,   319,   323,   328,   329,   334,   336,
+     341,   346,   351,   352,   356,   361,   362,   366,   371,   375,
+     380,   382,   387,   389,   392,   394,   391,   398,   400,   397,
+     403,   405,   410,   415,   420,   425,   430,   435,   440,   442,
+     447,   448,   452,   453,   458,   463,   468,   473,   474,   475,
+     480,   485,   489,   490,   493,   494,   498,   499,   504,   505,
+     509,   511,   515,   516,   520,   521,   523,   528,   530,   532,
+     537,   538,   543,   545,   550,   551,   556,   558,   563,   564,
+     569,   571,   576,   577,   582,   584,   589,   590,   595,   597,
+     602,   603,   608,   610,   615,   616,   621,   622,   627,   628,
+     630,   632,   637,   638,   640,   645,   646,   651,   653,   655,
+     660,   661,   663,   665,   670,   671,   673,   674,   676,   677,
+     678,   679,   680,   681,   685,   687,   689,   695,   696,   700,
+     701,   705,   706,   707,   709,   711,   716,   718,   720,   722,
+     727,   728,   732,   733,   738,   739,   740,   741,   742,   743,
+     747,   748,   749,   750,   755,   757,   762,   763,   767,   768,
+     772,   773,   778,   780,   785,   786,   787,   791,   792,   796,
+     797,   798,   799,   800,   802,   807,   808,   809,   812,   813,
+     816,   817,   820,   821,   824,   825
 };
 #endif
 
@@ -832,8 +831,8 @@ static const yytype_uint8 yyr2[] =
        1,     1,     1,     1,     1,     1
 };
 
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
-   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
+/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
+   Performed when YYTABLE doesn't specify something else to do.  Zero
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
@@ -954,8 +953,7 @@ static const yytype_int16 yypgoto[] =
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
    positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If zero, do what YYDEFACT says.
-   If YYTABLE_NINF, syntax error.  */
+   number is the opposite.  If YYTABLE_NINF, syntax error.  */
 #define YYTABLE_NINF -197
 static const yytype_int16 yytable[] =
 {
@@ -1067,6 +1065,12 @@ static const yytype_int16 yytable[] =
       40,     0,     0,    41
 };
 
+#define yypact_value_is_default(yystate) \
+  ((yystate) == (-293))
+
+#define yytable_value_is_error(yytable_value) \
+  YYID (0)
+
 static const yytype_int16 yycheck[] =
 {
        2,    18,     2,     6,     1,     7,   298,     7,     1,     1,
@@ -1233,9 +1237,18 @@ static const yytype_uint8 yystos[] =
 
 /* Like YYERROR except do call yyerror.  This remains here temporarily
    to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  */
+   Once GCC version 2 has supplanted version 1, this can go.  However,
+   YYFAIL appears to be in use.  Nevertheless, it is formally deprecated
+   in Bison 2.4.2's NEWS entry, where a plan to phase it out is
+   discussed.  */
 
 #define YYFAIL         goto yyerrlab
+#if defined YYFAIL
+  /* This is here to suppress warnings from the GCC cpp's
+     -Wunused-macros.  Normally we don't worry about that warning, but
+     some users do, and we want to make it easy for users to remove
+     YYFAIL uses, which will produce warnings from Bison 2.5.  */
+#endif
 
 #define YYRECOVERING()  (!!yyerrstatus)
 
@@ -1245,13 +1258,12 @@ do                                                              \
     {                                                          \
       yychar = (Token);                                                \
       yylval = (Value);                                                \
-      yytoken = YYTRANSLATE (yychar);                          \
       YYPOPSTACK (1);                                          \
       goto yybackup;                                           \
     }                                                          \
   else                                                         \
     {                                                          \
-      yyerror (YY_("syntax error: cannot back up")); \
+      yyerror (ctx, YY_("syntax error: cannot back up")); \
       YYERROR;                                                 \
     }                                                          \
 while (YYID (0))
@@ -1287,19 +1299,10 @@ while (YYID (0))
 #endif
 
 
-/* YY_LOCATION_PRINT -- Print the location on the stream.
-   This macro was not mandated originally: define only if we know
-   we won't break user code: when these are the locations we know.  */
+/* This macro is provided for backward compatibility. */
 
 #ifndef YY_LOCATION_PRINT
-# if YYLTYPE_IS_TRIVIAL
-#  define YY_LOCATION_PRINT(File, Loc)                 \
-     fprintf (File, "%d.%d-%d.%d",                     \
-             (Loc).first_line, (Loc).first_column,     \
-             (Loc).last_line,  (Loc).last_column)
-# else
-#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
 #endif
 
 
@@ -1308,7 +1311,7 @@ while (YYID (0))
 #ifdef YYLEX_PARAM
 # define YYLEX yylex (&yylval, YYLEX_PARAM)
 #else
-# define YYLEX yylex (&yylval)
+# define YYLEX yylex (&yylval, ctx)
 #endif
 
 /* Enable debugging if requested.  */
@@ -1331,7 +1334,7 @@ do {                                                                        \
     {                                                                    \
       YYFPRINTF (stderr, "%s ", Title);                                          \
       yy_symbol_print (stderr,                                           \
-                 Type, Value); \
+                 Type, Value, ctx); \
       YYFPRINTF (stderr, "\n");                                                  \
     }                                                                    \
 } while (YYID (0))
@@ -1345,17 +1348,19 @@ do {                                                                      \
 #if (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, parser_ctx_t *ctx)
 #else
 static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep)
+yy_symbol_value_print (yyoutput, yytype, yyvaluep, ctx)
     FILE *yyoutput;
     int yytype;
     YYSTYPE const * const yyvaluep;
+    parser_ctx_t *ctx;
 #endif
 {
   if (!yyvaluep)
     return;
+  YYUSE (ctx);
 # ifdef YYPRINT
   if (yytype < YYNTOKENS)
     YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
@@ -1377,13 +1382,14 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep)
 #if (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, parser_ctx_t *ctx)
 #else
 static void
-yy_symbol_print (yyoutput, yytype, yyvaluep)
+yy_symbol_print (yyoutput, yytype, yyvaluep, ctx)
     FILE *yyoutput;
     int yytype;
     YYSTYPE const * const yyvaluep;
+    parser_ctx_t *ctx;
 #endif
 {
   if (yytype < YYNTOKENS)
@@ -1391,7 +1397,7 @@ yy_symbol_print (yyoutput, yytype, yyvaluep)
   else
     YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
 
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep, ctx);
   YYFPRINTF (yyoutput, ")");
 }
 
@@ -1434,12 +1440,13 @@ do {                                                            \
 #if (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 static void
-yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule, parser_ctx_t *ctx)
 #else
 static void
-yy_reduce_print (yyvsp, yyrule)
+yy_reduce_print (yyvsp, yyrule, ctx)
     YYSTYPE *yyvsp;
     int yyrule;
+    parser_ctx_t *ctx;
 #endif
 {
   int yynrhs = yyr2[yyrule];
@@ -1453,7 +1460,7 @@ yy_reduce_print (yyvsp, yyrule)
       YYFPRINTF (stderr, "   $%d = ", yyi + 1);
       yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
                       &(yyvsp[(yyi + 1) - (yynrhs)])
-                                      );
+                                      , ctx);
       YYFPRINTF (stderr, "\n");
     }
 }
@@ -1461,7 +1468,7 @@ yy_reduce_print (yyvsp, yyrule)
 # define YY_REDUCE_PRINT(Rule)         \
 do {                                   \
   if (yydebug)                         \
-    yy_reduce_print (yyvsp, Rule); \
+    yy_reduce_print (yyvsp, Rule, ctx); \
 } while (YYID (0))
 
 /* Nonzero means print parse trace.  It is left uninitialized so that
@@ -1491,7 +1498,6 @@ int yydebug;
 # define YYMAXDEPTH 10000
 #endif
 
-\f
 
 #if YYERROR_VERBOSE
 
@@ -1594,115 +1600,142 @@ yytnamerr (char *yyres, const char *yystr)
 }
 # endif
 
-/* Copy into YYRESULT an error message about the unexpected token
-   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
-   including the terminating null byte.  If YYRESULT is null, do not
-   copy anything; just return the number of bytes that would be
-   copied.  As a special case, return 0 if an ordinary "syntax error"
-   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
-   size calculation.  */
-static YYSIZE_T
-yysyntax_error (char *yyresult, int yystate, int yychar)
-{
-  int yyn = yypact[yystate];
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+   about the unexpected token YYTOKEN for the state stack whose top is
+   YYSSP.
 
-  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
-    return 0;
-  else
+   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
+   not large enough to hold the message.  In that case, also set
+   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
+   required number of bytes is too large to store.  */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+                yytype_int16 *yyssp, int yytoken)
+{
+  YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]);
+  YYSIZE_T yysize = yysize0;
+  YYSIZE_T yysize1;
+  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+  /* Internationalized format string. */
+  const char *yyformat = 0;
+  /* Arguments of yyformat. */
+  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+  /* Number of reported tokens (one for the "unexpected", one per
+     "expected"). */
+  int yycount = 0;
+
+  /* There are many possibilities here to consider:
+     - Assume YYFAIL is not used.  It's too flawed to consider.  See
+       <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
+       for details.  YYERROR is fine as it does not invoke this
+       function.
+     - If this state is a consistent state with a default action, then
+       the only way this function was invoked is if the default action
+       is an error action.  In that case, don't check for expected
+       tokens because there are none.
+     - The only way there can be no lookahead present (in yychar) is if
+       this state is a consistent state with a default action.  Thus,
+       detecting the absence of a lookahead is sufficient to determine
+       that there is no unexpected or expected token to report.  In that
+       case, just report a simple "syntax error".
+     - Don't assume there isn't a lookahead just because this state is a
+       consistent state with a default action.  There might have been a
+       previous inconsistent state, consistent state with a non-default
+       action, or user semantic action that manipulated yychar.
+     - Of course, the expected token list depends on states to have
+       correct lookahead information, and it depends on the parser not
+       to perform extra reductions after fetching a lookahead from the
+       scanner and before detecting a syntax error.  Thus, state merging
+       (from LALR or IELR) and default reductions corrupt the expected
+       token list.  However, the list is correct for canonical LR with
+       one exception: it will still contain any token that will not be
+       accepted due to an error action in a later state.
+  */
+  if (yytoken != YYEMPTY)
     {
-      int yytype = YYTRANSLATE (yychar);
-      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
-      YYSIZE_T yysize = yysize0;
-      YYSIZE_T yysize1;
-      int yysize_overflow = 0;
-      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
-      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
-      int yyx;
-
-# if 0
-      /* This is so xgettext sees the translatable formats that are
-        constructed on the fly.  */
-      YY_("syntax error, unexpected %s");
-      YY_("syntax error, unexpected %s, expecting %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
-# endif
-      char *yyfmt;
-      char const *yyf;
-      static char const yyunexpected[] = "syntax error, unexpected %s";
-      static char const yyexpecting[] = ", expecting %s";
-      static char const yyor[] = " or %s";
-      char yyformat[sizeof yyunexpected
-                   + sizeof yyexpecting - 1
-                   + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
-                      * (sizeof yyor - 1))];
-      char const *yyprefix = yyexpecting;
-
-      /* Start YYX at -YYN if negative to avoid negative indexes in
-        YYCHECK.  */
-      int yyxbegin = yyn < 0 ? -yyn : 0;
-
-      /* Stay within bounds of both yycheck and yytname.  */
-      int yychecklim = YYLAST - yyn + 1;
-      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-      int yycount = 1;
-
-      yyarg[0] = yytname[yytype];
-      yyfmt = yystpcpy (yyformat, yyunexpected);
-
-      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-       if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
-         {
-           if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
-             {
-               yycount = 1;
-               yysize = yysize0;
-               yyformat[sizeof yyunexpected - 1] = '\0';
-               break;
-             }
-           yyarg[yycount++] = yytname[yyx];
-           yysize1 = yysize + yytnamerr (0, yytname[yyx]);
-           yysize_overflow |= (yysize1 < yysize);
-           yysize = yysize1;
-           yyfmt = yystpcpy (yyfmt, yyprefix);
-           yyprefix = yyor;
-         }
+      int yyn = yypact[*yyssp];
+      yyarg[yycount++] = yytname[yytoken];
+      if (!yypact_value_is_default (yyn))
+        {
+          /* Start YYX at -YYN if negative to avoid negative indexes in
+             YYCHECK.  In other words, skip the first -YYN actions for
+             this state because they are default actions.  */
+          int yyxbegin = yyn < 0 ? -yyn : 0;
+          /* Stay within bounds of both yycheck and yytname.  */
+          int yychecklim = YYLAST - yyn + 1;
+          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+          int yyx;
+
+          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+                && !yytable_value_is_error (yytable[yyx + yyn]))
+              {
+                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+                  {
+                    yycount = 1;
+                    yysize = yysize0;
+                    break;
+                  }
+                yyarg[yycount++] = yytname[yyx];
+                yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+                if (! (yysize <= yysize1
+                       && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                  return 2;
+                yysize = yysize1;
+              }
+        }
+    }
 
-      yyf = YY_(yyformat);
-      yysize1 = yysize + yystrlen (yyf);
-      yysize_overflow |= (yysize1 < yysize);
-      yysize = yysize1;
+  switch (yycount)
+    {
+# define YYCASE_(N, S)                      \
+      case N:                               \
+        yyformat = S;                       \
+      break
+      YYCASE_(0, YY_("syntax error"));
+      YYCASE_(1, YY_("syntax error, unexpected %s"));
+      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+    }
 
-      if (yysize_overflow)
-       return YYSIZE_MAXIMUM;
+  yysize1 = yysize + yystrlen (yyformat);
+  if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+    return 2;
+  yysize = yysize1;
 
-      if (yyresult)
-       {
-         /* Avoid sprintf, as that infringes on the user's name space.
-            Don't have undefined behavior even if the translation
-            produced a string with the wrong number of "%s"s.  */
-         char *yyp = yyresult;
-         int yyi = 0;
-         while ((*yyp = *yyf) != '\0')
-           {
-             if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
-               {
-                 yyp += yytnamerr (yyp, yyarg[yyi++]);
-                 yyf += 2;
-               }
-             else
-               {
-                 yyp++;
-                 yyf++;
-               }
-           }
-       }
-      return yysize;
+  if (*yymsg_alloc < yysize)
+    {
+      *yymsg_alloc = 2 * yysize;
+      if (! (yysize <= *yymsg_alloc
+             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+      return 1;
     }
+
+  /* Avoid sprintf, as that infringes on the user's name space.
+     Don't have undefined behavior even if the translation
+     produced a string with the wrong number of "%s"s.  */
+  {
+    char *yyp = *yymsg;
+    int yyi = 0;
+    while ((*yyp = *yyformat) != '\0')
+      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+        {
+          yyp += yytnamerr (yyp, yyarg[yyi++]);
+          yyformat += 2;
+        }
+      else
+        {
+          yyp++;
+          yyformat++;
+        }
+  }
+  return 0;
 }
 #endif /* YYERROR_VERBOSE */
-\f
 
 /*-----------------------------------------------.
 | Release the memory associated to this symbol.  |
@@ -1712,16 +1745,18 @@ yysyntax_error (char *yyresult, int yystate, int yychar)
 #if (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, parser_ctx_t *ctx)
 #else
 static void
-yydestruct (yymsg, yytype, yyvaluep)
+yydestruct (yymsg, yytype, yyvaluep, ctx)
     const char *yymsg;
     int yytype;
     YYSTYPE *yyvaluep;
+    parser_ctx_t *ctx;
 #endif
 {
   YYUSE (yyvaluep);
+  YYUSE (ctx);
 
   if (!yymsg)
     yymsg = "Deleting";
@@ -1735,6 +1770,7 @@ yydestruct (yymsg, yytype, yyvaluep)
     }
 }
 
+
 /* Prevent warnings from -Wmissing-prototypes.  */
 #ifdef YYPARSE_PARAM
 #if defined __STDC__ || defined __cplusplus
@@ -1744,19 +1780,16 @@ int yyparse ();
 #endif
 #else /* ! YYPARSE_PARAM */
 #if defined __STDC__ || defined __cplusplus
-int yyparse (void);
+int yyparse (parser_ctx_t *ctx);
 #else
 int yyparse ();
 #endif
 #endif /* ! YYPARSE_PARAM */
 
 
-
-
-
-/*-------------------------.
-| yyparse or yypush_parse.  |
-`-------------------------*/
+/*----------.
+| yyparse.  |
+`----------*/
 
 #ifdef YYPARSE_PARAM
 #if (defined __STDC__ || defined __C99__FUNC__ \
@@ -1772,11 +1805,11 @@ yyparse (YYPARSE_PARAM)
 #if (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 int
-yyparse (void)
+yyparse (parser_ctx_t *ctx)
 #else
 int
-yyparse ()
-
+yyparse (ctx)
+    parser_ctx_t *ctx;
 #endif
 #endif
 {
@@ -1943,7 +1976,7 @@ yybackup:
 
   /* First try to decide what to do without reference to lookahead token.  */
   yyn = yypact[yystate];
-  if (yyn == YYPACT_NINF)
+  if (yypact_value_is_default (yyn))
     goto yydefault;
 
   /* Not known => get a lookahead token if don't already have one.  */
@@ -1974,8 +2007,8 @@ yybackup:
   yyn = yytable[yyn];
   if (yyn <= 0)
     {
-      if (yyn == 0 || yyn == YYTABLE_NINF)
-       goto yyerrlab;
+      if (yytable_value_is_error (yyn))
+        goto yyerrlab;
       yyn = -yyn;
       goto yyreduce;
     }
@@ -2030,1482 +2063,1493 @@ yyreduce:
     {
         case 2:
 
-/* Line 1455 of yacc.c  */
-#line 253 "parser.y"
-    { program_parsed(ctx, (yyvsp[(1) - (3)].source_elements)); ;}
+/* Line 1806 of yacc.c  */
+#line 252 "parser.y"
+    { program_parsed(ctx, (yyvsp[(1) - (3)].source_elements)); }
     break;
 
   case 3:
 
-/* Line 1455 of yacc.c  */
-#line 256 "parser.y"
-    {;}
+/* Line 1806 of yacc.c  */
+#line 255 "parser.y"
+    {}
     break;
 
   case 4:
 
-/* Line 1455 of yacc.c  */
-#line 257 "parser.y"
-    {;}
+/* Line 1806 of yacc.c  */
+#line 256 "parser.y"
+    {}
     break;
 
   case 5:
 
-/* Line 1455 of yacc.c  */
-#line 261 "parser.y"
-    { (yyval.source_elements) = new_source_elements(ctx); ;}
+/* Line 1806 of yacc.c  */
+#line 260 "parser.y"
+    { (yyval.source_elements) = new_source_elements(ctx); }
     break;
 
   case 6:
 
-/* Line 1455 of yacc.c  */
-#line 263 "parser.y"
-    { (yyval.source_elements) = source_elements_add_statement((yyvsp[(1) - (2)].source_elements), (yyvsp[(2) - (2)].statement)); ;}
+/* Line 1806 of yacc.c  */
+#line 262 "parser.y"
+    { (yyval.source_elements) = source_elements_add_statement((yyvsp[(1) - (2)].source_elements), (yyvsp[(2) - (2)].statement)); }
     break;
 
   case 7:
 
-/* Line 1455 of yacc.c  */
-#line 268 "parser.y"
-    { (yyval.expr) = new_function_expression(ctx, (yyvsp[(2) - (8)].identifier), (yyvsp[(4) - (8)].parameter_list), (yyvsp[(7) - (8)].source_elements), (yyvsp[(1) - (8)].srcptr), (yyvsp[(8) - (8)].srcptr)-(yyvsp[(1) - (8)].srcptr)+1); ;}
+/* Line 1806 of yacc.c  */
+#line 267 "parser.y"
+    { (yyval.expr) = new_function_expression(ctx, (yyvsp[(2) - (8)].identifier), (yyvsp[(4) - (8)].parameter_list), (yyvsp[(7) - (8)].source_elements), (yyvsp[(1) - (8)].srcptr), (yyvsp[(8) - (8)].srcptr)-(yyvsp[(1) - (8)].srcptr)+1); }
     break;
 
   case 8:
 
-/* Line 1455 of yacc.c  */
-#line 271 "parser.y"
-    { (yyval.srcptr) = (yyvsp[(1) - (1)].srcptr); ;}
+/* Line 1806 of yacc.c  */
+#line 270 "parser.y"
+    { (yyval.srcptr) = (yyvsp[(1) - (1)].srcptr); }
     break;
 
   case 9:
 
-/* Line 1455 of yacc.c  */
-#line 275 "parser.y"
-    { (yyval.source_elements) = (yyvsp[(1) - (1)].source_elements); ;}
+/* Line 1806 of yacc.c  */
+#line 274 "parser.y"
+    { (yyval.source_elements) = (yyvsp[(1) - (1)].source_elements); }
     break;
 
   case 10:
 
-/* Line 1455 of yacc.c  */
-#line 279 "parser.y"
-    { (yyval.parameter_list) = new_parameter_list(ctx, (yyvsp[(1) - (1)].identifier)); ;}
+/* Line 1806 of yacc.c  */
+#line 278 "parser.y"
+    { (yyval.parameter_list) = new_parameter_list(ctx, (yyvsp[(1) - (1)].identifier)); }
     break;
 
   case 11:
 
-/* Line 1455 of yacc.c  */
-#line 281 "parser.y"
-    { (yyval.parameter_list) = parameter_list_add(ctx, (yyvsp[(1) - (3)].parameter_list), (yyvsp[(3) - (3)].identifier)); ;}
+/* Line 1806 of yacc.c  */
+#line 280 "parser.y"
+    { (yyval.parameter_list) = parameter_list_add(ctx, (yyvsp[(1) - (3)].parameter_list), (yyvsp[(3) - (3)].identifier)); }
     break;
 
   case 12:
 
-/* Line 1455 of yacc.c  */
-#line 285 "parser.y"
-    { (yyval.parameter_list) = NULL; ;}
+/* Line 1806 of yacc.c  */
+#line 284 "parser.y"
+    { (yyval.parameter_list) = NULL; }
     break;
 
   case 13:
 
-/* Line 1455 of yacc.c  */
-#line 286 "parser.y"
-    { (yyval.parameter_list) = (yyvsp[(1) - (1)].parameter_list); ;}
+/* Line 1806 of yacc.c  */
+#line 285 "parser.y"
+    { (yyval.parameter_list) = (yyvsp[(1) - (1)].parameter_list); }
     break;
 
   case 14:
 
-/* Line 1455 of yacc.c  */
-#line 290 "parser.y"
-    { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
+/* Line 1806 of yacc.c  */
+#line 289 "parser.y"
+    { (yyval.statement) = (yyvsp[(1) - (1)].statement); }
     break;
 
   case 15:
 
-/* Line 1455 of yacc.c  */
-#line 291 "parser.y"
-    { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
+/* Line 1806 of yacc.c  */
+#line 290 "parser.y"
+    { (yyval.statement) = (yyvsp[(1) - (1)].statement); }
     break;
 
   case 16:
 
-/* Line 1455 of yacc.c  */
-#line 292 "parser.y"
-    { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
+/* Line 1806 of yacc.c  */
+#line 291 "parser.y"
+    { (yyval.statement) = (yyvsp[(1) - (1)].statement); }
     break;
 
   case 17:
 
-/* Line 1455 of yacc.c  */
-#line 293 "parser.y"
-    { (yyval.statement) = new_expression_statement(ctx, (yyvsp[(1) - (1)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 292 "parser.y"
+    { (yyval.statement) = new_expression_statement(ctx, (yyvsp[(1) - (1)].expr)); }
     break;
 
   case 18:
 
-/* Line 1455 of yacc.c  */
-#line 294 "parser.y"
-    { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
+/* Line 1806 of yacc.c  */
+#line 293 "parser.y"
+    { (yyval.statement) = (yyvsp[(1) - (1)].statement); }
     break;
 
   case 19:
 
-/* Line 1455 of yacc.c  */
-#line 295 "parser.y"
-    { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
+/* Line 1806 of yacc.c  */
+#line 294 "parser.y"
+    { (yyval.statement) = (yyvsp[(1) - (1)].statement); }
     break;
 
   case 20:
 
-/* Line 1455 of yacc.c  */
-#line 296 "parser.y"
-    { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
+/* Line 1806 of yacc.c  */
+#line 295 "parser.y"
+    { (yyval.statement) = (yyvsp[(1) - (1)].statement); }
     break;
 
   case 21:
 
-/* Line 1455 of yacc.c  */
-#line 297 "parser.y"
-    { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
+/* Line 1806 of yacc.c  */
+#line 296 "parser.y"
+    { (yyval.statement) = (yyvsp[(1) - (1)].statement); }
     break;
 
   case 22:
 
-/* Line 1455 of yacc.c  */
-#line 298 "parser.y"
-    { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
+/* Line 1806 of yacc.c  */
+#line 297 "parser.y"
+    { (yyval.statement) = (yyvsp[(1) - (1)].statement); }
     break;
 
   case 23:
 
-/* Line 1455 of yacc.c  */
-#line 299 "parser.y"
-    { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
+/* Line 1806 of yacc.c  */
+#line 298 "parser.y"
+    { (yyval.statement) = (yyvsp[(1) - (1)].statement); }
     break;
 
   case 24:
 
-/* Line 1455 of yacc.c  */
-#line 300 "parser.y"
-    { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
+/* Line 1806 of yacc.c  */
+#line 299 "parser.y"
+    { (yyval.statement) = (yyvsp[(1) - (1)].statement); }
     break;
 
   case 25:
 
-/* Line 1455 of yacc.c  */
-#line 301 "parser.y"
-    { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
+/* Line 1806 of yacc.c  */
+#line 300 "parser.y"
+    { (yyval.statement) = (yyvsp[(1) - (1)].statement); }
     break;
 
   case 26:
 
-/* Line 1455 of yacc.c  */
-#line 302 "parser.y"
-    { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
+/* Line 1806 of yacc.c  */
+#line 301 "parser.y"
+    { (yyval.statement) = (yyvsp[(1) - (1)].statement); }
     break;
 
   case 27:
 
-/* Line 1455 of yacc.c  */
-#line 303 "parser.y"
-    { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
+/* Line 1806 of yacc.c  */
+#line 302 "parser.y"
+    { (yyval.statement) = (yyvsp[(1) - (1)].statement); }
     break;
 
   case 28:
 
-/* Line 1455 of yacc.c  */
-#line 304 "parser.y"
-    { (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
+/* Line 1806 of yacc.c  */
+#line 303 "parser.y"
+    { (yyval.statement) = (yyvsp[(1) - (1)].statement); }
     break;
 
   case 29:
 
-/* Line 1455 of yacc.c  */
-#line 308 "parser.y"
-    { (yyval.statement_list) = new_statement_list(ctx, (yyvsp[(1) - (1)].statement)); ;}
+/* Line 1806 of yacc.c  */
+#line 307 "parser.y"
+    { (yyval.statement_list) = new_statement_list(ctx, (yyvsp[(1) - (1)].statement)); }
     break;
 
   case 30:
 
-/* Line 1455 of yacc.c  */
-#line 310 "parser.y"
-    { (yyval.statement_list) = statement_list_add((yyvsp[(1) - (2)].statement_list), (yyvsp[(2) - (2)].statement)); ;}
+/* Line 1806 of yacc.c  */
+#line 309 "parser.y"
+    { (yyval.statement_list) = statement_list_add((yyvsp[(1) - (2)].statement_list), (yyvsp[(2) - (2)].statement)); }
     break;
 
   case 31:
 
-/* Line 1455 of yacc.c  */
-#line 314 "parser.y"
-    { (yyval.statement_list) = NULL; ;}
+/* Line 1806 of yacc.c  */
+#line 313 "parser.y"
+    { (yyval.statement_list) = NULL; }
     break;
 
   case 32:
 
-/* Line 1455 of yacc.c  */
-#line 315 "parser.y"
-    { (yyval.statement_list) = (yyvsp[(1) - (1)].statement_list); ;}
+/* Line 1806 of yacc.c  */
+#line 314 "parser.y"
+    { (yyval.statement_list) = (yyvsp[(1) - (1)].statement_list); }
     break;
 
   case 33:
 
-/* Line 1455 of yacc.c  */
-#line 319 "parser.y"
-    { (yyval.statement) = new_block_statement(ctx, (yyvsp[(2) - (3)].statement_list)); ;}
+/* Line 1806 of yacc.c  */
+#line 318 "parser.y"
+    { (yyval.statement) = new_block_statement(ctx, (yyvsp[(2) - (3)].statement_list)); }
     break;
 
   case 34:
 
-/* Line 1455 of yacc.c  */
-#line 320 "parser.y"
-    { (yyval.statement) = new_block_statement(ctx, NULL); ;}
+/* Line 1806 of yacc.c  */
+#line 319 "parser.y"
+    { (yyval.statement) = new_block_statement(ctx, NULL); }
     break;
 
   case 35:
 
-/* Line 1455 of yacc.c  */
-#line 325 "parser.y"
-    { (yyval.statement) = new_var_statement(ctx, (yyvsp[(2) - (3)].variable_list)); ;}
+/* Line 1806 of yacc.c  */
+#line 324 "parser.y"
+    { (yyval.statement) = new_var_statement(ctx, (yyvsp[(2) - (3)].variable_list)); }
     break;
 
   case 36:
 
-/* Line 1455 of yacc.c  */
-#line 329 "parser.y"
-    { (yyval.variable_list) = new_variable_list(ctx, (yyvsp[(1) - (1)].variable_declaration)); ;}
+/* Line 1806 of yacc.c  */
+#line 328 "parser.y"
+    { (yyval.variable_list) = new_variable_list(ctx, (yyvsp[(1) - (1)].variable_declaration)); }
     break;
 
   case 37:
 
-/* Line 1455 of yacc.c  */
-#line 331 "parser.y"
-    { (yyval.variable_list) = variable_list_add(ctx, (yyvsp[(1) - (3)].variable_list), (yyvsp[(3) - (3)].variable_declaration)); ;}
+/* Line 1806 of yacc.c  */
+#line 330 "parser.y"
+    { (yyval.variable_list) = variable_list_add(ctx, (yyvsp[(1) - (3)].variable_list), (yyvsp[(3) - (3)].variable_declaration)); }
     break;
 
   case 38:
 
-/* Line 1455 of yacc.c  */
-#line 336 "parser.y"
-    { (yyval.variable_list) = new_variable_list(ctx, (yyvsp[(1) - (1)].variable_declaration)); ;}
+/* Line 1806 of yacc.c  */
+#line 335 "parser.y"
+    { (yyval.variable_list) = new_variable_list(ctx, (yyvsp[(1) - (1)].variable_declaration)); }
     break;
 
   case 39:
 
-/* Line 1455 of yacc.c  */
-#line 338 "parser.y"
-    { (yyval.variable_list) = variable_list_add(ctx, (yyvsp[(1) - (3)].variable_list), (yyvsp[(3) - (3)].variable_declaration)); ;}
+/* Line 1806 of yacc.c  */
+#line 337 "parser.y"
+    { (yyval.variable_list) = variable_list_add(ctx, (yyvsp[(1) - (3)].variable_list), (yyvsp[(3) - (3)].variable_declaration)); }
     break;
 
   case 40:
 
-/* Line 1455 of yacc.c  */
-#line 343 "parser.y"
-    { (yyval.variable_declaration) = new_variable_declaration(ctx, (yyvsp[(1) - (2)].identifier), (yyvsp[(2) - (2)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 342 "parser.y"
+    { (yyval.variable_declaration) = new_variable_declaration(ctx, (yyvsp[(1) - (2)].identifier), (yyvsp[(2) - (2)].expr)); }
     break;
 
   case 41:
 
-/* Line 1455 of yacc.c  */
-#line 348 "parser.y"
-    { (yyval.variable_declaration) = new_variable_declaration(ctx, (yyvsp[(1) - (2)].identifier), (yyvsp[(2) - (2)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 347 "parser.y"
+    { (yyval.variable_declaration) = new_variable_declaration(ctx, (yyvsp[(1) - (2)].identifier), (yyvsp[(2) - (2)].expr)); }
     break;
 
   case 42:
 
-/* Line 1455 of yacc.c  */
-#line 352 "parser.y"
-    { (yyval.expr) = NULL; ;}
+/* Line 1806 of yacc.c  */
+#line 351 "parser.y"
+    { (yyval.expr) = NULL; }
     break;
 
   case 43:
 
-/* Line 1455 of yacc.c  */
-#line 353 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 352 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 44:
 
-/* Line 1455 of yacc.c  */
-#line 358 "parser.y"
-    { (yyval.expr) = (yyvsp[(2) - (2)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 357 "parser.y"
+    { (yyval.expr) = (yyvsp[(2) - (2)].expr); }
     break;
 
   case 45:
 
-/* Line 1455 of yacc.c  */
-#line 362 "parser.y"
-    { (yyval.expr) = NULL; ;}
+/* Line 1806 of yacc.c  */
+#line 361 "parser.y"
+    { (yyval.expr) = NULL; }
     break;
 
   case 46:
 
-/* Line 1455 of yacc.c  */
-#line 363 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 362 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 47:
 
-/* Line 1455 of yacc.c  */
-#line 368 "parser.y"
-    { (yyval.expr) = (yyvsp[(2) - (2)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 367 "parser.y"
+    { (yyval.expr) = (yyvsp[(2) - (2)].expr); }
     break;
 
   case 48:
 
-/* Line 1455 of yacc.c  */
-#line 372 "parser.y"
-    { (yyval.statement) = new_statement(ctx, STAT_EMPTY, 0); ;}
+/* Line 1806 of yacc.c  */
+#line 371 "parser.y"
+    { (yyval.statement) = new_statement(ctx, STAT_EMPTY, 0); }
     break;
 
   case 49:
 
-/* Line 1455 of yacc.c  */
-#line 377 "parser.y"
-    { (yyval.statement) = new_expression_statement(ctx, (yyvsp[(1) - (2)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 376 "parser.y"
+    { (yyval.statement) = new_expression_statement(ctx, (yyvsp[(1) - (2)].expr)); }
     break;
 
   case 50:
 
-/* Line 1455 of yacc.c  */
-#line 382 "parser.y"
-    { (yyval.statement) = new_if_statement(ctx, (yyvsp[(3) - (7)].expr), (yyvsp[(5) - (7)].statement), (yyvsp[(7) - (7)].statement)); ;}
+/* Line 1806 of yacc.c  */
+#line 381 "parser.y"
+    { (yyval.statement) = new_if_statement(ctx, (yyvsp[(3) - (7)].expr), (yyvsp[(5) - (7)].statement), (yyvsp[(7) - (7)].statement)); }
     break;
 
   case 51:
 
-/* Line 1455 of yacc.c  */
-#line 384 "parser.y"
-    { (yyval.statement) = new_if_statement(ctx, (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].statement), NULL); ;}
+/* Line 1806 of yacc.c  */
+#line 383 "parser.y"
+    { (yyval.statement) = new_if_statement(ctx, (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].statement), NULL); }
     break;
 
   case 52:
 
-/* Line 1455 of yacc.c  */
-#line 389 "parser.y"
-    { (yyval.statement) = new_while_statement(ctx, TRUE, (yyvsp[(5) - (7)].expr), (yyvsp[(2) - (7)].statement)); ;}
+/* Line 1806 of yacc.c  */
+#line 388 "parser.y"
+    { (yyval.statement) = new_while_statement(ctx, TRUE, (yyvsp[(5) - (7)].expr), (yyvsp[(2) - (7)].statement)); }
     break;
 
   case 53:
 
-/* Line 1455 of yacc.c  */
-#line 391 "parser.y"
-    { (yyval.statement) = new_while_statement(ctx, FALSE, (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].statement)); ;}
+/* Line 1806 of yacc.c  */
+#line 390 "parser.y"
+    { (yyval.statement) = new_while_statement(ctx, FALSE, (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].statement)); }
     break;
 
   case 54:
 
-/* Line 1455 of yacc.c  */
-#line 393 "parser.y"
-    { if(!explicit_error(ctx, (yyvsp[(3) - (3)].expr), ';')) YYABORT; ;}
+/* Line 1806 of yacc.c  */
+#line 392 "parser.y"
+    { if(!explicit_error(ctx, (yyvsp[(3) - (3)].expr), ';')) YYABORT; }
     break;
 
   case 55:
 
-/* Line 1455 of yacc.c  */
-#line 395 "parser.y"
-    { if(!explicit_error(ctx, (yyvsp[(6) - (6)].expr), ';')) YYABORT; ;}
+/* Line 1806 of yacc.c  */
+#line 394 "parser.y"
+    { if(!explicit_error(ctx, (yyvsp[(6) - (6)].expr), ';')) YYABORT; }
     break;
 
   case 56:
 
-/* Line 1455 of yacc.c  */
-#line 397 "parser.y"
-    { (yyval.statement) = new_for_statement(ctx, NULL, (yyvsp[(3) - (11)].expr), (yyvsp[(6) - (11)].expr), (yyvsp[(9) - (11)].expr), (yyvsp[(11) - (11)].statement)); ;}
+/* Line 1806 of yacc.c  */
+#line 396 "parser.y"
+    { (yyval.statement) = new_for_statement(ctx, NULL, (yyvsp[(3) - (11)].expr), (yyvsp[(6) - (11)].expr), (yyvsp[(9) - (11)].expr), (yyvsp[(11) - (11)].statement)); }
     break;
 
   case 57:
 
-/* Line 1455 of yacc.c  */
-#line 399 "parser.y"
-    { if(!explicit_error(ctx, (yyvsp[(4) - (4)].variable_list), ';')) YYABORT; ;}
+/* Line 1806 of yacc.c  */
+#line 398 "parser.y"
+    { if(!explicit_error(ctx, (yyvsp[(4) - (4)].variable_list), ';')) YYABORT; }
     break;
 
   case 58:
 
-/* Line 1455 of yacc.c  */
-#line 401 "parser.y"
-    { if(!explicit_error(ctx, (yyvsp[(7) - (7)].expr), ';')) YYABORT; ;}
+/* Line 1806 of yacc.c  */
+#line 400 "parser.y"
+    { if(!explicit_error(ctx, (yyvsp[(7) - (7)].expr), ';')) YYABORT; }
     break;
 
   case 59:
 
-/* Line 1455 of yacc.c  */
-#line 403 "parser.y"
-    { (yyval.statement) = new_for_statement(ctx, (yyvsp[(4) - (12)].variable_list), NULL, (yyvsp[(7) - (12)].expr), (yyvsp[(10) - (12)].expr), (yyvsp[(12) - (12)].statement)); ;}
+/* Line 1806 of yacc.c  */
+#line 402 "parser.y"
+    { (yyval.statement) = new_for_statement(ctx, (yyvsp[(4) - (12)].variable_list), NULL, (yyvsp[(7) - (12)].expr), (yyvsp[(10) - (12)].expr), (yyvsp[(12) - (12)].statement)); }
     break;
 
   case 60:
 
-/* Line 1455 of yacc.c  */
-#line 405 "parser.y"
-    { (yyval.statement) = new_forin_statement(ctx, NULL, (yyvsp[(3) - (7)].expr), (yyvsp[(5) - (7)].expr), (yyvsp[(7) - (7)].statement)); ;}
+/* Line 1806 of yacc.c  */
+#line 404 "parser.y"
+    { (yyval.statement) = new_forin_statement(ctx, NULL, (yyvsp[(3) - (7)].expr), (yyvsp[(5) - (7)].expr), (yyvsp[(7) - (7)].statement)); }
     break;
 
   case 61:
 
-/* Line 1455 of yacc.c  */
-#line 407 "parser.y"
-    { (yyval.statement) = new_forin_statement(ctx, (yyvsp[(4) - (8)].variable_declaration), NULL, (yyvsp[(6) - (8)].expr), (yyvsp[(8) - (8)].statement)); ;}
+/* Line 1806 of yacc.c  */
+#line 406 "parser.y"
+    { (yyval.statement) = new_forin_statement(ctx, (yyvsp[(4) - (8)].variable_declaration), NULL, (yyvsp[(6) - (8)].expr), (yyvsp[(8) - (8)].statement)); }
     break;
 
   case 62:
 
-/* Line 1455 of yacc.c  */
-#line 412 "parser.y"
-    { (yyval.statement) = new_continue_statement(ctx, (yyvsp[(2) - (3)].identifier)); ;}
+/* Line 1806 of yacc.c  */
+#line 411 "parser.y"
+    { (yyval.statement) = new_continue_statement(ctx, (yyvsp[(2) - (3)].identifier)); }
     break;
 
   case 63:
 
-/* Line 1455 of yacc.c  */
-#line 417 "parser.y"
-    { (yyval.statement) = new_break_statement(ctx, (yyvsp[(2) - (3)].identifier)); ;}
+/* Line 1806 of yacc.c  */
+#line 416 "parser.y"
+    { (yyval.statement) = new_break_statement(ctx, (yyvsp[(2) - (3)].identifier)); }
     break;
 
   case 64:
 
-/* Line 1455 of yacc.c  */
-#line 422 "parser.y"
-    { (yyval.statement) = new_return_statement(ctx, (yyvsp[(2) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 421 "parser.y"
+    { (yyval.statement) = new_return_statement(ctx, (yyvsp[(2) - (3)].expr)); }
     break;
 
   case 65:
 
-/* Line 1455 of yacc.c  */
-#line 427 "parser.y"
-    { (yyval.statement) = new_with_statement(ctx, (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].statement)); ;}
+/* Line 1806 of yacc.c  */
+#line 426 "parser.y"
+    { (yyval.statement) = new_with_statement(ctx, (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].statement)); }
     break;
 
   case 66:
 
-/* Line 1455 of yacc.c  */
-#line 432 "parser.y"
-    { (yyval.statement) = new_labelled_statement(ctx, (yyvsp[(1) - (3)].identifier), (yyvsp[(3) - (3)].statement)); ;}
+/* Line 1806 of yacc.c  */
+#line 431 "parser.y"
+    { (yyval.statement) = new_labelled_statement(ctx, (yyvsp[(1) - (3)].identifier), (yyvsp[(3) - (3)].statement)); }
     break;
 
   case 67:
 
-/* Line 1455 of yacc.c  */
-#line 437 "parser.y"
-    { (yyval.statement) = new_switch_statement(ctx, (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].case_clausule)); ;}
+/* Line 1806 of yacc.c  */
+#line 436 "parser.y"
+    { (yyval.statement) = new_switch_statement(ctx, (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].case_clausule)); }
     break;
 
   case 68:
 
-/* Line 1455 of yacc.c  */
-#line 442 "parser.y"
-    { (yyval.case_clausule) = new_case_block(ctx, (yyvsp[(2) - (3)].case_list), NULL, NULL); ;}
+/* Line 1806 of yacc.c  */
+#line 441 "parser.y"
+    { (yyval.case_clausule) = new_case_block(ctx, (yyvsp[(2) - (3)].case_list), NULL, NULL); }
     break;
 
   case 69:
 
-/* Line 1455 of yacc.c  */
-#line 444 "parser.y"
-    { (yyval.case_clausule) = new_case_block(ctx, (yyvsp[(2) - (5)].case_list), (yyvsp[(3) - (5)].case_clausule), (yyvsp[(4) - (5)].case_list)); ;}
+/* Line 1806 of yacc.c  */
+#line 443 "parser.y"
+    { (yyval.case_clausule) = new_case_block(ctx, (yyvsp[(2) - (5)].case_list), (yyvsp[(3) - (5)].case_clausule), (yyvsp[(4) - (5)].case_list)); }
     break;
 
   case 70:
 
-/* Line 1455 of yacc.c  */
-#line 448 "parser.y"
-    { (yyval.case_list) = NULL; ;}
+/* Line 1806 of yacc.c  */
+#line 447 "parser.y"
+    { (yyval.case_list) = NULL; }
     break;
 
   case 71:
 
-/* Line 1455 of yacc.c  */
-#line 449 "parser.y"
-    { (yyval.case_list) = (yyvsp[(1) - (1)].case_list); ;}
+/* Line 1806 of yacc.c  */
+#line 448 "parser.y"
+    { (yyval.case_list) = (yyvsp[(1) - (1)].case_list); }
     break;
 
   case 72:
 
-/* Line 1455 of yacc.c  */
-#line 453 "parser.y"
-    { (yyval.case_list) = new_case_list(ctx, (yyvsp[(1) - (1)].case_clausule)); ;}
+/* Line 1806 of yacc.c  */
+#line 452 "parser.y"
+    { (yyval.case_list) = new_case_list(ctx, (yyvsp[(1) - (1)].case_clausule)); }
     break;
 
   case 73:
 
-/* Line 1455 of yacc.c  */
-#line 455 "parser.y"
-    { (yyval.case_list) = case_list_add(ctx, (yyvsp[(1) - (2)].case_list), (yyvsp[(2) - (2)].case_clausule)); ;}
+/* Line 1806 of yacc.c  */
+#line 454 "parser.y"
+    { (yyval.case_list) = case_list_add(ctx, (yyvsp[(1) - (2)].case_list), (yyvsp[(2) - (2)].case_clausule)); }
     break;
 
   case 74:
 
-/* Line 1455 of yacc.c  */
-#line 460 "parser.y"
-    { (yyval.case_clausule) = new_case_clausule(ctx, (yyvsp[(2) - (4)].expr), (yyvsp[(4) - (4)].statement_list)); ;}
+/* Line 1806 of yacc.c  */
+#line 459 "parser.y"
+    { (yyval.case_clausule) = new_case_clausule(ctx, (yyvsp[(2) - (4)].expr), (yyvsp[(4) - (4)].statement_list)); }
     break;
 
   case 75:
 
-/* Line 1455 of yacc.c  */
-#line 465 "parser.y"
-    { (yyval.case_clausule) = new_case_clausule(ctx, NULL, (yyvsp[(3) - (3)].statement_list)); ;}
+/* Line 1806 of yacc.c  */
+#line 464 "parser.y"
+    { (yyval.case_clausule) = new_case_clausule(ctx, NULL, (yyvsp[(3) - (3)].statement_list)); }
     break;
 
   case 76:
 
-/* Line 1455 of yacc.c  */
-#line 470 "parser.y"
-    { (yyval.statement) = new_throw_statement(ctx, (yyvsp[(2) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 469 "parser.y"
+    { (yyval.statement) = new_throw_statement(ctx, (yyvsp[(2) - (3)].expr)); }
     break;
 
   case 77:
 
-/* Line 1455 of yacc.c  */
-#line 474 "parser.y"
-    { (yyval.statement) = new_try_statement(ctx, (yyvsp[(2) - (3)].statement), (yyvsp[(3) - (3)].catch_block), NULL); ;}
+/* Line 1806 of yacc.c  */
+#line 473 "parser.y"
+    { (yyval.statement) = new_try_statement(ctx, (yyvsp[(2) - (3)].statement), (yyvsp[(3) - (3)].catch_block), NULL); }
     break;
 
   case 78:
 
-/* Line 1455 of yacc.c  */
-#line 475 "parser.y"
-    { (yyval.statement) = new_try_statement(ctx, (yyvsp[(2) - (3)].statement), NULL, (yyvsp[(3) - (3)].statement)); ;}
+/* Line 1806 of yacc.c  */
+#line 474 "parser.y"
+    { (yyval.statement) = new_try_statement(ctx, (yyvsp[(2) - (3)].statement), NULL, (yyvsp[(3) - (3)].statement)); }
     break;
 
   case 79:
 
-/* Line 1455 of yacc.c  */
-#line 477 "parser.y"
-    { (yyval.statement) = new_try_statement(ctx, (yyvsp[(2) - (4)].statement), (yyvsp[(3) - (4)].catch_block), (yyvsp[(4) - (4)].statement)); ;}
+/* Line 1806 of yacc.c  */
+#line 476 "parser.y"
+    { (yyval.statement) = new_try_statement(ctx, (yyvsp[(2) - (4)].statement), (yyvsp[(3) - (4)].catch_block), (yyvsp[(4) - (4)].statement)); }
     break;
 
   case 80:
 
-/* Line 1455 of yacc.c  */
-#line 482 "parser.y"
-    { (yyval.catch_block) = new_catch_block(ctx, (yyvsp[(3) - (5)].identifier), (yyvsp[(5) - (5)].statement)); ;}
+/* Line 1806 of yacc.c  */
+#line 481 "parser.y"
+    { (yyval.catch_block) = new_catch_block(ctx, (yyvsp[(3) - (5)].identifier), (yyvsp[(5) - (5)].statement)); }
     break;
 
   case 81:
 
-/* Line 1455 of yacc.c  */
-#line 486 "parser.y"
-    { (yyval.statement) = (yyvsp[(2) - (2)].statement); ;}
+/* Line 1806 of yacc.c  */
+#line 485 "parser.y"
+    { (yyval.statement) = (yyvsp[(2) - (2)].statement); }
     break;
 
   case 82:
 
-/* Line 1455 of yacc.c  */
-#line 490 "parser.y"
-    { (yyval.expr) = NULL; ;}
+/* Line 1806 of yacc.c  */
+#line 489 "parser.y"
+    { (yyval.expr) = NULL; }
     break;
 
   case 83:
 
-/* Line 1455 of yacc.c  */
-#line 491 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 490 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 84:
 
-/* Line 1455 of yacc.c  */
-#line 494 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 493 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 85:
 
-/* Line 1455 of yacc.c  */
-#line 495 "parser.y"
-    { set_error(ctx, JS_E_SYNTAX); YYABORT; ;}
+/* Line 1806 of yacc.c  */
+#line 494 "parser.y"
+    { set_error(ctx, JS_E_SYNTAX); YYABORT; }
     break;
 
   case 86:
 
-/* Line 1455 of yacc.c  */
-#line 499 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 498 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 87:
 
-/* Line 1455 of yacc.c  */
-#line 501 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, EXPR_COMMA, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 500 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, EXPR_COMMA, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 88:
 
-/* Line 1455 of yacc.c  */
-#line 505 "parser.y"
-    { (yyval.expr) = NULL; ;}
+/* Line 1806 of yacc.c  */
+#line 504 "parser.y"
+    { (yyval.expr) = NULL; }
     break;
 
   case 89:
 
-/* Line 1455 of yacc.c  */
-#line 506 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 505 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 90:
 
-/* Line 1455 of yacc.c  */
-#line 511 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 510 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 91:
 
-/* Line 1455 of yacc.c  */
-#line 513 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, EXPR_COMMA, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 512 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, EXPR_COMMA, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 92:
 
-/* Line 1455 of yacc.c  */
-#line 516 "parser.y"
-    { (yyval.ival) = (yyvsp[(1) - (1)].ival); ;}
+/* Line 1806 of yacc.c  */
+#line 515 "parser.y"
+    { (yyval.ival) = (yyvsp[(1) - (1)].ival); }
     break;
 
   case 93:
 
-/* Line 1455 of yacc.c  */
-#line 517 "parser.y"
-    { (yyval.ival) = EXPR_ASSIGNDIV; ;}
+/* Line 1806 of yacc.c  */
+#line 516 "parser.y"
+    { (yyval.ival) = EXPR_ASSIGNDIV; }
     break;
 
   case 94:
 
-/* Line 1455 of yacc.c  */
-#line 521 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 520 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 95:
 
-/* Line 1455 of yacc.c  */
-#line 523 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, EXPR_ASSIGN, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 522 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, EXPR_ASSIGN, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 96:
 
-/* Line 1455 of yacc.c  */
-#line 525 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 524 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 97:
 
-/* Line 1455 of yacc.c  */
-#line 530 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 529 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 98:
 
-/* Line 1455 of yacc.c  */
-#line 532 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, EXPR_ASSIGN, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 531 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, EXPR_ASSIGN, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 99:
 
-/* Line 1455 of yacc.c  */
-#line 534 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 533 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 100:
 
-/* Line 1455 of yacc.c  */
-#line 538 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 537 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 101:
 
-/* Line 1455 of yacc.c  */
-#line 540 "parser.y"
-    { (yyval.expr) = new_conditional_expression(ctx, (yyvsp[(1) - (5)].expr), (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 539 "parser.y"
+    { (yyval.expr) = new_conditional_expression(ctx, (yyvsp[(1) - (5)].expr), (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].expr)); }
     break;
 
   case 102:
 
-/* Line 1455 of yacc.c  */
-#line 545 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 544 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 103:
 
-/* Line 1455 of yacc.c  */
-#line 547 "parser.y"
-    { (yyval.expr) = new_conditional_expression(ctx, (yyvsp[(1) - (5)].expr), (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 546 "parser.y"
+    { (yyval.expr) = new_conditional_expression(ctx, (yyvsp[(1) - (5)].expr), (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].expr)); }
     break;
 
   case 104:
 
-/* Line 1455 of yacc.c  */
-#line 551 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 550 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 105:
 
-/* Line 1455 of yacc.c  */
-#line 553 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, EXPR_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 552 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, EXPR_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 106:
 
-/* Line 1455 of yacc.c  */
-#line 558 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 557 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 107:
 
-/* Line 1455 of yacc.c  */
-#line 560 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, EXPR_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 559 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, EXPR_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 108:
 
-/* Line 1455 of yacc.c  */
-#line 564 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 563 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 109:
 
-/* Line 1455 of yacc.c  */
-#line 566 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, EXPR_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 565 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, EXPR_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 110:
 
-/* Line 1455 of yacc.c  */
-#line 571 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 570 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 111:
 
-/* Line 1455 of yacc.c  */
-#line 573 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, EXPR_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 572 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, EXPR_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 112:
 
-/* Line 1455 of yacc.c  */
-#line 577 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 576 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 113:
 
-/* Line 1455 of yacc.c  */
-#line 579 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, EXPR_BOR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 578 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, EXPR_BOR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 114:
 
-/* Line 1455 of yacc.c  */
-#line 584 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 583 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 115:
 
-/* Line 1455 of yacc.c  */
-#line 586 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, EXPR_BOR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 585 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, EXPR_BOR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 116:
 
-/* Line 1455 of yacc.c  */
-#line 590 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 589 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 117:
 
-/* Line 1455 of yacc.c  */
-#line 592 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, EXPR_BXOR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 591 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, EXPR_BXOR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 118:
 
-/* Line 1455 of yacc.c  */
-#line 597 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 596 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 119:
 
-/* Line 1455 of yacc.c  */
-#line 599 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, EXPR_BXOR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 598 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, EXPR_BXOR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 120:
 
-/* Line 1455 of yacc.c  */
-#line 603 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 602 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 121:
 
-/* Line 1455 of yacc.c  */
-#line 605 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, EXPR_BAND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 604 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, EXPR_BAND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 122:
 
-/* Line 1455 of yacc.c  */
-#line 610 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 609 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 123:
 
-/* Line 1455 of yacc.c  */
-#line 612 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, EXPR_BAND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 611 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, EXPR_BAND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 124:
 
-/* Line 1455 of yacc.c  */
-#line 616 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 615 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 125:
 
-/* Line 1455 of yacc.c  */
-#line 618 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 617 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 126:
 
-/* Line 1455 of yacc.c  */
-#line 622 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 621 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 127:
 
-/* Line 1455 of yacc.c  */
-#line 624 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 623 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 128:
 
-/* Line 1455 of yacc.c  */
-#line 628 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 627 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 129:
 
-/* Line 1455 of yacc.c  */
-#line 630 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 629 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 130:
 
-/* Line 1455 of yacc.c  */
-#line 632 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, EXPR_INSTANCEOF, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 631 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, EXPR_INSTANCEOF, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 131:
 
-/* Line 1455 of yacc.c  */
-#line 634 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, EXPR_IN, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 633 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, EXPR_IN, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 132:
 
-/* Line 1455 of yacc.c  */
-#line 638 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 637 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 133:
 
-/* Line 1455 of yacc.c  */
-#line 640 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 639 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 134:
 
-/* Line 1455 of yacc.c  */
-#line 642 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, EXPR_INSTANCEOF, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 641 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, EXPR_INSTANCEOF, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 135:
 
-/* Line 1455 of yacc.c  */
-#line 646 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 645 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 136:
 
-/* Line 1455 of yacc.c  */
-#line 648 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 647 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 137:
 
-/* Line 1455 of yacc.c  */
-#line 653 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 652 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 138:
 
-/* Line 1455 of yacc.c  */
-#line 655 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, EXPR_ADD, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 654 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, EXPR_ADD, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 139:
 
-/* Line 1455 of yacc.c  */
-#line 657 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, EXPR_SUB, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 656 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, EXPR_SUB, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 140:
 
-/* Line 1455 of yacc.c  */
-#line 661 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 660 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 141:
 
-/* Line 1455 of yacc.c  */
-#line 663 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, EXPR_MUL, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 662 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, EXPR_MUL, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 142:
 
-/* Line 1455 of yacc.c  */
-#line 665 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, EXPR_DIV, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 664 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, EXPR_DIV, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 143:
 
-/* Line 1455 of yacc.c  */
-#line 667 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, EXPR_MOD, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 666 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, EXPR_MOD, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 144:
 
-/* Line 1455 of yacc.c  */
-#line 671 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 670 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 145:
 
-/* Line 1455 of yacc.c  */
-#line 673 "parser.y"
-    { (yyval.expr) = new_unary_expression(ctx, EXPR_DELETE, (yyvsp[(2) - (2)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 672 "parser.y"
+    { (yyval.expr) = new_unary_expression(ctx, EXPR_DELETE, (yyvsp[(2) - (2)].expr)); }
     break;
 
   case 146:
 
-/* Line 1455 of yacc.c  */
-#line 674 "parser.y"
-    { (yyval.expr) = new_unary_expression(ctx, EXPR_VOID, (yyvsp[(2) - (2)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 673 "parser.y"
+    { (yyval.expr) = new_unary_expression(ctx, EXPR_VOID, (yyvsp[(2) - (2)].expr)); }
     break;
 
   case 147:
 
-/* Line 1455 of yacc.c  */
-#line 676 "parser.y"
-    { (yyval.expr) = new_unary_expression(ctx, EXPR_TYPEOF, (yyvsp[(2) - (2)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 675 "parser.y"
+    { (yyval.expr) = new_unary_expression(ctx, EXPR_TYPEOF, (yyvsp[(2) - (2)].expr)); }
     break;
 
   case 148:
 
-/* Line 1455 of yacc.c  */
-#line 677 "parser.y"
-    { (yyval.expr) = new_unary_expression(ctx, EXPR_PREINC, (yyvsp[(2) - (2)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 676 "parser.y"
+    { (yyval.expr) = new_unary_expression(ctx, EXPR_PREINC, (yyvsp[(2) - (2)].expr)); }
     break;
 
   case 149:
 
-/* Line 1455 of yacc.c  */
-#line 678 "parser.y"
-    { (yyval.expr) = new_unary_expression(ctx, EXPR_PREDEC, (yyvsp[(2) - (2)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 677 "parser.y"
+    { (yyval.expr) = new_unary_expression(ctx, EXPR_PREDEC, (yyvsp[(2) - (2)].expr)); }
     break;
 
   case 150:
 
-/* Line 1455 of yacc.c  */
-#line 679 "parser.y"
-    { (yyval.expr) = new_unary_expression(ctx, EXPR_PLUS, (yyvsp[(2) - (2)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 678 "parser.y"
+    { (yyval.expr) = new_unary_expression(ctx, EXPR_PLUS, (yyvsp[(2) - (2)].expr)); }
     break;
 
   case 151:
 
-/* Line 1455 of yacc.c  */
-#line 680 "parser.y"
-    { (yyval.expr) = new_unary_expression(ctx, EXPR_MINUS, (yyvsp[(2) - (2)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 679 "parser.y"
+    { (yyval.expr) = new_unary_expression(ctx, EXPR_MINUS, (yyvsp[(2) - (2)].expr)); }
     break;
 
   case 152:
 
-/* Line 1455 of yacc.c  */
-#line 681 "parser.y"
-    { (yyval.expr) = new_unary_expression(ctx, EXPR_BITNEG, (yyvsp[(2) - (2)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 680 "parser.y"
+    { (yyval.expr) = new_unary_expression(ctx, EXPR_BITNEG, (yyvsp[(2) - (2)].expr)); }
     break;
 
   case 153:
 
-/* Line 1455 of yacc.c  */
-#line 682 "parser.y"
-    { (yyval.expr) = new_unary_expression(ctx, EXPR_LOGNEG, (yyvsp[(2) - (2)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 681 "parser.y"
+    { (yyval.expr) = new_unary_expression(ctx, EXPR_LOGNEG, (yyvsp[(2) - (2)].expr)); }
     break;
 
   case 154:
 
-/* Line 1455 of yacc.c  */
-#line 687 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 686 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 155:
 
-/* Line 1455 of yacc.c  */
-#line 689 "parser.y"
-    { (yyval.expr) = new_unary_expression(ctx, EXPR_POSTINC, (yyvsp[(1) - (2)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 688 "parser.y"
+    { (yyval.expr) = new_unary_expression(ctx, EXPR_POSTINC, (yyvsp[(1) - (2)].expr)); }
     break;
 
   case 156:
 
-/* Line 1455 of yacc.c  */
-#line 691 "parser.y"
-    { (yyval.expr) = new_unary_expression(ctx, EXPR_POSTDEC, (yyvsp[(1) - (2)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 690 "parser.y"
+    { (yyval.expr) = new_unary_expression(ctx, EXPR_POSTDEC, (yyvsp[(1) - (2)].expr)); }
     break;
 
   case 157:
 
-/* Line 1455 of yacc.c  */
-#line 696 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 695 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 158:
 
-/* Line 1455 of yacc.c  */
-#line 697 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 696 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 159:
 
-/* Line 1455 of yacc.c  */
-#line 701 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 700 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 160:
 
-/* Line 1455 of yacc.c  */
-#line 702 "parser.y"
-    { (yyval.expr) = new_new_expression(ctx, (yyvsp[(2) - (2)].expr), NULL); ;}
+/* Line 1806 of yacc.c  */
+#line 701 "parser.y"
+    { (yyval.expr) = new_new_expression(ctx, (yyvsp[(2) - (2)].expr), NULL); }
     break;
 
   case 161:
 
-/* Line 1455 of yacc.c  */
-#line 706 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 705 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 162:
 
-/* Line 1455 of yacc.c  */
-#line 707 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 706 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 163:
 
-/* Line 1455 of yacc.c  */
-#line 709 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, EXPR_ARRAY, (yyvsp[(1) - (4)].expr), (yyvsp[(3) - (4)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 708 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, EXPR_ARRAY, (yyvsp[(1) - (4)].expr), (yyvsp[(3) - (4)].expr)); }
     break;
 
   case 164:
 
-/* Line 1455 of yacc.c  */
-#line 711 "parser.y"
-    { (yyval.expr) = new_member_expression(ctx, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].identifier)); ;}
+/* Line 1806 of yacc.c  */
+#line 710 "parser.y"
+    { (yyval.expr) = new_member_expression(ctx, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].identifier)); }
     break;
 
   case 165:
 
-/* Line 1455 of yacc.c  */
-#line 713 "parser.y"
-    { (yyval.expr) = new_new_expression(ctx, (yyvsp[(2) - (3)].expr), (yyvsp[(3) - (3)].argument_list)); ;}
+/* Line 1806 of yacc.c  */
+#line 712 "parser.y"
+    { (yyval.expr) = new_new_expression(ctx, (yyvsp[(2) - (3)].expr), (yyvsp[(3) - (3)].argument_list)); }
     break;
 
   case 166:
 
-/* Line 1455 of yacc.c  */
-#line 718 "parser.y"
-    { (yyval.expr) = new_call_expression(ctx, (yyvsp[(1) - (2)].expr), (yyvsp[(2) - (2)].argument_list)); ;}
+/* Line 1806 of yacc.c  */
+#line 717 "parser.y"
+    { (yyval.expr) = new_call_expression(ctx, (yyvsp[(1) - (2)].expr), (yyvsp[(2) - (2)].argument_list)); }
     break;
 
   case 167:
 
-/* Line 1455 of yacc.c  */
-#line 720 "parser.y"
-    { (yyval.expr) = new_call_expression(ctx, (yyvsp[(1) - (2)].expr), (yyvsp[(2) - (2)].argument_list)); ;}
+/* Line 1806 of yacc.c  */
+#line 719 "parser.y"
+    { (yyval.expr) = new_call_expression(ctx, (yyvsp[(1) - (2)].expr), (yyvsp[(2) - (2)].argument_list)); }
     break;
 
   case 168:
 
-/* Line 1455 of yacc.c  */
-#line 722 "parser.y"
-    { (yyval.expr) = new_binary_expression(ctx, EXPR_ARRAY, (yyvsp[(1) - (4)].expr), (yyvsp[(3) - (4)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 721 "parser.y"
+    { (yyval.expr) = new_binary_expression(ctx, EXPR_ARRAY, (yyvsp[(1) - (4)].expr), (yyvsp[(3) - (4)].expr)); }
     break;
 
   case 169:
 
-/* Line 1455 of yacc.c  */
-#line 724 "parser.y"
-    { (yyval.expr) = new_member_expression(ctx, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].identifier)); ;}
+/* Line 1806 of yacc.c  */
+#line 723 "parser.y"
+    { (yyval.expr) = new_member_expression(ctx, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].identifier)); }
     break;
 
   case 170:
 
-/* Line 1455 of yacc.c  */
-#line 728 "parser.y"
-    { (yyval.argument_list) = NULL; ;}
+/* Line 1806 of yacc.c  */
+#line 727 "parser.y"
+    { (yyval.argument_list) = NULL; }
     break;
 
   case 171:
 
-/* Line 1455 of yacc.c  */
-#line 729 "parser.y"
-    { (yyval.argument_list) = (yyvsp[(2) - (3)].argument_list); ;}
+/* Line 1806 of yacc.c  */
+#line 728 "parser.y"
+    { (yyval.argument_list) = (yyvsp[(2) - (3)].argument_list); }
     break;
 
   case 172:
 
-/* Line 1455 of yacc.c  */
-#line 733 "parser.y"
-    { (yyval.argument_list) = new_argument_list(ctx, (yyvsp[(1) - (1)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 732 "parser.y"
+    { (yyval.argument_list) = new_argument_list(ctx, (yyvsp[(1) - (1)].expr)); }
     break;
 
   case 173:
 
-/* Line 1455 of yacc.c  */
-#line 735 "parser.y"
-    { (yyval.argument_list) = argument_list_add(ctx, (yyvsp[(1) - (3)].argument_list), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 734 "parser.y"
+    { (yyval.argument_list) = argument_list_add(ctx, (yyvsp[(1) - (3)].argument_list), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 174:
 
-/* Line 1455 of yacc.c  */
-#line 739 "parser.y"
-    { (yyval.expr) = new_expression(ctx, EXPR_THIS, 0); ;}
+/* Line 1806 of yacc.c  */
+#line 738 "parser.y"
+    { (yyval.expr) = new_expression(ctx, EXPR_THIS, 0); }
     break;
 
   case 175:
 
-/* Line 1455 of yacc.c  */
-#line 740 "parser.y"
-    { (yyval.expr) = new_identifier_expression(ctx, (yyvsp[(1) - (1)].identifier)); ;}
+/* Line 1806 of yacc.c  */
+#line 739 "parser.y"
+    { (yyval.expr) = new_identifier_expression(ctx, (yyvsp[(1) - (1)].identifier)); }
     break;
 
   case 176:
 
-/* Line 1455 of yacc.c  */
-#line 741 "parser.y"
-    { (yyval.expr) = new_literal_expression(ctx, (yyvsp[(1) - (1)].literal)); ;}
+/* Line 1806 of yacc.c  */
+#line 740 "parser.y"
+    { (yyval.expr) = new_literal_expression(ctx, (yyvsp[(1) - (1)].literal)); }
     break;
 
   case 177:
 
-/* Line 1455 of yacc.c  */
-#line 742 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 741 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 178:
 
-/* Line 1455 of yacc.c  */
-#line 743 "parser.y"
-    { (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 742 "parser.y"
+    { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
     break;
 
   case 179:
 
-/* Line 1455 of yacc.c  */
-#line 744 "parser.y"
-    { (yyval.expr) = (yyvsp[(2) - (3)].expr); ;}
+/* Line 1806 of yacc.c  */
+#line 743 "parser.y"
+    { (yyval.expr) = (yyvsp[(2) - (3)].expr); }
     break;
 
   case 180:
 
-/* Line 1455 of yacc.c  */
-#line 748 "parser.y"
-    { (yyval.expr) = new_array_literal_expression(ctx, NULL, 0); ;}
+/* Line 1806 of yacc.c  */
+#line 747 "parser.y"
+    { (yyval.expr) = new_array_literal_expression(ctx, NULL, 0); }
     break;
 
   case 181:
 
-/* Line 1455 of yacc.c  */
-#line 749 "parser.y"
-    { (yyval.expr) = new_array_literal_expression(ctx, NULL, (yyvsp[(2) - (3)].ival)+1); ;}
+/* Line 1806 of yacc.c  */
+#line 748 "parser.y"
+    { (yyval.expr) = new_array_literal_expression(ctx, NULL, (yyvsp[(2) - (3)].ival)+1); }
     break;
 
   case 182:
 
-/* Line 1455 of yacc.c  */
-#line 750 "parser.y"
-    { (yyval.expr) = new_array_literal_expression(ctx, (yyvsp[(2) - (3)].element_list), 0); ;}
+/* Line 1806 of yacc.c  */
+#line 749 "parser.y"
+    { (yyval.expr) = new_array_literal_expression(ctx, (yyvsp[(2) - (3)].element_list), 0); }
     break;
 
   case 183:
 
-/* Line 1455 of yacc.c  */
-#line 752 "parser.y"
-    { (yyval.expr) = new_array_literal_expression(ctx, (yyvsp[(2) - (5)].element_list), (yyvsp[(4) - (5)].ival)+1); ;}
+/* Line 1806 of yacc.c  */
+#line 751 "parser.y"
+    { (yyval.expr) = new_array_literal_expression(ctx, (yyvsp[(2) - (5)].element_list), (yyvsp[(4) - (5)].ival)+1); }
     break;
 
   case 184:
 
-/* Line 1455 of yacc.c  */
-#line 757 "parser.y"
-    { (yyval.element_list) = new_element_list(ctx, (yyvsp[(1) - (2)].ival), (yyvsp[(2) - (2)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 756 "parser.y"
+    { (yyval.element_list) = new_element_list(ctx, (yyvsp[(1) - (2)].ival), (yyvsp[(2) - (2)].expr)); }
     break;
 
   case 185:
 
-/* Line 1455 of yacc.c  */
-#line 759 "parser.y"
-    { (yyval.element_list) = element_list_add(ctx, (yyvsp[(1) - (4)].element_list), (yyvsp[(3) - (4)].ival), (yyvsp[(4) - (4)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 758 "parser.y"
+    { (yyval.element_list) = element_list_add(ctx, (yyvsp[(1) - (4)].element_list), (yyvsp[(3) - (4)].ival), (yyvsp[(4) - (4)].expr)); }
     break;
 
   case 186:
 
-/* Line 1455 of yacc.c  */
-#line 763 "parser.y"
-    { (yyval.ival) = 1; ;}
+/* Line 1806 of yacc.c  */
+#line 762 "parser.y"
+    { (yyval.ival) = 1; }
     break;
 
   case 187:
 
-/* Line 1455 of yacc.c  */
-#line 764 "parser.y"
-    { (yyval.ival) = (yyvsp[(1) - (2)].ival) + 1; ;}
+/* Line 1806 of yacc.c  */
+#line 763 "parser.y"
+    { (yyval.ival) = (yyvsp[(1) - (2)].ival) + 1; }
     break;
 
   case 188:
 
-/* Line 1455 of yacc.c  */
-#line 768 "parser.y"
-    { (yyval.ival) = 0; ;}
+/* Line 1806 of yacc.c  */
+#line 767 "parser.y"
+    { (yyval.ival) = 0; }
     break;
 
   case 189:
 
-/* Line 1455 of yacc.c  */
-#line 769 "parser.y"
-    { (yyval.ival) = (yyvsp[(1) - (1)].ival); ;}
+/* Line 1806 of yacc.c  */
+#line 768 "parser.y"
+    { (yyval.ival) = (yyvsp[(1) - (1)].ival); }
     break;
 
   case 190:
 
-/* Line 1455 of yacc.c  */
-#line 773 "parser.y"
-    { (yyval.expr) = new_prop_and_value_expression(ctx, NULL); ;}
+/* Line 1806 of yacc.c  */
+#line 772 "parser.y"
+    { (yyval.expr) = new_prop_and_value_expression(ctx, NULL); }
     break;
 
   case 191:
 
-/* Line 1455 of yacc.c  */
-#line 775 "parser.y"
-    { (yyval.expr) = new_prop_and_value_expression(ctx, (yyvsp[(2) - (3)].property_list)); ;}
+/* Line 1806 of yacc.c  */
+#line 774 "parser.y"
+    { (yyval.expr) = new_prop_and_value_expression(ctx, (yyvsp[(2) - (3)].property_list)); }
     break;
 
   case 192:
 
-/* Line 1455 of yacc.c  */
-#line 780 "parser.y"
-    { (yyval.property_list) = new_property_list(ctx, (yyvsp[(1) - (3)].literal), (yyvsp[(3) - (3)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 779 "parser.y"
+    { (yyval.property_list) = new_property_list(ctx, (yyvsp[(1) - (3)].literal), (yyvsp[(3) - (3)].expr)); }
     break;
 
   case 193:
 
-/* Line 1455 of yacc.c  */
-#line 782 "parser.y"
-    { (yyval.property_list) = property_list_add(ctx, (yyvsp[(1) - (5)].property_list), (yyvsp[(3) - (5)].literal), (yyvsp[(5) - (5)].expr)); ;}
+/* Line 1806 of yacc.c  */
+#line 781 "parser.y"
+    { (yyval.property_list) = property_list_add(ctx, (yyvsp[(1) - (5)].property_list), (yyvsp[(3) - (5)].literal), (yyvsp[(5) - (5)].expr)); }
     break;
 
   case 194:
 
-/* Line 1455 of yacc.c  */
-#line 786 "parser.y"
-    { (yyval.literal) = new_string_literal(ctx, (yyvsp[(1) - (1)].identifier)); ;}
+/* Line 1806 of yacc.c  */
+#line 785 "parser.y"
+    { (yyval.literal) = new_string_literal(ctx, (yyvsp[(1) - (1)].identifier)); }
     break;
 
   case 195:
 
-/* Line 1455 of yacc.c  */
-#line 787 "parser.y"
-    { (yyval.literal) = new_string_literal(ctx, (yyvsp[(1) - (1)].wstr)); ;}
+/* Line 1806 of yacc.c  */
+#line 786 "parser.y"
+    { (yyval.literal) = new_string_literal(ctx, (yyvsp[(1) - (1)].wstr)); }
     break;
 
   case 196:
 
-/* Line 1455 of yacc.c  */
-#line 788 "parser.y"
-    { (yyval.literal) = (yyvsp[(1) - (1)].literal); ;}
+/* Line 1806 of yacc.c  */
+#line 787 "parser.y"
+    { (yyval.literal) = (yyvsp[(1) - (1)].literal); }
     break;
 
   case 197:
 
-/* Line 1455 of yacc.c  */
-#line 792 "parser.y"
-    { (yyval.identifier) = NULL; ;}
+/* Line 1806 of yacc.c  */
+#line 791 "parser.y"
+    { (yyval.identifier) = NULL; }
     break;
 
   case 198:
 
-/* Line 1455 of yacc.c  */
-#line 793 "parser.y"
-    { (yyval.identifier) = (yyvsp[(1) - (1)].identifier); ;}
+/* Line 1806 of yacc.c  */
+#line 792 "parser.y"
+    { (yyval.identifier) = (yyvsp[(1) - (1)].identifier); }
     break;
 
   case 199:
 
-/* Line 1455 of yacc.c  */
-#line 797 "parser.y"
-    { (yyval.literal) = new_null_literal(ctx); ;}
+/* Line 1806 of yacc.c  */
+#line 796 "parser.y"
+    { (yyval.literal) = new_null_literal(ctx); }
     break;
 
   case 200:
 
-/* Line 1455 of yacc.c  */
-#line 798 "parser.y"
-    { (yyval.literal) = (yyvsp[(1) - (1)].literal); ;}
+/* Line 1806 of yacc.c  */
+#line 797 "parser.y"
+    { (yyval.literal) = (yyvsp[(1) - (1)].literal); }
     break;
 
   case 201:
 
-/* Line 1455 of yacc.c  */
-#line 799 "parser.y"
-    { (yyval.literal) = (yyvsp[(1) - (1)].literal); ;}
+/* Line 1806 of yacc.c  */
+#line 798 "parser.y"
+    { (yyval.literal) = (yyvsp[(1) - (1)].literal); }
     break;
 
   case 202:
 
-/* Line 1455 of yacc.c  */
-#line 800 "parser.y"
-    { (yyval.literal) = new_string_literal(ctx, (yyvsp[(1) - (1)].wstr)); ;}
+/* Line 1806 of yacc.c  */
+#line 799 "parser.y"
+    { (yyval.literal) = new_string_literal(ctx, (yyvsp[(1) - (1)].wstr)); }
     break;
 
   case 203:
 
-/* Line 1455 of yacc.c  */
-#line 801 "parser.y"
+/* Line 1806 of yacc.c  */
+#line 800 "parser.y"
     { (yyval.literal) = parse_regexp(ctx);
-                                  if(!(yyval.literal)) YYABORT; ;}
+                                  if(!(yyval.literal)) YYABORT; }
     break;
 
   case 204:
 
-/* Line 1455 of yacc.c  */
-#line 803 "parser.y"
+/* Line 1806 of yacc.c  */
+#line 802 "parser.y"
     { (yyval.literal) = parse_regexp(ctx);
-                                  if(!(yyval.literal)) YYABORT; ;}
+                                  if(!(yyval.literal)) YYABORT; }
     break;
 
   case 205:
 
-/* Line 1455 of yacc.c  */
-#line 808 "parser.y"
-    { (yyval.literal) = new_boolean_literal(ctx, VARIANT_TRUE); ;}
+/* Line 1806 of yacc.c  */
+#line 807 "parser.y"
+    { (yyval.literal) = new_boolean_literal(ctx, VARIANT_TRUE); }
     break;
 
   case 206:
 
-/* Line 1455 of yacc.c  */
-#line 809 "parser.y"
-    { (yyval.literal) = new_boolean_literal(ctx, VARIANT_FALSE); ;}
+/* Line 1806 of yacc.c  */
+#line 808 "parser.y"
+    { (yyval.literal) = new_boolean_literal(ctx, VARIANT_FALSE); }
     break;
 
   case 207:
 
-/* Line 1455 of yacc.c  */
-#line 810 "parser.y"
-    { (yyval.literal) = (yyvsp[(1) - (1)].literal); ;}
+/* Line 1806 of yacc.c  */
+#line 809 "parser.y"
+    { (yyval.literal) = (yyvsp[(1) - (1)].literal); }
     break;
 
   case 209:
 
-/* Line 1455 of yacc.c  */
-#line 814 "parser.y"
-    { if(!allow_auto_semicolon(ctx)) {YYABORT;} ;}
+/* Line 1806 of yacc.c  */
+#line 813 "parser.y"
+    { if(!allow_auto_semicolon(ctx)) {YYABORT;} }
     break;
 
   case 211:
 
-/* Line 1455 of yacc.c  */
-#line 818 "parser.y"
-    { set_error(ctx, JS_E_MISSING_LBRACKET); YYABORT; ;}
+/* Line 1806 of yacc.c  */
+#line 817 "parser.y"
+    { set_error(ctx, JS_E_MISSING_LBRACKET); YYABORT; }
     break;
 
   case 213:
 
-/* Line 1455 of yacc.c  */
-#line 822 "parser.y"
-    { set_error(ctx, JS_E_MISSING_RBRACKET); YYABORT; ;}
+/* Line 1806 of yacc.c  */
+#line 821 "parser.y"
+    { set_error(ctx, JS_E_MISSING_RBRACKET); YYABORT; }
     break;
 
   case 215:
 
-/* Line 1455 of yacc.c  */
-#line 826 "parser.y"
-    { set_error(ctx, JS_E_MISSING_SEMICOLON); YYABORT; ;}
+/* Line 1806 of yacc.c  */
+#line 825 "parser.y"
+    { set_error(ctx, JS_E_MISSING_SEMICOLON); YYABORT; }
     break;
 
 
 
-/* Line 1455 of yacc.c  */
-#line 3507 "parser.tab.c"
+/* Line 1806 of yacc.c  */
+#line 3540 "parser.tab.c"
       default: break;
     }
+  /* User semantic actions sometimes alter yychar, and that requires
+     that yytoken be updated with the new translation.  We take the
+     approach of translating immediately before every use of yytoken.
+     One alternative is translating here after every semantic action,
+     but that translation would be missed if the semantic action invokes
+     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
+     incorrect destructor might then be invoked immediately.  In the
+     case of YYERROR or YYBACKUP, subsequent parser actions might lead
+     to an incorrect destructor call or verbose syntax error message
+     before the lookahead is translated.  */
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
 
   YYPOPSTACK (yylen);
@@ -3533,44 +3577,47 @@ yyreduce:
 | yyerrlab -- here on detecting error |
 `------------------------------------*/
 yyerrlab:
+  /* Make sure we have latest lookahead translation.  See comments at
+     user semantic actions for why this is necessary.  */
+  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
   /* If not already recovering from an error, report this error.  */
   if (!yyerrstatus)
     {
       ++yynerrs;
 #if ! YYERROR_VERBOSE
-      yyerror (YY_("syntax error"));
+      yyerror (ctx, YY_("syntax error"));
 #else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+                                        yyssp, yytoken)
       {
-       YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
-       if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
-         {
-           YYSIZE_T yyalloc = 2 * yysize;
-           if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
-             yyalloc = YYSTACK_ALLOC_MAXIMUM;
-           if (yymsg != yymsgbuf)
-             YYSTACK_FREE (yymsg);
-           yymsg = (char *) YYSTACK_ALLOC (yyalloc);
-           if (yymsg)
-             yymsg_alloc = yyalloc;
-           else
-             {
-               yymsg = yymsgbuf;
-               yymsg_alloc = sizeof yymsgbuf;
-             }
-         }
-
-       if (0 < yysize && yysize <= yymsg_alloc)
-         {
-           (void) yysyntax_error (yymsg, yystate, yychar);
-           yyerror (yymsg);
-         }
-       else
-         {
-           yyerror (YY_("syntax error"));
-           if (yysize != 0)
-             goto yyexhaustedlab;
-         }
+        char const *yymsgp = YY_("syntax error");
+        int yysyntax_error_status;
+        yysyntax_error_status = YYSYNTAX_ERROR;
+        if (yysyntax_error_status == 0)
+          yymsgp = yymsg;
+        else if (yysyntax_error_status == 1)
+          {
+            if (yymsg != yymsgbuf)
+              YYSTACK_FREE (yymsg);
+            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+            if (!yymsg)
+              {
+                yymsg = yymsgbuf;
+                yymsg_alloc = sizeof yymsgbuf;
+                yysyntax_error_status = 2;
+              }
+            else
+              {
+                yysyntax_error_status = YYSYNTAX_ERROR;
+                yymsgp = yymsg;
+              }
+          }
+        yyerror (ctx, yymsgp);
+        if (yysyntax_error_status == 2)
+          goto yyexhaustedlab;
       }
+# undef YYSYNTAX_ERROR
 #endif
     }
 
@@ -3590,7 +3637,7 @@ yyerrlab:
       else
        {
          yydestruct ("Error: discarding",
-                     yytoken, &yylval);
+                     yytoken, &yylval, ctx);
          yychar = YYEMPTY;
        }
     }
@@ -3629,7 +3676,7 @@ yyerrlab1:
   for (;;)
     {
       yyn = yypact[yystate];
-      if (yyn != YYPACT_NINF)
+      if (!yypact_value_is_default (yyn))
        {
          yyn += YYTERROR;
          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
@@ -3646,7 +3693,7 @@ yyerrlab1:
 
 
       yydestruct ("Error: popping",
-                 yystos[yystate], yyvsp);
+                 yystos[yystate], yyvsp, ctx);
       YYPOPSTACK (1);
       yystate = *yyssp;
       YY_STACK_PRINT (yyss, yyssp);
@@ -3681,15 +3728,20 @@ yyabortlab:
 | yyexhaustedlab -- memory exhaustion comes here.  |
 `-------------------------------------------------*/
 yyexhaustedlab:
-  yyerror (YY_("memory exhausted"));
+  yyerror (ctx, YY_("memory exhausted"));
   yyresult = 2;
   /* Fall through.  */
 #endif
 
 yyreturn:
   if (yychar != YYEMPTY)
-     yydestruct ("Cleanup: discarding lookahead",
-                yytoken, &yylval);
+    {
+      /* Make sure we have latest lookahead translation.  See comments at
+         user semantic actions for why this is necessary.  */
+      yytoken = YYTRANSLATE (yychar);
+      yydestruct ("Cleanup: discarding lookahead",
+                  yytoken, &yylval, ctx);
+    }
   /* Do not reclaim the symbols of the rule which action triggered
      this YYABORT or YYACCEPT.  */
   YYPOPSTACK (yylen);
@@ -3697,7 +3749,7 @@ yyreturn:
   while (yyssp != yyss)
     {
       yydestruct ("Cleanup: popping",
-                 yystos[*yyssp], yyvsp);
+                 yystos[*yyssp], yyvsp, ctx);
       YYPOPSTACK (1);
     }
 #ifndef yyoverflow
@@ -3714,8 +3766,8 @@ yyreturn:
 
 
 
-/* Line 1675 of yacc.c  */
-#line 828 "parser.y"
+/* Line 2067 of yacc.c  */
+#line 827 "parser.y"
 
 
 static BOOL allow_auto_semicolon(parser_ctx_t *ctx)
@@ -4277,7 +4329,7 @@ static expression_t *new_call_expression(parser_ctx_t *ctx, expression_t *expres
     return &ret->expr;
 }
 
-static int parser_error(const char *str)
+static int parser_error(parser_ctx_t *ctx, const char *str)
 {
     return 0;
 }
index 07151ac..7fd676c 100644 (file)
@@ -1,10 +1,8 @@
+/* A Bison parser, made by GNU Bison 2.5.  */
 
-/* A Bison parser, made by GNU Bison 2.4.1.  */
-
-/* Skeleton interface for Bison's Yacc-like parsers in C
+/* Bison interface for Yacc-like parsers in C
    
-      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
+      Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
    
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -92,8 +90,8 @@
 typedef union YYSTYPE
 {
 
-/* Line 1676 of yacc.c  */
-#line 145 "parser.y"
+/* Line 2068 of yacc.c  */
+#line 144 "parser.y"
 
     int                     ival;
     const WCHAR             *srcptr;
@@ -116,8 +114,8 @@ typedef union YYSTYPE
 
 
 
-/* Line 1676 of yacc.c  */
-#line 121 "parser.tab.h"
+/* Line 2068 of yacc.c  */
+#line 119 "parser.tab.h"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
index f5a2e72..b1ce3a6 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
 
-#define YYLEX_PARAM ctx
-#define YYPARSE_PARAM ctx
-
-static int parser_error(const char*);
+static int parser_error(parser_ctx_t*,const char*);
 static void set_error(parser_ctx_t*,UINT);
 static BOOL explicit_error(parser_ctx_t*,void*,WCHAR);
 static BOOL allow_auto_semicolon(parser_ctx_t*);
@@ -139,7 +136,9 @@ static source_elements_t *source_elements_add_statement(source_elements_t*,state
 
 %}
 
-%pure_parser
+%lex-param { parser_ctx_t *ctx }
+%parse-param { parser_ctx_t *ctx }
+%pure-parser
 %start Program
 
 %union {
index 80392a9..e86c706 100644 (file)
@@ -90,6 +90,22 @@ static HRESULT get_string_val(script_ctx_t *ctx, vdisp_t *jsthis, jsstr_t **val)
     return to_string(ctx, jsval_disp(jsthis->u.disp), val);
 }
 
+static HRESULT get_string_flat_val(script_ctx_t *ctx, vdisp_t *jsthis, jsstr_t **jsval, const WCHAR **val)
+{
+    HRESULT hres;
+
+    hres = get_string_val(ctx, jsthis, jsval);
+    if(FAILED(hres))
+        return hres;
+
+    *val = jsstr_flatten(*jsval);
+    if(*val)
+        return S_OK;
+
+    jsstr_release(*jsval);
+    return E_OUTOFMEMORY;
+}
+
 static HRESULT String_length(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
         jsval_t *r)
 {
@@ -160,13 +176,12 @@ static HRESULT do_attributeless_tag_format(script_ctx_t *ctx, vdisp_t *jsthis, j
 
     tagname_len = strlenW(tagname);
 
-    ret = jsstr_alloc_buf(jsstr_length(str) + 2*tagname_len + 5);
+    ptr = jsstr_alloc_buf(jsstr_length(str) + 2*tagname_len + 5, &ret);
     if(!ret) {
         jsstr_release(str);
         return E_OUTOFMEMORY;
     }
 
-    ptr = ret->str;
     *ptr++ = '<';
     memcpy(ptr, tagname, tagname_len*sizeof(WCHAR));
     ptr += tagname_len;
@@ -209,11 +224,10 @@ static HRESULT do_attribute_tag_format(script_ctx_t *ctx, vdisp_t *jsthis, unsig
         unsigned attrname_len = strlenW(attrname);
         unsigned tagname_len = strlenW(tagname);
         jsstr_t *ret;
+        WCHAR *ptr;
 
-        ret = jsstr_alloc_buf(2*tagname_len + attrname_len + jsstr_length(attr_value) + jsstr_length(str) + 9);
-        if(ret) {
-            WCHAR *ptr = ret->str;
-
+        ptr = jsstr_alloc_buf(2*tagname_len + attrname_len + jsstr_length(attr_value) + jsstr_length(str) + 9, &ret);
+        if(ptr) {
             *ptr++ = '<';
             memcpy(ptr, tagname, tagname_len*sizeof(WCHAR));
             ptr += tagname_len;
@@ -349,8 +363,11 @@ static HRESULT String_charCodeAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
         idx = d;
     }
 
-    if(r)
-        *r = jsval_number(str->str[idx]);
+    if(r) {
+        WCHAR c;
+        jsstr_extract(str, idx, 1, &c);
+        *r = jsval_number(c);
+    }
 
     jsstr_release(str);
     return S_OK;
@@ -360,52 +377,80 @@ static HRESULT String_charCodeAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
 static HRESULT String_concat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
         jsval_t *r)
 {
-    unsigned len = 0, i, str_cnt;
-    jsstr_t **strs, *ret = NULL;
-    WCHAR *ptr;
+    jsstr_t *ret, *str;
     HRESULT hres;
 
     TRACE("\n");
 
-    str_cnt = argc+1;
-    strs = heap_alloc_zero(str_cnt * sizeof(*strs));
-    if(!strs)
-        return E_OUTOFMEMORY;
+    hres = get_string_val(ctx, jsthis, &str);
+    if(FAILED(hres))
+        return hres;
 
-    hres = to_string(ctx, jsval_disp(jsthis->u.disp), strs);
-    if(SUCCEEDED(hres)) {
+    switch(argc) {
+    case 0:
+        ret = str;
+        break;
+    case 1: {
+        jsstr_t *arg_str;
+
+        hres = to_string(ctx, argv[0], &arg_str);
+        if(FAILED(hres)) {
+            jsstr_release(str);
+            return hres;
+        }
+
+        ret = jsstr_concat(str, arg_str);
+        jsstr_release(str);
+        if(!ret)
+            return E_OUTOFMEMORY;
+        break;
+    }
+    default: {
+        const unsigned str_cnt = argc+1;
+        unsigned len = 0, i;
+        jsstr_t **strs;
+        WCHAR *ptr;
+
+        strs = heap_alloc_zero(str_cnt * sizeof(*strs));
+        if(!strs) {
+            jsstr_release(str);
+            return E_OUTOFMEMORY;
+        }
+
+        strs[0] = str;
         for(i=0; i < argc; i++) {
             hres = to_string(ctx, argv[i], strs+i+1);
             if(FAILED(hres))
                 break;
         }
-    }
 
-    if(SUCCEEDED(hres)) {
-        for(i=0; i < str_cnt; i++) {
-            len += jsstr_length(strs[i]);
-            if(len > JSSTR_MAX_LENGTH) {
-                hres = E_OUTOFMEMORY;
-                break;
+        if(SUCCEEDED(hres)) {
+            for(i=0; i < str_cnt; i++) {
+                len += jsstr_length(strs[i]);
+                if(len > JSSTR_MAX_LENGTH) {
+                    hres = E_OUTOFMEMORY;
+                    break;
+                }
             }
-        }
 
-        ret = jsstr_alloc_buf(len);
-        if(ret) {
-            ptr = ret->str;
-            for(i=0; i < str_cnt; i++)
-                ptr += jsstr_flush(strs[i], ptr);
-        }else {
-            hres = E_OUTOFMEMORY;
+            if(SUCCEEDED(hres)) {
+                ptr = jsstr_alloc_buf(len, &ret);
+                if(ptr) {
+                    for(i=0; i < str_cnt; i++)
+                        ptr += jsstr_flush(strs[i], ptr);
+                }else {
+                    hres = E_OUTOFMEMORY;
+                }
+            }
         }
-    }
-
-    for(i=0; i < str_cnt; i++)
-        jsstr_release(strs[i]);
-    heap_free(strs);
 
-    if(FAILED(hres))
-        return hres;
+        while(i--)
+            jsstr_release(strs[i]);
+        heap_free(strs);
+        if(FAILED(hres))
+            return hres;
+    }
+    }
 
     if(r)
         *r = jsval_string(ret);
@@ -442,28 +487,29 @@ static HRESULT String_fontsize(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u
 static HRESULT String_indexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
         jsval_t *r)
 {
-    jsstr_t *search_str, *str;
+    jsstr_t *search_jsstr, *jsstr;
+    const WCHAR *search_str, *str;
     int length, pos = 0;
     INT ret = -1;
     HRESULT hres;
 
     TRACE("\n");
 
-    hres = get_string_val(ctx, jsthis, &str);
+    hres = get_string_flat_val(ctx, jsthis, &jsstr, &str);
     if(FAILED(hres))
         return hres;
 
-    length = jsstr_length(str);
+    length = jsstr_length(jsstr);
     if(!argc) {
         if(r)
             *r = jsval_number(-1);
-        jsstr_release(str);
+        jsstr_release(jsstr);
         return S_OK;
     }
 
-    hres = to_string(ctx, argv[0], &search_str);
+    hres = to_flat_string(ctx, argv[0], &search_jsstr, &search_str);
     if(FAILED(hres)) {
-        jsstr_release(str);
+        jsstr_release(jsstr);
         return hres;
     }
 
@@ -478,15 +524,15 @@ static HRESULT String_indexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
     if(SUCCEEDED(hres)) {
         const WCHAR *ptr;
 
-        ptr = strstrW(str->str+pos, search_str->str);
+        ptr = strstrW(str+pos, search_str);
         if(ptr)
-            ret = ptr - str->str;
+            ret = ptr - str;
         else
             ret = -1;
     }
 
-    jsstr_release(search_str);
-    jsstr_release(str);
+    jsstr_release(search_jsstr);
+    jsstr_release(jsstr);
     if(FAILED(hres))
         return hres;
 
@@ -507,31 +553,32 @@ static HRESULT String_lastIndexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
         jsval_t *r)
 {
     unsigned pos = 0, search_len, length;
-    jsstr_t *search_str, *str;
+    jsstr_t *search_jsstr, *jsstr;
+    const WCHAR *search_str, *str;
     INT ret = -1;
     HRESULT hres;
 
     TRACE("\n");
 
-    hres = get_string_val(ctx, jsthis, &str);
+    hres = get_string_flat_val(ctx, jsthis, &jsstr, &str);
     if(FAILED(hres))
         return hres;
 
     if(!argc) {
         if(r)
             *r = jsval_number(-1);
-        jsstr_release(str);
+        jsstr_release(jsstr);
         return S_OK;
     }
 
-    hres = to_string(ctx, argv[0], &search_str);
+    hres = to_flat_string(ctx, argv[0], &search_jsstr, &search_str);
     if(FAILED(hres)) {
-        jsstr_release(str);
+        jsstr_release(jsstr);
         return hres;
     }
 
-    search_len = jsstr_length(search_str);
-    length = jsstr_length(str);
+    search_len = jsstr_length(search_jsstr);
+    length = jsstr_length(jsstr);
 
     if(argc >= 2) {
         double d;
@@ -546,16 +593,16 @@ static HRESULT String_lastIndexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
     if(SUCCEEDED(hres) && length >= search_len) {
         const WCHAR *ptr;
 
-        for(ptr = str->str+min(pos, length-search_len); ptr >= str->str; ptr--) {
-            if(!memcmp(ptr, search_str->str, search_len*sizeof(WCHAR))) {
-                ret = ptr-str->str;
+        for(ptr = str+min(pos, length-search_len); ptr >= str; ptr--) {
+            if(!memcmp(ptr, search_str, search_len*sizeof(WCHAR))) {
+                ret = ptr-str;
                 break;
             }
         }
     }
 
-    jsstr_release(search_str);
-    jsstr_release(str);
+    jsstr_release(search_jsstr);
+    jsstr_release(jsstr);
     if(FAILED(hres))
         return hres;
 
@@ -625,36 +672,54 @@ typedef struct {
     DWORD len;
 } strbuf_t;
 
+static BOOL strbuf_ensure_size(strbuf_t *buf, unsigned len)
+{
+    WCHAR *new_buf;
+    DWORD new_size;
+
+    if(len <= buf->size)
+        return TRUE;
+
+    new_size = buf->size ? buf->size<<1 : 16;
+    if(new_size < len)
+        new_size = len;
+    if(buf->buf)
+        new_buf = heap_realloc(buf->buf, new_size*sizeof(WCHAR));
+    else
+        new_buf = heap_alloc(new_size*sizeof(WCHAR));
+    if(!new_buf)
+        return FALSE;
+
+    buf->buf = new_buf;
+    buf->size = new_size;
+    return TRUE;
+}
+
 static HRESULT strbuf_append(strbuf_t *buf, const WCHAR *str, DWORD len)
 {
     if(!len)
         return S_OK;
 
-    if(len + buf->len > buf->size) {
-        WCHAR *new_buf;
-        DWORD new_size;
-
-        new_size = buf->size ? buf->size<<1 : 16;
-        if(new_size < buf->len+len)
-            new_size = buf->len+len;
-        if(buf->buf)
-            new_buf = heap_realloc(buf->buf, new_size*sizeof(WCHAR));
-        else
-            new_buf = heap_alloc(new_size*sizeof(WCHAR));
-        if(!new_buf)
-            return E_OUTOFMEMORY;
-
-        buf->buf = new_buf;
-        buf->size = new_size;
-    }
+    if(!strbuf_ensure_size(buf, buf->len+len))
+        return E_OUTOFMEMORY;
 
     memcpy(buf->buf+buf->len, str, len*sizeof(WCHAR));
     buf->len += len;
     return S_OK;
 }
 
+static HRESULT strbuf_append_jsstr(strbuf_t *buf, jsstr_t *str)
+{
+    if(!strbuf_ensure_size(buf, buf->len+jsstr_length(str)))
+        return E_OUTOFMEMORY;
+
+    jsstr_flush(str, buf->buf+buf->len);
+    buf->len += jsstr_length(str);
+    return S_OK;
+}
+
 static HRESULT rep_call(script_ctx_t *ctx, jsdisp_t *func,
-        jsstr_t *str, match_state_t *match, jsstr_t **ret)
+        jsstr_t *jsstr, const WCHAR *str, match_state_t *match, jsstr_t **ret)
 {
     jsval_t *argv;
     unsigned argc;
@@ -676,7 +741,7 @@ static HRESULT rep_call(script_ctx_t *ctx, jsdisp_t *func,
     if(SUCCEEDED(hres)) {
         for(i=0; i < match->paren_count; i++) {
             if(match->parens[i].index != -1)
-                tmp_str = jsstr_substr(str, match->parens[i].index, match->parens[i].length);
+                tmp_str = jsstr_substr(jsstr, match->parens[i].index, match->parens[i].length);
             else
                 tmp_str = jsstr_empty();
             if(!tmp_str) {
@@ -688,8 +753,8 @@ static HRESULT rep_call(script_ctx_t *ctx, jsdisp_t *func,
     }
 
     if(SUCCEEDED(hres)) {
-        argv[match->paren_count+1] = jsval_number(match->cp-str->str - match->match_len);
-        argv[match->paren_count+2] = jsval_string(str);
+        argv[match->paren_count+1] = jsval_number(match->cp-str - match->match_len);
+        argv[match->paren_count+2] = jsval_string(jsstr);
     }
 
     if(SUCCEEDED(hres))
@@ -711,25 +776,26 @@ static HRESULT rep_call(script_ctx_t *ctx, jsdisp_t *func,
 static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
         jsval_t *r)
 {
-    DWORD rep_len=0;
-    jsstr_t *rep_str = NULL, *match_str = NULL, *str;
+    const WCHAR *str, *match_str = NULL, *rep_str = NULL;
+    jsstr_t *rep_jsstr, *match_jsstr, *jsstr;
     jsdisp_t *rep_func = NULL, *regexp = NULL;
     match_state_t *match = NULL, last_match = {0};
     strbuf_t ret = {NULL,0,0};
     DWORD re_flags = REM_NO_CTX_UPDATE|REM_ALLOC_RESULT;
+    DWORD rep_len=0;
     HRESULT hres = S_OK;
 
     TRACE("\n");
 
-    hres = get_string_val(ctx, jsthis, &str);
+    hres = get_string_flat_val(ctx, jsthis, &jsstr, &str);
     if(FAILED(hres))
         return hres;
 
     if(!argc) {
         if(r)
-            *r = jsval_string(str);
+            *r = jsval_string(jsstr);
         else
-            jsstr_release(str);
+            jsstr_release(jsstr);
         return S_OK;
     }
 
@@ -742,9 +808,9 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
     }
 
     if(!regexp) {
-        hres = to_string(ctx, argv[0], &match_str);
+        hres = to_flat_string(ctx, argv[0], &match_jsstr, &match_str);
         if(FAILED(hres)) {
-            jsstr_release(str);
+            jsstr_release(jsstr);
             return hres;
         }
     }
@@ -759,18 +825,18 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
         }
 
         if(!rep_func) {
-            hres = to_string(ctx, argv[1], &rep_str);
+            hres = to_flat_string(ctx, argv[1], &rep_jsstr, &rep_str);
             if(SUCCEEDED(hres))
-                rep_len = jsstr_length(rep_str);
+                rep_len = jsstr_length(rep_jsstr);
         }
     }
 
     if(SUCCEEDED(hres)) {
-        const WCHAR *ecp = str->str;
+        const WCHAR *ecp = str;
 
         while(1) {
             if(regexp) {
-                hres = regexp_match_next(ctx, regexp, re_flags, str, &match);
+                hres = regexp_match_next(ctx, regexp, re_flags, jsstr, &match);
                 re_flags = (re_flags | REM_CHECK_GLOBAL) & (~REM_ALLOC_RESULT);
 
                 if(hres == S_FALSE) {
@@ -786,13 +852,13 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
                 if(re_flags & REM_ALLOC_RESULT) {
                     re_flags &= ~REM_ALLOC_RESULT;
                     match = &last_match;
-                    match->cp = str->str;
+                    match->cp = str;
                 }
 
-                match->cp = strstrW(match->cp, match_str->str);
+                match->cp = strstrW(match->cp, match_str);
                 if(!match->cp)
                     break;
-                match->match_len = jsstr_length(match_str);
+                match->match_len = jsstr_length(match_jsstr);
                 match->cp += match->match_len;
             }
 
@@ -804,16 +870,16 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
             if(rep_func) {
                 jsstr_t *cstr;
 
-                hres = rep_call(ctx, rep_func, str, match, &cstr);
+                hres = rep_call(ctx, rep_func, jsstr, str, match, &cstr);
                 if(FAILED(hres))
                     break;
 
-                hres = strbuf_append(&ret, cstr->str, jsstr_length(cstr));
+                hres = strbuf_append_jsstr(&ret, cstr);
                 jsstr_release(cstr);
                 if(FAILED(hres))
                     break;
             }else if(rep_str && regexp) {
-                const WCHAR *ptr = rep_str->str, *ptr2;
+                const WCHAR *ptr = rep_str, *ptr2;
 
                 while((ptr2 = strchrW(ptr, '$'))) {
                     hres = strbuf_append(&ret, ptr, ptr2-ptr);
@@ -830,11 +896,11 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
                         ptr = ptr2+2;
                         break;
                     case '`':
-                        hres = strbuf_append(&ret, str->str, match->cp-str->str-match->match_len);
+                        hres = strbuf_append(&ret, str, match->cp-str-match->match_len);
                         ptr = ptr2+2;
                         break;
                     case '\'':
-                        hres = strbuf_append(&ret, ecp, (str->str+jsstr_length(str))-ecp);
+                        hres = strbuf_append(&ret, ecp, (str+jsstr_length(jsstr))-ecp);
                         ptr = ptr2+2;
                         break;
                     default: {
@@ -859,7 +925,7 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
                         }
 
                         if(match->parens[idx-1].index != -1)
-                            hres = strbuf_append(&ret, str->str+match->parens[idx-1].index,
+                            hres = strbuf_append(&ret, str+match->parens[idx-1].index,
                                     match->parens[idx-1].length);
                     }
                     }
@@ -869,11 +935,11 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
                 }
 
                 if(SUCCEEDED(hres))
-                    hres = strbuf_append(&ret, ptr, (rep_str->str+rep_len)-ptr);
+                    hres = strbuf_append(&ret, ptr, (rep_str+rep_len)-ptr);
                 if(FAILED(hres))
                     break;
             }else if(rep_str) {
-                hres = strbuf_append(&ret, rep_str->str, rep_len);
+                hres = strbuf_append(&ret, rep_str, rep_len);
                 if(FAILED(hres))
                     break;
             }else {
@@ -891,28 +957,28 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
         }
 
         if(SUCCEEDED(hres))
-            hres = strbuf_append(&ret, ecp, str->str+jsstr_length(str)-ecp);
+            hres = strbuf_append(&ret, ecp, str+jsstr_length(jsstr)-ecp);
     }
 
     if(rep_func)
         jsdisp_release(rep_func);
     if(rep_str)
-        jsstr_release(rep_str);
+        jsstr_release(rep_jsstr);
     if(match_str)
-        jsstr_release(match_str);
+        jsstr_release(match_jsstr);
     if(regexp)
         heap_free(match);
 
     if(SUCCEEDED(hres) && last_match.cp && regexp) {
         jsstr_release(ctx->last_match);
-        ctx->last_match = jsstr_addref(str);
-        ctx->last_match_index = last_match.cp-str->str-last_match.match_len;
+        ctx->last_match = jsstr_addref(jsstr);
+        ctx->last_match_index = last_match.cp-str-last_match.match_len;
         ctx->last_match_length = last_match.match_len;
     }
 
     if(regexp)
         jsdisp_release(regexp);
-    jsstr_release(str);
+    jsstr_release(jsstr);
 
     if(SUCCEEDED(hres) && r) {
         jsstr_t *ret_str;
@@ -933,20 +999,21 @@ static HRESULT String_search(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns
         jsval_t *r)
 {
     jsdisp_t *regexp = NULL;
-    jsstr_t *str;
+    const WCHAR *str;
+    jsstr_t *jsstr;
     match_state_t match, *match_ptr = &match;
     HRESULT hres;
 
     TRACE("\n");
 
-    hres = get_string_val(ctx, jsthis, &str);
+    hres = get_string_flat_val(ctx, jsthis, &jsstr, &str);
     if(FAILED(hres))
         return hres;
 
     if(!argc) {
         if(r)
             *r = jsval_null();
-        jsstr_release(str);
+        jsstr_release(jsstr);
         return S_OK;
     }
 
@@ -961,20 +1028,20 @@ static HRESULT String_search(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns
     if(!regexp) {
         hres = create_regexp_var(ctx, argv[0], NULL, &regexp);
         if(FAILED(hres)) {
-            jsstr_release(str);
+            jsstr_release(jsstr);
             return hres;
         }
     }
 
-    match.cp = str->str;
-    hres = regexp_match_next(ctx, regexp, REM_RESET_INDEX|REM_NO_PARENS, str, &match_ptr);
-    jsstr_release(str);
+    match.cp = str;
+    hres = regexp_match_next(ctx, regexp, REM_RESET_INDEX|REM_NO_PARENS, jsstr, &match_ptr);
+    jsstr_release(jsstr);
     jsdisp_release(regexp);
     if(FAILED(hres))
         return hres;
 
     if(r)
-        *r = jsval_number(hres == S_OK ? match.cp-match.match_len-str->str : -1);
+        *r = jsval_number(hres == S_OK ? match.cp-match.match_len-str : -1);
     return S_OK;
 }
 
@@ -1067,10 +1134,10 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
 {
     match_state_t match_result, *match_ptr = &match_result;
     DWORD length, i, match_len = 0;
-    const WCHAR *ptr, *ptr2;
+    const WCHAR *ptr, *ptr2, *str, *match_str = NULL;
     unsigned limit = UINT32_MAX;
     jsdisp_t *array, *regexp = NULL;
-    jsstr_t *str, *match_str = NULL, *tmp_str;
+    jsstr_t *jsstr, *match_jsstr, *tmp_str;
     HRESULT hres;
 
     TRACE("\n");
@@ -1080,16 +1147,16 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
         return E_NOTIMPL;
     }
 
-    hres = get_string_val(ctx, jsthis, &str);
+    hres = get_string_flat_val(ctx, jsthis, &jsstr, &str);
     if(FAILED(hres))
         return hres;
 
-    length = jsstr_length(str);
+    length = jsstr_length(jsstr);
 
     if(argc > 1 && !is_undefined(argv[1])) {
         hres = to_uint32(ctx, argv[1], &limit);
         if(FAILED(hres)) {
-            jsstr_release(str);
+            jsstr_release(jsstr);
             return hres;
         }
     }
@@ -1105,15 +1172,15 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
     }
 
     if(!regexp) {
-        hres = to_string(ctx, argv[0], &match_str);
+        hres = to_flat_string(ctx, argv[0], &match_jsstr, &match_str);
         if(FAILED(hres)) {
-            jsstr_release(str);
+            jsstr_release(jsstr);
             return hres;
         }
 
-        match_len = jsstr_length(match_str);
+        match_len = jsstr_length(match_jsstr);
         if(!match_len) {
-            jsstr_release(match_str);
+            jsstr_release(match_jsstr);
             match_str = NULL;
         }
     }
@@ -1121,16 +1188,16 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
     hres = create_array(ctx, 0, &array);
 
     if(SUCCEEDED(hres)) {
-        ptr = str->str;
-        match_result.cp = str->str;
+        ptr = str;
+        match_result.cp = str;
         for(i=0; i<limit; i++) {
             if(regexp) {
-                hres = regexp_match_next(ctx, regexp, REM_NO_PARENS, str, &match_ptr);
+                hres = regexp_match_next(ctx, regexp, REM_NO_PARENS, jsstr, &match_ptr);
                 if(hres != S_OK)
                     break;
                 ptr2 = match_result.cp - match_result.match_len;
             }else if(match_str) {
-                ptr2 = strstrW(ptr, match_str->str);
+                ptr2 = strstrW(ptr, match_str);
                 if(!ptr2)
                     break;
             }else {
@@ -1160,7 +1227,7 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
     }
 
     if(SUCCEEDED(hres) && (match_str || regexp) && i<limit) {
-        DWORD len = (str->str+length) - ptr;
+        DWORD len = (str+length) - ptr;
 
         if(len || match_str) {
             tmp_str = jsstr_alloc_len(ptr, len);
@@ -1177,8 +1244,8 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
     if(regexp)
         jsdisp_release(regexp);
     if(match_str)
-        jsstr_release(match_str);
-    jsstr_release(str);
+        jsstr_release(match_jsstr);
+    jsstr_release(jsstr);
 
     if(SUCCEEDED(hres) && r)
         *r = jsval_obj(array);
@@ -1337,15 +1404,16 @@ static HRESULT String_toLowerCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
 
     if(r) {
         jsstr_t *ret;
+        WCHAR *buf;
 
-        ret = jsstr_alloc_buf(jsstr_length(str));
-        if(!ret) {
+        buf = jsstr_alloc_buf(jsstr_length(str), &ret);
+        if(!buf) {
             jsstr_release(str);
             return E_OUTOFMEMORY;
         }
 
-        jsstr_flush(str, ret->str);
-        strlwrW(ret->str);
+        jsstr_flush(str, buf);
+        strlwrW(buf);
         *r = jsval_string(ret);
     }
     jsstr_release(str);
@@ -1366,15 +1434,16 @@ static HRESULT String_toUpperCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
 
     if(r) {
         jsstr_t *ret;
+        WCHAR *buf;
 
-        ret = jsstr_alloc_buf(jsstr_length(str));
-        if(!ret) {
+        buf = jsstr_alloc_buf(jsstr_length(str), &ret);
+        if(!buf) {
             jsstr_release(str);
             return E_OUTOFMEMORY;
         }
 
-        jsstr_flush(str, ret->str);
-        struprW(ret->str);
+        jsstr_flush(str, buf);
+        struprW(buf);
         *r = jsval_string(ret);
     }
     jsstr_release(str);
@@ -1525,14 +1594,15 @@ static const builtin_info_t StringInst_info = {
 static HRESULT StringConstr_fromCharCode(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
         unsigned argc, jsval_t *argv, jsval_t *r)
 {
+    WCHAR *ret_str;
     DWORD i, code;
     jsstr_t *ret;
     HRESULT hres;
 
     TRACE("\n");
 
-    ret = jsstr_alloc_buf(argc);
-    if(!ret)
+    ret_str = jsstr_alloc_buf(argc, &ret);
+    if(!ret_str)
         return E_OUTOFMEMORY;
 
     for(i=0; i<argc; i++) {
@@ -1542,7 +1612,7 @@ static HRESULT StringConstr_fromCharCode(script_ctx_t *ctx, vdisp_t *jsthis, WOR
             return hres;
         }
 
-        ret->str[i] = code;
+        ret_str[i] = code;
     }
 
     if(r)
index 985c1b7..3f0c181 100644 (file)
@@ -91,7 +91,7 @@ reactos/dll/win32/inseng          # Synced to Wine-1.7.1
 reactos/dll/win32/iphlpapi        # Out of sync
 reactos/dll/win32/itircl          # Synced to Wine-1.7.1
 reactos/dll/win32/itss            # Synced to Wine-1.7.1
-reactos/dll/win32/jscript         # Synced to Wine-1.5.26
+reactos/dll/win32/jscript         # Synced to Wine-1.7.1
 reactos/dll/win32/loadperf        # Synced to Wine-1.5.19
 reactos/dll/win32/localspl        # Synced to Wine-1.5.26
 reactos/dll/win32/localui         # Synced to Wine-1.5.19