diff options
Diffstat (limited to 'src/regparse.c')
| -rw-r--r-- | src/regparse.c | 1075 | 
1 files changed, 1006 insertions, 69 deletions
| diff --git a/src/regparse.c b/src/regparse.c index a5f8e5b..25291c5 100644 --- a/src/regparse.c +++ b/src/regparse.c @@ -48,6 +48,11 @@ OnigSyntaxType OnigSyntaxRuby = {    , ( ONIG_SYN_OP2_QMARK_GROUP_EFFECT |        ONIG_SYN_OP2_OPTION_RUBY |        ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP | ONIG_SYN_OP2_ESC_K_NAMED_BACKREF | +      ONIG_SYN_OP2_QMARK_LPAREN_IF_ELSE | +      ONIG_SYN_OP2_QMARK_TILDE_ABSENT_GROUP | +      ONIG_SYN_OP2_ESC_CAPITAL_R_GENERAL_NEWLINE | +      ONIG_SYN_OP2_ESC_CAPITAL_N_O_SUPER_DOT | +      ONIG_SYN_OP2_ESC_CAPITAL_K_KEEP |        ONIG_SYN_OP2_ESC_G_SUBEXP_CALL |        ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY  |        ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT | @@ -179,7 +184,10 @@ static int backref_rel_to_abs(int rel_no, ScanEnv* env)    }  } -#define ONOFF(v,f,negative)    (negative) ? ((v) &= ~(f)) : ((v) |= (f)) +#define OPTION_ON(v,f)     ((v) |= (f)) +#define OPTION_OFF(v,f)    ((v) &= ~(f)) + +#define OPTION_NEGATE(v,f,negative)    (negative) ? ((v) &= ~(f)) : ((v) |= (f))  #define MBCODE_START_POS(enc) \    (OnigCodePoint )(ONIGENC_MBC_MINLEN(enc) > 1 ? 0 : 0x80) @@ -301,6 +309,34 @@ strdup_with_null(OnigEncoding enc, UChar* s, UChar* end)  }  #endif +static int +save_entry(ScanEnv* env, enum SaveType type, int* id) +{ +  int nid = env->save_num; + +#if 0 +  if (IS_NULL(env->saves)) { +    int n = 10; +    env->saves = (SaveItem* )xmalloc(sizeof(SaveItem) * n); +    CHECK_NULL_RETURN_MEMERR(env->saves); +    env->save_alloc_num = n; +  } +  else if (env->save_alloc_num <= nid) { +    int n = env->save_alloc_num * 2; +    SaveItem* p = (SaveItem* )xrealloc(env->saves, sizeof(SaveItem) * n); +    CHECK_NULL_RETURN_MEMERR(p); +    env->saves = p; +    env->save_alloc_num = n; +  } + +  env->saves[nid].type = type; +#endif + +  env->save_num++; +  *id = nid; +  return 0; +} +  /* scan pattern methods */  #define PEND_VALUE   0 @@ -990,7 +1026,7 @@ scan_env_clear(ScanEnv* env)    env->error_end  = (UChar* )NULL;    env->num_call   = 0; -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL    env->unset_addr_list = NULL;    env->has_call_zero   = 0;  #endif @@ -1011,6 +1047,10 @@ scan_env_clear(ScanEnv* env)    env->has_recursion       = 0;  #endif    env->parse_depth         = 0; +  env->keep_num            = 0; +  env->save_num            = 0; +  env->save_alloc_num      = 0; +  env->saves               = 0;  }  static int @@ -1075,7 +1115,7 @@ onig_node_free(Node* node)  #endif    switch (NODE_TYPE(node)) { -  case NODE_STR: +  case NODE_STRING:      if (STR_(node)->capa != 0 &&          IS_NOT_NULL(STR_(node)->s) && STR_(node)->s != STR_(node)->buf) {        xfree(STR_(node)->s); @@ -1103,13 +1143,25 @@ onig_node_free(Node* node)      }      break; -  case NODE_BREF: -    if (IS_NOT_NULL(BREF_(node)->back_dynamic)) -      xfree(BREF_(node)->back_dynamic); +  case NODE_BACKREF: +    if (IS_NOT_NULL(BACKREF_(node)->back_dynamic)) +      xfree(BACKREF_(node)->back_dynamic);      break; -  case NODE_QUANT:    case NODE_ENCLOSURE: +    if (NODE_BODY(node)) +      onig_node_free(NODE_BODY(node)); + +    { +      EnclosureNode* en = ENCLOSURE_(node); +      if (en->type == ENCLOSURE_IF_ELSE) { +        onig_node_free(en->te.Then); +        onig_node_free(en->te.Else); +      } +    } +    break; + +  case NODE_QUANT:    case NODE_ANCHOR:      if (NODE_BODY(node))        onig_node_free(NODE_BODY(node)); @@ -1117,12 +1169,35 @@ onig_node_free(Node* node)    case NODE_CTYPE:    case NODE_CALL: +  case NODE_GIMMICK:      break;    }    xfree(node);  } +static void +cons_node_free_alone(Node* node) +{ +  NODE_CAR(node) = 0; +  NODE_CDR(node) = 0; +  onig_node_free(node); +} + +extern void +list_node_free_not_car(Node* node) +{ +  Node* next_node; + + start: +  if (IS_NULL(node)) return; + +  next_node = NODE_CDR(node); +  xfree(node); +  node = next_node; +  goto start; +} +  static Node*  node_new(void)  { @@ -1154,7 +1229,7 @@ node_new_cclass(void)    Node* node = node_new();    CHECK_NULL_RETURN(node); -  SET_NODE_TYPE(node, NODE_CCLASS); +  NODE_SET_TYPE(node, NODE_CCLASS);    initialize_cclass(CCLASS_(node));    return node;  } @@ -1165,19 +1240,61 @@ node_new_ctype(int type, int not)    Node* node = node_new();    CHECK_NULL_RETURN(node); -  SET_NODE_TYPE(node, NODE_CTYPE); +  NODE_SET_TYPE(node, NODE_CTYPE);    CTYPE_(node)->ctype = type;    CTYPE_(node)->not   = not;    return node;  }  static Node* +node_new_anychar(void) +{ +  Node* node = node_new_ctype(CTYPE_ANYCHAR, 0); +  return node; +} + +static Node* +node_new_anychar_with_fixed_option(OnigOptionType option) +{ +  CtypeNode* ct; +  Node* node; + +  node = node_new_anychar(); +  ct = CTYPE_(node); +  ct->options = option; +  NODE_STATUS_ADD(node, NST_FIXED_OPTION); +  return node; +} + +static int +node_new_no_newline(Node** node, ScanEnv* env) +{ +  Node* n; + +  n = node_new_anychar_with_fixed_option(ONIG_OPTION_NONE); +  CHECK_NULL_RETURN_MEMERR(n); +  *node = n; +  return 0; +} + +static int +node_new_true_anychar(Node** node, ScanEnv* env) +{ +  Node* n; + +  n = node_new_anychar_with_fixed_option(ONIG_OPTION_MULTILINE); +  CHECK_NULL_RETURN_MEMERR(n); +  *node = n; +  return 0; +} + +static Node*  node_new_list(Node* left, Node* right)  {    Node* node = node_new();    CHECK_NULL_RETURN(node); -  SET_NODE_TYPE(node, NODE_LIST); +  NODE_SET_TYPE(node, NODE_LIST);    NODE_CAR(node)  = left;    NODE_CDR(node) = right;    return node; @@ -1213,19 +1330,65 @@ onig_node_new_alt(Node* left, Node* right)    Node* node = node_new();    CHECK_NULL_RETURN(node); -  SET_NODE_TYPE(node, NODE_ALT); +  NODE_SET_TYPE(node, NODE_ALT);    NODE_CAR(node)  = left;    NODE_CDR(node) = right;    return node;  } +static Node* +make_list_or_alt(NodeType type, int n, Node* ns[]) +{ +  Node* r; + +  if (n <= 0) return NULL_NODE; + +  if (n == 1) { +    r = node_new(); +    CHECK_NULL_RETURN(r); +    NODE_SET_TYPE(r, type); +    NODE_CAR(r) = ns[0]; +    NODE_CDR(r) = NULL_NODE; +  } +  else { +    Node* right; + +    r = node_new(); +    CHECK_NULL_RETURN(r); + +    right = make_list_or_alt(type, n - 1, ns + 1); +    if (IS_NULL(right)) { +      onig_node_free(r); +      return NULL_NODE; +    } + +    NODE_SET_TYPE(r, type); +    NODE_CAR(r) = ns[0]; +    NODE_CDR(r) = right; +  } + +  return r; +} + +static Node* +make_list(int n, Node* ns[]) +{ +  return make_list_or_alt(NODE_LIST, n, ns); +} + +static Node* +make_alt(int n, Node* ns[]) +{ +  return make_list_or_alt(NODE_ALT, n, ns); +} +  extern Node*  onig_node_new_anchor(int type)  {    Node* node = node_new();    CHECK_NULL_RETURN(node); -  SET_NODE_TYPE(node, NODE_ANCHOR); +  NODE_SET_TYPE(node, NODE_ANCHOR);    ANCHOR_(node)->type     = type;    ANCHOR_(node)->char_len = -1;    return node; @@ -1243,16 +1406,16 @@ node_new_backref(int back_num, int* backrefs, int by_name,    CHECK_NULL_RETURN(node); -  SET_NODE_TYPE(node, NODE_BREF); -  BREF_(node)->back_num = back_num; -  BREF_(node)->back_dynamic = (int* )NULL; +  NODE_SET_TYPE(node, NODE_BACKREF); +  BACKREF_(node)->back_num = back_num; +  BACKREF_(node)->back_dynamic = (int* )NULL;    if (by_name != 0)      NODE_STATUS_ADD(node, NST_BY_NAME);  #ifdef USE_BACKREF_WITH_LEVEL    if (exist_level != 0) {      NODE_STATUS_ADD(node, NST_NEST_LEVEL); -    BREF_(node)->nest_level  = nest_level; +    BACKREF_(node)->nest_level  = nest_level;    }  #endif @@ -1266,7 +1429,7 @@ node_new_backref(int back_num, int* backrefs, int by_name,    if (back_num <= NODE_BACKREFS_SIZE) {      for (i = 0; i < back_num; i++) -      BREF_(node)->back_static[i] = backrefs[i]; +      BACKREF_(node)->back_static[i] = backrefs[i];    }    else {      int* p = (int* )xmalloc(sizeof(int) * back_num); @@ -1274,21 +1437,41 @@ node_new_backref(int back_num, int* backrefs, int by_name,        onig_node_free(node);        return NULL;      } -    BREF_(node)->back_dynamic = p; +    BACKREF_(node)->back_dynamic = p;      for (i = 0; i < back_num; i++)        p[i] = backrefs[i];    }    return node;  } -#ifdef USE_SUBEXP_CALL +static Node* +node_new_backref_checker(int back_num, int* backrefs, int by_name, +#ifdef USE_BACKREF_WITH_LEVEL +		 int exist_level, int nest_level, +#endif +		 ScanEnv* env) +{ +  Node* node; + +  node = node_new_backref(back_num, backrefs, by_name, +#ifdef USE_BACKREF_WITH_LEVEL +                          exist_level, nest_level, +#endif +                          env); +  CHECK_NULL_RETURN(node); + +  NODE_STATUS_ADD(node, NST_CHECKER); +  return node; +} + +#ifdef USE_CALL  static Node*  node_new_call(UChar* name, UChar* name_end, int gnum, int by_number)  {    Node* node = node_new();    CHECK_NULL_RETURN(node); -  SET_NODE_TYPE(node, NODE_CALL); +  NODE_SET_TYPE(node, NODE_CALL);    CALL_(node)->by_number   = by_number;    CALL_(node)->name        = name;    CALL_(node)->name_end    = name_end; @@ -1304,7 +1487,7 @@ node_new_quantifier(int lower, int upper, int by_number)    Node* node = node_new();    CHECK_NULL_RETURN(node); -  SET_NODE_TYPE(node, NODE_QUANT); +  NODE_SET_TYPE(node, NODE_QUANT);    QUANT_(node)->lower  = lower;    QUANT_(node)->upper  = upper;    QUANT_(node)->greedy = 1; @@ -1328,7 +1511,7 @@ node_new_enclosure(int type)    Node* node = node_new();    CHECK_NULL_RETURN(node); -  SET_NODE_TYPE(node, NODE_ENCLOSURE); +  NODE_SET_TYPE(node, NODE_ENCLOSURE);    ENCLOSURE_(node)->type = type;    switch (type) { @@ -1340,11 +1523,16 @@ node_new_enclosure(int type)      break;    case ENCLOSURE_OPTION: -    ENCLOSURE_(node)->o.option =  0; +    ENCLOSURE_(node)->o.options =  0;      break;    case ENCLOSURE_STOP_BACKTRACK:      break; + +  case ENCLOSURE_IF_ELSE: +    ENCLOSURE_(node)->te.Then = 0; +    ENCLOSURE_(node)->te.Else = 0; +    break;    }    ENCLOSURE_(node)->opt_count = 0; @@ -1358,7 +1546,20 @@ onig_node_new_enclosure(int type)  }  static Node* -node_new_enclosure_memory(int is_named) +node_new_enclosure_if_else(Node* cond, Node* Then, Node* Else) +{ +  Node* n; +  n = node_new_enclosure(ENCLOSURE_IF_ELSE); +  CHECK_NULL_RETURN(n); + +  NODE_BODY(n) = cond; +  ENCLOSURE_(n)->te.Then = Then; +  ENCLOSURE_(n)->te.Else = Else; +  return n; +} + +static Node* +node_new_memory(int is_named)  {    Node* node = node_new_enclosure(ENCLOSURE_MEMORY);    CHECK_NULL_RETURN(node); @@ -1373,10 +1574,395 @@ node_new_option(OnigOptionType option)  {    Node* node = node_new_enclosure(ENCLOSURE_OPTION);    CHECK_NULL_RETURN(node); -  ENCLOSURE_(node)->o.option = option; +  ENCLOSURE_(node)->o.options = option;    return node;  } +static int +node_new_fail(Node** node, ScanEnv* env) +{ +  *node = node_new(); +  CHECK_NULL_RETURN_MEMERR(*node); + +  NODE_SET_TYPE(*node, NODE_GIMMICK); +  GIMMICK_(*node)->type = GIMMICK_FAIL; +  return ONIG_NORMAL; +} + +static int +node_new_save_gimmick(Node** node, enum SaveType save_type, ScanEnv* env) +{ +  int id; +  int r; + +  r = save_entry(env, save_type, &id); +  if (r != ONIG_NORMAL) return r; + +  *node = node_new(); +  CHECK_NULL_RETURN_MEMERR(*node); + +  NODE_SET_TYPE(*node, NODE_GIMMICK); +  GIMMICK_(*node)->id   = id; +  GIMMICK_(*node)->type = GIMMICK_SAVE; +  GIMMICK_(*node)->detail_type = (int )save_type; + +  return ONIG_NORMAL; +} + +static int +node_new_update_var_gimmick(Node** node, enum UpdateVarType update_var_type, +                            int id, ScanEnv* env) +{ +  *node = node_new(); +  CHECK_NULL_RETURN_MEMERR(*node); + +  NODE_SET_TYPE(*node, NODE_GIMMICK); +  GIMMICK_(*node)->id   = id; +  GIMMICK_(*node)->type = GIMMICK_UPDATE_VAR; +  GIMMICK_(*node)->detail_type = (int )update_var_type; + +  return ONIG_NORMAL; +} + +static int +node_new_keep(Node** node, ScanEnv* env) +{ +  int r; + +  r = node_new_save_gimmick(node, SAVE_KEEP, env); +  if (r != 0) return r; + +  env->keep_num++; +  return ONIG_NORMAL; +} + +static int +make_absent_engine(Node** node, int pre_save_right_id, Node* absent, +                   Node* step_one, int lower, int upper, int possessive, +                   int is_range_cutter, ScanEnv* env) +{ +  int r; +  int i; +  int id; +  Node* x; +  Node* ns[4]; + +  for (i = 0; i < 4; i++) ns[i] = NULL_NODE; + +  ns[1] = absent; +  ns[3] = step_one; // for err +  r = node_new_save_gimmick(&ns[0], SAVE_S, env); +  if (r != 0) goto err; + +  id = GIMMICK_(ns[0])->id; +  r = node_new_update_var_gimmick(&ns[2], UPDATE_VAR_RIGHT_RANGE_FROM_S_STACK, +                                  id, env); +  if (r != 0) goto err; + +  r = node_new_fail(&ns[3], env); +  if (r != 0) goto err; + +  x = make_list(4, ns); +  if (IS_NULL(x)) goto err; + +  ns[0] = x; +  ns[1] = step_one; +  ns[2] = ns[3] = NULL_NODE; + +  x = make_alt(2, ns); +  if (IS_NULL(x)) goto err; + +  ns[0] = x; + +  x = node_new_quantifier(lower, upper, 0); +  if (IS_NULL(x)) goto err; + +  NODE_BODY(x) = ns[0]; +  ns[0] = x; + +  if (possessive != 0) { +    x = node_new_enclosure(ENCLOSURE_STOP_BACKTRACK); +    if (IS_NULL(x)) goto err; + +    NODE_BODY(x) = ns[0]; +    ns[0] = x; +  } + +  r = node_new_update_var_gimmick(&ns[1], UPDATE_VAR_RIGHT_RANGE_FROM_STACK, +                                  pre_save_right_id, env); +  if (r != 0) goto err; + +  r = node_new_fail(&ns[2], env); +  if (r != 0) goto err; + +  x = make_list(2, ns + 1); +  if (IS_NULL(x)) goto err; + +  ns[1] = x; ns[2] = NULL_NODE; + +  x = make_alt(2, ns); +  if (IS_NULL(x)) goto err; + +  if (is_range_cutter != 0) +    NODE_STATUS_ADD(x, NST_SUPER); + +  *node = x; +  return ONIG_NORMAL; + + err: +  for (i = 0; i < 4; i++) onig_node_free(ns[i]); +  return r; +} + +static int +make_absent_tail(Node** node1, Node** node2, int pre_save_right_id, +                 ScanEnv* env) +{ +  int r; +  int id; +  Node* save; +  Node* x; +  Node* ns[2]; + +  *node1 = *node2 = NULL_NODE; +  save = ns[0] = ns[1] = NULL_NODE; + +  r = node_new_save_gimmick(&save, SAVE_RIGHT_RANGE, env); +  if (r != 0) goto err; + +  id = GIMMICK_(save)->id; +  r = node_new_update_var_gimmick(&ns[0], UPDATE_VAR_RIGHT_RANGE_FROM_STACK, +                                  id, env); +  if (r != 0) goto err; + +  r = node_new_fail(&ns[1], env); +  if (r != 0) goto err; + +  x = make_list(2, ns); +  if (IS_NULL(x)) goto err; + +  ns[0] = NULL_NODE; ns[1] = x; + +  r = node_new_update_var_gimmick(&ns[0], UPDATE_VAR_RIGHT_RANGE_FROM_STACK, +                                  pre_save_right_id, env); +  if (r != 0) goto err; + +  x = make_alt(2, ns); +  if (IS_NULL(x)) goto err; + +  *node1 = save; +  *node2 = x; +  return ONIG_NORMAL; + + err: +  onig_node_free(save); +  onig_node_free(ns[0]); +  onig_node_free(ns[1]); +  return r; +} + +static int +is_simple_one_char_repeat(Node* node, Node** rquant, Node** rbody, +                          int* is_possessive, ScanEnv* env) +{ +  Node* quant; +  Node* body; + +  *rquant = *rbody = 0; +  *is_possessive = 0; + +  if (NODE_TYPE(node) == NODE_QUANT) { +    quant = node; +  } +  else { +    if (NODE_TYPE(node) == NODE_ENCLOSURE) { +      EnclosureNode* en = ENCLOSURE_(node); +      if (en->type == ENCLOSURE_STOP_BACKTRACK) { +        *is_possessive = 1; +        quant = NODE_ENCLOSURE_BODY(en); +        if (NODE_TYPE(quant) != NODE_QUANT) +          return 0; +      } +      else +        return 0; +    } +    else +      return 0; +  } + +  body = NODE_BODY(quant); +  switch (NODE_TYPE(body)) { +  case NODE_STRING: +    { +      int len; +      StrNode* sn = STR_(body); +      UChar *s = sn->s; + +      len = 0; +      while (s < sn->end) { +        s += enclen(env->enc, s); +        len++; +      } +      if (len != 1) +        return 0; +    } + +  case NODE_CCLASS: +    break; + +  default: +    return 0; +    break; +  } + +  if (node != quant) { +    NODE_BODY(node) = 0; +    onig_node_free(node); +  } +  NODE_BODY(quant) = NULL_NODE; +  *rquant = quant; +  *rbody  = body; +  return 1; +} + +static int +make_absent_tree_for_simple_one_char_repeat(Node** node, Node* absent, Node* quant, +                                            Node* body, int possessive, ScanEnv* env) +{ +  int r; +  int i; +  int id1; +  int lower, upper; +  Node* x; +  Node* ns[4]; + +  *node = NULL_NODE; +  r = ONIGERR_MEMORY; +  ns[0] = ns[1] = NULL_NODE; +  ns[2] = body, ns[3] = absent; + +  lower = QUANT_(quant)->lower; +  upper = QUANT_(quant)->upper; +  onig_node_free(quant); + +  r = node_new_save_gimmick(&ns[0], SAVE_RIGHT_RANGE, env); +  if (r != 0) goto err; + +  id1 = GIMMICK_(ns[0])->id; + +  r = make_absent_engine(&ns[1], id1, absent, body, lower, upper, possessive, +                         0, env); +  if (r != 0) goto err; + +  ns[2] = ns[3] = NULL_NODE; + +  r = make_absent_tail(&ns[2], &ns[3], id1, env); +  if (r != 0) goto err; + +  x = make_list(4, ns); +  if (IS_NULL(x)) goto err; + +  *node = x; +  return ONIG_NORMAL; + + err: +  for (i = 0; i < 4; i++) onig_node_free(ns[i]); +  return r; +} + +static int +make_absent_tree(Node** node, Node* absent, Node* expr, int is_range_cutter, +                 ScanEnv* env) +{ +  int r; +  int i; +  int id1, id2; +  int possessive; +  Node* x; +  Node* ns[7]; + +  r = ONIGERR_MEMORY; +  for (i = 0; i < 7; i++) ns[i] = NULL_NODE; +  ns[4] = expr; ns[5] = absent; + +  if (is_range_cutter == 0) { +    Node* quant; +    Node* body; + +    if (expr == NULL_NODE) { +      /* default expr \O* */ +      quant = node_new_quantifier(0, REPEAT_INFINITE, 0); +      if (IS_NULL(quant)) goto err; + +      r = node_new_true_anychar(&body, env); +      if (r != 0) { +        onig_node_free(quant); +        goto err; +      } +      possessive = 0; +      goto simple; +    } +    else { +      if (is_simple_one_char_repeat(expr, &quant, &body, &possessive, env)) { +      simple: +        r = make_absent_tree_for_simple_one_char_repeat(node, absent, quant, +                                                        body, possessive, env); +        if (r != 0) { +          ns[4] = NULL_NODE; +          onig_node_free(quant); +          onig_node_free(body); +          goto err; +        } + +        return ONIG_NORMAL; +      } +    } +  } + +  r = node_new_save_gimmick(&ns[0], SAVE_RIGHT_RANGE, env); +  if (r != 0) goto err; + +  id1 = GIMMICK_(ns[0])->id; + +  r = node_new_save_gimmick(&ns[1], SAVE_S, env); +  if (r != 0) goto err; + +  id2 = GIMMICK_(ns[1])->id; + +  r = node_new_true_anychar(&ns[3], env); +  if (r != 0) goto err; + +  possessive = 1; +  r = make_absent_engine(&ns[2], id1, absent, ns[3], 0, REPEAT_INFINITE, +                         possessive, is_range_cutter, env); +  if (r != 0) goto err; + +  ns[3] = NULL_NODE; +  ns[5] = NULL_NODE; + +  r = node_new_update_var_gimmick(&ns[3], UPDATE_VAR_S_FROM_STACK, id2, env); +  if (r != 0) goto err; + +  if (is_range_cutter != 0) { +    x = make_list(4, ns); +    if (IS_NULL(x)) goto err; +  } +  else { +    r = make_absent_tail(&ns[5], &ns[6], id1, env); +    if (r != 0) goto err; +   +    x = make_list(7, ns); +    if (IS_NULL(x)) goto err; +  } + +  *node = x; +  return ONIG_NORMAL; + + err: +  for (i = 0; i < 7; i++) onig_node_free(ns[i]); +  return r;   +} +  extern int  onig_node_str_cat(Node* node, const UChar* s, const UChar* end)  { @@ -1385,9 +1971,9 @@ onig_node_str_cat(Node* node, const UChar* s, const UChar* end)    if (addlen > 0) {      int len  = STR_(node)->end - STR_(node)->s; -    if (STR_(node)->capa > 0 || (len + addlen > NODE_STR_BUF_SIZE - 1)) { +    if (STR_(node)->capa > 0 || (len + addlen > NODE_STRING_BUF_SIZE - 1)) {        UChar* p; -      int capa = len + addlen + NODE_STR_MARGIN; +      int capa = len + addlen + NODE_STRING_MARGIN;        if (capa <= STR_(node)->capa) {          onig_strcpy(STR_(node)->s + len, s, end); @@ -1432,7 +2018,7 @@ node_str_cat_char(Node* node, UChar c)  extern void  onig_node_conv_to_str_node(Node* node, int flag)  { -  SET_NODE_TYPE(node, NODE_STR); +  NODE_SET_TYPE(node, NODE_STRING);    STR_(node)->flag = flag;    STR_(node)->capa = 0;    STR_(node)->s    = STR_(node)->buf; @@ -1459,7 +2045,7 @@ node_new_str(const UChar* s, const UChar* end)    Node* node = node_new();    CHECK_NULL_RETURN(node); -  SET_NODE_TYPE(node, NODE_STR); +  NODE_SET_TYPE(node, NODE_STRING);    STR_(node)->capa = 0;    STR_(node)->flag = 0;    STR_(node)->s    = STR_(node)->buf; @@ -1481,7 +2067,7 @@ static Node*  node_new_str_raw(UChar* s, UChar* end)  {    Node* node = node_new_str(s, end); -  NSTRING_SET_RAW(node); +  NODE_STRING_SET_RAW(node);    return node;  } @@ -1511,7 +2097,7 @@ str_node_split_last_char(StrNode* sn, OnigEncoding enc)      if (p && p > sn->s) { /* can be split. */        n = node_new_str(p, sn->end);        if ((sn->flag & STRING_RAW) != 0) -        NSTRING_SET_RAW(n); +        NODE_STRING_SET_RAW(n);        sn->end = (UChar* )p;      } @@ -1532,7 +2118,7 @@ str_node_can_be_split(StrNode* sn, OnigEncoding enc)  static int  node_str_head_pad(StrNode* sn, int num, UChar val)  { -  UChar buf[NODE_STR_BUF_SIZE]; +  UChar buf[NODE_STRING_BUF_SIZE];    int i, len;    len = sn->end - sn->s; @@ -2090,6 +2676,7 @@ is_invalid_quantifier_target(Node* node)  {    switch (NODE_TYPE(node)) {    case NODE_ANCHOR: +  case NODE_GIMMICK:      return 1;      break; @@ -2212,6 +2799,56 @@ onig_reduce_nested_quantifier(Node* pnode, Node* cnode)    onig_node_free(cnode);  } +static int +node_new_general_newline(Node** node, ScanEnv* env) +{ +  int r; +  int dlen, alen; +  UChar buf[ONIGENC_CODE_TO_MBC_MAXLEN * 2]; +  Node* crnl; +  Node* ncc; +  Node* x; +  CClassNode* cc; + +  dlen = ONIGENC_CODE_TO_MBC(env->enc, 0x0d, buf); +  if (dlen < 0) return dlen; +  alen = ONIGENC_CODE_TO_MBC(env->enc, 0x0a, buf + dlen); +  if (alen < 0) return alen; + +  crnl = node_new_str_raw(buf, buf + dlen + alen); +  CHECK_NULL_RETURN_MEMERR(crnl); + +  ncc = node_new_cclass(); +  if (IS_NULL(ncc)) goto err2; + +  cc = CCLASS_(ncc); +  if (dlen == 1) { +    bitset_set_range(cc->bs, 0x0a, 0x0d); +  } +  else { +    r = add_code_range(&(cc->mbuf), env, 0x0a, 0x0d); +    if (r != 0) { +    err1: +      onig_node_free(ncc); +    err2: +      onig_node_free(crnl); +      return ONIGERR_MEMORY; +    } +  } + +  if (ONIGENC_IS_UNICODE_ENCODING(env->enc)) { +    r = add_code_range(&(cc->mbuf), env, 0x85, 0x85); +    if (r != 0) goto err1; +    r = add_code_range(&(cc->mbuf), env, 0x2028, 0x2029); +    if (r != 0) goto err1; +  } + +  x = node_new_enclosure_if_else(crnl, 0, ncc); +  if (IS_NULL(x)) goto err1; + +  *node = x; +  return 0; +}  enum TokenSyms {    TK_EOT      = 0,   /* end of token */ @@ -2233,6 +2870,11 @@ enum TokenSyms {    TK_CC_OPEN,    TK_QUOTE_OPEN,    TK_CHAR_PROPERTY,    /* \p{...}, \P{...} */ +  TK_KEEP,             /* \K */ +  TK_GENERAL_NEWLINE,  /* \R */ +  TK_NO_NEWLINE,       /* \N */ +  TK_TRUE_ANYCHAR,     /* \O */ +    /* in cc */    TK_CC_CLOSE,    TK_CC_RANGE, @@ -2452,8 +3094,9 @@ static OnigCodePoint  get_name_end_code_point(OnigCodePoint start)  {    switch (start) { -  case '<':  return (OnigCodePoint )'>'; break; +  case '<':  return (OnigCodePoint )'>';  break;    case '\'': return (OnigCodePoint )'\''; break; +  case '(':  return (OnigCodePoint )')';  break;    default:      break;    } @@ -2706,7 +3349,7 @@ fetch_name(OnigCodePoint start_code, UChar** src, UChar* end,      if (c != end_code) {        r = ONIGERR_INVALID_GROUP_NAME; -      name_end = end; +      goto err;      }      if (*num_type != IS_NOT_NUM) { @@ -3378,6 +4021,26 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)        tok->u.prop.not   = 1;        break; +    case 'K': +      if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_CAPITAL_K_KEEP)) break; +      tok->type = TK_KEEP; +      break; + +    case 'R': +      if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_CAPITAL_R_GENERAL_NEWLINE)) break; +      tok->type = TK_GENERAL_NEWLINE; +      break; + +    case 'N': +      if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_CAPITAL_N_O_SUPER_DOT)) break; +      tok->type = TK_NO_NEWLINE; +      break; + +    case 'O': +      if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_CAPITAL_N_O_SUPER_DOT)) break; +      tok->type = TK_TRUE_ANYCHAR; +      break; +      case 'A':        if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_AZ_BUF_ANCHOR)) break;      begin_buf: @@ -3561,7 +4224,7 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)            if (r == 1) tok->u.backref.exist_level = 1;            else        tok->u.backref.exist_level = 0;  #else -          r = fetch_name(&p, end, &name_end, env, &back_num, &num_type, 1); +          r = fetch_name(c, &p, end, &name_end, env, &back_num, &num_type, 1);  #endif            if (r < 0) return r; @@ -3616,7 +4279,7 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)        break;  #endif -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL      case 'g':        if (!PEND && IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_G_SUBEXP_CALL)) {          PFETCH(c); @@ -3815,14 +4478,14 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)      case '^':        if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_LINE_ANCHOR)) break;        tok->type = TK_ANCHOR; -      tok->u.subtype = (IS_SINGLELINE(env->option) +      tok->u.subtype = (IS_SINGLELINE(env->options)  			? ANCHOR_BEGIN_BUF : ANCHOR_BEGIN_LINE);        break;      case '$':        if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_LINE_ANCHOR)) break;        tok->type = TK_ANCHOR; -      tok->u.subtype = (IS_SINGLELINE(env->option) +      tok->u.subtype = (IS_SINGLELINE(env->options)  			? ANCHOR_SEMI_END_BUF : ANCHOR_END_LINE);        break; @@ -3837,7 +4500,7 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)        break;      case '#': -      if (IS_EXTEND(env->option)) { +      if (IS_EXTEND(env->options)) {          while (!PEND) {            PFETCH(c);            if (ONIGENC_IS_CODE_NEWLINE(enc, c)) @@ -3849,7 +4512,7 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)        break;      case ' ': case '\t': case '\n': case '\r': case '\f': -      if (IS_EXTEND(env->option)) +      if (IS_EXTEND(env->options))          goto start;        break; @@ -4640,7 +5303,7 @@ parse_enclosure(Node** np, OnigToken* tok, int term, UChar** src, UChar* end,    *np = NULL;    if (PEND) return ONIGERR_END_PATTERN_WITH_UNMATCHED_PARENTHESIS; -  option = env->option; +  option = env->options;    if (PPEEK_IS('?') &&        IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_GROUP_EFFECT)) {      PINC; @@ -4711,7 +5374,7 @@ parse_enclosure(Node** np, OnigToken* tok, int term, UChar** src, UChar* end,            r = name_add(env->reg, name, name_end, num, env);            if (r != 0) return r; -          *np = node_new_enclosure_memory(1); +          *np = node_new_memory(1);            CHECK_NULL_RETURN_MEMERR(*np);            ENCLOSURE_(*np)->m.regnum = num;            if (list_capture != 0) @@ -4729,6 +5392,259 @@ parse_enclosure(Node** np, OnigToken* tok, int term, UChar** src, UChar* end,  #endif        break; +    case '~': +      if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_TILDE_ABSENT_GROUP)) { +        Node* absent; +        Node* expr; +        int head_bar; +        int is_range_cutter; + +        if (PEND) return ONIGERR_END_PATTERN_IN_GROUP; + +        if (PPEEK_IS('|')) { // (?~|generator|absent) +          PINC; +          if (PEND) return ONIGERR_END_PATTERN_IN_GROUP; + +          head_bar = 1; +          if (PPEEK_IS(')')) { // (?~|)  : absent clear +            PINC; +            r = node_new_update_var_gimmick(np, UPDATE_VAR_RIGHT_RANGE_INIT, +                                            0, env); +            if (r != 0) return r; +            goto end; +          } +        } +        else +          head_bar = 0; + +        r = fetch_token(tok, &p, end, env); +        if (r < 0) return r; +        r = parse_subexp(&absent, tok, term, &p, end, env); +        if (r < 0) { +          onig_node_free(absent); +          return r; +        } + +        expr = NULL_NODE; +        is_range_cutter = 0; +        if (head_bar != 0) { +          Node* top = absent; +          if (NODE_TYPE(top) != NODE_ALT || IS_NULL(NODE_CDR(top))) { +            expr = NULL_NODE; +            is_range_cutter = 1; +            //return ONIGERR_INVALID_ABSENT_GROUP_GENERATOR_PATTERN; +          } +          else { +            absent = NODE_CAR(top); +            expr   = NODE_CDR(top); +            NODE_CAR(top) = NULL_NODE; +            NODE_CDR(top) = NULL_NODE; +            onig_node_free(top); +            if (IS_NULL(NODE_CDR(expr))) { +              top = expr; +              expr = NODE_CAR(top); +              NODE_CAR(top) = NULL_NODE; +              onig_node_free(top); +            } +          } +        } + +        r = make_absent_tree(np, absent, expr, is_range_cutter, env); +        if (r != 0) { +          return r; +        } +        goto end; +      } +      else { +        return ONIGERR_UNDEFINED_GROUP_OPTION; +      } +      break; + +    case '(': +      /* (?()...) */ +      if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_LPAREN_IF_ELSE)) { +        UChar *prev; +        Node* condition; +        int condition_is_checker; + +        if (PEND) return ONIGERR_END_PATTERN_IN_GROUP; +        PFETCH(c); +        if (PEND) return ONIGERR_END_PATTERN_IN_GROUP; + +        if (ONIGENC_IS_CODE_DIGIT(enc, c) +            || c == '-' || c == '+' || c == '<' || c == '\'') { +          UChar* name_end; +          int back_num; +          int exist_level; +          int level; +          enum REF_NUM num_type; +          int is_enclosed; + +          is_enclosed = (c == '<' || c == '\'') ? 1 : 0; +          if (! is_enclosed) +            PUNFETCH; +          prev = p; +          exist_level = 0; +#ifdef USE_BACKREF_WITH_LEVEL +          name_end = NULL_UCHARP; /* no need. escape gcc warning. */ +          r = fetch_name_with_level( +                    (OnigCodePoint )(is_enclosed != 0 ? c : '('), +                    &p, end, &name_end, +                    env, &back_num, &level, &num_type); +          if (r == 1) exist_level = 1; +#else +          r = fetch_name((OnigCodePoint )(is_enclosed != 0 ? c : '('), +                         &p, end, &name_end, env, &back_num, &num_type, 1); +#endif +          if (r < 0) { +            if (is_enclosed == 0) { +              goto any_condition; +            } +            else +              return r; +          } + +          condition_is_checker = 1; +          if (num_type != IS_NOT_NUM) { +            if (num_type == IS_REL_NUM) { +              back_num = backref_rel_to_abs(back_num, env); +            } +            if (back_num <= 0) +              return ONIGERR_INVALID_BACKREF; + +            if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_STRICT_CHECK_BACKREF)) { +              if (back_num > env->num_mem || +                  IS_NULL(SCANENV_MEMENV(env)[back_num].node)) +                return ONIGERR_INVALID_BACKREF; +            } + +            condition = node_new_backref_checker(1, &back_num, 0, +#ifdef USE_BACKREF_WITH_LEVEL +                                                 exist_level, level, +#endif +                                                 env); +          } +          else { +            int num; +            int* backs; + +            num = onig_name_to_group_numbers(env->reg, prev, name_end, &backs); +            if (num <= 0) { +              onig_scan_env_set_error_string(env, +                        ONIGERR_UNDEFINED_NAME_REFERENCE, prev, name_end); +              return ONIGERR_UNDEFINED_NAME_REFERENCE; +            } +            if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_STRICT_CHECK_BACKREF)) { +              int i; +              for (i = 0; i < num; i++) { +                if (backs[i] > env->num_mem || +                    IS_NULL(SCANENV_MEMENV(env)[backs[i]].node)) +                  return ONIGERR_INVALID_BACKREF; +              } +            } + +            condition = node_new_backref_checker(num, backs, 1, +#ifdef USE_BACKREF_WITH_LEVEL +                                                 exist_level, level, +#endif +                                                 env); +          } + +          if (is_enclosed != 0) { +            if (PEND) goto err_if_else; +            PFETCH(c); +            if (c != ')') goto err_if_else; +          } +        } +        else { +        any_condition: +          PUNFETCH; +          condition_is_checker = 0; +          r = fetch_token(tok, &p, end, env); +          if (r < 0) return r; +          r = parse_subexp(&condition, tok, term, &p, end, env); +          if (r < 0) { +            onig_node_free(condition); +            return r; +          } +        } + +        CHECK_NULL_RETURN_MEMERR(condition); + +        if (PEND) { +        err_if_else: +          onig_node_free(condition); +          return ONIGERR_END_PATTERN_IN_GROUP; +        } + +        if (PPEEK_IS(')')) { /* case: empty body: make backref checker */ +          if (condition_is_checker == 0) { +            onig_node_free(condition); +            return ONIGERR_INVALID_IF_ELSE_SYNTAX; +          } +          PFETCH(c); +          *np = condition; +        } +        else { /* if-else */ +          int then_is_empty; +          Node *Then, *Else; + +          if (PPEEK_IS('|')) { +            PFETCH(c); +            Then = 0; +            then_is_empty = 1; +          } +          else +            then_is_empty = 0; + +          r = fetch_token(tok, &p, end, env); +          if (r < 0) { +            onig_node_free(condition); +            return r; +          } +          r = parse_subexp(&target, tok, term, &p, end, env); +          if (r < 0) { +            onig_node_free(condition); +            onig_node_free(target); +            return r; +          } + +          if (then_is_empty != 0) { +            Else = target; +          } +          else { +            if (NODE_TYPE(target) == NODE_ALT) { +              Then = NODE_CAR(target); +              if (NODE_CDR(NODE_CDR(target)) == NULL_NODE) { +                Else = NODE_CAR(NODE_CDR(target)); +                cons_node_free_alone(NODE_CDR(target)); +              } +              else { +                Else = NODE_CDR(target); +              } +              cons_node_free_alone(target); +            } +            else { +              Then = target; +              Else = 0; +            } +          } + +          *np = node_new_enclosure_if_else(condition, Then, Else); +          if (IS_NULL(*np)) { +            onig_node_free(condition); +            onig_node_free(Then); +            onig_node_free(Else); +            return ONIGERR_MEMORY; +          } +        } +        goto end; +      } +      else { +        return ONIGERR_UNDEFINED_GROUP_OPTION; +      } +      break; +      case '@':        if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_ATMARK_CAPTURE_HISTORY)) {  #ifdef USE_NAMED_GROUP @@ -4741,7 +5657,7 @@ parse_enclosure(Node** np, OnigToken* tok, int term, UChar** src, UChar* end,            PUNFETCH;          }  #endif -        *np = node_new_enclosure_memory(0); +        *np = node_new_memory(0);          CHECK_NULL_RETURN_MEMERR(*np);          num = scan_env_add_mem_entry(env);          if (num < 0) { @@ -4772,11 +5688,11 @@ parse_enclosure(Node** np, OnigToken* tok, int term, UChar** src, UChar* end,              break;            case '-':  neg = 1; break; -          case 'x':  ONOFF(option, ONIG_OPTION_EXTEND,     neg); break; -          case 'i':  ONOFF(option, ONIG_OPTION_IGNORECASE, neg); break; +          case 'x':  OPTION_NEGATE(option, ONIG_OPTION_EXTEND,     neg); break; +          case 'i':  OPTION_NEGATE(option, ONIG_OPTION_IGNORECASE, neg); break;            case 's':              if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL)) { -              ONOFF(option, ONIG_OPTION_MULTILINE,  neg); +              OPTION_NEGATE(option, ONIG_OPTION_MULTILINE,  neg);              }              else                return ONIGERR_UNDEFINED_GROUP_OPTION; @@ -4784,17 +5700,17 @@ parse_enclosure(Node** np, OnigToken* tok, int term, UChar** src, UChar* end,            case 'm':              if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL)) { -              ONOFF(option, ONIG_OPTION_SINGLELINE, (neg == 0 ? 1 : 0)); +              OPTION_NEGATE(option, ONIG_OPTION_SINGLELINE, (neg == 0 ? 1 : 0));              }              else if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_RUBY)) { -              ONOFF(option, ONIG_OPTION_MULTILINE,  neg); +              OPTION_NEGATE(option, ONIG_OPTION_MULTILINE,  neg);              }              else                return ONIGERR_UNDEFINED_GROUP_OPTION;              break;  #ifdef USE_POSIXLINE_OPTION            case 'p': -            ONOFF(option, ONIG_OPTION_MULTILINE|ONIG_OPTION_SINGLELINE, neg); +            OPTION_NEGATE(option, ONIG_OPTION_MULTILINE|ONIG_OPTION_SINGLELINE, neg);              break;  #endif            default: @@ -4808,13 +5724,13 @@ parse_enclosure(Node** np, OnigToken* tok, int term, UChar** src, UChar* end,              return 2; /* option only */            }            else if (c == ':') { -            OnigOptionType prev = env->option; +            OnigOptionType prev = env->options; -            env->option     = option; +            env->options = option;              r = fetch_token(tok, &p, end, env);              if (r < 0) return r;              r = parse_subexp(&target, tok, term, &p, end, env); -            env->option = prev; +            env->options = prev;              if (r < 0) {                onig_node_free(target);                return r; @@ -4837,10 +5753,10 @@ parse_enclosure(Node** np, OnigToken* tok, int term, UChar** src, UChar* end,      }    }    else { -    if (ONIG_IS_OPTION_ON(env->option, ONIG_OPTION_DONT_CAPTURE_GROUP)) +    if (ONIG_IS_OPTION_ON(env->options, ONIG_OPTION_DONT_CAPTURE_GROUP))        goto group; -    *np = node_new_enclosure_memory(0); +    *np = node_new_memory(0);      CHECK_NULL_RETURN_MEMERR(*np);      num = scan_env_add_mem_entry(env);      if (num < 0) return num; @@ -4866,6 +5782,7 @@ parse_enclosure(Node** np, OnigToken* tok, int term, UChar** src, UChar* end,      }    } + end:    *src = p;    return 0;  } @@ -4888,7 +5805,7 @@ set_quantifier(Node* qnode, Node* target, int group, ScanEnv* env)      return 1;    switch (NODE_TYPE(target)) { -  case NODE_STR: +  case NODE_STRING:      if (! group) {        StrNode* sn = STR_(target);        if (str_node_can_be_split(sn, env->enc)) { @@ -5060,7 +5977,7 @@ i_apply_case_fold(OnigCodePoint from, OnigCodePoint to[],            /* char-class expanded multi-char only               compare with string folded at match time. */ -          NSTRING_SET_AMBIG(snode); +          NODE_STRING_SET_AMBIG(snode);          }          else {            r = onig_node_str_cat(snode, buf, buf + len); @@ -5106,13 +6023,13 @@ parse_exp(Node** np, OnigToken* tok, int term,      if (r == 1) group = 1;      else if (r == 2) { /* option only */        Node* target; -      OnigOptionType prev = env->option; +      OnigOptionType prev = env->options; -      env->option = ENCLOSURE_(*np)->o.option; +      env->options = ENCLOSURE_(*np)->o.options;        r = fetch_token(tok, src, end, env);        if (r < 0) return r;        r = parse_subexp(&target, tok, term, src, end, env); -      env->option = prev; +      env->options = prev;        if (r < 0) {          onig_node_free(target);          return r; @@ -5161,7 +6078,7 @@ parse_exp(Node** np, OnigToken* tok, int term,          if (len >= ONIGENC_MBC_MINLEN(env->enc)) {            if (len == enclen(env->enc, STR_(*np)->s)) {//should not enclen_end()              r = fetch_token(tok, src, end, env); -            NSTRING_CLEAR_RAW(*np); +            NODE_STRING_CLEAR_RAW(*np);              goto string_end;            }          } @@ -5176,7 +6093,7 @@ parse_exp(Node** np, OnigToken* tok, int term,              rem = ONIGENC_MBC_MINLEN(env->enc) - len;              (void )node_str_head_pad(STR_(*np), rem, (UChar )0);              if (len + rem == enclen(env->enc, STR_(*np)->s)) { -              NSTRING_CLEAR_RAW(*np); +              NODE_STRING_CLEAR_RAW(*np);                goto string_end;              }            } @@ -5266,7 +6183,7 @@ parse_exp(Node** np, OnigToken* tok, int term,        if (r != 0) return r;        cc = CCLASS_(*np); -      if (IS_IGNORECASE(env->option)) { +      if (IS_IGNORECASE(env->options)) {          IApplyCaseFoldArg iarg;          iarg.env      = env; @@ -5293,12 +6210,12 @@ parse_exp(Node** np, OnigToken* tok, int term,      break;    case TK_ANYCHAR: -    *np = node_new_ctype(CTYPE_ANYCHAR, 0); +    *np = node_new_anychar();      CHECK_NULL_RETURN_MEMERR(*np);      break;    case TK_ANYCHAR_ANYTIME: -    *np = node_new_ctype(CTYPE_ANYCHAR, 0); +    *np = node_new_anychar();      CHECK_NULL_RETURN_MEMERR(*np);      qn = node_new_quantifier(0, REPEAT_INFINITE, 0);      CHECK_NULL_RETURN_MEMERR(qn); @@ -5319,7 +6236,7 @@ parse_exp(Node** np, OnigToken* tok, int term,      CHECK_NULL_RETURN_MEMERR(*np);      break; -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL    case TK_CALL:      {        int gnum = tok->u.call.gnum; @@ -5352,6 +6269,26 @@ parse_exp(Node** np, OnigToken* tok, int term,      }      break; +  case TK_KEEP: +    r = node_new_keep(np, env); +    if (r < 0) return r; +    break; + +  case TK_GENERAL_NEWLINE: +    r = node_new_general_newline(np, env); +    if (r < 0) return r; +    break; + +  case TK_NO_NEWLINE: +    r = node_new_no_newline(np, env); +    if (r < 0) return r; +    break; + +  case TK_TRUE_ANYCHAR: +    r = node_new_true_anychar(np, env); +    if (r < 0) return r; +    break; +    default:      return ONIGERR_PARSER_BUG;      break; @@ -5526,13 +6463,13 @@ parse_regexp(Node** top, UChar** src, UChar* end, ScanEnv* env)    return 0;  } -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL  static int  make_call_zero_body(Node* node, ScanEnv* env, Node** rnode)  {    int r; -  Node* x = node_new_enclosure_memory(0 /* 0: is not named */); +  Node* x = node_new_memory(0 /* 0: is not named */);    CHECK_NULL_RETURN_MEMERR(x);    NODE_BODY(x) = node; @@ -5560,7 +6497,7 @@ onig_parse_tree(Node** root, const UChar* pattern, const UChar* end,  #endif    scan_env_clear(env); -  env->option         = reg->options; +  env->options        = reg->options;    env->case_fold_flag = reg->case_fold_flag;    env->enc            = reg->enc;    env->syntax         = reg->syntax; @@ -5576,7 +6513,7 @@ onig_parse_tree(Node** root, const UChar* pattern, const UChar* end,    p = (UChar* )pattern;    r = parse_regexp(root, &p, (UChar* )end, env); -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL    if (r != 0) return r;    if (env->has_call_zero != 0) { | 
