Index: EcnlProtoTool/trunk/onigmo-6.1.3/src/regexec.c
===================================================================
--- EcnlProtoTool/trunk/onigmo-5.15.0/src/regexec.c	(revision 321)
+++ EcnlProtoTool/trunk/onigmo-6.1.3/src/regexec.c	(revision 331)
@@ -4,5 +4,5 @@
 /*-
  * Copyright (c) 2002-2008  K.Kosako  <sndgk393 AT ybb DOT ne DOT jp>
- * Copyright (c) 2011-2014  K.Takata  <kentkt AT csc DOT jp>
+ * Copyright (c) 2011-2016  K.Takata  <kentkt AT csc DOT jp>
  * All rights reserved.
  *
@@ -31,19 +31,37 @@
 #include "regint.h"
 
-#define USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE
-
-#ifndef USE_DIRECT_THREADED_VM
+#ifdef RUBY
+# undef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE
+#else
+# define USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE
+#endif
+
+#ifndef USE_TOKEN_THREADED_VM
 # ifdef __GNUC__
-#   define USE_DIRECT_THREADED_VM 1
+#  define USE_TOKEN_THREADED_VM 1
 # else
-#   define USE_DIRECT_THREADED_VM 0
+#  define USE_TOKEN_THREADED_VM 0
 # endif
 #endif
 
+#ifdef RUBY
+# define ENC_DUMMY_FLAG (1<<24)
+static inline int
+rb_enc_asciicompat(OnigEncoding enc)
+{
+  return ONIGENC_MBC_MINLEN(enc)==1 && !((enc)->ruby_encoding_index & ENC_DUMMY_FLAG);
+}
+# undef ONIGENC_IS_MBC_ASCII_WORD
+# define ONIGENC_IS_MBC_ASCII_WORD(enc,s,end) \
+    (rb_enc_asciicompat(enc) ? (ISALNUM(*s) || *s=='_') : \
+   onigenc_ascii_is_code_ctype( \
+	ONIGENC_MBC_TO_CODE(enc,s,end),ONIGENC_CTYPE_WORD,enc))
+#endif /* RUBY */
+
 #ifdef USE_CRNL_AS_LINE_TERMINATOR
-#define ONIGENC_IS_MBC_CRNL(enc,p,end) \
+# define ONIGENC_IS_MBC_CRNL(enc,p,end) \
   (ONIGENC_MBC_TO_CODE(enc,p,end) == 13 && \
-   ONIGENC_MBC_TO_CODE(enc,(p+enclen(enc,p)),end) == 10)
-#define ONIGENC_IS_MBC_NEWLINE_EX(enc,p,start,end,option,check_prev) \
+   ONIGENC_MBC_TO_CODE(enc,(p+enclen(enc,p,end)),end) == 10)
+# define ONIGENC_IS_MBC_NEWLINE_EX(enc,p,start,end,option,check_prev) \
   is_mbc_newline_ex((enc),(p),(start),(end),(option),(check_prev))
 static int
@@ -54,5 +72,5 @@
     if (ONIGENC_MBC_TO_CODE(enc, p, end) == 0x0a) {
       if (check_prev) {
-	const UChar *prev = onigenc_get_prev_char_head(enc, start, p);
+	const UChar *prev = onigenc_get_prev_char_head(enc, start, p, end);
 	if ((prev != NULL) && ONIGENC_MBC_TO_CODE(enc, prev, end) == 0x0d)
 	  return 0;
@@ -64,5 +82,5 @@
     }
     else {
-      const UChar *pnext = p + enclen(enc, p);
+      const UChar *pnext = p + enclen(enc, p, end);
       if (pnext < end &&
 	  ONIGENC_MBC_TO_CODE(enc, p, end) == 0x0d &&
@@ -79,5 +97,5 @@
 }
 #else /* USE_CRNL_AS_LINE_TERMINATOR */
-#define ONIGENC_IS_MBC_NEWLINE_EX(enc,p,start,end,option,check_prev) \
+# define ONIGENC_IS_MBC_NEWLINE_EX(enc,p,start,end,option,check_prev) \
   ONIGENC_IS_MBC_NEWLINE((enc), (p), (end))
 #endif /* USE_CRNL_AS_LINE_TERMINATOR */
@@ -94,5 +112,5 @@
     for (i = 0; i < node->num_childs; i++) {
       if (IS_NOT_NULL(node->childs[i])) {
-        history_tree_free(node->childs[i]);
+	history_tree_free(node->childs[i]);
       }
     }
@@ -145,5 +163,5 @@
 history_tree_add_child(OnigCaptureTreeNode* parent, OnigCaptureTreeNode* child)
 {
-#define HISTORY_TREE_INIT_ALLOC_SIZE  8
+# define HISTORY_TREE_INIT_ALLOC_SIZE  8
 
   if (parent->num_childs >= parent->allocated) {
@@ -153,5 +171,5 @@
       n = HISTORY_TREE_INIT_ALLOC_SIZE;
       parent->childs =
-        (OnigCaptureTreeNode** )xmalloc(sizeof(OnigCaptureTreeNode*) * n);
+	(OnigCaptureTreeNode** )xmalloc(sizeof(OnigCaptureTreeNode*) * n);
       CHECK_NULL_RETURN_MEMERR(parent->childs);
     }
@@ -160,6 +178,6 @@
       n = parent->allocated * 2;
       tmp =
-        (OnigCaptureTreeNode** )xrealloc(parent->childs,
-                                         sizeof(OnigCaptureTreeNode*) * n);
+	(OnigCaptureTreeNode** )xrealloc(parent->childs,
+					 sizeof(OnigCaptureTreeNode*) * n);
       if (tmp == 0) {
 	history_tree_clear(parent);
@@ -337,5 +355,5 @@
 
 extern void
-onig_region_copy(OnigRegion* to, OnigRegion* from)
+onig_region_copy(OnigRegion* to, const OnigRegion* from)
 {
 #define RREGC_SIZE   (sizeof(int) * from->num_regs)
@@ -386,4 +404,6 @@
 #define STK_RETURN                 0x0900
 #define STK_VOID                   0x0a00  /* for fill a blank */
+#define STK_ABSENT_POS             0x0b00  /* for absent */
+#define STK_ABSENT                 0x0c00  /* absent inner loop marker */
 
 /* stack type check mask */
@@ -393,5 +413,5 @@
 
 #ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE
-#define MATCH_ARG_INIT(msa, arg_option, arg_region, arg_start, arg_gpos) do {\
+# define MATCH_ARG_INIT(msa, arg_option, arg_region, arg_start, arg_gpos) do {\
   (msa).stack_p  = (void* )0;\
   (msa).options  = (arg_option);\
@@ -402,5 +422,5 @@
 } while(0)
 #else
-#define MATCH_ARG_INIT(msa, arg_option, arg_region, arg_start, arg_gpos) do {\
+# define MATCH_ARG_INIT(msa, arg_option, arg_region, arg_start, arg_gpos) do {\
   (msa).stack_p  = (void* )0;\
   (msa).options  = (arg_option);\
@@ -413,7 +433,7 @@
 #ifdef USE_COMBINATION_EXPLOSION_CHECK
 
-#define STATE_CHECK_BUFF_MALLOC_THRESHOLD_SIZE  16
-
-#define STATE_CHECK_BUFF_INIT(msa, str_len, offset, state_num) do {	\
+# define STATE_CHECK_BUFF_MALLOC_THRESHOLD_SIZE  16
+
+# define STATE_CHECK_BUFF_INIT(msa, str_len, offset, state_num) do {	\
   if ((state_num) > 0 && str_len >= STATE_CHECK_STRING_THRESHOLD_LEN) {\
     unsigned int size = (unsigned int )(((str_len) + 1) * (state_num) + 7) >> 3;\
@@ -441,5 +461,5 @@
   } while(0)
 
-#define MATCH_ARG_FREE(msa) do {\
+# define MATCH_ARG_FREE(msa) do {\
   if ((msa).stack_p) xfree((msa).stack_p);\
   if ((msa).state_check_buff_size >= STATE_CHECK_BUFF_MALLOC_THRESHOLD_SIZE) { \
@@ -448,6 +468,5 @@
 } while(0)
 #else /* USE_COMBINATION_EXPLOSION_CHECK */
-#define STATE_CHECK_BUFF_INIT(msa, str_len, offset, state_num)
-#define MATCH_ARG_FREE(msa)  if ((msa).stack_p) xfree((msa).stack_p)
+# define MATCH_ARG_FREE(msa)  if ((msa).stack_p) xfree((msa).stack_p)
 #endif /* USE_COMBINATION_EXPLOSION_CHECK */
 
@@ -466,5 +485,5 @@
       stk_end   = stk_base + msa->stack_n;\
     } else {\
-      stk_alloc = (OnigStackType* )xmalloc(sizeof(OnigStackType) * (stack_num));\
+      stk_alloc = (OnigStackType* )xalloca(sizeof(OnigStackType) * (stack_num));\
       stk_base  = stk_alloc;\
       stk       = stk_base;\
@@ -472,5 +491,5 @@
     }\
   } else if (msa->stack_p) {\
-    alloc_addr = (char* )xmalloc(sizeof(OnigStackIndex) * (ptr_num));\
+    alloc_addr = (char* )xalloca(sizeof(OnigStackIndex) * (ptr_num));\
     heap_addr  = NULL;\
     stk_alloc  = (OnigStackType* )(msa->stack_p);\
@@ -480,5 +499,5 @@
   }\
   else {\
-    alloc_addr = (char* )xmalloc(sizeof(OnigStackIndex) * (ptr_num)\
+    alloc_addr = (char* )xalloca(sizeof(OnigStackIndex) * (ptr_num)\
 		       + sizeof(OnigStackType) * (stack_num));\
     heap_addr  = NULL;\
@@ -538,7 +557,7 @@
     if (limit_size != 0 && n > limit_size) {
       if ((unsigned int )(stk_end - stk_base) == limit_size)
-        return ONIGERR_MATCH_STACK_LIMIT_OVER;
+	return ONIGERR_MATCH_STACK_LIMIT_OVER;
       else
-        n = limit_size;
+	n = limit_size;
     }
     x = (OnigStackType* )xrealloc(stk_base, sizeof(OnigStackType) * n);
@@ -577,7 +596,7 @@
 
 #ifdef USE_COMBINATION_EXPLOSION_CHECK
-#define STATE_CHECK_POS(s,snum) \
+# define STATE_CHECK_POS(s,snum) \
   (((s) - str) * num_comb_exp_check + ((snum) - 1))
-#define STATE_CHECK_VAL(v,snum) do {\
+# define STATE_CHECK_VAL(v,snum) do {\
   if (state_check_buff != NULL) {\
     int x = STATE_CHECK_POS(s,snum);\
@@ -588,5 +607,5 @@
 
 
-#define ELSE_IF_STATE_CHECK_MARK(stk) \
+# define ELSE_IF_STATE_CHECK_MARK(stk) \
   else if ((stk)->type == STK_STATE_CHECK_MARK) { \
     int x = STATE_CHECK_POS(stk->u.state.pstr, stk->u.state.state_check);\
@@ -594,5 +613,5 @@
   }
 
-#define STACK_PUSH(stack_type,pat,s,sprev,keep) do {\
+# define STACK_PUSH(stack_type,pat,s,sprev,keep) do {\
   STACK_ENSURE(1);\
   stk->type = (stack_type);\
@@ -605,5 +624,5 @@
 } while(0)
 
-#define STACK_PUSH_ENSURED(stack_type,pat) do {\
+# define STACK_PUSH_ENSURED(stack_type,pat) do {\
   stk->type = (stack_type);\
   stk->u.state.pcode = (pat);\
@@ -612,5 +631,5 @@
 } while(0)
 
-#define STACK_PUSH_ALT_WITH_STATE_CHECK(pat,s,sprev,snum,keep) do {\
+# define STACK_PUSH_ALT_WITH_STATE_CHECK(pat,s,sprev,snum,keep) do {\
   STACK_ENSURE(1);\
   stk->type = STK_ALT;\
@@ -623,5 +642,5 @@
 } while(0)
 
-#define STACK_PUSH_STATE_CHECK(s,snum) do {\
+# define STACK_PUSH_STATE_CHECK(s,snum) do {\
   if (state_check_buff != NULL) {\
     STACK_ENSURE(1);\
@@ -635,7 +654,7 @@
 #else /* USE_COMBINATION_EXPLOSION_CHECK */
 
-#define ELSE_IF_STATE_CHECK_MARK(stk)
-
-#define STACK_PUSH(stack_type,pat,s,sprev,keep) do {\
+# define ELSE_IF_STATE_CHECK_MARK(stk)
+
+# define STACK_PUSH(stack_type,pat,s,sprev,keep) do {\
   STACK_ENSURE(1);\
   stk->type = (stack_type);\
@@ -647,5 +666,5 @@
 } while(0)
 
-#define STACK_PUSH_ENSURED(stack_type,pat) do {\
+# define STACK_PUSH_ENSURED(stack_type,pat) do {\
   stk->type = (stack_type);\
   stk->u.state.pcode = (pat);\
@@ -657,5 +676,6 @@
 #define STACK_PUSH_POS(s,sprev,keep)         STACK_PUSH(STK_POS,NULL_UCHARP,s,sprev,keep)
 #define STACK_PUSH_POS_NOT(pat,s,sprev,keep) STACK_PUSH(STK_POS_NOT,pat,s,sprev,keep)
-#define STACK_PUSH_STOP_BT              STACK_PUSH_TYPE(STK_STOP_BT)
+#define STACK_PUSH_ABSENT                    STACK_PUSH_TYPE(STK_ABSENT)
+#define STACK_PUSH_STOP_BT                   STACK_PUSH_TYPE(STK_STOP_BT)
 #define STACK_PUSH_LOOK_BEHIND_NOT(pat,s,sprev,keep) \
         STACK_PUSH(STK_LOOK_BEHIND_NOT,pat,s,sprev,keep)
@@ -769,7 +789,15 @@
 } while(0)
 
+#define STACK_PUSH_ABSENT_POS(start, end) do {\
+  STACK_ENSURE(1);\
+  stk->type = STK_ABSENT_POS;\
+  stk->u.absent_pos.abs_pstr = (start);\
+  stk->u.absent_pos.end_pstr = (end);\
+  STACK_INC;\
+} while(0)
+
 
 #ifdef ONIG_DEBUG
-#define STACK_BASE_CHECK(p, at) \
+# define STACK_BASE_CHECK(p, at) \
   if ((p) < stk_base) {\
     fprintf(stderr, "at %s\n", at);\
@@ -777,5 +805,5 @@
   }
 #else
-#define STACK_BASE_CHECK(p, at)
+# define STACK_BASE_CHECK(p, at)
 #endif
 
@@ -867,4 +895,31 @@
     ELSE_IF_STATE_CHECK_MARK(stk);\
   }\
+} while(0)
+
+#define STACK_POP_TIL_ABSENT  do {\
+  while (1) {\
+    stk--;\
+    STACK_BASE_CHECK(stk, "STACK_POP_TIL_ABSENT"); \
+    if (stk->type == STK_ABSENT) break;\
+    else if (stk->type == STK_MEM_START) {\
+      mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\
+      mem_end_stk[stk->u.mem.num]   = stk->u.mem.end;\
+    }\
+    else if (stk->type == STK_REPEAT_INC) {\
+      STACK_AT(stk->u.repeat_inc.si)->u.repeat.count--;\
+    }\
+    else if (stk->type == STK_MEM_END) {\
+      mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\
+      mem_end_stk[stk->u.mem.num]   = stk->u.mem.end;\
+    }\
+    ELSE_IF_STATE_CHECK_MARK(stk);\
+  }\
+} while(0)
+
+#define STACK_POP_ABSENT_POS(start, end) do {\
+  stk--;\
+  STACK_BASE_CHECK(stk, "STACK_POP_ABSENT_POS"); \
+  (start) = stk->u.absent_pos.abs_pstr;\
+  (end) = stk->u.absent_pos.end_pstr;\
 } while(0)
 
@@ -1064,23 +1119,22 @@
 } while(0)
 
-#define STRING_CMP_IC(case_fold_flag,s1,ps2,len) do {\
-  if (string_cmp_ic(encode, case_fold_flag, s1, ps2, len) == 0) \
+#define STRING_CMP_IC(case_fold_flag,s1,ps2,len,text_end) do {\
+  if (string_cmp_ic(encode, case_fold_flag, s1, ps2, len, text_end) == 0) \
     goto fail; \
 } while(0)
 
 static int string_cmp_ic(OnigEncoding enc, int case_fold_flag,
-			 UChar* s1, UChar** ps2, OnigDistance mblen)
+			 UChar* s1, UChar** ps2, OnigDistance mblen, const UChar* text_end)
 {
   UChar buf1[ONIGENC_MBC_CASE_FOLD_MAXLEN];
   UChar buf2[ONIGENC_MBC_CASE_FOLD_MAXLEN];
-  UChar *p1, *p2, *end1, *s2, *end2;
+  UChar *p1, *p2, *end1, *s2;
   int len1, len2;
 
   s2   = *ps2;
   end1 = s1 + mblen;
-  end2 = s2 + mblen;
   while (s1 < end1) {
-    len1 = ONIGENC_MBC_CASE_FOLD(enc, case_fold_flag, &s1, end1, buf1);
-    len2 = ONIGENC_MBC_CASE_FOLD(enc, case_fold_flag, &s2, end2, buf2);
+    len1 = ONIGENC_MBC_CASE_FOLD(enc, case_fold_flag, &s1, text_end, buf1);
+    len2 = ONIGENC_MBC_CASE_FOLD(enc, case_fold_flag, &s2, text_end, buf2);
     if (len1 != len2) return 0;
     p1 = buf1;
@@ -1106,6 +1160,6 @@
 } while(0)
 
-#define STRING_CMP_VALUE_IC(case_fold_flag,s1,ps2,len,is_fail) do {\
-  if (string_cmp_ic(encode, case_fold_flag, s1, ps2, len) == 0) \
+#define STRING_CMP_VALUE_IC(case_fold_flag,s1,ps2,len,text_end,is_fail) do {\
+  if (string_cmp_ic(encode, case_fold_flag, s1, ps2, len, text_end) == 0) \
     is_fail = 1; \
   else \
@@ -1115,14 +1169,16 @@
 
 #define IS_EMPTY_STR           (str == end)
-#define ON_STR_BEGIN(s)       ((s) == str)
-#define ON_STR_END(s)         ((s) == end)
+#define ON_STR_BEGIN(s)        ((s) == str)
+#define ON_STR_END(s)          ((s) == end)
 #ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE
-#define DATA_ENSURE_CHECK1     (s < right_range)
-#define DATA_ENSURE_CHECK(n)   (s + (n) <= right_range)
-#define DATA_ENSURE(n)         if (s + (n) > right_range) goto fail
+# define DATA_ENSURE_CHECK1    (s < right_range)
+# define DATA_ENSURE_CHECK(n)  (s + (n) <= right_range)
+# define DATA_ENSURE(n)        if (s + (n) > right_range) goto fail
+# define ABSENT_END_POS        right_range
 #else
-#define DATA_ENSURE_CHECK1     (s < end)
-#define DATA_ENSURE_CHECK(n)   (s + (n) <= end)
-#define DATA_ENSURE(n)         if (s + (n) > end) goto fail
+# define DATA_ENSURE_CHECK1    (s < end)
+# define DATA_ENSURE_CHECK(n)  (s + (n) <= end)
+# define DATA_ENSURE(n)        if (s + (n) > end) goto fail
+# define ABSENT_END_POS        end
 #endif /* USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE */
 
@@ -1141,27 +1197,27 @@
       n = k->u.mem.num;
       if (n <= ONIG_MAX_CAPTURE_HISTORY_GROUP &&
-          BIT_STATUS_AT(reg->capture_history, n) != 0) {
-        child = history_node_new();
-        CHECK_NULL_RETURN_MEMERR(child);
-        child->group = n;
-        child->beg = k->u.mem.pstr - str;
-        r = history_tree_add_child(node, child);
-        if (r != 0) {
-          history_tree_free(child);
-          return r;
-        }
-        *kp = (k + 1);
-        r = make_capture_history_tree(child, kp, stk_top, str, reg);
-        if (r != 0) return r;
-
-        k = *kp;
-        child->end = k->u.mem.pstr - str;
+	  BIT_STATUS_AT(reg->capture_history, n) != 0) {
+	child = history_node_new();
+	CHECK_NULL_RETURN_MEMERR(child);
+	child->group = n;
+	child->beg = k->u.mem.pstr - str;
+	r = history_tree_add_child(node, child);
+	if (r != 0) {
+	  history_tree_free(child);
+	  return r;
+	}
+	*kp = (k + 1);
+	r = make_capture_history_tree(child, kp, stk_top, str, reg);
+	if (r != 0) return r;
+
+	k = *kp;
+	child->end = k->u.mem.pstr - str;
       }
     }
     else if (k->type == STK_MEM_END) {
       if (k->u.mem.num == node->group) {
-        node->end = k->u.mem.pstr - str;
-        *kp = k;
-        return 0;
+	node->end = k->u.mem.pstr - str;
+	*kp = k;
+	return 0;
       }
     }
@@ -1186,8 +1242,8 @@
 }
 
-static int backref_match_at_nested_level(regex_t* reg
-	 , OnigStackType* top, OnigStackType* stk_base
-	 , int ignore_case, int case_fold_flag
-	 , int nest, int mem_num, UChar* memp, UChar** s, const UChar* send)
+static int backref_match_at_nested_level(regex_t* reg,
+	 OnigStackType* top, OnigStackType* stk_base,
+	 int ignore_case, int case_fold_flag,
+	 int nest, int mem_num, UChar* memp, UChar** s, const UChar* send)
 {
   UChar *ss, *p, *pstart, *pend = NULL_UCHARP;
@@ -1216,5 +1272,5 @@
 	    if (ignore_case != 0) {
 	      if (string_cmp_ic(reg->enc, case_fold_flag,
-				pstart, &ss, pend - pstart) == 0)
+				pstart, &ss, pend - pstart, send) == 0)
 		return 0; /* or goto next_mem; */
 	    }
@@ -1246,25 +1302,35 @@
 #ifdef ONIG_DEBUG_STATISTICS
 
-#define USE_TIMEOFDAY
-
-#ifdef USE_TIMEOFDAY
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
+# ifdef _WIN32
+#  include <windows.h>
+static LARGE_INTEGER ts, te, freq;
+#  define GETTIME(t)	  QueryPerformanceCounter(&(t))
+#  define TIMEDIFF(te,ts) (unsigned long )(((te).QuadPart - (ts).QuadPart) \
+			    * 1000000 / freq.QuadPart)
+# else /* _WIN32 */
+
+#  define USE_TIMEOFDAY
+
+#  ifdef USE_TIMEOFDAY
+#   ifdef HAVE_SYS_TIME_H
+#    include <sys/time.h>
+#   endif
+#   ifdef HAVE_UNISTD_H
+#    include <unistd.h>
+#   endif
 static struct timeval ts, te;
-#define GETTIME(t)        gettimeofday(&(t), (struct timezone* )0)
-#define TIMEDIFF(te,ts)   (((te).tv_usec - (ts).tv_usec) + \
-                           (((te).tv_sec - (ts).tv_sec)*1000000))
-#else /* USE_TIMEOFDAY */
-#ifdef HAVE_SYS_TIMES_H
-#include <sys/times.h>
-#endif
+#   define GETTIME(t)      gettimeofday(&(t), (struct timezone* )0)
+#   define TIMEDIFF(te,ts) (((te).tv_usec - (ts).tv_usec) + \
+                            (((te).tv_sec - (ts).tv_sec)*1000000))
+#  else /* USE_TIMEOFDAY */
+#   ifdef HAVE_SYS_TIMES_H
+#    include <sys/times.h>
+#   endif
 static struct tms ts, te;
-#define GETTIME(t)         times(&(t))
-#define TIMEDIFF(te,ts)   ((te).tms_utime - (ts).tms_utime)
-#endif /* USE_TIMEOFDAY */
+#   define GETTIME(t)       times(&(t))
+#   define TIMEDIFF(te,ts)  ((te).tms_utime - (ts).tms_utime)
+#  endif /* USE_TIMEOFDAY */
+
+# endif /* _WIN32 */
 
 static int OpCounter[256];
@@ -1275,5 +1341,5 @@
 static int MaxStackDepth = 0;
 
-#define MOP_IN(opcode) do {\
+# define MOP_IN(opcode) do {\
   if (opcode == OpPrevTarget) OpPrevCounter[OpCurr]++;\
   OpCurr = opcode;\
@@ -1282,5 +1348,5 @@
 } while(0)
 
-#define MOP_OUT do {\
+# define MOP_OUT do {\
   GETTIME(te);\
   OpTime[OpCurr] += TIMEDIFF(te, ts);\
@@ -1295,4 +1361,7 @@
   }
   MaxStackDepth = 0;
+# ifdef _WIN32
+  QueryPerformanceFrequency(&freq);
+# endif
 }
 
@@ -1309,5 +1378,5 @@
 }
 
-#define STACK_INC do {\
+# define STACK_INC do {\
   stk++;\
   if (stk - stk_base > MaxStackDepth) \
@@ -1316,28 +1385,47 @@
 
 #else /* ONIG_DEBUG_STATISTICS */
-#define STACK_INC     stk++
-
-#define MOP_IN(opcode)
-#define MOP_OUT
+# define STACK_INC     stk++
+
+# define MOP_IN(opcode)
+# define MOP_OUT
 #endif /* ONIG_DEBUG_STATISTICS */
 
 
-
-/* matching region of POSIX API */
-typedef int regoff_t;
-
-typedef struct {
-  regoff_t  rm_so;
-  regoff_t  rm_eo;
-} posix_regmatch_t;
+#ifdef ONIG_DEBUG_MATCH
+static char *
+stack_type_str(int stack_type)
+{
+  switch (stack_type) {
+    case STK_ALT:		return "Alt   ";
+    case STK_LOOK_BEHIND_NOT:	return "LBNot ";
+    case STK_POS_NOT:		return "PosNot";
+    case STK_MEM_START:		return "MemS  ";
+    case STK_MEM_END:		return "MemE  ";
+    case STK_REPEAT_INC:	return "RepInc";
+    case STK_STATE_CHECK_MARK:	return "StChMk";
+    case STK_NULL_CHECK_START:	return "NulChS";
+    case STK_NULL_CHECK_END:	return "NulChE";
+    case STK_MEM_END_MARK:	return "MemEMk";
+    case STK_POS:		return "Pos   ";
+    case STK_STOP_BT:		return "StopBt";
+    case STK_REPEAT:		return "Rep   ";
+    case STK_CALL_FRAME:	return "Call  ";
+    case STK_RETURN:		return "Ret   ";
+    case STK_VOID:		return "Void  ";
+    case STK_ABSENT_POS:	return "AbsPos";
+    case STK_ABSENT:		return "Absent";
+    default:			return "      ";
+  }
+}
+#endif
 
 /* match data(str - end) from position (sstart). */
 /* if sstart == str then set sprev to NULL. */
 static OnigPosition
-match_at_(regex_t* reg, const UChar* str, const UChar* end,
+match_at(regex_t* reg, const UChar* str, const UChar* end,
 #ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE
 	 const UChar* right_range,
 #endif
-	 const UChar* sstart, UChar* sprev, OnigMatchArg* msa, char **palloca_base)
+	 const UChar* sstart, UChar* sprev, OnigMatchArg* msa)
 {
   static const UChar FinishCode[] = { OP_FINISH };
@@ -1354,4 +1442,5 @@
   UChar *p = reg->p;
   UChar *pkeep;
+  char *alloca_base;
   char *xmalloc_base = NULL;
   OnigStackType *stk_alloc, *stk_base, *stk, *stk_end;
@@ -1366,11 +1455,12 @@
 #endif
 
-#if USE_DIRECT_THREADED_VM
-#define VM_LOOP JUMP;
-#define VM_LOOP_END
-#define CASE(x) L_##x: sbegin = s; OPCODE_EXEC_HOOK;
-#define DEFAULT L_DEFAULT:
-#define NEXT sprev = sbegin; JUMP
-#define JUMP goto *oplabels[*p++]
+#if USE_TOKEN_THREADED_VM
+# define OP_OFFSET  1
+# define VM_LOOP JUMP;
+# define VM_LOOP_END
+# define CASE(x) L_##x: sbegin = s; OPCODE_EXEC_HOOK;
+# define DEFAULT L_DEFAULT:
+# define NEXT sprev = sbegin; JUMP
+# define JUMP goto *oplabels[*p++]
 
   static const void *oplabels[] = {
@@ -1400,5 +1490,4 @@
     &&L_OP_CCLASS_MB_NOT,
     &&L_OP_CCLASS_MIX_NOT,
-    &&L_OP_CCLASS_NODE,          /* pointer to CClassNode node */
 
     &&L_OP_ANYCHAR,                 /* "."  */
@@ -1413,22 +1502,22 @@
     &&L_OP_WORD_BOUND,
     &&L_OP_NOT_WORD_BOUND,
-#ifdef USE_WORD_BEGIN_END
+# ifdef USE_WORD_BEGIN_END
     &&L_OP_WORD_BEGIN,
     &&L_OP_WORD_END,
-#else
+# else
     &&L_DEFAULT,
     &&L_DEFAULT,
-#endif
+# endif
     &&L_OP_ASCII_WORD,
     &&L_OP_NOT_ASCII_WORD,
     &&L_OP_ASCII_WORD_BOUND,
     &&L_OP_NOT_ASCII_WORD_BOUND,
-#ifdef USE_WORD_BEGIN_END
+# ifdef USE_WORD_BEGIN_END
     &&L_OP_ASCII_WORD_BEGIN,
     &&L_OP_ASCII_WORD_END,
-#else
+# else
     &&L_DEFAULT,
     &&L_DEFAULT,
-#endif
+# endif
 
     &&L_OP_BEGIN_BUF,
@@ -1438,5 +1527,4 @@
     &&L_OP_SEMI_END_BUF,
     &&L_OP_BEGIN_POSITION,
-    &&L_OP_BEGIN_POS_OR_LINE,    /* used for implicit anchor optimization */
 
     &&L_OP_BACKREF1,
@@ -1446,23 +1534,23 @@
     &&L_OP_BACKREF_MULTI,
     &&L_OP_BACKREF_MULTI_IC,
-#ifdef USE_BACKREF_WITH_LEVEL
+# ifdef USE_BACKREF_WITH_LEVEL
     &&L_OP_BACKREF_WITH_LEVEL,   /* \k<xxx+n>, \k<xxx-n> */
-#else
+# else
     &&L_DEFAULT,
-#endif
+# endif
     &&L_OP_MEMORY_START,
     &&L_OP_MEMORY_START_PUSH,    /* push back-tracker to stack */
     &&L_OP_MEMORY_END_PUSH,      /* push back-tracker to stack */
-#ifdef USE_SUBEXP_CALL
+# ifdef USE_SUBEXP_CALL
     &&L_OP_MEMORY_END_PUSH_REC,  /* push back-tracker to stack */
-#else
+# else
     &&L_DEFAULT,
-#endif
+# endif
     &&L_OP_MEMORY_END,
-#ifdef USE_SUBEXP_CALL
+# ifdef USE_SUBEXP_CALL
     &&L_OP_MEMORY_END_REC,       /* push marker to stack */
-#else
+# else
     &&L_DEFAULT,
-#endif
+# endif
 
     &&L_OP_KEEP,
@@ -1472,5 +1560,9 @@
     &&L_OP_PUSH,
     &&L_OP_POP,
+# ifdef USE_OP_PUSH_OR_JUMP_EXACT
     &&L_OP_PUSH_OR_JUMP_EXACT1,  /* if match exact then push, else jump. */
+# else
+    &&L_DEFAULT,
+# endif
     &&L_OP_PUSH_IF_PEEK_NEXT,    /* if match exact then push, else none. */
     &&L_OP_REPEAT,               /* {n,m} */
@@ -1482,14 +1574,14 @@
     &&L_OP_NULL_CHECK_START,     /* null loop checker start */
     &&L_OP_NULL_CHECK_END,       /* null loop checker end   */
-#ifdef USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT
+# ifdef USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT
     &&L_OP_NULL_CHECK_END_MEMST, /* null loop checker end (with capture status) */
-#else
+# else
     &&L_DEFAULT,
-#endif
-#ifdef USE_SUBEXP_CALL
+# endif
+# ifdef USE_SUBEXP_CALL
     &&L_OP_NULL_CHECK_END_MEMST_PUSH, /* with capture status and push check-end */
-#else
+# else
     &&L_DEFAULT,
-#endif
+# endif
 
     &&L_OP_PUSH_POS,             /* (?=...)  start */
@@ -1502,94 +1594,96 @@
     &&L_OP_PUSH_LOOK_BEHIND_NOT, /* (?<!...) start */
     &&L_OP_FAIL_LOOK_BEHIND_NOT, /* (?<!...) end   */
-
-#ifdef USE_SUBEXP_CALL
+    &&L_OP_PUSH_ABSENT_POS,      /* (?~...)  start */
+    &&L_OP_ABSENT,               /* (?~...)  start of inner loop */
+    &&L_OP_ABSENT_END,           /* (?~...)  end   */
+
+# ifdef USE_SUBEXP_CALL
     &&L_OP_CALL,                 /* \g<name> */
     &&L_OP_RETURN,
-#else
+# else
     &&L_DEFAULT,
     &&L_DEFAULT,
-#endif
+# endif
     &&L_OP_CONDITION,
 
-#ifdef USE_COMBINATION_EXPLOSION_CHECK
+# ifdef USE_COMBINATION_EXPLOSION_CHECK
     &&L_OP_STATE_CHECK_PUSH,         /* combination explosion check and push */
     &&L_OP_STATE_CHECK_PUSH_OR_JUMP, /* check ok -> push, else jump  */
     &&L_OP_STATE_CHECK,              /* check only */
-#else
+# else
     &&L_DEFAULT,
     &&L_DEFAULT,
     &&L_DEFAULT,
-#endif
-#ifdef USE_COMBINATION_EXPLOSION_CHECK
+# endif
+# ifdef USE_COMBINATION_EXPLOSION_CHECK
     &&L_OP_STATE_CHECK_ANYCHAR_STAR,
     &&L_OP_STATE_CHECK_ANYCHAR_ML_STAR,
-#else
+# else
     &&L_DEFAULT,
     &&L_DEFAULT,
-#endif
+# endif
     /* no need: IS_DYNAMIC_OPTION() == 0 */
-#if 0   /* no need: IS_DYNAMIC_OPTION() == 0 */
+# if 0   /* no need: IS_DYNAMIC_OPTION() == 0 */
     &&L_OP_SET_OPTION_PUSH,    /* set option and push recover option */
     &&L_OP_SET_OPTION          /* set option */
-#else
+# else
     &&L_DEFAULT,
     &&L_DEFAULT
-#endif
+# endif
   };
-#else
-
-#define VM_LOOP                                 \
+#else /* USE_TOKEN_THREADED_VM */
+
+# define OP_OFFSET  0
+# define VM_LOOP                                \
   while (1) {                                   \
   OPCODE_EXEC_HOOK;                             \
   sbegin = s;                                   \
   switch (*p++) {
-#define VM_LOOP_END } sprev = sbegin; }
-#define CASE(x) case x:
-#define DEFAULT default:
-#define NEXT break
-#define JUMP continue; break
-#endif
+# define VM_LOOP_END } sprev = sbegin; }
+# define CASE(x) case x:
+# define DEFAULT default:
+# define NEXT break
+# define JUMP continue; break
+#endif /* USE_TOKEN_THREADED_VM */
 
 
 #ifdef USE_SUBEXP_CALL
-  /* Stack #0 is used to store the pattern itself and used for (?R), \g<0>, etc. */
-  n = reg->num_repeat + (reg->num_mem + 1) * 2;
-
-  STACK_INIT(*palloca_base, xmalloc_base, n, INIT_MATCH_STACK_SIZE);
+/* Stack #0 is used to store the pattern itself and used for (?R), \g<0>,
+   etc. Additional space is required. */
+# define ADD_NUMMEM 1
+#else
+/* Stack #0 not is used. */
+# define ADD_NUMMEM 0
+#endif
+
+  n = reg->num_repeat + (reg->num_mem + ADD_NUMMEM) * 2;
+
+  STACK_INIT(alloca_base, xmalloc_base, n, INIT_MATCH_STACK_SIZE);
   pop_level = reg->stack_pop_level;
   num_mem = reg->num_mem;
-  repeat_stk = (OnigStackIndex* )*palloca_base;
+  repeat_stk = (OnigStackIndex* )alloca_base;
 
   mem_start_stk = (OnigStackIndex* )(repeat_stk + reg->num_repeat);
-  mem_end_stk   = mem_start_stk + (num_mem + 1);
-#else /* USE_SUBEXP_CALL */
-  /* Stack #0 not is used. */
-  n = reg->num_repeat + reg->num_mem * 2;
-
-  STACK_INIT(*palloca_base, xmalloc_base, n, INIT_MATCH_STACK_SIZE);
-  pop_level = reg->stack_pop_level;
-  num_mem = reg->num_mem;
-  repeat_stk = (OnigStackIndex* )*palloca_base;
-
-  mem_start_stk = (OnigStackIndex* )(repeat_stk + reg->num_repeat);
-  mem_end_stk   = mem_start_stk + num_mem;
+  mem_end_stk   = mem_start_stk + (num_mem + ADD_NUMMEM);
+  {
+    OnigStackIndex *pp = mem_start_stk;
+    for (; pp < repeat_stk + n; pp += 2) {
+      pp[0] = INVALID_STACK_INDEX;
+      pp[1] = INVALID_STACK_INDEX;
+    }
+  }
+#ifndef USE_SUBEXP_CALL
   mem_start_stk--; /* for index start from 1,
 		      mem_start_stk[1]..mem_start_stk[num_mem] */
   mem_end_stk--;   /* for index start from 1,
 		      mem_end_stk[1]..mem_end_stk[num_mem] */
-#endif /* USE_SUBEXP_CALL */
-  {
-      OnigStackIndex *pp = mem_start_stk;
-      for (; pp < (repeat_stk + n); pp+=2) {
-	  pp[0] = INVALID_STACK_INDEX;
-	  pp[1] = INVALID_STACK_INDEX;
-      }
-  }
+#endif
 
 #ifdef ONIG_DEBUG_MATCH
-  fprintf(stderr, "match_at: str: %"PRIdPTR" (%p), end: %"PRIdPTR" (%p), start: %"PRIdPTR" (%p), sprev: %"PRIdPTR" (%p)\n",
-	  (intptr_t )str, str, (intptr_t )end, end, (intptr_t )sstart, sstart, (intptr_t )sprev, sprev);
+  fprintf(stderr, "match_at: str: %"PRIuPTR" (%p), end: %"PRIuPTR" (%p), start: %"PRIuPTR" (%p), sprev: %"PRIuPTR" (%p)\n",
+	  (uintptr_t )str, str, (uintptr_t )end, end, (uintptr_t )sstart, sstart, (uintptr_t )sprev, sprev);
   fprintf(stderr, "size: %d, start offset: %d\n",
 	  (int )(end - str), (int )(sstart - str));
+  fprintf(stderr, "\n ofs> str                   stk:type   addr:opcode\n");
 #endif
 
@@ -1601,9 +1695,9 @@
 
 #ifdef ONIG_DEBUG_MATCH
-#define OPCODE_EXEC_HOOK                                                \
+# define OPCODE_EXEC_HOOK                                               \
     if (s) {                                                            \
       UChar *op, *q, *bp, buf[50];                                      \
       int len;                                                          \
-      op = p - 1;                                                       \
+      op = p - OP_OFFSET;                                               \
       fprintf(stderr, "%4"PRIdPTR"> \"", (*op == OP_FINISH) ? (ptrdiff_t )-1 : s - str); \
       bp = buf;                                                         \
@@ -1611,19 +1705,22 @@
       if (*op != OP_FINISH) {    /* s may not be a valid pointer if OP_FINISH. */ \
 	for (i = 0; i < 7 && q < end; i++) {                            \
-	  len = enclen(encode, q);                                      \
+	  len = enclen(encode, q, end);                                 \
 	  while (len-- > 0) *bp++ = *q++;                               \
 	}                                                               \
+        if (q < end) { xmemcpy(bp, "...", 3); bp += 3; }                \
       }                                                                 \
-      if (q < end) { xmemcpy(bp, "...\"", 4); bp += 4; }                \
-      else         { xmemcpy(bp, "\"",    1); bp += 1; }                \
+      xmemcpy(bp, "\"", 1); bp += 1;                                    \
       *bp = 0;                                                          \
       fputs((char* )buf, stderr);                                       \
       for (i = 0; i < 20 - (bp - buf); i++) fputc(' ', stderr);         \
-      fprintf(stderr, "%4"PRIdPTR":", (op == FinishCode) ? (ptrdiff_t )-1 : op - reg->p); \
-      onig_print_compiled_byte_code(stderr, op, NULL, encode);           \
+      fprintf(stderr, "%4"PRIdPTR":%s %4"PRIdPTR":",                    \
+	  stk - stk_base - 1,                                           \
+	  (stk > stk_base) ? stack_type_str(stk[-1].type) : "      ",   \
+	  (op == FinishCode) ? (ptrdiff_t )-1 : op - reg->p);           \
+      onig_print_compiled_byte_code(stderr, op, reg->p+reg->used, NULL, encode); \
       fprintf(stderr, "\n");                                            \
     }
 #else
-#define OPCODE_EXEC_HOOK ((void) 0)
+# define OPCODE_EXEC_HOOK ((void) 0)
 #endif
 
@@ -1642,81 +1739,54 @@
 	  else
 	    goto end_best_len;
-        }
+	}
 #endif
 	best_len = n;
 	region = msa->region;
 	if (region) {
-#ifdef USE_POSIX_API_REGION_OPTION
-	  if (IS_POSIX_REGION(msa->options)) {
-	    posix_regmatch_t* rmt = (posix_regmatch_t* )region;
-
-	    rmt[0].rm_so = (regoff_t )(((pkeep > s) ? s : pkeep) - str);
-	    rmt[0].rm_eo = (regoff_t )(s - str);
-	    for (i = 1; i <= num_mem; i++) {
-	      if (mem_end_stk[i] != INVALID_STACK_INDEX) {
-		if (BIT_STATUS_AT(reg->bt_mem_start, i))
-		  rmt[i].rm_so = (regoff_t )(STACK_AT(mem_start_stk[i])->u.mem.pstr - str);
-		else
-		  rmt[i].rm_so = (regoff_t )((UChar* )((void* )(mem_start_stk[i])) - str);
-
-		rmt[i].rm_eo = (regoff_t )((BIT_STATUS_AT(reg->bt_mem_end, i)
+	  region->beg[0] = ((pkeep > s) ? s : pkeep) - str;
+	  region->end[0] = s - str;
+	  for (i = 1; i <= num_mem; i++) {
+	    if (mem_end_stk[i] != INVALID_STACK_INDEX) {
+	      if (BIT_STATUS_AT(reg->bt_mem_start, i))
+		region->beg[i] = STACK_AT(mem_start_stk[i])->u.mem.pstr - str;
+	      else
+		region->beg[i] = (UChar* )((void* )mem_start_stk[i]) - str;
+
+	      region->end[i] = (BIT_STATUS_AT(reg->bt_mem_end, i)
 				? STACK_AT(mem_end_stk[i])->u.mem.pstr
-				: (UChar* )((void* )mem_end_stk[i])) - str);
-	      }
-	      else {
-		rmt[i].rm_so = rmt[i].rm_eo = ONIG_REGION_NOTPOS;
-	      }
+				: (UChar* )((void* )mem_end_stk[i])) - str;
+	    }
+	    else {
+	      region->beg[i] = region->end[i] = ONIG_REGION_NOTPOS;
 	    }
 	  }
-	  else {
-#endif /* USE_POSIX_API_REGION_OPTION */
-	    region->beg[0] = ((pkeep > s) ? s : pkeep) - str;
-	    region->end[0] = s - str;
-	    for (i = 1; i <= num_mem; i++) {
-	      if (mem_end_stk[i] != INVALID_STACK_INDEX) {
-		if (BIT_STATUS_AT(reg->bt_mem_start, i))
-		  region->beg[i] = STACK_AT(mem_start_stk[i])->u.mem.pstr - str;
-		else
-		  region->beg[i] = (UChar* )((void* )mem_start_stk[i]) - str;
-
-		region->end[i] = (BIT_STATUS_AT(reg->bt_mem_end, i)
-				  ? STACK_AT(mem_end_stk[i])->u.mem.pstr
-				  : (UChar* )((void* )mem_end_stk[i])) - str;
-	      }
-	      else {
-		region->beg[i] = region->end[i] = ONIG_REGION_NOTPOS;
-	      }
+
+#ifdef USE_CAPTURE_HISTORY
+	  if (reg->capture_history != 0) {
+	    int r;
+	    OnigCaptureTreeNode* node;
+
+	    if (IS_NULL(region->history_root)) {
+	      region->history_root = node = history_node_new();
+	      CHECK_NULL_RETURN_MEMERR(node);
 	    }
-
-#ifdef USE_CAPTURE_HISTORY
-	    if (reg->capture_history != 0) {
-              int r;
-              OnigCaptureTreeNode* node;
-
-              if (IS_NULL(region->history_root)) {
-                region->history_root = node = history_node_new();
-                CHECK_NULL_RETURN_MEMERR(node);
-              }
-              else {
-                node = region->history_root;
-                history_tree_clear(node);
-              }
-
-              node->group = 0;
-              node->beg   = ((pkeep > s) ? s : pkeep) - str;
-              node->end   = s - str;
-
-              stkp = stk_base;
-              r = make_capture_history_tree(region->history_root, &stkp,
-                                            stk, (UChar* )str, reg);
-              if (r < 0) {
-                best_len = r; /* error code */
-                goto finish;
-              }
+	    else {
+	      node = region->history_root;
+	      history_tree_clear(node);
 	    }
+
+	    node->group = 0;
+	    node->beg   = ((pkeep > s) ? s : pkeep) - str;
+	    node->end   = s - str;
+
+	    stkp = stk_base;
+	    r = make_capture_history_tree(region->history_root, &stkp,
+		stk, (UChar* )str, reg);
+	    if (r < 0) {
+	      best_len = r; /* error code */
+	      goto finish;
+	    }
+	  }
 #endif /* USE_CAPTURE_HISTORY */
-#ifdef USE_POSIX_API_REGION_OPTION
-	  } /* else IS_POSIX_REGION() */
-#endif
 	} /* if (region) */
       } /* n > best_len */
@@ -1742,12 +1812,7 @@
 
     CASE(OP_EXACT1)  MOP_IN(OP_EXACT1);
-#if 0
       DATA_ENSURE(1);
       if (*p != *s) goto fail;
       p++; s++;
-#endif
-      if (*p != *s++) goto fail;
-      DATA_ENSURE(0);
-      p++;
       MOP_OUT;
       NEXT;
@@ -1767,6 +1832,6 @@
 	while (len-- > 0) {
 	  if (*p != *q) {
-            goto fail;
-          }
+	    goto fail;
+	  }
 	  p++; q++;
 	}
@@ -1950,10 +2015,10 @@
       if (BITSET_AT(((BitSetRef )p), *s) == 0) goto fail;
       p += SIZE_BITSET;
-      s += enclen(encode, s);   /* OP_CCLASS can match mb-code. \D, \S */
+      s += enclen(encode, s, end);   /* OP_CCLASS can match mb-code. \D, \S */
       MOP_OUT;
       NEXT;
 
     CASE(OP_CCLASS_MB)  MOP_IN(OP_CCLASS_MB);
-      if (! ONIGENC_IS_MBC_HEAD(encode, s)) goto fail;
+      if (! ONIGENC_IS_MBC_HEAD(encode, s, end)) goto fail;
 
     cclass_mb:
@@ -1965,5 +2030,5 @@
 
 	DATA_ENSURE(1);
-	mb_len = enclen(encode, s);
+	mb_len = enclen(encode, s, end);
 	DATA_ENSURE(mb_len);
 	ss = s;
@@ -1985,5 +2050,5 @@
     CASE(OP_CCLASS_MIX)  MOP_IN(OP_CCLASS_MIX);
       DATA_ENSURE(1);
-      if (ONIGENC_IS_MBC_HEAD(encode, s)) {
+      if (ONIGENC_IS_MBC_HEAD(encode, s, end)) {
 	p += SIZE_BITSET;
 	goto cclass_mb;
@@ -2005,5 +2070,5 @@
       if (BITSET_AT(((BitSetRef )p), *s) != 0) goto fail;
       p += SIZE_BITSET;
-      s += enclen(encode, s);
+      s += enclen(encode, s, end);
       MOP_OUT;
       NEXT;
@@ -2011,5 +2076,5 @@
     CASE(OP_CCLASS_MB_NOT)  MOP_IN(OP_CCLASS_MB_NOT);
       DATA_ENSURE(1);
-      if (! ONIGENC_IS_MBC_HEAD(encode, s)) {
+      if (! ONIGENC_IS_MBC_HEAD(encode, s, end)) {
 	s++;
 	GET_LENGTH_INC(tlen, p);
@@ -2023,8 +2088,8 @@
 	OnigCodePoint code;
 	UChar *ss;
-	int mb_len = enclen(encode, s);
+	int mb_len = enclen(encode, s, end);
 
 	if (! DATA_ENSURE_CHECK(mb_len)) {
-          DATA_ENSURE(1);
+	  DATA_ENSURE(1);
 	  s = (UChar* )end;
 	  p += tlen;
@@ -2052,5 +2117,5 @@
     CASE(OP_CCLASS_MIX_NOT)  MOP_IN(OP_CCLASS_MIX_NOT);
       DATA_ENSURE(1);
-      if (ONIGENC_IS_MBC_HEAD(encode, s)) {
+      if (ONIGENC_IS_MBC_HEAD(encode, s, end)) {
 	p += SIZE_BITSET;
 	goto cclass_mb_not;
@@ -2068,26 +2133,7 @@
       NEXT;
 
-    CASE(OP_CCLASS_NODE)  MOP_IN(OP_CCLASS_NODE);
-      {
-	OnigCodePoint code;
-        void *node;
-        int mb_len;
-        UChar *ss;
-
-        DATA_ENSURE(1);
-        GET_POINTER_INC(node, p);
-	mb_len = enclen(encode, s);
-	ss = s;
-	s += mb_len;
-	DATA_ENSURE(0);
-	code = ONIGENC_MBC_TO_CODE(encode, ss, s);
-	if (onig_is_code_in_cc_len(mb_len, code, node) == 0) goto fail;
-      }
-      MOP_OUT;
-      NEXT;
-
     CASE(OP_ANYCHAR)  MOP_IN(OP_ANYCHAR);
       DATA_ENSURE(1);
-      n = enclen(encode, s);
+      n = enclen(encode, s, end);
       DATA_ENSURE(n);
       if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0)) goto fail;
@@ -2098,5 +2144,5 @@
     CASE(OP_ANYCHAR_ML)  MOP_IN(OP_ANYCHAR_ML);
       DATA_ENSURE(1);
-      n = enclen(encode, s);
+      n = enclen(encode, s, end);
       DATA_ENSURE(n);
       s += n;
@@ -2107,17 +2153,17 @@
       while (DATA_ENSURE_CHECK1) {
 	STACK_PUSH_ALT(p, s, sprev, pkeep);
-	n = enclen(encode, s);
-        DATA_ENSURE(n);
-        if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0))  goto fail;
-        sprev = s;
-        s += n;
-      }
-      MOP_OUT;
-      NEXT;
+	n = enclen(encode, s, end);
+	DATA_ENSURE(n);
+	if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0))  goto fail;
+	sprev = s;
+	s += n;
+      }
+      MOP_OUT;
+      JUMP;
 
     CASE(OP_ANYCHAR_ML_STAR)  MOP_IN(OP_ANYCHAR_ML_STAR);
       while (DATA_ENSURE_CHECK1) {
 	STACK_PUSH_ALT(p, s, sprev, pkeep);
-	n = enclen(encode, s);
+	n = enclen(encode, s, end);
 	if (n > 1) {
 	  DATA_ENSURE(n);
@@ -2131,5 +2177,5 @@
       }
       MOP_OUT;
-      NEXT;
+      JUMP;
 
     CASE(OP_ANYCHAR_STAR_PEEK_NEXT)  MOP_IN(OP_ANYCHAR_STAR_PEEK_NEXT);
@@ -2138,9 +2184,9 @@
 	  STACK_PUSH_ALT(p + 1, s, sprev, pkeep);
 	}
-	n = enclen(encode, s);
-        DATA_ENSURE(n);
-        if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0))  goto fail;
-        sprev = s;
-        s += n;
+	n = enclen(encode, s, end);
+	DATA_ENSURE(n);
+	if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0))  goto fail;
+	sprev = s;
+	s += n;
       }
       p++;
@@ -2153,5 +2199,5 @@
 	  STACK_PUSH_ALT(p + 1, s, sprev, pkeep);
 	}
-	n = enclen(encode, s);
+	n = enclen(encode, s, end);
 	if (n > 1) {
 	  DATA_ENSURE(n);
@@ -2176,9 +2222,9 @@
 
 	STACK_PUSH_ALT_WITH_STATE_CHECK(p, s, sprev, mem, pkeep);
-	n = enclen(encode, s);
-        DATA_ENSURE(n);
-        if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0))  goto fail;
-        sprev = s;
-        s += n;
+	n = enclen(encode, s, end);
+	DATA_ENSURE(n);
+	if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0))  goto fail;
+	sprev = s;
+	s += n;
       }
       MOP_OUT;
@@ -2194,5 +2240,5 @@
 
 	STACK_PUSH_ALT_WITH_STATE_CHECK(p, s, sprev, mem, pkeep);
-	n = enclen(encode, s);
+	n = enclen(encode, s, end);
 	if (n > 1) {
 	  DATA_ENSURE(n);
@@ -2214,5 +2260,5 @@
 	goto fail;
 
-      s += enclen(encode, s);
+      s += enclen(encode, s, end);
       MOP_OUT;
       NEXT;
@@ -2223,5 +2269,5 @@
 	goto fail;
 
-      s += enclen(encode, s);
+      s += enclen(encode, s, end);
       MOP_OUT;
       NEXT;
@@ -2232,5 +2278,5 @@
 	goto fail;
 
-      s += enclen(encode, s);
+      s += enclen(encode, s, end);
       MOP_OUT;
       NEXT;
@@ -2241,5 +2287,5 @@
 	goto fail;
 
-      s += enclen(encode, s);
+      s += enclen(encode, s, end);
       MOP_OUT;
       NEXT;
@@ -2372,5 +2418,4 @@
 
     CASE(OP_BEGIN_LINE)  MOP_IN(OP_BEGIN_LINE);
-    op_begin_line:
       if (ON_STR_BEGIN(s)) {
 	if (IS_NOTBOL(msa->options)) goto fail;
@@ -2422,5 +2467,5 @@
       }
       else if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 1)) {
-	UChar* ss = s + enclen(encode, s);
+	UChar* ss = s + enclen(encode, s, end);
 	if (ON_STR_END(ss)) {
 	  MOP_OUT;
@@ -2430,5 +2475,5 @@
 	else if (IS_NEWLINE_CRLF(option)
 	    && ONIGENC_IS_MBC_CRNL(encode, s, end)) {
-	  ss += enclen(encode, ss);
+	  ss += enclen(encode, ss, end);
 	  if (ON_STR_END(ss)) {
 	    MOP_OUT;
@@ -2444,11 +2489,4 @@
       if (s != msa->gpos)
 	goto fail;
-
-      MOP_OUT;
-      JUMP;
-
-    CASE(OP_BEGIN_POS_OR_LINE)  MOP_IN(OP_BEGIN_POS_OR_LINE);
-      if (s != msa->gpos)
-	goto op_begin_line;
 
       MOP_OUT;
@@ -2543,5 +2581,5 @@
 	sprev = s;
 	STRING_CMP(pstart, s, n);
-	while (sprev + (len = enclen(encode, sprev)) < s)
+	while (sprev + (len = enclen(encode, sprev, end)) < s)
 	  sprev += len;
 
@@ -2573,6 +2611,6 @@
 	DATA_ENSURE(n);
 	sprev = s;
-	STRING_CMP_IC(case_fold_flag, pstart, &s, n);
-	while (sprev + (len = enclen(encode, sprev)) < s)
+	STRING_CMP_IC(case_fold_flag, pstart, &s, (int)n, end);
+	while (sprev + (len = enclen(encode, sprev, end)) < s)
 	  sprev += len;
 
@@ -2609,5 +2647,5 @@
 	  if (is_fail) continue;
 	  s = swork;
-	  while (sprev + (len = enclen(encode, sprev)) < s)
+	  while (sprev + (len = enclen(encode, sprev, end)) < s)
 	    sprev += len;
 
@@ -2645,8 +2683,8 @@
 	  sprev = s;
 	  swork = s;
-	  STRING_CMP_VALUE_IC(case_fold_flag, pstart, &swork, n, is_fail);
+	  STRING_CMP_VALUE_IC(case_fold_flag, pstart, &swork, n, end, is_fail);
 	  if (is_fail) continue;
 	  s = swork;
-	  while (sprev + (len = enclen(encode, sprev)) < s)
+	  while (sprev + (len = enclen(encode, sprev, end)) < s)
 	    sprev += len;
 
@@ -2671,7 +2709,7 @@
 
 	sprev = s;
-	if (backref_match_at_nested_level(reg, stk, stk_base, ic
-		  , case_fold_flag, (int )level, (int )tlen, p, &s, end)) {
-	  while (sprev + (len = enclen(encode, sprev)) < s)
+	if (backref_match_at_nested_level(reg, stk, stk_base, ic,
+		  case_fold_flag, (int )level, (int )tlen, p, &s, end)) {
+	  while (sprev + (len = enclen(encode, sprev, end)) < s)
 	    sprev += len;
 
@@ -2715,6 +2753,6 @@
 	if (isnull) {
 #ifdef ONIG_DEBUG_MATCH
-	  fprintf(stderr, "NULL_CHECK_END: skip  id:%d, s:%"PRIdPTR" (%p)\n",
-		  (int )mem, (intptr_t )s, s);
+	  fprintf(stderr, "NULL_CHECK_END: skip  id:%d, s:%"PRIuPTR" (%p)\n",
+		  (int )mem, (uintptr_t )s, s);
 #endif
 	null_check_found:
@@ -2748,8 +2786,8 @@
 	STACK_NULL_CHECK_MEMST(isnull, mem, s, reg);
 	if (isnull) {
-#ifdef ONIG_DEBUG_MATCH
-	  fprintf(stderr, "NULL_CHECK_END_MEMST: skip  id:%d, s:%"PRIdPTR" (%p)\n",
-		  (int )mem, (intptr_t )s, s);
-#endif
+# ifdef ONIG_DEBUG_MATCH
+	  fprintf(stderr, "NULL_CHECK_END_MEMST: skip  id:%d, s:%"PRIuPTR" (%p)\n",
+		  (int )mem, (uintptr_t )s, s);
+# endif
 	  if (isnull == -1) goto fail;
 	  goto null_check_found;
@@ -2767,14 +2805,14 @@
 
 	GET_MEMNUM_INC(mem, p); /* mem: null check id */
-#ifdef USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT
+# ifdef USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT
 	STACK_NULL_CHECK_MEMST_REC(isnull, mem, s, reg);
-#else
+# else
 	STACK_NULL_CHECK_REC(isnull, mem, s);
-#endif
+# endif
 	if (isnull) {
-#ifdef ONIG_DEBUG_MATCH
-	  fprintf(stderr, "NULL_CHECK_END_MEMST_PUSH: skip  id:%d, s:%"PRIdPTR" (%p)\n",
-		  (int )mem, (intptr_t )s, s);
-#endif
+# ifdef ONIG_DEBUG_MATCH
+	  fprintf(stderr, "NULL_CHECK_END_MEMST_PUSH: skip  id:%d, s:%"PRIuPTR" (%p)\n",
+		  (int )mem, (uintptr_t )s, s);
+# endif
 	  if (isnull == -1) goto fail;
 	  goto null_check_found;
@@ -2840,4 +2878,5 @@
       JUMP;
 
+#ifdef USE_OP_PUSH_OR_JUMP_EXACT
     CASE(OP_PUSH_OR_JUMP_EXACT1)  MOP_IN(OP_PUSH_OR_JUMP_EXACT1);
       GET_RELADDR_INC(addr, p);
@@ -2851,4 +2890,5 @@
       MOP_OUT;
       JUMP;
+#endif
 
     CASE(OP_PUSH_IF_PEEK_NEXT)  MOP_IN(OP_PUSH_IF_PEEK_NEXT);
@@ -2905,12 +2945,12 @@
       stkp->u.repeat.count++;
       if (stkp->u.repeat.count >= reg->repeat_range[mem].upper) {
-        /* end of repeat. Nothing to do. */
+	/* end of repeat. Nothing to do. */
       }
       else if (stkp->u.repeat.count >= reg->repeat_range[mem].lower) {
-        STACK_PUSH_ALT(p, s, sprev, pkeep);
-        p = STACK_AT(si)->u.repeat.pcode; /* Don't use stkp after PUSH. */
+	STACK_PUSH_ALT(p, s, sprev, pkeep);
+	p = STACK_AT(si)->u.repeat.pcode; /* Don't use stkp after PUSH. */
       }
       else {
-        p = stkp->u.repeat.pcode;
+	p = stkp->u.repeat.pcode;
       }
       STACK_PUSH_REPEAT_INC(si);
@@ -2934,17 +2974,17 @@
       stkp->u.repeat.count++;
       if (stkp->u.repeat.count < reg->repeat_range[mem].upper) {
-        if (stkp->u.repeat.count >= reg->repeat_range[mem].lower) {
-          UChar* pcode = stkp->u.repeat.pcode;
-
-          STACK_PUSH_REPEAT_INC(si);
-          STACK_PUSH_ALT(pcode, s, sprev, pkeep);
-        }
-        else {
-          p = stkp->u.repeat.pcode;
-          STACK_PUSH_REPEAT_INC(si);
-        }
+	if (stkp->u.repeat.count >= reg->repeat_range[mem].lower) {
+	  UChar* pcode = stkp->u.repeat.pcode;
+
+	  STACK_PUSH_REPEAT_INC(si);
+	  STACK_PUSH_ALT(pcode, s, sprev, pkeep);
+	}
+	else {
+	  p = stkp->u.repeat.pcode;
+	  STACK_PUSH_REPEAT_INC(si);
+	}
       }
       else if (stkp->u.repeat.count == reg->repeat_range[mem].upper) {
-        STACK_PUSH_REPEAT_INC(si);
+	STACK_PUSH_REPEAT_INC(si);
       }
       MOP_OUT;
@@ -2996,7 +3036,7 @@
     CASE(OP_LOOK_BEHIND)  MOP_IN(OP_LOOK_BEHIND);
       GET_LENGTH_INC(tlen, p);
-      s = (UChar* )ONIGENC_STEP_BACK(encode, str, s, (int )tlen);
+      s = (UChar* )ONIGENC_STEP_BACK(encode, str, s, end, (int )tlen);
       if (IS_NULL(s)) goto fail;
-      sprev = (UChar* )onigenc_get_prev_char_head(encode, str, s);
+      sprev = (UChar* )onigenc_get_prev_char_head(encode, str, s, end);
       MOP_OUT;
       JUMP;
@@ -3005,5 +3045,5 @@
       GET_RELADDR_INC(addr, p);
       GET_LENGTH_INC(tlen, p);
-      q = (UChar* )ONIGENC_STEP_BACK(encode, str, s, (int )tlen);
+      q = (UChar* )ONIGENC_STEP_BACK(encode, str, s, end, (int )tlen);
       if (IS_NULL(q)) {
 	/* too short case -> success. ex. /(?<!XXX)a/.match("a")
@@ -3015,5 +3055,5 @@
 	STACK_PUSH_LOOK_BEHIND_NOT(p + addr, s, sprev, pkeep);
 	s = q;
-	sprev = (UChar* )onigenc_get_prev_char_head(encode, str, s);
+	sprev = (UChar* )onigenc_get_prev_char_head(encode, str, s, end);
       }
       MOP_OUT;
@@ -3022,4 +3062,61 @@
     CASE(OP_FAIL_LOOK_BEHIND_NOT)  MOP_IN(OP_FAIL_LOOK_BEHIND_NOT);
       STACK_POP_TIL_LOOK_BEHIND_NOT;
+      goto fail;
+      NEXT;
+
+    CASE(OP_PUSH_ABSENT_POS)  MOP_IN(OP_PUSH_ABSENT_POS);
+      /* Save the absent-start-pos and the original end-pos. */
+      STACK_PUSH_ABSENT_POS(s, ABSENT_END_POS);
+      MOP_OUT;
+      JUMP;
+
+    CASE(OP_ABSENT)  MOP_IN(OP_ABSENT);
+      {
+	const UChar* aend = ABSENT_END_POS;
+	UChar* absent;
+	UChar* selfp = p - 1;
+
+	STACK_POP_ABSENT_POS(absent, ABSENT_END_POS);  /* Restore end-pos. */
+	GET_RELADDR_INC(addr, p);
+#ifdef ONIG_DEBUG_MATCH
+	fprintf(stderr, "ABSENT: s:%p, end:%p, absent:%p, aend:%p\n", s, end, absent, aend);
+#endif
+	if ((absent > aend) && (s > absent)) {
+	  /* An empty match occurred in (?~...) at the start point.
+	   * Never match. */
+	  STACK_POP;
+	  goto fail;
+	}
+	else if ((s >= aend) && (s > absent)) {
+	  if (s > aend) {
+	    /* Only one (or less) character matched in the last iteration.
+	     * This is not a possible point. */
+	    goto fail;
+	  }
+	  /* All possible points were found. Try matching after (?~...). */
+	  DATA_ENSURE(0);
+	  p += addr;
+	}
+	else {
+	  STACK_PUSH_ALT(p + addr, s, sprev, pkeep); /* Push possible point. */
+	  n = enclen(encode, s, end);
+	  STACK_PUSH_ABSENT_POS(absent, ABSENT_END_POS); /* Save the original pos. */
+	  STACK_PUSH_ALT(selfp, s + n, s, pkeep); /* Next iteration. */
+	  STACK_PUSH_ABSENT;
+	  ABSENT_END_POS = aend;
+	}
+      }
+      MOP_OUT;
+      JUMP;
+
+    CASE(OP_ABSENT_END)  MOP_IN(OP_ABSENT_END);
+      /* The pattern inside (?~...) was matched.
+       * Set the end-pos temporary and go to next iteration. */
+      if (sprev < ABSENT_END_POS)
+	ABSENT_END_POS = sprev;
+#ifdef ONIG_DEBUG_MATCH
+      fprintf(stderr, "ABSENT_END: end:%p\n", ABSENT_END_POS);
+#endif
+      STACK_POP_TIL_ABSENT;
       goto fail;
       NEXT;
@@ -3057,7 +3154,7 @@
     CASE(OP_FAIL)
       if (0) {
-        /* fall */
+	/* fall */
       fail:
-        MOP_OUT;
+	MOP_OUT;
       }
       MOP_IN(OP_FAIL);
@@ -3070,6 +3167,6 @@
 #ifdef USE_COMBINATION_EXPLOSION_CHECK
       if (stk->u.state.state_check != 0) {
-        stk->type = STK_STATE_CHECK_MARK;
-        stk++;
+	stk->type = STK_STATE_CHECK_MARK;
+	stk++;
       }
 #endif
@@ -3105,20 +3202,4 @@
 }
 
-static OnigPosition
-match_at(regex_t* reg, const UChar* str, const UChar* end,
-#ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE
-	const UChar* right_range,
-#endif
-	const UChar* sstart, UChar* sprev, OnigMatchArg* msa)
-{
-	char *alloca_base = NULL;
-	OnigPosition ret = match_at_(reg, str, end,
-#ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE
-		right_range,
-#endif
-		sstart, sprev, msa, &alloca_base);
-	if(alloca_base) xfree(alloca_base);
-	return ret;
-}
 
 static UChar*
@@ -3156,5 +3237,5 @@
 	return s;
     }
-    s += enclen(enc, s);
+    s += enclen(enc, s, text_end);
   }
 
@@ -3164,5 +3245,5 @@
 static int
 str_lower_case_match(OnigEncoding enc, int case_fold_flag,
-                     const UChar* t, const UChar* tend,
+		     const UChar* t, const UChar* tend,
 		     const UChar* p, const UChar* end)
 {
@@ -3201,5 +3282,5 @@
       return s;
 
-    s += enclen(enc, s);
+    s += enclen(enc, s, text_end);
   }
 
@@ -3219,5 +3300,5 @@
     s = (UChar* )text_start;
   else
-    s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, adjust_text, s);
+    s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, adjust_text, s, text_end);
 
   while (s >= text) {
@@ -3233,5 +3314,5 @@
 	return s;
     }
-    s = (UChar* )onigenc_get_prev_char_head(enc, adjust_text, s);
+    s = (UChar* )onigenc_get_prev_char_head(enc, adjust_text, s, text_end);
   }
 
@@ -3252,12 +3333,12 @@
     s = (UChar* )text_start;
   else
-    s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, adjust_text, s);
+    s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, adjust_text, s, text_end);
 
   while (s >= text) {
     if (str_lower_case_match(enc, case_fold_flag,
-                             target, target_end, s, text_end))
+			     target, target_end, s, text_end))
       return s;
 
-    s = (UChar* )onigenc_get_prev_char_head(enc, adjust_text, s);
+    s = (UChar* )onigenc_get_prev_char_head(enc, adjust_text, s, text_end);
   }
 
@@ -3276,8 +3357,8 @@
   ptrdiff_t skip, tlen1;
 
-#ifdef ONIG_DEBUG_SEARCH
+# ifdef ONIG_DEBUG_SEARCH
   fprintf(stderr, "bm_search_notrev: text: %"PRIuPTR" (%p), text_end: %"PRIuPTR" (%p), text_range: %"PRIuPTR" (%p)\n",
-	  text, text, text_end, text_end, text_range, text_range);
-#endif
+	  (uintptr_t )text, text, (uintptr_t )text_end, text_end, (uintptr_t )text_range, text_range);
+# endif
 
   tail = target_end - 1;
@@ -3300,9 +3381,10 @@
       t = s;
       do {
-        s += enclen(reg->enc, s);
+	s += enclen(reg->enc, s, end);
       } while ((s - t) < skip && s < end);
     }
   }
   else {
+# if OPT_EXACT_MAXLEN >= ONIG_CHAR_TABLE_SIZE
     while (s < end) {
       p = se = s + tlen1;
@@ -3315,7 +3397,8 @@
       t = s;
       do {
-        s += enclen(reg->enc, s);
+	s += enclen(reg->enc, s, end);
       } while ((s - t) < skip && s < end);
     }
+# endif
   }
 
@@ -3331,8 +3414,8 @@
   const UChar *tail;
 
-#ifdef ONIG_DEBUG_SEARCH
-  fprintf(stderr, "bm_search: text: %"PRIuPTR", text_end: %"PRIuPTR", text_range: %"PRIuPTR"\n",
-	  text, text_end, text_range);
-#endif
+# ifdef ONIG_DEBUG_SEARCH
+  fprintf(stderr, "bm_search: text: %"PRIuPTR" (%p), text_end: %"PRIuPTR" (%p), text_range: %"PRIuPTR" (%p)\n",
+	  (uintptr_t )text, text, (uintptr_t )text_end, text_end, (uintptr_t )text_range, text_range);
+# endif
 
   end = text_range + (target_end - target) - 1;
@@ -3346,8 +3429,8 @@
       p = s;
       t = tail;
-#ifdef ONIG_DEBUG_SEARCH
+# ifdef ONIG_DEBUG_SEARCH
       fprintf(stderr, "bm_search_loop: pos: %"PRIdPTR" %s\n",
 	  (intptr_t )(s - text), s);
-#endif
+# endif
       while (*p == *t) {
 	if (t == target) return (UChar* )p;
@@ -3358,4 +3441,5 @@
   }
   else { /* see int_map[] */
+# if OPT_EXACT_MAXLEN >= ONIG_CHAR_TABLE_SIZE
     while (s < end) {
       p = s;
@@ -3367,4 +3451,5 @@
       s += reg->int_map[*s];
     }
+# endif
   }
   return (UChar* )NULL;
@@ -3383,8 +3468,8 @@
   int case_fold_flag = reg->case_fold_flag;
 
-#ifdef ONIG_DEBUG_SEARCH
+# ifdef ONIG_DEBUG_SEARCH
   fprintf(stderr, "bm_search_notrev_ic: text: %d (%p), text_end: %d (%p), text_range: %d (%p)\n",
 	  (int )text, text, (int )text_end, text_end, (int )text_range, text_range);
-#endif
+# endif
 
   tail = target_end - 1;
@@ -3405,9 +3490,10 @@
       t = s;
       do {
-        s += enclen(reg->enc, s);
+	s += enclen(reg->enc, s, end);
       } while ((s - t) < skip && s < end);
     }
   }
   else {
+# if OPT_EXACT_MAXLEN >= ONIG_CHAR_TABLE_SIZE
     while (s < end) {
       se = s + tlen1;
@@ -3418,7 +3504,8 @@
       t = s;
       do {
-        s += enclen(reg->enc, s);
+	s += enclen(reg->enc, s, end);
       } while ((s - t) < skip && s < end);
     }
+# endif
   }
 
@@ -3436,8 +3523,8 @@
   int case_fold_flag = reg->case_fold_flag;
 
-#ifdef ONIG_DEBUG_SEARCH
+# ifdef ONIG_DEBUG_SEARCH
   fprintf(stderr, "bm_search_ic: text: %d (%p), text_end: %d (%p), text_range: %d (%p)\n",
 	  (int )text, text, (int )text_end, text_end, (int )text_range, text_range);
-#endif
+# endif
 
   end = text_range + (target_end - target) - 1;
@@ -3457,4 +3544,5 @@
   }
   else { /* see int_map[] */
+# if OPT_EXACT_MAXLEN >= ONIG_CHAR_TABLE_SIZE
     while (s < end) {
       p = s - (target_end - target) + 1;
@@ -3464,4 +3552,5 @@
       s += reg->int_map[*s];
     }
+# endif
   }
   return (UChar* )NULL;
@@ -3480,10 +3569,9 @@
   ptrdiff_t skip, tlen1;
   OnigEncoding enc = reg->enc;
-  int (*mbc_enc_len)(const OnigUChar* p) = enc->mbc_enc_len;
-
-#ifdef ONIG_DEBUG_SEARCH
-  fprintf(stderr, "bm_search_notrev: text: %"PRIdPTR" (%p), text_end: %"PRIdPTR" (%p), text_range: %"PRIdPTR" (%p)\n",
-	  (intptr_t )text, text, (intptr_t )text_end, text_end, (intptr_t )text_range, text_range);
-#endif
+
+# ifdef ONIG_DEBUG_SEARCH
+  fprintf(stderr, "bm_search_notrev: text: %"PRIuPTR" (%p), text_end: %"PRIuPTR" (%p), text_range: %"PRIuPTR" (%p)\n",
+	  (uintptr_t )text, text, (uintptr_t )text_end, text_end, (uintptr_t )text_range, text_range);
+# endif
 
   tail = target_end - 1;
@@ -3507,9 +3595,10 @@
       t = s;
       do {
-        s += mbc_enc_len(s);
+	s += enclen(enc, s, end);
       } while ((s - t) < skip && s < end);
     }
   }
   else {
+# if OPT_EXACT_MAXLEN >= ONIG_CHAR_TABLE_SIZE
     while (s < end) {
       p = se = s + tlen1;
@@ -3523,7 +3612,8 @@
       t = s;
       do {
-        s += mbc_enc_len(s);
+	s += enclen(enc, s, end);
       } while ((s - t) < skip && s < end);
     }
+# endif
   }
 
@@ -3539,4 +3629,9 @@
   const UChar *tail;
   ptrdiff_t tlen1;
+
+# ifdef ONIG_DEBUG_SEARCH
+  fprintf(stderr, "bm_search: text: %"PRIuPTR" (%p), text_end: %"PRIuPTR" (%p), text_range: %"PRIuPTR" (%p)\n",
+	  (uintptr_t )text, text, (uintptr_t )text_end, text_end, (uintptr_t )text_range, text_range);
+# endif
 
   tail = target_end - 1;
@@ -3560,4 +3655,5 @@
   }
   else { /* see int_map[] */
+# if OPT_EXACT_MAXLEN >= ONIG_CHAR_TABLE_SIZE
     while (s < end) {
       p = s;
@@ -3570,4 +3666,5 @@
       s += reg->int_map[s[1]];
     }
+# endif
   }
   return (UChar* )NULL;
@@ -3584,11 +3681,10 @@
   ptrdiff_t skip, tlen1;
   OnigEncoding enc = reg->enc;
-  int (*mbc_enc_len)(const OnigUChar* p) = enc->mbc_enc_len;
   int case_fold_flag = reg->case_fold_flag;
 
-#ifdef ONIG_DEBUG_SEARCH
-  fprintf(stderr, "bm_search_notrev_ic: text: %"PRIdPTR" (%p), text_end: %"PRIdPTR" (%p), text_range: %"PRIdPTR" (%p)\n",
-	  (intptr_t )text, text, (intptr_t )text_end, text_end, (intptr_t )text_range, text_range);
-#endif
+# ifdef ONIG_DEBUG_SEARCH
+  fprintf(stderr, "bm_search_notrev_ic: text: %"PRIuPTR" (%p), text_end: %"PRIuPTR" (%p), text_range: %"PRIuPTR" (%p)\n",
+	  (uintptr_t )text, text, (uintptr_t )text_end, text_end, (uintptr_t )text_range, text_range);
+# endif
 
   tail = target_end - 1;
@@ -3610,9 +3706,10 @@
       t = s;
       do {
-        s += mbc_enc_len(s);
+	s += enclen(enc, s, end);
       } while ((s - t) < skip && s < end);
     }
   }
   else {
+# if OPT_EXACT_MAXLEN >= ONIG_CHAR_TABLE_SIZE
     while (s < end) {
       se = s + tlen1;
@@ -3624,7 +3721,8 @@
       t = s;
       do {
-        s += mbc_enc_len(s);
+	s += enclen(enc, s, end);
       } while ((s - t) < skip && s < end);
     }
+# endif
   }
 
@@ -3643,8 +3741,8 @@
   int case_fold_flag = reg->case_fold_flag;
 
-#ifdef ONIG_DEBUG_SEARCH
-  fprintf(stderr, "bm_search_ic: text: %"PRIdPTR" (%p), text_end: %"PRIdPTR" (%p), text_range: %"PRIdPTR" (%p)\n",
-	  (intptr_t )text, text, (intptr_t )text_end, text_end, (intptr_t )text_range, text_range);
-#endif
+# ifdef ONIG_DEBUG_SEARCH
+  fprintf(stderr, "bm_search_ic: text: %"PRIuPTR" (%p), text_end: %"PRIuPTR" (%p), text_range: %"PRIuPTR" (%p)\n",
+	  (uintptr_t )text, text, (uintptr_t )text_end, text_end, (uintptr_t )text_range, text_range);
+# endif
 
   tail = target_end - 1;
@@ -3666,4 +3764,5 @@
   }
   else { /* see int_map[] */
+# if OPT_EXACT_MAXLEN >= ONIG_CHAR_TABLE_SIZE
     while (s < end) {
       p = s - tlen1;
@@ -3674,4 +3773,5 @@
       s += reg->int_map[s[1]];
     }
+# endif
   }
   return (UChar* )NULL;
@@ -3679,4 +3779,5 @@
 #endif /* USE_SUNDAY_QUICK_SEARCH */
 
+#ifdef USE_INT_MAP_BACKWARD
 static int
 set_bm_backward_skip(UChar* s, UChar* end, OnigEncoding enc ARG_UNUSED,
@@ -3711,5 +3812,5 @@
     s = text_start;
   else
-    s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, adjust_text, s);
+    s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, adjust_text, s, text_end);
 
   while (s >= text) {
@@ -3723,13 +3824,14 @@
 
     s -= reg->int_map_backward[*s];
-    s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, adjust_text, s);
+    s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, adjust_text, s, text_end);
   }
 
   return (UChar* )NULL;
 }
+#endif
 
 static UChar*
 map_search(OnigEncoding enc, UChar map[],
-	   const UChar* text, const UChar* text_range)
+	   const UChar* text, const UChar* text_range, const UChar* text_end)
 {
   const UChar *s = text;
@@ -3738,5 +3840,5 @@
     if (map[*s]) return (UChar* )s;
 
-    s += enclen(enc, s);
+    s += enclen(enc, s, text_end);
   }
   return (UChar* )NULL;
@@ -3746,5 +3848,5 @@
 map_search_backward(OnigEncoding enc, UChar map[],
 		    const UChar* text, const UChar* adjust_text,
-		    const UChar* text_start)
+		    const UChar* text_start, const UChar* text_end)
 {
   const UChar *s = text_start;
@@ -3753,5 +3855,5 @@
     if (map[*s]) return (UChar* )s;
 
-    s = onigenc_get_prev_char_head(enc, adjust_text, s);
+    s = onigenc_get_prev_char_head(enc, adjust_text, s, text_end);
   }
   return (UChar* )NULL;
@@ -3765,29 +3867,4 @@
   UChar *prev;
   OnigMatchArg msa;
-
-#if defined(USE_RECOMPILE_API) && defined(USE_MULTI_THREAD_SYSTEM)
- start:
-  THREAD_ATOMIC_START;
-  if (ONIG_STATE(reg) >= ONIG_STATE_NORMAL) {
-    ONIG_STATE_INC(reg);
-    if (IS_NOT_NULL(reg->chain) && ONIG_STATE(reg) == ONIG_STATE_NORMAL) {
-      onig_chain_reduce(reg);
-      ONIG_STATE_INC(reg);
-    }
-  }
-  else {
-    int n;
-
-    THREAD_ATOMIC_END;
-    n = 0;
-    while (ONIG_STATE(reg) < ONIG_STATE_NORMAL) {
-      if (++n > THREAD_PASS_LIMIT_COUNT)
-	return ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT;
-      THREAD_PASS;
-    }
-    goto start;
-  }
-  THREAD_ATOMIC_END;
-#endif /* USE_RECOMPILE_API && USE_MULTI_THREAD_SYSTEM */
 
   MATCH_ARG_INIT(msa, option, region, at, at);
@@ -3799,9 +3876,5 @@
 #endif
 
-  if (region
-#ifdef USE_POSIX_API_REGION_OPTION
-      && !IS_POSIX_REGION(option)
-#endif
-      ) {
+  if (region) {
     r = onig_region_resize_clear(region, reg->num_mem + 1);
   }
@@ -3810,5 +3883,5 @@
 
   if (r == 0) {
-    prev = (UChar* )onigenc_get_prev_char_head(reg->enc, str, at);
+    prev = (UChar* )onigenc_get_prev_char_head(reg->enc, str, at, end);
     r = match_at(reg, str, end,
 #ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE
@@ -3819,5 +3892,4 @@
 
   MATCH_ARG_FREE(msa);
-  ONIG_STATE_DEC_THREAD(reg);
   return r;
 }
@@ -3831,5 +3903,5 @@
 #ifdef ONIG_DEBUG_SEARCH
   fprintf(stderr, "forward_search_range: str: %"PRIuPTR" (%p), end: %"PRIuPTR" (%p), s: %"PRIuPTR" (%p), range: %"PRIuPTR" (%p)\n",
-	  (intptr_t )str, str, (intptr_t )end, end, (intptr_t )s, s, (intptr_t )range, range);
+	  (uintptr_t )str, str, (uintptr_t )end, end, (uintptr_t )s, s, (uintptr_t )range, range);
 #endif
 
@@ -3841,5 +3913,7 @@
     else {
       UChar *q = p + reg->dmin;
-      while (p < q) p += enclen(reg->enc, p);
+
+      if (q >= end) return 0; /* fail */
+      while (p < q) p += enclen(reg->enc, p, end);
     }
   }
@@ -3852,5 +3926,5 @@
   case ONIG_OPTIMIZE_EXACT_IC:
     p = slow_search_ic(reg->enc, reg->case_fold_flag,
-                       reg->exact, reg->exact_end, p, end, range);
+		       reg->exact, reg->exact_end, p, end, range);
     break;
 
@@ -3872,5 +3946,5 @@
 
   case ONIG_OPTIMIZE_MAP:
-    p = map_search(reg->enc, reg->map, p, range);
+    p = map_search(reg->enc, reg->map, p, range, end);
     break;
   }
@@ -3880,5 +3954,5 @@
     retry_gate:
       pprev = p;
-      p += enclen(reg->enc, p);
+      p += enclen(reg->enc, p, end);
       goto retry;
     }
@@ -3891,5 +3965,5 @@
 	if (!ON_STR_BEGIN(p)) {
 	  prev = onigenc_get_prev_char_head(reg->enc,
-					    (pprev ? pprev : str), p);
+					    (pprev ? pprev : str), p, end);
 	  if (!ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, prev, str, end, reg->options, 0))
 	    goto retry_gate;
@@ -3916,24 +3990,31 @@
       if (low_prev) {
 	if (*low > s)
-	  *low_prev = onigenc_get_prev_char_head(reg->enc, s, p);
+	  *low_prev = onigenc_get_prev_char_head(reg->enc, s, p, end);
 	else
 	  *low_prev = onigenc_get_prev_char_head(reg->enc,
-						 (pprev ? pprev : str), p);
+						 (pprev ? pprev : str), p, end);
       }
     }
     else {
       if (reg->dmax != ONIG_INFINITE_DISTANCE) {
-	*low = p - reg->dmax;
-	if (*low > s) {
-	  *low = onigenc_get_right_adjust_char_head_with_prev(reg->enc, s,
-							      *low, (const UChar** )low_prev);
-	  if (low_prev && IS_NULL(*low_prev))
-	    *low_prev = onigenc_get_prev_char_head(reg->enc,
-						   (pprev ? pprev : s), *low);
+	if (p < str + reg->dmax) {
+	  *low = (UChar* )str;
+	  if (low_prev)
+	    *low_prev = onigenc_get_prev_char_head(reg->enc, str, *low, end);
 	}
 	else {
-	  if (low_prev)
-	    *low_prev = onigenc_get_prev_char_head(reg->enc,
-					       (pprev ? pprev : str), *low);
+	  *low = p - reg->dmax;
+	  if (*low > s) {
+	    *low = onigenc_get_right_adjust_char_head_with_prev(reg->enc, s,
+								*low, end, (const UChar** )low_prev);
+	    if (low_prev && IS_NULL(*low_prev))
+	      *low_prev = onigenc_get_prev_char_head(reg->enc,
+						     (pprev ? pprev : s), *low, end);
+	  }
+	  else {
+	    if (low_prev)
+	      *low_prev = onigenc_get_prev_char_head(reg->enc,
+						 (pprev ? pprev : str), *low, end);
+	  }
 	}
       }
@@ -3960,5 +4041,4 @@
 		      UChar** low, UChar** high)
 {
-  int r;
   UChar *p;
 
@@ -3978,11 +4058,13 @@
   case ONIG_OPTIMIZE_EXACT_BM_NOT_REV_IC:
     p = slow_search_backward_ic(reg->enc, reg->case_fold_flag,
-                                reg->exact, reg->exact_end,
-                                range, adjrange, end, p);
+				reg->exact, reg->exact_end,
+				range, adjrange, end, p);
     break;
 
   case ONIG_OPTIMIZE_EXACT_BM:
   case ONIG_OPTIMIZE_EXACT_BM_NOT_REV:
+#ifdef USE_INT_MAP_BACKWARD
     if (IS_NULL(reg->int_map_backward)) {
+      int r;
       if (s - range < BM_BACKWARD_SEARCH_LENGTH_THRESHOLD)
 	goto exact_method;
@@ -3994,8 +4076,11 @@
     p = bm_search_backward(reg, reg->exact, reg->exact_end, range, adjrange,
 			   end, p);
+#else
+    goto exact_method;
+#endif
     break;
 
   case ONIG_OPTIMIZE_MAP:
-    p = map_search_backward(reg->enc, reg->map, range, adjrange, p);
+    p = map_search_backward(reg->enc, reg->map, range, adjrange, p, end);
     break;
   }
@@ -4008,5 +4093,5 @@
       case ANCHOR_BEGIN_LINE:
 	if (!ON_STR_BEGIN(p)) {
-	  prev = onigenc_get_prev_char_head(reg->enc, str, p);
+	  prev = onigenc_get_prev_char_head(reg->enc, str, p, end);
 	  if (!ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, prev, str, end, reg->options, 0)) {
 	    p = prev;
@@ -4028,5 +4113,5 @@
 	}
 	else if (! ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, p, str, end, reg->options, 1)) {
-	  p = onigenc_get_prev_char_head(reg->enc, adjrange, p);
+	  p = onigenc_get_prev_char_head(reg->enc, adjrange, p, end);
 	  if (IS_NULL(p)) goto fail;
 	  goto retry;
@@ -4040,5 +4125,5 @@
       *low  = p - reg->dmax;
       *high = p - reg->dmin;
-      *high = onigenc_get_right_adjust_char_head(reg->enc, adjrange, *high);
+      *high = onigenc_get_right_adjust_char_head(reg->enc, adjrange, *high, end);
     }
 
@@ -4078,40 +4163,11 @@
 #endif
 
-#if defined(USE_RECOMPILE_API) && defined(USE_MULTI_THREAD_SYSTEM)
- start:
-  THREAD_ATOMIC_START;
-  if (ONIG_STATE(reg) >= ONIG_STATE_NORMAL) {
-    ONIG_STATE_INC(reg);
-    if (IS_NOT_NULL(reg->chain) && ONIG_STATE(reg) == ONIG_STATE_NORMAL) {
-      onig_chain_reduce(reg);
-      ONIG_STATE_INC(reg);
-    }
-  }
-  else {
-    int n;
-
-    THREAD_ATOMIC_END;
-    n = 0;
-    while (ONIG_STATE(reg) < ONIG_STATE_NORMAL) {
-      if (++n > THREAD_PASS_LIMIT_COUNT)
-	return ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT;
-      THREAD_PASS;
-    }
-    goto start;
-  }
-  THREAD_ATOMIC_END;
-#endif /* USE_RECOMPILE_API && USE_MULTI_THREAD_SYSTEM */
-
 #ifdef ONIG_DEBUG_SEARCH
   fprintf(stderr,
      "onig_search (entry point): str: %"PRIuPTR" (%p), end: %"PRIuPTR", start: %"PRIuPTR", range: %"PRIuPTR"\n",
-     (intptr_t )str, str, end - str, start - str, range - str);
-#endif
-
-  if (region
-#ifdef USE_POSIX_API_REGION_OPTION
-      && !IS_POSIX_REGION(option)
-#endif
-      ) {
+     (uintptr_t )str, str, end - str, start - str, range - str);
+#endif
+
+  if (region) {
     r = onig_region_resize_clear(region, reg->num_mem + 1);
     if (r) goto finish_no_msa;
@@ -4122,6 +4178,6 @@
 
 #ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE
-#ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE
-#define MATCH_AND_RETURN_CHECK(upper_range) \
+# ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE
+#  define MATCH_AND_RETURN_CHECK(upper_range) \
   r = match_at(reg, str, end, (upper_range), s, prev, &msa); \
   if (r != ONIG_MISMATCH) {\
@@ -4133,6 +4189,6 @@
     else goto finish; /* error */ \
   }
-#else
-#define MATCH_AND_RETURN_CHECK(upper_range) \
+# else
+#  define MATCH_AND_RETURN_CHECK(upper_range) \
   r = match_at(reg, str, end, (upper_range), s, prev, &msa); \
   if (r != ONIG_MISMATCH) {\
@@ -4142,8 +4198,8 @@
     else goto finish; /* error */ \
   }
-#endif /* USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE */
+# endif /* USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE */
 #else
-#ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE
-#define MATCH_AND_RETURN_CHECK(none) \
+# ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE
+#  define MATCH_AND_RETURN_CHECK(none) \
   r = match_at(reg, str, end, s, prev, &msa);\
   if (r != ONIG_MISMATCH) {\
@@ -4155,6 +4211,6 @@
     else goto finish; /* error */ \
   }
-#else
-#define MATCH_AND_RETURN_CHECK(none) \
+# else
+#  define MATCH_AND_RETURN_CHECK(none) \
   r = match_at(reg, str, end, s, prev, &msa);\
   if (r != ONIG_MISMATCH) {\
@@ -4164,5 +4220,5 @@
     else goto finish; /* error */ \
   }
-#endif /* USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE */
+# endif /* USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE */
 #endif /* USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE */
 
@@ -4176,5 +4232,13 @@
     begin_position:
       if (range > start)
-	range = start + 1;
+      {
+	if (global_pos > start)
+	{
+	  if (global_pos < range)
+	    range = global_pos + 1;
+	}
+	else
+	  range = start + 1;
+      }
       else
 	range = start;
@@ -4206,5 +4270,5 @@
 	  start = min_semi_end - reg->anchor_dmax;
 	  if (start < end)
-	    start = onigenc_get_right_adjust_char_head(reg->enc, str, start);
+	    start = onigenc_get_right_adjust_char_head(reg->enc, str, start, end);
 	}
 	if ((OnigDistance )(max_semi_end - (range - 1)) < reg->anchor_dmin) {
@@ -4222,5 +4286,5 @@
 	if ((OnigDistance )(max_semi_end - start) < reg->anchor_dmin) {
 	  start = max_semi_end - reg->anchor_dmin;
-	  start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, start);
+	  start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, start, end);
 	}
 	if (range > start) goto mismatch_no_msa;
@@ -4228,5 +4292,5 @@
     }
     else if (reg->anchor & ANCHOR_SEMI_END_BUF) {
-      UChar* pre_end = ONIGENC_STEP_BACK(reg->enc, str, end, 1);
+      UChar* pre_end = ONIGENC_STEP_BACK(reg->enc, str, end, end, 1);
 
       max_semi_end = (UChar* )end;
@@ -4235,5 +4299,5 @@
 
 #ifdef USE_CRNL_AS_LINE_TERMINATOR
-	pre_end = ONIGENC_STEP_BACK(reg->enc, str, pre_end, 1);
+	pre_end = ONIGENC_STEP_BACK(reg->enc, str, pre_end, end, 1);
 	if (IS_NOT_NULL(pre_end) &&
 	    IS_NEWLINE_CRLF(reg->options) &&
@@ -4252,7 +4316,5 @@
     }
     else if ((reg->anchor & ANCHOR_ANYCHAR_STAR_ML)) {
-      if (! (reg->anchor & ANCHOR_LOOK_BEHIND)) {
-	goto begin_position;
-      }
+      goto begin_position;
     }
   }
@@ -4296,5 +4358,5 @@
   if (range > start) {   /* forward search */
     if (s > str)
-      prev = onigenc_get_prev_char_head(reg->enc, str, s);
+      prev = onigenc_get_prev_char_head(reg->enc, str, s, end);
     else
       prev = (UChar* )NULL;
@@ -4314,5 +4376,5 @@
 
       if ((end - start) < reg->threshold_len)
-        goto mismatch;
+	goto mismatch;
 
       if (reg->dmax != ONIG_INFINITE_DISTANCE) {
@@ -4327,5 +4389,5 @@
 	    MATCH_AND_RETURN_CHECK(orig_range);
 	    prev = s;
-	    s += enclen(reg->enc, s);
+	    s += enclen(reg->enc, s, end);
 	  }
 	} while (s < range);
@@ -4336,22 +4398,20 @@
 				   &low, &high, (UChar** )NULL)) goto mismatch;
 
-        if ((reg->anchor & ANCHOR_ANYCHAR_STAR) != 0) {
-          do {
-            if ((reg->anchor & ANCHOR_BEGIN_POSITION) == 0)
-              msa.gpos = s;     /* move \G position */
-            MATCH_AND_RETURN_CHECK(orig_range);
-            prev = s;
-            s += enclen(reg->enc, s);
-
-            if ((reg->anchor & (ANCHOR_LOOK_BEHIND | ANCHOR_PREC_READ_NOT)) == 0) {
-              while (!ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, prev, str, end, reg->options, 0)
-                     && s < range) {
-                prev = s;
-                s += enclen(reg->enc, s);
-              }
-            }
-          } while (s < range);
-          goto mismatch;
-        }
+	if ((reg->anchor & ANCHOR_ANYCHAR_STAR) != 0) {
+	  do {
+	    MATCH_AND_RETURN_CHECK(orig_range);
+	    prev = s;
+	    s += enclen(reg->enc, s, end);
+
+	    if ((reg->anchor & (ANCHOR_LOOK_BEHIND | ANCHOR_PREC_READ_NOT)) == 0) {
+	      while (!ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, prev, str, end, reg->options, 0)
+		  && s < range) {
+		prev = s;
+		s += enclen(reg->enc, s, end);
+	      }
+	    }
+	  } while (s < range);
+	  goto mismatch;
+	}
       }
     }
@@ -4360,5 +4420,5 @@
       MATCH_AND_RETURN_CHECK(orig_range);
       prev = s;
-      s += enclen(reg->enc, s);
+      s += enclen(reg->enc, s, end);
     } while (s < range);
 
@@ -4372,5 +4432,5 @@
 
       if (range < end)
-	adjrange = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, range);
+	adjrange = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, range, end);
       else
 	adjrange = (UChar* )end;
@@ -4389,5 +4449,5 @@
 
 	  while (s >= low) {
-	    prev = onigenc_get_prev_char_head(reg->enc, str, s);
+	    prev = onigenc_get_prev_char_head(reg->enc, str, s, end);
 	    MATCH_AND_RETURN_CHECK(orig_start);
 	    s = prev;
@@ -4408,5 +4468,5 @@
 	    else
 	      sch_start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc,
-						    start, sch_start);
+						    start, sch_start, end);
 	  }
 	}
@@ -4417,5 +4477,5 @@
 
     do {
-      prev = onigenc_get_prev_char_head(reg->enc, str, s);
+      prev = onigenc_get_prev_char_head(reg->enc, str, s, end);
       MATCH_AND_RETURN_CHECK(orig_start);
       s = prev;
@@ -4436,13 +4496,8 @@
  finish:
   MATCH_ARG_FREE(msa);
-  ONIG_STATE_DEC_THREAD(reg);
 
   /* If result is mismatch and no FIND_NOT_EMPTY option,
      then the region is not set in match_at(). */
-  if (IS_FIND_NOT_EMPTY(reg->options) && region
-#ifdef USE_POSIX_API_REGION_OPTION
-      && !IS_POSIX_REGION(option)
-#endif
-      ) {
+  if (IS_FIND_NOT_EMPTY(reg->options) && region) {
     onig_region_clear(region);
   }
@@ -4450,5 +4505,5 @@
 #ifdef ONIG_DEBUG
   if (r != ONIG_MISMATCH)
-    fprintf(stderr, "onig_search: error %"PRIdPTR"\n", r);
+    fprintf(stderr, "onig_search: error %"PRIdPTRDIFF"\n", r);
 #endif
   return r;
@@ -4457,19 +4512,59 @@
   r = ONIG_MISMATCH;
  finish_no_msa:
-  ONIG_STATE_DEC_THREAD(reg);
 #ifdef ONIG_DEBUG
   if (r != ONIG_MISMATCH)
-    fprintf(stderr, "onig_search: error %"PRIdPTR"\n", r);
+    fprintf(stderr, "onig_search: error %"PRIdPTRDIFF"\n", r);
 #endif
   return r;
 
  match:
-  ONIG_STATE_DEC_THREAD(reg);
   MATCH_ARG_FREE(msa);
   return s - str;
 }
 
+extern OnigPosition
+onig_scan(regex_t* reg, const UChar* str, const UChar* end,
+	  OnigRegion* region, OnigOptionType option,
+	  int (*scan_callback)(OnigPosition, OnigPosition, OnigRegion*, void*),
+	  void* callback_arg)
+{
+  OnigPosition r;
+  OnigPosition n;
+  int rs;
+  const UChar* start;
+
+  n = 0;
+  start = str;
+  while (1) {
+    r = onig_search(reg, str, end, start, end, region, option);
+    if (r >= 0) {
+      rs = scan_callback(n, r, region, callback_arg);
+      n++;
+      if (rs != 0)
+	return rs;
+
+      if (region->end[0] == start - str) {
+	if (start >= end) break;
+	start += enclen(reg->enc, start, end);
+      }
+      else
+	start = str + region->end[0];
+
+      if (start > end)
+	break;
+    }
+    else if (r == ONIG_MISMATCH) {
+      break;
+    }
+    else { /* error */
+      return r;
+    }
+  }
+
+  return n;
+}
+
 extern OnigEncoding
-onig_get_encoding(regex_t* reg)
+onig_get_encoding(const regex_t* reg)
 {
   return reg->enc;
@@ -4477,5 +4572,5 @@
 
 extern OnigOptionType
-onig_get_options(regex_t* reg)
+onig_get_options(const regex_t* reg)
 {
   return reg->options;
@@ -4483,11 +4578,11 @@
 
 extern  OnigCaseFoldType
-onig_get_case_fold_flag(regex_t* reg)
+onig_get_case_fold_flag(const regex_t* reg)
 {
   return reg->case_fold_flag;
 }
 
-extern OnigSyntaxType*
-onig_get_syntax(regex_t* reg)
+extern const OnigSyntaxType*
+onig_get_syntax(const regex_t* reg)
 {
   return reg->syntax;
@@ -4495,5 +4590,5 @@
 
 extern int
-onig_number_of_captures(regex_t* reg)
+onig_number_of_captures(const regex_t* reg)
 {
   return reg->num_mem;
@@ -4501,5 +4596,5 @@
 
 extern int
-onig_number_of_capture_histories(regex_t* reg)
+onig_number_of_capture_histories(const regex_t* reg)
 {
 #ifdef USE_CAPTURE_HISTORY
@@ -4518,5 +4613,5 @@
 
 extern void
-onig_copy_encoding(OnigEncoding to, OnigEncoding from)
+onig_copy_encoding(OnigEncodingType *to, OnigEncoding from)
 {
   *to = *from;
