Example #1
0
int
js_vm_object_nth (JSVirtualMachine *vm, JSObject *obj, int nth,
		  JSNode *value_return)
{
  int i;
  JSObjectPropHashBucket *b;

  value_return->type = JS_UNDEFINED;

  if (nth < 0)
    return 0;

  if (obj->hash == NULL)
    hash_create (vm, obj);

  for (i = 0; i < HASH_SIZE && nth >= obj->hash_lengths[i]; i++)
    nth -= obj->hash_lengths[i];

  if (i >= HASH_SIZE)
    return 0;

  /* The chain <i> is the correct one. */
  for (b = obj->hash[i]; b && nth > 0; b = b->next, nth--)
    ;
  if (b == NULL)
    {
      fprintf (stderr,
	       "js_vm_object_nth(): chain didn't contain that many items\n");
      abort ();
    }

  js_vm_make_string (vm, value_return, b->data, b->len);

  return 1;
}
Example #2
0
void
js_type_make_string (JSInterpPtr interp, JSType *type, unsigned char *data,
		     unsigned int length)
{
  JSNode *n = (JSNode *) type;

  js_vm_make_string (interp->vm, n, data, length);
}
Example #3
0
static void
unescape_global_method (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
			void *instance_context, JSNode *result_return,
			JSNode *args)
{
  unsigned char *dp;
  unsigned int n, i;
  JSNode *source;
  JSNode source_n;

  if (args->u.vinteger != 1)
    {
      sprintf_P (vm->error, b_core_string_3);
      js_vm_error (vm);
    }
  if (args[1].type == JS_STRING)
    source = &args[1];
  else
    {
      js_vm_to_string (vm, &args[1], &source_n);
      source = &source_n;
    }

  /*
   * Allocate the result string, Let's guess that we need at least
   * <source->u.vstring->len> bytes of data.
   */
  n = source->u.vstring->len;
  dp = source->u.vstring->data;
  js_vm_make_string (vm, result_return, NULL, n);
  result_return->u.vstring->len = 0;

  /*
   * Scan for escapes requiring characters.
   */
  for (i = 0; i < n;)
    {
      unsigned int c = dp[i];

      if (c != '%')
	i += 1;
      else if (i <= n - 6 && dp[i + 1] == 'u'
	       && scanhexdigits (dp + i + 2, 4, &c))
	i += 6;
      else if (i <= n - 3 && scanhexdigits (dp + i + 1, 2, &c))
	i += 3;
      else
	{
	  c = dp[i];
	  i += 1;
	}
      EMIT_TO_RESULT (c);
    }
}
Example #4
0
void js_vm_error(JSVirtualMachine * vm)
{
#if JS_RUNTIME_WARNING | JS_RUNTIME_DEBUG
	char error[1024];
#endif
#ifdef JS_RUNTIME_DEBUG
	const char *file;
	unsigned int ln;

	file = js_vm_debug_position(vm, &ln);
	if (file) {
		sprintf(error, "%s:%u: %s", file, ln, vm->error);
		strcpy(vm->error, error);
	}

	if (vm->stacktrace_on_error) {
		sprintf(error, "VM: error: %s%s", vm->error, JS_HOST_LINE_BREAK);
#ifdef JS_IOSTREAM
        js_iostream_write(vm->s_stderr, error, strlen(error));
#else
		fwrite(error, strlen(error), 1, stderr);
#endif
		js_vm_stacktrace(vm, (unsigned int) -1);
	}
#endif
	// We are jumping to a catch-block.  Format our error message to
	// the `thrown' node.
#ifdef JS_RUNTIME_WARNING
	if (vm->error_handler->sp)
		js_vm_make_string(vm, &vm->error_handler->thrown, vm->error, strlen(vm->error));
#endif
	longjmp(vm->error_handler->error_jmp, 1);
	// NOTREACHED (I hope)
#ifdef JS_RUNTIME_WARNING
	sprintf(error, "VM: no valid error handler initialized%s", JS_HOST_LINE_BREAK);
#ifdef JS_IOSTREAM
    js_iostream_write(vm->s_stderr, error, strlen(error));
	js_iostream_flush(vm->s_stderr);
#else
	fwrite(error, strlen(error), 1, stderr);
#endif
#endif
	abort();
}
Example #5
0
static void
copy_from_type_to_node (JSVirtualMachine *vm, JSNode *to, JSType *from)
{
  int i;

  switch (from->type)
    {
    case JS_TYPE_NULL:
      to->type = JS_NULL;
      break;

    case JS_TYPE_BOOLEAN:
      to->type = JS_BOOLEAN;
      to->u.vboolean = from->u.i;
      break;

    case JS_TYPE_INTEGER:
      to->type = JS_INTEGER;
      to->u.vinteger = from->u.i;
      break;

    case JS_TYPE_STRING:
      js_vm_make_string (vm, to, from->u.s->data, from->u.s->len);
      break;

    case JS_TYPE_DOUBLE:
      to->type = JS_FLOAT;
      to->u.vfloat = from->u.d;
      break;

    case JS_TYPE_ARRAY:
      js_vm_make_array (vm, to, from->u.array->length);
      for (i = 0; i < from->u.array->length; i++)
	copy_from_type_to_node (vm,
				&to->u.varray->data[i],
				&from->u.array->data[i]);
      break;

    default:
      to->type = JS_UNDEFINED;
      break;
    }
}
Example #6
0
/* Property proc. */
static int
property (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
	  void *instance_context, JSSymbol method, int set, JSNode *node)
{
  XJSCtx *ctx = builtin_info->obj_context;
  XJSInstanceCtx *instance = instance_context;

  if (method == ctx->s_errorMessage)
    {
      char *cp = instance->interp->vm->error;

      if (set)
	goto immutable;

      js_vm_make_string (vm, node, cp, strlen (cp));
    }
  else
    {
      if (!set)
	node->type = JS_UNDEFINED;

      return JS_PROPERTY_UNKNOWN;
    }

  return JS_PROPERTY_FOUND;


  /*
   * Error handling.
   */

 immutable:
  sprintf (vm->error, "JS.%s: immutable property",
	   js_vm_symname (vm, method));
  js_vm_error (vm);

  /* NOTREACHED. */
  return 0;
}
Example #7
0
/* Method proc. */
static int
method (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
        void *instance_context, JSSymbol method, JSNode *result_return,
        JSNode *args)
{
    JSNode *n = instance_context;
    char buf[256];

    if (method == vm->syms.s_toString)
    {
        if (n)
        {
            int radix = 10;

            if (args->u.vinteger == 0)
                ;
            else if (args->u.vinteger == 1)
            {
                if (args[1].type != JS_INTEGER)
                    goto argument_type_error;

                radix = args[1].u.vinteger;
            }
            else
                goto argument_error;

            if (n->type == JS_INTEGER)
            {
                switch (radix)
                {
                case 8:
                    sprintf (buf, "%o", (unsigned int) n->u.vinteger);
                    break;

                case 10:
                    sprintf (buf, "%ld", n->u.vinteger);
                    break;

                case 16:
                    sprintf (buf, "%lx", (unsigned long) n->u.vinteger);
                    break;

                default:
                    sprintf (vm->error, "Number.%s(): illegal radix %d",
                             js_vm_symname (vm, method), radix);
                    break;
                }
            }
            else if (n->type == JS_FLOAT)
                sprintf (buf, "%g", n->u.vfloat);
            else
                sprintf (buf, "NaN");

            js_vm_make_string (vm, result_return, buf, strlen (buf));
        }
        else
        {
            if (args->u.vinteger != 0)
                goto argument_error;
            js_vm_make_static_string (vm, result_return, "Number", 6);
        }
    }
    /* ********************************************************************** */
    else
        return JS_PROPERTY_UNKNOWN;

    return JS_PROPERTY_FOUND;


    /*
     * Error handling.
     */

argument_error:
    sprintf (vm->error, "Number.%s(): illegal amount of arguments",
             js_vm_symname (vm, method));
    js_vm_error (vm);

argument_type_error:
    sprintf (vm->error, "Number.%s(): illegal argument",
             js_vm_symname (vm, method));
    js_vm_error (vm);

    /* NOTREACHED */
    return 0;
}
Example #8
0
static void
escape_global_method (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
		      void *instance_context, JSNode *result_return,
		      JSNode *args)
{
  unsigned char *dp;
  unsigned int n, i;
  JSNode *source;
  JSNode source_n;
  static const prog_char charset[] PROGMEM =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@*_+-./";

  if (args->u.vinteger != 1)
    {
      sprintf (vm->error, b_core_string_2);
      js_vm_error (vm);
    }
  if (args[1].type == JS_STRING)
    source = &args[1];
  else
    {
      /* Convert the argument to string. */
      js_vm_to_string (vm, &args[1], &source_n);
      source = &source_n;
    }

  /*
   * Allocate the result string, Let's guess that we need at least
   * <source->u.vstring->len> bytes of data.
   */
  n = source->u.vstring->len;
  dp = source->u.vstring->data;
  js_vm_make_string (vm, result_return, NULL, n);
  result_return->u.vstring->len = 0;

  /*
   * Scan for characters requiring escapes.
   */
  for (i = 0; i < n; i += 1)
    {
      unsigned int c = dp[i];

      if (strchr_P (charset, c))
	EMIT_TO_RESULT (c);
      else if (c > 0xFF)
	{
	  unsigned char buf[6];

	  sprintf (buf, "%04x", c);
	  EMIT_TO_RESULT ('%');
	  EMIT_TO_RESULT ('u');
	  EMIT_TO_RESULT (buf[0]);
	  EMIT_TO_RESULT (buf[1]);
	  EMIT_TO_RESULT (buf[2]);
	  EMIT_TO_RESULT (buf[3]);
      }
    else
      {
	unsigned char buf[4];
	sprintf (buf, "%02x", c);

	EMIT_TO_RESULT ('%');
	EMIT_TO_RESULT (buf[0]);
	EMIT_TO_RESULT (buf[1]);
      }
    }
}
Example #9
0
/* Method proc. */
static int
method (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
	void *instance_context, JSSymbol method, JSNode *result_return,
	JSNode *args)
{
  ArrayCtx *ctx = builtin_info->obj_context;
  JSNode *n = instance_context;
  int i;

  /* Set the default result type. */
  result_return->type = JS_UNDEFINED;

  if (method == ctx->s_concat)
    {
      if (args->u.vinteger != 1)
	goto argument_error;
      if (args[1].type != JS_ARRAY)
	goto argument_type_error;

      js_vm_make_array (vm, result_return,
			n->u.varray->length + args[1].u.varray->length);

      memcpy (result_return->u.varray->data, n->u.varray->data,
	      n->u.varray->length * sizeof (JSNode));

      memcpy (&result_return->u.varray->data[n->u.varray->length],
	      args[1].u.varray->data,
	      args[1].u.varray->length * sizeof (JSNode));
    }
  /* ********************************************************************** */
  else if (method == ctx->s_join || method == vm->syms.s_toString)
    {
      char *glue = NULL;

      if (method == vm->syms.s_toString)
	{
	  if (args->u.vinteger != 0)
	    goto argument_error;
	}
      else
	{
	  if (args->u.vinteger == 0)
	    ;
	  else if (args->u.vinteger == 1)
	    {
	      JSNode glue_result;

	      js_vm_to_string (vm, &args[1], &glue_result);
	      glue = js_string_to_c_string (vm, &glue_result);
	    }
	  else
	    goto argument_error;
	}

      /* Ok, ready to run. */
      if (n->u.varray->length == 0)
	js_vm_make_static_string (vm, result_return, "", 0);
      else
	{
	  int len;
	  int glue_len = glue ? strlen (glue) : 1;

	  /* Estimate the result length. */
	  len = (n->u.varray->length * 5
		 + (n->u.varray->length - 1) * glue_len);

	  js_vm_make_string (vm, result_return, NULL, len);
	  result_return->u.vstring->len = 0;

	  /* Do the join. */
	  for (i = 0; i < n->u.varray->length; i++)
	    {
	      JSNode sitem;
	      int delta;

	      js_vm_to_string (vm, &n->u.varray->data[i], &sitem);
	      delta = sitem.u.vstring->len;

	      if (i + 1 < n->u.varray->length)
		delta += glue_len;

	      result_return->u.vstring->data
		= js_vm_realloc (vm, result_return->u.vstring->data,
				 result_return->u.vstring->len + delta);

	      memcpy (result_return->u.vstring->data
		      + result_return->u.vstring->len,
		      sitem.u.vstring->data,
		      sitem.u.vstring->len);
	      result_return->u.vstring->len += sitem.u.vstring->len;

	      if (i + 1 < n->u.varray->length)
		{
		  if (glue)
		    {
		      memcpy (result_return->u.vstring->data
			      + result_return->u.vstring->len,
			      glue, glue_len);
		      result_return->u.vstring->len += glue_len;
		    }
		  else
		    result_return->u.vstring->data
		      [result_return->u.vstring->len++] = ',';
		}
	    }
	}

      if (glue)
	js_free (glue);
    }
  /* ********************************************************************** */
  else if (method == ctx->s_pop)
    {
      if (args->u.vinteger != 0)
	goto argument_error;

      if (n->u.varray->length == 0)
	result_return->type = JS_UNDEFINED;
      else
	{
	  JS_COPY (result_return, &n->u.varray->data[n->u.varray->length - 1]);
	  n->u.varray->length--;
	}
    }
  /* ********************************************************************** */
  else if (method == ctx->s_push)
    {
      int old_len;

      if (args->u.vinteger == 0)
	goto argument_error;

      old_len = n->u.varray->length;
      js_vm_expand_array (vm, n, n->u.varray->length + args->u.vinteger);

      for (i = 0; i < args->u.vinteger; i++)
	JS_COPY (&n->u.varray->data[old_len + i], &args[i + 1]);

      JS_COPY (result_return, &args[i]);
    }
  /* ********************************************************************** */
  else if (method == ctx->s_reverse)
    {
      if (args->u.vinteger != 0)
	goto argument_error;

      for (i = 0; i < n->u.varray->length / 2; i++)
	{
	  JSNode tmp;

	  JS_COPY (&tmp, &n->u.varray->data[i]);
	  JS_COPY (&n->u.varray->data[i],
		   &n->u.varray->data[n->u.varray->length - i - 1]);
	  JS_COPY (&n->u.varray->data[n->u.varray->length - i - 1], &tmp);
	}
    }
  /* ********************************************************************** */
  else if (method == ctx->s_shift)
    {
      if (args->u.vinteger != 0)
	goto argument_error;

      if (n->u.varray->length == 0)
	result_return->type = JS_UNDEFINED;
      else
	{
	  JS_COPY (result_return, &n->u.varray->data[0]);
	  memmove (&n->u.varray->data[0], &n->u.varray->data[1],
		   (n->u.varray->length - 1) * sizeof (JSNode));
	  n->u.varray->length--;
	}
    }
  /* ********************************************************************** */
  else if (method == ctx->s_slice)
    {
      int start, end;

      if (args->u.vinteger < 1 || args->u.vinteger > 2)
	goto argument_error;

      if (args[1].type != JS_INTEGER)
	goto argument_type_error;

      start = args[1].u.vinteger;

      if (args->u.vinteger == 2)
	{
	  if (args[2].type != JS_INTEGER)
	    goto argument_type_error;

	  end = args[2].u.vinteger;
	}
      else
	end = n->u.varray->length;

      if (end < 0)
	end += n->u.varray->length;
      if (end < 0)
	end = start;

      js_vm_make_array (vm, result_return, end - start);

      /* Copy items. */
      for (i = 0; i < end - start; i++)
	JS_COPY (&result_return->u.varray->data[i],
		 &n->u.varray->data[start + i]);
    }
  /* ********************************************************************** */
  else if (method == ctx->s_splice)
    {
      unsigned int new_length;
      unsigned int old_length;
      int delta;

      if (args->u.vinteger < 2)
	goto argument_error;
      if (args[1].type != JS_INTEGER || args[2].type != JS_INTEGER)
	goto argument_type_error;

      if (args[2].u.vinteger == 0 && args->u.vinteger == 2)
	/* No deletions: must specify at least one item to insert. */
	goto argument_error;

      old_length = new_length = n->u.varray->length;
      if (args[1].u.vinteger < new_length)
	{
	  if (args[2].u.vinteger > new_length - args[1].u.vinteger)
	    {
	      args[2].u.vinteger = new_length - args[1].u.vinteger;
	      new_length = args[1].u.vinteger;
	    }
	  else
	    new_length -= args[2].u.vinteger;
	}
      else
	{
	  new_length = args[1].u.vinteger;
	  args[2].u.vinteger = 0;
	}

      new_length += args->u.vinteger - 2;

      if (new_length > n->u.varray->length)
	js_vm_expand_array (vm, n, new_length);
      else
	/* Cut the array. */
	n->u.varray->length = new_length;

      /* Do the stuffs we must do. */

      /* Create the result array. */
      if (args[2].u.vinteger == 0)
	result_return->type = JS_UNDEFINED;
      else
	{
	  js_vm_make_array (vm, result_return, args[2].u.vinteger);
	  for (i = 0; i < args[2].u.vinteger; i++)
	    JS_COPY (&result_return->u.varray->data[i],
		     &n->u.varray->data[args[1].u.vinteger + i]);
	}

      /* Delete and move. */
      delta = args->u.vinteger - 2 - args[2].u.vinteger;
      memmove (&n->u.varray->data[args[1].u.vinteger + args[2].u.vinteger
				 + delta],
	       &n->u.varray->data[args[1].u.vinteger + args[2].u.vinteger],
	       (old_length - (args[1].u.vinteger + args[2].u.vinteger))
	       * sizeof (JSNode));

      /* Insert. */
      for (i = 0; i < args->u.vinteger - 2; i++)
	JS_COPY (&n->u.varray->data[args[1].u.vinteger + i], &args[i + 3]);
    }
  /* ********************************************************************** */
  else if (method == ctx->s_sort)
    {
      MergesortCompFunc func;
      ArraySortCtx array_sort_ctx;
      void *func_ctx = NULL;	/* Initialized to keep compiler quiet. */

      if (args->u.vinteger == 0)
	{
	  func = sort_default_cmp_func;
	  func_ctx = vm;
	}
      else if (args->u.vinteger == 1)
	{
	  if (args[1].type != JS_FUNC && args[1].type != JS_BUILTIN)
	    goto argument_type_error;

	  func = sort_js_cmp_func;

	  /* Init context. */
	  array_sort_ctx.vm = vm;
	  array_sort_ctx.func = &args[1];

	  /* Init the argc part of the argument vector here. */
	  array_sort_ctx.argv[0].type = JS_INTEGER;
	  array_sort_ctx.argv[0].u.vinteger = 3;

	  func_ctx = &array_sort_ctx;
	}
      else
	goto argument_error;

      mergesort_r (n->u.varray->data, n->u.varray->length, sizeof (JSNode),
		   func, func_ctx);
    }
  /* ********************************************************************** */
  else if (method == ctx->s_unshift)
    {
      int old_len;

      if (args->u.vinteger == 0)
	goto argument_error;

      old_len = n->u.varray->length;
      js_vm_expand_array (vm, n, n->u.varray->length + args->u.vinteger);

      memmove (&n->u.varray->data[args->u.vinteger], n->u.varray->data,
	       old_len * sizeof (JSNode));

      for (i = 0; i < args->u.vinteger; i++)
	JS_COPY (&n->u.varray->data[i], &args[args->u.vinteger - i]);

      result_return->type = JS_INTEGER;
      result_return->u.vinteger = n->u.varray->length;
    }
  /* ********************************************************************** */
  else
    return JS_PROPERTY_UNKNOWN;

  return JS_PROPERTY_FOUND;


  /*
   * Error handling.
   */

 argument_error:
  sprintf (vm->error, "Array.%s(): illegal amount of arguments",
	   js_vm_symname (vm, method));
  js_vm_error (vm);

 argument_type_error:
  sprintf (vm->error, "Array.%s(): illegal argument",
	   js_vm_symname (vm, method));
  js_vm_error (vm);

  /* NOTREACHED */
  return 0;
}