Ruby 2.0.0p247(2013-06-27revision41674)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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