root/ext/mbstring/oniguruma/regexec.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. history_tree_clear
  2. history_tree_free
  3. history_root_free
  4. history_node_new
  5. history_tree_add_child
  6. history_tree_clone
  7. onig_get_capture_tree
  8. onig_region_clear
  9. onig_region_resize
  10. onig_region_resize_clear
  11. onig_region_set
  12. onig_region_init
  13. onig_region_new
  14. onig_region_free
  15. onig_region_copy
  16. onig_get_match_stack_limit_size
  17. onig_set_match_stack_limit_size
  18. stack_double
  19. string_cmp_ic
  20. make_capture_history_tree
  21. mem_is_in_memp
  22. backref_match_at_nested_level
  23. onig_statistics_init
  24. onig_print_statistics
  25. match_at
  26. slow_search
  27. str_lower_case_match
  28. slow_search_ic
  29. slow_search_backward
  30. slow_search_backward_ic
  31. bm_search_notrev
  32. bm_search
  33. set_bm_backward_skip
  34. bm_search_backward
  35. map_search
  36. map_search_backward
  37. onig_match
  38. forward_search_range
  39. backward_search_range
  40. onig_search
  41. onig_get_encoding
  42. onig_get_options
  43. onig_get_case_fold_flag
  44. onig_get_syntax
  45. onig_number_of_captures
  46. onig_number_of_capture_histories
  47. onig_copy_encoding

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

/* [<][>][^][v][top][bottom][index][help] */