Beispiel #1
0
static void
parseFloat_global_method (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
			  void *instance_context, JSNode *result_return,
			  JSNode *args)
{
  char *cp, *end;

  result_return->type = JS_FLOAT;

  if (args->u.vinteger != 1)
    {
      sprintf_P (vm->error, b_core_string_1);
      js_vm_error (vm);
    }
  if (args[1].type == JS_STRING)
    cp = js_string_to_c_string (vm, &args[1]);
  else
    {
      JSNode input;

      /* Convert the input to string. */
      js_vm_to_string (vm, &args[1], &input);
      cp = js_string_to_c_string (vm, &input);
    }

  result_return->u.vfloat = strtod (cp, &end);
  js_free (cp);

  if (cp == end)
    /* Couldn't parse, return NaN. */
    result_return->type = JS_NAN;
}
Beispiel #2
0
static int
sort_default_cmp_func (const void *aptr, const void *bptr, void *context)
{
  JSVirtualMachine *vm = context;
  const JSNode *a = aptr;
  const JSNode *b = bptr;
  JSNode astr, bstr;

  if (a->type == JS_UNDEFINED)
    return 1;
  if (b->type == JS_UNDEFINED)
    return -1;

  js_vm_to_string (vm, a, &astr);
  js_vm_to_string (vm, b, &bstr);

  return js_compare_strings (&astr, &bstr);
}
Beispiel #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);
    }
}
Beispiel #4
0
static void
parseInt_global_method (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
			void *instance_context, JSNode *result_return,
			JSNode *args)
{
  JSInt32 base = 0;
  char *cp, *end;

  result_return->type = JS_INTEGER;

  if (args->u.vinteger != 1 && args->u.vinteger != 2)
    {
      sprintf_P (vm->error, b_core_string_0);
      js_vm_error (vm);
    }
  if (args[1].type == JS_STRING)
    cp = js_string_to_c_string (vm, &args[1]);
  else
    {
      JSNode input;

      /* Convert the input to string. */
      js_vm_to_string (vm, &args[1], &input);
      cp = js_string_to_c_string (vm, &input);
    }
  if (args->u.vinteger == 2)
    {
      if (args[2].type == JS_INTEGER)
	base = args[2].u.vinteger;
      else
	base = js_vm_to_int32 (vm, &args[2]);
    }

  result_return->u.vinteger = strtol (cp, &end, base);
  js_free (cp);

  if (cp == end)
    result_return->type = JS_NAN;
}
Beispiel #5
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]);
      }
    }
}
Beispiel #6
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;
}