Index: EcnlProtoTool/trunk/onigmo-6.1.3/src/regparse.c
===================================================================
--- EcnlProtoTool/trunk/onigmo-5.15.0/src/regparse.c	(revision 321)
+++ EcnlProtoTool/trunk/onigmo-6.1.3/src/regparse.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.
  *
@@ -30,5 +30,5 @@
 
 #include "regparse.h"
-#include "st.h"
+#include <stdarg.h>
 
 #define WARN_BUFSIZE    256
@@ -37,5 +37,5 @@
 
 
-OnigSyntaxType OnigSyntaxRuby = {
+const OnigSyntaxType OnigSyntaxRuby = {
   (( SYN_GNU_REGEX_OP | ONIG_SYN_OP_QMARK_NON_GREEDY |
      ONIG_SYN_OP_ESC_OCTAL3 | ONIG_SYN_OP_ESC_X_HEX2 |
@@ -53,8 +53,12 @@
       ONIG_SYN_OP2_ESC_CAPITAL_M_BAR_META | ONIG_SYN_OP2_ESC_V_VTAB |
       ONIG_SYN_OP2_ESC_H_XDIGIT |
+#ifndef RUBY
+      ONIG_SYN_OP2_ESC_U_HEX4 |
+#endif
       ONIG_SYN_OP2_ESC_CAPITAL_X_EXTENDED_GRAPHEME_CLUSTER |
       ONIG_SYN_OP2_QMARK_LPAREN_CONDITION |
       ONIG_SYN_OP2_ESC_CAPITAL_R_LINEBREAK |
-      ONIG_SYN_OP2_ESC_CAPITAL_K_KEEP )
+      ONIG_SYN_OP2_ESC_CAPITAL_K_KEEP |
+      ONIG_SYN_OP2_QMARK_TILDE_ABSENT )
   , ( SYN_GNU_REGEX_BV |
       ONIG_SYN_ALLOW_INTERVAL_LOW_ABBREV |
@@ -64,4 +68,5 @@
       ONIG_SYN_FIXED_INTERVAL_IS_GREEDY_ONLY |
       ONIG_SYN_WARN_CC_OP_NOT_ESCAPED |
+      ONIG_SYN_WARN_CC_DUP |
       ONIG_SYN_WARN_REDUNDANT_NESTED_REPEAT )
   , ( ONIG_OPTION_ASCII_RANGE | ONIG_OPTION_POSIX_BRACKET_ALL_RANGE |
@@ -78,5 +83,5 @@
 };
 
-OnigSyntaxType*  OnigDefaultSyntax = ONIG_SYNTAX_RUBY;
+const OnigSyntaxType*  OnigDefaultSyntax = ONIG_SYNTAX_RUBY;
 
 extern void onig_null_warn(const char* s ARG_UNUSED) { }
@@ -103,4 +108,26 @@
   onig_verb_warn = f;
 }
+
+static void CC_DUP_WARN(ScanEnv *env);
+
+
+static unsigned int ParseDepthLimit = DEFAULT_PARSE_DEPTH_LIMIT;
+
+extern unsigned int
+onig_get_parse_depth_limit(void)
+{
+  return ParseDepthLimit;
+}
+
+extern int
+onig_set_parse_depth_limit(unsigned int depth)
+{
+  if (depth == 0)
+    ParseDepthLimit = DEFAULT_PARSE_DEPTH_LIMIT;
+  else
+    ParseDepthLimit = depth;
+  return 0;
+}
+
 
 static void
@@ -137,5 +164,5 @@
 
 #define SET_ALL_MULTI_BYTE_RANGE(enc, pbuf) \
-  add_code_range_to_buf(pbuf, MBCODE_START_POS(enc), ONIG_LAST_CODE_POINT)
+  add_code_range_to_buf(pbuf, env, MBCODE_START_POS(enc), ONIG_LAST_CODE_POINT)
 
 #define ADD_ALL_MULTI_BYTE_RANGE(enc, mbuf) do {\
@@ -146,4 +173,9 @@
 } while (0)
 
+
+#define BITSET_SET_BIT_CHKDUP(bs, pos) do { \
+  if (BITSET_AT(bs, pos)) CC_DUP_WARN(env); \
+  BS_ROOM(bs, pos) |= BS_BIT(pos); \
+} while (0)
 
 #define BITSET_IS_EMPTY(bs,empty) do {\
@@ -158,9 +190,9 @@
 
 static void
-bitset_set_range(BitSetRef bs, int from, int to)
+bitset_set_range(ScanEnv *env, BitSetRef bs, int from, int to)
 {
   int i;
   for (i = from; i <= to && i < SINGLE_BYTE_SIZE; i++) {
-    BITSET_SET_BIT(bs, i);
+    BITSET_SET_BIT_CHKDUP(bs, i);
   }
 }
@@ -210,4 +242,5 @@
 }
 
+#if defined(USE_NAMED_GROUP) && !defined(USE_ST_LIBRARY)
 extern int
 onig_strncmp(const UChar* s1, const UChar* s2, int n)
@@ -221,4 +254,5 @@
   return 0;
 }
+#endif
 
 extern void
@@ -259,7 +293,7 @@
 #ifdef __GNUC__
 /* get rid of Wunused-but-set-variable and Wuninitialized */
-#define PFETCH_READY  UChar* pfetch_prev = NULL; (void)pfetch_prev
+# define PFETCH_READY  UChar* pfetch_prev = NULL; (void)pfetch_prev
 #else
-#define PFETCH_READY  UChar* pfetch_prev
+# define PFETCH_READY  UChar* pfetch_prev
 #endif
 #define PEND         (p < end ?  0 : 1)
@@ -267,18 +301,18 @@
 #define PINC       do { \
   pfetch_prev = p; \
-  p += ONIGENC_MBC_ENC_LEN(enc, p); \
+  p += enclen(enc, p, end); \
 } while (0)
 #define PFETCH(c)  do { \
-  c = ONIGENC_MBC_TO_CODE(enc, p, end); \
+  c = ((enc->max_enc_len == 1) ? *p : ONIGENC_MBC_TO_CODE(enc, p, end)); \
   pfetch_prev = p; \
-  p += ONIGENC_MBC_ENC_LEN(enc, p); \
+  p += enclen(enc, p, end); \
 } while (0)
 
 #define PINC_S     do { \
-  p += ONIGENC_MBC_ENC_LEN(enc, p); \
+  p += enclen(enc, p, end); \
 } while (0)
 #define PFETCH_S(c) do { \
-  c = ONIGENC_MBC_TO_CODE(enc, p, end); \
-  p += ONIGENC_MBC_ENC_LEN(enc, p); \
+  c = ((enc->max_enc_len == 1) ? *p : ONIGENC_MBC_TO_CODE(enc, p, end)); \
+  p += enclen(enc, p, end); \
 } while (0)
 
@@ -319,15 +353,24 @@
 #ifdef USE_ST_LIBRARY
 
+# ifdef RUBY
+#  include "ruby/st.h"
+# else
+#  include "st.h"
+# endif
+
 typedef struct {
-  UChar* s;
-  UChar* end;
+  const UChar* s;
+  const UChar* end;
 } st_str_end_key;
 
 static int
-str_end_cmp(st_str_end_key* x, st_str_end_key* y)
-{
-  UChar *p, *q;
+str_end_cmp(st_data_t xp, st_data_t yp)
+{
+  const st_str_end_key *x, *y;
+  const UChar *p, *q;
   int c;
 
+  x = (const st_str_end_key *)xp;
+  y = (const st_str_end_key *)yp;
   if ((x->end - x->s) != (y->end - y->s))
     return 1;
@@ -345,9 +388,10 @@
 }
 
-static int
-str_end_hash(st_str_end_key* x)
-{
-  UChar *p;
-  int val = 0;
+static st_index_t
+str_end_hash(st_data_t xp)
+{
+  const st_str_end_key *x = (const st_str_end_key *)xp;
+  const UChar *p;
+  st_index_t val = 0;
 
   p = x->s;
@@ -360,7 +404,7 @@
 
 extern hash_table_type*
-onig_st_init_strend_table_with_size(int size)
-{
-  static struct st_hash_type hashType = {
+onig_st_init_strend_table_with_size(st_index_t size)
+{
+  static const struct st_hash_type hashType = {
     str_end_cmp,
     str_end_hash,
@@ -405,5 +449,5 @@
 #ifdef USE_NAMED_GROUP
 
-#define INIT_NAME_BACKREFS_ALLOC_NUM   8
+# define INIT_NAME_BACKREFS_ALLOC_NUM   8
 
 typedef struct {
@@ -416,10 +460,10 @@
 } NameEntry;
 
-#ifdef USE_ST_LIBRARY
+# ifdef USE_ST_LIBRARY
 
 typedef st_table  NameTable;
 typedef st_data_t HashDataType;   /* 1.6 st.h doesn't define st_data_t type */
 
-#ifdef ONIG_DEBUG
+#  ifdef ONIG_DEBUG
 static int
 i_print_name_entry(UChar* key, NameEntry* e, void* arg)
@@ -455,5 +499,5 @@
   return 0;
 }
-#endif /* ONIG_DEBUG */
+#  endif /* ONIG_DEBUG */
 
 static int
@@ -518,6 +562,6 @@
 {
   int r = (*(arg->func))(e->name,
-                         e->name + e->name_len,
-                         e->back_num,
+			 e->name + e->name_len,
+			 e->back_num,
 			 (e->back_num > 1 ? e->back_refs : &(e->back_ref1)),
 			 arg->reg, arg->arg);
@@ -577,17 +621,17 @@
 
 extern int
-onig_number_of_names(regex_t* reg)
+onig_number_of_names(const regex_t* reg)
 {
   NameTable* t = (NameTable* )reg->name_table;
 
   if (IS_NOT_NULL(t))
-    return t->num_entries;
+    return (int )t->num_entries;
   else
     return 0;
 }
 
-#else  /* USE_ST_LIBRARY */
-
-#define INIT_NAMES_ALLOC_NUM    8
+# else  /* USE_ST_LIBRARY */
+
+#  define INIT_NAMES_ALLOC_NUM    8
 
 typedef struct {
@@ -597,5 +641,5 @@
 } NameTable;
 
-#ifdef ONIG_DEBUG
+#  ifdef ONIG_DEBUG
 extern int
 onig_print_names(FILE* fp, regex_t* reg)
@@ -628,5 +672,5 @@
   return 0;
 }
-#endif
+#  endif
 
 static int
@@ -713,5 +757,5 @@
 
 extern int
-onig_number_of_names(regex_t* reg)
+onig_number_of_names(const regex_t* reg)
 {
   NameTable* t = (NameTable* )reg->name_table;
@@ -723,5 +767,5 @@
 }
 
-#endif /* else USE_ST_LIBRARY */
+# endif /* else USE_ST_LIBRARY */
 
 static int
@@ -737,5 +781,5 @@
   e = name_find(reg, name, name_end);
   if (IS_NULL(e)) {
-#ifdef USE_ST_LIBRARY
+# ifdef USE_ST_LIBRARY
     if (IS_NULL(t)) {
       t = onig_st_init_strend_table_with_size(5);
@@ -758,5 +802,5 @@
     e->back_refs  = (int* )NULL;
 
-#else
+# else
 
     if (IS_NULL(t)) {
@@ -801,5 +845,5 @@
     if (IS_NULL(e->name)) return ONIGERR_MEMORY;
     e->name_len = name_end - name;
-#endif
+# endif
   }
 
@@ -864,5 +908,5 @@
 extern int
 onig_name_to_backref_number(regex_t* reg, const UChar* name,
-			    const UChar* name_end, OnigRegion *region)
+			    const UChar* name_end, const OnigRegion *region)
 {
   int i, n, *nums;
@@ -897,5 +941,5 @@
 extern int
 onig_name_to_backref_number(regex_t* reg, const UChar* name,
-			    const UChar* name_end, OnigRegion* region)
+			    const UChar* name_end, const OnigRegion* region)
 {
   return ONIG_NO_SUPPORT_CONFIG;
@@ -910,5 +954,5 @@
 
 extern int
-onig_number_of_names(regex_t* reg)
+onig_number_of_names(const regex_t* reg)
 {
   return 0;
@@ -917,5 +961,5 @@
 
 extern int
-onig_noname_group_capture_is_active(regex_t* reg)
+onig_noname_group_capture_is_active(const regex_t* reg)
 {
   if (ONIG_IS_OPTION_ON(reg->options, ONIG_OPTION_DONT_CAPTURE_GROUP))
@@ -964,4 +1008,6 @@
   env->has_recursion       = 0;
 #endif
+  env->parse_depth         = 0;
+  env->warnings_flag       = 0;
 }
 
@@ -980,4 +1026,5 @@
 	alloc = INIT_SCANENV_MEMNODES_ALLOC_SIZE;
 	p = (Node** )xmalloc(sizeof(Node*) * alloc);
+	CHECK_NULL_RETURN_MEMERR(p);
 	xmemcpy(p, env->mem_nodes_static,
 		sizeof(Node*) * SCANENV_MEMNODES_SIZE);
@@ -986,6 +1033,6 @@
 	alloc = env->mem_alloc * 2;
 	p = (Node** )xrealloc(env->mem_nodes_dynamic, sizeof(Node*) * alloc);
-      }
-      CHECK_NULL_RETURN_MEMERR(p);
+	CHECK_NULL_RETURN_MEMERR(p);
+      }
 
       for (i = env->num_mem + 1; i < alloc; i++)
@@ -1012,12 +1059,4 @@
 
 
-#ifdef USE_PARSE_TREE_NODE_RECYCLE
-typedef struct _FreeNode {
-  struct _FreeNode* next;
-} FreeNode;
-
-static FreeNode* FreeNodeList = (FreeNode* )NULL;
-#endif
-
 extern void
 onig_node_free(Node* node)
@@ -1040,16 +1079,5 @@
       Node* next_node = NCDR(node);
 
-#ifdef USE_PARSE_TREE_NODE_RECYCLE
-      {
-	FreeNode* n = (FreeNode* )node;
-
-        THREAD_ATOMIC_START;
-	n->next = FreeNodeList;
-	FreeNodeList = n;
-        THREAD_ATOMIC_END;
-      }
-#else
       xfree(node);
-#endif
       node = next_node;
       goto start;
@@ -1061,7 +1089,6 @@
       CClassNode* cc = NCCLASS(node);
 
-      if (IS_NCCLASS_SHARE(cc)) return ;
       if (cc->mbuf)
-        bbuf_free(cc->mbuf);
+	bbuf_free(cc->mbuf);
     }
     break;
@@ -1088,34 +1115,6 @@
   }
 
-#ifdef USE_PARSE_TREE_NODE_RECYCLE
-  {
-    FreeNode* n = (FreeNode* )node;
-
-    THREAD_ATOMIC_START;
-    n->next = FreeNodeList;
-    FreeNodeList = n;
-    THREAD_ATOMIC_END;
-  }
-#else
   xfree(node);
-#endif
-}
-
-#ifdef USE_PARSE_TREE_NODE_RECYCLE
-extern int
-onig_free_node_list(void)
-{
-  FreeNode* n;
-
-  /* THREAD_ATOMIC_START; */
-  while (IS_NOT_NULL(FreeNodeList)) {
-    n = FreeNodeList;
-    FreeNodeList = FreeNodeList->next;
-    xfree(n);
-  }
-  /* THREAD_ATOMIC_END; */
-  return 0;
-}
-#endif
+}
 
 static Node*
@@ -1123,15 +1122,4 @@
 {
   Node* node;
-
-#ifdef USE_PARSE_TREE_NODE_RECYCLE
-  THREAD_ATOMIC_START;
-  if (IS_NOT_NULL(FreeNodeList)) {
-    node = (Node* )FreeNodeList;
-    FreeNodeList = FreeNodeList->next;
-    THREAD_ATOMIC_END;
-    return node;
-  }
-  THREAD_ATOMIC_END;
-#endif
 
   node = (Node* )xmalloc(sizeof(Node));
@@ -1139,24 +1127,4 @@
   return node;
 }
-
-#if defined(USE_MULTI_THREAD_SYSTEM) && \
-    defined(USE_SHARED_CCLASS_TABLE) && \
-    defined(USE_PARSE_TREE_NODE_RECYCLE)
-static Node*
-node_new_locked(void)
-{
-  Node* node;
-
-  if (IS_NOT_NULL(FreeNodeList)) {
-    node = (Node* )FreeNodeList;
-    FreeNodeList = FreeNodeList->next;
-    return node;
-  }
-
-  node = (Node* )xmalloc(sizeof(Node));
-  /* xmemset(node, 0, sizeof(Node)); */
-  return node;
-}
-#endif
 
 static void
@@ -1179,73 +1147,4 @@
   return node;
 }
-
-#if defined(USE_MULTI_THREAD_SYSTEM) && \
-    defined(USE_SHARED_CCLASS_TABLE) && \
-    defined(USE_PARSE_TREE_NODE_RECYCLE)
-static Node*
-node_new_cclass_locked(void)
-{
-  Node* node = node_new_locked();
-  CHECK_NULL_RETURN(node);
-
-  SET_NTYPE(node, NT_CCLASS);
-  initialize_cclass(NCCLASS(node));
-  return node;
-}
-#else
-#define node_new_cclass_locked()  node_new_cclass()
-#endif
-
-#ifdef USE_SHARED_CCLASS_TABLE
-static Node*
-node_new_cclass_by_codepoint_range(int not, OnigCodePoint sb_out,
-				   const OnigCodePoint ranges[])
-{
-  int n, i;
-  CClassNode* cc;
-  OnigCodePoint j;
-
-  Node* node = node_new_cclass_locked();
-  CHECK_NULL_RETURN(node);
-
-  cc = NCCLASS(node);
-  if (not != 0) NCCLASS_SET_NOT(cc);
-
-  BITSET_CLEAR(cc->bs);
-  if (sb_out > 0 && IS_NOT_NULL(ranges)) {
-    n = ONIGENC_CODE_RANGE_NUM(ranges);
-    for (i = 0; i < n; i++) {
-      for (j  = ONIGENC_CODE_RANGE_FROM(ranges, i);
-           j <= (OnigCodePoint )ONIGENC_CODE_RANGE_TO(ranges, i); j++) {
-	if (j >= sb_out) goto sb_end;
-
-        BITSET_SET_BIT(cc->bs, j);
-      }
-    }
-  }
-
- sb_end:
-  if (IS_NULL(ranges)) {
-  is_null:
-    cc->mbuf = NULL;
-  }
-  else {
-    BBuf* bbuf;
-
-    n = ONIGENC_CODE_RANGE_NUM(ranges);
-    if (n == 0) goto is_null;
-
-    bbuf = (BBuf* )xmalloc(sizeof(BBuf));
-    CHECK_NULL_RETURN(bbuf);
-    bbuf->alloc = n + 1;
-    bbuf->used  = n + 1;
-    bbuf->p     = (UChar* )((void* )ranges);
-
-    cc->mbuf = bbuf;
-  }
-
-  return node;
-}
-#endif /* USE_SHARED_CCLASS_TABLE */
 
 static Node*
@@ -1535,4 +1434,5 @@
 }
 
+#if 0
 extern void
 onig_node_conv_to_str_node(Node* node, int flag)
@@ -1544,4 +1444,5 @@
   NSTR(node)->end  = NSTR(node)->buf;
 }
+#endif
 
 extern void
@@ -1614,5 +1515,5 @@
 
   if (sn->end > sn->s) {
-    p = onigenc_get_prev_char_head(enc, sn->s, sn->end);
+    p = onigenc_get_prev_char_head(enc, sn->s, sn->end, sn->end);
     if (p && p > sn->s) { /* can be split. */
       n = node_new_str(p, sn->end);
@@ -1629,5 +1530,5 @@
 {
   if (sn->end > sn->s) {
-    return ((enclen(enc, sn->s) < sn->end - sn->s)  ?  1 : 0);
+    return ((enclen(enc, sn->s, sn->end) < sn->end - sn->s)  ?  1 : 0);
   }
   return 0;
@@ -1702,4 +1603,5 @@
     else {
       PUNFETCH;
+      maxlen++;
       break;
     }
@@ -1766,5 +1668,6 @@
 
 static int
-add_code_range_to_buf(BBuf** pbuf, OnigCodePoint from, OnigCodePoint to)
+add_code_range_to_buf0(BBuf** pbuf, ScanEnv* env, OnigCodePoint from, OnigCodePoint to,
+	int checkdup)
 {
   int r, inc_n, pos;
@@ -1807,4 +1710,7 @@
       bound = x;
   }
+  /* data[(low-1)*2+1] << from <= data[low*2]
+   * data[(high-1)*2+1] <= to << data[high*2]
+   */
 
   inc_n = low + 1 - high;
@@ -1813,4 +1719,7 @@
 
   if (inc_n != 1) {
+    if (checkdup && from <= data[low*2+1]
+	&& (data[low*2] <= from || data[low*2+1] <= to))
+      CC_DUP_WARN(env);
     if (from > data[low*2])
       from = data[low*2];
@@ -1845,5 +1754,11 @@
 
 static int
-add_code_range(BBuf** pbuf, ScanEnv* env, OnigCodePoint from, OnigCodePoint to)
+add_code_range_to_buf(BBuf** pbuf, ScanEnv* env, OnigCodePoint from, OnigCodePoint to)
+{
+  return add_code_range_to_buf0(pbuf, env, from, to, 1);
+}
+
+static int
+add_code_range0(BBuf** pbuf, ScanEnv* env, OnigCodePoint from, OnigCodePoint to, int checkdup)
 {
   if (from > to) {
@@ -1854,9 +1769,15 @@
   }
 
-  return add_code_range_to_buf(pbuf, from, to);
+  return add_code_range_to_buf0(pbuf, env, from, to, checkdup);
 }
 
 static int
-not_code_range_buf(OnigEncoding enc, BBuf* bbuf, BBuf** pbuf)
+add_code_range(BBuf** pbuf, ScanEnv* env, OnigCodePoint from, OnigCodePoint to)
+{
+  return add_code_range0(pbuf, env, from, to, 1);
+}
+
+static int
+not_code_range_buf(OnigEncoding enc, BBuf* bbuf, BBuf** pbuf, ScanEnv* env)
 {
   int r, i, n;
@@ -1880,5 +1801,5 @@
     to   = data[i*2+1];
     if (pre <= from - 1) {
-      r = add_code_range_to_buf(pbuf, pre, from - 1);
+      r = add_code_range_to_buf(pbuf, env, pre, from - 1);
       if (r != 0) return r;
     }
@@ -1887,5 +1808,5 @@
   }
   if (to < ONIG_LAST_CODE_POINT) {
-    r = add_code_range_to_buf(pbuf, to + 1, ONIG_LAST_CODE_POINT);
+    r = add_code_range_to_buf(pbuf, env, to + 1, ONIG_LAST_CODE_POINT);
   }
   return r;
@@ -1901,5 +1822,5 @@
 static int
 or_code_range_buf(OnigEncoding enc, BBuf* bbuf1, int not1,
-                  BBuf* bbuf2, int not2, BBuf** pbuf)
+                  BBuf* bbuf2, int not2, BBuf** pbuf, ScanEnv* env)
 {
   int r;
@@ -1927,5 +1848,5 @@
       }
       else {
-	return not_code_range_buf(enc, bbuf2, pbuf);
+	return not_code_range_buf(enc, bbuf2, pbuf, env);
       }
     }
@@ -1943,5 +1864,5 @@
   }
   else if (not1 == 0) { /* 1 OR (not 2) */
-    r = not_code_range_buf(enc, bbuf2, pbuf);
+    r = not_code_range_buf(enc, bbuf2, pbuf, env);
   }
   if (r != 0) return r;
@@ -1950,5 +1871,5 @@
     from = data1[i*2];
     to   = data1[i*2+1];
-    r = add_code_range_to_buf(pbuf, from, to);
+    r = add_code_range_to_buf(pbuf, env, from, to);
     if (r != 0) return r;
   }
@@ -1957,6 +1878,6 @@
 
 static int
-and_code_range1(BBuf** pbuf, OnigCodePoint from1, OnigCodePoint to1,
-	        OnigCodePoint* data, int n)
+and_code_range1(BBuf** pbuf, ScanEnv* env, OnigCodePoint from1, OnigCodePoint to1,
+		OnigCodePoint* data, int n)
 {
   int i, r;
@@ -1975,5 +1896,5 @@
       if (to2 < to1) {
 	if (from1 <= from2 - 1) {
-	  r = add_code_range_to_buf(pbuf, from1, from2-1);
+	  r = add_code_range_to_buf(pbuf, env, from1, from2-1);
 	  if (r != 0) return r;
 	}
@@ -1990,5 +1911,5 @@
   }
   if (from1 <= to1) {
-    r = add_code_range_to_buf(pbuf, from1, to1);
+    r = add_code_range_to_buf(pbuf, env, from1, to1);
     if (r != 0) return r;
   }
@@ -1997,5 +1918,5 @@
 
 static int
-and_code_range_buf(BBuf* bbuf1, int not1, BBuf* bbuf2, int not2, BBuf** pbuf)
+and_code_range_buf(BBuf* bbuf1, int not1, BBuf* bbuf2, int not2, BBuf** pbuf, ScanEnv* env)
 {
   int r;
@@ -2036,5 +1957,5 @@
 	from = MAX(from1, from2);
 	to   = MIN(to1, to2);
-	r = add_code_range_to_buf(pbuf, from, to);
+	r = add_code_range_to_buf(pbuf, env, from, to);
 	if (r != 0) return r;
       }
@@ -2045,5 +1966,5 @@
       from1 = data1[i*2];
       to1   = data1[i*2+1];
-      r = and_code_range1(pbuf, from1, to1, data2, n2);
+      r = and_code_range1(pbuf, env, from1, to1, data2, n2);
       if (r != 0) return r;
     }
@@ -2054,6 +1975,7 @@
 
 static int
-and_cclass(CClassNode* dest, CClassNode* cc, OnigEncoding enc)
-{
+and_cclass(CClassNode* dest, CClassNode* cc, ScanEnv* env)
+{
+  OnigEncoding enc = env->enc;
   int r, not1, not2;
   BBuf *buf1, *buf2, *pbuf = 0;
@@ -2087,11 +2009,11 @@
   if (! ONIGENC_IS_SINGLEBYTE(enc)) {
     if (not1 != 0 && not2 != 0) {
-      r = or_code_range_buf(enc, buf1, 0, buf2, 0, &pbuf);
+      r = or_code_range_buf(enc, buf1, 0, buf2, 0, &pbuf, env);
     }
     else {
-      r = and_code_range_buf(buf1, not1, buf2, not2, &pbuf);
+      r = and_code_range_buf(buf1, not1, buf2, not2, &pbuf, env);
       if (r == 0 && not1 != 0) {
 	BBuf *tbuf = 0;
-	r = not_code_range_buf(enc, pbuf, &tbuf);
+	r = not_code_range_buf(enc, pbuf, &tbuf, env);
 	bbuf_free(pbuf);
 	pbuf = tbuf;
@@ -2111,6 +2033,7 @@
 
 static int
-or_cclass(CClassNode* dest, CClassNode* cc, OnigEncoding enc)
-{
+or_cclass(CClassNode* dest, CClassNode* cc, ScanEnv* env)
+{
+  OnigEncoding enc = env->enc;
   int r, not1, not2;
   BBuf *buf1, *buf2, *pbuf = 0;
@@ -2144,11 +2067,11 @@
   if (! ONIGENC_IS_SINGLEBYTE(enc)) {
     if (not1 != 0 && not2 != 0) {
-      r = and_code_range_buf(buf1, 0, buf2, 0, &pbuf);
+      r = and_code_range_buf(buf1, 0, buf2, 0, &pbuf, env);
     }
     else {
-      r = or_code_range_buf(enc, buf1, not1, buf2, not2, &pbuf);
+      r = or_code_range_buf(enc, buf1, not1, buf2, not2, &pbuf, env);
       if (r == 0 && not1 != 0) {
 	BBuf *tbuf = 0;
-	r = not_code_range_buf(enc, pbuf, &tbuf);
+	r = not_code_range_buf(enc, pbuf, &tbuf, env);
 	bbuf_free(pbuf);
 	pbuf = tbuf;
@@ -2168,6 +2091,8 @@
 }
 
-static int
-conv_backslash_value(int c, ScanEnv* env)
+static void UNKNOWN_ESC_WARN(ScanEnv *env, int c);
+
+static OnigCodePoint
+conv_backslash_value(OnigCodePoint c, ScanEnv* env)
 {
   if (IS_SYNTAX_OP(env->syntax, ONIG_SYN_OP_ESC_CONTROL_CHARS)) {
@@ -2186,4 +2111,6 @@
 
     default:
+      if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))
+	  UNKNOWN_ESC_WARN(env, c);
       break;
     }
@@ -2193,5 +2120,5 @@
 
 #ifdef USE_NO_INVALID_QUANTIFIER
-#define is_invalid_quantifier_target(node) 0
+# define is_invalid_quantifier_target(node) 0
 #else
 static int
@@ -2265,4 +2192,5 @@
 
 static enum ReduceType const ReduceTypeTable[6][6] = {
+/* '?',     '*',     '+',    '??',    '*?',    '+?'      p / c   */
   {RQ_DEL,  RQ_A,    RQ_A,   RQ_QQ,   RQ_AQ,   RQ_ASIS}, /* '?'  */
   {RQ_DEL,  RQ_DEL,  RQ_DEL, RQ_P_QQ, RQ_P_QQ, RQ_DEL},  /* '*'  */
@@ -2467,4 +2395,5 @@
   if (IS_SYNTAX_OP(env->syntax, ONIG_SYN_OP_ESC_BRACE_INTERVAL)) {
     if (c != MC_ESC(env->syntax)) goto invalid;
+    if (PEND) goto invalid;
     PFETCH(c);
   }
@@ -2490,5 +2419,5 @@
 /* \M-, \C-, \c, or \... */
 static int
-fetch_escaped_value(UChar** src, UChar* end, ScanEnv* env)
+fetch_escaped_value(UChar** src, UChar* end, ScanEnv* env, OnigCodePoint* val)
 {
   int v;
@@ -2509,7 +2438,6 @@
       PFETCH_S(c);
       if (c == MC_ESC(env->syntax)) {
-        v = fetch_escaped_value(&p, end, env);
-        if (v < 0) return v;
-        c = (OnigCodePoint )v;
+	v = fetch_escaped_value(&p, end, env, &c);
+	if (v < 0) return v;
       }
       c = ((c & 0xff) | 0x80);
@@ -2535,13 +2463,12 @@
       PFETCH_S(c);
       if (c == '?') {
-        c = 0177;
+	c = 0177;
       }
       else {
-        if (c == MC_ESC(env->syntax)) {
-          v = fetch_escaped_value(&p, end, env);
-          if (v < 0) return v;
-          c = (OnigCodePoint )v;
-        }
-        c &= 0x9f;
+	if (c == MC_ESC(env->syntax)) {
+	  v = fetch_escaped_value(&p, end, env, &c);
+	  if (v < 0) return v;
+	}
+	c &= 0x9f;
       }
       break;
@@ -2558,5 +2485,6 @@
 
   *src = p;
-  return c;
+  *val = c;
+  return 0;
 }
 
@@ -2579,5 +2507,11 @@
 
 #ifdef USE_NAMED_GROUP
-#ifdef USE_BACKREF_WITH_LEVEL
+# ifdef RUBY
+#  define ONIGENC_IS_CODE_NAME(enc, c)  TRUE
+# else
+#  define ONIGENC_IS_CODE_NAME(enc, c)  ONIGENC_IS_CODE_WORD(enc, c)
+# endif
+
+# ifdef USE_BACKREF_WITH_LEVEL
 /*
    \k<name+n>, \k<name-n>
@@ -2624,5 +2558,5 @@
       pnum_head = p;
     }
-    else if (!ONIGENC_IS_CODE_WORD(enc, c)) {
+    else if (!ONIGENC_IS_CODE_NAME(enc, c)) {
       r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
     }
@@ -2639,12 +2573,12 @@
     if (is_num != 0) {
       if (ONIGENC_IS_CODE_DIGIT(enc, c)) {
-        is_num = 1;
+	is_num = 1;
       }
       else {
-        r = ONIGERR_INVALID_GROUP_NAME;
-        is_num = 0;
-      }
-    }
-    else if (!ONIGENC_IS_CODE_WORD(enc, c)) {
+	r = ONIGERR_INVALID_GROUP_NAME;
+	is_num = 0;
+      }
+    }
+    else if (!ONIGENC_IS_CODE_NAME(enc, c)) {
       r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
     }
@@ -2656,4 +2590,8 @@
       int flag = (c == '-' ? -1 : 1);
 
+      if (PEND) {
+	r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
+	goto end;
+      }
       PFETCH(c);
       if (! ONIGENC_IS_CODE_DIGIT(enc, c)) goto err;
@@ -2664,7 +2602,9 @@
       exist_level = 1;
 
-      PFETCH(c);
-      if (c == end_code)
-	goto end;
+      if (!PEND) {
+	PFETCH(c);
+	if (c == end_code)
+	  goto end;
+      }
     }
 
@@ -2693,5 +2633,5 @@
   }
 }
-#endif /* USE_BACKREF_WITH_LEVEL */
+# endif /* USE_BACKREF_WITH_LEVEL */
 
 /*
@@ -2730,16 +2670,5 @@
     if (ONIGENC_IS_CODE_DIGIT(enc, c)) {
       if (ref == 1)
-        is_num = 1;
-      else {
-        r = ONIGERR_INVALID_GROUP_NAME;
-        is_num = 0;
-      }
-    }
-    else if (c == '-') {
-      if (ref == 1) {
-        is_num = 2;
-        sign = -1;
-        pnum_head = p;
-      }
+	is_num = 1;
       else {
 	r = ONIGERR_INVALID_GROUP_NAME;
@@ -2747,5 +2676,16 @@
       }
     }
-    else if (!ONIGENC_IS_CODE_WORD(enc, c)) {
+    else if (c == '-') {
+      if (ref == 1) {
+	is_num = 2;
+	sign = -1;
+	pnum_head = p;
+      }
+      else {
+	r = ONIGERR_INVALID_GROUP_NAME;
+	is_num = 0;
+      }
+    }
+    else if (!ONIGENC_IS_CODE_NAME(enc, c)) {
       r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
     }
@@ -2757,24 +2697,28 @@
       PFETCH_S(c);
       if (c == end_code || c == ')') {
-	if (is_num == 2) r = ONIGERR_INVALID_GROUP_NAME;
+	if (is_num == 2) {
+	  r = ONIGERR_INVALID_GROUP_NAME;
+	  goto teardown;
+	}
 	break;
       }
 
       if (is_num != 0) {
-        if (ONIGENC_IS_CODE_DIGIT(enc, c)) {
-          is_num = 1;
-        }
-        else {
-          if (!ONIGENC_IS_CODE_WORD(enc, c))
-            r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
-          else
-            r = ONIGERR_INVALID_GROUP_NAME;
-          is_num = 0;
-        }
+	if (ONIGENC_IS_CODE_DIGIT(enc, c)) {
+	  is_num = 1;
+	}
+	else {
+	  if (!ONIGENC_IS_CODE_WORD(enc, c))
+	    r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
+	  else
+	    r = ONIGERR_INVALID_GROUP_NAME;
+	  goto teardown;
+	}
       }
       else {
-        if (!ONIGENC_IS_CODE_WORD(enc, c)) {
-          r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
-        }
+	if (!ONIGENC_IS_CODE_NAME(enc, c)) {
+	  r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
+	  goto teardown;
+	}
       }
     }
@@ -2783,4 +2727,5 @@
       r = ONIGERR_INVALID_GROUP_NAME;
       name_end = end;
+      goto err;
     }
 
@@ -2789,6 +2734,6 @@
       if (*rback_num < 0) return ONIGERR_TOO_BIG_NUMBER;
       else if (*rback_num == 0) {
-        r = ONIGERR_INVALID_GROUP_NAME;
-        goto err;
+	r = ONIGERR_INVALID_GROUP_NAME;
+	goto err;
       }
 
@@ -2801,9 +2746,10 @@
   }
   else {
+teardown:
     while (!PEND) {
       name_end = p;
       PFETCH_S(c);
       if (c == end_code || c == ')')
-        break;
+	break;
     }
     if (PEND)
@@ -2894,6 +2840,27 @@
 #endif /* USE_NAMED_GROUP */
 
+
 static void
-CC_ESC_WARN(ScanEnv* env, UChar *c)
+onig_syntax_warn(ScanEnv *env, const char *fmt, ...)
+{
+    va_list args;
+    UChar buf[WARN_BUFSIZE];
+    va_start(args, fmt);
+    onig_vsnprintf_with_pattern(buf, WARN_BUFSIZE, env->enc,
+		env->pattern, env->pattern_end,
+		(const UChar *)fmt, args);
+    va_end(args);
+#ifdef RUBY
+    if (env->sourcefile == NULL)
+      rb_warn("%s", (char *)buf);
+    else
+      rb_compile_warn(env->sourcefile, env->sourceline, "%s", (char *)buf);
+#else
+    (*onig_warn)((char* )buf);
+#endif
+}
+
+static void
+CC_ESC_WARN(ScanEnv *env, UChar *c)
 {
   if (onig_warn == onig_null_warn) return ;
@@ -2901,9 +2868,5 @@
   if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_WARN_CC_OP_NOT_ESCAPED) &&
       IS_SYNTAX_BV(env->syntax, ONIG_SYN_BACKSLASH_ESCAPE_IN_CC)) {
-    UChar buf[WARN_BUFSIZE];
-    onig_snprintf_with_pattern(buf, WARN_BUFSIZE, env->enc,
-		env->pattern, env->pattern_end,
-                (UChar* )"character class has '%s' without escape", c);
-    (*onig_warn)((char* )buf);
+    onig_syntax_warn(env, "character class has '%s' without escape", c);
   }
 }
@@ -2915,10 +2878,29 @@
 
   if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_WARN_CC_OP_NOT_ESCAPED)) {
-    UChar buf[WARN_BUFSIZE];
-    onig_snprintf_with_pattern(buf, WARN_BUFSIZE, env->enc,
-		env->pattern, env->pattern_end,
-		(UChar* )"regular expression has '%s' without escape", c);
-    (*onig_warn)((char* )buf);
-  }
+    onig_syntax_warn(env, "regular expression has '%s' without escape", c);
+  }
+}
+
+#ifndef RTEST
+# define RTEST(v)  1
+#endif
+
+static void
+CC_DUP_WARN(ScanEnv *env)
+{
+  if (onig_warn == onig_null_warn || !RTEST(ruby_verbose)) return ;
+
+  if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_WARN_CC_DUP) &&
+      !(env->warnings_flag & ONIG_SYN_WARN_CC_DUP)) {
+    env->warnings_flag |= ONIG_SYN_WARN_CC_DUP;
+    onig_syntax_warn(env, "character class has duplicated range");
+  }
+}
+
+static void
+UNKNOWN_ESC_WARN(ScanEnv *env, int c)
+{
+  if (onig_warn == onig_null_warn || !RTEST(ruby_verbose)) return ;
+  onig_syntax_warn(env, "Unknown escape \\%c is ignored", c);
 }
 
@@ -2934,10 +2916,10 @@
   while (p < to) {
     x = ONIGENC_MBC_TO_CODE(enc, p, to);
-    q = p + enclen(enc, p);
+    q = p + enclen(enc, p, to);
     if (x == s[0]) {
       for (i = 1; i < n && q < to; i++) {
 	x = ONIGENC_MBC_TO_CODE(enc, q, to);
 	if (x != s[i]) break;
-	q += enclen(enc, q);
+	q += enclen(enc, q, to);
       }
       if (i >= n) {
@@ -2954,5 +2936,5 @@
 static int
 str_exist_check_with_esc(OnigCodePoint s[], int n, UChar* from, UChar* to,
-		 OnigCodePoint bad, OnigEncoding enc, OnigSyntaxType* syn)
+		 OnigCodePoint bad, OnigEncoding enc, const OnigSyntaxType* syn)
 {
   int i, in_esc;
@@ -2965,17 +2947,17 @@
     if (in_esc) {
       in_esc = 0;
-      p += enclen(enc, p);
+      p += enclen(enc, p, to);
     }
     else {
       x = ONIGENC_MBC_TO_CODE(enc, p, to);
-      q = p + enclen(enc, p);
+      q = p + enclen(enc, p, to);
       if (x == s[0]) {
 	for (i = 1; i < n && q < to; i++) {
 	  x = ONIGENC_MBC_TO_CODE(enc, q, to);
 	  if (x != s[i]) break;
-	  q += enclen(enc, q);
+	  q += enclen(enc, q, to);
 	}
 	if (i >= n) return 1;
-	p += enclen(enc, p);
+	p += enclen(enc, p, to);
       }
       else {
@@ -2995,5 +2977,5 @@
   int num;
   OnigCodePoint c, c2;
-  OnigSyntaxType* syn = env->syntax;
+  const OnigSyntaxType* syn = env->syntax;
   OnigEncoding enc = env->enc;
   UChar* prev;
@@ -3073,4 +3055,6 @@
     case 'p':
     case 'P':
+      if (PEND) break;
+
       c2 = PPEEK;
       if (c2 == '{' &&
@@ -3080,5 +3064,5 @@
 	tok->u.prop.not = (c == 'P' ? 1 : 0);
 
-	if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT)) {
+	if (!PEND && IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT)) {
 	  PFETCH(c2);
 	  if (c2 == '^') {
@@ -3089,4 +3073,7 @@
 	}
       }
+      else {
+	onig_syntax_warn(env, "invalid Unicode Property \\%c", c);
+      }
       break;
 
@@ -3100,10 +3087,10 @@
 	if (num < 0) return ONIGERR_TOO_BIG_WIDE_CHAR_VALUE;
 	if (!PEND) {
-          c2 = PPEEK;
-          if (ONIGENC_IS_CODE_XDIGIT(enc, c2))
-            return ONIGERR_TOO_LONG_WIDE_CHAR_VALUE;
-        }
-
-	if (p > prev + enclen(enc, prev) && !PEND && (PPEEK_IS('}'))) {
+	  c2 = PPEEK;
+	  if (ONIGENC_IS_CODE_XDIGIT(enc, c2))
+	    return ONIGERR_TOO_LONG_WIDE_CHAR_VALUE;
+	}
+
+	if (p > prev + enclen(enc, prev, end) && !PEND && (PPEEK_IS('}'))) {
 	  PINC;
 	  tok->type   = TK_CODE_POINT;
@@ -3142,4 +3129,31 @@
 	tok->base   = 16;
 	tok->u.code = (OnigCodePoint )num;
+      }
+      break;
+
+    case 'o':
+      if (PEND) break;
+
+      prev = p;
+      if (PPEEK_IS('{') && IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_O_BRACE_OCTAL)) {
+	PINC;
+	num = scan_unsigned_octal_number(&p, end, 11, enc);
+	if (num < 0) return ONIGERR_TOO_BIG_WIDE_CHAR_VALUE;
+	if (!PEND) {
+	  c2 = PPEEK;
+	  if (ONIGENC_IS_CODE_DIGIT(enc, c2) && c2 < '8')
+	    return ONIGERR_TOO_LONG_WIDE_CHAR_VALUE;
+	}
+
+	if (p > prev + enclen(enc, prev, end) && !PEND && (PPEEK_IS('}'))) {
+	  PINC;
+	  tok->type   = TK_CODE_POINT;
+	  tok->base   = 8;
+	  tok->u.code = (OnigCodePoint )num;
+	}
+	else {
+	  /* can't read nothing or invalid format */
+	  p = prev;
+	}
       }
       break;
@@ -3163,8 +3177,8 @@
     default:
       PUNFETCH;
-      num = fetch_escaped_value(&p, end, env);
+      num = fetch_escaped_value(&p, end, env, &c2);
       if (num < 0) return num;
-      if (tok->u.c != num) {
-	tok->u.code = (OnigCodePoint )num;
+      if ((OnigCodePoint )tok->u.c != c2) {
+	tok->u.code = (OnigCodePoint )c2;
 	tok->type   = TK_CODE_POINT;
       }
@@ -3215,5 +3229,5 @@
 {
   int r, num;
-  OnigSyntaxType* syn = env->syntax;
+  const OnigSyntaxType* syn = env->syntax;
   UChar* prev;
   UChar* p = *src;
@@ -3224,5 +3238,5 @@
   prev = p;
 
-#ifdef USE_BACKREF_WITH_LEVEL
+# ifdef USE_BACKREF_WITH_LEVEL
   name_end = NULL_UCHARP; /* no need. escape gcc warning. */
   r = fetch_name_with_level(c, &p, end, &name_end,
@@ -3230,7 +3244,7 @@
   if (r == 1) tok->u.backref.exist_level = 1;
   else        tok->u.backref.exist_level = 0;
-#else
+# else
   r = fetch_name(&p, end, &name_end, env, &back_num, 1);
-#endif
+# endif
   if (r < 0) return r;
 
@@ -3270,5 +3284,5 @@
     tok->type = TK_BACKREF;
     tok->u.backref.by_name = 1;
-    if (num == 1) {
+    if (num == 1 || IS_SYNTAX_BV(syn, ONIG_SYN_USE_LEFT_MOST_NAMED_GROUP)) {
       tok->u.backref.num  = 1;
       tok->u.backref.ref1 = backs[0];
@@ -3290,5 +3304,5 @@
   OnigCodePoint c;
   OnigEncoding enc = env->enc;
-  OnigSyntaxType* syn = env->syntax;
+  const OnigSyntaxType* syn = env->syntax;
   UChar* prev;
   UChar* p = *src;
@@ -3523,9 +3537,9 @@
 	if (num < 0) return ONIGERR_TOO_BIG_WIDE_CHAR_VALUE;
 	if (!PEND) {
-          if (ONIGENC_IS_CODE_XDIGIT(enc, PPEEK))
-            return ONIGERR_TOO_LONG_WIDE_CHAR_VALUE;
-        }
-
-	if ((p > prev + enclen(enc, prev)) && !PEND && PPEEK_IS('}')) {
+	  if (ONIGENC_IS_CODE_XDIGIT(enc, PPEEK))
+	    return ONIGERR_TOO_LONG_WIDE_CHAR_VALUE;
+	}
+
+	if ((p > prev + enclen(enc, prev, end)) && !PEND && PPEEK_IS('}')) {
 	  PINC;
 	  tok->type   = TK_CODE_POINT;
@@ -3566,4 +3580,30 @@
       break;
 
+    case 'o':
+      if (PEND) break;
+
+      prev = p;
+      if (PPEEK_IS('{') && IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_O_BRACE_OCTAL)) {
+	PINC;
+	num = scan_unsigned_octal_number(&p, end, 11, enc);
+	if (num < 0) return ONIGERR_TOO_BIG_WIDE_CHAR_VALUE;
+	if (!PEND) {
+	  OnigCodePoint c = PPEEK;
+	  if (ONIGENC_IS_CODE_DIGIT(enc, c) && c < '8')
+	    return ONIGERR_TOO_LONG_WIDE_CHAR_VALUE;
+	}
+
+	if ((p > prev + enclen(enc, prev, end)) && !PEND && PPEEK_IS('}')) {
+	  PINC;
+	  tok->type   = TK_CODE_POINT;
+	  tok->u.code = (OnigCodePoint )num;
+	}
+	else {
+	  /* can't read nothing or invalid format */
+	  p = prev;
+	}
+      }
+      break;
+
     case '1': case '2': case '3': case '4':
     case '5': case '6': case '7': case '8': case '9':
@@ -3572,5 +3612,5 @@
       num = onig_scan_unsigned_number(&p, end, enc);
       if (num < 0 || num > ONIG_MAX_BACKREF_NUM) {
-        goto skip_backref;
+	goto skip_backref;
       }
 
@@ -3605,5 +3645,5 @@
 	prev = p;
 	num = scan_unsigned_octal_number(&p, end, (c == '0' ? 2:3), enc);
-	if (num < 0) return ONIGERR_TOO_BIG_NUMBER;
+	if (num < 0 || 0xff < num) return ONIGERR_TOO_BIG_NUMBER;
 	if (p == prev) {  /* can't read nothing. */
 	  num = 0; /* but, it's not error */
@@ -3620,5 +3660,5 @@
 #ifdef USE_NAMED_GROUP
     case 'k':
-      if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_K_NAMED_BACKREF)) {
+      if (!PEND && IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_K_NAMED_BACKREF)) {
 	PFETCH(c);
 	if (c == '<' || c == '\'') {
@@ -3626,6 +3666,8 @@
 	  if (r < 0) return r;
 	}
-	else
+	else {
 	  PUNFETCH;
+	  onig_syntax_warn(env, "invalid back reference");
+	}
       }
       break;
@@ -3634,6 +3676,6 @@
 #if defined(USE_SUBEXP_CALL) || defined(USE_NAMED_GROUP)
     case 'g':
-#ifdef USE_NAMED_GROUP
-      if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_G_BRACE_BACKREF)) {
+# ifdef USE_NAMED_GROUP
+      if (!PEND && IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_G_BRACE_BACKREF)) {
 	PFETCH(c);
 	if (c == '{') {
@@ -3644,7 +3686,7 @@
 	  PUNFETCH;
       }
-#endif
-#ifdef USE_SUBEXP_CALL
-      if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_G_SUBEXP_CALL)) {
+# endif
+# ifdef USE_SUBEXP_CALL
+      if (!PEND && IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_G_SUBEXP_CALL)) {
 	PFETCH(c);
 	if (c == '<' || c == '\'') {
@@ -3678,8 +3720,10 @@
 	  tok->u.call.rel      = rel;
 	}
-	else
+	else {
+	  onig_syntax_warn(env, "invalid subexp call");
 	  PUNFETCH;
-      }
-#endif
+	}
+      }
+# endif
       break;
 #endif
@@ -3699,5 +3743,5 @@
 	tok->u.prop.not = (c == 'P' ? 1 : 0);
 
-	if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT)) {
+	if (!PEND && IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT)) {
 	  PFETCH(c);
 	  if (c == '^') {
@@ -3708,4 +3752,7 @@
 	}
       }
+      else {
+	onig_syntax_warn(env, "invalid Unicode Property \\%c", c);
+      }
       break;
 
@@ -3729,14 +3776,18 @@
 
     default:
-      PUNFETCH;
-      num = fetch_escaped_value(&p, end, env);
-      if (num < 0) return num;
-      /* set_raw: */
-      if (tok->u.c != num) {
-	tok->type = TK_CODE_POINT;
-	tok->u.code = (OnigCodePoint )num;
-      }
-      else { /* string */
-	p = tok->backp + enclen(enc, tok->backp);
+      {
+	OnigCodePoint c2;
+
+	PUNFETCH;
+	num = fetch_escaped_value(&p, end, env, &c2);
+	if (num < 0) return num;
+	/* set_raw: */
+	if ((OnigCodePoint )tok->u.c != c2) {
+	  tok->type = TK_CODE_POINT;
+	  tok->u.code = (OnigCodePoint )c2;
+	}
+	else { /* string */
+	  p = tok->backp + enclen(enc, tok->backp, end);
+	}
       }
       break;
@@ -3828,20 +3879,20 @@
     case '(':
       if (PPEEK_IS('?') &&
-          IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_QMARK_GROUP_EFFECT)) {
-        PINC;
-        if (PPEEK_IS('#')) {
-          PFETCH(c);
-          while (1) {
-            if (PEND) return ONIGERR_END_PATTERN_IN_GROUP;
-            PFETCH(c);
-            if (c == MC_ESC(syn)) {
-              if (!PEND) PFETCH(c);
-            }
-            else {
-              if (c == ')') break;
-            }
-          }
-          goto start;
-        }
+	  IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_QMARK_GROUP_EFFECT)) {
+	PINC;
+	if (PPEEK_IS('#')) {
+	  PFETCH(c);
+	  while (1) {
+	    if (PEND) return ONIGERR_END_PATTERN_IN_GROUP;
+	    PFETCH(c);
+	    if (c == MC_ESC(syn)) {
+	      if (!PEND) PFETCH(c);
+	    }
+	    else {
+	      if (c == ')') break;
+	    }
+	  }
+	  goto start;
+	}
 #ifdef USE_PERL_SUBEXP_CALL
 	/* (?&name), (?n), (?R), (?0), (?+n), (?-n) */
@@ -3914,4 +3965,5 @@
 
 	  PINC;     /* skip 'P' */
+	  if (PEND) return ONIGERR_UNDEFINED_GROUP_OPTION;
 	  PFETCH(c);
 	  if (c == '=') {       /* (?P=name): backref */
@@ -3932,8 +3984,7 @@
 	    break;
 	  }
-	  PUNFETCH;
 	}
 #endif /* USE_CAPITAL_P_NAMED_GROUP */
-        PUNFETCH;
+	PUNFETCH;
       }
 
@@ -4003,5 +4054,5 @@
 static int
 add_ctype_to_cc_by_range(CClassNode* cc, int ctype ARG_UNUSED, int not,
-			 OnigEncoding enc ARG_UNUSED,
+                         ScanEnv* env,
                          OnigCodePoint sb_out, const OnigCodePoint mbr[])
 {
@@ -4013,9 +4064,9 @@
   if (not == 0) {
     for (i = 0; i < n; i++) {
-      for (j  = ONIGENC_CODE_RANGE_FROM(mbr, i);
-           j <= ONIGENC_CODE_RANGE_TO(mbr, i); j++) {
+      for (j = ONIGENC_CODE_RANGE_FROM(mbr, i);
+	  j <= ONIGENC_CODE_RANGE_TO(mbr, i); j++) {
 	if (j >= sb_out) {
 	  if (j > ONIGENC_CODE_RANGE_FROM(mbr, i)) {
-	    r = add_code_range_to_buf(&(cc->mbuf), j,
+	    r = add_code_range_to_buf(&(cc->mbuf), env, j,
 				      ONIGENC_CODE_RANGE_TO(mbr, i));
 	    if (r != 0) return r;
@@ -4025,5 +4076,5 @@
 	  goto sb_end;
 	}
-        BITSET_SET_BIT(cc->bs, j);
+	BITSET_SET_BIT_CHKDUP(cc->bs, j);
       }
     }
@@ -4031,5 +4082,5 @@
   sb_end:
     for ( ; i < n; i++) {
-      r = add_code_range_to_buf(&(cc->mbuf),
+      r = add_code_range_to_buf(&(cc->mbuf), env,
                                 ONIGENC_CODE_RANGE_FROM(mbr, i),
                                 ONIGENC_CODE_RANGE_TO(mbr, i));
@@ -4046,10 +4097,10 @@
 	  goto sb_end2;
 	}
-	BITSET_SET_BIT(cc->bs, j);
+	BITSET_SET_BIT_CHKDUP(cc->bs, j);
       }
       prev = ONIGENC_CODE_RANGE_TO(mbr, i) + 1;
     }
     for (j = prev; j < sb_out; j++) {
-      BITSET_SET_BIT(cc->bs, j);
+      BITSET_SET_BIT_CHKDUP(cc->bs, j);
     }
 
@@ -4059,5 +4110,5 @@
     for (i = 0; i < n; i++) {
       if (prev < ONIGENC_CODE_RANGE_FROM(mbr, i)) {
-	r = add_code_range_to_buf(&(cc->mbuf), prev,
+	r = add_code_range_to_buf(&(cc->mbuf), env, prev,
                                   ONIGENC_CODE_RANGE_FROM(mbr, i) - 1);
 	if (r != 0) return r;
@@ -4066,5 +4117,5 @@
     }
     if (prev < 0x7fffffff) {
-      r = add_code_range_to_buf(&(cc->mbuf), prev, 0x7fffffff);
+      r = add_code_range_to_buf(&(cc->mbuf), env, prev, 0x7fffffff);
       if (r != 0) return r;
     }
@@ -4088,9 +4139,9 @@
       CClassNode ccwork;
       initialize_cclass(&ccwork);
-      r = add_ctype_to_cc_by_range(&ccwork, ctype, not, env->enc, sb_out,
+      r = add_ctype_to_cc_by_range(&ccwork, ctype, not, env, sb_out,
 				   ranges);
       if (r == 0) {
 	if (not) {
-	  r = add_code_range_to_buf(&(ccwork.mbuf), 0x80, ONIG_LAST_CODE_POINT);
+	  r = add_code_range_to_buf0(&(ccwork.mbuf), env, 0x80, ONIG_LAST_CODE_POINT, FALSE);
 	}
 	else {
@@ -4098,14 +4149,17 @@
 	  initialize_cclass(&ccascii);
 	  if (ONIGENC_MBC_MINLEN(env->enc) > 1) {
-	    add_code_range(&(ccascii.mbuf), env, 0x00, 0x7F);
+	    r = add_code_range(&(ccascii.mbuf), env, 0x00, 0x7F);
 	  }
 	  else {
-	    bitset_set_range(ccascii.bs, 0x00, 0x7F);
+	    bitset_set_range(env, ccascii.bs, 0x00, 0x7F);
+	    r = 0;
 	  }
-	  r = and_cclass(&ccwork, &ccascii, enc);
+	  if (r == 0) {
+	    r = and_cclass(&ccwork, &ccascii, env);
+	  }
 	  if (IS_NOT_NULL(ccascii.mbuf)) bbuf_free(ccascii.mbuf);
 	}
 	if (r == 0) {
-	  r = or_cclass(cc, &ccwork, enc);
+	  r = or_cclass(cc, &ccwork, env);
 	}
 	if (IS_NOT_NULL(ccwork.mbuf)) bbuf_free(ccwork.mbuf);
@@ -4113,5 +4167,5 @@
     }
     else {
-      r = add_ctype_to_cc_by_range(cc, ctype, not, env->enc, sb_out, ranges);
+      r = add_ctype_to_cc_by_range(cc, ctype, not, env, sb_out, ranges);
     }
     return r;
@@ -4138,5 +4192,5 @@
       for (c = 0; c < SINGLE_BYTE_SIZE; c++) {
 	if (! ONIGENC_IS_CODE_CTYPE(enc, (OnigCodePoint )c, ctype))
-	  BITSET_SET_BIT(cc->bs, c);
+	  BITSET_SET_BIT_CHKDUP(cc->bs, c);
       }
       ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf);
@@ -4145,5 +4199,5 @@
       for (c = 0; c < SINGLE_BYTE_SIZE; c++) {
 	if (ONIGENC_IS_CODE_CTYPE(enc, (OnigCodePoint )c, ctype))
-	  BITSET_SET_BIT(cc->bs, c);
+	  BITSET_SET_BIT_CHKDUP(cc->bs, c);
       }
     }
@@ -4156,16 +4210,16 @@
 	if (! ONIGENC_IS_CODE_CTYPE(enc, (OnigCodePoint )c, ctype)
 	    || c >= maxcode)
-	  BITSET_SET_BIT(cc->bs, c);
+	  BITSET_SET_BIT_CHKDUP(cc->bs, c);
       }
       if (ascii_range)
-        ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf);
+	ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf);
     }
     else {
       for (c = 0; c < maxcode; c++) {
 	if (ONIGENC_IS_CODE_CTYPE(enc, (OnigCodePoint )c, ctype))
-	  BITSET_SET_BIT(cc->bs, c);
+	  BITSET_SET_BIT_CHKDUP(cc->bs, c);
       }
       if (! ascii_range)
-        ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf);
+	ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf);
     }
     break;
@@ -4174,17 +4228,17 @@
     if (not == 0) {
       for (c = 0; c < maxcode; c++) {
-	if (ONIGENC_IS_CODE_WORD(enc, c)) BITSET_SET_BIT(cc->bs, c);
+	if (ONIGENC_IS_CODE_WORD(enc, c)) BITSET_SET_BIT_CHKDUP(cc->bs, c);
       }
       if (! ascii_range)
-        ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf);
+	ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf);
     }
     else {
       for (c = 0; c < SINGLE_BYTE_SIZE; c++) {
-        if ((ONIGENC_CODE_TO_MBCLEN(enc, c) > 0) /* check invalid code point */
+	if ((ONIGENC_CODE_TO_MBCLEN(enc, c) > 0) /* check invalid code point */
 	    && (! ONIGENC_IS_CODE_WORD(enc, c) || c >= maxcode))
-	  BITSET_SET_BIT(cc->bs, c);
+	  BITSET_SET_BIT_CHKDUP(cc->bs, c);
       }
       if (ascii_range)
-        ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf);
+	ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf);
     }
     break;
@@ -4245,5 +4299,5 @@
       p = (UChar* )onigenc_step(enc, p, end, pb->len);
       if (onigenc_with_ascii_strncmp(enc, p, end, (UChar* )":]", 2) != 0)
-        return ONIGERR_INVALID_POSIX_BRACKET_TYPE;
+	return ONIGERR_INVALID_POSIX_BRACKET_TYPE;
 
       r = add_ctype_to_cc(cc, pb->ctype, not, ascii_range, env);
@@ -4276,5 +4330,5 @@
       PFETCH_S(c);
       if (c == ']')
-        return ONIGERR_INVALID_POSIX_BRACKET_TYPE;
+	return ONIGERR_INVALID_POSIX_BRACKET_TYPE;
     }
   }
@@ -4356,5 +4410,5 @@
 static int
 next_state_class(CClassNode* cc, CClassNode* asc_cc,
-	         OnigCodePoint* vs, enum CCVALTYPE* type,
+		 OnigCodePoint* vs, enum CCVALTYPE* type,
 		 enum CCSTATE* state, ScanEnv* env)
 {
@@ -4366,5 +4420,5 @@
   if (*state == CCS_VALUE && *type != CCV_CLASS) {
     if (*type == CCV_SB) {
-      BITSET_SET_BIT(cc->bs, (int )(*vs));
+      BITSET_SET_BIT_CHKDUP(cc->bs, (int )(*vs));
       if (IS_NOT_NULL(asc_cc))
 	BITSET_SET_BIT(asc_cc->bs, (int )(*vs));
@@ -4374,5 +4428,5 @@
       if (r < 0) return r;
       if (IS_NOT_NULL(asc_cc)) {
-	r = add_code_range(&(asc_cc->mbuf), env, *vs, *vs);
+	r = add_code_range0(&(asc_cc->mbuf), env, *vs, *vs, 0);
 	if (r < 0) return r;
       }
@@ -4387,6 +4441,6 @@
 static int
 next_state_val(CClassNode* cc, CClassNode* asc_cc,
-	       OnigCodePoint *vs, OnigCodePoint v,
-	       int* vs_israw, int v_israw,
+	       OnigCodePoint *from, OnigCodePoint to,
+	       int* from_israw, int to_israw,
 	       enum CCVALTYPE intype, enum CCVALTYPE* type,
 	       enum CCSTATE* state, ScanEnv* env)
@@ -4397,13 +4451,13 @@
   case CCS_VALUE:
     if (*type == CCV_SB) {
-      BITSET_SET_BIT(cc->bs, (int )(*vs));
+      BITSET_SET_BIT_CHKDUP(cc->bs, (int )(*from));
       if (IS_NOT_NULL(asc_cc))
-	BITSET_SET_BIT(asc_cc->bs, (int )(*vs));
+	BITSET_SET_BIT(asc_cc->bs, (int )(*from));
     }
     else if (*type == CCV_CODE_POINT) {
-      r = add_code_range(&(cc->mbuf), env, *vs, *vs);
+      r = add_code_range(&(cc->mbuf), env, *from, *from);
       if (r < 0) return r;
       if (IS_NOT_NULL(asc_cc)) {
-	r = add_code_range(&(asc_cc->mbuf), env, *vs, *vs);
+	r = add_code_range0(&(asc_cc->mbuf), env, *from, *from, 0);
 	if (r < 0) return r;
       }
@@ -4414,8 +4468,8 @@
     if (intype == *type) {
       if (intype == CCV_SB) {
-        if (*vs > 0xff || v > 0xff)
-          return ONIGERR_INVALID_CODE_POINT_VALUE;
-
-	if (*vs > v) {
+	if (*from > 0xff || to > 0xff)
+	  return ONIGERR_INVALID_CODE_POINT_VALUE;
+
+	if (*from > to) {
 	  if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC))
 	    goto ccs_range_end;
@@ -4423,13 +4477,13 @@
 	    return ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS;
 	}
-	bitset_set_range(cc->bs, (int )*vs, (int )v);
+	bitset_set_range(env, cc->bs, (int )*from, (int )to);
 	if (IS_NOT_NULL(asc_cc))
-	  bitset_set_range(asc_cc->bs, (int )*vs, (int )v);
+	  bitset_set_range(env, asc_cc->bs, (int )*from, (int )to);
       }
       else {
-	r = add_code_range(&(cc->mbuf), env, *vs, v);
+	r = add_code_range(&(cc->mbuf), env, *from, to);
 	if (r < 0) return r;
 	if (IS_NOT_NULL(asc_cc)) {
-	  r = add_code_range(&(asc_cc->mbuf), env, *vs, v);
+	  r = add_code_range0(&(asc_cc->mbuf), env, *from, to, 0);
 	  if (r < 0) return r;
 	}
@@ -4437,26 +4491,18 @@
     }
     else {
-#if 0
-      if (intype == CCV_CODE_POINT && *type == CCV_SB) {
-#endif
-	if (*vs > v) {
-	  if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC))
-	    goto ccs_range_end;
-	  else
-	    return ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS;
-	}
-	bitset_set_range(cc->bs, (int )*vs, (int )(v < 0xff ? v : 0xff));
-	r = add_code_range(&(cc->mbuf), env, (OnigCodePoint )*vs, v);
+      if (*from > to) {
+	if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC))
+	  goto ccs_range_end;
+	else
+	  return ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS;
+      }
+      bitset_set_range(env, cc->bs, (int )*from, (int )(to < 0xff ? to : 0xff));
+      r = add_code_range(&(cc->mbuf), env, (OnigCodePoint )*from, to);
+      if (r < 0) return r;
+      if (IS_NOT_NULL(asc_cc)) {
+	bitset_set_range(env, asc_cc->bs, (int )*from, (int )(to < 0xff ? to : 0xff));
+	r = add_code_range0(&(asc_cc->mbuf), env, (OnigCodePoint )*from, to, 0);
 	if (r < 0) return r;
-	if (IS_NOT_NULL(asc_cc)) {
-	  bitset_set_range(asc_cc->bs, (int )*vs, (int )(v < 0xff ? v : 0xff));
-	  r = add_code_range(&(asc_cc->mbuf), env, (OnigCodePoint )*vs, v);
-	  if (r < 0) return r;
-	}
-#if 0
-      }
-      else
-	return ONIGERR_MISMATCH_CODE_LENGTH_IN_CLASS_RANGE;
-#endif
+      }
     }
   ccs_range_end:
@@ -4473,7 +4519,7 @@
   }
 
-  *vs_israw = v_israw;
-  *vs       = v;
-  *type     = intype;
+  *from_israw = to_israw;
+  *from       = to;
+  *type       = intype;
   return 0;
 }
@@ -4519,6 +4565,9 @@
   int val_israw, in_israw;
 
+  *np = *asc_np = NULL_NODE;
+  env->parse_depth++;
+  if (env->parse_depth > ParseDepthLimit)
+    return ONIGERR_PARSE_DEPTH_LIMIT_OVER;
   prev_cc = asc_prev_cc = (CClassNode* )NULL;
-  *np = *asc_np = NULL_NODE;
   r = fetch_token_in_cc(tok, src, end, env);
   if (r == TK_CHAR && tok->u.c == '^' && tok->escaped == 0) {
@@ -4602,5 +4651,5 @@
 	}
 
-	len = enclen(env->enc, buf);
+	len = enclen(env->enc, buf, buf + i);
 	if (i < len) {
 	  r = ONIGERR_TOO_SHORT_MULTI_BYTE_STRING;
@@ -4610,5 +4659,6 @@
 	  p = psave;
 	  for (i = 1; i < len; i++) {
-	    r = fetch_token_in_cc(tok, &p, end, env);
+	    (void)fetch_token_in_cc(tok, &p, end, env);
+	    /* no need to check the retun value (already checked above) */
 	  }
 	  fetched = 0;
@@ -4710,4 +4760,10 @@
 	  goto range_end_val;
 	}
+
+	if (val_type == CCV_CLASS) {
+	  r = ONIGERR_UNMATCHED_RANGE_SPECIFIER_IN_CHAR_CLASS;
+	  goto err;
+	}
+
 	state = CCS_RANGE;
       }
@@ -4757,9 +4813,9 @@
 	if (r == 0) {
 	  acc = NCCLASS(anode);
-	  r = or_cclass(cc, acc, env->enc);
+	  r = or_cclass(cc, acc, env);
 	}
 	if (r == 0 && IS_NOT_NULL(aasc_node)) {
 	  acc = NCCLASS(aasc_node);
-	  r = or_cclass(asc_cc, acc, env->enc);
+	  r = or_cclass(asc_cc, acc, env);
 	}
 	onig_node_free(anode);
@@ -4781,9 +4837,9 @@
 
 	if (IS_NOT_NULL(prev_cc)) {
-	  r = and_cclass(prev_cc, cc, env->enc);
+	  r = and_cclass(prev_cc, cc, env);
 	  if (r != 0) goto err;
 	  bbuf_free(cc->mbuf);
 	  if (IS_NOT_NULL(asc_cc)) {
-	    r = and_cclass(asc_prev_cc, asc_cc, env->enc);
+	    r = and_cclass(asc_prev_cc, asc_cc, env);
 	    if (r != 0) goto err;
 	    bbuf_free(asc_cc->mbuf);
@@ -4829,10 +4885,10 @@
 
   if (IS_NOT_NULL(prev_cc)) {
-    r = and_cclass(prev_cc, cc, env->enc);
+    r = and_cclass(prev_cc, cc, env);
     if (r != 0) goto err;
     bbuf_free(cc->mbuf);
     cc = prev_cc;
     if (IS_NOT_NULL(asc_cc)) {
-      r = and_cclass(asc_prev_cc, asc_cc, env->enc);
+      r = and_cclass(asc_prev_cc, asc_cc, env);
       if (r != 0) goto err;
       bbuf_free(asc_cc->mbuf);
@@ -4863,14 +4919,15 @@
 
       if (ONIGENC_IS_CODE_NEWLINE(env->enc, NEWLINE_CODE)) {
-        if (ONIGENC_CODE_TO_MBCLEN(env->enc, NEWLINE_CODE) == 1)
-          BITSET_SET_BIT(cc->bs, NEWLINE_CODE);
-        else {
-          r = add_code_range(&(cc->mbuf), env, NEWLINE_CODE, NEWLINE_CODE);
-          if (r < 0) goto err;
-        }
+	if (ONIGENC_CODE_TO_MBCLEN(env->enc, NEWLINE_CODE) == 1)
+	  BITSET_SET_BIT_CHKDUP(cc->bs, NEWLINE_CODE);
+	else {
+	  r = add_code_range(&(cc->mbuf), env, NEWLINE_CODE, NEWLINE_CODE);
+	  if (r < 0) goto err;
+	}
       }
     }
   }
   *src = p;
+  env->parse_depth--;
   return 0;
 
@@ -4933,4 +4990,12 @@
       *np = node_new_enclose(ENCLOSE_STOP_BACKTRACK);
       break;
+    case '~':   /* (?~...) absent operator */
+      if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_TILDE_ABSENT)) {
+	*np = node_new_enclose(ENCLOSE_ABSENT);
+      }
+      else {
+	return ONIGERR_UNDEFINED_GROUP_OPTION;
+      }
+      break;
 
 #ifdef USE_NAMED_GROUP
@@ -4943,7 +5008,8 @@
       break;
 
-#ifdef USE_CAPITAL_P_NAMED_GROUP
+# ifdef USE_CAPITAL_P_NAMED_GROUP
     case 'P':   /* (?P<name>...) */
-      if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_CAPITAL_P_NAMED_GROUP)) {
+      if (!PEND &&
+	  IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_CAPITAL_P_NAMED_GROUP)) {
 	PFETCH(c);
 	if (c == '<') goto named_group1;
@@ -4951,8 +5017,9 @@
       return ONIGERR_UNDEFINED_GROUP_OPTION;
       break;
+# endif
 #endif
-#endif
 
     case '<':   /* look behind (?<=...), (?<!...) */
+      if (PEND) return ONIGERR_END_PATTERN_WITH_UNMATCHED_PARENTHESIS;
       PFETCH(c);
       if (c == '=')
@@ -4972,5 +5039,7 @@
 	  list_capture = 0;
 
+# ifdef USE_CAPTURE_HISTORY
 	named_group2:
+# endif
 	  name = p;
 	  r = fetch_name((OnigCodePoint )c, &p, end, &name_end, env, &num, 0);
@@ -5002,8 +5071,10 @@
       break;
 
+#ifdef USE_CAPTURE_HISTORY
     case '@':
       if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_ATMARK_CAPTURE_HISTORY)) {
-#ifdef USE_NAMED_GROUP
-	if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP)) {
+# ifdef USE_NAMED_GROUP
+	if (!PEND &&
+	    IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP)) {
 	  PFETCH(c);
 	  if (c == '<' || c == '\'') {
@@ -5013,5 +5084,5 @@
 	  PUNFETCH;
 	}
-#endif
+# endif
 	*np = node_new_enclose_memory(env->option, 0);
 	CHECK_NULL_RETURN_MEMERR(*np);
@@ -5028,7 +5099,9 @@
       }
       break;
+#endif /* USE_CAPTURE_HISTORY */
 
     case '(':   /* conditional expression: (?(cond)yes), (?(cond)yes|no) */
-      if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_LPAREN_CONDITION)) {
+      if (!PEND &&
+	  IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_LPAREN_CONDITION)) {
 	UChar *name = NULL;
 	UChar *name_end;
@@ -5048,5 +5121,5 @@
 	  if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_STRICT_CHECK_BACKREF)) {
 	    if (num > env->num_mem ||
-	        IS_NULL(SCANENV_MEM_NODES(env)[num]))
+		IS_NULL(SCANENV_MEM_NODES(env)[num]))
 	    return ONIGERR_INVALID_BACKREF;
 	  }
@@ -5054,28 +5127,21 @@
 #ifdef USE_NAMED_GROUP
 	else if (c == '<' || c == '\'') {    /* (<name>), ('name') */
-	  int nums;
-	  int *backs;
-
 	  name = p;
-	  r = fetch_name((OnigCodePoint )c, &p, end, &name_end, env, &num, 0);
+	  r = fetch_named_backref_token(c, tok, &p, end, env);
 	  if (r < 0) return r;
-	  PFETCH(c);
-	  if (c != ')') return ONIGERR_UNDEFINED_GROUP_OPTION;
-
-	  nums = onig_name_to_group_numbers(env->reg, name, name_end, &backs);
-	  if (nums <= 0) {
-	    onig_scan_env_set_error_string(env,
-		     ONIGERR_UNDEFINED_NAME_REFERENCE, name, name_end);
-	    return ONIGERR_UNDEFINED_NAME_REFERENCE;
+	  if (!PPEEK_IS(')')) return ONIGERR_UNDEFINED_GROUP_OPTION;
+	  PINC;
+
+	  if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_USE_LEFT_MOST_NAMED_GROUP)) {
+	    num = tok->u.backref.ref1;
 	  }
-	  if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_STRICT_CHECK_BACKREF)) {
-	    int i;
-	    for (i = 0; i < nums; i++) {
-	      if (backs[i] > env->num_mem ||
-		  IS_NULL(SCANENV_MEM_NODES(env)[backs[i]]))
-	      return ONIGERR_INVALID_BACKREF;
-	    }
+	  else {
+	    /* FIXME:
+	     * Use left most named group for now. This is the same as Perl.
+	     * However this should use the same strategy as normal back-
+	     * references on Ruby syntax; search right to left. */
+	    int len = tok->u.backref.num;
+	    num = len > 1 ? tok->u.backref.refs[0] : tok->u.backref.ref1;
 	  }
-	  num = backs[0];       /* XXX: use left most named group as Perl */
 	}
 #endif
@@ -5102,5 +5168,5 @@
 
     case '^':   /* loads default options */
-      if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL)) {
+      if (!PEND && IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL)) {
 	/* d-imsx */
 	ONOFF(option, ONIG_OPTION_ASCII_RANGE, 1);
@@ -5112,5 +5178,5 @@
       }
 #if 0
-      else if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_RUBY)) {
+      else if (!PEND && IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_RUBY)) {
 	/* d-imx */
 	ONOFF(option, ONIG_OPTION_ASCII_RANGE, 0);
@@ -5170,6 +5236,6 @@
 	  case 'a':     /* limits \d, \s, \w and POSIX brackets to ASCII range */
 	    if ((IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL) ||
-	         IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_RUBY)) &&
-	        (neg == 0)) {
+		 IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_RUBY)) &&
+		(neg == 0)) {
 	      ONOFF(option, ONIG_OPTION_ASCII_RANGE, 0);
 	      ONOFF(option, ONIG_OPTION_POSIX_BRACKET_ALL_RANGE, 1);
@@ -5182,6 +5248,6 @@
 	  case 'u':
 	    if ((IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL) ||
-	         IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_RUBY)) &&
-	        (neg == 0)) {
+		 IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_RUBY)) &&
+		(neg == 0)) {
 	      ONOFF(option, ONIG_OPTION_ASCII_RANGE, 1);
 	      ONOFF(option, ONIG_OPTION_POSIX_BRACKET_ALL_RANGE, 1);
@@ -5194,9 +5260,9 @@
 	  case 'd':
 	    if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL) &&
-	        (neg == 0)) {
+		(neg == 0)) {
 	      ONOFF(option, ONIG_OPTION_ASCII_RANGE, 1);
 	    }
 	    else if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_RUBY) &&
-	        (neg == 0)) {
+		(neg == 0)) {
 	      ONOFF(option, ONIG_OPTION_ASCII_RANGE, 0);
 	      ONOFF(option, ONIG_OPTION_POSIX_BRACKET_ALL_RANGE, 0);
@@ -5228,7 +5294,10 @@
 	    OnigOptionType prev = env->option;
 
-	    env->option     = option;
+	    env->option = option;
 	    r = fetch_token(tok, &p, end, env);
-	    if (r < 0) return r;
+	    if (r < 0) {
+	      env->option = prev;
+	      return r;
+	    }
 	    r = parse_subexp(&target, tok, term, &p, end, env);
 	    env->option = prev;
@@ -5345,34 +5414,27 @@
 
 #ifdef USE_WARNING_REDUNDANT_NESTED_REPEAT_OPERATOR
-      if (!IS_QUANTIFIER_BY_NUMBER(qn) && !IS_QUANTIFIER_BY_NUMBER(qnt) &&
+      if (nestq_num >= 0 && targetq_num >= 0 &&
 	  IS_SYNTAX_BV(env->syntax, ONIG_SYN_WARN_REDUNDANT_NESTED_REPEAT)) {
-        UChar buf[WARN_BUFSIZE];
-
-        switch (ReduceTypeTable[targetq_num][nestq_num]) {
-        case RQ_ASIS:
-          break;
-
-        case RQ_DEL:
-          if (onig_verb_warn != onig_null_warn) {
-            onig_snprintf_with_pattern(buf, WARN_BUFSIZE, env->enc,
-                                 env->pattern, env->pattern_end,
-                                 (UChar* )"redundant nested repeat operator");
-            (*onig_verb_warn)((char* )buf);
-          }
-          goto warn_exit;
-          break;
-
-        default:
-          if (onig_verb_warn != onig_null_warn) {
-            onig_snprintf_with_pattern(buf, WARN_BUFSIZE, env->enc,
-                                       env->pattern, env->pattern_end,
-            (UChar* )"nested repeat operator %s and %s was replaced with '%s'",
-            PopularQStr[targetq_num], PopularQStr[nestq_num],
-            ReduceQStr[ReduceTypeTable[targetq_num][nestq_num]]);
-            (*onig_verb_warn)((char* )buf);
-          }
-          goto warn_exit;
-          break;
-        }
+	switch (ReduceTypeTable[targetq_num][nestq_num]) {
+	case RQ_ASIS:
+	  break;
+
+	case RQ_DEL:
+	  if (onig_warn != onig_null_warn) {
+	    onig_syntax_warn(env, "regular expression has redundant nested repeat operator '%s'",
+		PopularQStr[targetq_num]);
+	  }
+	  goto warn_exit;
+	  break;
+
+	default:
+	  if (onig_warn != onig_null_warn) {
+	    onig_syntax_warn(env, "nested repeat operator '%s' and '%s' was replaced with '%s' in regular expression",
+		PopularQStr[targetq_num], PopularQStr[nestq_num],
+		ReduceQStr[ReduceTypeTable[targetq_num][nestq_num]]);
+	  }
+	  goto warn_exit;
+	  break;
+	}
       }
 
@@ -5402,83 +5464,4 @@
   return 0;
 }
-
-
-#ifdef USE_SHARED_CCLASS_TABLE
-
-#define THRESHOLD_RANGE_NUM_FOR_SHARE_CCLASS     8
-
-/* for ctype node hash table */
-
-typedef struct {
-  OnigEncoding enc;
-  int not;
-  int type;
-} type_cclass_key;
-
-static int type_cclass_cmp(type_cclass_key* x, type_cclass_key* y)
-{
-  if (x->type != y->type) return 1;
-  if (x->enc  != y->enc)  return 1;
-  if (x->not  != y->not)  return 1;
-  return 0;
-}
-
-static int type_cclass_hash(type_cclass_key* key)
-{
-  int i, val;
-  UChar *p;
-
-  val = 0;
-
-  p = (UChar* )&(key->enc);
-  for (i = 0; i < (int )sizeof(key->enc); i++) {
-    val = val * 997 + (int )*p++;
-  }
-
-  p = (UChar* )(&key->type);
-  for (i = 0; i < (int )sizeof(key->type); i++) {
-    val = val * 997 + (int )*p++;
-  }
-
-  val += key->not;
-  return val + (val >> 5);
-}
-
-static struct st_hash_type type_type_cclass_hash = {
-    type_cclass_cmp,
-    type_cclass_hash,
-};
-
-static st_table* OnigTypeCClassTable;
-
-
-static int
-i_free_shared_class(type_cclass_key* key, Node* node, void* arg ARG_UNUSED)
-{
-  if (IS_NOT_NULL(node)) {
-    CClassNode* cc = NCCLASS(node);
-    if (IS_NOT_NULL(cc->mbuf)) xfree(cc->mbuf);
-    xfree(node);
-  }
-
-  if (IS_NOT_NULL(key)) xfree(key);
-  return ST_DELETE;
-}
-
-extern int
-onig_free_shared_cclass_table(void)
-{
-  /* THREAD_ATOMIC_START; */
-  if (IS_NOT_NULL(OnigTypeCClassTable)) {
-    onig_st_foreach(OnigTypeCClassTable, i_free_shared_class, 0);
-    onig_st_free_table(OnigTypeCClassTable);
-    OnigTypeCClassTable = NULL;
-  }
-  /* THREAD_ATOMIC_END; */
-
-  return 0;
-}
-
-#endif /* USE_SHARED_CCLASS_TABLE */
 
 
@@ -5525,5 +5508,5 @@
   CClassNode* asc_cc;
   BitSetRef bs;
-  int add_flag;
+  int add_flag, r;
 
   iarg = (IApplyCaseFoldArg* )arg;
@@ -5552,5 +5535,6 @@
       if (add_flag) {
 	if (ONIGENC_MBC_MINLEN(env->enc) > 1 || *to >= SINGLE_BYTE_SIZE) {
-	  add_code_range(&(cc->mbuf), env, *to, *to);
+	  r = add_code_range0(&(cc->mbuf), env, *to, *to, 0);
+	  if (r < 0) return r;
 	}
 	else {
@@ -5564,5 +5548,6 @@
 	if (ONIGENC_MBC_MINLEN(env->enc) > 1 || *to >= SINGLE_BYTE_SIZE) {
 	  if (IS_NCCLASS_NOT(cc)) clear_not_flag_cclass(cc, env->enc);
-	  add_code_range(&(cc->mbuf), env, *to, *to);
+	  r = add_code_range0(&(cc->mbuf), env, *to, *to, 0);
+	  if (r < 0) return r;
 	}
 	else {
@@ -5654,5 +5639,5 @@
   Node* target2 = NULL;
   CClassNode* cc;
-  int num1, num2;
+  int num1, num2, r;
   UChar buf[ONIGENC_CODE_TO_MBC_MAXLEN * 2];
 
@@ -5670,8 +5655,9 @@
   cc = NCCLASS(right);
   if (ONIGENC_MBC_MINLEN(env->enc) > 1) {
-    add_code_range(&(cc->mbuf), env, 0x0A, 0x0D);
+    r = add_code_range(&(cc->mbuf), env, 0x0A, 0x0D);
+    if (r != 0) goto err;
   }
   else {
-    bitset_set_range(cc->bs, 0x0A, 0x0D);
+    bitset_set_range(env, cc->bs, 0x0A, 0x0D);
   }
 
@@ -5679,6 +5665,8 @@
   if (ONIGENC_IS_UNICODE(env->enc)) {
     /* UTF-8, UTF-16BE/LE, UTF-32BE/LE */
-    add_code_range(&(cc->mbuf), env, 0x85, 0x85);
-    add_code_range(&(cc->mbuf), env, 0x2028, 0x2029);
+    r = add_code_range(&(cc->mbuf), env, 0x85, 0x85);
+    if (r != 0) goto err;
+    r = add_code_range(&(cc->mbuf), env, 0x2028, 0x2029);
+    if (r != 0) goto err;
   }
 
@@ -5707,63 +5695,638 @@
 
 static int
+propname2ctype(ScanEnv* env, const char* propname)
+{
+  UChar* name = (UChar* )propname;
+  int ctype = env->enc->property_name_to_ctype(ONIG_ENCODING_ASCII,
+      name, name + strlen(propname));
+  return ctype;
+}
+
+static int
 node_extended_grapheme_cluster(Node** np, ScanEnv* env)
 {
-  /* same as (?>\P{M}\p{M}*) */
+  Node* tmp = NULL;
   Node* np1 = NULL;
-  Node* np2 = NULL;
-  Node* qn = NULL;
-  Node* list1 = NULL;
+  Node* list = NULL;
   Node* list2 = NULL;
+  Node* alt = NULL;
+  Node* alt2 = NULL;
+  BBuf *pbuf1 = NULL;
   int r = 0;
+  int num1;
+  UChar buf[ONIGENC_CODE_TO_MBC_MAXLEN * 2];
+  OnigOptionType option;
 
 #ifdef USE_UNICODE_PROPERTIES
   if (ONIGENC_IS_UNICODE(env->enc)) {
     /* UTF-8, UTF-16BE/LE, UTF-32BE/LE */
-    CClassNode* cc1;
-    CClassNode* cc2;
-    UChar* propname = (UChar* )"M";
-    int ctype = env->enc->property_name_to_ctype(ONIG_ENCODING_ASCII,
-	propname, propname + 1);
-    if (ctype >= 0) {
-      /* \P{M} */
-      np1 = node_new_cclass();
-      if (IS_NULL(np1)) goto err;
-      cc1 = NCCLASS(np1);
-      r = add_ctype_to_cc(cc1, ctype, 0, 0, env);
+    CClassNode* cc;
+    OnigCodePoint sb_out = (ONIGENC_MBC_MINLEN(env->enc) > 1) ? 0x00 : 0x80;
+    int extend = propname2ctype(env, "Grapheme_Cluster_Break=Extend");
+
+    /* Prepend*
+     * ( RI-sequence | Hangul-Syllable | !Control )
+     * ( Grapheme_Extend | SpacingMark )* */
+
+    /* ( Grapheme_Extend | SpacingMark )* */
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    r = add_ctype_to_cc(cc, extend, 0, 0, env);
+    if (r != 0) goto err;
+    r = add_ctype_to_cc(cc, propname2ctype(env, "Grapheme_Cluster_Break=SpacingMark"), 0, 0, env);
+    if (r != 0) goto err;
+    r = add_code_range(&(cc->mbuf), env, 0x200D, 0x200D);
+    if (r != 0) goto err;
+
+    tmp = node_new_quantifier(0, REPEAT_INFINITE, 0);
+    if (IS_NULL(tmp)) goto err;
+    NQTFR(tmp)->target = np1;
+    np1 = tmp;
+
+    tmp = node_new_list(np1, NULL_NODE);
+    if (IS_NULL(tmp)) goto err;
+    list = tmp;
+    np1 = NULL;
+
+    /* ( RI-sequence | Hangul-Syllable | !Control ) */
+    /* !Control */
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    r = add_ctype_to_cc(cc, propname2ctype(env, "Grapheme_Cluster_Break=Control"), 1, 0, env);
+    if (r != 0) goto err;
+    if (ONIGENC_MBC_MINLEN(env->enc) > 1) {
+      BBuf *pbuf2 = NULL;
+      r = add_code_range(&pbuf1, env, 0x0a, 0x0a);
       if (r != 0) goto err;
-      NCCLASS_SET_NOT(cc1);
-
-      /* \p{M}* */
-      np2 = node_new_cclass();
-      if (IS_NULL(np2)) goto err;
-      cc2 = NCCLASS(np2);
-      r = add_ctype_to_cc(cc2, ctype, 0, 0, env);
+      r = add_code_range(&pbuf1, env, 0x0d, 0x0d);
       if (r != 0) goto err;
-
-      qn = node_new_quantifier(0, REPEAT_INFINITE, 0);
-      if (IS_NULL(qn)) goto err;
-      NQTFR(qn)->target = np2;
-      np2 = NULL;
-
-      /* \P{M}\p{M}* */
-      list2 = node_new_list(qn, NULL_NODE);
-      if (IS_NULL(list2)) goto err;
-      qn = NULL;
-      list1 = node_new_list(np1, list2);
-      if (IS_NULL(list1)) goto err;
-      np1 = NULL;
-      list2 = NULL;
-
-      /* (?>...) */
-      *np = node_new_enclose(ENCLOSE_STOP_BACKTRACK);
-      if (IS_NULL(*np)) goto err;
-      NENCLOSE(*np)->target = list1;
-      return ONIG_NORMAL;
-    }
-  }
-#endif /* USE_UNICODE_PROPERTIES */
-  if (IS_NULL(*np)) {
+      r = and_code_range_buf(cc->mbuf, 0, pbuf1, 1, &pbuf2, env);
+      if (r != 0) {
+	bbuf_free(pbuf2);
+	goto err;
+      }
+      bbuf_free(pbuf1);
+      pbuf1 = NULL;
+      bbuf_free(cc->mbuf);
+      cc->mbuf = pbuf2;
+    }
+    else {
+      BITSET_CLEAR_BIT(cc->bs, 0x0a);
+      BITSET_CLEAR_BIT(cc->bs, 0x0d);
+    }
+
+    tmp = onig_node_new_alt(np1, NULL_NODE);
+    if (IS_NULL(tmp)) goto err;
+    alt = tmp;
+    np1 = NULL;
+
+    /* Hangul-Syllable
+     *  := L* V+ T*
+     *  | L* LV V* T*
+     *  | L* LVT T*
+     *  | L+
+     *  | T+ */
+
+    /* T+ */
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    r = add_ctype_to_cc(cc, propname2ctype(env, "Grapheme_Cluster_Break=T"), 0, 0, env);
+    if (r != 0) goto err;
+
+    tmp = node_new_quantifier(1, REPEAT_INFINITE, 0);
+    if (IS_NULL(tmp)) goto err;
+    NQTFR(tmp)->target = np1;
+    np1 = tmp;
+
+    tmp = onig_node_new_alt(np1, alt);
+    if (IS_NULL(tmp)) goto err;
+    alt = tmp;
+    np1 = NULL;
+
+    /* L+ */
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    r = add_ctype_to_cc(cc, propname2ctype(env, "Grapheme_Cluster_Break=L"), 0, 0, env);
+    if (r != 0) goto err;
+
+    tmp = node_new_quantifier(1, REPEAT_INFINITE, 0);
+    if (IS_NULL(tmp)) goto err;
+    NQTFR(tmp)->target = np1;
+    np1 = tmp;
+
+    tmp = onig_node_new_alt(np1, alt);
+    if (IS_NULL(tmp)) goto err;
+    alt = tmp;
+    np1 = NULL;
+
+    /* L* LVT T* */
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    r = add_ctype_to_cc(cc, propname2ctype(env, "Grapheme_Cluster_Break=T"), 0, 0, env);
+    if (r != 0) goto err;
+
+    tmp = node_new_quantifier(0, REPEAT_INFINITE, 0);
+    if (IS_NULL(tmp)) goto err;
+    NQTFR(tmp)->target = np1;
+    np1 = tmp;
+
+    tmp = node_new_list(np1, NULL_NODE);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    r = add_ctype_to_cc(cc, propname2ctype(env, "Grapheme_Cluster_Break=LVT"), 0, 0, env);
+    if (r != 0) goto err;
+
+    tmp = node_new_list(np1, list2);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    r = add_ctype_to_cc(cc, propname2ctype(env, "Grapheme_Cluster_Break=L"), 0, 0, env);
+    if (r != 0) goto err;
+
+    tmp = node_new_quantifier(0, REPEAT_INFINITE, 0);
+    if (IS_NULL(tmp)) goto err;
+    NQTFR(tmp)->target = np1;
+    np1 = tmp;
+
+    tmp = node_new_list(np1, list2);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    tmp = onig_node_new_alt(list2, alt);
+    if (IS_NULL(tmp)) goto err;
+    alt = tmp;
+    list2 = NULL;
+
+    /* L* LV V* T* */
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    r = add_ctype_to_cc(cc, propname2ctype(env, "Grapheme_Cluster_Break=T"), 0, 0, env);
+    if (r != 0) goto err;
+
+    tmp = node_new_quantifier(0, REPEAT_INFINITE, 0);
+    if (IS_NULL(tmp)) goto err;
+    NQTFR(tmp)->target = np1;
+    np1 = tmp;
+
+    tmp = node_new_list(np1, NULL_NODE);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    r = add_ctype_to_cc(cc, propname2ctype(env, "Grapheme_Cluster_Break=V"), 0, 0, env);
+    if (r != 0) goto err;
+
+    tmp = node_new_quantifier(0, REPEAT_INFINITE, 0);
+    if (IS_NULL(tmp)) goto err;
+    NQTFR(tmp)->target = np1;
+    np1 = tmp;
+
+    tmp = node_new_list(np1, list2);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    r = add_ctype_to_cc(cc, propname2ctype(env, "Grapheme_Cluster_Break=LV"), 0, 0, env);
+    if (r != 0) goto err;
+
+    tmp = node_new_list(np1, list2);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    r = add_ctype_to_cc(cc, propname2ctype(env, "Grapheme_Cluster_Break=L"), 0, 0, env);
+    if (r != 0) goto err;
+
+    tmp = node_new_quantifier(0, REPEAT_INFINITE, 0);
+    if (IS_NULL(tmp)) goto err;
+    NQTFR(tmp)->target = np1;
+    np1 = tmp;
+
+    tmp = node_new_list(np1, list2);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    tmp = onig_node_new_alt(list2, alt);
+    if (IS_NULL(tmp)) goto err;
+    alt = tmp;
+    list2 = NULL;
+
+    /* L* V+ T* */
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    r = add_ctype_to_cc(cc, propname2ctype(env, "Grapheme_Cluster_Break=T"), 0, 0, env);
+    if (r != 0) goto err;
+
+    tmp = node_new_quantifier(0, REPEAT_INFINITE, 0);
+    if (IS_NULL(tmp)) goto err;
+    NQTFR(tmp)->target = np1;
+    np1 = tmp;
+
+    tmp = node_new_list(np1, NULL_NODE);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    r = add_ctype_to_cc(cc, propname2ctype(env, "Grapheme_Cluster_Break=V"), 0, 0, env);
+    if (r != 0) goto err;
+
+    tmp = node_new_quantifier(1, REPEAT_INFINITE, 0);
+    if (IS_NULL(tmp)) goto err;
+    NQTFR(tmp)->target = np1;
+    np1 = tmp;
+
+    tmp = node_new_list(np1, list2);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    r = add_ctype_to_cc(cc, propname2ctype(env, "Grapheme_Cluster_Break=L"), 0, 0, env);
+    if (r != 0) goto err;
+
+    tmp = node_new_quantifier(0, REPEAT_INFINITE, 0);
+    if (IS_NULL(tmp)) goto err;
+    NQTFR(tmp)->target = np1;
+    np1 = tmp;
+
+    tmp = node_new_list(np1, list2);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    tmp = onig_node_new_alt(list2, alt);
+    if (IS_NULL(tmp)) goto err;
+    alt = tmp;
+    list2 = NULL;
+
+    /* Emoji sequence := (E_Base | EBG) Extend* E_Modifier?
+     *                   (ZWJ (Glue_After_Zwj | EBG Extend* E_Modifier?) )* */
+
+    /* ZWJ (Glue_After_Zwj | E_Base_GAZ Extend* E_Modifier?) */
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    r = add_ctype_to_cc(cc, propname2ctype(env, "Grapheme_Cluster_Break=E_Modifier"), 0, 0, env);
+    if (r != 0) goto err;
+
+    tmp = node_new_quantifier(0, 1, 0);
+    if (IS_NULL(tmp)) goto err;
+    NQTFR(tmp)->target = np1;
+    np1 = tmp;
+
+    tmp = node_new_list(np1, NULL_NODE);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    r = add_ctype_to_cc(cc, extend, 0, 0, env);
+    if (r != 0) goto err;
+
+    tmp = node_new_quantifier(0, REPEAT_INFINITE, 0);
+    if (IS_NULL(tmp)) goto err;
+    NQTFR(tmp)->target = np1;
+    np1 = tmp;
+
+    tmp = node_new_list(np1, list2);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    r = add_ctype_to_cc(cc, propname2ctype(env, "Grapheme_Cluster_Break=E_Base_GAZ"), 0, 0, env);
+    if (r != 0) goto err;
+
+    tmp = node_new_list(np1, list2);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    tmp = onig_node_new_alt(list2, NULL_NODE);
+    if (IS_NULL(tmp)) goto err;
+    alt2 = tmp;
+    list2 = NULL;
+
+    /* Glue_After_Zwj */
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    r = add_ctype_to_cc(cc, extend, 0, 0, env);
+    if (r != 0) goto err;
+
+    tmp = node_new_quantifier(0, REPEAT_INFINITE, 0);
+    if (IS_NULL(tmp)) goto err;
+    NQTFR(tmp)->target = np1;
+    np1 = tmp;
+
+    tmp = node_new_list(np1, NULL_NODE);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    {
+      static const OnigCodePoint ranges[] = {
+	13,
+	0x1F308, 0x1F308,
+	0x1F33E, 0x1F33E,
+	0x1F373, 0x1F373,
+	0x1F393, 0x1F393,
+	0x1F3A4, 0x1F3A4,
+	0x1F3A8, 0x1F3A8,
+	0x1F3EB, 0x1F3EB,
+	0x1F3ED, 0x1F3ED,
+	0x1F4BB, 0x1F4BC,
+	0x1F527, 0x1F527,
+	0x1F52C, 0x1F52C,
+	0x1F680, 0x1F680,
+	0x1F692, 0x1F692,
+      };
+      r = add_ctype_to_cc_by_range(cc, -1, 0, env, sb_out, ranges);
+      if (r != 0) goto err;
+    }
+    r = add_ctype_to_cc(cc, propname2ctype(env, "Grapheme_Cluster_Break=Glue_After_Zwj"), 0, 0, env);
+    if (r != 0) goto err;
+
+    tmp = node_new_list(np1, list2);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    tmp = onig_node_new_alt(list2, alt2);
+    if (IS_NULL(tmp)) goto err;
+    alt2 = tmp;
+    list2 = NULL;
+
+    /* Emoji variation sequence
+     * http://unicode.org/Public/emoji/4.0/emoji-zwj-sequences.txt
+     */
+    r = ONIGENC_CODE_TO_MBC(env->enc, 0xfe0f, buf);
+    if (r < 0) goto err;
+    np1 = node_new_str_raw(buf, buf + r);
+    if (IS_NULL(np1)) goto err;
+
+    tmp = node_new_quantifier(0, 1, 0);
+    if (IS_NULL(tmp)) goto err;
+    NQTFR(tmp)->target = np1;
+    np1 = tmp;
+
+    tmp = node_new_list(np1, NULL_NODE);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    {
+      static const OnigCodePoint ranges[] = {
+	4,
+	0x2640, 0x2640,
+	0x2642, 0x2642,
+	0x2695, 0x2696,
+	0x2708, 0x2708,
+      };
+      r = add_ctype_to_cc_by_range(cc, -1, 0, env, sb_out, ranges);
+      if (r != 0) goto err;
+    }
+
+    tmp = node_new_list(np1, list2);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    tmp = onig_node_new_alt(list2, alt2);
+    if (IS_NULL(tmp)) goto err;
+    alt2 = tmp;
+    list2 = NULL;
+
+    tmp = node_new_list(alt2, NULL_NODE);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    alt2 = NULL;
+
+    /* ZWJ */
+    r = ONIGENC_CODE_TO_MBC(env->enc, 0x200D, buf);
+    if (r < 0) goto err;
+    np1 = node_new_str_raw(buf, buf + r);
+    if (IS_NULL(np1)) goto err;
+
+    tmp = node_new_list(np1, list2);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    tmp = node_new_quantifier(0, REPEAT_INFINITE, 0);
+    if (IS_NULL(tmp)) goto err;
+    NQTFR(tmp)->target = list2;
+    np1 = tmp;
+    list2 = NULL;
+
+    tmp = node_new_list(np1, NULL_NODE);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    /* E_Modifier? */
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    r = add_ctype_to_cc(cc, propname2ctype(env, "Grapheme_Cluster_Break=E_Modifier"), 0, 0, env);
+    if (r != 0) goto err;
+
+    tmp = node_new_quantifier(0, 1, 0);
+    if (IS_NULL(tmp)) goto err;
+    NQTFR(tmp)->target = np1;
+    np1 = tmp;
+
+    tmp = node_new_list(np1, list2);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    /* Extend* */
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    r = add_ctype_to_cc(cc, extend, 0, 0, env);
+    if (r != 0) goto err;
+
+    tmp = node_new_quantifier(0, REPEAT_INFINITE, 0);
+    if (IS_NULL(tmp)) goto err;
+    NQTFR(tmp)->target = np1;
+    np1 = tmp;
+
+    tmp = node_new_list(np1, list2);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    /* (E_Base | EBG) */
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    {
+      static const OnigCodePoint ranges[] = {
+	8,
+	0x1F3C2, 0x1F3C2,
+	0x1F3C7, 0x1F3C7,
+	0x1F3CC, 0x1F3CC,
+	0x1F3F3, 0x1F3F3,
+	0x1F441, 0x1F441,
+	0x1F46F, 0x1F46F,
+	0x1F574, 0x1F574,
+	0x1F6CC, 0x1F6CC,
+      };
+      r = add_ctype_to_cc_by_range(cc, -1, 0, env, sb_out, ranges);
+      if (r != 0) goto err;
+    }
+    r = add_ctype_to_cc(cc, propname2ctype(env, "Grapheme_Cluster_Break=E_Base"), 0, 0, env);
+    if (r != 0) goto err;
+    r = add_ctype_to_cc(cc, propname2ctype(env, "Grapheme_Cluster_Break=E_Base_GAZ"), 0, 0, env);
+    if (r != 0) goto err;
+
+    tmp = node_new_list(np1, list2);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    tmp = onig_node_new_alt(list2, alt);
+    if (IS_NULL(tmp)) goto err;
+    alt = tmp;
+    list2 = NULL;
+
+    /* ZWJ (E_Base_GAZ | Glue_After_Zwj) E_Modifier? */
+    /* a sequence starting with ZWJ seems artificial, but GraphemeBreakTest
+     * has such examples.
+     * http://www.unicode.org/Public/9.0.0/ucd/auxiliary/GraphemeBreakTest.html
+     */
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    r = add_ctype_to_cc(cc, propname2ctype(env, "Grapheme_Cluster_Break=E_Modifier"), 0, 0, env);
+    if (r != 0) goto err;
+
+    tmp = node_new_quantifier(0, 1, 0);
+    if (IS_NULL(tmp)) goto err;
+    NQTFR(tmp)->target = np1;
+    np1 = tmp;
+
+    tmp = node_new_list(np1, NULL_NODE);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    r = add_ctype_to_cc(cc, propname2ctype(env, "Grapheme_Cluster_Break=Glue_After_Zwj"), 0, 0, env);
+    if (r != 0) goto err;
+    r = add_ctype_to_cc(cc, propname2ctype(env, "Grapheme_Cluster_Break=E_Base_GAZ"), 0, 0, env);
+    if (r != 0) goto err;
+
+    tmp = node_new_list(np1, list2);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    r = ONIGENC_CODE_TO_MBC(env->enc, 0x200D, buf);
+    if (r < 0) goto err;
+    np1 = node_new_str_raw(buf, buf + r);
+    if (IS_NULL(np1)) goto err;
+
+    tmp = node_new_list(np1, list2);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    tmp = onig_node_new_alt(list2, alt);
+    if (IS_NULL(tmp)) goto err;
+    alt = tmp;
+    list2 = NULL;
+
+    /* RI-Sequence := Regional_Indicator{2} */
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    r = add_code_range(&(cc->mbuf), env, 0x1F1E6, 0x1F1FF);
+    if (r != 0) goto err;
+
+    tmp = node_new_quantifier(2, 2, 0);
+    if (IS_NULL(tmp)) goto err;
+    NQTFR(tmp)->target = np1;
+    np1 = tmp;
+
+    tmp = node_new_list(np1, list2);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    tmp = onig_node_new_alt(list2, alt);
+    if (IS_NULL(tmp)) goto err;
+    alt = tmp;
+    list2 = NULL;
+
+    tmp = node_new_list(alt, list);
+    if (IS_NULL(tmp)) goto err;
+    list = tmp;
+    alt = NULL;
+
+    /* Prepend* */
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    r = add_ctype_to_cc(cc, propname2ctype(env, "Grapheme_Cluster_Break=Prepend"), 0, 0, env);
+    if (r != 0) goto err;
+
+    tmp = node_new_quantifier(0, REPEAT_INFINITE, 0);
+    if (IS_NULL(tmp)) goto err;
+    NQTFR(tmp)->target = np1;
+    np1 = tmp;
+
+    tmp = node_new_list(np1, list);
+    if (IS_NULL(tmp)) goto err;
+    list = tmp;
+    np1 = NULL;
+
     /* PerlSyntax: (?s:.), RubySyntax: (?m:.) */
-    OnigOptionType option;
     np1 = node_new_anychar();
     if (IS_NULL(np1)) goto err;
@@ -5771,16 +6334,118 @@
     option = env->option;
     ONOFF(option, ONIG_OPTION_MULTILINE, 0);
+    tmp = node_new_option(option);
+    if (IS_NULL(tmp)) goto err;
+    NENCLOSE(tmp)->target = np1;
+    np1 = tmp;
+
+    tmp = onig_node_new_alt(np1, NULL_NODE);
+    if (IS_NULL(tmp)) goto err;
+    alt = tmp;
+    np1 = NULL;
+
+    /* Prepend+ */
+    r = ONIGENC_CODE_TO_MBC(env->enc, 0x200D, buf);
+    if (r < 0) goto err;
+    np1 = node_new_str_raw(buf, buf + r);
+    if (IS_NULL(np1)) goto err;
+
+    tmp = node_new_quantifier(0, 1, 0);
+    if (IS_NULL(tmp)) goto err;
+    NQTFR(tmp)->target = np1;
+    np1 = tmp;
+
+    tmp = node_new_list(np1, NULL_NODE);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    np1 = node_new_cclass();
+    if (IS_NULL(np1)) goto err;
+    cc = NCCLASS(np1);
+    r = add_ctype_to_cc(cc, propname2ctype(env, "Grapheme_Cluster_Break=Prepend"), 0, 0, env);
+    if (r != 0) goto err;
+
+    tmp = node_new_quantifier(1, REPEAT_INFINITE, 0);
+    if (IS_NULL(tmp)) goto err;
+    NQTFR(tmp)->target = np1;
+    np1 = tmp;
+
+    tmp = node_new_list(np1, list2);
+    if (IS_NULL(tmp)) goto err;
+    list2 = tmp;
+    np1 = NULL;
+
+    tmp = onig_node_new_alt(list2, alt);
+    if (IS_NULL(tmp)) goto err;
+    alt = tmp;
+    list2 = NULL;
+
+    tmp = onig_node_new_alt(list, alt);
+    if (IS_NULL(tmp)) goto err;
+    alt = tmp;
+    list = NULL;
+  }
+  else
+#endif /* USE_UNICODE_PROPERTIES */
+  {
+    /* PerlSyntax: (?s:.), RubySyntax: (?m:.) */
+    np1 = node_new_anychar();
+    if (IS_NULL(np1)) goto err;
+
+    option = env->option;
+    ONOFF(option, ONIG_OPTION_MULTILINE, 0);
+    tmp = node_new_option(option);
+    if (IS_NULL(tmp)) goto err;
+    NENCLOSE(tmp)->target = np1;
+    np1 = tmp;
+
+    alt = onig_node_new_alt(np1, NULL_NODE);
+    if (IS_NULL(alt)) goto err;
+    np1 = NULL;
+  }
+
+  /* \x0D\x0A */
+  r = ONIGENC_CODE_TO_MBC(env->enc, 0x0D, buf);
+  if (r < 0) goto err;
+  num1 = r;
+  r = ONIGENC_CODE_TO_MBC(env->enc, 0x0A, buf + num1);
+  if (r < 0) goto err;
+  np1 = node_new_str_raw(buf, buf + num1 + r);
+  if (IS_NULL(np1)) goto err;
+
+  tmp = onig_node_new_alt(np1, alt);
+  if (IS_NULL(tmp)) goto err;
+  alt = tmp;
+  np1 = NULL;
+
+  /* (?>\x0D\x0A|...) */
+  tmp = node_new_enclose(ENCLOSE_STOP_BACKTRACK);
+  if (IS_NULL(tmp)) goto err;
+  NENCLOSE(tmp)->target = alt;
+  np1 = tmp;
+
+#ifdef USE_UNICODE_PROPERTIES
+  if (ONIGENC_IS_UNICODE(env->enc)) {
+    /* Don't ignore case. */
+    option = env->option;
+    ONOFF(option, ONIG_OPTION_IGNORECASE, 1);
     *np = node_new_option(option);
     if (IS_NULL(*np)) goto err;
     NENCLOSE(*np)->target = np1;
   }
+  else
+#endif
+  {
+    *np = np1;
+  }
   return ONIG_NORMAL;
 
  err:
   onig_node_free(np1);
-  onig_node_free(np2);
-  onig_node_free(qn);
-  onig_node_free(list1);
+  onig_node_free(list);
   onig_node_free(list2);
+  onig_node_free(alt);
+  onig_node_free(alt2);
+  bbuf_free(pbuf1);
   return (r == 0) ? ONIGERR_MEMORY : r;
 }
@@ -5815,5 +6480,5 @@
       c = data[0];
       if (((c < SINGLE_BYTE_SIZE) && BITSET_AT(cc->bs, c))) {
-        /* skip if c is included in the bitset */
+	/* skip if c is included in the bitset */
 	c = not_found;
       }
@@ -5829,7 +6494,7 @@
     if (b1 != 0) {
       if (((b1 & (b1 - 1)) == 0) && (c == not_found)) {
-        c = BITS_IN_ROOM * i + countbits(b1 - 1);
+	c = BITS_IN_ROOM * i + countbits(b1 - 1);
       } else {
-        return 0;  /* the character class contains multiple chars */
+	return 0;  /* the character class contains multiple chars */
       }
     }
@@ -5876,5 +6541,8 @@
       env->option = NENCLOSE(*np)->option;
       r = fetch_token(tok, src, end, env);
-      if (r < 0) return r;
+      if (r < 0) {
+	env->option = prev;
+	return r;
+      }
       r = parse_subexp(&target, tok, term, src, end, env);
       env->option = prev;
@@ -5949,5 +6617,5 @@
       while (1) {
 	if (len >= ONIGENC_MBC_MINLEN(env->enc)) {
-	  if (len == enclen(env->enc, NSTR(*np)->s)) {
+	  if (len == enclen(env->enc, NSTR(*np)->s, NSTR(*np)->end)) {
 	    r = fetch_token(tok, src, end, env);
 	    NSTRING_CLEAR_RAW(*np);
@@ -6029,67 +6697,11 @@
 	  CClassNode* cc;
 
-#ifdef USE_SHARED_CCLASS_TABLE
-          const OnigCodePoint *mbr;
-	  OnigCodePoint sb_out;
-
-          r = ONIGENC_GET_CTYPE_CODE_RANGE(env->enc, tok->u.prop.ctype,
-					   &sb_out, &mbr);
-          if (r == 0 &&
-              ! IS_ASCII_RANGE(env->option) &&
-              ONIGENC_CODE_RANGE_NUM(mbr)
-              >= THRESHOLD_RANGE_NUM_FOR_SHARE_CCLASS) {
-            type_cclass_key  key;
-            type_cclass_key* new_key;
-
-            key.enc  = env->enc;
-            key.not  = tok->u.prop.not;
-            key.type = tok->u.prop.ctype;
-
-            THREAD_ATOMIC_START;
-
-            if (IS_NULL(OnigTypeCClassTable)) {
-              OnigTypeCClassTable
-                = onig_st_init_table_with_size(&type_type_cclass_hash, 10);
-              if (IS_NULL(OnigTypeCClassTable)) {
-                THREAD_ATOMIC_END;
-                return ONIGERR_MEMORY;
-              }
-            }
-            else {
-              if (onig_st_lookup(OnigTypeCClassTable, (st_data_t )&key,
-                                 (st_data_t* )np)) {
-                THREAD_ATOMIC_END;
-                break;
-              }
-            }
-
-            *np = node_new_cclass_by_codepoint_range(tok->u.prop.not,
-						     sb_out, mbr);
-            if (IS_NULL(*np)) {
-              THREAD_ATOMIC_END;
-              return ONIGERR_MEMORY;
-            }
-
-            cc = NCCLASS(*np);
-            NCCLASS_SET_SHARE(cc);
-            new_key = (type_cclass_key* )xmalloc(sizeof(type_cclass_key));
-	    xmemcpy(new_key, &key, sizeof(type_cclass_key));
-            onig_st_add_direct(OnigTypeCClassTable, (st_data_t )new_key,
-                               (st_data_t )*np);
-
-            THREAD_ATOMIC_END;
-          }
-          else {
-#endif
-            *np = node_new_cclass();
-            CHECK_NULL_RETURN_MEMERR(*np);
-            cc = NCCLASS(*np);
-            r = add_ctype_to_cc(cc, tok->u.prop.ctype, 0,
-			    IS_ASCII_RANGE(env->option), env);
-	    if (r != 0) return r;
-            if (tok->u.prop.not != 0) NCCLASS_SET_NOT(cc);
-#ifdef USE_SHARED_CCLASS_TABLE
-          }
-#endif
+	  *np = node_new_cclass();
+	  CHECK_NULL_RETURN_MEMERR(*np);
+	  cc = NCCLASS(*np);
+	  r = add_ctype_to_cc(cc, tok->u.prop.ctype, 0,
+	      IS_ASCII_RANGE(env->option), env);
+	  if (r != 0) return r;
+	  if (tok->u.prop.not != 0) NCCLASS_SET_NOT(cc);
 	}
 	break;
@@ -6321,4 +6933,7 @@
 
   *top = NULL;
+  env->parse_depth++;
+  if (env->parse_depth > ParseDepthLimit)
+    return ONIGERR_PARSE_DEPTH_LIMIT_OVER;
   r = parse_branch(&node, tok, term, src, end, env);
   if (r < 0) {
@@ -6358,4 +6973,5 @@
   }
 
+  env->parse_depth--;
   return r;
 }
