node_extended_grapheme_cluster(Node** np, ScanEnv* env)
{
  /* same as (?>\P{M}\p{M}*) */
  Node* np1 = NULL;
  Node* np2 = NULL;
  Node* qn = NULL;
  Node* list1 = NULL;
  Node* list2 = NULL;
  int r = 0;

#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);
      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);
      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)) {
    /* PerlSyntax: (?s:.), RubySyntax: (?m:.) */
    OnigOptionType option;
    np1 = node_new_anychar();
    if (IS_NULL(np1)) goto err;

    option = env->option;
    ONOFF(option, ONIG_OPTION_MULTILINE, 0);
    *np = node_new_option(option);
    if (IS_NULL(*np)) goto err;
    NENCLOSE(*np)->target = np1;
  }
  return ONIG_NORMAL;

 err:
  onig_node_free(np1);
  onig_node_free(np2);
  onig_node_free(qn);
  onig_node_free(list1);
  onig_node_free(list2);
  return (r == 0) ? ONIGERR_MEMORY : r;
}
node_extended_grapheme_cluster(Node** np, ScanEnv* env)
{
   
  Node* np1 = NULL;
  Node* np2 = NULL;
  Node* qn = NULL;
  Node* list1 = NULL;
  Node* list2 = NULL;
  int r = 0;

#ifdef USE_UNICODE_PROPERTIES
  if (ONIGENC_IS_UNICODE(env->enc)) {
     
    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) {
       
      np1 = node_new_cclass();
      if (IS_NULL(np1)) goto err;
      cc1 = NCCLASS(np1);
      r = add_ctype_to_cc(cc1, ctype, 0, 0, env);
      if (r != 0) goto err;
      NCCLASS_SET_NOT(cc1);

       
      np2 = node_new_cclass();
      if (IS_NULL(np2)) goto err;
      cc2 = NCCLASS(np2);
      r = add_ctype_to_cc(cc2, ctype, 0, 0, env);
      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;

       
      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  
  if (IS_NULL(*np)) {
     
    OnigOptionType option;
    np1 = node_new_anychar();
    if (IS_NULL(np1)) goto err;

    option = env->option;
    ONOFF(option, ONIG_OPTION_MULTILINE, 0);
    *np = node_new_option(option);
    if (IS_NULL(*np)) goto err;
    NENCLOSE(*np)->target = np1;
  }
  return ONIG_NORMAL;

 err:
  onig_node_free(np1);
  onig_node_free(np2);
  onig_node_free(qn);
  onig_node_free(list1);
  onig_node_free(list2);
  return (r == 0) ? ONIGERR_MEMORY : r;
}