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

📄 b_regexp.c

📁 一个类似windows
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * The builtin RegExp object.
 * Copyright (c) 1998 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/ksrc/b_regexp.c,v $
 * $Id: b_regexp.c 21681 2006-04-21 15:00:24Z peterw $
 */

#include "jsint.h"
#include "regex.h"

/*
 * Types and definitions.
 */

/* These must be in sync with the values, found from `../jsc/asm.js'. */
#define JS_REGEXP_FLAG_G	0x01
#define JS_REGEXP_FLAG_I	0x02

/* Class context. */
struct regexp_ctx_st
{
  /* Static properties. */
  JSSymbol s_S1;
  JSSymbol s_S2;
  JSSymbol s_S3;
  JSSymbol s_S4;
  JSSymbol s_S5;
  JSSymbol s_S6;
  JSSymbol s_S7;
  JSSymbol s_S8;
  JSSymbol s_S9;
  JSSymbol s_S_;
  JSSymbol s_input;
  JSSymbol s_lastMatch;
  JSSymbol s_lastParen;
  JSSymbol s_leftContext;
  JSSymbol s_multiline;
  JSSymbol s_rightContext;

  /* Properties. */
  JSSymbol s_global;
  JSSymbol s_ignoreCase;
  JSSymbol s_lastIndex;
  JSSymbol s_source;

  /* Methods. */
  JSSymbol s_compile;
  JSSymbol s_exec;
  JSSymbol s_test;

  /* Data that is needed for the static properties. */

  JSNode input;
  struct re_registers regs;
};

typedef struct regexp_ctx_st RegexpCtx;

/* RegExp instance context. */
struct regexp_instance_ctx_st
{
  /* The source for this regexp. */
  char *source;
  unsigned int source_len;

  /* Flags. */
  unsigned int global : 1;
  unsigned int ignore_case : 1;
  unsigned int immutable : 1;

  /* Compiled pattern. */
  struct re_pattern_buffer compiled;

  /* The index from which the next match is started. */
  unsigned int last_index;
};

typedef struct regexp_instance_ctx_st RegexpInstanceCtx;


/*
 * Prorototypes for some static functions.
 */

static void new_proc (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
		      JSNode *args, JSNode *result_return);


/*
 * Static functions.
 */

/* A helper for RegExp.exec().  XXX Check the compliancy. */
static void
do_exec (JSVirtualMachine *vm, RegexpCtx *ctx, RegexpInstanceCtx *ictx,
	 char *input, unsigned int input_len, JSNode *result_return)
{
  int result;
  int i, j;

  result = re_search (&ictx->compiled, input, input_len,
		      ictx->global ? ictx->last_index : 0,
		      input_len, &ctx->regs);

  if (result < 0)
    {
      result_return->type = JS_NULL;
      return;
    }

  /* Success.  Count how many matches we had. */
  for (i = 0; i < ctx->regs.num_regs && ctx->regs.start[i] >= 0; i++)
    ;

  /* Create the result array and enter the sub-matches. */
  js_vm_make_array (vm, result_return, i);

  for (j = 0; j < i; j++)
    js_vm_make_string (vm, &result_return->u.varray->data[j],
		       input + ctx->regs.start[j],
		       ctx->regs.end[j] - ctx->regs.start[j]);

  ictx->last_index = ctx->regs.end[0];
}

/* Method proc. */
static int
method (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
	void *instance_context, JSSymbol method, JSNode *result_return,
	JSNode *args)
{
  RegexpCtx *ctx = builtin_info->obj_context;
  RegexpInstanceCtx *ictx = instance_context;
  int result;
  int i;

  /* Set the default return value. */
  result_return->type = JS_BOOLEAN;
  result_return->u.vboolean = 1;

  /* Static methods. */
  if (method == vm->syms.s_toString)
    {
      if (ictx)
	js_vm_make_string (vm, result_return, ictx->source, ictx->source_len);
      else
	js_vm_make_static_string (vm, result_return, "RegExp", 6);
    }
  /* ********************************************************************** */
  else if (ictx)
    {
      /* Methods */

      if (method == ctx->s_compile)
	{
	  int global = 0;
	  int ignore_case = 0;
	  const char *error;
	  JSNode *pattern;
	  JSNode pattern_cvt;

	  if (ictx->immutable)
	    goto immutable;

	  if (args->u.vinteger != 1 && args->u.vinteger != 2)
	    goto argument_error;

	  if (args[1].type == JS_STRING)
	    pattern = &args[1];
	  else
	    {
	      js_vm_to_string (vm, &args[1], &pattern_cvt);
	      pattern = &pattern_cvt;
	    }

	  if (args->u.vinteger == 2)
	    {
	      JSNode *flags;
	      JSNode cvt;

	      if (args[2].type == JS_STRING)
		flags = &args[2];
	      else
		{
		  js_vm_to_string (vm, &args[2], &cvt);
		  flags = &cvt;
		}

	      for (i = 0; i < flags->u.vstring->len; i++)
		switch (flags->u.vstring->data[i])
		  {
		  case 'g':
		    global = 1;
		    break;

		  case 'i':
		    ignore_case = 1;
		    break;

		  default:
		    sprintf (vm->error, "new RegExp(): illegal flag `%c'",
			     flags->u.vstring->data[i]);
		    js_vm_error (vm);
		    break;
		  }
	    }

	  if (ictx->source)
	    js_free (ictx->source);

	  ictx->source_len = pattern->u.vstring->len;
	  ictx->source = js_malloc (vm, ictx->source_len);
	  memcpy (ictx->source, pattern->u.vstring->data, ictx->source_len);

	  ictx->global = global;
	  ictx->ignore_case = ignore_case;

	  if (ictx->compiled.fastmap)
	    js_free (ictx->compiled.fastmap);

	  memset (&ictx->compiled, 0, sizeof (ictx->compiled));

	  if (ictx->ignore_case)
	    ictx->compiled.translate = js_latin1_tolower;

	  error = re_compile_pattern (ictx->source, ictx->source_len,
				      &ictx->compiled);
	  if (error)
	    {
	      sprintf (vm->error,
		       "RegExp.%s(): compilation of the expression failed: %s",
		       js_vm_symname (vm, method), error);
	      js_vm_error (vm);
	    }
	  ictx->compiled.fastmap = js_malloc (vm, 256);
	  re_compile_fastmap (&ictx->compiled);
	}
      /* ***************************************************************** */
      else if (method == ctx->s_exec)
	{
	  char *input;
	  unsigned int input_len;
	  JSNode *input_str;
	  JSNode cvt;

	  if (args->u.vinteger == 0)
	    {
	      if (ctx->input.type == JS_STRING)
		input_str = &ctx->input;
	      else
		{
		  js_vm_to_string (vm, &ctx->input, &cvt);
		  input_str = &cvt;
		}

	      input = (char*)input_str->u.vstring->data;
	      input_len = input_str->u.vstring->len;
	    }
	  else if (args->u.vinteger == 1)
	    {
	      if (args[1].type == JS_STRING)
		input_str = &args[1];
	      else
		{
		  js_vm_to_string (vm, &args[1], &cvt);
		  input_str = &cvt;
		}

	      input = (char*)input_str->u.vstring->data;
	      input_len = input_str->u.vstring->len;

	      /* Set the input property to the class context. */
	      JS_COPY (&ctx->input, input_str);
	    }
	  else
	    goto argument_error;

	  do_exec (vm, ctx, ictx, input, input_len, result_return);
	}
      /* ***************************************************************** */
      else if (method == ctx->s_test)
	{
	  char *input;
	  unsigned int input_len;
	  JSNode *input_str;
	  JSNode cvt;

	  if (args->u.vinteger == 0)
	    {
	      if (ctx->input.type == JS_STRING)
		input_str = &ctx->input;
	      else
		{
		  js_vm_to_string (vm, &ctx->input, &cvt);
		  input_str = &cvt;
		}

	      input = (char*)input_str->u.vstring->data;
	      input_len = input_str->u.vstring->len;
	    }
	  else if (args->u.vinteger == 1)
	    {
	      if (args[1].type == JS_STRING)
		input_str = &args[1];
	      else
		{
		  js_vm_to_string (vm, &args[1], &cvt);
		  input_str = &cvt;
		}

	      input = (char*)input_str->u.vstring->data;
	      input_len = input_str->u.vstring->len;

	      /* Set the input property to the class context. */
	      JS_COPY (&ctx->input, input_str);
	    }
	  else
	    goto argument_error;

	  result = re_search (&ictx->compiled, input, input_len,
			      ictx->global ? ictx->last_index : 0,
			      input_len, &ctx->regs);

	  result_return->type = JS_BOOLEAN;
	  result_return->u.vboolean = result >= 0;

	  if (result >= 0)
	    /* ctx->regs.num_regs can be 0.  Or can it??? */
	    ictx->last_index = ctx->regs.end[0];
	}
      /* ***************************************************************** */
      else
	return JS_PROPERTY_UNKNOWN;
    }
  /* ********************************************************************** */
  else
    return JS_PROPERTY_UNKNOWN;

  return JS_PROPERTY_FOUND;


  /*
   * Error handling.
   */

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

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

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

  /* NOTREACHED. */
  return 0;
}

/* Global method proc. */
static void
global_method (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
	       void *instance_context, JSNode *result_return,
	       JSNode *args)
{
  RegexpCtx *ctx = builtin_info->obj_context;
  RegexpInstanceCtx *ictx = instance_context;
  char *input = NULL;		/* Initialized to keep the compiler quiet. */
  unsigned int input_len = 0;	/* Likewise. */

  if (ictx)
    {
      /* A RegExp instance was called as a function. */

      if (args->u.vinteger == 0)
	{
	  if (ctx->input.type != JS_STRING)
	    {
	      sprintf (vm->error, "RegExp(): RegExp.input is not a string");
	      js_vm_error (vm);
	    }
	  input = (char*)ctx->input.u.vstring->data;
	  input_len = ctx->input.u.vstring->len;
	}
      else if (args->u.vinteger == 1)
	{
	  if (args[1].type != JS_STRING)
	    {
	      sprintf (vm->error, "RegExp(): illegal argument");
	      js_vm_error (vm);
	    }

	  input = (char*)args[1].u.vstring->data;
	  input_len = args[1].u.vstring->len;

	  /* Set the input property to the class context. */
	  JS_COPY (&ctx->input, &args[1]);
	}
      else
	{
	  sprintf (vm->error, "RegExp(): illegal amount of arguments");
	  js_vm_error (vm);
	}

      do_exec (vm, ctx, ictx, input, input_len, result_return);
    }
  else
    {
      /*
       * The `RegExp' was called as a function.  We do exactly the
       * same the `new RegExp()' would do with our arguments.
       */
      new_proc (vm, builtin_info, args, result_return);
    }
}

/* Property proc. */
static int
property (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
	  void *instance_context, JSSymbol property, int set, JSNode *node)
{
  RegexpCtx *ctx = builtin_info->obj_context;
  RegexpInstanceCtx *ictx = instance_context;
  int index;

  /* Static properties. */
  if (property == ctx->s_S1)
    {
      index = 1;

    dollar_index:

      if (set)
	goto immutable;

      if (ctx->input.type != JS_STRING
	  || ctx->regs.end[0] > ctx->input.u.vstring->len
	  || ctx->regs.start[index] < 0)
	node->type = JS_UNDEFINED;
      else
	js_vm_make_string (vm, node,
			   (char*)ctx->input.u.vstring->data
			   + ctx->regs.start[index],
			   ctx->regs.end[index] - ctx->regs.start[index]);
    }
  /* ********************************************************************** */
  else if (property == ctx->s_S2)
    {
      index = 2;
      goto dollar_index;
    }
  /* ********************************************************************** */
  else if (property == ctx->s_S3)
    {
      index = 3;
      goto dollar_index;
    }
  /* ********************************************************************** */
  else if (property == ctx->s_S4)
    {
      index = 4;
      goto dollar_index;
    }
  /* ********************************************************************** */
  else if (property == ctx->s_S5)
    {
      index = 5;
      goto dollar_index;
    }
  /* ********************************************************************** */
  else if (property == ctx->s_S6)
    {
      index = 6;
      goto dollar_index;
    }
  /* ********************************************************************** */
  else if (property == ctx->s_S7)
    {
      index = 7;
      goto dollar_index;
    }
  /* ********************************************************************** */
  else if (property == ctx->s_S8)
    {
      index = 8;
      goto dollar_index;
    }
  /* ********************************************************************** */
  else if (property == ctx->s_S9)
    {
      index = 9;
      goto dollar_index;
    }
  /* ********************************************************************** */
  else if (property == ctx->s_S_ || property == ctx->s_input)
    {
      if (set)
	{
	  if (node->type != JS_STRING)
	    goto argument_type_error;

	  JS_COPY (&ctx->input, node);
	}
      else
	JS_COPY (node, &ctx->input);
    }
  /* ********************************************************************** */
  else if (property == ctx->s_lastMatch)
    {
      if (set)
	goto immutable;

      if (ctx->input.type != JS_STRING
	  || ctx->regs.end[0] > ctx->input.u.vstring->len)
	node->type = JS_UNDEFINED;
      else
	js_vm_make_string (vm, node,
			   (char*)ctx->input.u.vstring->data +
			   ctx->regs.start[0],
			   ctx->regs.end[0] - ctx->regs.start[0]);
    }
  /* ********************************************************************** */
  else if (property == ctx->s_lastParen)
    {
      if (set)
	goto immutable;

      if (ctx->input.type != JS_STRING
	  || ctx->regs.end[0] > ctx->input.u.vstring->len)
	node->type = JS_UNDEFINED;
      else
	{
	  int i;

	  for (i = 1; i < ctx->regs.num_regs && ctx->regs.start[i] >= 0; i++)
	    ;
	  i--;
	  if (i == 0)
	    node->type = JS_UNDEFINED;
	  else
	    js_vm_make_string (vm, node,
			       (char*)ctx->input.u.vstring->data

⌨️ 快捷键说明

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