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

📄 js.c

📁 一个类似windows
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * JavaScript interpreter main glue.
 * 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: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/kjs/src/js.c,v $
 * $Id: js.c 21681 2006-04-21 15:00:24Z peterw $
 */

#include "js.h"
#include "jsint.h"

/*
 * Types and definitions.
 */

/* Context for js_global_method_stub. */
struct js_global_method_context_st
{
  JSGlobalMethodProc proc;
  void *context;
  JSFreeProc free_proc;
  JSInterpPtr interp;
};

typedef struct js_global_method_context_st JSGlobalMethodContext;

/* Context for user I/O function streams. */
struct js_user_io_func_ctx_st
{
  JSIOFunc func;
  void *context;
  long position;
};

typedef struct js_user_io_func_ctx_st JSUserIOFuncCtx;

struct js_method_reg_st
{
  JSSymbol sym;
  char *name;
  unsigned int flags;
  JSMethodProc method;
};

typedef struct js_method_reg_st JSMethodReg;

struct js_property_reg_st
{
  JSSymbol sym;
  char *name;
  unsigned int flags;
  JSPropertyProc property;
};

typedef struct js_property_reg_st JSPropertyReg;

/* The class handle. */
struct js_class_st
{
  char *name;
  JSInterpPtr interp;

  /* Flags. */
  unsigned int no_auto_destroy : 1;
  unsigned int interned : 1;

  void *class_context;
  JSFreeProc class_context_destructor;

  JSConstructor constructor;

  unsigned int num_methods;
  JSMethodReg *methods;

  unsigned int num_properties;
  JSPropertyReg *properties;
};

/* Object instance context. */
struct js_object_instance_ctx_st
{
  void *instance_context;
  JSFreeProc instance_context_destructor;
};

typedef struct js_object_instance_ctx_st JSObjectInstanceCtx;


/*
 * Prototypes for static functions.
 */

/* The module for JS' core global methods. */
static void js_core_globals (JSInterpPtr interp);

/*
 * Helper function to evaluate source <source> with compiler function
 * <compiler_function>.
 */
static int js_eval_source (JSInterpPtr interp, JSNode *source,
			   char *compiler_function);

/*
 * Helper function to compile source <source> with compiler function
 * <compiler_function>.  If <assembler_file> is not NULL, the
 * assembler listing of the compilation is saved to that file.  If
 * <byte_code_file> is not NULL, the byte_code data is saved to that
 * file.  If <bc_return> is not NULL, the resulting byte_code data is
 * returned in it as a JavaScript string node.
 */
static int js_compile_source (JSInterpPtr interp, JSNode *source,
			      char *compiler_function, char *assembler_file,
			      char *byte_code_file, JSNode *bc_return);

/*
 * The stub function for global methods, created with the
 * js_create_global_method() API function.
 */
static void js_global_method_stub (JSVirtualMachine *vm,
				   JSBuiltinInfo *builtin_info,
				   void *instance_context,
				   JSNode *result_return,
				   JSNode *args);

/*
 * Destructor for the global methods, created with the
 * js_create_global_method() API function.
 */
static void js_global_method_delete (JSBuiltinInfo *builtin_info,
				     void *instance_context);

static JSIOStream *iostream_iofunc (JSIOFunc func, void *context,
				    int readp, int writep);


/*
 * Global functions.
 */

const JSCharPtr
js_version ()
{
  return VERSION;
}


void
js_init_default_options (JSInterpOptions *options)
{
  memset (options, 0, sizeof (*options));

  options->stack_size = 2048;
  options->dispatch_method = JS_VM_DISPATCH_JUMPS;

  options->warn_undef = 1;

  options->optimize_peephole = 1;
  options->optimize_jumps_to_jumps = 1;

  options->fd_count = (unsigned long) -1;
}


JSInterpPtr
js_create_interp (JSInterpOptions *options)
{
  JSInterpPtr interp = NULL;
  JSByteCode *bc;
  JSInterpOptions default_options;
  JSIOStream *s_stdin = NULL;
  JSIOStream *s_stdout = NULL;
  JSIOStream *s_stderr = NULL;

  /*
   * Sanity check to assure that the js.h and jsint.h APIs share a
   * same view to the world.
   */
  assert (sizeof (JSNode) == sizeof (JSType));

  interp = js_calloc (NULL, 1, sizeof (*interp));
  if (interp == NULL)
    return NULL;

  if (options == NULL)
    {
      js_init_default_options (&default_options);
      options = &default_options;
    }

  memcpy (&interp->options, options, sizeof (*options));

  /* The default system streams. */

  if (options->s_stdin)
    s_stdin = iostream_iofunc (options->s_stdin, options->s_context, 1, 0);
  else
    s_stdin = js_iostream_file (stdin, 1, 0, 0);

  if (s_stdin == NULL)
    goto error_out;

  if (options->s_stdout)
    s_stdout = iostream_iofunc (options->s_stdout, options->s_context, 0, 1);
  else
    s_stdout = js_iostream_file (stdout, 0, 1, 0);

  if (s_stdout == NULL)
    goto error_out;
  s_stdout->autoflush = 1;

  if (options->s_stderr)
    s_stderr = iostream_iofunc (options->s_stderr, options->s_context, 0, 1);
  else
    s_stderr = js_iostream_file (stderr, 0, 1, 0);

  if (s_stderr == NULL)
    goto error_out;
  s_stderr->autoflush = 1;

  /* Create virtual machine. */
  interp->vm = js_vm_create (options->stack_size,
			     options->dispatch_method,
			     options->verbose,
			     options->stacktrace_on_error,
			     s_stdin, s_stdout, s_stderr);
  if (interp->vm == NULL)
    goto error_out;

  /* Set some options. */
  interp->vm->warn_undef = options->warn_undef;

  /* Set the security options. */

  if (options->secure_builtin_file)
    interp->vm->security |= JS_VM_SECURE_FILE;
  if (options->secure_builtin_system)
    interp->vm->security |= JS_VM_SECURE_SYSTEM;

  /* Set the event hook. */
  interp->vm->hook			 = options->hook;
  interp->vm->hook_context		 = options->hook_context;
  interp->vm->hook_operand_count_trigger = options->hook_operand_count_trigger;

  /* The file descriptor limit. */
  interp->vm->fd_count = options->fd_count;

  if (!options->no_compiler)
    {
      int result;

      /* Define compiler to the virtual machine. */
      bc = js_bc_read_data (js_compiler_bytecode, js_compiler_bytecode_len);
      if (bc == NULL)
	goto error_out;

      result = js_vm_execute (interp->vm, bc);
      js_bc_free (bc);
      if (!result)
	goto error_out;
    }

  /* Initialize our extensions. */
  if (!js_define_module (interp, js_core_globals))
    goto error_out;

  /* Ok, we'r done. */

#if 0
#if JS_DEBUG_MEMORY_LEAKS
  /* Let's see how much memory an empty interpreter takes. */
  js_alloc_dump_blocks ();
#endif /* JS_DEBUG_MEMORY_LEAKS */
#endif

  return interp;


  /*
   * Error handling.
   */

 error_out:

  if (interp)
    {
      if (interp->vm)
	js_vm_destroy (interp->vm);
      js_free (interp);
    }

  if (s_stdin)
    js_iostream_close (s_stdin);
  if (s_stdout)
    js_iostream_close (s_stdout);
  if (s_stderr)
    js_iostream_close (s_stderr);

  return NULL;
}


void
js_destroy_interp (JSInterpPtr interp)
{
  js_vm_destroy (interp->vm);
  js_free (interp);

#if 0
#if JS_DEBUG_MEMORY_LEAKS
  /* Let's see how much memory we leak. */
  js_alloc_dump_blocks ();
#endif /* JS_DEBUG_MEMORY_LEAKS */
#endif
}


const JSCharPtr
js_error_message (JSInterpPtr interp)
{
  return interp->vm->error;
}


void
js_result (JSInterpPtr interp, JSType *result_return)
{
  memcpy (result_return, &interp->vm->exec_result, sizeof (*result_return));
}


int
js_eval (JSInterpPtr interp, char *code)
{
  JSNode source;

  js_vm_make_static_string (interp->vm, &source, code, strlen (code));
  return js_eval_source (interp, &source, "JSC$compile_string");
}


int
js_eval_data (JSInterpPtr interp, char *data, unsigned int datalen)
{
  JSNode source;

  js_vm_make_static_string (interp->vm, &source, data, datalen);
  return js_eval_source (interp, &source, "JSC$compile_string");
}


int
js_eval_file (JSInterpPtr interp, char *filename)
{
  char *cp;
  int result;

  cp = strrchr (filename, '.');
  if (cp && strcmp (cp, ".jsc") == 0)
    {
    run_bytecode:
      result = js_execute_byte_code_file (interp, filename);
    }
  else if (cp && strcmp (cp, ".js") == 0)
    {
    try_javascript:
      result = js_eval_javascript_file (interp, filename);
    }
  else
    {
      FILE *fp;

      /* Must look into the file. */

      fp = fopen (filename, "r");
      if (fp)
	{
	  int ch;

	  if ((ch = getc (fp)) == '#')
	    {
	      /* Skip the first sh-command line. */
	      while ((ch = getc (fp)) != EOF && ch != '\n')
		;
	      if (ch == EOF)
		{
		  fclose (fp);
		  goto try_javascript;
		}
	    }
	  else
	    ungetc (ch, fp);

	  /* Check if we can read the file magic. */
	  ch = getc (fp);
	  if (ch == 0xc0)
	    {
	      ch = getc (fp);
	      if (ch == 0x01)
		{
		  ch = getc (fp);
		  if (ch == 'J')
		    {
		      ch = getc (fp);
		      if (ch == 'S')
			{
			  /* Got it.  We find a valid byte-code file magic. */
			  fclose (fp);
			  goto run_bytecode;
			}
		    }
		}
	    }

	  fclose (fp);
	  /* FALLTHROUGH */
	}

      /*
       * If nothing else helps, we assume that the file contains JavaScript
       * source code that must be compiled.
       */
      goto try_javascript;
    }

  return result;
}


int
js_eval_javascript_file (JSInterpPtr interp, char *filename)
{
  JSNode source;

  js_vm_make_static_string (interp->vm, &source, filename, strlen (filename));
  return js_eval_source (interp, &source, "JSC$compile_file");
}


int
js_execute_byte_code_file (JSInterpPtr interp, char *filename)
{
  JSByteCode *bc;
  FILE *fp;
  int result;

  fp = fopen (filename, "rb");
  if (fp == NULL)
    {
      /* Let's borrow vm's error buffer. */
      sprintf (interp->vm->error, "couldn't open byte-code file \"%s\": %s",
	       filename, strerror (errno));
      return 0;
    }

  bc = js_bc_read_file (fp);
  fclose (fp);

  if (bc == NULL)
    /* XXX Error message. */
    return 0;

  /* Execute it. */

  result = js_vm_execute (interp->vm, bc);
  js_bc_free (bc);

  return result;
}


int
js_apply (JSInterpPtr interp, char *name, unsigned int argc, JSType *argv)
{
  JSNode *args;
  unsigned int ui;
  int result;

  args = js_malloc (NULL, (argc + 1) * sizeof (JSNode));
  if (args == NULL)
    {
      sprintf (interp->vm->error, "VM: out of memory");
      return 0;
    }

  /* Set the argument count. */
  args[0].type = JS_INTEGER;
  args[0].u.vinteger = argc;

  /* Set the arguments. */
  for (ui = 0; ui < argc; ui++)
    JS_COPY (&args[ui + 1], (JSNode *) &argv[ui]);

  /* Call it. */
  result = js_vm_apply (interp->vm, name, NULL, argc + 1, args);

  js_free (args);

  return result;
}


int
js_compile (JSInterpPtr interp,  char *input_file, char *assembler_file,
	    char *byte_code_file)
{
  JSNode source;

  js_vm_make_static_string (interp->vm, &source, input_file,
			    strlen (input_file));
  return js_compile_source (interp, &source, "JSC$compile_file",
			    assembler_file, byte_code_file, NULL);
}


int
js_compile_to_byte_code (JSInterpPtr interp, char *input_file,
			 unsigned char **bc_return,
			 unsigned int *bc_len_return)
{
  JSNode source;
  int result;

  js_vm_make_static_string (interp->vm, &source, input_file,
			    strlen (input_file));
  result = js_compile_source (interp, &source, "JSC$compile_file",
			      NULL, NULL, &source);
  if (result == 0)
    return 0;

  /* Pass the data to the caller. */
  *bc_return = source.u.vstring->data;
  *bc_len_return = source.u.vstring->len;

  return result;
}


int
js_compile_data_to_byte_code (JSInterpPtr interp, char *data,
			      unsigned int datalen,
			      unsigned char **bc_return,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -