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 - regparse.c
Test: PHP Code Coverage
Date: 2009-11-19 Instrumented lines: 2506
Code covered: 35.8 % Executed lines: 897
Legend: not executed executed

       1                 : /**********************************************************************
       2                 :   regparse.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                 : #define WARN_BUFSIZE    256
      33                 : 
      34                 : OnigSyntaxType OnigSyntaxRuby = {
      35                 :   (( SYN_GNU_REGEX_OP | ONIG_SYN_OP_QMARK_NON_GREEDY |
      36                 :      ONIG_SYN_OP_ESC_OCTAL3 | ONIG_SYN_OP_ESC_X_HEX2 |
      37                 :      ONIG_SYN_OP_ESC_X_BRACE_HEX8 | ONIG_SYN_OP_ESC_CONTROL_CHARS |
      38                 :      ONIG_SYN_OP_ESC_C_CONTROL )
      39                 :    & ~ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END )
      40                 :   , ( ONIG_SYN_OP2_QMARK_GROUP_EFFECT |
      41                 :       ONIG_SYN_OP2_OPTION_RUBY |
      42                 :       ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP | ONIG_SYN_OP2_ESC_K_NAMED_BACKREF |
      43                 :       ONIG_SYN_OP2_ESC_G_SUBEXP_CALL |
      44                 :       ONIG_SYN_OP2_PLUS_POSSESSIVE_REPEAT |
      45                 :       ONIG_SYN_OP2_CCLASS_SET_OP | ONIG_SYN_OP2_ESC_CAPITAL_C_BAR_CONTROL |
      46                 :       ONIG_SYN_OP2_ESC_CAPITAL_M_BAR_META | ONIG_SYN_OP2_ESC_V_VTAB |
      47                 :       ONIG_SYN_OP2_ESC_H_XDIGIT )
      48                 :   , ( SYN_GNU_REGEX_BV | 
      49                 :       ONIG_SYN_ALLOW_INTERVAL_LOW_ABBREV |
      50                 :       ONIG_SYN_DIFFERENT_LEN_ALT_LOOK_BEHIND |
      51                 :       ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP |
      52                 :       ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME |
      53                 :       ONIG_SYN_FIXED_INTERVAL_IS_GREEDY_ONLY |
      54                 :       ONIG_SYN_WARN_CC_OP_NOT_ESCAPED |
      55                 :       ONIG_SYN_WARN_REDUNDANT_NESTED_REPEAT )
      56                 :   , ONIG_OPTION_NONE
      57                 : };
      58                 : 
      59                 : OnigSyntaxType*  OnigDefaultSyntax = ONIG_SYNTAX_RUBY;
      60                 : 
      61               0 : extern void onig_null_warn(const char* s) { }
      62                 : 
      63                 : #ifdef RUBY_PLATFORM
      64                 : extern void
      65                 : onig_rb_warn(const char* s)
      66                 : {
      67                 :   rb_warn(s);
      68                 : }
      69                 : 
      70                 : extern void
      71                 : onig_rb_warning(const char* s)
      72                 : {
      73                 :   rb_warning(s);
      74                 : }
      75                 : #endif
      76                 : 
      77                 : #ifdef DEFAULT_WARN_FUNCTION
      78                 : static OnigWarnFunc onig_warn = (OnigWarnFunc )DEFAULT_WARN_FUNCTION;
      79                 : #else
      80                 : static OnigWarnFunc onig_warn = onig_null_warn;
      81                 : #endif
      82                 : 
      83                 : #ifdef DEFAULT_VERB_WARN_FUNCTION
      84                 : static OnigWarnFunc onig_verb_warn = (OnigWarnFunc )DEFAULT_VERB_WARN_FUNCTION;
      85                 : #else
      86                 : static OnigWarnFunc onig_verb_warn = onig_null_warn;
      87                 : #endif
      88                 : 
      89                 : extern void onig_set_warn_func(OnigWarnFunc f)
      90               0 : {
      91               0 :   onig_warn = f;
      92               0 : }
      93                 : 
      94                 : extern void onig_set_verb_warn_func(OnigWarnFunc f)
      95               0 : {
      96               0 :   onig_verb_warn = f;
      97               0 : }
      98                 : 
      99                 : static void
     100                 : bbuf_free(BBuf* bbuf)
     101              42 : {
     102              42 :   if (IS_NOT_NULL(bbuf)) {
     103              42 :     if (IS_NOT_NULL(bbuf->p)) xfree(bbuf->p);
     104              42 :     xfree(bbuf);
     105                 :   }
     106              42 : }
     107                 : 
     108                 : static int
     109                 : bbuf_clone(BBuf** rto, BBuf* from)
     110               0 : {
     111                 :   int r;
     112                 :   BBuf *to;
     113                 : 
     114               0 :   *rto = to = (BBuf* )xmalloc(sizeof(BBuf));
     115               0 :   CHECK_NULL_RETURN_VAL(to, ONIGERR_MEMORY);
     116               0 :   r = BBUF_INIT(to, from->alloc);
     117               0 :   if (r != 0) return r;
     118               0 :   to->used = from->used;
     119               0 :   xmemcpy(to->p, from->p, from->used);
     120               0 :   return 0;
     121                 : }
     122                 : 
     123                 : #define ONOFF(v,f,negative)    (negative) ? ((v) &= ~(f)) : ((v) |= (f))
     124                 : 
     125                 : #define MBCODE_START_POS(enc) \
     126                 :   (OnigCodePoint )(ONIGENC_MBC_MINLEN(enc) > 1 ? 0 : 0x80)
     127                 : 
     128                 : #define SET_ALL_MULTI_BYTE_RANGE(enc, pbuf) \
     129                 :   add_code_range_to_buf(pbuf, MBCODE_START_POS(enc), ~((OnigCodePoint )0))
     130                 : 
     131                 : #define ADD_ALL_MULTI_BYTE_RANGE(enc, mbuf) do {\
     132                 :   if (! ONIGENC_IS_SINGLEBYTE(enc)) {\
     133                 :     r = SET_ALL_MULTI_BYTE_RANGE(enc, &(mbuf));\
     134                 :     if (r) return r;\
     135                 :   }\
     136                 : } while (0)
     137                 : 
     138                 : 
     139                 : #define BITSET_IS_EMPTY(bs,empty) do {\
     140                 :   int i;\
     141                 :   empty = 1;\
     142                 :   for (i = 0; i < BITSET_SIZE; i++) {\
     143                 :     if ((bs)[i] != 0) {\
     144                 :       empty = 0; break;\
     145                 :     }\
     146                 :   }\
     147                 : } while (0)
     148                 : 
     149                 : static void
     150                 : bitset_set_range(BitSetRef bs, int from, int to)
     151              34 : {
     152                 :   int i;
     153             744 :   for (i = from; i <= to && i < SINGLE_BYTE_SIZE; i++) {
     154             710 :     BITSET_SET_BIT(bs, i);
     155                 :   }
     156              34 : }
     157                 : 
     158                 : #if 0
     159                 : static void
     160                 : bitset_set_all(BitSetRef bs)
     161                 : {
     162                 :   int i;
     163                 :   for (i = 0; i < BITSET_SIZE; i++) {
     164                 :     bs[i] = ~((Bits )0);
     165                 :   }
     166                 : }
     167                 : #endif
     168                 : 
     169                 : static void
     170                 : bitset_invert(BitSetRef bs)
     171               0 : {
     172                 :   int i;
     173               0 :   for (i = 0; i < BITSET_SIZE; i++) {
     174               0 :     bs[i] = ~(bs[i]);
     175                 :   }
     176               0 : }
     177                 : 
     178                 : static void
     179                 : bitset_invert_to(BitSetRef from, BitSetRef to)
     180               0 : {
     181                 :   int i;
     182               0 :   for (i = 0; i < BITSET_SIZE; i++) {
     183               0 :     to[i] = ~(from[i]);
     184                 :   }
     185               0 : }
     186                 : 
     187                 : static void
     188                 : bitset_and(BitSetRef dest, BitSetRef bs)
     189               0 : {
     190                 :   int i;
     191               0 :   for (i = 0; i < BITSET_SIZE; i++) {
     192               0 :     dest[i] &= bs[i];
     193                 :   }
     194               0 : }
     195                 : 
     196                 : static void
     197                 : bitset_or(BitSetRef dest, BitSetRef bs)
     198               0 : {
     199                 :   int i;
     200               0 :   for (i = 0; i < BITSET_SIZE; i++) {
     201               0 :     dest[i] |= bs[i];
     202                 :   }
     203               0 : }
     204                 : 
     205                 : static void
     206                 : bitset_copy(BitSetRef dest, BitSetRef bs)
     207               0 : {
     208                 :   int i;
     209               0 :   for (i = 0; i < BITSET_SIZE; i++) {
     210               0 :     dest[i] = bs[i];
     211                 :   }
     212               0 : }
     213                 : 
     214                 : extern int
     215                 : onig_strncmp(const UChar* s1, const UChar* s2, int n)
     216               0 : {
     217                 :   int x;
     218                 : 
     219               0 :   while (n-- > 0) {
     220               0 :     x = *s2++ - *s1++;
     221               0 :     if (x) return x;
     222                 :   }
     223               0 :   return 0;
     224                 : }
     225                 : 
     226                 : static void
     227                 : k_strcpy(UChar* dest, const UChar* src, const UChar* end)
     228             355 : {
     229             355 :   int len = end - src;
     230             355 :   if (len > 0) {
     231             355 :     xmemcpy(dest, src, len);
     232             355 :     dest[len] = (UChar )0;
     233                 :   }
     234             355 : }
     235                 : 
     236                 : static UChar*
     237                 : strdup_with_null(OnigEncoding enc, UChar* s, UChar* end)
     238               0 : {
     239                 :   int slen, term_len, i;
     240                 :   UChar *r;
     241                 : 
     242               0 :   slen = end - s;
     243               0 :   term_len = ONIGENC_MBC_MINLEN(enc);
     244                 : 
     245               0 :   r = (UChar* )xmalloc(slen + term_len);
     246               0 :   CHECK_NULL_RETURN(r);
     247               0 :   xmemcpy(r, s, slen);
     248                 : 
     249               0 :   for (i = 0; i < term_len; i++)
     250               0 :     r[slen + i] = (UChar )0;
     251                 : 
     252               0 :   return r;
     253                 : }
     254                 : 
     255                 : 
     256                 : /* scan pattern methods */
     257                 : #define PEND_VALUE   0
     258                 : 
     259                 : #define PFETCH_READY  UChar* pfetch_prev
     260                 : #define PEND         (p < end ?  0 : 1)
     261                 : #define PUNFETCH     p = pfetch_prev
     262                 : #define PINC       do { \
     263                 :   pfetch_prev = p; \
     264                 :   p += ONIGENC_MBC_ENC_LEN(enc, p); \
     265                 : } while (0)
     266                 : #define PFETCH(c)  do { \
     267                 :   c = ONIGENC_MBC_TO_CODE(enc, p, end); \
     268                 :   pfetch_prev = p; \
     269                 :   p += ONIGENC_MBC_ENC_LEN(enc, p); \
     270                 : } while (0)
     271                 : 
     272                 : #define PPEEK        (p < end ? ONIGENC_MBC_TO_CODE(enc, p, end) : PEND_VALUE)
     273                 : #define PPEEK_IS(c)  (PPEEK == (OnigCodePoint )c)
     274                 : 
     275                 : static UChar*
     276                 : k_strcat_capa(UChar* dest, UChar* dest_end, const UChar* src, const UChar* src_end,
     277                 :               int capa)
     278               0 : {
     279                 :   UChar* r;
     280                 : 
     281               0 :   if (dest)
     282               0 :     r = (UChar* )xrealloc(dest, capa + 1);
     283                 :   else
     284               0 :     r = (UChar* )xmalloc(capa + 1);
     285                 : 
     286               0 :   CHECK_NULL_RETURN(r);
     287               0 :   k_strcpy(r + (dest_end - dest), src, src_end);
     288               0 :   return r;
     289                 : }
     290                 : 
     291                 : /* dest on static area */
     292                 : static UChar*
     293                 : strcat_capa_from_static(UChar* dest, UChar* dest_end,
     294                 :                         const UChar* src, const UChar* src_end, int capa)
     295               0 : {
     296                 :   UChar* r;
     297                 : 
     298               0 :   r = (UChar* )xmalloc(capa + 1);
     299               0 :   CHECK_NULL_RETURN(r);
     300               0 :   k_strcpy(r, dest, dest_end);
     301               0 :   k_strcpy(r + (dest_end - dest), src, src_end);
     302               0 :   return r;
     303                 : }
     304                 : 
     305                 : #ifdef USE_NAMED_GROUP
     306                 : 
     307                 : #define INIT_NAME_BACKREFS_ALLOC_NUM   8
     308                 : 
     309                 : typedef struct {
     310                 :   UChar* name;
     311                 :   int    name_len;   /* byte length */
     312                 :   int    back_num;   /* number of backrefs */
     313                 :   int    back_alloc;
     314                 :   int    back_ref1;
     315                 :   int*   back_refs;
     316                 : } NameEntry;
     317                 : 
     318                 : #ifdef USE_ST_HASH_TABLE
     319                 : 
     320                 : #include "st.h"
     321                 : 
     322                 : typedef struct {
     323                 :   unsigned char* s;
     324                 :   unsigned char* end;
     325                 : } st_strend_key;
     326                 : 
     327                 : static int strend_cmp(st_strend_key*, st_strend_key*);
     328                 : static int strend_hash(st_strend_key*);
     329                 : 
     330                 : static struct st_hash_type type_strend_hash = {
     331                 :   strend_cmp,
     332                 :   strend_hash,
     333                 : };
     334                 : 
     335                 : static st_table*
     336                 : onig_st_init_strend_table_with_size(int size)
     337               0 : {
     338               0 :     return onig_st_init_table_with_size(&type_strend_hash, size);
     339                 : }
     340                 : 
     341                 : static int
     342                 : onig_st_lookup_strend(st_table *table, const UChar* str_key, const UChar* end_key, st_data_t *value)
     343               0 : {
     344                 :     st_strend_key key;
     345                 : 
     346               0 :     key.s   = (unsigned char* )str_key;
     347               0 :     key.end = (unsigned char* )end_key;
     348                 : 
     349               0 :     return onig_st_lookup(table, (st_data_t )(&key), value);
     350                 : }
     351                 : 
     352                 : static int
     353                 : onig_st_insert_strend(st_table *table, const UChar* str_key, const UChar* end_key, st_data_t value)
     354               0 : {
     355                 :   st_strend_key* key;
     356                 :   int result;
     357                 : 
     358               0 :   key = (st_strend_key* )xmalloc(sizeof(st_strend_key));
     359               0 :   key->s   = (unsigned char* )str_key;
     360               0 :   key->end = (unsigned char* )end_key;
     361               0 :   result = onig_st_insert(table, (st_data_t )key, value);
     362               0 :   if (result) {
     363               0 :     xfree(key);
     364                 :   }
     365               0 :   return result;
     366                 : }
     367                 : 
     368                 : static int
     369                 : strend_cmp(st_strend_key* x, st_strend_key* y)
     370               0 : {
     371                 :   unsigned char *p, *q;
     372                 :   int c;
     373                 : 
     374               0 :   if ((x->end - x->s) != (y->end - y->s))
     375               0 :     return 1;
     376                 : 
     377               0 :   p = x->s;
     378               0 :   q = y->s;
     379               0 :   while (p < x->end) {
     380               0 :     c = (int )*p - (int )*q;
     381               0 :     if (c != 0) return c;
     382                 : 
     383               0 :     p++; q++;
     384                 :   }
     385                 : 
     386               0 :   return 0;
     387                 : }
     388                 : 
     389                 : static int
     390                 : strend_hash(st_strend_key* x)
     391               0 : {
     392                 :   int val;
     393                 :   unsigned char *p;
     394                 : 
     395               0 :   val = 0;
     396               0 :   p = x->s;
     397               0 :   while (p < x->end) {
     398               0 :     val = val * 997 + (int )*p++;
     399                 :   }
     400                 : 
     401               0 :   return val + (val >> 5);
     402                 : }
     403                 : 
     404                 : typedef st_table  NameTable;
     405                 : typedef st_data_t HashDataType;   /* 1.6 st.h doesn't define st_data_t type */
     406                 : 
     407                 : #define NAMEBUF_SIZE    24
     408                 : #define NAMEBUF_SIZE_1  25
     409                 : 
     410                 : #ifdef ONIG_DEBUG
     411                 : static int
     412                 : i_print_name_entry(UChar* key, NameEntry* e, void* arg)
     413                 : {
     414                 :   int i;
     415                 :   FILE* fp = (FILE* )arg;
     416                 : 
     417                 :   fprintf(fp, "%s: ", e->name);
     418                 :   if (e->back_num == 0)
     419                 :     fputs("-", fp);
     420                 :   else if (e->back_num == 1)
     421                 :     fprintf(fp, "%d", e->back_ref1);
     422                 :   else {
     423                 :     for (i = 0; i < e->back_num; i++) {
     424                 :       if (i > 0) fprintf(fp, ", ");
     425                 :       fprintf(fp, "%d", e->back_refs[i]);
     426                 :     }
     427                 :   }
     428                 :   fputs("\n", fp);
     429                 :   return ST_CONTINUE;
     430                 : }
     431                 : 
     432                 : extern int
     433                 : onig_print_names(FILE* fp, regex_t* reg)
     434                 : {
     435                 :   NameTable* t = (NameTable* )reg->name_table;
     436                 : 
     437                 :   if (IS_NOT_NULL(t)) {
     438                 :     fprintf(fp, "name table\n");
     439                 :     onig_st_foreach(t, i_print_name_entry, (HashDataType )fp);
     440                 :     fputs("\n", fp);
     441                 :   }
     442                 :   return 0;
     443                 : }
     444                 : #endif
     445                 : 
     446                 : static int
     447                 : i_free_name_entry(UChar* key, NameEntry* e, void* arg)
     448               0 : {
     449               0 :   xfree(e->name);
     450               0 :   if (IS_NOT_NULL(e->back_refs)) xfree(e->back_refs);
     451               0 :   xfree(key);
     452               0 :   xfree(e);
     453               0 :   return ST_DELETE;
     454                 : }
     455                 : 
     456                 : static int
     457                 : names_clear(regex_t* reg)
     458             290 : {
     459             290 :   NameTable* t = (NameTable* )reg->name_table;
     460                 : 
     461             290 :   if (IS_NOT_NULL(t)) {
     462               0 :     onig_st_foreach(t, i_free_name_entry, 0);
     463                 :   }
     464             290 :   return 0;
     465                 : }
     466                 : 
     467                 : extern int
     468                 : onig_names_free(regex_t* reg)
     469             145 : {
     470                 :   int r;
     471                 :   NameTable* t;
     472                 : 
     473             145 :   r = names_clear(reg);
     474             145 :   if (r) return r;
     475                 : 
     476             145 :   t = (NameTable* )reg->name_table;
     477             145 :   if (IS_NOT_NULL(t)) onig_st_free_table(t);
     478             145 :   reg->name_table = (void* )NULL;
     479             145 :   return 0;
     480                 : }
     481                 : 
     482                 : static NameEntry*
     483                 : name_find(regex_t* reg, const UChar* name, const UChar* name_end)
     484               0 : {
     485                 :   NameEntry* e;
     486               0 :   NameTable* t = (NameTable* )reg->name_table;
     487                 : 
     488               0 :   e = (NameEntry* )NULL;
     489               0 :   if (IS_NOT_NULL(t)) {
     490               0 :     onig_st_lookup_strend(t, name, name_end, (HashDataType* )((void* )(&e)));
     491                 :   }
     492               0 :   return e;
     493                 : }
     494                 : 
     495                 : typedef struct {
     496                 :   int (*func)(const UChar*, const UChar*,int,int*,regex_t*,void*);
     497                 :   regex_t* reg;
     498                 :   void* arg;
     499                 :   int ret;
     500                 :   OnigEncoding enc;
     501                 : } INamesArg;
     502                 : 
     503                 : static int
     504                 : i_names(UChar* key, NameEntry* e, INamesArg* arg)
     505               0 : {
     506                 :   int r = (*(arg->func))(e->name,
     507                 :                    /*e->name + onigenc_str_bytelen_null(arg->enc, e->name), */
     508                 :                          e->name + e->name_len,
     509                 :                          e->back_num,
     510                 :                          (e->back_num > 1 ? e->back_refs : &(e->back_ref1)),
     511               0 :                          arg->reg, arg->arg);
     512               0 :   if (r != 0) {
     513               0 :     arg->ret = r;
     514               0 :     return ST_STOP;
     515                 :   }
     516               0 :   return ST_CONTINUE;
     517                 : }
     518                 : 
     519                 : extern int
     520                 : onig_foreach_name(regex_t* reg,
     521                 :            int (*func)(const UChar*, const UChar*,int,int*,regex_t*,void*),
     522                 :            void* arg)
     523               0 : {
     524                 :   INamesArg narg;
     525               0 :   NameTable* t = (NameTable* )reg->name_table;
     526                 : 
     527               0 :   narg.ret = 0;
     528               0 :   if (IS_NOT_NULL(t)) {
     529               0 :     narg.func = func;
     530               0 :     narg.reg  = reg;
     531               0 :     narg.arg  = arg;
     532               0 :     narg.enc  = reg->enc; /* should be pattern encoding. */
     533               0 :     onig_st_foreach(t, i_names, (HashDataType )&narg);
     534                 :   }
     535               0 :   return narg.ret;
     536                 : }
     537                 : 
     538                 : static int
     539                 : i_renumber_name(UChar* key, NameEntry* e, GroupNumRemap* map)
     540               0 : {
     541                 :   int i;
     542                 : 
     543               0 :   if (e->back_num > 1) {
     544               0 :     for (i = 0; i < e->back_num; i++) {
     545               0 :       e->back_refs[i] = map[e->back_refs[i]].new_val;
     546                 :     }
     547                 :   }
     548               0 :   else if (e->back_num == 1) {
     549               0 :     e->back_ref1 = map[e->back_ref1].new_val;
     550                 :   }
     551                 : 
     552               0 :   return ST_CONTINUE;
     553                 : }
     554                 : 
     555                 : extern int
     556                 : onig_renumber_name_table(regex_t* reg, GroupNumRemap* map)
     557               0 : {
     558               0 :   NameTable* t = (NameTable* )reg->name_table;
     559                 : 
     560               0 :   if (IS_NOT_NULL(t)) {
     561               0 :     onig_st_foreach(t, i_renumber_name, (HashDataType )map);
     562                 :   }
     563               0 :   return 0;
     564                 : }
     565                 : 
     566                 : 
     567                 : extern int
     568                 : onig_number_of_names(regex_t* reg)
     569               0 : {
     570               0 :   NameTable* t = (NameTable* )reg->name_table;
     571                 : 
     572               0 :   if (IS_NOT_NULL(t))
     573               0 :     return t->num_entries;
     574                 :   else
     575               0 :     return 0;
     576                 : }
     577                 : 
     578                 : #else  /* USE_ST_HASH_TABLE */
     579                 : 
     580                 : #define INIT_NAMES_ALLOC_NUM    8
     581                 : 
     582                 : typedef struct {
     583                 :   NameEntry* e;
     584                 :   int        num;
     585                 :   int        alloc;
     586                 : } NameTable;
     587                 : 
     588                 : 
     589                 : #ifdef ONIG_DEBUG
     590                 : extern int
     591                 : onig_print_names(FILE* fp, regex_t* reg)
     592                 : {
     593                 :   int i, j;
     594                 :   NameEntry* e;
     595                 :   NameTable* t = (NameTable* )reg->name_table;
     596                 : 
     597                 :   if (IS_NOT_NULL(t) && t->num > 0) {
     598                 :     fprintf(fp, "name table\n");
     599                 :     for (i = 0; i < t->num; i++) {
     600                 :       e = &(t->e[i]);
     601                 :       fprintf(fp, "%s: ", e->name);
     602                 :       if (e->back_num == 0) {
     603                 :         fputs("-", fp);
     604                 :       }
     605                 :       else if (e->back_num == 1) {
     606                 :         fprintf(fp, "%d", e->back_ref1);
     607                 :       }
     608                 :       else {
     609                 :         for (j = 0; j < e->back_num; j++) {
     610                 :           if (j > 0) fprintf(fp, ", ");
     611                 :           fprintf(fp, "%d", e->back_refs[j]);
     612                 :         }
     613                 :       }
     614                 :       fputs("\n", fp);
     615                 :     }
     616                 :     fputs("\n", fp);
     617                 :   }
     618                 :   return 0;
     619                 : }
     620                 : #endif
     621                 : 
     622                 : static int
     623                 : names_clear(regex_t* reg)
     624                 : {
     625                 :   int i;
     626                 :   NameEntry* e;
     627                 :   NameTable* t = (NameTable* )reg->name_table;
     628                 : 
     629                 :   if (IS_NOT_NULL(t)) {
     630                 :     for (i = 0; i < t->num; i++) {
     631                 :       e = &(t->e[i]);
     632                 :       if (IS_NOT_NULL(e->name)) {
     633                 :         xfree(e->name);
     634                 :         e->name       = NULL;
     635                 :         e->name_len   = 0;
     636                 :         e->back_num   = 0;
     637                 :         e->back_alloc = 0;
     638                 :         if (IS_NOT_NULL(e->back_refs)) xfree(e->back_refs);
     639                 :         e->back_refs = (int* )NULL;
     640                 :       }
     641                 :     }
     642                 :     if (IS_NOT_NULL(t->e)) {
     643                 :       xfree(t->e);
     644                 :       t->e = NULL;
     645                 :     }
     646                 :     t->num = 0;
     647                 :   }
     648                 :   return 0;
     649                 : }
     650                 : 
     651                 : extern int
     652                 : onig_names_free(regex_t* reg)
     653                 : {
     654                 :   int r;
     655                 :   NameTable* t;
     656                 : 
     657                 :   r = names_clear(reg);
     658                 :   if (r) return r;
     659                 : 
     660                 :   t = (NameTable* )reg->name_table;
     661                 :   if (IS_NOT_NULL(t)) xfree(t);
     662                 :   reg->name_table = NULL;
     663                 :   return 0;
     664                 : }
     665                 : 
     666                 : static NameEntry*
     667                 : name_find(regex_t* reg, UChar* name, UChar* name_end)
     668                 : {
     669                 :   int i, len;
     670                 :   NameEntry* e;
     671                 :   NameTable* t = (NameTable* )reg->name_table;
     672                 : 
     673                 :   if (IS_NOT_NULL(t)) {
     674                 :     len = name_end - name;
     675                 :     for (i = 0; i < t->num; i++) {
     676                 :       e = &(t->e[i]);
     677                 :       if (len == e->name_len && onig_strncmp(name, e->name, len) == 0)
     678                 :         return e;
     679                 :     }
     680                 :   }
     681                 :   return (NameEntry* )NULL;
     682                 : }
     683                 : 
     684                 : extern int
     685                 : onig_foreach_name(regex_t* reg,
     686                 :            int (*func)(const UChar*, const UChar*,int,int*,regex_t*,void*),
     687                 :            void* arg)
     688                 : {
     689                 :   int i, r;
     690                 :   NameEntry* e;
     691                 :   NameTable* t = (NameTable* )reg->name_table;
     692                 : 
     693                 :   if (IS_NOT_NULL(t)) {
     694                 :     for (i = 0; i < t->num; i++) {
     695                 :       e = &(t->e[i]);
     696                 :       r = (*func)(e->name, e->name + e->name_len, e->back_num,
     697                 :                   (e->back_num > 1 ? e->back_refs : &(e->back_ref1)),
     698                 :                   reg, arg);
     699                 :       if (r != 0) return r;
     700                 :     }
     701                 :   }
     702                 :   return 0;
     703                 : }
     704                 : 
     705                 : extern int
     706                 : onig_number_of_names(regex_t* reg)
     707                 : {
     708                 :   NameTable* t = (NameTable* )reg->name_table;
     709                 : 
     710                 :   if (IS_NOT_NULL(t))
     711                 :     return t->num;
     712                 :   else
     713                 :     return 0;
     714                 : }
     715                 : 
     716                 : #endif /* else USE_ST_HASH_TABLE */
     717                 : 
     718                 : static int
     719                 : name_add(regex_t* reg, UChar* name, UChar* name_end, int backref, ScanEnv* env)
     720               0 : {
     721                 :   int alloc;
     722                 :   NameEntry* e;
     723               0 :   NameTable* t = (NameTable* )reg->name_table;
     724                 : 
     725               0 :   if (name_end - name <= 0)
     726               0 :     return ONIGERR_EMPTY_GROUP_NAME;
     727                 : 
     728               0 :   e = name_find(reg, name, name_end);
     729               0 :   if (IS_NULL(e)) {
     730                 : #ifdef USE_ST_HASH_TABLE
     731               0 :     if (IS_NULL(t)) {
     732               0 :       t = onig_st_init_strend_table_with_size(5);
     733               0 :       reg->name_table = (void* )t;
     734                 :     }
     735               0 :     e = (NameEntry* )xmalloc(sizeof(NameEntry));
     736               0 :     CHECK_NULL_RETURN_VAL(e, ONIGERR_MEMORY);
     737                 : 
     738               0 :     e->name = strdup_with_null(reg->enc, name, name_end);
     739               0 :     if (IS_NULL(e->name)) return ONIGERR_MEMORY;
     740               0 :     onig_st_insert_strend(t, e->name, (e->name + (name_end - name)),
     741                 :                           (HashDataType )e);
     742                 : 
     743               0 :     e->name_len   = name_end - name;
     744               0 :     e->back_num   = 0;
     745               0 :     e->back_alloc = 0;
     746               0 :     e->back_refs  = (int* )NULL;
     747                 : 
     748                 : #else
     749                 : 
     750                 :     if (IS_NULL(t)) {
     751                 :       alloc = INIT_NAMES_ALLOC_NUM;
     752                 :       t = (NameTable* )xmalloc(sizeof(NameTable));
     753                 :       CHECK_NULL_RETURN_VAL(t, ONIGERR_MEMORY);
     754                 :       t->e     = NULL;
     755                 :       t->alloc = 0;
     756                 :       t->num   = 0;
     757                 : 
     758                 :       t->e = (NameEntry* )xmalloc(sizeof(NameEntry) * alloc);
     759                 :       if (IS_NULL(t->e)) {
     760                 :         xfree(t);
     761                 :         return ONIGERR_MEMORY;
     762                 :       }
     763                 :       t->alloc = alloc;
     764                 :       reg->name_table = t;
     765                 :       goto clear;
     766                 :     }
     767                 :     else if (t->num == t->alloc) {
     768                 :       int i;
     769                 : 
     770                 :       alloc = t->alloc * 2;
     771                 :       t->e = (NameEntry* )xrealloc(t->e, sizeof(NameEntry) * alloc);
     772                 :       CHECK_NULL_RETURN_VAL(t->e, ONIGERR_MEMORY);
     773                 :       t->alloc = alloc;
     774                 : 
     775                 :     clear:
     776                 :       for (i = t->num; i < t->alloc; i++) {
     777                 :         t->e[i].name       = NULL;
     778                 :         t->e[i].name_len   = 0;
     779                 :         t->e[i].back_num   = 0;
     780                 :         t->e[i].back_alloc = 0;
     781                 :         t->e[i].back_refs  = (int* )NULL;
     782                 :       }
     783                 :     }
     784                 :     e = &(t->e[t->num]);
     785                 :     t->num++;
     786                 :     e->name = strdup_with_null(reg->enc, name, name_end);
     787                 :     e->name_len = name_end - name;
     788                 : #endif
     789                 :   }
     790                 : 
     791               0 :   if (e->back_num >= 1 &&
     792                 :       ! IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME)) {
     793               0 :     onig_scan_env_set_error_string(env, ONIGERR_MULTIPLEX_DEFINED_NAME,
     794                 :                                     name, name_end);
     795               0 :     return ONIGERR_MULTIPLEX_DEFINED_NAME;
     796                 :   }
     797                 : 
     798               0 :   e->back_num++;
     799               0 :   if (e->back_num == 1) {
     800               0 :     e->back_ref1 = backref;
     801                 :   }
     802                 :   else {
     803               0 :     if (e->back_num == 2) {
     804               0 :       alloc = INIT_NAME_BACKREFS_ALLOC_NUM;
     805               0 :       e->back_refs = (int* )xmalloc(sizeof(int) * alloc);
     806               0 :       CHECK_NULL_RETURN_VAL(e->back_refs, ONIGERR_MEMORY);
     807               0 :       e->back_alloc = alloc;
     808               0 :       e->back_refs[0] = e->back_ref1;
     809               0 :       e->back_refs[1] = backref;
     810                 :     }
     811                 :     else {
     812               0 :       if (e->back_num > e->back_alloc) {
     813               0 :         alloc = e->back_alloc * 2;
     814               0 :         e->back_refs = (int* )xrealloc(e->back_refs, sizeof(int) * alloc);
     815               0 :         CHECK_NULL_RETURN_VAL(e->back_refs, ONIGERR_MEMORY);
     816               0 :         e->back_alloc = alloc;
     817                 :       }
     818               0 :       e->back_refs[e->back_num - 1] = backref;
     819                 :     }
     820                 :   }
     821                 : 
     822               0 :   return 0;
     823                 : }
     824                 : 
     825                 : extern int
     826                 : onig_name_to_group_numbers(regex_t* reg, const UChar* name,
     827                 :                            const UChar* name_end, int** nums)
     828               0 : {
     829                 :   NameEntry* e;
     830                 : 
     831               0 :   e = name_find(reg, name, name_end);
     832               0 :   if (IS_NULL(e)) return ONIGERR_UNDEFINED_NAME_REFERENCE;
     833                 : 
     834               0 :   switch (e->back_num) {
     835                 :   case 0:
     836               0 :     break;
     837                 :   case 1:
     838               0 :     *nums = &(e->back_ref1);
     839               0 :     break;
     840                 :   default:
     841               0 :     *nums = e->back_refs;
     842                 :     break;
     843                 :   }
     844               0 :   return e->back_num;
     845                 : }
     846                 : 
     847                 : extern int
     848                 : onig_name_to_backref_number(regex_t* reg, const UChar* name,
     849                 :                             const UChar* name_end, OnigRegion *region)
     850               0 : {
     851                 :   int i, n, *nums;
     852                 : 
     853               0 :   n = onig_name_to_group_numbers(reg, name, name_end, &nums);
     854               0 :   if (n < 0)
     855               0 :     return n;
     856               0 :   else if (n == 0)
     857               0 :     return ONIGERR_PARSER_BUG;
     858               0 :   else if (n == 1)
     859               0 :     return nums[0];
     860                 :   else {
     861               0 :     if (IS_NOT_NULL(region)) {
     862               0 :       for (i = n - 1; i >= 0; i--) {
     863               0 :         if (region->beg[nums[i]] != ONIG_REGION_NOTPOS)
     864               0 :           return nums[i];
     865                 :       }
     866                 :     }
     867               0 :     return nums[n - 1];
     868                 :   }
     869                 : }
     870                 : 
     871                 : #else /* USE_NAMED_GROUP */
     872                 : 
     873                 : extern int
     874                 : onig_name_to_group_numbers(regex_t* reg, const UChar* name,
     875                 :                            const UChar* name_end, int** nums)
     876                 : {
     877                 :   return ONIG_NO_SUPPORT_CONFIG;
     878                 : }
     879                 : 
     880                 : extern int
     881                 : onig_name_to_backref_number(regex_t* reg, const UChar* name,
     882                 :                             const UChar* name_end, OnigRegion* region)
     883                 : {
     884                 :   return ONIG_NO_SUPPORT_CONFIG;
     885                 : }
     886                 : 
     887                 : extern int
     888                 : onig_foreach_name(regex_t* reg,
     889                 :            int (*func)(const UChar*, const UChar*,int,int*,regex_t*,void*),
     890                 :            void* arg)
     891                 : {
     892                 :   return ONIG_NO_SUPPORT_CONFIG;
     893                 : }
     894                 : 
     895                 : extern int
     896                 : onig_number_of_names(regex_t* reg)
     897                 : {
     898                 :   return 0;
     899                 : }
     900                 : #endif /* else USE_NAMED_GROUP */
     901                 : 
     902                 : extern int
     903                 : onig_noname_group_capture_is_active(regex_t* reg)
     904               0 : {
     905               0 :   if (ONIG_IS_OPTION_ON(reg->options, ONIG_OPTION_DONT_CAPTURE_GROUP))
     906               0 :     return 0;
     907                 : 
     908                 : #ifdef USE_NAMED_GROUP
     909               0 :   if (onig_number_of_names(reg) > 0 &&
     910                 :       IS_SYNTAX_BV(reg->syntax, ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP) &&
     911                 :       !ONIG_IS_OPTION_ON(reg->options, ONIG_OPTION_CAPTURE_GROUP)) {
     912               0 :     return 0;
     913                 :   }
     914                 : #endif
     915                 : 
     916               0 :   return 1;
     917                 : }
     918                 : 
     919                 : 
     920                 : #define INIT_SCANENV_MEMNODES_ALLOC_SIZE   16
     921                 : 
     922                 : static void
     923                 : scan_env_clear(ScanEnv* env)
     924             145 : {
     925                 :   int i;
     926                 : 
     927             145 :   BIT_STATUS_CLEAR(env->capture_history);
     928             145 :   BIT_STATUS_CLEAR(env->bt_mem_start);
     929             145 :   BIT_STATUS_CLEAR(env->bt_mem_end);
     930             145 :   BIT_STATUS_CLEAR(env->backrefed_mem);
     931             145 :   env->error             = (UChar* )NULL;
     932             145 :   env->error_end         = (UChar* )NULL;
     933             145 :   env->num_call          = 0;
     934             145 :   env->num_mem           = 0;
     935                 : #ifdef USE_NAMED_GROUP
     936             145 :   env->num_named         = 0;
     937                 : #endif
     938             145 :   env->mem_alloc         = 0;
     939             145 :   env->mem_nodes_dynamic = (Node** )NULL;
     940                 : 
     941            1305 :   for (i = 0; i < SCANENV_MEMNODES_SIZE; i++)
     942            1160 :     env->mem_nodes_static[i] = NULL_NODE;
     943                 : 
     944                 : #ifdef USE_COMBINATION_EXPLOSION_CHECK
     945             145 :   env->num_comb_exp_check  = 0;
     946             145 :   env->comb_exp_max_regnum = 0;
     947             145 :   env->curr_max_regnum     = 0;
     948             145 :   env->has_recursion       = 0;
     949                 : #endif
     950             145 : }
     951                 : 
     952                 : static int
     953                 : scan_env_add_mem_entry(ScanEnv* env)
     954              61 : {
     955                 :   int i, need, alloc;
     956                 :   Node** p;
     957                 : 
     958              61 :   need = env->num_mem + 1;
     959              61 :   if (need >= SCANENV_MEMNODES_SIZE) {
     960               0 :     if (env->mem_alloc <= need) {
     961               0 :       if (IS_NULL(env->mem_nodes_dynamic)) {
     962               0 :         alloc = INIT_SCANENV_MEMNODES_ALLOC_SIZE;
     963               0 :         p = (Node** )xmalloc(sizeof(Node*) * alloc);
     964               0 :         xmemcpy(p, env->mem_nodes_static,
     965                 :                 sizeof(Node*) * SCANENV_MEMNODES_SIZE);
     966                 :       }
     967                 :       else {
     968               0 :         alloc = env->mem_alloc * 2;
     969               0 :         p = (Node** )xrealloc(env->mem_nodes_dynamic, sizeof(Node*) * alloc);
     970                 :       }
     971               0 :       CHECK_NULL_RETURN_VAL(p, ONIGERR_MEMORY);
     972                 : 
     973               0 :       for (i = env->num_mem + 1; i < alloc; i++)
     974               0 :         p[i] = NULL_NODE;
     975                 : 
     976               0 :       env->mem_nodes_dynamic = p;
     977               0 :       env->mem_alloc = alloc;
     978                 :     }
     979                 :   }
     980                 : 
     981              61 :   env->num_mem++;
     982              61 :   return env->num_mem;
     983                 : }
     984                 : 
     985                 : static int
     986                 : scan_env_set_mem_node(ScanEnv* env, int num, Node* node)
     987              61 : {
     988              61 :   if (env->num_mem >= num)
     989              61 :     SCANENV_MEM_NODES(env)[num] = node;
     990                 :   else
     991               0 :     return ONIGERR_PARSER_BUG;
     992              61 :   return 0;
     993                 : }
     994                 : 
     995                 : 
     996                 : #ifdef USE_RECYCLE_NODE
     997                 : typedef struct _FreeNode {
     998                 :   struct _FreeNode* next;
     999                 : } FreeNode;
    1000                 : 
    1001                 : static FreeNode* FreeNodeList = (FreeNode* )NULL;
    1002                 : #endif
    1003                 : 
    1004                 : extern void
    1005                 : onig_node_free(Node* node)
    1006             781 : {
    1007             781 :  start:
    1008             781 :   if (IS_NULL(node)) return ;
    1009                 : 
    1010             717 :   switch (NTYPE(node)) {
    1011                 :   case N_STRING:
    1012             151 :     if (IS_NOT_NULL(NSTRING(node).s) && NSTRING(node).s != NSTRING(node).buf) {
    1013               0 :       xfree(NSTRING(node).s);
    1014                 :     }
    1015             151 :     break;
    1016                 : 
    1017                 :   case N_LIST:
    1018                 :   case N_ALT:
    1019             217 :     onig_node_free(NCONS(node).left);
    1020                 :     /* onig_node_free(NCONS(node).right); */
    1021                 :     {
    1022             217 :       Node* next_node = NCONS(node).right;
    1023                 : 
    1024                 : #ifdef USE_RECYCLE_NODE
    1025                 :       {
    1026             217 :         FreeNode* n = (FreeNode* )node;
    1027                 : 
    1028                 :         THREAD_ATOMIC_START;
    1029             217 :         n->next = FreeNodeList;
    1030             217 :         FreeNodeList = n;
    1031                 :         THREAD_ATOMIC_END;
    1032                 :       }
    1033                 : #else
    1034                 :       xfree(node);
    1035                 : #endif
    1036                 : 
    1037             217 :       node = next_node;
    1038             217 :       goto start;
    1039                 :     }
    1040                 :     break;
    1041                 : 
    1042                 :   case N_CCLASS:
    1043                 :     {
    1044              99 :       CClassNode* cc = &(NCCLASS(node));
    1045                 : 
    1046              99 :       if (IS_CCLASS_SHARE(cc))
    1047               6 :         return ;
    1048                 : 
    1049              93 :       if (cc->mbuf)
    1050              42 :         bbuf_free(cc->mbuf);
    1051                 :     }
    1052              93 :     break;
    1053                 : 
    1054                 :   case N_QUALIFIER:
    1055             126 :     if (NQUALIFIER(node).target)
    1056             126 :       onig_node_free(NQUALIFIER(node).target);
    1057             126 :     break;
    1058                 : 
    1059                 :   case N_EFFECT:
    1060              76 :     if (NEFFECT(node).target)
    1061              76 :       onig_node_free(NEFFECT(node).target);
    1062              76 :     break;
    1063                 : 
    1064                 :   case N_BACKREF:
    1065               0 :     if (IS_NOT_NULL(NBACKREF(node).back_dynamic))
    1066               0 :       xfree(NBACKREF(node).back_dynamic);
    1067               0 :     break;
    1068                 : 
    1069                 :   case N_ANCHOR:
    1070              18 :     if (NANCHOR(node).target)
    1071               0 :       onig_node_free(NANCHOR(node).target);
    1072                 :     break;
    1073                 :   }
    1074                 : 
    1075                 : #ifdef USE_RECYCLE_NODE
    1076                 :   {
    1077             494 :     FreeNode* n = (FreeNode* )node;
    1078                 : 
    1079                 :     THREAD_ATOMIC_START;
    1080             494 :     n->next = FreeNodeList;
    1081             494 :     FreeNodeList = n;
    1082                 :     THREAD_ATOMIC_END;
    1083                 :   }
    1084                 : #else
    1085                 :   xfree(node);
    1086                 : #endif
    1087                 : }
    1088                 : 
    1089                 : #ifdef USE_RECYCLE_NODE
    1090                 : extern int
    1091                 : onig_free_node_list()
    1092           13597 : {
    1093                 :   FreeNode* n;
    1094                 : 
    1095                 :   /* THREAD_ATOMIC_START; */
    1096           27453 :   while (IS_NOT_NULL(FreeNodeList)) {
    1097             259 :     n = FreeNodeList;
    1098             259 :     FreeNodeList = FreeNodeList->next;
    1099             259 :     xfree(n);
    1100                 :   }
    1101                 :   /* THREAD_ATOMIC_END; */
    1102           13597 :   return 0;
    1103                 : }
    1104                 : #endif
    1105                 : 
    1106                 : static Node*
    1107                 : node_new()
    1108             717 : {
    1109                 :   Node* node;
    1110                 : 
    1111                 : #ifdef USE_RECYCLE_NODE
    1112                 :   THREAD_ATOMIC_START;
    1113             717 :   if (IS_NOT_NULL(FreeNodeList)) {
    1114             452 :     node = (Node* )FreeNodeList;
    1115             452 :     FreeNodeList = FreeNodeList->next;
    1116                 :     THREAD_ATOMIC_END;
    1117             452 :     return node;
    1118                 :   }
    1119                 :   THREAD_ATOMIC_END;
    1120                 : #endif
    1121                 : 
    1122             265 :   node = (Node* )xmalloc(sizeof(Node));
    1123             265 :   return node;
    1124                 : }
    1125                 : 
    1126                 : 
    1127                 : static void
    1128                 : initialize_cclass(CClassNode* cc)
    1129              93 : {
    1130              93 :   BITSET_CLEAR(cc->bs);
    1131              93 :   cc->flags = 0;
    1132              93 :   cc->mbuf  = NULL;
    1133              93 : }
    1134                 : 
    1135                 : static Node*
    1136                 : node_new_cclass()
    1137              93 : {
    1138              93 :   Node* node = node_new();
    1139              93 :   CHECK_NULL_RETURN(node);
    1140              93 :   node->type = N_CCLASS;
    1141                 : 
    1142              93 :   initialize_cclass(&(NCCLASS(node)));
    1143              93 :   return node;
    1144                 : }
    1145                 : 
    1146                 : static Node*
    1147                 : node_new_cclass_by_codepoint_range(int not,
    1148                 :                    const OnigCodePoint sbr[], const OnigCodePoint mbr[])
    1149               6 : {
    1150                 :   CClassNode* cc;
    1151                 :   int n, i, j;
    1152                 : 
    1153               6 :   Node* node = node_new();
    1154               6 :   CHECK_NULL_RETURN(node);
    1155               6 :   node->type = N_CCLASS;
    1156                 : 
    1157               6 :   cc = &(NCCLASS(node));
    1158               6 :   cc->flags = 0;
    1159               6 :   if (not != 0) CCLASS_SET_NOT(cc);
    1160                 : 
    1161               6 :   BITSET_CLEAR(cc->bs);
    1162               6 :   if (IS_NOT_NULL(sbr)) {
    1163               6 :     n = ONIGENC_CODE_RANGE_NUM(sbr);
    1164              16 :     for (i = 0; i < n; i++) {
    1165              10 :       for (j  = ONIGENC_CODE_RANGE_FROM(sbr, i);
    1166              54 :            j <= (int )ONIGENC_CODE_RANGE_TO(sbr, i); j++) {
    1167              44 :         BITSET_SET_BIT(cc->bs, j);
    1168                 :       }
    1169                 :     }
    1170                 :   }
    1171                 : 
    1172               6 :   if (IS_NULL(mbr)) {
    1173               0 :   is_null:
    1174               0 :     cc->mbuf = NULL;
    1175                 :   }
    1176                 :   else {
    1177                 :     BBuf* bbuf;
    1178                 : 
    1179               6 :     n = ONIGENC_CODE_RANGE_NUM(mbr);
    1180               6 :     if (n == 0) goto is_null;
    1181                 : 
    1182               6 :     bbuf = (BBuf* )xmalloc(sizeof(BBuf));
    1183               6 :     CHECK_NULL_RETURN_VAL(bbuf, NULL);
    1184               6 :     bbuf->alloc = n + 1;
    1185               6 :     bbuf->used  = n + 1;
    1186               6 :     bbuf->p     = (UChar* )((void* )mbr);
    1187                 : 
    1188               6 :     cc->mbuf = bbuf;
    1189                 :   }
    1190                 : 
    1191               6 :   return node;
    1192                 : }
    1193                 : 
    1194                 : static Node*
    1195                 : node_new_ctype(int type)
    1196               4 : {
    1197               4 :   Node* node = node_new();
    1198               4 :   CHECK_NULL_RETURN(node);
    1199               4 :   node->type = N_CTYPE;
    1200               4 :   NCTYPE(node).type = type;
    1201               4 :   return node;
    1202                 : }
    1203                 : 
    1204                 : static Node*
    1205                 : node_new_anychar()
    1206              26 : {
    1207              26 :   Node* node = node_new();
    1208              26 :   CHECK_NULL_RETURN(node);
    1209              26 :   node->type = N_ANYCHAR;
    1210              26 :   return node;
    1211                 : }
    1212                 : 
    1213                 : static Node*
    1214                 : node_new_list(Node* left, Node* right)
    1215             213 : {
    1216             213 :   Node* node = node_new();
    1217             213 :   CHECK_NULL_RETURN(node);
    1218             213 :   node->type = N_LIST;
    1219             213 :   NCONS(node).left  = left;
    1220             213 :   NCONS(node).right = right;
    1221             213 :   return node;
    1222                 : }
    1223                 : 
    1224                 : extern Node*
    1225                 : onig_node_new_list(Node* left, Node* right)
    1226               0 : {
    1227               0 :   return node_new_list(left, right);
    1228                 : }
    1229                 : 
    1230                 : static Node*
    1231                 : node_new_alt(Node* left, Node* right)
    1232               4 : {
    1233               4 :   Node* node = node_new();
    1234               4 :   CHECK_NULL_RETURN(node);
    1235               4 :   node->type = N_ALT;
    1236               4 :   NCONS(node).left  = left;
    1237               4 :   NCONS(node).right = right;
    1238               4 :   return node;
    1239                 : }
    1240                 : 
    1241                 : extern Node*
    1242                 : onig_node_new_anchor(int type)
    1243              18 : {
    1244              18 :   Node* node = node_new();
    1245              18 :   CHECK_NULL_RETURN(node);
    1246              18 :   node->type = N_ANCHOR;
    1247              18 :   NANCHOR(node).type     = type;
    1248              18 :   NANCHOR(node).target   = NULL;
    1249              18 :   NANCHOR(node).char_len = -1;
    1250              18 :   return node;
    1251                 : }
    1252                 : 
    1253                 : static Node*
    1254                 : node_new_backref(int back_num, int* backrefs, int by_name,
    1255                 : #ifdef USE_BACKREF_AT_LEVEL
    1256                 :                  int exist_level, int nest_level,
    1257                 : #endif
    1258                 :                  ScanEnv* env)
    1259               0 : {
    1260                 :   int i;
    1261               0 :   Node* node = node_new();
    1262                 : 
    1263               0 :   CHECK_NULL_RETURN(node);
    1264               0 :   node->type = N_BACKREF;
    1265               0 :   NBACKREF(node).state    = 0;
    1266               0 :   NBACKREF(node).back_num = back_num;
    1267               0 :   NBACKREF(node).back_dynamic = (int* )NULL;
    1268               0 :   if (by_name != 0)
    1269               0 :     NBACKREF(node).state |= NST_NAME_REF;
    1270                 : 
    1271                 : #ifdef USE_BACKREF_AT_LEVEL
    1272               0 :   if (exist_level != 0) {
    1273               0 :     NBACKREF(node).state |= NST_NEST_LEVEL;
    1274               0 :     NBACKREF(node).nest_level  = nest_level;
    1275                 :   }
    1276                 : #endif
    1277                 : 
    1278               0 :   for (i = 0; i < back_num; i++) {
    1279               0 :     if (backrefs[i] <= env->num_mem &&
    1280                 :         IS_NULL(SCANENV_MEM_NODES(env)[backrefs[i]])) {
    1281               0 :       NBACKREF(node).state |= NST_RECURSION;   /* /...(\1).../ */
    1282               0 :       break;
    1283                 :     }
    1284                 :   }
    1285                 : 
    1286               0 :   if (back_num <= NODE_BACKREFS_SIZE) {
    1287               0 :     for (i = 0; i < back_num; i++)
    1288               0 :       NBACKREF(node).back_static[i] = backrefs[i];
    1289                 :   }
    1290                 :   else {
    1291               0 :     int* p = (int* )xmalloc(sizeof(int) * back_num);
    1292               0 :     if (IS_NULL(p)) {
    1293               0 :       onig_node_free(node);
    1294               0 :       return NULL;
    1295                 :     }
    1296               0 :     NBACKREF(node).back_dynamic = p;
    1297               0 :     for (i = 0; i < back_num; i++)
    1298               0 :       p[i] = backrefs[i];
    1299                 :   }
    1300               0 :   return node;
    1301                 : }
    1302                 : 
    1303                 : #ifdef USE_SUBEXP_CALL
    1304                 : static Node*
    1305                 : node_new_call(UChar* name, UChar* name_end)
    1306               0 : {
    1307               0 :   Node* node = node_new();
    1308               0 :   CHECK_NULL_RETURN(node);
    1309                 : 
    1310               0 :   node->type = N_CALL;
    1311               0 :   NCALL(node).state    = 0;
    1312               0 :   NCALL(node).ref_num  = CALLNODE_REFNUM_UNDEF;
    1313               0 :   NCALL(node).target   = NULL_NODE;
    1314               0 :   NCALL(node).name     = name;
    1315               0 :   NCALL(node).name_end = name_end;
    1316               0 :   return node;
    1317                 : }
    1318                 : #endif
    1319                 : 
    1320                 : static Node*
    1321                 : node_new_qualifier(int lower, int upper, int by_number)
    1322             126 : {
    1323             126 :   Node* node = node_new();
    1324             126 :   CHECK_NULL_RETURN(node);
    1325             126 :   node->type = N_QUALIFIER;
    1326             126 :   NQUALIFIER(node).state  = 0;
    1327             126 :   NQUALIFIER(node).target = NULL;
    1328             126 :   NQUALIFIER(node).lower  = lower;
    1329             126 :   NQUALIFIER(node).upper  = upper;
    1330             126 :   NQUALIFIER(node).greedy = 1;
    1331             126 :   NQUALIFIER(node).target_empty_info = NQ_TARGET_ISNOT_EMPTY;
    1332             126 :   NQUALIFIER(node).head_exact        = NULL_NODE;
    1333             126 :   NQUALIFIER(node).next_head_exact   = NULL_NODE;
    1334             126 :   NQUALIFIER(node).is_refered        = 0;
    1335             126 :   if (by_number != 0)
    1336               4 :     NQUALIFIER(node).state |= NST_BY_NUMBER;
    1337                 : 
    1338                 : #ifdef USE_COMBINATION_EXPLOSION_CHECK
    1339             126 :   NQUALIFIER(node).comb_exp_check_num = 0;
    1340                 : #endif
    1341                 : 
    1342             126 :   return node;
    1343                 : }
    1344                 : 
    1345                 : static Node*
    1346                 : node_new_effect(int type)
    1347              76 : {
    1348              76 :   Node* node = node_new();
    1349              76 :   CHECK_NULL_RETURN(node);
    1350              76 :   node->type = N_EFFECT;
    1351              76 :   NEFFECT(node).type      = type;
    1352              76 :   NEFFECT(node).state     =  0;
    1353              76 :   NEFFECT(node).regnum    =  0;
    1354              76 :   NEFFECT(node).option    =  0;
    1355              76 :   NEFFECT(node).target    = NULL;
    1356              76 :   NEFFECT(node).call_addr = -1;
    1357              76 :   NEFFECT(node).opt_count =  0;
    1358              76 :   return node;
    1359                 : }
    1360                 : 
    1361                 : extern Node*
    1362                 : onig_node_new_effect(int type)
    1363              15 : {
    1364              15 :   return node_new_effect(type);
    1365                 : }
    1366                 : 
    1367                 : static Node*
    1368                 : node_new_effect_memory(OnigOptionType option, int is_named)
    1369              61 : {
    1370              61 :   Node* node = node_new_effect(EFFECT_MEMORY);
    1371              61 :   CHECK_NULL_RETURN(node);
    1372              61 :   if (is_named != 0)
    1373               0 :     SET_EFFECT_STATUS(node, NST_NAMED_GROUP);
    1374                 : 
    1375                 : #ifdef USE_SUBEXP_CALL
    1376              61 :   NEFFECT(node).option = option;
    1377                 : #endif
    1378              61 :   return node;
    1379                 : }
    1380                 : 
    1381                 : static Node*
    1382                 : node_new_option(OnigOptionType option)
    1383               0 : {
    1384               0 :   Node* node = node_new_effect(EFFECT_OPTION);
    1385               0 :   CHECK_NULL_RETURN(node);
    1386               0 :   NEFFECT(node).option = option;
    1387               0 :   return node;
    1388                 : }
    1389                 : 
    1390                 : extern int
    1391                 : onig_node_str_cat(Node* node, const UChar* s, const UChar* end)
    1392             357 : {
    1393             357 :   int addlen = end - s;
    1394                 : 
    1395             357 :   if (addlen > 0) {
    1396             355 :     int len  = NSTRING(node).end - NSTRING(node).s;
    1397                 : 
    1398             355 :     if (NSTRING(node).capa > 0 || (len + addlen > NODE_STR_BUF_SIZE - 1)) {
    1399                 :       UChar* p;
    1400               0 :       int capa = len + addlen + NODE_STR_MARGIN;
    1401                 : 
    1402               0 :       if (capa <= NSTRING(node).capa) {
    1403               0 :         k_strcpy(NSTRING(node).s + len, s, end);
    1404                 :       }
    1405                 :       else {
    1406               0 :         if (NSTRING(node).s == NSTRING(node).buf)
    1407               0 :           p = strcat_capa_from_static(NSTRING(node).s, NSTRING(node).end,
    1408                 :                                       s, end, capa);
    1409                 :         else
    1410               0 :           p = k_strcat_capa(NSTRING(node).s, NSTRING(node).end, s, end, capa);
    1411                 : 
    1412               0 :         CHECK_NULL_RETURN_VAL(p, ONIGERR_MEMORY);
    1413               0 :         NSTRING(node).s    = p;
    1414               0 :         NSTRING(node).capa = capa;
    1415                 :       }
    1416                 :     }
    1417                 :     else {
    1418             355 :       k_strcpy(NSTRING(node).s + len, s, end);
    1419                 :     }
    1420             355 :     NSTRING(node).end = NSTRING(node).s + len + addlen;
    1421                 :   }
    1422                 : 
    1423             357 :   return 0;
    1424                 : }
    1425                 : 
    1426                 : static int
    1427                 : node_str_cat_char(Node* node, UChar c)
    1428               0 : {
    1429                 :   UChar s[1];
    1430                 : 
    1431               0 :   s[0] = c;
    1432               0 :   return onig_node_str_cat(node, s, s + 1);
    1433                 : }
    1434                 : 
    1435                 : extern void
    1436                 : onig_node_conv_to_str_node(Node* node, int flag)
    1437               0 : {
    1438               0 :   node->type = N_STRING;
    1439                 : 
    1440               0 :   NSTRING(node).flag = flag;
    1441               0 :   NSTRING(node).capa = 0;
    1442               0 :   NSTRING(node).s    = NSTRING(node).buf;
    1443               0 :   NSTRING(node).end  = NSTRING(node).buf;
    1444               0 : }
    1445                 : 
    1446                 : extern void
    1447                 : onig_node_str_clear(Node* node)
    1448               0 : {
    1449               0 :   if (NSTRING(node).capa != 0 &&
    1450                 :       IS_NOT_NULL(NSTRING(node).s) && NSTRING(node).s != NSTRING(node).buf) {
    1451               0 :     xfree(NSTRING(node).s);
    1452                 :   }
    1453                 : 
    1454               0 :   NSTRING(node).capa = 0;
    1455               0 :   NSTRING(node).flag = 0;
    1456               0 :   NSTRING(node).s    = NSTRING(node).buf;
    1457               0 :   NSTRING(node).end  = NSTRING(node).buf;
    1458               0 : }
    1459                 : 
    1460                 : static Node*
    1461                 : node_new_str(const UChar* s, const UChar* end)
    1462             151 : {
    1463             151 :   Node* node = node_new();
    1464             151 :   CHECK_NULL_RETURN(node);
    1465                 : 
    1466             151 :   node->type = N_STRING;
    1467             151 :   NSTRING(node).capa = 0;
    1468             151 :   NSTRING(node).flag = 0;
    1469             151 :   NSTRING(node).s    = NSTRING(node).buf;
    1470             151 :   NSTRING(node).end  = NSTRING(node).buf;
    1471             151 :   if (onig_node_str_cat(node, s, end)) {
    1472               0 :     onig_node_free(node);
    1473               0 :     return NULL;
    1474                 :   }
    1475             151 :   return node;
    1476                 : }
    1477                 : 
    1478                 : extern Node*
    1479                 : onig_node_new_str(const UChar* s, const UChar* end)
    1480               0 : {
    1481               0 :   return node_new_str(s, end);
    1482                 : }
    1483                 : 
    1484                 : static Node*
    1485                 : node_new_str_raw(UChar* s, UChar* end)
    1486               0 : {
    1487               0 :   Node* node = node_new_str(s, end);
    1488               0 :   NSTRING_SET_RAW(node);
    1489               0 :   return node;
    1490                 : }
    1491                 : 
    1492                 : static Node*
    1493                 : node_new_empty()
    1494               2 : {
    1495               2 :   return node_new_str(NULL, NULL);
    1496                 : }
    1497                 : 
    1498                 : static Node*
    1499                 : node_new_str_raw_char(UChar c)
    1500               0 : {
    1501                 :   UChar p[1];
    1502                 : 
    1503               0 :   p[0] = c;
    1504               0 :   return node_new_str_raw(p, p + 1);
    1505                 : }
    1506                 : 
    1507                 : static Node*
    1508                 : str_node_split_last_char(StrNode* sn, OnigEncoding enc)
    1509               9 : {
    1510                 :   const UChar *p;
    1511               9 :   Node* n = NULL_NODE;
    1512                 : 
    1513               9 :   if (sn->end > sn->s) {
    1514               9 :     p = onigenc_get_prev_char_head(enc, sn->s, sn->end);
    1515               9 :     if (p && p > sn->s) { /* can be splitted. */
    1516               9 :       n = node_new_str(p, sn->end);
    1517               9 :       if ((sn->flag & NSTR_RAW) != 0)
    1518               0 :         NSTRING_SET_RAW(n);
    1519               9 :       sn->end = (UChar* )p;
    1520                 :     }
    1521                 :   }
    1522               9 :   return n;
    1523                 : }
    1524                 : 
    1525                 : static int
    1526                 : str_node_can_be_split(StrNode* sn, OnigEncoding enc)
    1527              23 : {
    1528              23 :   if (sn->end > sn->s) {
    1529              23 :     return ((enc_len(enc, sn->s) < sn->end - sn->s)  ?  1 : 0);
    1530                 :   }
    1531               0 :   return 0;
    1532                 : }
    1533                 : 
    1534                 : extern int
    1535                 : onig_scan_unsigned_number(UChar** src, const UChar* end, OnigEncoding enc)
    1536               5 : {
    1537                 :   unsigned int num, val;
    1538                 :   OnigCodePoint c;
    1539               5 :   UChar* p = *src;
    1540                 :   PFETCH_READY;
    1541                 : 
    1542               5 :   num = 0;
    1543              15 :   while (!PEND) {
    1544              10 :     PFETCH(c);
    1545              10 :     if (ONIGENC_IS_CODE_DIGIT(enc, c)) {
    1546               5 :       val = (unsigned int )DIGITVAL(c);
    1547               5 :       if ((INT_MAX_LIMIT - val) / 10UL < num)
    1548               0 :         return -1;  /* overflow */
    1549                 : 
    1550               5 :       num = num * 10 + val;
    1551                 :     }
    1552                 :     else {
    1553               5 :       PUNFETCH;
    1554               5 :       break;
    1555                 :     }
    1556                 :   }
    1557               5 :   *src = p;
    1558               5 :   return num;
    1559                 : }
    1560                 : 
    1561                 : static int
    1562                 : scan_unsigned_hexadecimal_number(UChar** src, UChar* end, int maxlen,
    1563                 :                                  OnigEncoding enc)
    1564               0 : {
    1565                 :   OnigCodePoint c;
    1566                 :   unsigned int num, val;
    1567               0 :   UChar* p = *src;
    1568                 :   PFETCH_READY;
    1569                 : 
    1570               0 :   num = 0;
    1571               0 :   while (!PEND && maxlen-- != 0) {
    1572               0 :     PFETCH(c);
    1573               0 :     if (ONIGENC_IS_CODE_XDIGIT(enc, c)) {
    1574               0 :       val = (unsigned int )XDIGITVAL(enc,c);
    1575               0 :       if ((INT_MAX_LIMIT - val) / 16UL < num)
    1576               0 :         return -1;  /* overflow */
    1577                 : 
    1578               0 :       num = (num << 4) + XDIGITVAL(enc,c);
    1579                 :     }
    1580                 :     else {
    1581               0 :       PUNFETCH;
    1582               0 :       break;
    1583                 :     }
    1584                 :   }
    1585               0 :   *src = p;
    1586               0 :   return num;
    1587                 : }
    1588                 : 
    1589                 : static int
    1590                 : scan_unsigned_octal_number(UChar** src, UChar* end, int maxlen,
    1591                 :                            OnigEncoding enc)
    1592               0 : {
    1593                 :   OnigCodePoint c;
    1594                 :   unsigned int num, val;
    1595               0 :   UChar* p = *src;
    1596                 :   PFETCH_READY;
    1597                 : 
    1598               0 :   num = 0;
    1599               0 :   while (!PEND && maxlen-- != 0) {
    1600               0 :     PFETCH(c);
    1601               0 :     if (ONIGENC_IS_CODE_DIGIT(enc, c) && c < '8') {
    1602               0 :       val = ODIGITVAL(c);
    1603               0 :       if ((INT_MAX_LIMIT - val) / 8UL < num)
    1604               0 :         return -1;  /* overflow */
    1605                 : 
    1606               0 :       num = (num << 3) + val;
    1607                 :     }
    1608                 :     else {
    1609               0 :       PUNFETCH;
    1610               0 :       break;
    1611                 :     }
    1612                 :   }
    1613               0 :   *src = p;
    1614               0 :   return num;
    1615                 : }
    1616                 : 
    1617                 : 
    1618                 : #define BBUF_WRITE_CODE_POINT(bbuf,pos,code) \
    1619                 :     BBUF_WRITE(bbuf, pos, &(code), SIZE_CODE_POINT)
    1620                 : 
    1621                 : /* data format:
    1622                 :      [n][from-1][to-1][from-2][to-2] ... [from-n][to-n]
    1623                 :      (all data size is OnigCodePoint)
    1624                 :  */
    1625                 : static int
    1626                 : new_code_range(BBuf** pbuf)
    1627              42 : {
    1628                 : #define INIT_MULTI_BYTE_RANGE_SIZE  (SIZE_CODE_POINT * 5)
    1629                 :   int r;
    1630                 :   OnigCodePoint n;
    1631                 :   BBuf* bbuf;
    1632                 : 
    1633              42 :   bbuf = *pbuf = (BBuf* )xmalloc(sizeof(BBuf));
    1634              42 :   CHECK_NULL_RETURN_VAL(*pbuf, ONIGERR_MEMORY);
    1635              42 :   r = BBUF_INIT(*pbuf, INIT_MULTI_BYTE_RANGE_SIZE);
    1636              42 :   if (r) return r;
    1637                 : 
    1638              42 :   n = 0;
    1639              42 :   BBUF_WRITE_CODE_POINT(bbuf, 0, n);
    1640              42 :   return 0;
    1641                 : }
    1642                 : 
    1643                 : static int
    1644                 : add_code_range_to_buf(BBuf** pbuf, OnigCodePoint from, OnigCodePoint to)
    1645            5466 : {
    1646                 :   int r, inc_n, pos;
    1647                 :   int low, high, bound, x;
    1648                 :   OnigCodePoint n, *data;
    1649                 :   BBuf* bbuf;
    1650                 : 
    1651            5466 :   if (from > to) {
    1652               0 :     n = from; from = to; to = n;
    1653                 :   }
    1654                 : 
    1655            5466 :   if (IS_NULL(*pbuf)) {
    1656              42 :     r = new_code_range(pbuf);
    1657              42 :     if (r) return r;
    1658              42 :     bbuf = *pbuf;
    1659              42 :     n = 0;
    1660                 :   }
    1661                 :   else {
    1662            5424 :     bbuf = *pbuf;
    1663            5424 :     GET_CODE_POINT(n, bbuf->p);
    1664                 :   }
    1665            5466 :   data = (OnigCodePoint* )(bbuf->p);
    1666            5466 :   data++;
    1667                 : 
    1668           46336 :   for (low = 0, bound = n; low < bound; ) {
    1669           35404 :     x = (low + bound) >> 1;
    1670           35404 :     if (from > data[x*2 + 1])
    1671           35325 :       low = x + 1;
    1672                 :     else
    1673              79 :       bound = x;
    1674                 :   }
    1675                 : 
    1676           11052 :   for (high = low, bound = n; high < bound; ) {
    1677             120 :     x = (high + bound) >> 1;
    1678             120 :     if (to >= data[x*2] - 1)
    1679               5 :       high = x + 1;
    1680                 :     else
    1681             115 :       bound = x;
    1682                 :   }
    1683                 : 
    1684            5466 :   inc_n = low + 1 - high;
    1685            5466 :   if (n + inc_n > ONIG_MAX_MULTI_BYTE_RANGES_NUM)
    1686               0 :     return ONIGERR_TOO_MANY_MULTI_BYTE_RANGES;
    1687                 : 
    1688            5466 :   if (inc_n != 1) {
    1689               5 :     if (from > data[low*2])
    1690               0 :       from = data[low*2];
    1691               5 :     if (to < data[(high - 1)*2 + 1])
    1692               5 :       to = data[(high - 1)*2 + 1];
    1693                 :   }
    1694                 : 
    1695            5466 :   if (inc_n != 0 && (OnigCodePoint )high < n) {
    1696              17 :     int from_pos = SIZE_CODE_POINT * (1 + high * 2);
    1697              17 :     int to_pos   = SIZE_CODE_POINT * (1 + (low + 1) * 2);
    1698              17 :     int size = (n - high) * 2 * SIZE_CODE_POINT;
    1699                 : 
    1700              17 :     if (inc_n > 0) {
    1701              17 :       BBUF_MOVE_RIGHT(bbuf, from_pos, to_pos, size);
    1702                 :     }
    1703                 :     else {
    1704               0 :       BBUF_MOVE_LEFT_REDUCE(bbuf, from_pos, to_pos);
    1705                 :     }
    1706                 :   }
    1707                 : 
    1708            5466 :   pos = SIZE_CODE_POINT * (1 + low * 2);
    1709            5466 :   BBUF_ENSURE_SIZE(bbuf, pos + SIZE_CODE_POINT * 2);
    1710            5466 :   BBUF_WRITE_CODE_POINT(bbuf, pos, from);
    1711            5466 :   BBUF_WRITE_CODE_POINT(bbuf, pos + SIZE_CODE_POINT, to);
    1712            5466 :   n += inc_n;
    1713            5466 :   BBUF_WRITE_CODE_POINT(bbuf, 0, n);
    1714                 : 
    1715            5466 :   return 0;
    1716                 : }
    1717                 : 
    1718                 : static int
    1719                 : add_code_range(BBuf** pbuf, ScanEnv* env, OnigCodePoint from, OnigCodePoint to)
    1720              14 : {
    1721              14 :   if (from > to) {
    1722               0 :     if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC))
    1723               0 :       return 0;
    1724                 :     else
    1725               0 :       return ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS;
    1726                 :   }
    1727                 : 
    1728              14 :   return add_code_range_to_buf(pbuf, from, to);
    1729                 : }
    1730                 : 
    1731                 : static int
    1732                 : not_code_range_buf(OnigEncoding enc, BBuf* bbuf, BBuf** pbuf)
    1733               0 : {
    1734                 :   int r, i, n;
    1735               0 :   OnigCodePoint pre, from, *data, to = 0;
    1736                 : 
    1737               0 :   *pbuf = (BBuf* )NULL;
    1738               0 :   if (IS_NULL(bbuf)) {
    1739               0 :   set_all:
    1740               0 :     return SET_ALL_MULTI_BYTE_RANGE(enc, pbuf);
    1741                 :   }
    1742                 : 
    1743               0 :   data = (OnigCodePoint* )(bbuf->p);
    1744               0 :   GET_CODE_POINT(n, data);
    1745               0 :   data++;
    1746               0 :   if (n <= 0) goto set_all;
    1747                 : 
    1748               0 :   r = 0;
    1749               0 :   pre = MBCODE_START_POS(enc);
    1750               0 :   for (i = 0; i < n; i++) {
    1751               0 :     from = data[i*2];
    1752               0 :     to   = data[i*2+1];
    1753               0 :     if (pre <= from - 1) {
    1754               0 :       r = add_code_range_to_buf(pbuf, pre, from - 1);
    1755               0 :       if (r != 0) return r;
    1756                 :     }
    1757               0 :     if (to == ~((OnigCodePoint )0)) break;
    1758               0 :     pre = to + 1;
    1759                 :   }
    1760               0 :   if (to < ~((OnigCodePoint )0)) {
    1761               0 :     r = add_code_range_to_buf(pbuf, to + 1, ~((OnigCodePoint )0));
    1762                 :   }
    1763               0 :   return r;
    1764                 : }
    1765                 : 
    1766                 : #define SWAP_BBUF_NOT(bbuf1, not1, bbuf2, not2) do {\
    1767                 :   BBuf *tbuf; \
    1768                 :   int  tnot; \
    1769                 :   tnot = not1;  not1  = not2;  not2  = tnot; \
    1770                 :   tbuf = bbuf1; bbuf1 = bbuf2; bbuf2 = tbuf; \
    1771                 : } while (0)
    1772                 : 
    1773                 : static int
    1774                 : or_code_range_buf(OnigEncoding enc, BBuf* bbuf1, int not1,
    1775                 :                   BBuf* bbuf2, int not2, BBuf** pbuf)
    1776               0 : {
    1777                 :   int r;
    1778                 :   OnigCodePoint i, n1, *data1;
    1779                 :   OnigCodePoint from, to;
    1780                 : 
    1781               0 :   *pbuf = (BBuf* )NULL;
    1782               0 :   if (IS_NULL(bbuf1) && IS_NULL(bbuf2)) {
    1783               0 :     if (not1 != 0 || not2 != 0)
    1784               0 :       return SET_ALL_MULTI_BYTE_RANGE(enc, pbuf);
    1785               0 :     return 0;
    1786                 :   }
    1787                 : 
    1788               0 :   r = 0;
    1789               0 :   if (IS_NULL(bbuf2))
    1790               0 :     SWAP_BBUF_NOT(bbuf1, not1, bbuf2, not2);
    1791                 : 
    1792               0 :   if (IS_NULL(bbuf1)) {
    1793               0 :     if (not1 != 0) {
    1794               0 :       return SET_ALL_MULTI_BYTE_RANGE(enc, pbuf);
    1795                 :     }
    1796                 :     else {
    1797               0 :       if (not2 == 0) {
    1798               0 :         return bbuf_clone(pbuf, bbuf2);
    1799                 :       }
    1800                 :       else {
    1801               0 :         return not_code_range_buf(enc, bbuf2, pbuf);
    1802                 :       }
    1803                 :     }
    1804                 :   }
    1805                 : 
    1806               0 :   if (not1 != 0)
    1807               0 :     SWAP_BBUF_NOT(bbuf1, not1, bbuf2, not2);
    1808                 : 
    1809               0 :   data1 = (OnigCodePoint* )(bbuf1->p);
    1810               0 :   GET_CODE_POINT(n1, data1);
    1811               0 :   data1++;
    1812                 : 
    1813               0 :   if (not2 == 0 && not1 == 0) { /* 1 OR 2 */
    1814               0 :     r = bbuf_clone(pbuf, bbuf2);
    1815                 :   }
    1816               0 :   else if (not1 == 0) { /* 1 OR (not 2) */
    1817               0 :     r = not_code_range_buf(enc, bbuf2, pbuf);
    1818                 :   }
    1819               0 :   if (r != 0) return r;
    1820                 : 
    1821               0 :   for (i = 0; i < n1; i++) {
    1822               0 :     from = data1[i*2];
    1823               0 :     to   = data1[i*2+1];
    1824               0 :     r = add_code_range_to_buf(pbuf, from, to);
    1825               0 :     if (r != 0) return r;
    1826                 :   }
    1827               0 :   return 0;
    1828                 : }
    1829                 : 
    1830                 : static int
    1831                 : and_code_range1(BBuf** pbuf, OnigCodePoint from1, OnigCodePoint to1,
    1832                 :                 OnigCodePoint* data, int n)
    1833               0 : {
    1834                 :   int i, r;
    1835                 :   OnigCodePoint from2, to2;
    1836                 : 
    1837               0 :   for (i = 0; i < n; i++) {
    1838               0 :     from2 = data[i*2];
    1839               0 :     to2   = data[i*2+1];
    1840               0 :     if (from2 < from1) {
    1841               0 :       if (to2 < from1) continue;
    1842                 :       else {
    1843               0 :         from1 = to2 + 1;
    1844                 :       }
    1845                 :     }
    1846               0 :     else if (from2 <= to1) {
    1847               0 :       if (to2 < to1) {
    1848               0 :         if (from1 <= from2 - 1) {
    1849               0 :           r = add_code_range_to_buf(pbuf, from1, from2-1);
    1850               0 :           if (r != 0) return r;
    1851                 :         }
    1852               0 :         from1 = to2 + 1;
    1853                 :       }
    1854                 :       else {
    1855               0 :         to1 = from2 - 1;
    1856                 :       }
    1857                 :     }
    1858                 :     else {
    1859               0 :       from1 = from2;
    1860                 :     }
    1861               0 :     if (from1 > to1) break;
    1862                 :   }
    1863               0 :   if (from1 <= to1) {
    1864               0 :     r = add_code_range_to_buf(pbuf, from1, to1);
    1865               0 :     if (r != 0) return r;
    1866                 :   }
    1867               0 :   return 0;
    1868                 : }
    1869                 : 
    1870                 : static int
    1871                 : and_code_range_buf(BBuf* bbuf1, int not1, BBuf* bbuf2, int not2, BBuf** pbuf)
    1872               0 : {
    1873                 :   int r;
    1874                 :   OnigCodePoint i, j, n1, n2, *data1, *data2;
    1875                 :   OnigCodePoint from, to, from1, to1, from2, to2;
    1876                 : 
    1877               0 :   *pbuf = (BBuf* )NULL;
    1878               0 :   if (IS_NULL(bbuf1)) {
    1879               0 :     if (not1 != 0 && IS_NOT_NULL(bbuf2)) /* not1 != 0 -> not2 == 0 */
    1880               0 :       return bbuf_clone(pbuf, bbuf2);
    1881               0 :     return 0;
    1882                 :   }
    1883               0 :   else if (IS_NULL(bbuf2)) {
    1884               0 :     if (not2 != 0)
    1885               0 :       return bbuf_clone(pbuf, bbuf1);
    1886               0 :     return 0;
    1887                 :   }
    1888                 : 
    1889               0 :   if (not1 != 0)
    1890               0 :     SWAP_BBUF_NOT(bbuf1, not1, bbuf2, not2);
    1891                 : 
    1892               0 :   data1 = (OnigCodePoint* )(bbuf1->p);
    1893               0 :   data2 = (OnigCodePoint* )(bbuf2->p);
    1894               0 :   GET_CODE_POINT(n1, data1);
    1895               0 :   GET_CODE_POINT(n2, data2);
    1896               0 :   data1++;
    1897               0 :   data2++;
    1898                 : 
    1899               0 :   if (not2 == 0 && not1 == 0) { /* 1 AND 2 */
    1900               0 :     for (i = 0; i < n1; i++) {
    1901               0 :       from1 = data1[i*2];
    1902               0 :       to1   = data1[i*2+1];
    1903               0 :       for (j = 0; j < n2; j++) {
    1904               0 :         from2 = data2[j*2];
    1905               0 :         to2   = data2[j*2+1];
    1906               0 :         if (from2 > to1) break;
    1907               0 :         if (to2 < from1) continue;
    1908               0 :         from = MAX(from1, from2);
    1909               0 :         to   = MIN(to1, to2);
    1910               0 :         r = add_code_range_to_buf(pbuf, from, to);
    1911               0 :         if (r != 0) return r;
    1912                 :       }
    1913                 :     }
    1914                 :   }
    1915               0 :   else if (not1 == 0) { /* 1 AND (not 2) */
    1916               0 :     for (i = 0; i < n1; i++) {
    1917               0 :       from1 = data1[i*2];
    1918               0 :       to1   = data1[i*2+1];
    1919               0 :       r = and_code_range1(pbuf, from1, to1, data2, n2);
    1920               0 :       if (r != 0) return r;
    1921                 :     }
    1922                 :   }
    1923                 : 
    1924               0 :   return 0;
    1925                 : }
    1926                 : 
    1927                 : static int
    1928                 : clear_not_flag_cclass(CClassNode* cc, OnigEncoding enc)
    1929               0 : {
    1930                 :   BBuf *tbuf;
    1931                 :   int r;
    1932                 : 
    1933               0 :   if (IS_CCLASS_NOT(cc)) {
    1934               0 :     bitset_invert(cc->bs);
    1935                 : 
    1936               0 :     if (! ONIGENC_IS_SINGLEBYTE(enc)) {
    1937               0 :       r = not_code_range_buf(enc, cc->mbuf, &tbuf);
    1938               0 :       if (r != 0) return r;
    1939                 : 
    1940               0 :       bbuf_free(cc->mbuf);
    1941               0 :       cc->mbuf = tbuf;
    1942                 :     }
    1943                 : 
    1944               0 :     CCLASS_CLEAR_NOT(cc);
    1945                 :   }
    1946                 : 
    1947               0 :   return 0;
    1948                 : }
    1949                 : 
    1950                 : static int
    1951                 : and_cclass(CClassNode* dest, CClassNode* cc, OnigEncoding enc)
    1952               0 : {
    1953                 :   int r, not1, not2;
    1954                 :   BBuf *buf1, *buf2, *pbuf;
    1955                 :   BitSetRef bsr1, bsr2;
    1956                 :   BitSet bs1, bs2;
    1957                 : 
    1958               0 :   not1 = IS_CCLASS_NOT(dest);
    1959               0 :   bsr1 = dest->bs;
    1960               0 :   buf1 = dest->mbuf;
    1961               0 :   not2 = IS_CCLASS_NOT(cc);
    1962               0 :   bsr2 = cc->bs;
    1963               0 :   buf2 = cc->mbuf;
    1964                 : 
    1965               0 :   if (not1 != 0) {
    1966               0 :     bitset_invert_to(bsr1, bs1);
    1967               0 :     bsr1 = bs1;
    1968                 :   }
    1969               0 :   if (not2 != 0) {
    1970               0 :     bitset_invert_to(bsr2, bs2);
    1971               0 :     bsr2 = bs2;
    1972                 :   }
    1973               0 :   bitset_and(bsr1, bsr2);
    1974               0 :   if (bsr1 != dest->bs) {
    1975               0 :     bitset_copy(dest->bs, bsr1);
    1976               0 :     bsr1 = dest->bs;
    1977                 :   }
    1978               0 :   if (not1 != 0) {
    1979               0 :     bitset_invert(dest->bs);
    1980                 :   }
    1981                 : 
    1982               0 :   if (! ONIGENC_IS_SINGLEBYTE(enc)) {
    1983               0 :     if (not1 != 0 && not2 != 0) {
    1984               0 :       r = or_code_range_buf(enc, buf1, 0, buf2, 0, &pbuf);
    1985                 :     }
    1986                 :     else {
    1987               0 :       r = and_code_range_buf(buf1, not1, buf2, not2, &pbuf);
    1988               0 :       if (r == 0 && not1 != 0) {
    1989                 :         BBuf *tbuf;
    1990               0 :         r = not_code_range_buf(enc, pbuf, &tbuf);
    1991               0 :         if (r != 0) {
    1992               0 :           bbuf_free(pbuf);
    1993               0 :           return r;
    1994                 :         }
    1995               0 :         bbuf_free(pbuf);
    1996               0 :         pbuf = tbuf;
    1997                 :       }
    1998                 :     }
    1999               0 :     if (r != 0) return r;
    2000                 : 
    2001               0 :     dest->mbuf = pbuf;
    2002               0 :     bbuf_free(buf1);
    2003               0 :     return r;
    2004                 :   }
    2005               0 :   return 0;
    2006                 : }
    2007                 : 
    2008                 : static int
    2009                 : or_cclass(CClassNode* dest, CClassNode* cc, OnigEncoding enc)
    2010               0 : {
    2011                 :   int r, not1, not2;
    2012                 :   BBuf *buf1, *buf2, *pbuf;
    2013                 :   BitSetRef bsr1, bsr2;
    2014                 :   BitSet bs1, bs2;
    2015                 : 
    2016               0 :   not1 = IS_CCLASS_NOT(dest);
    2017               0 :   bsr1 = dest->bs;
    2018               0 :   buf1 = dest->mbuf;
    2019               0 :   not2 = IS_CCLASS_NOT(cc);
    2020               0 :   bsr2 = cc->bs;
    2021               0 :   buf2 = cc->mbuf;
    2022                 : 
    2023               0 :   if (not1 != 0) {
    2024               0 :     bitset_invert_to(bsr1, bs1);
    2025               0 :     bsr1 = bs1;
    2026                 :   }
    2027               0 :   if (not2 != 0) {
    2028               0 :     bitset_invert_to(bsr2, bs2);
    2029               0 :     bsr2 = bs2;
    2030                 :   }
    2031               0 :   bitset_or(bsr1, bsr2);
    2032               0 :   if (bsr1 != dest->bs) {
    2033               0 :     bitset_copy(dest->bs, bsr1);
    2034               0 :     bsr1 = dest->bs;
    2035                 :   }
    2036               0 :   if (not1 != 0) {
    2037               0 :     bitset_invert(dest->bs);
    2038                 :   }
    2039                 : 
    2040               0 :   if (! ONIGENC_IS_SINGLEBYTE(enc)) {
    2041               0 :     if (not1 != 0 && not2 != 0) {
    2042               0 :       r = and_code_range_buf(buf1, 0, buf2, 0, &pbuf);
    2043                 :     }
    2044                 :     else {
    2045               0 :       r = or_code_range_buf(enc, buf1, not1, buf2, not2, &pbuf);
    2046               0 :       if (r == 0 && not1 != 0) {
    2047                 :         BBuf *tbuf;
    2048               0 :         r = not_code_range_buf(enc, pbuf, &tbuf);
    2049               0 :         if (r != 0) {
    2050               0 :           bbuf_free(pbuf);
    2051               0 :           return r;
    2052                 :         }
    2053               0 :         bbuf_free(pbuf);
    2054               0 :         pbuf = tbuf;
    2055                 :       }
    2056                 :     }
    2057               0 :     if (r != 0) return r;
    2058                 : 
    2059               0 :     dest->mbuf = pbuf;
    2060               0 :     bbuf_free(buf1);
    2061               0 :     return r;
    2062                 :   }
    2063                 :   else
    2064               0 :     return 0;
    2065                 : }
    2066                 : 
    2067                 : static int
    2068                 : conv_backslash_value(int c, ScanEnv* env)
    2069               5 : {
    2070               5 :   if (IS_SYNTAX_OP(env->syntax, ONIG_SYN_OP_ESC_CONTROL_CHARS)) {
    2071               5 :     switch (c) {
    2072               0 :     case 'n':  return '\n';
    2073               0 :     case 't':  return '\t';
    2074               0 :     case 'r':  return '\r';
    2075               0 :     case 'f':  return '\f';
    2076               0 :     case 'a':  return '\007';
    2077               0 :     case 'b':  return '\010';
    2078               0 :     case 'e':  return '\033';
    2079                 :     case 'v':
    2080               0 :       if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_ESC_V_VTAB))
    2081               0 :         return '\v';
    2082                 :       break;
    2083                 : 
    2084                 :     default:
    2085                 :       break;
    2086                 :     }
    2087                 :   }
    2088               5 :   return c;
    2089                 : }
    2090                 : 
    2091                 : static int
    2092                 : is_invalid_qualifier_target(Node* node)
    2093             126 : {
    2094             126 :   switch (NTYPE(node)) {
    2095                 :   case N_ANCHOR:
    2096               0 :     return 1;
    2097                 :     break;
    2098                 : 
    2099                 :   case N_EFFECT:
    2100               5 :     if (NEFFECT(node).type == EFFECT_OPTION)
    2101               0 :       return is_invalid_qualifier_target(NEFFECT(node).target);
    2102               5 :     break;
    2103                 : 
    2104                 :   case N_LIST: /* ex. (?:\G\A)* */
    2105                 :     do {
    2106               0 :       if (! is_invalid_qualifier_target(NCONS(node).left)) return 0;
    2107               0 :     } while (IS_NOT_NULL(node = NCONS(node).right));
    2108               0 :     return 0;
    2109                 :     break;
    2110                 : 
    2111                 :   case N_ALT:  /* ex. (?:abc|\A)* */
    2112                 :     do {
    2113               0 :       if (is_invalid_qualifier_target(NCONS(node).left)) return 1;
    2114               0 :     } while (IS_NOT_NULL(node = NCONS(node).right));
    2115                 :     break;
    2116                 : 
    2117                 :   default:
    2118                 :     break;
    2119                 :   }
    2120             126 :   return 0;
    2121                 : }
    2122                 : 
    2123                 : /* ?:0, *:1, +:2, ??:3, *?:4, +?:5 */
    2124                 : static int
    2125                 : popular_qualifier_num(QualifierNode* qf)
    2126               0 : {
    2127               0 :   if (qf->greedy) {
    2128               0 :     if (qf->lower == 0) {
    2129               0 :       if (qf->upper == 1) return 0;
    2130               0 :       else if (IS_REPEAT_INFINITE(qf->upper)) return 1;
    2131                 :     }
    2132               0 :     else if (qf->lower == 1) {
    2133               0 :       if (IS_REPEAT_INFINITE(qf->upper)) return 2;
    2134                 :     }
    2135                 :   }
    2136                 :   else {
    2137               0 :     if (qf->lower == 0) {
    2138               0 :       if (qf->upper == 1) return 3;
    2139               0 :       else if (IS_REPEAT_INFINITE(qf->upper)) return 4;
    2140                 :     }
    2141               0 :     else if (qf->lower == 1) {
    2142               0 :       if (IS_REPEAT_INFINITE(qf->upper)) return 5;
    2143                 :     }
    2144                 :   }
    2145               0 :   return -1;
    2146                 : }
    2147                 : 
    2148                 : 
    2149                 : enum ReduceType {
    2150                 :   RQ_ASIS = 0, /* as is */
    2151                 :   RQ_DEL  = 1, /* delete parent */
    2152                 :   RQ_A,        /* to '*'    */
    2153                 :   RQ_AQ,       /* to '*?'   */
    2154                 :   RQ_QQ,       /* to '??'   */
    2155                 :   RQ_P_QQ,     /* to '+)??' */
    2156                 :   RQ_PQ_Q      /* to '+?)?' */
    2157                 : };
    2158                 : 
    2159                 : static enum ReduceType ReduceTypeTable[6][6] = {
    2160                 :   {RQ_DEL,  RQ_A,    RQ_A,   RQ_QQ,   RQ_AQ,   RQ_ASIS}, /* '?'  */
    2161                 :   {RQ_DEL,  RQ_DEL,  RQ_DEL, RQ_P_QQ, RQ_P_QQ, RQ_DEL},  /* '*'  */
    2162                 :   {RQ_A,    RQ_A,    RQ_DEL, RQ_ASIS, RQ_P_QQ, RQ_DEL},  /* '+'  */
    2163                 :   {RQ_DEL,  RQ_AQ,   RQ_AQ,  RQ_DEL,  RQ_AQ,   RQ_AQ},   /* '??' */
    2164                 :   {RQ_DEL,  RQ_DEL,  RQ_DEL, RQ_DEL,  RQ_DEL,  RQ_DEL},  /* '*?' */
    2165                 :   {RQ_ASIS, RQ_PQ_Q, RQ_DEL, RQ_AQ,   RQ_AQ,   RQ_DEL}   /* '+?' */
    2166                 : };
    2167                 : 
    2168                 : extern void
    2169                 : onig_reduce_nested_qualifier(Node* pnode, Node* cnode)
    2170               0 : {
    2171                 :   int pnum, cnum;
    2172                 :   QualifierNode *p, *c;
    2173                 : 
    2174               0 :   p = &(NQUALIFIER(pnode));
    2175               0 :   c = &(NQUALIFIER(cnode));
    2176               0 :   pnum = popular_qualifier_num(p);
    2177               0 :   cnum = popular_qualifier_num(c);
    2178                 : 
    2179               0 :   switch(ReduceTypeTable[cnum][pnum]) {
    2180                 :   case RQ_DEL:
    2181               0 :     *p = *c;
    2182               0 :     break;
    2183                 :   case RQ_A:
    2184               0 :     p->target = c->target;
    2185               0 :     p->lower  = 0;  p->upper = REPEAT_INFINITE;  p->greedy = 1;
    2186               0 :     break;
    2187                 :   case RQ_AQ:
    2188               0 :     p->target = c->target;
    2189               0 :     p->lower  = 0;  p->upper = REPEAT_INFINITE;  p->greedy = 0;
    2190               0 :     break;
    2191                 :   case RQ_QQ:
    2192               0 :     p->target = c->target;
    2193               0 :     p->lower  = 0;  p->upper = 1;  p->greedy = 0;
    2194               0 :     break;
    2195                 :   case RQ_P_QQ:
    2196               0 :     p->target = cnode;
    2197               0 :     p->lower  = 0;  p->upper = 1;  p->greedy = 0;
    2198               0 :     c->lower  = 1;  c->upper = REPEAT_INFINITE;  c->greedy = 1;
    2199               0 :     return ;
    2200                 :     break;
    2201                 :   case RQ_PQ_Q:
    2202               0 :     p->target = cnode;
    2203               0 :     p->lower  = 0;  p->upper = 1;  p->greedy = 1;
    2204               0 :     c->lower  = 1;  c->upper = REPEAT_INFINITE;  c->greedy = 0;
    2205               0 :     return ;
    2206                 :     break;
    2207                 :   case RQ_ASIS:
    2208               0 :     p->target = cnode;
    2209               0 :     return ;
    2210                 :     break;
    2211                 :   }
    2212                 : 
    2213               0 :   c->target = NULL_NODE;
    2214               0 :   onig_node_free(cnode);
    2215                 : }
    2216                 : 
    2217                 : 
    2218                 : enum TokenSyms {
    2219                 :   TK_EOT      = 0,   /* end of token */
    2220                 :   TK_RAW_BYTE = 1,
    2221                 :   TK_CHAR,
    2222                 :   TK_STRING,
    2223                 :   TK_CODE_POINT,
    2224                 :   TK_ANYCHAR,
    2225                 :   TK_CHAR_TYPE,
    2226                 :   TK_BACKREF,
    2227                 :   TK_CALL,
    2228                 :   TK_ANCHOR,
    2229                 :   TK_OP_REPEAT,
    2230                 :   TK_INTERVAL,
    2231                 :   TK_ANYCHAR_ANYTIME,  /* SQL '%' == .* */
    2232                 :   TK_ALT,
    2233                 :   TK_SUBEXP_OPEN,
    2234                 :   TK_SUBEXP_CLOSE,
    2235                 :   TK_CC_OPEN,
    2236                 :   TK_QUOTE_OPEN,
    2237                 :   TK_CHAR_PROPERTY,    /* \p{...}, \P{...} */
    2238                 :   /* in cc */
    2239                 :   TK_CC_CLOSE,
    2240                 :   TK_CC_RANGE,
    2241                 :   TK_POSIX_BRACKET_OPEN,
    2242                 :   TK_CC_AND,             /* && */
    2243                 :   TK_CC_CC_OPEN          /* [ */
    2244                 : };
    2245                 : 
    2246                 : typedef struct {
    2247                 :   enum TokenSyms type;
    2248                 :   int escaped;
    2249                 :   int base;   /* is number: 8, 16 (used in [....]) */
    2250                 :   UChar* backp;
    2251                 :   union {
    2252                 :     UChar* s;
    2253                 :     int   c;
    2254                 :     OnigCodePoint code;
    2255                 :     int   anchor;
    2256                 :     int   subtype;
    2257                 :     struct {
    2258                 :       int lower;
    2259                 :       int upper;
    2260                 :       int greedy;
    2261                 :       int possessive;
    2262                 :     } repeat;
    2263                 :     struct {
    2264                 :       int  num;
    2265                 :       int  ref1;
    2266                 :       int* refs;
    2267                 :       int  by_name;
    2268                 : #ifdef USE_BACKREF_AT_LEVEL
    2269                 :       int  exist_level;
    2270                 :       int  level;   /* \k<name+n> */
    2271                 : #endif
    2272                 :     } backref;
    2273                 :     struct {
    2274                 :       UChar* name;
    2275                 :       UChar* name_end;
    2276                 :     } call;
    2277                 :     struct {
    2278                 :       int not;
    2279                 :     } prop;
    2280                 :   } u;
    2281                 : } OnigToken;
    2282                 : 
    2283                 : 
    2284                 : static int
    2285                 : fetch_range_qualifier(UChar** src, UChar* end, OnigToken* tok, ScanEnv* env)
    2286               4 : {
    2287               4 :   int low, up, syn_allow, non_low = 0;
    2288               4 :   int r = 0;
    2289                 :   OnigCodePoint c;
    2290               4 :   OnigEncoding enc = env->enc;
    2291               4 :   UChar* p = *src;
    2292                 :   PFETCH_READY;
    2293                 : 
    2294               4 :   syn_allow = IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_INVALID_INTERVAL);
    2295                 : 
    2296               4 :   if (PEND) {
    2297               0 :     if (syn_allow)
    2298               0 :       return 1;  /* "....{" : OK! */
    2299                 :     else
    2300               0 :       return ONIGERR_END_PATTERN_AT_LEFT_BRACE;  /* "....{" syntax error */
    2301                 :   }
    2302                 : 
    2303               4 :   if (! syn_allow) {
    2304               0 :     c = PPEEK;
    2305               0 :     if (c == ')' || c == '(' || c == '|') {
    2306               0 :       return ONIGERR_END_PATTERN_AT_LEFT_BRACE;
    2307                 :     }
    2308                 :   }
    2309                 : 
    2310               4 :   low = onig_scan_unsigned_number(&p, end, env->enc);
    2311               4 :   if (low < 0) return ONIGERR_TOO_BIG_NUMBER_FOR_REPEAT_RANGE;
    2312               4 :   if (low > ONIG_MAX_REPEAT_NUM)
    2313               0 :     return ONIGERR_TOO_BIG_NUMBER_FOR_REPEAT_RANGE;
    2314                 : 
    2315               4 :   if (p == *src) { /* can't read low */
    2316               0 :     if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_INTERVAL_LOW_ABBREV)) {
    2317                 :       /* allow {,n} as {0,n} */
    2318               0 :       low = 0;
    2319               0 :       non_low = 1;
    2320                 :     }
    2321                 :     else
    2322               0 :       goto invalid;
    2323                 :   }
    2324                 : 
    2325               4 :   if (PEND) goto invalid;
    2326               4 :   PFETCH(c);
    2327               4 :   if (c == ',') {
    2328               1 :     UChar* prev = p;
    2329               1 :     up = onig_scan_unsigned_number(&p, end, env->enc);
    2330               1 :     if (up < 0) return ONIGERR_TOO_BIG_NUMBER_FOR_REPEAT_RANGE;
    2331               1 :     if (up > ONIG_MAX_REPEAT_NUM)
    2332               0 :       return ONIGERR_TOO_BIG_NUMBER_FOR_REPEAT_RANGE;
    2333                 : 
    2334               1 :     if (p == prev) {
    2335               0 :       if (non_low != 0)
    2336               0 :         goto invalid;
    2337               0 :       up = REPEAT_INFINITE;  /* {n,} : {n,infinite} */
    2338                 :     }
    2339                 :   }
    2340                 :   else {
    2341               3 :     if (non_low != 0)
    2342               0 :       goto invalid;
    2343                 : 
    2344               3 :     PUNFETCH;
    2345               3 :     up = low;  /* {n} : exact n times */
    2346               3 :     r = 2;     /* fixed */
    2347                 :   }
    2348                 : 
    2349               4 :   if (PEND) goto invalid;
    2350               4 :   PFETCH(c);
    2351               4 :   if (IS_SYNTAX_OP(env->syntax, ONIG_SYN_OP_ESC_BRACE_INTERVAL)) {
    2352               0 :     if (c != MC_ESC(enc)) goto invalid;
    2353               0 :     PFETCH(c);
    2354                 :   }
    2355               4 :   if (c != '}') goto invalid;
    2356                 : 
    2357               4 :   if (!IS_REPEAT_INFINITE(up) && low > up) {
    2358               0 :     return ONIGERR_UPPER_SMALLER_THAN_LOWER_IN_REPEAT_RANGE;
    2359                 :   }
    2360                 : 
    2361               4 :   tok->type = TK_INTERVAL;
    2362               4 :   tok->u.repeat.lower = low;
    2363               4 :   tok->u.repeat.upper = up;
    2364               4 :   *src = p;
    2365               4 :   return r; /* 0: normal {n,m}, 2: fixed {n} */
    2366                 : 
    2367               0 :  invalid:
    2368               0 :   if (syn_allow)
    2369               0 :     return 1;  /* OK */
    2370                 :   else
    2371               0 :     return ONIGERR_INVALID_REPEAT_RANGE_PATTERN;
    2372                 : }
    2373                 : 
    2374                 : /* \M-, \C-, \c, or \... */
    2375                 : static int
    2376                 : fetch_escaped_value(UChar** src, UChar* end, ScanEnv* env)
    2377               5 : {
    2378                 :   int v;
    2379                 :   OnigCodePoint c;
    2380               5 :   OnigEncoding enc = env->enc;
    2381               5 :   UChar* p = *src;
    2382                 :   PFETCH_READY;
    2383                 : 
    2384               5 :   if (PEND) return ONIGERR_END_PATTERN_AT_ESCAPE;
    2385                 : 
    2386               5 :   PFETCH(c);
    2387               5 :   switch (c) {
    2388                 :   case 'M':
    2389               0 :     if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_ESC_CAPITAL_M_BAR_META)) {
    2390               0 :       if (PEND) return ONIGERR_END_PATTERN_AT_META;
    2391               0 :       PFETCH(c);
    2392               0 :       if (c != '-') return ONIGERR_META_CODE_SYNTAX;
    2393               0 :       if (PEND) return ONIGERR_END_PATTERN_AT_META;
    2394               0 :       PFETCH(c);
    2395               0 :       if (c == MC_ESC(enc)) {
    2396               0 :         v = fetch_escaped_value(&p, end, env);
    2397               0 :         if (v < 0) return v;
    2398               0 :         c = (OnigCodePoint )v;
    2399                 :       }
    2400               0 :       c = ((c & 0xff) | 0x80);
    2401                 :     }
    2402                 :     else
    2403               0 :       goto backslash;
    2404               0 :     break;
    2405                 : 
    2406                 :   case 'C':
    2407               0 :     if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_ESC_CAPITAL_C_BAR_CONTROL)) {
    2408               0 :       if (PEND) return ONIGERR_END_PATTERN_AT_CONTROL;
    2409               0 :       PFETCH(c);
    2410               0 :       if (c != '-') return ONIGERR_CONTROL_CODE_SYNTAX;
    2411               0 :       goto control;
    2412                 :     }
    2413                 :     else
    2414               0 :       goto backslash;
    2415                 : 
    2416                 :   case 'c':
    2417               0 :     if (IS_SYNTAX_OP(env->syntax, ONIG_SYN_OP_ESC_C_CONTROL)) {
    2418               0 :     control:
    2419               0 :       if (PEND) return ONIGERR_END_PATTERN_AT_CONTROL;
    2420               0 :       PFETCH(c);
    2421               0 :       if (c == '?') {
    2422               0 :         c = 0177;
    2423                 :       }
    2424                 :       else {
    2425               0 :         if (c == MC_ESC(enc)) {
    2426               0 :           v = fetch_escaped_value(&p, end, env);
    2427               0 :           if (v < 0) return v;
    2428               0 :           c = (OnigCodePoint )v;
    2429                 :         }
    2430               0 :         c &= 0x9f;
    2431                 :       }
    2432               0 :       break;
    2433                 :     }
    2434                 :     /* fall through */
    2435                 : 
    2436                 :   default:
    2437                 :     {
    2438               5 :     backslash:
    2439               5 :       c = conv_backslash_value(c, env);
    2440                 :     }
    2441                 :     break;
    2442                 :   }
    2443                 : 
    2444               5 :   *src = p;
    2445               5 :   return c;
    2446                 : }
    2447                 : 
    2448                 : static int fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env);
    2449                 : 
    2450                 : #ifdef USE_NAMED_GROUP
    2451                 : #ifdef USE_BACKREF_AT_LEVEL
    2452                 : /*
    2453                 :    \k<name+n>, \k<name-n>
    2454                 : */
    2455                 : static int
    2456                 : fetch_name_with_level(UChar** src, UChar* end, UChar** rname_end
    2457                 :                       , ScanEnv* env, int* level)
    2458               0 : {
    2459               0 :   int r, exist_level = 0;
    2460               0 :   OnigCodePoint c = 0;
    2461                 :   OnigCodePoint first_code;
    2462               0 :   OnigEncoding enc = env->enc;
    2463                 :   UChar *name_end;
    2464               0 :   UChar *p = *src;
    2465                 :   PFETCH_READY;
    2466                 : 
    2467               0 :   name_end = end;
    2468               0 :   r = 0;
    2469               0 :   if (PEND) {
    2470               0 :     return ONIGERR_EMPTY_GROUP_NAME;
    2471                 :   }
    2472                 :   else {
    2473               0 :     PFETCH(c);
    2474               0 :     first_code = c;
    2475               0 :     if (c == '>')
    2476               0 :       return ONIGERR_EMPTY_GROUP_NAME;
    2477                 : 
    2478               0 :     if (!ONIGENC_IS_CODE_WORD(enc, c)) {
    2479               0 :       r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
    2480                 :     }
    2481                 :   }
    2482                 : 
    2483               0 :   while (!PEND) {
    2484               0 :     name_end = p;
    2485               0 :     PFETCH(c);
    2486               0 :     if (c == '>' || c == ')' || c == '+' || c == '-') break;
    2487                 : 
    2488               0 :     if (!ONIGENC_IS_CODE_WORD(enc, c)) {
    2489               0 :       r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
    2490                 :     }
    2491                 :   }
    2492                 : 
    2493               0 :   if (c != '>') {
    2494               0 :     if (c == '+' || c == '-') {
    2495                 :       int num;
    2496               0 :       int flag = (c == '-' ? -1 : 1);
    2497                 : 
    2498               0 :       PFETCH(c);
    2499               0 :       if (! ONIGENC_IS_CODE_DIGIT(enc, c)) goto err;
    2500               0 :       PUNFETCH;
    2501               0 :       num = onig_scan_unsigned_number(&p, end, enc);
    2502               0 :       if (num < 0) return ONIGERR_TOO_BIG_NUMBER;
    2503               0 :       *level = (num * flag);
    2504               0 :       exist_level = 1;
    2505                 : 
    2506               0 :       PFETCH(c);
    2507               0 :       if (c == '>')
    2508               0 :         goto first_check;
    2509                 :     }
    2510                 : 
    2511               0 :   err:
    2512               0 :     r = ONIGERR_INVALID_GROUP_NAME;
    2513               0 :     name_end = end;
    2514                 :   }
    2515                 :   else {
    2516               0 :   first_check:
    2517               0 :     if (ONIGENC_IS_CODE_ASCII(first_code) &&
    2518                 :         ONIGENC_IS_CODE_UPPER(enc, first_code))
    2519               0 :       r = ONIGERR_INVALID_GROUP_NAME;
    2520                 :   }
    2521                 : 
    2522               0 :   if (r == 0) {
    2523               0 :     *rname_end = name_end;
    2524               0 :     *src = p;
    2525               0 :     return (exist_level ? 1 : 0);
    2526                 :   }
    2527                 :   else {
    2528               0 :     onig_scan_env_set_error_string(env, r, *src, name_end);
    2529               0 :     return r;
    2530                 :   }
    2531                 : }
    2532                 : #endif /* USE_BACKREF_AT_LEVEL */
    2533                 : 
    2534                 : /*
    2535                 :   def: 0 -> define name    (don't allow number name)
    2536                 :        1 -> reference name (allow number name)
    2537                 : */
    2538                 : static int
    2539                 : fetch_name(UChar** src, UChar* end, UChar** rname_end, ScanEnv* env, int ref)
    2540               0 : {
    2541                 :   int r, is_num;
    2542               0 :   OnigCodePoint c = 0;
    2543                 :   OnigCodePoint first_code;
    2544               0 :   OnigEncoding enc = env->enc;
    2545                 :   UChar *name_end;
    2546               0 :   UChar *p = *src;
    2547                 :   PFETCH_READY;
    2548                 : 
    2549               0 :   name_end = end;
    2550               0 :   r = 0;
    2551               0 :   is_num = 0;
    2552               0 :   if (PEND) {
    2553               0 :     return ONIGERR_EMPTY_GROUP_NAME;
    2554                 :   }
    2555                 :   else {
    2556               0 :     PFETCH(c);
    2557               0 :     first_code = c;
    2558               0 :     if (c == '>')
    2559               0 :       return ONIGERR_EMPTY_GROUP_NAME;
    2560                 : 
    2561               0 :     if (ONIGENC_IS_CODE_DIGIT(enc, c)) {
    2562               0 :       if (ref == 1)
    2563               0 :         is_num = 1;
    2564                 :       else {
    2565               0 :         r = ONIGERR_INVALID_GROUP_NAME;
    2566                 :       }
    2567                 :     }
    2568               0 :     else if (!ONIGENC_IS_CODE_WORD(enc, c)) {
    2569               0 :       r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
    2570                 :     }
    2571                 :   }
    2572                 : 
    2573               0 :   while (!PEND) {
    2574               0 :     name_end = p;
    2575               0 :     PFETCH(c);
    2576               0 :     if (c == '>' || c == ')') break;
    2577                 : 
    2578               0 :     if (is_num == 1) {
    2579               0 :       if (! ONIGENC_IS_CODE_DIGIT(enc, c)) {
    2580               0 :         if (!ONIGENC_IS_CODE_WORD(enc, c))
    2581               0 :           r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
    2582                 :         else
    2583               0 :           r = ONIGERR_INVALID_GROUP_NAME;
    2584                 :       }
    2585                 :     }
    2586                 :     else {
    2587               0 :       if (!ONIGENC_IS_CODE_WORD(enc, c)) {
    2588               0 :         r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
    2589                 :       }
    2590                 :     }
    2591                 :   }
    2592                 : 
    2593               0 :   if (c != '>') {
    2594               0 :     r = ONIGERR_INVALID_GROUP_NAME;
    2595               0 :     name_end = end;
    2596                 :   }
    2597                 :   else {
    2598               0 :     if (ONIGENC_IS_CODE_ASCII(first_code) &&
    2599                 :         ONIGENC_IS_CODE_UPPER(enc, first_code))
    2600               0 :       r = ONIGERR_INVALID_GROUP_NAME;
    2601                 :   }
    2602                 : 
    2603               0 :   if (r == 0) {
    2604               0 :     *rname_end = name_end;
    2605               0 :     *src = p;
    2606               0 :     return 0;
    2607                 :   }
    2608                 :   else {
    2609               0 :     onig_scan_env_set_error_string(env, r, *src, name_end);
    2610               0 :     return r;
    2611                 :   }
    2612                 : }
    2613                 : #else
    2614                 : static int
    2615                 : fetch_name(UChar** src, UChar* end, UChar** rname_end, ScanEnv* env, int ref)
    2616                 : {
    2617                 :   int r, len;
    2618                 :   OnigCodePoint c = 0;
    2619                 :   UChar *name_end;
    2620                 :   OnigEncoding enc = env->enc;
    2621                 :   UChar *p = *src;
    2622                 :   PFETCH_READY;
    2623                 : 
    2624                 :   r = 0;
    2625                 :   while (!PEND) {
    2626                 :     name_end = p;
    2627                 :     if (enc_len(enc, p) > 1)
    2628                 :       r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
    2629                 : 
    2630                 :     PFETCH(c);
    2631                 :     if (c == '>' || c == ')') break;
    2632                 :     if (! ONIGENC_IS_CODE_DIGIT(enc, c))
    2633                 :       r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
    2634                 :   }
    2635                 :   if (c != '>') {
    2636                 :     r = ONIGERR_INVALID_GROUP_NAME;
    2637                 :     name_end = end;
    2638                 :   }
    2639                 : 
    2640                 :   if (r == 0) {
    2641                 :     *rname_end = name_end;
    2642                 :     *src = p;
    2643                 :     return 0;
    2644                 :   }
    2645                 :   else {
    2646                 :   err:
    2647                 :     onig_scan_env_set_error_string(env, r, *src, name_end);
    2648                 :     return r;
    2649                 :   }
    2650                 : }
    2651                 : #endif
    2652                 : 
    2653                 : static void
    2654                 : CC_ESC_WARN(ScanEnv* env, UChar *c)
    2655               0 : {
    2656               0 :   if (onig_warn == onig_null_warn) return ;
    2657                 : 
    2658               0 :   if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_WARN_CC_OP_NOT_ESCAPED) &&
    2659                 :       IS_SYNTAX_BV(env->syntax, ONIG_SYN_BACKSLASH_ESCAPE_IN_CC)) {
    2660                 :     UChar buf[WARN_BUFSIZE];
    2661               0 :     onig_snprintf_with_pattern(buf, WARN_BUFSIZE, env->enc,
    2662                 :                 env->pattern, env->pattern_end,
    2663                 :                 (UChar* )"character class has '%s' without escape", c);
    2664               0 :     (*onig_warn)((char* )buf);
    2665                 :   }
    2666                 : }
    2667                 : 
    2668                 : static void
    2669                 : CCEND_ESC_WARN(ScanEnv* env, UChar* c)
    2670               0 : {
    2671               0 :   if (onig_warn == onig_null_warn) return ;
    2672                 : 
    2673               0 :   if (IS_SYNTAX_BV((env)->syntax, ONIG_SYN_WARN_CC_OP_NOT_ESCAPED)) {
    2674                 :     UChar buf[WARN_BUFSIZE];
    2675               0 :     onig_snprintf_with_pattern(buf, WARN_BUFSIZE, (env)->enc,
    2676                 :                 (env)->pattern, (env)->pattern_end,
    2677                 :                 (UChar* )"regular expression has '%s' without escape", c);
    2678               0 :     (*onig_warn)((char* )buf);
    2679                 :   }
    2680                 : }
    2681                 : 
    2682                 : static UChar*
    2683                 : find_str_position(OnigCodePoint s[], int n, UChar* from, UChar* to,
    2684                 :                   UChar **next, OnigEncoding enc)
    2685               0 : {
    2686                 :   int i;
    2687                 :   OnigCodePoint x;
    2688                 :   UChar *q;
    2689               0 :   UChar *p = from;
    2690                 :   
    2691               0 :   while (p < to) {
    2692               0 :     x = ONIGENC_MBC_TO_CODE(enc, p, to);
    2693               0 :     q = p + enc_len(enc, p);
    2694               0 :     if (x == s[0]) {
    2695               0 :       for (i = 1; i < n && q < to; i++) {
    2696               0 :         x = ONIGENC_MBC_TO_CODE(enc, q, to);
    2697               0 :         if (x != s[i]) break;
    2698               0 :         q += enc_len(enc, q);
    2699                 :       }
    2700               0 :       if (i >= n) {
    2701               0 :         if (IS_NOT_NULL(next))
    2702               0 :           *next = q;
    2703               0 :         return p;
    2704                 :       }
    2705                 :     }
    2706               0 :     p = q;
    2707                 :   }
    2708               0 :   return NULL_UCHARP;
    2709                 : }
    2710                 : 
    2711                 : static int
    2712                 : str_exist_check_with_esc(OnigCodePoint s[], int n, UChar* from, UChar* to,
    2713                 :                          OnigCodePoint bad, OnigEncoding enc)
    2714              41 : {
    2715                 :   int i, in_esc;
    2716                 :   OnigCodePoint x;
    2717                 :   UChar *q;
    2718              41 :   UChar *p = from;
    2719                 : 
    2720              41 :   in_esc = 0;
    2721             289 :   while (p < to) {
    2722             248 :     if (in_esc) {
    2723               0 :       in_esc = 0;
    2724               0 :       p += enc_len(enc, p);
    2725                 :     }
    2726                 :     else {
    2727             248 :       x = ONIGENC_MBC_TO_CODE(enc, p, to);
    2728             248 :       q = p + enc_len(enc, p);
    2729             248 :       if (x == s[0]) {
    2730              82 :         for (i = 1; i < n && q < to; i++) {
    2731              41 :           x = ONIGENC_MBC_TO_CODE(enc, q, to);
    2732              41 :           if (x != s[i]) break;
    2733              41 :           q += enc_len(enc, q);
    2734                 :         }
    2735              41 :         if (i >= n) return 1;
    2736               0 :         p += enc_len(enc, p);
    2737                 :       }
    2738                 :       else {
    2739             207 :         x = ONIGENC_MBC_TO_CODE(enc, p, to);
    2740             207 :         if (x == bad) return 0;
    2741             207 :         else if (x == MC_ESC(enc)) in_esc = 1;
    2742             207 :         p = q;
    2743                 :       }
    2744                 :     }
    2745                 :   }
    2746               0 :   return 0;
    2747                 : }
    2748                 : 
    2749                 : static int
    2750                 : fetch_token_in_cc(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
    2751             298 : {
    2752                 :   int num;
    2753                 :   OnigCodePoint c, c2;
    2754             298 :   OnigSyntaxType* syn = env->syntax;
    2755             298 :   OnigEncoding enc = env->enc;
    2756                 :   UChar* prev;
    2757             298 :   UChar* p = *src;
    2758                 :   PFETCH_READY;
    2759                 : 
    2760             298 :   if (PEND) {
    2761               0 :     tok->type = TK_EOT;
    2762               0 :     return tok->type;
    2763                 :   }
    2764                 : 
    2765             298 :   PFETCH(c);
    2766             298 :   tok->type = TK_CHAR;
    2767             298 :   tok->base = 0;
    2768             298 :   tok->u.c  = c;
    2769             298 :   tok->escaped = 0;
    2770                 : 
    2771             298 :   if (c == ']') {
    2772              93 :     tok->type = TK_CC_CLOSE;
    2773                 :   }
    2774             205 :   else if (c == '-') {
    2775              49 :     tok->type = TK_CC_RANGE;
    2776                 :   }
    2777             156 :   else if (c == MC_ESC(enc)) {
    2778               1 :     if (! IS_SYNTAX_BV(syn, ONIG_SYN_BACKSLASH_ESCAPE_IN_CC))
    2779               0 :       goto end;
    2780                 : 
    2781               1 :     if (PEND) return ONIGERR_END_PATTERN_AT_ESCAPE;
    2782                 : 
    2783               1 :     PFETCH(c);
    2784               1 :     tok->escaped = 1;
    2785               1 :     tok->u.c = c;
    2786               1 :     switch (c) {
    2787                 :     case 'w':
    2788               0 :       tok->type = TK_CHAR_TYPE;
    2789               0 :       tok->u.subtype = CTYPE_WORD;
    2790               0 :       break;
    2791                 :     case 'W':
    2792               0 :       tok->type = TK_CHAR_TYPE;
    2793               0 :       tok->u.subtype = CTYPE_NOT_WORD;
    2794               0 :       break;
    2795                 :     case 'd':
    2796               0 :       tok->type = TK_CHAR_TYPE;
    2797               0 :       tok->u.subtype = CTYPE_DIGIT;
    2798               0 :       break;
    2799                 :     case 'D':
    2800               0 :       tok->type = TK_CHAR_TYPE;
    2801               0 :       tok->u.subtype = CTYPE_NOT_DIGIT;
    2802               0 :       break;
    2803                 :     case 's':
    2804               1 :       tok->type = TK_CHAR_TYPE;
    2805               1 :       tok->u.subtype = CTYPE_WHITE_SPACE;
    2806               1 :       break;
    2807                 :     case 'S':
    2808               0 :       tok->type = TK_CHAR_TYPE;
    2809               0 :       tok->u.subtype = CTYPE_NOT_WHITE_SPACE;
    2810               0 :       break;
    2811                 :     case 'h':
    2812               0 :       if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_H_XDIGIT)) break;
    2813               0 :       tok->type = TK_CHAR_TYPE;
    2814               0 :       tok->u.subtype = CTYPE_XDIGIT;
    2815               0 :       break;
    2816                 :     case 'H':
    2817               0 :       if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_H_XDIGIT)) break;
    2818               0 :       tok->type = TK_CHAR_TYPE;
    2819               0 :       tok->u.subtype = CTYPE_NOT_XDIGIT;
    2820               0 :       break;
    2821                 : 
    2822                 :     case 'p':
    2823                 :     case 'P':
    2824               0 :       c2 = PPEEK;
    2825               0 :       if (c2 == '{' &&
    2826                 :           IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY)) {
    2827               0 :         PINC;
    2828               0 :         tok->type = TK_CHAR_PROPERTY;
    2829               0 :         tok->u.prop.not = (c == 'P' ? 1 : 0);
    2830                 : 
    2831               0 :         if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT)) {
    2832               0 :           PFETCH(c2);
    2833               0 :           if (c2 == '^') {
    2834               0 :             tok->u.prop.not = (tok->u.prop.not == 0 ? 1 : 0);
    2835                 :           }
    2836                 :           else
    2837               0 :             PUNFETCH;
    2838                 :         }
    2839                 :       }
    2840               0 :       break;
    2841                 : 
    2842                 :     case 'x':
    2843               0 :       if (PEND) break;
    2844                 : 
    2845               0 :       prev = p;
    2846               0 :       if (PPEEK_IS('{') && IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_X_BRACE_HEX8)) {
    2847               0 :         PINC;
    2848               0 :         num = scan_unsigned_hexadecimal_number(&p, end, 8, enc);
    2849               0 :         if (num < 0) return ONIGERR_TOO_BIG_WIDE_CHAR_VALUE;
    2850               0 :         if (!PEND) {
    2851               0 :           c2 = PPEEK;
    2852               0 :           if (ONIGENC_IS_CODE_XDIGIT(enc, c2))
    2853               0 :             return ONIGERR_TOO_LONG_WIDE_CHAR_VALUE;
    2854                 :         }
    2855                 : 
    2856               0 :         if (p > prev + enc_len(enc, prev) && !PEND && (PPEEK_IS('}'))) {
    2857               0 :           PINC;
    2858               0 :           tok->type   = TK_CODE_POINT;
    2859               0 :           tok->base   = 16;
    2860               0 :           tok->u.code = (OnigCodePoint )num;
    2861                 :         }
    2862                 :         else {
    2863                 :           /* can't read nothing or invalid format */
    2864               0 :           p = prev;
    2865                 :         }
    2866                 :       }
    2867               0 :       else if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_X_HEX2)) {
    2868               0 :         num = scan_unsigned_hexadecimal_number(&p, end, 2, enc);
    2869               0 :         if (num < 0) return ONIGERR_TOO_BIG_NUMBER;
    2870               0 :         if (p == prev) {  /* can't read nothing. */
    2871               0 :           num = 0; /* but, it's not error */
    2872                 :         }
    2873               0 :         tok->type = TK_RAW_BYTE;
    2874               0 :         tok->base = 16;
    2875               0 :         tok->u.c  = num;
    2876                 :       }
    2877               0 :       break;
    2878                 : 
    2879                 :     case 'u':
    2880               0 :       if (PEND) break;
    2881                 : 
    2882               0 :       prev = p;
    2883               0 :       if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_U_HEX4)) {
    2884               0 :         num = scan_unsigned_hexadecimal_number(&p, end, 4, enc);
    2885               0 :         if (num < 0) return ONIGERR_TOO_BIG_NUMBER;
    2886               0 :         if (p == prev) {  /* can't read nothing. */
    2887               0 :           num = 0; /* but, it's not error */
    2888                 :         }
    2889               0 :         tok->type   = TK_CODE_POINT;
    2890               0 :         tok->base   = 16;
    2891               0 :         tok->u.code = (OnigCodePoint )num;
    2892                 :       }
    2893               0 :       break;
    2894                 : 
    2895                 :     case '0':
    2896                 :     case '1': case '2': case '3': case '4': case '5': case '6': case '7':
    2897               0 :       if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_OCTAL3)) {
    2898               0 :         PUNFETCH;
    2899               0 :         prev = p;
    2900               0 :         num = scan_unsigned_octal_number(&p, end, 3, enc);
    2901               0 :         if (num < 0) return ONIGERR_TOO_BIG_NUMBER;
    2902               0 :         if (p == prev) {  /* can't read nothing. */
    2903               0 :           num = 0; /* but, it's not error */
    2904                 :         }
    2905               0 :         tok->type = TK_RAW_BYTE;
    2906               0 :         tok->base = 8;
    2907               0 :         tok->u.c  = num;
    2908                 :       }
    2909               0 :       break;
    2910                 : 
    2911                 :     default:
    2912               0 :       PUNFETCH;
    2913               0 :       num = fetch_escaped_value(&p, end, env);
    2914               0 :       if (num < 0) return num;
    2915               0 :       if (tok->u.c != num) {
    2916               0 :         tok->u.code = (OnigCodePoint )num;
    2917               0 :         tok->type   = TK_CODE_POINT;
    2918                 :       }
    2919                 :       break;
    2920                 :     }
    2921                 :   }
    2922             155 :   else if (c == '[') {
    2923              82 :     if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_POSIX_BRACKET) && (PPEEK_IS(':'))) {
    2924              41 :       OnigCodePoint send[] = { (OnigCodePoint )':', (OnigCodePoint )']' };
    2925              41 :       tok->backp = p; /* point at '[' is readed */
    2926              41 :       PINC;
    2927              41 :       if (str_exist_check_with_esc(send, 2, p, end,
    2928                 :                                    (OnigCodePoint )']', enc)) {
    2929              41 :         tok->type = TK_POSIX_BRACKET_OPEN;
    2930                 :       }
    2931                 :       else {
    2932               0 :         PUNFETCH;
    2933               0 :         goto cc_in_cc;
    2934                 :       }
    2935                 :     }
    2936                 :     else {
    2937               0 :     cc_in_cc:
    2938               0 :       if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_CCLASS_SET_OP)) {
    2939               0 :         tok->type = TK_CC_CC_OPEN;
    2940                 :       }
    2941                 :       else {
    2942               0 :         CC_ESC_WARN(env, (UChar* )"[");
    2943                 :       }
    2944                 :     }
    2945                 :   }
    2946             114 :   else if (c == '&') {
    2947               0 :     if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_CCLASS_SET_OP) &&
    2948                 :         !PEND && (PPEEK_IS('&'))) {
    2949               0 :       PINC;
    2950               0 :       tok->type = TK_CC_AND;
    2951                 :     }
    2952                 :   }
    2953                 : 
    2954             298 :  end:
    2955             298 :   *src = p;
    2956             298 :   return tok->type;
    2957                 : }
    2958                 : 
    2959                 : static int
    2960                 : fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
    2961             888 : {
    2962                 :   int r, num;
    2963                 :   OnigCodePoint c;
    2964             888 :   OnigEncoding enc = env->enc;
    2965             888 :   OnigSyntaxType* syn = env->syntax;
    2966                 :   UChar* prev;
    2967             888 :   UChar* p = *src;
    2968                 :   PFETCH_READY;
    2969                 : 
    2970             893 :  start:
    2971             893 :   if (PEND) {
    2972             145 :     tok->type = TK_EOT;
    2973             145 :     return tok->type;
    2974                 :   }
    2975                 : 
    2976             748 :   tok->type  = TK_STRING;
    2977             748 :   tok->base  = 0;
    2978             748 :   tok->backp = p;
    2979                 : 
    2980             748 :   PFETCH(c);
    2981             892 :   if (IS_MC_ESC_CODE(c, enc, syn)) {
    2982              18 :     if (PEND) return ONIGERR_END_PATTERN_AT_ESCAPE;
    2983                 : 
    2984              18 :     tok->backp = p;
    2985              18 :     PFETCH(c);
    2986                 : 
    2987              18 :     tok->u.c = c;
    2988              18 :     tok->escaped = 1;
    2989              18 :     switch (c) {
    2990                 :     case '*':
    2991               0 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_ASTERISK_ZERO_INF)) break;
    2992               0 :       tok->type = TK_OP_REPEAT;
    2993               0 :       tok->u.repeat.lower = 0;
    2994               0 :       tok->u.repeat.upper = REPEAT_INFINITE;
    2995               0 :       goto greedy_check;
    2996                 :       break;
    2997                 : 
    2998                 :     case '+':
    2999               0 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_PLUS_ONE_INF)) break;
    3000               0 :       tok->type = TK_OP_REPEAT;
    3001               0 :       tok->u.repeat.lower = 1;
    3002               0 :       tok->u.repeat.upper = REPEAT_INFINITE;
    3003               0 :       goto greedy_check;
    3004                 :       break;
    3005                 : 
    3006                 :     case '?':
    3007               1 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_QMARK_ZERO_ONE)) break;
    3008               0 :       tok->type = TK_OP_REPEAT;
    3009               0 :       tok->u.repeat.lower = 0;
    3010               0 :       tok->u.repeat.upper = 1;
    3011             123 :     greedy_check:
    3012             126 :       if (!PEND && PPEEK_IS('?') &&
    3013                 :           IS_SYNTAX_OP(syn, ONIG_SYN_OP_QMARK_NON_GREEDY)) {
    3014               3 :         PFETCH(c);
    3015               3 :         tok->u.repeat.greedy     = 0;
    3016               3 :         tok->u.repeat.possessive = 0;
    3017                 :       }
    3018                 :       else {
    3019             123 :       possessive_check:
    3020             123 :         if (!PEND && PPEEK_IS('+') &&
    3021                 :             ((IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_PLUS_POSSESSIVE_REPEAT) &&
    3022                 :               tok->type != TK_INTERVAL)  ||
    3023                 :              (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_PLUS_POSSESSIVE_INTERVAL) &&
    3024                 :               tok->type == TK_INTERVAL))) {
    3025               0 :           PFETCH(c);
    3026               0 :           tok->u.repeat.greedy     = 1;
    3027               0 :           tok->u.repeat.possessive = 1;
    3028                 :         }
    3029                 :         else {
    3030             123 :           tok->u.repeat.greedy     = 1;
    3031             123 :           tok->u.repeat.possessive = 0;
    3032                 :         }
    3033                 :       }
    3034             126 :       break;
    3035                 : 
    3036                 :     case '{':
    3037               0 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_BRACE_INTERVAL)) break;
    3038               0 :       r = fetch_range_qualifier(&p, end, tok, env);
    3039               0 :       if (r < 0) return r;  /* error */
    3040               0 :       if (r == 0) goto greedy_check;
    3041               0 :       else if (r == 2) { /* {n} */
    3042               0 :         if (IS_SYNTAX_BV(syn, ONIG_SYN_FIXED_INTERVAL_IS_GREEDY_ONLY))
    3043               0 :           goto possessive_check;
    3044                 : 
    3045               0 :         goto greedy_check;
    3046                 :       }
    3047                 :       /* r == 1 : normal char */
    3048               0 :       break;
    3049                 : 
    3050                 :     case '|':
    3051               0 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_VBAR_ALT)) break;
    3052               0 :       tok->type = TK_ALT;
    3053               0 :       break;
    3054                 : 
    3055                 :     case '(':
    3056               0 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_LPAREN_SUBEXP)) break;
    3057               0 :       tok->type = TK_SUBEXP_OPEN;
    3058               0 :       break;
    3059                 : 
    3060                 :     case ')':
    3061               0 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_LPAREN_SUBEXP)) break;
    3062               0 :       tok->type = TK_SUBEXP_CLOSE;
    3063               0 :       break;
    3064                 : 
    3065                 :     case 'w':
    3066               3 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_W_WORD)) break;
    3067               3 :       tok->type = TK_CHAR_TYPE;
    3068               3 :       tok->u.subtype = CTYPE_WORD;
    3069               3 :       break;
    3070                 : 
    3071                 :     case 'W':
    3072               1 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_W_WORD)) break;
    3073               1 :       tok->type = TK_CHAR_TYPE;
    3074               1 :       tok->u.subtype = CTYPE_NOT_WORD;
    3075               1 :       break;
    3076                 : 
    3077                 :     case 'b':
    3078               1 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_B_WORD_BOUND)) break;
    3079               1 :       tok->type = TK_ANCHOR;
    3080               1 :       tok->u.anchor = ANCHOR_WORD_BOUND;
    3081               1 :       break;
    3082                 : 
    3083                 :     case 'B':
    3084               1 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_B_WORD_BOUND)) break;
    3085               1 :       tok->type = TK_ANCHOR;
    3086               1 :       tok->u.anchor = ANCHOR_NOT_WORD_BOUND;
    3087               1 :       break;
    3088                 : 
    3089                 : #ifdef USE_WORD_BEGIN_END
    3090                 :     case '<':
    3091               0 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END)) break;
    3092               0 :       tok->type = TK_ANCHOR;
    3093               0 :       tok->u.anchor = ANCHOR_WORD_BEGIN;
    3094               0 :       break;
    3095                 : 
    3096                 :     case '>':
    3097               0 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END)) break;
    3098               0 :       tok->type = TK_ANCHOR;
    3099               0 :       tok->u.anchor = ANCHOR_WORD_END;
    3100               0 :       break;
    3101                 : #endif
    3102                 : 
    3103                 :     case 's':
    3104               3 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_S_WHITE_SPACE)) break;
    3105               3 :       tok->type = TK_CHAR_TYPE;
    3106               3 :       tok->u.subtype = CTYPE_WHITE_SPACE;
    3107               3 :       break;
    3108                 : 
    3109                 :     case 'S':
    3110               1 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_S_WHITE_SPACE)) break;
    3111               1 :       tok->type = TK_CHAR_TYPE;
    3112               1 :       tok->u.subtype = CTYPE_NOT_WHITE_SPACE;
    3113               1 :       break;
    3114                 : 
    3115                 :     case 'd':
    3116               1 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_D_DIGIT)) break;
    3117               1 :       tok->type = TK_CHAR_TYPE;
    3118               1 :       tok->u.subtype = CTYPE_DIGIT;
    3119               1 :       break;
    3120                 : 
    3121                 :     case 'D':
    3122               1 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_D_DIGIT)) break;
    3123               1 :       tok->type = TK_CHAR_TYPE;
    3124               1 :       tok->u.subtype = CTYPE_NOT_DIGIT;
    3125               1 :       break;
    3126                 : 
    3127                 :     case 'h':
    3128               0 :       if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_H_XDIGIT)) break;
    3129               0 :       tok->type = TK_CHAR_TYPE;
    3130               0 :       tok->u.subtype = CTYPE_XDIGIT;
    3131               0 :       break;
    3132                 : 
    3133                 :     case 'H':
    3134               0 :       if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_H_XDIGIT)) break;
    3135               0 :       tok->type = TK_CHAR_TYPE;
    3136               0 :       tok->u.subtype = CTYPE_NOT_XDIGIT;
    3137               0 :       break;
    3138                 : 
    3139                 :     case 'A':
    3140               0 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_AZ_BUF_ANCHOR)) break;
    3141               0 :     begin_buf:
    3142               0 :       tok->type = TK_ANCHOR;
    3143               0 :       tok->u.subtype = ANCHOR_BEGIN_BUF;
    3144               0 :       break;
    3145                 : 
    3146                 :     case 'Z':
    3147               0 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_AZ_BUF_ANCHOR)) break;
    3148               0 :       tok->type = TK_ANCHOR;
    3149               0 :       tok->u.subtype = ANCHOR_SEMI_END_BUF;
    3150               0 :       break;
    3151                 : 
    3152                 :     case 'z':
    3153               0 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_AZ_BUF_ANCHOR)) break;
    3154               0 :     end_buf:
    3155               0 :       tok->type = TK_ANCHOR;
    3156               0 :       tok->u.subtype = ANCHOR_END_BUF;
    3157               0 :       break;
    3158                 : 
    3159                 :     case 'G':
    3160               0 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_CAPITAL_G_BEGIN_ANCHOR)) break;
    3161               0 :       tok->type = TK_ANCHOR;
    3162               0 :       tok->u.subtype = ANCHOR_BEGIN_POSITION;
    3163               0 :       break;
    3164                 : 
    3165                 :     case '`':
    3166               0 :       if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_GNU_BUF_ANCHOR)) break;
    3167               0 :       goto begin_buf;
    3168                 :       break;
    3169                 : 
    3170                 :     case '\'':
    3171               0 :       if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_GNU_BUF_ANCHOR)) break;
    3172               0 :       goto end_buf;
    3173                 :       break;
    3174                 : 
    3175                 :     case 'x':
    3176               0 :       if (PEND) break;
    3177                 : 
    3178               0 :       prev = p;
    3179               0 :       if (PPEEK_IS('{') && IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_X_BRACE_HEX8)) {
    3180               0 :         PINC;
    3181               0 :         num = scan_unsigned_hexadecimal_number(&p, end, 8, enc);
    3182               0 :         if (num < 0) return ONIGERR_TOO_BIG_WIDE_CHAR_VALUE;
    3183               0 :         if (!PEND) {
    3184               0 :           if (ONIGENC_IS_CODE_XDIGIT(enc, PPEEK))
    3185               0 :             return ONIGERR_TOO_LONG_WIDE_CHAR_VALUE;
    3186                 :         }
    3187                 : 
    3188               0 :         if ((p > prev + enc_len(enc, prev)) && !PEND && PPEEK_IS('}')) {
    3189               0 :           PINC;
    3190               0 :           tok->type   = TK_CODE_POINT;
    3191               0 :           tok->u.code = (OnigCodePoint )num;
    3192                 :         }
    3193                 :         else {
    3194                 :           /* can't read nothing or invalid format */
    3195               0 :           p = prev;
    3196                 :         }
    3197                 :       }
    3198               0 :       else if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_X_HEX2)) {
    3199               0 :         num = scan_unsigned_hexadecimal_number(&p, end, 2, enc);
    3200               0 :         if (num < 0) return ONIGERR_TOO_BIG_NUMBER;
    3201               0 :         if (p == prev) {  /* can't read nothing. */
    3202               0 :           num = 0; /* but, it's not error */
    3203                 :         }
    3204               0 :         tok->type = TK_RAW_BYTE;
    3205               0 :         tok->base = 16;
    3206               0 :         tok->u.c  = num;
    3207                 :       }
    3208               0 :       break;
    3209                 : 
    3210                 :     case 'u':
    3211               0 :       if (PEND) break;
    3212                 : 
    3213               0 :       prev = p;
    3214               0 :       if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_U_HEX4)) {
    3215               0 :         num = scan_unsigned_hexadecimal_number(&p, end, 4, enc);
    3216               0 :         if (num < 0) return ONIGERR_TOO_BIG_NUMBER;
    3217               0 :         if (p == prev) {  /* can't read nothing. */
    3218               0 :           num = 0; /* but, it's not error */
    3219                 :         }
    3220               0 :         tok->type   = TK_CODE_POINT;
    3221               0 :         tok->base   = 16;
    3222               0 :         tok->u.code = (OnigCodePoint )num;
    3223                 :       }
    3224               0 :       break;
    3225                 : 
    3226                 :     case '1': case '2': case '3': case '4':
    3227                 :     case '5': case '6': case '7': case '8': case '9':
    3228               0 :       PUNFETCH;
    3229               0 :       prev = p;
    3230               0 :       num = onig_scan_unsigned_number(&p, end, enc);
    3231               0 :       if (num < 0 || num > ONIG_MAX_BACKREF_NUM) {
    3232                 :         goto skip_backref;
    3233                 :       }
    3234                 : 
    3235               0 :       if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_DECIMAL_BACKREF) && 
    3236                 :           (num <= env->num_mem || num <= 9)) { /* This spec. from GNU regex */
    3237               0 :         if (IS_SYNTAX_BV(syn, ONIG_SYN_STRICT_CHECK_BACKREF)) {
    3238               0 :           if (num > env->num_mem || IS_NULL(SCANENV_MEM_NODES(env)[num]))
    3239               0 :             return ONIGERR_INVALID_BACKREF;
    3240                 :         }
    3241                 : 
    3242               0 :         tok->type = TK_BACKREF;
    3243               0 :         tok->u.backref.num     = 1;
    3244               0 :         tok->u.backref.ref1    = num;
    3245               0 :         tok->u.backref.by_name = 0;
    3246                 : #ifdef USE_BACKREF_AT_LEVEL
    3247               0 :         tok->u.backref.exist_level = 0;
    3248                 : #endif
    3249               0 :         break;
    3250                 :       }
    3251                 : 
    3252               0 :     skip_backref:
    3253               0 :       if (c == '8' || c == '9') {
    3254                 :         /* normal char */
    3255               0 :         p = prev; PINC;
    3256               0 :         break;
    3257                 :       }
    3258                 : 
    3259               0 :       p = prev;
    3260                 :       /* fall through */
    3261                 :     case '0':
    3262               0 :       if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_OCTAL3)) {
    3263               0 :         prev = p;
    3264               0 :         num = scan_unsigned_octal_number(&p, end, (c == '0' ? 2:3), enc);
    3265               0 :         if (num < 0) return ONIGERR_TOO_BIG_NUMBER;
    3266               0 :         if (p == prev) {  /* can't read nothing. */
    3267               0 :           num = 0; /* but, it's not error */
    3268                 :         }
    3269               0 :         tok->type = TK_RAW_BYTE;
    3270               0 :         tok->base = 8;
    3271               0 :         tok->u.c  = num;
    3272                 :       }
    3273               0 :       else if (c != '0') {
    3274               0 :         PINC;
    3275                 :       }
    3276               0 :       break;
    3277                 : 
    3278                 : #ifdef USE_NAMED_GROUP
    3279                 :     case 'k':
    3280               0 :       if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_K_NAMED_BACKREF)) {
    3281               0 :         PFETCH(c);
    3282               0 :         if (c == '<') {
    3283                 :           UChar* name_end;
    3284                 :           int* backs;
    3285                 : 
    3286               0 :           prev = p;
    3287                 : 
    3288                 : #ifdef USE_BACKREF_AT_LEVEL
    3289               0 :           name_end = NULL_UCHARP; /* no need. escape gcc warning. */
    3290               0 :           r = fetch_name_with_level(&p, end, &name_end, env, &tok->u.backref.level);
    3291               0 :           if (r == 1) tok->u.backref.exist_level = 1;
    3292               0 :           else        tok->u.backref.exist_level = 0;
    3293                 : #else
    3294                 :           r = fetch_name(&p, end, &name_end, env, 1);
    3295                 : #endif
    3296               0 :           if (r < 0) return r;
    3297                 : 
    3298               0 :           num = onig_name_to_group_numbers(env->reg, prev, name_end, &backs);
    3299               0 :           if (num <= 0) {
    3300               0 :             onig_scan_env_set_error_string(env,
    3301                 :                             ONIGERR_UNDEFINED_NAME_REFERENCE, prev, name_end);
    3302               0 :             return ONIGERR_UNDEFINED_NAME_REFERENCE;
    3303                 :           }
    3304               0 :           if (IS_SYNTAX_BV(syn, ONIG_SYN_STRICT_CHECK_BACKREF)) {
    3305                 :             int i;
    3306               0 :             for (i = 0; i < num; i++) {
    3307               0 :               if (backs[i] > env->num_mem ||
    3308                 :                   IS_NULL(SCANENV_MEM_NODES(env)[backs[i]]))
    3309               0 :                 return ONIGERR_INVALID_BACKREF;
    3310                 :             }
    3311                 :           }
    3312                 : 
    3313               0 :           tok->type = TK_BACKREF;
    3314               0 :           tok->u.backref.by_name = 1;
    3315               0 :           if (num == 1) {
    3316               0 :             tok->u.backref.num  = 1;
    3317               0 :             tok->u.backref.ref1 = backs[0];
    3318                 :           }
    3319                 :           else {
    3320               0 :             tok->u.backref.num  = num;
    3321               0 :             tok->u.backref.refs = backs;
    3322                 :           }
    3323                 :         }
    3324                 :         else
    3325               0 :           PUNFETCH;
    3326                 :       }
    3327               0 :       break;
    3328                 : #endif
    3329                 : 
    3330                 : #ifdef USE_SUBEXP_CALL
    3331                 :     case 'g':
    3332               0 :       if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_G_SUBEXP_CALL)) {
    3333               0 :         PFETCH(c);
    3334               0 :         if (c == '<') {
    3335                 :           UChar* name_end;
    3336                 : 
    3337               0 :           prev = p;
    3338               0 :           r = fetch_name(&p, end, &name_end, env, 1);
    3339               0 :           if (r < 0) return r;
    3340                 : 
    3341               0 :           tok->type = TK_CALL;
    3342               0 :           tok->u.call.name     = prev;
    3343               0 :           tok->u.call.name_end = name_end;
    3344                 :         }
    3345                 :         else
    3346               0 :           PUNFETCH;
    3347                 :       }
    3348               0 :       break;
    3349                 : #endif
    3350                 : 
    3351                 :     case 'Q':
    3352               0 :       if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_CAPITAL_Q_QUOTE)) {
    3353               0 :         tok->type = TK_QUOTE_OPEN;
    3354                 :       }
    3355               0 :       break;
    3356                 : 
    3357                 :     case 'p':
    3358                 :     case 'P':
    3359               0 :       if (PPEEK_IS('{') &&
    3360                 :           IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY)) {
    3361               0 :         PINC;
    3362               0 :         tok->type = TK_CHAR_PROPERTY;
    3363               0 :         tok->u.prop.not = (c == 'P' ? 1 : 0);
    3364                 : 
    3365               0 :         if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT)) {
    3366               0 :           PFETCH(c);
    3367               0 :           if (c == '^') {
    3368               0 :             tok->u.prop.not = (tok->u.prop.not == 0 ? 1 : 0);
    3369                 :           }
    3370                 :           else
    3371               0 :             PUNFETCH;
    3372                 :         }
    3373                 :       }
    3374               0 :       break;
    3375                 : 
    3376                 :     default:
    3377               5 :       PUNFETCH;
    3378               5 :       num = fetch_escaped_value(&p, end, env);
    3379               5 :       if (num < 0) return num;
    3380                 :       /* set_raw: */
    3381               5 :       if (tok->u.c != num) {
    3382               0 :         tok->type = TK_CODE_POINT;
    3383               0 :         tok->u.code = (OnigCodePoint )num;
    3384                 :       }
    3385                 :       else { /* string */
    3386               5 :         p = tok->backp + enc_len(enc, tok->backp);
    3387                 :       }
    3388                 :       break;
    3389                 :     }
    3390                 :   }
    3391                 :   else {
    3392             730 :     tok->u.c = c;
    3393             730 :     tok->escaped = 0;
    3394                 : 
    3395                 : #ifdef USE_VARIABLE_META_CHARS
    3396             730 :     if ((c != ONIG_INEFFECTIVE_META_CHAR) &&
    3397                 :         IS_SYNTAX_OP(syn, ONIG_SYN_OP_VARIABLE_META_CHARACTERS)) {
    3398               0 :       if (c == MC_ANYCHAR(enc))
    3399               0 :         goto any_char;
    3400               0 :       else if (c == MC_ANYTIME(enc))
    3401               0 :         goto anytime;
    3402               0 :       else if (c == MC_ZERO_OR_ONE_TIME(enc))
    3403               0 :         goto zero_or_one_time;
    3404               0 :       else if (c == MC_ONE_OR_MORE_TIME(enc))
    3405               0 :         goto one_or_more_time;
    3406               0 :       else if (c == MC_ANYCHAR_ANYTIME(enc)) {
    3407               0 :         tok->type = TK_ANYCHAR_ANYTIME;
    3408               0 :         goto out;
    3409                 :       }
    3410                 :     }
    3411                 : #endif
    3412                 : 
    3413             730 :     switch (c) {
    3414                 :     case '.':
    3415              26 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_DOT_ANYCHAR)) break;
    3416                 : #ifdef USE_VARIABLE_META_CHARS
    3417              26 :     any_char:
    3418                 : #endif
    3419              26 :       tok->type = TK_ANYCHAR;
    3420              26 :       break;
    3421                 : 
    3422                 :     case '*':
    3423              26 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ASTERISK_ZERO_INF)) break;
    3424                 : #ifdef USE_VARIABLE_META_CHARS
    3425              26 :     anytime:
    3426                 : #endif
    3427              26 :       tok->type = TK_OP_REPEAT;
    3428              26 :       tok->u.repeat.lower = 0;
    3429              26 :       tok->u.repeat.upper = REPEAT_INFINITE;
    3430              26 :       goto greedy_check;
    3431                 :       break;
    3432                 : 
    3433                 :     case '+':
    3434              75 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_PLUS_ONE_INF)) break;
    3435                 : #ifdef USE_VARIABLE_META_CHARS
    3436              75 :     one_or_more_time:
    3437                 : #endif
    3438              75 :       tok->type = TK_OP_REPEAT;
    3439              75 :       tok->u.repeat.lower = 1;
    3440              75 :       tok->u.repeat.upper = REPEAT_INFINITE;
    3441              75 :       goto greedy_check;
    3442                 :       break;
    3443                 : 
    3444                 :     case '?':
    3445              21 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_QMARK_ZERO_ONE)) break;
    3446                 : #ifdef USE_VARIABLE_META_CHARS
    3447              21 :     zero_or_one_time:
    3448                 : #endif
    3449              21 :       tok->type = TK_OP_REPEAT;
    3450              21 :       tok->u.repeat.lower = 0;
    3451              21 :       tok->u.repeat.upper = 1;
    3452              21 :       goto greedy_check;
    3453                 :       break;
    3454                 : 
    3455                 :     case '{':
    3456               4 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_BRACE_INTERVAL)) break;
    3457               4 :       r = fetch_range_qualifier(&p, end, tok, env);
    3458               4 :       if (r < 0) return r;  /* error */
    3459               4 :       if (r == 0) goto greedy_check;
    3460               3 :       else if (r == 2) { /* {n} */
    3461               3 :         if (IS_SYNTAX_BV(syn, ONIG_SYN_FIXED_INTERVAL_IS_GREEDY_ONLY))
    3462               3 :           goto possessive_check;
    3463                 : 
    3464               0 :         goto greedy_check;
    3465                 :       }
    3466                 :       /* r == 1 : normal char */
    3467               0 :       break;
    3468                 : 
    3469                 :     case '|':
    3470               2 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_VBAR_ALT)) break;
    3471               2 :       tok->type = TK_ALT;
    3472               2 :       break;
    3473                 : 
    3474                 :     case '(':
    3475              61 :       if (PPEEK_IS('?') &&
    3476                 :           IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_QMARK_GROUP_EFFECT)) {
    3477               0 :         PINC;
    3478               0 :         if (PPEEK_IS('#')) {
    3479               0 :           PFETCH(c);
    3480                 :           while (1) {
    3481               0 :             if (PEND) return ONIGERR_END_PATTERN_IN_GROUP;
    3482               0 :             PFETCH(c);
    3483               0 :             if (c == MC_ESC(enc)) {
    3484               0 :               if (!PEND) PFETCH(c);
    3485                 :             }
    3486                 :             else {
    3487               0 :               if (c == ')') break;
    3488                 :             }
    3489               0 :           }
    3490               0 :           goto start;
    3491                 :         }
    3492               0 :         PUNFETCH;
    3493                 :       }
    3494                 : 
    3495              61 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_LPAREN_SUBEXP)) break;
    3496              61 :       tok->type = TK_SUBEXP_OPEN;
    3497              61 :       break;
    3498                 : 
    3499                 :     case ')':
    3500              61 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_LPAREN_SUBEXP)) break;
    3501              61 :       tok->type = TK_SUBEXP_CLOSE;
    3502              61 :       break;
    3503                 : 
    3504                 :     case '^':
    3505               4 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_LINE_ANCHOR)) break;
    3506               4 :       tok->type = TK_ANCHOR;
    3507               4 :       tok->u.subtype = (IS_SINGLELINE(env->option)
    3508                 :                         ? ANCHOR_BEGIN_BUF : ANCHOR_BEGIN_LINE);
    3509               4 :       break;
    3510                 : 
    3511                 :     case '$':
    3512              12 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_LINE_ANCHOR)) break;
    3513              12 :       tok->type = TK_ANCHOR;
    3514              12 :       tok->u.subtype = (IS_SINGLELINE(env->option)
    3515                 :                         ? ANCHOR_END_BUF : ANCHOR_END_LINE);
    3516              12 :       break;
    3517                 : 
    3518                 :     case '[':
    3519              93 :       if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_BRACKET_CC)) break;
    3520              93 :       tok->type = TK_CC_OPEN;
    3521              93 :       break;
    3522                 : 
    3523                 :     case ']':
    3524               0 :       if (*src > env->pattern)   /* /].../ is allowed. */
    3525               0 :         CCEND_ESC_WARN(env, (UChar* )"]");
    3526               0 :       break;
    3527                 : 
    3528                 :     case '#':
    3529               1 :       if (IS_EXTEND(env->option)) {
    3530               0 :         while (!PEND) {
    3531               0 :           PFETCH(c);
    3532               0 :           if (ONIGENC_IS_CODE_NEWLINE(enc, c))
    3533               0 :             break;
    3534                 :         }
    3535               0 :         goto start;
    3536                 :         break;
    3537                 :       }
    3538               1 :       break;
    3539                 : 
    3540                 :     case ' ': case '\t': case '\n': case '\r': case '\f':
    3541              39 :       if (IS_EXTEND(env->option))
    3542               5 :         goto start;
    3543                 :       break;
    3544                 : 
    3545                 :     default:
    3546                 :       /* string */
    3547                 :       break;
    3548                 :     }
    3549                 :   }
    3550                 : 
    3551                 : #ifdef USE_VARIABLE_META_CHARS
    3552             743 :  out:
    3553                 : #endif
    3554             743 :   *src = p;
    3555             743 :   return tok->type;
    3556                 : }
    3557                 : 
    3558                 : static int
    3559                 : add_ctype_to_cc_by_range(CClassNode* cc, int ctype, int not, OnigEncoding enc,
    3560                 :                          const OnigCodePoint sbr[], const OnigCodePoint mbr[])
    3561              34 : {
    3562                 :   int i, r;
    3563                 :   OnigCodePoint j;
    3564                 : 
    3565              34 :   int nsb = ONIGENC_CODE_RANGE_NUM(sbr);
    3566              34 :   int nmb = ONIGENC_CODE_RANGE_NUM(mbr);
    3567                 : 
    3568              34 :   if (not == 0) {
    3569             130 :     for (i = 0; i < nsb; i++) {
    3570              96 :       for (j  = ONIGENC_CODE_RANGE_FROM(sbr, i);
    3571            1332 :            j <= ONIGENC_CODE_RANGE_TO(sbr, i); j++) {
    3572            1236 :         BITSET_SET_BIT(cc->bs, j);
    3573                 :       }
    3574                 :     }
    3575                 : 
    3576            5486 :     for (i = 0; i < nmb; i++) {
    3577            5452 :       r = add_code_range_to_buf(&(cc->mbuf),
    3578                 :                                 ONIGENC_CODE_RANGE_FROM(mbr, i),
    3579                 :                                 ONIGENC_CODE_RANGE_TO(mbr, i));
    3580            5452 :       if (r != 0) return r;
    3581                 :     }
    3582                 :   }
    3583                 :   else {
    3584               0 :     OnigCodePoint prev = 0;
    3585                 : 
    3586               0 :     if (ONIGENC_MBC_MINLEN(enc) == 1) {
    3587               0 :       for (i = 0; i < nsb; i++) {
    3588               0 :         for (j = prev;
    3589               0 :              j < ONIGENC_CODE_RANGE_FROM(sbr, i); j++) {
    3590               0 :           BITSET_SET_BIT(cc->bs, j);
    3591                 :         }
    3592               0 :         prev = ONIGENC_CODE_RANGE_TO(sbr, i) + 1;
    3593                 :       }
    3594               0 :       if (prev < 0x7f) {
    3595               0 :         for (j = prev; j < 0x7f; j++) {
    3596               0 :           BITSET_SET_BIT(cc->bs, j);
    3597                 :         }
    3598                 :       }
    3599                 : 
    3600               0 :       prev = 0x80;
    3601                 :     }
    3602                 : 
    3603               0 :     for (i = 0; i < nmb; i++) {
    3604               0 :       if (prev < ONIGENC_CODE_RANGE_FROM(mbr, i)) {
    3605               0 :         r = add_code_range_to_buf(&(cc->mbuf), prev,
    3606                 :                                   ONIGENC_CODE_RANGE_FROM(mbr, i) - 1);
    3607               0 :         if (r != 0) return r;
    3608                 :       }
    3609               0 :       prev = ONIGENC_CODE_RANGE_TO(mbr, i) + 1;
    3610                 :     }
    3611               0 :     if (prev < 0x7fffffff) {
    3612               0 :       r = add_code_range_to_buf(&(cc->mbuf), prev, 0x7fffffff);
    3613               0 :       if (r != 0) return r;
    3614                 :     }
    3615                 :   }
    3616                 : 
    3617              34 :   return 0;
    3618                 : }
    3619                 : 
    3620                 : static int
    3621                 : add_ctype_to_cc(CClassNode* cc, int ctype, int not, ScanEnv* env)
    3622              42 : {
    3623                 :   int c, r;
    3624                 :   const OnigCodePoint *sbr, *mbr;
    3625              42 :   OnigEncoding enc = env->enc;
    3626                 : 
    3627              42 :   r = ONIGENC_GET_CTYPE_CODE_RANGE(enc, ctype, &sbr, &mbr);
    3628              42 :   if (r == 0) {
    3629              34 :     return add_ctype_to_cc_by_range(cc, ctype, not, env->enc, sbr, mbr);
    3630                 :   }
    3631               8 :   else if (r != ONIG_NO_SUPPORT_CONFIG) {
    3632               0 :     return r;
    3633                 :   }
    3634                 : 
    3635               8 :   r = 0;
    3636               8 :   switch (ctype) {
    3637                 :   case ONIGENC_CTYPE_ALPHA:
    3638                 :   case ONIGENC_CTYPE_BLANK:
    3639                 :   case ONIGENC_CTYPE_CNTRL:
    3640                 :   case ONIGENC_CTYPE_DIGIT:
    3641                 :   case ONIGENC_CTYPE_LOWER:
    3642                 :   case ONIGENC_CTYPE_PUNCT:
    3643                 :   case ONIGENC_CTYPE_SPACE:
    3644                 :   case ONIGENC_CTYPE_UPPER:
    3645                 :   case ONIGENC_CTYPE_XDIGIT:
    3646                 :   case ONIGENC_CTYPE_ASCII:
    3647                 :   case ONIGENC_CTYPE_ALNUM:
    3648               8 :     if (not != 0) {
    3649               0 :       for (c = 0; c < SINGLE_BYTE_SIZE; c++) {
    3650               0 :         if (! ONIGENC_IS_CODE_CTYPE(enc, (OnigCodePoint )c, ctype))
    3651               0 :           BITSET_SET_BIT(cc->bs, c);
    3652                 :       }
    3653               0 :       ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf);
    3654                 :     }
    3655                 :     else {
    3656            2056 :       for (c = 0; c < SINGLE_BYTE_SIZE; c++) {
    3657            2048 :         if (ONIGENC_IS_CODE_CTYPE(enc, (OnigCodePoint )c, ctype))
    3658              49 :           BITSET_SET_BIT(cc->bs, c);
    3659                 :       }
    3660                 :     }
    3661               8 :     break;
    3662                 : 
    3663                 :   case ONIGENC_CTYPE_GRAPH:
    3664                 :   case ONIGENC_CTYPE_PRINT:
    3665               0 :     if (not != 0) {
    3666               0 :       for (c = 0; c < SINGLE_BYTE_SIZE; c++) {
    3667               0 :         if (! ONIGENC_IS_CODE_CTYPE(enc, (OnigCodePoint )c, ctype))
    3668               0 :           BITSET_SET_BIT(cc->bs, c);
    3669                 :       }
    3670                 :     }
    3671                 :     else {
    3672               0 :       for (c = 0; c < SINGLE_BYTE_SIZE; c++) {
    3673               0 :         if (ONIGENC_IS_CODE_CTYPE(enc, (OnigCodePoint )c, ctype))
    3674               0 :           BITSET_SET_BIT(cc->bs, c);
    3675                 :       }
    3676               0 :       ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf);
    3677                 :     }
    3678               0 :     break;
    3679                 : 
    3680                 :   case ONIGENC_CTYPE_WORD:
    3681               0 :     if (not == 0) {
    3682               0 :       for (c = 0; c < SINGLE_BYTE_SIZE; c++) {
    3683               0 :         if (ONIGENC_IS_CODE_SB_WORD(enc, c)) BITSET_SET_BIT(cc->bs, c);
    3684                 :       }
    3685               0 :       ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf);
    3686                 :     }
    3687                 :     else {
    3688               0 :       for (c = 0; c < SINGLE_BYTE_SIZE; c++) {
    3689               0 :         if ((ONIGENC_CODE_TO_MBCLEN(enc, c) > 0)  /* 0: invalid code point */
    3690                 :             && ! ONIGENC_IS_CODE_WORD(enc, c))
    3691               0 :           BITSET_SET_BIT(cc->bs, c);
    3692                 :       }
    3693                 :     }
    3694               0 :     break;
    3695                 : 
    3696                 :   default:
    3697               0 :     return ONIGERR_PARSER_BUG;
    3698                 :     break;
    3699                 :   }
    3700                 : 
    3701               8 :   return r;
    3702                 : }
    3703                 : 
    3704                 : static int
    3705                 : parse_ctype_to_enc_ctype(int pctype, int* not)
    3706               7 : {
    3707                 :   int ctype;
    3708                 : 
    3709               7 :   switch (pctype) {
    3710                 :   case CTYPE_WORD:
    3711               0 :     ctype = ONIGENC_CTYPE_WORD;
    3712               0 :     *not = 0;
    3713               0 :     break;
    3714                 :   case CTYPE_NOT_WORD:
    3715               0 :     ctype = ONIGENC_CTYPE_WORD;
    3716               0 :     *not = 1;
    3717               0 :     break;
    3718                 :   case CTYPE_WHITE_SPACE:
    3719               4 :     ctype = ONIGENC_CTYPE_SPACE;
    3720               4 :     *not = 0;
    3721               4 :     break;
    3722                 :   case CTYPE_NOT_WHITE_SPACE:
    3723               1 :     ctype = ONIGENC_CTYPE_SPACE;
    3724               1 :     *not = 1;
    3725               1 :     break;
    3726                 :   case CTYPE_DIGIT:
    3727               1 :     ctype = ONIGENC_CTYPE_DIGIT;
    3728               1 :     *not = 0;
    3729               1 :     break;
    3730                 :   case CTYPE_NOT_DIGIT:
    3731               1 :     ctype = ONIGENC_CTYPE_DIGIT;
    3732               1 :     *not = 1;
    3733               1 :     break;
    3734                 :   case CTYPE_XDIGIT:
    3735               0 :     ctype = ONIGENC_CTYPE_XDIGIT;
    3736               0 :     *not = 0;
    3737               0 :     break;
    3738                 :   case CTYPE_NOT_XDIGIT:
    3739               0 :     ctype = ONIGENC_CTYPE_XDIGIT;
    3740               0 :     *not = 1;
    3741               0 :     break;
    3742                 :   default:
    3743               0 :     return ONIGERR_PARSER_BUG;
    3744                 :     break;
    3745                 :   }
    3746               7 :   return ctype;
    3747                 : }
    3748                 : 
    3749                 : typedef struct {
    3750                 :   UChar    *name;
    3751                 :   int       ctype;
    3752                 :   short int len;
    3753                 : } PosixBracketEntryType;
    3754                 : 
    3755                 : static int
    3756                 : parse_posix_bracket(CClassNode* cc, UChar** src, UChar* end, ScanEnv* env)
    3757              41 : {
    3758                 : #define POSIX_BRACKET_CHECK_LIMIT_LENGTH  20
    3759                 : #define POSIX_BRACKET_NAME_MAX_LEN         6
    3760                 : 
    3761                 :   static PosixBracketEntryType PBS[] = {
    3762                 :     { (UChar* )"alnum",  ONIGENC_CTYPE_ALNUM,  5 },
    3763                 :     { (UChar* )"alpha",  ONIGENC_CTYPE_ALPHA,  5 },
    3764                 :     { (UChar* )"blank",  ONIGENC_CTYPE_BLANK,  5 },
    3765                 :     { (UChar* )"cntrl",  ONIGENC_CTYPE_CNTRL,  5 },
    3766                 :     { (UChar* )"digit",  ONIGENC_CTYPE_DIGIT,  5 },
    3767                 :     { (UChar* )"graph",  ONIGENC_CTYPE_GRAPH,  5 },
    3768                 :     { (UChar* )"lower",  ONIGENC_CTYPE_LOWER,  5 },
    3769                 :     { (UChar* )"print",  ONIGENC_CTYPE_PRINT,  5 },
    3770                 :     { (UChar* )"punct",  ONIGENC_CTYPE_PUNCT,  5 },
    3771                 :     { (UChar* )"space",  ONIGENC_CTYPE_SPACE,  5 },
    3772                 :     { (UChar* )"upper",  ONIGENC_CTYPE_UPPER,  5 },
    3773                 :     { (UChar* )"xdigit", ONIGENC_CTYPE_XDIGIT, 6 },
    3774                 :     { (UChar* )"ascii",  ONIGENC_CTYPE_ASCII,  5 },
    3775                 :     { (UChar* )NULL, -1, 0 }
    3776                 :   };
    3777                 : 
    3778                 :   PosixBracketEntryType *pb;
    3779                 :   int not, i, r;
    3780                 :   OnigCodePoint c;
    3781              41 :   OnigEncoding enc = env->enc;
    3782              41 :   UChar *p = *src;
    3783                 :   PFETCH_READY;
    3784                 : 
    3785              41 :   if (PPEEK_IS('^')) {
    3786               0 :     PINC;
    3787               0 :     not = 1;
    3788                 :   }
    3789                 :   else
    3790              41 :     not = 0;
    3791                 : 
    3792              41 :   if (onigenc_strlen(enc, p, end) < POSIX_BRACKET_NAME_MAX_LEN + 2)
    3793               0 :     goto not_posix_bracket;
    3794                 : 
    3795             316 :   for (pb = PBS; IS_NOT_NULL(pb->name); pb++) {
    3796             316 :     if (onigenc_with_ascii_strncmp(enc, p, end, pb->name, pb->len) == 0) {
    3797              41 :       p = (UChar* )onigenc_step(enc, p, end, pb->len);
    3798              41 :       if (onigenc_with_ascii_strncmp(enc, p, end, (UChar* )":]", 2) != 0)
    3799               0 :         return ONIGERR_INVALID_POSIX_BRACKET_TYPE;
    3800                 : 
    3801              41 :       r = add_ctype_to_cc(cc, pb->ctype, not, env);
    3802              41 :       if (r != 0) return r;
    3803                 : 
    3804              41 :       PINC; PINC;
    3805              41 :       *src = p;
    3806              41 :       return 0;
    3807                 :     }
    3808                 :   }
    3809                 : 
    3810               0 :  not_posix_bracket:
    3811               0 :   c = 0;
    3812               0 :   i = 0;
    3813               0 :   while (!PEND && ((c = PPEEK) != ':') && c != ']') {
    3814               0 :     PINC;
    3815               0 :     if (++i > POSIX_BRACKET_CHECK_LIMIT_LENGTH) break;
    3816                 :   }
    3817               0 :   if (c == ':' && ! PEND) {
    3818               0 :     PINC;
    3819               0 :     if (! PEND) {
    3820               0 :       PFETCH(c);
    3821               0 :       if (c == ']')
    3822               0 :         return ONIGERR_INVALID_POSIX_BRACKET_TYPE;
    3823                 :     }
    3824                 :   }
    3825                 : 
    3826               0 :   return 1;   /* 1: is not POSIX bracket, but no error. */
    3827                 : }
    3828                 : 
    3829                 : static int
    3830                 : property_name_to_ctype(UChar* p, UChar* end, OnigEncoding enc)
    3831               0 : {
    3832                 :   static PosixBracketEntryType PBS[] = {
    3833                 :     { (UChar* )"Alnum",  ONIGENC_CTYPE_ALNUM,  5 },
    3834                 :     { (UChar* )"Alpha",  ONIGENC_CTYPE_ALPHA,  5 },
    3835                 :     { (UChar* )"Blank",  ONIGENC_CTYPE_BLANK,  5 },
    3836                 :     { (UChar* )"Cntrl",  ONIGENC_CTYPE_CNTRL,  5 },
    3837                 :     { (UChar* )"Digit",  ONIGENC_CTYPE_DIGIT,  5 },
    3838                 :     { (UChar* )"Graph",  ONIGENC_CTYPE_GRAPH,  5 },
    3839                 :     { (UChar* )"Lower",  ONIGENC_CTYPE_LOWER,  5 },
    3840                 :     { (UChar* )"Print",  ONIGENC_CTYPE_PRINT,  5 },
    3841                 :     { (UChar* )"Punct",  ONIGENC_CTYPE_PUNCT,  5 },
    3842                 :     { (UChar* )"Space",  ONIGENC_CTYPE_SPACE,  5 },
    3843                 :     { (UChar* )"Upper",  ONIGENC_CTYPE_UPPER,  5 },
    3844                 :     { (UChar* )"XDigit", ONIGENC_CTYPE_XDIGIT, 6 },
    3845                 :     { (UChar* )"ASCII",  ONIGENC_CTYPE_ASCII,  5 },
    3846                 :     { (UChar* )NULL, -1, 0 }
    3847                 :   };
    3848                 : 
    3849                 :   PosixBracketEntryType *pb;
    3850                 :   int len;
    3851                 : 
    3852               0 :   len = onigenc_strlen(enc, p, end);
    3853               0 :   for (pb = PBS; IS_NOT_NULL(pb->name); pb++) {
    3854               0 :     if (len == pb->len &&
    3855                 :         onigenc_with_ascii_strncmp(enc, p, end, pb->name, pb->len) == 0)
    3856               0 :       return pb->ctype;
    3857                 :   }
    3858                 : 
    3859               0 :   return -1;
    3860                 : }
    3861                 : 
    3862                 : static int
    3863                 : fetch_char_property_to_ctype(UChar** src, UChar* end, ScanEnv* env)
    3864               0 : {
    3865                 :   int ctype;
    3866                 :   OnigCodePoint c;
    3867               0 :   OnigEncoding enc = env->enc;
    3868               0 :   UChar *prev, *start, *p = *src;
    3869                 :   PFETCH_READY;
    3870                 : 
    3871                 :   /* 'IsXXXX' => 'XXXX' */
    3872               0 :   if (!PEND &&
    3873                 :       IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_CHAR_PROPERTY_PREFIX_IS)) {
    3874               0 :     c = PPEEK;
    3875               0 :     if (c == 'I') {
    3876               0 :       PINC;
    3877               0 :       if (! PEND) {
    3878               0 :         c = PPEEK;
    3879               0 :         if (c == 's')
    3880               0 :           PINC;
    3881                 :         else
    3882               0 :           PUNFETCH;
    3883                 :       }
    3884                 :     }
    3885                 :   }
    3886                 : 
    3887               0 :   start = prev = p;
    3888                 : 
    3889               0 :   while (!PEND) {
    3890               0 :     prev = p;
    3891               0 :     PFETCH(c);
    3892               0 :     if (c == '}') {
    3893               0 :       ctype = property_name_to_ctype(start, prev, enc);
    3894               0 :       if (ctype < 0) break;
    3895                 : 
    3896               0 :       *src = p;
    3897               0 :       return ctype;
    3898                 :     }
    3899               0 :     else if (c == '(' || c == ')' || c == '{' || c == '|')
    3900                 :       break;
    3901                 :   }
    3902                 : 
    3903               0 :   onig_scan_env_set_error_string(env, ONIGERR_INVALID_CHAR_PROPERTY_NAME,
    3904                 :                                  *src, prev);
    3905               0 :   return ONIGERR_INVALID_CHAR_PROPERTY_NAME;
    3906                 : }
    3907                 : 
    3908                 : static int
    3909                 : parse_char_property(Node** np, OnigToken* tok, UChar** src, UChar* end,
    3910                 :                     ScanEnv* env)
    3911               0 : {
    3912                 :   int r, ctype;
    3913                 :   CClassNode* cc;
    3914                 : 
    3915               0 :   ctype = fetch_char_property_to_ctype(src, end, env);
    3916               0 :   if (ctype < 0) return ctype;
    3917                 : 
    3918               0 :   *np = node_new_cclass();
    3919               0 :   CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
    3920               0 :   cc = &(NCCLASS(*np));
    3921               0 :   r = add_ctype_to_cc(cc, ctype, 0, env);
    3922               0 :   if (r != 0) return r;
    3923               0 :   if (tok->u.prop.not != 0) CCLASS_SET_NOT(cc);
    3924                 : 
    3925               0 :   return 0;
    3926                 : }
    3927                 : 
    3928                 : 
    3929                 : enum CCSTATE {
    3930                 :   CCS_VALUE,
    3931                 :   CCS_RANGE,
    3932                 :   CCS_COMPLETE,
    3933                 :   CCS_START
    3934                 : };
    3935                 : 
    3936                 : enum CCVALTYPE {
    3937                 :   CCV_SB,
    3938                 :   CCV_CODE_POINT,
    3939                 :   CCV_CLASS
    3940                 : };
    3941                 : 
    3942                 : static int
    3943                 : next_state_class(CClassNode* cc, OnigCodePoint* vs, enum CCVALTYPE* type,
    3944                 :                  enum CCSTATE* state, ScanEnv* env)
    3945              42 : {
    3946                 :   int r;
    3947                 : 
    3948              42 :   if (*state == CCS_RANGE)
    3949               0 :     return ONIGERR_CHAR_CLASS_VALUE_AT_END_OF_RANGE;
    3950                 : 
    3951              42 :   if (*state == CCS_VALUE && *type != CCV_CLASS) {
    3952               0 :     if (*type == CCV_SB)
    3953               0 :       BITSET_SET_BIT(cc->bs, (int )(*vs));
    3954               0 :     else if (*type == CCV_CODE_POINT) {
    3955               0 :       r = add_code_range(&(cc->mbuf), env, *vs, *vs);
    3956               0 :       if (r < 0) return r;
    3957                 :     }
    3958                 :   }
    3959                 : 
    3960              42 :   *state = CCS_VALUE;
    3961              42 :   *type  = CCV_CLASS;
    3962              42 :   return 0;
    3963                 : }
    3964                 : 
    3965                 : static int
    3966                 : next_state_val(CClassNode* cc, OnigCodePoint *vs, OnigCodePoint v,
    3967                 :                int* vs_israw, int v_israw,
    3968                 :                enum CCVALTYPE intype, enum CCVALTYPE* type,
    3969                 :                enum CCSTATE* state, ScanEnv* env)
    3970             160 : {
    3971                 :   int r;
    3972                 : 
    3973             160 :   switch (*state) {
    3974                 :   case CCS_VALUE:
    3975              59 :     if (*type == CCV_SB)
    3976              18 :       BITSET_SET_BIT(cc->bs, (int )(*vs));
    3977              41 :     else if (*type == CCV_CODE_POINT) {
    3978               0 :       r = add_code_range(&(cc->mbuf), env, *vs, *vs);
    3979               0 :       if (r < 0) return r;
    3980                 :     }
    3981              59 :     break;
    3982                 : 
    3983                 :   case CCS_RANGE:
    3984              48 :     if (intype == *type) {
    3985              48 :       if (intype == CCV_SB) {
    3986              34 :         if (*vs > 0xff || v > 0xff)
    3987               0 :           return ONIGERR_INVALID_WIDE_CHAR_VALUE;
    3988                 : 
    3989              34 :         if (*vs > v) {
    3990               0 :           if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC))
    3991               0 :             goto ccs_range_end;
    3992                 :           else
    3993               0 :             return ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS;
    3994                 :         }
    3995              34 :         bitset_set_range(cc->bs, (int )*vs, (int )v);
    3996                 :       }
    3997                 :       else {
    3998              14 :         r = add_code_range(&(cc->mbuf), env, *vs, v);
    3999              14 :         if (r < 0) return r;
    4000                 :       }
    4001                 :     }
    4002                 :     else {
    4003                 : #if 0
    4004                 :       if (intype == CCV_CODE_POINT && *type == CCV_SB) {
    4005                 : #endif
    4006               0 :         if (*vs > v) {
    4007               0 :           if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC))
    4008               0 :             goto ccs_range_end;
    4009                 :           else
    4010               0 :             return ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS;
    4011                 :         }
    4012               0 :         bitset_set_range(cc->bs, (int )*vs, (int )(v < 0xff ? v : 0xff));
    4013               0 :         r = add_code_range(&(cc->mbuf), env, (OnigCodePoint )*vs, v);
    4014               0 :         if (r < 0) return r;
    4015                 : #if 0
    4016                 :       }
    4017                 :       else
    4018                 :         return ONIGERR_MISMATCH_CODE_LENGTH_IN_CLASS_RANGE;
    4019                 : #endif
    4020                 :     }
    4021              48 :   ccs_range_end:
    4022              48 :     *state = CCS_COMPLETE;
    4023              48 :     break;
    4024                 : 
    4025                 :   case CCS_COMPLETE:
    4026                 :   case CCS_START:
    4027              53 :     *state = CCS_VALUE;
    4028                 :     break;
    4029                 : 
    4030                 :   default:
    4031                 :     break;
    4032                 :   }
    4033                 : 
    4034             160 :   *vs_israw = v_israw;
    4035             160 :   *vs       = v;
    4036             160 :   *type     = intype;
    4037             160 :   return 0;
    4038                 : }
    4039                 : 
    4040                 : static int
    4041                 : code_exist_check(OnigCodePoint c, UChar* from, UChar* end, int ignore_escaped,
    4042                 :                  OnigEncoding enc)
    4043               0 : {
    4044                 :   int in_esc;
    4045                 :   OnigCodePoint code;
    4046               0 :   UChar* p = from;
    4047                 :   PFETCH_READY;
    4048                 : 
    4049               0 :   in_esc = 0;
    4050               0 :   while (! PEND) {
    4051               0 :     if (ignore_escaped && in_esc) {
    4052               0 :       in_esc = 0;
    4053                 :     }
    4054                 :     else {
    4055               0 :       PFETCH(code);
    4056               0 :       if (code == c) return 1;
    4057               0 :       if (code == MC_ESC(enc)) in_esc = 1;
    4058                 :     }
    4059                 :   }
    4060               0 :   return 0;
    4061                 : }
    4062                 : 
    4063                 : static int
    4064                 : parse_char_class(Node** np, OnigToken* tok, UChar** src, UChar* end,
    4065                 :                  ScanEnv* env)
    4066              93 : {
    4067                 :   int r, neg, len, fetched, and_start;
    4068                 :   OnigCodePoint v, vs;
    4069                 :   UChar *p;
    4070                 :   Node* node;
    4071                 :   CClassNode *cc, *prev_cc;
    4072                 :   CClassNode work_cc;
    4073                 : 
    4074                 :   enum CCSTATE state;
    4075                 :   enum CCVALTYPE val_type, in_type;
    4076                 :   int val_israw, in_israw;
    4077                 : 
    4078              93 :   prev_cc = (CClassNode* )NULL;
    4079              93 :   *np = NULL_NODE;
    4080              93 :   r = fetch_token_in_cc(tok, src, end, env);
    4081              94 :   if (r == TK_CHAR && tok->u.c == '^' && tok->escaped == 0) {
    4082               1 :     neg = 1;
    4083               1 :     r = fetch_token_in_cc(tok, src, end, env);
    4084                 :   }
    4085                 :   else {
    4086              92 :     neg = 0;
    4087                 :   }
    4088                 : 
    4089              93 :   if (r < 0) return r;
    4090              93 :   if (r == TK_CC_CLOSE) {
    4091               0 :     if (! code_exist_check((OnigCodePoint )']',
    4092                 :                            *src, env->pattern_end, 1, env->enc))
    4093               0 :       return ONIGERR_EMPTY_CHAR_CLASS;
    4094                 : 
    4095               0 :     CC_ESC_WARN(env, (UChar* )"]");
    4096               0 :     r = tok->type = TK_CHAR;  /* allow []...] */
    4097                 :   }
    4098                 : 
    4099              93 :   *np = node = node_new_cclass();
    4100              93 :   CHECK_NULL_RETURN_VAL(node, ONIGERR_MEMORY);
    4101              93 :   cc = &(NCCLASS(node));
    4102                 : 
    4103              93 :   and_start = 0;
    4104              93 :   state = CCS_START;
    4105              93 :   p = *src;
    4106             390 :   while (r != TK_CC_CLOSE) {
    4107             204 :     fetched = 0;
    4108             204 :     switch (r) {
    4109                 :     case TK_CHAR:
    4110             113 :       len = ONIGENC_CODE_TO_MBCLEN(env->enc, tok->u.c);
    4111             113 :       if (len > 1) {
    4112              28 :         in_type = CCV_CODE_POINT;
    4113                 :       }
    4114                 :       else {
    4115              85 :       sb_char:
    4116              85 :         in_type = CCV_SB;
    4117                 :       }
    4118             113 :       v = (OnigCodePoint )tok->u.c;
    4119             113 :       in_israw = 0;
    4120             113 :       goto val_entry2;
    4121                 :       break;
    4122                 : 
    4123                 :     case TK_RAW_BYTE:
    4124                 :       /* tok->base != 0 : octal or hexadec. */
    4125               0 :       if (! ONIGENC_IS_SINGLEBYTE(env->enc) && tok->base != 0) {
    4126                 :         UChar buf[ONIGENC_CODE_TO_MBC_MAXLEN];
    4127               0 :         UChar* bufe = buf + ONIGENC_CODE_TO_MBC_MAXLEN;
    4128               0 :         UChar* psave = p;
    4129               0 :         int i, base = tok->base;
    4130                 : 
    4131               0 :         buf[0] = tok->u.c;
    4132               0 :         for (i = 1; i < ONIGENC_MBC_MAXLEN(env->enc); i++) {
    4133               0 :           r = fetch_token_in_cc(tok, &p, end, env);
    4134               0 :           if (r < 0) goto err;
    4135               0 :           if (r != TK_RAW_BYTE || tok->base != base) {
    4136               0 :             fetched = 1;
    4137               0 :             break;
    4138                 :           }
    4139               0 :           buf[i] = tok->u.c;
    4140                 :         }
    4141                 : 
    4142               0 :         if (i < ONIGENC_MBC_MINLEN(env->enc)) {
    4143               0 :           r = ONIGERR_TOO_SHORT_MULTI_BYTE_STRING;
    4144               0 :           goto err;
    4145                 :         }
    4146                 : 
    4147               0 :         len = enc_len(env->enc, buf);
    4148               0 :         if (i < len) {
    4149               0 :           r = ONIGERR_TOO_SHORT_MULTI_BYTE_STRING;
    4150               0 :           goto err;
    4151                 :         }
    4152               0 :         else if (i > len) { /* fetch back */
    4153               0 :           p = psave;
    4154               0 :           for (i = 1; i < len; i++) {
    4155               0 :             r = fetch_token_in_cc(tok, &p, end, env);
    4156                 :           }
    4157               0 :           fetched = 0;
    4158                 :         }
    4159                 : 
    4160               0 :         if (i == 1) {
    4161               0 :           v = (OnigCodePoint )buf[0];
    4162               0 :           goto raw_single;
    4163                 :         }
    4164                 :         else {
    4165               0 :           v = ONIGENC_MBC_TO_CODE(env->enc, buf, bufe);
    4166               0 :           in_type = CCV_CODE_POINT;
    4167                 :         }
    4168                 :       }
    4169                 :       else {
    4170               0 :         v = (OnigCodePoint )tok->u.c;
    4171               0 :       raw_single:
    4172               0 :         in_type = CCV_SB;
    4173                 :       }
    4174               0 :       in_israw = 1;
    4175               0 :       goto val_entry2;
    4176                 :       break;
    4177                 : 
    4178                 :     case TK_CODE_POINT:
    4179               0 :       v = tok->u.code;
    4180               0 :       in_israw = 1;
    4181               1 :     val_entry:
    4182               1 :       len = ONIGENC_CODE_TO_MBCLEN(env->enc, v);
    4183               1 :       if (len < 0) {
    4184               0 :         r = len;
    4185               0 :         goto err;
    4186                 :       }
    4187               1 :       in_type = (len == 1 ? CCV_SB : CCV_CODE_POINT);
    4188             114 :     val_entry2:
    4189             114 :       r = next_state_val(cc, &vs, v, &val_israw, in_israw, in_type, &val_type,
    4190                 :                          &state, env);
    4191             114 :       if (r != 0) goto err;
    4192             114 :       break;
    4193                 : 
    4194                 :     case TK_POSIX_BRACKET_OPEN:
    4195              41 :       r = parse_posix_bracket(cc, &p, end, env);
    4196              41 :       if (r < 0) goto err;
    4197              41 :       if (r == 1) {  /* is not POSIX bracket */
    4198               0 :         CC_ESC_WARN(env, (UChar* )"[");
    4199               0 :         p = tok->backp;
    4200               0 :         v = (OnigCodePoint )tok->u.c;
    4201               0 :         in_israw = 0;
    4202               0 :         goto val_entry;
    4203                 :       }
    4204              41 :       goto next_class;
    4205                 :       break;
    4206                 : 
    4207                 :     case TK_CHAR_TYPE:
    4208                 :       {
    4209                 :         int ctype, not;
    4210               1 :         ctype = parse_ctype_to_enc_ctype(tok->u.subtype, &not);
    4211               1 :         r = add_ctype_to_cc(cc, ctype, not, env);
    4212               1 :         if (r != 0) return r;
    4213                 :       }
    4214                 : 
    4215              42 :     next_class:
    4216              42 :       r = next_state_class(cc, &vs, &val_type, &state, env);
    4217              42 :       if (r != 0) goto err;
    4218              42 :       break;
    4219                 : 
    4220                 :     case TK_CHAR_PROPERTY:
    4221                 :       {
    4222                 :         int ctype;
    4223                 : 
    4224               0 :         ctype = fetch_char_property_to_ctype(&p, end, env);
    4225               0 :         if (ctype < 0) return ctype;
    4226               0 :         r = add_ctype_to_cc(cc, ctype, tok->u.prop.not, env);
    4227               0 :         if (r != 0) return r;
    4228               0 :         goto next_class;
    4229                 :       }
    4230                 :       break;
    4231                 : 
    4232                 :     case TK_CC_RANGE:
    4233              49 :       if (state == CCS_VALUE) {
    4234              48 :         r = fetch_token_in_cc(tok, &p, end, env);
    4235              48 :         if (r < 0) goto err;
    4236              48 :         fetched = 1;
    4237              48 :         if (r == TK_CC_CLOSE) { /* allow [x-] */
    4238               0 :         range_end_val:
    4239               0 :           v = (OnigCodePoint )'-';
    4240               0 :           in_israw = 0;
    4241               0 :           goto val_entry;
    4242                 :         }
    4243              48 :         else if (r == TK_CC_AND) {
    4244               0 :           CC_ESC_WARN(env, (UChar* )"-");
    4245               0 :           goto range_end_val;
    4246                 :         }
    4247              48 :         state = CCS_RANGE;
    4248                 :       }
    4249               1 :       else if (state == CCS_START) {
    4250                 :         /* [-xa] is allowed */
    4251               1 :         v = (OnigCodePoint )tok->u.c;
    4252               1 :         in_israw = 0;
    4253                 : 
    4254               1 :         r = fetch_token_in_cc(tok, &p, end, env);
    4255               1 :         if (r < 0) goto err;
    4256               1 :         fetched = 1;
    4257                 :         /* [--x] or [a&&-x] is warned. */
    4258               1 :         if (r == TK_CC_RANGE || and_start != 0)
    4259               0 :           CC_ESC_WARN(env, (UChar* )"-");
    4260                 : 
    4261               1 :         goto val_entry;
    4262                 :       }
    4263               0 :       else if (state == CCS_RANGE) {
    4264               0 :         CC_ESC_WARN(env, (UChar* )"-");
    4265               0 :         goto sb_char;  /* [!--x] is allowed */
    4266                 :       }
    4267                 :       else { /* CCS_COMPLETE */
    4268               0 :         r = fetch_token_in_cc(tok, &p, end, env);
    4269               0 :         if (r < 0) goto err;
    4270               0 :         fetched = 1;
    4271               0 :         if (r == TK_CC_CLOSE) goto range_end_val; /* allow [a-b-] */
    4272               0 :         else if (r == TK_CC_AND) {
    4273               0 :           CC_ESC_WARN(env, (UChar* )"-");
    4274               0 :           goto range_end_val;
    4275                 :         }
    4276                 :         
    4277               0 :         if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_DOUBLE_RANGE_OP_IN_CC)) {
    4278               0 :           CC_ESC_WARN(env, (UChar* )"-");
    4279               0 :           goto sb_char;   /* [0-9-a] is allowed as [0-9\-a] */
    4280                 :         }
    4281               0 :         r = ONIGERR_UNMATCHED_RANGE_SPECIFIER_IN_CHAR_CLASS;
    4282               0 :         goto err;
    4283                 :       }
    4284              48 :       break;
    4285                 : 
    4286                 :     case TK_CC_CC_OPEN: /* [ */
    4287                 :       {
    4288                 :         Node *anode;
    4289                 :         CClassNode* acc;
    4290                 : 
    4291               0 :         r = parse_char_class(&anode, tok, &p, end, env);
    4292               0 :         if (r != 0) goto cc_open_err;
    4293               0 :         acc = &(NCCLASS(anode));
    4294               0 :         r = or_cclass(cc, acc, env->enc);
    4295                 : 
    4296               0 :         onig_node_free(anode);
    4297               0 :       cc_open_err:
    4298               0 :         if (r != 0) goto err;
    4299                 :       }
    4300               0 :       break;
    4301                 : 
    4302                 :     case TK_CC_AND: /* && */
    4303                 :       {
    4304               0 :         if (state == CCS_VALUE) {
    4305               0 :           r = next_state_val(cc, &vs, 0, &val_israw, 0, val_type,
    4306                 :                              &val_type, &state, env);
    4307               0 :           if (r != 0) goto err;
    4308                 :         }
    4309                 :         /* initialize local variables */
    4310               0 :         and_start = 1;
    4311               0 :         state = CCS_START;
    4312                 : 
    4313               0 :         if (IS_NOT_NULL(prev_cc)) {
    4314               0 :           r = and_cclass(prev_cc, cc, env->enc);
    4315               0 :           if (r != 0) goto err;
    4316               0 :           bbuf_free(cc->mbuf);
    4317                 :         }
    4318                 :         else {
    4319               0 :           prev_cc = cc;
    4320               0 :           cc = &work_cc;
    4321                 :         }
    4322               0 :         initialize_cclass(cc);
    4323                 :       }
    4324               0 :       break;
    4325                 : 
    4326                 :     case TK_EOT:
    4327               0 :       r = ONIGERR_PREMATURE_END_OF_CHAR_CLASS;
    4328               0 :       goto err;
    4329                 :       break;
    4330                 :     default:
    4331               0 :       r = ONIGERR_PARSER_BUG;
    4332               0 :       goto err;
    4333                 :       break;
    4334                 :     }
    4335                 : 
    4336             204 :     if (fetched)
    4337              49 :       r = tok->type;
    4338                 :     else {
    4339             155 :       r = fetch_token_in_cc(tok, &p, end, env);
    4340             155 :       if (r < 0) goto err;
    4341                 :     }
    4342                 :   }
    4343                 : 
    4344              93 :   if (state == CCS_VALUE) {
    4345              46 :     r = next_state_val(cc, &vs, 0, &val_israw, 0, val_type,
    4346                 :                        &val_type, &state, env);
    4347              46 :     if (r != 0) goto err;
    4348                 :   }
    4349                 : 
    4350              93 :   if (IS_NOT_NULL(prev_cc)) {
    4351               0 :     r = and_cclass(prev_cc, cc, env->enc);
    4352               0 :     if (r != 0) goto err;
    4353               0 :     bbuf_free(cc->mbuf);
    4354               0 :     cc = prev_cc;
    4355                 :   }
    4356                 : 
    4357              93 :   if (neg != 0)
    4358               1 :     CCLASS_SET_NOT(cc);
    4359                 :   else
    4360              92 :     CCLASS_CLEAR_NOT(cc);
    4361              93 :   if (IS_CCLASS_NOT(cc) &&
    4362                 :       IS_SYNTAX_BV(env->syntax, ONIG_SYN_NOT_NEWLINE_IN_NEGATIVE_CC)) {
    4363                 :     int is_empty;
    4364                 : 
    4365               0 :     is_empty = (IS_NULL(cc->mbuf) ? 1 : 0);
    4366               0 :     if (is_empty != 0)
    4367               0 :       BITSET_IS_EMPTY(cc->bs, is_empty);
    4368                 : 
    4369               0 :     if (is_empty == 0) {
    4370                 : #define NEWLINE_CODE    0x0a
    4371                 : 
    4372               0 :       if (ONIGENC_IS_CODE_NEWLINE(env->enc, NEWLINE_CODE)) {
    4373               0 :         if (ONIGENC_CODE_TO_MBCLEN(env->enc, NEWLINE_CODE) == 1)
    4374               0 :           BITSET_SET_BIT(cc->bs, NEWLINE_CODE);
    4375                 :         else
    4376               0 :           add_code_range(&(cc->mbuf), env, NEWLINE_CODE, NEWLINE_CODE);
    4377                 :       }
    4378                 :     }
    4379                 :   }
    4380              93 :   *src = p;
    4381              93 :   return 0;
    4382                 : 
    4383               0 :  err:
    4384               0 :   if (cc != &(NCCLASS(*np)))
    4385               0 :     bbuf_free(cc->mbuf);
    4386               0 :   onig_node_free(*np);
    4387               0 :   return r;
    4388                 : }
    4389                 : 
    4390                 : static int parse_subexp(Node** top, OnigToken* tok, int term,
    4391                 :                         UChar** src, UChar* end, ScanEnv* env);
    4392                 : 
    4393                 : static int
    4394                 : parse_effect(Node** np, OnigToken* tok, int term, UChar** src, UChar* end,
    4395                 :              ScanEnv* env)
    4396              61 : {
    4397                 :   int r, num;
    4398                 :   int list_capture;
    4399                 :   Node *target;
    4400                 :   OnigOptionType option;
    4401              61 :   OnigEncoding enc = env->enc;
    4402                 :   OnigCodePoint c;
    4403              61 :   UChar* p = *src;
    4404                 :   PFETCH_READY;
    4405                 : 
    4406              61 :   *np = NULL;
    4407              61 :   if (PEND) return ONIGERR_END_PATTERN_WITH_UNMATCHED_PARENTHESIS;
    4408                 : 
    4409              61 :   option = env->option;
    4410              61 :   if (PPEEK_IS('?') &&
    4411                 :       IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_GROUP_EFFECT)) {
    4412               0 :     PINC;
    4413               0 :     if (PEND) return ONIGERR_END_PATTERN_IN_GROUP;
    4414                 : 
    4415               0 :     PFETCH(c);
    4416               0 :     switch (c) {
    4417                 :     case ':':   /* (?:...) grouping only */
    4418               0 :     group:
    4419               0 :       r = fetch_token(tok, &p, end, env);
    4420               0 :       if (r < 0) return r;
    4421               0 :       r = parse_subexp(np, tok, term, &p, end, env);
    4422               0 :       if (r < 0) return r;
    4423               0 :       *src = p;
    4424               0 :       return 1; /* group */
    4425                 :       break;
    4426                 : 
    4427                 :     case '=':
    4428               0 :       *np = onig_node_new_anchor(ANCHOR_PREC_READ);
    4429               0 :       break;
    4430                 :     case '!':  /*         preceding read */
    4431               0 :       *np = onig_node_new_anchor(ANCHOR_PREC_READ_NOT);
    4432               0 :       break;
    4433                 :     case '>':            /* (?>...) stop backtrack */
    4434               0 :       *np = node_new_effect(EFFECT_STOP_BACKTRACK);
    4435               0 :       break;
    4436                 : 
    4437                 :     case '<':   /* look behind (?<=...), (?<!...) */
    4438               0 :       PFETCH(c);
    4439               0 :       if (c == '=')
    4440               0 :         *np = onig_node_new_anchor(ANCHOR_LOOK_BEHIND);
    4441               0 :       else if (c == '!')
    4442               0 :         *np = onig_node_new_anchor(ANCHOR_LOOK_BEHIND_NOT);
    4443                 : #ifdef USE_NAMED_GROUP
    4444               0 :       else if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP)) {
    4445                 :         UChar *name;
    4446                 :         UChar *name_end;
    4447                 : 
    4448               0 :         PUNFETCH;
    4449               0 :         list_capture = 0;
    4450                 : 
    4451               0 :       named_group:
    4452               0 :         name = p;
    4453               0 :         r = fetch_name(&p, end, &name_end, env, 0);
    4454               0 :         if (r < 0) return r;
    4455                 : 
    4456               0 :         num = scan_env_add_mem_entry(env);
    4457               0 :         if (num < 0) return num;
    4458               0 :         if (list_capture != 0 && num >= BIT_STATUS_BITS_NUM)
    4459               0 :           return ONIGERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY;
    4460                 : 
    4461               0 :         r = name_add(env->reg, name, name_end, num, env);
    4462               0 :         if (r != 0) return r;
    4463               0 :         *np = node_new_effect_memory(env->option, 1);
    4464               0 :         CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
    4465               0 :         NEFFECT(*np).regnum = num;
    4466               0 :         if (list_capture != 0)
    4467               0 :           BIT_STATUS_ON_AT_SIMPLE(env->capture_history, num);
    4468               0 :         env->num_named++;
    4469                 :       }
    4470                 : #endif
    4471                 :       else
    4472               0 :         return ONIGERR_UNDEFINED_GROUP_OPTION;
    4473               0 :       break;
    4474                 : 
    4475                 :     case '@':
    4476               0 :       if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_ATMARK_CAPTURE_HISTORY)) {
    4477                 : #ifdef USE_NAMED_GROUP
    4478               0 :         if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP)) {
    4479               0 :           PFETCH(c);
    4480               0 :           if (c == '<') {
    4481               0 :             list_capture = 1;
    4482               0 :             goto named_group; /* (?@<name>...) */
    4483                 :           }
    4484               0 :           PUNFETCH;
    4485                 :         }
    4486                 : #endif
    4487               0 :         *np = node_new_effect_memory(env->option, 0);
    4488               0 :         CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
    4489               0 :         num = scan_env_add_mem_entry(env);
    4490               0 :         if (num < 0) {
    4491               0 :           onig_node_free(*np);
    4492               0 :           return num;
    4493                 :         }
    4494               0 :         else if (num >= BIT_STATUS_BITS_NUM) {
    4495               0 :           onig_node_free(*np);
    4496               0 :           return ONIGERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY;
    4497                 :         }
    4498               0 :         NEFFECT(*np).regnum = num;
    4499               0 :         BIT_STATUS_ON_AT_SIMPLE(env->capture_history, num);
    4500                 :       }
    4501                 :       else {
    4502               0 :         return ONIGERR_UNDEFINED_GROUP_OPTION;
    4503                 :       }
    4504               0 :       break;
    4505                 : 
    4506                 : #ifdef USE_POSIXLINE_OPTION
    4507                 :     case 'p':
    4508                 : #endif
    4509                 :     case '-': case 'i': case 'm': case 's': case 'x':
    4510                 :       {
    4511               0 :         int neg = 0;
    4512                 : 
    4513                 :         while (1) {
    4514               0 :           switch (c) {
    4515                 :           case ':':
    4516                 :           case ')':
    4517               0 :           break;
    4518                 : 
    4519               0 :           case '-':  neg = 1; break;
    4520               0 :           case 'x':  ONOFF(option, ONIG_OPTION_EXTEND,     neg); break;
    4521               0 :           case 'i':  ONOFF(option, ONIG_OPTION_IGNORECASE, neg); break;
    4522                 :           case 's':
    4523               0 :             if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL)) {
    4524               0 :               ONOFF(option, ONIG_OPTION_MULTILINE,  neg);
    4525                 :             }
    4526                 :             else
    4527               0 :               return ONIGERR_UNDEFINED_GROUP_OPTION;
    4528               0 :             break;
    4529                 : 
    4530                 :           case 'm':
    4531               0 :             if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL)) {
    4532               0 :               ONOFF(option, ONIG_OPTION_SINGLELINE, (neg == 0 ? 1 : 0));
    4533                 :             }
    4534               0 :             else if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_RUBY)) {
    4535               0 :               ONOFF(option, ONIG_OPTION_MULTILINE,  neg);
    4536                 :             }
    4537                 :             else
    4538               0 :               return ONIGERR_UNDEFINED_GROUP_OPTION;
    4539               0 :             break;
    4540                 : #ifdef USE_POSIXLINE_OPTION
    4541                 :           case 'p':
    4542                 :             ONOFF(option, ONIG_OPTION_MULTILINE|ONIG_OPTION_SINGLELINE, neg);
    4543                 :             break;
    4544                 : #endif
    4545                 :           default:
    4546               0 :             return ONIGERR_UNDEFINED_GROUP_OPTION;
    4547                 :           }
    4548                 : 
    4549               0 :           if (c == ')') {
    4550               0 :             *np = node_new_option(option);
    4551               0 :             CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
    4552               0 :             *src = p;
    4553               0 :             return 2; /* option only */
    4554                 :           }
    4555               0 :           else if (c == ':') {
    4556               0 :             OnigOptionType prev = env->option;
    4557                 : 
    4558               0 :             env->option     = option;
    4559               0 :             r = fetch_token(tok, &p, end, env);
    4560               0 :             if (r < 0) return r;
    4561               0 :             r = parse_subexp(&target, tok, term, &p, end, env);
    4562               0 :             env->option = prev;
    4563               0 :             if (r < 0) return r;
    4564               0 :             *np = node_new_option(option);
    4565               0 :             CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
    4566               0 :             NEFFECT(*np).target = target;
    4567               0 :             *src = p;
    4568               0 :             return 0;
    4569                 :           }
    4570                 : 
    4571               0 :           if (PEND) return ONIGERR_END_PATTERN_IN_GROUP;
    4572               0 :           PFETCH(c);
    4573               0 :         }
    4574                 :       }
    4575                 :       break;
    4576                 : 
    4577                 :     default:
    4578               0 :       return ONIGERR_UNDEFINED_GROUP_OPTION;
    4579                 :     }
    4580                 :   }
    4581                 :   else {
    4582              61 :     if (ONIG_IS_OPTION_ON(env->option, ONIG_OPTION_DONT_CAPTURE_GROUP))
    4583               0 :       goto group;
    4584                 : 
    4585              61 :     *np = node_new_effect_memory(env->option, 0);
    4586              61 :     CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
    4587              61 :     num = scan_env_add_mem_entry(env);
    4588              61 :     if (num < 0) return num;
    4589              61 :     NEFFECT(*np).regnum = num;
    4590                 :   }
    4591                 : 
    4592              61 :   CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
    4593              61 :   r = fetch_token(tok, &p, end, env);
    4594              61 :   if (r < 0) return r;
    4595              61 :   r = parse_subexp(&target, tok, term, &p, end, env);
    4596              61 :   if (r < 0) return r;
    4597                 : 
    4598              61 :   if (NTYPE(*np) == N_ANCHOR)
    4599               0 :     NANCHOR(*np).target = target;
    4600                 :   else {
    4601              61 :     NEFFECT(*np).target = target;
    4602              61 :     if (NEFFECT(*np).type == EFFECT_MEMORY) {
    4603                 :       /* Don't move this to previous of parse_subexp() */
    4604              61 :       r = scan_env_set_mem_node(env, NEFFECT(*np).regnum, *np);
    4605              61 :       if (r != 0) return r;
    4606                 :     }
    4607                 :   }
    4608                 : 
    4609              61 :   *src = p;
    4610              61 :   return 0;
    4611                 : }
    4612                 : 
    4613                 : static const char* PopularQStr[] = {
    4614                 :   "?", "*", "+", "??", "*?", "+?"
    4615                 : };
    4616                 : 
    4617                 : static const char* ReduceQStr[] = {
    4618                 :   "", "", "*", "*?", "??", "+ and ??", "+? and ?"
    4619                 : };
    4620                 : 
    4621                 : static int
    4622                 : set_qualifier(Node* qnode, Node* target, int group, ScanEnv* env)
    4623             126 : {
    4624                 :   QualifierNode* qn;
    4625                 : 
    4626             126 :   qn = &(NQUALIFIER(qnode));
    4627             126 :   if (qn->lower == 1 && qn->upper == 1) {
    4628               0 :     return 1;
    4629                 :   }
    4630                 : 
    4631             126 :   switch (NTYPE(target)) {
    4632                 :   case N_STRING:
    4633              23 :     if (! group) {
    4634              23 :       StrNode* sn = &(NSTRING(target));
    4635              23 :       if (str_node_can_be_split(sn, env->enc)) {
    4636               9 :         Node* n = str_node_split_last_char(sn, env->enc);
    4637               9 :         if (IS_NOT_NULL(n)) {
    4638               9 :           qn->target = n;
    4639               9 :           return 2;
    4640                 :         }
    4641                 :       }
    4642                 :     }
    4643              14 :     break;
    4644                 : 
    4645                 :   case N_QUALIFIER:
    4646                 :     { /* check redundant double repeat. */
    4647                 :       /* verbose warn (?:.?)? etc... but not warn (.?)? etc... */
    4648               0 :       QualifierNode* qnt = &(NQUALIFIER(target));
    4649               0 :       int nestq_num   = popular_qualifier_num(qn);
    4650               0 :       int targetq_num = popular_qualifier_num(qnt);
    4651                 : 
    4652                 : #ifdef USE_WARNING_REDUNDANT_NESTED_REPEAT_OPERATOR
    4653               0 :       if (!IS_QUALIFIER_BY_NUMBER(qn) && !IS_QUALIFIER_BY_NUMBER(qnt) &&
    4654                 :           IS_SYNTAX_BV(env->syntax, ONIG_SYN_WARN_REDUNDANT_NESTED_REPEAT)) {
    4655                 :         UChar buf[WARN_BUFSIZE];
    4656                 : 
    4657               0 :         switch(ReduceTypeTable[targetq_num][nestq_num]) {
    4658                 :         case RQ_ASIS:
    4659               0 :           break;
    4660                 : 
    4661                 :         case RQ_DEL:
    4662               0 :           if (onig_verb_warn != onig_null_warn) {
    4663               0 :             onig_snprintf_with_pattern(buf, WARN_BUFSIZE, env->enc,
    4664                 :                                  env->pattern, env->pattern_end,
    4665                 :                                  (UChar* )"redundant nested repeat operator");
    4666               0 :             (*onig_verb_warn)((char* )buf);
    4667                 :           }
    4668               0 :           goto warn_exit;
    4669                 :           break;
    4670                 : 
    4671                 :         default:
    4672               0 :           if (onig_verb_warn != onig_null_warn) {
    4673               0 :             onig_snprintf_with_pattern(buf, WARN_BUFSIZE, env->enc,
    4674                 :                                        env->pattern, env->pattern_end,
    4675                 :             (UChar* )"nested repeat operator %s and %s was replaced with '%s'",
    4676                 :             PopularQStr[targetq_num], PopularQStr[nestq_num],
    4677                 :             ReduceQStr[ReduceTypeTable[targetq_num][nestq_num]]);
    4678               0 :             (*onig_verb_warn)((char* )buf);
    4679                 :           }
    4680               0 :           goto warn_exit;
    4681                 :           break;
    4682                 :         }
    4683                 :       }
    4684                 : 
    4685               0 :     warn_exit:
    4686                 : #endif
    4687               0 :       if (targetq_num >= 0) {
    4688               0 :         if (nestq_num >= 0) {
    4689               0 :           onig_reduce_nested_qualifier(qnode, target);
    4690               0 :           goto q_exit;
    4691                 :         }
    4692               0 :         else if (targetq_num == 1 || targetq_num == 2) { /* * or + */
    4693                 :           /* (?:a*){n,m}, (?:a+){n,m} => (?:a*){n,n}, (?:a+){n,n} */
    4694               0 :           if (! IS_REPEAT_INFINITE(qn->upper) && qn->upper > 1 && qn->greedy) {
    4695               0 :             qn->upper = (qn->lower == 0 ? 1 : qn->lower);
    4696                 :           }
    4697                 :         }
    4698                 :       }
    4699                 :     }
    4700                 :     break;
    4701                 : 
    4702                 :   default:
    4703                 :     break;
    4704                 :   }
    4705                 : 
    4706             117 :   qn->target = target;
    4707             117 :  q_exit:
    4708             117 :   return 0;
    4709                 : }
    4710                 : 
    4711                 : static int
    4712                 : make_compound_alt_node_from_cc(OnigAmbigType ambig_flag, OnigEncoding enc,
    4713                 :                                CClassNode* cc, Node** root)
    4714               0 : {
    4715                 :   int r, i, j, k, clen, len, ncode, n;
    4716                 :   UChar buf[ONIGENC_CODE_TO_MBC_MAXLEN];
    4717               0 :   Node **ptail, *snode = NULL_NODE;
    4718                 :   const OnigCompAmbigCodes* ccs;
    4719                 :   const OnigCompAmbigCodeItem* ci;
    4720                 :   OnigAmbigType amb;
    4721                 : 
    4722               0 :   n = 0;
    4723               0 :   *root = NULL_NODE;
    4724               0 :   ptail = root;
    4725                 : 
    4726                 : 
    4727               0 :   for (amb = 0x01; amb <= ONIGENC_AMBIGUOUS_MATCH_LIMIT; amb <<= 1) {
    4728               0 :     if ((amb & ambig_flag) == 0)  continue;
    4729                 : 
    4730               0 :     ncode = ONIGENC_GET_ALL_COMP_AMBIG_CODES(enc, amb, &ccs);
    4731               0 :     for (i = 0; i < ncode; i++) {
    4732               0 :       if (onig_is_code_in_cc(enc, ccs[i].code, cc)) {
    4733               0 :         for (j = 0; j < ccs[i].n; j++) {
    4734               0 :           ci = &(ccs[i].items[j]);
    4735               0 :           if (ci->len > 1) { /* compound only */
    4736               0 :             if (IS_CCLASS_NOT(cc)) clear_not_flag_cclass(cc, enc);
    4737                 : 
    4738               0 :             clen = ci->len;
    4739               0 :             for (k = 0; k < clen; k++) {
    4740               0 :               len = ONIGENC_CODE_TO_MBC(enc, ci->code[k], buf);
    4741                 : 
    4742               0 :               if (k == 0) {
    4743               0 :                 snode = node_new_str_raw(buf, buf + len);
    4744               0 :                 CHECK_NULL_RETURN_VAL(snode, ONIGERR_MEMORY);
    4745                 :               }
    4746                 :               else {
    4747               0 :                 r = onig_node_str_cat(snode, buf, buf + len);
    4748               0 :                 if (r < 0) return r;
    4749                 :               }
    4750                 :             }
    4751                 : 
    4752               0 :             *ptail = node_new_alt(snode, NULL_NODE);
    4753               0 :             CHECK_NULL_RETURN_VAL(*ptail, ONIGERR_MEMORY);
    4754               0 :             ptail = &(NCONS(*ptail).right);
    4755               0 :             n++;
    4756                 :         }
    4757                 :         }
    4758                 :       }
    4759                 :     }
    4760                 :   }
    4761                 : 
    4762               0 :   return n;
    4763                 : }
    4764                 : 
    4765                 : 
    4766                 : #ifdef USE_SHARED_CCLASS_TABLE
    4767                 : 
    4768                 : #define THRESHOLD_RANGE_NUM_FOR_SHARE_CCLASS     8
    4769                 : 
    4770                 : /* for ctype node hash table */
    4771                 : 
    4772                 : typedef struct {
    4773                 :   OnigEncoding enc;
    4774                 :   int not;
    4775                 :   int type;
    4776                 : } type_cclass_key;
    4777                 : 
    4778                 : static int type_cclass_cmp(type_cclass_key* x, type_cclass_key* y)
    4779               0 : {
    4780               0 :   if (x->type != y->type) return 1;
    4781               0 :   if (x->enc  != y->enc)  return 1;
    4782               0 :   if (x->not  != y->not)  return 1;
    4783               0 :   return 0;
    4784                 : }
    4785                 : 
    4786                 : static int type_cclass_hash(type_cclass_key* key)
    4787              10 : {
    4788                 :   int i, val;
    4789                 :   unsigned char *p;
    4790                 : 
    4791              10 :   val = 0;
    4792                 : 
    4793              10 :   p = (unsigned char* )&(key->enc);
    4794              50 :   for (i = 0; i < sizeof(key->enc); i++) {
    4795              40 :     val = val * 997 + (int )*p++;
    4796                 :   }
    4797                 : 
    4798              10 :   p = (unsigned char* )(&key->type);
    4799              50 :   for (i = 0; i < sizeof(key->type); i++) {
    4800              40 :     val = val * 997 + (int )*p++;
    4801                 :   }
    4802                 : 
    4803              10 :   val += key->not;
    4804              10 :   return val + (val >> 5);
    4805                 : }
    4806                 : 
    4807                 : static struct st_hash_type type_type_cclass_hash = {
    4808                 :     type_cclass_cmp,
    4809                 :     type_cclass_hash,
    4810                 : };
    4811                 : 
    4812                 : static st_table* OnigTypeCClassTable;
    4813                 : 
    4814                 : 
    4815                 : static int
    4816                 : i_free_shared_class(type_cclass_key* key, Node* node, void* arg)
    4817               6 : {
    4818               6 :   if (IS_NOT_NULL(node)) {
    4819               6 :     CClassNode* cc = &(NCCLASS(node));
    4820               6 :     if (IS_NOT_NULL(cc->mbuf)) xfree(cc->mbuf);
    4821               6 :     xfree(node);
    4822                 :   }
    4823                 : 
    4824               6 :   if (IS_NOT_NULL(key)) xfree(key);
    4825               6 :   return ST_DELETE;
    4826                 : }
    4827                 : 
    4828                 : extern int
    4829                 : onig_free_shared_cclass_table()
    4830           13597 : {
    4831           13597 :   if (IS_NOT_NULL(OnigTypeCClassTable)) {
    4832               2 :     onig_st_foreach(OnigTypeCClassTable, i_free_shared_class, 0);
    4833               2 :     xfree(OnigTypeCClassTable);
    4834               2 :     OnigTypeCClassTable = NULL;
    4835                 :   }
    4836                 : 
    4837           13597 :   return 0;
    4838                 : }
    4839                 : 
    4840                 : #endif /* USE_SHARED_CCLASS_TABLE */
    4841                 : 
    4842                 : 
    4843                 : static int
    4844                 : parse_exp(Node** np, OnigToken* tok, int term,
    4845                 :           UChar** src, UChar* end, ScanEnv* env)
    4846             350 : {
    4847             350 :   int r, len, group = 0;
    4848                 :   Node* qn;
    4849                 :   Node** targetp;
    4850                 : 
    4851             350 :   *np = NULL;
    4852             350 :   if (tok->type == term)
    4853               2 :     goto end_of_token;
    4854                 : 
    4855             348 :   switch (tok->type) {
    4856                 :   case TK_ALT:
    4857                 :   case TK_EOT:
    4858               2 :   end_of_token:
    4859               2 :   *np = node_new_empty();
    4860               2 :   return tok->type;
    4861                 :   break;
    4862                 : 
    4863                 :   case TK_SUBEXP_OPEN:
    4864              61 :     r = parse_effect(np, tok, TK_SUBEXP_CLOSE, src, end, env);
    4865              61 :     if (r < 0) return r;
    4866              61 :     if (r == 1) group = 1;
    4867              61 :     else if (r == 2) { /* option only */
    4868                 :       Node* target;
    4869               0 :       OnigOptionType prev = env->option;
    4870                 : 
    4871               0 :       env->option = NEFFECT(*np).option;
    4872               0 :       r = fetch_token(tok, src, end, env);
    4873               0 :       if (r < 0) return r;
    4874               0 :       r = parse_subexp(&target, tok, term, src, end, env);
    4875               0 :       env->option = prev;
    4876               0 :       if (r < 0) return r;
    4877               0 :       NEFFECT(*np).target = target;     
    4878               0 :       return tok->type;
    4879                 :     }
    4880              61 :     break;
    4881                 : 
    4882                 :   case TK_SUBEXP_CLOSE:
    4883               0 :     if (! IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_UNMATCHED_CLOSE_SUBEXP))
    4884               0 :       return ONIGERR_UNMATCHED_CLOSE_PARENTHESIS;
    4885                 : 
    4886               0 :     if (tok->escaped) goto tk_raw_byte;
    4887               0 :     else goto tk_byte;
    4888                 :     break;
    4889                 : 
    4890                 :   case TK_STRING:
    4891             140 :   tk_byte:
    4892                 :     {
    4893             140 :       *np = node_new_str(tok->backp, *src);
    4894             140 :       CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
    4895                 : 
    4896                 :       while (1) {
    4897             346 :         r = fetch_token(tok, src, end, env);
    4898             346 :         if (r < 0) return r;
    4899             346 :         if (r != TK_STRING) break;
    4900                 : 
    4901             206 :         r = onig_node_str_cat(*np, tok->backp, *src);
    4902             206 :         if (r < 0) return r;
    4903             206 :       }
    4904                 : 
    4905             140 :     string_end:
    4906             140 :       targetp = np;
    4907             140 :       goto repeat;
    4908                 :     }
    4909                 :     break;
    4910                 : 
    4911                 :   case TK_RAW_BYTE:
    4912               0 :   tk_raw_byte:
    4913                 :     {
    4914               0 :       *np = node_new_str_raw_char((UChar )tok->u.c);
    4915               0 :       CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
    4916               0 :       len = 1;
    4917                 :       while (1) {
    4918               0 :         r = fetch_token(tok, src, end, env);
    4919               0 :         if (r < 0) return r;
    4920               0 :         if (r != TK_RAW_BYTE) {
    4921                 : #ifndef NUMBERED_CHAR_IS_NOT_CASE_AMBIG
    4922               0 :           if (len >= enc_len(env->enc, NSTRING(*np).s)) {
    4923               0 :             NSTRING_CLEAR_RAW(*np);
    4924                 :           }
    4925                 : #endif
    4926               0 :           goto string_end;
    4927                 :         }
    4928                 : 
    4929               0 :         r = node_str_cat_char(*np, (UChar )tok->u.c);
    4930               0 :         if (r < 0) return r;
    4931               0 :         len++;
    4932               0 :       }
    4933                 :     }
    4934                 :     break;
    4935                 : 
    4936                 :   case TK_CODE_POINT:
    4937                 :     {
    4938                 :       UChar buf[ONIGENC_CODE_TO_MBC_MAXLEN];
    4939               0 :       int num = ONIGENC_CODE_TO_MBC(env->enc, tok->u.code, buf);
    4940               0 :       if (num < 0) return num;
    4941                 : #ifdef NUMBERED_CHAR_IS_NOT_CASE_AMBIG
    4942                 :       *np = node_new_str_raw(buf, buf + num);
    4943                 : #else
    4944               0 :       *np = node_new_str(buf, buf + num);
    4945                 : #endif
    4946               0 :       CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
    4947                 :     }
    4948               0 :     break;
    4949                 : 
    4950                 :   case TK_QUOTE_OPEN:
    4951                 :     {
    4952                 :       OnigCodePoint end_op[2];
    4953                 :       UChar *qstart, *qend, *nextp;
    4954                 : 
    4955               0 :       end_op[0] = (OnigCodePoint )MC_ESC(env->enc);
    4956               0 :       end_op[1] = (OnigCodePoint )'E';
    4957               0 :       qstart = *src;
    4958               0 :       qend = find_str_position(end_op, 2, qstart, end, &nextp, env->enc);
    4959               0 :       if (IS_NULL(qend)) {
    4960               0 :         nextp = qend = end;
    4961                 :       }
    4962               0 :       *np = node_new_str(qstart, qend);
    4963               0 :       CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
    4964               0 :       *src = nextp;
    4965                 :     }
    4966               0 :     break;
    4967                 : 
    4968                 :   case TK_CHAR_TYPE:
    4969                 :     {
    4970              10 :       switch (tok->u.subtype) {
    4971                 :       case CTYPE_WORD:
    4972                 :       case CTYPE_NOT_WORD:
    4973               4 :         *np = node_new_ctype(tok->u.subtype);
    4974               4 :         CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
    4975               4 :         break;
    4976                 : 
    4977                 :       case CTYPE_WHITE_SPACE:
    4978                 :       case CTYPE_NOT_WHITE_SPACE:
    4979                 :       case CTYPE_DIGIT:
    4980                 :       case CTYPE_NOT_DIGIT:
    4981                 :       case CTYPE_XDIGIT:
    4982                 :       case CTYPE_NOT_XDIGIT:
    4983                 :         {
    4984                 :           CClassNode* cc;
    4985                 :           int ctype, not;
    4986                 : 
    4987                 : #ifdef USE_SHARED_CCLASS_TABLE
    4988                 :           const OnigCodePoint *sbr, *mbr;
    4989                 : 
    4990               6 :           ctype = parse_ctype_to_enc_ctype(tok->u.subtype, &not);
    4991               6 :           r = ONIGENC_GET_CTYPE_CODE_RANGE(env->enc, ctype, &sbr, &mbr);
    4992              12 :           if (r == 0 &&
    4993                 :               ONIGENC_CODE_RANGE_NUM(mbr)
    4994                 :               >= THRESHOLD_RANGE_NUM_FOR_SHARE_CCLASS) {
    4995                 :             type_cclass_key  key;
    4996                 :             type_cclass_key* new_key;
    4997                 : 
    4998               6 :             key.enc  = env->enc;
    4999               6 :             key.not  = not;
    5000               6 :             key.type = ctype;
    5001                 : 
    5002                 :             THREAD_ATOMIC_START;
    5003                 : 
    5004               6 :             if (IS_NULL(OnigTypeCClassTable)) {
    5005               2 :               OnigTypeCClassTable
    5006                 :                 = onig_st_init_table_with_size(&type_type_cclass_hash, 10);
    5007               2 :               if (IS_NULL(OnigTypeCClassTable)) {
    5008                 :                 THREAD_ATOMIC_END;
    5009               0 :                 return ONIGERR_MEMORY;
    5010                 :               }
    5011                 :             }
    5012                 :             else {
    5013               4 :               if (onig_st_lookup(OnigTypeCClassTable, (st_data_t )&key,
    5014                 :                                  (st_data_t* )np)) {
    5015                 :                 THREAD_ATOMIC_END;
    5016               0 :                 break;
    5017                 :               }
    5018                 :             }
    5019                 : 
    5020               6 :             *np = node_new_cclass_by_codepoint_range(not, sbr, mbr);
    5021               6 :             if (IS_NULL(*np)) {
    5022                 :               THREAD_ATOMIC_END;
    5023               0 :               return ONIGERR_MEMORY;
    5024                 :             }
    5025                 : 
    5026               6 :             CCLASS_SET_SHARE(&(NCCLASS(*np)));
    5027               6 :             new_key = (type_cclass_key* )xmalloc(sizeof(type_cclass_key));
    5028               6 :             onig_st_add_direct(OnigTypeCClassTable, (st_data_t )new_key,
    5029                 :                                (st_data_t )*np);
    5030                 :             
    5031                 :             THREAD_ATOMIC_END;
    5032                 :           }
    5033                 :           else {
    5034                 : #endif
    5035               0 :             ctype = parse_ctype_to_enc_ctype(tok->u.subtype, &not);
    5036               0 :             *np = node_new_cclass();
    5037               0 :             CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
    5038               0 :             cc = &(NCCLASS(*np));
    5039               0 :             add_ctype_to_cc(cc, ctype, 0, env);
    5040               0 :             if (not != 0) CCLASS_SET_NOT(cc);
    5041                 : #ifdef USE_SHARED_CCLASS_TABLE
    5042                 :           }
    5043                 : #endif
    5044                 :         }
    5045               6 :         break;
    5046                 : 
    5047                 :       default:
    5048               0 :         return ONIGERR_PARSER_BUG;
    5049                 :         break;
    5050                 :       }
    5051                 :     }
    5052              10 :     break;
    5053                 : 
    5054                 :   case TK_CHAR_PROPERTY:
    5055               0 :     r = parse_char_property(np, tok, src, end, env);
    5056               0 :     if (r != 0) return r;
    5057               0 :     break;
    5058                 : 
    5059                 :   case TK_CC_OPEN:
    5060                 :     {
    5061                 :       CClassNode* cc;
    5062                 : 
    5063              93 :       r = parse_char_class(np, tok, src, end, env);
    5064              93 :       if (r != 0) return r;
    5065                 : 
    5066              93 :       cc = &(NCCLASS(*np));
    5067                 : 
    5068              93 :       if (IS_IGNORECASE(env->option)) {
    5069                 :         int i, n, in_cc;
    5070                 :         const OnigPairAmbigCodes* ccs;
    5071               1 :         BitSetRef bs = cc->bs;
    5072                 :         OnigAmbigType amb;
    5073                 : 
    5074               3 :         for (amb = 0x01; amb <= ONIGENC_AMBIGUOUS_MATCH_LIMIT; amb <<= 1) {
    5075               2 :           if ((amb & env->ambig_flag) == 0)  continue;
    5076                 : 
    5077               2 :           n = ONIGENC_GET_ALL_PAIR_AMBIG_CODES(env->enc, amb, &ccs);
    5078             114 :           for (i = 0; i < n; i++) {
    5079             112 :             in_cc = onig_is_code_in_cc(env->enc, ccs[i].from, cc);
    5080                 : 
    5081             112 :             if ((in_cc != 0 && !IS_CCLASS_NOT(cc)) ||
    5082                 :                 (in_cc == 0 && IS_CCLASS_NOT(cc))) {
    5083               0 :               if (ONIGENC_MBC_MINLEN(env->enc) > 1 ||
    5084                 :                   ccs[i].from >= SINGLE_BYTE_SIZE) {
    5085                 :                 /* if (cc->not) clear_not_flag_cclass(cc, env->enc); */
    5086               0 :                 add_code_range(&(cc->mbuf), env, ccs[i].to, ccs[i].to);
    5087                 :               }
    5088                 :               else {
    5089               0 :                 if (BITSET_AT(bs, ccs[i].from)) {
    5090                 :                   /* /(?i:[^A-C])/.match("a") ==> fail. */
    5091               0 :                   BITSET_SET_BIT(bs, ccs[i].to);
    5092                 :                 }
    5093               0 :                 if (BITSET_AT(bs, ccs[i].to)) {
    5094               0 :                   BITSET_SET_BIT(bs, ccs[i].from);
    5095                 :                 }
    5096                 :               }
    5097                 :             }
    5098                 :           }
    5099                 :         }
    5100                 :       }
    5101                 : 
    5102              93 :       if (IS_IGNORECASE(env->option) &&
    5103                 :           (env->ambig_flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) {
    5104                 :         int res;
    5105                 :         Node *alt_root, *work;
    5106                 : 
    5107               0 :         res = make_compound_alt_node_from_cc(env->ambig_flag, env->enc,
    5108                 :                                              cc, &alt_root);
    5109               0 :         if (res < 0) return res;
    5110               0 :         if (res > 0) {
    5111               0 :           work = node_new_alt(*np, alt_root);
    5112               0 :           if (IS_NULL(work)) {
    5113               0 :             onig_node_free(alt_root);
    5114               0 :             return ONIGERR_MEMORY;
    5115                 :           }
    5116               0 :           *np = work;
    5117                 :         }
    5118                 :       }
    5119                 :     }
    5120              93 :     break;
    5121                 : 
    5122                 :   case TK_ANYCHAR:
    5123              26 :     *np = node_new_anychar();
    5124              26 :     CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
    5125              26 :     break;
    5126                 : 
    5127                 :   case TK_ANYCHAR_ANYTIME:
    5128               0 :     *np = node_new_anychar();
    5129               0 :     CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
    5130               0 :     qn = node_new_qualifier(0, REPEAT_INFINITE, 0);
    5131               0 :     CHECK_NULL_RETURN_VAL(qn, ONIGERR_MEMORY);
    5132               0 :     NQUALIFIER(qn).target = *np;
    5133               0 :     *np = qn;
    5134               0 :     break;
    5135                 : 
    5136                 :   case TK_BACKREF:
    5137               0 :     len = tok->u.backref.num;
    5138               0 :     *np = node_new_backref(len,
    5139                 :                    (len > 1 ? tok->u.backref.refs : &(tok->u.backref.ref1)),
    5140                 :                            tok->u.backref.by_name,
    5141                 : #ifdef USE_BACKREF_AT_LEVEL
    5142                 :                            tok->u.backref.exist_level,
    5143                 :                            tok->u.backref.level,
    5144                 : #endif
    5145                 :                            env);
    5146               0 :     CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
    5147               0 :     break;
    5148                 : 
    5149                 : #ifdef USE_SUBEXP_CALL
    5150                 :   case TK_CALL:
    5151               0 :     *np = node_new_call(tok->u.call.name, tok->u.call.name_end);
    5152               0 :     CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
    5153               0 :     env->num_call++;
    5154               0 :     break;
    5155                 : #endif
    5156                 : 
    5157                 :   case TK_ANCHOR:
    5158              18 :     *np = onig_node_new_anchor(tok->u.anchor);
    5159              18 :     break;
    5160                 : 
    5161                 :   case TK_OP_REPEAT:
    5162                 :   case TK_INTERVAL:
    5163               0 :     if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_CONTEXT_INDEP_REPEAT_OPS)) {
    5164               0 :       if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_CONTEXT_INVALID_REPEAT_OPS))
    5165               0 :         return ONIGERR_TARGET_OF_REPEAT_OPERATOR_NOT_SPECIFIED;
    5166                 :       else
    5167               0 :         *np = node_new_empty();
    5168                 :     }
    5169                 :     else {
    5170               0 :       goto tk_byte;
    5171                 :     }
    5172               0 :     break;
    5173                 : 
    5174                 :   default:
    5175               0 :     return ONIGERR_PARSER_BUG;
    5176                 :     break;
    5177                 :   }
    5178                 : 
    5179                 :   {
    5180             208 :     targetp = np;
    5181                 : 
    5182             334 :   re_entry:
    5183             334 :     r = fetch_token(tok, src, end, env);
    5184             334 :     if (r < 0) return r;
    5185                 : 
    5186             474 :   repeat:
    5187             474 :     if (r == TK_OP_REPEAT || r == TK_INTERVAL) {
    5188             126 :       if (is_invalid_qualifier_target(*targetp))
    5189               0 :         return ONIGERR_TARGET_OF_REPEAT_OPERATOR_INVALID;
    5190                 : 
    5191             126 :       qn = node_new_qualifier(tok->u.repeat.lower, tok->u.repeat.upper,
    5192                 :                               (r == TK_INTERVAL ? 1 : 0));
    5193             126 :       CHECK_NULL_RETURN_VAL(qn, ONIGERR_MEMORY);
    5194             126 :       NQUALIFIER(qn).greedy = tok->u.repeat.greedy;
    5195             126 :       r = set_qualifier(qn, *targetp, group, env);
    5196             126 :       if (r < 0) return r;
    5197                 :       
    5198             126 :       if (tok->u.repeat.possessive != 0) {
    5199                 :         Node* en;
    5200               0 :         en = node_new_effect(EFFECT_STOP_BACKTRACK);
    5201               0 :         CHECK_NULL_RETURN_VAL(en, ONIGERR_MEMORY);
    5202               0 :         NEFFECT(en).target = qn;
    5203               0 :         qn = en;
    5204                 :       }
    5205                 : 
    5206             126 :       if (r == 0) {
    5207             117 :         *targetp = qn;
    5208                 :       }
    5209               9 :       else if (r == 2) { /* split case: /abc+/ */
    5210                 :         Node *tmp;
    5211                 : 
    5212               9 :         *targetp = node_new_list(*targetp, NULL);
    5213               9 :         CHECK_NULL_RETURN_VAL(*targetp, ONIGERR_MEMORY);
    5214               9 :         tmp = NCONS(*targetp).right = node_new_list(qn, NULL);
    5215               9 :         CHECK_NULL_RETURN_VAL(tmp, ONIGERR_MEMORY);
    5216               9 :         targetp = &(NCONS(tmp).left);
    5217                 :       }
    5218             126 :       goto re_entry;
    5219                 :     }
    5220                 :   }
    5221                 : 
    5222             348 :   return r;
    5223                 : }
    5224                 : 
    5225                 : static int
    5226                 : parse_branch(Node** top, OnigToken* tok, int term,
    5227                 :              UChar** src, UChar* end, ScanEnv* env)
    5228             208 : {
    5229                 :   int r;
    5230                 :   Node *node, **headp;
    5231                 : 
    5232             208 :   *top = NULL;
    5233             208 :   r = parse_exp(&node, tok, term, src, end, env);
    5234             208 :   if (r < 0) return r;
    5235                 : 
    5236             354 :   if (r == TK_EOT || r == term || r == TK_ALT) {
    5237             146 :     *top = node;
    5238                 :   }
    5239                 :   else {
    5240              62 :     *top  = node_new_list(node, NULL);
    5241              62 :     headp = &(NCONS(*top).right);
    5242             266 :     while (r != TK_EOT && r != term && r != TK_ALT) {
    5243             142 :       r = parse_exp(&node, tok, term, src, end, env);
    5244             142 :       if (r < 0) return r;
    5245                 : 
    5246             142 :       if (NTYPE(node) == N_LIST) {
    5247               9 :         *headp = node;
    5248               9 :         while (IS_NOT_NULL(NCONS(node).right)) node = NCONS(node).right;
    5249               9 :         headp = &(NCONS(node).right);
    5250                 :       }
    5251                 :       else {
    5252             133 :         *headp = node_new_list(node, NULL);
    5253             133 :         headp = &(NCONS(*headp).right);
    5254                 :       }
    5255                 :     }
    5256                 :   }
    5257                 : 
    5258             208 :   return r;
    5259                 : }
    5260                 : 
    5261                 : /* term_tok: TK_EOT or TK_SUBEXP_CLOSE */
    5262                 : static int
    5263                 : parse_subexp(Node** top, OnigToken* tok, int term,
    5264                 :              UChar** src, UChar* end, ScanEnv* env)
    5265             206 : {
    5266                 :   int r;
    5267                 :   Node *node, **headp;
    5268                 : 
    5269             206 :   *top = NULL;
    5270             206 :   r = parse_branch(&node, tok, term, src, end, env);
    5271             206 :   if (r < 0) {
    5272               0 :     onig_node_free(node);
    5273               0 :     return r;
    5274                 :   }
    5275                 : 
    5276             206 :   if (r == term) {
    5277             204 :     *top = node;
    5278                 :   }
    5279               2 :   else if (r == TK_ALT) {
    5280               2 :     *top  = node_new_alt(node, NULL);
    5281               2 :     headp = &(NCONS(*top).right);
    5282               6 :     while (r == TK_ALT) {
    5283               2 :       r = fetch_token(tok, src, end, env);
    5284               2 :       if (r < 0) return r;
    5285               2 :       r = parse_branch(&node, tok, term, src, end, env);
    5286               2 :       if (r < 0) return r;
    5287                 : 
    5288               2 :       *headp = node_new_alt(node, NULL);
    5289               2 :       headp = &(NCONS(*headp).right);
    5290                 :     }
    5291                 : 
    5292               2 :     if (tok->type != term)
    5293               0 :       goto err;
    5294                 :   }
    5295                 :   else {
    5296               0 :   err:
    5297               0 :     if (term == TK_SUBEXP_CLOSE)
    5298               0 :       return ONIGERR_END_PATTERN_WITH_UNMATCHED_PARENTHESIS;
    5299                 :     else
    5300               0 :       return ONIGERR_PARSER_BUG;
    5301                 :   }
    5302                 : 
    5303             206 :   return r;
    5304                 : }
    5305                 : 
    5306                 : static int
    5307                 : parse_regexp(Node** top, UChar** src, UChar* end, ScanEnv* env)
    5308             145 : {
    5309                 :   int r;
    5310                 :   OnigToken tok;
    5311                 : 
    5312             145 :   r = fetch_token(&tok, src, end, env);
    5313             145 :   if (r < 0) return r;
    5314             145 :   r = parse_subexp(top, &tok, TK_EOT, src, end, env);
    5315             145 :   if (r < 0) return r;
    5316             145 :   return 0;
    5317                 : }
    5318                 : 
    5319                 : extern int
    5320                 : onig_parse_make_tree(Node** root, const UChar* pattern, const UChar* end, regex_t* reg,
    5321                 :                       ScanEnv* env)
    5322             145 : {
    5323                 :   int r;
    5324                 :   UChar* p;
    5325                 : 
    5326                 : #ifdef USE_NAMED_GROUP
    5327             145 :   names_clear(reg);
    5328                 : #endif
    5329                 : 
    5330             145 :   scan_env_clear(env);
    5331             145 :   env->option      = reg->options;
    5332             145 :   env->ambig_flag  = reg->ambig_flag;
    5333             145 :   env->enc         = reg->enc;
    5334             145 :   env->syntax      = reg->syntax;
    5335             145 :   env->pattern     = (UChar* )pattern;
    5336             145 :   env->pattern_end = (UChar* )end;
    5337             145 :   env->reg         = reg;
    5338                 : 
    5339             145 :   *root = NULL;
    5340             145 :   p = (UChar* )pattern;
    5341             145 :   r = parse_regexp(root, &p, (UChar* )end, env);
    5342             145 :   reg->num_mem = env->num_mem;
    5343             145 :   return r;
    5344                 : }
    5345                 : 
    5346                 : extern void
    5347                 : onig_scan_env_set_error_string(ScanEnv* env, int ecode,
    5348                 :                                 UChar* arg, UChar* arg_end)
    5349               0 : {
    5350               0 :   env->error     = arg;
    5351               0 :   env->error_end = arg_end;
    5352               0 : }

Generated by: LTP GCOV extension version 1.5

Generated at Thu, 19 Nov 2009 08:20:11 +0000 (5 days ago)

Copyright © 2005-2009 The PHP Group
All rights reserved.