ClamAV is an open source (GPLv2) anti-virus toolkit.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
clamav/libclamav/js/jsint.h

1778 lines
44 KiB

/*
* Internal definitions for the JavaScript interpreter.
* Copyright (c) 1998-1999 New Generation Software (NGS) Oy
*
* Author: Markku Rossi <mtr@ngs.fi>
*/
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA
*/
/*
* $Source: /tmp/cvsroot-15-2-2007/clamav-devel/libclamav/js/jsint.h,v $
* $Id: jsint.h,v 1.4 2006/11/10 20:17:43 njh Exp $
*/
#ifndef JSINT_H
#define JSINT_H
/* We have always jsconfig.h */
#include "jsconfig.h"
#include <stdio.h>
#include <assert.h>
#include <setjmp.h>
#include <math.h>
#include <time.h>
#include <limits.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if STDC_HEADERS
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <float.h>
#else /* not STDC_HEADERS */
#if HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if HAVE_ERRNO_H
#include <errno.h>
#endif
#if HAVE_STRING_H
#include <string.h>
#endif
#if HAVE_FLOAT_H
#include <float.h>
#endif
#endif /* not STDC_HEADERS */
/* Misc system headers. */
#include <sys/types.h>
/*
* Protability kludges. If something is missing from the w32
* environment, please edit the micros/w32.{c,h} files and implement
* them.
*/
#ifndef WIN32
/* Directory handling. */
#include <dirent.h>
#endif /* not WIN32 */
#include "js.h"
#if __cplusplus
extern "C" {
#endif
/*
* Types and definitions.
*/
/* Some portability features. */
#ifdef WIN32
#define JS_HOST_LINE_BREAK "\r\n"
#define JS_HOST_LINE_BREAK_LEN 2
#else /* not WIN32 */
#define JS_HOST_LINE_BREAK "\n"
#define JS_HOST_LINE_BREAK_LEN 1
#endif /* not WIN32 */
#define JS_BC_FILE_MAGIC 0xc0014a53
#define JS_GLOBAL_NAME ".global"
#define JS_SYMBOL_NULL ((JSSymbol) -1)
#define JS_IS_STR_WHITE_SPACE_CHAR(ch) \
((ch) == '\t' || (ch) == ' ' || (ch) == '\f' || (ch) == '\v' \
|| (ch) == '\r' || (ch) == '\n')
/*
* Read macros for byte code files.
*/
#define JS_BC_READ_INT32(cp, var) \
(var) = (cp)[0]; \
(var) <<= 8; \
(var) |= (cp)[1]; \
(var) <<= 8; \
(var) |= (cp)[2]; \
(var) <<= 8; \
(var) |= (cp)[3]
#define JS_BC_READ_INT16(cp, var) \
(var) = (cp)[0]; \
(var) <<= 8; \
(var) |= (cp)[1]
#define JS_BC_READ_INT8(cp, var) \
(var) = (cp)[0]
#define JS_BC_WRITE_INT32(cp, var) \
cp[3] = (unsigned char) ((var) & 0x000000ff); \
cp[2] = (unsigned char) (((var) >> 8) & 0x000000ff); \
cp[1] = (unsigned char) (((var) >> 16) & 0x000000ff); \
cp[0] = (unsigned char) (((var) >> 24) & 0x000000ff)
/* General VM macros. */
/* STACKFRAME */
#define JS_SP0 sp
#define JS_SP1 (sp + 1)
#define JS_SP2 (sp + 2)
#define JS_SP(n) (sp + (n))
#define JS_LOCAL(n) (fp - 4 - (n))
#define JS_ARG(n) (fp + 1 + (n))
#define JS_WITHPTR (fp - 2)
#define JS_ARGS_FIXP (fp - 1)
#define JS_PUSH() sp--
#define JS_POP() sp++
#define JS_POP_N(n) sp += (n)
#define JS_COPY(to, from) \
do { \
(to)->type = (from)->type; \
(to)->u.copy.a = (from)->u.copy.a; \
(to)->u.copy.b = (from)->u.copy.b; \
} while (0)
#define JS_CONST(n) (&vm->consts[(n)])
#define JS_GLOBAL(n) (&vm->globals[(n)])
#define JS_SAVE_REGS() \
do { \
vm->sp = sp; \
vm->pc = pc; \
} while (0)
#define JS_CALL_HOOK(event) \
do { \
int hook_result; \
\
if (vm->hook) \
if ((hook_result = (*vm->hook) ((event), vm->hook_context)) != 0) \
{ \
JS_SAVE_REGS (); \
sprintf (vm->error, "hook break %d", hook_result); \
js_vm_error (vm); \
/* NOTREACHED */ \
} \
} while (0)
#define JS_VM_ALLOCATE_FD(vm, where) \
do { \
if ((vm)->fd_count == 0) \
{ \
sprintf ((vm)->error, "%s: no more file descriptors allowed", \
(where)); \
js_vm_error (vm); \
} \
(vm)->fd_count--; \
} while (0)
#define JS_VM_FREE_FD(vm) \
do { \
(vm)->fd_count++; \
} while (0)
#define JS_MAYBE_GC() \
do { \
if (vm->gc.bytes_allocated >= vm->gc.trigger) \
{ \
js_vm_garbage_collect (vm, fp, sp); \
JS_CALL_HOOK (JS_VM_EVENT_GARBAGE_COLLECT); \
} \
} while (0)
#define JS_IS_TRUE(n) ((n)->type > JS_INTEGER \
|| ((n)->type == JS_BOOLEAN && (n)->u.vboolean) \
|| ((n)->type == JS_INTEGER && (n)->u.vinteger))
#define JS_IS_FALSE(n) ((n)->type < JS_BOOLEAN \
|| ((n)->type == JS_BOOLEAN && !(n)->u.vboolean) \
|| ((n)->type == JS_INTEGER && !(n)->u.vinteger))
#define JS_RESERVE_STACK_FOR_FUNCTION 10
#define JS_SUBROUTINE_CALL(function) \
do { \
/* Check that we have enought space in the stack. */ \
if (sp - JS_RESERVE_STACK_FOR_FUNCTION < vm->stack) \
ERROR ("stack overflow"); \
\
/* STACKFRAME */ \
\
/* Save frame pointer. */ \
JS_SP0->type = JS_IPTR; \
JS_SP0->u.iptr = fp; \
\
/* Update fp. */ \
fp = JS_SP0; \
JS_PUSH (); \
\
/* Insert an empty args_fix. */ \
JS_SP0->type = JS_ARGS_FIX; \
JS_SP0->u.args_fix.argc = 0; \
JS_SP0->u.args_fix.delta = 0; \
JS_PUSH (); \
\
/* Insert empty with pointer. */ \
JS_SP0->type = JS_IPTR; \
JS_SP0->u.iptr = NULL; \
JS_PUSH (); \
\
/* Save return address. */ \
JS_SP0->type = JS_IPTR; \
JS_SP0->u.iptr = pc; \
JS_PUSH (); \
\
/* And finally, jump to the method code. */ \
CALL_USER_FUNC ((function)); \
} while (0)
#define JS_OPERAND_CMP_REL(_OP_) \
do { \
if (JS_SP2->type == JS_STRING && JS_SP1->type == JS_STRING) \
{ \
JS_SP2->u.vboolean \
= js_compare_strings (JS_SP2, JS_SP1) _OP_ 0; \
JS_SP2->type = JS_BOOLEAN; \
JS_POP (); \
} \
else if (JS_SP2->type == JS_INTEGER && JS_SP1->type == JS_INTEGER) \
{ \
JS_SP2->u.vboolean \
= JS_SP2->u.vinteger _OP_ JS_SP1->u.vinteger; \
JS_SP2->type = JS_BOOLEAN; \
JS_POP (); \
} \
else \
{ \
JSNode l, r; \
\
/* Do it the hard way. */ \
switch (JS_SP2->type) \
{ \
case JS_INTEGER: \
case JS_FLOAT: \
case JS_NAN: \
JS_COPY (&l, JS_SP2); \
break; \
\
default: \
js_vm_to_number (vm, JS_SP2, &l); \
break; \
} \
\
switch (JS_SP1->type) \
{ \
case JS_INTEGER: \
case JS_FLOAT: \
case JS_NAN: \
JS_COPY (&r, JS_SP1); \
break; \
\
default: \
js_vm_to_number (vm, JS_SP1, &r); \
break; \
} \
\
/* Do the comparison. */ \
JS_POP (); \
\
if (l.type == JS_NAN || r.type == JS_NAN) \
JS_SP1->type = JS_UNDEFINED; \
else if (l.type == JS_INTEGER && r.type == JS_INTEGER) \
{ \
JS_SP1->type = JS_BOOLEAN; \
JS_SP1->u.vboolean = l.u.vinteger _OP_ r.u.vinteger; \
} \
else \
{ \
double ld, rd; \
\
if (l.type == JS_FLOAT) \
ld = l.u.vfloat; \
else \
ld = (double) l.u.vinteger; \
\
if (r.type == JS_FLOAT) \
rd = r.u.vfloat; \
else \
rd = (double) r.u.vinteger; \
\
JS_SP1->type = JS_BOOLEAN; \
JS_SP1->u.vboolean = ld _OP_ rd; \
} \
} \
} while (0)
#define JS_OPERAND_CMP_EQ(_OP_, _VAL_) \
while (1) { \
int res; \
if (JS_SP2->type == JS_SP1->type) \
{ \
/* Comparsion between same types. */ \
switch (JS_SP2->type) \
{ \
case JS_INTEGER: \
res = JS_SP2->u.vinteger _OP_ JS_SP1->u.vinteger; \
break; \
\
case JS_STRING: \
res = js_compare_strings (JS_SP2, JS_SP1) _OP_ 0; \
break; \
\
case JS_FLOAT: \
res = JS_SP2->u.vfloat _OP_ JS_SP1->u.vfloat; \
break; \
\
case JS_NAN: \
/* 11.9.3: cases 5 and 6 */ \
res = !_VAL_; \
break; \
\
case JS_BOOLEAN: \
res = JS_SP2->u.vboolean _OP_ JS_SP1->u.vboolean; \
break; \
\
case JS_OBJECT: \
res = JS_SP2->u.vobject _OP_ JS_SP1->u.vobject; \
break; \
\
case JS_BUILTIN: \
res = ((JS_SP2->u.vbuiltin->info \
== JS_SP1->u.vbuiltin->info \
&& (JS_SP2->u.vbuiltin->instance_context \
== JS_SP1->u.vbuiltin->instance_context)) \
? _VAL_ : !_VAL_); \
break; \
\
case JS_FUNC: \
res = JS_SP2->u.vfunction _OP_ JS_SP1->u.vfunction; \
break; \
\
case JS_SYMBOL: \
res = JS_SP2->u.vsymbol _OP_ JS_SP1->u.vsymbol; \
break; \
\
case JS_IPTR: \
res = JS_SP2->u.iptr _OP_ JS_SP1->u.iptr; \
break; \
\
default: \
res = _VAL_; \
break; \
} \
} \
else \
{ \
/* Type conversions between different types. */ \
\
if ((JS_SP2->type == JS_UNDEFINED || JS_SP2->type == JS_NULL) \
&& (JS_SP1->type == JS_UNDEFINED \
|| JS_SP1->type == JS_NULL)) \
res = _VAL_; \
\
/* Numbers. */ \
else if (JS_IS_NUMBER (JS_SP2) && JS_IS_NUMBER (JS_SP1)) \
{ \
if (JS_SP2->type == JS_NAN || JS_SP1->type == JS_NAN) \
/* 11.9.3: cases 5 and 6 */ \
res = !_VAL_; \
else if (JS_SP2->type == JS_INTEGER) \
/* Integer-integer was already handled. */ \
res = (double) JS_SP2->u.vinteger _OP_ JS_SP1->u.vfloat; \
else \
/* Integer-integer was already handled. */ \
res = JS_SP2->u.vfloat _OP_ (double) JS_SP1->u.vinteger; \
} \
else \
{ \
JSNode l, r; \
\
/* Must perform type casts. */ \
\
if ((JS_SP2->type == JS_STRING || JS_SP2->type == JS_BOOLEAN \
|| JS_IS_NUMBER (JS_SP2)) \
&& (JS_SP1->type == JS_STRING \
|| JS_SP1->type == JS_BOOLEAN \
|| JS_IS_NUMBER (JS_SP1))) \
{ \
js_vm_to_number (vm, JS_SP2, &l); \
js_vm_to_number (vm, JS_SP1, &r); \
\
if (l.type == JS_NAN || r.type == JS_NAN) \
res = !_VAL_; \
else if (l.type == JS_INTEGER) \
{ \
if (r.type == JS_INTEGER) \
res = l.u.vinteger _OP_ r.u.vinteger; \
else \
res = (double) l.u.vinteger _OP_ r.u.vfloat; \
} \
else \
{ \
if (r.type == JS_INTEGER) \
res = l.u.vfloat _OP_ (double) r.u.vinteger; \
else \
res = l.u.vfloat _OP_ r.u.vfloat; \
} \
} \
else if (JS_SP2->type == JS_OBJECT \
&& (JS_SP1->type == JS_STRING \
|| JS_IS_NUMBER (JS_SP1))) \
{ \
JSNode cvt; \
\
/* ECMA 11.9.3 21. No preferred type specified. */ \
js_vm_to_primitive (vm, JS_SP2, &cvt, JS_UNDEFINED); \
JS_COPY (JS_SP2, &cvt); \
continue; \
} \
else if (JS_SP1->type == JS_OBJECT \
&& (JS_SP2->type == JS_STRING \
|| JS_IS_NUMBER (JS_SP2))) \
{ \
JSNode cvt; \
\
/* ECMA 11.9.3 20. No preferred type specified. */ \
js_vm_to_primitive (vm, JS_SP1, &cvt, JS_UNDEFINED); \
JS_COPY (JS_SP1, &cvt); \
continue; \
} \
else \
res = !_VAL_; \
} \
} \
\
JS_SP2->type = JS_BOOLEAN; \
JS_SP2->u.vboolean = res; \
JS_POP (); \
break; \
}
#define JS_OPERAND_CMP_SEQ(_OP_, _VAL_) \
do { \
int res; \
if (JS_SP2->type == JS_SP1->type) \
{ \
switch (JS_SP2->type) \
{ \
case JS_INTEGER: \
res = JS_SP2->u.vinteger _OP_ JS_SP1->u.vinteger; \
break; \
\
case JS_FLOAT: \
res = JS_SP2->u.vfloat _OP_ JS_SP1->u.vfloat; \
break; \
\
case JS_NAN: \
/* 11.9.6: cases 3 and 4 */ \
res = !_VAL_; \
break; \
\
case JS_STRING: \
res = js_compare_strings (JS_SP2, JS_SP1) _OP_ 0; \
break; \
\
case JS_BOOLEAN: \
res = JS_SP2->u.vboolean _OP_ JS_SP1->u.vboolean; \
break; \
\
case JS_OBJECT: \
res = JS_SP2->u.vobject _OP_ JS_SP1->u.vobject; \
break; \
\
case JS_BUILTIN: \
res = ((JS_SP2->u.vbuiltin->info \
== JS_SP1->u.vbuiltin->info \
&& (JS_SP2->u.vbuiltin->instance_context \
== JS_SP1->u.vbuiltin->instance_context)) \
? _VAL_ : !_VAL_); \
break; \
\
case JS_FUNC: \
res = JS_SP2->u.vfunction _OP_ JS_SP1->u.vfunction; \
break; \
\
default: \
/* 11.9.6: case 12 */ \
res = !_VAL_; \
break; \
} \
} \
else \
{ \
/* Only numbers are allowed here. */ \
if (JS_IS_NUMBER (JS_SP2) && JS_IS_NUMBER (JS_SP1)) \
{ \
if (JS_SP2->type == JS_NAN || JS_SP1->type == JS_NAN) \
/* 11.9.6: cases 3 and 4 */ \
res = !_VAL_; \
else if (JS_SP2->type == JS_INTEGER) \
res = (double) JS_SP2->u.vinteger _OP_ JS_SP1->u.vfloat; \
else \
res = JS_SP2->u.vfloat _OP_ (double) JS_SP1->u.vinteger; \
} \
else \
res = !_VAL_; \
} \
\
JS_SP2->type = JS_BOOLEAN; \
JS_SP2->u.vboolean = res; \
JS_POP (); \
\
} while (0)
#define JS_OPERAND_BINARY(_OP_) \
do { \
if (JS_SP2->type == JS_INTEGER && JS_SP1->type == JS_INTEGER) \
{ \
JS_SP2->u.vinteger = ((JSInt32) JS_SP2->u.vinteger \
_OP_ (JSInt32) JS_SP1->u.vinteger); \
JS_POP (); \
} \
else \
{ \
JSInt32 l, r; \
\
l = js_vm_to_int32 (vm, JS_SP2); \
r = js_vm_to_int32 (vm, JS_SP1); \
\
JS_SP2->u.vinteger = (l _OP_ r); \
JS_SP2->type = JS_INTEGER; \
JS_POP (); \
} \
} while (0)
#define JS_IS_NUMBER(n) \
((n)->type == JS_INTEGER || (n)->type == JS_FLOAT || (n)->type == JS_NAN)
/* Some math macros. */
#define JS_MAKE_POSITIVE_INFINITY(node) \
do { \
(node)->type = JS_FLOAT; \
(node)->u.vfloat = HUGE_VAL; \
} while (0)
#define JS_MAKE_NEGATIVE_INFINITY(node) \
do { \
(node)->type = JS_FLOAT; \
(node)->u.vfloat = -HUGE_VAL; \
} while (0)
#define JS_IS_POSITIVE_INFINITY(node) \
((node)->type == JS_FLOAT && (node)->u.vfloat == HUGE_VAL)
#define JS_IS_NEGATIVE_INFINITY(node) \
((node)->type == JS_FLOAT && (node)->u.vfloat == -HUGE_VAL)
#define JS_IS_FINITE(node) \
(!JS_IS_POSITIVE_INFINITY ((node)) \
&& !JS_IS_NEGATIVE_INFINITY ((node)) \
&& (node)->type != JS_NAN) \
#define JS_IS_PRIMITIVE_VALUE(node) \
((node)->type == JS_UNDEFINED || (node)->type == JS_NULL \
|| (node)->type == JS_BOOLEAN || JS_IS_NUMBER ((node)) \
|| (node)->type == JS_STRING)
/* Macro to clear all flags from a heap memory block. */
#define JS_HEAP_MEMORY_BLOCK_CLEAR_FLAGS(mb) \
do { \
(mb)->flag_mark = 0; \
(mb)->flag_destroyable = 0; \
} while (0)
#define JS_NUM_HEAP_FREELISTS 20
/*
* Virtual machine security flags. When these flags are enabled in
* the vm->security, the appropriate built-in modules don't implement
* insecure methods.
*/
#define JS_VM_SECURE_FILE 0x01
#define JS_VM_SECURE_SYSTEM 0x02
/*
* Noticeable virtual machine events. The `JS_VM_EVENT_OPERAND_COUNT'
* event is generated only if the interpreter was configured with the
* `--enable-operand-hooks' option.
*/
#define JS_VM_EVENT_OPERAND_COUNT 1
#define JS_VM_EVENT_GARBAGE_COLLECT 2
/*
* Integer types.
*/
typedef unsigned char JSUInt8;
typedef signed char JSInt8;
typedef unsigned short JSUInt16;
typedef short JSInt16;
#if SIZEOF_INT == 4
typedef unsigned int JSUInt32;
typedef int JSInt32;
#else /* not SIZEOF_INT == 4 */
#if SIZEOF_LONG == 4
typedef unsigned long JSUInt32;
typedef long JSInt32;
#else /* not SIZEOF_LONG == 4 */
#error "do not know how to define a 32 bit long integer"
#endif /* not SIZEOF_LONG == 4 */
#endif /* not SIZEOF_INT == 4 */
/*
* An unsigned interger number that can be used to align structures to
* correct byte boundaries. On 64 bit machines (Alpha) this should be
* 64 bits long, etc. For now one, we just assume that the mashine is
* a LP64 so the `unsigned long' is a correct type for it.
*/
typedef unsigned long JSUIntAlign;
/* I/O streams. */
/* Buffer filler or flusher function. */
typedef int (*JSIOStreamIOFunc) (void *context, unsigned char *buffer,
unsigned int todo, int *error_return);
typedef int (*JSIOStreamSeek) (void *context, long offset, int whence);
typedef long (*JSIOStreamGetPosition) (void *context);
typedef long (*JSIOStreamGetLength) (void *context);
typedef void (*JSIOStreamClose) (void *context);
/* The I/O stream handle. */
struct js_io_stream_st
{
unsigned char *buffer; /* Must be reallocatable with js_realloc(). */
unsigned int buflen;
unsigned int data_in_buf;
unsigned int bufpos;
/* Flags. */
unsigned int at_eof : 1;
unsigned int autoflush : 1;
unsigned int writep : 1; /* Does the buffer contain write data? */
/* The system error code for the last operation that failed. */
int error;
/* Only one of the read and write is active. */
JSIOStreamIOFunc read;
JSIOStreamIOFunc write;
JSIOStreamSeek seek;
JSIOStreamGetPosition get_position;
JSIOStreamGetLength get_length;
JSIOStreamClose close;
void *context;
};
typedef struct js_io_stream_st JSIOStream;
/* The destroy callback for the destroyable heap blocks. */
typedef void (*JSHeapDestroyableCB) (void *ptr);
/*
* Each destroyable heap block must be castable to this structure e.g.
* the first item in the block must be pointer to the destroy function.
*/
struct js_heap_destroyable_st
{
JSHeapDestroyableCB destroy;
};
typedef struct js_heap_destroyable_st JSHeapDestroyable;
/* Interned symbol. */
typedef unsigned int JSSymbol;
/* JavaScript Types. */
typedef enum
{
JS_UNDEFINED = 0,
JS_NULL = 1,
JS_BOOLEAN = 2,
JS_INTEGER = 3, /* Integer, float and nan are `number' */
JS_STRING = 4,
JS_FLOAT = 5,
JS_ARRAY = 6,
JS_OBJECT = 7,
/*
* The following ones are the internal types, used by this implementation.
*/
JS_SYMBOL = 10,
JS_BUILTIN = 11,
JS_FUNC = 12,
JS_NAN = 13,
JS_IPTR = 14,
JS_ARGS_FIX = 15
} JSNodeType;
struct js_node_st;
struct js_vm_st;
struct js_builtin_info_st;
/* Registry information for builtin objects. */
#define JS_PROPERTY_FOUND 1
#define JS_PROPERTY_UNKNOWN 0
typedef void (*JSBuiltinGlobalMethod) (struct js_vm_st *vm,
struct js_builtin_info_st *builtin_info,
void *instance_context,
struct js_node_st *result_return,
struct js_node_st *args);
/*
* Function to call method <method> from the object. Function must return
* JS_PROPERTY_FOUND if the method was found or JS_PROPERTY_UNKNOWN
* otherwise.
*/
typedef int (*JSBuiltinMethod) (struct js_vm_st *vm,
struct js_builtin_info_st *builtin_info,
void *instance_context,
JSSymbol method,
struct js_node_st *result_return,
struct js_node_st *args);
/*
* Function to load and set property <property> of object. If <set>
* is true, property <property> should be set to value <node>. Otherwise
* function should return the value of property <property> in <node>.
* Function must return JS_PROPERTY_FOUND if the property was found or
* JS_PROPERTY_UNKNOWN otherwise.
*/
typedef int (*JSBuiltinProperty) (struct js_vm_st *vm,
struct js_builtin_info_st *builtin_info,
void *instance_context,
JSSymbol property, int set,
struct js_node_st *node);
typedef void (*JSBuiltinNew) (struct js_vm_st *vm,
struct js_builtin_info_st *builtin_info,
struct js_node_st *args,
struct js_node_st *result_return);
typedef void (*JSBuiltinDelete) (struct js_builtin_info_st *builtin_info,
void *instance_context);
typedef void (*JSBuiltinMark) (struct js_builtin_info_st *builtin_info,
void *instance_context);
typedef void (*JSBuiltinObjectCtxDelete) (void *obj_context);
struct js_builtin_info_st
{
JSHeapDestroyableCB destroy;
JSBuiltinGlobalMethod global_method_proc;
JSBuiltinMethod method_proc;
JSBuiltinProperty property_proc;
JSBuiltinNew new_proc;
JSBuiltinDelete delete_proc;
JSBuiltinMark mark_proc;
void *obj_context;
JSBuiltinObjectCtxDelete obj_context_delete;
struct js_object_st *prototype;
};
typedef struct js_builtin_info_st JSBuiltinInfo;
/* Builtin object / class. */
struct js_builtin_st
{
JSHeapDestroyableCB destroy;
JSBuiltinInfo *info;
void *instance_context;
struct js_object_st *prototype;
};
typedef struct js_builtin_st JSBuiltin;
/* String. */
struct js_string_st
{
/* Flags. */
unsigned int staticp : 1;
unsigned char *data;
unsigned int len;
struct js_object_st *prototype;
};
typedef struct js_string_st JSString;
/* Array. */
struct js_array_st
{
unsigned int length;
struct js_node_st *data;
struct js_object_st *prototype;
};
typedef struct js_array_st JSArray;
/* Function. */
struct js_function_st
{
void *implementation;
struct js_object_st *prototype;
};
typedef struct js_function_st JSFunction;
/* Node. */
struct js_node_st
{
JSNodeType type;
union
{
unsigned int vboolean;
JSString *vstring;
long vinteger;
double vfloat;
struct js_object_st *vobject;
JSArray *varray;
/* Internal values. */
JSSymbol vsymbol;
JSBuiltin *vbuiltin;
JSFunction *vfunction;
void *iptr;
struct
{
JSUInt32 argc;
JSUInt32 delta;
} args_fix;
struct
{
JSUInt32 a;
JSUInt32 b;
} copy;
} u;
};
typedef struct js_node_st JSNode;
/* Object. */
/* Hash node for object's properties. */
struct js_object_prop_hash_bucket_st
{
struct js_object_prop_hash_bucket_st *next;
unsigned char *data;
unsigned int len;
unsigned int value;
};
typedef struct js_object_prop_hash_bucket_st JSObjectPropHashBucket;
/* The attribute flags for object's properties. */
#define JS_ATTRIB_READONLY 1
#define JS_ATTRIB_DONTENUM 2
#define JS_ATTRIB_DONTDELETE 4
#define JS_ATTRIB_Internal 8
/* Object's property. */
struct js_property_st
{
JSSymbol name;
JSNode value;
unsigned int attributes;
};
typedef struct js_property_st JSProperty;
struct js_object_st
{
JSObjectPropHashBucket **hash;
unsigned int *hash_lengths;
unsigned int num_props; /* Number of properties in this object. */
JSProperty *props;
};
typedef struct js_object_st JSObject;
/* Byte code. */
typedef enum
{
JS_BCST_CODE = 0,
JS_BCST_CONSTANTS = 1,
JS_BCST_SYMTAB = 2,
JS_BCST_DEBUG = 3
} JSBCSectionType;
struct js_bc_sect_st
{
JSBCSectionType type;
unsigned int length;
void *data; /* <length> bytes of data */
};
typedef struct js_bc_sect_st JSBCSect;
struct js_bc_st
{
unsigned int num_sects;
JSBCSect *sects;
};
typedef struct js_bc_st JSByteCode;
/* Debug information. */
#define JS_DI_FILENAME 1
#define JS_DI_LINENUMBER 2
/* Heap block. */
struct js_heap_block_st
{
struct js_heap_block_st *next;
unsigned int size;
/* <size> bytes of data follows the structure. */
};
typedef struct js_heap_block_st JSHeapBlock;
/* Heap memory block. */
#define JS_MEM_DEBUG 0
/* All allocated blocks have this header. */
struct js_heap_memory_block_st
{
#if JS_MEM_DEBUG
JSUIntAlign magic;
#endif
JSUIntAlign flag_mark : 1;
JSUIntAlign flag_destroyable : 1;
JSUIntAlign size : (sizeof (JSUIntAlign) * 8 - 2);
/* <size> bytes of data follows this header. */
};
typedef struct js_heap_memory_block_st JSHeapMemoryBlock;
/*
* When the block is on the freelist, it has this header. The first
* sizeof (void *) bytes of the block's data is used to hold the
* freelist next pointer.
*/
struct js_heap_freelist_block_st
{
JSHeapMemoryBlock block;
JSHeapMemoryBlock *next;
};
typedef struct js_heap_freelist_block_st JSHeapFreelistBlock;
/* Parsed symbol table entry. */
struct js_symtab_entry_st
{
char *name;
unsigned int offset;
};
typedef struct js_symtab_entry_st JSSymtabEntry;
/*
* Entry points to different byte-code instruction dispatcher functions.
* Each dispatcher must implement these.
*/
typedef int (*JSVMExecute) (struct js_vm_st *vm, JSByteCode *bc,
JSSymtabEntry *symtab,
unsigned int num_symtab_entries,
unsigned int consts_offset,
unsigned int anonymous_function_offset,
unsigned char *debug_info,
unsigned int debug_info_len,
JSNode *object, JSNode *func,
unsigned int argc, JSNode *argv);
typedef const char *(*JSVMFuncName) (struct js_vm_st *vm, void *pc);
typedef const char *(*JSVMDebugPosition) (struct js_vm_st *vm,
unsigned int *linenum_return);
/* Virtual Machine. */
#define JS_HASH_TABLE_SIZE 256
struct js_hash_bucket_st
{
struct js_hash_bucket_st *next;
char *name;
union
{
void *data;
unsigned int ui;
} u;
};
typedef struct js_hash_bucket_st JSHashBucket;
/* Error handler frame. */
struct js_error_handler_frame_st
{
struct js_error_handler_frame_st *next;
jmp_buf error_jmp;
/* The value thrown by the throw operand. */
JSNode thrown;
/* Saved state for the `try_push' operand. */
JSNode *sp;
JSNode *fp;
void *pc;
JSInt32 pc_delta;
};
typedef struct js_error_handler_frame_st JSErrorHandlerFrame;
struct js_vm_st
{
/* Options for the virtual machine. */
unsigned int verbose; /* verbosity has different levels. */
unsigned int stacktrace_on_error : 1;
unsigned int verbose_stacktrace : 1;
unsigned int warn_undef : 1;
/* Security flags. */
unsigned long security;
/* The default system streams. */
JSIOStream *s_stdin;
JSIOStream *s_stdout;
JSIOStream *s_stderr;
/* The byte-code instruction dispatcher. */
JSVMDispatchMethod dispatch_method;
const char *dispatch_method_name;
JSVMExecute dispatch_execute;
JSVMFuncName dispatch_func_name;
JSVMDebugPosition dispatch_debug_position;
/* Constants pool. */
JSNode *consts;
unsigned int num_consts;
unsigned int consts_alloc;
/*
* Global symbols (both functions and variables). <globals_hash> is
* a name-to-index mapping between symbol names and their positions
* in <globals>.
*/
JSHashBucket *globals_hash[JS_HASH_TABLE_SIZE];
JSNode *globals;
unsigned int num_globals;
unsigned int globals_alloc;
/* The next anonymous function id. */
unsigned int anonymous_function_next_id;
/* Stack. */
JSNode *stack;
unsigned int stack_size;
JSNode *sp; /* Fuzzy stack pointer. */
void *pc; /* Fuzzy program counter. */
/* Builtin objects for the primitive datatypes. */
JSBuiltinInfo *prim[JS_IPTR + 1];
/* Some commonly used symbols. */
struct
{
JSSymbol s___proto__;
JSSymbol s_prototype;
JSSymbol s_toSource;
JSSymbol s_toString;
JSSymbol s_valueOf;
} syms;
/* Heap. */
JSHeapBlock *heap;
JSHeapMemoryBlock *heap_freelists[JS_NUM_HEAP_FREELISTS];
unsigned long heap_size;
/* Information for the garbage collector. */
struct
{
unsigned long trigger;
unsigned long bytes_allocated;
unsigned long bytes_free;
unsigned long count;
} gc;
/* Error handler frames. */
JSErrorHandlerFrame *error_handler;
/* Buffer for the error message. Sorry, we don't support long errors ;-) */
char error[1024];
/*
* The result from the latest evaluation. This is set when the
* js_vm_execute(), js_vm_apply(), or js_vm_call_method() functions
* return to the caller.
*/
JSNode exec_result;
/* Event callback hook. */
int (*hook) (int event, void *context);
void *hook_context;
unsigned int hook_operand_count;
unsigned int hook_operand_count_trigger;
/* How many file descriptors can be allocated. */
unsigned long fd_count;
#if PROFILING
/* Byte-code operand profiling support. */
unsigned int prof_count[256];
unsigned char prof_op;
#endif /* PROFILING */
};
typedef struct js_vm_st JSVirtualMachine;
/*
* Global variables.
*/
extern unsigned char js_latin1_tolower[256];
extern unsigned char js_latin1_toupper[256];
/*
* Prototypes for global functions.
*/
/*
* Memory allocation routines. If the allocation request fails, the
* error recovery is performed according to the argument <vm>. If
* <vm> is not NULL, an error message is formatted to vm->error and an
* error is raise with js_vm_error(). If the <vm> is NULL, the
* functions will return value NULL. It is an error to call these
* functions with a non-NULL <vm> that has no error handler
* initialized.
*/
#ifndef JS_DEBUG_MEMORY_LEAKS
#define JS_DEBUG_MEMORY_LEAKS 0
#endif /* not JS_DEBUG_MEMORY_LEAKS */
#if JS_DEBUG_MEMORY_LEAKS
#define js_malloc(vm, size) js_malloc_i ((vm), (size), \
__FILE__, __LINE__)
#define js_calloc(vm, num, size) js_calloc_i ((vm), (num), (size), \
__FILE__, __LINE__)
#define js_realloc(vm, ptr, size) js_realloc_i ((vm), (ptr), (size), \
__FILE__, __LINE__)
#define js_strdup(vm, str) js_strdup_i ((vm), (str), \
__FILE__, __LINE__)
void *js_malloc_i (JSVirtualMachine *vm, size_t size, char *, int);
void *js_calloc_i (JSVirtualMachine *vm, size_t num, size_t size, char *, int);
void *js_realloc_i (JSVirtualMachine *vm, void *ptr, size_t size, char *, int);
void js_free (void *ptr);
char *js_strdup_i (JSVirtualMachine *vm, const char *str, char *, int);
#else /* not JS_DEBUG_MEMORY_LEAKS */
void *js_malloc (JSVirtualMachine *vm, size_t size);
void *js_calloc (JSVirtualMachine *vm, size_t num, size_t size);
void *js_realloc (JSVirtualMachine *vm, void *ptr, size_t size);
void js_free (void *ptr);
char *js_strdup (JSVirtualMachine *vm, const char *str);
#endif /* not JS_DEBUG_MEMORY_LEAKS */
/* Byte code. */
JSByteCode *js_bc_read_file (FILE *fp);
JSByteCode *js_bc_read_data (unsigned char *data, unsigned int datalen);
void js_bc_free (JSByteCode *bc);
/* I/O streams. */
/* Allocate one I/O stream handle. */
JSIOStream *js_iostream_new ();
JSIOStream *js_iostream_file (FILE *fp, int readp, int writep, int do_close);
JSIOStream *js_iostream_pipe (FILE *fp, int readp);
size_t js_iostream_read (JSIOStream *stream, void *ptr, size_t size);
size_t js_iostream_write (JSIOStream *stream, void *ptr, size_t size);
int js_iostream_flush (JSIOStream *stream);
int js_iostream_unget (JSIOStream *stream, int byte);
int js_iostream_close (JSIOStream *stream);
int js_iostream_seek (JSIOStream *stream, long offset, int whence);
long js_iostream_get_position (JSIOStream *stream);
long js_iostream_get_length (JSIOStream *stream);
void js_iostream_fill_buffer (JSIOStream *stream);
/* Virtual machine. */
JSVirtualMachine *js_vm_create (unsigned int stack_size,
JSVMDispatchMethod dispatch_method,
unsigned int verbose, int stacktrace_on_error,
JSIOStream *s_stdin, JSIOStream *s_stdout,
JSIOStream *s_stderr);
void js_vm_destroy (JSVirtualMachine *vm);
/*
* Execute byte code <bc>. Function returns 1 if the operation was
* successful or 0 if any errors were encountered. In case of errors,
* the error message is stored at vm->error.
*/
int js_vm_execute (JSVirtualMachine *vm, JSByteCode *bc);
/*
* Apply function <func_name> to arguments <argc, argv>. If
* function's name <func_name> is NULL, then <func> must specify function
* to which arguments are applied.
*/
int js_vm_apply (JSVirtualMachine *vm, char *func_name, JSNode *func,
unsigned int argc, JSNode *argv);
/*
* Call method <method_name> from object <objet> with arguments <argc, argv>.
*/
int js_vm_call_method (JSVirtualMachine *vm, JSNode *object,
const char *method_name, unsigned int argc,
JSNode *argv);
/* Map program counter to the source file line. */
const char *js_vm_debug_position (JSVirtualMachine *vm,
unsigned int *linenum_return);
/* Fetch the function name from the program counter value. */
const char *js_vm_func_name (JSVirtualMachine *vm, void *pc);
/* Intern symbol <name, len> to virtual machine and return its JSSymbol id. */
JSSymbol js_vm_intern_with_len (JSVirtualMachine *vm, const char *name,
unsigned int len);
/* Intern symbol <name> to virtual machine and return its JSSymbol id. */
static inline JSSymbol
js_vm_intern (JSVirtualMachine *vm, const char *name)
{
return js_vm_intern_with_len (vm, name, strlen (name));
}
/* Return the name of symbol <sym>. */
const char *js_vm_symname (JSVirtualMachine *vm, JSSymbol sym);
/*
* ToPrimitive(). Convert node <n> to its primitive value and return
* the result in <result_return>.
*/
void js_vm_to_primitive (JSVirtualMachine *vm, const JSNode *n,
JSNode *result_return, JSNodeType preferred_type);
/*
* ToString(). Convert node <n> to its string presentations and
* return the result in <result_return>.
*/
void js_vm_to_string (JSVirtualMachine *vm, const JSNode *n,
JSNode *result_return);
/*
* ToNumber(). Convert node <n> to its number presentations and
* return the result in <result_return>.
*/
void js_vm_to_number (JSVirtualMachine *vm, const JSNode *n,
JSNode *result_return);
/* ToObject(). Convert node <n> to object according to its type. */
void js_vm_to_object (JSVirtualMachine *vm, const JSNode *n,
JSNode *result_return);
/*
* ToInt32(). Convert node <n> to its signed 32 bit integer
* presentation and return the result.
*/
JSInt32 js_vm_to_int32 (JSVirtualMachine *vm, JSNode *n);
/*
* ToBoolean(). Convert node <n> to a boolean value and return the
* result.
*/
int js_vm_to_boolean (JSVirtualMachine *vm, JSNode *n);
/*
* Raise an error. The error message must have been saved to vm->error
* before this function is called. The function never returns.
*/
void js_vm_error (JSVirtualMachine *vm);
/*
* Count a hash value for <data_len> bytes of data <data>. The resulting
* hash value should be re-mapped to the correct range, for example,
* with the mod operand.
*/
static inline unsigned int
js_count_hash (const char *data, unsigned int data_len)
{
unsigned int val = 0, i;
for (i = 0; i < data_len; i++)
val = (val << 5) ^ (unsigned char) data[i]
^ (val >> 16) ^ (val >> 7);
return val;
}
/* Prototypes for the different instruction dispatcher implementations. */
#if ALL_DISPATCHERS
int js_vm_switch0_exec (JSVirtualMachine *vm, JSByteCode *bc,
JSSymtabEntry *symtab,
unsigned int num_symtab_entries,
unsigned int consts_offset,
unsigned int anonymous_function_offset,
unsigned char *debug_info,
unsigned int debug_info_len,
JSNode *object, JSNode *func,
unsigned int argc, JSNode *argv);
const char *js_vm_switch0_func_name (JSVirtualMachine *vm, void *pc);
const char *js_vm_switch0_debug_position (JSVirtualMachine *vm,
unsigned int *linenum_return);
#endif /* ALL_DISPATCHERS */
int js_vm_switch_exec (JSVirtualMachine *vm, JSByteCode *bc,
JSSymtabEntry *symtab,
unsigned int num_symtab_entries,
unsigned int consts_offset,
unsigned int anonymous_function_offset,
unsigned char *debug_info, unsigned int debug_info_len,
JSNode *object, JSNode *func,
unsigned int argc, JSNode *argv);
const char *js_vm_switch_func_name (JSVirtualMachine *vm, void *pc);
const char *js_vm_switch_debug_position (JSVirtualMachine *vm,
unsigned int *linenum_return);
int js_vm_jumps_exec (JSVirtualMachine *vm, JSByteCode *bc,
JSSymtabEntry *symtab,
unsigned int num_symtab_entries,
unsigned int consts_offset,
unsigned int anonymous_function_offset,
unsigned char *debug_info, unsigned int debug_info_len,
JSNode *object, JSNode *func,
unsigned int argc, JSNode *argv);
const char *js_vm_jumps_func_name (JSVirtualMachine *vm, void *pc);
const char *js_vm_jumps_debug_position (JSVirtualMachine *vm,
unsigned int *linenum_return);
/* Heap. */
void *js_vm_alloc (JSVirtualMachine *vm, unsigned int size);
void *js_vm_alloc_destroyable (JSVirtualMachine *vm, unsigned int size);
void *js_vm_realloc (JSVirtualMachine *vm, void *ptr, unsigned int new_size);
void js_vm_free (JSVirtualMachine *vm, void *ptr);
void js_vm_garbage_collect (JSVirtualMachine *vm, JSNode *fp, JSNode *sp);
void js_vm_clear_heap (JSVirtualMachine *vm);
void js_vm_mark (JSNode *node);
int js_vm_mark_ptr (void *ptr);
int js_vm_is_marked_ptr (void *ptr);
/* Function. */
static inline JSFunction *
js_vm_make_function (JSVirtualMachine *vm, void *implementation)
{
JSFunction *f = (JSFunction *) js_vm_alloc (vm, sizeof (*f));
f->implementation = implementation;
f->prototype = (JSObject *) NULL;
return f;
}
/* Built-in. */
/* Create a new built-in info. */
JSBuiltinInfo *js_vm_builtin_info_create (JSVirtualMachine *vm);
/* Create a new builtin object with <info, instance_context> to <result>. */
void js_vm_builtin_create (JSVirtualMachine *vm, JSNode *result,
JSBuiltinInfo *info, void *instance_context);
/* Array. */
static inline void
js_vm_make_array (JSVirtualMachine *vm, JSNode *n, unsigned int length)
{
unsigned int i;
n->type = JS_ARRAY;
n->u.varray = (JSArray *) js_vm_alloc (vm, sizeof (*n->u.varray));
n->u.varray->prototype = NULL;
n->u.varray->length = length;
n->u.varray->data = (JSNode *) js_vm_alloc (vm, length * sizeof (JSNode));
for (i = 0; i < length; i++)
n->u.varray->data[i].type = JS_UNDEFINED;
}
static inline void
js_vm_expand_array (JSVirtualMachine *vm, JSNode *n, unsigned int length)
{
if (n->u.varray->length < length)
{
n->u.varray->data = (JSNode *) js_vm_realloc (vm, n->u.varray->data,
length * sizeof (JSNode));
for (; n->u.varray->length < length; n->u.varray->length++)
n->u.varray->data[n->u.varray->length].type = JS_UNDEFINED;
}
}
/* File. */
/* Enter file <fp> to the system. */
void js_builtin_File_new (JSVirtualMachine *vm, JSNode *result_return,
char *path, JSIOStream *stream, int dont_close);
/* RegExp. */
/*
* Create a new regular expression node from <source, sourcelen> according
* to <flags>. The argument <immutable> defines whether the created
* regexp is immutable. The new regexp is returned in <result_return>.
* If the <info> is NULL, the function will resolve it. Otherwise the given
* value is used.
*/
void js_builtin_RegExp_new (JSVirtualMachine *vm, char *source,
unsigned int source_len, unsigned int flags,
int immutable, JSBuiltinInfo *info,
JSNode *result_return);
/*
* Do search-replace for the string <data, datalen> by replacing
* matches of <regexp> with <repl, repl_len>. The resulting string is
* returned in <result_return>
*/
void js_builtin_RegExp_replace (JSVirtualMachine *vm, char *data,
unsigned int datalen, JSNode *regexp,
char *repl, unsigned int repl_len,
JSNode *result_return);
/*
* Do regexp match against <data, datalen>. Format the result array
* to <result_return>.
*/
void js_builtin_RegExp_match (JSVirtualMachine *vm, char *data,
unsigned int datalen, JSNode *regexp,
JSNode *result_return);
/*
* Do regexp search against <data, datalen>. Return the start index of
* the match in <result_return>.
*/
void js_builtin_RegExp_search (JSVirtualMachine *vm, char *data,
unsigned int datalen, JSNode *regexp,
JSNode *result_return);
/*
* Split the string <data, datalen> by regular expression <regexp>.
* Function returns an array containing the substrings.
*/
void js_builtin_RegExp_split (JSVirtualMachine *vm, char *data,
unsigned int datalen, JSNode *regexp,
unsigned int limit, JSNode *result_return);
/* Object. */
JSObject *js_vm_object_new (JSVirtualMachine *vm);
void js_vm_object_mark (JSObject *obj);
int js_vm_object_load_property (JSVirtualMachine *vm, JSObject *obj,
JSSymbol prop, JSNode *value_return);
void js_vm_object_store_property (JSVirtualMachine *vm, JSObject *obj,
JSSymbol prop, JSNode *value);
void js_vm_object_delete_property (JSVirtualMachine *vm, JSObject *obj,
JSSymbol prop);
void js_vm_object_load_array (JSVirtualMachine *vm, JSObject *obj, JSNode *sel,
JSNode *value_return);
void js_vm_object_store_array (JSVirtualMachine *vm, JSObject *obj,
JSNode *sel, JSNode *value);
void js_vm_object_delete_array (JSVirtualMachine *vm, JSObject *obj,
JSNode *sel);
int js_vm_object_nth (JSVirtualMachine *vm, JSObject *obj, int nth,
JSNode *value_return);
/* Debug. */
void js_vm_stacktrace (JSVirtualMachine *vm, unsigned int num_frames);
/* Strings. */
static inline void
js_vm_make_string (JSVirtualMachine *vm, JSNode *n, const char *data,
unsigned int data_len)
{
n->type = JS_STRING;
n->u.vstring = (JSString *) js_vm_alloc (vm, sizeof (*n->u.vstring));
n->u.vstring->staticp = 0;
n->u.vstring->prototype = NULL;
n->u.vstring->len = data_len;
n->u.vstring->data = (unsigned char *) js_vm_alloc (vm, data_len);
if (data)
memcpy (n->u.vstring->data, data, data_len);
}
static inline void
js_vm_make_static_string (JSVirtualMachine *vm, JSNode *n, const char *data,
unsigned int data_len)
{
n->type = JS_STRING;
n->u.vstring = (JSString *) js_vm_alloc (vm, sizeof (*n->u.vstring));
n->u.vstring->staticp = 1;
n->u.vstring->prototype = NULL;
n->u.vstring->len = data_len;
n->u.vstring->data = (unsigned char *) data;
}
static inline int
js_compare_strings (JSNode *a, JSNode *b)
{
unsigned int i;
for (i = 0; i < a->u.vstring->len && i < b->u.vstring->len; i++)
{
if (a->u.vstring->data[i] < b->u.vstring->data[i])
return -1;
if (a->u.vstring->data[i] > b->u.vstring->data[i])
return 1;
}
if (a->u.vstring->len < b->u.vstring->len)
return -1;
if (a->u.vstring->len > b->u.vstring->len)
return 1;
return 0;
}
static inline char *
js_string_to_c_string (JSVirtualMachine *vm, const JSNode *a)
{
char *cp;
cp = (char *) js_malloc (vm, a->u.vstring->len + 1);
memcpy (cp, a->u.vstring->data, a->u.vstring->len);
cp[a->u.vstring->len] = '\0';
return cp;
}
/* Dynamic loading. */
/*
* Try to open shared library <filename>. If the opening was
* successful, a handle to the library is returned. Otherwise, the
* function returns NULL, and an error message is returned in
* <error_return>. The argument <error_return_len> specifies the
* maximum length of the error message the function should return.
*/
void *js_dl_open (const char *filename, char *error_return,
unsigned int error_return_len);
/*
* Try to fetch the address of the symbol <symbol> from shared library
* <library>.
*/
void *js_dl_sym (void *library, char *symbol, char *error_return,
unsigned int error_return_len);
/* Misc helper functions. */
unsigned long js_crc32 (const unsigned char *s, unsigned int len);
/*
* Definitions for the JavaScript part of the JavaScript interp.
*/
/* Flags for the compiler. See `jsc/entry.js'. */
#define JSC_FLAG_VERBOSE 0x00000001
#define JSC_FLAG_ANNOTATE_ASSEMBLER 0x00000002
#define JSC_FLAG_GENERATE_DEBUG_INFO 0x00000004
#define JSC_FLAG_GENERATE_EXECUTABLE_BC_FILES 0x00000008
#define JSC_FLAG_OPTIMIZE_PEEPHOLE 0x00000020
#define JSC_FLAG_OPTIMIZE_JUMPS 0x00000040
#define JSC_FLAG_OPTIMIZE_BC_SIZE 0x00000080
#define JSC_FLAG_OPTIMIZE_HEAVY 0x00000100
#define JSC_FLAG_OPTIMIZE_MASK 0x0000fff0
#define JSC_FLAG_WARN_UNUSED_ARGUMENT 0x00010000
#define JSC_FLAG_WARN_UNUSED_VARIABLE 0x00020000
#define JSC_FLAG_WARN_SHADOW 0x00040000
#define JSC_FLAG_WARN_WITH_CLOBBER 0x00080000
#define JSC_FLAG_WARN_MISSING_SEMICOLON 0x00100000
#define JSC_FLAG_WARN_STRICT_ECMA 0x00200000
#define JSC_FLAG_WARN_DEPRECATED 0x00400000
#define JSC_FLAG_WARN_MASK 0xffff0000
/* JavaScript interpreter handle. */
struct js_interp_st
{
JSInterpOptions options;
JSVirtualMachine *vm;
};
/* Declaration for the JS compiler byte-code. */
extern const unsigned char js_compiler_bytecode[];
extern unsigned int js_compiler_bytecode_len;
#ifdef __cplusplus
}
#endif
#endif /* not JSINT_H */