diff options
author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2017-08-13 13:55:30 +0200 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2017-08-13 13:55:30 +0200 |
commit | a89a4ac904bc93b1d93b410394fa05c23260351b (patch) | |
tree | b10c64aff1d79627925154364772774fc82d07ff /src/regcomp.c | |
parent | b6c6e4122f35fbead1e9661dfb2d852b39faf8ff (diff) | |
parent | ae063b1e6ea3d97ea4e3404bfd8289895619d04f (diff) |
Merge branch 'release/6.5.0-1'6.5.0-1
Diffstat (limited to 'src/regcomp.c')
-rw-r--r-- | src/regcomp.c | 1102 |
1 files changed, 834 insertions, 268 deletions
diff --git a/src/regcomp.c b/src/regcomp.c index db83739..47023cb 100644 --- a/src/regcomp.c +++ b/src/regcomp.c @@ -147,7 +147,7 @@ swap_node(Node* a, Node* b) Node c; c = *a; *a = *b; *b = c; - if (NODE_TYPE(a) == NODE_STR) { + if (NODE_TYPE(a) == NODE_STRING) { StrNode* sn = STR_(a); if (sn->capa == 0) { int len = sn->end - sn->s; @@ -156,7 +156,7 @@ swap_node(Node* a, Node* b) } } - if (NODE_TYPE(b) == NODE_STR) { + if (NODE_TYPE(b) == NODE_STRING) { StrNode* sn = STR_(b); if (sn->capa == 0) { int len = sn->end - sn->s; @@ -169,11 +169,11 @@ swap_node(Node* a, Node* b) static OnigLen distance_add(OnigLen d1, OnigLen d2) { - if (d1 == ONIG_INFINITE_DISTANCE || d2 == ONIG_INFINITE_DISTANCE) - return ONIG_INFINITE_DISTANCE; + if (d1 == INFINITE_LEN || d2 == INFINITE_LEN) + return INFINITE_LEN; else { - if (d1 <= ONIG_INFINITE_DISTANCE - d2) return d1 + d2; - else return ONIG_INFINITE_DISTANCE; + if (d1 <= INFINITE_LEN - d2) return d1 + d2; + else return INFINITE_LEN; } } @@ -182,10 +182,10 @@ distance_multiply(OnigLen d, int m) { if (m == 0) return 0; - if (d < ONIG_INFINITE_DISTANCE / m) + if (d < INFINITE_LEN / m) return d * m; else - return ONIG_INFINITE_DISTANCE; + return INFINITE_LEN; } static int @@ -230,7 +230,7 @@ onig_bbuf_init(BBuf* buf, int size) } -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL static int unset_addr_list_init(UnsetAddrList* list, int size) @@ -271,7 +271,7 @@ unset_addr_list_add(UnsetAddrList* list, int offset, struct _Node* node) list->num++; return 0; } -#endif /* USE_SUBEXP_CALL */ +#endif /* USE_CALL */ static int @@ -347,6 +347,24 @@ add_option(regex_t* reg, OnigOptionType option) } static int +add_save_type(regex_t* reg, enum SaveType type) +{ + SaveType t = (SaveType )type; + + BBUF_ADD(reg, &t, SIZE_SAVE_TYPE); + return 0; +} + +static int +add_update_var_type(regex_t* reg, enum UpdateVarType type) +{ + UpdateVarType t = (UpdateVarType )type; + + BBUF_ADD(reg, &t, SIZE_UPDATE_VAR_TYPE); + return 0; +} + +static int add_opcode_rel_addr(regex_t* reg, int opcode, int addr) { int r; @@ -466,7 +484,7 @@ compile_tree_empty_check(Node* node, regex_t* reg, int empty_info, ScanEnv* env) return r; } -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL static int compile_call(CallNode* node, regex_t* reg, ScanEnv* env) { @@ -545,7 +563,7 @@ compile_length_string_node(Node* node, regex_t* reg) if (sn->end <= sn->s) return 0; - ambig = NSTRING_IS_AMBIG(node); + ambig = NODE_STRING_IS_AMBIG(node); p = prev = sn->s; prev_len = enclen(enc, p); @@ -594,7 +612,7 @@ compile_string_node(Node* node, regex_t* reg) return 0; end = sn->end; - ambig = NSTRING_IS_AMBIG(node); + ambig = NODE_STRING_IS_AMBIG(node); p = prev = sn->s; prev_len = enclen(enc, p); @@ -767,7 +785,7 @@ compile_range_repeat_node(QuantNode* qn, int target_len, int empty_info, if (r != 0) return r; if ( -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL NODE_IS_IN_MULTI_ENTRY(qn) || #endif NODE_IS_IN_REAL_REPEAT(qn)) { @@ -893,7 +911,7 @@ compile_quantifier_node(QuantNode* qn, regex_t* reg, ScanEnv* env) r = compile_tree_n_times(NODE_QUANT_BODY(qn), qn->lower, reg, env); if (r != 0) return r; if (IS_NOT_NULL(qn->next_head_exact) && !CKN_ON) { - if (IS_MULTILINE(reg->options)) + if (IS_MULTILINE(CTYPE_OPTION(NODE_QUANT_BODY(qn), reg))) r = add_opcode(reg, OP_ANYCHAR_ML_STAR_PEEK_NEXT); else r = add_opcode(reg, OP_ANYCHAR_STAR_PEEK_NEXT); @@ -906,7 +924,7 @@ compile_quantifier_node(QuantNode* qn, regex_t* reg, ScanEnv* env) return add_bytes(reg, STR_(qn->next_head_exact)->s, 1); } else { - if (IS_MULTILINE(reg->options)) { + if (IS_MULTILINE(CTYPE_OPTION(NODE_QUANT_BODY(qn), reg))) { r = add_opcode(reg, (CKN_ON ? OP_STATE_CHECK_ANYCHAR_ML_STAR : OP_ANYCHAR_ML_STAR)); @@ -1109,7 +1127,7 @@ compile_quantifier_node(QuantNode* qn, regex_t* reg, ScanEnv* env) r = compile_tree_n_times(NODE_QUANT_BODY(qn), qn->lower, reg, env); if (r != 0) return r; if (IS_NOT_NULL(qn->next_head_exact)) { - if (IS_MULTILINE(reg->options)) + if (IS_MULTILINE(CTYPE_OPTION(NODE_QUANT_BODY(qn), reg))) r = add_opcode(reg, OP_ANYCHAR_ML_STAR_PEEK_NEXT); else r = add_opcode(reg, OP_ANYCHAR_STAR_PEEK_NEXT); @@ -1117,7 +1135,7 @@ compile_quantifier_node(QuantNode* qn, regex_t* reg, ScanEnv* env) return add_bytes(reg, STR_(qn->next_head_exact)->s, 1); } else { - if (IS_MULTILINE(reg->options)) + if (IS_MULTILINE(CTYPE_OPTION(NODE_QUANT_BODY(qn), reg))) return add_opcode(reg, OP_ANYCHAR_ML_STAR); else return add_opcode(reg, OP_ANYCHAR_STAR); @@ -1229,7 +1247,7 @@ compile_length_option_node(EnclosureNode* node, regex_t* reg) int tlen; OnigOptionType prev = reg->options; - reg->options = node->o.option; + reg->options = node->o.options; tlen = compile_length_tree(NODE_ENCLOSURE_BODY(node), reg); reg->options = prev; @@ -1249,8 +1267,8 @@ compile_option_node(EnclosureNode* node, regex_t* reg, ScanEnv* env) int r; OnigOptionType prev = reg->options; - if (IS_DYNAMIC_OPTION(prev ^ node->o.option)) { - r = add_opcode_option(reg, OP_SET_OPTION_PUSH, node->o.option); + if (IS_DYNAMIC_OPTION(prev ^ node->o.options)) { + r = add_opcode_option(reg, OP_SET_OPTION_PUSH, node->o.options); if (r != 0) return r; r = add_opcode_option(reg, OP_SET_OPTION, prev); if (r != 0) return r; @@ -1258,11 +1276,11 @@ compile_option_node(EnclosureNode* node, regex_t* reg, ScanEnv* env) if (r != 0) return r; } - reg->options = node->o.option; + reg->options = node->o.options; r = compile_tree(NODE_ENCLOSURE_BODY(node), reg, env); reg->options = prev; - if (IS_DYNAMIC_OPTION(prev ^ node->o.option)) { + if (IS_DYNAMIC_OPTION(prev ^ node->o.options)) { if (r != 0) return r; r = add_opcode_option(reg, OP_SET_OPTION, prev); } @@ -1287,7 +1305,7 @@ compile_length_enclosure_node(EnclosureNode* node, regex_t* reg) switch (node->type) { case ENCLOSURE_MEMORY: -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL if (node->m.regnum == 0 && NODE_IS_CALLED(node)) { len = tlen + SIZE_OP_CALL + SIZE_OP_JUMP + SIZE_OP_RETURN; @@ -1336,6 +1354,32 @@ compile_length_enclosure_node(EnclosureNode* node, regex_t* reg) } break; + case ENCLOSURE_IF_ELSE: + { + Node* cond = NODE_ENCLOSURE_BODY(node); + Node* Then = node->te.Then; + Node* Else = node->te.Else; + + len = compile_length_tree(cond, reg); + if (len < 0) return len; + len += SIZE_OP_PUSH; + len += SIZE_OP_PUSH_STOP_BT + SIZE_OP_POP_STOP_BT; + + if (IS_NOT_NULL(Then)) { + tlen = compile_length_tree(Then, reg); + if (tlen < 0) return tlen; + len += tlen; + } + + if (IS_NOT_NULL(Else)) { + len += SIZE_OP_JUMP; + tlen = compile_length_tree(Else, reg); + if (tlen < 0) return tlen; + len += tlen; + } + } + break; + default: return ONIGERR_TYPE_BUG; break; @@ -1352,7 +1396,7 @@ compile_enclosure_memory_node(EnclosureNode* node, regex_t* reg, ScanEnv* env) int r; int len; -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL if (node->m.regnum == 0 && NODE_IS_CALLED(node)) { r = add_opcode(reg, OP_CALL); if (r != 0) return r; @@ -1370,9 +1414,7 @@ compile_enclosure_memory_node(EnclosureNode* node, regex_t* reg, ScanEnv* env) r = add_opcode(reg, OP_RETURN); return r; } -#endif -#ifdef USE_SUBEXP_CALL if (NODE_IS_CALLED(node)) { r = add_opcode(reg, OP_CALL); if (r != 0) return r; @@ -1404,7 +1446,7 @@ compile_enclosure_memory_node(EnclosureNode* node, regex_t* reg, ScanEnv* env) r = compile_tree(NODE_ENCLOSURE_BODY(node), reg, env); if (r != 0) return r; -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL if (MEM_STATUS_AT0(reg->bt_mem_end, node->m.regnum)) r = add_opcode(reg, (NODE_IS_RECURSION(node) ? OP_MEMORY_END_PUSH_REC : OP_MEMORY_END_PUSH)); @@ -1434,14 +1476,15 @@ compile_enclosure_node(EnclosureNode* node, regex_t* reg, ScanEnv* env) { int r, len; - if (node->type == ENCLOSURE_OPTION) - return compile_option_node(node, reg, env); - switch (node->type) { case ENCLOSURE_MEMORY: r = compile_enclosure_memory_node(node, reg, env); break; + case ENCLOSURE_OPTION: + r = compile_option_node(node, reg, env); + break; + case ENCLOSURE_STOP_BACKTRACK: if (NODE_IS_STOP_BT_SIMPLE_REPEAT(node)) { QuantNode* qn = QUANT_(NODE_ENCLOSURE_BODY(node)); @@ -1469,6 +1512,49 @@ compile_enclosure_node(EnclosureNode* node, regex_t* reg, ScanEnv* env) } break; + case ENCLOSURE_IF_ELSE: + { + int cond_len, then_len, jump_len; + Node* cond = NODE_ENCLOSURE_BODY(node); + Node* Then = node->te.Then; + Node* Else = node->te.Else; + + r = add_opcode(reg, OP_PUSH_STOP_BT); + if (r != 0) return r; + + cond_len = compile_length_tree(cond, reg); + if (cond_len < 0) return cond_len; + if (IS_NOT_NULL(Then)) { + then_len = compile_length_tree(Then, reg); + if (then_len < 0) return then_len; + } + else + then_len = 0; + + jump_len = cond_len + then_len + SIZE_OP_POP_STOP_BT; + if (IS_NOT_NULL(Else)) jump_len += SIZE_OP_JUMP; + + r = add_opcode_rel_addr(reg, OP_PUSH, jump_len); + if (r != 0) return r; + r = compile_tree(cond, reg, env); + if (r != 0) return r; + r = add_opcode(reg, OP_POP_STOP_BT); + if (r != 0) return r; + + if (IS_NOT_NULL(Then)) { + r = compile_tree(Then, reg, env); + if (r != 0) return r; + } + + if (IS_NOT_NULL(Else)) { + int else_len = compile_length_tree(Else, reg); + r = add_opcode_rel_addr(reg, OP_JUMP, else_len); + if (r != 0) return r; + r = compile_tree(Else, reg, env); + } + } + break; + default: return ONIGERR_TYPE_BUG; break; @@ -1490,10 +1576,10 @@ compile_length_anchor_node(AnchorNode* node, regex_t* reg) switch (node->type) { case ANCHOR_PREC_READ: - len = SIZE_OP_PUSH_POS + tlen + SIZE_OP_POP_POS; + len = SIZE_OP_PREC_READ_START + tlen + SIZE_OP_PREC_READ_END; break; case ANCHOR_PREC_READ_NOT: - len = SIZE_OP_PUSH_POS_NOT + tlen + SIZE_OP_FAIL_POS; + len = SIZE_OP_PUSH_PREC_READ_NOT + tlen + SIZE_OP_FAIL_PREC_READ_NOT; break; case ANCHOR_LOOK_BEHIND: len = SIZE_OP_LOOK_BEHIND + tlen; @@ -1531,21 +1617,21 @@ compile_anchor_node(AnchorNode* node, regex_t* reg, ScanEnv* env) #endif case ANCHOR_PREC_READ: - r = add_opcode(reg, OP_PUSH_POS); + r = add_opcode(reg, OP_PREC_READ_START); if (r != 0) return r; r = compile_tree(NODE_ANCHOR_BODY(node), reg, env); if (r != 0) return r; - r = add_opcode(reg, OP_POP_POS); + r = add_opcode(reg, OP_PREC_READ_END); break; case ANCHOR_PREC_READ_NOT: len = compile_length_tree(NODE_ANCHOR_BODY(node), reg); if (len < 0) return len; - r = add_opcode_rel_addr(reg, OP_PUSH_POS_NOT, len + SIZE_OP_FAIL_POS); + r = add_opcode_rel_addr(reg, OP_PUSH_PREC_READ_NOT, len + SIZE_OP_FAIL_PREC_READ_NOT); if (r != 0) return r; r = compile_tree(NODE_ANCHOR_BODY(node), reg, env); if (r != 0) return r; - r = add_opcode(reg, OP_FAIL_POS); + r = add_opcode(reg, OP_FAIL_PREC_READ_NOT); break; case ANCHOR_LOOK_BEHIND: @@ -1596,6 +1682,67 @@ compile_anchor_node(AnchorNode* node, regex_t* reg, ScanEnv* env) } static int +compile_gimmick_node(GimmickNode* node, regex_t* reg) +{ + int r; + + switch (node->type) { + case GIMMICK_FAIL: + r = add_opcode(reg, OP_FAIL); + break; + + case GIMMICK_KEEP: + r = add_opcode(reg, OP_PUSH_SAVE_VAL); + if (r != 0) return r; + r = add_save_type(reg, SAVE_KEEP); + if (r != 0) return r; + r = add_mem_num(reg, node->id); + break; + + case GIMMICK_SAVE: + r = add_opcode(reg, OP_PUSH_SAVE_VAL); + if (r != 0) return r; + r = add_save_type(reg, node->detail_type); + if (r != 0) return r; + r = add_mem_num(reg, node->id); + break; + + case GIMMICK_UPDATE_VAR: + r = add_opcode(reg, OP_UPDATE_VAR); + if (r != 0) return r; + r = add_update_var_type(reg, node->detail_type); + if (r != 0) return r; + r = add_mem_num(reg, node->id); + break; + } + + return r; +} + +static int +compile_length_gimmick_node(GimmickNode* node, regex_t* reg) +{ + int len; + + switch (node->type) { + case GIMMICK_FAIL: + len = SIZE_OP_FAIL; + break; + + case GIMMICK_KEEP: + case GIMMICK_SAVE: + len = SIZE_OP_PUSH_SAVE_VAL; + break; + + case GIMMICK_UPDATE_VAR: + len = SIZE_OP_UPDATE_VAR; + break; + } + + return len; +} + +static int compile_length_tree(Node* node, regex_t* reg) { int len, r; @@ -1624,8 +1771,8 @@ compile_length_tree(Node* node, regex_t* reg) } break; - case NODE_STR: - if (NSTRING_IS_RAW(node)) + case NODE_STRING: + if (NODE_STRING_IS_RAW(node)) r = compile_length_string_raw_node(STR_(node), reg); else r = compile_length_string_node(node, reg); @@ -1639,28 +1786,39 @@ compile_length_tree(Node* node, regex_t* reg) r = SIZE_OPCODE; break; - case NODE_BREF: + case NODE_BACKREF: { - BRefNode* br = BREF_(node); + BackRefNode* br = BACKREF_(node); + if (NODE_IS_CHECKER(node)) { #ifdef USE_BACKREF_WITH_LEVEL - if (NODE_IS_NEST_LEVEL(node)) { - r = SIZE_OPCODE + SIZE_OPTION + SIZE_LENGTH + - SIZE_LENGTH + (SIZE_MEMNUM * br->back_num); - } - else + if (NODE_IS_NEST_LEVEL(node)) { + r = SIZE_OPCODE + SIZE_LENGTH + SIZE_LENGTH + (SIZE_MEMNUM * br->back_num); + } + else #endif - if (br->back_num == 1) { - r = ((!IS_IGNORECASE(reg->options) && br->back_static[0] <= 2) - ? SIZE_OPCODE : (SIZE_OPCODE + SIZE_MEMNUM)); + r = SIZE_OPCODE + SIZE_LENGTH + (SIZE_MEMNUM * br->back_num); } else { - r = SIZE_OPCODE + SIZE_LENGTH + (SIZE_MEMNUM * br->back_num); +#ifdef USE_BACKREF_WITH_LEVEL + if (NODE_IS_NEST_LEVEL(node)) { + r = SIZE_OPCODE + SIZE_OPTION + SIZE_LENGTH + + SIZE_LENGTH + (SIZE_MEMNUM * br->back_num); + } + else +#endif + if (br->back_num == 1) { + r = ((!IS_IGNORECASE(reg->options) && br->back_static[0] <= 2) + ? SIZE_OPCODE : (SIZE_OPCODE + SIZE_MEMNUM)); + } + else { + r = SIZE_OPCODE + SIZE_LENGTH + (SIZE_MEMNUM * br->back_num); + } } } break; -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL case NODE_CALL: r = SIZE_OP_CALL; break; @@ -1678,6 +1836,10 @@ compile_length_tree(Node* node, regex_t* reg) r = compile_length_anchor_node(ANCHOR_(node), reg); break; + case NODE_GIMMICK: + r = compile_length_gimmick_node(GIMMICK_(node), reg); + break; + default: return ONIGERR_TYPE_BUG; break; @@ -1713,7 +1875,8 @@ compile_tree(Node* node, regex_t* reg, ScanEnv* env) do { len = compile_length_tree(NODE_CAR(node), reg); if (IS_NOT_NULL(NODE_CDR(node))) { - r = add_opcode_rel_addr(reg, OP_PUSH, len + SIZE_OP_JUMP); + enum OpCode push = NODE_IS_SUPER(node) ? OP_PUSH_SUPER : OP_PUSH; + r = add_opcode_rel_addr(reg, push, len + SIZE_OP_JUMP); if (r != 0) break; } r = compile_tree(NODE_CAR(node), reg, env); @@ -1727,8 +1890,8 @@ compile_tree(Node* node, regex_t* reg, ScanEnv* env) } break; - case NODE_STR: - if (NSTRING_IS_RAW(node)) + case NODE_STRING: + if (NODE_STRING_IS_RAW(node)) r = compile_string_raw_node(STR_(node), reg); else r = compile_string_node(node, reg); @@ -1744,7 +1907,7 @@ compile_tree(Node* node, regex_t* reg, ScanEnv* env) switch (CTYPE_(node)->ctype) { case CTYPE_ANYCHAR: - if (IS_MULTILINE(reg->options)) + if (IS_MULTILINE(CTYPE_OPTION(node, reg))) r = add_opcode(reg, OP_ANYCHAR_ML); else r = add_opcode(reg, OP_ANYCHAR); @@ -1764,69 +1927,86 @@ compile_tree(Node* node, regex_t* reg, ScanEnv* env) } break; - case NODE_BREF: + case NODE_BACKREF: { - BRefNode* br = BREF_(node); + BackRefNode* br = BACKREF_(node); + if (NODE_IS_CHECKER(node)) { #ifdef USE_BACKREF_WITH_LEVEL - if (NODE_IS_NEST_LEVEL(node)) { - r = add_opcode(reg, OP_BACKREF_WITH_LEVEL); - if (r != 0) return r; - r = add_option(reg, (reg->options & ONIG_OPTION_IGNORECASE)); - if (r != 0) return r; - r = add_length(reg, br->nest_level); - if (r != 0) return r; + if (NODE_IS_NEST_LEVEL(node)) { + r = add_opcode(reg, OP_BACKREF_CHECK_WITH_LEVEL); + if (r != 0) return r; + r = add_length(reg, br->nest_level); + if (r != 0) return r; + } + else +#endif + { + r = add_opcode(reg, OP_BACKREF_CHECK); + if (r != 0) return r; + } goto add_bacref_mems; } - else -#endif - if (br->back_num == 1) { - n = br->back_static[0]; - if (IS_IGNORECASE(reg->options)) { - r = add_opcode(reg, OP_BACKREFN_IC); + else { +#ifdef USE_BACKREF_WITH_LEVEL + if (NODE_IS_NEST_LEVEL(node)) { + r = add_opcode(reg, OP_BACKREF_WITH_LEVEL); + if (r != 0) return r; + r = add_option(reg, (reg->options & ONIG_OPTION_IGNORECASE)); + if (r != 0) return r; + r = add_length(reg, br->nest_level); if (r != 0) return r; - r = add_mem_num(reg, n); + + goto add_bacref_mems; } - else { - switch (n) { - case 1: r = add_opcode(reg, OP_BACKREF1); break; - case 2: r = add_opcode(reg, OP_BACKREF2); break; - default: - r = add_opcode(reg, OP_BACKREFN); + else +#endif + if (br->back_num == 1) { + n = br->back_static[0]; + if (IS_IGNORECASE(reg->options)) { + r = add_opcode(reg, OP_BACKREF_N_IC); if (r != 0) return r; r = add_mem_num(reg, n); - break; } - } - } - else { - int i; - int* p; - - if (IS_IGNORECASE(reg->options)) { - r = add_opcode(reg, OP_BACKREF_MULTI_IC); + else { + switch (n) { + case 1: r = add_opcode(reg, OP_BACKREF1); break; + case 2: r = add_opcode(reg, OP_BACKREF2); break; + default: + r = add_opcode(reg, OP_BACKREF_N); + if (r != 0) return r; + r = add_mem_num(reg, n); + break; + } + } } else { - r = add_opcode(reg, OP_BACKREF_MULTI); - } - if (r != 0) return r; + int i; + int* p; -#ifdef USE_BACKREF_WITH_LEVEL - add_bacref_mems: -#endif - r = add_length(reg, br->back_num); - if (r != 0) return r; - p = BACKREFS_P(br); - for (i = br->back_num - 1; i >= 0; i--) { - r = add_mem_num(reg, p[i]); + if (IS_IGNORECASE(reg->options)) { + r = add_opcode(reg, OP_BACKREF_MULTI_IC); + } + else { + r = add_opcode(reg, OP_BACKREF_MULTI); + } if (r != 0) return r; + + add_bacref_mems: + r = add_length(reg, br->back_num); + if (r != 0) return r; + p = BACKREFS_P(br); + for (i = br->back_num - 1; i >= 0; i--) { + r = add_mem_num(reg, p[i]); + if (r != 0) return r; + } } } } break; -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL case NODE_CALL: r = compile_call(CALL_(node), reg, env); break; @@ -1844,6 +2024,10 @@ compile_tree(Node* node, regex_t* reg, ScanEnv* env) r = compile_anchor_node(ANCHOR_(node), reg, env); break; + case NODE_GIMMICK: + r = compile_gimmick_node(GIMMICK_(node), reg); + break; + default: #ifdef ONIG_DEBUG fprintf(stderr, "compile_tree: undefined node type %d\n", NODE_TYPE(node)); @@ -1898,6 +2082,18 @@ noname_disable_map(Node** plink, GroupNumRemap* map, int* counter) r = noname_disable_map(plink, map, counter); } } + else if (en->type == ENCLOSURE_IF_ELSE) { + r = noname_disable_map(&(NODE_ENCLOSURE_BODY(en)), map, counter); + if (r != 0) return r; + if (IS_NOT_NULL(en->te.Then)) { + r = noname_disable_map(&(en->te.Then), map, counter); + if (r != 0) return r; + } + if (IS_NOT_NULL(en->te.Else)) { + r = noname_disable_map(&(en->te.Else), map, counter); + if (r != 0) return r; + } + } else r = noname_disable_map(&(NODE_BODY(node)), map, counter); } @@ -1920,7 +2116,7 @@ renumber_node_backref(Node* node, GroupNumRemap* map) { int i, pos, n, old_num; int *backs; - BRefNode* bn = BREF_(node); + BackRefNode* bn = BACKREF_(node); if (! NODE_IS_BY_NAME(node)) return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED; @@ -1957,11 +2153,29 @@ renumber_by_map(Node* node, GroupNumRemap* map) break; case NODE_QUANT: - case NODE_ENCLOSURE: r = renumber_by_map(NODE_BODY(node), map); break; - case NODE_BREF: + case NODE_ENCLOSURE: + { + EnclosureNode* en = ENCLOSURE_(node); + r = renumber_by_map(NODE_BODY(node), map); + if (r != 0) return r; + + if (en->type == ENCLOSURE_IF_ELSE) { + if (IS_NOT_NULL(en->te.Then)) { + r = renumber_by_map(en->te.Then, map); + if (r != 0) return r; + } + if (IS_NOT_NULL(en->te.Else)) { + r = renumber_by_map(en->te.Else, map); + if (r != 0) return r; + } + } + } + break; + + case NODE_BACKREF: r = renumber_node_backref(node, map); break; @@ -1995,11 +2209,30 @@ numbered_ref_check(Node* node) break; /* fall */ case NODE_QUANT: - case NODE_ENCLOSURE: r = numbered_ref_check(NODE_BODY(node)); break; - case NODE_BREF: + case NODE_ENCLOSURE: + { + EnclosureNode* en = ENCLOSURE_(node); + r = numbered_ref_check(NODE_BODY(node)); + if (r != 0) return r; + + if (en->type == ENCLOSURE_IF_ELSE) { + if (IS_NOT_NULL(en->te.Then)) { + r = numbered_ref_check(en->te.Then); + if (r != 0) return r; + } + if (IS_NOT_NULL(en->te.Else)) { + r = numbered_ref_check(en->te.Else); + if (r != 0) return r; + } + } + } + + break; + + case NODE_BACKREF: if (! NODE_IS_BY_NAME(node)) return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED; break; @@ -2052,7 +2285,7 @@ disable_noname_group_capture(Node** root, regex_t* reg, ScanEnv* env) } #endif /* USE_NAMED_GROUP */ -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL static int unset_addr_list_fix(UnsetAddrList* uslist, regex_t* reg) { @@ -2061,9 +2294,11 @@ unset_addr_list_fix(UnsetAddrList* uslist, regex_t* reg) AbsAddrType addr; for (i = 0; i < uslist->num; i++) { + if (! NODE_IS_ADDR_FIXED(uslist->us[i].target)) + return ONIGERR_PARSER_BUG; + en = ENCLOSURE_(uslist->us[i].target); - if (! NODE_IS_ADDR_FIXED(en)) return ONIGERR_PARSER_BUG; - addr = en->m.called_addr; + addr = en->m.called_addr; offset = uslist->us[i].offset; BBUF_WRITE(reg, offset, &addr, SIZE_ABSADDR); @@ -2120,7 +2355,7 @@ get_char_length_tree1(Node* node, regex_t* reg, int* len, int level) } break; - case NODE_STR: + case NODE_STRING: { StrNode* sn = STR_(node); UChar *s = sn->s; @@ -2135,16 +2370,21 @@ get_char_length_tree1(Node* node, regex_t* reg, int* len, int level) { QuantNode* qn = QUANT_(node); if (qn->lower == qn->upper) { - r = get_char_length_tree1(NODE_BODY(node), reg, &tlen, level); - if (r == 0) - *len = distance_multiply(tlen, qn->lower); + if (qn->upper == 0) { + *len = 0; + } + else { + r = get_char_length_tree1(NODE_BODY(node), reg, &tlen, level); + if (r == 0) + *len = distance_multiply(tlen, qn->lower); + } } else r = GET_CHAR_LEN_VARLEN; } break; -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL case NODE_CALL: if (! NODE_IS_RECURSION(node)) r = get_char_length_tree1(NODE_BODY(node), reg, len, level); @@ -2166,7 +2406,7 @@ get_char_length_tree1(Node* node, regex_t* reg, int* len, int level) EnclosureNode* en = ENCLOSURE_(node); switch (en->type) { case ENCLOSURE_MEMORY: -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL if (NODE_IS_CLEN_FIXED(node)) *len = en->char_len; else { @@ -2182,6 +2422,31 @@ get_char_length_tree1(Node* node, regex_t* reg, int* len, int level) case ENCLOSURE_STOP_BACKTRACK: r = get_char_length_tree1(NODE_BODY(node), reg, len, level); break; + case ENCLOSURE_IF_ELSE: + { + int clen, elen; + r = get_char_length_tree1(NODE_BODY(node), reg, &clen, level); + if (r == 0) { + if (IS_NOT_NULL(en->te.Then)) { + r = get_char_length_tree1(en->te.Then, reg, &tlen, level); + if (r != 0) break; + } + else tlen = 0; + if (IS_NOT_NULL(en->te.Else)) { + r = get_char_length_tree1(en->te.Else, reg, &elen, level); + if (r != 0) break; + } + else elen = 0; + + if (clen + tlen != elen) { + r = GET_CHAR_LEN_VARLEN; + } + else { + *len = elen; + } + } + } + break; default: break; } @@ -2189,8 +2454,13 @@ get_char_length_tree1(Node* node, regex_t* reg, int* len, int level) break; case NODE_ANCHOR: + case NODE_GIMMICK: break; + case NODE_BACKREF: + if (NODE_IS_CHECKER(node)) + break; + /* fall */ default: r = GET_CHAR_LEN_VARLEN; break; @@ -2241,7 +2511,7 @@ is_exclusive(Node* x, Node* y, regex_t* reg) } break; - case NODE_STR: + case NODE_STRING: goto swap; break; @@ -2318,7 +2588,7 @@ is_exclusive(Node* x, Node* y, regex_t* reg) } break; - case NODE_STR: + case NODE_STRING: goto swap; break; @@ -2328,10 +2598,10 @@ is_exclusive(Node* x, Node* y, regex_t* reg) } break; - case NODE_STR: + case NODE_STRING: { StrNode* xs = STR_(x); - if (NSTRING_LEN(x) == 0) + if (NODE_STRING_LEN(x) == 0) break; //c = *(xs->s); @@ -2362,13 +2632,13 @@ is_exclusive(Node* x, Node* y, regex_t* reg) } break; - case NODE_STR: + case NODE_STRING: { UChar *q; StrNode* ys = STR_(y); - len = NSTRING_LEN(x); - if (len > NSTRING_LEN(y)) len = NSTRING_LEN(y); - if (NSTRING_IS_AMBIG(x) || NSTRING_IS_AMBIG(y)) { + len = NODE_STRING_LEN(x); + if (len > NODE_STRING_LEN(y)) len = NODE_STRING_LEN(y); + if (NODE_STRING_IS_AMBIG(x) || NODE_STRING_IS_AMBIG(y)) { /* tiny version */ return 0; } @@ -2399,9 +2669,9 @@ get_head_value_node(Node* node, int exact, regex_t* reg) Node* n = NULL_NODE; switch (NODE_TYPE(node)) { - case NODE_BREF: + case NODE_BACKREF: case NODE_ALT: -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL case NODE_CALL: #endif break; @@ -2420,7 +2690,7 @@ get_head_value_node(Node* node, int exact, regex_t* reg) n = get_head_value_node(NODE_CAR(node), exact, reg); break; - case NODE_STR: + case NODE_STRING: { StrNode* sn = STR_(node); @@ -2428,7 +2698,7 @@ get_head_value_node(Node* node, int exact, regex_t* reg) break; if (exact != 0 && - !NSTRING_IS_RAW(node) && IS_IGNORECASE(reg->options)) { + !NODE_STRING_IS_RAW(node) && IS_IGNORECASE(reg->options)) { } else { n = node; @@ -2456,7 +2726,7 @@ get_head_value_node(Node* node, int exact, regex_t* reg) { OnigOptionType options = reg->options; - reg->options = ENCLOSURE_(node)->o.option; + reg->options = ENCLOSURE_(node)->o.options; n = get_head_value_node(NODE_BODY(node), exact, reg); reg->options = options; } @@ -2464,6 +2734,7 @@ get_head_value_node(Node* node, int exact, regex_t* reg) case ENCLOSURE_MEMORY: case ENCLOSURE_STOP_BACKTRACK: + case ENCLOSURE_IF_ELSE: n = get_head_value_node(NODE_BODY(node), exact, reg); break; } @@ -2475,6 +2746,7 @@ get_head_value_node(Node* node, int exact, regex_t* reg) n = get_head_value_node(NODE_BODY(node), exact, reg); break; + case NODE_GIMMICK: default: break; } @@ -2512,6 +2784,15 @@ check_type_tree(Node* node, int type_mask, int enclosure_mask, int anchor_mask) return 1; r = check_type_tree(NODE_BODY(node), type_mask, enclosure_mask, anchor_mask); + if (r == 0 && en->type == ENCLOSURE_IF_ELSE) { + if (IS_NOT_NULL(en->te.Then)) { + r = check_type_tree(en->te.Then, type_mask, enclosure_mask, anchor_mask); + if (r != 0) break; + } + if (IS_NOT_NULL(en->te.Else)) { + r = check_type_tree(en->te.Else, type_mask, enclosure_mask, anchor_mask); + } + } } break; @@ -2524,6 +2805,7 @@ check_type_tree(Node* node, int type_mask, int enclosure_mask, int anchor_mask) r = check_type_tree(NODE_BODY(node), type_mask, enclosure_mask, anchor_mask); break; + case NODE_GIMMICK: default: break; } @@ -2531,31 +2813,31 @@ check_type_tree(Node* node, int type_mask, int enclosure_mask, int anchor_mask) } static OnigLen -get_min_len(Node* node, ScanEnv* env) +tree_min_len(Node* node, ScanEnv* env) { OnigLen len; OnigLen tmin; len = 0; switch (NODE_TYPE(node)) { - case NODE_BREF: - { + case NODE_BACKREF: + if (! NODE_IS_CHECKER(node)) { int i; int* backs; MemEnv* mem_env = SCANENV_MEMENV(env); - BRefNode* br = BREF_(node); + BackRefNode* br = BACKREF_(node); if (NODE_IS_RECURSION(node)) break; backs = BACKREFS_P(br); - len = get_min_len(mem_env[backs[0]].node, env); + len = tree_min_len(mem_env[backs[0]].node, env); for (i = 1; i < br->back_num; i++) { - tmin = get_min_len(mem_env[backs[i]].node, env); + tmin = tree_min_len(mem_env[backs[i]].node, env); if (len > tmin) len = tmin; } } break; -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL case NODE_CALL: { Node* t = NODE_BODY(node); @@ -2564,15 +2846,15 @@ get_min_len(Node* node, ScanEnv* env) len = ENCLOSURE_(t)->min_len; } else - len = get_min_len(t, env); + len = tree_min_len(t, env); } break; #endif case NODE_LIST: do { - tmin = get_min_len(NODE_CAR(node), env); - len += tmin; + tmin = tree_min_len(NODE_CAR(node), env); + len = distance_add(len, tmin); } while (IS_NOT_NULL(node = NODE_CDR(node))); break; @@ -2582,14 +2864,14 @@ get_min_len(Node* node, ScanEnv* env) y = node; do { x = NODE_CAR(y); - tmin = get_min_len(x, env); + tmin = tree_min_len(x, env); if (y == node) len = tmin; else if (len > tmin) len = tmin; } while (IS_NOT_NULL(y = NODE_CDR(y))); } break; - case NODE_STR: + case NODE_STRING: { StrNode* sn = STR_(node); len = sn->end - sn->s; @@ -2598,7 +2880,7 @@ get_min_len(Node* node, ScanEnv* env) case NODE_CTYPE: case NODE_CCLASS: - len = 1; + len = ONIGENC_MBC_MINLEN(env->enc); break; case NODE_QUANT: @@ -2606,7 +2888,7 @@ get_min_len(Node* node, ScanEnv* env) QuantNode* qn = QUANT_(node); if (qn->lower > 0) { - len = get_min_len(NODE_BODY(node), env); + len = tree_min_len(NODE_BODY(node), env); len = distance_multiply(len, qn->lower); } } @@ -2624,7 +2906,7 @@ get_min_len(Node* node, ScanEnv* env) len = 0; // recursive else { NODE_STATUS_ADD(node, NST_MARK1); - len = get_min_len(NODE_BODY(node), env); + len = tree_min_len(NODE_BODY(node), env); NODE_STATUS_REMOVE(node, NST_MARK1); en->min_len = len; @@ -2635,12 +2917,34 @@ get_min_len(Node* node, ScanEnv* env) case ENCLOSURE_OPTION: case ENCLOSURE_STOP_BACKTRACK: - len = get_min_len(NODE_BODY(node), env); + len = tree_min_len(NODE_BODY(node), env); + break; + case ENCLOSURE_IF_ELSE: + { + int elen; + len = tree_min_len(NODE_BODY(node), env); + if (IS_NOT_NULL(en->te.Then)) + len += tree_min_len(en->te.Then, env); + if (IS_NOT_NULL(en->te.Else)) + elen = tree_min_len(en->te.Else, env); + else elen = 0; + + if (elen < len) len = elen; + } break; } } break; + case NODE_GIMMICK: + { + GimmickNode* g = GIMMICK_(node); + if (g->type == GIMMICK_FAIL) { + len = INFINITE_LEN; + break; + } + } + /* fall */ case NODE_ANCHOR: default: break; @@ -2650,7 +2954,7 @@ get_min_len(Node* node, ScanEnv* env) } static OnigLen -get_max_len(Node* node, ScanEnv* env) +tree_max_len(Node* node, ScanEnv* env) { OnigLen len; OnigLen tmax; @@ -2659,19 +2963,19 @@ get_max_len(Node* node, ScanEnv* env) switch (NODE_TYPE(node)) { case NODE_LIST: do { - tmax = get_max_len(NODE_CAR(node), env); + tmax = tree_max_len(NODE_CAR(node), env); len = distance_add(len, tmax); } while (IS_NOT_NULL(node = NODE_CDR(node))); break; case NODE_ALT: do { - tmax = get_max_len(NODE_CAR(node), env); + tmax = tree_max_len(NODE_CAR(node), env); if (len < tmax) len = tmax; } while (IS_NOT_NULL(node = NODE_CDR(node))); break; - case NODE_STR: + case NODE_STRING: { StrNode* sn = STR_(node); len = sn->end - sn->s; @@ -2683,30 +2987,30 @@ get_max_len(Node* node, ScanEnv* env) len = ONIGENC_MBC_MAXLEN_DIST(env->enc); break; - case NODE_BREF: - { + case NODE_BACKREF: + if (! NODE_IS_CHECKER(node)) { int i; int* backs; MemEnv* mem_env = SCANENV_MEMENV(env); - BRefNode* br = BREF_(node); + BackRefNode* br = BACKREF_(node); if (NODE_IS_RECURSION(node)) { - len = ONIG_INFINITE_DISTANCE; + len = INFINITE_LEN; break; } backs = BACKREFS_P(br); for (i = 0; i < br->back_num; i++) { - tmax = get_max_len(mem_env[backs[i]].node, env); + tmax = tree_max_len(mem_env[backs[i]].node, env); if (len < tmax) len = tmax; } } break; -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL case NODE_CALL: if (! NODE_IS_RECURSION(node)) - len = get_max_len(NODE_BODY(node), env); + len = tree_max_len(NODE_BODY(node), env); else - len = ONIG_INFINITE_DISTANCE; + len = INFINITE_LEN; break; #endif @@ -2715,12 +3019,12 @@ get_max_len(Node* node, ScanEnv* env) QuantNode* qn = QUANT_(node); if (qn->upper != 0) { - len = get_max_len(NODE_BODY(node), env); + len = tree_max_len(NODE_BODY(node), env); if (len != 0) { if (! IS_REPEAT_INFINITE(qn->upper)) len = distance_multiply(len, qn->upper); else - len = ONIG_INFINITE_DISTANCE; + len = INFINITE_LEN; } } } @@ -2735,10 +3039,10 @@ get_max_len(Node* node, ScanEnv* env) len = en->max_len; else { if (NODE_IS_MARK1(node)) - len = ONIG_INFINITE_DISTANCE; + len = INFINITE_LEN; else { NODE_STATUS_ADD(node, NST_MARK1); - len = get_max_len(NODE_BODY(node), env); + len = tree_max_len(NODE_BODY(node), env); NODE_STATUS_REMOVE(node, NST_MARK1); en->max_len = len; @@ -2749,13 +3053,29 @@ get_max_len(Node* node, ScanEnv* env) case ENCLOSURE_OPTION: case ENCLOSURE_STOP_BACKTRACK: - len = get_max_len(NODE_BODY(node), env); + len = tree_max_len(NODE_BODY(node), env); + break; + case ENCLOSURE_IF_ELSE: + { + int tlen, elen; + len = tree_max_len(NODE_BODY(node), env); + if (IS_NOT_NULL(en->te.Then)) { + tlen = tree_max_len(en->te.Then, env); + len = distance_add(len, tlen); + } + if (IS_NOT_NULL(en->te.Else)) + elen = tree_max_len(en->te.Else, env); + else elen = 0; + + if (elen > len) len = elen; + } break; } } break; case NODE_ANCHOR: + case NODE_GIMMICK: default: break; } @@ -2783,14 +3103,31 @@ check_backrefs(Node* node, ScanEnv* env) } /* fall */ case NODE_QUANT: + r = check_backrefs(NODE_BODY(node), env); + break; + case NODE_ENCLOSURE: r = check_backrefs(NODE_BODY(node), env); + { + EnclosureNode* en = ENCLOSURE_(node); + + if (en->type == ENCLOSURE_IF_ELSE) { + if (r != 0) return r; + if (IS_NOT_NULL(en->te.Then)) { + r = check_backrefs(en->te.Then, env); + if (r != 0) return r; + } + if (IS_NOT_NULL(en->te.Else)) { + r = check_backrefs(en->te.Else, env); + } + } + } break; - case NODE_BREF: + case NODE_BACKREF: { int i; - BRefNode* br = BREF_(node); + BackRefNode* br = BACKREF_(node); int* backs = BACKREFS_P(br); MemEnv* mem_env = SCANENV_MEMENV(env); @@ -2813,7 +3150,7 @@ check_backrefs(Node* node, ScanEnv* env) } -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL #define RECURSION_EXIST (1<<0) #define RECURSION_MUST (1<<1) @@ -2822,6 +3159,7 @@ check_backrefs(Node* node, ScanEnv* env) static int infinite_recursive_call_check(Node* node, ScanEnv* env, int head) { + int ret; int r = 0; switch (NODE_TYPE(node)) { @@ -2829,15 +3167,14 @@ infinite_recursive_call_check(Node* node, ScanEnv* env, int head) { Node *x; OnigLen min; - int ret; x = node; do { ret = infinite_recursive_call_check(NODE_CAR(x), env, head); if (ret < 0 || (ret & RECURSION_INFINITE) != 0) return ret; r |= ret; - if (head) { - min = get_min_len(NODE_CAR(x), env); + if (head != 0) { + min = tree_min_len(NODE_CAR(x), env); if (min != 0) head = 0; } } while (IS_NOT_NULL(x = NODE_CDR(x))); @@ -2846,7 +3183,6 @@ infinite_recursive_call_check(Node* node, ScanEnv* env, int head) case NODE_ALT: { - int ret; int must; must = RECURSION_MUST; @@ -2894,6 +3230,31 @@ infinite_recursive_call_check(Node* node, ScanEnv* env, int head) NODE_STATUS_REMOVE(node, NST_MARK2); } } + else if (en->type == ENCLOSURE_IF_ELSE) { + int eret; + + ret = infinite_recursive_call_check(NODE_BODY(node), env, head); + if (ret < 0 || (ret & RECURSION_INFINITE) != 0) return ret; + r |= ret; + if (IS_NOT_NULL(en->te.Then)) { + OnigLen min; + if (head != 0) { + min = tree_min_len(NODE_BODY(node), env); + } + else min = 0; + + ret = infinite_recursive_call_check(en->te.Then, env, min != 0 ? 0:head); + if (ret < 0 || (ret & RECURSION_INFINITE) != 0) return ret; + r |= ret; + } + if (IS_NOT_NULL(en->te.Else)) { + eret = infinite_recursive_call_check(en->te.Else, env, head); + if (eret < 0 || (eret & RECURSION_INFINITE) != 0) return eret; + r |= (eret & RECURSION_EXIST); + if ((eret & RECURSION_MUST) == 0) + r &= ~RECURSION_MUST; + } + } else { r = infinite_recursive_call_check(NODE_BODY(node), env, head); } @@ -2948,6 +3309,16 @@ infinite_recursive_call_check_trav(Node* node, ScanEnv* env) NODE_STATUS_REMOVE(node, NST_MARK1); } } + else if (en->type == ENCLOSURE_IF_ELSE) { + if (IS_NOT_NULL(en->te.Then)) { + r = infinite_recursive_call_check_trav(en->te.Then, env); + if (r != 0) return r; + } + if (IS_NOT_NULL(en->te.Else)) { + r = infinite_recursive_call_check_trav(en->te.Else, env); + if (r != 0) return r; + } + } } r = infinite_recursive_call_check_trav(NODE_BODY(node), env); @@ -2987,7 +3358,10 @@ recursive_call_check(Node* node) case NODE_CALL: r = recursive_call_check(NODE_BODY(node)); - if (r != 0) NODE_STATUS_ADD(node, NST_RECURSION); + if (r != 0) { + if (NODE_IS_MARK1(NODE_BODY(node))) + NODE_STATUS_ADD(node, NST_RECURSION); + } break; case NODE_ENCLOSURE: @@ -3005,6 +3379,16 @@ recursive_call_check(Node* node) NODE_STATUS_REMOVE(node, NST_MARK2); } } + else if (en->type == ENCLOSURE_IF_ELSE) { + r = 0; + if (IS_NOT_NULL(en->te.Then)) { + r |= recursive_call_check(en->te.Then); + } + if (IS_NOT_NULL(en->te.Else)) { + r |= recursive_call_check(en->te.Else); + } + r |= recursive_call_check(NODE_BODY(node)); + } else { r = recursive_call_check(NODE_BODY(node)); } @@ -3058,6 +3442,8 @@ recursive_call_check_trav(Node* node, ScanEnv* env, int state) case NODE_ENCLOSURE: { + int ret; + int state1; EnclosureNode* en = ENCLOSURE_(node); if (en->type == ENCLOSURE_MEMORY) { @@ -3075,16 +3461,25 @@ recursive_call_check_trav(Node* node, ScanEnv* env, int state) } } - { - int ret; - int state1 = state; + state1 = state; + if (NODE_IS_RECURSION(node)) + state1 |= IN_RECURSION; - if (NODE_IS_RECURSION(node)) - state1 |= IN_RECURSION; + ret = recursive_call_check_trav(NODE_BODY(node), env, state1); + if (ret == FOUND_CALLED_NODE) + r = FOUND_CALLED_NODE; - ret = recursive_call_check_trav(NODE_BODY(node), env, state1); - if (ret == FOUND_CALLED_NODE) - r = FOUND_CALLED_NODE; + if (en->type == ENCLOSURE_IF_ELSE) { + if (IS_NOT_NULL(en->te.Then)) { + ret = recursive_call_check_trav(en->te.Then, env, state1); + if (ret == FOUND_CALLED_NODE) + r = FOUND_CALLED_NODE; + } + if (IS_NOT_NULL(en->te.Else)) { + ret = recursive_call_check_trav(en->te.Else, env, state1); + if (ret == FOUND_CALLED_NODE) + r = FOUND_CALLED_NODE; + } } } break; @@ -3126,7 +3521,7 @@ divide_look_behind_alternatives(Node* node) if (anc_type == ANCHOR_LOOK_BEHIND_NOT) { np = node; do { - SET_NODE_TYPE(np, NODE_LIST); /* alt -> list */ + NODE_SET_TYPE(np, NODE_LIST); /* alt -> list */ } while (IS_NOT_NULL(np = NODE_CDR(np))); } return 0; @@ -3257,8 +3652,8 @@ expand_case_fold_make_rem_string(Node** rnode, UChar *s, UChar *end, return r; } - NSTRING_SET_AMBIG(node); - NSTRING_SET_DONT_GET_OPT_INFO(node); + NODE_STRING_SET_AMBIG(node); + NODE_STRING_SET_DONT_GET_OPT_INFO(node); *rnode = node; return 0; } @@ -3386,7 +3781,7 @@ expand_case_fold_string(Node* node, regex_t* reg) OnigCaseFoldCodeItem items[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM]; StrNode* sn = STR_(node); - if (NSTRING_IS_AMBIG(node)) return 0; + if (NODE_STRING_IS_AMBIG(node)) return 0; start = sn->s; end = sn->end; @@ -3529,10 +3924,8 @@ setup_comb_exp_check(Node* node, int state, ScanEnv* env) switch (NODE_TYPE(node)) { case NODE_LIST: { - Node* prev = NULL_NODE; do { r = setup_comb_exp_check(NODE_CAR(node), r, env); - prev = NODE_CAR(node); } while (r >= 0 && IS_NOT_NULL(node = NODE_CDR(node))); } break; @@ -3619,8 +4012,8 @@ setup_comb_exp_check(Node* node, int state, ScanEnv* env) switch (en->type) { case ENCLOSURE_MEMORY: { - if (env->curr_max_regnum < en->regnum) - env->curr_max_regnum = en->regnum; + if (env->curr_max_regnum < en->m.regnum) + env->curr_max_regnum = en->m.regnum; r = setup_comb_exp_check(NODE_ENCLOSURE_BODY(en), state, env); } @@ -3633,7 +4026,7 @@ setup_comb_exp_check(Node* node, int state, ScanEnv* env) } break; -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL case NODE_CALL: if (NODE_IS_RECURSION(node)) env->has_recursion = 1; @@ -3668,7 +4061,7 @@ quantifiers_memory_node_info(Node* node) } break; -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL case NODE_CALL: if (NODE_IS_RECURSION(node)) { return QUANT_BODY_IS_EMPTY_REC; /* tiny version */ @@ -3702,17 +4095,32 @@ quantifiers_memory_node_info(Node* node) case ENCLOSURE_STOP_BACKTRACK: r = quantifiers_memory_node_info(NODE_BODY(node)); break; + case ENCLOSURE_IF_ELSE: + { + int v; + r = quantifiers_memory_node_info(NODE_BODY(node)); + if (IS_NOT_NULL(en->te.Then)) { + v = quantifiers_memory_node_info(en->te.Then); + if (v > r) r = v; + } + if (IS_NOT_NULL(en->te.Else)) { + v = quantifiers_memory_node_info(en->te.Else); + if (v > r) r = v; + } + } + break; default: break; } } break; - case NODE_BREF: - case NODE_STR: + case NODE_BACKREF: + case NODE_STRING: case NODE_CTYPE: case NODE_CCLASS: case NODE_ANCHOR: + case NODE_GIMMICK: default: break; } @@ -3729,7 +4137,7 @@ quantifiers_memory_node_info(Node* node) #define IN_ZERO_REPEAT (1<<4) #define IN_MULTI_ENTRY (1<<5) -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL #ifdef __GNUC__ __inline @@ -3745,7 +4153,7 @@ setup_call_node_call(CallNode* cn, ScanEnv* env, int state) #ifdef USE_NAMED_GROUP if (env->num_named > 0 && IS_SYNTAX_BV(env->syntax, ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP) && - !ONIG_IS_OPTION_ON(env->option, ONIG_OPTION_CAPTURE_GROUP)) { + !ONIG_IS_OPTION_ON(env->options, ONIG_OPTION_CAPTURE_GROUP)) { return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED; } #endif @@ -3811,10 +4219,26 @@ setup_call2_call(Node* node) break; case NODE_ENCLOSURE: - if (! NODE_IS_MARK1(node)) { - NODE_STATUS_ADD(node, NST_MARK1); - setup_call2_call(NODE_BODY(node)); - NODE_STATUS_REMOVE(node, NST_MARK1); + { + EnclosureNode* en = ENCLOSURE_(node); + + if (en->type == ENCLOSURE_MEMORY) { + if (! NODE_IS_MARK1(node)) { + NODE_STATUS_ADD(node, NST_MARK1); + setup_call2_call(NODE_BODY(node)); + NODE_STATUS_REMOVE(node, NST_MARK1); + } + } + else if (en->type == ENCLOSURE_IF_ELSE) { + setup_call2_call(NODE_BODY(node)); + if (IS_NOT_NULL(en->te.Then)) + setup_call2_call(en->te.Then); + if (IS_NOT_NULL(en->te.Else)) + setup_call2_call(en->te.Else); + } + else { + setup_call2_call(NODE_BODY(node)); + } } break; @@ -3868,11 +4292,29 @@ setup_call(Node* node, ScanEnv* env, int state) break; case NODE_ENCLOSURE: - if ((state & IN_ZERO_REPEAT) != 0) { - NODE_STATUS_ADD(node, NST_IN_ZERO_REPEAT); - ENCLOSURE_(node)->m.entry_count--; + { + EnclosureNode* en = ENCLOSURE_(node); + + if (en->type == ENCLOSURE_MEMORY) { + if ((state & IN_ZERO_REPEAT) != 0) { + NODE_STATUS_ADD(node, NST_IN_ZERO_REPEAT); + ENCLOSURE_(node)->m.entry_count--; + } + r = setup_call(NODE_BODY(node), env, state); + } + else if (en->type == ENCLOSURE_IF_ELSE) { + r = setup_call(NODE_BODY(node), env, state); + if (r != 0) return r; + if (IS_NOT_NULL(en->te.Then)) { + r = setup_call(en->te.Then, env, state); + if (r != 0) return r; + } + if (IS_NOT_NULL(en->te.Else)) + r = setup_call(en->te.Else, env, state); + } + else + r = setup_call(NODE_BODY(node), env, state); } - r = setup_call(NODE_BODY(node), env, state); break; case NODE_CALL: @@ -3918,6 +4360,20 @@ setup_call2(Node* node) case NODE_ENCLOSURE: if (! NODE_IS_IN_ZERO_REPEAT(node)) r = setup_call2(NODE_BODY(node)); + + { + EnclosureNode* en = ENCLOSURE_(node); + + if (r != 0) return r; + if (en->type == ENCLOSURE_IF_ELSE) { + if (IS_NOT_NULL(en->te.Then)) { + r = setup_call2(en->te.Then); + if (r != 0) return r; + } + if (IS_NOT_NULL(en->te.Else)) + r = setup_call2(en->te.Else); + } + } break; case NODE_CALL: @@ -3997,6 +4453,13 @@ setup_called_state_call(Node* node, int state) NODE_STATUS_REMOVE(node, NST_MARK1); } } + else if (en->type == ENCLOSURE_IF_ELSE) { + if (IS_NOT_NULL(en->te.Then)) { + setup_called_state_call(en->te.Then, state); + } + if (IS_NOT_NULL(en->te.Else)) + setup_called_state_call(en->te.Else, state); + } else { setup_called_state_call(NODE_BODY(node), state); } @@ -4025,7 +4488,7 @@ setup_called_state(Node* node, int state) } while (IS_NOT_NULL(node = NODE_CDR(node))); break; -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL case NODE_CALL: setup_called_state_call(node, state); break; @@ -4046,6 +4509,13 @@ setup_called_state(Node* node, int state) case ENCLOSURE_STOP_BACKTRACK: setup_called_state(NODE_BODY(node), state); break; + case ENCLOSURE_IF_ELSE: + setup_called_state(NODE_BODY(node), state); + if (IS_NOT_NULL(en->te.Then)) + setup_called_state(en->te.Then, state); + if (IS_NOT_NULL(en->te.Else)) + setup_called_state(en->te.Else, state); + break; } } break; @@ -4082,16 +4552,17 @@ setup_called_state(Node* node, int state) } break; - case NODE_BREF: - case NODE_STR: + case NODE_BACKREF: + case NODE_STRING: case NODE_CTYPE: case NODE_CCLASS: + case NODE_GIMMICK: default: break; } } -#endif /* USE_SUBEXP_CALL */ +#endif /* USE_CALL */ static int setup_tree(Node* node, regex_t* reg, int state, ScanEnv* env); @@ -4104,8 +4575,9 @@ setup_anchor(Node* node, regex_t* reg, int state, ScanEnv* env) { /* allowed node types in look-behind */ #define ALLOWED_TYPE_IN_LB \ - ( BIT_NODE_LIST | BIT_NODE_ALT | BIT_NODE_STR | BIT_NODE_CCLASS | BIT_NODE_CTYPE \ - | BIT_NODE_ANCHOR | BIT_NODE_ENCLOSURE | BIT_NODE_QUANT | BIT_NODE_CALL ) + ( BIT_NODE_LIST | BIT_NODE_ALT | BIT_NODE_STRING | BIT_NODE_CCLASS \ + | BIT_NODE_CTYPE | BIT_NODE_ANCHOR | BIT_NODE_ENCLOSURE | BIT_NODE_QUANT \ + | BIT_NODE_CALL ) #define ALLOWED_ENCLOSURE_IN_LB ( ENCLOSURE_MEMORY | ENCLOSURE_OPTION ) #define ALLOWED_ENCLOSURE_IN_LB_NOT ENCLOSURE_OPTION @@ -4182,7 +4654,7 @@ setup_quant(Node* node, regex_t* reg, int state, ScanEnv* env) } if (IS_REPEAT_INFINITE(qn->upper) || qn->upper >= 1) { - d = get_min_len(body, env); + d = tree_min_len(body, env); if (d == 0) { #ifdef USE_INSISTENT_CHECK_CAPTURES_STATUS_IN_ENDLESS_REPEAT qn->body_empty_info = quantifiers_memory_node_info(body); @@ -4208,10 +4680,10 @@ setup_quant(Node* node, regex_t* reg, int state, ScanEnv* env) /* expand string */ #define EXPAND_STRING_MAX_LENGTH 100 - if (NODE_TYPE(body) == NODE_STR) { + if (NODE_TYPE(body) == NODE_STRING) { if (!IS_REPEAT_INFINITE(qn->lower) && qn->lower == qn->upper && qn->lower > 1 && qn->lower <= EXPAND_STRING_MAX_LENGTH) { - int len = NSTRING_LEN(body); + int len = NODE_STRING_LEN(body); StrNode* sn = STR_(body); if (len * qn->lower <= EXPAND_STRING_MAX_LENGTH) { @@ -4278,17 +4750,17 @@ setup_tree(Node* node, regex_t* reg, int state, ScanEnv* env) } while (r == 0 && IS_NOT_NULL(node = NODE_CDR(node))); break; - case NODE_STR: - if (IS_IGNORECASE(reg->options) && !NSTRING_IS_RAW(node)) { + case NODE_STRING: + if (IS_IGNORECASE(reg->options) && !NODE_STRING_IS_RAW(node)) { r = expand_case_fold_string(node, reg); } break; - case NODE_BREF: + case NODE_BACKREF: { int i; int* p; - BRefNode* br = BREF_(node); + BackRefNode* br = BACKREF_(node); p = BACKREFS_P(br); for (i = 0; i < br->back_num; i++) { if (p[i] > env->num_mem) return ONIGERR_INVALID_BACKREF; @@ -4311,14 +4783,14 @@ setup_tree(Node* node, regex_t* reg, int state, ScanEnv* env) case ENCLOSURE_OPTION: { OnigOptionType options = reg->options; - reg->options = ENCLOSURE_(node)->o.option; + reg->options = ENCLOSURE_(node)->o.options; r = setup_tree(NODE_BODY(node), reg, state, env); reg->options = options; } break; case ENCLOSURE_MEMORY: -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL state |= en->m.called_state; #endif @@ -4343,6 +4815,17 @@ setup_tree(Node* node, regex_t* reg, int state, ScanEnv* env) } } break; + + case ENCLOSURE_IF_ELSE: + r = setup_tree(NODE_BODY(node), reg, (state | IN_ALT), env); + if (r != 0) return r; + if (IS_NOT_NULL(en->te.Then)) { + r = setup_tree(en->te.Then, reg, (state | IN_ALT), env); + if (r != 0) return r; + } + if (IS_NOT_NULL(en->te.Else)) + r = setup_tree(en->te.Else, reg, (state | IN_ALT), env); + break; } } break; @@ -4355,11 +4838,12 @@ setup_tree(Node* node, regex_t* reg, int state, ScanEnv* env) r = setup_anchor(node, reg, state, env); break; -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL case NODE_CALL: #endif case NODE_CTYPE: case NODE_CCLASS: + case NODE_GIMMICK: default: break; } @@ -4487,7 +4971,7 @@ distance_value(MinMaxLen* mm) OnigLen d; - if (mm->max == ONIG_INFINITE_DISTANCE) return 0; + if (mm->max == INFINITE_LEN) return 0; d = mm->max - mm->min; if (d < (OnigLen )(sizeof(dist_vals)/sizeof(dist_vals[0]))) @@ -5048,15 +5532,15 @@ optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env) } break; - case NODE_STR: + case NODE_STRING: { StrNode* sn = STR_(node); int slen = sn->end - sn->s; - int is_raw = NSTRING_IS_RAW(node); + int is_raw = NODE_STRING_IS_RAW(node); - if (! NSTRING_IS_AMBIG(node)) { + if (! NODE_STRING_IS_AMBIG(node)) { concat_opt_exact_info_str(&opt->exb, sn->s, sn->end, - NSTRING_IS_RAW(node), env->enc); + NODE_STRING_IS_RAW(node), env->enc); if (slen > 0) { add_char_opt_map_info(&opt->map, *(sn->s), env->enc); } @@ -5065,7 +5549,7 @@ optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env) else { int max; - if (NSTRING_IS_DONT_GET_OPT_INFO(node)) { + if (NODE_STRING_IS_DONT_GET_OPT_INFO(node)) { int n = onigenc_strlen(env->enc, sn->s, sn->end); max = ONIGENC_MBC_MAXLEN_DIST(env->enc) * n; } @@ -5191,24 +5675,24 @@ optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env) } break; - case NODE_BREF: - { + case NODE_BACKREF: + if (! NODE_IS_CHECKER(node)) { int i; int* backs; OnigLen min, max, tmin, tmax; MemEnv* mem_env = SCANENV_MEMENV(env->scan_env); - BRefNode* br = BREF_(node); + BackRefNode* br = BACKREF_(node); if (NODE_IS_RECURSION(node)) { - set_mml(&opt->len, 0, ONIG_INFINITE_DISTANCE); + set_mml(&opt->len, 0, INFINITE_LEN); break; } backs = BACKREFS_P(br); - min = get_min_len(mem_env[backs[0]].node, env->scan_env); - max = get_max_len(mem_env[backs[0]].node, env->scan_env); + min = tree_min_len(mem_env[backs[0]].node, env->scan_env); + max = tree_max_len(mem_env[backs[0]].node, env->scan_env); for (i = 1; i < br->back_num; i++) { - tmin = get_min_len(mem_env[backs[i]].node, env->scan_env); - tmax = get_max_len(mem_env[backs[i]].node, env->scan_env); + tmin = tree_min_len(mem_env[backs[i]].node, env->scan_env); + tmax = tree_max_len(mem_env[backs[i]].node, env->scan_env); if (min > tmin) min = tmin; if (max < tmax) max = tmax; } @@ -5216,13 +5700,13 @@ optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env) } break; -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL case NODE_CALL: if (NODE_IS_RECURSION(node)) - set_mml(&opt->len, 0, ONIG_INFINITE_DISTANCE); + set_mml(&opt->len, 0, INFINITE_LEN); else { OnigOptionType save = env->options; - env->options = ENCLOSURE_(NODE_BODY(node))->o.option; + env->options = ENCLOSURE_(NODE_BODY(node))->o.options; r = optimize_node_left(NODE_BODY(node), opt, env); env->options = save; } @@ -5242,7 +5726,7 @@ optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env) if (qn->lower == 0 && IS_REPEAT_INFINITE(qn->upper)) { if (env->mmd.max == 0 && NODE_IS_ANYCHAR(NODE_BODY(node)) && qn->greedy != 0) { - if (IS_MULTILINE(env->options)) + if (IS_MULTILINE(CTYPE_OPTION(NODE_QUANT_BODY(qn), env))) add_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR_ML); else add_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR); @@ -5274,7 +5758,7 @@ optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env) min = distance_multiply(nopt.len.min, qn->lower); if (IS_REPEAT_INFINITE(qn->upper)) - max = (nopt.len.max > 0 ? ONIG_INFINITE_DISTANCE : 0); + max = (nopt.len.max > 0 ? INFINITE_LEN : 0); else max = distance_multiply(nopt.len.max, qn->upper); @@ -5291,20 +5775,20 @@ optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env) { OnigOptionType save = env->options; - env->options = en->o.option; + env->options = en->o.options; r = optimize_node_left(NODE_BODY(node), opt, env); env->options = save; } break; case ENCLOSURE_MEMORY: -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL en->opt_count++; if (en->opt_count > MAX_NODE_OPT_INFO_REF_COUNT) { OnigLen min, max; min = 0; - max = ONIG_INFINITE_DISTANCE; + max = INFINITE_LEN; if (NODE_IS_MIN_FIXED(node)) min = en->min_len; if (NODE_IS_MAX_FIXED(node)) max = en->max_len; set_mml(&opt->len, min, max); @@ -5324,10 +5808,39 @@ optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env) case ENCLOSURE_STOP_BACKTRACK: r = optimize_node_left(NODE_BODY(node), opt, env); break; + + case ENCLOSURE_IF_ELSE: + { + OptEnv nenv; + NodeOptInfo nopt; + + copy_opt_env(&nenv, env); + r = optimize_node_left(NODE_ENCLOSURE_BODY(en), &nopt, &nenv); + if (r == 0) { + add_mml(&nenv.mmd, &nopt.len); + concat_left_node_opt_info(env->enc, opt, &nopt); + if (IS_NOT_NULL(en->te.Then)) { + r = optimize_node_left(en->te.Then, &nopt, &nenv); + if (r == 0) { + concat_left_node_opt_info(env->enc, opt, &nopt); + } + } + + if (IS_NOT_NULL(en->te.Else)) { + r = optimize_node_left(en->te.Else, &nopt, env); + if (r == 0) + alt_merge_node_opt_info(opt, &nopt, env); + } + } + } + break; } } break; + case NODE_GIMMICK: + break; + default: #ifdef ONIG_DEBUG fprintf(stderr, "optimize_node_left: undefined node type %d\n", NODE_TYPE(node)); @@ -5379,7 +5892,7 @@ set_optimize_exact_info(regex_t* reg, OptExactInfo* e) reg->dmin = e->mmd.min; reg->dmax = e->mmd.max; - if (reg->dmin != ONIG_INFINITE_DISTANCE) { + if (reg->dmin != INFINITE_LEN) { reg->threshold_len = reg->dmin + (reg->exact_end - reg->exact); } @@ -5398,7 +5911,7 @@ set_optimize_map_info(regex_t* reg, OptMapInfo* m) reg->dmin = m->mmd.min; reg->dmax = m->mmd.max; - if (reg->dmin != ONIG_INFINITE_DISTANCE) { + if (reg->dmin != INFINITE_LEN) { reg->threshold_len = reg->dmin + 1; } } @@ -5531,14 +6044,14 @@ static void print_enc_string(FILE* fp, OnigEncoding enc, static void print_distance_range(FILE* f, OnigLen a, OnigLen b) { - if (a == ONIG_INFINITE_DISTANCE) + if (a == INFINITE_LEN) fputs("inf", f); else fprintf(f, "(%u)", a); fputs("-", f); - if (b == ONIG_INFINITE_DISTANCE) + if (b == INFINITE_LEN) fputs("inf", f); else fprintf(f, "(%u)", b); @@ -5656,7 +6169,7 @@ onig_free_body(regex_t* reg) if (IS_NOT_NULL(reg->int_map)) xfree(reg->int_map); if (IS_NOT_NULL(reg->int_map_backward)) xfree(reg->int_map_backward); if (IS_NOT_NULL(reg->repeat_range)) xfree(reg->repeat_range); - if (IS_NOT_NULL(reg->chain)) onig_free(reg->chain); + if (IS_NOT_NULL(REG_EXTP(reg))) xfree(REG_EXTP(reg)); #ifdef USE_NAMED_GROUP onig_names_free(reg); @@ -5702,7 +6215,7 @@ onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end, int r, init_size; Node* root; ScanEnv scan_env; -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL UnsetAddrList uslist; #endif @@ -5751,7 +6264,7 @@ onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end, r = check_backrefs(root, &scan_env); if (r != 0) goto err; -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL if (scan_env.num_call > 0) { r = unset_addr_list_init(&uslist, scan_env.num_call); if (r != 0) goto err; @@ -5791,12 +6304,12 @@ onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end, #ifdef USE_COMBINATION_EXPLOSION_CHECK if (scan_env.backrefed_mem == 0 -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL || scan_env.num_call == 0 #endif ) { setup_comb_exp_check(root, 0, &scan_env); -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL if (scan_env.has_recursion != 0) { scan_env.num_comb_exp_check = 0; } @@ -5829,8 +6342,17 @@ onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end, r = compile_tree(root, reg, &scan_env); if (r == 0) { + if (scan_env.keep_num > 0) { + r = add_opcode(reg, OP_UPDATE_VAR); + if (r != 0) goto err; + r = add_update_var_type(reg, UPDATE_VAR_KEEP_FROM_STACK_LAST); + if (r != 0) goto err; + r = add_mem_num(reg, 0 /* not used */); + if (r != 0) goto err; + } + r = add_opcode(reg, OP_END); -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL if (scan_env.num_call > 0) { r = unset_addr_list_fix(&uslist, reg); unset_addr_list_end(&uslist); @@ -5847,7 +6369,7 @@ onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end, reg->stack_pop_level = STACK_POP_LEVEL_FREE; } } -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL else if (scan_env.num_call > 0) { unset_addr_list_end(&uslist); } @@ -5865,7 +6387,7 @@ onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end, return r; err_unset: -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL if (scan_env.num_call > 0) { unset_addr_list_end(&uslist); } @@ -5890,8 +6412,8 @@ static int onig_inited = 0; extern int onig_reg_init(regex_t* reg, OnigOptionType option, - OnigCaseFoldType case_fold_flag, - OnigEncoding enc, OnigSyntaxType* syntax) + OnigCaseFoldType case_fold_flag, + OnigEncoding enc, OnigSyntaxType* syntax) { int r; @@ -5938,7 +6460,7 @@ onig_reg_init(regex_t* reg, OnigOptionType option, (reg)->exact = (UChar* )NULL; (reg)->int_map = (int* )NULL; (reg)->int_map_backward = (int* )NULL; - (reg)->chain = (regex_t* )NULL; + REG_EXTPL(reg) = NULL; (reg)->p = (UChar* )NULL; (reg)->alloc = 0; @@ -6165,11 +6687,13 @@ OnigOpInfoType OnigOpInfo[] = { { OP_BEGIN_POSITION, "begin-position", ARG_NON }, { OP_BACKREF1, "backref1", ARG_NON }, { OP_BACKREF2, "backref2", ARG_NON }, - { OP_BACKREFN, "backrefn", ARG_MEMNUM }, - { OP_BACKREFN_IC, "backrefn-ic", ARG_SPECIAL }, + { OP_BACKREF_N, "backref-n", ARG_MEMNUM }, + { OP_BACKREF_N_IC, "backref-n-ic", ARG_SPECIAL }, { OP_BACKREF_MULTI, "backref_multi", ARG_SPECIAL }, { OP_BACKREF_MULTI_IC, "backref_multi-ic", ARG_SPECIAL }, - { OP_BACKREF_WITH_LEVEL, "backref_at_level", ARG_SPECIAL }, + { OP_BACKREF_WITH_LEVEL, "backref_with_level", ARG_SPECIAL }, + { OP_BACKREF_CHECK, "backref_check", ARG_SPECIAL }, + { OP_BACKREF_CHECK_WITH_LEVEL, "backref_check_with_level", ARG_SPECIAL }, { OP_MEMORY_START_PUSH, "mem-start-push", ARG_MEMNUM }, { OP_MEMORY_START, "mem-start", ARG_MEMNUM }, { OP_MEMORY_END_PUSH, "mem-end-push", ARG_MEMNUM }, @@ -6181,6 +6705,7 @@ OnigOpInfoType OnigOpInfo[] = { { OP_FAIL, "fail", ARG_NON }, { OP_JUMP, "jump", ARG_RELADDR }, { OP_PUSH, "push", ARG_RELADDR }, + { OP_PUSH_SUPER, "push_SUPER", ARG_RELADDR }, { OP_POP, "pop", ARG_NON }, { OP_PUSH_OR_JUMP_EXACT1, "push-or-jump-e1", ARG_SPECIAL }, { OP_PUSH_IF_PEEK_NEXT, "push-if-peek-next", ARG_SPECIAL }, @@ -6194,10 +6719,10 @@ OnigOpInfoType OnigOpInfo[] = { { OP_EMPTY_CHECK_END, "empty-check-end", ARG_MEMNUM }, { OP_EMPTY_CHECK_END_MEMST,"empty-check-end-memst", ARG_MEMNUM }, { OP_EMPTY_CHECK_END_MEMST_PUSH,"empty-check-end-memst-push", ARG_MEMNUM }, - { OP_PUSH_POS, "push-pos", ARG_NON }, - { OP_POP_POS, "pop-pos", ARG_NON }, - { OP_PUSH_POS_NOT, "push-pos-not", ARG_RELADDR }, - { OP_FAIL_POS, "fail-pos", ARG_NON }, + { OP_PREC_READ_START, "push-pos", ARG_NON }, + { OP_PREC_READ_END, "pop-pos", ARG_NON }, + { OP_PUSH_PREC_READ_NOT, "push-prec-read-not", ARG_RELADDR }, + { OP_FAIL_PREC_READ_NOT, "fail-prec-read-not", ARG_NON }, { OP_PUSH_STOP_BT, "push-stop-bt", ARG_NON }, { OP_POP_STOP_BT, "pop-stop-bt", ARG_NON }, { OP_LOOK_BEHIND, "look-behind", ARG_SPECIAL }, @@ -6205,6 +6730,8 @@ OnigOpInfoType OnigOpInfo[] = { { OP_FAIL_LOOK_BEHIND_NOT, "fail-look-behind-not", ARG_NON }, { OP_CALL, "call", ARG_ABSADDR }, { OP_RETURN, "return", ARG_NON }, + { OP_PUSH_SAVE_VAL, "push-save-val", ARG_SPECIAL }, + { OP_UPDATE_VAR, "update-var", ARG_SPECIAL }, { OP_STATE_CHECK_PUSH, "state-check-push", ARG_SPECIAL }, { OP_STATE_CHECK_PUSH_OR_JUMP, "state-check-push-or-jump", ARG_SPECIAL }, { OP_STATE_CHECK, "state-check", ARG_STATE_CHECK }, @@ -6272,6 +6799,7 @@ onig_print_compiled_byte_code(FILE* f, UChar* bp, UChar** nextp, UChar* start, MemNumType mem; StateCheckNumType scn; OnigCodePoint code; + OnigOptionType option; UChar *q; fprintf(f, "%s", op2name(*bp)); @@ -6421,7 +6949,7 @@ onig_print_compiled_byte_code(FILE* f, UChar* bp, UChar** nextp, UChar* start, } break; - case OP_BACKREFN_IC: + case OP_BACKREF_N_IC: mem = *((MemNumType* )bp); bp += SIZE_MEMNUM; fprintf(f, ":%d", mem); @@ -6429,6 +6957,7 @@ onig_print_compiled_byte_code(FILE* f, UChar* bp, UChar** nextp, UChar* start, case OP_BACKREF_MULTI_IC: case OP_BACKREF_MULTI: + case OP_BACKREF_CHECK: fputs(" ", f); GET_LENGTH_INC(len, bp); for (i = 0; i < len; i++) { @@ -6439,12 +6968,13 @@ onig_print_compiled_byte_code(FILE* f, UChar* bp, UChar** nextp, UChar* start, break; case OP_BACKREF_WITH_LEVEL: + GET_OPTION_INC(option, bp); + fprintf(f, ":%d", option); + /* fall */ + case OP_BACKREF_CHECK_WITH_LEVEL: { - OnigOptionType option; LengthType level; - GET_OPTION_INC(option, bp); - fprintf(f, ":%d", option); GET_LENGTH_INC(level, bp); fprintf(f, ":%d", level); @@ -6501,6 +7031,24 @@ onig_print_compiled_byte_code(FILE* f, UChar* bp, UChar** nextp, UChar* start, p_rel_addr(f, addr, bp, start); break; + case OP_PUSH_SAVE_VAL: + { + SaveType type; + GET_SAVE_TYPE_INC(type, bp); + GET_MEMNUM_INC(mem, bp); + fprintf(f, ":%d:%d", type, mem); + } + break; + + case OP_UPDATE_VAR: + { + UpdateVarType type; + GET_UPDATE_VAR_TYPE_INC(type, bp); + GET_MEMNUM_INC(mem, bp); + fprintf(f, ":%d:%d", type, mem); + } + break; + default: fprintf(stderr, "onig_print_compiled_byte_code: undefined code %d\n", *--bp); @@ -6576,9 +7124,9 @@ print_indent_tree(FILE* f, Node* node, int indent) } break; - case NODE_STR: + case NODE_STRING: fprintf(f, "<string%s:%p>", - (NSTRING_IS_RAW(node) ? "-raw" : ""), node); + (NODE_STRING_IS_RAW(node) ? "-raw" : ""), node); for (p = STR_(node)->s; p < STR_(node)->end; p++) { if (*p >= 0x20 && *p < 0x7f) fputc(*p, f); @@ -6659,12 +7207,12 @@ print_indent_tree(FILE* f, Node* node, int indent) } break; - case NODE_BREF: + case NODE_BACKREF: { int* p; - BRefNode* br = BREF_(node); + BackRefNode* br = BACKREF_(node); p = BACKREFS_P(br); - fprintf(f, "<backref:%p>", node); + fprintf(f, "<backref%s:%p>", NODE_IS_CHECKER(node) ? "-checker" : "", node); for (i = 0; i < br->back_num; i++) { if (i > 0) fputs(", ", f); fprintf(f, "%d", p[i]); @@ -6672,7 +7220,7 @@ print_indent_tree(FILE* f, Node* node, int indent) } break; -#ifdef USE_SUBEXP_CALL +#ifdef USE_CALL case NODE_CALL: { CallNode* cn = CALL_(node); @@ -6693,10 +7241,10 @@ print_indent_tree(FILE* f, Node* node, int indent) fprintf(f, "<enclosure:%p> ", node); switch (ENCLOSURE_(node)->type) { case ENCLOSURE_OPTION: - fprintf(f, "option:%d", ENCLOSURE_(node)->option); + fprintf(f, "option:%d", ENCLOSURE_(node)->o.options); break; case ENCLOSURE_MEMORY: - fprintf(f, "memory:%d", ENCLOSURE_(node)->regnum); + fprintf(f, "memory:%d", ENCLOSURE_(node)->m.regnum); break; case ENCLOSURE_STOP_BACKTRACK: fprintf(f, "stop-bt"); @@ -6709,6 +7257,24 @@ print_indent_tree(FILE* f, Node* node, int indent) print_indent_tree(f, NODE_BODY(node), indent + add); break; + case NODE_GIMMICK: + fprintf(f, "<gimmick:%p> ", node); + switch (GIMMICK_(node)->type) { + case GIMMICK_FAIL: + fprintf(f, "fail"); + break; + case GIMMICK_KEEP: + fprintf(f, "keep:%d", GIMMICK_(node)->id); + break; + case GIMMICK_SAVE: + fprintf(f, "save:%d:%d", GIMMICK_(node)->detail_type, GIMMICK_(node)->id); + break; + case GIMMICK_UPDATE_VAR: + fprintf(f, "update_var:%d:%d", GIMMICK_(node)->detail_type, GIMMICK_(node)->id); + break; + } + break; + default: fprintf(f, "print_indent_tree: undefined node type %d\n", NODE_TYPE(node)); break; |