regcomp.c

Go to the documentation of this file.
00001 /**********************************************************************
00002   regcomp.c -  Onigmo (Oniguruma-mod) (regular expression library)
00003 **********************************************************************/
00004 /*-
00005  * Copyright (c) 2002-2008  K.Kosako  <sndgk393 AT ybb DOT ne DOT jp>
00006  * Copyright (c) 2011-2013  K.Takata  <kentkt AT csc DOT jp>
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted provided that the following conditions
00011  * are met:
00012  * 1. Redistributions of source code must retain the above copyright
00013  *    notice, this list of conditions and the following disclaimer.
00014  * 2. Redistributions in binary form must reproduce the above copyright
00015  *    notice, this list of conditions and the following disclaimer in the
00016  *    documentation and/or other materials provided with the distribution.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
00019  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
00022  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00023  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00024  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00025  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00026  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00027  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  */
00030 
00031 #include "regparse.h"
00032 
00033 OnigCaseFoldType OnigDefaultCaseFoldFlag = ONIGENC_CASE_FOLD_MIN;
00034 
00035 extern OnigCaseFoldType
00036 onig_get_default_case_fold_flag(void)
00037 {
00038   return OnigDefaultCaseFoldFlag;
00039 }
00040 
00041 extern int
00042 onig_set_default_case_fold_flag(OnigCaseFoldType case_fold_flag)
00043 {
00044   OnigDefaultCaseFoldFlag = case_fold_flag;
00045   return 0;
00046 }
00047 
00048 
00049 #ifndef PLATFORM_UNALIGNED_WORD_ACCESS
00050 static unsigned char PadBuf[WORD_ALIGNMENT_SIZE];
00051 #endif
00052 
00053 #if 0
00054 static UChar*
00055 str_dup(UChar* s, UChar* end)
00056 {
00057   ptrdiff_t len = end - s;
00058 
00059   if (len > 0) {
00060     UChar* r = (UChar* )xmalloc(len + 1);
00061     CHECK_NULL_RETURN(r);
00062     xmemcpy(r, s, len);
00063     r[len] = (UChar )0;
00064     return r;
00065   }
00066   else return NULL;
00067 }
00068 #endif
00069 
00070 static void
00071 swap_node(Node* a, Node* b)
00072 {
00073   Node c;
00074   c = *a; *a = *b; *b = c;
00075 
00076   if (NTYPE(a) == NT_STR) {
00077     StrNode* sn = NSTR(a);
00078     if (sn->capa == 0) {
00079       size_t len = sn->end - sn->s;
00080       sn->s   = sn->buf;
00081       sn->end = sn->s + len;
00082     }
00083   }
00084 
00085   if (NTYPE(b) == NT_STR) {
00086     StrNode* sn = NSTR(b);
00087     if (sn->capa == 0) {
00088       size_t len = sn->end - sn->s;
00089       sn->s   = sn->buf;
00090       sn->end = sn->s + len;
00091     }
00092   }
00093 }
00094 
00095 static OnigDistance
00096 distance_add(OnigDistance d1, OnigDistance d2)
00097 {
00098   if (d1 == ONIG_INFINITE_DISTANCE || d2 == ONIG_INFINITE_DISTANCE)
00099     return ONIG_INFINITE_DISTANCE;
00100   else {
00101     if (d1 <= ONIG_INFINITE_DISTANCE - d2) return d1 + d2;
00102     else return ONIG_INFINITE_DISTANCE;
00103   }
00104 }
00105 
00106 static OnigDistance
00107 distance_multiply(OnigDistance d, int m)
00108 {
00109   if (m == 0) return 0;
00110 
00111   if (d < ONIG_INFINITE_DISTANCE / m)
00112     return d * m;
00113   else
00114     return ONIG_INFINITE_DISTANCE;
00115 }
00116 
00117 static int
00118 bitset_is_empty(BitSetRef bs)
00119 {
00120   int i;
00121   for (i = 0; i < BITSET_SIZE; i++) {
00122     if (bs[i] != 0) return 0;
00123   }
00124   return 1;
00125 }
00126 
00127 #ifdef ONIG_DEBUG
00128 static int
00129 onig_is_prelude(void)
00130 {
00131     return !rb_const_defined(rb_cThread, rb_intern_const("MUTEX_FOR_THREAD_EXCLUSIVE"));
00132 }
00133 
00134 static int
00135 bitset_on_num(BitSetRef bs)
00136 {
00137   int i, n;
00138 
00139   n = 0;
00140   for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
00141     if (BITSET_AT(bs, i)) n++;
00142   }
00143   return n;
00144 }
00145 #endif
00146 
00147 extern int
00148 onig_bbuf_init(BBuf* buf, OnigDistance size)
00149 {
00150   if (size <= 0) {
00151     size   = 0;
00152     buf->p = NULL;
00153   }
00154   else {
00155     buf->p = (UChar* )xmalloc(size);
00156     if (IS_NULL(buf->p)) return(ONIGERR_MEMORY);
00157   }
00158 
00159   buf->alloc = (unsigned int )size;
00160   buf->used  = 0;
00161   return 0;
00162 }
00163 
00164 
00165 #ifdef USE_SUBEXP_CALL
00166 
00167 static int
00168 unset_addr_list_init(UnsetAddrList* uslist, int size)
00169 {
00170   UnsetAddr* p;
00171 
00172   p = (UnsetAddr* )xmalloc(sizeof(UnsetAddr)* size);
00173   CHECK_NULL_RETURN_MEMERR(p);
00174   uslist->num   = 0;
00175   uslist->alloc = size;
00176   uslist->us    = p;
00177   return 0;
00178 }
00179 
00180 static void
00181 unset_addr_list_end(UnsetAddrList* uslist)
00182 {
00183   if (IS_NOT_NULL(uslist->us))
00184     xfree(uslist->us);
00185 }
00186 
00187 static int
00188 unset_addr_list_add(UnsetAddrList* uslist, int offset, struct _Node* node)
00189 {
00190   UnsetAddr* p;
00191   int size;
00192 
00193   if (uslist->num >= uslist->alloc) {
00194     size = uslist->alloc * 2;
00195     p = (UnsetAddr* )xrealloc(uslist->us, sizeof(UnsetAddr) * size);
00196     CHECK_NULL_RETURN_MEMERR(p);
00197     uslist->alloc = size;
00198     uslist->us    = p;
00199   }
00200 
00201   uslist->us[uslist->num].offset = offset;
00202   uslist->us[uslist->num].target = node;
00203   uslist->num++;
00204   return 0;
00205 }
00206 #endif /* USE_SUBEXP_CALL */
00207 
00208 
00209 static int
00210 add_opcode(regex_t* reg, int opcode)
00211 {
00212   BBUF_ADD1(reg, opcode);
00213   return 0;
00214 }
00215 
00216 #ifdef USE_COMBINATION_EXPLOSION_CHECK
00217 static int
00218 add_state_check_num(regex_t* reg, int num)
00219 {
00220   StateCheckNumType n = (StateCheckNumType )num;
00221 
00222   BBUF_ADD(reg, &n, SIZE_STATE_CHECK_NUM);
00223   return 0;
00224 }
00225 #endif
00226 
00227 static int
00228 add_rel_addr(regex_t* reg, int addr)
00229 {
00230   RelAddrType ra = (RelAddrType )addr;
00231 
00232   BBUF_ADD(reg, &ra, SIZE_RELADDR);
00233   return 0;
00234 }
00235 
00236 static int
00237 add_abs_addr(regex_t* reg, int addr)
00238 {
00239   AbsAddrType ra = (AbsAddrType )addr;
00240 
00241   BBUF_ADD(reg, &ra, SIZE_ABSADDR);
00242   return 0;
00243 }
00244 
00245 static int
00246 add_length(regex_t* reg, OnigDistance len)
00247 {
00248   LengthType l = (LengthType )len;
00249 
00250   BBUF_ADD(reg, &l, SIZE_LENGTH);
00251   return 0;
00252 }
00253 
00254 static int
00255 add_mem_num(regex_t* reg, int num)
00256 {
00257   MemNumType n = (MemNumType )num;
00258 
00259   BBUF_ADD(reg, &n, SIZE_MEMNUM);
00260   return 0;
00261 }
00262 
00263 static int
00264 add_pointer(regex_t* reg, void* addr)
00265 {
00266   PointerType ptr = (PointerType )addr;
00267 
00268   BBUF_ADD(reg, &ptr, SIZE_POINTER);
00269   return 0;
00270 }
00271 
00272 static int
00273 add_option(regex_t* reg, OnigOptionType option)
00274 {
00275   BBUF_ADD(reg, &option, SIZE_OPTION);
00276   return 0;
00277 }
00278 
00279 static int
00280 add_opcode_rel_addr(regex_t* reg, int opcode, int addr)
00281 {
00282   int r;
00283 
00284   r = add_opcode(reg, opcode);
00285   if (r) return r;
00286   r = add_rel_addr(reg, addr);
00287   return r;
00288 }
00289 
00290 static int
00291 add_bytes(regex_t* reg, UChar* bytes, OnigDistance len)
00292 {
00293   BBUF_ADD(reg, bytes, len);
00294   return 0;
00295 }
00296 
00297 static int
00298 add_bitset(regex_t* reg, BitSetRef bs)
00299 {
00300   BBUF_ADD(reg, bs, SIZE_BITSET);
00301   return 0;
00302 }
00303 
00304 static int
00305 add_opcode_option(regex_t* reg, int opcode, OnigOptionType option)
00306 {
00307   int r;
00308 
00309   r = add_opcode(reg, opcode);
00310   if (r) return r;
00311   r = add_option(reg, option);
00312   return r;
00313 }
00314 
00315 static int compile_length_tree(Node* node, regex_t* reg);
00316 static int compile_tree(Node* node, regex_t* reg);
00317 
00318 
00319 #define IS_NEED_STR_LEN_OP_EXACT(op) \
00320    ((op) == OP_EXACTN    || (op) == OP_EXACTMB2N ||\
00321     (op) == OP_EXACTMB3N || (op) == OP_EXACTMBN  || (op) == OP_EXACTN_IC)
00322 
00323 static int
00324 select_str_opcode(int mb_len, OnigDistance str_len, int ignore_case)
00325 {
00326   int op;
00327 
00328   if (ignore_case) {
00329     switch (str_len) {
00330     case 1:  op = OP_EXACT1_IC; break;
00331     default: op = OP_EXACTN_IC; break;
00332     }
00333   }
00334   else {
00335     switch (mb_len) {
00336     case 1:
00337       switch (str_len) {
00338       case 1:  op = OP_EXACT1; break;
00339       case 2:  op = OP_EXACT2; break;
00340       case 3:  op = OP_EXACT3; break;
00341       case 4:  op = OP_EXACT4; break;
00342       case 5:  op = OP_EXACT5; break;
00343       default: op = OP_EXACTN; break;
00344       }
00345       break;
00346 
00347     case 2:
00348       switch (str_len) {
00349       case 1:  op = OP_EXACTMB2N1; break;
00350       case 2:  op = OP_EXACTMB2N2; break;
00351       case 3:  op = OP_EXACTMB2N3; break;
00352       default: op = OP_EXACTMB2N;  break;
00353       }
00354       break;
00355 
00356     case 3:
00357       op = OP_EXACTMB3N;
00358       break;
00359 
00360     default:
00361       op = OP_EXACTMBN;
00362       break;
00363     }
00364   }
00365   return op;
00366 }
00367 
00368 static int
00369 compile_tree_empty_check(Node* node, regex_t* reg, int empty_info)
00370 {
00371   int r;
00372   int saved_num_null_check = reg->num_null_check;
00373 
00374   if (empty_info != 0) {
00375     r = add_opcode(reg, OP_NULL_CHECK_START);
00376     if (r) return r;
00377     r = add_mem_num(reg, reg->num_null_check); /* NULL CHECK ID */
00378     if (r) return r;
00379     reg->num_null_check++;
00380   }
00381 
00382   r = compile_tree(node, reg);
00383   if (r) return r;
00384 
00385   if (empty_info != 0) {
00386     if (empty_info == NQ_TARGET_IS_EMPTY)
00387       r = add_opcode(reg, OP_NULL_CHECK_END);
00388     else if (empty_info == NQ_TARGET_IS_EMPTY_MEM)
00389       r = add_opcode(reg, OP_NULL_CHECK_END_MEMST);
00390     else if (empty_info == NQ_TARGET_IS_EMPTY_REC)
00391       r = add_opcode(reg, OP_NULL_CHECK_END_MEMST_PUSH);
00392 
00393     if (r) return r;
00394     r = add_mem_num(reg, saved_num_null_check); /* NULL CHECK ID */
00395   }
00396   return r;
00397 }
00398 
00399 #ifdef USE_SUBEXP_CALL
00400 static int
00401 compile_call(CallNode* node, regex_t* reg)
00402 {
00403   int r;
00404 
00405   r = add_opcode(reg, OP_CALL);
00406   if (r) return r;
00407   r = unset_addr_list_add(node->unset_addr_list, BBUF_GET_OFFSET_POS(reg),
00408                           node->target);
00409   if (r) return r;
00410   r = add_abs_addr(reg, 0 /*dummy addr.*/);
00411   return r;
00412 }
00413 #endif
00414 
00415 static int
00416 compile_tree_n_times(Node* node, int n, regex_t* reg)
00417 {
00418   int i, r;
00419 
00420   for (i = 0; i < n; i++) {
00421     r = compile_tree(node, reg);
00422     if (r) return r;
00423   }
00424   return 0;
00425 }
00426 
00427 static int
00428 add_compile_string_length(UChar* s ARG_UNUSED, int mb_len, OnigDistance str_len,
00429                           regex_t* reg ARG_UNUSED, int ignore_case)
00430 {
00431   int len;
00432   int op = select_str_opcode(mb_len, str_len, ignore_case);
00433 
00434   len = SIZE_OPCODE;
00435 
00436   if (op == OP_EXACTMBN)  len += SIZE_LENGTH;
00437   if (IS_NEED_STR_LEN_OP_EXACT(op))
00438     len += SIZE_LENGTH;
00439 
00440   len += mb_len * (int )str_len;
00441   return len;
00442 }
00443 
00444 static int
00445 add_compile_string(UChar* s, int mb_len, OnigDistance str_len,
00446                    regex_t* reg, int ignore_case)
00447 {
00448   int op = select_str_opcode(mb_len, str_len, ignore_case);
00449   add_opcode(reg, op);
00450 
00451   if (op == OP_EXACTMBN)
00452     add_length(reg, mb_len);
00453 
00454   if (IS_NEED_STR_LEN_OP_EXACT(op)) {
00455     if (op == OP_EXACTN_IC)
00456       add_length(reg, mb_len * str_len);
00457     else
00458       add_length(reg, str_len);
00459   }
00460 
00461   add_bytes(reg, s, mb_len * str_len);
00462   return 0;
00463 }
00464 
00465 
00466 static int
00467 compile_length_string_node(Node* node, regex_t* reg)
00468 {
00469   int rlen, r, len, prev_len, slen, ambig;
00470   OnigEncoding enc = reg->enc;
00471   UChar *p, *prev;
00472   StrNode* sn;
00473 
00474   sn = NSTR(node);
00475   if (sn->end <= sn->s)
00476     return 0;
00477 
00478   ambig = NSTRING_IS_AMBIG(node);
00479 
00480   p = prev = sn->s;
00481   prev_len = enclen(enc, p, sn->end);
00482   p += prev_len;
00483   slen = 1;
00484   rlen = 0;
00485 
00486   for (; p < sn->end; ) {
00487     len = enclen(enc, p, sn->end);
00488     if (len == prev_len) {
00489       slen++;
00490     }
00491     else {
00492       r = add_compile_string_length(prev, prev_len, slen, reg, ambig);
00493       rlen += r;
00494       prev = p;
00495       slen = 1;
00496       prev_len = len;
00497     }
00498     p += len;
00499   }
00500   r = add_compile_string_length(prev, prev_len, slen, reg, ambig);
00501   rlen += r;
00502   return rlen;
00503 }
00504 
00505 static int
00506 compile_length_string_raw_node(StrNode* sn, regex_t* reg)
00507 {
00508   if (sn->end <= sn->s)
00509     return 0;
00510 
00511   return add_compile_string_length(sn->s, 1 /* sb */, sn->end - sn->s, reg, 0);
00512 }
00513 
00514 static int
00515 compile_string_node(Node* node, regex_t* reg)
00516 {
00517   int r, len, prev_len, slen, ambig;
00518   OnigEncoding enc = reg->enc;
00519   UChar *p, *prev, *end;
00520   StrNode* sn;
00521 
00522   sn = NSTR(node);
00523   if (sn->end <= sn->s)
00524     return 0;
00525 
00526   end = sn->end;
00527   ambig = NSTRING_IS_AMBIG(node);
00528 
00529   p = prev = sn->s;
00530   prev_len = enclen(enc, p, end);
00531   p += prev_len;
00532   slen = 1;
00533 
00534   for (; p < end; ) {
00535     len = enclen(enc, p, end);
00536     if (len == prev_len) {
00537       slen++;
00538     }
00539     else {
00540       r = add_compile_string(prev, prev_len, slen, reg, ambig);
00541       if (r) return r;
00542 
00543       prev  = p;
00544       slen  = 1;
00545       prev_len = len;
00546     }
00547 
00548     p += len;
00549   }
00550   return add_compile_string(prev, prev_len, slen, reg, ambig);
00551 }
00552 
00553 static int
00554 compile_string_raw_node(StrNode* sn, regex_t* reg)
00555 {
00556   if (sn->end <= sn->s)
00557     return 0;
00558 
00559   return add_compile_string(sn->s, 1 /* sb */, sn->end - sn->s, reg, 0);
00560 }
00561 
00562 static int
00563 add_multi_byte_cclass(BBuf* mbuf, regex_t* reg)
00564 {
00565 #ifdef PLATFORM_UNALIGNED_WORD_ACCESS
00566   add_length(reg, mbuf->used);
00567   return add_bytes(reg, mbuf->p, mbuf->used);
00568 #else
00569   int r, pad_size;
00570   UChar* p = BBUF_GET_ADD_ADDRESS(reg) + SIZE_LENGTH;
00571 
00572   GET_ALIGNMENT_PAD_SIZE(p, pad_size);
00573   add_length(reg, mbuf->used + (WORD_ALIGNMENT_SIZE - 1));
00574   if (pad_size != 0) add_bytes(reg, PadBuf, pad_size);
00575 
00576   r = add_bytes(reg, mbuf->p, mbuf->used);
00577 
00578   /* padding for return value from compile_length_cclass_node() to be fix. */
00579   pad_size = (WORD_ALIGNMENT_SIZE - 1) - pad_size;
00580   if (pad_size != 0) add_bytes(reg, PadBuf, pad_size);
00581   return r;
00582 #endif
00583 }
00584 
00585 static int
00586 compile_length_cclass_node(CClassNode* cc, regex_t* reg)
00587 {
00588   int len;
00589 
00590   if (IS_NCCLASS_SHARE(cc)) {
00591     len = SIZE_OPCODE + SIZE_POINTER;
00592     return len;
00593   }
00594 
00595   if (IS_NULL(cc->mbuf)) {
00596     len = SIZE_OPCODE + SIZE_BITSET;
00597   }
00598   else {
00599     if (ONIGENC_MBC_MINLEN(reg->enc) > 1 || bitset_is_empty(cc->bs)) {
00600       len = SIZE_OPCODE;
00601     }
00602     else {
00603       len = SIZE_OPCODE + SIZE_BITSET;
00604     }
00605 #ifdef PLATFORM_UNALIGNED_WORD_ACCESS
00606     len += SIZE_LENGTH + cc->mbuf->used;
00607 #else
00608     len += SIZE_LENGTH + cc->mbuf->used + (WORD_ALIGNMENT_SIZE - 1);
00609 #endif
00610   }
00611 
00612   return len;
00613 }
00614 
00615 static int
00616 compile_cclass_node(CClassNode* cc, regex_t* reg)
00617 {
00618   int r;
00619 
00620   if (IS_NCCLASS_SHARE(cc)) {
00621     add_opcode(reg, OP_CCLASS_NODE);
00622     r = add_pointer(reg, cc);
00623     return r;
00624   }
00625 
00626   if (IS_NULL(cc->mbuf)) {
00627     if (IS_NCCLASS_NOT(cc))
00628       add_opcode(reg, OP_CCLASS_NOT);
00629     else
00630       add_opcode(reg, OP_CCLASS);
00631 
00632     r = add_bitset(reg, cc->bs);
00633   }
00634   else {
00635     if (ONIGENC_MBC_MINLEN(reg->enc) > 1 || bitset_is_empty(cc->bs)) {
00636       if (IS_NCCLASS_NOT(cc))
00637         add_opcode(reg, OP_CCLASS_MB_NOT);
00638       else
00639         add_opcode(reg, OP_CCLASS_MB);
00640 
00641       r = add_multi_byte_cclass(cc->mbuf, reg);
00642     }
00643     else {
00644       if (IS_NCCLASS_NOT(cc))
00645         add_opcode(reg, OP_CCLASS_MIX_NOT);
00646       else
00647         add_opcode(reg, OP_CCLASS_MIX);
00648 
00649       r = add_bitset(reg, cc->bs);
00650       if (r) return r;
00651       r = add_multi_byte_cclass(cc->mbuf, reg);
00652     }
00653   }
00654 
00655   return r;
00656 }
00657 
00658 static int
00659 entry_repeat_range(regex_t* reg, int id, int lower, int upper)
00660 {
00661 #define REPEAT_RANGE_ALLOC  4
00662 
00663   OnigRepeatRange* p;
00664 
00665   if (reg->repeat_range_alloc == 0) {
00666     p = (OnigRepeatRange* )xmalloc(sizeof(OnigRepeatRange) * REPEAT_RANGE_ALLOC);
00667     CHECK_NULL_RETURN_MEMERR(p);
00668     reg->repeat_range = p;
00669     reg->repeat_range_alloc = REPEAT_RANGE_ALLOC;
00670   }
00671   else if (reg->repeat_range_alloc <= id) {
00672     int n;
00673     n = reg->repeat_range_alloc + REPEAT_RANGE_ALLOC;
00674     p = (OnigRepeatRange* )xrealloc(reg->repeat_range,
00675                                     sizeof(OnigRepeatRange) * n);
00676     CHECK_NULL_RETURN_MEMERR(p);
00677     reg->repeat_range = p;
00678     reg->repeat_range_alloc = n;
00679   }
00680   else {
00681     p = reg->repeat_range;
00682   }
00683 
00684   p[id].lower = lower;
00685   p[id].upper = (IS_REPEAT_INFINITE(upper) ? 0x7fffffff : upper);
00686   return 0;
00687 }
00688 
00689 static int
00690 compile_range_repeat_node(QtfrNode* qn, int target_len, int empty_info,
00691                           regex_t* reg)
00692 {
00693   int r;
00694   int num_repeat = reg->num_repeat;
00695 
00696   r = add_opcode(reg, qn->greedy ? OP_REPEAT : OP_REPEAT_NG);
00697   if (r) return r;
00698   r = add_mem_num(reg, num_repeat); /* OP_REPEAT ID */
00699   reg->num_repeat++;
00700   if (r) return r;
00701   r = add_rel_addr(reg, target_len + SIZE_OP_REPEAT_INC);
00702   if (r) return r;
00703 
00704   r = entry_repeat_range(reg, num_repeat, qn->lower, qn->upper);
00705   if (r) return r;
00706 
00707   r = compile_tree_empty_check(qn->target, reg, empty_info);
00708   if (r) return r;
00709 
00710   if (
00711 #ifdef USE_SUBEXP_CALL
00712       reg->num_call > 0 ||
00713 #endif
00714       IS_QUANTIFIER_IN_REPEAT(qn)) {
00715     r = add_opcode(reg, qn->greedy ? OP_REPEAT_INC_SG : OP_REPEAT_INC_NG_SG);
00716   }
00717   else {
00718     r = add_opcode(reg, qn->greedy ? OP_REPEAT_INC : OP_REPEAT_INC_NG);
00719   }
00720   if (r) return r;
00721   r = add_mem_num(reg, num_repeat); /* OP_REPEAT ID */
00722   return r;
00723 }
00724 
00725 static int
00726 is_anychar_star_quantifier(QtfrNode* qn)
00727 {
00728   if (qn->greedy && IS_REPEAT_INFINITE(qn->upper) &&
00729       NTYPE(qn->target) == NT_CANY)
00730     return 1;
00731   else
00732     return 0;
00733 }
00734 
00735 #define QUANTIFIER_EXPAND_LIMIT_SIZE   50
00736 #define CKN_ON   (ckn > 0)
00737 
00738 #ifdef USE_COMBINATION_EXPLOSION_CHECK
00739 
00740 static int
00741 compile_length_quantifier_node(QtfrNode* qn, regex_t* reg)
00742 {
00743   int len, mod_tlen, cklen;
00744   int ckn;
00745   int infinite = IS_REPEAT_INFINITE(qn->upper);
00746   int empty_info = qn->target_empty_info;
00747   int tlen = compile_length_tree(qn->target, reg);
00748 
00749   if (tlen < 0) return tlen;
00750 
00751   ckn = ((reg->num_comb_exp_check > 0) ? qn->comb_exp_check_num : 0);
00752 
00753   cklen = (CKN_ON ? SIZE_STATE_CHECK_NUM: 0);
00754 
00755   /* anychar repeat */
00756   if (NTYPE(qn->target) == NT_CANY) {
00757     if (qn->greedy && infinite) {
00758       if (IS_NOT_NULL(qn->next_head_exact) && !CKN_ON)
00759         return SIZE_OP_ANYCHAR_STAR_PEEK_NEXT + tlen * qn->lower + cklen;
00760       else
00761         return SIZE_OP_ANYCHAR_STAR + tlen * qn->lower + cklen;
00762     }
00763   }
00764 
00765   if (empty_info != 0)
00766     mod_tlen = tlen + (SIZE_OP_NULL_CHECK_START + SIZE_OP_NULL_CHECK_END);
00767   else
00768     mod_tlen = tlen;
00769 
00770   if (infinite && qn->lower <= 1) {
00771     if (qn->greedy) {
00772       if (qn->lower == 1)
00773         len = SIZE_OP_JUMP;
00774       else
00775         len = 0;
00776 
00777       len += SIZE_OP_PUSH + cklen + mod_tlen + SIZE_OP_JUMP;
00778     }
00779     else {
00780       if (qn->lower == 0)
00781         len = SIZE_OP_JUMP;
00782       else
00783         len = 0;
00784 
00785       len += mod_tlen + SIZE_OP_PUSH + cklen;
00786     }
00787   }
00788   else if (qn->upper == 0) {
00789     if (qn->is_refered != 0) /* /(?<n>..){0}/ */
00790       len = SIZE_OP_JUMP + tlen;
00791     else
00792       len = 0;
00793   }
00794   else if (qn->upper == 1 && qn->greedy) {
00795     if (qn->lower == 0) {
00796       if (CKN_ON) {
00797         len = SIZE_OP_STATE_CHECK_PUSH + tlen;
00798       }
00799       else {
00800         len = SIZE_OP_PUSH + tlen;
00801       }
00802     }
00803     else {
00804       len = tlen;
00805     }
00806   }
00807   else if (!qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */
00808     len = SIZE_OP_PUSH + cklen + SIZE_OP_JUMP + tlen;
00809   }
00810   else {
00811     len = SIZE_OP_REPEAT_INC
00812         + mod_tlen + SIZE_OPCODE + SIZE_RELADDR + SIZE_MEMNUM;
00813     if (CKN_ON)
00814       len += SIZE_OP_STATE_CHECK;
00815   }
00816 
00817   return len;
00818 }
00819 
00820 static int
00821 compile_quantifier_node(QtfrNode* qn, regex_t* reg)
00822 {
00823   int r, mod_tlen;
00824   int ckn;
00825   int infinite = IS_REPEAT_INFINITE(qn->upper);
00826   int empty_info = qn->target_empty_info;
00827   int tlen = compile_length_tree(qn->target, reg);
00828 
00829   if (tlen < 0) return tlen;
00830 
00831   ckn = ((reg->num_comb_exp_check > 0) ? qn->comb_exp_check_num : 0);
00832 
00833   if (is_anychar_star_quantifier(qn)) {
00834     r = compile_tree_n_times(qn->target, qn->lower, reg);
00835     if (r) return r;
00836     if (IS_NOT_NULL(qn->next_head_exact) && !CKN_ON) {
00837       if (IS_MULTILINE(reg->options))
00838         r = add_opcode(reg, OP_ANYCHAR_ML_STAR_PEEK_NEXT);
00839       else
00840         r = add_opcode(reg, OP_ANYCHAR_STAR_PEEK_NEXT);
00841       if (r) return r;
00842       if (CKN_ON) {
00843         r = add_state_check_num(reg, ckn);
00844         if (r) return r;
00845       }
00846 
00847       return add_bytes(reg, NSTR(qn->next_head_exact)->s, 1);
00848     }
00849     else {
00850       if (IS_MULTILINE(reg->options)) {
00851         r = add_opcode(reg, (CKN_ON ?
00852                                OP_STATE_CHECK_ANYCHAR_ML_STAR
00853                              : OP_ANYCHAR_ML_STAR));
00854       }
00855       else {
00856         r = add_opcode(reg, (CKN_ON ?
00857                                OP_STATE_CHECK_ANYCHAR_STAR
00858                              : OP_ANYCHAR_STAR));
00859       }
00860       if (r) return r;
00861       if (CKN_ON)
00862         r = add_state_check_num(reg, ckn);
00863 
00864       return r;
00865     }
00866   }
00867 
00868   if (empty_info != 0)
00869     mod_tlen = tlen + (SIZE_OP_NULL_CHECK_START + SIZE_OP_NULL_CHECK_END);
00870   else
00871     mod_tlen = tlen;
00872 
00873   if (infinite && qn->lower <= 1) {
00874     if (qn->greedy) {
00875       if (qn->lower == 1) {
00876         r = add_opcode_rel_addr(reg, OP_JUMP,
00877                         (CKN_ON ? SIZE_OP_STATE_CHECK_PUSH : SIZE_OP_PUSH));
00878         if (r) return r;
00879       }
00880 
00881       if (CKN_ON) {
00882         r = add_opcode(reg, OP_STATE_CHECK_PUSH);
00883         if (r) return r;
00884         r = add_state_check_num(reg, ckn);
00885         if (r) return r;
00886         r = add_rel_addr(reg, mod_tlen + SIZE_OP_JUMP);
00887       }
00888       else {
00889         r = add_opcode_rel_addr(reg, OP_PUSH, mod_tlen + SIZE_OP_JUMP);
00890       }
00891       if (r) return r;
00892       r = compile_tree_empty_check(qn->target, reg, empty_info);
00893       if (r) return r;
00894       r = add_opcode_rel_addr(reg, OP_JUMP,
00895               -(mod_tlen + (int )SIZE_OP_JUMP
00896                 + (int )(CKN_ON ? SIZE_OP_STATE_CHECK_PUSH : SIZE_OP_PUSH)));
00897     }
00898     else {
00899       if (qn->lower == 0) {
00900         r = add_opcode_rel_addr(reg, OP_JUMP, mod_tlen);
00901         if (r) return r;
00902       }
00903       r = compile_tree_empty_check(qn->target, reg, empty_info);
00904       if (r) return r;
00905       if (CKN_ON) {
00906         r = add_opcode(reg, OP_STATE_CHECK_PUSH_OR_JUMP);
00907         if (r) return r;
00908         r = add_state_check_num(reg, ckn);
00909         if (r) return r;
00910         r = add_rel_addr(reg,
00911                  -(mod_tlen + (int )SIZE_OP_STATE_CHECK_PUSH_OR_JUMP));
00912       }
00913       else
00914         r = add_opcode_rel_addr(reg, OP_PUSH, -(mod_tlen + (int )SIZE_OP_PUSH));
00915     }
00916   }
00917   else if (qn->upper == 0) {
00918     if (qn->is_refered != 0) { /* /(?<n>..){0}/ */
00919       r = add_opcode_rel_addr(reg, OP_JUMP, tlen);
00920       if (r) return r;
00921       r = compile_tree(qn->target, reg);
00922     }
00923     else
00924       r = 0;
00925   }
00926   else if (qn->upper == 1 && qn->greedy) {
00927     if (qn->lower == 0) {
00928       if (CKN_ON) {
00929         r = add_opcode(reg, OP_STATE_CHECK_PUSH);
00930         if (r) return r;
00931         r = add_state_check_num(reg, ckn);
00932         if (r) return r;
00933         r = add_rel_addr(reg, tlen);
00934       }
00935       else {
00936         r = add_opcode_rel_addr(reg, OP_PUSH, tlen);
00937       }
00938       if (r) return r;
00939     }
00940 
00941     r = compile_tree(qn->target, reg);
00942   }
00943   else if (!qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */
00944     if (CKN_ON) {
00945       r = add_opcode(reg, OP_STATE_CHECK_PUSH);
00946       if (r) return r;
00947       r = add_state_check_num(reg, ckn);
00948       if (r) return r;
00949       r = add_rel_addr(reg, SIZE_OP_JUMP);
00950     }
00951     else {
00952       r = add_opcode_rel_addr(reg, OP_PUSH, SIZE_OP_JUMP);
00953     }
00954 
00955     if (r) return r;
00956     r = add_opcode_rel_addr(reg, OP_JUMP, tlen);
00957     if (r) return r;
00958     r = compile_tree(qn->target, reg);
00959   }
00960   else {
00961     r = compile_range_repeat_node(qn, mod_tlen, empty_info, reg);
00962     if (CKN_ON) {
00963       if (r) return r;
00964       r = add_opcode(reg, OP_STATE_CHECK);
00965       if (r) return r;
00966       r = add_state_check_num(reg, ckn);
00967     }
00968   }
00969   return r;
00970 }
00971 
00972 #else /* USE_COMBINATION_EXPLOSION_CHECK */
00973 
00974 static int
00975 compile_length_quantifier_node(QtfrNode* qn, regex_t* reg)
00976 {
00977   int len, mod_tlen;
00978   int infinite = IS_REPEAT_INFINITE(qn->upper);
00979   int empty_info = qn->target_empty_info;
00980   int tlen = compile_length_tree(qn->target, reg);
00981 
00982   if (tlen < 0) return tlen;
00983 
00984   /* anychar repeat */
00985   if (NTYPE(qn->target) == NT_CANY) {
00986     if (qn->greedy && infinite) {
00987       if (IS_NOT_NULL(qn->next_head_exact))
00988         return SIZE_OP_ANYCHAR_STAR_PEEK_NEXT + tlen * qn->lower;
00989       else
00990         return SIZE_OP_ANYCHAR_STAR + tlen * qn->lower;
00991     }
00992   }
00993 
00994   if (empty_info != 0)
00995     mod_tlen = tlen + (SIZE_OP_NULL_CHECK_START + SIZE_OP_NULL_CHECK_END);
00996   else
00997     mod_tlen = tlen;
00998 
00999   if (infinite &&
01000       (qn->lower <= 1 || tlen * qn->lower <= QUANTIFIER_EXPAND_LIMIT_SIZE)) {
01001     if (qn->lower == 1 && tlen > QUANTIFIER_EXPAND_LIMIT_SIZE) {
01002       len = SIZE_OP_JUMP;
01003     }
01004     else {
01005       len = tlen * qn->lower;
01006     }
01007 
01008     if (qn->greedy) {
01009       if (IS_NOT_NULL(qn->head_exact))
01010         len += SIZE_OP_PUSH_OR_JUMP_EXACT1 + mod_tlen + SIZE_OP_JUMP;
01011       else if (IS_NOT_NULL(qn->next_head_exact))
01012         len += SIZE_OP_PUSH_IF_PEEK_NEXT + mod_tlen + SIZE_OP_JUMP;
01013       else
01014         len += SIZE_OP_PUSH + mod_tlen + SIZE_OP_JUMP;
01015     }
01016     else
01017       len += SIZE_OP_JUMP + mod_tlen + SIZE_OP_PUSH;
01018   }
01019   else if (qn->upper == 0 && qn->is_refered != 0) { /* /(?<n>..){0}/ */
01020     len = SIZE_OP_JUMP + tlen;
01021   }
01022   else if (!infinite && qn->greedy &&
01023            (qn->upper == 1 || (tlen + SIZE_OP_PUSH) * qn->upper
01024                                       <= QUANTIFIER_EXPAND_LIMIT_SIZE)) {
01025     len = tlen * qn->lower;
01026     len += (SIZE_OP_PUSH + tlen) * (qn->upper - qn->lower);
01027   }
01028   else if (!qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */
01029     len = SIZE_OP_PUSH + SIZE_OP_JUMP + tlen;
01030   }
01031   else {
01032     len = SIZE_OP_REPEAT_INC
01033         + mod_tlen + SIZE_OPCODE + SIZE_RELADDR + SIZE_MEMNUM;
01034   }
01035 
01036   return len;
01037 }
01038 
01039 static int
01040 compile_quantifier_node(QtfrNode* qn, regex_t* reg)
01041 {
01042   int i, r, mod_tlen;
01043   int infinite = IS_REPEAT_INFINITE(qn->upper);
01044   int empty_info = qn->target_empty_info;
01045   int tlen = compile_length_tree(qn->target, reg);
01046 
01047   if (tlen < 0) return tlen;
01048 
01049   if (is_anychar_star_quantifier(qn)) {
01050     r = compile_tree_n_times(qn->target, qn->lower, reg);
01051     if (r) return r;
01052     if (IS_NOT_NULL(qn->next_head_exact)) {
01053       if (IS_MULTILINE(reg->options))
01054         r = add_opcode(reg, OP_ANYCHAR_ML_STAR_PEEK_NEXT);
01055       else
01056         r = add_opcode(reg, OP_ANYCHAR_STAR_PEEK_NEXT);
01057       if (r) return r;
01058       return add_bytes(reg, NSTR(qn->next_head_exact)->s, 1);
01059     }
01060     else {
01061       if (IS_MULTILINE(reg->options))
01062         return add_opcode(reg, OP_ANYCHAR_ML_STAR);
01063       else
01064         return add_opcode(reg, OP_ANYCHAR_STAR);
01065     }
01066   }
01067 
01068   if (empty_info != 0)
01069     mod_tlen = tlen + (SIZE_OP_NULL_CHECK_START + SIZE_OP_NULL_CHECK_END);
01070   else
01071     mod_tlen = tlen;
01072 
01073   if (infinite &&
01074       (qn->lower <= 1 || tlen * qn->lower <= QUANTIFIER_EXPAND_LIMIT_SIZE)) {
01075     if (qn->lower == 1 && tlen > QUANTIFIER_EXPAND_LIMIT_SIZE) {
01076       if (qn->greedy) {
01077         if (IS_NOT_NULL(qn->head_exact))
01078           r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH_OR_JUMP_EXACT1);
01079         else if (IS_NOT_NULL(qn->next_head_exact))
01080           r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH_IF_PEEK_NEXT);
01081         else
01082           r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH);
01083       }
01084       else {
01085         r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_JUMP);
01086       }
01087       if (r) return r;
01088     }
01089     else {
01090       r = compile_tree_n_times(qn->target, qn->lower, reg);
01091       if (r) return r;
01092     }
01093 
01094     if (qn->greedy) {
01095       if (IS_NOT_NULL(qn->head_exact)) {
01096         r = add_opcode_rel_addr(reg, OP_PUSH_OR_JUMP_EXACT1,
01097                              mod_tlen + SIZE_OP_JUMP);
01098         if (r) return r;
01099         add_bytes(reg, NSTR(qn->head_exact)->s, 1);
01100         r = compile_tree_empty_check(qn->target, reg, empty_info);
01101         if (r) return r;
01102         r = add_opcode_rel_addr(reg, OP_JUMP,
01103         -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH_OR_JUMP_EXACT1));
01104       }
01105       else if (IS_NOT_NULL(qn->next_head_exact)) {
01106         r = add_opcode_rel_addr(reg, OP_PUSH_IF_PEEK_NEXT,
01107                                 mod_tlen + SIZE_OP_JUMP);
01108         if (r) return r;
01109         add_bytes(reg, NSTR(qn->next_head_exact)->s, 1);
01110         r = compile_tree_empty_check(qn->target, reg, empty_info);
01111         if (r) return r;
01112         r = add_opcode_rel_addr(reg, OP_JUMP,
01113           -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH_IF_PEEK_NEXT));
01114       }
01115       else {
01116         r = add_opcode_rel_addr(reg, OP_PUSH, mod_tlen + SIZE_OP_JUMP);
01117         if (r) return r;
01118         r = compile_tree_empty_check(qn->target, reg, empty_info);
01119         if (r) return r;
01120         r = add_opcode_rel_addr(reg, OP_JUMP,
01121                      -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH));
01122       }
01123     }
01124     else {
01125       r = add_opcode_rel_addr(reg, OP_JUMP, mod_tlen);
01126       if (r) return r;
01127       r = compile_tree_empty_check(qn->target, reg, empty_info);
01128       if (r) return r;
01129       r = add_opcode_rel_addr(reg, OP_PUSH, -(mod_tlen + (int )SIZE_OP_PUSH));
01130     }
01131   }
01132   else if (qn->upper == 0 && qn->is_refered != 0) { /* /(?<n>..){0}/ */
01133     r = add_opcode_rel_addr(reg, OP_JUMP, tlen);
01134     if (r) return r;
01135     r = compile_tree(qn->target, reg);
01136   }
01137   else if (!infinite && qn->greedy &&
01138            (qn->upper == 1 || (tlen + SIZE_OP_PUSH) * qn->upper
01139                                   <= QUANTIFIER_EXPAND_LIMIT_SIZE)) {
01140     int n = qn->upper - qn->lower;
01141 
01142     r = compile_tree_n_times(qn->target, qn->lower, reg);
01143     if (r) return r;
01144 
01145     for (i = 0; i < n; i++) {
01146       r = add_opcode_rel_addr(reg, OP_PUSH,
01147                            (n - i) * tlen + (n - i - 1) * SIZE_OP_PUSH);
01148       if (r) return r;
01149       r = compile_tree(qn->target, reg);
01150       if (r) return r;
01151     }
01152   }
01153   else if (!qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */
01154     r = add_opcode_rel_addr(reg, OP_PUSH, SIZE_OP_JUMP);
01155     if (r) return r;
01156     r = add_opcode_rel_addr(reg, OP_JUMP, tlen);
01157     if (r) return r;
01158     r = compile_tree(qn->target, reg);
01159   }
01160   else {
01161     r = compile_range_repeat_node(qn, mod_tlen, empty_info, reg);
01162   }
01163   return r;
01164 }
01165 #endif /* USE_COMBINATION_EXPLOSION_CHECK */
01166 
01167 static int
01168 compile_length_option_node(EncloseNode* node, regex_t* reg)
01169 {
01170   int tlen;
01171   OnigOptionType prev = reg->options;
01172 
01173   reg->options = node->option;
01174   tlen = compile_length_tree(node->target, reg);
01175   reg->options = prev;
01176 
01177   if (tlen < 0) return tlen;
01178 
01179   if (IS_DYNAMIC_OPTION(prev ^ node->option)) {
01180     return SIZE_OP_SET_OPTION_PUSH + SIZE_OP_SET_OPTION + SIZE_OP_FAIL
01181            + tlen + SIZE_OP_SET_OPTION;
01182   }
01183   else
01184     return tlen;
01185 }
01186 
01187 static int
01188 compile_option_node(EncloseNode* node, regex_t* reg)
01189 {
01190   int r;
01191   OnigOptionType prev = reg->options;
01192 
01193   if (IS_DYNAMIC_OPTION(prev ^ node->option)) {
01194     r = add_opcode_option(reg, OP_SET_OPTION_PUSH, node->option);
01195     if (r) return r;
01196     r = add_opcode_option(reg, OP_SET_OPTION, prev);
01197     if (r) return r;
01198     r = add_opcode(reg, OP_FAIL);
01199     if (r) return r;
01200   }
01201 
01202   reg->options = node->option;
01203   r = compile_tree(node->target, reg);
01204   reg->options = prev;
01205 
01206   if (IS_DYNAMIC_OPTION(prev ^ node->option)) {
01207     if (r) return r;
01208     r = add_opcode_option(reg, OP_SET_OPTION, prev);
01209   }
01210   return r;
01211 }
01212 
01213 static int
01214 compile_length_enclose_node(EncloseNode* node, regex_t* reg)
01215 {
01216   int len;
01217   int tlen;
01218 
01219   if (node->type == ENCLOSE_OPTION)
01220     return compile_length_option_node(node, reg);
01221 
01222   if (node->target) {
01223     tlen = compile_length_tree(node->target, reg);
01224     if (tlen < 0) return tlen;
01225   }
01226   else
01227     tlen = 0;
01228 
01229   switch (node->type) {
01230   case ENCLOSE_MEMORY:
01231 #ifdef USE_SUBEXP_CALL
01232     if (IS_ENCLOSE_CALLED(node)) {
01233       len = SIZE_OP_MEMORY_START_PUSH + tlen
01234           + SIZE_OP_CALL + SIZE_OP_JUMP + SIZE_OP_RETURN;
01235       if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))
01236         len += (IS_ENCLOSE_RECURSION(node)
01237                 ? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_PUSH);
01238       else
01239         len += (IS_ENCLOSE_RECURSION(node)
01240                 ? SIZE_OP_MEMORY_END_REC : SIZE_OP_MEMORY_END);
01241     }
01242     else
01243 #endif
01244     {
01245       if (BIT_STATUS_AT(reg->bt_mem_start, node->regnum))
01246         len = SIZE_OP_MEMORY_START_PUSH;
01247       else
01248         len = SIZE_OP_MEMORY_START;
01249 
01250       len += tlen + (BIT_STATUS_AT(reg->bt_mem_end, node->regnum)
01251                      ? SIZE_OP_MEMORY_END_PUSH : SIZE_OP_MEMORY_END);
01252     }
01253     break;
01254 
01255   case ENCLOSE_STOP_BACKTRACK:
01256     if (IS_ENCLOSE_STOP_BT_SIMPLE_REPEAT(node)) {
01257       QtfrNode* qn = NQTFR(node->target);
01258       tlen = compile_length_tree(qn->target, reg);
01259       if (tlen < 0) return tlen;
01260 
01261       len = tlen * qn->lower
01262           + SIZE_OP_PUSH + tlen + SIZE_OP_POP + SIZE_OP_JUMP;
01263     }
01264     else {
01265       len = SIZE_OP_PUSH_STOP_BT + tlen + SIZE_OP_POP_STOP_BT;
01266     }
01267     break;
01268 
01269   case ENCLOSE_CONDITION:
01270     len = SIZE_OP_CONDITION;
01271     if (NTYPE(node->target) == NT_ALT) {
01272       Node* x = node->target;
01273 
01274       tlen = compile_length_tree(NCAR(x), reg); /* yes-node */
01275       if (tlen < 0) return tlen;
01276       len += tlen + SIZE_OP_JUMP;
01277       if (NCDR(x) == NULL) return ONIGERR_PARSER_BUG;
01278       x = NCDR(x);
01279       tlen = compile_length_tree(NCAR(x), reg); /* no-node */
01280       if (tlen < 0) return tlen;
01281       len += tlen;
01282       if (NCDR(x) != NULL) return ONIGERR_INVALID_CONDITION_PATTERN;
01283     }
01284     else {
01285       return ONIGERR_PARSER_BUG;
01286     }
01287     break;
01288 
01289   default:
01290     return ONIGERR_TYPE_BUG;
01291     break;
01292   }
01293 
01294   return len;
01295 }
01296 
01297 static int get_char_length_tree(Node* node, regex_t* reg, int* len);
01298 
01299 static int
01300 compile_enclose_node(EncloseNode* node, regex_t* reg)
01301 {
01302   int r, len;
01303 
01304   if (node->type == ENCLOSE_OPTION)
01305     return compile_option_node(node, reg);
01306 
01307   switch (node->type) {
01308   case ENCLOSE_MEMORY:
01309 #ifdef USE_SUBEXP_CALL
01310     if (IS_ENCLOSE_CALLED(node)) {
01311       r = add_opcode(reg, OP_CALL);
01312       if (r) return r;
01313       node->call_addr = BBUF_GET_OFFSET_POS(reg) + SIZE_ABSADDR + SIZE_OP_JUMP;
01314       node->state |= NST_ADDR_FIXED;
01315       r = add_abs_addr(reg, (int )node->call_addr);
01316       if (r) return r;
01317       len = compile_length_tree(node->target, reg);
01318       len += (SIZE_OP_MEMORY_START_PUSH + SIZE_OP_RETURN);
01319       if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))
01320         len += (IS_ENCLOSE_RECURSION(node)
01321                 ? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_PUSH);
01322       else
01323         len += (IS_ENCLOSE_RECURSION(node)
01324                 ? SIZE_OP_MEMORY_END_REC : SIZE_OP_MEMORY_END);
01325 
01326       r = add_opcode_rel_addr(reg, OP_JUMP, len);
01327       if (r) return r;
01328     }
01329 #endif
01330     if (BIT_STATUS_AT(reg->bt_mem_start, node->regnum))
01331       r = add_opcode(reg, OP_MEMORY_START_PUSH);
01332     else
01333       r = add_opcode(reg, OP_MEMORY_START);
01334     if (r) return r;
01335     r = add_mem_num(reg, node->regnum);
01336     if (r) return r;
01337     r = compile_tree(node->target, reg);
01338     if (r) return r;
01339 #ifdef USE_SUBEXP_CALL
01340     if (IS_ENCLOSE_CALLED(node)) {
01341       if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))
01342         r = add_opcode(reg, (IS_ENCLOSE_RECURSION(node)
01343                              ? OP_MEMORY_END_PUSH_REC : OP_MEMORY_END_PUSH));
01344       else
01345         r = add_opcode(reg, (IS_ENCLOSE_RECURSION(node)
01346                              ? OP_MEMORY_END_REC : OP_MEMORY_END));
01347 
01348       if (r) return r;
01349       r = add_mem_num(reg, node->regnum);
01350       if (r) return r;
01351       r = add_opcode(reg, OP_RETURN);
01352     }
01353     else
01354 #endif
01355     {
01356       if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))
01357         r = add_opcode(reg, OP_MEMORY_END_PUSH);
01358       else
01359         r = add_opcode(reg, OP_MEMORY_END);
01360       if (r) return r;
01361       r = add_mem_num(reg, node->regnum);
01362     }
01363     break;
01364 
01365   case ENCLOSE_STOP_BACKTRACK:
01366     if (IS_ENCLOSE_STOP_BT_SIMPLE_REPEAT(node)) {
01367       QtfrNode* qn = NQTFR(node->target);
01368       r = compile_tree_n_times(qn->target, qn->lower, reg);
01369       if (r) return r;
01370 
01371       len = compile_length_tree(qn->target, reg);
01372       if (len < 0) return len;
01373 
01374       r = add_opcode_rel_addr(reg, OP_PUSH, len + SIZE_OP_POP + SIZE_OP_JUMP);
01375       if (r) return r;
01376       r = compile_tree(qn->target, reg);
01377       if (r) return r;
01378       r = add_opcode(reg, OP_POP);
01379       if (r) return r;
01380       r = add_opcode_rel_addr(reg, OP_JUMP,
01381          -((int )SIZE_OP_PUSH + len + (int )SIZE_OP_POP + (int )SIZE_OP_JUMP));
01382     }
01383     else {
01384       r = add_opcode(reg, OP_PUSH_STOP_BT);
01385       if (r) return r;
01386       r = compile_tree(node->target, reg);
01387       if (r) return r;
01388       r = add_opcode(reg, OP_POP_STOP_BT);
01389     }
01390     break;
01391 
01392   case ENCLOSE_CONDITION:
01393     r = add_opcode(reg, OP_CONDITION);
01394     if (r) return r;
01395     r = add_mem_num(reg, node->regnum);
01396     if (r) return r;
01397 
01398     if (NTYPE(node->target) == NT_ALT) {
01399       Node* x = node->target;
01400       int len2;
01401 
01402       len = compile_length_tree(NCAR(x), reg);  /* yes-node */
01403       if (len < 0) return len;
01404       if (NCDR(x) == NULL) return ONIGERR_PARSER_BUG;
01405       x = NCDR(x);
01406       len2 = compile_length_tree(NCAR(x), reg); /* no-node */
01407       if (len2 < 0) return len2;
01408       if (NCDR(x) != NULL) return ONIGERR_INVALID_CONDITION_PATTERN;
01409 
01410       x = node->target;
01411       r = add_rel_addr(reg, len + SIZE_OP_JUMP);
01412       if (r) return r;
01413       r = compile_tree(NCAR(x), reg);   /* yes-node */
01414       if (r) return r;
01415       r = add_opcode_rel_addr(reg, OP_JUMP, len2);
01416       if (r) return r;
01417       x = NCDR(x);
01418       r = compile_tree(NCAR(x), reg);   /* no-node */
01419     }
01420     else {
01421       return ONIGERR_PARSER_BUG;
01422     }
01423     break;
01424 
01425   default:
01426     return ONIGERR_TYPE_BUG;
01427     break;
01428   }
01429 
01430   return r;
01431 }
01432 
01433 static int
01434 compile_length_anchor_node(AnchorNode* node, regex_t* reg)
01435 {
01436   int len;
01437   int tlen = 0;
01438 
01439   if (node->target) {
01440     tlen = compile_length_tree(node->target, reg);
01441     if (tlen < 0) return tlen;
01442   }
01443 
01444   switch (node->type) {
01445   case ANCHOR_PREC_READ:
01446     len = SIZE_OP_PUSH_POS + tlen + SIZE_OP_POP_POS;
01447     break;
01448   case ANCHOR_PREC_READ_NOT:
01449     len = SIZE_OP_PUSH_POS_NOT + tlen + SIZE_OP_FAIL_POS;
01450     break;
01451   case ANCHOR_LOOK_BEHIND:
01452     len = SIZE_OP_LOOK_BEHIND + tlen;
01453     break;
01454   case ANCHOR_LOOK_BEHIND_NOT:
01455     len = SIZE_OP_PUSH_LOOK_BEHIND_NOT + tlen + SIZE_OP_FAIL_LOOK_BEHIND_NOT;
01456     break;
01457 
01458   default:
01459     len = SIZE_OPCODE;
01460     break;
01461   }
01462 
01463   return len;
01464 }
01465 
01466 static int
01467 compile_anchor_node(AnchorNode* node, regex_t* reg)
01468 {
01469   int r, len;
01470 
01471   switch (node->type) {
01472   case ANCHOR_BEGIN_BUF:      r = add_opcode(reg, OP_BEGIN_BUF);      break;
01473   case ANCHOR_END_BUF:        r = add_opcode(reg, OP_END_BUF);        break;
01474   case ANCHOR_BEGIN_LINE:     r = add_opcode(reg, OP_BEGIN_LINE);     break;
01475   case ANCHOR_END_LINE:       r = add_opcode(reg, OP_END_LINE);       break;
01476   case ANCHOR_SEMI_END_BUF:   r = add_opcode(reg, OP_SEMI_END_BUF);   break;
01477   case ANCHOR_BEGIN_POSITION: r = add_opcode(reg, OP_BEGIN_POSITION); break;
01478 
01479   /* used for implicit anchor optimization: /.*a/ ==> /(?:^|\G).*a/ */
01480   case ANCHOR_ANYCHAR_STAR:   r = add_opcode(reg, OP_BEGIN_POS_OR_LINE); break;
01481 
01482   case ANCHOR_WORD_BOUND:
01483     if (node->ascii_range)    r = add_opcode(reg, OP_ASCII_WORD_BOUND);
01484     else                      r = add_opcode(reg, OP_WORD_BOUND);
01485     break;
01486   case ANCHOR_NOT_WORD_BOUND:
01487     if (node->ascii_range)    r = add_opcode(reg, OP_NOT_ASCII_WORD_BOUND);
01488     else                      r = add_opcode(reg, OP_NOT_WORD_BOUND);
01489     break;
01490 #ifdef USE_WORD_BEGIN_END
01491   case ANCHOR_WORD_BEGIN:
01492     if (node->ascii_range)    r = add_opcode(reg, OP_ASCII_WORD_BEGIN);
01493     else                      r = add_opcode(reg, OP_WORD_BEGIN);
01494     break;
01495   case ANCHOR_WORD_END:
01496     if (node->ascii_range)    r = add_opcode(reg, OP_ASCII_WORD_END);
01497     else                      r = add_opcode(reg, OP_WORD_END);
01498     break;
01499 #endif
01500   case ANCHOR_KEEP:           r = add_opcode(reg, OP_KEEP);           break;
01501 
01502   case ANCHOR_PREC_READ:
01503     r = add_opcode(reg, OP_PUSH_POS);
01504     if (r) return r;
01505     r = compile_tree(node->target, reg);
01506     if (r) return r;
01507     r = add_opcode(reg, OP_POP_POS);
01508     break;
01509 
01510   case ANCHOR_PREC_READ_NOT:
01511     len = compile_length_tree(node->target, reg);
01512     if (len < 0) return len;
01513     r = add_opcode_rel_addr(reg, OP_PUSH_POS_NOT, len + SIZE_OP_FAIL_POS);
01514     if (r) return r;
01515     r = compile_tree(node->target, reg);
01516     if (r) return r;
01517     r = add_opcode(reg, OP_FAIL_POS);
01518     break;
01519 
01520   case ANCHOR_LOOK_BEHIND:
01521     {
01522       int n;
01523       r = add_opcode(reg, OP_LOOK_BEHIND);
01524       if (r) return r;
01525       if (node->char_len < 0) {
01526         r = get_char_length_tree(node->target, reg, &n);
01527         if (r) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
01528       }
01529       else
01530         n = node->char_len;
01531       r = add_length(reg, n);
01532       if (r) return r;
01533       r = compile_tree(node->target, reg);
01534     }
01535     break;
01536 
01537   case ANCHOR_LOOK_BEHIND_NOT:
01538     {
01539       int n;
01540       len = compile_length_tree(node->target, reg);
01541       r = add_opcode_rel_addr(reg, OP_PUSH_LOOK_BEHIND_NOT,
01542                            len + SIZE_OP_FAIL_LOOK_BEHIND_NOT);
01543       if (r) return r;
01544       if (node->char_len < 0) {
01545         r = get_char_length_tree(node->target, reg, &n);
01546         if (r) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
01547       }
01548       else
01549         n = node->char_len;
01550       r = add_length(reg, n);
01551       if (r) return r;
01552       r = compile_tree(node->target, reg);
01553       if (r) return r;
01554       r = add_opcode(reg, OP_FAIL_LOOK_BEHIND_NOT);
01555     }
01556     break;
01557 
01558   default:
01559     return ONIGERR_TYPE_BUG;
01560     break;
01561   }
01562 
01563   return r;
01564 }
01565 
01566 static int
01567 compile_length_tree(Node* node, regex_t* reg)
01568 {
01569   int len, type, r;
01570 
01571   type = NTYPE(node);
01572   switch (type) {
01573   case NT_LIST:
01574     len = 0;
01575     do {
01576       r = compile_length_tree(NCAR(node), reg);
01577       if (r < 0) return r;
01578       len += r;
01579     } while (IS_NOT_NULL(node = NCDR(node)));
01580     r = len;
01581     break;
01582 
01583   case NT_ALT:
01584     {
01585       int n;
01586 
01587       n = r = 0;
01588       do {
01589         r += compile_length_tree(NCAR(node), reg);
01590         n++;
01591       } while (IS_NOT_NULL(node = NCDR(node)));
01592       r += (SIZE_OP_PUSH + SIZE_OP_JUMP) * (n - 1);
01593     }
01594     break;
01595 
01596   case NT_STR:
01597     if (NSTRING_IS_RAW(node))
01598       r = compile_length_string_raw_node(NSTR(node), reg);
01599     else
01600       r = compile_length_string_node(node, reg);
01601     break;
01602 
01603   case NT_CCLASS:
01604     r = compile_length_cclass_node(NCCLASS(node), reg);
01605     break;
01606 
01607   case NT_CTYPE:
01608   case NT_CANY:
01609     r = SIZE_OPCODE;
01610     break;
01611 
01612   case NT_BREF:
01613     {
01614       BRefNode* br = NBREF(node);
01615 
01616 #ifdef USE_BACKREF_WITH_LEVEL
01617       if (IS_BACKREF_NEST_LEVEL(br)) {
01618         r = SIZE_OPCODE + SIZE_OPTION + SIZE_LENGTH +
01619             SIZE_LENGTH + (SIZE_MEMNUM * br->back_num);
01620       }
01621       else
01622 #endif
01623       if (br->back_num == 1) {
01624         r = ((!IS_IGNORECASE(reg->options) && br->back_static[0] <= 2)
01625              ? SIZE_OPCODE : (SIZE_OPCODE + SIZE_MEMNUM));
01626       }
01627       else {
01628         r = SIZE_OPCODE + SIZE_LENGTH + (SIZE_MEMNUM * br->back_num);
01629       }
01630     }
01631     break;
01632 
01633 #ifdef USE_SUBEXP_CALL
01634   case NT_CALL:
01635     r = SIZE_OP_CALL;
01636     break;
01637 #endif
01638 
01639   case NT_QTFR:
01640     r = compile_length_quantifier_node(NQTFR(node), reg);
01641     break;
01642 
01643   case NT_ENCLOSE:
01644     r = compile_length_enclose_node(NENCLOSE(node), reg);
01645     break;
01646 
01647   case NT_ANCHOR:
01648     r = compile_length_anchor_node(NANCHOR(node), reg);
01649     break;
01650 
01651   default:
01652     return ONIGERR_TYPE_BUG;
01653     break;
01654   }
01655 
01656   return r;
01657 }
01658 
01659 static int
01660 compile_tree(Node* node, regex_t* reg)
01661 {
01662   int n, type, len, pos, r = 0;
01663 
01664   type = NTYPE(node);
01665   switch (type) {
01666   case NT_LIST:
01667     do {
01668       r = compile_tree(NCAR(node), reg);
01669     } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
01670     break;
01671 
01672   case NT_ALT:
01673     {
01674       Node* x = node;
01675       len = 0;
01676       do {
01677         len += compile_length_tree(NCAR(x), reg);
01678         if (NCDR(x) != NULL) {
01679           len += SIZE_OP_PUSH + SIZE_OP_JUMP;
01680         }
01681       } while (IS_NOT_NULL(x = NCDR(x)));
01682       pos = reg->used + len;  /* goal position */
01683 
01684       do {
01685         len = compile_length_tree(NCAR(node), reg);
01686         if (IS_NOT_NULL(NCDR(node))) {
01687           r = add_opcode_rel_addr(reg, OP_PUSH, len + SIZE_OP_JUMP);
01688           if (r) break;
01689         }
01690         r = compile_tree(NCAR(node), reg);
01691         if (r) break;
01692         if (IS_NOT_NULL(NCDR(node))) {
01693           len = pos - (reg->used + SIZE_OP_JUMP);
01694           r = add_opcode_rel_addr(reg, OP_JUMP, len);
01695           if (r) break;
01696         }
01697       } while (IS_NOT_NULL(node = NCDR(node)));
01698     }
01699     break;
01700 
01701   case NT_STR:
01702     if (NSTRING_IS_RAW(node))
01703       r = compile_string_raw_node(NSTR(node), reg);
01704     else
01705       r = compile_string_node(node, reg);
01706     break;
01707 
01708   case NT_CCLASS:
01709     r = compile_cclass_node(NCCLASS(node), reg);
01710     break;
01711 
01712   case NT_CTYPE:
01713     {
01714       int op;
01715 
01716       switch (NCTYPE(node)->ctype) {
01717       case ONIGENC_CTYPE_WORD:
01718         if (NCTYPE(node)->ascii_range != 0) {
01719           if (NCTYPE(node)->not != 0)  op = OP_NOT_ASCII_WORD;
01720           else                         op = OP_ASCII_WORD;
01721         }
01722         else {
01723           if (NCTYPE(node)->not != 0)  op = OP_NOT_WORD;
01724           else                         op = OP_WORD;
01725         }
01726         break;
01727       default:
01728         return ONIGERR_TYPE_BUG;
01729         break;
01730       }
01731       r = add_opcode(reg, op);
01732     }
01733     break;
01734 
01735   case NT_CANY:
01736     if (IS_MULTILINE(reg->options))
01737       r = add_opcode(reg, OP_ANYCHAR_ML);
01738     else
01739       r = add_opcode(reg, OP_ANYCHAR);
01740     break;
01741 
01742   case NT_BREF:
01743     {
01744       BRefNode* br = NBREF(node);
01745 
01746 #ifdef USE_BACKREF_WITH_LEVEL
01747       if (IS_BACKREF_NEST_LEVEL(br)) {
01748         r = add_opcode(reg, OP_BACKREF_WITH_LEVEL);
01749         if (r) return r;
01750         r = add_option(reg, (reg->options & ONIG_OPTION_IGNORECASE));
01751         if (r) return r;
01752         r = add_length(reg, br->nest_level);
01753         if (r) return r;
01754 
01755         goto add_bacref_mems;
01756       }
01757       else
01758 #endif
01759       if (br->back_num == 1) {
01760         n = br->back_static[0];
01761         if (IS_IGNORECASE(reg->options)) {
01762           r = add_opcode(reg, OP_BACKREFN_IC);
01763           if (r) return r;
01764           r = add_mem_num(reg, n);
01765         }
01766         else {
01767           switch (n) {
01768           case 1:  r = add_opcode(reg, OP_BACKREF1); break;
01769           case 2:  r = add_opcode(reg, OP_BACKREF2); break;
01770           default:
01771             r = add_opcode(reg, OP_BACKREFN);
01772             if (r) return r;
01773             r = add_mem_num(reg, n);
01774             break;
01775           }
01776         }
01777       }
01778       else {
01779         int i;
01780         int* p;
01781 
01782         if (IS_IGNORECASE(reg->options)) {
01783           r = add_opcode(reg, OP_BACKREF_MULTI_IC);
01784         }
01785         else {
01786           r = add_opcode(reg, OP_BACKREF_MULTI);
01787         }
01788         if (r) return r;
01789 
01790 #ifdef USE_BACKREF_WITH_LEVEL
01791       add_bacref_mems:
01792 #endif
01793         r = add_length(reg, br->back_num);
01794         if (r) return r;
01795         p = BACKREFS_P(br);
01796         for (i = br->back_num - 1; i >= 0; i--) {
01797           r = add_mem_num(reg, p[i]);
01798           if (r) return r;
01799         }
01800       }
01801     }
01802     break;
01803 
01804 #ifdef USE_SUBEXP_CALL
01805   case NT_CALL:
01806     r = compile_call(NCALL(node), reg);
01807     break;
01808 #endif
01809 
01810   case NT_QTFR:
01811     r = compile_quantifier_node(NQTFR(node), reg);
01812     break;
01813 
01814   case NT_ENCLOSE:
01815     r = compile_enclose_node(NENCLOSE(node), reg);
01816     break;
01817 
01818   case NT_ANCHOR:
01819     r = compile_anchor_node(NANCHOR(node), reg);
01820     break;
01821 
01822   default:
01823 #ifdef ONIG_DEBUG
01824     fprintf(stderr, "compile_tree: undefined node type %d\n", NTYPE(node));
01825 #endif
01826     break;
01827   }
01828 
01829   return r;
01830 }
01831 
01832 #ifdef USE_NAMED_GROUP
01833 
01834 static int
01835 noname_disable_map(Node** plink, GroupNumRemap* map, int* counter)
01836 {
01837   int r = 0;
01838   Node* node = *plink;
01839 
01840   switch (NTYPE(node)) {
01841   case NT_LIST:
01842   case NT_ALT:
01843     do {
01844       r = noname_disable_map(&(NCAR(node)), map, counter);
01845     } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
01846     break;
01847 
01848   case NT_QTFR:
01849     {
01850       Node** ptarget = &(NQTFR(node)->target);
01851       Node*  old = *ptarget;
01852       r = noname_disable_map(ptarget, map, counter);
01853       if (*ptarget != old && NTYPE(*ptarget) == NT_QTFR) {
01854         onig_reduce_nested_quantifier(node, *ptarget);
01855       }
01856     }
01857     break;
01858 
01859   case NT_ENCLOSE:
01860     {
01861       EncloseNode* en = NENCLOSE(node);
01862       if (en->type == ENCLOSE_MEMORY) {
01863         if (IS_ENCLOSE_NAMED_GROUP(en)) {
01864           (*counter)++;
01865           map[en->regnum].new_val = *counter;
01866           en->regnum = *counter;
01867           r = noname_disable_map(&(en->target), map, counter);
01868         }
01869         else {
01870           *plink = en->target;
01871           en->target = NULL_NODE;
01872           onig_node_free(node);
01873           r = noname_disable_map(plink, map, counter);
01874         }
01875       }
01876       else
01877         r = noname_disable_map(&(en->target), map, counter);
01878     }
01879     break;
01880 
01881   case NT_ANCHOR:
01882     {
01883       AnchorNode* an = NANCHOR(node);
01884       switch (an->type) {
01885       case ANCHOR_PREC_READ:
01886       case ANCHOR_PREC_READ_NOT:
01887       case ANCHOR_LOOK_BEHIND:
01888       case ANCHOR_LOOK_BEHIND_NOT:
01889         r = noname_disable_map(&(an->target), map, counter);
01890         break;
01891       }
01892     }
01893     break;
01894 
01895   default:
01896     break;
01897   }
01898 
01899   return r;
01900 }
01901 
01902 static int
01903 renumber_node_backref(Node* node, GroupNumRemap* map)
01904 {
01905   int i, pos, n, old_num;
01906   int *backs;
01907   BRefNode* bn = NBREF(node);
01908 
01909   if (! IS_BACKREF_NAME_REF(bn))
01910     return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;
01911 
01912   old_num = bn->back_num;
01913   if (IS_NULL(bn->back_dynamic))
01914     backs = bn->back_static;
01915   else
01916     backs = bn->back_dynamic;
01917 
01918   for (i = 0, pos = 0; i < old_num; i++) {
01919     n = map[backs[i]].new_val;
01920     if (n > 0) {
01921       backs[pos] = n;
01922       pos++;
01923     }
01924   }
01925 
01926   bn->back_num = pos;
01927   return 0;
01928 }
01929 
01930 static int
01931 renumber_by_map(Node* node, GroupNumRemap* map)
01932 {
01933   int r = 0;
01934 
01935   switch (NTYPE(node)) {
01936   case NT_LIST:
01937   case NT_ALT:
01938     do {
01939       r = renumber_by_map(NCAR(node), map);
01940     } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
01941     break;
01942   case NT_QTFR:
01943     r = renumber_by_map(NQTFR(node)->target, map);
01944     break;
01945   case NT_ENCLOSE:
01946     {
01947       EncloseNode* en = NENCLOSE(node);
01948       if (en->type == ENCLOSE_CONDITION)
01949         en->regnum = map[en->regnum].new_val;
01950       r = renumber_by_map(en->target, map);
01951     }
01952     break;
01953 
01954   case NT_BREF:
01955     r = renumber_node_backref(node, map);
01956     break;
01957 
01958   case NT_ANCHOR:
01959     {
01960       AnchorNode* an = NANCHOR(node);
01961       switch (an->type) {
01962       case ANCHOR_PREC_READ:
01963       case ANCHOR_PREC_READ_NOT:
01964       case ANCHOR_LOOK_BEHIND:
01965       case ANCHOR_LOOK_BEHIND_NOT:
01966         r = renumber_by_map(an->target, map);
01967         break;
01968       }
01969     }
01970     break;
01971 
01972   default:
01973     break;
01974   }
01975 
01976   return r;
01977 }
01978 
01979 static int
01980 numbered_ref_check(Node* node)
01981 {
01982   int r = 0;
01983 
01984   switch (NTYPE(node)) {
01985   case NT_LIST:
01986   case NT_ALT:
01987     do {
01988       r = numbered_ref_check(NCAR(node));
01989     } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
01990     break;
01991   case NT_QTFR:
01992     r = numbered_ref_check(NQTFR(node)->target);
01993     break;
01994   case NT_ENCLOSE:
01995     r = numbered_ref_check(NENCLOSE(node)->target);
01996     break;
01997 
01998   case NT_BREF:
01999     if (! IS_BACKREF_NAME_REF(NBREF(node)))
02000       return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;
02001     break;
02002 
02003   default:
02004     break;
02005   }
02006 
02007   return r;
02008 }
02009 
02010 static int
02011 disable_noname_group_capture(Node** root, regex_t* reg, ScanEnv* env)
02012 {
02013   int r, i, pos, counter;
02014   BitStatusType loc;
02015   GroupNumRemap* map;
02016 
02017   map = (GroupNumRemap* )xalloca(sizeof(GroupNumRemap) * (env->num_mem + 1));
02018   CHECK_NULL_RETURN_MEMERR(map);
02019   for (i = 1; i <= env->num_mem; i++) {
02020     map[i].new_val = 0;
02021   }
02022   counter = 0;
02023   r = noname_disable_map(root, map, &counter);
02024   if (r != 0) return r;
02025 
02026   r = renumber_by_map(*root, map);
02027   if (r != 0) return r;
02028 
02029   for (i = 1, pos = 1; i <= env->num_mem; i++) {
02030     if (map[i].new_val > 0) {
02031       SCANENV_MEM_NODES(env)[pos] = SCANENV_MEM_NODES(env)[i];
02032       pos++;
02033     }
02034   }
02035 
02036   loc = env->capture_history;
02037   BIT_STATUS_CLEAR(env->capture_history);
02038   for (i = 1; i <= ONIG_MAX_CAPTURE_HISTORY_GROUP; i++) {
02039     if (BIT_STATUS_AT(loc, i)) {
02040       BIT_STATUS_ON_AT_SIMPLE(env->capture_history, map[i].new_val);
02041     }
02042   }
02043 
02044   env->num_mem = env->num_named;
02045   reg->num_mem = env->num_named;
02046 
02047   return onig_renumber_name_table(reg, map);
02048 }
02049 #endif /* USE_NAMED_GROUP */
02050 
02051 #ifdef USE_SUBEXP_CALL
02052 static int
02053 unset_addr_list_fix(UnsetAddrList* uslist, regex_t* reg)
02054 {
02055   int i, offset;
02056   EncloseNode* en;
02057   AbsAddrType addr;
02058 
02059   for (i = 0; i < uslist->num; i++) {
02060     en = NENCLOSE(uslist->us[i].target);
02061     if (! IS_ENCLOSE_ADDR_FIXED(en)) return ONIGERR_PARSER_BUG;
02062     addr = en->call_addr;
02063     offset = uslist->us[i].offset;
02064 
02065     BBUF_WRITE(reg, offset, &addr, SIZE_ABSADDR);
02066   }
02067   return 0;
02068 }
02069 #endif
02070 
02071 #ifdef USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT
02072 static int
02073 quantifiers_memory_node_info(Node* node)
02074 {
02075   int r = 0;
02076 
02077   switch (NTYPE(node)) {
02078   case NT_LIST:
02079   case NT_ALT:
02080     {
02081       int v;
02082       do {
02083         v = quantifiers_memory_node_info(NCAR(node));
02084         if (v > r) r = v;
02085       } while (v >= 0 && IS_NOT_NULL(node = NCDR(node)));
02086     }
02087     break;
02088 
02089 #ifdef USE_SUBEXP_CALL
02090   case NT_CALL:
02091     if (IS_CALL_RECURSION(NCALL(node))) {
02092       return NQ_TARGET_IS_EMPTY_REC; /* tiny version */
02093     }
02094     else
02095       r = quantifiers_memory_node_info(NCALL(node)->target);
02096     break;
02097 #endif
02098 
02099   case NT_QTFR:
02100     {
02101       QtfrNode* qn = NQTFR(node);
02102       if (qn->upper != 0) {
02103         r = quantifiers_memory_node_info(qn->target);
02104       }
02105     }
02106     break;
02107 
02108   case NT_ENCLOSE:
02109     {
02110       EncloseNode* en = NENCLOSE(node);
02111       switch (en->type) {
02112       case ENCLOSE_MEMORY:
02113         return NQ_TARGET_IS_EMPTY_MEM;
02114         break;
02115 
02116       case ENCLOSE_OPTION:
02117       case ENCLOSE_STOP_BACKTRACK:
02118       case ENCLOSE_CONDITION:
02119         r = quantifiers_memory_node_info(en->target);
02120         break;
02121       default:
02122         break;
02123       }
02124     }
02125     break;
02126 
02127   case NT_BREF:
02128   case NT_STR:
02129   case NT_CTYPE:
02130   case NT_CCLASS:
02131   case NT_CANY:
02132   case NT_ANCHOR:
02133   default:
02134     break;
02135   }
02136 
02137   return r;
02138 }
02139 #endif /* USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT */
02140 
02141 static int
02142 get_min_match_length(Node* node, OnigDistance *min, ScanEnv* env)
02143 {
02144   OnigDistance tmin;
02145   int r = 0;
02146 
02147   *min = 0;
02148   switch (NTYPE(node)) {
02149   case NT_BREF:
02150     {
02151       int i;
02152       int* backs;
02153       Node** nodes = SCANENV_MEM_NODES(env);
02154       BRefNode* br = NBREF(node);
02155       if (br->state & NST_RECURSION) break;
02156 
02157       backs = BACKREFS_P(br);
02158       if (backs[0] > env->num_mem)  return ONIGERR_INVALID_BACKREF;
02159       r = get_min_match_length(nodes[backs[0]], min, env);
02160       if (r != 0) break;
02161       for (i = 1; i < br->back_num; i++) {
02162         if (backs[i] > env->num_mem)  return ONIGERR_INVALID_BACKREF;
02163         r = get_min_match_length(nodes[backs[i]], &tmin, env);
02164         if (r != 0) break;
02165         if (*min > tmin) *min = tmin;
02166       }
02167     }
02168     break;
02169 
02170 #ifdef USE_SUBEXP_CALL
02171   case NT_CALL:
02172     if (IS_CALL_RECURSION(NCALL(node))) {
02173       EncloseNode* en = NENCLOSE(NCALL(node)->target);
02174       if (IS_ENCLOSE_MIN_FIXED(en))
02175         *min = en->min_len;
02176     }
02177     else
02178       r = get_min_match_length(NCALL(node)->target, min, env);
02179     break;
02180 #endif
02181 
02182   case NT_LIST:
02183     do {
02184       r = get_min_match_length(NCAR(node), &tmin, env);
02185       if (r == 0) *min += tmin;
02186     } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
02187     break;
02188 
02189   case NT_ALT:
02190     {
02191       Node *x, *y;
02192       y = node;
02193       do {
02194         x = NCAR(y);
02195         r = get_min_match_length(x, &tmin, env);
02196         if (r != 0) break;
02197         if (y == node) *min = tmin;
02198         else if (*min > tmin) *min = tmin;
02199       } while (r == 0 && IS_NOT_NULL(y = NCDR(y)));
02200     }
02201     break;
02202 
02203   case NT_STR:
02204     {
02205       StrNode* sn = NSTR(node);
02206       *min = sn->end - sn->s;
02207     }
02208     break;
02209 
02210   case NT_CTYPE:
02211     *min = 1;
02212     break;
02213 
02214   case NT_CCLASS:
02215   case NT_CANY:
02216     *min = 1;
02217     break;
02218 
02219   case NT_QTFR:
02220     {
02221       QtfrNode* qn = NQTFR(node);
02222 
02223       if (qn->lower > 0) {
02224         r = get_min_match_length(qn->target, min, env);
02225         if (r == 0)
02226           *min = distance_multiply(*min, qn->lower);
02227       }
02228     }
02229     break;
02230 
02231   case NT_ENCLOSE:
02232     {
02233       EncloseNode* en = NENCLOSE(node);
02234       switch (en->type) {
02235       case ENCLOSE_MEMORY:
02236 #ifdef USE_SUBEXP_CALL
02237         if (IS_ENCLOSE_MIN_FIXED(en))
02238           *min = en->min_len;
02239         else {
02240           r = get_min_match_length(en->target, min, env);
02241           if (r == 0) {
02242             en->min_len = *min;
02243             SET_ENCLOSE_STATUS(node, NST_MIN_FIXED);
02244           }
02245         }
02246         break;
02247 #endif
02248       case ENCLOSE_OPTION:
02249       case ENCLOSE_STOP_BACKTRACK:
02250       case ENCLOSE_CONDITION:
02251         r = get_min_match_length(en->target, min, env);
02252         break;
02253       }
02254     }
02255     break;
02256 
02257   case NT_ANCHOR:
02258   default:
02259     break;
02260   }
02261 
02262   return r;
02263 }
02264 
02265 static int
02266 get_max_match_length(Node* node, OnigDistance *max, ScanEnv* env)
02267 {
02268   OnigDistance tmax;
02269   int r = 0;
02270 
02271   *max = 0;
02272   switch (NTYPE(node)) {
02273   case NT_LIST:
02274     do {
02275       r = get_max_match_length(NCAR(node), &tmax, env);
02276       if (r == 0)
02277         *max = distance_add(*max, tmax);
02278     } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
02279     break;
02280 
02281   case NT_ALT:
02282     do {
02283       r = get_max_match_length(NCAR(node), &tmax, env);
02284       if (r == 0 && *max < tmax) *max = tmax;
02285     } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
02286     break;
02287 
02288   case NT_STR:
02289     {
02290       StrNode* sn = NSTR(node);
02291       *max = sn->end - sn->s;
02292     }
02293     break;
02294 
02295   case NT_CTYPE:
02296     *max = ONIGENC_MBC_MAXLEN_DIST(env->enc);
02297     break;
02298 
02299   case NT_CCLASS:
02300   case NT_CANY:
02301     *max = ONIGENC_MBC_MAXLEN_DIST(env->enc);
02302     break;
02303 
02304   case NT_BREF:
02305     {
02306       int i;
02307       int* backs;
02308       Node** nodes = SCANENV_MEM_NODES(env);
02309       BRefNode* br = NBREF(node);
02310       if (br->state & NST_RECURSION) {
02311         *max = ONIG_INFINITE_DISTANCE;
02312         break;
02313       }
02314       backs = BACKREFS_P(br);
02315       for (i = 0; i < br->back_num; i++) {
02316         if (backs[i] > env->num_mem)  return ONIGERR_INVALID_BACKREF;
02317         r = get_max_match_length(nodes[backs[i]], &tmax, env);
02318         if (r != 0) break;
02319         if (*max < tmax) *max = tmax;
02320       }
02321     }
02322     break;
02323 
02324 #ifdef USE_SUBEXP_CALL
02325   case NT_CALL:
02326     if (! IS_CALL_RECURSION(NCALL(node)))
02327       r = get_max_match_length(NCALL(node)->target, max, env);
02328     else
02329       *max = ONIG_INFINITE_DISTANCE;
02330     break;
02331 #endif
02332 
02333   case NT_QTFR:
02334     {
02335       QtfrNode* qn = NQTFR(node);
02336 
02337       if (qn->upper != 0) {
02338         r = get_max_match_length(qn->target, max, env);
02339         if (r == 0 && *max != 0) {
02340           if (! IS_REPEAT_INFINITE(qn->upper))
02341             *max = distance_multiply(*max, qn->upper);
02342           else
02343             *max = ONIG_INFINITE_DISTANCE;
02344         }
02345       }
02346     }
02347     break;
02348 
02349   case NT_ENCLOSE:
02350     {
02351       EncloseNode* en = NENCLOSE(node);
02352       switch (en->type) {
02353       case ENCLOSE_MEMORY:
02354 #ifdef USE_SUBEXP_CALL
02355         if (IS_ENCLOSE_MAX_FIXED(en))
02356           *max = en->max_len;
02357         else {
02358           r = get_max_match_length(en->target, max, env);
02359           if (r == 0) {
02360             en->max_len = *max;
02361             SET_ENCLOSE_STATUS(node, NST_MAX_FIXED);
02362           }
02363         }
02364         break;
02365 #endif
02366       case ENCLOSE_OPTION:
02367       case ENCLOSE_STOP_BACKTRACK:
02368       case ENCLOSE_CONDITION:
02369         r = get_max_match_length(en->target, max, env);
02370         break;
02371       }
02372     }
02373     break;
02374 
02375   case NT_ANCHOR:
02376   default:
02377     break;
02378   }
02379 
02380   return r;
02381 }
02382 
02383 #define GET_CHAR_LEN_VARLEN           -1
02384 #define GET_CHAR_LEN_TOP_ALT_VARLEN   -2
02385 
02386 /* fixed size pattern node only */
02387 static int
02388 get_char_length_tree1(Node* node, regex_t* reg, int* len, int level)
02389 {
02390   int tlen;
02391   int r = 0;
02392 
02393   level++;
02394   *len = 0;
02395   switch (NTYPE(node)) {
02396   case NT_LIST:
02397     do {
02398       r = get_char_length_tree1(NCAR(node), reg, &tlen, level);
02399       if (r == 0)
02400         *len = (int )distance_add(*len, tlen);
02401     } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
02402     break;
02403 
02404   case NT_ALT:
02405     {
02406       int tlen2;
02407       int varlen = 0;
02408 
02409       r = get_char_length_tree1(NCAR(node), reg, &tlen, level);
02410       while (r == 0 && IS_NOT_NULL(node = NCDR(node))) {
02411         r = get_char_length_tree1(NCAR(node), reg, &tlen2, level);
02412         if (r == 0) {
02413           if (tlen != tlen2)
02414             varlen = 1;
02415         }
02416       }
02417       if (r == 0) {
02418         if (varlen != 0) {
02419           if (level == 1)
02420             r = GET_CHAR_LEN_TOP_ALT_VARLEN;
02421           else
02422             r = GET_CHAR_LEN_VARLEN;
02423         }
02424         else
02425           *len = tlen;
02426       }
02427     }
02428     break;
02429 
02430   case NT_STR:
02431     {
02432       StrNode* sn = NSTR(node);
02433       UChar *s = sn->s;
02434       while (s < sn->end) {
02435         s += enclen(reg->enc, s, sn->end);
02436         (*len)++;
02437       }
02438     }
02439     break;
02440 
02441   case NT_QTFR:
02442     {
02443       QtfrNode* qn = NQTFR(node);
02444       if (qn->lower == qn->upper) {
02445         r = get_char_length_tree1(qn->target, reg, &tlen, level);
02446         if (r == 0)
02447           *len = (int )distance_multiply(tlen, qn->lower);
02448       }
02449       else
02450         r = GET_CHAR_LEN_VARLEN;
02451     }
02452     break;
02453 
02454 #ifdef USE_SUBEXP_CALL
02455   case NT_CALL:
02456     if (! IS_CALL_RECURSION(NCALL(node)))
02457       r = get_char_length_tree1(NCALL(node)->target, reg, len, level);
02458     else
02459       r = GET_CHAR_LEN_VARLEN;
02460     break;
02461 #endif
02462 
02463   case NT_CTYPE:
02464     *len = 1;
02465     break;
02466 
02467   case NT_CCLASS:
02468   case NT_CANY:
02469     *len = 1;
02470     break;
02471 
02472   case NT_ENCLOSE:
02473     {
02474       EncloseNode* en = NENCLOSE(node);
02475       switch (en->type) {
02476       case ENCLOSE_MEMORY:
02477 #ifdef USE_SUBEXP_CALL
02478         if (IS_ENCLOSE_CLEN_FIXED(en))
02479           *len = en->char_len;
02480         else {
02481           r = get_char_length_tree1(en->target, reg, len, level);
02482           if (r == 0) {
02483             en->char_len = *len;
02484             SET_ENCLOSE_STATUS(node, NST_CLEN_FIXED);
02485           }
02486         }
02487         break;
02488 #endif
02489       case ENCLOSE_OPTION:
02490       case ENCLOSE_STOP_BACKTRACK:
02491       case ENCLOSE_CONDITION:
02492         r = get_char_length_tree1(en->target, reg, len, level);
02493         break;
02494       default:
02495         break;
02496       }
02497     }
02498     break;
02499 
02500   case NT_ANCHOR:
02501     break;
02502 
02503   default:
02504     r = GET_CHAR_LEN_VARLEN;
02505     break;
02506   }
02507 
02508   return r;
02509 }
02510 
02511 static int
02512 get_char_length_tree(Node* node, regex_t* reg, int* len)
02513 {
02514   return get_char_length_tree1(node, reg, len, 0);
02515 }
02516 
02517 /* x is not included y ==>  1 : 0 */
02518 static int
02519 is_not_included(Node* x, Node* y, regex_t* reg)
02520 {
02521   int i;
02522   OnigDistance len;
02523   OnigCodePoint code;
02524   UChar *p;
02525   int ytype;
02526 
02527  retry:
02528   ytype = NTYPE(y);
02529   switch (NTYPE(x)) {
02530   case NT_CTYPE:
02531     {
02532       switch (ytype) {
02533       case NT_CTYPE:
02534         if (NCTYPE(y)->ctype == NCTYPE(x)->ctype &&
02535             NCTYPE(y)->not   != NCTYPE(x)->not &&
02536             NCTYPE(y)->ascii_range == NCTYPE(x)->ascii_range)
02537           return 1;
02538         else
02539           return 0;
02540         break;
02541 
02542       case NT_CCLASS:
02543       swap:
02544         {
02545           Node* tmp;
02546           tmp = x; x = y; y = tmp;
02547           goto retry;
02548         }
02549         break;
02550 
02551       case NT_STR:
02552         goto swap;
02553         break;
02554 
02555       default:
02556         break;
02557       }
02558     }
02559     break;
02560 
02561   case NT_CCLASS:
02562     {
02563       CClassNode* xc = NCCLASS(x);
02564       switch (ytype) {
02565       case NT_CTYPE:
02566         switch (NCTYPE(y)->ctype) {
02567         case ONIGENC_CTYPE_WORD:
02568           if (NCTYPE(y)->not == 0) {
02569             if (IS_NULL(xc->mbuf) && !IS_NCCLASS_NOT(xc)) {
02570               for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
02571                 if (BITSET_AT(xc->bs, i)) {
02572                   if (NCTYPE(y)->ascii_range) {
02573                     if (IS_CODE_SB_WORD(reg->enc, i)) return 0;
02574                   }
02575                   else {
02576                     if (ONIGENC_IS_CODE_WORD(reg->enc, i)) return 0;
02577                   }
02578                 }
02579               }
02580               return 1;
02581             }
02582             return 0;
02583           }
02584           else {
02585             for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
02586               int is_word;
02587               if (NCTYPE(y)->ascii_range)
02588                 is_word = IS_CODE_SB_WORD(reg->enc, i);
02589               else
02590                 is_word = ONIGENC_IS_CODE_WORD(reg->enc, i);
02591               if (! is_word) {
02592                 if (!IS_NCCLASS_NOT(xc)) {
02593                   if (BITSET_AT(xc->bs, i))
02594                     return 0;
02595                 }
02596                 else {
02597                   if (! BITSET_AT(xc->bs, i))
02598                     return 0;
02599                 }
02600               }
02601             }
02602             return 1;
02603           }
02604           break;
02605 
02606         default:
02607           break;
02608         }
02609         break;
02610 
02611       case NT_CCLASS:
02612         {
02613           int v;
02614           CClassNode* yc = NCCLASS(y);
02615 
02616           for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
02617             v = BITSET_AT(xc->bs, i);
02618             if ((v != 0 && !IS_NCCLASS_NOT(xc)) ||
02619                 (v == 0 && IS_NCCLASS_NOT(xc))) {
02620               v = BITSET_AT(yc->bs, i);
02621               if ((v != 0 && !IS_NCCLASS_NOT(yc)) ||
02622                   (v == 0 && IS_NCCLASS_NOT(yc)))
02623                 return 0;
02624             }
02625           }
02626           if ((IS_NULL(xc->mbuf) && !IS_NCCLASS_NOT(xc)) ||
02627               (IS_NULL(yc->mbuf) && !IS_NCCLASS_NOT(yc)))
02628             return 1;
02629           return 0;
02630         }
02631         break;
02632 
02633       case NT_STR:
02634         goto swap;
02635         break;
02636 
02637       default:
02638         break;
02639       }
02640     }
02641     break;
02642 
02643   case NT_STR:
02644     {
02645       StrNode* xs = NSTR(x);
02646       if (NSTRING_LEN(x) == 0)
02647         break;
02648 
02649       switch (ytype) {
02650       case NT_CTYPE:
02651         switch (NCTYPE(y)->ctype) {
02652         case ONIGENC_CTYPE_WORD:
02653           if (NCTYPE(y)->ascii_range) {
02654             if (ONIGENC_IS_MBC_ASCII_WORD(reg->enc, xs->s, xs->end))
02655               return NCTYPE(y)->not;
02656             else
02657               return !(NCTYPE(y)->not);
02658           }
02659           else {
02660             if (ONIGENC_IS_MBC_WORD(reg->enc, xs->s, xs->end))
02661               return NCTYPE(y)->not;
02662             else
02663               return !(NCTYPE(y)->not);
02664           }
02665           break;
02666         default:
02667           break;
02668         }
02669         break;
02670 
02671       case NT_CCLASS:
02672         {
02673           CClassNode* cc = NCCLASS(y);
02674 
02675           code = ONIGENC_MBC_TO_CODE(reg->enc, xs->s,
02676                                      xs->s + ONIGENC_MBC_MAXLEN(reg->enc));
02677           return (onig_is_code_in_cc(reg->enc, code, cc) != 0 ? 0 : 1);
02678         }
02679         break;
02680 
02681       case NT_STR:
02682         {
02683           UChar *q;
02684           StrNode* ys = NSTR(y);
02685           len = NSTRING_LEN(x);
02686           if (len > NSTRING_LEN(y)) len = NSTRING_LEN(y);
02687           if (NSTRING_IS_AMBIG(x) || NSTRING_IS_AMBIG(y)) {
02688             /* tiny version */
02689             return 0;
02690           }
02691           else {
02692             for (i = 0, p = ys->s, q = xs->s; (OnigDistance )i < len; i++, p++, q++) {
02693               if (*p != *q) return 1;
02694             }
02695           }
02696         }
02697         break;
02698 
02699       default:
02700         break;
02701       }
02702     }
02703     break;
02704 
02705   default:
02706     break;
02707   }
02708 
02709   return 0;
02710 }
02711 
02712 static Node*
02713 get_head_value_node(Node* node, int exact, regex_t* reg)
02714 {
02715   Node* n = NULL_NODE;
02716 
02717   switch (NTYPE(node)) {
02718   case NT_BREF:
02719   case NT_ALT:
02720   case NT_CANY:
02721 #ifdef USE_SUBEXP_CALL
02722   case NT_CALL:
02723 #endif
02724     break;
02725 
02726   case NT_CTYPE:
02727   case NT_CCLASS:
02728     if (exact == 0) {
02729       n = node;
02730     }
02731     break;
02732 
02733   case NT_LIST:
02734     n = get_head_value_node(NCAR(node), exact, reg);
02735     break;
02736 
02737   case NT_STR:
02738     {
02739       StrNode* sn = NSTR(node);
02740 
02741       if (sn->end <= sn->s)
02742         break;
02743 
02744       if (exact != 0 &&
02745           !NSTRING_IS_RAW(node) && IS_IGNORECASE(reg->options)) {
02746       }
02747       else {
02748         n = node;
02749       }
02750     }
02751     break;
02752 
02753   case NT_QTFR:
02754     {
02755       QtfrNode* qn = NQTFR(node);
02756       if (qn->lower > 0) {
02757         if (IS_NOT_NULL(qn->head_exact))
02758           n = qn->head_exact;
02759         else
02760           n = get_head_value_node(qn->target, exact, reg);
02761       }
02762     }
02763     break;
02764 
02765   case NT_ENCLOSE:
02766     {
02767       EncloseNode* en = NENCLOSE(node);
02768       switch (en->type) {
02769       case ENCLOSE_OPTION:
02770         {
02771           OnigOptionType options = reg->options;
02772 
02773           reg->options = NENCLOSE(node)->option;
02774           n = get_head_value_node(NENCLOSE(node)->target, exact, reg);
02775           reg->options = options;
02776         }
02777         break;
02778 
02779       case ENCLOSE_MEMORY:
02780       case ENCLOSE_STOP_BACKTRACK:
02781       case ENCLOSE_CONDITION:
02782         n = get_head_value_node(en->target, exact, reg);
02783         break;
02784       }
02785     }
02786     break;
02787 
02788   case NT_ANCHOR:
02789     if (NANCHOR(node)->type == ANCHOR_PREC_READ)
02790       n = get_head_value_node(NANCHOR(node)->target, exact, reg);
02791     break;
02792 
02793   default:
02794     break;
02795   }
02796 
02797   return n;
02798 }
02799 
02800 static int
02801 check_type_tree(Node* node, int type_mask, int enclose_mask, int anchor_mask)
02802 {
02803   int type, r = 0;
02804 
02805   type = NTYPE(node);
02806   if ((NTYPE2BIT(type) & type_mask) == 0)
02807     return 1;
02808 
02809   switch (type) {
02810   case NT_LIST:
02811   case NT_ALT:
02812     do {
02813       r = check_type_tree(NCAR(node), type_mask, enclose_mask,
02814                           anchor_mask);
02815     } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
02816     break;
02817 
02818   case NT_QTFR:
02819     r = check_type_tree(NQTFR(node)->target, type_mask, enclose_mask,
02820                         anchor_mask);
02821     break;
02822 
02823   case NT_ENCLOSE:
02824     {
02825       EncloseNode* en = NENCLOSE(node);
02826       if ((en->type & enclose_mask) == 0)
02827         return 1;
02828 
02829       r = check_type_tree(en->target, type_mask, enclose_mask, anchor_mask);
02830     }
02831     break;
02832 
02833   case NT_ANCHOR:
02834     type = NANCHOR(node)->type;
02835     if ((type & anchor_mask) == 0)
02836       return 1;
02837 
02838     if (NANCHOR(node)->target)
02839       r = check_type_tree(NANCHOR(node)->target,
02840                           type_mask, enclose_mask, anchor_mask);
02841     break;
02842 
02843   default:
02844     break;
02845   }
02846   return r;
02847 }
02848 
02849 #ifdef USE_SUBEXP_CALL
02850 
02851 #define RECURSION_EXIST       1
02852 #define RECURSION_INFINITE    2
02853 
02854 static int
02855 subexp_inf_recursive_check(Node* node, ScanEnv* env, int head)
02856 {
02857   int type;
02858   int r = 0;
02859 
02860   type = NTYPE(node);
02861   switch (type) {
02862   case NT_LIST:
02863     {
02864       Node *x;
02865       OnigDistance min;
02866       int ret;
02867 
02868       x = node;
02869       do {
02870         ret = subexp_inf_recursive_check(NCAR(x), env, head);
02871         if (ret < 0 || ret == RECURSION_INFINITE) return ret;
02872         r |= ret;
02873         if (head) {
02874           ret = get_min_match_length(NCAR(x), &min, env);
02875           if (ret != 0) return ret;
02876           if (min != 0) head = 0;
02877         }
02878       } while (IS_NOT_NULL(x = NCDR(x)));
02879     }
02880     break;
02881 
02882   case NT_ALT:
02883     {
02884       int ret;
02885       r = RECURSION_EXIST;
02886       do {
02887         ret = subexp_inf_recursive_check(NCAR(node), env, head);
02888         if (ret < 0 || ret == RECURSION_INFINITE) return ret;
02889         r &= ret;
02890       } while (IS_NOT_NULL(node = NCDR(node)));
02891     }
02892     break;
02893 
02894   case NT_QTFR:
02895     r = subexp_inf_recursive_check(NQTFR(node)->target, env, head);
02896     if (r == RECURSION_EXIST) {
02897       if (NQTFR(node)->lower == 0) r = 0;
02898     }
02899     break;
02900 
02901   case NT_ANCHOR:
02902     {
02903       AnchorNode* an = NANCHOR(node);
02904       switch (an->type) {
02905       case ANCHOR_PREC_READ:
02906       case ANCHOR_PREC_READ_NOT:
02907       case ANCHOR_LOOK_BEHIND:
02908       case ANCHOR_LOOK_BEHIND_NOT:
02909         r = subexp_inf_recursive_check(an->target, env, head);
02910         break;
02911       }
02912     }
02913     break;
02914 
02915   case NT_CALL:
02916     r = subexp_inf_recursive_check(NCALL(node)->target, env, head);
02917     break;
02918 
02919   case NT_ENCLOSE:
02920     if (IS_ENCLOSE_MARK2(NENCLOSE(node)))
02921       return 0;
02922     else if (IS_ENCLOSE_MARK1(NENCLOSE(node)))
02923       return (head == 0 ? RECURSION_EXIST : RECURSION_INFINITE);
02924     else {
02925       SET_ENCLOSE_STATUS(node, NST_MARK2);
02926       r = subexp_inf_recursive_check(NENCLOSE(node)->target, env, head);
02927       CLEAR_ENCLOSE_STATUS(node, NST_MARK2);
02928     }
02929     break;
02930 
02931   default:
02932     break;
02933   }
02934 
02935   return r;
02936 }
02937 
02938 static int
02939 subexp_inf_recursive_check_trav(Node* node, ScanEnv* env)
02940 {
02941   int type;
02942   int r = 0;
02943 
02944   type = NTYPE(node);
02945   switch (type) {
02946   case NT_LIST:
02947   case NT_ALT:
02948     do {
02949       r = subexp_inf_recursive_check_trav(NCAR(node), env);
02950     } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
02951     break;
02952 
02953   case NT_QTFR:
02954     r = subexp_inf_recursive_check_trav(NQTFR(node)->target, env);
02955     break;
02956 
02957   case NT_ANCHOR:
02958     {
02959       AnchorNode* an = NANCHOR(node);
02960       switch (an->type) {
02961       case ANCHOR_PREC_READ:
02962       case ANCHOR_PREC_READ_NOT:
02963       case ANCHOR_LOOK_BEHIND:
02964       case ANCHOR_LOOK_BEHIND_NOT:
02965         r = subexp_inf_recursive_check_trav(an->target, env);
02966         break;
02967       }
02968     }
02969     break;
02970 
02971   case NT_ENCLOSE:
02972     {
02973       EncloseNode* en = NENCLOSE(node);
02974 
02975       if (IS_ENCLOSE_RECURSION(en)) {
02976         SET_ENCLOSE_STATUS(node, NST_MARK1);
02977         r = subexp_inf_recursive_check(en->target, env, 1);
02978         if (r > 0) return ONIGERR_NEVER_ENDING_RECURSION;
02979         CLEAR_ENCLOSE_STATUS(node, NST_MARK1);
02980       }
02981       r = subexp_inf_recursive_check_trav(en->target, env);
02982     }
02983 
02984     break;
02985 
02986   default:
02987     break;
02988   }
02989 
02990   return r;
02991 }
02992 
02993 static int
02994 subexp_recursive_check(Node* node)
02995 {
02996   int r = 0;
02997 
02998   switch (NTYPE(node)) {
02999   case NT_LIST:
03000   case NT_ALT:
03001     do {
03002       r |= subexp_recursive_check(NCAR(node));
03003     } while (IS_NOT_NULL(node = NCDR(node)));
03004     break;
03005 
03006   case NT_QTFR:
03007     r = subexp_recursive_check(NQTFR(node)->target);
03008     break;
03009 
03010   case NT_ANCHOR:
03011     {
03012       AnchorNode* an = NANCHOR(node);
03013       switch (an->type) {
03014       case ANCHOR_PREC_READ:
03015       case ANCHOR_PREC_READ_NOT:
03016       case ANCHOR_LOOK_BEHIND:
03017       case ANCHOR_LOOK_BEHIND_NOT:
03018         r = subexp_recursive_check(an->target);
03019         break;
03020       }
03021     }
03022     break;
03023 
03024   case NT_CALL:
03025     r = subexp_recursive_check(NCALL(node)->target);
03026     if (r != 0) SET_CALL_RECURSION(node);
03027     break;
03028 
03029   case NT_ENCLOSE:
03030     if (IS_ENCLOSE_MARK2(NENCLOSE(node)))
03031       return 0;
03032     else if (IS_ENCLOSE_MARK1(NENCLOSE(node)))
03033       return 1; /* recursion */
03034     else {
03035       SET_ENCLOSE_STATUS(node, NST_MARK2);
03036       r = subexp_recursive_check(NENCLOSE(node)->target);
03037       CLEAR_ENCLOSE_STATUS(node, NST_MARK2);
03038     }
03039     break;
03040 
03041   default:
03042     break;
03043   }
03044 
03045   return r;
03046 }
03047 
03048 
03049 static int
03050 subexp_recursive_check_trav(Node* node, ScanEnv* env)
03051 {
03052 #define FOUND_CALLED_NODE    1
03053 
03054   int type;
03055   int r = 0;
03056 
03057   type = NTYPE(node);
03058   switch (type) {
03059   case NT_LIST:
03060   case NT_ALT:
03061     {
03062       int ret;
03063       do {
03064         ret = subexp_recursive_check_trav(NCAR(node), env);
03065         if (ret == FOUND_CALLED_NODE) r = FOUND_CALLED_NODE;
03066         else if (ret < 0) return ret;
03067       } while (IS_NOT_NULL(node = NCDR(node)));
03068     }
03069     break;
03070 
03071   case NT_QTFR:
03072     r = subexp_recursive_check_trav(NQTFR(node)->target, env);
03073     if (NQTFR(node)->upper == 0) {
03074       if (r == FOUND_CALLED_NODE)
03075         NQTFR(node)->is_refered = 1;
03076     }
03077     break;
03078 
03079   case NT_ANCHOR:
03080     {
03081       AnchorNode* an = NANCHOR(node);
03082       switch (an->type) {
03083       case ANCHOR_PREC_READ:
03084       case ANCHOR_PREC_READ_NOT:
03085       case ANCHOR_LOOK_BEHIND:
03086       case ANCHOR_LOOK_BEHIND_NOT:
03087         r = subexp_recursive_check_trav(an->target, env);
03088         break;
03089       }
03090     }
03091     break;
03092 
03093   case NT_ENCLOSE:
03094     {
03095       EncloseNode* en = NENCLOSE(node);
03096 
03097       if (! IS_ENCLOSE_RECURSION(en)) {
03098         if (IS_ENCLOSE_CALLED(en)) {
03099           SET_ENCLOSE_STATUS(node, NST_MARK1);
03100           r = subexp_recursive_check(en->target);
03101           if (r != 0) SET_ENCLOSE_STATUS(node, NST_RECURSION);
03102           CLEAR_ENCLOSE_STATUS(node, NST_MARK1);
03103         }
03104       }
03105       r = subexp_recursive_check_trav(en->target, env);
03106       if (IS_ENCLOSE_CALLED(en))
03107         r |= FOUND_CALLED_NODE;
03108     }
03109     break;
03110 
03111   default:
03112     break;
03113   }
03114 
03115   return r;
03116 }
03117 
03118 static int
03119 setup_subexp_call(Node* node, ScanEnv* env)
03120 {
03121   int type;
03122   int r = 0;
03123 
03124   type = NTYPE(node);
03125   switch (type) {
03126   case NT_LIST:
03127     do {
03128       r = setup_subexp_call(NCAR(node), env);
03129     } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
03130     break;
03131 
03132   case NT_ALT:
03133     do {
03134       r = setup_subexp_call(NCAR(node), env);
03135     } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
03136     break;
03137 
03138   case NT_QTFR:
03139     r = setup_subexp_call(NQTFR(node)->target, env);
03140     break;
03141   case NT_ENCLOSE:
03142     r = setup_subexp_call(NENCLOSE(node)->target, env);
03143     break;
03144 
03145   case NT_CALL:
03146     {
03147       CallNode* cn = NCALL(node);
03148       Node** nodes = SCANENV_MEM_NODES(env);
03149 
03150       if (cn->group_num != 0) {
03151         int gnum = cn->group_num;
03152 
03153 #ifdef USE_NAMED_GROUP
03154         if (env->num_named > 0 &&
03155             IS_SYNTAX_BV(env->syntax, ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP) &&
03156             !ONIG_IS_OPTION_ON(env->option, ONIG_OPTION_CAPTURE_GROUP)) {
03157           return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;
03158         }
03159 #endif
03160         if (gnum > env->num_mem) {
03161           onig_scan_env_set_error_string(env,
03162                  ONIGERR_UNDEFINED_GROUP_REFERENCE, cn->name, cn->name_end);
03163           return ONIGERR_UNDEFINED_GROUP_REFERENCE;
03164         }
03165 
03166 #ifdef USE_NAMED_GROUP
03167       set_call_attr:
03168 #endif
03169         cn->target = nodes[cn->group_num];
03170         if (IS_NULL(cn->target)) {
03171           onig_scan_env_set_error_string(env,
03172                  ONIGERR_UNDEFINED_NAME_REFERENCE, cn->name, cn->name_end);
03173           return ONIGERR_UNDEFINED_NAME_REFERENCE;
03174         }
03175         SET_ENCLOSE_STATUS(cn->target, NST_CALLED);
03176         BIT_STATUS_ON_AT(env->bt_mem_start, cn->group_num);
03177         cn->unset_addr_list = env->unset_addr_list;
03178       }
03179 #ifdef USE_NAMED_GROUP
03180 #ifdef USE_PERL_SUBEXP_CALL
03181       else if (cn->name == cn->name_end) {
03182         goto set_call_attr;
03183       }
03184 #endif
03185       else {
03186         int *refs;
03187 
03188         int n = onig_name_to_group_numbers(env->reg, cn->name, cn->name_end,
03189                                            &refs);
03190         if (n <= 0) {
03191           onig_scan_env_set_error_string(env,
03192                  ONIGERR_UNDEFINED_NAME_REFERENCE, cn->name, cn->name_end);
03193           return ONIGERR_UNDEFINED_NAME_REFERENCE;
03194         }
03195         else if (n > 1 &&
03196             ! IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME_CALL)) {
03197           onig_scan_env_set_error_string(env,
03198             ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL, cn->name, cn->name_end);
03199           return ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL;
03200         }
03201         else {
03202           cn->group_num = refs[0];
03203           goto set_call_attr;
03204         }
03205       }
03206 #endif
03207     }
03208     break;
03209 
03210   case NT_ANCHOR:
03211     {
03212       AnchorNode* an = NANCHOR(node);
03213 
03214       switch (an->type) {
03215       case ANCHOR_PREC_READ:
03216       case ANCHOR_PREC_READ_NOT:
03217       case ANCHOR_LOOK_BEHIND:
03218       case ANCHOR_LOOK_BEHIND_NOT:
03219         r = setup_subexp_call(an->target, env);
03220         break;
03221       }
03222     }
03223     break;
03224 
03225   default:
03226     break;
03227   }
03228 
03229   return r;
03230 }
03231 #endif
03232 
03233 /* divide different length alternatives in look-behind.
03234   (?<=A|B) ==> (?<=A)|(?<=B)
03235   (?<!A|B) ==> (?<!A)(?<!B)
03236 */
03237 static int
03238 divide_look_behind_alternatives(Node* node)
03239 {
03240   Node *head, *np, *insert_node;
03241   AnchorNode* an = NANCHOR(node);
03242   int anc_type = an->type;
03243 
03244   head = an->target;
03245   np = NCAR(head);
03246   swap_node(node, head);
03247   NCAR(node) = head;
03248   NANCHOR(head)->target = np;
03249 
03250   np = node;
03251   while ((np = NCDR(np)) != NULL_NODE) {
03252     insert_node = onig_node_new_anchor(anc_type);
03253     CHECK_NULL_RETURN_MEMERR(insert_node);
03254     NANCHOR(insert_node)->target = NCAR(np);
03255     NCAR(np) = insert_node;
03256   }
03257 
03258   if (anc_type == ANCHOR_LOOK_BEHIND_NOT) {
03259     np = node;
03260     do {
03261       SET_NTYPE(np, NT_LIST);  /* alt -> list */
03262     } while ((np = NCDR(np)) != NULL_NODE);
03263   }
03264   return 0;
03265 }
03266 
03267 static int
03268 setup_look_behind(Node* node, regex_t* reg, ScanEnv* env)
03269 {
03270   int r, len;
03271   AnchorNode* an = NANCHOR(node);
03272 
03273   r = get_char_length_tree(an->target, reg, &len);
03274   if (r == 0)
03275     an->char_len = len;
03276   else if (r == GET_CHAR_LEN_VARLEN)
03277     r = ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
03278   else if (r == GET_CHAR_LEN_TOP_ALT_VARLEN) {
03279     if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_DIFFERENT_LEN_ALT_LOOK_BEHIND))
03280       r = divide_look_behind_alternatives(node);
03281     else
03282       r = ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
03283   }
03284 
03285   return r;
03286 }
03287 
03288 static int
03289 next_setup(Node* node, Node* next_node, int in_root, regex_t* reg)
03290 {
03291   int type;
03292 
03293  retry:
03294   type = NTYPE(node);
03295   if (type == NT_QTFR) {
03296     QtfrNode* qn = NQTFR(node);
03297     if (qn->greedy && IS_REPEAT_INFINITE(qn->upper)) {
03298 #ifdef USE_QTFR_PEEK_NEXT
03299       Node* n = get_head_value_node(next_node, 1, reg);
03300       /* '\0': for UTF-16BE etc... */
03301       if (IS_NOT_NULL(n) && NSTR(n)->s[0] != '\0') {
03302         qn->next_head_exact = n;
03303       }
03304 #endif
03305       /* automatic possessivation a*b ==> (?>a*)b */
03306       if (qn->lower <= 1) {
03307         int ttype = NTYPE(qn->target);
03308         if (IS_NODE_TYPE_SIMPLE(ttype)) {
03309           Node *x, *y;
03310           x = get_head_value_node(qn->target, 0, reg);
03311           if (IS_NOT_NULL(x)) {
03312             y = get_head_value_node(next_node,  0, reg);
03313             if (IS_NOT_NULL(y) && is_not_included(x, y, reg)) {
03314               Node* en = onig_node_new_enclose(ENCLOSE_STOP_BACKTRACK);
03315               CHECK_NULL_RETURN_MEMERR(en);
03316               SET_ENCLOSE_STATUS(en, NST_STOP_BT_SIMPLE_REPEAT);
03317               swap_node(node, en);
03318               NENCLOSE(node)->target = en;
03319             }
03320           }
03321         }
03322       }
03323 
03324 #ifndef ONIG_DONT_OPTIMIZE
03325       if (NTYPE(node) == NT_QTFR && /* the type may be changed by above block */
03326           in_root && /* qn->lower == 0 && */
03327           NTYPE(qn->target) == NT_CANY &&
03328           ! IS_MULTILINE(reg->options)) {
03329         /* implicit anchor: /.*a/ ==> /(?:^|\G).*a/ */
03330         Node *np;
03331         np = onig_node_new_list(NULL_NODE, NULL_NODE);
03332         CHECK_NULL_RETURN_MEMERR(np);
03333         swap_node(node, np);
03334         NCDR(node) = onig_node_new_list(np, NULL_NODE);
03335         if (IS_NULL(NCDR(node))) {
03336           onig_node_free(np);
03337           return ONIGERR_MEMORY;
03338         }
03339         np = onig_node_new_anchor(ANCHOR_ANYCHAR_STAR);   /* (?:^|\G) */
03340         CHECK_NULL_RETURN_MEMERR(np);
03341         NCAR(node) = np;
03342       }
03343 #endif
03344     }
03345   }
03346   else if (type == NT_ENCLOSE) {
03347     EncloseNode* en = NENCLOSE(node);
03348     in_root = 0;
03349     if (en->type == ENCLOSE_MEMORY) {
03350       node = en->target;
03351       goto retry;
03352     }
03353   }
03354   return 0;
03355 }
03356 
03357 
03358 static int
03359 update_string_node_case_fold(regex_t* reg, Node *node)
03360 {
03361   UChar *p, *end, buf[ONIGENC_MBC_CASE_FOLD_MAXLEN];
03362   UChar *sbuf, *ebuf, *sp;
03363   int r, i, len;
03364   OnigDistance sbuf_size;
03365   StrNode* sn = NSTR(node);
03366 
03367   end = sn->end;
03368   sbuf_size = (end - sn->s) * 2;
03369   sbuf = (UChar* )xmalloc(sbuf_size);
03370   CHECK_NULL_RETURN_MEMERR(sbuf);
03371   ebuf = sbuf + sbuf_size;
03372 
03373   sp = sbuf;
03374   p = sn->s;
03375   while (p < end) {
03376     len = ONIGENC_MBC_CASE_FOLD(reg->enc, reg->case_fold_flag, &p, end, buf);
03377     for (i = 0; i < len; i++) {
03378       if (sp >= ebuf) {
03379         UChar* p = (UChar* )xrealloc(sbuf, sbuf_size * 2);
03380         if (IS_NULL(p)) {
03381           xfree(sbuf);
03382           return ONIGERR_MEMORY;
03383         }
03384         sbuf = p;
03385         sp = sbuf + sbuf_size;
03386         sbuf_size *= 2;
03387         ebuf = sbuf + sbuf_size;
03388       }
03389 
03390       *sp++ = buf[i];
03391     }
03392   }
03393 
03394   r = onig_node_str_set(node, sbuf, sp);
03395   if (r != 0) {
03396     xfree(sbuf);
03397     return r;
03398   }
03399 
03400   xfree(sbuf);
03401   return 0;
03402 }
03403 
03404 static int
03405 expand_case_fold_make_rem_string(Node** rnode, UChar *s, UChar *end,
03406                                  regex_t* reg)
03407 {
03408   int r;
03409   Node *node;
03410 
03411   node = onig_node_new_str(s, end);
03412   if (IS_NULL(node)) return ONIGERR_MEMORY;
03413 
03414   r = update_string_node_case_fold(reg, node);
03415   if (r != 0) {
03416     onig_node_free(node);
03417     return r;
03418   }
03419 
03420   NSTRING_SET_AMBIG(node);
03421   NSTRING_SET_DONT_GET_OPT_INFO(node);
03422   *rnode = node;
03423   return 0;
03424 }
03425 
03426 static int
03427 expand_case_fold_string_alt(int item_num, OnigCaseFoldCodeItem items[],
03428                             UChar *p, int slen, UChar *end,
03429                             regex_t* reg, Node **rnode)
03430 {
03431   int r, i, j, len, varlen, varclen;
03432   Node *anode, *var_anode, *snode, *xnode, *an;
03433   UChar buf[ONIGENC_CODE_TO_MBC_MAXLEN];
03434 
03435   *rnode = var_anode = NULL_NODE;
03436 
03437   varlen = 0;
03438   varclen = 0;
03439   for (i = 0; i < item_num; i++) {
03440     if (items[i].byte_len != slen) {
03441       varlen = 1;
03442       break;
03443     }
03444     if (items[i].code_len != 1) {
03445       varclen = 1;
03446     }
03447   }
03448 
03449   if (varlen != 0) {
03450     *rnode = var_anode = onig_node_new_alt(NULL_NODE, NULL_NODE);
03451     if (IS_NULL(var_anode)) return ONIGERR_MEMORY;
03452 
03453     xnode = onig_node_new_list(NULL, NULL);
03454     if (IS_NULL(xnode)) goto mem_err;
03455     NCAR(var_anode) = xnode;
03456 
03457     anode = onig_node_new_alt(NULL_NODE, NULL_NODE);
03458     if (IS_NULL(anode)) goto mem_err;
03459     NCAR(xnode) = anode;
03460   }
03461   else {
03462     *rnode = anode = onig_node_new_alt(NULL_NODE, NULL_NODE);
03463     if (IS_NULL(anode)) return ONIGERR_MEMORY;
03464   }
03465 
03466   snode = onig_node_new_str(p, p + slen);
03467   if (IS_NULL(snode)) goto mem_err;
03468 
03469   NCAR(anode) = snode;
03470 
03471   for (i = 0; i < item_num; i++) {
03472     snode = onig_node_new_str(NULL, NULL);
03473     if (IS_NULL(snode)) goto mem_err;
03474 
03475     for (j = 0; j < items[i].code_len; j++) {
03476       len = ONIGENC_CODE_TO_MBC(reg->enc, items[i].code[j], buf);
03477       if (len < 0) {
03478         r = len;
03479         goto mem_err2;
03480       }
03481 
03482       r = onig_node_str_cat(snode, buf, buf + len);
03483       if (r != 0) goto mem_err2;
03484     }
03485 
03486     an = onig_node_new_alt(NULL_NODE, NULL_NODE);
03487     if (IS_NULL(an)) {
03488       goto mem_err2;
03489     }
03490 
03491     if (items[i].byte_len != slen) {
03492       Node *rem;
03493       UChar *q = p + items[i].byte_len;
03494 
03495       if (q < end) {
03496         r = expand_case_fold_make_rem_string(&rem, q, end, reg);
03497         if (r != 0) {
03498           onig_node_free(an);
03499           goto mem_err2;
03500         }
03501 
03502         xnode = onig_node_list_add(NULL_NODE, snode);
03503         if (IS_NULL(xnode)) {
03504           onig_node_free(an);
03505           onig_node_free(rem);
03506           goto mem_err2;
03507         }
03508         if (IS_NULL(onig_node_list_add(xnode, rem))) {
03509           onig_node_free(an);
03510           onig_node_free(xnode);
03511           onig_node_free(rem);
03512           goto mem_err;
03513         }
03514 
03515         NCAR(an) = xnode;
03516       }
03517       else {
03518         NCAR(an) = snode;
03519       }
03520 
03521       NCDR(var_anode) = an;
03522       var_anode = an;
03523     }
03524     else {
03525       NCAR(an)     = snode;
03526       NCDR(anode) = an;
03527       anode = an;
03528     }
03529   }
03530 
03531   if (varclen && !varlen)
03532     return 2;
03533   return varlen;
03534 
03535  mem_err2:
03536   onig_node_free(snode);
03537 
03538  mem_err:
03539   onig_node_free(*rnode);
03540 
03541   return ONIGERR_MEMORY;
03542 }
03543 
03544 static int
03545 expand_case_fold_string(Node* node, regex_t* reg)
03546 {
03547 #define THRESHOLD_CASE_FOLD_ALT_FOR_EXPANSION  8
03548 
03549   int r, n, len, alt_num;
03550   int varlen = 0;
03551   UChar *start, *end, *p;
03552   Node *top_root, *root, *snode, *prev_node;
03553   OnigCaseFoldCodeItem items[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM];
03554   StrNode* sn = NSTR(node);
03555 
03556   if (NSTRING_IS_AMBIG(node)) return 0;
03557 
03558   start = sn->s;
03559   end   = sn->end;
03560   if (start >= end) return 0;
03561 
03562   r = 0;
03563   top_root = root = prev_node = snode = NULL_NODE;
03564   alt_num = 1;
03565   p = start;
03566   while (p < end) {
03567     n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(reg->enc, reg->case_fold_flag,
03568                                            p, end, items);
03569     if (n < 0) {
03570       r = n;
03571       goto err;
03572     }
03573 
03574     len = enclen(reg->enc, p, end);
03575 
03576     if (n == 0) {
03577       if (IS_NULL(snode)) {
03578         if (IS_NULL(root) && IS_NOT_NULL(prev_node)) {
03579           top_root = root = onig_node_list_add(NULL_NODE, prev_node);
03580           if (IS_NULL(root)) {
03581             onig_node_free(prev_node);
03582             goto mem_err;
03583           }
03584         }
03585 
03586         prev_node = snode = onig_node_new_str(NULL, NULL);
03587         if (IS_NULL(snode)) goto mem_err;
03588         if (IS_NOT_NULL(root)) {
03589           if (IS_NULL(onig_node_list_add(root, snode))) {
03590             onig_node_free(snode);
03591             goto mem_err;
03592           }
03593         }
03594       }
03595 
03596       r = onig_node_str_cat(snode, p, p + len);
03597       if (r != 0) goto err;
03598     }
03599     else {
03600       alt_num *= (n + 1);
03601       if (alt_num > THRESHOLD_CASE_FOLD_ALT_FOR_EXPANSION) break;
03602 
03603       if (IS_NULL(root) && IS_NOT_NULL(prev_node)) {
03604         top_root = root = onig_node_list_add(NULL_NODE, prev_node);
03605         if (IS_NULL(root)) {
03606           onig_node_free(prev_node);
03607           goto mem_err;
03608         }
03609       }
03610 
03611       r = expand_case_fold_string_alt(n, items, p, len, end, reg, &prev_node);
03612       if (r < 0) goto mem_err;
03613       if (r > 0) varlen = 1;
03614       if (r == 1) {
03615         if (IS_NULL(root)) {
03616           top_root = prev_node;
03617         }
03618         else {
03619           if (IS_NULL(onig_node_list_add(root, prev_node))) {
03620             onig_node_free(prev_node);
03621             goto mem_err;
03622           }
03623         }
03624 
03625         root = NCAR(prev_node);
03626       }
03627       else { /* r == 0 || r == 2 */
03628         if (IS_NOT_NULL(root)) {
03629           if (IS_NULL(onig_node_list_add(root, prev_node))) {
03630             onig_node_free(prev_node);
03631             goto mem_err;
03632           }
03633         }
03634       }
03635 
03636       snode = NULL_NODE;
03637     }
03638 
03639     p += len;
03640   }
03641 
03642   if (p < end) {
03643     Node *srem;
03644 
03645     r = expand_case_fold_make_rem_string(&srem, p, end, reg);
03646     if (r != 0) goto mem_err;
03647 
03648     if (IS_NOT_NULL(prev_node) && IS_NULL(root)) {
03649       top_root = root = onig_node_list_add(NULL_NODE, prev_node);
03650       if (IS_NULL(root)) {
03651         onig_node_free(srem);
03652         onig_node_free(prev_node);
03653         goto mem_err;
03654       }
03655     }
03656 
03657     if (IS_NULL(root)) {
03658       prev_node = srem;
03659     }
03660     else {
03661       if (IS_NULL(onig_node_list_add(root, srem))) {
03662         onig_node_free(srem);
03663         goto mem_err;
03664       }
03665     }
03666   }
03667 
03668   /* ending */
03669   top_root = (IS_NOT_NULL(top_root) ? top_root : prev_node);
03670   if (!varlen) {
03671     /* When all expanded strings are same length, case-insensitive
03672        BM search will be used. */
03673     r = update_string_node_case_fold(reg, node);
03674     if (r == 0) {
03675       NSTRING_SET_AMBIG(node);
03676     }
03677   }
03678   else {
03679     swap_node(node, top_root);
03680     r = 0;
03681   }
03682   onig_node_free(top_root);
03683   return r;
03684 
03685  mem_err:
03686   r = ONIGERR_MEMORY;
03687 
03688  err:
03689   onig_node_free(top_root);
03690   return r;
03691 }
03692 
03693 
03694 #ifdef USE_COMBINATION_EXPLOSION_CHECK
03695 
03696 #define CEC_THRES_NUM_BIG_REPEAT         512
03697 #define CEC_INFINITE_NUM          0x7fffffff
03698 
03699 #define CEC_IN_INFINITE_REPEAT    (1<<0)
03700 #define CEC_IN_FINITE_REPEAT      (1<<1)
03701 #define CEC_CONT_BIG_REPEAT       (1<<2)
03702 
03703 static int
03704 setup_comb_exp_check(Node* node, int state, ScanEnv* env)
03705 {
03706   int type;
03707   int r = state;
03708 
03709   type = NTYPE(node);
03710   switch (type) {
03711   case NT_LIST:
03712     {
03713       Node* prev = NULL_NODE;
03714       do {
03715         r = setup_comb_exp_check(NCAR(node), r, env);
03716         prev = NCAR(node);
03717       } while (r >= 0 && IS_NOT_NULL(node = NCDR(node)));
03718     }
03719     break;
03720 
03721   case NT_ALT:
03722     {
03723       int ret;
03724       do {
03725         ret = setup_comb_exp_check(NCAR(node), state, env);
03726         r |= ret;
03727       } while (ret >= 0 && IS_NOT_NULL(node = NCDR(node)));
03728     }
03729     break;
03730 
03731   case NT_QTFR:
03732     {
03733       int child_state = state;
03734       int add_state = 0;
03735       QtfrNode* qn = NQTFR(node);
03736       Node* target = qn->target;
03737       int var_num;
03738 
03739       if (! IS_REPEAT_INFINITE(qn->upper)) {
03740         if (qn->upper > 1) {
03741           /* {0,1}, {1,1} are allowed */
03742           child_state |= CEC_IN_FINITE_REPEAT;
03743 
03744           /* check (a*){n,m}, (a+){n,m} => (a*){n,n}, (a+){n,n} */
03745           if (env->backrefed_mem == 0) {
03746             if (NTYPE(qn->target) == NT_ENCLOSE) {
03747               EncloseNode* en = NENCLOSE(qn->target);
03748               if (en->type == ENCLOSE_MEMORY) {
03749                 if (NTYPE(en->target) == NT_QTFR) {
03750                   QtfrNode* q = NQTFR(en->target);
03751                   if (IS_REPEAT_INFINITE(q->upper)
03752                       && q->greedy == qn->greedy) {
03753                     qn->upper = (qn->lower == 0 ? 1 : qn->lower);
03754                     if (qn->upper == 1)
03755                       child_state = state;
03756                   }
03757                 }
03758               }
03759             }
03760           }
03761         }
03762       }
03763 
03764       if (state & CEC_IN_FINITE_REPEAT) {
03765         qn->comb_exp_check_num = -1;
03766       }
03767       else {
03768         if (IS_REPEAT_INFINITE(qn->upper)) {
03769           var_num = CEC_INFINITE_NUM;
03770           child_state |= CEC_IN_INFINITE_REPEAT;
03771         }
03772         else {
03773           var_num = qn->upper - qn->lower;
03774         }
03775 
03776         if (var_num >= CEC_THRES_NUM_BIG_REPEAT)
03777           add_state |= CEC_CONT_BIG_REPEAT;
03778 
03779         if (((state & CEC_IN_INFINITE_REPEAT) != 0 && var_num != 0) ||
03780             ((state & CEC_CONT_BIG_REPEAT) != 0 &&
03781              var_num >= CEC_THRES_NUM_BIG_REPEAT)) {
03782           if (qn->comb_exp_check_num == 0) {
03783             env->num_comb_exp_check++;
03784             qn->comb_exp_check_num = env->num_comb_exp_check;
03785             if (env->curr_max_regnum > env->comb_exp_max_regnum)
03786               env->comb_exp_max_regnum = env->curr_max_regnum;
03787           }
03788         }
03789       }
03790 
03791       r = setup_comb_exp_check(target, child_state, env);
03792       r |= add_state;
03793     }
03794     break;
03795 
03796   case NT_ENCLOSE:
03797     {
03798       EncloseNode* en = NENCLOSE(node);
03799 
03800       switch (en->type) {
03801       case ENCLOSE_MEMORY:
03802         {
03803           if (env->curr_max_regnum < en->regnum)
03804             env->curr_max_regnum = en->regnum;
03805 
03806           r = setup_comb_exp_check(en->target, state, env);
03807         }
03808         break;
03809 
03810       default:
03811         r = setup_comb_exp_check(en->target, state, env);
03812         break;
03813       }
03814     }
03815     break;
03816 
03817 #ifdef USE_SUBEXP_CALL
03818   case NT_CALL:
03819     if (IS_CALL_RECURSION(NCALL(node)))
03820       env->has_recursion = 1;
03821     else
03822       r = setup_comb_exp_check(NCALL(node)->target, state, env);
03823     break;
03824 #endif
03825 
03826   default:
03827     break;
03828   }
03829 
03830   return r;
03831 }
03832 #endif
03833 
03834 #define IN_ALT        (1<<0)
03835 #define IN_NOT        (1<<1)
03836 #define IN_REPEAT     (1<<2)
03837 #define IN_VAR_REPEAT (1<<3)
03838 #define IN_ROOT       (1<<4)
03839 
03840 /* setup_tree does the following work.
03841  1. check empty loop. (set qn->target_empty_info)
03842  2. expand ignore-case in char class.
03843  3. set memory status bit flags. (reg->mem_stats)
03844  4. set qn->head_exact for [push, exact] -> [push_or_jump_exact1, exact].
03845  5. find invalid patterns in look-behind.
03846  6. expand repeated string.
03847  */
03848 static int
03849 setup_tree(Node* node, regex_t* reg, int state, ScanEnv* env)
03850 {
03851   int type;
03852   int r = 0;
03853   int in_root = state & IN_ROOT;
03854 
03855   state &= ~IN_ROOT;
03856 restart:
03857   type = NTYPE(node);
03858   switch (type) {
03859   case NT_LIST:
03860     {
03861       Node* prev = NULL_NODE;
03862       int prev_in_root = 0;
03863       state |= in_root;
03864       do {
03865         r = setup_tree(NCAR(node), reg, state, env);
03866         if (IS_NOT_NULL(prev) && r == 0) {
03867           r = next_setup(prev, NCAR(node), prev_in_root, reg);
03868         }
03869         prev = NCAR(node);
03870         prev_in_root = state & IN_ROOT;
03871         state &= ~IN_ROOT;
03872       } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
03873     }
03874     break;
03875 
03876   case NT_ALT:
03877     do {
03878       r = setup_tree(NCAR(node), reg, (state | IN_ALT), env);
03879     } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
03880     break;
03881 
03882   case NT_CCLASS:
03883     break;
03884 
03885   case NT_STR:
03886     if (IS_IGNORECASE(reg->options) && !NSTRING_IS_RAW(node)) {
03887       r = expand_case_fold_string(node, reg);
03888     }
03889     break;
03890 
03891   case NT_CTYPE:
03892   case NT_CANY:
03893     break;
03894 
03895 #ifdef USE_SUBEXP_CALL
03896   case NT_CALL:
03897     break;
03898 #endif
03899 
03900   case NT_BREF:
03901     {
03902       int i;
03903       int* p;
03904       Node** nodes = SCANENV_MEM_NODES(env);
03905       BRefNode* br = NBREF(node);
03906       p = BACKREFS_P(br);
03907       for (i = 0; i < br->back_num; i++) {
03908         if (p[i] > env->num_mem)  return ONIGERR_INVALID_BACKREF;
03909         BIT_STATUS_ON_AT(env->backrefed_mem, p[i]);
03910         BIT_STATUS_ON_AT(env->bt_mem_start, p[i]);
03911 #ifdef USE_BACKREF_WITH_LEVEL
03912         if (IS_BACKREF_NEST_LEVEL(br)) {
03913           BIT_STATUS_ON_AT(env->bt_mem_end, p[i]);
03914         }
03915 #endif
03916         SET_ENCLOSE_STATUS(nodes[p[i]], NST_MEM_BACKREFED);
03917       }
03918     }
03919     break;
03920 
03921   case NT_QTFR:
03922     {
03923       OnigDistance d;
03924       QtfrNode* qn = NQTFR(node);
03925       Node* target = qn->target;
03926 
03927       if ((state & IN_REPEAT) != 0) {
03928         qn->state |= NST_IN_REPEAT;
03929       }
03930 
03931       if (IS_REPEAT_INFINITE(qn->upper) || qn->upper >= 1) {
03932         r = get_min_match_length(target, &d, env);
03933         if (r) break;
03934         if (d == 0) {
03935           qn->target_empty_info = NQ_TARGET_IS_EMPTY;
03936 #ifdef USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT
03937           r = quantifiers_memory_node_info(target);
03938           if (r < 0) break;
03939           if (r > 0) {
03940             qn->target_empty_info = r;
03941           }
03942 #endif
03943 #if 0
03944           r = get_max_match_length(target, &d, env);
03945           if (r == 0 && d == 0) {
03946             /*  ()* ==> ()?, ()+ ==> ()  */
03947             qn->upper = 1;
03948             if (qn->lower > 1) qn->lower = 1;
03949             if (NTYPE(target) == NT_STR) {
03950               qn->upper = qn->lower = 0;  /* /(?:)+/ ==> // */
03951             }
03952           }
03953 #endif
03954         }
03955       }
03956 
03957       state |= IN_REPEAT;
03958       if (qn->lower != qn->upper)
03959         state |= IN_VAR_REPEAT;
03960       r = setup_tree(target, reg, state, env);
03961       if (r) break;
03962 
03963       /* expand string */
03964 #define EXPAND_STRING_MAX_LENGTH  100
03965       if (NTYPE(target) == NT_STR) {
03966         if (qn->lower > 1) {
03967           int i, n = qn->lower;
03968           OnigDistance len = NSTRING_LEN(target);
03969           StrNode* sn = NSTR(target);
03970           Node* np;
03971 
03972           np = onig_node_new_str(sn->s, sn->end);
03973           if (IS_NULL(np)) return ONIGERR_MEMORY;
03974           NSTR(np)->flag = sn->flag;
03975 
03976           for (i = 1; i < n && (i+1) * len <= EXPAND_STRING_MAX_LENGTH; i++) {
03977             r = onig_node_str_cat(np, sn->s, sn->end);
03978             if (r) {
03979               onig_node_free(np);
03980               return r;
03981             }
03982           }
03983           if (i < qn->upper || IS_REPEAT_INFINITE(qn->upper)) {
03984             Node *np1, *np2;
03985 
03986             qn->lower -= i;
03987             if (! IS_REPEAT_INFINITE(qn->upper))
03988               qn->upper -= i;
03989 
03990             np1 = onig_node_new_list(np, NULL);
03991             if (IS_NULL(np1)) {
03992               onig_node_free(np);
03993               return ONIGERR_MEMORY;
03994             }
03995             swap_node(np1, node);
03996             np2 = onig_node_list_add(node, np1);
03997             if (IS_NULL(np2)) {
03998               onig_node_free(np1);
03999               return ONIGERR_MEMORY;
04000             }
04001           }
04002           else {
04003             swap_node(np, node);
04004             onig_node_free(np);
04005           }
04006           break; /* break case NT_QTFR: */
04007         }
04008       }
04009 
04010 #ifdef USE_OP_PUSH_OR_JUMP_EXACT
04011       if (qn->greedy && (qn->target_empty_info != 0)) {
04012         if (NTYPE(target) == NT_QTFR) {
04013           QtfrNode* tqn = NQTFR(target);
04014           if (IS_NOT_NULL(tqn->head_exact)) {
04015             qn->head_exact  = tqn->head_exact;
04016             tqn->head_exact = NULL;
04017           }
04018         }
04019         else {
04020           qn->head_exact = get_head_value_node(qn->target, 1, reg);
04021         }
04022       }
04023 #endif
04024     }
04025     break;
04026 
04027   case NT_ENCLOSE:
04028     {
04029       EncloseNode* en = NENCLOSE(node);
04030 
04031       switch (en->type) {
04032       case ENCLOSE_OPTION:
04033         {
04034           OnigOptionType options = reg->options;
04035           state |= in_root;
04036           reg->options = NENCLOSE(node)->option;
04037           r = setup_tree(NENCLOSE(node)->target, reg, state, env);
04038           reg->options = options;
04039         }
04040         break;
04041 
04042       case ENCLOSE_MEMORY:
04043         if ((state & (IN_ALT | IN_NOT | IN_VAR_REPEAT)) != 0) {
04044           BIT_STATUS_ON_AT(env->bt_mem_start, en->regnum);
04045           /* SET_ENCLOSE_STATUS(node, NST_MEM_IN_ALT_NOT); */
04046         }
04047         r = setup_tree(en->target, reg, state, env);
04048         break;
04049 
04050       case ENCLOSE_STOP_BACKTRACK:
04051         {
04052           Node* target = en->target;
04053           r = setup_tree(target, reg, state, env);
04054           if (NTYPE(target) == NT_QTFR) {
04055             QtfrNode* tqn = NQTFR(target);
04056             if (IS_REPEAT_INFINITE(tqn->upper) && tqn->lower <= 1 &&
04057                 tqn->greedy != 0) {  /* (?>a*), a*+ etc... */
04058               int qtype = NTYPE(tqn->target);
04059               if (IS_NODE_TYPE_SIMPLE(qtype))
04060                 SET_ENCLOSE_STATUS(node, NST_STOP_BT_SIMPLE_REPEAT);
04061             }
04062           }
04063         }
04064         break;
04065 
04066       case ENCLOSE_CONDITION:
04067 #ifdef USE_NAMED_GROUP
04068         if (! IS_ENCLOSE_NAME_REF(NENCLOSE(node)) &&
04069             env->num_named > 0 &&
04070             IS_SYNTAX_BV(env->syntax, ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP) &&
04071             !ONIG_IS_OPTION_ON(env->option, ONIG_OPTION_CAPTURE_GROUP)) {
04072           return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;
04073         }
04074 #endif
04075         r = setup_tree(NENCLOSE(node)->target, reg, state, env);
04076         break;
04077       }
04078     }
04079     break;
04080 
04081   case NT_ANCHOR:
04082     {
04083       AnchorNode* an = NANCHOR(node);
04084 
04085       switch (an->type) {
04086       case ANCHOR_PREC_READ:
04087         r = setup_tree(an->target, reg, state, env);
04088         break;
04089       case ANCHOR_PREC_READ_NOT:
04090         r = setup_tree(an->target, reg, (state | IN_NOT), env);
04091         break;
04092 
04093 /* allowed node types in look-behind */
04094 #define ALLOWED_TYPE_IN_LB  \
04095   ( BIT_NT_LIST | BIT_NT_ALT | BIT_NT_STR | BIT_NT_CCLASS | BIT_NT_CTYPE | \
04096     BIT_NT_CANY | BIT_NT_ANCHOR | BIT_NT_ENCLOSE | BIT_NT_QTFR | BIT_NT_CALL )
04097 
04098 #define ALLOWED_ENCLOSE_IN_LB       ( ENCLOSE_MEMORY | ENCLOSE_OPTION )
04099 #define ALLOWED_ENCLOSE_IN_LB_NOT   ENCLOSE_OPTION
04100 
04101 #define ALLOWED_ANCHOR_IN_LB \
04102 ( ANCHOR_LOOK_BEHIND | ANCHOR_LOOK_BEHIND_NOT | ANCHOR_BEGIN_LINE | \
04103   ANCHOR_END_LINE | ANCHOR_BEGIN_BUF | ANCHOR_BEGIN_POSITION | ANCHOR_KEEP | \
04104   ANCHOR_WORD_BOUND | ANCHOR_NOT_WORD_BOUND | \
04105   ANCHOR_WORD_BEGIN | ANCHOR_WORD_END )
04106 #define ALLOWED_ANCHOR_IN_LB_NOT \
04107 ( ANCHOR_LOOK_BEHIND | ANCHOR_LOOK_BEHIND_NOT | ANCHOR_BEGIN_LINE | \
04108   ANCHOR_END_LINE | ANCHOR_BEGIN_BUF | ANCHOR_BEGIN_POSITION | ANCHOR_KEEP | \
04109   ANCHOR_WORD_BOUND | ANCHOR_NOT_WORD_BOUND | \
04110   ANCHOR_WORD_BEGIN | ANCHOR_WORD_END )
04111 
04112       case ANCHOR_LOOK_BEHIND:
04113         {
04114           r = check_type_tree(an->target, ALLOWED_TYPE_IN_LB,
04115                               ALLOWED_ENCLOSE_IN_LB, ALLOWED_ANCHOR_IN_LB);
04116           if (r < 0) return r;
04117           if (r > 0) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
04118           r = setup_look_behind(node, reg, env);
04119           if (r != 0) return r;
04120           if (NTYPE(node) != NT_ANCHOR) goto restart;
04121           r = setup_tree(an->target, reg, state, env);
04122         }
04123         break;
04124 
04125       case ANCHOR_LOOK_BEHIND_NOT:
04126         {
04127           r = check_type_tree(an->target, ALLOWED_TYPE_IN_LB,
04128                       ALLOWED_ENCLOSE_IN_LB_NOT, ALLOWED_ANCHOR_IN_LB_NOT);
04129           if (r < 0) return r;
04130           if (r > 0) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
04131           r = setup_look_behind(node, reg, env);
04132           if (r != 0) return r;
04133           if (NTYPE(node) != NT_ANCHOR) goto restart;
04134           r = setup_tree(an->target, reg, (state | IN_NOT), env);
04135         }
04136         break;
04137       }
04138     }
04139     break;
04140 
04141   default:
04142     break;
04143   }
04144 
04145   return r;
04146 }
04147 
04148 #ifndef USE_SUNDAY_QUICK_SEARCH
04149 /* set skip map for Boyer-Moore search */
04150 static int
04151 set_bm_skip(UChar* s, UChar* end, regex_t* reg,
04152             UChar skip[], int** int_skip, int ignore_case)
04153 {
04154   OnigDistance i, len;
04155   int clen, flen, n, j, k;
04156   UChar *p, buf[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM][ONIGENC_MBC_CASE_FOLD_MAXLEN];
04157   OnigCaseFoldCodeItem items[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM];
04158   OnigEncoding enc = reg->enc;
04159 
04160   len = end - s;
04161   if (len < ONIG_CHAR_TABLE_SIZE) {
04162     for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) skip[i] = (UChar )len;
04163 
04164     n = 0;
04165     for (i = 0; i < len - 1; i += clen) {
04166       p = s + i;
04167       if (ignore_case)
04168         n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc, reg->case_fold_flag,
04169                                                p, end, items);
04170       clen = enclen(enc, p, end);
04171 
04172       for (j = 0; j < n; j++) {
04173         if ((items[j].code_len != 1) || (items[j].byte_len != clen))
04174           return 1;  /* different length isn't supported. */
04175         flen = ONIGENC_CODE_TO_MBC(enc, items[j].code[0], buf[j]);
04176         if (flen != clen)
04177           return 1;  /* different length isn't supported. */
04178       }
04179       for (j = 0; j < clen; j++) {
04180         skip[s[i + j]] = (UChar )(len - 1 - i - j);
04181         for (k = 0; k < n; k++) {
04182           skip[buf[k][j]] = (UChar )(len - 1 - i - j);
04183         }
04184       }
04185     }
04186   }
04187   else {
04188     if (IS_NULL(*int_skip)) {
04189       *int_skip = (int* )xmalloc(sizeof(int) * ONIG_CHAR_TABLE_SIZE);
04190       if (IS_NULL(*int_skip)) return ONIGERR_MEMORY;
04191     }
04192     for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) (*int_skip)[i] = (int )len;
04193 
04194     n = 0;
04195     for (i = 0; i < len - 1; i += clen) {
04196       p = s + i;
04197       if (ignore_case)
04198         n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc, reg->case_fold_flag,
04199                                                p, end, items);
04200       clen = enclen(enc, p, end);
04201 
04202       for (j = 0; j < n; j++) {
04203         if ((items[j].code_len != 1) || (items[j].byte_len != clen))
04204           return 1;  /* different length isn't supported. */
04205         flen = ONIGENC_CODE_TO_MBC(enc, items[j].code[0], buf[j]);
04206         if (flen != clen)
04207           return 1;  /* different length isn't supported. */
04208       }
04209       for (j = 0; j < clen; j++) {
04210         (*int_skip)[s[i + j]] = (int )(len - 1 - i - j);
04211         for (k = 0; k < n; k++) {
04212           (*int_skip)[buf[k][j]] = (int )(len - 1 - i - j);
04213         }
04214       }
04215     }
04216   }
04217   return 0;
04218 }
04219 
04220 #else /* USE_SUNDAY_QUICK_SEARCH */
04221 
04222 /* set skip map for Sunday's quick search */
04223 static int
04224 set_bm_skip(UChar* s, UChar* end, regex_t* reg,
04225             UChar skip[], int** int_skip, int ignore_case)
04226 {
04227   OnigDistance i, len;
04228   int clen, flen, n, j, k;
04229   UChar *p, buf[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM][ONIGENC_MBC_CASE_FOLD_MAXLEN];
04230   OnigCaseFoldCodeItem items[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM];
04231   OnigEncoding enc = reg->enc;
04232 
04233   len = end - s;
04234   if (len < ONIG_CHAR_TABLE_SIZE) {
04235     for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) skip[i] = (UChar )(len + 1);
04236 
04237     n = 0;
04238     for (i = 0; i < len; i += clen) {
04239       p = s + i;
04240       if (ignore_case)
04241         n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc, reg->case_fold_flag,
04242                                                p, end, items);
04243       clen = enclen(enc, p, end);
04244 
04245       for (j = 0; j < n; j++) {
04246         if ((items[j].code_len != 1) || (items[j].byte_len != clen))
04247           return 1;  /* different length isn't supported. */
04248         flen = ONIGENC_CODE_TO_MBC(enc, items[j].code[0], buf[j]);
04249         if (flen != clen)
04250           return 1;  /* different length isn't supported. */
04251       }
04252       for (j = 0; j < clen; j++) {
04253         skip[s[i + j]] = (UChar )(len - i - j);
04254         for (k = 0; k < n; k++) {
04255           skip[buf[k][j]] = (UChar )(len - i - j);
04256         }
04257       }
04258     }
04259   }
04260   else {
04261     if (IS_NULL(*int_skip)) {
04262       *int_skip = (int* )xmalloc(sizeof(int) * ONIG_CHAR_TABLE_SIZE);
04263       if (IS_NULL(*int_skip)) return ONIGERR_MEMORY;
04264     }
04265     for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) (*int_skip)[i] = (int )(len + 1);
04266 
04267     n = 0;
04268     for (i = 0; i < len; i += clen) {
04269       p = s + i;
04270       if (ignore_case)
04271         n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc, reg->case_fold_flag,
04272                                                p, end, items);
04273       clen = enclen(enc, p, end);
04274 
04275       for (j = 0; j < n; j++) {
04276         if ((items[j].code_len != 1) || (items[j].byte_len != clen))
04277           return 1;  /* different length isn't supported. */
04278         flen = ONIGENC_CODE_TO_MBC(enc, items[j].code[0], buf[j]);
04279         if (flen != clen)
04280           return 1;  /* different length isn't supported. */
04281       }
04282       for (j = 0; j < clen; j++) {
04283         (*int_skip)[s[i + j]] = (int )(len - i - j);
04284         for (k = 0; k < n; k++) {
04285           (*int_skip)[buf[k][j]] = (int )(len - i - j);
04286         }
04287       }
04288     }
04289   }
04290   return 0;
04291 }
04292 #endif /* USE_SUNDAY_QUICK_SEARCH */
04293 
04294 #define OPT_EXACT_MAXLEN   24
04295 
04296 typedef struct {
04297   OnigDistance min;  /* min byte length */
04298   OnigDistance max;  /* max byte length */
04299 } MinMaxLen;
04300 
04301 typedef struct {
04302   MinMaxLen        mmd;
04303   OnigEncoding     enc;
04304   OnigOptionType   options;
04305   OnigCaseFoldType case_fold_flag;
04306   ScanEnv*         scan_env;
04307 } OptEnv;
04308 
04309 typedef struct {
04310   int left_anchor;
04311   int right_anchor;
04312 } OptAncInfo;
04313 
04314 typedef struct {
04315   MinMaxLen  mmd; /* info position */
04316   OptAncInfo anc;
04317 
04318   int   reach_end;
04319   int   ignore_case;  /* -1: unset, 0: case sensitive, 1: ignore case */
04320   int   len;
04321   UChar s[OPT_EXACT_MAXLEN];
04322 } OptExactInfo;
04323 
04324 typedef struct {
04325   MinMaxLen mmd; /* info position */
04326   OptAncInfo anc;
04327 
04328   int   value;      /* weighted value */
04329   UChar map[ONIG_CHAR_TABLE_SIZE];
04330 } OptMapInfo;
04331 
04332 typedef struct {
04333   MinMaxLen    len;
04334 
04335   OptAncInfo   anc;
04336   OptExactInfo exb;    /* boundary */
04337   OptExactInfo exm;    /* middle */
04338   OptExactInfo expr;   /* prec read (?=...) */
04339 
04340   OptMapInfo   map;   /* boundary */
04341 } NodeOptInfo;
04342 
04343 
04344 static int
04345 map_position_value(OnigEncoding enc, int i)
04346 {
04347   static const short int ByteValTable[] = {
04348      5,  1,  1,  1,  1,  1,  1,  1,  1, 10, 10,  1,  1, 10,  1,  1,
04349      1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
04350     12,  4,  7,  4,  4,  4,  4,  4,  4,  5,  5,  5,  5,  5,  5,  5,
04351      6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  5,  5,  5,  5,  5,  5,
04352      5,  6,  6,  6,  6,  7,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
04353      6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  5,  6,  5,  5,  5,
04354      5,  6,  6,  6,  6,  7,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
04355      6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  5,  5,  5,  5,  1
04356   };
04357 
04358   if (i < (int )(sizeof(ByteValTable)/sizeof(ByteValTable[0]))) {
04359     if (i == 0 && ONIGENC_MBC_MINLEN(enc) > 1)
04360       return 20;
04361     else
04362       return (int )ByteValTable[i];
04363   }
04364   else
04365     return 4;   /* Take it easy. */
04366 }
04367 
04368 static int
04369 distance_value(MinMaxLen* mm)
04370 {
04371   /* 1000 / (min-max-dist + 1) */
04372   static const short int dist_vals[] = {
04373     1000,  500,  333,  250,  200,  167,  143,  125,  111,  100,
04374       91,   83,   77,   71,   67,   63,   59,   56,   53,   50,
04375       48,   45,   43,   42,   40,   38,   37,   36,   34,   33,
04376       32,   31,   30,   29,   29,   28,   27,   26,   26,   25,
04377       24,   24,   23,   23,   22,   22,   21,   21,   20,   20,
04378       20,   19,   19,   19,   18,   18,   18,   17,   17,   17,
04379       16,   16,   16,   16,   15,   15,   15,   15,   14,   14,
04380       14,   14,   14,   14,   13,   13,   13,   13,   13,   13,
04381       12,   12,   12,   12,   12,   12,   11,   11,   11,   11,
04382       11,   11,   11,   11,   11,   10,   10,   10,   10,   10
04383   };
04384 
04385   OnigDistance d;
04386 
04387   if (mm->max == ONIG_INFINITE_DISTANCE) return 0;
04388 
04389   d = mm->max - mm->min;
04390   if (d < sizeof(dist_vals)/sizeof(dist_vals[0]))
04391     /* return dist_vals[d] * 16 / (mm->min + 12); */
04392     return (int )dist_vals[d];
04393   else
04394     return 1;
04395 }
04396 
04397 static int
04398 comp_distance_value(MinMaxLen* d1, MinMaxLen* d2, int v1, int v2)
04399 {
04400   if (v2 <= 0) return -1;
04401   if (v1 <= 0) return  1;
04402 
04403   v1 *= distance_value(d1);
04404   v2 *= distance_value(d2);
04405 
04406   if (v2 > v1) return  1;
04407   if (v2 < v1) return -1;
04408 
04409   if (d2->min < d1->min) return  1;
04410   if (d2->min > d1->min) return -1;
04411   return 0;
04412 }
04413 
04414 static int
04415 is_equal_mml(MinMaxLen* a, MinMaxLen* b)
04416 {
04417   return (a->min == b->min && a->max == b->max) ? 1 : 0;
04418 }
04419 
04420 
04421 static void
04422 set_mml(MinMaxLen* mml, OnigDistance min, OnigDistance max)
04423 {
04424   mml->min = min;
04425   mml->max = max;
04426 }
04427 
04428 static void
04429 clear_mml(MinMaxLen* mml)
04430 {
04431   mml->min = mml->max = 0;
04432 }
04433 
04434 static void
04435 copy_mml(MinMaxLen* to, MinMaxLen* from)
04436 {
04437   to->min = from->min;
04438   to->max = from->max;
04439 }
04440 
04441 static void
04442 add_mml(MinMaxLen* to, MinMaxLen* from)
04443 {
04444   to->min = distance_add(to->min, from->min);
04445   to->max = distance_add(to->max, from->max);
04446 }
04447 
04448 #if 0
04449 static void
04450 add_len_mml(MinMaxLen* to, OnigDistance len)
04451 {
04452   to->min = distance_add(to->min, len);
04453   to->max = distance_add(to->max, len);
04454 }
04455 #endif
04456 
04457 static void
04458 alt_merge_mml(MinMaxLen* to, MinMaxLen* from)
04459 {
04460   if (to->min > from->min) to->min = from->min;
04461   if (to->max < from->max) to->max = from->max;
04462 }
04463 
04464 static void
04465 copy_opt_env(OptEnv* to, OptEnv* from)
04466 {
04467   *to = *from;
04468 }
04469 
04470 static void
04471 clear_opt_anc_info(OptAncInfo* anc)
04472 {
04473   anc->left_anchor  = 0;
04474   anc->right_anchor = 0;
04475 }
04476 
04477 static void
04478 copy_opt_anc_info(OptAncInfo* to, OptAncInfo* from)
04479 {
04480   *to = *from;
04481 }
04482 
04483 static void
04484 concat_opt_anc_info(OptAncInfo* to, OptAncInfo* left, OptAncInfo* right,
04485                     OnigDistance left_len, OnigDistance right_len)
04486 {
04487   clear_opt_anc_info(to);
04488 
04489   to->left_anchor = left->left_anchor;
04490   if (left_len == 0) {
04491     to->left_anchor |= right->left_anchor;
04492   }
04493 
04494   to->right_anchor = right->right_anchor;
04495   if (right_len == 0) {
04496     to->right_anchor |= left->right_anchor;
04497   }
04498   else {
04499     to->right_anchor |= (left->right_anchor & ANCHOR_PREC_READ_NOT);
04500   }
04501 }
04502 
04503 static int
04504 is_left_anchor(int anc)
04505 {
04506   if (anc == ANCHOR_END_BUF || anc == ANCHOR_SEMI_END_BUF ||
04507       anc == ANCHOR_END_LINE || anc == ANCHOR_PREC_READ ||
04508       anc == ANCHOR_PREC_READ_NOT)
04509     return 0;
04510 
04511   return 1;
04512 }
04513 
04514 static int
04515 is_set_opt_anc_info(OptAncInfo* to, int anc)
04516 {
04517   if ((to->left_anchor & anc) != 0) return 1;
04518 
04519   return ((to->right_anchor & anc) != 0 ? 1 : 0);
04520 }
04521 
04522 static void
04523 add_opt_anc_info(OptAncInfo* to, int anc)
04524 {
04525   if (is_left_anchor(anc))
04526     to->left_anchor |= anc;
04527   else
04528     to->right_anchor |= anc;
04529 }
04530 
04531 static void
04532 remove_opt_anc_info(OptAncInfo* to, int anc)
04533 {
04534   if (is_left_anchor(anc))
04535     to->left_anchor &= ~anc;
04536   else
04537     to->right_anchor &= ~anc;
04538 }
04539 
04540 static void
04541 alt_merge_opt_anc_info(OptAncInfo* to, OptAncInfo* add)
04542 {
04543   to->left_anchor  &= add->left_anchor;
04544   to->right_anchor &= add->right_anchor;
04545 }
04546 
04547 static int
04548 is_full_opt_exact_info(OptExactInfo* ex)
04549 {
04550   return (ex->len >= OPT_EXACT_MAXLEN ? 1 : 0);
04551 }
04552 
04553 static void
04554 clear_opt_exact_info(OptExactInfo* ex)
04555 {
04556   clear_mml(&ex->mmd);
04557   clear_opt_anc_info(&ex->anc);
04558   ex->reach_end   = 0;
04559   ex->ignore_case = -1;   /* unset */
04560   ex->len         = 0;
04561   ex->s[0]        = '\0';
04562 }
04563 
04564 static void
04565 copy_opt_exact_info(OptExactInfo* to, OptExactInfo* from)
04566 {
04567   *to = *from;
04568 }
04569 
04570 static void
04571 concat_opt_exact_info(OptExactInfo* to, OptExactInfo* add, OnigEncoding enc)
04572 {
04573   int i, j, len;
04574   UChar *p, *end;
04575   OptAncInfo tanc;
04576 
04577   if (to->ignore_case < 0)
04578     to->ignore_case = add->ignore_case;
04579   else if (to->ignore_case != add->ignore_case)
04580     return ;  /* avoid */
04581 
04582   p = add->s;
04583   end = p + add->len;
04584   for (i = to->len; p < end; ) {
04585     len = enclen(enc, p, end);
04586     if (i + len > OPT_EXACT_MAXLEN) break;
04587     for (j = 0; j < len && p < end; j++)
04588       to->s[i++] = *p++;
04589   }
04590 
04591   to->len = i;
04592   to->reach_end = (p == end ? add->reach_end : 0);
04593 
04594   concat_opt_anc_info(&tanc, &to->anc, &add->anc, 1, 1);
04595   if (! to->reach_end) tanc.right_anchor = 0;
04596   copy_opt_anc_info(&to->anc, &tanc);
04597 }
04598 
04599 static void
04600 concat_opt_exact_info_str(OptExactInfo* to, UChar* s, UChar* end,
04601                           int raw ARG_UNUSED, OnigEncoding enc)
04602 {
04603   int i, j, len;
04604   UChar *p;
04605 
04606   for (i = to->len, p = s; p < end && i < OPT_EXACT_MAXLEN; ) {
04607     len = enclen(enc, p, end);
04608     if (i + len > OPT_EXACT_MAXLEN) break;
04609     for (j = 0; j < len && p < end; j++)
04610       to->s[i++] = *p++;
04611   }
04612 
04613   to->len = i;
04614 }
04615 
04616 static void
04617 alt_merge_opt_exact_info(OptExactInfo* to, OptExactInfo* add, OptEnv* env)
04618 {
04619   int i, j, len;
04620 
04621   if (add->len == 0 || to->len == 0) {
04622     clear_opt_exact_info(to);
04623     return ;
04624   }
04625 
04626   if (! is_equal_mml(&to->mmd, &add->mmd)) {
04627     clear_opt_exact_info(to);
04628     return ;
04629   }
04630 
04631   for (i = 0; i < to->len && i < add->len; ) {
04632     if (to->s[i] != add->s[i]) break;
04633     len = enclen(env->enc, to->s + i, to->s + to->len);
04634 
04635     for (j = 1; j < len; j++) {
04636       if (to->s[i+j] != add->s[i+j]) break;
04637     }
04638     if (j < len) break;
04639     i += len;
04640   }
04641 
04642   if (! add->reach_end || i < add->len || i < to->len) {
04643     to->reach_end = 0;
04644   }
04645   to->len = i;
04646   if (to->ignore_case < 0)
04647     to->ignore_case = add->ignore_case;
04648   else if (add->ignore_case >= 0)
04649     to->ignore_case |= add->ignore_case;
04650 
04651   alt_merge_opt_anc_info(&to->anc, &add->anc);
04652   if (! to->reach_end) to->anc.right_anchor = 0;
04653 }
04654 
04655 static void
04656 select_opt_exact_info(OnigEncoding enc, OptExactInfo* now, OptExactInfo* alt)
04657 {
04658   int v1, v2;
04659 
04660   v1 = now->len;
04661   v2 = alt->len;
04662 
04663   if (v2 == 0) {
04664     return ;
04665   }
04666   else if (v1 == 0) {
04667     copy_opt_exact_info(now, alt);
04668     return ;
04669   }
04670   else if (v1 <= 2 && v2 <= 2) {
04671     /* ByteValTable[x] is big value --> low price */
04672     v2 = map_position_value(enc, now->s[0]);
04673     v1 = map_position_value(enc, alt->s[0]);
04674 
04675     if (now->len > 1) v1 += 5;
04676     if (alt->len > 1) v2 += 5;
04677   }
04678 
04679   if (now->ignore_case <= 0) v1 *= 2;
04680   if (alt->ignore_case <= 0) v2 *= 2;
04681 
04682   if (comp_distance_value(&now->mmd, &alt->mmd, v1, v2) > 0)
04683     copy_opt_exact_info(now, alt);
04684 }
04685 
04686 static void
04687 clear_opt_map_info(OptMapInfo* map)
04688 {
04689   static const OptMapInfo clean_info = {
04690     {0, 0}, {0, 0}, 0,
04691     {
04692       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
04693       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
04694       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
04695       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
04696       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
04697       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
04698       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
04699       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
04700       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
04701       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
04702       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
04703       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
04704       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
04705       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
04706       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
04707       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
04708     }
04709   };
04710 
04711   xmemcpy(map, &clean_info, sizeof(OptMapInfo));
04712 }
04713 
04714 static void
04715 copy_opt_map_info(OptMapInfo* to, OptMapInfo* from)
04716 {
04717   *to = *from;
04718 }
04719 
04720 static void
04721 add_char_opt_map_info(OptMapInfo* map, UChar c, OnigEncoding enc)
04722 {
04723   if (map->map[c] == 0) {
04724     map->map[c] = 1;
04725     map->value += map_position_value(enc, c);
04726   }
04727 }
04728 
04729 static int
04730 add_char_amb_opt_map_info(OptMapInfo* map, UChar* p, UChar* end,
04731                           OnigEncoding enc, OnigCaseFoldType case_fold_flag)
04732 {
04733   OnigCaseFoldCodeItem items[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM];
04734   UChar buf[ONIGENC_CODE_TO_MBC_MAXLEN];
04735   int i, n;
04736 
04737   add_char_opt_map_info(map, p[0], enc);
04738 
04739   case_fold_flag = DISABLE_CASE_FOLD_MULTI_CHAR(case_fold_flag);
04740   n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc, case_fold_flag, p, end, items);
04741   if (n < 0) return n;
04742 
04743   for (i = 0; i < n; i++) {
04744     ONIGENC_CODE_TO_MBC(enc, items[i].code[0], buf);
04745     add_char_opt_map_info(map, buf[0], enc);
04746   }
04747 
04748   return 0;
04749 }
04750 
04751 static void
04752 select_opt_map_info(OptMapInfo* now, OptMapInfo* alt)
04753 {
04754   const int z = 1<<15; /* 32768: something big value */
04755 
04756   int v1, v2;
04757 
04758   if (alt->value == 0) return ;
04759   if (now->value == 0) {
04760     copy_opt_map_info(now, alt);
04761     return ;
04762   }
04763 
04764   v1 = z / now->value;
04765   v2 = z / alt->value;
04766   if (comp_distance_value(&now->mmd, &alt->mmd, v1, v2) > 0)
04767     copy_opt_map_info(now, alt);
04768 }
04769 
04770 static int
04771 comp_opt_exact_or_map_info(OptExactInfo* e, OptMapInfo* m)
04772 {
04773 #define COMP_EM_BASE  20
04774   int ve, vm;
04775 
04776   if (m->value <= 0) return -1;
04777 
04778   ve = COMP_EM_BASE * e->len * (e->ignore_case > 0 ? 1 : 2);
04779   vm = COMP_EM_BASE * 5 * 2 / m->value;
04780   return comp_distance_value(&e->mmd, &m->mmd, ve, vm);
04781 }
04782 
04783 static void
04784 alt_merge_opt_map_info(OnigEncoding enc, OptMapInfo* to, OptMapInfo* add)
04785 {
04786   int i, val;
04787 
04788   /* if (! is_equal_mml(&to->mmd, &add->mmd)) return ; */
04789   if (to->value == 0) return ;
04790   if (add->value == 0 || to->mmd.max < add->mmd.min) {
04791     clear_opt_map_info(to);
04792     return ;
04793   }
04794 
04795   alt_merge_mml(&to->mmd, &add->mmd);
04796 
04797   val = 0;
04798   for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) {
04799     if (add->map[i])
04800       to->map[i] = 1;
04801 
04802     if (to->map[i])
04803       val += map_position_value(enc, i);
04804   }
04805   to->value = val;
04806 
04807   alt_merge_opt_anc_info(&to->anc, &add->anc);
04808 }
04809 
04810 static void
04811 set_bound_node_opt_info(NodeOptInfo* opt, MinMaxLen* mmd)
04812 {
04813   copy_mml(&(opt->exb.mmd),  mmd);
04814   copy_mml(&(opt->expr.mmd), mmd);
04815   copy_mml(&(opt->map.mmd),  mmd);
04816 }
04817 
04818 static void
04819 clear_node_opt_info(NodeOptInfo* opt)
04820 {
04821   clear_mml(&opt->len);
04822   clear_opt_anc_info(&opt->anc);
04823   clear_opt_exact_info(&opt->exb);
04824   clear_opt_exact_info(&opt->exm);
04825   clear_opt_exact_info(&opt->expr);
04826   clear_opt_map_info(&opt->map);
04827 }
04828 
04829 static void
04830 copy_node_opt_info(NodeOptInfo* to, NodeOptInfo* from)
04831 {
04832   *to = *from;
04833 }
04834 
04835 static void
04836 concat_left_node_opt_info(OnigEncoding enc, NodeOptInfo* to, NodeOptInfo* add)
04837 {
04838   int exb_reach, exm_reach;
04839   OptAncInfo tanc;
04840 
04841   concat_opt_anc_info(&tanc, &to->anc, &add->anc, to->len.max, add->len.max);
04842   copy_opt_anc_info(&to->anc, &tanc);
04843 
04844   if (add->exb.len > 0 && to->len.max == 0) {
04845     concat_opt_anc_info(&tanc, &to->anc, &add->exb.anc,
04846                         to->len.max, add->len.max);
04847     copy_opt_anc_info(&add->exb.anc, &tanc);
04848   }
04849 
04850   if (add->map.value > 0 && to->len.max == 0) {
04851     if (add->map.mmd.max == 0)
04852       add->map.anc.left_anchor |= to->anc.left_anchor;
04853   }
04854 
04855   exb_reach = to->exb.reach_end;
04856   exm_reach = to->exm.reach_end;
04857 
04858   if (add->len.max != 0)
04859     to->exb.reach_end = to->exm.reach_end = 0;
04860 
04861   if (add->exb.len > 0) {
04862     if (exb_reach) {
04863       concat_opt_exact_info(&to->exb, &add->exb, enc);
04864       clear_opt_exact_info(&add->exb);
04865     }
04866     else if (exm_reach) {
04867       concat_opt_exact_info(&to->exm, &add->exb, enc);
04868       clear_opt_exact_info(&add->exb);
04869     }
04870   }
04871   select_opt_exact_info(enc, &to->exm, &add->exb);
04872   select_opt_exact_info(enc, &to->exm, &add->exm);
04873 
04874   if (to->expr.len > 0) {
04875     if (add->len.max > 0) {
04876       if (to->expr.len > (int )add->len.max)
04877         to->expr.len = (int )add->len.max;
04878 
04879       if (to->expr.mmd.max == 0)
04880         select_opt_exact_info(enc, &to->exb, &to->expr);
04881       else
04882         select_opt_exact_info(enc, &to->exm, &to->expr);
04883     }
04884   }
04885   else if (add->expr.len > 0) {
04886     copy_opt_exact_info(&to->expr, &add->expr);
04887   }
04888 
04889   select_opt_map_info(&to->map, &add->map);
04890 
04891   add_mml(&to->len, &add->len);
04892 }
04893 
04894 static void
04895 alt_merge_node_opt_info(NodeOptInfo* to, NodeOptInfo* add, OptEnv* env)
04896 {
04897   alt_merge_opt_anc_info  (&to->anc,  &add->anc);
04898   alt_merge_opt_exact_info(&to->exb,  &add->exb, env);
04899   alt_merge_opt_exact_info(&to->exm,  &add->exm, env);
04900   alt_merge_opt_exact_info(&to->expr, &add->expr, env);
04901   alt_merge_opt_map_info(env->enc, &to->map,  &add->map);
04902 
04903   alt_merge_mml(&to->len, &add->len);
04904 }
04905 
04906 
04907 #define MAX_NODE_OPT_INFO_REF_COUNT    5
04908 
04909 static int
04910 optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env)
04911 {
04912   int type;
04913   int r = 0;
04914 
04915   clear_node_opt_info(opt);
04916   set_bound_node_opt_info(opt, &env->mmd);
04917 
04918   type = NTYPE(node);
04919   switch (type) {
04920   case NT_LIST:
04921     {
04922       OptEnv nenv;
04923       NodeOptInfo nopt;
04924       Node* nd = node;
04925 
04926       copy_opt_env(&nenv, env);
04927       do {
04928         r = optimize_node_left(NCAR(nd), &nopt, &nenv);
04929         if (r == 0) {
04930           add_mml(&nenv.mmd, &nopt.len);
04931           concat_left_node_opt_info(env->enc, opt, &nopt);
04932         }
04933       } while (r == 0 && IS_NOT_NULL(nd = NCDR(nd)));
04934     }
04935     break;
04936 
04937   case NT_ALT:
04938     {
04939       NodeOptInfo nopt;
04940       Node* nd = node;
04941 
04942       do {
04943         r = optimize_node_left(NCAR(nd), &nopt, env);
04944         if (r == 0) {
04945           if (nd == node) copy_node_opt_info(opt, &nopt);
04946           else            alt_merge_node_opt_info(opt, &nopt, env);
04947         }
04948       } while ((r == 0) && IS_NOT_NULL(nd = NCDR(nd)));
04949     }
04950     break;
04951 
04952   case NT_STR:
04953     {
04954       StrNode* sn = NSTR(node);
04955       OnigDistance slen = sn->end - sn->s;
04956       int is_raw = NSTRING_IS_RAW(node);
04957 
04958       if (! NSTRING_IS_AMBIG(node)) {
04959         concat_opt_exact_info_str(&opt->exb, sn->s, sn->end,
04960                                   is_raw, env->enc);
04961         opt->exb.ignore_case = 0;
04962         if (slen > 0) {
04963           add_char_opt_map_info(&opt->map, *(sn->s), env->enc);
04964         }
04965         set_mml(&opt->len, slen, slen);
04966       }
04967       else {
04968         OnigDistance max;
04969 
04970         if (NSTRING_IS_DONT_GET_OPT_INFO(node)) {
04971           int n = onigenc_strlen(env->enc, sn->s, sn->end);
04972           max = ONIGENC_MBC_MAXLEN_DIST(env->enc) * n;
04973         }
04974         else {
04975           concat_opt_exact_info_str(&opt->exb, sn->s, sn->end,
04976                                     is_raw, env->enc);
04977           opt->exb.ignore_case = 1;
04978 
04979           if (slen > 0) {
04980             r = add_char_amb_opt_map_info(&opt->map, sn->s, sn->end,
04981                                           env->enc, env->case_fold_flag);
04982             if (r != 0) break;
04983           }
04984 
04985           max = slen;
04986         }
04987 
04988         set_mml(&opt->len, slen, max);
04989       }
04990 
04991       if ((OnigDistance )opt->exb.len == slen)
04992         opt->exb.reach_end = 1;
04993     }
04994     break;
04995 
04996   case NT_CCLASS:
04997     {
04998       int i, z;
04999       CClassNode* cc = NCCLASS(node);
05000 
05001       /* no need to check ignore case. (set in setup_tree()) */
05002 
05003       if (IS_NOT_NULL(cc->mbuf) || IS_NCCLASS_NOT(cc)) {
05004         OnigDistance min = ONIGENC_MBC_MINLEN(env->enc);
05005         OnigDistance max = ONIGENC_MBC_MAXLEN_DIST(env->enc);
05006 
05007         set_mml(&opt->len, min, max);
05008       }
05009       else {
05010         for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
05011           z = BITSET_AT(cc->bs, i);
05012           if ((z && !IS_NCCLASS_NOT(cc)) || (!z && IS_NCCLASS_NOT(cc))) {
05013             add_char_opt_map_info(&opt->map, (UChar )i, env->enc);
05014           }
05015         }
05016         set_mml(&opt->len, 1, 1);
05017       }
05018     }
05019     break;
05020 
05021   case NT_CTYPE:
05022     {
05023       int i, min, max;
05024       int maxcode;
05025 
05026       max = ONIGENC_MBC_MAXLEN_DIST(env->enc);
05027 
05028       if (max == 1) {
05029         min = 1;
05030 
05031         maxcode = NCTYPE(node)->ascii_range ? 0x80 : SINGLE_BYTE_SIZE;
05032         switch (NCTYPE(node)->ctype) {
05033         case ONIGENC_CTYPE_WORD:
05034           if (NCTYPE(node)->not != 0) {
05035             for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
05036               if (! ONIGENC_IS_CODE_WORD(env->enc, i) || i >= maxcode) {
05037                 add_char_opt_map_info(&opt->map, (UChar )i, env->enc);
05038               }
05039             }
05040           }
05041           else {
05042             for (i = 0; i < maxcode; i++) {
05043               if (ONIGENC_IS_CODE_WORD(env->enc, i)) {
05044                 add_char_opt_map_info(&opt->map, (UChar )i, env->enc);
05045               }
05046             }
05047           }
05048           break;
05049         }
05050       }
05051       else {
05052         min = ONIGENC_MBC_MINLEN(env->enc);
05053       }
05054       set_mml(&opt->len, min, max);
05055     }
05056     break;
05057 
05058   case NT_CANY:
05059     {
05060       OnigDistance min = ONIGENC_MBC_MINLEN(env->enc);
05061       OnigDistance max = ONIGENC_MBC_MAXLEN_DIST(env->enc);
05062       set_mml(&opt->len, min, max);
05063     }
05064     break;
05065 
05066   case NT_ANCHOR:
05067     switch (NANCHOR(node)->type) {
05068     case ANCHOR_BEGIN_BUF:
05069     case ANCHOR_BEGIN_POSITION:
05070     case ANCHOR_BEGIN_LINE:
05071     case ANCHOR_END_BUF:
05072     case ANCHOR_SEMI_END_BUF:
05073     case ANCHOR_END_LINE:
05074     case ANCHOR_LOOK_BEHIND:    /* just for (?<=x).* */
05075     case ANCHOR_PREC_READ_NOT:  /* just for (?!x).* */
05076       add_opt_anc_info(&opt->anc, NANCHOR(node)->type);
05077       break;
05078 
05079     case ANCHOR_PREC_READ:
05080       {
05081         NodeOptInfo nopt;
05082 
05083         r = optimize_node_left(NANCHOR(node)->target, &nopt, env);
05084         if (r == 0) {
05085           if (nopt.exb.len > 0)
05086             copy_opt_exact_info(&opt->expr, &nopt.exb);
05087           else if (nopt.exm.len > 0)
05088             copy_opt_exact_info(&opt->expr, &nopt.exm);
05089 
05090           opt->expr.reach_end = 0;
05091 
05092           if (nopt.map.value > 0)
05093             copy_opt_map_info(&opt->map, &nopt.map);
05094         }
05095       }
05096       break;
05097 
05098     case ANCHOR_LOOK_BEHIND_NOT:
05099       break;
05100     }
05101     break;
05102 
05103   case NT_BREF:
05104     {
05105       int i;
05106       int* backs;
05107       OnigDistance min, max, tmin, tmax;
05108       Node** nodes = SCANENV_MEM_NODES(env->scan_env);
05109       BRefNode* br = NBREF(node);
05110 
05111       if (br->state & NST_RECURSION) {
05112         set_mml(&opt->len, 0, ONIG_INFINITE_DISTANCE);
05113         break;
05114       }
05115       backs = BACKREFS_P(br);
05116       r = get_min_match_length(nodes[backs[0]], &min, env->scan_env);
05117       if (r != 0) break;
05118       r = get_max_match_length(nodes[backs[0]], &max, env->scan_env);
05119       if (r != 0) break;
05120       for (i = 1; i < br->back_num; i++) {
05121         r = get_min_match_length(nodes[backs[i]], &tmin, env->scan_env);
05122         if (r != 0) break;
05123         r = get_max_match_length(nodes[backs[i]], &tmax, env->scan_env);
05124         if (r != 0) break;
05125         if (min > tmin) min = tmin;
05126         if (max < tmax) max = tmax;
05127       }
05128       if (r == 0) set_mml(&opt->len, min, max);
05129     }
05130     break;
05131 
05132 #ifdef USE_SUBEXP_CALL
05133   case NT_CALL:
05134     if (IS_CALL_RECURSION(NCALL(node)))
05135       set_mml(&opt->len, 0, ONIG_INFINITE_DISTANCE);
05136     else {
05137       OnigOptionType save = env->options;
05138       env->options = NENCLOSE(NCALL(node)->target)->option;
05139       r = optimize_node_left(NCALL(node)->target, opt, env);
05140       env->options = save;
05141     }
05142     break;
05143 #endif
05144 
05145   case NT_QTFR:
05146     {
05147       int i;
05148       OnigDistance min, max;
05149       NodeOptInfo nopt;
05150       QtfrNode* qn = NQTFR(node);
05151 
05152       r = optimize_node_left(qn->target, &nopt, env);
05153       if (r) break;
05154 
05155       if (/*qn->lower == 0 &&*/ IS_REPEAT_INFINITE(qn->upper)) {
05156         if (env->mmd.max == 0 &&
05157             NTYPE(qn->target) == NT_CANY && qn->greedy) {
05158           if (IS_MULTILINE(env->options))
05159             /* implicit anchor: /.*a/ ==> /\A.*a/ */
05160             add_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR_ML);
05161           else
05162             add_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR);
05163         }
05164       }
05165       else {
05166         if (qn->lower > 0) {
05167           copy_node_opt_info(opt, &nopt);
05168           if (nopt.exb.len > 0) {
05169             if (nopt.exb.reach_end) {
05170               for (i = 2; i <= qn->lower &&
05171                           ! is_full_opt_exact_info(&opt->exb); i++) {
05172                 concat_opt_exact_info(&opt->exb, &nopt.exb, env->enc);
05173               }
05174               if (i < qn->lower) {
05175                 opt->exb.reach_end = 0;
05176               }
05177             }
05178           }
05179 
05180           if (qn->lower != qn->upper) {
05181             opt->exb.reach_end = 0;
05182             opt->exm.reach_end = 0;
05183           }
05184           if (qn->lower > 1)
05185             opt->exm.reach_end = 0;
05186         }
05187       }
05188 
05189       min = distance_multiply(nopt.len.min, qn->lower);
05190       if (IS_REPEAT_INFINITE(qn->upper))
05191         max = (nopt.len.max > 0 ? ONIG_INFINITE_DISTANCE : 0);
05192       else
05193         max = distance_multiply(nopt.len.max, qn->upper);
05194 
05195       set_mml(&opt->len, min, max);
05196     }
05197     break;
05198 
05199   case NT_ENCLOSE:
05200     {
05201       EncloseNode* en = NENCLOSE(node);
05202 
05203       switch (en->type) {
05204       case ENCLOSE_OPTION:
05205         {
05206           OnigOptionType save = env->options;
05207 
05208           env->options = en->option;
05209           r = optimize_node_left(en->target, opt, env);
05210           env->options = save;
05211         }
05212         break;
05213 
05214       case ENCLOSE_MEMORY:
05215 #ifdef USE_SUBEXP_CALL
05216         en->opt_count++;
05217         if (en->opt_count > MAX_NODE_OPT_INFO_REF_COUNT) {
05218           OnigDistance min, max;
05219 
05220           min = 0;
05221           max = ONIG_INFINITE_DISTANCE;
05222           if (IS_ENCLOSE_MIN_FIXED(en)) min = en->min_len;
05223           if (IS_ENCLOSE_MAX_FIXED(en)) max = en->max_len;
05224           set_mml(&opt->len, min, max);
05225         }
05226         else
05227 #endif
05228         {
05229           r = optimize_node_left(en->target, opt, env);
05230 
05231           if (is_set_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR_MASK)) {
05232             if (BIT_STATUS_AT(env->scan_env->backrefed_mem, en->regnum))
05233               remove_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR_MASK);
05234           }
05235         }
05236         break;
05237 
05238       case ENCLOSE_STOP_BACKTRACK:
05239       case ENCLOSE_CONDITION:
05240         r = optimize_node_left(en->target, opt, env);
05241         break;
05242       }
05243     }
05244     break;
05245 
05246   default:
05247 #ifdef ONIG_DEBUG
05248     if (!onig_is_prelude()) fprintf(stderr, "optimize_node_left: undefined node type %d\n",
05249             NTYPE(node));
05250 #endif
05251     r = ONIGERR_TYPE_BUG;
05252     break;
05253   }
05254 
05255   return r;
05256 }
05257 
05258 static int
05259 set_optimize_exact_info(regex_t* reg, OptExactInfo* e)
05260 {
05261   int r;
05262   int allow_reverse;
05263 
05264   if (e->len == 0) return 0;
05265 
05266   reg->exact = (UChar* )xmalloc(e->len);
05267   CHECK_NULL_RETURN_MEMERR(reg->exact);
05268   xmemcpy(reg->exact, e->s, e->len);
05269   reg->exact_end = reg->exact + e->len;
05270 
05271   allow_reverse =
05272         ONIGENC_IS_ALLOWED_REVERSE_MATCH(reg->enc, reg->exact, reg->exact_end);
05273 
05274   if (e->ignore_case > 0) {
05275     if (e->len >= 3 || (e->len >= 2 && allow_reverse)) {
05276       r = set_bm_skip(reg->exact, reg->exact_end, reg,
05277                       reg->map, &(reg->int_map), 1);
05278       if (r == 0) {
05279         reg->optimize = (allow_reverse != 0
05280                          ? ONIG_OPTIMIZE_EXACT_BM_IC : ONIG_OPTIMIZE_EXACT_BM_NOT_REV_IC);
05281       }
05282       else {
05283         reg->optimize = ONIG_OPTIMIZE_EXACT_IC;
05284       }
05285     }
05286     else {
05287       reg->optimize = ONIG_OPTIMIZE_EXACT_IC;
05288     }
05289   }
05290   else {
05291     if (e->len >= 3 || (e->len >= 2 && allow_reverse)) {
05292       r = set_bm_skip(reg->exact, reg->exact_end, reg,
05293                       reg->map, &(reg->int_map), 0);
05294       if (r) return r;
05295 
05296       reg->optimize = (allow_reverse != 0
05297                        ? ONIG_OPTIMIZE_EXACT_BM : ONIG_OPTIMIZE_EXACT_BM_NOT_REV);
05298     }
05299     else {
05300       reg->optimize = ONIG_OPTIMIZE_EXACT;
05301     }
05302   }
05303 
05304   reg->dmin = e->mmd.min;
05305   reg->dmax = e->mmd.max;
05306 
05307   if (reg->dmin != ONIG_INFINITE_DISTANCE) {
05308     reg->threshold_len = (int )(reg->dmin + (reg->exact_end - reg->exact));
05309   }
05310 
05311   return 0;
05312 }
05313 
05314 static void
05315 set_optimize_map_info(regex_t* reg, OptMapInfo* m)
05316 {
05317   int i;
05318 
05319   for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++)
05320     reg->map[i] = m->map[i];
05321 
05322   reg->optimize   = ONIG_OPTIMIZE_MAP;
05323   reg->dmin       = m->mmd.min;
05324   reg->dmax       = m->mmd.max;
05325 
05326   if (reg->dmin != ONIG_INFINITE_DISTANCE) {
05327     reg->threshold_len = (int )(reg->dmin + 1);
05328   }
05329 }
05330 
05331 static void
05332 set_sub_anchor(regex_t* reg, OptAncInfo* anc)
05333 {
05334   reg->sub_anchor |= anc->left_anchor  & ANCHOR_BEGIN_LINE;
05335   reg->sub_anchor |= anc->right_anchor & ANCHOR_END_LINE;
05336 }
05337 
05338 #ifdef ONIG_DEBUG
05339 static void print_optimize_info(FILE* f, regex_t* reg);
05340 #endif
05341 
05342 static int
05343 set_optimize_info_from_tree(Node* node, regex_t* reg, ScanEnv* scan_env)
05344 {
05345 
05346   int r;
05347   NodeOptInfo opt;
05348   OptEnv env;
05349 
05350   env.enc            = reg->enc;
05351   env.options        = reg->options;
05352   env.case_fold_flag = reg->case_fold_flag;
05353   env.scan_env   = scan_env;
05354   clear_mml(&env.mmd);
05355 
05356   r = optimize_node_left(node, &opt, &env);
05357   if (r) return r;
05358 
05359   reg->anchor = opt.anc.left_anchor & (ANCHOR_BEGIN_BUF |
05360         ANCHOR_BEGIN_POSITION | ANCHOR_ANYCHAR_STAR | ANCHOR_ANYCHAR_STAR_ML |
05361         ANCHOR_LOOK_BEHIND);
05362 
05363   reg->anchor |= opt.anc.right_anchor & (ANCHOR_END_BUF | ANCHOR_SEMI_END_BUF |
05364         ANCHOR_PREC_READ_NOT);
05365 
05366   if (reg->anchor & (ANCHOR_END_BUF | ANCHOR_SEMI_END_BUF)) {
05367     reg->anchor_dmin = opt.len.min;
05368     reg->anchor_dmax = opt.len.max;
05369   }
05370 
05371   if (opt.exb.len > 0 || opt.exm.len > 0) {
05372     select_opt_exact_info(reg->enc, &opt.exb, &opt.exm);
05373     if (opt.map.value > 0 &&
05374         comp_opt_exact_or_map_info(&opt.exb, &opt.map) > 0) {
05375       goto set_map;
05376     }
05377     else {
05378       r = set_optimize_exact_info(reg, &opt.exb);
05379       set_sub_anchor(reg, &opt.exb.anc);
05380     }
05381   }
05382   else if (opt.map.value > 0) {
05383   set_map:
05384     set_optimize_map_info(reg, &opt.map);
05385     set_sub_anchor(reg, &opt.map.anc);
05386   }
05387   else {
05388     reg->sub_anchor |= opt.anc.left_anchor & ANCHOR_BEGIN_LINE;
05389     if (opt.len.max == 0)
05390       reg->sub_anchor |= opt.anc.right_anchor & ANCHOR_END_LINE;
05391   }
05392 
05393 #if defined(ONIG_DEBUG_COMPILE) || defined(ONIG_DEBUG_MATCH)
05394   if (!onig_is_prelude()) print_optimize_info(stderr, reg);
05395 #endif
05396   return r;
05397 }
05398 
05399 static void
05400 clear_optimize_info(regex_t* reg)
05401 {
05402   reg->optimize      = ONIG_OPTIMIZE_NONE;
05403   reg->anchor        = 0;
05404   reg->anchor_dmin   = 0;
05405   reg->anchor_dmax   = 0;
05406   reg->sub_anchor    = 0;
05407   reg->exact_end     = (UChar* )NULL;
05408   reg->threshold_len = 0;
05409   if (IS_NOT_NULL(reg->exact)) {
05410     xfree(reg->exact);
05411     reg->exact = (UChar* )NULL;
05412   }
05413 }
05414 
05415 #ifdef ONIG_DEBUG
05416 
05417 static void print_enc_string(FILE* fp, OnigEncoding enc,
05418                              const UChar *s, const UChar *end)
05419 {
05420   fprintf(fp, "\nPATTERN: /");
05421 
05422   if (ONIGENC_MBC_MINLEN(enc) > 1) {
05423     const UChar *p;
05424     OnigCodePoint code;
05425 
05426     p = s;
05427     while (p < end) {
05428       code = ONIGENC_MBC_TO_CODE(enc, p, end);
05429       if (code >= 0x80) {
05430         fprintf(fp, " 0x%04x ", (int )code);
05431       }
05432       else {
05433         fputc((int )code, fp);
05434       }
05435 
05436       p += enclen(enc, p, end);
05437     }
05438   }
05439   else {
05440     while (s < end) {
05441       fputc((int )*s, fp);
05442       s++;
05443     }
05444   }
05445 
05446   fprintf(fp, "/ (%s)\n", enc->name);
05447 }
05448 
05449 static void
05450 print_distance_range(FILE* f, OnigDistance a, OnigDistance b)
05451 {
05452   if (a == ONIG_INFINITE_DISTANCE)
05453     fputs("inf", f);
05454   else
05455     fprintf(f, "(%"PRIuSIZE")", a);
05456 
05457   fputs("-", f);
05458 
05459   if (b == ONIG_INFINITE_DISTANCE)
05460     fputs("inf", f);
05461   else
05462     fprintf(f, "(%"PRIuSIZE")", b);
05463 }
05464 
05465 static void
05466 print_anchor(FILE* f, int anchor)
05467 {
05468   int q = 0;
05469 
05470   fprintf(f, "[");
05471 
05472   if (anchor & ANCHOR_BEGIN_BUF) {
05473     fprintf(f, "begin-buf");
05474     q = 1;
05475   }
05476   if (anchor & ANCHOR_BEGIN_LINE) {
05477     if (q) fprintf(f, ", ");
05478     q = 1;
05479     fprintf(f, "begin-line");
05480   }
05481   if (anchor & ANCHOR_BEGIN_POSITION) {
05482     if (q) fprintf(f, ", ");
05483     q = 1;
05484     fprintf(f, "begin-pos");
05485   }
05486   if (anchor & ANCHOR_END_BUF) {
05487     if (q) fprintf(f, ", ");
05488     q = 1;
05489     fprintf(f, "end-buf");
05490   }
05491   if (anchor & ANCHOR_SEMI_END_BUF) {
05492     if (q) fprintf(f, ", ");
05493     q = 1;
05494     fprintf(f, "semi-end-buf");
05495   }
05496   if (anchor & ANCHOR_END_LINE) {
05497     if (q) fprintf(f, ", ");
05498     q = 1;
05499     fprintf(f, "end-line");
05500   }
05501   if (anchor & ANCHOR_ANYCHAR_STAR) {
05502     if (q) fprintf(f, ", ");
05503     q = 1;
05504     fprintf(f, "anychar-star");
05505   }
05506   if (anchor & ANCHOR_ANYCHAR_STAR_ML) {
05507     if (q) fprintf(f, ", ");
05508     fprintf(f, "anychar-star-ml");
05509   }
05510 
05511   fprintf(f, "]");
05512 }
05513 
05514 static void
05515 print_optimize_info(FILE* f, regex_t* reg)
05516 {
05517   static const char* on[] = { "NONE", "EXACT", "EXACT_BM", "EXACT_BM_NOT_REV",
05518                               "EXACT_IC", "MAP",
05519                               "EXACT_BM_IC", "EXACT_BM_NOT_REV_IC" };
05520 
05521   fprintf(f, "optimize: %s\n", on[reg->optimize]);
05522   fprintf(f, "  anchor: "); print_anchor(f, reg->anchor);
05523   if ((reg->anchor & ANCHOR_END_BUF_MASK) != 0)
05524     print_distance_range(f, reg->anchor_dmin, reg->anchor_dmax);
05525   fprintf(f, "\n");
05526 
05527   if (reg->optimize) {
05528     fprintf(f, "  sub anchor: "); print_anchor(f, reg->sub_anchor);
05529     fprintf(f, "\n");
05530   }
05531   fprintf(f, "\n");
05532 
05533   if (reg->exact) {
05534     UChar *p;
05535     fprintf(f, "exact: [");
05536     for (p = reg->exact; p < reg->exact_end; p++) {
05537       fputc(*p, f);
05538     }
05539     fprintf(f, "]: length: %ld\n", (reg->exact_end - reg->exact));
05540   }
05541   else if (reg->optimize & ONIG_OPTIMIZE_MAP) {
05542     int c, i, n = 0;
05543 
05544     for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++)
05545       if (reg->map[i]) n++;
05546 
05547     fprintf(f, "map: n=%d\n", n);
05548     if (n > 0) {
05549       c = 0;
05550       fputc('[', f);
05551       for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) {
05552         if (reg->map[i] != 0) {
05553           if (c > 0)  fputs(", ", f);
05554           c++;
05555           if (ONIGENC_MBC_MAXLEN(reg->enc) == 1 &&
05556               ONIGENC_IS_CODE_PRINT(reg->enc, (OnigCodePoint )i))
05557             fputc(i, f);
05558           else
05559             fprintf(f, "%d", i);
05560         }
05561       }
05562       fprintf(f, "]\n");
05563     }
05564   }
05565 }
05566 #endif /* ONIG_DEBUG */
05567 
05568 
05569 extern void
05570 onig_free_body(regex_t* reg)
05571 {
05572   if (IS_NOT_NULL(reg)) {
05573     if (IS_NOT_NULL(reg->p))                xfree(reg->p);
05574     if (IS_NOT_NULL(reg->exact))            xfree(reg->exact);
05575     if (IS_NOT_NULL(reg->int_map))          xfree(reg->int_map);
05576     if (IS_NOT_NULL(reg->int_map_backward)) xfree(reg->int_map_backward);
05577     if (IS_NOT_NULL(reg->repeat_range))     xfree(reg->repeat_range);
05578     if (IS_NOT_NULL(reg->chain))            onig_free(reg->chain);
05579 
05580 #ifdef USE_NAMED_GROUP
05581     onig_names_free(reg);
05582 #endif
05583   }
05584 }
05585 
05586 extern void
05587 onig_free(regex_t* reg)
05588 {
05589   if (IS_NOT_NULL(reg)) {
05590     onig_free_body(reg);
05591     xfree(reg);
05592   }
05593 }
05594 
05595 size_t
05596 onig_memsize(const regex_t *reg)
05597 {
05598     size_t size = sizeof(regex_t);
05599     if (IS_NULL(reg)) return 0;
05600     if (IS_NOT_NULL(reg->p))                size += reg->alloc;
05601     if (IS_NOT_NULL(reg->exact))            size += reg->exact_end - reg->exact;
05602     if (IS_NOT_NULL(reg->int_map))          size += sizeof(int) * ONIG_CHAR_TABLE_SIZE;
05603     if (IS_NOT_NULL(reg->int_map_backward)) size += sizeof(int) * ONIG_CHAR_TABLE_SIZE;
05604     if (IS_NOT_NULL(reg->repeat_range))     size += reg->repeat_range_alloc * sizeof(OnigRepeatRange);
05605     if (IS_NOT_NULL(reg->chain))            size += onig_memsize(reg->chain);
05606 
05607     return size;
05608 }
05609 
05610 size_t
05611 onig_region_memsize(const OnigRegion *regs)
05612 {
05613     size_t size = sizeof(*regs);
05614     if (IS_NULL(regs)) return 0;
05615     size += regs->allocated * (sizeof(*regs->beg) + sizeof(*regs->end));
05616     return size;
05617 }
05618 
05619 #define REGEX_TRANSFER(to,from) do {\
05620   (to)->state = ONIG_STATE_MODIFY;\
05621   onig_free_body(to);\
05622   xmemcpy(to, from, sizeof(regex_t));\
05623   xfree(from);\
05624 } while (0)
05625 
05626 extern void
05627 onig_transfer(regex_t* to, regex_t* from)
05628 {
05629   THREAD_ATOMIC_START;
05630   REGEX_TRANSFER(to, from);
05631   THREAD_ATOMIC_END;
05632 }
05633 
05634 #define REGEX_CHAIN_HEAD(reg) do {\
05635   while (IS_NOT_NULL((reg)->chain)) {\
05636     (reg) = (reg)->chain;\
05637   }\
05638 } while (0)
05639 
05640 extern void
05641 onig_chain_link_add(regex_t* to, regex_t* add)
05642 {
05643   THREAD_ATOMIC_START;
05644   REGEX_CHAIN_HEAD(to);
05645   to->chain = add;
05646   THREAD_ATOMIC_END;
05647 }
05648 
05649 extern void
05650 onig_chain_reduce(regex_t* reg)
05651 {
05652   regex_t *head, *prev;
05653 
05654   prev = reg;
05655   head = prev->chain;
05656   if (IS_NOT_NULL(head)) {
05657     reg->state = ONIG_STATE_MODIFY;
05658     while (IS_NOT_NULL(head->chain)) {
05659       prev = head;
05660       head = head->chain;
05661     }
05662     prev->chain = (regex_t* )NULL;
05663     REGEX_TRANSFER(reg, head);
05664   }
05665 }
05666 
05667 #ifdef ONIG_DEBUG
05668 static void print_compiled_byte_code_list P_((FILE* f, regex_t* reg));
05669 #endif
05670 #ifdef ONIG_DEBUG_PARSE_TREE
05671 static void print_tree P_((FILE* f, Node* node));
05672 #endif
05673 
05674 extern int
05675 onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end,
05676               OnigErrorInfo* einfo, const char *sourcefile, int sourceline)
05677 {
05678 #define COMPILE_INIT_SIZE  20
05679 
05680   int r;
05681   OnigDistance init_size;
05682   Node*  root;
05683   ScanEnv  scan_env = {0};
05684 #ifdef USE_SUBEXP_CALL
05685   UnsetAddrList  uslist;
05686 #endif
05687 
05688   if (IS_NOT_NULL(einfo)) einfo->par = (UChar* )NULL;
05689 
05690   scan_env.sourcefile = sourcefile;
05691   scan_env.sourceline = sourceline;
05692   reg->state = ONIG_STATE_COMPILING;
05693 
05694 #ifdef ONIG_DEBUG
05695   if (!onig_is_prelude()) print_enc_string(stderr, reg->enc, pattern, pattern_end);
05696 #endif
05697 
05698   if (reg->alloc == 0) {
05699     init_size = (pattern_end - pattern) * 2;
05700     if (init_size <= 0) init_size = COMPILE_INIT_SIZE;
05701     r = BBUF_INIT(reg, init_size);
05702     if (r != 0) goto end;
05703   }
05704   else
05705     reg->used = 0;
05706 
05707   reg->num_mem            = 0;
05708   reg->num_repeat         = 0;
05709   reg->num_null_check     = 0;
05710   reg->repeat_range_alloc = 0;
05711   reg->repeat_range       = (OnigRepeatRange* )NULL;
05712 #ifdef USE_COMBINATION_EXPLOSION_CHECK
05713   reg->num_comb_exp_check = 0;
05714 #endif
05715 
05716   r = onig_parse_make_tree(&root, pattern, pattern_end, reg, &scan_env);
05717   if (r != 0) goto err;
05718 
05719 #ifdef ONIG_DEBUG_PARSE_TREE
05720 # if 0
05721   fprintf(stderr, "ORIGINAL PARSE TREE:\n");
05722   if (!onig_is_prelude()) {
05723     print_tree(stderr, root);
05724   }
05725 # endif
05726 #endif
05727 
05728 #ifdef USE_NAMED_GROUP
05729   /* mixed use named group and no-named group */
05730   if (scan_env.num_named > 0 &&
05731       IS_SYNTAX_BV(scan_env.syntax, ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP) &&
05732       !ONIG_IS_OPTION_ON(reg->options, ONIG_OPTION_CAPTURE_GROUP)) {
05733     if (scan_env.num_named != scan_env.num_mem)
05734       r = disable_noname_group_capture(&root, reg, &scan_env);
05735     else
05736       r = numbered_ref_check(root);
05737 
05738     if (r != 0) goto err;
05739   }
05740 #endif
05741 
05742 #ifdef USE_SUBEXP_CALL
05743   if (scan_env.num_call > 0) {
05744     r = unset_addr_list_init(&uslist, scan_env.num_call);
05745     if (r != 0) goto err;
05746     scan_env.unset_addr_list = &uslist;
05747     r = setup_subexp_call(root, &scan_env);
05748     if (r != 0) goto err_unset;
05749     r = subexp_recursive_check_trav(root, &scan_env);
05750     if (r  < 0) goto err_unset;
05751     r = subexp_inf_recursive_check_trav(root, &scan_env);
05752     if (r != 0) goto err_unset;
05753 
05754     reg->num_call = scan_env.num_call;
05755   }
05756   else
05757     reg->num_call = 0;
05758 #endif
05759 
05760   r = setup_tree(root, reg, IN_ROOT, &scan_env);
05761   if (r != 0) goto err_unset;
05762 
05763 #ifdef ONIG_DEBUG_PARSE_TREE
05764   if (!onig_is_prelude()) print_tree(stderr, root);
05765 #endif
05766 
05767   reg->capture_history  = scan_env.capture_history;
05768   reg->bt_mem_start     = scan_env.bt_mem_start;
05769   reg->bt_mem_start    |= reg->capture_history;
05770   if (IS_FIND_CONDITION(reg->options))
05771     BIT_STATUS_ON_ALL(reg->bt_mem_end);
05772   else {
05773     reg->bt_mem_end  = scan_env.bt_mem_end;
05774     reg->bt_mem_end |= reg->capture_history;
05775   }
05776 
05777 #ifdef USE_COMBINATION_EXPLOSION_CHECK
05778   if (scan_env.backrefed_mem == 0
05779 #ifdef USE_SUBEXP_CALL
05780       || scan_env.num_call == 0
05781 #endif
05782       ) {
05783     setup_comb_exp_check(root, 0, &scan_env);
05784 #ifdef USE_SUBEXP_CALL
05785     if (scan_env.has_recursion != 0) {
05786       scan_env.num_comb_exp_check = 0;
05787     }
05788     else
05789 #endif
05790     if (scan_env.comb_exp_max_regnum > 0) {
05791       int i;
05792       for (i = 1; i <= scan_env.comb_exp_max_regnum; i++) {
05793         if (BIT_STATUS_AT(scan_env.backrefed_mem, i) != 0) {
05794           scan_env.num_comb_exp_check = 0;
05795           break;
05796         }
05797       }
05798     }
05799   }
05800 
05801   reg->num_comb_exp_check = scan_env.num_comb_exp_check;
05802 #endif
05803 
05804   clear_optimize_info(reg);
05805 #ifndef ONIG_DONT_OPTIMIZE
05806   r = set_optimize_info_from_tree(root, reg, &scan_env);
05807   if (r != 0) goto err_unset;
05808 #endif
05809 
05810   if (IS_NOT_NULL(scan_env.mem_nodes_dynamic)) {
05811     xfree(scan_env.mem_nodes_dynamic);
05812     scan_env.mem_nodes_dynamic = (Node** )NULL;
05813   }
05814 
05815   r = compile_tree(root, reg);
05816   if (r == 0) {
05817     r = add_opcode(reg, OP_END);
05818 #ifdef USE_SUBEXP_CALL
05819     if (scan_env.num_call > 0) {
05820       r = unset_addr_list_fix(&uslist, reg);
05821       unset_addr_list_end(&uslist);
05822       if (r) goto err;
05823     }
05824 #endif
05825 
05826     if ((reg->num_repeat != 0) || (reg->bt_mem_end != 0))
05827       reg->stack_pop_level = STACK_POP_LEVEL_ALL;
05828     else {
05829       if (reg->bt_mem_start != 0)
05830         reg->stack_pop_level = STACK_POP_LEVEL_MEM_START;
05831       else
05832         reg->stack_pop_level = STACK_POP_LEVEL_FREE;
05833     }
05834   }
05835 #ifdef USE_SUBEXP_CALL
05836   else if (scan_env.num_call > 0) {
05837     unset_addr_list_end(&uslist);
05838   }
05839 #endif
05840   onig_node_free(root);
05841 
05842 #ifdef ONIG_DEBUG_COMPILE
05843 #ifdef USE_NAMED_GROUP
05844   if (!onig_is_prelude()) onig_print_names(stderr, reg);
05845 #endif
05846   if (!onig_is_prelude()) print_compiled_byte_code_list(stderr, reg);
05847 #endif
05848 
05849  end:
05850   reg->state = ONIG_STATE_NORMAL;
05851   return r;
05852 
05853  err_unset:
05854 #ifdef USE_SUBEXP_CALL
05855   if (scan_env.num_call > 0) {
05856     unset_addr_list_end(&uslist);
05857   }
05858 #endif
05859  err:
05860   if (IS_NOT_NULL(scan_env.error)) {
05861     if (IS_NOT_NULL(einfo)) {
05862       einfo->enc     = scan_env.enc;
05863       einfo->par     = scan_env.error;
05864       einfo->par_end = scan_env.error_end;
05865     }
05866   }
05867 
05868   onig_node_free(root);
05869   if (IS_NOT_NULL(scan_env.mem_nodes_dynamic))
05870       xfree(scan_env.mem_nodes_dynamic);
05871   return r;
05872 }
05873 
05874 #ifdef USE_RECOMPILE_API
05875 extern int
05876 onig_recompile(regex_t* reg, const UChar* pattern, const UChar* pattern_end,
05877             OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax,
05878             OnigErrorInfo* einfo)
05879 {
05880   int r;
05881   regex_t *new_reg;
05882 
05883   r = onig_new(&new_reg, pattern, pattern_end, option, enc, syntax, einfo);
05884   if (r) return r;
05885   if (ONIG_STATE(reg) == ONIG_STATE_NORMAL) {
05886     onig_transfer(reg, new_reg);
05887   }
05888   else {
05889     onig_chain_link_add(reg, new_reg);
05890   }
05891   return 0;
05892 }
05893 #endif
05894 
05895 static int onig_inited = 0;
05896 
05897 extern int
05898 onig_reg_init(regex_t* reg, OnigOptionType option,
05899               OnigCaseFoldType case_fold_flag,
05900               OnigEncoding enc, const OnigSyntaxType* syntax)
05901 {
05902   if (! onig_inited)
05903     onig_init();
05904 
05905   if (IS_NULL(reg))
05906     return ONIGERR_INVALID_ARGUMENT;
05907 
05908   if (ONIGENC_IS_UNDEF(enc))
05909     return ONIGERR_DEFAULT_ENCODING_IS_NOT_SET;
05910 
05911   if ((option & (ONIG_OPTION_DONT_CAPTURE_GROUP|ONIG_OPTION_CAPTURE_GROUP))
05912       == (ONIG_OPTION_DONT_CAPTURE_GROUP|ONIG_OPTION_CAPTURE_GROUP)) {
05913     return ONIGERR_INVALID_COMBINATION_OF_OPTIONS;
05914   }
05915 
05916   (reg)->state = ONIG_STATE_MODIFY;
05917 
05918   if ((option & ONIG_OPTION_NEGATE_SINGLELINE) != 0) {
05919     option |= syntax->options;
05920     option &= ~ONIG_OPTION_SINGLELINE;
05921   }
05922   else
05923     option |= syntax->options;
05924 
05925   (reg)->enc              = enc;
05926   (reg)->options          = option;
05927   (reg)->syntax           = syntax;
05928   (reg)->optimize         = 0;
05929   (reg)->exact            = (UChar* )NULL;
05930   (reg)->int_map          = (int* )NULL;
05931   (reg)->int_map_backward = (int* )NULL;
05932   (reg)->chain            = (regex_t* )NULL;
05933 
05934   (reg)->p                = (UChar* )NULL;
05935   (reg)->alloc            = 0;
05936   (reg)->used             = 0;
05937   (reg)->name_table       = (void* )NULL;
05938 
05939   (reg)->case_fold_flag   = case_fold_flag;
05940   return 0;
05941 }
05942 
05943 extern int
05944 onig_new_without_alloc(regex_t* reg, const UChar* pattern,
05945           const UChar* pattern_end, OnigOptionType option, OnigEncoding enc,
05946           OnigSyntaxType* syntax, OnigErrorInfo* einfo)
05947 {
05948   int r;
05949 
05950   r = onig_reg_init(reg, option, ONIGENC_CASE_FOLD_DEFAULT, enc, syntax);
05951   if (r) return r;
05952 
05953   r = onig_compile(reg, pattern, pattern_end, einfo, NULL, 0);
05954   return r;
05955 }
05956 
05957 extern int
05958 onig_new(regex_t** reg, const UChar* pattern, const UChar* pattern_end,
05959           OnigOptionType option, OnigEncoding enc, const OnigSyntaxType* syntax,
05960           OnigErrorInfo* einfo)
05961 {
05962   int r;
05963 
05964   *reg = (regex_t* )xmalloc(sizeof(regex_t));
05965   if (IS_NULL(*reg)) return ONIGERR_MEMORY;
05966 
05967   r = onig_reg_init(*reg, option, ONIGENC_CASE_FOLD_DEFAULT, enc, syntax);
05968   if (r) goto err;
05969 
05970   r = onig_compile(*reg, pattern, pattern_end, einfo, NULL, 0);
05971   if (r) {
05972   err:
05973     onig_free(*reg);
05974     *reg = NULL;
05975   }
05976   return r;
05977 }
05978 
05979 
05980 extern int
05981 onig_init(void)
05982 {
05983   if (onig_inited != 0)
05984     return 0;
05985 
05986   THREAD_SYSTEM_INIT;
05987   THREAD_ATOMIC_START;
05988 
05989   onig_inited = 1;
05990 
05991   onigenc_init();
05992   /* onigenc_set_default_caseconv_table((UChar* )0); */
05993 
05994 #ifdef ONIG_DEBUG_STATISTICS
05995   onig_statistics_init();
05996 #endif
05997 
05998   THREAD_ATOMIC_END;
05999   return 0;
06000 }
06001 
06002 
06003 extern int
06004 onig_end(void)
06005 {
06006   THREAD_ATOMIC_START;
06007 
06008 #ifdef ONIG_DEBUG_STATISTICS
06009   if (!onig_is_prelude()) onig_print_statistics(stderr);
06010 #endif
06011 
06012 #ifdef USE_SHARED_CCLASS_TABLE
06013   onig_free_shared_cclass_table();
06014 #endif
06015 
06016 #ifdef USE_PARSE_TREE_NODE_RECYCLE
06017   onig_free_node_list();
06018 #endif
06019 
06020   onig_inited = 0;
06021 
06022   THREAD_ATOMIC_END;
06023   THREAD_SYSTEM_END;
06024   return 0;
06025 }
06026 
06027 extern int
06028 onig_is_in_code_range(const UChar* p, OnigCodePoint code)
06029 {
06030   OnigCodePoint n, *data;
06031   OnigCodePoint low, high, x;
06032 
06033   GET_CODE_POINT(n, p);
06034   data = (OnigCodePoint* )p;
06035   data++;
06036 
06037   for (low = 0, high = n; low < high; ) {
06038     x = (low + high) >> 1;
06039     if (code > data[x * 2 + 1])
06040       low = x + 1;
06041     else
06042       high = x;
06043   }
06044 
06045   return ((low < n && code >= data[low * 2]) ? 1 : 0);
06046 }
06047 
06048 extern int
06049 onig_is_code_in_cc_len(int elen, OnigCodePoint code, CClassNode* cc)
06050 {
06051   int found;
06052 
06053   if (elen > 1 || (code >= SINGLE_BYTE_SIZE)) {
06054     if (IS_NULL(cc->mbuf)) {
06055       found = 0;
06056     }
06057     else {
06058       found = (onig_is_in_code_range(cc->mbuf->p, code) != 0 ? 1 : 0);
06059     }
06060   }
06061   else {
06062     found = (BITSET_AT(cc->bs, code) == 0 ? 0 : 1);
06063   }
06064 
06065   if (IS_NCCLASS_NOT(cc))
06066     return !found;
06067   else
06068     return found;
06069 }
06070 
06071 extern int
06072 onig_is_code_in_cc(OnigEncoding enc, OnigCodePoint code, CClassNode* cc)
06073 {
06074   int len;
06075 
06076   if (ONIGENC_MBC_MINLEN(enc) > 1) {
06077     len = 2;
06078   }
06079   else {
06080     len = ONIGENC_CODE_TO_MBCLEN(enc, code);
06081   }
06082   return onig_is_code_in_cc_len(len, code, cc);
06083 }
06084 
06085 
06086 #ifdef ONIG_DEBUG
06087 
06088 /* arguments type */
06089 #define ARG_SPECIAL     -1
06090 #define ARG_NON          0
06091 #define ARG_RELADDR      1
06092 #define ARG_ABSADDR      2
06093 #define ARG_LENGTH       3
06094 #define ARG_MEMNUM       4
06095 #define ARG_OPTION       5
06096 #define ARG_STATE_CHECK  6
06097 
06098 OnigOpInfoType OnigOpInfo[] = {
06099   { OP_FINISH,            "finish",          ARG_NON },
06100   { OP_END,               "end",             ARG_NON },
06101   { OP_EXACT1,            "exact1",          ARG_SPECIAL },
06102   { OP_EXACT2,            "exact2",          ARG_SPECIAL },
06103   { OP_EXACT3,            "exact3",          ARG_SPECIAL },
06104   { OP_EXACT4,            "exact4",          ARG_SPECIAL },
06105   { OP_EXACT5,            "exact5",          ARG_SPECIAL },
06106   { OP_EXACTN,            "exactn",          ARG_SPECIAL },
06107   { OP_EXACTMB2N1,        "exactmb2-n1",     ARG_SPECIAL },
06108   { OP_EXACTMB2N2,        "exactmb2-n2",     ARG_SPECIAL },
06109   { OP_EXACTMB2N3,        "exactmb2-n3",     ARG_SPECIAL },
06110   { OP_EXACTMB2N,         "exactmb2-n",      ARG_SPECIAL },
06111   { OP_EXACTMB3N,         "exactmb3n"  ,     ARG_SPECIAL },
06112   { OP_EXACTMBN,          "exactmbn",        ARG_SPECIAL },
06113   { OP_EXACT1_IC,         "exact1-ic",       ARG_SPECIAL },
06114   { OP_EXACTN_IC,         "exactn-ic",       ARG_SPECIAL },
06115   { OP_CCLASS,            "cclass",          ARG_SPECIAL },
06116   { OP_CCLASS_MB,         "cclass-mb",       ARG_SPECIAL },
06117   { OP_CCLASS_MIX,        "cclass-mix",      ARG_SPECIAL },
06118   { OP_CCLASS_NOT,        "cclass-not",      ARG_SPECIAL },
06119   { OP_CCLASS_MB_NOT,     "cclass-mb-not",   ARG_SPECIAL },
06120   { OP_CCLASS_MIX_NOT,    "cclass-mix-not",  ARG_SPECIAL },
06121   { OP_CCLASS_NODE,       "cclass-node",     ARG_SPECIAL },
06122   { OP_ANYCHAR,           "anychar",         ARG_NON },
06123   { OP_ANYCHAR_ML,        "anychar-ml",      ARG_NON },
06124   { OP_ANYCHAR_STAR,      "anychar*",        ARG_NON },
06125   { OP_ANYCHAR_ML_STAR,   "anychar-ml*",     ARG_NON },
06126   { OP_ANYCHAR_STAR_PEEK_NEXT, "anychar*-peek-next", ARG_SPECIAL },
06127   { OP_ANYCHAR_ML_STAR_PEEK_NEXT, "anychar-ml*-peek-next", ARG_SPECIAL },
06128   { OP_WORD,                "word",            ARG_NON },
06129   { OP_NOT_WORD,            "not-word",        ARG_NON },
06130   { OP_WORD_BOUND,          "word-bound",      ARG_NON },
06131   { OP_NOT_WORD_BOUND,      "not-word-bound",  ARG_NON },
06132   { OP_WORD_BEGIN,          "word-begin",      ARG_NON },
06133   { OP_WORD_END,            "word-end",        ARG_NON },
06134   { OP_ASCII_WORD,          "ascii-word",           ARG_NON },
06135   { OP_NOT_ASCII_WORD,      "not-ascii-word",       ARG_NON },
06136   { OP_ASCII_WORD_BOUND,    "ascii-word-bound",     ARG_NON },
06137   { OP_NOT_ASCII_WORD_BOUND,"not-ascii-word-bound", ARG_NON },
06138   { OP_ASCII_WORD_BEGIN,    "ascii-word-begin",     ARG_NON },
06139   { OP_ASCII_WORD_END,      "ascii-word-end",       ARG_NON },
06140   { OP_BEGIN_BUF,           "begin-buf",       ARG_NON },
06141   { OP_END_BUF,             "end-buf",         ARG_NON },
06142   { OP_BEGIN_LINE,          "begin-line",      ARG_NON },
06143   { OP_END_LINE,            "end-line",        ARG_NON },
06144   { OP_SEMI_END_BUF,        "semi-end-buf",    ARG_NON },
06145   { OP_BEGIN_POSITION,      "begin-position",  ARG_NON },
06146   { OP_BEGIN_POS_OR_LINE,   "begin-pos-or-line",    ARG_NON },
06147   { OP_BACKREF1,            "backref1",             ARG_NON },
06148   { OP_BACKREF2,            "backref2",             ARG_NON },
06149   { OP_BACKREFN,            "backrefn",             ARG_MEMNUM  },
06150   { OP_BACKREFN_IC,         "backrefn-ic",          ARG_SPECIAL },
06151   { OP_BACKREF_MULTI,       "backref_multi",        ARG_SPECIAL },
06152   { OP_BACKREF_MULTI_IC,    "backref_multi-ic",     ARG_SPECIAL },
06153   { OP_BACKREF_WITH_LEVEL,  "backref_at_level",     ARG_SPECIAL },
06154   { OP_MEMORY_START_PUSH,   "mem-start-push",       ARG_MEMNUM  },
06155   { OP_MEMORY_START,        "mem-start",            ARG_MEMNUM  },
06156   { OP_MEMORY_END_PUSH,     "mem-end-push",         ARG_MEMNUM  },
06157   { OP_MEMORY_END_PUSH_REC, "mem-end-push-rec",     ARG_MEMNUM  },
06158   { OP_MEMORY_END,          "mem-end",              ARG_MEMNUM  },
06159   { OP_MEMORY_END_REC,      "mem-end-rec",          ARG_MEMNUM  },
06160   { OP_SET_OPTION_PUSH,     "set-option-push",      ARG_OPTION  },
06161   { OP_SET_OPTION,          "set-option",           ARG_OPTION  },
06162   { OP_KEEP,                "keep",                 ARG_NON },
06163   { OP_FAIL,                "fail",                 ARG_NON },
06164   { OP_JUMP,                "jump",                 ARG_RELADDR },
06165   { OP_PUSH,                "push",                 ARG_RELADDR },
06166   { OP_POP,                 "pop",                  ARG_NON },
06167   { OP_PUSH_OR_JUMP_EXACT1, "push-or-jump-e1",      ARG_SPECIAL },
06168   { OP_PUSH_IF_PEEK_NEXT,   "push-if-peek-next",    ARG_SPECIAL },
06169   { OP_REPEAT,              "repeat",               ARG_SPECIAL },
06170   { OP_REPEAT_NG,           "repeat-ng",            ARG_SPECIAL },
06171   { OP_REPEAT_INC,          "repeat-inc",           ARG_MEMNUM  },
06172   { OP_REPEAT_INC_NG,       "repeat-inc-ng",        ARG_MEMNUM  },
06173   { OP_REPEAT_INC_SG,       "repeat-inc-sg",        ARG_MEMNUM  },
06174   { OP_REPEAT_INC_NG_SG,    "repeat-inc-ng-sg",     ARG_MEMNUM  },
06175   { OP_NULL_CHECK_START,    "null-check-start",     ARG_MEMNUM  },
06176   { OP_NULL_CHECK_END,      "null-check-end",       ARG_MEMNUM  },
06177   { OP_NULL_CHECK_END_MEMST,"null-check-end-memst", ARG_MEMNUM  },
06178   { OP_NULL_CHECK_END_MEMST_PUSH,"null-check-end-memst-push", ARG_MEMNUM  },
06179   { OP_PUSH_POS,             "push-pos",             ARG_NON },
06180   { OP_POP_POS,              "pop-pos",              ARG_NON },
06181   { OP_PUSH_POS_NOT,         "push-pos-not",         ARG_RELADDR },
06182   { OP_FAIL_POS,             "fail-pos",             ARG_NON },
06183   { OP_PUSH_STOP_BT,         "push-stop-bt",         ARG_NON },
06184   { OP_POP_STOP_BT,          "pop-stop-bt",          ARG_NON },
06185   { OP_LOOK_BEHIND,          "look-behind",          ARG_SPECIAL },
06186   { OP_PUSH_LOOK_BEHIND_NOT, "push-look-behind-not", ARG_SPECIAL },
06187   { OP_FAIL_LOOK_BEHIND_NOT, "fail-look-behind-not", ARG_NON },
06188   { OP_CALL,                 "call",                 ARG_ABSADDR },
06189   { OP_RETURN,               "return",               ARG_NON },
06190   { OP_CONDITION,            "condition",            ARG_SPECIAL },
06191   { OP_STATE_CHECK_PUSH,         "state-check-push",         ARG_SPECIAL },
06192   { OP_STATE_CHECK_PUSH_OR_JUMP, "state-check-push-or-jump", ARG_SPECIAL },
06193   { OP_STATE_CHECK,              "state-check",              ARG_STATE_CHECK },
06194   { OP_STATE_CHECK_ANYCHAR_STAR, "state-check-anychar*",     ARG_STATE_CHECK },
06195   { OP_STATE_CHECK_ANYCHAR_ML_STAR,
06196     "state-check-anychar-ml*", ARG_STATE_CHECK },
06197   { -1, "", ARG_NON }
06198 };
06199 
06200 static const char*
06201 op2name(int opcode)
06202 {
06203   int i;
06204 
06205   for (i = 0; OnigOpInfo[i].opcode >= 0; i++) {
06206     if (opcode == OnigOpInfo[i].opcode)
06207       return OnigOpInfo[i].name;
06208   }
06209   return "";
06210 }
06211 
06212 static int
06213 op2arg_type(int opcode)
06214 {
06215   int i;
06216 
06217   for (i = 0; OnigOpInfo[i].opcode >= 0; i++) {
06218     if (opcode == OnigOpInfo[i].opcode)
06219       return OnigOpInfo[i].arg_type;
06220   }
06221   return ARG_SPECIAL;
06222 }
06223 
06224 static void
06225 Indent(FILE* f, int indent)
06226 {
06227   int i;
06228   for (i = 0; i < indent; i++) putc(' ', f);
06229 }
06230 
06231 static void
06232 p_string(FILE* f, int len, UChar* s)
06233 {
06234   fputs(":", f);
06235   while (len-- > 0) { fputc(*s++, f); }
06236 }
06237 
06238 static void
06239 p_len_string(FILE* f, LengthType len, int mb_len, UChar* s)
06240 {
06241   int x = len * mb_len;
06242 
06243   fprintf(f, ":%d:", len);
06244   while (x-- > 0) { fputc(*s++, f); }
06245 }
06246 
06247 extern void
06248 onig_print_compiled_byte_code(FILE* f, UChar* bp, UChar* bpend, UChar** nextp,
06249                               OnigEncoding enc)
06250 {
06251   int i, n, arg_type;
06252   RelAddrType addr;
06253   LengthType len;
06254   MemNumType mem;
06255   StateCheckNumType scn;
06256   OnigCodePoint code;
06257   UChar *q;
06258 
06259   fprintf(f, "[%s", op2name(*bp));
06260   arg_type = op2arg_type(*bp);
06261   if (arg_type != ARG_SPECIAL) {
06262     bp++;
06263     switch (arg_type) {
06264     case ARG_NON:
06265       break;
06266     case ARG_RELADDR:
06267       GET_RELADDR_INC(addr, bp);
06268       fprintf(f, ":(%d)", addr);
06269       break;
06270     case ARG_ABSADDR:
06271       GET_ABSADDR_INC(addr, bp);
06272       fprintf(f, ":(%d)", addr);
06273       break;
06274     case ARG_LENGTH:
06275       GET_LENGTH_INC(len, bp);
06276       fprintf(f, ":%d", len);
06277       break;
06278     case ARG_MEMNUM:
06279       mem = *((MemNumType* )bp);
06280       bp += SIZE_MEMNUM;
06281       fprintf(f, ":%d", mem);
06282       break;
06283     case ARG_OPTION:
06284       {
06285         OnigOptionType option = *((OnigOptionType* )bp);
06286         bp += SIZE_OPTION;
06287         fprintf(f, ":%d", option);
06288       }
06289       break;
06290 
06291     case ARG_STATE_CHECK:
06292       scn = *((StateCheckNumType* )bp);
06293       bp += SIZE_STATE_CHECK_NUM;
06294       fprintf(f, ":%d", scn);
06295       break;
06296     }
06297   }
06298   else {
06299     switch (*bp++) {
06300     case OP_EXACT1:
06301     case OP_ANYCHAR_STAR_PEEK_NEXT:
06302     case OP_ANYCHAR_ML_STAR_PEEK_NEXT:
06303       p_string(f, 1, bp++); break;
06304     case OP_EXACT2:
06305       p_string(f, 2, bp); bp += 2; break;
06306     case OP_EXACT3:
06307       p_string(f, 3, bp); bp += 3; break;
06308     case OP_EXACT4:
06309       p_string(f, 4, bp); bp += 4; break;
06310     case OP_EXACT5:
06311       p_string(f, 5, bp); bp += 5; break;
06312     case OP_EXACTN:
06313       GET_LENGTH_INC(len, bp);
06314       p_len_string(f, len, 1, bp);
06315       bp += len;
06316       break;
06317 
06318     case OP_EXACTMB2N1:
06319       p_string(f, 2, bp); bp += 2; break;
06320     case OP_EXACTMB2N2:
06321       p_string(f, 4, bp); bp += 4; break;
06322     case OP_EXACTMB2N3:
06323       p_string(f, 6, bp); bp += 6; break;
06324     case OP_EXACTMB2N:
06325       GET_LENGTH_INC(len, bp);
06326       p_len_string(f, len, 2, bp);
06327       bp += len * 2;
06328       break;
06329     case OP_EXACTMB3N:
06330       GET_LENGTH_INC(len, bp);
06331       p_len_string(f, len, 3, bp);
06332       bp += len * 3;
06333       break;
06334     case OP_EXACTMBN:
06335       {
06336         int mb_len;
06337 
06338         GET_LENGTH_INC(mb_len, bp);
06339         GET_LENGTH_INC(len, bp);
06340         fprintf(f, ":%d:%d:", mb_len, len);
06341         n = len * mb_len;
06342         while (n-- > 0) { fputc(*bp++, f); }
06343       }
06344       break;
06345 
06346     case OP_EXACT1_IC:
06347       len = enclen(enc, bp, bpend);
06348       p_string(f, len, bp);
06349       bp += len;
06350       break;
06351     case OP_EXACTN_IC:
06352       GET_LENGTH_INC(len, bp);
06353       p_len_string(f, len, 1, bp);
06354       bp += len;
06355       break;
06356 
06357     case OP_CCLASS:
06358       n = bitset_on_num((BitSetRef )bp);
06359       bp += SIZE_BITSET;
06360       fprintf(f, ":%d", n);
06361       break;
06362 
06363     case OP_CCLASS_NOT:
06364       n = bitset_on_num((BitSetRef )bp);
06365       bp += SIZE_BITSET;
06366       fprintf(f, ":%d", n);
06367       break;
06368 
06369     case OP_CCLASS_MB:
06370     case OP_CCLASS_MB_NOT:
06371       GET_LENGTH_INC(len, bp);
06372       q = bp;
06373 #ifndef PLATFORM_UNALIGNED_WORD_ACCESS
06374       ALIGNMENT_RIGHT(q);
06375 #endif
06376       GET_CODE_POINT(code, q);
06377       bp += len;
06378       fprintf(f, ":%d:%d", (int )code, len);
06379       break;
06380 
06381     case OP_CCLASS_MIX:
06382     case OP_CCLASS_MIX_NOT:
06383       n = bitset_on_num((BitSetRef )bp);
06384       bp += SIZE_BITSET;
06385       GET_LENGTH_INC(len, bp);
06386       q = bp;
06387 #ifndef PLATFORM_UNALIGNED_WORD_ACCESS
06388       ALIGNMENT_RIGHT(q);
06389 #endif
06390       GET_CODE_POINT(code, q);
06391       bp += len;
06392       fprintf(f, ":%d:%d:%d", n, (int )code, len);
06393       break;
06394 
06395     case OP_CCLASS_NODE:
06396       {
06397         CClassNode *cc;
06398 
06399         GET_POINTER_INC(cc, bp);
06400         n = bitset_on_num(cc->bs);
06401         fprintf(f, ":%"PRIuPTR":%d", (uintptr_t)cc, n);
06402       }
06403       break;
06404 
06405     case OP_BACKREFN_IC:
06406       mem = *((MemNumType* )bp);
06407       bp += SIZE_MEMNUM;
06408       fprintf(f, ":%d", mem);
06409       break;
06410 
06411     case OP_BACKREF_MULTI_IC:
06412     case OP_BACKREF_MULTI:
06413       fputs(" ", f);
06414       GET_LENGTH_INC(len, bp);
06415       for (i = 0; i < len; i++) {
06416         GET_MEMNUM_INC(mem, bp);
06417         if (i > 0) fputs(", ", f);
06418         fprintf(f, "%d", mem);
06419       }
06420       break;
06421 
06422     case OP_BACKREF_WITH_LEVEL:
06423       {
06424         OnigOptionType option;
06425         LengthType level;
06426 
06427         GET_OPTION_INC(option, bp);
06428         fprintf(f, ":%d", option);
06429         GET_LENGTH_INC(level, bp);
06430         fprintf(f, ":%d", level);
06431 
06432         fputs(" ", f);
06433         GET_LENGTH_INC(len, bp);
06434         for (i = 0; i < len; i++) {
06435           GET_MEMNUM_INC(mem, bp);
06436           if (i > 0) fputs(", ", f);
06437           fprintf(f, "%d", mem);
06438         }
06439       }
06440       break;
06441 
06442     case OP_REPEAT:
06443     case OP_REPEAT_NG:
06444       {
06445         mem = *((MemNumType* )bp);
06446         bp += SIZE_MEMNUM;
06447         addr = *((RelAddrType* )bp);
06448         bp += SIZE_RELADDR;
06449         fprintf(f, ":%d:%d", mem, addr);
06450       }
06451       break;
06452 
06453     case OP_PUSH_OR_JUMP_EXACT1:
06454     case OP_PUSH_IF_PEEK_NEXT:
06455       addr = *((RelAddrType* )bp);
06456       bp += SIZE_RELADDR;
06457       fprintf(f, ":(%d)", addr);
06458       p_string(f, 1, bp);
06459       bp += 1;
06460       break;
06461 
06462     case OP_LOOK_BEHIND:
06463       GET_LENGTH_INC(len, bp);
06464       fprintf(f, ":%d", len);
06465       break;
06466 
06467     case OP_PUSH_LOOK_BEHIND_NOT:
06468       GET_RELADDR_INC(addr, bp);
06469       GET_LENGTH_INC(len, bp);
06470       fprintf(f, ":%d:(%d)", len, addr);
06471       break;
06472 
06473     case OP_STATE_CHECK_PUSH:
06474     case OP_STATE_CHECK_PUSH_OR_JUMP:
06475       scn = *((StateCheckNumType* )bp);
06476       bp += SIZE_STATE_CHECK_NUM;
06477       addr = *((RelAddrType* )bp);
06478       bp += SIZE_RELADDR;
06479       fprintf(f, ":%d:(%d)", scn, addr);
06480       break;
06481 
06482     case OP_CONDITION:
06483       GET_MEMNUM_INC(mem, bp);
06484       GET_RELADDR_INC(addr, bp);
06485       fprintf(f, ":%d:(%d)", mem, addr);
06486       break;
06487 
06488     default:
06489       fprintf(stderr, "onig_print_compiled_byte_code: undefined code %d\n",
06490               *--bp);
06491     }
06492   }
06493   fputs("]", f);
06494   if (nextp) *nextp = bp;
06495 }
06496 
06497 static void
06498 print_compiled_byte_code_list(FILE* f, regex_t* reg)
06499 {
06500   int ncode;
06501   UChar* bp = reg->p;
06502   UChar* end = reg->p + reg->used;
06503 
06504   fprintf(f, "code length: %d", reg->used);
06505 
06506   ncode = -1;
06507   while (bp < end) {
06508     ncode++;
06509     if (ncode % 5 == 0)
06510       fprintf(f, "\n%ld:", bp - reg->p);
06511     else
06512       fprintf(f, " %ld:", bp - reg->p);
06513     onig_print_compiled_byte_code(f, bp, end, &bp, reg->enc);
06514   }
06515 
06516   fprintf(f, "\n");
06517 }
06518 
06519 static void
06520 print_indent_tree(FILE* f, Node* node, int indent)
06521 {
06522   int i, type, container_p = 0;
06523   int add = 3;
06524   UChar* p;
06525 
06526   Indent(f, indent);
06527   if (IS_NULL(node)) {
06528     fprintf(f, "ERROR: null node!!!\n");
06529     exit (0);
06530   }
06531 
06532   type = NTYPE(node);
06533   switch (type) {
06534   case NT_LIST:
06535   case NT_ALT:
06536     if (NTYPE(node) == NT_LIST)
06537       fprintf(f, "<list:%"PRIxPTR">\n", (intptr_t)node);
06538     else
06539       fprintf(f, "<alt:%"PRIxPTR">\n", (intptr_t)node);
06540 
06541     print_indent_tree(f, NCAR(node), indent + add);
06542     while (IS_NOT_NULL(node = NCDR(node))) {
06543       if (NTYPE(node) != type) {
06544         fprintf(f, "ERROR: list/alt right is not a cons. %d\n", NTYPE(node));
06545         exit(0);
06546       }
06547       print_indent_tree(f, NCAR(node), indent + add);
06548     }
06549     break;
06550 
06551   case NT_STR:
06552     fprintf(f, "<string%s:%"PRIxPTR">",
06553             (NSTRING_IS_RAW(node) ? "-raw" : ""), (intptr_t)node);
06554     for (p = NSTR(node)->s; p < NSTR(node)->end; p++) {
06555       if (*p >= 0x20 && *p < 0x7f)
06556         fputc(*p, f);
06557       else {
06558         fprintf(f, " 0x%02x", *p);
06559       }
06560     }
06561     break;
06562 
06563   case NT_CCLASS:
06564     fprintf(f, "<cclass:%"PRIxPTR">", (intptr_t)node);
06565     if (IS_NCCLASS_NOT(NCCLASS(node))) fputs(" not", f);
06566     if (NCCLASS(node)->mbuf) {
06567       BBuf* bbuf = NCCLASS(node)->mbuf;
06568       for (i = 0; i < (int )bbuf->used; i++) {
06569         if (i > 0) fprintf(f, ",");
06570         fprintf(f, "%0x", bbuf->p[i]);
06571       }
06572     }
06573     break;
06574 
06575   case NT_CTYPE:
06576     fprintf(f, "<ctype:%"PRIxPTR"> ", (intptr_t)node);
06577     switch (NCTYPE(node)->ctype) {
06578     case ONIGENC_CTYPE_WORD:
06579       if (NCTYPE(node)->not != 0)
06580         fputs("not word",       f);
06581       else
06582         fputs("word",           f);
06583       break;
06584 
06585     default:
06586       fprintf(f, "ERROR: undefined ctype.\n");
06587       exit(0);
06588     }
06589     break;
06590 
06591   case NT_CANY:
06592     fprintf(f, "<anychar:%"PRIxPTR">", (intptr_t)node);
06593     break;
06594 
06595   case NT_ANCHOR:
06596     fprintf(f, "<anchor:%"PRIxPTR"> ", (intptr_t)node);
06597     switch (NANCHOR(node)->type) {
06598     case ANCHOR_BEGIN_BUF:      fputs("begin buf",      f); break;
06599     case ANCHOR_END_BUF:        fputs("end buf",        f); break;
06600     case ANCHOR_BEGIN_LINE:     fputs("begin line",     f); break;
06601     case ANCHOR_END_LINE:       fputs("end line",       f); break;
06602     case ANCHOR_SEMI_END_BUF:   fputs("semi end buf",   f); break;
06603     case ANCHOR_BEGIN_POSITION: fputs("begin position", f); break;
06604     case ANCHOR_ANYCHAR_STAR:   fputs("begin position/line", f); break;
06605 
06606     case ANCHOR_WORD_BOUND:      fputs("word bound",     f); break;
06607     case ANCHOR_NOT_WORD_BOUND:  fputs("not word bound", f); break;
06608 #ifdef USE_WORD_BEGIN_END
06609     case ANCHOR_WORD_BEGIN:      fputs("word begin", f);     break;
06610     case ANCHOR_WORD_END:        fputs("word end", f);       break;
06611 #endif
06612     case ANCHOR_PREC_READ:       fputs("prec read",      f); container_p = TRUE; break;
06613     case ANCHOR_PREC_READ_NOT:   fputs("prec read not",  f); container_p = TRUE; break;
06614     case ANCHOR_LOOK_BEHIND:     fputs("look_behind",    f); container_p = TRUE; break;
06615     case ANCHOR_LOOK_BEHIND_NOT: fputs("look_behind_not",f); container_p = TRUE; break;
06616     case ANCHOR_KEEP:            fputs("keep",f);            break;
06617 
06618     default:
06619       fprintf(f, "ERROR: undefined anchor type.\n");
06620       break;
06621     }
06622     break;
06623 
06624   case NT_BREF:
06625     {
06626       int* p;
06627       BRefNode* br = NBREF(node);
06628       p = BACKREFS_P(br);
06629       fprintf(f, "<backref:%"PRIxPTR">", (intptr_t)node);
06630       for (i = 0; i < br->back_num; i++) {
06631         if (i > 0) fputs(", ", f);
06632         fprintf(f, "%d", p[i]);
06633       }
06634     }
06635     break;
06636 
06637 #ifdef USE_SUBEXP_CALL
06638   case NT_CALL:
06639     {
06640       CallNode* cn = NCALL(node);
06641       fprintf(f, "<call:%"PRIxPTR">", (intptr_t)node);
06642       p_string(f, cn->name_end - cn->name, cn->name);
06643     }
06644     break;
06645 #endif
06646 
06647   case NT_QTFR:
06648     fprintf(f, "<quantifier:%"PRIxPTR">{%d,%d}%s\n", (intptr_t)node,
06649             NQTFR(node)->lower, NQTFR(node)->upper,
06650             (NQTFR(node)->greedy ? "" : "?"));
06651     print_indent_tree(f, NQTFR(node)->target, indent + add);
06652     break;
06653 
06654   case NT_ENCLOSE:
06655     fprintf(f, "<enclose:%"PRIxPTR"> ", (intptr_t)node);
06656     switch (NENCLOSE(node)->type) {
06657     case ENCLOSE_OPTION:
06658       fprintf(f, "option:%d", NENCLOSE(node)->option);
06659       break;
06660     case ENCLOSE_MEMORY:
06661       fprintf(f, "memory:%d", NENCLOSE(node)->regnum);
06662       break;
06663     case ENCLOSE_STOP_BACKTRACK:
06664       fprintf(f, "stop-bt");
06665       break;
06666     case ENCLOSE_CONDITION:
06667       fprintf(f, "condition:%d", NENCLOSE(node)->regnum);
06668       break;
06669 
06670     default:
06671       break;
06672     }
06673     fprintf(f, "\n");
06674     print_indent_tree(f, NENCLOSE(node)->target, indent + add);
06675     break;
06676 
06677   default:
06678     fprintf(f, "print_indent_tree: undefined node type %d\n", NTYPE(node));
06679     break;
06680   }
06681 
06682   if (type != NT_LIST && type != NT_ALT && type != NT_QTFR &&
06683       type != NT_ENCLOSE)
06684     fprintf(f, "\n");
06685 
06686   if (container_p) print_indent_tree(f, NANCHOR(node)->target, indent + add);
06687 
06688   fflush(f);
06689 }
06690 #endif /* ONIG_DEBUG */
06691 
06692 #ifdef ONIG_DEBUG_PARSE_TREE
06693 static void
06694 print_tree(FILE* f, Node* node)
06695 {
06696   print_indent_tree(f, node, 0);
06697 }
06698 #endif
06699 

Generated on 19 Jul 2016 for Ruby by  doxygen 1.4.7