PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - mbstring/oniguruma - regcomp.c
Test: PHP Code Coverage
Date: 2009-11-19 Instrumented lines: 2274
Code covered: 51.5 % Executed lines: 1172
Legend: not executed executed

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