Blame src/regcomp.c

Packit b89d10
/**********************************************************************
Packit b89d10
  regcomp.c -  Oniguruma (regular expression library)
Packit b89d10
**********************************************************************/
Packit b89d10
/*-
Packit b89d10
 * Copyright (c) 2002-2018  K.Kosako  <sndgk393 AT ybb DOT ne DOT jp>
Packit b89d10
 * All rights reserved.
Packit b89d10
 *
Packit b89d10
 * Redistribution and use in source and binary forms, with or without
Packit b89d10
 * modification, are permitted provided that the following conditions
Packit b89d10
 * are met:
Packit b89d10
 * 1. Redistributions of source code must retain the above copyright
Packit b89d10
 *    notice, this list of conditions and the following disclaimer.
Packit b89d10
 * 2. Redistributions in binary form must reproduce the above copyright
Packit b89d10
 *    notice, this list of conditions and the following disclaimer in the
Packit b89d10
 *    documentation and/or other materials provided with the distribution.
Packit b89d10
 *
Packit b89d10
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
Packit b89d10
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit b89d10
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit b89d10
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
Packit b89d10
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit b89d10
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
Packit b89d10
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
Packit b89d10
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
Packit b89d10
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
Packit b89d10
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
Packit b89d10
 * SUCH DAMAGE.
Packit b89d10
 */
Packit b89d10
Packit b89d10
#include "regparse.h"
Packit b89d10
Packit b89d10
OnigCaseFoldType OnigDefaultCaseFoldFlag = ONIGENC_CASE_FOLD_MIN;
Packit b89d10
Packit b89d10
#if 0
Packit b89d10
typedef struct {
Packit b89d10
  int  n;
Packit b89d10
  int  alloc;
Packit b89d10
  int* v;
Packit b89d10
} int_stack;
Packit b89d10
Packit b89d10
static int
Packit b89d10
make_int_stack(int_stack** rs, int init_size)
Packit b89d10
{
Packit b89d10
  int_stack* s;
Packit b89d10
  int* v;
Packit b89d10
Packit b89d10
  *rs = 0;
Packit b89d10
Packit b89d10
  s = xmalloc(sizeof(*s));
Packit b89d10
  if (IS_NULL(s)) return ONIGERR_MEMORY;
Packit b89d10
Packit b89d10
  v = (int* )xmalloc(sizeof(int) * init_size);
Packit b89d10
  if (IS_NULL(v)) {
Packit b89d10
    xfree(s);
Packit b89d10
    return ONIGERR_MEMORY;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  s->n = 0;
Packit b89d10
  s->alloc = init_size;
Packit b89d10
  s->v = v;
Packit b89d10
Packit b89d10
  *rs = s;
Packit b89d10
  return ONIG_NORMAL;
Packit b89d10
}
Packit b89d10
Packit b89d10
static void
Packit b89d10
free_int_stack(int_stack* s)
Packit b89d10
{
Packit b89d10
  if (IS_NOT_NULL(s)) {
Packit b89d10
    if (IS_NOT_NULL(s->v))
Packit b89d10
      xfree(s->v);
Packit b89d10
    xfree(s);
Packit b89d10
  }
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
int_stack_push(int_stack* s, int v)
Packit b89d10
{
Packit b89d10
  if (s->n >= s->alloc) {
Packit b89d10
    int new_size = s->alloc * 2;
Packit b89d10
    int* nv = (int* )xrealloc(s->v, sizeof(int) * new_size);
Packit b89d10
    if (IS_NULL(nv)) return ONIGERR_MEMORY;
Packit b89d10
Packit b89d10
    s->alloc = new_size;
Packit b89d10
    s->v = nv;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  s->v[s->n] = v;
Packit b89d10
  s->n++;
Packit b89d10
  return ONIG_NORMAL;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
int_stack_pop(int_stack* s)
Packit b89d10
{
Packit b89d10
  int v;
Packit b89d10
Packit b89d10
#ifdef ONIG_DEBUG
Packit b89d10
  if (s->n <= 0) {
Packit b89d10
    fprintf(stderr, "int_stack_pop: fail empty. %p\n", s);
Packit b89d10
    return 0;
Packit b89d10
  }
Packit b89d10
#endif
Packit b89d10
Packit b89d10
  v = s->v[s->n];
Packit b89d10
  s->n--;
Packit b89d10
  return v;
Packit b89d10
}
Packit b89d10
#endif
Packit b89d10
Packit b89d10
extern OnigCaseFoldType
Packit b89d10
onig_get_default_case_fold_flag(void)
Packit b89d10
{
Packit b89d10
  return OnigDefaultCaseFoldFlag;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_set_default_case_fold_flag(OnigCaseFoldType case_fold_flag)
Packit b89d10
{
Packit b89d10
  OnigDefaultCaseFoldFlag = case_fold_flag;
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
int_multiply_cmp(int x, int y, int v)
Packit b89d10
{
Packit b89d10
  if (x == 0 || y == 0) return -1;
Packit b89d10
Packit b89d10
  if (x < INT_MAX / y) {
Packit b89d10
    int xy = x * y;
Packit b89d10
    if (xy > v) return 1;
Packit b89d10
    else {
Packit b89d10
      if (xy == v) return 0;
Packit b89d10
      else return -1;
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
  else
Packit b89d10
    return 1;
Packit b89d10
}
Packit b89d10
Packit b89d10
Packit b89d10
#ifndef PLATFORM_UNALIGNED_WORD_ACCESS
Packit b89d10
static unsigned char PadBuf[WORD_ALIGNMENT_SIZE];
Packit b89d10
#endif
Packit b89d10
Packit b89d10
static void
Packit b89d10
swap_node(Node* a, Node* b)
Packit b89d10
{
Packit b89d10
  Node c;
Packit b89d10
Packit b89d10
  c = *a; *a = *b; *b = c;
Packit b89d10
Packit b89d10
  if (NODE_TYPE(a) == NODE_STRING) {
Packit b89d10
    StrNode* sn = STR_(a);
Packit b89d10
    if (sn->capa == 0) {
Packit b89d10
      int len = (int )(sn->end - sn->s);
Packit b89d10
      sn->s   = sn->buf;
Packit b89d10
      sn->end = sn->s + len;
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
Packit b89d10
  if (NODE_TYPE(b) == NODE_STRING) {
Packit b89d10
    StrNode* sn = STR_(b);
Packit b89d10
    if (sn->capa == 0) {
Packit b89d10
      int len = (int )(sn->end - sn->s);
Packit b89d10
      sn->s   = sn->buf;
Packit b89d10
      sn->end = sn->s + len;
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
}
Packit b89d10
Packit b89d10
static OnigLen
Packit b89d10
distance_add(OnigLen d1, OnigLen d2)
Packit b89d10
{
Packit b89d10
  if (d1 == INFINITE_LEN || d2 == INFINITE_LEN)
Packit b89d10
    return INFINITE_LEN;
Packit b89d10
  else {
Packit b89d10
    if (d1 <= INFINITE_LEN - d2) return d1 + d2;
Packit b89d10
    else return INFINITE_LEN;
Packit b89d10
  }
Packit b89d10
}
Packit b89d10
Packit b89d10
static OnigLen
Packit b89d10
distance_multiply(OnigLen d, int m)
Packit b89d10
{
Packit b89d10
  if (m == 0) return 0;
Packit b89d10
Packit b89d10
  if (d < INFINITE_LEN / m)
Packit b89d10
    return d * m;
Packit b89d10
  else
Packit b89d10
    return INFINITE_LEN;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
bitset_is_empty(BitSetRef bs)
Packit b89d10
{
Packit b89d10
  int i;
Packit b89d10
Packit b89d10
  for (i = 0; i < (int )BITSET_SIZE; i++) {
Packit b89d10
    if (bs[i] != 0) return 0;
Packit b89d10
  }
Packit b89d10
  return 1;
Packit b89d10
}
Packit b89d10
Packit b89d10
extern int
Packit b89d10
onig_bbuf_init(BBuf* buf, int size)
Packit b89d10
{
Packit b89d10
  if (size <= 0) {
Packit b89d10
    size   = 0;
Packit b89d10
    buf->p = NULL;
Packit b89d10
  }
Packit b89d10
  else {
Packit b89d10
    buf->p = (UChar* )xmalloc(size);
Packit b89d10
    if (IS_NULL(buf->p)) return(ONIGERR_MEMORY);
Packit b89d10
  }
Packit b89d10
Packit b89d10
  buf->alloc = size;
Packit b89d10
  buf->used  = 0;
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
Packit b89d10
#ifdef USE_CALL
Packit b89d10
Packit b89d10
static int
Packit b89d10
unset_addr_list_init(UnsetAddrList* list, int size)
Packit b89d10
{
Packit b89d10
  UnsetAddr* p = (UnsetAddr* )xmalloc(sizeof(UnsetAddr)* size);
Packit b89d10
  CHECK_NULL_RETURN_MEMERR(p);
Packit b89d10
Packit b89d10
  list->num   = 0;
Packit b89d10
  list->alloc = size;
Packit b89d10
  list->us    = p;
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static void
Packit b89d10
unset_addr_list_end(UnsetAddrList* list)
Packit b89d10
{
Packit b89d10
  if (IS_NOT_NULL(list->us))
Packit b89d10
    xfree(list->us);
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
unset_addr_list_add(UnsetAddrList* list, int offset, struct _Node* node)
Packit b89d10
{
Packit b89d10
  UnsetAddr* p;
Packit b89d10
  int size;
Packit b89d10
Packit b89d10
  if (list->num >= list->alloc) {
Packit b89d10
    size = list->alloc * 2;
Packit b89d10
    p = (UnsetAddr* )xrealloc(list->us, sizeof(UnsetAddr) * size);
Packit b89d10
    CHECK_NULL_RETURN_MEMERR(p);
Packit b89d10
    list->alloc = size;
Packit b89d10
    list->us    = p;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  list->us[list->num].offset = offset;
Packit b89d10
  list->us[list->num].target = node;
Packit b89d10
  list->num++;
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
#endif /* USE_CALL */
Packit b89d10
Packit b89d10
Packit b89d10
static int
Packit b89d10
add_opcode(regex_t* reg, int opcode)
Packit b89d10
{
Packit b89d10
  BB_ADD1(reg, opcode);
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
add_rel_addr(regex_t* reg, int addr)
Packit b89d10
{
Packit b89d10
  RelAddrType ra = (RelAddrType )addr;
Packit b89d10
Packit b89d10
  BB_ADD(reg, &ra, SIZE_RELADDR);
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
add_abs_addr(regex_t* reg, int addr)
Packit b89d10
{
Packit b89d10
  AbsAddrType ra = (AbsAddrType )addr;
Packit b89d10
Packit b89d10
  BB_ADD(reg, &ra, SIZE_ABSADDR);
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
add_length(regex_t* reg, int len)
Packit b89d10
{
Packit b89d10
  LengthType l = (LengthType )len;
Packit b89d10
Packit b89d10
  BB_ADD(reg, &l, SIZE_LENGTH);
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
add_mem_num(regex_t* reg, int num)
Packit b89d10
{
Packit b89d10
  MemNumType n = (MemNumType )num;
Packit b89d10
Packit b89d10
  BB_ADD(reg, &n, SIZE_MEMNUM);
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
#if 0
Packit b89d10
static int
Packit b89d10
add_pointer(regex_t* reg, void* addr)
Packit b89d10
{
Packit b89d10
  PointerType ptr = (PointerType )addr;
Packit b89d10
Packit b89d10
  BB_ADD(reg, &ptr, SIZE_POINTER);
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
#endif
Packit b89d10
Packit b89d10
static int
Packit b89d10
add_option(regex_t* reg, OnigOptionType option)
Packit b89d10
{
Packit b89d10
  BB_ADD(reg, &option, SIZE_OPTION);
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
add_save_type(regex_t* reg, enum SaveType type)
Packit b89d10
{
Packit b89d10
  SaveType t = (SaveType )type;
Packit b89d10
Packit b89d10
  BB_ADD(reg, &t, SIZE_SAVE_TYPE);
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
add_update_var_type(regex_t* reg, enum UpdateVarType type)
Packit b89d10
{
Packit b89d10
  UpdateVarType t = (UpdateVarType )type;
Packit b89d10
Packit b89d10
  BB_ADD(reg, &t, SIZE_UPDATE_VAR_TYPE);
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
add_mode(regex_t* reg, ModeType mode)
Packit b89d10
{
Packit b89d10
  BB_ADD(reg, &mode, SIZE_MODE);
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
add_opcode_rel_addr(regex_t* reg, int opcode, int addr)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
Packit b89d10
  r = add_opcode(reg, opcode);
Packit b89d10
  if (r != 0) return r;
Packit b89d10
  r = add_rel_addr(reg, addr);
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
add_bytes(regex_t* reg, UChar* bytes, int len)
Packit b89d10
{
Packit b89d10
  BB_ADD(reg, bytes, len);
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
add_bitset(regex_t* reg, BitSetRef bs)
Packit b89d10
{
Packit b89d10
  BB_ADD(reg, bs, SIZE_BITSET);
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
add_opcode_option(regex_t* reg, int opcode, OnigOptionType option)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
Packit b89d10
  r = add_opcode(reg, opcode);
Packit b89d10
  if (r != 0) return r;
Packit b89d10
  r = add_option(reg, option);
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int compile_length_tree(Node* node, regex_t* reg);
Packit b89d10
static int compile_tree(Node* node, regex_t* reg, ScanEnv* env);
Packit b89d10
Packit b89d10
Packit b89d10
#define IS_NEED_STR_LEN_OP_EXACT(op) \
Packit b89d10
   ((op) == OP_EXACTN    || (op) == OP_EXACTMB2N ||\
Packit b89d10
    (op) == OP_EXACTMB3N || (op) == OP_EXACTMBN  || (op) == OP_EXACTN_IC)
Packit b89d10
Packit b89d10
static int
Packit b89d10
select_str_opcode(int mb_len, int str_len, int ignore_case)
Packit b89d10
{
Packit b89d10
  int op;
Packit b89d10
Packit b89d10
  if (ignore_case) {
Packit b89d10
    switch (str_len) {
Packit b89d10
    case 1:  op = OP_EXACT1_IC; break;
Packit b89d10
    default: op = OP_EXACTN_IC; break;
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
  else {
Packit b89d10
    switch (mb_len) {
Packit b89d10
    case 1:
Packit b89d10
      switch (str_len) {
Packit b89d10
      case 1:  op = OP_EXACT1; break;
Packit b89d10
      case 2:  op = OP_EXACT2; break;
Packit b89d10
      case 3:  op = OP_EXACT3; break;
Packit b89d10
      case 4:  op = OP_EXACT4; break;
Packit b89d10
      case 5:  op = OP_EXACT5; break;
Packit b89d10
      default: op = OP_EXACTN; break;
Packit b89d10
      }
Packit b89d10
      break;
Packit b89d10
Packit b89d10
    case 2:
Packit b89d10
      switch (str_len) {
Packit b89d10
      case 1:  op = OP_EXACTMB2N1; break;
Packit b89d10
      case 2:  op = OP_EXACTMB2N2; break;
Packit b89d10
      case 3:  op = OP_EXACTMB2N3; break;
Packit b89d10
      default: op = OP_EXACTMB2N;  break;
Packit b89d10
      }
Packit b89d10
      break;
Packit b89d10
Packit b89d10
    case 3:
Packit b89d10
      op = OP_EXACTMB3N;
Packit b89d10
      break;
Packit b89d10
Packit b89d10
    default:
Packit b89d10
      op = OP_EXACTMBN;
Packit b89d10
      break;
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
  return op;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
compile_tree_empty_check(Node* node, regex_t* reg, int empty_info, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
  int saved_num_null_check = reg->num_null_check;
Packit b89d10
Packit b89d10
  if (empty_info != QUANT_BODY_IS_NOT_EMPTY) {
Packit b89d10
    r = add_opcode(reg, OP_EMPTY_CHECK_START);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    r = add_mem_num(reg, reg->num_null_check); /* NULL CHECK ID */
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    reg->num_null_check++;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  r = compile_tree(node, reg, env);
Packit b89d10
  if (r != 0) return r;
Packit b89d10
Packit b89d10
  if (empty_info != QUANT_BODY_IS_NOT_EMPTY) {
Packit b89d10
    if (empty_info == QUANT_BODY_IS_EMPTY)
Packit b89d10
      r = add_opcode(reg, OP_EMPTY_CHECK_END);
Packit b89d10
    else if (empty_info == QUANT_BODY_IS_EMPTY_MEM)
Packit b89d10
      r = add_opcode(reg, OP_EMPTY_CHECK_END_MEMST);
Packit b89d10
    else if (empty_info == QUANT_BODY_IS_EMPTY_REC)
Packit b89d10
      r = add_opcode(reg, OP_EMPTY_CHECK_END_MEMST_PUSH);
Packit b89d10
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    r = add_mem_num(reg, saved_num_null_check); /* NULL CHECK ID */
Packit b89d10
  }
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
#ifdef USE_CALL
Packit b89d10
static int
Packit b89d10
compile_call(CallNode* node, regex_t* reg, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
Packit b89d10
  r = add_opcode(reg, OP_CALL);
Packit b89d10
  if (r != 0) return r;
Packit b89d10
  r = unset_addr_list_add(env->unset_addr_list, BB_GET_OFFSET_POS(reg),
Packit b89d10
                          NODE_CALL_BODY(node));
Packit b89d10
  if (r != 0) return r;
Packit b89d10
  r = add_abs_addr(reg, 0 /*dummy addr.*/);
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
#endif
Packit b89d10
Packit b89d10
static int
Packit b89d10
compile_tree_n_times(Node* node, int n, regex_t* reg, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  int i, r;
Packit b89d10
Packit b89d10
  for (i = 0; i < n; i++) {
Packit b89d10
    r = compile_tree(node, reg, env);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
  }
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
add_compile_string_length(UChar* s ARG_UNUSED, int mb_len, int str_len,
Packit b89d10
                          regex_t* reg ARG_UNUSED, int ignore_case)
Packit b89d10
{
Packit b89d10
  int len;
Packit b89d10
  int op = select_str_opcode(mb_len, str_len, ignore_case);
Packit b89d10
Packit b89d10
  len = SIZE_OPCODE;
Packit b89d10
Packit b89d10
  if (op == OP_EXACTMBN)  len += SIZE_LENGTH;
Packit b89d10
  if (IS_NEED_STR_LEN_OP_EXACT(op))
Packit b89d10
    len += SIZE_LENGTH;
Packit b89d10
Packit b89d10
  len += mb_len * str_len;
Packit b89d10
  return len;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
add_compile_string(UChar* s, int mb_len, int str_len,
Packit b89d10
                   regex_t* reg, int ignore_case)
Packit b89d10
{
Packit b89d10
  int op = select_str_opcode(mb_len, str_len, ignore_case);
Packit b89d10
  add_opcode(reg, op);
Packit b89d10
Packit b89d10
  if (op == OP_EXACTMBN)
Packit b89d10
    add_length(reg, mb_len);
Packit b89d10
Packit b89d10
  if (IS_NEED_STR_LEN_OP_EXACT(op)) {
Packit b89d10
    if (op == OP_EXACTN_IC)
Packit b89d10
      add_length(reg, mb_len * str_len);
Packit b89d10
    else
Packit b89d10
      add_length(reg, str_len);
Packit b89d10
  }
Packit b89d10
Packit b89d10
  add_bytes(reg, s, mb_len * str_len);
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
Packit b89d10
static int
Packit b89d10
compile_length_string_node(Node* node, regex_t* reg)
Packit b89d10
{
Packit b89d10
  int rlen, r, len, prev_len, slen, ambig;
Packit b89d10
  UChar *p, *prev;
Packit b89d10
  StrNode* sn;
Packit b89d10
  OnigEncoding enc = reg->enc;
Packit b89d10
Packit b89d10
  sn = STR_(node);
Packit b89d10
  if (sn->end <= sn->s)
Packit b89d10
    return 0;
Packit b89d10
Packit b89d10
  ambig = NODE_STRING_IS_AMBIG(node);
Packit b89d10
Packit b89d10
  p = prev = sn->s;
Packit b89d10
  prev_len = enclen(enc, p);
Packit b89d10
  p += prev_len;
Packit b89d10
  slen = 1;
Packit b89d10
  rlen = 0;
Packit b89d10
Packit b89d10
  for (; p < sn->end; ) {
Packit b89d10
    len = enclen(enc, p);
Packit b89d10
    if (len == prev_len) {
Packit b89d10
      slen++;
Packit b89d10
    }
Packit b89d10
    else {
Packit b89d10
      r = add_compile_string_length(prev, prev_len, slen, reg, ambig);
Packit b89d10
      rlen += r;
Packit b89d10
      prev = p;
Packit b89d10
      slen = 1;
Packit b89d10
      prev_len = len;
Packit b89d10
    }
Packit b89d10
    p += len;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  r = add_compile_string_length(prev, prev_len, slen, reg, ambig);
Packit b89d10
  rlen += r;
Packit b89d10
  return rlen;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
compile_length_string_raw_node(StrNode* sn, regex_t* reg)
Packit b89d10
{
Packit b89d10
  if (sn->end <= sn->s)
Packit b89d10
    return 0;
Packit b89d10
Packit b89d10
  return add_compile_string_length(sn->s, 1 /* sb */, (int )(sn->end - sn->s),
Packit b89d10
                                   reg, 0);
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
compile_string_node(Node* node, regex_t* reg)
Packit b89d10
{
Packit b89d10
  int r, len, prev_len, slen, ambig;
Packit b89d10
  UChar *p, *prev, *end;
Packit b89d10
  StrNode* sn;
Packit b89d10
  OnigEncoding enc = reg->enc;
Packit b89d10
Packit b89d10
  sn = STR_(node);
Packit b89d10
  if (sn->end <= sn->s)
Packit b89d10
    return 0;
Packit b89d10
Packit b89d10
  end = sn->end;
Packit b89d10
  ambig = NODE_STRING_IS_AMBIG(node);
Packit b89d10
Packit b89d10
  p = prev = sn->s;
Packit b89d10
  prev_len = enclen(enc, p);
Packit b89d10
  p += prev_len;
Packit b89d10
  slen = 1;
Packit b89d10
Packit b89d10
  for (; p < end; ) {
Packit b89d10
    len = enclen(enc, p);
Packit b89d10
    if (len == prev_len) {
Packit b89d10
      slen++;
Packit b89d10
    }
Packit b89d10
    else {
Packit b89d10
      r = add_compile_string(prev, prev_len, slen, reg, ambig);
Packit b89d10
      if (r != 0) return r;
Packit b89d10
Packit b89d10
      prev  = p;
Packit b89d10
      slen  = 1;
Packit b89d10
      prev_len = len;
Packit b89d10
    }
Packit b89d10
Packit b89d10
    p += len;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return add_compile_string(prev, prev_len, slen, reg, ambig);
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
compile_string_raw_node(StrNode* sn, regex_t* reg)
Packit b89d10
{
Packit b89d10
  if (sn->end <= sn->s)
Packit b89d10
    return 0;
Packit b89d10
Packit b89d10
  return add_compile_string(sn->s, 1 /* sb */, (int )(sn->end - sn->s), reg, 0);
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
add_multi_byte_cclass(BBuf* mbuf, regex_t* reg)
Packit b89d10
{
Packit b89d10
#ifdef PLATFORM_UNALIGNED_WORD_ACCESS
Packit b89d10
  add_length(reg, mbuf->used);
Packit b89d10
  return add_bytes(reg, mbuf->p, mbuf->used);
Packit b89d10
#else
Packit b89d10
  int r, pad_size;
Packit b89d10
  UChar* p = BB_GET_ADD_ADDRESS(reg) + SIZE_LENGTH;
Packit b89d10
Packit b89d10
  GET_ALIGNMENT_PAD_SIZE(p, pad_size);
Packit b89d10
  add_length(reg, mbuf->used + (WORD_ALIGNMENT_SIZE - 1));
Packit b89d10
  if (pad_size != 0) add_bytes(reg, PadBuf, pad_size);
Packit b89d10
Packit b89d10
  r = add_bytes(reg, mbuf->p, mbuf->used);
Packit b89d10
Packit b89d10
  /* padding for return value from compile_length_cclass_node() to be fix. */
Packit b89d10
  pad_size = (WORD_ALIGNMENT_SIZE - 1) - pad_size;
Packit b89d10
  if (pad_size != 0) add_bytes(reg, PadBuf, pad_size);
Packit b89d10
  return r;
Packit b89d10
#endif
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
compile_length_cclass_node(CClassNode* cc, regex_t* reg)
Packit b89d10
{
Packit b89d10
  int len;
Packit b89d10
Packit b89d10
  if (IS_NULL(cc->mbuf)) {
Packit b89d10
    len = SIZE_OPCODE + SIZE_BITSET;
Packit b89d10
  }
Packit b89d10
  else {
Packit b89d10
    if (ONIGENC_MBC_MINLEN(reg->enc) > 1 || bitset_is_empty(cc->bs)) {
Packit b89d10
      len = SIZE_OPCODE;
Packit b89d10
    }
Packit b89d10
    else {
Packit b89d10
      len = SIZE_OPCODE + SIZE_BITSET;
Packit b89d10
    }
Packit b89d10
#ifdef PLATFORM_UNALIGNED_WORD_ACCESS
Packit b89d10
    len += SIZE_LENGTH + cc->mbuf->used;
Packit b89d10
#else
Packit b89d10
    len += SIZE_LENGTH + cc->mbuf->used + (WORD_ALIGNMENT_SIZE - 1);
Packit b89d10
#endif
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return len;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
compile_cclass_node(CClassNode* cc, regex_t* reg)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
Packit b89d10
  if (IS_NULL(cc->mbuf)) {
Packit b89d10
    if (IS_NCCLASS_NOT(cc))
Packit b89d10
      add_opcode(reg, OP_CCLASS_NOT);
Packit b89d10
    else
Packit b89d10
      add_opcode(reg, OP_CCLASS);
Packit b89d10
Packit b89d10
    r = add_bitset(reg, cc->bs);
Packit b89d10
  }
Packit b89d10
  else {
Packit b89d10
    if (ONIGENC_MBC_MINLEN(reg->enc) > 1 || bitset_is_empty(cc->bs)) {
Packit b89d10
      if (IS_NCCLASS_NOT(cc))
Packit b89d10
        add_opcode(reg, OP_CCLASS_MB_NOT);
Packit b89d10
      else
Packit b89d10
        add_opcode(reg, OP_CCLASS_MB);
Packit b89d10
Packit b89d10
      r = add_multi_byte_cclass(cc->mbuf, reg);
Packit b89d10
    }
Packit b89d10
    else {
Packit b89d10
      if (IS_NCCLASS_NOT(cc))
Packit b89d10
        add_opcode(reg, OP_CCLASS_MIX_NOT);
Packit b89d10
      else
Packit b89d10
        add_opcode(reg, OP_CCLASS_MIX);
Packit b89d10
Packit b89d10
      r = add_bitset(reg, cc->bs);
Packit b89d10
      if (r != 0) return r;
Packit b89d10
      r = add_multi_byte_cclass(cc->mbuf, reg);
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
entry_repeat_range(regex_t* reg, int id, int lower, int upper)
Packit b89d10
{
Packit b89d10
#define REPEAT_RANGE_ALLOC  4
Packit b89d10
Packit b89d10
  OnigRepeatRange* p;
Packit b89d10
Packit b89d10
  if (reg->repeat_range_alloc == 0) {
Packit b89d10
    p = (OnigRepeatRange* )xmalloc(sizeof(OnigRepeatRange) * REPEAT_RANGE_ALLOC);
Packit b89d10
    CHECK_NULL_RETURN_MEMERR(p);
Packit b89d10
    reg->repeat_range = p;
Packit b89d10
    reg->repeat_range_alloc = REPEAT_RANGE_ALLOC;
Packit b89d10
  }
Packit b89d10
  else if (reg->repeat_range_alloc <= id) {
Packit b89d10
    int n;
Packit b89d10
    n = reg->repeat_range_alloc + REPEAT_RANGE_ALLOC;
Packit b89d10
    p = (OnigRepeatRange* )xrealloc(reg->repeat_range,
Packit b89d10
                                    sizeof(OnigRepeatRange) * n);
Packit b89d10
    CHECK_NULL_RETURN_MEMERR(p);
Packit b89d10
    reg->repeat_range = p;
Packit b89d10
    reg->repeat_range_alloc = n;
Packit b89d10
  }
Packit b89d10
  else {
Packit b89d10
    p = reg->repeat_range;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  p[id].lower = lower;
Packit b89d10
  p[id].upper = (IS_REPEAT_INFINITE(upper) ? 0x7fffffff : upper);
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
compile_range_repeat_node(QuantNode* qn, int target_len, int empty_info,
Packit b89d10
                          regex_t* reg, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
  int num_repeat = reg->num_repeat;
Packit b89d10
Packit b89d10
  r = add_opcode(reg, qn->greedy ? OP_REPEAT : OP_REPEAT_NG);
Packit b89d10
  if (r != 0) return r;
Packit b89d10
  r = add_mem_num(reg, num_repeat); /* OP_REPEAT ID */
Packit b89d10
  reg->num_repeat++;
Packit b89d10
  if (r != 0) return r;
Packit b89d10
  r = add_rel_addr(reg, target_len + SIZE_OP_REPEAT_INC);
Packit b89d10
  if (r != 0) return r;
Packit b89d10
Packit b89d10
  r = entry_repeat_range(reg, num_repeat, qn->lower, qn->upper);
Packit b89d10
  if (r != 0) return r;
Packit b89d10
Packit b89d10
  r = compile_tree_empty_check(NODE_QUANT_BODY(qn), reg, empty_info, env);
Packit b89d10
  if (r != 0) return r;
Packit b89d10
Packit b89d10
  if (
Packit b89d10
#ifdef USE_CALL
Packit b89d10
      NODE_IS_IN_MULTI_ENTRY(qn) ||
Packit b89d10
#endif
Packit b89d10
      NODE_IS_IN_REAL_REPEAT(qn)) {
Packit b89d10
    r = add_opcode(reg, qn->greedy ? OP_REPEAT_INC_SG : OP_REPEAT_INC_NG_SG);
Packit b89d10
  }
Packit b89d10
  else {
Packit b89d10
    r = add_opcode(reg, qn->greedy ? OP_REPEAT_INC : OP_REPEAT_INC_NG);
Packit b89d10
  }
Packit b89d10
  if (r != 0) return r;
Packit b89d10
  r = add_mem_num(reg, num_repeat); /* OP_REPEAT ID */
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
is_anychar_infinite_greedy(QuantNode* qn)
Packit b89d10
{
Packit b89d10
  if (qn->greedy && IS_REPEAT_INFINITE(qn->upper) &&
Packit b89d10
      NODE_IS_ANYCHAR(NODE_QUANT_BODY(qn)))
Packit b89d10
    return 1;
Packit b89d10
  else
Packit b89d10
    return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
#define QUANTIFIER_EXPAND_LIMIT_SIZE   50
Packit b89d10
#define CKN_ON   (ckn > 0)
Packit b89d10
Packit b89d10
static int
Packit b89d10
compile_length_quantifier_node(QuantNode* qn, regex_t* reg)
Packit b89d10
{
Packit b89d10
  int len, mod_tlen;
Packit b89d10
  int infinite = IS_REPEAT_INFINITE(qn->upper);
Packit b89d10
  enum QuantBodyEmpty empty_info = qn->body_empty_info;
Packit b89d10
  int tlen = compile_length_tree(NODE_QUANT_BODY(qn), reg);
Packit b89d10
Packit b89d10
  if (tlen < 0) return tlen;
Packit b89d10
  if (tlen == 0) return 0;
Packit b89d10
Packit b89d10
  /* anychar repeat */
Packit b89d10
  if (is_anychar_infinite_greedy(qn)) {
Packit b89d10
    if (qn->lower <= 1 ||
Packit b89d10
        int_multiply_cmp(tlen, qn->lower, QUANTIFIER_EXPAND_LIMIT_SIZE) <= 0) {
Packit b89d10
      if (IS_NOT_NULL(qn->next_head_exact))
Packit b89d10
        return SIZE_OP_ANYCHAR_STAR_PEEK_NEXT + tlen * qn->lower;
Packit b89d10
      else
Packit b89d10
        return SIZE_OP_ANYCHAR_STAR + tlen * qn->lower;
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
Packit b89d10
  if (empty_info == QUANT_BODY_IS_NOT_EMPTY)
Packit b89d10
    mod_tlen = tlen;
Packit b89d10
  else
Packit b89d10
    mod_tlen = tlen + (SIZE_OP_EMPTY_CHECK_START + SIZE_OP_EMPTY_CHECK_END);
Packit b89d10
Packit b89d10
  if (infinite &&
Packit b89d10
      (qn->lower <= 1 ||
Packit b89d10
       int_multiply_cmp(tlen, qn->lower, QUANTIFIER_EXPAND_LIMIT_SIZE) <= 0)) {
Packit b89d10
    if (qn->lower == 1 && tlen > QUANTIFIER_EXPAND_LIMIT_SIZE) {
Packit b89d10
      len = SIZE_OP_JUMP;
Packit b89d10
    }
Packit b89d10
    else {
Packit b89d10
      len = tlen * qn->lower;
Packit b89d10
    }
Packit b89d10
Packit b89d10
    if (qn->greedy) {
Packit b89d10
      if (IS_NOT_NULL(qn->head_exact))
Packit b89d10
        len += SIZE_OP_PUSH_OR_JUMP_EXACT1 + mod_tlen + SIZE_OP_JUMP;
Packit b89d10
      else if (IS_NOT_NULL(qn->next_head_exact))
Packit b89d10
        len += SIZE_OP_PUSH_IF_PEEK_NEXT + mod_tlen + SIZE_OP_JUMP;
Packit b89d10
      else
Packit b89d10
        len += SIZE_OP_PUSH + mod_tlen + SIZE_OP_JUMP;
Packit b89d10
    }
Packit b89d10
    else
Packit b89d10
      len += SIZE_OP_JUMP + mod_tlen + SIZE_OP_PUSH;
Packit b89d10
  }
Packit b89d10
  else if (qn->upper == 0 && qn->is_refered != 0) { /* /(?<n>..){0}/ */
Packit b89d10
    len = SIZE_OP_JUMP + tlen;
Packit b89d10
  }
Packit b89d10
  else if (!infinite && qn->greedy &&
Packit b89d10
           (qn->upper == 1 ||
Packit b89d10
            int_multiply_cmp(tlen + SIZE_OP_PUSH, qn->upper,
Packit b89d10
                             QUANTIFIER_EXPAND_LIMIT_SIZE) <= 0)) {
Packit b89d10
    len = tlen * qn->lower;
Packit b89d10
    len += (SIZE_OP_PUSH + tlen) * (qn->upper - qn->lower);
Packit b89d10
  }
Packit b89d10
  else if (!qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */
Packit b89d10
    len = SIZE_OP_PUSH + SIZE_OP_JUMP + tlen;
Packit b89d10
  }
Packit b89d10
  else {
Packit b89d10
    len = SIZE_OP_REPEAT_INC
Packit b89d10
        + mod_tlen + SIZE_OPCODE + SIZE_RELADDR + SIZE_MEMNUM;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return len;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
compile_quantifier_node(QuantNode* qn, regex_t* reg, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  int i, r, mod_tlen;
Packit b89d10
  int infinite = IS_REPEAT_INFINITE(qn->upper);
Packit b89d10
  enum QuantBodyEmpty empty_info = qn->body_empty_info;
Packit b89d10
  int tlen = compile_length_tree(NODE_QUANT_BODY(qn), reg);
Packit b89d10
Packit b89d10
  if (tlen < 0) return tlen;
Packit b89d10
  if (tlen == 0) return 0;
Packit b89d10
Packit b89d10
  if (is_anychar_infinite_greedy(qn) &&
Packit b89d10
      (qn->lower <= 1 ||
Packit b89d10
       int_multiply_cmp(tlen, qn->lower, QUANTIFIER_EXPAND_LIMIT_SIZE) <= 0)) {
Packit b89d10
    r = compile_tree_n_times(NODE_QUANT_BODY(qn), qn->lower, reg, env);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    if (IS_NOT_NULL(qn->next_head_exact)) {
Packit b89d10
      if (IS_MULTILINE(CTYPE_OPTION(NODE_QUANT_BODY(qn), reg)))
Packit b89d10
        r = add_opcode(reg, OP_ANYCHAR_ML_STAR_PEEK_NEXT);
Packit b89d10
      else
Packit b89d10
        r = add_opcode(reg, OP_ANYCHAR_STAR_PEEK_NEXT);
Packit b89d10
      if (r != 0) return r;
Packit b89d10
      return add_bytes(reg, STR_(qn->next_head_exact)->s, 1);
Packit b89d10
    }
Packit b89d10
    else {
Packit b89d10
      if (IS_MULTILINE(CTYPE_OPTION(NODE_QUANT_BODY(qn), reg)))
Packit b89d10
        return add_opcode(reg, OP_ANYCHAR_ML_STAR);
Packit b89d10
      else
Packit b89d10
        return add_opcode(reg, OP_ANYCHAR_STAR);
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
Packit b89d10
  if (empty_info == QUANT_BODY_IS_NOT_EMPTY)
Packit b89d10
    mod_tlen = tlen;
Packit b89d10
  else
Packit b89d10
    mod_tlen = tlen + (SIZE_OP_EMPTY_CHECK_START + SIZE_OP_EMPTY_CHECK_END);
Packit b89d10
Packit b89d10
  if (infinite &&
Packit b89d10
      (qn->lower <= 1 ||
Packit b89d10
       int_multiply_cmp(tlen, qn->lower, QUANTIFIER_EXPAND_LIMIT_SIZE) <= 0)) {
Packit b89d10
    if (qn->lower == 1 && tlen > QUANTIFIER_EXPAND_LIMIT_SIZE) {
Packit b89d10
      if (qn->greedy) {
Packit b89d10
        if (IS_NOT_NULL(qn->head_exact))
Packit b89d10
          r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH_OR_JUMP_EXACT1);
Packit b89d10
        else if (IS_NOT_NULL(qn->next_head_exact))
Packit b89d10
          r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH_IF_PEEK_NEXT);
Packit b89d10
        else
Packit b89d10
          r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH);
Packit b89d10
      }
Packit b89d10
      else {
Packit b89d10
        r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_JUMP);
Packit b89d10
      }
Packit b89d10
      if (r != 0) return r;
Packit b89d10
    }
Packit b89d10
    else {
Packit b89d10
      r = compile_tree_n_times(NODE_QUANT_BODY(qn), qn->lower, reg, env);
Packit b89d10
      if (r != 0) return r;
Packit b89d10
    }
Packit b89d10
Packit b89d10
    if (qn->greedy) {
Packit b89d10
      if (IS_NOT_NULL(qn->head_exact)) {
Packit b89d10
        r = add_opcode_rel_addr(reg, OP_PUSH_OR_JUMP_EXACT1,
Packit b89d10
                                mod_tlen + SIZE_OP_JUMP);
Packit b89d10
        if (r != 0) return r;
Packit b89d10
        add_bytes(reg, STR_(qn->head_exact)->s, 1);
Packit b89d10
        r = compile_tree_empty_check(NODE_QUANT_BODY(qn), reg, empty_info, env);
Packit b89d10
        if (r != 0) return r;
Packit b89d10
        r = add_opcode_rel_addr(reg, OP_JUMP,
Packit b89d10
           -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH_OR_JUMP_EXACT1));
Packit b89d10
      }
Packit b89d10
      else if (IS_NOT_NULL(qn->next_head_exact)) {
Packit b89d10
        r = add_opcode_rel_addr(reg, OP_PUSH_IF_PEEK_NEXT,
Packit b89d10
                                mod_tlen + SIZE_OP_JUMP);
Packit b89d10
        if (r != 0) return r;
Packit b89d10
        add_bytes(reg, STR_(qn->next_head_exact)->s, 1);
Packit b89d10
        r = compile_tree_empty_check(NODE_QUANT_BODY(qn), reg, empty_info, env);
Packit b89d10
        if (r != 0) return r;
Packit b89d10
        r = add_opcode_rel_addr(reg, OP_JUMP,
Packit b89d10
           -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH_IF_PEEK_NEXT));
Packit b89d10
      }
Packit b89d10
      else {
Packit b89d10
        r = add_opcode_rel_addr(reg, OP_PUSH, mod_tlen + SIZE_OP_JUMP);
Packit b89d10
        if (r != 0) return r;
Packit b89d10
        r = compile_tree_empty_check(NODE_QUANT_BODY(qn), reg, empty_info, env);
Packit b89d10
        if (r != 0) return r;
Packit b89d10
        r = add_opcode_rel_addr(reg, OP_JUMP,
Packit b89d10
                   -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH));
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    else {
Packit b89d10
      r = add_opcode_rel_addr(reg, OP_JUMP, mod_tlen);
Packit b89d10
      if (r != 0) return r;
Packit b89d10
      r = compile_tree_empty_check(NODE_QUANT_BODY(qn), reg, empty_info, env);
Packit b89d10
      if (r != 0) return r;
Packit b89d10
      r = add_opcode_rel_addr(reg, OP_PUSH, -(mod_tlen + (int )SIZE_OP_PUSH));
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
  else if (qn->upper == 0 && qn->is_refered != 0) { /* /(?<n>..){0}/ */
Packit b89d10
    r = add_opcode_rel_addr(reg, OP_JUMP, tlen);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    r = compile_tree(NODE_QUANT_BODY(qn), reg, env);
Packit b89d10
  }
Packit b89d10
  else if (! infinite && qn->greedy &&
Packit b89d10
           (qn->upper == 1 ||
Packit b89d10
            int_multiply_cmp(tlen + SIZE_OP_PUSH, qn->upper,
Packit b89d10
                             QUANTIFIER_EXPAND_LIMIT_SIZE) <= 0)) {
Packit b89d10
    int n = qn->upper - qn->lower;
Packit b89d10
Packit b89d10
    r = compile_tree_n_times(NODE_QUANT_BODY(qn), qn->lower, reg, env);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
Packit b89d10
    for (i = 0; i < n; i++) {
Packit b89d10
      r = add_opcode_rel_addr(reg, OP_PUSH,
Packit b89d10
                              (n - i) * tlen + (n - i - 1) * SIZE_OP_PUSH);
Packit b89d10
      if (r != 0) return r;
Packit b89d10
      r = compile_tree(NODE_QUANT_BODY(qn), reg, env);
Packit b89d10
      if (r != 0) return r;
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
  else if (! qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */
Packit b89d10
    r = add_opcode_rel_addr(reg, OP_PUSH, SIZE_OP_JUMP);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    r = add_opcode_rel_addr(reg, OP_JUMP, tlen);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    r = compile_tree(NODE_QUANT_BODY(qn), reg, env);
Packit b89d10
  }
Packit b89d10
  else {
Packit b89d10
    r = compile_range_repeat_node(qn, mod_tlen, empty_info, reg, env);
Packit b89d10
  }
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
compile_length_option_node(EnclosureNode* node, regex_t* reg)
Packit b89d10
{
Packit b89d10
  int tlen;
Packit b89d10
  OnigOptionType prev = reg->options;
Packit b89d10
Packit b89d10
  reg->options = node->o.options;
Packit b89d10
  tlen = compile_length_tree(NODE_ENCLOSURE_BODY(node), reg);
Packit b89d10
  reg->options = prev;
Packit b89d10
Packit b89d10
  if (tlen < 0) return tlen;
Packit b89d10
Packit b89d10
  if (IS_DYNAMIC_OPTION(prev ^ node->option)) {
Packit b89d10
    return SIZE_OP_SET_OPTION_PUSH + SIZE_OP_SET_OPTION + SIZE_OP_FAIL
Packit b89d10
           + tlen + SIZE_OP_SET_OPTION;
Packit b89d10
  }
Packit b89d10
  else
Packit b89d10
    return tlen;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
compile_option_node(EnclosureNode* node, regex_t* reg, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
  OnigOptionType prev = reg->options;
Packit b89d10
Packit b89d10
  if (IS_DYNAMIC_OPTION(prev ^ node->o.options)) {
Packit b89d10
    r = add_opcode_option(reg, OP_SET_OPTION_PUSH, node->o.options);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    r = add_opcode_option(reg, OP_SET_OPTION, prev);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    r = add_opcode(reg, OP_FAIL);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  reg->options = node->o.options;
Packit b89d10
  r = compile_tree(NODE_ENCLOSURE_BODY(node), reg, env);
Packit b89d10
  reg->options = prev;
Packit b89d10
Packit b89d10
  if (IS_DYNAMIC_OPTION(prev ^ node->o.options)) {
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    r = add_opcode_option(reg, OP_SET_OPTION, prev);
Packit b89d10
  }
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
compile_length_enclosure_node(EnclosureNode* node, regex_t* reg)
Packit b89d10
{
Packit b89d10
  int len;
Packit b89d10
  int tlen;
Packit b89d10
Packit b89d10
  if (node->type == ENCLOSURE_OPTION)
Packit b89d10
    return compile_length_option_node(node, reg);
Packit b89d10
Packit b89d10
  if (NODE_ENCLOSURE_BODY(node)) {
Packit b89d10
    tlen = compile_length_tree(NODE_ENCLOSURE_BODY(node), reg);
Packit b89d10
    if (tlen < 0) return tlen;
Packit b89d10
  }
Packit b89d10
  else
Packit b89d10
    tlen = 0;
Packit b89d10
Packit b89d10
  switch (node->type) {
Packit b89d10
  case ENCLOSURE_MEMORY:
Packit b89d10
#ifdef USE_CALL
Packit b89d10
Packit b89d10
    if (node->m.regnum == 0 && NODE_IS_CALLED(node)) {
Packit b89d10
      len = tlen + SIZE_OP_CALL + SIZE_OP_JUMP + SIZE_OP_RETURN;
Packit b89d10
      return len;
Packit b89d10
    }
Packit b89d10
Packit b89d10
    if (NODE_IS_CALLED(node)) {
Packit b89d10
      len = SIZE_OP_MEMORY_START_PUSH + tlen
Packit b89d10
        + SIZE_OP_CALL + SIZE_OP_JUMP + SIZE_OP_RETURN;
Packit b89d10
      if (MEM_STATUS_AT0(reg->bt_mem_end, node->m.regnum))
Packit b89d10
        len += (NODE_IS_RECURSION(node)
Packit b89d10
                ? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_PUSH);
Packit b89d10
      else
Packit b89d10
        len += (NODE_IS_RECURSION(node)
Packit b89d10
                ? SIZE_OP_MEMORY_END_REC : SIZE_OP_MEMORY_END);
Packit b89d10
    }
Packit b89d10
    else if (NODE_IS_RECURSION(node)) {
Packit b89d10
      len = SIZE_OP_MEMORY_START_PUSH;
Packit b89d10
      len += tlen + (MEM_STATUS_AT0(reg->bt_mem_end, node->m.regnum)
Packit b89d10
                     ? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_REC);
Packit b89d10
    }
Packit b89d10
    else
Packit b89d10
#endif
Packit b89d10
    {
Packit b89d10
      if (MEM_STATUS_AT0(reg->bt_mem_start, node->m.regnum))
Packit b89d10
        len = SIZE_OP_MEMORY_START_PUSH;
Packit b89d10
      else
Packit b89d10
        len = SIZE_OP_MEMORY_START;
Packit b89d10
Packit b89d10
      len += tlen + (MEM_STATUS_AT0(reg->bt_mem_end, node->m.regnum)
Packit b89d10
                     ? SIZE_OP_MEMORY_END_PUSH : SIZE_OP_MEMORY_END);
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case ENCLOSURE_STOP_BACKTRACK:
Packit b89d10
    if (NODE_IS_STOP_BT_SIMPLE_REPEAT(node)) {
Packit b89d10
      QuantNode* qn = QUANT_(NODE_ENCLOSURE_BODY(node));
Packit b89d10
      tlen = compile_length_tree(NODE_QUANT_BODY(qn), reg);
Packit b89d10
      if (tlen < 0) return tlen;
Packit b89d10
Packit b89d10
      len = tlen * qn->lower
Packit b89d10
        + SIZE_OP_PUSH + tlen + SIZE_OP_POP_OUT + SIZE_OP_JUMP;
Packit b89d10
    }
Packit b89d10
    else {
Packit b89d10
      len = SIZE_OP_ATOMIC_START + tlen + SIZE_OP_ATOMIC_END;
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case ENCLOSURE_IF_ELSE:
Packit b89d10
    {
Packit b89d10
      Node* cond = NODE_ENCLOSURE_BODY(node);
Packit b89d10
      Node* Then = node->te.Then;
Packit b89d10
      Node* Else = node->te.Else;
Packit b89d10
Packit b89d10
      len = compile_length_tree(cond, reg);
Packit b89d10
      if (len < 0) return len;
Packit b89d10
      len += SIZE_OP_PUSH;
Packit b89d10
      len += SIZE_OP_ATOMIC_START + SIZE_OP_ATOMIC_END;
Packit b89d10
Packit b89d10
      if (IS_NOT_NULL(Then)) {
Packit b89d10
        tlen = compile_length_tree(Then, reg);
Packit b89d10
        if (tlen < 0) return tlen;
Packit b89d10
        len += tlen;
Packit b89d10
      }
Packit b89d10
Packit b89d10
      if (IS_NOT_NULL(Else)) {
Packit b89d10
        len += SIZE_OP_JUMP;
Packit b89d10
        tlen = compile_length_tree(Else, reg);
Packit b89d10
        if (tlen < 0) return tlen;
Packit b89d10
        len += tlen;
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  default:
Packit b89d10
    return ONIGERR_TYPE_BUG;
Packit b89d10
    break;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return len;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int get_char_length_tree(Node* node, regex_t* reg, int* len);
Packit b89d10
Packit b89d10
static int
Packit b89d10
compile_enclosure_memory_node(EnclosureNode* node, regex_t* reg, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
  int len;
Packit b89d10
Packit b89d10
#ifdef USE_CALL
Packit b89d10
  if (node->m.regnum == 0 && NODE_IS_CALLED(node)) {
Packit b89d10
    r = add_opcode(reg, OP_CALL);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    node->m.called_addr = BB_GET_OFFSET_POS(reg) + SIZE_ABSADDR + SIZE_OP_JUMP;
Packit b89d10
    NODE_STATUS_ADD(node, NST_ADDR_FIXED);
Packit b89d10
    r = add_abs_addr(reg, (int )node->m.called_addr);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    len = compile_length_tree(NODE_ENCLOSURE_BODY(node), reg);
Packit b89d10
    len += SIZE_OP_RETURN;
Packit b89d10
    r = add_opcode_rel_addr(reg, OP_JUMP, len);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
Packit b89d10
    r = compile_tree(NODE_ENCLOSURE_BODY(node), reg, env);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    r = add_opcode(reg, OP_RETURN);
Packit b89d10
    return r;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  if (NODE_IS_CALLED(node)) {
Packit b89d10
    r = add_opcode(reg, OP_CALL);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    node->m.called_addr = BB_GET_OFFSET_POS(reg) + SIZE_ABSADDR + SIZE_OP_JUMP;
Packit b89d10
    NODE_STATUS_ADD(node, NST_ADDR_FIXED);
Packit b89d10
    r = add_abs_addr(reg, (int )node->m.called_addr);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    len = compile_length_tree(NODE_ENCLOSURE_BODY(node), reg);
Packit b89d10
    len += (SIZE_OP_MEMORY_START_PUSH + SIZE_OP_RETURN);
Packit b89d10
    if (MEM_STATUS_AT0(reg->bt_mem_end, node->m.regnum))
Packit b89d10
      len += (NODE_IS_RECURSION(node)
Packit b89d10
              ? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_PUSH);
Packit b89d10
    else
Packit b89d10
      len += (NODE_IS_RECURSION(node)
Packit b89d10
              ? SIZE_OP_MEMORY_END_REC : SIZE_OP_MEMORY_END);
Packit b89d10
Packit b89d10
    r = add_opcode_rel_addr(reg, OP_JUMP, len);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
  }
Packit b89d10
#endif
Packit b89d10
Packit b89d10
  if (MEM_STATUS_AT0(reg->bt_mem_start, node->m.regnum))
Packit b89d10
    r = add_opcode(reg, OP_MEMORY_START_PUSH);
Packit b89d10
  else
Packit b89d10
    r = add_opcode(reg, OP_MEMORY_START);
Packit b89d10
  if (r != 0) return r;
Packit b89d10
  r = add_mem_num(reg, node->m.regnum);
Packit b89d10
  if (r != 0) return r;
Packit b89d10
  r = compile_tree(NODE_ENCLOSURE_BODY(node), reg, env);
Packit b89d10
  if (r != 0) return r;
Packit b89d10
Packit b89d10
#ifdef USE_CALL
Packit b89d10
  if (MEM_STATUS_AT0(reg->bt_mem_end, node->m.regnum))
Packit b89d10
    r = add_opcode(reg, (NODE_IS_RECURSION(node)
Packit b89d10
                         ? OP_MEMORY_END_PUSH_REC : OP_MEMORY_END_PUSH));
Packit b89d10
  else
Packit b89d10
    r = add_opcode(reg, (NODE_IS_RECURSION(node)
Packit b89d10
                         ? OP_MEMORY_END_REC : OP_MEMORY_END));
Packit b89d10
  if (r != 0) return r;
Packit b89d10
  r = add_mem_num(reg, node->m.regnum);
Packit b89d10
  if (NODE_IS_CALLED(node)) {
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    r = add_opcode(reg, OP_RETURN);
Packit b89d10
  }
Packit b89d10
#else
Packit b89d10
  if (MEM_STATUS_AT0(reg->bt_mem_end, node->m.regnum))
Packit b89d10
    r = add_opcode(reg, OP_MEMORY_END_PUSH);
Packit b89d10
  else
Packit b89d10
    r = add_opcode(reg, OP_MEMORY_END);
Packit b89d10
  if (r != 0) return r;
Packit b89d10
  r = add_mem_num(reg, node->m.regnum);
Packit b89d10
#endif
Packit b89d10
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
compile_enclosure_node(EnclosureNode* node, regex_t* reg, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  int r, len;
Packit b89d10
Packit b89d10
  switch (node->type) {
Packit b89d10
  case ENCLOSURE_MEMORY:
Packit b89d10
    r = compile_enclosure_memory_node(node, reg, env);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case ENCLOSURE_OPTION:
Packit b89d10
    r = compile_option_node(node, reg, env);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case ENCLOSURE_STOP_BACKTRACK:
Packit b89d10
    if (NODE_IS_STOP_BT_SIMPLE_REPEAT(node)) {
Packit b89d10
      QuantNode* qn = QUANT_(NODE_ENCLOSURE_BODY(node));
Packit b89d10
      r = compile_tree_n_times(NODE_QUANT_BODY(qn), qn->lower, reg, env);
Packit b89d10
      if (r != 0) return r;
Packit b89d10
Packit b89d10
      len = compile_length_tree(NODE_QUANT_BODY(qn), reg);
Packit b89d10
      if (len < 0) return len;
Packit b89d10
Packit b89d10
      r = add_opcode_rel_addr(reg, OP_PUSH, len + SIZE_OP_POP_OUT + SIZE_OP_JUMP);
Packit b89d10
      if (r != 0) return r;
Packit b89d10
      r = compile_tree(NODE_QUANT_BODY(qn), reg, env);
Packit b89d10
      if (r != 0) return r;
Packit b89d10
      r = add_opcode(reg, OP_POP_OUT);
Packit b89d10
      if (r != 0) return r;
Packit b89d10
      r = add_opcode_rel_addr(reg, OP_JUMP,
Packit b89d10
           -((int )SIZE_OP_PUSH + len + (int )SIZE_OP_POP_OUT + (int )SIZE_OP_JUMP));
Packit b89d10
    }
Packit b89d10
    else {
Packit b89d10
      r = add_opcode(reg, OP_ATOMIC_START);
Packit b89d10
      if (r != 0) return r;
Packit b89d10
      r = compile_tree(NODE_ENCLOSURE_BODY(node), reg, env);
Packit b89d10
      if (r != 0) return r;
Packit b89d10
      r = add_opcode(reg, OP_ATOMIC_END);
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case ENCLOSURE_IF_ELSE:
Packit b89d10
    {
Packit b89d10
      int cond_len, then_len, jump_len;
Packit b89d10
      Node* cond = NODE_ENCLOSURE_BODY(node);
Packit b89d10
      Node* Then = node->te.Then;
Packit b89d10
      Node* Else = node->te.Else;
Packit b89d10
Packit b89d10
      r = add_opcode(reg, OP_ATOMIC_START);
Packit b89d10
      if (r != 0) return r;
Packit b89d10
Packit b89d10
      cond_len = compile_length_tree(cond, reg);
Packit b89d10
      if (cond_len < 0) return cond_len;
Packit b89d10
      if (IS_NOT_NULL(Then)) {
Packit b89d10
        then_len = compile_length_tree(Then, reg);
Packit b89d10
        if (then_len < 0) return then_len;
Packit b89d10
      }
Packit b89d10
      else
Packit b89d10
        then_len = 0;
Packit b89d10
Packit b89d10
      jump_len = cond_len + then_len + SIZE_OP_ATOMIC_END;
Packit b89d10
      if (IS_NOT_NULL(Else)) jump_len += SIZE_OP_JUMP;
Packit b89d10
Packit b89d10
      r = add_opcode_rel_addr(reg, OP_PUSH, jump_len);
Packit b89d10
      if (r != 0) return r;
Packit b89d10
      r = compile_tree(cond, reg, env);
Packit b89d10
      if (r != 0) return r;
Packit b89d10
      r = add_opcode(reg, OP_ATOMIC_END);
Packit b89d10
      if (r != 0) return r;
Packit b89d10
Packit b89d10
      if (IS_NOT_NULL(Then)) {
Packit b89d10
        r = compile_tree(Then, reg, env);
Packit b89d10
        if (r != 0) return r;
Packit b89d10
      }
Packit b89d10
Packit b89d10
      if (IS_NOT_NULL(Else)) {
Packit b89d10
        int else_len = compile_length_tree(Else, reg);
Packit b89d10
        r = add_opcode_rel_addr(reg, OP_JUMP, else_len);
Packit b89d10
        if (r != 0) return r;
Packit b89d10
        r = compile_tree(Else, reg, env);
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  default:
Packit b89d10
    return ONIGERR_TYPE_BUG;
Packit b89d10
    break;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
compile_length_anchor_node(AnchorNode* node, regex_t* reg)
Packit b89d10
{
Packit b89d10
  int len;
Packit b89d10
  int tlen = 0;
Packit b89d10
Packit b89d10
  if (IS_NOT_NULL(NODE_ANCHOR_BODY(node))) {
Packit b89d10
    tlen = compile_length_tree(NODE_ANCHOR_BODY(node), reg);
Packit b89d10
    if (tlen < 0) return tlen;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  switch (node->type) {
Packit b89d10
  case ANCHOR_PREC_READ:
Packit b89d10
    len = SIZE_OP_PREC_READ_START + tlen + SIZE_OP_PREC_READ_END;
Packit b89d10
    break;
Packit b89d10
  case ANCHOR_PREC_READ_NOT:
Packit b89d10
    len = SIZE_OP_PREC_READ_NOT_START + tlen + SIZE_OP_PREC_READ_NOT_END;
Packit b89d10
    break;
Packit b89d10
  case ANCHOR_LOOK_BEHIND:
Packit b89d10
    len = SIZE_OP_LOOK_BEHIND + tlen;
Packit b89d10
    break;
Packit b89d10
  case ANCHOR_LOOK_BEHIND_NOT:
Packit b89d10
    len = SIZE_OP_LOOK_BEHIND_NOT_START + tlen + SIZE_OP_LOOK_BEHIND_NOT_END;
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case ANCHOR_WORD_BOUNDARY:
Packit b89d10
  case ANCHOR_NO_WORD_BOUNDARY:
Packit b89d10
#ifdef USE_WORD_BEGIN_END
Packit b89d10
  case ANCHOR_WORD_BEGIN:
Packit b89d10
  case ANCHOR_WORD_END:
Packit b89d10
#endif
Packit b89d10
    len = SIZE_OP_WORD_BOUNDARY;
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case ANCHOR_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY:
Packit b89d10
  case ANCHOR_NO_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY:
Packit b89d10
    len = SIZE_OPCODE;
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  default:
Packit b89d10
    len = SIZE_OPCODE;
Packit b89d10
    break;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return len;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
compile_anchor_node(AnchorNode* node, regex_t* reg, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  int r, len;
Packit b89d10
  enum OpCode op;
Packit b89d10
Packit b89d10
  switch (node->type) {
Packit b89d10
  case ANCHOR_BEGIN_BUF:      r = add_opcode(reg, OP_BEGIN_BUF);      break;
Packit b89d10
  case ANCHOR_END_BUF:        r = add_opcode(reg, OP_END_BUF);        break;
Packit b89d10
  case ANCHOR_BEGIN_LINE:     r = add_opcode(reg, OP_BEGIN_LINE);     break;
Packit b89d10
  case ANCHOR_END_LINE:       r = add_opcode(reg, OP_END_LINE);       break;
Packit b89d10
  case ANCHOR_SEMI_END_BUF:   r = add_opcode(reg, OP_SEMI_END_BUF);   break;
Packit b89d10
  case ANCHOR_BEGIN_POSITION: r = add_opcode(reg, OP_BEGIN_POSITION); break;
Packit b89d10
Packit b89d10
  case ANCHOR_WORD_BOUNDARY:
Packit b89d10
    op = OP_WORD_BOUNDARY;
Packit b89d10
  word:
Packit b89d10
    r = add_opcode(reg, op);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    r = add_mode(reg, (ModeType )node->ascii_mode);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case ANCHOR_NO_WORD_BOUNDARY:
Packit b89d10
    op = OP_NO_WORD_BOUNDARY; goto word;
Packit b89d10
    break;
Packit b89d10
#ifdef USE_WORD_BEGIN_END
Packit b89d10
  case ANCHOR_WORD_BEGIN:
Packit b89d10
    op = OP_WORD_BEGIN; goto word;
Packit b89d10
    break;
Packit b89d10
  case ANCHOR_WORD_END:
Packit b89d10
    op = OP_WORD_END; goto word;
Packit b89d10
    break;
Packit b89d10
#endif
Packit b89d10
Packit b89d10
  case ANCHOR_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY:
Packit b89d10
    r = add_opcode(reg, OP_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case ANCHOR_NO_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY:
Packit b89d10
    r = add_opcode(reg, OP_NO_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case ANCHOR_PREC_READ:
Packit b89d10
    r = add_opcode(reg, OP_PREC_READ_START);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    r = compile_tree(NODE_ANCHOR_BODY(node), reg, env);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    r = add_opcode(reg, OP_PREC_READ_END);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case ANCHOR_PREC_READ_NOT:
Packit b89d10
    len = compile_length_tree(NODE_ANCHOR_BODY(node), reg);
Packit b89d10
    if (len < 0) return len;
Packit b89d10
    r = add_opcode_rel_addr(reg, OP_PREC_READ_NOT_START, len + SIZE_OP_PREC_READ_NOT_END);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    r = compile_tree(NODE_ANCHOR_BODY(node), reg, env);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    r = add_opcode(reg, OP_PREC_READ_NOT_END);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case ANCHOR_LOOK_BEHIND:
Packit b89d10
    {
Packit b89d10
      int n;
Packit b89d10
      r = add_opcode(reg, OP_LOOK_BEHIND);
Packit b89d10
      if (r != 0) return r;
Packit b89d10
      if (node->char_len < 0) {
Packit b89d10
        r = get_char_length_tree(NODE_ANCHOR_BODY(node), reg, &n);
Packit b89d10
        if (r != 0) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
Packit b89d10
      }
Packit b89d10
      else
Packit b89d10
        n = node->char_len;
Packit b89d10
Packit b89d10
      r = add_length(reg, n);
Packit b89d10
      if (r != 0) return r;
Packit b89d10
      r = compile_tree(NODE_ANCHOR_BODY(node), reg, env);
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case ANCHOR_LOOK_BEHIND_NOT:
Packit b89d10
    {
Packit b89d10
      int n;
Packit b89d10
Packit b89d10
      len = compile_length_tree(NODE_ANCHOR_BODY(node), reg);
Packit b89d10
      r = add_opcode_rel_addr(reg, OP_LOOK_BEHIND_NOT_START,
Packit b89d10
                              len + SIZE_OP_LOOK_BEHIND_NOT_END);
Packit b89d10
      if (r != 0) return r;
Packit b89d10
      if (node->char_len < 0) {
Packit b89d10
        r = get_char_length_tree(NODE_ANCHOR_BODY(node), reg, &n);
Packit b89d10
        if (r != 0) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
Packit b89d10
      }
Packit b89d10
      else
Packit b89d10
        n = node->char_len;
Packit b89d10
      r = add_length(reg, n);
Packit b89d10
      if (r != 0) return r;
Packit b89d10
      r = compile_tree(NODE_ANCHOR_BODY(node), reg, env);
Packit b89d10
      if (r != 0) return r;
Packit b89d10
      r = add_opcode(reg, OP_LOOK_BEHIND_NOT_END);
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  default:
Packit b89d10
    return ONIGERR_TYPE_BUG;
Packit b89d10
    break;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
compile_gimmick_node(GimmickNode* node, regex_t* reg)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
Packit b89d10
  switch (node->type) {
Packit b89d10
  case GIMMICK_FAIL:
Packit b89d10
    r = add_opcode(reg, OP_FAIL);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case GIMMICK_KEEP:
Packit b89d10
    r = add_opcode(reg, OP_PUSH_SAVE_VAL);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    r = add_save_type(reg, SAVE_KEEP);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    r = add_mem_num(reg, node->id);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case GIMMICK_SAVE:
Packit b89d10
    r = add_opcode(reg, OP_PUSH_SAVE_VAL);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    r = add_save_type(reg, node->detail_type);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    r = add_mem_num(reg, node->id);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case GIMMICK_UPDATE_VAR:
Packit b89d10
    r = add_opcode(reg, OP_UPDATE_VAR);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    r = add_update_var_type(reg, node->detail_type);
Packit b89d10
    if (r != 0) return r;
Packit b89d10
    r = add_mem_num(reg, node->id);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
#ifdef USE_CALLOUT
Packit b89d10
  case GIMMICK_CALLOUT:
Packit b89d10
    switch (node->detail_type) {
Packit b89d10
    case ONIG_CALLOUT_OF_CONTENTS:
Packit b89d10
    case ONIG_CALLOUT_OF_NAME:
Packit b89d10
      {
Packit b89d10
        r = add_opcode(reg, (node->detail_type == ONIG_CALLOUT_OF_CONTENTS) ?
Packit b89d10
                                  OP_CALLOUT_CONTENTS : OP_CALLOUT_NAME);
Packit b89d10
        if (r != 0) return r;
Packit b89d10
        if (node->detail_type == ONIG_CALLOUT_OF_NAME) {
Packit b89d10
          r = add_mem_num(reg, node->id);
Packit b89d10
          if (r != 0) return r;
Packit b89d10
        }
Packit b89d10
        r = add_mem_num(reg, node->num);
Packit b89d10
        if (r != 0) return r;
Packit b89d10
      }
Packit b89d10
      break;
Packit b89d10
Packit b89d10
    default:
Packit b89d10
      r = ONIGERR_TYPE_BUG;
Packit b89d10
      break;
Packit b89d10
    }
Packit b89d10
#endif
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
compile_length_gimmick_node(GimmickNode* node, regex_t* reg)
Packit b89d10
{
Packit b89d10
  int len;
Packit b89d10
Packit b89d10
  switch (node->type) {
Packit b89d10
  case GIMMICK_FAIL:
Packit b89d10
    len = SIZE_OP_FAIL;
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case GIMMICK_KEEP:
Packit b89d10
  case GIMMICK_SAVE:
Packit b89d10
    len = SIZE_OP_PUSH_SAVE_VAL;
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case GIMMICK_UPDATE_VAR:
Packit b89d10
    len = SIZE_OP_UPDATE_VAR;
Packit b89d10
    break;
Packit b89d10
Packit b89d10
#ifdef USE_CALLOUT
Packit b89d10
  case GIMMICK_CALLOUT:
Packit b89d10
    switch (node->detail_type) {
Packit b89d10
    case ONIG_CALLOUT_OF_CONTENTS:
Packit b89d10
      len = SIZE_OP_CALLOUT_CONTENTS;
Packit b89d10
      break;
Packit b89d10
    case ONIG_CALLOUT_OF_NAME:
Packit b89d10
      len = SIZE_OP_CALLOUT_NAME;
Packit b89d10
      break;
Packit b89d10
Packit b89d10
    default:
Packit b89d10
      len = ONIGERR_TYPE_BUG;
Packit b89d10
      break;
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
#endif
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return len;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
compile_length_tree(Node* node, regex_t* reg)
Packit b89d10
{
Packit b89d10
  int len, r;
Packit b89d10
Packit b89d10
  switch (NODE_TYPE(node)) {
Packit b89d10
  case NODE_LIST:
Packit b89d10
    len = 0;
Packit b89d10
    do {
Packit b89d10
      r = compile_length_tree(NODE_CAR(node), reg);
Packit b89d10
      if (r < 0) return r;
Packit b89d10
      len += r;
Packit b89d10
    } while (IS_NOT_NULL(node = NODE_CDR(node)));
Packit b89d10
    r = len;
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ALT:
Packit b89d10
    {
Packit b89d10
      int n;
Packit b89d10
Packit b89d10
      n = r = 0;
Packit b89d10
      do {
Packit b89d10
        r += compile_length_tree(NODE_CAR(node), reg);
Packit b89d10
        n++;
Packit b89d10
      } while (IS_NOT_NULL(node = NODE_CDR(node)));
Packit b89d10
      r += (SIZE_OP_PUSH + SIZE_OP_JUMP) * (n - 1);
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_STRING:
Packit b89d10
    if (NODE_STRING_IS_RAW(node))
Packit b89d10
      r = compile_length_string_raw_node(STR_(node), reg);
Packit b89d10
    else
Packit b89d10
      r = compile_length_string_node(node, reg);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_CCLASS:
Packit b89d10
    r = compile_length_cclass_node(CCLASS_(node), reg);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_CTYPE:
Packit b89d10
    r = SIZE_OPCODE;
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_BACKREF:
Packit b89d10
    {
Packit b89d10
      BackRefNode* br = BACKREF_(node);
Packit b89d10
Packit b89d10
      if (NODE_IS_CHECKER(node)) {
Packit b89d10
#ifdef USE_BACKREF_WITH_LEVEL
Packit b89d10
        if (NODE_IS_NEST_LEVEL(node)) {
Packit b89d10
          r = SIZE_OPCODE + SIZE_LENGTH + SIZE_LENGTH + (SIZE_MEMNUM * br->back_num);
Packit b89d10
        }
Packit b89d10
        else
Packit b89d10
#endif
Packit b89d10
          r = SIZE_OPCODE + SIZE_LENGTH + (SIZE_MEMNUM * br->back_num);
Packit b89d10
      }
Packit b89d10
      else {
Packit b89d10
#ifdef USE_BACKREF_WITH_LEVEL
Packit b89d10
        if (NODE_IS_NEST_LEVEL(node)) {
Packit b89d10
          r = SIZE_OPCODE + SIZE_OPTION + SIZE_LENGTH +
Packit b89d10
            SIZE_LENGTH + (SIZE_MEMNUM * br->back_num);
Packit b89d10
        }
Packit b89d10
        else
Packit b89d10
#endif
Packit b89d10
        if (br->back_num == 1) {
Packit b89d10
          r = ((!IS_IGNORECASE(reg->options) && br->back_static[0] <= 2)
Packit b89d10
               ? SIZE_OPCODE : (SIZE_OPCODE + SIZE_MEMNUM));
Packit b89d10
        }
Packit b89d10
        else {
Packit b89d10
          r = SIZE_OPCODE + SIZE_LENGTH + (SIZE_MEMNUM * br->back_num);
Packit b89d10
        }
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
#ifdef USE_CALL
Packit b89d10
  case NODE_CALL:
Packit b89d10
    r = SIZE_OP_CALL;
Packit b89d10
    break;
Packit b89d10
#endif
Packit b89d10
Packit b89d10
  case NODE_QUANT:
Packit b89d10
    r = compile_length_quantifier_node(QUANT_(node), reg);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ENCLOSURE:
Packit b89d10
    r = compile_length_enclosure_node(ENCLOSURE_(node), reg);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ANCHOR:
Packit b89d10
    r = compile_length_anchor_node(ANCHOR_(node), reg);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_GIMMICK:
Packit b89d10
    r = compile_length_gimmick_node(GIMMICK_(node), reg);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  default:
Packit b89d10
    return ONIGERR_TYPE_BUG;
Packit b89d10
    break;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
compile_tree(Node* node, regex_t* reg, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  int n, len, pos, r = 0;
Packit b89d10
Packit b89d10
  switch (NODE_TYPE(node)) {
Packit b89d10
  case NODE_LIST:
Packit b89d10
    do {
Packit b89d10
      r = compile_tree(NODE_CAR(node), reg, env);
Packit b89d10
    } while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ALT:
Packit b89d10
    {
Packit b89d10
      Node* x = node;
Packit b89d10
      len = 0;
Packit b89d10
      do {
Packit b89d10
        len += compile_length_tree(NODE_CAR(x), reg);
Packit b89d10
        if (IS_NOT_NULL(NODE_CDR(x))) {
Packit b89d10
          len += SIZE_OP_PUSH + SIZE_OP_JUMP;
Packit b89d10
        }
Packit b89d10
      } while (IS_NOT_NULL(x = NODE_CDR(x)));
Packit b89d10
      pos = reg->used + len;  /* goal position */
Packit b89d10
Packit b89d10
      do {
Packit b89d10
        len = compile_length_tree(NODE_CAR(node), reg);
Packit b89d10
        if (IS_NOT_NULL(NODE_CDR(node))) {
Packit b89d10
          enum OpCode push = NODE_IS_SUPER(node) ? OP_PUSH_SUPER : OP_PUSH;
Packit b89d10
          r = add_opcode_rel_addr(reg, push, len + SIZE_OP_JUMP);
Packit b89d10
          if (r != 0) break;
Packit b89d10
        }
Packit b89d10
        r = compile_tree(NODE_CAR(node), reg, env);
Packit b89d10
        if (r != 0) break;
Packit b89d10
        if (IS_NOT_NULL(NODE_CDR(node))) {
Packit b89d10
          len = pos - (reg->used + SIZE_OP_JUMP);
Packit b89d10
          r = add_opcode_rel_addr(reg, OP_JUMP, len);
Packit b89d10
          if (r != 0) break;
Packit b89d10
        }
Packit b89d10
      } while (IS_NOT_NULL(node = NODE_CDR(node)));
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_STRING:
Packit b89d10
    if (NODE_STRING_IS_RAW(node))
Packit b89d10
      r = compile_string_raw_node(STR_(node), reg);
Packit b89d10
    else
Packit b89d10
      r = compile_string_node(node, reg);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_CCLASS:
Packit b89d10
    r = compile_cclass_node(CCLASS_(node), reg);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_CTYPE:
Packit b89d10
    {
Packit b89d10
      int op;
Packit b89d10
Packit b89d10
      switch (CTYPE_(node)->ctype) {
Packit b89d10
      case CTYPE_ANYCHAR:
Packit b89d10
        if (IS_MULTILINE(CTYPE_OPTION(node, reg)))
Packit b89d10
          r = add_opcode(reg, OP_ANYCHAR_ML);
Packit b89d10
        else
Packit b89d10
          r = add_opcode(reg, OP_ANYCHAR);
Packit b89d10
        break;
Packit b89d10
Packit b89d10
      case ONIGENC_CTYPE_WORD:
Packit b89d10
        if (CTYPE_(node)->ascii_mode == 0) {
Packit b89d10
          op = CTYPE_(node)->not != 0 ? OP_NO_WORD : OP_WORD;
Packit b89d10
        }
Packit b89d10
        else {
Packit b89d10
          op = CTYPE_(node)->not != 0 ? OP_NO_WORD_ASCII : OP_WORD_ASCII;
Packit b89d10
        }
Packit b89d10
        r = add_opcode(reg, op);
Packit b89d10
        break;
Packit b89d10
Packit b89d10
      default:
Packit b89d10
        return ONIGERR_TYPE_BUG;
Packit b89d10
        break;
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_BACKREF:
Packit b89d10
    {
Packit b89d10
      BackRefNode* br = BACKREF_(node);
Packit b89d10
Packit b89d10
      if (NODE_IS_CHECKER(node)) {
Packit b89d10
#ifdef USE_BACKREF_WITH_LEVEL
Packit b89d10
        if (NODE_IS_NEST_LEVEL(node)) {
Packit b89d10
          r = add_opcode(reg, OP_BACKREF_CHECK_WITH_LEVEL);
Packit b89d10
          if (r != 0) return r;
Packit b89d10
          r = add_length(reg, br->nest_level);
Packit b89d10
          if (r != 0) return r;
Packit b89d10
        }
Packit b89d10
        else
Packit b89d10
#endif
Packit b89d10
          {
Packit b89d10
            r = add_opcode(reg, OP_BACKREF_CHECK);
Packit b89d10
            if (r != 0) return r;
Packit b89d10
          }
Packit b89d10
Packit b89d10
        goto add_bacref_mems;
Packit b89d10
      }
Packit b89d10
      else {
Packit b89d10
#ifdef USE_BACKREF_WITH_LEVEL
Packit b89d10
        if (NODE_IS_NEST_LEVEL(node)) {
Packit b89d10
          r = add_opcode(reg, OP_BACKREF_WITH_LEVEL);
Packit b89d10
          if (r != 0) return r;
Packit b89d10
          r = add_option(reg, (reg->options & ONIG_OPTION_IGNORECASE));
Packit b89d10
          if (r != 0) return r;
Packit b89d10
          r = add_length(reg, br->nest_level);
Packit b89d10
          if (r != 0) return r;
Packit b89d10
Packit b89d10
          goto add_bacref_mems;
Packit b89d10
        }
Packit b89d10
        else
Packit b89d10
#endif
Packit b89d10
        if (br->back_num == 1) {
Packit b89d10
          n = br->back_static[0];
Packit b89d10
          if (IS_IGNORECASE(reg->options)) {
Packit b89d10
            r = add_opcode(reg, OP_BACKREF_N_IC);
Packit b89d10
            if (r != 0) return r;
Packit b89d10
            r = add_mem_num(reg, n);
Packit b89d10
          }
Packit b89d10
          else {
Packit b89d10
            switch (n) {
Packit b89d10
            case 1:  r = add_opcode(reg, OP_BACKREF1); break;
Packit b89d10
            case 2:  r = add_opcode(reg, OP_BACKREF2); break;
Packit b89d10
            default:
Packit b89d10
              r = add_opcode(reg, OP_BACKREF_N);
Packit b89d10
              if (r != 0) return r;
Packit b89d10
              r = add_mem_num(reg, n);
Packit b89d10
              break;
Packit b89d10
            }
Packit b89d10
          }
Packit b89d10
        }
Packit b89d10
        else {
Packit b89d10
          int i;
Packit b89d10
          int* p;
Packit b89d10
Packit b89d10
          if (IS_IGNORECASE(reg->options)) {
Packit b89d10
            r = add_opcode(reg, OP_BACKREF_MULTI_IC);
Packit b89d10
          }
Packit b89d10
          else {
Packit b89d10
            r = add_opcode(reg, OP_BACKREF_MULTI);
Packit b89d10
          }
Packit b89d10
          if (r != 0) return r;
Packit b89d10
Packit b89d10
        add_bacref_mems:
Packit b89d10
          r = add_length(reg, br->back_num);
Packit b89d10
          if (r != 0) return r;
Packit b89d10
          p = BACKREFS_P(br);
Packit b89d10
          for (i = br->back_num - 1; i >= 0; i--) {
Packit b89d10
            r = add_mem_num(reg, p[i]);
Packit b89d10
            if (r != 0) return r;
Packit b89d10
          }
Packit b89d10
        }
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
#ifdef USE_CALL
Packit b89d10
  case NODE_CALL:
Packit b89d10
    r = compile_call(CALL_(node), reg, env);
Packit b89d10
    break;
Packit b89d10
#endif
Packit b89d10
Packit b89d10
  case NODE_QUANT:
Packit b89d10
    r = compile_quantifier_node(QUANT_(node), reg, env);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ENCLOSURE:
Packit b89d10
    r = compile_enclosure_node(ENCLOSURE_(node), reg, env);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ANCHOR:
Packit b89d10
    r = compile_anchor_node(ANCHOR_(node), reg, env);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_GIMMICK:
Packit b89d10
    r = compile_gimmick_node(GIMMICK_(node), reg);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  default:
Packit b89d10
#ifdef ONIG_DEBUG
Packit b89d10
    fprintf(stderr, "compile_tree: undefined node type %d\n", NODE_TYPE(node));
Packit b89d10
#endif
Packit b89d10
    break;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
noname_disable_map(Node** plink, GroupNumRemap* map, int* counter)
Packit b89d10
{
Packit b89d10
  int r = 0;
Packit b89d10
  Node* node = *plink;
Packit b89d10
Packit b89d10
  switch (NODE_TYPE(node)) {
Packit b89d10
  case NODE_LIST:
Packit b89d10
  case NODE_ALT:
Packit b89d10
    do {
Packit b89d10
      r = noname_disable_map(&(NODE_CAR(node)), map, counter);
Packit b89d10
    } while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_QUANT:
Packit b89d10
    {
Packit b89d10
      Node** ptarget = &(NODE_BODY(node));
Packit b89d10
      Node*  old = *ptarget;
Packit b89d10
      r = noname_disable_map(ptarget, map, counter);
Packit b89d10
      if (*ptarget != old && NODE_TYPE(*ptarget) == NODE_QUANT) {
Packit b89d10
        onig_reduce_nested_quantifier(node, *ptarget);
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ENCLOSURE:
Packit b89d10
    {
Packit b89d10
      EnclosureNode* en = ENCLOSURE_(node);
Packit b89d10
      if (en->type == ENCLOSURE_MEMORY) {
Packit b89d10
        if (NODE_IS_NAMED_GROUP(node)) {
Packit b89d10
          (*counter)++;
Packit b89d10
          map[en->m.regnum].new_val = *counter;
Packit b89d10
          en->m.regnum = *counter;
Packit b89d10
          r = noname_disable_map(&(NODE_BODY(node)), map, counter);
Packit b89d10
        }
Packit b89d10
        else {
Packit b89d10
          *plink = NODE_BODY(node);
Packit b89d10
          NODE_BODY(node) = NULL_NODE;
Packit b89d10
          onig_node_free(node);
Packit b89d10
          r = noname_disable_map(plink, map, counter);
Packit b89d10
        }
Packit b89d10
      }
Packit b89d10
      else if (en->type == ENCLOSURE_IF_ELSE) {
Packit b89d10
        r = noname_disable_map(&(NODE_ENCLOSURE_BODY(en)), map, counter);
Packit b89d10
        if (r != 0) return r;
Packit b89d10
        if (IS_NOT_NULL(en->te.Then)) {
Packit b89d10
          r = noname_disable_map(&(en->te.Then), map, counter);
Packit b89d10
          if (r != 0) return r;
Packit b89d10
        }
Packit b89d10
        if (IS_NOT_NULL(en->te.Else)) {
Packit b89d10
          r = noname_disable_map(&(en->te.Else), map, counter);
Packit b89d10
          if (r != 0) return r;
Packit b89d10
        }
Packit b89d10
      }
Packit b89d10
      else
Packit b89d10
        r = noname_disable_map(&(NODE_BODY(node)), map, counter);
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ANCHOR:
Packit b89d10
    if (IS_NOT_NULL(NODE_BODY(node)))
Packit b89d10
      r = noname_disable_map(&(NODE_BODY(node)), map, counter);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  default:
Packit b89d10
    break;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
renumber_node_backref(Node* node, GroupNumRemap* map)
Packit b89d10
{
Packit b89d10
  int i, pos, n, old_num;
Packit b89d10
  int *backs;
Packit b89d10
  BackRefNode* bn = BACKREF_(node);
Packit b89d10
Packit b89d10
  if (! NODE_IS_BY_NAME(node))
Packit b89d10
    return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;
Packit b89d10
Packit b89d10
  old_num = bn->back_num;
Packit b89d10
  if (IS_NULL(bn->back_dynamic))
Packit b89d10
    backs = bn->back_static;
Packit b89d10
  else
Packit b89d10
    backs = bn->back_dynamic;
Packit b89d10
Packit b89d10
  for (i = 0, pos = 0; i < old_num; i++) {
Packit b89d10
    n = map[backs[i]].new_val;
Packit b89d10
    if (n > 0) {
Packit b89d10
      backs[pos] = n;
Packit b89d10
      pos++;
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
Packit b89d10
  bn->back_num = pos;
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
renumber_by_map(Node* node, GroupNumRemap* map)
Packit b89d10
{
Packit b89d10
  int r = 0;
Packit b89d10
Packit b89d10
  switch (NODE_TYPE(node)) {
Packit b89d10
  case NODE_LIST:
Packit b89d10
  case NODE_ALT:
Packit b89d10
    do {
Packit b89d10
      r = renumber_by_map(NODE_CAR(node), map);
Packit b89d10
    } while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_QUANT:
Packit b89d10
    r = renumber_by_map(NODE_BODY(node), map);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ENCLOSURE:
Packit b89d10
    {
Packit b89d10
      EnclosureNode* en = ENCLOSURE_(node);
Packit b89d10
Packit b89d10
      r = renumber_by_map(NODE_BODY(node), map);
Packit b89d10
      if (r != 0) return r;
Packit b89d10
Packit b89d10
      if (en->type == ENCLOSURE_IF_ELSE) {
Packit b89d10
        if (IS_NOT_NULL(en->te.Then)) {
Packit b89d10
          r = renumber_by_map(en->te.Then, map);
Packit b89d10
          if (r != 0) return r;
Packit b89d10
        }
Packit b89d10
        if (IS_NOT_NULL(en->te.Else)) {
Packit b89d10
          r = renumber_by_map(en->te.Else, map);
Packit b89d10
          if (r != 0) return r;
Packit b89d10
        }
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_BACKREF:
Packit b89d10
    r = renumber_node_backref(node, map);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ANCHOR:
Packit b89d10
    if (IS_NOT_NULL(NODE_BODY(node)))
Packit b89d10
      r = renumber_by_map(NODE_BODY(node), map);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  default:
Packit b89d10
    break;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
numbered_ref_check(Node* node)
Packit b89d10
{
Packit b89d10
  int r = 0;
Packit b89d10
Packit b89d10
  switch (NODE_TYPE(node)) {
Packit b89d10
  case NODE_LIST:
Packit b89d10
  case NODE_ALT:
Packit b89d10
    do {
Packit b89d10
      r = numbered_ref_check(NODE_CAR(node));
Packit b89d10
    } while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ANCHOR:
Packit b89d10
    if (IS_NULL(NODE_BODY(node)))
Packit b89d10
      break;
Packit b89d10
    /* fall */
Packit b89d10
  case NODE_QUANT:
Packit b89d10
    r = numbered_ref_check(NODE_BODY(node));
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ENCLOSURE:
Packit b89d10
    {
Packit b89d10
      EnclosureNode* en = ENCLOSURE_(node);
Packit b89d10
Packit b89d10
      r = numbered_ref_check(NODE_BODY(node));
Packit b89d10
      if (r != 0) return r;
Packit b89d10
Packit b89d10
      if (en->type == ENCLOSURE_IF_ELSE) {
Packit b89d10
        if (IS_NOT_NULL(en->te.Then)) {
Packit b89d10
          r = numbered_ref_check(en->te.Then);
Packit b89d10
          if (r != 0) return r;
Packit b89d10
        }
Packit b89d10
        if (IS_NOT_NULL(en->te.Else)) {
Packit b89d10
          r = numbered_ref_check(en->te.Else);
Packit b89d10
          if (r != 0) return r;
Packit b89d10
        }
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_BACKREF:
Packit b89d10
    if (! NODE_IS_BY_NAME(node))
Packit b89d10
      return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  default:
Packit b89d10
    break;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
disable_noname_group_capture(Node** root, regex_t* reg, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  int r, i, pos, counter;
Packit b89d10
  MemStatusType loc;
Packit b89d10
  GroupNumRemap* map;
Packit b89d10
Packit b89d10
  map = (GroupNumRemap* )xalloca(sizeof(GroupNumRemap) * (env->num_mem + 1));
Packit b89d10
  CHECK_NULL_RETURN_MEMERR(map);
Packit b89d10
  for (i = 1; i <= env->num_mem; i++) {
Packit b89d10
    map[i].new_val = 0;
Packit b89d10
  }
Packit b89d10
  counter = 0;
Packit b89d10
  r = noname_disable_map(root, map, &counter);
Packit b89d10
  if (r != 0) return r;
Packit b89d10
Packit b89d10
  r = renumber_by_map(*root, map);
Packit b89d10
  if (r != 0) return r;
Packit b89d10
Packit b89d10
  for (i = 1, pos = 1; i <= env->num_mem; i++) {
Packit b89d10
    if (map[i].new_val > 0) {
Packit b89d10
      SCANENV_MEMENV(env)[pos] = SCANENV_MEMENV(env)[i];
Packit b89d10
      pos++;
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
Packit b89d10
  loc = env->capture_history;
Packit b89d10
  MEM_STATUS_CLEAR(env->capture_history);
Packit b89d10
  for (i = 1; i <= ONIG_MAX_CAPTURE_HISTORY_GROUP; i++) {
Packit b89d10
    if (MEM_STATUS_AT(loc, i)) {
Packit b89d10
      MEM_STATUS_ON_SIMPLE(env->capture_history, map[i].new_val);
Packit b89d10
    }
Packit b89d10
  }
Packit b89d10
Packit b89d10
  env->num_mem = env->num_named;
Packit b89d10
  reg->num_mem = env->num_named;
Packit b89d10
Packit b89d10
  return onig_renumber_name_table(reg, map);
Packit b89d10
}
Packit b89d10
Packit b89d10
#ifdef USE_CALL
Packit b89d10
static int
Packit b89d10
fix_unset_addr_list(UnsetAddrList* uslist, regex_t* reg)
Packit b89d10
{
Packit b89d10
  int i, offset;
Packit b89d10
  EnclosureNode* en;
Packit b89d10
  AbsAddrType addr;
Packit b89d10
Packit b89d10
  for (i = 0; i < uslist->num; i++) {
Packit b89d10
    if (! NODE_IS_ADDR_FIXED(uslist->us[i].target))
Packit b89d10
      return ONIGERR_PARSER_BUG;
Packit b89d10
Packit b89d10
    en = ENCLOSURE_(uslist->us[i].target);
Packit b89d10
    addr   = en->m.called_addr;
Packit b89d10
    offset = uslist->us[i].offset;
Packit b89d10
Packit b89d10
    BB_WRITE(reg, offset, &addr, SIZE_ABSADDR);
Packit b89d10
  }
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
#endif
Packit b89d10
Packit b89d10
Packit b89d10
#define GET_CHAR_LEN_VARLEN           -1
Packit b89d10
#define GET_CHAR_LEN_TOP_ALT_VARLEN   -2
Packit b89d10
Packit b89d10
/* fixed size pattern node only */
Packit b89d10
static int
Packit b89d10
get_char_length_tree1(Node* node, regex_t* reg, int* len, int level)
Packit b89d10
{
Packit b89d10
  int tlen;
Packit b89d10
  int r = 0;
Packit b89d10
Packit b89d10
  level++;
Packit b89d10
  *len = 0;
Packit b89d10
  switch (NODE_TYPE(node)) {
Packit b89d10
  case NODE_LIST:
Packit b89d10
    do {
Packit b89d10
      r = get_char_length_tree1(NODE_CAR(node), reg, &tlen, level);
Packit b89d10
      if (r == 0)
Packit b89d10
        *len = distance_add(*len, tlen);
Packit b89d10
    } while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ALT:
Packit b89d10
    {
Packit b89d10
      int tlen2;
Packit b89d10
      int varlen = 0;
Packit b89d10
Packit b89d10
      r = get_char_length_tree1(NODE_CAR(node), reg, &tlen, level);
Packit b89d10
      while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node))) {
Packit b89d10
        r = get_char_length_tree1(NODE_CAR(node), reg, &tlen2, level);
Packit b89d10
        if (r == 0) {
Packit b89d10
          if (tlen != tlen2)
Packit b89d10
            varlen = 1;
Packit b89d10
        }
Packit b89d10
      }
Packit b89d10
      if (r == 0) {
Packit b89d10
        if (varlen != 0) {
Packit b89d10
          if (level == 1)
Packit b89d10
            r = GET_CHAR_LEN_TOP_ALT_VARLEN;
Packit b89d10
          else
Packit b89d10
            r = GET_CHAR_LEN_VARLEN;
Packit b89d10
        }
Packit b89d10
        else
Packit b89d10
          *len = tlen;
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_STRING:
Packit b89d10
    {
Packit b89d10
      StrNode* sn = STR_(node);
Packit b89d10
      UChar *s = sn->s;
Packit b89d10
Packit b89d10
      while (s < sn->end) {
Packit b89d10
        s += enclen(reg->enc, s);
Packit b89d10
        (*len)++;
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_QUANT:
Packit b89d10
    {
Packit b89d10
      QuantNode* qn = QUANT_(node);
Packit b89d10
Packit b89d10
      if (qn->lower == qn->upper) {
Packit b89d10
        if (qn->upper == 0) {
Packit b89d10
          *len = 0;
Packit b89d10
        }
Packit b89d10
        else {
Packit b89d10
          r = get_char_length_tree1(NODE_BODY(node), reg, &tlen, level);
Packit b89d10
          if (r == 0)
Packit b89d10
            *len = distance_multiply(tlen, qn->lower);
Packit b89d10
        }
Packit b89d10
      }
Packit b89d10
      else
Packit b89d10
        r = GET_CHAR_LEN_VARLEN;
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
#ifdef USE_CALL
Packit b89d10
  case NODE_CALL:
Packit b89d10
    if (! NODE_IS_RECURSION(node))
Packit b89d10
      r = get_char_length_tree1(NODE_BODY(node), reg, len, level);
Packit b89d10
    else
Packit b89d10
      r = GET_CHAR_LEN_VARLEN;
Packit b89d10
    break;
Packit b89d10
#endif
Packit b89d10
Packit b89d10
  case NODE_CTYPE:
Packit b89d10
  case NODE_CCLASS:
Packit b89d10
    *len = 1;
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ENCLOSURE:
Packit b89d10
    {
Packit b89d10
      EnclosureNode* en = ENCLOSURE_(node);
Packit b89d10
Packit b89d10
      switch (en->type) {
Packit b89d10
      case ENCLOSURE_MEMORY:
Packit b89d10
#ifdef USE_CALL
Packit b89d10
        if (NODE_IS_CLEN_FIXED(node))
Packit b89d10
          *len = en->char_len;
Packit b89d10
        else {
Packit b89d10
          r = get_char_length_tree1(NODE_BODY(node), reg, len, level);
Packit b89d10
          if (r == 0) {
Packit b89d10
            en->char_len = *len;
Packit b89d10
            NODE_STATUS_ADD(node, NST_CLEN_FIXED);
Packit b89d10
          }
Packit b89d10
        }
Packit b89d10
        break;
Packit b89d10
#endif
Packit b89d10
      case ENCLOSURE_OPTION:
Packit b89d10
      case ENCLOSURE_STOP_BACKTRACK:
Packit b89d10
        r = get_char_length_tree1(NODE_BODY(node), reg, len, level);
Packit b89d10
        break;
Packit b89d10
      case ENCLOSURE_IF_ELSE:
Packit b89d10
        {
Packit b89d10
          int clen, elen;
Packit b89d10
Packit b89d10
          r = get_char_length_tree1(NODE_BODY(node), reg, &clen, level);
Packit b89d10
          if (r == 0) {
Packit b89d10
            if (IS_NOT_NULL(en->te.Then)) {
Packit b89d10
              r = get_char_length_tree1(en->te.Then, reg, &tlen, level);
Packit b89d10
              if (r != 0) break;
Packit b89d10
            }
Packit b89d10
            else tlen = 0;
Packit b89d10
            if (IS_NOT_NULL(en->te.Else)) {
Packit b89d10
              r = get_char_length_tree1(en->te.Else, reg, &elen, level);
Packit b89d10
              if (r != 0) break;
Packit b89d10
            }
Packit b89d10
            else elen = 0;
Packit b89d10
Packit b89d10
            if (clen + tlen != elen) {
Packit b89d10
              r = GET_CHAR_LEN_VARLEN;
Packit b89d10
            }
Packit b89d10
            else {
Packit b89d10
              *len = elen;
Packit b89d10
            }
Packit b89d10
          }
Packit b89d10
        }
Packit b89d10
        break;
Packit b89d10
Packit b89d10
      default:
Packit b89d10
        break;
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ANCHOR:
Packit b89d10
  case NODE_GIMMICK:
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_BACKREF:
Packit b89d10
    if (NODE_IS_CHECKER(node))
Packit b89d10
      break;
Packit b89d10
    /* fall */
Packit b89d10
  default:
Packit b89d10
    r = GET_CHAR_LEN_VARLEN;
Packit b89d10
    break;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
get_char_length_tree(Node* node, regex_t* reg, int* len)
Packit b89d10
{
Packit b89d10
  return get_char_length_tree1(node, reg, len, 0);
Packit b89d10
}
Packit b89d10
Packit b89d10
/* x is not included y ==>  1 : 0 */
Packit b89d10
static int
Packit b89d10
is_exclusive(Node* x, Node* y, regex_t* reg)
Packit b89d10
{
Packit b89d10
  int i, len;
Packit b89d10
  OnigCodePoint code;
Packit b89d10
  UChar *p;
Packit b89d10
  NodeType ytype;
Packit b89d10
Packit b89d10
 retry:
Packit b89d10
  ytype = NODE_TYPE(y);
Packit b89d10
  switch (NODE_TYPE(x)) {
Packit b89d10
  case NODE_CTYPE:
Packit b89d10
    {
Packit b89d10
      if (CTYPE_(x)->ctype == CTYPE_ANYCHAR ||
Packit b89d10
          CTYPE_(y)->ctype == CTYPE_ANYCHAR)
Packit b89d10
        break;
Packit b89d10
Packit b89d10
      switch (ytype) {
Packit b89d10
      case NODE_CTYPE:
Packit b89d10
        if (CTYPE_(y)->ctype == CTYPE_(x)->ctype &&
Packit b89d10
            CTYPE_(y)->not   != CTYPE_(x)->not &&
Packit b89d10
            CTYPE_(y)->ascii_mode == CTYPE_(x)->ascii_mode)
Packit b89d10
          return 1;
Packit b89d10
        else
Packit b89d10
          return 0;
Packit b89d10
        break;
Packit b89d10
Packit b89d10
      case NODE_CCLASS:
Packit b89d10
      swap:
Packit b89d10
        {
Packit b89d10
          Node* tmp;
Packit b89d10
          tmp = x; x = y; y = tmp;
Packit b89d10
          goto retry;
Packit b89d10
        }
Packit b89d10
        break;
Packit b89d10
Packit b89d10
      case NODE_STRING:
Packit b89d10
        goto swap;
Packit b89d10
        break;
Packit b89d10
Packit b89d10
      default:
Packit b89d10
        break;
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_CCLASS:
Packit b89d10
    {
Packit b89d10
      int range;
Packit b89d10
      CClassNode* xc = CCLASS_(x);
Packit b89d10
Packit b89d10
      switch (ytype) {
Packit b89d10
      case NODE_CTYPE:
Packit b89d10
        switch (CTYPE_(y)->ctype) {
Packit b89d10
        case CTYPE_ANYCHAR:
Packit b89d10
          return 0;
Packit b89d10
          break;
Packit b89d10
Packit b89d10
        case ONIGENC_CTYPE_WORD:
Packit b89d10
          if (CTYPE_(y)->not == 0) {
Packit b89d10
            if (IS_NULL(xc->mbuf) && !IS_NCCLASS_NOT(xc)) {
Packit b89d10
              range = CTYPE_(y)->ascii_mode != 0 ? 128 : SINGLE_BYTE_SIZE;
Packit b89d10
              for (i = 0; i < range; i++) {
Packit b89d10
                if (BITSET_AT(xc->bs, i)) {
Packit b89d10
                  if (ONIGENC_IS_CODE_WORD(reg->enc, i)) return 0;
Packit b89d10
                }
Packit b89d10
              }
Packit b89d10
              return 1;
Packit b89d10
            }
Packit b89d10
            return 0;
Packit b89d10
          }
Packit b89d10
          else {
Packit b89d10
            if (IS_NOT_NULL(xc->mbuf)) return 0;
Packit b89d10
            if (IS_NCCLASS_NOT(xc)) return 0;
Packit b89d10
Packit b89d10
            range = CTYPE_(y)->ascii_mode != 0 ? 128 : SINGLE_BYTE_SIZE;
Packit b89d10
            for (i = 0; i < range; i++) {
Packit b89d10
              if (! ONIGENC_IS_CODE_WORD(reg->enc, i)) {
Packit b89d10
                if (BITSET_AT(xc->bs, i))
Packit b89d10
                  return 0;
Packit b89d10
              }
Packit b89d10
            }
Packit b89d10
            for (i = range; i < SINGLE_BYTE_SIZE; i++) {
Packit b89d10
              if (BITSET_AT(xc->bs, i)) return 0;
Packit b89d10
            }
Packit b89d10
            return 1;
Packit b89d10
          }
Packit b89d10
          break;
Packit b89d10
Packit b89d10
        default:
Packit b89d10
          break;
Packit b89d10
        }
Packit b89d10
        break;
Packit b89d10
Packit b89d10
      case NODE_CCLASS:
Packit b89d10
        {
Packit b89d10
          int v;
Packit b89d10
          CClassNode* yc = CCLASS_(y);
Packit b89d10
Packit b89d10
          for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
Packit b89d10
            v = BITSET_AT(xc->bs, i);
Packit b89d10
            if ((v != 0 && !IS_NCCLASS_NOT(xc)) || (v == 0 && IS_NCCLASS_NOT(xc))) {
Packit b89d10
              v = BITSET_AT(yc->bs, i);
Packit b89d10
              if ((v != 0 && !IS_NCCLASS_NOT(yc)) ||
Packit b89d10
                  (v == 0 && IS_NCCLASS_NOT(yc)))
Packit b89d10
                return 0;
Packit b89d10
            }
Packit b89d10
          }
Packit b89d10
          if ((IS_NULL(xc->mbuf) && !IS_NCCLASS_NOT(xc)) ||
Packit b89d10
              (IS_NULL(yc->mbuf) && !IS_NCCLASS_NOT(yc)))
Packit b89d10
            return 1;
Packit b89d10
          return 0;
Packit b89d10
        }
Packit b89d10
        break;
Packit b89d10
Packit b89d10
      case NODE_STRING:
Packit b89d10
        goto swap;
Packit b89d10
        break;
Packit b89d10
Packit b89d10
      default:
Packit b89d10
        break;
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_STRING:
Packit b89d10
    {
Packit b89d10
      StrNode* xs = STR_(x);
Packit b89d10
Packit b89d10
      if (NODE_STRING_LEN(x) == 0)
Packit b89d10
        break;
Packit b89d10
Packit b89d10
      switch (ytype) {
Packit b89d10
      case NODE_CTYPE:
Packit b89d10
        switch (CTYPE_(y)->ctype) {
Packit b89d10
        case CTYPE_ANYCHAR:
Packit b89d10
          break;
Packit b89d10
Packit b89d10
        case ONIGENC_CTYPE_WORD:
Packit b89d10
          if (CTYPE_(y)->ascii_mode == 0) {
Packit b89d10
            if (ONIGENC_IS_MBC_WORD(reg->enc, xs->s, xs->end))
Packit b89d10
              return CTYPE_(y)->not;
Packit b89d10
            else
Packit b89d10
              return !(CTYPE_(y)->not);
Packit b89d10
          }
Packit b89d10
          else {
Packit b89d10
            if (ONIGENC_IS_MBC_WORD_ASCII(reg->enc, xs->s, xs->end))
Packit b89d10
              return CTYPE_(y)->not;
Packit b89d10
            else
Packit b89d10
              return !(CTYPE_(y)->not);
Packit b89d10
          }
Packit b89d10
          break;
Packit b89d10
        default:
Packit b89d10
          break;
Packit b89d10
        }
Packit b89d10
        break;
Packit b89d10
Packit b89d10
      case NODE_CCLASS:
Packit b89d10
        {
Packit b89d10
          CClassNode* cc = CCLASS_(y);
Packit b89d10
Packit b89d10
          code = ONIGENC_MBC_TO_CODE(reg->enc, xs->s,
Packit b89d10
                                     xs->s + ONIGENC_MBC_MAXLEN(reg->enc));
Packit b89d10
          return (onig_is_code_in_cc(reg->enc, code, cc) != 0 ? 0 : 1);
Packit b89d10
        }
Packit b89d10
        break;
Packit b89d10
Packit b89d10
      case NODE_STRING:
Packit b89d10
        {
Packit b89d10
          UChar *q;
Packit b89d10
          StrNode* ys = STR_(y);
Packit b89d10
Packit b89d10
          len = NODE_STRING_LEN(x);
Packit b89d10
          if (len > NODE_STRING_LEN(y)) len = NODE_STRING_LEN(y);
Packit b89d10
          if (NODE_STRING_IS_AMBIG(x) || NODE_STRING_IS_AMBIG(y)) {
Packit b89d10
            /* tiny version */
Packit b89d10
            return 0;
Packit b89d10
          }
Packit b89d10
          else {
Packit b89d10
            for (i = 0, p = ys->s, q = xs->s; i < len; i++, p++, q++) {
Packit b89d10
              if (*p != *q) return 1;
Packit b89d10
            }
Packit b89d10
          }
Packit b89d10
        }
Packit b89d10
        break;
Packit b89d10
Packit b89d10
      default:
Packit b89d10
        break;
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  default:
Packit b89d10
    break;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static Node*
Packit b89d10
get_head_value_node(Node* node, int exact, regex_t* reg)
Packit b89d10
{
Packit b89d10
  Node* n = NULL_NODE;
Packit b89d10
Packit b89d10
  switch (NODE_TYPE(node)) {
Packit b89d10
  case NODE_BACKREF:
Packit b89d10
  case NODE_ALT:
Packit b89d10
#ifdef USE_CALL
Packit b89d10
  case NODE_CALL:
Packit b89d10
#endif
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_CTYPE:
Packit b89d10
    if (CTYPE_(node)->ctype == CTYPE_ANYCHAR)
Packit b89d10
      break;
Packit b89d10
    /* fall */
Packit b89d10
  case NODE_CCLASS:
Packit b89d10
    if (exact == 0) {
Packit b89d10
      n = node;
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_LIST:
Packit b89d10
    n = get_head_value_node(NODE_CAR(node), exact, reg);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_STRING:
Packit b89d10
    {
Packit b89d10
      StrNode* sn = STR_(node);
Packit b89d10
Packit b89d10
      if (sn->end <= sn->s)
Packit b89d10
        break;
Packit b89d10
Packit b89d10
      if (exact != 0 &&
Packit b89d10
          !NODE_STRING_IS_RAW(node) && IS_IGNORECASE(reg->options)) {
Packit b89d10
      }
Packit b89d10
      else {
Packit b89d10
        n = node;
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_QUANT:
Packit b89d10
    {
Packit b89d10
      QuantNode* qn = QUANT_(node);
Packit b89d10
      if (qn->lower > 0) {
Packit b89d10
        if (IS_NOT_NULL(qn->head_exact))
Packit b89d10
          n = qn->head_exact;
Packit b89d10
        else
Packit b89d10
          n = get_head_value_node(NODE_BODY(node), exact, reg);
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ENCLOSURE:
Packit b89d10
    {
Packit b89d10
      EnclosureNode* en = ENCLOSURE_(node);
Packit b89d10
      switch (en->type) {
Packit b89d10
      case ENCLOSURE_OPTION:
Packit b89d10
        {
Packit b89d10
          OnigOptionType options = reg->options;
Packit b89d10
Packit b89d10
          reg->options = ENCLOSURE_(node)->o.options;
Packit b89d10
          n = get_head_value_node(NODE_BODY(node), exact, reg);
Packit b89d10
          reg->options = options;
Packit b89d10
        }
Packit b89d10
        break;
Packit b89d10
Packit b89d10
      case ENCLOSURE_MEMORY:
Packit b89d10
      case ENCLOSURE_STOP_BACKTRACK:
Packit b89d10
      case ENCLOSURE_IF_ELSE:
Packit b89d10
        n = get_head_value_node(NODE_BODY(node), exact, reg);
Packit b89d10
        break;
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ANCHOR:
Packit b89d10
    if (ANCHOR_(node)->type == ANCHOR_PREC_READ)
Packit b89d10
      n = get_head_value_node(NODE_BODY(node), exact, reg);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_GIMMICK:
Packit b89d10
  default:
Packit b89d10
    break;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return n;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
check_type_tree(Node* node, int type_mask, int enclosure_mask, int anchor_mask)
Packit b89d10
{
Packit b89d10
  NodeType type;
Packit b89d10
  int r = 0;
Packit b89d10
Packit b89d10
  type = NODE_TYPE(node);
Packit b89d10
  if ((NODE_TYPE2BIT(type) & type_mask) == 0)
Packit b89d10
    return 1;
Packit b89d10
Packit b89d10
  switch (type) {
Packit b89d10
  case NODE_LIST:
Packit b89d10
  case NODE_ALT:
Packit b89d10
    do {
Packit b89d10
      r = check_type_tree(NODE_CAR(node), type_mask, enclosure_mask,
Packit b89d10
                          anchor_mask);
Packit b89d10
    } while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_QUANT:
Packit b89d10
    r = check_type_tree(NODE_BODY(node), type_mask, enclosure_mask, anchor_mask);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ENCLOSURE:
Packit b89d10
    {
Packit b89d10
      EnclosureNode* en = ENCLOSURE_(node);
Packit b89d10
      if (((1<<en->type) & enclosure_mask) == 0)
Packit b89d10
        return 1;
Packit b89d10
Packit b89d10
      r = check_type_tree(NODE_BODY(node), type_mask, enclosure_mask, anchor_mask);
Packit b89d10
      if (r == 0 && en->type == ENCLOSURE_IF_ELSE) {
Packit b89d10
        if (IS_NOT_NULL(en->te.Then)) {
Packit b89d10
          r = check_type_tree(en->te.Then, type_mask, enclosure_mask, anchor_mask);
Packit b89d10
          if (r != 0) break;
Packit b89d10
        }
Packit b89d10
        if (IS_NOT_NULL(en->te.Else)) {
Packit b89d10
          r = check_type_tree(en->te.Else, type_mask, enclosure_mask, anchor_mask);
Packit b89d10
        }
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ANCHOR:
Packit b89d10
    type = ANCHOR_(node)->type;
Packit b89d10
    if ((type & anchor_mask) == 0)
Packit b89d10
      return 1;
Packit b89d10
Packit b89d10
    if (IS_NOT_NULL(NODE_BODY(node)))
Packit b89d10
      r = check_type_tree(NODE_BODY(node), type_mask, enclosure_mask, anchor_mask);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_GIMMICK:
Packit b89d10
  default:
Packit b89d10
    break;
Packit b89d10
  }
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static OnigLen
Packit b89d10
tree_min_len(Node* node, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  OnigLen len;
Packit b89d10
  OnigLen tmin;
Packit b89d10
Packit b89d10
  len = 0;
Packit b89d10
  switch (NODE_TYPE(node)) {
Packit b89d10
  case NODE_BACKREF:
Packit b89d10
    if (! NODE_IS_CHECKER(node)) {
Packit b89d10
      int i;
Packit b89d10
      int* backs;
Packit b89d10
      MemEnv* mem_env = SCANENV_MEMENV(env);
Packit b89d10
      BackRefNode* br = BACKREF_(node);
Packit b89d10
      if (NODE_IS_RECURSION(node)) break;
Packit b89d10
Packit b89d10
      backs = BACKREFS_P(br);
Packit b89d10
      len = tree_min_len(mem_env[backs[0]].node, env);
Packit b89d10
      for (i = 1; i < br->back_num; i++) {
Packit b89d10
        tmin = tree_min_len(mem_env[backs[i]].node, env);
Packit b89d10
        if (len > tmin) len = tmin;
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
#ifdef USE_CALL
Packit b89d10
  case NODE_CALL:
Packit b89d10
    {
Packit b89d10
      Node* t = NODE_BODY(node);
Packit b89d10
      if (NODE_IS_RECURSION(node)) {
Packit b89d10
        if (NODE_IS_MIN_FIXED(t))
Packit b89d10
          len = ENCLOSURE_(t)->min_len;
Packit b89d10
      }
Packit b89d10
      else
Packit b89d10
        len = tree_min_len(t, env);
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
#endif
Packit b89d10
Packit b89d10
  case NODE_LIST:
Packit b89d10
    do {
Packit b89d10
      tmin = tree_min_len(NODE_CAR(node), env);
Packit b89d10
      len = distance_add(len, tmin);
Packit b89d10
    } while (IS_NOT_NULL(node = NODE_CDR(node)));
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ALT:
Packit b89d10
    {
Packit b89d10
      Node *x, *y;
Packit b89d10
      y = node;
Packit b89d10
      do {
Packit b89d10
        x = NODE_CAR(y);
Packit b89d10
        tmin = tree_min_len(x, env);
Packit b89d10
        if (y == node) len = tmin;
Packit b89d10
        else if (len > tmin) len = tmin;
Packit b89d10
      } while (IS_NOT_NULL(y = NODE_CDR(y)));
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_STRING:
Packit b89d10
    {
Packit b89d10
      StrNode* sn = STR_(node);
Packit b89d10
      len = (int )(sn->end - sn->s);
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_CTYPE:
Packit b89d10
  case NODE_CCLASS:
Packit b89d10
    len = ONIGENC_MBC_MINLEN(env->enc);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_QUANT:
Packit b89d10
    {
Packit b89d10
      QuantNode* qn = QUANT_(node);
Packit b89d10
Packit b89d10
      if (qn->lower > 0) {
Packit b89d10
        len = tree_min_len(NODE_BODY(node), env);
Packit b89d10
        len = distance_multiply(len, qn->lower);
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ENCLOSURE:
Packit b89d10
    {
Packit b89d10
      EnclosureNode* en = ENCLOSURE_(node);
Packit b89d10
      switch (en->type) {
Packit b89d10
      case ENCLOSURE_MEMORY:
Packit b89d10
        if (NODE_IS_MIN_FIXED(node))
Packit b89d10
          len = en->min_len;
Packit b89d10
        else {
Packit b89d10
          if (NODE_IS_MARK1(node))
Packit b89d10
            len = 0;  /* recursive */
Packit b89d10
          else {
Packit b89d10
            NODE_STATUS_ADD(node, NST_MARK1);
Packit b89d10
            len = tree_min_len(NODE_BODY(node), env);
Packit b89d10
            NODE_STATUS_REMOVE(node, NST_MARK1);
Packit b89d10
Packit b89d10
            en->min_len = len;
Packit b89d10
            NODE_STATUS_ADD(node, NST_MIN_FIXED);
Packit b89d10
          }
Packit b89d10
        }
Packit b89d10
        break;
Packit b89d10
Packit b89d10
      case ENCLOSURE_OPTION:
Packit b89d10
      case ENCLOSURE_STOP_BACKTRACK:
Packit b89d10
        len = tree_min_len(NODE_BODY(node), env);
Packit b89d10
        break;
Packit b89d10
      case ENCLOSURE_IF_ELSE:
Packit b89d10
        {
Packit b89d10
          OnigLen elen;
Packit b89d10
Packit b89d10
          len = tree_min_len(NODE_BODY(node), env);
Packit b89d10
          if (IS_NOT_NULL(en->te.Then))
Packit b89d10
            len += tree_min_len(en->te.Then, env);
Packit b89d10
          if (IS_NOT_NULL(en->te.Else))
Packit b89d10
            elen = tree_min_len(en->te.Else, env);
Packit b89d10
          else elen = 0;
Packit b89d10
Packit b89d10
          if (elen < len) len = elen;
Packit b89d10
        }
Packit b89d10
        break;
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_GIMMICK:
Packit b89d10
    {
Packit b89d10
      GimmickNode* g = GIMMICK_(node);
Packit b89d10
      if (g->type == GIMMICK_FAIL) {
Packit b89d10
        len = INFINITE_LEN;
Packit b89d10
        break;
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    /* fall */
Packit b89d10
  case NODE_ANCHOR:
Packit b89d10
  default:
Packit b89d10
    break;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return len;
Packit b89d10
}
Packit b89d10
Packit b89d10
static OnigLen
Packit b89d10
tree_max_len(Node* node, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  OnigLen len;
Packit b89d10
  OnigLen tmax;
Packit b89d10
Packit b89d10
  len = 0;
Packit b89d10
  switch (NODE_TYPE(node)) {
Packit b89d10
  case NODE_LIST:
Packit b89d10
    do {
Packit b89d10
      tmax = tree_max_len(NODE_CAR(node), env);
Packit b89d10
      len = distance_add(len, tmax);
Packit b89d10
    } while (IS_NOT_NULL(node = NODE_CDR(node)));
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ALT:
Packit b89d10
    do {
Packit b89d10
      tmax = tree_max_len(NODE_CAR(node), env);
Packit b89d10
      if (len < tmax) len = tmax;
Packit b89d10
    } while (IS_NOT_NULL(node = NODE_CDR(node)));
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_STRING:
Packit b89d10
    {
Packit b89d10
      StrNode* sn = STR_(node);
Packit b89d10
      len = (OnigLen )(sn->end - sn->s);
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_CTYPE:
Packit b89d10
  case NODE_CCLASS:
Packit b89d10
    len = ONIGENC_MBC_MAXLEN_DIST(env->enc);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_BACKREF:
Packit b89d10
    if (! NODE_IS_CHECKER(node)) {
Packit b89d10
      int i;
Packit b89d10
      int* backs;
Packit b89d10
      MemEnv* mem_env = SCANENV_MEMENV(env);
Packit b89d10
      BackRefNode* br = BACKREF_(node);
Packit b89d10
      if (NODE_IS_RECURSION(node)) {
Packit b89d10
        len = INFINITE_LEN;
Packit b89d10
        break;
Packit b89d10
      }
Packit b89d10
      backs = BACKREFS_P(br);
Packit b89d10
      for (i = 0; i < br->back_num; i++) {
Packit b89d10
        tmax = tree_max_len(mem_env[backs[i]].node, env);
Packit b89d10
        if (len < tmax) len = tmax;
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
#ifdef USE_CALL
Packit b89d10
  case NODE_CALL:
Packit b89d10
    if (! NODE_IS_RECURSION(node))
Packit b89d10
      len = tree_max_len(NODE_BODY(node), env);
Packit b89d10
    else
Packit b89d10
      len = INFINITE_LEN;
Packit b89d10
    break;
Packit b89d10
#endif
Packit b89d10
Packit b89d10
  case NODE_QUANT:
Packit b89d10
    {
Packit b89d10
      QuantNode* qn = QUANT_(node);
Packit b89d10
Packit b89d10
      if (qn->upper != 0) {
Packit b89d10
        len = tree_max_len(NODE_BODY(node), env);
Packit b89d10
        if (len != 0) {
Packit b89d10
          if (! IS_REPEAT_INFINITE(qn->upper))
Packit b89d10
            len = distance_multiply(len, qn->upper);
Packit b89d10
          else
Packit b89d10
            len = INFINITE_LEN;
Packit b89d10
        }
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ENCLOSURE:
Packit b89d10
    {
Packit b89d10
      EnclosureNode* en = ENCLOSURE_(node);
Packit b89d10
      switch (en->type) {
Packit b89d10
      case ENCLOSURE_MEMORY:
Packit b89d10
        if (NODE_IS_MAX_FIXED(node))
Packit b89d10
          len = en->max_len;
Packit b89d10
        else {
Packit b89d10
          if (NODE_IS_MARK1(node))
Packit b89d10
            len = INFINITE_LEN;
Packit b89d10
          else {
Packit b89d10
            NODE_STATUS_ADD(node, NST_MARK1);
Packit b89d10
            len = tree_max_len(NODE_BODY(node), env);
Packit b89d10
            NODE_STATUS_REMOVE(node, NST_MARK1);
Packit b89d10
Packit b89d10
            en->max_len = len;
Packit b89d10
            NODE_STATUS_ADD(node, NST_MAX_FIXED);
Packit b89d10
          }
Packit b89d10
        }
Packit b89d10
        break;
Packit b89d10
Packit b89d10
      case ENCLOSURE_OPTION:
Packit b89d10
      case ENCLOSURE_STOP_BACKTRACK:
Packit b89d10
        len = tree_max_len(NODE_BODY(node), env);
Packit b89d10
        break;
Packit b89d10
      case ENCLOSURE_IF_ELSE:
Packit b89d10
        {
Packit b89d10
          OnigLen tlen, elen;
Packit b89d10
Packit b89d10
          len = tree_max_len(NODE_BODY(node), env);
Packit b89d10
          if (IS_NOT_NULL(en->te.Then)) {
Packit b89d10
            tlen = tree_max_len(en->te.Then, env);
Packit b89d10
            len = distance_add(len, tlen);
Packit b89d10
          }
Packit b89d10
          if (IS_NOT_NULL(en->te.Else))
Packit b89d10
            elen = tree_max_len(en->te.Else, env);
Packit b89d10
          else elen = 0;
Packit b89d10
Packit b89d10
          if (elen > len) len = elen;
Packit b89d10
        }
Packit b89d10
        break;
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ANCHOR:
Packit b89d10
  case NODE_GIMMICK:
Packit b89d10
  default:
Packit b89d10
    break;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return len;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
check_backrefs(Node* node, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
Packit b89d10
  switch (NODE_TYPE(node)) {
Packit b89d10
  case NODE_LIST:
Packit b89d10
  case NODE_ALT:
Packit b89d10
    do {
Packit b89d10
      r = check_backrefs(NODE_CAR(node), env);
Packit b89d10
    } while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ANCHOR:
Packit b89d10
    if (! ANCHOR_HAS_BODY(ANCHOR_(node))) {
Packit b89d10
      r = 0;
Packit b89d10
      break;
Packit b89d10
    }
Packit b89d10
    /* fall */
Packit b89d10
  case NODE_QUANT:
Packit b89d10
    r = check_backrefs(NODE_BODY(node), env);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ENCLOSURE:
Packit b89d10
    r = check_backrefs(NODE_BODY(node), env);
Packit b89d10
    {
Packit b89d10
      EnclosureNode* en = ENCLOSURE_(node);
Packit b89d10
Packit b89d10
      if (en->type == ENCLOSURE_IF_ELSE) {
Packit b89d10
        if (r != 0) return r;
Packit b89d10
        if (IS_NOT_NULL(en->te.Then)) {
Packit b89d10
          r = check_backrefs(en->te.Then, env);
Packit b89d10
          if (r != 0) return r;
Packit b89d10
        }
Packit b89d10
        if (IS_NOT_NULL(en->te.Else)) {
Packit b89d10
          r = check_backrefs(en->te.Else, env);
Packit b89d10
        }
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_BACKREF:
Packit b89d10
    {
Packit b89d10
      int i;
Packit b89d10
      BackRefNode* br = BACKREF_(node);
Packit b89d10
      int* backs = BACKREFS_P(br);
Packit b89d10
      MemEnv* mem_env = SCANENV_MEMENV(env);
Packit b89d10
Packit b89d10
      for (i = 0; i < br->back_num; i++) {
Packit b89d10
        if (backs[i] > env->num_mem)
Packit b89d10
          return ONIGERR_INVALID_BACKREF;
Packit b89d10
Packit b89d10
        NODE_STATUS_ADD(mem_env[backs[i]].node, NST_BACKREF);
Packit b89d10
      }
Packit b89d10
      r = 0;
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  default:
Packit b89d10
    r = 0;
Packit b89d10
    break;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
Packit b89d10
#ifdef USE_CALL
Packit b89d10
Packit b89d10
#define RECURSION_EXIST        (1<<0)
Packit b89d10
#define RECURSION_MUST         (1<<1)
Packit b89d10
#define RECURSION_INFINITE     (1<<2)
Packit b89d10
Packit b89d10
static int
Packit b89d10
infinite_recursive_call_check(Node* node, ScanEnv* env, int head)
Packit b89d10
{
Packit b89d10
  int ret;
Packit b89d10
  int r = 0;
Packit b89d10
Packit b89d10
  switch (NODE_TYPE(node)) {
Packit b89d10
  case NODE_LIST:
Packit b89d10
    {
Packit b89d10
      Node *x;
Packit b89d10
      OnigLen min;
Packit b89d10
Packit b89d10
      x = node;
Packit b89d10
      do {
Packit b89d10
        ret = infinite_recursive_call_check(NODE_CAR(x), env, head);
Packit b89d10
        if (ret < 0 || (ret & RECURSION_INFINITE) != 0) return ret;
Packit b89d10
        r |= ret;
Packit b89d10
        if (head != 0) {
Packit b89d10
          min = tree_min_len(NODE_CAR(x), env);
Packit b89d10
          if (min != 0) head = 0;
Packit b89d10
        }
Packit b89d10
      } while (IS_NOT_NULL(x = NODE_CDR(x)));
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ALT:
Packit b89d10
    {
Packit b89d10
      int must;
Packit b89d10
Packit b89d10
      must = RECURSION_MUST;
Packit b89d10
      do {
Packit b89d10
        ret = infinite_recursive_call_check(NODE_CAR(node), env, head);
Packit b89d10
        if (ret < 0 || (ret & RECURSION_INFINITE) != 0) return ret;
Packit b89d10
Packit b89d10
        r    |= (ret & RECURSION_EXIST);
Packit b89d10
        must &= ret;
Packit b89d10
      } while (IS_NOT_NULL(node = NODE_CDR(node)));
Packit b89d10
      r |= must;
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_QUANT:
Packit b89d10
    r = infinite_recursive_call_check(NODE_BODY(node), env, head);
Packit b89d10
    if (r < 0) return r;
Packit b89d10
    if ((r & RECURSION_MUST) != 0) {
Packit b89d10
      if (QUANT_(node)->lower == 0)
Packit b89d10
        r &= ~RECURSION_MUST;
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ANCHOR:
Packit b89d10
    if (! ANCHOR_HAS_BODY(ANCHOR_(node)))
Packit b89d10
      break;
Packit b89d10
    /* fall */
Packit b89d10
  case NODE_CALL:
Packit b89d10
    r = infinite_recursive_call_check(NODE_BODY(node), env, head);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ENCLOSURE:
Packit b89d10
    {
Packit b89d10
      EnclosureNode* en = ENCLOSURE_(node);
Packit b89d10
Packit b89d10
      if (en->type == ENCLOSURE_MEMORY) {
Packit b89d10
        if (NODE_IS_MARK2(node))
Packit b89d10
          return 0;
Packit b89d10
        else if (NODE_IS_MARK1(node))
Packit b89d10
          return (head == 0 ? RECURSION_EXIST | RECURSION_MUST
Packit b89d10
                  : RECURSION_EXIST | RECURSION_MUST | RECURSION_INFINITE);
Packit b89d10
        else {
Packit b89d10
          NODE_STATUS_ADD(node, NST_MARK2);
Packit b89d10
          r = infinite_recursive_call_check(NODE_BODY(node), env, head);
Packit b89d10
          NODE_STATUS_REMOVE(node, NST_MARK2);
Packit b89d10
        }
Packit b89d10
      }
Packit b89d10
      else if (en->type == ENCLOSURE_IF_ELSE) {
Packit b89d10
        int eret;
Packit b89d10
Packit b89d10
        ret = infinite_recursive_call_check(NODE_BODY(node), env, head);
Packit b89d10
        if (ret < 0 || (ret & RECURSION_INFINITE) != 0) return ret;
Packit b89d10
        r |= ret;
Packit b89d10
        if (IS_NOT_NULL(en->te.Then)) {
Packit b89d10
          OnigLen min;
Packit b89d10
          if (head != 0) {
Packit b89d10
            min = tree_min_len(NODE_BODY(node), env);
Packit b89d10
          }
Packit b89d10
          else min = 0;
Packit b89d10
Packit b89d10
          ret = infinite_recursive_call_check(en->te.Then, env, min != 0 ? 0:head);
Packit b89d10
          if (ret < 0 || (ret & RECURSION_INFINITE) != 0) return ret;
Packit b89d10
          r |= ret;
Packit b89d10
        }
Packit b89d10
        if (IS_NOT_NULL(en->te.Else)) {
Packit b89d10
          eret = infinite_recursive_call_check(en->te.Else, env, head);
Packit b89d10
          if (eret < 0 || (eret & RECURSION_INFINITE) != 0) return eret;
Packit b89d10
          r |= (eret & RECURSION_EXIST);
Packit b89d10
          if ((eret & RECURSION_MUST) == 0)
Packit b89d10
            r &= ~RECURSION_MUST;
Packit b89d10
        }
Packit b89d10
      }
Packit b89d10
      else {
Packit b89d10
        r = infinite_recursive_call_check(NODE_BODY(node), env, head);
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  default:
Packit b89d10
    break;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
infinite_recursive_call_check_trav(Node* node, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
Packit b89d10
  switch (NODE_TYPE(node)) {
Packit b89d10
  case NODE_LIST:
Packit b89d10
  case NODE_ALT:
Packit b89d10
    do {
Packit b89d10
      r = infinite_recursive_call_check_trav(NODE_CAR(node), env);
Packit b89d10
    } while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ANCHOR:
Packit b89d10
    if (! ANCHOR_HAS_BODY(ANCHOR_(node))) {
Packit b89d10
      r = 0;
Packit b89d10
      break;
Packit b89d10
    }
Packit b89d10
    /* fall */
Packit b89d10
  case NODE_QUANT:
Packit b89d10
    r = infinite_recursive_call_check_trav(NODE_BODY(node), env);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ENCLOSURE:
Packit b89d10
    {
Packit b89d10
      EnclosureNode* en = ENCLOSURE_(node);
Packit b89d10
Packit b89d10
      if (en->type == ENCLOSURE_MEMORY) {
Packit b89d10
        if (NODE_IS_RECURSION(node) && NODE_IS_CALLED(node)) {
Packit b89d10
          int ret;
Packit b89d10
Packit b89d10
          NODE_STATUS_ADD(node, NST_MARK1);
Packit b89d10
Packit b89d10
          ret = infinite_recursive_call_check(NODE_BODY(node), env, 1);
Packit b89d10
          if (ret < 0) return ret;
Packit b89d10
          else if ((ret & (RECURSION_MUST | RECURSION_INFINITE)) != 0)
Packit b89d10
            return ONIGERR_NEVER_ENDING_RECURSION;
Packit b89d10
Packit b89d10
          NODE_STATUS_REMOVE(node, NST_MARK1);
Packit b89d10
        }
Packit b89d10
      }
Packit b89d10
      else if (en->type == ENCLOSURE_IF_ELSE) {
Packit b89d10
        if (IS_NOT_NULL(en->te.Then)) {
Packit b89d10
          r = infinite_recursive_call_check_trav(en->te.Then, env);
Packit b89d10
          if (r != 0) return r;
Packit b89d10
        }
Packit b89d10
        if (IS_NOT_NULL(en->te.Else)) {
Packit b89d10
          r = infinite_recursive_call_check_trav(en->te.Else, env);
Packit b89d10
          if (r != 0) return r;
Packit b89d10
        }
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
Packit b89d10
    r = infinite_recursive_call_check_trav(NODE_BODY(node), env);
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  default:
Packit b89d10
    r = 0;
Packit b89d10
    break;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
recursive_call_check(Node* node)
Packit b89d10
{
Packit b89d10
  int r;
Packit b89d10
Packit b89d10
  switch (NODE_TYPE(node)) {
Packit b89d10
  case NODE_LIST:
Packit b89d10
  case NODE_ALT:
Packit b89d10
    r = 0;
Packit b89d10
    do {
Packit b89d10
      r |= recursive_call_check(NODE_CAR(node));
Packit b89d10
    } while (IS_NOT_NULL(node = NODE_CDR(node)));
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ANCHOR:
Packit b89d10
    if (! ANCHOR_HAS_BODY(ANCHOR_(node))) {
Packit b89d10
      r = 0;
Packit b89d10
      break;
Packit b89d10
    }
Packit b89d10
    /* fall */
Packit b89d10
  case NODE_QUANT:
Packit b89d10
    r = recursive_call_check(NODE_BODY(node));
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_CALL:
Packit b89d10
    r = recursive_call_check(NODE_BODY(node));
Packit b89d10
    if (r != 0) {
Packit b89d10
      if (NODE_IS_MARK1(NODE_BODY(node)))
Packit b89d10
        NODE_STATUS_ADD(node, NST_RECURSION);
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ENCLOSURE:
Packit b89d10
    {
Packit b89d10
      EnclosureNode* en = ENCLOSURE_(node);
Packit b89d10
Packit b89d10
      if (en->type == ENCLOSURE_MEMORY) {
Packit b89d10
        if (NODE_IS_MARK2(node))
Packit b89d10
          return 0;
Packit b89d10
        else if (NODE_IS_MARK1(node))
Packit b89d10
          return 1; /* recursion */
Packit b89d10
        else {
Packit b89d10
          NODE_STATUS_ADD(node, NST_MARK2);
Packit b89d10
          r = recursive_call_check(NODE_BODY(node));
Packit b89d10
          NODE_STATUS_REMOVE(node, NST_MARK2);
Packit b89d10
        }
Packit b89d10
      }
Packit b89d10
      else if (en->type == ENCLOSURE_IF_ELSE) {
Packit b89d10
        r = 0;
Packit b89d10
        if (IS_NOT_NULL(en->te.Then)) {
Packit b89d10
          r |= recursive_call_check(en->te.Then);
Packit b89d10
        }
Packit b89d10
        if (IS_NOT_NULL(en->te.Else)) {
Packit b89d10
          r |= recursive_call_check(en->te.Else);
Packit b89d10
        }
Packit b89d10
        r |= recursive_call_check(NODE_BODY(node));
Packit b89d10
      }
Packit b89d10
      else {
Packit b89d10
        r = recursive_call_check(NODE_BODY(node));
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  default:
Packit b89d10
    r = 0;
Packit b89d10
    break;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
#define IN_RECURSION         (1<<0)
Packit b89d10
#define FOUND_CALLED_NODE    1
Packit b89d10
Packit b89d10
static int
Packit b89d10
recursive_call_check_trav(Node* node, ScanEnv* env, int state)
Packit b89d10
{
Packit b89d10
  int r = 0;
Packit b89d10
Packit b89d10
  switch (NODE_TYPE(node)) {
Packit b89d10
  case NODE_LIST:
Packit b89d10
  case NODE_ALT:
Packit b89d10
    {
Packit b89d10
      int ret;
Packit b89d10
      do {
Packit b89d10
        ret = recursive_call_check_trav(NODE_CAR(node), env, state);
Packit b89d10
        if (ret == FOUND_CALLED_NODE) r = FOUND_CALLED_NODE;
Packit b89d10
        else if (ret < 0) return ret;
Packit b89d10
      } while (IS_NOT_NULL(node = NODE_CDR(node)));
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_QUANT:
Packit b89d10
    r = recursive_call_check_trav(NODE_BODY(node), env, state);
Packit b89d10
    if (QUANT_(node)->upper == 0) {
Packit b89d10
      if (r == FOUND_CALLED_NODE)
Packit b89d10
        QUANT_(node)->is_refered = 1;
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ANCHOR:
Packit b89d10
    {
Packit b89d10
      AnchorNode* an = ANCHOR_(node);
Packit b89d10
      if (ANCHOR_HAS_BODY(an))
Packit b89d10
        r = recursive_call_check_trav(NODE_ANCHOR_BODY(an), env, state);
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  case NODE_ENCLOSURE:
Packit b89d10
    {
Packit b89d10
      int ret;
Packit b89d10
      int state1;
Packit b89d10
      EnclosureNode* en = ENCLOSURE_(node);
Packit b89d10
Packit b89d10
      if (en->type == ENCLOSURE_MEMORY) {
Packit b89d10
        if (NODE_IS_CALLED(node) || (state & IN_RECURSION) != 0) {
Packit b89d10
          if (! NODE_IS_RECURSION(node)) {
Packit b89d10
            NODE_STATUS_ADD(node, NST_MARK1);
Packit b89d10
            r = recursive_call_check(NODE_BODY(node));
Packit b89d10
            if (r != 0)
Packit b89d10
              NODE_STATUS_ADD(node, NST_RECURSION);
Packit b89d10
            NODE_STATUS_REMOVE(node, NST_MARK1);
Packit b89d10
          }
Packit b89d10
Packit b89d10
          if (NODE_IS_CALLED(node))
Packit b89d10
            r = FOUND_CALLED_NODE;
Packit b89d10
        }
Packit b89d10
      }
Packit b89d10
Packit b89d10
      state1 = state;
Packit b89d10
      if (NODE_IS_RECURSION(node))
Packit b89d10
        state1 |= IN_RECURSION;
Packit b89d10
Packit b89d10
      ret = recursive_call_check_trav(NODE_BODY(node), env, state1);
Packit b89d10
      if (ret == FOUND_CALLED_NODE)
Packit b89d10
        r = FOUND_CALLED_NODE;
Packit b89d10
Packit b89d10
      if (en->type == ENCLOSURE_IF_ELSE) {
Packit b89d10
        if (IS_NOT_NULL(en->te.Then)) {
Packit b89d10
          ret = recursive_call_check_trav(en->te.Then, env, state1);
Packit b89d10
          if (ret == FOUND_CALLED_NODE)
Packit b89d10
            r = FOUND_CALLED_NODE;
Packit b89d10
        }
Packit b89d10
        if (IS_NOT_NULL(en->te.Else)) {
Packit b89d10
          ret = recursive_call_check_trav(en->te.Else, env, state1);
Packit b89d10
          if (ret == FOUND_CALLED_NODE)
Packit b89d10
            r = FOUND_CALLED_NODE;
Packit b89d10
        }
Packit b89d10
      }
Packit b89d10
    }
Packit b89d10
    break;
Packit b89d10
Packit b89d10
  default:
Packit b89d10
    break;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  return r;
Packit b89d10
}
Packit b89d10
Packit b89d10
#endif
Packit b89d10
Packit b89d10
/* divide different length alternatives in look-behind.
Packit b89d10
  (?<=A|B) ==> (?<=A)|(?<=B)
Packit b89d10
  (? (?
Packit b89d10
*/
Packit b89d10
static int
Packit b89d10
divide_look_behind_alternatives(Node* node)
Packit b89d10
{
Packit b89d10
  Node *head, *np, *insert_node;
Packit b89d10
  AnchorNode* an = ANCHOR_(node);
Packit b89d10
  int anc_type = an->type;
Packit b89d10
Packit b89d10
  head = NODE_ANCHOR_BODY(an);
Packit b89d10
  np = NODE_CAR(head);
Packit b89d10
  swap_node(node, head);
Packit b89d10
  NODE_CAR(node) = head;
Packit b89d10
  NODE_BODY(head) = np;
Packit b89d10
Packit b89d10
  np = node;
Packit b89d10
  while (IS_NOT_NULL(np = NODE_CDR(np))) {
Packit b89d10
    insert_node = onig_node_new_anchor(anc_type, an->ascii_mode);
Packit b89d10
    CHECK_NULL_RETURN_MEMERR(insert_node);
Packit b89d10
    NODE_BODY(insert_node) = NODE_CAR(np);
Packit b89d10
    NODE_CAR(np) = insert_node;
Packit b89d10
  }
Packit b89d10
Packit b89d10
  if (anc_type == ANCHOR_LOOK_BEHIND_NOT) {
Packit b89d10
    np = node;
Packit b89d10
    do {
Packit b89d10
      NODE_SET_TYPE(np, NODE_LIST);  /* alt -> list */
Packit b89d10
    } while (IS_NOT_NULL(np = NODE_CDR(np)));
Packit b89d10
  }
Packit b89d10
  return 0;
Packit b89d10
}
Packit b89d10
Packit b89d10
static int
Packit b89d10
setup_look_behind(Node* node, regex_t* reg, ScanEnv* env)
Packit b89d10
{
Packit b89d10
  int r, len;
Packit b89d10
  AnchorNode* an = ANCHOR_(node);