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

1.1     ! misho       1: /**********************************************************************
        !             2:   regexec.c -  Oniguruma (regular expression library)
        !             3: **********************************************************************/
        !             4: /*-
        !             5:  * Copyright (c) 2002-2007  K.Kosako  <sndgk393 AT ybb DOT ne DOT jp>
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  *
        !            17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
        !            18:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            19:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            20:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
        !            21:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            22:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            23:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            24:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            25:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            26:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            27:  * SUCH DAMAGE.
        !            28:  */
        !            29: 
        !            30: #include "regint.h"
        !            31: 
        !            32: #ifdef USE_CRNL_AS_LINE_TERMINATOR
        !            33: #define ONIGENC_IS_MBC_CRNL(enc,p,end) \
        !            34:   (ONIGENC_MBC_TO_CODE(enc,p,end) == 13 && \
        !            35:    ONIGENC_IS_MBC_NEWLINE(enc,(p+enc_len(enc,p)),end))
        !            36: #endif
        !            37: 
        !            38: #ifdef USE_CAPTURE_HISTORY
        !            39: static void history_tree_free(OnigCaptureTreeNode* node);
        !            40: 
        !            41: static void
        !            42: history_tree_clear(OnigCaptureTreeNode* node)
        !            43: {
        !            44:   int i;
        !            45: 
        !            46:   if (IS_NOT_NULL(node)) {
        !            47:     for (i = 0; i < node->num_childs; i++) {
        !            48:       if (IS_NOT_NULL(node->childs[i])) {
        !            49:         history_tree_free(node->childs[i]);
        !            50:       }
        !            51:     }
        !            52:     for (i = 0; i < node->allocated; i++) {
        !            53:       node->childs[i] = (OnigCaptureTreeNode* )0;
        !            54:     }
        !            55:     node->num_childs = 0;
        !            56:     node->beg = ONIG_REGION_NOTPOS;
        !            57:     node->end = ONIG_REGION_NOTPOS;
        !            58:     node->group = -1;
        !            59:   }
        !            60: }
        !            61: 
        !            62: static void
        !            63: history_tree_free(OnigCaptureTreeNode* node)
        !            64: {
        !            65:   history_tree_clear(node);
        !            66:   xfree(node);
        !            67: }
        !            68: 
        !            69: static void
        !            70: history_root_free(OnigRegion* r)
        !            71: {
        !            72:   if (IS_NOT_NULL(r->history_root)) {
        !            73:     history_tree_free(r->history_root);
        !            74:     r->history_root = (OnigCaptureTreeNode* )0;
        !            75:   }
        !            76: }
        !            77: 
        !            78: static OnigCaptureTreeNode*
        !            79: history_node_new(void)
        !            80: {
        !            81:   OnigCaptureTreeNode* node;
        !            82: 
        !            83:   node = (OnigCaptureTreeNode* )xmalloc(sizeof(OnigCaptureTreeNode));
        !            84:   CHECK_NULL_RETURN(node);
        !            85:   node->childs     = (OnigCaptureTreeNode** )0;
        !            86:   node->allocated  = 0;
        !            87:   node->num_childs = 0;
        !            88:   node->group      = -1;
        !            89:   node->beg        = ONIG_REGION_NOTPOS;
        !            90:   node->end        = ONIG_REGION_NOTPOS;
        !            91: 
        !            92:   return node;
        !            93: }
        !            94: 
        !            95: static int
        !            96: history_tree_add_child(OnigCaptureTreeNode* parent, OnigCaptureTreeNode* child)
        !            97: {
        !            98: #define HISTORY_TREE_INIT_ALLOC_SIZE  8
        !            99: 
        !           100:   if (parent->num_childs >= parent->allocated) {
        !           101:     int n, i;
        !           102: 
        !           103:     if (IS_NULL(parent->childs)) {
        !           104:       n = HISTORY_TREE_INIT_ALLOC_SIZE;
        !           105:       parent->childs =
        !           106:         (OnigCaptureTreeNode** )xmalloc(sizeof(OnigCaptureTreeNode*) * n);
        !           107:     }
        !           108:     else {
        !           109:       n = parent->allocated * 2;
        !           110:       parent->childs =
        !           111:         (OnigCaptureTreeNode** )xrealloc(parent->childs,
        !           112:                                          sizeof(OnigCaptureTreeNode*) * n);
        !           113:     }
        !           114:     CHECK_NULL_RETURN_VAL(parent->childs, ONIGERR_MEMORY);
        !           115:     for (i = parent->allocated; i < n; i++) {
        !           116:       parent->childs[i] = (OnigCaptureTreeNode* )0;
        !           117:     }
        !           118:     parent->allocated = n;
        !           119:   }
        !           120: 
        !           121:   parent->childs[parent->num_childs] = child;
        !           122:   parent->num_childs++;
        !           123:   return 0;
        !           124: }
        !           125: 
        !           126: static OnigCaptureTreeNode*
        !           127: history_tree_clone(OnigCaptureTreeNode* node)
        !           128: {
        !           129:   int i;
        !           130:   OnigCaptureTreeNode *clone, *child;
        !           131: 
        !           132:   clone = history_node_new();
        !           133:   CHECK_NULL_RETURN(clone);
        !           134: 
        !           135:   clone->beg = node->beg;
        !           136:   clone->end = node->end;
        !           137:   for (i = 0; i < node->num_childs; i++) {
        !           138:     child = history_tree_clone(node->childs[i]);
        !           139:     if (IS_NULL(child)) {
        !           140:       history_tree_free(clone);
        !           141:       return (OnigCaptureTreeNode* )0;
        !           142:     }
        !           143:     history_tree_add_child(clone, child);
        !           144:   }
        !           145: 
        !           146:   return clone;
        !           147: }
        !           148: 
        !           149: extern  OnigCaptureTreeNode*
        !           150: onig_get_capture_tree(OnigRegion* region)
        !           151: {
        !           152:   return region->history_root;
        !           153: }
        !           154: #endif /* USE_CAPTURE_HISTORY */
        !           155: 
        !           156: extern void
        !           157: onig_region_clear(OnigRegion* region)
        !           158: {
        !           159:   int i;
        !           160: 
        !           161:   for (i = 0; i < region->num_regs; i++) {
        !           162:     region->beg[i] = region->end[i] = ONIG_REGION_NOTPOS;
        !           163:   }
        !           164: #ifdef USE_CAPTURE_HISTORY
        !           165:   history_root_free(region);
        !           166: #endif
        !           167: }
        !           168: 
        !           169: extern int
        !           170: onig_region_resize(OnigRegion* region, int n)
        !           171: {
        !           172:   region->num_regs = n;
        !           173: 
        !           174:   if (n < ONIG_NREGION)
        !           175:     n = ONIG_NREGION;
        !           176: 
        !           177:   if (region->allocated == 0) {
        !           178:     region->beg = (int* )xmalloc(n * sizeof(int));
        !           179:     region->end = (int* )xmalloc(n * sizeof(int));
        !           180: 
        !           181:     if (region->beg == 0 || region->end == 0)
        !           182:       return ONIGERR_MEMORY;
        !           183: 
        !           184:     region->allocated = n;
        !           185:   }
        !           186:   else if (region->allocated < n) {
        !           187:     region->beg = (int* )xrealloc(region->beg, n * sizeof(int));
        !           188:     region->end = (int* )xrealloc(region->end, n * sizeof(int));
        !           189: 
        !           190:     if (region->beg == 0 || region->end == 0)
        !           191:       return ONIGERR_MEMORY;
        !           192: 
        !           193:     region->allocated = n;
        !           194:   }
        !           195: 
        !           196:   return 0;
        !           197: }
        !           198: 
        !           199: extern int
        !           200: onig_region_resize_clear(OnigRegion* region, int n)
        !           201: {
        !           202:   int r;
        !           203:   
        !           204:   r = onig_region_resize(region, n);
        !           205:   if (r != 0) return r;
        !           206:   onig_region_clear(region);
        !           207:   return 0;
        !           208: }
        !           209:     
        !           210: extern int
        !           211: onig_region_set(OnigRegion* region, int at, int beg, int end)
        !           212: {
        !           213:   if (at < 0) return ONIGERR_INVALID_ARGUMENT;
        !           214: 
        !           215:   if (at >= region->allocated) {
        !           216:     int r = onig_region_resize(region, at + 1);
        !           217:     if (r < 0) return r;
        !           218:   }
        !           219:   
        !           220:   region->beg[at] = beg;
        !           221:   region->end[at] = end;
        !           222:   return 0;
        !           223: }
        !           224: 
        !           225: extern void
        !           226: onig_region_init(OnigRegion* region)
        !           227: {
        !           228:   region->num_regs     = 0;
        !           229:   region->allocated    = 0;
        !           230:   region->beg          = (int* )0;
        !           231:   region->end          = (int* )0;
        !           232:   region->history_root = (OnigCaptureTreeNode* )0;
        !           233: }
        !           234: 
        !           235: extern OnigRegion*
        !           236: onig_region_new(void)
        !           237: {
        !           238:   OnigRegion* r;
        !           239: 
        !           240:   r = (OnigRegion* )xmalloc(sizeof(OnigRegion));
        !           241:   onig_region_init(r);
        !           242:   return r;
        !           243: }
        !           244: 
        !           245: extern void
        !           246: onig_region_free(OnigRegion* r, int free_self)
        !           247: {
        !           248:   if (r) {
        !           249:     if (r->allocated > 0) {
        !           250:       if (r->beg) xfree(r->beg);
        !           251:       if (r->end) xfree(r->end);
        !           252:       r->allocated = 0;
        !           253:     }
        !           254: #ifdef USE_CAPTURE_HISTORY
        !           255:     history_root_free(r);
        !           256: #endif
        !           257:     if (free_self) xfree(r);
        !           258:   }
        !           259: }
        !           260: 
        !           261: extern void
        !           262: onig_region_copy(OnigRegion* to, OnigRegion* from)
        !           263: {
        !           264: #define RREGC_SIZE   (sizeof(int) * from->num_regs)
        !           265:   int i;
        !           266: 
        !           267:   if (to == from) return;
        !           268: 
        !           269:   if (to->allocated == 0) {
        !           270:     if (from->num_regs > 0) {
        !           271:       to->beg = (int* )xmalloc(RREGC_SIZE);
        !           272:       to->end = (int* )xmalloc(RREGC_SIZE);
        !           273:       to->allocated = from->num_regs;
        !           274:     }
        !           275:   }
        !           276:   else if (to->allocated < from->num_regs) {
        !           277:     to->beg = (int* )xrealloc(to->beg, RREGC_SIZE);
        !           278:     to->end = (int* )xrealloc(to->end, RREGC_SIZE);
        !           279:     to->allocated = from->num_regs;
        !           280:   }
        !           281: 
        !           282:   for (i = 0; i < from->num_regs; i++) {
        !           283:     to->beg[i] = from->beg[i];
        !           284:     to->end[i] = from->end[i];
        !           285:   }
        !           286:   to->num_regs = from->num_regs;
        !           287: 
        !           288: #ifdef USE_CAPTURE_HISTORY
        !           289:   history_root_free(to);
        !           290: 
        !           291:   if (IS_NOT_NULL(from->history_root)) {
        !           292:     to->history_root = history_tree_clone(from->history_root);
        !           293:   }
        !           294: #endif
        !           295: }
        !           296: 
        !           297: 
        !           298: /** stack **/
        !           299: #define INVALID_STACK_INDEX   -1
        !           300: typedef long StackIndex;
        !           301: 
        !           302: typedef struct _StackType {
        !           303:   unsigned int type;
        !           304:   union {
        !           305:     struct {
        !           306:       UChar *pcode;      /* byte code position */
        !           307:       UChar *pstr;       /* string position */
        !           308:       UChar *pstr_prev;  /* previous char position of pstr */
        !           309: #ifdef USE_COMBINATION_EXPLOSION_CHECK
        !           310:       unsigned int state_check;
        !           311: #endif
        !           312:     } state;
        !           313:     struct {
        !           314:       int   count;       /* for OP_REPEAT_INC, OP_REPEAT_INC_NG */
        !           315:       UChar *pcode;      /* byte code position (head of repeated target) */
        !           316:       int   num;         /* repeat id */
        !           317:     } repeat;
        !           318:     struct {
        !           319:       StackIndex si;     /* index of stack */
        !           320:     } repeat_inc;
        !           321:     struct {
        !           322:       int num;           /* memory num */
        !           323:       UChar *pstr;       /* start/end position */
        !           324:       /* Following information is setted, if this stack type is MEM-START */
        !           325:       StackIndex start;  /* prev. info (for backtrack  "(...)*" ) */
        !           326:       StackIndex end;    /* prev. info (for backtrack  "(...)*" ) */
        !           327:     } mem;
        !           328:     struct {
        !           329:       int num;           /* null check id */
        !           330:       UChar *pstr;       /* start position */
        !           331:     } null_check;
        !           332: #ifdef USE_SUBEXP_CALL
        !           333:     struct {
        !           334:       UChar *ret_addr;   /* byte code position */
        !           335:       int    num;        /* null check id */
        !           336:       UChar *pstr;       /* string position */
        !           337:     } call_frame;
        !           338: #endif
        !           339:   } u;
        !           340: } StackType;
        !           341: 
        !           342: /* stack type */
        !           343: /* used by normal-POP */
        !           344: #define STK_ALT                    0x0001
        !           345: #define STK_LOOK_BEHIND_NOT        0x0002
        !           346: #define STK_POS_NOT                0x0003
        !           347: /* handled by normal-POP */
        !           348: #define STK_MEM_START              0x0100
        !           349: #define STK_MEM_END                0x8200
        !           350: #define STK_REPEAT_INC             0x0300
        !           351: #define STK_STATE_CHECK_MARK       0x1000
        !           352: /* avoided by normal-POP */
        !           353: #define STK_NULL_CHECK_START       0x3000
        !           354: #define STK_NULL_CHECK_END         0x5000  /* for recursive call */
        !           355: #define STK_MEM_END_MARK           0x8400
        !           356: #define STK_POS                    0x0500  /* used when POP-POS */
        !           357: #define STK_STOP_BT                0x0600  /* mark for "(?>...)" */
        !           358: #define STK_REPEAT                 0x0700
        !           359: #define STK_CALL_FRAME             0x0800
        !           360: #define STK_RETURN                 0x0900
        !           361: #define STK_VOID                   0x0a00  /* for fill a blank */
        !           362: 
        !           363: /* stack type check mask */
        !           364: #define STK_MASK_POP_USED          0x00ff
        !           365: #define STK_MASK_TO_VOID_TARGET    0x10ff
        !           366: #define STK_MASK_MEM_END_OR_MARK   0x8000  /* MEM_END or MEM_END_MARK */
        !           367: 
        !           368: typedef struct {
        !           369:   void* stack_p;
        !           370:   int   stack_n;
        !           371:   OnigOptionType options;
        !           372:   OnigRegion*    region;
        !           373:   const UChar* start;   /* search start position (for \G: BEGIN_POSITION) */
        !           374: #ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE
        !           375:   int    best_len;      /* for ONIG_OPTION_FIND_LONGEST */
        !           376:   UChar* best_s;
        !           377: #endif
        !           378: #ifdef USE_COMBINATION_EXPLOSION_CHECK
        !           379:   void* state_check_buff;
        !           380:   int   state_check_buff_size;
        !           381: #endif
        !           382: } MatchArg;
        !           383: 
        !           384: #ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE
        !           385: #define MATCH_ARG_INIT(msa, arg_option, arg_region, arg_start) do {\
        !           386:   (msa).stack_p  = (void* )0;\
        !           387:   (msa).options  = (arg_option);\
        !           388:   (msa).region   = (arg_region);\
        !           389:   (msa).start    = (arg_start);\
        !           390:   (msa).best_len = ONIG_MISMATCH;\
        !           391: } while (0)
        !           392: #else
        !           393: #define MATCH_ARG_INIT(msa, arg_option, arg_region, arg_start) do {\
        !           394:   (msa).stack_p  = (void* )0;\
        !           395:   (msa).options  = (arg_option);\
        !           396:   (msa).region   = (arg_region);\
        !           397:   (msa).start    = (arg_start);\
        !           398: } while (0)
        !           399: #endif
        !           400: 
        !           401: #ifdef USE_COMBINATION_EXPLOSION_CHECK
        !           402: 
        !           403: #define STATE_CHECK_BUFF_MALLOC_THRESHOLD_SIZE  16
        !           404: 
        !           405: #define STATE_CHECK_BUFF_INIT(msa, str_len, offset, state_num) do {    \
        !           406:   if ((state_num) > 0 && str_len >= STATE_CHECK_STRING_THRESHOLD_LEN) {\
        !           407:     unsigned int size = (unsigned int )(((str_len) + 1) * (state_num) + 7) >> 3;\
        !           408:     offset = ((offset) * (state_num)) >> 3;\
        !           409:     if (size > 0 && offset < size && size < STATE_CHECK_BUFF_MAX_SIZE) {\
        !           410:       if (size >= STATE_CHECK_BUFF_MALLOC_THRESHOLD_SIZE) \
        !           411:         (msa).state_check_buff = (void* )xmalloc(size);\
        !           412:       else \
        !           413:         (msa).state_check_buff = (void* )xalloca(size);\
        !           414:       xmemset(((char* )((msa).state_check_buff)+(offset)), 0, \
        !           415:               (size_t )(size - (offset))); \
        !           416:       (msa).state_check_buff_size = size;\
        !           417:     }\
        !           418:     else {\
        !           419:       (msa).state_check_buff = (void* )0;\
        !           420:       (msa).state_check_buff_size = 0;\
        !           421:     }\
        !           422:   }\
        !           423:   else {\
        !           424:     (msa).state_check_buff = (void* )0;\
        !           425:     (msa).state_check_buff_size = 0;\
        !           426:   }\
        !           427: } while (0)
        !           428: 
        !           429: #define MATCH_ARG_FREE(msa) do {\
        !           430:   if ((msa).stack_p) xfree((msa).stack_p);\
        !           431:   if ((msa).state_check_buff_size >= STATE_CHECK_BUFF_MALLOC_THRESHOLD_SIZE) { \
        !           432:     if ((msa).state_check_buff) xfree((msa).state_check_buff);\
        !           433:   }\
        !           434: } while (0);
        !           435: #else
        !           436: #define STATE_CHECK_BUFF_INIT(msa, str_len, offset, state_num)
        !           437: #define MATCH_ARG_FREE(msa)  if ((msa).stack_p) xfree((msa).stack_p)
        !           438: #endif
        !           439: 
        !           440: 
        !           441: 
        !           442: #define STACK_INIT(alloc_addr, ptr_num, stack_num)  do {\
        !           443:   if (msa->stack_p) {\
        !           444:     alloc_addr = (char* )xalloca(sizeof(char*) * (ptr_num));\
        !           445:     stk_alloc  = (StackType* )(msa->stack_p);\
        !           446:     stk_base   = stk_alloc;\
        !           447:     stk        = stk_base;\
        !           448:     stk_end    = stk_base + msa->stack_n;\
        !           449:   }\
        !           450:   else {\
        !           451:     alloc_addr = (char* )xalloca(sizeof(char*) * (ptr_num)\
        !           452:                       + sizeof(StackType) * (stack_num));\
        !           453:     stk_alloc  = (StackType* )(alloc_addr + sizeof(char*) * (ptr_num));\
        !           454:     stk_base   = stk_alloc;\
        !           455:     stk        = stk_base;\
        !           456:     stk_end    = stk_base + (stack_num);\
        !           457:   }\
        !           458: } while(0)
        !           459: 
        !           460: #define STACK_SAVE do{\
        !           461:   if (stk_base != stk_alloc) {\
        !           462:     msa->stack_p = stk_base;\
        !           463:     msa->stack_n = stk_end - stk_base;\
        !           464:   };\
        !           465: } while(0)
        !           466: 
        !           467: static unsigned int MatchStackLimitSize = DEFAULT_MATCH_STACK_LIMIT_SIZE;
        !           468: 
        !           469: extern unsigned int
        !           470: onig_get_match_stack_limit_size(void)
        !           471: {
        !           472:   return MatchStackLimitSize;
        !           473: }
        !           474: 
        !           475: extern int
        !           476: onig_set_match_stack_limit_size(unsigned int size)
        !           477: {
        !           478:   MatchStackLimitSize = size;
        !           479:   return 0;
        !           480: }
        !           481: 
        !           482: static int
        !           483: stack_double(StackType** arg_stk_base, StackType** arg_stk_end,
        !           484:             StackType** arg_stk, StackType* stk_alloc, MatchArg* msa)
        !           485: {
        !           486:   unsigned int n;
        !           487:   StackType *x, *stk_base, *stk_end, *stk;
        !           488: 
        !           489:   stk_base = *arg_stk_base;
        !           490:   stk_end  = *arg_stk_end;
        !           491:   stk      = *arg_stk;
        !           492: 
        !           493:   n = stk_end - stk_base;
        !           494:   if (stk_base == stk_alloc && IS_NULL(msa->stack_p)) {
        !           495:     x = (StackType* )xmalloc(sizeof(StackType) * n * 2);
        !           496:     if (IS_NULL(x)) {
        !           497:       STACK_SAVE;
        !           498:       return ONIGERR_MEMORY;
        !           499:     }
        !           500:     xmemcpy(x, stk_base, n * sizeof(StackType));
        !           501:     n *= 2;
        !           502:   }
        !           503:   else {
        !           504:     n *= 2;
        !           505:     if (MatchStackLimitSize != 0 && n > MatchStackLimitSize) {
        !           506:       if ((unsigned int )(stk_end - stk_base) == MatchStackLimitSize)
        !           507:         return ONIGERR_MATCH_STACK_LIMIT_OVER;
        !           508:       else
        !           509:         n = MatchStackLimitSize;
        !           510:     }
        !           511:     x = (StackType* )xrealloc(stk_base, sizeof(StackType) * n);
        !           512:     if (IS_NULL(x)) {
        !           513:       STACK_SAVE;
        !           514:       return ONIGERR_MEMORY;
        !           515:     }
        !           516:   }
        !           517:   *arg_stk      = x + (stk - stk_base);
        !           518:   *arg_stk_base = x;
        !           519:   *arg_stk_end  = x + n;
        !           520:   return 0;
        !           521: }
        !           522: 
        !           523: #define STACK_ENSURE(n)        do {\
        !           524:   if (stk_end - stk < (n)) {\
        !           525:     int r = stack_double(&stk_base, &stk_end, &stk, stk_alloc, msa);\
        !           526:     if (r != 0) { STACK_SAVE; return r; } \
        !           527:   }\
        !           528: } while(0)
        !           529: 
        !           530: #define STACK_AT(index)        (stk_base + (index))
        !           531: #define GET_STACK_INDEX(stk)   ((stk) - stk_base)
        !           532: 
        !           533: #define STACK_PUSH_TYPE(stack_type) do {\
        !           534:   STACK_ENSURE(1);\
        !           535:   stk->type = (stack_type);\
        !           536:   STACK_INC;\
        !           537: } while(0)
        !           538: 
        !           539: #define IS_TO_VOID_TARGET(stk) (((stk)->type & STK_MASK_TO_VOID_TARGET) != 0)
        !           540: 
        !           541: #ifdef USE_COMBINATION_EXPLOSION_CHECK
        !           542: #define STATE_CHECK_POS(s,snum) \
        !           543:   (((s) - str) * num_comb_exp_check + ((snum) - 1))
        !           544: #define STATE_CHECK_VAL(v,snum) do {\
        !           545:   if (state_check_buff != NULL) {\
        !           546:     int x = STATE_CHECK_POS(s,snum);\
        !           547:     (v) = state_check_buff[x/8] & (1<<(x%8));\
        !           548:   }\
        !           549:   else (v) = 0;\
        !           550: } while(0)
        !           551: 
        !           552: 
        !           553: #define ELSE_IF_STATE_CHECK_MARK(stk) \
        !           554:   else if ((stk)->type == STK_STATE_CHECK_MARK) { \
        !           555:     int x = STATE_CHECK_POS(stk->u.state.pstr, stk->u.state.state_check);\
        !           556:     state_check_buff[x/8] |= (1<<(x%8));                               \
        !           557:   }
        !           558: 
        !           559: #define STACK_PUSH(stack_type,pat,s,sprev) do {\
        !           560:   STACK_ENSURE(1);\
        !           561:   stk->type = (stack_type);\
        !           562:   stk->u.state.pcode     = (pat);\
        !           563:   stk->u.state.pstr      = (s);\
        !           564:   stk->u.state.pstr_prev = (sprev);\
        !           565:   stk->u.state.state_check = 0;\
        !           566:   STACK_INC;\
        !           567: } while(0)
        !           568: 
        !           569: #define STACK_PUSH_ENSURED(stack_type,pat) do {\
        !           570:   stk->type = (stack_type);\
        !           571:   stk->u.state.pcode = (pat);\
        !           572:   stk->u.state.state_check = 0;\
        !           573:   STACK_INC;\
        !           574: } while(0)
        !           575: 
        !           576: #define STACK_PUSH_ALT_WITH_STATE_CHECK(pat,s,sprev,snum) do {\
        !           577:   STACK_ENSURE(1);\
        !           578:   stk->type = STK_ALT;\
        !           579:   stk->u.state.pcode     = (pat);\
        !           580:   stk->u.state.pstr      = (s);\
        !           581:   stk->u.state.pstr_prev = (sprev);\
        !           582:   stk->u.state.state_check = ((state_check_buff != NULL) ? (snum) : 0);\
        !           583:   STACK_INC;\
        !           584: } while(0)
        !           585: 
        !           586: #define STACK_PUSH_STATE_CHECK(s,snum) do {\
        !           587:   if (state_check_buff != NULL) {\
        !           588:     STACK_ENSURE(1);\
        !           589:     stk->type = STK_STATE_CHECK_MARK;\
        !           590:     stk->u.state.pstr = (s);\
        !           591:     stk->u.state.state_check = (snum);\
        !           592:     STACK_INC;\
        !           593:   }\
        !           594: } while(0)
        !           595: 
        !           596: #else /* USE_COMBINATION_EXPLOSION_CHECK */
        !           597: 
        !           598: #define ELSE_IF_STATE_CHECK_MARK(stk)
        !           599: 
        !           600: #define STACK_PUSH(stack_type,pat,s,sprev) do {\
        !           601:   STACK_ENSURE(1);\
        !           602:   stk->type = (stack_type);\
        !           603:   stk->u.state.pcode     = (pat);\
        !           604:   stk->u.state.pstr      = (s);\
        !           605:   stk->u.state.pstr_prev = (sprev);\
        !           606:   STACK_INC;\
        !           607: } while(0)
        !           608: 
        !           609: #define STACK_PUSH_ENSURED(stack_type,pat) do {\
        !           610:   stk->type = (stack_type);\
        !           611:   stk->u.state.pcode = (pat);\
        !           612:   STACK_INC;\
        !           613: } while(0)
        !           614: #endif /* USE_COMBINATION_EXPLOSION_CHECK */
        !           615: 
        !           616: #define STACK_PUSH_ALT(pat,s,sprev)     STACK_PUSH(STK_ALT,pat,s,sprev)
        !           617: #define STACK_PUSH_POS(s,sprev)         STACK_PUSH(STK_POS,NULL_UCHARP,s,sprev)
        !           618: #define STACK_PUSH_POS_NOT(pat,s,sprev) STACK_PUSH(STK_POS_NOT,pat,s,sprev)
        !           619: #define STACK_PUSH_STOP_BT              STACK_PUSH_TYPE(STK_STOP_BT)
        !           620: #define STACK_PUSH_LOOK_BEHIND_NOT(pat,s,sprev) \
        !           621:         STACK_PUSH(STK_LOOK_BEHIND_NOT,pat,s,sprev)
        !           622: 
        !           623: #define STACK_PUSH_REPEAT(id, pat) do {\
        !           624:   STACK_ENSURE(1);\
        !           625:   stk->type = STK_REPEAT;\
        !           626:   stk->u.repeat.num    = (id);\
        !           627:   stk->u.repeat.pcode  = (pat);\
        !           628:   stk->u.repeat.count  = 0;\
        !           629:   STACK_INC;\
        !           630: } while(0)
        !           631: 
        !           632: #define STACK_PUSH_REPEAT_INC(sindex) do {\
        !           633:   STACK_ENSURE(1);\
        !           634:   stk->type = STK_REPEAT_INC;\
        !           635:   stk->u.repeat_inc.si  = (sindex);\
        !           636:   STACK_INC;\
        !           637: } while(0)
        !           638: 
        !           639: #define STACK_PUSH_MEM_START(mnum, s) do {\
        !           640:   STACK_ENSURE(1);\
        !           641:   stk->type = STK_MEM_START;\
        !           642:   stk->u.mem.num      = (mnum);\
        !           643:   stk->u.mem.pstr     = (s);\
        !           644:   stk->u.mem.start    = mem_start_stk[mnum];\
        !           645:   stk->u.mem.end      = mem_end_stk[mnum];\
        !           646:   mem_start_stk[mnum] = GET_STACK_INDEX(stk);\
        !           647:   mem_end_stk[mnum]   = INVALID_STACK_INDEX;\
        !           648:   STACK_INC;\
        !           649: } while(0)
        !           650: 
        !           651: #define STACK_PUSH_MEM_END(mnum, s) do {\
        !           652:   STACK_ENSURE(1);\
        !           653:   stk->type = STK_MEM_END;\
        !           654:   stk->u.mem.num    = (mnum);\
        !           655:   stk->u.mem.pstr   = (s);\
        !           656:   stk->u.mem.start  = mem_start_stk[mnum];\
        !           657:   stk->u.mem.end    = mem_end_stk[mnum];\
        !           658:   mem_end_stk[mnum] = GET_STACK_INDEX(stk);\
        !           659:   STACK_INC;\
        !           660: } while(0)
        !           661: 
        !           662: #define STACK_PUSH_MEM_END_MARK(mnum) do {\
        !           663:   STACK_ENSURE(1);\
        !           664:   stk->type = STK_MEM_END_MARK;\
        !           665:   stk->u.mem.num = (mnum);\
        !           666:   STACK_INC;\
        !           667: } while(0)
        !           668: 
        !           669: #define STACK_GET_MEM_START(mnum, k) do {\
        !           670:   int level = 0;\
        !           671:   k = stk;\
        !           672:   while (k > stk_base) {\
        !           673:     k--;\
        !           674:     if ((k->type & STK_MASK_MEM_END_OR_MARK) != 0 \
        !           675:       && k->u.mem.num == (mnum)) {\
        !           676:       level++;\
        !           677:     }\
        !           678:     else if (k->type == STK_MEM_START && k->u.mem.num == (mnum)) {\
        !           679:       if (level == 0) break;\
        !           680:       level--;\
        !           681:     }\
        !           682:   }\
        !           683: } while (0)
        !           684: 
        !           685: #define STACK_GET_MEM_RANGE(k, mnum, start, end) do {\
        !           686:   int level = 0;\
        !           687:   while (k < stk) {\
        !           688:     if (k->type == STK_MEM_START && k->u.mem.num == (mnum)) {\
        !           689:       if (level == 0) (start) = k->u.mem.pstr;\
        !           690:       level++;\
        !           691:     }\
        !           692:     else if (k->type == STK_MEM_END && k->u.mem.num == (mnum)) {\
        !           693:       level--;\
        !           694:       if (level == 0) {\
        !           695:         (end) = k->u.mem.pstr;\
        !           696:         break;\
        !           697:       }\
        !           698:     }\
        !           699:     k++;\
        !           700:   }\
        !           701: } while (0)
        !           702: 
        !           703: #define STACK_PUSH_NULL_CHECK_START(cnum, s) do {\
        !           704:   STACK_ENSURE(1);\
        !           705:   stk->type = STK_NULL_CHECK_START;\
        !           706:   stk->u.null_check.num  = (cnum);\
        !           707:   stk->u.null_check.pstr = (s);\
        !           708:   STACK_INC;\
        !           709: } while(0)
        !           710: 
        !           711: #define STACK_PUSH_NULL_CHECK_END(cnum) do {\
        !           712:   STACK_ENSURE(1);\
        !           713:   stk->type = STK_NULL_CHECK_END;\
        !           714:   stk->u.null_check.num  = (cnum);\
        !           715:   STACK_INC;\
        !           716: } while(0)
        !           717: 
        !           718: #define STACK_PUSH_CALL_FRAME(pat) do {\
        !           719:   STACK_ENSURE(1);\
        !           720:   stk->type = STK_CALL_FRAME;\
        !           721:   stk->u.call_frame.ret_addr = (pat);\
        !           722:   STACK_INC;\
        !           723: } while(0)
        !           724: 
        !           725: #define STACK_PUSH_RETURN do {\
        !           726:   STACK_ENSURE(1);\
        !           727:   stk->type = STK_RETURN;\
        !           728:   STACK_INC;\
        !           729: } while(0)
        !           730: 
        !           731: 
        !           732: #ifdef ONIG_DEBUG
        !           733: #define STACK_BASE_CHECK(p, at) \
        !           734:   if ((p) < stk_base) {\
        !           735:     fprintf(stderr, "at %s\n", at);\
        !           736:     goto stack_error;\
        !           737:   }
        !           738: #else
        !           739: #define STACK_BASE_CHECK(p, at)
        !           740: #endif
        !           741: 
        !           742: #define STACK_POP_ONE do {\
        !           743:   stk--;\
        !           744:   STACK_BASE_CHECK(stk, "STACK_POP_ONE"); \
        !           745: } while(0)
        !           746: 
        !           747: #define STACK_POP  do {\
        !           748:   switch (pop_level) {\
        !           749:   case STACK_POP_LEVEL_FREE:\
        !           750:     while (1) {\
        !           751:       stk--;\
        !           752:       STACK_BASE_CHECK(stk, "STACK_POP"); \
        !           753:       if ((stk->type & STK_MASK_POP_USED) != 0)  break;\
        !           754:       ELSE_IF_STATE_CHECK_MARK(stk);\
        !           755:     }\
        !           756:     break;\
        !           757:   case STACK_POP_LEVEL_MEM_START:\
        !           758:     while (1) {\
        !           759:       stk--;\
        !           760:       STACK_BASE_CHECK(stk, "STACK_POP 2"); \
        !           761:       if ((stk->type & STK_MASK_POP_USED) != 0)  break;\
        !           762:       else if (stk->type == STK_MEM_START) {\
        !           763:         mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\
        !           764:         mem_end_stk[stk->u.mem.num]   = stk->u.mem.end;\
        !           765:       }\
        !           766:       ELSE_IF_STATE_CHECK_MARK(stk);\
        !           767:     }\
        !           768:     break;\
        !           769:   default:\
        !           770:     while (1) {\
        !           771:       stk--;\
        !           772:       STACK_BASE_CHECK(stk, "STACK_POP 3"); \
        !           773:       if ((stk->type & STK_MASK_POP_USED) != 0)  break;\
        !           774:       else if (stk->type == STK_MEM_START) {\
        !           775:         mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\
        !           776:         mem_end_stk[stk->u.mem.num]   = stk->u.mem.end;\
        !           777:       }\
        !           778:       else if (stk->type == STK_REPEAT_INC) {\
        !           779:         STACK_AT(stk->u.repeat_inc.si)->u.repeat.count--;\
        !           780:       }\
        !           781:       else if (stk->type == STK_MEM_END) {\
        !           782:         mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\
        !           783:         mem_end_stk[stk->u.mem.num]   = stk->u.mem.end;\
        !           784:       }\
        !           785:       ELSE_IF_STATE_CHECK_MARK(stk);\
        !           786:     }\
        !           787:     break;\
        !           788:   }\
        !           789: } while(0)
        !           790: 
        !           791: #define STACK_POP_TIL_POS_NOT  do {\
        !           792:   while (1) {\
        !           793:     stk--;\
        !           794:     STACK_BASE_CHECK(stk, "STACK_POP_TIL_POS_NOT"); \
        !           795:     if (stk->type == STK_POS_NOT) break;\
        !           796:     else if (stk->type == STK_MEM_START) {\
        !           797:       mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\
        !           798:       mem_end_stk[stk->u.mem.num]   = stk->u.mem.end;\
        !           799:     }\
        !           800:     else if (stk->type == STK_REPEAT_INC) {\
        !           801:       STACK_AT(stk->u.repeat_inc.si)->u.repeat.count--;\
        !           802:     }\
        !           803:     else if (stk->type == STK_MEM_END) {\
        !           804:       mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\
        !           805:       mem_end_stk[stk->u.mem.num]   = stk->u.mem.end;\
        !           806:     }\
        !           807:     ELSE_IF_STATE_CHECK_MARK(stk);\
        !           808:   }\
        !           809: } while(0)
        !           810: 
        !           811: #define STACK_POP_TIL_LOOK_BEHIND_NOT  do {\
        !           812:   while (1) {\
        !           813:     stk--;\
        !           814:     STACK_BASE_CHECK(stk, "STACK_POP_TIL_LOOK_BEHIND_NOT"); \
        !           815:     if (stk->type == STK_LOOK_BEHIND_NOT) break;\
        !           816:     else if (stk->type == STK_MEM_START) {\
        !           817:       mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\
        !           818:       mem_end_stk[stk->u.mem.num]   = stk->u.mem.end;\
        !           819:     }\
        !           820:     else if (stk->type == STK_REPEAT_INC) {\
        !           821:       STACK_AT(stk->u.repeat_inc.si)->u.repeat.count--;\
        !           822:     }\
        !           823:     else if (stk->type == STK_MEM_END) {\
        !           824:       mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\
        !           825:       mem_end_stk[stk->u.mem.num]   = stk->u.mem.end;\
        !           826:     }\
        !           827:     ELSE_IF_STATE_CHECK_MARK(stk);\
        !           828:   }\
        !           829: } while(0)
        !           830: 
        !           831: #define STACK_POS_END(k) do {\
        !           832:   k = stk;\
        !           833:   while (1) {\
        !           834:     k--;\
        !           835:     STACK_BASE_CHECK(k, "STACK_POS_END"); \
        !           836:     if (IS_TO_VOID_TARGET(k)) {\
        !           837:       k->type = STK_VOID;\
        !           838:     }\
        !           839:     else if (k->type == STK_POS) {\
        !           840:       k->type = STK_VOID;\
        !           841:       break;\
        !           842:     }\
        !           843:   }\
        !           844: } while(0)
        !           845: 
        !           846: #define STACK_STOP_BT_END do {\
        !           847:   StackType *k = stk;\
        !           848:   while (1) {\
        !           849:     k--;\
        !           850:     STACK_BASE_CHECK(k, "STACK_STOP_BT_END"); \
        !           851:     if (IS_TO_VOID_TARGET(k)) {\
        !           852:       k->type = STK_VOID;\
        !           853:     }\
        !           854:     else if (k->type == STK_STOP_BT) {\
        !           855:       k->type = STK_VOID;\
        !           856:       break;\
        !           857:     }\
        !           858:   }\
        !           859: } while(0)
        !           860: 
        !           861: #define STACK_NULL_CHECK(isnull,id,s) do {\
        !           862:   StackType* k = stk;\
        !           863:   while (1) {\
        !           864:     k--;\
        !           865:     STACK_BASE_CHECK(k, "STACK_NULL_CHECK"); \
        !           866:     if (k->type == STK_NULL_CHECK_START) {\
        !           867:       if (k->u.null_check.num == (id)) {\
        !           868:         (isnull) = (k->u.null_check.pstr == (s));\
        !           869:         break;\
        !           870:       }\
        !           871:     }\
        !           872:   }\
        !           873: } while(0)
        !           874: 
        !           875: #define STACK_NULL_CHECK_REC(isnull,id,s) do {\
        !           876:   int level = 0;\
        !           877:   StackType* k = stk;\
        !           878:   while (1) {\
        !           879:     k--;\
        !           880:     STACK_BASE_CHECK(k, "STACK_NULL_CHECK_REC"); \
        !           881:     if (k->type == STK_NULL_CHECK_START) {\
        !           882:       if (k->u.null_check.num == (id)) {\
        !           883:         if (level == 0) {\
        !           884:           (isnull) = (k->u.null_check.pstr == (s));\
        !           885:           break;\
        !           886:         }\
        !           887:         else level--;\
        !           888:       }\
        !           889:     }\
        !           890:     else if (k->type == STK_NULL_CHECK_END) {\
        !           891:       level++;\
        !           892:     }\
        !           893:   }\
        !           894: } while(0)
        !           895: 
        !           896: #define STACK_NULL_CHECK_MEMST(isnull,id,s,reg) do {\
        !           897:   StackType* k = stk;\
        !           898:   while (1) {\
        !           899:     k--;\
        !           900:     STACK_BASE_CHECK(k, "STACK_NULL_CHECK_MEMST"); \
        !           901:     if (k->type == STK_NULL_CHECK_START) {\
        !           902:       if (k->u.null_check.num == (id)) {\
        !           903:         if (k->u.null_check.pstr != (s)) {\
        !           904:           (isnull) = 0;\
        !           905:           break;\
        !           906:         }\
        !           907:         else {\
        !           908:           UChar* endp;\
        !           909:           (isnull) = 1;\
        !           910:           while (k < stk) {\
        !           911:             if (k->type == STK_MEM_START) {\
        !           912:               if (k->u.mem.end == INVALID_STACK_INDEX) {\
        !           913:                 (isnull) = 0; break;\
        !           914:               }\
        !           915:               if (BIT_STATUS_AT(reg->bt_mem_end, k->u.mem.num))\
        !           916:                 endp = STACK_AT(k->u.mem.end)->u.mem.pstr;\
        !           917:               else\
        !           918:                 endp = (UChar* )k->u.mem.end;\
        !           919:               if (STACK_AT(k->u.mem.start)->u.mem.pstr != endp) {\
        !           920:                 (isnull) = 0; break;\
        !           921:               }\
        !           922:               else if (endp != s) {\
        !           923:                 (isnull) = -1; /* empty, but position changed */ \
        !           924:               }\
        !           925:             }\
        !           926:             k++;\
        !           927:           }\
        !           928:          break;\
        !           929:         }\
        !           930:       }\
        !           931:     }\
        !           932:   }\
        !           933: } while(0)
        !           934: 
        !           935: #define STACK_NULL_CHECK_MEMST_REC(isnull,id,s,reg) do {\
        !           936:   int level = 0;\
        !           937:   StackType* k = stk;\
        !           938:   while (1) {\
        !           939:     k--;\
        !           940:     STACK_BASE_CHECK(k, "STACK_NULL_CHECK_MEMST_REC"); \
        !           941:     if (k->type == STK_NULL_CHECK_START) {\
        !           942:       if (k->u.null_check.num == (id)) {\
        !           943:         if (level == 0) {\
        !           944:           if (k->u.null_check.pstr != (s)) {\
        !           945:             (isnull) = 0;\
        !           946:             break;\
        !           947:           }\
        !           948:           else {\
        !           949:             UChar* endp;\
        !           950:             (isnull) = 1;\
        !           951:             while (k < stk) {\
        !           952:               if (k->type == STK_MEM_START) {\
        !           953:                 if (k->u.mem.end == INVALID_STACK_INDEX) {\
        !           954:                   (isnull) = 0; break;\
        !           955:                 }\
        !           956:                 if (BIT_STATUS_AT(reg->bt_mem_end, k->u.mem.num))\
        !           957:                   endp = STACK_AT(k->u.mem.end)->u.mem.pstr;\
        !           958:                 else\
        !           959:                   endp = (UChar* )k->u.mem.end;\
        !           960:                 if (STACK_AT(k->u.mem.start)->u.mem.pstr != endp) {\
        !           961:                   (isnull) = 0; break;\
        !           962:                 }\
        !           963:                 else if (endp != s) {\
        !           964:                   (isnull) = -1; /* empty, but position changed */ \
        !           965:                 }\
        !           966:               }\
        !           967:               k++;\
        !           968:             }\
        !           969:            break;\
        !           970:           }\
        !           971:         }\
        !           972:         else {\
        !           973:           level--;\
        !           974:         }\
        !           975:       }\
        !           976:     }\
        !           977:     else if (k->type == STK_NULL_CHECK_END) {\
        !           978:       if (k->u.null_check.num == (id)) level++;\
        !           979:     }\
        !           980:   }\
        !           981: } while(0)
        !           982: 
        !           983: #define STACK_GET_REPEAT(id, k) do {\
        !           984:   int level = 0;\
        !           985:   k = stk;\
        !           986:   while (1) {\
        !           987:     k--;\
        !           988:     STACK_BASE_CHECK(k, "STACK_GET_REPEAT"); \
        !           989:     if (k->type == STK_REPEAT) {\
        !           990:       if (level == 0) {\
        !           991:         if (k->u.repeat.num == (id)) {\
        !           992:           break;\
        !           993:         }\
        !           994:       }\
        !           995:     }\
        !           996:     else if (k->type == STK_CALL_FRAME) level--;\
        !           997:     else if (k->type == STK_RETURN)     level++;\
        !           998:   }\
        !           999: } while (0)
        !          1000: 
        !          1001: #define STACK_RETURN(addr)  do {\
        !          1002:   int level = 0;\
        !          1003:   StackType* k = stk;\
        !          1004:   while (1) {\
        !          1005:     k--;\
        !          1006:     STACK_BASE_CHECK(k, "STACK_RETURN"); \
        !          1007:     if (k->type == STK_CALL_FRAME) {\
        !          1008:       if (level == 0) {\
        !          1009:         (addr) = k->u.call_frame.ret_addr;\
        !          1010:         break;\
        !          1011:       }\
        !          1012:       else level--;\
        !          1013:     }\
        !          1014:     else if (k->type == STK_RETURN)\
        !          1015:       level++;\
        !          1016:   }\
        !          1017: } while(0)
        !          1018: 
        !          1019: 
        !          1020: #define STRING_CMP(s1,s2,len) do {\
        !          1021:   while (len-- > 0) {\
        !          1022:     if (*s1++ != *s2++) goto fail;\
        !          1023:   }\
        !          1024: } while(0)
        !          1025: 
        !          1026: #define STRING_CMP_IC(ambig_flag,s1,ps2,len) do {\
        !          1027:   if (string_cmp_ic(encode, ambig_flag, s1, ps2, len) == 0) \
        !          1028:     goto fail; \
        !          1029: } while(0)
        !          1030: 
        !          1031: static int string_cmp_ic(OnigEncoding enc, int ambig_flag,
        !          1032:                         UChar* s1, UChar** ps2, int mblen)
        !          1033: {
        !          1034:   UChar buf1[ONIGENC_MBC_NORMALIZE_MAXLEN];
        !          1035:   UChar buf2[ONIGENC_MBC_NORMALIZE_MAXLEN];
        !          1036:   UChar *p1, *p2, *end, *s2, *end2;
        !          1037:   int len1, len2;
        !          1038: 
        !          1039:   s2   = *ps2;
        !          1040:   end  = s1 + mblen;
        !          1041:   end2 = s2 + mblen;
        !          1042:   while (s1 < end) {
        !          1043:     len1 = ONIGENC_MBC_TO_NORMALIZE(enc, ambig_flag, &s1, end, buf1);
        !          1044:     len2 = ONIGENC_MBC_TO_NORMALIZE(enc, ambig_flag, &s2, end2, buf2);
        !          1045:     if (len1 != len2) return 0;
        !          1046:     p1 = buf1;
        !          1047:     p2 = buf2;
        !          1048:     while (len1-- > 0) {
        !          1049:       if (*p1 != *p2) return 0;
        !          1050:       p1++;
        !          1051:       p2++;
        !          1052:     }
        !          1053:   }
        !          1054: 
        !          1055:   *ps2 = s2;
        !          1056:   return 1;
        !          1057: }
        !          1058: 
        !          1059: #define STRING_CMP_VALUE(s1,s2,len,is_fail) do {\
        !          1060:   is_fail = 0;\
        !          1061:   while (len-- > 0) {\
        !          1062:     if (*s1++ != *s2++) {\
        !          1063:       is_fail = 1; break;\
        !          1064:     }\
        !          1065:   }\
        !          1066: } while(0)
        !          1067: 
        !          1068: #define STRING_CMP_VALUE_IC(ambig_flag,s1,ps2,len,is_fail) do {\
        !          1069:   if (string_cmp_ic(encode, ambig_flag, s1, ps2, len) == 0) \
        !          1070:     is_fail = 1; \
        !          1071:   else \
        !          1072:     is_fail = 0; \
        !          1073: } while(0)
        !          1074: 
        !          1075: 
        !          1076: #define ON_STR_BEGIN(s)  ((s) == str)
        !          1077: #define ON_STR_END(s)    ((s) == end)
        !          1078: #define IS_EMPTY_STR     (str == end)
        !          1079: 
        !          1080: #define DATA_ENSURE(n) \
        !          1081:   if (s + (n) > end) goto fail
        !          1082: 
        !          1083: #define DATA_ENSURE_CHECK(n)   (s + (n) <= end)
        !          1084: 
        !          1085: #ifdef USE_CAPTURE_HISTORY
        !          1086: static int
        !          1087: make_capture_history_tree(OnigCaptureTreeNode* node, StackType** kp,
        !          1088:                           StackType* stk_top, UChar* str, regex_t* reg)
        !          1089: {
        !          1090:   int n, r;
        !          1091:   OnigCaptureTreeNode* child;
        !          1092:   StackType* k = *kp;
        !          1093: 
        !          1094:   while (k < stk_top) {
        !          1095:     if (k->type == STK_MEM_START) {
        !          1096:       n = k->u.mem.num;
        !          1097:       if (n <= ONIG_MAX_CAPTURE_HISTORY_GROUP &&
        !          1098:           BIT_STATUS_AT(reg->capture_history, n) != 0) {
        !          1099:         child = history_node_new();
        !          1100:         CHECK_NULL_RETURN_VAL(child, ONIGERR_MEMORY);
        !          1101:         child->group = n;
        !          1102:         child->beg = (int )(k->u.mem.pstr - str);
        !          1103:         r = history_tree_add_child(node, child);
        !          1104:         if (r != 0) return r;
        !          1105:         *kp = (k + 1);
        !          1106:         r = make_capture_history_tree(child, kp, stk_top, str, reg);
        !          1107:         if (r != 0) return r;
        !          1108: 
        !          1109:         k = *kp;
        !          1110:         child->end = (int )(k->u.mem.pstr - str);
        !          1111:       }
        !          1112:     }
        !          1113:     else if (k->type == STK_MEM_END) {
        !          1114:       if (k->u.mem.num == node->group) {
        !          1115:         node->end = (int )(k->u.mem.pstr - str);
        !          1116:         *kp = k;
        !          1117:         return 0;
        !          1118:       }
        !          1119:     }
        !          1120:     k++;
        !          1121:   }
        !          1122: 
        !          1123:   return 1; /* 1: root node ending. */
        !          1124: }
        !          1125: #endif
        !          1126: 
        !          1127: #ifdef USE_BACKREF_AT_LEVEL
        !          1128: static int mem_is_in_memp(int mem, int num, UChar* memp)
        !          1129: {
        !          1130:   int i;
        !          1131:   MemNumType m;
        !          1132: 
        !          1133:   for (i = 0; i < num; i++) {
        !          1134:     GET_MEMNUM_INC(m, memp);
        !          1135:     if (mem == (int )m) return 1;
        !          1136:   }
        !          1137:   return 0;
        !          1138: }
        !          1139: 
        !          1140: static int backref_match_at_nested_level(regex_t* reg
        !          1141:         , StackType* top, StackType* stk_base
        !          1142:         , int ignore_case, int ambig_flag
        !          1143:         , int nest, int mem_num, UChar* memp, UChar** s, const UChar* send)
        !          1144: {
        !          1145:   UChar *ss, *p, *pstart, *pend = NULL_UCHARP;
        !          1146:   int level;
        !          1147:   StackType* k;
        !          1148: 
        !          1149:   level = 0;
        !          1150:   k = top;
        !          1151:   k--;
        !          1152:   while (k >= stk_base) {
        !          1153:     if (k->type == STK_CALL_FRAME) {
        !          1154:       level--;
        !          1155:     }
        !          1156:     else if (k->type == STK_RETURN) {
        !          1157:       level++;
        !          1158:     }
        !          1159:     else if (level == nest) {
        !          1160:       if (k->type == STK_MEM_START) {
        !          1161:        if (mem_is_in_memp(k->u.mem.num, mem_num, memp)) {
        !          1162:          pstart = k->u.mem.pstr;
        !          1163:          if (pend != NULL_UCHARP) {
        !          1164:            if (pend - pstart > send - *s) return 0; /* or goto next_mem; */
        !          1165:            p  = pstart;
        !          1166:            ss = *s;
        !          1167: 
        !          1168:            if (ignore_case != 0) {
        !          1169:              if (string_cmp_ic(reg->enc, ambig_flag,
        !          1170:                                pstart, &ss, (int )(pend - pstart)) == 0)
        !          1171:                return 0; /* or goto next_mem; */
        !          1172:            }
        !          1173:            else {
        !          1174:              while (p < pend) {
        !          1175:                if (*p++ != *ss++) return 0; /* or goto next_mem; */
        !          1176:              }
        !          1177:            }
        !          1178: 
        !          1179:            *s = ss;
        !          1180:            return 1;
        !          1181:          }
        !          1182:        }
        !          1183:       }
        !          1184:       else if (k->type == STK_MEM_END) {
        !          1185:        if (mem_is_in_memp(k->u.mem.num, mem_num, memp)) {
        !          1186:          pend = k->u.mem.pstr;
        !          1187:        }
        !          1188:       }
        !          1189:     }
        !          1190:     k--;
        !          1191:   }
        !          1192: 
        !          1193:   return 0;
        !          1194: }
        !          1195: #endif /* USE_BACKREF_AT_LEVEL */
        !          1196: 
        !          1197: 
        !          1198: #ifdef RUBY_PLATFORM
        !          1199: 
        !          1200: typedef struct {
        !          1201:   int state;
        !          1202:   regex_t*  reg;
        !          1203:   MatchArg* msa;
        !          1204:   StackType* stk_base;
        !          1205: } TrapEnsureArg;
        !          1206: 
        !          1207: static VALUE
        !          1208: trap_ensure(VALUE arg)
        !          1209: {
        !          1210:   TrapEnsureArg* ta = (TrapEnsureArg* )arg;
        !          1211: 
        !          1212:   if (ta->state == 0) { /* trap_exec() is not normal return */
        !          1213:     ONIG_STATE_DEC_THREAD(ta->reg);
        !          1214:     if (! IS_NULL(ta->msa->stack_p) && ta->stk_base != ta->msa->stack_p)
        !          1215:       xfree(ta->stk_base);
        !          1216: 
        !          1217:     MATCH_ARG_FREE(*(ta->msa));
        !          1218:   }
        !          1219: 
        !          1220:   return Qnil;
        !          1221: }
        !          1222: 
        !          1223: static VALUE
        !          1224: trap_exec(VALUE arg)
        !          1225: {
        !          1226:   TrapEnsureArg* ta;
        !          1227: 
        !          1228:   rb_trap_exec();
        !          1229: 
        !          1230:   ta = (TrapEnsureArg* )arg;
        !          1231:   ta->state = 1; /* normal return */
        !          1232:   return Qnil;
        !          1233: }
        !          1234: 
        !          1235: extern void
        !          1236: onig_exec_trap(regex_t* reg, MatchArg* msa, StackType* stk_base)
        !          1237: {
        !          1238:   VALUE arg;
        !          1239:   TrapEnsureArg ta;
        !          1240: 
        !          1241:   ta.state    = 0;
        !          1242:   ta.reg      = reg;
        !          1243:   ta.msa      = msa;
        !          1244:   ta.stk_base = stk_base;
        !          1245:   arg = (VALUE )(&ta);
        !          1246:   rb_ensure(trap_exec, arg, trap_ensure, arg);
        !          1247: }
        !          1248: 
        !          1249: #define CHECK_INTERRUPT_IN_MATCH_AT do {\
        !          1250:   if (rb_trap_pending) {\
        !          1251:     if (! rb_prohibit_interrupt) {\
        !          1252:       onig_exec_trap(reg, msa, stk_base);\
        !          1253:     }\
        !          1254:   }\
        !          1255: } while (0)
        !          1256: #else
        !          1257: #define CHECK_INTERRUPT_IN_MATCH_AT
        !          1258: #endif /* RUBY_PLATFORM */
        !          1259: 
        !          1260: #ifdef ONIG_DEBUG_STATISTICS
        !          1261: 
        !          1262: #define USE_TIMEOFDAY
        !          1263: 
        !          1264: #ifdef USE_TIMEOFDAY
        !          1265: #ifdef HAVE_SYS_TIME_H
        !          1266: #include <sys/time.h>
        !          1267: #endif
        !          1268: #ifdef HAVE_UNISTD_H
        !          1269: #include <unistd.h>
        !          1270: #endif
        !          1271: static struct timeval ts, te;
        !          1272: #define GETTIME(t)        gettimeofday(&(t), (struct timezone* )0)
        !          1273: #define TIMEDIFF(te,ts)   (((te).tv_usec - (ts).tv_usec) + \
        !          1274:                            (((te).tv_sec - (ts).tv_sec)*1000000))
        !          1275: #else
        !          1276: #ifdef HAVE_SYS_TIMES_H
        !          1277: #include <sys/times.h>
        !          1278: #endif
        !          1279: static struct tms ts, te;
        !          1280: #define GETTIME(t)         times(&(t))
        !          1281: #define TIMEDIFF(te,ts)   ((te).tms_utime - (ts).tms_utime)
        !          1282: #endif
        !          1283: 
        !          1284: static int OpCounter[256];
        !          1285: static int OpPrevCounter[256];
        !          1286: static unsigned long OpTime[256];
        !          1287: static int OpCurr = OP_FINISH;
        !          1288: static int OpPrevTarget = OP_FAIL;
        !          1289: static int MaxStackDepth = 0;
        !          1290: 
        !          1291: #define STAT_OP_IN(opcode) do {\
        !          1292:   if (opcode == OpPrevTarget) OpPrevCounter[OpCurr]++;\
        !          1293:   OpCurr = opcode;\
        !          1294:   OpCounter[opcode]++;\
        !          1295:   GETTIME(ts);\
        !          1296: } while (0)
        !          1297: 
        !          1298: #define STAT_OP_OUT do {\
        !          1299:   GETTIME(te);\
        !          1300:   OpTime[OpCurr] += TIMEDIFF(te, ts);\
        !          1301: } while (0)
        !          1302: 
        !          1303: #ifdef RUBY_PLATFORM
        !          1304: 
        !          1305: /*
        !          1306:  * :nodoc:
        !          1307:  */
        !          1308: static VALUE onig_stat_print(void)
        !          1309: {
        !          1310:   onig_print_statistics(stderr);
        !          1311:   return Qnil;
        !          1312: }
        !          1313: #endif
        !          1314: 
        !          1315: extern void onig_statistics_init(void)
        !          1316: {
        !          1317:   int i;
        !          1318:   for (i = 0; i < 256; i++) {
        !          1319:     OpCounter[i] = OpPrevCounter[i] = 0; OpTime[i] = 0;
        !          1320:   }
        !          1321:   MaxStackDepth = 0;
        !          1322: 
        !          1323: #ifdef RUBY_PLATFORM
        !          1324:   rb_define_global_function("onig_stat_print", onig_stat_print, 0);
        !          1325: #endif
        !          1326: }
        !          1327: 
        !          1328: extern void
        !          1329: onig_print_statistics(FILE* f)
        !          1330: {
        !          1331:   int i;
        !          1332:   fprintf(f, "   count      prev        time\n");
        !          1333:   for (i = 0; OnigOpInfo[i].opcode >= 0; i++) {
        !          1334:     fprintf(f, "%8d: %8d: %10ld: %s\n",
        !          1335:            OpCounter[i], OpPrevCounter[i], OpTime[i], OnigOpInfo[i].name);
        !          1336:   }
        !          1337:   fprintf(f, "\nmax stack depth: %d\n", MaxStackDepth);
        !          1338: }
        !          1339: 
        !          1340: #define STACK_INC do {\
        !          1341:   stk++;\
        !          1342:   if (stk - stk_base > MaxStackDepth) \
        !          1343:     MaxStackDepth = stk - stk_base;\
        !          1344: } while (0)
        !          1345: 
        !          1346: #else
        !          1347: #define STACK_INC     stk++
        !          1348: 
        !          1349: #define STAT_OP_IN(opcode)
        !          1350: #define STAT_OP_OUT
        !          1351: #endif
        !          1352: 
        !          1353: extern int
        !          1354: onig_is_in_code_range(const UChar* p, OnigCodePoint code)
        !          1355: {
        !          1356:   OnigCodePoint n, *data;
        !          1357:   OnigCodePoint low, high, x;
        !          1358: 
        !          1359:   GET_CODE_POINT(n, p);
        !          1360:   data = (OnigCodePoint* )p;
        !          1361:   data++;
        !          1362: 
        !          1363:   for (low = 0, high = n; low < high; ) {
        !          1364:     x = (low + high) >> 1;
        !          1365:     if (code > data[x * 2 + 1])
        !          1366:       low = x + 1;
        !          1367:     else
        !          1368:       high = x;
        !          1369:   }
        !          1370: 
        !          1371:   return ((low < n && code >= data[low * 2]) ? 1 : 0);
        !          1372: }
        !          1373: 
        !          1374: static int
        !          1375: is_code_in_cc(int enclen, OnigCodePoint code, CClassNode* cc)
        !          1376: {
        !          1377:   int found;
        !          1378: 
        !          1379:   if (enclen > 1 || (code >= SINGLE_BYTE_SIZE)) {
        !          1380:     if (IS_NULL(cc->mbuf)) {
        !          1381:       found = 0;
        !          1382:     }
        !          1383:     else {
        !          1384:       found = (onig_is_in_code_range(cc->mbuf->p, code) != 0 ? 1 : 0);
        !          1385:     }
        !          1386:   }
        !          1387:   else {
        !          1388:     found = (BITSET_AT(cc->bs, code) == 0 ? 0 : 1);
        !          1389:   }
        !          1390: 
        !          1391:   if (IS_CCLASS_NOT(cc))
        !          1392:     return !found;
        !          1393:   else
        !          1394:     return found;
        !          1395: }
        !          1396: 
        !          1397: extern int
        !          1398: onig_is_code_in_cc(OnigEncoding enc, OnigCodePoint code, CClassNode* cc)
        !          1399: {
        !          1400:   int len;
        !          1401: 
        !          1402:   if (ONIGENC_MBC_MINLEN(enc) > 1) {
        !          1403:     len = 2;
        !          1404:   }
        !          1405:   else {
        !          1406:     len = ONIGENC_CODE_TO_MBCLEN(enc, code);
        !          1407:   }
        !          1408:   return is_code_in_cc(len, code, cc);
        !          1409: }
        !          1410: 
        !          1411: 
        !          1412: /* matching region of POSIX API */
        !          1413: typedef int regoff_t;
        !          1414: 
        !          1415: typedef struct {
        !          1416:   regoff_t  rm_so;
        !          1417:   regoff_t  rm_eo;
        !          1418: } posix_regmatch_t;
        !          1419: 
        !          1420: /* match data(str - end) from position (sstart). */
        !          1421: /* if sstart == str then set sprev to NULL. */
        !          1422: static int
        !          1423: match_at(regex_t* reg, const UChar* str, const UChar* end, const UChar* sstart,
        !          1424:         UChar* sprev, MatchArg* msa)
        !          1425: {
        !          1426:   static UChar FinishCode[] = { OP_FINISH };
        !          1427: 
        !          1428:   int i, n, num_mem, best_len, pop_level;
        !          1429:   LengthType tlen, tlen2;
        !          1430:   MemNumType mem;
        !          1431:   RelAddrType addr;
        !          1432:   OnigOptionType option = reg->options;
        !          1433:   OnigEncoding encode = reg->enc;
        !          1434:   OnigAmbigType ambig_flag = reg->ambig_flag;
        !          1435:   UChar *s, *q, *sbegin;
        !          1436:   UChar *p = reg->p;
        !          1437:   char *alloca_base;
        !          1438:   StackType *stk_alloc, *stk_base, *stk, *stk_end;
        !          1439:   StackType *stkp; /* used as any purpose. */
        !          1440:   StackIndex si;
        !          1441:   StackIndex *repeat_stk;
        !          1442:   StackIndex *mem_start_stk, *mem_end_stk;
        !          1443: #ifdef USE_COMBINATION_EXPLOSION_CHECK
        !          1444:   int scv;
        !          1445:   unsigned char* state_check_buff = msa->state_check_buff;
        !          1446:   int num_comb_exp_check = reg->num_comb_exp_check;
        !          1447: #endif
        !          1448:   n = reg->num_repeat + reg->num_mem * 2;
        !          1449: 
        !          1450:   STACK_INIT(alloca_base, n, INIT_MATCH_STACK_SIZE);
        !          1451:   pop_level = reg->stack_pop_level;
        !          1452:   num_mem = reg->num_mem;
        !          1453:   repeat_stk = (StackIndex* )alloca_base;
        !          1454: 
        !          1455:   mem_start_stk = (StackIndex* )(repeat_stk + reg->num_repeat);
        !          1456:   mem_end_stk   = mem_start_stk + num_mem;
        !          1457:   mem_start_stk--; /* for index start from 1,
        !          1458:                      mem_start_stk[1]..mem_start_stk[num_mem] */
        !          1459:   mem_end_stk--;   /* for index start from 1,
        !          1460:                      mem_end_stk[1]..mem_end_stk[num_mem] */
        !          1461:   for (i = 1; i <= num_mem; i++) {
        !          1462:     mem_start_stk[i] = mem_end_stk[i] = INVALID_STACK_INDEX;
        !          1463:   }
        !          1464: 
        !          1465: #ifdef ONIG_DEBUG_MATCH
        !          1466:   fprintf(stderr, "match_at: str: %d, end: %d, start: %d, sprev: %d\n",
        !          1467:          (int )str, (int )end, (int )sstart, (int )sprev);
        !          1468:   fprintf(stderr, "size: %d, start offset: %d\n",
        !          1469:          (int )(end - str), (int )(sstart - str));
        !          1470: #endif
        !          1471: 
        !          1472:   STACK_PUSH_ENSURED(STK_ALT, FinishCode);  /* bottom stack */
        !          1473:   best_len = ONIG_MISMATCH;
        !          1474:   s = (UChar* )sstart;
        !          1475:   while (1) {
        !          1476: #ifdef ONIG_DEBUG_MATCH
        !          1477:     {
        !          1478:       UChar *q, *bp, buf[50];
        !          1479:       int len;
        !          1480:       fprintf(stderr, "%4d> \"", (int )(s - str));
        !          1481:       bp = buf;
        !          1482:       for (i = 0, q = s; i < 7 && q < end; i++) {
        !          1483:        len = enc_len(encode, q);
        !          1484:        while (len-- > 0) *bp++ = *q++;
        !          1485:       }
        !          1486:       if (q < end) { xmemcpy(bp, "...\"", 4); bp += 4; }
        !          1487:       else         { xmemcpy(bp, "\"",    1); bp += 1; }
        !          1488:       *bp = 0;
        !          1489:       fputs(buf, stderr);
        !          1490:       for (i = 0; i < 20 - (bp - buf); i++) fputc(' ', stderr);
        !          1491:       onig_print_compiled_byte_code(stderr, p, NULL, encode);
        !          1492:       fprintf(stderr, "\n");
        !          1493:     }
        !          1494: #endif
        !          1495: 
        !          1496:     sbegin = s;
        !          1497:     switch (*p++) {
        !          1498:     case OP_END:  STAT_OP_IN(OP_END);
        !          1499:       n = s - sstart;
        !          1500:       if (n > best_len) {
        !          1501:        OnigRegion* region;
        !          1502: #ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE
        !          1503:        if (IS_FIND_LONGEST(option)) {
        !          1504:          if (n > msa->best_len) {
        !          1505:            msa->best_len = n;
        !          1506:            msa->best_s   = (UChar* )sstart;
        !          1507:          }
        !          1508:          else
        !          1509:            goto end_best_len;
        !          1510:         }
        !          1511: #endif
        !          1512:        best_len = n;
        !          1513:        region = msa->region;
        !          1514:        if (region) {
        !          1515: #ifdef USE_POSIX_REGION_OPTION
        !          1516:          if (IS_POSIX_REGION(msa->options)) {
        !          1517:            posix_regmatch_t* rmt = (posix_regmatch_t* )region;
        !          1518: 
        !          1519:            rmt[0].rm_so = sstart - str;
        !          1520:            rmt[0].rm_eo = s      - str;
        !          1521:            for (i = 1; i <= num_mem; i++) {
        !          1522:              if (mem_end_stk[i] != INVALID_STACK_INDEX) {
        !          1523:                if (BIT_STATUS_AT(reg->bt_mem_start, i))
        !          1524:                  rmt[i].rm_so = STACK_AT(mem_start_stk[i])->u.mem.pstr - str;
        !          1525:                else
        !          1526:                  rmt[i].rm_so = (UChar* )((void* )(mem_start_stk[i])) - str;
        !          1527: 
        !          1528:                rmt[i].rm_eo = (BIT_STATUS_AT(reg->bt_mem_end, i)
        !          1529:                                ? STACK_AT(mem_end_stk[i])->u.mem.pstr
        !          1530:                                : (UChar* )((void* )mem_end_stk[i])) - str;
        !          1531:              }
        !          1532:              else {
        !          1533:                rmt[i].rm_so = rmt[i].rm_eo = ONIG_REGION_NOTPOS;
        !          1534:              }
        !          1535:            }
        !          1536:          }
        !          1537:          else {
        !          1538: #endif /* USE_POSIX_REGION_OPTION */
        !          1539:            region->beg[0] = sstart - str;
        !          1540:            region->end[0] = s      - str;
        !          1541:            for (i = 1; i <= num_mem; i++) {
        !          1542:              if (mem_end_stk[i] != INVALID_STACK_INDEX) {
        !          1543:                if (BIT_STATUS_AT(reg->bt_mem_start, i))
        !          1544:                  region->beg[i] = STACK_AT(mem_start_stk[i])->u.mem.pstr - str;
        !          1545:                else
        !          1546:                  region->beg[i] = (UChar* )((void* )mem_start_stk[i]) - str;
        !          1547: 
        !          1548:                region->end[i] = (BIT_STATUS_AT(reg->bt_mem_end, i)
        !          1549:                                  ? STACK_AT(mem_end_stk[i])->u.mem.pstr
        !          1550:                                  : (UChar* )((void* )mem_end_stk[i])) - str;
        !          1551:              }
        !          1552:              else {
        !          1553:                region->beg[i] = region->end[i] = ONIG_REGION_NOTPOS;
        !          1554:              }
        !          1555:            }
        !          1556: 
        !          1557: #ifdef USE_CAPTURE_HISTORY
        !          1558:            if (reg->capture_history != 0) {
        !          1559:               int r;
        !          1560:               OnigCaptureTreeNode* node;
        !          1561: 
        !          1562:               if (IS_NULL(region->history_root)) {
        !          1563:                 region->history_root = node = history_node_new();
        !          1564:                 CHECK_NULL_RETURN_VAL(node, ONIGERR_MEMORY);
        !          1565:               }
        !          1566:               else {
        !          1567:                 node = region->history_root;
        !          1568:                 history_tree_clear(node);
        !          1569:               }
        !          1570: 
        !          1571:               node->group = 0;
        !          1572:               node->beg   = sstart - str;
        !          1573:               node->end   = s      - str;
        !          1574: 
        !          1575:               stkp = stk_base;
        !          1576:               r = make_capture_history_tree(region->history_root, &stkp,
        !          1577:                                             stk, (UChar* )str, reg);
        !          1578:               if (r < 0) {
        !          1579:                 best_len = r; /* error code */
        !          1580:                 goto finish;
        !          1581:               }
        !          1582:            }
        !          1583: #endif /* USE_CAPTURE_HISTORY */
        !          1584: #ifdef USE_POSIX_REGION_OPTION
        !          1585:          } /* else IS_POSIX_REGION() */
        !          1586: #endif
        !          1587:        } /* if (region) */
        !          1588:       } /* n > best_len */
        !          1589: 
        !          1590: #ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE
        !          1591:     end_best_len:
        !          1592: #endif
        !          1593:       STAT_OP_OUT;
        !          1594: 
        !          1595:       if (IS_FIND_CONDITION(option)) {
        !          1596:        if (IS_FIND_NOT_EMPTY(option) && s == sstart) {
        !          1597:          best_len = ONIG_MISMATCH;
        !          1598:          goto fail; /* for retry */
        !          1599:        }
        !          1600:        if (IS_FIND_LONGEST(option) && s < end) {
        !          1601:          goto fail; /* for retry */
        !          1602:        }
        !          1603:       }
        !          1604: 
        !          1605:       /* default behavior: return first-matching result. */
        !          1606:       goto finish;
        !          1607:       break;
        !          1608: 
        !          1609:     case OP_EXACT1:  STAT_OP_IN(OP_EXACT1);
        !          1610: #if 0
        !          1611:       DATA_ENSURE(1);
        !          1612:       if (*p != *s) goto fail;
        !          1613:       p++; s++;
        !          1614: #endif
        !          1615:       if (*p != *s++) goto fail;
        !          1616:       DATA_ENSURE(0);
        !          1617:       p++;
        !          1618:       STAT_OP_OUT;
        !          1619:       break;
        !          1620: 
        !          1621:     case OP_EXACT1_IC:  STAT_OP_IN(OP_EXACT1_IC);
        !          1622:       {
        !          1623:        int len;
        !          1624:        UChar *q, *ss, *sp, lowbuf[ONIGENC_MBC_NORMALIZE_MAXLEN];
        !          1625: 
        !          1626:        DATA_ENSURE(1);
        !          1627:         ss = s;
        !          1628:         sp = p;
        !          1629: 
        !          1630:        len = ONIGENC_MBC_TO_NORMALIZE(encode, ambig_flag, &s, end, lowbuf);
        !          1631:        DATA_ENSURE(0);
        !          1632:        q = lowbuf;
        !          1633:        while (len-- > 0) {
        !          1634:          if (*p != *q) {
        !          1635:             goto fail;
        !          1636:           }
        !          1637:          p++; q++;
        !          1638:        }
        !          1639:       }
        !          1640:       STAT_OP_OUT;
        !          1641:       break;
        !          1642: 
        !          1643:     case OP_EXACT2:  STAT_OP_IN(OP_EXACT2);
        !          1644:       DATA_ENSURE(2);
        !          1645:       if (*p != *s) goto fail;
        !          1646:       p++; s++;
        !          1647:       if (*p != *s) goto fail;
        !          1648:       sprev = s;
        !          1649:       p++; s++;
        !          1650:       STAT_OP_OUT;
        !          1651:       continue;
        !          1652:       break;
        !          1653: 
        !          1654:     case OP_EXACT3:  STAT_OP_IN(OP_EXACT3);
        !          1655:       DATA_ENSURE(3);
        !          1656:       if (*p != *s) goto fail;
        !          1657:       p++; s++;
        !          1658:       if (*p != *s) goto fail;
        !          1659:       p++; s++;
        !          1660:       if (*p != *s) goto fail;
        !          1661:       sprev = s;
        !          1662:       p++; s++;
        !          1663:       STAT_OP_OUT;
        !          1664:       continue;
        !          1665:       break;
        !          1666: 
        !          1667:     case OP_EXACT4:  STAT_OP_IN(OP_EXACT4);
        !          1668:       DATA_ENSURE(4);
        !          1669:       if (*p != *s) goto fail;
        !          1670:       p++; s++;
        !          1671:       if (*p != *s) goto fail;
        !          1672:       p++; s++;
        !          1673:       if (*p != *s) goto fail;
        !          1674:       p++; s++;
        !          1675:       if (*p != *s) goto fail;
        !          1676:       sprev = s;
        !          1677:       p++; s++;
        !          1678:       STAT_OP_OUT;
        !          1679:       continue;
        !          1680:       break;
        !          1681: 
        !          1682:     case OP_EXACT5:  STAT_OP_IN(OP_EXACT5);
        !          1683:       DATA_ENSURE(5);
        !          1684:       if (*p != *s) goto fail;
        !          1685:       p++; s++;
        !          1686:       if (*p != *s) goto fail;
        !          1687:       p++; s++;
        !          1688:       if (*p != *s) goto fail;
        !          1689:       p++; s++;
        !          1690:       if (*p != *s) goto fail;
        !          1691:       p++; s++;
        !          1692:       if (*p != *s) goto fail;
        !          1693:       sprev = s;
        !          1694:       p++; s++;
        !          1695:       STAT_OP_OUT;
        !          1696:       continue;
        !          1697:       break;
        !          1698: 
        !          1699:     case OP_EXACTN:  STAT_OP_IN(OP_EXACTN);
        !          1700:       GET_LENGTH_INC(tlen, p);
        !          1701:       DATA_ENSURE(tlen);
        !          1702:       while (tlen-- > 0) {
        !          1703:        if (*p++ != *s++) goto fail;
        !          1704:       }
        !          1705:       sprev = s - 1;
        !          1706:       STAT_OP_OUT;
        !          1707:       continue;
        !          1708:       break;
        !          1709: 
        !          1710:     case OP_EXACTN_IC:  STAT_OP_IN(OP_EXACTN_IC);
        !          1711:       {
        !          1712:        int len;
        !          1713:        UChar *ss, *sp, *q, *endp, lowbuf[ONIGENC_MBC_NORMALIZE_MAXLEN];
        !          1714: 
        !          1715:        GET_LENGTH_INC(tlen, p);
        !          1716:        endp = p + tlen;
        !          1717: 
        !          1718:        while (p < endp) {
        !          1719:          sprev = s;
        !          1720:          DATA_ENSURE(1);
        !          1721:           ss = s;
        !          1722:           sp = p;
        !          1723: 
        !          1724:          len = ONIGENC_MBC_TO_NORMALIZE(encode, ambig_flag, &s, end, lowbuf);
        !          1725:          DATA_ENSURE(0);
        !          1726:          q = lowbuf;
        !          1727:          while (len-- > 0) {
        !          1728:            if (*p != *q) {
        !          1729:               goto fail;
        !          1730:             }
        !          1731:            p++; q++;
        !          1732:          }
        !          1733:        }
        !          1734:       }
        !          1735: 
        !          1736:       STAT_OP_OUT;
        !          1737:       continue;
        !          1738:       break;
        !          1739: 
        !          1740:     case OP_EXACTMB2N1:  STAT_OP_IN(OP_EXACTMB2N1);
        !          1741:       DATA_ENSURE(2);
        !          1742:       if (*p != *s) goto fail;
        !          1743:       p++; s++;
        !          1744:       if (*p != *s) goto fail;
        !          1745:       p++; s++;
        !          1746:       STAT_OP_OUT;
        !          1747:       break;
        !          1748: 
        !          1749:     case OP_EXACTMB2N2:  STAT_OP_IN(OP_EXACTMB2N2);
        !          1750:       DATA_ENSURE(4);
        !          1751:       if (*p != *s) goto fail;
        !          1752:       p++; s++;
        !          1753:       if (*p != *s) goto fail;
        !          1754:       p++; s++;
        !          1755:       sprev = s;
        !          1756:       if (*p != *s) goto fail;
        !          1757:       p++; s++;
        !          1758:       if (*p != *s) goto fail;
        !          1759:       p++; s++;
        !          1760:       STAT_OP_OUT;
        !          1761:       continue;
        !          1762:       break;
        !          1763: 
        !          1764:     case OP_EXACTMB2N3:  STAT_OP_IN(OP_EXACTMB2N3);
        !          1765:       DATA_ENSURE(6);
        !          1766:       if (*p != *s) goto fail;
        !          1767:       p++; s++;
        !          1768:       if (*p != *s) goto fail;
        !          1769:       p++; s++;
        !          1770:       if (*p != *s) goto fail;
        !          1771:       p++; s++;
        !          1772:       if (*p != *s) goto fail;
        !          1773:       p++; s++;
        !          1774:       sprev = s;
        !          1775:       if (*p != *s) goto fail;
        !          1776:       p++; s++;
        !          1777:       if (*p != *s) goto fail;
        !          1778:       p++; s++;
        !          1779:       STAT_OP_OUT;
        !          1780:       continue;
        !          1781:       break;
        !          1782: 
        !          1783:     case OP_EXACTMB2N:  STAT_OP_IN(OP_EXACTMB2N);
        !          1784:       GET_LENGTH_INC(tlen, p);
        !          1785:       DATA_ENSURE(tlen * 2);
        !          1786:       while (tlen-- > 0) {
        !          1787:        if (*p != *s) goto fail;
        !          1788:        p++; s++;
        !          1789:        if (*p != *s) goto fail;
        !          1790:        p++; s++;
        !          1791:       }
        !          1792:       sprev = s - 2;
        !          1793:       STAT_OP_OUT;
        !          1794:       continue;
        !          1795:       break;
        !          1796: 
        !          1797:     case OP_EXACTMB3N:  STAT_OP_IN(OP_EXACTMB3N);
        !          1798:       GET_LENGTH_INC(tlen, p);
        !          1799:       DATA_ENSURE(tlen * 3);
        !          1800:       while (tlen-- > 0) {
        !          1801:        if (*p != *s) goto fail;
        !          1802:        p++; s++;
        !          1803:        if (*p != *s) goto fail;
        !          1804:        p++; s++;
        !          1805:        if (*p != *s) goto fail;
        !          1806:        p++; s++;
        !          1807:       }
        !          1808:       sprev = s - 3;
        !          1809:       STAT_OP_OUT;
        !          1810:       continue;
        !          1811:       break;
        !          1812: 
        !          1813:     case OP_EXACTMBN:  STAT_OP_IN(OP_EXACTMBN);
        !          1814:       GET_LENGTH_INC(tlen,  p);  /* mb-len */
        !          1815:       GET_LENGTH_INC(tlen2, p);  /* string len */
        !          1816:       tlen2 *= tlen;
        !          1817:       DATA_ENSURE(tlen2);
        !          1818:       while (tlen2-- > 0) {
        !          1819:        if (*p != *s) goto fail;
        !          1820:        p++; s++;
        !          1821:       }
        !          1822:       sprev = s - tlen;
        !          1823:       STAT_OP_OUT;
        !          1824:       continue;
        !          1825:       break;
        !          1826: 
        !          1827:     case OP_CCLASS:  STAT_OP_IN(OP_CCLASS);
        !          1828:       DATA_ENSURE(1);
        !          1829:       if (BITSET_AT(((BitSetRef )p), *s) == 0) goto fail;
        !          1830:       p += SIZE_BITSET;
        !          1831:       s += enc_len(encode, s);   /* OP_CCLASS can match mb-code. \D, \S */
        !          1832:       STAT_OP_OUT;
        !          1833:       break;
        !          1834: 
        !          1835:     case OP_CCLASS_MB:  STAT_OP_IN(OP_CCLASS_MB);
        !          1836:       if (! ONIGENC_IS_MBC_HEAD(encode, s)) goto fail;
        !          1837: 
        !          1838:     cclass_mb:
        !          1839:       GET_LENGTH_INC(tlen, p);
        !          1840:       {
        !          1841:        OnigCodePoint code;
        !          1842:        UChar *ss;
        !          1843:        int mb_len;
        !          1844: 
        !          1845:        DATA_ENSURE(1);
        !          1846:        mb_len = enc_len(encode, s);
        !          1847:        DATA_ENSURE(mb_len);
        !          1848:        ss = s;
        !          1849:        s += mb_len;
        !          1850:        code = ONIGENC_MBC_TO_CODE(encode, ss, s);
        !          1851: 
        !          1852: #ifdef PLATFORM_UNALIGNED_WORD_ACCESS
        !          1853:        if (! onig_is_in_code_range(p, code)) goto fail;
        !          1854: #else
        !          1855:        q = p;
        !          1856:        ALIGNMENT_RIGHT(q);
        !          1857:        if (! onig_is_in_code_range(q, code)) goto fail;
        !          1858: #endif
        !          1859:       }
        !          1860:       p += tlen;
        !          1861:       STAT_OP_OUT;
        !          1862:       break;
        !          1863: 
        !          1864:     case OP_CCLASS_MIX:  STAT_OP_IN(OP_CCLASS_MIX);
        !          1865:       DATA_ENSURE(1);
        !          1866:       if (ONIGENC_IS_MBC_HEAD(encode, s)) {
        !          1867:        p += SIZE_BITSET;
        !          1868:        goto cclass_mb;
        !          1869:       }
        !          1870:       else {
        !          1871:        if (BITSET_AT(((BitSetRef )p), *s) == 0)
        !          1872:          goto fail;
        !          1873: 
        !          1874:        p += SIZE_BITSET;
        !          1875:        GET_LENGTH_INC(tlen, p);
        !          1876:        p += tlen;
        !          1877:        s++;
        !          1878:       }
        !          1879:       STAT_OP_OUT;
        !          1880:       break;
        !          1881: 
        !          1882:     case OP_CCLASS_NOT:  STAT_OP_IN(OP_CCLASS_NOT);
        !          1883:       DATA_ENSURE(1);
        !          1884:       if (BITSET_AT(((BitSetRef )p), *s) != 0) goto fail;
        !          1885:       p += SIZE_BITSET;
        !          1886:       s += enc_len(encode, s);
        !          1887:       STAT_OP_OUT;
        !          1888:       break;
        !          1889: 
        !          1890:     case OP_CCLASS_MB_NOT:  STAT_OP_IN(OP_CCLASS_MB_NOT);
        !          1891:       DATA_ENSURE(1);
        !          1892:       if (! ONIGENC_IS_MBC_HEAD(encode, s)) {
        !          1893:        s++;
        !          1894:        GET_LENGTH_INC(tlen, p);
        !          1895:        p += tlen;
        !          1896:        goto cc_mb_not_success;
        !          1897:       }
        !          1898: 
        !          1899:     cclass_mb_not:
        !          1900:       GET_LENGTH_INC(tlen, p);
        !          1901:       {
        !          1902:        OnigCodePoint code;
        !          1903:        UChar *ss;
        !          1904:        int mb_len = enc_len(encode, s);
        !          1905: 
        !          1906:        if (s + mb_len > end) {
        !          1907:           DATA_ENSURE(1);
        !          1908:          s = (UChar* )end;
        !          1909:          p += tlen;
        !          1910:          goto cc_mb_not_success;
        !          1911:        }
        !          1912: 
        !          1913:        ss = s;
        !          1914:        s += mb_len;
        !          1915:        code = ONIGENC_MBC_TO_CODE(encode, ss, s);
        !          1916: 
        !          1917: #ifdef PLATFORM_UNALIGNED_WORD_ACCESS
        !          1918:        if (onig_is_in_code_range(p, code)) goto fail;
        !          1919: #else
        !          1920:        q = p;
        !          1921:        ALIGNMENT_RIGHT(q);
        !          1922:        if (onig_is_in_code_range(q, code)) goto fail;
        !          1923: #endif
        !          1924:       }
        !          1925:       p += tlen;
        !          1926: 
        !          1927:     cc_mb_not_success:
        !          1928:       STAT_OP_OUT;
        !          1929:       break;
        !          1930: 
        !          1931:     case OP_CCLASS_MIX_NOT:  STAT_OP_IN(OP_CCLASS_MIX_NOT);
        !          1932:       DATA_ENSURE(1);
        !          1933:       if (ONIGENC_IS_MBC_HEAD(encode, s)) {
        !          1934:        p += SIZE_BITSET;
        !          1935:        goto cclass_mb_not;
        !          1936:       }
        !          1937:       else {
        !          1938:        if (BITSET_AT(((BitSetRef )p), *s) != 0)
        !          1939:          goto fail;
        !          1940: 
        !          1941:        p += SIZE_BITSET;
        !          1942:        GET_LENGTH_INC(tlen, p);
        !          1943:        p += tlen;
        !          1944:        s++;
        !          1945:       }
        !          1946:       STAT_OP_OUT;
        !          1947:       break;
        !          1948: 
        !          1949:     case OP_CCLASS_NODE:  STAT_OP_IN(OP_CCLASS_NODE);
        !          1950:       {
        !          1951:        OnigCodePoint code;
        !          1952:         void *node;
        !          1953:         int mb_len;
        !          1954:         UChar *ss;
        !          1955: 
        !          1956:         DATA_ENSURE(1);
        !          1957:         GET_POINTER_INC(node, p);
        !          1958:        mb_len = enc_len(encode, s);
        !          1959:        ss = s;
        !          1960:        s += mb_len;
        !          1961:        DATA_ENSURE(0);
        !          1962:        code = ONIGENC_MBC_TO_CODE(encode, ss, s);
        !          1963:        if (is_code_in_cc(mb_len, code, node) == 0) goto fail;
        !          1964:       }
        !          1965:       STAT_OP_OUT;
        !          1966:       break;
        !          1967: 
        !          1968:     case OP_ANYCHAR:  STAT_OP_IN(OP_ANYCHAR);
        !          1969:       DATA_ENSURE(1);
        !          1970:       n = enc_len(encode, s);
        !          1971:       DATA_ENSURE(n);
        !          1972:       if (ONIGENC_IS_MBC_NEWLINE(encode, s, end)) goto fail;
        !          1973:       s += n;
        !          1974:       STAT_OP_OUT;
        !          1975:       break;
        !          1976: 
        !          1977:     case OP_ANYCHAR_ML:  STAT_OP_IN(OP_ANYCHAR_ML);
        !          1978:       DATA_ENSURE(1);
        !          1979:       n = enc_len(encode, s);
        !          1980:       DATA_ENSURE(n);
        !          1981:       s += n;
        !          1982:       STAT_OP_OUT;
        !          1983:       break;
        !          1984: 
        !          1985:     case OP_ANYCHAR_STAR:  STAT_OP_IN(OP_ANYCHAR_STAR);
        !          1986:       while (s < end) {
        !          1987:        STACK_PUSH_ALT(p, s, sprev);
        !          1988:        n = enc_len(encode, s);
        !          1989:         DATA_ENSURE(n);
        !          1990:         if (ONIGENC_IS_MBC_NEWLINE(encode, s, end))  goto fail;
        !          1991:         sprev = s;
        !          1992:         s += n;
        !          1993:       }
        !          1994:       STAT_OP_OUT;
        !          1995:       break;
        !          1996: 
        !          1997:     case OP_ANYCHAR_ML_STAR:  STAT_OP_IN(OP_ANYCHAR_ML_STAR);
        !          1998:       while (s < end) {
        !          1999:        STACK_PUSH_ALT(p, s, sprev);
        !          2000:        n = enc_len(encode, s);
        !          2001:        if (n > 1) {
        !          2002:          DATA_ENSURE(n);
        !          2003:          sprev = s;
        !          2004:          s += n;
        !          2005:        }
        !          2006:        else {
        !          2007:          sprev = s;
        !          2008:          s++;
        !          2009:        }
        !          2010:       }
        !          2011:       STAT_OP_OUT;
        !          2012:       break;
        !          2013: 
        !          2014:     case OP_ANYCHAR_STAR_PEEK_NEXT:  STAT_OP_IN(OP_ANYCHAR_STAR_PEEK_NEXT);
        !          2015:       while (s < end) {
        !          2016:        if (*p == *s) {
        !          2017:          STACK_PUSH_ALT(p + 1, s, sprev);
        !          2018:        }
        !          2019:        n = enc_len(encode, s);
        !          2020:         DATA_ENSURE(n);
        !          2021:         if (ONIGENC_IS_MBC_NEWLINE(encode, s, end))  goto fail;
        !          2022:         sprev = s;
        !          2023:         s += n;
        !          2024:       }
        !          2025:       p++;
        !          2026:       STAT_OP_OUT;
        !          2027:       break;
        !          2028: 
        !          2029:     case OP_ANYCHAR_ML_STAR_PEEK_NEXT:STAT_OP_IN(OP_ANYCHAR_ML_STAR_PEEK_NEXT);
        !          2030:       while (s < end) {
        !          2031:        if (*p == *s) {
        !          2032:          STACK_PUSH_ALT(p + 1, s, sprev);
        !          2033:        }
        !          2034:        n = enc_len(encode, s);
        !          2035:        if (n >1) {
        !          2036:          DATA_ENSURE(n);
        !          2037:          sprev = s;
        !          2038:          s += n;
        !          2039:        }
        !          2040:        else {
        !          2041:          sprev = s;
        !          2042:          s++;
        !          2043:        }
        !          2044:       }
        !          2045:       p++;
        !          2046:       STAT_OP_OUT;
        !          2047:       break;
        !          2048: 
        !          2049: #ifdef USE_COMBINATION_EXPLOSION_CHECK
        !          2050:     case OP_STATE_CHECK_ANYCHAR_STAR:  STAT_OP_IN(OP_STATE_CHECK_ANYCHAR_STAR);
        !          2051:       GET_STATE_CHECK_NUM_INC(mem, p);
        !          2052:       while (s < end) {
        !          2053:        STATE_CHECK_VAL(scv, mem);
        !          2054:        if (scv) goto fail;
        !          2055: 
        !          2056:        STACK_PUSH_ALT_WITH_STATE_CHECK(p, s, sprev, mem);
        !          2057:        n = enc_len(encode, s);
        !          2058:         DATA_ENSURE(n);
        !          2059:         if (ONIGENC_IS_MBC_NEWLINE(encode, s, end))  goto fail;
        !          2060:         sprev = s;
        !          2061:         s += n;
        !          2062:       }
        !          2063:       STAT_OP_OUT;
        !          2064:       break;
        !          2065: 
        !          2066:     case OP_STATE_CHECK_ANYCHAR_ML_STAR:
        !          2067:       STAT_OP_IN(OP_STATE_CHECK_ANYCHAR_ML_STAR);
        !          2068: 
        !          2069:       GET_STATE_CHECK_NUM_INC(mem, p);
        !          2070:       while (s < end) {
        !          2071:        STATE_CHECK_VAL(scv, mem);
        !          2072:        if (scv) goto fail;
        !          2073: 
        !          2074:        STACK_PUSH_ALT_WITH_STATE_CHECK(p, s, sprev, mem);
        !          2075:        n = enc_len(encode, s);
        !          2076:        if (n > 1) {
        !          2077:          DATA_ENSURE(n);
        !          2078:          sprev = s;
        !          2079:          s += n;
        !          2080:        }
        !          2081:        else {
        !          2082:          sprev = s;
        !          2083:          s++;
        !          2084:        }
        !          2085:       }
        !          2086:       STAT_OP_OUT;
        !          2087:       break;
        !          2088: #endif /* USE_COMBINATION_EXPLOSION_CHECK */
        !          2089: 
        !          2090:     case OP_WORD:  STAT_OP_IN(OP_WORD);
        !          2091:       DATA_ENSURE(1);
        !          2092:       if (! ONIGENC_IS_MBC_WORD(encode, s, end))
        !          2093:        goto fail;
        !          2094: 
        !          2095:       s += enc_len(encode, s);
        !          2096:       STAT_OP_OUT;
        !          2097:       break;
        !          2098: 
        !          2099:     case OP_NOT_WORD:  STAT_OP_IN(OP_NOT_WORD);
        !          2100:       DATA_ENSURE(1);
        !          2101:       if (ONIGENC_IS_MBC_WORD(encode, s, end))
        !          2102:        goto fail;
        !          2103: 
        !          2104:       s += enc_len(encode, s);
        !          2105:       STAT_OP_OUT;
        !          2106:       break;
        !          2107: 
        !          2108:     case OP_WORD_BOUND:  STAT_OP_IN(OP_WORD_BOUND);
        !          2109:       if (ON_STR_BEGIN(s)) {
        !          2110:        DATA_ENSURE(1);
        !          2111:        if (! ONIGENC_IS_MBC_WORD(encode, s, end))
        !          2112:          goto fail;
        !          2113:       }
        !          2114:       else if (ON_STR_END(s)) {
        !          2115:        if (! ONIGENC_IS_MBC_WORD(encode, sprev, end))
        !          2116:          goto fail;
        !          2117:       }
        !          2118:       else {
        !          2119:        if (ONIGENC_IS_MBC_WORD(encode, s, end)
        !          2120:            == ONIGENC_IS_MBC_WORD(encode, sprev, end))
        !          2121:          goto fail;
        !          2122:       }
        !          2123:       STAT_OP_OUT;
        !          2124:       continue;
        !          2125:       break;
        !          2126: 
        !          2127:     case OP_NOT_WORD_BOUND:  STAT_OP_IN(OP_NOT_WORD_BOUND);
        !          2128:       if (ON_STR_BEGIN(s)) {
        !          2129:        if (DATA_ENSURE_CHECK(1) && ONIGENC_IS_MBC_WORD(encode, s, end))
        !          2130:          goto fail;
        !          2131:       }
        !          2132:       else if (ON_STR_END(s)) {
        !          2133:        if (ONIGENC_IS_MBC_WORD(encode, sprev, end))
        !          2134:          goto fail;
        !          2135:       }
        !          2136:       else {
        !          2137:        if (ONIGENC_IS_MBC_WORD(encode, s, end)
        !          2138:            != ONIGENC_IS_MBC_WORD(encode, sprev, end))
        !          2139:          goto fail;
        !          2140:       }
        !          2141:       STAT_OP_OUT;
        !          2142:       continue;
        !          2143:       break;
        !          2144: 
        !          2145: #ifdef USE_WORD_BEGIN_END
        !          2146:     case OP_WORD_BEGIN:  STAT_OP_IN(OP_WORD_BEGIN);
        !          2147:       if (DATA_ENSURE_CHECK(1) && ONIGENC_IS_MBC_WORD(encode, s, end)) {
        !          2148:        if (ON_STR_BEGIN(s) || !ONIGENC_IS_MBC_WORD(encode, sprev, end)) {
        !          2149:          STAT_OP_OUT;
        !          2150:          continue;
        !          2151:        }
        !          2152:       }
        !          2153:       goto fail;
        !          2154:       break;
        !          2155: 
        !          2156:     case OP_WORD_END:  STAT_OP_IN(OP_WORD_END);
        !          2157:       if (!ON_STR_BEGIN(s) && ONIGENC_IS_MBC_WORD(encode, sprev, end)) {
        !          2158:        if (ON_STR_END(s) || !ONIGENC_IS_MBC_WORD(encode, s, end)) {
        !          2159:          STAT_OP_OUT;
        !          2160:          continue;
        !          2161:        }
        !          2162:       }
        !          2163:       goto fail;
        !          2164:       break;
        !          2165: #endif
        !          2166: 
        !          2167:     case OP_BEGIN_BUF:  STAT_OP_IN(OP_BEGIN_BUF);
        !          2168:       if (! ON_STR_BEGIN(s)) goto fail;
        !          2169: 
        !          2170:       STAT_OP_OUT;
        !          2171:       continue;
        !          2172:       break;
        !          2173: 
        !          2174:     case OP_END_BUF:  STAT_OP_IN(OP_END_BUF);
        !          2175:       if (! ON_STR_END(s)) goto fail;
        !          2176: 
        !          2177:       STAT_OP_OUT;
        !          2178:       continue;
        !          2179:       break;
        !          2180: 
        !          2181:     case OP_BEGIN_LINE:  STAT_OP_IN(OP_BEGIN_LINE);
        !          2182:       if (ON_STR_BEGIN(s)) {
        !          2183:        if (IS_NOTBOL(msa->options)) goto fail;
        !          2184:        STAT_OP_OUT;
        !          2185:        continue;
        !          2186:       }
        !          2187:       else if (ONIGENC_IS_MBC_NEWLINE(encode, sprev, end) && !ON_STR_END(s)) {
        !          2188:        STAT_OP_OUT;
        !          2189:        continue;
        !          2190:       }
        !          2191:       goto fail;
        !          2192:       break;
        !          2193: 
        !          2194:     case OP_END_LINE:  STAT_OP_IN(OP_END_LINE);
        !          2195:       if (ON_STR_END(s)) {
        !          2196: #ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE
        !          2197:        if (IS_EMPTY_STR || !ONIGENC_IS_MBC_NEWLINE(encode, sprev, end)) {
        !          2198: #endif
        !          2199:          if (IS_NOTEOL(msa->options)) goto fail;
        !          2200:          STAT_OP_OUT;
        !          2201:          continue;
        !          2202: #ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE
        !          2203:        }
        !          2204: #endif
        !          2205:       }
        !          2206:       else if (ONIGENC_IS_MBC_NEWLINE(encode, s, end)) {
        !          2207:        STAT_OP_OUT;
        !          2208:        continue;
        !          2209:       }
        !          2210: #ifdef USE_CRNL_AS_LINE_TERMINATOR
        !          2211:       else if (ONIGENC_IS_MBC_CRNL(encode, s, end)) {
        !          2212:        STAT_OP_OUT;
        !          2213:        continue;
        !          2214:       }
        !          2215: #endif
        !          2216:       goto fail;
        !          2217:       break;
        !          2218: 
        !          2219:     case OP_SEMI_END_BUF:  STAT_OP_IN(OP_SEMI_END_BUF);
        !          2220:       if (ON_STR_END(s)) {
        !          2221: #ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE
        !          2222:        if (IS_EMPTY_STR || !ONIGENC_IS_MBC_NEWLINE(encode, sprev, end)) {
        !          2223: #endif
        !          2224:          if (IS_NOTEOL(msa->options)) goto fail;   /* Is it needed? */
        !          2225:          STAT_OP_OUT;
        !          2226:          continue;
        !          2227: #ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE
        !          2228:        }
        !          2229: #endif
        !          2230:       }
        !          2231:       else if (ONIGENC_IS_MBC_NEWLINE(encode, s, end) &&
        !          2232:               ON_STR_END(s + enc_len(encode, s))) {
        !          2233:        STAT_OP_OUT;
        !          2234:        continue;
        !          2235:       }
        !          2236: #ifdef USE_CRNL_AS_LINE_TERMINATOR
        !          2237:       else if (ONIGENC_IS_MBC_CRNL(encode, s, end)) {
        !          2238:         UChar* ss = s + enc_len(encode, s);
        !          2239:         if (ON_STR_END(ss + enc_len(encode, ss))) {
        !          2240:           STAT_OP_OUT;
        !          2241:           continue;
        !          2242:         }
        !          2243:       }
        !          2244: #endif
        !          2245:       goto fail;
        !          2246:       break;
        !          2247: 
        !          2248:     case OP_BEGIN_POSITION:  STAT_OP_IN(OP_BEGIN_POSITION);
        !          2249:       if (s != msa->start)
        !          2250:        goto fail;
        !          2251: 
        !          2252:       STAT_OP_OUT;
        !          2253:       continue;
        !          2254:       break;
        !          2255: 
        !          2256:     case OP_MEMORY_START_PUSH:  STAT_OP_IN(OP_MEMORY_START_PUSH);
        !          2257:       GET_MEMNUM_INC(mem, p);
        !          2258:       STACK_PUSH_MEM_START(mem, s);
        !          2259:       STAT_OP_OUT;
        !          2260:       continue;
        !          2261:       break;
        !          2262: 
        !          2263:     case OP_MEMORY_START:  STAT_OP_IN(OP_MEMORY_START);
        !          2264:       GET_MEMNUM_INC(mem, p);
        !          2265:       mem_start_stk[mem] = (StackIndex )((void* )s);
        !          2266:       STAT_OP_OUT;
        !          2267:       continue;
        !          2268:       break;
        !          2269: 
        !          2270:     case OP_MEMORY_END_PUSH:  STAT_OP_IN(OP_MEMORY_END_PUSH);
        !          2271:       GET_MEMNUM_INC(mem, p);
        !          2272:       STACK_PUSH_MEM_END(mem, s);
        !          2273:       STAT_OP_OUT;
        !          2274:       continue;
        !          2275:       break;
        !          2276: 
        !          2277:     case OP_MEMORY_END:  STAT_OP_IN(OP_MEMORY_END);
        !          2278:       GET_MEMNUM_INC(mem, p);
        !          2279:       mem_end_stk[mem] = (StackIndex )((void* )s);
        !          2280:       STAT_OP_OUT;
        !          2281:       continue;
        !          2282:       break;
        !          2283: 
        !          2284: #ifdef USE_SUBEXP_CALL
        !          2285:     case OP_MEMORY_END_PUSH_REC:  STAT_OP_IN(OP_MEMORY_END_PUSH_REC);
        !          2286:       GET_MEMNUM_INC(mem, p);
        !          2287:       STACK_GET_MEM_START(mem, stkp); /* should be before push mem-end. */
        !          2288:       STACK_PUSH_MEM_END(mem, s);
        !          2289:       mem_start_stk[mem] = GET_STACK_INDEX(stkp);
        !          2290:       STAT_OP_OUT;
        !          2291:       continue;
        !          2292:       break;
        !          2293: 
        !          2294:     case OP_MEMORY_END_REC:  STAT_OP_IN(OP_MEMORY_END_REC);
        !          2295:       GET_MEMNUM_INC(mem, p);
        !          2296:       mem_end_stk[mem] = (StackIndex )((void* )s);
        !          2297:       STACK_GET_MEM_START(mem, stkp);
        !          2298: 
        !          2299:       if (BIT_STATUS_AT(reg->bt_mem_start, mem))
        !          2300:        mem_start_stk[mem] = GET_STACK_INDEX(stkp);
        !          2301:       else
        !          2302:        mem_start_stk[mem] = (StackIndex )((void* )stkp->u.mem.pstr);
        !          2303: 
        !          2304:       STACK_PUSH_MEM_END_MARK(mem);
        !          2305:       STAT_OP_OUT;
        !          2306:       continue;
        !          2307:       break;
        !          2308: #endif
        !          2309: 
        !          2310:     case OP_BACKREF1:  STAT_OP_IN(OP_BACKREF1);
        !          2311:       mem = 1;
        !          2312:       goto backref;
        !          2313:       break;
        !          2314: 
        !          2315:     case OP_BACKREF2:  STAT_OP_IN(OP_BACKREF2);
        !          2316:       mem = 2;
        !          2317:       goto backref;
        !          2318:       break;
        !          2319: 
        !          2320:     case OP_BACKREFN:  STAT_OP_IN(OP_BACKREFN);
        !          2321:       GET_MEMNUM_INC(mem, p);
        !          2322:     backref:
        !          2323:       {
        !          2324:        int len;
        !          2325:        UChar *pstart, *pend;
        !          2326: 
        !          2327:        /* if you want to remove following line, 
        !          2328:           you should check in parse and compile time. */
        !          2329:        if (mem > num_mem) goto fail;
        !          2330:        if (mem_end_stk[mem]   == INVALID_STACK_INDEX) goto fail;
        !          2331:        if (mem_start_stk[mem] == INVALID_STACK_INDEX) goto fail;
        !          2332: 
        !          2333:        if (BIT_STATUS_AT(reg->bt_mem_start, mem))
        !          2334:          pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;
        !          2335:        else
        !          2336:          pstart = (UChar* )((void* )mem_start_stk[mem]);
        !          2337: 
        !          2338:        pend = (BIT_STATUS_AT(reg->bt_mem_end, mem)
        !          2339:                ? STACK_AT(mem_end_stk[mem])->u.mem.pstr
        !          2340:                : (UChar* )((void* )mem_end_stk[mem]));
        !          2341:        n = pend - pstart;
        !          2342:        DATA_ENSURE(n);
        !          2343:        sprev = s;
        !          2344:        STRING_CMP(pstart, s, n);
        !          2345:        while (sprev + (len = enc_len(encode, sprev)) < s)
        !          2346:          sprev += len;
        !          2347: 
        !          2348:        STAT_OP_OUT;
        !          2349:        continue;
        !          2350:       }
        !          2351:       break;
        !          2352: 
        !          2353:     case OP_BACKREFN_IC:  STAT_OP_IN(OP_BACKREFN_IC);
        !          2354:       GET_MEMNUM_INC(mem, p);
        !          2355:       {
        !          2356:        int len;
        !          2357:        UChar *pstart, *pend;
        !          2358: 
        !          2359:        /* if you want to remove following line, 
        !          2360:           you should check in parse and compile time. */
        !          2361:        if (mem > num_mem) goto fail;
        !          2362:        if (mem_end_stk[mem]   == INVALID_STACK_INDEX) goto fail;
        !          2363:        if (mem_start_stk[mem] == INVALID_STACK_INDEX) goto fail;
        !          2364: 
        !          2365:        if (BIT_STATUS_AT(reg->bt_mem_start, mem))
        !          2366:          pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;
        !          2367:        else
        !          2368:          pstart = (UChar* )((void* )mem_start_stk[mem]);
        !          2369: 
        !          2370:        pend = (BIT_STATUS_AT(reg->bt_mem_end, mem)
        !          2371:                ? STACK_AT(mem_end_stk[mem])->u.mem.pstr
        !          2372:                : (UChar* )((void* )mem_end_stk[mem]));
        !          2373:        n = pend - pstart;
        !          2374:        DATA_ENSURE(n);
        !          2375:        sprev = s;
        !          2376:        STRING_CMP_IC(ambig_flag, pstart, &s, n);
        !          2377:        while (sprev + (len = enc_len(encode, sprev)) < s)
        !          2378:          sprev += len;
        !          2379: 
        !          2380:        STAT_OP_OUT;
        !          2381:        continue;
        !          2382:       }
        !          2383:       break;
        !          2384: 
        !          2385:     case OP_BACKREF_MULTI:  STAT_OP_IN(OP_BACKREF_MULTI);
        !          2386:       {
        !          2387:        int len, is_fail;
        !          2388:        UChar *pstart, *pend, *swork;
        !          2389: 
        !          2390:        GET_LENGTH_INC(tlen, p);
        !          2391:        for (i = 0; i < tlen; i++) {
        !          2392:          GET_MEMNUM_INC(mem, p);
        !          2393: 
        !          2394:          if (mem_end_stk[mem]   == INVALID_STACK_INDEX) continue;
        !          2395:          if (mem_start_stk[mem] == INVALID_STACK_INDEX) continue;
        !          2396: 
        !          2397:          if (BIT_STATUS_AT(reg->bt_mem_start, mem))
        !          2398:            pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;
        !          2399:          else
        !          2400:            pstart = (UChar* )((void* )mem_start_stk[mem]);
        !          2401: 
        !          2402:          pend = (BIT_STATUS_AT(reg->bt_mem_end, mem)
        !          2403:                  ? STACK_AT(mem_end_stk[mem])->u.mem.pstr
        !          2404:                  : (UChar* )((void* )mem_end_stk[mem]));
        !          2405:          n = pend - pstart;
        !          2406:          DATA_ENSURE(n);
        !          2407:          sprev = s;
        !          2408:          swork = s;
        !          2409:          STRING_CMP_VALUE(pstart, swork, n, is_fail);
        !          2410:          if (is_fail) continue;
        !          2411:          s = swork;
        !          2412:          while (sprev + (len = enc_len(encode, sprev)) < s)
        !          2413:            sprev += len;
        !          2414: 
        !          2415:          p += (SIZE_MEMNUM * (tlen - i - 1));
        !          2416:          break; /* success */
        !          2417:        }
        !          2418:        if (i == tlen) goto fail;
        !          2419:        STAT_OP_OUT;
        !          2420:        continue;
        !          2421:       }
        !          2422:       break;
        !          2423: 
        !          2424:     case OP_BACKREF_MULTI_IC:  STAT_OP_IN(OP_BACKREF_MULTI_IC);
        !          2425:       {
        !          2426:        int len, is_fail;
        !          2427:        UChar *pstart, *pend, *swork;
        !          2428: 
        !          2429:        GET_LENGTH_INC(tlen, p);
        !          2430:        for (i = 0; i < tlen; i++) {
        !          2431:          GET_MEMNUM_INC(mem, p);
        !          2432: 
        !          2433:          if (mem_end_stk[mem]   == INVALID_STACK_INDEX) continue;
        !          2434:          if (mem_start_stk[mem] == INVALID_STACK_INDEX) continue;
        !          2435: 
        !          2436:          if (BIT_STATUS_AT(reg->bt_mem_start, mem))
        !          2437:            pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;
        !          2438:          else
        !          2439:            pstart = (UChar* )((void* )mem_start_stk[mem]);
        !          2440: 
        !          2441:          pend = (BIT_STATUS_AT(reg->bt_mem_end, mem)
        !          2442:                  ? STACK_AT(mem_end_stk[mem])->u.mem.pstr
        !          2443:                  : (UChar* )((void* )mem_end_stk[mem]));
        !          2444:          n = pend - pstart;
        !          2445:          DATA_ENSURE(n);
        !          2446:          sprev = s;
        !          2447:          swork = s;
        !          2448:          STRING_CMP_VALUE_IC(ambig_flag, pstart, &swork, n, is_fail);
        !          2449:          if (is_fail) continue;
        !          2450:          s = swork;
        !          2451:          while (sprev + (len = enc_len(encode, sprev)) < s)
        !          2452:            sprev += len;
        !          2453: 
        !          2454:          p += (SIZE_MEMNUM * (tlen - i - 1));
        !          2455:          break; /* success */
        !          2456:        }
        !          2457:        if (i == tlen) goto fail;
        !          2458:        STAT_OP_OUT;
        !          2459:        continue;
        !          2460:       }
        !          2461:       break;
        !          2462: 
        !          2463: #ifdef USE_BACKREF_AT_LEVEL
        !          2464:     case OP_BACKREF_AT_LEVEL:
        !          2465:       {
        !          2466:        int len;
        !          2467:        OnigOptionType ic;
        !          2468:        LengthType level;
        !          2469: 
        !          2470:        GET_OPTION_INC(ic,    p);
        !          2471:        GET_LENGTH_INC(level, p);
        !          2472:        GET_LENGTH_INC(tlen,  p);
        !          2473: 
        !          2474:        sprev = s;
        !          2475:        if (backref_match_at_nested_level(reg, stk, stk_base, ic, ambig_flag
        !          2476:                                  , (int )level, (int )tlen, p, &s, end)) {
        !          2477:          while (sprev + (len = enc_len(encode, sprev)) < s)
        !          2478:            sprev += len;
        !          2479: 
        !          2480:          p += (SIZE_MEMNUM * tlen);
        !          2481:        }
        !          2482:        else
        !          2483:          goto fail;
        !          2484: 
        !          2485:        STAT_OP_OUT;
        !          2486:        continue;
        !          2487:       }
        !          2488:       
        !          2489:       break;
        !          2490: #endif
        !          2491:     
        !          2492:     case OP_SET_OPTION_PUSH:  STAT_OP_IN(OP_SET_OPTION_PUSH);
        !          2493:       GET_OPTION_INC(option, p);
        !          2494:       STACK_PUSH_ALT(p, s, sprev);
        !          2495:       p += SIZE_OP_SET_OPTION + SIZE_OP_FAIL;
        !          2496:       STAT_OP_OUT;
        !          2497:       continue;
        !          2498:       break;
        !          2499: 
        !          2500:     case OP_SET_OPTION:  STAT_OP_IN(OP_SET_OPTION);
        !          2501:       GET_OPTION_INC(option, p);
        !          2502:       STAT_OP_OUT;
        !          2503:       continue;
        !          2504:       break;
        !          2505: 
        !          2506:     case OP_NULL_CHECK_START:  STAT_OP_IN(OP_NULL_CHECK_START);
        !          2507:       GET_MEMNUM_INC(mem, p);    /* mem: null check id */
        !          2508:       STACK_PUSH_NULL_CHECK_START(mem, s);
        !          2509:       STAT_OP_OUT;
        !          2510:       continue;
        !          2511:       break;
        !          2512: 
        !          2513:     case OP_NULL_CHECK_END:  STAT_OP_IN(OP_NULL_CHECK_END);
        !          2514:       {
        !          2515:        int isnull;
        !          2516: 
        !          2517:        GET_MEMNUM_INC(mem, p); /* mem: null check id */
        !          2518:        STACK_NULL_CHECK(isnull, mem, s);
        !          2519:        if (isnull) {
        !          2520: #ifdef ONIG_DEBUG_MATCH
        !          2521:          fprintf(stderr, "NULL_CHECK_END: skip  id:%d, s:%d\n",
        !          2522:                  (int )mem, (int )s);
        !          2523: #endif
        !          2524:        null_check_found:
        !          2525:          /* empty loop founded, skip next instruction */
        !          2526:          switch (*p++) {
        !          2527:          case OP_JUMP:
        !          2528:          case OP_PUSH:
        !          2529:            p += SIZE_RELADDR;
        !          2530:            break;
        !          2531:          case OP_REPEAT_INC:
        !          2532:          case OP_REPEAT_INC_NG:
        !          2533:          case OP_REPEAT_INC_SG:
        !          2534:          case OP_REPEAT_INC_NG_SG:
        !          2535:            p += SIZE_MEMNUM;
        !          2536:            break;
        !          2537:          default:
        !          2538:            goto unexpected_bytecode_error;
        !          2539:            break;
        !          2540:          }
        !          2541:        }
        !          2542:       }
        !          2543:       STAT_OP_OUT;
        !          2544:       continue;
        !          2545:       break;
        !          2546: 
        !          2547: #ifdef USE_INFINITE_REPEAT_MONOMANIAC_MEM_STATUS_CHECK
        !          2548:     case OP_NULL_CHECK_END_MEMST:  STAT_OP_IN(OP_NULL_CHECK_END_MEMST);
        !          2549:       {
        !          2550:        int isnull;
        !          2551: 
        !          2552:        GET_MEMNUM_INC(mem, p); /* mem: null check id */
        !          2553:        STACK_NULL_CHECK_MEMST(isnull, mem, s, reg);
        !          2554:        if (isnull) {
        !          2555: #ifdef ONIG_DEBUG_MATCH
        !          2556:          fprintf(stderr, "NULL_CHECK_END_MEMST: skip  id:%d, s:%d\n",
        !          2557:                  (int )mem, (int )s);
        !          2558: #endif
        !          2559:          if (isnull == -1) goto fail;
        !          2560:          goto  null_check_found;
        !          2561:        }
        !          2562:       }
        !          2563:       STAT_OP_OUT;
        !          2564:       continue;
        !          2565:       break;
        !          2566: #endif
        !          2567: 
        !          2568: #ifdef USE_SUBEXP_CALL
        !          2569:     case OP_NULL_CHECK_END_MEMST_PUSH:
        !          2570:       STAT_OP_IN(OP_NULL_CHECK_END_MEMST_PUSH);
        !          2571:       {
        !          2572:        int isnull;
        !          2573: 
        !          2574:        GET_MEMNUM_INC(mem, p); /* mem: null check id */
        !          2575: #ifdef USE_INFINITE_REPEAT_MONOMANIAC_MEM_STATUS_CHECK
        !          2576:        STACK_NULL_CHECK_MEMST_REC(isnull, mem, s, reg);
        !          2577: #else
        !          2578:        STACK_NULL_CHECK_REC(isnull, mem, s);
        !          2579: #endif
        !          2580:        if (isnull) {
        !          2581: #ifdef ONIG_DEBUG_MATCH
        !          2582:          fprintf(stderr, "NULL_CHECK_END_MEMST_PUSH: skip  id:%d, s:%d\n",
        !          2583:                  (int )mem, (int )s);
        !          2584: #endif
        !          2585:          if (isnull == -1) goto fail;
        !          2586:          goto  null_check_found;
        !          2587:        }
        !          2588:        else {
        !          2589:          STACK_PUSH_NULL_CHECK_END(mem);
        !          2590:        }
        !          2591:       }
        !          2592:       STAT_OP_OUT;
        !          2593:       continue;
        !          2594:       break;
        !          2595: #endif
        !          2596: 
        !          2597:     case OP_JUMP:  STAT_OP_IN(OP_JUMP);
        !          2598:       GET_RELADDR_INC(addr, p);
        !          2599:       p += addr;
        !          2600:       STAT_OP_OUT;
        !          2601:       CHECK_INTERRUPT_IN_MATCH_AT;
        !          2602:       continue;
        !          2603:       break;
        !          2604: 
        !          2605:     case OP_PUSH:  STAT_OP_IN(OP_PUSH);
        !          2606:       GET_RELADDR_INC(addr, p);
        !          2607:       STACK_PUSH_ALT(p + addr, s, sprev);
        !          2608:       STAT_OP_OUT;
        !          2609:       continue;
        !          2610:       break;
        !          2611: 
        !          2612: #ifdef USE_COMBINATION_EXPLOSION_CHECK
        !          2613:     case OP_STATE_CHECK_PUSH:  STAT_OP_IN(OP_STATE_CHECK_PUSH);
        !          2614:       GET_STATE_CHECK_NUM_INC(mem, p);
        !          2615:       STATE_CHECK_VAL(scv, mem);
        !          2616:       if (scv) goto fail;
        !          2617: 
        !          2618:       GET_RELADDR_INC(addr, p);
        !          2619:       STACK_PUSH_ALT_WITH_STATE_CHECK(p + addr, s, sprev, mem);
        !          2620:       STAT_OP_OUT;
        !          2621:       continue;
        !          2622:       break;
        !          2623: 
        !          2624:     case OP_STATE_CHECK_PUSH_OR_JUMP:  STAT_OP_IN(OP_STATE_CHECK_PUSH_OR_JUMP);
        !          2625:       GET_STATE_CHECK_NUM_INC(mem, p);
        !          2626:       GET_RELADDR_INC(addr, p);
        !          2627:       STATE_CHECK_VAL(scv, mem);
        !          2628:       if (scv) {
        !          2629:        p += addr;
        !          2630:       }
        !          2631:       else {
        !          2632:        STACK_PUSH_ALT_WITH_STATE_CHECK(p + addr, s, sprev, mem);
        !          2633:       }
        !          2634:       STAT_OP_OUT;
        !          2635:       continue;
        !          2636:       break;
        !          2637: 
        !          2638:     case OP_STATE_CHECK:  STAT_OP_IN(OP_STATE_CHECK);
        !          2639:       GET_STATE_CHECK_NUM_INC(mem, p);
        !          2640:       STATE_CHECK_VAL(scv, mem);
        !          2641:       if (scv) goto fail;
        !          2642: 
        !          2643:       STACK_PUSH_STATE_CHECK(s, mem);
        !          2644:       STAT_OP_OUT;
        !          2645:       continue;
        !          2646:       break;
        !          2647: #endif /* USE_COMBINATION_EXPLOSION_CHECK */
        !          2648: 
        !          2649:     case OP_POP:  STAT_OP_IN(OP_POP);
        !          2650:       STACK_POP_ONE;
        !          2651:       STAT_OP_OUT;
        !          2652:       continue;
        !          2653:       break;
        !          2654: 
        !          2655:     case OP_PUSH_OR_JUMP_EXACT1:  STAT_OP_IN(OP_PUSH_OR_JUMP_EXACT1);
        !          2656:       GET_RELADDR_INC(addr, p);
        !          2657:       if (*p == *s && DATA_ENSURE_CHECK(1)) {
        !          2658:        p++;
        !          2659:        STACK_PUSH_ALT(p + addr, s, sprev);
        !          2660:        STAT_OP_OUT;
        !          2661:        continue;
        !          2662:       }
        !          2663:       p += (addr + 1);
        !          2664:       STAT_OP_OUT;
        !          2665:       continue;
        !          2666:       break;
        !          2667: 
        !          2668:     case OP_PUSH_IF_PEEK_NEXT:  STAT_OP_IN(OP_PUSH_IF_PEEK_NEXT);
        !          2669:       GET_RELADDR_INC(addr, p);
        !          2670:       if (*p == *s) {
        !          2671:        p++;
        !          2672:        STACK_PUSH_ALT(p + addr, s, sprev);
        !          2673:        STAT_OP_OUT;
        !          2674:        continue;
        !          2675:       }
        !          2676:       p++;
        !          2677:       STAT_OP_OUT;
        !          2678:       continue;
        !          2679:       break;
        !          2680: 
        !          2681:     case OP_REPEAT:  STAT_OP_IN(OP_REPEAT);
        !          2682:       {
        !          2683:        GET_MEMNUM_INC(mem, p);    /* mem: OP_REPEAT ID */
        !          2684:        GET_RELADDR_INC(addr, p);
        !          2685: 
        !          2686:        STACK_ENSURE(1);
        !          2687:        repeat_stk[mem] = GET_STACK_INDEX(stk);
        !          2688:        STACK_PUSH_REPEAT(mem, p);
        !          2689: 
        !          2690:        if (reg->repeat_range[mem].lower == 0) {
        !          2691:          STACK_PUSH_ALT(p + addr, s, sprev);
        !          2692:        }
        !          2693:       }
        !          2694:       STAT_OP_OUT;
        !          2695:       continue;
        !          2696:       break;
        !          2697: 
        !          2698:     case OP_REPEAT_NG:  STAT_OP_IN(OP_REPEAT_NG);
        !          2699:       {
        !          2700:        GET_MEMNUM_INC(mem, p);    /* mem: OP_REPEAT ID */
        !          2701:        GET_RELADDR_INC(addr, p);
        !          2702: 
        !          2703:        STACK_ENSURE(1);
        !          2704:        repeat_stk[mem] = GET_STACK_INDEX(stk);
        !          2705:        STACK_PUSH_REPEAT(mem, p);
        !          2706: 
        !          2707:        if (reg->repeat_range[mem].lower == 0) {
        !          2708:          STACK_PUSH_ALT(p, s, sprev);
        !          2709:          p += addr;
        !          2710:        }
        !          2711:       }
        !          2712:       STAT_OP_OUT;
        !          2713:       continue;
        !          2714:       break;
        !          2715: 
        !          2716:     case OP_REPEAT_INC:  STAT_OP_IN(OP_REPEAT_INC);
        !          2717:       GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */
        !          2718:       si = repeat_stk[mem];
        !          2719:       stkp = STACK_AT(si);
        !          2720: 
        !          2721:     repeat_inc:
        !          2722:       stkp->u.repeat.count++;
        !          2723:       if (stkp->u.repeat.count >= reg->repeat_range[mem].upper) {
        !          2724:         /* end of repeat. Nothing to do. */
        !          2725:       }
        !          2726:       else if (stkp->u.repeat.count >= reg->repeat_range[mem].lower) {
        !          2727:         STACK_PUSH_ALT(p, s, sprev);
        !          2728:         p = STACK_AT(si)->u.repeat.pcode; /* Don't use stkp after PUSH. */
        !          2729:       }
        !          2730:       else {
        !          2731:         p = stkp->u.repeat.pcode;
        !          2732:       }
        !          2733:       STACK_PUSH_REPEAT_INC(si);
        !          2734:       STAT_OP_OUT;
        !          2735:       CHECK_INTERRUPT_IN_MATCH_AT;
        !          2736:       continue;
        !          2737:       break;
        !          2738: 
        !          2739:     case OP_REPEAT_INC_SG:  STAT_OP_IN(OP_REPEAT_INC_SG);
        !          2740:       GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */
        !          2741:       STACK_GET_REPEAT(mem, stkp);
        !          2742:       si = GET_STACK_INDEX(stkp);
        !          2743:       goto repeat_inc;
        !          2744:       break;
        !          2745: 
        !          2746:     case OP_REPEAT_INC_NG:  STAT_OP_IN(OP_REPEAT_INC_NG);
        !          2747:       GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */
        !          2748:       si = repeat_stk[mem];
        !          2749:       stkp = STACK_AT(si);
        !          2750: 
        !          2751:     repeat_inc_ng:
        !          2752:       stkp->u.repeat.count++;
        !          2753:       if (stkp->u.repeat.count < reg->repeat_range[mem].upper) {
        !          2754:         if (stkp->u.repeat.count >= reg->repeat_range[mem].lower) {
        !          2755:           UChar* pcode = stkp->u.repeat.pcode;
        !          2756: 
        !          2757:           STACK_PUSH_REPEAT_INC(si);
        !          2758:           STACK_PUSH_ALT(pcode, s, sprev);
        !          2759:         }
        !          2760:         else {
        !          2761:           p = stkp->u.repeat.pcode;
        !          2762:           STACK_PUSH_REPEAT_INC(si);
        !          2763:         }
        !          2764:       }
        !          2765:       else if (stkp->u.repeat.count == reg->repeat_range[mem].upper) {
        !          2766:         STACK_PUSH_REPEAT_INC(si);
        !          2767:       }
        !          2768:       STAT_OP_OUT;
        !          2769:       CHECK_INTERRUPT_IN_MATCH_AT;
        !          2770:       continue;
        !          2771:       break;
        !          2772: 
        !          2773:     case OP_REPEAT_INC_NG_SG:  STAT_OP_IN(OP_REPEAT_INC_NG_SG);
        !          2774:       GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */
        !          2775:       STACK_GET_REPEAT(mem, stkp);
        !          2776:       si = GET_STACK_INDEX(stkp);
        !          2777:       goto repeat_inc_ng;
        !          2778:       break;
        !          2779: 
        !          2780:     case OP_PUSH_POS:  STAT_OP_IN(OP_PUSH_POS);
        !          2781:       STACK_PUSH_POS(s, sprev);
        !          2782:       STAT_OP_OUT;
        !          2783:       continue;
        !          2784:       break;
        !          2785: 
        !          2786:     case OP_POP_POS:  STAT_OP_IN(OP_POP_POS);
        !          2787:       {
        !          2788:        STACK_POS_END(stkp);
        !          2789:        s     = stkp->u.state.pstr;
        !          2790:        sprev = stkp->u.state.pstr_prev;
        !          2791:       }
        !          2792:       STAT_OP_OUT;
        !          2793:       continue;
        !          2794:       break;
        !          2795: 
        !          2796:     case OP_PUSH_POS_NOT:  STAT_OP_IN(OP_PUSH_POS_NOT);
        !          2797:       GET_RELADDR_INC(addr, p);
        !          2798:       STACK_PUSH_POS_NOT(p + addr, s, sprev);
        !          2799:       STAT_OP_OUT;
        !          2800:       continue;
        !          2801:       break;
        !          2802: 
        !          2803:     case OP_FAIL_POS:  STAT_OP_IN(OP_FAIL_POS);
        !          2804:       STACK_POP_TIL_POS_NOT;
        !          2805:       goto fail;
        !          2806:       break;
        !          2807: 
        !          2808:     case OP_PUSH_STOP_BT:  STAT_OP_IN(OP_PUSH_STOP_BT);
        !          2809:       STACK_PUSH_STOP_BT;
        !          2810:       STAT_OP_OUT;
        !          2811:       continue;
        !          2812:       break;
        !          2813: 
        !          2814:     case OP_POP_STOP_BT:  STAT_OP_IN(OP_POP_STOP_BT);
        !          2815:       STACK_STOP_BT_END;
        !          2816:       STAT_OP_OUT;
        !          2817:       continue;
        !          2818:       break;
        !          2819: 
        !          2820:     case OP_LOOK_BEHIND:  STAT_OP_IN(OP_LOOK_BEHIND);
        !          2821:       GET_LENGTH_INC(tlen, p);
        !          2822:       s = (UChar* )ONIGENC_STEP_BACK(encode, str, s, (int )tlen);
        !          2823:       if (IS_NULL(s)) goto fail;
        !          2824:       sprev = (UChar* )onigenc_get_prev_char_head(encode, str, s);
        !          2825:       STAT_OP_OUT;
        !          2826:       continue;
        !          2827:       break;
        !          2828: 
        !          2829:     case OP_PUSH_LOOK_BEHIND_NOT:  STAT_OP_IN(OP_PUSH_LOOK_BEHIND_NOT);
        !          2830:       GET_RELADDR_INC(addr, p);
        !          2831:       GET_LENGTH_INC(tlen, p);
        !          2832:       q = (UChar* )ONIGENC_STEP_BACK(encode, str, s, (int )tlen);
        !          2833:       if (IS_NULL(q)) {
        !          2834:        /* too short case -> success. ex. /(?<!XXX)a/.match("a")
        !          2835:           If you want to change to fail, replace following line. */
        !          2836:        p += addr;
        !          2837:        /* goto fail; */
        !          2838:       }
        !          2839:       else {
        !          2840:        STACK_PUSH_LOOK_BEHIND_NOT(p + addr, s, sprev);
        !          2841:        s = q;
        !          2842:        sprev = (UChar* )onigenc_get_prev_char_head(encode, str, s);
        !          2843:       }
        !          2844:       STAT_OP_OUT;
        !          2845:       continue;
        !          2846:       break;
        !          2847: 
        !          2848:     case OP_FAIL_LOOK_BEHIND_NOT:  STAT_OP_IN(OP_FAIL_LOOK_BEHIND_NOT);
        !          2849:       STACK_POP_TIL_LOOK_BEHIND_NOT;
        !          2850:       goto fail;
        !          2851:       break;
        !          2852: 
        !          2853: #ifdef USE_SUBEXP_CALL
        !          2854:     case OP_CALL:  STAT_OP_IN(OP_CALL);
        !          2855:       GET_ABSADDR_INC(addr, p);
        !          2856:       STACK_PUSH_CALL_FRAME(p);
        !          2857:       p = reg->p + addr;
        !          2858:       STAT_OP_OUT;
        !          2859:       continue;
        !          2860:       break;
        !          2861: 
        !          2862:     case OP_RETURN:  STAT_OP_IN(OP_RETURN);
        !          2863:       STACK_RETURN(p);
        !          2864:       STACK_PUSH_RETURN;
        !          2865:       STAT_OP_OUT;
        !          2866:       continue;
        !          2867:       break;
        !          2868: #endif
        !          2869: 
        !          2870:     case OP_FINISH:
        !          2871:       goto finish;
        !          2872:       break;
        !          2873: 
        !          2874:     fail:
        !          2875:       STAT_OP_OUT;
        !          2876:       /* fall */
        !          2877:     case OP_FAIL:  STAT_OP_IN(OP_FAIL);
        !          2878:       STACK_POP;
        !          2879:       p     = stk->u.state.pcode;
        !          2880:       s     = stk->u.state.pstr;
        !          2881:       sprev = stk->u.state.pstr_prev;
        !          2882: 
        !          2883: #ifdef USE_COMBINATION_EXPLOSION_CHECK
        !          2884:       if (stk->u.state.state_check != 0) {
        !          2885:         stk->type = STK_STATE_CHECK_MARK;
        !          2886:         stk++;
        !          2887:       }
        !          2888: #endif
        !          2889: 
        !          2890:       STAT_OP_OUT;
        !          2891:       continue;
        !          2892:       break;
        !          2893: 
        !          2894:     default:
        !          2895:       goto bytecode_error;
        !          2896: 
        !          2897:     } /* end of switch */
        !          2898:     sprev = sbegin;
        !          2899:   } /* end of while(1) */
        !          2900: 
        !          2901:  finish:
        !          2902:   STACK_SAVE;
        !          2903:   return best_len;
        !          2904: 
        !          2905: #ifdef ONIG_DEBUG
        !          2906:  stack_error:
        !          2907:   STACK_SAVE;
        !          2908:   return ONIGERR_STACK_BUG;
        !          2909: #endif
        !          2910: 
        !          2911:  bytecode_error:
        !          2912:   STACK_SAVE;
        !          2913:   return ONIGERR_UNDEFINED_BYTECODE;
        !          2914: 
        !          2915:  unexpected_bytecode_error:
        !          2916:   STACK_SAVE;
        !          2917:   return ONIGERR_UNEXPECTED_BYTECODE;
        !          2918: }
        !          2919: 
        !          2920: 
        !          2921: static UChar*
        !          2922: slow_search(OnigEncoding enc, UChar* target, UChar* target_end,
        !          2923:            const UChar* text, const UChar* text_end, UChar* text_range)
        !          2924: {
        !          2925:   UChar *t, *p, *s, *end;
        !          2926: 
        !          2927:   end = (UChar* )text_end;
        !          2928:   end -= target_end - target - 1;
        !          2929:   if (end > text_range)
        !          2930:     end = text_range;
        !          2931: 
        !          2932:   s = (UChar* )text;
        !          2933: 
        !          2934:   while (s < end) {
        !          2935:     if (*s == *target) {
        !          2936:       p = s + 1;
        !          2937:       t = target + 1;
        !          2938:       while (t < target_end) {
        !          2939:        if (*t != *p++)
        !          2940:          break;
        !          2941:        t++;
        !          2942:       }
        !          2943:       if (t == target_end)
        !          2944:        return s;
        !          2945:     }
        !          2946:     s += enc_len(enc, s);
        !          2947:   }
        !          2948: 
        !          2949:   return (UChar* )NULL;
        !          2950: }
        !          2951: 
        !          2952: static int
        !          2953: str_lower_case_match(OnigEncoding enc, int ambig_flag,
        !          2954:                      const UChar* t, const UChar* tend,
        !          2955:                     const UChar* p, const UChar* end)
        !          2956: {
        !          2957:   int lowlen;
        !          2958:   UChar *q, lowbuf[ONIGENC_MBC_NORMALIZE_MAXLEN];
        !          2959:   const UChar* tsave;
        !          2960:   const UChar* psave;
        !          2961: 
        !          2962:   tsave = t;
        !          2963:   psave = p;
        !          2964: 
        !          2965:   while (t < tend) {
        !          2966:     lowlen = ONIGENC_MBC_TO_NORMALIZE(enc, ambig_flag, &p, end, lowbuf);
        !          2967:     q = lowbuf;
        !          2968:     while (lowlen > 0) {
        !          2969:       if (*t++ != *q++) {
        !          2970:        return 0;
        !          2971:       }
        !          2972:       lowlen--;
        !          2973:     }
        !          2974:   }
        !          2975: 
        !          2976:   return 1;
        !          2977: }
        !          2978: 
        !          2979: static UChar*
        !          2980: slow_search_ic(OnigEncoding enc, int ambig_flag,
        !          2981:               UChar* target, UChar* target_end,
        !          2982:               const UChar* text, const UChar* text_end, UChar* text_range)
        !          2983: {
        !          2984:   UChar *s, *end;
        !          2985: 
        !          2986:   end = (UChar* )text_end;
        !          2987:   end -= target_end - target - 1;
        !          2988:   if (end > text_range)
        !          2989:     end = text_range;
        !          2990: 
        !          2991:   s = (UChar* )text;
        !          2992: 
        !          2993:   while (s < end) {
        !          2994:     if (str_lower_case_match(enc, ambig_flag, target, target_end, s, text_end))
        !          2995:       return s;
        !          2996: 
        !          2997:     s += enc_len(enc, s);
        !          2998:   }
        !          2999: 
        !          3000:   return (UChar* )NULL;
        !          3001: }
        !          3002: 
        !          3003: static UChar*
        !          3004: slow_search_backward(OnigEncoding enc, UChar* target, UChar* target_end,
        !          3005:                     const UChar* text, const UChar* adjust_text,
        !          3006:                     const UChar* text_end, const UChar* text_start)
        !          3007: {
        !          3008:   UChar *t, *p, *s;
        !          3009: 
        !          3010:   s = (UChar* )text_end;
        !          3011:   s -= (target_end - target);
        !          3012:   if (s > text_start)
        !          3013:     s = (UChar* )text_start;
        !          3014:   else
        !          3015:     s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, adjust_text, s);
        !          3016: 
        !          3017:   while (s >= text) {
        !          3018:     if (*s == *target) {
        !          3019:       p = s + 1;
        !          3020:       t = target + 1;
        !          3021:       while (t < target_end) {
        !          3022:        if (*t != *p++)
        !          3023:          break;
        !          3024:        t++;
        !          3025:       }
        !          3026:       if (t == target_end)
        !          3027:        return s;
        !          3028:     }
        !          3029:     s = (UChar* )onigenc_get_prev_char_head(enc, adjust_text, s);
        !          3030:   }
        !          3031: 
        !          3032:   return (UChar* )NULL;
        !          3033: }
        !          3034: 
        !          3035: static UChar*
        !          3036: slow_search_backward_ic(OnigEncoding enc, int ambig_flag,
        !          3037:                        UChar* target, UChar* target_end,
        !          3038:                        const UChar* text, const UChar* adjust_text,
        !          3039:                        const UChar* text_end, const UChar* text_start)
        !          3040: {
        !          3041:   UChar *s;
        !          3042: 
        !          3043:   s = (UChar* )text_end;
        !          3044:   s -= (target_end - target);
        !          3045:   if (s > text_start)
        !          3046:     s = (UChar* )text_start;
        !          3047:   else
        !          3048:     s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, adjust_text, s);
        !          3049: 
        !          3050:   while (s >= text) {
        !          3051:     if (str_lower_case_match(enc, ambig_flag,
        !          3052:                              target, target_end, s, text_end))
        !          3053:       return s;
        !          3054: 
        !          3055:     s = (UChar* )onigenc_get_prev_char_head(enc, adjust_text, s);
        !          3056:   }
        !          3057: 
        !          3058:   return (UChar* )NULL;
        !          3059: }
        !          3060: 
        !          3061: static UChar*
        !          3062: bm_search_notrev(regex_t* reg, const UChar* target, const UChar* target_end,
        !          3063:                 const UChar* text, const UChar* text_end,
        !          3064:                 const UChar* text_range)
        !          3065: {
        !          3066:   const UChar *s, *se, *t, *p, *end;
        !          3067:   const UChar *tail;
        !          3068:   int skip, tlen1;
        !          3069: 
        !          3070: #ifdef ONIG_DEBUG_SEARCH
        !          3071:   fprintf(stderr, "bm_search_notrev: text: %d, text_end: %d, text_range: %d\n",
        !          3072:          (int )text, (int )text_end, (int )text_range);
        !          3073: #endif
        !          3074: 
        !          3075:   tail = target_end - 1;
        !          3076:   tlen1 = tail - target;
        !          3077:   end = text_range;
        !          3078:   if (end + tlen1 > text_end)
        !          3079:     end = text_end - tlen1;
        !          3080: 
        !          3081:   s = text;
        !          3082: 
        !          3083:   if (IS_NULL(reg->int_map)) {
        !          3084:     while (s < end) {
        !          3085:       p = se = s + tlen1;
        !          3086:       t = tail;
        !          3087:       while (t >= target && *p == *t) {
        !          3088:         p--; t--;
        !          3089:       }
        !          3090:       if (t < target) return (UChar* )s;
        !          3091: 
        !          3092:       skip = reg->map[*se];
        !          3093:       t = s;
        !          3094:       do {
        !          3095:         s += enc_len(reg->enc, s);
        !          3096:       } while ((s - t) < skip && s < end);
        !          3097:     }
        !          3098:   }
        !          3099:   else {
        !          3100:     while (s < end) {
        !          3101:       p = se = s + tlen1;
        !          3102:       t = tail;
        !          3103:       while (t >= target && *p == *t) {
        !          3104:         p--; t--;
        !          3105:       }
        !          3106:       if (t < target) return (UChar* )s;
        !          3107: 
        !          3108:       skip = reg->int_map[*se];
        !          3109:       t = s;
        !          3110:       do {
        !          3111:         s += enc_len(reg->enc, s);
        !          3112:       } while ((s - t) < skip && s < end);
        !          3113:     }
        !          3114:   }
        !          3115: 
        !          3116:   return (UChar* )NULL;
        !          3117: }
        !          3118: 
        !          3119: static UChar*
        !          3120: bm_search(regex_t* reg, const UChar* target, const UChar* target_end,
        !          3121:          const UChar* text, const UChar* text_end, const UChar* text_range)
        !          3122: {
        !          3123:   const UChar *s, *t, *p, *end;
        !          3124:   const UChar *tail;
        !          3125: 
        !          3126:   end = text_range + (target_end - target) - 1;
        !          3127:   if (end > text_end)
        !          3128:     end = text_end;
        !          3129: 
        !          3130:   tail = target_end - 1;
        !          3131:   s = text + (target_end - target) - 1;
        !          3132:   if (IS_NULL(reg->int_map)) {
        !          3133:     while (s < end) {
        !          3134:       p = s;
        !          3135:       t = tail;
        !          3136:       while (t >= target && *p == *t) {
        !          3137:        p--; t--;
        !          3138:       }
        !          3139:       if (t < target) return (UChar* )(p + 1);
        !          3140:       s += reg->map[*s];
        !          3141:     }
        !          3142:   }
        !          3143:   else { /* see int_map[] */
        !          3144:     while (s < end) {
        !          3145:       p = s;
        !          3146:       t = tail;
        !          3147:       while (t >= target && *p == *t) {
        !          3148:        p--; t--;
        !          3149:       }
        !          3150:       if (t < target) return (UChar* )(p + 1);
        !          3151:       s += reg->int_map[*s];
        !          3152:     }
        !          3153:   }
        !          3154:   return (UChar* )NULL;
        !          3155: }
        !          3156: 
        !          3157: static int
        !          3158: set_bm_backward_skip(UChar* s, UChar* end, OnigEncoding enc, int** skip)
        !          3159:                     
        !          3160: {
        !          3161:   int i, len;
        !          3162: 
        !          3163:   if (IS_NULL(*skip)) {
        !          3164:     *skip = (int* )xmalloc(sizeof(int) * ONIG_CHAR_TABLE_SIZE);
        !          3165:     if (IS_NULL(*skip)) return ONIGERR_MEMORY;
        !          3166:   }
        !          3167: 
        !          3168:   len = end - s;
        !          3169:   for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++)
        !          3170:     (*skip)[i] = len;
        !          3171: 
        !          3172:   for (i = len - 1; i > 0; i--)
        !          3173:     (*skip)[s[i]] = i;
        !          3174: 
        !          3175:   return 0;
        !          3176: }
        !          3177: 
        !          3178: static UChar*
        !          3179: bm_search_backward(regex_t* reg, const UChar* target, const UChar* target_end,
        !          3180:                   const UChar* text, const UChar* adjust_text,
        !          3181:                   const UChar* text_end, const UChar* text_start)
        !          3182: {
        !          3183:   const UChar *s, *t, *p;
        !          3184: 
        !          3185:   s = text_end - (target_end - target);
        !          3186:   if (text_start < s)
        !          3187:     s = text_start;
        !          3188:   else
        !          3189:     s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, adjust_text, s);
        !          3190: 
        !          3191:   while (s >= text) {
        !          3192:     p = s;
        !          3193:     t = target;
        !          3194:     while (t < target_end && *p == *t) {
        !          3195:       p++; t++;
        !          3196:     }
        !          3197:     if (t == target_end)
        !          3198:       return (UChar* )s;
        !          3199: 
        !          3200:     s -= reg->int_map_backward[*s];
        !          3201:     s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, adjust_text, s);
        !          3202:   }
        !          3203: 
        !          3204:   return (UChar* )NULL;
        !          3205: }
        !          3206: 
        !          3207: static UChar*
        !          3208: map_search(OnigEncoding enc, UChar map[],
        !          3209:           const UChar* text, const UChar* text_range)
        !          3210: {
        !          3211:   const UChar *s = text;
        !          3212: 
        !          3213:   while (s < text_range) {
        !          3214:     if (map[*s]) return (UChar* )s;
        !          3215: 
        !          3216:     s += enc_len(enc, s);
        !          3217:   }
        !          3218:   return (UChar* )NULL;
        !          3219: }
        !          3220: 
        !          3221: static UChar*
        !          3222: map_search_backward(OnigEncoding enc, UChar map[],
        !          3223:                    const UChar* text, const UChar* adjust_text,
        !          3224:                    const UChar* text_start)
        !          3225: {
        !          3226:   const UChar *s = text_start;
        !          3227: 
        !          3228:   while (s >= text) {
        !          3229:     if (map[*s]) return (UChar* )s;
        !          3230: 
        !          3231:     s = onigenc_get_prev_char_head(enc, adjust_text, s);
        !          3232:   }
        !          3233:   return (UChar* )NULL;
        !          3234: }
        !          3235: 
        !          3236: extern int
        !          3237: onig_match(regex_t* reg, const UChar* str, const UChar* end, const UChar* at, OnigRegion* region,
        !          3238:            OnigOptionType option)
        !          3239: {
        !          3240:   int r;
        !          3241:   UChar *prev;
        !          3242:   MatchArg msa;
        !          3243: 
        !          3244: #if defined(USE_RECOMPILE_API) && defined(USE_MULTI_THREAD_SYSTEM)
        !          3245:  start:
        !          3246:   THREAD_ATOMIC_START;
        !          3247:   if (ONIG_STATE(reg) >= ONIG_STATE_NORMAL) {
        !          3248:     ONIG_STATE_INC(reg);
        !          3249:     if (IS_NOT_NULL(reg->chain) && ONIG_STATE(reg) == ONIG_STATE_NORMAL) {
        !          3250:       onig_chain_reduce(reg);
        !          3251:       ONIG_STATE_INC(reg);
        !          3252:     }
        !          3253:   }
        !          3254:   else {
        !          3255:     int n;
        !          3256: 
        !          3257:     THREAD_ATOMIC_END;
        !          3258:     n = 0;
        !          3259:     while (ONIG_STATE(reg) < ONIG_STATE_NORMAL) {
        !          3260:       if (++n > THREAD_PASS_LIMIT_COUNT)
        !          3261:        return ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT;
        !          3262:       THREAD_PASS;
        !          3263:     }
        !          3264:     goto start;
        !          3265:   }
        !          3266:   THREAD_ATOMIC_END;
        !          3267: #endif /* USE_RECOMPILE_API && USE_MULTI_THREAD_SYSTEM */
        !          3268: 
        !          3269:   MATCH_ARG_INIT(msa, option, region, at);
        !          3270: #ifdef USE_COMBINATION_EXPLOSION_CHECK
        !          3271:   {
        !          3272:     int offset = at - str;
        !          3273:     STATE_CHECK_BUFF_INIT(msa, end - str, offset, reg->num_comb_exp_check);
        !          3274:   }
        !          3275: #endif
        !          3276: 
        !          3277:   if (region
        !          3278: #ifdef USE_POSIX_REGION_OPTION
        !          3279:       && !IS_POSIX_REGION(option)
        !          3280: #endif
        !          3281:       ) {
        !          3282:     r = onig_region_resize_clear(region, reg->num_mem + 1);
        !          3283:   }
        !          3284:   else
        !          3285:     r = 0;
        !          3286: 
        !          3287:   if (r == 0) {
        !          3288:     prev = (UChar* )onigenc_get_prev_char_head(reg->enc, str, at);
        !          3289:     r = match_at(reg, str, end, at, prev, &msa);
        !          3290:   }
        !          3291: 
        !          3292:   MATCH_ARG_FREE(msa);
        !          3293:   ONIG_STATE_DEC_THREAD(reg);
        !          3294:   return r;
        !          3295: }
        !          3296: 
        !          3297: static int
        !          3298: forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
        !          3299:                     UChar* range, UChar** low, UChar** high, UChar** low_prev)
        !          3300: {
        !          3301:   UChar *p, *pprev = (UChar* )NULL;
        !          3302: 
        !          3303: #ifdef ONIG_DEBUG_SEARCH
        !          3304:   fprintf(stderr, "forward_search_range: str: %d, end: %d, s: %d, range: %d\n",
        !          3305:          (int )str, (int )end, (int )s, (int )range);
        !          3306: #endif
        !          3307: 
        !          3308:   p = s;
        !          3309:   if (reg->dmin > 0) {
        !          3310:     if (ONIGENC_IS_SINGLEBYTE(reg->enc)) {
        !          3311:       p += reg->dmin;
        !          3312:     }
        !          3313:     else {
        !          3314:       UChar *q = p + reg->dmin;
        !          3315:       while (p < q) p += enc_len(reg->enc, p);
        !          3316:     }
        !          3317:   }
        !          3318: 
        !          3319:  retry:
        !          3320:   switch (reg->optimize) {
        !          3321:   case ONIG_OPTIMIZE_EXACT:
        !          3322:     p = slow_search(reg->enc, reg->exact, reg->exact_end, p, end, range);
        !          3323:     break;
        !          3324:   case ONIG_OPTIMIZE_EXACT_IC:
        !          3325:     p = slow_search_ic(reg->enc, reg->ambig_flag,
        !          3326:                        reg->exact, reg->exact_end, p, end, range);
        !          3327:     break;
        !          3328: 
        !          3329:   case ONIG_OPTIMIZE_EXACT_BM:
        !          3330:     p = bm_search(reg, reg->exact, reg->exact_end, p, end, range);
        !          3331:     break;
        !          3332: 
        !          3333:   case ONIG_OPTIMIZE_EXACT_BM_NOT_REV:
        !          3334:     p = bm_search_notrev(reg, reg->exact, reg->exact_end, p, end, range);
        !          3335:     break;
        !          3336: 
        !          3337:   case ONIG_OPTIMIZE_MAP:
        !          3338:     p = map_search(reg->enc, reg->map, p, range);
        !          3339:     break;
        !          3340:   }
        !          3341: 
        !          3342:   if (p && p < range) {
        !          3343:     if (p - reg->dmin < s) {
        !          3344:     retry_gate:
        !          3345:       pprev = p;
        !          3346:       p += enc_len(reg->enc, p);
        !          3347:       goto retry;
        !          3348:     }
        !          3349: 
        !          3350:     if (reg->sub_anchor) {
        !          3351:       UChar* prev;
        !          3352: 
        !          3353:       switch (reg->sub_anchor) {
        !          3354:       case ANCHOR_BEGIN_LINE:
        !          3355:        if (!ON_STR_BEGIN(p)) {
        !          3356:          prev = onigenc_get_prev_char_head(reg->enc,
        !          3357:                                            (pprev ? pprev : str), p);
        !          3358:          if (!ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end))
        !          3359:            goto retry_gate;
        !          3360:        }
        !          3361:        break;
        !          3362: 
        !          3363:       case ANCHOR_END_LINE:
        !          3364:        if (ON_STR_END(p)) {
        !          3365:          prev = (UChar* )onigenc_get_prev_char_head(reg->enc,
        !          3366:                                            (pprev ? pprev : str), p);
        !          3367:          if (prev && ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end))
        !          3368:            goto retry_gate;
        !          3369:        }
        !          3370:        else if (! ONIGENC_IS_MBC_NEWLINE(reg->enc, p, end)
        !          3371: #ifdef USE_CRNL_AS_LINE_TERMINATOR
        !          3372:               && ! ONIGENC_IS_MBC_CRNL(reg->enc, p, end)
        !          3373: #endif
        !          3374:                 )
        !          3375:          goto retry_gate;
        !          3376:        break;
        !          3377:       }
        !          3378:     }
        !          3379: 
        !          3380:     if (reg->dmax == 0) {
        !          3381:       *low = p;
        !          3382:       if (low_prev) {
        !          3383:        if (*low > s)
        !          3384:          *low_prev = onigenc_get_prev_char_head(reg->enc, s, p);
        !          3385:        else
        !          3386:          *low_prev = onigenc_get_prev_char_head(reg->enc,
        !          3387:                                                 (pprev ? pprev : str), p);
        !          3388:       }
        !          3389:     }
        !          3390:     else {
        !          3391:       if (reg->dmax != ONIG_INFINITE_DISTANCE) {
        !          3392:        *low = p - reg->dmax;
        !          3393:        if (*low > s) {
        !          3394:          *low = onigenc_get_right_adjust_char_head_with_prev(reg->enc, s,
        !          3395:                                                              *low, (const UChar** )low_prev);
        !          3396:          if (low_prev && IS_NULL(*low_prev))
        !          3397:            *low_prev = onigenc_get_prev_char_head(reg->enc,
        !          3398:                                                   (pprev ? pprev : s), *low);
        !          3399:        }
        !          3400:        else {
        !          3401:          if (low_prev)
        !          3402:            *low_prev = onigenc_get_prev_char_head(reg->enc,
        !          3403:                                               (pprev ? pprev : str), *low);
        !          3404:        }
        !          3405:       }
        !          3406:     }
        !          3407:     /* no needs to adjust *high, *high is used as range check only */
        !          3408:     *high = p - reg->dmin;
        !          3409: 
        !          3410: #ifdef ONIG_DEBUG_SEARCH
        !          3411:     fprintf(stderr,
        !          3412:     "forward_search_range success: low: %d, high: %d, dmin: %d, dmax: %d\n",
        !          3413:            (int )(*low - str), (int )(*high - str), reg->dmin, reg->dmax);
        !          3414: #endif
        !          3415:     return 1; /* success */
        !          3416:   }
        !          3417: 
        !          3418:   return 0; /* fail */
        !          3419: }
        !          3420: 
        !          3421: static int set_bm_backward_skip P_((UChar* s, UChar* end, OnigEncoding enc,
        !          3422:                                    int** skip));
        !          3423: 
        !          3424: #define BM_BACKWARD_SEARCH_LENGTH_THRESHOLD   100
        !          3425: 
        !          3426: static int
        !          3427: backward_search_range(regex_t* reg, const UChar* str, const UChar* end,
        !          3428:                      UChar* s, const UChar* range, UChar* adjrange,
        !          3429:                      UChar** low, UChar** high)
        !          3430: {
        !          3431:   int r;
        !          3432:   UChar *p;
        !          3433: 
        !          3434:   range += reg->dmin;
        !          3435:   p = s;
        !          3436: 
        !          3437:  retry:
        !          3438:   switch (reg->optimize) {
        !          3439:   case ONIG_OPTIMIZE_EXACT:
        !          3440:   exact_method:
        !          3441:     p = slow_search_backward(reg->enc, reg->exact, reg->exact_end,
        !          3442:                             range, adjrange, end, p);
        !          3443:     break;
        !          3444: 
        !          3445:   case ONIG_OPTIMIZE_EXACT_IC:
        !          3446:     p = slow_search_backward_ic(reg->enc, reg->ambig_flag,
        !          3447:                                 reg->exact, reg->exact_end,
        !          3448:                                 range, adjrange, end, p);
        !          3449:     break;
        !          3450: 
        !          3451:   case ONIG_OPTIMIZE_EXACT_BM:
        !          3452:   case ONIG_OPTIMIZE_EXACT_BM_NOT_REV:
        !          3453:     if (IS_NULL(reg->int_map_backward)) {
        !          3454:       if (s - range < BM_BACKWARD_SEARCH_LENGTH_THRESHOLD)
        !          3455:        goto exact_method;
        !          3456: 
        !          3457:       r = set_bm_backward_skip(reg->exact, reg->exact_end, reg->enc,
        !          3458:                               &(reg->int_map_backward));
        !          3459:       if (r) return r;
        !          3460:     }
        !          3461:     p = bm_search_backward(reg, reg->exact, reg->exact_end, range, adjrange,
        !          3462:                           end, p);
        !          3463:     break;
        !          3464: 
        !          3465:   case ONIG_OPTIMIZE_MAP:
        !          3466:     p = map_search_backward(reg->enc, reg->map, range, adjrange, p);
        !          3467:     break;
        !          3468:   }
        !          3469: 
        !          3470:   if (p) {
        !          3471:     if (reg->sub_anchor) {
        !          3472:       UChar* prev;
        !          3473: 
        !          3474:       switch (reg->sub_anchor) {
        !          3475:       case ANCHOR_BEGIN_LINE:
        !          3476:        if (!ON_STR_BEGIN(p)) {
        !          3477:          prev = onigenc_get_prev_char_head(reg->enc, str, p);
        !          3478:          if (!ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end)) {
        !          3479:            p = prev;
        !          3480:            goto retry;
        !          3481:          }
        !          3482:        }
        !          3483:        break;
        !          3484: 
        !          3485:       case ANCHOR_END_LINE:
        !          3486:        if (ON_STR_END(p)) {
        !          3487:          prev = onigenc_get_prev_char_head(reg->enc, adjrange, p);
        !          3488:          if (IS_NULL(prev)) goto fail;
        !          3489:          if (ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end)) {
        !          3490:            p = prev;
        !          3491:            goto retry;
        !          3492:          }
        !          3493:        }
        !          3494:        else if (! ONIGENC_IS_MBC_NEWLINE(reg->enc, p, end)
        !          3495: #ifdef USE_CRNL_AS_LINE_TERMINATOR
        !          3496:               && ! ONIGENC_IS_MBC_CRNL(reg->enc, p, end)
        !          3497: #endif
        !          3498:                 ) {
        !          3499:          p = onigenc_get_prev_char_head(reg->enc, adjrange, p);
        !          3500:          if (IS_NULL(p)) goto fail;
        !          3501:          goto retry;
        !          3502:        }
        !          3503:        break;
        !          3504:       }
        !          3505:     }
        !          3506: 
        !          3507:     /* no needs to adjust *high, *high is used as range check only */
        !          3508:     if (reg->dmax != ONIG_INFINITE_DISTANCE) {
        !          3509:       *low  = p - reg->dmax;
        !          3510:       *high = p - reg->dmin;
        !          3511:       *high = onigenc_get_right_adjust_char_head(reg->enc, adjrange, *high);
        !          3512:     }
        !          3513: 
        !          3514: #ifdef ONIG_DEBUG_SEARCH
        !          3515:     fprintf(stderr, "backward_search_range: low: %d, high: %d\n",
        !          3516:            (int )(*low - str), (int )(*high - str));
        !          3517: #endif
        !          3518:     return 1; /* success */
        !          3519:   }
        !          3520: 
        !          3521:  fail:
        !          3522: #ifdef ONIG_DEBUG_SEARCH
        !          3523:   fprintf(stderr, "backward_search_range: fail.\n");
        !          3524: #endif
        !          3525:   return 0; /* fail */
        !          3526: }
        !          3527: 
        !          3528: 
        !          3529: extern int
        !          3530: onig_search(regex_t* reg, const UChar* str, const UChar* end,
        !          3531:            const UChar* start, const UChar* range, OnigRegion* region, OnigOptionType option)
        !          3532: {
        !          3533:   int r;
        !          3534:   UChar *s, *prev;
        !          3535:   MatchArg msa;
        !          3536:   const UChar *orig_start = start;
        !          3537: 
        !          3538: #if defined(USE_RECOMPILE_API) && defined(USE_MULTI_THREAD_SYSTEM)
        !          3539:  start:
        !          3540:   THREAD_ATOMIC_START;
        !          3541:   if (ONIG_STATE(reg) >= ONIG_STATE_NORMAL) {
        !          3542:     ONIG_STATE_INC(reg);
        !          3543:     if (IS_NOT_NULL(reg->chain) && ONIG_STATE(reg) == ONIG_STATE_NORMAL) {
        !          3544:       onig_chain_reduce(reg);
        !          3545:       ONIG_STATE_INC(reg);
        !          3546:     }
        !          3547:   }
        !          3548:   else {
        !          3549:     int n;
        !          3550: 
        !          3551:     THREAD_ATOMIC_END;
        !          3552:     n = 0;
        !          3553:     while (ONIG_STATE(reg) < ONIG_STATE_NORMAL) {
        !          3554:       if (++n > THREAD_PASS_LIMIT_COUNT)
        !          3555:        return ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT;
        !          3556:       THREAD_PASS;
        !          3557:     }
        !          3558:     goto start;
        !          3559:   }
        !          3560:   THREAD_ATOMIC_END;
        !          3561: #endif /* USE_RECOMPILE_API && USE_MULTI_THREAD_SYSTEM */
        !          3562: 
        !          3563: #ifdef ONIG_DEBUG_SEARCH
        !          3564:   fprintf(stderr,
        !          3565:      "onig_search (entry point): str: %d, end: %d, start: %d, range: %d\n",
        !          3566:      (int )str, (int )(end - str), (int )(start - str), (int )(range - str));
        !          3567: #endif
        !          3568: 
        !          3569:   if (region
        !          3570: #ifdef USE_POSIX_REGION_OPTION
        !          3571:       && !IS_POSIX_REGION(option)
        !          3572: #endif
        !          3573:       ) {
        !          3574:     r = onig_region_resize_clear(region, reg->num_mem + 1);
        !          3575:     if (r) goto finish_no_msa;
        !          3576:   }
        !          3577: 
        !          3578:   if (start > end || start < str) goto mismatch_no_msa;
        !          3579: 
        !          3580: #ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE
        !          3581: #define MATCH_AND_RETURN_CHECK \
        !          3582:   r = match_at(reg, str, end, s, prev, &msa);\
        !          3583:   if (r != ONIG_MISMATCH) {\
        !          3584:     if (r >= 0) {\
        !          3585:       if (! IS_FIND_LONGEST(reg->options)) {\
        !          3586:         goto match;\
        !          3587:       }\
        !          3588:     }\
        !          3589:     else goto finish; /* error */ \
        !          3590:   }
        !          3591: #else
        !          3592: #define MATCH_AND_RETURN_CHECK \
        !          3593:   r = match_at(reg, str, end, s, prev, &msa);\
        !          3594:   if (r != ONIG_MISMATCH) {\
        !          3595:     if (r >= 0) {\
        !          3596:       goto match;\
        !          3597:     }\
        !          3598:     else goto finish; /* error */ \
        !          3599:   }
        !          3600: #endif
        !          3601: 
        !          3602:   /* anchor optimize: resume search range */
        !          3603:   if (reg->anchor != 0 && str < end) {
        !          3604:     UChar *min_semi_end, *max_semi_end;
        !          3605: 
        !          3606:     if (reg->anchor & ANCHOR_BEGIN_POSITION) {
        !          3607:       /* search start-position only */
        !          3608:     begin_position:
        !          3609:       if (range > start)
        !          3610:        range = start + 1;
        !          3611:       else
        !          3612:        range = start;
        !          3613:     }
        !          3614:     else if (reg->anchor & ANCHOR_BEGIN_BUF) {
        !          3615:       /* search str-position only */
        !          3616:       if (range > start) {
        !          3617:        if (start != str) goto mismatch_no_msa;
        !          3618:        range = str + 1;
        !          3619:       }
        !          3620:       else {
        !          3621:        if (range <= str) {
        !          3622:          start = str;
        !          3623:          range = str;
        !          3624:        }
        !          3625:        else
        !          3626:          goto mismatch_no_msa;
        !          3627:       }
        !          3628:     }
        !          3629:     else if (reg->anchor & ANCHOR_END_BUF) {
        !          3630:       min_semi_end = max_semi_end = (UChar* )end;
        !          3631: 
        !          3632:     end_buf:
        !          3633:       if ((OnigDistance )(max_semi_end - str) < reg->anchor_dmin)
        !          3634:        goto mismatch_no_msa;
        !          3635: 
        !          3636:       if (range > start) {
        !          3637:        if ((OnigDistance )(min_semi_end - start) > reg->anchor_dmax) {
        !          3638:          start = min_semi_end - reg->anchor_dmax;
        !          3639:          if (start < end)
        !          3640:            start = onigenc_get_right_adjust_char_head(reg->enc, str, start);
        !          3641:          else { /* match with empty at end */
        !          3642:            start = onigenc_get_prev_char_head(reg->enc, str, end);
        !          3643:          }
        !          3644:        }
        !          3645:        if ((OnigDistance )(max_semi_end - (range - 1)) < reg->anchor_dmin) {
        !          3646:          range = max_semi_end - reg->anchor_dmin + 1;
        !          3647:        }
        !          3648: 
        !          3649:        if (start >= range) goto mismatch_no_msa;
        !          3650:       }
        !          3651:       else {
        !          3652:        if ((OnigDistance )(min_semi_end - range) > reg->anchor_dmax) {
        !          3653:          range = min_semi_end - reg->anchor_dmax;
        !          3654:        }
        !          3655:        if ((OnigDistance )(max_semi_end - start) < reg->anchor_dmin) {
        !          3656:          start = max_semi_end - reg->anchor_dmin;
        !          3657:          start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, start);
        !          3658:        }
        !          3659:        if (range > start) goto mismatch_no_msa;
        !          3660:       }
        !          3661:     }
        !          3662:     else if (reg->anchor & ANCHOR_SEMI_END_BUF) {
        !          3663:       UChar* pre_end = ONIGENC_STEP_BACK(reg->enc, str, end, 1);
        !          3664: 
        !          3665:       max_semi_end = (UChar* )end;
        !          3666:       if (ONIGENC_IS_MBC_NEWLINE(reg->enc, pre_end, end)) {
        !          3667:        min_semi_end = pre_end;
        !          3668: 
        !          3669: #ifdef USE_CRNL_AS_LINE_TERMINATOR
        !          3670:        pre_end = ONIGENC_STEP_BACK(reg->enc, str, pre_end, 1);
        !          3671:        if (IS_NOT_NULL(pre_end) &&
        !          3672:            ONIGENC_IS_MBC_CRNL(reg->enc, pre_end, end)) {
        !          3673:          min_semi_end = pre_end;
        !          3674:        }
        !          3675: #endif
        !          3676:        if (min_semi_end > str && start <= min_semi_end) {
        !          3677:          goto end_buf;
        !          3678:        }
        !          3679:       }
        !          3680:       else {
        !          3681:        min_semi_end = (UChar* )end;
        !          3682:        goto end_buf;
        !          3683:       }
        !          3684:     }
        !          3685:     else if ((reg->anchor & ANCHOR_ANYCHAR_STAR_ML)) {
        !          3686:       goto begin_position;
        !          3687:     }
        !          3688:   }
        !          3689:   else if (str == end) { /* empty string */
        !          3690:     static const UChar* address_for_empty_string = (UChar* )"";
        !          3691: 
        !          3692: #ifdef ONIG_DEBUG_SEARCH
        !          3693:     fprintf(stderr, "onig_search: empty string.\n");
        !          3694: #endif
        !          3695: 
        !          3696:     if (reg->threshold_len == 0) {
        !          3697:       start = end = str = address_for_empty_string;
        !          3698:       s = (UChar* )start;
        !          3699:       prev = (UChar* )NULL;
        !          3700: 
        !          3701:       MATCH_ARG_INIT(msa, option, region, start);
        !          3702: #ifdef USE_COMBINATION_EXPLOSION_CHECK
        !          3703:       msa.state_check_buff      = (void* )0;
        !          3704:       msa.state_check_buff_size = 0;
        !          3705: #endif
        !          3706:       MATCH_AND_RETURN_CHECK;
        !          3707:       goto mismatch;
        !          3708:     }
        !          3709:     goto mismatch_no_msa;
        !          3710:   }
        !          3711: 
        !          3712: #ifdef ONIG_DEBUG_SEARCH
        !          3713:   fprintf(stderr, "onig_search(apply anchor): end: %d, start: %d, range: %d\n",
        !          3714:          (int )(end - str), (int )(start - str), (int )(range - str));
        !          3715: #endif
        !          3716: 
        !          3717:   MATCH_ARG_INIT(msa, option, region, orig_start);
        !          3718: #ifdef USE_COMBINATION_EXPLOSION_CHECK
        !          3719:   {
        !          3720:     int offset = (MIN(start, range) - str);
        !          3721:     STATE_CHECK_BUFF_INIT(msa, end - str, offset, reg->num_comb_exp_check);
        !          3722:   }
        !          3723: #endif
        !          3724: 
        !          3725:   s = (UChar* )start;
        !          3726:   if (range > start) {   /* forward search */
        !          3727:     if (s > str)
        !          3728:       prev = onigenc_get_prev_char_head(reg->enc, str, s);
        !          3729:     else
        !          3730:       prev = (UChar* )NULL;
        !          3731: 
        !          3732:     if (reg->optimize != ONIG_OPTIMIZE_NONE) {
        !          3733:       UChar *sch_range, *low, *high, *low_prev;
        !          3734: 
        !          3735:       sch_range = (UChar* )range;
        !          3736:       if (reg->dmax != 0) {
        !          3737:        if (reg->dmax == ONIG_INFINITE_DISTANCE)
        !          3738:          sch_range = (UChar* )end;
        !          3739:        else {
        !          3740:          sch_range += reg->dmax;
        !          3741:          if (sch_range > end) sch_range = (UChar* )end;
        !          3742:        }
        !          3743:       }
        !          3744: 
        !          3745:       if ((end - start) < reg->threshold_len)
        !          3746:         goto mismatch;
        !          3747: 
        !          3748:       if (reg->dmax != ONIG_INFINITE_DISTANCE) {
        !          3749:        do {
        !          3750:          if (! forward_search_range(reg, str, end, s, sch_range,
        !          3751:                                     &low, &high, &low_prev)) goto mismatch;
        !          3752:          if (s < low) {
        !          3753:            s    = low;
        !          3754:            prev = low_prev;
        !          3755:          }
        !          3756:          while (s <= high) {
        !          3757:            MATCH_AND_RETURN_CHECK;
        !          3758:            prev = s;
        !          3759:            s += enc_len(reg->enc, s);
        !          3760:          }
        !          3761:        } while (s < range);
        !          3762:        goto mismatch;
        !          3763:       }
        !          3764:       else { /* check only. */
        !          3765:        if (! forward_search_range(reg, str, end, s, sch_range,
        !          3766:                                   &low, &high, (UChar** )NULL)) goto mismatch;
        !          3767: 
        !          3768:         if ((reg->anchor & ANCHOR_ANYCHAR_STAR) != 0) {
        !          3769:           do {
        !          3770:             MATCH_AND_RETURN_CHECK;
        !          3771:             prev = s;
        !          3772:             s += enc_len(reg->enc, s);
        !          3773: 
        !          3774:             while (!ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end) && s < range) {
        !          3775:               prev = s;
        !          3776:               s += enc_len(reg->enc, s);
        !          3777:             }
        !          3778:           } while (s < range);
        !          3779:           goto mismatch;
        !          3780:         }
        !          3781:       }
        !          3782:     }
        !          3783: 
        !          3784:     do {
        !          3785:       MATCH_AND_RETURN_CHECK;
        !          3786:       prev = s;
        !          3787:       s += enc_len(reg->enc, s);
        !          3788:     } while (s < range);
        !          3789: 
        !          3790:     if (s == range) { /* because empty match with /$/. */
        !          3791:       MATCH_AND_RETURN_CHECK;
        !          3792:     }
        !          3793:   }
        !          3794:   else {  /* backward search */
        !          3795:     if (reg->optimize != ONIG_OPTIMIZE_NONE) {
        !          3796:       UChar *low, *high, *adjrange, *sch_start;
        !          3797: 
        !          3798:       if (range < end)
        !          3799:        adjrange = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, range);
        !          3800:       else
        !          3801:        adjrange = (UChar* )end;
        !          3802: 
        !          3803:       if (reg->dmax != ONIG_INFINITE_DISTANCE &&
        !          3804:          (end - range) >= reg->threshold_len) {
        !          3805:        do {
        !          3806:          sch_start = s + reg->dmax;
        !          3807:          if (sch_start > end) sch_start = (UChar* )end;
        !          3808:          if (backward_search_range(reg, str, end, sch_start, range, adjrange,
        !          3809:                                    &low, &high) <= 0)
        !          3810:            goto mismatch;
        !          3811: 
        !          3812:          if (s > high)
        !          3813:            s = high;
        !          3814: 
        !          3815:          while (s >= low) {
        !          3816:            prev = onigenc_get_prev_char_head(reg->enc, str, s);
        !          3817:            MATCH_AND_RETURN_CHECK;
        !          3818:            s = prev;
        !          3819:          }
        !          3820:        } while (s >= range);
        !          3821:        goto mismatch;
        !          3822:       }
        !          3823:       else { /* check only. */
        !          3824:        if ((end - range) < reg->threshold_len) goto mismatch;
        !          3825: 
        !          3826:        sch_start = s;
        !          3827:        if (reg->dmax != 0) {
        !          3828:          if (reg->dmax == ONIG_INFINITE_DISTANCE)
        !          3829:            sch_start = (UChar* )end;
        !          3830:          else {
        !          3831:            sch_start += reg->dmax;
        !          3832:            if (sch_start > end) sch_start = (UChar* )end;
        !          3833:            else
        !          3834:              sch_start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc,
        !          3835:                                                    start, sch_start);
        !          3836:          }
        !          3837:        }
        !          3838:        if (backward_search_range(reg, str, end, sch_start, range, adjrange,
        !          3839:                                  &low, &high) <= 0) goto mismatch;
        !          3840:       }
        !          3841:     }
        !          3842: 
        !          3843:     do {
        !          3844:       prev = onigenc_get_prev_char_head(reg->enc, str, s);
        !          3845:       MATCH_AND_RETURN_CHECK;
        !          3846:       s = prev;
        !          3847:     } while (s >= range);
        !          3848:   }
        !          3849: 
        !          3850:  mismatch:
        !          3851: #ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE
        !          3852:   if (IS_FIND_LONGEST(reg->options)) {
        !          3853:     if (msa.best_len >= 0) {
        !          3854:       s = msa.best_s;
        !          3855:       goto match;
        !          3856:     }
        !          3857:   }
        !          3858: #endif
        !          3859:   r = ONIG_MISMATCH;
        !          3860: 
        !          3861:  finish:
        !          3862:   MATCH_ARG_FREE(msa);
        !          3863:   ONIG_STATE_DEC_THREAD(reg);
        !          3864: 
        !          3865:   /* If result is mismatch and no FIND_NOT_EMPTY option,
        !          3866:      then the region is not setted in match_at(). */
        !          3867:   if (IS_FIND_NOT_EMPTY(reg->options) && region
        !          3868: #ifdef USE_POSIX_REGION_OPTION
        !          3869:       && !IS_POSIX_REGION(option)
        !          3870: #endif
        !          3871:       ) {
        !          3872:     onig_region_clear(region);
        !          3873:   }
        !          3874: 
        !          3875: #ifdef ONIG_DEBUG
        !          3876:   if (r != ONIG_MISMATCH)
        !          3877:     fprintf(stderr, "onig_search: error %d\n", r);
        !          3878: #endif
        !          3879:   return r;
        !          3880: 
        !          3881:  mismatch_no_msa:
        !          3882:   r = ONIG_MISMATCH;
        !          3883:  finish_no_msa:
        !          3884:   ONIG_STATE_DEC_THREAD(reg);
        !          3885: #ifdef ONIG_DEBUG
        !          3886:   if (r != ONIG_MISMATCH)
        !          3887:     fprintf(stderr, "onig_search: error %d\n", r);
        !          3888: #endif
        !          3889:   return r;
        !          3890: 
        !          3891:  match:
        !          3892:   ONIG_STATE_DEC_THREAD(reg);
        !          3893:   MATCH_ARG_FREE(msa);
        !          3894:   return s - str;
        !          3895: }
        !          3896: 
        !          3897: extern OnigEncoding
        !          3898: onig_get_encoding(regex_t* reg)
        !          3899: {
        !          3900:   return reg->enc;
        !          3901: }
        !          3902: 
        !          3903: extern OnigOptionType
        !          3904: onig_get_options(regex_t* reg)
        !          3905: {
        !          3906:   return reg->options;
        !          3907: }
        !          3908: 
        !          3909: extern  OnigAmbigType
        !          3910: onig_get_ambig_flag(regex_t* reg)
        !          3911: {
        !          3912:   return reg->ambig_flag;
        !          3913: }
        !          3914: 
        !          3915: extern OnigSyntaxType*
        !          3916: onig_get_syntax(regex_t* reg)
        !          3917: {
        !          3918:   return reg->syntax;
        !          3919: }
        !          3920: 
        !          3921: extern int
        !          3922: onig_number_of_captures(regex_t* reg)
        !          3923: {
        !          3924:   return reg->num_mem;
        !          3925: }
        !          3926: 
        !          3927: extern int
        !          3928: onig_number_of_capture_histories(regex_t* reg)
        !          3929: {
        !          3930: #ifdef USE_CAPTURE_HISTORY
        !          3931:   int i, n;
        !          3932: 
        !          3933:   n = 0;
        !          3934:   for (i = 0; i <= ONIG_MAX_CAPTURE_HISTORY_GROUP; i++) {
        !          3935:     if (BIT_STATUS_AT(reg->capture_history, i) != 0)
        !          3936:       n++;
        !          3937:   }
        !          3938:   return n;
        !          3939: #else
        !          3940:   return 0;
        !          3941: #endif
        !          3942: }
        !          3943: 
        !          3944: extern void
        !          3945: onig_copy_encoding(OnigEncoding to, OnigEncoding from)
        !          3946: {
        !          3947:   *to = *from;
        !          3948: }
        !          3949: 

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