/
dgd-rgx/
dgd-rgx/doc/
dgd-rgx/doc/kfun/
dgd-rgx/src/
dgd-rgx/src/regex/
# include "dgd.h"
# include "str.h"
# include "array.h"
# include "interpret.h"
# include "regex/regex.h"
# include "rgx.h"
# include <memory.h>

static char trans_table[256];

/*
 * NAME:	regexp->init()
 * DESCRIPTION:	initialize regexp handling
 */
void rgx_init()
{
  register int i;

  for (i = 0; i < 256; ++i)
    trans_table[i] = i;
  for (i = 'a'; i <= 'z'; ++i)
    trans_table[i] = i + 'A' - 'a';
}

/*
 * NAME:	regexp->new()
 * DESCRIPTION:	create a new regexp buffer
 */
array *rgx_new(pattern, case_matters)
string *pattern;
int case_matters;
{
  char *translate;
  struct re_pattern_buffer patbuf;
  char fastmap[256];
  const char *compile_error;
  array *result;
  register value *v;

  translate = (case_matters ? (char *) 0 : trans_table);

  patbuf.buffer    = 0;
  patbuf.allocated = 0;
  patbuf.used      = 0;

  patbuf.fastmap   = fastmap;
  patbuf.translate = translate;

  patbuf.fastmap_accurate = 0;

  compile_error = re_compile_pattern(pattern->text, pattern->len, &patbuf);
  if (compile_error != (char *) 0)
    {
      regfree(&patbuf);
      error(compile_error);
    }

  re_compile_fastmap(&patbuf);

  result = arr_new(3L);
  v = result->elts;

  v->type = T_STRING;
  str_ref(v->u.string = str_new((char *) &patbuf, (long) sizeof(patbuf)));
  ++v;
  v->type = T_STRING;
  str_ref(v->u.string = str_new((char *) patbuf.buffer,
				(long) patbuf.allocated));
  ++v;
  v->type = T_STRING;
  str_ref(v->u.string = str_new(fastmap, 256L));

  /* don't let regfree() try to free these */
  patbuf.fastmap   = 0;
  patbuf.translate = 0;

  regfree(&patbuf);

  return result;
}

/*
 * NAME:	regexp->match()
 * DESCRIPTION:	perform regexp matching, given a pattern and subject string
 */
array *rgx_match(pattern, subject, reverse)
value *pattern;
string *subject;
int reverse;
{
  long sub_len;
  struct re_pattern_buffer patbuf;
  struct re_registers regs;
  regoff_t starts[RGX_NREGS + 1], ends[RGX_NREGS + 1];
  array *result;
  register value *v;
  register int i;

  if (pattern[0].u.string->len != sizeof(struct re_pattern_buffer))
    error("Invalid compiled pattern");

  memcpy((char *) &patbuf, pattern[0].u.string->text,
	 sizeof(struct re_pattern_buffer));

  if (patbuf.allocated != (unsigned long) pattern[1].u.string->len ||
      pattern[2].u.string->len != 256)
    error("Invalid compiled pattern");

  patbuf.buffer  = (unsigned char *) pattern[1].u.string->text;
  patbuf.fastmap = pattern[2].u.string->text;

  regs.num_regs = RGX_NREGS;
  regs.start = starts;
  regs.end   = ends;
  patbuf.regs_allocated = REGS_FIXED;

  sub_len = subject->len;
  if (re_search(&patbuf, subject->text, sub_len, reverse ? sub_len : 0,
		reverse ? -(sub_len + 1) : sub_len + 1, &regs) == -1)
    return (array *) 0;

  result = arr_new((long) RGX_NREGS * 2);
  v = result->elts;

  v->type = T_INT;
  v->u.number = starts[0];
  ++v;

  v->type = T_INT;
  v->u.number = ends[0] - 1;
  ++v;

  for (i = 1; i < RGX_NREGS; ++i, v += 2)
    {
      v[0].type = T_INT;
      v[1].type = T_INT;

      if (starts[i] == -1)
	{
	  v[0].u.number = 0;
	  v[1].u.number = -1;
	}
      else
	{
	  v[0].u.number = starts[i];
	  v[1].u.number = ends[i] - 1;
	}
    }

  return result;
}