]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/RegularExpressionDxe/Oniguruma/regexec.c
MdeModulePkg RegularExpressionDxe: Update Oniguruma to 6.9.0
[mirror_edk2.git] / MdeModulePkg / Universal / RegularExpressionDxe / Oniguruma / regexec.c
index a175f3a6cc499c100d7cf44a32d15ea4e2298d26..7b0fda07f8966d0a43fc352b2f2fdc39a97286c1 100644 (file)
@@ -2,11 +2,9 @@
   regexec.c -  Oniguruma (regular expression library)\r
 **********************************************************************/\r
 /*-\r
- * Copyright (c) 2002-2008  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
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\r
  * SUCH DAMAGE.\r
  */\r
-\r
 #include "regint.h"\r
 \r
-#define USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE\r
+#define IS_MBC_WORD_ASCII_MODE(enc,s,end,mode) \\r
+  ((mode) == 0 ? ONIGENC_IS_MBC_WORD(enc,s,end) : ONIGENC_IS_MBC_WORD_ASCII(enc,s,end))\r
 \r
 #ifdef USE_CRNL_AS_LINE_TERMINATOR\r
 #define ONIGENC_IS_MBC_CRNL(enc,p,end) \\r
    ONIGENC_IS_MBC_NEWLINE(enc,(p+enclen(enc,p)),end))\r
 #endif\r
 \r
+#define CHECK_INTERRUPT_IN_MATCH\r
+\r
+#ifdef USE_CALLOUT\r
+typedef struct {\r
+  int last_match_at_call_counter;\r
+  struct {\r
+    OnigType  type;\r
+    OnigValue val;\r
+  } slot[ONIG_CALLOUT_DATA_SLOT_NUM];\r
+} CalloutData;\r
+#endif\r
+\r
+struct OnigMatchParamStruct {\r
+  unsigned int    match_stack_limit;\r
+  unsigned long   retry_limit_in_match;\r
+#ifdef USE_CALLOUT\r
+  OnigCalloutFunc progress_callout_of_contents;\r
+  OnigCalloutFunc retraction_callout_of_contents;\r
+  int             match_at_call_counter;\r
+  void*           callout_user_data;\r
+  CalloutData*    callout_data;\r
+  int             callout_data_alloc_num;\r
+#endif\r
+};\r
+\r
+extern int\r
+onig_set_match_stack_limit_size_of_match_param(OnigMatchParam* param,\r
+                                               unsigned int limit)\r
+{\r
+  param->match_stack_limit = limit;\r
+  return ONIG_NORMAL;\r
+}\r
+\r
+extern int\r
+onig_set_retry_limit_in_match_of_match_param(OnigMatchParam* param,\r
+                                             unsigned long limit)\r
+{\r
+  param->retry_limit_in_match = limit;\r
+  return ONIG_NORMAL;\r
+}\r
+\r
+extern int\r
+onig_set_progress_callout_of_match_param(OnigMatchParam* param, OnigCalloutFunc f)\r
+{\r
+#ifdef USE_CALLOUT\r
+  param->progress_callout_of_contents = f;\r
+  return ONIG_NORMAL;\r
+#else\r
+  return ONIG_NO_SUPPORT_CONFIG;\r
+#endif\r
+}\r
+\r
+extern int\r
+onig_set_retraction_callout_of_match_param(OnigMatchParam* param, OnigCalloutFunc f)\r
+{\r
+#ifdef USE_CALLOUT\r
+  param->retraction_callout_of_contents = f;\r
+  return ONIG_NORMAL;\r
+#else\r
+  return ONIG_NO_SUPPORT_CONFIG;\r
+#endif\r
+}\r
+\r
+extern int\r
+onig_set_callout_user_data_of_match_param(OnigMatchParam* param, void* user_data)\r
+{\r
+#ifdef USE_CALLOUT\r
+  param->callout_user_data = user_data;\r
+  return ONIG_NORMAL;\r
+#else\r
+  return ONIG_NO_SUPPORT_CONFIG;\r
+#endif\r
+}\r
+\r
+\r
+\r
+typedef struct {\r
+  void* stack_p;\r
+  int   stack_n;\r
+  OnigOptionType options;\r
+  OnigRegion*    region;\r
+  int            ptr_num;\r
+  const UChar*   start;   /* search start position (for \G: BEGIN_POSITION) */\r
+  unsigned int   match_stack_limit;\r
+  unsigned long  retry_limit_in_match;\r
+  OnigMatchParam* mp;\r
+#ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE\r
+  int    best_len;      /* for ONIG_OPTION_FIND_LONGEST */\r
+  UChar* best_s;\r
+#endif\r
+} MatchArg;\r
+\r
+\r
+#ifdef ONIG_DEBUG\r
+\r
+/* arguments type */\r
+typedef enum {\r
+  ARG_SPECIAL =  -1,\r
+  ARG_NON     =   0,\r
+  ARG_RELADDR =   1,\r
+  ARG_ABSADDR =   2,\r
+  ARG_LENGTH  =   3,\r
+  ARG_MEMNUM  =   4,\r
+  ARG_OPTION  =   5,\r
+  ARG_MODE    =   6\r
+} OpArgType;\r
+\r
+typedef struct {\r
+  short int opcode;\r
+  char*     name;\r
+  OpArgType arg_type;\r
+} OpInfoType;\r
+\r
+static OpInfoType OpInfo[] = {\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
+#ifdef USE_OP_CCLASS_NODE\r
+  { OP_CCLASS_NODE,       "cclass-node",     ARG_SPECIAL },\r
+#endif\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_WORD_ASCII,          "word-ascii",      ARG_NON },\r
+  { OP_NO_WORD,             "not-word",        ARG_NON },\r
+  { OP_NO_WORD_ASCII,       "not-word-ascii",  ARG_NON },\r
+  { OP_WORD_BOUNDARY,       "word-boundary",     ARG_MODE },\r
+  { OP_NO_WORD_BOUNDARY,    "not-word-boundary", ARG_MODE },\r
+  { OP_WORD_BEGIN,          "word-begin",      ARG_MODE },\r
+  { OP_WORD_END,            "word-end",        ARG_MODE },\r
+  { OP_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY, "extended-grapheme-cluster-boundary", ARG_NON },\r
+  { OP_NO_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY, "no-extended-grapheme-cluster-boundary", 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_BACKREF_N,            "backref-n",           ARG_MEMNUM  },\r
+  { OP_BACKREF_N_IC,         "backref-n-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_with_level",   ARG_SPECIAL },\r
+  { OP_BACKREF_CHECK,       "backref_check",        ARG_SPECIAL },\r
+  { OP_BACKREF_CHECK_WITH_LEVEL, "backref_check_with_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_FAIL,                "fail",                 ARG_NON },\r
+  { OP_JUMP,                "jump",                 ARG_RELADDR },\r
+  { OP_PUSH,                "push",                 ARG_RELADDR },\r
+  { OP_PUSH_SUPER,          "push-super",           ARG_RELADDR },\r
+  { OP_POP_OUT,             "pop-out",              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_EMPTY_CHECK_START,   "empty-check-start",    ARG_MEMNUM  },\r
+  { OP_EMPTY_CHECK_END,     "empty-check-end",      ARG_MEMNUM  },\r
+  { OP_EMPTY_CHECK_END_MEMST,"empty-check-end-memst", ARG_MEMNUM  },\r
+  { OP_EMPTY_CHECK_END_MEMST_PUSH,"empty-check-end-memst-push", ARG_MEMNUM  },\r
+  { OP_PREC_READ_START,      "push-pos",             ARG_NON },\r
+  { OP_PREC_READ_END,        "pop-pos",              ARG_NON },\r
+  { OP_PREC_READ_NOT_START,  "prec-read-not-start",  ARG_RELADDR },\r
+  { OP_PREC_READ_NOT_END,    "prec-read-not-end",    ARG_NON },\r
+  { OP_ATOMIC_START,         "atomic-start",         ARG_NON },\r
+  { OP_ATOMIC_END,           "atomic-end",           ARG_NON },\r
+  { OP_LOOK_BEHIND,          "look-behind",          ARG_SPECIAL },\r
+  { OP_LOOK_BEHIND_NOT_START, "look-behind-not-start", ARG_SPECIAL },\r
+  { OP_LOOK_BEHIND_NOT_END,  "look-behind-not-end",  ARG_NON },\r
+  { OP_CALL,                 "call",                 ARG_ABSADDR },\r
+  { OP_RETURN,               "return",               ARG_NON },\r
+  { OP_PUSH_SAVE_VAL,        "push-save-val",        ARG_SPECIAL },\r
+  { OP_UPDATE_VAR,           "update-var",           ARG_SPECIAL },\r
+#ifdef USE_CALLOUT\r
+  { OP_CALLOUT_CONTENTS,     "callout-contents",     ARG_SPECIAL },\r
+  { OP_CALLOUT_NAME,         "callout-name",         ARG_SPECIAL },\r
+#endif\r
+  { -1, "", ARG_NON }\r
+};\r
+\r
+static char*\r
+op2name(int opcode)\r
+{\r
+  int i;\r
+\r
+  for (i = 0; OpInfo[i].opcode >= 0; i++) {\r
+    if (opcode == OpInfo[i].opcode)\r
+      return OpInfo[i].name;\r
+  }\r
+  return "";\r
+}\r
+\r
+static int\r
+op2arg_type(int opcode)\r
+{\r
+  int i;\r
+\r
+  for (i = 0; OpInfo[i].opcode >= 0; i++) {\r
+    if (opcode == OpInfo[i].opcode)\r
+      return OpInfo[i].arg_type;\r
+  }\r
+  return ARG_SPECIAL;\r
+}\r
+\r
+static void\r
+p_string(FILE* f, int len, UChar* s)\r
+{\r
+  fputs(":", f);\r
+  while (len-- > 0) { fputc(*s++, f); }\r
+}\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
+static void\r
+p_rel_addr(FILE* f, RelAddrType rel_addr, UChar* p, UChar* start)\r
+{\r
+  RelAddrType curr = (RelAddrType )(p - start);\r
+\r
+  fprintf(f, "{%d/%d}", rel_addr, curr + rel_addr);\r
+}\r
+\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
+\r
+extern void\r
+onig_print_compiled_byte_code(FILE* f, UChar* bp, UChar** nextp, UChar* start,\r
+                              OnigEncoding enc)\r
+{\r
+  int i, n;\r
+  OpArgType   arg_type;\r
+  RelAddrType addr;\r
+  LengthType  len;\r
+  MemNumType  mem;\r
+  OnigCodePoint  code;\r
+  OnigOptionType option;\r
+  ModeType mode;\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
+      fputc(':', f);\r
+      p_rel_addr(f, addr, bp, start);\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
+    case ARG_MODE:\r
+      mode = *((ModeType* )bp);\r
+      bp += SIZE_MODE;\r
+      fprintf(f, ":%d", mode);\r
+      break;\r
+    default:\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
+#ifdef USE_OP_CCLASS_NODE\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, ":%p:%d", cc, n);\r
+      }\r
+      break;\r
+#endif\r
+\r
+    case OP_BACKREF_N_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
+    case OP_BACKREF_CHECK:\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
+      GET_OPTION_INC(option, bp);\r
+      fprintf(f, ":%d", option);\r
+      /* fall */\r
+    case OP_BACKREF_CHECK_WITH_LEVEL:\r
+      {\r
+        LengthType level;\r
+\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
+      fputc(':', f);\r
+      p_rel_addr(f, addr, bp, start);\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_LOOK_BEHIND_NOT_START:\r
+      GET_RELADDR_INC(addr, bp);\r
+      GET_LENGTH_INC(len, bp);\r
+      fprintf(f, ":%d:", len);\r
+      p_rel_addr(f, addr, bp, start);\r
+      break;\r
+\r
+    case OP_PUSH_SAVE_VAL:\r
+      {\r
+        SaveType type;\r
+        GET_SAVE_TYPE_INC(type, bp);\r
+        GET_MEMNUM_INC(mem, bp);\r
+        fprintf(f, ":%d:%d", type, mem);\r
+      }\r
+      break;\r
+\r
+    case OP_UPDATE_VAR:\r
+      {\r
+        UpdateVarType type;\r
+        GET_UPDATE_VAR_TYPE_INC(type, bp);\r
+        GET_MEMNUM_INC(mem, bp);\r
+        fprintf(f, ":%d:%d", type, mem);\r
+      }\r
+      break;\r
+\r
+#ifdef USE_CALLOUT\r
+    case OP_CALLOUT_CONTENTS:\r
+      {\r
+        GET_MEMNUM_INC(mem,  bp); /* number */\r
+        fprintf(f, ":%d", mem);\r
+      }\r
+      break;\r
+\r
+    case OP_CALLOUT_NAME:\r
+      {\r
+        int id;\r
+\r
+        GET_MEMNUM_INC(id,   bp); /* id */\r
+        GET_MEMNUM_INC(mem,  bp); /* number */\r
+\r
+        fprintf(f, ":%d:%d", id, mem);\r
+      }\r
+      break;\r
+#endif\r
+\r
+    default:\r
+      fprintf(stderr, "onig_print_compiled_byte_code: undefined code %d\n", *--bp);\r
+    }\r
+  }\r
+  if (nextp) *nextp = bp;\r
+}\r
+#endif /* ONIG_DEBUG */\r
+\r
+#ifdef ONIG_DEBUG_COMPILE\r
+extern void\r
+onig_print_compiled_byte_code_list(FILE* f, regex_t* reg)\r
+{\r
+  UChar* bp;\r
+  UChar* start = reg->p;\r
+  UChar* end   = reg->p + reg->used;\r
+\r
+  fprintf(f, "bt_mem_start: 0x%x, bt_mem_end: 0x%x\n",\r
+          reg->bt_mem_start, reg->bt_mem_end);\r
+  fprintf(f, "code-length: %d\n", reg->used);\r
+\r
+  bp = start;\r
+  while (bp < end) {\r
+    int pos = bp - start;\r
+\r
+    fprintf(f, "%4d: ", pos);\r
+    onig_print_compiled_byte_code(f, bp, &bp, start, reg->enc);\r
+    fprintf(f, "\n");\r
+  }\r
+  fprintf(f, "\n");\r
+}\r
+#endif\r
+\r
+\r
 #ifdef USE_CAPTURE_HISTORY\r
 static void history_tree_free(OnigCaptureTreeNode* node);\r
 \r
@@ -243,16 +821,15 @@ onig_region_new(void)
   OnigRegion* r;\r
 \r
   r = (OnigRegion* )xmalloc(sizeof(OnigRegion));\r
-  if (r != NULL) {\r
-    onig_region_init(r);\r
-  }\r
+  CHECK_NULL_RETURN(r);\r
+  onig_region_init(r);\r
   return r;\r
 }\r
 \r
 extern void\r
 onig_region_free(OnigRegion* r, int free_self)\r
 {\r
-  if (r) {\r
+  if (r != 0) {\r
     if (r->allocated > 0) {\r
       if (r->beg) xfree(r->beg);\r
       if (r->end) xfree(r->end);\r
@@ -276,20 +853,20 @@ onig_region_copy(OnigRegion* to, OnigRegion* from)
   if (to->allocated == 0) {\r
     if (from->num_regs > 0) {\r
       to->beg = (int* )xmalloc(RREGC_SIZE);\r
+      if (IS_NULL(to->beg)) return;\r
       to->end = (int* )xmalloc(RREGC_SIZE);\r
+      if (IS_NULL(to->end)) return;\r
       to->allocated = from->num_regs;\r
     }\r
   }\r
   else if (to->allocated < from->num_regs) {\r
     to->beg = (int* )xrealloc(to->beg, RREGC_SIZE, sizeof(int) * to->allocated);\r
+    if (IS_NULL(to->beg)) return;\r
     to->end = (int* )xrealloc(to->end, RREGC_SIZE, sizeof(int) * to->allocated);\r
+    if (IS_NULL(to->end)) return;\r
     to->allocated = from->num_regs;\r
   }\r
 \r
-  if (to->beg == NULL || to->end == NULL) {\r
-    return;\r
-  }\r
-\r
   for (i = 0; i < from->num_regs; i++) {\r
     to->beg[i] = from->beg[i];\r
     to->end[i] = from->end[i];\r
@@ -305,251 +882,604 @@ onig_region_copy(OnigRegion* to, OnigRegion* from)
 #endif\r
 }\r
 \r
+#ifdef USE_CALLOUT\r
+#define CALLOUT_BODY(func, ain, aname_id, anum, user, args, result) do { \\r
+  args.in            = (ain);\\r
+  args.name_id       = (aname_id);\\r
+  args.num           = anum;\\r
+  args.regex         = reg;\\r
+  args.string        = str;\\r
+  args.string_end    = end;\\r
+  args.start         = sstart;\\r
+  args.right_range   = right_range;\\r
+  args.current       = s;\\r
+  args.retry_in_match_counter = retry_in_match_counter;\\r
+  args.msa           = msa;\\r
+  args.stk_base      = stk_base;\\r
+  args.stk           = stk;\\r
+  args.mem_start_stk = mem_start_stk;\\r
+  args.mem_end_stk   = mem_end_stk;\\r
+  result = (func)(&args, user);\\r
+} while (0)\r
+\r
+#define RETRACTION_CALLOUT(func, aname_id, anum, user) do {\\r
+  int result;\\r
+  OnigCalloutArgs args;\\r
+  CALLOUT_BODY(func, ONIG_CALLOUT_IN_RETRACTION, aname_id, anum, user, args, result);\\r
+  switch (result) {\\r
+  case ONIG_CALLOUT_FAIL:\\r
+  case ONIG_CALLOUT_SUCCESS:\\r
+    break;\\r
+  default:\\r
+    if (result > 0) {\\r
+      result = ONIGERR_INVALID_ARGUMENT;\\r
+    }\\r
+    best_len = result;\\r
+    goto finish;\\r
+    break;\\r
+  }\\r
+} while(0)\r
+#endif\r
+\r
 \r
 /** stack **/\r
 #define INVALID_STACK_INDEX   -1\r
 \r
+#define STK_ALT_FLAG               0x0001\r
+\r
 /* stack type */\r
 /* used by normal-POP */\r
-#define STK_ALT                    0x0001\r
-#define STK_LOOK_BEHIND_NOT        0x0002\r
-#define STK_POS_NOT                0x0003\r
+#define STK_SUPER_ALT             STK_ALT_FLAG\r
+#define STK_ALT                   (0x0002 | STK_ALT_FLAG)\r
+#define STK_ALT_PREC_READ_NOT     (0x0004 | STK_ALT_FLAG)\r
+#define STK_ALT_LOOK_BEHIND_NOT   (0x0006 | STK_ALT_FLAG)\r
+\r
 /* handled by normal-POP */\r
-#define STK_MEM_START              0x0100\r
-#define STK_MEM_END                0x8200\r
-#define STK_REPEAT_INC             0x0300\r
-#define STK_STATE_CHECK_MARK       0x1000\r
+#define STK_MEM_START              0x0010\r
+#define STK_MEM_END                0x8030\r
+#define STK_REPEAT_INC             0x0050\r
+#ifdef USE_CALLOUT\r
+#define STK_CALLOUT                0x0070\r
+#endif\r
+\r
 /* avoided by normal-POP */\r
-#define STK_NULL_CHECK_START       0x3000\r
-#define STK_NULL_CHECK_END         0x5000  /* for recursive call */\r
-#define STK_MEM_END_MARK           0x8400\r
-#define STK_POS                    0x0500  /* used when POP-POS */\r
-#define STK_STOP_BT                0x0600  /* mark for "(?>...)" */\r
-#define STK_REPEAT                 0x0700\r
-#define STK_CALL_FRAME             0x0800\r
-#define STK_RETURN                 0x0900\r
-#define STK_VOID                   0x0a00  /* for fill a blank */\r
+#define STK_VOID                   0x0000  /* for fill a blank */\r
+#define STK_EMPTY_CHECK_START      0x3000\r
+#define STK_EMPTY_CHECK_END        0x5000  /* for recursive call */\r
+#define STK_MEM_END_MARK           0x8100\r
+#define STK_TO_VOID_START          0x1200  /* mark for "(?>...)" */\r
+#define STK_REPEAT                 0x0300\r
+#define STK_CALL_FRAME             0x0400\r
+#define STK_RETURN                 0x0500\r
+#define STK_SAVE_VAL               0x0600\r
 \r
 /* stack type check mask */\r
-#define STK_MASK_POP_USED          0x00ff\r
-#define STK_MASK_TO_VOID_TARGET    0x10ff\r
+#define STK_MASK_POP_USED          STK_ALT_FLAG\r
+#define STK_MASK_POP_HANDLED       0x0010\r
+#define STK_MASK_POP_HANDLED_TIL   (STK_MASK_POP_HANDLED | 0x0004)\r
+#define STK_MASK_TO_VOID_TARGET    0x100e\r
 #define STK_MASK_MEM_END_OR_MARK   0x8000  /* MEM_END or MEM_END_MARK */\r
 \r
+typedef intptr_t StackIndex;\r
+\r
+typedef struct _StackType {\r
+  unsigned int type;\r
+  int zid;\r
+  union {\r
+    struct {\r
+      UChar *pcode;      /* byte code position */\r
+      UChar *pstr;       /* string position */\r
+      UChar *pstr_prev;  /* previous char position of pstr */\r
+    } state;\r
+    struct {\r
+      int   count;       /* for OP_REPEAT_INC, OP_REPEAT_INC_NG */\r
+      UChar *pcode;      /* byte code position (head of repeated target) */\r
+    } repeat;\r
+    struct {\r
+      StackIndex si;     /* index of stack */\r
+    } repeat_inc;\r
+    struct {\r
+      UChar *pstr;       /* start/end position */\r
+      /* Following information is set, if this stack type is MEM-START */\r
+      StackIndex prev_start;  /* prev. info (for backtrack  "(...)*" ) */\r
+      StackIndex prev_end;    /* prev. info (for backtrack  "(...)*" ) */\r
+    } mem;\r
+    struct {\r
+      UChar *pstr;       /* start position */\r
+    } empty_check;\r
+#ifdef USE_CALL\r
+    struct {\r
+      UChar *ret_addr;   /* byte code position */\r
+      UChar *pstr;       /* string position */\r
+    } call_frame;\r
+#endif\r
+    struct {\r
+      enum SaveType type;\r
+      UChar* v;\r
+      UChar* v2;\r
+    } val;\r
+#ifdef USE_CALLOUT\r
+    struct {\r
+      int num;\r
+      OnigCalloutFunc func;\r
+    } callout;\r
+#endif\r
+  } u;\r
+} StackType;\r
+\r
+#ifdef USE_CALLOUT\r
+\r
+struct OnigCalloutArgsStruct {\r
+  OnigCalloutIn    in;\r
+  int              name_id;   /* name id or ONIG_NON_NAME_ID */\r
+  int              num;\r
+  OnigRegex        regex;\r
+  const OnigUChar* string;\r
+  const OnigUChar* string_end;\r
+  const OnigUChar* start;\r
+  const OnigUChar* right_range;\r
+  const OnigUChar* current;  /* current matching position */\r
+  unsigned long    retry_in_match_counter;\r
+\r
+  /* invisible to users */\r
+  MatchArg*   msa;\r
+  StackType*  stk_base;\r
+  StackType*  stk;\r
+  StackIndex* mem_start_stk;\r
+  StackIndex* mem_end_stk;\r
+};\r
+\r
+#endif\r
+\r
+\r
 #ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE\r
-#define MATCH_ARG_INIT(msa, arg_option, arg_region, arg_start) do {\\r
+#define MATCH_ARG_INIT(msa, reg, arg_option, arg_region, arg_start, mp) do { \\r
   (msa).stack_p  = (void* )0;\\r
   (msa).options  = (arg_option);\\r
   (msa).region   = (arg_region);\\r
   (msa).start    = (arg_start);\\r
+  (msa).match_stack_limit  = (mp)->match_stack_limit;\\r
+  (msa).retry_limit_in_match = (mp)->retry_limit_in_match;\\r
+  (msa).mp = mp;\\r
   (msa).best_len = ONIG_MISMATCH;\\r
+  (msa).ptr_num  = (reg)->num_repeat + ((reg)->num_mem + 1) * 2; \\r
 } while(0)\r
 #else\r
-#define MATCH_ARG_INIT(msa, arg_option, arg_region, arg_start) do {\\r
+#define MATCH_ARG_INIT(msa, reg, arg_option, arg_region, arg_start, mp) do { \\r
   (msa).stack_p  = (void* )0;\\r
   (msa).options  = (arg_option);\\r
   (msa).region   = (arg_region);\\r
   (msa).start    = (arg_start);\\r
+  (msa).match_stack_limit  = (mp)->match_stack_limit;\\r
+  (msa).retry_limit_in_match = (mp)->retry_limit_in_match;\\r
+  (msa).mp = mp;\\r
+  (msa).ptr_num  = (reg)->num_repeat + ((reg)->num_mem + 1) * 2; \\r
 } while(0)\r
 #endif\r
 \r
-#ifdef USE_COMBINATION_EXPLOSION_CHECK\r
-\r
-#define STATE_CHECK_BUFF_MALLOC_THRESHOLD_SIZE  16\r
-\r
-#define STATE_CHECK_BUFF_INIT(msa, str_len, offset, state_num) do {    \\r
-  if ((state_num) > 0 && str_len >= STATE_CHECK_STRING_THRESHOLD_LEN) {\\r
-    unsigned int size = (unsigned int )(((str_len) + 1) * (state_num) + 7) >> 3;\\r
-    offset = ((offset) * (state_num)) >> 3;\\r
-    if (size > 0 && offset < size && size < STATE_CHECK_BUFF_MAX_SIZE) {\\r
-      if (size >= STATE_CHECK_BUFF_MALLOC_THRESHOLD_SIZE) \\r
-        (msa).state_check_buff = (void* )xmalloc(size);\\r
-      else \\r
-        (msa).state_check_buff = (void* )xalloca(size);\\r
-      xmemset(((char* )((msa).state_check_buff)+(offset)), 0, \\r
-              (size_t )(size - (offset))); \\r
-      (msa).state_check_buff_size = size;\\r
-    }\\r
-    else {\\r
-      (msa).state_check_buff = (void* )0;\\r
-      (msa).state_check_buff_size = 0;\\r
-    }\\r
-  }\\r
-  else {\\r
-    (msa).state_check_buff = (void* )0;\\r
-    (msa).state_check_buff_size = 0;\\r
-  }\\r
-  } while(0)\r
-\r
-#define MATCH_ARG_FREE(msa) do {\\r
-  if ((msa).stack_p) xfree((msa).stack_p);\\r
-  if ((msa).state_check_buff_size >= STATE_CHECK_BUFF_MALLOC_THRESHOLD_SIZE) { \\r
-    if ((msa).state_check_buff) xfree((msa).state_check_buff);\\r
-  }\\r
-} while(0)\r
-#else\r
-#define STATE_CHECK_BUFF_INIT(msa, str_len, offset, state_num)\r
 #define MATCH_ARG_FREE(msa)  if ((msa).stack_p) xfree((msa).stack_p)\r
-#endif\r
 \r
 \r
+#define ALLOCA_PTR_NUM_LIMIT   50\r
 \r
-#define STACK_INIT(alloc_addr, ptr_num, stack_num)  do {\\r
+#define STACK_INIT(stack_num)  do {\\r
   if (msa->stack_p) {\\r
-    alloc_addr = (char* )xmalloc(sizeof(char*) * (ptr_num));\\r
-    stk_alloc  = (OnigStackType* )(msa->stack_p);\\r
-    stk_base   = stk_alloc;\\r
+    is_alloca  = 0;\\r
+    alloc_base = msa->stack_p;\\r
+    stk_base   = (StackType* )(alloc_base\\r
+                 + (sizeof(StackIndex) * msa->ptr_num));\\r
     stk        = stk_base;\\r
     stk_end    = stk_base + msa->stack_n;\\r
   }\\r
+  else if (msa->ptr_num > ALLOCA_PTR_NUM_LIMIT) {\\r
+    is_alloca  = 0;\\r
+    alloc_base = (char* )xmalloc(sizeof(StackIndex) * msa->ptr_num\\r
+                  + sizeof(StackType) * (stack_num));\\r
+    CHECK_NULL_RETURN_MEMERR(alloc_base);\\r
+    stk_base   = (StackType* )(alloc_base\\r
+                 + (sizeof(StackIndex) * msa->ptr_num));\\r
+    stk        = stk_base;\\r
+    stk_end    = stk_base + (stack_num);\\r
+  }\\r
   else {\\r
-    alloc_addr = (char* )xmalloc(sizeof(char*) * (ptr_num)\\r
-                      + sizeof(OnigStackType) * (stack_num));\\r
-    stk_alloc  = (OnigStackType* )(alloc_addr + sizeof(char*) * (ptr_num));\\r
-    stk_base   = stk_alloc;\\r
+    is_alloca  = 1;\\r
+    alloc_base = (char* )xmalloc(sizeof(StackIndex) * msa->ptr_num\\r
+                 + sizeof(StackType) * (stack_num));\\r
+    CHECK_NULL_RETURN_MEMERR(alloc_base);\\r
+    stk_base   = (StackType* )(alloc_base\\r
+                 + (sizeof(StackIndex) * msa->ptr_num));\\r
     stk        = stk_base;\\r
     stk_end    = stk_base + (stack_num);\\r
   }\\r
-} while(0)\r
+} while(0);\r
+\r
 \r
 #define STACK_SAVE do{\\r
-  if (stk_base != stk_alloc) {\\r
-    msa->stack_p = stk_base;\\r
-    msa->stack_n = (int)(stk_end - stk_base);\\r
+    msa->stack_n = (int )(stk_end - stk_base);\\r
+  if (is_alloca != 0) {\\r
+    size_t size = sizeof(StackIndex) * msa->ptr_num \\r
+                + sizeof(StackType) * msa->stack_n;\\r
+    msa->stack_p = xmalloc(size);\\r
+    CHECK_NULL_RETURN_MEMERR(msa->stack_p);\\r
+    xmemcpy(msa->stack_p, alloc_base, size);\\r
+  }\\r
+  else {\\r
+    msa->stack_p = alloc_base;\\r
   };\\r
 } while(0)\r
 \r
-static unsigned int MatchStackLimitSize = DEFAULT_MATCH_STACK_LIMIT_SIZE;\r
+#define UPDATE_FOR_STACK_REALLOC do{\\r
+  repeat_stk    = (StackIndex* )alloc_base;\\r
+  mem_start_stk = (StackIndex* )(repeat_stk + reg->num_repeat);\\r
+  mem_end_stk   = mem_start_stk + num_mem + 1;\\r
+} while(0)\r
+\r
+static unsigned int MatchStackLimit = DEFAULT_MATCH_STACK_LIMIT_SIZE;\r
 \r
 extern unsigned int\r
 onig_get_match_stack_limit_size(void)\r
 {\r
-  return MatchStackLimitSize;\r
+  return MatchStackLimit;\r
 }\r
 \r
 extern int\r
 onig_set_match_stack_limit_size(unsigned int size)\r
 {\r
-  MatchStackLimitSize = size;\r
+  MatchStackLimit = size;\r
   return 0;\r
 }\r
 \r
-static int\r
-stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,\r
-            OnigStackType** arg_stk, OnigStackType* stk_alloc, OnigMatchArg* msa)\r
-{\r
-  unsigned int n;\r
-  OnigStackType *x, *stk_base, *stk_end, *stk;\r
+#ifdef USE_RETRY_LIMIT_IN_MATCH\r
 \r
-  stk_base = *arg_stk_base;\r
-  stk_end  = *arg_stk_end;\r
-  stk      = *arg_stk;\r
+static unsigned long RetryLimitInMatch = DEFAULT_RETRY_LIMIT_IN_MATCH;\r
 \r
-  n = (unsigned int)(stk_end - stk_base);\r
-  if (stk_base == stk_alloc && IS_NULL(msa->stack_p)) {\r
-    x = (OnigStackType* )xmalloc(sizeof(OnigStackType) * n * 2);\r
-    if (IS_NULL(x)) {\r
-      STACK_SAVE;\r
-      return ONIGERR_MEMORY;\r
-    }\r
-    xmemcpy(x, stk_base, n * sizeof(OnigStackType));\r
-    n *= 2;\r
-  }\r
-  else {\r
-    n *= 2;\r
-    if (MatchStackLimitSize != 0 && n > MatchStackLimitSize) {\r
-      if ((unsigned int )(stk_end - stk_base) == MatchStackLimitSize)\r
-        return ONIGERR_MATCH_STACK_LIMIT_OVER;\r
-      else\r
-        n = MatchStackLimitSize;\r
-    }\r
-    x = (OnigStackType* )xrealloc(stk_base, sizeof(OnigStackType) * n, sizeof(OnigStackType) * (stk_end - stk_base));\r
-    if (IS_NULL(x)) {\r
-      STACK_SAVE;\r
-      return ONIGERR_MEMORY;\r
-    }\r
-  }\r
-  *arg_stk      = x + (stk - stk_base);\r
-  *arg_stk_base = x;\r
-  *arg_stk_end  = x + n;\r
-  return 0;\r
-}\r
+#define CHECK_RETRY_LIMIT_IN_MATCH  do {\\r
+  if (retry_in_match_counter++ > retry_limit_in_match) goto retry_limit_in_match_over;\\r
+} while (0)\r
 \r
-#define STACK_ENSURE(n)        do {\\r
-  if (stk_end - stk < (n)) {\\r
-    int r = stack_double(&stk_base, &stk_end, &stk, stk_alloc, msa);\\r
-    if (r != 0) { STACK_SAVE; return r; } \\r
-  }\\r
-} while(0)\r
+#else\r
 \r
-#define STACK_AT(index)        (stk_base + (index))\r
-#define GET_STACK_INDEX(stk)   ((OnigStackIndex)((stk) - stk_base))\r
+#define CHECK_RETRY_LIMIT_IN_MATCH\r
 \r
-#define STACK_PUSH_TYPE(stack_type) do {\\r
-  STACK_ENSURE(1);\\r
-  stk->type = (stack_type);\\r
-  STACK_INC;\\r
-} while(0)\r
+#endif /* USE_RETRY_LIMIT_IN_MATCH */\r
 \r
-#define IS_TO_VOID_TARGET(stk) (((stk)->type & STK_MASK_TO_VOID_TARGET) != 0)\r
+extern unsigned long\r
+onig_get_retry_limit_in_match(void)\r
+{\r
+#ifdef USE_RETRY_LIMIT_IN_MATCH\r
+  return RetryLimitInMatch;\r
+#else\r
+  /* return ONIG_NO_SUPPORT_CONFIG; */\r
+  return 0;\r
+#endif\r
+}\r
 \r
-#ifdef USE_COMBINATION_EXPLOSION_CHECK\r
-#define STATE_CHECK_POS(s,snum) \\r
-  (((s) - str) * num_comb_exp_check + ((snum) - 1))\r
-#define STATE_CHECK_VAL(v,snum) do {\\r
-  if (state_check_buff != NULL) {\\r
-    int x = STATE_CHECK_POS(s,snum);\\r
-    (v) = state_check_buff[x/8] & (1<<(x%8));\\r
-  }\\r
-  else (v) = 0;\\r
-} while(0)\r
+extern int\r
+onig_set_retry_limit_in_match(unsigned long size)\r
+{\r
+#ifdef USE_RETRY_LIMIT_IN_MATCH\r
+  RetryLimitInMatch = size;\r
+  return 0;\r
+#else\r
+  return ONIG_NO_SUPPORT_CONFIG;\r
+#endif\r
+}\r
+\r
+static OnigCalloutFunc DefaultProgressCallout;\r
+static OnigCalloutFunc DefaultRetractionCallout;\r
 \r
+extern OnigMatchParam*\r
+onig_new_match_param(void)\r
+{\r
+  OnigMatchParam* p;\r
 \r
-#define ELSE_IF_STATE_CHECK_MARK(stk) \\r
-  else if ((stk)->type == STK_STATE_CHECK_MARK) { \\r
-    int x = STATE_CHECK_POS(stk->u.state.pstr, stk->u.state.state_check);\\r
-    state_check_buff[x/8] |= (1<<(x%8));                               \\r
+  p = (OnigMatchParam* )xmalloc(sizeof(*p));\r
+  if (IS_NOT_NULL(p)) {\r
+    onig_initialize_match_param(p);\r
   }\r
 \r
-#define STACK_PUSH(stack_type,pat,s,sprev) do {\\r
-  STACK_ENSURE(1);\\r
-  stk->type = (stack_type);\\r
-  stk->u.state.pcode     = (pat);\\r
-  stk->u.state.pstr      = (s);\\r
-  stk->u.state.pstr_prev = (sprev);\\r
-  stk->u.state.state_check = 0;\\r
-  STACK_INC;\\r
-} while(0)\r
+  return p;\r
+}\r
 \r
-#define STACK_PUSH_ENSURED(stack_type,pat) do {\\r
-  stk->type = (stack_type);\\r
-  stk->u.state.pcode = (pat);\\r
-  stk->u.state.state_check = 0;\\r
-  STACK_INC;\\r
-} while(0)\r
+extern void\r
+onig_free_match_param_content(OnigMatchParam* p)\r
+{\r
+#ifdef USE_CALLOUT\r
+  if (IS_NOT_NULL(p->callout_data)) {\r
+    xfree(p->callout_data);\r
+    p->callout_data = 0;\r
+  }\r
+#endif\r
+}\r
 \r
-#define STACK_PUSH_ALT_WITH_STATE_CHECK(pat,s,sprev,snum) do {\\r
-  STACK_ENSURE(1);\\r
-  stk->type = STK_ALT;\\r
-  stk->u.state.pcode     = (pat);\\r
-  stk->u.state.pstr      = (s);\\r
-  stk->u.state.pstr_prev = (sprev);\\r
-  stk->u.state.state_check = ((state_check_buff != NULL) ? (snum) : 0);\\r
-  STACK_INC;\\r
-} while(0)\r
+extern void\r
+onig_free_match_param(OnigMatchParam* p)\r
+{\r
+  if (IS_NOT_NULL(p)) {\r
+    onig_free_match_param_content(p);\r
+    xfree(p);\r
+  }\r
+}\r
+\r
+extern int\r
+onig_initialize_match_param(OnigMatchParam* mp)\r
+{\r
+  mp->match_stack_limit  = MatchStackLimit;\r
+#ifdef USE_RETRY_LIMIT_IN_MATCH\r
+  mp->retry_limit_in_match = RetryLimitInMatch;\r
+#endif\r
+  mp->progress_callout_of_contents   = DefaultProgressCallout;\r
+  mp->retraction_callout_of_contents = DefaultRetractionCallout;\r
+\r
+#ifdef USE_CALLOUT\r
+  mp->match_at_call_counter  = 0;\r
+  mp->callout_user_data      = 0;\r
+  mp->callout_data           = 0;\r
+  mp->callout_data_alloc_num = 0;\r
+#endif\r
+\r
+  return ONIG_NORMAL;\r
+}\r
+\r
+#ifdef USE_CALLOUT\r
+\r
+static int\r
+adjust_match_param(regex_t* reg, OnigMatchParam* mp)\r
+{\r
+  RegexExt* ext = REG_EXTP(reg);\r
+\r
+  mp->match_at_call_counter = 0;\r
+\r
+  if (IS_NULL(ext) || ext->callout_num == 0) return ONIG_NORMAL;\r
+\r
+  if (ext->callout_num > mp->callout_data_alloc_num) {\r
+    CalloutData* d;\r
+    size_t n = ext->callout_num * sizeof(*d);\r
+    if (IS_NOT_NULL(mp->callout_data))\r
+      d = (CalloutData* )xrealloc(mp->callout_data, n, mp->callout_data_alloc_num * sizeof(*d));\r
+    else\r
+      d = (CalloutData* )xmalloc(n);\r
+    CHECK_NULL_RETURN_MEMERR(d);\r
+\r
+    mp->callout_data = d;\r
+    mp->callout_data_alloc_num = ext->callout_num;\r
+  }\r
+\r
+  xmemset(mp->callout_data, 0, mp->callout_data_alloc_num * sizeof(CalloutData));\r
+  return ONIG_NORMAL;\r
+}\r
+\r
+#define ADJUST_MATCH_PARAM(reg, mp) \\r
+  r = adjust_match_param(reg, mp);\\r
+  if (r != ONIG_NORMAL) return r;\r
+\r
+#define CALLOUT_DATA_AT_NUM(mp, num)  ((mp)->callout_data + ((num) - 1))\r
+\r
+extern int\r
+onig_check_callout_data_and_clear_old_values(OnigCalloutArgs* args)\r
+{\r
+  OnigMatchParam* mp;\r
+  int num;\r
+  CalloutData* d;\r
+\r
+  mp  = args->msa->mp;\r
+  num = args->num;\r
+\r
+  d = CALLOUT_DATA_AT_NUM(mp, num);\r
+  if (d->last_match_at_call_counter != mp->match_at_call_counter) {\r
+    xmemset(d, 0, sizeof(*d));\r
+    d->last_match_at_call_counter = mp->match_at_call_counter;\r
+    return d->last_match_at_call_counter;\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+extern int\r
+onig_get_callout_data_dont_clear_old(regex_t* reg, OnigMatchParam* mp,\r
+                                     int callout_num, int slot,\r
+                                     OnigType* type, OnigValue* val)\r
+{\r
+  OnigType t;\r
+  CalloutData* d;\r
+\r
+  if (callout_num <= 0) return ONIGERR_INVALID_ARGUMENT;\r
+\r
+  d = CALLOUT_DATA_AT_NUM(mp, callout_num);\r
+  t = d->slot[slot].type;\r
+  if (IS_NOT_NULL(type)) *type = t;\r
+  if (IS_NOT_NULL(val))  *val  = d->slot[slot].val;\r
+  return (t == ONIG_TYPE_VOID ? 1 : ONIG_NORMAL);\r
+}\r
+\r
+extern int\r
+onig_get_callout_data_by_callout_args_self_dont_clear_old(OnigCalloutArgs* args,\r
+                                                          int slot, OnigType* type,\r
+                                                          OnigValue* val)\r
+{\r
+  return onig_get_callout_data_dont_clear_old(args->regex, args->msa->mp,\r
+                                              args->num, slot, type, val);\r
+}\r
+\r
+extern int\r
+onig_get_callout_data(regex_t* reg, OnigMatchParam* mp,\r
+                      int callout_num, int slot,\r
+                      OnigType* type, OnigValue* val)\r
+{\r
+  OnigType t;\r
+  CalloutData* d;\r
+\r
+  if (callout_num <= 0) return ONIGERR_INVALID_ARGUMENT;\r
+\r
+  d = CALLOUT_DATA_AT_NUM(mp, callout_num);\r
+  if (d->last_match_at_call_counter != mp->match_at_call_counter) {\r
+    xmemset(d, 0, sizeof(*d));\r
+    d->last_match_at_call_counter = mp->match_at_call_counter;\r
+  }\r
+\r
+  t = d->slot[slot].type;\r
+  if (IS_NOT_NULL(type)) *type = t;\r
+  if (IS_NOT_NULL(val))  *val  = d->slot[slot].val;\r
+  return (t == ONIG_TYPE_VOID ? 1 : ONIG_NORMAL);\r
+}\r
+\r
+extern int\r
+onig_get_callout_data_by_tag(regex_t* reg, OnigMatchParam* mp,\r
+                             const UChar* tag, const UChar* tag_end, int slot,\r
+                             OnigType* type, OnigValue* val)\r
+{\r
+  int num;\r
+\r
+  num = onig_get_callout_num_by_tag(reg, tag, tag_end);\r
+  if (num < 0)  return num;\r
+  if (num == 0) return ONIGERR_INVALID_CALLOUT_TAG_NAME;\r
+\r
+  return onig_get_callout_data(reg, mp, num, slot, type, val);\r
+}\r
+\r
+extern int\r
+onig_get_callout_data_by_callout_args(OnigCalloutArgs* args,\r
+                                      int callout_num, int slot,\r
+                                      OnigType* type, OnigValue* val)\r
+{\r
+  return onig_get_callout_data(args->regex, args->msa->mp, callout_num, slot,\r
+                               type, val);\r
+}\r
+\r
+extern int\r
+onig_get_callout_data_by_callout_args_self(OnigCalloutArgs* args,\r
+                                           int slot, OnigType* type, OnigValue* val)\r
+{\r
+  return onig_get_callout_data(args->regex, args->msa->mp, args->num, slot,\r
+                               type, val);\r
+}\r
+\r
+extern int\r
+onig_set_callout_data(regex_t* reg, OnigMatchParam* mp,\r
+                      int callout_num, int slot,\r
+                      OnigType type, OnigValue* val)\r
+{\r
+  CalloutData* d;\r
+\r
+  if (callout_num <= 0) return ONIGERR_INVALID_ARGUMENT;\r
+\r
+  d = CALLOUT_DATA_AT_NUM(mp, callout_num);\r
+  d->slot[slot].type = type;\r
+  d->slot[slot].val  = *val;\r
+  d->last_match_at_call_counter = mp->match_at_call_counter;\r
+\r
+  return ONIG_NORMAL;\r
+}\r
+\r
+extern int\r
+onig_set_callout_data_by_tag(regex_t* reg, OnigMatchParam* mp,\r
+                             const UChar* tag, const UChar* tag_end, int slot,\r
+                             OnigType type, OnigValue* val)\r
+{\r
+  int num;\r
+\r
+  num = onig_get_callout_num_by_tag(reg, tag, tag_end);\r
+  if (num < 0)  return num;\r
+  if (num == 0) return ONIGERR_INVALID_CALLOUT_TAG_NAME;\r
+\r
+  return onig_set_callout_data(reg, mp, num, slot, type, val);\r
+}\r
+\r
+extern int\r
+onig_set_callout_data_by_callout_args(OnigCalloutArgs* args,\r
+                                      int callout_num, int slot,\r
+                                      OnigType type, OnigValue* val)\r
+{\r
+  return onig_set_callout_data(args->regex, args->msa->mp, callout_num, slot,\r
+                               type, val);\r
+}\r
+\r
+extern int\r
+onig_set_callout_data_by_callout_args_self(OnigCalloutArgs* args,\r
+                                           int slot, OnigType type, OnigValue* val)\r
+{\r
+  return onig_set_callout_data(args->regex, args->msa->mp, args->num, slot,\r
+                               type, val);\r
+}\r
+\r
+#else\r
+#define ADJUST_MATCH_PARAM(reg, mp)\r
+#endif /* USE_CALLOUT */\r
+\r
+\r
+static int\r
+stack_double(int is_alloca, char** arg_alloc_base,\r
+             StackType** arg_stk_base, StackType** arg_stk_end, StackType** arg_stk,\r
+             MatchArg* msa)\r
+{\r
+  unsigned int n;\r
+  int used;\r
+  size_t size;\r
+  size_t new_size;\r
+  char* alloc_base;\r
+  char* new_alloc_base;\r
+  StackType *stk_base, *stk_end, *stk;\r
+\r
+  alloc_base = *arg_alloc_base;\r
+  stk_base = *arg_stk_base;\r
+  stk_end  = *arg_stk_end;\r
+  stk      = *arg_stk;\r
+\r
+  n = (unsigned int )(stk_end - stk_base);\r
+  size = sizeof(StackIndex) * msa->ptr_num + sizeof(StackType) * n;\r
+  n *= 2;\r
+  new_size = sizeof(StackIndex) * msa->ptr_num + sizeof(StackType) * n;\r
+  if (is_alloca != 0) {\r
+    new_alloc_base = (char* )xmalloc(new_size);\r
+    if (IS_NULL(new_alloc_base)) {\r
+      STACK_SAVE;\r
+      return ONIGERR_MEMORY;\r
+    }\r
+    xmemcpy(new_alloc_base, alloc_base, size);\r
+  }\r
+  else {\r
+    if (msa->match_stack_limit != 0 && n > msa->match_stack_limit) {\r
+      if ((unsigned int )(stk_end - stk_base) == msa->match_stack_limit)\r
+        return ONIGERR_MATCH_STACK_LIMIT_OVER;\r
+      else\r
+        n = msa->match_stack_limit;\r
+    }\r
+    new_alloc_base = (char* )xrealloc(alloc_base, new_size, size);\r
+    if (IS_NULL(new_alloc_base)) {\r
+      STACK_SAVE;\r
+      return ONIGERR_MEMORY;\r
+    }\r
+  }\r
+\r
+  alloc_base = new_alloc_base;\r
+  used = (int )(stk - stk_base);\r
+  *arg_alloc_base = alloc_base;\r
+  *arg_stk_base   = (StackType* )(alloc_base\r
+                                  + (sizeof(StackIndex) * msa->ptr_num));\r
+  *arg_stk      = *arg_stk_base + used;\r
+  *arg_stk_end  = *arg_stk_base + n;\r
+  return 0;\r
+}\r
 \r
-#define STACK_PUSH_STATE_CHECK(s,snum) do {\\r
-  if (state_check_buff != NULL) {\\r
-    STACK_ENSURE(1);\\r
-    stk->type = STK_STATE_CHECK_MARK;\\r
-    stk->u.state.pstr = (s);\\r
-    stk->u.state.state_check = (snum);\\r
-    STACK_INC;\\r
+#define STACK_ENSURE(n) do {\\r
+    if ((int )(stk_end - stk) < (n)) {\\r
+    int r = stack_double(is_alloca, &alloc_base, &stk_base, &stk_end, &stk, msa);\\r
+    if (r != 0) { STACK_SAVE; return r; } \\r
+    is_alloca = 0;\\r
+    UPDATE_FOR_STACK_REALLOC;\\r
   }\\r
 } while(0)\r
 \r
-#else /* USE_COMBINATION_EXPLOSION_CHECK */\r
+#define STACK_AT(index)        (stk_base + (index))\r
+#define GET_STACK_INDEX(stk)   ((stk) - stk_base)\r
+\r
+#define STACK_PUSH_TYPE(stack_type) do {\\r
+  STACK_ENSURE(1);\\r
+  stk->type = (stack_type);\\r
+  STACK_INC;\\r
+} while(0)\r
 \r
-#define ELSE_IF_STATE_CHECK_MARK(stk)\r
+#define IS_TO_VOID_TARGET(stk) (((stk)->type & STK_MASK_TO_VOID_TARGET) != 0)\r
 \r
 #define STACK_PUSH(stack_type,pat,s,sprev) do {\\r
   STACK_ENSURE(1);\\r
@@ -565,19 +1495,37 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
   stk->u.state.pcode = (pat);\\r
   STACK_INC;\\r
 } while(0)\r
-#endif /* USE_COMBINATION_EXPLOSION_CHECK */\r
 \r
-#define STACK_PUSH_ALT(pat,s,sprev)     STACK_PUSH(STK_ALT,pat,s,sprev)\r
-#define STACK_PUSH_POS(s,sprev)         STACK_PUSH(STK_POS,NULL_UCHARP,s,sprev)\r
-#define STACK_PUSH_POS_NOT(pat,s,sprev) STACK_PUSH(STK_POS_NOT,pat,s,sprev)\r
-#define STACK_PUSH_STOP_BT              STACK_PUSH_TYPE(STK_STOP_BT)\r
-#define STACK_PUSH_LOOK_BEHIND_NOT(pat,s,sprev) \\r
-        STACK_PUSH(STK_LOOK_BEHIND_NOT,pat,s,sprev)\r
+#ifdef ONIG_DEBUG_MATCH\r
+#define STACK_PUSH_BOTTOM(stack_type,pat) do {\\r
+  stk->type = (stack_type);\\r
+  stk->u.state.pcode = (pat);\\r
+  stk->u.state.pstr      = s;\\r
+  stk->u.state.pstr_prev = sprev;\\r
+  STACK_INC;\\r
+} while (0)\r
+#else\r
+#define STACK_PUSH_BOTTOM(stack_type,pat) do {\\r
+  stk->type = (stack_type);\\r
+  stk->u.state.pcode = (pat);\\r
+  STACK_INC;\\r
+} while (0)\r
+#endif\r
 \r
-#define STACK_PUSH_REPEAT(id, pat) do {\\r
+#define STACK_PUSH_ALT(pat,s,sprev)       STACK_PUSH(STK_ALT,pat,s,sprev)\r
+#define STACK_PUSH_SUPER_ALT(pat,s,sprev) STACK_PUSH(STK_SUPER_ALT,pat,s,sprev)\r
+#define STACK_PUSH_POS(s,sprev) \\r
+  STACK_PUSH(STK_TO_VOID_START,NULL_UCHARP,s,sprev)\r
+#define STACK_PUSH_ALT_PREC_READ_NOT(pat,s,sprev) \\r
+  STACK_PUSH(STK_ALT_PREC_READ_NOT,pat,s,sprev)\r
+#define STACK_PUSH_TO_VOID_START        STACK_PUSH_TYPE(STK_TO_VOID_START)\r
+#define STACK_PUSH_ALT_LOOK_BEHIND_NOT(pat,s,sprev) \\r
+  STACK_PUSH(STK_ALT_LOOK_BEHIND_NOT,pat,s,sprev)\r
+\r
+#define STACK_PUSH_REPEAT(sid, pat) do {\\r
   STACK_ENSURE(1);\\r
   stk->type = STK_REPEAT;\\r
-  stk->u.repeat.num    = (id);\\r
+  stk->zid  = (sid);\\r
   stk->u.repeat.pcode  = (pat);\\r
   stk->u.repeat.count  = 0;\\r
   STACK_INC;\\r
@@ -593,22 +1541,22 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
 #define STACK_PUSH_MEM_START(mnum, s) do {\\r
   STACK_ENSURE(1);\\r
   stk->type = STK_MEM_START;\\r
-  stk->u.mem.num      = (int)(mnum);\\r
-  stk->u.mem.pstr     = (s);\\r
-  stk->u.mem.start    = mem_start_stk[mnum];\\r
-  stk->u.mem.end      = mem_end_stk[mnum];\\r
-  mem_start_stk[mnum] = GET_STACK_INDEX(stk);\\r
-  mem_end_stk[mnum]   = INVALID_STACK_INDEX;\\r
+  stk->zid  = (mnum);\\r
+  stk->u.mem.pstr       = (s);\\r
+  stk->u.mem.prev_start = mem_start_stk[mnum];\\r
+  stk->u.mem.prev_end   = mem_end_stk[mnum];\\r
+  mem_start_stk[mnum]   = GET_STACK_INDEX(stk);\\r
+  mem_end_stk[mnum]     = INVALID_STACK_INDEX;\\r
   STACK_INC;\\r
 } while(0)\r
 \r
 #define STACK_PUSH_MEM_END(mnum, s) do {\\r
   STACK_ENSURE(1);\\r
   stk->type = STK_MEM_END;\\r
-  stk->u.mem.num    = (mnum);\\r
-  stk->u.mem.pstr   = (s);\\r
-  stk->u.mem.start  = mem_start_stk[mnum];\\r
-  stk->u.mem.end    = mem_end_stk[mnum];\\r
+  stk->zid  = (mnum);\\r
+  stk->u.mem.pstr       = (s);\\r
+  stk->u.mem.prev_start = mem_start_stk[mnum];\\r
+  stk->u.mem.prev_end   = mem_end_stk[mnum];\\r
   mem_end_stk[mnum] = GET_STACK_INDEX(stk);\\r
   STACK_INC;\\r
 } while(0)\r
@@ -616,7 +1564,7 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
 #define STACK_PUSH_MEM_END_MARK(mnum) do {\\r
   STACK_ENSURE(1);\\r
   stk->type = STK_MEM_END_MARK;\\r
-  stk->u.mem.num = (mnum);\\r
+  stk->zid  = (mnum);\\r
   STACK_INC;\\r
 } while(0)\r
 \r
@@ -626,10 +1574,10 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
   while (k > stk_base) {\\r
     k--;\\r
     if ((k->type & STK_MASK_MEM_END_OR_MARK) != 0 \\r
-      && k->u.mem.num == (mnum)) {\\r
+      && k->zid == (mnum)) {\\r
       level++;\\r
     }\\r
-    else if (k->type == STK_MEM_START && k->u.mem.num == (mnum)) {\\r
+    else if (k->type == STK_MEM_START && k->zid == (mnum)) {\\r
       if (level == 0) break;\\r
       level--;\\r
     }\\r
@@ -654,18 +1602,18 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
   }\\r
 } while(0)\r
 \r
-#define STACK_PUSH_NULL_CHECK_START(cnum, s) do {\\r
+#define STACK_PUSH_EMPTY_CHECK_START(cnum, s) do {\\r
   STACK_ENSURE(1);\\r
-  stk->type = STK_NULL_CHECK_START;\\r
-  stk->u.null_check.num  = (cnum);\\r
-  stk->u.null_check.pstr = (s);\\r
+  stk->type = STK_EMPTY_CHECK_START;\\r
+  stk->zid  = (cnum);\\r
+  stk->u.empty_check.pstr = (s);\\r
   STACK_INC;\\r
 } while(0)\r
 \r
-#define STACK_PUSH_NULL_CHECK_END(cnum) do {\\r
+#define STACK_PUSH_EMPTY_CHECK_END(cnum) do {\\r
   STACK_ENSURE(1);\\r
-  stk->type = STK_NULL_CHECK_END;\\r
-  stk->u.null_check.num  = (cnum);\\r
+  stk->type = STK_EMPTY_CHECK_END;\\r
+  stk->zid  = (cnum);\\r
   STACK_INC;\\r
 } while(0)\r
 \r
@@ -682,6 +1630,115 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
   STACK_INC;\\r
 } while(0)\r
 \r
+#define STACK_PUSH_SAVE_VAL(sid, stype, sval) do {\\r
+  STACK_ENSURE(1);\\r
+  stk->type = STK_SAVE_VAL;\\r
+  stk->zid  = (sid);\\r
+  stk->u.val.type = (stype);\\r
+  stk->u.val.v    = (UChar* )(sval);\\r
+  STACK_INC;\\r
+} while(0)\r
+\r
+#define STACK_PUSH_SAVE_VAL_WITH_SPREV(sid, stype, sval) do {\\r
+  STACK_ENSURE(1);\\r
+  stk->type = STK_SAVE_VAL;\\r
+  stk->zid  = (sid);\\r
+  stk->u.val.type = (stype);\\r
+  stk->u.val.v    = (UChar* )(sval);\\r
+  stk->u.val.v2   = sprev;\\r
+  STACK_INC;\\r
+} while(0)\r
+\r
+#define STACK_GET_SAVE_VAL_TYPE_LAST(stype, sval) do {\\r
+  StackType *k = stk;\\r
+  while (k > stk_base) {\\r
+    k--;\\r
+    STACK_BASE_CHECK(k, "STACK_GET_SAVE_VAL_TYPE_LAST"); \\r
+    if (k->type == STK_SAVE_VAL && k->u.val.type == (stype)) {\\r
+      (sval) = k->u.val.v;\\r
+      break;\\r
+    }\\r
+  }\\r
+} while (0)\r
+\r
+#define STACK_GET_SAVE_VAL_TYPE_LAST_ID(stype, sid, sval) do { \\r
+  int level = 0;\\r
+  StackType *k = stk;\\r
+  while (k > stk_base) {\\r
+    k--;\\r
+    STACK_BASE_CHECK(k, "STACK_GET_SAVE_VAL_TYPE_LAST_ID"); \\r
+    if (k->type == STK_SAVE_VAL && k->u.val.type == (stype)\\r
+        && k->zid == (sid)) {\\r
+      if (level == 0) {\\r
+        (sval) = k->u.val.v;\\r
+        break;\\r
+      }\\r
+    }\\r
+    else if (k->type == STK_CALL_FRAME)\\r
+      level--;\\r
+    else if (k->type == STK_RETURN)\\r
+      level++;\\r
+  }\\r
+} while (0)\r
+\r
+#define STACK_GET_SAVE_VAL_TYPE_LAST_ID_WITH_SPREV(stype, sid, sval) do { \\r
+  int level = 0;\\r
+  StackType *k = stk;\\r
+  while (k > stk_base) {\\r
+    k--;\\r
+    STACK_BASE_CHECK(k, "STACK_GET_SAVE_VAL_TYPE_LAST_ID"); \\r
+    if (k->type == STK_SAVE_VAL && k->u.val.type == (stype)\\r
+        && k->zid == (sid)) {\\r
+      if (level == 0) {\\r
+        (sval) = k->u.val.v;\\r
+        sprev  = k->u.val.v2;\\r
+        break;\\r
+      }\\r
+    }\\r
+    else if (k->type == STK_CALL_FRAME)\\r
+      level--;\\r
+    else if (k->type == STK_RETURN)\\r
+      level++;\\r
+  }\\r
+} while (0)\r
+\r
+#define STACK_GET_SAVE_VAL_TYPE_LAST_ID_FROM(stype, sid, sval, stk_from) do { \\r
+  int level = 0;\\r
+  StackType *k = (stk_from);\\r
+  while (k > stk_base) {\\r
+    STACK_BASE_CHECK(k, "STACK_GET_SAVE_VAL_TYPE_LAST_ID_FROM"); \\r
+    if (k->type == STK_SAVE_VAL && k->u.val.type == (stype)\\r
+        && k->u.val.id == (sid)) {\\r
+      if (level == 0) {\\r
+        (sval) = k->u.val.v;\\r
+        break;\\r
+      }\\r
+    }\\r
+    else if (k->type == STK_CALL_FRAME)\\r
+      level--;\\r
+    else if (k->type == STK_RETURN)\\r
+      level++;\\r
+    k--;\\r
+  }\\r
+} while (0)\r
+\r
+#define STACK_PUSH_CALLOUT_CONTENTS(anum, func) do {\\r
+  STACK_ENSURE(1);\\r
+  stk->type = STK_CALLOUT;\\r
+  stk->zid  = ONIG_NON_NAME_ID;\\r
+  stk->u.callout.num = (anum);\\r
+  stk->u.callout.func = (func);\\r
+  STACK_INC;\\r
+} while(0)\r
+\r
+#define STACK_PUSH_CALLOUT_NAME(aid, anum, func) do {\\r
+  STACK_ENSURE(1);\\r
+  stk->type = STK_CALLOUT;\\r
+  stk->zid  = (aid);\\r
+  stk->u.callout.num = (anum);\\r
+  stk->u.callout.func = (func);\\r
+  STACK_INC;\\r
+} while(0)\r
 \r
 #ifdef ONIG_DEBUG\r
 #define STACK_BASE_CHECK(p, at) \\r
@@ -698,6 +1755,16 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
   STACK_BASE_CHECK(stk, "STACK_POP_ONE"); \\r
 } while(0)\r
 \r
+\r
+#ifdef USE_CALLOUT\r
+#define POP_CALLOUT_CASE \\r
+  else if (stk->type == STK_CALLOUT) {\\r
+    RETRACTION_CALLOUT(stk->u.callout.func, stk->zid, stk->u.callout.num, msa->mp->callout_user_data);\\r
+  }\r
+#else\r
+#define POP_CALLOUT_CASE\r
+#endif\r
+\r
 #define STACK_POP  do {\\r
   switch (pop_level) {\\r
   case STACK_POP_LEVEL_FREE:\\r
@@ -705,7 +1772,6 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
       stk--;\\r
       STACK_BASE_CHECK(stk, "STACK_POP"); \\r
       if ((stk->type & STK_MASK_POP_USED) != 0)  break;\\r
-      ELSE_IF_STATE_CHECK_MARK(stk);\\r
     }\\r
     break;\\r
   case STACK_POP_LEVEL_MEM_START:\\r
@@ -714,10 +1780,9 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
       STACK_BASE_CHECK(stk, "STACK_POP 2"); \\r
       if ((stk->type & STK_MASK_POP_USED) != 0)  break;\\r
       else if (stk->type == STK_MEM_START) {\\r
-        mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\\r
-        mem_end_stk[stk->u.mem.num]   = stk->u.mem.end;\\r
+        mem_start_stk[stk->zid] = stk->u.mem.prev_start;\\r
+        mem_end_stk[stk->zid]   = stk->u.mem.prev_end;\\r
       }\\r
-      ELSE_IF_STATE_CHECK_MARK(stk);\\r
     }\\r
     break;\\r
   default:\\r
@@ -725,136 +1790,108 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
       stk--;\\r
       STACK_BASE_CHECK(stk, "STACK_POP 3"); \\r
       if ((stk->type & STK_MASK_POP_USED) != 0)  break;\\r
-      else if (stk->type == STK_MEM_START) {\\r
-        mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\\r
-        mem_end_stk[stk->u.mem.num]   = stk->u.mem.end;\\r
-      }\\r
-      else if (stk->type == STK_REPEAT_INC) {\\r
-        STACK_AT(stk->u.repeat_inc.si)->u.repeat.count--;\\r
-      }\\r
-      else if (stk->type == STK_MEM_END) {\\r
-        mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\\r
-        mem_end_stk[stk->u.mem.num]   = stk->u.mem.end;\\r
+      else if ((stk->type & STK_MASK_POP_HANDLED) != 0) {\\r
+        if (stk->type == STK_MEM_START) {\\r
+          mem_start_stk[stk->zid] = stk->u.mem.prev_start;\\r
+          mem_end_stk[stk->zid]   = stk->u.mem.prev_end;\\r
+        }\\r
+        else if (stk->type == STK_REPEAT_INC) {\\r
+          STACK_AT(stk->u.repeat_inc.si)->u.repeat.count--;\\r
+        }\\r
+        else if (stk->type == STK_MEM_END) {\\r
+          mem_start_stk[stk->zid] = stk->u.mem.prev_start;\\r
+          mem_end_stk[stk->zid]   = stk->u.mem.prev_end;\\r
+        }\\r
+        POP_CALLOUT_CASE\\r
       }\\r
-      ELSE_IF_STATE_CHECK_MARK(stk);\\r
     }\\r
     break;\\r
   }\\r
 } while(0)\r
 \r
-#define STACK_POP_TIL_POS_NOT  do {\\r
+#define POP_TIL_BODY(aname, til_type) do {\\r
   while (1) {\\r
     stk--;\\r
-    STACK_BASE_CHECK(stk, "STACK_POP_TIL_POS_NOT"); \\r
-    if (stk->type == STK_POS_NOT) break;\\r
-    else if (stk->type == STK_MEM_START) {\\r
-      mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\\r
-      mem_end_stk[stk->u.mem.num]   = stk->u.mem.end;\\r
-    }\\r
-    else if (stk->type == STK_REPEAT_INC) {\\r
-      STACK_AT(stk->u.repeat_inc.si)->u.repeat.count--;\\r
-    }\\r
-    else if (stk->type == STK_MEM_END) {\\r
-      mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\\r
-      mem_end_stk[stk->u.mem.num]   = stk->u.mem.end;\\r
+    STACK_BASE_CHECK(stk, (aname));\\r
+    if ((stk->type & STK_MASK_POP_HANDLED_TIL) != 0) {\\r
+      if (stk->type == (til_type)) break;\\r
+      else {\\r
+        if (stk->type == STK_MEM_START) {\\r
+          mem_start_stk[stk->zid] = stk->u.mem.prev_start;\\r
+          mem_end_stk[stk->zid]   = stk->u.mem.prev_end;\\r
+        }\\r
+        else if (stk->type == STK_REPEAT_INC) {\\r
+          STACK_AT(stk->u.repeat_inc.si)->u.repeat.count--;\\r
+        }\\r
+        else if (stk->type == STK_MEM_END) {\\r
+          mem_start_stk[stk->zid] = stk->u.mem.prev_start;\\r
+          mem_end_stk[stk->zid]   = stk->u.mem.prev_end;\\r
+        }\\r
+        /* Don't call callout here because negation of total success by (?!..) (?<!..) */\\r
+      }\\r
     }\\r
-    ELSE_IF_STATE_CHECK_MARK(stk);\\r
   }\\r
 } while(0)\r
 \r
-#define STACK_POP_TIL_LOOK_BEHIND_NOT  do {\\r
-  while (1) {\\r
-    stk--;\\r
-    STACK_BASE_CHECK(stk, "STACK_POP_TIL_LOOK_BEHIND_NOT"); \\r
-    if (stk->type == STK_LOOK_BEHIND_NOT) break;\\r
-    else if (stk->type == STK_MEM_START) {\\r
-      mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\\r
-      mem_end_stk[stk->u.mem.num]   = stk->u.mem.end;\\r
-    }\\r
-    else if (stk->type == STK_REPEAT_INC) {\\r
-      STACK_AT(stk->u.repeat_inc.si)->u.repeat.count--;\\r
-    }\\r
-    else if (stk->type == STK_MEM_END) {\\r
-      mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\\r
-      mem_end_stk[stk->u.mem.num]   = stk->u.mem.end;\\r
-    }\\r
-    ELSE_IF_STATE_CHECK_MARK(stk);\\r
-  }\\r
+#define STACK_POP_TIL_ALT_PREC_READ_NOT  do {\\r
+  POP_TIL_BODY("STACK_POP_TIL_ALT_PREC_READ_NOT", STK_ALT_PREC_READ_NOT);\\r
 } while(0)\r
 \r
-#define STACK_POS_END(k) do {\\r
-  k = stk;\\r
-  while (1) {\\r
-    k--;\\r
-    STACK_BASE_CHECK(k, "STACK_POS_END"); \\r
-    if (IS_TO_VOID_TARGET(k)) {\\r
-      k->type = STK_VOID;\\r
-    }\\r
-    else if (k->type == STK_POS) {\\r
-      k->type = STK_VOID;\\r
-      break;\\r
-    }\\r
-  }\\r
+#define STACK_POP_TIL_ALT_LOOK_BEHIND_NOT  do {\\r
+  POP_TIL_BODY("STACK_POP_TIL_ALT_LOOK_BEHIND_NOT", STK_ALT_LOOK_BEHIND_NOT);\\r
 } while(0)\r
 \r
-#define STACK_STOP_BT_END do {\\r
-  OnigStackType *k = stk;\\r
+\r
+#define STACK_EXEC_TO_VOID(k) do {\\r
+  k = stk;\\r
   while (1) {\\r
     k--;\\r
-    STACK_BASE_CHECK(k, "STACK_STOP_BT_END"); \\r
+    STACK_BASE_CHECK(k, "STACK_EXEC_TO_VOID"); \\r
     if (IS_TO_VOID_TARGET(k)) {\\r
+      if (k->type == STK_TO_VOID_START) {\\r
+        k->type = STK_VOID;\\r
+        break;\\r
+      }\\r
       k->type = STK_VOID;\\r
     }\\r
-    else if (k->type == STK_STOP_BT) {\\r
-      k->type = STK_VOID;\\r
-      break;\\r
-    }\\r
   }\\r
 } while(0)\r
 \r
-#define STACK_NULL_CHECK(isnull,id,s) do {\\r
-  OnigStackType* k = stk;\\r
+#define STACK_EMPTY_CHECK(isnull,sid,s) do {\\r
+  StackType* k = stk;\\r
   while (1) {\\r
     k--;\\r
-    STACK_BASE_CHECK(k, "STACK_NULL_CHECK"); \\r
-    if (k->type == STK_NULL_CHECK_START) {\\r
-      if (k->u.null_check.num == (id)) {\\r
-        (isnull) = (k->u.null_check.pstr == (s));\\r
+    STACK_BASE_CHECK(k, "STACK_EMPTY_CHECK"); \\r
+    if (k->type == STK_EMPTY_CHECK_START) {\\r
+      if (k->zid == (sid)) {\\r
+        (isnull) = (k->u.empty_check.pstr == (s));\\r
         break;\\r
       }\\r
     }\\r
   }\\r
 } while(0)\r
 \r
-#define STACK_NULL_CHECK_REC(isnull,id,s) do {\\r
-  int level = 0;\\r
-  OnigStackType* k = stk;\\r
-  while (1) {\\r
-    k--;\\r
-    STACK_BASE_CHECK(k, "STACK_NULL_CHECK_REC"); \\r
-    if (k->type == STK_NULL_CHECK_START) {\\r
-      if (k->u.null_check.num == (id)) {\\r
-        if (level == 0) {\\r
-          (isnull) = (k->u.null_check.pstr == (s));\\r
-          break;\\r
-        }\\r
-        else level--;\\r
-      }\\r
-    }\\r
-    else if (k->type == STK_NULL_CHECK_END) {\\r
-      level++;\\r
-    }\\r
+#define STACK_MEM_START_GET_PREV_END_ADDR(k /* STK_MEM_START*/, reg, addr) do {\\r
+  if (k->u.mem.prev_end == INVALID_STACK_INDEX) {\\r
+    (addr) = 0;\\r
   }\\r
-} while(0)\r
+  else {\\r
+    if (MEM_STATUS_AT((reg)->bt_mem_end, k->zid))\\r
+      (addr) = STACK_AT(k->u.mem.prev_end)->u.mem.pstr;\\r
+    else\\r
+      (addr) = (UChar* )k->u.mem.prev_end;\\r
+  }\\r
+} while (0)\r
 \r
-#define STACK_NULL_CHECK_MEMST(isnull,id,s,reg) do {\\r
-  OnigStackType* k = stk;\\r
+#ifdef USE_INSISTENT_CHECK_CAPTURES_IN_EMPTY_REPEAT\r
+#define STACK_EMPTY_CHECK_MEM(isnull,sid,s,reg) do {\\r
+  StackType* k = stk;\\r
   while (1) {\\r
     k--;\\r
-    STACK_BASE_CHECK(k, "STACK_NULL_CHECK_MEMST"); \\r
-    if (k->type == STK_NULL_CHECK_START) {\\r
-      if (k->u.null_check.num == (id)) {\\r
-        if (k->u.null_check.pstr != (s)) {\\r
+    STACK_BASE_CHECK(k, "STACK_EMPTY_CHECK_MEM"); \\r
+    if (k->type == STK_EMPTY_CHECK_START) {\\r
+      if (k->zid == (sid)) {\\r
+        if (k->u.empty_check.pstr != (s)) {\\r
           (isnull) = 0;\\r
           break;\\r
         }\\r
@@ -863,14 +1900,11 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
           (isnull) = 1;\\r
           while (k < stk) {\\r
             if (k->type == STK_MEM_START) {\\r
-              if (k->u.mem.end == INVALID_STACK_INDEX) {\\r
+              STACK_MEM_START_GET_PREV_END_ADDR(k, reg, endp);\\r
+              if (endp == 0) {\\r
                 (isnull) = 0; break;\\r
               }\\r
-              if (BIT_STATUS_AT(reg->bt_mem_end, k->u.mem.num))\\r
-                endp = STACK_AT(k->u.mem.end)->u.mem.pstr;\\r
-              else\\r
-                endp = (UChar* )(UINTN)k->u.mem.end;\\r
-              if (STACK_AT(k->u.mem.start)->u.mem.pstr != endp) {\\r
+              else if (STACK_AT(k->u.mem.prev_start)->u.mem.pstr != endp) {\\r
                 (isnull) = 0; break;\\r
               }\\r
               else if (endp != s) {\\r
@@ -879,23 +1913,23 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
             }\\r
             k++;\\r
           }\\r
-         break;\\r
+          break;\\r
         }\\r
       }\\r
     }\\r
   }\\r
 } while(0)\r
 \r
-#define STACK_NULL_CHECK_MEMST_REC(isnull,id,s,reg) do {\\r
+#define STACK_EMPTY_CHECK_MEM_REC(isnull,sid,s,reg) do {\\r
   int level = 0;\\r
-  OnigStackType* k = stk;\\r
+  StackType* k = stk;\\r
   while (1) {\\r
     k--;\\r
-    STACK_BASE_CHECK(k, "STACK_NULL_CHECK_MEMST_REC"); \\r
-    if (k->type == STK_NULL_CHECK_START) {\\r
-      if (k->u.null_check.num == (id)) {\\r
+    STACK_BASE_CHECK(k, "STACK_EMPTY_CHECK_MEM_REC");\\r
+    if (k->type == STK_EMPTY_CHECK_START) {\\r
+      if (k->zid == (sid)) {\\r
         if (level == 0) {\\r
-          if (k->u.null_check.pstr != (s)) {\\r
+          if (k->u.empty_check.pstr != (s)) {\\r
             (isnull) = 0;\\r
             break;\\r
           }\\r
@@ -904,23 +1938,28 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
             (isnull) = 1;\\r
             while (k < stk) {\\r
               if (k->type == STK_MEM_START) {\\r
-                if (k->u.mem.end == INVALID_STACK_INDEX) {\\r
-                  (isnull) = 0; break;\\r
-                }\\r
-                if (BIT_STATUS_AT(reg->bt_mem_end, k->u.mem.num))\\r
-                  endp = STACK_AT(k->u.mem.end)->u.mem.pstr;\\r
-                else\\r
-                  endp = (UChar* )(UINTN)k->u.mem.end;\\r
-                if (STACK_AT(k->u.mem.start)->u.mem.pstr != endp) {\\r
-                  (isnull) = 0; break;\\r
-                }\\r
-                else if (endp != s) {\\r
-                  (isnull) = -1; /* empty, but position changed */ \\r
+                if (level == 0) {\\r
+                  STACK_MEM_START_GET_PREV_END_ADDR(k, reg, endp);\\r
+                  if (endp == 0) {\\r
+                    (isnull) = 0; break;\\r
+                  }\\r
+                  else if (STACK_AT(k->u.mem.prev_start)->u.mem.pstr != endp) { \\r
+                    (isnull) = 0; break;\\r
+                  }\\r
+                  else if (endp != s) {\\r
+                    (isnull) = -1; /* empty, but position changed */\\r
+                  }\\r
                 }\\r
               }\\r
+              else if (k->type == STK_EMPTY_CHECK_START) {\\r
+                if (k->zid == (sid)) level++;\\r
+              }\\r
+              else if (k->type == STK_EMPTY_CHECK_END) {\\r
+                if (k->zid == (sid)) level--;\\r
+              }\\r
               k++;\\r
             }\\r
-           break;\\r
+            break;\\r
           }\\r
         }\\r
         else {\\r
@@ -928,13 +1967,35 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
         }\\r
       }\\r
     }\\r
-    else if (k->type == STK_NULL_CHECK_END) {\\r
-      if (k->u.null_check.num == (id)) level++;\\r
+    else if (k->type == STK_EMPTY_CHECK_END) {\\r
+      if (k->zid == (sid)) level++;\\r
+    }\\r
+  }\\r
+} while(0)\r
+#else\r
+#define STACK_EMPTY_CHECK_REC(isnull,id,s) do {\\r
+  int level = 0;\\r
+  StackType* k = stk;\\r
+  while (1) {\\r
+    k--;\\r
+    STACK_BASE_CHECK(k, "STACK_EMPTY_CHECK_REC"); \\r
+    if (k->type == STK_EMPTY_CHECK_START) {\\r
+      if (k->u.empty_check.num == (id)) {\\r
+        if (level == 0) {\\r
+          (isnull) = (k->u.empty_check.pstr == (s));\\r
+          break;\\r
+        }\\r
+      }\\r
+      level--;\\r
+    }\\r
+    else if (k->type == STK_EMPTY_CHECK_END) {\\r
+      level++;\\r
     }\\r
   }\\r
 } while(0)\r
+#endif /* USE_INSISTENT_CHECK_CAPTURES_IN_EMPTY_REPEAT */\r
 \r
-#define STACK_GET_REPEAT(id, k) do {\\r
+#define STACK_GET_REPEAT(sid, k) do {\\r
   int level = 0;\\r
   k = stk;\\r
   while (1) {\\r
@@ -942,7 +2003,7 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
     STACK_BASE_CHECK(k, "STACK_GET_REPEAT"); \\r
     if (k->type == STK_REPEAT) {\\r
       if (level == 0) {\\r
-        if (k->u.repeat.num == (id)) {\\r
+        if (k->zid == (sid)) {\\r
           break;\\r
         }\\r
       }\\r
@@ -954,7 +2015,7 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
 \r
 #define STACK_RETURN(addr)  do {\\r
   int level = 0;\\r
-  OnigStackType* k = stk;\\r
+  StackType* k = stk;\\r
   while (1) {\\r
     k--;\\r
     STACK_BASE_CHECK(k, "STACK_RETURN"); \\r
@@ -983,7 +2044,7 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
 } while(0)\r
 \r
 static int string_cmp_ic(OnigEncoding enc, int case_fold_flag,\r
-                        UChar* s1, UChar** ps2, int mblen)\r
+                         UChar* s1, UChar** ps2, int mblen)\r
 {\r
   UChar buf1[ONIGENC_MBC_CASE_FOLD_MAXLEN];\r
   UChar buf2[ONIGENC_MBC_CASE_FOLD_MAXLEN];\r
@@ -1028,33 +2089,28 @@ static int string_cmp_ic(OnigEncoding enc, int case_fold_flag,
 \r
 \r
 #define IS_EMPTY_STR           (str == end)\r
-#define ON_STR_BEGIN(s)       ((s) == str)\r
-#define ON_STR_END(s)         ((s) == end)\r
-#ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE\r
+#define ON_STR_BEGIN(s)        ((s) == str)\r
+#define ON_STR_END(s)          ((s) == end)\r
 #define DATA_ENSURE_CHECK1     (s < right_range)\r
 #define DATA_ENSURE_CHECK(n)   (s + (n) <= right_range)\r
 #define DATA_ENSURE(n)         if (s + (n) > right_range) goto fail\r
-#else\r
-#define DATA_ENSURE_CHECK1     (s < end)\r
-#define DATA_ENSURE_CHECK(n)   (s + (n) <= end)\r
-#define DATA_ENSURE(n)         if (s + (n) > end) goto fail\r
-#endif /* USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE */\r
 \r
+#define INIT_RIGHT_RANGE    right_range = (UChar* )in_right_range\r
 \r
 #ifdef USE_CAPTURE_HISTORY\r
 static int\r
-make_capture_history_tree(OnigCaptureTreeNode* node, OnigStackType** kp,\r
-                          OnigStackType* stk_top, UChar* str, regex_t* reg)\r
+make_capture_history_tree(OnigCaptureTreeNode* node, StackType** kp,\r
+                          StackType* stk_top, UChar* str, regex_t* reg)\r
 {\r
   int n, r;\r
   OnigCaptureTreeNode* child;\r
-  OnigStackType* k = *kp;\r
+  StackType* k = *kp;\r
 \r
   while (k < stk_top) {\r
     if (k->type == STK_MEM_START) {\r
-      n = k->u.mem.num;\r
+      n = k->zid;\r
       if (n <= ONIG_MAX_CAPTURE_HISTORY_GROUP &&\r
-          BIT_STATUS_AT(reg->capture_history, n) != 0) {\r
+          MEM_STATUS_AT(reg->capture_history, n) != 0) {\r
         child = history_node_new();\r
         CHECK_NULL_RETURN_MEMERR(child);\r
         child->group = n;\r
@@ -1070,7 +2126,7 @@ make_capture_history_tree(OnigCaptureTreeNode* node, OnigStackType** kp,
       }\r
     }\r
     else if (k->type == STK_MEM_END) {\r
-      if (k->u.mem.num == node->group) {\r
+      if (k->zid == node->group) {\r
         node->end = (int )(k->u.mem.pstr - str);\r
         *kp = k;\r
         return 0;\r
@@ -1096,14 +2152,16 @@ static int mem_is_in_memp(int mem, int num, UChar* memp)
   return 0;\r
 }\r
 \r
-static int backref_match_at_nested_level(regex_t* reg\r
-        , OnigStackType* top, OnigStackType* stk_base\r
-        , int ignore_case, int case_fold_flag\r
-        , int nest, int mem_num, UChar* memp, UChar** s, const UChar* send)\r
+static int\r
+backref_match_at_nested_level(regex_t* reg,\r
+                              StackType* top, StackType* stk_base,\r
+                              int ignore_case, int case_fold_flag,\r
+                              int nest, int mem_num, UChar* memp,\r
+                              UChar** s, const UChar* send)\r
 {\r
   UChar *ss, *p, *pstart, *pend = NULL_UCHARP;\r
   int level;\r
-  OnigStackType* k;\r
+  StackType* k;\r
 \r
   level = 0;\r
   k = top;\r
@@ -1117,33 +2175,64 @@ static int backref_match_at_nested_level(regex_t* reg
     }\r
     else if (level == nest) {\r
       if (k->type == STK_MEM_START) {\r
-       if (mem_is_in_memp(k->u.mem.num, mem_num, memp)) {\r
-         pstart = k->u.mem.pstr;\r
-         if (pend != NULL_UCHARP) {\r
-           if (pend - pstart > send - *s) return 0; /* or goto next_mem; */\r
-           p  = pstart;\r
-           ss = *s;\r
-\r
-           if (ignore_case != 0) {\r
-             if (string_cmp_ic(reg->enc, case_fold_flag,\r
-                               pstart, &ss, (int )(pend - pstart)) == 0)\r
-               return 0; /* or goto next_mem; */\r
-           }\r
-           else {\r
-             while (p < pend) {\r
-               if (*p++ != *ss++) return 0; /* or goto next_mem; */\r
-             }\r
-           }\r
-\r
-           *s = ss;\r
-           return 1;\r
-         }\r
-       }\r
+        if (mem_is_in_memp(k->zid, mem_num, memp)) {\r
+          pstart = k->u.mem.pstr;\r
+          if (IS_NOT_NULL(pend)) {\r
+            if (pend - pstart > send - *s) return 0; /* or goto next_mem; */\r
+            p  = pstart;\r
+            ss = *s;\r
+\r
+            if (ignore_case != 0) {\r
+              if (string_cmp_ic(reg->enc, case_fold_flag,\r
+                                pstart, &ss, (int )(pend - pstart)) == 0)\r
+                return 0; /* or goto next_mem; */\r
+            }\r
+            else {\r
+              while (p < pend) {\r
+                if (*p++ != *ss++) return 0; /* or goto next_mem; */\r
+              }\r
+            }\r
+\r
+            *s = ss;\r
+            return 1;\r
+          }\r
+        }\r
       }\r
       else if (k->type == STK_MEM_END) {\r
-       if (mem_is_in_memp(k->u.mem.num, mem_num, memp)) {\r
-         pend = k->u.mem.pstr;\r
-       }\r
+        if (mem_is_in_memp(k->zid, mem_num, memp)) {\r
+          pend = k->u.mem.pstr;\r
+        }\r
+      }\r
+    }\r
+    k--;\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+static int\r
+backref_check_at_nested_level(regex_t* reg,\r
+                              StackType* top, StackType* stk_base,\r
+                              int nest, int mem_num, UChar* memp)\r
+{\r
+  int level;\r
+  StackType* k;\r
+\r
+  level = 0;\r
+  k = top;\r
+  k--;\r
+  while (k >= stk_base) {\r
+    if (k->type == STK_CALL_FRAME) {\r
+      level--;\r
+    }\r
+    else if (k->type == STK_RETURN) {\r
+      level++;\r
+    }\r
+    else if (level == nest) {\r
+      if (k->type == STK_MEM_END) {\r
+        if (mem_is_in_memp(k->zid, mem_num, memp)) {\r
+          return 1;\r
+        }\r
       }\r
     }\r
     k--;\r
@@ -1185,14 +2274,14 @@ static int OpCurr = OP_FINISH;
 static int OpPrevTarget = OP_FAIL;\r
 static int MaxStackDepth = 0;\r
 \r
-#define MOP_IN(opcode) do {\\r
+#define SOP_IN(opcode) do {\\r
   if (opcode == OpPrevTarget) OpPrevCounter[OpCurr]++;\\r
   OpCurr = opcode;\\r
   OpCounter[opcode]++;\\r
   GETTIME(ts);\\r
 } while(0)\r
 \r
-#define MOP_OUT do {\\r
+#define SOP_OUT do {\\r
   GETTIME(te);\\r
   OpTime[OpCurr] += TIMEDIFF(te, ts);\\r
 } while(0)\r
@@ -1207,16 +2296,24 @@ onig_statistics_init(void)
   MaxStackDepth = 0;\r
 }\r
 \r
-extern void\r
+extern int\r
 onig_print_statistics(FILE* f)\r
 {\r
+  int r;\r
   int i;\r
-  fprintf(f, "   count      prev        time\n");\r
-  for (i = 0; OnigOpInfo[i].opcode >= 0; i++) {\r
-    fprintf(f, "%8d: %8d: %10ld: %s\n",\r
-           OpCounter[i], OpPrevCounter[i], OpTime[i], OnigOpInfo[i].name);\r
+\r
+  r = fprintf(f, "   count      prev        time\n");\r
+  if (r < 0) return -1;\r
+\r
+  for (i = 0; OpInfo[i].opcode >= 0; i++) {\r
+    r = fprintf(f, "%8d: %8d: %10ld: %s\n",\r
+                OpCounter[i], OpPrevCounter[i], OpTime[i], OpInfo[i].name);\r
+    if (r < 0) return -1;\r
   }\r
-  fprintf(f, "\nmax stack depth: %d\n", MaxStackDepth);\r
+  r = fprintf(f, "\nmax stack depth: %d\n", MaxStackDepth);\r
+  if (r < 0) return -1;\r
+\r
+  return 0;\r
 }\r
 \r
 #define STACK_INC do {\\r
@@ -1228,8 +2325,8 @@ onig_print_statistics(FILE* f)
 #else\r
 #define STACK_INC     stk++\r
 \r
-#define MOP_IN(opcode)\r
-#define MOP_OUT\r
+#define SOP_IN(opcode)\r
+#define SOP_OUT\r
 #endif\r
 \r
 \r
@@ -1245,10 +2342,8 @@ typedef struct {
 /* if sstart == str then set sprev to NULL. */\r
 static int\r
 match_at(regex_t* reg, const UChar* str, const UChar* end,\r
-#ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE\r
-        const UChar* right_range,\r
-#endif\r
-        const UChar* sstart, UChar* sprev, OnigMatchArg* msa)\r
+         const UChar* in_right_range, const UChar* sstart, UChar* sprev,\r
+         MatchArg* msa)\r
 {\r
   static UChar FinishCode[] = { OP_FINISH };\r
 \r
@@ -1256,133 +2351,159 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
   LengthType tlen, tlen2;\r
   MemNumType mem;\r
   RelAddrType addr;\r
+  UChar *s, *q, *sbegin;\r
+  UChar *right_range;\r
+  int is_alloca;\r
+  char *alloc_base;\r
+  StackType *stk_base, *stk, *stk_end;\r
+  StackType *stkp; /* used as any purpose. */\r
+  StackIndex si;\r
+  StackIndex *repeat_stk;\r
+  StackIndex *mem_start_stk, *mem_end_stk;\r
+  UChar* keep;\r
+#ifdef USE_RETRY_LIMIT_IN_MATCH\r
+  unsigned long retry_limit_in_match;\r
+  unsigned long retry_in_match_counter;\r
+#endif\r
+\r
+#ifdef USE_CALLOUT\r
+  int of;\r
+#endif\r
+\r
+  UChar *p = reg->p;\r
   OnigOptionType option = reg->options;\r
   OnigEncoding encode = reg->enc;\r
   OnigCaseFoldType case_fold_flag = reg->case_fold_flag;\r
-  UChar *s, *q, *sbegin;\r
-  UChar *p = reg->p;\r
-  char *alloca_base;\r
-  OnigStackType *stk_alloc, *stk_base, *stk, *stk_end;\r
-  OnigStackType *stkp; /* used as any purpose. */\r
-  OnigStackIndex si;\r
-  OnigStackIndex *repeat_stk;\r
-  OnigStackIndex *mem_start_stk, *mem_end_stk;\r
-#ifdef USE_COMBINATION_EXPLOSION_CHECK\r
-  int scv;\r
-  unsigned char* state_check_buff = msa->state_check_buff;\r
-  int num_comb_exp_check = reg->num_comb_exp_check;\r
-#endif\r
-  n = reg->num_repeat + reg->num_mem * 2;\r
-\r
-  STACK_INIT(alloca_base, n, INIT_MATCH_STACK_SIZE);\r
+\r
+#ifdef USE_CALLOUT\r
+  msa->mp->match_at_call_counter++;\r
+#endif\r
+\r
+#ifdef USE_RETRY_LIMIT_IN_MATCH\r
+  retry_limit_in_match = msa->retry_limit_in_match;\r
+#endif\r
+\r
   pop_level = reg->stack_pop_level;\r
   num_mem = reg->num_mem;\r
-  repeat_stk = (OnigStackIndex* )alloca_base;\r
-\r
-  mem_start_stk = (OnigStackIndex* )(repeat_stk + reg->num_repeat);\r
-  mem_end_stk   = mem_start_stk + num_mem;\r
-  mem_start_stk--; /* for index start from 1,\r
-                     mem_start_stk[1]..mem_start_stk[num_mem] */\r
-  mem_end_stk--;   /* for index start from 1,\r
-                     mem_end_stk[1]..mem_end_stk[num_mem] */\r
+  STACK_INIT(INIT_MATCH_STACK_SIZE);\r
+  UPDATE_FOR_STACK_REALLOC;\r
   for (i = 1; i <= num_mem; i++) {\r
     mem_start_stk[i] = mem_end_stk[i] = INVALID_STACK_INDEX;\r
   }\r
 \r
 #ifdef ONIG_DEBUG_MATCH\r
-  fprintf(stderr, "match_at: str: %d, end: %d, start: %d, sprev: %d\n",\r
-         (int )str, (int )end, (int )sstart, (int )sprev);\r
+  fprintf(stderr, "match_at: str: %p, end: %p, start: %p, sprev: %p\n",\r
+          str, end, sstart, sprev);\r
   fprintf(stderr, "size: %d, start offset: %d\n",\r
-         (int )(end - str), (int )(sstart - str));\r
+          (int )(end - str), (int )(sstart - str));\r
 #endif\r
 \r
-  STACK_PUSH_ENSURED(STK_ALT, FinishCode);  /* bottom stack */\r
   best_len = ONIG_MISMATCH;\r
-  s = (UChar* )sstart;\r
+  keep = s = (UChar* )sstart;\r
+  STACK_PUSH_BOTTOM(STK_ALT, FinishCode);  /* bottom stack */\r
+  INIT_RIGHT_RANGE;\r
+\r
+#ifdef USE_RETRY_LIMIT_IN_MATCH\r
+  retry_in_match_counter = 0;\r
+#endif\r
+\r
   while (1) {\r
 #ifdef ONIG_DEBUG_MATCH\r
     {\r
+      static unsigned int counter = 1;\r
+\r
       UChar *q, *bp, buf[50];\r
       int len;\r
-      fprintf(stderr, "%4d> \"", (int )(s - str));\r
+      fprintf(stderr, "%7u: %7ld: %4d> \"",\r
+              counter, GET_STACK_INDEX(stk), (int )(s - str));\r
+      counter++;\r
+\r
       bp = buf;\r
       for (i = 0, q = s; i < 7 && q < end; i++) {\r
-       len = enclen(encode, q);\r
-       while (len-- > 0) *bp++ = *q++;\r
+        len = enclen(encode, q);\r
+        while (len-- > 0) *bp++ = *q++;\r
       }\r
       if (q < end) { xmemcpy(bp, "...\"", 4); bp += 4; }\r
       else         { xmemcpy(bp, "\"",    1); bp += 1; }\r
       *bp = 0;\r
       fputs((char* )buf, stderr);\r
+\r
       for (i = 0; i < 20 - (bp - buf); i++) fputc(' ', stderr);\r
-      onig_print_compiled_byte_code(stderr, p, NULL, encode);\r
+      if (p == FinishCode)\r
+        fprintf(stderr, "----: ");\r
+      else\r
+        fprintf(stderr, "%4d: ", (int )(p - reg->p));\r
+      onig_print_compiled_byte_code(stderr, p, NULL, reg->p, encode);\r
       fprintf(stderr, "\n");\r
     }\r
 #endif\r
 \r
     sbegin = s;\r
     switch (*p++) {\r
-    case OP_END:  MOP_IN(OP_END);\r
-      n = (int)(s - sstart);\r
+    case OP_END:  SOP_IN(OP_END);\r
+      n = (int )(s - sstart);\r
       if (n > best_len) {\r
-       OnigRegion* region;\r
+        OnigRegion* region;\r
 #ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE\r
-       if (IS_FIND_LONGEST(option)) {\r
-         if (n > msa->best_len) {\r
-           msa->best_len = n;\r
-           msa->best_s   = (UChar* )sstart;\r
-         }\r
-         else\r
-           goto end_best_len;\r
+        if (IS_FIND_LONGEST(option)) {\r
+          if (n > msa->best_len) {\r
+            msa->best_len = n;\r
+            msa->best_s   = (UChar* )sstart;\r
+          }\r
+          else\r
+            goto end_best_len;\r
         }\r
 #endif\r
-       best_len = n;\r
-       region = msa->region;\r
-       if (region) {\r
+        best_len = n;\r
+        region = msa->region;\r
+        if (region) {\r
+          if (keep > s) keep = s;\r
+\r
 #ifdef USE_POSIX_API_REGION_OPTION\r
-         if (IS_POSIX_REGION(msa->options)) {\r
-           posix_regmatch_t* rmt = (posix_regmatch_t* )region;\r
-\r
-           rmt[0].rm_so = (regoff_t)(sstart - str);\r
-           rmt[0].rm_eo = (regoff_t)(s      - str);\r
-           for (i = 1; i <= num_mem; i++) {\r
-             if (mem_end_stk[i] != INVALID_STACK_INDEX) {\r
-               if (BIT_STATUS_AT(reg->bt_mem_start, i))\r
-                 rmt[i].rm_so = (regoff_t)(STACK_AT(mem_start_stk[i])->u.mem.pstr - str);\r
-               else\r
-                 rmt[i].rm_so = (regoff_t)((UChar* )((void* )(UINTN)(mem_start_stk[i])) - str);\r
-\r
-               rmt[i].rm_eo = (regoff_t)((BIT_STATUS_AT(reg->bt_mem_end, i)\r
-                               ? STACK_AT(mem_end_stk[i])->u.mem.pstr\r
-                               : (UChar* )((void* )(UINTN)mem_end_stk[i])) - str);\r
-             }\r
-             else {\r
-               rmt[i].rm_so = rmt[i].rm_eo = ONIG_REGION_NOTPOS;\r
-             }\r
-           }\r
-         }\r
-         else {\r
+          if (IS_POSIX_REGION(msa->options)) {\r
+            posix_regmatch_t* rmt = (posix_regmatch_t* )region;\r
+\r
+            rmt[0].rm_so = (regoff_t )(keep - str);\r
+            rmt[0].rm_eo = (regoff_t )(s    - str);\r
+            for (i = 1; i <= num_mem; i++) {\r
+              if (mem_end_stk[i] != INVALID_STACK_INDEX) {\r
+                if (MEM_STATUS_AT(reg->bt_mem_start, i))\r
+                  rmt[i].rm_so = (regoff_t )(STACK_AT(mem_start_stk[i])->u.mem.pstr - str);\r
+                else\r
+                  rmt[i].rm_so = (regoff_t )((UChar* )((void* )(mem_start_stk[i])) - str);\r
+\r
+                rmt[i].rm_eo = (regoff_t )((MEM_STATUS_AT(reg->bt_mem_end, i)\r
+                                            ? STACK_AT(mem_end_stk[i])->u.mem.pstr\r
+                                            : (UChar* )((void* )mem_end_stk[i]))\r
+                                           - str);\r
+              }\r
+              else {\r
+                rmt[i].rm_so = rmt[i].rm_eo = ONIG_REGION_NOTPOS;\r
+              }\r
+            }\r
+          }\r
+          else {\r
 #endif /* USE_POSIX_API_REGION_OPTION */\r
-           region->beg[0] = (int)(sstart - str);\r
-           region->end[0] = (int)(s      - str);\r
-           for (i = 1; i <= num_mem; i++) {\r
-             if (mem_end_stk[i] != INVALID_STACK_INDEX) {\r
-               if (BIT_STATUS_AT(reg->bt_mem_start, i))\r
-                 region->beg[i] = (int)(STACK_AT(mem_start_stk[i])->u.mem.pstr - str);\r
-               else\r
-                 region->beg[i] = (int)((UChar* )((void* )(UINTN)mem_start_stk[i]) - str);\r
-\r
-               region->end[i] = (int)((BIT_STATUS_AT(reg->bt_mem_end, i)\r
-                                 ? STACK_AT(mem_end_stk[i])->u.mem.pstr\r
-                                 : (UChar* )((void* )(UINTN)mem_end_stk[i])) - str);\r
-             }\r
-             else {\r
-               region->beg[i] = region->end[i] = ONIG_REGION_NOTPOS;\r
-             }\r
-           }\r
+            region->beg[0] = (int )(keep - str);\r
+            region->end[0] = (int )(s    - str);\r
+            for (i = 1; i <= num_mem; i++) {\r
+              if (mem_end_stk[i] != INVALID_STACK_INDEX) {\r
+                if (MEM_STATUS_AT(reg->bt_mem_start, i))\r
+                  region->beg[i] = (int )(STACK_AT(mem_start_stk[i])->u.mem.pstr - str);\r
+                else\r
+                  region->beg[i] = (int )((UChar* )((void* )mem_start_stk[i]) - str);\r
+\r
+                region->end[i] = (int )((MEM_STATUS_AT(reg->bt_mem_end, i)\r
+                                         ? STACK_AT(mem_end_stk[i])->u.mem.pstr\r
+                                         : (UChar* )((void* )mem_end_stk[i])) - str);\r
+              }\r
+              else {\r
+                region->beg[i] = region->end[i] = ONIG_REGION_NOTPOS;\r
+              }\r
+            }\r
 \r
 #ifdef USE_CAPTURE_HISTORY\r
-           if (reg->capture_history != 0) {\r
+            if (reg->capture_history != 0) {\r
               int r;\r
               OnigCaptureTreeNode* node;\r
 \r
@@ -1396,8 +2517,8 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
               }\r
 \r
               node->group = 0;\r
-              node->beg   = (int)(sstart - str);\r
-              node->end   = (int)(s      - str);\r
+              node->beg   = (int )(keep - str);\r
+              node->end   = (int )(s    - str);\r
 \r
               stkp = stk_base;\r
               r = make_capture_history_tree(region->history_root, &stkp,\r
@@ -1406,79 +2527,74 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
                 best_len = r; /* error code */\r
                 goto finish;\r
               }\r
-           }\r
+            }\r
 #endif /* USE_CAPTURE_HISTORY */\r
 #ifdef USE_POSIX_API_REGION_OPTION\r
-         } /* else IS_POSIX_REGION() */\r
+          } /* else IS_POSIX_REGION() */\r
 #endif\r
-       } /* if (region) */\r
+        } /* if (region) */\r
       } /* n > best_len */\r
 \r
 #ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE\r
     end_best_len:\r
 #endif\r
-      MOP_OUT;\r
+      SOP_OUT;\r
 \r
       if (IS_FIND_CONDITION(option)) {\r
-       if (IS_FIND_NOT_EMPTY(option) && s == sstart) {\r
-         best_len = ONIG_MISMATCH;\r
-         goto fail; /* for retry */\r
-       }\r
-       if (IS_FIND_LONGEST(option) && DATA_ENSURE_CHECK1) {\r
-         goto fail; /* for retry */\r
-       }\r
+        if (IS_FIND_NOT_EMPTY(option) && s == sstart) {\r
+          best_len = ONIG_MISMATCH;\r
+          goto fail; /* for retry */\r
+        }\r
+        if (IS_FIND_LONGEST(option) && DATA_ENSURE_CHECK1) {\r
+          goto fail; /* for retry */\r
+        }\r
       }\r
 \r
       /* default behavior: return first-matching result. */\r
       goto finish;\r
       break;\r
 \r
-    case OP_EXACT1:  MOP_IN(OP_EXACT1);\r
-#if 0\r
+    case OP_EXACT1:  SOP_IN(OP_EXACT1);\r
       DATA_ENSURE(1);\r
       if (*p != *s) goto fail;\r
       p++; s++;\r
-#endif\r
-      if (*p != *s++) goto fail;\r
-      DATA_ENSURE(0);\r
-      p++;\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       break;\r
 \r
-    case OP_EXACT1_IC:  MOP_IN(OP_EXACT1_IC);\r
+    case OP_EXACT1_IC:  SOP_IN(OP_EXACT1_IC);\r
       {\r
-       int len;\r
-       UChar *q1, lowbuf[ONIGENC_MBC_CASE_FOLD_MAXLEN];\r
-\r
-       DATA_ENSURE(1);\r
-       len = ONIGENC_MBC_CASE_FOLD(encode,\r
-                   /* DISABLE_CASE_FOLD_MULTI_CHAR(case_fold_flag), */\r
-                   case_fold_flag,\r
-                   &s, end, lowbuf);\r
-       DATA_ENSURE(0);\r
-       q1 = lowbuf;\r
-       while (len-- > 0) {\r
-         if (*p != *q1) {\r
+        int len;\r
+        UChar *q, lowbuf[ONIGENC_MBC_CASE_FOLD_MAXLEN];\r
+\r
+        DATA_ENSURE(1);\r
+        len = ONIGENC_MBC_CASE_FOLD(encode,\r
+                 /* DISABLE_CASE_FOLD_MULTI_CHAR(case_fold_flag), */\r
+                                    case_fold_flag,\r
+                                    &s, end, lowbuf);\r
+        DATA_ENSURE(0);\r
+        q = lowbuf;\r
+        while (len-- > 0) {\r
+          if (*p != *q) {\r
             goto fail;\r
           }\r
-         p++; q1++;\r
-       }\r
+          p++; q++;\r
+        }\r
       }\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       break;\r
 \r
-    case OP_EXACT2:  MOP_IN(OP_EXACT2);\r
+    case OP_EXACT2:  SOP_IN(OP_EXACT2);\r
       DATA_ENSURE(2);\r
       if (*p != *s) goto fail;\r
       p++; s++;\r
       if (*p != *s) goto fail;\r
       sprev = s;\r
       p++; s++;\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_EXACT3:  MOP_IN(OP_EXACT3);\r
+    case OP_EXACT3:  SOP_IN(OP_EXACT3);\r
       DATA_ENSURE(3);\r
       if (*p != *s) goto fail;\r
       p++; s++;\r
@@ -1487,11 +2603,11 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
       if (*p != *s) goto fail;\r
       sprev = s;\r
       p++; s++;\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_EXACT4:  MOP_IN(OP_EXACT4);\r
+    case OP_EXACT4:  SOP_IN(OP_EXACT4);\r
       DATA_ENSURE(4);\r
       if (*p != *s) goto fail;\r
       p++; s++;\r
@@ -1502,11 +2618,11 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
       if (*p != *s) goto fail;\r
       sprev = s;\r
       p++; s++;\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_EXACT5:  MOP_IN(OP_EXACT5);\r
+    case OP_EXACT5:  SOP_IN(OP_EXACT5);\r
       DATA_ENSURE(5);\r
       if (*p != *s) goto fail;\r
       p++; s++;\r
@@ -1519,59 +2635,59 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
       if (*p != *s) goto fail;\r
       sprev = s;\r
       p++; s++;\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_EXACTN:  MOP_IN(OP_EXACTN);\r
+    case OP_EXACTN:  SOP_IN(OP_EXACTN);\r
       GET_LENGTH_INC(tlen, p);\r
       DATA_ENSURE(tlen);\r
       while (tlen-- > 0) {\r
-       if (*p++ != *s++) goto fail;\r
+        if (*p++ != *s++) goto fail;\r
       }\r
       sprev = s - 1;\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_EXACTN_IC:  MOP_IN(OP_EXACTN_IC);\r
+    case OP_EXACTN_IC:  SOP_IN(OP_EXACTN_IC);\r
       {\r
-       int len;\r
-       UChar *qn, *endp, lowbuf[ONIGENC_MBC_CASE_FOLD_MAXLEN];\r
-\r
-       GET_LENGTH_INC(tlen, p);\r
-       endp = p + tlen;\r
-\r
-       while (p < endp) {\r
-         sprev = s;\r
-         DATA_ENSURE(1);\r
-         len = ONIGENC_MBC_CASE_FOLD(encode,\r
-                     /* DISABLE_CASE_FOLD_MULTI_CHAR(case_fold_flag), */\r
-                     case_fold_flag,\r
-                     &s, end, lowbuf);\r
-         DATA_ENSURE(0);\r
-         qn = lowbuf;\r
-         while (len-- > 0) {\r
-           if (*p != *qn) goto fail;\r
-           p++; qn++;\r
-         }\r
-       }\r
-      }\r
-\r
-      MOP_OUT;\r
+        int len;\r
+        UChar *q, *endp, lowbuf[ONIGENC_MBC_CASE_FOLD_MAXLEN];\r
+\r
+        GET_LENGTH_INC(tlen, p);\r
+        endp = p + tlen;\r
+\r
+        while (p < endp) {\r
+          sprev = s;\r
+          DATA_ENSURE(1);\r
+          len = ONIGENC_MBC_CASE_FOLD(encode,\r
+                        /* DISABLE_CASE_FOLD_MULTI_CHAR(case_fold_flag), */\r
+                                      case_fold_flag,\r
+                                      &s, end, lowbuf);\r
+          DATA_ENSURE(0);\r
+          q = lowbuf;\r
+          while (len-- > 0) {\r
+            if (*p != *q) goto fail;\r
+            p++; q++;\r
+          }\r
+        }\r
+      }\r
+\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_EXACTMB2N1:  MOP_IN(OP_EXACTMB2N1);\r
+    case OP_EXACTMB2N1:  SOP_IN(OP_EXACTMB2N1);\r
       DATA_ENSURE(2);\r
       if (*p != *s) goto fail;\r
       p++; s++;\r
       if (*p != *s) goto fail;\r
       p++; s++;\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       break;\r
 \r
-    case OP_EXACTMB2N2:  MOP_IN(OP_EXACTMB2N2);\r
+    case OP_EXACTMB2N2:  SOP_IN(OP_EXACTMB2N2);\r
       DATA_ENSURE(4);\r
       if (*p != *s) goto fail;\r
       p++; s++;\r
@@ -1582,11 +2698,11 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
       p++; s++;\r
       if (*p != *s) goto fail;\r
       p++; s++;\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_EXACTMB2N3:  MOP_IN(OP_EXACTMB2N3);\r
+    case OP_EXACTMB2N3:  SOP_IN(OP_EXACTMB2N3);\r
       DATA_ENSURE(6);\r
       if (*p != *s) goto fail;\r
       p++; s++;\r
@@ -1601,469 +2717,488 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
       p++; s++;\r
       if (*p != *s) goto fail;\r
       p++; s++;\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_EXACTMB2N:  MOP_IN(OP_EXACTMB2N);\r
+    case OP_EXACTMB2N:  SOP_IN(OP_EXACTMB2N);\r
       GET_LENGTH_INC(tlen, p);\r
       DATA_ENSURE(tlen * 2);\r
       while (tlen-- > 0) {\r
-       if (*p != *s) goto fail;\r
-       p++; s++;\r
-       if (*p != *s) goto fail;\r
-       p++; s++;\r
+        if (*p != *s) goto fail;\r
+        p++; s++;\r
+        if (*p != *s) goto fail;\r
+        p++; s++;\r
       }\r
       sprev = s - 2;\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_EXACTMB3N:  MOP_IN(OP_EXACTMB3N);\r
+    case OP_EXACTMB3N:  SOP_IN(OP_EXACTMB3N);\r
       GET_LENGTH_INC(tlen, p);\r
       DATA_ENSURE(tlen * 3);\r
       while (tlen-- > 0) {\r
-       if (*p != *s) goto fail;\r
-       p++; s++;\r
-       if (*p != *s) goto fail;\r
-       p++; s++;\r
-       if (*p != *s) goto fail;\r
-       p++; s++;\r
+        if (*p != *s) goto fail;\r
+        p++; s++;\r
+        if (*p != *s) goto fail;\r
+        p++; s++;\r
+        if (*p != *s) goto fail;\r
+        p++; s++;\r
       }\r
       sprev = s - 3;\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_EXACTMBN:  MOP_IN(OP_EXACTMBN);\r
+    case OP_EXACTMBN:  SOP_IN(OP_EXACTMBN);\r
       GET_LENGTH_INC(tlen,  p);  /* mb-len */\r
       GET_LENGTH_INC(tlen2, p);  /* string len */\r
       tlen2 *= tlen;\r
       DATA_ENSURE(tlen2);\r
       while (tlen2-- > 0) {\r
-       if (*p != *s) goto fail;\r
-       p++; s++;\r
+        if (*p != *s) goto fail;\r
+        p++; s++;\r
       }\r
       sprev = s - tlen;\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_CCLASS:  MOP_IN(OP_CCLASS);\r
+    case OP_CCLASS:  SOP_IN(OP_CCLASS);\r
       DATA_ENSURE(1);\r
       if (BITSET_AT(((BitSetRef )p), *s) == 0) goto fail;\r
       p += SIZE_BITSET;\r
       s += enclen(encode, s);   /* OP_CCLASS can match mb-code. \D, \S */\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       break;\r
 \r
-    case OP_CCLASS_MB:  MOP_IN(OP_CCLASS_MB);\r
+    case OP_CCLASS_MB:  SOP_IN(OP_CCLASS_MB);\r
       if (! ONIGENC_IS_MBC_HEAD(encode, s)) goto fail;\r
 \r
     cclass_mb:\r
       GET_LENGTH_INC(tlen, p);\r
       {\r
-       OnigCodePoint code;\r
-       UChar *ss;\r
-       int mb_len;\r
+        OnigCodePoint code;\r
+        UChar *ss;\r
+        int mb_len;\r
 \r
-       DATA_ENSURE(1);\r
-       mb_len = enclen(encode, s);\r
-       DATA_ENSURE(mb_len);\r
-       ss = s;\r
-       s += mb_len;\r
-       code = ONIGENC_MBC_TO_CODE(encode, ss, s);\r
+        DATA_ENSURE(1);\r
+        mb_len = enclen(encode, s);\r
+        DATA_ENSURE(mb_len);\r
+        ss = s;\r
+        s += mb_len;\r
+        code = ONIGENC_MBC_TO_CODE(encode, ss, s);\r
 \r
 #ifdef PLATFORM_UNALIGNED_WORD_ACCESS\r
-       if (! onig_is_in_code_range(p, code)) goto fail;\r
+        if (! onig_is_in_code_range(p, code)) goto fail;\r
 #else\r
-       q = p;\r
-       ALIGNMENT_RIGHT(q);\r
-       if (! onig_is_in_code_range(q, code)) goto fail;\r
+        q = p;\r
+        ALIGNMENT_RIGHT(q);\r
+        if (! onig_is_in_code_range(q, code)) goto fail;\r
 #endif\r
       }\r
       p += tlen;\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       break;\r
 \r
-    case OP_CCLASS_MIX:  MOP_IN(OP_CCLASS_MIX);\r
+    case OP_CCLASS_MIX:  SOP_IN(OP_CCLASS_MIX);\r
       DATA_ENSURE(1);\r
       if (ONIGENC_IS_MBC_HEAD(encode, s)) {\r
-       p += SIZE_BITSET;\r
-       goto cclass_mb;\r
+        p += SIZE_BITSET;\r
+        goto cclass_mb;\r
       }\r
       else {\r
-       if (BITSET_AT(((BitSetRef )p), *s) == 0)\r
-         goto fail;\r
+        if (BITSET_AT(((BitSetRef )p), *s) == 0)\r
+          goto fail;\r
 \r
-       p += SIZE_BITSET;\r
-       GET_LENGTH_INC(tlen, p);\r
-       p += tlen;\r
-       s++;\r
+        p += SIZE_BITSET;\r
+        GET_LENGTH_INC(tlen, p);\r
+        p += tlen;\r
+        s++;\r
       }\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       break;\r
 \r
-    case OP_CCLASS_NOT:  MOP_IN(OP_CCLASS_NOT);\r
+    case OP_CCLASS_NOT:  SOP_IN(OP_CCLASS_NOT);\r
       DATA_ENSURE(1);\r
       if (BITSET_AT(((BitSetRef )p), *s) != 0) goto fail;\r
       p += SIZE_BITSET;\r
       s += enclen(encode, s);\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       break;\r
 \r
-    case OP_CCLASS_MB_NOT:  MOP_IN(OP_CCLASS_MB_NOT);\r
+    case OP_CCLASS_MB_NOT:  SOP_IN(OP_CCLASS_MB_NOT);\r
       DATA_ENSURE(1);\r
       if (! ONIGENC_IS_MBC_HEAD(encode, s)) {\r
-       s++;\r
-       GET_LENGTH_INC(tlen, p);\r
-       p += tlen;\r
-       goto cc_mb_not_success;\r
+        s++;\r
+        GET_LENGTH_INC(tlen, p);\r
+        p += tlen;\r
+        goto cc_mb_not_success;\r
       }\r
 \r
     cclass_mb_not:\r
       GET_LENGTH_INC(tlen, p);\r
       {\r
-       OnigCodePoint code;\r
-       UChar *ss;\r
-       int mb_len = enclen(encode, s);\r
+        OnigCodePoint code;\r
+        UChar *ss;\r
+        int mb_len = enclen(encode, s);\r
 \r
-       if (! DATA_ENSURE_CHECK(mb_len)) {\r
+        if (! DATA_ENSURE_CHECK(mb_len)) {\r
           DATA_ENSURE(1);\r
-         s = (UChar* )end;\r
-         p += tlen;\r
-         goto cc_mb_not_success;\r
-       }\r
+          s = (UChar* )end;\r
+          p += tlen;\r
+          goto cc_mb_not_success;\r
+        }\r
 \r
-       ss = s;\r
-       s += mb_len;\r
-       code = ONIGENC_MBC_TO_CODE(encode, ss, s);\r
+        ss = s;\r
+        s += mb_len;\r
+        code = ONIGENC_MBC_TO_CODE(encode, ss, s);\r
 \r
 #ifdef PLATFORM_UNALIGNED_WORD_ACCESS\r
-       if (onig_is_in_code_range(p, code)) goto fail;\r
+        if (onig_is_in_code_range(p, code)) goto fail;\r
 #else\r
-       q = p;\r
-       ALIGNMENT_RIGHT(q);\r
-       if (onig_is_in_code_range(q, code)) goto fail;\r
+        q = p;\r
+        ALIGNMENT_RIGHT(q);\r
+        if (onig_is_in_code_range(q, code)) goto fail;\r
 #endif\r
       }\r
       p += tlen;\r
 \r
     cc_mb_not_success:\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       break;\r
 \r
-    case OP_CCLASS_MIX_NOT:  MOP_IN(OP_CCLASS_MIX_NOT);\r
+    case OP_CCLASS_MIX_NOT:  SOP_IN(OP_CCLASS_MIX_NOT);\r
       DATA_ENSURE(1);\r
       if (ONIGENC_IS_MBC_HEAD(encode, s)) {\r
-       p += SIZE_BITSET;\r
-       goto cclass_mb_not;\r
+        p += SIZE_BITSET;\r
+        goto cclass_mb_not;\r
       }\r
       else {\r
-       if (BITSET_AT(((BitSetRef )p), *s) != 0)\r
-         goto fail;\r
+        if (BITSET_AT(((BitSetRef )p), *s) != 0)\r
+          goto fail;\r
 \r
-       p += SIZE_BITSET;\r
-       GET_LENGTH_INC(tlen, p);\r
-       p += tlen;\r
-       s++;\r
+        p += SIZE_BITSET;\r
+        GET_LENGTH_INC(tlen, p);\r
+        p += tlen;\r
+        s++;\r
       }\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       break;\r
 \r
-    case OP_CCLASS_NODE:  MOP_IN(OP_CCLASS_NODE);\r
+#ifdef USE_OP_CCLASS_NODE\r
+    case OP_CCLASS_NODE:  SOP_IN(OP_CCLASS_NODE);\r
       {\r
-       OnigCodePoint code;\r
+        OnigCodePoint code;\r
         void *node;\r
         int mb_len;\r
         UChar *ss;\r
 \r
         DATA_ENSURE(1);\r
         GET_POINTER_INC(node, p);\r
-       mb_len = enclen(encode, s);\r
-       ss = s;\r
-       s += mb_len;\r
-       DATA_ENSURE(0);\r
-       code = ONIGENC_MBC_TO_CODE(encode, ss, s);\r
-       if (onig_is_code_in_cc_len(mb_len, code, node) == 0) goto fail;\r
+        mb_len = enclen(encode, s);\r
+        ss = s;\r
+        s += mb_len;\r
+        DATA_ENSURE(0);\r
+        code = ONIGENC_MBC_TO_CODE(encode, ss, s);\r
+        if (onig_is_code_in_cc_len(mb_len, code, node) == 0) goto fail;\r
       }\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       break;\r
+#endif\r
 \r
-    case OP_ANYCHAR:  MOP_IN(OP_ANYCHAR);\r
+    case OP_ANYCHAR:  SOP_IN(OP_ANYCHAR);\r
       DATA_ENSURE(1);\r
       n = enclen(encode, s);\r
       DATA_ENSURE(n);\r
       if (ONIGENC_IS_MBC_NEWLINE(encode, s, end)) goto fail;\r
       s += n;\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       break;\r
 \r
-    case OP_ANYCHAR_ML:  MOP_IN(OP_ANYCHAR_ML);\r
+    case OP_ANYCHAR_ML:  SOP_IN(OP_ANYCHAR_ML);\r
       DATA_ENSURE(1);\r
       n = enclen(encode, s);\r
       DATA_ENSURE(n);\r
       s += n;\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       break;\r
 \r
-    case OP_ANYCHAR_STAR:  MOP_IN(OP_ANYCHAR_STAR);\r
+    case OP_ANYCHAR_STAR:  SOP_IN(OP_ANYCHAR_STAR);\r
       while (DATA_ENSURE_CHECK1) {\r
-       STACK_PUSH_ALT(p, s, sprev);\r
-       n = enclen(encode, s);\r
+        STACK_PUSH_ALT(p, s, sprev);\r
+        n = enclen(encode, s);\r
         DATA_ENSURE(n);\r
         if (ONIGENC_IS_MBC_NEWLINE(encode, s, end))  goto fail;\r
         sprev = s;\r
         s += n;\r
       }\r
-      MOP_OUT;\r
+      SOP_OUT;\r
+      continue;\r
       break;\r
 \r
-    case OP_ANYCHAR_ML_STAR:  MOP_IN(OP_ANYCHAR_ML_STAR);\r
+    case OP_ANYCHAR_ML_STAR:  SOP_IN(OP_ANYCHAR_ML_STAR);\r
       while (DATA_ENSURE_CHECK1) {\r
-       STACK_PUSH_ALT(p, s, sprev);\r
-       n = enclen(encode, s);\r
-       if (n > 1) {\r
-         DATA_ENSURE(n);\r
-         sprev = s;\r
-         s += n;\r
-       }\r
-       else {\r
-         sprev = s;\r
-         s++;\r
-       }\r
-      }\r
-      MOP_OUT;\r
-      break;\r
-\r
-    case OP_ANYCHAR_STAR_PEEK_NEXT:  MOP_IN(OP_ANYCHAR_STAR_PEEK_NEXT);\r
+        STACK_PUSH_ALT(p, s, sprev);\r
+        n = enclen(encode, s);\r
+        if (n > 1) {\r
+          DATA_ENSURE(n);\r
+          sprev = s;\r
+          s += n;\r
+        }\r
+        else {\r
+          sprev = s;\r
+          s++;\r
+        }\r
+      }\r
+      SOP_OUT;\r
+      continue;\r
+      break;\r
+\r
+    case OP_ANYCHAR_STAR_PEEK_NEXT:  SOP_IN(OP_ANYCHAR_STAR_PEEK_NEXT);\r
       while (DATA_ENSURE_CHECK1) {\r
-       if (*p == *s) {\r
-         STACK_PUSH_ALT(p + 1, s, sprev);\r
-       }\r
-       n = enclen(encode, s);\r
+        if (*p == *s) {\r
+          STACK_PUSH_ALT(p + 1, s, sprev);\r
+        }\r
+        n = enclen(encode, s);\r
         DATA_ENSURE(n);\r
         if (ONIGENC_IS_MBC_NEWLINE(encode, s, end))  goto fail;\r
         sprev = s;\r
         s += n;\r
       }\r
       p++;\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       break;\r
 \r
-    case OP_ANYCHAR_ML_STAR_PEEK_NEXT:MOP_IN(OP_ANYCHAR_ML_STAR_PEEK_NEXT);\r
+    case OP_ANYCHAR_ML_STAR_PEEK_NEXT:SOP_IN(OP_ANYCHAR_ML_STAR_PEEK_NEXT);\r
       while (DATA_ENSURE_CHECK1) {\r
-       if (*p == *s) {\r
-         STACK_PUSH_ALT(p + 1, s, sprev);\r
-       }\r
-       n = enclen(encode, s);\r
-       if (n > 1) {\r
-         DATA_ENSURE(n);\r
-         sprev = s;\r
-         s += n;\r
-       }\r
-       else {\r
-         sprev = s;\r
-         s++;\r
-       }\r
+        if (*p == *s) {\r
+          STACK_PUSH_ALT(p + 1, s, sprev);\r
+        }\r
+        n = enclen(encode, s);\r
+        if (n > 1) {\r
+          DATA_ENSURE(n);\r
+          sprev = s;\r
+          s += n;\r
+        }\r
+        else {\r
+          sprev = s;\r
+          s++;\r
+        }\r
       }\r
       p++;\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       break;\r
 \r
-#ifdef USE_COMBINATION_EXPLOSION_CHECK\r
-    case OP_STATE_CHECK_ANYCHAR_STAR:  MOP_IN(OP_STATE_CHECK_ANYCHAR_STAR);\r
-      GET_STATE_CHECK_NUM_INC(mem, p);\r
-      while (DATA_ENSURE_CHECK1) {\r
-       STATE_CHECK_VAL(scv, mem);\r
-       if (scv) goto fail;\r
+    case OP_WORD:  SOP_IN(OP_WORD);\r
+      DATA_ENSURE(1);\r
+      if (! ONIGENC_IS_MBC_WORD(encode, s, end))\r
+        goto fail;\r
 \r
-       STACK_PUSH_ALT_WITH_STATE_CHECK(p, s, sprev, mem);\r
-       n = enclen(encode, s);\r
-        DATA_ENSURE(n);\r
-        if (ONIGENC_IS_MBC_NEWLINE(encode, s, end))  goto fail;\r
-        sprev = s;\r
-        s += n;\r
-      }\r
-      MOP_OUT;\r
+      s += enclen(encode, s);\r
+      SOP_OUT;\r
       break;\r
 \r
-    case OP_STATE_CHECK_ANYCHAR_ML_STAR:\r
-      MOP_IN(OP_STATE_CHECK_ANYCHAR_ML_STAR);\r
-\r
-      GET_STATE_CHECK_NUM_INC(mem, p);\r
-      while (DATA_ENSURE_CHECK1) {\r
-       STATE_CHECK_VAL(scv, mem);\r
-       if (scv) goto fail;\r
-\r
-       STACK_PUSH_ALT_WITH_STATE_CHECK(p, s, sprev, mem);\r
-       n = enclen(encode, s);\r
-       if (n > 1) {\r
-         DATA_ENSURE(n);\r
-         sprev = s;\r
-         s += n;\r
-       }\r
-       else {\r
-         sprev = s;\r
-         s++;\r
-       }\r
-      }\r
-      MOP_OUT;\r
-      break;\r
-#endif /* USE_COMBINATION_EXPLOSION_CHECK */\r
-\r
-    case OP_WORD:  MOP_IN(OP_WORD);\r
+    case OP_WORD_ASCII:  SOP_IN(OP_WORD_ASCII);\r
       DATA_ENSURE(1);\r
-      if (! ONIGENC_IS_MBC_WORD(encode, s, end))\r
-       goto fail;\r
+      if (! ONIGENC_IS_MBC_WORD_ASCII(encode, s, end))\r
+        goto fail;\r
 \r
       s += enclen(encode, s);\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       break;\r
 \r
-    case OP_NOT_WORD:  MOP_IN(OP_NOT_WORD);\r
+    case OP_NO_WORD:  SOP_IN(OP_NO_WORD);\r
       DATA_ENSURE(1);\r
       if (ONIGENC_IS_MBC_WORD(encode, s, end))\r
-       goto fail;\r
+        goto fail;\r
 \r
       s += enclen(encode, s);\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       break;\r
 \r
-    case OP_WORD_BOUND:  MOP_IN(OP_WORD_BOUND);\r
-      if (ON_STR_BEGIN(s)) {\r
-       DATA_ENSURE(1);\r
-       if (! ONIGENC_IS_MBC_WORD(encode, s, end))\r
-         goto fail;\r
-      }\r
-      else if (ON_STR_END(s)) {\r
-       if (! ONIGENC_IS_MBC_WORD(encode, sprev, end))\r
-         goto fail;\r
-      }\r
-      else {\r
-       if (ONIGENC_IS_MBC_WORD(encode, s, end)\r
-           == ONIGENC_IS_MBC_WORD(encode, sprev, end))\r
-         goto fail;\r
+    case OP_NO_WORD_ASCII:  SOP_IN(OP_NO_WORD_ASCII);\r
+      DATA_ENSURE(1);\r
+      if (ONIGENC_IS_MBC_WORD_ASCII(encode, s, end))\r
+        goto fail;\r
+\r
+      s += enclen(encode, s);\r
+      SOP_OUT;\r
+      break;\r
+\r
+    case OP_WORD_BOUNDARY:  SOP_IN(OP_WORD_BOUNDARY);\r
+      {\r
+        ModeType mode;\r
+        GET_MODE_INC(mode, p); /* ascii_mode */\r
+\r
+        if (ON_STR_BEGIN(s)) {\r
+          DATA_ENSURE(1);\r
+          if (! IS_MBC_WORD_ASCII_MODE(encode, s, end, mode))\r
+            goto fail;\r
+        }\r
+        else if (ON_STR_END(s)) {\r
+          if (! IS_MBC_WORD_ASCII_MODE(encode, sprev, end, mode))\r
+            goto fail;\r
+        }\r
+        else {\r
+          if (IS_MBC_WORD_ASCII_MODE(encode, s, end, mode)\r
+              == IS_MBC_WORD_ASCII_MODE(encode, sprev, end, mode))\r
+            goto fail;\r
+        }\r
       }\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_NOT_WORD_BOUND:  MOP_IN(OP_NOT_WORD_BOUND);\r
-      if (ON_STR_BEGIN(s)) {\r
-       if (DATA_ENSURE_CHECK1 && ONIGENC_IS_MBC_WORD(encode, s, end))\r
-         goto fail;\r
-      }\r
-      else if (ON_STR_END(s)) {\r
-       if (ONIGENC_IS_MBC_WORD(encode, sprev, end))\r
-         goto fail;\r
-      }\r
-      else {\r
-       if (ONIGENC_IS_MBC_WORD(encode, s, end)\r
-           != ONIGENC_IS_MBC_WORD(encode, sprev, end))\r
-         goto fail;\r
+    case OP_NO_WORD_BOUNDARY:  SOP_IN(OP_NO_WORD_BOUNDARY);\r
+      {\r
+        ModeType mode;\r
+        GET_MODE_INC(mode, p); /* ascii_mode */\r
+\r
+        if (ON_STR_BEGIN(s)) {\r
+          if (DATA_ENSURE_CHECK1 && IS_MBC_WORD_ASCII_MODE(encode, s, end, mode))\r
+            goto fail;\r
+        }\r
+        else if (ON_STR_END(s)) {\r
+          if (IS_MBC_WORD_ASCII_MODE(encode, sprev, end, mode))\r
+            goto fail;\r
+        }\r
+        else {\r
+          if (IS_MBC_WORD_ASCII_MODE(encode, s, end, mode)\r
+              != IS_MBC_WORD_ASCII_MODE(encode, sprev, end, mode))\r
+            goto fail;\r
+        }\r
       }\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
 #ifdef USE_WORD_BEGIN_END\r
-    case OP_WORD_BEGIN:  MOP_IN(OP_WORD_BEGIN);\r
-      if (DATA_ENSURE_CHECK1 && ONIGENC_IS_MBC_WORD(encode, s, end)) {\r
-       if (ON_STR_BEGIN(s) || !ONIGENC_IS_MBC_WORD(encode, sprev, end)) {\r
-         MOP_OUT;\r
-         continue;\r
-       }\r
+    case OP_WORD_BEGIN:  SOP_IN(OP_WORD_BEGIN);\r
+      {\r
+        ModeType mode;\r
+        GET_MODE_INC(mode, p); /* ascii_mode */\r
+\r
+        if (DATA_ENSURE_CHECK1 && IS_MBC_WORD_ASCII_MODE(encode, s, end, mode)) {\r
+          if (ON_STR_BEGIN(s) || !IS_MBC_WORD_ASCII_MODE(encode, sprev, end, mode)) {\r
+            SOP_OUT;\r
+            continue;\r
+          }\r
+        }\r
       }\r
       goto fail;\r
       break;\r
 \r
-    case OP_WORD_END:  MOP_IN(OP_WORD_END);\r
-      if (!ON_STR_BEGIN(s) && ONIGENC_IS_MBC_WORD(encode, sprev, end)) {\r
-       if (ON_STR_END(s) || !ONIGENC_IS_MBC_WORD(encode, s, end)) {\r
-         MOP_OUT;\r
-         continue;\r
-       }\r
+    case OP_WORD_END:  SOP_IN(OP_WORD_END);\r
+      {\r
+        ModeType mode;\r
+        GET_MODE_INC(mode, p); /* ascii_mode */\r
+\r
+        if (!ON_STR_BEGIN(s) && IS_MBC_WORD_ASCII_MODE(encode, sprev, end, mode)) {\r
+          if (ON_STR_END(s) || ! IS_MBC_WORD_ASCII_MODE(encode, s, end, mode)) {\r
+            SOP_OUT;\r
+            continue;\r
+          }\r
+        }\r
       }\r
       goto fail;\r
       break;\r
 #endif\r
 \r
-    case OP_BEGIN_BUF:  MOP_IN(OP_BEGIN_BUF);\r
+    case OP_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY:\r
+      SOP_IN(OP_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY);\r
+      if (onigenc_egcb_is_break_position(encode, s, sprev, str, end)) {\r
+        SOP_OUT;\r
+        continue;\r
+      }\r
+      goto fail;\r
+      break;\r
+\r
+    case OP_NO_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY:\r
+      SOP_IN(OP_NO_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY);\r
+      if (onigenc_egcb_is_break_position(encode, s, sprev, str, end))\r
+        goto fail;\r
+\r
+      SOP_OUT;\r
+      continue;\r
+      break;\r
+\r
+    case OP_BEGIN_BUF:  SOP_IN(OP_BEGIN_BUF);\r
       if (! ON_STR_BEGIN(s)) goto fail;\r
 \r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_END_BUF:  MOP_IN(OP_END_BUF);\r
+    case OP_END_BUF:  SOP_IN(OP_END_BUF);\r
       if (! ON_STR_END(s)) goto fail;\r
 \r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_BEGIN_LINE:  MOP_IN(OP_BEGIN_LINE);\r
+    case OP_BEGIN_LINE:  SOP_IN(OP_BEGIN_LINE);\r
       if (ON_STR_BEGIN(s)) {\r
-       if (IS_NOTBOL(msa->options)) goto fail;\r
-       MOP_OUT;\r
-       continue;\r
+        if (IS_NOTBOL(msa->options)) goto fail;\r
+        SOP_OUT;\r
+        continue;\r
       }\r
       else if (ONIGENC_IS_MBC_NEWLINE(encode, sprev, end) && !ON_STR_END(s)) {\r
-       MOP_OUT;\r
-       continue;\r
+        SOP_OUT;\r
+        continue;\r
       }\r
       goto fail;\r
       break;\r
 \r
-    case OP_END_LINE:  MOP_IN(OP_END_LINE);\r
+    case OP_END_LINE:  SOP_IN(OP_END_LINE);\r
       if (ON_STR_END(s)) {\r
 #ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE\r
-       if (IS_EMPTY_STR || !ONIGENC_IS_MBC_NEWLINE(encode, sprev, end)) {\r
+        if (IS_EMPTY_STR || !ONIGENC_IS_MBC_NEWLINE(encode, sprev, end)) {\r
 #endif\r
-         if (IS_NOTEOL(msa->options)) goto fail;\r
-         MOP_OUT;\r
-         continue;\r
+          if (IS_NOTEOL(msa->options)) goto fail;\r
+          SOP_OUT;\r
+          continue;\r
 #ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE\r
-       }\r
+        }\r
 #endif\r
       }\r
       else if (ONIGENC_IS_MBC_NEWLINE(encode, s, end)) {\r
-       MOP_OUT;\r
-       continue;\r
+        SOP_OUT;\r
+        continue;\r
       }\r
 #ifdef USE_CRNL_AS_LINE_TERMINATOR\r
       else if (ONIGENC_IS_MBC_CRNL(encode, s, end)) {\r
-       MOP_OUT;\r
-       continue;\r
+        SOP_OUT;\r
+        continue;\r
       }\r
 #endif\r
       goto fail;\r
       break;\r
 \r
-    case OP_SEMI_END_BUF:  MOP_IN(OP_SEMI_END_BUF);\r
+    case OP_SEMI_END_BUF:  SOP_IN(OP_SEMI_END_BUF);\r
       if (ON_STR_END(s)) {\r
 #ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE\r
-       if (IS_EMPTY_STR || !ONIGENC_IS_MBC_NEWLINE(encode, sprev, end)) {\r
+        if (IS_EMPTY_STR || !ONIGENC_IS_MBC_NEWLINE(encode, sprev, end)) {\r
 #endif\r
-         if (IS_NOTEOL(msa->options)) goto fail;\r
-         MOP_OUT;\r
-         continue;\r
+          if (IS_NOTEOL(msa->options)) goto fail;\r
+          SOP_OUT;\r
+          continue;\r
 #ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE\r
-       }\r
+        }\r
 #endif\r
       }\r
       else if (ONIGENC_IS_MBC_NEWLINE(encode, s, end) &&\r
-              ON_STR_END(s + enclen(encode, s))) {\r
-       MOP_OUT;\r
-       continue;\r
+               ON_STR_END(s + enclen(encode, s))) {\r
+        SOP_OUT;\r
+        continue;\r
       }\r
 #ifdef USE_CRNL_AS_LINE_TERMINATOR\r
       else if (ONIGENC_IS_MBC_CRNL(encode, s, end)) {\r
         UChar* ss = s + enclen(encode, s);\r
-       ss += enclen(encode, ss);\r
+        ss += enclen(encode, ss);\r
         if (ON_STR_END(ss)) {\r
-          MOP_OUT;\r
+          SOP_OUT;\r
           continue;\r
         }\r
       }\r
@@ -2071,477 +3206,464 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
       goto fail;\r
       break;\r
 \r
-    case OP_BEGIN_POSITION:  MOP_IN(OP_BEGIN_POSITION);\r
+    case OP_BEGIN_POSITION:  SOP_IN(OP_BEGIN_POSITION);\r
       if (s != msa->start)\r
-       goto fail;\r
+        goto fail;\r
 \r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_MEMORY_START_PUSH:  MOP_IN(OP_MEMORY_START_PUSH);\r
+    case OP_MEMORY_START_PUSH:  SOP_IN(OP_MEMORY_START_PUSH);\r
       GET_MEMNUM_INC(mem, p);\r
       STACK_PUSH_MEM_START(mem, s);\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_MEMORY_START:  MOP_IN(OP_MEMORY_START);\r
+    case OP_MEMORY_START:  SOP_IN(OP_MEMORY_START);\r
       GET_MEMNUM_INC(mem, p);\r
-      mem_start_stk[mem] = (OnigStackIndex )(UINTN)((void* )s);\r
-      MOP_OUT;\r
+      mem_start_stk[mem] = (StackIndex )((void* )s);\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_MEMORY_END_PUSH:  MOP_IN(OP_MEMORY_END_PUSH);\r
+    case OP_MEMORY_END_PUSH:  SOP_IN(OP_MEMORY_END_PUSH);\r
       GET_MEMNUM_INC(mem, p);\r
       STACK_PUSH_MEM_END(mem, s);\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_MEMORY_END:  MOP_IN(OP_MEMORY_END);\r
+    case OP_MEMORY_END:  SOP_IN(OP_MEMORY_END);\r
       GET_MEMNUM_INC(mem, p);\r
-      mem_end_stk[mem] = (OnigStackIndex )(UINTN)((void* )s);\r
-      MOP_OUT;\r
+      mem_end_stk[mem] = (StackIndex )((void* )s);\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-#ifdef USE_SUBEXP_CALL\r
-    case OP_MEMORY_END_PUSH_REC:  MOP_IN(OP_MEMORY_END_PUSH_REC);\r
+#ifdef USE_CALL\r
+    case OP_MEMORY_END_PUSH_REC:  SOP_IN(OP_MEMORY_END_PUSH_REC);\r
       GET_MEMNUM_INC(mem, p);\r
       STACK_GET_MEM_START(mem, stkp); /* should be before push mem-end. */\r
       STACK_PUSH_MEM_END(mem, s);\r
       mem_start_stk[mem] = GET_STACK_INDEX(stkp);\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_MEMORY_END_REC:  MOP_IN(OP_MEMORY_END_REC);\r
+    case OP_MEMORY_END_REC:  SOP_IN(OP_MEMORY_END_REC);\r
       GET_MEMNUM_INC(mem, p);\r
-      mem_end_stk[mem] = (OnigStackIndex )(UINTN)((void* )s);\r
+      mem_end_stk[mem] = (StackIndex )((void* )s);\r
       STACK_GET_MEM_START(mem, stkp);\r
 \r
-      if (BIT_STATUS_AT(reg->bt_mem_start, mem))\r
-       mem_start_stk[mem] = GET_STACK_INDEX(stkp);\r
+      if (MEM_STATUS_AT(reg->bt_mem_start, mem))\r
+        mem_start_stk[mem] = GET_STACK_INDEX(stkp);\r
       else\r
-       mem_start_stk[mem] = (OnigStackIndex )(UINTN)((void* )stkp->u.mem.pstr);\r
+        mem_start_stk[mem] = (StackIndex )((void* )stkp->u.mem.pstr);\r
 \r
       STACK_PUSH_MEM_END_MARK(mem);\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 #endif\r
 \r
-    case OP_BACKREF1:  MOP_IN(OP_BACKREF1);\r
+    case OP_BACKREF1:  SOP_IN(OP_BACKREF1);\r
       mem = 1;\r
       goto backref;\r
       break;\r
 \r
-    case OP_BACKREF2:  MOP_IN(OP_BACKREF2);\r
+    case OP_BACKREF2:  SOP_IN(OP_BACKREF2);\r
       mem = 2;\r
       goto backref;\r
       break;\r
 \r
-    case OP_BACKREFN:  MOP_IN(OP_BACKREFN);\r
+    case OP_BACKREF_N:  SOP_IN(OP_BACKREF_N);\r
       GET_MEMNUM_INC(mem, p);\r
     backref:\r
       {\r
-       int len;\r
-       UChar *pstart, *pend;\r
+        int len;\r
+        UChar *pstart, *pend;\r
 \r
-       /* if you want to remove following line, \r
-          you should check in parse and compile time. */\r
-       if (mem > num_mem) goto fail;\r
-       if (mem_end_stk[mem]   == INVALID_STACK_INDEX) goto fail;\r
-       if (mem_start_stk[mem] == INVALID_STACK_INDEX) goto fail;\r
+        if (mem_end_stk[mem]   == INVALID_STACK_INDEX) goto fail;\r
+        if (mem_start_stk[mem] == INVALID_STACK_INDEX) goto fail;\r
 \r
-       if (BIT_STATUS_AT(reg->bt_mem_start, mem))\r
-         pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;\r
-       else\r
-         pstart = (UChar* )((void* )(UINTN)mem_start_stk[mem]);\r
+        if (MEM_STATUS_AT(reg->bt_mem_start, mem))\r
+          pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;\r
+        else\r
+          pstart = (UChar* )((void* )mem_start_stk[mem]);\r
 \r
-       pend = (BIT_STATUS_AT(reg->bt_mem_end, mem)\r
-               ? STACK_AT(mem_end_stk[mem])->u.mem.pstr\r
-               : (UChar* )((void* )(UINTN)mem_end_stk[mem]));\r
-       n = (int)(pend - pstart);\r
-       DATA_ENSURE(n);\r
-       sprev = s;\r
-       STRING_CMP(pstart, s, n);\r
-       while (sprev + (len = enclen(encode, sprev)) < s)\r
-         sprev += len;\r
+        pend = (MEM_STATUS_AT(reg->bt_mem_end, mem)\r
+                ? STACK_AT(mem_end_stk[mem])->u.mem.pstr\r
+                : (UChar* )((void* )mem_end_stk[mem]));\r
+        n = (int )(pend - pstart);\r
+        DATA_ENSURE(n);\r
+        sprev = s;\r
+        STRING_CMP(pstart, s, n);\r
+        while (sprev + (len = enclen(encode, sprev)) < s)\r
+          sprev += len;\r
 \r
-       MOP_OUT;\r
-       continue;\r
+        SOP_OUT;\r
+        continue;\r
       }\r
       break;\r
 \r
-    case OP_BACKREFN_IC:  MOP_IN(OP_BACKREFN_IC);\r
+    case OP_BACKREF_N_IC:  SOP_IN(OP_BACKREF_N_IC);\r
       GET_MEMNUM_INC(mem, p);\r
       {\r
-       int len;\r
-       UChar *pstart, *pend;\r
+        int len;\r
+        UChar *pstart, *pend;\r
 \r
-       /* if you want to remove following line, \r
-          you should check in parse and compile time. */\r
-       if (mem > num_mem) goto fail;\r
-       if (mem_end_stk[mem]   == INVALID_STACK_INDEX) goto fail;\r
-       if (mem_start_stk[mem] == INVALID_STACK_INDEX) goto fail;\r
+        if (mem_end_stk[mem]   == INVALID_STACK_INDEX) goto fail;\r
+        if (mem_start_stk[mem] == INVALID_STACK_INDEX) goto fail;\r
 \r
-       if (BIT_STATUS_AT(reg->bt_mem_start, mem))\r
-         pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;\r
-       else\r
-         pstart = (UChar* )((void* )(UINTN)mem_start_stk[mem]);\r
+        if (MEM_STATUS_AT(reg->bt_mem_start, mem))\r
+          pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;\r
+        else\r
+          pstart = (UChar* )((void* )mem_start_stk[mem]);\r
 \r
-       pend = (BIT_STATUS_AT(reg->bt_mem_end, mem)\r
-               ? STACK_AT(mem_end_stk[mem])->u.mem.pstr\r
-               : (UChar* )((void* )(UINTN)mem_end_stk[mem]));\r
-       n = (int)(pend - pstart);\r
-       DATA_ENSURE(n);\r
-       sprev = s;\r
-       STRING_CMP_IC(case_fold_flag, pstart, &s, n);\r
-       while (sprev + (len = enclen(encode, sprev)) < s)\r
-         sprev += len;\r
+        pend = (MEM_STATUS_AT(reg->bt_mem_end, mem)\r
+                ? STACK_AT(mem_end_stk[mem])->u.mem.pstr\r
+                : (UChar* )((void* )mem_end_stk[mem]));\r
+        n = (int )(pend - pstart);\r
+        DATA_ENSURE(n);\r
+        sprev = s;\r
+        STRING_CMP_IC(case_fold_flag, pstart, &s, n);\r
+        while (sprev + (len = enclen(encode, sprev)) < s)\r
+          sprev += len;\r
 \r
-       MOP_OUT;\r
-       continue;\r
+        SOP_OUT;\r
+        continue;\r
       }\r
       break;\r
 \r
-    case OP_BACKREF_MULTI:  MOP_IN(OP_BACKREF_MULTI);\r
+    case OP_BACKREF_MULTI:  SOP_IN(OP_BACKREF_MULTI);\r
       {\r
-       int len, is_fail;\r
-       UChar *pstart, *pend, *swork;\r
-\r
-       GET_LENGTH_INC(tlen, p);\r
-       for (i = 0; i < tlen; i++) {\r
-         GET_MEMNUM_INC(mem, p);\r
-\r
-         if (mem_end_stk[mem]   == INVALID_STACK_INDEX) continue;\r
-         if (mem_start_stk[mem] == INVALID_STACK_INDEX) continue;\r
-\r
-         if (BIT_STATUS_AT(reg->bt_mem_start, mem))\r
-           pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;\r
-         else\r
-           pstart = (UChar* )((void* )(UINTN)mem_start_stk[mem]);\r
-\r
-         pend = (BIT_STATUS_AT(reg->bt_mem_end, mem)\r
-                 ? STACK_AT(mem_end_stk[mem])->u.mem.pstr\r
-                 : (UChar* )((void* )(UINTN)mem_end_stk[mem]));\r
-         n = (int)(pend - pstart);\r
-         DATA_ENSURE(n);\r
-         sprev = s;\r
-         swork = s;\r
-         STRING_CMP_VALUE(pstart, swork, n, is_fail);\r
-         if (is_fail) continue;\r
-         s = swork;\r
-         while (sprev + (len = enclen(encode, sprev)) < s)\r
-           sprev += len;\r
-\r
-         p += (SIZE_MEMNUM * (tlen - i - 1));\r
-         break; /* success */\r
-       }\r
-       if (i == tlen) goto fail;\r
-       MOP_OUT;\r
-       continue;\r
-      }\r
-      break;\r
-\r
-    case OP_BACKREF_MULTI_IC:  MOP_IN(OP_BACKREF_MULTI_IC);\r
+        int len, is_fail;\r
+        UChar *pstart, *pend, *swork;\r
+\r
+        GET_LENGTH_INC(tlen, p);\r
+        for (i = 0; i < tlen; i++) {\r
+          GET_MEMNUM_INC(mem, p);\r
+\r
+          if (mem_end_stk[mem]   == INVALID_STACK_INDEX) continue;\r
+          if (mem_start_stk[mem] == INVALID_STACK_INDEX) continue;\r
+\r
+          if (MEM_STATUS_AT(reg->bt_mem_start, mem))\r
+            pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;\r
+          else\r
+            pstart = (UChar* )((void* )mem_start_stk[mem]);\r
+\r
+          pend = (MEM_STATUS_AT(reg->bt_mem_end, mem)\r
+                  ? STACK_AT(mem_end_stk[mem])->u.mem.pstr\r
+                  : (UChar* )((void* )mem_end_stk[mem]));\r
+          n = (int )(pend - pstart);\r
+          DATA_ENSURE(n);\r
+          sprev = s;\r
+          swork = s;\r
+          STRING_CMP_VALUE(pstart, swork, n, is_fail);\r
+          if (is_fail) continue;\r
+          s = swork;\r
+          while (sprev + (len = enclen(encode, sprev)) < s)\r
+            sprev += len;\r
+\r
+          p += (SIZE_MEMNUM * (tlen - i - 1));\r
+          break; /* success */\r
+        }\r
+        if (i == tlen) goto fail;\r
+        SOP_OUT;\r
+        continue;\r
+      }\r
+      break;\r
+\r
+    case OP_BACKREF_MULTI_IC:  SOP_IN(OP_BACKREF_MULTI_IC);\r
       {\r
-       int len, is_fail;\r
-       UChar *pstart, *pend, *swork;\r
-\r
-       GET_LENGTH_INC(tlen, p);\r
-       for (i = 0; i < tlen; i++) {\r
-         GET_MEMNUM_INC(mem, p);\r
-\r
-         if (mem_end_stk[mem]   == INVALID_STACK_INDEX) continue;\r
-         if (mem_start_stk[mem] == INVALID_STACK_INDEX) continue;\r
-\r
-         if (BIT_STATUS_AT(reg->bt_mem_start, mem))\r
-           pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;\r
-         else\r
-           pstart = (UChar* )((void* )(UINTN)mem_start_stk[mem]);\r
-\r
-         pend = (BIT_STATUS_AT(reg->bt_mem_end, mem)\r
-                 ? STACK_AT(mem_end_stk[mem])->u.mem.pstr\r
-                 : (UChar* )((void* )(UINTN)mem_end_stk[mem]));\r
-         n = (int)(pend - pstart);\r
-         DATA_ENSURE(n);\r
-         sprev = s;\r
-         swork = s;\r
-         STRING_CMP_VALUE_IC(case_fold_flag, pstart, &swork, n, is_fail);\r
-         if (is_fail) continue;\r
-         s = swork;\r
-         while (sprev + (len = enclen(encode, sprev)) < s)\r
-           sprev += len;\r
-\r
-         p += (SIZE_MEMNUM * (tlen - i - 1));\r
-         break; /* success */\r
-       }\r
-       if (i == tlen) goto fail;\r
-       MOP_OUT;\r
-       continue;\r
+        int len, is_fail;\r
+        UChar *pstart, *pend, *swork;\r
+\r
+        GET_LENGTH_INC(tlen, p);\r
+        for (i = 0; i < tlen; i++) {\r
+          GET_MEMNUM_INC(mem, p);\r
+\r
+          if (mem_end_stk[mem]   == INVALID_STACK_INDEX) continue;\r
+          if (mem_start_stk[mem] == INVALID_STACK_INDEX) continue;\r
+\r
+          if (MEM_STATUS_AT(reg->bt_mem_start, mem))\r
+            pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;\r
+          else\r
+            pstart = (UChar* )((void* )mem_start_stk[mem]);\r
+\r
+          pend = (MEM_STATUS_AT(reg->bt_mem_end, mem)\r
+                  ? STACK_AT(mem_end_stk[mem])->u.mem.pstr\r
+                  : (UChar* )((void* )mem_end_stk[mem]));\r
+          n = (int )(pend - pstart);\r
+          DATA_ENSURE(n);\r
+          sprev = s;\r
+          swork = s;\r
+          STRING_CMP_VALUE_IC(case_fold_flag, pstart, &swork, n, is_fail);\r
+          if (is_fail) continue;\r
+          s = swork;\r
+          while (sprev + (len = enclen(encode, sprev)) < s)\r
+            sprev += len;\r
+\r
+          p += (SIZE_MEMNUM * (tlen - i - 1));\r
+          break; /* success */\r
+        }\r
+        if (i == tlen) goto fail;\r
+        SOP_OUT;\r
+        continue;\r
       }\r
       break;\r
 \r
 #ifdef USE_BACKREF_WITH_LEVEL\r
     case OP_BACKREF_WITH_LEVEL:\r
       {\r
-       int len;\r
-       OnigOptionType ic;\r
-       LengthType level;\r
-\r
-       GET_OPTION_INC(ic,    p);\r
-       GET_LENGTH_INC(level, p);\r
-       GET_LENGTH_INC(tlen,  p);\r
+        int len;\r
+        OnigOptionType ic;\r
+        LengthType level;\r
 \r
-       sprev = s;\r
-       if (backref_match_at_nested_level(reg, stk, stk_base, ic\r
-                 , case_fold_flag, (int )level, (int )tlen, p, &s, end)) {\r
-         while (sprev + (len = enclen(encode, sprev)) < s)\r
-           sprev += len;\r
+        GET_OPTION_INC(ic,    p);\r
+        GET_LENGTH_INC(level, p);\r
+        GET_LENGTH_INC(tlen,  p);\r
 \r
-         p += (SIZE_MEMNUM * tlen);\r
-       }\r
-       else\r
-         goto fail;\r
+        sprev = s;\r
+        if (backref_match_at_nested_level(reg, stk, stk_base, ic\r
+                     , case_fold_flag, (int )level, (int )tlen, p, &s, end)) {\r
+          if (sprev < end) {\r
+            while (sprev + (len = enclen(encode, sprev)) < s)\r
+              sprev += len;\r
+          }\r
+          p += (SIZE_MEMNUM * tlen);\r
+        }\r
+        else\r
+          goto fail;\r
 \r
-       MOP_OUT;\r
-       continue;\r
+        SOP_OUT;\r
+        continue;\r
       }\r
-      \r
       break;\r
 #endif\r
 \r
-#if 0   /* no need: IS_DYNAMIC_OPTION() == 0 */\r
-    case OP_SET_OPTION_PUSH:  MOP_IN(OP_SET_OPTION_PUSH);\r
-      GET_OPTION_INC(option, p);\r
-      STACK_PUSH_ALT(p, s, sprev);\r
-      p += SIZE_OP_SET_OPTION + SIZE_OP_FAIL;\r
-      MOP_OUT;\r
-      continue;\r
+    case OP_BACKREF_CHECK:  SOP_IN(OP_BACKREF_CHECK);\r
+      {\r
+        GET_LENGTH_INC(tlen, p);\r
+        for (i = 0; i < tlen; i++) {\r
+          GET_MEMNUM_INC(mem, p);\r
+\r
+          if (mem_end_stk[mem]   == INVALID_STACK_INDEX) continue;\r
+          if (mem_start_stk[mem] == INVALID_STACK_INDEX) continue;\r
+\r
+          p += (SIZE_MEMNUM * (tlen - i - 1));\r
+          break; /* success */\r
+        }\r
+        if (i == tlen) goto fail;\r
+        SOP_OUT;\r
+        continue;\r
+      }\r
       break;\r
 \r
-    case OP_SET_OPTION:  MOP_IN(OP_SET_OPTION);\r
-      GET_OPTION_INC(option, p);\r
-      MOP_OUT;\r
-      continue;\r
+#ifdef USE_BACKREF_WITH_LEVEL\r
+    case OP_BACKREF_CHECK_WITH_LEVEL:\r
+      {\r
+        LengthType level;\r
+\r
+        GET_LENGTH_INC(level, p);\r
+        GET_LENGTH_INC(tlen,  p);\r
+\r
+        if (backref_check_at_nested_level(reg, stk, stk_base,\r
+                                          (int )level, (int )tlen, p) != 0) {\r
+          p += (SIZE_MEMNUM * tlen);\r
+        }\r
+        else\r
+          goto fail;\r
+\r
+        SOP_OUT;\r
+        continue;\r
+      }\r
       break;\r
 #endif\r
 \r
-    case OP_NULL_CHECK_START:  MOP_IN(OP_NULL_CHECK_START);\r
+    case OP_EMPTY_CHECK_START:  SOP_IN(OP_EMPTY_CHECK_START);\r
       GET_MEMNUM_INC(mem, p);    /* mem: null check id */\r
-      STACK_PUSH_NULL_CHECK_START(mem, s);\r
-      MOP_OUT;\r
+      STACK_PUSH_EMPTY_CHECK_START(mem, s);\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_NULL_CHECK_END:  MOP_IN(OP_NULL_CHECK_END);\r
+    case OP_EMPTY_CHECK_END:  SOP_IN(OP_EMPTY_CHECK_END);\r
       {\r
-       int isnull;\r
+        int is_empty;\r
 \r
-       GET_MEMNUM_INC(mem, p); /* mem: null check id */\r
-       STACK_NULL_CHECK(isnull, mem, s);\r
-       if (isnull) {\r
+        GET_MEMNUM_INC(mem, p); /* mem: null check id */\r
+        STACK_EMPTY_CHECK(is_empty, mem, s);\r
+        if (is_empty) {\r
 #ifdef ONIG_DEBUG_MATCH\r
-         fprintf(stderr, "NULL_CHECK_END: skip  id:%d, s:%d\n",\r
-                 (int )mem, (int )s);\r
-#endif\r
-       null_check_found:\r
-         /* empty loop founded, skip next instruction */\r
-         switch (*p++) {\r
-         case OP_JUMP:\r
-         case OP_PUSH:\r
-           p += SIZE_RELADDR;\r
-           break;\r
-         case OP_REPEAT_INC:\r
-         case OP_REPEAT_INC_NG:\r
-         case OP_REPEAT_INC_SG:\r
-         case OP_REPEAT_INC_NG_SG:\r
-           p += SIZE_MEMNUM;\r
-           break;\r
-         default:\r
-           goto unexpected_bytecode_error;\r
-           break;\r
-         }\r
-       }\r
-      }\r
-      MOP_OUT;\r
+          fprintf(stderr, "EMPTY_CHECK_END: skip  id:%d, s:%p\n", (int )mem, s);\r
+#endif\r
+        empty_check_found:\r
+          /* empty loop founded, skip next instruction */\r
+          switch (*p++) {\r
+          case OP_JUMP:\r
+          case OP_PUSH:\r
+            p += SIZE_RELADDR;\r
+            break;\r
+          case OP_REPEAT_INC:\r
+          case OP_REPEAT_INC_NG:\r
+          case OP_REPEAT_INC_SG:\r
+          case OP_REPEAT_INC_NG_SG:\r
+            p += SIZE_MEMNUM;\r
+            break;\r
+          default:\r
+            goto unexpected_bytecode_error;\r
+            break;\r
+          }\r
+        }\r
+      }\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-#ifdef USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT\r
-    case OP_NULL_CHECK_END_MEMST:  MOP_IN(OP_NULL_CHECK_END_MEMST);\r
+#ifdef USE_INSISTENT_CHECK_CAPTURES_IN_EMPTY_REPEAT\r
+    case OP_EMPTY_CHECK_END_MEMST:  SOP_IN(OP_EMPTY_CHECK_END_MEMST);\r
       {\r
-       int isnull;\r
+        int is_empty;\r
 \r
-       GET_MEMNUM_INC(mem, p); /* mem: null check id */\r
-       STACK_NULL_CHECK_MEMST(isnull, mem, s, reg);\r
-       if (isnull) {\r
+        GET_MEMNUM_INC(mem, p); /* mem: null check id */\r
+        STACK_EMPTY_CHECK_MEM(is_empty, mem, s, reg);\r
+        if (is_empty) {\r
 #ifdef ONIG_DEBUG_MATCH\r
-         fprintf(stderr, "NULL_CHECK_END_MEMST: skip  id:%d, s:%d\n",\r
-                 (int )mem, (int )s);\r
+          fprintf(stderr, "EMPTY_CHECK_END_MEM: skip  id:%d, s:%p\n", (int)mem, s);\r
 #endif\r
-         if (isnull == -1) goto fail;\r
-         goto  null_check_found;\r
-       }\r
+          if (is_empty == -1) goto fail;\r
+          goto empty_check_found;\r
+        }\r
       }\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 #endif\r
 \r
-#ifdef USE_SUBEXP_CALL\r
-    case OP_NULL_CHECK_END_MEMST_PUSH:\r
-      MOP_IN(OP_NULL_CHECK_END_MEMST_PUSH);\r
+#ifdef USE_CALL\r
+    case OP_EMPTY_CHECK_END_MEMST_PUSH:\r
+      SOP_IN(OP_EMPTY_CHECK_END_MEMST_PUSH);\r
       {\r
-       int isnull;\r
+        int is_empty;\r
 \r
-       GET_MEMNUM_INC(mem, p); /* mem: null check id */\r
-#ifdef USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT\r
-       STACK_NULL_CHECK_MEMST_REC(isnull, mem, s, reg);\r
+        GET_MEMNUM_INC(mem, p); /* mem: null check id */\r
+#ifdef USE_INSISTENT_CHECK_CAPTURES_IN_EMPTY_REPEAT\r
+        STACK_EMPTY_CHECK_MEM_REC(is_empty, mem, s, reg);\r
 #else\r
-       STACK_NULL_CHECK_REC(isnull, mem, s);\r
+        STACK_EMPTY_CHECK_REC(is_empty, mem, s);\r
 #endif\r
-       if (isnull) {\r
+        if (is_empty) {\r
 #ifdef ONIG_DEBUG_MATCH\r
-         fprintf(stderr, "NULL_CHECK_END_MEMST_PUSH: skip  id:%d, s:%d\n",\r
-                 (int )mem, (int )s);\r
+          fprintf(stderr, "EMPTY_CHECK_END_MEM_PUSH: skip  id:%d, s:%p\n",\r
+                  (int )mem, s);\r
 #endif\r
-         if (isnull == -1) goto fail;\r
-         goto  null_check_found;\r
-       }\r
-       else {\r
-         STACK_PUSH_NULL_CHECK_END(mem);\r
-       }\r
-      }\r
-      MOP_OUT;\r
-      continue;\r
+          if (is_empty == -1) goto fail;\r
+          goto empty_check_found;\r
+        }\r
+        else {\r
+          STACK_PUSH_EMPTY_CHECK_END(mem);\r
+        }\r
+      }\r
+      SOP_OUT;\r
+      continue;\r
       break;\r
 #endif\r
 \r
-    case OP_JUMP:  MOP_IN(OP_JUMP);\r
+    case OP_JUMP:  SOP_IN(OP_JUMP);\r
       GET_RELADDR_INC(addr, p);\r
       p += addr;\r
-      MOP_OUT;\r
-      CHECK_INTERRUPT_IN_MATCH_AT;\r
+      SOP_OUT;\r
+      CHECK_INTERRUPT_IN_MATCH;\r
       continue;\r
       break;\r
 \r
-    case OP_PUSH:  MOP_IN(OP_PUSH);\r
+    case OP_PUSH:  SOP_IN(OP_PUSH);\r
       GET_RELADDR_INC(addr, p);\r
       STACK_PUSH_ALT(p + addr, s, sprev);\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-#ifdef USE_COMBINATION_EXPLOSION_CHECK\r
-    case OP_STATE_CHECK_PUSH:  MOP_IN(OP_STATE_CHECK_PUSH);\r
-      GET_STATE_CHECK_NUM_INC(mem, p);\r
-      STATE_CHECK_VAL(scv, mem);\r
-      if (scv) goto fail;\r
-\r
+    case OP_PUSH_SUPER:  SOP_IN(OP_PUSH_SUPER);\r
       GET_RELADDR_INC(addr, p);\r
-      STACK_PUSH_ALT_WITH_STATE_CHECK(p + addr, s, sprev, mem);\r
-      MOP_OUT;\r
-      continue;\r
-      break;\r
-\r
-    case OP_STATE_CHECK_PUSH_OR_JUMP:  MOP_IN(OP_STATE_CHECK_PUSH_OR_JUMP);\r
-      GET_STATE_CHECK_NUM_INC(mem, p);\r
-      GET_RELADDR_INC(addr, p);\r
-      STATE_CHECK_VAL(scv, mem);\r
-      if (scv) {\r
-       p += addr;\r
-      }\r
-      else {\r
-       STACK_PUSH_ALT_WITH_STATE_CHECK(p + addr, s, sprev, mem);\r
-      }\r
-      MOP_OUT;\r
+      STACK_PUSH_SUPER_ALT(p + addr, s, sprev);\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_STATE_CHECK:  MOP_IN(OP_STATE_CHECK);\r
-      GET_STATE_CHECK_NUM_INC(mem, p);\r
-      STATE_CHECK_VAL(scv, mem);\r
-      if (scv) goto fail;\r
-\r
-      STACK_PUSH_STATE_CHECK(s, mem);\r
-      MOP_OUT;\r
-      continue;\r
-      break;\r
-#endif /* USE_COMBINATION_EXPLOSION_CHECK */\r
-\r
-    case OP_POP:  MOP_IN(OP_POP);\r
+    case OP_POP_OUT:  SOP_IN(OP_POP_OUT);\r
       STACK_POP_ONE;\r
-      MOP_OUT;\r
+      /* for stop backtrack */\r
+      /* CHECK_RETRY_LIMIT_IN_MATCH; */\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_PUSH_OR_JUMP_EXACT1:  MOP_IN(OP_PUSH_OR_JUMP_EXACT1);\r
+    case OP_PUSH_OR_JUMP_EXACT1:  SOP_IN(OP_PUSH_OR_JUMP_EXACT1);\r
       GET_RELADDR_INC(addr, p);\r
       if (*p == *s && DATA_ENSURE_CHECK1) {\r
-       p++;\r
-       STACK_PUSH_ALT(p + addr, s, sprev);\r
-       MOP_OUT;\r
-       continue;\r
+        p++;\r
+        STACK_PUSH_ALT(p + addr, s, sprev);\r
+        SOP_OUT;\r
+        continue;\r
       }\r
       p += (addr + 1);\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_PUSH_IF_PEEK_NEXT:  MOP_IN(OP_PUSH_IF_PEEK_NEXT);\r
+    case OP_PUSH_IF_PEEK_NEXT:  SOP_IN(OP_PUSH_IF_PEEK_NEXT);\r
       GET_RELADDR_INC(addr, p);\r
       if (*p == *s) {\r
-       p++;\r
-       STACK_PUSH_ALT(p + addr, s, sprev);\r
-       MOP_OUT;\r
-       continue;\r
+        p++;\r
+        STACK_PUSH_ALT(p + addr, s, sprev);\r
+        SOP_OUT;\r
+        continue;\r
       }\r
       p++;\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_REPEAT:  MOP_IN(OP_REPEAT);\r
+    case OP_REPEAT:  SOP_IN(OP_REPEAT);\r
       {\r
-       GET_MEMNUM_INC(mem, p);    /* mem: OP_REPEAT ID */\r
-       GET_RELADDR_INC(addr, p);\r
+        GET_MEMNUM_INC(mem, p);    /* mem: OP_REPEAT ID */\r
+        GET_RELADDR_INC(addr, p);\r
 \r
-       STACK_ENSURE(1);\r
-       repeat_stk[mem] = GET_STACK_INDEX(stk);\r
-       STACK_PUSH_REPEAT(mem, p);\r
+        STACK_ENSURE(1);\r
+        repeat_stk[mem] = GET_STACK_INDEX(stk);\r
+        STACK_PUSH_REPEAT(mem, p);\r
 \r
-       if (reg->repeat_range[mem].lower == 0) {\r
-         STACK_PUSH_ALT(p + addr, s, sprev);\r
-       }\r
+        if (reg->repeat_range[mem].lower == 0) {\r
+          STACK_PUSH_ALT(p + addr, s, sprev);\r
+        }\r
       }\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_REPEAT_NG:  MOP_IN(OP_REPEAT_NG);\r
+    case OP_REPEAT_NG:  SOP_IN(OP_REPEAT_NG);\r
       {\r
-       GET_MEMNUM_INC(mem, p);    /* mem: OP_REPEAT ID */\r
-       GET_RELADDR_INC(addr, p);\r
+        GET_MEMNUM_INC(mem, p);    /* mem: OP_REPEAT ID */\r
+        GET_RELADDR_INC(addr, p);\r
 \r
-       STACK_ENSURE(1);\r
-       repeat_stk[mem] = GET_STACK_INDEX(stk);\r
-       STACK_PUSH_REPEAT(mem, p);\r
+        STACK_ENSURE(1);\r
+        repeat_stk[mem] = GET_STACK_INDEX(stk);\r
+        STACK_PUSH_REPEAT(mem, p);\r
 \r
-       if (reg->repeat_range[mem].lower == 0) {\r
-         STACK_PUSH_ALT(p, s, sprev);\r
-         p += addr;\r
-       }\r
+        if (reg->repeat_range[mem].lower == 0) {\r
+          STACK_PUSH_ALT(p, s, sprev);\r
+          p += addr;\r
+        }\r
       }\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_REPEAT_INC:  MOP_IN(OP_REPEAT_INC);\r
+    case OP_REPEAT_INC:  SOP_IN(OP_REPEAT_INC);\r
       GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */\r
       si = repeat_stk[mem];\r
       stkp = STACK_AT(si);\r
@@ -2559,19 +3681,19 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
         p = stkp->u.repeat.pcode;\r
       }\r
       STACK_PUSH_REPEAT_INC(si);\r
-      MOP_OUT;\r
-      CHECK_INTERRUPT_IN_MATCH_AT;\r
+      SOP_OUT;\r
+      CHECK_INTERRUPT_IN_MATCH;\r
       continue;\r
       break;\r
 \r
-    case OP_REPEAT_INC_SG:  MOP_IN(OP_REPEAT_INC_SG);\r
+    case OP_REPEAT_INC_SG:  SOP_IN(OP_REPEAT_INC_SG);\r
       GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */\r
       STACK_GET_REPEAT(mem, stkp);\r
       si = GET_STACK_INDEX(stkp);\r
       goto repeat_inc;\r
       break;\r
 \r
-    case OP_REPEAT_INC_NG:  MOP_IN(OP_REPEAT_INC_NG);\r
+    case OP_REPEAT_INC_NG:  SOP_IN(OP_REPEAT_INC_NG);\r
       GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */\r
       si = repeat_stk[mem];\r
       stkp = STACK_AT(si);\r
@@ -2593,104 +3715,234 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
       else if (stkp->u.repeat.count == reg->repeat_range[mem].upper) {\r
         STACK_PUSH_REPEAT_INC(si);\r
       }\r
-      MOP_OUT;\r
-      CHECK_INTERRUPT_IN_MATCH_AT;\r
+      SOP_OUT;\r
+      CHECK_INTERRUPT_IN_MATCH;\r
       continue;\r
       break;\r
 \r
-    case OP_REPEAT_INC_NG_SG:  MOP_IN(OP_REPEAT_INC_NG_SG);\r
+    case OP_REPEAT_INC_NG_SG:  SOP_IN(OP_REPEAT_INC_NG_SG);\r
       GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */\r
       STACK_GET_REPEAT(mem, stkp);\r
       si = GET_STACK_INDEX(stkp);\r
       goto repeat_inc_ng;\r
       break;\r
 \r
-    case OP_PUSH_POS:  MOP_IN(OP_PUSH_POS);\r
+    case OP_PREC_READ_START:  SOP_IN(OP_PREC_READ_START);\r
       STACK_PUSH_POS(s, sprev);\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_POP_POS:  MOP_IN(OP_POP_POS);\r
+    case OP_PREC_READ_END:  SOP_IN(OP_PREC_READ_END);\r
       {\r
-       STACK_POS_END(stkp);\r
-       s     = stkp->u.state.pstr;\r
-       sprev = stkp->u.state.pstr_prev;\r
+        STACK_EXEC_TO_VOID(stkp);\r
+        s     = stkp->u.state.pstr;\r
+        sprev = stkp->u.state.pstr_prev;\r
       }\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_PUSH_POS_NOT:  MOP_IN(OP_PUSH_POS_NOT);\r
+    case OP_PREC_READ_NOT_START:  SOP_IN(OP_PREC_READ_NOT_START);\r
       GET_RELADDR_INC(addr, p);\r
-      STACK_PUSH_POS_NOT(p + addr, s, sprev);\r
-      MOP_OUT;\r
+      STACK_PUSH_ALT_PREC_READ_NOT(p + addr, s, sprev);\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_FAIL_POS:  MOP_IN(OP_FAIL_POS);\r
-      STACK_POP_TIL_POS_NOT;\r
+    case OP_PREC_READ_NOT_END:  SOP_IN(OP_PREC_READ_NOT_END);\r
+      STACK_POP_TIL_ALT_PREC_READ_NOT;\r
       goto fail;\r
       break;\r
 \r
-    case OP_PUSH_STOP_BT:  MOP_IN(OP_PUSH_STOP_BT);\r
-      STACK_PUSH_STOP_BT;\r
-      MOP_OUT;\r
+    case OP_ATOMIC_START:  SOP_IN(OP_ATOMIC_START);\r
+      STACK_PUSH_TO_VOID_START;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_POP_STOP_BT:  MOP_IN(OP_POP_STOP_BT);\r
-      STACK_STOP_BT_END;\r
-      MOP_OUT;\r
+    case OP_ATOMIC_END:  SOP_IN(OP_ATOMIC_END);\r
+      STACK_EXEC_TO_VOID(stkp);\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_LOOK_BEHIND:  MOP_IN(OP_LOOK_BEHIND);\r
+    case OP_LOOK_BEHIND:  SOP_IN(OP_LOOK_BEHIND);\r
       GET_LENGTH_INC(tlen, p);\r
       s = (UChar* )ONIGENC_STEP_BACK(encode, str, s, (int )tlen);\r
       if (IS_NULL(s)) goto fail;\r
       sprev = (UChar* )onigenc_get_prev_char_head(encode, str, s);\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_PUSH_LOOK_BEHIND_NOT:  MOP_IN(OP_PUSH_LOOK_BEHIND_NOT);\r
+    case OP_LOOK_BEHIND_NOT_START:  SOP_IN(OP_LOOK_BEHIND_NOT_START);\r
       GET_RELADDR_INC(addr, p);\r
       GET_LENGTH_INC(tlen, p);\r
       q = (UChar* )ONIGENC_STEP_BACK(encode, str, s, (int )tlen);\r
       if (IS_NULL(q)) {\r
-       /* too short case -> success. ex. /(?<!XXX)a/.match("a")\r
-          If you want to change to fail, replace following line. */\r
-       p += addr;\r
-       /* goto fail; */\r
+        /* too short case -> success. ex. /(?<!XXX)a/.match("a")\r
+           If you want to change to fail, replace following line. */\r
+        p += addr;\r
+        /* goto fail; */\r
       }\r
       else {\r
-       STACK_PUSH_LOOK_BEHIND_NOT(p + addr, s, sprev);\r
-       s = q;\r
-       sprev = (UChar* )onigenc_get_prev_char_head(encode, str, s);\r
+        STACK_PUSH_ALT_LOOK_BEHIND_NOT(p + addr, s, sprev);\r
+        s = q;\r
+        sprev = (UChar* )onigenc_get_prev_char_head(encode, str, s);\r
       }\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_FAIL_LOOK_BEHIND_NOT:  MOP_IN(OP_FAIL_LOOK_BEHIND_NOT);\r
-      STACK_POP_TIL_LOOK_BEHIND_NOT;\r
+    case OP_LOOK_BEHIND_NOT_END:  SOP_IN(OP_LOOK_BEHIND_NOT_END);\r
+      STACK_POP_TIL_ALT_LOOK_BEHIND_NOT;\r
       goto fail;\r
       break;\r
 \r
-#ifdef USE_SUBEXP_CALL\r
-    case OP_CALL:  MOP_IN(OP_CALL);\r
+#ifdef USE_CALL\r
+    case OP_CALL:  SOP_IN(OP_CALL);\r
       GET_ABSADDR_INC(addr, p);\r
       STACK_PUSH_CALL_FRAME(p);\r
       p = reg->p + addr;\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
-    case OP_RETURN:  MOP_IN(OP_RETURN);\r
+    case OP_RETURN:  SOP_IN(OP_RETURN);\r
       STACK_RETURN(p);\r
       STACK_PUSH_RETURN;\r
-      MOP_OUT;\r
+      SOP_OUT;\r
+      continue;\r
+      break;\r
+#endif\r
+\r
+    case OP_PUSH_SAVE_VAL: SOP_IN(OP_PUSH_SAVE_VAL);\r
+      {\r
+        SaveType type;\r
+        GET_SAVE_TYPE_INC(type, p);\r
+        GET_MEMNUM_INC(mem, p); /* mem: save id */\r
+        switch ((enum SaveType )type) {\r
+        case SAVE_KEEP:\r
+          STACK_PUSH_SAVE_VAL(mem, type, s);\r
+          break;\r
+\r
+        case SAVE_S:\r
+          STACK_PUSH_SAVE_VAL_WITH_SPREV(mem, type, s);\r
+          break;\r
+\r
+        case SAVE_RIGHT_RANGE:\r
+          STACK_PUSH_SAVE_VAL(mem, SAVE_RIGHT_RANGE, right_range);\r
+          break;\r
+        }\r
+      }\r
+      SOP_OUT;\r
+      continue;\r
+      break;\r
+\r
+    case OP_UPDATE_VAR: SOP_IN(OP_UPDATE_VAR);\r
+      {\r
+        UpdateVarType type;\r
+        enum SaveType save_type;\r
+\r
+        GET_UPDATE_VAR_TYPE_INC(type, p);\r
+        GET_MEMNUM_INC(mem, p); /* mem: save id */\r
+        switch ((enum UpdateVarType )type) {\r
+        case UPDATE_VAR_KEEP_FROM_STACK_LAST:\r
+          STACK_GET_SAVE_VAL_TYPE_LAST(SAVE_KEEP, keep);\r
+          break;\r
+        case UPDATE_VAR_S_FROM_STACK:\r
+          STACK_GET_SAVE_VAL_TYPE_LAST_ID_WITH_SPREV(SAVE_S, mem, s);\r
+          break;\r
+        case UPDATE_VAR_RIGHT_RANGE_FROM_S_STACK:\r
+          save_type = SAVE_S;\r
+          goto get_save_val_type_last_id;\r
+          break;\r
+        case UPDATE_VAR_RIGHT_RANGE_FROM_STACK:\r
+          save_type = SAVE_RIGHT_RANGE;\r
+        get_save_val_type_last_id:\r
+          STACK_GET_SAVE_VAL_TYPE_LAST_ID(save_type, mem, right_range);\r
+          break;\r
+        case UPDATE_VAR_RIGHT_RANGE_INIT:\r
+          INIT_RIGHT_RANGE;\r
+          break;\r
+        }\r
+      }\r
+      SOP_OUT;\r
+      continue;\r
+      break;\r
+\r
+#ifdef USE_CALLOUT\r
+    case OP_CALLOUT_CONTENTS: SOP_IN(OP_CALLOUT_CONTENTS);\r
+      of = ONIG_CALLOUT_OF_CONTENTS;\r
+      goto callout_common_entry;\r
+\r
+      SOP_OUT;\r
+      continue;\r
+      break;\r
+\r
+    case OP_CALLOUT_NAME: SOP_IN(OP_CALLOUT_NAME);\r
+      {\r
+        int call_result;\r
+        int name_id;\r
+        int num;\r
+        int in;\r
+        CalloutListEntry* e;\r
+        OnigCalloutFunc func;\r
+        OnigCalloutArgs args;\r
+\r
+        of = ONIG_CALLOUT_OF_NAME;\r
+        GET_MEMNUM_INC(name_id, p);\r
+\r
+      callout_common_entry:\r
+        GET_MEMNUM_INC(num, p);\r
+        e = onig_reg_callout_list_at(reg, num);\r
+        in = e->in;\r
+        if (of == ONIG_CALLOUT_OF_NAME) {\r
+          func = onig_get_callout_start_func(reg, num);\r
+        }\r
+        else {\r
+          name_id = ONIG_NON_NAME_ID;\r
+          func = msa->mp->progress_callout_of_contents;\r
+        }\r
+\r
+        if (IS_NOT_NULL(func) && (in & ONIG_CALLOUT_IN_PROGRESS) != 0) {\r
+          CALLOUT_BODY(func, ONIG_CALLOUT_IN_PROGRESS, name_id,\r
+                       num, msa->mp->callout_user_data, args, call_result);\r
+          switch (call_result) {\r
+          case ONIG_CALLOUT_FAIL:\r
+            goto fail;\r
+            break;\r
+          case ONIG_CALLOUT_SUCCESS:\r
+            goto retraction_callout2;\r
+            break;\r
+          default: /* error code */\r
+            if (call_result > 0) {\r
+              call_result = ONIGERR_INVALID_ARGUMENT;\r
+            }\r
+            best_len = call_result;\r
+            goto finish;\r
+            break;\r
+          }\r
+        }\r
+        else {\r
+        retraction_callout2:\r
+          if ((in & ONIG_CALLOUT_IN_RETRACTION) != 0) {\r
+            if (of == ONIG_CALLOUT_OF_NAME) {\r
+              if (IS_NOT_NULL(func)) {\r
+                STACK_PUSH_CALLOUT_NAME(name_id, num, func);\r
+              }\r
+            }\r
+            else {\r
+              func = msa->mp->retraction_callout_of_contents;\r
+              if (IS_NOT_NULL(func)) {\r
+                STACK_PUSH_CALLOUT_CONTENTS(num, func);\r
+              }\r
+            }\r
+          }\r
+        }\r
+      }\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 #endif\r
@@ -2700,22 +3952,15 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
       break;\r
 \r
     fail:\r
-      MOP_OUT;\r
+      SOP_OUT;\r
       /* fall */\r
-    case OP_FAIL:  MOP_IN(OP_FAIL);\r
+    case OP_FAIL:  SOP_IN(OP_FAIL);\r
       STACK_POP;\r
       p     = stk->u.state.pcode;\r
       s     = stk->u.state.pstr;\r
       sprev = stk->u.state.pstr_prev;\r
-\r
-#ifdef USE_COMBINATION_EXPLOSION_CHECK\r
-      if (stk->u.state.state_check != 0) {\r
-        stk->type = STK_STATE_CHECK_MARK;\r
-        stk++;\r
-      }\r
-#endif\r
-\r
-      MOP_OUT;\r
+      CHECK_RETRY_LIMIT_IN_MATCH;\r
+      SOP_OUT;\r
       continue;\r
       break;\r
 \r
@@ -2728,31 +3973,33 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
 \r
  finish:\r
   STACK_SAVE;\r
-  xfree(alloca_base);\r
   return best_len;\r
 \r
 #ifdef ONIG_DEBUG\r
  stack_error:\r
   STACK_SAVE;\r
-  xfree(alloca_base);\r
   return ONIGERR_STACK_BUG;\r
 #endif\r
 \r
  bytecode_error:\r
   STACK_SAVE;\r
-  xfree(alloca_base);\r
   return ONIGERR_UNDEFINED_BYTECODE;\r
 \r
  unexpected_bytecode_error:\r
   STACK_SAVE;\r
-  xfree(alloca_base);\r
   return ONIGERR_UNEXPECTED_BYTECODE;\r
+\r
+#ifdef USE_RETRY_LIMIT_IN_MATCH\r
+ retry_limit_in_match_over:\r
+  STACK_SAVE;\r
+  return ONIGERR_RETRY_LIMIT_IN_MATCH_OVER;\r
+#endif\r
 }\r
 \r
 \r
 static UChar*\r
 slow_search(OnigEncoding enc, UChar* target, UChar* target_end,\r
-           const UChar* text, const UChar* text_end, UChar* text_range)\r
+            const UChar* text, const UChar* text_end, UChar* text_range)\r
 {\r
   UChar *t, *p, *s, *end;\r
 \r
@@ -2768,12 +4015,12 @@ slow_search(OnigEncoding enc, UChar* target, UChar* target_end,
       p = s + 1;\r
       t = target + 1;\r
       while (t < target_end) {\r
-       if (*t != *p++)\r
-         break;\r
-       t++;\r
+        if (*t != *p++)\r
+          break;\r
+        t++;\r
       }\r
       if (t == target_end)\r
-       return s;\r
+        return s;\r
     }\r
     s += enclen(enc, s);\r
   }\r
@@ -2784,7 +4031,7 @@ slow_search(OnigEncoding enc, UChar* target, UChar* target_end,
 static int\r
 str_lower_case_match(OnigEncoding enc, int case_fold_flag,\r
                      const UChar* t, const UChar* tend,\r
-                    const UChar* p, const UChar* end)\r
+                     const UChar* p, const UChar* end)\r
 {\r
   int lowlen;\r
   UChar *q, lowbuf[ONIGENC_MBC_CASE_FOLD_MAXLEN];\r
@@ -2793,7 +4040,7 @@ str_lower_case_match(OnigEncoding enc, int case_fold_flag,
     lowlen = ONIGENC_MBC_CASE_FOLD(enc, case_fold_flag, &p, end, lowbuf);\r
     q = lowbuf;\r
     while (lowlen > 0) {\r
-      if (*t++ != *q++)        return 0;\r
+      if (*t++ != *q++) return 0;\r
       lowlen--;\r
     }\r
   }\r
@@ -2803,8 +4050,8 @@ str_lower_case_match(OnigEncoding enc, int case_fold_flag,
 \r
 static UChar*\r
 slow_search_ic(OnigEncoding enc, int case_fold_flag,\r
-              UChar* target, UChar* target_end,\r
-              const UChar* text, const UChar* text_end, UChar* text_range)\r
+               UChar* target, UChar* target_end,\r
+               const UChar* text, const UChar* text_end, UChar* text_range)\r
 {\r
   UChar *s, *end;\r
 \r
@@ -2817,7 +4064,7 @@ slow_search_ic(OnigEncoding enc, int case_fold_flag,
 \r
   while (s < end) {\r
     if (str_lower_case_match(enc, case_fold_flag, target, target_end,\r
-                            s, text_end))\r
+                             s, text_end))\r
       return s;\r
 \r
     s += enclen(enc, s);\r
@@ -2828,8 +4075,8 @@ slow_search_ic(OnigEncoding enc, int case_fold_flag,
 \r
 static UChar*\r
 slow_search_backward(OnigEncoding enc, UChar* target, UChar* target_end,\r
-                    const UChar* text, const UChar* adjust_text,\r
-                    const UChar* text_end, const UChar* text_start)\r
+                     const UChar* text, const UChar* adjust_text,\r
+                     const UChar* text_end, const UChar* text_start)\r
 {\r
   UChar *t, *p, *s;\r
 \r
@@ -2845,12 +4092,12 @@ slow_search_backward(OnigEncoding enc, UChar* target, UChar* target_end,
       p = s + 1;\r
       t = target + 1;\r
       while (t < target_end) {\r
-       if (*t != *p++)\r
-         break;\r
-       t++;\r
+        if (*t != *p++)\r
+          break;\r
+        t++;\r
       }\r
       if (t == target_end)\r
-       return s;\r
+        return s;\r
     }\r
     s = (UChar* )onigenc_get_prev_char_head(enc, adjust_text, s);\r
   }\r
@@ -2860,9 +4107,9 @@ slow_search_backward(OnigEncoding enc, UChar* target, UChar* target_end,
 \r
 static UChar*\r
 slow_search_backward_ic(OnigEncoding enc, int case_fold_flag,\r
-                       UChar* target, UChar* target_end,\r
-                       const UChar* text, const UChar* adjust_text,\r
-                       const UChar* text_end, const UChar* text_start)\r
+                        UChar* target, UChar* target_end,\r
+                        const UChar* text, const UChar* adjust_text,\r
+                        const UChar* text_end, const UChar* text_start)\r
 {\r
   UChar *s;\r
 \r
@@ -2886,20 +4133,20 @@ slow_search_backward_ic(OnigEncoding enc, int case_fold_flag,
 \r
 static UChar*\r
 bm_search_notrev(regex_t* reg, const UChar* target, const UChar* target_end,\r
-                const UChar* text, const UChar* text_end,\r
-                const UChar* text_range)\r
+                 const UChar* text, const UChar* text_end,\r
+                 const UChar* text_range)\r
 {\r
   const UChar *s, *se, *t, *p, *end;\r
   const UChar *tail;\r
   int skip, tlen1;\r
 \r
 #ifdef ONIG_DEBUG_SEARCH\r
-  fprintf(stderr, "bm_search_notrev: text: %d, text_end: %d, text_range: %d\n",\r
-         (int )text, (int )text_end, (int )text_range);\r
+  fprintf(stderr, "bm_search_notrev: text: %p, text_end: %p, text_range: %p\n",\r
+          text, text_end, text_range);\r
 #endif\r
 \r
   tail = target_end - 1;\r
-  tlen1 = (int)(tail - target);\r
+  tlen1 = (int )(tail - target);\r
   end = text_range;\r
   if (end + tlen1 > text_end)\r
     end = text_end - tlen1;\r
@@ -2911,8 +4158,8 @@ bm_search_notrev(regex_t* reg, const UChar* target, const UChar* target_end,
       p = se = s + tlen1;\r
       t = tail;\r
       while (*p == *t) {\r
-       if (t == target) return (UChar* )s;\r
-       p--; t--;\r
+        if (t == target) return (UChar* )s;\r
+        p--; t--;\r
       }\r
       skip = reg->map[*se];\r
       t = s;\r
@@ -2926,8 +4173,8 @@ bm_search_notrev(regex_t* reg, const UChar* target, const UChar* target_end,
       p = se = s + tlen1;\r
       t = tail;\r
       while (*p == *t) {\r
-       if (t == target) return (UChar* )s;\r
-       p--; t--;\r
+        if (t == target) return (UChar* )s;\r
+        p--; t--;\r
       }\r
       skip = reg->int_map[*se];\r
       t = s;\r
@@ -2942,7 +4189,7 @@ bm_search_notrev(regex_t* reg, const UChar* target, const UChar* target_end,
 \r
 static UChar*\r
 bm_search(regex_t* reg, const UChar* target, const UChar* target_end,\r
-         const UChar* text, const UChar* text_end, const UChar* text_range)\r
+          const UChar* text, const UChar* text_end, const UChar* text_range)\r
 {\r
   const UChar *s, *t, *p, *end;\r
   const UChar *tail;\r
@@ -2958,8 +4205,8 @@ bm_search(regex_t* reg, const UChar* target, const UChar* target_end,
       p = s;\r
       t = tail;\r
       while (*p == *t) {\r
-       if (t == target) return (UChar* )p;\r
-       p--; t--;\r
+        if (t == target) return (UChar* )p;\r
+        p--; t--;\r
       }\r
       s += reg->map[*s];\r
     }\r
@@ -2969,8 +4216,8 @@ bm_search(regex_t* reg, const UChar* target, const UChar* target_end,
       p = s;\r
       t = tail;\r
       while (*p == *t) {\r
-       if (t == target) return (UChar* )p;\r
-       p--; t--;\r
+        if (t == target) return (UChar* )p;\r
+        p--; t--;\r
       }\r
       s += reg->int_map[*s];\r
     }\r
@@ -2978,10 +4225,9 @@ bm_search(regex_t* reg, const UChar* target, const UChar* target_end,
   return (UChar* )NULL;\r
 }\r
 \r
+#ifdef USE_INT_MAP_BACKWARD\r
 static int\r
-set_bm_backward_skip(UChar* s, UChar* end, OnigEncoding enc ARG_UNUSED,\r
-                    int** skip)\r
-                    \r
+set_bm_backward_skip(UChar* s, UChar* end, OnigEncoding enc ARG_UNUSED, int** skip)\r
 {\r
   int i, len;\r
 \r
@@ -2990,7 +4236,7 @@ set_bm_backward_skip(UChar* s, UChar* end, OnigEncoding enc ARG_UNUSED,
     if (IS_NULL(*skip)) return ONIGERR_MEMORY;\r
   }\r
 \r
-  len = (int)(end - s);\r
+  len = end - s;\r
   for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++)\r
     (*skip)[i] = len;\r
 \r
@@ -3002,8 +4248,8 @@ set_bm_backward_skip(UChar* s, UChar* end, OnigEncoding enc ARG_UNUSED,
 \r
 static UChar*\r
 bm_search_backward(regex_t* reg, const UChar* target, const UChar* target_end,\r
-                  const UChar* text, const UChar* adjust_text,\r
-                  const UChar* text_end, const UChar* text_start)\r
+                   const UChar* text, const UChar* adjust_text,\r
+                   const UChar* text_end, const UChar* text_start)\r
 {\r
   const UChar *s, *t, *p;\r
 \r
@@ -3028,10 +4274,11 @@ bm_search_backward(regex_t* reg, const UChar* target, const UChar* target_end,
 \r
   return (UChar* )NULL;\r
 }\r
+#endif\r
 \r
 static UChar*\r
 map_search(OnigEncoding enc, UChar map[],\r
-          const UChar* text, const UChar* text_range)\r
+           const UChar* text, const UChar* text_range)\r
 {\r
   const UChar *s = text;\r
 \r
@@ -3045,8 +4292,8 @@ map_search(OnigEncoding enc, UChar map[],
 \r
 static UChar*\r
 map_search_backward(OnigEncoding enc, UChar map[],\r
-                   const UChar* text, const UChar* adjust_text,\r
-                   const UChar* text_start)\r
+                    const UChar* text, const UChar* adjust_text,\r
+                    const UChar* text_start)\r
 {\r
   const UChar *s = text_start;\r
 \r
@@ -3057,48 +4304,30 @@ map_search_backward(OnigEncoding enc, UChar map[],
   }\r
   return (UChar* )NULL;\r
 }\r
+extern int\r
+onig_match(regex_t* reg, const UChar* str, const UChar* end, const UChar* at,\r
+           OnigRegion* region, OnigOptionType option)\r
+{\r
+  int r;\r
+  OnigMatchParam mp;\r
+\r
+  onig_initialize_match_param(&mp);\r
+  r = onig_match_with_param(reg, str, end, at, region, option, &mp);\r
+  onig_free_match_param_content(&mp);\r
+  return r;\r
+}\r
 \r
 extern int\r
-onig_match(regex_t* reg, const UChar* str, const UChar* end, const UChar* at, OnigRegion* region,\r
-           OnigOptionType option)\r
+onig_match_with_param(regex_t* reg, const UChar* str, const UChar* end,\r
+                      const UChar* at, OnigRegion* region, OnigOptionType option,\r
+                      OnigMatchParam* mp)\r
 {\r
   int r;\r
   UChar *prev;\r
-  OnigMatchArg msa;\r
-\r
-#if defined(USE_RECOMPILE_API) && defined(USE_MULTI_THREAD_SYSTEM)\r
- start:\r
-  THREAD_ATOMIC_START;\r
-  if (ONIG_STATE(reg) >= ONIG_STATE_NORMAL) {\r
-    ONIG_STATE_INC(reg);\r
-    if (IS_NOT_NULL(reg->chain) && ONIG_STATE(reg) == ONIG_STATE_NORMAL) {\r
-      onig_chain_reduce(reg);\r
-      ONIG_STATE_INC(reg);\r
-    }\r
-  }\r
-  else {\r
-    int n;\r
-\r
-    THREAD_ATOMIC_END;\r
-    n = 0;\r
-    while (ONIG_STATE(reg) < ONIG_STATE_NORMAL) {\r
-      if (++n > THREAD_PASS_LIMIT_COUNT)\r
-       return ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT;\r
-      THREAD_PASS;\r
-    }\r
-    goto start;\r
-  }\r
-  THREAD_ATOMIC_END;\r
-#endif /* USE_RECOMPILE_API && USE_MULTI_THREAD_SYSTEM */\r
-\r
-  MATCH_ARG_INIT(msa, option, region, at);\r
-#ifdef USE_COMBINATION_EXPLOSION_CHECK\r
-  {\r
-    int offset = at - str;\r
-    STATE_CHECK_BUFF_INIT(msa, end - str, offset, reg->num_comb_exp_check);\r
-  }\r
-#endif\r
+  MatchArg msa;\r
 \r
+  ADJUST_MATCH_PARAM(reg, mp);\r
+  MATCH_ARG_INIT(msa, reg, option, region, at, mp);\r
   if (region\r
 #ifdef USE_POSIX_API_REGION_OPTION\r
       && !IS_POSIX_REGION(option)\r
@@ -3110,28 +4339,31 @@ onig_match(regex_t* reg, const UChar* str, const UChar* end, const UChar* at, On
     r = 0;\r
 \r
   if (r == 0) {\r
+    if (ONIG_IS_OPTION_ON(option, ONIG_OPTION_CHECK_VALIDITY_OF_STRING)) {\r
+      if (! ONIGENC_IS_VALID_MBC_STRING(reg->enc, str, end)) {\r
+        r = ONIGERR_INVALID_WIDE_CHAR_VALUE;\r
+        goto end;\r
+      }\r
+    }\r
+\r
     prev = (UChar* )onigenc_get_prev_char_head(reg->enc, str, at);\r
-    r = match_at(reg, str, end,\r
-#ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE\r
-                end,\r
-#endif\r
-                at, prev, &msa);\r
+    r = match_at(reg, str, end, end, at, prev, &msa);\r
   }\r
 \r
+ end:\r
   MATCH_ARG_FREE(msa);\r
-  ONIG_STATE_DEC_THREAD(reg);\r
   return r;\r
 }\r
 \r
 static int\r
 forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,\r
-                    UChar* range, UChar** low, UChar** high, UChar** low_prev)\r
+                     UChar* range, UChar** low, UChar** high, UChar** low_prev)\r
 {\r
   UChar *p, *pprev = (UChar* )NULL;\r
 \r
 #ifdef ONIG_DEBUG_SEARCH\r
-  fprintf(stderr, "forward_search_range: str: %d, end: %d, s: %d, range: %d\n",\r
-         (int )str, (int )end, (int )s, (int )range);\r
+  fprintf(stderr, "forward_search_range: str: %p, end: %p, s: %p, range: %p\n",\r
+          str, end, s, range);\r
 #endif\r
 \r
   p = s;\r
@@ -3141,29 +4373,31 @@ forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
     }\r
     else {\r
       UChar *q = p + reg->dmin;\r
+\r
+      if (q >= end) return 0; /* fail */\r
       while (p < q) p += enclen(reg->enc, p);\r
     }\r
   }\r
 \r
  retry:\r
   switch (reg->optimize) {\r
-  case ONIG_OPTIMIZE_EXACT:\r
+  case OPTIMIZE_EXACT:\r
     p = slow_search(reg->enc, reg->exact, reg->exact_end, p, end, range);\r
     break;\r
-  case ONIG_OPTIMIZE_EXACT_IC:\r
+  case OPTIMIZE_EXACT_IC:\r
     p = slow_search_ic(reg->enc, reg->case_fold_flag,\r
                        reg->exact, reg->exact_end, p, end, range);\r
     break;\r
 \r
-  case ONIG_OPTIMIZE_EXACT_BM:\r
+  case OPTIMIZE_EXACT_BM:\r
     p = bm_search(reg, reg->exact, reg->exact_end, p, end, range);\r
     break;\r
 \r
-  case ONIG_OPTIMIZE_EXACT_BM_NOT_REV:\r
+  case OPTIMIZE_EXACT_BM_NO_REV:\r
     p = bm_search_notrev(reg, reg->exact, reg->exact_end, p, end, range);\r
     break;\r
 \r
-  case ONIG_OPTIMIZE_MAP:\r
+  case OPTIMIZE_MAP:\r
     p = map_search(reg->enc, reg->map, p, range);\r
     break;\r
   }\r
@@ -3181,58 +4415,65 @@ forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
 \r
       switch (reg->sub_anchor) {\r
       case ANCHOR_BEGIN_LINE:\r
-       if (!ON_STR_BEGIN(p)) {\r
-         prev = onigenc_get_prev_char_head(reg->enc,\r
-                                           (pprev ? pprev : str), p);\r
-         if (!ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end))\r
-           goto retry_gate;\r
-       }\r
-       break;\r
+        if (!ON_STR_BEGIN(p)) {\r
+          prev = onigenc_get_prev_char_head(reg->enc,\r
+                                            (pprev ? pprev : str), p);\r
+          if (!ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end))\r
+            goto retry_gate;\r
+        }\r
+        break;\r
 \r
       case ANCHOR_END_LINE:\r
-       if (ON_STR_END(p)) {\r
+        if (ON_STR_END(p)) {\r
 #ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE\r
-         prev = (UChar* )onigenc_get_prev_char_head(reg->enc,\r
-                                           (pprev ? pprev : str), p);\r
-         if (prev && ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end))\r
-           goto retry_gate;\r
+          prev = (UChar* )onigenc_get_prev_char_head(reg->enc,\r
+                                                     (pprev ? pprev : str), p);\r
+          if (prev && ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end))\r
+            goto retry_gate;\r
 #endif\r
-       }\r
-       else if (! ONIGENC_IS_MBC_NEWLINE(reg->enc, p, end)\r
+        }\r
+        else if (! ONIGENC_IS_MBC_NEWLINE(reg->enc, p, end)\r
 #ifdef USE_CRNL_AS_LINE_TERMINATOR\r
-              && ! ONIGENC_IS_MBC_CRNL(reg->enc, p, end)\r
+                 && ! ONIGENC_IS_MBC_CRNL(reg->enc, p, end)\r
 #endif\r
-                )\r
-         goto retry_gate;\r
-       break;\r
+                 )\r
+          goto retry_gate;\r
+        break;\r
       }\r
     }\r
 \r
     if (reg->dmax == 0) {\r
       *low = p;\r
       if (low_prev) {\r
-       if (*low > s)\r
-         *low_prev = onigenc_get_prev_char_head(reg->enc, s, p);\r
-       else\r
-         *low_prev = onigenc_get_prev_char_head(reg->enc,\r
-                                                (pprev ? pprev : str), p);\r
+        if (*low > s)\r
+          *low_prev = onigenc_get_prev_char_head(reg->enc, s, p);\r
+        else\r
+          *low_prev = onigenc_get_prev_char_head(reg->enc,\r
+                                                 (pprev ? pprev : str), p);\r
       }\r
     }\r
     else {\r
-      if (reg->dmax != ONIG_INFINITE_DISTANCE) {\r
-       *low = p - reg->dmax;\r
-       if (*low > s) {\r
-         *low = onigenc_get_right_adjust_char_head_with_prev(reg->enc, s,\r
-                                                             *low, (const UChar** )low_prev);\r
-         if (low_prev && IS_NULL(*low_prev))\r
-           *low_prev = onigenc_get_prev_char_head(reg->enc,\r
-                                                  (pprev ? pprev : s), *low);\r
-       }\r
-       else {\r
-         if (low_prev)\r
-           *low_prev = onigenc_get_prev_char_head(reg->enc,\r
-                                              (pprev ? pprev : str), *low);\r
-       }\r
+      if (reg->dmax != INFINITE_LEN) {\r
+        if (p - str < reg->dmax) {\r
+          *low = (UChar* )str;\r
+          if (low_prev)\r
+            *low_prev = onigenc_get_prev_char_head(reg->enc, str, *low);\r
+        }\r
+        else {\r
+          *low = p - reg->dmax;\r
+          if (*low > s) {\r
+            *low = onigenc_get_right_adjust_char_head_with_prev(reg->enc, s,\r
+                                                 *low, (const UChar** )low_prev);\r
+            if (low_prev && IS_NULL(*low_prev))\r
+              *low_prev = onigenc_get_prev_char_head(reg->enc,\r
+                                                     (pprev ? pprev : s), *low);\r
+          }\r
+          else {\r
+            if (low_prev)\r
+              *low_prev = onigenc_get_prev_char_head(reg->enc,\r
+                                                     (pprev ? pprev : str), *low);\r
+          }\r
+        }\r
       }\r
     }\r
     /* no needs to adjust *high, *high is used as range check only */\r
@@ -3240,8 +4481,8 @@ forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
 \r
 #ifdef ONIG_DEBUG_SEARCH\r
     fprintf(stderr,\r
-    "forward_search_range success: low: %d, high: %d, dmin: %d, dmax: %d\n",\r
-           (int )(*low - str), (int )(*high - str), reg->dmin, reg->dmax);\r
+            "forward_search_range success: low: %d, high: %d, dmin: %d, dmax: %d\n",\r
+            (int )(*low - str), (int )(*high - str), reg->dmin, reg->dmax);\r
 #endif\r
     return 1; /* success */\r
   }\r
@@ -3249,17 +4490,14 @@ forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
   return 0; /* fail */\r
 }\r
 \r
-static int set_bm_backward_skip P_((UChar* s, UChar* end, OnigEncoding enc,\r
-                                   int** skip));\r
 \r
 #define BM_BACKWARD_SEARCH_LENGTH_THRESHOLD   100\r
 \r
 static int\r
 backward_search_range(regex_t* reg, const UChar* str, const UChar* end,\r
-                     UChar* s, const UChar* range, UChar* adjrange,\r
-                     UChar** low, UChar** high)\r
+                      UChar* s, const UChar* range, UChar* adjrange,\r
+                      UChar** low, UChar** high)\r
 {\r
-  int r;\r
   UChar *p;\r
 \r
   range += reg->dmin;\r
@@ -3267,33 +4505,39 @@ backward_search_range(regex_t* reg, const UChar* str, const UChar* end,
 \r
  retry:\r
   switch (reg->optimize) {\r
-  case ONIG_OPTIMIZE_EXACT:\r
+  case OPTIMIZE_EXACT:\r
   exact_method:\r
     p = slow_search_backward(reg->enc, reg->exact, reg->exact_end,\r
-                            range, adjrange, end, p);\r
+                             range, adjrange, end, p);\r
     break;\r
 \r
-  case ONIG_OPTIMIZE_EXACT_IC:\r
+  case OPTIMIZE_EXACT_IC:\r
     p = slow_search_backward_ic(reg->enc, reg->case_fold_flag,\r
                                 reg->exact, reg->exact_end,\r
                                 range, adjrange, end, p);\r
     break;\r
 \r
-  case ONIG_OPTIMIZE_EXACT_BM:\r
-  case ONIG_OPTIMIZE_EXACT_BM_NOT_REV:\r
+  case OPTIMIZE_EXACT_BM:\r
+  case OPTIMIZE_EXACT_BM_NO_REV:\r
+#ifdef USE_INT_MAP_BACKWARD\r
     if (IS_NULL(reg->int_map_backward)) {\r
+      int r;\r
+\r
       if (s - range < BM_BACKWARD_SEARCH_LENGTH_THRESHOLD)\r
-       goto exact_method;\r
+        goto exact_method;\r
 \r
       r = set_bm_backward_skip(reg->exact, reg->exact_end, reg->enc,\r
-                              &(reg->int_map_backward));\r
-      if (r) return r;\r
+                               &(reg->int_map_backward));\r
+      if (r != 0) return r;\r
     }\r
     p = bm_search_backward(reg, reg->exact, reg->exact_end, range, adjrange,\r
-                          end, p);\r
+                           end, p);\r
+#else\r
+    goto exact_method;\r
+#endif\r
     break;\r
 \r
-  case ONIG_OPTIMIZE_MAP:\r
+  case OPTIMIZE_MAP:\r
     p = map_search_backward(reg->enc, reg->map, range, adjrange, p);\r
     break;\r
   }\r
@@ -3304,41 +4548,41 @@ backward_search_range(regex_t* reg, const UChar* str, const UChar* end,
 \r
       switch (reg->sub_anchor) {\r
       case ANCHOR_BEGIN_LINE:\r
-       if (!ON_STR_BEGIN(p)) {\r
-         prev = onigenc_get_prev_char_head(reg->enc, str, p);\r
-         if (!ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end)) {\r
-           p = prev;\r
-           goto retry;\r
-         }\r
-       }\r
-       break;\r
+        if (!ON_STR_BEGIN(p)) {\r
+          prev = onigenc_get_prev_char_head(reg->enc, str, p);\r
+          if (!ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end)) {\r
+            p = prev;\r
+            goto retry;\r
+          }\r
+        }\r
+        break;\r
 \r
       case ANCHOR_END_LINE:\r
-       if (ON_STR_END(p)) {\r
+        if (ON_STR_END(p)) {\r
 #ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE\r
-         prev = onigenc_get_prev_char_head(reg->enc, adjrange, p);\r
-         if (IS_NULL(prev)) goto fail;\r
-         if (ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end)) {\r
-           p = prev;\r
-           goto retry;\r
-         }\r
-#endif\r
-       }\r
-       else if (! ONIGENC_IS_MBC_NEWLINE(reg->enc, p, end)\r
+          prev = onigenc_get_prev_char_head(reg->enc, adjrange, p);\r
+          if (IS_NULL(prev)) goto fail;\r
+          if (ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end)) {\r
+            p = prev;\r
+            goto retry;\r
+          }\r
+#endif\r
+        }\r
+        else if (! ONIGENC_IS_MBC_NEWLINE(reg->enc, p, end)\r
 #ifdef USE_CRNL_AS_LINE_TERMINATOR\r
-              && ! ONIGENC_IS_MBC_CRNL(reg->enc, p, end)\r
+                 && ! ONIGENC_IS_MBC_CRNL(reg->enc, p, end)\r
 #endif\r
-                ) {\r
-         p = onigenc_get_prev_char_head(reg->enc, adjrange, p);\r
-         if (IS_NULL(p)) goto fail;\r
-         goto retry;\r
-       }\r
-       break;\r
+                 ) {\r
+          p = onigenc_get_prev_char_head(reg->enc, adjrange, p);\r
+          if (IS_NULL(p)) goto fail;\r
+          goto retry;\r
+        }\r
+        break;\r
       }\r
     }\r
 \r
     /* no needs to adjust *high, *high is used as range check only */\r
-    if (reg->dmax != ONIG_INFINITE_DISTANCE) {\r
+    if (reg->dmax != INFINITE_LEN) {\r
       *low  = p - reg->dmax;\r
       *high = p - reg->dmin;\r
       *high = onigenc_get_right_adjust_char_head(reg->enc, adjrange, *high);\r
@@ -3346,7 +4590,7 @@ backward_search_range(regex_t* reg, const UChar* str, const UChar* end,
 \r
 #ifdef ONIG_DEBUG_SEARCH\r
     fprintf(stderr, "backward_search_range: low: %d, high: %d\n",\r
-           (int )(*low - str), (int )(*high - str));\r
+            (int )(*low - str), (int )(*high - str));\r
 #endif\r
     return 1; /* success */\r
   }\r
@@ -3361,60 +4605,57 @@ backward_search_range(regex_t* reg, const UChar* str, const UChar* end,
 \r
 extern int\r
 onig_search(regex_t* reg, const UChar* str, const UChar* end,\r
-           const UChar* start, const UChar* range, OnigRegion* region, OnigOptionType option)\r
+            const UChar* start, const UChar* range, OnigRegion* region,\r
+            OnigOptionType option)\r
+{\r
+  int r;\r
+  OnigMatchParam mp;\r
+\r
+  onig_initialize_match_param(&mp);\r
+  r = onig_search_with_param(reg, str, end, start, range, region, option, &mp);\r
+  onig_free_match_param_content(&mp);\r
+  return r;\r
+\r
+}\r
+\r
+extern int\r
+onig_search_with_param(regex_t* reg, const UChar* str, const UChar* end,\r
+                       const UChar* start, const UChar* range, OnigRegion* region,\r
+                       OnigOptionType option, OnigMatchParam* mp)\r
 {\r
   int r;\r
   UChar *s, *prev;\r
-  OnigMatchArg msa;\r
+  MatchArg msa;\r
   const UChar *orig_start = start;\r
-#ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE\r
   const UChar *orig_range = range;\r
-#endif\r
-\r
-#if defined(USE_RECOMPILE_API) && defined(USE_MULTI_THREAD_SYSTEM)\r
- start:\r
-  THREAD_ATOMIC_START;\r
-  if (ONIG_STATE(reg) >= ONIG_STATE_NORMAL) {\r
-    ONIG_STATE_INC(reg);\r
-    if (IS_NOT_NULL(reg->chain) && ONIG_STATE(reg) == ONIG_STATE_NORMAL) {\r
-      onig_chain_reduce(reg);\r
-      ONIG_STATE_INC(reg);\r
-    }\r
-  }\r
-  else {\r
-    int n;\r
-\r
-    THREAD_ATOMIC_END;\r
-    n = 0;\r
-    while (ONIG_STATE(reg) < ONIG_STATE_NORMAL) {\r
-      if (++n > THREAD_PASS_LIMIT_COUNT)\r
-       return ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT;\r
-      THREAD_PASS;\r
-    }\r
-    goto start;\r
-  }\r
-  THREAD_ATOMIC_END;\r
-#endif /* USE_RECOMPILE_API && USE_MULTI_THREAD_SYSTEM */\r
 \r
 #ifdef ONIG_DEBUG_SEARCH\r
   fprintf(stderr,\r
-     "onig_search (entry point): str: %d, end: %d, start: %d, range: %d\n",\r
-     (int )str, (int )(end - str), (int )(start - str), (int )(range - str));\r
+     "onig_search (entry point): str: %p, end: %d, start: %d, range: %d\n",\r
+     str, (int )(end - str), (int )(start - str), (int )(range - str));\r
 #endif\r
 \r
+  ADJUST_MATCH_PARAM(reg, mp);\r
+\r
   if (region\r
 #ifdef USE_POSIX_API_REGION_OPTION\r
       && !IS_POSIX_REGION(option)\r
 #endif\r
       ) {\r
     r = onig_region_resize_clear(region, reg->num_mem + 1);\r
-    if (r) goto finish_no_msa;\r
+    if (r != 0) goto finish_no_msa;\r
   }\r
 \r
   if (start > end || start < str) goto mismatch_no_msa;\r
 \r
+  if (ONIG_IS_OPTION_ON(option, ONIG_OPTION_CHECK_VALIDITY_OF_STRING)) {\r
+    if (! ONIGENC_IS_VALID_MBC_STRING(reg->enc, str, end)) {\r
+      r = ONIGERR_INVALID_WIDE_CHAR_VALUE;\r
+      goto finish_no_msa;\r
+    }\r
+  }\r
+\r
 \r
-#ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE\r
 #ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE\r
 #define MATCH_AND_RETURN_CHECK(upper_range) \\r
   r = match_at(reg, str, end, (upper_range), s, prev, &msa); \\r
@@ -3436,29 +4677,6 @@ onig_search(regex_t* reg, const UChar* str, const UChar* end,
     else goto finish; /* error */ \\r
   }\r
 #endif /* USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE */\r
-#else\r
-#ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE\r
-#define MATCH_AND_RETURN_CHECK(none) \\r
-  r = match_at(reg, str, end, s, prev, &msa);\\r
-  if (r != ONIG_MISMATCH) {\\r
-    if (r >= 0) {\\r
-      if (! IS_FIND_LONGEST(reg->options)) {\\r
-        goto match;\\r
-      }\\r
-    }\\r
-    else goto finish; /* error */ \\r
-  }\r
-#else\r
-#define MATCH_AND_RETURN_CHECK(none) \\r
-  r = match_at(reg, str, end, s, prev, &msa);\\r
-  if (r != ONIG_MISMATCH) {\\r
-    if (r >= 0) {\\r
-      goto match;\\r
-    }\\r
-    else goto finish; /* error */ \\r
-  }\r
-#endif /* USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE */\r
-#endif /* USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE */\r
 \r
 \r
   /* anchor optimize: resume search range */\r
@@ -3469,56 +4687,55 @@ onig_search(regex_t* reg, const UChar* str, const UChar* end,
       /* search start-position only */\r
     begin_position:\r
       if (range > start)\r
-       range = start + 1;\r
+        range = start + 1;\r
       else\r
-       range = start;\r
+        range = start;\r
     }\r
     else if (reg->anchor & ANCHOR_BEGIN_BUF) {\r
       /* search str-position only */\r
       if (range > start) {\r
-       if (start != str) goto mismatch_no_msa;\r
-       range = str + 1;\r
+        if (start != str) goto mismatch_no_msa;\r
+        range = str + 1;\r
       }\r
       else {\r
-       if (range <= str) {\r
-         start = str;\r
-         range = str;\r
-       }\r
-       else\r
-         goto mismatch_no_msa;\r
+        if (range <= str) {\r
+          start = str;\r
+          range = str;\r
+        }\r
+        else\r
+          goto mismatch_no_msa;\r
       }\r
     }\r
     else if (reg->anchor & ANCHOR_END_BUF) {\r
       min_semi_end = max_semi_end = (UChar* )end;\r
 \r
     end_buf:\r
-      if ((OnigDistance )(max_semi_end - str) < reg->anchor_dmin)\r
-       goto mismatch_no_msa;\r
+      if ((OnigLen )(max_semi_end - str) < reg->anchor_dmin)\r
+        goto mismatch_no_msa;\r
 \r
       if (range > start) {\r
-       if ((OnigDistance )(min_semi_end - start) > reg->anchor_dmax) {\r
-         start = min_semi_end - reg->anchor_dmax;\r
-         if (start < end)\r
-           start = onigenc_get_right_adjust_char_head(reg->enc, str, start);\r
-         else { /* match with empty at end */\r
-           start = onigenc_get_prev_char_head(reg->enc, str, end);\r
-         }\r
-       }\r
-       if ((OnigDistance )(max_semi_end - (range - 1)) < reg->anchor_dmin) {\r
-         range = max_semi_end - reg->anchor_dmin + 1;\r
-       }\r
-\r
-       if (start >= range) goto mismatch_no_msa;\r
+        if ((OnigLen )(min_semi_end - start) > reg->anchor_dmax) {\r
+          start = min_semi_end - reg->anchor_dmax;\r
+          if (start < end)\r
+            start = onigenc_get_right_adjust_char_head(reg->enc, str, start);\r
+        }\r
+        if ((OnigLen )(max_semi_end - (range - 1)) < reg->anchor_dmin) {\r
+          range = max_semi_end - reg->anchor_dmin + 1;\r
+        }\r
+\r
+        if (start > range) goto mismatch_no_msa;\r
+        /* If start == range, match with empty at end.\r
+           Backward search is used. */\r
       }\r
       else {\r
-       if ((OnigDistance )(min_semi_end - range) > reg->anchor_dmax) {\r
-         range = min_semi_end - reg->anchor_dmax;\r
-       }\r
-       if ((OnigDistance )(max_semi_end - start) < reg->anchor_dmin) {\r
-         start = max_semi_end - reg->anchor_dmin;\r
-         start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, start);\r
-       }\r
-       if (range > start) goto mismatch_no_msa;\r
+        if ((OnigLen )(min_semi_end - range) > reg->anchor_dmax) {\r
+          range = min_semi_end - reg->anchor_dmax;\r
+        }\r
+        if ((OnigLen )(max_semi_end - start) < reg->anchor_dmin) {\r
+          start = max_semi_end - reg->anchor_dmin;\r
+          start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, start);\r
+        }\r
+        if (range > start) goto mismatch_no_msa;\r
       }\r
     }\r
     else if (reg->anchor & ANCHOR_SEMI_END_BUF) {\r
@@ -3526,25 +4743,25 @@ onig_search(regex_t* reg, const UChar* str, const UChar* end,
 \r
       max_semi_end = (UChar* )end;\r
       if (ONIGENC_IS_MBC_NEWLINE(reg->enc, pre_end, end)) {\r
-       min_semi_end = pre_end;\r
+        min_semi_end = pre_end;\r
 \r
 #ifdef USE_CRNL_AS_LINE_TERMINATOR\r
-       pre_end = ONIGENC_STEP_BACK(reg->enc, str, pre_end, 1);\r
-       if (IS_NOT_NULL(pre_end) &&\r
-           ONIGENC_IS_MBC_CRNL(reg->enc, pre_end, end)) {\r
-         min_semi_end = pre_end;\r
-       }\r
+        pre_end = ONIGENC_STEP_BACK(reg->enc, str, pre_end, 1);\r
+        if (IS_NOT_NULL(pre_end) &&\r
+            ONIGENC_IS_MBC_CRNL(reg->enc, pre_end, end)) {\r
+          min_semi_end = pre_end;\r
+        }\r
 #endif\r
-       if (min_semi_end > str && start <= min_semi_end) {\r
-         goto end_buf;\r
-       }\r
+        if (min_semi_end > str && start <= min_semi_end) {\r
+          goto end_buf;\r
+        }\r
       }\r
       else {\r
-       min_semi_end = (UChar* )end;\r
-       goto end_buf;\r
+        min_semi_end = (UChar* )end;\r
+        goto end_buf;\r
       }\r
     }\r
-    else if ((reg->anchor & ANCHOR_ANYCHAR_STAR_ML)) {\r
+    else if ((reg->anchor & ANCHOR_ANYCHAR_INF_ML)) {\r
       goto begin_position;\r
     }\r
   }\r
@@ -3560,11 +4777,7 @@ onig_search(regex_t* reg, const UChar* str, const UChar* end,
       s = (UChar* )start;\r
       prev = (UChar* )NULL;\r
 \r
-      MATCH_ARG_INIT(msa, option, region, start);\r
-#ifdef USE_COMBINATION_EXPLOSION_CHECK\r
-      msa.state_check_buff = (void* )0;\r
-      msa.state_check_buff_size = 0;   /* NO NEED, for valgrind */\r
-#endif\r
+      MATCH_ARG_INIT(msa, reg, option, region, start, mp);\r
       MATCH_AND_RETURN_CHECK(end);\r
       goto mismatch;\r
     }\r
@@ -3573,16 +4786,10 @@ onig_search(regex_t* reg, const UChar* str, const UChar* end,
 \r
 #ifdef ONIG_DEBUG_SEARCH\r
   fprintf(stderr, "onig_search(apply anchor): end: %d, start: %d, range: %d\n",\r
-         (int )(end - str), (int )(start - str), (int )(range - str));\r
+          (int )(end - str), (int )(start - str), (int )(range - str));\r
 #endif\r
 \r
-  MATCH_ARG_INIT(msa, option, region, orig_start);\r
-#ifdef USE_COMBINATION_EXPLOSION_CHECK\r
-  {\r
-    int offset = (MIN(start, range) - str);\r
-    STATE_CHECK_BUFF_INIT(msa, end - str, offset, reg->num_comb_exp_check);\r
-  }\r
-#endif\r
+  MATCH_ARG_INIT(msa, reg, option, region, orig_start, mp);\r
 \r
   s = (UChar* )start;\r
   if (range > start) {   /* forward search */\r
@@ -3591,51 +4798,53 @@ onig_search(regex_t* reg, const UChar* str, const UChar* end,
     else\r
       prev = (UChar* )NULL;\r
 \r
-    if (reg->optimize != ONIG_OPTIMIZE_NONE) {\r
+    if (reg->optimize != OPTIMIZE_NONE) {\r
       UChar *sch_range, *low, *high, *low_prev;\r
 \r
       sch_range = (UChar* )range;\r
       if (reg->dmax != 0) {\r
-       if (reg->dmax == ONIG_INFINITE_DISTANCE)\r
-         sch_range = (UChar* )end;\r
-       else {\r
-         sch_range += reg->dmax;\r
-         if (sch_range > end) sch_range = (UChar* )end;\r
-       }\r
+        if (reg->dmax == INFINITE_LEN)\r
+          sch_range = (UChar* )end;\r
+        else {\r
+          sch_range += reg->dmax;\r
+          if (sch_range > end) sch_range = (UChar* )end;\r
+        }\r
       }\r
 \r
       if ((end - start) < reg->threshold_len)\r
         goto mismatch;\r
 \r
-      if (reg->dmax != ONIG_INFINITE_DISTANCE) {\r
-       do {\r
-         if (! forward_search_range(reg, str, end, s, sch_range,\r
-                                    &low, &high, &low_prev)) goto mismatch;\r
-         if (s < low) {\r
-           s    = low;\r
-           prev = low_prev;\r
-         }\r
-         while (s <= high) {\r
-           MATCH_AND_RETURN_CHECK(orig_range);\r
-           prev = s;\r
-           s += enclen(reg->enc, s);\r
-         }\r
-       } while (s < range);\r
-       goto mismatch;\r
+      if (reg->dmax != INFINITE_LEN) {\r
+        do {\r
+          if (! forward_search_range(reg, str, end, s, sch_range,\r
+                                     &low, &high, &low_prev)) goto mismatch;\r
+          if (s < low) {\r
+            s    = low;\r
+            prev = low_prev;\r
+          }\r
+          while (s <= high) {\r
+            MATCH_AND_RETURN_CHECK(orig_range);\r
+            prev = s;\r
+            s += enclen(reg->enc, s);\r
+          }\r
+        } while (s < range);\r
+        goto mismatch;\r
       }\r
       else { /* check only. */\r
-       if (! forward_search_range(reg, str, end, s, sch_range,\r
-                                  &low, &high, (UChar** )NULL)) goto mismatch;\r
+        if (! forward_search_range(reg, str, end, s, sch_range,\r
+                                   &low, &high, (UChar** )NULL)) goto mismatch;\r
 \r
-        if ((reg->anchor & ANCHOR_ANYCHAR_STAR) != 0) {\r
+        if ((reg->anchor & ANCHOR_ANYCHAR_INF) != 0) {\r
           do {\r
             MATCH_AND_RETURN_CHECK(orig_range);\r
             prev = s;\r
             s += enclen(reg->enc, s);\r
 \r
-            while (!ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end) && s < range) {\r
-              prev = s;\r
-              s += enclen(reg->enc, s);\r
+            if ((reg->anchor & (ANCHOR_LOOK_BEHIND | ANCHOR_PREC_READ_NOT)) == 0) {\r
+              while (!ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end) && s < range) {\r
+                prev = s;\r
+                s += enclen(reg->enc, s);\r
+              }\r
             }\r
           } while (s < range);\r
           goto mismatch;\r
@@ -3654,56 +4863,54 @@ onig_search(regex_t* reg, const UChar* str, const UChar* end,
     }\r
   }\r
   else {  /* backward search */\r
-#ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE\r
     if (orig_start < end)\r
       orig_start += enclen(reg->enc, orig_start); /* is upper range */\r
-#endif\r
 \r
-    if (reg->optimize != ONIG_OPTIMIZE_NONE) {\r
+    if (reg->optimize != OPTIMIZE_NONE) {\r
       UChar *low, *high, *adjrange, *sch_start;\r
 \r
       if (range < end)\r
-       adjrange = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, range);\r
+        adjrange = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, range);\r
       else\r
-       adjrange = (UChar* )end;\r
-\r
-      if (reg->dmax != ONIG_INFINITE_DISTANCE &&\r
-         (end - range) >= reg->threshold_len) {\r
-       do {\r
-         sch_start = s + reg->dmax;\r
-         if (sch_start > end) sch_start = (UChar* )end;\r
-         if (backward_search_range(reg, str, end, sch_start, range, adjrange,\r
-                                   &low, &high) <= 0)\r
-           goto mismatch;\r
-\r
-         if (s > high)\r
-           s = high;\r
-\r
-         while (s >= low) {\r
-           prev = onigenc_get_prev_char_head(reg->enc, str, s);\r
-           MATCH_AND_RETURN_CHECK(orig_start);\r
-           s = prev;\r
-         }\r
-       } while (s >= range);\r
-       goto mismatch;\r
+        adjrange = (UChar* )end;\r
+\r
+      if (reg->dmax != INFINITE_LEN &&\r
+          (end - range) >= reg->threshold_len) {\r
+        do {\r
+          sch_start = s + reg->dmax;\r
+          if (sch_start > end) sch_start = (UChar* )end;\r
+          if (backward_search_range(reg, str, end, sch_start, range, adjrange,\r
+                                    &low, &high) <= 0)\r
+            goto mismatch;\r
+\r
+          if (s > high)\r
+            s = high;\r
+\r
+          while (s >= low) {\r
+            prev = onigenc_get_prev_char_head(reg->enc, str, s);\r
+            MATCH_AND_RETURN_CHECK(orig_start);\r
+            s = prev;\r
+          }\r
+        } while (s >= range);\r
+        goto mismatch;\r
       }\r
       else { /* check only. */\r
-       if ((end - range) < reg->threshold_len) goto mismatch;\r
-\r
-       sch_start = s;\r
-       if (reg->dmax != 0) {\r
-         if (reg->dmax == ONIG_INFINITE_DISTANCE)\r
-           sch_start = (UChar* )end;\r
-         else {\r
-           sch_start += reg->dmax;\r
-           if (sch_start > end) sch_start = (UChar* )end;\r
-           else\r
-             sch_start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc,\r
-                                                   start, sch_start);\r
-         }\r
-       }\r
-       if (backward_search_range(reg, str, end, sch_start, range, adjrange,\r
-                                 &low, &high) <= 0) goto mismatch;\r
+        if ((end - range) < reg->threshold_len) goto mismatch;\r
+\r
+        sch_start = s;\r
+        if (reg->dmax != 0) {\r
+          if (reg->dmax == INFINITE_LEN)\r
+            sch_start = (UChar* )end;\r
+          else {\r
+            sch_start += reg->dmax;\r
+            if (sch_start > end) sch_start = (UChar* )end;\r
+            else\r
+              sch_start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc,\r
+                                                        start, sch_start);\r
+          }\r
+        }\r
+        if (backward_search_range(reg, str, end, sch_start, range, adjrange,\r
+                                  &low, &high) <= 0) goto mismatch;\r
       }\r
     }\r
 \r
@@ -3727,10 +4934,9 @@ onig_search(regex_t* reg, const UChar* str, const UChar* end,
 \r
  finish:\r
   MATCH_ARG_FREE(msa);\r
-  ONIG_STATE_DEC_THREAD(reg);\r
 \r
   /* If result is mismatch and no FIND_NOT_EMPTY option,\r
-     then the region is not setted in match_at(). */\r
+     then the region is not set in match_at(). */\r
   if (IS_FIND_NOT_EMPTY(reg->options) && region\r
 #ifdef USE_POSIX_API_REGION_OPTION\r
       && !IS_POSIX_REGION(option)\r
@@ -3748,7 +4954,6 @@ onig_search(regex_t* reg, const UChar* str, const UChar* end,
  mismatch_no_msa:\r
   r = ONIG_MISMATCH;\r
  finish_no_msa:\r
-  ONIG_STATE_DEC_THREAD(reg);\r
 #ifdef ONIG_DEBUG\r
   if (r != ONIG_MISMATCH)\r
     fprintf(stderr, "onig_search: error %d\n", r);\r
@@ -3756,9 +4961,57 @@ onig_search(regex_t* reg, const UChar* str, const UChar* end,
   return r;\r
 \r
  match:\r
-  ONIG_STATE_DEC_THREAD(reg);\r
   MATCH_ARG_FREE(msa);\r
-  return (int)(s - str);\r
+  return (int )(s - str);\r
+}\r
+\r
+extern int\r
+onig_scan(regex_t* reg, const UChar* str, const UChar* end,\r
+          OnigRegion* region, OnigOptionType option,\r
+          int (*scan_callback)(int, int, OnigRegion*, void*),\r
+          void* callback_arg)\r
+{\r
+  int r;\r
+  int n;\r
+  int rs;\r
+  const UChar* start;\r
+\r
+  if (ONIG_IS_OPTION_ON(option, ONIG_OPTION_CHECK_VALIDITY_OF_STRING)) {\r
+    if (! ONIGENC_IS_VALID_MBC_STRING(reg->enc, str, end))\r
+      return ONIGERR_INVALID_WIDE_CHAR_VALUE;\r
+\r
+    ONIG_OPTION_OFF(option, ONIG_OPTION_CHECK_VALIDITY_OF_STRING);\r
+  }\r
+\r
+  n = 0;\r
+  start = str;\r
+  while (1) {\r
+    r = onig_search(reg, str, end, start, end, region, option);\r
+    if (r >= 0) {\r
+      rs = scan_callback(n, r, region, callback_arg);\r
+      n++;\r
+      if (rs != 0)\r
+        return rs;\r
+\r
+      if (region->end[0] == start - str) {\r
+        if (start >= end) break;\r
+        start += enclen(reg->enc, start);\r
+      }\r
+      else\r
+        start = str + region->end[0];\r
+\r
+      if (start > end)\r
+        break;\r
+    }\r
+    else if (r == ONIG_MISMATCH) {\r
+      break;\r
+    }\r
+    else { /* error */\r
+      return r;\r
+    }\r
+  }\r
+\r
+  return n;\r
 }\r
 \r
 extern OnigEncoding\r
@@ -3799,7 +5052,7 @@ onig_number_of_capture_histories(regex_t* reg)
 \r
   n = 0;\r
   for (i = 0; i <= ONIG_MAX_CAPTURE_HISTORY_GROUP; i++) {\r
-    if (BIT_STATUS_AT(reg->capture_history, i) != 0)\r
+    if (MEM_STATUS_AT(reg->capture_history, i) != 0)\r
       n++;\r
   }\r
   return n;\r
@@ -3814,3 +5067,627 @@ onig_copy_encoding(OnigEncoding to, OnigEncoding from)
   *to = *from;\r
 }\r
 \r
+\r
+/* for callout functions */\r
+\r
+#ifdef USE_CALLOUT\r
+\r
+extern OnigCalloutFunc\r
+onig_get_progress_callout(void)\r
+{\r
+  return DefaultProgressCallout;\r
+}\r
+\r
+extern int\r
+onig_set_progress_callout(OnigCalloutFunc f)\r
+{\r
+  DefaultProgressCallout = f;\r
+  return ONIG_NORMAL;\r
+}\r
+\r
+extern OnigCalloutFunc\r
+onig_get_retraction_callout(void)\r
+{\r
+  return DefaultRetractionCallout;\r
+}\r
+\r
+extern int\r
+onig_set_retraction_callout(OnigCalloutFunc f)\r
+{\r
+  DefaultRetractionCallout = f;\r
+  return ONIG_NORMAL;\r
+}\r
+\r
+extern int\r
+onig_get_callout_num_by_callout_args(OnigCalloutArgs* args)\r
+{\r
+  return args->num;\r
+}\r
+\r
+extern OnigCalloutIn\r
+onig_get_callout_in_by_callout_args(OnigCalloutArgs* args)\r
+{\r
+  return args->in;\r
+}\r
+\r
+extern int\r
+onig_get_name_id_by_callout_args(OnigCalloutArgs* args)\r
+{\r
+  return args->name_id;\r
+}\r
+\r
+extern const UChar*\r
+onig_get_contents_by_callout_args(OnigCalloutArgs* args)\r
+{\r
+  int num;\r
+  CalloutListEntry* e;\r
+\r
+  num = args->num;\r
+  e = onig_reg_callout_list_at(args->regex, num);\r
+  if (IS_NULL(e)) return 0;\r
+  if (e->of == ONIG_CALLOUT_OF_CONTENTS) {\r
+    return e->u.content.start;\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+extern const UChar*\r
+onig_get_contents_end_by_callout_args(OnigCalloutArgs* args)\r
+{\r
+  int num;\r
+  CalloutListEntry* e;\r
+\r
+  num = args->num;\r
+  e = onig_reg_callout_list_at(args->regex, num);\r
+  if (IS_NULL(e)) return 0;\r
+  if (e->of == ONIG_CALLOUT_OF_CONTENTS) {\r
+    return e->u.content.end;\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+extern int\r
+onig_get_args_num_by_callout_args(OnigCalloutArgs* args)\r
+{\r
+  int num;\r
+  CalloutListEntry* e;\r
+\r
+  num = args->num;\r
+  e = onig_reg_callout_list_at(args->regex, num);\r
+  if (IS_NULL(e)) return ONIGERR_INVALID_ARGUMENT;\r
+  if (e->of == ONIG_CALLOUT_OF_NAME) {\r
+    return e->u.arg.num;\r
+  }\r
+\r
+  return ONIGERR_INVALID_ARGUMENT;\r
+}\r
+\r
+extern int\r
+onig_get_passed_args_num_by_callout_args(OnigCalloutArgs* args)\r
+{\r
+  int num;\r
+  CalloutListEntry* e;\r
+\r
+  num = args->num;\r
+  e = onig_reg_callout_list_at(args->regex, num);\r
+  if (IS_NULL(e)) return ONIGERR_INVALID_ARGUMENT;\r
+  if (e->of == ONIG_CALLOUT_OF_NAME) {\r
+    return e->u.arg.passed_num;\r
+  }\r
+\r
+  return ONIGERR_INVALID_ARGUMENT;\r
+}\r
+\r
+extern int\r
+onig_get_arg_by_callout_args(OnigCalloutArgs* args, int index,\r
+                             OnigType* type, OnigValue* val)\r
+{\r
+  int num;\r
+  CalloutListEntry* e;\r
+\r
+  num = args->num;\r
+  e = onig_reg_callout_list_at(args->regex, num);\r
+  if (IS_NULL(e)) return ONIGERR_INVALID_ARGUMENT;\r
+  if (e->of == ONIG_CALLOUT_OF_NAME) {\r
+    if (IS_NOT_NULL(type)) *type = e->u.arg.types[index];\r
+    if (IS_NOT_NULL(val))  *val  = e->u.arg.vals[index];\r
+    return ONIG_NORMAL;\r
+  }\r
+\r
+  return ONIGERR_INVALID_ARGUMENT;\r
+}\r
+\r
+extern const UChar*\r
+onig_get_string_by_callout_args(OnigCalloutArgs* args)\r
+{\r
+  return args->string;\r
+}\r
+\r
+extern const UChar*\r
+onig_get_string_end_by_callout_args(OnigCalloutArgs* args)\r
+{\r
+  return args->string_end;\r
+}\r
+\r
+extern const UChar*\r
+onig_get_start_by_callout_args(OnigCalloutArgs* args)\r
+{\r
+  return args->start;\r
+}\r
+\r
+extern const UChar*\r
+onig_get_right_range_by_callout_args(OnigCalloutArgs* args)\r
+{\r
+  return args->right_range;\r
+}\r
+\r
+extern const UChar*\r
+onig_get_current_by_callout_args(OnigCalloutArgs* args)\r
+{\r
+  return args->current;\r
+}\r
+\r
+extern OnigRegex\r
+onig_get_regex_by_callout_args(OnigCalloutArgs* args)\r
+{\r
+  return args->regex;\r
+}\r
+\r
+extern unsigned long\r
+onig_get_retry_counter_by_callout_args(OnigCalloutArgs* args)\r
+{\r
+  return args->retry_in_match_counter;\r
+}\r
+\r
+\r
+extern int\r
+onig_get_capture_range_in_callout(OnigCalloutArgs* a, int mem_num, int* begin, int* end)\r
+{\r
+  OnigRegex    reg;\r
+  const UChar* str;\r
+  StackType*   stk_base;\r
+  int i;\r
+\r
+  i = mem_num;\r
+  reg = a->regex;\r
+  str = a->string;\r
+  stk_base = a->stk_base;\r
+\r
+  if (i > 0) {\r
+    if (a->mem_end_stk[i] != INVALID_STACK_INDEX) {\r
+      if (MEM_STATUS_AT(reg->bt_mem_start, i))\r
+        *begin = (int )(STACK_AT(a->mem_start_stk[i])->u.mem.pstr - str);\r
+      else\r
+        *begin = (int )((UChar* )((void* )a->mem_start_stk[i]) - str);\r
+\r
+      *end = (int )((MEM_STATUS_AT(reg->bt_mem_end, i)\r
+                     ? STACK_AT(a->mem_end_stk[i])->u.mem.pstr\r
+                     : (UChar* )((void* )a->mem_end_stk[i])) - str);\r
+    }\r
+    else {\r
+      *begin = *end = ONIG_REGION_NOTPOS;\r
+    }\r
+  }\r
+  else if (i == 0) {\r
+#if 0\r
+    *begin = a->start   - str;\r
+    *end   = a->current - str;\r
+#else\r
+    return ONIGERR_INVALID_ARGUMENT;\r
+#endif\r
+  }\r
+  else\r
+    return ONIGERR_INVALID_ARGUMENT;\r
+\r
+  return ONIG_NORMAL;\r
+}\r
+\r
+extern int\r
+onig_get_used_stack_size_in_callout(OnigCalloutArgs* a, int* used_num, int* used_bytes)\r
+{\r
+  int n;\r
+\r
+  n = (int )(a->stk - a->stk_base);\r
+\r
+  if (used_num != 0)\r
+    *used_num = n;\r
+\r
+  if (used_bytes != 0)\r
+    *used_bytes = n * sizeof(StackType);\r
+\r
+  return ONIG_NORMAL;\r
+}\r
+\r
+\r
+/* builtin callout functions */\r
+\r
+extern int\r
+onig_builtin_fail(OnigCalloutArgs* args ARG_UNUSED, void* user_data ARG_UNUSED)\r
+{\r
+  return ONIG_CALLOUT_FAIL;\r
+}\r
+\r
+extern int\r
+onig_builtin_mismatch(OnigCalloutArgs* args ARG_UNUSED, void* user_data ARG_UNUSED)\r
+{\r
+  return ONIG_MISMATCH;\r
+}\r
+\r
+#if 0\r
+extern int\r
+onig_builtin_success(OnigCalloutArgs* args ARG_UNUSED, void* user_data ARG_UNUSED)\r
+{\r
+  return ONIG_CALLOUT_SUCCESS;\r
+}\r
+#endif\r
+\r
+extern int\r
+onig_builtin_error(OnigCalloutArgs* args, void* user_data ARG_UNUSED)\r
+{\r
+  int r;\r
+  int n;\r
+  OnigValue val;\r
+\r
+  r = onig_get_arg_by_callout_args(args, 0, 0, &val);\r
+  if (r != ONIG_NORMAL) return r;\r
+\r
+  n = (int )val.l;\r
+  if (n >= 0) {\r
+    n = ONIGERR_INVALID_CALLOUT_BODY;\r
+  }\r
+\r
+  return n;\r
+}\r
+\r
+extern int\r
+onig_builtin_count(OnigCalloutArgs* args, void* user_data)\r
+{\r
+  (void )onig_check_callout_data_and_clear_old_values(args);\r
+\r
+  return onig_builtin_total_count(args, user_data);\r
+}\r
+\r
+extern int\r
+onig_builtin_total_count(OnigCalloutArgs* args, void* user_data ARG_UNUSED)\r
+{\r
+  int r;\r
+  int slot;\r
+  OnigType  type;\r
+  OnigValue val;\r
+  OnigValue aval;\r
+  OnigCodePoint count_type;\r
+\r
+  r = onig_get_arg_by_callout_args(args, 0, &type, &aval);\r
+  if (r != ONIG_NORMAL) return r;\r
+\r
+  count_type = aval.c;\r
+  if (count_type != '>' && count_type != 'X' && count_type != '<')\r
+    return ONIGERR_INVALID_CALLOUT_ARG;\r
+\r
+  r = onig_get_callout_data_by_callout_args_self_dont_clear_old(args, 0,\r
+                                                                &type, &val);\r
+  if (r < ONIG_NORMAL)\r
+    return r;\r
+  else if (r > ONIG_NORMAL) {\r
+    /* type == void: initial state */\r
+    val.l = 0;\r
+  }\r
+\r
+  if (args->in == ONIG_CALLOUT_IN_RETRACTION) {\r
+    slot = 2;\r
+    if (count_type == '<')\r
+      val.l++;\r
+    else if (count_type == 'X')\r
+      val.l--;\r
+  }\r
+  else {\r
+    slot = 1;\r
+    if (count_type != '<')\r
+      val.l++;\r
+  }\r
+\r
+  r = onig_set_callout_data_by_callout_args_self(args, 0, ONIG_TYPE_LONG, &val);\r
+  if (r != ONIG_NORMAL) return r;\r
+\r
+  /* slot 1: in progress counter, slot 2: in retraction counter */\r
+  r = onig_get_callout_data_by_callout_args_self_dont_clear_old(args, slot,\r
+                                                                &type, &val);\r
+  if (r < ONIG_NORMAL)\r
+    return r;\r
+  else if (r > ONIG_NORMAL) {\r
+    val.l = 0;\r
+  }\r
+\r
+  val.l++;\r
+  r = onig_set_callout_data_by_callout_args_self(args, slot, ONIG_TYPE_LONG, &val);\r
+  if (r != ONIG_NORMAL) return r;\r
+\r
+  return ONIG_CALLOUT_SUCCESS;\r
+}\r
+\r
+extern int\r
+onig_builtin_max(OnigCalloutArgs* args, void* user_data ARG_UNUSED)\r
+{\r
+  int r;\r
+  int slot;\r
+  long max_val;\r
+  OnigCodePoint count_type;\r
+  OnigType  type;\r
+  OnigValue val;\r
+  OnigValue aval;\r
+\r
+  (void )onig_check_callout_data_and_clear_old_values(args);\r
+\r
+  slot = 0;\r
+  r = onig_get_callout_data_by_callout_args_self(args, slot, &type, &val);\r
+  if (r < ONIG_NORMAL)\r
+    return r;\r
+  else if (r > ONIG_NORMAL) {\r
+    /* type == void: initial state */\r
+    type  = ONIG_TYPE_LONG;\r
+    val.l = 0;\r
+  }\r
+\r
+  r = onig_get_arg_by_callout_args(args, 0, &type, &aval);\r
+  if (r != ONIG_NORMAL) return r;\r
+  if (type == ONIG_TYPE_TAG) {\r
+    r = onig_get_callout_data_by_callout_args(args, aval.tag, 0, &type, &aval);\r
+    if (r < ONIG_NORMAL) return r;\r
+    else if (r > ONIG_NORMAL)\r
+      max_val = 0L;\r
+    else\r
+      max_val = aval.l;\r
+  }\r
+  else { /* LONG */\r
+    max_val = aval.l;\r
+  }\r
+\r
+  r = onig_get_arg_by_callout_args(args, 1, &type, &aval);\r
+  if (r != ONIG_NORMAL) return r;\r
+\r
+  count_type = aval.c;\r
+  if (count_type != '>' && count_type != 'X' && count_type != '<')\r
+    return ONIGERR_INVALID_CALLOUT_ARG;\r
+\r
+  if (args->in == ONIG_CALLOUT_IN_RETRACTION) {\r
+    if (count_type == '<') {\r
+      if (val.l >= max_val) return ONIG_CALLOUT_FAIL;\r
+      val.l++;\r
+    }\r
+    else if (count_type == 'X')\r
+      val.l--;\r
+  }\r
+  else {\r
+    if (count_type != '<') {\r
+      if (val.l >= max_val) return ONIG_CALLOUT_FAIL;\r
+      val.l++;\r
+    }\r
+  }\r
+\r
+  r = onig_set_callout_data_by_callout_args_self(args, slot, ONIG_TYPE_LONG, &val);\r
+  if (r != ONIG_NORMAL) return r;\r
+\r
+  return ONIG_CALLOUT_SUCCESS;\r
+}\r
+\r
+enum OP_CMP {\r
+  OP_EQ,\r
+  OP_NE,\r
+  OP_LT,\r
+  OP_GT,\r
+  OP_LE,\r
+  OP_GE\r
+};\r
+\r
+extern int\r
+onig_builtin_cmp(OnigCalloutArgs* args, void* user_data ARG_UNUSED)\r
+{\r
+  int r;\r
+  int slot;\r
+  long lv;\r
+  long rv;\r
+  OnigType  type;\r
+  OnigValue val;\r
+  regex_t* reg;\r
+  enum OP_CMP op;\r
+\r
+  reg = args->regex;\r
+\r
+  r = onig_get_arg_by_callout_args(args, 0, &type, &val);\r
+  if (r != ONIG_NORMAL) return r;\r
+\r
+  if (type == ONIG_TYPE_TAG) {\r
+    r = onig_get_callout_data_by_callout_args(args, val.tag, 0, &type, &val);\r
+    if (r < ONIG_NORMAL) return r;\r
+    else if (r > ONIG_NORMAL)\r
+      lv = 0L;\r
+    else\r
+      lv = val.l;\r
+  }\r
+  else { /* ONIG_TYPE_LONG */\r
+    lv = val.l;\r
+  }\r
+\r
+  r = onig_get_arg_by_callout_args(args, 2, &type, &val);\r
+  if (r != ONIG_NORMAL) return r;\r
+\r
+  if (type == ONIG_TYPE_TAG) {\r
+    r = onig_get_callout_data_by_callout_args(args, val.tag, 0, &type, &val);\r
+    if (r < ONIG_NORMAL) return r;\r
+    else if (r > ONIG_NORMAL)\r
+      rv = 0L;\r
+    else\r
+      rv = val.l;\r
+  }\r
+  else { /* ONIG_TYPE_LONG */\r
+    rv = val.l;\r
+  }\r
+\r
+  slot = 0;\r
+  r = onig_get_callout_data_by_callout_args_self(args, slot, &type, &val);\r
+  if (r < ONIG_NORMAL)\r
+    return r;\r
+  else if (r > ONIG_NORMAL) {\r
+    /* type == void: initial state */\r
+    OnigCodePoint c1, c2;\r
+    UChar* p;\r
+\r
+    r = onig_get_arg_by_callout_args(args, 1, &type, &val);\r
+    if (r != ONIG_NORMAL) return r;\r
+\r
+    p = val.s.start;\r
+    c1 = ONIGENC_MBC_TO_CODE(reg->enc, p, val.s.end);\r
+    p += ONIGENC_MBC_ENC_LEN(reg->enc, p);\r
+    if (p < val.s.end) {\r
+      c2 = ONIGENC_MBC_TO_CODE(reg->enc, p, val.s.end);\r
+      p += ONIGENC_MBC_ENC_LEN(reg->enc, p);\r
+      if (p != val.s.end)  return ONIGERR_INVALID_CALLOUT_ARG;\r
+    }\r
+    else\r
+      c2 = 0;\r
+\r
+    switch (c1) {\r
+    case '=':\r
+      if (c2 != '=') return ONIGERR_INVALID_CALLOUT_ARG;\r
+      op = OP_EQ;\r
+      break;\r
+    case '!':\r
+      if (c2 != '=') return ONIGERR_INVALID_CALLOUT_ARG;\r
+      op = OP_NE;\r
+      break;\r
+    case '<':\r
+      if (c2 == '=') op = OP_LE;\r
+      else if (c2 == 0) op = OP_LT;\r
+      else  return ONIGERR_INVALID_CALLOUT_ARG;\r
+      break;\r
+    case '>':\r
+      if (c2 == '=') op = OP_GE;\r
+      else if (c2 == 0) op = OP_GT;\r
+      else  return ONIGERR_INVALID_CALLOUT_ARG;\r
+      break;\r
+    default:\r
+      return ONIGERR_INVALID_CALLOUT_ARG;\r
+      break;\r
+    }\r
+    val.l = (long )op;\r
+    r = onig_set_callout_data_by_callout_args_self(args, slot, ONIG_TYPE_LONG, &val);\r
+    if (r != ONIG_NORMAL) return r;\r
+  }\r
+  else {\r
+    op = (enum OP_CMP )val.l;\r
+  }\r
+\r
+  switch (op) {\r
+  case OP_EQ: r = (lv == rv); break;\r
+  case OP_NE: r = (lv != rv); break;\r
+  case OP_LT: r = (lv <  rv); break;\r
+  case OP_GT: r = (lv >  rv); break;\r
+  case OP_LE: r = (lv <= rv); break;\r
+  case OP_GE: r = (lv >= rv); break;\r
+  }\r
+\r
+  return r == 0 ? ONIG_CALLOUT_FAIL : ONIG_CALLOUT_SUCCESS;\r
+}\r
+\r
+\r
+//#include <stdio.h>\r
+\r
+static FILE* OutFp;\r
+\r
+/* name start with "onig_" for macros. */\r
+static int\r
+onig_builtin_monitor(OnigCalloutArgs* args, void* user_data)\r
+{\r
+  int r;\r
+  int num;\r
+  size_t tag_len;\r
+  const UChar* start;\r
+  const UChar* right;\r
+  const UChar* current;\r
+  const UChar* string;\r
+  const UChar* strend;\r
+  const UChar* tag_start;\r
+  const UChar* tag_end;\r
+  regex_t* reg;\r
+  OnigCalloutIn in;\r
+  OnigType type;\r
+  OnigValue val;\r
+  char buf[20];\r
+  FILE* fp;\r
+\r
+  fp = OutFp;\r
+\r
+  r = onig_get_arg_by_callout_args(args, 0, &type, &val);\r
+  if (r != ONIG_NORMAL) return r;\r
+\r
+  in = onig_get_callout_in_by_callout_args(args);\r
+  if (in == ONIG_CALLOUT_IN_PROGRESS) {\r
+    if (val.c == '<')\r
+      return ONIG_CALLOUT_SUCCESS;\r
+  }\r
+  else {\r
+    if (val.c != 'X' && val.c != '<')\r
+      return ONIG_CALLOUT_SUCCESS;\r
+  }\r
+\r
+  num       = onig_get_callout_num_by_callout_args(args);\r
+  start     = onig_get_start_by_callout_args(args);\r
+  right     = onig_get_right_range_by_callout_args(args);\r
+  current   = onig_get_current_by_callout_args(args);\r
+  string    = onig_get_string_by_callout_args(args);\r
+  strend    = onig_get_string_end_by_callout_args(args);\r
+  reg       = onig_get_regex_by_callout_args(args);\r
+  tag_start = onig_get_callout_tag_start(reg, num);\r
+  tag_end   = onig_get_callout_tag_end(reg, num);\r
+\r
+  if (tag_start == 0)\r
+    sprintf_s(buf, sizeof(buf), "#%d", num);\r
+  else {\r
+    /* CAUTION: tag string is not terminated with NULL. */\r
+    int i;\r
+\r
+    tag_len = tag_end - tag_start;\r
+    if (tag_len >= sizeof(buf)) tag_len = sizeof(buf) - 1;\r
+    for (i = 0; i < tag_len; i++) buf[i] = tag_start[i];\r
+    buf[tag_len] = '\0';\r
+  }\r
+\r
+  fprintf(fp, "ONIG-MONITOR: %-4s %s at: %d [%d - %d] len: %d\n",\r
+          buf,\r
+          in == ONIG_CALLOUT_IN_PROGRESS ? "=>" : "<=",\r
+          (int )(current - string),\r
+          (int )(start   - string),\r
+          (int )(right   - string),\r
+          (int )(strend  - string));\r
+  //fflush(fp);\r
+\r
+  return ONIG_CALLOUT_SUCCESS;\r
+}\r
+\r
+extern int\r
+onig_setup_builtin_monitors_by_ascii_encoded_name(void* fp /* FILE* */)\r
+{\r
+  int id;\r
+  char* name;\r
+  OnigEncoding enc;\r
+  unsigned int ts[4];\r
+  OnigValue opts[4];\r
+\r
+  if (IS_NOT_NULL(fp))\r
+    OutFp = (FILE* )fp;\r
+  else\r
+    OutFp = stdout;\r
+\r
+  enc = ONIG_ENCODING_ASCII;\r
+\r
+  name = "MON";\r
+  ts[0] = ONIG_TYPE_CHAR;\r
+  opts[0].c = '>';\r
+  BC_B_O(name, monitor, 1, ts, 1, opts);\r
+\r
+  return ONIG_NORMAL;\r
+}\r
+\r
+#endif /* USE_CALLOUT */\r