+static void\r
+initialize_cclass(CClassNode* cc)\r
+{\r
+ BITSET_CLEAR(cc->bs);\r
+ cc->flags = 0;\r
+ cc->mbuf = NULL;\r
+}\r
+\r
+static Node*\r
+node_new_cclass(void)\r
+{\r
+ Node* node = node_new();\r
+ CHECK_NULL_RETURN(node);\r
+\r
+ NODE_SET_TYPE(node, NODE_CCLASS);\r
+ initialize_cclass(CCLASS_(node));\r
+ return node;\r
+}\r
+\r
+static Node*\r
+node_new_ctype(int type, int not, OnigOptionType options)\r
+{\r
+ Node* node = node_new();\r
+ CHECK_NULL_RETURN(node);\r
+\r
+ NODE_SET_TYPE(node, NODE_CTYPE);\r
+ CTYPE_(node)->ctype = type;\r
+ CTYPE_(node)->not = not;\r
+ CTYPE_(node)->options = options;\r
+ CTYPE_(node)->ascii_mode = IS_ASCII_MODE_CTYPE_OPTION(type, options);\r
+ return node;\r
+}\r
+\r
+static Node*\r
+node_new_anychar(void)\r
+{\r
+ Node* node = node_new_ctype(CTYPE_ANYCHAR, 0, ONIG_OPTION_NONE);\r
+ return node;\r
+}\r
+\r
+static Node*\r
+node_new_anychar_with_fixed_option(OnigOptionType option)\r
+{\r
+ CtypeNode* ct;\r
+ Node* node;\r
+\r
+ node = node_new_anychar();\r
+ ct = CTYPE_(node);\r
+ ct->options = option;\r
+ NODE_STATUS_ADD(node, FIXED_OPTION);\r
+ return node;\r
+}\r
+\r
+static int\r
+node_new_no_newline(Node** node, ScanEnv* env)\r
+{\r
+ Node* n;\r
+\r
+ n = node_new_anychar_with_fixed_option(ONIG_OPTION_NONE);\r
+ CHECK_NULL_RETURN_MEMERR(n);\r
+ *node = n;\r
+ return 0;\r
+}\r
+\r
+static int\r
+node_new_true_anychar(Node** node, ScanEnv* env)\r
+{\r
+ Node* n;\r
+\r
+ n = node_new_anychar_with_fixed_option(ONIG_OPTION_MULTILINE);\r
+ CHECK_NULL_RETURN_MEMERR(n);\r
+ *node = n;\r
+ return 0;\r
+}\r
+\r
+static Node*\r
+node_new_list(Node* left, Node* right)\r
+{\r
+ Node* node = node_new();\r
+ CHECK_NULL_RETURN(node);\r
+\r
+ NODE_SET_TYPE(node, NODE_LIST);\r
+ NODE_CAR(node) = left;\r
+ NODE_CDR(node) = right;\r
+ return node;\r
+}\r
+\r
+extern Node*\r
+onig_node_new_list(Node* left, Node* right)\r
+{\r
+ return node_new_list(left, right);\r
+}\r
+\r
+extern Node*\r
+onig_node_list_add(Node* list, Node* x)\r
+{\r
+ Node *n;\r
+\r
+ n = onig_node_new_list(x, NULL);\r
+ if (IS_NULL(n)) return NULL_NODE;\r
+\r
+ if (IS_NOT_NULL(list)) {\r
+ while (IS_NOT_NULL(NODE_CDR(list)))\r
+ list = NODE_CDR(list);\r
+\r
+ NODE_CDR(list) = n;\r
+ }\r
+\r
+ return n;\r
+}\r
+\r
+extern Node*\r
+onig_node_new_alt(Node* left, Node* right)\r
+{\r
+ Node* node = node_new();\r
+ CHECK_NULL_RETURN(node);\r
+\r
+ NODE_SET_TYPE(node, NODE_ALT);\r
+ NODE_CAR(node) = left;\r
+ NODE_CDR(node) = right;\r
+ return node;\r
+}\r
+\r
+static Node*\r
+make_list_or_alt(NodeType type, int n, Node* ns[])\r
+{\r
+ Node* r;\r
+\r
+ if (n <= 0) return NULL_NODE;\r
+\r
+ if (n == 1) {\r
+ r = node_new();\r
+ CHECK_NULL_RETURN(r);\r
+ NODE_SET_TYPE(r, type);\r
+ NODE_CAR(r) = ns[0];\r
+ NODE_CDR(r) = NULL_NODE;\r
+ }\r
+ else {\r
+ Node* right;\r
+\r
+ r = node_new();\r
+ CHECK_NULL_RETURN(r);\r
+\r
+ right = make_list_or_alt(type, n - 1, ns + 1);\r
+ if (IS_NULL(right)) {\r
+ onig_node_free(r);\r
+ return NULL_NODE;\r
+ }\r
+\r
+ NODE_SET_TYPE(r, type);\r
+ NODE_CAR(r) = ns[0];\r
+ NODE_CDR(r) = right;\r
+ }\r
+\r
+ return r;\r
+}\r
+\r
+static Node*\r
+make_list(int n, Node* ns[])\r
+{\r
+ return make_list_or_alt(NODE_LIST, n, ns);\r
+}\r
+\r
+static Node*\r
+make_alt(int n, Node* ns[])\r
+{\r
+ return make_list_or_alt(NODE_ALT, n, ns);\r
+}\r
+\r
+extern Node*\r
+onig_node_new_anchor(int type, int ascii_mode)\r
+{\r
+ Node* node = node_new();\r
+ CHECK_NULL_RETURN(node);\r
+\r
+ NODE_SET_TYPE(node, NODE_ANCHOR);\r
+ ANCHOR_(node)->type = type;\r
+ ANCHOR_(node)->char_len = -1;\r
+ ANCHOR_(node)->ascii_mode = ascii_mode;\r
+ return node;\r
+}\r
+\r
+static Node*\r
+node_new_backref(int back_num, int* backrefs, int by_name,\r
+#ifdef USE_BACKREF_WITH_LEVEL\r
+ int exist_level, int nest_level,\r
+#endif\r
+ ScanEnv* env)\r
+{\r
+ int i;\r
+ Node* node = node_new();\r
+\r
+ CHECK_NULL_RETURN(node);\r
+\r
+ NODE_SET_TYPE(node, NODE_BACKREF);\r
+ BACKREF_(node)->back_num = back_num;\r
+ BACKREF_(node)->back_dynamic = (int* )NULL;\r
+ if (by_name != 0)\r
+ NODE_STATUS_ADD(node, BY_NAME);\r
+\r
+#ifdef USE_BACKREF_WITH_LEVEL\r
+ if (exist_level != 0) {\r
+ NODE_STATUS_ADD(node, NEST_LEVEL);\r
+ BACKREF_(node)->nest_level = nest_level;\r
+ }\r
+#endif\r
+\r
+ for (i = 0; i < back_num; i++) {\r
+ if (backrefs[i] <= env->num_mem &&\r
+ IS_NULL(SCANENV_MEMENV(env)[backrefs[i]].node)) {\r
+ NODE_STATUS_ADD(node, RECURSION); /* /...(\1).../ */\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (back_num <= NODE_BACKREFS_SIZE) {\r
+ for (i = 0; i < back_num; i++)\r
+ BACKREF_(node)->back_static[i] = backrefs[i];\r
+ }\r
+ else {\r
+ int* p = (int* )xmalloc(sizeof(int) * back_num);\r
+ if (IS_NULL(p)) {\r
+ onig_node_free(node);\r
+ return NULL;\r
+ }\r
+ BACKREF_(node)->back_dynamic = p;\r
+ for (i = 0; i < back_num; i++)\r
+ p[i] = backrefs[i];\r
+ }\r
+ return node;\r
+}\r
+\r
+static Node*\r
+node_new_backref_checker(int back_num, int* backrefs, int by_name,\r
+#ifdef USE_BACKREF_WITH_LEVEL\r
+ int exist_level, int nest_level,\r
+#endif\r
+ ScanEnv* env)\r
+{\r
+ Node* node;\r
+\r
+ node = node_new_backref(back_num, backrefs, by_name,\r
+#ifdef USE_BACKREF_WITH_LEVEL\r
+ exist_level, nest_level,\r
+#endif\r
+ env);\r
+ CHECK_NULL_RETURN(node);\r
+\r
+ NODE_STATUS_ADD(node, CHECKER);\r
+ return node;\r
+}\r
+\r
+#ifdef USE_CALL\r
+static Node*\r
+node_new_call(UChar* name, UChar* name_end, int gnum, int by_number)\r
+{\r
+ Node* node = node_new();\r
+ CHECK_NULL_RETURN(node);\r
+\r
+ NODE_SET_TYPE(node, NODE_CALL);\r
+ CALL_(node)->by_number = by_number;\r
+ CALL_(node)->name = name;\r
+ CALL_(node)->name_end = name_end;\r
+ CALL_(node)->group_num = gnum;\r
+ CALL_(node)->entry_count = 1;\r
+ return node;\r
+}\r
+#endif\r
+\r
+static Node*\r
+node_new_quantifier(int lower, int upper, int by_number)\r
+{\r
+ Node* node = node_new();\r
+ CHECK_NULL_RETURN(node);\r
+\r
+ NODE_SET_TYPE(node, NODE_QUANT);\r
+ QUANT_(node)->lower = lower;\r
+ QUANT_(node)->upper = upper;\r
+ QUANT_(node)->greedy = 1;\r
+ QUANT_(node)->body_empty_info = QUANT_BODY_IS_NOT_EMPTY;\r
+ QUANT_(node)->head_exact = NULL_NODE;\r
+ QUANT_(node)->next_head_exact = NULL_NODE;\r
+ QUANT_(node)->is_refered = 0;\r
+ if (by_number != 0)\r
+ NODE_STATUS_ADD(node, BY_NUMBER);\r
+\r
+ return node;\r
+}\r
+\r
+static Node*\r
+node_new_enclosure(enum EnclosureType type)\r
+{\r
+ Node* node = node_new();\r
+ CHECK_NULL_RETURN(node);\r
+\r
+ NODE_SET_TYPE(node, NODE_ENCLOSURE);\r
+ ENCLOSURE_(node)->type = type;\r
+\r
+ switch (type) {\r
+ case ENCLOSURE_MEMORY:\r
+ ENCLOSURE_(node)->m.regnum = 0;\r
+ ENCLOSURE_(node)->m.called_addr = -1;\r
+ ENCLOSURE_(node)->m.entry_count = 1;\r
+ ENCLOSURE_(node)->m.called_state = 0;\r
+ break;\r
+\r
+ case ENCLOSURE_OPTION:\r
+ ENCLOSURE_(node)->o.options = 0;\r
+ break;\r
+\r
+ case ENCLOSURE_STOP_BACKTRACK:\r
+ break;\r
+\r
+ case ENCLOSURE_IF_ELSE:\r
+ ENCLOSURE_(node)->te.Then = 0;\r
+ ENCLOSURE_(node)->te.Else = 0;\r
+ break;\r
+ }\r
+\r
+ ENCLOSURE_(node)->opt_count = 0;\r
+ return node;\r
+}\r
+\r
+extern Node*\r
+onig_node_new_enclosure(int type)\r
+{\r
+ return node_new_enclosure(type);\r
+}\r
+\r
+static Node*\r
+node_new_enclosure_if_else(Node* cond, Node* Then, Node* Else)\r
+{\r
+ Node* n;\r
+ n = node_new_enclosure(ENCLOSURE_IF_ELSE);\r
+ CHECK_NULL_RETURN(n);\r
+\r
+ NODE_BODY(n) = cond;\r
+ ENCLOSURE_(n)->te.Then = Then;\r
+ ENCLOSURE_(n)->te.Else = Else;\r
+ return n;\r
+}\r
+\r
+static Node*\r
+node_new_memory(int is_named)\r
+{\r
+ Node* node = node_new_enclosure(ENCLOSURE_MEMORY);\r
+ CHECK_NULL_RETURN(node);\r
+ if (is_named != 0)\r
+ NODE_STATUS_ADD(node, NAMED_GROUP);\r
+\r
+ return node;\r
+}\r
+\r
+static Node*\r
+node_new_option(OnigOptionType option)\r
+{\r
+ Node* node = node_new_enclosure(ENCLOSURE_OPTION);\r
+ CHECK_NULL_RETURN(node);\r
+ ENCLOSURE_(node)->o.options = option;\r
+ return node;\r
+}\r
+\r
+static int\r
+node_new_fail(Node** node, ScanEnv* env)\r
+{\r
+ *node = node_new();\r
+ CHECK_NULL_RETURN_MEMERR(*node);\r
+\r
+ NODE_SET_TYPE(*node, NODE_GIMMICK);\r
+ GIMMICK_(*node)->type = GIMMICK_FAIL;\r
+ return ONIG_NORMAL;\r
+}\r
+\r
+static int\r
+node_new_save_gimmick(Node** node, enum SaveType save_type, ScanEnv* env)\r
+{\r
+ int id;\r
+ int r;\r
+\r
+ r = save_entry(env, save_type, &id);\r
+ if (r != ONIG_NORMAL) return r;\r
+\r
+ *node = node_new();\r
+ CHECK_NULL_RETURN_MEMERR(*node);\r
+\r
+ NODE_SET_TYPE(*node, NODE_GIMMICK);\r
+ GIMMICK_(*node)->id = id;\r
+ GIMMICK_(*node)->type = GIMMICK_SAVE;\r
+ GIMMICK_(*node)->detail_type = (int )save_type;\r
+\r
+ return ONIG_NORMAL;\r
+}\r
+\r
+static int\r
+node_new_update_var_gimmick(Node** node, enum UpdateVarType update_var_type,\r
+ int id, ScanEnv* env)\r
+{\r
+ *node = node_new();\r
+ CHECK_NULL_RETURN_MEMERR(*node);\r
+\r
+ NODE_SET_TYPE(*node, NODE_GIMMICK);\r
+ GIMMICK_(*node)->id = id;\r
+ GIMMICK_(*node)->type = GIMMICK_UPDATE_VAR;\r
+ GIMMICK_(*node)->detail_type = (int )update_var_type;\r
+\r
+ return ONIG_NORMAL;\r
+}\r
+\r
+static int\r
+node_new_keep(Node** node, ScanEnv* env)\r
+{\r
+ int r;\r
+\r
+ r = node_new_save_gimmick(node, SAVE_KEEP, env);\r
+ if (r != 0) return r;\r
+\r
+ env->keep_num++;\r
+ return ONIG_NORMAL;\r
+}\r
+\r
+#ifdef USE_CALLOUT\r
+\r
+extern void\r
+onig_free_reg_callout_list(int n, CalloutListEntry* list)\r
+{\r
+ int i;\r
+ int j;\r
+\r
+ if (IS_NULL(list)) return ;\r
+\r
+ for (i = 0; i < n; i++) {\r
+ if (list[i].of == ONIG_CALLOUT_OF_NAME) {\r
+ for (j = 0; j < list[i].u.arg.passed_num; j++) {\r
+ if (list[i].u.arg.types[j] == ONIG_TYPE_STRING) {\r
+ if (IS_NOT_NULL(list[i].u.arg.vals[j].s.start))\r
+ xfree(list[i].u.arg.vals[j].s.start);\r
+ }\r
+ }\r
+ }\r
+ else { /* ONIG_CALLOUT_OF_CONTENTS */\r
+ if (IS_NOT_NULL(list[i].u.content.start)) {\r
+ xfree((void* )list[i].u.content.start);\r
+ }\r
+ }\r
+ }\r
+\r
+ xfree(list);\r
+}\r
+\r
+extern CalloutListEntry*\r
+onig_reg_callout_list_at(regex_t* reg, int num)\r
+{\r
+ RegexExt* ext = REG_EXTP(reg);\r
+ CHECK_NULL_RETURN(ext);\r
+\r
+ if (num <= 0 || num > ext->callout_num)\r
+ return 0;\r
+\r
+ num--;\r
+ return ext->callout_list + num;\r
+}\r
+\r
+static int\r
+reg_callout_list_entry(ScanEnv* env, int* rnum)\r
+{\r
+#define INIT_CALLOUT_LIST_NUM 3\r
+\r
+ int num;\r
+ CalloutListEntry* list;\r
+ CalloutListEntry* e;\r
+ RegexExt* ext;\r
+\r
+ ext = onig_get_regex_ext(env->reg);\r
+ CHECK_NULL_RETURN_MEMERR(ext);\r
+\r
+ if (IS_NULL(ext->callout_list)) {\r
+ list = (CalloutListEntry* )xmalloc(sizeof(*list) * INIT_CALLOUT_LIST_NUM);\r
+ CHECK_NULL_RETURN_MEMERR(list);\r
+\r
+ ext->callout_list = list;\r
+ ext->callout_list_alloc = INIT_CALLOUT_LIST_NUM;\r
+ ext->callout_num = 0;\r
+ }\r
+\r
+ num = ext->callout_num + 1;\r
+ if (num > ext->callout_list_alloc) {\r
+ int alloc = ext->callout_list_alloc * 2;\r
+ list = (CalloutListEntry* )xrealloc(ext->callout_list,\r
+ sizeof(CalloutListEntry) * alloc,\r
+ sizeof(CalloutListEntry) * ext->callout_list_alloc);\r
+ CHECK_NULL_RETURN_MEMERR(list);\r
+\r
+ ext->callout_list = list;\r
+ ext->callout_list_alloc = alloc;\r
+ }\r
+\r
+ e = ext->callout_list + (num - 1);\r
+\r
+ e->flag = 0;\r
+ e->of = 0;\r
+ e->in = ONIG_CALLOUT_OF_CONTENTS;\r
+ e->type = 0;\r
+ e->tag_start = 0;\r
+ e->tag_end = 0;\r
+ e->start_func = 0;\r
+ e->end_func = 0;\r
+ e->u.arg.num = 0;\r
+ e->u.arg.passed_num = 0;\r
+\r
+ ext->callout_num = num;\r
+ *rnum = num;\r
+ return ONIG_NORMAL;\r
+}\r
+\r
+static int\r
+node_new_callout(Node** node, OnigCalloutOf callout_of, int num, int id,\r
+ ScanEnv* env)\r
+{\r
+ *node = node_new();\r
+ CHECK_NULL_RETURN_MEMERR(*node);\r
+\r
+ NODE_SET_TYPE(*node, NODE_GIMMICK);\r
+ GIMMICK_(*node)->id = id;\r
+ GIMMICK_(*node)->num = num;\r
+ GIMMICK_(*node)->type = GIMMICK_CALLOUT;\r
+ GIMMICK_(*node)->detail_type = (int )callout_of;\r
+\r
+ return ONIG_NORMAL;\r
+}\r
+#endif\r
+\r
+static int\r
+make_extended_grapheme_cluster(Node** node, ScanEnv* env)\r
+{\r
+ int r;\r
+ int i;\r
+ Node* x;\r
+ Node* ns[2];\r
+\r
+ /* \X == (?>\O(?:\Y\O)*) */\r
+\r
+ ns[1] = NULL_NODE;\r
+\r
+ r = ONIGERR_MEMORY;\r
+ ns[0] = onig_node_new_anchor(ANCHOR_NO_EXTENDED_GRAPHEME_CLUSTER_BOUNDARY, 0);\r
+ if (IS_NULL(ns[0])) goto err;\r
+\r
+ r = node_new_true_anychar(&ns[1], env);\r
+ if (r != 0) goto err1;\r
+\r
+ x = make_list(2, ns);\r
+ if (IS_NULL(x)) goto err;\r
+ ns[0] = x;\r
+ ns[1] = NULL_NODE;\r
+\r
+ x = node_new_quantifier(0, REPEAT_INFINITE, 1);\r
+ if (IS_NULL(x)) goto err;\r
+\r
+ NODE_BODY(x) = ns[0];\r
+ ns[0] = NULL_NODE;\r
+ ns[1] = x;\r
+\r
+ r = node_new_true_anychar(&ns[0], env);\r
+ if (r != 0) goto err1;\r
+\r
+ x = make_list(2, ns);\r
+ if (IS_NULL(x)) goto err;\r
+\r
+ ns[0] = x;\r
+ ns[1] = NULL_NODE;\r
+\r
+ x = node_new_enclosure(ENCLOSURE_STOP_BACKTRACK);\r
+ if (IS_NULL(x)) goto err;\r
+\r
+ NODE_BODY(x) = ns[0];\r
+\r
+ *node = x;\r
+ return ONIG_NORMAL;\r
+\r
+ err:\r
+ r = ONIGERR_MEMORY;\r
+ err1:\r
+ for (i = 0; i < 2; i++) onig_node_free(ns[i]);\r
+ return r;\r
+}\r
+\r
+static int\r
+make_absent_engine(Node** node, int pre_save_right_id, Node* absent,\r
+ Node* step_one, int lower, int upper, int possessive,\r
+ int is_range_cutter, ScanEnv* env)\r
+{\r
+ int r;\r
+ int i;\r
+ int id;\r
+ Node* x;\r
+ Node* ns[4];\r
+\r
+ for (i = 0; i < 4; i++) ns[i] = NULL_NODE;\r
+\r
+ ns[1] = absent;\r
+ ns[3] = step_one; /* for err */\r
+ r = node_new_save_gimmick(&ns[0], SAVE_S, env);\r
+ if (r != 0) goto err;\r
+\r
+ id = GIMMICK_(ns[0])->id;\r
+ r = node_new_update_var_gimmick(&ns[2], UPDATE_VAR_RIGHT_RANGE_FROM_S_STACK,\r
+ id, env);\r
+ if (r != 0) goto err;\r
+\r
+ r = node_new_fail(&ns[3], env);\r
+ if (r != 0) goto err;\r
+\r
+ x = make_list(4, ns);\r
+ if (IS_NULL(x)) goto err0;\r
+\r
+ ns[0] = x;\r
+ ns[1] = step_one;\r
+ ns[2] = ns[3] = NULL_NODE;\r
+\r
+ x = make_alt(2, ns);\r
+ if (IS_NULL(x)) goto err0;\r
+\r
+ ns[0] = x;\r
+\r
+ x = node_new_quantifier(lower, upper, 0);\r
+ if (IS_NULL(x)) goto err0;\r
+\r
+ NODE_BODY(x) = ns[0];\r
+ ns[0] = x;\r
+\r
+ if (possessive != 0) {\r
+ x = node_new_enclosure(ENCLOSURE_STOP_BACKTRACK);\r
+ if (IS_NULL(x)) goto err0;\r
+\r
+ NODE_BODY(x) = ns[0];\r
+ ns[0] = x;\r
+ }\r
+\r
+ r = node_new_update_var_gimmick(&ns[1], UPDATE_VAR_RIGHT_RANGE_FROM_STACK,\r
+ pre_save_right_id, env);\r
+ if (r != 0) goto err;\r
+\r
+ r = node_new_fail(&ns[2], env);\r
+ if (r != 0) goto err;\r
+\r
+ x = make_list(2, ns + 1);\r
+ if (IS_NULL(x)) goto err0;\r
+\r
+ ns[1] = x; ns[2] = NULL_NODE;\r
+\r
+ x = make_alt(2, ns);\r
+ if (IS_NULL(x)) goto err0;\r
+\r
+ if (is_range_cutter != 0)\r
+ NODE_STATUS_ADD(x, SUPER);\r
+\r
+ *node = x;\r
+ return ONIG_NORMAL;\r
+\r
+ err0:\r
+ r = ONIGERR_MEMORY;\r
+ err:\r
+ for (i = 0; i < 4; i++) onig_node_free(ns[i]);\r
+ return r;\r
+}\r
+\r
+static int\r
+make_absent_tail(Node** node1, Node** node2, int pre_save_right_id,\r
+ ScanEnv* env)\r
+{\r
+ int r;\r
+ int id;\r
+ Node* save;\r
+ Node* x;\r
+ Node* ns[2];\r
+\r
+ *node1 = *node2 = NULL_NODE;\r
+ save = ns[0] = ns[1] = NULL_NODE;\r
+\r
+ r = node_new_save_gimmick(&save, SAVE_RIGHT_RANGE, env);\r
+ if (r != 0) goto err;\r
+\r
+ id = GIMMICK_(save)->id;\r
+ r = node_new_update_var_gimmick(&ns[0], UPDATE_VAR_RIGHT_RANGE_FROM_STACK,\r
+ id, env);\r
+ if (r != 0) goto err;\r
+\r
+ r = node_new_fail(&ns[1], env);\r
+ if (r != 0) goto err;\r
+\r
+ x = make_list(2, ns);\r
+ if (IS_NULL(x)) goto err0;\r
+\r
+ ns[0] = NULL_NODE; ns[1] = x;\r
+\r
+ r = node_new_update_var_gimmick(&ns[0], UPDATE_VAR_RIGHT_RANGE_FROM_STACK,\r
+ pre_save_right_id, env);\r
+ if (r != 0) goto err;\r
+\r
+ x = make_alt(2, ns);\r
+ if (IS_NULL(x)) goto err0;\r
+\r
+ *node1 = save;\r
+ *node2 = x;\r
+ return ONIG_NORMAL;\r
+\r
+ err0:\r
+ r = ONIGERR_MEMORY;\r
+ err:\r
+ onig_node_free(save);\r
+ onig_node_free(ns[0]);\r
+ onig_node_free(ns[1]);\r
+ return r;\r
+}\r
+\r
+static int\r
+make_range_clear(Node** node, ScanEnv* env)\r
+{\r
+ int r;\r
+ int id;\r
+ Node* save;\r
+ Node* x;\r
+ Node* ns[2];\r
+\r
+ *node = NULL_NODE;\r
+ save = ns[0] = ns[1] = NULL_NODE;\r
+\r
+ r = node_new_save_gimmick(&save, SAVE_RIGHT_RANGE, env);\r
+ if (r != 0) goto err;\r
+\r
+ id = GIMMICK_(save)->id;\r
+ r = node_new_update_var_gimmick(&ns[0], UPDATE_VAR_RIGHT_RANGE_FROM_STACK,\r
+ id, env);\r
+ if (r != 0) goto err;\r
+\r
+ r = node_new_fail(&ns[1], env);\r
+ if (r != 0) goto err;\r
+\r
+ x = make_list(2, ns);\r
+ if (IS_NULL(x)) goto err0;\r
+\r
+ ns[0] = NULL_NODE; ns[1] = x;\r
+\r
+ r = node_new_update_var_gimmick(&ns[0], UPDATE_VAR_RIGHT_RANGE_INIT, 0, env);\r
+ if (r != 0) goto err;\r
+\r
+ x = make_alt(2, ns);\r
+ if (IS_NULL(x)) goto err0;\r
+\r
+ NODE_STATUS_ADD(x, SUPER);\r
+\r
+ ns[0] = save;\r
+ ns[1] = x;\r
+ save = NULL_NODE;\r
+ x = make_list(2, ns);\r
+ if (IS_NULL(x)) goto err0;\r
+\r
+ *node = x;\r
+ return ONIG_NORMAL;\r
+\r
+ err0:\r
+ r = ONIGERR_MEMORY;\r
+ err:\r
+ onig_node_free(save);\r
+ onig_node_free(ns[0]);\r
+ onig_node_free(ns[1]);\r
+ return r;\r
+}\r
+\r
+static int\r
+is_simple_one_char_repeat(Node* node, Node** rquant, Node** rbody,\r
+ int* is_possessive, ScanEnv* env)\r
+{\r
+ Node* quant;\r
+ Node* body;\r
+\r
+ *rquant = *rbody = 0;\r
+ *is_possessive = 0;\r
+\r
+ if (NODE_TYPE(node) == NODE_QUANT) {\r
+ quant = node;\r
+ }\r
+ else {\r
+ if (NODE_TYPE(node) == NODE_ENCLOSURE) {\r
+ EnclosureNode* en = ENCLOSURE_(node);\r
+ if (en->type == ENCLOSURE_STOP_BACKTRACK) {\r
+ *is_possessive = 1;\r
+ quant = NODE_ENCLOSURE_BODY(en);\r
+ if (NODE_TYPE(quant) != NODE_QUANT)\r
+ return 0;\r
+ }\r
+ else\r
+ return 0;\r
+ }\r
+ else\r
+ return 0;\r
+ }\r
+\r
+ if (QUANT_(quant)->greedy == 0)\r
+ return 0;\r
+\r
+ body = NODE_BODY(quant);\r
+ switch (NODE_TYPE(body)) {\r
+ case NODE_STRING:\r
+ {\r
+ int len;\r
+ StrNode* sn = STR_(body);\r
+ UChar *s = sn->s;\r
+\r
+ len = 0;\r
+ while (s < sn->end) {\r
+ s += enclen(env->enc, s);\r
+ len++;\r
+ }\r
+ if (len != 1)\r
+ return 0;\r
+ }\r
+\r
+ case NODE_CCLASS:\r
+ break;\r
+\r
+ default:\r
+ return 0;\r
+ break;\r
+ }\r
+\r
+ if (node != quant) {\r
+ NODE_BODY(node) = 0;\r
+ onig_node_free(node);\r
+ }\r
+ NODE_BODY(quant) = NULL_NODE;\r
+ *rquant = quant;\r
+ *rbody = body;\r
+ return 1;\r
+}\r
+\r
+static int\r
+make_absent_tree_for_simple_one_char_repeat(Node** node, Node* absent, Node* quant,\r
+ Node* body, int possessive, ScanEnv* env)\r
+{\r
+ int r;\r
+ int i;\r
+ int id1;\r
+ int lower, upper;\r
+ Node* x;\r
+ Node* ns[4];\r
+\r
+ *node = NULL_NODE;\r
+ r = ONIGERR_MEMORY;\r
+ ns[0] = ns[1] = NULL_NODE;\r
+ ns[2] = body, ns[3] = absent;\r
+\r
+ lower = QUANT_(quant)->lower;\r
+ upper = QUANT_(quant)->upper;\r
+ onig_node_free(quant);\r
+\r
+ r = node_new_save_gimmick(&ns[0], SAVE_RIGHT_RANGE, env);\r
+ if (r != 0) goto err;\r
+\r
+ id1 = GIMMICK_(ns[0])->id;\r
+\r
+ r = make_absent_engine(&ns[1], id1, absent, body, lower, upper, possessive,\r
+ 0, env);\r
+ if (r != 0) goto err;\r
+\r
+ ns[2] = ns[3] = NULL_NODE;\r
+\r
+ r = node_new_update_var_gimmick(&ns[2], UPDATE_VAR_RIGHT_RANGE_FROM_STACK,\r
+ id1, env);\r
+ if (r != 0) goto err;\r
+\r
+ x = make_list(3, ns);\r
+ if (IS_NULL(x)) goto err0;\r
+\r
+ *node = x;\r
+ return ONIG_NORMAL;\r
+\r
+ err0:\r
+ r = ONIGERR_MEMORY;\r
+ err:\r
+ for (i = 0; i < 4; i++) onig_node_free(ns[i]);\r
+ return r;\r
+}\r
+\r
+static int\r
+make_absent_tree(Node** node, Node* absent, Node* expr, int is_range_cutter,\r
+ ScanEnv* env)\r
+{\r
+ int r;\r
+ int i;\r
+ int id1, id2;\r
+ int possessive;\r
+ Node* x;\r
+ Node* ns[7];\r
+\r
+ r = ONIGERR_MEMORY;\r
+ for (i = 0; i < 7; i++) ns[i] = NULL_NODE;\r
+ ns[4] = expr; ns[5] = absent;\r
+\r
+ if (is_range_cutter == 0) {\r
+ Node* quant;\r
+ Node* body;\r
+\r
+ if (expr == NULL_NODE) {\r
+ /* default expr \O* */\r
+ quant = node_new_quantifier(0, REPEAT_INFINITE, 0);\r
+ if (IS_NULL(quant)) goto err0;\r
+\r
+ r = node_new_true_anychar(&body, env);\r
+ if (r != 0) {\r
+ onig_node_free(quant);\r
+ goto err;\r
+ }\r
+ possessive = 0;\r
+ goto simple;\r
+ }\r
+ else {\r
+ if (is_simple_one_char_repeat(expr, &quant, &body, &possessive, env)) {\r
+ simple:\r
+ r = make_absent_tree_for_simple_one_char_repeat(node, absent, quant,\r
+ body, possessive, env);\r
+ if (r != 0) {\r
+ ns[4] = NULL_NODE;\r
+ onig_node_free(quant);\r
+ onig_node_free(body);\r
+ goto err;\r
+ }\r
+\r
+ return ONIG_NORMAL;\r
+ }\r
+ }\r
+ }\r
+\r
+ r = node_new_save_gimmick(&ns[0], SAVE_RIGHT_RANGE, env);\r
+ if (r != 0) goto err;\r
+\r
+ id1 = GIMMICK_(ns[0])->id;\r
+\r
+ r = node_new_save_gimmick(&ns[1], SAVE_S, env);\r
+ if (r != 0) goto err;\r
+\r
+ id2 = GIMMICK_(ns[1])->id;\r
+\r
+ r = node_new_true_anychar(&ns[3], env);\r
+ if (r != 0) goto err;\r
+\r
+ possessive = 1;\r
+ r = make_absent_engine(&ns[2], id1, absent, ns[3], 0, REPEAT_INFINITE,\r
+ possessive, is_range_cutter, env);\r
+ if (r != 0) goto err;\r
+\r
+ ns[3] = NULL_NODE;\r
+ ns[5] = NULL_NODE;\r
+\r
+ r = node_new_update_var_gimmick(&ns[3], UPDATE_VAR_S_FROM_STACK, id2, env);\r
+ if (r != 0) goto err;\r
+\r
+ if (is_range_cutter != 0) {\r
+ x = make_list(4, ns);\r
+ if (IS_NULL(x)) goto err0;\r
+ }\r
+ else {\r
+ r = make_absent_tail(&ns[5], &ns[6], id1, env);\r
+ if (r != 0) goto err;\r
+ \r
+ x = make_list(7, ns);\r
+ if (IS_NULL(x)) goto err0;\r
+ }\r
+\r
+ *node = x;\r
+ return ONIG_NORMAL;\r
+\r
+ err0:\r
+ r = ONIGERR_MEMORY;\r
+ err:\r
+ for (i = 0; i < 7; i++) onig_node_free(ns[i]);\r
+ return r; \r
+}\r
+\r
+extern int\r
+onig_node_str_cat(Node* node, const UChar* s, const UChar* end)\r
+{\r
+ int addlen = (int )(end - s);\r
+\r
+ if (addlen > 0) {\r
+ int len = (int )(STR_(node)->end - STR_(node)->s);\r
+\r
+ if (STR_(node)->capa > 0 || (len + addlen > NODE_STRING_BUF_SIZE - 1)) {\r
+ UChar* p;\r
+ int capa = len + addlen + NODE_STRING_MARGIN;\r
+\r
+ if (capa <= STR_(node)->capa) {\r
+ onig_strcpy(STR_(node)->s + len, s, end);\r
+ }\r
+ else {\r
+ if (STR_(node)->s == STR_(node)->buf)\r
+ p = strcat_capa_from_static(STR_(node)->s, STR_(node)->end,\r
+ s, end, capa);\r
+ else\r
+ p = strcat_capa(STR_(node)->s, STR_(node)->end, s, end, capa, STR_(node)->capa);\r
+\r
+ CHECK_NULL_RETURN_MEMERR(p);\r
+ STR_(node)->s = p;\r
+ STR_(node)->capa = capa;\r
+ }\r
+ }\r
+ else {\r
+ onig_strcpy(STR_(node)->s + len, s, end);\r
+ }\r
+ STR_(node)->end = STR_(node)->s + len + addlen;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+extern int\r
+onig_node_str_set(Node* node, const UChar* s, const UChar* end)\r
+{\r
+ onig_node_str_clear(node);\r
+ return onig_node_str_cat(node, s, end);\r
+}\r
+\r
+static int\r
+node_str_cat_char(Node* node, UChar c)\r
+{\r
+ UChar s[1];\r
+\r
+ s[0] = c;\r
+ return onig_node_str_cat(node, s, s + 1);\r
+}\r
+\r
+extern void\r
+onig_node_conv_to_str_node(Node* node, int flag)\r
+{\r
+ NODE_SET_TYPE(node, NODE_STRING);\r
+ STR_(node)->flag = flag;\r
+ STR_(node)->capa = 0;\r
+ STR_(node)->s = STR_(node)->buf;\r
+ STR_(node)->end = STR_(node)->buf;\r
+}\r
+\r
+extern void\r
+onig_node_str_clear(Node* node)\r
+{\r
+ if (STR_(node)->capa != 0 &&\r
+ IS_NOT_NULL(STR_(node)->s) && STR_(node)->s != STR_(node)->buf) {\r
+ xfree(STR_(node)->s);\r
+ }\r
+\r
+ STR_(node)->capa = 0;\r
+ STR_(node)->flag = 0;\r
+ STR_(node)->s = STR_(node)->buf;\r
+ STR_(node)->end = STR_(node)->buf;\r
+}\r
+\r
+static Node*\r
+node_new_str(const UChar* s, const UChar* end)\r
+{\r
+ Node* node = node_new();\r
+ CHECK_NULL_RETURN(node);\r
+\r
+ NODE_SET_TYPE(node, NODE_STRING);\r
+ STR_(node)->capa = 0;\r
+ STR_(node)->flag = 0;\r
+ STR_(node)->s = STR_(node)->buf;\r
+ STR_(node)->end = STR_(node)->buf;\r
+ if (onig_node_str_cat(node, s, end)) {\r
+ onig_node_free(node);\r
+ return NULL;\r
+ }\r
+ return node;\r
+}\r
+\r
+extern Node*\r
+onig_node_new_str(const UChar* s, const UChar* end)\r
+{\r
+ return node_new_str(s, end);\r
+}\r
+\r
+static Node*\r
+node_new_str_raw(UChar* s, UChar* end)\r
+{\r
+ Node* node = node_new_str(s, end);\r
+ NODE_STRING_SET_RAW(node);\r
+ return node;\r
+}\r
+\r
+static Node*\r
+node_new_empty(void)\r
+{\r
+ return node_new_str(NULL, NULL);\r
+}\r
+\r
+static Node*\r
+node_new_str_raw_char(UChar c)\r
+{\r
+ UChar p[1];\r
+\r
+ p[0] = c;\r
+ return node_new_str_raw(p, p + 1);\r
+}\r
+\r
+static Node*\r
+str_node_split_last_char(Node* node, OnigEncoding enc)\r
+{\r
+ const UChar *p;\r
+ Node* rn;\r
+ StrNode* sn;\r
+\r
+ sn = STR_(node);\r
+ rn = NULL_NODE;\r
+ if (sn->end > sn->s) {\r
+ p = onigenc_get_prev_char_head(enc, sn->s, sn->end);\r
+ if (p && p > sn->s) { /* can be split. */\r
+ rn = node_new_str(p, sn->end);\r
+ if (NODE_STRING_IS_RAW(node))\r
+ NODE_STRING_SET_RAW(rn);\r
+\r
+ sn->end = (UChar* )p;\r
+ }\r
+ }\r
+ return rn;\r
+}\r
+\r
+static int\r
+str_node_can_be_split(Node* node, OnigEncoding enc)\r
+{\r
+ StrNode* sn = STR_(node);\r
+ if (sn->end > sn->s) {\r
+ return ((enclen(enc, sn->s) < sn->end - sn->s) ? 1 : 0);\r
+ }\r
+ return 0;\r
+}\r
+\r
+#ifdef USE_PAD_TO_SHORT_BYTE_CHAR\r
+static int\r
+node_str_head_pad(StrNode* sn, int num, UChar val)\r
+{\r
+ UChar buf[NODE_STRING_BUF_SIZE];\r
+ int i, len;\r
+\r
+ len = sn->end - sn->s;\r
+ onig_strcpy(buf, sn->s, sn->end);\r
+ onig_strcpy(&(sn->s[num]), buf, buf + len);\r
+ sn->end += num;\r
+\r
+ for (i = 0; i < num; i++) {\r
+ sn->s[i] = val;\r
+ }\r
+}\r
+#endif\r
+\r
+extern int\r
+onig_scan_unsigned_number(UChar** src, const UChar* end, OnigEncoding enc)\r
+{\r
+ unsigned int num, val;\r
+ OnigCodePoint c;\r
+ UChar* p = *src;\r
+ PFETCH_READY;\r
+\r
+ num = 0;\r
+ while (! PEND) {\r
+ PFETCH(c);\r
+ if (IS_CODE_DIGIT_ASCII(enc, c)) {\r
+ val = (unsigned int )DIGITVAL(c);\r
+ if ((INT_MAX_LIMIT - val) / 10UL < num)\r
+ return -1; /* overflow */\r
+\r
+ num = num * 10 + val;\r
+ }\r
+ else {\r
+ PUNFETCH;\r
+ break;\r
+ }\r
+ }\r
+ *src = p;\r
+ return num;\r
+}\r
+\r
+static int\r
+scan_unsigned_hexadecimal_number(UChar** src, UChar* end, int minlen,\r
+ int maxlen, OnigEncoding enc)\r
+{\r
+ OnigCodePoint c;\r
+ unsigned int num, val;\r
+ int n;\r
+ UChar* p = *src;\r
+ PFETCH_READY;\r
+\r
+ num = 0;\r
+ n = 0;\r
+ while (! PEND && n < maxlen) {\r
+ PFETCH(c);\r
+ if (IS_CODE_XDIGIT_ASCII(enc, c)) {\r
+ n++;\r
+ val = (unsigned int )XDIGITVAL(enc,c);\r
+ if ((INT_MAX_LIMIT - val) / 16UL < num)\r
+ return ONIGERR_TOO_BIG_NUMBER; /* overflow */\r
+\r
+ num = (num << 4) + XDIGITVAL(enc,c);\r
+ }\r
+ else {\r
+ PUNFETCH;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (n < minlen)\r
+ return ONIGERR_INVALID_CODE_POINT_VALUE;\r
+\r
+ *src = p;\r
+ return num;\r
+}\r
+\r
+static int\r
+scan_unsigned_octal_number(UChar** src, UChar* end, int maxlen,\r
+ OnigEncoding enc)\r
+{\r
+ OnigCodePoint c;\r
+ unsigned int num, val;\r
+ UChar* p = *src;\r
+ PFETCH_READY;\r
+\r
+ num = 0;\r
+ while (! PEND && maxlen-- != 0) {\r
+ PFETCH(c);\r
+ if (IS_CODE_DIGIT_ASCII(enc, c) && c < '8') {\r
+ val = ODIGITVAL(c);\r
+ if ((INT_MAX_LIMIT - val) / 8UL < num)\r
+ return -1; /* overflow */\r
+\r
+ num = (num << 3) + val;\r
+ }\r
+ else {\r
+ PUNFETCH;\r
+ break;\r
+ }\r
+ }\r
+ *src = p;\r
+ return num;\r
+}\r
+\r
+\r
+#define BB_WRITE_CODE_POINT(bbuf,pos,code) \\r
+ BB_WRITE(bbuf, pos, &(code), SIZE_CODE_POINT)\r
+\r
+/* data format:\r
+ [n][from-1][to-1][from-2][to-2] ... [from-n][to-n]\r
+ (all data size is OnigCodePoint)\r
+ */\r
+static int\r
+new_code_range(BBuf** pbuf)\r
+{\r
+#define INIT_MULTI_BYTE_RANGE_SIZE (SIZE_CODE_POINT * 5)\r
+ int r;\r
+ OnigCodePoint n;\r
+ BBuf* bbuf;\r
+\r
+ bbuf = *pbuf = (BBuf* )xmalloc(sizeof(BBuf));\r
+ CHECK_NULL_RETURN_MEMERR(bbuf);\r
+ r = BB_INIT(bbuf, INIT_MULTI_BYTE_RANGE_SIZE);\r
+ if (r != 0) {\r
+ xfree(bbuf);\r
+ *pbuf = 0;\r
+ return r;\r
+ }\r
+\r
+ n = 0;\r
+ BB_WRITE_CODE_POINT(bbuf, 0, n);\r
+ return 0;\r
+}\r
+\r
+static int\r
+add_code_range_to_buf(BBuf** pbuf, OnigCodePoint from, OnigCodePoint to)\r
+{\r
+ int r, inc_n, pos;\r
+ int low, high, bound, x;\r
+ OnigCodePoint n, *data;\r
+ BBuf* bbuf;\r
+\r
+ if (from > to) {\r
+ n = from; from = to; to = n;\r
+ }\r
+\r
+ if (IS_NULL(*pbuf)) {\r
+ r = new_code_range(pbuf);\r
+ if (r != 0) return r;\r
+ bbuf = *pbuf;\r
+ n = 0;\r
+ }\r
+ else {\r
+ bbuf = *pbuf;\r
+ GET_CODE_POINT(n, bbuf->p);\r
+ }\r
+ data = (OnigCodePoint* )(bbuf->p);\r
+ data++;\r
+\r
+ for (low = 0, bound = n; low < bound; ) {\r
+ x = (low + bound) >> 1;\r
+ if (from > data[x*2 + 1])\r
+ low = x + 1;\r
+ else\r
+ bound = x;\r
+ }\r
+\r
+ high = (to == ~((OnigCodePoint )0)) ? n : low;\r
+ for (bound = n; high < bound; ) {\r
+ x = (high + bound) >> 1;\r
+ if (to + 1 >= data[x*2])\r
+ high = x + 1;\r
+ else\r
+ bound = x;\r
+ }\r
+\r
+ inc_n = low + 1 - high;\r
+ if (n + inc_n > ONIG_MAX_MULTI_BYTE_RANGES_NUM)\r
+ return ONIGERR_TOO_MANY_MULTI_BYTE_RANGES;\r
+\r
+ if (inc_n != 1) {\r
+ if (from > data[low*2])\r
+ from = data[low*2];\r
+ if (to < data[(high - 1)*2 + 1])\r
+ to = data[(high - 1)*2 + 1];\r
+ }\r
+\r
+ if (inc_n != 0 && (OnigCodePoint )high < n) {\r
+ int from_pos = SIZE_CODE_POINT * (1 + high * 2);\r
+ int to_pos = SIZE_CODE_POINT * (1 + (low + 1) * 2);\r
+ int size = (n - high) * 2 * SIZE_CODE_POINT;\r
+\r
+ if (inc_n > 0) {\r
+ BB_MOVE_RIGHT(bbuf, from_pos, to_pos, size);\r
+ }\r
+ else {\r
+ BB_MOVE_LEFT_REDUCE(bbuf, from_pos, to_pos);\r
+ }\r
+ }\r
+\r
+ pos = SIZE_CODE_POINT * (1 + low * 2);\r
+ BB_ENSURE_SIZE(bbuf, pos + SIZE_CODE_POINT * 2);\r
+ BB_WRITE_CODE_POINT(bbuf, pos, from);\r
+ BB_WRITE_CODE_POINT(bbuf, pos + SIZE_CODE_POINT, to);\r
+ n += inc_n;\r
+ BB_WRITE_CODE_POINT(bbuf, 0, n);\r
+\r
+ return 0;\r
+}\r
+\r
+static int\r
+add_code_range(BBuf** pbuf, ScanEnv* env, OnigCodePoint from, OnigCodePoint to)\r
+{\r
+ if (from > to) {\r
+ if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC))\r
+ return 0;\r
+ else\r
+ return ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS;\r
+ }\r
+\r
+ return add_code_range_to_buf(pbuf, from, to);\r
+}\r
+\r
+static int\r
+not_code_range_buf(OnigEncoding enc, BBuf* bbuf, BBuf** pbuf)\r
+{\r
+ int r, i, n;\r
+ OnigCodePoint pre, from, *data, to = 0;\r
+\r
+ *pbuf = (BBuf* )NULL;\r
+ if (IS_NULL(bbuf)) {\r
+ set_all:\r
+ return SET_ALL_MULTI_BYTE_RANGE(enc, pbuf);\r
+ }\r
+\r
+ data = (OnigCodePoint* )(bbuf->p);\r
+ GET_CODE_POINT(n, data);\r
+ data++;\r
+ if (n <= 0) goto set_all;\r
+\r
+ r = 0;\r
+ pre = MBCODE_START_POS(enc);\r
+ for (i = 0; i < n; i++) {\r
+ from = data[i*2];\r
+ to = data[i*2+1];\r
+ if (pre <= from - 1) {\r
+ r = add_code_range_to_buf(pbuf, pre, from - 1);\r
+ if (r != 0) return r;\r
+ }\r
+ if (to == ~((OnigCodePoint )0)) break;\r
+ pre = to + 1;\r
+ }\r
+ if (to < ~((OnigCodePoint )0)) {\r
+ r = add_code_range_to_buf(pbuf, to + 1, ~((OnigCodePoint )0));\r
+ }\r
+ return r;\r
+}\r
+\r
+#define SWAP_BB_NOT(bbuf1, not1, bbuf2, not2) do {\\r
+ BBuf *tbuf; \\r
+ int tnot; \\r
+ tnot = not1; not1 = not2; not2 = tnot; \\r
+ tbuf = bbuf1; bbuf1 = bbuf2; bbuf2 = tbuf; \\r
+} while (0)\r
+\r
+static int\r
+or_code_range_buf(OnigEncoding enc, BBuf* bbuf1, int not1,\r
+ BBuf* bbuf2, int not2, BBuf** pbuf)\r
+{\r
+ int r;\r
+ OnigCodePoint i, n1, *data1;\r
+ OnigCodePoint from, to;\r
+\r
+ *pbuf = (BBuf* )NULL;\r
+ if (IS_NULL(bbuf1) && IS_NULL(bbuf2)) {\r
+ if (not1 != 0 || not2 != 0)\r
+ return SET_ALL_MULTI_BYTE_RANGE(enc, pbuf);\r
+ return 0;\r
+ }\r
+\r
+ r = 0;\r
+ if (IS_NULL(bbuf2))\r
+ SWAP_BB_NOT(bbuf1, not1, bbuf2, not2);\r
+\r
+ if (IS_NULL(bbuf1)) {\r
+ if (not1 != 0) {\r
+ return SET_ALL_MULTI_BYTE_RANGE(enc, pbuf);\r
+ }\r
+ else {\r
+ if (not2 == 0) {\r
+ return bbuf_clone(pbuf, bbuf2);\r
+ }\r
+ else {\r
+ return not_code_range_buf(enc, bbuf2, pbuf);\r
+ }\r
+ }\r
+ }\r
+\r
+ if (not1 != 0)\r
+ SWAP_BB_NOT(bbuf1, not1, bbuf2, not2);\r
+\r
+ data1 = (OnigCodePoint* )(bbuf1->p);\r
+ GET_CODE_POINT(n1, data1);\r
+ data1++;\r
+\r
+ if (not2 == 0 && not1 == 0) { /* 1 OR 2 */\r
+ r = bbuf_clone(pbuf, bbuf2);\r
+ }\r
+ else if (not1 == 0) { /* 1 OR (not 2) */\r
+ r = not_code_range_buf(enc, bbuf2, pbuf);\r
+ }\r
+ if (r != 0) return r;\r
+\r
+ for (i = 0; i < n1; i++) {\r
+ from = data1[i*2];\r
+ to = data1[i*2+1];\r
+ r = add_code_range_to_buf(pbuf, from, to);\r
+ if (r != 0) return r;\r
+ }\r
+ return 0;\r
+}\r
+\r
+static int\r
+and_code_range1(BBuf** pbuf, OnigCodePoint from1, OnigCodePoint to1,\r
+ OnigCodePoint* data, int n)\r
+{\r
+ int i, r;\r
+ OnigCodePoint from2, to2;\r
+\r
+ for (i = 0; i < n; i++) {\r
+ from2 = data[i*2];\r
+ to2 = data[i*2+1];\r
+ if (from2 < from1) {\r
+ if (to2 < from1) continue;\r
+ else {\r
+ from1 = to2 + 1;\r
+ }\r
+ }\r
+ else if (from2 <= to1) {\r
+ if (to2 < to1) {\r
+ if (from1 <= from2 - 1) {\r
+ r = add_code_range_to_buf(pbuf, from1, from2-1);\r
+ if (r != 0) return r;\r
+ }\r
+ from1 = to2 + 1;\r
+ }\r
+ else {\r
+ to1 = from2 - 1;\r
+ }\r
+ }\r
+ else {\r
+ from1 = from2;\r
+ }\r
+ if (from1 > to1) break;\r
+ }\r
+ if (from1 <= to1) {\r
+ r = add_code_range_to_buf(pbuf, from1, to1);\r
+ if (r != 0) return r;\r
+ }\r
+ return 0;\r
+}\r
+\r
+static int\r
+and_code_range_buf(BBuf* bbuf1, int not1, BBuf* bbuf2, int not2, BBuf** pbuf)\r
+{\r
+ int r;\r
+ OnigCodePoint i, j, n1, n2, *data1, *data2;\r
+ OnigCodePoint from, to, from1, to1, from2, to2;\r
+\r
+ *pbuf = (BBuf* )NULL;\r
+ if (IS_NULL(bbuf1)) {\r
+ if (not1 != 0 && IS_NOT_NULL(bbuf2)) /* not1 != 0 -> not2 == 0 */\r
+ return bbuf_clone(pbuf, bbuf2);\r
+ return 0;\r
+ }\r
+ else if (IS_NULL(bbuf2)) {\r
+ if (not2 != 0)\r
+ return bbuf_clone(pbuf, bbuf1);\r
+ return 0;\r
+ }\r
+\r
+ if (not1 != 0)\r
+ SWAP_BB_NOT(bbuf1, not1, bbuf2, not2);\r
+\r
+ data1 = (OnigCodePoint* )(bbuf1->p);\r
+ data2 = (OnigCodePoint* )(bbuf2->p);\r
+ GET_CODE_POINT(n1, data1);\r
+ GET_CODE_POINT(n2, data2);\r
+ data1++;\r
+ data2++;\r
+\r
+ if (not2 == 0 && not1 == 0) { /* 1 AND 2 */\r
+ for (i = 0; i < n1; i++) {\r
+ from1 = data1[i*2];\r
+ to1 = data1[i*2+1];\r
+ for (j = 0; j < n2; j++) {\r
+ from2 = data2[j*2];\r
+ to2 = data2[j*2+1];\r
+ if (from2 > to1) break;\r
+ if (to2 < from1) continue;\r
+ from = MAX(from1, from2);\r
+ to = MIN(to1, to2);\r
+ r = add_code_range_to_buf(pbuf, from, to);\r
+ if (r != 0) return r;\r
+ }\r
+ }\r
+ }\r
+ else if (not1 == 0) { /* 1 AND (not 2) */\r
+ for (i = 0; i < n1; i++) {\r
+ from1 = data1[i*2];\r
+ to1 = data1[i*2+1];\r