📄 js.c
字号:
*/
static int
js_eval_source (JSInterpPtr interp, JSNode *source, char *compiler_function)
{
JSNode argv[5];
int i = 0;
int result;
JSByteCode *bc;
/* Let's compile the code. */
/* Argument count. */
argv[i].type = JS_INTEGER;
argv[i].u.vinteger = 4;
i++;
/* Source to compiler. */
JS_COPY (&argv[i], source);
i++;
/* Flags. */
argv[i].type = JS_INTEGER;
argv[i].u.vinteger = 0;
if (interp->options.verbose)
argv[i].u.vinteger = JSC_FLAG_VERBOSE;
argv[i].u.vinteger |= JSC_FLAG_GENERATE_DEBUG_INFO;
argv[i].u.vinteger |= JSC_FLAG_OPTIMIZE_PEEPHOLE;
argv[i].u.vinteger |= JSC_FLAG_OPTIMIZE_JUMPS;
argv[i].u.vinteger |= JSC_FLAG_WARN_WITH_CLOBBER;
i++;
/* Assembler file. */
argv[i].type = JS_NULL;
i++;
/* Byte-code file. */
argv[i].type = JS_NULL;
i++;
/* Call the compiler entry point. */
result = js_vm_apply (interp->vm, compiler_function, NULL, i, argv);
if (result == 0)
return 0;
/*
* The resulting byte-code file is now at vm->exec_result.
*
* Note! The byte-code is a string allocated form the vm heap.
* The garbage collector can free it when it wants since the result
* isn't protected. However, we have no risk here because we
* first convert the byte-code data block to our internal
* JSByteCode block that shares no memory with the original data.
*/
assert (interp->vm->exec_result.type == JS_STRING);
bc = js_bc_read_data (interp->vm->exec_result.u.vstring->data,
interp->vm->exec_result.u.vstring->len);
/* And finally, execute it. */
result = js_vm_execute (interp->vm, bc);
/* Free the byte-code. */
js_bc_free (bc);
return result;
}
static int
js_compile_source (JSInterpPtr interp, JSNode *source,
char *compiler_function, char *assembler_file,
char *byte_code_file, JSNode *bc_return)
{
JSNode argv[5];
int i = 0;
int result;
/* Init arguments. */
argv[i].type = JS_INTEGER;
argv[i].u.vinteger = 4;
i++;
/* Source to compiler. */
JS_COPY (&argv[1], source);
i++;
/* Flags. */
argv[i].type = JS_INTEGER;
argv[i].u.vinteger = 0;
if (interp->options.verbose)
argv[i].u.vinteger |= JSC_FLAG_VERBOSE;
if (interp->options.annotate_assembler)
argv[i].u.vinteger |= JSC_FLAG_ANNOTATE_ASSEMBLER;
if (interp->options.debug_info)
argv[i].u.vinteger |= JSC_FLAG_GENERATE_DEBUG_INFO;
if (interp->options.executable_bc_files)
argv[i].u.vinteger |= JSC_FLAG_GENERATE_EXECUTABLE_BC_FILES;
if (interp->options.warn_unused_argument)
argv[i].u.vinteger |= JSC_FLAG_WARN_UNUSED_ARGUMENT;
if (interp->options.warn_unused_variable)
argv[i].u.vinteger |= JSC_FLAG_WARN_UNUSED_VARIABLE;
if (interp->options.warn_shadow)
argv[i].u.vinteger |= JSC_FLAG_WARN_SHADOW;
if (interp->options.warn_with_clobber)
argv[i].u.vinteger |= JSC_FLAG_WARN_WITH_CLOBBER;
if (interp->options.warn_missing_semicolon)
argv[i].u.vinteger |= JSC_FLAG_WARN_MISSING_SEMICOLON;
if (interp->options.warn_strict_ecma)
argv[i].u.vinteger |= JSC_FLAG_WARN_STRICT_ECMA;
if (interp->options.warn_deprecated)
argv[i].u.vinteger |= JSC_FLAG_WARN_DEPRECATED;
if (interp->options.optimize_peephole)
argv[i].u.vinteger |= JSC_FLAG_OPTIMIZE_PEEPHOLE;
if (interp->options.optimize_jumps_to_jumps)
argv[i].u.vinteger |= JSC_FLAG_OPTIMIZE_JUMPS;
if (interp->options.optimize_bc_size)
argv[i].u.vinteger |= JSC_FLAG_OPTIMIZE_BC_SIZE;
if (interp->options.optimize_heavy)
argv[i].u.vinteger |= JSC_FLAG_OPTIMIZE_HEAVY;
i++;
/* Assembler file. */
if (assembler_file)
js_vm_make_static_string (interp->vm, &argv[i], assembler_file,
strlen (assembler_file));
else
argv[i].type = JS_NULL;
i++;
/* Byte-code file. */
if (byte_code_file)
js_vm_make_static_string (interp->vm, &argv[i], byte_code_file,
strlen (byte_code_file));
else
argv[i].type = JS_NULL;
i++;
/* Call the compiler entry point. */
result = js_vm_apply (interp->vm, compiler_function, NULL, i, argv);
if (result == 0)
return 0;
if (bc_return)
/* User wanted to get the resulting byte-code data. Here it is. */
JS_COPY (bc_return, &interp->vm->exec_result);
return result;
}
/*
* Global methods.
*/
static void
eval_global_method (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
void *instance_context, JSNode *result_return,
JSNode *args)
{
JSInterpPtr interp = instance_context;
if (args->u.vinteger != 1)
{
sprintf (vm->error, "eval(): illegal amount of arguments");
js_vm_error (vm);
}
if (args[1].type != JS_STRING)
{
/* Return it to the caller. */
JS_COPY (result_return, &args[1]);
return;
}
/*
* Ok, we'r ready to eval it. The source strings is our argument, so,
* it is in the stack and therefore, protected for gc.
*/
if (!js_eval_source (interp, &args[1], "JSC$compile_string"))
{
/* The evaluation failed. Throw it as an error to our caller. */
js_vm_error (vm);
}
/* Pass the return value to our caller. */
JS_COPY (result_return, &vm->exec_result);
}
static void
load_class_global_method (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
void *instance_context,
JSNode *result_return, JSNode *args)
{
JSInterpPtr interp = instance_context;
int i;
if (args->u.vinteger == 0)
{
sprintf (vm->error, "loadClass(): no arguments given");
js_vm_error (vm);
}
for (i = 1; i <= args->u.vinteger; i++)
{
char *cp, *cp2;
void *lib;
void (*func) (JSInterpPtr interp);
char *func_name;
char buf[512];
if (args[i].type != JS_STRING)
{
sprintf (vm->error, "loadClass(): illegal argument");
js_vm_error (vm);
}
cp = js_string_to_c_string (vm, &args[i]);
/* Extract the function name. */
func_name = strrchr (cp, ':');
if (func_name == NULL)
{
func_name = strrchr (cp, '/');
if (func_name == NULL)
func_name = cp;
else
func_name++;
}
else
{
*func_name = '\0';
func_name++;
}
/* Try to open the library. */
lib = js_dl_open (cp, buf, sizeof (buf));
if (lib == NULL)
{
sprintf (vm->error, "loadClass(): couldn't open library `%s': %s",
cp, buf);
js_vm_error (vm);
}
/*
* Strip all suffixes from the library name: if the <func_name>
* is extracted from it, this will convert the library name
* `foo.so.x.y' to the canonical entry point name `foo'.
*/
cp2 = strchr (cp, '.');
if (cp2)
*cp2 = '\0';
func = js_dl_sym (lib, func_name, buf, sizeof (buf));
if (func == NULL)
{
sprintf (vm->error,
"loadClass(): couldn't find the init function `%s': %s",
func_name, buf);
js_vm_error (vm);
}
/* All done with this argument. */
js_free (cp);
/*
* And finally, call the library entry point. All possible errors
* will throw us to the containing top-level.
*/
(*func) (interp);
}
result_return->type = JS_UNDEFINED;
}
static void
call_method_global_method (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
void *instance_context,
JSNode *result_return, JSNode *args)
{
/* JSInterpPtr interp = instance_context; */
JSNode *argv;
int i;
int result;
char *cp;
if (args->u.vinteger != 3)
{
sprintf (vm->error, "callMethod(): illegal amount of arguments");
js_vm_error (vm);
}
if (args[2].type != JS_STRING)
{
illegal_argument:
sprintf (vm->error, "callMethod(): illegal argument");
js_vm_error (vm);
}
if (args[3].type != JS_ARRAY)
goto illegal_argument;
/* Create the argument array. */
argv = js_malloc (vm, (args[3].u.varray->length + 1) * sizeof (JSNode));
/* The argument count. */
argv[0].type = JS_INTEGER;
argv[0].u.vinteger = args[3].u.varray->length;
for (i = 0; i < args[3].u.varray->length; i++)
JS_COPY (&argv[i + 1], &args[3].u.varray->data[i]);
/* Method name to C string. */
cp = js_string_to_c_string (vm, &args[2]);
/* Call it. */
result = js_vm_call_method (vm, &args[1], cp, args[3].u.varray->length + 1,
argv);
/* Cleanup. */
js_free (cp);
js_free (argv);
if (result)
JS_COPY (result_return, &vm->exec_result);
else
/* The error message is already there. */
js_vm_error (vm);
}
static void
js_core_globals (JSInterpPtr interp)
{
JSNode *n;
JSBuiltinInfo *info;
JSVirtualMachine *vm = interp->vm;
if (!interp->options.no_compiler)
{
/* Command `eval'. */
info = js_vm_builtin_info_create (vm);
info->global_method_proc = eval_global_method;
n = &interp->vm->globals[js_vm_intern (interp->vm, "eval")];
js_vm_builtin_create (interp->vm, n, info, interp);
}
/* Command `loadClass'. */
info = js_vm_builtin_info_create (vm);
info->global_method_proc = load_class_global_method;
n = &interp->vm->globals[js_vm_intern (interp->vm, "loadClass")];
js_vm_builtin_create (interp->vm, n, info, interp);
/* Command `callMethod'. */
info = js_vm_builtin_info_create (vm);
info->global_method_proc = call_method_global_method;
n = &interp->vm->globals[js_vm_intern (interp->vm, "callMethod")];
js_vm_builtin_create (interp->vm, n, info, interp);
}
static void
js_global_method_stub (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
void *instance_context, JSNode *result_return,
JSNode *args)
{
JSMethodResult result;
JSGlobalMethodContext *ctx = instance_context;
/* Set the default result. */
result_return->type = JS_UNDEFINED;
/* Call the user supplied function. */
result = (*ctx->proc) (ctx->context, ctx->interp, args->u.vinteger,
(JSType *) &args[1], (JSType *) result_return,
vm->error);
if (result != JS_OK)
js_vm_error (ctx->interp->vm);
}
static void
js_global_method_delete (JSBuiltinInfo *builtin_info, void *instance_context)
{
JSGlobalMethodContext *ctx = instance_context;
if (ctx)
{
if (ctx->free_proc)
(*ctx->free_proc) (ctx->context);
js_free (ctx);
}
}
/* I/O Stream to user I/O function. */
static int
iofunc_io (void *context, unsigned char *buffer, unsigned int todo,
int *error_return)
{
JSUserIOFuncCtx *ctx = context;
int moved;
*error_return = 0;
moved = (*ctx->func) (ctx->context, buffer, todo);
if (moved >= 0)
ctx->position += moved;
return moved;
}
static int
iofunc_seek (void *context, long offset, int whence)
{
return -1;
}
static long
iofunc_get_position (void *context)
{
JSUserIOFuncCtx *ctx = context;
return ctx->position;
}
static long
iofunc_get_length (void *context)
{
return -1;
}
static void
iofunc_close (void *context)
{
js_free (context);
}
static JSIOStream *
iostream_iofunc (JSIOFunc func, void *context, int readp, int writep)
{
JSIOStream *stream = js_iostream_new ();
JSUserIOFuncCtx *ctx;
ctx = js_malloc (NULL, sizeof (*ctx));
if (ctx == NULL)
{
(void) js_iostream_close (stream);
return NULL;
}
/* Init context. */
ctx->func = func;
ctx->context = context;
ctx->position = 0;
if (readp)
stream->read = iofunc_io;
if (writep)
stream->write = iofunc_io;
stream->seek = iofunc_seek;
stream->get_position = iofunc_get_position;
stream->get_length = iofunc_get_length;
stream->close = iofunc_close;
stream->context = ctx;
return stream;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -