RPA Toolkit
RJS prop access changes...
[rpatk.git] / rjs / rjs.c
1 /*
2  *  Regular Pattern Analyzer (RPA)
3  *  Copyright (c) 2009-2010 Martin Stoilov
4  *
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  *  Martin Stoilov <martin@rpasearch.com>
19  */
20
21 #include <stdarg.h>
22 #include "rlib/rmem.h"
23 #include "rlib/rmap.h"
24 #include "rjs/rjs.h"
25 #include "rvm/rvmcodegen.h"
26 #include "rvmoperator.h"
27 #include "rvmoperatorbin.h"
28 #include "rvmoperatorcast.h"
29 #include "rvmoperatornot.h"
30 #include "rvmoperatorlogicnot.h"
31
32
33 static void rjs_engine_initgp(rjs_engine_t *jse);
34 static void rjs_engine_print(rvmcpu_t *cpu, rvm_asmins_t *ins);
35 static void rjs_engine_dbgprint(rvmcpu_t *cpu, rvm_asmins_t *ins);
36 static void rjs_engine_object(rvmcpu_t *cpu, rvm_asmins_t *ins);
37 static void rjs_string_ltrim(rvmcpu_t *cpu, rvm_asmins_t *ins);
38 static void rjs_string_length(rvmcpu_t *cpu, rvm_asmins_t *ins);
39
40 static rvm_switable_t rjsswitable[] = {
41                 {"print", rjs_engine_print},
42                 {"dbgprint", rjs_engine_dbgprint},
43                 {"Object", rjs_engine_object},
44                 {"Array", rjs_engine_object},
45                 {"string.ltrim", rjs_string_ltrim},
46                 {"string.length", rjs_string_length},
47                 {NULL, NULL},
48 };
49
50
51 static void rjs_op_cast(rvmcpu_t *cpu, rvm_asmins_t *ins)
52 {
53         rvmreg_type_t type = (rvmreg_type_t)RVM_CPUREG_GETU(cpu, ins->op3);
54         rvmreg_t tmp;
55
56         RVM_REG_CLEAR(&tmp);
57         RVM_REG_SETTYPE(&tmp, type);
58         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, RVM_CPUREG_PTR(cpu, ins->op1), RVM_CPUREG_PTR(cpu, ins->op2), &tmp);
59 }
60
61
62 static void rjs_op_eadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
63 {
64         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
65         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
66
67         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_ADD, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
68 }
69
70
71 static void rjs_op_esub(rvmcpu_t *cpu, rvm_asmins_t *ins)
72 {
73         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
74         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
75
76         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_SUB, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
77 }
78
79
80 static void rjs_op_eneg(rvmcpu_t *cpu, rvm_asmins_t *ins)
81 {
82         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
83         rvmreg_t zero;
84
85         rvm_reg_setunsigned(&zero, 0);
86         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_SUB, cpu, RVM_CPUREG_PTR(cpu, ins->op1), &zero, arg2);
87 }
88
89
90
91 static void rjs_op_emul(rvmcpu_t *cpu, rvm_asmins_t *ins)
92 {
93         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
94         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
95
96         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_MUL, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
97 }
98
99
100 static void rjs_op_ediv(rvmcpu_t *cpu, rvm_asmins_t *ins)
101 {
102         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
103         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
104
105         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_DIV, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
106 }
107
108
109 static void rjs_op_emod(rvmcpu_t *cpu, rvm_asmins_t *ins)
110 {
111         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
112         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
113
114         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_MOD, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
115 }
116
117
118 static void rjs_op_elsl(rvmcpu_t *cpu, rvm_asmins_t *ins)
119 {
120         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
121         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
122
123         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_LSL, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
124 }
125
126
127 static void rjs_op_elsr(rvmcpu_t *cpu, rvm_asmins_t *ins)
128 {
129         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
130         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
131
132         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_LSR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
133 }
134
135
136 static void rjs_op_elsru(rvmcpu_t *cpu, rvm_asmins_t *ins)
137 {
138         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
139         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
140
141         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_LSRU, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
142 }
143
144
145 static void rjs_op_eand(rvmcpu_t *cpu, rvm_asmins_t *ins)
146 {
147         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
148         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
149
150         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_AND, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
151 }
152
153
154 static void rjs_op_eorr(rvmcpu_t *cpu, rvm_asmins_t *ins)
155 {
156         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
157         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
158
159         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_OR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
160 }
161
162
163 static void rjs_op_exor(rvmcpu_t *cpu, rvm_asmins_t *ins)
164 {
165         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
166         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
167
168         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_XOR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
169 }
170
171
172 static void rjs_op_enot(rvmcpu_t *cpu, rvm_asmins_t *ins)
173 {
174         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
175
176         rjs_opmap_invoke_unary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_NOT, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2);
177 }
178
179
180 static void rjs_op_eland(rvmcpu_t *cpu, rvm_asmins_t *ins)
181 {
182         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
183         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
184
185         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_LOGICAND, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
186 }
187
188
189 static void rjs_op_elor(rvmcpu_t *cpu, rvm_asmins_t *ins)
190 {
191         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
192         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
193
194         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_LOGICOR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
195 }
196
197
198 static void rjs_op_elnot(rvmcpu_t *cpu, rvm_asmins_t *ins)
199 {
200         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
201
202         rjs_opmap_invoke_unary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_LOGICNOT, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2);
203 }
204
205
206 static void rjs_op_eeq(rvmcpu_t *cpu, rvm_asmins_t *ins)
207 {
208         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
209         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
210
211         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_EQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
212 }
213
214
215 static void rjs_op_enoteq(rvmcpu_t *cpu, rvm_asmins_t *ins)
216 {
217         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
218         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
219
220         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_NOTEQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
221 }
222
223
224 static void rjs_op_egreat(rvmcpu_t *cpu, rvm_asmins_t *ins)
225 {
226         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
227         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
228
229         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_GREATER, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
230 }
231
232
233 static void rjs_op_egreateq(rvmcpu_t *cpu, rvm_asmins_t *ins)
234 {
235         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
236         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
237
238         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_GREATEREQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
239 }
240
241
242 static void rjs_op_elesseq(rvmcpu_t *cpu, rvm_asmins_t *ins)
243 {
244         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
245         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
246
247         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_LESSEQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
248 }
249
250
251 static void rjs_op_eless(rvmcpu_t *cpu, rvm_asmins_t *ins)
252 {
253         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
254         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
255
256         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_LESS, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
257 }
258
259
260 static void rjs_op_ecmp(rvmcpu_t *cpu, rvm_asmins_t *ins)
261 {
262         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
263         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
264
265         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CMP, cpu, NULL, arg1, arg2);
266 }
267
268
269 static void rjs_op_ecmn(rvmcpu_t *cpu, rvm_asmins_t *ins)
270 {
271         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
272         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
273
274         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CMN, cpu, NULL, arg1, arg2);
275 }
276
277
278 static void rjs_op_stralloc(rvmcpu_t *cpu, rvm_asmins_t *ins)
279 {
280         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
281         rstring_t *s = r_string_create_strsize((const char*)RVM_CPUREG_GETP(cpu, ins->op2), (unsigned long)RVM_CPUREG_GETU(cpu, ins->op3));
282         if (!s) {
283                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
284         }
285         r_gc_add(cpu->gc, (robject_t*)s);
286         rvm_reg_setstring(arg1, s);
287 }
288
289
290 static void rjs_op_mapalloc(rvmcpu_t *cpu, rvm_asmins_t *ins)
291 {
292         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
293         rmap_t *a = r_map_create(sizeof(rvmreg_t), 7);
294         if (!a) {
295                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
296         }
297         r_gc_add(cpu->gc, (robject_t*)a);
298         rvm_reg_setjsobject(arg1, (robject_t*)a);
299 }
300
301
302 static long rjs_op_mapproplookupadd(rmap_t *map, rvmcpu_t *cpu, rvm_asmins_t *ins)
303 {
304         long index;
305         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
306
307         if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_SIGNED || RVM_REG_GETTYPE(arg3) == RVM_DTYPE_UNSIGNED) {
308                 index = r_map_lookup_l(map, -1, (long)RVM_REG_GETL(arg3));
309                 if (index < 0)
310                         index = r_map_gckey_add_l(map, cpu->gc, (long)RVM_REG_GETL(arg3), NULL);
311         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_DOUBLE) {
312                 index = r_map_lookup_d(map, -1, RVM_REG_GETD(arg3));
313                 if (index < 0)
314                         index = r_map_gckey_add_d(map, cpu->gc, RVM_REG_GETD(arg3), NULL);
315         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_STRING) {
316                 index = r_map_lookup(map, -1, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.str, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.size);
317                 if (index < 0)
318                         index = r_map_gckey_add(map, cpu->gc, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.str, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.size, NULL);
319         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_POINTER) {
320                 index = r_map_lookup(map, -1, (char*)RVM_CPUREG_GETP(cpu, ins->op3), (unsigned int)RVM_CPUREG_GETL(cpu, ins->op1));
321                 if (index < 0)
322                         index = r_map_gckey_add(map, cpu->gc, (char*)RVM_CPUREG_GETP(cpu, ins->op3), (unsigned int)RVM_CPUREG_GETL(cpu, ins->op1), NULL);
323         } else {
324                 index = -1;
325         }
326
327         return index;
328 }
329
330
331 static void rjs_op_proplookupadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
332 {
333         long index = -1;
334         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
335         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
336         rmap_t *map = (rmap_t*)RVM_REG_GETP(arg2);
337
338         if (rvm_reg_gettype(arg2) == RVM_DTYPE_MAP) {
339                 index = rjs_op_mapproplookupadd(map, cpu, ins);
340         } else {
341
342         }
343         RVM_REG_CLEAR(arg1);
344         RVM_REG_SETTYPE(arg1, RVM_DTYPE_SIGNED);
345         RVM_REG_SETL(arg1, index);
346 }
347
348
349 static long rjs_op_mapproplookup(rmap_t *map, rvmcpu_t *cpu, rvm_asmins_t *ins)
350 {
351         long index = -1;
352         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
353
354         if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_SIGNED || RVM_REG_GETTYPE(arg3) == RVM_DTYPE_UNSIGNED) {
355                 index = r_map_lookup_l(map, -1, (long)RVM_REG_GETL(arg3));
356         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_DOUBLE) {
357                 index = r_map_lookup_d(map, -1, RVM_REG_GETD(arg3));
358         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_STRING) {
359                 index = r_map_lookup(map, -1, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.str, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.size);
360         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_POINTER) {
361                 index = r_map_lookup(map, -1, (char*)RVM_CPUREG_GETP(cpu, ins->op3), (unsigned int)RVM_CPUREG_GETL(cpu, ins->op1));
362         }
363         return index;
364 }
365
366
367 static long rjs_op_stringproplookup(rstring_t *str, rvmcpu_t *cpu, rvm_asmins_t *ins)
368 {
369         long index = -1;
370         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
371
372         if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_SIGNED || RVM_REG_GETTYPE(arg3) == RVM_DTYPE_UNSIGNED) {
373                 index = RVM_REG_GETL(arg3);
374         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_DOUBLE) {
375                 index = (long)RVM_REG_GETD(arg3);
376         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_STRING) {
377                 index = r_strtol(((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.str, NULL, 10);
378         }
379         return index;
380 }
381
382
383 static void rjs_op_proplookup(rvmcpu_t *cpu, rvm_asmins_t *ins)
384 {
385         long index = -1;
386         rboolean globalprop = 0;
387         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
388         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
389
390         if (rvm_reg_gettype(arg2) == RVM_DTYPE_MAP) {
391                 rmap_t *map = (rmap_t*)RVM_REG_GETP(arg2);
392                 index = rjs_op_mapproplookup(map, cpu, ins);
393                 rvm_reg_setsigned(arg1, index);
394         } else if (rvm_reg_gettype(arg2) == RVM_DTYPE_STRING) {
395                 rstring_t *str = (rstring_t*)RVM_REG_GETP(arg2);
396                 index = rjs_op_stringproplookup(str, cpu, ins);
397                 if (index < 0) {
398                         index = rjs_op_mapproplookup(RJS_CPU2JSE(cpu)->props[RVM_DTYPE_STRING], cpu, ins);
399                         if (index >= 0)
400                                 globalprop = TRUE;
401                 }
402                 rvm_reg_setsigned(arg1, index);
403                 if (globalprop)
404                         RVM_REG_SETFLAG(arg1, RVM_INFOBIT_GLOBAL);
405         }
406 }
407
408
409 static void rjs_op_propstr(rvmcpu_t *cpu, rvm_asmins_t *ins)
410 {
411         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
412         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
413         rvmreg_t tmp = rvm_reg_create_signed(0);
414         rmap_t *a = NULL;
415         rpointer value;
416         long index;
417
418         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
419         index = (long)RVM_REG_GETL(&tmp);
420         if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP) {
421
422                 return;
423         }
424         a = (rmap_t*)RVM_REG_GETP(arg2);
425         value = r_map_value(a, index);
426         if (!value)
427                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
428         r_map_setvalue(a, index, arg1);
429 }
430
431
432 static void rjs_op_propldr(rvmcpu_t *cpu, rvm_asmins_t *ins)
433 {
434         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
435         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
436         rvmreg_t tmp = rvm_reg_create_signed(0);
437         rpointer value;
438         long index;
439
440         index = (long)RVM_REG_GETL(arg1);
441         if (rvm_reg_gettype(arg2) == RVM_DTYPE_MAP) {
442                 rmap_t *a = (rmap_t*)RVM_REG_GETP(arg2);
443                 value = r_map_value(a, index);
444                 if (value) {
445                         *arg1 = *((rvmreg_t*)value);
446                 }
447         } else if (rvm_reg_gettype(arg2) == RVM_DTYPE_STRING) {
448                 rstring_t *s = (rstring_t*)RVM_REG_GETP(arg2);
449                 if (RVM_REG_TSTFLAG(arg1, RVM_INFOBIT_GLOBAL)) {
450                         rmap_t *a = RJS_CPU2JSE(cpu)->props[RVM_DTYPE_STRING];
451                         value = r_map_value(a, index);
452                         if (value) {
453                                 *arg1 = *((rvmreg_t*)value);
454                         }
455                 } else {
456                         rstring_t *allocstr;
457                         if (index >= s->s.size) {
458                                 rvm_reg_setundef(arg1);
459                                 return;
460                         }
461                         allocstr = r_string_create_strsize(&s->s.str[index], 1);
462                         r_gc_add(cpu->gc, (robject_t*)allocstr);
463                         rvm_reg_setstring(arg1, allocstr);
464                 }
465         } else {
466                 rvm_reg_setundef(arg1);
467         }
468 }
469
470
471 static void rjs_op_propkeyldr(rvmcpu_t *cpu, rvm_asmins_t *ins)
472 {
473         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
474         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
475         rvmreg_t tmp = rvm_reg_create_signed(0);
476         rmap_t *map = NULL;
477         rstring_t *key;
478         long index;
479
480         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
481         index = (long)RVM_REG_GETL(&tmp);
482         RVM_REG_CLEAR(arg1);
483         RVM_REG_SETTYPE(arg1, RVM_DTYPE_UNDEF);
484         if (rvm_reg_gettype(arg2) == RVM_DTYPE_MAP) {
485                 map = (rmap_t*)RVM_REG_GETP(arg2);
486                 key = r_map_key(map, index);
487                 if (key) {
488                         rvm_reg_setstring(arg1, key);
489                 }
490         } else if (rvm_reg_gettype(arg2) == RVM_DTYPE_STRING) {
491
492         }
493 }
494
495
496 static void rjs_op_propdel(rvmcpu_t *cpu, rvm_asmins_t *ins)
497 {
498         int ret;
499         long index;
500         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
501         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
502         rvmreg_t tmp = rvm_reg_create_signed(0);
503         rmap_t *a = NULL;
504
505         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
506         index = (long)RVM_REG_GETL(&tmp);
507         rvm_reg_setboolean(arg1, 0);
508         if (rvm_reg_gettype(arg2) == RVM_DTYPE_MAP) {
509                 a = (rmap_t*)RVM_REG_GETP(arg2);
510                 ret = r_map_delete(a, index);
511                 rvm_reg_setboolean(arg1, ret == 0 ? 1 : 0);
512         }
513 }
514
515
516 static void rjs_op_propaddr(rvmcpu_t *cpu, rvm_asmins_t *ins)
517 {
518         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
519         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
520         rvmreg_t tmp = rvm_reg_create_signed(0);
521         rmap_t *a;
522         rpointer value;
523         long index;
524
525         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
526         index = (long)RVM_REG_GETL(&tmp);
527         if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP)
528                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
529         a = (rmap_t*)RVM_REG_GETP(arg2);
530         value = r_map_value(a, index);
531         if (!value)
532                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
533         RVM_REG_CLEAR(arg1);
534         RVM_REG_SETTYPE(arg1, RVM_DTYPE_POINTER);
535         RVM_REG_SETP(arg1, value);
536 }
537
538
539 static void rjs_op_propnext(rvmcpu_t *cpu, rvm_asmins_t *ins)
540 {
541         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
542         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
543         rvmreg_t tmp = rvm_reg_create_signed(0);
544         rmap_t *map = NULL;
545         long index = -1;
546
547         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
548         index = (long)RVM_REG_GETL(&tmp);
549         if (rvm_reg_gettype(arg2) == RVM_DTYPE_MAP) {
550                 map = (rmap_t*)RVM_REG_GETP(arg2);
551                 if (index < 0)
552                         index = r_map_first(map);
553                 else
554                         index = r_map_next(map, index);
555         }
556         RVM_REG_CLEAR(arg1);
557         RVM_REG_SETTYPE(arg1, RVM_DTYPE_SIGNED);
558         RVM_REG_SETL(arg1, index);
559 }
560
561
562 static void rjs_op_propprev(rvmcpu_t *cpu, rvm_asmins_t *ins)
563 {
564         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
565         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
566         rvmreg_t tmp = rvm_reg_create_signed(0);
567         rmap_t *map = NULL;
568         long index = -1;
569
570         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
571         index = (long)RVM_REG_GETL(&tmp);
572         if (rvm_reg_gettype(arg2) == RVM_DTYPE_MAP) {
573                 map = (rmap_t*)RVM_REG_GETP(arg2);
574                 if (index < 0)
575                         index = r_map_last(map);
576                 else
577                         index = r_map_prev(map, index);
578         }
579         RVM_REG_CLEAR(arg1);
580         RVM_REG_SETTYPE(arg1, RVM_DTYPE_SIGNED);
581         RVM_REG_SETL(arg1, index);
582 }
583
584
585 static void rjs_op_mapdel(rvmcpu_t *cpu, rvm_asmins_t *ins)
586 {
587         int ret;
588         long index;
589         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
590         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
591         rvmreg_t tmp = rvm_reg_create_signed(0);
592         rmap_t *a = NULL;
593
594         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
595         index = (long)RVM_REG_GETL(&tmp);
596         if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP)
597                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
598         a = (rmap_t*)RVM_REG_GETP(arg2);
599         ret = r_map_delete(a, index);
600         rvm_reg_setboolean(arg1, ret == 0 ? 1 : 0);
601 }
602
603
604 static void rjs_op_maplookup(rvmcpu_t *cpu, rvm_asmins_t *ins)
605 {
606         long index;
607         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
608         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
609         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
610         rmap_t *a = (rmap_t*)RVM_REG_GETP(arg2);
611
612         if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP) {
613                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
614         }
615         if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_SIGNED || RVM_REG_GETTYPE(arg3) == RVM_DTYPE_UNSIGNED) {
616                 index = r_map_lookup_l(a, -1, (long)RVM_REG_GETL(arg3));
617         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_DOUBLE) {
618                 index = r_map_lookup_d(a, -1, RVM_REG_GETD(arg3));
619         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_STRING) {
620                 index = r_map_lookup(a, -1, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.str, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.size);
621         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_POINTER) {
622                 index = r_map_lookup(a, -1, (char*)RVM_CPUREG_GETP(cpu, ins->op3), (unsigned int)RVM_CPUREG_GETL(cpu, ins->op1));
623         } else {
624                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
625         }
626
627         RVM_REG_CLEAR(arg1);
628         RVM_REG_SETTYPE(arg1, RVM_DTYPE_SIGNED);
629         RVM_REG_SETL(arg1, index);
630 }
631
632
633 static void rjs_op_mapadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
634 {
635         long index;
636         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
637         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
638         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
639         rmap_t *a = (rmap_t*)RVM_REG_GETP(arg2);
640
641         if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP) {
642                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
643         }
644         if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_SIGNED || RVM_REG_GETTYPE(arg3) == RVM_DTYPE_UNSIGNED) {
645                 index = r_map_gckey_add_l(a, cpu->gc, (long)RVM_REG_GETL(arg3), NULL);
646         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_DOUBLE) {
647                 index = r_map_gckey_add_d(a, cpu->gc, RVM_REG_GETD(arg3), NULL);
648         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_STRING) {
649                 index = r_map_gckey_add(a, cpu->gc, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.str, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.size, NULL);
650         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_POINTER) {
651                 index = r_map_gckey_add(a, cpu->gc, (char*)RVM_CPUREG_GETP(cpu, ins->op3), (unsigned int)RVM_CPUREG_GETL(cpu, ins->op1), NULL);
652         } else {
653                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
654         }
655
656         RVM_REG_CLEAR(arg1);
657         RVM_REG_SETTYPE(arg1, RVM_DTYPE_SIGNED);
658         RVM_REG_SETL(arg1, index);
659 }
660
661
662 static void rjs_op_maplookupadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
663 {
664         long index;
665         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
666         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
667         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
668         rmap_t *a = (rmap_t*)RVM_REG_GETP(arg2);
669
670         if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP) {
671                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
672         }
673         if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_SIGNED || RVM_REG_GETTYPE(arg3) == RVM_DTYPE_UNSIGNED) {
674                 index = r_map_lookup_l(a, -1, (long)RVM_REG_GETL(arg3));
675                 if (index < 0)
676                         index = r_map_gckey_add_l(a, cpu->gc, (long)RVM_REG_GETL(arg3), NULL);
677         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_DOUBLE) {
678                 index = r_map_lookup_d(a, -1, RVM_REG_GETD(arg3));
679                 if (index < 0)
680                         index = r_map_gckey_add_d(a, cpu->gc, RVM_REG_GETD(arg3), NULL);
681         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_STRING) {
682                 index = r_map_lookup(a, -1, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.str, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.size);
683                 if (index < 0)
684                         index = r_map_gckey_add(a, cpu->gc, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.str, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.size, NULL);
685         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_POINTER) {
686                 index = r_map_lookup(a, -1, (char*)RVM_CPUREG_GETP(cpu, ins->op3), (unsigned int)RVM_CPUREG_GETL(cpu, ins->op1));
687                 if (index < 0)
688                         index = r_map_gckey_add(a, cpu->gc, (char*)RVM_CPUREG_GETP(cpu, ins->op3), (unsigned int)RVM_CPUREG_GETL(cpu, ins->op1), NULL);
689         } else {
690                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
691         }
692         RVM_REG_CLEAR(arg1);
693         RVM_REG_SETTYPE(arg1, RVM_DTYPE_SIGNED);
694         RVM_REG_SETL(arg1, index);
695 }
696
697
698 static void rjs_op_mapaddr(rvmcpu_t *cpu, rvm_asmins_t *ins)
699 {
700         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
701         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
702         rvmreg_t tmp = rvm_reg_create_signed(0);
703         rmap_t *a;
704         rpointer value;
705         long index;
706
707         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
708         index = (long)RVM_REG_GETL(&tmp);
709         if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP)
710                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
711         a = (rmap_t*)RVM_REG_GETP(arg2);
712         value = r_map_value(a, index);
713         if (!value)
714                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
715         RVM_REG_CLEAR(arg1);
716         RVM_REG_SETTYPE(arg1, RVM_DTYPE_POINTER);
717         RVM_REG_SETP(arg1, value);
718 }
719
720
721 static void rjs_op_mapldr(rvmcpu_t *cpu, rvm_asmins_t *ins)
722 {
723         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
724         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
725         rvmreg_t tmp = rvm_reg_create_signed(0);
726         rmap_t *a = NULL;
727         rpointer value;
728         long index;
729
730         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
731         index = (long)RVM_REG_GETL(&tmp);
732         if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP)
733                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
734         a = (rmap_t*)RVM_REG_GETP(arg2);
735         value = r_map_value(a, index);
736         if (!value) {
737                 RVM_REG_CLEAR(arg1);
738                 RVM_REG_SETTYPE(arg1, RVM_DTYPE_UNDEF);
739         } else {
740                 *arg1 = *((rvmreg_t*)value);
741         }
742 }
743
744
745 static void rjs_op_mapkeyldr(rvmcpu_t *cpu, rvm_asmins_t *ins)
746 {
747         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
748         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
749         rvmreg_t tmp = rvm_reg_create_signed(0);
750         rmap_t *a = NULL;
751         rstring_t *key;
752         long index;
753
754         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
755         index = (long)RVM_REG_GETL(&tmp);
756         if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP)
757                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
758         a = (rmap_t*)RVM_REG_GETP(arg2);
759         key = r_map_key(a, index);
760         if (!key) {
761                 RVM_REG_CLEAR(arg1);
762                 RVM_REG_SETTYPE(arg1, RVM_DTYPE_UNDEF);
763         } else {
764                 rvm_reg_setstring(arg1, key);
765         }
766 }
767
768
769 static void rjs_op_mapnext(rvmcpu_t *cpu, rvm_asmins_t *ins)
770 {
771         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
772         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
773         rvmreg_t tmp = rvm_reg_create_signed(0);
774         rmap_t *a = NULL;
775         long index;
776
777         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
778         index = (long)RVM_REG_GETL(&tmp);
779         if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP)
780                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
781         a = (rmap_t*)RVM_REG_GETP(arg2);
782         if (index < 0)
783                 index = r_map_first(a);
784         else
785                 index = r_map_next(a, index);
786         RVM_REG_CLEAR(arg1);
787         RVM_REG_SETTYPE(arg1, RVM_DTYPE_SIGNED);
788         RVM_REG_SETL(arg1, index);
789 }
790
791
792 static void rjs_op_mapprev(rvmcpu_t *cpu, rvm_asmins_t *ins)
793 {
794         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
795         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
796         rvmreg_t tmp = rvm_reg_create_signed(0);
797         rmap_t *a = NULL;
798         long index;
799
800         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
801         index = (long)RVM_REG_GETL(&tmp);
802         if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP)
803                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
804         a = (rmap_t*)RVM_REG_GETP(arg2);
805         if (index < 0)
806                 index = r_map_last(a);
807         else
808                 index = r_map_prev(a, index);
809         RVM_REG_CLEAR(arg1);
810         RVM_REG_SETTYPE(arg1, RVM_DTYPE_SIGNED);
811         RVM_REG_SETL(arg1, index);
812 }
813
814
815 static void rjs_op_mapstr(rvmcpu_t *cpu, rvm_asmins_t *ins)
816 {
817         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
818         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
819         rvmreg_t tmp = rvm_reg_create_signed(0);
820         rmap_t *a = NULL;
821         rpointer value;
822         long index;
823
824         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
825         index = (long)RVM_REG_GETL(&tmp);
826         if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP)
827                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
828         a = (rmap_t*)RVM_REG_GETP(arg2);
829         value = r_map_value(a, index);
830         if (!value)
831                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
832         r_map_setvalue(a, index, arg1);
833 }
834
835
836 const char *rjs_version()
837 {
838         return RJS_VERSION_STRING;
839 }
840
841
842 static void rjs_string_ltrim(rvmcpu_t *cpu, rvm_asmins_t *ins)
843 {
844         const char *ptr, *list;
845         unsigned long size;
846         rvmreg_t *r = NULL, *l = NULL;
847         rstring_t *src, *dest;
848
849         r = (rvmreg_t *) RVM_CPUREG_PTR(cpu, TP);
850         if (RJS_SWI_PARAMS(cpu) > 0) {
851                 l = (rvmreg_t *) RJS_SWI_PARAM(cpu, 1);
852                 if (rvm_reg_gettype(l) != RVM_DTYPE_STRING)
853                         RJS_SWI_ABORT(rjs_engine_get(cpu), NULL);
854         }
855         if (rvm_reg_gettype(r) != RVM_DTYPE_STRING)
856                 RJS_SWI_ABORT(rjs_engine_get(cpu), NULL);
857         if (l)
858                 list = ((rstring_t *)RVM_REG_GETP(l))->s.str;
859         else
860                 list = " \t\n\r\0";
861         src = (rstring_t *)RVM_REG_GETP(r);
862         ptr = src->s.str;
863         size = src->s.size;
864         while (size > 0) {
865                 if (!r_strchr(list, *ptr))
866                         break;
867                 size--;
868                 ptr++;
869         }
870         dest = r_string_create_strsize(ptr, size);
871         r_gc_add(cpu->gc, (robject_t*)dest);
872         rvm_reg_setstring(RVM_CPUREG_PTR(cpu, R0), dest);
873 }
874
875
876 static void rjs_string_length(rvmcpu_t *cpu, rvm_asmins_t *ins)
877 {
878         unsigned long size;
879         rvmreg_t *r = NULL;
880         rstring_t *src;
881
882         r = (rvmreg_t *) RVM_CPUREG_PTR(cpu, TP);
883         if (rvm_reg_gettype(r) != RVM_DTYPE_STRING)
884                 RJS_SWI_ABORT(rjs_engine_get(cpu), NULL);
885         src = (rstring_t *)RVM_REG_GETP(r);
886         size = src->s.size;
887         rvm_reg_setsigned(RVM_CPUREG_PTR(cpu, R0), size);
888 }
889
890
891 rjs_engine_t *rjs_engine_create()
892 {
893         rvmcpu_t *cpu;
894         rvmreg_t *tp;
895         rvmreg_t tmp;
896         rjs_engine_t *jse = (rjs_engine_t *) r_zmalloc(sizeof(*jse));
897
898         jse->pa = rjs_parser_create();
899         jse->cpu = cpu = rvm_cpu_create_default();
900         jse->co = rjs_compiler_create(jse->cpu);
901         jse->cgs = r_array_create(sizeof(rvm_codegen_t*));
902         jse->errors = r_array_create(sizeof(rjs_error_t));
903         jse->cpu->userdata1 = jse;
904         rvm_cpu_addswitable(jse->cpu, "rjsswitable", rjsswitable);
905         if (!jse->pa || !jse->cpu || !jse->co || !jse->cgs)
906                 goto error;
907         rjs_engine_initgp(jse);
908         tp = rvm_cpu_alloc_global(jse->cpu);
909         rvm_reg_setjsobject(tp, (robject_t *)r_map_create(sizeof(rvmreg_t), 7));
910         r_gc_add(jse->cpu->gc, (robject_t*)RVM_REG_GETP(tp));
911         rvm_cpu_setreg(jse->cpu, TP, tp);
912
913         rvm_cpu_setophandler(cpu, RJS_CAST, "RJS_CAST", rjs_op_cast);
914         rvm_cpu_setophandler(cpu, RJS_ENEG, "RJS_ENEG", rjs_op_eneg);
915         rvm_cpu_setophandler(cpu, RJS_EADD, "RJS_EADD", rjs_op_eadd);
916         rvm_cpu_setophandler(cpu, RJS_ESUB, "RJS_ESUB", rjs_op_esub);
917         rvm_cpu_setophandler(cpu, RJS_EMUL, "RJS_EMUL", rjs_op_emul);
918         rvm_cpu_setophandler(cpu, RJS_EDIV, "RJS_EDIV", rjs_op_ediv);
919         rvm_cpu_setophandler(cpu, RJS_EMOD, "RJS_EMOD", rjs_op_emod);
920         rvm_cpu_setophandler(cpu, RJS_ELSL, "RJS_ELSL", rjs_op_elsl);
921         rvm_cpu_setophandler(cpu, RJS_ELSR, "RJS_ELSR", rjs_op_elsr);
922         rvm_cpu_setophandler(cpu, RJS_ELSRU, "RJS_ELSRU", rjs_op_elsru);
923         rvm_cpu_setophandler(cpu, RJS_EAND, "RJS_EAND", rjs_op_eand);
924         rvm_cpu_setophandler(cpu, RJS_EORR, "RJS_EORR", rjs_op_eorr);
925         rvm_cpu_setophandler(cpu, RJS_EXOR, "RJS_EXOR", rjs_op_exor);
926         rvm_cpu_setophandler(cpu, RJS_ENOT, "RJS_ENOT", rjs_op_enot);
927         rvm_cpu_setophandler(cpu, RJS_ELAND, "RJS_ELAND", rjs_op_eland);
928         rvm_cpu_setophandler(cpu, RJS_ELOR, "RJS_ELOR", rjs_op_elor);
929         rvm_cpu_setophandler(cpu, RJS_ELNOT, "RJS_ELNOT", rjs_op_elnot);
930         rvm_cpu_setophandler(cpu, RJS_EEQ, "RJS_EEQ", rjs_op_eeq);
931         rvm_cpu_setophandler(cpu, RJS_ENOTEQ, "RJS_ENOTEQ", rjs_op_enoteq);
932         rvm_cpu_setophandler(cpu, RJS_EGREAT, "RJS_EGREAT", rjs_op_egreat);
933         rvm_cpu_setophandler(cpu, RJS_EGREATEQ, "RJS_EGREATEQ", rjs_op_egreateq);
934         rvm_cpu_setophandler(cpu, RJS_ELESS, "RJS_ELESS", rjs_op_eless);
935         rvm_cpu_setophandler(cpu, RJS_ELESSEQ, "RJS_ELESSEQ", rjs_op_elesseq);
936         rvm_cpu_setophandler(cpu, RJS_ECMP, "RJS_ECMP", rjs_op_ecmp);
937         rvm_cpu_setophandler(cpu, RJS_ECMN, "RJS_ECMN", rjs_op_ecmn);
938         rvm_cpu_setophandler(cpu, RJS_PROPLKUP, "RJS_PROPLKUP", rjs_op_proplookup);
939         rvm_cpu_setophandler(cpu, RJS_PROPLKUPADD, "RJS_PROPLKUPADD", rjs_op_proplookupadd);
940         rvm_cpu_setophandler(cpu, RJS_PROPLDR, "RJS_PROPLDR", rjs_op_propldr);
941         rvm_cpu_setophandler(cpu, RJS_PROPSTR, "RJS_PROPSTR", rjs_op_propstr);
942         rvm_cpu_setophandler(cpu, RJS_PROPADDR, "RJS_PROPADDR", rjs_op_propaddr);
943         rvm_cpu_setophandler(cpu, RJS_PROPKEYLDR, "RJS_PROPKEYLDR", rjs_op_propkeyldr);
944         rvm_cpu_setophandler(cpu, RJS_PROPDEL, "RJS_PROPDEL", rjs_op_propdel);
945         rvm_cpu_setophandler(cpu, RJS_PROPNEXT, "RJS_PROPNEXT", rjs_op_propnext);
946         rvm_cpu_setophandler(cpu, RJS_PROPPREV, "RJS_PROPPREV", rjs_op_propprev);
947         rvm_cpu_setophandler(cpu, RJS_STRALLOC, "RJS_STRALLOC", rjs_op_stralloc);
948         rvm_cpu_setophandler(cpu, RJS_MAPALLOC, "RJS_MAPALLOC", rjs_op_mapalloc);
949
950         cpu->userdata2 = rjs_opmap_create();
951         rjs_op_binary_init(RJS_USERDATA2MAP(cpu->userdata2));
952         rjs_op_cast_init(RJS_USERDATA2MAP(cpu->userdata2));
953         rjs_op_not_init(RJS_USERDATA2MAP(cpu->userdata2));
954         rjs_op_logicnot_init(RJS_USERDATA2MAP(cpu->userdata2));
955
956
957         jse->props[RVM_DTYPE_STRING] = r_map_create(sizeof(rvmreg_t), 3);
958         tmp = rvm_reg_create_swi(rvm_cpu_swilookup_s(cpu, "rjsswitable", "string.ltrim"));
959         r_map_add_s(jse->props[RVM_DTYPE_STRING], "ltrim", &tmp);
960         tmp = rvm_reg_create_swi(rvm_cpu_swilookup_s(cpu, "rjsswitable", "string.length"));
961         r_map_add_s(jse->props[RVM_DTYPE_STRING], "length", &tmp);
962         r_gc_add(jse->cpu->gc, (robject_t*)jse->props[RVM_DTYPE_STRING]);
963
964         return jse;
965 error:
966         rjs_engine_destroy(jse);
967         return NULL;
968 }
969
970
971 void rjs_engine_destroy(rjs_engine_t *jse)
972 {
973         unsigned long i;
974
975         if (jse) {
976                 if (jse->cgs) {
977                         for (i = 0; i < r_array_length(jse->cgs); i++) {
978                                 rvm_codegen_destroy(r_array_index(jse->cgs, i, rvm_codegen_t*));
979                         }
980                 }
981                 r_array_destroy(jse->cgs);
982                 r_array_destroy(jse->errors);
983                 rjs_parser_destroy(jse->pa);
984                 rjs_opmap_destroy(RJS_USERDATA2MAP(jse->cpu->userdata2));
985                 rvm_cpu_destroy(jse->cpu);
986                 rjs_compiler_destroy(jse->co);
987                 r_free(jse);
988         }
989 }
990
991
992 static void rjs_engine_addtypename(rjs_engine_t *jse, rmap_t *types, unsigned long type, const char *typename)
993 {
994         rvmreg_t rs;
995         rstring_t *s;
996
997         s = r_string_create_from_ansistr(typename);
998         r_gc_add(jse->cpu->gc, (robject_t*)s);
999         rvm_reg_setstring(&rs, s);
1000         r_map_add_l(types, type, &rs);
1001 }
1002
1003
1004 static void rjs_engine_inittypes(rjs_engine_t *jse)
1005 {
1006         rmap_t *gmap = (rmap_t *)RVM_CPUREG_GETP(jse->cpu, GP);
1007         rmap_t *types;
1008         rvmreg_t rt;
1009
1010         types = r_map_create(sizeof(rvmreg_t), 3);
1011         r_gc_add(jse->cpu->gc, (robject_t*)types);
1012         rvm_reg_setjsobject(&rt, (robject_t *)types);
1013         r_map_add_l(gmap, RJS_GPKEY_TYPES, &rt);
1014         rjs_engine_addtypename(jse, types, RVM_DTYPE_UNDEF, "undefined");
1015         rjs_engine_addtypename(jse, types, RVM_DTYPE_BOOLEAN, "boolean");
1016         rjs_engine_addtypename(jse, types, RVM_DTYPE_DOUBLE, "number");
1017         rjs_engine_addtypename(jse, types, RVM_DTYPE_UNSIGNED, "number");
1018         rjs_engine_addtypename(jse, types, RVM_DTYPE_SIGNED, "number");
1019         rjs_engine_addtypename(jse, types, RVM_DTYPE_STRING, "string");
1020         rjs_engine_addtypename(jse, types, RVM_DTYPE_FUNCTION, "object");
1021         rjs_engine_addtypename(jse, types, RVM_DTYPE_NAN, "object");
1022         rjs_engine_addtypename(jse, types, RVM_DTYPE_MAP, "object");
1023         rjs_engine_addtypename(jse, types, RVM_DTYPE_POINTER, "object");
1024 }
1025
1026
1027 static void rjs_engine_initgp(rjs_engine_t *jse)
1028 {
1029         rvmreg_t gp;
1030         rmap_t *gmap;
1031
1032         rvm_reg_init(&gp);
1033         gmap = r_map_create(sizeof(rvmreg_t), 7);
1034         r_gc_add(jse->cpu->gc, (robject_t*)gmap);
1035         rvm_reg_setjsobject(RVM_CPUREG_PTR(jse->cpu, GP), (robject_t *)gmap);
1036         rjs_engine_inittypes(jse);
1037 }
1038
1039
1040 int rjs_engine_open(rjs_engine_t *jse)
1041 {
1042         return 0;
1043 }
1044
1045
1046 int rjs_engine_addswitable(rjs_engine_t *jse, const char *tabname, rvm_switable_t *switalbe)
1047 {
1048         return rvm_cpu_addswitable(jse->cpu, tabname, switalbe);
1049 }
1050
1051
1052 static int rjs_engine_parse(rjs_engine_t *jse, const char *script, unsigned long size, rarray_t *records, rjs_error_t *error)
1053 {
1054         long res = 0;
1055
1056         res = rjs_parser_exec(jse->pa, script, size, records, error);
1057         return res;
1058 }
1059
1060
1061 int rjs_engine_compile(rjs_engine_t *jse, const char *script, unsigned long size)
1062 {
1063         rvm_codegen_t *topcg = NULL;
1064         rarray_t *records = rpa_records_create();
1065         rjs_error_t error;
1066         jse->co->debug = jse->debugcompile;
1067
1068         r_memset(&error, 0, sizeof(error));
1069         if (rjs_engine_parse(jse, script, size, records, &error) < 0) {
1070
1071                 goto err;
1072         }
1073
1074         topcg =  r_array_empty(jse->cgs) ? NULL : r_array_last(jse->cgs, rvm_codegen_t*);
1075         if (!topcg || (topcg->userdata & RJS_COMPILER_CODEGENKEEP)) {
1076                 /*
1077                  * Keep this script codegen object. Allocate a new one for the
1078                  * next script.
1079                  */
1080                 topcg = rvm_codegen_create();
1081                 r_array_add(jse->cgs, &topcg);
1082         } else {
1083                 rvm_codegen_clear(topcg);
1084         }
1085         topcg->userdata = 0;
1086         if (rjs_compiler_compile(jse->co, script, size, records, topcg, &error) < 0) {
1087                 topcg->userdata = 0;
1088                 goto err;
1089         }
1090
1091         rpa_records_destroy(records);
1092         return 0;
1093
1094 err:
1095         r_array_add(jse->errors, &error);
1096         rpa_records_destroy(records);
1097         return -1;
1098 }
1099
1100
1101 int rjs_engine_dumpast(rjs_engine_t *jse, const char *script, unsigned long size)
1102 {
1103         rjs_error_t error;
1104         rarray_t *records = rpa_records_create();
1105
1106         if (rjs_engine_parse(jse, script, size, records, &error) < 0) {
1107
1108
1109                 return -1;
1110         }
1111
1112         if (records) {
1113                 long i;
1114                 for (i = 0; i < rpa_records_length(records); i++)
1115                         rpa_record_dump(records, i);
1116         }
1117
1118         rpa_records_destroy(records);
1119         return 0;
1120 }
1121
1122
1123 int rjs_engine_compile_s(rjs_engine_t *jse, const char *script)
1124 {
1125         return rjs_engine_compile(jse, script, r_strlen(script));
1126 }
1127
1128
1129 int rjs_engine_close(rjs_engine_t *jse)
1130 {
1131
1132         return 0;
1133 }
1134
1135
1136 int rjs_engine_run(rjs_engine_t *jse)
1137 {
1138         int res = 0;
1139         rvm_codegen_t *cg = r_array_empty(jse->cgs) ? NULL : r_array_last(jse->cgs, rvm_codegen_t*);
1140
1141         if (!cg) {
1142
1143                 return -1;
1144         }
1145         if (jse->debugexec) {
1146                 res = rvm_cpu_exec_debug(jse->cpu, rvm_codegen_getcode(cg, 0), 0);
1147         } else {
1148                 res = rvm_cpu_exec(jse->cpu, rvm_codegen_getcode(cg, 0), 0);
1149         }
1150
1151         if (jse->cpu->error == RVM_E_USERABORT) {
1152                 rword idx = RVM_CPUREG_GETIP(jse->cpu, PC) - rvm_codegen_getcode(cg, 0);
1153                 if (idx >= 0) {
1154                         r_printf("Aborted at source index: %ld\n", rvm_codegen_getsource(cg, (unsigned long)idx));
1155                 }
1156         }
1157         return res;
1158 }
1159
1160
1161 rvmreg_t * rjs_engine_exec(rjs_engine_t *jse, const char *script, unsigned long size)
1162 {
1163         if (rjs_engine_compile(jse, script, size) < 0)
1164                 return NULL;
1165         RVM_CPUREG_SETU(jse->cpu, FP, 0);
1166         RVM_CPUREG_SETU(jse->cpu, SP, 0);
1167         if (rjs_engine_run(jse) < 0)
1168                 return NULL;
1169         return RVM_CPUREG_PTR(jse->cpu, R0);
1170 }
1171
1172
1173 rvmreg_t *rjs_engine_exec_s(rjs_engine_t *jse, const char *script)
1174 {
1175         return rjs_engine_exec(jse, script, r_strlen(script));
1176 }
1177
1178
1179 static int rjs_compiler_argarray_setup(rjs_compiler_t *co)
1180 {
1181         rvm_varmap_t *v;
1182         rvmreg_t count = rvm_reg_create_signed(0);
1183         rmap_t *a;
1184
1185         v = rvm_scope_tiplookup_s(co->scope, "ARGS");
1186         if (!v) {
1187                 return -1;
1188         }
1189         a = r_map_create(sizeof(rvmreg_t), 7);
1190         r_gc_add(co->cpu->gc, (robject_t*)a);
1191         r_map_add_s(a, "count", &count);
1192         rvm_reg_setjsobject((rvmreg_t*)v->data.ptr, (robject_t*)a);
1193         return 0;
1194 }
1195
1196
1197 static int rjs_compiler_addarg(rjs_compiler_t *co, rvmreg_t *arg)
1198 {
1199         rvm_varmap_t *v;
1200         rmap_t *a;
1201         rvmreg_t *count;
1202         long index;
1203
1204         v = rvm_scope_tiplookup_s(co->scope, "ARGS");
1205         if (!v) {
1206                 return -1;
1207         }
1208         a = (rmap_t*)RVM_REG_GETP((rvmreg_t*)v->data.ptr);
1209         index = r_map_lookup_s(a, -1, "count");
1210         R_ASSERT(index >= 0);
1211         count = (rvmreg_t *)r_map_value(a, index);
1212         r_map_add_l(a, (long)RVM_REG_GETL(count), arg);
1213         rvm_reg_setsigned(count, RVM_REG_GETL(count) + 1);
1214
1215         return 0;
1216 }
1217
1218
1219 rvmreg_t *rjs_engine_vexec(rjs_engine_t *jse, const char *script, unsigned long size, unsigned long nargs, va_list args)
1220 {
1221         rvmreg_t arg;
1222         unsigned long i = 0;
1223
1224         if (rjs_engine_compile(jse, script, size) < 0)
1225                 return NULL;
1226         if (nargs > 0) {
1227                 rjs_compiler_argarray_setup(jse->co);
1228                 for (i = 0; i < nargs; i++) {
1229                         arg = va_arg(args, rvmreg_t);
1230                         rjs_compiler_addarg(jse->co, &arg);
1231                 }
1232         }
1233         RVM_CPUREG_SETU(jse->cpu, FP, 0);
1234         RVM_CPUREG_SETU(jse->cpu, SP, 0);
1235         if (rjs_engine_run(jse) < 0)
1236                 return NULL;
1237         return RVM_CPUREG_PTR(jse->cpu, R0);
1238 }
1239
1240
1241 rvmreg_t *rjs_engine_args_exec(rjs_engine_t *jse, const char *script, unsigned long size, unsigned long nargs, ...)
1242 {
1243         rvmreg_t *ret;
1244         va_list args;
1245         va_start(args, nargs);
1246         ret = rjs_engine_vexec(jse, script, size, nargs, args);
1247         va_end(args);
1248         return ret;
1249 }
1250
1251
1252 rvmreg_t *rjs_engine_args_exec_s(rjs_engine_t *jse, const char *script, unsigned long nargs, ...)
1253 {
1254         rvmreg_t *ret;
1255         va_list args;
1256         va_start(args, nargs);
1257         ret = rjs_engine_vexec(jse, script, r_strlen(script), nargs, args);
1258         va_end(args);
1259         return ret;
1260 }
1261
1262
1263 static void rjs_engine_print(rvmcpu_t *cpu, rvm_asmins_t *ins)
1264 {
1265         rvmreg_t *r = (rvmreg_t *)RVM_STACK_ADDR(cpu->stack, RVM_CPUREG_GETU(cpu, FP) + 1);
1266
1267         if (rvm_reg_gettype(r) == RVM_DTYPE_UNSIGNED)
1268                 r_printf("%lu\n", RVM_REG_GETU(r));
1269         else if (rvm_reg_gettype(r) == RVM_DTYPE_NAN)
1270                 r_printf("NaN\n");
1271         else if (rvm_reg_gettype(r) == RVM_DTYPE_UNDEF)
1272                 r_printf("undefined\n");
1273         else if (rvm_reg_gettype(r) == RVM_DTYPE_BOOLEAN)
1274                 r_printf("%s\n", RVM_REG_GETU(r) ? "true" : "false");
1275         else if (rvm_reg_gettype(r) == RVM_DTYPE_POINTER)
1276                 r_printf("%p\n", RVM_REG_GETP(r));
1277         else if (rvm_reg_gettype(r) == RVM_DTYPE_SIGNED)
1278                 r_printf("%ld\n", RVM_REG_GETL(r));
1279         else if (rvm_reg_gettype(r) == RVM_DTYPE_DOUBLE)
1280                 r_printf("%f\n", RVM_REG_GETD(r));
1281         else if (rvm_reg_gettype(r) == RVM_DTYPE_STRING)
1282                 r_printf("%s\n", ((rstring_t*) RVM_REG_GETP(r))->s.str);
1283         else if (rvm_reg_gettype(r) == RVM_DTYPE_STRPTR)
1284                 r_printf("(STRPTR) %s\n", (RVM_REG_GETSTR(r)));
1285         else if (rvm_reg_gettype(r) == RVM_DTYPE_MAP)
1286                 r_printf("(object) %p\n",RVM_REG_GETP(r));
1287         else if (rvm_reg_gettype(r) == RVM_DTYPE_HARRAY)
1288                 r_printf("(hashed array) %p\n",RVM_REG_GETP(r));
1289         else if (rvm_reg_gettype(r) == RVM_DTYPE_SWIID)
1290                 r_printf("(function) %p\n",RVM_REG_GETP(r));
1291         else
1292                 r_printf("%p\n", RVM_REG_GETP(r));
1293 }
1294
1295
1296 static void rjs_engine_dbgprint(rvmcpu_t *cpu, rvm_asmins_t *ins)
1297 {
1298         rvmreg_t *r = (rvmreg_t *)RVM_STACK_ADDR(cpu->stack, RVM_CPUREG_GETU(cpu, FP) + 1);
1299
1300         if (rvm_reg_gettype(r) == RVM_DTYPE_UNSIGNED)
1301                 r_printf("(UNSIGNED) %lu\n", RVM_REG_GETU(r));
1302         else if (rvm_reg_gettype(r) == RVM_DTYPE_NAN)
1303                 r_printf("(NAN) NaN\n");
1304         else if (rvm_reg_gettype(r) == RVM_DTYPE_UNDEF)
1305                 r_printf("(UNDEF) undefined\n");
1306         else if (rvm_reg_gettype(r) == RVM_DTYPE_BOOLEAN)
1307                 r_printf("(BOOLEAN) %s\n", RVM_REG_GETU(r) ? "true" : "false");
1308         else if (rvm_reg_gettype(r) == RVM_DTYPE_POINTER)
1309                 r_printf("(POINTER) %p\n", RVM_REG_GETP(r));
1310         else if (rvm_reg_gettype(r) == RVM_DTYPE_SIGNED)
1311                 r_printf("(LONG) %ld\n", RVM_REG_GETL(r));
1312         else if (rvm_reg_gettype(r) == RVM_DTYPE_DOUBLE)
1313                 r_printf("(DOUBLE) %f\n", RVM_REG_GETD(r));
1314         else if (rvm_reg_gettype(r) == RVM_DTYPE_STRING)
1315                 r_printf("(STRING) %s\n", ((rstring_t*) RVM_REG_GETP(r))->s.str);
1316         else if (rvm_reg_gettype(r) == RVM_DTYPE_STRPTR)
1317                 r_printf("(STRPTR) %s\n", (RVM_REG_GETSTR(r)));
1318         else if (rvm_reg_gettype(r) == RVM_DTYPE_MAP)
1319                 r_printf("(object) %p\n",RVM_REG_GETP(r));
1320         else if (rvm_reg_gettype(r) == RVM_DTYPE_HARRAY)
1321                 r_printf("(hashed array) %p\n",RVM_REG_GETP(r));
1322         else if (rvm_reg_gettype(r) == RVM_DTYPE_SWIID)
1323                 r_printf("(swi function) %p\n",RVM_REG_GETP(r));
1324         else if (rvm_reg_gettype(r) == RVM_DTYPE_FUNCTION)
1325                 r_printf("(function) %p\n",RVM_REG_GETP(r));
1326         else
1327                 r_printf("%p\n", RVM_REG_GETP(r));
1328 }
1329
1330
1331 static void rjs_engine_object(rvmcpu_t *cpu, rvm_asmins_t *ins)
1332 {
1333
1334 }
1335
1336
1337 void rjs_engine_abort(rjs_engine_t *jse, rjs_error_t *error)
1338 {
1339         if (error) {
1340                 r_array_add(jse->errors, error);
1341         }
1342         rvm_cpu_abort(jse->cpu);
1343 }
1344
1345
1346 rjs_engine_t *rjs_engine_get(rvmcpu_t *cpu)
1347 {
1348         return (rjs_engine_t *)cpu->userdata1;
1349 }