Ruby 3.3.0p0 (2023-12-25 revision 5124f9ac7513eb590c37717337c430cb93caa151)
regexec.c
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-2016 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#ifdef RUBY
34# undef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE
35#else
36# define USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE
37#endif
38
39#ifndef USE_TOKEN_THREADED_VM
40# ifdef __GNUC__
41# define USE_TOKEN_THREADED_VM 1
42# else
43# define USE_TOKEN_THREADED_VM 0
44# endif
45#endif
46
47#ifdef RUBY
48# define ENC_DUMMY_FLAG (1<<24)
49static inline int
50rb_enc_asciicompat(OnigEncoding enc)
51{
52 return ONIGENC_MBC_MINLEN(enc)==1 && !((enc)->ruby_encoding_index & ENC_DUMMY_FLAG);
53}
54# undef ONIGENC_IS_MBC_ASCII_WORD
55# define ONIGENC_IS_MBC_ASCII_WORD(enc,s,end) \
56 (rb_enc_asciicompat(enc) ? (ISALNUM(*s) || *s=='_') : \
57 onigenc_ascii_is_code_ctype( \
58 ONIGENC_MBC_TO_CODE(enc,s,end),ONIGENC_CTYPE_WORD,enc))
59#endif /* RUBY */
60
61#ifdef USE_CRNL_AS_LINE_TERMINATOR
62# define ONIGENC_IS_MBC_CRNL(enc,p,end) \
63 (ONIGENC_MBC_TO_CODE(enc,p,end) == 13 && \
64 ONIGENC_MBC_TO_CODE(enc,(p+enclen(enc,p,end)),end) == 10)
65# define ONIGENC_IS_MBC_NEWLINE_EX(enc,p,start,end,option,check_prev) \
66 is_mbc_newline_ex((enc),(p),(start),(end),(option),(check_prev))
67static int
68is_mbc_newline_ex(OnigEncoding enc, const UChar *p, const UChar *start,
69 const UChar *end, OnigOptionType option, int check_prev)
70{
71 if (IS_NEWLINE_CRLF(option)) {
72 if (ONIGENC_MBC_TO_CODE(enc, p, end) == 0x0a) {
73 if (check_prev) {
74 const UChar *prev = onigenc_get_prev_char_head(enc, start, p, end);
75 if ((prev != NULL) && ONIGENC_MBC_TO_CODE(enc, prev, end) == 0x0d)
76 return 0;
77 else
78 return 1;
79 }
80 else
81 return 1;
82 }
83 else {
84 const UChar *pnext = p + enclen(enc, p, end);
85 if (pnext < end &&
86 ONIGENC_MBC_TO_CODE(enc, p, end) == 0x0d &&
87 ONIGENC_MBC_TO_CODE(enc, pnext, end) == 0x0a)
88 return 1;
89 if (ONIGENC_IS_MBC_NEWLINE(enc, p, end))
90 return 1;
91 return 0;
92 }
93 }
94 else {
95 return ONIGENC_IS_MBC_NEWLINE(enc, p, end);
96 }
97}
98#else /* USE_CRNL_AS_LINE_TERMINATOR */
99# define ONIGENC_IS_MBC_NEWLINE_EX(enc,p,start,end,option,check_prev) \
100 ONIGENC_IS_MBC_NEWLINE((enc), (p), (end))
101#endif /* USE_CRNL_AS_LINE_TERMINATOR */
102
103#ifdef USE_CAPTURE_HISTORY
104static void history_tree_free(OnigCaptureTreeNode* node);
105
106static void
107history_tree_clear(OnigCaptureTreeNode* node)
108{
109 int i;
110
111 if (IS_NOT_NULL(node)) {
112 for (i = 0; i < node->num_childs; i++) {
113 if (IS_NOT_NULL(node->childs[i])) {
114 history_tree_free(node->childs[i]);
115 }
116 }
117 for (i = 0; i < node->allocated; i++) {
118 node->childs[i] = (OnigCaptureTreeNode* )0;
119 }
120 node->num_childs = 0;
121 node->beg = ONIG_REGION_NOTPOS;
122 node->end = ONIG_REGION_NOTPOS;
123 node->group = -1;
124 xfree(node->childs);
125 node->childs = (OnigCaptureTreeNode** )0;
126 }
127}
128
129static void
130history_tree_free(OnigCaptureTreeNode* node)
131{
132 history_tree_clear(node);
133 xfree(node);
134}
135
136static void
137history_root_free(OnigRegion* r)
138{
139 if (IS_NOT_NULL(r->history_root)) {
140 history_tree_free(r->history_root);
141 r->history_root = (OnigCaptureTreeNode* )0;
142 }
143}
144
145static OnigCaptureTreeNode*
146history_node_new(void)
147{
148 OnigCaptureTreeNode* node;
149
150 node = (OnigCaptureTreeNode* )xmalloc(sizeof(OnigCaptureTreeNode));
151 CHECK_NULL_RETURN(node);
152 node->childs = (OnigCaptureTreeNode** )0;
153 node->allocated = 0;
154 node->num_childs = 0;
155 node->group = -1;
156 node->beg = ONIG_REGION_NOTPOS;
157 node->end = ONIG_REGION_NOTPOS;
158
159 return node;
160}
161
162static int
163history_tree_add_child(OnigCaptureTreeNode* parent, OnigCaptureTreeNode* child)
164{
165# define HISTORY_TREE_INIT_ALLOC_SIZE 8
166
167 if (parent->num_childs >= parent->allocated) {
168 int n, i;
169
170 if (IS_NULL(parent->childs)) {
171 n = HISTORY_TREE_INIT_ALLOC_SIZE;
172 parent->childs =
173 (OnigCaptureTreeNode** )xmalloc(sizeof(OnigCaptureTreeNode*) * n);
174 CHECK_NULL_RETURN_MEMERR(parent->childs);
175 }
176 else {
177 OnigCaptureTreeNode** tmp;
178 n = parent->allocated * 2;
179 tmp =
180 (OnigCaptureTreeNode** )xrealloc(parent->childs,
181 sizeof(OnigCaptureTreeNode*) * n);
182 if (tmp == 0) {
183 history_tree_clear(parent);
184 return ONIGERR_MEMORY;
185 }
186 parent->childs = tmp;
187 }
188 for (i = parent->allocated; i < n; i++) {
189 parent->childs[i] = (OnigCaptureTreeNode* )0;
190 }
191 parent->allocated = n;
192 }
193
194 parent->childs[parent->num_childs] = child;
195 parent->num_childs++;
196 return 0;
197}
198
199static OnigCaptureTreeNode*
200history_tree_clone(OnigCaptureTreeNode* node)
201{
202 int i, r;
203 OnigCaptureTreeNode *clone, *child;
204
205 clone = history_node_new();
206 CHECK_NULL_RETURN(clone);
207
208 clone->beg = node->beg;
209 clone->end = node->end;
210 for (i = 0; i < node->num_childs; i++) {
211 child = history_tree_clone(node->childs[i]);
212 if (IS_NULL(child)) {
213 history_tree_free(clone);
214 return (OnigCaptureTreeNode* )0;
215 }
216 r = history_tree_add_child(clone, child);
217 if (r != 0) {
218 history_tree_free(child);
219 history_tree_free(clone);
220 return (OnigCaptureTreeNode* )0;
221 }
222 }
223
224 return clone;
225}
226
227extern OnigCaptureTreeNode*
228onig_get_capture_tree(OnigRegion* region)
229{
230 return region->history_root;
231}
232#endif /* USE_CAPTURE_HISTORY */
233
234#ifdef USE_MATCH_CACHE
235
236/*
237Glossary for "match cache"
238
239"match cache" or "match cache optimization"
240The `Regexp#match` optimization by using a cache.
241
242"cache opcode"
243A cachable opcode (e.g. `OP_PUSH`, `OP_REPEAT`, etc).
244It is corresponding to some cache points.
245
246"cache point"
247A cachable point on matching.
248Usually, one-to-one corresponding between a cache opcode and a cache point exists,
249but cache opcodes between `OP_REPEAT` and `OP_REPEAT_INC` have some corresponding
250cache points depending on repetition counts.
251
252"match cache point"
253A pair of a cache point and a position on an input string.
254We encode a match cache point to an integer value by the following equation:
255"match cache point" = "position on input string" * "total number of cache points" + "cache point"
256
257"match cache buffer"
258A bit-array for memoizing (recording) match cache points once backtracked.
259*/
260
261/* count the total number of cache opcodes for allocating a match cache buffer. */
262static OnigPosition
263count_num_cache_opcodes(const regex_t* reg, long* num_cache_opcodes_ptr)
264{
265 UChar* p = reg->p;
266 UChar* pend = p + reg->used;
267 LengthType len;
268 MemNumType repeat_mem;
269 OnigEncoding enc = reg->enc;
270 MemNumType current_repeat_mem = -1;
271 long num_cache_opcodes = 0;
272 int lookaround_nesting = 0;
273
274 while (p < pend) {
275 switch (*p++) {
276 case OP_FINISH:
277 case OP_END:
278 break;
279
280 case OP_EXACT1: p++; break;
281 case OP_EXACT2: p += 2; break;
282 case OP_EXACT3: p += 3; break;
283 case OP_EXACT4: p += 4; break;
284 case OP_EXACT5: p += 5; break;
285 case OP_EXACTN:
286 GET_LENGTH_INC(len, p); p += len; break;
287 case OP_EXACTMB2N1: p += 2; break;
288 case OP_EXACTMB2N2: p += 4; break;
289 case OP_EXACTMB2N3: p += 6; break;
290 case OP_EXACTMB2N:
291 GET_LENGTH_INC(len, p); p += len * 2; break;
292 case OP_EXACTMB3N:
293 GET_LENGTH_INC(len, p); p += len * 3; break;
294 case OP_EXACTMBN:
295 {
296 int mb_len;
297 GET_LENGTH_INC(mb_len, p);
298 GET_LENGTH_INC(len, p);
299 p += mb_len * len;
300 }
301 break;
302
303 case OP_EXACT1_IC:
304 len = enclen(enc, p, pend); p += len; break;
305 case OP_EXACTN_IC:
306 GET_LENGTH_INC(len, p); p += len; break;
307
308 case OP_CCLASS:
309 case OP_CCLASS_NOT:
310 p += SIZE_BITSET; break;
311 case OP_CCLASS_MB:
312 case OP_CCLASS_MB_NOT:
313 GET_LENGTH_INC(len, p); p += len; break;
314 case OP_CCLASS_MIX:
315 case OP_CCLASS_MIX_NOT:
316 p += SIZE_BITSET;
317 GET_LENGTH_INC(len, p);
318 p += len;
319 break;
320
321 case OP_ANYCHAR:
322 case OP_ANYCHAR_ML:
323 break;
324 case OP_ANYCHAR_STAR:
325 case OP_ANYCHAR_ML_STAR:
326 num_cache_opcodes++; break;
327 case OP_ANYCHAR_STAR_PEEK_NEXT:
328 case OP_ANYCHAR_ML_STAR_PEEK_NEXT:
329 p++; num_cache_opcodes++; break;
330
331 case OP_WORD:
332 case OP_NOT_WORD:
333 case OP_WORD_BOUND:
334 case OP_NOT_WORD_BOUND:
335 case OP_WORD_BEGIN:
336 case OP_WORD_END:
337 break;
338
339 case OP_ASCII_WORD:
340 case OP_NOT_ASCII_WORD:
341 case OP_ASCII_WORD_BOUND:
342 case OP_NOT_ASCII_WORD_BOUND:
343 case OP_ASCII_WORD_BEGIN:
344 case OP_ASCII_WORD_END:
345 break;
346
347 case OP_BEGIN_BUF:
348 case OP_END_BUF:
349 case OP_BEGIN_LINE:
350 case OP_END_LINE:
351 case OP_SEMI_END_BUF:
352 case OP_BEGIN_POSITION:
353 break;
354
355 case OP_BACKREF1:
356 case OP_BACKREF2:
357 case OP_BACKREFN:
358 case OP_BACKREFN_IC:
359 case OP_BACKREF_MULTI:
360 case OP_BACKREF_MULTI_IC:
361 case OP_BACKREF_WITH_LEVEL:
362 goto impossible;
363
364 case OP_MEMORY_START:
365 case OP_MEMORY_START_PUSH:
366 case OP_MEMORY_END_PUSH:
367 case OP_MEMORY_END_PUSH_REC:
368 case OP_MEMORY_END:
369 case OP_MEMORY_END_REC:
370 p += SIZE_MEMNUM;
371 // A memory (capture) in look-around is found.
372 if (lookaround_nesting != 0) {
373 goto impossible;
374 }
375 break;
376
377 case OP_KEEP:
378 break;
379
380 case OP_FAIL:
381 break;
382 case OP_JUMP:
383 p += SIZE_RELADDR;
384 break;
385 case OP_PUSH:
386 p += SIZE_RELADDR;
387 num_cache_opcodes++;
388 break;
389 case OP_POP:
390 break;
391 case OP_PUSH_OR_JUMP_EXACT1:
392 case OP_PUSH_IF_PEEK_NEXT:
393 p += SIZE_RELADDR + 1; num_cache_opcodes++; break;
394 case OP_REPEAT:
395 case OP_REPEAT_NG:
396 if (current_repeat_mem != -1) {
397 // A nested OP_REPEAT is not yet supported.
398 goto impossible;
399 }
400 GET_MEMNUM_INC(repeat_mem, p);
401 p += SIZE_RELADDR;
402 if (reg->repeat_range[repeat_mem].lower == 0) {
403 num_cache_opcodes++;
404 }
405 current_repeat_mem = repeat_mem;
406 break;
407 case OP_REPEAT_INC:
408 case OP_REPEAT_INC_NG:
409 GET_MEMNUM_INC(repeat_mem, p);
410 if (repeat_mem != current_repeat_mem) {
411 // A lone or invalid OP_REPEAT_INC is found.
412 goto impossible;
413 }
414 {
415 OnigRepeatRange *repeat_range = &reg->repeat_range[repeat_mem];
416 if (repeat_range->lower < repeat_range->upper) {
417 num_cache_opcodes++;
418 }
419 current_repeat_mem = -1;
420 }
421 break;
422 case OP_REPEAT_INC_SG:
423 case OP_REPEAT_INC_NG_SG:
424 goto impossible;
425 case OP_NULL_CHECK_START:
426 p += SIZE_MEMNUM;
427 break;
428 case OP_NULL_CHECK_END:
429 case OP_NULL_CHECK_END_MEMST_PUSH:
430 p += SIZE_MEMNUM;
431 break;
432 case OP_NULL_CHECK_END_MEMST:
433 p += SIZE_MEMNUM;
434 break;
435
436 case OP_PUSH_POS:
437 if (lookaround_nesting < 0) {
438 // A look-around nested in a atomic grouping is found.
439 goto impossible;
440 }
441 lookaround_nesting++;
442 break;
443 case OP_PUSH_POS_NOT:
444 if (lookaround_nesting < 0) {
445 // A look-around nested in a atomic grouping is found.
446 goto impossible;
447 }
448 p += SIZE_RELADDR;
449 lookaround_nesting++;
450 break;
451 case OP_PUSH_LOOK_BEHIND_NOT:
452 if (lookaround_nesting < 0) {
453 // A look-around nested in a atomic grouping is found.
454 goto impossible;
455 }
456 p += SIZE_RELADDR;
457 p += SIZE_LENGTH;
458 lookaround_nesting++;
459 break;
460 case OP_POP_POS:
461 case OP_FAIL_POS:
462 case OP_FAIL_LOOK_BEHIND_NOT:
463 lookaround_nesting--;
464 break;
465 case OP_PUSH_STOP_BT:
466 if (lookaround_nesting != 0) {
467 // A nested atomic grouping is found.
468 goto impossible;
469 }
470 lookaround_nesting++;
471 lookaround_nesting *= -1;
472 break;
473 case OP_POP_STOP_BT:
474 lookaround_nesting *= -1;
475 lookaround_nesting--;
476 break;
477 case OP_LOOK_BEHIND:
478 p += SIZE_LENGTH;
479 break;
480
481 case OP_PUSH_ABSENT_POS:
482 case OP_ABSENT_END:
483 case OP_ABSENT:
484 goto impossible;
485
486 case OP_CALL:
487 case OP_RETURN:
488 goto impossible;
489
490 case OP_CONDITION:
491 goto impossible;
492
493 case OP_STATE_CHECK_PUSH:
494 case OP_STATE_CHECK_PUSH_OR_JUMP:
495 case OP_STATE_CHECK:
496 case OP_STATE_CHECK_ANYCHAR_STAR:
497 case OP_STATE_CHECK_ANYCHAR_ML_STAR:
498 goto impossible;
499
500 case OP_SET_OPTION_PUSH:
501 case OP_SET_OPTION:
502 p += SIZE_OPTION;
503 break;
504
505 default:
506 goto bytecode_error;
507 }
508 }
509
510 *num_cache_opcodes_ptr = num_cache_opcodes;
511 return 0;
512
513impossible:
514 *num_cache_opcodes_ptr = NUM_CACHE_OPCODES_IMPOSSIBLE;
515 return 0;
516
517bytecode_error:
518 return ONIGERR_UNDEFINED_BYTECODE;
519}
520
521/* collect cache opcodes from the given regex program, and compute the total number of cache points. */
522static OnigPosition
523init_cache_opcodes(const regex_t* reg, OnigCacheOpcode* cache_opcodes, long* num_cache_points_ptr)
524{
525 UChar* pbegin;
526 UChar* p = reg->p;
527 UChar* pend = p + reg->used;
528 LengthType len;
529 MemNumType repeat_mem;
530 OnigEncoding enc = reg->enc;
531 MemNumType current_repeat_mem = -1;
532 long cache_point = 0;
533 long num_cache_points_at_repeat = 0;
534 int lookaround_nesting = 0;
535 const OnigCacheOpcode* cache_opcodes_begin = cache_opcodes;
536 OnigCacheOpcode* cache_opcodes_at_repeat = NULL;
537
538# define INC_CACHE_OPCODES do {\
539 cache_opcodes->addr = pbegin;\
540 cache_opcodes->cache_point = cache_point - num_cache_points_at_repeat;\
541 cache_opcodes->outer_repeat_mem = current_repeat_mem;\
542 cache_opcodes->num_cache_points_at_outer_repeat = num_cache_points_at_repeat;\
543 cache_opcodes->num_cache_points_in_outer_repeat = 0;\
544 cache_opcodes->lookaround_nesting = lookaround_nesting;\
545 cache_point += lookaround_nesting > 0 ? 2 : 1;\
546 cache_opcodes++;\
547 } while (0)
548
549# define INC_LOOKAROUND_NESTING lookaround_nesting++
550# define DEC_LOOKAROUND_NESTING do {\
551 UChar* match_addr = p - 1;\
552 OnigCacheOpcode* cache_opcodes_in_lookaround = cache_opcodes - 1;\
553 while (\
554 cache_opcodes_in_lookaround >= cache_opcodes_begin &&\
555 cache_opcodes_in_lookaround->lookaround_nesting == lookaround_nesting\
556 ) {\
557 cache_opcodes_in_lookaround->match_addr = match_addr;\
558 cache_opcodes_in_lookaround--;\
559 }\
560 lookaround_nesting--;\
561 } while (0)
562
563 while (p < pend) {
564 pbegin = p;
565 switch (*p++) {
566 case OP_FINISH:
567 case OP_END:
568 break;
569
570 case OP_EXACT1: p++; break;
571 case OP_EXACT2: p += 2; break;
572 case OP_EXACT3: p += 3; break;
573 case OP_EXACT4: p += 4; break;
574 case OP_EXACT5: p += 5; break;
575 case OP_EXACTN:
576 GET_LENGTH_INC(len, p); p += len; break;
577 case OP_EXACTMB2N1: p += 2; break;
578 case OP_EXACTMB2N2: p += 4; break;
579 case OP_EXACTMB2N3: p += 6; break;
580 case OP_EXACTMB2N:
581 GET_LENGTH_INC(len, p); p += len * 2; break;
582 case OP_EXACTMB3N:
583 GET_LENGTH_INC(len, p); p += len * 3; break;
584 case OP_EXACTMBN:
585 {
586 int mb_len;
587 GET_LENGTH_INC(mb_len, p);
588 GET_LENGTH_INC(len, p);
589 p += mb_len * len;
590 }
591 break;
592
593 case OP_EXACT1_IC:
594 len = enclen(enc, p, pend); p += len; break;
595 case OP_EXACTN_IC:
596 GET_LENGTH_INC(len, p); p += len; break;
597
598 case OP_CCLASS:
599 case OP_CCLASS_NOT:
600 p += SIZE_BITSET; break;
601 case OP_CCLASS_MB:
602 case OP_CCLASS_MB_NOT:
603 GET_LENGTH_INC(len, p); p += len; break;
604 case OP_CCLASS_MIX:
605 case OP_CCLASS_MIX_NOT:
606 p += SIZE_BITSET;
607 GET_LENGTH_INC(len, p);
608 p += len;
609 break;
610
611 case OP_ANYCHAR:
612 case OP_ANYCHAR_ML:
613 break;
614 case OP_ANYCHAR_STAR:
615 case OP_ANYCHAR_ML_STAR:
616 INC_CACHE_OPCODES;
617 break;
618 case OP_ANYCHAR_STAR_PEEK_NEXT:
619 case OP_ANYCHAR_ML_STAR_PEEK_NEXT:
620 p++;
621 INC_CACHE_OPCODES;
622 break;
623
624 case OP_WORD:
625 case OP_NOT_WORD:
626 case OP_WORD_BOUND:
627 case OP_NOT_WORD_BOUND:
628 case OP_WORD_BEGIN:
629 case OP_WORD_END:
630 break;
631
632 case OP_ASCII_WORD:
633 case OP_NOT_ASCII_WORD:
634 case OP_ASCII_WORD_BOUND:
635 case OP_NOT_ASCII_WORD_BOUND:
636 case OP_ASCII_WORD_BEGIN:
637 case OP_ASCII_WORD_END:
638 break;
639
640 case OP_BEGIN_BUF:
641 case OP_END_BUF:
642 case OP_BEGIN_LINE:
643 case OP_END_LINE:
644 case OP_SEMI_END_BUF:
645 case OP_BEGIN_POSITION:
646 break;
647
648 case OP_BACKREF1:
649 case OP_BACKREF2:
650 case OP_BACKREFN:
651 case OP_BACKREFN_IC:
652 case OP_BACKREF_MULTI:
653 case OP_BACKREF_MULTI_IC:
654 case OP_BACKREF_WITH_LEVEL:
655 goto unexpected_bytecode_error;
656
657 case OP_MEMORY_START:
658 case OP_MEMORY_START_PUSH:
659 case OP_MEMORY_END_PUSH:
660 case OP_MEMORY_END_PUSH_REC:
661 case OP_MEMORY_END:
662 case OP_MEMORY_END_REC:
663 p += SIZE_MEMNUM;
664 if (lookaround_nesting != 0) {
665 goto unexpected_bytecode_error;
666 }
667 break;
668
669 case OP_KEEP:
670 break;
671
672 case OP_FAIL:
673 break;
674 case OP_JUMP:
675 p += SIZE_RELADDR;
676 break;
677 case OP_PUSH:
678 p += SIZE_RELADDR;
679 INC_CACHE_OPCODES;
680 break;
681 case OP_POP:
682 break;
683 case OP_PUSH_OR_JUMP_EXACT1:
684 case OP_PUSH_IF_PEEK_NEXT:
685 p += SIZE_RELADDR + 1;
686 INC_CACHE_OPCODES;
687 break;
688 case OP_REPEAT:
689 case OP_REPEAT_NG:
690 GET_MEMNUM_INC(repeat_mem, p);
691 p += SIZE_RELADDR;
692 if (reg->repeat_range[repeat_mem].lower == 0) {
693 INC_CACHE_OPCODES;
694 }
695 current_repeat_mem = repeat_mem;
696 num_cache_points_at_repeat = cache_point;
697 cache_opcodes_at_repeat = cache_opcodes;
698 break;
699 case OP_REPEAT_INC:
700 case OP_REPEAT_INC_NG:
701 GET_MEMNUM_INC(repeat_mem, p);
702 {
703 long num_cache_points_in_repeat = cache_point - num_cache_points_at_repeat;
704 OnigRepeatRange *repeat_range = &reg->repeat_range[repeat_mem];
705 if (repeat_range->lower < repeat_range->upper) {
706 INC_CACHE_OPCODES;
707 cache_point--;
708 }
709 cache_point -= num_cache_points_in_repeat;
710 int repeat_bounds = repeat_range->upper == 0x7fffffff ? 1 : repeat_range->upper - repeat_range->lower;
711 cache_point += num_cache_points_in_repeat * repeat_range->lower + (num_cache_points_in_repeat + 1) * repeat_bounds;
712 OnigCacheOpcode* cache_opcodes_in_repeat = cache_opcodes - 1;
713 while (cache_opcodes_at_repeat <= cache_opcodes_in_repeat) {
714 cache_opcodes_in_repeat->num_cache_points_in_outer_repeat = num_cache_points_in_repeat;
715 cache_opcodes_in_repeat--;
716 }
717 current_repeat_mem = -1;
718 num_cache_points_at_repeat = 0;
719 cache_opcodes_at_repeat = NULL;
720 }
721 break;
722 case OP_REPEAT_INC_SG:
723 case OP_REPEAT_INC_NG_SG:
724 goto unexpected_bytecode_error;
725 case OP_NULL_CHECK_START:
726 p += SIZE_MEMNUM;
727 break;
728 case OP_NULL_CHECK_END:
729 case OP_NULL_CHECK_END_MEMST_PUSH:
730 p += SIZE_MEMNUM;
731 break;
732 case OP_NULL_CHECK_END_MEMST:
733 p += SIZE_MEMNUM;
734 break;
735
736 case OP_PUSH_POS:
737 INC_LOOKAROUND_NESTING;
738 break;
739 case OP_PUSH_POS_NOT:
740 p += SIZE_RELADDR;
741 INC_LOOKAROUND_NESTING;
742 break;
743 case OP_PUSH_LOOK_BEHIND_NOT:
744 p += SIZE_RELADDR;
745 p += SIZE_LENGTH;
746 INC_LOOKAROUND_NESTING;
747 break;
748 case OP_POP_POS:
749 case OP_FAIL_POS:
750 case OP_FAIL_LOOK_BEHIND_NOT:
751 DEC_LOOKAROUND_NESTING;
752 break;
753 case OP_PUSH_STOP_BT:
754 INC_LOOKAROUND_NESTING;
755 lookaround_nesting *= -1;
756 break;
757 case OP_POP_STOP_BT:
758 lookaround_nesting *= -1;
759 DEC_LOOKAROUND_NESTING;
760 break;
761 case OP_LOOK_BEHIND:
762 p += SIZE_LENGTH;
763 break;
764
765 case OP_ABSENT_END:
766 case OP_ABSENT:
767 goto unexpected_bytecode_error;
768
769 case OP_CALL:
770 case OP_RETURN:
771 goto unexpected_bytecode_error;
772
773 case OP_CONDITION:
774 goto unexpected_bytecode_error;
775
776 case OP_STATE_CHECK_PUSH:
777 case OP_STATE_CHECK_PUSH_OR_JUMP:
778 case OP_STATE_CHECK:
779 case OP_STATE_CHECK_ANYCHAR_STAR:
780 case OP_STATE_CHECK_ANYCHAR_ML_STAR:
781 goto unexpected_bytecode_error;
782
783 case OP_SET_OPTION_PUSH:
784 case OP_SET_OPTION:
785 p += SIZE_OPTION;
786 break;
787
788 default:
789 goto bytecode_error;
790 }
791 }
792
793 *num_cache_points_ptr = cache_point;
794 return 0;
795
796unexpected_bytecode_error:
797 return ONIGERR_UNEXPECTED_BYTECODE;
798
799bytecode_error:
800 return ONIGERR_UNDEFINED_BYTECODE;
801}
802#else
803static OnigPosition
804count_num_cache_opcodes(regex_t* reg, long* num_cache_opcodes)
805{
806 *num_cache_opcodes = NUM_CACHE_OPCODES_IMPOSSIBLE;
807 return 0;
808}
809#endif /* USE_MATCH_CACHE */
810
811extern int
812onig_check_linear_time(OnigRegexType* reg)
813{
814 long num_cache_opcodes = 0;
815 count_num_cache_opcodes(reg, &num_cache_opcodes);
816 return num_cache_opcodes != NUM_CACHE_OPCODES_IMPOSSIBLE;
817}
818
819extern void
820onig_region_clear(OnigRegion* region)
821{
822 int i;
823
824 for (i = 0; i < region->num_regs; i++) {
825 region->beg[i] = region->end[i] = ONIG_REGION_NOTPOS;
826 }
827#ifdef USE_CAPTURE_HISTORY
828 history_root_free(region);
829#endif
830}
831
832extern int
833onig_region_resize(OnigRegion* region, int n)
834{
835 region->num_regs = n;
836
837 if (n < ONIG_NREGION)
838 n = ONIG_NREGION;
839
840 if (region->allocated == 0) {
841 region->beg = (OnigPosition* )xmalloc(n * sizeof(OnigPosition));
842 if (region->beg == 0)
843 return ONIGERR_MEMORY;
844
845 region->end = (OnigPosition* )xmalloc(n * sizeof(OnigPosition));
846 if (region->end == 0) {
847 xfree(region->beg);
848 return ONIGERR_MEMORY;
849 }
850
851 region->allocated = n;
852 }
853 else if (region->allocated < n) {
854 OnigPosition *tmp;
855
856 region->allocated = 0;
857 tmp = (OnigPosition* )xrealloc(region->beg, n * sizeof(OnigPosition));
858 if (tmp == 0) {
859 xfree(region->beg);
860 xfree(region->end);
861 return ONIGERR_MEMORY;
862 }
863 region->beg = tmp;
864 tmp = (OnigPosition* )xrealloc(region->end, n * sizeof(OnigPosition));
865 if (tmp == 0) {
866 xfree(region->beg);
867 xfree(region->end);
868 return ONIGERR_MEMORY;
869 }
870 region->end = tmp;
871
872 region->allocated = n;
873 }
874
875 return 0;
876}
877
878static int
879onig_region_resize_clear(OnigRegion* region, int n)
880{
881 int r;
882
883 r = onig_region_resize(region, n);
884 if (r != 0) return r;
885 onig_region_clear(region);
886 return 0;
887}
888
889extern int
890onig_region_set(OnigRegion* region, int at, int beg, int end)
891{
892 if (at < 0) return ONIGERR_INVALID_ARGUMENT;
893
894 if (at >= region->allocated) {
895 int r = onig_region_resize(region, at + 1);
896 if (r < 0) return r;
897 }
898
899 region->beg[at] = beg;
900 region->end[at] = end;
901 return 0;
902}
903
904extern void
905onig_region_init(OnigRegion* region)
906{
907 region->num_regs = 0;
908 region->allocated = 0;
909 region->beg = (OnigPosition* )0;
910 region->end = (OnigPosition* )0;
911#ifdef USE_CAPTURE_HISTORY
912 region->history_root = (OnigCaptureTreeNode* )0;
913#endif
914}
915
916extern OnigRegion*
917onig_region_new(void)
918{
919 OnigRegion* r;
920
921 r = (OnigRegion* )xmalloc(sizeof(OnigRegion));
922 if (r)
923 onig_region_init(r);
924 return r;
925}
926
927extern void
928onig_region_free(OnigRegion* r, int free_self)
929{
930 if (r) {
931 if (r->allocated > 0) {
932 xfree(r->beg);
933 xfree(r->end);
934 }
935#ifdef USE_CAPTURE_HISTORY
936 history_root_free(r);
937#endif
938 if (free_self) {
939 xfree(r);
940 }
941 else {
942 memset(r, 0, sizeof(OnigRegion));
943 }
944 }
945}
946
947extern void
948onig_region_copy(OnigRegion* to, const OnigRegion* from)
949{
950#define RREGC_SIZE (sizeof(int) * from->num_regs)
951 int i, r;
952
953 if (to == from) return;
954
955 r = onig_region_resize(to, from->num_regs);
956 if (r) return;
957
958 for (i = 0; i < from->num_regs; i++) {
959 to->beg[i] = from->beg[i];
960 to->end[i] = from->end[i];
961 }
962 to->num_regs = from->num_regs;
963
964#ifdef USE_CAPTURE_HISTORY
965 history_root_free(to);
966
967 if (IS_NOT_NULL(from->history_root)) {
968 to->history_root = history_tree_clone(from->history_root);
969 }
970#endif
971}
972
973
975#define INVALID_STACK_INDEX -1
976
977/* stack type */
978/* used by normal-POP */
979#define STK_ALT 0x0001
980#define STK_LOOK_BEHIND_NOT 0x0002
981#define STK_POS_NOT 0x0003
982/* handled by normal-POP */
983#define STK_MEM_START 0x0100
984#define STK_MEM_END 0x8200
985#define STK_REPEAT_INC 0x0300
986#define STK_STATE_CHECK_MARK 0x1000
987/* avoided by normal-POP */
988#define STK_NULL_CHECK_START 0x3000
989#define STK_NULL_CHECK_END 0x5000 /* for recursive call */
990#define STK_MEM_END_MARK 0x8400
991#define STK_POS 0x0500 /* used when POP-POS */
992#define STK_STOP_BT 0x0600 /* mark for "(?>...)" */
993#define STK_REPEAT 0x0700
994#define STK_CALL_FRAME 0x0800
995#define STK_RETURN 0x0900
996#define STK_VOID 0x0a00 /* for fill a blank */
997#define STK_ABSENT_POS 0x0b00 /* for absent */
998#define STK_ABSENT 0x0c00 /* absent inner loop marker */
999#define STK_MATCH_CACHE_POINT 0x0d00 /* for the match cache optimization */
1000#define STK_ATOMIC_MATCH_CACHE_POINT 0x0e00
1001
1002/* stack type check mask */
1003#define STK_MASK_POP_USED 0x00ff
1004#define STK_MASK_TO_VOID_TARGET 0x10ff
1005#define STK_MASK_MEM_END_OR_MARK 0x8000 /* MEM_END or MEM_END_MARK */
1006
1007#ifdef USE_MATCH_CACHE
1008#define MATCH_ARG_INIT_MATCH_CACHE(msa) do {\
1009 (msa).match_cache_status = MATCH_CACHE_STATUS_UNINIT;\
1010 (msa).num_fails = 0;\
1011 (msa).num_cache_opcodes = NUM_CACHE_OPCODES_UNINIT;\
1012 (msa).cache_opcodes = (OnigCacheOpcode*)NULL;\
1013 (msa).num_cache_points = 0;\
1014 (msa).match_cache_buf = (uint8_t*)NULL;\
1015} while(0)
1016#define MATCH_ARG_FREE_MATCH_CACHE(msa) do {\
1017 xfree((msa).cache_opcodes);\
1018 xfree((msa).match_cache_buf);\
1019 (msa).cache_opcodes = (OnigCacheOpcode*)NULL;\
1020 (msa).match_cache_buf = (uint8_t*)NULL;\
1021} while(0)
1022#else
1023#define MATCH_ARG_INIT_MATCH_CACHE(msa)
1024#define MATCH_ARG_FREE_MATCH_CACHE(msa)
1025#endif
1026
1027#ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE
1028# define MATCH_ARG_INIT(msa, arg_option, arg_region, arg_start, arg_gpos) do {\
1029 (msa).stack_p = (void* )0;\
1030 (msa).options = (arg_option);\
1031 (msa).region = (arg_region);\
1032 (msa).start = (arg_start);\
1033 (msa).gpos = (arg_gpos);\
1034 (msa).best_len = ONIG_MISMATCH;\
1035 (msa).counter = 0;\
1036 (msa).end_time = 0;\
1037 MATCH_ARG_INIT_MATCH_CACHE(msa);\
1038} while(0)
1039#else
1040# define MATCH_ARG_INIT(msa, arg_option, arg_region, arg_start, arg_gpos) do {\
1041 (msa).stack_p = (void* )0;\
1042 (msa).options = (arg_option);\
1043 (msa).region = (arg_region);\
1044 (msa).start = (arg_start);\
1045 (msa).gpos = (arg_gpos);\
1046 (msa).counter = 0;\
1047 (msa).end_time = 0;\
1048 MATCH_ARG_INIT_MATCH_CACHE(msa);\
1049} while(0)
1050#endif
1051
1052#ifdef USE_COMBINATION_EXPLOSION_CHECK
1053
1054# define STATE_CHECK_BUFF_MALLOC_THRESHOLD_SIZE 16
1055
1056# define STATE_CHECK_BUFF_INIT(msa, str_len, offset, state_num) do { \
1057 if ((state_num) > 0 && str_len >= STATE_CHECK_STRING_THRESHOLD_LEN) {\
1058 unsigned int size = (unsigned int )(((str_len) + 1) * (state_num) + 7) >> 3;\
1059 offset = ((offset) * (state_num)) >> 3;\
1060 if (size > 0 && offset < size && size < STATE_CHECK_BUFF_MAX_SIZE) {\
1061 if (size >= STATE_CHECK_BUFF_MALLOC_THRESHOLD_SIZE) {\
1062 (msa).state_check_buff = (void* )xmalloc(size);\
1063 CHECK_NULL_RETURN_MEMERR((msa).state_check_buff);\
1064 }\
1065 else \
1066 (msa).state_check_buff = (void* )xalloca(size);\
1067 xmemset(((char* )((msa).state_check_buff)+(offset)), 0, \
1068 (size_t )(size - (offset))); \
1069 (msa).state_check_buff_size = size;\
1070 }\
1071 else {\
1072 (msa).state_check_buff = (void* )0;\
1073 (msa).state_check_buff_size = 0;\
1074 }\
1075 }\
1076 else {\
1077 (msa).state_check_buff = (void* )0;\
1078 (msa).state_check_buff_size = 0;\
1079 }\
1080 } while(0)
1081
1082# define MATCH_ARG_FREE(msa) do {\
1083 xfree((msa).stack_p);\
1084 if ((msa).state_check_buff_size >= STATE_CHECK_BUFF_MALLOC_THRESHOLD_SIZE) { \
1085 xfree((msa).state_check_buff);\
1086 }\
1087 MATCH_ARG_FREE_MATCH_CACHE(msa);\
1088} while(0)
1089#else /* USE_COMBINATION_EXPLOSION_CHECK */
1090# define MATCH_ARG_FREE(msa) do {\
1091 xfree((msa).stack_p);\
1092 MATCH_ARG_FREE_MATCH_CACHE(msa);\
1093} while (0)
1094#endif /* USE_COMBINATION_EXPLOSION_CHECK */
1095
1096
1097
1098#define MAX_PTR_NUM 100
1099
1100#define STACK_INIT(alloc_addr, heap_addr, ptr_num, stack_num) do {\
1101 if (ptr_num > MAX_PTR_NUM) {\
1102 alloc_addr = (char* )xmalloc(sizeof(OnigStackIndex) * (ptr_num));\
1103 heap_addr = alloc_addr;\
1104 if (msa->stack_p) {\
1105 stk_alloc = (OnigStackType* )(msa->stack_p);\
1106 stk_base = stk_alloc;\
1107 stk = stk_base;\
1108 stk_end = stk_base + msa->stack_n;\
1109 } else {\
1110 stk_alloc = (OnigStackType* )xalloca(sizeof(OnigStackType) * (stack_num));\
1111 stk_base = stk_alloc;\
1112 stk = stk_base;\
1113 stk_end = stk_base + (stack_num);\
1114 }\
1115 } else if (msa->stack_p) {\
1116 alloc_addr = (char* )xalloca(sizeof(OnigStackIndex) * (ptr_num));\
1117 heap_addr = NULL;\
1118 stk_alloc = (OnigStackType* )(msa->stack_p);\
1119 stk_base = stk_alloc;\
1120 stk = stk_base;\
1121 stk_end = stk_base + msa->stack_n;\
1122 }\
1123 else {\
1124 alloc_addr = (char* )xalloca(sizeof(OnigStackIndex) * (ptr_num)\
1125 + sizeof(OnigStackType) * (stack_num));\
1126 heap_addr = NULL;\
1127 stk_alloc = (OnigStackType* )(alloc_addr + sizeof(OnigStackIndex) * (ptr_num));\
1128 stk_base = stk_alloc;\
1129 stk = stk_base;\
1130 stk_end = stk_base + (stack_num);\
1131 }\
1132} while(0)
1133
1134#define STACK_SAVE do{\
1135 if (stk_base != stk_alloc) {\
1136 msa->stack_p = stk_base;\
1137 msa->stack_n = stk_end - stk_base; /* TODO: check overflow */\
1138 };\
1139} while(0)
1140
1141static unsigned int MatchStackLimitSize = DEFAULT_MATCH_STACK_LIMIT_SIZE;
1142
1143extern unsigned int
1144onig_get_match_stack_limit_size(void)
1145{
1146 return MatchStackLimitSize;
1147}
1148
1149extern int
1150onig_set_match_stack_limit_size(unsigned int size)
1151{
1152 MatchStackLimitSize = size;
1153 return 0;
1154}
1155
1156static int
1157stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
1158 OnigStackType** arg_stk, OnigStackType* stk_alloc, OnigMatchArg* msa)
1159{
1160 size_t n;
1161 OnigStackType *x, *stk_base, *stk_end, *stk;
1162
1163 stk_base = *arg_stk_base;
1164 stk_end = *arg_stk_end;
1165 stk = *arg_stk;
1166
1167 n = stk_end - stk_base;
1168 if (stk_base == stk_alloc && IS_NULL(msa->stack_p)) {
1169 x = (OnigStackType* )xmalloc(sizeof(OnigStackType) * n * 2);
1170 if (IS_NULL(x)) {
1171 STACK_SAVE;
1172 return ONIGERR_MEMORY;
1173 }
1174 xmemcpy(x, stk_base, n * sizeof(OnigStackType));
1175 n *= 2;
1176 }
1177 else {
1178 unsigned int limit_size = MatchStackLimitSize;
1179 n *= 2;
1180 if (limit_size != 0 && n > limit_size) {
1181 if ((unsigned int )(stk_end - stk_base) == limit_size)
1182 return ONIGERR_MATCH_STACK_LIMIT_OVER;
1183 else
1184 n = limit_size;
1185 }
1186 x = (OnigStackType* )xrealloc(stk_base, sizeof(OnigStackType) * n);
1187 if (IS_NULL(x)) {
1188 STACK_SAVE;
1189 return ONIGERR_MEMORY;
1190 }
1191 }
1192 *arg_stk = x + (stk - stk_base);
1193 *arg_stk_base = x;
1194 *arg_stk_end = x + n;
1195 return 0;
1196}
1197
1198#define STACK_ENSURE(n) do {\
1199 if (stk_end - stk < (n)) {\
1200 int r = stack_double(&stk_base, &stk_end, &stk, stk_alloc, msa);\
1201 if (r != 0) {\
1202 STACK_SAVE;\
1203 xfree(xmalloc_base);\
1204 return r;\
1205 }\
1206 }\
1207} while(0)
1208
1209#define STACK_AT(index) (stk_base + (index))
1210#define GET_STACK_INDEX(stk) ((stk) - stk_base)
1211
1212#define STACK_PUSH_TYPE(stack_type) do {\
1213 STACK_ENSURE(1);\
1214 stk->type = (stack_type);\
1215 stk->null_check = stk == stk_base ? 0 : (stk-1)->null_check;\
1216 STACK_INC;\
1217} while(0)
1218
1219#define IS_TO_VOID_TARGET(stk) (((stk)->type & STK_MASK_TO_VOID_TARGET) != 0)
1220
1221#ifdef USE_COMBINATION_EXPLOSION_CHECK
1222# define STATE_CHECK_POS(s,snum) \
1223 (((s) - str) * num_comb_exp_check + ((snum) - 1))
1224# define STATE_CHECK_VAL(v,snum) do {\
1225 if (state_check_buff != NULL) {\
1226 ptrdiff_t x = STATE_CHECK_POS(s,snum);\
1227 (v) = state_check_buff[x/8] & (1<<(x%8));\
1228 }\
1229 else (v) = 0;\
1230} while(0)
1231
1232
1233# define ELSE_IF_STATE_CHECK_MARK(stk) \
1234 else if ((stk)->type == STK_STATE_CHECK_MARK) { \
1235 ptrdiff_t x = STATE_CHECK_POS(stk->u.state.pstr, stk->u.state.state_check);\
1236 state_check_buff[x/8] |= (1<<(x%8)); \
1237 }
1238
1239# define STACK_PUSH(stack_type,pat,s,sprev,keep) do {\
1240 STACK_ENSURE(1);\
1241 stk->type = (stack_type);\
1242 stk->u.state.pcode = (pat);\
1243 stk->u.state.pstr = (s);\
1244 stk->u.state.pstr_prev = (sprev);\
1245 stk->u.state.state_check = 0;\
1246 stk->u.state.pkeep = (keep);\
1247 STACK_INC;\
1248} while(0)
1249
1250# define STACK_PUSH_ENSURED(stack_type,pat) do {\
1251 stk->type = (stack_type);\
1252 stk->u.state.pcode = (pat);\
1253 stk->u.state.state_check = 0;\
1254 STACK_INC;\
1255} while(0)
1256
1257# define STACK_PUSH_ALT_WITH_STATE_CHECK(pat,s,sprev,snum,keep) do {\
1258 STACK_ENSURE(1);\
1259 stk->type = STK_ALT;\
1260 stk->u.state.pcode = (pat);\
1261 stk->u.state.pstr = (s);\
1262 stk->u.state.pstr_prev = (sprev);\
1263 stk->u.state.state_check = ((state_check_buff != NULL) ? (snum) : 0);\
1264 stk->u.state.pkeep = (keep);\
1265 STACK_INC;\
1266} while(0)
1267
1268# define STACK_PUSH_STATE_CHECK(s,snum) do {\
1269 if (state_check_buff != NULL) {\
1270 STACK_ENSURE(1);\
1271 stk->type = STK_STATE_CHECK_MARK;\
1272 stk->u.state.pstr = (s);\
1273 stk->u.state.state_check = (snum);\
1274 STACK_INC;\
1275 }\
1276} while(0)
1277
1278#else /* USE_COMBINATION_EXPLOSION_CHECK */
1279
1280# define ELSE_IF_STATE_CHECK_MARK(stk)
1281
1282# define STACK_PUSH(stack_type,pat,s,sprev,keep) do {\
1283 STACK_ENSURE(1);\
1284 stk->type = (stack_type);\
1285 stk->null_check = stk == stk_base ? 0 : (stk-1)->null_check;\
1286 stk->u.state.pcode = (pat);\
1287 stk->u.state.pstr = (s);\
1288 stk->u.state.pstr_prev = (sprev);\
1289 stk->u.state.pkeep = (keep);\
1290 STACK_INC;\
1291} while(0)
1292
1293# define STACK_PUSH_ENSURED(stack_type,pat) do {\
1294 stk->type = (stack_type);\
1295 stk->null_check = stk == stk_base ? 0 : (stk-1)->null_check;\
1296 stk->u.state.pcode = (pat);\
1297 STACK_INC;\
1298} while(0)
1299#endif /* USE_COMBINATION_EXPLOSION_CHECK */
1300
1301#define STACK_PUSH_ALT(pat,s,sprev,keep) STACK_PUSH(STK_ALT,pat,s,sprev,keep)
1302#define STACK_PUSH_POS(s,sprev,keep) STACK_PUSH(STK_POS,NULL_UCHARP,s,sprev,keep)
1303#define STACK_PUSH_POS_NOT(pat,s,sprev,keep) STACK_PUSH(STK_POS_NOT,pat,s,sprev,keep)
1304#define STACK_PUSH_ABSENT STACK_PUSH_TYPE(STK_ABSENT)
1305#define STACK_PUSH_STOP_BT STACK_PUSH_TYPE(STK_STOP_BT)
1306#define STACK_PUSH_LOOK_BEHIND_NOT(pat,s,sprev,keep) \
1307 STACK_PUSH(STK_LOOK_BEHIND_NOT,pat,s,sprev,keep)
1308
1309#define STACK_PUSH_REPEAT(id, pat) do {\
1310 STACK_ENSURE(1);\
1311 stk->type = STK_REPEAT;\
1312 stk->null_check = stk == stk_base ? 0 : (stk-1)->null_check;\
1313 stk->u.repeat.num = (id);\
1314 stk->u.repeat.pcode = (pat);\
1315 stk->u.repeat.count = 0;\
1316 STACK_INC;\
1317} while(0)
1318
1319#define STACK_PUSH_REPEAT_INC(sindex) do {\
1320 STACK_ENSURE(1);\
1321 stk->type = STK_REPEAT_INC;\
1322 stk->null_check = stk == stk_base ? 0 : (stk-1)->null_check;\
1323 stk->u.repeat_inc.si = (sindex);\
1324 STACK_INC;\
1325} while(0)
1326
1327#define STACK_PUSH_MEM_START(mnum, s) do {\
1328 STACK_ENSURE(1);\
1329 stk->type = STK_MEM_START;\
1330 stk->null_check = stk == stk_base ? 0 : (stk-1)->null_check;\
1331 stk->u.mem.num = (mnum);\
1332 stk->u.mem.pstr = (s);\
1333 stk->u.mem.start = mem_start_stk[mnum];\
1334 stk->u.mem.end = mem_end_stk[mnum];\
1335 mem_start_stk[mnum] = GET_STACK_INDEX(stk);\
1336 mem_end_stk[mnum] = INVALID_STACK_INDEX;\
1337 STACK_INC;\
1338} while(0)
1339
1340#define STACK_PUSH_MEM_END(mnum, s) do {\
1341 STACK_ENSURE(1);\
1342 stk->type = STK_MEM_END;\
1343 stk->null_check = stk == stk_base ? 0 : (stk-1)->null_check;\
1344 stk->u.mem.num = (mnum);\
1345 stk->u.mem.pstr = (s);\
1346 stk->u.mem.start = mem_start_stk[mnum];\
1347 stk->u.mem.end = mem_end_stk[mnum];\
1348 mem_end_stk[mnum] = GET_STACK_INDEX(stk);\
1349 STACK_INC;\
1350} while(0)
1351
1352#define STACK_PUSH_MEM_END_MARK(mnum) do {\
1353 STACK_ENSURE(1);\
1354 stk->type = STK_MEM_END_MARK;\
1355 stk->null_check = stk == stk_base ? 0 : (stk-1)->null_check;\
1356 stk->u.mem.num = (mnum);\
1357 STACK_INC;\
1358} while(0)
1359
1360#define STACK_GET_MEM_START(mnum, k) do {\
1361 int level = 0;\
1362 k = stk;\
1363 while (k > stk_base) {\
1364 k--;\
1365 if ((k->type & STK_MASK_MEM_END_OR_MARK) != 0 \
1366 && k->u.mem.num == (mnum)) {\
1367 level++;\
1368 }\
1369 else if (k->type == STK_MEM_START && k->u.mem.num == (mnum)) {\
1370 if (level == 0) break;\
1371 level--;\
1372 }\
1373 }\
1374} while(0)
1375
1376#define STACK_GET_MEM_RANGE(k, mnum, start, end) do {\
1377 int level = 0;\
1378 while (k < stk) {\
1379 if (k->type == STK_MEM_START && k->u.mem.num == (mnum)) {\
1380 if (level == 0) (start) = k->u.mem.pstr;\
1381 level++;\
1382 }\
1383 else if (k->type == STK_MEM_END && k->u.mem.num == (mnum)) {\
1384 level--;\
1385 if (level == 0) {\
1386 (end) = k->u.mem.pstr;\
1387 break;\
1388 }\
1389 }\
1390 k++;\
1391 }\
1392} while(0)
1393
1394#define STACK_PUSH_NULL_CHECK_START(cnum, s) do {\
1395 STACK_ENSURE(1);\
1396 stk->type = STK_NULL_CHECK_START;\
1397 stk->null_check = (OnigStackIndex)(stk - stk_base);\
1398 stk->u.null_check.num = (cnum);\
1399 stk->u.null_check.pstr = (s);\
1400 STACK_INC;\
1401} while(0)
1402
1403#define STACK_PUSH_NULL_CHECK_END(cnum) do {\
1404 STACK_ENSURE(1);\
1405 stk->type = STK_NULL_CHECK_END;\
1406 stk->null_check = (OnigStackIndex)(stk - stk_base);\
1407 stk->u.null_check.num = (cnum);\
1408 STACK_INC;\
1409} while(0)
1410
1411#define STACK_PUSH_CALL_FRAME(pat) do {\
1412 STACK_ENSURE(1);\
1413 stk->type = STK_CALL_FRAME;\
1414 stk->null_check = stk == stk_base ? 0 : (stk-1)->null_check;\
1415 stk->u.call_frame.ret_addr = (pat);\
1416 STACK_INC;\
1417} while(0)
1418
1419#define STACK_PUSH_RETURN do {\
1420 STACK_ENSURE(1);\
1421 stk->type = STK_RETURN;\
1422 stk->null_check = stk == stk_base ? 0 : (stk-1)->null_check;\
1423 STACK_INC;\
1424} while(0)
1425
1426#define STACK_PUSH_ABSENT_POS(start, end) do {\
1427 STACK_ENSURE(1);\
1428 stk->type = STK_ABSENT_POS;\
1429 stk->null_check = stk == stk_base ? 0 : (stk-1)->null_check;\
1430 stk->u.absent_pos.abs_pstr = (start);\
1431 stk->u.absent_pos.end_pstr = (end);\
1432 STACK_INC;\
1433} while(0)
1434
1435#define STACK_PUSH_MATCH_CACHE_POINT(match_cache_point_index, match_cache_point_mask) do {\
1436 STACK_ENSURE(1);\
1437 stk->type = STK_MATCH_CACHE_POINT;\
1438 stk->null_check = stk == stk_base ? 0 : (stk-1)->null_check;\
1439 stk->u.match_cache_point.index = (match_cache_point_index);\
1440 stk->u.match_cache_point.mask = (match_cache_point_mask);\
1441 STACK_INC;\
1442} while(0)
1443
1444
1445#ifdef ONIG_DEBUG
1446# define STACK_BASE_CHECK(p, at) \
1447 if ((p) < stk_base) {\
1448 fprintf(stderr, "at %s\n", at);\
1449 goto stack_error;\
1450 }
1451#else
1452# define STACK_BASE_CHECK(p, at)
1453#endif
1454
1455#ifdef ONIG_DEBUG_MATCH_CACHE
1456# define MATCH_CACHE_DEBUG_MEMOIZE(stkp) fprintf(stderr, "MATCH CACHE: memoize (index=%ld mask=%d)\n", stkp->u.match_cache_point.index, stkp->u.match_cache_point.mask);
1457#else
1458# define MATCH_CACHE_DEBUG_MEMOIZE(stkp) ((void) 0)
1459#endif
1460
1461#ifdef USE_MATCH_CACHE
1462# define INC_NUM_FAILS msa->num_fails++
1463# define MEMOIZE_MATCH_CACHE_POINT do {\
1464 if (stk->type == STK_MATCH_CACHE_POINT) {\
1465 msa->match_cache_buf[stk->u.match_cache_point.index] |= stk->u.match_cache_point.mask;\
1466 MATCH_CACHE_DEBUG_MEMOIZE(stk);\
1467 } else if (stk->type == STK_ATOMIC_MATCH_CACHE_POINT) {\
1468 memoize_extended_match_cache_point(msa->match_cache_buf, stk->u.match_cache_point.index, stk->u.match_cache_point.mask);\
1469 MATCH_CACHE_DEBUG_MEMOIZE(stkp);\
1470 }\
1471 } while(0)
1472# define MEMOIZE_LOOKAROUND_MATCH_CACHE_POINT(stkp) do {\
1473 if (stkp->type == STK_MATCH_CACHE_POINT) {\
1474 stkp->type = STK_VOID;\
1475 memoize_extended_match_cache_point(msa->match_cache_buf, stkp->u.match_cache_point.index, stkp->u.match_cache_point.mask);\
1476 MATCH_CACHE_DEBUG_MEMOIZE(stkp);\
1477 }\
1478 } while(0)
1479# define MEMOIZE_ATOMIC_MATCH_CACHE_POINT do {\
1480 if (stk->type == STK_MATCH_CACHE_POINT) {\
1481 memoize_extended_match_cache_point(msa->match_cache_buf, stk->u.match_cache_point.index, stk->u.match_cache_point.mask);\
1482 MATCH_CACHE_DEBUG_MEMOIZE(stkp);\
1483 }\
1484 } while(0)
1485#else
1486# define INC_NUM_FAILS ((void) 0)
1487# define MEMOIZE_MATCH_CACHE_POINT ((void) 0)
1488# define MEMOIZE_LOOKAROUND_MATCH_CACHE_POINT ((void) 0)
1489#endif
1490
1491#define STACK_POP_ONE do {\
1492 stk--;\
1493 STACK_BASE_CHECK(stk, "STACK_POP_ONE"); \
1494} while(0)
1495
1496#define STACK_POP do {\
1497 switch (pop_level) {\
1498 case STACK_POP_LEVEL_FREE:\
1499 while (1) {\
1500 stk--;\
1501 STACK_BASE_CHECK(stk, "STACK_POP"); \
1502 if ((stk->type & STK_MASK_POP_USED) != 0) break;\
1503 ELSE_IF_STATE_CHECK_MARK(stk);\
1504 MEMOIZE_MATCH_CACHE_POINT;\
1505 }\
1506 break;\
1507 case STACK_POP_LEVEL_MEM_START:\
1508 while (1) {\
1509 stk--;\
1510 STACK_BASE_CHECK(stk, "STACK_POP 2"); \
1511 if ((stk->type & STK_MASK_POP_USED) != 0) break;\
1512 else if (stk->type == STK_MEM_START) {\
1513 mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\
1514 mem_end_stk[stk->u.mem.num] = stk->u.mem.end;\
1515 }\
1516 ELSE_IF_STATE_CHECK_MARK(stk);\
1517 MEMOIZE_MATCH_CACHE_POINT;\
1518 }\
1519 break;\
1520 default:\
1521 while (1) {\
1522 stk--;\
1523 STACK_BASE_CHECK(stk, "STACK_POP 3"); \
1524 if ((stk->type & STK_MASK_POP_USED) != 0) break;\
1525 else if (stk->type == STK_MEM_START) {\
1526 mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\
1527 mem_end_stk[stk->u.mem.num] = stk->u.mem.end;\
1528 }\
1529 else if (stk->type == STK_REPEAT_INC) {\
1530 STACK_AT(stk->u.repeat_inc.si)->u.repeat.count--;\
1531 }\
1532 else if (stk->type == STK_MEM_END) {\
1533 mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\
1534 mem_end_stk[stk->u.mem.num] = stk->u.mem.end;\
1535 }\
1536 ELSE_IF_STATE_CHECK_MARK(stk);\
1537 MEMOIZE_MATCH_CACHE_POINT;\
1538 }\
1539 break;\
1540 }\
1541} while(0)
1542
1543#define STACK_POP_TIL_POS_NOT do {\
1544 while (1) {\
1545 stk--;\
1546 STACK_BASE_CHECK(stk, "STACK_POP_TIL_POS_NOT"); \
1547 if (stk->type == STK_POS_NOT) break;\
1548 else if (stk->type == STK_MEM_START) {\
1549 mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\
1550 mem_end_stk[stk->u.mem.num] = stk->u.mem.end;\
1551 }\
1552 else if (stk->type == STK_REPEAT_INC) {\
1553 STACK_AT(stk->u.repeat_inc.si)->u.repeat.count--;\
1554 }\
1555 else if (stk->type == STK_MEM_END) {\
1556 mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\
1557 mem_end_stk[stk->u.mem.num] = stk->u.mem.end;\
1558 }\
1559 else if (IS_TO_VOID_TARGET(stk)) {\
1560 INC_NUM_FAILS;\
1561 }\
1562 ELSE_IF_STATE_CHECK_MARK(stk);\
1563 MEMOIZE_LOOKAROUND_MATCH_CACHE_POINT(stk);\
1564 }\
1565} while(0)
1566
1567#define STACK_POP_TIL_LOOK_BEHIND_NOT do {\
1568 while (1) {\
1569 stk--;\
1570 STACK_BASE_CHECK(stk, "STACK_POP_TIL_LOOK_BEHIND_NOT"); \
1571 if (stk->type == STK_LOOK_BEHIND_NOT) break;\
1572 else if (stk->type == STK_MEM_START) {\
1573 mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\
1574 mem_end_stk[stk->u.mem.num] = stk->u.mem.end;\
1575 }\
1576 else if (stk->type == STK_REPEAT_INC) {\
1577 STACK_AT(stk->u.repeat_inc.si)->u.repeat.count--;\
1578 }\
1579 else if (stk->type == STK_MEM_END) {\
1580 mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\
1581 mem_end_stk[stk->u.mem.num] = stk->u.mem.end;\
1582 }\
1583 ELSE_IF_STATE_CHECK_MARK(stk);\
1584 }\
1585} while(0)
1586
1587#define STACK_POP_TIL_ABSENT do {\
1588 while (1) {\
1589 stk--;\
1590 STACK_BASE_CHECK(stk, "STACK_POP_TIL_ABSENT"); \
1591 if (stk->type == STK_ABSENT) break;\
1592 else if (stk->type == STK_MEM_START) {\
1593 mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\
1594 mem_end_stk[stk->u.mem.num] = stk->u.mem.end;\
1595 }\
1596 else if (stk->type == STK_REPEAT_INC) {\
1597 STACK_AT(stk->u.repeat_inc.si)->u.repeat.count--;\
1598 }\
1599 else if (stk->type == STK_MEM_END) {\
1600 mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\
1601 mem_end_stk[stk->u.mem.num] = stk->u.mem.end;\
1602 }\
1603 ELSE_IF_STATE_CHECK_MARK(stk);\
1604 }\
1605} while(0)
1606
1607#define STACK_POP_ABSENT_POS(start, end) do {\
1608 stk--;\
1609 STACK_BASE_CHECK(stk, "STACK_POP_ABSENT_POS"); \
1610 (start) = stk->u.absent_pos.abs_pstr;\
1611 (end) = stk->u.absent_pos.end_pstr;\
1612} while(0)
1613
1614#define STACK_POS_END(k) do {\
1615 k = stk;\
1616 while (1) {\
1617 k--;\
1618 STACK_BASE_CHECK(k, "STACK_POS_END"); \
1619 if (IS_TO_VOID_TARGET(k)) {\
1620 INC_NUM_FAILS;\
1621 k->type = STK_VOID;\
1622 }\
1623 else if (k->type == STK_POS) {\
1624 k->type = STK_VOID;\
1625 break;\
1626 }\
1627 MEMOIZE_LOOKAROUND_MATCH_CACHE_POINT(k);\
1628 }\
1629} while(0)
1630
1631#define STACK_STOP_BT_END do {\
1632 OnigStackType *k = stk;\
1633 while (1) {\
1634 k--;\
1635 STACK_BASE_CHECK(k, "STACK_STOP_BT_END"); \
1636 if (IS_TO_VOID_TARGET(k)) {\
1637 INC_NUM_FAILS;\
1638 k->type = STK_VOID;\
1639 }\
1640 else if (k->type == STK_STOP_BT) {\
1641 k->type = STK_VOID;\
1642 break;\
1643 }\
1644 else if (k->type == STK_MATCH_CACHE_POINT) {\
1645 k->type = STK_ATOMIC_MATCH_CACHE_POINT;\
1646 }\
1647 }\
1648} while(0)
1649
1650#define STACK_STOP_BT_FAIL do {\
1651 while (1) {\
1652 stk--;\
1653 STACK_BASE_CHECK(stk, "STACK_STOP_BT_END"); \
1654 if (stk->type == STK_STOP_BT) {\
1655 stk->type = STK_VOID;\
1656 break;\
1657 }\
1658 MEMOIZE_ATOMIC_MATCH_CACHE_POINT;\
1659 }\
1660} while(0)
1661
1662#define STACK_NULL_CHECK(isnull,id,s) do {\
1663 OnigStackType* k = STACK_AT((stk-1)->null_check)+1;\
1664 while (1) {\
1665 k--;\
1666 STACK_BASE_CHECK(k, "STACK_NULL_CHECK"); \
1667 if (k->type == STK_NULL_CHECK_START) {\
1668 if (k->u.null_check.num == (id)) {\
1669 (isnull) = (k->u.null_check.pstr == (s));\
1670 break;\
1671 }\
1672 }\
1673 }\
1674} while(0)
1675
1676#define STACK_NULL_CHECK_REC(isnull,id,s) do {\
1677 int level = 0;\
1678 OnigStackType* k = STACK_AT((stk-1)->null_check)+1;\
1679 while (1) {\
1680 k--;\
1681 STACK_BASE_CHECK(k, "STACK_NULL_CHECK_REC"); \
1682 if (k->type == STK_NULL_CHECK_START) {\
1683 if (k->u.null_check.num == (id)) {\
1684 if (level == 0) {\
1685 (isnull) = (k->u.null_check.pstr == (s));\
1686 break;\
1687 }\
1688 else level--;\
1689 }\
1690 }\
1691 else if (k->type == STK_NULL_CHECK_END) {\
1692 level++;\
1693 }\
1694 }\
1695} while(0)
1696
1697#define STACK_NULL_CHECK_MEMST(isnull,id,s,reg) do {\
1698 OnigStackType* k = STACK_AT((stk-1)->null_check)+1;\
1699 while (1) {\
1700 k--;\
1701 STACK_BASE_CHECK(k, "STACK_NULL_CHECK_MEMST"); \
1702 if (k->type == STK_NULL_CHECK_START) {\
1703 if (k->u.null_check.num == (id)) {\
1704 if (k->u.null_check.pstr != (s)) {\
1705 (isnull) = 0;\
1706 break;\
1707 }\
1708 else {\
1709 UChar* endp;\
1710 (isnull) = 1;\
1711 while (k < stk) {\
1712 if (k->type == STK_MEM_START) {\
1713 if (k->u.mem.end == INVALID_STACK_INDEX) {\
1714 (isnull) = 0; break;\
1715 }\
1716 if (BIT_STATUS_AT(reg->bt_mem_end, k->u.mem.num))\
1717 endp = STACK_AT(k->u.mem.end)->u.mem.pstr;\
1718 else\
1719 endp = (UChar* )k->u.mem.end;\
1720 if (STACK_AT(k->u.mem.start)->u.mem.pstr != endp) {\
1721 (isnull) = 0; break;\
1722 }\
1723 else if (endp != s) {\
1724 (isnull) = -1; /* empty, but position changed */ \
1725 }\
1726 }\
1727 k++;\
1728 }\
1729 break;\
1730 }\
1731 }\
1732 }\
1733 }\
1734} while(0)
1735
1736#define STACK_NULL_CHECK_MEMST_REC(isnull,id,s,reg) do {\
1737 int level = 0;\
1738 OnigStackType* k = STACK_AT((stk-1)->null_check)+1;\
1739 while (1) {\
1740 k--;\
1741 STACK_BASE_CHECK(k, "STACK_NULL_CHECK_MEMST_REC"); \
1742 if (k->type == STK_NULL_CHECK_START) {\
1743 if (k->u.null_check.num == (id)) {\
1744 if (level == 0) {\
1745 if (k->u.null_check.pstr != (s)) {\
1746 (isnull) = 0;\
1747 break;\
1748 }\
1749 else {\
1750 UChar* endp;\
1751 (isnull) = 1;\
1752 while (k < stk) {\
1753 if (k->type == STK_MEM_START) {\
1754 if (k->u.mem.end == INVALID_STACK_INDEX) {\
1755 (isnull) = 0; break;\
1756 }\
1757 if (BIT_STATUS_AT(reg->bt_mem_end, k->u.mem.num))\
1758 endp = STACK_AT(k->u.mem.end)->u.mem.pstr;\
1759 else\
1760 endp = (UChar* )k->u.mem.end;\
1761 if (STACK_AT(k->u.mem.start)->u.mem.pstr != endp) {\
1762 (isnull) = 0; break;\
1763 }\
1764 else if (endp != s) {\
1765 (isnull) = -1; /* empty, but position changed */ \
1766 }\
1767 }\
1768 k++;\
1769 }\
1770 break;\
1771 }\
1772 }\
1773 else {\
1774 level--;\
1775 }\
1776 }\
1777 }\
1778 else if (k->type == STK_NULL_CHECK_END) {\
1779 if (k->u.null_check.num == (id)) level++;\
1780 }\
1781 }\
1782} while(0)
1783
1784#define STACK_GET_REPEAT(id, k) do {\
1785 int level = 0;\
1786 k = stk;\
1787 while (1) {\
1788 k--;\
1789 STACK_BASE_CHECK(k, "STACK_GET_REPEAT"); \
1790 if (k->type == STK_REPEAT) {\
1791 if (level == 0) {\
1792 if (k->u.repeat.num == (id)) {\
1793 break;\
1794 }\
1795 }\
1796 }\
1797 else if (k->type == STK_CALL_FRAME) level--;\
1798 else if (k->type == STK_RETURN) level++;\
1799 }\
1800} while(0)
1801
1802#define STACK_RETURN(addr) do {\
1803 int level = 0;\
1804 OnigStackType* k = stk;\
1805 while (1) {\
1806 k--;\
1807 STACK_BASE_CHECK(k, "STACK_RETURN"); \
1808 if (k->type == STK_CALL_FRAME) {\
1809 if (level == 0) {\
1810 (addr) = k->u.call_frame.ret_addr;\
1811 break;\
1812 }\
1813 else level--;\
1814 }\
1815 else if (k->type == STK_RETURN)\
1816 level++;\
1817 }\
1818} while(0)
1819
1820
1821#define STRING_CMP(s1,s2,len) do {\
1822 while (len-- > 0) {\
1823 if (*s1++ != *s2++) goto fail;\
1824 }\
1825} while(0)
1826
1827#define STRING_CMP_IC(case_fold_flag,s1,ps2,len,text_end) do {\
1828 if (string_cmp_ic(encode, case_fold_flag, s1, ps2, len, text_end) == 0) \
1829 goto fail; \
1830} while(0)
1831
1832static int string_cmp_ic(OnigEncoding enc, int case_fold_flag,
1833 UChar* s1, UChar** ps2, OnigDistance mblen, const UChar* text_end)
1834{
1835 UChar buf1[ONIGENC_MBC_CASE_FOLD_MAXLEN];
1836 UChar buf2[ONIGENC_MBC_CASE_FOLD_MAXLEN];
1837 UChar *p1, *p2, *end1, *s2;
1838 int len1, len2;
1839
1840 s2 = *ps2;
1841 end1 = s1 + mblen;
1842 while (s1 < end1) {
1843 len1 = ONIGENC_MBC_CASE_FOLD(enc, case_fold_flag, &s1, text_end, buf1);
1844 len2 = ONIGENC_MBC_CASE_FOLD(enc, case_fold_flag, &s2, text_end, buf2);
1845 if (len1 != len2) return 0;
1846 p1 = buf1;
1847 p2 = buf2;
1848 while (len1-- > 0) {
1849 if (*p1 != *p2) return 0;
1850 p1++;
1851 p2++;
1852 }
1853 }
1854
1855 *ps2 = s2;
1856 return 1;
1857}
1858
1859#define STRING_CMP_VALUE(s1,s2,len,is_fail) do {\
1860 is_fail = 0;\
1861 while (len-- > 0) {\
1862 if (*s1++ != *s2++) {\
1863 is_fail = 1; break;\
1864 }\
1865 }\
1866} while(0)
1867
1868#define STRING_CMP_VALUE_IC(case_fold_flag,s1,ps2,len,text_end,is_fail) do {\
1869 if (string_cmp_ic(encode, case_fold_flag, s1, ps2, len, text_end) == 0) \
1870 is_fail = 1; \
1871 else \
1872 is_fail = 0; \
1873} while(0)
1874
1875
1876#define IS_EMPTY_STR (str == end)
1877#define ON_STR_BEGIN(s) ((s) == str)
1878#define ON_STR_END(s) ((s) == end)
1879#ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE
1880# define DATA_ENSURE_CHECK1 (s < right_range)
1881# define DATA_ENSURE_CHECK(n) (s + (n) <= right_range)
1882# define DATA_ENSURE(n) if (s + (n) > right_range) goto fail
1883# define DATA_ENSURE_CONTINUE(n) if (s + (n) > right_range) continue
1884# define ABSENT_END_POS right_range
1885#else
1886# define DATA_ENSURE_CHECK1 (s < end)
1887# define DATA_ENSURE_CHECK(n) (s + (n) <= end)
1888# define DATA_ENSURE(n) if (s + (n) > end) goto fail
1889# define DATA_ENSURE_CONTINUE(n) if (s + (n) > end) continue
1890# define ABSENT_END_POS end
1891#endif /* USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE */
1892
1893
1894#ifdef USE_CAPTURE_HISTORY
1895static int
1896make_capture_history_tree(OnigCaptureTreeNode* node, OnigStackType** kp,
1897 OnigStackType* stk_top, UChar* str, regex_t* reg)
1898{
1899 int n, r;
1900 OnigCaptureTreeNode* child;
1901 OnigStackType* k = *kp;
1902
1903 while (k < stk_top) {
1904 if (k->type == STK_MEM_START) {
1905 n = k->u.mem.num;
1906 if (n <= ONIG_MAX_CAPTURE_HISTORY_GROUP &&
1907 BIT_STATUS_AT(reg->capture_history, n) != 0) {
1908 child = history_node_new();
1909 CHECK_NULL_RETURN_MEMERR(child);
1910 child->group = n;
1911 child->beg = k->u.mem.pstr - str;
1912 r = history_tree_add_child(node, child);
1913 if (r != 0) {
1914 history_tree_free(child);
1915 return r;
1916 }
1917 *kp = (k + 1);
1918 r = make_capture_history_tree(child, kp, stk_top, str, reg);
1919 if (r != 0) return r;
1920
1921 k = *kp;
1922 child->end = k->u.mem.pstr - str;
1923 }
1924 }
1925 else if (k->type == STK_MEM_END) {
1926 if (k->u.mem.num == node->group) {
1927 node->end = k->u.mem.pstr - str;
1928 *kp = k;
1929 return 0;
1930 }
1931 }
1932 k++;
1933 }
1934
1935 return 1; /* 1: root node ending. */
1936}
1937#endif /* USE_CAPTURE_HISTORY */
1938
1939#ifdef USE_BACKREF_WITH_LEVEL
1940static int
1941mem_is_in_memp(int mem, int num, UChar* memp)
1942{
1943 int i;
1944 MemNumType m;
1945
1946 for (i = 0; i < num; i++) {
1947 GET_MEMNUM_INC(m, memp);
1948 if (mem == (int )m) return 1;
1949 }
1950 return 0;
1951}
1952
1953static int backref_match_at_nested_level(regex_t* reg,
1954 OnigStackType* top, OnigStackType* stk_base,
1955 int ignore_case, int case_fold_flag,
1956 int nest, int mem_num, UChar* memp, UChar** s, const UChar* send)
1957{
1958 UChar *ss, *p, *pstart, *pend = NULL_UCHARP;
1959 int level;
1960 OnigStackType* k;
1961
1962 level = 0;
1963 k = top;
1964 k--;
1965 while (k >= stk_base) {
1966 if (k->type == STK_CALL_FRAME) {
1967 level--;
1968 }
1969 else if (k->type == STK_RETURN) {
1970 level++;
1971 }
1972 else if (level == nest) {
1973 if (k->type == STK_MEM_START) {
1974 if (mem_is_in_memp(k->u.mem.num, mem_num, memp)) {
1975 pstart = k->u.mem.pstr;
1976 if (pend != NULL_UCHARP) {
1977 if (pend - pstart > send - *s) return 0; /* or goto next_mem; */
1978 p = pstart;
1979 ss = *s;
1980
1981 if (ignore_case != 0) {
1982 if (string_cmp_ic(reg->enc, case_fold_flag,
1983 pstart, &ss, pend - pstart, send) == 0)
1984 return 0; /* or goto next_mem; */
1985 }
1986 else {
1987 while (p < pend) {
1988 if (*p++ != *ss++) return 0; /* or goto next_mem; */
1989 }
1990 }
1991
1992 *s = ss;
1993 return 1;
1994 }
1995 }
1996 }
1997 else if (k->type == STK_MEM_END) {
1998 if (mem_is_in_memp(k->u.mem.num, mem_num, memp)) {
1999 pend = k->u.mem.pstr;
2000 }
2001 }
2002 }
2003 k--;
2004 }
2005
2006 return 0;
2007}
2008#endif /* USE_BACKREF_WITH_LEVEL */
2009
2010
2011#ifdef ONIG_DEBUG_STATISTICS
2012
2013# ifdef _WIN32
2014# include <windows.h>
2015static LARGE_INTEGER ts, te, freq;
2016# define GETTIME(t) QueryPerformanceCounter(&(t))
2017# define TIMEDIFF(te,ts) (unsigned long )(((te).QuadPart - (ts).QuadPart) \
2018 * 1000000 / freq.QuadPart)
2019# else /* _WIN32 */
2020
2021# define USE_TIMEOFDAY
2022
2023# ifdef USE_TIMEOFDAY
2024# ifdef HAVE_SYS_TIME_H
2025# include <sys/time.h>
2026# endif
2027# ifdef HAVE_UNISTD_H
2028# include <unistd.h>
2029# endif
2030static struct timeval ts, te;
2031# define GETTIME(t) gettimeofday(&(t), (struct timezone* )0)
2032# define TIMEDIFF(te,ts) (((te).tv_usec - (ts).tv_usec) + \
2033 (((te).tv_sec - (ts).tv_sec)*1000000))
2034# else /* USE_TIMEOFDAY */
2035# ifdef HAVE_SYS_TIMES_H
2036# include <sys/times.h>
2037# endif
2038static struct tms ts, te;
2039# define GETTIME(t) times(&(t))
2040# define TIMEDIFF(te,ts) ((te).tms_utime - (ts).tms_utime)
2041# endif /* USE_TIMEOFDAY */
2042
2043# endif /* _WIN32 */
2044
2045static int OpCounter[256];
2046static int OpPrevCounter[256];
2047static unsigned long OpTime[256];
2048static int OpCurr = OP_FINISH;
2049static int OpPrevTarget = OP_FAIL;
2050static int MaxStackDepth = 0;
2051
2052# define MOP_IN(opcode) do {\
2053 if (opcode == OpPrevTarget) OpPrevCounter[OpCurr]++;\
2054 OpCurr = opcode;\
2055 OpCounter[opcode]++;\
2056 GETTIME(ts);\
2057} while(0)
2058
2059# define MOP_OUT do {\
2060 GETTIME(te);\
2061 OpTime[OpCurr] += TIMEDIFF(te, ts);\
2062} while(0)
2063
2064extern void
2065onig_statistics_init(void)
2066{
2067 int i;
2068 for (i = 0; i < 256; i++) {
2069 OpCounter[i] = OpPrevCounter[i] = 0; OpTime[i] = 0;
2070 }
2071 MaxStackDepth = 0;
2072# ifdef _WIN32
2073 QueryPerformanceFrequency(&freq);
2074# endif
2075}
2076
2077extern void
2078onig_print_statistics(FILE* f)
2079{
2080 int i;
2081 fprintf(f, " count prev time\n");
2082 for (i = 0; OnigOpInfo[i].opcode >= 0; i++) {
2083 fprintf(f, "%8d: %8d: %10lu: %s\n",
2084 OpCounter[i], OpPrevCounter[i], OpTime[i], OnigOpInfo[i].name);
2085 }
2086 fprintf(f, "\nmax stack depth: %d\n", MaxStackDepth);
2087}
2088
2089# define STACK_INC do {\
2090 stk++;\
2091 if (stk - stk_base > MaxStackDepth) \
2092 MaxStackDepth = stk - stk_base;\
2093} while(0)
2094
2095#else /* ONIG_DEBUG_STATISTICS */
2096# define STACK_INC stk++
2097
2098# define MOP_IN(opcode)
2099# define MOP_OUT
2100#endif /* ONIG_DEBUG_STATISTICS */
2101
2102
2103#ifdef ONIG_DEBUG_MATCH
2104static const char *
2105stack_type_str(int stack_type)
2106{
2107 switch (stack_type) {
2108 case STK_ALT: return "Alt ";
2109 case STK_LOOK_BEHIND_NOT: return "LBNot ";
2110 case STK_POS_NOT: return "PosNot";
2111 case STK_MEM_START: return "MemS ";
2112 case STK_MEM_END: return "MemE ";
2113 case STK_REPEAT_INC: return "RepInc";
2114 case STK_STATE_CHECK_MARK: return "StChMk";
2115 case STK_NULL_CHECK_START: return "NulChS";
2116 case STK_NULL_CHECK_END: return "NulChE";
2117 case STK_MEM_END_MARK: return "MemEMk";
2118 case STK_POS: return "Pos ";
2119 case STK_STOP_BT: return "StopBt";
2120 case STK_REPEAT: return "Rep ";
2121 case STK_CALL_FRAME: return "Call ";
2122 case STK_RETURN: return "Ret ";
2123 case STK_VOID: return "Void ";
2124 case STK_ABSENT_POS: return "AbsPos";
2125 case STK_ABSENT: return "Absent";
2126 case STK_MATCH_CACHE_POINT: return "MCache";
2127 default: return " ";
2128 }
2129}
2130#endif
2131#ifdef USE_MATCH_CACHE
2132
2133static long
2134bsearch_cache_opcodes(const OnigCacheOpcode *cache_opcodes, long num_cache_opcodes, const UChar* p)
2135{
2136 long l = 0, r = num_cache_opcodes - 1, m = 0;
2137
2138 while (l <= r) {
2139 m = (l + r) / 2;
2140 if (cache_opcodes[m].addr == p) break;
2141 if (cache_opcodes[m].addr < p) l = m + 1;
2142 else r = m - 1;
2143 }
2144 return m;
2145}
2146
2147static long
2148find_cache_point(regex_t* reg, const OnigCacheOpcode* cache_opcodes, long num_cache_opcodes, const UChar* p, const OnigStackType *stk, const OnigStackIndex *repeat_stk, const OnigCacheOpcode **cache_opcode_ptr)
2149{
2150 long m;
2151 const OnigCacheOpcode* cache_opcode;
2152 const OnigRepeatRange* range;
2153 const OnigStackType *stkp;
2154 int count = 0;
2155 int is_inc = *p == OP_REPEAT_INC || *p == OP_REPEAT_INC_NG;
2156 long cache_point;
2157 long num_cache_points_at_outer_repeat;
2158 long num_cache_points_in_outer_repeat;
2159
2160 m = bsearch_cache_opcodes(cache_opcodes, num_cache_opcodes, p);
2161
2162 if (!(0 <= m && m < num_cache_opcodes && cache_opcodes[m].addr == p)) {
2163 return -1;
2164 }
2165
2166 cache_opcode = &cache_opcodes[m];
2167 *cache_opcode_ptr = &cache_opcodes[m];
2168 cache_point = cache_opcode->cache_point;
2169 if (cache_opcode->outer_repeat_mem == -1) {
2170 return cache_point;
2171 }
2172
2173 num_cache_points_at_outer_repeat = cache_opcode->num_cache_points_at_outer_repeat;
2174 num_cache_points_in_outer_repeat = cache_opcode->num_cache_points_in_outer_repeat;
2175
2176 range = &reg->repeat_range[cache_opcode->outer_repeat_mem];
2177
2178 stkp = &stk[repeat_stk[cache_opcode->outer_repeat_mem]];
2179 count = is_inc ? stkp->u.repeat.count - 1 : stkp->u.repeat.count;
2180
2181 if (count < range->lower) {
2182 return num_cache_points_at_outer_repeat +
2183 num_cache_points_in_outer_repeat * count +
2184 cache_point;
2185 }
2186
2187 if (range->upper == 0x7fffffff) {
2188 return num_cache_points_at_outer_repeat +
2189 num_cache_points_in_outer_repeat * (range->lower - (is_inc ? 1 : 0)) + (is_inc ? 0 : 1) +
2190 cache_point;
2191 }
2192
2193 return num_cache_points_at_outer_repeat +
2194 num_cache_points_in_outer_repeat * (range->lower - 1) +
2195 (num_cache_points_in_outer_repeat + 1) * (count - range->lower + 1) +
2196 cache_point;
2197}
2198
2199static int check_extended_match_cache_point(uint8_t *match_cache_buf, long match_cache_point_index, uint8_t match_cache_point_mask) {
2200 if (match_cache_point_mask & 0x80) {
2201 return (match_cache_buf[match_cache_point_index + 1] & 0x01) > 0;
2202 } else {
2203 return (match_cache_buf[match_cache_point_index] & (match_cache_point_mask << 1)) > 0;
2204 }
2205}
2206
2207static void memoize_extended_match_cache_point(uint8_t *match_cache_buf, long match_cache_point_index, uint8_t match_cache_point_mask) {
2208 match_cache_buf[match_cache_point_index] |= match_cache_point_mask;
2209 if (match_cache_point_mask & 0x80) {
2210 match_cache_buf[match_cache_point_index + 1] |= 0x01;
2211 } else {
2212 match_cache_buf[match_cache_point_index] |= match_cache_point_mask << 1;
2213 }
2214}
2215
2216#endif /* USE_MATCH_CACHE */
2217
2218/* match data(str - end) from position (sstart). */
2219/* if sstart == str then set sprev to NULL. */
2220static OnigPosition
2221match_at(regex_t* reg, const UChar* str, const UChar* end,
2222#ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE
2223 const UChar* right_range,
2224#endif
2225 const UChar* sstart, UChar* sprev, OnigMatchArg* msa)
2226{
2227 static const UChar FinishCode[] = { OP_FINISH };
2228
2229 int i, num_mem, pop_level;
2230 ptrdiff_t n, best_len;
2231 LengthType tlen, tlen2;
2232 MemNumType mem;
2233 RelAddrType addr;
2234 OnigOptionType option = reg->options;
2235 OnigEncoding encode = reg->enc;
2236 OnigCaseFoldType case_fold_flag = reg->case_fold_flag;
2237 UChar *s, *q, *sbegin;
2238 UChar *p = reg->p;
2239 UChar *pbegin = p;
2240 UChar *pkeep;
2241 char *alloca_base;
2242 char *xmalloc_base = NULL;
2243 OnigStackType *stk_alloc, *stk_base, *stk, *stk_end;
2244 OnigStackType *stkp; /* used as any purpose. */
2245 OnigStackIndex si;
2246 OnigStackIndex *repeat_stk;
2247 OnigStackIndex *mem_start_stk, *mem_end_stk;
2248#ifdef USE_COMBINATION_EXPLOSION_CHECK
2249 int scv;
2250 unsigned char* state_check_buff = msa->state_check_buff;
2251 int num_comb_exp_check = reg->num_comb_exp_check;
2252#endif
2253
2254#if USE_TOKEN_THREADED_VM
2255# define OP_OFFSET 1
2256# define VM_LOOP JUMP;
2257# define VM_LOOP_END
2258# define CASE(x) L_##x: sbegin = s; OPCODE_EXEC_HOOK;
2259# define DEFAULT L_DEFAULT:
2260# define NEXT sprev = sbegin; JUMP
2261# define JUMP pbegin = p; RB_GNUC_EXTENSION_BLOCK(goto *oplabels[*p++])
2262
2263 RB_GNUC_EXTENSION static const void *oplabels[] = {
2264 &&L_OP_FINISH, /* matching process terminator (no more alternative) */
2265 &&L_OP_END, /* pattern code terminator (success end) */
2266
2267 &&L_OP_EXACT1, /* single byte, N = 1 */
2268 &&L_OP_EXACT2, /* single byte, N = 2 */
2269 &&L_OP_EXACT3, /* single byte, N = 3 */
2270 &&L_OP_EXACT4, /* single byte, N = 4 */
2271 &&L_OP_EXACT5, /* single byte, N = 5 */
2272 &&L_OP_EXACTN, /* single byte */
2273 &&L_OP_EXACTMB2N1, /* mb-length = 2 N = 1 */
2274 &&L_OP_EXACTMB2N2, /* mb-length = 2 N = 2 */
2275 &&L_OP_EXACTMB2N3, /* mb-length = 2 N = 3 */
2276 &&L_OP_EXACTMB2N, /* mb-length = 2 */
2277 &&L_OP_EXACTMB3N, /* mb-length = 3 */
2278 &&L_OP_EXACTMBN, /* other length */
2279
2280 &&L_OP_EXACT1_IC, /* single byte, N = 1, ignore case */
2281 &&L_OP_EXACTN_IC, /* single byte, ignore case */
2282
2283 &&L_OP_CCLASS,
2284 &&L_OP_CCLASS_MB,
2285 &&L_OP_CCLASS_MIX,
2286 &&L_OP_CCLASS_NOT,
2287 &&L_OP_CCLASS_MB_NOT,
2288 &&L_OP_CCLASS_MIX_NOT,
2289
2290 &&L_OP_ANYCHAR, /* "." */
2291 &&L_OP_ANYCHAR_ML, /* "." multi-line */
2292 &&L_OP_ANYCHAR_STAR, /* ".*" */
2293 &&L_OP_ANYCHAR_ML_STAR, /* ".*" multi-line */
2294 &&L_OP_ANYCHAR_STAR_PEEK_NEXT,
2295 &&L_OP_ANYCHAR_ML_STAR_PEEK_NEXT,
2296
2297 &&L_OP_WORD,
2298 &&L_OP_NOT_WORD,
2299 &&L_OP_WORD_BOUND,
2300 &&L_OP_NOT_WORD_BOUND,
2301# ifdef USE_WORD_BEGIN_END
2302 &&L_OP_WORD_BEGIN,
2303 &&L_OP_WORD_END,
2304# else
2305 &&L_DEFAULT,
2306 &&L_DEFAULT,
2307# endif
2308 &&L_OP_ASCII_WORD,
2309 &&L_OP_NOT_ASCII_WORD,
2310 &&L_OP_ASCII_WORD_BOUND,
2311 &&L_OP_NOT_ASCII_WORD_BOUND,
2312# ifdef USE_WORD_BEGIN_END
2313 &&L_OP_ASCII_WORD_BEGIN,
2314 &&L_OP_ASCII_WORD_END,
2315# else
2316 &&L_DEFAULT,
2317 &&L_DEFAULT,
2318# endif
2319
2320 &&L_OP_BEGIN_BUF,
2321 &&L_OP_END_BUF,
2322 &&L_OP_BEGIN_LINE,
2323 &&L_OP_END_LINE,
2324 &&L_OP_SEMI_END_BUF,
2325 &&L_OP_BEGIN_POSITION,
2326
2327 &&L_OP_BACKREF1,
2328 &&L_OP_BACKREF2,
2329 &&L_OP_BACKREFN,
2330 &&L_OP_BACKREFN_IC,
2331 &&L_OP_BACKREF_MULTI,
2332 &&L_OP_BACKREF_MULTI_IC,
2333# ifdef USE_BACKREF_WITH_LEVEL
2334 &&L_OP_BACKREF_WITH_LEVEL, /* \k<xxx+n>, \k<xxx-n> */
2335# else
2336 &&L_DEFAULT,
2337# endif
2338 &&L_OP_MEMORY_START,
2339 &&L_OP_MEMORY_START_PUSH, /* push back-tracker to stack */
2340 &&L_OP_MEMORY_END_PUSH, /* push back-tracker to stack */
2341# ifdef USE_SUBEXP_CALL
2342 &&L_OP_MEMORY_END_PUSH_REC, /* push back-tracker to stack */
2343# else
2344 &&L_DEFAULT,
2345# endif
2346 &&L_OP_MEMORY_END,
2347# ifdef USE_SUBEXP_CALL
2348 &&L_OP_MEMORY_END_REC, /* push marker to stack */
2349# else
2350 &&L_DEFAULT,
2351# endif
2352
2353 &&L_OP_KEEP,
2354
2355 &&L_OP_FAIL, /* pop stack and move */
2356 &&L_OP_JUMP,
2357 &&L_OP_PUSH,
2358 &&L_OP_POP,
2359# ifdef USE_OP_PUSH_OR_JUMP_EXACT
2360 &&L_OP_PUSH_OR_JUMP_EXACT1, /* if match exact then push, else jump. */
2361# else
2362 &&L_DEFAULT,
2363# endif
2364 &&L_OP_PUSH_IF_PEEK_NEXT, /* if match exact then push, else none. */
2365 &&L_OP_REPEAT, /* {n,m} */
2366 &&L_OP_REPEAT_NG, /* {n,m}? (non greedy) */
2367 &&L_OP_REPEAT_INC,
2368 &&L_OP_REPEAT_INC_NG, /* non greedy */
2369 &&L_OP_REPEAT_INC_SG, /* search and get in stack */
2370 &&L_OP_REPEAT_INC_NG_SG, /* search and get in stack (non greedy) */
2371 &&L_OP_NULL_CHECK_START, /* null loop checker start */
2372 &&L_OP_NULL_CHECK_END, /* null loop checker end */
2373# ifdef USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT
2374 &&L_OP_NULL_CHECK_END_MEMST, /* null loop checker end (with capture status) */
2375# else
2376 &&L_DEFAULT,
2377# endif
2378# ifdef USE_SUBEXP_CALL
2379 &&L_OP_NULL_CHECK_END_MEMST_PUSH, /* with capture status and push check-end */
2380# else
2381 &&L_DEFAULT,
2382# endif
2383
2384 &&L_OP_PUSH_POS, /* (?=...) start */
2385 &&L_OP_POP_POS, /* (?=...) end */
2386 &&L_OP_PUSH_POS_NOT, /* (?!...) start */
2387 &&L_OP_FAIL_POS, /* (?!...) end */
2388 &&L_OP_PUSH_STOP_BT, /* (?>...) start */
2389 &&L_OP_POP_STOP_BT, /* (?>...) end */
2390 &&L_OP_LOOK_BEHIND, /* (?<=...) start (no needs end opcode) */
2391 &&L_OP_PUSH_LOOK_BEHIND_NOT, /* (?<!...) start */
2392 &&L_OP_FAIL_LOOK_BEHIND_NOT, /* (?<!...) end */
2393 &&L_OP_PUSH_ABSENT_POS, /* (?~...) start */
2394 &&L_OP_ABSENT, /* (?~...) start of inner loop */
2395 &&L_OP_ABSENT_END, /* (?~...) end */
2396
2397# ifdef USE_SUBEXP_CALL
2398 &&L_OP_CALL, /* \g<name> */
2399 &&L_OP_RETURN,
2400# else
2401 &&L_DEFAULT,
2402 &&L_DEFAULT,
2403# endif
2404 &&L_OP_CONDITION,
2405
2406# ifdef USE_COMBINATION_EXPLOSION_CHECK
2407 &&L_OP_STATE_CHECK_PUSH, /* combination explosion check and push */
2408 &&L_OP_STATE_CHECK_PUSH_OR_JUMP, /* check ok -> push, else jump */
2409 &&L_OP_STATE_CHECK, /* check only */
2410# else
2411 &&L_DEFAULT,
2412 &&L_DEFAULT,
2413 &&L_DEFAULT,
2414# endif
2415# ifdef USE_COMBINATION_EXPLOSION_CHECK
2416 &&L_OP_STATE_CHECK_ANYCHAR_STAR,
2417 &&L_OP_STATE_CHECK_ANYCHAR_ML_STAR,
2418# else
2419 &&L_DEFAULT,
2420 &&L_DEFAULT,
2421# endif
2422 /* no need: IS_DYNAMIC_OPTION() == 0 */
2423# if 0 /* no need: IS_DYNAMIC_OPTION() == 0 */
2424 &&L_OP_SET_OPTION_PUSH, /* set option and push recover option */
2425 &&L_OP_SET_OPTION /* set option */
2426# else
2427 &&L_DEFAULT,
2428 &&L_DEFAULT
2429# endif
2430 };
2431#else /* USE_TOKEN_THREADED_VM */
2432
2433# define OP_OFFSET 0
2434# define VM_LOOP \
2435 while (1) { \
2436 OPCODE_EXEC_HOOK; \
2437 pbegin = p; \
2438 sbegin = s; \
2439 switch (*p++) {
2440# define VM_LOOP_END } sprev = sbegin; }
2441# define CASE(x) case x:
2442# define DEFAULT default:
2443# define NEXT break
2444# define JUMP continue; break
2445#endif /* USE_TOKEN_THREADED_VM */
2446
2447
2448#ifdef USE_SUBEXP_CALL
2449/* Stack #0 is used to store the pattern itself and used for (?R), \g<0>,
2450 etc. Additional space is required. */
2451# define ADD_NUMMEM 1
2452#else
2453/* Stack #0 not is used. */
2454# define ADD_NUMMEM 0
2455#endif
2456
2457 n = reg->num_repeat + (reg->num_mem + ADD_NUMMEM) * 2;
2458
2459 STACK_INIT(alloca_base, xmalloc_base, n, INIT_MATCH_STACK_SIZE);
2460 pop_level = reg->stack_pop_level;
2461 num_mem = reg->num_mem;
2462 repeat_stk = (OnigStackIndex* )alloca_base;
2463
2464 mem_start_stk = (OnigStackIndex* )(repeat_stk + reg->num_repeat);
2465 mem_end_stk = mem_start_stk + (num_mem + ADD_NUMMEM);
2466 {
2467 OnigStackIndex *pp = mem_start_stk;
2468 for (; pp < repeat_stk + n; pp += 2) {
2469 pp[0] = INVALID_STACK_INDEX;
2470 pp[1] = INVALID_STACK_INDEX;
2471 }
2472 }
2473#ifndef USE_SUBEXP_CALL
2474 mem_start_stk--; /* for index start from 1,
2475 mem_start_stk[1]..mem_start_stk[num_mem] */
2476 mem_end_stk--; /* for index start from 1,
2477 mem_end_stk[1]..mem_end_stk[num_mem] */
2478#endif
2479
2480#ifdef ONIG_DEBUG_MATCH
2481 fprintf(stderr, "match_at: str: %"PRIuPTR" (%p), end: %"PRIuPTR" (%p), start: %"PRIuPTR" (%p), sprev: %"PRIuPTR" (%p)\n",
2482 (uintptr_t )str, str, (uintptr_t )end, end, (uintptr_t )sstart, sstart, (uintptr_t )sprev, sprev);
2483 fprintf(stderr, "size: %d, start offset: %d\n",
2484 (int )(end - str), (int )(sstart - str));
2485 fprintf(stderr, "\n ofs> str stk:type addr:opcode\n");
2486#endif
2487
2488 STACK_PUSH_ENSURED(STK_ALT, (UChar* )FinishCode); /* bottom stack */
2489 best_len = ONIG_MISMATCH;
2490 s = (UChar* )sstart;
2491 pkeep = (UChar* )sstart;
2492
2493
2494#ifdef ONIG_DEBUG_MATCH
2495# define OPCODE_EXEC_HOOK \
2496 if (s) { \
2497 UChar *op, *q, *bp, buf[50]; \
2498 int len; \
2499 op = p - OP_OFFSET; \
2500 fprintf(stderr, "%4"PRIdPTR"> \"", (*op == OP_FINISH) ? (ptrdiff_t )-1 : s - str); \
2501 bp = buf; \
2502 q = s; \
2503 if (*op != OP_FINISH) { /* s may not be a valid pointer if OP_FINISH. */ \
2504 for (i = 0; i < 7 && q < end; i++) { \
2505 len = enclen(encode, q, end); \
2506 while (len-- > 0) *bp++ = *q++; \
2507 } \
2508 if (q < end) { xmemcpy(bp, "...", 3); bp += 3; } \
2509 } \
2510 xmemcpy(bp, "\"", 1); bp += 1; \
2511 *bp = 0; \
2512 fputs((char* )buf, stderr); \
2513 for (i = 0; i < 20 - (bp - buf); i++) fputc(' ', stderr); \
2514 fprintf(stderr, "%4"PRIdPTR":%s %4"PRIdPTR":", \
2515 stk - stk_base - 1, \
2516 (stk > stk_base) ? stack_type_str(stk[-1].type) : " ", \
2517 (op == FinishCode) ? (ptrdiff_t )-1 : op - reg->p); \
2518 onig_print_compiled_byte_code(stderr, op, reg->p+reg->used, NULL, encode); \
2519 fprintf(stderr, "\n"); \
2520 }
2521#else
2522# define OPCODE_EXEC_HOOK ((void) 0)
2523#endif
2524
2525#ifdef USE_MATCH_CACHE
2526#ifdef ONIG_DEBUG_MATCH_CACHE
2527#define MATCH_CACHE_DEBUG fprintf(stderr, "MATCH CACHE: cache %ld (p=%p index=%ld mask=%d)\n", match_cache_point, pbegin, match_cache_point_index, match_cache_point_mask)
2528#define MATCH_CACHE_DEBUG_HIT fprintf(stderr, "MATCH CACHE: cache hit\n")
2529#else
2530#define MATCH_CACHE_DEBUG ((void) 0)
2531#define MATCH_CACHE_DEBUG_HIT ((void) 0)
2532#endif
2533
2534# define CHECK_MATCH_CACHE do {\
2535 if (msa->match_cache_status == MATCH_CACHE_STATUS_ENABLED) {\
2536 const OnigCacheOpcode *cache_opcode;\
2537 long cache_point = find_cache_point(reg, msa->cache_opcodes, msa->num_cache_opcodes, pbegin, stk_base, repeat_stk, &cache_opcode);\
2538 if (cache_point >= 0) {\
2539 long match_cache_point = msa->num_cache_points * (long)(s - str) + cache_point;\
2540 long match_cache_point_index = match_cache_point >> 3;\
2541 uint8_t match_cache_point_mask = 1 << (match_cache_point & 7);\
2542 MATCH_CACHE_DEBUG;\
2543 if (msa->match_cache_buf[match_cache_point_index] & match_cache_point_mask) {\
2544 MATCH_CACHE_DEBUG_HIT;\
2545 if (cache_opcode->lookaround_nesting == 0) goto fail;\
2546 else if (cache_opcode->lookaround_nesting < 0) {\
2547 if (check_extended_match_cache_point(msa->match_cache_buf, match_cache_point_index, match_cache_point_mask)) {\
2548 STACK_STOP_BT_FAIL;\
2549 goto fail;\
2550 } else goto fail;\
2551 } else {\
2552 if (check_extended_match_cache_point(msa->match_cache_buf, match_cache_point_index, match_cache_point_mask)) {\
2553 p = cache_opcode->match_addr;\
2554 MOP_OUT;\
2555 JUMP;\
2556 } else goto fail;\
2557 }\
2558 }\
2559 STACK_PUSH_MATCH_CACHE_POINT(match_cache_point_index, match_cache_point_mask);\
2560 }\
2561 }\
2562} while (0)
2563#else
2564# define CHECK_MATCH_CACHE ((void) 0)
2565#endif
2566
2567 VM_LOOP {
2568 CASE(OP_END) MOP_IN(OP_END);
2569 n = s - sstart;
2570 if (n > best_len) {
2571 OnigRegion* region;
2572#ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE
2573 if (IS_FIND_LONGEST(option)) {
2574 if (n > msa->best_len) {
2575 msa->best_len = n;
2576 msa->best_s = (UChar* )sstart;
2577 }
2578 else
2579 goto end_best_len;
2580 }
2581#endif
2582 best_len = n;
2583 region = msa->region;
2584 if (region) {
2585 region->beg[0] = ((pkeep > s) ? s : pkeep) - str;
2586 region->end[0] = s - str;
2587 for (i = 1; i <= num_mem; i++) {
2588 if (mem_end_stk[i] != INVALID_STACK_INDEX) {
2589 if (BIT_STATUS_AT(reg->bt_mem_start, i))
2590 region->beg[i] = STACK_AT(mem_start_stk[i])->u.mem.pstr - str;
2591 else
2592 region->beg[i] = (UChar* )((void* )mem_start_stk[i]) - str;
2593
2594 region->end[i] = (BIT_STATUS_AT(reg->bt_mem_end, i)
2595 ? STACK_AT(mem_end_stk[i])->u.mem.pstr
2596 : (UChar* )((void* )mem_end_stk[i])) - str;
2597 }
2598 else {
2599 region->beg[i] = region->end[i] = ONIG_REGION_NOTPOS;
2600 }
2601 }
2602
2603#ifdef USE_CAPTURE_HISTORY
2604 if (reg->capture_history != 0) {
2605 int r;
2606 OnigCaptureTreeNode* node;
2607
2608 if (IS_NULL(region->history_root)) {
2609 region->history_root = node = history_node_new();
2610 CHECK_NULL_RETURN_MEMERR(node);
2611 }
2612 else {
2613 node = region->history_root;
2614 history_tree_clear(node);
2615 }
2616
2617 node->group = 0;
2618 node->beg = ((pkeep > s) ? s : pkeep) - str;
2619 node->end = s - str;
2620
2621 stkp = stk_base;
2622 r = make_capture_history_tree(region->history_root, &stkp,
2623 stk, (UChar* )str, reg);
2624 if (r < 0) {
2625 best_len = r; /* error code */
2626 goto finish;
2627 }
2628 }
2629#endif /* USE_CAPTURE_HISTORY */
2630 } /* if (region) */
2631 } /* n > best_len */
2632
2633#ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE
2634 end_best_len:
2635#endif
2636 MOP_OUT;
2637
2638 if (IS_FIND_CONDITION(option)) {
2639 if (IS_FIND_NOT_EMPTY(option) && s == sstart) {
2640 best_len = ONIG_MISMATCH;
2641 goto fail; /* for retry */
2642 }
2643 if (IS_FIND_LONGEST(option) && DATA_ENSURE_CHECK1) {
2644 goto fail; /* for retry */
2645 }
2646 }
2647
2648 /* default behavior: return first-matching result. */
2649 goto finish;
2650 NEXT;
2651
2652 CASE(OP_EXACT1) MOP_IN(OP_EXACT1);
2653 DATA_ENSURE(1);
2654 if (*p != *s) goto fail;
2655 p++; s++;
2656 MOP_OUT;
2657 NEXT;
2658
2659 CASE(OP_EXACT1_IC) MOP_IN(OP_EXACT1_IC);
2660 {
2661 int len;
2662 UChar *q, lowbuf[ONIGENC_MBC_CASE_FOLD_MAXLEN];
2663
2664 DATA_ENSURE(1);
2665 len = ONIGENC_MBC_CASE_FOLD(encode,
2666 /* DISABLE_CASE_FOLD_MULTI_CHAR(case_fold_flag), */
2667 case_fold_flag,
2668 &s, end, lowbuf);
2669 DATA_ENSURE(0);
2670 q = lowbuf;
2671 while (len-- > 0) {
2672 if (*p != *q) {
2673 goto fail;
2674 }
2675 p++; q++;
2676 }
2677 }
2678 MOP_OUT;
2679 NEXT;
2680
2681 CASE(OP_EXACT2) MOP_IN(OP_EXACT2);
2682 DATA_ENSURE(2);
2683 if (*p != *s) goto fail;
2684 p++; s++;
2685 if (*p != *s) goto fail;
2686 sprev = s;
2687 p++; s++;
2688 MOP_OUT;
2689 JUMP;
2690
2691 CASE(OP_EXACT3) MOP_IN(OP_EXACT3);
2692 DATA_ENSURE(3);
2693 if (*p != *s) goto fail;
2694 p++; s++;
2695 if (*p != *s) goto fail;
2696 p++; s++;
2697 if (*p != *s) goto fail;
2698 sprev = s;
2699 p++; s++;
2700 MOP_OUT;
2701 JUMP;
2702
2703 CASE(OP_EXACT4) MOP_IN(OP_EXACT4);
2704 DATA_ENSURE(4);
2705 if (*p != *s) goto fail;
2706 p++; s++;
2707 if (*p != *s) goto fail;
2708 p++; s++;
2709 if (*p != *s) goto fail;
2710 p++; s++;
2711 if (*p != *s) goto fail;
2712 sprev = s;
2713 p++; s++;
2714 MOP_OUT;
2715 JUMP;
2716
2717 CASE(OP_EXACT5) MOP_IN(OP_EXACT5);
2718 DATA_ENSURE(5);
2719 if (*p != *s) goto fail;
2720 p++; s++;
2721 if (*p != *s) goto fail;
2722 p++; s++;
2723 if (*p != *s) goto fail;
2724 p++; s++;
2725 if (*p != *s) goto fail;
2726 p++; s++;
2727 if (*p != *s) goto fail;
2728 sprev = s;
2729 p++; s++;
2730 MOP_OUT;
2731 JUMP;
2732
2733 CASE(OP_EXACTN) MOP_IN(OP_EXACTN);
2734 GET_LENGTH_INC(tlen, p);
2735 DATA_ENSURE(tlen);
2736 while (tlen-- > 0) {
2737 if (*p++ != *s++) goto fail;
2738 }
2739 sprev = s - 1;
2740 MOP_OUT;
2741 JUMP;
2742
2743 CASE(OP_EXACTN_IC) MOP_IN(OP_EXACTN_IC);
2744 {
2745 int len;
2746 UChar *q, *endp, lowbuf[ONIGENC_MBC_CASE_FOLD_MAXLEN];
2747
2748 GET_LENGTH_INC(tlen, p);
2749 endp = p + tlen;
2750
2751 while (p < endp) {
2752 sprev = s;
2753 DATA_ENSURE(1);
2754 len = ONIGENC_MBC_CASE_FOLD(encode,
2755 /* DISABLE_CASE_FOLD_MULTI_CHAR(case_fold_flag), */
2756 case_fold_flag,
2757 &s, end, lowbuf);
2758 DATA_ENSURE(0);
2759 q = lowbuf;
2760 while (len-- > 0) {
2761 if (*p != *q) goto fail;
2762 p++; q++;
2763 }
2764 }
2765 }
2766
2767 MOP_OUT;
2768 JUMP;
2769
2770 CASE(OP_EXACTMB2N1) MOP_IN(OP_EXACTMB2N1);
2771 DATA_ENSURE(2);
2772 if (*p != *s) goto fail;
2773 p++; s++;
2774 if (*p != *s) goto fail;
2775 p++; s++;
2776 MOP_OUT;
2777 NEXT;
2778
2779 CASE(OP_EXACTMB2N2) MOP_IN(OP_EXACTMB2N2);
2780 DATA_ENSURE(4);
2781 if (*p != *s) goto fail;
2782 p++; s++;
2783 if (*p != *s) goto fail;
2784 p++; s++;
2785 sprev = s;
2786 if (*p != *s) goto fail;
2787 p++; s++;
2788 if (*p != *s) goto fail;
2789 p++; s++;
2790 MOP_OUT;
2791 JUMP;
2792
2793 CASE(OP_EXACTMB2N3) MOP_IN(OP_EXACTMB2N3);
2794 DATA_ENSURE(6);
2795 if (*p != *s) goto fail;
2796 p++; s++;
2797 if (*p != *s) goto fail;
2798 p++; s++;
2799 if (*p != *s) goto fail;
2800 p++; s++;
2801 if (*p != *s) goto fail;
2802 p++; s++;
2803 sprev = s;
2804 if (*p != *s) goto fail;
2805 p++; s++;
2806 if (*p != *s) goto fail;
2807 p++; s++;
2808 MOP_OUT;
2809 JUMP;
2810
2811 CASE(OP_EXACTMB2N) MOP_IN(OP_EXACTMB2N);
2812 GET_LENGTH_INC(tlen, p);
2813 DATA_ENSURE(tlen * 2);
2814 while (tlen-- > 0) {
2815 if (*p != *s) goto fail;
2816 p++; s++;
2817 if (*p != *s) goto fail;
2818 p++; s++;
2819 }
2820 sprev = s - 2;
2821 MOP_OUT;
2822 JUMP;
2823
2824 CASE(OP_EXACTMB3N) MOP_IN(OP_EXACTMB3N);
2825 GET_LENGTH_INC(tlen, p);
2826 DATA_ENSURE(tlen * 3);
2827 while (tlen-- > 0) {
2828 if (*p != *s) goto fail;
2829 p++; s++;
2830 if (*p != *s) goto fail;
2831 p++; s++;
2832 if (*p != *s) goto fail;
2833 p++; s++;
2834 }
2835 sprev = s - 3;
2836 MOP_OUT;
2837 JUMP;
2838
2839 CASE(OP_EXACTMBN) MOP_IN(OP_EXACTMBN);
2840 GET_LENGTH_INC(tlen, p); /* mb-len */
2841 GET_LENGTH_INC(tlen2, p); /* string len */
2842 tlen2 *= tlen;
2843 DATA_ENSURE(tlen2);
2844 while (tlen2-- > 0) {
2845 if (*p != *s) goto fail;
2846 p++; s++;
2847 }
2848 sprev = s - tlen;
2849 MOP_OUT;
2850 JUMP;
2851
2852 CASE(OP_CCLASS) MOP_IN(OP_CCLASS);
2853 DATA_ENSURE(1);
2854 if (BITSET_AT(((BitSetRef )p), *s) == 0) goto fail;
2855 p += SIZE_BITSET;
2856 s += enclen(encode, s, end); /* OP_CCLASS can match mb-code. \D, \S */
2857 MOP_OUT;
2858 NEXT;
2859
2860 CASE(OP_CCLASS_MB) MOP_IN(OP_CCLASS_MB);
2861 if (! ONIGENC_IS_MBC_HEAD(encode, s, end)) goto fail;
2862
2863 cclass_mb:
2864 GET_LENGTH_INC(tlen, p);
2865 {
2866 OnigCodePoint code;
2867 UChar *ss;
2868 int mb_len;
2869
2870 DATA_ENSURE(1);
2871 mb_len = enclen(encode, s, end);
2872 DATA_ENSURE(mb_len);
2873 ss = s;
2874 s += mb_len;
2875 code = ONIGENC_MBC_TO_CODE(encode, ss, s);
2876
2877#ifdef PLATFORM_UNALIGNED_WORD_ACCESS
2878 if (! onig_is_in_code_range(p, code)) goto fail;
2879#else
2880 q = p;
2881 ALIGNMENT_RIGHT(q);
2882 if (! onig_is_in_code_range(q, code)) goto fail;
2883#endif
2884 }
2885 p += tlen;
2886 MOP_OUT;
2887 NEXT;
2888
2889 CASE(OP_CCLASS_MIX) MOP_IN(OP_CCLASS_MIX);
2890 DATA_ENSURE(1);
2891 if (ONIGENC_IS_MBC_HEAD(encode, s, end)) {
2892 p += SIZE_BITSET;
2893 goto cclass_mb;
2894 }
2895 else {
2896 if (BITSET_AT(((BitSetRef )p), *s) == 0)
2897 goto fail;
2898
2899 p += SIZE_BITSET;
2900 GET_LENGTH_INC(tlen, p);
2901 p += tlen;
2902 s++;
2903 }
2904 MOP_OUT;
2905 NEXT;
2906
2907 CASE(OP_CCLASS_NOT) MOP_IN(OP_CCLASS_NOT);
2908 DATA_ENSURE(1);
2909 if (BITSET_AT(((BitSetRef )p), *s) != 0) goto fail;
2910 p += SIZE_BITSET;
2911 s += enclen(encode, s, end);
2912 MOP_OUT;
2913 NEXT;
2914
2915 CASE(OP_CCLASS_MB_NOT) MOP_IN(OP_CCLASS_MB_NOT);
2916 DATA_ENSURE(1);
2917 if (! ONIGENC_IS_MBC_HEAD(encode, s, end)) {
2918 s++;
2919 GET_LENGTH_INC(tlen, p);
2920 p += tlen;
2921 goto cc_mb_not_success;
2922 }
2923
2924 cclass_mb_not:
2925 GET_LENGTH_INC(tlen, p);
2926 {
2927 OnigCodePoint code;
2928 UChar *ss;
2929 int mb_len = enclen(encode, s, end);
2930
2931 if (! DATA_ENSURE_CHECK(mb_len)) {
2932 DATA_ENSURE(1);
2933 s = (UChar* )end;
2934 p += tlen;
2935 goto cc_mb_not_success;
2936 }
2937
2938 ss = s;
2939 s += mb_len;
2940 code = ONIGENC_MBC_TO_CODE(encode, ss, s);
2941
2942#ifdef PLATFORM_UNALIGNED_WORD_ACCESS
2943 if (onig_is_in_code_range(p, code)) goto fail;
2944#else
2945 q = p;
2946 ALIGNMENT_RIGHT(q);
2947 if (onig_is_in_code_range(q, code)) goto fail;
2948#endif
2949 }
2950 p += tlen;
2951
2952 cc_mb_not_success:
2953 MOP_OUT;
2954 NEXT;
2955
2956 CASE(OP_CCLASS_MIX_NOT) MOP_IN(OP_CCLASS_MIX_NOT);
2957 DATA_ENSURE(1);
2958 if (ONIGENC_IS_MBC_HEAD(encode, s, end)) {
2959 p += SIZE_BITSET;
2960 goto cclass_mb_not;
2961 }
2962 else {
2963 if (BITSET_AT(((BitSetRef )p), *s) != 0)
2964 goto fail;
2965
2966 p += SIZE_BITSET;
2967 GET_LENGTH_INC(tlen, p);
2968 p += tlen;
2969 s++;
2970 }
2971 MOP_OUT;
2972 NEXT;
2973
2974 CASE(OP_ANYCHAR) MOP_IN(OP_ANYCHAR);
2975 DATA_ENSURE(1);
2976 n = enclen(encode, s, end);
2977 DATA_ENSURE(n);
2978 if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0)) goto fail;
2979 s += n;
2980 MOP_OUT;
2981 NEXT;
2982
2983 CASE(OP_ANYCHAR_ML) MOP_IN(OP_ANYCHAR_ML);
2984 DATA_ENSURE(1);
2985 n = enclen(encode, s, end);
2986 DATA_ENSURE(n);
2987 s += n;
2988 MOP_OUT;
2989 NEXT;
2990
2991 CASE(OP_ANYCHAR_STAR) MOP_IN(OP_ANYCHAR_STAR);
2992 while (DATA_ENSURE_CHECK1) {
2993 CHECK_MATCH_CACHE;
2994 STACK_PUSH_ALT(p, s, sprev, pkeep);
2995 n = enclen(encode, s, end);
2996 DATA_ENSURE(n);
2997 if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0)) goto fail;
2998 sprev = s;
2999 s += n;
3000 }
3001 MOP_OUT;
3002 JUMP;
3003
3004 CASE(OP_ANYCHAR_ML_STAR) MOP_IN(OP_ANYCHAR_ML_STAR);
3005 while (DATA_ENSURE_CHECK1) {
3006 CHECK_MATCH_CACHE;
3007 STACK_PUSH_ALT(p, s, sprev, pkeep);
3008 n = enclen(encode, s, end);
3009 if (n > 1) {
3010 DATA_ENSURE(n);
3011 sprev = s;
3012 s += n;
3013 }
3014 else {
3015 sprev = s;
3016 s++;
3017 }
3018 }
3019 MOP_OUT;
3020 JUMP;
3021
3022 CASE(OP_ANYCHAR_STAR_PEEK_NEXT) MOP_IN(OP_ANYCHAR_STAR_PEEK_NEXT);
3023 while (DATA_ENSURE_CHECK1) {
3024 CHECK_MATCH_CACHE;
3025 if (*p == *s) {
3026 STACK_PUSH_ALT(p + 1, s, sprev, pkeep);
3027 } else {
3028#ifdef USE_MATCH_CACHE
3029 /* We need to increment num_fails here, for invoking a cache optimization correctly. */
3030 /* Actually, the matching will be failed if we use `OP_ANYCHAR_STAR` simply in this case.*/
3031 msa->num_fails++;
3032#endif
3033 }
3034 n = enclen(encode, s, end);
3035 DATA_ENSURE(n);
3036 if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0)) goto fail;
3037 sprev = s;
3038 s += n;
3039 }
3040 p++;
3041 MOP_OUT;
3042 NEXT;
3043
3044 CASE(OP_ANYCHAR_ML_STAR_PEEK_NEXT)MOP_IN(OP_ANYCHAR_ML_STAR_PEEK_NEXT);
3045 while (DATA_ENSURE_CHECK1) {
3046 CHECK_MATCH_CACHE;
3047 if (*p == *s) {
3048 STACK_PUSH_ALT(p + 1, s, sprev, pkeep);
3049 } else {
3050#ifdef USE_MATCH_CACHE
3051 /* We need to increment num_fails here, for invoking a cache optimization correctly. */
3052 /* Actually, the matching will be failed if we use `OP_ANYCHAR_STAR_ML` simply in this case.*/
3053 msa->num_fails++;
3054#endif
3055 }
3056 n = enclen(encode, s, end);
3057 if (n > 1) {
3058 DATA_ENSURE(n);
3059 sprev = s;
3060 s += n;
3061 }
3062 else {
3063 sprev = s;
3064 s++;
3065 }
3066 }
3067 p++;
3068 MOP_OUT;
3069 NEXT;
3070
3071#ifdef USE_COMBINATION_EXPLOSION_CHECK
3072 CASE(OP_STATE_CHECK_ANYCHAR_STAR) MOP_IN(OP_STATE_CHECK_ANYCHAR_STAR);
3073 GET_STATE_CHECK_NUM_INC(mem, p);
3074 while (DATA_ENSURE_CHECK1) {
3075 STATE_CHECK_VAL(scv, mem);
3076 if (scv) goto fail;
3077
3078 STACK_PUSH_ALT_WITH_STATE_CHECK(p, s, sprev, mem, pkeep);
3079 n = enclen(encode, s, end);
3080 DATA_ENSURE(n);
3081 if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0)) goto fail;
3082 sprev = s;
3083 s += n;
3084 }
3085 MOP_OUT;
3086 NEXT;
3087
3088 CASE(OP_STATE_CHECK_ANYCHAR_ML_STAR)
3089 MOP_IN(OP_STATE_CHECK_ANYCHAR_ML_STAR);
3090
3091 GET_STATE_CHECK_NUM_INC(mem, p);
3092 while (DATA_ENSURE_CHECK1) {
3093 STATE_CHECK_VAL(scv, mem);
3094 if (scv) goto fail;
3095
3096 STACK_PUSH_ALT_WITH_STATE_CHECK(p, s, sprev, mem, pkeep);
3097 n = enclen(encode, s, end);
3098 if (n > 1) {
3099 DATA_ENSURE(n);
3100 sprev = s;
3101 s += n;
3102 }
3103 else {
3104 sprev = s;
3105 s++;
3106 }
3107 }
3108 MOP_OUT;
3109 NEXT;
3110#endif /* USE_COMBINATION_EXPLOSION_CHECK */
3111
3112 CASE(OP_WORD) MOP_IN(OP_WORD);
3113 DATA_ENSURE(1);
3114 if (! ONIGENC_IS_MBC_WORD(encode, s, end))
3115 goto fail;
3116
3117 s += enclen(encode, s, end);
3118 MOP_OUT;
3119 NEXT;
3120
3121 CASE(OP_ASCII_WORD) MOP_IN(OP_ASCII_WORD);
3122 DATA_ENSURE(1);
3123 if (! ONIGENC_IS_MBC_ASCII_WORD(encode, s, end))
3124 goto fail;
3125
3126 s += enclen(encode, s, end);
3127 MOP_OUT;
3128 NEXT;
3129
3130 CASE(OP_NOT_WORD) MOP_IN(OP_NOT_WORD);
3131 DATA_ENSURE(1);
3132 if (ONIGENC_IS_MBC_WORD(encode, s, end))
3133 goto fail;
3134
3135 s += enclen(encode, s, end);
3136 MOP_OUT;
3137 NEXT;
3138
3139 CASE(OP_NOT_ASCII_WORD) MOP_IN(OP_NOT_ASCII_WORD);
3140 DATA_ENSURE(1);
3141 if (ONIGENC_IS_MBC_ASCII_WORD(encode, s, end))
3142 goto fail;
3143
3144 s += enclen(encode, s, end);
3145 MOP_OUT;
3146 NEXT;
3147
3148 CASE(OP_WORD_BOUND) MOP_IN(OP_WORD_BOUND);
3149 if (ON_STR_BEGIN(s)) {
3150 DATA_ENSURE(1);
3151 if (! ONIGENC_IS_MBC_WORD(encode, s, end))
3152 goto fail;
3153 }
3154 else if (ON_STR_END(s)) {
3155 if (! ONIGENC_IS_MBC_WORD(encode, sprev, end))
3156 goto fail;
3157 }
3158 else {
3159 if (ONIGENC_IS_MBC_WORD(encode, s, end)
3160 == ONIGENC_IS_MBC_WORD(encode, sprev, end))
3161 goto fail;
3162 }
3163 MOP_OUT;
3164 JUMP;
3165
3166 CASE(OP_ASCII_WORD_BOUND) MOP_IN(OP_ASCII_WORD_BOUND);
3167 if (ON_STR_BEGIN(s)) {
3168 DATA_ENSURE(1);
3169 if (! ONIGENC_IS_MBC_ASCII_WORD(encode, s, end))
3170 goto fail;
3171 }
3172 else if (ON_STR_END(s)) {
3173 if (! ONIGENC_IS_MBC_ASCII_WORD(encode, sprev, end))
3174 goto fail;
3175 }
3176 else {
3177 if (ONIGENC_IS_MBC_ASCII_WORD(encode, s, end)
3178 == ONIGENC_IS_MBC_ASCII_WORD(encode, sprev, end))
3179 goto fail;
3180 }
3181 MOP_OUT;
3182 JUMP;
3183
3184 CASE(OP_NOT_WORD_BOUND) MOP_IN(OP_NOT_WORD_BOUND);
3185 if (ON_STR_BEGIN(s)) {
3186 if (DATA_ENSURE_CHECK1 && ONIGENC_IS_MBC_WORD(encode, s, end))
3187 goto fail;
3188 }
3189 else if (ON_STR_END(s)) {
3190 if (ONIGENC_IS_MBC_WORD(encode, sprev, end))
3191 goto fail;
3192 }
3193 else {
3194 if (ONIGENC_IS_MBC_WORD(encode, s, end)
3195 != ONIGENC_IS_MBC_WORD(encode, sprev, end))
3196 goto fail;
3197 }
3198 MOP_OUT;
3199 JUMP;
3200
3201 CASE(OP_NOT_ASCII_WORD_BOUND) MOP_IN(OP_NOT_ASCII_WORD_BOUND);
3202 if (ON_STR_BEGIN(s)) {
3203 if (DATA_ENSURE_CHECK1 && ONIGENC_IS_MBC_ASCII_WORD(encode, s, end))
3204 goto fail;
3205 }
3206 else if (ON_STR_END(s)) {
3207 if (ONIGENC_IS_MBC_ASCII_WORD(encode, sprev, end))
3208 goto fail;
3209 }
3210 else {
3211 if (ONIGENC_IS_MBC_ASCII_WORD(encode, s, end)
3212 != ONIGENC_IS_MBC_ASCII_WORD(encode, sprev, end))
3213 goto fail;
3214 }
3215 MOP_OUT;
3216 JUMP;
3217
3218#ifdef USE_WORD_BEGIN_END
3219 CASE(OP_WORD_BEGIN) MOP_IN(OP_WORD_BEGIN);
3220 if (DATA_ENSURE_CHECK1 && ONIGENC_IS_MBC_WORD(encode, s, end)) {
3221 if (ON_STR_BEGIN(s) || !ONIGENC_IS_MBC_WORD(encode, sprev, end)) {
3222 MOP_OUT;
3223 JUMP;
3224 }
3225 }
3226 goto fail;
3227 NEXT;
3228
3229 CASE(OP_ASCII_WORD_BEGIN) MOP_IN(OP_ASCII_WORD_BEGIN);
3230 if (DATA_ENSURE_CHECK1 && ONIGENC_IS_MBC_ASCII_WORD(encode, s, end)) {
3231 if (ON_STR_BEGIN(s) || !ONIGENC_IS_MBC_ASCII_WORD(encode, sprev, end)) {
3232 MOP_OUT;
3233 JUMP;
3234 }
3235 }
3236 goto fail;
3237 NEXT;
3238
3239 CASE(OP_WORD_END) MOP_IN(OP_WORD_END);
3240 if (!ON_STR_BEGIN(s) && ONIGENC_IS_MBC_WORD(encode, sprev, end)) {
3241 if (ON_STR_END(s) || !ONIGENC_IS_MBC_WORD(encode, s, end)) {
3242 MOP_OUT;
3243 JUMP;
3244 }
3245 }
3246 goto fail;
3247 NEXT;
3248
3249 CASE(OP_ASCII_WORD_END) MOP_IN(OP_ASCII_WORD_END);
3250 if (!ON_STR_BEGIN(s) && ONIGENC_IS_MBC_ASCII_WORD(encode, sprev, end)) {
3251 if (ON_STR_END(s) || !ONIGENC_IS_MBC_ASCII_WORD(encode, s, end)) {
3252 MOP_OUT;
3253 JUMP;
3254 }
3255 }
3256 goto fail;
3257 NEXT;
3258#endif
3259
3260 CASE(OP_BEGIN_BUF) MOP_IN(OP_BEGIN_BUF);
3261 if (! ON_STR_BEGIN(s)) goto fail;
3262 if (IS_NOTBOS(msa->options)) goto fail;
3263
3264 MOP_OUT;
3265 JUMP;
3266
3267 CASE(OP_END_BUF) MOP_IN(OP_END_BUF);
3268 if (! ON_STR_END(s)) goto fail;
3269 if (IS_NOTEOS(msa->options)) goto fail;
3270
3271 MOP_OUT;
3272 JUMP;
3273
3274 CASE(OP_BEGIN_LINE) MOP_IN(OP_BEGIN_LINE);
3275 if (ON_STR_BEGIN(s)) {
3276 if (IS_NOTBOL(msa->options)) goto fail;
3277 MOP_OUT;
3278 JUMP;
3279 }
3280 else if (ONIGENC_IS_MBC_NEWLINE(encode, sprev, end)
3281#ifdef USE_CRNL_AS_LINE_TERMINATOR
3282 && !(IS_NEWLINE_CRLF(option)
3283 && ONIGENC_IS_MBC_CRNL(encode, sprev, end))
3284#endif
3285 && !ON_STR_END(s)) {
3286 MOP_OUT;
3287 JUMP;
3288 }
3289 goto fail;
3290 NEXT;
3291
3292 CASE(OP_END_LINE) MOP_IN(OP_END_LINE);
3293 if (ON_STR_END(s)) {
3294#ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE
3295 if (IS_EMPTY_STR || !ONIGENC_IS_MBC_NEWLINE_EX(encode, sprev, str, end, option, 1)) {
3296#endif
3297 if (IS_NOTEOL(msa->options)) goto fail;
3298 MOP_OUT;
3299 JUMP;
3300#ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE
3301 }
3302#endif
3303 }
3304 else if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 1)) {
3305 MOP_OUT;
3306 JUMP;
3307 }
3308 goto fail;
3309 NEXT;
3310
3311 CASE(OP_SEMI_END_BUF) MOP_IN(OP_SEMI_END_BUF);
3312 if (ON_STR_END(s)) {
3313#ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE
3314 if (IS_EMPTY_STR || !ONIGENC_IS_MBC_NEWLINE_EX(encode, sprev, str, end, option, 1)) {
3315#endif
3316 if (IS_NOTEOL(msa->options)) goto fail;
3317 MOP_OUT;
3318 JUMP;
3319#ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE
3320 }
3321#endif
3322 }
3323 else if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 1)) {
3324 UChar* ss = s + enclen(encode, s, end);
3325 if (ON_STR_END(ss)) {
3326 MOP_OUT;
3327 JUMP;
3328 }
3329#ifdef USE_CRNL_AS_LINE_TERMINATOR
3330 else if (IS_NEWLINE_CRLF(option)
3331 && ONIGENC_IS_MBC_CRNL(encode, s, end)) {
3332 ss += enclen(encode, ss, end);
3333 if (ON_STR_END(ss)) {
3334 MOP_OUT;
3335 JUMP;
3336 }
3337 }
3338#endif
3339 }
3340 goto fail;
3341 NEXT;
3342
3343 CASE(OP_BEGIN_POSITION) MOP_IN(OP_BEGIN_POSITION);
3344 if (s != msa->gpos)
3345 goto fail;
3346
3347 MOP_OUT;
3348 JUMP;
3349
3350 CASE(OP_MEMORY_START_PUSH) MOP_IN(OP_MEMORY_START_PUSH);
3351 GET_MEMNUM_INC(mem, p);
3352 STACK_PUSH_MEM_START(mem, s);
3353 MOP_OUT;
3354 JUMP;
3355
3356 CASE(OP_MEMORY_START) MOP_IN(OP_MEMORY_START);
3357 GET_MEMNUM_INC(mem, p);
3358 mem_start_stk[mem] = (OnigStackIndex )((void* )s);
3359 mem_end_stk[mem] = INVALID_STACK_INDEX;
3360 MOP_OUT;
3361 JUMP;
3362
3363 CASE(OP_MEMORY_END_PUSH) MOP_IN(OP_MEMORY_END_PUSH);
3364 GET_MEMNUM_INC(mem, p);
3365 STACK_PUSH_MEM_END(mem, s);
3366 MOP_OUT;
3367 JUMP;
3368
3369 CASE(OP_MEMORY_END) MOP_IN(OP_MEMORY_END);
3370 GET_MEMNUM_INC(mem, p);
3371 mem_end_stk[mem] = (OnigStackIndex )((void* )s);
3372 MOP_OUT;
3373 JUMP;
3374
3375 CASE(OP_KEEP) MOP_IN(OP_KEEP);
3376 pkeep = s;
3377 MOP_OUT;
3378 JUMP;
3379
3380#ifdef USE_SUBEXP_CALL
3381 CASE(OP_MEMORY_END_PUSH_REC) MOP_IN(OP_MEMORY_END_PUSH_REC);
3382 GET_MEMNUM_INC(mem, p);
3383 STACK_GET_MEM_START(mem, stkp); /* should be before push mem-end. */
3384 STACK_PUSH_MEM_END(mem, s);
3385 mem_start_stk[mem] = GET_STACK_INDEX(stkp);
3386 MOP_OUT;
3387 JUMP;
3388
3389 CASE(OP_MEMORY_END_REC) MOP_IN(OP_MEMORY_END_REC);
3390 GET_MEMNUM_INC(mem, p);
3391 mem_end_stk[mem] = (OnigStackIndex )((void* )s);
3392 STACK_GET_MEM_START(mem, stkp);
3393
3394 if (BIT_STATUS_AT(reg->bt_mem_start, mem))
3395 mem_start_stk[mem] = GET_STACK_INDEX(stkp);
3396 else
3397 mem_start_stk[mem] = (OnigStackIndex )((void* )stkp->u.mem.pstr);
3398
3399 STACK_PUSH_MEM_END_MARK(mem);
3400 MOP_OUT;
3401 JUMP;
3402#endif
3403
3404 CASE(OP_BACKREF1) MOP_IN(OP_BACKREF1);
3405 mem = 1;
3406 goto backref;
3407 NEXT;
3408
3409 CASE(OP_BACKREF2) MOP_IN(OP_BACKREF2);
3410 mem = 2;
3411 goto backref;
3412 NEXT;
3413
3414 CASE(OP_BACKREFN) MOP_IN(OP_BACKREFN);
3415 GET_MEMNUM_INC(mem, p);
3416 backref:
3417 {
3418 int len;
3419 UChar *pstart, *pend;
3420
3421 /* if you want to remove following line,
3422 you should check in parse and compile time. */
3423 if (mem > num_mem) goto fail;
3424 if (mem_end_stk[mem] == INVALID_STACK_INDEX) goto fail;
3425 if (mem_start_stk[mem] == INVALID_STACK_INDEX) goto fail;
3426
3427 if (BIT_STATUS_AT(reg->bt_mem_start, mem))
3428 pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;
3429 else
3430 pstart = (UChar* )((void* )mem_start_stk[mem]);
3431
3432 pend = (BIT_STATUS_AT(reg->bt_mem_end, mem)
3433 ? STACK_AT(mem_end_stk[mem])->u.mem.pstr
3434 : (UChar* )((void* )mem_end_stk[mem]));
3435 n = pend - pstart;
3436 DATA_ENSURE(n);
3437 sprev = s;
3438 STRING_CMP(pstart, s, n);
3439 while (sprev + (len = enclen(encode, sprev, end)) < s)
3440 sprev += len;
3441
3442 MOP_OUT;
3443 JUMP;
3444 }
3445
3446 CASE(OP_BACKREFN_IC) MOP_IN(OP_BACKREFN_IC);
3447 GET_MEMNUM_INC(mem, p);
3448 {
3449 int len;
3450 UChar *pstart, *pend;
3451
3452 /* if you want to remove following line,
3453 you should check in parse and compile time. */
3454 if (mem > num_mem) goto fail;
3455 if (mem_end_stk[mem] == INVALID_STACK_INDEX) goto fail;
3456 if (mem_start_stk[mem] == INVALID_STACK_INDEX) goto fail;
3457
3458 if (BIT_STATUS_AT(reg->bt_mem_start, mem))
3459 pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;
3460 else
3461 pstart = (UChar* )((void* )mem_start_stk[mem]);
3462
3463 pend = (BIT_STATUS_AT(reg->bt_mem_end, mem)
3464 ? STACK_AT(mem_end_stk[mem])->u.mem.pstr
3465 : (UChar* )((void* )mem_end_stk[mem]));
3466 n = pend - pstart;
3467 DATA_ENSURE(n);
3468 sprev = s;
3469 STRING_CMP_IC(case_fold_flag, pstart, &s, (int)n, end);
3470 while (sprev + (len = enclen(encode, sprev, end)) < s)
3471 sprev += len;
3472
3473 MOP_OUT;
3474 JUMP;
3475 }
3476 NEXT;
3477
3478 CASE(OP_BACKREF_MULTI) MOP_IN(OP_BACKREF_MULTI);
3479 {
3480 int len, is_fail;
3481 UChar *pstart, *pend, *swork;
3482
3483 GET_LENGTH_INC(tlen, p);
3484 for (i = 0; i < tlen; i++) {
3485 GET_MEMNUM_INC(mem, p);
3486
3487 if (mem_end_stk[mem] == INVALID_STACK_INDEX) continue;
3488 if (mem_start_stk[mem] == INVALID_STACK_INDEX) continue;
3489
3490 if (BIT_STATUS_AT(reg->bt_mem_start, mem))
3491 pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;
3492 else
3493 pstart = (UChar* )((void* )mem_start_stk[mem]);
3494
3495 pend = (BIT_STATUS_AT(reg->bt_mem_end, mem)
3496 ? STACK_AT(mem_end_stk[mem])->u.mem.pstr
3497 : (UChar* )((void* )mem_end_stk[mem]));
3498 n = pend - pstart;
3499 DATA_ENSURE_CONTINUE(n);
3500 sprev = s;
3501 swork = s;
3502 STRING_CMP_VALUE(pstart, swork, n, is_fail);
3503 if (is_fail) continue;
3504 s = swork;
3505 while (sprev + (len = enclen(encode, sprev, end)) < s)
3506 sprev += len;
3507
3508 p += (SIZE_MEMNUM * (tlen - i - 1));
3509 break; /* success */
3510 }
3511 if (i == tlen) goto fail;
3512 MOP_OUT;
3513 JUMP;
3514 }
3515 NEXT;
3516
3517 CASE(OP_BACKREF_MULTI_IC) MOP_IN(OP_BACKREF_MULTI_IC);
3518 {
3519 int len, is_fail;
3520 UChar *pstart, *pend, *swork;
3521
3522 GET_LENGTH_INC(tlen, p);
3523 for (i = 0; i < tlen; i++) {
3524 GET_MEMNUM_INC(mem, p);
3525
3526 if (mem_end_stk[mem] == INVALID_STACK_INDEX) continue;
3527 if (mem_start_stk[mem] == INVALID_STACK_INDEX) continue;
3528
3529 if (BIT_STATUS_AT(reg->bt_mem_start, mem))
3530 pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;
3531 else
3532 pstart = (UChar* )((void* )mem_start_stk[mem]);
3533
3534 pend = (BIT_STATUS_AT(reg->bt_mem_end, mem)
3535 ? STACK_AT(mem_end_stk[mem])->u.mem.pstr
3536 : (UChar* )((void* )mem_end_stk[mem]));
3537 n = pend - pstart;
3538 DATA_ENSURE_CONTINUE(n);
3539 sprev = s;
3540 swork = s;
3541 STRING_CMP_VALUE_IC(case_fold_flag, pstart, &swork, n, end, is_fail);
3542 if (is_fail) continue;
3543 s = swork;
3544 while (sprev + (len = enclen(encode, sprev, end)) < s)
3545 sprev += len;
3546
3547 p += (SIZE_MEMNUM * (tlen - i - 1));
3548 break; /* success */
3549 }
3550 if (i == tlen) goto fail;
3551 MOP_OUT;
3552 JUMP;
3553 }
3554
3555#ifdef USE_BACKREF_WITH_LEVEL
3556 CASE(OP_BACKREF_WITH_LEVEL)
3557 {
3558 int len;
3559 OnigOptionType ic;
3560 LengthType level;
3561
3562 GET_OPTION_INC(ic, p);
3563 GET_LENGTH_INC(level, p);
3564 GET_LENGTH_INC(tlen, p);
3565
3566 sprev = s;
3567 if (backref_match_at_nested_level(reg, stk, stk_base, ic,
3568 case_fold_flag, (int )level, (int )tlen, p, &s, end)) {
3569 while (sprev + (len = enclen(encode, sprev, end)) < s)
3570 sprev += len;
3571
3572 p += (SIZE_MEMNUM * tlen);
3573 }
3574 else
3575 goto fail;
3576
3577 MOP_OUT;
3578 JUMP;
3579 }
3580
3581#endif
3582
3583#if 0 /* no need: IS_DYNAMIC_OPTION() == 0 */
3584 CASE(OP_SET_OPTION_PUSH) MOP_IN(OP_SET_OPTION_PUSH);
3585 GET_OPTION_INC(option, p);
3586 STACK_PUSH_ALT(p, s, sprev, pkeep);
3587 p += SIZE_OP_SET_OPTION + SIZE_OP_FAIL;
3588 MOP_OUT;
3589 JUMP;
3590
3591 CASE(OP_SET_OPTION) MOP_IN(OP_SET_OPTION);
3592 GET_OPTION_INC(option, p);
3593 MOP_OUT;
3594 JUMP;
3595#endif
3596
3597 CASE(OP_NULL_CHECK_START) MOP_IN(OP_NULL_CHECK_START);
3598 GET_MEMNUM_INC(mem, p); /* mem: null check id */
3599 STACK_PUSH_NULL_CHECK_START(mem, s);
3600 MOP_OUT;
3601 JUMP;
3602
3603 CASE(OP_NULL_CHECK_END) MOP_IN(OP_NULL_CHECK_END);
3604 {
3605 int isnull;
3606
3607 GET_MEMNUM_INC(mem, p); /* mem: null check id */
3608 STACK_NULL_CHECK(isnull, mem, s);
3609 if (isnull) {
3610#ifdef ONIG_DEBUG_MATCH
3611 fprintf(stderr, "NULL_CHECK_END: skip id:%d, s:%"PRIuPTR" (%p)\n",
3612 (int )mem, (uintptr_t )s, s);
3613#endif
3614 null_check_found:
3615 /* empty loop founded, skip next instruction */
3616 switch (*p++) {
3617 case OP_JUMP:
3618 case OP_PUSH:
3619 p += SIZE_RELADDR;
3620 break;
3621 case OP_REPEAT_INC:
3622 case OP_REPEAT_INC_NG:
3623 case OP_REPEAT_INC_SG:
3624 case OP_REPEAT_INC_NG_SG:
3625 p += SIZE_MEMNUM;
3626 break;
3627 default:
3628 goto unexpected_bytecode_error;
3629 break;
3630 }
3631 }
3632 }
3633 MOP_OUT;
3634 JUMP;
3635
3636#ifdef USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT
3637 CASE(OP_NULL_CHECK_END_MEMST) MOP_IN(OP_NULL_CHECK_END_MEMST);
3638 {
3639 int isnull;
3640
3641 GET_MEMNUM_INC(mem, p); /* mem: null check id */
3642 STACK_NULL_CHECK_MEMST(isnull, mem, s, reg);
3643 if (isnull) {
3644# ifdef ONIG_DEBUG_MATCH
3645 fprintf(stderr, "NULL_CHECK_END_MEMST: skip id:%d, s:%"PRIuPTR" (%p)\n",
3646 (int )mem, (uintptr_t )s, s);
3647# endif
3648 if (isnull == -1) goto fail;
3649 goto null_check_found;
3650 }
3651 }
3652 MOP_OUT;
3653 JUMP;
3654#endif
3655
3656#ifdef USE_SUBEXP_CALL
3657 CASE(OP_NULL_CHECK_END_MEMST_PUSH)
3658 MOP_IN(OP_NULL_CHECK_END_MEMST_PUSH);
3659 {
3660 int isnull;
3661
3662 GET_MEMNUM_INC(mem, p); /* mem: null check id */
3663# ifdef USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT
3664 STACK_NULL_CHECK_MEMST_REC(isnull, mem, s, reg);
3665# else
3666 STACK_NULL_CHECK_REC(isnull, mem, s);
3667# endif
3668 if (isnull) {
3669# ifdef ONIG_DEBUG_MATCH
3670 fprintf(stderr, "NULL_CHECK_END_MEMST_PUSH: skip id:%d, s:%"PRIuPTR" (%p)\n",
3671 (int )mem, (uintptr_t )s, s);
3672# endif
3673 if (isnull == -1) goto fail;
3674 goto null_check_found;
3675 }
3676 else {
3677 STACK_PUSH_NULL_CHECK_END(mem);
3678 }
3679 }
3680 MOP_OUT;
3681 JUMP;
3682#endif
3683
3684 CASE(OP_JUMP) MOP_IN(OP_JUMP);
3685 GET_RELADDR_INC(addr, p);
3686 p += addr;
3687 MOP_OUT;
3688 CHECK_INTERRUPT_IN_MATCH_AT;
3689 JUMP;
3690
3691 CASE(OP_PUSH) MOP_IN(OP_PUSH);
3692 GET_RELADDR_INC(addr, p);
3693 CHECK_MATCH_CACHE;
3694 STACK_PUSH_ALT(p + addr, s, sprev, pkeep);
3695 MOP_OUT;
3696 JUMP;
3697
3698#ifdef USE_COMBINATION_EXPLOSION_CHECK
3699 CASE(OP_STATE_CHECK_PUSH) MOP_IN(OP_STATE_CHECK_PUSH);
3700 GET_STATE_CHECK_NUM_INC(mem, p);
3701 STATE_CHECK_VAL(scv, mem);
3702 if (scv) goto fail;
3703
3704 GET_RELADDR_INC(addr, p);
3705 STACK_PUSH_ALT_WITH_STATE_CHECK(p + addr, s, sprev, mem, pkeep);
3706 MOP_OUT;
3707 JUMP;
3708
3709 CASE(OP_STATE_CHECK_PUSH_OR_JUMP) MOP_IN(OP_STATE_CHECK_PUSH_OR_JUMP);
3710 GET_STATE_CHECK_NUM_INC(mem, p);
3711 GET_RELADDR_INC(addr, p);
3712 STATE_CHECK_VAL(scv, mem);
3713 if (scv) {
3714 p += addr;
3715 }
3716 else {
3717 STACK_PUSH_ALT_WITH_STATE_CHECK(p + addr, s, sprev, mem, pkeep);
3718 }
3719 MOP_OUT;
3720 JUMP;
3721
3722 CASE(OP_STATE_CHECK) MOP_IN(OP_STATE_CHECK);
3723 GET_STATE_CHECK_NUM_INC(mem, p);
3724 STATE_CHECK_VAL(scv, mem);
3725 if (scv) goto fail;
3726
3727 STACK_PUSH_STATE_CHECK(s, mem);
3728 MOP_OUT;
3729 JUMP;
3730#endif /* USE_COMBINATION_EXPLOSION_CHECK */
3731
3732 CASE(OP_POP) MOP_IN(OP_POP);
3733 STACK_POP_ONE;
3734#ifdef USE_MATCH_CACHE
3735 /* We need to increment num_fails here, for invoking a cache optimization correctly, */
3736 /* because Onigmo makes a loop, which is pairwise disjoint to the following set, as atomic. */
3737 msa->num_fails++;
3738#endif
3739 MOP_OUT;
3740 JUMP;
3741
3742#ifdef USE_OP_PUSH_OR_JUMP_EXACT
3743 CASE(OP_PUSH_OR_JUMP_EXACT1) MOP_IN(OP_PUSH_OR_JUMP_EXACT1);
3744 GET_RELADDR_INC(addr, p);
3745 if (*p == *s && DATA_ENSURE_CHECK1) {
3746 p++;
3747 CHECK_MATCH_CACHE;
3748 STACK_PUSH_ALT(p + addr, s, sprev, pkeep);
3749 MOP_OUT;
3750 JUMP;
3751 }
3752 p += (addr + 1);
3753 MOP_OUT;
3754 JUMP;
3755#endif
3756
3757 CASE(OP_PUSH_IF_PEEK_NEXT) MOP_IN(OP_PUSH_IF_PEEK_NEXT);
3758 GET_RELADDR_INC(addr, p);
3759 if (*p == *s) {
3760 p++;
3761 CHECK_MATCH_CACHE;
3762 STACK_PUSH_ALT(p + addr, s, sprev, pkeep);
3763 MOP_OUT;
3764 JUMP;
3765 }
3766 p++;
3767 MOP_OUT;
3768 JUMP;
3769
3770 CASE(OP_REPEAT) MOP_IN(OP_REPEAT);
3771 {
3772 GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */
3773 GET_RELADDR_INC(addr, p);
3774
3775 STACK_ENSURE(1);
3776 repeat_stk[mem] = GET_STACK_INDEX(stk);
3777 STACK_PUSH_REPEAT(mem, p);
3778
3779 if (reg->repeat_range[mem].lower == 0) {
3780 CHECK_MATCH_CACHE;
3781 STACK_PUSH_ALT(p + addr, s, sprev, pkeep);
3782 }
3783 }
3784 MOP_OUT;
3785 JUMP;
3786
3787 CASE(OP_REPEAT_NG) MOP_IN(OP_REPEAT_NG);
3788 {
3789 GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */
3790 GET_RELADDR_INC(addr, p);
3791
3792 STACK_ENSURE(1);
3793 repeat_stk[mem] = GET_STACK_INDEX(stk);
3794 STACK_PUSH_REPEAT(mem, p);
3795
3796 if (reg->repeat_range[mem].lower == 0) {
3797 CHECK_MATCH_CACHE;
3798 STACK_PUSH_ALT(p, s, sprev, pkeep);
3799 p += addr;
3800 }
3801 }
3802 MOP_OUT;
3803 JUMP;
3804
3805 CASE(OP_REPEAT_INC) MOP_IN(OP_REPEAT_INC);
3806 GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */
3807 si = repeat_stk[mem];
3808 stkp = STACK_AT(si);
3809
3810 repeat_inc:
3811 stkp->u.repeat.count++;
3812 if (stkp->u.repeat.count >= reg->repeat_range[mem].upper) {
3813 /* end of repeat. Nothing to do. */
3814 }
3815 else if (stkp->u.repeat.count >= reg->repeat_range[mem].lower) {
3816 if (*pbegin == OP_REPEAT_INC) {
3817 CHECK_MATCH_CACHE;
3818 }
3819 STACK_PUSH_ALT(p, s, sprev, pkeep);
3820 p = STACK_AT(si)->u.repeat.pcode; /* Don't use stkp after PUSH. */
3821 }
3822 else {
3823 p = stkp->u.repeat.pcode;
3824 }
3825 STACK_PUSH_REPEAT_INC(si);
3826 MOP_OUT;
3827 CHECK_INTERRUPT_IN_MATCH_AT;
3828 JUMP;
3829
3830 CASE(OP_REPEAT_INC_SG) MOP_IN(OP_REPEAT_INC_SG);
3831 GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */
3832 STACK_GET_REPEAT(mem, stkp);
3833 si = GET_STACK_INDEX(stkp);
3834 goto repeat_inc;
3835 NEXT;
3836
3837 CASE(OP_REPEAT_INC_NG) MOP_IN(OP_REPEAT_INC_NG);
3838 GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */
3839 si = repeat_stk[mem];
3840 stkp = STACK_AT(si);
3841
3842 repeat_inc_ng:
3843 stkp->u.repeat.count++;
3844 if (stkp->u.repeat.count < reg->repeat_range[mem].upper) {
3845 if (stkp->u.repeat.count >= reg->repeat_range[mem].lower) {
3846 UChar* pcode = stkp->u.repeat.pcode;
3847
3848 STACK_PUSH_REPEAT_INC(si);
3849 if (*pbegin == OP_REPEAT_INC_NG) {
3850 CHECK_MATCH_CACHE;
3851 }
3852 STACK_PUSH_ALT(pcode, s, sprev, pkeep);
3853 }
3854 else {
3855 p = stkp->u.repeat.pcode;
3856 STACK_PUSH_REPEAT_INC(si);
3857 }
3858 }
3859 else if (stkp->u.repeat.count == reg->repeat_range[mem].upper) {
3860 STACK_PUSH_REPEAT_INC(si);
3861 }
3862 MOP_OUT;
3863 CHECK_INTERRUPT_IN_MATCH_AT;
3864 JUMP;
3865
3866 CASE(OP_REPEAT_INC_NG_SG) MOP_IN(OP_REPEAT_INC_NG_SG);
3867 GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */
3868 STACK_GET_REPEAT(mem, stkp);
3869 si = GET_STACK_INDEX(stkp);
3870 goto repeat_inc_ng;
3871 NEXT;
3872
3873 CASE(OP_PUSH_POS) MOP_IN(OP_PUSH_POS);
3874 STACK_PUSH_POS(s, sprev, pkeep);
3875 MOP_OUT;
3876 JUMP;
3877
3878 CASE(OP_POP_POS) MOP_IN(OP_POP_POS);
3879 {
3880 STACK_POS_END(stkp);
3881 s = stkp->u.state.pstr;
3882 sprev = stkp->u.state.pstr_prev;
3883 }
3884 MOP_OUT;
3885 JUMP;
3886
3887 CASE(OP_PUSH_POS_NOT) MOP_IN(OP_PUSH_POS_NOT);
3888 GET_RELADDR_INC(addr, p);
3889 STACK_PUSH_POS_NOT(p + addr, s, sprev, pkeep);
3890 MOP_OUT;
3891 JUMP;
3892
3893 CASE(OP_FAIL_POS) MOP_IN(OP_FAIL_POS);
3894 STACK_POP_TIL_POS_NOT;
3895 goto fail;
3896 NEXT;
3897
3898 CASE(OP_PUSH_STOP_BT) MOP_IN(OP_PUSH_STOP_BT);
3899 STACK_PUSH_STOP_BT;
3900 MOP_OUT;
3901 JUMP;
3902
3903 CASE(OP_POP_STOP_BT) MOP_IN(OP_POP_STOP_BT);
3904 STACK_STOP_BT_END;
3905 MOP_OUT;
3906 JUMP;
3907
3908 CASE(OP_LOOK_BEHIND) MOP_IN(OP_LOOK_BEHIND);
3909 GET_LENGTH_INC(tlen, p);
3910 s = (UChar* )ONIGENC_STEP_BACK(encode, str, s, end, (int )tlen);
3911 if (IS_NULL(s)) goto fail;
3912 sprev = (UChar* )onigenc_get_prev_char_head(encode, str, s, end);
3913 MOP_OUT;
3914 JUMP;
3915
3916 CASE(OP_PUSH_LOOK_BEHIND_NOT) MOP_IN(OP_PUSH_LOOK_BEHIND_NOT);
3917 GET_RELADDR_INC(addr, p);
3918 GET_LENGTH_INC(tlen, p);
3919 q = (UChar* )ONIGENC_STEP_BACK(encode, str, s, end, (int )tlen);
3920 if (IS_NULL(q)) {
3921 /* too short case -> success. ex. /(?<!XXX)a/.match("a")
3922 If you want to change to fail, replace following line. */
3923 p += addr;
3924 /* goto fail; */
3925 }
3926 else {
3927 STACK_PUSH_LOOK_BEHIND_NOT(p + addr, s, sprev, pkeep);
3928 s = q;
3929 sprev = (UChar* )onigenc_get_prev_char_head(encode, str, s, end);
3930 }
3931 MOP_OUT;
3932 JUMP;
3933
3934 CASE(OP_FAIL_LOOK_BEHIND_NOT) MOP_IN(OP_FAIL_LOOK_BEHIND_NOT);
3935 STACK_POP_TIL_LOOK_BEHIND_NOT;
3936 goto fail;
3937 NEXT;
3938
3939 CASE(OP_PUSH_ABSENT_POS) MOP_IN(OP_PUSH_ABSENT_POS);
3940 /* Save the absent-start-pos and the original end-pos. */
3941 STACK_PUSH_ABSENT_POS(s, ABSENT_END_POS);
3942 MOP_OUT;
3943 JUMP;
3944
3945 CASE(OP_ABSENT) MOP_IN(OP_ABSENT);
3946 {
3947 const UChar* aend = ABSENT_END_POS;
3948 UChar* absent;
3949 UChar* selfp = p - 1;
3950
3951 STACK_POP_ABSENT_POS(absent, ABSENT_END_POS); /* Restore end-pos. */
3952 GET_RELADDR_INC(addr, p);
3953#ifdef ONIG_DEBUG_MATCH
3954 fprintf(stderr, "ABSENT: s:%p, end:%p, absent:%p, aend:%p\n", s, end, absent, aend);
3955#endif
3956 if ((absent > aend) && (s > absent)) {
3957 /* An empty match occurred in (?~...) at the start point.
3958 * Never match. */
3959 STACK_POP;
3960 goto fail;
3961 }
3962 else if ((s >= aend) && (s > absent)) {
3963 if (s > aend) {
3964 /* Only one (or less) character matched in the last iteration.
3965 * This is not a possible point. */
3966 goto fail;
3967 }
3968 /* All possible points were found. Try matching after (?~...). */
3969 DATA_ENSURE(0);
3970 p += addr;
3971 }
3972 else if (s == end) {
3973 /* At the end of the string, just match with it */
3974 DATA_ENSURE(0);
3975 p += addr;
3976 }
3977 else {
3978 STACK_PUSH_ALT(p + addr, s, sprev, pkeep); /* Push possible point. */
3979 n = enclen(encode, s, end);
3980 STACK_PUSH_ABSENT_POS(absent, ABSENT_END_POS); /* Save the original pos. */
3981 STACK_PUSH_ALT(selfp, s + n, s, pkeep); /* Next iteration. */
3982 STACK_PUSH_ABSENT;
3983 ABSENT_END_POS = aend;
3984 }
3985 }
3986 MOP_OUT;
3987 JUMP;
3988
3989 CASE(OP_ABSENT_END) MOP_IN(OP_ABSENT_END);
3990 /* The pattern inside (?~...) was matched.
3991 * Set the end-pos temporary and go to next iteration. */
3992 if (sprev < ABSENT_END_POS)
3993 ABSENT_END_POS = sprev;
3994#ifdef ONIG_DEBUG_MATCH
3995 fprintf(stderr, "ABSENT_END: end:%p\n", ABSENT_END_POS);
3996#endif
3997 STACK_POP_TIL_ABSENT;
3998 goto fail;
3999 NEXT;
4000
4001#ifdef USE_SUBEXP_CALL
4002 CASE(OP_CALL) MOP_IN(OP_CALL);
4003 GET_ABSADDR_INC(addr, p);
4004 STACK_PUSH_CALL_FRAME(p);
4005 p = reg->p + addr;
4006 MOP_OUT;
4007 JUMP;
4008
4009 CASE(OP_RETURN) MOP_IN(OP_RETURN);
4010 STACK_RETURN(p);
4011 STACK_PUSH_RETURN;
4012 MOP_OUT;
4013 JUMP;
4014#endif
4015
4016 CASE(OP_CONDITION) MOP_IN(OP_CONDITION);
4017 GET_MEMNUM_INC(mem, p);
4018 GET_RELADDR_INC(addr, p);
4019 if ((mem > num_mem) ||
4020 (mem_end_stk[mem] == INVALID_STACK_INDEX) ||
4021 (mem_start_stk[mem] == INVALID_STACK_INDEX)) {
4022 p += addr;
4023 }
4024 MOP_OUT;
4025 JUMP;
4026
4027 CASE(OP_FINISH)
4028 goto finish;
4029 NEXT;
4030
4031 CASE(OP_FAIL)
4032 if (0) {
4033 /* fall */
4034 fail:
4035 MOP_OUT;
4036 }
4037 MOP_IN(OP_FAIL);
4038 STACK_POP;
4039 p = stk->u.state.pcode;
4040 s = stk->u.state.pstr;
4041 sprev = stk->u.state.pstr_prev;
4042 pkeep = stk->u.state.pkeep;
4043
4044#ifdef USE_MATCH_CACHE
4045 if (
4046 msa->match_cache_status != MATCH_CACHE_STATUS_DISABLED &&
4047 ++msa->num_fails >= (long)(end - str) * msa->num_cache_opcodes
4048 ) {
4049 if (msa->match_cache_status == MATCH_CACHE_STATUS_UNINIT) {
4050 msa->match_cache_status = MATCH_CACHE_STATUS_INIT;
4051 OnigPosition r = count_num_cache_opcodes(reg, &msa->num_cache_opcodes);
4052 if (r < 0) goto bytecode_error;
4053 }
4054 if (msa->num_cache_opcodes == NUM_CACHE_OPCODES_IMPOSSIBLE || msa->num_cache_opcodes == 0) {
4055 msa->match_cache_status = MATCH_CACHE_STATUS_DISABLED;
4056 goto fail_match_cache;
4057 }
4058 if (msa->num_fails < (long)(end - str) * msa->num_cache_opcodes) {
4059 goto fail_match_cache;
4060 }
4061 if (msa->cache_opcodes == NULL) {
4062 msa->match_cache_status = MATCH_CACHE_STATUS_ENABLED;
4063 OnigCacheOpcode* cache_opcodes = (OnigCacheOpcode*)xmalloc(msa->num_cache_opcodes * sizeof(OnigCacheOpcode));
4064 if (cache_opcodes == NULL) {
4065 return ONIGERR_MEMORY;
4066 }
4067 OnigPosition r = init_cache_opcodes(reg, cache_opcodes, &msa->num_cache_points);
4068 if (r < 0) {
4069 if (r == ONIGERR_UNEXPECTED_BYTECODE) goto unexpected_bytecode_error;
4070 else goto bytecode_error;
4071 }
4072 msa->cache_opcodes = cache_opcodes;
4073#ifdef ONIG_DEBUG_MATCH_CACHE
4074 fprintf(stderr, "MATCH CACHE: #cache opcodes = %ld\n", msa->num_cache_opcodes);
4075 fprintf(stderr, "MATCH CACHE: #cache points = %ld\n", msa->num_cache_points);
4076 fprintf(stderr, "MATCH CACHE: cache opcodes (%p):\n", msa->cache_opcodes);
4077 for (int i = 0; i < msa->num_cache_opcodes; i++) {
4078 fprintf(stderr, "MATCH CACHE: [%p] cache_point=%ld outer_repeat_mem=%d num_cache_opcodes_at_outer_repeat=%ld num_cache_opcodes_in_outer_repeat=%ld lookaround_nesting=%d match_addr=%p\n", msa->cache_opcodes[i].addr, msa->cache_opcodes[i].cache_point, msa->cache_opcodes[i].outer_repeat_mem, msa->cache_opcodes[i].num_cache_points_at_outer_repeat, msa->cache_opcodes[i].num_cache_points_in_outer_repeat, msa->cache_opcodes[i].lookaround_nesting, msa->cache_opcodes[i].match_addr);
4079 }
4080#endif
4081 }
4082 if (msa->match_cache_buf == NULL) {
4083 size_t length = (end - str) + 1;
4084 size_t num_match_cache_points = (size_t)msa->num_cache_points * length;
4085#ifdef ONIG_DEBUG_MATCH_CACHE
4086 fprintf(stderr, "MATCH CACHE: #match cache points = %ld (length = %zu)\n", num_match_cache_points, length);
4087#endif
4088 /* Overflow check */
4089 if (num_match_cache_points / length != (size_t)msa->num_cache_points) {
4090 return ONIGERR_MEMORY;
4091 }
4092 if (num_match_cache_points >= LONG_MAX_LIMIT) {
4093 return ONIGERR_MEMORY;
4094 }
4095 size_t match_cache_buf_length = (num_match_cache_points >> 3) + (num_match_cache_points & 7 ? 1 : 0) + 1;
4096 uint8_t* match_cache_buf = (uint8_t*)xmalloc(match_cache_buf_length * sizeof(uint8_t));
4097 if (match_cache_buf == NULL) {
4098 return ONIGERR_MEMORY;
4099 }
4100 xmemset(match_cache_buf, 0, match_cache_buf_length * sizeof(uint8_t));
4101 msa->match_cache_buf = match_cache_buf;
4102 }
4103 }
4104 fail_match_cache:
4105#endif
4106
4107#ifdef USE_COMBINATION_EXPLOSION_CHECK
4108 if (stk->u.state.state_check != 0) {
4109 stk->type = STK_STATE_CHECK_MARK;
4110 stk++;
4111 }
4112#endif
4113
4114 MOP_OUT;
4115 CHECK_INTERRUPT_IN_MATCH_AT;
4116 JUMP;
4117
4118 DEFAULT
4119 goto bytecode_error;
4120 } VM_LOOP_END
4121
4122 finish:
4123 STACK_SAVE;
4124 xfree(xmalloc_base);
4125 return best_len;
4126
4127#ifdef ONIG_DEBUG
4128 stack_error:
4129 STACK_SAVE;
4130 xfree(xmalloc_base);
4131 return ONIGERR_STACK_BUG;
4132#endif
4133
4134 bytecode_error:
4135 STACK_SAVE;
4136 xfree(xmalloc_base);
4137 return ONIGERR_UNDEFINED_BYTECODE;
4138
4139 unexpected_bytecode_error:
4140 STACK_SAVE;
4141 xfree(xmalloc_base);
4142 return ONIGERR_UNEXPECTED_BYTECODE;
4143}
4144
4145
4146static UChar*
4147slow_search(OnigEncoding enc, UChar* target, UChar* target_end,
4148 const UChar* text, const UChar* text_end, UChar* text_range)
4149{
4150 UChar *t, *p, *s, *end;
4151
4152 end = (UChar* )text_end;
4153 end -= target_end - target - 1;
4154 if (end > text_range)
4155 end = text_range;
4156
4157 s = (UChar* )text;
4158
4159 if (enc->max_enc_len == enc->min_enc_len) {
4160 int n = enc->max_enc_len;
4161
4162 while (s < end) {
4163 if (*s == *target) {
4164 p = s + 1;
4165 t = target + 1;
4166 if (target_end == t || memcmp(t, p, target_end - t) == 0)
4167 return s;
4168 }
4169 s += n;
4170 }
4171 return (UChar* )NULL;
4172 }
4173 while (s < end) {
4174 if (*s == *target) {
4175 p = s + 1;
4176 t = target + 1;
4177 if (target_end == t || memcmp(t, p, target_end - t) == 0)
4178 return s;
4179 }
4180 s += enclen(enc, s, text_end);
4181 }
4182
4183 return (UChar* )NULL;
4184}
4185
4186static int
4187str_lower_case_match(OnigEncoding enc, int case_fold_flag,
4188 const UChar* t, const UChar* tend,
4189 const UChar* p, const UChar* end)
4190{
4191 int lowlen;
4192 UChar *q, lowbuf[ONIGENC_MBC_CASE_FOLD_MAXLEN];
4193
4194 while (t < tend) {
4195 lowlen = ONIGENC_MBC_CASE_FOLD(enc, case_fold_flag, &p, end, lowbuf);
4196 q = lowbuf;
4197 while (lowlen > 0) {
4198 if (*t++ != *q++) return 0;
4199 lowlen--;
4200 }
4201 }
4202
4203 return 1;
4204}
4205
4206static UChar*
4207slow_search_ic(OnigEncoding enc, int case_fold_flag,
4208 UChar* target, UChar* target_end,
4209 const UChar* text, const UChar* text_end, UChar* text_range)
4210{
4211 UChar *s, *end;
4212
4213 end = (UChar* )text_end;
4214 end -= target_end - target - 1;
4215 if (end > text_range)
4216 end = text_range;
4217
4218 s = (UChar* )text;
4219
4220 while (s < end) {
4221 if (str_lower_case_match(enc, case_fold_flag, target, target_end,
4222 s, text_end))
4223 return s;
4224
4225 s += enclen(enc, s, text_end);
4226 }
4227
4228 return (UChar* )NULL;
4229}
4230
4231static UChar*
4232slow_search_backward(OnigEncoding enc, UChar* target, UChar* target_end,
4233 const UChar* text, const UChar* adjust_text,
4234 const UChar* text_end, const UChar* text_start)
4235{
4236 UChar *t, *p, *s;
4237
4238 s = (UChar* )text_end;
4239 s -= (target_end - target);
4240 if (s > text_start)
4241 s = (UChar* )text_start;
4242 else
4243 s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, adjust_text, s, text_end);
4244
4245 while (s >= text) {
4246 if (*s == *target) {
4247 p = s + 1;
4248 t = target + 1;
4249 while (t < target_end) {
4250 if (*t != *p++)
4251 break;
4252 t++;
4253 }
4254 if (t == target_end)
4255 return s;
4256 }
4257 s = (UChar* )onigenc_get_prev_char_head(enc, adjust_text, s, text_end);
4258 }
4259
4260 return (UChar* )NULL;
4261}
4262
4263static UChar*
4264slow_search_backward_ic(OnigEncoding enc, int case_fold_flag,
4265 UChar* target, UChar* target_end,
4266 const UChar* text, const UChar* adjust_text,
4267 const UChar* text_end, const UChar* text_start)
4268{
4269 UChar *s;
4270
4271 s = (UChar* )text_end;
4272 s -= (target_end - target);
4273 if (s > text_start)
4274 s = (UChar* )text_start;
4275 else
4276 s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, adjust_text, s, text_end);
4277
4278 while (s >= text) {
4279 if (str_lower_case_match(enc, case_fold_flag,
4280 target, target_end, s, text_end))
4281 return s;
4282
4283 s = (UChar* )onigenc_get_prev_char_head(enc, adjust_text, s, text_end);
4284 }
4285
4286 return (UChar* )NULL;
4287}
4288
4289#ifndef USE_SUNDAY_QUICK_SEARCH
4290/* Boyer-Moore-Horspool search applied to a multibyte string */
4291static UChar*
4292bm_search_notrev(regex_t* reg, const UChar* target, const UChar* target_end,
4293 const UChar* text, const UChar* text_end,
4294 const UChar* text_range)
4295{
4296 const UChar *s, *se, *t, *p, *end;
4297 const UChar *tail;
4298 ptrdiff_t skip, tlen1;
4299
4300# ifdef ONIG_DEBUG_SEARCH
4301 fprintf(stderr, "bm_search_notrev: text: %"PRIuPTR" (%p), text_end: %"PRIuPTR" (%p), text_range: %"PRIuPTR" (%p)\n",
4302 (uintptr_t )text, text, (uintptr_t )text_end, text_end, (uintptr_t )text_range, text_range);
4303# endif
4304
4305 tail = target_end - 1;
4306 tlen1 = tail - target;
4307 end = text_range;
4308 if (end + tlen1 > text_end)
4309 end = text_end - tlen1;
4310
4311 s = text;
4312
4313 if (IS_NULL(reg->int_map)) {
4314 while (s < end) {
4315 p = se = s + tlen1;
4316 t = tail;
4317 while (*p == *t) {
4318 if (t == target) return (UChar* )s;
4319 p--; t--;
4320 }
4321 skip = reg->map[*se];
4322 t = s;
4323 do {
4324 s += enclen(reg->enc, s, end);
4325 } while ((s - t) < skip && s < end);
4326 }
4327 }
4328 else {
4329# if OPT_EXACT_MAXLEN >= ONIG_CHAR_TABLE_SIZE
4330 while (s < end) {
4331 p = se = s + tlen1;
4332 t = tail;
4333 while (*p == *t) {
4334 if (t == target) return (UChar* )s;
4335 p--; t--;
4336 }
4337 skip = reg->int_map[*se];
4338 t = s;
4339 do {
4340 s += enclen(reg->enc, s, end);
4341 } while ((s - t) < skip && s < end);
4342 }
4343# endif
4344 }
4345
4346 return (UChar* )NULL;
4347}
4348
4349/* Boyer-Moore-Horspool search */
4350static UChar*
4351bm_search(regex_t* reg, const UChar* target, const UChar* target_end,
4352 const UChar* text, const UChar* text_end, const UChar* text_range)
4353{
4354 const UChar *s, *t, *p, *end;
4355 const UChar *tail;
4356
4357# ifdef ONIG_DEBUG_SEARCH
4358 fprintf(stderr, "bm_search: text: %"PRIuPTR" (%p), text_end: %"PRIuPTR" (%p), text_range: %"PRIuPTR" (%p)\n",
4359 (uintptr_t )text, text, (uintptr_t )text_end, text_end, (uintptr_t )text_range, text_range);
4360# endif
4361
4362 end = text_range + (target_end - target) - 1;
4363 if (end > text_end)
4364 end = text_end;
4365
4366 tail = target_end - 1;
4367 s = text + (target_end - target) - 1;
4368 if (IS_NULL(reg->int_map)) {
4369 while (s < end) {
4370 p = s;
4371 t = tail;
4372# ifdef ONIG_DEBUG_SEARCH
4373 fprintf(stderr, "bm_search_loop: pos: %"PRIdPTR" %s\n",
4374 (intptr_t )(s - text), s);
4375# endif
4376 while (*p == *t) {
4377 if (t == target) return (UChar* )p;
4378 p--; t--;
4379 }
4380 s += reg->map[*s];
4381 }
4382 }
4383 else { /* see int_map[] */
4384# if OPT_EXACT_MAXLEN >= ONIG_CHAR_TABLE_SIZE
4385 while (s < end) {
4386 p = s;
4387 t = tail;
4388 while (*p == *t) {
4389 if (t == target) return (UChar* )p;
4390 p--; t--;
4391 }
4392 s += reg->int_map[*s];
4393 }
4394# endif
4395 }
4396 return (UChar* )NULL;
4397}
4398
4399/* Boyer-Moore-Horspool search applied to a multibyte string (ignore case) */
4400static UChar*
4401bm_search_notrev_ic(regex_t* reg, const UChar* target, const UChar* target_end,
4402 const UChar* text, const UChar* text_end,
4403 const UChar* text_range)
4404{
4405 const UChar *s, *se, *t, *end;
4406 const UChar *tail;
4407 ptrdiff_t skip, tlen1;
4408 OnigEncoding enc = reg->enc;
4409 int case_fold_flag = reg->case_fold_flag;
4410
4411# ifdef ONIG_DEBUG_SEARCH
4412 fprintf(stderr, "bm_search_notrev_ic: text: %d (%p), text_end: %d (%p), text_range: %d (%p)\n",
4413 (int )text, text, (int )text_end, text_end, (int )text_range, text_range);
4414# endif
4415
4416 tail = target_end - 1;
4417 tlen1 = tail - target;
4418 end = text_range;
4419 if (end + tlen1 > text_end)
4420 end = text_end - tlen1;
4421
4422 s = text;
4423
4424 if (IS_NULL(reg->int_map)) {
4425 while (s < end) {
4426 se = s + tlen1;
4427 if (str_lower_case_match(enc, case_fold_flag, target, target_end,
4428 s, se + 1))
4429 return (UChar* )s;
4430 skip = reg->map[*se];
4431 t = s;
4432 do {
4433 s += enclen(reg->enc, s, end);
4434 } while ((s - t) < skip && s < end);
4435 }
4436 }
4437 else {
4438# if OPT_EXACT_MAXLEN >= ONIG_CHAR_TABLE_SIZE
4439 while (s < end) {
4440 se = s + tlen1;
4441 if (str_lower_case_match(enc, case_fold_flag, target, target_end,
4442 s, se + 1))
4443 return (UChar* )s;
4444 skip = reg->int_map[*se];
4445 t = s;
4446 do {
4447 s += enclen(reg->enc, s, end);
4448 } while ((s - t) < skip && s < end);
4449 }
4450# endif
4451 }
4452
4453 return (UChar* )NULL;
4454}
4455
4456/* Boyer-Moore-Horspool search (ignore case) */
4457static UChar*
4458bm_search_ic(regex_t* reg, const UChar* target, const UChar* target_end,
4459 const UChar* text, const UChar* text_end, const UChar* text_range)
4460{
4461 const UChar *s, *p, *end;
4462 const UChar *tail;
4463 OnigEncoding enc = reg->enc;
4464 int case_fold_flag = reg->case_fold_flag;
4465
4466# ifdef ONIG_DEBUG_SEARCH
4467 fprintf(stderr, "bm_search_ic: text: %d (%p), text_end: %d (%p), text_range: %d (%p)\n",
4468 (int )text, text, (int )text_end, text_end, (int )text_range, text_range);
4469# endif
4470
4471 end = text_range + (target_end - target) - 1;
4472 if (end > text_end)
4473 end = text_end;
4474
4475 tail = target_end - 1;
4476 s = text + (target_end - target) - 1;
4477 if (IS_NULL(reg->int_map)) {
4478 while (s < end) {
4479 p = s - (target_end - target) + 1;
4480 if (str_lower_case_match(enc, case_fold_flag, target, target_end,
4481 p, s + 1))
4482 return (UChar* )p;
4483 s += reg->map[*s];
4484 }
4485 }
4486 else { /* see int_map[] */
4487# if OPT_EXACT_MAXLEN >= ONIG_CHAR_TABLE_SIZE
4488 while (s < end) {
4489 p = s - (target_end - target) + 1;
4490 if (str_lower_case_match(enc, case_fold_flag, target, target_end,
4491 p, s + 1))
4492 return (UChar* )p;
4493 s += reg->int_map[*s];
4494 }
4495# endif
4496 }
4497 return (UChar* )NULL;
4498}
4499
4500#else /* USE_SUNDAY_QUICK_SEARCH */
4501
4502/* Sunday's quick search applied to a multibyte string */
4503static UChar*
4504bm_search_notrev(regex_t* reg, const UChar* target, const UChar* target_end,
4505 const UChar* text, const UChar* text_end,
4506 const UChar* text_range)
4507{
4508 const UChar *s, *se, *t, *p, *end;
4509 const UChar *tail;
4510 ptrdiff_t skip, tlen1;
4511 OnigEncoding enc = reg->enc;
4512
4513# ifdef ONIG_DEBUG_SEARCH
4514 fprintf(stderr, "bm_search_notrev: text: %"PRIuPTR" (%p), text_end: %"PRIuPTR" (%p), text_range: %"PRIuPTR" (%p)\n",
4515 (uintptr_t )text, text, (uintptr_t )text_end, text_end, (uintptr_t )text_range, text_range);
4516# endif
4517
4518 tail = target_end - 1;
4519 tlen1 = tail - target;
4520 end = text_range;
4521 if (end + tlen1 > text_end)
4522 end = text_end - tlen1;
4523
4524 s = text;
4525
4526 if (IS_NULL(reg->int_map)) {
4527 while (s < end) {
4528 p = se = s + tlen1;
4529 t = tail;
4530 while (*p == *t) {
4531 if (t == target) return (UChar* )s;
4532 p--; t--;
4533 }
4534 if (s + 1 >= end) break;
4535 skip = reg->map[se[1]];
4536 t = s;
4537 do {
4538 s += enclen(enc, s, end);
4539 } while ((s - t) < skip && s < end);
4540 }
4541 }
4542 else {
4543# if OPT_EXACT_MAXLEN >= ONIG_CHAR_TABLE_SIZE
4544 while (s < end) {
4545 p = se = s + tlen1;
4546 t = tail;
4547 while (*p == *t) {
4548 if (t == target) return (UChar* )s;
4549 p--; t--;
4550 }
4551 if (s + 1 >= end) break;
4552 skip = reg->int_map[se[1]];
4553 t = s;
4554 do {
4555 s += enclen(enc, s, end);
4556 } while ((s - t) < skip && s < end);
4557 }
4558# endif
4559 }
4560
4561 return (UChar* )NULL;
4562}
4563
4564/* Sunday's quick search */
4565static UChar*
4566bm_search(regex_t* reg, const UChar* target, const UChar* target_end,
4567 const UChar* text, const UChar* text_end, const UChar* text_range)
4568{
4569 const UChar *s, *t, *p, *end;
4570 const UChar *tail;
4571 ptrdiff_t tlen1;
4572
4573# ifdef ONIG_DEBUG_SEARCH
4574 fprintf(stderr, "bm_search: text: %"PRIuPTR" (%p), text_end: %"PRIuPTR" (%p), text_range: %"PRIuPTR" (%p)\n",
4575 (uintptr_t )text, text, (uintptr_t )text_end, text_end, (uintptr_t )text_range, text_range);
4576# endif
4577
4578 tail = target_end - 1;
4579 tlen1 = tail - target;
4580 end = text_range + tlen1;
4581 if (end > text_end)
4582 end = text_end;
4583
4584 s = text + tlen1;
4585 if (IS_NULL(reg->int_map)) {
4586 while (s < end) {
4587 p = s;
4588 t = tail;
4589 while (*p == *t) {
4590 if (t == target) return (UChar* )p;
4591 p--; t--;
4592 }
4593 if (s + 1 >= end) break;
4594 s += reg->map[s[1]];
4595 }
4596 }
4597 else { /* see int_map[] */
4598# if OPT_EXACT_MAXLEN >= ONIG_CHAR_TABLE_SIZE
4599 while (s < end) {
4600 p = s;
4601 t = tail;
4602 while (*p == *t) {
4603 if (t == target) return (UChar* )p;
4604 p--; t--;
4605 }
4606 if (s + 1 >= end) break;
4607 s += reg->int_map[s[1]];
4608 }
4609# endif
4610 }
4611 return (UChar* )NULL;
4612}
4613
4614/* Sunday's quick search applied to a multibyte string (ignore case) */
4615static UChar*
4616bm_search_notrev_ic(regex_t* reg, const UChar* target, const UChar* target_end,
4617 const UChar* text, const UChar* text_end,
4618 const UChar* text_range)
4619{
4620 const UChar *s, *se, *t, *end;
4621 const UChar *tail;
4622 ptrdiff_t skip, tlen1;
4623 OnigEncoding enc = reg->enc;
4624 int case_fold_flag = reg->case_fold_flag;
4625
4626# ifdef ONIG_DEBUG_SEARCH
4627 fprintf(stderr, "bm_search_notrev_ic: text: %"PRIuPTR" (%p), text_end: %"PRIuPTR" (%p), text_range: %"PRIuPTR" (%p)\n",
4628 (uintptr_t )text, text, (uintptr_t )text_end, text_end, (uintptr_t )text_range, text_range);
4629# endif
4630
4631 tail = target_end - 1;
4632 tlen1 = tail - target;
4633 end = text_range;
4634 if (end + tlen1 > text_end)
4635 end = text_end - tlen1;
4636
4637 s = text;
4638
4639 if (IS_NULL(reg->int_map)) {
4640 while (s < end) {
4641 se = s + tlen1;
4642 if (str_lower_case_match(enc, case_fold_flag, target, target_end,
4643 s, se + 1))
4644 return (UChar* )s;
4645 if (s + 1 >= end) break;
4646 skip = reg->map[se[1]];
4647 t = s;
4648 do {
4649 s += enclen(enc, s, end);
4650 } while ((s - t) < skip && s < end);
4651 }
4652 }
4653 else {
4654# if OPT_EXACT_MAXLEN >= ONIG_CHAR_TABLE_SIZE
4655 while (s < end) {
4656 se = s + tlen1;
4657 if (str_lower_case_match(enc, case_fold_flag, target, target_end,
4658 s, se + 1))
4659 return (UChar* )s;
4660 if (s + 1 >= end) break;
4661 skip = reg->int_map[se[1]];
4662 t = s;
4663 do {
4664 s += enclen(enc, s, end);
4665 } while ((s - t) < skip && s < end);
4666 }
4667# endif
4668 }
4669
4670 return (UChar* )NULL;
4671}
4672
4673/* Sunday's quick search (ignore case) */
4674static UChar*
4675bm_search_ic(regex_t* reg, const UChar* target, const UChar* target_end,
4676 const UChar* text, const UChar* text_end, const UChar* text_range)
4677{
4678 const UChar *s, *p, *end;
4679 const UChar *tail;
4680 ptrdiff_t tlen1;
4681 OnigEncoding enc = reg->enc;
4682 int case_fold_flag = reg->case_fold_flag;
4683
4684# ifdef ONIG_DEBUG_SEARCH
4685 fprintf(stderr, "bm_search_ic: text: %"PRIuPTR" (%p), text_end: %"PRIuPTR" (%p), text_range: %"PRIuPTR" (%p)\n",
4686 (uintptr_t )text, text, (uintptr_t )text_end, text_end, (uintptr_t )text_range, text_range);
4687# endif
4688
4689 tail = target_end - 1;
4690 tlen1 = tail - target;
4691 end = text_range + tlen1;
4692 if (end > text_end)
4693 end = text_end;
4694
4695 s = text + tlen1;
4696 if (IS_NULL(reg->int_map)) {
4697 while (s < end) {
4698 p = s - tlen1;
4699 if (str_lower_case_match(enc, case_fold_flag, target, target_end,
4700 p, s + 1))
4701 return (UChar* )p;
4702 if (s + 1 >= end) break;
4703 s += reg->map[s[1]];
4704 }
4705 }
4706 else { /* see int_map[] */
4707# if OPT_EXACT_MAXLEN >= ONIG_CHAR_TABLE_SIZE
4708 while (s < end) {
4709 p = s - tlen1;
4710 if (str_lower_case_match(enc, case_fold_flag, target, target_end,
4711 p, s + 1))
4712 return (UChar* )p;
4713 if (s + 1 >= end) break;
4714 s += reg->int_map[s[1]];
4715 }
4716# endif
4717 }
4718 return (UChar* )NULL;
4719}
4720#endif /* USE_SUNDAY_QUICK_SEARCH */
4721
4722#ifdef USE_INT_MAP_BACKWARD
4723static int
4724set_bm_backward_skip(UChar* s, UChar* end, OnigEncoding enc ARG_UNUSED,
4725 int** skip)
4726{
4727 int i, len;
4728
4729 if (IS_NULL(*skip)) {
4730 *skip = (int* )xmalloc(sizeof(int) * ONIG_CHAR_TABLE_SIZE);
4731 if (IS_NULL(*skip)) return ONIGERR_MEMORY;
4732 }
4733
4734 len = (int )(end - s);
4735 for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++)
4736 (*skip)[i] = len;
4737
4738 for (i = len - 1; i > 0; i--)
4739 (*skip)[s[i]] = i;
4740
4741 return 0;
4742}
4743
4744static UChar*
4745bm_search_backward(regex_t* reg, const UChar* target, const UChar* target_end,
4746 const UChar* text, const UChar* adjust_text,
4747 const UChar* text_end, const UChar* text_start)
4748{
4749 const UChar *s, *t, *p;
4750
4751 s = text_end - (target_end - target);
4752 if (text_start < s)
4753 s = text_start;
4754 else
4755 s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, adjust_text, s, text_end);
4756
4757 while (s >= text) {
4758 p = s;
4759 t = target;
4760 while (t < target_end && *p == *t) {
4761 p++; t++;
4762 }
4763 if (t == target_end)
4764 return (UChar* )s;
4765
4766 s -= reg->int_map_backward[*s];
4767 s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, adjust_text, s, text_end);
4768 }
4769
4770 return (UChar* )NULL;
4771}
4772#endif
4773
4774static UChar*
4775map_search(OnigEncoding enc, UChar map[],
4776 const UChar* text, const UChar* text_range, const UChar* text_end)
4777{
4778 const UChar *s = text;
4779
4780 while (s < text_range) {
4781 if (map[*s]) return (UChar* )s;
4782
4783 s += enclen(enc, s, text_end);
4784 }
4785 return (UChar* )NULL;
4786}
4787
4788static UChar*
4789map_search_backward(OnigEncoding enc, UChar map[],
4790 const UChar* text, const UChar* adjust_text,
4791 const UChar* text_start, const UChar* text_end)
4792{
4793 const UChar *s = text_start;
4794
4795 while (s >= text) {
4796 if (map[*s]) return (UChar* )s;
4797
4798 s = onigenc_get_prev_char_head(enc, adjust_text, s, text_end);
4799 }
4800 return (UChar* )NULL;
4801}
4802
4803extern OnigPosition
4804onig_match(regex_t* reg, const UChar* str, const UChar* end, const UChar* at, OnigRegion* region,
4805 OnigOptionType option)
4806{
4807 ptrdiff_t r;
4808 UChar *prev;
4809 OnigMatchArg msa;
4810
4811 MATCH_ARG_INIT(msa, option, region, at, at);
4812#ifdef USE_COMBINATION_EXPLOSION_CHECK
4813 {
4814 ptrdiff_t offset = at - str;
4815 STATE_CHECK_BUFF_INIT(msa, end - str, offset, reg->num_comb_exp_check);
4816 }
4817#endif
4818
4819 if (region) {
4820 r = onig_region_resize_clear(region, reg->num_mem + 1);
4821 }
4822 else
4823 r = 0;
4824
4825 if (r == 0) {
4826 prev = (UChar* )onigenc_get_prev_char_head(reg->enc, str, at, end);
4827 r = match_at(reg, str, end,
4828#ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE
4829 end,
4830#endif
4831 at, prev, &msa);
4832 }
4833
4834 MATCH_ARG_FREE(msa);
4835 return r;
4836}
4837
4838static int
4839forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
4840 UChar* range, UChar** low, UChar** high, UChar** low_prev)
4841{
4842 UChar *p, *pprev = (UChar* )NULL;
4843
4844#ifdef ONIG_DEBUG_SEARCH
4845 fprintf(stderr, "forward_search_range: str: %"PRIuPTR" (%p), end: %"PRIuPTR" (%p), s: %"PRIuPTR" (%p), range: %"PRIuPTR" (%p)\n",
4846 (uintptr_t )str, str, (uintptr_t )end, end, (uintptr_t )s, s, (uintptr_t )range, range);
4847#endif
4848
4849 p = s;
4850 if (reg->dmin > 0) {
4851 if (ONIGENC_IS_SINGLEBYTE(reg->enc)) {
4852 p += reg->dmin;
4853 }
4854 else {
4855 UChar *q = p + reg->dmin;
4856
4857 if (q >= end) return 0; /* fail */
4858 while (p < q) p += enclen(reg->enc, p, end);
4859 }
4860 }
4861
4862 retry:
4863 switch (reg->optimize) {
4864 case ONIG_OPTIMIZE_EXACT:
4865 p = slow_search(reg->enc, reg->exact, reg->exact_end, p, end, range);
4866 break;
4867 case ONIG_OPTIMIZE_EXACT_IC:
4868 p = slow_search_ic(reg->enc, reg->case_fold_flag,
4869 reg->exact, reg->exact_end, p, end, range);
4870 break;
4871
4872 case ONIG_OPTIMIZE_EXACT_BM:
4873 p = bm_search(reg, reg->exact, reg->exact_end, p, end, range);
4874 break;
4875
4876 case ONIG_OPTIMIZE_EXACT_BM_NOT_REV:
4877 p = bm_search_notrev(reg, reg->exact, reg->exact_end, p, end, range);
4878 break;
4879
4880 case ONIG_OPTIMIZE_EXACT_BM_IC:
4881 p = bm_search_ic(reg, reg->exact, reg->exact_end, p, end, range);
4882 break;
4883
4884 case ONIG_OPTIMIZE_EXACT_BM_NOT_REV_IC:
4885 p = bm_search_notrev_ic(reg, reg->exact, reg->exact_end, p, end, range);
4886 break;
4887
4888 case ONIG_OPTIMIZE_MAP:
4889 p = map_search(reg->enc, reg->map, p, range, end);
4890 break;
4891 }
4892
4893 if (p && p < range) {
4894 if (p - reg->dmin < s) {
4895 retry_gate:
4896 pprev = p;
4897 p += enclen(reg->enc, p, end);
4898 goto retry;
4899 }
4900
4901 if (reg->sub_anchor) {
4902 UChar* prev;
4903
4904 switch (reg->sub_anchor) {
4905 case ANCHOR_BEGIN_LINE:
4906 if (!ON_STR_BEGIN(p)) {
4907 prev = onigenc_get_prev_char_head(reg->enc,
4908 (pprev ? pprev : str), p, end);
4909 if (!ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, prev, str, end, reg->options, 0))
4910 goto retry_gate;
4911 }
4912 break;
4913
4914 case ANCHOR_END_LINE:
4915 if (ON_STR_END(p)) {
4916#ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE
4917 prev = (UChar* )onigenc_get_prev_char_head(reg->enc,
4918 (pprev ? pprev : str), p);
4919 if (prev && ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, prev, str, end, reg->options, 1))
4920 goto retry_gate;
4921#endif
4922 }
4923 else if (! ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, p, str, end, reg->options, 1))
4924 goto retry_gate;
4925 break;
4926 }
4927 }
4928
4929 if (reg->dmax == 0) {
4930 *low = p;
4931 if (low_prev) {
4932 if (*low > s)
4933 *low_prev = onigenc_get_prev_char_head(reg->enc, s, p, end);
4934 else
4935 *low_prev = onigenc_get_prev_char_head(reg->enc,
4936 (pprev ? pprev : str), p, end);
4937 }
4938 }
4939 else {
4940 if (reg->dmax != ONIG_INFINITE_DISTANCE) {
4941 if (p < str + reg->dmax) {
4942 *low = (UChar* )str;
4943 if (low_prev)
4944 *low_prev = onigenc_get_prev_char_head(reg->enc, str, *low, end);
4945 }
4946 else {
4947 *low = p - reg->dmax;
4948 if (*low > s) {
4949 *low = onigenc_get_right_adjust_char_head_with_prev(reg->enc, s,
4950 *low, end, (const UChar** )low_prev);
4951 if (low_prev && IS_NULL(*low_prev))
4952 *low_prev = onigenc_get_prev_char_head(reg->enc,
4953 (pprev ? pprev : s), *low, end);
4954 }
4955 else {
4956 if (low_prev)
4957 *low_prev = onigenc_get_prev_char_head(reg->enc,
4958 (pprev ? pprev : str), *low, end);
4959 }
4960 }
4961 }
4962 }
4963 /* no needs to adjust *high, *high is used as range check only */
4964 *high = p - reg->dmin;
4965
4966#ifdef ONIG_DEBUG_SEARCH
4967 fprintf(stderr,
4968 "forward_search_range success: low: %"PRIdPTR", high: %"PRIdPTR", dmin: %"PRIdPTR", dmax: %"PRIdPTR"\n",
4969 *low - str, *high - str, reg->dmin, reg->dmax);
4970#endif
4971 return 1; /* success */
4972 }
4973
4974 return 0; /* fail */
4975}
4976
4977#define BM_BACKWARD_SEARCH_LENGTH_THRESHOLD 100
4978
4979static int
4980backward_search_range(regex_t* reg, const UChar* str, const UChar* end,
4981 UChar* s, const UChar* range, UChar* adjrange,
4982 UChar** low, UChar** high)
4983{
4984 UChar *p;
4985
4986 range += reg->dmin;
4987 p = s;
4988
4989 retry:
4990 switch (reg->optimize) {
4991 case ONIG_OPTIMIZE_EXACT:
4992 exact_method:
4993 p = slow_search_backward(reg->enc, reg->exact, reg->exact_end,
4994 range, adjrange, end, p);
4995 break;
4996
4997 case ONIG_OPTIMIZE_EXACT_IC:
4998 case ONIG_OPTIMIZE_EXACT_BM_IC:
4999 case ONIG_OPTIMIZE_EXACT_BM_NOT_REV_IC:
5000 p = slow_search_backward_ic(reg->enc, reg->case_fold_flag,
5001 reg->exact, reg->exact_end,
5002 range, adjrange, end, p);
5003 break;
5004
5005 case ONIG_OPTIMIZE_EXACT_BM:
5006 case ONIG_OPTIMIZE_EXACT_BM_NOT_REV:
5007#ifdef USE_INT_MAP_BACKWARD
5008 if (IS_NULL(reg->int_map_backward)) {
5009 int r;
5010 if (s - range < BM_BACKWARD_SEARCH_LENGTH_THRESHOLD)
5011 goto exact_method;
5012
5013 r = set_bm_backward_skip(reg->exact, reg->exact_end, reg->enc,
5014 &(reg->int_map_backward));
5015 if (r) return r;
5016 }
5017 p = bm_search_backward(reg, reg->exact, reg->exact_end, range, adjrange,
5018 end, p);
5019#else
5020 goto exact_method;
5021#endif
5022 break;
5023
5024 case ONIG_OPTIMIZE_MAP:
5025 p = map_search_backward(reg->enc, reg->map, range, adjrange, p, end);
5026 break;
5027 }
5028
5029 if (p) {
5030 if (reg->sub_anchor) {
5031 UChar* prev;
5032
5033 switch (reg->sub_anchor) {
5034 case ANCHOR_BEGIN_LINE:
5035 if (!ON_STR_BEGIN(p)) {
5036 prev = onigenc_get_prev_char_head(reg->enc, str, p, end);
5037 if (!ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, prev, str, end, reg->options, 0)) {
5038 p = prev;
5039 goto retry;
5040 }
5041 }
5042 break;
5043
5044 case ANCHOR_END_LINE:
5045 if (ON_STR_END(p)) {
5046#ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE
5047 prev = onigenc_get_prev_char_head(reg->enc, adjrange, p);
5048 if (IS_NULL(prev)) goto fail;
5049 if (ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, prev, str, end, reg->options, 1)) {
5050 p = prev;
5051 goto retry;
5052 }
5053#endif
5054 }
5055 else if (! ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, p, str, end, reg->options, 1)) {
5056 p = onigenc_get_prev_char_head(reg->enc, adjrange, p, end);
5057 if (IS_NULL(p)) goto fail;
5058 goto retry;
5059 }
5060 break;
5061 }
5062 }
5063
5064 /* no needs to adjust *high, *high is used as range check only */
5065 if (reg->dmax != ONIG_INFINITE_DISTANCE) {
5066 *low = p - reg->dmax;
5067 *high = p - reg->dmin;
5068 *high = onigenc_get_right_adjust_char_head(reg->enc, adjrange, *high, end);
5069 }
5070
5071#ifdef ONIG_DEBUG_SEARCH
5072 fprintf(stderr, "backward_search_range: low: %d, high: %d\n",
5073 (int )(*low - str), (int )(*high - str));
5074#endif
5075 return 1; /* success */
5076 }
5077
5078 fail:
5079#ifdef ONIG_DEBUG_SEARCH
5080 fprintf(stderr, "backward_search_range: fail.\n");
5081#endif
5082 return 0; /* fail */
5083}
5084
5085
5086extern OnigPosition
5087onig_search(regex_t* reg, const UChar* str, const UChar* end,
5088 const UChar* start, const UChar* range, OnigRegion* region, OnigOptionType option)
5089{
5090 return onig_search_gpos(reg, str, end, start, start, range, region, option);
5091}
5092
5093extern OnigPosition
5094onig_search_gpos(regex_t* reg, const UChar* str, const UChar* end,
5095 const UChar* global_pos,
5096 const UChar* start, const UChar* range, OnigRegion* region, OnigOptionType option)
5097{
5098 ptrdiff_t r;
5099 UChar *s, *prev;
5100 OnigMatchArg msa;
5101#ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE
5102 const UChar *orig_start = start;
5103 const UChar *orig_range = range;
5104#endif
5105
5106#ifdef ONIG_DEBUG_SEARCH
5107 fprintf(stderr,
5108 "onig_search (entry point): str: %"PRIuPTR" (%p), end: %"PRIuPTR", start: %"PRIuPTR", range: %"PRIuPTR"\n",
5109 (uintptr_t )str, str, end - str, start - str, range - str);
5110#endif
5111
5112 if (region) {
5113 r = onig_region_resize_clear(region, reg->num_mem + 1);
5114 if (r) goto finish_no_msa;
5115 }
5116
5117 if (start > end || start < str) goto mismatch_no_msa;
5118
5119
5120#ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE
5121# ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE
5122# define MATCH_AND_RETURN_CHECK(upper_range) \
5123 r = match_at(reg, str, end, (upper_range), s, prev, &msa); \
5124 if (r != ONIG_MISMATCH) {\
5125 if (r >= 0) {\
5126 if (! IS_FIND_LONGEST(reg->options)) {\
5127 goto match;\
5128 }\
5129 }\
5130 else goto finish; /* error */ \
5131 }
5132# else
5133# define MATCH_AND_RETURN_CHECK(upper_range) \
5134 r = match_at(reg, str, end, (upper_range), s, prev, &msa); \
5135 if (r != ONIG_MISMATCH) {\
5136 if (r >= 0) {\
5137 goto match;\
5138 }\
5139 else goto finish; /* error */ \
5140 }
5141# endif /* USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE */
5142#else
5143# ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE
5144# define MATCH_AND_RETURN_CHECK(none) \
5145 r = match_at(reg, str, end, s, prev, &msa);\
5146 if (r != ONIG_MISMATCH) {\
5147 if (r >= 0) {\
5148 if (! IS_FIND_LONGEST(reg->options)) {\
5149 goto match;\
5150 }\
5151 }\
5152 else goto finish; /* error */ \
5153 }
5154# else
5155# define MATCH_AND_RETURN_CHECK(none) \
5156 r = match_at(reg, str, end, s, prev, &msa);\
5157 if (r != ONIG_MISMATCH) {\
5158 if (r >= 0) {\
5159 goto match;\
5160 }\
5161 else goto finish; /* error */ \
5162 }
5163# endif /* USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE */
5164#endif /* USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE */
5165
5166
5167 /* anchor optimize: resume search range */
5168 if (reg->anchor != 0 && str < end) {
5169 UChar *min_semi_end, *max_semi_end;
5170
5171 if (reg->anchor & ANCHOR_BEGIN_POSITION) {
5172 /* search start-position only */
5173 begin_position:
5174 if (range > start)
5175 {
5176 if (global_pos > start)
5177 {
5178 if (global_pos < range)
5179 range = global_pos + 1;
5180 }
5181 else
5182 range = start + 1;
5183 }
5184 else
5185 range = start;
5186 }
5187 else if (reg->anchor & ANCHOR_BEGIN_BUF) {
5188 /* search str-position only */
5189 if (range > start) {
5190 if (start != str) goto mismatch_no_msa;
5191 range = str + 1;
5192 }
5193 else {
5194 if (range <= str) {
5195 start = str;
5196 range = str;
5197 }
5198 else
5199 goto mismatch_no_msa;
5200 }
5201 }
5202 else if (reg->anchor & ANCHOR_END_BUF) {
5203 min_semi_end = max_semi_end = (UChar* )end;
5204
5205 end_buf:
5206 if ((OnigDistance )(max_semi_end - str) < reg->anchor_dmin)
5207 goto mismatch_no_msa;
5208
5209 if (range > start) {
5210 if ((OnigDistance )(min_semi_end - start) > reg->anchor_dmax) {
5211 start = min_semi_end - reg->anchor_dmax;
5212 if (start < end)
5213 start = onigenc_get_right_adjust_char_head(reg->enc, str, start, end);
5214 }
5215 if ((OnigDistance )(max_semi_end - (range - 1)) < reg->anchor_dmin) {
5216 range = max_semi_end - reg->anchor_dmin + 1;
5217 }
5218
5219 if (start > range) goto mismatch_no_msa;
5220 /* If start == range, match with empty at end.
5221 Backward search is used. */
5222 }
5223 else {
5224 if ((OnigDistance )(min_semi_end - range) > reg->anchor_dmax) {
5225 range = min_semi_end - reg->anchor_dmax;
5226 }
5227 if ((OnigDistance )(max_semi_end - start) < reg->anchor_dmin) {
5228 start = max_semi_end - reg->anchor_dmin;
5229 start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, start, end);
5230 }
5231 if (range > start) goto mismatch_no_msa;
5232 }
5233 }
5234 else if (reg->anchor & ANCHOR_SEMI_END_BUF) {
5235 UChar* pre_end = ONIGENC_STEP_BACK(reg->enc, str, end, end, 1);
5236
5237 max_semi_end = (UChar* )end;
5238 if (ONIGENC_IS_MBC_NEWLINE(reg->enc, pre_end, end)) {
5239 min_semi_end = pre_end;
5240
5241#ifdef USE_CRNL_AS_LINE_TERMINATOR
5242 pre_end = ONIGENC_STEP_BACK(reg->enc, str, pre_end, end, 1);
5243 if (IS_NOT_NULL(pre_end) &&
5244 IS_NEWLINE_CRLF(reg->options) &&
5245 ONIGENC_IS_MBC_CRNL(reg->enc, pre_end, end)) {
5246 min_semi_end = pre_end;
5247 }
5248#endif
5249 if (min_semi_end > str && start <= min_semi_end) {
5250 goto end_buf;
5251 }
5252 }
5253 else {
5254 min_semi_end = (UChar* )end;
5255 goto end_buf;
5256 }
5257 }
5258 else if ((reg->anchor & ANCHOR_ANYCHAR_STAR_ML)) {
5259 goto begin_position;
5260 }
5261 }
5262 else if (str == end) { /* empty string */
5263 static const UChar address_for_empty_string[] = "";
5264
5265#ifdef ONIG_DEBUG_SEARCH
5266 fprintf(stderr, "onig_search: empty string.\n");
5267#endif
5268
5269 if (reg->threshold_len == 0) {
5270 start = end = str = address_for_empty_string;
5271 s = (UChar* )start;
5272 prev = (UChar* )NULL;
5273
5274 MATCH_ARG_INIT(msa, option, region, start, start);
5275#ifdef USE_COMBINATION_EXPLOSION_CHECK
5276 msa.state_check_buff = (void* )0;
5277 msa.state_check_buff_size = 0; /* NO NEED, for valgrind */
5278#endif
5279 MATCH_AND_RETURN_CHECK(end);
5280 goto mismatch;
5281 }
5282 goto mismatch_no_msa;
5283 }
5284
5285#ifdef ONIG_DEBUG_SEARCH
5286 fprintf(stderr, "onig_search(apply anchor): end: %d, start: %d, range: %d\n",
5287 (int )(end - str), (int )(start - str), (int )(range - str));
5288#endif
5289
5290 MATCH_ARG_INIT(msa, option, region, start, global_pos);
5291#ifdef USE_COMBINATION_EXPLOSION_CHECK
5292 {
5293 ptrdiff_t offset = (MIN(start, range) - str);
5294 STATE_CHECK_BUFF_INIT(msa, end - str, offset, reg->num_comb_exp_check);
5295 }
5296#endif
5297
5298 s = (UChar* )start;
5299 if (range > start) { /* forward search */
5300 if (s > str)
5301 prev = onigenc_get_prev_char_head(reg->enc, str, s, end);
5302 else
5303 prev = (UChar* )NULL;
5304
5305 if (reg->optimize != ONIG_OPTIMIZE_NONE) {
5306 UChar *sch_range, *low, *high, *low_prev;
5307
5308 sch_range = (UChar* )range;
5309 if (reg->dmax != 0) {
5310 if (reg->dmax == ONIG_INFINITE_DISTANCE)
5311 sch_range = (UChar* )end;
5312 else {
5313 sch_range += reg->dmax;
5314 if (sch_range > end) sch_range = (UChar* )end;
5315 }
5316 }
5317
5318 if ((end - start) < reg->threshold_len)
5319 goto mismatch;
5320
5321 if (reg->dmax != ONIG_INFINITE_DISTANCE) {
5322 do {
5323 if (! forward_search_range(reg, str, end, s, sch_range,
5324 &low, &high, &low_prev)) goto mismatch;
5325 if (s < low) {
5326 s = low;
5327 prev = low_prev;
5328 }
5329 while (s <= high) {
5330 MATCH_AND_RETURN_CHECK(orig_range);
5331 prev = s;
5332 s += enclen(reg->enc, s, end);
5333 }
5334 } while (s < range);
5335 goto mismatch;
5336 }
5337 else { /* check only. */
5338 if (! forward_search_range(reg, str, end, s, sch_range,
5339 &low, &high, (UChar** )NULL)) goto mismatch;
5340
5341 if ((reg->anchor & ANCHOR_ANYCHAR_STAR) != 0) {
5342 do {
5343 MATCH_AND_RETURN_CHECK(orig_range);
5344 prev = s;
5345 s += enclen(reg->enc, s, end);
5346
5347 if ((reg->anchor & (ANCHOR_LOOK_BEHIND | ANCHOR_PREC_READ_NOT)) == 0) {
5348 while (!ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, prev, str, end, reg->options, 0)
5349 && s < range) {
5350 prev = s;
5351 s += enclen(reg->enc, s, end);
5352 }
5353 }
5354 } while (s < range);
5355 goto mismatch;
5356 }
5357 }
5358 }
5359
5360 do {
5361 MATCH_AND_RETURN_CHECK(orig_range);
5362 prev = s;
5363 s += enclen(reg->enc, s, end);
5364 } while (s < range);
5365
5366 if (s == range) { /* because empty match with /$/. */
5367 MATCH_AND_RETURN_CHECK(orig_range);
5368 }
5369 }
5370 else { /* backward search */
5371 if (reg->optimize != ONIG_OPTIMIZE_NONE) {
5372 UChar *low, *high, *adjrange, *sch_start;
5373
5374 if (range < end)
5375 adjrange = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, range, end);
5376 else
5377 adjrange = (UChar* )end;
5378
5379 if (reg->dmax != ONIG_INFINITE_DISTANCE &&
5380 (end - range) >= reg->threshold_len) {
5381 do {
5382 sch_start = s + reg->dmax;
5383 if (sch_start > end) sch_start = (UChar* )end;
5384 if (backward_search_range(reg, str, end, sch_start, range, adjrange,
5385 &low, &high) <= 0)
5386 goto mismatch;
5387
5388 if (s > high)
5389 s = high;
5390
5391 while (s >= low) {
5392 prev = onigenc_get_prev_char_head(reg->enc, str, s, end);
5393 MATCH_AND_RETURN_CHECK(orig_start);
5394 s = prev;
5395 }
5396 } while (s >= range);
5397 goto mismatch;
5398 }
5399 else { /* check only. */
5400 if ((end - range) < reg->threshold_len) goto mismatch;
5401
5402 sch_start = s;
5403 if (reg->dmax != 0) {
5404 if (reg->dmax == ONIG_INFINITE_DISTANCE)
5405 sch_start = (UChar* )end;
5406 else {
5407 sch_start += reg->dmax;
5408 if (sch_start > end) sch_start = (UChar* )end;
5409 else
5410 sch_start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc,
5411 start, sch_start, end);
5412 }
5413 }
5414 if (backward_search_range(reg, str, end, sch_start, range, adjrange,
5415 &low, &high) <= 0) goto mismatch;
5416 }
5417 }
5418
5419 do {
5420 prev = onigenc_get_prev_char_head(reg->enc, str, s, end);
5421 MATCH_AND_RETURN_CHECK(orig_start);
5422 s = prev;
5423 } while (s >= range);
5424 }
5425
5426 mismatch:
5427#ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE
5428 if (IS_FIND_LONGEST(reg->options)) {
5429 if (msa.best_len >= 0) {
5430 s = msa.best_s;
5431 goto match;
5432 }
5433 }
5434#endif
5435 r = ONIG_MISMATCH;
5436
5437 finish:
5438 MATCH_ARG_FREE(msa);
5439
5440 /* If result is mismatch and no FIND_NOT_EMPTY option,
5441 then the region is not set in match_at(). */
5442 if (IS_FIND_NOT_EMPTY(reg->options) && region) {
5443 onig_region_clear(region);
5444 }
5445
5446#ifdef ONIG_DEBUG
5447 if (r != ONIG_MISMATCH)
5448 fprintf(stderr, "onig_search: error %"PRIdPTRDIFF"\n", r);
5449#endif
5450 return r;
5451
5452 mismatch_no_msa:
5453 r = ONIG_MISMATCH;
5454 finish_no_msa:
5455#ifdef ONIG_DEBUG
5456 if (r != ONIG_MISMATCH)
5457 fprintf(stderr, "onig_search: error %"PRIdPTRDIFF"\n", r);
5458#endif
5459 return r;
5460
5461 match:
5462 MATCH_ARG_FREE(msa);
5463 return s - str;
5464}
5465
5466extern OnigPosition
5467onig_scan(regex_t* reg, const UChar* str, const UChar* end,
5468 OnigRegion* region, OnigOptionType option,
5469 int (*scan_callback)(OnigPosition, OnigPosition, OnigRegion*, void*),
5470 void* callback_arg)
5471{
5472 OnigPosition r;
5473 OnigPosition n;
5474 int rs;
5475 const UChar* start;
5476
5477 n = 0;
5478 start = str;
5479 while (1) {
5480 r = onig_search(reg, str, end, start, end, region, option);
5481 if (r >= 0) {
5482 rs = scan_callback(n, r, region, callback_arg);
5483 n++;
5484 if (rs != 0)
5485 return rs;
5486
5487 if (region->end[0] == start - str) {
5488 if (start >= end) break;
5489 start += enclen(reg->enc, start, end);
5490 }
5491 else
5492 start = str + region->end[0];
5493
5494 if (start > end)
5495 break;
5496 }
5497 else if (r == ONIG_MISMATCH) {
5498 break;
5499 }
5500 else { /* error */
5501 return r;
5502 }
5503 }
5504
5505 return n;
5506}
5507
5508extern OnigEncoding
5509onig_get_encoding(const regex_t* reg)
5510{
5511 return reg->enc;
5512}
5513
5514extern OnigOptionType
5515onig_get_options(const regex_t* reg)
5516{
5517 return reg->options;
5518}
5519
5520extern OnigCaseFoldType
5521onig_get_case_fold_flag(const regex_t* reg)
5522{
5523 return reg->case_fold_flag;
5524}
5525
5526extern const OnigSyntaxType*
5527onig_get_syntax(const regex_t* reg)
5528{
5529 return reg->syntax;
5530}
5531
5532extern int
5533onig_number_of_captures(const regex_t* reg)
5534{
5535 return reg->num_mem;
5536}
5537
5538extern int
5539onig_number_of_capture_histories(const regex_t* reg)
5540{
5541#ifdef USE_CAPTURE_HISTORY
5542 int i, n;
5543
5544 n = 0;
5545 for (i = 0; i <= ONIG_MAX_CAPTURE_HISTORY_GROUP; i++) {
5546 if (BIT_STATUS_AT(reg->capture_history, i) != 0)
5547 n++;
5548 }
5549 return n;
5550#else
5551 return 0;
5552#endif
5553}
5554
5555extern void
5556onig_copy_encoding(OnigEncodingType *to, OnigEncoding from)
5557{
5558 *to = *from;
5559}
#define xfree
Old name of ruby_xfree.
Definition xmalloc.h:58
#define xrealloc
Old name of ruby_xrealloc.
Definition xmalloc.h:56
#define xmalloc
Old name of ruby_xmalloc.
Definition xmalloc.h:53
#define RB_GNUC_EXTENSION
This is expanded to nothing for non-GCC compilers.
Definition defines.h:89
int len
Length of the buffer.
Definition io.h:8
Definition win32.h:700