Annotation of embedaddon/php/ext/mbstring/oniguruma/regcomp.c, revision 1.1

1.1     ! misho       1: /**********************************************************************
        !             2:   regcomp.c -  Oniguruma (regular expression library)
        !             3: **********************************************************************/
        !             4: /*-
        !             5:  * Copyright (c) 2002-2007  K.Kosako  <sndgk393 AT ybb DOT ne DOT jp>
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  *
        !            17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
        !            18:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            19:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            20:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
        !            21:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            22:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            23:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            24:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            25:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            26:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            27:  * SUCH DAMAGE.
        !            28:  */
        !            29: 
        !            30: #include "regparse.h"
        !            31: 
        !            32: OnigAmbigType OnigDefaultAmbigFlag =
        !            33:   (ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE |
        !            34:    ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE);
        !            35: 
        !            36: extern OnigAmbigType
        !            37: onig_get_default_ambig_flag(void)
        !            38: {
        !            39:   return OnigDefaultAmbigFlag;
        !            40: }
        !            41: 
        !            42: extern int
        !            43: onig_set_default_ambig_flag(OnigAmbigType ambig_flag)
        !            44: {
        !            45:   OnigDefaultAmbigFlag = ambig_flag;
        !            46:   return 0;
        !            47: }
        !            48: 
        !            49: 
        !            50: static UChar*
        !            51: k_strdup(UChar* s, UChar* end)
        !            52: {
        !            53:   int len = end - s;
        !            54: 
        !            55:   if (len > 0) {
        !            56:     UChar* r = (UChar* )xmalloc(len + 1);
        !            57:     CHECK_NULL_RETURN(r);
        !            58:     xmemcpy(r, s, len);
        !            59:     r[len] = (UChar )0;
        !            60:     return r;
        !            61:   }
        !            62:   else return NULL;
        !            63: }
        !            64: 
        !            65: /*
        !            66:   Caution: node should not be a string node.
        !            67:            (s and end member address break)
        !            68: */
        !            69: static void
        !            70: swap_node(Node* a, Node* b)
        !            71: {
        !            72:   Node c;
        !            73:   c = *a; *a = *b; *b = c;
        !            74: }
        !            75: 
        !            76: static OnigDistance
        !            77: distance_add(OnigDistance d1, OnigDistance d2)
        !            78: {
        !            79:   if (d1 == ONIG_INFINITE_DISTANCE || d2 == ONIG_INFINITE_DISTANCE)
        !            80:     return ONIG_INFINITE_DISTANCE;
        !            81:   else {
        !            82:     if (d1 <= ONIG_INFINITE_DISTANCE - d2) return d1 + d2;
        !            83:     else return ONIG_INFINITE_DISTANCE;
        !            84:   }
        !            85: }
        !            86: 
        !            87: static OnigDistance
        !            88: distance_multiply(OnigDistance d, int m)
        !            89: {
        !            90:   if (m == 0) return 0;
        !            91: 
        !            92:   if (d < ONIG_INFINITE_DISTANCE / m)
        !            93:     return d * m;
        !            94:   else
        !            95:     return ONIG_INFINITE_DISTANCE;
        !            96: }
        !            97: 
        !            98: static int
        !            99: bitset_is_empty(BitSetRef bs)
        !           100: {
        !           101:   int i;
        !           102:   for (i = 0; i < BITSET_SIZE; i++) {
        !           103:     if (bs[i] != 0) return 0;
        !           104:   }
        !           105:   return 1;
        !           106: }
        !           107: 
        !           108: #ifdef ONIG_DEBUG
        !           109: static int
        !           110: bitset_on_num(BitSetRef bs)
        !           111: {
        !           112:   int i, n;
        !           113: 
        !           114:   n = 0;
        !           115:   for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
        !           116:     if (BITSET_AT(bs, i)) n++;
        !           117:   }
        !           118:   return n;
        !           119: }
        !           120: #endif
        !           121: 
        !           122: extern int
        !           123: onig_bbuf_init(BBuf* buf, int size)
        !           124: {
        !           125:   buf->p = (UChar* )xmalloc(size);
        !           126:   if (IS_NULL(buf->p)) return(ONIGERR_MEMORY);
        !           127: 
        !           128:   buf->alloc = size;
        !           129:   buf->used  = 0;
        !           130:   return 0;
        !           131: }
        !           132: 
        !           133: 
        !           134: #ifdef USE_SUBEXP_CALL
        !           135: 
        !           136: static int
        !           137: unset_addr_list_init(UnsetAddrList* uslist, int size)
        !           138: {
        !           139:   UnsetAddr* p;
        !           140: 
        !           141:   p = (UnsetAddr* )xmalloc(sizeof(UnsetAddr)* size);
        !           142:   CHECK_NULL_RETURN_VAL(p, ONIGERR_MEMORY);
        !           143:   uslist->num   = 0;
        !           144:   uslist->alloc = size;
        !           145:   uslist->us    = p;
        !           146:   return 0;
        !           147: }
        !           148: 
        !           149: static void
        !           150: unset_addr_list_end(UnsetAddrList* uslist)
        !           151: {
        !           152:   if (IS_NOT_NULL(uslist->us))
        !           153:     xfree(uslist->us);
        !           154: }
        !           155: 
        !           156: static int
        !           157: unset_addr_list_add(UnsetAddrList* uslist, int offset, struct _Node* node)
        !           158: {
        !           159:   UnsetAddr* p;
        !           160:   int size;
        !           161: 
        !           162:   if (uslist->num >= uslist->alloc) {
        !           163:     size = uslist->alloc * 2;
        !           164:     p = (UnsetAddr* )xrealloc(uslist->us, sizeof(UnsetAddr) * size);
        !           165:     CHECK_NULL_RETURN_VAL(p, ONIGERR_MEMORY);
        !           166:     uslist->alloc = size;
        !           167:     uslist->us    = p;
        !           168:   }
        !           169: 
        !           170:   uslist->us[uslist->num].offset = offset;
        !           171:   uslist->us[uslist->num].target = node;
        !           172:   uslist->num++;
        !           173:   return 0;
        !           174: }
        !           175: #endif /* USE_SUBEXP_CALL */
        !           176: 
        !           177: 
        !           178: static int
        !           179: add_opcode(regex_t* reg, int opcode)
        !           180: {
        !           181:   BBUF_ADD1(reg, opcode);
        !           182:   return 0;
        !           183: }
        !           184: 
        !           185: #ifdef USE_COMBINATION_EXPLOSION_CHECK
        !           186: static int
        !           187: add_state_check_num(regex_t* reg, int num)
        !           188: {
        !           189:   StateCheckNumType n = (StateCheckNumType )num;
        !           190: 
        !           191:   BBUF_ADD(reg, &n, SIZE_STATE_CHECK_NUM);
        !           192:   return 0;
        !           193: }
        !           194: #endif
        !           195: 
        !           196: static int
        !           197: add_rel_addr(regex_t* reg, int addr)
        !           198: {
        !           199:   RelAddrType ra = (RelAddrType )addr;
        !           200: 
        !           201:   BBUF_ADD(reg, &ra, SIZE_RELADDR);
        !           202:   return 0;
        !           203: }
        !           204: 
        !           205: static int
        !           206: add_abs_addr(regex_t* reg, int addr)
        !           207: {
        !           208:   AbsAddrType ra = (AbsAddrType )addr;
        !           209: 
        !           210:   BBUF_ADD(reg, &ra, SIZE_ABSADDR);
        !           211:   return 0;
        !           212: }
        !           213: 
        !           214: static int
        !           215: add_length(regex_t* reg, int len)
        !           216: {
        !           217:   LengthType l = (LengthType )len;
        !           218: 
        !           219:   BBUF_ADD(reg, &l, SIZE_LENGTH);
        !           220:   return 0;
        !           221: }
        !           222: 
        !           223: static int
        !           224: add_mem_num(regex_t* reg, int num)
        !           225: {
        !           226:   MemNumType n = (MemNumType )num;
        !           227: 
        !           228:   BBUF_ADD(reg, &n, SIZE_MEMNUM);
        !           229:   return 0;
        !           230: }
        !           231: 
        !           232: static int
        !           233: add_pointer(regex_t* reg, void* addr)
        !           234: {
        !           235:   PointerType ptr = (PointerType )addr;
        !           236: 
        !           237:   BBUF_ADD(reg, &ptr, SIZE_POINTER);
        !           238:   return 0;
        !           239: }
        !           240: 
        !           241: static int
        !           242: add_option(regex_t* reg, OnigOptionType option)
        !           243: {
        !           244:   BBUF_ADD(reg, &option, SIZE_OPTION);
        !           245:   return 0;
        !           246: }
        !           247: 
        !           248: static int
        !           249: add_opcode_rel_addr(regex_t* reg, int opcode, int addr)
        !           250: {
        !           251:   int r;
        !           252: 
        !           253:   r = add_opcode(reg, opcode);
        !           254:   if (r) return r;
        !           255:   r = add_rel_addr(reg, addr);
        !           256:   return r;
        !           257: }
        !           258: 
        !           259: static int
        !           260: add_bytes(regex_t* reg, UChar* bytes, int len)
        !           261: {
        !           262:   BBUF_ADD(reg, bytes, len);
        !           263:   return 0;
        !           264: }
        !           265: 
        !           266: static int
        !           267: add_bitset(regex_t* reg, BitSetRef bs)
        !           268: {
        !           269:   BBUF_ADD(reg, bs, SIZE_BITSET);
        !           270:   return 0;
        !           271: }
        !           272: 
        !           273: static int
        !           274: add_opcode_option(regex_t* reg, int opcode, OnigOptionType option)
        !           275: {
        !           276:   int r;
        !           277: 
        !           278:   r = add_opcode(reg, opcode);
        !           279:   if (r) return r;
        !           280:   r = add_option(reg, option);
        !           281:   return r;
        !           282: }
        !           283: 
        !           284: static int compile_length_tree(Node* node, regex_t* reg);
        !           285: static int compile_tree(Node* node, regex_t* reg);
        !           286: 
        !           287: 
        !           288: #define IS_NEED_STR_LEN_OP_EXACT(op) \
        !           289:    ((op) == OP_EXACTN    || (op) == OP_EXACTMB2N ||\
        !           290:     (op) == OP_EXACTMB3N || (op) == OP_EXACTMBN  || (op) == OP_EXACTN_IC)
        !           291: 
        !           292: static int
        !           293: select_str_opcode(int mb_len, int str_len, int ignore_case)
        !           294: {
        !           295:   int op;
        !           296: 
        !           297:   if (ignore_case) {
        !           298:     switch (str_len) {
        !           299:     case 1:  op = OP_EXACT1_IC; break;
        !           300:     default: op = OP_EXACTN_IC; break;
        !           301:     }
        !           302:   }
        !           303:   else {
        !           304:     switch (mb_len) {
        !           305:     case 1:
        !           306:       switch (str_len) {
        !           307:       case 1:  op = OP_EXACT1; break;
        !           308:       case 2:  op = OP_EXACT2; break;
        !           309:       case 3:  op = OP_EXACT3; break;
        !           310:       case 4:  op = OP_EXACT4; break;
        !           311:       case 5:  op = OP_EXACT5; break;
        !           312:       default: op = OP_EXACTN; break;
        !           313:       }
        !           314:       break;
        !           315: 
        !           316:     case 2:
        !           317:       switch (str_len) {
        !           318:       case 1:  op = OP_EXACTMB2N1; break;
        !           319:       case 2:  op = OP_EXACTMB2N2; break;
        !           320:       case 3:  op = OP_EXACTMB2N3; break;
        !           321:       default: op = OP_EXACTMB2N;  break;
        !           322:       }
        !           323:       break;
        !           324: 
        !           325:     case 3:
        !           326:       op = OP_EXACTMB3N;
        !           327:       break;
        !           328: 
        !           329:     default:
        !           330:       op = OP_EXACTMBN;
        !           331:       break;
        !           332:     }
        !           333:   }
        !           334:   return op;
        !           335: }
        !           336: 
        !           337: static int
        !           338: compile_tree_empty_check(Node* node, regex_t* reg, int empty_info)
        !           339: {
        !           340:   int r;
        !           341:   int saved_num_null_check = reg->num_null_check;
        !           342: 
        !           343:   if (empty_info != 0) {
        !           344:     r = add_opcode(reg, OP_NULL_CHECK_START);
        !           345:     if (r) return r;
        !           346:     r = add_mem_num(reg, reg->num_null_check); /* NULL CHECK ID */
        !           347:     if (r) return r;
        !           348:     reg->num_null_check++;
        !           349:   }
        !           350: 
        !           351:   r = compile_tree(node, reg);
        !           352:   if (r) return r;
        !           353: 
        !           354:   if (empty_info != 0) {
        !           355:     if (empty_info == NQ_TARGET_IS_EMPTY)
        !           356:       r = add_opcode(reg, OP_NULL_CHECK_END);
        !           357:     else if (empty_info == NQ_TARGET_IS_EMPTY_MEM)
        !           358:       r = add_opcode(reg, OP_NULL_CHECK_END_MEMST);
        !           359:     else if (empty_info == NQ_TARGET_IS_EMPTY_REC)
        !           360:       r = add_opcode(reg, OP_NULL_CHECK_END_MEMST_PUSH);
        !           361: 
        !           362:     if (r) return r;
        !           363:     r = add_mem_num(reg, saved_num_null_check); /* NULL CHECK ID */
        !           364:   }
        !           365:   return r;
        !           366: }
        !           367: 
        !           368: #ifdef USE_SUBEXP_CALL
        !           369: static int
        !           370: compile_call(CallNode* node, regex_t* reg)
        !           371: {
        !           372:   int r;
        !           373: 
        !           374:   r = add_opcode(reg, OP_CALL);
        !           375:   if (r) return r;
        !           376:   r = unset_addr_list_add(node->unset_addr_list, BBUF_GET_OFFSET_POS(reg),
        !           377:                           node->target);
        !           378:   if (r) return r;
        !           379:   r = add_abs_addr(reg, 0 /*dummy addr.*/);
        !           380:   return r;
        !           381: }
        !           382: #endif
        !           383: 
        !           384: static int
        !           385: compile_tree_n_times(Node* node, int n, regex_t* reg)
        !           386: {
        !           387:   int i, r;
        !           388: 
        !           389:   for (i = 0; i < n; i++) {
        !           390:     r = compile_tree(node, reg);
        !           391:     if (r) return r;
        !           392:   }
        !           393:   return 0;
        !           394: }
        !           395: 
        !           396: static int
        !           397: add_compile_string_length(UChar* s, int mb_len, int str_len,
        !           398:                           regex_t* reg, int ignore_case)
        !           399: {
        !           400:   int len;
        !           401:   int op = select_str_opcode(mb_len, str_len, ignore_case);
        !           402: 
        !           403:   len = SIZE_OPCODE;
        !           404: 
        !           405:   if (op == OP_EXACTMBN)  len += SIZE_LENGTH;
        !           406:   if (IS_NEED_STR_LEN_OP_EXACT(op))
        !           407:     len += SIZE_LENGTH;
        !           408: 
        !           409:   len += mb_len * str_len;
        !           410:   return len;
        !           411: }
        !           412: 
        !           413: static int
        !           414: add_compile_string(UChar* s, int mb_len, int str_len,
        !           415:                    regex_t* reg, int ignore_case)
        !           416: {
        !           417:   int op = select_str_opcode(mb_len, str_len, ignore_case);
        !           418:   add_opcode(reg, op);
        !           419: 
        !           420:   if (op == OP_EXACTMBN)
        !           421:     add_length(reg, mb_len);
        !           422: 
        !           423:   if (IS_NEED_STR_LEN_OP_EXACT(op)) {
        !           424:     if (op == OP_EXACTN_IC)
        !           425:       add_length(reg, mb_len * str_len);
        !           426:     else
        !           427:       add_length(reg, str_len);
        !           428:   }
        !           429: 
        !           430:   add_bytes(reg, s, mb_len * str_len);
        !           431:   return 0;
        !           432: }
        !           433: 
        !           434: 
        !           435: static int
        !           436: compile_length_string_node(Node* node, regex_t* reg)
        !           437: {
        !           438:   int rlen, r, len, prev_len, slen, ambig;
        !           439:   OnigEncoding enc = reg->enc;
        !           440:   UChar *p, *prev;
        !           441:   StrNode* sn;
        !           442: 
        !           443:   sn = &(NSTRING(node));
        !           444:   if (sn->end <= sn->s)
        !           445:     return 0;
        !           446: 
        !           447:   ambig = NSTRING_IS_AMBIG(node);
        !           448: 
        !           449:   p = prev = sn->s;
        !           450:   prev_len = enc_len(enc, p);
        !           451:   p += prev_len;
        !           452:   slen = 1;
        !           453:   rlen = 0;
        !           454: 
        !           455:   for (; p < sn->end; ) {
        !           456:     len = enc_len(enc, p);
        !           457:     if (len == prev_len) {
        !           458:       slen++;
        !           459:     }
        !           460:     else {
        !           461:       r = add_compile_string_length(prev, prev_len, slen, reg, ambig);
        !           462:       rlen += r;
        !           463:       prev = p;
        !           464:       slen = 1;
        !           465:       prev_len = len;
        !           466:     }
        !           467:     p += len;
        !           468:   }
        !           469:   r = add_compile_string_length(prev, prev_len, slen, reg, ambig);
        !           470:   rlen += r;
        !           471:   return rlen;
        !           472: }
        !           473: 
        !           474: static int
        !           475: compile_length_string_raw_node(StrNode* sn, regex_t* reg)
        !           476: {
        !           477:   if (sn->end <= sn->s)
        !           478:     return 0;
        !           479: 
        !           480:   return add_compile_string_length(sn->s, 1 /* sb */, sn->end - sn->s, reg, 0);
        !           481: }
        !           482: 
        !           483: static int
        !           484: compile_string_node(Node* node, regex_t* reg)
        !           485: {
        !           486:   int r, len, prev_len, slen, ambig;
        !           487:   OnigEncoding enc = reg->enc;
        !           488:   UChar *p, *prev, *end;
        !           489:   StrNode* sn;
        !           490: 
        !           491:   sn = &(NSTRING(node));
        !           492:   if (sn->end <= sn->s)
        !           493:     return 0;
        !           494: 
        !           495:   end = sn->end;
        !           496:   ambig = NSTRING_IS_AMBIG(node);
        !           497: 
        !           498:   p = prev = sn->s;
        !           499:   prev_len = enc_len(enc, p);
        !           500:   p += prev_len;
        !           501:   slen = 1;
        !           502: 
        !           503:   for (; p < end; ) {
        !           504:     len = enc_len(enc, p);
        !           505:     if (len == prev_len) {
        !           506:       slen++;
        !           507:     }
        !           508:     else {
        !           509:       r = add_compile_string(prev, prev_len, slen, reg, ambig);
        !           510:       if (r) return r;
        !           511: 
        !           512:       prev  = p;
        !           513:       slen  = 1;
        !           514:       prev_len = len;
        !           515:     }
        !           516: 
        !           517:     p += len;
        !           518:   }
        !           519:   return add_compile_string(prev, prev_len, slen, reg, ambig);
        !           520: }
        !           521: 
        !           522: static int
        !           523: compile_string_raw_node(StrNode* sn, regex_t* reg)
        !           524: {
        !           525:   if (sn->end <= sn->s)
        !           526:     return 0;
        !           527: 
        !           528:   return add_compile_string(sn->s, 1 /* sb */, sn->end - sn->s, reg, 0);
        !           529: }
        !           530: 
        !           531: static int
        !           532: add_multi_byte_cclass(BBuf* mbuf, regex_t* reg)
        !           533: {
        !           534: #ifdef PLATFORM_UNALIGNED_WORD_ACCESS
        !           535:   add_length(reg, mbuf->used);
        !           536:   return add_bytes(reg, mbuf->p, mbuf->used);
        !           537: #else
        !           538:   static unsigned char PadBuf[WORD_ALIGNMENT_SIZE];
        !           539: 
        !           540:   int r, pad_size;
        !           541:   UChar* p = BBUF_GET_ADD_ADDRESS(reg) + SIZE_LENGTH;
        !           542: 
        !           543:   GET_ALIGNMENT_PAD_SIZE(p, pad_size);
        !           544:   add_length(reg, mbuf->used + (WORD_ALIGNMENT_SIZE - 1));
        !           545:   if (pad_size != 0) add_bytes(reg, PadBuf, pad_size);
        !           546: 
        !           547:   r = add_bytes(reg, mbuf->p, mbuf->used);
        !           548: 
        !           549:   /* padding for return value from compile_length_cclass_node() to be fix. */
        !           550:   pad_size = (WORD_ALIGNMENT_SIZE - 1) - pad_size;
        !           551:   if (pad_size != 0) add_bytes(reg, PadBuf, pad_size);
        !           552:   return r;
        !           553: #endif
        !           554: }
        !           555: 
        !           556: static int
        !           557: compile_length_cclass_node(CClassNode* cc, regex_t* reg)
        !           558: {
        !           559:   int len;
        !           560: 
        !           561:   if (IS_CCLASS_SHARE(cc)) {
        !           562:     len = SIZE_OPCODE + SIZE_POINTER;
        !           563:     return len;
        !           564:   }
        !           565: 
        !           566:   if (IS_NULL(cc->mbuf)) {
        !           567:     len = SIZE_OPCODE + SIZE_BITSET;
        !           568:   }
        !           569:   else {
        !           570:     if (ONIGENC_MBC_MINLEN(reg->enc) > 1 || bitset_is_empty(cc->bs)) {
        !           571:       len = SIZE_OPCODE;
        !           572:     }
        !           573:     else {
        !           574:       len = SIZE_OPCODE + SIZE_BITSET;
        !           575:     }
        !           576: #ifdef PLATFORM_UNALIGNED_WORD_ACCESS
        !           577:     len += SIZE_LENGTH + cc->mbuf->used;
        !           578: #else
        !           579:     len += SIZE_LENGTH + cc->mbuf->used + (WORD_ALIGNMENT_SIZE - 1);
        !           580: #endif
        !           581:   }
        !           582: 
        !           583:   return len;
        !           584: }
        !           585: 
        !           586: static int
        !           587: compile_cclass_node(CClassNode* cc, regex_t* reg)
        !           588: {
        !           589:   int r;
        !           590: 
        !           591:   if (IS_CCLASS_SHARE(cc)) {
        !           592:     add_opcode(reg, OP_CCLASS_NODE);
        !           593:     r = add_pointer(reg, cc);
        !           594:     return r;
        !           595:   }
        !           596: 
        !           597:   if (IS_NULL(cc->mbuf)) {
        !           598:     if (IS_CCLASS_NOT(cc))
        !           599:       add_opcode(reg, OP_CCLASS_NOT);
        !           600:     else
        !           601:       add_opcode(reg, OP_CCLASS);
        !           602: 
        !           603:     r = add_bitset(reg, cc->bs);
        !           604:   }
        !           605:   else {
        !           606:     if (ONIGENC_MBC_MINLEN(reg->enc) > 1 || bitset_is_empty(cc->bs)) {
        !           607:       if (IS_CCLASS_NOT(cc))
        !           608:         add_opcode(reg, OP_CCLASS_MB_NOT);
        !           609:       else
        !           610:         add_opcode(reg, OP_CCLASS_MB);
        !           611: 
        !           612:       r = add_multi_byte_cclass(cc->mbuf, reg);
        !           613:     }
        !           614:     else {
        !           615:       if (IS_CCLASS_NOT(cc))
        !           616:         add_opcode(reg, OP_CCLASS_MIX_NOT);
        !           617:       else
        !           618:         add_opcode(reg, OP_CCLASS_MIX);
        !           619: 
        !           620:       r = add_bitset(reg, cc->bs);
        !           621:       if (r) return r;
        !           622:       r = add_multi_byte_cclass(cc->mbuf, reg);
        !           623:     }
        !           624:   }
        !           625: 
        !           626:   return r;
        !           627: }
        !           628: 
        !           629: static int
        !           630: entry_repeat_range(regex_t* reg, int id, int lower, int upper)
        !           631: {
        !           632: #define REPEAT_RANGE_ALLOC  4
        !           633: 
        !           634:   OnigRepeatRange* p;
        !           635: 
        !           636:   if (reg->repeat_range_alloc == 0) {
        !           637:     p = (OnigRepeatRange* )xmalloc(sizeof(OnigRepeatRange) * REPEAT_RANGE_ALLOC);
        !           638:     CHECK_NULL_RETURN_VAL(p, ONIGERR_MEMORY);
        !           639:     reg->repeat_range = p;
        !           640:     reg->repeat_range_alloc = REPEAT_RANGE_ALLOC;
        !           641:   }
        !           642:   else if (reg->repeat_range_alloc <= id) {
        !           643:     int n;
        !           644:     n = reg->repeat_range_alloc + REPEAT_RANGE_ALLOC;
        !           645:     p = (OnigRepeatRange* )xrealloc(reg->repeat_range,
        !           646:                                     sizeof(OnigRepeatRange) * n);
        !           647:     CHECK_NULL_RETURN_VAL(p, ONIGERR_MEMORY);
        !           648:     reg->repeat_range = p;
        !           649:     reg->repeat_range_alloc = n;
        !           650:   }
        !           651:   else {
        !           652:     p = reg->repeat_range;
        !           653:   }
        !           654: 
        !           655:   p[id].lower = lower;
        !           656:   p[id].upper = (IS_REPEAT_INFINITE(upper) ? 0x7fffffff : upper);
        !           657:   return 0;
        !           658: }
        !           659: 
        !           660: static int
        !           661: compile_range_repeat_node(QuantifierNode* qn, int target_len, int empty_info,
        !           662:                           regex_t* reg)
        !           663: {
        !           664:   int r;
        !           665:   int num_repeat = reg->num_repeat;
        !           666: 
        !           667:   r = add_opcode(reg, qn->greedy ? OP_REPEAT : OP_REPEAT_NG);
        !           668:   if (r) return r;
        !           669:   r = add_mem_num(reg, num_repeat); /* OP_REPEAT ID */
        !           670:   reg->num_repeat++;
        !           671:   if (r) return r;
        !           672:   r = add_rel_addr(reg, target_len + SIZE_OP_REPEAT_INC);
        !           673:   if (r) return r;
        !           674: 
        !           675:   r = entry_repeat_range(reg, num_repeat, qn->lower, qn->upper);
        !           676:   if (r) return r;
        !           677: 
        !           678:   r = compile_tree_empty_check(qn->target, reg, empty_info);
        !           679:   if (r) return r;
        !           680: 
        !           681:   if (
        !           682: #ifdef USE_SUBEXP_CALL
        !           683:       reg->num_call > 0 ||
        !           684: #endif
        !           685:       IS_QUANTIFIER_IN_REPEAT(qn)) {
        !           686:     r = add_opcode(reg, qn->greedy ? OP_REPEAT_INC_SG : OP_REPEAT_INC_NG_SG);
        !           687:   }
        !           688:   else {
        !           689:     r = add_opcode(reg, qn->greedy ? OP_REPEAT_INC : OP_REPEAT_INC_NG);
        !           690:   }
        !           691:   if (r) return r;
        !           692:   r = add_mem_num(reg, num_repeat); /* OP_REPEAT ID */
        !           693:   return r;
        !           694: }
        !           695: 
        !           696: static int
        !           697: is_anychar_star_quantifier(QuantifierNode* qn)
        !           698: {
        !           699:   if (qn->greedy && IS_REPEAT_INFINITE(qn->upper) &&
        !           700:       NTYPE(qn->target) == N_ANYCHAR)
        !           701:     return 1;
        !           702:   else
        !           703:     return 0;
        !           704: }
        !           705: 
        !           706: #define QUANTIFIER_EXPAND_LIMIT_SIZE   50
        !           707: #define CKN_ON   (ckn > 0)
        !           708: 
        !           709: #ifdef USE_COMBINATION_EXPLOSION_CHECK
        !           710: 
        !           711: static int
        !           712: compile_length_quantifier_node(QuantifierNode* qn, regex_t* reg)
        !           713: {
        !           714:   int len, mod_tlen, cklen;
        !           715:   int ckn;
        !           716:   int infinite = IS_REPEAT_INFINITE(qn->upper);
        !           717:   int empty_info = qn->target_empty_info;
        !           718:   int tlen = compile_length_tree(qn->target, reg);
        !           719: 
        !           720:   if (tlen < 0) return tlen;
        !           721: 
        !           722:   ckn = ((reg->num_comb_exp_check > 0) ? qn->comb_exp_check_num : 0);
        !           723: 
        !           724:   cklen = (CKN_ON ? SIZE_STATE_CHECK_NUM: 0);
        !           725: 
        !           726:   /* anychar repeat */
        !           727:   if (NTYPE(qn->target) == N_ANYCHAR) {
        !           728:     if (qn->greedy && infinite) {
        !           729:       if (IS_NOT_NULL(qn->next_head_exact) && !CKN_ON)
        !           730:         return SIZE_OP_ANYCHAR_STAR_PEEK_NEXT + tlen * qn->lower + cklen;
        !           731:       else
        !           732:         return SIZE_OP_ANYCHAR_STAR + tlen * qn->lower + cklen;
        !           733:     }
        !           734:   }
        !           735: 
        !           736:   if (empty_info != 0)
        !           737:     mod_tlen = tlen + (SIZE_OP_NULL_CHECK_START + SIZE_OP_NULL_CHECK_END);
        !           738:   else
        !           739:     mod_tlen = tlen;
        !           740: 
        !           741:   if (infinite && qn->lower <= 1) {
        !           742:     if (qn->greedy) {
        !           743:       if (qn->lower == 1)
        !           744:        len = SIZE_OP_JUMP;
        !           745:       else
        !           746:        len = 0;
        !           747: 
        !           748:       len += SIZE_OP_PUSH + cklen + mod_tlen + SIZE_OP_JUMP;
        !           749:     }
        !           750:     else {
        !           751:       if (qn->lower == 0)
        !           752:        len = SIZE_OP_JUMP;
        !           753:       else
        !           754:        len = 0;
        !           755: 
        !           756:       len += mod_tlen + SIZE_OP_PUSH + cklen;
        !           757:     }
        !           758:   }
        !           759:   else if (qn->upper == 0) {
        !           760:     if (qn->is_refered != 0) /* /(?<n>..){0}/ */
        !           761:       len = SIZE_OP_JUMP + tlen;
        !           762:     else
        !           763:       len = 0;
        !           764:   }
        !           765:   else if (qn->upper == 1 && qn->greedy) {
        !           766:     if (qn->lower == 0) {
        !           767:       if (CKN_ON) {
        !           768:        len = SIZE_OP_STATE_CHECK_PUSH + tlen;
        !           769:       }
        !           770:       else {
        !           771:        len = SIZE_OP_PUSH + tlen;
        !           772:       }
        !           773:     }
        !           774:     else {
        !           775:       len = tlen;
        !           776:     }
        !           777:   }
        !           778:   else if (!qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */
        !           779:     len = SIZE_OP_PUSH + cklen + SIZE_OP_JUMP + tlen;
        !           780:   }
        !           781:   else {
        !           782:     len = SIZE_OP_REPEAT_INC
        !           783:         + mod_tlen + SIZE_OPCODE + SIZE_RELADDR + SIZE_MEMNUM;
        !           784:     if (CKN_ON)
        !           785:       len += SIZE_OP_STATE_CHECK;
        !           786:   }
        !           787: 
        !           788:   return len;
        !           789: }
        !           790: 
        !           791: static int
        !           792: compile_quantifier_node(QuantifierNode* qn, regex_t* reg)
        !           793: {
        !           794:   int r, mod_tlen;
        !           795:   int ckn;
        !           796:   int infinite = IS_REPEAT_INFINITE(qn->upper);
        !           797:   int empty_info = qn->target_empty_info;
        !           798:   int tlen = compile_length_tree(qn->target, reg);
        !           799: 
        !           800:   if (tlen < 0) return tlen;
        !           801: 
        !           802:   ckn = ((reg->num_comb_exp_check > 0) ? qn->comb_exp_check_num : 0);
        !           803: 
        !           804:   if (is_anychar_star_quantifier(qn)) {
        !           805:     r = compile_tree_n_times(qn->target, qn->lower, reg);
        !           806:     if (r) return r;
        !           807:     if (IS_NOT_NULL(qn->next_head_exact) && !CKN_ON) {
        !           808:       if (IS_MULTILINE(reg->options))
        !           809:        r = add_opcode(reg, OP_ANYCHAR_ML_STAR_PEEK_NEXT);
        !           810:       else
        !           811:        r = add_opcode(reg, OP_ANYCHAR_STAR_PEEK_NEXT);
        !           812:       if (r) return r;
        !           813:       if (CKN_ON) {
        !           814:        r = add_state_check_num(reg, ckn);
        !           815:        if (r) return r;
        !           816:       }
        !           817: 
        !           818:       return add_bytes(reg, NSTRING(qn->next_head_exact).s, 1);
        !           819:     }
        !           820:     else {
        !           821:       if (IS_MULTILINE(reg->options)) {
        !           822:        r = add_opcode(reg, (CKN_ON ?
        !           823:                               OP_STATE_CHECK_ANYCHAR_ML_STAR
        !           824:                             : OP_ANYCHAR_ML_STAR));
        !           825:       }
        !           826:       else {
        !           827:        r = add_opcode(reg, (CKN_ON ?
        !           828:                               OP_STATE_CHECK_ANYCHAR_STAR
        !           829:                             : OP_ANYCHAR_STAR));
        !           830:       }
        !           831:       if (r) return r;
        !           832:       if (CKN_ON)
        !           833:        r = add_state_check_num(reg, ckn);
        !           834: 
        !           835:       return r;
        !           836:     }
        !           837:   }
        !           838: 
        !           839:   if (empty_info != 0)
        !           840:     mod_tlen = tlen + (SIZE_OP_NULL_CHECK_START + SIZE_OP_NULL_CHECK_END);
        !           841:   else
        !           842:     mod_tlen = tlen;
        !           843: 
        !           844:   if (infinite && qn->lower <= 1) {
        !           845:     if (qn->greedy) {
        !           846:       if (qn->lower == 1) {
        !           847:        r = add_opcode_rel_addr(reg, OP_JUMP,
        !           848:                        (CKN_ON ? SIZE_OP_STATE_CHECK_PUSH : SIZE_OP_PUSH));
        !           849:        if (r) return r;
        !           850:       }
        !           851: 
        !           852:       if (CKN_ON) {
        !           853:        r = add_opcode(reg, OP_STATE_CHECK_PUSH);
        !           854:        if (r) return r;
        !           855:        r = add_state_check_num(reg, ckn);
        !           856:        if (r) return r;
        !           857:        r = add_rel_addr(reg, mod_tlen + SIZE_OP_JUMP);
        !           858:       }
        !           859:       else {
        !           860:        r = add_opcode_rel_addr(reg, OP_PUSH, mod_tlen + SIZE_OP_JUMP);
        !           861:       }
        !           862:       if (r) return r;
        !           863:       r = compile_tree_empty_check(qn->target, reg, empty_info);
        !           864:       if (r) return r;
        !           865:       r = add_opcode_rel_addr(reg, OP_JUMP,
        !           866:              -(mod_tlen + (int )SIZE_OP_JUMP
        !           867:                + (int )(CKN_ON ? SIZE_OP_STATE_CHECK_PUSH : SIZE_OP_PUSH)));
        !           868:     }
        !           869:     else {
        !           870:       if (qn->lower == 0) {
        !           871:        r = add_opcode_rel_addr(reg, OP_JUMP, mod_tlen);
        !           872:        if (r) return r;
        !           873:       }
        !           874:       r = compile_tree_empty_check(qn->target, reg, empty_info);
        !           875:       if (r) return r;
        !           876:       if (CKN_ON) {
        !           877:        r = add_opcode(reg, OP_STATE_CHECK_PUSH_OR_JUMP);
        !           878:        if (r) return r;
        !           879:        r = add_state_check_num(reg, ckn);
        !           880:        if (r) return r;
        !           881:        r = add_rel_addr(reg,
        !           882:                 -(mod_tlen + (int )SIZE_OP_STATE_CHECK_PUSH_OR_JUMP));
        !           883:       }
        !           884:       else
        !           885:        r = add_opcode_rel_addr(reg, OP_PUSH, -(mod_tlen + (int )SIZE_OP_PUSH));
        !           886:     }
        !           887:   }
        !           888:   else if (qn->upper == 0) {
        !           889:     if (qn->is_refered != 0) { /* /(?<n>..){0}/ */
        !           890:       r = add_opcode_rel_addr(reg, OP_JUMP, tlen);
        !           891:       if (r) return r;
        !           892:       r = compile_tree(qn->target, reg);
        !           893:     }
        !           894:     else
        !           895:       r = 0;
        !           896:   }
        !           897:   else if (qn->upper == 1 && qn->greedy) {
        !           898:     if (qn->lower == 0) {
        !           899:       if (CKN_ON) {
        !           900:        r = add_opcode(reg, OP_STATE_CHECK_PUSH);
        !           901:        if (r) return r;
        !           902:        r = add_state_check_num(reg, ckn);
        !           903:        if (r) return r;
        !           904:        r = add_rel_addr(reg, tlen);
        !           905:       }
        !           906:       else {
        !           907:        r = add_opcode_rel_addr(reg, OP_PUSH, tlen);
        !           908:       }
        !           909:       if (r) return r;
        !           910:     }
        !           911: 
        !           912:     r = compile_tree(qn->target, reg);
        !           913:   }
        !           914:   else if (!qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */
        !           915:     if (CKN_ON) {
        !           916:       r = add_opcode(reg, OP_STATE_CHECK_PUSH);
        !           917:       if (r) return r;
        !           918:       r = add_state_check_num(reg, ckn);
        !           919:       if (r) return r;
        !           920:       r = add_rel_addr(reg, SIZE_OP_JUMP);
        !           921:     }
        !           922:     else {
        !           923:       r = add_opcode_rel_addr(reg, OP_PUSH, SIZE_OP_JUMP);
        !           924:     }
        !           925: 
        !           926:     if (r) return r;
        !           927:     r = add_opcode_rel_addr(reg, OP_JUMP, tlen);
        !           928:     if (r) return r;
        !           929:     r = compile_tree(qn->target, reg);
        !           930:   }
        !           931:   else {
        !           932:     r = compile_range_repeat_node(qn, mod_tlen, empty_info, reg);
        !           933:     if (CKN_ON) {
        !           934:       if (r) return r;
        !           935:       r = add_opcode(reg, OP_STATE_CHECK);
        !           936:       if (r) return r;
        !           937:       r = add_state_check_num(reg, ckn);
        !           938:     }
        !           939:   }
        !           940:   return r;
        !           941: }
        !           942: 
        !           943: #else /* USE_COMBINATION_EXPLOSION_CHECK */
        !           944: 
        !           945: static int
        !           946: compile_length_quantifier_node(QuantifierNode* qn, regex_t* reg)
        !           947: {
        !           948:   int len, mod_tlen;
        !           949:   int infinite = IS_REPEAT_INFINITE(qn->upper);
        !           950:   int empty_info = qn->target_empty_info;
        !           951:   int tlen = compile_length_tree(qn->target, reg);
        !           952: 
        !           953:   if (tlen < 0) return tlen;
        !           954: 
        !           955:   /* anychar repeat */
        !           956:   if (NTYPE(qn->target) == N_ANYCHAR) {
        !           957:     if (qn->greedy && infinite) {
        !           958:       if (IS_NOT_NULL(qn->next_head_exact))
        !           959:         return SIZE_OP_ANYCHAR_STAR_PEEK_NEXT + tlen * qn->lower;
        !           960:       else
        !           961:         return SIZE_OP_ANYCHAR_STAR + tlen * qn->lower;
        !           962:     }
        !           963:   }
        !           964: 
        !           965:   if (empty_info != 0)
        !           966:     mod_tlen = tlen + (SIZE_OP_NULL_CHECK_START + SIZE_OP_NULL_CHECK_END);
        !           967:   else
        !           968:     mod_tlen = tlen;
        !           969: 
        !           970:   if (infinite &&
        !           971:       (qn->lower <= 1 || tlen * qn->lower <= QUANTIFIER_EXPAND_LIMIT_SIZE)) {
        !           972:     if (qn->lower == 1 && tlen > QUANTIFIER_EXPAND_LIMIT_SIZE) {
        !           973:       len = SIZE_OP_JUMP;
        !           974:     }
        !           975:     else {
        !           976:       len = tlen * qn->lower;
        !           977:     }
        !           978: 
        !           979:     if (qn->greedy) {
        !           980:       if (IS_NOT_NULL(qn->head_exact))
        !           981:        len += SIZE_OP_PUSH_OR_JUMP_EXACT1 + mod_tlen + SIZE_OP_JUMP;
        !           982:       else if (IS_NOT_NULL(qn->next_head_exact))
        !           983:        len += SIZE_OP_PUSH_IF_PEEK_NEXT + mod_tlen + SIZE_OP_JUMP;
        !           984:       else
        !           985:        len += SIZE_OP_PUSH + mod_tlen + SIZE_OP_JUMP;
        !           986:     }
        !           987:     else
        !           988:       len += SIZE_OP_JUMP + mod_tlen + SIZE_OP_PUSH;
        !           989:   }
        !           990:   else if (qn->upper == 0 && qn->is_refered != 0) { /* /(?<n>..){0}/ */
        !           991:     len = SIZE_OP_JUMP + tlen;
        !           992:   }
        !           993:   else if (!infinite && qn->greedy &&
        !           994:            (qn->upper == 1 || (tlen + SIZE_OP_PUSH) * qn->upper
        !           995:                                       <= QUANTIFIER_EXPAND_LIMIT_SIZE)) {
        !           996:     len = tlen * qn->lower;
        !           997:     len += (SIZE_OP_PUSH + tlen) * (qn->upper - qn->lower);
        !           998:   }
        !           999:   else if (!qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */
        !          1000:     len = SIZE_OP_PUSH + SIZE_OP_JUMP + tlen;
        !          1001:   }
        !          1002:   else {
        !          1003:     len = SIZE_OP_REPEAT_INC
        !          1004:         + mod_tlen + SIZE_OPCODE + SIZE_RELADDR + SIZE_MEMNUM;
        !          1005:   }
        !          1006: 
        !          1007:   return len;
        !          1008: }
        !          1009: 
        !          1010: static int
        !          1011: compile_quantifier_node(QuantifierNode* qn, regex_t* reg)
        !          1012: {
        !          1013:   int i, r, mod_tlen;
        !          1014:   int infinite = IS_REPEAT_INFINITE(qn->upper);
        !          1015:   int empty_info = qn->target_empty_info;
        !          1016:   int tlen = compile_length_tree(qn->target, reg);
        !          1017: 
        !          1018:   if (tlen < 0) return tlen;
        !          1019: 
        !          1020:   if (is_anychar_star_quantifier(qn)) {
        !          1021:     r = compile_tree_n_times(qn->target, qn->lower, reg);
        !          1022:     if (r) return r;
        !          1023:     if (IS_NOT_NULL(qn->next_head_exact)) {
        !          1024:       if (IS_MULTILINE(reg->options))
        !          1025:        r = add_opcode(reg, OP_ANYCHAR_ML_STAR_PEEK_NEXT);
        !          1026:       else
        !          1027:        r = add_opcode(reg, OP_ANYCHAR_STAR_PEEK_NEXT);
        !          1028:       if (r) return r;
        !          1029:       return add_bytes(reg, NSTRING(qn->next_head_exact).s, 1);
        !          1030:     }
        !          1031:     else {
        !          1032:       if (IS_MULTILINE(reg->options))
        !          1033:        return add_opcode(reg, OP_ANYCHAR_ML_STAR);
        !          1034:       else
        !          1035:        return add_opcode(reg, OP_ANYCHAR_STAR);
        !          1036:     }
        !          1037:   }
        !          1038: 
        !          1039:   if (empty_info != 0)
        !          1040:     mod_tlen = tlen + (SIZE_OP_NULL_CHECK_START + SIZE_OP_NULL_CHECK_END);
        !          1041:   else
        !          1042:     mod_tlen = tlen;
        !          1043: 
        !          1044:   if (infinite &&
        !          1045:       (qn->lower <= 1 || tlen * qn->lower <= QUANTIFIER_EXPAND_LIMIT_SIZE)) {
        !          1046:     if (qn->lower == 1 && tlen > QUANTIFIER_EXPAND_LIMIT_SIZE) {
        !          1047:       if (qn->greedy) {
        !          1048:        if (IS_NOT_NULL(qn->head_exact))
        !          1049:          r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH_OR_JUMP_EXACT1);
        !          1050:        else if (IS_NOT_NULL(qn->next_head_exact))
        !          1051:          r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH_IF_PEEK_NEXT);
        !          1052:        else
        !          1053:          r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH);
        !          1054:       }
        !          1055:       else {
        !          1056:        r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_JUMP);
        !          1057:       }
        !          1058:       if (r) return r;
        !          1059:     }
        !          1060:     else {
        !          1061:       r = compile_tree_n_times(qn->target, qn->lower, reg);
        !          1062:       if (r) return r;
        !          1063:     }
        !          1064: 
        !          1065:     if (qn->greedy) {
        !          1066:       if (IS_NOT_NULL(qn->head_exact)) {
        !          1067:        r = add_opcode_rel_addr(reg, OP_PUSH_OR_JUMP_EXACT1,
        !          1068:                             mod_tlen + SIZE_OP_JUMP);
        !          1069:        if (r) return r;
        !          1070:        add_bytes(reg, NSTRING(qn->head_exact).s, 1);
        !          1071:        r = compile_tree_empty_check(qn->target, reg, empty_info);
        !          1072:        if (r) return r;
        !          1073:        r = add_opcode_rel_addr(reg, OP_JUMP,
        !          1074:        -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH_OR_JUMP_EXACT1));
        !          1075:       }
        !          1076:       else if (IS_NOT_NULL(qn->next_head_exact)) {
        !          1077:        r = add_opcode_rel_addr(reg, OP_PUSH_IF_PEEK_NEXT,
        !          1078:                                mod_tlen + SIZE_OP_JUMP);
        !          1079:        if (r) return r;
        !          1080:        add_bytes(reg, NSTRING(qn->next_head_exact).s, 1);
        !          1081:        r = compile_tree_empty_check(qn->target, reg, empty_info);
        !          1082:        if (r) return r;
        !          1083:        r = add_opcode_rel_addr(reg, OP_JUMP,
        !          1084:           -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH_IF_PEEK_NEXT));
        !          1085:       }
        !          1086:       else {
        !          1087:        r = add_opcode_rel_addr(reg, OP_PUSH, mod_tlen + SIZE_OP_JUMP);
        !          1088:        if (r) return r;
        !          1089:        r = compile_tree_empty_check(qn->target, reg, empty_info);
        !          1090:        if (r) return r;
        !          1091:        r = add_opcode_rel_addr(reg, OP_JUMP,
        !          1092:                     -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH));
        !          1093:       }
        !          1094:     }
        !          1095:     else {
        !          1096:       r = add_opcode_rel_addr(reg, OP_JUMP, mod_tlen);
        !          1097:       if (r) return r;
        !          1098:       r = compile_tree_empty_check(qn->target, reg, empty_info);
        !          1099:       if (r) return r;
        !          1100:       r = add_opcode_rel_addr(reg, OP_PUSH, -(mod_tlen + (int )SIZE_OP_PUSH));
        !          1101:     }
        !          1102:   }
        !          1103:   else if (qn->upper == 0 && qn->is_refered != 0) { /* /(?<n>..){0}/ */
        !          1104:     r = add_opcode_rel_addr(reg, OP_JUMP, tlen);
        !          1105:     if (r) return r;
        !          1106:     r = compile_tree(qn->target, reg);
        !          1107:   }
        !          1108:   else if (!infinite && qn->greedy &&
        !          1109:            (qn->upper == 1 || (tlen + SIZE_OP_PUSH) * qn->upper
        !          1110:                                   <= QUANTIFIER_EXPAND_LIMIT_SIZE)) {
        !          1111:     int n = qn->upper - qn->lower;
        !          1112: 
        !          1113:     r = compile_tree_n_times(qn->target, qn->lower, reg);
        !          1114:     if (r) return r;
        !          1115: 
        !          1116:     for (i = 0; i < n; i++) {
        !          1117:       r = add_opcode_rel_addr(reg, OP_PUSH,
        !          1118:                           (n - i) * tlen + (n - i - 1) * SIZE_OP_PUSH);
        !          1119:       if (r) return r;
        !          1120:       r = compile_tree(qn->target, reg);
        !          1121:       if (r) return r;
        !          1122:     }
        !          1123:   }
        !          1124:   else if (!qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */
        !          1125:     r = add_opcode_rel_addr(reg, OP_PUSH, SIZE_OP_JUMP);
        !          1126:     if (r) return r;
        !          1127:     r = add_opcode_rel_addr(reg, OP_JUMP, tlen);
        !          1128:     if (r) return r;
        !          1129:     r = compile_tree(qn->target, reg);
        !          1130:   }
        !          1131:   else {
        !          1132:     r = compile_range_repeat_node(qn, mod_tlen, empty_info, reg);
        !          1133:   }
        !          1134:   return r;
        !          1135: }
        !          1136: #endif /* USE_COMBINATION_EXPLOSION_CHECK */
        !          1137: 
        !          1138: static int
        !          1139: compile_length_option_node(EffectNode* node, regex_t* reg)
        !          1140: {
        !          1141:   int tlen;
        !          1142:   OnigOptionType prev = reg->options;
        !          1143: 
        !          1144:   reg->options = node->option;
        !          1145:   tlen = compile_length_tree(node->target, reg);
        !          1146:   reg->options = prev;
        !          1147: 
        !          1148:   if (tlen < 0) return tlen;
        !          1149: 
        !          1150:   if (IS_DYNAMIC_OPTION(prev ^ node->option)) {
        !          1151:     return SIZE_OP_SET_OPTION_PUSH + SIZE_OP_SET_OPTION + SIZE_OP_FAIL
        !          1152:            + tlen + SIZE_OP_SET_OPTION;
        !          1153:   }
        !          1154:   else
        !          1155:     return tlen;
        !          1156: }
        !          1157: 
        !          1158: static int
        !          1159: compile_option_node(EffectNode* node, regex_t* reg)
        !          1160: {
        !          1161:   int r;
        !          1162:   OnigOptionType prev = reg->options;
        !          1163: 
        !          1164:   if (IS_DYNAMIC_OPTION(prev ^ node->option)) {
        !          1165:     r = add_opcode_option(reg, OP_SET_OPTION_PUSH, node->option);
        !          1166:     if (r) return r;
        !          1167:     r = add_opcode_option(reg, OP_SET_OPTION, prev);
        !          1168:     if (r) return r;
        !          1169:     r = add_opcode(reg, OP_FAIL);
        !          1170:     if (r) return r;
        !          1171:   }
        !          1172: 
        !          1173:   reg->options = node->option;
        !          1174:   r = compile_tree(node->target, reg);
        !          1175:   reg->options = prev;
        !          1176: 
        !          1177:   if (IS_DYNAMIC_OPTION(prev ^ node->option)) {
        !          1178:     if (r) return r;
        !          1179:     r = add_opcode_option(reg, OP_SET_OPTION, prev);
        !          1180:   }
        !          1181:   return r;
        !          1182: }
        !          1183: 
        !          1184: static int
        !          1185: compile_length_effect_node(EffectNode* node, regex_t* reg)
        !          1186: {
        !          1187:   int len;
        !          1188:   int tlen;
        !          1189: 
        !          1190:   if (node->type == EFFECT_OPTION)
        !          1191:     return compile_length_option_node(node, reg);
        !          1192: 
        !          1193:   if (node->target) {
        !          1194:     tlen = compile_length_tree(node->target, reg);
        !          1195:     if (tlen < 0) return tlen;
        !          1196:   }
        !          1197:   else
        !          1198:     tlen = 0;
        !          1199: 
        !          1200:   switch (node->type) {
        !          1201:   case EFFECT_MEMORY:
        !          1202: #ifdef USE_SUBEXP_CALL
        !          1203:     if (IS_EFFECT_CALLED(node)) {
        !          1204:       len = SIZE_OP_MEMORY_START_PUSH + tlen
        !          1205:          + SIZE_OP_CALL + SIZE_OP_JUMP + SIZE_OP_RETURN;
        !          1206:       if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))
        !          1207:        len += (IS_EFFECT_RECURSION(node)
        !          1208:                ? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_PUSH);
        !          1209:       else
        !          1210:        len += (IS_EFFECT_RECURSION(node)
        !          1211:                ? SIZE_OP_MEMORY_END_REC : SIZE_OP_MEMORY_END);
        !          1212:     }
        !          1213:     else
        !          1214: #endif
        !          1215:     {
        !          1216:       if (BIT_STATUS_AT(reg->bt_mem_start, node->regnum))
        !          1217:        len = SIZE_OP_MEMORY_START_PUSH;
        !          1218:       else
        !          1219:        len = SIZE_OP_MEMORY_START;
        !          1220: 
        !          1221:       len += tlen + (BIT_STATUS_AT(reg->bt_mem_end, node->regnum)
        !          1222:                     ? SIZE_OP_MEMORY_END_PUSH : SIZE_OP_MEMORY_END);
        !          1223:     }
        !          1224:     break;
        !          1225: 
        !          1226:   case EFFECT_STOP_BACKTRACK:
        !          1227:     if (IS_EFFECT_STOP_BT_SIMPLE_REPEAT(node)) {
        !          1228:       QuantifierNode* qn = &NQUANTIFIER(node->target);
        !          1229:       tlen = compile_length_tree(qn->target, reg);
        !          1230:       if (tlen < 0) return tlen;
        !          1231: 
        !          1232:       len = tlen * qn->lower
        !          1233:          + SIZE_OP_PUSH + tlen + SIZE_OP_POP + SIZE_OP_JUMP;
        !          1234:     }
        !          1235:     else {
        !          1236:       len = SIZE_OP_PUSH_STOP_BT + tlen + SIZE_OP_POP_STOP_BT;
        !          1237:     }
        !          1238:     break;
        !          1239: 
        !          1240:   default:
        !          1241:     return ONIGERR_TYPE_BUG;
        !          1242:     break;
        !          1243:   }
        !          1244: 
        !          1245:   return len;
        !          1246: }
        !          1247: 
        !          1248: static int get_char_length_tree(Node* node, regex_t* reg, int* len);
        !          1249: 
        !          1250: static int
        !          1251: compile_effect_node(EffectNode* node, regex_t* reg)
        !          1252: {
        !          1253:   int r, len;
        !          1254: 
        !          1255:   if (node->type == EFFECT_OPTION)
        !          1256:     return compile_option_node(node, reg);
        !          1257: 
        !          1258:   switch (node->type) {
        !          1259:   case EFFECT_MEMORY:
        !          1260: #ifdef USE_SUBEXP_CALL
        !          1261:     if (IS_EFFECT_CALLED(node)) {
        !          1262:       r = add_opcode(reg, OP_CALL);
        !          1263:       if (r) return r;
        !          1264:       node->call_addr = BBUF_GET_OFFSET_POS(reg) + SIZE_ABSADDR + SIZE_OP_JUMP;
        !          1265:       node->state |= NST_ADDR_FIXED;
        !          1266:       r = add_abs_addr(reg, (int )node->call_addr);
        !          1267:       if (r) return r;
        !          1268:       len = compile_length_tree(node->target, reg);
        !          1269:       len += (SIZE_OP_MEMORY_START_PUSH + SIZE_OP_RETURN);
        !          1270:       if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))
        !          1271:        len += (IS_EFFECT_RECURSION(node)
        !          1272:                ? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_PUSH);
        !          1273:       else
        !          1274:        len += (IS_EFFECT_RECURSION(node)
        !          1275:                ? SIZE_OP_MEMORY_END_REC : SIZE_OP_MEMORY_END);
        !          1276: 
        !          1277:       r = add_opcode_rel_addr(reg, OP_JUMP, len);
        !          1278:       if (r) return r;
        !          1279:     }
        !          1280: #endif
        !          1281:     if (BIT_STATUS_AT(reg->bt_mem_start, node->regnum))
        !          1282:       r = add_opcode(reg, OP_MEMORY_START_PUSH);
        !          1283:     else
        !          1284:       r = add_opcode(reg, OP_MEMORY_START);
        !          1285:     if (r) return r;
        !          1286:     r = add_mem_num(reg, node->regnum);
        !          1287:     if (r) return r;
        !          1288:     r = compile_tree(node->target, reg);
        !          1289:     if (r) return r;
        !          1290: #ifdef USE_SUBEXP_CALL
        !          1291:     if (IS_EFFECT_CALLED(node)) {
        !          1292:       if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))
        !          1293:        r = add_opcode(reg, (IS_EFFECT_RECURSION(node)
        !          1294:                             ? OP_MEMORY_END_PUSH_REC : OP_MEMORY_END_PUSH));
        !          1295:       else
        !          1296:        r = add_opcode(reg, (IS_EFFECT_RECURSION(node)
        !          1297:                             ? OP_MEMORY_END_REC : OP_MEMORY_END));
        !          1298: 
        !          1299:       if (r) return r;
        !          1300:       r = add_mem_num(reg, node->regnum);
        !          1301:       if (r) return r;
        !          1302:       r = add_opcode(reg, OP_RETURN);
        !          1303:     }
        !          1304:     else
        !          1305: #endif
        !          1306:     {
        !          1307:       if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))
        !          1308:        r = add_opcode(reg, OP_MEMORY_END_PUSH);
        !          1309:       else
        !          1310:        r = add_opcode(reg, OP_MEMORY_END);
        !          1311:       if (r) return r;
        !          1312:       r = add_mem_num(reg, node->regnum);
        !          1313:     }
        !          1314:     break;
        !          1315: 
        !          1316:   case EFFECT_STOP_BACKTRACK:
        !          1317:     if (IS_EFFECT_STOP_BT_SIMPLE_REPEAT(node)) {
        !          1318:       QuantifierNode* qn = &NQUANTIFIER(node->target);
        !          1319:       r = compile_tree_n_times(qn->target, qn->lower, reg);
        !          1320:       if (r) return r;
        !          1321: 
        !          1322:       len = compile_length_tree(qn->target, reg);
        !          1323:       if (len < 0) return len;
        !          1324: 
        !          1325:       r = add_opcode_rel_addr(reg, OP_PUSH, len + SIZE_OP_POP + SIZE_OP_JUMP);
        !          1326:       if (r) return r;
        !          1327:       r = compile_tree(qn->target, reg);
        !          1328:       if (r) return r;
        !          1329:       r = add_opcode(reg, OP_POP);
        !          1330:       if (r) return r;
        !          1331:       r = add_opcode_rel_addr(reg, OP_JUMP,
        !          1332:         -((int )SIZE_OP_PUSH + len + (int )SIZE_OP_POP + (int )SIZE_OP_JUMP));
        !          1333:     }
        !          1334:     else {
        !          1335:       r = add_opcode(reg, OP_PUSH_STOP_BT);
        !          1336:       if (r) return r;
        !          1337:       r = compile_tree(node->target, reg);
        !          1338:       if (r) return r;
        !          1339:       r = add_opcode(reg, OP_POP_STOP_BT);
        !          1340:     }
        !          1341:     break;
        !          1342: 
        !          1343:   default:
        !          1344:     return ONIGERR_TYPE_BUG;
        !          1345:     break;
        !          1346:   }
        !          1347: 
        !          1348:   return r;
        !          1349: }
        !          1350: 
        !          1351: static int
        !          1352: compile_length_anchor_node(AnchorNode* node, regex_t* reg)
        !          1353: {
        !          1354:   int len;
        !          1355:   int tlen = 0;
        !          1356: 
        !          1357:   if (node->target) {
        !          1358:     tlen = compile_length_tree(node->target, reg);
        !          1359:     if (tlen < 0) return tlen;
        !          1360:   }
        !          1361: 
        !          1362:   switch (node->type) {
        !          1363:   case ANCHOR_PREC_READ:
        !          1364:     len = SIZE_OP_PUSH_POS + tlen + SIZE_OP_POP_POS;
        !          1365:     break;
        !          1366:   case ANCHOR_PREC_READ_NOT:
        !          1367:     len = SIZE_OP_PUSH_POS_NOT + tlen + SIZE_OP_FAIL_POS;
        !          1368:     break;
        !          1369:   case ANCHOR_LOOK_BEHIND:
        !          1370:     len = SIZE_OP_LOOK_BEHIND + tlen;
        !          1371:     break;
        !          1372:   case ANCHOR_LOOK_BEHIND_NOT:
        !          1373:     len = SIZE_OP_PUSH_LOOK_BEHIND_NOT + tlen + SIZE_OP_FAIL_LOOK_BEHIND_NOT;
        !          1374:     break;
        !          1375: 
        !          1376:   default:
        !          1377:     len = SIZE_OPCODE;
        !          1378:     break;
        !          1379:   }
        !          1380: 
        !          1381:   return len;
        !          1382: }
        !          1383: 
        !          1384: static int
        !          1385: compile_anchor_node(AnchorNode* node, regex_t* reg)
        !          1386: {
        !          1387:   int r, len;
        !          1388: 
        !          1389:   switch (node->type) {
        !          1390:   case ANCHOR_BEGIN_BUF:      r = add_opcode(reg, OP_BEGIN_BUF);      break;
        !          1391:   case ANCHOR_END_BUF:        r = add_opcode(reg, OP_END_BUF);        break;
        !          1392:   case ANCHOR_BEGIN_LINE:     r = add_opcode(reg, OP_BEGIN_LINE);     break;
        !          1393:   case ANCHOR_END_LINE:       r = add_opcode(reg, OP_END_LINE);       break;
        !          1394:   case ANCHOR_SEMI_END_BUF:   r = add_opcode(reg, OP_SEMI_END_BUF);   break;
        !          1395:   case ANCHOR_BEGIN_POSITION: r = add_opcode(reg, OP_BEGIN_POSITION); break;
        !          1396: 
        !          1397:   case ANCHOR_WORD_BOUND:     r = add_opcode(reg, OP_WORD_BOUND);     break;
        !          1398:   case ANCHOR_NOT_WORD_BOUND: r = add_opcode(reg, OP_NOT_WORD_BOUND); break;
        !          1399: #ifdef USE_WORD_BEGIN_END
        !          1400:   case ANCHOR_WORD_BEGIN:     r = add_opcode(reg, OP_WORD_BEGIN);     break;
        !          1401:   case ANCHOR_WORD_END:       r = add_opcode(reg, OP_WORD_END);       break;
        !          1402: #endif
        !          1403: 
        !          1404:   case ANCHOR_PREC_READ:
        !          1405:     r = add_opcode(reg, OP_PUSH_POS);
        !          1406:     if (r) return r;
        !          1407:     r = compile_tree(node->target, reg);
        !          1408:     if (r) return r;
        !          1409:     r = add_opcode(reg, OP_POP_POS);
        !          1410:     break;
        !          1411: 
        !          1412:   case ANCHOR_PREC_READ_NOT:
        !          1413:     len = compile_length_tree(node->target, reg);
        !          1414:     if (len < 0) return len;
        !          1415:     r = add_opcode_rel_addr(reg, OP_PUSH_POS_NOT, len + SIZE_OP_FAIL_POS);
        !          1416:     if (r) return r;
        !          1417:     r = compile_tree(node->target, reg);
        !          1418:     if (r) return r;
        !          1419:     r = add_opcode(reg, OP_FAIL_POS);
        !          1420:     break;
        !          1421: 
        !          1422:   case ANCHOR_LOOK_BEHIND:
        !          1423:     {
        !          1424:       int n;
        !          1425:       r = add_opcode(reg, OP_LOOK_BEHIND);
        !          1426:       if (r) return r;
        !          1427:       if (node->char_len < 0) {
        !          1428:        r = get_char_length_tree(node->target, reg, &n);
        !          1429:        if (r) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
        !          1430:       }
        !          1431:       else
        !          1432:        n = node->char_len;
        !          1433:       r = add_length(reg, n);
        !          1434:       if (r) return r;
        !          1435:       r = compile_tree(node->target, reg);
        !          1436:     }
        !          1437:     break;
        !          1438: 
        !          1439:   case ANCHOR_LOOK_BEHIND_NOT:
        !          1440:     {
        !          1441:       int n;
        !          1442:       len = compile_length_tree(node->target, reg);
        !          1443:       r = add_opcode_rel_addr(reg, OP_PUSH_LOOK_BEHIND_NOT,
        !          1444:                           len + SIZE_OP_FAIL_LOOK_BEHIND_NOT);
        !          1445:       if (r) return r;
        !          1446:       if (node->char_len < 0) {
        !          1447:        r = get_char_length_tree(node->target, reg, &n);
        !          1448:        if (r) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
        !          1449:       }
        !          1450:       else
        !          1451:        n = node->char_len;
        !          1452:       r = add_length(reg, n);
        !          1453:       if (r) return r;
        !          1454:       r = compile_tree(node->target, reg);
        !          1455:       if (r) return r;
        !          1456:       r = add_opcode(reg, OP_FAIL_LOOK_BEHIND_NOT);
        !          1457:     }
        !          1458:     break;
        !          1459: 
        !          1460:   default:
        !          1461:     return ONIGERR_TYPE_BUG;
        !          1462:     break;
        !          1463:   }
        !          1464: 
        !          1465:   return r;
        !          1466: }
        !          1467: 
        !          1468: static int
        !          1469: compile_length_tree(Node* node, regex_t* reg)
        !          1470: {
        !          1471:   int len, type, r;
        !          1472: 
        !          1473:   type = NTYPE(node);
        !          1474:   switch (type) {
        !          1475:   case N_LIST:
        !          1476:     len = 0;
        !          1477:     do {
        !          1478:       r = compile_length_tree(NCONS(node).left, reg);
        !          1479:       if (r < 0) return r;
        !          1480:       len += r;
        !          1481:     } while (IS_NOT_NULL(node = NCONS(node).right));
        !          1482:     r = len;
        !          1483:     break;
        !          1484: 
        !          1485:   case N_ALT:
        !          1486:     {
        !          1487:       int n;
        !          1488: 
        !          1489:       n = r = 0;
        !          1490:       do {
        !          1491:        r += compile_length_tree(NCONS(node).left, reg);
        !          1492:        n++;
        !          1493:       } while (IS_NOT_NULL(node = NCONS(node).right));
        !          1494:       r += (SIZE_OP_PUSH + SIZE_OP_JUMP) * (n - 1);
        !          1495:     }
        !          1496:     break;
        !          1497: 
        !          1498:   case N_STRING:
        !          1499:     if (NSTRING_IS_RAW(node))
        !          1500:       r = compile_length_string_raw_node(&(NSTRING(node)), reg);
        !          1501:     else
        !          1502:       r = compile_length_string_node(node, reg);
        !          1503:     break;
        !          1504: 
        !          1505:   case N_CCLASS:
        !          1506:     r = compile_length_cclass_node(&(NCCLASS(node)), reg);
        !          1507:     break;
        !          1508: 
        !          1509:   case N_CTYPE:
        !          1510:   case N_ANYCHAR:
        !          1511:     r = SIZE_OPCODE;
        !          1512:     break;
        !          1513: 
        !          1514:   case N_BACKREF:
        !          1515:     {
        !          1516:       BackrefNode* br = &(NBACKREF(node));
        !          1517: 
        !          1518: #ifdef USE_BACKREF_AT_LEVEL
        !          1519:       if (IS_BACKREF_NEST_LEVEL(br)) {
        !          1520:         r = SIZE_OPCODE + SIZE_OPTION + SIZE_LENGTH +
        !          1521:             SIZE_LENGTH + (SIZE_MEMNUM * br->back_num);
        !          1522:       }
        !          1523:       else
        !          1524: #endif
        !          1525:       if (br->back_num == 1) {
        !          1526:        r = ((!IS_IGNORECASE(reg->options) && br->back_static[0] <= 2)
        !          1527:             ? SIZE_OPCODE : (SIZE_OPCODE + SIZE_MEMNUM));
        !          1528:       }
        !          1529:       else {
        !          1530:        r = SIZE_OPCODE + SIZE_LENGTH + (SIZE_MEMNUM * br->back_num);
        !          1531:       }
        !          1532:     }
        !          1533:     break;
        !          1534: 
        !          1535: #ifdef USE_SUBEXP_CALL
        !          1536:   case N_CALL:
        !          1537:     r = SIZE_OP_CALL;
        !          1538:     break;
        !          1539: #endif
        !          1540: 
        !          1541:   case N_QUANTIFIER:
        !          1542:     r = compile_length_quantifier_node(&(NQUANTIFIER(node)), reg);
        !          1543:     break;
        !          1544: 
        !          1545:   case N_EFFECT:
        !          1546:     r = compile_length_effect_node(&NEFFECT(node), reg);
        !          1547:     break;
        !          1548: 
        !          1549:   case N_ANCHOR:
        !          1550:     r = compile_length_anchor_node(&(NANCHOR(node)), reg);
        !          1551:     break;
        !          1552: 
        !          1553:   default:
        !          1554:     return ONIGERR_TYPE_BUG;
        !          1555:     break;
        !          1556:   }
        !          1557: 
        !          1558:   return r;
        !          1559: }
        !          1560: 
        !          1561: static int
        !          1562: compile_tree(Node* node, regex_t* reg)
        !          1563: {
        !          1564:   int n, type, len, pos, r = 0;
        !          1565: 
        !          1566:   type = NTYPE(node);
        !          1567:   switch (type) {
        !          1568:   case N_LIST:
        !          1569:     do {
        !          1570:       r = compile_tree(NCONS(node).left, reg);
        !          1571:     } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
        !          1572:     break;
        !          1573: 
        !          1574:   case N_ALT:
        !          1575:     {
        !          1576:       Node* x = node;
        !          1577:       len = 0;
        !          1578:       do {
        !          1579:        len += compile_length_tree(NCONS(x).left, reg);
        !          1580:        if (NCONS(x).right != NULL) {
        !          1581:          len += SIZE_OP_PUSH + SIZE_OP_JUMP;
        !          1582:        }
        !          1583:       } while (IS_NOT_NULL(x = NCONS(x).right));
        !          1584:       pos = reg->used + len;  /* goal position */
        !          1585: 
        !          1586:       do {
        !          1587:        len = compile_length_tree(NCONS(node).left, reg);
        !          1588:        if (IS_NOT_NULL(NCONS(node).right)) {
        !          1589:          r = add_opcode_rel_addr(reg, OP_PUSH, len + SIZE_OP_JUMP);
        !          1590:          if (r) break;
        !          1591:        }
        !          1592:        r = compile_tree(NCONS(node).left, reg);
        !          1593:        if (r) break;
        !          1594:        if (IS_NOT_NULL(NCONS(node).right)) {
        !          1595:          len = pos - (reg->used + SIZE_OP_JUMP);
        !          1596:          r = add_opcode_rel_addr(reg, OP_JUMP, len);
        !          1597:          if (r) break;
        !          1598:        }
        !          1599:       } while (IS_NOT_NULL(node = NCONS(node).right));
        !          1600:     }
        !          1601:     break;
        !          1602: 
        !          1603:   case N_STRING:
        !          1604:     if (NSTRING_IS_RAW(node))
        !          1605:       r = compile_string_raw_node(&(NSTRING(node)), reg);
        !          1606:     else
        !          1607:       r = compile_string_node(node, reg);
        !          1608:     break;
        !          1609: 
        !          1610:   case N_CCLASS:
        !          1611:     r = compile_cclass_node(&(NCCLASS(node)), reg);
        !          1612:     break;
        !          1613: 
        !          1614:   case N_CTYPE:
        !          1615:     {
        !          1616:       int op;
        !          1617: 
        !          1618:       switch (NCTYPE(node).type) {
        !          1619:       case CTYPE_WORD:            op = OP_WORD;           break;
        !          1620:       case CTYPE_NOT_WORD:        op = OP_NOT_WORD;       break;
        !          1621:       default:
        !          1622:        return ONIGERR_TYPE_BUG;
        !          1623:        break;
        !          1624:       }
        !          1625:       r = add_opcode(reg, op);
        !          1626:     }
        !          1627:     break;
        !          1628: 
        !          1629:   case N_ANYCHAR:
        !          1630:     if (IS_MULTILINE(reg->options))
        !          1631:       r = add_opcode(reg, OP_ANYCHAR_ML);
        !          1632:     else
        !          1633:       r = add_opcode(reg, OP_ANYCHAR);
        !          1634:     break;
        !          1635: 
        !          1636:   case N_BACKREF:
        !          1637:     {
        !          1638:       BackrefNode* br = &(NBACKREF(node));
        !          1639: 
        !          1640: #ifdef USE_BACKREF_AT_LEVEL
        !          1641:       if (IS_BACKREF_NEST_LEVEL(br)) {
        !          1642:        r = add_opcode(reg, OP_BACKREF_AT_LEVEL);
        !          1643:        if (r) return r;
        !          1644:        r = add_option(reg, (reg->options & ONIG_OPTION_IGNORECASE));
        !          1645:        if (r) return r;
        !          1646:        r = add_length(reg, br->nest_level);
        !          1647:        if (r) return r;
        !          1648: 
        !          1649:        goto add_bacref_mems;
        !          1650:       }
        !          1651:       else
        !          1652: #endif
        !          1653:       if (br->back_num == 1) {
        !          1654:        n = br->back_static[0];
        !          1655:        if (IS_IGNORECASE(reg->options)) {
        !          1656:          r = add_opcode(reg, OP_BACKREFN_IC);
        !          1657:          if (r) return r;
        !          1658:          r = add_mem_num(reg, n);
        !          1659:        }
        !          1660:        else {
        !          1661:          switch (n) {
        !          1662:          case 1:  r = add_opcode(reg, OP_BACKREF1); break;
        !          1663:          case 2:  r = add_opcode(reg, OP_BACKREF2); break;
        !          1664:          default:
        !          1665:            r = add_opcode(reg, OP_BACKREFN);
        !          1666:            if (r) return r;
        !          1667:            r = add_mem_num(reg, n);
        !          1668:            break;
        !          1669:          }
        !          1670:        }
        !          1671:       }
        !          1672:       else {
        !          1673:        int i;
        !          1674:        int* p;
        !          1675: 
        !          1676:         if (IS_IGNORECASE(reg->options)) {
        !          1677:           r = add_opcode(reg, OP_BACKREF_MULTI_IC);
        !          1678:         }
        !          1679:         else {
        !          1680:           r = add_opcode(reg, OP_BACKREF_MULTI);
        !          1681:         }
        !          1682:        if (r) return r;
        !          1683: 
        !          1684: #ifdef USE_BACKREF_AT_LEVEL
        !          1685:       add_bacref_mems:
        !          1686: #endif
        !          1687:        r = add_length(reg, br->back_num);
        !          1688:        if (r) return r;
        !          1689:        p = BACKREFS_P(br);
        !          1690:        for (i = br->back_num - 1; i >= 0; i--) {
        !          1691:          r = add_mem_num(reg, p[i]);
        !          1692:          if (r) return r;
        !          1693:        }
        !          1694:       }
        !          1695:     }
        !          1696:     break;
        !          1697: 
        !          1698: #ifdef USE_SUBEXP_CALL
        !          1699:   case N_CALL:
        !          1700:     r = compile_call(&(NCALL(node)), reg);
        !          1701:     break;
        !          1702: #endif
        !          1703: 
        !          1704:   case N_QUANTIFIER:
        !          1705:     r = compile_quantifier_node(&(NQUANTIFIER(node)), reg);
        !          1706:     break;
        !          1707: 
        !          1708:   case N_EFFECT:
        !          1709:     r = compile_effect_node(&NEFFECT(node), reg);
        !          1710:     break;
        !          1711: 
        !          1712:   case N_ANCHOR:
        !          1713:     r = compile_anchor_node(&(NANCHOR(node)), reg);
        !          1714:     break;
        !          1715: 
        !          1716:   default:
        !          1717: #ifdef ONIG_DEBUG
        !          1718:     fprintf(stderr, "compile_tree: undefined node type %d\n", NTYPE(node));
        !          1719: #endif
        !          1720:     break;
        !          1721:   }
        !          1722: 
        !          1723:   return r;
        !          1724: }
        !          1725: 
        !          1726: #ifdef USE_NAMED_GROUP
        !          1727: 
        !          1728: static int
        !          1729: noname_disable_map(Node** plink, GroupNumRemap* map, int* counter)
        !          1730: {
        !          1731:   int r = 0;
        !          1732:   Node* node = *plink;
        !          1733: 
        !          1734:   switch (NTYPE(node)) {
        !          1735:   case N_LIST:
        !          1736:   case N_ALT:
        !          1737:     do {
        !          1738:       r = noname_disable_map(&(NCONS(node).left), map, counter);
        !          1739:     } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
        !          1740:     break;
        !          1741: 
        !          1742:   case N_QUANTIFIER:
        !          1743:     {
        !          1744:       Node** ptarget = &(NQUANTIFIER(node).target);
        !          1745:       Node*  old = *ptarget;
        !          1746:       r = noname_disable_map(ptarget, map, counter);
        !          1747:       if (*ptarget != old && NTYPE(*ptarget) == N_QUANTIFIER) {
        !          1748:        onig_reduce_nested_quantifier(node, *ptarget);
        !          1749:       }
        !          1750:     }
        !          1751:     break;
        !          1752: 
        !          1753:   case N_EFFECT:
        !          1754:     {
        !          1755:       EffectNode* en = &(NEFFECT(node));
        !          1756:       if (en->type == EFFECT_MEMORY) {
        !          1757:        if (IS_EFFECT_NAMED_GROUP(en)) {
        !          1758:          (*counter)++;
        !          1759:          map[en->regnum].new_val = *counter;
        !          1760:          en->regnum = *counter;
        !          1761:          r = noname_disable_map(&(en->target), map, counter);
        !          1762:        }
        !          1763:        else {
        !          1764:          *plink = en->target;
        !          1765:          en->target = NULL_NODE;
        !          1766:          onig_node_free(node);
        !          1767:          r = noname_disable_map(plink, map, counter);
        !          1768:        }
        !          1769:       }
        !          1770:       else
        !          1771:        r = noname_disable_map(&(en->target), map, counter);
        !          1772:     }
        !          1773:     break;
        !          1774: 
        !          1775:   default:
        !          1776:     break;
        !          1777:   }
        !          1778: 
        !          1779:   return r;
        !          1780: }
        !          1781: 
        !          1782: static int
        !          1783: renumber_node_backref(Node* node, GroupNumRemap* map)
        !          1784: {
        !          1785:   int i, pos, n, old_num;
        !          1786:   int *backs;
        !          1787:   BackrefNode* bn = &(NBACKREF(node));
        !          1788: 
        !          1789:   if (! IS_BACKREF_NAME_REF(bn))
        !          1790:     return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;
        !          1791: 
        !          1792:   old_num = bn->back_num;
        !          1793:   if (IS_NULL(bn->back_dynamic))
        !          1794:     backs = bn->back_static;
        !          1795:   else
        !          1796:     backs = bn->back_dynamic;
        !          1797: 
        !          1798:   for (i = 0, pos = 0; i < old_num; i++) {
        !          1799:     n = map[backs[i]].new_val;
        !          1800:     if (n > 0) {
        !          1801:       backs[pos] = n;
        !          1802:       pos++;
        !          1803:     }
        !          1804:   }
        !          1805: 
        !          1806:   bn->back_num = pos;
        !          1807:   return 0;
        !          1808: }
        !          1809: 
        !          1810: static int
        !          1811: renumber_by_map(Node* node, GroupNumRemap* map)
        !          1812: {
        !          1813:   int r = 0;
        !          1814: 
        !          1815:   switch (NTYPE(node)) {
        !          1816:   case N_LIST:
        !          1817:   case N_ALT:
        !          1818:     do {
        !          1819:       r = renumber_by_map(NCONS(node).left, map);
        !          1820:     } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
        !          1821:     break;
        !          1822:   case N_QUANTIFIER:
        !          1823:     r = renumber_by_map(NQUANTIFIER(node).target, map);
        !          1824:     break;
        !          1825:   case N_EFFECT:
        !          1826:     r = renumber_by_map(NEFFECT(node).target, map);
        !          1827:     break;
        !          1828: 
        !          1829:   case N_BACKREF:
        !          1830:     r = renumber_node_backref(node, map);
        !          1831:     break;
        !          1832: 
        !          1833:   default:
        !          1834:     break;
        !          1835:   }
        !          1836: 
        !          1837:   return r;
        !          1838: }
        !          1839: 
        !          1840: static int
        !          1841: numbered_ref_check(Node* node)
        !          1842: {
        !          1843:   int r = 0;
        !          1844: 
        !          1845:   switch (NTYPE(node)) {
        !          1846:   case N_LIST:
        !          1847:   case N_ALT:
        !          1848:     do {
        !          1849:       r = numbered_ref_check(NCONS(node).left);
        !          1850:     } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
        !          1851:     break;
        !          1852:   case N_QUANTIFIER:
        !          1853:     r = numbered_ref_check(NQUANTIFIER(node).target);
        !          1854:     break;
        !          1855:   case N_EFFECT:
        !          1856:     r = numbered_ref_check(NEFFECT(node).target);
        !          1857:     break;
        !          1858: 
        !          1859:   case N_BACKREF:
        !          1860:     if (! IS_BACKREF_NAME_REF(&(NBACKREF(node))))
        !          1861:       return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;
        !          1862:     break;
        !          1863: 
        !          1864:   default:
        !          1865:     break;
        !          1866:   }
        !          1867: 
        !          1868:   return r;
        !          1869: }
        !          1870: 
        !          1871: static int
        !          1872: disable_noname_group_capture(Node** root, regex_t* reg, ScanEnv* env)
        !          1873: {
        !          1874:   int r, i, pos, counter;
        !          1875:   BitStatusType loc;
        !          1876:   GroupNumRemap* map;
        !          1877: 
        !          1878:   map = (GroupNumRemap* )xalloca(sizeof(GroupNumRemap) * (env->num_mem + 1));
        !          1879:   CHECK_NULL_RETURN_VAL(map, ONIGERR_MEMORY);
        !          1880:   for (i = 1; i <= env->num_mem; i++) {
        !          1881:     map[i].new_val = 0;
        !          1882:   }
        !          1883:   counter = 0;
        !          1884:   r = noname_disable_map(root, map, &counter);
        !          1885:   if (r != 0) return r;
        !          1886: 
        !          1887:   r = renumber_by_map(*root, map);
        !          1888:   if (r != 0) return r;
        !          1889: 
        !          1890:   for (i = 1, pos = 1; i <= env->num_mem; i++) {
        !          1891:     if (map[i].new_val > 0) {
        !          1892:       SCANENV_MEM_NODES(env)[pos] = SCANENV_MEM_NODES(env)[i];
        !          1893:       pos++;
        !          1894:     }
        !          1895:   }
        !          1896: 
        !          1897:   loc = env->capture_history;
        !          1898:   BIT_STATUS_CLEAR(env->capture_history);
        !          1899:   for (i = 1; i <= ONIG_MAX_CAPTURE_HISTORY_GROUP; i++) {
        !          1900:     if (BIT_STATUS_AT(loc, i)) {
        !          1901:       BIT_STATUS_ON_AT_SIMPLE(env->capture_history, map[i].new_val);
        !          1902:     }
        !          1903:   }
        !          1904: 
        !          1905:   env->num_mem = env->num_named;
        !          1906:   reg->num_mem = env->num_named;
        !          1907: 
        !          1908:   return onig_renumber_name_table(reg, map);
        !          1909: }
        !          1910: #endif /* USE_NAMED_GROUP */
        !          1911: 
        !          1912: #ifdef USE_SUBEXP_CALL
        !          1913: static int
        !          1914: unset_addr_list_fix(UnsetAddrList* uslist, regex_t* reg)
        !          1915: {
        !          1916:   int i, offset;
        !          1917:   EffectNode* en;
        !          1918:   AbsAddrType addr;
        !          1919: 
        !          1920:   for (i = 0; i < uslist->num; i++) {
        !          1921:     en = &(NEFFECT(uslist->us[i].target));
        !          1922:     if (! IS_EFFECT_ADDR_FIXED(en)) return ONIGERR_PARSER_BUG;
        !          1923:     addr = en->call_addr;
        !          1924:     offset = uslist->us[i].offset;
        !          1925: 
        !          1926:     BBUF_WRITE(reg, offset, &addr, SIZE_ABSADDR);
        !          1927:   }
        !          1928:   return 0;
        !          1929: }
        !          1930: #endif
        !          1931: 
        !          1932: #ifdef USE_INFINITE_REPEAT_MONOMANIAC_MEM_STATUS_CHECK
        !          1933: static int
        !          1934: quantifiers_memory_node_info(Node* node)
        !          1935: {
        !          1936:   int r = 0;
        !          1937: 
        !          1938:   switch (NTYPE(node)) {
        !          1939:   case N_LIST:
        !          1940:   case N_ALT:
        !          1941:     {
        !          1942:       int v;
        !          1943:       do {
        !          1944:        v = quantifiers_memory_node_info(NCONS(node).left);
        !          1945:        if (v > r) r = v;
        !          1946:       } while (v >= 0 && IS_NOT_NULL(node = NCONS(node).right));
        !          1947:     }
        !          1948:     break;
        !          1949: 
        !          1950: #ifdef USE_SUBEXP_CALL
        !          1951:   case N_CALL:
        !          1952:     if (IS_CALL_RECURSION(&NCALL(node))) {
        !          1953:       return NQ_TARGET_IS_EMPTY_REC; /* tiny version */
        !          1954:     }
        !          1955:     else
        !          1956:       r = quantifiers_memory_node_info(NCALL(node).target);
        !          1957:     break;
        !          1958: #endif
        !          1959: 
        !          1960:   case N_QUANTIFIER:
        !          1961:     {
        !          1962:       QuantifierNode* qn = &(NQUANTIFIER(node));
        !          1963:       if (qn->upper != 0) {
        !          1964:        r = quantifiers_memory_node_info(qn->target);
        !          1965:       }
        !          1966:     }
        !          1967:     break;
        !          1968: 
        !          1969:   case N_EFFECT:
        !          1970:     {
        !          1971:       EffectNode* en = &(NEFFECT(node));
        !          1972:       switch (en->type) {
        !          1973:       case EFFECT_MEMORY:
        !          1974:        return NQ_TARGET_IS_EMPTY_MEM;
        !          1975:        break;
        !          1976: 
        !          1977:       case EFFECT_OPTION:
        !          1978:       case EFFECT_STOP_BACKTRACK:
        !          1979:        r = quantifiers_memory_node_info(en->target);
        !          1980:        break;
        !          1981:       default:
        !          1982:        break;
        !          1983:       }
        !          1984:     }
        !          1985:     break;
        !          1986: 
        !          1987:   case N_BACKREF:
        !          1988:   case N_STRING:
        !          1989:   case N_CTYPE:
        !          1990:   case N_CCLASS:
        !          1991:   case N_ANYCHAR:
        !          1992:   case N_ANCHOR:
        !          1993:   default:
        !          1994:     break;
        !          1995:   }
        !          1996: 
        !          1997:   return r;
        !          1998: }
        !          1999: #endif /* USE_INFINITE_REPEAT_MONOMANIAC_MEM_STATUS_CHECK */
        !          2000: 
        !          2001: static int
        !          2002: get_min_match_length(Node* node, OnigDistance *min, ScanEnv* env)
        !          2003: {
        !          2004:   OnigDistance tmin;
        !          2005:   int r = 0;
        !          2006: 
        !          2007:   *min = 0;
        !          2008:   switch (NTYPE(node)) {
        !          2009:   case N_BACKREF:
        !          2010:     {
        !          2011:       int i;
        !          2012:       int* backs;
        !          2013:       Node** nodes = SCANENV_MEM_NODES(env);
        !          2014:       BackrefNode* br = &(NBACKREF(node));
        !          2015:       if (br->state & NST_RECURSION) break;
        !          2016: 
        !          2017:       backs = BACKREFS_P(br);
        !          2018:       if (backs[0] > env->num_mem)  return ONIGERR_INVALID_BACKREF;
        !          2019:       r = get_min_match_length(nodes[backs[0]], min, env);
        !          2020:       if (r != 0) break;
        !          2021:       for (i = 1; i < br->back_num; i++) {
        !          2022:        if (backs[i] > env->num_mem)  return ONIGERR_INVALID_BACKREF;
        !          2023:        r = get_min_match_length(nodes[backs[i]], &tmin, env);
        !          2024:        if (r != 0) break;
        !          2025:        if (*min > tmin) *min = tmin;
        !          2026:       }
        !          2027:     }
        !          2028:     break;
        !          2029: 
        !          2030: #ifdef USE_SUBEXP_CALL
        !          2031:   case N_CALL:
        !          2032:     if (IS_CALL_RECURSION(&NCALL(node))) {
        !          2033:       EffectNode* en = &(NEFFECT(NCALL(node).target));
        !          2034:       if (IS_EFFECT_MIN_FIXED(en))
        !          2035:        *min = en->min_len;
        !          2036:     }
        !          2037:     else
        !          2038:       r = get_min_match_length(NCALL(node).target, min, env);
        !          2039:     break;
        !          2040: #endif
        !          2041: 
        !          2042:   case N_LIST:
        !          2043:     do {
        !          2044:       r = get_min_match_length(NCONS(node).left, &tmin, env);
        !          2045:       if (r == 0) *min += tmin;
        !          2046:     } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
        !          2047:     break;
        !          2048: 
        !          2049:   case N_ALT:
        !          2050:     {
        !          2051:       Node *x, *y;
        !          2052:       y = node;
        !          2053:       do {
        !          2054:        x = NCONS(y).left;
        !          2055:        r = get_min_match_length(x, &tmin, env);
        !          2056:        if (r != 0) break;
        !          2057:        if (y == node) *min = tmin;
        !          2058:        else if (*min > tmin) *min = tmin;
        !          2059:       } while (r == 0 && IS_NOT_NULL(y = NCONS(y).right));
        !          2060:     }
        !          2061:     break;
        !          2062: 
        !          2063:   case N_STRING:
        !          2064:     {
        !          2065:       StrNode* sn = &(NSTRING(node));
        !          2066:       *min = sn->end - sn->s;
        !          2067:     }
        !          2068:     break;
        !          2069: 
        !          2070:   case N_CTYPE:
        !          2071:     switch (NCTYPE(node).type) {
        !          2072:     case CTYPE_WORD:     *min = 1; break;
        !          2073:     case CTYPE_NOT_WORD: *min = 1; break;
        !          2074:     default:
        !          2075:       break;
        !          2076:     }
        !          2077:     break;
        !          2078: 
        !          2079:   case N_CCLASS:
        !          2080:   case N_ANYCHAR:
        !          2081:     *min = 1;
        !          2082:     break;
        !          2083: 
        !          2084:   case N_QUANTIFIER:
        !          2085:     {
        !          2086:       QuantifierNode* qn = &(NQUANTIFIER(node));
        !          2087: 
        !          2088:       if (qn->lower > 0) {
        !          2089:        r = get_min_match_length(qn->target, min, env);
        !          2090:        if (r == 0)
        !          2091:          *min = distance_multiply(*min, qn->lower);
        !          2092:       }
        !          2093:     }
        !          2094:     break;
        !          2095: 
        !          2096:   case N_EFFECT:
        !          2097:     {
        !          2098:       EffectNode* en = &(NEFFECT(node));
        !          2099:       switch (en->type) {
        !          2100:       case EFFECT_MEMORY:
        !          2101: #ifdef USE_SUBEXP_CALL
        !          2102:        if (IS_EFFECT_MIN_FIXED(en))
        !          2103:          *min = en->min_len;
        !          2104:        else {
        !          2105:          r = get_min_match_length(en->target, min, env);
        !          2106:          if (r == 0) {
        !          2107:            en->min_len = *min;
        !          2108:            SET_EFFECT_STATUS(node, NST_MIN_FIXED);
        !          2109:          }
        !          2110:        }
        !          2111:        break;
        !          2112: #endif
        !          2113:       case EFFECT_OPTION:
        !          2114:       case EFFECT_STOP_BACKTRACK:
        !          2115:        r = get_min_match_length(en->target, min, env);
        !          2116:        break;
        !          2117:       }
        !          2118:     }
        !          2119:     break;
        !          2120: 
        !          2121:   case N_ANCHOR:
        !          2122:   default:
        !          2123:     break;
        !          2124:   }
        !          2125: 
        !          2126:   return r;
        !          2127: }
        !          2128: 
        !          2129: static int
        !          2130: get_max_match_length(Node* node, OnigDistance *max, ScanEnv* env)
        !          2131: {
        !          2132:   OnigDistance tmax;
        !          2133:   int r = 0;
        !          2134: 
        !          2135:   *max = 0;
        !          2136:   switch (NTYPE(node)) {
        !          2137:   case N_LIST:
        !          2138:     do {
        !          2139:       r = get_max_match_length(NCONS(node).left, &tmax, env);
        !          2140:       if (r == 0)
        !          2141:        *max = distance_add(*max, tmax);
        !          2142:     } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
        !          2143:     break;
        !          2144: 
        !          2145:   case N_ALT:
        !          2146:     do {
        !          2147:       r = get_max_match_length(NCONS(node).left, &tmax, env);
        !          2148:       if (r == 0 && *max < tmax) *max = tmax;
        !          2149:     } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
        !          2150:     break;
        !          2151: 
        !          2152:   case N_STRING:
        !          2153:     {
        !          2154:       StrNode* sn = &(NSTRING(node));
        !          2155:       *max = sn->end - sn->s;
        !          2156:     }
        !          2157:     break;
        !          2158: 
        !          2159:   case N_CTYPE:
        !          2160:     switch (NCTYPE(node).type) {
        !          2161:     case CTYPE_WORD:
        !          2162:     case CTYPE_NOT_WORD:
        !          2163:       *max = ONIGENC_MBC_MAXLEN_DIST(env->enc);
        !          2164:       break;
        !          2165: 
        !          2166:     default:
        !          2167:       break;
        !          2168:     }
        !          2169:     break;
        !          2170: 
        !          2171:   case N_CCLASS:
        !          2172:   case N_ANYCHAR:
        !          2173:     *max = ONIGENC_MBC_MAXLEN_DIST(env->enc);
        !          2174:     break;
        !          2175: 
        !          2176:   case N_BACKREF:
        !          2177:     {
        !          2178:       int i;
        !          2179:       int* backs;
        !          2180:       Node** nodes = SCANENV_MEM_NODES(env);
        !          2181:       BackrefNode* br = &(NBACKREF(node));
        !          2182:       if (br->state & NST_RECURSION) {
        !          2183:        *max = ONIG_INFINITE_DISTANCE;
        !          2184:        break;
        !          2185:       }
        !          2186:       backs = BACKREFS_P(br);
        !          2187:       for (i = 0; i < br->back_num; i++) {
        !          2188:        if (backs[i] > env->num_mem)  return ONIGERR_INVALID_BACKREF;
        !          2189:        r = get_max_match_length(nodes[backs[i]], &tmax, env);
        !          2190:        if (r != 0) break;
        !          2191:        if (*max < tmax) *max = tmax;
        !          2192:       }
        !          2193:     }
        !          2194:     break;
        !          2195: 
        !          2196: #ifdef USE_SUBEXP_CALL
        !          2197:   case N_CALL:
        !          2198:     if (! IS_CALL_RECURSION(&(NCALL(node))))
        !          2199:       r = get_max_match_length(NCALL(node).target, max, env);
        !          2200:     else
        !          2201:       *max = ONIG_INFINITE_DISTANCE;
        !          2202:     break;
        !          2203: #endif
        !          2204: 
        !          2205:   case N_QUANTIFIER:
        !          2206:     {
        !          2207:       QuantifierNode* qn = &(NQUANTIFIER(node));
        !          2208: 
        !          2209:       if (qn->upper != 0) {
        !          2210:        r = get_max_match_length(qn->target, max, env);
        !          2211:        if (r == 0 && *max != 0) {
        !          2212:          if (! IS_REPEAT_INFINITE(qn->upper))
        !          2213:            *max = distance_multiply(*max, qn->upper);
        !          2214:          else
        !          2215:            *max = ONIG_INFINITE_DISTANCE;
        !          2216:        }
        !          2217:       }
        !          2218:     }
        !          2219:     break;
        !          2220: 
        !          2221:   case N_EFFECT:
        !          2222:     {
        !          2223:       EffectNode* en = &(NEFFECT(node));
        !          2224:       switch (en->type) {
        !          2225:       case EFFECT_MEMORY:
        !          2226: #ifdef USE_SUBEXP_CALL
        !          2227:        if (IS_EFFECT_MAX_FIXED(en))
        !          2228:          *max = en->max_len;
        !          2229:        else {
        !          2230:          r = get_max_match_length(en->target, max, env);
        !          2231:          if (r == 0) {
        !          2232:            en->max_len = *max;
        !          2233:            SET_EFFECT_STATUS(node, NST_MAX_FIXED);
        !          2234:          }
        !          2235:        }
        !          2236:        break;
        !          2237: #endif
        !          2238:       case EFFECT_OPTION:
        !          2239:       case EFFECT_STOP_BACKTRACK:
        !          2240:        r = get_max_match_length(en->target, max, env);
        !          2241:        break;
        !          2242:       }
        !          2243:     }
        !          2244:     break;
        !          2245: 
        !          2246:   case N_ANCHOR:
        !          2247:   default:
        !          2248:     break;
        !          2249:   }
        !          2250: 
        !          2251:   return r;
        !          2252: }
        !          2253: 
        !          2254: #define GET_CHAR_LEN_VARLEN           -1
        !          2255: #define GET_CHAR_LEN_TOP_ALT_VARLEN   -2
        !          2256: 
        !          2257: /* fixed size pattern node only */
        !          2258: static int
        !          2259: get_char_length_tree1(Node* node, regex_t* reg, int* len, int level)
        !          2260: {
        !          2261:   int tlen;
        !          2262:   int r = 0;
        !          2263: 
        !          2264:   level++;
        !          2265:   *len = 0;
        !          2266:   switch (NTYPE(node)) {
        !          2267:   case N_LIST:
        !          2268:     do {
        !          2269:       r = get_char_length_tree1(NCONS(node).left, reg, &tlen, level);
        !          2270:       if (r == 0)
        !          2271:        *len = distance_add(*len, tlen);
        !          2272:     } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
        !          2273:     break;
        !          2274: 
        !          2275:   case N_ALT:
        !          2276:     {
        !          2277:       int tlen2;
        !          2278:       int varlen = 0;
        !          2279: 
        !          2280:       r = get_char_length_tree1(NCONS(node).left, reg, &tlen, level);
        !          2281:       while (r == 0 && IS_NOT_NULL(node = NCONS(node).right)) {
        !          2282:        r = get_char_length_tree1(NCONS(node).left, reg, &tlen2, level);
        !          2283:        if (r == 0) {
        !          2284:          if (tlen != tlen2)
        !          2285:            varlen = 1;
        !          2286:        }
        !          2287:       }
        !          2288:       if (r == 0) {
        !          2289:        if (varlen != 0) {
        !          2290:          if (level == 1)
        !          2291:            r = GET_CHAR_LEN_TOP_ALT_VARLEN;
        !          2292:          else
        !          2293:            r = GET_CHAR_LEN_VARLEN;
        !          2294:        }
        !          2295:        else
        !          2296:          *len = tlen;
        !          2297:       }
        !          2298:     }
        !          2299:     break;
        !          2300: 
        !          2301:   case N_STRING:
        !          2302:     {
        !          2303:       StrNode* sn = &(NSTRING(node));
        !          2304:       UChar *s = sn->s;
        !          2305:       while (s < sn->end) {
        !          2306:        s += enc_len(reg->enc, s);
        !          2307:        (*len)++;
        !          2308:       }
        !          2309:     }
        !          2310:     break;
        !          2311: 
        !          2312:   case N_QUANTIFIER:
        !          2313:     {
        !          2314:       QuantifierNode* qn = &(NQUANTIFIER(node));
        !          2315:       if (qn->lower == qn->upper) {
        !          2316:        r = get_char_length_tree1(qn->target, reg, &tlen, level);
        !          2317:        if (r == 0)
        !          2318:          *len = distance_multiply(tlen, qn->lower);
        !          2319:       }
        !          2320:       else
        !          2321:        r = GET_CHAR_LEN_VARLEN;
        !          2322:     }
        !          2323:     break;
        !          2324: 
        !          2325: #ifdef USE_SUBEXP_CALL
        !          2326:   case N_CALL:
        !          2327:     if (! IS_CALL_RECURSION(&(NCALL(node))))
        !          2328:       r = get_char_length_tree1(NCALL(node).target, reg, len, level);
        !          2329:     else
        !          2330:       r = GET_CHAR_LEN_VARLEN;
        !          2331:     break;
        !          2332: #endif
        !          2333: 
        !          2334:   case N_CTYPE:
        !          2335:     switch (NCTYPE(node).type) {
        !          2336:     case CTYPE_WORD:
        !          2337:     case CTYPE_NOT_WORD:
        !          2338:       *len = 1;
        !          2339:       break;
        !          2340:     }
        !          2341:     break;
        !          2342: 
        !          2343:   case N_CCLASS:
        !          2344:   case N_ANYCHAR:
        !          2345:     *len = 1;
        !          2346:     break;
        !          2347: 
        !          2348:   case N_EFFECT:
        !          2349:     {
        !          2350:       EffectNode* en = &(NEFFECT(node));
        !          2351:       switch (en->type) {
        !          2352:       case EFFECT_MEMORY:
        !          2353: #ifdef USE_SUBEXP_CALL
        !          2354:        if (IS_EFFECT_CLEN_FIXED(en))
        !          2355:          *len = en->char_len;
        !          2356:        else {
        !          2357:          r = get_char_length_tree1(en->target, reg, len, level);
        !          2358:          if (r == 0) {
        !          2359:            en->char_len = *len;
        !          2360:            SET_EFFECT_STATUS(node, NST_CLEN_FIXED);
        !          2361:          }
        !          2362:        }
        !          2363:        break;
        !          2364: #endif
        !          2365:       case EFFECT_OPTION:
        !          2366:       case EFFECT_STOP_BACKTRACK:
        !          2367:        r = get_char_length_tree1(en->target, reg, len, level);
        !          2368:        break;
        !          2369:       default:
        !          2370:        break;
        !          2371:       }
        !          2372:     }
        !          2373:     break;
        !          2374: 
        !          2375:   case N_ANCHOR:
        !          2376:     break;
        !          2377: 
        !          2378:   default:
        !          2379:     r = GET_CHAR_LEN_VARLEN;
        !          2380:     break;
        !          2381:   }
        !          2382: 
        !          2383:   return r;
        !          2384: }
        !          2385: 
        !          2386: static int
        !          2387: get_char_length_tree(Node* node, regex_t* reg, int* len)
        !          2388: {
        !          2389:   return get_char_length_tree1(node, reg, len, 0);
        !          2390: }
        !          2391: 
        !          2392: /* x is not included y ==>  1 : 0 */
        !          2393: static int
        !          2394: is_not_included(Node* x, Node* y, regex_t* reg)
        !          2395: {
        !          2396:   int i, len;
        !          2397:   OnigCodePoint code;
        !          2398:   UChar *p, c;
        !          2399:   int ytype;
        !          2400: 
        !          2401:  retry:
        !          2402:   ytype = NTYPE(y);
        !          2403:   switch (NTYPE(x)) {
        !          2404:   case N_CTYPE:
        !          2405:     {
        !          2406:       switch (ytype) {
        !          2407:       case N_CTYPE:
        !          2408:        switch (NCTYPE(x).type) {
        !          2409:        case CTYPE_WORD:
        !          2410:          if (NCTYPE(y).type == CTYPE_NOT_WORD)
        !          2411:            return 1;
        !          2412:          else
        !          2413:            return 0;
        !          2414:          break;
        !          2415:        case CTYPE_NOT_WORD:
        !          2416:          if (NCTYPE(y).type == CTYPE_WORD)
        !          2417:            return 1;
        !          2418:          else
        !          2419:            return 0;
        !          2420:          break;
        !          2421:        default:
        !          2422:          break;
        !          2423:        }
        !          2424:        break;
        !          2425: 
        !          2426:       case N_CCLASS:
        !          2427:       swap:
        !          2428:        {
        !          2429:          Node* tmp;
        !          2430:          tmp = x; x = y; y = tmp;
        !          2431:          goto retry;
        !          2432:        }
        !          2433:        break;
        !          2434: 
        !          2435:       case N_STRING:
        !          2436:        goto swap;
        !          2437:        break;
        !          2438: 
        !          2439:       default:
        !          2440:        break;
        !          2441:       }
        !          2442:     }
        !          2443:     break;
        !          2444: 
        !          2445:   case N_CCLASS:
        !          2446:     {
        !          2447:       CClassNode* xc = &(NCCLASS(x));
        !          2448:       switch (ytype) {
        !          2449:       case N_CTYPE:
        !          2450:        switch (NCTYPE(y).type) {
        !          2451:        case CTYPE_WORD:
        !          2452:          if (IS_NULL(xc->mbuf) && !IS_CCLASS_NOT(xc)) {
        !          2453:            for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
        !          2454:              if (BITSET_AT(xc->bs, i)) {
        !          2455:                if (ONIGENC_IS_CODE_SB_WORD(reg->enc, i)) return 0;
        !          2456:              }
        !          2457:            }
        !          2458:            return 1;
        !          2459:          }
        !          2460:          return 0;
        !          2461:          break;
        !          2462:        case CTYPE_NOT_WORD:
        !          2463:          for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
        !          2464:            if (! ONIGENC_IS_CODE_SB_WORD(reg->enc, i)) {
        !          2465:              if (!IS_CCLASS_NOT(xc)) {
        !          2466:                if (BITSET_AT(xc->bs, i))
        !          2467:                  return 0;
        !          2468:              }
        !          2469:              else {
        !          2470:                if (! BITSET_AT(xc->bs, i))
        !          2471:                  return 0;
        !          2472:              }
        !          2473:            }
        !          2474:          }
        !          2475:          return 1;
        !          2476:          break;
        !          2477: 
        !          2478:        default:
        !          2479:          break;
        !          2480:        }
        !          2481:        break;
        !          2482: 
        !          2483:       case N_CCLASS:
        !          2484:        {
        !          2485:          int v;
        !          2486:          CClassNode* yc = &(NCCLASS(y));
        !          2487: 
        !          2488:          for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
        !          2489:            v = BITSET_AT(xc->bs, i);
        !          2490:            if ((v != 0 && !IS_CCLASS_NOT(xc)) ||
        !          2491:                 (v == 0 && IS_CCLASS_NOT(xc))) {
        !          2492:              v = BITSET_AT(yc->bs, i);
        !          2493:              if ((v != 0 && !IS_CCLASS_NOT(yc)) ||
        !          2494:                   (v == 0 && IS_CCLASS_NOT(yc)))
        !          2495:                return 0;
        !          2496:            }
        !          2497:          }
        !          2498:          if ((IS_NULL(xc->mbuf) && !IS_CCLASS_NOT(xc)) ||
        !          2499:              (IS_NULL(yc->mbuf) && !IS_CCLASS_NOT(yc)))
        !          2500:            return 1;
        !          2501:          return 0;
        !          2502:        }
        !          2503:        break;
        !          2504: 
        !          2505:       case N_STRING:
        !          2506:        goto swap;
        !          2507:        break;
        !          2508: 
        !          2509:       default:
        !          2510:        break;
        !          2511:       }
        !          2512:     }
        !          2513:     break;
        !          2514: 
        !          2515:   case N_STRING:
        !          2516:     {
        !          2517:       StrNode* xs = &(NSTRING(x));
        !          2518:       if (NSTRING_LEN(x) == 0)
        !          2519:        break;
        !          2520: 
        !          2521:       c = *(xs->s);
        !          2522:       switch (ytype) {
        !          2523:       case N_CTYPE:
        !          2524:        switch (NCTYPE(y).type) {
        !          2525:        case CTYPE_WORD:
        !          2526:          return (ONIGENC_IS_MBC_WORD(reg->enc, xs->s, xs->end) ? 0 : 1);
        !          2527:          break;
        !          2528:        case CTYPE_NOT_WORD:
        !          2529:          return (ONIGENC_IS_MBC_WORD(reg->enc, xs->s, xs->end) ? 1 : 0);
        !          2530:          break;
        !          2531:        default:
        !          2532:          break;
        !          2533:        }
        !          2534:        break;
        !          2535: 
        !          2536:       case N_CCLASS:
        !          2537:        {
        !          2538:          CClassNode* cc = &(NCCLASS(y));
        !          2539: 
        !          2540:          code = ONIGENC_MBC_TO_CODE(reg->enc, xs->s,
        !          2541:                                     xs->s + ONIGENC_MBC_MAXLEN(reg->enc));
        !          2542:          return (onig_is_code_in_cc(reg->enc, code, cc) != 0 ? 0 : 1);
        !          2543:        }
        !          2544:        break;
        !          2545: 
        !          2546:       case N_STRING:
        !          2547:        {
        !          2548:          UChar *q;
        !          2549:          StrNode* ys = &(NSTRING(y));
        !          2550:          len = NSTRING_LEN(x);
        !          2551:          if (len > NSTRING_LEN(y)) len = NSTRING_LEN(y);
        !          2552:          if (NSTRING_IS_AMBIG(x) || NSTRING_IS_AMBIG(y)) {
        !          2553:             /* tiny version */
        !          2554:             return 0;
        !          2555:          }
        !          2556:          else {
        !          2557:            for (i = 0, p = ys->s, q = xs->s; i < len; i++, p++, q++) {
        !          2558:              if (*p != *q) return 1;
        !          2559:            }
        !          2560:          }
        !          2561:        }
        !          2562:        break;
        !          2563:        
        !          2564:       default:
        !          2565:        break;
        !          2566:       }
        !          2567:     }
        !          2568:     break;
        !          2569: 
        !          2570:   default:
        !          2571:     break;
        !          2572:   }
        !          2573: 
        !          2574:   return 0;
        !          2575: }
        !          2576: 
        !          2577: static Node*
        !          2578: get_head_value_node(Node* node, int exact, regex_t* reg)
        !          2579: {
        !          2580:   Node* n = NULL_NODE;
        !          2581: 
        !          2582:   switch (NTYPE(node)) {
        !          2583:   case N_BACKREF:
        !          2584:   case N_ALT:
        !          2585:   case N_ANYCHAR:
        !          2586: #ifdef USE_SUBEXP_CALL
        !          2587:   case N_CALL:
        !          2588: #endif
        !          2589:     break;
        !          2590: 
        !          2591:   case N_CTYPE:
        !          2592:   case N_CCLASS:
        !          2593:     if (exact == 0) {
        !          2594:       n = node;
        !          2595:     }
        !          2596:     break;
        !          2597: 
        !          2598:   case N_LIST:
        !          2599:     n = get_head_value_node(NCONS(node).left, exact, reg);
        !          2600:     break;
        !          2601: 
        !          2602:   case N_STRING:
        !          2603:     {
        !          2604:       StrNode* sn = &(NSTRING(node));
        !          2605: 
        !          2606:       if (sn->end <= sn->s)
        !          2607:        break;
        !          2608: 
        !          2609:       if (exact != 0 &&
        !          2610:          !NSTRING_IS_RAW(node) && IS_IGNORECASE(reg->options)) {
        !          2611: #if 0
        !          2612:         UChar* tmp = sn->s;
        !          2613:        if (! ONIGENC_IS_MBC_AMBIGUOUS(reg->enc, reg->ambig_flag,
        !          2614:                                        &tmp, sn->end))
        !          2615:          n = node;
        !          2616: #endif
        !          2617:       }
        !          2618:       else {
        !          2619:        n = node;
        !          2620:       }
        !          2621:     }
        !          2622:     break;
        !          2623: 
        !          2624:   case N_QUANTIFIER:
        !          2625:     {
        !          2626:       QuantifierNode* qn = &(NQUANTIFIER(node));
        !          2627:       if (qn->lower > 0) {
        !          2628:        if (IS_NOT_NULL(qn->head_exact))
        !          2629:          n = qn->head_exact;
        !          2630:        else
        !          2631:          n = get_head_value_node(qn->target, exact, reg);
        !          2632:       }
        !          2633:     }
        !          2634:     break;
        !          2635: 
        !          2636:   case N_EFFECT:
        !          2637:     {
        !          2638:       EffectNode* en = &(NEFFECT(node));
        !          2639:       switch (en->type) {
        !          2640:       case EFFECT_OPTION:
        !          2641:        {
        !          2642:          OnigOptionType options = reg->options;
        !          2643: 
        !          2644:          reg->options = NEFFECT(node).option;
        !          2645:          n = get_head_value_node(NEFFECT(node).target, exact, reg);
        !          2646:          reg->options = options;
        !          2647:        }
        !          2648:        break;
        !          2649: 
        !          2650:       case EFFECT_MEMORY:
        !          2651:       case EFFECT_STOP_BACKTRACK:
        !          2652:        n = get_head_value_node(en->target, exact, reg);
        !          2653:        break;
        !          2654:       }
        !          2655:     }
        !          2656:     break;
        !          2657: 
        !          2658:   case N_ANCHOR:
        !          2659:     if (NANCHOR(node).type == ANCHOR_PREC_READ)
        !          2660:       n = get_head_value_node(NANCHOR(node).target, exact, reg);
        !          2661:     break;
        !          2662: 
        !          2663:   default:
        !          2664:     break;
        !          2665:   }
        !          2666: 
        !          2667:   return n;
        !          2668: }
        !          2669: 
        !          2670: static int
        !          2671: check_type_tree(Node* node, int type_mask, int effect_mask, int anchor_mask)
        !          2672: {
        !          2673:   int type, r = 0;
        !          2674: 
        !          2675:   type = NTYPE(node);
        !          2676:   if ((type & type_mask) == 0)
        !          2677:     return 1;
        !          2678: 
        !          2679:   switch (type) {
        !          2680:   case N_LIST:
        !          2681:   case N_ALT:
        !          2682:     do {
        !          2683:       r = check_type_tree(NCONS(node).left, type_mask, effect_mask, anchor_mask);
        !          2684:     } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
        !          2685:     break;
        !          2686: 
        !          2687:   case N_QUANTIFIER:
        !          2688:     r = check_type_tree(NQUANTIFIER(node).target, type_mask, effect_mask,
        !          2689:                        anchor_mask);
        !          2690:     break;
        !          2691: 
        !          2692:   case N_EFFECT:
        !          2693:     {
        !          2694:       EffectNode* en = &(NEFFECT(node));
        !          2695:       if ((en->type & effect_mask) == 0)
        !          2696:        return 1;
        !          2697: 
        !          2698:       r = check_type_tree(en->target, type_mask, effect_mask, anchor_mask);
        !          2699:     }
        !          2700:     break;
        !          2701: 
        !          2702:   case N_ANCHOR:
        !          2703:     type = NANCHOR(node).type;
        !          2704:     if ((type & anchor_mask) == 0)
        !          2705:       return 1;
        !          2706: 
        !          2707:     if (NANCHOR(node).target)
        !          2708:       r = check_type_tree(NANCHOR(node).target,
        !          2709:                          type_mask, effect_mask, anchor_mask);
        !          2710:     break;
        !          2711: 
        !          2712:   default:
        !          2713:     break;
        !          2714:   }
        !          2715:   return r;
        !          2716: }
        !          2717: 
        !          2718: #ifdef USE_SUBEXP_CALL
        !          2719: 
        !          2720: #define RECURSION_EXIST       1
        !          2721: #define RECURSION_INFINITE    2
        !          2722: 
        !          2723: static int
        !          2724: subexp_inf_recursive_check(Node* node, ScanEnv* env, int head)
        !          2725: {
        !          2726:   int type;
        !          2727:   int r = 0;
        !          2728: 
        !          2729:   type = NTYPE(node);
        !          2730:   switch (type) {
        !          2731:   case N_LIST:
        !          2732:     {
        !          2733:       Node *x;
        !          2734:       OnigDistance min;
        !          2735:       int ret;
        !          2736: 
        !          2737:       x = node;
        !          2738:       do {
        !          2739:        ret = subexp_inf_recursive_check(NCONS(x).left, env, head);
        !          2740:        if (ret < 0 || ret == RECURSION_INFINITE) return ret;
        !          2741:        r |= ret;
        !          2742:        if (head) {
        !          2743:          ret = get_min_match_length(NCONS(x).left, &min, env);
        !          2744:          if (ret != 0) return ret;
        !          2745:          if (min != 0) head = 0;
        !          2746:        }
        !          2747:       } while (IS_NOT_NULL(x = NCONS(x).right));
        !          2748:     }
        !          2749:     break;
        !          2750: 
        !          2751:   case N_ALT:
        !          2752:     {
        !          2753:       int ret;
        !          2754:       r = RECURSION_EXIST;
        !          2755:       do {
        !          2756:        ret = subexp_inf_recursive_check(NCONS(node).left, env, head);
        !          2757:        if (ret < 0 || ret == RECURSION_INFINITE) return ret;
        !          2758:        r &= ret;
        !          2759:       } while (IS_NOT_NULL(node = NCONS(node).right));
        !          2760:     }
        !          2761:     break;
        !          2762: 
        !          2763:   case N_QUANTIFIER:
        !          2764:     r = subexp_inf_recursive_check(NQUANTIFIER(node).target, env, head);
        !          2765:     if (r == RECURSION_EXIST) {
        !          2766:       if (NQUANTIFIER(node).lower == 0) r = 0;
        !          2767:     }
        !          2768:     break;
        !          2769: 
        !          2770:   case N_ANCHOR:
        !          2771:     {
        !          2772:       AnchorNode* an = &(NANCHOR(node));
        !          2773:       switch (an->type) {
        !          2774:       case ANCHOR_PREC_READ:
        !          2775:       case ANCHOR_PREC_READ_NOT:
        !          2776:       case ANCHOR_LOOK_BEHIND:
        !          2777:       case ANCHOR_LOOK_BEHIND_NOT:
        !          2778:        r = subexp_inf_recursive_check(an->target, env, head);
        !          2779:        break;
        !          2780:       }
        !          2781:     }
        !          2782:     break;
        !          2783: 
        !          2784:   case N_CALL:
        !          2785:     r = subexp_inf_recursive_check(NCALL(node).target, env, head);
        !          2786:     break;
        !          2787: 
        !          2788:   case N_EFFECT:
        !          2789:     if (IS_EFFECT_MARK2(&(NEFFECT(node))))
        !          2790:       return 0;
        !          2791:     else if (IS_EFFECT_MARK1(&(NEFFECT(node))))
        !          2792:       return (head == 0 ? RECURSION_EXIST : RECURSION_INFINITE);
        !          2793:     else {
        !          2794:       SET_EFFECT_STATUS(node, NST_MARK2);
        !          2795:       r = subexp_inf_recursive_check(NEFFECT(node).target, env, head);
        !          2796:       CLEAR_EFFECT_STATUS(node, NST_MARK2);
        !          2797:     }
        !          2798:     break;
        !          2799: 
        !          2800:   default:
        !          2801:     break;
        !          2802:   }
        !          2803: 
        !          2804:   return r;
        !          2805: }
        !          2806: 
        !          2807: static int
        !          2808: subexp_inf_recursive_check_trav(Node* node, ScanEnv* env)
        !          2809: {
        !          2810:   int type;
        !          2811:   int r = 0;
        !          2812: 
        !          2813:   type = NTYPE(node);
        !          2814:   switch (type) {
        !          2815:   case N_LIST:
        !          2816:   case N_ALT:
        !          2817:     do {
        !          2818:       r = subexp_inf_recursive_check_trav(NCONS(node).left, env);
        !          2819:     } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
        !          2820:     break;
        !          2821: 
        !          2822:   case N_QUANTIFIER:
        !          2823:     r = subexp_inf_recursive_check_trav(NQUANTIFIER(node).target, env);
        !          2824:     break;
        !          2825: 
        !          2826:   case N_ANCHOR:
        !          2827:     {
        !          2828:       AnchorNode* an = &(NANCHOR(node));
        !          2829:       switch (an->type) {
        !          2830:       case ANCHOR_PREC_READ:
        !          2831:       case ANCHOR_PREC_READ_NOT:
        !          2832:       case ANCHOR_LOOK_BEHIND:
        !          2833:       case ANCHOR_LOOK_BEHIND_NOT:
        !          2834:        r = subexp_inf_recursive_check_trav(an->target, env);
        !          2835:        break;
        !          2836:       }
        !          2837:     }
        !          2838:     break;
        !          2839: 
        !          2840:   case N_EFFECT:
        !          2841:     {
        !          2842:       EffectNode* en = &(NEFFECT(node));
        !          2843: 
        !          2844:       if (IS_EFFECT_RECURSION(en)) {
        !          2845:        SET_EFFECT_STATUS(node, NST_MARK1);
        !          2846:        r = subexp_inf_recursive_check(en->target, env, 1);
        !          2847:        if (r > 0) return ONIGERR_NEVER_ENDING_RECURSION;
        !          2848:        CLEAR_EFFECT_STATUS(node, NST_MARK1);
        !          2849:       }
        !          2850:       r = subexp_inf_recursive_check_trav(en->target, env);
        !          2851:     }
        !          2852: 
        !          2853:     break;
        !          2854: 
        !          2855:   default:
        !          2856:     break;
        !          2857:   }
        !          2858: 
        !          2859:   return r;
        !          2860: }
        !          2861: 
        !          2862: static int
        !          2863: subexp_recursive_check(Node* node)
        !          2864: {
        !          2865:   int type;
        !          2866:   int r = 0;
        !          2867: 
        !          2868:   type = NTYPE(node);
        !          2869:   switch (type) {
        !          2870:   case N_LIST:
        !          2871:   case N_ALT:
        !          2872:     do {
        !          2873:       r |= subexp_recursive_check(NCONS(node).left);
        !          2874:     } while (IS_NOT_NULL(node = NCONS(node).right));
        !          2875:     break;
        !          2876: 
        !          2877:   case N_QUANTIFIER:
        !          2878:     r = subexp_recursive_check(NQUANTIFIER(node).target);
        !          2879:     break;
        !          2880: 
        !          2881:   case N_ANCHOR:
        !          2882:     {
        !          2883:       AnchorNode* an = &(NANCHOR(node));
        !          2884:       switch (an->type) {
        !          2885:       case ANCHOR_PREC_READ:
        !          2886:       case ANCHOR_PREC_READ_NOT:
        !          2887:       case ANCHOR_LOOK_BEHIND:
        !          2888:       case ANCHOR_LOOK_BEHIND_NOT:
        !          2889:        r = subexp_recursive_check(an->target);
        !          2890:        break;
        !          2891:       }
        !          2892:     }
        !          2893:     break;
        !          2894: 
        !          2895:   case N_CALL:
        !          2896:     r = subexp_recursive_check(NCALL(node).target);
        !          2897:     if (r != 0) SET_CALL_RECURSION(node);
        !          2898:     break;
        !          2899: 
        !          2900:   case N_EFFECT:
        !          2901:     if (IS_EFFECT_MARK2(&(NEFFECT(node))))
        !          2902:       return 0;
        !          2903:     else if (IS_EFFECT_MARK1(&(NEFFECT(node))))
        !          2904:       return 1; /* recursion */
        !          2905:     else {
        !          2906:       SET_EFFECT_STATUS(node, NST_MARK2);
        !          2907:       r = subexp_recursive_check(NEFFECT(node).target);
        !          2908:       CLEAR_EFFECT_STATUS(node, NST_MARK2);
        !          2909:     }
        !          2910:     break;
        !          2911: 
        !          2912:   default:
        !          2913:     break;
        !          2914:   }
        !          2915: 
        !          2916:   return r;
        !          2917: }
        !          2918: 
        !          2919: 
        !          2920: static int
        !          2921: subexp_recursive_check_trav(Node* node, ScanEnv* env)
        !          2922: {
        !          2923: #define FOUND_CALLED_NODE    1
        !          2924: 
        !          2925:   int type;
        !          2926:   int r = 0;
        !          2927: 
        !          2928:   type = NTYPE(node);
        !          2929:   switch (type) {
        !          2930:   case N_LIST:
        !          2931:   case N_ALT:
        !          2932:     {
        !          2933:       int ret;
        !          2934:       do {
        !          2935:        ret = subexp_recursive_check_trav(NCONS(node).left, env);
        !          2936:        if (ret == FOUND_CALLED_NODE) r = FOUND_CALLED_NODE;
        !          2937:        else if (ret < 0) return ret;
        !          2938:       } while (IS_NOT_NULL(node = NCONS(node).right));
        !          2939:     }
        !          2940:     break;
        !          2941: 
        !          2942:   case N_QUANTIFIER:
        !          2943:     r = subexp_recursive_check_trav(NQUANTIFIER(node).target, env);
        !          2944:     if (NQUANTIFIER(node).upper == 0) {
        !          2945:       if (r == FOUND_CALLED_NODE)
        !          2946:        NQUANTIFIER(node).is_refered = 1;
        !          2947:     }
        !          2948:     break;
        !          2949: 
        !          2950:   case N_ANCHOR:
        !          2951:     {
        !          2952:       AnchorNode* an = &(NANCHOR(node));
        !          2953:       switch (an->type) {
        !          2954:       case ANCHOR_PREC_READ:
        !          2955:       case ANCHOR_PREC_READ_NOT:
        !          2956:       case ANCHOR_LOOK_BEHIND:
        !          2957:       case ANCHOR_LOOK_BEHIND_NOT:
        !          2958:        r = subexp_recursive_check_trav(an->target, env);
        !          2959:        break;
        !          2960:       }
        !          2961:     }
        !          2962:     break;
        !          2963: 
        !          2964:   case N_EFFECT:
        !          2965:     {
        !          2966:       EffectNode* en = &(NEFFECT(node));
        !          2967: 
        !          2968:       if (! IS_EFFECT_RECURSION(en)) {
        !          2969:        if (IS_EFFECT_CALLED(en)) {
        !          2970:          SET_EFFECT_STATUS(node, NST_MARK1);
        !          2971:          r = subexp_recursive_check(en->target);
        !          2972:          if (r != 0) SET_EFFECT_STATUS(node, NST_RECURSION);
        !          2973:          CLEAR_EFFECT_STATUS(node, NST_MARK1);
        !          2974:        }
        !          2975:       }
        !          2976:       r = subexp_recursive_check_trav(en->target, env);
        !          2977:       if (IS_EFFECT_CALLED(en))
        !          2978:        r |= FOUND_CALLED_NODE;
        !          2979:     }
        !          2980:     break;
        !          2981: 
        !          2982:   default:
        !          2983:     break;
        !          2984:   }
        !          2985: 
        !          2986:   return r;
        !          2987: }
        !          2988: 
        !          2989: static int
        !          2990: setup_subexp_call(Node* node, ScanEnv* env)
        !          2991: {
        !          2992:   int type;
        !          2993:   int r = 0;
        !          2994: 
        !          2995:   type = NTYPE(node);
        !          2996:   switch (type) {
        !          2997:   case N_LIST:
        !          2998:     do {
        !          2999:       r = setup_subexp_call(NCONS(node).left, env);
        !          3000:     } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
        !          3001:     break;
        !          3002: 
        !          3003:   case N_ALT:
        !          3004:     do {
        !          3005:       r = setup_subexp_call(NCONS(node).left, env);
        !          3006:     } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
        !          3007:     break;
        !          3008: 
        !          3009:   case N_QUANTIFIER:
        !          3010:     r = setup_subexp_call(NQUANTIFIER(node).target, env);
        !          3011:     break;
        !          3012:   case N_EFFECT:
        !          3013:     r = setup_subexp_call(NEFFECT(node).target, env);
        !          3014:     break;
        !          3015: 
        !          3016:   case N_CALL:
        !          3017:     {
        !          3018:       int n, num, *refs;
        !          3019:       UChar *p;
        !          3020:       CallNode* cn = &(NCALL(node));
        !          3021:       Node** nodes = SCANENV_MEM_NODES(env);
        !          3022: 
        !          3023: #ifdef USE_NAMED_GROUP
        !          3024:       n = onig_name_to_group_numbers(env->reg, cn->name, cn->name_end, &refs);
        !          3025: #else
        !          3026:       n = -1;
        !          3027: #endif
        !          3028:       if (n <= 0) {
        !          3029:        /* name not found, check group number. (?*ddd) */
        !          3030:        p = cn->name;
        !          3031:        num = onig_scan_unsigned_number(&p, cn->name_end, env->enc);
        !          3032:        if (num <= 0 || p != cn->name_end) {
        !          3033:          onig_scan_env_set_error_string(env,
        !          3034:                  ONIGERR_UNDEFINED_NAME_REFERENCE, cn->name, cn->name_end);
        !          3035:          return ONIGERR_UNDEFINED_NAME_REFERENCE;
        !          3036:        }
        !          3037: #ifdef USE_NAMED_GROUP
        !          3038:        if (env->num_named > 0 &&
        !          3039:            IS_SYNTAX_BV(env->syntax, ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP) &&
        !          3040:            !ONIG_IS_OPTION_ON(env->option, ONIG_OPTION_CAPTURE_GROUP)) {
        !          3041:          return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;
        !          3042:        }
        !          3043: #endif
        !          3044:        if (num > env->num_mem) {
        !          3045:          onig_scan_env_set_error_string(env,
        !          3046:                 ONIGERR_UNDEFINED_GROUP_REFERENCE, cn->name, cn->name_end);
        !          3047:          return ONIGERR_UNDEFINED_GROUP_REFERENCE;
        !          3048:        }
        !          3049:        cn->ref_num = num;
        !          3050:        goto set_call_attr;
        !          3051:       }
        !          3052:       else if (n > 1) {
        !          3053:        onig_scan_env_set_error_string(env,
        !          3054:               ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL, cn->name, cn->name_end);
        !          3055:        return ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL;
        !          3056:       }
        !          3057:       else {
        !          3058:        cn->ref_num = refs[0];
        !          3059:       set_call_attr:
        !          3060:        cn->target = nodes[cn->ref_num];
        !          3061:        if (IS_NULL(cn->target)) {
        !          3062:          onig_scan_env_set_error_string(env,
        !          3063:                  ONIGERR_UNDEFINED_NAME_REFERENCE, cn->name, cn->name_end);
        !          3064:          return ONIGERR_UNDEFINED_NAME_REFERENCE;
        !          3065:        }
        !          3066:        SET_EFFECT_STATUS(cn->target, NST_CALLED);
        !          3067:        BIT_STATUS_ON_AT(env->bt_mem_start, cn->ref_num);
        !          3068:        cn->unset_addr_list = env->unset_addr_list;
        !          3069:       }
        !          3070:     }
        !          3071:     break;
        !          3072: 
        !          3073:   case N_ANCHOR:
        !          3074:     {
        !          3075:       AnchorNode* an = &(NANCHOR(node));
        !          3076: 
        !          3077:       switch (an->type) {
        !          3078:       case ANCHOR_PREC_READ:
        !          3079:       case ANCHOR_PREC_READ_NOT:
        !          3080:       case ANCHOR_LOOK_BEHIND:
        !          3081:       case ANCHOR_LOOK_BEHIND_NOT:
        !          3082:        r = setup_subexp_call(an->target, env);
        !          3083:        break;
        !          3084:       }
        !          3085:     }
        !          3086:     break;
        !          3087: 
        !          3088:   default:
        !          3089:     break;
        !          3090:   }
        !          3091: 
        !          3092:   return r;
        !          3093: }
        !          3094: #endif
        !          3095: 
        !          3096: /* divide different length alternatives in look-behind.
        !          3097:   (?<=A|B) ==> (?<=A)|(?<=B)
        !          3098:   (?<!A|B) ==> (?<!A)(?<!B)
        !          3099: */
        !          3100: static int
        !          3101: divide_look_behind_alternatives(Node* node)
        !          3102: {
        !          3103:   Node tmp_node;
        !          3104:   Node *head, *np, *insert_node;
        !          3105:   AnchorNode* an = &(NANCHOR(node));
        !          3106:   int anc_type = an->type;
        !          3107: 
        !          3108:   head = an->target;
        !          3109:   np = NCONS(head).left;
        !          3110:   tmp_node = *node; *node = *head; *head = tmp_node;
        !          3111:   NCONS(node).left = head;
        !          3112:   NANCHOR(head).target = np;
        !          3113: 
        !          3114:   np = node;
        !          3115:   while ((np = NCONS(np).right) != NULL_NODE) {
        !          3116:     insert_node = onig_node_new_anchor(anc_type);
        !          3117:     CHECK_NULL_RETURN_VAL(insert_node, ONIGERR_MEMORY);
        !          3118:     NANCHOR(insert_node).target = NCONS(np).left;
        !          3119:     NCONS(np).left = insert_node;
        !          3120:   }
        !          3121: 
        !          3122:   if (anc_type == ANCHOR_LOOK_BEHIND_NOT) {
        !          3123:     np = node;
        !          3124:     do {
        !          3125:       np->type = N_LIST;  /* alt -> list */
        !          3126:     } while ((np = NCONS(np).right) != NULL_NODE);
        !          3127:   }
        !          3128:   return 0;
        !          3129: }
        !          3130: 
        !          3131: static int
        !          3132: setup_look_behind(Node* node, regex_t* reg, ScanEnv* env)
        !          3133: {
        !          3134:   int r, len;
        !          3135:   AnchorNode* an = &(NANCHOR(node));
        !          3136: 
        !          3137:   r = get_char_length_tree(an->target, reg, &len);
        !          3138:   if (r == 0)
        !          3139:     an->char_len = len;
        !          3140:   else if (r == GET_CHAR_LEN_VARLEN)
        !          3141:     r = ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
        !          3142:   else if (r == GET_CHAR_LEN_TOP_ALT_VARLEN) {
        !          3143:     if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_DIFFERENT_LEN_ALT_LOOK_BEHIND))
        !          3144:       r = divide_look_behind_alternatives(node);
        !          3145:     else
        !          3146:       r = ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
        !          3147:   }
        !          3148: 
        !          3149:   return r;
        !          3150: }
        !          3151: 
        !          3152: static int
        !          3153: next_setup(Node* node, Node* next_node, regex_t* reg)
        !          3154: {
        !          3155:   int type;
        !          3156: 
        !          3157:  retry:
        !          3158:   type = NTYPE(node);
        !          3159:   if (type == N_QUANTIFIER) {
        !          3160:     QuantifierNode* qn = &(NQUANTIFIER(node));
        !          3161:     if (qn->greedy && IS_REPEAT_INFINITE(qn->upper)) {
        !          3162: #ifdef USE_QUANTIFIER_PEEK_NEXT
        !          3163:       qn->next_head_exact = get_head_value_node(next_node, 1, reg);
        !          3164: #endif
        !          3165:       /* automatic posseivation a*b ==> (?>a*)b */
        !          3166:       if (qn->lower <= 1) {
        !          3167:        int ttype = NTYPE(qn->target);
        !          3168:        if (IS_NODE_TYPE_SIMPLE(ttype)) {
        !          3169:          Node *x, *y;
        !          3170:          x = get_head_value_node(qn->target, 0, reg);
        !          3171:          if (IS_NOT_NULL(x)) {
        !          3172:            y = get_head_value_node(next_node,  0, reg);
        !          3173:            if (IS_NOT_NULL(y) && is_not_included(x, y, reg)) {
        !          3174:              Node* en = onig_node_new_effect(EFFECT_STOP_BACKTRACK);
        !          3175:              CHECK_NULL_RETURN_VAL(en, ONIGERR_MEMORY);
        !          3176:              SET_EFFECT_STATUS(en, NST_STOP_BT_SIMPLE_REPEAT);
        !          3177:              swap_node(node, en);
        !          3178:              NEFFECT(node).target = en;
        !          3179:            }
        !          3180:          }
        !          3181:        }
        !          3182:       }
        !          3183:     }
        !          3184:   }
        !          3185:   else if (type == N_EFFECT) {
        !          3186:     EffectNode* en = &(NEFFECT(node));
        !          3187:     if (en->type == EFFECT_MEMORY) {
        !          3188:       node = en->target;
        !          3189:       goto retry;
        !          3190:     }
        !          3191:   }
        !          3192:   return 0;
        !          3193: }
        !          3194: 
        !          3195: 
        !          3196: static int
        !          3197: divide_ambig_string_node_sub(regex_t* reg, int prev_ambig,
        !          3198:                              UChar* prev_start, UChar* prev,
        !          3199:                              UChar* end, Node*** tailp, Node** root)
        !          3200: {
        !          3201:   UChar *tmp, *wp;
        !          3202:   Node* snode;
        !          3203: 
        !          3204:   if (prev_ambig != 0) {
        !          3205:     tmp = prev_start;
        !          3206:     wp  = prev_start;
        !          3207:     while (tmp < prev) {
        !          3208:       wp += ONIGENC_MBC_TO_NORMALIZE(reg->enc, reg->ambig_flag,
        !          3209:                                      &tmp, end, wp);
        !          3210:     }
        !          3211:     snode = onig_node_new_str(prev_start, wp);
        !          3212:     CHECK_NULL_RETURN_VAL(snode, ONIGERR_MEMORY);
        !          3213:     NSTRING_SET_AMBIG(snode);
        !          3214:     if (wp != prev) NSTRING_SET_AMBIG_REDUCE(snode);
        !          3215:   }
        !          3216:   else {
        !          3217:     snode = onig_node_new_str(prev_start, prev);
        !          3218:     CHECK_NULL_RETURN_VAL(snode, ONIGERR_MEMORY);
        !          3219:   }
        !          3220: 
        !          3221:   if (*tailp == (Node** )0) {
        !          3222:     *root = onig_node_new_list(snode, NULL);
        !          3223:     CHECK_NULL_RETURN_VAL(*root, ONIGERR_MEMORY);
        !          3224:     *tailp = &(NCONS(*root).right);
        !          3225:   }
        !          3226:   else {
        !          3227:     **tailp = onig_node_new_list(snode, NULL);
        !          3228:     CHECK_NULL_RETURN_VAL(**tailp, ONIGERR_MEMORY);
        !          3229:     *tailp = &(NCONS(**tailp).right);
        !          3230:   }
        !          3231: 
        !          3232:   return 0;
        !          3233: }
        !          3234: 
        !          3235: static int
        !          3236: divide_ambig_string_node(Node* node, regex_t* reg)
        !          3237: {
        !          3238:   StrNode* sn = &NSTRING(node);
        !          3239:   int ambig, prev_ambig;
        !          3240:   UChar *prev, *p, *end, *prev_start, *start, *tmp, *wp;
        !          3241:   Node *root = NULL_NODE;
        !          3242:   Node **tailp = (Node** )0;
        !          3243:   int r;
        !          3244: 
        !          3245:   start = prev_start = p = sn->s;
        !          3246:   end  = sn->end;
        !          3247:   if (p >= end) return 0;
        !          3248: 
        !          3249:   prev_ambig = ONIGENC_IS_MBC_AMBIGUOUS(reg->enc, reg->ambig_flag, &p, end);
        !          3250: 
        !          3251:   while (p < end) {
        !          3252:     prev = p;
        !          3253:     if (prev_ambig != (ambig = ONIGENC_IS_MBC_AMBIGUOUS(reg->enc,
        !          3254:                                               reg->ambig_flag, &p, end))) {
        !          3255: 
        !          3256:       r = divide_ambig_string_node_sub(reg, prev_ambig, prev_start, prev,
        !          3257:                                        end, &tailp, &root);
        !          3258:       if (r != 0) return r;
        !          3259: 
        !          3260:       prev_ambig = ambig;
        !          3261:       prev_start = prev;
        !          3262:     }
        !          3263:   }
        !          3264: 
        !          3265:   if (prev_start == start) {
        !          3266:     if (prev_ambig != 0) {
        !          3267:       NSTRING_SET_AMBIG(node);
        !          3268:       tmp = start;
        !          3269:       wp  = start;
        !          3270:       while (tmp < end) {
        !          3271:         wp += ONIGENC_MBC_TO_NORMALIZE(reg->enc, reg->ambig_flag,
        !          3272:                                        &tmp, end, wp);
        !          3273:       }
        !          3274:       if (wp != sn->end) NSTRING_SET_AMBIG_REDUCE(node);
        !          3275:       sn->end = wp;
        !          3276:     }
        !          3277:   }
        !          3278:   else {
        !          3279:     r = divide_ambig_string_node_sub(reg, prev_ambig, prev_start, end,
        !          3280:                                      end, &tailp, &root);
        !          3281:     if (r != 0) return r;
        !          3282: 
        !          3283:     swap_node(node, root);
        !          3284:     onig_node_str_clear(root); /* should be after swap! */
        !          3285:     onig_node_free(root);      /* free original string node */
        !          3286:   }
        !          3287: 
        !          3288:   return 0;
        !          3289: }
        !          3290: 
        !          3291: #ifdef USE_COMBINATION_EXPLOSION_CHECK
        !          3292: 
        !          3293: #define CEC_THRES_NUM_BIG_REPEAT         512
        !          3294: #define CEC_INFINITE_NUM          0x7fffffff
        !          3295: 
        !          3296: #define CEC_IN_INFINITE_REPEAT    (1<<0)
        !          3297: #define CEC_IN_FINITE_REPEAT      (1<<1)
        !          3298: #define CEC_CONT_BIG_REPEAT       (1<<2)
        !          3299: 
        !          3300: static int
        !          3301: setup_comb_exp_check(Node* node, int state, ScanEnv* env)
        !          3302: {
        !          3303:   int type;
        !          3304:   int r = state;
        !          3305: 
        !          3306:   type = NTYPE(node);
        !          3307:   switch (type) {
        !          3308:   case N_LIST:
        !          3309:     {
        !          3310:       Node* prev = NULL_NODE;
        !          3311:       do {
        !          3312:        r = setup_comb_exp_check(NCONS(node).left, r, env);
        !          3313:        prev = NCONS(node).left;
        !          3314:       } while (r >= 0 && IS_NOT_NULL(node = NCONS(node).right));
        !          3315:     }
        !          3316:     break;
        !          3317: 
        !          3318:   case N_ALT:
        !          3319:     {
        !          3320:       int ret;
        !          3321:       do {
        !          3322:        ret = setup_comb_exp_check(NCONS(node).left, state, env);
        !          3323:        r |= ret;
        !          3324:       } while (ret >= 0 && IS_NOT_NULL(node = NCONS(node).right));
        !          3325:     }
        !          3326:     break;
        !          3327: 
        !          3328:   case N_QUANTIFIER:
        !          3329:     {
        !          3330:       int child_state = state;
        !          3331:       int add_state = 0;
        !          3332:       QuantifierNode* qn = &(NQUANTIFIER(node));
        !          3333:       Node* target = qn->target;
        !          3334:       int var_num;
        !          3335: 
        !          3336:       if (! IS_REPEAT_INFINITE(qn->upper)) {
        !          3337:        if (qn->upper > 1) {
        !          3338:          /* {0,1}, {1,1} are allowed */
        !          3339:          child_state |= CEC_IN_FINITE_REPEAT;
        !          3340: 
        !          3341:          /* check (a*){n,m}, (a+){n,m} => (a*){n,n}, (a+){n,n} */
        !          3342:          if (env->backrefed_mem == 0) {
        !          3343:            if (NTYPE(qn->target) == N_EFFECT) {
        !          3344:              EffectNode* en = &(NEFFECT(qn->target));
        !          3345:              if (en->type == EFFECT_MEMORY) {
        !          3346:                if (NTYPE(en->target) == N_QUANTIFIER) {
        !          3347:                  QuantifierNode* q = &(NQUANTIFIER(en->target));
        !          3348:                  if (IS_REPEAT_INFINITE(q->upper)
        !          3349:                      && q->greedy == qn->greedy) {
        !          3350:                    qn->upper = (qn->lower == 0 ? 1 : qn->lower);
        !          3351:                    if (qn->upper == 1)
        !          3352:                      child_state = state;
        !          3353:                  }
        !          3354:                }
        !          3355:              }
        !          3356:            }
        !          3357:          }
        !          3358:        }
        !          3359:       }
        !          3360: 
        !          3361:       if (state & CEC_IN_FINITE_REPEAT) {
        !          3362:        qn->comb_exp_check_num = -1;
        !          3363:       }
        !          3364:       else {
        !          3365:        if (IS_REPEAT_INFINITE(qn->upper)) {
        !          3366:          var_num = CEC_INFINITE_NUM;
        !          3367:          child_state |= CEC_IN_INFINITE_REPEAT;
        !          3368:        }
        !          3369:        else {
        !          3370:          var_num = qn->upper - qn->lower;
        !          3371:        }
        !          3372: 
        !          3373:        if (var_num >= CEC_THRES_NUM_BIG_REPEAT)
        !          3374:          add_state |= CEC_CONT_BIG_REPEAT;
        !          3375: 
        !          3376:        if (((state & CEC_IN_INFINITE_REPEAT) != 0 && var_num != 0) ||
        !          3377:            ((state & CEC_CONT_BIG_REPEAT) != 0 &&
        !          3378:             var_num >= CEC_THRES_NUM_BIG_REPEAT)) {
        !          3379:          if (qn->comb_exp_check_num == 0) {
        !          3380:            env->num_comb_exp_check++;
        !          3381:            qn->comb_exp_check_num = env->num_comb_exp_check;
        !          3382:            if (env->curr_max_regnum > env->comb_exp_max_regnum)
        !          3383:              env->comb_exp_max_regnum = env->curr_max_regnum;
        !          3384:          }
        !          3385:        }
        !          3386:       }
        !          3387: 
        !          3388:       r = setup_comb_exp_check(target, child_state, env);
        !          3389:       r |= add_state;
        !          3390:     }
        !          3391:     break;
        !          3392: 
        !          3393:   case N_EFFECT:
        !          3394:     {
        !          3395:       EffectNode* en = &(NEFFECT(node));
        !          3396: 
        !          3397:       switch (en->type) {
        !          3398:       case EFFECT_MEMORY:
        !          3399:        {
        !          3400:          if (env->curr_max_regnum < en->regnum)
        !          3401:            env->curr_max_regnum = en->regnum;
        !          3402: 
        !          3403:          r = setup_comb_exp_check(en->target, state, env);
        !          3404:        }
        !          3405:        break;
        !          3406: 
        !          3407:       default:
        !          3408:        r = setup_comb_exp_check(en->target, state, env);
        !          3409:        break;
        !          3410:       }
        !          3411:     }
        !          3412:     break;
        !          3413: 
        !          3414: #ifdef USE_SUBEXP_CALL
        !          3415:   case N_CALL:
        !          3416:     if (IS_CALL_RECURSION(&(NCALL(node))))
        !          3417:       env->has_recursion = 1;
        !          3418:     else
        !          3419:       r = setup_comb_exp_check(NCALL(node).target, state, env);
        !          3420:     break;
        !          3421: #endif
        !          3422: 
        !          3423:   default:
        !          3424:     break;
        !          3425:   }
        !          3426: 
        !          3427:   return r;
        !          3428: }
        !          3429: #endif
        !          3430: 
        !          3431: #define IN_ALT        (1<<0)
        !          3432: #define IN_NOT        (1<<1)
        !          3433: #define IN_REPEAT     (1<<2)
        !          3434: #define IN_VAR_REPEAT (1<<3)
        !          3435: 
        !          3436: /* setup_tree does the following work.
        !          3437:  1. check empty loop. (set qn->target_empty_info)
        !          3438:  2. expand ignore-case in char class.
        !          3439:  3. set memory status bit flags. (reg->mem_stats)
        !          3440:  4. set qn->head_exact for [push, exact] -> [push_or_jump_exact1, exact].
        !          3441:  5. find invalid patterns in look-behind.
        !          3442:  6. expand repeated string.
        !          3443:  */
        !          3444: static int
        !          3445: setup_tree(Node* node, regex_t* reg, int state, ScanEnv* env)
        !          3446: {
        !          3447:   int type;
        !          3448:   int r = 0;
        !          3449: 
        !          3450:   type = NTYPE(node);
        !          3451:   switch (type) {
        !          3452:   case N_LIST:
        !          3453:     {
        !          3454:       Node* prev = NULL_NODE;
        !          3455:       do {
        !          3456:        r = setup_tree(NCONS(node).left, reg, state, env);
        !          3457:        if (IS_NOT_NULL(prev) && r == 0) {
        !          3458:          r = next_setup(prev, NCONS(node).left, reg);
        !          3459:        }
        !          3460:        prev = NCONS(node).left;
        !          3461:       } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
        !          3462:     }
        !          3463:     break;
        !          3464: 
        !          3465:   case N_ALT:
        !          3466:     do {
        !          3467:       r = setup_tree(NCONS(node).left, reg, (state | IN_ALT), env);
        !          3468:     } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
        !          3469:     break;
        !          3470: 
        !          3471:   case N_CCLASS:
        !          3472:     break;
        !          3473: 
        !          3474:   case N_STRING:
        !          3475:     if (IS_IGNORECASE(reg->options) && !NSTRING_IS_RAW(node)) {
        !          3476:       r = divide_ambig_string_node(node, reg);
        !          3477:     }
        !          3478:     break;
        !          3479: 
        !          3480:   case N_CTYPE:
        !          3481:   case N_ANYCHAR:
        !          3482:     break;
        !          3483: 
        !          3484: #ifdef USE_SUBEXP_CALL
        !          3485:   case N_CALL:
        !          3486:     break;
        !          3487: #endif
        !          3488: 
        !          3489:   case N_BACKREF:
        !          3490:     {
        !          3491:       int i;
        !          3492:       int* p;
        !          3493:       Node** nodes = SCANENV_MEM_NODES(env);
        !          3494:       BackrefNode* br = &(NBACKREF(node));
        !          3495:       p = BACKREFS_P(br);
        !          3496:       for (i = 0; i < br->back_num; i++) {
        !          3497:        if (p[i] > env->num_mem)  return ONIGERR_INVALID_BACKREF;
        !          3498:        BIT_STATUS_ON_AT(env->backrefed_mem, p[i]);
        !          3499:        BIT_STATUS_ON_AT(env->bt_mem_start, p[i]);
        !          3500: #ifdef USE_BACKREF_AT_LEVEL
        !          3501:        if (IS_BACKREF_NEST_LEVEL(br)) {
        !          3502:          BIT_STATUS_ON_AT(env->bt_mem_end, p[i]);
        !          3503:        }
        !          3504: #endif
        !          3505:        SET_EFFECT_STATUS(nodes[p[i]], NST_MEM_BACKREFED);
        !          3506:       }
        !          3507:     }
        !          3508:     break;
        !          3509: 
        !          3510:   case N_QUANTIFIER:
        !          3511:     {
        !          3512:       OnigDistance d;
        !          3513:       QuantifierNode* qn = &(NQUANTIFIER(node));
        !          3514:       Node* target = qn->target;
        !          3515: 
        !          3516:       if ((state & IN_REPEAT) != 0) {
        !          3517:         qn->state |= NST_IN_REPEAT;
        !          3518:       }
        !          3519: 
        !          3520:       if (IS_REPEAT_INFINITE(qn->upper) || qn->upper >= 1) {
        !          3521:        r = get_min_match_length(target, &d, env);
        !          3522:        if (r) break;
        !          3523:        if (d == 0) {
        !          3524:          qn->target_empty_info = NQ_TARGET_IS_EMPTY;
        !          3525: #ifdef USE_INFINITE_REPEAT_MONOMANIAC_MEM_STATUS_CHECK
        !          3526:          r = quantifiers_memory_node_info(target);
        !          3527:          if (r < 0) break;
        !          3528:          if (r > 0) {
        !          3529:            qn->target_empty_info = r;
        !          3530:          }
        !          3531: #endif
        !          3532: #if 0
        !          3533:          r = get_max_match_length(target, &d, env);
        !          3534:          if (r == 0 && d == 0) {
        !          3535:            /*  ()* ==> ()?, ()+ ==> ()  */
        !          3536:            qn->upper = 1;
        !          3537:            if (qn->lower > 1) qn->lower = 1;
        !          3538:            if (NTYPE(target) == N_STRING) {
        !          3539:              qn->upper = qn->lower = 0;  /* /(?:)+/ ==> // */
        !          3540:            }
        !          3541:          }
        !          3542: #endif
        !          3543:        }
        !          3544:       }
        !          3545: 
        !          3546:       state |= IN_REPEAT;
        !          3547:       if (qn->lower != qn->upper)
        !          3548:        state |= IN_VAR_REPEAT;
        !          3549:       r = setup_tree(target, reg, state, env);
        !          3550:       if (r) break;
        !          3551: 
        !          3552:       /* expand string */
        !          3553: #define EXPAND_STRING_MAX_LENGTH  100
        !          3554:       if (NTYPE(target) == N_STRING) {
        !          3555:        if (!IS_REPEAT_INFINITE(qn->lower) && qn->lower == qn->upper &&
        !          3556:            qn->lower > 1 && qn->lower <= EXPAND_STRING_MAX_LENGTH) {
        !          3557:          int len = NSTRING_LEN(target);
        !          3558:          StrNode* sn = &(NSTRING(target));
        !          3559: 
        !          3560:          if (len * qn->lower <= EXPAND_STRING_MAX_LENGTH) {
        !          3561:            int i, n = qn->lower;
        !          3562:            onig_node_conv_to_str_node(node, NSTRING(target).flag);
        !          3563:            for (i = 0; i < n; i++) {
        !          3564:              r = onig_node_str_cat(node, sn->s, sn->end);
        !          3565:              if (r) break;
        !          3566:            }
        !          3567:            onig_node_free(target);
        !          3568:            break; /* break case N_QUANTIFIER: */
        !          3569:          }
        !          3570:        }
        !          3571:       }
        !          3572: 
        !          3573: #ifdef USE_OP_PUSH_OR_JUMP_EXACT
        !          3574:       if (qn->greedy && (qn->target_empty_info != 0)) {
        !          3575:        if (NTYPE(target) == N_QUANTIFIER) {
        !          3576:          QuantifierNode* tqn = &(NQUANTIFIER(target));
        !          3577:          if (IS_NOT_NULL(tqn->head_exact)) {
        !          3578:            qn->head_exact  = tqn->head_exact;
        !          3579:            tqn->head_exact = NULL;
        !          3580:          }
        !          3581:        }
        !          3582:        else {
        !          3583:          qn->head_exact = get_head_value_node(qn->target, 1, reg);
        !          3584:        }
        !          3585:       }
        !          3586: #endif
        !          3587:     }
        !          3588:     break;
        !          3589: 
        !          3590:   case N_EFFECT:
        !          3591:     {
        !          3592:       EffectNode* en = &(NEFFECT(node));
        !          3593: 
        !          3594:       switch (en->type) {
        !          3595:       case EFFECT_OPTION:
        !          3596:        {
        !          3597:          OnigOptionType options = reg->options;
        !          3598:          reg->options = NEFFECT(node).option;
        !          3599:          r = setup_tree(NEFFECT(node).target, reg, state, env);
        !          3600:          reg->options = options;
        !          3601:        }
        !          3602:        break;
        !          3603: 
        !          3604:       case EFFECT_MEMORY:
        !          3605:        if ((state & (IN_ALT | IN_NOT | IN_VAR_REPEAT)) != 0) {
        !          3606:          BIT_STATUS_ON_AT(env->bt_mem_start, en->regnum);
        !          3607:          /* SET_EFFECT_STATUS(node, NST_MEM_IN_ALT_NOT); */
        !          3608:        }
        !          3609:         r = setup_tree(en->target, reg, state, env);
        !          3610:         break;
        !          3611: 
        !          3612:       case EFFECT_STOP_BACKTRACK:
        !          3613:        {
        !          3614:          Node* target = en->target;
        !          3615:          r = setup_tree(target, reg, state, env);
        !          3616:          if (NTYPE(target) == N_QUANTIFIER) {
        !          3617:            QuantifierNode* tqn = &(NQUANTIFIER(target));
        !          3618:            if (IS_REPEAT_INFINITE(tqn->upper) && tqn->lower <= 1 &&
        !          3619:                tqn->greedy != 0) {  /* (?>a*), a*+ etc... */
        !          3620:              int qtype = NTYPE(tqn->target);
        !          3621:              if (IS_NODE_TYPE_SIMPLE(qtype))
        !          3622:                SET_EFFECT_STATUS(node, NST_STOP_BT_SIMPLE_REPEAT);
        !          3623:            }
        !          3624:          }
        !          3625:        }
        !          3626:        break;
        !          3627:       }
        !          3628:     }
        !          3629:     break;
        !          3630: 
        !          3631:   case N_ANCHOR:
        !          3632:     {
        !          3633:       AnchorNode* an = &(NANCHOR(node));
        !          3634: 
        !          3635:       switch (an->type) {
        !          3636:       case ANCHOR_PREC_READ:
        !          3637:        r = setup_tree(an->target, reg, state, env);
        !          3638:        break;
        !          3639:       case ANCHOR_PREC_READ_NOT:
        !          3640:        r = setup_tree(an->target, reg, (state | IN_NOT), env);
        !          3641:        break;
        !          3642: 
        !          3643: /* allowed node types in look-behind */
        !          3644: #define ALLOWED_TYPE_IN_LB  \
        !          3645:   ( N_LIST | N_ALT | N_STRING | N_CCLASS | N_CTYPE | \
        !          3646:     N_ANYCHAR | N_ANCHOR | N_EFFECT | N_QUANTIFIER | N_CALL )
        !          3647: 
        !          3648: #define ALLOWED_EFFECT_IN_LB       ( EFFECT_MEMORY )
        !          3649: #define ALLOWED_EFFECT_IN_LB_NOT   0
        !          3650: 
        !          3651: #define ALLOWED_ANCHOR_IN_LB \
        !          3652: ( ANCHOR_LOOK_BEHIND | ANCHOR_BEGIN_LINE | ANCHOR_END_LINE | ANCHOR_BEGIN_BUF | ANCHOR_BEGIN_POSITION )
        !          3653: #define ALLOWED_ANCHOR_IN_LB_NOT \
        !          3654: ( ANCHOR_LOOK_BEHIND | ANCHOR_LOOK_BEHIND_NOT | ANCHOR_BEGIN_LINE | ANCHOR_END_LINE | ANCHOR_BEGIN_BUF | ANCHOR_BEGIN_POSITION )
        !          3655: 
        !          3656:       case ANCHOR_LOOK_BEHIND:
        !          3657:        {
        !          3658:          r = check_type_tree(an->target, ALLOWED_TYPE_IN_LB,
        !          3659:                              ALLOWED_EFFECT_IN_LB, ALLOWED_ANCHOR_IN_LB);
        !          3660:          if (r < 0) return r;
        !          3661:          if (r > 0) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
        !          3662:          r = setup_look_behind(node, reg, env);
        !          3663:          if (r != 0) return r;
        !          3664:          r = setup_tree(an->target, reg, state, env);
        !          3665:        }
        !          3666:        break;
        !          3667: 
        !          3668:       case ANCHOR_LOOK_BEHIND_NOT:
        !          3669:        {
        !          3670:          r = check_type_tree(an->target, ALLOWED_TYPE_IN_LB,
        !          3671:                      ALLOWED_EFFECT_IN_LB_NOT, ALLOWED_ANCHOR_IN_LB_NOT);
        !          3672:          if (r < 0) return r;
        !          3673:          if (r > 0) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
        !          3674:          r = setup_look_behind(node, reg, env);
        !          3675:          if (r != 0) return r;
        !          3676:          r = setup_tree(an->target, reg, (state | IN_NOT), env);
        !          3677:        }
        !          3678:        break;
        !          3679:       }
        !          3680:     }
        !          3681:     break;
        !          3682: 
        !          3683:   default:
        !          3684:     break;
        !          3685:   }
        !          3686: 
        !          3687:   return r;
        !          3688: }
        !          3689: 
        !          3690: /* set skip map for Boyer-Moor search */
        !          3691: static int
        !          3692: set_bm_skip(UChar* s, UChar* end, OnigEncoding enc,
        !          3693:            UChar skip[], int** int_skip)
        !          3694: {
        !          3695:   int i, len;
        !          3696: 
        !          3697:   len = end - s;
        !          3698:   if (len < ONIG_CHAR_TABLE_SIZE) {
        !          3699:     for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) skip[i] = len;
        !          3700: 
        !          3701:     for (i = 0; i < len - 1; i++)
        !          3702:       skip[s[i]] = len - 1 - i;
        !          3703:   }
        !          3704:   else {
        !          3705:     if (IS_NULL(*int_skip)) {
        !          3706:       *int_skip = (int* )xmalloc(sizeof(int) * ONIG_CHAR_TABLE_SIZE);
        !          3707:       if (IS_NULL(*int_skip)) return ONIGERR_MEMORY;
        !          3708:     }
        !          3709:     for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) (*int_skip)[i] = len;
        !          3710: 
        !          3711:     for (i = 0; i < len - 1; i++)
        !          3712:       (*int_skip)[s[i]] = len - 1 - i;
        !          3713:   }
        !          3714:   return 0;
        !          3715: }
        !          3716: 
        !          3717: #define OPT_EXACT_MAXLEN   24
        !          3718: 
        !          3719: typedef struct {
        !          3720:   OnigDistance min;  /* min byte length */
        !          3721:   OnigDistance max;  /* max byte length */
        !          3722: } MinMaxLen;
        !          3723: 
        !          3724: typedef struct {
        !          3725:   MinMaxLen       mmd;
        !          3726:   OnigEncoding    enc;
        !          3727:   OnigOptionType  options;
        !          3728:   OnigAmbigType   ambig_flag;
        !          3729:   ScanEnv*        scan_env;
        !          3730: } OptEnv;
        !          3731: 
        !          3732: typedef struct {
        !          3733:   int left_anchor;
        !          3734:   int right_anchor;
        !          3735: } OptAncInfo;
        !          3736: 
        !          3737: typedef struct {
        !          3738:   MinMaxLen  mmd; /* info position */
        !          3739:   OptAncInfo anc;
        !          3740: 
        !          3741:   int   reach_end;
        !          3742:   int   ignore_case;
        !          3743:   int   len;
        !          3744:   UChar s[OPT_EXACT_MAXLEN];
        !          3745: } OptExactInfo;
        !          3746: 
        !          3747: typedef struct {
        !          3748:   MinMaxLen mmd; /* info position */
        !          3749:   OptAncInfo anc;
        !          3750: 
        !          3751:   int   value;      /* weighted value */
        !          3752:   UChar map[ONIG_CHAR_TABLE_SIZE];
        !          3753: } OptMapInfo;
        !          3754: 
        !          3755: typedef struct {
        !          3756:   MinMaxLen    len;
        !          3757: 
        !          3758:   OptAncInfo   anc;
        !          3759:   OptExactInfo exb;    /* boundary */
        !          3760:   OptExactInfo exm;    /* middle */
        !          3761:   OptExactInfo expr;   /* prec read (?=...) */
        !          3762: 
        !          3763:   OptMapInfo   map;   /* boundary */
        !          3764: } NodeOptInfo;
        !          3765: 
        !          3766: 
        !          3767: static int
        !          3768: map_position_value(OnigEncoding enc, int i)
        !          3769: {
        !          3770:   static const short int ByteValTable[] = {
        !          3771:      5,  1,  1,  1,  1,  1,  1,  1,  1, 10, 10,  1,  1, 10,  1,  1,
        !          3772:      1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        !          3773:     12,  4,  7,  4,  4,  4,  4,  4,  4,  5,  5,  5,  5,  5,  5,  5,
        !          3774:      6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  5,  5,  5,  5,  5,  5,
        !          3775:      5,  6,  6,  6,  6,  7,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
        !          3776:      6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  5,  6,  5,  5,  5,
        !          3777:      5,  6,  6,  6,  6,  7,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
        !          3778:      6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  5,  5,  5,  5,  1
        !          3779:   };
        !          3780: 
        !          3781:   if (i < sizeof(ByteValTable)/sizeof(ByteValTable[0])) {
        !          3782:     if (i == 0 && ONIGENC_MBC_MINLEN(enc) > 1)
        !          3783:       return 20;
        !          3784:     else
        !          3785:       return (int )ByteValTable[i];
        !          3786:   }
        !          3787:   else
        !          3788:     return 4;   /* Take it easy. */
        !          3789: }
        !          3790: 
        !          3791: static int
        !          3792: distance_value(MinMaxLen* mm)
        !          3793: {
        !          3794:   /* 1000 / (min-max-dist + 1) */
        !          3795:   static const short int dist_vals[] = {
        !          3796:     1000,  500,  333,  250,  200,  167,  143,  125,  111,  100, 
        !          3797:       91,   83,   77,   71,   67,   63,   59,   56,   53,   50, 
        !          3798:       48,   45,   43,   42,   40,   38,   37,   36,   34,   33, 
        !          3799:       32,   31,   30,   29,   29,   28,   27,   26,   26,   25, 
        !          3800:       24,   24,   23,   23,   22,   22,   21,   21,   20,   20, 
        !          3801:       20,   19,   19,   19,   18,   18,   18,   17,   17,   17, 
        !          3802:       16,   16,   16,   16,   15,   15,   15,   15,   14,   14, 
        !          3803:       14,   14,   14,   14,   13,   13,   13,   13,   13,   13, 
        !          3804:       12,   12,   12,   12,   12,   12,   11,   11,   11,   11, 
        !          3805:       11,   11,   11,   11,   11,   10,   10,   10,   10,   10
        !          3806:   };
        !          3807: 
        !          3808:   int d;
        !          3809: 
        !          3810:   if (mm->max == ONIG_INFINITE_DISTANCE) return 0;
        !          3811: 
        !          3812:   d = mm->max - mm->min;
        !          3813:   if (d < sizeof(dist_vals)/sizeof(dist_vals[0]))
        !          3814:     /* return dist_vals[d] * 16 / (mm->min + 12); */
        !          3815:     return (int )dist_vals[d];
        !          3816:   else
        !          3817:     return 1;
        !          3818: }
        !          3819: 
        !          3820: static int
        !          3821: comp_distance_value(MinMaxLen* d1, MinMaxLen* d2, int v1, int v2)
        !          3822: {
        !          3823:   if (v2 <= 0) return -1;
        !          3824:   if (v1 <= 0) return  1;
        !          3825: 
        !          3826:   v1 *= distance_value(d1);
        !          3827:   v2 *= distance_value(d2);
        !          3828: 
        !          3829:   if (v2 > v1) return  1;
        !          3830:   if (v2 < v1) return -1;
        !          3831: 
        !          3832:   if (d2->min < d1->min) return  1;
        !          3833:   if (d2->min > d1->min) return -1;
        !          3834:   return 0;
        !          3835: }
        !          3836: 
        !          3837: static int
        !          3838: is_equal_mml(MinMaxLen* a, MinMaxLen* b)
        !          3839: {
        !          3840:   return (a->min == b->min && a->max == b->max) ? 1 : 0;
        !          3841: }
        !          3842: 
        !          3843: 
        !          3844: static void
        !          3845: set_mml(MinMaxLen* mml, OnigDistance min, OnigDistance max)
        !          3846: {
        !          3847:   mml->min = min;
        !          3848:   mml->max = max;
        !          3849: }
        !          3850: 
        !          3851: static void
        !          3852: clear_mml(MinMaxLen* mml)
        !          3853: {
        !          3854:   mml->min = mml->max = 0;
        !          3855: }
        !          3856: 
        !          3857: static void
        !          3858: copy_mml(MinMaxLen* to, MinMaxLen* from)
        !          3859: {
        !          3860:   to->min = from->min;
        !          3861:   to->max = from->max;
        !          3862: }
        !          3863: 
        !          3864: static void
        !          3865: add_mml(MinMaxLen* to, MinMaxLen* from)
        !          3866: {
        !          3867:   to->min = distance_add(to->min, from->min);
        !          3868:   to->max = distance_add(to->max, from->max);
        !          3869: }
        !          3870: 
        !          3871: #if 0
        !          3872: static void
        !          3873: add_len_mml(MinMaxLen* to, OnigDistance len)
        !          3874: {
        !          3875:   to->min = distance_add(to->min, len);
        !          3876:   to->max = distance_add(to->max, len);
        !          3877: }
        !          3878: #endif
        !          3879: 
        !          3880: static void
        !          3881: alt_merge_mml(MinMaxLen* to, MinMaxLen* from)
        !          3882: {
        !          3883:   if (to->min > from->min) to->min = from->min;
        !          3884:   if (to->max < from->max) to->max = from->max;
        !          3885: }
        !          3886: 
        !          3887: static void
        !          3888: copy_opt_env(OptEnv* to, OptEnv* from)
        !          3889: {
        !          3890:   *to = *from;
        !          3891: }
        !          3892: 
        !          3893: static void
        !          3894: clear_opt_anc_info(OptAncInfo* anc)
        !          3895: {
        !          3896:   anc->left_anchor  = 0;
        !          3897:   anc->right_anchor = 0;
        !          3898: }
        !          3899: 
        !          3900: static void
        !          3901: copy_opt_anc_info(OptAncInfo* to, OptAncInfo* from)
        !          3902: {
        !          3903:   *to = *from;
        !          3904: }
        !          3905: 
        !          3906: static void
        !          3907: concat_opt_anc_info(OptAncInfo* to, OptAncInfo* left, OptAncInfo* right,
        !          3908:                    OnigDistance left_len, OnigDistance right_len)
        !          3909: {
        !          3910:   clear_opt_anc_info(to);
        !          3911: 
        !          3912:   to->left_anchor = left->left_anchor;
        !          3913:   if (left_len == 0) {
        !          3914:     to->left_anchor |= right->left_anchor;
        !          3915:   }
        !          3916: 
        !          3917:   to->right_anchor = right->right_anchor;
        !          3918:   if (right_len == 0) {
        !          3919:     to->right_anchor |= left->right_anchor;
        !          3920:   }
        !          3921: }
        !          3922: 
        !          3923: static int
        !          3924: is_left_anchor(int anc)
        !          3925: {
        !          3926:   if (anc == ANCHOR_END_BUF || anc == ANCHOR_SEMI_END_BUF ||
        !          3927:       anc == ANCHOR_END_LINE || anc == ANCHOR_PREC_READ ||
        !          3928:       anc == ANCHOR_PREC_READ_NOT)
        !          3929:     return 0;
        !          3930: 
        !          3931:   return 1;
        !          3932: }
        !          3933: 
        !          3934: static int
        !          3935: is_set_opt_anc_info(OptAncInfo* to, int anc)
        !          3936: {
        !          3937:   if ((to->left_anchor & anc) != 0) return 1;
        !          3938: 
        !          3939:   return ((to->right_anchor & anc) != 0 ? 1 : 0);
        !          3940: }
        !          3941: 
        !          3942: static void
        !          3943: add_opt_anc_info(OptAncInfo* to, int anc)
        !          3944: {
        !          3945:   if (is_left_anchor(anc))
        !          3946:     to->left_anchor |= anc;
        !          3947:   else
        !          3948:     to->right_anchor |= anc;
        !          3949: }
        !          3950: 
        !          3951: static void
        !          3952: remove_opt_anc_info(OptAncInfo* to, int anc)
        !          3953: {
        !          3954:   if (is_left_anchor(anc))
        !          3955:     to->left_anchor &= ~anc;
        !          3956:   else
        !          3957:     to->right_anchor &= ~anc;
        !          3958: }
        !          3959: 
        !          3960: static void
        !          3961: alt_merge_opt_anc_info(OptAncInfo* to, OptAncInfo* add)
        !          3962: {
        !          3963:   to->left_anchor  &= add->left_anchor;
        !          3964:   to->right_anchor &= add->right_anchor;
        !          3965: }
        !          3966: 
        !          3967: static int
        !          3968: is_full_opt_exact_info(OptExactInfo* ex)
        !          3969: {
        !          3970:   return (ex->len >= OPT_EXACT_MAXLEN ? 1 : 0);
        !          3971: }
        !          3972: 
        !          3973: static void
        !          3974: clear_opt_exact_info(OptExactInfo* ex)
        !          3975: {
        !          3976:   clear_mml(&ex->mmd);
        !          3977:   clear_opt_anc_info(&ex->anc);
        !          3978:   ex->reach_end   = 0;
        !          3979:   ex->ignore_case = 0;
        !          3980:   ex->len         = 0;
        !          3981:   ex->s[0]        = '\0';
        !          3982: }
        !          3983: 
        !          3984: static void
        !          3985: copy_opt_exact_info(OptExactInfo* to, OptExactInfo* from)
        !          3986: {
        !          3987:   *to = *from;
        !          3988: }
        !          3989: 
        !          3990: static void
        !          3991: concat_opt_exact_info(OptExactInfo* to, OptExactInfo* add, OnigEncoding enc)
        !          3992: {
        !          3993:   int i, j, len;
        !          3994:   UChar *p, *end;
        !          3995:   OptAncInfo tanc;
        !          3996: 
        !          3997:   if (! to->ignore_case && add->ignore_case) {
        !          3998:     if (to->len >= add->len) return ;  /* avoid */
        !          3999: 
        !          4000:     to->ignore_case = 1;
        !          4001:   }
        !          4002: 
        !          4003:   p = add->s;
        !          4004:   end = p + add->len;
        !          4005:   for (i = to->len; p < end; ) {
        !          4006:     len = enc_len(enc, p);
        !          4007:     if (i + len > OPT_EXACT_MAXLEN) break;
        !          4008:     for (j = 0; j < len && p < end; j++)
        !          4009:       to->s[i++] = *p++;
        !          4010:   }
        !          4011: 
        !          4012:   to->len = i;
        !          4013:   to->reach_end = (p == end ? add->reach_end : 0);
        !          4014: 
        !          4015:   concat_opt_anc_info(&tanc, &to->anc, &add->anc, 1, 1);
        !          4016:   if (! to->reach_end) tanc.right_anchor = 0;
        !          4017:   copy_opt_anc_info(&to->anc, &tanc);
        !          4018: }
        !          4019: 
        !          4020: static void
        !          4021: concat_opt_exact_info_str(OptExactInfo* to,
        !          4022:                          UChar* s, UChar* end, int raw, OnigEncoding enc)
        !          4023: {
        !          4024:   int i, j, len;
        !          4025:   UChar *p;
        !          4026: 
        !          4027:   for (i = to->len, p = s; p < end && i < OPT_EXACT_MAXLEN; ) {
        !          4028:     len = enc_len(enc, p);
        !          4029:     if (i + len > OPT_EXACT_MAXLEN) break;
        !          4030:     for (j = 0; j < len && p < end; j++)
        !          4031:       to->s[i++] = *p++;
        !          4032:   }
        !          4033: 
        !          4034:   to->len = i;
        !          4035: }
        !          4036: 
        !          4037: static void
        !          4038: alt_merge_opt_exact_info(OptExactInfo* to, OptExactInfo* add, OptEnv* env)
        !          4039: {
        !          4040:   int i, j, len;
        !          4041: 
        !          4042:   if (add->len == 0 || to->len == 0) {
        !          4043:     clear_opt_exact_info(to);
        !          4044:     return ;
        !          4045:   }
        !          4046: 
        !          4047:   if (! is_equal_mml(&to->mmd, &add->mmd)) {
        !          4048:     clear_opt_exact_info(to);
        !          4049:     return ;
        !          4050:   }
        !          4051: 
        !          4052:   for (i = 0; i < to->len && i < add->len; ) {
        !          4053:     if (to->s[i] != add->s[i]) break;
        !          4054:     len = enc_len(env->enc, to->s + i);
        !          4055: 
        !          4056:     for (j = 1; j < len; j++) {
        !          4057:       if (to->s[i+j] != add->s[i+j]) break;
        !          4058:     }
        !          4059:     if (j < len) break;
        !          4060:     i += len;
        !          4061:   }
        !          4062: 
        !          4063:   if (! add->reach_end || i < add->len || i < to->len) {
        !          4064:     to->reach_end = 0;
        !          4065:   }
        !          4066:   to->len = i;
        !          4067:   to->ignore_case |= add->ignore_case;
        !          4068: 
        !          4069:   alt_merge_opt_anc_info(&to->anc, &add->anc);
        !          4070:   if (! to->reach_end) to->anc.right_anchor = 0;
        !          4071: }
        !          4072: 
        !          4073: static void
        !          4074: select_opt_exact_info(OnigEncoding enc, OptExactInfo* now, OptExactInfo* alt)
        !          4075: {
        !          4076:   int v1, v2;
        !          4077: 
        !          4078:   v1 = now->len;
        !          4079:   v2 = alt->len;
        !          4080: 
        !          4081:   if (v2 == 0) {
        !          4082:     return ;
        !          4083:   }
        !          4084:   else if (v1 == 0) {
        !          4085:     copy_opt_exact_info(now, alt);
        !          4086:     return ;
        !          4087:   }
        !          4088:   else if (v1 <= 2 && v2 <= 2) {
        !          4089:     /* ByteValTable[x] is big value --> low price */
        !          4090:     v2 = map_position_value(enc, now->s[0]);
        !          4091:     v1 = map_position_value(enc, alt->s[0]);
        !          4092: 
        !          4093:     if (now->len > 1) v1 += 5;
        !          4094:     if (alt->len > 1) v2 += 5;
        !          4095:   }
        !          4096: 
        !          4097:   if (now->ignore_case == 0) v1 *= 2;
        !          4098:   if (alt->ignore_case == 0) v2 *= 2;
        !          4099: 
        !          4100:   if (comp_distance_value(&now->mmd, &alt->mmd, v1, v2) > 0)
        !          4101:     copy_opt_exact_info(now, alt);
        !          4102: }
        !          4103: 
        !          4104: static void
        !          4105: clear_opt_map_info(OptMapInfo* map)
        !          4106: {
        !          4107:   static const OptMapInfo clean_info = {
        !          4108:     {0, 0}, {0, 0}, 0,
        !          4109:     {
        !          4110:       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        !          4111:       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        !          4112:       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        !          4113:       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        !          4114:       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        !          4115:       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        !          4116:       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        !          4117:       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        !          4118:       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        !          4119:       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        !          4120:       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        !          4121:       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        !          4122:       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        !          4123:       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        !          4124:       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        !          4125:       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
        !          4126:     }
        !          4127:   };
        !          4128: 
        !          4129:   xmemcpy(map, &clean_info, sizeof(OptMapInfo));
        !          4130: }
        !          4131: 
        !          4132: static void
        !          4133: copy_opt_map_info(OptMapInfo* to, OptMapInfo* from)
        !          4134: {
        !          4135:   *to = *from;
        !          4136: }
        !          4137: 
        !          4138: static void
        !          4139: add_char_opt_map_info(OptMapInfo* map, UChar c, OnigEncoding enc)
        !          4140: {
        !          4141:   if (map->map[c] == 0) {
        !          4142:     map->map[c] = 1;
        !          4143:     map->value += map_position_value(enc, c);
        !          4144:   }
        !          4145: }
        !          4146: 
        !          4147: static int
        !          4148: add_char_amb_opt_map_info(OptMapInfo* map, UChar* p, UChar* end,
        !          4149:                           OnigEncoding enc, OnigAmbigType ambig_flag)
        !          4150: {
        !          4151:   int i, n, len;
        !          4152:   UChar buf[ONIGENC_MBC_NORMALIZE_MAXLEN];
        !          4153:   OnigCodePoint code;
        !          4154:   const OnigPairAmbigCodes* pccs;
        !          4155:   OnigAmbigType amb;
        !          4156: 
        !          4157:   add_char_opt_map_info(map, p[0], enc);
        !          4158:   code = ONIGENC_MBC_TO_CODE(enc, p, end);
        !          4159: 
        !          4160:   for (amb = 0x01; amb <= ONIGENC_AMBIGUOUS_MATCH_LIMIT; amb <<= 1) {
        !          4161:     if ((amb & ambig_flag) == 0)  continue;
        !          4162: 
        !          4163:     n = ONIGENC_GET_ALL_PAIR_AMBIG_CODES(enc, amb, &pccs);
        !          4164:     for (i = 0; i < n; i++) {
        !          4165:       if (pccs[i].from == code) {
        !          4166:         len = ONIGENC_CODE_TO_MBC(enc, pccs[i].to, buf);
        !          4167:         if (len < 0) return len;
        !          4168:         add_char_opt_map_info(map, buf[0], enc);
        !          4169:       }
        !          4170:     }
        !          4171:   }
        !          4172:   return 0;
        !          4173: }
        !          4174: 
        !          4175: static void
        !          4176: select_opt_map_info(OptMapInfo* now, OptMapInfo* alt)
        !          4177: {
        !          4178:   static int z = 1<<15; /* 32768: something big value */
        !          4179: 
        !          4180:   int v1, v2;
        !          4181: 
        !          4182:   if (alt->value == 0) return ;
        !          4183:   if (now->value == 0) {
        !          4184:     copy_opt_map_info(now, alt);
        !          4185:     return ;
        !          4186:   }
        !          4187: 
        !          4188:   v1 = z / now->value;
        !          4189:   v2 = z / alt->value;
        !          4190:   if (comp_distance_value(&now->mmd, &alt->mmd, v1, v2) > 0)
        !          4191:     copy_opt_map_info(now, alt);
        !          4192: }
        !          4193: 
        !          4194: static int
        !          4195: comp_opt_exact_or_map_info(OptExactInfo* e, OptMapInfo* m)
        !          4196: {
        !          4197: #define COMP_EM_BASE  20
        !          4198:   int ve, vm;
        !          4199: 
        !          4200:   if (m->value <= 0) return -1;
        !          4201: 
        !          4202:   ve = COMP_EM_BASE * e->len * (e->ignore_case ? 1 : 2);
        !          4203:   vm = COMP_EM_BASE * 5 * 2 / m->value;
        !          4204:   return comp_distance_value(&e->mmd, &m->mmd, ve, vm);
        !          4205: }
        !          4206: 
        !          4207: static void
        !          4208: alt_merge_opt_map_info(OnigEncoding enc, OptMapInfo* to, OptMapInfo* add)
        !          4209: {
        !          4210:   int i, val;
        !          4211: 
        !          4212:   /* if (! is_equal_mml(&to->mmd, &add->mmd)) return ; */
        !          4213:   if (to->value == 0) return ;
        !          4214:   if (add->value == 0 || to->mmd.max < add->mmd.min) {
        !          4215:     clear_opt_map_info(to);
        !          4216:     return ;
        !          4217:   }
        !          4218: 
        !          4219:   alt_merge_mml(&to->mmd, &add->mmd);
        !          4220: 
        !          4221:   val = 0;
        !          4222:   for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) {
        !          4223:     if (add->map[i])
        !          4224:       to->map[i] = 1;
        !          4225: 
        !          4226:     if (to->map[i])
        !          4227:       val += map_position_value(enc, i);
        !          4228:   }
        !          4229:   to->value = val;
        !          4230: 
        !          4231:   alt_merge_opt_anc_info(&to->anc, &add->anc);
        !          4232: }
        !          4233: 
        !          4234: static void
        !          4235: set_bound_node_opt_info(NodeOptInfo* opt, MinMaxLen* mmd)
        !          4236: {
        !          4237:   copy_mml(&(opt->exb.mmd),  mmd);
        !          4238:   copy_mml(&(opt->expr.mmd), mmd);
        !          4239:   copy_mml(&(opt->map.mmd),  mmd);
        !          4240: }
        !          4241: 
        !          4242: static void
        !          4243: clear_node_opt_info(NodeOptInfo* opt)
        !          4244: {
        !          4245:   clear_mml(&opt->len);
        !          4246:   clear_opt_anc_info(&opt->anc);
        !          4247:   clear_opt_exact_info(&opt->exb);
        !          4248:   clear_opt_exact_info(&opt->exm);
        !          4249:   clear_opt_exact_info(&opt->expr);
        !          4250:   clear_opt_map_info(&opt->map);
        !          4251: }
        !          4252: 
        !          4253: static void
        !          4254: copy_node_opt_info(NodeOptInfo* to, NodeOptInfo* from)
        !          4255: {
        !          4256:   *to = *from;
        !          4257: }
        !          4258: 
        !          4259: static void
        !          4260: concat_left_node_opt_info(OnigEncoding enc, NodeOptInfo* to, NodeOptInfo* add)
        !          4261: {
        !          4262:   int exb_reach, exm_reach;
        !          4263:   OptAncInfo tanc;
        !          4264: 
        !          4265:   concat_opt_anc_info(&tanc, &to->anc, &add->anc, to->len.max, add->len.max);
        !          4266:   copy_opt_anc_info(&to->anc, &tanc);
        !          4267: 
        !          4268:   if (add->exb.len > 0 && to->len.max == 0) {
        !          4269:     concat_opt_anc_info(&tanc, &to->anc, &add->exb.anc,
        !          4270:                        to->len.max, add->len.max);
        !          4271:     copy_opt_anc_info(&add->exb.anc, &tanc);
        !          4272:   }
        !          4273: 
        !          4274:   if (add->map.value > 0 && to->len.max == 0) {
        !          4275:     if (add->map.mmd.max == 0)
        !          4276:       add->map.anc.left_anchor |= to->anc.left_anchor;
        !          4277:   }
        !          4278: 
        !          4279:   exb_reach = to->exb.reach_end;
        !          4280:   exm_reach = to->exm.reach_end;
        !          4281: 
        !          4282:   if (add->len.max != 0)
        !          4283:     to->exb.reach_end = to->exm.reach_end = 0;
        !          4284: 
        !          4285:   if (add->exb.len > 0) {
        !          4286:     if (exb_reach) {
        !          4287:       concat_opt_exact_info(&to->exb, &add->exb, enc);
        !          4288:       clear_opt_exact_info(&add->exb);
        !          4289:     }
        !          4290:     else if (exm_reach) {
        !          4291:       concat_opt_exact_info(&to->exm, &add->exb, enc);
        !          4292:       clear_opt_exact_info(&add->exb);
        !          4293:     }
        !          4294:   }
        !          4295:   select_opt_exact_info(enc, &to->exm, &add->exb);
        !          4296:   select_opt_exact_info(enc, &to->exm, &add->exm);
        !          4297: 
        !          4298:   if (to->expr.len > 0) {
        !          4299:     if (add->len.max > 0) {
        !          4300:       if (to->expr.len > (int )add->len.max)
        !          4301:        to->expr.len = add->len.max;
        !          4302: 
        !          4303:       if (to->expr.mmd.max == 0)
        !          4304:        select_opt_exact_info(enc, &to->exb, &to->expr);
        !          4305:       else
        !          4306:        select_opt_exact_info(enc, &to->exm, &to->expr);
        !          4307:     }
        !          4308:   }
        !          4309:   else if (add->expr.len > 0) {
        !          4310:     copy_opt_exact_info(&to->expr, &add->expr);
        !          4311:   }
        !          4312: 
        !          4313:   select_opt_map_info(&to->map, &add->map);
        !          4314: 
        !          4315:   add_mml(&to->len, &add->len);
        !          4316: }
        !          4317: 
        !          4318: static void
        !          4319: alt_merge_node_opt_info(NodeOptInfo* to, NodeOptInfo* add, OptEnv* env)
        !          4320: {
        !          4321:   alt_merge_opt_anc_info  (&to->anc,  &add->anc);
        !          4322:   alt_merge_opt_exact_info(&to->exb,  &add->exb, env);
        !          4323:   alt_merge_opt_exact_info(&to->exm,  &add->exm, env);
        !          4324:   alt_merge_opt_exact_info(&to->expr, &add->expr, env);
        !          4325:   alt_merge_opt_map_info(env->enc, &to->map,  &add->map);
        !          4326: 
        !          4327:   alt_merge_mml(&to->len, &add->len);
        !          4328: }
        !          4329: 
        !          4330: 
        !          4331: #define MAX_NODE_OPT_INFO_REF_COUNT    5
        !          4332: 
        !          4333: static int
        !          4334: optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env)
        !          4335: {
        !          4336:   int type;
        !          4337:   int r = 0;
        !          4338: 
        !          4339:   clear_node_opt_info(opt);
        !          4340:   set_bound_node_opt_info(opt, &env->mmd);
        !          4341: 
        !          4342:   type = NTYPE(node);
        !          4343:   switch (type) {
        !          4344:   case N_LIST:
        !          4345:     {
        !          4346:       OptEnv nenv;
        !          4347:       NodeOptInfo nopt;
        !          4348:       Node* nd = node;
        !          4349: 
        !          4350:       copy_opt_env(&nenv, env);
        !          4351:       do {
        !          4352:        r = optimize_node_left(NCONS(nd).left, &nopt, &nenv);
        !          4353:        if (r == 0) {
        !          4354:          add_mml(&nenv.mmd, &nopt.len);
        !          4355:          concat_left_node_opt_info(env->enc, opt, &nopt);
        !          4356:        }
        !          4357:       } while (r == 0 && IS_NOT_NULL(nd = NCONS(nd).right));
        !          4358:     }
        !          4359:     break;
        !          4360: 
        !          4361:   case N_ALT:
        !          4362:     {
        !          4363:       NodeOptInfo nopt;
        !          4364:       Node* nd = node;
        !          4365: 
        !          4366:       do {
        !          4367:        r = optimize_node_left(NCONS(nd).left, &nopt, env);
        !          4368:        if (r == 0) {
        !          4369:          if (nd == node) copy_node_opt_info(opt, &nopt);
        !          4370:          else            alt_merge_node_opt_info(opt, &nopt, env);
        !          4371:        }
        !          4372:       } while ((r == 0) && IS_NOT_NULL(nd = NCONS(nd).right));
        !          4373:     }
        !          4374:     break;
        !          4375: 
        !          4376:   case N_STRING:
        !          4377:     {
        !          4378:       StrNode* sn = &(NSTRING(node));
        !          4379:       int slen = sn->end - sn->s;
        !          4380:       int is_raw = NSTRING_IS_RAW(node);
        !          4381: 
        !          4382:       if (! NSTRING_IS_AMBIG(node)) {
        !          4383:        concat_opt_exact_info_str(&opt->exb, sn->s, sn->end,
        !          4384:                                  NSTRING_IS_RAW(node), env->enc);
        !          4385:        if (slen > 0) {
        !          4386:          add_char_opt_map_info(&opt->map, *(sn->s), env->enc);
        !          4387:        }
        !          4388:         set_mml(&opt->len, slen, slen);
        !          4389:       }
        !          4390:       else {
        !          4391:         int n, max;
        !          4392: 
        !          4393:         concat_opt_exact_info_str(&opt->exb, sn->s, sn->end,
        !          4394:                                   is_raw, env->enc);
        !          4395:         opt->exb.ignore_case = 1;
        !          4396: 
        !          4397:        if (slen > 0) {
        !          4398:           r = add_char_amb_opt_map_info(&opt->map, sn->s, sn->end,
        !          4399:                                         env->enc, env->ambig_flag);
        !          4400:           if (r != 0) break;
        !          4401:        }
        !          4402: 
        !          4403:         if (NSTRING_IS_AMBIG_REDUCE(node)) {
        !          4404:           n = onigenc_strlen(env->enc, sn->s, sn->end);
        !          4405:           max = ONIGENC_MBC_MAXLEN_DIST(env->enc) * n;
        !          4406:         }
        !          4407:         else {
        !          4408:           max = slen;
        !          4409:         }
        !          4410:         set_mml(&opt->len, slen, max);
        !          4411:       }
        !          4412: 
        !          4413:       if (opt->exb.len == slen)
        !          4414:        opt->exb.reach_end = 1;
        !          4415:     }
        !          4416:     break;
        !          4417: 
        !          4418:   case N_CCLASS:
        !          4419:     {
        !          4420:       int i, z;
        !          4421:       CClassNode* cc = &(NCCLASS(node));
        !          4422: 
        !          4423:       /* no need to check ignore case. (setted in setup_tree()) */
        !          4424: 
        !          4425:       if (IS_NOT_NULL(cc->mbuf) || IS_CCLASS_NOT(cc)) {
        !          4426:         OnigDistance min = ONIGENC_MBC_MINLEN(env->enc);
        !          4427:        OnigDistance max = ONIGENC_MBC_MAXLEN_DIST(env->enc);
        !          4428: 
        !          4429:        set_mml(&opt->len, min, max);
        !          4430:       }
        !          4431:       else {
        !          4432:         for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
        !          4433:           z = BITSET_AT(cc->bs, i);
        !          4434:           if ((z && !IS_CCLASS_NOT(cc)) || (!z && IS_CCLASS_NOT(cc))) {
        !          4435:             add_char_opt_map_info(&opt->map, (UChar )i, env->enc);
        !          4436:           }
        !          4437:         }
        !          4438:        set_mml(&opt->len, 1, 1);
        !          4439:       }
        !          4440:     }
        !          4441:     break;
        !          4442: 
        !          4443:   case N_CTYPE:
        !          4444:     {
        !          4445:       int i, min, max;
        !          4446: 
        !          4447:       max = ONIGENC_MBC_MAXLEN_DIST(env->enc);
        !          4448: 
        !          4449:       if (max == 1) {
        !          4450:         min = 1;
        !          4451: 
        !          4452:        switch (NCTYPE(node).type) {
        !          4453:        case CTYPE_NOT_WORD:
        !          4454:           for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
        !          4455:             if (! ONIGENC_IS_CODE_WORD(env->enc, i)) {
        !          4456:               add_char_opt_map_info(&opt->map, (UChar )i, env->enc);
        !          4457:             }
        !          4458:           }
        !          4459:           break;
        !          4460: 
        !          4461:        case CTYPE_WORD:
        !          4462:           for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
        !          4463:             if (ONIGENC_IS_CODE_WORD(env->enc, i)) {
        !          4464:               add_char_opt_map_info(&opt->map, (UChar )i, env->enc);
        !          4465:             }
        !          4466:           }
        !          4467:          break;
        !          4468:        }
        !          4469:       }
        !          4470:       else {
        !          4471:         min = ONIGENC_MBC_MINLEN(env->enc);
        !          4472:       }
        !          4473:       set_mml(&opt->len, min, max);
        !          4474:     }
        !          4475:     break;
        !          4476: 
        !          4477:   case N_ANYCHAR:
        !          4478:     {
        !          4479:       OnigDistance min = ONIGENC_MBC_MINLEN(env->enc);
        !          4480:       OnigDistance max = ONIGENC_MBC_MAXLEN_DIST(env->enc);
        !          4481:       set_mml(&opt->len, min, max);
        !          4482:     }
        !          4483:     break;
        !          4484: 
        !          4485:   case N_ANCHOR:
        !          4486:     switch (NANCHOR(node).type) {
        !          4487:     case ANCHOR_BEGIN_BUF:
        !          4488:     case ANCHOR_BEGIN_POSITION:
        !          4489:     case ANCHOR_BEGIN_LINE:
        !          4490:     case ANCHOR_END_BUF:
        !          4491:     case ANCHOR_SEMI_END_BUF:
        !          4492:     case ANCHOR_END_LINE:
        !          4493:       add_opt_anc_info(&opt->anc, NANCHOR(node).type);
        !          4494:       break;
        !          4495: 
        !          4496:     case ANCHOR_PREC_READ:
        !          4497:       {
        !          4498:        NodeOptInfo nopt;
        !          4499: 
        !          4500:        r = optimize_node_left(NANCHOR(node).target, &nopt, env);
        !          4501:        if (r == 0) {
        !          4502:          if (nopt.exb.len > 0)
        !          4503:            copy_opt_exact_info(&opt->expr, &nopt.exb);
        !          4504:          else if (nopt.exm.len > 0)
        !          4505:            copy_opt_exact_info(&opt->expr, &nopt.exm);
        !          4506: 
        !          4507:          opt->expr.reach_end = 0;
        !          4508: 
        !          4509:          if (nopt.map.value > 0)
        !          4510:            copy_opt_map_info(&opt->map, &nopt.map);
        !          4511:        }
        !          4512:       }
        !          4513:       break;
        !          4514: 
        !          4515:     case ANCHOR_PREC_READ_NOT:
        !          4516:     case ANCHOR_LOOK_BEHIND: /* Sorry, I can't make use of it. */
        !          4517:     case ANCHOR_LOOK_BEHIND_NOT:
        !          4518:       break;
        !          4519:     }
        !          4520:     break;
        !          4521: 
        !          4522:   case N_BACKREF:
        !          4523:     {
        !          4524:       int i;
        !          4525:       int* backs;
        !          4526:       OnigDistance min, max, tmin, tmax;
        !          4527:       Node** nodes = SCANENV_MEM_NODES(env->scan_env);
        !          4528:       BackrefNode* br = &(NBACKREF(node));
        !          4529: 
        !          4530:       if (br->state & NST_RECURSION) {
        !          4531:        set_mml(&opt->len, 0, ONIG_INFINITE_DISTANCE);
        !          4532:        break;
        !          4533:       }
        !          4534:       backs = BACKREFS_P(br);
        !          4535:       r = get_min_match_length(nodes[backs[0]], &min, env->scan_env);
        !          4536:       if (r != 0) break;
        !          4537:       r = get_max_match_length(nodes[backs[0]], &max, env->scan_env);
        !          4538:       if (r != 0) break;
        !          4539:       for (i = 1; i < br->back_num; i++) {
        !          4540:        r = get_min_match_length(nodes[backs[i]], &tmin, env->scan_env);
        !          4541:        if (r != 0) break;
        !          4542:        r = get_max_match_length(nodes[backs[i]], &tmax, env->scan_env);
        !          4543:        if (r != 0) break;
        !          4544:        if (min > tmin) min = tmin;
        !          4545:        if (max < tmax) max = tmax;
        !          4546:       }
        !          4547:       if (r == 0) set_mml(&opt->len, min, max);
        !          4548:     }
        !          4549:     break;
        !          4550: 
        !          4551: #ifdef USE_SUBEXP_CALL
        !          4552:   case N_CALL:
        !          4553:     if (IS_CALL_RECURSION(&(NCALL(node))))
        !          4554:       set_mml(&opt->len, 0, ONIG_INFINITE_DISTANCE);
        !          4555:     else {
        !          4556:       OnigOptionType save = env->options;
        !          4557:       env->options = NEFFECT(NCALL(node).target).option;
        !          4558:       r = optimize_node_left(NCALL(node).target, opt, env);
        !          4559:       env->options = save;
        !          4560:     }
        !          4561:     break;
        !          4562: #endif
        !          4563: 
        !          4564:   case N_QUANTIFIER:
        !          4565:     {
        !          4566:       int i;
        !          4567:       OnigDistance min, max;
        !          4568:       NodeOptInfo nopt;
        !          4569:       QuantifierNode* qn = &(NQUANTIFIER(node));
        !          4570: 
        !          4571:       r = optimize_node_left(qn->target, &nopt, env);
        !          4572:       if (r) break;
        !          4573: 
        !          4574:       if (qn->lower == 0 && IS_REPEAT_INFINITE(qn->upper)) {
        !          4575:        if (env->mmd.max == 0 &&
        !          4576:            NTYPE(qn->target) == N_ANYCHAR && qn->greedy) {
        !          4577:          if (IS_MULTILINE(env->options))
        !          4578:            add_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR_ML);
        !          4579:          else
        !          4580:            add_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR);
        !          4581:        }
        !          4582:       }
        !          4583:       else {
        !          4584:        if (qn->lower > 0) {
        !          4585:          copy_node_opt_info(opt, &nopt);
        !          4586:          if (nopt.exb.len > 0) {
        !          4587:            if (nopt.exb.reach_end) {
        !          4588:              for (i = 2; i < qn->lower &&
        !          4589:                          ! is_full_opt_exact_info(&opt->exb); i++) {
        !          4590:                concat_opt_exact_info(&opt->exb, &nopt.exb, env->enc);
        !          4591:              }
        !          4592:              if (i < qn->lower) {
        !          4593:                opt->exb.reach_end = 0;
        !          4594:              }
        !          4595:            }
        !          4596:          }
        !          4597: 
        !          4598:          if (qn->lower != qn->upper) {
        !          4599:            opt->exb.reach_end = 0;
        !          4600:            opt->exm.reach_end = 0;
        !          4601:          }
        !          4602:          if (qn->lower > 1)
        !          4603:            opt->exm.reach_end = 0;
        !          4604:        }
        !          4605:       }
        !          4606: 
        !          4607:       min = distance_multiply(nopt.len.min, qn->lower);
        !          4608:       if (IS_REPEAT_INFINITE(qn->upper))
        !          4609:        max = (nopt.len.max > 0 ? ONIG_INFINITE_DISTANCE : 0);
        !          4610:       else
        !          4611:        max = distance_multiply(nopt.len.max, qn->upper);
        !          4612: 
        !          4613:       set_mml(&opt->len, min, max);
        !          4614:     }
        !          4615:     break;
        !          4616: 
        !          4617:   case N_EFFECT:
        !          4618:     {
        !          4619:       EffectNode* en = &(NEFFECT(node));
        !          4620: 
        !          4621:       switch (en->type) {
        !          4622:       case EFFECT_OPTION:
        !          4623:        {
        !          4624:          OnigOptionType save = env->options;
        !          4625: 
        !          4626:          env->options = en->option;
        !          4627:          r = optimize_node_left(en->target, opt, env);
        !          4628:          env->options = save;
        !          4629:        }
        !          4630:        break;
        !          4631: 
        !          4632:       case EFFECT_MEMORY:
        !          4633: #ifdef USE_SUBEXP_CALL
        !          4634:        en->opt_count++;
        !          4635:        if (en->opt_count > MAX_NODE_OPT_INFO_REF_COUNT) {
        !          4636:          OnigDistance min, max;
        !          4637: 
        !          4638:          min = 0;
        !          4639:          max = ONIG_INFINITE_DISTANCE;
        !          4640:          if (IS_EFFECT_MIN_FIXED(en)) min = en->min_len;
        !          4641:          if (IS_EFFECT_MAX_FIXED(en)) max = en->max_len;
        !          4642:          set_mml(&opt->len, min, max);
        !          4643:        }
        !          4644:        else
        !          4645: #endif
        !          4646:        {
        !          4647:          r = optimize_node_left(en->target, opt, env);
        !          4648: 
        !          4649:          if (is_set_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR_MASK)) {
        !          4650:            if (BIT_STATUS_AT(env->scan_env->backrefed_mem, en->regnum))
        !          4651:              remove_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR_MASK);
        !          4652:          }
        !          4653:        }
        !          4654:        break;
        !          4655: 
        !          4656:       case EFFECT_STOP_BACKTRACK:
        !          4657:        r = optimize_node_left(en->target, opt, env);
        !          4658:        break;
        !          4659:       }
        !          4660:     }
        !          4661:     break;
        !          4662: 
        !          4663:   default:
        !          4664: #ifdef ONIG_DEBUG
        !          4665:     fprintf(stderr, "optimize_node_left: undefined node type %d\n",
        !          4666:            NTYPE(node));
        !          4667: #endif
        !          4668:     r = ONIGERR_TYPE_BUG;
        !          4669:     break;
        !          4670:   }
        !          4671: 
        !          4672:   return r;
        !          4673: }
        !          4674: 
        !          4675: static int
        !          4676: set_optimize_exact_info(regex_t* reg, OptExactInfo* e)
        !          4677: {
        !          4678:   int r;
        !          4679: 
        !          4680:   if (e->len == 0) return 0;
        !          4681: 
        !          4682:   if (e->ignore_case) {
        !          4683:     reg->exact = (UChar* )xmalloc(e->len);
        !          4684:     CHECK_NULL_RETURN_VAL(reg->exact, ONIGERR_MEMORY);
        !          4685:     xmemcpy(reg->exact, e->s, e->len);
        !          4686:     reg->exact_end = reg->exact + e->len;
        !          4687:     reg->optimize = ONIG_OPTIMIZE_EXACT_IC;
        !          4688:   }
        !          4689:   else {
        !          4690:     int allow_reverse;
        !          4691: 
        !          4692:     reg->exact = k_strdup(e->s, e->s + e->len);
        !          4693:     CHECK_NULL_RETURN_VAL(reg->exact, ONIGERR_MEMORY);
        !          4694:     reg->exact_end = reg->exact + e->len;
        !          4695:  
        !          4696:     allow_reverse =
        !          4697:        ONIGENC_IS_ALLOWED_REVERSE_MATCH(reg->enc, reg->exact, reg->exact_end);
        !          4698: 
        !          4699:     if (e->len >= 3 || (e->len >= 2 && allow_reverse)) {
        !          4700:       r = set_bm_skip(reg->exact, reg->exact_end, reg->enc,
        !          4701:                      reg->map, &(reg->int_map));
        !          4702:       if (r) return r;
        !          4703: 
        !          4704:       reg->optimize = (allow_reverse != 0
        !          4705:                       ? ONIG_OPTIMIZE_EXACT_BM : ONIG_OPTIMIZE_EXACT_BM_NOT_REV);
        !          4706:     }
        !          4707:     else {
        !          4708:       reg->optimize = ONIG_OPTIMIZE_EXACT;
        !          4709:     }
        !          4710:   }
        !          4711: 
        !          4712:   reg->dmin = e->mmd.min;
        !          4713:   reg->dmax = e->mmd.max;
        !          4714: 
        !          4715:   if (reg->dmin != ONIG_INFINITE_DISTANCE) {
        !          4716:     reg->threshold_len = reg->dmin + (reg->exact_end - reg->exact);
        !          4717:   }
        !          4718: 
        !          4719:   return 0;
        !          4720: }
        !          4721: 
        !          4722: static void
        !          4723: set_optimize_map_info(regex_t* reg, OptMapInfo* m)
        !          4724: {
        !          4725:   int i;
        !          4726: 
        !          4727:   for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++)
        !          4728:     reg->map[i] = m->map[i];
        !          4729: 
        !          4730:   reg->optimize   = ONIG_OPTIMIZE_MAP;
        !          4731:   reg->dmin       = m->mmd.min;
        !          4732:   reg->dmax       = m->mmd.max;
        !          4733: 
        !          4734:   if (reg->dmin != ONIG_INFINITE_DISTANCE) {
        !          4735:     reg->threshold_len = reg->dmin + 1;
        !          4736:   }
        !          4737: }
        !          4738: 
        !          4739: static void
        !          4740: set_sub_anchor(regex_t* reg, OptAncInfo* anc)
        !          4741: {
        !          4742:   reg->sub_anchor |= anc->left_anchor  & ANCHOR_BEGIN_LINE;
        !          4743:   reg->sub_anchor |= anc->right_anchor & ANCHOR_END_LINE;
        !          4744: }
        !          4745: 
        !          4746: #ifdef ONIG_DEBUG
        !          4747: static void print_optimize_info(FILE* f, regex_t* reg);
        !          4748: #endif
        !          4749: 
        !          4750: static int
        !          4751: set_optimize_info_from_tree(Node* node, regex_t* reg, ScanEnv* scan_env)
        !          4752: {
        !          4753: 
        !          4754:   int r;
        !          4755:   NodeOptInfo opt;
        !          4756:   OptEnv env;
        !          4757: 
        !          4758:   env.enc        = reg->enc;
        !          4759:   env.options    = reg->options;
        !          4760:   env.ambig_flag = reg->ambig_flag;
        !          4761:   env.scan_env   = scan_env;
        !          4762:   clear_mml(&env.mmd);
        !          4763: 
        !          4764:   r = optimize_node_left(node, &opt, &env);
        !          4765:   if (r) return r;
        !          4766: 
        !          4767:   reg->anchor = opt.anc.left_anchor & (ANCHOR_BEGIN_BUF |
        !          4768:         ANCHOR_BEGIN_POSITION | ANCHOR_ANYCHAR_STAR | ANCHOR_ANYCHAR_STAR_ML);
        !          4769: 
        !          4770:   reg->anchor |= opt.anc.right_anchor & (ANCHOR_END_BUF | ANCHOR_SEMI_END_BUF);
        !          4771: 
        !          4772:   if (reg->anchor & (ANCHOR_END_BUF | ANCHOR_SEMI_END_BUF)) {
        !          4773:     reg->anchor_dmin = opt.len.min;
        !          4774:     reg->anchor_dmax = opt.len.max;
        !          4775:   }
        !          4776: 
        !          4777:   if (opt.exb.len > 0 || opt.exm.len > 0) {
        !          4778:     select_opt_exact_info(reg->enc, &opt.exb, &opt.exm);
        !          4779:     if (opt.map.value > 0 &&
        !          4780:        comp_opt_exact_or_map_info(&opt.exb, &opt.map) > 0) {
        !          4781:       goto set_map;
        !          4782:     }
        !          4783:     else {
        !          4784:       r = set_optimize_exact_info(reg, &opt.exb);
        !          4785:       set_sub_anchor(reg, &opt.exb.anc);
        !          4786:     }
        !          4787:   }
        !          4788:   else if (opt.map.value > 0) {
        !          4789:   set_map:
        !          4790:     set_optimize_map_info(reg, &opt.map);
        !          4791:     set_sub_anchor(reg, &opt.map.anc);
        !          4792:   }
        !          4793:   else {
        !          4794:     reg->sub_anchor |= opt.anc.left_anchor & ANCHOR_BEGIN_LINE;
        !          4795:     if (opt.len.max == 0)
        !          4796:       reg->sub_anchor |= opt.anc.right_anchor & ANCHOR_END_LINE;
        !          4797:   }
        !          4798: 
        !          4799: #if defined(ONIG_DEBUG_COMPILE) || defined(ONIG_DEBUG_MATCH)
        !          4800:   print_optimize_info(stderr, reg);
        !          4801: #endif
        !          4802:   return r;
        !          4803: }
        !          4804: 
        !          4805: static void
        !          4806: clear_optimize_info(regex_t* reg)
        !          4807: {
        !          4808:   reg->optimize      = ONIG_OPTIMIZE_NONE;
        !          4809:   reg->anchor        = 0;
        !          4810:   reg->anchor_dmin   = 0;
        !          4811:   reg->anchor_dmax   = 0;
        !          4812:   reg->sub_anchor    = 0;
        !          4813:   reg->exact_end     = (UChar* )NULL;
        !          4814:   reg->threshold_len = 0;
        !          4815:   if (IS_NOT_NULL(reg->exact)) {
        !          4816:     xfree(reg->exact);
        !          4817:     reg->exact = (UChar* )NULL;
        !          4818:   }
        !          4819: }
        !          4820: 
        !          4821: #ifdef ONIG_DEBUG
        !          4822: 
        !          4823: static void print_enc_string(FILE* fp, OnigEncoding enc,
        !          4824:                             const UChar *s, const UChar *end)
        !          4825: {
        !          4826:   fprintf(fp, "\nPATTERN: /");
        !          4827: 
        !          4828:   if (ONIGENC_MBC_MINLEN(enc) > 1) {
        !          4829:     const UChar *p;
        !          4830:     OnigCodePoint code;
        !          4831: 
        !          4832:     p = s;
        !          4833:     while (p < end) {
        !          4834:       code = ONIGENC_MBC_TO_CODE(enc, p, end);
        !          4835:       if (code >= 0x80) {
        !          4836:        fprintf(fp, " 0x%04x ", (int )code);
        !          4837:       }
        !          4838:       else {
        !          4839:        fputc((int )code, fp);
        !          4840:       }
        !          4841: 
        !          4842:       p += enc_len(enc, p);
        !          4843:     }
        !          4844:   }
        !          4845:   else {
        !          4846:     while (s < end) {
        !          4847:       fputc((int )*s, fp);
        !          4848:       s++;
        !          4849:     }
        !          4850:   }
        !          4851: 
        !          4852:   fprintf(fp, "/\n");
        !          4853: }
        !          4854: 
        !          4855: static void
        !          4856: print_distance_range(FILE* f, OnigDistance a, OnigDistance b)
        !          4857: {
        !          4858:   if (a == ONIG_INFINITE_DISTANCE)
        !          4859:     fputs("inf", f);
        !          4860:   else
        !          4861:     fprintf(f, "(%u)", a);
        !          4862: 
        !          4863:   fputs("-", f);
        !          4864: 
        !          4865:   if (b == ONIG_INFINITE_DISTANCE)
        !          4866:     fputs("inf", f);
        !          4867:   else
        !          4868:     fprintf(f, "(%u)", b);
        !          4869: }
        !          4870: 
        !          4871: static void
        !          4872: print_anchor(FILE* f, int anchor)
        !          4873: {
        !          4874:   int q = 0;
        !          4875: 
        !          4876:   fprintf(f, "[");
        !          4877: 
        !          4878:   if (anchor & ANCHOR_BEGIN_BUF) {
        !          4879:     fprintf(f, "begin-buf");
        !          4880:     q = 1;
        !          4881:   }
        !          4882:   if (anchor & ANCHOR_BEGIN_LINE) {
        !          4883:     if (q) fprintf(f, ", ");
        !          4884:     q = 1;
        !          4885:     fprintf(f, "begin-line");
        !          4886:   }
        !          4887:   if (anchor & ANCHOR_BEGIN_POSITION) {
        !          4888:     if (q) fprintf(f, ", ");
        !          4889:     q = 1;
        !          4890:     fprintf(f, "begin-pos");
        !          4891:   }
        !          4892:   if (anchor & ANCHOR_END_BUF) {
        !          4893:     if (q) fprintf(f, ", ");
        !          4894:     q = 1;
        !          4895:     fprintf(f, "end-buf");
        !          4896:   }
        !          4897:   if (anchor & ANCHOR_SEMI_END_BUF) {
        !          4898:     if (q) fprintf(f, ", ");
        !          4899:     q = 1;
        !          4900:     fprintf(f, "semi-end-buf");
        !          4901:   }
        !          4902:   if (anchor & ANCHOR_END_LINE) {
        !          4903:     if (q) fprintf(f, ", ");
        !          4904:     q = 1;
        !          4905:     fprintf(f, "end-line");
        !          4906:   }
        !          4907:   if (anchor & ANCHOR_ANYCHAR_STAR) {
        !          4908:     if (q) fprintf(f, ", ");
        !          4909:     q = 1;
        !          4910:     fprintf(f, "anychar-star");
        !          4911:   }
        !          4912:   if (anchor & ANCHOR_ANYCHAR_STAR_ML) {
        !          4913:     if (q) fprintf(f, ", ");
        !          4914:     fprintf(f, "anychar-star-pl");
        !          4915:   }
        !          4916: 
        !          4917:   fprintf(f, "]");
        !          4918: }
        !          4919: 
        !          4920: static void
        !          4921: print_optimize_info(FILE* f, regex_t* reg)
        !          4922: {
        !          4923:   static const char* on[] = { "NONE", "EXACT", "EXACT_BM", "EXACT_BM_NOT_REV",
        !          4924:                               "EXACT_IC", "MAP" };
        !          4925: 
        !          4926:   fprintf(f, "optimize: %s\n", on[reg->optimize]);
        !          4927:   fprintf(f, "  anchor: "); print_anchor(f, reg->anchor);
        !          4928:   if ((reg->anchor & ANCHOR_END_BUF_MASK) != 0)
        !          4929:     print_distance_range(f, reg->anchor_dmin, reg->anchor_dmax);
        !          4930:   fprintf(f, "\n");
        !          4931: 
        !          4932:   if (reg->optimize) {
        !          4933:     fprintf(f, "  sub anchor: "); print_anchor(f, reg->sub_anchor);
        !          4934:     fprintf(f, "\n");
        !          4935:   }
        !          4936:   fprintf(f, "\n");
        !          4937: 
        !          4938:   if (reg->exact) {
        !          4939:     UChar *p;
        !          4940:     fprintf(f, "exact: [");
        !          4941:     for (p = reg->exact; p < reg->exact_end; p++) {
        !          4942:       fputc(*p, f);
        !          4943:     }
        !          4944:     fprintf(f, "]: length: %d\n", (reg->exact_end - reg->exact));
        !          4945:   }
        !          4946:   else if (reg->optimize & ONIG_OPTIMIZE_MAP) {
        !          4947:     int c, i, n = 0;
        !          4948: 
        !          4949:     for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++)
        !          4950:       if (reg->map[i]) n++;
        !          4951: 
        !          4952:     fprintf(f, "map: n=%d\n", n);
        !          4953:     if (n > 0) {
        !          4954:       c = 0;
        !          4955:       fputc('[', f);
        !          4956:       for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) {
        !          4957:        if (reg->map[i] != 0) {
        !          4958:           if (c > 0)  fputs(", ", f);
        !          4959:           c++;
        !          4960:           if (ONIGENC_MBC_MAXLEN(reg->enc) == 1 &&
        !          4961:               ONIGENC_IS_CODE_PRINT(reg->enc, (OnigCodePoint )i))
        !          4962:             fputc(i, f);
        !          4963:           else
        !          4964:             fprintf(f, "%d", i);
        !          4965:         }
        !          4966:       }
        !          4967:       fprintf(f, "]\n");
        !          4968:     }
        !          4969:   }
        !          4970: }
        !          4971: #endif /* ONIG_DEBUG */
        !          4972: 
        !          4973: 
        !          4974: static void
        !          4975: onig_free_body(regex_t* reg)
        !          4976: {
        !          4977:   if (IS_NOT_NULL(reg->p))                xfree(reg->p);
        !          4978:   if (IS_NOT_NULL(reg->exact))            xfree(reg->exact);
        !          4979:   if (IS_NOT_NULL(reg->int_map))          xfree(reg->int_map);
        !          4980:   if (IS_NOT_NULL(reg->int_map_backward)) xfree(reg->int_map_backward);
        !          4981:   if (IS_NOT_NULL(reg->repeat_range))     xfree(reg->repeat_range);
        !          4982:   if (IS_NOT_NULL(reg->chain))            onig_free(reg->chain);
        !          4983: 
        !          4984: #ifdef USE_NAMED_GROUP
        !          4985:   onig_names_free(reg);
        !          4986: #endif
        !          4987: }
        !          4988: 
        !          4989: extern void
        !          4990: onig_free(regex_t* reg)
        !          4991: {
        !          4992:   if (IS_NOT_NULL(reg)) {
        !          4993:     onig_free_body(reg);
        !          4994:     xfree(reg);
        !          4995:   }
        !          4996: }
        !          4997: 
        !          4998: #define REGEX_TRANSFER(to,from) do {\
        !          4999:   (to)->state = ONIG_STATE_MODIFY;\
        !          5000:   onig_free_body(to);\
        !          5001:   xmemcpy(to, from, sizeof(regex_t));\
        !          5002:   xfree(from);\
        !          5003: } while (0)
        !          5004: 
        !          5005: extern void
        !          5006: onig_transfer(regex_t* to, regex_t* from)
        !          5007: {
        !          5008:   THREAD_ATOMIC_START;
        !          5009:   REGEX_TRANSFER(to, from);
        !          5010:   THREAD_ATOMIC_END;
        !          5011: }
        !          5012: 
        !          5013: #define REGEX_CHAIN_HEAD(reg) do {\
        !          5014:   while (IS_NOT_NULL((reg)->chain)) {\
        !          5015:     (reg) = (reg)->chain;\
        !          5016:   }\
        !          5017: } while (0)
        !          5018: 
        !          5019: extern void
        !          5020: onig_chain_link_add(regex_t* to, regex_t* add)
        !          5021: {
        !          5022:   THREAD_ATOMIC_START;
        !          5023:   REGEX_CHAIN_HEAD(to);
        !          5024:   to->chain = add;
        !          5025:   THREAD_ATOMIC_END;
        !          5026: }
        !          5027: 
        !          5028: extern void
        !          5029: onig_chain_reduce(regex_t* reg)
        !          5030: {
        !          5031:   regex_t *head, *prev;
        !          5032: 
        !          5033:   prev = reg;
        !          5034:   head = prev->chain;
        !          5035:   if (IS_NOT_NULL(head)) {
        !          5036:     reg->state = ONIG_STATE_MODIFY;
        !          5037:     while (IS_NOT_NULL(head->chain)) {
        !          5038:       prev = head;
        !          5039:       head = head->chain;
        !          5040:     }
        !          5041:     prev->chain = (regex_t* )NULL;
        !          5042:     REGEX_TRANSFER(reg, head);
        !          5043:   }
        !          5044: }
        !          5045: 
        !          5046: #if 0
        !          5047: extern int
        !          5048: onig_clone(regex_t** to, regex_t* from)
        !          5049: {
        !          5050:   int r, size;
        !          5051:   regex_t* reg;
        !          5052: 
        !          5053: #ifdef USE_MULTI_THREAD_SYSTEM
        !          5054:   if (ONIG_STATE(from) >= ONIG_STATE_NORMAL) {
        !          5055:     ONIG_STATE_INC(from);
        !          5056:     if (IS_NOT_NULL(from->chain) && ONIG_STATE(reg) == ONIG_STATE_NORMAL) {
        !          5057:       onig_chain_reduce(from);
        !          5058:       ONIG_STATE_INC(from);
        !          5059:     }
        !          5060:   }
        !          5061:   else {
        !          5062:     int n = 0;
        !          5063:     while (ONIG_STATE(from) < ONIG_STATE_NORMAL) {
        !          5064:       if (++n > THREAD_PASS_LIMIT_COUNT)
        !          5065:        return ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT;
        !          5066:       THREAD_PASS;
        !          5067:     }
        !          5068:     ONIG_STATE_INC(from);
        !          5069:   }
        !          5070: #endif /* USE_MULTI_THREAD_SYSTEM */
        !          5071: 
        !          5072:   r = onig_alloc_init(&reg, ONIG_OPTION_NONE, ONIGENC_AMBIGUOUS_MATCH_DEFAULT,
        !          5073:                       from->enc, ONIG_SYNTAX_DEFAULT);
        !          5074:   if (r != 0) {
        !          5075:     ONIG_STATE_DEC(from);
        !          5076:     return r;
        !          5077:   }
        !          5078: 
        !          5079:   xmemcpy(reg, from, sizeof(onig_t));
        !          5080:   reg->chain = (regex_t* )NULL;
        !          5081:   reg->state = ONIG_STATE_NORMAL;
        !          5082: 
        !          5083:   if (from->p) {
        !          5084:     reg->p = (UChar* )xmalloc(reg->alloc);
        !          5085:     if (IS_NULL(reg->p)) goto mem_error;
        !          5086:     xmemcpy(reg->p, from->p, reg->alloc);
        !          5087:   }
        !          5088: 
        !          5089:   if (from->exact) {
        !          5090:     reg->exact = (UChar* )xmalloc(from->exact_end - from->exact);
        !          5091:     if (IS_NULL(reg->exact)) goto mem_error;
        !          5092:     reg->exact_end = reg->exact + (from->exact_end - from->exact);
        !          5093:     xmemcpy(reg->exact, from->exact, reg->exact_end - reg->exact);
        !          5094:   }
        !          5095: 
        !          5096:   if (from->int_map) {
        !          5097:     size = sizeof(int) * ONIG_CHAR_TABLE_SIZE;
        !          5098:     reg->int_map = (int* )xmalloc(size);
        !          5099:     if (IS_NULL(reg->int_map)) goto mem_error;
        !          5100:     xmemcpy(reg->int_map, from->int_map, size);
        !          5101:   }
        !          5102: 
        !          5103:   if (from->int_map_backward) {
        !          5104:     size = sizeof(int) * ONIG_CHAR_TABLE_SIZE;
        !          5105:     reg->int_map_backward = (int* )xmalloc(size);
        !          5106:     if (IS_NULL(reg->int_map_backward)) goto mem_error;
        !          5107:     xmemcpy(reg->int_map_backward, from->int_map_backward, size);
        !          5108:   }
        !          5109: 
        !          5110: #ifdef USE_NAMED_GROUP
        !          5111:   reg->name_table = names_clone(from); /* names_clone is not implemented */
        !          5112: #endif
        !          5113: 
        !          5114:   ONIG_STATE_DEC(from);
        !          5115:   *to = reg;
        !          5116:   return 0;
        !          5117: 
        !          5118:  mem_error:
        !          5119:   ONIG_STATE_DEC(from);
        !          5120:   return ONIGERR_MEMORY;
        !          5121: }
        !          5122: #endif
        !          5123: 
        !          5124: #ifdef ONIG_DEBUG
        !          5125: static void print_compiled_byte_code_list P_((FILE* f, regex_t* reg));
        !          5126: #endif
        !          5127: #ifdef ONIG_DEBUG_PARSE_TREE
        !          5128: static void print_tree P_((FILE* f, Node* node));
        !          5129: #endif
        !          5130: 
        !          5131: extern int
        !          5132: onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end,
        !          5133:              OnigErrorInfo* einfo)
        !          5134: {
        !          5135: #define COMPILE_INIT_SIZE  20
        !          5136: 
        !          5137:   int r, init_size;
        !          5138:   Node*  root;
        !          5139:   ScanEnv  scan_env;
        !          5140: #ifdef USE_SUBEXP_CALL
        !          5141:   UnsetAddrList  uslist;
        !          5142: #endif
        !          5143: 
        !          5144:   reg->state = ONIG_STATE_COMPILING;
        !          5145: 
        !          5146: #ifdef ONIG_DEBUG
        !          5147:   print_enc_string(stderr, reg->enc, pattern, pattern_end);
        !          5148: #endif
        !          5149: 
        !          5150:   if (reg->alloc == 0) {
        !          5151:     init_size = (pattern_end - pattern) * 2;
        !          5152:     if (init_size <= 0) init_size = COMPILE_INIT_SIZE;
        !          5153:     r = BBUF_INIT(reg, init_size);
        !          5154:     if (r != 0) goto end;
        !          5155:   }
        !          5156:   else
        !          5157:     reg->used = 0;
        !          5158: 
        !          5159:   reg->num_mem            = 0;
        !          5160:   reg->num_repeat         = 0;
        !          5161:   reg->num_null_check     = 0;
        !          5162:   reg->repeat_range_alloc = 0;
        !          5163:   reg->repeat_range       = (OnigRepeatRange* )NULL;
        !          5164: #ifdef USE_COMBINATION_EXPLOSION_CHECK
        !          5165:   reg->num_comb_exp_check = 0;
        !          5166: #endif
        !          5167: 
        !          5168:   r = onig_parse_make_tree(&root, pattern, pattern_end, reg, &scan_env);
        !          5169:   if (r != 0) goto err;
        !          5170: 
        !          5171: #ifdef USE_NAMED_GROUP
        !          5172:   /* mixed use named group and no-named group */
        !          5173:   if (scan_env.num_named > 0 &&
        !          5174:       IS_SYNTAX_BV(scan_env.syntax, ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP) &&
        !          5175:       !ONIG_IS_OPTION_ON(reg->options, ONIG_OPTION_CAPTURE_GROUP)) {
        !          5176:     if (scan_env.num_named != scan_env.num_mem)
        !          5177:       r = disable_noname_group_capture(&root, reg, &scan_env);
        !          5178:     else
        !          5179:       r = numbered_ref_check(root);
        !          5180: 
        !          5181:     if (r != 0) goto err;
        !          5182:   }
        !          5183: #endif
        !          5184: 
        !          5185: #ifdef ONIG_DEBUG_PARSE_TREE
        !          5186:   print_tree(stderr, root);
        !          5187: #endif
        !          5188: 
        !          5189: #ifdef USE_SUBEXP_CALL
        !          5190:   if (scan_env.num_call > 0) {
        !          5191:     r = unset_addr_list_init(&uslist, scan_env.num_call);
        !          5192:     if (r != 0) goto err;
        !          5193:     scan_env.unset_addr_list = &uslist;
        !          5194:     r = setup_subexp_call(root, &scan_env);
        !          5195:     if (r != 0) goto err_unset;
        !          5196:     r = subexp_recursive_check_trav(root, &scan_env);
        !          5197:     if (r  < 0) goto err_unset;
        !          5198:     r = subexp_inf_recursive_check_trav(root, &scan_env);
        !          5199:     if (r != 0) goto err_unset;
        !          5200: 
        !          5201:     reg->num_call = scan_env.num_call;
        !          5202:   }
        !          5203:   else
        !          5204:     reg->num_call = 0;
        !          5205: #endif
        !          5206: 
        !          5207:   r = setup_tree(root, reg, 0, &scan_env);
        !          5208:   if (r != 0) goto err_unset;
        !          5209: 
        !          5210:   reg->capture_history  = scan_env.capture_history;
        !          5211:   reg->bt_mem_start     = scan_env.bt_mem_start;
        !          5212:   reg->bt_mem_start    |= reg->capture_history;
        !          5213:   if (IS_FIND_CONDITION(reg->options))
        !          5214:     BIT_STATUS_ON_ALL(reg->bt_mem_end);
        !          5215:   else {
        !          5216:     reg->bt_mem_end  = scan_env.bt_mem_end;
        !          5217:     reg->bt_mem_end |= reg->capture_history;
        !          5218:   }
        !          5219: 
        !          5220: #ifdef USE_COMBINATION_EXPLOSION_CHECK
        !          5221:   if (scan_env.backrefed_mem == 0
        !          5222: #ifdef USE_SUBEXP_CALL
        !          5223:       || scan_env.num_call == 0
        !          5224: #endif
        !          5225:       ) {
        !          5226:     setup_comb_exp_check(root, 0, &scan_env);
        !          5227: #ifdef USE_SUBEXP_CALL
        !          5228:     if (scan_env.has_recursion != 0) {
        !          5229:       scan_env.num_comb_exp_check = 0;
        !          5230:     }
        !          5231:     else
        !          5232: #endif
        !          5233:     if (scan_env.comb_exp_max_regnum > 0) {
        !          5234:       int i;
        !          5235:       for (i = 1; i <= scan_env.comb_exp_max_regnum; i++) {
        !          5236:        if (BIT_STATUS_AT(scan_env.backrefed_mem, i) != 0) {
        !          5237:          scan_env.num_comb_exp_check = 0;
        !          5238:          break;
        !          5239:        }
        !          5240:       }
        !          5241:     }
        !          5242:   }
        !          5243: 
        !          5244:   reg->num_comb_exp_check = scan_env.num_comb_exp_check;
        !          5245: #endif
        !          5246: 
        !          5247:   clear_optimize_info(reg);
        !          5248: #ifndef ONIG_DONT_OPTIMIZE
        !          5249:   r = set_optimize_info_from_tree(root, reg, &scan_env);
        !          5250:   if (r != 0) goto err_unset;
        !          5251: #endif
        !          5252: 
        !          5253:   if (IS_NOT_NULL(scan_env.mem_nodes_dynamic)) {
        !          5254:     xfree(scan_env.mem_nodes_dynamic);
        !          5255:     scan_env.mem_nodes_dynamic = (Node** )NULL;
        !          5256:   }
        !          5257: 
        !          5258:   r = compile_tree(root, reg);
        !          5259:   if (r == 0) {
        !          5260:     r = add_opcode(reg, OP_END);
        !          5261: #ifdef USE_SUBEXP_CALL
        !          5262:     if (scan_env.num_call > 0) {
        !          5263:       r = unset_addr_list_fix(&uslist, reg);
        !          5264:       unset_addr_list_end(&uslist);
        !          5265:       if (r) goto err;
        !          5266:     }
        !          5267: #endif
        !          5268: 
        !          5269:     if ((reg->num_repeat != 0) || (reg->bt_mem_end != 0))
        !          5270:       reg->stack_pop_level = STACK_POP_LEVEL_ALL;
        !          5271:     else {
        !          5272:       if (reg->bt_mem_start != 0)
        !          5273:        reg->stack_pop_level = STACK_POP_LEVEL_MEM_START;
        !          5274:       else
        !          5275:        reg->stack_pop_level = STACK_POP_LEVEL_FREE;
        !          5276:     }
        !          5277:   }
        !          5278: #ifdef USE_SUBEXP_CALL
        !          5279:   else if (scan_env.num_call > 0) {
        !          5280:     unset_addr_list_end(&uslist);
        !          5281:   }
        !          5282: #endif
        !          5283:   onig_node_free(root);
        !          5284: 
        !          5285: #ifdef ONIG_DEBUG_COMPILE
        !          5286: #ifdef USE_NAMED_GROUP
        !          5287:   onig_print_names(stderr, reg);
        !          5288: #endif
        !          5289:   print_compiled_byte_code_list(stderr, reg);
        !          5290: #endif
        !          5291: 
        !          5292:  end:
        !          5293:   reg->state = ONIG_STATE_NORMAL;
        !          5294:   return r;
        !          5295: 
        !          5296:  err_unset:
        !          5297: #ifdef USE_SUBEXP_CALL
        !          5298:   if (scan_env.num_call > 0) {
        !          5299:     unset_addr_list_end(&uslist);
        !          5300:   }
        !          5301: #endif
        !          5302:  err:
        !          5303:   if (IS_NOT_NULL(scan_env.error)) {
        !          5304:     if (IS_NOT_NULL(einfo)) {
        !          5305:       einfo->enc     = scan_env.enc;
        !          5306:       einfo->par     = scan_env.error;
        !          5307:       einfo->par_end = scan_env.error_end;
        !          5308:     }
        !          5309:   }
        !          5310: 
        !          5311:   if (IS_NOT_NULL(root)) onig_node_free(root);
        !          5312:   if (IS_NOT_NULL(scan_env.mem_nodes_dynamic))
        !          5313:       xfree(scan_env.mem_nodes_dynamic);
        !          5314:   return r;
        !          5315: }
        !          5316: 
        !          5317: #ifdef USE_RECOMPILE_API
        !          5318: extern int
        !          5319: onig_recompile(regex_t* reg, const UChar* pattern, const UChar* pattern_end,
        !          5320:            OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax,
        !          5321:            OnigErrorInfo* einfo)
        !          5322: {
        !          5323:   int r;
        !          5324:   regex_t *new_reg;
        !          5325: 
        !          5326:   r = onig_new(&new_reg, pattern, pattern_end, option, enc, syntax, einfo);
        !          5327:   if (r) return r;
        !          5328:   if (ONIG_STATE(reg) == ONIG_STATE_NORMAL) {
        !          5329:     onig_transfer(reg, new_reg);
        !          5330:   }
        !          5331:   else {
        !          5332:     onig_chain_link_add(reg, new_reg);
        !          5333:   }
        !          5334:   return 0;
        !          5335: }
        !          5336: #endif
        !          5337: 
        !          5338: static int onig_inited = 0;
        !          5339: 
        !          5340: extern int
        !          5341: onig_alloc_init(regex_t** reg, OnigOptionType option, OnigAmbigType ambig_flag,
        !          5342:                 OnigEncoding enc, OnigSyntaxType* syntax)
        !          5343: {
        !          5344:   if (! onig_inited)
        !          5345:     onig_init();
        !          5346: 
        !          5347:   if (ONIGENC_IS_UNDEF(enc))
        !          5348:     return ONIGERR_DEFAULT_ENCODING_IS_NOT_SETTED;
        !          5349: 
        !          5350:   if ((option & (ONIG_OPTION_DONT_CAPTURE_GROUP|ONIG_OPTION_CAPTURE_GROUP))
        !          5351:       == (ONIG_OPTION_DONT_CAPTURE_GROUP|ONIG_OPTION_CAPTURE_GROUP)) {
        !          5352:     return ONIGERR_INVALID_COMBINATION_OF_OPTIONS;
        !          5353:   }
        !          5354: 
        !          5355:   *reg = (regex_t* )xmalloc(sizeof(regex_t));
        !          5356:   if (IS_NULL(*reg)) return ONIGERR_MEMORY;
        !          5357:   (*reg)->state = ONIG_STATE_MODIFY;
        !          5358: 
        !          5359:   if ((option & ONIG_OPTION_NEGATE_SINGLELINE) != 0) {
        !          5360:     option |= syntax->options;
        !          5361:     option &= ~ONIG_OPTION_SINGLELINE;
        !          5362:   }
        !          5363:   else
        !          5364:     option |= syntax->options;
        !          5365: 
        !          5366:   (*reg)->enc              = enc;
        !          5367:   (*reg)->options          = option;
        !          5368:   (*reg)->syntax           = syntax;
        !          5369:   (*reg)->optimize         = 0;
        !          5370:   (*reg)->exact            = (UChar* )NULL;
        !          5371:   (*reg)->int_map          = (int* )NULL;
        !          5372:   (*reg)->int_map_backward = (int* )NULL;
        !          5373:   (*reg)->chain            = (regex_t* )NULL;
        !          5374: 
        !          5375:   (*reg)->p                = (UChar* )NULL;
        !          5376:   (*reg)->alloc            = 0;
        !          5377:   (*reg)->used             = 0;
        !          5378:   (*reg)->name_table       = (void* )NULL;
        !          5379: 
        !          5380:   (*reg)->ambig_flag       = ambig_flag;
        !          5381:   (*reg)->ambig_flag      &= ONIGENC_SUPPORT_AMBIG_FLAG(enc);
        !          5382: 
        !          5383:   return 0;
        !          5384: }
        !          5385: 
        !          5386: extern int
        !          5387: onig_new(regex_t** reg, const UChar* pattern, const UChar* pattern_end,
        !          5388:          OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax,
        !          5389:          OnigErrorInfo* einfo)
        !          5390: {
        !          5391:   int r;
        !          5392: 
        !          5393:   if (IS_NOT_NULL(einfo)) einfo->par = (UChar* )NULL;
        !          5394: 
        !          5395:   r = onig_alloc_init(reg, option, ONIGENC_AMBIGUOUS_MATCH_DEFAULT,
        !          5396:                       enc, syntax);
        !          5397:   if (r) return r;
        !          5398: 
        !          5399:   r = onig_compile(*reg, pattern, pattern_end, einfo);
        !          5400:   if (r) {
        !          5401:     onig_free(*reg);
        !          5402:     *reg = NULL;
        !          5403:   }
        !          5404:   return r;
        !          5405: }
        !          5406: 
        !          5407: extern int
        !          5408: onig_init(void)
        !          5409: {
        !          5410:   if (onig_inited != 0)
        !          5411:     return 0;
        !          5412: 
        !          5413:   onig_inited = 1;
        !          5414: 
        !          5415:   THREAD_SYSTEM_INIT;
        !          5416:   THREAD_ATOMIC_START;
        !          5417: 
        !          5418:   onigenc_init();
        !          5419:   onigenc_set_default_caseconv_table((UChar* )0);
        !          5420: 
        !          5421: #ifdef ONIG_DEBUG_STATISTICS
        !          5422:   onig_statistics_init();
        !          5423: #endif
        !          5424: 
        !          5425:   THREAD_ATOMIC_END;
        !          5426:   return 0;
        !          5427: }
        !          5428: 
        !          5429: 
        !          5430: extern int
        !          5431: onig_end(void)
        !          5432: {
        !          5433:   extern int onig_free_shared_cclass_table(void);
        !          5434: 
        !          5435:   THREAD_ATOMIC_START;
        !          5436: 
        !          5437: #ifdef ONIG_DEBUG_STATISTICS
        !          5438:   onig_print_statistics(stderr);
        !          5439: #endif
        !          5440: 
        !          5441: #ifdef USE_SHARED_CCLASS_TABLE
        !          5442:   onig_free_shared_cclass_table();
        !          5443: #endif
        !          5444: 
        !          5445: #ifdef USE_RECYCLE_NODE
        !          5446:   onig_free_node_list();
        !          5447: #endif
        !          5448: 
        !          5449:   onig_inited = 0;
        !          5450: 
        !          5451:   THREAD_ATOMIC_END;
        !          5452:   THREAD_SYSTEM_END;
        !          5453:   return 0;
        !          5454: }
        !          5455: 
        !          5456: 
        !          5457: #ifdef ONIG_DEBUG
        !          5458: 
        !          5459: /* arguments type */
        !          5460: #define ARG_SPECIAL     -1
        !          5461: #define ARG_NON          0
        !          5462: #define ARG_RELADDR      1
        !          5463: #define ARG_ABSADDR      2
        !          5464: #define ARG_LENGTH       3
        !          5465: #define ARG_MEMNUM       4
        !          5466: #define ARG_OPTION       5
        !          5467: #define ARG_STATE_CHECK  6
        !          5468: 
        !          5469: OnigOpInfoType OnigOpInfo[] = {
        !          5470:   { OP_FINISH,            "finish",          ARG_NON },
        !          5471:   { OP_END,               "end",             ARG_NON },
        !          5472:   { OP_EXACT1,            "exact1",          ARG_SPECIAL },
        !          5473:   { OP_EXACT2,            "exact2",          ARG_SPECIAL },
        !          5474:   { OP_EXACT3,            "exact3",          ARG_SPECIAL },
        !          5475:   { OP_EXACT4,            "exact4",          ARG_SPECIAL },
        !          5476:   { OP_EXACT5,            "exact5",          ARG_SPECIAL },
        !          5477:   { OP_EXACTN,            "exactn",          ARG_SPECIAL },
        !          5478:   { OP_EXACTMB2N1,        "exactmb2-n1",     ARG_SPECIAL },
        !          5479:   { OP_EXACTMB2N2,        "exactmb2-n2",     ARG_SPECIAL },
        !          5480:   { OP_EXACTMB2N3,        "exactmb2-n3",     ARG_SPECIAL },
        !          5481:   { OP_EXACTMB2N,         "exactmb2-n",      ARG_SPECIAL },
        !          5482:   { OP_EXACTMB3N,         "exactmb3n"  ,     ARG_SPECIAL },
        !          5483:   { OP_EXACTMBN,          "exactmbn",        ARG_SPECIAL },
        !          5484:   { OP_EXACT1_IC,         "exact1-ic",       ARG_SPECIAL },
        !          5485:   { OP_EXACTN_IC,         "exactn-ic",       ARG_SPECIAL },
        !          5486:   { OP_CCLASS,            "cclass",          ARG_SPECIAL },
        !          5487:   { OP_CCLASS_MB,         "cclass-mb",       ARG_SPECIAL },
        !          5488:   { OP_CCLASS_MIX,        "cclass-mix",      ARG_SPECIAL },
        !          5489:   { OP_CCLASS_NOT,        "cclass-not",      ARG_SPECIAL },
        !          5490:   { OP_CCLASS_MB_NOT,     "cclass-mb-not",   ARG_SPECIAL },
        !          5491:   { OP_CCLASS_MIX_NOT,    "cclass-mix-not",  ARG_SPECIAL },
        !          5492:   { OP_CCLASS_NODE,       "cclass-node",     ARG_SPECIAL },
        !          5493:   { OP_ANYCHAR,           "anychar",         ARG_NON },
        !          5494:   { OP_ANYCHAR_ML,        "anychar-ml",      ARG_NON },
        !          5495:   { OP_ANYCHAR_STAR,      "anychar*",        ARG_NON },
        !          5496:   { OP_ANYCHAR_ML_STAR,   "anychar-ml*",     ARG_NON },
        !          5497:   { OP_ANYCHAR_STAR_PEEK_NEXT, "anychar*-peek-next", ARG_SPECIAL },
        !          5498:   { OP_ANYCHAR_ML_STAR_PEEK_NEXT, "anychar-ml*-peek-next", ARG_SPECIAL },
        !          5499:   { OP_WORD,                "word",            ARG_NON },
        !          5500:   { OP_NOT_WORD,            "not-word",        ARG_NON },
        !          5501:   { OP_WORD_BOUND,          "word-bound",      ARG_NON },
        !          5502:   { OP_NOT_WORD_BOUND,      "not-word-bound",  ARG_NON },
        !          5503:   { OP_WORD_BEGIN,          "word-begin",      ARG_NON },
        !          5504:   { OP_WORD_END,            "word-end",        ARG_NON },
        !          5505:   { OP_BEGIN_BUF,           "begin-buf",       ARG_NON },
        !          5506:   { OP_END_BUF,             "end-buf",         ARG_NON },
        !          5507:   { OP_BEGIN_LINE,          "begin-line",      ARG_NON },
        !          5508:   { OP_END_LINE,            "end-line",        ARG_NON },
        !          5509:   { OP_SEMI_END_BUF,        "semi-end-buf",    ARG_NON },
        !          5510:   { OP_BEGIN_POSITION,      "begin-position",  ARG_NON },
        !          5511:   { OP_BACKREF1,            "backref1",             ARG_NON },
        !          5512:   { OP_BACKREF2,            "backref2",             ARG_NON },
        !          5513:   { OP_BACKREFN,            "backrefn",             ARG_MEMNUM  },
        !          5514:   { OP_BACKREFN_IC,         "backrefn-ic",          ARG_SPECIAL },
        !          5515:   { OP_BACKREF_MULTI,       "backref_multi",        ARG_SPECIAL },
        !          5516:   { OP_BACKREF_MULTI_IC,    "backref_multi-ic",     ARG_SPECIAL },
        !          5517:   { OP_BACKREF_AT_LEVEL,    "backref_at_level",     ARG_SPECIAL },
        !          5518:   { OP_MEMORY_START_PUSH,   "mem-start-push",       ARG_MEMNUM  },
        !          5519:   { OP_MEMORY_START,        "mem-start",            ARG_MEMNUM  },
        !          5520:   { OP_MEMORY_END_PUSH,     "mem-end-push",         ARG_MEMNUM  },
        !          5521:   { OP_MEMORY_END_PUSH_REC, "mem-end-push-rec",     ARG_MEMNUM  },
        !          5522:   { OP_MEMORY_END,          "mem-end",              ARG_MEMNUM  },
        !          5523:   { OP_MEMORY_END_REC,      "mem-end-rec",          ARG_MEMNUM  },
        !          5524:   { OP_SET_OPTION_PUSH,     "set-option-push",      ARG_OPTION  },
        !          5525:   { OP_SET_OPTION,          "set-option",           ARG_OPTION  },
        !          5526:   { OP_FAIL,                "fail",                 ARG_NON },
        !          5527:   { OP_JUMP,                "jump",                 ARG_RELADDR },
        !          5528:   { OP_PUSH,                "push",                 ARG_RELADDR },
        !          5529:   { OP_POP,                 "pop",                  ARG_NON },
        !          5530:   { OP_PUSH_OR_JUMP_EXACT1, "push-or-jump-e1",      ARG_SPECIAL },
        !          5531:   { OP_PUSH_IF_PEEK_NEXT,   "push-if-peek-next",    ARG_SPECIAL },
        !          5532:   { OP_REPEAT,              "repeat",               ARG_SPECIAL },
        !          5533:   { OP_REPEAT_NG,           "repeat-ng",            ARG_SPECIAL },
        !          5534:   { OP_REPEAT_INC,          "repeat-inc",           ARG_MEMNUM  },
        !          5535:   { OP_REPEAT_INC_NG,       "repeat-inc-ng",        ARG_MEMNUM  },
        !          5536:   { OP_REPEAT_INC_SG,       "repeat-inc-sg",        ARG_MEMNUM  },
        !          5537:   { OP_REPEAT_INC_NG_SG,    "repeat-inc-ng-sg",     ARG_MEMNUM  },
        !          5538:   { OP_NULL_CHECK_START,    "null-check-start",     ARG_MEMNUM  },
        !          5539:   { OP_NULL_CHECK_END,      "null-check-end",       ARG_MEMNUM  },
        !          5540:   { OP_NULL_CHECK_END_MEMST,"null-check-end-memst", ARG_MEMNUM  },
        !          5541:   { OP_NULL_CHECK_END_MEMST_PUSH,"null-check-end-memst-push", ARG_MEMNUM  },
        !          5542:   { OP_PUSH_POS,             "push-pos",             ARG_NON },
        !          5543:   { OP_POP_POS,              "pop-pos",              ARG_NON },
        !          5544:   { OP_PUSH_POS_NOT,         "push-pos-not",         ARG_RELADDR },
        !          5545:   { OP_FAIL_POS,             "fail-pos",             ARG_NON },
        !          5546:   { OP_PUSH_STOP_BT,         "push-stop-bt",         ARG_NON },
        !          5547:   { OP_POP_STOP_BT,          "pop-stop-bt",          ARG_NON },
        !          5548:   { OP_LOOK_BEHIND,          "look-behind",          ARG_SPECIAL },
        !          5549:   { OP_PUSH_LOOK_BEHIND_NOT, "push-look-behind-not", ARG_SPECIAL },
        !          5550:   { OP_FAIL_LOOK_BEHIND_NOT, "fail-look-behind-not", ARG_NON },
        !          5551:   { OP_CALL,                 "call",                 ARG_ABSADDR },
        !          5552:   { OP_RETURN,               "return",               ARG_NON },
        !          5553:   { OP_STATE_CHECK_PUSH,         "state-check-push",         ARG_SPECIAL },
        !          5554:   { OP_STATE_CHECK_PUSH_OR_JUMP, "state-check-push-or-jump", ARG_SPECIAL },
        !          5555:   { OP_STATE_CHECK,              "state-check",              ARG_STATE_CHECK },
        !          5556:   { OP_STATE_CHECK_ANYCHAR_STAR, "state-check-anychar*",     ARG_STATE_CHECK },
        !          5557:   { OP_STATE_CHECK_ANYCHAR_ML_STAR,
        !          5558:     "state-check-anychar-ml*", ARG_STATE_CHECK },
        !          5559:   { -1, "", ARG_NON }
        !          5560: };
        !          5561: 
        !          5562: static char*
        !          5563: op2name(int opcode)
        !          5564: {
        !          5565:   int i;
        !          5566: 
        !          5567:   for (i = 0; OnigOpInfo[i].opcode >= 0; i++) {
        !          5568:     if (opcode == OnigOpInfo[i].opcode)
        !          5569:       return OnigOpInfo[i].name;
        !          5570:   }
        !          5571:   return "";
        !          5572: }
        !          5573: 
        !          5574: static int
        !          5575: op2arg_type(int opcode)
        !          5576: {
        !          5577:   int i;
        !          5578: 
        !          5579:   for (i = 0; OnigOpInfo[i].opcode >= 0; i++) {
        !          5580:     if (opcode == OnigOpInfo[i].opcode)
        !          5581:       return OnigOpInfo[i].arg_type;
        !          5582:   }
        !          5583:   return ARG_SPECIAL;
        !          5584: }
        !          5585: 
        !          5586: static void
        !          5587: Indent(FILE* f, int indent)
        !          5588: {
        !          5589:   int i;
        !          5590:   for (i = 0; i < indent; i++) putc(' ', f);
        !          5591: }
        !          5592: 
        !          5593: static void
        !          5594: p_string(FILE* f, int len, UChar* s)
        !          5595: {
        !          5596:   fputs(":", f);
        !          5597:   while (len-- > 0) { fputc(*s++, f); }
        !          5598: }
        !          5599: 
        !          5600: static void
        !          5601: p_len_string(FILE* f, LengthType len, int mb_len, UChar* s)
        !          5602: {
        !          5603:   int x = len * mb_len;
        !          5604: 
        !          5605:   fprintf(f, ":%d:", len);
        !          5606:   while (x-- > 0) { fputc(*s++, f); }
        !          5607: }
        !          5608: 
        !          5609: extern void
        !          5610: onig_print_compiled_byte_code(FILE* f, UChar* bp, UChar** nextp,
        !          5611:                               OnigEncoding enc)
        !          5612: {
        !          5613:   int i, n, arg_type;
        !          5614:   RelAddrType addr;
        !          5615:   LengthType len;
        !          5616:   MemNumType mem;
        !          5617:   StateCheckNumType scn;
        !          5618:   OnigCodePoint code;
        !          5619:   UChar *q;
        !          5620: 
        !          5621:   fprintf(f, "[%s", op2name(*bp));
        !          5622:   arg_type = op2arg_type(*bp);
        !          5623:   if (arg_type != ARG_SPECIAL) {
        !          5624:     bp++;
        !          5625:     switch (arg_type) {
        !          5626:     case ARG_NON:
        !          5627:       break;
        !          5628:     case ARG_RELADDR:
        !          5629:       GET_RELADDR_INC(addr, bp);
        !          5630:       fprintf(f, ":(%d)", addr);
        !          5631:       break;
        !          5632:     case ARG_ABSADDR:
        !          5633:       GET_ABSADDR_INC(addr, bp);
        !          5634:       fprintf(f, ":(%d)", addr);
        !          5635:       break;
        !          5636:     case ARG_LENGTH:
        !          5637:       GET_LENGTH_INC(len, bp);
        !          5638:       fprintf(f, ":%d", len);
        !          5639:       break;
        !          5640:     case ARG_MEMNUM:
        !          5641:       mem = *((MemNumType* )bp);
        !          5642:       bp += SIZE_MEMNUM;
        !          5643:       fprintf(f, ":%d", mem);
        !          5644:       break;
        !          5645:     case ARG_OPTION:
        !          5646:       {
        !          5647:        OnigOptionType option = *((OnigOptionType* )bp);
        !          5648:        bp += SIZE_OPTION;
        !          5649:        fprintf(f, ":%d", option);
        !          5650:       }
        !          5651:       break;
        !          5652: 
        !          5653:     case ARG_STATE_CHECK:
        !          5654:       scn = *((StateCheckNumType* )bp);
        !          5655:       bp += SIZE_STATE_CHECK_NUM;
        !          5656:       fprintf(f, ":%d", scn);
        !          5657:       break;
        !          5658:     }
        !          5659:   }
        !          5660:   else {
        !          5661:     switch (*bp++) {
        !          5662:     case OP_EXACT1:
        !          5663:     case OP_ANYCHAR_STAR_PEEK_NEXT:
        !          5664:     case OP_ANYCHAR_ML_STAR_PEEK_NEXT:
        !          5665:       p_string(f, 1, bp++); break;
        !          5666:     case OP_EXACT2:
        !          5667:       p_string(f, 2, bp); bp += 2; break;
        !          5668:     case OP_EXACT3:
        !          5669:       p_string(f, 3, bp); bp += 3; break;
        !          5670:     case OP_EXACT4:
        !          5671:       p_string(f, 4, bp); bp += 4; break;
        !          5672:     case OP_EXACT5:
        !          5673:       p_string(f, 5, bp); bp += 5; break;
        !          5674:     case OP_EXACTN:
        !          5675:       GET_LENGTH_INC(len, bp);
        !          5676:       p_len_string(f, len, 1, bp);
        !          5677:       bp += len;
        !          5678:       break;
        !          5679:     
        !          5680:     case OP_EXACTMB2N1:
        !          5681:       p_string(f, 2, bp); bp += 2; break;
        !          5682:     case OP_EXACTMB2N2:
        !          5683:       p_string(f, 4, bp); bp += 4; break;
        !          5684:     case OP_EXACTMB2N3:
        !          5685:       p_string(f, 6, bp); bp += 6; break;
        !          5686:     case OP_EXACTMB2N:
        !          5687:       GET_LENGTH_INC(len, bp);
        !          5688:       p_len_string(f, len, 2, bp);
        !          5689:       bp += len * 2;
        !          5690:       break;
        !          5691:     case OP_EXACTMB3N:
        !          5692:       GET_LENGTH_INC(len, bp);
        !          5693:       p_len_string(f, len, 3, bp);
        !          5694:       bp += len * 3;
        !          5695:       break;
        !          5696:     case OP_EXACTMBN:
        !          5697:       {
        !          5698:        int mb_len;
        !          5699:       
        !          5700:        GET_LENGTH_INC(mb_len, bp);
        !          5701:        GET_LENGTH_INC(len, bp);
        !          5702:        fprintf(f, ":%d:%d:", mb_len, len);
        !          5703:        n = len * mb_len;
        !          5704:        while (n-- > 0) { fputc(*bp++, f); }
        !          5705:       }
        !          5706:       break;
        !          5707: 
        !          5708:     case OP_EXACT1_IC:
        !          5709:       len = enc_len(enc, bp);
        !          5710:       p_string(f, len, bp);
        !          5711:       bp += len;
        !          5712:       break;
        !          5713:     case OP_EXACTN_IC:
        !          5714:       GET_LENGTH_INC(len, bp);
        !          5715:       p_len_string(f, len, 1, bp);
        !          5716:       bp += len;
        !          5717:       break;
        !          5718: 
        !          5719:     case OP_CCLASS:
        !          5720:       n = bitset_on_num((BitSetRef )bp);
        !          5721:       bp += SIZE_BITSET;
        !          5722:       fprintf(f, ":%d", n);
        !          5723:       break;
        !          5724: 
        !          5725:     case OP_CCLASS_NOT:
        !          5726:       n = bitset_on_num((BitSetRef )bp);
        !          5727:       bp += SIZE_BITSET;
        !          5728:       fprintf(f, ":%d", n);
        !          5729:       break;
        !          5730: 
        !          5731:     case OP_CCLASS_MB:
        !          5732:     case OP_CCLASS_MB_NOT:
        !          5733:       GET_LENGTH_INC(len, bp);
        !          5734:       q = bp;
        !          5735: #ifndef PLATFORM_UNALIGNED_WORD_ACCESS
        !          5736:       ALIGNMENT_RIGHT(q);
        !          5737: #endif
        !          5738:       GET_CODE_POINT(code, q);
        !          5739:       bp += len;
        !          5740:       fprintf(f, ":%d:%d", (int )code, len);
        !          5741:       break;
        !          5742: 
        !          5743:     case OP_CCLASS_MIX:
        !          5744:     case OP_CCLASS_MIX_NOT:
        !          5745:       n = bitset_on_num((BitSetRef )bp);
        !          5746:       bp += SIZE_BITSET;
        !          5747:       GET_LENGTH_INC(len, bp);
        !          5748:       q = bp;
        !          5749: #ifndef PLATFORM_UNALIGNED_WORD_ACCESS
        !          5750:       ALIGNMENT_RIGHT(q);
        !          5751: #endif
        !          5752:       GET_CODE_POINT(code, q);
        !          5753:       bp += len;
        !          5754:       fprintf(f, ":%d:%d:%d", n, (int )code, len);
        !          5755:       break;
        !          5756: 
        !          5757:     case OP_CCLASS_NODE:
        !          5758:       {
        !          5759:         CClassNode *cc;
        !          5760: 
        !          5761:         GET_POINTER_INC(cc, bp);
        !          5762:         n = bitset_on_num(cc->bs);
        !          5763:         fprintf(f, ":%u:%d", (unsigned int )cc, n);
        !          5764:       }
        !          5765:       break;
        !          5766: 
        !          5767:     case OP_BACKREFN_IC:
        !          5768:       mem = *((MemNumType* )bp);
        !          5769:       bp += SIZE_MEMNUM;
        !          5770:       fprintf(f, ":%d", mem);
        !          5771:       break;
        !          5772: 
        !          5773:     case OP_BACKREF_MULTI_IC:
        !          5774:     case OP_BACKREF_MULTI:
        !          5775:       fputs(" ", f);
        !          5776:       GET_LENGTH_INC(len, bp);
        !          5777:       for (i = 0; i < len; i++) {
        !          5778:        GET_MEMNUM_INC(mem, bp);
        !          5779:        if (i > 0) fputs(", ", f);
        !          5780:        fprintf(f, "%d", mem);
        !          5781:       }
        !          5782:       break;
        !          5783: 
        !          5784:     case OP_BACKREF_AT_LEVEL:
        !          5785:       {
        !          5786:        OnigOptionType option;
        !          5787:        LengthType level;
        !          5788: 
        !          5789:        GET_OPTION_INC(option, bp);
        !          5790:        fprintf(f, ":%d", option);
        !          5791:        GET_LENGTH_INC(level, bp);
        !          5792:        fprintf(f, ":%d", level);
        !          5793: 
        !          5794:        fputs(" ", f);
        !          5795:        GET_LENGTH_INC(len, bp);
        !          5796:        for (i = 0; i < len; i++) {
        !          5797:          GET_MEMNUM_INC(mem, bp);
        !          5798:          if (i > 0) fputs(", ", f);
        !          5799:          fprintf(f, "%d", mem);
        !          5800:        }
        !          5801:       }
        !          5802:       break;
        !          5803: 
        !          5804:     case OP_REPEAT:
        !          5805:     case OP_REPEAT_NG:
        !          5806:       {
        !          5807:        mem = *((MemNumType* )bp);
        !          5808:        bp += SIZE_MEMNUM;
        !          5809:        addr = *((RelAddrType* )bp);
        !          5810:        bp += SIZE_RELADDR;
        !          5811:        fprintf(f, ":%d:%d", mem, addr);
        !          5812:       }
        !          5813:       break;
        !          5814: 
        !          5815:     case OP_PUSH_OR_JUMP_EXACT1:
        !          5816:     case OP_PUSH_IF_PEEK_NEXT:
        !          5817:       addr = *((RelAddrType* )bp);
        !          5818:       bp += SIZE_RELADDR;
        !          5819:       fprintf(f, ":(%d)", addr);
        !          5820:       p_string(f, 1, bp);
        !          5821:       bp += 1;
        !          5822:       break;
        !          5823: 
        !          5824:     case OP_LOOK_BEHIND:
        !          5825:       GET_LENGTH_INC(len, bp);
        !          5826:       fprintf(f, ":%d", len);
        !          5827:       break;
        !          5828: 
        !          5829:     case OP_PUSH_LOOK_BEHIND_NOT:
        !          5830:       GET_RELADDR_INC(addr, bp);
        !          5831:       GET_LENGTH_INC(len, bp);
        !          5832:       fprintf(f, ":%d:(%d)", len, addr);
        !          5833:       break;
        !          5834: 
        !          5835:     case OP_STATE_CHECK_PUSH:
        !          5836:     case OP_STATE_CHECK_PUSH_OR_JUMP:
        !          5837:       scn = *((StateCheckNumType* )bp);
        !          5838:       bp += SIZE_STATE_CHECK_NUM;
        !          5839:       addr = *((RelAddrType* )bp);
        !          5840:       bp += SIZE_RELADDR;
        !          5841:       fprintf(f, ":%d:(%d)", scn, addr);
        !          5842:       break;
        !          5843: 
        !          5844:     default:
        !          5845:       fprintf(stderr, "onig_print_compiled_byte_code: undefined code %d\n",
        !          5846:              *--bp);
        !          5847:     }
        !          5848:   }
        !          5849:   fputs("]", f);
        !          5850:   if (nextp) *nextp = bp;
        !          5851: }
        !          5852: 
        !          5853: static void
        !          5854: print_compiled_byte_code_list(FILE* f, regex_t* reg)
        !          5855: {
        !          5856:   int ncode;
        !          5857:   UChar* bp = reg->p;
        !          5858:   UChar* end = reg->p + reg->used;
        !          5859: 
        !          5860:   fprintf(f, "code length: %d\n", reg->used);
        !          5861: 
        !          5862:   ncode = 0;
        !          5863:   while (bp < end) {
        !          5864:     ncode++;
        !          5865:     if (bp > reg->p) {
        !          5866:       if (ncode % 5 == 0)
        !          5867:        fprintf(f, "\n");
        !          5868:       else
        !          5869:        fputs(" ", f);
        !          5870:     }
        !          5871:     onig_print_compiled_byte_code(f, bp, &bp, reg->enc);
        !          5872:   }
        !          5873: 
        !          5874:   fprintf(f, "\n");
        !          5875: }
        !          5876: 
        !          5877: static void
        !          5878: print_indent_tree(FILE* f, Node* node, int indent)
        !          5879: {
        !          5880:   int i, type;
        !          5881:   int add = 3;
        !          5882:   UChar* p;
        !          5883: 
        !          5884:   Indent(f, indent);
        !          5885:   if (IS_NULL(node)) {
        !          5886:     fprintf(f, "ERROR: null node!!!\n");
        !          5887:     exit (0);
        !          5888:   }
        !          5889: 
        !          5890:   type = NTYPE(node);
        !          5891:   switch (type) {
        !          5892:   case N_LIST:
        !          5893:   case N_ALT:
        !          5894:     if (NTYPE(node) == N_LIST)
        !          5895:       fprintf(f, "<list:%x>\n", (int )node);
        !          5896:     else
        !          5897:       fprintf(f, "<alt:%x>\n", (int )node);
        !          5898: 
        !          5899:     print_indent_tree(f, NCONS(node).left, indent + add);
        !          5900:     while (IS_NOT_NULL(node = NCONS(node).right)) {
        !          5901:       if (NTYPE(node) != type) {
        !          5902:        fprintf(f, "ERROR: list/alt right is not a cons. %d\n", NTYPE(node));
        !          5903:        exit(0);
        !          5904:       }
        !          5905:       print_indent_tree(f, NCONS(node).left, indent + add);
        !          5906:     }
        !          5907:     break;
        !          5908: 
        !          5909:   case N_STRING:
        !          5910:     fprintf(f, "<string%s:%x>",
        !          5911:            (NSTRING_IS_RAW(node) ? "-raw" : ""), (int )node);
        !          5912:     for (p = NSTRING(node).s; p < NSTRING(node).end; p++) {
        !          5913:       if (*p >= 0x20 && *p < 0x7f)
        !          5914:        fputc(*p, f);
        !          5915:       else {
        !          5916:        fprintf(f, " 0x%02x", *p);
        !          5917:       }
        !          5918:     }
        !          5919:     break;
        !          5920: 
        !          5921:   case N_CCLASS:
        !          5922:     fprintf(f, "<cclass:%x>", (int )node);
        !          5923:     if (IS_CCLASS_NOT(&NCCLASS(node))) fputs(" not", f);
        !          5924:     if (NCCLASS(node).mbuf) {
        !          5925:       BBuf* bbuf = NCCLASS(node).mbuf;
        !          5926:       for (i = 0; i < bbuf->used; i++) {
        !          5927:        if (i > 0) fprintf(f, ",");
        !          5928:        fprintf(f, "%0x", bbuf->p[i]);
        !          5929:       }
        !          5930:     }
        !          5931:     break;
        !          5932: 
        !          5933:   case N_CTYPE:
        !          5934:     fprintf(f, "<ctype:%x> ", (int )node);
        !          5935:     switch (NCTYPE(node).type) {
        !          5936:     case CTYPE_WORD:            fputs("word",           f); break;
        !          5937:     case CTYPE_NOT_WORD:        fputs("not word",       f); break;
        !          5938:     default:
        !          5939:       fprintf(f, "ERROR: undefined ctype.\n");
        !          5940:       exit(0);
        !          5941:     }
        !          5942:     break;
        !          5943: 
        !          5944:   case N_ANYCHAR:
        !          5945:     fprintf(f, "<anychar:%x>", (int )node);
        !          5946:     break;
        !          5947: 
        !          5948:   case N_ANCHOR:
        !          5949:     fprintf(f, "<anchor:%x> ", (int )node);
        !          5950:     switch (NANCHOR(node).type) {
        !          5951:     case ANCHOR_BEGIN_BUF:      fputs("begin buf",      f); break;
        !          5952:     case ANCHOR_END_BUF:        fputs("end buf",        f); break;
        !          5953:     case ANCHOR_BEGIN_LINE:     fputs("begin line",     f); break;
        !          5954:     case ANCHOR_END_LINE:       fputs("end line",       f); break;
        !          5955:     case ANCHOR_SEMI_END_BUF:   fputs("semi end buf",   f); break;
        !          5956:     case ANCHOR_BEGIN_POSITION: fputs("begin position", f); break;
        !          5957: 
        !          5958:     case ANCHOR_WORD_BOUND:      fputs("word bound",     f); break;
        !          5959:     case ANCHOR_NOT_WORD_BOUND:  fputs("not word bound", f); break;
        !          5960: #ifdef USE_WORD_BEGIN_END
        !          5961:     case ANCHOR_WORD_BEGIN:      fputs("word begin", f);     break;
        !          5962:     case ANCHOR_WORD_END:        fputs("word end", f);       break;
        !          5963: #endif
        !          5964:     case ANCHOR_PREC_READ:       fputs("prec read",      f); break;
        !          5965:     case ANCHOR_PREC_READ_NOT:   fputs("prec read not",  f); break;
        !          5966:     case ANCHOR_LOOK_BEHIND:     fputs("look_behind",    f); break;
        !          5967:     case ANCHOR_LOOK_BEHIND_NOT: fputs("look_behind_not",f); break;
        !          5968: 
        !          5969:     default:
        !          5970:       fprintf(f, "ERROR: undefined anchor type.\n");
        !          5971:       break;
        !          5972:     }
        !          5973:     break;
        !          5974: 
        !          5975:   case N_BACKREF:
        !          5976:     {
        !          5977:       int* p;
        !          5978:       BackrefNode* br = &(NBACKREF(node));
        !          5979:       p = BACKREFS_P(br);
        !          5980:       fprintf(f, "<backref:%x>", (int )node);
        !          5981:       for (i = 0; i < br->back_num; i++) {
        !          5982:        if (i > 0) fputs(", ", f);
        !          5983:        fprintf(f, "%d", p[i]);
        !          5984:       }
        !          5985:     }
        !          5986:     break;
        !          5987: 
        !          5988: #ifdef USE_SUBEXP_CALL
        !          5989:   case N_CALL:
        !          5990:     {
        !          5991:       CallNode* cn = &(NCALL(node));
        !          5992:       fprintf(f, "<call:%x>", (int )node);
        !          5993:       p_string(f, cn->name_end - cn->name, cn->name);
        !          5994:     }
        !          5995:     break;
        !          5996: #endif
        !          5997: 
        !          5998:   case N_QUANTIFIER:
        !          5999:     fprintf(f, "<quantifier:%x>{%d,%d}%s\n", (int )node,
        !          6000:            NQUANTIFIER(node).lower, NQUANTIFIER(node).upper,
        !          6001:            (NQUANTIFIER(node).greedy ? "" : "?"));
        !          6002:     print_indent_tree(f, NQUANTIFIER(node).target, indent + add);
        !          6003:     break;
        !          6004: 
        !          6005:   case N_EFFECT:
        !          6006:     fprintf(f, "<effect:%x> ", (int )node);
        !          6007:     switch (NEFFECT(node).type) {
        !          6008:     case EFFECT_OPTION:
        !          6009:       fprintf(f, "option:%d\n", NEFFECT(node).option);
        !          6010:       print_indent_tree(f, NEFFECT(node).target, indent + add);
        !          6011:       break;
        !          6012:     case EFFECT_MEMORY:
        !          6013:       fprintf(f, "memory:%d", NEFFECT(node).regnum);
        !          6014:       break;
        !          6015:     case EFFECT_STOP_BACKTRACK:
        !          6016:       fprintf(f, "stop-bt");
        !          6017:       break;
        !          6018: 
        !          6019:     default:
        !          6020:       break;
        !          6021:     }
        !          6022:     fprintf(f, "\n");
        !          6023:     print_indent_tree(f, NEFFECT(node).target, indent + add);
        !          6024:     break;
        !          6025: 
        !          6026:   default:
        !          6027:     fprintf(f, "print_indent_tree: undefined node type %d\n", NTYPE(node));
        !          6028:     break;
        !          6029:   }
        !          6030: 
        !          6031:   if (type != N_LIST && type != N_ALT && type != N_QUANTIFIER &&
        !          6032:       type != N_EFFECT)
        !          6033:     fprintf(f, "\n");
        !          6034:   fflush(f);
        !          6035: }
        !          6036: #endif /* ONIG_DEBUG */
        !          6037: 
        !          6038: #ifdef ONIG_DEBUG_PARSE_TREE
        !          6039: static void
        !          6040: print_tree(FILE* f, Node* node)
        !          6041: {
        !          6042:   print_indent_tree(f, node, 0);
        !          6043: }
        !          6044: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>