⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 js.c

📁 一个类似windows
💻 C
📖 第 1 页 / 共 3 页
字号:
 */

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 + -