inline -> __inline
[reactos.git] / reactos / lib / kjs / include / jsint.h
1 /*
2 * Internal definitions for the JavaScript interpreter.
3 * Copyright (c) 1998-1999 New Generation Software (NGS) Oy
4 *
5 * Author: Markku Rossi <mtr@ngs.fi>
6 */
7
8 /*
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
18 *
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the Free
21 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22 * MA 02111-1307, USA
23 */
24
25 /*
26 * $Source: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/kjs/include/jsint.h,v $
27 * $Id$
28 */
29
30 #ifndef JSINT_H
31 #define JSINT_H
32
33 /* We have always jsconfig.h */
34 #include <jsconfig.h>
35
36 #include <stdio.h>
37 #include <assert.h>
38 /* #include <setjmp.h> */
39 /* #include <math.h> */
40 #include <time.h>
41 #include <limits.h>
42
43 #if HAVE_UNISTD_H
44 #include <unistd.h>
45 #endif
46
47 #if STDC_HEADERS
48 #include <stdlib.h>
49 #include <errno.h>
50 #include <string.h>
51 #include <float.h>
52
53 #else /* not STDC_HEADERS */
54
55 #if HAVE_STDLIB_H
56 #include <stdlib.h>
57 #endif
58
59 #if HAVE_ERRNO_H
60 #include <errno.h>
61 #endif
62
63 #if HAVE_STRING_H
64 #include <string.h>
65 #endif
66
67 #if HAVE_FLOAT_H
68 #include <float.h>
69 #endif
70
71 #endif /* not STDC_HEADERS */
72
73 /* Misc system headers. */
74
75 #include <sys/types.h>
76
77 /*
78 * Protability kludges. If something is missing from the w32
79 * environment, please edit the micros/w32.{c,h} files and implement
80 * them.
81 */
82 #ifndef WIN32
83
84 /* Directory handling. */
85 #include <dirent.h>
86
87 #endif /* not WIN32 */
88
89 #include <js.h>
90
91 #if __cplusplus
92 extern "C" {
93 #endif
94
95 /*
96 * Types and definitions.
97 */
98
99 /* Some portability features. */
100 #ifdef WIN32
101
102 #define JS_HOST_LINE_BREAK "\r\n"
103 #define JS_HOST_LINE_BREAK_LEN 2
104
105 #else /* not WIN32 */
106
107 #define JS_HOST_LINE_BREAK "\n"
108 #define JS_HOST_LINE_BREAK_LEN 1
109
110 #endif /* not WIN32 */
111
112
113 #define JS_BC_FILE_MAGIC 0xc0014a53
114
115 #define JS_GLOBAL_NAME ".global"
116
117 #define JS_SYMBOL_NULL ((JSSymbol) -1)
118
119 #define JS_IS_STR_WHITE_SPACE_CHAR(ch) \
120 ((ch) == '\t' || (ch) == ' ' || (ch) == '\f' || (ch) == '\v' \
121 || (ch) == '\r' || (ch) == '\n')
122
123 /*
124 * Read macros for byte code files.
125 */
126
127 #define JS_BC_READ_INT32(cp, var) \
128 (var) = (cp)[0]; \
129 (var) <<= 8; \
130 (var) |= (cp)[1]; \
131 (var) <<= 8; \
132 (var) |= (cp)[2]; \
133 (var) <<= 8; \
134 (var) |= (cp)[3]
135
136 #define JS_BC_READ_INT16(cp, var) \
137 (var) = (cp)[0]; \
138 (var) <<= 8; \
139 (var) |= (cp)[1]
140
141 #define JS_BC_READ_INT8(cp, var) \
142 (var) = (cp)[0]
143
144 #define JS_BC_WRITE_INT32(cp, var) \
145 cp[3] = (unsigned char) ((var) & 0x000000ff); \
146 cp[2] = (unsigned char) (((var) >> 8) & 0x000000ff); \
147 cp[1] = (unsigned char) (((var) >> 16) & 0x000000ff); \
148 cp[0] = (unsigned char) (((var) >> 24) & 0x000000ff)
149
150
151 /* General VM macros. */
152
153 /* STACKFRAME */
154
155 #define JS_SP0 sp
156 #define JS_SP1 (sp + 1)
157 #define JS_SP2 (sp + 2)
158 #define JS_SP(n) (sp + (n))
159
160 #define JS_LOCAL(n) (fp - 4 - (n))
161 #define JS_ARG(n) (fp + 1 + (n))
162
163 #define JS_WITHPTR (fp - 2)
164 #define JS_ARGS_FIXP (fp - 1)
165
166 #define JS_PUSH() sp--
167 #define JS_POP() sp++
168 #define JS_POP_N(n) sp += (n)
169
170 #define JS_COPY(to, from) \
171 do { \
172 (to)->type = (from)->type; \
173 (to)->u.copy.a = (from)->u.copy.a; \
174 (to)->u.copy.b = (from)->u.copy.b; \
175 } while (0)
176
177 #define JS_CONST(n) (&vm->consts[(n)])
178 #define JS_GLOBAL(n) (&vm->globals[(n)])
179
180 #define JS_SAVE_REGS() \
181 do { \
182 vm->sp = sp; \
183 vm->pc = pc; \
184 } while (0)
185
186 #define JS_CALL_HOOK(event) \
187 do { \
188 int hook_result; \
189 \
190 if (vm->hook) \
191 if ((hook_result = (*vm->hook) ((event), vm->hook_context)) != 0) \
192 { \
193 JS_SAVE_REGS (); \
194 sprintf (vm->error, "hook break %d", hook_result); \
195 js_vm_error (vm); \
196 /* NOTREACHED */ \
197 } \
198 } while (0)
199
200 #define JS_VM_ALLOCATE_FD(vm, where) \
201 do { \
202 if ((vm)->fd_count == 0) \
203 { \
204 sprintf ((vm)->error, "%s: no more file descriptors allowed", \
205 (where)); \
206 js_vm_error (vm); \
207 } \
208 (vm)->fd_count--; \
209 } while (0)
210
211 #define JS_VM_FREE_FD(vm) \
212 do { \
213 (vm)->fd_count++; \
214 } while (0)
215
216 #define JS_MAYBE_GC() \
217 do { \
218 if (vm->gc.bytes_allocated >= vm->gc.trigger) \
219 { \
220 js_vm_garbage_collect (vm, fp, sp); \
221 JS_CALL_HOOK (JS_VM_EVENT_GARBAGE_COLLECT); \
222 } \
223 } while (0)
224
225 #define JS_IS_TRUE(n) ((n)->type > JS_INTEGER \
226 || ((n)->type == JS_BOOLEAN && (n)->u.vboolean) \
227 || ((n)->type == JS_INTEGER && (n)->u.vinteger))
228
229 #define JS_IS_FALSE(n) ((n)->type < JS_BOOLEAN \
230 || ((n)->type == JS_BOOLEAN && !(n)->u.vboolean) \
231 || ((n)->type == JS_INTEGER && !(n)->u.vinteger))
232
233 #define JS_RESERVE_STACK_FOR_FUNCTION 10
234
235 #define JS_SUBROUTINE_CALL(function) \
236 do { \
237 /* Check that we have enought space in the stack. */ \
238 if (sp - JS_RESERVE_STACK_FOR_FUNCTION < vm->stack) \
239 ERROR ("stack overflow"); \
240 \
241 /* STACKFRAME */ \
242 \
243 /* Save frame pointer. */ \
244 JS_SP0->type = JS_IPTR; \
245 JS_SP0->u.iptr = fp; \
246 \
247 /* Update fp. */ \
248 fp = JS_SP0; \
249 JS_PUSH (); \
250 \
251 /* Insert an empty args_fix. */ \
252 JS_SP0->type = JS_ARGS_FIX; \
253 JS_SP0->u.args_fix.argc = 0; \
254 JS_SP0->u.args_fix.delta = 0; \
255 JS_PUSH (); \
256 \
257 /* Insert empty with pointer. */ \
258 JS_SP0->type = JS_IPTR; \
259 JS_SP0->u.iptr = NULL; \
260 JS_PUSH (); \
261 \
262 /* Save return address. */ \
263 JS_SP0->type = JS_IPTR; \
264 JS_SP0->u.iptr = pc; \
265 JS_PUSH (); \
266 \
267 /* And finally, jump to the method code. */ \
268 CALL_USER_FUNC ((function)); \
269 } while (0)
270
271 #define JS_OPERAND_CMP_REL(_OP_) \
272 do { \
273 if (JS_SP2->type == JS_STRING && JS_SP1->type == JS_STRING) \
274 { \
275 JS_SP2->u.vboolean \
276 = js_compare_strings (JS_SP2, JS_SP1) _OP_ 0; \
277 JS_SP2->type = JS_BOOLEAN; \
278 JS_POP (); \
279 } \
280 else if (JS_SP2->type == JS_INTEGER && JS_SP1->type == JS_INTEGER) \
281 { \
282 JS_SP2->u.vboolean \
283 = JS_SP2->u.vinteger _OP_ JS_SP1->u.vinteger; \
284 JS_SP2->type = JS_BOOLEAN; \
285 JS_POP (); \
286 } \
287 else \
288 { \
289 JSNode l, r; \
290 \
291 /* Do it the hard way. */ \
292 switch (JS_SP2->type) \
293 { \
294 case JS_INTEGER: \
295 case JS_FLOAT: \
296 case JS_NAN: \
297 JS_COPY (&l, JS_SP2); \
298 break; \
299 \
300 default: \
301 js_vm_to_number (vm, JS_SP2, &l); \
302 break; \
303 } \
304 \
305 switch (JS_SP1->type) \
306 { \
307 case JS_INTEGER: \
308 case JS_FLOAT: \
309 case JS_NAN: \
310 JS_COPY (&r, JS_SP1); \
311 break; \
312 \
313 default: \
314 js_vm_to_number (vm, JS_SP1, &r); \
315 break; \
316 } \
317 \
318 /* Do the comparison. */ \
319 JS_POP (); \
320 \
321 if (l.type == JS_NAN || r.type == JS_NAN) \
322 JS_SP1->type = JS_UNDEFINED; \
323 else if (l.type == JS_INTEGER && r.type == JS_INTEGER) \
324 { \
325 JS_SP1->type = JS_BOOLEAN; \
326 JS_SP1->u.vboolean = l.u.vinteger _OP_ r.u.vinteger; \
327 } \
328 else \
329 { \
330 double ld, rd; \
331 \
332 if (l.type == JS_FLOAT) \
333 ld = l.u.vfloat; \
334 else \
335 ld = (double) l.u.vinteger; \
336 \
337 if (r.type == JS_FLOAT) \
338 rd = r.u.vfloat; \
339 else \
340 rd = (double) r.u.vinteger; \
341 \
342 JS_SP1->type = JS_BOOLEAN; \
343 JS_SP1->u.vboolean = ld _OP_ rd; \
344 } \
345 } \
346 } while (0)
347
348 #define JS_OPERAND_CMP_EQ(_OP_, _VAL_) \
349 while (1) { \
350 int res; \
351 if (JS_SP2->type == JS_SP1->type) \
352 { \
353 /* Comparsion between same types. */ \
354 switch (JS_SP2->type) \
355 { \
356 case JS_INTEGER: \
357 res = JS_SP2->u.vinteger _OP_ JS_SP1->u.vinteger; \
358 break; \
359 \
360 case JS_STRING: \
361 res = js_compare_strings (JS_SP2, JS_SP1) _OP_ 0; \
362 break; \
363 \
364 case JS_FLOAT: \
365 res = JS_SP2->u.vfloat _OP_ JS_SP1->u.vfloat; \
366 break; \
367 \
368 case JS_NAN: \
369 /* 11.9.3: cases 5 and 6 */ \
370 res = !_VAL_; \
371 break; \
372 \
373 case JS_BOOLEAN: \
374 res = JS_SP2->u.vboolean _OP_ JS_SP1->u.vboolean; \
375 break; \
376 \
377 case JS_OBJECT: \
378 res = JS_SP2->u.vobject _OP_ JS_SP1->u.vobject; \
379 break; \
380 \
381 case JS_BUILTIN: \
382 res = ((JS_SP2->u.vbuiltin->info \
383 == JS_SP1->u.vbuiltin->info \
384 && (JS_SP2->u.vbuiltin->instance_context \
385 == JS_SP1->u.vbuiltin->instance_context)) \
386 ? _VAL_ : !_VAL_); \
387 break; \
388 \
389 case JS_FUNC: \
390 res = JS_SP2->u.vfunction _OP_ JS_SP1->u.vfunction; \
391 break; \
392 \
393 case JS_SYMBOL: \
394 res = JS_SP2->u.vsymbol _OP_ JS_SP1->u.vsymbol; \
395 break; \
396 \
397 case JS_IPTR: \
398 res = JS_SP2->u.iptr _OP_ JS_SP1->u.iptr; \
399 break; \
400 \
401 default: \
402 res = _VAL_; \
403 break; \
404 } \
405 } \
406 else \
407 { \
408 /* Type conversions between different types. */ \
409 \
410 if ((JS_SP2->type == JS_UNDEFINED || JS_SP2->type == JS_NULL) \
411 && (JS_SP1->type == JS_UNDEFINED \
412 || JS_SP1->type == JS_NULL)) \
413 res = _VAL_; \
414 \
415 /* Numbers. */ \
416 else if (JS_IS_NUMBER (JS_SP2) && JS_IS_NUMBER (JS_SP1)) \
417 { \
418 if (JS_SP2->type == JS_NAN || JS_SP1->type == JS_NAN) \
419 /* 11.9.3: cases 5 and 6 */ \
420 res = !_VAL_; \
421 else if (JS_SP2->type == JS_INTEGER) \
422 /* Integer-integer was already handled. */ \
423 res = (double) JS_SP2->u.vinteger _OP_ JS_SP1->u.vfloat; \
424 else \
425 /* Integer-integer was already handled. */ \
426 res = JS_SP2->u.vfloat _OP_ (double) JS_SP1->u.vinteger; \
427 } \
428 else \
429 { \
430 JSNode l, r; \
431 \
432 /* Must perform type casts. */ \
433 \
434 if ((JS_SP2->type == JS_STRING || JS_SP2->type == JS_BOOLEAN \
435 || JS_IS_NUMBER (JS_SP2)) \
436 && (JS_SP1->type == JS_STRING \
437 || JS_SP1->type == JS_BOOLEAN \
438 || JS_IS_NUMBER (JS_SP1))) \
439 { \
440 js_vm_to_number (vm, JS_SP2, &l); \
441 js_vm_to_number (vm, JS_SP1, &r); \
442 \
443 if (l.type == JS_NAN || r.type == JS_NAN) \
444 res = !_VAL_; \
445 else if (l.type == JS_INTEGER) \
446 { \
447 if (r.type == JS_INTEGER) \
448 res = l.u.vinteger _OP_ r.u.vinteger; \
449 else \
450 res = (double) l.u.vinteger _OP_ r.u.vfloat; \
451 } \
452 else \
453 { \
454 if (r.type == JS_INTEGER) \
455 res = l.u.vfloat _OP_ (double) r.u.vinteger; \
456 else \
457 res = l.u.vfloat _OP_ r.u.vfloat; \
458 } \
459 } \
460 else if (JS_SP2->type == JS_OBJECT \
461 && (JS_SP1->type == JS_STRING \
462 || JS_IS_NUMBER (JS_SP1))) \
463 { \
464 JSNode cvt; \
465 \
466 /* ECMA 11.9.3 21. No preferred type specified. */ \
467 js_vm_to_primitive (vm, JS_SP2, &cvt, JS_UNDEFINED); \
468 JS_COPY (JS_SP2, &cvt); \
469 continue; \
470 } \
471 else if (JS_SP1->type == JS_OBJECT \
472 && (JS_SP2->type == JS_STRING \
473 || JS_IS_NUMBER (JS_SP2))) \
474 { \
475 JSNode cvt; \
476 \
477 /* ECMA 11.9.3 20. No preferred type specified. */ \
478 js_vm_to_primitive (vm, JS_SP1, &cvt, JS_UNDEFINED); \
479 JS_COPY (JS_SP1, &cvt); \
480 continue; \
481 } \
482 else \
483 res = !_VAL_; \
484 } \
485 } \
486 \
487 JS_SP2->type = JS_BOOLEAN; \
488 JS_SP2->u.vboolean = res; \
489 JS_POP (); \
490 break; \
491 }
492
493 #define JS_OPERAND_CMP_SEQ(_OP_, _VAL_) \
494 do { \
495 int res; \
496 if (JS_SP2->type == JS_SP1->type) \
497 { \
498 switch (JS_SP2->type) \
499 { \
500 case JS_INTEGER: \
501 res = JS_SP2->u.vinteger _OP_ JS_SP1->u.vinteger; \
502 break; \
503 \
504 case JS_FLOAT: \
505 res = JS_SP2->u.vfloat _OP_ JS_SP1->u.vfloat; \
506 break; \
507 \
508 case JS_NAN: \
509 /* 11.9.6: cases 3 and 4 */ \
510 res = !_VAL_; \
511 break; \
512 \
513 case JS_STRING: \
514 res = js_compare_strings (JS_SP2, JS_SP1) _OP_ 0; \
515 break; \
516 \
517 case JS_BOOLEAN: \
518 res = JS_SP2->u.vboolean _OP_ JS_SP1->u.vboolean; \
519 break; \
520 \
521 case JS_OBJECT: \
522 res = JS_SP2->u.vobject _OP_ JS_SP1->u.vobject; \
523 break; \
524 \
525 case JS_BUILTIN: \
526 res = ((JS_SP2->u.vbuiltin->info \
527 == JS_SP1->u.vbuiltin->info \
528 && (JS_SP2->u.vbuiltin->instance_context \
529 == JS_SP1->u.vbuiltin->instance_context)) \
530 ? _VAL_ : !_VAL_); \
531 break; \
532 \
533 case JS_FUNC: \
534 res = JS_SP2->u.vfunction _OP_ JS_SP1->u.vfunction; \
535 break; \
536 \
537 default: \
538 /* 11.9.6: case 12 */ \
539 res = !_VAL_; \
540 break; \
541 } \
542 } \
543 else \
544 { \
545 /* Only numbers are allowed here. */ \
546 if (JS_IS_NUMBER (JS_SP2) && JS_IS_NUMBER (JS_SP1)) \
547 { \
548 if (JS_SP2->type == JS_NAN || JS_SP1->type == JS_NAN) \
549 /* 11.9.6: cases 3 and 4 */ \
550 res = !_VAL_; \
551 else if (JS_SP2->type == JS_INTEGER) \
552 res = (double) JS_SP2->u.vinteger _OP_ JS_SP1->u.vfloat; \
553 else \
554 res = JS_SP2->u.vfloat _OP_ (double) JS_SP1->u.vinteger; \
555 } \
556 else \
557 res = !_VAL_; \
558 } \
559 \
560 JS_SP2->type = JS_BOOLEAN; \
561 JS_SP2->u.vboolean = res; \
562 JS_POP (); \
563 \
564 } while (0)
565
566 #define JS_OPERAND_BINARY(_OP_) \
567 do { \
568 if (JS_SP2->type == JS_INTEGER && JS_SP1->type == JS_INTEGER) \
569 { \
570 JS_SP2->u.vinteger = ((JSInt32) JS_SP2->u.vinteger \
571 _OP_ (JSInt32) JS_SP1->u.vinteger); \
572 JS_POP (); \
573 } \
574 else \
575 { \
576 JSInt32 l, r; \
577 \
578 l = js_vm_to_int32 (vm, JS_SP2); \
579 r = js_vm_to_int32 (vm, JS_SP1); \
580 \
581 JS_SP2->u.vinteger = (l _OP_ r); \
582 JS_SP2->type = JS_INTEGER; \
583 JS_POP (); \
584 } \
585 } while (0)
586
587
588 #define JS_IS_NUMBER(n) \
589 ((n)->type == JS_INTEGER || (n)->type == JS_FLOAT || (n)->type == JS_NAN)
590
591 /* Some math macros. */
592
593 #define JS_MAKE_POSITIVE_INFINITY(node) \
594 do { \
595 (node)->type = JS_FLOAT; \
596 (node)->u.vfloat = HUGE_VAL; \
597 } while (0)
598
599 #define JS_MAKE_NEGATIVE_INFINITY(node) \
600 do { \
601 (node)->type = JS_FLOAT; \
602 (node)->u.vfloat = -HUGE_VAL; \
603 } while (0)
604
605 #define JS_IS_POSITIVE_INFINITY(node) \
606 ((node)->type == JS_FLOAT && (node)->u.vfloat == HUGE_VAL)
607
608 #define JS_IS_NEGATIVE_INFINITY(node) \
609 ((node)->type == JS_FLOAT && (node)->u.vfloat == -HUGE_VAL)
610
611 #define JS_IS_FINITE(node) \
612 (!JS_IS_POSITIVE_INFINITY ((node)) \
613 && !JS_IS_NEGATIVE_INFINITY ((node)) \
614 && (node)->type != JS_NAN) \
615
616 #define JS_IS_PRIMITIVE_VALUE(node) \
617 ((node)->type == JS_UNDEFINED || (node)->type == JS_NULL \
618 || (node)->type == JS_BOOLEAN || JS_IS_NUMBER ((node)) \
619 || (node)->type == JS_STRING)
620
621 /* Macro to clear all flags from a heap memory block. */
622 #define JS_HEAP_MEMORY_BLOCK_CLEAR_FLAGS(mb) \
623 do { \
624 (mb)->flag_mark = 0; \
625 (mb)->flag_destroyable = 0; \
626 } while (0)
627
628 #define JS_NUM_HEAP_FREELISTS 20
629
630 /*
631 * Virtual machine security flags. When these flags are enabled in
632 * the vm->security, the appropriate built-in modules don't implement
633 * insecure methods.
634 */
635
636 #define JS_VM_SECURE_FILE 0x01
637 #define JS_VM_SECURE_SYSTEM 0x02
638
639 /*
640 * Noticeable virtual machine events. The `JS_VM_EVENT_OPERAND_COUNT'
641 * event is generated only if the interpreter was configured with the
642 * `--enable-operand-hooks' option.
643 */
644
645 #define JS_VM_EVENT_OPERAND_COUNT 1
646 #define JS_VM_EVENT_GARBAGE_COLLECT 2
647
648 /*
649 * Integer types.
650 */
651
652 typedef unsigned char JSUInt8;
653 typedef signed char JSInt8;
654
655 typedef unsigned short JSUInt16;
656 typedef short JSInt16;
657
658 #if SIZEOF_INT == 4
659
660 typedef unsigned int JSUInt32;
661 typedef int JSInt32;
662
663 #else /* not SIZEOF_INT == 4 */
664
665 #if SIZEOF_LONG == 4
666
667 typedef unsigned long JSUInt32;
668 typedef long JSInt32;
669
670 #else /* not SIZEOF_LONG == 4 */
671
672 #error "do not know how to define a 32 bit long integer"
673
674 #endif /* not SIZEOF_LONG == 4 */
675
676 #endif /* not SIZEOF_INT == 4 */
677
678 /*
679 * An unsigned interger number that can be used to align structures to
680 * correct byte boundaries. On 64 bit machines (Alpha) this should be
681 * 64 bits long, etc. For now one, we just assume that the mashine is
682 * a LP64 so the `unsigned long' is a correct type for it.
683 */
684 typedef unsigned long JSUIntAlign;
685
686 /* I/O streams. */
687
688 /* Buffer filler or flusher function. */
689 typedef int (*JSIOStreamIOFunc) (void *context, unsigned char *buffer,
690 unsigned int todo, int *error_return);
691
692 typedef int (*JSIOStreamSeek) (void *context, long offset, int whence);
693
694 typedef long (*JSIOStreamGetPosition) (void *context);
695
696 typedef long (*JSIOStreamGetLength) (void *context);
697
698 typedef void (*JSIOStreamClose) (void *context);
699
700 /* The I/O stream handle. */
701 struct js_io_stream_st
702 {
703 unsigned char *buffer; /* Must be reallocatable with js_realloc(). */
704 unsigned int buflen;
705 unsigned int data_in_buf;
706 unsigned int bufpos;
707
708 /* Flags. */
709 unsigned int at_eof : 1;
710 unsigned int autoflush : 1;
711 unsigned int writep : 1; /* Does the buffer contain write data? */
712
713 /* The system error code for the last operation that failed. */
714 int error;
715
716 /* Only one of the read and write is active. */
717 JSIOStreamIOFunc read;
718 JSIOStreamIOFunc write;
719 JSIOStreamSeek seek;
720 JSIOStreamGetPosition get_position;
721 JSIOStreamGetLength get_length;
722
723 JSIOStreamClose close;
724
725 void *context;
726 };
727
728 typedef struct js_io_stream_st JSIOStream;
729
730
731 /* The destroy callback for the destroyable heap blocks. */
732 typedef void (*JSHeapDestroyableCB) (void *ptr);
733
734 /*
735 * Each destroyable heap block must be castable to this structure e.g.
736 * the first item in the block must be pointer to the destroy function.
737 */
738 struct js_heap_destroyable_st
739 {
740 JSHeapDestroyableCB destroy;
741 };
742
743 typedef struct js_heap_destroyable_st JSHeapDestroyable;
744
745
746 /* Interned symbol. */
747 typedef unsigned int JSSymbol;
748
749 /* JavaScript Types. */
750
751 typedef enum
752 {
753 JS_UNDEFINED = 0,
754 JS_NULL = 1,
755 JS_BOOLEAN = 2,
756 JS_INTEGER = 3, /* Integer, float and nan are `number' */
757 JS_STRING = 4,
758 JS_FLOAT = 5,
759 JS_ARRAY = 6,
760 JS_OBJECT = 7,
761
762 /*
763 * The following ones are the internal types, used by this implementation.
764 */
765
766 JS_SYMBOL = 10,
767 JS_BUILTIN = 11,
768 JS_FUNC = 12,
769 JS_NAN = 13,
770
771 JS_IPTR = 14,
772 JS_ARGS_FIX = 15
773 } JSNodeType;
774
775 struct js_node_st;
776 struct js_vm_st;
777 struct js_builtin_info_st;
778
779 /* Registry information for builtin objects. */
780
781 #define JS_PROPERTY_FOUND 1
782 #define JS_PROPERTY_UNKNOWN 0
783
784 typedef void (*JSBuiltinGlobalMethod) (struct js_vm_st *vm,
785 struct js_builtin_info_st *builtin_info,
786 void *instance_context,
787 struct js_node_st *result_return,
788 struct js_node_st *args);
789
790 /*
791 * Function to call method <method> from the object. Function must return
792 * JS_PROPERTY_FOUND if the method was found or JS_PROPERTY_UNKNOWN
793 * otherwise.
794 */
795 typedef int (*JSBuiltinMethod) (struct js_vm_st *vm,
796 struct js_builtin_info_st *builtin_info,
797 void *instance_context,
798 JSSymbol method,
799 struct js_node_st *result_return,
800 struct js_node_st *args);
801
802 /*
803 * Function to load and set property <property> of object. If <set>
804 * is true, property <property> should be set to value <node>. Otherwise
805 * function should return the value of property <property> in <node>.
806 * Function must return JS_PROPERTY_FOUND if the property was found or
807 * JS_PROPERTY_UNKNOWN otherwise.
808 */
809 typedef int (*JSBuiltinProperty) (struct js_vm_st *vm,
810 struct js_builtin_info_st *builtin_info,
811 void *instance_context,
812 JSSymbol property, int set,
813 struct js_node_st *node);
814
815 typedef void (*JSBuiltinNew) (struct js_vm_st *vm,
816 struct js_builtin_info_st *builtin_info,
817 struct js_node_st *args,
818 struct js_node_st *result_return);
819
820 typedef void (*JSBuiltinDelete) (struct js_builtin_info_st *builtin_info,
821 void *instance_context);
822
823 typedef void (*JSBuiltinMark) (struct js_builtin_info_st *builtin_info,
824 void *instance_context);
825
826 typedef void (*JSBuiltinObjectCtxDelete) (void *obj_context);
827
828 struct js_builtin_info_st
829 {
830 JSHeapDestroyableCB destroy;
831
832 JSBuiltinGlobalMethod global_method_proc;
833 JSBuiltinMethod method_proc;
834 JSBuiltinProperty property_proc;
835 JSBuiltinNew new_proc;
836 JSBuiltinDelete delete_proc;
837 JSBuiltinMark mark_proc;
838
839 void *obj_context;
840 JSBuiltinObjectCtxDelete obj_context_delete;
841
842 struct js_object_st *prototype;
843 };
844
845 typedef struct js_builtin_info_st JSBuiltinInfo;
846
847 /* Builtin object / class. */
848 struct js_builtin_st
849 {
850 JSHeapDestroyableCB destroy;
851
852 JSBuiltinInfo *info;
853 void *instance_context;
854
855 struct js_object_st *prototype;
856 };
857
858 typedef struct js_builtin_st JSBuiltin;
859
860 /* String. */
861 struct js_string_st
862 {
863 /* Flags. */
864 unsigned int staticp : 1;
865
866 unsigned char *data;
867 unsigned int len;
868
869 struct js_object_st *prototype;
870 };
871
872 typedef struct js_string_st JSString;
873
874 /* Array. */
875 struct js_array_st
876 {
877 unsigned int length;
878 struct js_node_st *data;
879
880 struct js_object_st *prototype;
881 };
882
883 typedef struct js_array_st JSArray;
884
885 /* Function. */
886 struct js_function_st
887 {
888 void *implementation;
889 struct js_object_st *prototype;
890 };
891
892 typedef struct js_function_st JSFunction;
893
894 /* Node. */
895 struct js_node_st
896 {
897 JSNodeType type;
898
899 union
900 {
901 unsigned int vboolean;
902
903 JSString *vstring;
904
905 long vinteger;
906 double vfloat;
907
908 struct js_object_st *vobject;
909
910 JSArray *varray;
911
912 /* Internal values. */
913
914 JSSymbol vsymbol;
915
916 JSBuiltin *vbuiltin;
917
918 JSFunction *vfunction;
919
920 void *iptr;
921
922 struct
923 {
924 JSUInt32 argc;
925 JSUInt32 delta;
926 } args_fix;
927
928 struct
929 {
930 JSUInt32 a;
931 JSUInt32 b;
932 } copy;
933 } u;
934 };
935
936 typedef struct js_node_st JSNode;
937
938
939 /* Object. */
940
941 /* Hash node for object's properties. */
942 struct js_object_prop_hash_bucket_st
943 {
944 struct js_object_prop_hash_bucket_st *next;
945 unsigned char *data;
946 unsigned int len;
947 unsigned int value;
948 };
949
950 typedef struct js_object_prop_hash_bucket_st JSObjectPropHashBucket;
951
952 /* The attribute flags for object's properties. */
953 #define JS_ATTRIB_READONLY 1
954 #define JS_ATTRIB_DONTENUM 2
955 #define JS_ATTRIB_DONTDELETE 4
956 #define JS_ATTRIB_Internal 8
957
958 /* Object's property. */
959 struct js_property_st
960 {
961 JSSymbol name;
962 JSNode value;
963 unsigned int attributes;
964 };
965
966 typedef struct js_property_st JSProperty;
967
968 struct js_object_st
969 {
970 JSObjectPropHashBucket **hash;
971 unsigned int *hash_lengths;
972 unsigned int num_props; /* Number of properties in this object. */
973 JSProperty *props;
974 };
975
976 typedef struct js_object_st JSObject;
977
978
979 /* Byte code. */
980
981 typedef enum
982 {
983 JS_BCST_CODE = 0,
984 JS_BCST_CONSTANTS = 1,
985 JS_BCST_SYMTAB = 2,
986 JS_BCST_DEBUG = 3
987 } JSBCSectionType;
988
989 struct js_bc_sect_st
990 {
991 JSBCSectionType type;
992 unsigned int length;
993 void *data; /* <length> bytes of data */
994 };
995
996 typedef struct js_bc_sect_st JSBCSect;
997
998 struct js_bc_st
999 {
1000 unsigned int num_sects;
1001 JSBCSect *sects;
1002 };
1003
1004 typedef struct js_bc_st JSByteCode;
1005
1006 /* Debug information. */
1007 #define JS_DI_FILENAME 1
1008 #define JS_DI_LINENUMBER 2
1009
1010 /* Heap block. */
1011 struct js_heap_block_st
1012 {
1013 struct js_heap_block_st *next;
1014 unsigned int size;
1015 /* <size> bytes of data follows the structure. */
1016 };
1017
1018 typedef struct js_heap_block_st JSHeapBlock;
1019
1020 /* Heap memory block. */
1021
1022 #define JS_MEM_DEBUG 0
1023
1024 /* All allocated blocks have this header. */
1025 struct js_heap_memory_block_st
1026 {
1027 #if JS_MEM_DEBUG
1028 JSUIntAlign magic;
1029 #endif
1030
1031 JSUIntAlign flag_mark : 1;
1032 JSUIntAlign flag_destroyable : 1;
1033 JSUIntAlign size : (sizeof (JSUIntAlign) * 8 - 2);
1034 /* <size> bytes of data follows this header. */
1035 };
1036
1037 typedef struct js_heap_memory_block_st JSHeapMemoryBlock;
1038
1039 /*
1040 * When the block is on the freelist, it has this header. The first
1041 * sizeof (void *) bytes of the block's data is used to hold the
1042 * freelist next pointer.
1043 */
1044 struct js_heap_freelist_block_st
1045 {
1046 JSHeapMemoryBlock block;
1047 JSHeapMemoryBlock *next;
1048 };
1049
1050 typedef struct js_heap_freelist_block_st JSHeapFreelistBlock;
1051
1052
1053 /* Parsed symbol table entry. */
1054 struct js_symtab_entry_st
1055 {
1056 char *name;
1057 unsigned int offset;
1058 };
1059
1060 typedef struct js_symtab_entry_st JSSymtabEntry;
1061
1062
1063 /*
1064 * Entry points to different byte-code instruction dispatcher functions.
1065 * Each dispatcher must implement these.
1066 */
1067
1068 typedef int (*JSVMExecute) (struct js_vm_st *vm, JSByteCode *bc,
1069 JSSymtabEntry *symtab,
1070 unsigned int num_symtab_entries,
1071 unsigned int consts_offset,
1072 unsigned int anonymous_function_offset,
1073 unsigned char *debug_info,
1074 unsigned int debug_info_len,
1075 JSNode *object, JSNode *func,
1076 unsigned int argc, JSNode *argv);
1077
1078 typedef const char *(*JSVMFuncName) (struct js_vm_st *vm, void *pc);
1079
1080 typedef const char *(*JSVMDebugPosition) (struct js_vm_st *vm,
1081 unsigned int *linenum_return);
1082
1083
1084 /* Virtual Machine. */
1085
1086 #define JS_HASH_TABLE_SIZE 256
1087
1088 struct js_hash_bucket_st
1089 {
1090 struct js_hash_bucket_st *next;
1091 char *name;
1092 union
1093 {
1094 void *data;
1095 unsigned int ui;
1096 } u;
1097 };
1098
1099 typedef struct js_hash_bucket_st JSHashBucket;
1100
1101 /* Error handler frame. */
1102 struct js_error_handler_frame_st
1103 {
1104 struct js_error_handler_frame_st *next;
1105 jmp_buf error_jmp;
1106
1107 /* The value thrown by the throw operand. */
1108 JSNode thrown;
1109
1110 /* Saved state for the `try_push' operand. */
1111 JSNode *sp;
1112 JSNode *fp;
1113 void *pc;
1114 JSInt32 pc_delta;
1115 };
1116
1117 typedef struct js_error_handler_frame_st JSErrorHandlerFrame;
1118
1119 struct js_vm_st
1120 {
1121 /* Options for the virtual machine. */
1122 unsigned int verbose; /* verbosity has different levels. */
1123
1124 unsigned int stacktrace_on_error : 1;
1125 unsigned int verbose_stacktrace : 1;
1126 unsigned int warn_undef : 1;
1127
1128 /* Security flags. */
1129 unsigned long security;
1130
1131 /* The default system streams. */
1132 JSIOStream *s_stdin;
1133 JSIOStream *s_stdout;
1134 JSIOStream *s_stderr;
1135
1136 /* The byte-code instruction dispatcher. */
1137 JSVMDispatchMethod dispatch_method;
1138 const char *dispatch_method_name;
1139 JSVMExecute dispatch_execute;
1140 JSVMFuncName dispatch_func_name;
1141 JSVMDebugPosition dispatch_debug_position;
1142
1143 /* Constants pool. */
1144 JSNode *consts;
1145 unsigned int num_consts;
1146 unsigned int consts_alloc;
1147
1148 /*
1149 * Global symbols (both functions and variables). <globals_hash> is
1150 * a name-to-index mapping between symbol names and their positions
1151 * in <globals>.
1152 */
1153 JSHashBucket *globals_hash[JS_HASH_TABLE_SIZE];
1154 JSNode *globals;
1155 unsigned int num_globals;
1156 unsigned int globals_alloc;
1157
1158 /* The next anonymous function id. */
1159 unsigned int anonymous_function_next_id;
1160
1161 /* Stack. */
1162 JSNode *stack;
1163 unsigned int stack_size;
1164 JSNode *sp; /* Fuzzy stack pointer. */
1165
1166 void *pc; /* Fuzzy program counter. */
1167
1168 /* Builtin objects for the primitive datatypes. */
1169 JSBuiltinInfo *prim[JS_IPTR + 1];
1170
1171 /* Some commonly used symbols. */
1172 struct
1173 {
1174 JSSymbol s___proto__;
1175 JSSymbol s_prototype;
1176 JSSymbol s_toSource;
1177 JSSymbol s_toString;
1178 JSSymbol s_valueOf;
1179 } syms;
1180
1181 /* Heap. */
1182
1183 JSHeapBlock *heap;
1184 JSHeapMemoryBlock *heap_freelists[JS_NUM_HEAP_FREELISTS];
1185 unsigned long heap_size;
1186
1187 /* Information for the garbage collector. */
1188 struct
1189 {
1190 unsigned long trigger;
1191 unsigned long bytes_allocated;
1192 unsigned long bytes_free;
1193 unsigned long count;
1194 } gc;
1195
1196 /* Error handler frames. */
1197 JSErrorHandlerFrame *error_handler;
1198
1199 /* Buffer for the error message. Sorry, we don't support long errors ;-) */
1200 char error[1024];
1201
1202 /*
1203 * The result from the latest evaluation. This is set when the
1204 * js_vm_execute(), js_vm_apply(), or js_vm_call_method() functions
1205 * return to the caller.
1206 */
1207 JSNode exec_result;
1208
1209 /* Event callback hook. */
1210 int (*hook) (int event, void *context);
1211 void *hook_context;
1212 unsigned int hook_operand_count;
1213 unsigned int hook_operand_count_trigger;
1214
1215 /* How many file descriptors can be allocated. */
1216 unsigned long fd_count;
1217
1218 #if PROFILING
1219
1220 /* Byte-code operand profiling support. */
1221
1222 unsigned int prof_count[256];
1223 unsigned char prof_op;
1224
1225 #endif /* PROFILING */
1226 };
1227
1228 typedef struct js_vm_st JSVirtualMachine;
1229
1230 #include "kjs_structs.h"
1231
1232 /*
1233 * Global variables.
1234 */
1235
1236 extern unsigned char js_latin1_tolower[256];
1237 extern unsigned char js_latin1_toupper[256];
1238
1239 /*
1240 * Prototypes for global functions.
1241 */
1242
1243 /*
1244 * Memory allocation routines. If the allocation request fails, the
1245 * error recovery is performed according to the argument <vm>. If
1246 * <vm> is not NULL, an error message is formatted to vm->error and an
1247 * error is raise with js_vm_error(). If the <vm> is NULL, the
1248 * functions will return value NULL. It is an error to call these
1249 * functions with a non-NULL <vm> that has no error handler
1250 * initialized.
1251 */
1252
1253 #ifndef JS_DEBUG_MEMORY_LEAKS
1254 #define JS_DEBUG_MEMORY_LEAKS 0
1255 #endif /* not JS_DEBUG_MEMORY_LEAKS */
1256
1257 #if JS_DEBUG_MEMORY_LEAKS
1258
1259 #define js_malloc(vm, size) js_malloc_i ((vm), (size), \
1260 __FILE__, __LINE__)
1261 #define js_calloc(vm, num, size) js_calloc_i ((vm), (num), (size), \
1262 __FILE__, __LINE__)
1263 #define js_realloc(vm, ptr, size) js_realloc_i ((vm), (ptr), (size), \
1264 __FILE__, __LINE__)
1265 #define js_strdup(vm, str) js_strdup_i ((vm), (str), \
1266 __FILE__, __LINE__)
1267
1268 void *js_malloc_i (JSVirtualMachine *vm, size_t size, char *, int);
1269 void *js_calloc_i (JSVirtualMachine *vm, size_t num, size_t size, char *, int);
1270 void *js_realloc_i (JSVirtualMachine *vm, void *ptr, size_t size, char *, int);
1271 void js_free (void *ptr);
1272 char *js_strdup_i (JSVirtualMachine *vm, const char *str, char *, int);
1273
1274 #else /* not JS_DEBUG_MEMORY_LEAKS */
1275
1276 void *js_malloc (JSVirtualMachine *vm, size_t size);
1277 void *js_calloc (JSVirtualMachine *vm, size_t num, size_t size);
1278 void *js_realloc (JSVirtualMachine *vm, void *ptr, size_t size);
1279 void js_free (void *ptr);
1280 char *js_strdup (JSVirtualMachine *vm, const char *str);
1281
1282 #endif /* not JS_DEBUG_MEMORY_LEAKS */
1283
1284
1285 /* Byte code. */
1286
1287 JSByteCode *js_bc_read_file (FILE *fp);
1288
1289 JSByteCode *js_bc_read_data (unsigned char *data, unsigned int datalen);
1290
1291 void js_bc_free (JSByteCode *bc);
1292
1293
1294 /* I/O streams. */
1295
1296 /* Allocate one I/O stream handle. */
1297 JSIOStream *js_iostream_new ();
1298
1299 JSIOStream *js_iostream_file (FILE *fp, int readp, int writep, int do_close);
1300
1301 JSIOStream *js_iostream_pipe (FILE *fp, int readp);
1302
1303 size_t js_iostream_read (JSIOStream *stream, void *ptr, size_t size);
1304
1305 size_t js_iostream_write (JSIOStream *stream, void *ptr, size_t size);
1306
1307 int js_iostream_flush (JSIOStream *stream);
1308
1309 int js_iostream_unget (JSIOStream *stream, int byte);
1310
1311 int js_iostream_close (JSIOStream *stream);
1312
1313 int js_iostream_seek (JSIOStream *stream, long offset, int whence);
1314
1315 long js_iostream_get_position (JSIOStream *stream);
1316
1317 long js_iostream_get_length (JSIOStream *stream);
1318
1319 void js_iostream_fill_buffer (JSIOStream *stream);
1320
1321
1322 /* Virtual machine. */
1323
1324 struct _KJS;
1325
1326 JSVirtualMachine *js_vm_create (struct _KJS *kjs,
1327 unsigned int stack_size,
1328 JSVMDispatchMethod dispatch_method,
1329 unsigned int verbose, int stacktrace_on_error,
1330 JSIOStream *s_stdin, JSIOStream *s_stdout,
1331 JSIOStream *s_stderr);
1332
1333 void js_vm_destroy (JSVirtualMachine *vm);
1334
1335 /*
1336 * Execute byte code <bc>. Function returns 1 if the operation was
1337 * successful or 0 if any errors were encountered. In case of errors,
1338 * the error message is stored at vm->error.
1339 */
1340 int js_vm_execute (JSVirtualMachine *vm, JSByteCode *bc);
1341
1342 /*
1343 * Apply function <func_name> to arguments <argc, argv>. If
1344 * function's name <func_name> is NULL, then <func> must specify function
1345 * to which arguments are applied.
1346 */
1347 int js_vm_apply (JSVirtualMachine *vm, char *func_name, JSNode *func,
1348 unsigned int argc, JSNode *argv);
1349
1350 /*
1351 * Call method <method_name> from object <objet> with arguments <argc, argv>.
1352 */
1353 int js_vm_call_method (JSVirtualMachine *vm, JSNode *object,
1354 const char *method_name, unsigned int argc,
1355 JSNode *argv);
1356
1357 /* Map program counter to the source file line. */
1358 const char *js_vm_debug_position (JSVirtualMachine *vm,
1359 unsigned int *linenum_return);
1360
1361 /* Fetch the function name from the program counter value. */
1362 const char *js_vm_func_name (JSVirtualMachine *vm, void *pc);
1363
1364 /* Intern symbol <name, len> to virtual machine and return its JSSymbol id. */
1365 JSSymbol js_vm_intern_with_len (JSVirtualMachine *vm, const char *name,
1366 unsigned int len);
1367
1368 /* Intern symbol <name> to virtual machine and return its JSSymbol id. */
1369 static __inline JSSymbol
1370 js_vm_intern (JSVirtualMachine *vm, const char *name)
1371 {
1372 return js_vm_intern_with_len (vm, name, strlen (name));
1373 }
1374
1375 /* Return the name of symbol <sym>. */
1376 const char *js_vm_symname (JSVirtualMachine *vm, JSSymbol sym);
1377
1378 /*
1379 * ToPrimitive(). Convert node <n> to its primitive value and return
1380 * the result in <result_return>.
1381 */
1382 void js_vm_to_primitive (JSVirtualMachine *vm, const JSNode *n,
1383 JSNode *result_return, JSNodeType preferred_type);
1384
1385 /*
1386 * ToString(). Convert node <n> to its string presentations and
1387 * return the result in <result_return>.
1388 */
1389 void js_vm_to_string (JSVirtualMachine *vm, const JSNode *n,
1390 JSNode *result_return);
1391
1392 /*
1393 * ToNumber(). Convert node <n> to its number presentations and
1394 * return the result in <result_return>.
1395 */
1396 void js_vm_to_number (JSVirtualMachine *vm, const JSNode *n,
1397 JSNode *result_return);
1398
1399 /* ToObject(). Convert node <n> to object according to its type. */
1400 void js_vm_to_object (JSVirtualMachine *vm, const JSNode *n,
1401 JSNode *result_return);
1402
1403 /*
1404 * ToInt32(). Convert node <n> to its signed 32 bit integer
1405 * presentation and return the result.
1406 */
1407 JSInt32 js_vm_to_int32 (JSVirtualMachine *vm, JSNode *n);
1408
1409 /*
1410 * ToBoolean(). Convert node <n> to a boolean value and return the
1411 * result.
1412 */
1413 int js_vm_to_boolean (JSVirtualMachine *vm, JSNode *n);
1414
1415
1416 /*
1417 * Raise an error. The error message must have been saved to vm->error
1418 * before this function is called. The function never returns.
1419 */
1420 void js_vm_error (JSVirtualMachine *vm);
1421
1422 /*
1423 * Count a hash value for <data_len> bytes of data <data>. The resulting
1424 * hash value should be re-mapped to the correct range, for example,
1425 * with the mod operand.
1426 */
1427 static __inline unsigned int
1428 js_count_hash (const char *data, unsigned int data_len)
1429 {
1430 unsigned int val = 0, i;
1431
1432 for (i = 0; i < data_len; i++)
1433 val = (val << 5) ^ (unsigned char) data[i]
1434 ^ (val >> 16) ^ (val >> 7);
1435
1436 return val;
1437 }
1438
1439
1440 /* Prototypes for the different instruction dispatcher implementations. */
1441
1442 #if ALL_DISPATCHERS
1443
1444 int js_vm_switch0_exec (JSVirtualMachine *vm, JSByteCode *bc,
1445 JSSymtabEntry *symtab,
1446 unsigned int num_symtab_entries,
1447 unsigned int consts_offset,
1448 unsigned int anonymous_function_offset,
1449 unsigned char *debug_info,
1450 unsigned int debug_info_len,
1451 JSNode *object, JSNode *func,
1452 unsigned int argc, JSNode *argv);
1453
1454 const char *js_vm_switch0_func_name (JSVirtualMachine *vm, void *pc);
1455
1456 const char *js_vm_switch0_debug_position (JSVirtualMachine *vm,
1457 unsigned int *linenum_return);
1458
1459 #endif /* ALL_DISPATCHERS */
1460
1461 int js_vm_switch_exec (JSVirtualMachine *vm, JSByteCode *bc,
1462 JSSymtabEntry *symtab,
1463 unsigned int num_symtab_entries,
1464 unsigned int consts_offset,
1465 unsigned int anonymous_function_offset,
1466 unsigned char *debug_info, unsigned int debug_info_len,
1467 JSNode *object, JSNode *func,
1468 unsigned int argc, JSNode *argv);
1469
1470 const char *js_vm_switch_func_name (JSVirtualMachine *vm, void *pc);
1471
1472 const char *js_vm_switch_debug_position (JSVirtualMachine *vm,
1473 unsigned int *linenum_return);
1474
1475 int js_vm_jumps_exec (JSVirtualMachine *vm, JSByteCode *bc,
1476 JSSymtabEntry *symtab,
1477 unsigned int num_symtab_entries,
1478 unsigned int consts_offset,
1479 unsigned int anonymous_function_offset,
1480 unsigned char *debug_info, unsigned int debug_info_len,
1481 JSNode *object, JSNode *func,
1482 unsigned int argc, JSNode *argv);
1483
1484 const char *js_vm_jumps_func_name (JSVirtualMachine *vm, void *pc);
1485
1486 const char *js_vm_jumps_debug_position (JSVirtualMachine *vm,
1487 unsigned int *linenum_return);
1488
1489
1490 /* Heap. */
1491
1492 void *js_vm_alloc (JSVirtualMachine *vm, unsigned int size);
1493
1494 void *js_vm_alloc_destroyable (JSVirtualMachine *vm, unsigned int size);
1495
1496 void *js_vm_realloc (JSVirtualMachine *vm, void *ptr, unsigned int new_size);
1497
1498 void js_vm_free (JSVirtualMachine *vm, void *ptr);
1499
1500 void js_vm_garbage_collect (JSVirtualMachine *vm, JSNode *fp, JSNode *sp);
1501
1502 void js_vm_clear_heap (JSVirtualMachine *vm);
1503
1504 void js_vm_mark (JSNode *node);
1505
1506 int js_vm_mark_ptr (void *ptr);
1507
1508 int js_vm_is_marked_ptr (void *ptr);
1509
1510 /* Function. */
1511
1512 static __inline JSFunction *
1513 js_vm_make_function (JSVirtualMachine *vm, void *implementation)
1514 {
1515 JSFunction *f = (JSFunction *) js_vm_alloc (vm, sizeof (*f));
1516
1517 f->implementation = implementation;
1518 f->prototype = (JSObject *) NULL;
1519
1520 return f;
1521 }
1522
1523
1524 /* Built-in. */
1525
1526 /* Create a new built-in info. */
1527 JSBuiltinInfo *js_vm_builtin_info_create (JSVirtualMachine *vm);
1528
1529 /* Create a new builtin object with <info, instance_context> to <result>. */
1530 void js_vm_builtin_create (JSVirtualMachine *vm, JSNode *result,
1531 JSBuiltinInfo *info, void *instance_context);
1532
1533 /* Array. */
1534
1535 static __inline void
1536 js_vm_make_array (JSVirtualMachine *vm, JSNode *n, unsigned int length)
1537 {
1538 unsigned int i;
1539
1540 n->type = JS_ARRAY;
1541 n->u.varray = (JSArray *) js_vm_alloc (vm, sizeof (*n->u.varray));
1542 n->u.varray->prototype = NULL;
1543 n->u.varray->length = length;
1544 n->u.varray->data = (JSNode *) js_vm_alloc (vm, length * sizeof (JSNode));
1545
1546 for (i = 0; i < length; i++)
1547 n->u.varray->data[i].type = JS_UNDEFINED;
1548 }
1549
1550 static __inline void
1551 js_vm_expand_array (JSVirtualMachine *vm, JSNode *n, unsigned int length)
1552 {
1553 if (n->u.varray->length < length)
1554 {
1555 n->u.varray->data = (JSNode *) js_vm_realloc (vm, n->u.varray->data,
1556 length * sizeof (JSNode));
1557 for (; n->u.varray->length < length; n->u.varray->length++)
1558 n->u.varray->data[n->u.varray->length].type = JS_UNDEFINED;
1559 }
1560 }
1561
1562 /* File. */
1563
1564 /* Enter file <fp> to the system. */
1565 void js_builtin_File_new (JSVirtualMachine *vm, JSNode *result_return,
1566 char *path, JSIOStream *stream, int dont_close);
1567
1568 /* RegExp. */
1569
1570 /*
1571 * Create a new regular expression node from <source, sourcelen> according
1572 * to <flags>. The argument <immutable> defines whether the created
1573 * regexp is immutable. The new regexp is returned in <result_return>.
1574 * If the <info> is NULL, the function will resolve it. Otherwise the given
1575 * value is used.
1576 */
1577 void js_builtin_RegExp_new (JSVirtualMachine *vm, char *source,
1578 unsigned int source_len, unsigned int flags,
1579 int immutable, JSBuiltinInfo *info,
1580 JSNode *result_return);
1581
1582 /*
1583 * Do search-replace for the string <data, datalen> by replacing
1584 * matches of <regexp> with <repl, repl_len>. The resulting string is
1585 * returned in <result_return>
1586 */
1587 void js_builtin_RegExp_replace (JSVirtualMachine *vm, char *data,
1588 unsigned int datalen, JSNode *regexp,
1589 char *repl, unsigned int repl_len,
1590 JSNode *result_return);
1591
1592 /*
1593 * Do regexp match against <data, datalen>. Format the result array
1594 * to <result_return>.
1595 */
1596 void js_builtin_RegExp_match (JSVirtualMachine *vm, char *data,
1597 unsigned int datalen, JSNode *regexp,
1598 JSNode *result_return);
1599
1600 /*
1601 * Do regexp search against <data, datalen>. Return the start index of
1602 * the match in <result_return>.
1603 */
1604 void js_builtin_RegExp_search (JSVirtualMachine *vm, char *data,
1605 unsigned int datalen, JSNode *regexp,
1606 JSNode *result_return);
1607
1608 /*
1609 * Split the string <data, datalen> by regular expression <regexp>.
1610 * Function returns an array containing the substrings.
1611 */
1612 void js_builtin_RegExp_split (JSVirtualMachine *vm, char *data,
1613 unsigned int datalen, JSNode *regexp,
1614 unsigned int limit, JSNode *result_return);
1615
1616 /* Object. */
1617
1618 JSObject *js_vm_object_new (JSVirtualMachine *vm);
1619
1620 void js_vm_object_mark (JSObject *obj);
1621
1622 int js_vm_object_load_property (JSVirtualMachine *vm, JSObject *obj,
1623 JSSymbol prop, JSNode *value_return);
1624
1625 void js_vm_object_store_property (JSVirtualMachine *vm, JSObject *obj,
1626 JSSymbol prop, JSNode *value);
1627
1628 void js_vm_object_delete_property (JSVirtualMachine *vm, JSObject *obj,
1629 JSSymbol prop);
1630
1631 void js_vm_object_load_array (JSVirtualMachine *vm, JSObject *obj, JSNode *sel,
1632 JSNode *value_return);
1633
1634 void js_vm_object_store_array (JSVirtualMachine *vm, JSObject *obj,
1635 JSNode *sel, JSNode *value);
1636
1637 void js_vm_object_delete_array (JSVirtualMachine *vm, JSObject *obj,
1638 JSNode *sel);
1639
1640 int js_vm_object_nth (JSVirtualMachine *vm, JSObject *obj, int nth,
1641 JSNode *value_return);
1642
1643
1644 /* Debug. */
1645
1646 void js_vm_stacktrace (JSVirtualMachine *vm, unsigned int num_frames);
1647
1648
1649 /* Strings. */
1650
1651 static __inline void
1652 js_vm_make_string (JSVirtualMachine *vm, JSNode *n, const char *data,
1653 unsigned int data_len)
1654 {
1655 n->type = JS_STRING;
1656 n->u.vstring = (JSString *) js_vm_alloc (vm, sizeof (*n->u.vstring));
1657 n->u.vstring->staticp = 0;
1658 n->u.vstring->prototype = NULL;
1659 n->u.vstring->len = data_len;
1660 n->u.vstring->data = (unsigned char *) js_vm_alloc (vm, data_len);
1661 if (data)
1662 memcpy (n->u.vstring->data, data, data_len);
1663
1664 }
1665
1666
1667 static __inline void
1668 js_vm_make_static_string (JSVirtualMachine *vm, JSNode *n, const char *data,
1669 unsigned int data_len)
1670 {
1671 n->type = JS_STRING;
1672 n->u.vstring = (JSString *) js_vm_alloc (vm, sizeof (*n->u.vstring));
1673 n->u.vstring->staticp = 1;
1674 n->u.vstring->prototype = NULL;
1675 n->u.vstring->len = data_len;
1676 n->u.vstring->data = (unsigned char *) data;
1677 }
1678
1679
1680 static __inline int
1681 js_compare_strings (JSNode *a, JSNode *b)
1682 {
1683 unsigned int i;
1684
1685 for (i = 0; i < a->u.vstring->len && i < b->u.vstring->len; i++)
1686 {
1687 if (a->u.vstring->data[i] < b->u.vstring->data[i])
1688 return -1;
1689 if (a->u.vstring->data[i] > b->u.vstring->data[i])
1690 return 1;
1691 }
1692 if (a->u.vstring->len < b->u.vstring->len)
1693 return -1;
1694 if (a->u.vstring->len > b->u.vstring->len)
1695 return 1;
1696
1697 return 0;
1698 }
1699
1700
1701 static __inline char *
1702 js_string_to_c_string (JSVirtualMachine *vm, const JSNode *a)
1703 {
1704 char *cp;
1705
1706 cp = (char *) js_malloc (vm, a->u.vstring->len + 1);
1707 memcpy (cp, a->u.vstring->data, a->u.vstring->len);
1708 cp[a->u.vstring->len] = '\0';
1709
1710 return cp;
1711 }
1712
1713
1714 /* Dynamic loading. */
1715
1716 /*
1717 * Try to open shared library <filename>. If the opening was
1718 * successful, a handle to the library is returned. Otherwise, the
1719 * function returns NULL, and an error message is returned in
1720 * <error_return>. The argument <error_return_len> specifies the
1721 * maximum length of the error message the function should return.
1722 */
1723 void *js_dl_open (const char *filename, char *error_return,
1724 unsigned int error_return_len);
1725
1726 /*
1727 * Try to fetch the address of the symbol <symbol> from shared library
1728 * <library>.
1729 */
1730 void *js_dl_sym (void *library, char *symbol, char *error_return,
1731 unsigned int error_return_len);
1732
1733
1734 /* Misc helper functions. */
1735
1736 unsigned long js_crc32 (const unsigned char *s, unsigned int len);
1737
1738 \f
1739 /*
1740 * Definitions for the JavaScript part of the JavaScript interp.
1741 */
1742
1743 /* Flags for the compiler. See `jsc/entry.js'. */
1744
1745 #define JSC_FLAG_VERBOSE 0x00000001
1746 #define JSC_FLAG_ANNOTATE_ASSEMBLER 0x00000002
1747 #define JSC_FLAG_GENERATE_DEBUG_INFO 0x00000004
1748 #define JSC_FLAG_GENERATE_EXECUTABLE_BC_FILES 0x00000008
1749
1750 #define JSC_FLAG_OPTIMIZE_PEEPHOLE 0x00000020
1751 #define JSC_FLAG_OPTIMIZE_JUMPS 0x00000040
1752 #define JSC_FLAG_OPTIMIZE_BC_SIZE 0x00000080
1753 #define JSC_FLAG_OPTIMIZE_HEAVY 0x00000100
1754
1755 #define JSC_FLAG_OPTIMIZE_MASK 0x0000fff0
1756
1757 #define JSC_FLAG_WARN_UNUSED_ARGUMENT 0x00010000
1758 #define JSC_FLAG_WARN_UNUSED_VARIABLE 0x00020000
1759 #define JSC_FLAG_WARN_SHADOW 0x00040000
1760 #define JSC_FLAG_WARN_WITH_CLOBBER 0x00080000
1761 #define JSC_FLAG_WARN_MISSING_SEMICOLON 0x00100000
1762 #define JSC_FLAG_WARN_STRICT_ECMA 0x00200000
1763 #define JSC_FLAG_WARN_DEPRECATED 0x00400000
1764
1765 #define JSC_FLAG_WARN_MASK 0xffff0000
1766
1767 /* JavaScript interpreter handle. */
1768 struct js_interp_st
1769 {
1770 JSInterpOptions options;
1771 JSVirtualMachine *vm;
1772 };
1773
1774 /* Declaration for the JS compiler byte-code. */
1775 extern unsigned char js_compiler_bytecode[];
1776 extern unsigned int js_compiler_bytecode_len;
1777
1778 #ifdef __cplusplus
1779 }
1780 #endif
1781
1782 #endif /* not JSINT_H */