]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/RegularExpressionDxe/Oniguruma/regcomp.c
MdeModulePkg RegularExpressionDxe: Update Oniguruma to 6.9.0
[mirror_edk2.git] / MdeModulePkg / Universal / RegularExpressionDxe / Oniguruma / regcomp.c
index ea63b09d0c85fb564c4e4f79adef779c3af99ee1..cc061780c7ea659bf03600dd45bc2acb97d35c93 100644 (file)
@@ -2,11 +2,9 @@
   regcomp.c -  Oniguruma (regular expression library)\r
 **********************************************************************/\r
 /*-\r
- * Copyright (c) 2002-2013  K.Kosako  <sndgk393 AT ybb DOT ne DOT jp>\r
+ * Copyright (c) 2002-2018  K.Kosako  <sndgk393 AT ybb DOT ne DOT jp>\r
  * All rights reserved.\r
  *\r
- * (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
- *\r
  * Redistribution and use in source and binary forms, with or without\r
  * modification, are permitted provided that the following conditions\r
  * are met:\r
 \r
 OnigCaseFoldType OnigDefaultCaseFoldFlag = ONIGENC_CASE_FOLD_MIN;\r
 \r
+#if 0\r
+typedef struct {\r
+  int  n;\r
+  int  alloc;\r
+  int* v;\r
+} int_stack;\r
+\r
+static int\r
+make_int_stack(int_stack** rs, int init_size)\r
+{\r
+  int_stack* s;\r
+  int* v;\r
+\r
+  *rs = 0;\r
+\r
+  s = xmalloc(sizeof(*s));\r
+  if (IS_NULL(s)) return ONIGERR_MEMORY;\r
+\r
+  v = (int* )xmalloc(sizeof(int) * init_size);\r
+  if (IS_NULL(v)) {\r
+    xfree(s);\r
+    return ONIGERR_MEMORY;\r
+  }\r
+\r
+  s->n = 0;\r
+  s->alloc = init_size;\r
+  s->v = v;\r
+\r
+  *rs = s;\r
+  return ONIG_NORMAL;\r
+}\r
+\r
+static void\r
+free_int_stack(int_stack* s)\r
+{\r
+  if (IS_NOT_NULL(s)) {\r
+    if (IS_NOT_NULL(s->v))\r
+      xfree(s->v);\r
+    xfree(s);\r
+  }\r
+}\r
+\r
+static int\r
+int_stack_push(int_stack* s, int v)\r
+{\r
+  if (s->n >= s->alloc) {\r
+    int new_size = s->alloc * 2;\r
+    int* nv = (int* )xrealloc(s->v, sizeof(int) * new_size);\r
+    if (IS_NULL(nv)) return ONIGERR_MEMORY;\r
+\r
+    s->alloc = new_size;\r
+    s->v = nv;\r
+  }\r
+\r
+  s->v[s->n] = v;\r
+  s->n++;\r
+  return ONIG_NORMAL;\r
+}\r
+\r
+static int\r
+int_stack_pop(int_stack* s)\r
+{\r
+  int v;\r
+\r
+#ifdef ONIG_DEBUG\r
+  if (s->n <= 0) {\r
+    fprintf(stderr, "int_stack_pop: fail empty. %p\n", s);\r
+    return 0;\r
+  }\r
+#endif\r
+\r
+  v = s->v[s->n];\r
+  s->n--;\r
+  return v;\r
+}\r
+#endif\r
+\r
 extern OnigCaseFoldType\r
 onig_get_default_case_fold_flag(void)\r
 {\r
@@ -46,99 +121,87 @@ onig_set_default_case_fold_flag(OnigCaseFoldType case_fold_flag)
   return 0;\r
 }\r
 \r
-\r
-#ifndef PLATFORM_UNALIGNED_WORD_ACCESS\r
-static unsigned char PadBuf[WORD_ALIGNMENT_SIZE];\r
-#endif\r
-\r
-static UChar*\r
-str_dup(UChar* s, UChar* end)\r
+static int\r
+int_multiply_cmp(int x, int y, int v)\r
 {\r
-  int len = (int)(end - s);\r
+  if (x == 0 || y == 0) return -1;\r
 \r
-  if (len > 0) {\r
-    UChar* r = (UChar* )xmalloc(len + 1);\r
-    CHECK_NULL_RETURN(r);\r
-    xmemcpy(r, s, len);\r
-    r[len] = (UChar )0;\r
-    return r;\r
+  if (x < INT_MAX / y) {\r
+    int xy = x * y;\r
+    if (xy > v) return 1;\r
+    else {\r
+      if (xy == v) return 0;\r
+      else return -1;\r
+    }\r
   }\r
-  else return NULL;\r
+  else\r
+    return 1;\r
 }\r
 \r
+\r
+#ifndef PLATFORM_UNALIGNED_WORD_ACCESS\r
+static unsigned char PadBuf[WORD_ALIGNMENT_SIZE];\r
+#endif\r
+\r
 static void\r
 swap_node(Node* a, Node* b)\r
 {\r
   Node c;\r
-  CopyMem (&c, a, sizeof (Node));\r
-  CopyMem (a, b, sizeof (Node));\r
-  CopyMem (b, &c, sizeof (Node));\r
 \r
-  if (NTYPE(a) == NT_STR) {\r
-    StrNode* sn = NSTR(a);\r
+  c = *a; *a = *b; *b = c;\r
+\r
+  if (NODE_TYPE(a) == NODE_STRING) {\r
+    StrNode* sn = STR_(a);\r
     if (sn->capa == 0) {\r
-      int len = (int)(sn->end - sn->s);\r
+      int len = (int )(sn->end - sn->s);\r
       sn->s   = sn->buf;\r
       sn->end = sn->s + len;\r
     }\r
   }\r
 \r
-  if (NTYPE(b) == NT_STR) {\r
-    StrNode* sn = NSTR(b);\r
+  if (NODE_TYPE(b) == NODE_STRING) {\r
+    StrNode* sn = STR_(b);\r
     if (sn->capa == 0) {\r
-      int len = (int)(sn->end - sn->s);\r
+      int len = (int )(sn->end - sn->s);\r
       sn->s   = sn->buf;\r
       sn->end = sn->s + len;\r
     }\r
   }\r
 }\r
 \r
-static OnigDistance\r
-distance_add(OnigDistance d1, OnigDistance d2)\r
+static OnigLen\r
+distance_add(OnigLen d1, OnigLen d2)\r
 {\r
-  if (d1 == ONIG_INFINITE_DISTANCE || d2 == ONIG_INFINITE_DISTANCE)\r
-    return ONIG_INFINITE_DISTANCE;\r
+  if (d1 == INFINITE_LEN || d2 == INFINITE_LEN)\r
+    return INFINITE_LEN;\r
   else {\r
-    if (d1 <= ONIG_INFINITE_DISTANCE - d2) return d1 + d2;\r
-    else return ONIG_INFINITE_DISTANCE;\r
+    if (d1 <= INFINITE_LEN - d2) return d1 + d2;\r
+    else return INFINITE_LEN;\r
   }\r
 }\r
 \r
-static OnigDistance\r
-distance_multiply(OnigDistance d, int m)\r
+static OnigLen\r
+distance_multiply(OnigLen d, int m)\r
 {\r
   if (m == 0) return 0;\r
 \r
-  if (d < ONIG_INFINITE_DISTANCE / m)\r
+  if (d < INFINITE_LEN / m)\r
     return d * m;\r
   else\r
-    return ONIG_INFINITE_DISTANCE;\r
+    return INFINITE_LEN;\r
 }\r
 \r
 static int\r
 bitset_is_empty(BitSetRef bs)\r
 {\r
   int i;\r
+\r
   for (i = 0; i < (int )BITSET_SIZE; i++) {\r
     if (bs[i] != 0) return 0;\r
   }\r
   return 1;\r
 }\r
 \r
-#ifdef ONIG_DEBUG\r
-static int\r
-bitset_on_num(BitSetRef bs)\r
-{\r
-  int i, n;\r
-\r
-  n = 0;\r
-  for (i = 0; i < SINGLE_BYTE_SIZE; i++) {\r
-    if (BITSET_AT(bs, i)) n++;\r
-  }\r
-  return n;\r
-}\r
-#endif\r
-\r
 extern int\r
 onig_bbuf_init(BBuf* buf, int size)\r
 {\r
@@ -157,74 +220,62 @@ onig_bbuf_init(BBuf* buf, int size)
 }\r
 \r
 \r
-#ifdef USE_SUBEXP_CALL\r
+#ifdef USE_CALL\r
 \r
 static int\r
-unset_addr_list_init(UnsetAddrList* uslist, int size)\r
+unset_addr_list_init(UnsetAddrList* list, int size)\r
 {\r
-  UnsetAddr* p;\r
-\r
-  p = (UnsetAddr* )xmalloc(sizeof(UnsetAddr)* size);\r
+  UnsetAddr* p = (UnsetAddr* )xmalloc(sizeof(UnsetAddr)* size);\r
   CHECK_NULL_RETURN_MEMERR(p);\r
-  uslist->num   = 0;\r
-  uslist->alloc = size;\r
-  uslist->us    = p;\r
+\r
+  list->num   = 0;\r
+  list->alloc = size;\r
+  list->us    = p;\r
   return 0;\r
 }\r
 \r
 static void\r
-unset_addr_list_end(UnsetAddrList* uslist)\r
+unset_addr_list_end(UnsetAddrList* list)\r
 {\r
-  if (IS_NOT_NULL(uslist->us))\r
-    xfree(uslist->us);\r
+  if (IS_NOT_NULL(list->us))\r
+    xfree(list->us);\r
 }\r
 \r
 static int\r
-unset_addr_list_add(UnsetAddrList* uslist, int offset, struct _Node* node)\r
+unset_addr_list_add(UnsetAddrList* list, int offset, struct _Node* node)\r
 {\r
   UnsetAddr* p;\r
   int size;\r
 \r
-  if (uslist->num >= uslist->alloc) {\r
-    size = uslist->alloc * 2;\r
-    p = (UnsetAddr* )xrealloc(uslist->us, sizeof(UnsetAddr) * size, sizeof(UnsetAddr) * uslist->alloc);\r
+  if (list->num >= list->alloc) {\r
+    size = list->alloc * 2;\r
+    p = (UnsetAddr* )xrealloc(list->us, sizeof(UnsetAddr) * size, sizeof(UnsetAddr)* list->alloc);\r
     CHECK_NULL_RETURN_MEMERR(p);\r
-    uslist->alloc = size;\r
-    uslist->us    = p;\r
+    list->alloc = size;\r
+    list->us    = p;\r
   }\r
 \r
-  uslist->us[uslist->num].offset = offset;\r
-  uslist->us[uslist->num].target = node;\r
-  uslist->num++;\r
+  list->us[list->num].offset = offset;\r
+  list->us[list->num].target = node;\r
+  list->num++;\r
   return 0;\r
 }\r
-#endif /* USE_SUBEXP_CALL */\r
+#endif /* USE_CALL */\r
 \r
 \r
 static int\r
 add_opcode(regex_t* reg, int opcode)\r
 {\r
-  BBUF_ADD1(reg, ((unsigned char)opcode));\r
-  return 0;\r
-}\r
-\r
-#ifdef USE_COMBINATION_EXPLOSION_CHECK\r
-static int\r
-add_state_check_num(regex_t* reg, int num)\r
-{\r
-  StateCheckNumType n = (StateCheckNumType )num;\r
-\r
-  BBUF_ADD(reg, &n, SIZE_STATE_CHECK_NUM);\r
+  BB_ADD1(reg, opcode);\r
   return 0;\r
 }\r
-#endif\r
 \r
 static int\r
 add_rel_addr(regex_t* reg, int addr)\r
 {\r
   RelAddrType ra = (RelAddrType )addr;\r
 \r
-  BBUF_ADD(reg, &ra, SIZE_RELADDR);\r
+  BB_ADD(reg, &ra, SIZE_RELADDR);\r
   return 0;\r
 }\r
 \r
@@ -233,7 +284,7 @@ add_abs_addr(regex_t* reg, int addr)
 {\r
   AbsAddrType ra = (AbsAddrType )addr;\r
 \r
-  BBUF_ADD(reg, &ra, SIZE_ABSADDR);\r
+  BB_ADD(reg, &ra, SIZE_ABSADDR);\r
   return 0;\r
 }\r
 \r
@@ -242,7 +293,7 @@ add_length(regex_t* reg, int len)
 {\r
   LengthType l = (LengthType )len;\r
 \r
-  BBUF_ADD(reg, &l, SIZE_LENGTH);\r
+  BB_ADD(reg, &l, SIZE_LENGTH);\r
   return 0;\r
 }\r
 \r
@@ -251,64 +302,80 @@ add_mem_num(regex_t* reg, int num)
 {\r
   MemNumType n = (MemNumType )num;\r
 \r
-  BBUF_ADD(reg, &n, SIZE_MEMNUM);\r
+  BB_ADD(reg, &n, SIZE_MEMNUM);\r
   return 0;\r
 }\r
 \r
+#if 0\r
 static int\r
 add_pointer(regex_t* reg, void* addr)\r
 {\r
   PointerType ptr = (PointerType )addr;\r
 \r
-  BBUF_ADD(reg, &ptr, SIZE_POINTER);\r
+  BB_ADD(reg, &ptr, SIZE_POINTER);\r
   return 0;\r
 }\r
+#endif\r
 \r
 static int\r
 add_option(regex_t* reg, OnigOptionType option)\r
 {\r
-  BBUF_ADD(reg, &option, SIZE_OPTION);\r
+  BB_ADD(reg, &option, SIZE_OPTION);\r
   return 0;\r
 }\r
 \r
 static int\r
-add_opcode_rel_addr(regex_t* reg, int opcode, int addr)\r
+add_save_type(regex_t* reg, enum SaveType type)\r
 {\r
-  int r;\r
+  SaveType t = (SaveType )type;\r
 \r
-  r = add_opcode(reg, opcode);\r
-  if (r) return r;\r
-  r = add_rel_addr(reg, addr);\r
-  return r;\r
+  BB_ADD(reg, &t, SIZE_SAVE_TYPE);\r
+  return 0;\r
 }\r
 \r
 static int\r
-add_bytes(regex_t* reg, UChar* bytes, int len)\r
+add_update_var_type(regex_t* reg, enum UpdateVarType type)\r
 {\r
-  BBUF_ADD(reg, bytes, len);\r
+  UpdateVarType t = (UpdateVarType )type;\r
+\r
+  BB_ADD(reg, &t, SIZE_UPDATE_VAR_TYPE);\r
   return 0;\r
 }\r
 \r
 static int\r
-add_bitset(regex_t* reg, BitSetRef bs)\r
+add_mode(regex_t* reg, ModeType mode)\r
 {\r
-  BBUF_ADD(reg, bs, SIZE_BITSET);\r
+  BB_ADD(reg, &mode, SIZE_MODE);\r
   return 0;\r
 }\r
 \r
 static int\r
-add_opcode_option(regex_t* reg, int opcode, OnigOptionType option)\r
+add_opcode_rel_addr(regex_t* reg, int opcode, int addr)\r
 {\r
   int r;\r
 \r
   r = add_opcode(reg, opcode);\r
-  if (r) return r;\r
-  r = add_option(reg, option);\r
+  if (r != 0) return r;\r
+  r = add_rel_addr(reg, addr);\r
   return r;\r
 }\r
 \r
+static int\r
+add_bytes(regex_t* reg, UChar* bytes, int len)\r
+{\r
+  BB_ADD(reg, bytes, len);\r
+  return 0;\r
+}\r
+\r
+static int\r
+add_bitset(regex_t* reg, BitSetRef bs)\r
+{\r
+  BB_ADD(reg, bs, SIZE_BITSET);\r
+  return 0;\r
+}\r
+\r
 static int compile_length_tree(Node* node, regex_t* reg);\r
-static int compile_tree(Node* node, regex_t* reg);\r
+static int compile_tree(Node* node, regex_t* reg, ScanEnv* env);\r
 \r
 \r
 #define IS_NEED_STR_LEN_OP_EXACT(op) \\r
@@ -361,60 +428,60 @@ select_str_opcode(int mb_len, int str_len, int ignore_case)
 }\r
 \r
 static int\r
-compile_tree_empty_check(Node* node, regex_t* reg, int empty_info)\r
+compile_tree_empty_check(Node* node, regex_t* reg, int empty_info, ScanEnv* env)\r
 {\r
   int r;\r
   int saved_num_null_check = reg->num_null_check;\r
 \r
-  if (empty_info != 0) {\r
-    r = add_opcode(reg, OP_NULL_CHECK_START);\r
-    if (r) return r;\r
+  if (empty_info != QUANT_BODY_IS_NOT_EMPTY) {\r
+    r = add_opcode(reg, OP_EMPTY_CHECK_START);\r
+    if (r != 0) return r;\r
     r = add_mem_num(reg, reg->num_null_check); /* NULL CHECK ID */\r
-    if (r) return r;\r
+    if (r != 0) return r;\r
     reg->num_null_check++;\r
   }\r
 \r
-  r = compile_tree(node, reg);\r
-  if (r) return r;\r
+  r = compile_tree(node, reg, env);\r
+  if (r != 0) return r;\r
 \r
-  if (empty_info != 0) {\r
-    if (empty_info == NQ_TARGET_IS_EMPTY)\r
-      r = add_opcode(reg, OP_NULL_CHECK_END);\r
-    else if (empty_info == NQ_TARGET_IS_EMPTY_MEM)\r
-      r = add_opcode(reg, OP_NULL_CHECK_END_MEMST);\r
-    else if (empty_info == NQ_TARGET_IS_EMPTY_REC)\r
-      r = add_opcode(reg, OP_NULL_CHECK_END_MEMST_PUSH);\r
+  if (empty_info != QUANT_BODY_IS_NOT_EMPTY) {\r
+    if (empty_info == QUANT_BODY_IS_EMPTY)\r
+      r = add_opcode(reg, OP_EMPTY_CHECK_END);\r
+    else if (empty_info == QUANT_BODY_IS_EMPTY_MEM)\r
+      r = add_opcode(reg, OP_EMPTY_CHECK_END_MEMST);\r
+    else if (empty_info == QUANT_BODY_IS_EMPTY_REC)\r
+      r = add_opcode(reg, OP_EMPTY_CHECK_END_MEMST_PUSH);\r
 \r
-    if (r) return r;\r
+    if (r != 0) return r;\r
     r = add_mem_num(reg, saved_num_null_check); /* NULL CHECK ID */\r
   }\r
   return r;\r
 }\r
 \r
-#ifdef USE_SUBEXP_CALL\r
+#ifdef USE_CALL\r
 static int\r
-compile_call(CallNode* node, regex_t* reg)\r
+compile_call(CallNode* node, regex_t* reg, ScanEnv* env)\r
 {\r
   int r;\r
 \r
   r = add_opcode(reg, OP_CALL);\r
-  if (r) return r;\r
-  r = unset_addr_list_add(node->unset_addr_list, BBUF_GET_OFFSET_POS(reg),\r
-                          node->target);\r
-  if (r) return r;\r
+  if (r != 0) return r;\r
+  r = unset_addr_list_add(env->unset_addr_list, BB_GET_OFFSET_POS(reg),\r
+                          NODE_CALL_BODY(node));\r
+  if (r != 0) return r;\r
   r = add_abs_addr(reg, 0 /*dummy addr.*/);\r
   return r;\r
 }\r
 #endif\r
 \r
 static int\r
-compile_tree_n_times(Node* node, int n, regex_t* reg)\r
+compile_tree_n_times(Node* node, int n, regex_t* reg, ScanEnv* env)\r
 {\r
   int i, r;\r
 \r
   for (i = 0; i < n; i++) {\r
-    r = compile_tree(node, reg);\r
-    if (r) return r;\r
+    r = compile_tree(node, reg, env);\r
+    if (r != 0) return r;\r
   }\r
   return 0;\r
 }\r
@@ -462,15 +529,15 @@ static int
 compile_length_string_node(Node* node, regex_t* reg)\r
 {\r
   int rlen, r, len, prev_len, slen, ambig;\r
-  OnigEncoding enc = reg->enc;\r
   UChar *p, *prev;\r
   StrNode* sn;\r
+  OnigEncoding enc = reg->enc;\r
 \r
-  sn = NSTR(node);\r
+  sn = STR_(node);\r
   if (sn->end <= sn->s)\r
     return 0;\r
 \r
-  ambig = NSTRING_IS_AMBIG(node);\r
+  ambig = NODE_STRING_IS_AMBIG(node);\r
 \r
   p = prev = sn->s;\r
   prev_len = enclen(enc, p);\r
@@ -492,6 +559,7 @@ compile_length_string_node(Node* node, regex_t* reg)
     }\r
     p += len;\r
   }\r
+\r
   r = add_compile_string_length(prev, prev_len, slen, reg, ambig);\r
   rlen += r;\r
   return rlen;\r
@@ -503,23 +571,24 @@ compile_length_string_raw_node(StrNode* sn, regex_t* reg)
   if (sn->end <= sn->s)\r
     return 0;\r
 \r
-  return add_compile_string_length(sn->s, 1 /* sb */, (int)(sn->end - sn->s), reg, 0);\r
+  return add_compile_string_length(sn->s, 1 /* sb */, (int )(sn->end - sn->s),\r
+                                   reg, 0);\r
 }\r
 \r
 static int\r
 compile_string_node(Node* node, regex_t* reg)\r
 {\r
   int r, len, prev_len, slen, ambig;\r
-  OnigEncoding enc = reg->enc;\r
   UChar *p, *prev, *end;\r
   StrNode* sn;\r
+  OnigEncoding enc = reg->enc;\r
 \r
-  sn = NSTR(node);\r
+  sn = STR_(node);\r
   if (sn->end <= sn->s)\r
     return 0;\r
 \r
   end = sn->end;\r
-  ambig = NSTRING_IS_AMBIG(node);\r
+  ambig = NODE_STRING_IS_AMBIG(node);\r
 \r
   p = prev = sn->s;\r
   prev_len = enclen(enc, p);\r
@@ -533,7 +602,7 @@ compile_string_node(Node* node, regex_t* reg)
     }\r
     else {\r
       r = add_compile_string(prev, prev_len, slen, reg, ambig);\r
-      if (r) return r;\r
+      if (r != 0) return r;\r
 \r
       prev  = p;\r
       slen  = 1;\r
@@ -542,6 +611,7 @@ compile_string_node(Node* node, regex_t* reg)
 \r
     p += len;\r
   }\r
+\r
   return add_compile_string(prev, prev_len, slen, reg, ambig);\r
 }\r
 \r
@@ -551,7 +621,7 @@ compile_string_raw_node(StrNode* sn, regex_t* reg)
   if (sn->end <= sn->s)\r
     return 0;\r
 \r
-  return add_compile_string(sn->s, 1 /* sb */, (int)(sn->end - sn->s), reg, 0);\r
+  return add_compile_string(sn->s, 1 /* sb */, (int )(sn->end - sn->s), reg, 0);\r
 }\r
 \r
 static int\r
@@ -562,7 +632,7 @@ add_multi_byte_cclass(BBuf* mbuf, regex_t* reg)
   return add_bytes(reg, mbuf->p, mbuf->used);\r
 #else\r
   int r, pad_size;\r
-  UChar* p = BBUF_GET_ADD_ADDRESS(reg) + SIZE_LENGTH;\r
+  UChar* p = BB_GET_ADD_ADDRESS(reg) + SIZE_LENGTH;\r
 \r
   GET_ALIGNMENT_PAD_SIZE(p, pad_size);\r
   add_length(reg, mbuf->used + (WORD_ALIGNMENT_SIZE - 1));\r
@@ -582,11 +652,6 @@ compile_length_cclass_node(CClassNode* cc, regex_t* reg)
 {\r
   int len;\r
 \r
-  if (IS_NCCLASS_SHARE(cc)) {\r
-    len = SIZE_OPCODE + SIZE_POINTER;\r
-    return len;\r
-  }\r
-\r
   if (IS_NULL(cc->mbuf)) {\r
     len = SIZE_OPCODE + SIZE_BITSET;\r
   }\r
@@ -612,12 +677,6 @@ compile_cclass_node(CClassNode* cc, regex_t* reg)
 {\r
   int r;\r
 \r
-  if (IS_NCCLASS_SHARE(cc)) {\r
-    add_opcode(reg, OP_CCLASS_NODE);\r
-    r = add_pointer(reg, cc);\r
-    return r;\r
-  }\r
-\r
   if (IS_NULL(cc->mbuf)) {\r
     if (IS_NCCLASS_NOT(cc))\r
       add_opcode(reg, OP_CCLASS_NOT);\r
@@ -642,7 +701,7 @@ compile_cclass_node(CClassNode* cc, regex_t* reg)
         add_opcode(reg, OP_CCLASS_MIX);\r
 \r
       r = add_bitset(reg, cc->bs);\r
-      if (r) return r;\r
+      if (r != 0) return r;\r
       r = add_multi_byte_cclass(cc->mbuf, reg);\r
     }\r
   }\r
@@ -683,46 +742,46 @@ entry_repeat_range(regex_t* reg, int id, int lower, int upper)
 }\r
 \r
 static int\r
-compile_range_repeat_node(QtfrNode* qn, int target_len, int empty_info,\r
-                          regex_t* reg)\r
+compile_range_repeat_node(QuantNode* qn, int target_len, int empty_info,\r
+                          regex_t* reg, ScanEnv* env)\r
 {\r
   int r;\r
   int num_repeat = reg->num_repeat;\r
 \r
   r = add_opcode(reg, qn->greedy ? OP_REPEAT : OP_REPEAT_NG);\r
-  if (r) return r;\r
+  if (r != 0) return r;\r
   r = add_mem_num(reg, num_repeat); /* OP_REPEAT ID */\r
   reg->num_repeat++;\r
-  if (r) return r;\r
+  if (r != 0) return r;\r
   r = add_rel_addr(reg, target_len + SIZE_OP_REPEAT_INC);\r
-  if (r) return r;\r
+  if (r != 0) return r;\r
 \r
   r = entry_repeat_range(reg, num_repeat, qn->lower, qn->upper);\r
-  if (r) return r;\r
+  if (r != 0) return r;\r
 \r
-  r = compile_tree_empty_check(qn->target, reg, empty_info);\r
-  if (r) return r;\r
+  r = compile_tree_empty_check(NODE_QUANT_BODY(qn), reg, empty_info, env);\r
+  if (r != 0) return r;\r
 \r
   if (\r
-#ifdef USE_SUBEXP_CALL\r
-      reg->num_call > 0 ||\r
+#ifdef USE_CALL\r
+      NODE_IS_IN_MULTI_ENTRY(qn) ||\r
 #endif\r
-      IS_QUANTIFIER_IN_REPEAT(qn)) {\r
+      NODE_IS_IN_REAL_REPEAT(qn)) {\r
     r = add_opcode(reg, qn->greedy ? OP_REPEAT_INC_SG : OP_REPEAT_INC_NG_SG);\r
   }\r
   else {\r
     r = add_opcode(reg, qn->greedy ? OP_REPEAT_INC : OP_REPEAT_INC_NG);\r
   }\r
-  if (r) return r;\r
+  if (r != 0) return r;\r
   r = add_mem_num(reg, num_repeat); /* OP_REPEAT ID */\r
   return r;\r
 }\r
 \r
 static int\r
-is_anychar_star_quantifier(QtfrNode* qn)\r
+is_anychar_infinite_greedy(QuantNode* qn)\r
 {\r
   if (qn->greedy && IS_REPEAT_INFINITE(qn->upper) &&\r
-      NTYPE(qn->target) == NT_CANY)\r
+      NODE_IS_ANYCHAR(NODE_QUANT_BODY(qn)))\r
     return 1;\r
   else\r
     return 0;\r
@@ -731,255 +790,21 @@ is_anychar_star_quantifier(QtfrNode* qn)
 #define QUANTIFIER_EXPAND_LIMIT_SIZE   50\r
 #define CKN_ON   (ckn > 0)\r
 \r
-#ifdef USE_COMBINATION_EXPLOSION_CHECK\r
-\r
-static int\r
-compile_length_quantifier_node(QtfrNode* qn, regex_t* reg)\r
-{\r
-  int len, mod_tlen, cklen;\r
-  int ckn;\r
-  int infinite = IS_REPEAT_INFINITE(qn->upper);\r
-  int empty_info = qn->target_empty_info;\r
-  int tlen = compile_length_tree(qn->target, reg);\r
-\r
-  if (tlen < 0) return tlen;\r
-\r
-  ckn = ((reg->num_comb_exp_check > 0) ? qn->comb_exp_check_num : 0);\r
-\r
-  cklen = (CKN_ON ? SIZE_STATE_CHECK_NUM: 0);\r
-\r
-  /* anychar repeat */\r
-  if (NTYPE(qn->target) == NT_CANY) {\r
-    if (qn->greedy && infinite) {\r
-      if (IS_NOT_NULL(qn->next_head_exact) && !CKN_ON)\r
-        return SIZE_OP_ANYCHAR_STAR_PEEK_NEXT + tlen * qn->lower + cklen;\r
-      else\r
-        return SIZE_OP_ANYCHAR_STAR + tlen * qn->lower + cklen;\r
-    }\r
-  }\r
-\r
-  if (empty_info != 0)\r
-    mod_tlen = tlen + (SIZE_OP_NULL_CHECK_START + SIZE_OP_NULL_CHECK_END);\r
-  else\r
-    mod_tlen = tlen;\r
-\r
-  if (infinite && qn->lower <= 1) {\r
-    if (qn->greedy) {\r
-      if (qn->lower == 1)\r
-       len = SIZE_OP_JUMP;\r
-      else\r
-       len = 0;\r
-\r
-      len += SIZE_OP_PUSH + cklen + mod_tlen + SIZE_OP_JUMP;\r
-    }\r
-    else {\r
-      if (qn->lower == 0)\r
-       len = SIZE_OP_JUMP;\r
-      else\r
-       len = 0;\r
-\r
-      len += mod_tlen + SIZE_OP_PUSH + cklen;\r
-    }\r
-  }\r
-  else if (qn->upper == 0) {\r
-    if (qn->is_refered != 0) /* /(?<n>..){0}/ */\r
-      len = SIZE_OP_JUMP + tlen;\r
-    else\r
-      len = 0;\r
-  }\r
-  else if (qn->upper == 1 && qn->greedy) {\r
-    if (qn->lower == 0) {\r
-      if (CKN_ON) {\r
-       len = SIZE_OP_STATE_CHECK_PUSH + tlen;\r
-      }\r
-      else {\r
-       len = SIZE_OP_PUSH + tlen;\r
-      }\r
-    }\r
-    else {\r
-      len = tlen;\r
-    }\r
-  }\r
-  else if (!qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */\r
-    len = SIZE_OP_PUSH + cklen + SIZE_OP_JUMP + tlen;\r
-  }\r
-  else {\r
-    len = SIZE_OP_REPEAT_INC\r
-        + mod_tlen + SIZE_OPCODE + SIZE_RELADDR + SIZE_MEMNUM;\r
-    if (CKN_ON)\r
-      len += SIZE_OP_STATE_CHECK;\r
-  }\r
-\r
-  return len;\r
-}\r
-\r
-static int\r
-compile_quantifier_node(QtfrNode* qn, regex_t* reg)\r
-{\r
-  int r, mod_tlen;\r
-  int ckn;\r
-  int infinite = IS_REPEAT_INFINITE(qn->upper);\r
-  int empty_info = qn->target_empty_info;\r
-  int tlen = compile_length_tree(qn->target, reg);\r
-\r
-  if (tlen < 0) return tlen;\r
-\r
-  ckn = ((reg->num_comb_exp_check > 0) ? qn->comb_exp_check_num : 0);\r
-\r
-  if (is_anychar_star_quantifier(qn)) {\r
-    r = compile_tree_n_times(qn->target, qn->lower, reg);\r
-    if (r) return r;\r
-    if (IS_NOT_NULL(qn->next_head_exact) && !CKN_ON) {\r
-      if (IS_MULTILINE(reg->options))\r
-       r = add_opcode(reg, OP_ANYCHAR_ML_STAR_PEEK_NEXT);\r
-      else\r
-       r = add_opcode(reg, OP_ANYCHAR_STAR_PEEK_NEXT);\r
-      if (r) return r;\r
-      if (CKN_ON) {\r
-       r = add_state_check_num(reg, ckn);\r
-       if (r) return r;\r
-      }\r
-\r
-      return add_bytes(reg, NSTR(qn->next_head_exact)->s, 1);\r
-    }\r
-    else {\r
-      if (IS_MULTILINE(reg->options)) {\r
-       r = add_opcode(reg, (CKN_ON ?\r
-                              OP_STATE_CHECK_ANYCHAR_ML_STAR\r
-                            : OP_ANYCHAR_ML_STAR));\r
-      }\r
-      else {\r
-       r = add_opcode(reg, (CKN_ON ?\r
-                              OP_STATE_CHECK_ANYCHAR_STAR\r
-                            : OP_ANYCHAR_STAR));\r
-      }\r
-      if (r) return r;\r
-      if (CKN_ON)\r
-       r = add_state_check_num(reg, ckn);\r
-\r
-      return r;\r
-    }\r
-  }\r
-\r
-  if (empty_info != 0)\r
-    mod_tlen = tlen + (SIZE_OP_NULL_CHECK_START + SIZE_OP_NULL_CHECK_END);\r
-  else\r
-    mod_tlen = tlen;\r
-\r
-  if (infinite && qn->lower <= 1) {\r
-    if (qn->greedy) {\r
-      if (qn->lower == 1) {\r
-       r = add_opcode_rel_addr(reg, OP_JUMP,\r
-                       (CKN_ON ? SIZE_OP_STATE_CHECK_PUSH : SIZE_OP_PUSH));\r
-       if (r) return r;\r
-      }\r
-\r
-      if (CKN_ON) {\r
-       r = add_opcode(reg, OP_STATE_CHECK_PUSH);\r
-       if (r) return r;\r
-       r = add_state_check_num(reg, ckn);\r
-       if (r) return r;\r
-       r = add_rel_addr(reg, mod_tlen + SIZE_OP_JUMP);\r
-      }\r
-      else {\r
-       r = add_opcode_rel_addr(reg, OP_PUSH, mod_tlen + SIZE_OP_JUMP);\r
-      }\r
-      if (r) return r;\r
-      r = compile_tree_empty_check(qn->target, reg, empty_info);\r
-      if (r) return r;\r
-      r = add_opcode_rel_addr(reg, OP_JUMP,\r
-             -(mod_tlen + (int )SIZE_OP_JUMP\r
-               + (int )(CKN_ON ? SIZE_OP_STATE_CHECK_PUSH : SIZE_OP_PUSH)));\r
-    }\r
-    else {\r
-      if (qn->lower == 0) {\r
-       r = add_opcode_rel_addr(reg, OP_JUMP, mod_tlen);\r
-       if (r) return r;\r
-      }\r
-      r = compile_tree_empty_check(qn->target, reg, empty_info);\r
-      if (r) return r;\r
-      if (CKN_ON) {\r
-       r = add_opcode(reg, OP_STATE_CHECK_PUSH_OR_JUMP);\r
-       if (r) return r;\r
-       r = add_state_check_num(reg, ckn);\r
-       if (r) return r;\r
-       r = add_rel_addr(reg,\r
-                -(mod_tlen + (int )SIZE_OP_STATE_CHECK_PUSH_OR_JUMP));\r
-      }\r
-      else\r
-       r = add_opcode_rel_addr(reg, OP_PUSH, -(mod_tlen + (int )SIZE_OP_PUSH));\r
-    }\r
-  }\r
-  else if (qn->upper == 0) {\r
-    if (qn->is_refered != 0) { /* /(?<n>..){0}/ */\r
-      r = add_opcode_rel_addr(reg, OP_JUMP, tlen);\r
-      if (r) return r;\r
-      r = compile_tree(qn->target, reg);\r
-    }\r
-    else\r
-      r = 0;\r
-  }\r
-  else if (qn->upper == 1 && qn->greedy) {\r
-    if (qn->lower == 0) {\r
-      if (CKN_ON) {\r
-       r = add_opcode(reg, OP_STATE_CHECK_PUSH);\r
-       if (r) return r;\r
-       r = add_state_check_num(reg, ckn);\r
-       if (r) return r;\r
-       r = add_rel_addr(reg, tlen);\r
-      }\r
-      else {\r
-       r = add_opcode_rel_addr(reg, OP_PUSH, tlen);\r
-      }\r
-      if (r) return r;\r
-    }\r
-\r
-    r = compile_tree(qn->target, reg);\r
-  }\r
-  else if (!qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */\r
-    if (CKN_ON) {\r
-      r = add_opcode(reg, OP_STATE_CHECK_PUSH);\r
-      if (r) return r;\r
-      r = add_state_check_num(reg, ckn);\r
-      if (r) return r;\r
-      r = add_rel_addr(reg, SIZE_OP_JUMP);\r
-    }\r
-    else {\r
-      r = add_opcode_rel_addr(reg, OP_PUSH, SIZE_OP_JUMP);\r
-    }\r
-\r
-    if (r) return r;\r
-    r = add_opcode_rel_addr(reg, OP_JUMP, tlen);\r
-    if (r) return r;\r
-    r = compile_tree(qn->target, reg);\r
-  }\r
-  else {\r
-    r = compile_range_repeat_node(qn, mod_tlen, empty_info, reg);\r
-    if (CKN_ON) {\r
-      if (r) return r;\r
-      r = add_opcode(reg, OP_STATE_CHECK);\r
-      if (r) return r;\r
-      r = add_state_check_num(reg, ckn);\r
-    }\r
-  }\r
-  return r;\r
-}\r
-\r
-#else /* USE_COMBINATION_EXPLOSION_CHECK */\r
-\r
 static int\r
-compile_length_quantifier_node(QtfrNode* qn, regex_t* reg)\r
+compile_length_quantifier_node(QuantNode* qn, regex_t* reg)\r
 {\r
   int len, mod_tlen;\r
   int infinite = IS_REPEAT_INFINITE(qn->upper);\r
-  int empty_info = qn->target_empty_info;\r
-  int tlen = compile_length_tree(qn->target, reg);\r
+  enum QuantBodyEmpty empty_info = qn->body_empty_info;\r
+  int tlen = compile_length_tree(NODE_QUANT_BODY(qn), reg);\r
 \r
   if (tlen < 0) return tlen;\r
+  if (tlen == 0) return 0;\r
 \r
   /* anychar repeat */\r
-  if (NTYPE(qn->target) == NT_CANY) {\r
-    if (qn->greedy && infinite) {\r
+  if (is_anychar_infinite_greedy(qn)) {\r
+    if (qn->lower <= 1 ||\r
+        int_multiply_cmp(tlen, qn->lower, QUANTIFIER_EXPAND_LIMIT_SIZE) <= 0) {\r
       if (IS_NOT_NULL(qn->next_head_exact))\r
         return SIZE_OP_ANYCHAR_STAR_PEEK_NEXT + tlen * qn->lower;\r
       else\r
@@ -987,13 +812,14 @@ compile_length_quantifier_node(QtfrNode* qn, regex_t* reg)
     }\r
   }\r
 \r
-  if (empty_info != 0)\r
-    mod_tlen = tlen + (SIZE_OP_NULL_CHECK_START + SIZE_OP_NULL_CHECK_END);\r
-  else\r
+  if (empty_info == QUANT_BODY_IS_NOT_EMPTY)\r
     mod_tlen = tlen;\r
+  else\r
+    mod_tlen = tlen + (SIZE_OP_EMPTY_CHECK_START + SIZE_OP_EMPTY_CHECK_END);\r
 \r
   if (infinite &&\r
-      (qn->lower <= 1 || tlen * qn->lower <= QUANTIFIER_EXPAND_LIMIT_SIZE)) {\r
+      (qn->lower <= 1 ||\r
+       int_multiply_cmp(tlen, qn->lower, QUANTIFIER_EXPAND_LIMIT_SIZE) <= 0)) {\r
     if (qn->lower == 1 && tlen > QUANTIFIER_EXPAND_LIMIT_SIZE) {\r
       len = SIZE_OP_JUMP;\r
     }\r
@@ -1003,11 +829,11 @@ compile_length_quantifier_node(QtfrNode* qn, regex_t* reg)
 \r
     if (qn->greedy) {\r
       if (IS_NOT_NULL(qn->head_exact))\r
-       len += SIZE_OP_PUSH_OR_JUMP_EXACT1 + mod_tlen + SIZE_OP_JUMP;\r
+        len += SIZE_OP_PUSH_OR_JUMP_EXACT1 + mod_tlen + SIZE_OP_JUMP;\r
       else if (IS_NOT_NULL(qn->next_head_exact))\r
-       len += SIZE_OP_PUSH_IF_PEEK_NEXT + mod_tlen + SIZE_OP_JUMP;\r
+        len += SIZE_OP_PUSH_IF_PEEK_NEXT + mod_tlen + SIZE_OP_JUMP;\r
       else\r
-       len += SIZE_OP_PUSH + mod_tlen + SIZE_OP_JUMP;\r
+        len += SIZE_OP_PUSH + mod_tlen + SIZE_OP_JUMP;\r
     }\r
     else\r
       len += SIZE_OP_JUMP + mod_tlen + SIZE_OP_PUSH;\r
@@ -1016,8 +842,9 @@ compile_length_quantifier_node(QtfrNode* qn, regex_t* reg)
     len = SIZE_OP_JUMP + tlen;\r
   }\r
   else if (!infinite && qn->greedy &&\r
-           (qn->upper == 1 || (tlen + SIZE_OP_PUSH) * qn->upper\r
-                                      <= QUANTIFIER_EXPAND_LIMIT_SIZE)) {\r
+           (qn->upper == 1 ||\r
+            int_multiply_cmp(tlen + SIZE_OP_PUSH, qn->upper,\r
+                             QUANTIFIER_EXPAND_LIMIT_SIZE) <= 0)) {\r
     len = tlen * qn->lower;\r
     len += (SIZE_OP_PUSH + tlen) * (qn->upper - qn->lower);\r
   }\r
@@ -1033,341 +860,428 @@ compile_length_quantifier_node(QtfrNode* qn, regex_t* reg)
 }\r
 \r
 static int\r
-compile_quantifier_node(QtfrNode* qn, regex_t* reg)\r
+compile_quantifier_node(QuantNode* qn, regex_t* reg, ScanEnv* env)\r
 {\r
   int i, r, mod_tlen;\r
   int infinite = IS_REPEAT_INFINITE(qn->upper);\r
-  int empty_info = qn->target_empty_info;\r
-  int tlen = compile_length_tree(qn->target, reg);\r
+  enum QuantBodyEmpty empty_info = qn->body_empty_info;\r
+  int tlen = compile_length_tree(NODE_QUANT_BODY(qn), reg);\r
 \r
   if (tlen < 0) return tlen;\r
+  if (tlen == 0) return 0;\r
 \r
-  if (is_anychar_star_quantifier(qn)) {\r
-    r = compile_tree_n_times(qn->target, qn->lower, reg);\r
-    if (r) return r;\r
+  if (is_anychar_infinite_greedy(qn) &&\r
+      (qn->lower <= 1 ||\r
+       int_multiply_cmp(tlen, qn->lower, QUANTIFIER_EXPAND_LIMIT_SIZE) <= 0)) {\r
+    r = compile_tree_n_times(NODE_QUANT_BODY(qn), qn->lower, reg, env);\r
+    if (r != 0) return r;\r
     if (IS_NOT_NULL(qn->next_head_exact)) {\r
-      if (IS_MULTILINE(reg->options))\r
-       r = add_opcode(reg, OP_ANYCHAR_ML_STAR_PEEK_NEXT);\r
+      if (IS_MULTILINE(CTYPE_OPTION(NODE_QUANT_BODY(qn), reg)))\r
+        r = add_opcode(reg, OP_ANYCHAR_ML_STAR_PEEK_NEXT);\r
       else\r
-       r = add_opcode(reg, OP_ANYCHAR_STAR_PEEK_NEXT);\r
-      if (r) return r;\r
-      return add_bytes(reg, NSTR(qn->next_head_exact)->s, 1);\r
+        r = add_opcode(reg, OP_ANYCHAR_STAR_PEEK_NEXT);\r
+      if (r != 0) return r;\r
+      return add_bytes(reg, STR_(qn->next_head_exact)->s, 1);\r
     }\r
     else {\r
-      if (IS_MULTILINE(reg->options))\r
-       return add_opcode(reg, OP_ANYCHAR_ML_STAR);\r
+      if (IS_MULTILINE(CTYPE_OPTION(NODE_QUANT_BODY(qn), reg)))\r
+        return add_opcode(reg, OP_ANYCHAR_ML_STAR);\r
       else\r
-       return add_opcode(reg, OP_ANYCHAR_STAR);\r
+        return add_opcode(reg, OP_ANYCHAR_STAR);\r
     }\r
   }\r
 \r
-  if (empty_info != 0)\r
-    mod_tlen = tlen + (SIZE_OP_NULL_CHECK_START + SIZE_OP_NULL_CHECK_END);\r
-  else\r
+  if (empty_info == QUANT_BODY_IS_NOT_EMPTY)\r
     mod_tlen = tlen;\r
+  else\r
+    mod_tlen = tlen + (SIZE_OP_EMPTY_CHECK_START + SIZE_OP_EMPTY_CHECK_END);\r
 \r
   if (infinite &&\r
-      (qn->lower <= 1 || tlen * qn->lower <= QUANTIFIER_EXPAND_LIMIT_SIZE)) {\r
+      (qn->lower <= 1 ||\r
+       int_multiply_cmp(tlen, qn->lower, QUANTIFIER_EXPAND_LIMIT_SIZE) <= 0)) {\r
     if (qn->lower == 1 && tlen > QUANTIFIER_EXPAND_LIMIT_SIZE) {\r
       if (qn->greedy) {\r
-       if (IS_NOT_NULL(qn->head_exact))\r
-         r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH_OR_JUMP_EXACT1);\r
-       else if (IS_NOT_NULL(qn->next_head_exact))\r
-         r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH_IF_PEEK_NEXT);\r
-       else\r
-         r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH);\r
+        if (IS_NOT_NULL(qn->head_exact))\r
+          r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH_OR_JUMP_EXACT1);\r
+        else if (IS_NOT_NULL(qn->next_head_exact))\r
+          r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH_IF_PEEK_NEXT);\r
+        else\r
+          r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH);\r
       }\r
       else {\r
-       r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_JUMP);\r
+        r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_JUMP);\r
       }\r
-      if (r) return r;\r
+      if (r != 0) return r;\r
     }\r
     else {\r
-      r = compile_tree_n_times(qn->target, qn->lower, reg);\r
-      if (r) return r;\r
+      r = compile_tree_n_times(NODE_QUANT_BODY(qn), qn->lower, reg, env);\r
+      if (r != 0) return r;\r
     }\r
 \r
     if (qn->greedy) {\r
       if (IS_NOT_NULL(qn->head_exact)) {\r
-       r = add_opcode_rel_addr(reg, OP_PUSH_OR_JUMP_EXACT1,\r
-                            mod_tlen + SIZE_OP_JUMP);\r
-       if (r) return r;\r
-       add_bytes(reg, NSTR(qn->head_exact)->s, 1);\r
-       r = compile_tree_empty_check(qn->target, reg, empty_info);\r
-       if (r) return r;\r
-       r = add_opcode_rel_addr(reg, OP_JUMP,\r
-       -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH_OR_JUMP_EXACT1));\r
+        r = add_opcode_rel_addr(reg, OP_PUSH_OR_JUMP_EXACT1,\r
+                                mod_tlen + SIZE_OP_JUMP);\r
+        if (r != 0) return r;\r
+        add_bytes(reg, STR_(qn->head_exact)->s, 1);\r
+        r = compile_tree_empty_check(NODE_QUANT_BODY(qn), reg, empty_info, env);\r
+        if (r != 0) return r;\r
+        r = add_opcode_rel_addr(reg, OP_JUMP,\r
+           -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH_OR_JUMP_EXACT1));\r
       }\r
       else if (IS_NOT_NULL(qn->next_head_exact)) {\r
-       r = add_opcode_rel_addr(reg, OP_PUSH_IF_PEEK_NEXT,\r
-                               mod_tlen + SIZE_OP_JUMP);\r
-       if (r) return r;\r
-       add_bytes(reg, NSTR(qn->next_head_exact)->s, 1);\r
-       r = compile_tree_empty_check(qn->target, reg, empty_info);\r
-       if (r) return r;\r
-       r = add_opcode_rel_addr(reg, OP_JUMP,\r
-          -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH_IF_PEEK_NEXT));\r
+        r = add_opcode_rel_addr(reg, OP_PUSH_IF_PEEK_NEXT,\r
+                                mod_tlen + SIZE_OP_JUMP);\r
+        if (r != 0) return r;\r
+        add_bytes(reg, STR_(qn->next_head_exact)->s, 1);\r
+        r = compile_tree_empty_check(NODE_QUANT_BODY(qn), reg, empty_info, env);\r
+        if (r != 0) return r;\r
+        r = add_opcode_rel_addr(reg, OP_JUMP,\r
+           -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH_IF_PEEK_NEXT));\r
       }\r
       else {\r
-       r = add_opcode_rel_addr(reg, OP_PUSH, mod_tlen + SIZE_OP_JUMP);\r
-       if (r) return r;\r
-       r = compile_tree_empty_check(qn->target, reg, empty_info);\r
-       if (r) return r;\r
-       r = add_opcode_rel_addr(reg, OP_JUMP,\r
-                    -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH));\r
+        r = add_opcode_rel_addr(reg, OP_PUSH, mod_tlen + SIZE_OP_JUMP);\r
+        if (r != 0) return r;\r
+        r = compile_tree_empty_check(NODE_QUANT_BODY(qn), reg, empty_info, env);\r
+        if (r != 0) return r;\r
+        r = add_opcode_rel_addr(reg, OP_JUMP,\r
+                   -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH));\r
       }\r
     }\r
     else {\r
       r = add_opcode_rel_addr(reg, OP_JUMP, mod_tlen);\r
-      if (r) return r;\r
-      r = compile_tree_empty_check(qn->target, reg, empty_info);\r
-      if (r) return r;\r
+      if (r != 0) return r;\r
+      r = compile_tree_empty_check(NODE_QUANT_BODY(qn), reg, empty_info, env);\r
+      if (r != 0) return r;\r
       r = add_opcode_rel_addr(reg, OP_PUSH, -(mod_tlen + (int )SIZE_OP_PUSH));\r
     }\r
   }\r
   else if (qn->upper == 0 && qn->is_refered != 0) { /* /(?<n>..){0}/ */\r
     r = add_opcode_rel_addr(reg, OP_JUMP, tlen);\r
-    if (r) return r;\r
-    r = compile_tree(qn->target, reg);\r
+    if (r != 0) return r;\r
+    r = compile_tree(NODE_QUANT_BODY(qn), reg, env);\r
   }\r
-  else if (!infinite && qn->greedy &&\r
-           (qn->upper == 1 || (tlen + SIZE_OP_PUSH) * qn->upper\r
-                                  <= QUANTIFIER_EXPAND_LIMIT_SIZE)) {\r
+  else if (! infinite && qn->greedy &&\r
+           (qn->upper == 1 ||\r
+            int_multiply_cmp(tlen + SIZE_OP_PUSH, qn->upper,\r
+                             QUANTIFIER_EXPAND_LIMIT_SIZE) <= 0)) {\r
     int n = qn->upper - qn->lower;\r
 \r
-    r = compile_tree_n_times(qn->target, qn->lower, reg);\r
-    if (r) return r;\r
+    r = compile_tree_n_times(NODE_QUANT_BODY(qn), qn->lower, reg, env);\r
+    if (r != 0) return r;\r
 \r
     for (i = 0; i < n; i++) {\r
       r = add_opcode_rel_addr(reg, OP_PUSH,\r
-                          (n - i) * tlen + (n - i - 1) * SIZE_OP_PUSH);\r
-      if (r) return r;\r
-      r = compile_tree(qn->target, reg);\r
-      if (r) return r;\r
+                              (n - i) * tlen + (n - i - 1) * SIZE_OP_PUSH);\r
+      if (r != 0) return r;\r
+      r = compile_tree(NODE_QUANT_BODY(qn), reg, env);\r
+      if (r != 0) return r;\r
     }\r
   }\r
-  else if (!qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */\r
+  else if (! qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */\r
     r = add_opcode_rel_addr(reg, OP_PUSH, SIZE_OP_JUMP);\r
-    if (r) return r;\r
+    if (r != 0) return r;\r
     r = add_opcode_rel_addr(reg, OP_JUMP, tlen);\r
-    if (r) return r;\r
-    r = compile_tree(qn->target, reg);\r
+    if (r != 0) return r;\r
+    r = compile_tree(NODE_QUANT_BODY(qn), reg, env);\r
   }\r
   else {\r
-    r = compile_range_repeat_node(qn, mod_tlen, empty_info, reg);\r
+    r = compile_range_repeat_node(qn, mod_tlen, empty_info, reg, env);\r
   }\r
   return r;\r
 }\r
-#endif /* USE_COMBINATION_EXPLOSION_CHECK */\r
 \r
 static int\r
-compile_length_option_node(EncloseNode* node, regex_t* reg)\r
+compile_length_option_node(EnclosureNode* node, regex_t* reg)\r
 {\r
   int tlen;\r
   OnigOptionType prev = reg->options;\r
 \r
-  reg->options = node->option;\r
-  tlen = compile_length_tree(node->target, reg);\r
+  reg->options = node->o.options;\r
+  tlen = compile_length_tree(NODE_ENCLOSURE_BODY(node), reg);\r
   reg->options = prev;\r
 \r
-  if (tlen < 0) return tlen;\r
-\r
-  if (IS_DYNAMIC_OPTION(prev ^ node->option)) {\r
-    return SIZE_OP_SET_OPTION_PUSH + SIZE_OP_SET_OPTION + SIZE_OP_FAIL\r
-           + tlen + SIZE_OP_SET_OPTION;\r
-  }\r
-  else\r
-    return tlen;\r
+  return tlen;\r
 }\r
 \r
 static int\r
-compile_option_node(EncloseNode* node, regex_t* reg)\r
+compile_option_node(EnclosureNode* node, regex_t* reg, ScanEnv* env)\r
 {\r
   int r;\r
   OnigOptionType prev = reg->options;\r
 \r
-  if (IS_DYNAMIC_OPTION(prev ^ node->option)) {\r
-    r = add_opcode_option(reg, OP_SET_OPTION_PUSH, node->option);\r
-    if (r) return r;\r
-    r = add_opcode_option(reg, OP_SET_OPTION, prev);\r
-    if (r) return r;\r
-    r = add_opcode(reg, OP_FAIL);\r
-    if (r) return r;\r
-  }\r
-\r
-  reg->options = node->option;\r
-  r = compile_tree(node->target, reg);\r
+  reg->options = node->o.options;\r
+  r = compile_tree(NODE_ENCLOSURE_BODY(node), reg, env);\r
   reg->options = prev;\r
 \r
-  if (IS_DYNAMIC_OPTION(prev ^ node->option)) {\r
-    if (r) return r;\r
-    r = add_opcode_option(reg, OP_SET_OPTION, prev);\r
-  }\r
   return r;\r
 }\r
 \r
 static int\r
-compile_length_enclose_node(EncloseNode* node, regex_t* reg)\r
+compile_length_enclosure_node(EnclosureNode* node, regex_t* reg)\r
 {\r
   int len;\r
   int tlen;\r
-  QtfrNode* qn;\r
 \r
-  qn = NULL;\r
-\r
-  if (node->type == ENCLOSE_OPTION)\r
+  if (node->type == ENCLOSURE_OPTION)\r
     return compile_length_option_node(node, reg);\r
 \r
-  if (node->target) {\r
-    tlen = compile_length_tree(node->target, reg);\r
+  if (NODE_ENCLOSURE_BODY(node)) {\r
+    tlen = compile_length_tree(NODE_ENCLOSURE_BODY(node), reg);\r
     if (tlen < 0) return tlen;\r
   }\r
   else\r
     tlen = 0;\r
 \r
   switch (node->type) {\r
-  case ENCLOSE_MEMORY:\r
-#ifdef USE_SUBEXP_CALL\r
-    if (IS_ENCLOSE_CALLED(node)) {\r
+  case ENCLOSURE_MEMORY:\r
+#ifdef USE_CALL\r
+\r
+    if (node->m.regnum == 0 && NODE_IS_CALLED(node)) {\r
+      len = tlen + SIZE_OP_CALL + SIZE_OP_JUMP + SIZE_OP_RETURN;\r
+      return len;\r
+    }\r
+\r
+    if (NODE_IS_CALLED(node)) {\r
       len = SIZE_OP_MEMORY_START_PUSH + tlen\r
-         + SIZE_OP_CALL + SIZE_OP_JUMP + SIZE_OP_RETURN;\r
-      if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))\r
-       len += (IS_ENCLOSE_RECURSION(node)\r
-               ? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_PUSH);\r
+        + SIZE_OP_CALL + SIZE_OP_JUMP + SIZE_OP_RETURN;\r
+      if (MEM_STATUS_AT0(reg->bt_mem_end, node->m.regnum))\r
+        len += (NODE_IS_RECURSION(node)\r
+                ? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_PUSH);\r
       else\r
-       len += (IS_ENCLOSE_RECURSION(node)\r
-               ? SIZE_OP_MEMORY_END_REC : SIZE_OP_MEMORY_END);\r
+        len += (NODE_IS_RECURSION(node)\r
+                ? SIZE_OP_MEMORY_END_REC : SIZE_OP_MEMORY_END);\r
+    }\r
+    else if (NODE_IS_RECURSION(node)) {\r
+      len = SIZE_OP_MEMORY_START_PUSH;\r
+      len += tlen + (MEM_STATUS_AT0(reg->bt_mem_end, node->m.regnum)\r
+                     ? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_REC);\r
     }\r
     else\r
 #endif\r
     {\r
-      if (BIT_STATUS_AT(reg->bt_mem_start, node->regnum))\r
-       len = SIZE_OP_MEMORY_START_PUSH;\r
+      if (MEM_STATUS_AT0(reg->bt_mem_start, node->m.regnum))\r
+        len = SIZE_OP_MEMORY_START_PUSH;\r
       else\r
-       len = SIZE_OP_MEMORY_START;\r
+        len = SIZE_OP_MEMORY_START;\r
 \r
-      len += tlen + (BIT_STATUS_AT(reg->bt_mem_end, node->regnum)\r
-                    ? SIZE_OP_MEMORY_END_PUSH : SIZE_OP_MEMORY_END);\r
+      len += tlen + (MEM_STATUS_AT0(reg->bt_mem_end, node->m.regnum)\r
+                     ? SIZE_OP_MEMORY_END_PUSH : SIZE_OP_MEMORY_END);\r
     }\r
     break;\r
 \r
-  case ENCLOSE_STOP_BACKTRACK:\r
-    if (IS_ENCLOSE_STOP_BT_SIMPLE_REPEAT(node)) {\r
-      if (node->target == NULL) {\r
-        CHECK_NULL_RETURN_MEMERR(node->target);\r
-      }\r
-      qn = NQTFR(node->target);\r
-      tlen = compile_length_tree(qn->target, reg);\r
+  case ENCLOSURE_STOP_BACKTRACK:\r
+    if (NODE_IS_STOP_BT_SIMPLE_REPEAT(node)) {\r
+      QuantNode* qn = QUANT_(NODE_ENCLOSURE_BODY(node));\r
+      tlen = compile_length_tree(NODE_QUANT_BODY(qn), reg);\r
       if (tlen < 0) return tlen;\r
 \r
       len = tlen * qn->lower\r
-         + SIZE_OP_PUSH + tlen + SIZE_OP_POP + SIZE_OP_JUMP;\r
+        + SIZE_OP_PUSH + tlen + SIZE_OP_POP_OUT + SIZE_OP_JUMP;\r
     }\r
     else {\r
-      len = SIZE_OP_PUSH_STOP_BT + tlen + SIZE_OP_POP_STOP_BT;\r
+      len = SIZE_OP_ATOMIC_START + tlen + SIZE_OP_ATOMIC_END;\r
     }\r
     break;\r
 \r
-  default:\r
-    return ONIGERR_TYPE_BUG;\r
-    break;\r
-  }\r
+  case ENCLOSURE_IF_ELSE:\r
+    {\r
+      Node* cond = NODE_ENCLOSURE_BODY(node);\r
+      Node* Then = node->te.Then;\r
+      Node* Else = node->te.Else;\r
 \r
-  return len;\r
-}\r
+      len = compile_length_tree(cond, reg);\r
+      if (len < 0) return len;\r
+      len += SIZE_OP_PUSH;\r
+      len += SIZE_OP_ATOMIC_START + SIZE_OP_ATOMIC_END;\r
+\r
+      if (IS_NOT_NULL(Then)) {\r
+        tlen = compile_length_tree(Then, reg);\r
+        if (tlen < 0) return tlen;\r
+        len += tlen;\r
+      }\r
+\r
+      if (IS_NOT_NULL(Else)) {\r
+        len += SIZE_OP_JUMP;\r
+        tlen = compile_length_tree(Else, reg);\r
+        if (tlen < 0) return tlen;\r
+        len += tlen;\r
+      }\r
+    }\r
+    break;\r
+\r
+  default:\r
+    return ONIGERR_TYPE_BUG;\r
+    break;\r
+  }\r
+\r
+  return len;\r
+}\r
 \r
 static int get_char_length_tree(Node* node, regex_t* reg, int* len);\r
 \r
 static int\r
-compile_enclose_node(EncloseNode* node, regex_t* reg)\r
+compile_enclosure_memory_node(EnclosureNode* node, regex_t* reg, ScanEnv* env)\r
 {\r
-  int r, len;\r
+  int r;\r
+  int len;\r
 \r
-  if (node->type == ENCLOSE_OPTION)\r
-    return compile_option_node(node, reg);\r
+#ifdef USE_CALL\r
+  if (node->m.regnum == 0 && NODE_IS_CALLED(node)) {\r
+    r = add_opcode(reg, OP_CALL);\r
+    if (r != 0) return r;\r
+    node->m.called_addr = BB_GET_OFFSET_POS(reg) + SIZE_ABSADDR + SIZE_OP_JUMP;\r
+    NODE_STATUS_ADD(node, ADDR_FIXED);\r
+    r = add_abs_addr(reg, (int )node->m.called_addr);\r
+    if (r != 0) return r;\r
+    len = compile_length_tree(NODE_ENCLOSURE_BODY(node), reg);\r
+    len += SIZE_OP_RETURN;\r
+    r = add_opcode_rel_addr(reg, OP_JUMP, len);\r
+    if (r != 0) return r;\r
+\r
+    r = compile_tree(NODE_ENCLOSURE_BODY(node), reg, env);\r
+    if (r != 0) return r;\r
+    r = add_opcode(reg, OP_RETURN);\r
+    return r;\r
+  }\r
 \r
-  switch (node->type) {\r
-  case ENCLOSE_MEMORY:\r
-#ifdef USE_SUBEXP_CALL\r
-    if (IS_ENCLOSE_CALLED(node)) {\r
-      r = add_opcode(reg, OP_CALL);\r
-      if (r) return r;\r
-      node->call_addr = BBUF_GET_OFFSET_POS(reg) + SIZE_ABSADDR + SIZE_OP_JUMP;\r
-      node->state |= NST_ADDR_FIXED;\r
-      r = add_abs_addr(reg, (int )node->call_addr);\r
-      if (r) return r;\r
-      len = compile_length_tree(node->target, reg);\r
-      len += (SIZE_OP_MEMORY_START_PUSH + SIZE_OP_RETURN);\r
-      if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))\r
-       len += (IS_ENCLOSE_RECURSION(node)\r
-               ? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_PUSH);\r
-      else\r
-       len += (IS_ENCLOSE_RECURSION(node)\r
-               ? SIZE_OP_MEMORY_END_REC : SIZE_OP_MEMORY_END);\r
+  if (NODE_IS_CALLED(node)) {\r
+    r = add_opcode(reg, OP_CALL);\r
+    if (r != 0) return r;\r
+    node->m.called_addr = BB_GET_OFFSET_POS(reg) + SIZE_ABSADDR + SIZE_OP_JUMP;\r
+    NODE_STATUS_ADD(node, ADDR_FIXED);\r
+    r = add_abs_addr(reg, (int )node->m.called_addr);\r
+    if (r != 0) return r;\r
+    len = compile_length_tree(NODE_ENCLOSURE_BODY(node), reg);\r
+    len += (SIZE_OP_MEMORY_START_PUSH + SIZE_OP_RETURN);\r
+    if (MEM_STATUS_AT0(reg->bt_mem_end, node->m.regnum))\r
+      len += (NODE_IS_RECURSION(node)\r
+              ? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_PUSH);\r
+    else\r
+      len += (NODE_IS_RECURSION(node)\r
+              ? SIZE_OP_MEMORY_END_REC : SIZE_OP_MEMORY_END);\r
 \r
-      r = add_opcode_rel_addr(reg, OP_JUMP, len);\r
-      if (r) return r;\r
-    }\r
+    r = add_opcode_rel_addr(reg, OP_JUMP, len);\r
+    if (r != 0) return r;\r
+  }\r
 #endif\r
-    if (BIT_STATUS_AT(reg->bt_mem_start, node->regnum))\r
-      r = add_opcode(reg, OP_MEMORY_START_PUSH);\r
-    else\r
-      r = add_opcode(reg, OP_MEMORY_START);\r
-    if (r) return r;\r
-    r = add_mem_num(reg, node->regnum);\r
-    if (r) return r;\r
-    r = compile_tree(node->target, reg);\r
-    if (r) return r;\r
-#ifdef USE_SUBEXP_CALL\r
-    if (IS_ENCLOSE_CALLED(node)) {\r
-      if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))\r
-       r = add_opcode(reg, (IS_ENCLOSE_RECURSION(node)\r
-                            ? OP_MEMORY_END_PUSH_REC : OP_MEMORY_END_PUSH));\r
-      else\r
-       r = add_opcode(reg, (IS_ENCLOSE_RECURSION(node)\r
-                            ? OP_MEMORY_END_REC : OP_MEMORY_END));\r
 \r
-      if (r) return r;\r
-      r = add_mem_num(reg, node->regnum);\r
-      if (r) return r;\r
-      r = add_opcode(reg, OP_RETURN);\r
-    }\r
-    else\r
+  if (MEM_STATUS_AT0(reg->bt_mem_start, node->m.regnum))\r
+    r = add_opcode(reg, OP_MEMORY_START_PUSH);\r
+  else\r
+    r = add_opcode(reg, OP_MEMORY_START);\r
+  if (r != 0) return r;\r
+  r = add_mem_num(reg, node->m.regnum);\r
+  if (r != 0) return r;\r
+  r = compile_tree(NODE_ENCLOSURE_BODY(node), reg, env);\r
+  if (r != 0) return r;\r
+\r
+#ifdef USE_CALL\r
+  if (MEM_STATUS_AT0(reg->bt_mem_end, node->m.regnum))\r
+    r = add_opcode(reg, (NODE_IS_RECURSION(node)\r
+                         ? OP_MEMORY_END_PUSH_REC : OP_MEMORY_END_PUSH));\r
+  else\r
+    r = add_opcode(reg, (NODE_IS_RECURSION(node)\r
+                         ? OP_MEMORY_END_REC : OP_MEMORY_END));\r
+  if (r != 0) return r;\r
+  r = add_mem_num(reg, node->m.regnum);\r
+  if (NODE_IS_CALLED(node)) {\r
+    if (r != 0) return r;\r
+    r = add_opcode(reg, OP_RETURN);\r
+  }\r
+#else\r
+  if (MEM_STATUS_AT0(reg->bt_mem_end, node->m.regnum))\r
+    r = add_opcode(reg, OP_MEMORY_END_PUSH);\r
+  else\r
+    r = add_opcode(reg, OP_MEMORY_END);\r
+  if (r != 0) return r;\r
+  r = add_mem_num(reg, node->m.regnum);\r
 #endif\r
-    {\r
-      if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))\r
-       r = add_opcode(reg, OP_MEMORY_END_PUSH);\r
-      else\r
-       r = add_opcode(reg, OP_MEMORY_END);\r
-      if (r) return r;\r
-      r = add_mem_num(reg, node->regnum);\r
-    }\r
+\r
+  return r;\r
+}\r
+\r
+static int\r
+compile_enclosure_node(EnclosureNode* node, regex_t* reg, ScanEnv* env)\r
+{\r
+  int r, len;\r
+\r
+  switch (node->type) {\r
+  case ENCLOSURE_MEMORY:\r
+    r = compile_enclosure_memory_node(node, reg, env);\r
+    break;\r
+\r
+  case ENCLOSURE_OPTION:\r
+    r = compile_option_node(node, reg, env);\r
     break;\r
 \r
-  case ENCLOSE_STOP_BACKTRACK:\r
-    if (IS_ENCLOSE_STOP_BT_SIMPLE_REPEAT(node)) {\r
-      QtfrNode* qn = NQTFR(node->target);\r
-      r = compile_tree_n_times(qn->target, qn->lower, reg);\r
-      if (r) return r;\r
+  case ENCLOSURE_STOP_BACKTRACK:\r
+    if (NODE_IS_STOP_BT_SIMPLE_REPEAT(node)) {\r
+      QuantNode* qn = QUANT_(NODE_ENCLOSURE_BODY(node));\r
+      r = compile_tree_n_times(NODE_QUANT_BODY(qn), qn->lower, reg, env);\r
+      if (r != 0) return r;\r
 \r
-      len = compile_length_tree(qn->target, reg);\r
+      len = compile_length_tree(NODE_QUANT_BODY(qn), reg);\r
       if (len < 0) return len;\r
 \r
-      r = add_opcode_rel_addr(reg, OP_PUSH, len + SIZE_OP_POP + SIZE_OP_JUMP);\r
-      if (r) return r;\r
-      r = compile_tree(qn->target, reg);\r
-      if (r) return r;\r
-      r = add_opcode(reg, OP_POP);\r
-      if (r) return r;\r
+      r = add_opcode_rel_addr(reg, OP_PUSH, len + SIZE_OP_POP_OUT + SIZE_OP_JUMP);\r
+      if (r != 0) return r;\r
+      r = compile_tree(NODE_QUANT_BODY(qn), reg, env);\r
+      if (r != 0) return r;\r
+      r = add_opcode(reg, OP_POP_OUT);\r
+      if (r != 0) return r;\r
       r = add_opcode_rel_addr(reg, OP_JUMP,\r
-        -((int )SIZE_OP_PUSH + len + (int )SIZE_OP_POP + (int )SIZE_OP_JUMP));\r
+           -((int )SIZE_OP_PUSH + len + (int )SIZE_OP_POP_OUT + (int )SIZE_OP_JUMP));\r
     }\r
     else {\r
-      r = add_opcode(reg, OP_PUSH_STOP_BT);\r
-      if (r) return r;\r
-      r = compile_tree(node->target, reg);\r
-      if (r) return r;\r
-      r = add_opcode(reg, OP_POP_STOP_BT);\r
+      r = add_opcode(reg, OP_ATOMIC_START);\r
+      if (r != 0) return r;\r
+      r = compile_tree(NODE_ENCLOSURE_BODY(node), reg, env);\r
+      if (r != 0) return r;\r
+      r = add_opcode(reg, OP_ATOMIC_END);\r
+    }\r
+    break;\r
+\r
+  case ENCLOSURE_IF_ELSE:\r
+    {\r
+      int cond_len, then_len, jump_len;\r
+      Node* cond = NODE_ENCLOSURE_BODY(node);\r
+      Node* Then = node->te.Then;\r
+      Node* Else = node->te.Else;\r
+\r
+      r = add_opcode(reg, OP_ATOMIC_START);\r
+      if (r != 0) return r;\r
+\r
+      cond_len = compile_length_tree(cond, reg);\r
+      if (cond_len < 0) return cond_len;\r
+      if (IS_NOT_NULL(Then)) {\r
+        then_len = compile_length_tree(Then, reg);\r
+        if (then_len < 0) return then_len;\r
+      }\r
+      else\r
+        then_len = 0;\r
+\r
+      jump_len = cond_len + then_len + SIZE_OP_ATOMIC_END;\r
+      if (IS_NOT_NULL(Else)) jump_len += SIZE_OP_JUMP;\r
+\r
+      r = add_opcode_rel_addr(reg, OP_PUSH, jump_len);\r
+      if (r != 0) return r;\r
+      r = compile_tree(cond, reg, env);\r
+      if (r != 0) return r;\r
+      r = add_opcode(reg, OP_ATOMIC_END);\r
+      if (r != 0) return r;\r
+\r
+      if (IS_NOT_NULL(Then)) {\r
+        r = compile_tree(Then, reg, env);\r
+        if (r != 0) return r;\r
+      }\r
+\r
+      if (IS_NOT_NULL(Else)) {\r
+        int else_len = compile_length_tree(Else, reg);\r
+        r = add_opcode_rel_addr(reg, OP_JUMP, else_len);\r
+        if (r != 0) return r;\r
+        r = compile_tree(Else, reg, env);\r
+      }\r
     }\r
     break;\r
 \r
@@ -1385,23 +1299,37 @@ compile_length_anchor_node(AnchorNode* node, regex_t* reg)
   int len;\r
   int tlen = 0;\r
 \r
-  if (node->target) {\r
-    tlen = compile_length_tree(node->target, reg);\r
+  if (IS_NOT_NULL(NODE_ANCHOR_BODY(node))) {\r
+    tlen = compile_length_tree(NODE_ANCHOR_BODY(node), reg);\r
     if (tlen < 0) return tlen;\r
   }\r
 \r
   switch (node->type) {\r
   case ANCHOR_PREC_READ:\r
-    len = SIZE_OP_PUSH_POS + tlen + SIZE_OP_POP_POS;\r
+    len = SIZE_OP_PREC_READ_START + tlen + SIZE_OP_PREC_READ_END;\r
     break;\r
   case ANCHOR_PREC_READ_NOT:\r
-    len = SIZE_OP_PUSH_POS_NOT + tlen + SIZE_OP_FAIL_POS;\r
+    len = SIZE_OP_PREC_READ_NOT_START + tlen + SIZE_OP_PREC_READ_NOT_END;\r
     break;\r
   case ANCHOR_LOOK_BEHIND:\r
     len = SIZE_OP_LOOK_BEHIND + tlen;\r
     break;\r
   case ANCHOR_LOOK_BEHIND_NOT:\r
-    len = SIZE_OP_PUSH_LOOK_BEHIND_NOT + tlen + SIZE_OP_FAIL_LOOK_BEHIND_NOT;\r
+    len = SIZE_OP_LOOK_BEHIND_NOT_START + tlen + SIZE_OP_LOOK_BEHIND_NOT_END;\r
+    break;\r
+\r
+  case ANCHOR_WORD_BOUNDARY:\r
+  case ANCHOR_NO_WORD_BOUNDARY:\r
+#ifdef USE_WORD_BEGIN_END\r
+  case ANCHOR_WORD_BEGIN:\r
+  case ANCHOR_WORD_END:\r
+#endif\r
+    len = SIZE_OP_WORD_BOUNDARY;\r
+    break;\r
+\r
+  case ANCHOR_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY:\r
+  case ANCHOR_NO_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY:\r
+    len = SIZE_OPCODE;\r
     break;\r
 \r
   default:\r
@@ -1413,9 +1341,10 @@ compile_length_anchor_node(AnchorNode* node, regex_t* reg)
 }\r
 \r
 static int\r
-compile_anchor_node(AnchorNode* node, regex_t* reg)\r
+compile_anchor_node(AnchorNode* node, regex_t* reg, ScanEnv* env)\r
 {\r
   int r, len;\r
+  enum OpCode op;\r
 \r
   switch (node->type) {\r
   case ANCHOR_BEGIN_BUF:      r = add_opcode(reg, OP_BEGIN_BUF);      break;\r
@@ -1425,66 +1354,89 @@ compile_anchor_node(AnchorNode* node, regex_t* reg)
   case ANCHOR_SEMI_END_BUF:   r = add_opcode(reg, OP_SEMI_END_BUF);   break;\r
   case ANCHOR_BEGIN_POSITION: r = add_opcode(reg, OP_BEGIN_POSITION); break;\r
 \r
-  case ANCHOR_WORD_BOUND:     r = add_opcode(reg, OP_WORD_BOUND);     break;\r
-  case ANCHOR_NOT_WORD_BOUND: r = add_opcode(reg, OP_NOT_WORD_BOUND); break;\r
+  case ANCHOR_WORD_BOUNDARY:\r
+    op = OP_WORD_BOUNDARY;\r
+  word:\r
+    r = add_opcode(reg, op);\r
+    if (r != 0) return r;\r
+    r = add_mode(reg, (ModeType )node->ascii_mode);\r
+    break;\r
+\r
+  case ANCHOR_NO_WORD_BOUNDARY:\r
+    op = OP_NO_WORD_BOUNDARY; goto word;\r
+    break;\r
 #ifdef USE_WORD_BEGIN_END\r
-  case ANCHOR_WORD_BEGIN:     r = add_opcode(reg, OP_WORD_BEGIN);     break;\r
-  case ANCHOR_WORD_END:       r = add_opcode(reg, OP_WORD_END);       break;\r
+  case ANCHOR_WORD_BEGIN:\r
+    op = OP_WORD_BEGIN; goto word;\r
+    break;\r
+  case ANCHOR_WORD_END:\r
+    op = OP_WORD_END; goto word;\r
+    break;\r
 #endif\r
 \r
+  case ANCHOR_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY:\r
+    r = add_opcode(reg, OP_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY);\r
+    break;\r
+\r
+  case ANCHOR_NO_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY:\r
+    r = add_opcode(reg, OP_NO_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY);\r
+    break;\r
+\r
   case ANCHOR_PREC_READ:\r
-    r = add_opcode(reg, OP_PUSH_POS);\r
-    if (r) return r;\r
-    r = compile_tree(node->target, reg);\r
-    if (r) return r;\r
-    r = add_opcode(reg, OP_POP_POS);\r
+    r = add_opcode(reg, OP_PREC_READ_START);\r
+    if (r != 0) return r;\r
+    r = compile_tree(NODE_ANCHOR_BODY(node), reg, env);\r
+    if (r != 0) return r;\r
+    r = add_opcode(reg, OP_PREC_READ_END);\r
     break;\r
 \r
   case ANCHOR_PREC_READ_NOT:\r
-    len = compile_length_tree(node->target, reg);\r
+    len = compile_length_tree(NODE_ANCHOR_BODY(node), reg);\r
     if (len < 0) return len;\r
-    r = add_opcode_rel_addr(reg, OP_PUSH_POS_NOT, len + SIZE_OP_FAIL_POS);\r
-    if (r) return r;\r
-    r = compile_tree(node->target, reg);\r
-    if (r) return r;\r
-    r = add_opcode(reg, OP_FAIL_POS);\r
+    r = add_opcode_rel_addr(reg, OP_PREC_READ_NOT_START, len + SIZE_OP_PREC_READ_NOT_END);\r
+    if (r != 0) return r;\r
+    r = compile_tree(NODE_ANCHOR_BODY(node), reg, env);\r
+    if (r != 0) return r;\r
+    r = add_opcode(reg, OP_PREC_READ_NOT_END);\r
     break;\r
 \r
   case ANCHOR_LOOK_BEHIND:\r
     {\r
       int n;\r
       r = add_opcode(reg, OP_LOOK_BEHIND);\r
-      if (r) return r;\r
+      if (r != 0) return r;\r
       if (node->char_len < 0) {\r
-       r = get_char_length_tree(node->target, reg, &n);\r
-       if (r) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;\r
+        r = get_char_length_tree(NODE_ANCHOR_BODY(node), reg, &n);\r
+        if (r != 0) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;\r
       }\r
       else\r
-       n = node->char_len;\r
+        n = node->char_len;\r
+\r
       r = add_length(reg, n);\r
-      if (r) return r;\r
-      r = compile_tree(node->target, reg);\r
+      if (r != 0) return r;\r
+      r = compile_tree(NODE_ANCHOR_BODY(node), reg, env);\r
     }\r
     break;\r
 \r
   case ANCHOR_LOOK_BEHIND_NOT:\r
     {\r
       int n;\r
-      len = compile_length_tree(node->target, reg);\r
-      r = add_opcode_rel_addr(reg, OP_PUSH_LOOK_BEHIND_NOT,\r
-                          len + SIZE_OP_FAIL_LOOK_BEHIND_NOT);\r
-      if (r) return r;\r
+\r
+      len = compile_length_tree(NODE_ANCHOR_BODY(node), reg);\r
+      r = add_opcode_rel_addr(reg, OP_LOOK_BEHIND_NOT_START,\r
+                              len + SIZE_OP_LOOK_BEHIND_NOT_END);\r
+      if (r != 0) return r;\r
       if (node->char_len < 0) {\r
-       r = get_char_length_tree(node->target, reg, &n);\r
-       if (r) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;\r
+        r = get_char_length_tree(NODE_ANCHOR_BODY(node), reg, &n);\r
+        if (r != 0) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;\r
       }\r
       else\r
-       n = node->char_len;\r
+        n = node->char_len;\r
       r = add_length(reg, n);\r
-      if (r) return r;\r
-      r = compile_tree(node->target, reg);\r
-      if (r) return r;\r
-      r = add_opcode(reg, OP_FAIL_LOOK_BEHIND_NOT);\r
+      if (r != 0) return r;\r
+      r = compile_tree(NODE_ANCHOR_BODY(node), reg, env);\r
+      if (r != 0) return r;\r
+      r = add_opcode(reg, OP_LOOK_BEHIND_NOT_END);\r
     }\r
     break;\r
 \r
@@ -1496,89 +1448,204 @@ compile_anchor_node(AnchorNode* node, regex_t* reg)
   return r;\r
 }\r
 \r
+static int\r
+compile_gimmick_node(GimmickNode* node, regex_t* reg)\r
+{\r
+  int r;\r
+\r
+  switch (node->type) {\r
+  case GIMMICK_FAIL:\r
+    r = add_opcode(reg, OP_FAIL);\r
+    break;\r
+\r
+  case GIMMICK_KEEP:\r
+    r = add_opcode(reg, OP_PUSH_SAVE_VAL);\r
+    if (r != 0) return r;\r
+    r = add_save_type(reg, SAVE_KEEP);\r
+    if (r != 0) return r;\r
+    r = add_mem_num(reg, node->id);\r
+    break;\r
+\r
+  case GIMMICK_SAVE:\r
+    r = add_opcode(reg, OP_PUSH_SAVE_VAL);\r
+    if (r != 0) return r;\r
+    r = add_save_type(reg, node->detail_type);\r
+    if (r != 0) return r;\r
+    r = add_mem_num(reg, node->id);\r
+    break;\r
+\r
+  case GIMMICK_UPDATE_VAR:\r
+    r = add_opcode(reg, OP_UPDATE_VAR);\r
+    if (r != 0) return r;\r
+    r = add_update_var_type(reg, node->detail_type);\r
+    if (r != 0) return r;\r
+    r = add_mem_num(reg, node->id);\r
+    break;\r
+\r
+#ifdef USE_CALLOUT\r
+  case GIMMICK_CALLOUT:\r
+    switch (node->detail_type) {\r
+    case ONIG_CALLOUT_OF_CONTENTS:\r
+    case ONIG_CALLOUT_OF_NAME:\r
+      {\r
+        r = add_opcode(reg, (node->detail_type == ONIG_CALLOUT_OF_CONTENTS) ?\r
+                                  OP_CALLOUT_CONTENTS : OP_CALLOUT_NAME);\r
+        if (r != 0) return r;\r
+        if (node->detail_type == ONIG_CALLOUT_OF_NAME) {\r
+          r = add_mem_num(reg, node->id);\r
+          if (r != 0) return r;\r
+        }\r
+        r = add_mem_num(reg, node->num);\r
+        if (r != 0) return r;\r
+      }\r
+      break;\r
+\r
+    default:\r
+      r = ONIGERR_TYPE_BUG;\r
+      break;\r
+    }\r
+#endif\r
+  }\r
+\r
+  return r;\r
+}\r
+\r
+static int\r
+compile_length_gimmick_node(GimmickNode* node, regex_t* reg)\r
+{\r
+  int len;\r
+\r
+  switch (node->type) {\r
+  case GIMMICK_FAIL:\r
+    len = SIZE_OP_FAIL;\r
+    break;\r
+\r
+  case GIMMICK_KEEP:\r
+  case GIMMICK_SAVE:\r
+    len = SIZE_OP_PUSH_SAVE_VAL;\r
+    break;\r
+\r
+  case GIMMICK_UPDATE_VAR:\r
+    len = SIZE_OP_UPDATE_VAR;\r
+    break;\r
+\r
+#ifdef USE_CALLOUT\r
+  case GIMMICK_CALLOUT:\r
+    switch (node->detail_type) {\r
+    case ONIG_CALLOUT_OF_CONTENTS:\r
+      len = SIZE_OP_CALLOUT_CONTENTS;\r
+      break;\r
+    case ONIG_CALLOUT_OF_NAME:\r
+      len = SIZE_OP_CALLOUT_NAME;\r
+      break;\r
+\r
+    default:\r
+      len = ONIGERR_TYPE_BUG;\r
+      break;\r
+    }\r
+    break;\r
+#endif\r
+  }\r
+\r
+  return len;\r
+}\r
+\r
 static int\r
 compile_length_tree(Node* node, regex_t* reg)\r
 {\r
-  int len, type, r;\r
+  int len, r;\r
 \r
-  type = NTYPE(node);\r
-  switch (type) {\r
-  case NT_LIST:\r
+  switch (NODE_TYPE(node)) {\r
+  case NODE_LIST:\r
     len = 0;\r
     do {\r
-      r = compile_length_tree(NCAR(node), reg);\r
+      r = compile_length_tree(NODE_CAR(node), reg);\r
       if (r < 0) return r;\r
       len += r;\r
-    } while (IS_NOT_NULL(node = NCDR(node)));\r
+    } while (IS_NOT_NULL(node = NODE_CDR(node)));\r
     r = len;\r
     break;\r
 \r
-  case NT_ALT:\r
+  case NODE_ALT:\r
     {\r
       int n;\r
 \r
       n = r = 0;\r
       do {\r
-       r += compile_length_tree(NCAR(node), reg);\r
-       n++;\r
-      } while (IS_NOT_NULL(node = NCDR(node)));\r
+        r += compile_length_tree(NODE_CAR(node), reg);\r
+        n++;\r
+      } while (IS_NOT_NULL(node = NODE_CDR(node)));\r
       r += (SIZE_OP_PUSH + SIZE_OP_JUMP) * (n - 1);\r
     }\r
     break;\r
 \r
-  case NT_STR:\r
-    if (NSTRING_IS_RAW(node))\r
-      r = compile_length_string_raw_node(NSTR(node), reg);\r
+  case NODE_STRING:\r
+    if (NODE_STRING_IS_RAW(node))\r
+      r = compile_length_string_raw_node(STR_(node), reg);\r
     else\r
       r = compile_length_string_node(node, reg);\r
     break;\r
 \r
-  case NT_CCLASS:\r
-    r = compile_length_cclass_node(NCCLASS(node), reg);\r
+  case NODE_CCLASS:\r
+    r = compile_length_cclass_node(CCLASS_(node), reg);\r
     break;\r
 \r
-  case NT_CTYPE:\r
-  case NT_CANY:\r
+  case NODE_CTYPE:\r
     r = SIZE_OPCODE;\r
     break;\r
 \r
-  case NT_BREF:\r
+  case NODE_BACKREF:\r
     {\r
-      BRefNode* br = NBREF(node);\r
+      BackRefNode* br = BACKREF_(node);\r
 \r
+      if (NODE_IS_CHECKER(node)) {\r
 #ifdef USE_BACKREF_WITH_LEVEL\r
-      if (IS_BACKREF_NEST_LEVEL(br)) {\r
-        r = SIZE_OPCODE + SIZE_OPTION + SIZE_LENGTH +\r
-            SIZE_LENGTH + (SIZE_MEMNUM * br->back_num);\r
-      }\r
-      else\r
+        if (NODE_IS_NEST_LEVEL(node)) {\r
+          r = SIZE_OPCODE + SIZE_LENGTH + SIZE_LENGTH + (SIZE_MEMNUM * br->back_num);\r
+        }\r
+        else\r
 #endif\r
-      if (br->back_num == 1) {\r
-       r = ((!IS_IGNORECASE(reg->options) && br->back_static[0] <= 2)\r
-            ? SIZE_OPCODE : (SIZE_OPCODE + SIZE_MEMNUM));\r
+          r = SIZE_OPCODE + SIZE_LENGTH + (SIZE_MEMNUM * br->back_num);\r
       }\r
       else {\r
-       r = SIZE_OPCODE + SIZE_LENGTH + (SIZE_MEMNUM * br->back_num);\r
+#ifdef USE_BACKREF_WITH_LEVEL\r
+        if (NODE_IS_NEST_LEVEL(node)) {\r
+          r = SIZE_OPCODE + SIZE_OPTION + SIZE_LENGTH +\r
+            SIZE_LENGTH + (SIZE_MEMNUM * br->back_num);\r
+        }\r
+        else\r
+#endif\r
+        if (br->back_num == 1) {\r
+          r = ((!IS_IGNORECASE(reg->options) && br->back_static[0] <= 2)\r
+               ? SIZE_OPCODE : (SIZE_OPCODE + SIZE_MEMNUM));\r
+        }\r
+        else {\r
+          r = SIZE_OPCODE + SIZE_LENGTH + (SIZE_MEMNUM * br->back_num);\r
+        }\r
       }\r
     }\r
     break;\r
 \r
-#ifdef USE_SUBEXP_CALL\r
-  case NT_CALL:\r
+#ifdef USE_CALL\r
+  case NODE_CALL:\r
     r = SIZE_OP_CALL;\r
     break;\r
 #endif\r
 \r
-  case NT_QTFR:\r
-    r = compile_length_quantifier_node(NQTFR(node), reg);\r
+  case NODE_QUANT:\r
+    r = compile_length_quantifier_node(QUANT_(node), reg);\r
+    break;\r
+\r
+  case NODE_ENCLOSURE:\r
+    r = compile_length_enclosure_node(ENCLOSURE_(node), reg);\r
     break;\r
 \r
-  case NT_ENCLOSE:\r
-    r = compile_length_enclose_node(NENCLOSE(node), reg);\r
+  case NODE_ANCHOR:\r
+    r = compile_length_anchor_node(ANCHOR_(node), reg);\r
     break;\r
 \r
-  case NT_ANCHOR:\r
-    r = compile_length_anchor_node(NANCHOR(node), reg);\r
+  case NODE_GIMMICK:\r
+    r = compile_length_gimmick_node(GIMMICK_(node), reg);\r
     break;\r
 \r
   default:\r
@@ -1590,165 +1657,191 @@ compile_length_tree(Node* node, regex_t* reg)
 }\r
 \r
 static int\r
-compile_tree(Node* node, regex_t* reg)\r
+compile_tree(Node* node, regex_t* reg, ScanEnv* env)\r
 {\r
-  int n, type, len, pos, r = 0;\r
+  int n, len, pos, r = 0;\r
 \r
-  type = NTYPE(node);\r
-  switch (type) {\r
-  case NT_LIST:\r
+  switch (NODE_TYPE(node)) {\r
+  case NODE_LIST:\r
     do {\r
-      r = compile_tree(NCAR(node), reg);\r
-    } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));\r
+      r = compile_tree(NODE_CAR(node), reg, env);\r
+    } while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));\r
     break;\r
 \r
-  case NT_ALT:\r
+  case NODE_ALT:\r
     {\r
       Node* x = node;\r
       len = 0;\r
       do {\r
-       len += compile_length_tree(NCAR(x), reg);\r
-       if (NCDR(x) != NULL) {\r
-         len += SIZE_OP_PUSH + SIZE_OP_JUMP;\r
-       }\r
-      } while (IS_NOT_NULL(x = NCDR(x)));\r
+        len += compile_length_tree(NODE_CAR(x), reg);\r
+        if (IS_NOT_NULL(NODE_CDR(x))) {\r
+          len += SIZE_OP_PUSH + SIZE_OP_JUMP;\r
+        }\r
+      } while (IS_NOT_NULL(x = NODE_CDR(x)));\r
       pos = reg->used + len;  /* goal position */\r
 \r
       do {\r
-       len = compile_length_tree(NCAR(node), reg);\r
-       if (IS_NOT_NULL(NCDR(node))) {\r
-         r = add_opcode_rel_addr(reg, OP_PUSH, len + SIZE_OP_JUMP);\r
-         if (r) break;\r
-       }\r
-       r = compile_tree(NCAR(node), reg);\r
-       if (r) break;\r
-       if (IS_NOT_NULL(NCDR(node))) {\r
-         len = pos - (reg->used + SIZE_OP_JUMP);\r
-         r = add_opcode_rel_addr(reg, OP_JUMP, len);\r
-         if (r) break;\r
-       }\r
-      } while (IS_NOT_NULL(node = NCDR(node)));\r
-    }\r
-    break;\r
-\r
-  case NT_STR:\r
-    if (NSTRING_IS_RAW(node))\r
-      r = compile_string_raw_node(NSTR(node), reg);\r
+        len = compile_length_tree(NODE_CAR(node), reg);\r
+        if (IS_NOT_NULL(NODE_CDR(node))) {\r
+          enum OpCode push = NODE_IS_SUPER(node) ? OP_PUSH_SUPER : OP_PUSH;\r
+          r = add_opcode_rel_addr(reg, push, len + SIZE_OP_JUMP);\r
+          if (r != 0) break;\r
+        }\r
+        r = compile_tree(NODE_CAR(node), reg, env);\r
+        if (r != 0) break;\r
+        if (IS_NOT_NULL(NODE_CDR(node))) {\r
+          len = pos - (reg->used + SIZE_OP_JUMP);\r
+          r = add_opcode_rel_addr(reg, OP_JUMP, len);\r
+          if (r != 0) break;\r
+        }\r
+      } while (IS_NOT_NULL(node = NODE_CDR(node)));\r
+    }\r
+    break;\r
+\r
+  case NODE_STRING:\r
+    if (NODE_STRING_IS_RAW(node))\r
+      r = compile_string_raw_node(STR_(node), reg);\r
     else\r
       r = compile_string_node(node, reg);\r
     break;\r
 \r
-  case NT_CCLASS:\r
-    r = compile_cclass_node(NCCLASS(node), reg);\r
+  case NODE_CCLASS:\r
+    r = compile_cclass_node(CCLASS_(node), reg);\r
     break;\r
 \r
-  case NT_CTYPE:\r
+  case NODE_CTYPE:\r
     {\r
       int op;\r
 \r
-      switch (NCTYPE(node)->ctype) {\r
+      switch (CTYPE_(node)->ctype) {\r
+      case CTYPE_ANYCHAR:\r
+        if (IS_MULTILINE(CTYPE_OPTION(node, reg)))\r
+          r = add_opcode(reg, OP_ANYCHAR_ML);\r
+        else\r
+          r = add_opcode(reg, OP_ANYCHAR);\r
+        break;\r
+\r
       case ONIGENC_CTYPE_WORD:\r
-       if (NCTYPE(node)->not != 0)  op = OP_NOT_WORD;\r
-       else                         op = OP_WORD;\r
-       break;\r
+        if (CTYPE_(node)->ascii_mode == 0) {\r
+          op = CTYPE_(node)->not != 0 ? OP_NO_WORD : OP_WORD;\r
+        }\r
+        else {\r
+          op = CTYPE_(node)->not != 0 ? OP_NO_WORD_ASCII : OP_WORD_ASCII;\r
+        }\r
+        r = add_opcode(reg, op);\r
+        break;\r
+\r
       default:\r
-       return ONIGERR_TYPE_BUG;\r
-       break;\r
+        return ONIGERR_TYPE_BUG;\r
+        break;\r
       }\r
-      r = add_opcode(reg, op);\r
     }\r
     break;\r
 \r
-  case NT_CANY:\r
-    if (IS_MULTILINE(reg->options))\r
-      r = add_opcode(reg, OP_ANYCHAR_ML);\r
-    else\r
-      r = add_opcode(reg, OP_ANYCHAR);\r
-    break;\r
-\r
-  case NT_BREF:\r
+  case NODE_BACKREF:\r
     {\r
-      BRefNode* br = NBREF(node);\r
+      BackRefNode* br = BACKREF_(node);\r
 \r
+      if (NODE_IS_CHECKER(node)) {\r
 #ifdef USE_BACKREF_WITH_LEVEL\r
-      if (IS_BACKREF_NEST_LEVEL(br)) {\r
-       r = add_opcode(reg, OP_BACKREF_WITH_LEVEL);\r
-       if (r) return r;\r
-       r = add_option(reg, (reg->options & ONIG_OPTION_IGNORECASE));\r
-       if (r) return r;\r
-       r = add_length(reg, br->nest_level);\r
-       if (r) return r;\r
-\r
-       goto add_bacref_mems;\r
-      }\r
-      else\r
+        if (NODE_IS_NEST_LEVEL(node)) {\r
+          r = add_opcode(reg, OP_BACKREF_CHECK_WITH_LEVEL);\r
+          if (r != 0) return r;\r
+          r = add_length(reg, br->nest_level);\r
+          if (r != 0) return r;\r
+        }\r
+        else\r
 #endif\r
-      if (br->back_num == 1) {\r
-       n = br->back_static[0];\r
-       if (IS_IGNORECASE(reg->options)) {\r
-         r = add_opcode(reg, OP_BACKREFN_IC);\r
-         if (r) return r;\r
-         r = add_mem_num(reg, n);\r
-       }\r
-       else {\r
-         switch (n) {\r
-         case 1:  r = add_opcode(reg, OP_BACKREF1); break;\r
-         case 2:  r = add_opcode(reg, OP_BACKREF2); break;\r
-         default:\r
-           r = add_opcode(reg, OP_BACKREFN);\r
-           if (r) return r;\r
-           r = add_mem_num(reg, n);\r
-           break;\r
-         }\r
-       }\r
+          {\r
+            r = add_opcode(reg, OP_BACKREF_CHECK);\r
+            if (r != 0) return r;\r
+          }\r
+\r
+        goto add_bacref_mems;\r
       }\r
       else {\r
-       int i;\r
-       int* p;\r
-\r
-        if (IS_IGNORECASE(reg->options)) {\r
-          r = add_opcode(reg, OP_BACKREF_MULTI_IC);\r
+#ifdef USE_BACKREF_WITH_LEVEL\r
+        if (NODE_IS_NEST_LEVEL(node)) {\r
+          r = add_opcode(reg, OP_BACKREF_WITH_LEVEL);\r
+          if (r != 0) return r;\r
+          r = add_option(reg, (reg->options & ONIG_OPTION_IGNORECASE));\r
+          if (r != 0) return r;\r
+          r = add_length(reg, br->nest_level);\r
+          if (r != 0) return r;\r
+\r
+          goto add_bacref_mems;\r
         }\r
-        else {\r
-          r = add_opcode(reg, OP_BACKREF_MULTI);\r
+        else\r
+#endif\r
+        if (br->back_num == 1) {\r
+          n = br->back_static[0];\r
+          if (IS_IGNORECASE(reg->options)) {\r
+            r = add_opcode(reg, OP_BACKREF_N_IC);\r
+            if (r != 0) return r;\r
+            r = add_mem_num(reg, n);\r
+          }\r
+          else {\r
+            switch (n) {\r
+            case 1:  r = add_opcode(reg, OP_BACKREF1); break;\r
+            case 2:  r = add_opcode(reg, OP_BACKREF2); break;\r
+            default:\r
+              r = add_opcode(reg, OP_BACKREF_N);\r
+              if (r != 0) return r;\r
+              r = add_mem_num(reg, n);\r
+              break;\r
+            }\r
+          }\r
         }\r
-       if (r) return r;\r
+        else {\r
+          int i;\r
+          int* p;\r
 \r
-#ifdef USE_BACKREF_WITH_LEVEL\r
-      add_bacref_mems:\r
-#endif\r
-       r = add_length(reg, br->back_num);\r
-       if (r) return r;\r
-       p = BACKREFS_P(br);\r
-       for (i = br->back_num - 1; i >= 0; i--) {\r
-         r = add_mem_num(reg, p[i]);\r
-         if (r) return r;\r
-       }\r
+          if (IS_IGNORECASE(reg->options)) {\r
+            r = add_opcode(reg, OP_BACKREF_MULTI_IC);\r
+          }\r
+          else {\r
+            r = add_opcode(reg, OP_BACKREF_MULTI);\r
+          }\r
+          if (r != 0) return r;\r
+\r
+        add_bacref_mems:\r
+          r = add_length(reg, br->back_num);\r
+          if (r != 0) return r;\r
+          p = BACKREFS_P(br);\r
+          for (i = br->back_num - 1; i >= 0; i--) {\r
+            r = add_mem_num(reg, p[i]);\r
+            if (r != 0) return r;\r
+          }\r
+        }\r
       }\r
     }\r
     break;\r
 \r
-#ifdef USE_SUBEXP_CALL\r
-  case NT_CALL:\r
-    r = compile_call(NCALL(node), reg);\r
+#ifdef USE_CALL\r
+  case NODE_CALL:\r
+    r = compile_call(CALL_(node), reg, env);\r
     break;\r
 #endif\r
 \r
-  case NT_QTFR:\r
-    r = compile_quantifier_node(NQTFR(node), reg);\r
+  case NODE_QUANT:\r
+    r = compile_quantifier_node(QUANT_(node), reg, env);\r
     break;\r
 \r
-  case NT_ENCLOSE:\r
-    r = compile_enclose_node(NENCLOSE(node), reg);\r
+  case NODE_ENCLOSURE:\r
+    r = compile_enclosure_node(ENCLOSURE_(node), reg, env);\r
     break;\r
 \r
-  case NT_ANCHOR:\r
-    r = compile_anchor_node(NANCHOR(node), reg);\r
+  case NODE_ANCHOR:\r
+    r = compile_anchor_node(ANCHOR_(node), reg, env);\r
+    break;\r
+\r
+  case NODE_GIMMICK:\r
+    r = compile_gimmick_node(GIMMICK_(node), reg);\r
     break;\r
 \r
   default:\r
 #ifdef ONIG_DEBUG\r
-    fprintf(stderr, "compile_tree: undefined node type %d\n", NTYPE(node));\r
+    fprintf(stderr, "compile_tree: undefined node type %d\n", NODE_TYPE(node));\r
 #endif\r
     break;\r
   }\r
@@ -1756,55 +1849,70 @@ compile_tree(Node* node, regex_t* reg)
   return r;\r
 }\r
 \r
-#ifdef USE_NAMED_GROUP\r
-\r
 static int\r
 noname_disable_map(Node** plink, GroupNumRemap* map, int* counter)\r
 {\r
   int r = 0;\r
   Node* node = *plink;\r
 \r
-  switch (NTYPE(node)) {\r
-  case NT_LIST:\r
-  case NT_ALT:\r
+  switch (NODE_TYPE(node)) {\r
+  case NODE_LIST:\r
+  case NODE_ALT:\r
     do {\r
-      r = noname_disable_map(&(NCAR(node)), map, counter);\r
-    } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));\r
+      r = noname_disable_map(&(NODE_CAR(node)), map, counter);\r
+    } while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));\r
     break;\r
 \r
-  case NT_QTFR:\r
+  case NODE_QUANT:\r
     {\r
-      Node** ptarget = &(NQTFR(node)->target);\r
+      Node** ptarget = &(NODE_BODY(node));\r
       Node*  old = *ptarget;\r
       r = noname_disable_map(ptarget, map, counter);\r
-      if (*ptarget != old && NTYPE(*ptarget) == NT_QTFR) {\r
-       onig_reduce_nested_quantifier(node, *ptarget);\r
+      if (*ptarget != old && NODE_TYPE(*ptarget) == NODE_QUANT) {\r
+        onig_reduce_nested_quantifier(node, *ptarget);\r
       }\r
     }\r
     break;\r
 \r
-  case NT_ENCLOSE:\r
+  case NODE_ENCLOSURE:\r
     {\r
-      EncloseNode* en = NENCLOSE(node);\r
-      if (en->type == ENCLOSE_MEMORY) {\r
-       if (IS_ENCLOSE_NAMED_GROUP(en)) {\r
-         (*counter)++;\r
-         map[en->regnum].new_val = *counter;\r
-         en->regnum = *counter;\r
-         r = noname_disable_map(&(en->target), map, counter);\r
-       }\r
-       else {\r
-         *plink = en->target;\r
-         en->target = NULL_NODE;\r
-         onig_node_free(node);\r
-         r = noname_disable_map(plink, map, counter);\r
-       }\r
+      EnclosureNode* en = ENCLOSURE_(node);\r
+      if (en->type == ENCLOSURE_MEMORY) {\r
+        if (NODE_IS_NAMED_GROUP(node)) {\r
+          (*counter)++;\r
+          map[en->m.regnum].new_val = *counter;\r
+          en->m.regnum = *counter;\r
+          r = noname_disable_map(&(NODE_BODY(node)), map, counter);\r
+        }\r
+        else {\r
+          *plink = NODE_BODY(node);\r
+          NODE_BODY(node) = NULL_NODE;\r
+          onig_node_free(node);\r
+          r = noname_disable_map(plink, map, counter);\r
+        }\r
+      }\r
+      else if (en->type == ENCLOSURE_IF_ELSE) {\r
+        r = noname_disable_map(&(NODE_ENCLOSURE_BODY(en)), map, counter);\r
+        if (r != 0) return r;\r
+        if (IS_NOT_NULL(en->te.Then)) {\r
+          r = noname_disable_map(&(en->te.Then), map, counter);\r
+          if (r != 0) return r;\r
+        }\r
+        if (IS_NOT_NULL(en->te.Else)) {\r
+          r = noname_disable_map(&(en->te.Else), map, counter);\r
+          if (r != 0) return r;\r
+        }\r
       }\r
       else\r
-       r = noname_disable_map(&(en->target), map, counter);\r
+        r = noname_disable_map(&(NODE_BODY(node)), map, counter);\r
     }\r
     break;\r
 \r
+  case NODE_ANCHOR:\r
+    if (IS_NOT_NULL(NODE_BODY(node)))\r
+      r = noname_disable_map(&(NODE_BODY(node)), map, counter);\r
+    break;\r
+\r
   default:\r
     break;\r
   }\r
@@ -1817,9 +1925,9 @@ renumber_node_backref(Node* node, GroupNumRemap* map)
 {\r
   int i, pos, n, old_num;\r
   int *backs;\r
-  BRefNode* bn = NBREF(node);\r
+  BackRefNode* bn = BACKREF_(node);\r
 \r
-  if (! IS_BACKREF_NAME_REF(bn))\r
+  if (! NODE_IS_BY_NAME(node))\r
     return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;\r
 \r
   old_num = bn->back_num;\r
@@ -1845,24 +1953,47 @@ renumber_by_map(Node* node, GroupNumRemap* map)
 {\r
   int r = 0;\r
 \r
-  switch (NTYPE(node)) {\r
-  case NT_LIST:\r
-  case NT_ALT:\r
+  switch (NODE_TYPE(node)) {\r
+  case NODE_LIST:\r
+  case NODE_ALT:\r
     do {\r
-      r = renumber_by_map(NCAR(node), map);\r
-    } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));\r
+      r = renumber_by_map(NODE_CAR(node), map);\r
+    } while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));\r
     break;\r
-  case NT_QTFR:\r
-    r = renumber_by_map(NQTFR(node)->target, map);\r
+\r
+  case NODE_QUANT:\r
+    r = renumber_by_map(NODE_BODY(node), map);\r
     break;\r
-  case NT_ENCLOSE:\r
-    r = renumber_by_map(NENCLOSE(node)->target, map);\r
+\r
+  case NODE_ENCLOSURE:\r
+    {\r
+      EnclosureNode* en = ENCLOSURE_(node);\r
+\r
+      r = renumber_by_map(NODE_BODY(node), map);\r
+      if (r != 0) return r;\r
+\r
+      if (en->type == ENCLOSURE_IF_ELSE) {\r
+        if (IS_NOT_NULL(en->te.Then)) {\r
+          r = renumber_by_map(en->te.Then, map);\r
+          if (r != 0) return r;\r
+        }\r
+        if (IS_NOT_NULL(en->te.Else)) {\r
+          r = renumber_by_map(en->te.Else, map);\r
+          if (r != 0) return r;\r
+        }\r
+      }\r
+    }\r
     break;\r
 \r
-  case NT_BREF:\r
+  case NODE_BACKREF:\r
     r = renumber_node_backref(node, map);\r
     break;\r
 \r
+  case NODE_ANCHOR:\r
+    if (IS_NOT_NULL(NODE_BODY(node)))\r
+      r = renumber_by_map(NODE_BODY(node), map);\r
+    break;\r
+\r
   default:\r
     break;\r
   }\r
@@ -1875,22 +2006,45 @@ numbered_ref_check(Node* node)
 {\r
   int r = 0;\r
 \r
-  switch (NTYPE(node)) {\r
-  case NT_LIST:\r
-  case NT_ALT:\r
+  switch (NODE_TYPE(node)) {\r
+  case NODE_LIST:\r
+  case NODE_ALT:\r
     do {\r
-      r = numbered_ref_check(NCAR(node));\r
-    } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));\r
+      r = numbered_ref_check(NODE_CAR(node));\r
+    } while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));\r
     break;\r
-  case NT_QTFR:\r
-    r = numbered_ref_check(NQTFR(node)->target);\r
+\r
+  case NODE_ANCHOR:\r
+    if (IS_NULL(NODE_BODY(node)))\r
+      break;\r
+    /* fall */\r
+  case NODE_QUANT:\r
+    r = numbered_ref_check(NODE_BODY(node));\r
     break;\r
-  case NT_ENCLOSE:\r
-    r = numbered_ref_check(NENCLOSE(node)->target);\r
+\r
+  case NODE_ENCLOSURE:\r
+    {\r
+      EnclosureNode* en = ENCLOSURE_(node);\r
+\r
+      r = numbered_ref_check(NODE_BODY(node));\r
+      if (r != 0) return r;\r
+\r
+      if (en->type == ENCLOSURE_IF_ELSE) {\r
+        if (IS_NOT_NULL(en->te.Then)) {\r
+          r = numbered_ref_check(en->te.Then);\r
+          if (r != 0) return r;\r
+        }\r
+        if (IS_NOT_NULL(en->te.Else)) {\r
+          r = numbered_ref_check(en->te.Else);\r
+          if (r != 0) return r;\r
+        }\r
+      }\r
+    }\r
+\r
     break;\r
 \r
-  case NT_BREF:\r
-    if (! IS_BACKREF_NAME_REF(NBREF(node)))\r
+  case NODE_BACKREF:\r
+    if (! NODE_IS_BY_NAME(node))\r
       return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;\r
     break;\r
 \r
@@ -1905,8 +2059,8 @@ static int
 disable_noname_group_capture(Node** root, regex_t* reg, ScanEnv* env)\r
 {\r
   int r, i, pos, counter;\r
-  int Result;\r
-  BitStatusType loc;\r
+  int result;\r
+  MemStatusType loc;\r
   GroupNumRemap* map;\r
 \r
   map = (GroupNumRemap* )xmalloc(sizeof(GroupNumRemap) * (env->num_mem + 1));\r
@@ -1923,476 +2077,204 @@ disable_noname_group_capture(Node** root, regex_t* reg, ScanEnv* env)
 \r
   for (i = 1, pos = 1; i <= env->num_mem; i++) {\r
     if (map[i].new_val > 0) {\r
-      SCANENV_MEM_NODES(env)[pos] = SCANENV_MEM_NODES(env)[i];\r
+      SCANENV_MEMENV(env)[pos] = SCANENV_MEMENV(env)[i];\r
       pos++;\r
     }\r
   }\r
 \r
   loc = env->capture_history;\r
-  BIT_STATUS_CLEAR(env->capture_history);\r
+  MEM_STATUS_CLEAR(env->capture_history);\r
   for (i = 1; i <= ONIG_MAX_CAPTURE_HISTORY_GROUP; i++) {\r
-    if (BIT_STATUS_AT(loc, i)) {\r
-      BIT_STATUS_ON_AT_SIMPLE(env->capture_history, map[i].new_val);\r
+    if (MEM_STATUS_AT(loc, i)) {\r
+      MEM_STATUS_ON_SIMPLE(env->capture_history, map[i].new_val);\r
     }\r
   }\r
 \r
   env->num_mem = env->num_named;\r
   reg->num_mem = env->num_named;\r
-\r
-  Result = onig_renumber_name_table(reg, map);\r
+  result = onig_renumber_name_table(reg, map);\r
   xfree(map);\r
-  return Result;\r
+  return result;\r
 }\r
-#endif /* USE_NAMED_GROUP */\r
 \r
-#ifdef USE_SUBEXP_CALL\r
+#ifdef USE_CALL\r
 static int\r
-unset_addr_list_fix(UnsetAddrList* uslist, regex_t* reg)\r
+fix_unset_addr_list(UnsetAddrList* uslist, regex_t* reg)\r
 {\r
   int i, offset;\r
-  EncloseNode* en;\r
+  EnclosureNode* en;\r
   AbsAddrType addr;\r
 \r
   for (i = 0; i < uslist->num; i++) {\r
-    en = NENCLOSE(uslist->us[i].target);\r
-    if (! IS_ENCLOSE_ADDR_FIXED(en)) return ONIGERR_PARSER_BUG;\r
-    addr = en->call_addr;\r
+    if (! NODE_IS_ADDR_FIXED(uslist->us[i].target))\r
+      return ONIGERR_PARSER_BUG;\r
+\r
+    en = ENCLOSURE_(uslist->us[i].target);\r
+    addr   = en->m.called_addr;\r
     offset = uslist->us[i].offset;\r
 \r
-    BBUF_WRITE(reg, offset, &addr, SIZE_ABSADDR);\r
+    BB_WRITE(reg, offset, &addr, SIZE_ABSADDR);\r
   }\r
   return 0;\r
 }\r
 #endif\r
 \r
-#ifdef USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT\r
+\r
+#define GET_CHAR_LEN_VARLEN           -1\r
+#define GET_CHAR_LEN_TOP_ALT_VARLEN   -2\r
+\r
+/* fixed size pattern node only */\r
 static int\r
-quantifiers_memory_node_info(Node* node)\r
+get_char_length_tree1(Node* node, regex_t* reg, int* len, int level)\r
 {\r
+  int tlen;\r
   int r = 0;\r
 \r
-  switch (NTYPE(node)) {\r
-  case NT_LIST:\r
-  case NT_ALT:\r
-    {\r
-      int v;\r
-      do {\r
-       v = quantifiers_memory_node_info(NCAR(node));\r
-       if (v > r) r = v;\r
-      } while (v >= 0 && IS_NOT_NULL(node = NCDR(node)));\r
-    }\r
+  level++;\r
+  *len = 0;\r
+  switch (NODE_TYPE(node)) {\r
+  case NODE_LIST:\r
+    do {\r
+      r = get_char_length_tree1(NODE_CAR(node), reg, &tlen, level);\r
+      if (r == 0)\r
+        *len = distance_add(*len, tlen);\r
+    } while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));\r
     break;\r
 \r
-#ifdef USE_SUBEXP_CALL\r
-  case NT_CALL:\r
-    if (IS_CALL_RECURSION(NCALL(node))) {\r
-      return NQ_TARGET_IS_EMPTY_REC; /* tiny version */\r
+  case NODE_ALT:\r
+    {\r
+      int tlen2;\r
+      int varlen = 0;\r
+\r
+      r = get_char_length_tree1(NODE_CAR(node), reg, &tlen, level);\r
+      while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node))) {\r
+        r = get_char_length_tree1(NODE_CAR(node), reg, &tlen2, level);\r
+        if (r == 0) {\r
+          if (tlen != tlen2)\r
+            varlen = 1;\r
+        }\r
+      }\r
+      if (r == 0) {\r
+        if (varlen != 0) {\r
+          if (level == 1)\r
+            r = GET_CHAR_LEN_TOP_ALT_VARLEN;\r
+          else\r
+            r = GET_CHAR_LEN_VARLEN;\r
+        }\r
+        else\r
+          *len = tlen;\r
+      }\r
     }\r
-    else\r
-      r = quantifiers_memory_node_info(NCALL(node)->target);\r
     break;\r
-#endif\r
 \r
-  case NT_QTFR:\r
+  case NODE_STRING:\r
     {\r
-      QtfrNode* qn = NQTFR(node);\r
-      if (qn->upper != 0) {\r
-       r = quantifiers_memory_node_info(qn->target);\r
+      StrNode* sn = STR_(node);\r
+      UChar *s = sn->s;\r
+\r
+      while (s < sn->end) {\r
+        s += enclen(reg->enc, s);\r
+        (*len)++;\r
       }\r
     }\r
     break;\r
 \r
-  case NT_ENCLOSE:\r
+  case NODE_QUANT:\r
     {\r
-      EncloseNode* en = NENCLOSE(node);\r
-      switch (en->type) {\r
-      case ENCLOSE_MEMORY:\r
-       return NQ_TARGET_IS_EMPTY_MEM;\r
-       break;\r
-\r
-      case ENCLOSE_OPTION:\r
-      case ENCLOSE_STOP_BACKTRACK:\r
-       r = quantifiers_memory_node_info(en->target);\r
-       break;\r
-      default:\r
-       break;\r
-      }\r
-    }\r
-    break;\r
-\r
-  case NT_BREF:\r
-  case NT_STR:\r
-  case NT_CTYPE:\r
-  case NT_CCLASS:\r
-  case NT_CANY:\r
-  case NT_ANCHOR:\r
-  default:\r
-    break;\r
-  }\r
-\r
-  return r;\r
-}\r
-#endif /* USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT */\r
-\r
-static int\r
-get_min_match_length(Node* node, OnigDistance *min, ScanEnv* env)\r
-{\r
-  OnigDistance tmin;\r
-  int r = 0;\r
-\r
-  *min = 0;\r
-  switch (NTYPE(node)) {\r
-  case NT_BREF:\r
-    {\r
-      int i;\r
-      int* backs;\r
-      Node** nodes = SCANENV_MEM_NODES(env);\r
-      BRefNode* br = NBREF(node);\r
-      if (br->state & NST_RECURSION) break;\r
-\r
-      backs = BACKREFS_P(br);\r
-      if (backs[0] > env->num_mem)  return ONIGERR_INVALID_BACKREF;\r
-      r = get_min_match_length(nodes[backs[0]], min, env);\r
-      if (r != 0) break;\r
-      for (i = 1; i < br->back_num; i++) {\r
-       if (backs[i] > env->num_mem)  return ONIGERR_INVALID_BACKREF;\r
-       r = get_min_match_length(nodes[backs[i]], &tmin, env);\r
-       if (r != 0) break;\r
-       if (*min > tmin) *min = tmin;\r
-      }\r
-    }\r
-    break;\r
-\r
-#ifdef USE_SUBEXP_CALL\r
-  case NT_CALL:\r
-    if (IS_CALL_RECURSION(NCALL(node))) {\r
-      EncloseNode* en = NENCLOSE(NCALL(node)->target);\r
-      if (IS_ENCLOSE_MIN_FIXED(en))\r
-       *min = en->min_len;\r
-    }\r
-    else\r
-      r = get_min_match_length(NCALL(node)->target, min, env);\r
-    break;\r
-#endif\r
-\r
-  case NT_LIST:\r
-    do {\r
-      r = get_min_match_length(NCAR(node), &tmin, env);\r
-      if (r == 0) *min += tmin;\r
-    } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));\r
-    break;\r
-\r
-  case NT_ALT:\r
-    {\r
-      Node *x, *y;\r
-      y = node;\r
-      do {\r
-       x = NCAR(y);\r
-       r = get_min_match_length(x, &tmin, env);\r
-       if (r != 0) break;\r
-       if (y == node) *min = tmin;\r
-       else if (*min > tmin) *min = tmin;\r
-      } while (r == 0 && IS_NOT_NULL(y = NCDR(y)));\r
-    }\r
-    break;\r
-\r
-  case NT_STR:\r
-    {\r
-      StrNode* sn = NSTR(node);\r
-      *min = (OnigDistance)(sn->end - sn->s);\r
-    }\r
-    break;\r
-\r
-  case NT_CTYPE:\r
-    *min = 1;\r
-    break;\r
-\r
-  case NT_CCLASS:\r
-  case NT_CANY:\r
-    *min = 1;\r
-    break;\r
-\r
-  case NT_QTFR:\r
-    {\r
-      QtfrNode* qn = NQTFR(node);\r
-\r
-      if (qn->lower > 0) {\r
-       r = get_min_match_length(qn->target, min, env);\r
-       if (r == 0)\r
-         *min = distance_multiply(*min, qn->lower);\r
-      }\r
-    }\r
-    break;\r
-\r
-  case NT_ENCLOSE:\r
-    {\r
-      EncloseNode* en = NENCLOSE(node);\r
-      switch (en->type) {\r
-      case ENCLOSE_MEMORY:\r
-#ifdef USE_SUBEXP_CALL\r
-       if (IS_ENCLOSE_MIN_FIXED(en))\r
-         *min = en->min_len;\r
-       else {\r
-         r = get_min_match_length(en->target, min, env);\r
-         if (r == 0) {\r
-           en->min_len = *min;\r
-           SET_ENCLOSE_STATUS(node, NST_MIN_FIXED);\r
-         }\r
-       }\r
-       break;\r
-#endif\r
-      case ENCLOSE_OPTION:\r
-      case ENCLOSE_STOP_BACKTRACK:\r
-       r = get_min_match_length(en->target, min, env);\r
-       break;\r
-      }\r
-    }\r
-    break;\r
-\r
-  case NT_ANCHOR:\r
-  default:\r
-    break;\r
-  }\r
-\r
-  return r;\r
-}\r
-\r
-static int\r
-get_max_match_length(Node* node, OnigDistance *max, ScanEnv* env)\r
-{\r
-  OnigDistance tmax;\r
-  int r = 0;\r
-\r
-  *max = 0;\r
-  switch (NTYPE(node)) {\r
-  case NT_LIST:\r
-    do {\r
-      r = get_max_match_length(NCAR(node), &tmax, env);\r
-      if (r == 0)\r
-       *max = distance_add(*max, tmax);\r
-    } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));\r
-    break;\r
-\r
-  case NT_ALT:\r
-    do {\r
-      r = get_max_match_length(NCAR(node), &tmax, env);\r
-      if (r == 0 && *max < tmax) *max = tmax;\r
-    } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));\r
-    break;\r
-\r
-  case NT_STR:\r
-    {\r
-      StrNode* sn = NSTR(node);\r
-      *max = (OnigDistance)(sn->end - sn->s);\r
-    }\r
-    break;\r
-\r
-  case NT_CTYPE:\r
-    *max = ONIGENC_MBC_MAXLEN_DIST(env->enc);\r
-    break;\r
-\r
-  case NT_CCLASS:\r
-  case NT_CANY:\r
-    *max = ONIGENC_MBC_MAXLEN_DIST(env->enc);\r
-    break;\r
-\r
-  case NT_BREF:\r
-    {\r
-      int i;\r
-      int* backs;\r
-      Node** nodes = SCANENV_MEM_NODES(env);\r
-      BRefNode* br = NBREF(node);\r
-      if (br->state & NST_RECURSION) {\r
-       *max = ONIG_INFINITE_DISTANCE;\r
-       break;\r
-      }\r
-      backs = BACKREFS_P(br);\r
-      for (i = 0; i < br->back_num; i++) {\r
-       if (backs[i] > env->num_mem)  return ONIGERR_INVALID_BACKREF;\r
-       r = get_max_match_length(nodes[backs[i]], &tmax, env);\r
-       if (r != 0) break;\r
-       if (*max < tmax) *max = tmax;\r
-      }\r
-    }\r
-    break;\r
-\r
-#ifdef USE_SUBEXP_CALL\r
-  case NT_CALL:\r
-    if (! IS_CALL_RECURSION(NCALL(node)))\r
-      r = get_max_match_length(NCALL(node)->target, max, env);\r
-    else\r
-      *max = ONIG_INFINITE_DISTANCE;\r
-    break;\r
-#endif\r
-\r
-  case NT_QTFR:\r
-    {\r
-      QtfrNode* qn = NQTFR(node);\r
-\r
-      if (qn->upper != 0) {\r
-       r = get_max_match_length(qn->target, max, env);\r
-       if (r == 0 && *max != 0) {\r
-         if (! IS_REPEAT_INFINITE(qn->upper))\r
-           *max = distance_multiply(*max, qn->upper);\r
-         else\r
-           *max = ONIG_INFINITE_DISTANCE;\r
-       }\r
-      }\r
-    }\r
-    break;\r
-\r
-  case NT_ENCLOSE:\r
-    {\r
-      EncloseNode* en = NENCLOSE(node);\r
-      switch (en->type) {\r
-      case ENCLOSE_MEMORY:\r
-#ifdef USE_SUBEXP_CALL\r
-       if (IS_ENCLOSE_MAX_FIXED(en))\r
-         *max = en->max_len;\r
-       else {\r
-         r = get_max_match_length(en->target, max, env);\r
-         if (r == 0) {\r
-           en->max_len = *max;\r
-           SET_ENCLOSE_STATUS(node, NST_MAX_FIXED);\r
-         }\r
-       }\r
-       break;\r
-#endif\r
-      case ENCLOSE_OPTION:\r
-      case ENCLOSE_STOP_BACKTRACK:\r
-       r = get_max_match_length(en->target, max, env);\r
-       break;\r
-      }\r
-    }\r
-    break;\r
-\r
-  case NT_ANCHOR:\r
-  default:\r
-    break;\r
-  }\r
-\r
-  return r;\r
-}\r
-\r
-#define GET_CHAR_LEN_VARLEN           -1\r
-#define GET_CHAR_LEN_TOP_ALT_VARLEN   -2\r
-\r
-/* fixed size pattern node only */\r
-static int\r
-get_char_length_tree1(Node* node, regex_t* reg, int* len, int level)\r
-{\r
-  int tlen;\r
-  int r = 0;\r
-\r
-  level++;\r
-  *len = 0;\r
-  switch (NTYPE(node)) {\r
-  case NT_LIST:\r
-    do {\r
-      r = get_char_length_tree1(NCAR(node), reg, &tlen, level);\r
-      if (r == 0)\r
-       *len = distance_add(*len, tlen);\r
-    } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));\r
-    break;\r
-\r
-  case NT_ALT:\r
-    {\r
-      int tlen2;\r
-      int varlen = 0;\r
+      QuantNode* qn = QUANT_(node);\r
 \r
-      r = get_char_length_tree1(NCAR(node), reg, &tlen, level);\r
-      while (r == 0 && IS_NOT_NULL(node = NCDR(node))) {\r
-       r = get_char_length_tree1(NCAR(node), reg, &tlen2, level);\r
-       if (r == 0) {\r
-         if (tlen != tlen2)\r
-           varlen = 1;\r
-       }\r
-      }\r
-      if (r == 0) {\r
-       if (varlen != 0) {\r
-         if (level == 1)\r
-           r = GET_CHAR_LEN_TOP_ALT_VARLEN;\r
-         else\r
-           r = GET_CHAR_LEN_VARLEN;\r
-       }\r
-       else\r
-         *len = tlen;\r
-      }\r
-    }\r
-    break;\r
-\r
-  case NT_STR:\r
-    {\r
-      StrNode* sn = NSTR(node);\r
-      UChar *s = sn->s;\r
-      while (s < sn->end) {\r
-       s += enclen(reg->enc, s);\r
-       (*len)++;\r
-      }\r
-    }\r
-    break;\r
-\r
-  case NT_QTFR:\r
-    {\r
-      QtfrNode* qn = NQTFR(node);\r
       if (qn->lower == qn->upper) {\r
-       r = get_char_length_tree1(qn->target, reg, &tlen, level);\r
-       if (r == 0)\r
-         *len = distance_multiply(tlen, qn->lower);\r
+        if (qn->upper == 0) {\r
+          *len = 0;\r
+        }\r
+        else {\r
+          r = get_char_length_tree1(NODE_BODY(node), reg, &tlen, level);\r
+          if (r == 0)\r
+            *len = distance_multiply(tlen, qn->lower);\r
+        }\r
       }\r
       else\r
-       r = GET_CHAR_LEN_VARLEN;\r
+        r = GET_CHAR_LEN_VARLEN;\r
     }\r
     break;\r
 \r
-#ifdef USE_SUBEXP_CALL\r
-  case NT_CALL:\r
-    if (! IS_CALL_RECURSION(NCALL(node)))\r
-      r = get_char_length_tree1(NCALL(node)->target, reg, len, level);\r
+#ifdef USE_CALL\r
+  case NODE_CALL:\r
+    if (! NODE_IS_RECURSION(node))\r
+      r = get_char_length_tree1(NODE_BODY(node), reg, len, level);\r
     else\r
       r = GET_CHAR_LEN_VARLEN;\r
     break;\r
 #endif\r
 \r
-  case NT_CTYPE:\r
-    *len = 1;\r
-    break;\r
-\r
-  case NT_CCLASS:\r
-  case NT_CANY:\r
+  case NODE_CTYPE:\r
+  case NODE_CCLASS:\r
     *len = 1;\r
     break;\r
 \r
-  case NT_ENCLOSE:\r
+  case NODE_ENCLOSURE:\r
     {\r
-      EncloseNode* en = NENCLOSE(node);\r
+      EnclosureNode* en = ENCLOSURE_(node);\r
+\r
       switch (en->type) {\r
-      case ENCLOSE_MEMORY:\r
-#ifdef USE_SUBEXP_CALL\r
-       if (IS_ENCLOSE_CLEN_FIXED(en))\r
-         *len = en->char_len;\r
-       else {\r
-         r = get_char_length_tree1(en->target, reg, len, level);\r
-         if (r == 0) {\r
-           en->char_len = *len;\r
-           SET_ENCLOSE_STATUS(node, NST_CLEN_FIXED);\r
-         }\r
-       }\r
-       break;\r
+      case ENCLOSURE_MEMORY:\r
+#ifdef USE_CALL\r
+        if (NODE_IS_CLEN_FIXED(node))\r
+          *len = en->char_len;\r
+        else {\r
+          r = get_char_length_tree1(NODE_BODY(node), reg, len, level);\r
+          if (r == 0) {\r
+            en->char_len = *len;\r
+            NODE_STATUS_ADD(node, CLEN_FIXED);\r
+          }\r
+        }\r
+        break;\r
 #endif\r
-      case ENCLOSE_OPTION:\r
-      case ENCLOSE_STOP_BACKTRACK:\r
-       r = get_char_length_tree1(en->target, reg, len, level);\r
-       break;\r
+      case ENCLOSURE_OPTION:\r
+      case ENCLOSURE_STOP_BACKTRACK:\r
+        r = get_char_length_tree1(NODE_BODY(node), reg, len, level);\r
+        break;\r
+      case ENCLOSURE_IF_ELSE:\r
+        {\r
+          int clen, elen;\r
+\r
+          r = get_char_length_tree1(NODE_BODY(node), reg, &clen, level);\r
+          if (r == 0) {\r
+            if (IS_NOT_NULL(en->te.Then)) {\r
+              r = get_char_length_tree1(en->te.Then, reg, &tlen, level);\r
+              if (r != 0) break;\r
+            }\r
+            else tlen = 0;\r
+            if (IS_NOT_NULL(en->te.Else)) {\r
+              r = get_char_length_tree1(en->te.Else, reg, &elen, level);\r
+              if (r != 0) break;\r
+            }\r
+            else elen = 0;\r
+\r
+            if (clen + tlen != elen) {\r
+              r = GET_CHAR_LEN_VARLEN;\r
+            }\r
+            else {\r
+              *len = elen;\r
+            }\r
+          }\r
+        }\r
+        break;\r
+\r
       default:\r
-       break;\r
+        break;\r
       }\r
     }\r
     break;\r
 \r
-  case NT_ANCHOR:\r
+  case NODE_ANCHOR:\r
+  case NODE_GIMMICK:\r
     break;\r
 \r
+  case NODE_BACKREF:\r
+    if (NODE_IS_CHECKER(node))\r
+      break;\r
+    /* fall */\r
   default:\r
     r = GET_CHAR_LEN_VARLEN;\r
     break;\r
@@ -2409,142 +2291,165 @@ get_char_length_tree(Node* node, regex_t* reg, int* len)
 \r
 /* x is not included y ==>  1 : 0 */\r
 static int\r
-is_not_included(Node* x, Node* y, regex_t* reg)\r
+is_exclusive(Node* x, Node* y, regex_t* reg)\r
 {\r
   int i, len;\r
   OnigCodePoint code;\r
   UChar *p;\r
-  int ytype;\r
+  NodeType ytype;\r
 \r
  retry:\r
-  ytype = NTYPE(y);\r
-  switch (NTYPE(x)) {\r
-  case NT_CTYPE:\r
+  ytype = NODE_TYPE(y);\r
+  switch (NODE_TYPE(x)) {\r
+  case NODE_CTYPE:\r
     {\r
+      if (CTYPE_(x)->ctype == CTYPE_ANYCHAR ||\r
+          CTYPE_(y)->ctype == CTYPE_ANYCHAR)\r
+        break;\r
+\r
       switch (ytype) {\r
-      case NT_CTYPE:\r
-       if (NCTYPE(y)->ctype == NCTYPE(x)->ctype &&\r
-           NCTYPE(y)->not   != NCTYPE(x)->not)\r
-         return 1;\r
-       else\r
-         return 0;\r
-       break;\r
-\r
-      case NT_CCLASS:\r
+      case NODE_CTYPE:\r
+        if (CTYPE_(y)->ctype == CTYPE_(x)->ctype &&\r
+            CTYPE_(y)->not   != CTYPE_(x)->not &&\r
+            CTYPE_(y)->ascii_mode == CTYPE_(x)->ascii_mode)\r
+          return 1;\r
+        else\r
+          return 0;\r
+        break;\r
+\r
+      case NODE_CCLASS:\r
       swap:\r
-       {\r
-         Node* tmp;\r
-         tmp = x; x = y; y = tmp;\r
-         goto retry;\r
-       }\r
-       break;\r
+        {\r
+          Node* tmp;\r
+          tmp = x; x = y; y = tmp;\r
+          goto retry;\r
+        }\r
+        break;\r
 \r
-      case NT_STR:\r
-       goto swap;\r
-       break;\r
+      case NODE_STRING:\r
+        goto swap;\r
+        break;\r
 \r
       default:\r
-       break;\r
+        break;\r
       }\r
     }\r
     break;\r
 \r
-  case NT_CCLASS:\r
+  case NODE_CCLASS:\r
     {\r
-      CClassNode* xc = NCCLASS(x);\r
+      int range;\r
+      CClassNode* xc = CCLASS_(x);\r
+\r
       switch (ytype) {\r
-      case NT_CTYPE:\r
-       switch (NCTYPE(y)->ctype) {\r
-       case ONIGENC_CTYPE_WORD:\r
-         if (NCTYPE(y)->not == 0) {\r
-           if (IS_NULL(xc->mbuf) && !IS_NCCLASS_NOT(xc)) {\r
-             for (i = 0; i < SINGLE_BYTE_SIZE; i++) {\r
-               if (BITSET_AT(xc->bs, i)) {\r
-                 if (IS_CODE_SB_WORD(reg->enc, i)) return 0;\r
-               }\r
-             }\r
-             return 1;\r
-           }\r
-           return 0;\r
-         }\r
-         else {\r
-           for (i = 0; i < SINGLE_BYTE_SIZE; i++) {\r
-             if (! IS_CODE_SB_WORD(reg->enc, i)) {\r
-               if (!IS_NCCLASS_NOT(xc)) {\r
-                 if (BITSET_AT(xc->bs, i))\r
-                   return 0;\r
-               }\r
-               else {\r
-                 if (! BITSET_AT(xc->bs, i))\r
-                   return 0;\r
-               }\r
-             }\r
-           }\r
-           return 1;\r
-         }\r
-         break;\r
-\r
-       default:\r
-         break;\r
-       }\r
-       break;\r
-\r
-      case NT_CCLASS:\r
-       {\r
-         int v;\r
-         CClassNode* yc = NCCLASS(y);\r
-\r
-         for (i = 0; i < SINGLE_BYTE_SIZE; i++) {\r
-           v = BITSET_AT(xc->bs, i);\r
-           if ((v != 0 && !IS_NCCLASS_NOT(xc)) ||\r
-                (v == 0 && IS_NCCLASS_NOT(xc))) {\r
-             v = BITSET_AT(yc->bs, i);\r
-             if ((v != 0 && !IS_NCCLASS_NOT(yc)) ||\r
+      case NODE_CTYPE:\r
+        switch (CTYPE_(y)->ctype) {\r
+        case CTYPE_ANYCHAR:\r
+          return 0;\r
+          break;\r
+\r
+        case ONIGENC_CTYPE_WORD:\r
+          if (CTYPE_(y)->not == 0) {\r
+            if (IS_NULL(xc->mbuf) && !IS_NCCLASS_NOT(xc)) {\r
+              range = CTYPE_(y)->ascii_mode != 0 ? 128 : SINGLE_BYTE_SIZE;\r
+              for (i = 0; i < range; i++) {\r
+                if (BITSET_AT(xc->bs, i)) {\r
+                  if (ONIGENC_IS_CODE_WORD(reg->enc, i)) return 0;\r
+                }\r
+              }\r
+              return 1;\r
+            }\r
+            return 0;\r
+          }\r
+          else {\r
+            if (IS_NOT_NULL(xc->mbuf)) return 0;\r
+            if (IS_NCCLASS_NOT(xc)) return 0;\r
+\r
+            range = CTYPE_(y)->ascii_mode != 0 ? 128 : SINGLE_BYTE_SIZE;\r
+            for (i = 0; i < range; i++) {\r
+              if (! ONIGENC_IS_CODE_WORD(reg->enc, i)) {\r
+                if (BITSET_AT(xc->bs, i))\r
+                  return 0;\r
+              }\r
+            }\r
+            for (i = range; i < SINGLE_BYTE_SIZE; i++) {\r
+              if (BITSET_AT(xc->bs, i)) return 0;\r
+            }\r
+            return 1;\r
+          }\r
+          break;\r
+\r
+        default:\r
+          break;\r
+        }\r
+        break;\r
+\r
+      case NODE_CCLASS:\r
+        {\r
+          int v;\r
+          CClassNode* yc = CCLASS_(y);\r
+\r
+          for (i = 0; i < SINGLE_BYTE_SIZE; i++) {\r
+            v = BITSET_AT(xc->bs, i);\r
+            if ((v != 0 && !IS_NCCLASS_NOT(xc)) || (v == 0 && IS_NCCLASS_NOT(xc))) {\r
+              v = BITSET_AT(yc->bs, i);\r
+              if ((v != 0 && !IS_NCCLASS_NOT(yc)) ||\r
                   (v == 0 && IS_NCCLASS_NOT(yc)))\r
-               return 0;\r
-           }\r
-         }\r
-         if ((IS_NULL(xc->mbuf) && !IS_NCCLASS_NOT(xc)) ||\r
-             (IS_NULL(yc->mbuf) && !IS_NCCLASS_NOT(yc)))\r
-           return 1;\r
-         return 0;\r
-       }\r
-       break;\r
-\r
-      case NT_STR:\r
-       goto swap;\r
-       break;\r
+                return 0;\r
+            }\r
+          }\r
+          if ((IS_NULL(xc->mbuf) && !IS_NCCLASS_NOT(xc)) ||\r
+              (IS_NULL(yc->mbuf) && !IS_NCCLASS_NOT(yc)))\r
+            return 1;\r
+          return 0;\r
+        }\r
+        break;\r
+\r
+      case NODE_STRING:\r
+        goto swap;\r
+        break;\r
 \r
       default:\r
-       break;\r
+        break;\r
       }\r
     }\r
     break;\r
 \r
-  case NT_STR:\r
+  case NODE_STRING:\r
     {\r
-      StrNode* xs = NSTR(x);\r
-      if (NSTRING_LEN(x) == 0)\r
-       break;\r
+      StrNode* xs = STR_(x);\r
+\r
+      if (NODE_STRING_LEN(x) == 0)\r
+        break;\r
 \r
-      //c = *(xs->s);\r
       switch (ytype) {\r
-      case NT_CTYPE:\r
-        switch (NCTYPE(y)->ctype) {\r
+      case NODE_CTYPE:\r
+        switch (CTYPE_(y)->ctype) {\r
+        case CTYPE_ANYCHAR:\r
+          break;\r
+\r
         case ONIGENC_CTYPE_WORD:\r
-          if (ONIGENC_IS_MBC_WORD(reg->enc, xs->s, xs->end))\r
-            return NCTYPE(y)->not;\r
-          else\r
-            return !(NCTYPE(y)->not);\r
+          if (CTYPE_(y)->ascii_mode == 0) {\r
+            if (ONIGENC_IS_MBC_WORD(reg->enc, xs->s, xs->end))\r
+              return CTYPE_(y)->not;\r
+            else\r
+              return !(CTYPE_(y)->not);\r
+          }\r
+          else {\r
+            if (ONIGENC_IS_MBC_WORD_ASCII(reg->enc, xs->s, xs->end))\r
+              return CTYPE_(y)->not;\r
+            else\r
+              return !(CTYPE_(y)->not);\r
+          }\r
           break;\r
         default:\r
           break;\r
         }\r
         break;\r
 \r
-      case NT_CCLASS:\r
+      case NODE_CCLASS:\r
         {\r
-          CClassNode* cc = NCCLASS(y);\r
+          CClassNode* cc = CCLASS_(y);\r
 \r
           code = ONIGENC_MBC_TO_CODE(reg->enc, xs->s,\r
                                      xs->s + ONIGENC_MBC_MAXLEN(reg->enc));\r
@@ -2552,13 +2457,14 @@ is_not_included(Node* x, Node* y, regex_t* reg)
         }\r
         break;\r
 \r
-      case NT_STR:\r
+      case NODE_STRING:\r
         {\r
           UChar *q;\r
-          StrNode* ys = NSTR(y);\r
-          len = NSTRING_LEN(x);\r
-          if (len > NSTRING_LEN(y)) len = NSTRING_LEN(y);\r
-          if (NSTRING_IS_AMBIG(x) || NSTRING_IS_AMBIG(y)) {\r
+          StrNode* ys = STR_(y);\r
+\r
+          len = NODE_STRING_LEN(x);\r
+          if (len > NODE_STRING_LEN(y)) len = NODE_STRING_LEN(y);\r
+          if (NODE_STRING_IS_AMBIG(x) || NODE_STRING_IS_AMBIG(y)) {\r
             /* tiny version */\r
             return 0;\r
           }\r
@@ -2569,7 +2475,7 @@ is_not_included(Node* x, Node* y, regex_t* reg)
           }\r
         }\r
         break;\r
-       \r
+\r
       default:\r
         break;\r
       }\r
@@ -2588,81 +2494,85 @@ get_head_value_node(Node* node, int exact, regex_t* reg)
 {\r
   Node* n = NULL_NODE;\r
 \r
-  switch (NTYPE(node)) {\r
-  case NT_BREF:\r
-  case NT_ALT:\r
-  case NT_CANY:\r
-#ifdef USE_SUBEXP_CALL\r
-  case NT_CALL:\r
+  switch (NODE_TYPE(node)) {\r
+  case NODE_BACKREF:\r
+  case NODE_ALT:\r
+#ifdef USE_CALL\r
+  case NODE_CALL:\r
 #endif\r
     break;\r
 \r
-  case NT_CTYPE:\r
-  case NT_CCLASS:\r
+  case NODE_CTYPE:\r
+    if (CTYPE_(node)->ctype == CTYPE_ANYCHAR)\r
+      break;\r
+    /* fall */\r
+  case NODE_CCLASS:\r
     if (exact == 0) {\r
       n = node;\r
     }\r
     break;\r
 \r
-  case NT_LIST:\r
-    n = get_head_value_node(NCAR(node), exact, reg);\r
+  case NODE_LIST:\r
+    n = get_head_value_node(NODE_CAR(node), exact, reg);\r
     break;\r
 \r
-  case NT_STR:\r
+  case NODE_STRING:\r
     {\r
-      StrNode* sn = NSTR(node);\r
+      StrNode* sn = STR_(node);\r
 \r
       if (sn->end <= sn->s)\r
-       break;\r
+        break;\r
 \r
       if (exact != 0 &&\r
-         !NSTRING_IS_RAW(node) && IS_IGNORECASE(reg->options)) {\r
+          !NODE_STRING_IS_RAW(node) && IS_IGNORECASE(reg->options)) {\r
       }\r
       else {\r
-       n = node;\r
+        n = node;\r
       }\r
     }\r
     break;\r
 \r
-  case NT_QTFR:\r
+  case NODE_QUANT:\r
     {\r
-      QtfrNode* qn = NQTFR(node);\r
+      QuantNode* qn = QUANT_(node);\r
       if (qn->lower > 0) {\r
-       if (IS_NOT_NULL(qn->head_exact))\r
-         n = qn->head_exact;\r
-       else\r
-         n = get_head_value_node(qn->target, exact, reg);\r
+        if (IS_NOT_NULL(qn->head_exact))\r
+          n = qn->head_exact;\r
+        else\r
+          n = get_head_value_node(NODE_BODY(node), exact, reg);\r
       }\r
     }\r
     break;\r
 \r
-  case NT_ENCLOSE:\r
+  case NODE_ENCLOSURE:\r
     {\r
-      EncloseNode* en = NENCLOSE(node);\r
+      EnclosureNode* en = ENCLOSURE_(node);\r
       switch (en->type) {\r
-      case ENCLOSE_OPTION:\r
-       {\r
-         OnigOptionType options = reg->options;\r
-\r
-         reg->options = NENCLOSE(node)->option;\r
-         n = get_head_value_node(NENCLOSE(node)->target, exact, reg);\r
-         reg->options = options;\r
-       }\r
-       break;\r
-\r
-      case ENCLOSE_MEMORY:\r
-      case ENCLOSE_STOP_BACKTRACK:\r
-       n = get_head_value_node(en->target, exact, reg);\r
-       break;\r
+      case ENCLOSURE_OPTION:\r
+        {\r
+          OnigOptionType options = reg->options;\r
+\r
+          reg->options = ENCLOSURE_(node)->o.options;\r
+          n = get_head_value_node(NODE_BODY(node), exact, reg);\r
+          reg->options = options;\r
+        }\r
+        break;\r
+\r
+      case ENCLOSURE_MEMORY:\r
+      case ENCLOSURE_STOP_BACKTRACK:\r
+      case ENCLOSURE_IF_ELSE:\r
+        n = get_head_value_node(NODE_BODY(node), exact, reg);\r
+        break;\r
       }\r
     }\r
     break;\r
 \r
-  case NT_ANCHOR:\r
-    if (NANCHOR(node)->type == ANCHOR_PREC_READ)\r
-      n = get_head_value_node(NANCHOR(node)->target, exact, reg);\r
+  case NODE_ANCHOR:\r
+    if (ANCHOR_(node)->type == ANCHOR_PREC_READ)\r
+      n = get_head_value_node(NODE_BODY(node), exact, reg);\r
     break;\r
 \r
+  case NODE_GIMMICK:\r
   default:\r
     break;\r
   }\r
@@ -2671,247 +2581,396 @@ get_head_value_node(Node* node, int exact, regex_t* reg)
 }\r
 \r
 static int\r
-check_type_tree(Node* node, int type_mask, int enclose_mask, int anchor_mask)\r
+check_type_tree(Node* node, int type_mask, int enclosure_mask, int anchor_mask)\r
 {\r
-  int type, r = 0;\r
+  NodeType type;\r
+  int r = 0;\r
 \r
-  type = NTYPE(node);\r
-  if ((NTYPE2BIT(type) & type_mask) == 0)\r
+  type = NODE_TYPE(node);\r
+  if ((NODE_TYPE2BIT(type) & type_mask) == 0)\r
     return 1;\r
 \r
   switch (type) {\r
-  case NT_LIST:\r
-  case NT_ALT:\r
+  case NODE_LIST:\r
+  case NODE_ALT:\r
     do {\r
-      r = check_type_tree(NCAR(node), type_mask, enclose_mask,\r
-                         anchor_mask);\r
-    } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));\r
+      r = check_type_tree(NODE_CAR(node), type_mask, enclosure_mask,\r
+                          anchor_mask);\r
+    } while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));\r
     break;\r
 \r
-  case NT_QTFR:\r
-    r = check_type_tree(NQTFR(node)->target, type_mask, enclose_mask,\r
-                       anchor_mask);\r
+  case NODE_QUANT:\r
+    r = check_type_tree(NODE_BODY(node), type_mask, enclosure_mask, anchor_mask);\r
     break;\r
 \r
-  case NT_ENCLOSE:\r
+  case NODE_ENCLOSURE:\r
     {\r
-      EncloseNode* en = NENCLOSE(node);\r
-      if ((en->type & enclose_mask) == 0)\r
-       return 1;\r
-\r
-      r = check_type_tree(en->target, type_mask, enclose_mask, anchor_mask);\r
+      EnclosureNode* en = ENCLOSURE_(node);\r
+      if (((1<<en->type) & enclosure_mask) == 0)\r
+        return 1;\r
+\r
+      r = check_type_tree(NODE_BODY(node), type_mask, enclosure_mask, anchor_mask);\r
+      if (r == 0 && en->type == ENCLOSURE_IF_ELSE) {\r
+        if (IS_NOT_NULL(en->te.Then)) {\r
+          r = check_type_tree(en->te.Then, type_mask, enclosure_mask, anchor_mask);\r
+          if (r != 0) break;\r
+        }\r
+        if (IS_NOT_NULL(en->te.Else)) {\r
+          r = check_type_tree(en->te.Else, type_mask, enclosure_mask, anchor_mask);\r
+        }\r
+      }\r
     }\r
     break;\r
 \r
-  case NT_ANCHOR:\r
-    type = NANCHOR(node)->type;\r
+  case NODE_ANCHOR:\r
+    type = ANCHOR_(node)->type;\r
     if ((type & anchor_mask) == 0)\r
       return 1;\r
 \r
-    if (NANCHOR(node)->target)\r
-      r = check_type_tree(NANCHOR(node)->target,\r
-                         type_mask, enclose_mask, anchor_mask);\r
+    if (IS_NOT_NULL(NODE_BODY(node)))\r
+      r = check_type_tree(NODE_BODY(node), type_mask, enclosure_mask, anchor_mask);\r
     break;\r
 \r
+  case NODE_GIMMICK:\r
   default:\r
     break;\r
   }\r
   return r;\r
 }\r
 \r
-#ifdef USE_SUBEXP_CALL\r
-\r
-#define RECURSION_EXIST       1\r
-#define RECURSION_INFINITE    2\r
-\r
-static int\r
-subexp_inf_recursive_check(Node* node, ScanEnv* env, int head)\r
+static OnigLen\r
+tree_min_len(Node* node, ScanEnv* env)\r
 {\r
-  int type;\r
-  int r = 0;\r
+  OnigLen len;\r
+  OnigLen tmin;\r
 \r
-  type = NTYPE(node);\r
-  switch (type) {\r
-  case NT_LIST:\r
-    {\r
-      Node *x;\r
-      OnigDistance min;\r
-      int ret;\r
+  len = 0;\r
+  switch (NODE_TYPE(node)) {\r
+  case NODE_BACKREF:\r
+    if (! NODE_IS_CHECKER(node)) {\r
+      int i;\r
+      int* backs;\r
+      MemEnv* mem_env = SCANENV_MEMENV(env);\r
+      BackRefNode* br = BACKREF_(node);\r
+      if (NODE_IS_RECURSION(node)) break;\r
 \r
-      x = node;\r
-      do {\r
-       ret = subexp_inf_recursive_check(NCAR(x), env, head);\r
-       if (ret < 0 || ret == RECURSION_INFINITE) return ret;\r
-       r |= ret;\r
-       if (head) {\r
-         ret = get_min_match_length(NCAR(x), &min, env);\r
-         if (ret != 0) return ret;\r
-         if (min != 0) head = 0;\r
-       }\r
-      } while (IS_NOT_NULL(x = NCDR(x)));\r
+      backs = BACKREFS_P(br);\r
+      len = tree_min_len(mem_env[backs[0]].node, env);\r
+      for (i = 1; i < br->back_num; i++) {\r
+        tmin = tree_min_len(mem_env[backs[i]].node, env);\r
+        if (len > tmin) len = tmin;\r
+      }\r
     }\r
     break;\r
 \r
-  case NT_ALT:\r
+#ifdef USE_CALL\r
+  case NODE_CALL:\r
     {\r
-      int ret;\r
-      r = RECURSION_EXIST;\r
+      Node* t = NODE_BODY(node);\r
+      if (NODE_IS_RECURSION(node)) {\r
+        if (NODE_IS_MIN_FIXED(t))\r
+          len = ENCLOSURE_(t)->min_len;\r
+      }\r
+      else\r
+        len = tree_min_len(t, env);\r
+    }\r
+    break;\r
+#endif\r
+\r
+  case NODE_LIST:\r
+    do {\r
+      tmin = tree_min_len(NODE_CAR(node), env);\r
+      len = distance_add(len, tmin);\r
+    } while (IS_NOT_NULL(node = NODE_CDR(node)));\r
+    break;\r
+\r
+  case NODE_ALT:\r
+    {\r
+      Node *x, *y;\r
+      y = node;\r
       do {\r
-       ret = subexp_inf_recursive_check(NCAR(node), env, head);\r
-       if (ret < 0 || ret == RECURSION_INFINITE) return ret;\r
-       r &= ret;\r
-      } while (IS_NOT_NULL(node = NCDR(node)));\r
+        x = NODE_CAR(y);\r
+        tmin = tree_min_len(x, env);\r
+        if (y == node) len = tmin;\r
+        else if (len > tmin) len = tmin;\r
+      } while (IS_NOT_NULL(y = NODE_CDR(y)));\r
     }\r
     break;\r
 \r
-  case NT_QTFR:\r
-    r = subexp_inf_recursive_check(NQTFR(node)->target, env, head);\r
-    if (r == RECURSION_EXIST) {\r
-      if (NQTFR(node)->lower == 0) r = 0;\r
+  case NODE_STRING:\r
+    {\r
+      StrNode* sn = STR_(node);\r
+      len = (int )(sn->end - sn->s);\r
     }\r
     break;\r
 \r
-  case NT_ANCHOR:\r
+  case NODE_CTYPE:\r
+  case NODE_CCLASS:\r
+    len = ONIGENC_MBC_MINLEN(env->enc);\r
+    break;\r
+\r
+  case NODE_QUANT:\r
     {\r
-      AnchorNode* an = NANCHOR(node);\r
-      switch (an->type) {\r
-      case ANCHOR_PREC_READ:\r
-      case ANCHOR_PREC_READ_NOT:\r
-      case ANCHOR_LOOK_BEHIND:\r
-      case ANCHOR_LOOK_BEHIND_NOT:\r
-       r = subexp_inf_recursive_check(an->target, env, head);\r
-       break;\r
+      QuantNode* qn = QUANT_(node);\r
+\r
+      if (qn->lower > 0) {\r
+        len = tree_min_len(NODE_BODY(node), env);\r
+        len = distance_multiply(len, qn->lower);\r
       }\r
     }\r
     break;\r
 \r
-  case NT_CALL:\r
-    r = subexp_inf_recursive_check(NCALL(node)->target, env, head);\r
-    break;\r
+  case NODE_ENCLOSURE:\r
+    {\r
+      EnclosureNode* en = ENCLOSURE_(node);\r
+      switch (en->type) {\r
+      case ENCLOSURE_MEMORY:\r
+        if (NODE_IS_MIN_FIXED(node))\r
+          len = en->min_len;\r
+        else {\r
+          if (NODE_IS_MARK1(node))\r
+            len = 0;  /* recursive */\r
+          else {\r
+            NODE_STATUS_ADD(node, MARK1);\r
+            len = tree_min_len(NODE_BODY(node), env);\r
+            NODE_STATUS_REMOVE(node, MARK1);\r
 \r
-  case NT_ENCLOSE:\r
-    if (IS_ENCLOSE_MARK2(NENCLOSE(node)))\r
-      return 0;\r
-    else if (IS_ENCLOSE_MARK1(NENCLOSE(node)))\r
-      return (head == 0 ? RECURSION_EXIST : RECURSION_INFINITE);\r
-    else {\r
-      SET_ENCLOSE_STATUS(node, NST_MARK2);\r
-      r = subexp_inf_recursive_check(NENCLOSE(node)->target, env, head);\r
-      CLEAR_ENCLOSE_STATUS(node, NST_MARK2);\r
+            en->min_len = len;\r
+            NODE_STATUS_ADD(node, MIN_FIXED);\r
+          }\r
+        }\r
+        break;\r
+\r
+      case ENCLOSURE_OPTION:\r
+      case ENCLOSURE_STOP_BACKTRACK:\r
+        len = tree_min_len(NODE_BODY(node), env);\r
+        break;\r
+      case ENCLOSURE_IF_ELSE:\r
+        {\r
+          OnigLen elen;\r
+\r
+          len = tree_min_len(NODE_BODY(node), env);\r
+          if (IS_NOT_NULL(en->te.Then))\r
+            len += tree_min_len(en->te.Then, env);\r
+          if (IS_NOT_NULL(en->te.Else))\r
+            elen = tree_min_len(en->te.Else, env);\r
+          else elen = 0;\r
+\r
+          if (elen < len) len = elen;\r
+        }\r
+        break;\r
+      }\r
     }\r
     break;\r
 \r
+  case NODE_GIMMICK:\r
+    {\r
+      GimmickNode* g = GIMMICK_(node);\r
+      if (g->type == GIMMICK_FAIL) {\r
+        len = INFINITE_LEN;\r
+        break;\r
+      }\r
+    }\r
+    /* fall */\r
+  case NODE_ANCHOR:\r
   default:\r
     break;\r
   }\r
 \r
-  return r;\r
+  return len;\r
 }\r
 \r
-static int\r
-subexp_inf_recursive_check_trav(Node* node, ScanEnv* env)\r
+static OnigLen\r
+tree_max_len(Node* node, ScanEnv* env)\r
 {\r
-  int type;\r
-  int r = 0;\r
+  OnigLen len;\r
+  OnigLen tmax;\r
 \r
-  type = NTYPE(node);\r
-  switch (type) {\r
-  case NT_LIST:\r
-  case NT_ALT:\r
+  len = 0;\r
+  switch (NODE_TYPE(node)) {\r
+  case NODE_LIST:\r
     do {\r
-      r = subexp_inf_recursive_check_trav(NCAR(node), env);\r
-    } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));\r
+      tmax = tree_max_len(NODE_CAR(node), env);\r
+      len = distance_add(len, tmax);\r
+    } while (IS_NOT_NULL(node = NODE_CDR(node)));\r
     break;\r
 \r
-  case NT_QTFR:\r
-    r = subexp_inf_recursive_check_trav(NQTFR(node)->target, env);\r
+  case NODE_ALT:\r
+    do {\r
+      tmax = tree_max_len(NODE_CAR(node), env);\r
+      if (len < tmax) len = tmax;\r
+    } while (IS_NOT_NULL(node = NODE_CDR(node)));\r
     break;\r
 \r
-  case NT_ANCHOR:\r
+  case NODE_STRING:\r
     {\r
-      AnchorNode* an = NANCHOR(node);\r
-      switch (an->type) {\r
-      case ANCHOR_PREC_READ:\r
-      case ANCHOR_PREC_READ_NOT:\r
-      case ANCHOR_LOOK_BEHIND:\r
-      case ANCHOR_LOOK_BEHIND_NOT:\r
-       r = subexp_inf_recursive_check_trav(an->target, env);\r
-       break;\r
+      StrNode* sn = STR_(node);\r
+      len = (OnigLen )(sn->end - sn->s);\r
+    }\r
+    break;\r
+\r
+  case NODE_CTYPE:\r
+  case NODE_CCLASS:\r
+    len = ONIGENC_MBC_MAXLEN_DIST(env->enc);\r
+    break;\r
+\r
+  case NODE_BACKREF:\r
+    if (! NODE_IS_CHECKER(node)) {\r
+      int i;\r
+      int* backs;\r
+      MemEnv* mem_env = SCANENV_MEMENV(env);\r
+      BackRefNode* br = BACKREF_(node);\r
+      if (NODE_IS_RECURSION(node)) {\r
+        len = INFINITE_LEN;\r
+        break;\r
+      }\r
+      backs = BACKREFS_P(br);\r
+      for (i = 0; i < br->back_num; i++) {\r
+        tmax = tree_max_len(mem_env[backs[i]].node, env);\r
+        if (len < tmax) len = tmax;\r
       }\r
     }\r
     break;\r
 \r
-  case NT_ENCLOSE:\r
+#ifdef USE_CALL\r
+  case NODE_CALL:\r
+    if (! NODE_IS_RECURSION(node))\r
+      len = tree_max_len(NODE_BODY(node), env);\r
+    else\r
+      len = INFINITE_LEN;\r
+    break;\r
+#endif\r
+\r
+  case NODE_QUANT:\r
     {\r
-      EncloseNode* en = NENCLOSE(node);\r
+      QuantNode* qn = QUANT_(node);\r
 \r
-      if (IS_ENCLOSE_RECURSION(en)) {\r
-       SET_ENCLOSE_STATUS(node, NST_MARK1);\r
-       r = subexp_inf_recursive_check(en->target, env, 1);\r
-       if (r > 0) return ONIGERR_NEVER_ENDING_RECURSION;\r
-       CLEAR_ENCLOSE_STATUS(node, NST_MARK1);\r
+      if (qn->upper != 0) {\r
+        len = tree_max_len(NODE_BODY(node), env);\r
+        if (len != 0) {\r
+          if (! IS_REPEAT_INFINITE(qn->upper))\r
+            len = distance_multiply(len, qn->upper);\r
+          else\r
+            len = INFINITE_LEN;\r
+        }\r
       }\r
-      r = subexp_inf_recursive_check_trav(en->target, env);\r
     }\r
+    break;\r
+\r
+  case NODE_ENCLOSURE:\r
+    {\r
+      EnclosureNode* en = ENCLOSURE_(node);\r
+      switch (en->type) {\r
+      case ENCLOSURE_MEMORY:\r
+        if (NODE_IS_MAX_FIXED(node))\r
+          len = en->max_len;\r
+        else {\r
+          if (NODE_IS_MARK1(node))\r
+            len = INFINITE_LEN;\r
+          else {\r
+            NODE_STATUS_ADD(node, MARK1);\r
+            len = tree_max_len(NODE_BODY(node), env);\r
+            NODE_STATUS_REMOVE(node, MARK1);\r
+\r
+            en->max_len = len;\r
+            NODE_STATUS_ADD(node, MAX_FIXED);\r
+          }\r
+        }\r
+        break;\r
+\r
+      case ENCLOSURE_OPTION:\r
+      case ENCLOSURE_STOP_BACKTRACK:\r
+        len = tree_max_len(NODE_BODY(node), env);\r
+        break;\r
+      case ENCLOSURE_IF_ELSE:\r
+        {\r
+          OnigLen tlen, elen;\r
+\r
+          len = tree_max_len(NODE_BODY(node), env);\r
+          if (IS_NOT_NULL(en->te.Then)) {\r
+            tlen = tree_max_len(en->te.Then, env);\r
+            len = distance_add(len, tlen);\r
+          }\r
+          if (IS_NOT_NULL(en->te.Else))\r
+            elen = tree_max_len(en->te.Else, env);\r
+          else elen = 0;\r
 \r
+          if (elen > len) len = elen;\r
+        }\r
+        break;\r
+      }\r
+    }\r
     break;\r
 \r
+  case NODE_ANCHOR:\r
+  case NODE_GIMMICK:\r
   default:\r
     break;\r
   }\r
 \r
-  return r;\r
+  return len;\r
 }\r
 \r
 static int\r
-subexp_recursive_check(Node* node)\r
+check_backrefs(Node* node, ScanEnv* env)\r
 {\r
-  int r = 0;\r
+  int r;\r
 \r
-  switch (NTYPE(node)) {\r
-  case NT_LIST:\r
-  case NT_ALT:\r
+  switch (NODE_TYPE(node)) {\r
+  case NODE_LIST:\r
+  case NODE_ALT:\r
     do {\r
-      r |= subexp_recursive_check(NCAR(node));\r
-    } while (IS_NOT_NULL(node = NCDR(node)));\r
+      r = check_backrefs(NODE_CAR(node), env);\r
+    } while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));\r
     break;\r
 \r
-  case NT_QTFR:\r
-    r = subexp_recursive_check(NQTFR(node)->target);\r
+  case NODE_ANCHOR:\r
+    if (! ANCHOR_HAS_BODY(ANCHOR_(node))) {\r
+      r = 0;\r
+      break;\r
+    }\r
+    /* fall */\r
+  case NODE_QUANT:\r
+    r = check_backrefs(NODE_BODY(node), env);\r
     break;\r
 \r
-  case NT_ANCHOR:\r
+  case NODE_ENCLOSURE:\r
+    r = check_backrefs(NODE_BODY(node), env);\r
     {\r
-      AnchorNode* an = NANCHOR(node);\r
-      switch (an->type) {\r
-      case ANCHOR_PREC_READ:\r
-      case ANCHOR_PREC_READ_NOT:\r
-      case ANCHOR_LOOK_BEHIND:\r
-      case ANCHOR_LOOK_BEHIND_NOT:\r
-       r = subexp_recursive_check(an->target);\r
-       break;\r
+      EnclosureNode* en = ENCLOSURE_(node);\r
+\r
+      if (en->type == ENCLOSURE_IF_ELSE) {\r
+        if (r != 0) return r;\r
+        if (IS_NOT_NULL(en->te.Then)) {\r
+          r = check_backrefs(en->te.Then, env);\r
+          if (r != 0) return r;\r
+        }\r
+        if (IS_NOT_NULL(en->te.Else)) {\r
+          r = check_backrefs(en->te.Else, env);\r
+        }\r
       }\r
     }\r
     break;\r
 \r
-  case NT_CALL:\r
-    r = subexp_recursive_check(NCALL(node)->target);\r
-    if (r != 0) SET_CALL_RECURSION(node);\r
-    break;\r
+  case NODE_BACKREF:\r
+    {\r
+      int i;\r
+      BackRefNode* br = BACKREF_(node);\r
+      int* backs = BACKREFS_P(br);\r
+      MemEnv* mem_env = SCANENV_MEMENV(env);\r
 \r
-  case NT_ENCLOSE:\r
-    if (IS_ENCLOSE_MARK2(NENCLOSE(node)))\r
-      return 0;\r
-    else if (IS_ENCLOSE_MARK1(NENCLOSE(node)))\r
-      return 1; /* recursion */\r
-    else {\r
-      SET_ENCLOSE_STATUS(node, NST_MARK2);\r
-      r = subexp_recursive_check(NENCLOSE(node)->target);\r
-      CLEAR_ENCLOSE_STATUS(node, NST_MARK2);\r
+      for (i = 0; i < br->back_num; i++) {\r
+        if (backs[i] > env->num_mem)\r
+          return ONIGERR_INVALID_BACKREF;\r
+\r
+        NODE_STATUS_ADD(mem_env[backs[i]].node, BACKREF);\r
+      }\r
+      r = 0;\r
     }\r
     break;\r
 \r
   default:\r
+    r = 0;\r
     break;\r
   }\r
 \r
@@ -2919,65 +2978,114 @@ subexp_recursive_check(Node* node)
 }\r
 \r
 \r
+#ifdef USE_CALL\r
+\r
+#define RECURSION_EXIST        (1<<0)\r
+#define RECURSION_MUST         (1<<1)\r
+#define RECURSION_INFINITE     (1<<2)\r
+\r
 static int\r
-subexp_recursive_check_trav(Node* node, ScanEnv* env)\r
+infinite_recursive_call_check(Node* node, ScanEnv* env, int head)\r
 {\r
-#define FOUND_CALLED_NODE    1\r
-\r
-  int type;\r
+  int ret;\r
   int r = 0;\r
 \r
-  type = NTYPE(node);\r
-  switch (type) {\r
-  case NT_LIST:\r
-  case NT_ALT:\r
+  switch (NODE_TYPE(node)) {\r
+  case NODE_LIST:\r
     {\r
-      int ret;\r
+      Node *x;\r
+      OnigLen min;\r
+\r
+      x = node;\r
       do {\r
-       ret = subexp_recursive_check_trav(NCAR(node), env);\r
-       if (ret == FOUND_CALLED_NODE) r = FOUND_CALLED_NODE;\r
-       else if (ret < 0) return ret;\r
-      } while (IS_NOT_NULL(node = NCDR(node)));\r
+        ret = infinite_recursive_call_check(NODE_CAR(x), env, head);\r
+        if (ret < 0 || (ret & RECURSION_INFINITE) != 0) return ret;\r
+        r |= ret;\r
+        if (head != 0) {\r
+          min = tree_min_len(NODE_CAR(x), env);\r
+          if (min != 0) head = 0;\r
+        }\r
+      } while (IS_NOT_NULL(x = NODE_CDR(x)));\r
     }\r
     break;\r
 \r
-  case NT_QTFR:\r
-    r = subexp_recursive_check_trav(NQTFR(node)->target, env);\r
-    if (NQTFR(node)->upper == 0) {\r
-      if (r == FOUND_CALLED_NODE)\r
-       NQTFR(node)->is_refered = 1;\r
+  case NODE_ALT:\r
+    {\r
+      int must;\r
+\r
+      must = RECURSION_MUST;\r
+      do {\r
+        ret = infinite_recursive_call_check(NODE_CAR(node), env, head);\r
+        if (ret < 0 || (ret & RECURSION_INFINITE) != 0) return ret;\r
+\r
+        r    |= (ret & RECURSION_EXIST);\r
+        must &= ret;\r
+      } while (IS_NOT_NULL(node = NODE_CDR(node)));\r
+      r |= must;\r
     }\r
     break;\r
 \r
-  case NT_ANCHOR:\r
-    {\r
-      AnchorNode* an = NANCHOR(node);\r
-      switch (an->type) {\r
-      case ANCHOR_PREC_READ:\r
-      case ANCHOR_PREC_READ_NOT:\r
-      case ANCHOR_LOOK_BEHIND:\r
-      case ANCHOR_LOOK_BEHIND_NOT:\r
-       r = subexp_recursive_check_trav(an->target, env);\r
-       break;\r
-      }\r
+  case NODE_QUANT:\r
+    r = infinite_recursive_call_check(NODE_BODY(node), env, head);\r
+    if (r < 0) return r;\r
+    if ((r & RECURSION_MUST) != 0) {\r
+      if (QUANT_(node)->lower == 0)\r
+        r &= ~RECURSION_MUST;\r
     }\r
     break;\r
 \r
-  case NT_ENCLOSE:\r
+  case NODE_ANCHOR:\r
+    if (! ANCHOR_HAS_BODY(ANCHOR_(node)))\r
+      break;\r
+    /* fall */\r
+  case NODE_CALL:\r
+    r = infinite_recursive_call_check(NODE_BODY(node), env, head);\r
+    break;\r
+\r
+  case NODE_ENCLOSURE:\r
     {\r
-      EncloseNode* en = NENCLOSE(node);\r
-\r
-      if (! IS_ENCLOSE_RECURSION(en)) {\r
-       if (IS_ENCLOSE_CALLED(en)) {\r
-         SET_ENCLOSE_STATUS(node, NST_MARK1);\r
-         r = subexp_recursive_check(en->target);\r
-         if (r != 0) SET_ENCLOSE_STATUS(node, NST_RECURSION);\r
-         CLEAR_ENCLOSE_STATUS(node, NST_MARK1);\r
-       }\r
+      EnclosureNode* en = ENCLOSURE_(node);\r
+\r
+      if (en->type == ENCLOSURE_MEMORY) {\r
+        if (NODE_IS_MARK2(node))\r
+          return 0;\r
+        else if (NODE_IS_MARK1(node))\r
+          return (head == 0 ? RECURSION_EXIST | RECURSION_MUST\r
+                  : RECURSION_EXIST | RECURSION_MUST | RECURSION_INFINITE);\r
+        else {\r
+          NODE_STATUS_ADD(node, MARK2);\r
+          r = infinite_recursive_call_check(NODE_BODY(node), env, head);\r
+          NODE_STATUS_REMOVE(node, MARK2);\r
+        }\r
+      }\r
+      else if (en->type == ENCLOSURE_IF_ELSE) {\r
+        int eret;\r
+\r
+        ret = infinite_recursive_call_check(NODE_BODY(node), env, head);\r
+        if (ret < 0 || (ret & RECURSION_INFINITE) != 0) return ret;\r
+        r |= ret;\r
+        if (IS_NOT_NULL(en->te.Then)) {\r
+          OnigLen min;\r
+          if (head != 0) {\r
+            min = tree_min_len(NODE_BODY(node), env);\r
+          }\r
+          else min = 0;\r
+\r
+          ret = infinite_recursive_call_check(en->te.Then, env, min != 0 ? 0:head);\r
+          if (ret < 0 || (ret & RECURSION_INFINITE) != 0) return ret;\r
+          r |= ret;\r
+        }\r
+        if (IS_NOT_NULL(en->te.Else)) {\r
+          eret = infinite_recursive_call_check(en->te.Else, env, head);\r
+          if (eret < 0 || (eret & RECURSION_INFINITE) != 0) return eret;\r
+          r |= (eret & RECURSION_EXIST);\r
+          if ((eret & RECURSION_MUST) == 0)\r
+            r &= ~RECURSION_MUST;\r
+        }\r
+      }\r
+      else {\r
+        r = infinite_recursive_call_check(NODE_BODY(node), env, head);\r
       }\r
-      r = subexp_recursive_check_trav(en->target, env);\r
-      if (IS_ENCLOSE_CALLED(en))\r
-       r |= FOUND_CALLED_NODE;\r
     }\r
     break;\r
 \r
@@ -2989,102 +3097,217 @@ subexp_recursive_check_trav(Node* node, ScanEnv* env)
 }\r
 \r
 static int\r
-setup_subexp_call(Node* node, ScanEnv* env)\r
+infinite_recursive_call_check_trav(Node* node, ScanEnv* env)\r
 {\r
-  int type;\r
-  int r = 0;\r
+  int r;\r
 \r
-  type = NTYPE(node);\r
-  switch (type) {\r
-  case NT_LIST:\r
+  switch (NODE_TYPE(node)) {\r
+  case NODE_LIST:\r
+  case NODE_ALT:\r
     do {\r
-      r = setup_subexp_call(NCAR(node), env);\r
-    } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));\r
+      r = infinite_recursive_call_check_trav(NODE_CAR(node), env);\r
+    } while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));\r
+    break;\r
+\r
+  case NODE_ANCHOR:\r
+    if (! ANCHOR_HAS_BODY(ANCHOR_(node))) {\r
+      r = 0;\r
+      break;\r
+    }\r
+    /* fall */\r
+  case NODE_QUANT:\r
+    r = infinite_recursive_call_check_trav(NODE_BODY(node), env);\r
+    break;\r
+\r
+  case NODE_ENCLOSURE:\r
+    {\r
+      EnclosureNode* en = ENCLOSURE_(node);\r
+\r
+      if (en->type == ENCLOSURE_MEMORY) {\r
+        if (NODE_IS_RECURSION(node) && NODE_IS_CALLED(node)) {\r
+          int ret;\r
+\r
+          NODE_STATUS_ADD(node, MARK1);\r
+\r
+          ret = infinite_recursive_call_check(NODE_BODY(node), env, 1);\r
+          if (ret < 0) return ret;\r
+          else if ((ret & (RECURSION_MUST | RECURSION_INFINITE)) != 0)\r
+            return ONIGERR_NEVER_ENDING_RECURSION;\r
+\r
+          NODE_STATUS_REMOVE(node, MARK1);\r
+        }\r
+      }\r
+      else if (en->type == ENCLOSURE_IF_ELSE) {\r
+        if (IS_NOT_NULL(en->te.Then)) {\r
+          r = infinite_recursive_call_check_trav(en->te.Then, env);\r
+          if (r != 0) return r;\r
+        }\r
+        if (IS_NOT_NULL(en->te.Else)) {\r
+          r = infinite_recursive_call_check_trav(en->te.Else, env);\r
+          if (r != 0) return r;\r
+        }\r
+      }\r
+    }\r
+\r
+    r = infinite_recursive_call_check_trav(NODE_BODY(node), env);\r
+    break;\r
+\r
+  default:\r
+    r = 0;\r
     break;\r
+  }\r
+\r
+  return r;\r
+}\r
+\r
+static int\r
+recursive_call_check(Node* node)\r
+{\r
+  int r;\r
 \r
-  case NT_ALT:\r
+  switch (NODE_TYPE(node)) {\r
+  case NODE_LIST:\r
+  case NODE_ALT:\r
+    r = 0;\r
     do {\r
-      r = setup_subexp_call(NCAR(node), env);\r
-    } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));\r
+      r |= recursive_call_check(NODE_CAR(node));\r
+    } while (IS_NOT_NULL(node = NODE_CDR(node)));\r
     break;\r
 \r
-  case NT_QTFR:\r
-    r = setup_subexp_call(NQTFR(node)->target, env);\r
+  case NODE_ANCHOR:\r
+    if (! ANCHOR_HAS_BODY(ANCHOR_(node))) {\r
+      r = 0;\r
+      break;\r
+    }\r
+    /* fall */\r
+  case NODE_QUANT:\r
+    r = recursive_call_check(NODE_BODY(node));\r
     break;\r
-  case NT_ENCLOSE:\r
-    r = setup_subexp_call(NENCLOSE(node)->target, env);\r
+\r
+  case NODE_CALL:\r
+    r = recursive_call_check(NODE_BODY(node));\r
+    if (r != 0) {\r
+      if (NODE_IS_MARK1(NODE_BODY(node)))\r
+        NODE_STATUS_ADD(node, RECURSION);\r
+    }\r
     break;\r
 \r
-  case NT_CALL:\r
+  case NODE_ENCLOSURE:\r
     {\r
-      CallNode* cn = NCALL(node);\r
-      Node** nodes = SCANENV_MEM_NODES(env);\r
-\r
-      if (cn->group_num != 0) {\r
-       int gnum = cn->group_num;\r
-\r
-#ifdef USE_NAMED_GROUP\r
-       if (env->num_named > 0 &&\r
-           IS_SYNTAX_BV(env->syntax, ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP) &&\r
-           !ONIG_IS_OPTION_ON(env->option, ONIG_OPTION_CAPTURE_GROUP)) {\r
-         return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;\r
-       }\r
-#endif\r
-       if (gnum > env->num_mem) {\r
-         onig_scan_env_set_error_string(env,\r
-                ONIGERR_UNDEFINED_GROUP_REFERENCE, cn->name, cn->name_end);\r
-         return ONIGERR_UNDEFINED_GROUP_REFERENCE;\r
-       }\r
-\r
-#ifdef USE_NAMED_GROUP\r
-      set_call_attr:\r
-#endif\r
-       cn->target = nodes[cn->group_num];\r
-       if (IS_NULL(cn->target)) {\r
-         onig_scan_env_set_error_string(env,\r
-                ONIGERR_UNDEFINED_NAME_REFERENCE, cn->name, cn->name_end);\r
-         return ONIGERR_UNDEFINED_NAME_REFERENCE;\r
-       }\r
-       SET_ENCLOSE_STATUS(cn->target, NST_CALLED);\r
-       BIT_STATUS_ON_AT(env->bt_mem_start, cn->group_num);\r
-       cn->unset_addr_list = env->unset_addr_list;\r
+      EnclosureNode* en = ENCLOSURE_(node);\r
+\r
+      if (en->type == ENCLOSURE_MEMORY) {\r
+        if (NODE_IS_MARK2(node))\r
+          return 0;\r
+        else if (NODE_IS_MARK1(node))\r
+          return 1; /* recursion */\r
+        else {\r
+          NODE_STATUS_ADD(node, MARK2);\r
+          r = recursive_call_check(NODE_BODY(node));\r
+          NODE_STATUS_REMOVE(node, MARK2);\r
+        }\r
+      }\r
+      else if (en->type == ENCLOSURE_IF_ELSE) {\r
+        r = 0;\r
+        if (IS_NOT_NULL(en->te.Then)) {\r
+          r |= recursive_call_check(en->te.Then);\r
+        }\r
+        if (IS_NOT_NULL(en->te.Else)) {\r
+          r |= recursive_call_check(en->te.Else);\r
+        }\r
+        r |= recursive_call_check(NODE_BODY(node));\r
       }\r
-#ifdef USE_NAMED_GROUP\r
       else {\r
-       int *refs;\r
-\r
-       int n = onig_name_to_group_numbers(env->reg, cn->name, cn->name_end,\r
-                                          &refs);\r
-       if (n <= 0) {\r
-         onig_scan_env_set_error_string(env,\r
-                ONIGERR_UNDEFINED_NAME_REFERENCE, cn->name, cn->name_end);\r
-         return ONIGERR_UNDEFINED_NAME_REFERENCE;\r
-       }\r
-       else if (n > 1) {\r
-         onig_scan_env_set_error_string(env,\r
-           ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL, cn->name, cn->name_end);\r
-         return ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL;\r
-       }\r
-       else {\r
-         cn->group_num = refs[0];\r
-         goto set_call_attr;\r
-       }\r
+        r = recursive_call_check(NODE_BODY(node));\r
       }\r
-#endif\r
     }\r
     break;\r
 \r
-  case NT_ANCHOR:\r
+  default:\r
+    r = 0;\r
+    break;\r
+  }\r
+\r
+  return r;\r
+}\r
+\r
+#define IN_RECURSION         (1<<0)\r
+#define FOUND_CALLED_NODE    1\r
+\r
+static int\r
+recursive_call_check_trav(Node* node, ScanEnv* env, int state)\r
+{\r
+  int r = 0;\r
+\r
+  switch (NODE_TYPE(node)) {\r
+  case NODE_LIST:\r
+  case NODE_ALT:\r
     {\r
-      AnchorNode* an = NANCHOR(node);\r
+      int ret;\r
+      do {\r
+        ret = recursive_call_check_trav(NODE_CAR(node), env, state);\r
+        if (ret == FOUND_CALLED_NODE) r = FOUND_CALLED_NODE;\r
+        else if (ret < 0) return ret;\r
+      } while (IS_NOT_NULL(node = NODE_CDR(node)));\r
+    }\r
+    break;\r
 \r
-      switch (an->type) {\r
-      case ANCHOR_PREC_READ:\r
-      case ANCHOR_PREC_READ_NOT:\r
-      case ANCHOR_LOOK_BEHIND:\r
-      case ANCHOR_LOOK_BEHIND_NOT:\r
-       r = setup_subexp_call(an->target, env);\r
-       break;\r
+  case NODE_QUANT:\r
+    r = recursive_call_check_trav(NODE_BODY(node), env, state);\r
+    if (QUANT_(node)->upper == 0) {\r
+      if (r == FOUND_CALLED_NODE)\r
+        QUANT_(node)->is_refered = 1;\r
+    }\r
+    break;\r
+\r
+  case NODE_ANCHOR:\r
+    {\r
+      AnchorNode* an = ANCHOR_(node);\r
+      if (ANCHOR_HAS_BODY(an))\r
+        r = recursive_call_check_trav(NODE_ANCHOR_BODY(an), env, state);\r
+    }\r
+    break;\r
+\r
+  case NODE_ENCLOSURE:\r
+    {\r
+      int ret;\r
+      int state1;\r
+      EnclosureNode* en = ENCLOSURE_(node);\r
+\r
+      if (en->type == ENCLOSURE_MEMORY) {\r
+        if (NODE_IS_CALLED(node) || (state & IN_RECURSION) != 0) {\r
+          if (! NODE_IS_RECURSION(node)) {\r
+            NODE_STATUS_ADD(node, MARK1);\r
+            r = recursive_call_check(NODE_BODY(node));\r
+            if (r != 0)\r
+              NODE_STATUS_ADD(node, RECURSION);\r
+            NODE_STATUS_REMOVE(node, MARK1);\r
+          }\r
+\r
+          if (NODE_IS_CALLED(node))\r
+            r = FOUND_CALLED_NODE;\r
+        }\r
+      }\r
+\r
+      state1 = state;\r
+      if (NODE_IS_RECURSION(node))\r
+        state1 |= IN_RECURSION;\r
+\r
+      ret = recursive_call_check_trav(NODE_BODY(node), env, state1);\r
+      if (ret == FOUND_CALLED_NODE)\r
+        r = FOUND_CALLED_NODE;\r
+\r
+      if (en->type == ENCLOSURE_IF_ELSE) {\r
+        if (IS_NOT_NULL(en->te.Then)) {\r
+          ret = recursive_call_check_trav(en->te.Then, env, state1);\r
+          if (ret == FOUND_CALLED_NODE)\r
+            r = FOUND_CALLED_NODE;\r
+        }\r
+        if (IS_NOT_NULL(en->te.Else)) {\r
+          ret = recursive_call_check_trav(en->te.Else, env, state1);\r
+          if (ret == FOUND_CALLED_NODE)\r
+            r = FOUND_CALLED_NODE;\r
+        }\r
       }\r
     }\r
     break;\r
@@ -3095,6 +3318,7 @@ setup_subexp_call(Node* node, ScanEnv* env)
 \r
   return r;\r
 }\r
+\r
 #endif\r
 \r
 /* divide different length alternatives in look-behind.\r
@@ -3105,28 +3329,28 @@ static int
 divide_look_behind_alternatives(Node* node)\r
 {\r
   Node *head, *np, *insert_node;\r
-  AnchorNode* an = NANCHOR(node);\r
+  AnchorNode* an = ANCHOR_(node);\r
   int anc_type = an->type;\r
 \r
-  head = an->target;\r
-  np = NCAR(head);\r
+  head = NODE_ANCHOR_BODY(an);\r
+  np = NODE_CAR(head);\r
   swap_node(node, head);\r
-  NCAR(node) = head;\r
-  NANCHOR(head)->target = np;\r
+  NODE_CAR(node) = head;\r
+  NODE_BODY(head) = np;\r
 \r
   np = node;\r
-  while ((np = NCDR(np)) != NULL_NODE) {\r
-    insert_node = onig_node_new_anchor(anc_type);\r
+  while (IS_NOT_NULL(np = NODE_CDR(np))) {\r
+    insert_node = onig_node_new_anchor(anc_type, an->ascii_mode);\r
     CHECK_NULL_RETURN_MEMERR(insert_node);\r
-    NANCHOR(insert_node)->target = NCAR(np);\r
-    NCAR(np) = insert_node;\r
+    NODE_BODY(insert_node) = NODE_CAR(np);\r
+    NODE_CAR(np) = insert_node;\r
   }\r
 \r
   if (anc_type == ANCHOR_LOOK_BEHIND_NOT) {\r
     np = node;\r
     do {\r
-      SET_NTYPE(np, NT_LIST);  /* alt -> list */\r
-    } while ((np = NCDR(np)) != NULL_NODE);\r
+      NODE_SET_TYPE(np, NODE_LIST);  /* alt -> list */\r
+    } while (IS_NOT_NULL(np = NODE_CDR(np)));\r
   }\r
   return 0;\r
 }\r
@@ -3135,9 +3359,9 @@ static int
 setup_look_behind(Node* node, regex_t* reg, ScanEnv* env)\r
 {\r
   int r, len;\r
-  AnchorNode* an = NANCHOR(node);\r
+  AnchorNode* an = ANCHOR_(node);\r
 \r
-  r = get_char_length_tree(an->target, reg, &len);\r
+  r = get_char_length_tree(NODE_ANCHOR_BODY(an), reg, &len);\r
   if (r == 0)\r
     an->char_len = len;\r
   else if (r == GET_CHAR_LEN_VARLEN)\r
@@ -3155,44 +3379,43 @@ setup_look_behind(Node* node, regex_t* reg, ScanEnv* env)
 static int\r
 next_setup(Node* node, Node* next_node, regex_t* reg)\r
 {\r
-  int type;\r
+  NodeType type;\r
 \r
  retry:\r
-  type = NTYPE(node);\r
-  if (type == NT_QTFR) {\r
-    QtfrNode* qn = NQTFR(node);\r
+  type = NODE_TYPE(node);\r
+  if (type == NODE_QUANT) {\r
+    QuantNode* qn = QUANT_(node);\r
     if (qn->greedy && IS_REPEAT_INFINITE(qn->upper)) {\r
-#ifdef USE_QTFR_PEEK_NEXT\r
+#ifdef USE_QUANT_PEEK_NEXT\r
       Node* n = get_head_value_node(next_node, 1, reg);\r
       /* '\0': for UTF-16BE etc... */\r
-      if (IS_NOT_NULL(n) && NSTR(n)->s[0] != '\0') {\r
-       qn->next_head_exact = n;\r
+      if (IS_NOT_NULL(n) && STR_(n)->s[0] != '\0') {\r
+        qn->next_head_exact = n;\r
       }\r
 #endif\r
       /* automatic posseivation a*b ==> (?>a*)b */\r
       if (qn->lower <= 1) {\r
-       int ttype = NTYPE(qn->target);\r
-       if (IS_NODE_TYPE_SIMPLE(ttype)) {\r
-         Node *x, *y;\r
-         x = get_head_value_node(qn->target, 0, reg);\r
-         if (IS_NOT_NULL(x)) {\r
-           y = get_head_value_node(next_node,  0, reg);\r
-           if (IS_NOT_NULL(y) && is_not_included(x, y, reg)) {\r
-             Node* en = onig_node_new_enclose(ENCLOSE_STOP_BACKTRACK);\r
-             CHECK_NULL_RETURN_MEMERR(en);\r
-             SET_ENCLOSE_STATUS(en, NST_STOP_BT_SIMPLE_REPEAT);\r
-             swap_node(node, en);\r
-             NENCLOSE(node)->target = en;\r
-           }\r
-         }\r
-       }\r
+        if (NODE_IS_SIMPLE_TYPE(NODE_BODY(node))) {\r
+          Node *x, *y;\r
+          x = get_head_value_node(NODE_BODY(node), 0, reg);\r
+          if (IS_NOT_NULL(x)) {\r
+            y = get_head_value_node(next_node,  0, reg);\r
+            if (IS_NOT_NULL(y) && is_exclusive(x, y, reg)) {\r
+              Node* en = onig_node_new_enclosure(ENCLOSURE_STOP_BACKTRACK);\r
+              CHECK_NULL_RETURN_MEMERR(en);\r
+              NODE_STATUS_ADD(en, STOP_BT_SIMPLE_REPEAT);\r
+              swap_node(node, en);\r
+              NODE_BODY(node) = en;\r
+            }\r
+          }\r
+        }\r
       }\r
     }\r
   }\r
-  else if (type == NT_ENCLOSE) {\r
-    EncloseNode* en = NENCLOSE(node);\r
-    if (en->type == ENCLOSE_MEMORY) {\r
-      node = en->target;\r
+  else if (type == NODE_ENCLOSURE) {\r
+    EnclosureNode* en = ENCLOSURE_(node);\r
+    if (en->type == ENCLOSURE_MEMORY) {\r
+      node = NODE_BODY(node);\r
       goto retry;\r
     }\r
   }\r
@@ -3206,10 +3429,10 @@ update_string_node_case_fold(regex_t* reg, Node *node)
   UChar *p, *end, buf[ONIGENC_MBC_CASE_FOLD_MAXLEN];\r
   UChar *sbuf, *ebuf, *sp;\r
   int r, i, len, sbuf_size;\r
-  StrNode* sn = NSTR(node);\r
+  StrNode* sn = STR_(node);\r
 \r
   end = sn->end;\r
-  sbuf_size = (int)(end - sn->s) * 2;\r
+  sbuf_size = (int )(end - sn->s) * 2;\r
   sbuf = (UChar* )xmalloc(sbuf_size);\r
   CHECK_NULL_RETURN_MEMERR(sbuf);\r
   ebuf = sbuf + sbuf_size;\r
@@ -3242,8 +3465,7 @@ update_string_node_case_fold(regex_t* reg, Node *node)
 }\r
 \r
 static int\r
-expand_case_fold_make_rem_string(Node** rnode, UChar *s, UChar *end,\r
-                                regex_t* reg)\r
+expand_case_fold_make_rem_string(Node** rnode, UChar *s, UChar *end, regex_t* reg)\r
 {\r
   int r;\r
   Node *node;\r
@@ -3257,21 +3479,21 @@ expand_case_fold_make_rem_string(Node** rnode, UChar *s, UChar *end,
     return r;\r
   }\r
 \r
-  NSTRING_SET_AMBIG(node);\r
-  NSTRING_SET_DONT_GET_OPT_INFO(node);\r
+  NODE_STRING_SET_AMBIG(node);\r
+  NODE_STRING_SET_DONT_GET_OPT_INFO(node);\r
   *rnode = node;\r
   return 0;\r
 }\r
 \r
 static int\r
-expand_case_fold_string_alt(int item_num, OnigCaseFoldCodeItem items[],\r
-                           UChar *p, int slen, UChar *end,\r
-                           regex_t* reg, Node **rnode)\r
+expand_case_fold_string_alt(int item_num, OnigCaseFoldCodeItem items[], UChar *p,\r
+                            int slen, UChar *end, regex_t* reg, Node **rnode)\r
 {\r
-  int r, i, j, len, varlen;\r
+  int r, i, j;\r
+  int len;\r
+  int varlen;\r
   Node *anode, *var_anode, *snode, *xnode, *an;\r
   UChar buf[ONIGENC_CODE_TO_MBC_MAXLEN];\r
-  xnode = NULL_NODE;\r
 \r
   *rnode = var_anode = NULL_NODE;\r
 \r
@@ -3289,11 +3511,11 @@ expand_case_fold_string_alt(int item_num, OnigCaseFoldCodeItem items[],
 \r
     xnode = onig_node_new_list(NULL, NULL);\r
     if (IS_NULL(xnode)) goto mem_err;\r
-    NCAR(var_anode) = xnode;\r
+    NODE_CAR(var_anode) = xnode;\r
 \r
     anode = onig_node_new_alt(NULL_NODE, NULL_NODE);\r
     if (IS_NULL(anode)) goto mem_err;\r
-    NCAR(xnode) = anode;\r
+    NODE_CAR(xnode) = anode;\r
   }\r
   else {\r
     *rnode = anode = onig_node_new_alt(NULL_NODE, NULL_NODE);\r
@@ -3303,7 +3525,7 @@ expand_case_fold_string_alt(int item_num, OnigCaseFoldCodeItem items[],
   snode = onig_node_new_str(p, p + slen);\r
   if (IS_NULL(snode)) goto mem_err;\r
 \r
-  NCAR(anode) = snode;\r
+  NODE_CAR(anode) = snode;\r
 \r
   for (i = 0; i < item_num; i++) {\r
     snode = onig_node_new_str(NULL, NULL);\r
@@ -3312,8 +3534,8 @@ expand_case_fold_string_alt(int item_num, OnigCaseFoldCodeItem items[],
     for (j = 0; j < items[i].code_len; j++) {\r
       len = ONIGENC_CODE_TO_MBC(reg->enc, items[i].code[j], buf);\r
       if (len < 0) {\r
-       r = len;\r
-       goto mem_err2;\r
+        r = len;\r
+        goto mem_err2;\r
       }\r
 \r
       r = onig_node_str_cat(snode, buf, buf + len);\r
@@ -3326,7 +3548,7 @@ expand_case_fold_string_alt(int item_num, OnigCaseFoldCodeItem items[],
     }\r
 \r
     if (items[i].byte_len != slen) {\r
-      Node *rem = NULL_NODE;\r
+      Node *rem;\r
       UChar *q = p + items[i].byte_len;\r
 \r
       if (q < end) {\r
@@ -3349,24 +3571,18 @@ expand_case_fold_string_alt(int item_num, OnigCaseFoldCodeItem items[],
           goto mem_err;\r
         }\r
 \r
-        NCAR(an) = xnode;\r
+        NODE_CAR(an) = xnode;\r
       }\r
       else {\r
-        NCAR(an) = snode;\r
+        NODE_CAR(an) = snode;\r
       }\r
 \r
-      if (var_anode == NULL) {\r
-        onig_node_free(an);\r
-        onig_node_free(xnode);\r
-        onig_node_free(rem);\r
-        goto mem_err2;\r
-      }\r
-      NCDR(var_anode) = an;\r
+      NODE_CDR(var_anode) = an;\r
       var_anode = an;\r
     }\r
     else {\r
-      NCAR(an)     = snode;\r
-      NCDR(anode) = an;\r
+      NODE_CAR(an)     = snode;\r
+      NODE_CDR(anode) = an;\r
       anode = an;\r
     }\r
   }\r
@@ -3391,9 +3607,9 @@ expand_case_fold_string(Node* node, regex_t* reg)
   UChar *start, *end, *p;\r
   Node *top_root, *root, *snode, *prev_node;\r
   OnigCaseFoldCodeItem items[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM];\r
-  StrNode* sn = NSTR(node);\r
+  StrNode* sn = STR_(node);\r
 \r
-  if (NSTRING_IS_AMBIG(node)) return 0;\r
+  if (NODE_STRING_IS_AMBIG(node)) return 0;\r
 \r
   start = sn->s;\r
   end   = sn->end;\r
@@ -3404,8 +3620,8 @@ expand_case_fold_string(Node* node, regex_t* reg)
   alt_num = 1;\r
   p = start;\r
   while (p < end) {\r
-    n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(reg->enc, reg->case_fold_flag,\r
-                                          p, end, items);\r
+    n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(reg->enc, reg->case_fold_flag, p, end,\r
+                                           items);\r
     if (n < 0) {\r
       r = n;\r
       goto err;\r
@@ -3415,22 +3631,22 @@ expand_case_fold_string(Node* node, regex_t* reg)
 \r
     if (n == 0) {\r
       if (IS_NULL(snode)) {\r
-       if (IS_NULL(root) && IS_NOT_NULL(prev_node)) {\r
-         top_root = root = onig_node_list_add(NULL_NODE, prev_node);\r
-         if (IS_NULL(root)) {\r
-           onig_node_free(prev_node);\r
-           goto mem_err;\r
-         }\r
-       }\r
-\r
-       prev_node = snode = onig_node_new_str(NULL, NULL);\r
-       if (IS_NULL(snode)) goto mem_err;\r
-       if (IS_NOT_NULL(root)) {\r
-         if (IS_NULL(onig_node_list_add(root, snode))) {\r
-           onig_node_free(snode);\r
-           goto mem_err;\r
-         }\r
-       }\r
+        if (IS_NULL(root) && IS_NOT_NULL(prev_node)) {\r
+          top_root = root = onig_node_list_add(NULL_NODE, prev_node);\r
+          if (IS_NULL(root)) {\r
+            onig_node_free(prev_node);\r
+            goto mem_err;\r
+          }\r
+        }\r
+\r
+        prev_node = snode = onig_node_new_str(NULL, NULL);\r
+        if (IS_NULL(snode)) goto mem_err;\r
+        if (IS_NOT_NULL(root)) {\r
+          if (IS_NULL(onig_node_list_add(root, snode))) {\r
+            onig_node_free(snode);\r
+            goto mem_err;\r
+          }\r
+        }\r
       }\r
 \r
       r = onig_node_str_cat(snode, p, p + len);\r
@@ -3441,37 +3657,37 @@ expand_case_fold_string(Node* node, regex_t* reg)
       if (alt_num > THRESHOLD_CASE_FOLD_ALT_FOR_EXPANSION) break;\r
 \r
       if (IS_NULL(root) && IS_NOT_NULL(prev_node)) {\r
-       top_root = root = onig_node_list_add(NULL_NODE, prev_node);\r
-       if (IS_NULL(root)) {\r
-         onig_node_free(prev_node);\r
-         goto mem_err;\r
-       }\r
+        top_root = root = onig_node_list_add(NULL_NODE, prev_node);\r
+        if (IS_NULL(root)) {\r
+          onig_node_free(prev_node);\r
+          goto mem_err;\r
+        }\r
       }\r
 \r
       r = expand_case_fold_string_alt(n, items, p, len, end, reg, &prev_node);\r
       if (r < 0) goto mem_err;\r
       if (r == 1) {\r
-       if (IS_NULL(root)) {\r
-         top_root = prev_node;\r
-       }\r
-       else {\r
-         if (IS_NULL(onig_node_list_add(root, prev_node))) {\r
-           onig_node_free(prev_node);\r
-           goto mem_err;\r
-         }\r
-       }\r
-\r
-       root = NCAR(prev_node);\r
-      }\r
-      else { /* r == 0 */\r
-       if (IS_NOT_NULL(root)) {\r
-         if (IS_NULL(onig_node_list_add(root, prev_node))) {\r
-           onig_node_free(prev_node);\r
-           goto mem_err;\r
-         }\r
-       }\r
-      }\r
-\r
+        if (IS_NULL(root)) {\r
+          top_root = prev_node;\r
+        }\r
+        else {\r
+          if (IS_NULL(onig_node_list_add(root, prev_node))) {\r
+            onig_node_free(prev_node);\r
+            goto mem_err;\r
+          }\r
+        }\r
+\r
+        root = NODE_CAR(prev_node);\r
+      }\r
+      else { /* r == 0 */\r
+        if (IS_NOT_NULL(root)) {\r
+          if (IS_NULL(onig_node_list_add(root, prev_node))) {\r
+            onig_node_free(prev_node);\r
+            goto mem_err;\r
+          }\r
+        }\r
+      }\r
+\r
       snode = NULL_NODE;\r
     }\r
 \r
@@ -3487,185 +3703,712 @@ expand_case_fold_string(Node* node, regex_t* reg)
     if (IS_NOT_NULL(prev_node) && IS_NULL(root)) {\r
       top_root = root = onig_node_list_add(NULL_NODE, prev_node);\r
       if (IS_NULL(root)) {\r
-       onig_node_free(srem);\r
-       onig_node_free(prev_node);\r
-       goto mem_err;\r
+        onig_node_free(srem);\r
+        onig_node_free(prev_node);\r
+        goto mem_err;\r
+      }\r
+    }\r
+\r
+    if (IS_NULL(root)) {\r
+      prev_node = srem;\r
+    }\r
+    else {\r
+      if (IS_NULL(onig_node_list_add(root, srem))) {\r
+        onig_node_free(srem);\r
+        goto mem_err;\r
+      }\r
+    }\r
+  }\r
+\r
+  /* ending */\r
+  top_root = (IS_NOT_NULL(top_root) ? top_root : prev_node);\r
+  swap_node(node, top_root);\r
+  onig_node_free(top_root);\r
+  return 0;\r
+\r
+ mem_err:\r
+  r = ONIGERR_MEMORY;\r
+\r
+ err:\r
+  onig_node_free(top_root);\r
+  return r;\r
+}\r
+\r
+#ifdef USE_INSISTENT_CHECK_CAPTURES_IN_EMPTY_REPEAT\r
+static enum QuantBodyEmpty\r
+quantifiers_memory_node_info(Node* node)\r
+{\r
+  int r = QUANT_BODY_IS_EMPTY;\r
+\r
+  switch (NODE_TYPE(node)) {\r
+  case NODE_LIST:\r
+  case NODE_ALT:\r
+    {\r
+      int v;\r
+      do {\r
+        v = quantifiers_memory_node_info(NODE_CAR(node));\r
+        if (v > r) r = v;\r
+      } while (IS_NOT_NULL(node = NODE_CDR(node)));\r
+    }\r
+    break;\r
+\r
+#ifdef USE_CALL\r
+  case NODE_CALL:\r
+    if (NODE_IS_RECURSION(node)) {\r
+      return QUANT_BODY_IS_EMPTY_REC; /* tiny version */\r
+    }\r
+    else\r
+      r = quantifiers_memory_node_info(NODE_BODY(node));\r
+    break;\r
+#endif\r
+\r
+  case NODE_QUANT:\r
+    {\r
+      QuantNode* qn = QUANT_(node);\r
+      if (qn->upper != 0) {\r
+        r = quantifiers_memory_node_info(NODE_BODY(node));\r
+      }\r
+    }\r
+    break;\r
+\r
+  case NODE_ENCLOSURE:\r
+    {\r
+      EnclosureNode* en = ENCLOSURE_(node);\r
+      switch (en->type) {\r
+      case ENCLOSURE_MEMORY:\r
+        if (NODE_IS_RECURSION(node)) {\r
+          return QUANT_BODY_IS_EMPTY_REC;\r
+        }\r
+        return QUANT_BODY_IS_EMPTY_MEM;\r
+        break;\r
+\r
+      case ENCLOSURE_OPTION:\r
+      case ENCLOSURE_STOP_BACKTRACK:\r
+        r = quantifiers_memory_node_info(NODE_BODY(node));\r
+        break;\r
+      case ENCLOSURE_IF_ELSE:\r
+        {\r
+          int v;\r
+          r = quantifiers_memory_node_info(NODE_BODY(node));\r
+          if (IS_NOT_NULL(en->te.Then)) {\r
+            v = quantifiers_memory_node_info(en->te.Then);\r
+            if (v > r) r = v;\r
+          }\r
+          if (IS_NOT_NULL(en->te.Else)) {\r
+            v = quantifiers_memory_node_info(en->te.Else);\r
+            if (v > r) r = v;\r
+          }\r
+        }\r
+        break;\r
+      default:\r
+        break;\r
+      }\r
+    }\r
+    break;\r
+\r
+  case NODE_BACKREF:\r
+  case NODE_STRING:\r
+  case NODE_CTYPE:\r
+  case NODE_CCLASS:\r
+  case NODE_ANCHOR:\r
+  case NODE_GIMMICK:\r
+  default:\r
+    break;\r
+  }\r
+\r
+  return r;\r
+}\r
+#endif /* USE_INSISTENT_CHECK_CAPTURES_IN_EMPTY_REPEAT */\r
+\r
+\r
+#define IN_ALT          (1<<0)\r
+#define IN_NOT          (1<<1)\r
+#define IN_REAL_REPEAT  (1<<2)\r
+#define IN_VAR_REPEAT   (1<<3)\r
+#define IN_ZERO_REPEAT  (1<<4)\r
+#define IN_MULTI_ENTRY  (1<<5)\r
+\r
+#ifdef USE_CALL\r
+\r
+#ifdef __GNUC__\r
+__inline\r
+#endif\r
+static int\r
+setup_call_node_call(CallNode* cn, ScanEnv* env, int state)\r
+{\r
+  MemEnv* mem_env = SCANENV_MEMENV(env);\r
+\r
+  if (cn->by_number != 0) {\r
+    int gnum = cn->group_num;\r
+\r
+    if (env->num_named > 0 &&\r
+        IS_SYNTAX_BV(env->syntax, ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP) &&\r
+        ! ONIG_IS_OPTION_ON(env->options, ONIG_OPTION_CAPTURE_GROUP)) {\r
+      return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;\r
+    }\r
+\r
+    if (gnum > env->num_mem) {\r
+      onig_scan_env_set_error_string(env, ONIGERR_UNDEFINED_GROUP_REFERENCE,\r
+                                     cn->name, cn->name_end);\r
+      return ONIGERR_UNDEFINED_GROUP_REFERENCE;\r
+    }\r
+\r
+  set_call_attr:\r
+    NODE_CALL_BODY(cn) = mem_env[cn->group_num].node;\r
+    if (IS_NULL(NODE_CALL_BODY(cn))) {\r
+      onig_scan_env_set_error_string(env, ONIGERR_UNDEFINED_NAME_REFERENCE,\r
+                                     cn->name, cn->name_end);\r
+      return ONIGERR_UNDEFINED_NAME_REFERENCE;\r
+    }\r
+  }\r
+  else {\r
+    int *refs;\r
+\r
+    int n = onig_name_to_group_numbers(env->reg, cn->name, cn->name_end, &refs);\r
+    if (n <= 0) {\r
+      onig_scan_env_set_error_string(env, ONIGERR_UNDEFINED_NAME_REFERENCE,\r
+                                     cn->name, cn->name_end);\r
+      return ONIGERR_UNDEFINED_NAME_REFERENCE;\r
+    }\r
+    else if (n > 1) {\r
+      onig_scan_env_set_error_string(env, ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL,\r
+                                     cn->name, cn->name_end);\r
+      return ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL;\r
+    }\r
+    else {\r
+      cn->group_num = refs[0];\r
+      goto set_call_attr;\r
+    }\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+static void\r
+setup_call2_call(Node* node)\r
+{\r
+  switch (NODE_TYPE(node)) {\r
+  case NODE_LIST:\r
+  case NODE_ALT:\r
+    do {\r
+      setup_call2_call(NODE_CAR(node));\r
+    } while (IS_NOT_NULL(node = NODE_CDR(node)));\r
+    break;\r
+\r
+  case NODE_QUANT:\r
+    setup_call2_call(NODE_BODY(node));\r
+    break;\r
+\r
+  case NODE_ANCHOR:\r
+    if (ANCHOR_HAS_BODY(ANCHOR_(node)))\r
+      setup_call2_call(NODE_BODY(node));\r
+    break;\r
+\r
+  case NODE_ENCLOSURE:\r
+    {\r
+      EnclosureNode* en = ENCLOSURE_(node);\r
+\r
+      if (en->type == ENCLOSURE_MEMORY) {\r
+        if (! NODE_IS_MARK1(node)) {\r
+          NODE_STATUS_ADD(node, MARK1);\r
+          setup_call2_call(NODE_BODY(node));\r
+          NODE_STATUS_REMOVE(node, MARK1);\r
+        }\r
+      }\r
+      else if (en->type == ENCLOSURE_IF_ELSE) {\r
+        setup_call2_call(NODE_BODY(node));\r
+        if (IS_NOT_NULL(en->te.Then))\r
+          setup_call2_call(en->te.Then);\r
+        if (IS_NOT_NULL(en->te.Else))\r
+          setup_call2_call(en->te.Else);\r
+      }\r
+      else {\r
+        setup_call2_call(NODE_BODY(node));\r
+      }\r
+    }\r
+    break;\r
+\r
+  case NODE_CALL:\r
+    if (! NODE_IS_MARK1(node)) {\r
+      NODE_STATUS_ADD(node, MARK1);\r
+      {\r
+        CallNode* cn = CALL_(node);\r
+        Node* called = NODE_CALL_BODY(cn);\r
+\r
+        cn->entry_count++;\r
+\r
+        NODE_STATUS_ADD(called, CALLED);\r
+        ENCLOSURE_(called)->m.entry_count++;\r
+        setup_call2_call(called);\r
+      }\r
+      NODE_STATUS_REMOVE(node, MARK1);\r
+    }\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+}\r
+\r
+static int\r
+setup_call(Node* node, ScanEnv* env, int state)\r
+{\r
+  int r;\r
+\r
+  switch (NODE_TYPE(node)) {\r
+  case NODE_LIST:\r
+  case NODE_ALT:\r
+    do {\r
+      r = setup_call(NODE_CAR(node), env, state);\r
+    } while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));\r
+    break;\r
+\r
+  case NODE_QUANT:\r
+    if (QUANT_(node)->upper == 0)\r
+      state |= IN_ZERO_REPEAT;\r
+\r
+    r = setup_call(NODE_BODY(node), env, state);\r
+    break;\r
+\r
+  case NODE_ANCHOR:\r
+    if (ANCHOR_HAS_BODY(ANCHOR_(node)))\r
+      r = setup_call(NODE_BODY(node), env, state);\r
+    else\r
+      r = 0;\r
+    break;\r
+\r
+  case NODE_ENCLOSURE:\r
+    {\r
+      EnclosureNode* en = ENCLOSURE_(node);\r
+\r
+      if (en->type == ENCLOSURE_MEMORY) {\r
+        if ((state & IN_ZERO_REPEAT) != 0) {\r
+          NODE_STATUS_ADD(node, IN_ZERO_REPEAT);\r
+          ENCLOSURE_(node)->m.entry_count--;\r
+        }\r
+        r = setup_call(NODE_BODY(node), env, state);\r
+      }\r
+      else if (en->type == ENCLOSURE_IF_ELSE) {\r
+        r = setup_call(NODE_BODY(node), env, state);\r
+        if (r != 0) return r;\r
+        if (IS_NOT_NULL(en->te.Then)) {\r
+          r = setup_call(en->te.Then, env, state);\r
+          if (r != 0) return r;\r
+        }\r
+        if (IS_NOT_NULL(en->te.Else))\r
+          r = setup_call(en->te.Else, env, state);\r
+      }\r
+      else\r
+        r = setup_call(NODE_BODY(node), env, state);\r
+    }\r
+    break;\r
+\r
+  case NODE_CALL:\r
+    if ((state & IN_ZERO_REPEAT) != 0) {\r
+      NODE_STATUS_ADD(node, IN_ZERO_REPEAT);\r
+      CALL_(node)->entry_count--;\r
+    }\r
+\r
+    r = setup_call_node_call(CALL_(node), env, state);\r
+    break;\r
+\r
+  default:\r
+    r = 0;\r
+    break;\r
+  }\r
+\r
+  return r;\r
+}\r
+\r
+static int\r
+setup_call2(Node* node)\r
+{\r
+  int r = 0;\r
+\r
+  switch (NODE_TYPE(node)) {\r
+  case NODE_LIST:\r
+  case NODE_ALT:\r
+    do {\r
+      r = setup_call2(NODE_CAR(node));\r
+    } while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));\r
+    break;\r
+\r
+  case NODE_QUANT:\r
+    if (QUANT_(node)->upper != 0)\r
+      r = setup_call2(NODE_BODY(node));\r
+    break;\r
+\r
+  case NODE_ANCHOR:\r
+    if (ANCHOR_HAS_BODY(ANCHOR_(node)))\r
+      r = setup_call2(NODE_BODY(node));\r
+    break;\r
+\r
+  case NODE_ENCLOSURE:\r
+    if (! NODE_IS_IN_ZERO_REPEAT(node))\r
+      r = setup_call2(NODE_BODY(node));\r
+\r
+    {\r
+      EnclosureNode* en = ENCLOSURE_(node);\r
+\r
+      if (r != 0) return r;\r
+      if (en->type == ENCLOSURE_IF_ELSE) {\r
+        if (IS_NOT_NULL(en->te.Then)) {\r
+          r = setup_call2(en->te.Then);\r
+          if (r != 0) return r;\r
+        }\r
+        if (IS_NOT_NULL(en->te.Else))\r
+          r = setup_call2(en->te.Else);\r
+      }\r
+    }\r
+    break;\r
+\r
+  case NODE_CALL:\r
+    if (! NODE_IS_IN_ZERO_REPEAT(node)) {\r
+      setup_call2_call(node);\r
+    }\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+\r
+  return r;\r
+}\r
+\r
+\r
+static void\r
+setup_called_state_call(Node* node, int state)\r
+{\r
+  switch (NODE_TYPE(node)) {\r
+  case NODE_ALT:\r
+    state |= IN_ALT;\r
+    /* fall */\r
+  case NODE_LIST:\r
+    do {\r
+      setup_called_state_call(NODE_CAR(node), state);\r
+    } while (IS_NOT_NULL(node = NODE_CDR(node)));\r
+    break;\r
+\r
+  case NODE_QUANT:\r
+    {\r
+      QuantNode* qn = QUANT_(node);\r
+\r
+      if (IS_REPEAT_INFINITE(qn->upper) || qn->upper >= 2)\r
+        state |= IN_REAL_REPEAT;\r
+      if (qn->lower != qn->upper)\r
+        state |= IN_VAR_REPEAT;\r
+\r
+      setup_called_state_call(NODE_QUANT_BODY(qn), state);\r
+    }\r
+    break;\r
+\r
+  case NODE_ANCHOR:\r
+    {\r
+      AnchorNode* an = ANCHOR_(node);\r
+\r
+      switch (an->type) {\r
+      case ANCHOR_PREC_READ_NOT:\r
+      case ANCHOR_LOOK_BEHIND_NOT:\r
+        state |= IN_NOT;\r
+        /* fall */\r
+      case ANCHOR_PREC_READ:\r
+      case ANCHOR_LOOK_BEHIND:\r
+        setup_called_state_call(NODE_ANCHOR_BODY(an), state);\r
+        break;\r
+      default:\r
+        break;\r
+      }\r
+    }\r
+    break;\r
+\r
+  case NODE_ENCLOSURE:\r
+    {\r
+      EnclosureNode* en = ENCLOSURE_(node);\r
+\r
+      if (en->type == ENCLOSURE_MEMORY) {\r
+        if (NODE_IS_MARK1(node)) {\r
+          if ((~en->m.called_state & state) != 0) {\r
+            en->m.called_state |= state;\r
+            setup_called_state_call(NODE_BODY(node), state);\r
+          }\r
+        }\r
+        else {\r
+          NODE_STATUS_ADD(node, MARK1);\r
+          en->m.called_state |= state;\r
+          setup_called_state_call(NODE_BODY(node), state);\r
+          NODE_STATUS_REMOVE(node, MARK1);\r
+        }\r
+      }\r
+      else if (en->type == ENCLOSURE_IF_ELSE) {\r
+        if (IS_NOT_NULL(en->te.Then)) {\r
+          setup_called_state_call(en->te.Then, state);\r
+        }\r
+        if (IS_NOT_NULL(en->te.Else))\r
+          setup_called_state_call(en->te.Else, state);\r
+      }\r
+      else {\r
+        setup_called_state_call(NODE_BODY(node), state);\r
+      }\r
+    }\r
+    break;\r
+\r
+  case NODE_CALL:\r
+    setup_called_state_call(NODE_BODY(node), state);\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+}\r
+\r
+static void\r
+setup_called_state(Node* node, int state)\r
+{\r
+  switch (NODE_TYPE(node)) {\r
+  case NODE_ALT:\r
+    state |= IN_ALT;\r
+    /* fall */\r
+  case NODE_LIST:\r
+    do {\r
+      setup_called_state(NODE_CAR(node), state);\r
+    } while (IS_NOT_NULL(node = NODE_CDR(node)));\r
+    break;\r
+\r
+#ifdef USE_CALL\r
+  case NODE_CALL:\r
+    setup_called_state_call(node, state);\r
+    break;\r
+#endif\r
+\r
+  case NODE_ENCLOSURE:\r
+    {\r
+      EnclosureNode* en = ENCLOSURE_(node);\r
+\r
+      switch (en->type) {\r
+      case ENCLOSURE_MEMORY:\r
+        if (en->m.entry_count > 1)\r
+          state |= IN_MULTI_ENTRY;\r
+\r
+        en->m.called_state |= state;\r
+        /* fall */\r
+      case ENCLOSURE_OPTION:\r
+      case ENCLOSURE_STOP_BACKTRACK:\r
+        setup_called_state(NODE_BODY(node), state);\r
+        break;\r
+      case ENCLOSURE_IF_ELSE:\r
+        setup_called_state(NODE_BODY(node), state);\r
+        if (IS_NOT_NULL(en->te.Then))\r
+          setup_called_state(en->te.Then, state);\r
+        if (IS_NOT_NULL(en->te.Else))\r
+          setup_called_state(en->te.Else, state);\r
+        break;\r
+      }\r
+    }\r
+    break;\r
+\r
+  case NODE_QUANT:\r
+    {\r
+      QuantNode* qn = QUANT_(node);\r
+\r
+      if (IS_REPEAT_INFINITE(qn->upper) || qn->upper >= 2)\r
+        state |= IN_REAL_REPEAT;\r
+      if (qn->lower != qn->upper)\r
+        state |= IN_VAR_REPEAT;\r
+\r
+      setup_called_state(NODE_QUANT_BODY(qn), state);\r
+    }\r
+    break;\r
+\r
+  case NODE_ANCHOR:\r
+    {\r
+      AnchorNode* an = ANCHOR_(node);\r
+\r
+      switch (an->type) {\r
+      case ANCHOR_PREC_READ_NOT:\r
+      case ANCHOR_LOOK_BEHIND_NOT:\r
+        state |= IN_NOT;\r
+        /* fall */\r
+      case ANCHOR_PREC_READ:\r
+      case ANCHOR_LOOK_BEHIND:\r
+        setup_called_state(NODE_ANCHOR_BODY(an), state);\r
+        break;\r
+      default:\r
+        break;\r
       }\r
     }\r
+    break;\r
 \r
-    if (IS_NULL(root)) {\r
-      prev_node = srem;\r
-    }\r
-    else {\r
-      if (IS_NULL(onig_node_list_add(root, srem))) {\r
-       onig_node_free(srem);\r
-       goto mem_err;\r
-      }\r
-    }\r
+  case NODE_BACKREF:\r
+  case NODE_STRING:\r
+  case NODE_CTYPE:\r
+  case NODE_CCLASS:\r
+  case NODE_GIMMICK:\r
+  default:\r
+    break;\r
   }\r
+}\r
 \r
-  /* ending */\r
-  top_root = (IS_NOT_NULL(top_root) ? top_root : prev_node);\r
-  swap_node(node, top_root);\r
-  onig_node_free(top_root);\r
-  return 0;\r
+#endif  /* USE_CALL */\r
 \r
- mem_err:\r
-  r = ONIGERR_MEMORY;\r
 \r
- err:\r
-  onig_node_free(top_root);\r
-  return r;\r
-}\r
+static int setup_tree(Node* node, regex_t* reg, int state, ScanEnv* env);\r
+\r
+#ifdef __GNUC__\r
+__inline\r
+#endif\r
+static int\r
+setup_anchor(Node* node, regex_t* reg, int state, ScanEnv* env)\r
+{\r
+/* allowed node types in look-behind */\r
+#define ALLOWED_TYPE_IN_LB \\r
+  ( NODE_BIT_LIST | NODE_BIT_ALT | NODE_BIT_STRING | NODE_BIT_CCLASS \\r
+  | NODE_BIT_CTYPE | NODE_BIT_ANCHOR | NODE_BIT_ENCLOSURE | NODE_BIT_QUANT \\r
+  | NODE_BIT_CALL | NODE_BIT_GIMMICK)\r
 \r
+#define ALLOWED_ENCLOSURE_IN_LB       ( 1<<ENCLOSURE_MEMORY | 1<<ENCLOSURE_OPTION )\r
+#define ALLOWED_ENCLOSURE_IN_LB_NOT   (1<<ENCLOSURE_OPTION)\r
 \r
-#ifdef USE_COMBINATION_EXPLOSION_CHECK\r
+#define ALLOWED_ANCHOR_IN_LB \\r
+  ( ANCHOR_LOOK_BEHIND | ANCHOR_BEGIN_LINE | ANCHOR_END_LINE | ANCHOR_BEGIN_BUF \\r
+  | ANCHOR_BEGIN_POSITION | ANCHOR_WORD_BOUNDARY | ANCHOR_NO_WORD_BOUNDARY \\r
+  | ANCHOR_WORD_BEGIN | ANCHOR_WORD_END \\r
+  | ANCHOR_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY \\r
+  | ANCHOR_NO_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY )\r
 \r
-#define CEC_THRES_NUM_BIG_REPEAT         512\r
-#define CEC_INFINITE_NUM          0x7fffffff\r
+#define ALLOWED_ANCHOR_IN_LB_NOT \\r
+  ( ANCHOR_LOOK_BEHIND | ANCHOR_LOOK_BEHIND_NOT | ANCHOR_BEGIN_LINE \\r
+  | ANCHOR_END_LINE | ANCHOR_BEGIN_BUF | ANCHOR_BEGIN_POSITION | ANCHOR_WORD_BOUNDARY \\r
+  | ANCHOR_NO_WORD_BOUNDARY | ANCHOR_WORD_BEGIN | ANCHOR_WORD_END \\r
+  | ANCHOR_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY \\r
+  | ANCHOR_NO_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY )\r
 \r
-#define CEC_IN_INFINITE_REPEAT    (1<<0)\r
-#define CEC_IN_FINITE_REPEAT      (1<<1)\r
-#define CEC_CONT_BIG_REPEAT       (1<<2)\r
+  int r;\r
+  AnchorNode* an = ANCHOR_(node);\r
 \r
-static int\r
-setup_comb_exp_check(Node* node, int state, ScanEnv* env)\r
-{\r
-  int type;\r
-  int r = state;\r
+  switch (an->type) {\r
+  case ANCHOR_PREC_READ:\r
+    r = setup_tree(NODE_ANCHOR_BODY(an), reg, state, env);\r
+    break;\r
+  case ANCHOR_PREC_READ_NOT:\r
+    r = setup_tree(NODE_ANCHOR_BODY(an), reg, (state | IN_NOT), env);\r
+    break;\r
 \r
-  type = NTYPE(node);\r
-  switch (type) {\r
-  case NT_LIST:\r
+  case ANCHOR_LOOK_BEHIND:\r
     {\r
-      Node* prev = NULL_NODE;\r
-      do {\r
-       r = setup_comb_exp_check(NCAR(node), r, env);\r
-       prev = NCAR(node);\r
-      } while (r >= 0 && IS_NOT_NULL(node = NCDR(node)));\r
+      r = check_type_tree(NODE_ANCHOR_BODY(an), ALLOWED_TYPE_IN_LB,\r
+                          ALLOWED_ENCLOSURE_IN_LB, ALLOWED_ANCHOR_IN_LB);\r
+      if (r < 0) return r;\r
+      if (r > 0) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;\r
+      r = setup_tree(NODE_ANCHOR_BODY(an), reg, state, env);\r
+      if (r != 0) return r;\r
+      r = setup_look_behind(node, reg, env);\r
     }\r
     break;\r
 \r
-  case NT_ALT:\r
+  case ANCHOR_LOOK_BEHIND_NOT:\r
     {\r
-      int ret;\r
-      do {\r
-       ret = setup_comb_exp_check(NCAR(node), state, env);\r
-       r |= ret;\r
-      } while (ret >= 0 && IS_NOT_NULL(node = NCDR(node)));\r
+      r = check_type_tree(NODE_ANCHOR_BODY(an), ALLOWED_TYPE_IN_LB,\r
+                          ALLOWED_ENCLOSURE_IN_LB_NOT, ALLOWED_ANCHOR_IN_LB_NOT);\r
+      if (r < 0) return r;\r
+      if (r > 0) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;\r
+      r = setup_tree(NODE_ANCHOR_BODY(an), reg, (state | IN_NOT), env);\r
+      if (r != 0) return r;\r
+      r = setup_look_behind(node, reg, env);\r
     }\r
     break;\r
 \r
-  case NT_QTFR:\r
-    {\r
-      int child_state = state;\r
-      int add_state = 0;\r
-      QtfrNode* qn = NQTFR(node);\r
-      Node* target = qn->target;\r
-      int var_num;\r
-\r
-      if (! IS_REPEAT_INFINITE(qn->upper)) {\r
-       if (qn->upper > 1) {\r
-         /* {0,1}, {1,1} are allowed */\r
-         child_state |= CEC_IN_FINITE_REPEAT;\r
-\r
-         /* check (a*){n,m}, (a+){n,m} => (a*){n,n}, (a+){n,n} */\r
-         if (env->backrefed_mem == 0) {\r
-           if (NTYPE(qn->target) == NT_ENCLOSE) {\r
-             EncloseNode* en = NENCLOSE(qn->target);\r
-             if (en->type == ENCLOSE_MEMORY) {\r
-               if (NTYPE(en->target) == NT_QTFR) {\r
-                 QtfrNode* q = NQTFR(en->target);\r
-                 if (IS_REPEAT_INFINITE(q->upper)\r
-                     && q->greedy == qn->greedy) {\r
-                   qn->upper = (qn->lower == 0 ? 1 : qn->lower);\r
-                   if (qn->upper == 1)\r
-                     child_state = state;\r
-                 }\r
-               }\r
-             }\r
-           }\r
-         }\r
-       }\r
-      }\r
+  default:\r
+    r = 0;\r
+    break;\r
+  }\r
 \r
-      if (state & CEC_IN_FINITE_REPEAT) {\r
-       qn->comb_exp_check_num = -1;\r
-      }\r
-      else {\r
-       if (IS_REPEAT_INFINITE(qn->upper)) {\r
-         var_num = CEC_INFINITE_NUM;\r
-         child_state |= CEC_IN_INFINITE_REPEAT;\r
-       }\r
-       else {\r
-         var_num = qn->upper - qn->lower;\r
-       }\r
-\r
-       if (var_num >= CEC_THRES_NUM_BIG_REPEAT)\r
-         add_state |= CEC_CONT_BIG_REPEAT;\r
-\r
-       if (((state & CEC_IN_INFINITE_REPEAT) != 0 && var_num != 0) ||\r
-           ((state & CEC_CONT_BIG_REPEAT) != 0 &&\r
-            var_num >= CEC_THRES_NUM_BIG_REPEAT)) {\r
-         if (qn->comb_exp_check_num == 0) {\r
-           env->num_comb_exp_check++;\r
-           qn->comb_exp_check_num = env->num_comb_exp_check;\r
-           if (env->curr_max_regnum > env->comb_exp_max_regnum)\r
-             env->comb_exp_max_regnum = env->curr_max_regnum;\r
-         }\r
-       }\r
-      }\r
+  return r;\r
+}\r
 \r
-      r = setup_comb_exp_check(target, child_state, env);\r
-      r |= add_state;\r
+#ifdef __GNUC__\r
+__inline\r
+#endif\r
+static int\r
+setup_quant(Node* node, regex_t* reg, int state, ScanEnv* env)\r
+{\r
+  int r;\r
+  OnigLen d;\r
+  QuantNode* qn = QUANT_(node);\r
+  Node* body = NODE_BODY(node);\r
+\r
+  if ((state & IN_REAL_REPEAT) != 0) {\r
+    NODE_STATUS_ADD(node, IN_REAL_REPEAT);\r
+  }\r
+  if ((state & IN_MULTI_ENTRY) != 0) {\r
+    NODE_STATUS_ADD(node, IN_MULTI_ENTRY);\r
+  }\r
+\r
+  if (IS_REPEAT_INFINITE(qn->upper) || qn->upper >= 1) {\r
+    d = tree_min_len(body, env);\r
+    if (d == 0) {\r
+#ifdef USE_INSISTENT_CHECK_CAPTURES_IN_EMPTY_REPEAT\r
+      qn->body_empty_info = quantifiers_memory_node_info(body);\r
+      if (qn->body_empty_info == QUANT_BODY_IS_EMPTY_REC) {\r
+        if (NODE_TYPE(body) == NODE_ENCLOSURE &&\r
+            ENCLOSURE_(body)->type == ENCLOSURE_MEMORY) {\r
+          MEM_STATUS_ON(env->bt_mem_end, ENCLOSURE_(body)->m.regnum);\r
+        }\r
+      }\r
+#else\r
+      qn->body_empty_info = QUANT_BODY_IS_EMPTY;\r
+#endif\r
     }\r
-    break;\r
-\r
-  case NT_ENCLOSE:\r
-    {\r
-      EncloseNode* en = NENCLOSE(node);\r
+  }\r
 \r
-      switch (en->type) {\r
-      case ENCLOSE_MEMORY:\r
-       {\r
-         if (env->curr_max_regnum < en->regnum)\r
-           env->curr_max_regnum = en->regnum;\r
+  if (IS_REPEAT_INFINITE(qn->upper) || qn->upper >= 2)\r
+    state |= IN_REAL_REPEAT;\r
+  if (qn->lower != qn->upper)\r
+    state |= IN_VAR_REPEAT;\r
 \r
-         r = setup_comb_exp_check(en->target, state, env);\r
-       }\r
-       break;\r
+  r = setup_tree(body, reg, state, env);\r
+  if (r != 0) return r;\r
 \r
-      default:\r
-       r = setup_comb_exp_check(en->target, state, env);\r
-       break;\r
+  /* expand string */\r
+#define EXPAND_STRING_MAX_LENGTH  100\r
+  if (NODE_TYPE(body) == NODE_STRING) {\r
+    if (!IS_REPEAT_INFINITE(qn->lower) && qn->lower == qn->upper &&\r
+        qn->lower > 1 && qn->lower <= EXPAND_STRING_MAX_LENGTH) {\r
+      int len = NODE_STRING_LEN(body);\r
+      StrNode* sn = STR_(body);\r
+\r
+      if (len * qn->lower <= EXPAND_STRING_MAX_LENGTH) {\r
+        int i, n = qn->lower;\r
+        onig_node_conv_to_str_node(node, STR_(body)->flag);\r
+        for (i = 0; i < n; i++) {\r
+          r = onig_node_str_cat(node, sn->s, sn->end);\r
+          if (r != 0) return r;\r
+        }\r
+        onig_node_free(body);\r
+        return r;\r
       }\r
     }\r
-    break;\r
-\r
-#ifdef USE_SUBEXP_CALL\r
-  case NT_CALL:\r
-    if (IS_CALL_RECURSION(NCALL(node)))\r
-      env->has_recursion = 1;\r
-    else\r
-      r = setup_comb_exp_check(NCALL(node)->target, state, env);\r
-    break;\r
-#endif\r
+  }\r
 \r
-  default:\r
-    break;\r
+#ifdef USE_OP_PUSH_OR_JUMP_EXACT\r
+  if (qn->greedy && (qn->body_empty_info != QUANT_BODY_IS_NOT_EMPTY)) {\r
+    if (NODE_TYPE(body) == NODE_QUANT) {\r
+      QuantNode* tqn = QUANT_(body);\r
+      if (IS_NOT_NULL(tqn->head_exact)) {\r
+        qn->head_exact  = tqn->head_exact;\r
+        tqn->head_exact = NULL;\r
+      }\r
+    }\r
+    else {\r
+      qn->head_exact = get_head_value_node(NODE_BODY(node), 1, reg);\r
+    }\r
   }\r
+#endif\r
 \r
   return r;\r
 }\r
-#endif\r
-\r
-#define IN_ALT        (1<<0)\r
-#define IN_NOT        (1<<1)\r
-#define IN_REPEAT     (1<<2)\r
-#define IN_VAR_REPEAT (1<<3)\r
 \r
 /* setup_tree does the following work.\r
- 1. check empty loop. (set qn->target_empty_info)\r
+ 1. check empty loop. (set qn->body_empty_info)\r
  2. expand ignore-case in char class.\r
  3. set memory status bit flags. (reg->mem_stats)\r
  4. set qn->head_exact for [push, exact] -> [push_or_jump_exact1, exact].\r
@@ -3675,242 +4418,122 @@ setup_comb_exp_check(Node* node, int state, ScanEnv* env)
 static int\r
 setup_tree(Node* node, regex_t* reg, int state, ScanEnv* env)\r
 {\r
-  int type;\r
   int r = 0;\r
 \r
-  type = NTYPE(node);\r
-  switch (type) {\r
-  case NT_LIST:\r
+  switch (NODE_TYPE(node)) {\r
+  case NODE_LIST:\r
     {\r
       Node* prev = NULL_NODE;\r
       do {\r
-       r = setup_tree(NCAR(node), reg, state, env);\r
-       if (IS_NOT_NULL(prev) && r == 0) {\r
-         r = next_setup(prev, NCAR(node), reg);\r
-       }\r
-       prev = NCAR(node);\r
-      } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));\r
+        r = setup_tree(NODE_CAR(node), reg, state, env);\r
+        if (IS_NOT_NULL(prev) && r == 0) {\r
+          r = next_setup(prev, NODE_CAR(node), reg);\r
+        }\r
+        prev = NODE_CAR(node);\r
+      } while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));\r
     }\r
     break;\r
 \r
-  case NT_ALT:\r
+  case NODE_ALT:\r
     do {\r
-      r = setup_tree(NCAR(node), reg, (state | IN_ALT), env);\r
-    } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));\r
+      r = setup_tree(NODE_CAR(node), reg, (state | IN_ALT), env);\r
+    } while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node)));\r
     break;\r
 \r
-  case NT_CCLASS:\r
-    break;\r
-\r
-  case NT_STR:\r
-    if (IS_IGNORECASE(reg->options) && !NSTRING_IS_RAW(node)) {\r
+  case NODE_STRING:\r
+    if (IS_IGNORECASE(reg->options) && !NODE_STRING_IS_RAW(node)) {\r
       r = expand_case_fold_string(node, reg);\r
     }\r
     break;\r
 \r
-  case NT_CTYPE:\r
-  case NT_CANY:\r
-    break;\r
-\r
-#ifdef USE_SUBEXP_CALL\r
-  case NT_CALL:\r
-    break;\r
-#endif\r
-\r
-  case NT_BREF:\r
+  case NODE_BACKREF:\r
     {\r
       int i;\r
       int* p;\r
-      Node** nodes = SCANENV_MEM_NODES(env);\r
-      BRefNode* br = NBREF(node);\r
+      BackRefNode* br = BACKREF_(node);\r
       p = BACKREFS_P(br);\r
       for (i = 0; i < br->back_num; i++) {\r
-       if (p[i] > env->num_mem)  return ONIGERR_INVALID_BACKREF;\r
-       BIT_STATUS_ON_AT(env->backrefed_mem, p[i]);\r
-       BIT_STATUS_ON_AT(env->bt_mem_start, p[i]);\r
+        if (p[i] > env->num_mem)  return ONIGERR_INVALID_BACKREF;\r
+        MEM_STATUS_ON(env->backrefed_mem, p[i]);\r
+        MEM_STATUS_ON(env->bt_mem_start, p[i]);\r
 #ifdef USE_BACKREF_WITH_LEVEL\r
-       if (IS_BACKREF_NEST_LEVEL(br)) {\r
-         BIT_STATUS_ON_AT(env->bt_mem_end, p[i]);\r
-       }\r
+        if (NODE_IS_NEST_LEVEL(node)) {\r
+          MEM_STATUS_ON(env->bt_mem_end, p[i]);\r
+        }\r
 #endif\r
-       SET_ENCLOSE_STATUS(nodes[p[i]], NST_MEM_BACKREFED);\r
       }\r
     }\r
     break;\r
 \r
-  case NT_QTFR:\r
+  case NODE_ENCLOSURE:\r
     {\r
-      OnigDistance d;\r
-      QtfrNode* qn = NQTFR(node);\r
-      Node* target = qn->target;\r
-\r
-      if ((state & IN_REPEAT) != 0) {\r
-        qn->state |= NST_IN_REPEAT;\r
-      }\r
-\r
-      if (IS_REPEAT_INFINITE(qn->upper) || qn->upper >= 1) {\r
-       r = get_min_match_length(target, &d, env);\r
-       if (r) break;\r
-       if (d == 0) {\r
-         qn->target_empty_info = NQ_TARGET_IS_EMPTY;\r
-#ifdef USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT\r
-         r = quantifiers_memory_node_info(target);\r
-         if (r < 0) break;\r
-         if (r > 0) {\r
-           qn->target_empty_info = r;\r
-         }\r
-#endif\r
-#if 0\r
-         r = get_max_match_length(target, &d, env);\r
-         if (r == 0 && d == 0) {\r
-           /*  ()* ==> ()?, ()+ ==> ()  */\r
-           qn->upper = 1;\r
-           if (qn->lower > 1) qn->lower = 1;\r
-           if (NTYPE(target) == NT_STR) {\r
-             qn->upper = qn->lower = 0;  /* /(?:)+/ ==> // */\r
-           }\r
-         }\r
-#endif\r
-       }\r
-      }\r
-\r
-      state |= IN_REPEAT;\r
-      if (qn->lower != qn->upper)\r
-       state |= IN_VAR_REPEAT;\r
-      r = setup_tree(target, reg, state, env);\r
-      if (r) break;\r
+      EnclosureNode* en = ENCLOSURE_(node);\r
 \r
-      /* expand string */\r
-#define EXPAND_STRING_MAX_LENGTH  100\r
-      if (NTYPE(target) == NT_STR) {\r
-       if (!IS_REPEAT_INFINITE(qn->lower) && qn->lower == qn->upper &&\r
-           qn->lower > 1 && qn->lower <= EXPAND_STRING_MAX_LENGTH) {\r
-         int len = NSTRING_LEN(target);\r
-         StrNode* sn = NSTR(target);\r
-\r
-         if (len * qn->lower <= EXPAND_STRING_MAX_LENGTH) {\r
-           int i, n = qn->lower;\r
-           onig_node_conv_to_str_node(node, NSTR(target)->flag);\r
-           for (i = 0; i < n; i++) {\r
-             r = onig_node_str_cat(node, sn->s, sn->end);\r
-             if (r) break;\r
-           }\r
-           onig_node_free(target);\r
-           break; /* break case NT_QTFR: */\r
-         }\r
-       }\r
-      }\r
+      switch (en->type) {\r
+      case ENCLOSURE_OPTION:\r
+        {\r
+          OnigOptionType options = reg->options;\r
+          reg->options = ENCLOSURE_(node)->o.options;\r
+          r = setup_tree(NODE_BODY(node), reg, state, env);\r
+          reg->options = options;\r
+        }\r
+        break;\r
 \r
-#ifdef USE_OP_PUSH_OR_JUMP_EXACT\r
-      if (qn->greedy && (qn->target_empty_info != 0)) {\r
-       if (NTYPE(target) == NT_QTFR) {\r
-         QtfrNode* tqn = NQTFR(target);\r
-         if (IS_NOT_NULL(tqn->head_exact)) {\r
-           qn->head_exact  = tqn->head_exact;\r
-           tqn->head_exact = NULL;\r
-         }\r
-       }\r
-       else {\r
-         qn->head_exact = get_head_value_node(qn->target, 1, reg);\r
-       }\r
-      }\r
+      case ENCLOSURE_MEMORY:\r
+#ifdef USE_CALL\r
+        state |= en->m.called_state;\r
 #endif\r
-    }\r
-    break;\r
 \r
-  case NT_ENCLOSE:\r
-    {\r
-      EncloseNode* en = NENCLOSE(node);\r
+        if ((state & (IN_ALT | IN_NOT | IN_VAR_REPEAT | IN_MULTI_ENTRY)) != 0\r
+            || NODE_IS_RECURSION(node)) {\r
+          MEM_STATUS_ON(env->bt_mem_start, en->m.regnum);\r
+        }\r
+        r = setup_tree(NODE_BODY(node), reg, state, env);\r
+        break;\r
 \r
-      switch (en->type) {\r
-      case ENCLOSE_OPTION:\r
-       {\r
-         OnigOptionType options = reg->options;\r
-         reg->options = NENCLOSE(node)->option;\r
-         r = setup_tree(NENCLOSE(node)->target, reg, state, env);\r
-         reg->options = options;\r
-       }\r
-       break;\r
-\r
-      case ENCLOSE_MEMORY:\r
-       if ((state & (IN_ALT | IN_NOT | IN_VAR_REPEAT)) != 0) {\r
-         BIT_STATUS_ON_AT(env->bt_mem_start, en->regnum);\r
-         /* SET_ENCLOSE_STATUS(node, NST_MEM_IN_ALT_NOT); */\r
-       }\r
-        r = setup_tree(en->target, reg, state, env);\r
+      case ENCLOSURE_STOP_BACKTRACK:\r
+        {\r
+          Node* target = NODE_BODY(node);\r
+          r = setup_tree(target, reg, state, env);\r
+          if (NODE_TYPE(target) == NODE_QUANT) {\r
+            QuantNode* tqn = QUANT_(target);\r
+            if (IS_REPEAT_INFINITE(tqn->upper) && tqn->lower <= 1 &&\r
+                tqn->greedy != 0) {  /* (?>a*), a*+ etc... */\r
+              if (NODE_IS_SIMPLE_TYPE(NODE_BODY(target)))\r
+                NODE_STATUS_ADD(node, STOP_BT_SIMPLE_REPEAT);\r
+            }\r
+          }\r
+        }\r
         break;\r
 \r
-      case ENCLOSE_STOP_BACKTRACK:\r
-       {\r
-         Node* target = en->target;\r
-         r = setup_tree(target, reg, state, env);\r
-         if (NTYPE(target) == NT_QTFR) {\r
-           QtfrNode* tqn = NQTFR(target);\r
-           if (IS_REPEAT_INFINITE(tqn->upper) && tqn->lower <= 1 &&\r
-               tqn->greedy != 0) {  /* (?>a*), a*+ etc... */\r
-             int qtype = NTYPE(tqn->target);\r
-             if (IS_NODE_TYPE_SIMPLE(qtype))\r
-               SET_ENCLOSE_STATUS(node, NST_STOP_BT_SIMPLE_REPEAT);\r
-           }\r
-         }\r
-       }\r
-       break;\r
+      case ENCLOSURE_IF_ELSE:\r
+        r = setup_tree(NODE_BODY(node), reg, (state | IN_ALT), env);\r
+        if (r != 0) return r;\r
+        if (IS_NOT_NULL(en->te.Then)) {\r
+          r = setup_tree(en->te.Then, reg, (state | IN_ALT), env);\r
+          if (r != 0) return r;\r
+        }\r
+        if (IS_NOT_NULL(en->te.Else))\r
+          r = setup_tree(en->te.Else, reg, (state | IN_ALT), env);\r
+        break;\r
       }\r
     }\r
     break;\r
 \r
-  case NT_ANCHOR:\r
-    {\r
-      AnchorNode* an = NANCHOR(node);\r
-\r
-      switch (an->type) {\r
-      case ANCHOR_PREC_READ:\r
-       r = setup_tree(an->target, reg, state, env);\r
-       break;\r
-      case ANCHOR_PREC_READ_NOT:\r
-       r = setup_tree(an->target, reg, (state | IN_NOT), env);\r
-       break;\r
-\r
-/* allowed node types in look-behind */\r
-#define ALLOWED_TYPE_IN_LB  \\r
-  ( BIT_NT_LIST | BIT_NT_ALT | BIT_NT_STR | BIT_NT_CCLASS | BIT_NT_CTYPE | \\r
-    BIT_NT_CANY | BIT_NT_ANCHOR | BIT_NT_ENCLOSE | BIT_NT_QTFR | BIT_NT_CALL )\r
-\r
-#define ALLOWED_ENCLOSE_IN_LB       ( ENCLOSE_MEMORY )\r
-#define ALLOWED_ENCLOSE_IN_LB_NOT   0\r
-\r
-#define ALLOWED_ANCHOR_IN_LB \\r
-( ANCHOR_LOOK_BEHIND | ANCHOR_BEGIN_LINE | ANCHOR_END_LINE | ANCHOR_BEGIN_BUF | ANCHOR_BEGIN_POSITION )\r
-#define ALLOWED_ANCHOR_IN_LB_NOT \\r
-( ANCHOR_LOOK_BEHIND | ANCHOR_LOOK_BEHIND_NOT | ANCHOR_BEGIN_LINE | ANCHOR_END_LINE | ANCHOR_BEGIN_BUF | ANCHOR_BEGIN_POSITION )\r
-\r
-      case ANCHOR_LOOK_BEHIND:\r
-       {\r
-         r = check_type_tree(an->target, ALLOWED_TYPE_IN_LB,\r
-                             ALLOWED_ENCLOSE_IN_LB, ALLOWED_ANCHOR_IN_LB);\r
-         if (r < 0) return r;\r
-         if (r > 0) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;\r
-         r = setup_look_behind(node, reg, env);\r
-         if (r != 0) return r;\r
-         r = setup_tree(an->target, reg, state, env);\r
-       }\r
-       break;\r
+  case NODE_QUANT:\r
+    r = setup_quant(node, reg, state, env);\r
+    break;\r
 \r
-      case ANCHOR_LOOK_BEHIND_NOT:\r
-       {\r
-         r = check_type_tree(an->target, ALLOWED_TYPE_IN_LB,\r
-                     ALLOWED_ENCLOSE_IN_LB_NOT, ALLOWED_ANCHOR_IN_LB_NOT);\r
-         if (r < 0) return r;\r
-         if (r > 0) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;\r
-         r = setup_look_behind(node, reg, env);\r
-         if (r != 0) return r;\r
-         r = setup_tree(an->target, reg, (state | IN_NOT), env);\r
-       }\r
-       break;\r
-      }\r
-    }\r
+  case NODE_ANCHOR:\r
+    r = setup_anchor(node, reg, state, env);\r
     break;\r
 \r
+#ifdef USE_CALL\r
+  case NODE_CALL:\r
+#endif\r
+  case NODE_CTYPE:\r
+  case NODE_CCLASS:\r
+  case NODE_GIMMICK:\r
   default:\r
     break;\r
   }\r
@@ -3918,19 +4541,19 @@ setup_tree(Node* node, regex_t* reg, int state, ScanEnv* env)
   return r;\r
 }\r
 \r
-/* set skip map for Boyer-Moor search */\r
+/* set skip map for Boyer-Moore search */\r
 static int\r
 set_bm_skip(UChar* s, UChar* end, OnigEncoding enc ARG_UNUSED,\r
-           UChar skip[], int** int_skip)\r
+            UChar skip[], int** int_skip)\r
 {\r
   int i, len;\r
 \r
-  len = (int)(end - s);\r
+  len = (int )(end - s);\r
   if (len < ONIG_CHAR_TABLE_SIZE) {\r
-    for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) skip[i] = (UChar)len;\r
+    for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) skip[i] = len;\r
 \r
     for (i = 0; i < len - 1; i++)\r
-      skip[s[i]] = (UChar)(len - 1 - i);\r
+      skip[s[i]] = len - 1 - i;\r
   }\r
   else {\r
     if (IS_NULL(*int_skip)) {\r
@@ -3948,12 +4571,12 @@ set_bm_skip(UChar* s, UChar* end, OnigEncoding enc ARG_UNUSED,
 #define OPT_EXACT_MAXLEN   24\r
 \r
 typedef struct {\r
-  OnigDistance min;  /* min byte length */\r
-  OnigDistance max;  /* max byte length */\r
-} MinMaxLen;\r
+  OnigLen min;  /* min byte length */\r
+  OnigLen max;  /* max byte length */\r
+} MinMax;\r
 \r
 typedef struct {\r
-  MinMaxLen        mmd;\r
+  MinMax           mmd;\r
   OnigEncoding     enc;\r
   OnigOptionType   options;\r
   OnigCaseFoldType case_fold_flag;\r
@@ -3961,44 +4584,40 @@ typedef struct {
 } OptEnv;\r
 \r
 typedef struct {\r
-  int left_anchor;\r
-  int right_anchor;\r
-} OptAncInfo;\r
+  int left;\r
+  int right;\r
+} OptAnc;\r
 \r
 typedef struct {\r
-  MinMaxLen  mmd; /* info position */\r
-  OptAncInfo anc;\r
-\r
-  int   reach_end;\r
-  int   ignore_case;\r
-  int   len;\r
-  UChar s[OPT_EXACT_MAXLEN];\r
-} OptExactInfo;\r
+  MinMax     mmd;   /* position */\r
+  OptAnc     anc;\r
+  int        reach_end;\r
+  int        ignore_case;\r
+  int        len;\r
+  UChar      s[OPT_EXACT_MAXLEN];\r
+} OptExact;\r
 \r
 typedef struct {\r
-  MinMaxLen mmd; /* info position */\r
-  OptAncInfo anc;\r
-\r
-  int   value;      /* weighted value */\r
-  UChar map[ONIG_CHAR_TABLE_SIZE];\r
-} OptMapInfo;\r
+  MinMax    mmd;    /* position */\r
+  OptAnc    anc;\r
+  int       value;  /* weighted value */\r
+  UChar     map[ONIG_CHAR_TABLE_SIZE];\r
+} OptMap;\r
 \r
 typedef struct {\r
-  MinMaxLen    len;\r
-\r
-  OptAncInfo   anc;\r
-  OptExactInfo exb;    /* boundary */\r
-  OptExactInfo exm;    /* middle */\r
-  OptExactInfo expr;   /* prec read (?=...) */\r
-\r
-  OptMapInfo   map;   /* boundary */\r
-} NodeOptInfo;\r
+  MinMax    len;\r
+  OptAnc    anc;\r
+  OptExact  exb;     /* boundary */\r
+  OptExact  exm;     /* middle */\r
+  OptExact  expr;    /* prec read (?=...) */\r
+  OptMap    map;     /* boundary */\r
+} NodeOpt;\r
 \r
 \r
 static int\r
 map_position_value(OnigEncoding enc, int i)\r
 {\r
-  static const short int ByteValTable[] = {\r
+  static const short int Vals[] = {\r
      5,  1,  1,  1,  1,  1,  1,  1,  1, 10, 10,  1,  1, 10,  1,  1,\r
      1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,\r
     12,  4,  7,  4,  4,  4,  4,  4,  4,  5,  5,  5,  5,  5,  5,  5,\r
@@ -4009,18 +4628,18 @@ map_position_value(OnigEncoding enc, int i)
      6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  5,  5,  5,  5,  1\r
   };\r
 \r
-  if (i < (int )(sizeof(ByteValTable)/sizeof(ByteValTable[0]))) {\r
+  if (i < (int )(sizeof(Vals)/sizeof(Vals[0]))) {\r
     if (i == 0 && ONIGENC_MBC_MINLEN(enc) > 1)\r
       return 20;\r
     else\r
-      return (int )ByteValTable[i];\r
+      return (int )Vals[i];\r
   }\r
   else\r
     return 4;   /* Take it easy. */\r
 }\r
 \r
 static int\r
-distance_value(MinMaxLen* mm)\r
+distance_value(MinMax* mm)\r
 {\r
   /* 1000 / (min-max-dist + 1) */\r
   static const short int dist_vals[] = {\r
@@ -4036,12 +4655,12 @@ distance_value(MinMaxLen* mm)
       11,   11,   11,   11,   11,   10,   10,   10,   10,   10\r
   };\r
 \r
-  int d;\r
+  OnigLen d;\r
 \r
-  if (mm->max == ONIG_INFINITE_DISTANCE) return 0;\r
+  if (mm->max == INFINITE_LEN) return 0;\r
 \r
   d = mm->max - mm->min;\r
-  if (d < (int )(sizeof(dist_vals)/sizeof(dist_vals[0])))\r
+  if (d < (OnigLen )(sizeof(dist_vals)/sizeof(dist_vals[0])))\r
     /* return dist_vals[d] * 16 / (mm->min + 12); */\r
     return (int )dist_vals[d];\r
   else\r
@@ -4049,7 +4668,7 @@ distance_value(MinMaxLen* mm)
 }\r
 \r
 static int\r
-comp_distance_value(MinMaxLen* d1, MinMaxLen* d2, int v1, int v2)\r
+comp_distance_value(MinMax* d1, MinMax* d2, int v1, int v2)\r
 {\r
   if (v2 <= 0) return -1;\r
   if (v1 <= 0) return  1;\r
@@ -4066,50 +4685,40 @@ comp_distance_value(MinMaxLen* d1, MinMaxLen* d2, int v1, int v2)
 }\r
 \r
 static int\r
-is_equal_mml(MinMaxLen* a, MinMaxLen* b)\r
+is_equal_mml(MinMax* a, MinMax* b)\r
 {\r
   return (a->min == b->min && a->max == b->max) ? 1 : 0;\r
 }\r
 \r
-\r
 static void\r
-set_mml(MinMaxLen* mml, OnigDistance min, OnigDistance max)\r
+set_mml(MinMax* l, OnigLen min, OnigLen max)\r
 {\r
-  mml->min = min;\r
-  mml->max = max;\r
+  l->min = min;\r
+  l->max = max;\r
 }\r
 \r
 static void\r
-clear_mml(MinMaxLen* mml)\r
+clear_mml(MinMaxl)\r
 {\r
-  mml->min = mml->max = 0;\r
+  l->min = l->max = 0;\r
 }\r
 \r
 static void\r
-copy_mml(MinMaxLen* to, MinMaxLen* from)\r
+copy_mml(MinMax* to, MinMax* from)\r
 {\r
   to->min = from->min;\r
   to->max = from->max;\r
 }\r
 \r
 static void\r
-add_mml(MinMaxLen* to, MinMaxLen* from)\r
+add_mml(MinMax* to, MinMax* from)\r
 {\r
   to->min = distance_add(to->min, from->min);\r
   to->max = distance_add(to->max, from->max);\r
 }\r
 \r
-#if 0\r
-static void\r
-add_len_mml(MinMaxLen* to, OnigDistance len)\r
-{\r
-  to->min = distance_add(to->min, len);\r
-  to->max = distance_add(to->max, len);\r
-}\r
-#endif\r
-\r
 static void\r
-alt_merge_mml(MinMaxLen* to, MinMaxLen* from)\r
+alt_merge_mml(MinMax* to, MinMax* from)\r
 {\r
   if (to->min > from->min) to->min = from->min;\r
   if (to->max < from->max) to->max = from->max;\r
@@ -4118,124 +4727,130 @@ alt_merge_mml(MinMaxLen* to, MinMaxLen* from)
 static void\r
 copy_opt_env(OptEnv* to, OptEnv* from)\r
 {\r
-  CopyMem (to, from, sizeof (OptEnv));\r
+  *to = *from;\r
 }\r
 \r
 static void\r
-clear_opt_anc_info(OptAncInfo* anc)\r
+clear_opt_anc_info(OptAnc* a)\r
 {\r
-  anc->left_anchor  = 0;\r
-  anc->right_anchor = 0;\r
+  a->left  = 0;\r
+  a->right = 0;\r
 }\r
 \r
 static void\r
-copy_opt_anc_info(OptAncInfo* to, OptAncInfo* from)\r
+copy_opt_anc_info(OptAnc* to, OptAnc* from)\r
 {\r
-  CopyMem (to, from, sizeof (OptAncInfo));\r
+  *to = *from;\r
 }\r
 \r
 static void\r
-concat_opt_anc_info(OptAncInfo* to, OptAncInfo* left, OptAncInfo* right,\r
-                   OnigDistance left_len, OnigDistance right_len)\r
+concat_opt_anc_info(OptAnc* to, OptAnc* left, OptAnc* right,\r
+                    OnigLen left_len, OnigLen right_len)\r
 {\r
   clear_opt_anc_info(to);\r
 \r
-  to->left_anchor = left->left_anchor;\r
+  to->left = left->left;\r
   if (left_len == 0) {\r
-    to->left_anchor |= right->left_anchor;\r
+    to->left |= right->left;\r
   }\r
 \r
-  to->right_anchor = right->right_anchor;\r
+  to->right = right->right;\r
   if (right_len == 0) {\r
-    to->right_anchor |= left->right_anchor;\r
+    to->right |= left->right;\r
+  }\r
+  else {\r
+    to->right |= (left->right & ANCHOR_PREC_READ_NOT);\r
   }\r
 }\r
 \r
 static int\r
-is_left_anchor(int anc)\r
+is_left(int a)\r
 {\r
-  if (anc == ANCHOR_END_BUF || anc == ANCHOR_SEMI_END_BUF ||\r
-      anc == ANCHOR_END_LINE || anc == ANCHOR_PREC_READ ||\r
-      anc == ANCHOR_PREC_READ_NOT)\r
+  if (a == ANCHOR_END_BUF  || a == ANCHOR_SEMI_END_BUF ||\r
+      a == ANCHOR_END_LINE || a == ANCHOR_PREC_READ || a == ANCHOR_PREC_READ_NOT)\r
     return 0;\r
 \r
   return 1;\r
 }\r
 \r
 static int\r
-is_set_opt_anc_info(OptAncInfo* to, int anc)\r
+is_set_opt_anc_info(OptAnc* to, int anc)\r
 {\r
-  if ((to->left_anchor & anc) != 0) return 1;\r
+  if ((to->left & anc) != 0) return 1;\r
 \r
-  return ((to->right_anchor & anc) != 0 ? 1 : 0);\r
+  return ((to->right & anc) != 0 ? 1 : 0);\r
 }\r
 \r
 static void\r
-add_opt_anc_info(OptAncInfo* to, int anc)\r
+add_opt_anc_info(OptAnc* to, int anc)\r
 {\r
-  if (is_left_anchor(anc))\r
-    to->left_anchor |= anc;\r
+  if (is_left(anc))\r
+    to->left |= anc;\r
   else\r
-    to->right_anchor |= anc;\r
+    to->right |= anc;\r
 }\r
 \r
 static void\r
-remove_opt_anc_info(OptAncInfo* to, int anc)\r
+remove_opt_anc_info(OptAnc* to, int anc)\r
 {\r
-  if (is_left_anchor(anc))\r
-    to->left_anchor &= ~anc;\r
+  if (is_left(anc))\r
+    to->left &= ~anc;\r
   else\r
-    to->right_anchor &= ~anc;\r
+    to->right &= ~anc;\r
 }\r
 \r
 static void\r
-alt_merge_opt_anc_info(OptAncInfo* to, OptAncInfo* add)\r
+alt_merge_opt_anc_info(OptAnc* to, OptAnc* add)\r
 {\r
-  to->left_anchor  &= add->left_anchor;\r
-  to->right_anchor &= add->right_anchor;\r
+  to->left  &= add->left;\r
+  to->right &= add->right;\r
 }\r
 \r
 static int\r
-is_full_opt_exact_info(OptExactInfo* ex)\r
+is_full_opt_exact(OptExact* e)\r
 {\r
-  return (ex->len >= OPT_EXACT_MAXLEN ? 1 : 0);\r
+  return (e->len >= OPT_EXACT_MAXLEN ? 1 : 0);\r
 }\r
 \r
 static void\r
-clear_opt_exact_info(OptExactInfo* ex)\r
+clear_opt_exact(OptExact* e)\r
 {\r
-  clear_mml(&ex->mmd);\r
-  clear_opt_anc_info(&ex->anc);\r
-  ex->reach_end   = 0;\r
-  ex->ignore_case = 0;\r
-  ex->len         = 0;\r
-  ex->s[0]        = '\0';\r
+  clear_mml(&e->mmd);\r
+  clear_opt_anc_info(&e->anc);\r
+  e->reach_end   = 0;\r
+  e->ignore_case = 0;\r
+  e->len         = 0;\r
+  e->s[0]        = '\0';\r
 }\r
 \r
 static void\r
-copy_opt_exact_info(OptExactInfo* to, OptExactInfo* from)\r
+copy_opt_exact(OptExact* to, OptExact* from)\r
 {\r
-  CopyMem (to, from, sizeof (OptExactInfo));\r
+  *to = *from;\r
 }\r
 \r
-static void\r
-concat_opt_exact_info(OptExactInfo* to, OptExactInfo* add, OnigEncoding enc)\r
+static int\r
+concat_opt_exact(OptExact* to, OptExact* add, OnigEncoding enc)\r
 {\r
-  int i, j, len;\r
+  int i, j, len, r;\r
   UChar *p, *end;\r
-  OptAncInfo tanc;\r
+  OptAnc tanc;\r
 \r
   if (! to->ignore_case && add->ignore_case) {\r
-    if (to->len >= add->len) return ;  /* avoid */\r
+    if (to->len >= add->len) return 0;  /* avoid */\r
 \r
     to->ignore_case = 1;\r
   }\r
 \r
+  r = 0;\r
   p = add->s;\r
   end = p + add->len;\r
   for (i = to->len; p < end; ) {\r
     len = enclen(enc, p);\r
-    if (i + len > OPT_EXACT_MAXLEN) break;\r
+    if (i + len > OPT_EXACT_MAXLEN) {\r
+      r = 1; /* 1:full */\r
+      break;\r
+    }\r
     for (j = 0; j < len && p < end; j++)\r
       to->s[i++] = *p++;\r
   }\r
@@ -4244,13 +4859,14 @@ concat_opt_exact_info(OptExactInfo* to, OptExactInfo* add, OnigEncoding enc)
   to->reach_end = (p == end ? add->reach_end : 0);\r
 \r
   concat_opt_anc_info(&tanc, &to->anc, &add->anc, 1, 1);\r
-  if (! to->reach_end) tanc.right_anchor = 0;\r
+  if (! to->reach_end) tanc.right = 0;\r
   copy_opt_anc_info(&to->anc, &tanc);\r
+\r
+  return r;\r
 }\r
 \r
 static void\r
-concat_opt_exact_info_str(OptExactInfo* to, UChar* s, UChar* end,\r
-                         int raw ARG_UNUSED, OnigEncoding enc)\r
+concat_opt_exact_str(OptExact* to, UChar* s, UChar* end, OnigEncoding enc)\r
 {\r
   int i, j, len;\r
   UChar *p;\r
@@ -4266,17 +4882,17 @@ concat_opt_exact_info_str(OptExactInfo* to, UChar* s, UChar* end,
 }\r
 \r
 static void\r
-alt_merge_opt_exact_info(OptExactInfo* to, OptExactInfo* add, OptEnv* env)\r
+alt_merge_opt_exact(OptExact* to, OptExact* add, OptEnv* env)\r
 {\r
   int i, j, len;\r
 \r
   if (add->len == 0 || to->len == 0) {\r
-    clear_opt_exact_info(to);\r
+    clear_opt_exact(to);\r
     return ;\r
   }\r
 \r
   if (! is_equal_mml(&to->mmd, &add->mmd)) {\r
-    clear_opt_exact_info(to);\r
+    clear_opt_exact(to);\r
     return ;\r
   }\r
 \r
@@ -4298,44 +4914,44 @@ alt_merge_opt_exact_info(OptExactInfo* to, OptExactInfo* add, OptEnv* env)
   to->ignore_case |= add->ignore_case;\r
 \r
   alt_merge_opt_anc_info(&to->anc, &add->anc);\r
-  if (! to->reach_end) to->anc.right_anchor = 0;\r
+  if (! to->reach_end) to->anc.right = 0;\r
 }\r
 \r
 static void\r
-select_opt_exact_info(OnigEncoding enc, OptExactInfo* now, OptExactInfo* alt)\r
+select_opt_exact(OnigEncoding enc, OptExact* now, OptExact* alt)\r
 {\r
-  int v1, v2;\r
+  int vn, va;\r
 \r
-  v1 = now->len;\r
-  v2 = alt->len;\r
+  vn = now->len;\r
+  va = alt->len;\r
 \r
-  if (v2 == 0) {\r
+  if (va == 0) {\r
     return ;\r
   }\r
-  else if (v1 == 0) {\r
-    copy_opt_exact_info(now, alt);\r
+  else if (vn == 0) {\r
+    copy_opt_exact(now, alt);\r
     return ;\r
   }\r
-  else if (v1 <= 2 && v2 <= 2) {\r
+  else if (vn <= 2 && va <= 2) {\r
     /* ByteValTable[x] is big value --> low price */\r
-    v2 = map_position_value(enc, now->s[0]);\r
-    v1 = map_position_value(enc, alt->s[0]);\r
+    va = map_position_value(enc, now->s[0]);\r
+    vn = map_position_value(enc, alt->s[0]);\r
 \r
-    if (now->len > 1) v1 += 5;\r
-    if (alt->len > 1) v2 += 5;\r
+    if (now->len > 1) vn += 5;\r
+    if (alt->len > 1) va += 5;\r
   }\r
 \r
-  if (now->ignore_case == 0) v1 *= 2;\r
-  if (alt->ignore_case == 0) v2 *= 2;\r
+  if (now->ignore_case == 0) vn *= 2;\r
+  if (alt->ignore_case == 0) va *= 2;\r
 \r
-  if (comp_distance_value(&now->mmd, &alt->mmd, v1, v2) > 0)\r
-    copy_opt_exact_info(now, alt);\r
+  if (comp_distance_value(&now->mmd, &alt->mmd, vn, va) > 0)\r
+    copy_opt_exact(now, alt);\r
 }\r
 \r
 static void\r
-clear_opt_map_info(OptMapInfo* map)\r
+clear_opt_map(OptMap* map)\r
 {\r
-  static const OptMapInfo clean_info = {\r
+  static const OptMap clean_info = {\r
     {0, 0}, {0, 0}, 0,\r
     {\r
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
@@ -4357,87 +4973,87 @@ clear_opt_map_info(OptMapInfo* map)
     }\r
   };\r
 \r
-  xmemcpy(map, &clean_info, sizeof(OptMapInfo));\r
+  xmemcpy(map, &clean_info, sizeof(OptMap));\r
 }\r
 \r
 static void\r
-copy_opt_map_info(OptMapInfo* to, OptMapInfo* from)\r
+copy_opt_map(OptMap* to, OptMap* from)\r
 {\r
-  CopyMem (to, from, sizeof (OptMapInfo));\r
+  xmemcpy(to,from,sizeof(OptMap));\r
 }\r
 \r
 static void\r
-add_char_opt_map_info(OptMapInfo* map, UChar c, OnigEncoding enc)\r
+add_char_opt_map(OptMap* m, UChar c, OnigEncoding enc)\r
 {\r
-  if (map->map[c] == 0) {\r
-    map->map[c] = 1;\r
-    map->value += map_position_value(enc, c);\r
+  if (m->map[c] == 0) {\r
+    m->map[c] = 1;\r
+    m->value += map_position_value(enc, c);\r
   }\r
 }\r
 \r
 static int\r
-add_char_amb_opt_map_info(OptMapInfo* map, UChar* p, UChar* end,\r
-                          OnigEncoding enc, OnigCaseFoldType case_fold_flag)\r
+add_char_amb_opt_map(OptMap* map, UChar* p, UChar* end,\r
+                     OnigEncoding enc, OnigCaseFoldType fold_flag)\r
 {\r
   OnigCaseFoldCodeItem items[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM];\r
   UChar buf[ONIGENC_CODE_TO_MBC_MAXLEN];\r
   int i, n;\r
 \r
-  add_char_opt_map_info(map, p[0], enc);\r
+  add_char_opt_map(map, p[0], enc);\r
 \r
-  case_fold_flag = DISABLE_CASE_FOLD_MULTI_CHAR(case_fold_flag);\r
-  n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc, case_fold_flag, p, end, items);\r
+  fold_flag = DISABLE_CASE_FOLD_MULTI_CHAR(fold_flag);\r
+  n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc, fold_flag, p, end, items);\r
   if (n < 0) return n;\r
 \r
   for (i = 0; i < n; i++) {\r
     ONIGENC_CODE_TO_MBC(enc, items[i].code[0], buf);\r
-    add_char_opt_map_info(map, buf[0], enc);\r
+    add_char_opt_map(map, buf[0], enc);\r
   }\r
 \r
   return 0;\r
 }\r
 \r
 static void\r
-select_opt_map_info(OptMapInfo* now, OptMapInfo* alt)\r
+select_opt_map(OptMap* now, OptMap* alt)\r
 {\r
   static int z = 1<<15; /* 32768: something big value */\r
 \r
-  int v1, v2;\r
+  int vn, va;\r
 \r
   if (alt->value == 0) return ;\r
   if (now->value == 0) {\r
-    copy_opt_map_info(now, alt);\r
+    copy_opt_map(now, alt);\r
     return ;\r
   }\r
 \r
-  v1 = z / now->value;\r
-  v2 = z / alt->value;\r
-  if (comp_distance_value(&now->mmd, &alt->mmd, v1, v2) > 0)\r
-    copy_opt_map_info(now, alt);\r
+  vn = z / now->value;\r
+  va = z / alt->value;\r
+  if (comp_distance_value(&now->mmd, &alt->mmd, vn, va) > 0)\r
+    copy_opt_map(now, alt);\r
 }\r
 \r
 static int\r
-comp_opt_exact_or_map_info(OptExactInfo* e, OptMapInfo* m)\r
+comp_opt_exact_or_map(OptExact* e, OptMap* m)\r
 {\r
 #define COMP_EM_BASE  20\r
-  int ve, vm;\r
+  int ae, am;\r
 \r
   if (m->value <= 0) return -1;\r
 \r
-  ve = COMP_EM_BASE * e->len * (e->ignore_case ? 1 : 2);\r
-  vm = COMP_EM_BASE * 5 * 2 / m->value;\r
-  return comp_distance_value(&e->mmd, &m->mmd, ve, vm);\r
+  ae = COMP_EM_BASE * e->len * (e->ignore_case ? 1 : 2);\r
+  am = COMP_EM_BASE * 5 * 2 / m->value;\r
+  return comp_distance_value(&e->mmd, &m->mmd, ae, am);\r
 }\r
 \r
 static void\r
-alt_merge_opt_map_info(OnigEncoding enc, OptMapInfo* to, OptMapInfo* add)\r
+alt_merge_opt_map(OnigEncoding enc, OptMap* to, OptMap* add)\r
 {\r
   int i, val;\r
 \r
   /* if (! is_equal_mml(&to->mmd, &add->mmd)) return ; */\r
   if (to->value == 0) return ;\r
   if (add->value == 0 || to->mmd.max < add->mmd.min) {\r
-    clear_opt_map_info(to);\r
+    clear_opt_map(to);\r
     return ;\r
   }\r
 \r
@@ -4457,48 +5073,47 @@ alt_merge_opt_map_info(OnigEncoding enc, OptMapInfo* to, OptMapInfo* add)
 }\r
 \r
 static void\r
-set_bound_node_opt_info(NodeOptInfo* opt, MinMaxLen* mmd)\r
+set_bound_node_opt_info(NodeOpt* opt, MinMax* plen)\r
 {\r
-  copy_mml(&(opt->exb.mmd),  mmd);\r
-  copy_mml(&(opt->expr.mmd), mmd);\r
-  copy_mml(&(opt->map.mmd),  mmd);\r
+  copy_mml(&(opt->exb.mmd),  plen);\r
+  copy_mml(&(opt->expr.mmd), plen);\r
+  copy_mml(&(opt->map.mmd),  plen);\r
 }\r
 \r
 static void\r
-clear_node_opt_info(NodeOptInfo* opt)\r
+clear_node_opt_info(NodeOpt* opt)\r
 {\r
   clear_mml(&opt->len);\r
   clear_opt_anc_info(&opt->anc);\r
-  clear_opt_exact_info(&opt->exb);\r
-  clear_opt_exact_info(&opt->exm);\r
-  clear_opt_exact_info(&opt->expr);\r
-  clear_opt_map_info(&opt->map);\r
+  clear_opt_exact(&opt->exb);\r
+  clear_opt_exact(&opt->exm);\r
+  clear_opt_exact(&opt->expr);\r
+  clear_opt_map(&opt->map);\r
 }\r
 \r
 static void\r
-copy_node_opt_info(NodeOptInfo* to, NodeOptInfo* from)\r
+copy_node_opt_info(NodeOpt* to, NodeOpt* from)\r
 {\r
-  CopyMem (to, from, sizeof (NodeOptInfo));\r
+  xmemcpy(to,from,sizeof(NodeOpt));\r
 }\r
 \r
 static void\r
-concat_left_node_opt_info(OnigEncoding enc, NodeOptInfo* to, NodeOptInfo* add)\r
+concat_left_node_opt_info(OnigEncoding enc, NodeOpt* to, NodeOpt* add)\r
 {\r
   int exb_reach, exm_reach;\r
-  OptAncInfo tanc;\r
+  OptAnc tanc;\r
 \r
   concat_opt_anc_info(&tanc, &to->anc, &add->anc, to->len.max, add->len.max);\r
   copy_opt_anc_info(&to->anc, &tanc);\r
 \r
   if (add->exb.len > 0 && to->len.max == 0) {\r
-    concat_opt_anc_info(&tanc, &to->anc, &add->exb.anc,\r
-                       to->len.max, add->len.max);\r
+    concat_opt_anc_info(&tanc, &to->anc, &add->exb.anc, to->len.max, add->len.max);\r
     copy_opt_anc_info(&add->exb.anc, &tanc);\r
   }\r
 \r
   if (add->map.value > 0 && to->len.max == 0) {\r
     if (add->map.mmd.max == 0)\r
-      add->map.anc.left_anchor |= to->anc.left_anchor;\r
+      add->map.anc.left |= to->anc.left;\r
   }\r
 \r
   exb_reach = to->exb.reach_end;\r
@@ -4509,45 +5124,44 @@ concat_left_node_opt_info(OnigEncoding enc, NodeOptInfo* to, NodeOptInfo* add)
 \r
   if (add->exb.len > 0) {\r
     if (exb_reach) {\r
-      concat_opt_exact_info(&to->exb, &add->exb, enc);\r
-      clear_opt_exact_info(&add->exb);\r
+      concat_opt_exact(&to->exb, &add->exb, enc);\r
+      clear_opt_exact(&add->exb);\r
     }\r
     else if (exm_reach) {\r
-      concat_opt_exact_info(&to->exm, &add->exb, enc);\r
-      clear_opt_exact_info(&add->exb);\r
+      concat_opt_exact(&to->exm, &add->exb, enc);\r
+      clear_opt_exact(&add->exb);\r
     }\r
   }\r
-  select_opt_exact_info(enc, &to->exm, &add->exb);\r
-  select_opt_exact_info(enc, &to->exm, &add->exm);\r
+  select_opt_exact(enc, &to->exm, &add->exb);\r
+  select_opt_exact(enc, &to->exm, &add->exm);\r
 \r
   if (to->expr.len > 0) {\r
     if (add->len.max > 0) {\r
       if (to->expr.len > (int )add->len.max)\r
-       to->expr.len = add->len.max;\r
+        to->expr.len = add->len.max;\r
 \r
       if (to->expr.mmd.max == 0)\r
-       select_opt_exact_info(enc, &to->exb, &to->expr);\r
+        select_opt_exact(enc, &to->exb, &to->expr);\r
       else\r
-       select_opt_exact_info(enc, &to->exm, &to->expr);\r
+        select_opt_exact(enc, &to->exm, &to->expr);\r
     }\r
   }\r
   else if (add->expr.len > 0) {\r
-    copy_opt_exact_info(&to->expr, &add->expr);\r
+    copy_opt_exact(&to->expr, &add->expr);\r
   }\r
 \r
-  select_opt_map_info(&to->map, &add->map);\r
-\r
+  select_opt_map(&to->map, &add->map);\r
   add_mml(&to->len, &add->len);\r
 }\r
 \r
 static void\r
-alt_merge_node_opt_info(NodeOptInfo* to, NodeOptInfo* add, OptEnv* env)\r
+alt_merge_node_opt_info(NodeOpt* to, NodeOpt* add, OptEnv* env)\r
 {\r
-  alt_merge_opt_anc_info  (&to->anc,  &add->anc);\r
-  alt_merge_opt_exact_info(&to->exb,  &add->exb, env);\r
-  alt_merge_opt_exact_info(&to->exm,  &add->exm, env);\r
-  alt_merge_opt_exact_info(&to->expr, &add->expr, env);\r
-  alt_merge_opt_map_info(env->enc, &to->map,  &add->map);\r
+  alt_merge_opt_anc_info(&to->anc, &add->anc);\r
+  alt_merge_opt_exact(&to->exb,  &add->exb, env);\r
+  alt_merge_opt_exact(&to->exm,  &add->exm, env);\r
+  alt_merge_opt_exact(&to->expr, &add->expr, env);\r
+  alt_merge_opt_map(env->enc, &to->map, &add->map);\r
 \r
   alt_merge_mml(&to->len, &add->len);\r
 }\r
@@ -4556,341 +5170,354 @@ alt_merge_node_opt_info(NodeOptInfo* to, NodeOptInfo* add, OptEnv* env)
 #define MAX_NODE_OPT_INFO_REF_COUNT    5\r
 \r
 static int\r
-optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env)\r
+optimize_nodes(Node* node, NodeOpt* opt, OptEnv* env)\r
 {\r
-  int type;\r
-  int r = 0;\r
+  int i;\r
+  int r;\r
+  NodeOpt xo;\r
+  OnigEncoding enc;\r
 \r
+  r = 0;\r
+  enc = env->enc;\r
   clear_node_opt_info(opt);\r
   set_bound_node_opt_info(opt, &env->mmd);\r
 \r
-  type = NTYPE(node);\r
-  switch (type) {\r
-  case NT_LIST:\r
+  switch (NODE_TYPE(node)) {\r
+  case NODE_LIST:\r
     {\r
       OptEnv nenv;\r
-      NodeOptInfo nopt;\r
       Node* nd = node;\r
 \r
       copy_opt_env(&nenv, env);\r
       do {\r
-       r = optimize_node_left(NCAR(nd), &nopt, &nenv);\r
-       if (r == 0) {\r
-         add_mml(&nenv.mmd, &nopt.len);\r
-         concat_left_node_opt_info(env->enc, opt, &nopt);\r
-       }\r
-      } while (r == 0 && IS_NOT_NULL(nd = NCDR(nd)));\r
+        r = optimize_nodes(NODE_CAR(nd), &xo, &nenv);\r
+        if (r == 0) {\r
+          add_mml(&nenv.mmd, &xo.len);\r
+          concat_left_node_opt_info(enc, opt, &xo);\r
+        }\r
+      } while (r == 0 && IS_NOT_NULL(nd = NODE_CDR(nd)));\r
     }\r
     break;\r
 \r
-  case NT_ALT:\r
+  case NODE_ALT:\r
     {\r
-      NodeOptInfo nopt;\r
       Node* nd = node;\r
 \r
       do {\r
-       r = optimize_node_left(NCAR(nd), &nopt, env);\r
-       if (r == 0) {\r
-         if (nd == node) copy_node_opt_info(opt, &nopt);\r
-         else            alt_merge_node_opt_info(opt, &nopt, env);\r
-       }\r
-      } while ((r == 0) && IS_NOT_NULL(nd = NCDR(nd)));\r
+        r = optimize_nodes(NODE_CAR(nd), &xo, env);\r
+        if (r == 0) {\r
+          if (nd == node) copy_node_opt_info(opt, &xo);\r
+          else            alt_merge_node_opt_info(opt, &xo, env);\r
+        }\r
+      } while ((r == 0) && IS_NOT_NULL(nd = NODE_CDR(nd)));\r
     }\r
     break;\r
 \r
-  case NT_STR:\r
+  case NODE_STRING:\r
     {\r
-      StrNode* sn = NSTR(node);\r
-      int slen = (int)(sn->end - sn->s);\r
-      int is_raw = NSTRING_IS_RAW(node);\r
-\r
-      if (! NSTRING_IS_AMBIG(node)) {\r
-       concat_opt_exact_info_str(&opt->exb, sn->s, sn->end,\r
-                                 NSTRING_IS_RAW(node), env->enc);\r
-       if (slen > 0) {\r
-         add_char_opt_map_info(&opt->map, *(sn->s), env->enc);\r
-       }\r
+      StrNode* sn = STR_(node);\r
+      int slen = (int )(sn->end - sn->s);\r
+      /* int is_raw = NODE_STRING_IS_RAW(node); */\r
+\r
+      if (! NODE_STRING_IS_AMBIG(node)) {\r
+        concat_opt_exact_str(&opt->exb, sn->s, sn->end, enc);\r
+        if (slen > 0) {\r
+          add_char_opt_map(&opt->map, *(sn->s), enc);\r
+        }\r
         set_mml(&opt->len, slen, slen);\r
       }\r
       else {\r
         int max;\r
 \r
-       if (NSTRING_IS_DONT_GET_OPT_INFO(node)) {\r
-          int n = onigenc_strlen(env->enc, sn->s, sn->end);\r
-          max = ONIGENC_MBC_MAXLEN_DIST(env->enc) * n;\r
-       }\r
-       else {\r
-         concat_opt_exact_info_str(&opt->exb, sn->s, sn->end,\r
-                                   is_raw, env->enc);\r
-         opt->exb.ignore_case = 1;\r
+        if (NODE_STRING_IS_DONT_GET_OPT_INFO(node)) {\r
+          int n = onigenc_strlen(enc, sn->s, sn->end);\r
+          max = ONIGENC_MBC_MAXLEN_DIST(enc) * n;\r
+        }\r
+        else {\r
+          concat_opt_exact_str(&opt->exb, sn->s, sn->end, enc);\r
+          opt->exb.ignore_case = 1;\r
 \r
-         if (slen > 0) {\r
-           r = add_char_amb_opt_map_info(&opt->map, sn->s, sn->end,\r
-                                         env->enc, env->case_fold_flag);\r
-           if (r != 0) break;\r
-         }\r
+          if (slen > 0) {\r
+            r = add_char_amb_opt_map(&opt->map, sn->s, sn->end,\r
+                                     enc, env->case_fold_flag);\r
+            if (r != 0) break;\r
+          }\r
 \r
-         max = slen;\r
-       }\r
+          max = slen;\r
+        }\r
 \r
         set_mml(&opt->len, slen, max);\r
       }\r
 \r
       if (opt->exb.len == slen)\r
-       opt->exb.reach_end = 1;\r
+        opt->exb.reach_end = 1;\r
     }\r
     break;\r
 \r
-  case NT_CCLASS:\r
+  case NODE_CCLASS:\r
     {\r
-      int i, z;\r
-      CClassNode* cc = NCCLASS(node);\r
+      int z;\r
+      CClassNode* cc = CCLASS_(node);\r
 \r
-      /* no need to check ignore case. (setted in setup_tree()) */\r
+      /* no need to check ignore case. (set in setup_tree()) */\r
 \r
       if (IS_NOT_NULL(cc->mbuf) || IS_NCCLASS_NOT(cc)) {\r
-        OnigDistance min = ONIGENC_MBC_MINLEN(env->enc);\r
-       OnigDistance max = ONIGENC_MBC_MAXLEN_DIST(env->enc);\r
+        OnigLen min = ONIGENC_MBC_MINLEN(enc);\r
+        OnigLen max = ONIGENC_MBC_MAXLEN_DIST(enc);\r
 \r
-       set_mml(&opt->len, min, max);\r
+        set_mml(&opt->len, min, max);\r
       }\r
       else {\r
         for (i = 0; i < SINGLE_BYTE_SIZE; i++) {\r
           z = BITSET_AT(cc->bs, i);\r
-          if ((z && !IS_NCCLASS_NOT(cc)) || (!z && IS_NCCLASS_NOT(cc))) {\r
-            add_char_opt_map_info(&opt->map, (UChar )i, env->enc);\r
+          if ((z && ! IS_NCCLASS_NOT(cc)) || (! z && IS_NCCLASS_NOT(cc))) {\r
+            add_char_opt_map(&opt->map, (UChar )i, enc);\r
           }\r
         }\r
-       set_mml(&opt->len, 1, 1);\r
+        set_mml(&opt->len, 1, 1);\r
       }\r
     }\r
     break;\r
 \r
-  case NT_CTYPE:\r
+  case NODE_CTYPE:\r
     {\r
-      int i, min, max;\r
+      int min, max;\r
+      int range;\r
 \r
-      max = ONIGENC_MBC_MAXLEN_DIST(env->enc);\r
+      max = ONIGENC_MBC_MAXLEN_DIST(enc);\r
 \r
       if (max == 1) {\r
         min = 1;\r
 \r
-       switch (NCTYPE(node)->ctype) {\r
-       case ONIGENC_CTYPE_WORD:\r
-         if (NCTYPE(node)->not != 0) {\r
-           for (i = 0; i < SINGLE_BYTE_SIZE; i++) {\r
-             if (! ONIGENC_IS_CODE_WORD(env->enc, i)) {\r
-               add_char_opt_map_info(&opt->map, (UChar )i, env->enc);\r
-             }\r
-           }\r
-         }\r
-         else {\r
-           for (i = 0; i < SINGLE_BYTE_SIZE; i++) {\r
-             if (ONIGENC_IS_CODE_WORD(env->enc, i)) {\r
-               add_char_opt_map_info(&opt->map, (UChar )i, env->enc);\r
-             }\r
-           }\r
-         }\r
-         break;\r
-       }\r
+        switch (CTYPE_(node)->ctype) {\r
+        case CTYPE_ANYCHAR:\r
+          break;\r
+\r
+        case ONIGENC_CTYPE_WORD:\r
+          range = CTYPE_(node)->ascii_mode != 0 ? 128 : SINGLE_BYTE_SIZE;\r
+          if (CTYPE_(node)->not != 0) {\r
+            for (i = 0; i < range; i++) {\r
+              if (! ONIGENC_IS_CODE_WORD(enc, i)) {\r
+                add_char_opt_map(&opt->map, (UChar )i, enc);\r
+              }\r
+            }\r
+            for (i = range; i < SINGLE_BYTE_SIZE; i++) {\r
+              add_char_opt_map(&opt->map, (UChar )i, enc);\r
+            }\r
+          }\r
+          else {\r
+            for (i = 0; i < range; i++) {\r
+              if (ONIGENC_IS_CODE_WORD(enc, i)) {\r
+                add_char_opt_map(&opt->map, (UChar )i, enc);\r
+              }\r
+            }\r
+          }\r
+          break;\r
+        }\r
       }\r
       else {\r
-        min = ONIGENC_MBC_MINLEN(env->enc);\r
+        min = ONIGENC_MBC_MINLEN(enc);\r
       }\r
       set_mml(&opt->len, min, max);\r
     }\r
     break;\r
 \r
-  case NT_CANY:\r
-    {\r
-      OnigDistance min = ONIGENC_MBC_MINLEN(env->enc);\r
-      OnigDistance max = ONIGENC_MBC_MAXLEN_DIST(env->enc);\r
-      set_mml(&opt->len, min, max);\r
-    }\r
-    break;\r
-\r
-  case NT_ANCHOR:\r
-    switch (NANCHOR(node)->type) {\r
+  case NODE_ANCHOR:\r
+    switch (ANCHOR_(node)->type) {\r
     case ANCHOR_BEGIN_BUF:\r
     case ANCHOR_BEGIN_POSITION:\r
     case ANCHOR_BEGIN_LINE:\r
     case ANCHOR_END_BUF:\r
     case ANCHOR_SEMI_END_BUF:\r
     case ANCHOR_END_LINE:\r
-      add_opt_anc_info(&opt->anc, NANCHOR(node)->type);\r
+    case ANCHOR_PREC_READ_NOT:\r
+    case ANCHOR_LOOK_BEHIND:\r
+      add_opt_anc_info(&opt->anc, ANCHOR_(node)->type);\r
       break;\r
 \r
     case ANCHOR_PREC_READ:\r
       {\r
-       NodeOptInfo nopt;\r
+        r = optimize_nodes(NODE_BODY(node), &xo, env);\r
+        if (r == 0) {\r
+          if (xo.exb.len > 0)\r
+            copy_opt_exact(&opt->expr, &xo.exb);\r
+          else if (xo.exm.len > 0)\r
+            copy_opt_exact(&opt->expr, &xo.exm);\r
 \r
-       r = optimize_node_left(NANCHOR(node)->target, &nopt, env);\r
-       if (r == 0) {\r
-         if (nopt.exb.len > 0)\r
-           copy_opt_exact_info(&opt->expr, &nopt.exb);\r
-         else if (nopt.exm.len > 0)\r
-           copy_opt_exact_info(&opt->expr, &nopt.exm);\r
+          opt->expr.reach_end = 0;\r
 \r
-         opt->expr.reach_end = 0;\r
-\r
-         if (nopt.map.value > 0)\r
-           copy_opt_map_info(&opt->map, &nopt.map);\r
-       }\r
+          if (xo.map.value > 0)\r
+            copy_opt_map(&opt->map, &xo.map);\r
+        }\r
       }\r
       break;\r
 \r
-    case ANCHOR_PREC_READ_NOT:\r
-    case ANCHOR_LOOK_BEHIND: /* Sorry, I can't make use of it. */\r
     case ANCHOR_LOOK_BEHIND_NOT:\r
       break;\r
     }\r
     break;\r
 \r
-  case NT_BREF:\r
-    {\r
-      int i;\r
+  case NODE_BACKREF:\r
+    if (! NODE_IS_CHECKER(node)) {\r
       int* backs;\r
-      OnigDistance min, max, tmin, tmax;\r
-      Node** nodes = SCANENV_MEM_NODES(env->scan_env);\r
-      BRefNode* br = NBREF(node);\r
+      OnigLen min, max, tmin, tmax;\r
+      MemEnv* mem_env = SCANENV_MEMENV(env->scan_env);\r
+      BackRefNode* br = BACKREF_(node);\r
 \r
-      if (br->state & NST_RECURSION) {\r
-       set_mml(&opt->len, 0, ONIG_INFINITE_DISTANCE);\r
-       break;\r
+      if (NODE_IS_RECURSION(node)) {\r
+        set_mml(&opt->len, 0, INFINITE_LEN);\r
+        break;\r
       }\r
       backs = BACKREFS_P(br);\r
-      r = get_min_match_length(nodes[backs[0]], &min, env->scan_env);\r
-      if (r != 0) break;\r
-      r = get_max_match_length(nodes[backs[0]], &max, env->scan_env);\r
-      if (r != 0) break;\r
+      min = tree_min_len(mem_env[backs[0]].node, env->scan_env);\r
+      max = tree_max_len(mem_env[backs[0]].node, env->scan_env);\r
       for (i = 1; i < br->back_num; i++) {\r
-       r = get_min_match_length(nodes[backs[i]], &tmin, env->scan_env);\r
-       if (r != 0) break;\r
-       r = get_max_match_length(nodes[backs[i]], &tmax, env->scan_env);\r
-       if (r != 0) break;\r
-       if (min > tmin) min = tmin;\r
-       if (max < tmax) max = tmax;\r
+        tmin = tree_min_len(mem_env[backs[i]].node, env->scan_env);\r
+        tmax = tree_max_len(mem_env[backs[i]].node, env->scan_env);\r
+        if (min > tmin) min = tmin;\r
+        if (max < tmax) max = tmax;\r
       }\r
-      if (r == 0) set_mml(&opt->len, min, max);\r
+      set_mml(&opt->len, min, max);\r
     }\r
     break;\r
 \r
-#ifdef USE_SUBEXP_CALL\r
-  case NT_CALL:\r
-    if (IS_CALL_RECURSION(NCALL(node)))\r
-      set_mml(&opt->len, 0, ONIG_INFINITE_DISTANCE);\r
+#ifdef USE_CALL\r
+  case NODE_CALL:\r
+    if (NODE_IS_RECURSION(node))\r
+      set_mml(&opt->len, 0, INFINITE_LEN);\r
     else {\r
       OnigOptionType save = env->options;\r
-      env->options = NENCLOSE(NCALL(node)->target)->option;\r
-      r = optimize_node_left(NCALL(node)->target, opt, env);\r
+      env->options = ENCLOSURE_(NODE_BODY(node))->o.options;\r
+      r = optimize_nodes(NODE_BODY(node), opt, env);\r
       env->options = save;\r
     }\r
     break;\r
 #endif\r
 \r
-  case NT_QTFR:\r
+  case NODE_QUANT:\r
     {\r
-      int i;\r
-      OnigDistance min, max;\r
-      NodeOptInfo nopt;\r
-      QtfrNode* qn = NQTFR(node);\r
-\r
-      r = optimize_node_left(qn->target, &nopt, env);\r
-      if (r) break;\r
-\r
-      if (qn->lower == 0 && IS_REPEAT_INFINITE(qn->upper)) {\r
-       if (env->mmd.max == 0 &&\r
-           NTYPE(qn->target) == NT_CANY && qn->greedy) {\r
-         if (IS_MULTILINE(env->options))\r
-           add_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR_ML);\r
-         else\r
-           add_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR);\r
-       }\r
+      OnigLen min, max;\r
+      QuantNode* qn = QUANT_(node);\r
+\r
+      r = optimize_nodes(NODE_BODY(node), &xo, env);\r
+      if (r != 0) break;\r
+\r
+      if (qn->lower > 0) {\r
+        copy_node_opt_info(opt, &xo);\r
+        if (xo.exb.len > 0) {\r
+          if (xo.exb.reach_end) {\r
+            for (i = 2; i <= qn->lower && ! is_full_opt_exact(&opt->exb); i++) {\r
+              int rc = concat_opt_exact(&opt->exb, &xo.exb, enc);\r
+              if (rc > 0) break;\r
+            }\r
+            if (i < qn->lower) opt->exb.reach_end = 0;\r
+          }\r
+        }\r
+\r
+        if (qn->lower != qn->upper) {\r
+          opt->exb.reach_end = 0;\r
+          opt->exm.reach_end = 0;\r
+        }\r
+        if (qn->lower > 1)\r
+          opt->exm.reach_end = 0;\r
+      }\r
+\r
+      if (IS_REPEAT_INFINITE(qn->upper)) {\r
+        if (env->mmd.max == 0 &&\r
+            NODE_IS_ANYCHAR(NODE_BODY(node)) && qn->greedy != 0) {\r
+          if (IS_MULTILINE(CTYPE_OPTION(NODE_QUANT_BODY(qn), env)))\r
+            add_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_INF_ML);\r
+          else\r
+            add_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_INF);\r
+        }\r
+\r
+        max = (xo.len.max > 0 ? INFINITE_LEN : 0);\r
       }\r
       else {\r
-       if (qn->lower > 0) {\r
-         copy_node_opt_info(opt, &nopt);\r
-         if (nopt.exb.len > 0) {\r
-           if (nopt.exb.reach_end) {\r
-             for (i = 2; i <= qn->lower &&\r
-                         ! is_full_opt_exact_info(&opt->exb); i++) {\r
-               concat_opt_exact_info(&opt->exb, &nopt.exb, env->enc);\r
-             }\r
-             if (i < qn->lower) {\r
-               opt->exb.reach_end = 0;\r
-             }\r
-           }\r
-         }\r
-\r
-         if (qn->lower != qn->upper) {\r
-           opt->exb.reach_end = 0;\r
-           opt->exm.reach_end = 0;\r
-         }\r
-         if (qn->lower > 1)\r
-           opt->exm.reach_end = 0;\r
-       }\r
+        max = distance_multiply(xo.len.max, qn->upper);\r
       }\r
 \r
-      min = distance_multiply(nopt.len.min, qn->lower);\r
-      if (IS_REPEAT_INFINITE(qn->upper))\r
-       max = (nopt.len.max > 0 ? ONIG_INFINITE_DISTANCE : 0);\r
-      else\r
-       max = distance_multiply(nopt.len.max, qn->upper);\r
-\r
+      min = distance_multiply(xo.len.min, qn->lower);\r
       set_mml(&opt->len, min, max);\r
     }\r
     break;\r
 \r
-  case NT_ENCLOSE:\r
-    {\r
-      EncloseNode* en = NENCLOSE(node);\r
-\r
-      switch (en->type) {\r
-      case ENCLOSE_OPTION:\r
-       {\r
-         OnigOptionType save = env->options;\r
-\r
-         env->options = en->option;\r
-         r = optimize_node_left(en->target, opt, env);\r
-         env->options = save;\r
-       }\r
-       break;\r
-\r
-      case ENCLOSE_MEMORY:\r
-#ifdef USE_SUBEXP_CALL\r
-       en->opt_count++;\r
-       if (en->opt_count > MAX_NODE_OPT_INFO_REF_COUNT) {\r
-         OnigDistance min, max;\r
-\r
-         min = 0;\r
-         max = ONIG_INFINITE_DISTANCE;\r
-         if (IS_ENCLOSE_MIN_FIXED(en)) min = en->min_len;\r
-         if (IS_ENCLOSE_MAX_FIXED(en)) max = en->max_len;\r
-         set_mml(&opt->len, min, max);\r
-       }\r
-       else\r
-#endif\r
-       {\r
-         r = optimize_node_left(en->target, opt, env);\r
-\r
-         if (is_set_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR_MASK)) {\r
-           if (BIT_STATUS_AT(env->scan_env->backrefed_mem, en->regnum))\r
-             remove_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR_MASK);\r
-         }\r
-       }\r
-       break;\r
-\r
-      case ENCLOSE_STOP_BACKTRACK:\r
-       r = optimize_node_left(en->target, opt, env);\r
-       break;\r
-      }\r
-    }\r
+  case NODE_ENCLOSURE:\r
+    {\r
+      EnclosureNode* en = ENCLOSURE_(node);\r
+\r
+      switch (en->type) {\r
+      case ENCLOSURE_OPTION:\r
+        {\r
+          OnigOptionType save = env->options;\r
+\r
+          env->options = en->o.options;\r
+          r = optimize_nodes(NODE_BODY(node), opt, env);\r
+          env->options = save;\r
+        }\r
+        break;\r
+\r
+      case ENCLOSURE_MEMORY:\r
+#ifdef USE_CALL\r
+        en->opt_count++;\r
+        if (en->opt_count > MAX_NODE_OPT_INFO_REF_COUNT) {\r
+          OnigLen min, max;\r
+\r
+          min = 0;\r
+          max = INFINITE_LEN;\r
+          if (NODE_IS_MIN_FIXED(node)) min = en->min_len;\r
+          if (NODE_IS_MAX_FIXED(node)) max = en->max_len;\r
+          set_mml(&opt->len, min, max);\r
+        }\r
+        else\r
+#endif\r
+          {\r
+            r = optimize_nodes(NODE_BODY(node), opt, env);\r
+            if (is_set_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_INF_MASK)) {\r
+              if (MEM_STATUS_AT0(env->scan_env->backrefed_mem, en->m.regnum))\r
+                remove_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_INF_MASK);\r
+            }\r
+          }\r
+        break;\r
+\r
+      case ENCLOSURE_STOP_BACKTRACK:\r
+        r = optimize_nodes(NODE_BODY(node), opt, env);\r
+        break;\r
+\r
+      case ENCLOSURE_IF_ELSE:\r
+        {\r
+          OptEnv nenv;\r
+\r
+          copy_opt_env(&nenv, env);\r
+          r = optimize_nodes(NODE_ENCLOSURE_BODY(en), &xo, &nenv);\r
+          if (r == 0) {\r
+            add_mml(&nenv.mmd, &xo.len);\r
+            concat_left_node_opt_info(enc, opt, &xo);\r
+            if (IS_NOT_NULL(en->te.Then)) {\r
+              r = optimize_nodes(en->te.Then, &xo, &nenv);\r
+              if (r == 0) {\r
+                concat_left_node_opt_info(enc, opt, &xo);\r
+              }\r
+            }\r
+\r
+            if (IS_NOT_NULL(en->te.Else)) {\r
+              r = optimize_nodes(en->te.Else, &xo, env);\r
+              if (r == 0)\r
+                alt_merge_node_opt_info(opt, &xo, env);\r
+            }\r
+          }\r
+        }\r
+        break;\r
+      }\r
+    }\r
+    break;\r
+\r
+  case NODE_GIMMICK:\r
     break;\r
 \r
   default:\r
 #ifdef ONIG_DEBUG\r
-    fprintf(stderr, "optimize_node_left: undefined node type %d\n",\r
-           NTYPE(node));\r
+    fprintf(stderr, "optimize_nodes: undefined node type %d\n", NODE_TYPE(node));\r
 #endif\r
     r = ONIGERR_TYPE_BUG;\r
     break;\r
@@ -4900,7 +5527,7 @@ optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env)
 }\r
 \r
 static int\r
-set_optimize_exact_info(regex_t* reg, OptExactInfo* e)\r
+set_optimize_exact(regex_t* reg, OptExact* e)\r
 {\r
   int r;\r
 \r
@@ -4911,90 +5538,94 @@ set_optimize_exact_info(regex_t* reg, OptExactInfo* e)
     CHECK_NULL_RETURN_MEMERR(reg->exact);\r
     xmemcpy(reg->exact, e->s, e->len);\r
     reg->exact_end = reg->exact + e->len;\r
-    reg->optimize = ONIG_OPTIMIZE_EXACT_IC;\r
+    reg->optimize = OPTIMIZE_EXACT_IC;\r
   }\r
   else {\r
     int allow_reverse;\r
 \r
-    reg->exact = str_dup(e->s, e->s + e->len);\r
+    reg->exact = onigenc_strdup(reg->enc, e->s, e->s + e->len);\r
     CHECK_NULL_RETURN_MEMERR(reg->exact);\r
     reg->exact_end = reg->exact + e->len;\r
  \r
     allow_reverse =\r
-       ONIGENC_IS_ALLOWED_REVERSE_MATCH(reg->enc, reg->exact, reg->exact_end);\r
+      ONIGENC_IS_ALLOWED_REVERSE_MATCH(reg->enc, reg->exact, reg->exact_end);\r
 \r
     if (e->len >= 3 || (e->len >= 2 && allow_reverse)) {\r
       r = set_bm_skip(reg->exact, reg->exact_end, reg->enc,\r
-                     reg->map, &(reg->int_map));\r
-      if (r) return r;\r
+                      reg->map, &(reg->int_map));\r
+      if (r != 0) return r;\r
 \r
       reg->optimize = (allow_reverse != 0\r
-                      ? ONIG_OPTIMIZE_EXACT_BM : ONIG_OPTIMIZE_EXACT_BM_NOT_REV);\r
+                       ? OPTIMIZE_EXACT_BM : OPTIMIZE_EXACT_BM_NO_REV);\r
     }\r
     else {\r
-      reg->optimize = ONIG_OPTIMIZE_EXACT;\r
+      reg->optimize = OPTIMIZE_EXACT;\r
     }\r
   }\r
 \r
   reg->dmin = e->mmd.min;\r
   reg->dmax = e->mmd.max;\r
 \r
-  if (reg->dmin != ONIG_INFINITE_DISTANCE) {\r
-    reg->threshold_len = reg->dmin + (int)(reg->exact_end - reg->exact);\r
+  if (reg->dmin != INFINITE_LEN) {\r
+    reg->threshold_len = reg->dmin + (int )(reg->exact_end - reg->exact);\r
   }\r
 \r
   return 0;\r
 }\r
 \r
 static void\r
-set_optimize_map_info(regex_t* reg, OptMapInfo* m)\r
+set_optimize_map(regex_t* reg, OptMap* m)\r
 {\r
   int i;\r
 \r
   for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++)\r
     reg->map[i] = m->map[i];\r
 \r
-  reg->optimize   = ONIG_OPTIMIZE_MAP;\r
+  reg->optimize   = OPTIMIZE_MAP;\r
   reg->dmin       = m->mmd.min;\r
   reg->dmax       = m->mmd.max;\r
 \r
-  if (reg->dmin != ONIG_INFINITE_DISTANCE) {\r
+  if (reg->dmin != INFINITE_LEN) {\r
     reg->threshold_len = reg->dmin + 1;\r
   }\r
 }\r
 \r
 static void\r
-set_sub_anchor(regex_t* reg, OptAncInfo* anc)\r
+set_sub_anchor(regex_t* reg, OptAnc* anc)\r
 {\r
-  reg->sub_anchor |= anc->left_anchor  & ANCHOR_BEGIN_LINE;\r
-  reg->sub_anchor |= anc->right_anchor & ANCHOR_END_LINE;\r
+  reg->sub_anchor |= anc->left  & ANCHOR_BEGIN_LINE;\r
+  reg->sub_anchor |= anc->right & ANCHOR_END_LINE;\r
 }\r
 \r
-#ifdef ONIG_DEBUG\r
+#if defined(ONIG_DEBUG_COMPILE) || defined(ONIG_DEBUG_MATCH)\r
 static void print_optimize_info(FILE* f, regex_t* reg);\r
 #endif\r
 \r
 static int\r
 set_optimize_info_from_tree(Node* node, regex_t* reg, ScanEnv* scan_env)\r
 {\r
-\r
   int r;\r
-  NodeOptInfo opt;\r
+  NodeOpt opt;\r
   OptEnv env;\r
 \r
   env.enc            = reg->enc;\r
   env.options        = reg->options;\r
   env.case_fold_flag = reg->case_fold_flag;\r
-  env.scan_env   = scan_env;\r
+  env.scan_env       = scan_env;\r
   clear_mml(&env.mmd);\r
 \r
-  r = optimize_node_left(node, &opt, &env);\r
-  if (r) return r;\r
+  r = optimize_nodes(node, &opt, &env);\r
+  if (r != 0) return r;\r
+\r
+  reg->anchor = opt.anc.left & (ANCHOR_BEGIN_BUF |\r
+        ANCHOR_BEGIN_POSITION | ANCHOR_ANYCHAR_INF | ANCHOR_ANYCHAR_INF_ML |\r
+        ANCHOR_LOOK_BEHIND);\r
 \r
-  reg->anchor = opt.anc.left_anchor & (ANCHOR_BEGIN_BUF |\r
-        ANCHOR_BEGIN_POSITION | ANCHOR_ANYCHAR_STAR | ANCHOR_ANYCHAR_STAR_ML);\r
+  if ((opt.anc.left & (ANCHOR_LOOK_BEHIND | ANCHOR_PREC_READ_NOT)) != 0)\r
+    reg->anchor &= ~ANCHOR_ANYCHAR_INF_ML;\r
 \r
-  reg->anchor |= opt.anc.right_anchor & (ANCHOR_END_BUF | ANCHOR_SEMI_END_BUF);\r
+  reg->anchor |= opt.anc.right & (ANCHOR_END_BUF | ANCHOR_SEMI_END_BUF |\r
+       ANCHOR_PREC_READ_NOT);\r
 \r
   if (reg->anchor & (ANCHOR_END_BUF | ANCHOR_SEMI_END_BUF)) {\r
     reg->anchor_dmin = opt.len.min;\r
@@ -5002,25 +5633,24 @@ set_optimize_info_from_tree(Node* node, regex_t* reg, ScanEnv* scan_env)
   }\r
 \r
   if (opt.exb.len > 0 || opt.exm.len > 0) {\r
-    select_opt_exact_info(reg->enc, &opt.exb, &opt.exm);\r
-    if (opt.map.value > 0 &&\r
-       comp_opt_exact_or_map_info(&opt.exb, &opt.map) > 0) {\r
+    select_opt_exact(reg->enc, &opt.exb, &opt.exm);\r
+    if (opt.map.value > 0 && comp_opt_exact_or_map(&opt.exb, &opt.map) > 0) {\r
       goto set_map;\r
     }\r
     else {\r
-      r = set_optimize_exact_info(reg, &opt.exb);\r
+      r = set_optimize_exact(reg, &opt.exb);\r
       set_sub_anchor(reg, &opt.exb.anc);\r
     }\r
   }\r
   else if (opt.map.value > 0) {\r
   set_map:\r
-    set_optimize_map_info(reg, &opt.map);\r
+    set_optimize_map(reg, &opt.map);\r
     set_sub_anchor(reg, &opt.map.anc);\r
   }\r
   else {\r
-    reg->sub_anchor |= opt.anc.left_anchor & ANCHOR_BEGIN_LINE;\r
+    reg->sub_anchor |= opt.anc.left & ANCHOR_BEGIN_LINE;\r
     if (opt.len.max == 0)\r
-      reg->sub_anchor |= opt.anc.right_anchor & ANCHOR_END_LINE;\r
+      reg->sub_anchor |= opt.anc.right & ANCHOR_END_LINE;\r
   }\r
 \r
 #if defined(ONIG_DEBUG_COMPILE) || defined(ONIG_DEBUG_MATCH)\r
@@ -5032,7 +5662,7 @@ set_optimize_info_from_tree(Node* node, regex_t* reg, ScanEnv* scan_env)
 static void\r
 clear_optimize_info(regex_t* reg)\r
 {\r
-  reg->optimize      = ONIG_OPTIMIZE_NONE;\r
+  reg->optimize      = OPTIMIZE_NONE;\r
   reg->anchor        = 0;\r
   reg->anchor_dmin   = 0;\r
   reg->anchor_dmax   = 0;\r
@@ -5048,7 +5678,7 @@ clear_optimize_info(regex_t* reg)
 #ifdef ONIG_DEBUG\r
 \r
 static void print_enc_string(FILE* fp, OnigEncoding enc,\r
-                            const UChar *s, const UChar *end)\r
+                             const UChar *s, const UChar *end)\r
 {\r
   fprintf(fp, "\nPATTERN: /");\r
 \r
@@ -5060,10 +5690,10 @@ static void print_enc_string(FILE* fp, OnigEncoding enc,
     while (p < end) {\r
       code = ONIGENC_MBC_TO_CODE(enc, p, end);\r
       if (code >= 0x80) {\r
-       fprintf(fp, " 0x%04x ", (int )code);\r
+        fprintf(fp, " 0x%04x ", (int )code);\r
       }\r
       else {\r
-       fputc((int )code, fp);\r
+        fputc((int )code, fp);\r
       }\r
 \r
       p += enclen(enc, p);\r
@@ -5079,17 +5709,21 @@ static void print_enc_string(FILE* fp, OnigEncoding enc,
   fprintf(fp, "/\n");\r
 }\r
 \r
+#endif /* ONIG_DEBUG */\r
+\r
+#if defined(ONIG_DEBUG_COMPILE) || defined(ONIG_DEBUG_MATCH)\r
+\r
 static void\r
-print_distance_range(FILE* f, OnigDistance a, OnigDistance b)\r
+print_distance_range(FILE* f, OnigLen a, OnigLen b)\r
 {\r
-  if (a == ONIG_INFINITE_DISTANCE)\r
+  if (a == INFINITE_LEN)\r
     fputs("inf", f);\r
   else\r
     fprintf(f, "(%u)", a);\r
 \r
   fputs("-", f);\r
 \r
-  if (b == ONIG_INFINITE_DISTANCE)\r
+  if (b == INFINITE_LEN)\r
     fputs("inf", f);\r
   else\r
     fprintf(f, "(%u)", b);\r
@@ -5131,14 +5765,14 @@ print_anchor(FILE* f, int anchor)
     q = 1;\r
     fprintf(f, "end-line");\r
   }\r
-  if (anchor & ANCHOR_ANYCHAR_STAR) {\r
+  if (anchor & ANCHOR_ANYCHAR_INF) {\r
     if (q) fprintf(f, ", ");\r
     q = 1;\r
-    fprintf(f, "anychar-star");\r
+    fprintf(f, "anychar-inf");\r
   }\r
-  if (anchor & ANCHOR_ANYCHAR_STAR_ML) {\r
+  if (anchor & ANCHOR_ANYCHAR_INF_ML) {\r
     if (q) fprintf(f, ", ");\r
-    fprintf(f, "anychar-star-pl");\r
+    fprintf(f, "anychar-inf-ml");\r
   }\r
 \r
   fprintf(f, "]");\r
@@ -5168,9 +5802,9 @@ print_optimize_info(FILE* f, regex_t* reg)
     for (p = reg->exact; p < reg->exact_end; p++) {\r
       fputc(*p, f);\r
     }\r
-    fprintf(f, "]: length: %d\n", (reg->exact_end - reg->exact));\r
+    fprintf(f, "]: length: %ld\n", (reg->exact_end - reg->exact));\r
   }\r
-  else if (reg->optimize & ONIG_OPTIMIZE_MAP) {\r
+  else if (reg->optimize & OPTIMIZE_MAP) {\r
     int c, i, n = 0;\r
 \r
     for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++)\r
@@ -5181,7 +5815,7 @@ print_optimize_info(FILE* f, regex_t* reg)
       c = 0;\r
       fputc('[', f);\r
       for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) {\r
-       if (reg->map[i] != 0) {\r
+        if (reg->map[i] != 0) {\r
           if (c > 0)  fputs(", ", f);\r
           c++;\r
           if (ONIGENC_MBC_MAXLEN(reg->enc) == 1 &&\r
@@ -5195,7 +5829,67 @@ print_optimize_info(FILE* f, regex_t* reg)
     }\r
   }\r
 }\r
-#endif /* ONIG_DEBUG */\r
+#endif\r
+\r
+\r
+extern RegexExt*\r
+onig_get_regex_ext(regex_t* reg)\r
+{\r
+  if (IS_NULL(REG_EXTP(reg))) {\r
+    RegexExt* ext = (RegexExt* )xmalloc(sizeof(*ext));\r
+    if (IS_NULL(ext)) return 0;\r
+\r
+    ext->pattern      = 0;\r
+    ext->pattern_end  = 0;\r
+#ifdef USE_CALLOUT\r
+    ext->tag_table    = 0;\r
+    ext->callout_num  = 0;\r
+    ext->callout_list_alloc = 0;\r
+    ext->callout_list = 0;\r
+#endif\r
+\r
+    REG_EXTPL(reg) = (void* )ext;\r
+  }\r
+\r
+  return REG_EXTP(reg);\r
+}\r
+\r
+static void\r
+free_regex_ext(RegexExt* ext)\r
+{\r
+  if (IS_NOT_NULL(ext)) {\r
+    if (IS_NOT_NULL(ext->pattern))\r
+      xfree((void* )ext->pattern);\r
+\r
+#ifdef USE_CALLOUT\r
+    if (IS_NOT_NULL(ext->tag_table))\r
+      onig_callout_tag_table_free(ext->tag_table);\r
+\r
+    if (IS_NOT_NULL(ext->callout_list))\r
+      onig_free_reg_callout_list(ext->callout_num, ext->callout_list);\r
+#endif\r
+\r
+    xfree(ext);\r
+  }\r
+}\r
+\r
+extern int\r
+onig_ext_set_pattern(regex_t* reg, const UChar* pattern, const UChar* pattern_end)\r
+{\r
+  RegexExt* ext;\r
+  UChar* s;\r
+\r
+  ext = onig_get_regex_ext(reg);\r
+  CHECK_NULL_RETURN_MEMERR(ext);\r
+\r
+  s = onigenc_strdup(reg->enc, pattern, pattern_end);\r
+  CHECK_NULL_RETURN_MEMERR(s);\r
+\r
+  ext->pattern     = s;\r
+  ext->pattern_end = s + (pattern_end - pattern);\r
+\r
+  return ONIG_NORMAL;\r
+}\r
 \r
 \r
 extern void\r
@@ -5207,11 +5901,12 @@ onig_free_body(regex_t* reg)
     if (IS_NOT_NULL(reg->int_map))          xfree(reg->int_map);\r
     if (IS_NOT_NULL(reg->int_map_backward)) xfree(reg->int_map_backward);\r
     if (IS_NOT_NULL(reg->repeat_range))     xfree(reg->repeat_range);\r
-    if (IS_NOT_NULL(reg->chain))            onig_free(reg->chain);\r
+    if (IS_NOT_NULL(REG_EXTP(reg))) {\r
+      free_regex_ext(REG_EXTP(reg));\r
+      REG_EXTPL(reg) = 0;\r
+    }\r
 \r
-#ifdef USE_NAMED_GROUP\r
     onig_names_free(reg);\r
-#endif\r
   }\r
 }\r
 \r
@@ -5225,7 +5920,6 @@ onig_free(regex_t* reg)
 }\r
 \r
 #define REGEX_TRANSFER(to,from) do {\\r
-  (to)->state = ONIG_STATE_MODIFY;\\r
   onig_free_body(to);\\r
   xmemcpy(to, from, sizeof(regex_t));\\r
   xfree(from);\\r
@@ -5234,76 +5928,41 @@ onig_free(regex_t* reg)
 extern void\r
 onig_transfer(regex_t* to, regex_t* from)\r
 {\r
-  THREAD_ATOMIC_START;\r
   REGEX_TRANSFER(to, from);\r
-  THREAD_ATOMIC_END;\r
-}\r
-\r
-#define REGEX_CHAIN_HEAD(reg) do {\\r
-  while (IS_NOT_NULL((reg)->chain)) {\\r
-    (reg) = (reg)->chain;\\r
-  }\\r
-} while (0)\r
-\r
-extern void\r
-onig_chain_link_add(regex_t* to, regex_t* add)\r
-{\r
-  THREAD_ATOMIC_START;\r
-  REGEX_CHAIN_HEAD(to);\r
-  to->chain = add;\r
-  THREAD_ATOMIC_END;\r
 }\r
 \r
-extern void\r
-onig_chain_reduce(regex_t* reg)\r
-{\r
-  regex_t *head, *prev;\r
-\r
-  prev = reg;\r
-  head = prev->chain;\r
-  if (IS_NOT_NULL(head)) {\r
-    reg->state = ONIG_STATE_MODIFY;\r
-    while (IS_NOT_NULL(head->chain)) {\r
-      prev = head;\r
-      head = head->chain;\r
-    }\r
-    prev->chain = (regex_t* )NULL;\r
-    REGEX_TRANSFER(reg, head);\r
-  }\r
-}\r
 \r
-#ifdef ONIG_DEBUG\r
-static void print_compiled_byte_code_list P_((FILE* f, regex_t* reg));\r
-#endif\r
-#ifdef ONIG_DEBUG_PARSE_TREE\r
+#ifdef ONIG_DEBUG_PARSE\r
 static void print_tree P_((FILE* f, Node* node));\r
 #endif\r
 \r
 extern int\r
 onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end,\r
-             OnigErrorInfo* einfo)\r
+             OnigErrorInfo* einfo)\r
 {\r
 #define COMPILE_INIT_SIZE  20\r
 \r
   int r, init_size;\r
   Node*  root;\r
   ScanEnv  scan_env;\r
-#ifdef USE_SUBEXP_CALL\r
+#ifdef USE_CALL\r
   UnsetAddrList  uslist;\r
 #endif\r
 \r
-  if (IS_NOT_NULL(einfo)) einfo->par = (UChar* )NULL;\r
-\r
-  reg->state = ONIG_STATE_COMPILING;\r
+  root = 0;\r
+  if (IS_NOT_NULL(einfo)) {\r
+    einfo->enc = reg->enc;\r
+    einfo->par = (UChar* )NULL;\r
+  }\r
 \r
 #ifdef ONIG_DEBUG\r
   print_enc_string(stderr, reg->enc, pattern, pattern_end);\r
 #endif\r
 \r
   if (reg->alloc == 0) {\r
-    init_size = ((int)(pattern_end - pattern)) * 2;\r
+    init_size = (int )(pattern_end - pattern) * 2;\r
     if (init_size <= 0) init_size = COMPILE_INIT_SIZE;\r
-    r = BBUF_INIT(reg, init_size);\r
+    r = BB_INIT(reg, init_size);\r
     if (r != 0) goto end;\r
   }\r
   else\r
@@ -5314,18 +5973,14 @@ onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end,
   reg->num_null_check     = 0;\r
   reg->repeat_range_alloc = 0;\r
   reg->repeat_range       = (OnigRepeatRange* )NULL;\r
-#ifdef USE_COMBINATION_EXPLOSION_CHECK\r
-  reg->num_comb_exp_check = 0;\r
-#endif\r
 \r
-  r = onig_parse_make_tree(&root, pattern, pattern_end, reg, &scan_env);\r
-  if (r != 0 || root == NULL) goto err;\r
+  r = onig_parse_tree(&root, pattern, pattern_end, reg, &scan_env);\r
+  if (r != 0) goto err;\r
 \r
-#ifdef USE_NAMED_GROUP\r
   /* mixed use named group and no-named group */\r
   if (scan_env.num_named > 0 &&\r
       IS_SYNTAX_BV(scan_env.syntax, ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP) &&\r
-      !ONIG_IS_OPTION_ON(reg->options, ONIG_OPTION_CAPTURE_GROUP)) {\r
+      ! ONIG_IS_OPTION_ON(reg->options, ONIG_OPTION_CAPTURE_GROUP)) {\r
     if (scan_env.num_named != scan_env.num_mem)\r
       r = disable_noname_group_capture(&root, reg, &scan_env);\r
     else\r
@@ -5333,30 +5988,34 @@ onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end,
 \r
     if (r != 0) goto err;\r
   }\r
-#endif\r
 \r
-#ifdef USE_SUBEXP_CALL\r
+  r = check_backrefs(root, &scan_env);\r
+  if (r != 0) goto err;\r
+\r
+#ifdef USE_CALL\r
   if (scan_env.num_call > 0) {\r
     r = unset_addr_list_init(&uslist, scan_env.num_call);\r
     if (r != 0) goto err;\r
     scan_env.unset_addr_list = &uslist;\r
-    r = setup_subexp_call(root, &scan_env);\r
+    r = setup_call(root, &scan_env, 0);\r
+    if (r != 0) goto err_unset;\r
+    r = setup_call2(root);\r
     if (r != 0) goto err_unset;\r
-    r = subexp_recursive_check_trav(root, &scan_env);\r
+    r = recursive_call_check_trav(root, &scan_env, 0);\r
     if (r  < 0) goto err_unset;\r
-    r = subexp_inf_recursive_check_trav(root, &scan_env);\r
+    r = infinite_recursive_call_check_trav(root, &scan_env);\r
     if (r != 0) goto err_unset;\r
 \r
-    reg->num_call = scan_env.num_call;\r
+    setup_called_state(root, 0);\r
   }\r
-  else\r
-    reg->num_call = 0;\r
+\r
+  reg->num_call = scan_env.num_call;\r
 #endif\r
 \r
   r = setup_tree(root, reg, 0, &scan_env);\r
   if (r != 0) goto err_unset;\r
 \r
-#ifdef ONIG_DEBUG_PARSE_TREE\r
+#ifdef ONIG_DEBUG_PARSE\r
   print_tree(stderr, root);\r
 #endif\r
 \r
@@ -5364,38 +6023,12 @@ onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end,
   reg->bt_mem_start     = scan_env.bt_mem_start;\r
   reg->bt_mem_start    |= reg->capture_history;\r
   if (IS_FIND_CONDITION(reg->options))\r
-    BIT_STATUS_ON_ALL(reg->bt_mem_end);\r
+    MEM_STATUS_ON_ALL(reg->bt_mem_end);\r
   else {\r
     reg->bt_mem_end  = scan_env.bt_mem_end;\r
     reg->bt_mem_end |= reg->capture_history;\r
   }\r
-\r
-#ifdef USE_COMBINATION_EXPLOSION_CHECK\r
-  if (scan_env.backrefed_mem == 0\r
-#ifdef USE_SUBEXP_CALL\r
-      || scan_env.num_call == 0\r
-#endif\r
-      ) {\r
-    setup_comb_exp_check(root, 0, &scan_env);\r
-#ifdef USE_SUBEXP_CALL\r
-    if (scan_env.has_recursion != 0) {\r
-      scan_env.num_comb_exp_check = 0;\r
-    }\r
-    else\r
-#endif\r
-    if (scan_env.comb_exp_max_regnum > 0) {\r
-      int i;\r
-      for (i = 1; i <= scan_env.comb_exp_max_regnum; i++) {\r
-       if (BIT_STATUS_AT(scan_env.backrefed_mem, i) != 0) {\r
-         scan_env.num_comb_exp_check = 0;\r
-         break;\r
-       }\r
-      }\r
-    }\r
-  }\r
-\r
-  reg->num_comb_exp_check = scan_env.num_comb_exp_check;\r
-#endif\r
+  reg->bt_mem_start |= reg->bt_mem_end;\r
 \r
   clear_optimize_info(reg);\r
 #ifndef ONIG_DONT_OPTIMIZE\r
@@ -5403,32 +6036,45 @@ onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end,
   if (r != 0) goto err_unset;\r
 #endif\r
 \r
-  if (IS_NOT_NULL(scan_env.mem_nodes_dynamic)) {\r
-    xfree(scan_env.mem_nodes_dynamic);\r
-    scan_env.mem_nodes_dynamic = (Node** )NULL;\r
+  if (IS_NOT_NULL(scan_env.mem_env_dynamic)) {\r
+    xfree(scan_env.mem_env_dynamic);\r
+    scan_env.mem_env_dynamic = (MemEnv* )NULL;\r
   }\r
 \r
-  r = compile_tree(root, reg);\r
+  r = compile_tree(root, reg, &scan_env);\r
   if (r == 0) {\r
+    if (scan_env.keep_num > 0) {\r
+      r = add_opcode(reg, OP_UPDATE_VAR);\r
+      if (r != 0) goto err;\r
+      r = add_update_var_type(reg, UPDATE_VAR_KEEP_FROM_STACK_LAST);\r
+      if (r != 0) goto err;\r
+      r = add_mem_num(reg, 0 /* not used */);\r
+      if (r != 0) goto err;\r
+    }\r
+\r
     r = add_opcode(reg, OP_END);\r
-#ifdef USE_SUBEXP_CALL\r
+#ifdef USE_CALL\r
     if (scan_env.num_call > 0) {\r
-      r = unset_addr_list_fix(&uslist, reg);\r
+      r = fix_unset_addr_list(&uslist, reg);\r
       unset_addr_list_end(&uslist);\r
-      if (r) goto err;\r
+      if (r != 0) goto err;\r
     }\r
 #endif\r
 \r
-    if ((reg->num_repeat != 0) || (reg->bt_mem_end != 0))\r
+    if ((reg->num_repeat != 0) || (reg->bt_mem_end != 0)\r
+#ifdef USE_CALLOUT\r
+        || (IS_NOT_NULL(REG_EXTP(reg)) && REG_EXTP(reg)->callout_num != 0)\r
+#endif\r
+        )\r
       reg->stack_pop_level = STACK_POP_LEVEL_ALL;\r
     else {\r
       if (reg->bt_mem_start != 0)\r
-       reg->stack_pop_level = STACK_POP_LEVEL_MEM_START;\r
+        reg->stack_pop_level = STACK_POP_LEVEL_MEM_START;\r
       else\r
-       reg->stack_pop_level = STACK_POP_LEVEL_FREE;\r
+        reg->stack_pop_level = STACK_POP_LEVEL_FREE;\r
     }\r
   }\r
-#ifdef USE_SUBEXP_CALL\r
+#ifdef USE_CALL\r
   else if (scan_env.num_call > 0) {\r
     unset_addr_list_end(&uslist);\r
   }\r
@@ -5436,18 +6082,15 @@ onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end,
   onig_node_free(root);\r
 \r
 #ifdef ONIG_DEBUG_COMPILE\r
-#ifdef USE_NAMED_GROUP\r
   onig_print_names(stderr, reg);\r
-#endif\r
-  print_compiled_byte_code_list(stderr, reg);\r
+  onig_print_compiled_byte_code_list(stderr, reg);\r
 #endif\r
 \r
  end:\r
-  reg->state = ONIG_STATE_NORMAL;\r
   return r;\r
 \r
  err_unset:\r
-#ifdef USE_SUBEXP_CALL\r
+#ifdef USE_CALL\r
   if (scan_env.num_call > 0) {\r
     unset_addr_list_end(&uslist);\r
   }\r
@@ -5455,48 +6098,39 @@ onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end,
  err:\r
   if (IS_NOT_NULL(scan_env.error)) {\r
     if (IS_NOT_NULL(einfo)) {\r
-      einfo->enc     = scan_env.enc;\r
       einfo->par     = scan_env.error;\r
       einfo->par_end = scan_env.error_end;\r
     }\r
   }\r
 \r
   onig_node_free(root);\r
-  if (IS_NOT_NULL(scan_env.mem_nodes_dynamic))\r
-      xfree(scan_env.mem_nodes_dynamic);\r
+  if (IS_NOT_NULL(scan_env.mem_env_dynamic))\r
+      xfree(scan_env.mem_env_dynamic);\r
   return r;\r
 }\r
 \r
-#ifdef USE_RECOMPILE_API\r
+\r
+static int onig_inited = 0;\r
+\r
 extern int\r
-onig_recompile(regex_t* reg, const UChar* pattern, const UChar* pattern_end,\r
-           OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax,\r
-           OnigErrorInfo* einfo)\r
+onig_reg_init(regex_t* reg, OnigOptionType option, OnigCaseFoldType case_fold_flag,\r
+              OnigEncoding enc, OnigSyntaxType* syntax)\r
 {\r
   int r;\r
-  regex_t *new_reg;\r
 \r
-  r = onig_new(&new_reg, pattern, pattern_end, option, enc, syntax, einfo);\r
-  if (r) return r;\r
-  if (ONIG_STATE(reg) == ONIG_STATE_NORMAL) {\r
-    onig_transfer(reg, new_reg);\r
-  }\r
-  else {\r
-    onig_chain_link_add(reg, new_reg);\r
-  }\r
-  return 0;\r
-}\r
-#endif\r
+  xmemset(reg, 0, sizeof(*reg));\r
 \r
-static int onig_inited = 0;\r
+  if (onig_inited == 0) {\r
+#if 0\r
+    return ONIGERR_LIBRARY_IS_NOT_INITIALIZED;\r
+#else\r
+    r = onig_initialize(&enc, 1);\r
+    if (r != 0)\r
+      return ONIGERR_FAIL_TO_INITIALIZE;\r
 \r
-extern int\r
-onig_reg_init(regex_t* reg, OnigOptionType option,\r
-             OnigCaseFoldType case_fold_flag,\r
-             OnigEncoding enc, OnigSyntaxType* syntax)\r
-{\r
-  if (! onig_inited)\r
-    onig_init();\r
+    onig_warning("You didn't call onig_initialize() explicitly");\r
+#endif\r
+  }\r
 \r
   if (IS_NULL(reg))\r
     return ONIGERR_INVALID_ARGUMENT;\r
@@ -5509,8 +6143,6 @@ onig_reg_init(regex_t* reg, OnigOptionType option,
     return ONIGERR_INVALID_COMBINATION_OF_OPTIONS;\r
   }\r
 \r
-  (reg)->state = ONIG_STATE_MODIFY;\r
-\r
   if ((option & ONIG_OPTION_NEGATE_SINGLELINE) != 0) {\r
     option |= syntax->options;\r
     option &= ~ONIG_OPTION_SINGLELINE;\r
@@ -5525,7 +6157,7 @@ onig_reg_init(regex_t* reg, OnigOptionType option,
   (reg)->exact            = (UChar* )NULL;\r
   (reg)->int_map          = (int* )NULL;\r
   (reg)->int_map_backward = (int* )NULL;\r
-  (reg)->chain            = (regex_t* )NULL;\r
+  REG_EXTPL(reg) = NULL;\r
 \r
   (reg)->p                = (UChar* )NULL;\r
   (reg)->alloc            = 0;\r
@@ -5537,14 +6169,15 @@ onig_reg_init(regex_t* reg, OnigOptionType option,
 }\r
 \r
 extern int\r
-onig_new_without_alloc(regex_t* reg, const UChar* pattern,\r
-          const UChar* pattern_end, OnigOptionType option, OnigEncoding enc,\r
-          OnigSyntaxType* syntax, OnigErrorInfo* einfo)\r
+onig_new_without_alloc(regex_t* reg,\r
+                       const UChar* pattern, const UChar* pattern_end,\r
+                       OnigOptionType option, OnigEncoding enc,\r
+                       OnigSyntaxType* syntax, OnigErrorInfo* einfo)\r
 {\r
   int r;\r
 \r
   r = onig_reg_init(reg, option, ONIGENC_CASE_FOLD_DEFAULT, enc, syntax);\r
-  if (r) return r;\r
+  if (r != 0) return r;\r
 \r
   r = onig_compile(reg, pattern, pattern_end, einfo);\r
   return r;\r
@@ -5552,8 +6185,8 @@ onig_new_without_alloc(regex_t* reg, const UChar* pattern,
 \r
 extern int\r
 onig_new(regex_t** reg, const UChar* pattern, const UChar* pattern_end,\r
-         OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax,\r
-         OnigErrorInfo* einfo)\r
+         OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax,\r
+         OnigErrorInfo* einfo)\r
 {\r
   int r;\r
 \r
@@ -5561,10 +6194,10 @@ onig_new(regex_t** reg, const UChar* pattern, const UChar* pattern_end,
   if (IS_NULL(*reg)) return ONIGERR_MEMORY;\r
 \r
   r = onig_reg_init(*reg, option, ONIGENC_CASE_FOLD_DEFAULT, enc, syntax);\r
-  if (r) goto err;\r
+  if (r != 0) goto err;\r
 \r
   r = onig_compile(*reg, pattern, pattern_end, einfo);\r
-  if (r) {\r
+  if (r != 0) {\r
   err:\r
     onig_free(*reg);\r
     *reg = NULL;\r
@@ -5572,37 +6205,41 @@ onig_new(regex_t** reg, const UChar* pattern, const UChar* pattern_end,
   return r;\r
 }\r
 \r
-\r
 extern int\r
-onig_init(void)\r
+onig_initialize(OnigEncoding encodings[], int n)\r
 {\r
+  int i;\r
+  int r;\r
+\r
   if (onig_inited != 0)\r
     return 0;\r
 \r
-  THREAD_SYSTEM_INIT;\r
-  THREAD_ATOMIC_START;\r
+  onigenc_init();\r
 \r
   onig_inited = 1;\r
 \r
-  onigenc_init();\r
-  /* onigenc_set_default_caseconv_table((UChar* )0); */\r
-\r
-#ifdef ONIG_DEBUG_STATISTICS\r
-  onig_statistics_init();\r
-#endif\r
+  for (i = 0; i < n; i++) {\r
+    OnigEncoding enc = encodings[i];\r
+    r = onig_initialize_encoding(enc);\r
+    if (r != 0)\r
+      return r;\r
+  }\r
 \r
-  THREAD_ATOMIC_END;\r
-  return 0;\r
+  return ONIG_NORMAL;\r
 }\r
 \r
+typedef struct EndCallListItem {\r
+  struct EndCallListItem* next;\r
+  void (*func)(void);\r
+} EndCallListItemType;\r
 \r
-static OnigEndCallListItemType* EndCallTop;\r
+static EndCallListItemType* EndCallTop;\r
 \r
 extern void onig_add_end_call(void (*func)(void))\r
 {\r
-  OnigEndCallListItemType* item;\r
+  EndCallListItemType* item;\r
 \r
-  item = (OnigEndCallListItemType* )xmalloc(sizeof(*item));\r
+  item = (EndCallListItemType* )xmalloc(sizeof(*item));\r
   if (item == 0) return ;\r
 \r
   item->next = EndCallTop;\r
@@ -5614,7 +6251,7 @@ extern void onig_add_end_call(void (*func)(void))
 static void\r
 exec_end_call_list(void)\r
 {\r
-  OnigEndCallListItemType* prev;\r
+  EndCallListItemType* prev;\r
   void (*func)(void);\r
 \r
   while (EndCallTop != 0) {\r
@@ -5630,26 +6267,16 @@ exec_end_call_list(void)
 extern int\r
 onig_end(void)\r
 {\r
-  THREAD_ATOMIC_START;\r
-\r
   exec_end_call_list();\r
 \r
-#ifdef ONIG_DEBUG_STATISTICS\r
-  onig_print_statistics(stderr);\r
+#ifdef USE_CALLOUT\r
+  onig_global_callout_names_free();\r
 #endif\r
 \r
-#ifdef USE_SHARED_CCLASS_TABLE\r
-  onig_free_shared_cclass_table();\r
-#endif\r
-\r
-#ifdef USE_PARSE_TREE_NODE_RECYCLE\r
-  onig_free_node_list();\r
-#endif\r
+  onigenc_end();\r
 \r
   onig_inited = 0;\r
 \r
-  THREAD_ATOMIC_END;\r
-  THREAD_SYSTEM_END;\r
   return 0;\r
 }\r
 \r
@@ -5675,9 +6302,10 @@ onig_is_in_code_range(const UChar* p, OnigCodePoint code)
 }\r
 \r
 extern int\r
-onig_is_code_in_cc_len(int elen, OnigCodePoint code, CClassNode* cc)\r
+onig_is_code_in_cc_len(int elen, OnigCodePoint code, /* CClassNode* */ void* cc_arg)\r
 {\r
   int found;\r
+  CClassNode* cc = (CClassNode* )cc_arg;\r
 \r
   if (elen > 1 || (code >= SINGLE_BYTE_SIZE)) {\r
     if (IS_NULL(cc->mbuf)) {\r
@@ -5712,141 +6340,7 @@ onig_is_code_in_cc(OnigEncoding enc, OnigCodePoint code, CClassNode* cc)
 }\r
 \r
 \r
-#ifdef ONIG_DEBUG\r
-\r
-/* arguments type */\r
-#define ARG_SPECIAL     -1\r
-#define ARG_NON          0\r
-#define ARG_RELADDR      1\r
-#define ARG_ABSADDR      2\r
-#define ARG_LENGTH       3\r
-#define ARG_MEMNUM       4\r
-#define ARG_OPTION       5\r
-#define ARG_STATE_CHECK  6\r
-\r
-OnigOpInfoType OnigOpInfo[] = {\r
-  { OP_FINISH,            "finish",          ARG_NON },\r
-  { OP_END,               "end",             ARG_NON },\r
-  { OP_EXACT1,            "exact1",          ARG_SPECIAL },\r
-  { OP_EXACT2,            "exact2",          ARG_SPECIAL },\r
-  { OP_EXACT3,            "exact3",          ARG_SPECIAL },\r
-  { OP_EXACT4,            "exact4",          ARG_SPECIAL },\r
-  { OP_EXACT5,            "exact5",          ARG_SPECIAL },\r
-  { OP_EXACTN,            "exactn",          ARG_SPECIAL },\r
-  { OP_EXACTMB2N1,        "exactmb2-n1",     ARG_SPECIAL },\r
-  { OP_EXACTMB2N2,        "exactmb2-n2",     ARG_SPECIAL },\r
-  { OP_EXACTMB2N3,        "exactmb2-n3",     ARG_SPECIAL },\r
-  { OP_EXACTMB2N,         "exactmb2-n",      ARG_SPECIAL },\r
-  { OP_EXACTMB3N,         "exactmb3n"  ,     ARG_SPECIAL },\r
-  { OP_EXACTMBN,          "exactmbn",        ARG_SPECIAL },\r
-  { OP_EXACT1_IC,         "exact1-ic",       ARG_SPECIAL },\r
-  { OP_EXACTN_IC,         "exactn-ic",       ARG_SPECIAL },\r
-  { OP_CCLASS,            "cclass",          ARG_SPECIAL },\r
-  { OP_CCLASS_MB,         "cclass-mb",       ARG_SPECIAL },\r
-  { OP_CCLASS_MIX,        "cclass-mix",      ARG_SPECIAL },\r
-  { OP_CCLASS_NOT,        "cclass-not",      ARG_SPECIAL },\r
-  { OP_CCLASS_MB_NOT,     "cclass-mb-not",   ARG_SPECIAL },\r
-  { OP_CCLASS_MIX_NOT,    "cclass-mix-not",  ARG_SPECIAL },\r
-  { OP_CCLASS_NODE,       "cclass-node",     ARG_SPECIAL },\r
-  { OP_ANYCHAR,           "anychar",         ARG_NON },\r
-  { OP_ANYCHAR_ML,        "anychar-ml",      ARG_NON },\r
-  { OP_ANYCHAR_STAR,      "anychar*",        ARG_NON },\r
-  { OP_ANYCHAR_ML_STAR,   "anychar-ml*",     ARG_NON },\r
-  { OP_ANYCHAR_STAR_PEEK_NEXT, "anychar*-peek-next", ARG_SPECIAL },\r
-  { OP_ANYCHAR_ML_STAR_PEEK_NEXT, "anychar-ml*-peek-next", ARG_SPECIAL },\r
-  { OP_WORD,                "word",            ARG_NON },\r
-  { OP_NOT_WORD,            "not-word",        ARG_NON },\r
-  { OP_WORD_BOUND,          "word-bound",      ARG_NON },\r
-  { OP_NOT_WORD_BOUND,      "not-word-bound",  ARG_NON },\r
-  { OP_WORD_BEGIN,          "word-begin",      ARG_NON },\r
-  { OP_WORD_END,            "word-end",        ARG_NON },\r
-  { OP_BEGIN_BUF,           "begin-buf",       ARG_NON },\r
-  { OP_END_BUF,             "end-buf",         ARG_NON },\r
-  { OP_BEGIN_LINE,          "begin-line",      ARG_NON },\r
-  { OP_END_LINE,            "end-line",        ARG_NON },\r
-  { OP_SEMI_END_BUF,        "semi-end-buf",    ARG_NON },\r
-  { OP_BEGIN_POSITION,      "begin-position",  ARG_NON },\r
-  { OP_BACKREF1,            "backref1",             ARG_NON },\r
-  { OP_BACKREF2,            "backref2",             ARG_NON },\r
-  { OP_BACKREFN,            "backrefn",             ARG_MEMNUM  },\r
-  { OP_BACKREFN_IC,         "backrefn-ic",          ARG_SPECIAL },\r
-  { OP_BACKREF_MULTI,       "backref_multi",        ARG_SPECIAL },\r
-  { OP_BACKREF_MULTI_IC,    "backref_multi-ic",     ARG_SPECIAL },\r
-  { OP_BACKREF_WITH_LEVEL,    "backref_at_level",     ARG_SPECIAL },\r
-  { OP_MEMORY_START_PUSH,   "mem-start-push",       ARG_MEMNUM  },\r
-  { OP_MEMORY_START,        "mem-start",            ARG_MEMNUM  },\r
-  { OP_MEMORY_END_PUSH,     "mem-end-push",         ARG_MEMNUM  },\r
-  { OP_MEMORY_END_PUSH_REC, "mem-end-push-rec",     ARG_MEMNUM  },\r
-  { OP_MEMORY_END,          "mem-end",              ARG_MEMNUM  },\r
-  { OP_MEMORY_END_REC,      "mem-end-rec",          ARG_MEMNUM  },\r
-  { OP_SET_OPTION_PUSH,     "set-option-push",      ARG_OPTION  },\r
-  { OP_SET_OPTION,          "set-option",           ARG_OPTION  },\r
-  { OP_FAIL,                "fail",                 ARG_NON },\r
-  { OP_JUMP,                "jump",                 ARG_RELADDR },\r
-  { OP_PUSH,                "push",                 ARG_RELADDR },\r
-  { OP_POP,                 "pop",                  ARG_NON },\r
-  { OP_PUSH_OR_JUMP_EXACT1, "push-or-jump-e1",      ARG_SPECIAL },\r
-  { OP_PUSH_IF_PEEK_NEXT,   "push-if-peek-next",    ARG_SPECIAL },\r
-  { OP_REPEAT,              "repeat",               ARG_SPECIAL },\r
-  { OP_REPEAT_NG,           "repeat-ng",            ARG_SPECIAL },\r
-  { OP_REPEAT_INC,          "repeat-inc",           ARG_MEMNUM  },\r
-  { OP_REPEAT_INC_NG,       "repeat-inc-ng",        ARG_MEMNUM  },\r
-  { OP_REPEAT_INC_SG,       "repeat-inc-sg",        ARG_MEMNUM  },\r
-  { OP_REPEAT_INC_NG_SG,    "repeat-inc-ng-sg",     ARG_MEMNUM  },\r
-  { OP_NULL_CHECK_START,    "null-check-start",     ARG_MEMNUM  },\r
-  { OP_NULL_CHECK_END,      "null-check-end",       ARG_MEMNUM  },\r
-  { OP_NULL_CHECK_END_MEMST,"null-check-end-memst", ARG_MEMNUM  },\r
-  { OP_NULL_CHECK_END_MEMST_PUSH,"null-check-end-memst-push", ARG_MEMNUM  },\r
-  { OP_PUSH_POS,             "push-pos",             ARG_NON },\r
-  { OP_POP_POS,              "pop-pos",              ARG_NON },\r
-  { OP_PUSH_POS_NOT,         "push-pos-not",         ARG_RELADDR },\r
-  { OP_FAIL_POS,             "fail-pos",             ARG_NON },\r
-  { OP_PUSH_STOP_BT,         "push-stop-bt",         ARG_NON },\r
-  { OP_POP_STOP_BT,          "pop-stop-bt",          ARG_NON },\r
-  { OP_LOOK_BEHIND,          "look-behind",          ARG_SPECIAL },\r
-  { OP_PUSH_LOOK_BEHIND_NOT, "push-look-behind-not", ARG_SPECIAL },\r
-  { OP_FAIL_LOOK_BEHIND_NOT, "fail-look-behind-not", ARG_NON },\r
-  { OP_CALL,                 "call",                 ARG_ABSADDR },\r
-  { OP_RETURN,               "return",               ARG_NON },\r
-  { OP_STATE_CHECK_PUSH,         "state-check-push",         ARG_SPECIAL },\r
-  { OP_STATE_CHECK_PUSH_OR_JUMP, "state-check-push-or-jump", ARG_SPECIAL },\r
-  { OP_STATE_CHECK,              "state-check",              ARG_STATE_CHECK },\r
-  { OP_STATE_CHECK_ANYCHAR_STAR, "state-check-anychar*",     ARG_STATE_CHECK },\r
-  { OP_STATE_CHECK_ANYCHAR_ML_STAR,\r
-    "state-check-anychar-ml*", ARG_STATE_CHECK },\r
-  { -1, "", ARG_NON }\r
-};\r
-\r
-static char*\r
-op2name(int opcode)\r
-{\r
-  int i;\r
-\r
-  for (i = 0; OnigOpInfo[i].opcode >= 0; i++) {\r
-    if (opcode == OnigOpInfo[i].opcode)\r
-      return OnigOpInfo[i].name;\r
-  }\r
-  return "";\r
-}\r
-\r
-static int\r
-op2arg_type(int opcode)\r
-{\r
-  int i;\r
-\r
-  for (i = 0; OnigOpInfo[i].opcode >= 0; i++) {\r
-    if (opcode == OnigOpInfo[i].opcode)\r
-      return OnigOpInfo[i].arg_type;\r
-  }\r
-  return ARG_SPECIAL;\r
-}\r
-\r
-static void\r
-Indent(FILE* f, int indent)\r
-{\r
-  int i;\r
-  for (i = 0; i < indent; i++) putc(' ', f);\r
-}\r
+#ifdef ONIG_DEBUG_PARSE\r
 \r
 static void\r
 p_string(FILE* f, int len, UChar* s)\r
@@ -5856,288 +6350,19 @@ p_string(FILE* f, int len, UChar* s)
 }\r
 \r
 static void\r
-p_len_string(FILE* f, LengthType len, int mb_len, UChar* s)\r
-{\r
-  int x = len * mb_len;\r
-\r
-  fprintf(f, ":%d:", len);\r
-  while (x-- > 0) { fputc(*s++, f); }\r
-}\r
-\r
-extern void\r
-onig_print_compiled_byte_code(FILE* f, UChar* bp, UChar** nextp,\r
-                              OnigEncoding enc)\r
-{\r
-  int i, n, arg_type;\r
-  RelAddrType addr;\r
-  LengthType len;\r
-  MemNumType mem;\r
-  StateCheckNumType scn;\r
-  OnigCodePoint code;\r
-  UChar *q;\r
-\r
-  fprintf(f, "[%s", op2name(*bp));\r
-  arg_type = op2arg_type(*bp);\r
-  if (arg_type != ARG_SPECIAL) {\r
-    bp++;\r
-    switch (arg_type) {\r
-    case ARG_NON:\r
-      break;\r
-    case ARG_RELADDR:\r
-      GET_RELADDR_INC(addr, bp);\r
-      fprintf(f, ":(%d)", addr);\r
-      break;\r
-    case ARG_ABSADDR:\r
-      GET_ABSADDR_INC(addr, bp);\r
-      fprintf(f, ":(%d)", addr);\r
-      break;\r
-    case ARG_LENGTH:\r
-      GET_LENGTH_INC(len, bp);\r
-      fprintf(f, ":%d", len);\r
-      break;\r
-    case ARG_MEMNUM:\r
-      mem = *((MemNumType* )bp);\r
-      bp += SIZE_MEMNUM;\r
-      fprintf(f, ":%d", mem);\r
-      break;\r
-    case ARG_OPTION:\r
-      {\r
-       OnigOptionType option = *((OnigOptionType* )bp);\r
-       bp += SIZE_OPTION;\r
-       fprintf(f, ":%d", option);\r
-      }\r
-      break;\r
-\r
-    case ARG_STATE_CHECK:\r
-      scn = *((StateCheckNumType* )bp);\r
-      bp += SIZE_STATE_CHECK_NUM;\r
-      fprintf(f, ":%d", scn);\r
-      break;\r
-    }\r
-  }\r
-  else {\r
-    switch (*bp++) {\r
-    case OP_EXACT1:\r
-    case OP_ANYCHAR_STAR_PEEK_NEXT:\r
-    case OP_ANYCHAR_ML_STAR_PEEK_NEXT:\r
-      p_string(f, 1, bp++); break;\r
-    case OP_EXACT2:\r
-      p_string(f, 2, bp); bp += 2; break;\r
-    case OP_EXACT3:\r
-      p_string(f, 3, bp); bp += 3; break;\r
-    case OP_EXACT4:\r
-      p_string(f, 4, bp); bp += 4; break;\r
-    case OP_EXACT5:\r
-      p_string(f, 5, bp); bp += 5; break;\r
-    case OP_EXACTN:\r
-      GET_LENGTH_INC(len, bp);\r
-      p_len_string(f, len, 1, bp);\r
-      bp += len;\r
-      break;\r
-    \r
-    case OP_EXACTMB2N1:\r
-      p_string(f, 2, bp); bp += 2; break;\r
-    case OP_EXACTMB2N2:\r
-      p_string(f, 4, bp); bp += 4; break;\r
-    case OP_EXACTMB2N3:\r
-      p_string(f, 6, bp); bp += 6; break;\r
-    case OP_EXACTMB2N:\r
-      GET_LENGTH_INC(len, bp);\r
-      p_len_string(f, len, 2, bp);\r
-      bp += len * 2;\r
-      break;\r
-    case OP_EXACTMB3N:\r
-      GET_LENGTH_INC(len, bp);\r
-      p_len_string(f, len, 3, bp);\r
-      bp += len * 3;\r
-      break;\r
-    case OP_EXACTMBN:\r
-      {\r
-       int mb_len;\r
-      \r
-       GET_LENGTH_INC(mb_len, bp);\r
-       GET_LENGTH_INC(len, bp);\r
-       fprintf(f, ":%d:%d:", mb_len, len);\r
-       n = len * mb_len;\r
-       while (n-- > 0) { fputc(*bp++, f); }\r
-      }\r
-      break;\r
-\r
-    case OP_EXACT1_IC:\r
-      len = enclen(enc, bp);\r
-      p_string(f, len, bp);\r
-      bp += len;\r
-      break;\r
-    case OP_EXACTN_IC:\r
-      GET_LENGTH_INC(len, bp);\r
-      p_len_string(f, len, 1, bp);\r
-      bp += len;\r
-      break;\r
-\r
-    case OP_CCLASS:\r
-      n = bitset_on_num((BitSetRef )bp);\r
-      bp += SIZE_BITSET;\r
-      fprintf(f, ":%d", n);\r
-      break;\r
-\r
-    case OP_CCLASS_NOT:\r
-      n = bitset_on_num((BitSetRef )bp);\r
-      bp += SIZE_BITSET;\r
-      fprintf(f, ":%d", n);\r
-      break;\r
-\r
-    case OP_CCLASS_MB:\r
-    case OP_CCLASS_MB_NOT:\r
-      GET_LENGTH_INC(len, bp);\r
-      q = bp;\r
-#ifndef PLATFORM_UNALIGNED_WORD_ACCESS\r
-      ALIGNMENT_RIGHT(q);\r
-#endif\r
-      GET_CODE_POINT(code, q);\r
-      bp += len;\r
-      fprintf(f, ":%d:%d", (int )code, len);\r
-      break;\r
-\r
-    case OP_CCLASS_MIX:\r
-    case OP_CCLASS_MIX_NOT:\r
-      n = bitset_on_num((BitSetRef )bp);\r
-      bp += SIZE_BITSET;\r
-      GET_LENGTH_INC(len, bp);\r
-      q = bp;\r
-#ifndef PLATFORM_UNALIGNED_WORD_ACCESS\r
-      ALIGNMENT_RIGHT(q);\r
-#endif\r
-      GET_CODE_POINT(code, q);\r
-      bp += len;\r
-      fprintf(f, ":%d:%d:%d", n, (int )code, len);\r
-      break;\r
-\r
-    case OP_CCLASS_NODE:\r
-      {\r
-        CClassNode *cc;\r
-\r
-        GET_POINTER_INC(cc, bp);\r
-        n = bitset_on_num(cc->bs);\r
-        fprintf(f, ":%u:%d", (unsigned int )cc, n);\r
-      }\r
-      break;\r
-\r
-    case OP_BACKREFN_IC:\r
-      mem = *((MemNumType* )bp);\r
-      bp += SIZE_MEMNUM;\r
-      fprintf(f, ":%d", mem);\r
-      break;\r
-\r
-    case OP_BACKREF_MULTI_IC:\r
-    case OP_BACKREF_MULTI:\r
-      fputs(" ", f);\r
-      GET_LENGTH_INC(len, bp);\r
-      for (i = 0; i < len; i++) {\r
-       GET_MEMNUM_INC(mem, bp);\r
-       if (i > 0) fputs(", ", f);\r
-       fprintf(f, "%d", mem);\r
-      }\r
-      break;\r
-\r
-    case OP_BACKREF_WITH_LEVEL:\r
-      {\r
-       OnigOptionType option;\r
-       LengthType level;\r
-\r
-       GET_OPTION_INC(option, bp);\r
-       fprintf(f, ":%d", option);\r
-       GET_LENGTH_INC(level, bp);\r
-       fprintf(f, ":%d", level);\r
-\r
-       fputs(" ", f);\r
-       GET_LENGTH_INC(len, bp);\r
-       for (i = 0; i < len; i++) {\r
-         GET_MEMNUM_INC(mem, bp);\r
-         if (i > 0) fputs(", ", f);\r
-         fprintf(f, "%d", mem);\r
-       }\r
-      }\r
-      break;\r
-\r
-    case OP_REPEAT:\r
-    case OP_REPEAT_NG:\r
-      {\r
-       mem = *((MemNumType* )bp);\r
-       bp += SIZE_MEMNUM;\r
-       addr = *((RelAddrType* )bp);\r
-       bp += SIZE_RELADDR;\r
-       fprintf(f, ":%d:%d", mem, addr);\r
-      }\r
-      break;\r
-\r
-    case OP_PUSH_OR_JUMP_EXACT1:\r
-    case OP_PUSH_IF_PEEK_NEXT:\r
-      addr = *((RelAddrType* )bp);\r
-      bp += SIZE_RELADDR;\r
-      fprintf(f, ":(%d)", addr);\r
-      p_string(f, 1, bp);\r
-      bp += 1;\r
-      break;\r
-\r
-    case OP_LOOK_BEHIND:\r
-      GET_LENGTH_INC(len, bp);\r
-      fprintf(f, ":%d", len);\r
-      break;\r
-\r
-    case OP_PUSH_LOOK_BEHIND_NOT:\r
-      GET_RELADDR_INC(addr, bp);\r
-      GET_LENGTH_INC(len, bp);\r
-      fprintf(f, ":%d:(%d)", len, addr);\r
-      break;\r
-\r
-    case OP_STATE_CHECK_PUSH:\r
-    case OP_STATE_CHECK_PUSH_OR_JUMP:\r
-      scn = *((StateCheckNumType* )bp);\r
-      bp += SIZE_STATE_CHECK_NUM;\r
-      addr = *((RelAddrType* )bp);\r
-      bp += SIZE_RELADDR;\r
-      fprintf(f, ":%d:(%d)", scn, addr);\r
-      break;\r
-\r
-    default:\r
-      fprintf(stderr, "onig_print_compiled_byte_code: undefined code %d\n",\r
-             *--bp);\r
-    }\r
-  }\r
-  fputs("]", f);\r
-  if (nextp) *nextp = bp;\r
-}\r
-\r
-static void\r
-print_compiled_byte_code_list(FILE* f, regex_t* reg)\r
+Indent(FILE* f, int indent)\r
 {\r
-  int ncode;\r
-  UChar* bp = reg->p;\r
-  UChar* end = reg->p + reg->used;\r
-\r
-  fprintf(f, "code length: %d\n", reg->used);\r
-\r
-  ncode = 0;\r
-  while (bp < end) {\r
-    ncode++;\r
-    if (bp > reg->p) {\r
-      if (ncode % 5 == 0)\r
-       fprintf(f, "\n");\r
-      else\r
-       fputs(" ", f);\r
-    }\r
-    onig_print_compiled_byte_code(f, bp, &bp, reg->enc);\r
-  }\r
-\r
-  fprintf(f, "\n");\r
+  int i;\r
+  for (i = 0; i < indent; i++) putc(' ', f);\r
 }\r
 \r
 static void\r
 print_indent_tree(FILE* f, Node* node, int indent)\r
 {\r
-  int i, type;\r
-  int add = 3;\r
+  int i;\r
+  NodeType type;\r
   UChar* p;\r
+  int add = 3;\r
 \r
   Indent(f, indent);\r
   if (IS_NULL(node)) {\r
@@ -6145,57 +6370,64 @@ print_indent_tree(FILE* f, Node* node, int indent)
     exit (0);\r
   }\r
 \r
-  type = NTYPE(node);\r
+  type = NODE_TYPE(node);\r
   switch (type) {\r
-  case NT_LIST:\r
-  case NT_ALT:\r
-    if (NTYPE(node) == NT_LIST)\r
-      fprintf(f, "<list:%x>\n", (int )node);\r
+  case NODE_LIST:\r
+  case NODE_ALT:\r
+    if (type == NODE_LIST)\r
+      fprintf(f, "<list:%p>\n", node);\r
     else\r
-      fprintf(f, "<alt:%x>\n", (int )node);\r
+      fprintf(f, "<alt:%p>\n", node);\r
 \r
-    print_indent_tree(f, NCAR(node), indent + add);\r
-    while (IS_NOT_NULL(node = NCDR(node))) {\r
-      if (NTYPE(node) != type) {\r
-       fprintf(f, "ERROR: list/alt right is not a cons. %d\n", NTYPE(node));\r
-       exit(0);\r
+    print_indent_tree(f, NODE_CAR(node), indent + add);\r
+    while (IS_NOT_NULL(node = NODE_CDR(node))) {\r
+      if (NODE_TYPE(node) != type) {\r
+        fprintf(f, "ERROR: list/alt right is not a cons. %d\n", NODE_TYPE(node));\r
+        exit(0);\r
       }\r
-      print_indent_tree(f, NCAR(node), indent + add);\r
+      print_indent_tree(f, NODE_CAR(node), indent + add);\r
     }\r
     break;\r
 \r
-  case NT_STR:\r
-    fprintf(f, "<string%s:%x>",\r
-           (NSTRING_IS_RAW(node) ? "-raw" : ""), (int )node);\r
-    for (p = NSTR(node)->s; p < NSTR(node)->end; p++) {\r
+  case NODE_STRING:\r
+    fprintf(f, "<string%s:%p>", (NODE_STRING_IS_RAW(node) ? "-raw" : ""), node);\r
+    for (p = STR_(node)->s; p < STR_(node)->end; p++) {\r
       if (*p >= 0x20 && *p < 0x7f)\r
-       fputc(*p, f);\r
+        fputc(*p, f);\r
       else {\r
-       fprintf(f, " 0x%02x", *p);\r
+        fprintf(f, " 0x%02x", *p);\r
       }\r
     }\r
     break;\r
 \r
-  case NT_CCLASS:\r
-    fprintf(f, "<cclass:%x>", (int )node);\r
-    if (IS_NCCLASS_NOT(NCCLASS(node))) fputs(" not", f);\r
-    if (NCCLASS(node)->mbuf) {\r
-      BBuf* bbuf = NCCLASS(node)->mbuf;\r
+  case NODE_CCLASS:\r
+    fprintf(f, "<cclass:%p>", node);\r
+    if (IS_NCCLASS_NOT(CCLASS_(node))) fputs(" not", f);\r
+    if (CCLASS_(node)->mbuf) {\r
+      BBuf* bbuf = CCLASS_(node)->mbuf;\r
       for (i = 0; i < bbuf->used; i++) {\r
-       if (i > 0) fprintf(f, ",");\r
-       fprintf(f, "%0x", bbuf->p[i]);\r
+        if (i > 0) fprintf(f, ",");\r
+        fprintf(f, "%0x", bbuf->p[i]);\r
       }\r
     }\r
     break;\r
 \r
-  case NT_CTYPE:\r
-    fprintf(f, "<ctype:%x> ", (int )node);\r
-    switch (NCTYPE(node)->ctype) {\r
+  case NODE_CTYPE:\r
+    fprintf(f, "<ctype:%p> ", node);\r
+    switch (CTYPE_(node)->ctype) {\r
+    case CTYPE_ANYCHAR:\r
+      fprintf(f, "<anychar:%p>", node);\r
+      break;\r
+\r
     case ONIGENC_CTYPE_WORD:\r
-      if (NCTYPE(node)->not != 0)\r
-       fputs("not word",       f);\r
+      if (CTYPE_(node)->not != 0)\r
+        fputs("not word", f);\r
       else\r
-       fputs("word",           f);\r
+        fputs("word",     f);\r
+\r
+      if (CTYPE_(node)->ascii_mode != 0)\r
+        fputs(" (ascii)", f);\r
+\r
       break;\r
 \r
     default:\r
@@ -6204,30 +6436,42 @@ print_indent_tree(FILE* f, Node* node, int indent)
     }\r
     break;\r
 \r
-  case NT_CANY:\r
-    fprintf(f, "<anychar:%x>", (int )node);\r
-    break;\r
-\r
-  case NT_ANCHOR:\r
-    fprintf(f, "<anchor:%x> ", (int )node);\r
-    switch (NANCHOR(node)->type) {\r
-    case ANCHOR_BEGIN_BUF:      fputs("begin buf",      f); break;\r
-    case ANCHOR_END_BUF:        fputs("end buf",        f); break;\r
-    case ANCHOR_BEGIN_LINE:     fputs("begin line",     f); break;\r
-    case ANCHOR_END_LINE:       fputs("end line",       f); break;\r
-    case ANCHOR_SEMI_END_BUF:   fputs("semi end buf",   f); break;\r
-    case ANCHOR_BEGIN_POSITION: fputs("begin position", f); break;\r
+  case NODE_ANCHOR:\r
+    fprintf(f, "<anchor:%p> ", node);\r
+    switch (ANCHOR_(node)->type) {\r
+    case ANCHOR_BEGIN_BUF:        fputs("begin buf",      f); break;\r
+    case ANCHOR_END_BUF:          fputs("end buf",        f); break;\r
+    case ANCHOR_BEGIN_LINE:       fputs("begin line",     f); break;\r
+    case ANCHOR_END_LINE:         fputs("end line",       f); break;\r
+    case ANCHOR_SEMI_END_BUF:     fputs("semi end buf",   f); break;\r
+    case ANCHOR_BEGIN_POSITION:   fputs("begin position", f); break;\r
 \r
-    case ANCHOR_WORD_BOUND:      fputs("word bound",     f); break;\r
-    case ANCHOR_NOT_WORD_BOUND:  fputs("not word bound", f); break;\r
+    case ANCHOR_WORD_BOUNDARY:    fputs("word boundary",     f); break;\r
+    case ANCHOR_NO_WORD_BOUNDARY: fputs("not word boundary", f); break;\r
 #ifdef USE_WORD_BEGIN_END\r
-    case ANCHOR_WORD_BEGIN:      fputs("word begin", f);     break;\r
-    case ANCHOR_WORD_END:        fputs("word end", f);       break;\r
+    case ANCHOR_WORD_BEGIN:       fputs("word begin", f);     break;\r
+    case ANCHOR_WORD_END:         fputs("word end", f);       break;\r
 #endif\r
-    case ANCHOR_PREC_READ:       fputs("prec read",      f); break;\r
-    case ANCHOR_PREC_READ_NOT:   fputs("prec read not",  f); break;\r
-    case ANCHOR_LOOK_BEHIND:     fputs("look_behind",    f); break;\r
-    case ANCHOR_LOOK_BEHIND_NOT: fputs("look_behind_not",f); break;\r
+    case ANCHOR_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY:\r
+      fputs("extended-grapheme-cluster boundary", f); break;\r
+    case ANCHOR_NO_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY:\r
+      fputs("no-extended-grapheme-cluster boundary", f); break;\r
+    case ANCHOR_PREC_READ:\r
+      fprintf(f, "prec read\n");\r
+      print_indent_tree(f, NODE_BODY(node), indent + add);\r
+      break;\r
+    case ANCHOR_PREC_READ_NOT:\r
+      fprintf(f, "prec read not\n");\r
+      print_indent_tree(f, NODE_BODY(node), indent + add);\r
+      break;\r
+    case ANCHOR_LOOK_BEHIND:\r
+      fprintf(f, "look behind\n");\r
+      print_indent_tree(f, NODE_BODY(node), indent + add);\r
+      break;\r
+    case ANCHOR_LOOK_BEHIND_NOT:\r
+      fprintf(f, "look behind not\n");\r
+      print_indent_tree(f, NODE_BODY(node), indent + add);\r
+      break;\r
 \r
     default:\r
       fprintf(f, "ERROR: undefined anchor type.\n");\r
@@ -6235,46 +6479,46 @@ print_indent_tree(FILE* f, Node* node, int indent)
     }\r
     break;\r
 \r
-  case NT_BREF:\r
+  case NODE_BACKREF:\r
     {\r
       int* p;\r
-      BRefNode* br = NBREF(node);\r
+      BackRefNode* br = BACKREF_(node);\r
       p = BACKREFS_P(br);\r
-      fprintf(f, "<backref:%x>", (int )node);\r
+      fprintf(f, "<backref%s:%p>", NODE_IS_CHECKER(node) ? "-checker" : "", node);\r
       for (i = 0; i < br->back_num; i++) {\r
-       if (i > 0) fputs(", ", f);\r
-       fprintf(f, "%d", p[i]);\r
+        if (i > 0) fputs(", ", f);\r
+        fprintf(f, "%d", p[i]);\r
       }\r
     }\r
     break;\r
 \r
-#ifdef USE_SUBEXP_CALL\r
-  case NT_CALL:\r
+#ifdef USE_CALL\r
+  case NODE_CALL:\r
     {\r
-      CallNode* cn = NCALL(node);\r
-      fprintf(f, "<call:%x>", (int )node);\r
+      CallNode* cn = CALL_(node);\r
+      fprintf(f, "<call:%p>", node);\r
       p_string(f, cn->name_end - cn->name, cn->name);\r
     }\r
     break;\r
 #endif\r
 \r
-  case NT_QTFR:\r
-    fprintf(f, "<quantifier:%x>{%d,%d}%s\n", (int )node,\r
-           NQTFR(node)->lower, NQTFR(node)->upper,\r
-           (NQTFR(node)->greedy ? "" : "?"));\r
-    print_indent_tree(f, NQTFR(node)->target, indent + add);\r
+  case NODE_QUANT:\r
+    fprintf(f, "<quantifier:%p>{%d,%d}%s\n", node,\r
+            QUANT_(node)->lower, QUANT_(node)->upper,\r
+            (QUANT_(node)->greedy ? "" : "?"));\r
+    print_indent_tree(f, NODE_BODY(node), indent + add);\r
     break;\r
 \r
-  case NT_ENCLOSE:\r
-    fprintf(f, "<enclose:%x> ", (int )node);\r
-    switch (NENCLOSE(node)->type) {\r
-    case ENCLOSE_OPTION:\r
-      fprintf(f, "option:%d", NENCLOSE(node)->option);\r
+  case NODE_ENCLOSURE:\r
+    fprintf(f, "<enclosure:%p> ", node);\r
+    switch (ENCLOSURE_(node)->type) {\r
+    case ENCLOSURE_OPTION:\r
+      fprintf(f, "option:%d", ENCLOSURE_(node)->o.options);\r
       break;\r
-    case ENCLOSE_MEMORY:\r
-      fprintf(f, "memory:%d", NENCLOSE(node)->regnum);\r
+    case ENCLOSURE_MEMORY:\r
+      fprintf(f, "memory:%d", ENCLOSURE_(node)->m.regnum);\r
       break;\r
-    case ENCLOSE_STOP_BACKTRACK:\r
+    case ENCLOSURE_STOP_BACKTRACK:\r
       fprintf(f, "stop-bt");\r
       break;\r
 \r
@@ -6282,22 +6526,49 @@ print_indent_tree(FILE* f, Node* node, int indent)
       break;\r
     }\r
     fprintf(f, "\n");\r
-    print_indent_tree(f, NENCLOSE(node)->target, indent + add);\r
+    print_indent_tree(f, NODE_BODY(node), indent + add);\r
+    break;\r
+\r
+  case NODE_GIMMICK:\r
+    fprintf(f, "<gimmick:%p> ", node);\r
+    switch (GIMMICK_(node)->type) {\r
+    case GIMMICK_FAIL:\r
+      fprintf(f, "fail");\r
+      break;\r
+    case GIMMICK_KEEP:\r
+      fprintf(f, "keep:%d", GIMMICK_(node)->id);\r
+      break;\r
+    case GIMMICK_SAVE:\r
+      fprintf(f, "save:%d:%d", GIMMICK_(node)->detail_type, GIMMICK_(node)->id);\r
+      break;\r
+    case GIMMICK_UPDATE_VAR:\r
+      fprintf(f, "update_var:%d:%d", GIMMICK_(node)->detail_type, GIMMICK_(node)->id);\r
+      break;\r
+#ifdef USE_CALLOUT\r
+    case GIMMICK_CALLOUT:\r
+      switch (GIMMICK_(node)->detail_type) {\r
+      case ONIG_CALLOUT_OF_CONTENTS:\r
+        fprintf(f, "callout:contents:%d", GIMMICK_(node)->num);\r
+        break;\r
+      case ONIG_CALLOUT_OF_NAME:\r
+        fprintf(f, "callout:name:%d:%d", GIMMICK_(node)->id, GIMMICK_(node)->num);\r
+        break;\r
+      }\r
+#endif\r
+    }\r
     break;\r
 \r
   default:\r
-    fprintf(f, "print_indent_tree: undefined node type %d\n", NTYPE(node));\r
+    fprintf(f, "print_indent_tree: undefined node type %d\n", NODE_TYPE(node));\r
     break;\r
   }\r
 \r
-  if (type != NT_LIST && type != NT_ALT && type != NT_QTFR &&\r
-      type != NT_ENCLOSE)\r
+  if (type != NODE_LIST && type != NODE_ALT && type != NODE_QUANT &&\r
+      type != NODE_ENCLOSURE)\r
     fprintf(f, "\n");\r
   fflush(f);\r
 }\r
-#endif /* ONIG_DEBUG */\r
 \r
-#ifdef ONIG_DEBUG_PARSE_TREE\r
 static void\r
 print_tree(FILE* f, Node* node)\r
 {\r