source: EcnlProtoTool/trunk/onigmo-5.15.0/src/regexec.c@ 279

Last change on this file since 279 was 279, checked in by coas-nagasima, 7 years ago

ファイルを追加、更新。

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