Ruby 4.1.0dev (2026-09-27 revision f6ff9e7d02e46360f8930b280a3dd921cccbda29)
regcomp.c (f6ff9e7d02e46360f8930b280a3dd921cccbda29)
1/**********************************************************************
2 regcomp.c - Onigmo (Oniguruma-mod) (regular expression library)
3**********************************************************************/
4/*-
5 * Copyright (c) 2002-2018 K.Kosako <sndgk393 AT ybb DOT ne DOT jp>
6 * Copyright (c) 2011-2019 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 "regparse.h"
32
33OnigCaseFoldType OnigDefaultCaseFoldFlag = ONIGENC_CASE_FOLD_MIN;
34
35extern OnigCaseFoldType
36onig_get_default_case_fold_flag(void)
37{
38 return OnigDefaultCaseFoldFlag;
39}
40
41extern int
42onig_set_default_case_fold_flag(OnigCaseFoldType case_fold_flag)
43{
44 OnigDefaultCaseFoldFlag = case_fold_flag;
45 return 0;
46}
47
48
49#ifndef PLATFORM_UNALIGNED_WORD_ACCESS
50static unsigned char PadBuf[WORD_ALIGNMENT_SIZE];
51#endif
52
53#if 0
54static UChar*
55str_dup(UChar* s, UChar* end)
56{
57 ptrdiff_t len = end - s;
58
59 if (len > 0) {
60 UChar* r = (UChar* )xmalloc(len + 1);
61 CHECK_NULL_RETURN(r);
62 xmemcpy(r, s, len);
63 r[len] = (UChar )0;
64 return r;
65 }
66 else return NULL;
67}
68#endif
69
70static void
71swap_node(Node* a, Node* b)
72{
73 Node c;
74 c = *a; *a = *b; *b = c;
75
76 if (NTYPE(a) == NT_STR) {
77 StrNode* sn = NSTR(a);
78 if (sn->capa == 0) {
79 size_t len = sn->end - sn->s;
80 sn->s = sn->buf;
81 sn->end = sn->s + len;
82 }
83 }
84
85 if (NTYPE(b) == NT_STR) {
86 StrNode* sn = NSTR(b);
87 if (sn->capa == 0) {
88 size_t len = sn->end - sn->s;
89 sn->s = sn->buf;
90 sn->end = sn->s + len;
91 }
92 }
93}
94
95static OnigDistance
96distance_add(OnigDistance d1, OnigDistance d2)
97{
98 if (d1 == ONIG_INFINITE_DISTANCE || d2 == ONIG_INFINITE_DISTANCE)
99 return ONIG_INFINITE_DISTANCE;
100 else {
101 if (d1 <= ONIG_INFINITE_DISTANCE - d2) return d1 + d2;
102 else return ONIG_INFINITE_DISTANCE;
103 }
104}
105
106static OnigDistance
107distance_multiply(OnigDistance d, int m)
108{
109 if (m == 0) return 0;
110
111 if (d < ONIG_INFINITE_DISTANCE / m)
112 return d * m;
113 else
114 return ONIG_INFINITE_DISTANCE;
115}
116
117static int
118bitset_is_empty(BitSetRef bs)
119{
120 int i;
121 for (i = 0; i < BITSET_SIZE; i++) {
122 if (bs[i] != 0) return 0;
123 }
124 return 1;
125}
126
127#ifdef ONIG_DEBUG
128static int
129bitset_on_num(BitSetRef bs)
130{
131 int i, n;
132
133 n = 0;
134 for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
135 if (BITSET_AT(bs, i)) n++;
136 }
137 return n;
138}
139#endif
140
141// Attempt to right size allocated buffers for a regex post compile
142static void
143onig_reg_resize(regex_t *reg)
144{
145 do {
146 if (!reg->used) {
147 xfree(reg->p);
148 reg->alloc = 0;
149 reg->p = 0;
150 }
151 else if (reg->alloc > reg->used) {
152 unsigned char *new_ptr = xrealloc(reg->p, reg->used);
153 // Skip the right size optimization if memory allocation fails
154 if (new_ptr) {
155 reg->alloc = reg->used;
156 reg->p = new_ptr;
157 }
158 }
159 } while ((reg = reg->chain) != 0);
160}
161
162extern int
163onig_bbuf_init(BBuf* buf, OnigDistance size)
164{
165 if (size <= 0) {
166 size = 0;
167 buf->p = NULL;
168 }
169 else {
170 buf->p = (UChar* )xmalloc(size);
171 if (IS_NULL(buf->p)) return(ONIGERR_MEMORY);
172 }
173
174 buf->alloc = (unsigned int )size;
175 buf->used = 0;
176 return 0;
177}
178
179
180#ifdef USE_SUBEXP_CALL
181
182static int
183unset_addr_list_init(UnsetAddrList* uslist, int size)
184{
185 UnsetAddr* p;
186
187 p = (UnsetAddr* )xmalloc(sizeof(UnsetAddr)* size);
188 CHECK_NULL_RETURN_MEMERR(p);
189 uslist->num = 0;
190 uslist->alloc = size;
191 uslist->us = p;
192 return 0;
193}
194
195static void
196unset_addr_list_end(UnsetAddrList* uslist)
197{
198 xfree(uslist->us);
199}
200
201static int
202unset_addr_list_add(UnsetAddrList* uslist, int offset, struct _Node* node)
203{
204 UnsetAddr* p;
205 int size;
206
207 if (uslist->num >= uslist->alloc) {
208 size = uslist->alloc * 2;
209 p = (UnsetAddr* )xrealloc(uslist->us, sizeof(UnsetAddr) * size);
210 CHECK_NULL_RETURN_MEMERR(p);
211 uslist->alloc = size;
212 uslist->us = p;
213 }
214
215 uslist->us[uslist->num].offset = offset;
216 uslist->us[uslist->num].target = node;
217 uslist->num++;
218 return 0;
219}
220#endif /* USE_SUBEXP_CALL */
221
222
223static int
224add_opcode(regex_t* reg, int opcode)
225{
226 /* Every instruction passes here, so this is where a program that would
227 outgrow its offset type is stopped, while it is still being emitted. */
228 if (reg->used > MAX_COMPILED_PROGRAM_SIZE)
229 return ONIGERR_TOO_BIG_COMPILED_PROGRAM;
230 BBUF_ADD1(reg, opcode);
231 return 0;
232}
233
234#ifdef USE_COMBINATION_EXPLOSION_CHECK
235static int
236add_state_check_num(regex_t* reg, int num)
237{
238 StateCheckNumType n = (StateCheckNumType )num;
239
240 BBUF_ADD(reg, &n, SIZE_STATE_CHECK_NUM);
241 return 0;
242}
243#endif
244
245static int
246add_rel_addr(regex_t* reg, int addr)
247{
248 RelAddrType ra = (RelAddrType )addr;
249
250 BBUF_ADD(reg, &ra, SIZE_RELADDR);
251 return 0;
252}
253
254static int
255add_abs_addr(regex_t* reg, int addr)
256{
257 AbsAddrType ra = (AbsAddrType )addr;
258
259 BBUF_ADD(reg, &ra, SIZE_ABSADDR);
260 return 0;
261}
262
263static int
264add_length(regex_t* reg, OnigDistance len)
265{
266 LengthType l = (LengthType )len;
267
268 BBUF_ADD(reg, &l, SIZE_LENGTH);
269 return 0;
270}
271
272static int
273add_mem_num(regex_t* reg, int num)
274{
275 MemNumType n = (MemNumType )num;
276
277 BBUF_ADD(reg, &n, SIZE_MEMNUM);
278 return 0;
279}
280
281#if 0
282static int
283add_pointer(regex_t* reg, void* addr)
284{
285 PointerType ptr = (PointerType )addr;
286
287 BBUF_ADD(reg, &ptr, SIZE_POINTER);
288 return 0;
289}
290#endif
291
292static int
293add_option(regex_t* reg, OnigOptionType option)
294{
295 BBUF_ADD(reg, &option, SIZE_OPTION);
296 return 0;
297}
298
299static int
300add_opcode_rel_addr(regex_t* reg, int opcode, int addr)
301{
302 int r;
303
304 r = add_opcode(reg, opcode);
305 if (r) return r;
306 r = add_rel_addr(reg, addr);
307 return r;
308}
309
310static int
311add_bytes(regex_t* reg, UChar* bytes, OnigDistance len)
312{
313 BBUF_ADD(reg, bytes, len);
314 return 0;
315}
316
317static int
318add_bitset(regex_t* reg, BitSetRef bs)
319{
320 BBUF_ADD(reg, bs, SIZE_BITSET);
321 return 0;
322}
323
324static int
325add_opcode_option(regex_t* reg, int opcode, OnigOptionType option)
326{
327 int r;
328
329 r = add_opcode(reg, opcode);
330 if (r) return r;
331 r = add_option(reg, option);
332 return r;
333}
334
335static int compile_length_tree(Node* node, regex_t* reg);
336static int compile_tree(Node* node, regex_t* reg);
337
338
339#define IS_NEED_STR_LEN_OP_EXACT(op) \
340 ((op) == OP_EXACTN || (op) == OP_EXACTMB2N ||\
341 (op) == OP_EXACTMB3N || (op) == OP_EXACTMBN || (op) == OP_EXACTN_IC)
342
343static int
344select_str_opcode(int mb_len, OnigDistance byte_len, int ignore_case)
345{
346 int op;
347 OnigDistance str_len = roomof(byte_len, mb_len);
348
349 if (ignore_case) {
350 switch (str_len) {
351 case 1: op = OP_EXACT1_IC; break;
352 default: op = OP_EXACTN_IC; break;
353 }
354 }
355 else {
356 switch (mb_len) {
357 case 1:
358 switch (str_len) {
359 case 1: op = OP_EXACT1; break;
360 case 2: op = OP_EXACT2; break;
361 case 3: op = OP_EXACT3; break;
362 case 4: op = OP_EXACT4; break;
363 case 5: op = OP_EXACT5; break;
364 default: op = OP_EXACTN; break;
365 }
366 break;
367
368 case 2:
369 switch (str_len) {
370 case 1: op = OP_EXACTMB2N1; break;
371 case 2: op = OP_EXACTMB2N2; break;
372 case 3: op = OP_EXACTMB2N3; break;
373 default: op = OP_EXACTMB2N; break;
374 }
375 break;
376
377 case 3:
378 op = OP_EXACTMB3N;
379 break;
380
381 default:
382 op = OP_EXACTMBN;
383 break;
384 }
385 }
386 return op;
387}
388
389static int
390compile_tree_empty_check(Node* node, regex_t* reg, int empty_info)
391{
392 int r;
393 int saved_num_null_check = reg->num_null_check;
394
395 if (empty_info != 0) {
396 r = add_opcode(reg, OP_NULL_CHECK_START);
397 if (r) return r;
398 r = add_mem_num(reg, reg->num_null_check); /* NULL CHECK ID */
399 if (r) return r;
400 reg->num_null_check++;
401 if ((MemNumType)reg->num_null_check <= 0) return ONIGERR_TOO_MANY_NULL_CHECK;
402 }
403
404 r = compile_tree(node, reg);
405 if (r) return r;
406
407 if (empty_info != 0) {
408 if (empty_info == NQ_TARGET_IS_EMPTY)
409 r = add_opcode(reg, OP_NULL_CHECK_END);
410 else if (empty_info == NQ_TARGET_IS_EMPTY_MEM)
411 r = add_opcode(reg, OP_NULL_CHECK_END_MEMST);
412 else if (empty_info == NQ_TARGET_IS_EMPTY_REC)
413 r = add_opcode(reg, OP_NULL_CHECK_END_MEMST_PUSH);
414
415 if (r) return r;
416 r = add_mem_num(reg, saved_num_null_check); /* NULL CHECK ID */
417 }
418 return r;
419}
420
421#ifdef USE_SUBEXP_CALL
422static int
423compile_call(CallNode* node, regex_t* reg)
424{
425 int r;
426
427 r = add_opcode(reg, OP_CALL);
428 if (r) return r;
429 r = unset_addr_list_add(node->unset_addr_list, BBUF_GET_OFFSET_POS(reg),
430 node->target);
431 if (r) return r;
432 r = add_abs_addr(reg, 0 /*dummy addr.*/);
433 return r;
434}
435#endif
436
437static int
438compile_tree_n_times(Node* node, int n, regex_t* reg)
439{
440 int i, r;
441
442 for (i = 0; i < n; i++) {
443 r = compile_tree(node, reg);
444 if (r) return r;
445 }
446 return 0;
447}
448
449static int
450add_compile_string_length(UChar* s ARG_UNUSED, int mb_len, OnigDistance byte_len,
451 regex_t* reg ARG_UNUSED, int ignore_case)
452{
453 int len;
454 int op = select_str_opcode(mb_len, byte_len, ignore_case);
455
456 len = SIZE_OPCODE;
457
458 if (op == OP_EXACTMBN) len += SIZE_LENGTH;
459 if (IS_NEED_STR_LEN_OP_EXACT(op))
460 len += SIZE_LENGTH;
461
462 len += (int )byte_len;
463 return len;
464}
465
466static int
467add_compile_string(UChar* s, int mb_len, OnigDistance byte_len,
468 regex_t* reg, int ignore_case)
469{
470 int op = select_str_opcode(mb_len, byte_len, ignore_case);
471 add_opcode(reg, op);
472
473 if (op == OP_EXACTMBN)
474 add_length(reg, mb_len);
475
476 if (IS_NEED_STR_LEN_OP_EXACT(op)) {
477 if (op == OP_EXACTN_IC)
478 add_length(reg, byte_len);
479 else
480 add_length(reg, byte_len / mb_len);
481 }
482
483 add_bytes(reg, s, byte_len);
484 return 0;
485}
486
487
488static int
489compile_length_string_node(Node* node, regex_t* reg)
490{
491 int rlen, r, len, prev_len, blen, ambig;
492 OnigEncoding enc = reg->enc;
493 UChar *p, *prev;
494 StrNode* sn;
495
496 sn = NSTR(node);
497 if (sn->end <= sn->s)
498 return 0;
499
500 ambig = NSTRING_IS_AMBIG(node);
501
502 p = prev = sn->s;
503 prev_len = enclen(enc, p, sn->end);
504 p += prev_len;
505 blen = prev_len;
506 rlen = 0;
507
508 for (; p < sn->end; ) {
509 len = enclen(enc, p, sn->end);
510 if (len == prev_len || ambig) {
511 blen += len;
512 }
513 else {
514 r = add_compile_string_length(prev, prev_len, blen, reg, ambig);
515 rlen += r;
516 prev = p;
517 blen = len;
518 prev_len = len;
519 }
520 p += len;
521 }
522 r = add_compile_string_length(prev, prev_len, blen, reg, ambig);
523 rlen += r;
524 return rlen;
525}
526
527static int
528compile_length_string_raw_node(StrNode* sn, regex_t* reg)
529{
530 if (sn->end <= sn->s)
531 return 0;
532
533 return add_compile_string_length(sn->s, 1 /* sb */, sn->end - sn->s, reg, 0);
534}
535
536static int
537compile_string_node(Node* node, regex_t* reg)
538{
539 int r, len, prev_len, blen, ambig;
540 OnigEncoding enc = reg->enc;
541 UChar *p, *prev, *end;
542 StrNode* sn;
543
544 sn = NSTR(node);
545 if (sn->end <= sn->s)
546 return 0;
547
548 end = sn->end;
549 ambig = NSTRING_IS_AMBIG(node);
550
551 p = prev = sn->s;
552 prev_len = enclen(enc, p, end);
553 p += prev_len;
554 blen = prev_len;
555
556 for (; p < end; ) {
557 len = enclen(enc, p, end);
558 if (len == prev_len || ambig) {
559 blen += len;
560 }
561 else {
562 r = add_compile_string(prev, prev_len, blen, reg, ambig);
563 if (r) return r;
564
565 prev = p;
566 blen = len;
567 prev_len = len;
568 }
569
570 p += len;
571 }
572 return add_compile_string(prev, prev_len, blen, reg, ambig);
573}
574
575static int
576compile_string_raw_node(StrNode* sn, regex_t* reg)
577{
578 if (sn->end <= sn->s)
579 return 0;
580
581 return add_compile_string(sn->s, 1 /* sb */, sn->end - sn->s, reg, 0);
582}
583
584static int
585add_multi_byte_cclass(BBuf* mbuf, regex_t* reg)
586{
587#ifdef PLATFORM_UNALIGNED_WORD_ACCESS
588 add_length(reg, mbuf->used);
589 return add_bytes(reg, mbuf->p, mbuf->used);
590#else
591 int r, pad_size;
592 UChar* p = BBUF_GET_ADD_ADDRESS(reg) + SIZE_LENGTH;
593
594 GET_ALIGNMENT_PAD_SIZE(p, pad_size);
595 add_length(reg, mbuf->used + (WORD_ALIGNMENT_SIZE - 1));
596 if (pad_size != 0) add_bytes(reg, PadBuf, pad_size);
597
598 r = add_bytes(reg, mbuf->p, mbuf->used);
599
600 /* padding for return value from compile_length_cclass_node() to be fix. */
601 pad_size = (WORD_ALIGNMENT_SIZE - 1) - pad_size;
602 if (pad_size != 0) add_bytes(reg, PadBuf, pad_size);
603 return r;
604#endif
605}
606
607static int
608compile_length_cclass_node(CClassNode* cc, regex_t* reg)
609{
610 int len;
611
612 if (IS_NULL(cc->mbuf)) {
613 len = SIZE_OPCODE + SIZE_BITSET;
614 }
615 else {
616 if (ONIGENC_MBC_MINLEN(reg->enc) > 1 || bitset_is_empty(cc->bs)) {
617 len = SIZE_OPCODE;
618 }
619 else {
620 len = SIZE_OPCODE + SIZE_BITSET;
621 }
622#ifdef PLATFORM_UNALIGNED_WORD_ACCESS
623 len += SIZE_LENGTH + cc->mbuf->used;
624#else
625 len += SIZE_LENGTH + cc->mbuf->used + (WORD_ALIGNMENT_SIZE - 1);
626#endif
627 }
628
629 return len;
630}
631
632static int
633compile_cclass_node(CClassNode* cc, regex_t* reg)
634{
635 int r;
636
637 if (IS_NULL(cc->mbuf)) {
638 if (IS_NCCLASS_NOT(cc))
639 add_opcode(reg, OP_CCLASS_NOT);
640 else
641 add_opcode(reg, OP_CCLASS);
642
643 r = add_bitset(reg, cc->bs);
644 }
645 else {
646 if (ONIGENC_MBC_MINLEN(reg->enc) > 1 || bitset_is_empty(cc->bs)) {
647 if (IS_NCCLASS_NOT(cc))
648 add_opcode(reg, OP_CCLASS_MB_NOT);
649 else
650 add_opcode(reg, OP_CCLASS_MB);
651
652 r = add_multi_byte_cclass(cc->mbuf, reg);
653 }
654 else {
655 if (IS_NCCLASS_NOT(cc))
656 add_opcode(reg, OP_CCLASS_MIX_NOT);
657 else
658 add_opcode(reg, OP_CCLASS_MIX);
659
660 r = add_bitset(reg, cc->bs);
661 if (r) return r;
662 r = add_multi_byte_cclass(cc->mbuf, reg);
663 }
664 }
665
666 return r;
667}
668
669static int
670entry_repeat_range(regex_t* reg, int id, int lower, int upper)
671{
672#define REPEAT_RANGE_ALLOC 4
673
675
676 if (reg->repeat_range_alloc == 0) {
677 p = (OnigRepeatRange* )xmalloc(sizeof(OnigRepeatRange) * REPEAT_RANGE_ALLOC);
678 CHECK_NULL_RETURN_MEMERR(p);
679 reg->repeat_range = p;
680 reg->repeat_range_alloc = REPEAT_RANGE_ALLOC;
681 }
682 else if (reg->repeat_range_alloc <= id) {
683 int n;
684 n = reg->repeat_range_alloc + REPEAT_RANGE_ALLOC;
685 p = (OnigRepeatRange* )xrealloc(reg->repeat_range,
686 sizeof(OnigRepeatRange) * n);
687 CHECK_NULL_RETURN_MEMERR(p);
688 reg->repeat_range = p;
689 reg->repeat_range_alloc = n;
690 }
691 else {
692 p = reg->repeat_range;
693 }
694
695 p[id].lower = lower;
696 p[id].upper = (IS_REPEAT_INFINITE(upper) ? 0x7fffffff : upper);
697 return 0;
698}
699
700static int
701compile_range_repeat_node(QtfrNode* qn, int target_len, int empty_info,
702 regex_t* reg)
703{
704 int r;
705 int num_repeat = reg->num_repeat;
706
707 r = add_opcode(reg, qn->greedy ? OP_REPEAT : OP_REPEAT_NG);
708 if (r) return r;
709 r = add_mem_num(reg, num_repeat); /* OP_REPEAT ID */
710 reg->num_repeat++;
711 if ((MemNumType)reg->num_repeat <= 0) return ONIGERR_TOO_MANY_RANGE_REPEAT;
712 if (r) return r;
713 r = add_rel_addr(reg, target_len + SIZE_OP_REPEAT_INC);
714 if (r) return r;
715
716 r = entry_repeat_range(reg, num_repeat, qn->lower, qn->upper);
717 if (r) return r;
718
719 r = compile_tree_empty_check(qn->target, reg, empty_info);
720 if (r) return r;
721
722 if (
723#ifdef USE_SUBEXP_CALL
724 reg->num_call > 0 ||
725#endif
726 IS_QUANTIFIER_IN_REPEAT(qn)) {
727 r = add_opcode(reg, qn->greedy ? OP_REPEAT_INC_SG : OP_REPEAT_INC_NG_SG);
728 }
729 else {
730 r = add_opcode(reg, qn->greedy ? OP_REPEAT_INC : OP_REPEAT_INC_NG);
731 }
732 if (r) return r;
733 r = add_mem_num(reg, num_repeat); /* OP_REPEAT ID */
734 return r;
735}
736
737static int
738is_anychar_star_quantifier(QtfrNode* qn)
739{
740 if (qn->greedy && IS_REPEAT_INFINITE(qn->upper) &&
741 NTYPE(qn->target) == NT_CANY)
742 return 1;
743 else
744 return 0;
745}
746
747#define QUANTIFIER_EXPAND_LIMIT_SIZE 50
748/* (tlen * n <= QUANTIFIER_EXPAND_LIMIT_SIZE) without overflowing int: tlen
749 and n are each bounded by ONIG_MAX_REPEAT_NUM, but their product is not. */
750#define IS_EXPAND_LIMIT_OK(tlen, n) \
751 ((n) <= 0 || (tlen) <= QUANTIFIER_EXPAND_LIMIT_SIZE / (n))
752#define CKN_ON (ckn > 0)
753
754#ifdef USE_COMBINATION_EXPLOSION_CHECK
755
756static int
757compile_length_quantifier_node(QtfrNode* qn, regex_t* reg)
758{
759 int len, mod_tlen, cklen;
760 int ckn;
761 int infinite = IS_REPEAT_INFINITE(qn->upper);
762 int empty_info = qn->target_empty_info;
763 int tlen = compile_length_tree(qn->target, reg);
764
765 if (tlen < 0) return tlen;
766
767 ckn = ((reg->num_comb_exp_check > 0) ? qn->comb_exp_check_num : 0);
768
769 cklen = (CKN_ON ? SIZE_STATE_CHECK_NUM: 0);
770
771 /* anychar repeat */
772 if (NTYPE(qn->target) == NT_CANY) {
773 if (qn->greedy && infinite) {
774 if (IS_NOT_NULL(qn->next_head_exact) && !CKN_ON)
775 return SIZE_OP_ANYCHAR_STAR_PEEK_NEXT + tlen * qn->lower + cklen;
776 else
777 return SIZE_OP_ANYCHAR_STAR + tlen * qn->lower + cklen;
778 }
779 }
780
781 if (empty_info != 0)
782 mod_tlen = tlen + (SIZE_OP_NULL_CHECK_START + SIZE_OP_NULL_CHECK_END);
783 else
784 mod_tlen = tlen;
785
786 if (infinite && qn->lower <= 1) {
787 if (qn->greedy) {
788 if (qn->lower == 1)
789 len = SIZE_OP_JUMP;
790 else
791 len = 0;
792
793 len += SIZE_OP_PUSH + cklen + mod_tlen + SIZE_OP_JUMP;
794 }
795 else {
796 if (qn->lower == 0)
797 len = SIZE_OP_JUMP;
798 else
799 len = 0;
800
801 len += mod_tlen + SIZE_OP_PUSH + cklen;
802 }
803 }
804 else if (qn->upper == 0) {
805 if (qn->is_referred != 0) /* /(?<n>..){0}/ */
806 len = SIZE_OP_JUMP + tlen;
807 else
808 len = 0;
809 }
810 else if (qn->upper == 1 && qn->greedy) {
811 if (qn->lower == 0) {
812 if (CKN_ON) {
813 len = SIZE_OP_STATE_CHECK_PUSH + tlen;
814 }
815 else {
816 len = SIZE_OP_PUSH + tlen;
817 }
818 }
819 else {
820 len = tlen;
821 }
822 }
823 else if (!qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */
824 len = SIZE_OP_PUSH + cklen + SIZE_OP_JUMP + tlen;
825 }
826 else {
827 len = SIZE_OP_REPEAT_INC
828 + mod_tlen + SIZE_OPCODE + SIZE_RELADDR + SIZE_MEMNUM;
829 if (CKN_ON)
830 len += SIZE_OP_STATE_CHECK;
831 }
832
833 return len;
834}
835
836static int
837compile_quantifier_node(QtfrNode* qn, regex_t* reg)
838{
839 int r, mod_tlen;
840 int ckn;
841 int infinite = IS_REPEAT_INFINITE(qn->upper);
842 int empty_info = qn->target_empty_info;
843 int tlen = compile_length_tree(qn->target, reg);
844
845 if (tlen < 0) return tlen;
846
847 ckn = ((reg->num_comb_exp_check > 0) ? qn->comb_exp_check_num : 0);
848
849 if (is_anychar_star_quantifier(qn)) {
850 r = compile_tree_n_times(qn->target, qn->lower, reg);
851 if (r) return r;
852 if (IS_NOT_NULL(qn->next_head_exact) && !CKN_ON) {
853 if (IS_MULTILINE(reg->options))
854 r = add_opcode(reg, OP_ANYCHAR_ML_STAR_PEEK_NEXT);
855 else
856 r = add_opcode(reg, OP_ANYCHAR_STAR_PEEK_NEXT);
857 if (r) return r;
858 if (CKN_ON) {
859 r = add_state_check_num(reg, ckn);
860 if (r) return r;
861 }
862
863 return add_bytes(reg, NSTR(qn->next_head_exact)->s, 1);
864 }
865 else {
866 if (IS_MULTILINE(reg->options)) {
867 r = add_opcode(reg, (CKN_ON ?
868 OP_STATE_CHECK_ANYCHAR_ML_STAR
869 : OP_ANYCHAR_ML_STAR));
870 }
871 else {
872 r = add_opcode(reg, (CKN_ON ?
873 OP_STATE_CHECK_ANYCHAR_STAR
874 : OP_ANYCHAR_STAR));
875 }
876 if (r) return r;
877 if (CKN_ON)
878 r = add_state_check_num(reg, ckn);
879
880 return r;
881 }
882 }
883
884 if (empty_info != 0)
885 mod_tlen = tlen + (SIZE_OP_NULL_CHECK_START + SIZE_OP_NULL_CHECK_END);
886 else
887 mod_tlen = tlen;
888
889 if (infinite && qn->lower <= 1) {
890 if (qn->greedy) {
891 if (qn->lower == 1) {
892 r = add_opcode_rel_addr(reg, OP_JUMP,
893 (CKN_ON ? SIZE_OP_STATE_CHECK_PUSH : SIZE_OP_PUSH));
894 if (r) return r;
895 }
896
897 if (CKN_ON) {
898 r = add_opcode(reg, OP_STATE_CHECK_PUSH);
899 if (r) return r;
900 r = add_state_check_num(reg, ckn);
901 if (r) return r;
902 r = add_rel_addr(reg, mod_tlen + SIZE_OP_JUMP);
903 }
904 else {
905 r = add_opcode_rel_addr(reg, OP_PUSH, mod_tlen + SIZE_OP_JUMP);
906 }
907 if (r) return r;
908 r = compile_tree_empty_check(qn->target, reg, empty_info);
909 if (r) return r;
910 r = add_opcode_rel_addr(reg, OP_JUMP,
911 -(mod_tlen + (int )SIZE_OP_JUMP
912 + (int )(CKN_ON ? SIZE_OP_STATE_CHECK_PUSH : SIZE_OP_PUSH)));
913 }
914 else {
915 if (qn->lower == 0) {
916 r = add_opcode_rel_addr(reg, OP_JUMP, mod_tlen);
917 if (r) return r;
918 }
919 r = compile_tree_empty_check(qn->target, reg, empty_info);
920 if (r) return r;
921 if (CKN_ON) {
922 r = add_opcode(reg, OP_STATE_CHECK_PUSH_OR_JUMP);
923 if (r) return r;
924 r = add_state_check_num(reg, ckn);
925 if (r) return r;
926 r = add_rel_addr(reg,
927 -(mod_tlen + (int )SIZE_OP_STATE_CHECK_PUSH_OR_JUMP));
928 }
929 else
930 r = add_opcode_rel_addr(reg, OP_PUSH, -(mod_tlen + (int )SIZE_OP_PUSH));
931 }
932 }
933 else if (qn->upper == 0) {
934 if (qn->is_referred != 0) { /* /(?<n>..){0}/ */
935 r = add_opcode_rel_addr(reg, OP_JUMP, tlen);
936 if (r) return r;
937 r = compile_tree(qn->target, reg);
938 }
939 else
940 r = 0;
941 }
942 else if (qn->upper == 1 && qn->greedy) {
943 if (qn->lower == 0) {
944 if (CKN_ON) {
945 r = add_opcode(reg, OP_STATE_CHECK_PUSH);
946 if (r) return r;
947 r = add_state_check_num(reg, ckn);
948 if (r) return r;
949 r = add_rel_addr(reg, tlen);
950 }
951 else {
952 r = add_opcode_rel_addr(reg, OP_PUSH, tlen);
953 }
954 if (r) return r;
955 }
956
957 r = compile_tree(qn->target, reg);
958 }
959 else if (!qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */
960 if (CKN_ON) {
961 r = add_opcode(reg, OP_STATE_CHECK_PUSH);
962 if (r) return r;
963 r = add_state_check_num(reg, ckn);
964 if (r) return r;
965 r = add_rel_addr(reg, SIZE_OP_JUMP);
966 }
967 else {
968 r = add_opcode_rel_addr(reg, OP_PUSH, SIZE_OP_JUMP);
969 }
970
971 if (r) return r;
972 r = add_opcode_rel_addr(reg, OP_JUMP, tlen);
973 if (r) return r;
974 r = compile_tree(qn->target, reg);
975 }
976 else {
977 r = compile_range_repeat_node(qn, mod_tlen, empty_info, reg);
978 if (CKN_ON) {
979 if (r) return r;
980 r = add_opcode(reg, OP_STATE_CHECK);
981 if (r) return r;
982 r = add_state_check_num(reg, ckn);
983 }
984 }
985 return r;
986}
987
988#else /* USE_COMBINATION_EXPLOSION_CHECK */
989
990static int
991compile_length_quantifier_node(QtfrNode* qn, regex_t* reg)
992{
993 int len, mod_tlen;
994 int infinite = IS_REPEAT_INFINITE(qn->upper);
995 int empty_info = qn->target_empty_info;
996 int tlen = compile_length_tree(qn->target, reg);
997
998 if (tlen < 0) return tlen;
999
1000 /* anychar repeat */
1001 if (NTYPE(qn->target) == NT_CANY) {
1002 if (qn->greedy && infinite) {
1003 if (IS_NOT_NULL(qn->next_head_exact))
1004 return SIZE_OP_ANYCHAR_STAR_PEEK_NEXT + tlen * qn->lower;
1005 else
1006 return SIZE_OP_ANYCHAR_STAR + tlen * qn->lower;
1007 }
1008 }
1009
1010 if (empty_info != 0)
1011 mod_tlen = tlen + (SIZE_OP_NULL_CHECK_START + SIZE_OP_NULL_CHECK_END);
1012 else
1013 mod_tlen = tlen;
1014
1015 if (infinite &&
1016 (qn->lower <= 1 || IS_EXPAND_LIMIT_OK(tlen, qn->lower))) {
1017 if (qn->lower == 1 && tlen > QUANTIFIER_EXPAND_LIMIT_SIZE) {
1018 len = SIZE_OP_JUMP;
1019 }
1020 else {
1021 len = tlen * qn->lower;
1022 }
1023
1024 if (qn->greedy) {
1025#ifdef USE_OP_PUSH_OR_JUMP_EXACT
1026 if (IS_NOT_NULL(qn->head_exact))
1027 len += SIZE_OP_PUSH_OR_JUMP_EXACT1 + mod_tlen + SIZE_OP_JUMP;
1028 else
1029#endif
1030 if (IS_NOT_NULL(qn->next_head_exact))
1031 len += SIZE_OP_PUSH_IF_PEEK_NEXT + mod_tlen + SIZE_OP_JUMP;
1032 else
1033 len += SIZE_OP_PUSH + mod_tlen + SIZE_OP_JUMP;
1034 }
1035 else
1036 len += SIZE_OP_JUMP + mod_tlen + SIZE_OP_PUSH;
1037 }
1038 else if (qn->upper == 0 && qn->is_referred != 0) { /* /(?<n>..){0}/ */
1039 len = SIZE_OP_JUMP + tlen;
1040 }
1041 else if (!infinite && qn->greedy &&
1042 (qn->upper == 1 ||
1043 IS_EXPAND_LIMIT_OK(tlen + SIZE_OP_PUSH, qn->upper))) {
1044 len = tlen * qn->lower;
1045 len += (SIZE_OP_PUSH + tlen) * (qn->upper - qn->lower);
1046 }
1047 else if (!qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */
1048 len = SIZE_OP_PUSH + SIZE_OP_JUMP + tlen;
1049 }
1050 else {
1051 len = SIZE_OP_REPEAT_INC
1052 + mod_tlen + SIZE_OPCODE + SIZE_RELADDR + SIZE_MEMNUM;
1053 }
1054
1055 return len;
1056}
1057
1058static int
1059compile_quantifier_node(QtfrNode* qn, regex_t* reg)
1060{
1061 int i, r, mod_tlen;
1062 int infinite = IS_REPEAT_INFINITE(qn->upper);
1063 int empty_info = qn->target_empty_info;
1064 int tlen = compile_length_tree(qn->target, reg);
1065
1066 if (tlen < 0) return tlen;
1067
1068 if (is_anychar_star_quantifier(qn)) {
1069 r = compile_tree_n_times(qn->target, qn->lower, reg);
1070 if (r) return r;
1071 if (IS_NOT_NULL(qn->next_head_exact)) {
1072 if (IS_MULTILINE(reg->options))
1073 r = add_opcode(reg, OP_ANYCHAR_ML_STAR_PEEK_NEXT);
1074 else
1075 r = add_opcode(reg, OP_ANYCHAR_STAR_PEEK_NEXT);
1076 if (r) return r;
1077 return add_bytes(reg, NSTR(qn->next_head_exact)->s, 1);
1078 }
1079 else {
1080 if (IS_MULTILINE(reg->options))
1081 return add_opcode(reg, OP_ANYCHAR_ML_STAR);
1082 else
1083 return add_opcode(reg, OP_ANYCHAR_STAR);
1084 }
1085 }
1086
1087 if (empty_info != 0)
1088 mod_tlen = tlen + (SIZE_OP_NULL_CHECK_START + SIZE_OP_NULL_CHECK_END);
1089 else
1090 mod_tlen = tlen;
1091
1092 if (infinite &&
1093 (qn->lower <= 1 || IS_EXPAND_LIMIT_OK(tlen, qn->lower))) {
1094 if (qn->lower == 1 && tlen > QUANTIFIER_EXPAND_LIMIT_SIZE) {
1095 if (qn->greedy) {
1096#ifdef USE_OP_PUSH_OR_JUMP_EXACT
1097 if (IS_NOT_NULL(qn->head_exact))
1098 r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH_OR_JUMP_EXACT1);
1099 else
1100#endif
1101 if (IS_NOT_NULL(qn->next_head_exact))
1102 r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH_IF_PEEK_NEXT);
1103 else
1104 r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH);
1105 }
1106 else {
1107 r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_JUMP);
1108 }
1109 if (r) return r;
1110 }
1111 else {
1112 r = compile_tree_n_times(qn->target, qn->lower, reg);
1113 if (r) return r;
1114 }
1115
1116 if (qn->greedy) {
1117#ifdef USE_OP_PUSH_OR_JUMP_EXACT
1118 if (IS_NOT_NULL(qn->head_exact)) {
1119 r = add_opcode_rel_addr(reg, OP_PUSH_OR_JUMP_EXACT1,
1120 mod_tlen + SIZE_OP_JUMP);
1121 if (r) return r;
1122 add_bytes(reg, NSTR(qn->head_exact)->s, 1);
1123 r = compile_tree_empty_check(qn->target, reg, empty_info);
1124 if (r) return r;
1125 r = add_opcode_rel_addr(reg, OP_JUMP,
1126 -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH_OR_JUMP_EXACT1));
1127 }
1128 else
1129#endif
1130 if (IS_NOT_NULL(qn->next_head_exact)) {
1131 r = add_opcode_rel_addr(reg, OP_PUSH_IF_PEEK_NEXT,
1132 mod_tlen + SIZE_OP_JUMP);
1133 if (r) return r;
1134 add_bytes(reg, NSTR(qn->next_head_exact)->s, 1);
1135 r = compile_tree_empty_check(qn->target, reg, empty_info);
1136 if (r) return r;
1137 r = add_opcode_rel_addr(reg, OP_JUMP,
1138 -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH_IF_PEEK_NEXT));
1139 }
1140 else {
1141 r = add_opcode_rel_addr(reg, OP_PUSH, mod_tlen + SIZE_OP_JUMP);
1142 if (r) return r;
1143 r = compile_tree_empty_check(qn->target, reg, empty_info);
1144 if (r) return r;
1145 r = add_opcode_rel_addr(reg, OP_JUMP,
1146 -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH));
1147 }
1148 }
1149 else {
1150 r = add_opcode_rel_addr(reg, OP_JUMP, mod_tlen);
1151 if (r) return r;
1152 r = compile_tree_empty_check(qn->target, reg, empty_info);
1153 if (r) return r;
1154 r = add_opcode_rel_addr(reg, OP_PUSH, -(mod_tlen + (int )SIZE_OP_PUSH));
1155 }
1156 }
1157 else if (qn->upper == 0 && qn->is_referred != 0) { /* /(?<n>..){0}/ */
1158 r = add_opcode_rel_addr(reg, OP_JUMP, tlen);
1159 if (r) return r;
1160 r = compile_tree(qn->target, reg);
1161 }
1162 else if (!infinite && qn->greedy &&
1163 (qn->upper == 1 ||
1164 IS_EXPAND_LIMIT_OK(tlen + SIZE_OP_PUSH, qn->upper))) {
1165 int n = qn->upper - qn->lower;
1166
1167 r = compile_tree_n_times(qn->target, qn->lower, reg);
1168 if (r) return r;
1169
1170 for (i = 0; i < n; i++) {
1171 r = add_opcode_rel_addr(reg, OP_PUSH,
1172 (n - i) * tlen + (n - i - 1) * SIZE_OP_PUSH);
1173 if (r) return r;
1174 r = compile_tree(qn->target, reg);
1175 if (r) return r;
1176 }
1177 }
1178 else if (!qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */
1179 r = add_opcode_rel_addr(reg, OP_PUSH, SIZE_OP_JUMP);
1180 if (r) return r;
1181 r = add_opcode_rel_addr(reg, OP_JUMP, tlen);
1182 if (r) return r;
1183 r = compile_tree(qn->target, reg);
1184 }
1185 else {
1186 r = compile_range_repeat_node(qn, mod_tlen, empty_info, reg);
1187 }
1188 return r;
1189}
1190#endif /* USE_COMBINATION_EXPLOSION_CHECK */
1191
1192static int
1193compile_length_option_node(EncloseNode* node, regex_t* reg)
1194{
1195 int tlen;
1196 OnigOptionType prev = reg->options;
1197
1198 reg->options = node->option;
1199 tlen = compile_length_tree(node->target, reg);
1200 reg->options = prev;
1201
1202 if (tlen < 0) return tlen;
1203
1204 if (IS_DYNAMIC_OPTION(prev ^ node->option)) {
1205 return SIZE_OP_SET_OPTION_PUSH + SIZE_OP_SET_OPTION + SIZE_OP_FAIL
1206 + tlen + SIZE_OP_SET_OPTION;
1207 }
1208 else
1209 return tlen;
1210}
1211
1212static int
1213compile_option_node(EncloseNode* node, regex_t* reg)
1214{
1215 int r;
1216 OnigOptionType prev = reg->options;
1217
1218 if (IS_DYNAMIC_OPTION(prev ^ node->option)) {
1219 r = add_opcode_option(reg, OP_SET_OPTION_PUSH, node->option);
1220 if (r) return r;
1221 r = add_opcode_option(reg, OP_SET_OPTION, prev);
1222 if (r) return r;
1223 r = add_opcode(reg, OP_FAIL);
1224 if (r) return r;
1225 }
1226
1227 reg->options = node->option;
1228 r = compile_tree(node->target, reg);
1229 reg->options = prev;
1230
1231 if (IS_DYNAMIC_OPTION(prev ^ node->option)) {
1232 if (r) return r;
1233 r = add_opcode_option(reg, OP_SET_OPTION, prev);
1234 }
1235 return r;
1236}
1237
1238static int
1239compile_length_enclose_node(EncloseNode* node, regex_t* reg)
1240{
1241 int len;
1242 int tlen;
1243
1244 if (node->type == ENCLOSE_OPTION)
1245 return compile_length_option_node(node, reg);
1246
1247 if (node->target) {
1248 tlen = compile_length_tree(node->target, reg);
1249 if (tlen < 0) return tlen;
1250 }
1251 else
1252 tlen = 0;
1253
1254 switch (node->type) {
1255 case ENCLOSE_MEMORY:
1256#ifdef USE_SUBEXP_CALL
1257 if (IS_ENCLOSE_CALLED(node)) {
1258 len = SIZE_OP_MEMORY_START_PUSH + tlen
1259 + SIZE_OP_CALL + SIZE_OP_JUMP + SIZE_OP_RETURN;
1260 if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))
1261 len += (IS_ENCLOSE_RECURSION(node)
1262 ? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_PUSH);
1263 else
1264 len += (IS_ENCLOSE_RECURSION(node)
1265 ? SIZE_OP_MEMORY_END_REC : SIZE_OP_MEMORY_END);
1266 }
1267 else if (IS_ENCLOSE_RECURSION(node)) {
1268 len = SIZE_OP_MEMORY_START_PUSH;
1269 len += tlen + (BIT_STATUS_AT(reg->bt_mem_end, node->regnum)
1270 ? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_REC);
1271 }
1272 else
1273#endif
1274 {
1275 if (BIT_STATUS_AT(reg->bt_mem_start, node->regnum))
1276 len = SIZE_OP_MEMORY_START_PUSH;
1277 else
1278 len = SIZE_OP_MEMORY_START;
1279
1280 len += tlen + (BIT_STATUS_AT(reg->bt_mem_end, node->regnum)
1281 ? SIZE_OP_MEMORY_END_PUSH : SIZE_OP_MEMORY_END);
1282 }
1283 break;
1284
1285 case ENCLOSE_STOP_BACKTRACK:
1286 /* Disable POP_STOP_BT optimization for simple repeat under the match cache */
1287 /* optimization because the match cache optimization pushes an extra item to */
1288 /* the stack and it breaks the assumption for this optimization. */
1289#ifndef USE_MATCH_CACHE
1290 if (IS_ENCLOSE_STOP_BT_SIMPLE_REPEAT(node)) {
1291 QtfrNode* qn = NQTFR(node->target);
1292 tlen = compile_length_tree(qn->target, reg);
1293 if (tlen < 0) return tlen;
1294
1295 len = tlen * qn->lower
1296 + SIZE_OP_PUSH + tlen + SIZE_OP_POP + SIZE_OP_JUMP;
1297 }
1298 else {
1299#endif
1300 len = SIZE_OP_PUSH_STOP_BT + tlen + SIZE_OP_POP_STOP_BT;
1301#ifndef USE_MATCH_CACHE
1302 }
1303#endif
1304 break;
1305
1306 case ENCLOSE_CONDITION:
1307 len = SIZE_OP_CONDITION;
1308 if (NTYPE(node->target) == NT_ALT) {
1309 Node* x = node->target;
1310
1311 tlen = compile_length_tree(NCAR(x), reg); /* yes-node */
1312 if (tlen < 0) return tlen;
1313 len += tlen + SIZE_OP_JUMP;
1314 if (NCDR(x) == NULL) return ONIGERR_PARSER_BUG;
1315 x = NCDR(x);
1316 tlen = compile_length_tree(NCAR(x), reg); /* no-node */
1317 if (tlen < 0) return tlen;
1318 len += tlen;
1319 if (NCDR(x) != NULL) return ONIGERR_INVALID_CONDITION_PATTERN;
1320 }
1321 else {
1322 return ONIGERR_PARSER_BUG;
1323 }
1324 break;
1325
1326 case ENCLOSE_ABSENT:
1327 len = SIZE_OP_PUSH_ABSENT_POS + SIZE_OP_ABSENT + tlen + SIZE_OP_ABSENT_END;
1328 break;
1329
1330 default:
1331 return ONIGERR_TYPE_BUG;
1332 break;
1333 }
1334
1335 return len;
1336}
1337
1338static int get_char_length_tree(Node* node, regex_t* reg, int* len);
1339
1340static int
1341compile_enclose_node(EncloseNode* node, regex_t* reg)
1342{
1343 int r, len;
1344
1345 if (node->type == ENCLOSE_OPTION)
1346 return compile_option_node(node, reg);
1347
1348 switch (node->type) {
1349 case ENCLOSE_MEMORY:
1350#ifdef USE_SUBEXP_CALL
1351 if (IS_ENCLOSE_CALLED(node)) {
1352 r = add_opcode(reg, OP_CALL);
1353 if (r) return r;
1354 node->call_addr = BBUF_GET_OFFSET_POS(reg) + SIZE_ABSADDR + SIZE_OP_JUMP;
1355 node->state |= NST_ADDR_FIXED;
1356 r = add_abs_addr(reg, (int )node->call_addr);
1357 if (r) return r;
1358 len = compile_length_tree(node->target, reg);
1359 len += (SIZE_OP_MEMORY_START_PUSH + SIZE_OP_RETURN);
1360 if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))
1361 len += (IS_ENCLOSE_RECURSION(node)
1362 ? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_PUSH);
1363 else
1364 len += (IS_ENCLOSE_RECURSION(node)
1365 ? SIZE_OP_MEMORY_END_REC : SIZE_OP_MEMORY_END);
1366
1367 r = add_opcode_rel_addr(reg, OP_JUMP, len);
1368 if (r) return r;
1369 }
1370#endif
1371 if (BIT_STATUS_AT(reg->bt_mem_start, node->regnum))
1372 r = add_opcode(reg, OP_MEMORY_START_PUSH);
1373 else
1374 r = add_opcode(reg, OP_MEMORY_START);
1375 if (r) return r;
1376 r = add_mem_num(reg, node->regnum);
1377 if (r) return r;
1378 r = compile_tree(node->target, reg);
1379 if (r) return r;
1380#ifdef USE_SUBEXP_CALL
1381 if (IS_ENCLOSE_CALLED(node)) {
1382 if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))
1383 r = add_opcode(reg, (IS_ENCLOSE_RECURSION(node)
1384 ? OP_MEMORY_END_PUSH_REC : OP_MEMORY_END_PUSH));
1385 else
1386 r = add_opcode(reg, (IS_ENCLOSE_RECURSION(node)
1387 ? OP_MEMORY_END_REC : OP_MEMORY_END));
1388
1389 if (r) return r;
1390 r = add_mem_num(reg, node->regnum);
1391 if (r) return r;
1392 r = add_opcode(reg, OP_RETURN);
1393 }
1394 else if (IS_ENCLOSE_RECURSION(node)) {
1395 if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))
1396 r = add_opcode(reg, OP_MEMORY_END_PUSH_REC);
1397 else
1398 r = add_opcode(reg, OP_MEMORY_END_REC);
1399 if (r) return r;
1400 r = add_mem_num(reg, node->regnum);
1401 }
1402 else
1403#endif
1404 {
1405 if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))
1406 r = add_opcode(reg, OP_MEMORY_END_PUSH);
1407 else
1408 r = add_opcode(reg, OP_MEMORY_END);
1409 if (r) return r;
1410 r = add_mem_num(reg, node->regnum);
1411 }
1412 break;
1413
1414 case ENCLOSE_STOP_BACKTRACK:
1415 /* Disable POP_STOP_BT optimization for simple repeat under the match cache */
1416 /* optimization because the match cache optimization pushes an extra item to */
1417 /* the stack and it breaks the assumption for this optimization. */
1418#ifndef USE_MATCH_CACHE
1419 if (IS_ENCLOSE_STOP_BT_SIMPLE_REPEAT(node)) {
1420 QtfrNode* qn = NQTFR(node->target);
1421 r = compile_tree_n_times(qn->target, qn->lower, reg);
1422 if (r) return r;
1423
1424 len = compile_length_tree(qn->target, reg);
1425 if (len < 0) return len;
1426
1427 r = add_opcode_rel_addr(reg, OP_PUSH, len + SIZE_OP_POP + SIZE_OP_JUMP);
1428 if (r) return r;
1429 r = compile_tree(qn->target, reg);
1430 if (r) return r;
1431 r = add_opcode(reg, OP_POP);
1432 if (r) return r;
1433 r = add_opcode_rel_addr(reg, OP_JUMP,
1434 -((int )SIZE_OP_PUSH + len + (int )SIZE_OP_POP + (int )SIZE_OP_JUMP));
1435 }
1436 else {
1437#endif
1438 r = add_opcode(reg, OP_PUSH_STOP_BT);
1439 if (r) return r;
1440 r = compile_tree(node->target, reg);
1441 if (r) return r;
1442 r = add_opcode(reg, OP_POP_STOP_BT);
1443#ifndef USE_MATCH_CACHE
1444 }
1445#endif
1446 break;
1447
1448 case ENCLOSE_CONDITION:
1449 r = add_opcode(reg, OP_CONDITION);
1450 if (r) return r;
1451 r = add_mem_num(reg, node->regnum);
1452 if (r) return r;
1453
1454 if (NTYPE(node->target) == NT_ALT) {
1455 Node* x = node->target;
1456 int len2;
1457
1458 len = compile_length_tree(NCAR(x), reg); /* yes-node */
1459 if (len < 0) return len;
1460 if (NCDR(x) == NULL) return ONIGERR_PARSER_BUG;
1461 x = NCDR(x);
1462 len2 = compile_length_tree(NCAR(x), reg); /* no-node */
1463 if (len2 < 0) return len2;
1464 if (NCDR(x) != NULL) return ONIGERR_INVALID_CONDITION_PATTERN;
1465
1466 x = node->target;
1467 r = add_rel_addr(reg, len + SIZE_OP_JUMP);
1468 if (r) return r;
1469 r = compile_tree(NCAR(x), reg); /* yes-node */
1470 if (r) return r;
1471 r = add_opcode_rel_addr(reg, OP_JUMP, len2);
1472 if (r) return r;
1473 x = NCDR(x);
1474 r = compile_tree(NCAR(x), reg); /* no-node */
1475 }
1476 else {
1477 return ONIGERR_PARSER_BUG;
1478 }
1479 break;
1480
1481 case ENCLOSE_ABSENT:
1482 len = compile_length_tree(node->target, reg);
1483 if (len < 0) return len;
1484
1485 r = add_opcode(reg, OP_PUSH_ABSENT_POS);
1486 if (r) return r;
1487 r = add_opcode_rel_addr(reg, OP_ABSENT, len + SIZE_OP_ABSENT_END);
1488 if (r) return r;
1489 r = compile_tree(node->target, reg);
1490 if (r) return r;
1491 r = add_opcode(reg, OP_ABSENT_END);
1492 break;
1493
1494 default:
1495 return ONIGERR_TYPE_BUG;
1496 break;
1497 }
1498
1499 return r;
1500}
1501
1502static int
1503compile_length_anchor_node(AnchorNode* node, regex_t* reg)
1504{
1505 int len;
1506 int tlen = 0;
1507
1508 if (node->target) {
1509 tlen = compile_length_tree(node->target, reg);
1510 if (tlen < 0) return tlen;
1511 }
1512
1513 switch (node->type) {
1514 case ANCHOR_PREC_READ:
1515 len = SIZE_OP_PUSH_POS + tlen + SIZE_OP_POP_POS;
1516 break;
1517 case ANCHOR_PREC_READ_NOT:
1518 len = SIZE_OP_PUSH_POS_NOT + tlen + SIZE_OP_FAIL_POS;
1519 break;
1520 case ANCHOR_LOOK_BEHIND:
1521 len = SIZE_OP_LOOK_BEHIND + tlen;
1522 break;
1523 case ANCHOR_LOOK_BEHIND_NOT:
1524 len = SIZE_OP_PUSH_LOOK_BEHIND_NOT + tlen + SIZE_OP_FAIL_LOOK_BEHIND_NOT;
1525 break;
1526
1527 default:
1528 len = SIZE_OPCODE;
1529 break;
1530 }
1531
1532 return len;
1533}
1534
1535static int
1536compile_anchor_node(AnchorNode* node, regex_t* reg)
1537{
1538 int r, len;
1539
1540 switch (node->type) {
1541 case ANCHOR_BEGIN_BUF: r = add_opcode(reg, OP_BEGIN_BUF); break;
1542 case ANCHOR_END_BUF: r = add_opcode(reg, OP_END_BUF); break;
1543 case ANCHOR_BEGIN_LINE: r = add_opcode(reg, OP_BEGIN_LINE); break;
1544 case ANCHOR_END_LINE: r = add_opcode(reg, OP_END_LINE); break;
1545 case ANCHOR_SEMI_END_BUF: r = add_opcode(reg, OP_SEMI_END_BUF); break;
1546 case ANCHOR_BEGIN_POSITION: r = add_opcode(reg, OP_BEGIN_POSITION); break;
1547
1548 case ANCHOR_WORD_BOUND:
1549 if (node->ascii_range) r = add_opcode(reg, OP_ASCII_WORD_BOUND);
1550 else r = add_opcode(reg, OP_WORD_BOUND);
1551 break;
1552 case ANCHOR_NOT_WORD_BOUND:
1553 if (node->ascii_range) r = add_opcode(reg, OP_NOT_ASCII_WORD_BOUND);
1554 else r = add_opcode(reg, OP_NOT_WORD_BOUND);
1555 break;
1556#ifdef USE_WORD_BEGIN_END
1557 case ANCHOR_WORD_BEGIN:
1558 if (node->ascii_range) r = add_opcode(reg, OP_ASCII_WORD_BEGIN);
1559 else r = add_opcode(reg, OP_WORD_BEGIN);
1560 break;
1561 case ANCHOR_WORD_END:
1562 if (node->ascii_range) r = add_opcode(reg, OP_ASCII_WORD_END);
1563 else r = add_opcode(reg, OP_WORD_END);
1564 break;
1565#endif
1566 case ANCHOR_KEEP: r = add_opcode(reg, OP_KEEP); break;
1567
1568 case ANCHOR_PREC_READ:
1569 r = add_opcode(reg, OP_PUSH_POS);
1570 if (r) return r;
1571 r = compile_tree(node->target, reg);
1572 if (r) return r;
1573 r = add_opcode(reg, OP_POP_POS);
1574 break;
1575
1576 case ANCHOR_PREC_READ_NOT:
1577 len = compile_length_tree(node->target, reg);
1578 if (len < 0) return len;
1579 r = add_opcode_rel_addr(reg, OP_PUSH_POS_NOT, len + SIZE_OP_FAIL_POS);
1580 if (r) return r;
1581 r = compile_tree(node->target, reg);
1582 if (r) return r;
1583 r = add_opcode(reg, OP_FAIL_POS);
1584 break;
1585
1586 case ANCHOR_LOOK_BEHIND:
1587 {
1588 int n;
1589 r = add_opcode(reg, OP_LOOK_BEHIND);
1590 if (r) return r;
1591 if (node->char_len < 0) {
1592 r = get_char_length_tree(node->target, reg, &n);
1593 if (r) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
1594 }
1595 else
1596 n = node->char_len;
1597 r = add_length(reg, n);
1598 if (r) return r;
1599 r = compile_tree(node->target, reg);
1600 }
1601 break;
1602
1603 case ANCHOR_LOOK_BEHIND_NOT:
1604 {
1605 int n;
1606 len = compile_length_tree(node->target, reg);
1607 r = add_opcode_rel_addr(reg, OP_PUSH_LOOK_BEHIND_NOT,
1608 len + SIZE_OP_FAIL_LOOK_BEHIND_NOT);
1609 if (r) return r;
1610 if (node->char_len < 0) {
1611 r = get_char_length_tree(node->target, reg, &n);
1612 if (r) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
1613 }
1614 else
1615 n = node->char_len;
1616 r = add_length(reg, n);
1617 if (r) return r;
1618 r = compile_tree(node->target, reg);
1619 if (r) return r;
1620 r = add_opcode(reg, OP_FAIL_LOOK_BEHIND_NOT);
1621 }
1622 break;
1623
1624 default:
1625 return ONIGERR_TYPE_BUG;
1626 break;
1627 }
1628
1629 return r;
1630}
1631
1632static int
1633compile_length_tree(Node* node, regex_t* reg)
1634{
1635 int len, type, r;
1636
1637 type = NTYPE(node);
1638 switch (type) {
1639 case NT_LIST:
1640 len = 0;
1641 do {
1642 r = compile_length_tree(NCAR(node), reg);
1643 if (r < 0) return r;
1644 len += r;
1645 } while (IS_NOT_NULL(node = NCDR(node)));
1646 r = len;
1647 break;
1648
1649 case NT_ALT:
1650 {
1651 int n = 0;
1652 len = 0;
1653 do {
1654 r = compile_length_tree(NCAR(node), reg);
1655 if (r < 0) return r;
1656 len += r;
1657 n++;
1658 } while (IS_NOT_NULL(node = NCDR(node)));
1659 r = len;
1660 r += (SIZE_OP_PUSH + SIZE_OP_JUMP) * (n - 1);
1661 }
1662 break;
1663
1664 case NT_STR:
1665 if (NSTRING_IS_RAW(node))
1666 r = compile_length_string_raw_node(NSTR(node), reg);
1667 else
1668 r = compile_length_string_node(node, reg);
1669 break;
1670
1671 case NT_CCLASS:
1672 r = compile_length_cclass_node(NCCLASS(node), reg);
1673 break;
1674
1675 case NT_CTYPE:
1676 case NT_CANY:
1677 r = SIZE_OPCODE;
1678 break;
1679
1680 case NT_BREF:
1681 {
1682 BRefNode* br = NBREF(node);
1683
1684#ifdef USE_BACKREF_WITH_LEVEL
1685 if (IS_BACKREF_NEST_LEVEL(br)) {
1686 r = SIZE_OPCODE + SIZE_OPTION + SIZE_LENGTH +
1687 SIZE_LENGTH + (SIZE_MEMNUM * br->back_num);
1688 }
1689 else
1690#endif
1691 if (br->back_num == 1) {
1692 r = ((!IS_IGNORECASE(reg->options) && br->back_static[0] <= 2)
1693 ? SIZE_OPCODE : (SIZE_OPCODE + SIZE_MEMNUM));
1694 }
1695 else {
1696 r = SIZE_OPCODE + SIZE_LENGTH + (SIZE_MEMNUM * br->back_num);
1697 }
1698 }
1699 break;
1700
1701#ifdef USE_SUBEXP_CALL
1702 case NT_CALL:
1703 r = SIZE_OP_CALL;
1704 break;
1705#endif
1706
1707 case NT_QTFR:
1708 r = compile_length_quantifier_node(NQTFR(node), reg);
1709 break;
1710
1711 case NT_ENCLOSE:
1712 r = compile_length_enclose_node(NENCLOSE(node), reg);
1713 break;
1714
1715 case NT_ANCHOR:
1716 r = compile_length_anchor_node(NANCHOR(node), reg);
1717 break;
1718
1719 default:
1720 return ONIGERR_TYPE_BUG;
1721 break;
1722 }
1723
1724 return r;
1725}
1726
1727static int
1728compile_tree(Node* node, regex_t* reg)
1729{
1730 int n, type, len, pos, r = 0;
1731
1732 type = NTYPE(node);
1733 switch (type) {
1734 case NT_LIST:
1735 do {
1736 r = compile_tree(NCAR(node), reg);
1737 } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
1738 break;
1739
1740 case NT_ALT:
1741 {
1742 Node* x = node;
1743 len = 0;
1744 do {
1745 len += compile_length_tree(NCAR(x), reg);
1746 if (NCDR(x) != NULL) {
1747 len += SIZE_OP_PUSH + SIZE_OP_JUMP;
1748 }
1749 } while (IS_NOT_NULL(x = NCDR(x)));
1750 pos = reg->used + len; /* goal position */
1751
1752 do {
1753 len = compile_length_tree(NCAR(node), reg);
1754 if (IS_NOT_NULL(NCDR(node))) {
1755 r = add_opcode_rel_addr(reg, OP_PUSH, len + SIZE_OP_JUMP);
1756 if (r) break;
1757 }
1758 r = compile_tree(NCAR(node), reg);
1759 if (r) break;
1760 if (IS_NOT_NULL(NCDR(node))) {
1761 len = pos - (reg->used + SIZE_OP_JUMP);
1762 r = add_opcode_rel_addr(reg, OP_JUMP, len);
1763 if (r) break;
1764 }
1765 } while (IS_NOT_NULL(node = NCDR(node)));
1766 }
1767 break;
1768
1769 case NT_STR:
1770 if (NSTRING_IS_RAW(node))
1771 r = compile_string_raw_node(NSTR(node), reg);
1772 else
1773 r = compile_string_node(node, reg);
1774 break;
1775
1776 case NT_CCLASS:
1777 r = compile_cclass_node(NCCLASS(node), reg);
1778 break;
1779
1780 case NT_CTYPE:
1781 {
1782 int op;
1783
1784 switch (NCTYPE(node)->ctype) {
1785 case ONIGENC_CTYPE_WORD:
1786 if (NCTYPE(node)->ascii_range != 0) {
1787 if (NCTYPE(node)->not != 0) op = OP_NOT_ASCII_WORD;
1788 else op = OP_ASCII_WORD;
1789 }
1790 else {
1791 if (NCTYPE(node)->not != 0) op = OP_NOT_WORD;
1792 else op = OP_WORD;
1793 }
1794 break;
1795 default:
1796 return ONIGERR_TYPE_BUG;
1797 break;
1798 }
1799 r = add_opcode(reg, op);
1800 }
1801 break;
1802
1803 case NT_CANY:
1804 if (IS_MULTILINE(reg->options))
1805 r = add_opcode(reg, OP_ANYCHAR_ML);
1806 else
1807 r = add_opcode(reg, OP_ANYCHAR);
1808 break;
1809
1810 case NT_BREF:
1811 {
1812 BRefNode* br = NBREF(node);
1813
1814#ifdef USE_BACKREF_WITH_LEVEL
1815 if (IS_BACKREF_NEST_LEVEL(br)) {
1816 r = add_opcode(reg, OP_BACKREF_WITH_LEVEL);
1817 if (r) return r;
1818 r = add_option(reg, (reg->options & ONIG_OPTION_IGNORECASE));
1819 if (r) return r;
1820 r = add_length(reg, br->nest_level);
1821 if (r) return r;
1822
1823 goto add_bacref_mems;
1824 }
1825 else
1826#endif
1827 if (br->back_num == 1) {
1828 n = br->back_static[0];
1829 if (IS_IGNORECASE(reg->options)) {
1830 r = add_opcode(reg, OP_BACKREFN_IC);
1831 if (r) return r;
1832 r = add_mem_num(reg, n);
1833 }
1834 else {
1835 switch (n) {
1836 case 1: r = add_opcode(reg, OP_BACKREF1); break;
1837 case 2: r = add_opcode(reg, OP_BACKREF2); break;
1838 default:
1839 r = add_opcode(reg, OP_BACKREFN);
1840 if (r) return r;
1841 r = add_mem_num(reg, n);
1842 break;
1843 }
1844 }
1845 }
1846 else {
1847 int i;
1848 int* p;
1849
1850 if (IS_IGNORECASE(reg->options)) {
1851 r = add_opcode(reg, OP_BACKREF_MULTI_IC);
1852 }
1853 else {
1854 r = add_opcode(reg, OP_BACKREF_MULTI);
1855 }
1856 if (r) return r;
1857
1858#ifdef USE_BACKREF_WITH_LEVEL
1859 add_bacref_mems:
1860#endif
1861 r = add_length(reg, br->back_num);
1862 if (r) return r;
1863 p = BACKREFS_P(br);
1864 for (i = br->back_num - 1; i >= 0; i--) {
1865 r = add_mem_num(reg, p[i]);
1866 if (r) return r;
1867 }
1868 }
1869 }
1870 break;
1871
1872#ifdef USE_SUBEXP_CALL
1873 case NT_CALL:
1874 r = compile_call(NCALL(node), reg);
1875 break;
1876#endif
1877
1878 case NT_QTFR:
1879 r = compile_quantifier_node(NQTFR(node), reg);
1880 break;
1881
1882 case NT_ENCLOSE:
1883 r = compile_enclose_node(NENCLOSE(node), reg);
1884 break;
1885
1886 case NT_ANCHOR:
1887 r = compile_anchor_node(NANCHOR(node), reg);
1888 break;
1889
1890 default:
1891#ifdef ONIG_DEBUG
1892 fprintf(stderr, "compile_tree: undefined node type %d\n", NTYPE(node));
1893#endif
1894 break;
1895 }
1896
1897 return r;
1898}
1899
1900#ifdef USE_NAMED_GROUP
1901
1902static int
1903noname_disable_map(Node** plink, GroupNumRemap* map, int* counter)
1904{
1905 int r = 0;
1906 Node* node = *plink;
1907
1908 switch (NTYPE(node)) {
1909 case NT_LIST:
1910 case NT_ALT:
1911 do {
1912 r = noname_disable_map(&(NCAR(node)), map, counter);
1913 } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
1914 break;
1915
1916 case NT_QTFR:
1917 {
1918 Node** ptarget = &(NQTFR(node)->target);
1919 Node* old = *ptarget;
1920 r = noname_disable_map(ptarget, map, counter);
1921 if (*ptarget != old && NTYPE(*ptarget) == NT_QTFR) {
1922 onig_reduce_nested_quantifier(node, *ptarget);
1923 }
1924 }
1925 break;
1926
1927 case NT_ENCLOSE:
1928 {
1929 EncloseNode* en = NENCLOSE(node);
1930 if (en->type == ENCLOSE_MEMORY) {
1931 if (IS_ENCLOSE_NAMED_GROUP(en)) {
1932 (*counter)++;
1933 map[en->regnum].new_val = *counter;
1934 en->regnum = *counter;
1935 }
1936 else if (en->regnum != 0) {
1937 *plink = en->target;
1938 en->target = NULL_NODE;
1939 onig_node_free(node);
1940 r = noname_disable_map(plink, map, counter);
1941 break;
1942 }
1943 }
1944 r = noname_disable_map(&(en->target), map, counter);
1945 }
1946 break;
1947
1948 case NT_ANCHOR:
1949 if (NANCHOR(node)->target)
1950 r = noname_disable_map(&(NANCHOR(node)->target), map, counter);
1951 break;
1952
1953 default:
1954 break;
1955 }
1956
1957 return r;
1958}
1959
1960static int
1961renumber_node_backref(Node* node, GroupNumRemap* map, const int num_mem)
1962{
1963 int i, pos, n, old_num;
1964 int *backs;
1965 BRefNode* bn = NBREF(node);
1966
1967 if (! IS_BACKREF_NAME_REF(bn))
1968 return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;
1969
1970 old_num = bn->back_num;
1971 if (IS_NULL(bn->back_dynamic))
1972 backs = bn->back_static;
1973 else
1974 backs = bn->back_dynamic;
1975
1976 for (i = 0, pos = 0; i < old_num; i++) {
1977 if (backs[i] > num_mem) return ONIGERR_INVALID_BACKREF;
1978 n = map[backs[i]].new_val;
1979 if (n > 0) {
1980 backs[pos] = n;
1981 pos++;
1982 }
1983 }
1984
1985 bn->back_num = pos;
1986 return 0;
1987}
1988
1989static int
1990renumber_by_map(Node* node, GroupNumRemap* map, const int num_mem)
1991{
1992 int r = 0;
1993
1994 switch (NTYPE(node)) {
1995 case NT_LIST:
1996 case NT_ALT:
1997 do {
1998 r = renumber_by_map(NCAR(node), map, num_mem);
1999 } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
2000 break;
2001 case NT_QTFR:
2002 r = renumber_by_map(NQTFR(node)->target, map, num_mem);
2003 break;
2004 case NT_ENCLOSE:
2005 {
2006 EncloseNode* en = NENCLOSE(node);
2007 if (en->type == ENCLOSE_CONDITION) {
2008 if (en->regnum > num_mem) return ONIGERR_INVALID_BACKREF;
2009 en->regnum = map[en->regnum].new_val;
2010 }
2011 r = renumber_by_map(en->target, map, num_mem);
2012 }
2013 break;
2014
2015 case NT_BREF:
2016 r = renumber_node_backref(node, map, num_mem);
2017 break;
2018
2019 case NT_ANCHOR:
2020 if (NANCHOR(node)->target)
2021 r = renumber_by_map(NANCHOR(node)->target, map, num_mem);
2022 break;
2023
2024 default:
2025 break;
2026 }
2027
2028 return r;
2029}
2030
2031static int
2032numbered_ref_check(Node* node)
2033{
2034 int r = 0;
2035
2036 switch (NTYPE(node)) {
2037 case NT_LIST:
2038 case NT_ALT:
2039 do {
2040 r = numbered_ref_check(NCAR(node));
2041 } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
2042 break;
2043 case NT_QTFR:
2044 r = numbered_ref_check(NQTFR(node)->target);
2045 break;
2046 case NT_ENCLOSE:
2047 r = numbered_ref_check(NENCLOSE(node)->target);
2048 break;
2049
2050 case NT_BREF:
2051 if (! IS_BACKREF_NAME_REF(NBREF(node)))
2052 return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;
2053 break;
2054
2055 case NT_ANCHOR:
2056 if (NANCHOR(node)->target)
2057 r = numbered_ref_check(NANCHOR(node)->target);
2058 break;
2059
2060 default:
2061 break;
2062 }
2063
2064 return r;
2065}
2066
2067static int
2068disable_noname_group_capture(Node** root, regex_t* reg, ScanEnv* env)
2069{
2070 int r, i, pos, counter;
2071 BitStatusType loc;
2072 GroupNumRemap* map;
2073
2074 map = (GroupNumRemap* )xalloca(sizeof(GroupNumRemap) * (env->num_mem + 1));
2075 CHECK_NULL_RETURN_MEMERR(map);
2076 for (i = 1; i <= env->num_mem; i++) {
2077 map[i].new_val = 0;
2078 }
2079 counter = 0;
2080 r = noname_disable_map(root, map, &counter);
2081 if (r != 0) return r;
2082
2083 r = renumber_by_map(*root, map, env->num_mem);
2084 if (r != 0) return r;
2085
2086 for (i = 1, pos = 1; i <= env->num_mem; i++) {
2087 if (map[i].new_val > 0) {
2088 SCANENV_MEM_NODES(env)[pos] = SCANENV_MEM_NODES(env)[i];
2089 pos++;
2090 }
2091 }
2092
2093 loc = env->capture_history;
2094 BIT_STATUS_CLEAR(env->capture_history);
2095 for (i = 1; i <= ONIG_MAX_CAPTURE_HISTORY_GROUP; i++) {
2096 if (BIT_STATUS_AT(loc, i)) {
2097 BIT_STATUS_ON_AT_SIMPLE(env->capture_history, map[i].new_val);
2098 }
2099 }
2100
2101 env->num_mem = env->num_named;
2102 reg->num_mem = env->num_named;
2103
2104 return onig_renumber_name_table(reg, map);
2105}
2106#endif /* USE_NAMED_GROUP */
2107
2108#ifdef USE_SUBEXP_CALL
2109static int
2110unset_addr_list_fix(UnsetAddrList* uslist, regex_t* reg)
2111{
2112 int i, offset;
2113 EncloseNode* en;
2114 AbsAddrType addr;
2115
2116 for (i = 0; i < uslist->num; i++) {
2117 en = NENCLOSE(uslist->us[i].target);
2118 if (! IS_ENCLOSE_ADDR_FIXED(en)) return ONIGERR_PARSER_BUG;
2119 addr = en->call_addr;
2120 offset = uslist->us[i].offset;
2121
2122 BBUF_WRITE(reg, offset, &addr, SIZE_ABSADDR);
2123 }
2124 return 0;
2125}
2126#endif
2127
2128#ifdef USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT
2129static int
2130quantifiers_memory_node_info(Node* node)
2131{
2132 int r = 0;
2133
2134 switch (NTYPE(node)) {
2135 case NT_LIST:
2136 case NT_ALT:
2137 {
2138 int v;
2139 do {
2140 v = quantifiers_memory_node_info(NCAR(node));
2141 if (v > r) r = v;
2142 } while (v >= 0 && IS_NOT_NULL(node = NCDR(node)));
2143 }
2144 break;
2145
2146# ifdef USE_SUBEXP_CALL
2147 case NT_CALL:
2148 if (IS_CALL_RECURSION(NCALL(node))) {
2149 return NQ_TARGET_IS_EMPTY_REC; /* tiny version */
2150 }
2151 else
2152 r = quantifiers_memory_node_info(NCALL(node)->target);
2153 break;
2154# endif
2155
2156 case NT_QTFR:
2157 {
2158 QtfrNode* qn = NQTFR(node);
2159 if (qn->upper != 0) {
2160 r = quantifiers_memory_node_info(qn->target);
2161 }
2162 }
2163 break;
2164
2165 case NT_ENCLOSE:
2166 {
2167 EncloseNode* en = NENCLOSE(node);
2168 switch (en->type) {
2169 case ENCLOSE_MEMORY:
2170 return NQ_TARGET_IS_EMPTY_MEM;
2171 break;
2172
2173 case ENCLOSE_OPTION:
2174 case ENCLOSE_STOP_BACKTRACK:
2175 case ENCLOSE_CONDITION:
2176 case ENCLOSE_ABSENT:
2177 r = quantifiers_memory_node_info(en->target);
2178 break;
2179 default:
2180 break;
2181 }
2182 }
2183 break;
2184
2185 case NT_BREF:
2186 case NT_STR:
2187 case NT_CTYPE:
2188 case NT_CCLASS:
2189 case NT_CANY:
2190 case NT_ANCHOR:
2191 default:
2192 break;
2193 }
2194
2195 return r;
2196}
2197#endif /* USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT */
2198
2199static int
2200get_min_match_length(Node* node, OnigDistance *min, ScanEnv* env)
2201{
2202 OnigDistance tmin;
2203 int r = 0;
2204
2205 *min = 0;
2206 switch (NTYPE(node)) {
2207 case NT_BREF:
2208 {
2209 int i;
2210 int* backs;
2211 Node** nodes = SCANENV_MEM_NODES(env);
2212 BRefNode* br = NBREF(node);
2213 if (br->state & NST_RECURSION) break;
2214
2215 backs = BACKREFS_P(br);
2216 if (backs[0] > env->num_mem) return ONIGERR_INVALID_BACKREF;
2217 r = get_min_match_length(nodes[backs[0]], min, env);
2218 if (r != 0) break;
2219 for (i = 1; i < br->back_num; i++) {
2220 if (backs[i] > env->num_mem) return ONIGERR_INVALID_BACKREF;
2221 r = get_min_match_length(nodes[backs[i]], &tmin, env);
2222 if (r != 0) break;
2223 if (*min > tmin) *min = tmin;
2224 }
2225 }
2226 break;
2227
2228#ifdef USE_SUBEXP_CALL
2229 case NT_CALL:
2230 if (IS_CALL_RECURSION(NCALL(node))) {
2231 EncloseNode* en = NENCLOSE(NCALL(node)->target);
2232 if (IS_ENCLOSE_MIN_FIXED(en))
2233 *min = en->min_len;
2234 }
2235 else
2236 r = get_min_match_length(NCALL(node)->target, min, env);
2237 break;
2238#endif
2239
2240 case NT_LIST:
2241 do {
2242 r = get_min_match_length(NCAR(node), &tmin, env);
2243 if (r == 0) *min += tmin;
2244 } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
2245 break;
2246
2247 case NT_ALT:
2248 {
2249 Node *x, *y;
2250 y = node;
2251 do {
2252 x = NCAR(y);
2253 r = get_min_match_length(x, &tmin, env);
2254 if (r != 0) break;
2255 if (y == node) *min = tmin;
2256 else if (*min > tmin) *min = tmin;
2257 } while (r == 0 && IS_NOT_NULL(y = NCDR(y)));
2258 }
2259 break;
2260
2261 case NT_STR:
2262 {
2263 StrNode* sn = NSTR(node);
2264 *min = sn->end - sn->s;
2265 }
2266 break;
2267
2268 case NT_CTYPE:
2269 *min = 1;
2270 break;
2271
2272 case NT_CCLASS:
2273 case NT_CANY:
2274 *min = 1;
2275 break;
2276
2277 case NT_QTFR:
2278 {
2279 QtfrNode* qn = NQTFR(node);
2280
2281 if (qn->lower > 0) {
2282 r = get_min_match_length(qn->target, min, env);
2283 if (r == 0)
2284 *min = distance_multiply(*min, qn->lower);
2285 }
2286 }
2287 break;
2288
2289 case NT_ENCLOSE:
2290 {
2291 EncloseNode* en = NENCLOSE(node);
2292 switch (en->type) {
2293 case ENCLOSE_MEMORY:
2294 if (IS_ENCLOSE_MIN_FIXED(en))
2295 *min = en->min_len;
2296 else {
2297 if (IS_ENCLOSE_MARK1(NENCLOSE(node)))
2298 *min = 0; /* recursive */
2299 else {
2300 SET_ENCLOSE_STATUS(node, NST_MARK1);
2301 r = get_min_match_length(en->target, min, env);
2302 CLEAR_ENCLOSE_STATUS(node, NST_MARK1);
2303 if (r == 0) {
2304 en->min_len = *min;
2305 SET_ENCLOSE_STATUS(node, NST_MIN_FIXED);
2306 }
2307 }
2308 }
2309 break;
2310
2311 case ENCLOSE_OPTION:
2312 case ENCLOSE_STOP_BACKTRACK:
2313 case ENCLOSE_CONDITION:
2314 r = get_min_match_length(en->target, min, env);
2315 break;
2316
2317 case ENCLOSE_ABSENT:
2318 break;
2319 }
2320 }
2321 break;
2322
2323 case NT_ANCHOR:
2324 default:
2325 break;
2326 }
2327
2328 return r;
2329}
2330
2331static int
2332get_max_match_length(Node* node, OnigDistance *max, ScanEnv* env)
2333{
2334 OnigDistance tmax;
2335 int r = 0;
2336
2337 *max = 0;
2338 switch (NTYPE(node)) {
2339 case NT_LIST:
2340 do {
2341 r = get_max_match_length(NCAR(node), &tmax, env);
2342 if (r == 0)
2343 *max = distance_add(*max, tmax);
2344 } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
2345 break;
2346
2347 case NT_ALT:
2348 do {
2349 r = get_max_match_length(NCAR(node), &tmax, env);
2350 if (r == 0 && *max < tmax) *max = tmax;
2351 } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
2352 break;
2353
2354 case NT_STR:
2355 {
2356 StrNode* sn = NSTR(node);
2357 *max = sn->end - sn->s;
2358 }
2359 break;
2360
2361 case NT_CTYPE:
2362 *max = ONIGENC_MBC_MAXLEN_DIST(env->enc);
2363 break;
2364
2365 case NT_CCLASS:
2366 case NT_CANY:
2367 *max = ONIGENC_MBC_MAXLEN_DIST(env->enc);
2368 break;
2369
2370 case NT_BREF:
2371 {
2372 int i;
2373 int* backs;
2374 Node** nodes = SCANENV_MEM_NODES(env);
2375 BRefNode* br = NBREF(node);
2376 if (br->state & NST_RECURSION) {
2377 *max = ONIG_INFINITE_DISTANCE;
2378 break;
2379 }
2380 backs = BACKREFS_P(br);
2381 for (i = 0; i < br->back_num; i++) {
2382 if (backs[i] > env->num_mem) return ONIGERR_INVALID_BACKREF;
2383 r = get_max_match_length(nodes[backs[i]], &tmax, env);
2384 if (r != 0) break;
2385 if (*max < tmax) *max = tmax;
2386 }
2387 }
2388 break;
2389
2390#ifdef USE_SUBEXP_CALL
2391 case NT_CALL:
2392 if (! IS_CALL_RECURSION(NCALL(node)))
2393 r = get_max_match_length(NCALL(node)->target, max, env);
2394 else
2395 *max = ONIG_INFINITE_DISTANCE;
2396 break;
2397#endif
2398
2399 case NT_QTFR:
2400 {
2401 QtfrNode* qn = NQTFR(node);
2402
2403 if (qn->upper != 0) {
2404 r = get_max_match_length(qn->target, max, env);
2405 if (r == 0 && *max != 0) {
2406 if (! IS_REPEAT_INFINITE(qn->upper))
2407 *max = distance_multiply(*max, qn->upper);
2408 else
2409 *max = ONIG_INFINITE_DISTANCE;
2410 }
2411 }
2412 }
2413 break;
2414
2415 case NT_ENCLOSE:
2416 {
2417 EncloseNode* en = NENCLOSE(node);
2418 switch (en->type) {
2419 case ENCLOSE_MEMORY:
2420 if (IS_ENCLOSE_MAX_FIXED(en))
2421 *max = en->max_len;
2422 else {
2423 if (IS_ENCLOSE_MARK1(NENCLOSE(node)))
2424 *max = ONIG_INFINITE_DISTANCE;
2425 else {
2426 SET_ENCLOSE_STATUS(node, NST_MARK1);
2427 r = get_max_match_length(en->target, max, env);
2428 CLEAR_ENCLOSE_STATUS(node, NST_MARK1);
2429 if (r == 0) {
2430 en->max_len = *max;
2431 SET_ENCLOSE_STATUS(node, NST_MAX_FIXED);
2432 }
2433 }
2434 }
2435 break;
2436
2437 case ENCLOSE_OPTION:
2438 case ENCLOSE_STOP_BACKTRACK:
2439 case ENCLOSE_CONDITION:
2440 r = get_max_match_length(en->target, max, env);
2441 break;
2442
2443 case ENCLOSE_ABSENT:
2444 break;
2445 }
2446 }
2447 break;
2448
2449 case NT_ANCHOR:
2450 default:
2451 break;
2452 }
2453
2454 return r;
2455}
2456
2457#define GET_CHAR_LEN_VARLEN -1
2458#define GET_CHAR_LEN_TOP_ALT_VARLEN -2
2459
2460/* fixed size pattern node only */
2461static int
2462get_char_length_tree1(Node* node, regex_t* reg, int* len, int level)
2463{
2464 int tlen;
2465 int r = 0;
2466
2467 level++;
2468 *len = 0;
2469 switch (NTYPE(node)) {
2470 case NT_LIST:
2471 do {
2472 r = get_char_length_tree1(NCAR(node), reg, &tlen, level);
2473 if (r == 0)
2474 *len = (int )distance_add(*len, tlen);
2475 } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
2476 break;
2477
2478 case NT_ALT:
2479 {
2480 int tlen2;
2481 int varlen = 0;
2482
2483 r = get_char_length_tree1(NCAR(node), reg, &tlen, level);
2484 while (r == 0 && IS_NOT_NULL(node = NCDR(node))) {
2485 r = get_char_length_tree1(NCAR(node), reg, &tlen2, level);
2486 if (r == 0) {
2487 if (tlen != tlen2)
2488 varlen = 1;
2489 }
2490 }
2491 if (r == 0) {
2492 if (varlen != 0) {
2493 if (level == 1)
2494 r = GET_CHAR_LEN_TOP_ALT_VARLEN;
2495 else
2496 r = GET_CHAR_LEN_VARLEN;
2497 }
2498 else
2499 *len = tlen;
2500 }
2501 }
2502 break;
2503
2504 case NT_STR:
2505 {
2506 StrNode* sn = NSTR(node);
2507 UChar *s = sn->s;
2508 while (s < sn->end) {
2509 s += enclen(reg->enc, s, sn->end);
2510 (*len)++;
2511 }
2512 }
2513 break;
2514
2515 case NT_QTFR:
2516 {
2517 QtfrNode* qn = NQTFR(node);
2518 if (qn->lower == qn->upper) {
2519 r = get_char_length_tree1(qn->target, reg, &tlen, level);
2520 if (r == 0)
2521 *len = (int )distance_multiply(tlen, qn->lower);
2522 }
2523 else
2524 r = GET_CHAR_LEN_VARLEN;
2525 }
2526 break;
2527
2528#ifdef USE_SUBEXP_CALL
2529 case NT_CALL:
2530 if (! IS_CALL_RECURSION(NCALL(node)))
2531 r = get_char_length_tree1(NCALL(node)->target, reg, len, level);
2532 else
2533 r = GET_CHAR_LEN_VARLEN;
2534 break;
2535#endif
2536
2537 case NT_CTYPE:
2538 *len = 1;
2539 break;
2540
2541 case NT_CCLASS:
2542 case NT_CANY:
2543 *len = 1;
2544 break;
2545
2546 case NT_ENCLOSE:
2547 {
2548 EncloseNode* en = NENCLOSE(node);
2549 switch (en->type) {
2550 case ENCLOSE_MEMORY:
2551#ifdef USE_SUBEXP_CALL
2552 if (IS_ENCLOSE_CLEN_FIXED(en))
2553 *len = en->char_len;
2554 else {
2555 r = get_char_length_tree1(en->target, reg, len, level);
2556 if (r == 0) {
2557 en->char_len = *len;
2558 SET_ENCLOSE_STATUS(node, NST_CLEN_FIXED);
2559 }
2560 }
2561 break;
2562#endif
2563 case ENCLOSE_OPTION:
2564 case ENCLOSE_STOP_BACKTRACK:
2565 case ENCLOSE_CONDITION:
2566 r = get_char_length_tree1(en->target, reg, len, level);
2567 break;
2568 case ENCLOSE_ABSENT:
2569 default:
2570 break;
2571 }
2572 }
2573 break;
2574
2575 case NT_ANCHOR:
2576 break;
2577
2578 default:
2579 r = GET_CHAR_LEN_VARLEN;
2580 break;
2581 }
2582
2583 return r;
2584}
2585
2586static int
2587get_char_length_tree(Node* node, regex_t* reg, int* len)
2588{
2589 return get_char_length_tree1(node, reg, len, 0);
2590}
2591
2592/* x is not included y ==> 1 : 0 */
2593static int
2594is_not_included(Node* x, Node* y, regex_t* reg)
2595{
2596 int i;
2597 OnigDistance len;
2598 OnigCodePoint code;
2599 UChar *p;
2600 int ytype;
2601
2602 retry:
2603 ytype = NTYPE(y);
2604 switch (NTYPE(x)) {
2605 case NT_CTYPE:
2606 {
2607 switch (ytype) {
2608 case NT_CTYPE:
2609 if (NCTYPE(y)->ctype == NCTYPE(x)->ctype &&
2610 NCTYPE(y)->not != NCTYPE(x)->not &&
2611 NCTYPE(y)->ascii_range == NCTYPE(x)->ascii_range)
2612 return 1;
2613 else
2614 return 0;
2615 break;
2616
2617 case NT_CCLASS:
2618 swap:
2619 {
2620 Node* tmp;
2621 tmp = x; x = y; y = tmp;
2622 goto retry;
2623 }
2624 break;
2625
2626 case NT_STR:
2627 goto swap;
2628 break;
2629
2630 default:
2631 break;
2632 }
2633 }
2634 break;
2635
2636 case NT_CCLASS:
2637 {
2638 CClassNode* xc = NCCLASS(x);
2639 switch (ytype) {
2640 case NT_CTYPE:
2641 switch (NCTYPE(y)->ctype) {
2642 case ONIGENC_CTYPE_WORD:
2643 if (NCTYPE(y)->not == 0) {
2644 if (IS_NULL(xc->mbuf) && !IS_NCCLASS_NOT(xc)) {
2645 for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
2646 if (BITSET_AT(xc->bs, i)) {
2647 if (NCTYPE(y)->ascii_range) {
2648 if (IS_CODE_SB_WORD(reg->enc, i)) return 0;
2649 }
2650 else {
2651 if (ONIGENC_IS_CODE_WORD(reg->enc, i)) return 0;
2652 }
2653 }
2654 }
2655 return 1;
2656 }
2657 return 0;
2658 }
2659 else {
2660 if (IS_NOT_NULL(xc->mbuf)) return 0;
2661 for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
2662 int is_word;
2663 if (NCTYPE(y)->ascii_range)
2664 is_word = IS_CODE_SB_WORD(reg->enc, i);
2665 else
2666 is_word = ONIGENC_IS_CODE_WORD(reg->enc, i);
2667 if (! is_word) {
2668 if (!IS_NCCLASS_NOT(xc)) {
2669 if (BITSET_AT(xc->bs, i))
2670 return 0;
2671 }
2672 else {
2673 if (! BITSET_AT(xc->bs, i))
2674 return 0;
2675 }
2676 }
2677 }
2678 return 1;
2679 }
2680 break;
2681
2682 default:
2683 break;
2684 }
2685 break;
2686
2687 case NT_CCLASS:
2688 {
2689 int v;
2690 CClassNode* yc = NCCLASS(y);
2691
2692 for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
2693 v = BITSET_AT(xc->bs, i);
2694 if ((v != 0 && !IS_NCCLASS_NOT(xc)) ||
2695 (v == 0 && IS_NCCLASS_NOT(xc))) {
2696 v = BITSET_AT(yc->bs, i);
2697 if ((v != 0 && !IS_NCCLASS_NOT(yc)) ||
2698 (v == 0 && IS_NCCLASS_NOT(yc)))
2699 return 0;
2700 }
2701 }
2702 if ((IS_NULL(xc->mbuf) && !IS_NCCLASS_NOT(xc)) ||
2703 (IS_NULL(yc->mbuf) && !IS_NCCLASS_NOT(yc)))
2704 return 1;
2705 return 0;
2706 }
2707 break;
2708
2709 case NT_STR:
2710 goto swap;
2711 break;
2712
2713 default:
2714 break;
2715 }
2716 }
2717 break;
2718
2719 case NT_STR:
2720 {
2721 StrNode* xs = NSTR(x);
2722 if (NSTRING_LEN(x) == 0)
2723 break;
2724
2725 switch (ytype) {
2726 case NT_CTYPE:
2727 switch (NCTYPE(y)->ctype) {
2728 case ONIGENC_CTYPE_WORD:
2729 if (NCTYPE(y)->ascii_range) {
2730 if (ONIGENC_IS_MBC_ASCII_WORD(reg->enc, xs->s, xs->end))
2731 return NCTYPE(y)->not;
2732 else
2733 return !(NCTYPE(y)->not);
2734 }
2735 else {
2736 if (ONIGENC_IS_MBC_WORD(reg->enc, xs->s, xs->end))
2737 return NCTYPE(y)->not;
2738 else
2739 return !(NCTYPE(y)->not);
2740 }
2741 break;
2742 default:
2743 break;
2744 }
2745 break;
2746
2747 case NT_CCLASS:
2748 {
2749 CClassNode* cc = NCCLASS(y);
2750
2751 code = ONIGENC_MBC_TO_CODE(reg->enc, xs->s,
2752 xs->s + ONIGENC_MBC_MAXLEN(reg->enc));
2753 return (onig_is_code_in_cc(reg->enc, code, cc) != 0 ? 0 : 1);
2754 }
2755 break;
2756
2757 case NT_STR:
2758 {
2759 UChar *q;
2760 StrNode* ys = NSTR(y);
2761 len = NSTRING_LEN(x);
2762 if (len > NSTRING_LEN(y)) len = NSTRING_LEN(y);
2763 if (NSTRING_IS_AMBIG(x) || NSTRING_IS_AMBIG(y)) {
2764 /* tiny version */
2765 return 0;
2766 }
2767 else {
2768 for (i = 0, p = ys->s, q = xs->s; (OnigDistance )i < len; i++, p++, q++) {
2769 if (*p != *q) return 1;
2770 }
2771 }
2772 }
2773 break;
2774
2775 default:
2776 break;
2777 }
2778 }
2779 break;
2780
2781 default:
2782 break;
2783 }
2784
2785 return 0;
2786}
2787
2788static Node*
2789get_head_value_node(Node* node, int exact, regex_t* reg)
2790{
2791 Node* n = NULL_NODE;
2792
2793 switch (NTYPE(node)) {
2794 case NT_BREF:
2795 case NT_ALT:
2796 case NT_CANY:
2797#ifdef USE_SUBEXP_CALL
2798 case NT_CALL:
2799#endif
2800 break;
2801
2802 case NT_CTYPE:
2803 case NT_CCLASS:
2804 if (exact == 0) {
2805 n = node;
2806 }
2807 break;
2808
2809 case NT_LIST:
2810 n = get_head_value_node(NCAR(node), exact, reg);
2811 break;
2812
2813 case NT_STR:
2814 {
2815 StrNode* sn = NSTR(node);
2816 if (sn->end <= sn->s)
2817 break;
2818
2819 if (exact == 0 ||
2820 NSTRING_IS_RAW(node) || !IS_IGNORECASE(reg->options)) {
2821 n = node;
2822 }
2823 }
2824 break;
2825
2826 case NT_QTFR:
2827 {
2828 QtfrNode* qn = NQTFR(node);
2829 if (qn->lower > 0) {
2830#ifdef USE_OP_PUSH_OR_JUMP_EXACT
2831 if (IS_NOT_NULL(qn->head_exact))
2832 n = qn->head_exact;
2833 else
2834#endif
2835 n = get_head_value_node(qn->target, exact, reg);
2836 }
2837 }
2838 break;
2839
2840 case NT_ENCLOSE:
2841 {
2842 EncloseNode* en = NENCLOSE(node);
2843 switch (en->type) {
2844 case ENCLOSE_OPTION:
2845 {
2846 OnigOptionType options = reg->options;
2847
2848 reg->options = NENCLOSE(node)->option;
2849 n = get_head_value_node(NENCLOSE(node)->target, exact, reg);
2850 reg->options = options;
2851 }
2852 break;
2853
2854 case ENCLOSE_MEMORY:
2855 case ENCLOSE_STOP_BACKTRACK:
2856 case ENCLOSE_CONDITION:
2857 n = get_head_value_node(en->target, exact, reg);
2858 break;
2859
2860 case ENCLOSE_ABSENT:
2861 break;
2862 }
2863 }
2864 break;
2865
2866 case NT_ANCHOR:
2867 if (NANCHOR(node)->type == ANCHOR_PREC_READ)
2868 n = get_head_value_node(NANCHOR(node)->target, exact, reg);
2869 break;
2870
2871 default:
2872 break;
2873 }
2874
2875 return n;
2876}
2877
2878static int
2879check_type_tree(Node* node, int type_mask, int enclose_mask, int anchor_mask)
2880{
2881 int type, r = 0;
2882
2883 type = NTYPE(node);
2884 if ((NTYPE2BIT(type) & type_mask) == 0)
2885 return 1;
2886
2887 switch (type) {
2888 case NT_LIST:
2889 case NT_ALT:
2890 do {
2891 r = check_type_tree(NCAR(node), type_mask, enclose_mask,
2892 anchor_mask);
2893 } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
2894 break;
2895
2896 case NT_QTFR:
2897 r = check_type_tree(NQTFR(node)->target, type_mask, enclose_mask,
2898 anchor_mask);
2899 break;
2900
2901 case NT_ENCLOSE:
2902 {
2903 EncloseNode* en = NENCLOSE(node);
2904 if ((en->type & enclose_mask) == 0)
2905 return 1;
2906
2907 r = check_type_tree(en->target, type_mask, enclose_mask, anchor_mask);
2908 }
2909 break;
2910
2911 case NT_ANCHOR:
2912 type = NANCHOR(node)->type;
2913 if ((type & anchor_mask) == 0)
2914 return 1;
2915
2916 if (NANCHOR(node)->target)
2917 r = check_type_tree(NANCHOR(node)->target,
2918 type_mask, enclose_mask, anchor_mask);
2919 break;
2920
2921 default:
2922 break;
2923 }
2924 return r;
2925}
2926
2927#ifdef USE_SUBEXP_CALL
2928
2929# define RECURSION_EXIST 1
2930# define RECURSION_INFINITE 2
2931
2932static int
2933subexp_inf_recursive_check(Node* node, ScanEnv* env, int head)
2934{
2935 int type;
2936 int r = 0;
2937
2938 type = NTYPE(node);
2939 switch (type) {
2940 case NT_LIST:
2941 {
2942 Node *x;
2943 OnigDistance min;
2944 int ret;
2945
2946 x = node;
2947 do {
2948 ret = subexp_inf_recursive_check(NCAR(x), env, head);
2949 if (ret < 0 || ret == RECURSION_INFINITE) return ret;
2950 r |= ret;
2951 if (head) {
2952 ret = get_min_match_length(NCAR(x), &min, env);
2953 if (ret != 0) return ret;
2954 if (min != 0) head = 0;
2955 }
2956 } while (IS_NOT_NULL(x = NCDR(x)));
2957 }
2958 break;
2959
2960 case NT_ALT:
2961 {
2962 int ret;
2963 r = RECURSION_EXIST;
2964 do {
2965 ret = subexp_inf_recursive_check(NCAR(node), env, head);
2966 if (ret < 0 || ret == RECURSION_INFINITE) return ret;
2967 r &= ret;
2968 } while (IS_NOT_NULL(node = NCDR(node)));
2969 }
2970 break;
2971
2972 case NT_QTFR:
2973 r = subexp_inf_recursive_check(NQTFR(node)->target, env, head);
2974 if (r == RECURSION_EXIST) {
2975 if (NQTFR(node)->lower == 0) r = 0;
2976 }
2977 break;
2978
2979 case NT_ANCHOR:
2980 {
2981 AnchorNode* an = NANCHOR(node);
2982 switch (an->type) {
2983 case ANCHOR_PREC_READ:
2984 case ANCHOR_PREC_READ_NOT:
2985 case ANCHOR_LOOK_BEHIND:
2986 case ANCHOR_LOOK_BEHIND_NOT:
2987 r = subexp_inf_recursive_check(an->target, env, head);
2988 break;
2989 }
2990 }
2991 break;
2992
2993 case NT_CALL:
2994 r = subexp_inf_recursive_check(NCALL(node)->target, env, head);
2995 break;
2996
2997 case NT_ENCLOSE:
2998 if (IS_ENCLOSE_MARK2(NENCLOSE(node)))
2999 return 0;
3000 else if (IS_ENCLOSE_MARK1(NENCLOSE(node)))
3001 return (head == 0 ? RECURSION_EXIST : RECURSION_INFINITE);
3002 else {
3003 SET_ENCLOSE_STATUS(node, NST_MARK2);
3004 r = subexp_inf_recursive_check(NENCLOSE(node)->target, env, head);
3005 CLEAR_ENCLOSE_STATUS(node, NST_MARK2);
3006 }
3007 break;
3008
3009 default:
3010 break;
3011 }
3012
3013 return r;
3014}
3015
3016static int
3017subexp_inf_recursive_check_trav(Node* node, ScanEnv* env)
3018{
3019 int type;
3020 int r = 0;
3021
3022 type = NTYPE(node);
3023 switch (type) {
3024 case NT_LIST:
3025 case NT_ALT:
3026 do {
3027 r = subexp_inf_recursive_check_trav(NCAR(node), env);
3028 } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
3029 break;
3030
3031 case NT_QTFR:
3032 r = subexp_inf_recursive_check_trav(NQTFR(node)->target, env);
3033 break;
3034
3035 case NT_ANCHOR:
3036 {
3037 AnchorNode* an = NANCHOR(node);
3038 switch (an->type) {
3039 case ANCHOR_PREC_READ:
3040 case ANCHOR_PREC_READ_NOT:
3041 case ANCHOR_LOOK_BEHIND:
3042 case ANCHOR_LOOK_BEHIND_NOT:
3043 r = subexp_inf_recursive_check_trav(an->target, env);
3044 break;
3045 }
3046 }
3047 break;
3048
3049 case NT_ENCLOSE:
3050 {
3051 EncloseNode* en = NENCLOSE(node);
3052
3053 if (IS_ENCLOSE_RECURSION(en)) {
3054 SET_ENCLOSE_STATUS(node, NST_MARK1);
3055 r = subexp_inf_recursive_check(en->target, env, 1);
3056 if (r > 0) return ONIGERR_NEVER_ENDING_RECURSION;
3057 CLEAR_ENCLOSE_STATUS(node, NST_MARK1);
3058 }
3059 r = subexp_inf_recursive_check_trav(en->target, env);
3060 }
3061
3062 break;
3063
3064 default:
3065 break;
3066 }
3067
3068 return r;
3069}
3070
3071static int
3072subexp_recursive_check(Node* node)
3073{
3074 int r = 0;
3075
3076 switch (NTYPE(node)) {
3077 case NT_LIST:
3078 case NT_ALT:
3079 do {
3080 r |= subexp_recursive_check(NCAR(node));
3081 } while (IS_NOT_NULL(node = NCDR(node)));
3082 break;
3083
3084 case NT_QTFR:
3085 r = subexp_recursive_check(NQTFR(node)->target);
3086 break;
3087
3088 case NT_ANCHOR:
3089 {
3090 AnchorNode* an = NANCHOR(node);
3091 switch (an->type) {
3092 case ANCHOR_PREC_READ:
3093 case ANCHOR_PREC_READ_NOT:
3094 case ANCHOR_LOOK_BEHIND:
3095 case ANCHOR_LOOK_BEHIND_NOT:
3096 r = subexp_recursive_check(an->target);
3097 break;
3098 }
3099 }
3100 break;
3101
3102 case NT_CALL:
3103 r = subexp_recursive_check(NCALL(node)->target);
3104 if (r != 0) SET_CALL_RECURSION(node);
3105 break;
3106
3107 case NT_ENCLOSE:
3108 if (IS_ENCLOSE_MARK2(NENCLOSE(node)))
3109 return 0;
3110 else if (IS_ENCLOSE_MARK1(NENCLOSE(node)))
3111 return 1; /* recursion */
3112 else {
3113 SET_ENCLOSE_STATUS(node, NST_MARK2);
3114 r = subexp_recursive_check(NENCLOSE(node)->target);
3115 CLEAR_ENCLOSE_STATUS(node, NST_MARK2);
3116 }
3117 break;
3118
3119 default:
3120 break;
3121 }
3122
3123 return r;
3124}
3125
3126
3127static int
3128subexp_recursive_check_trav(Node* node, ScanEnv* env)
3129{
3130# define FOUND_CALLED_NODE 1
3131
3132 int type;
3133 int r = 0;
3134
3135 type = NTYPE(node);
3136 switch (type) {
3137 case NT_LIST:
3138 case NT_ALT:
3139 {
3140 int ret;
3141 do {
3142 ret = subexp_recursive_check_trav(NCAR(node), env);
3143 if (ret == FOUND_CALLED_NODE) r = FOUND_CALLED_NODE;
3144 else if (ret < 0) return ret;
3145 } while (IS_NOT_NULL(node = NCDR(node)));
3146 }
3147 break;
3148
3149 case NT_QTFR:
3150 r = subexp_recursive_check_trav(NQTFR(node)->target, env);
3151 if (NQTFR(node)->upper == 0) {
3152 if (r == FOUND_CALLED_NODE)
3153 NQTFR(node)->is_referred = 1;
3154 }
3155 break;
3156
3157 case NT_ANCHOR:
3158 {
3159 AnchorNode* an = NANCHOR(node);
3160 switch (an->type) {
3161 case ANCHOR_PREC_READ:
3162 case ANCHOR_PREC_READ_NOT:
3163 case ANCHOR_LOOK_BEHIND:
3164 case ANCHOR_LOOK_BEHIND_NOT:
3165 r = subexp_recursive_check_trav(an->target, env);
3166 break;
3167 }
3168 }
3169 break;
3170
3171 case NT_ENCLOSE:
3172 {
3173 EncloseNode* en = NENCLOSE(node);
3174
3175 if (! IS_ENCLOSE_RECURSION(en)) {
3176 if (IS_ENCLOSE_CALLED(en)) {
3177 SET_ENCLOSE_STATUS(node, NST_MARK1);
3178 r = subexp_recursive_check(en->target);
3179 if (r != 0) SET_ENCLOSE_STATUS(node, NST_RECURSION);
3180 CLEAR_ENCLOSE_STATUS(node, NST_MARK1);
3181 }
3182 }
3183 r = subexp_recursive_check_trav(en->target, env);
3184 if (IS_ENCLOSE_CALLED(en))
3185 r |= FOUND_CALLED_NODE;
3186 }
3187 break;
3188
3189 default:
3190 break;
3191 }
3192
3193 return r;
3194}
3195
3196static int
3197setup_subexp_call(Node* node, ScanEnv* env)
3198{
3199 int type;
3200 int r = 0;
3201
3202 type = NTYPE(node);
3203 switch (type) {
3204 case NT_LIST:
3205 do {
3206 r = setup_subexp_call(NCAR(node), env);
3207 } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
3208 break;
3209
3210 case NT_ALT:
3211 do {
3212 r = setup_subexp_call(NCAR(node), env);
3213 } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
3214 break;
3215
3216 case NT_QTFR:
3217 r = setup_subexp_call(NQTFR(node)->target, env);
3218 break;
3219 case NT_ENCLOSE:
3220 r = setup_subexp_call(NENCLOSE(node)->target, env);
3221 break;
3222
3223 case NT_CALL:
3224 {
3225 CallNode* cn = NCALL(node);
3226 Node** nodes = SCANENV_MEM_NODES(env);
3227
3228 if (cn->group_num != 0) {
3229 int gnum = cn->group_num;
3230
3231# ifdef USE_NAMED_GROUP
3232 if (env->num_named > 0 &&
3233 IS_SYNTAX_BV(env->syntax, ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP) &&
3234 !ONIG_IS_OPTION_ON(env->option, ONIG_OPTION_CAPTURE_GROUP)) {
3235 return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;
3236 }
3237# endif
3238 if (gnum > env->num_mem) {
3239 onig_scan_env_set_error_string(env,
3240 ONIGERR_UNDEFINED_GROUP_REFERENCE, cn->name, cn->name_end);
3241 return ONIGERR_UNDEFINED_GROUP_REFERENCE;
3242 }
3243
3244# ifdef USE_NAMED_GROUP
3245 set_call_attr:
3246# endif
3247 cn->target = nodes[cn->group_num];
3248 if (IS_NULL(cn->target)) {
3249 onig_scan_env_set_error_string(env,
3250 ONIGERR_UNDEFINED_NAME_REFERENCE, cn->name, cn->name_end);
3251 return ONIGERR_UNDEFINED_NAME_REFERENCE;
3252 }
3253 SET_ENCLOSE_STATUS(cn->target, NST_CALLED);
3254 BIT_STATUS_ON_AT(env->bt_mem_start, cn->group_num);
3255 cn->unset_addr_list = env->unset_addr_list;
3256 }
3257# ifdef USE_NAMED_GROUP
3258# ifdef USE_PERL_SUBEXP_CALL
3259 else if (cn->name == cn->name_end) {
3260 goto set_call_attr;
3261 }
3262# endif
3263 else {
3264 int *refs;
3265
3266 int n = onig_name_to_group_numbers(env->reg, cn->name, cn->name_end,
3267 &refs);
3268 if (n <= 0) {
3269 onig_scan_env_set_error_string(env,
3270 ONIGERR_UNDEFINED_NAME_REFERENCE, cn->name, cn->name_end);
3271 return ONIGERR_UNDEFINED_NAME_REFERENCE;
3272 }
3273 else if (n > 1 &&
3274 ! IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME_CALL)) {
3275 onig_scan_env_set_error_string(env,
3276 ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL, cn->name, cn->name_end);
3277 return ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL;
3278 }
3279 else {
3280 cn->group_num = refs[0];
3281 goto set_call_attr;
3282 }
3283 }
3284# endif
3285 }
3286 break;
3287
3288 case NT_ANCHOR:
3289 {
3290 AnchorNode* an = NANCHOR(node);
3291
3292 switch (an->type) {
3293 case ANCHOR_PREC_READ:
3294 case ANCHOR_PREC_READ_NOT:
3295 case ANCHOR_LOOK_BEHIND:
3296 case ANCHOR_LOOK_BEHIND_NOT:
3297 r = setup_subexp_call(an->target, env);
3298 break;
3299 }
3300 }
3301 break;
3302
3303 default:
3304 break;
3305 }
3306
3307 return r;
3308}
3309#endif
3310
3311#define IN_ALT (1<<0)
3312#define IN_NOT (1<<1)
3313#define IN_REPEAT (1<<2)
3314#define IN_VAR_REPEAT (1<<3)
3315#define IN_CALL (1<<4)
3316#define IN_RECCALL (1<<5)
3317#define IN_LOOK_BEHIND (1<<6)
3318
3319/* divide different length alternatives in look-behind.
3320 (?<=A|B) ==> (?<=A)|(?<=B)
3321 (?<!A|B) ==> (?<!A)(?<!B)
3322*/
3323static int
3324divide_look_behind_alternatives(Node* node)
3325{
3326 Node *head, *np, *insert_node;
3327 AnchorNode* an = NANCHOR(node);
3328 int anc_type = an->type;
3329
3330 head = an->target;
3331 np = NCAR(head);
3332 swap_node(node, head);
3333 NCAR(node) = head;
3334 NANCHOR(head)->target = np;
3335
3336 np = node;
3337 while ((np = NCDR(np)) != NULL_NODE) {
3338 insert_node = onig_node_new_anchor(anc_type);
3339 CHECK_NULL_RETURN_MEMERR(insert_node);
3340 NANCHOR(insert_node)->target = NCAR(np);
3341 NCAR(np) = insert_node;
3342 }
3343
3344 if (anc_type == ANCHOR_LOOK_BEHIND_NOT) {
3345 np = node;
3346 do {
3347 SET_NTYPE(np, NT_LIST); /* alt -> list */
3348 } while ((np = NCDR(np)) != NULL_NODE);
3349 }
3350 return 0;
3351}
3352
3353static int
3354setup_look_behind(Node* node, regex_t* reg, ScanEnv* env)
3355{
3356 int r, len;
3357 AnchorNode* an = NANCHOR(node);
3358
3359 r = get_char_length_tree(an->target, reg, &len);
3360 if (r == 0)
3361 an->char_len = len;
3362 else if (r == GET_CHAR_LEN_VARLEN)
3363 r = ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
3364 else if (r == GET_CHAR_LEN_TOP_ALT_VARLEN) {
3365 if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_DIFFERENT_LEN_ALT_LOOK_BEHIND))
3366 r = divide_look_behind_alternatives(node);
3367 else
3368 r = ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
3369 }
3370
3371 return r;
3372}
3373
3374static int
3375next_setup(Node* node, Node* next_node, regex_t* reg)
3376{
3377 int type;
3378
3379 retry:
3380 type = NTYPE(node);
3381 if (type == NT_QTFR) {
3382 QtfrNode* qn = NQTFR(node);
3383 if (qn->greedy && IS_REPEAT_INFINITE(qn->upper)) {
3384#ifdef USE_QTFR_PEEK_NEXT
3385 Node* n = get_head_value_node(next_node, 1, reg);
3386 /* '\0': for UTF-16BE etc... */
3387 if (IS_NOT_NULL(n) && NSTR(n)->s[0] != '\0') {
3388 qn->next_head_exact = n;
3389 }
3390#endif
3391 /* automatic possessification a*b ==> (?>a*)b */
3392 if (qn->lower <= 1) {
3393 int ttype = NTYPE(qn->target);
3394 if (IS_NODE_TYPE_SIMPLE(ttype)) {
3395 Node *x, *y;
3396 x = get_head_value_node(qn->target, 0, reg);
3397 if (IS_NOT_NULL(x)) {
3398 y = get_head_value_node(next_node, 0, reg);
3399 if (IS_NOT_NULL(y) && is_not_included(x, y, reg)) {
3400 Node* en = onig_node_new_enclose(ENCLOSE_STOP_BACKTRACK);
3401 CHECK_NULL_RETURN_MEMERR(en);
3402 SET_ENCLOSE_STATUS(en, NST_STOP_BT_SIMPLE_REPEAT);
3403 swap_node(node, en);
3404 NENCLOSE(node)->target = en;
3405 }
3406 }
3407 }
3408 }
3409 }
3410 }
3411 else if (type == NT_ENCLOSE) {
3412 EncloseNode* en = NENCLOSE(node);
3413 if (en->type == ENCLOSE_MEMORY && !IS_ENCLOSE_CALLED(en)) {
3414 node = en->target;
3415 goto retry;
3416 }
3417 }
3418 return 0;
3419}
3420
3421
3422static int
3423update_string_node_case_fold(regex_t* reg, Node *node)
3424{
3425 UChar *p, *end, buf[ONIGENC_MBC_CASE_FOLD_MAXLEN];
3426 UChar *sbuf, *ebuf, *sp;
3427 int r, i, len;
3428 OnigDistance sbuf_size;
3429 StrNode* sn = NSTR(node);
3430
3431 end = sn->end;
3432 sbuf_size = (end - sn->s) * 2;
3433 sbuf = (UChar* )xmalloc(sbuf_size);
3434 CHECK_NULL_RETURN_MEMERR(sbuf);
3435 ebuf = sbuf + sbuf_size;
3436
3437 sp = sbuf;
3438 p = sn->s;
3439 while (p < end) {
3440 len = ONIGENC_MBC_CASE_FOLD(reg->enc, reg->case_fold_flag, &p, end, buf);
3441 for (i = 0; i < len; i++) {
3442 if (sp >= ebuf) {
3443 UChar* p = (UChar* )xrealloc(sbuf, sbuf_size * 2);
3444 if (IS_NULL(p)) {
3445 xfree(sbuf);
3446 return ONIGERR_MEMORY;
3447 }
3448 sbuf = p;
3449 sp = sbuf + sbuf_size;
3450 sbuf_size *= 2;
3451 ebuf = sbuf + sbuf_size;
3452 }
3453
3454 *sp++ = buf[i];
3455 }
3456 }
3457
3458 r = onig_node_str_set(node, sbuf, sp);
3459
3460 xfree(sbuf);
3461 return r;
3462}
3463
3464static int
3465expand_case_fold_make_rem_string(Node** rnode, UChar *s, UChar *end,
3466 regex_t* reg)
3467{
3468 int r;
3469 Node *node;
3470
3471 node = onig_node_new_str(s, end);
3472 if (IS_NULL(node)) return ONIGERR_MEMORY;
3473
3474 r = update_string_node_case_fold(reg, node);
3475 if (r != 0) {
3476 onig_node_free(node);
3477 return r;
3478 }
3479
3480 NSTRING_SET_AMBIG(node);
3481 NSTRING_SET_DONT_GET_OPT_INFO(node);
3482 *rnode = node;
3483 return 0;
3484}
3485
3486static int
3487is_case_fold_variable_len(int item_num, OnigCaseFoldCodeItem items[],
3488 int slen)
3489{
3490 int i;
3491
3492 for (i = 0; i < item_num; i++) {
3493 if (items[i].byte_len != slen) {
3494 return 1;
3495 }
3496 if (items[i].code_len != 1) {
3497 return 1;
3498 }
3499 }
3500 return 0;
3501}
3502
3503static int
3504expand_case_fold_string_alt(int item_num, OnigCaseFoldCodeItem items[],
3505 UChar *p, int slen, UChar *end,
3506 regex_t* reg, Node **rnode)
3507{
3508 int r, i, j, len, varlen;
3509 Node *anode, *var_anode, *snode, *xnode, *an;
3510 UChar buf[ONIGENC_CODE_TO_MBC_MAXLEN];
3511
3512 *rnode = var_anode = NULL_NODE;
3513
3514 varlen = 0;
3515 for (i = 0; i < item_num; i++) {
3516 if (items[i].byte_len != slen) {
3517 varlen = 1;
3518 break;
3519 }
3520 }
3521
3522 if (varlen != 0) {
3523 *rnode = var_anode = onig_node_new_alt(NULL_NODE, NULL_NODE);
3524 if (IS_NULL(var_anode)) return ONIGERR_MEMORY;
3525
3526 xnode = onig_node_new_list(NULL, NULL);
3527 if (IS_NULL(xnode)) goto mem_err;
3528 NCAR(var_anode) = xnode;
3529
3530 anode = onig_node_new_alt(NULL_NODE, NULL_NODE);
3531 if (IS_NULL(anode)) goto mem_err;
3532 NCAR(xnode) = anode;
3533 }
3534 else {
3535 *rnode = anode = onig_node_new_alt(NULL_NODE, NULL_NODE);
3536 if (IS_NULL(anode)) return ONIGERR_MEMORY;
3537 }
3538
3539 snode = onig_node_new_str(p, p + slen);
3540 if (IS_NULL(snode)) goto mem_err;
3541
3542 NCAR(anode) = snode;
3543
3544 for (i = 0; i < item_num; i++) {
3545 snode = onig_node_new_str(NULL, NULL);
3546 if (IS_NULL(snode)) goto mem_err;
3547
3548 for (j = 0; j < items[i].code_len; j++) {
3549 len = ONIGENC_CODE_TO_MBC(reg->enc, items[i].code[j], buf);
3550 if (len < 0) {
3551 r = len;
3552 goto mem_err2;
3553 }
3554
3555 r = onig_node_str_cat(snode, buf, buf + len);
3556 if (r != 0) goto mem_err2;
3557 }
3558
3559 an = onig_node_new_alt(NULL_NODE, NULL_NODE);
3560 if (IS_NULL(an)) {
3561 goto mem_err2;
3562 }
3563
3564 if (items[i].byte_len != slen) {
3565 Node *rem;
3566 UChar *q = p + items[i].byte_len;
3567
3568 if (q < end) {
3569 r = expand_case_fold_make_rem_string(&rem, q, end, reg);
3570 if (r != 0) {
3571 onig_node_free(an);
3572 goto mem_err2;
3573 }
3574
3575 xnode = onig_node_list_add(NULL_NODE, snode);
3576 if (IS_NULL(xnode)) {
3577 onig_node_free(an);
3578 onig_node_free(rem);
3579 goto mem_err2;
3580 }
3581 if (IS_NULL(onig_node_list_add(xnode, rem))) {
3582 onig_node_free(an);
3583 onig_node_free(xnode);
3584 onig_node_free(rem);
3585 goto mem_err;
3586 }
3587
3588 NCAR(an) = xnode;
3589 }
3590 else {
3591 NCAR(an) = snode;
3592 }
3593
3594 NCDR(var_anode) = an;
3595 var_anode = an;
3596 }
3597 else {
3598 NCAR(an) = snode;
3599 NCDR(anode) = an;
3600 anode = an;
3601 }
3602 }
3603
3604 return varlen;
3605
3606 mem_err2:
3607 onig_node_free(snode);
3608
3609 mem_err:
3610 onig_node_free(*rnode);
3611
3612 return ONIGERR_MEMORY;
3613}
3614
3615#define THRESHOLD_CASE_FOLD_ALT_FOR_EXPANSION 8
3616
3617static int
3618expand_case_fold_string(Node* node, regex_t* reg, int state)
3619{
3620 int r, n, len, alt_num;
3621 int varlen = 0;
3622 int is_in_look_behind;
3623 UChar *start, *end, *p;
3624 Node *top_root, *root, *snode, *prev_node;
3625 OnigCaseFoldCodeItem items[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM];
3626 StrNode* sn;
3627
3628 if (NSTRING_IS_AMBIG(node)) return 0;
3629
3630 sn = NSTR(node);
3631
3632 start = sn->s;
3633 end = sn->end;
3634 if (start >= end) return 0;
3635
3636 is_in_look_behind = (state & IN_LOOK_BEHIND) != 0;
3637
3638 r = 0;
3639 top_root = root = prev_node = snode = NULL_NODE;
3640 alt_num = 1;
3641 p = start;
3642 while (p < end) {
3643 n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(reg->enc, reg->case_fold_flag,
3644 p, end, items);
3645 if (n < 0) {
3646 r = n;
3647 goto err;
3648 }
3649
3650 len = enclen(reg->enc, p, end);
3651
3652 varlen = is_case_fold_variable_len(n, items, len);
3653 if (n == 0 || varlen == 0 || is_in_look_behind) {
3654 if (IS_NULL(snode)) {
3655 if (IS_NULL(root) && IS_NOT_NULL(prev_node)) {
3656 onig_node_free(top_root);
3657 top_root = root = onig_node_list_add(NULL_NODE, prev_node);
3658 if (IS_NULL(root)) {
3659 onig_node_free(prev_node);
3660 goto mem_err;
3661 }
3662 }
3663
3664 prev_node = snode = onig_node_new_str(NULL, NULL);
3665 if (IS_NULL(snode)) goto mem_err;
3666 if (IS_NOT_NULL(root)) {
3667 if (IS_NULL(onig_node_list_add(root, snode))) {
3668 onig_node_free(snode);
3669 goto mem_err;
3670 }
3671 }
3672 }
3673
3674 r = onig_node_str_cat(snode, p, p + len);
3675 if (r != 0) goto err;
3676 }
3677 else {
3678 alt_num *= (n + 1);
3679 if (alt_num > THRESHOLD_CASE_FOLD_ALT_FOR_EXPANSION) break;
3680
3681 if (IS_NOT_NULL(snode)) {
3682 r = update_string_node_case_fold(reg, snode);
3683 if (r == 0) {
3684 NSTRING_SET_AMBIG(snode);
3685 }
3686 }
3687 if (IS_NULL(root) && IS_NOT_NULL(prev_node)) {
3688 onig_node_free(top_root);
3689 top_root = root = onig_node_list_add(NULL_NODE, prev_node);
3690 if (IS_NULL(root)) {
3691 onig_node_free(prev_node);
3692 goto mem_err;
3693 }
3694 }
3695
3696 r = expand_case_fold_string_alt(n, items, p, len, end, reg, &prev_node);
3697 if (r < 0) goto mem_err;
3698 if (r == 1) {
3699 if (IS_NULL(root)) {
3700 top_root = prev_node;
3701 }
3702 else {
3703 if (IS_NULL(onig_node_list_add(root, prev_node))) {
3704 onig_node_free(prev_node);
3705 goto mem_err;
3706 }
3707 }
3708
3709 root = NCAR(prev_node);
3710 }
3711 else { /* r == 0 */
3712 if (IS_NOT_NULL(root)) {
3713 if (IS_NULL(onig_node_list_add(root, prev_node))) {
3714 onig_node_free(prev_node);
3715 goto mem_err;
3716 }
3717 }
3718 }
3719
3720 snode = NULL_NODE;
3721 }
3722
3723 p += len;
3724 }
3725 if (IS_NOT_NULL(snode)) {
3726 r = update_string_node_case_fold(reg, snode);
3727 if (r == 0) {
3728 NSTRING_SET_AMBIG(snode);
3729 }
3730 }
3731
3732 if (p < end) {
3733 Node *srem;
3734
3735 r = expand_case_fold_make_rem_string(&srem, p, end, reg);
3736 if (r != 0) goto mem_err;
3737
3738 if (IS_NOT_NULL(prev_node) && IS_NULL(root)) {
3739 onig_node_free(top_root);
3740 top_root = root = onig_node_list_add(NULL_NODE, prev_node);
3741 if (IS_NULL(root)) {
3742 onig_node_free(srem);
3743 onig_node_free(prev_node);
3744 goto mem_err;
3745 }
3746 }
3747
3748 if (IS_NULL(root)) {
3749 prev_node = srem;
3750 }
3751 else {
3752 if (IS_NULL(onig_node_list_add(root, srem))) {
3753 onig_node_free(srem);
3754 goto mem_err;
3755 }
3756 }
3757 }
3758
3759 /* ending */
3760 top_root = (IS_NOT_NULL(top_root) ? top_root : prev_node);
3761 swap_node(node, top_root);
3762 onig_node_free(top_root);
3763 return 0;
3764
3765 mem_err:
3766 r = ONIGERR_MEMORY;
3767
3768 err:
3769 onig_node_free(top_root);
3770 return r;
3771}
3772
3773
3774#ifdef USE_COMBINATION_EXPLOSION_CHECK
3775
3776# define CEC_THRES_NUM_BIG_REPEAT 512
3777# define CEC_INFINITE_NUM 0x7fffffff
3778
3779# define CEC_IN_INFINITE_REPEAT (1<<0)
3780# define CEC_IN_FINITE_REPEAT (1<<1)
3781# define CEC_CONT_BIG_REPEAT (1<<2)
3782
3783static int
3784setup_comb_exp_check(Node* node, int state, ScanEnv* env)
3785{
3786 int type;
3787 int r = state;
3788
3789 type = NTYPE(node);
3790 switch (type) {
3791 case NT_LIST:
3792 {
3793 do {
3794 r = setup_comb_exp_check(NCAR(node), r, env);
3795 } while (r >= 0 && IS_NOT_NULL(node = NCDR(node)));
3796 }
3797 break;
3798
3799 case NT_ALT:
3800 {
3801 int ret;
3802 do {
3803 ret = setup_comb_exp_check(NCAR(node), state, env);
3804 r |= ret;
3805 } while (ret >= 0 && IS_NOT_NULL(node = NCDR(node)));
3806 }
3807 break;
3808
3809 case NT_QTFR:
3810 {
3811 int child_state = state;
3812 int add_state = 0;
3813 QtfrNode* qn = NQTFR(node);
3814 Node* target = qn->target;
3815 int var_num;
3816
3817 if (! IS_REPEAT_INFINITE(qn->upper)) {
3818 if (qn->upper > 1) {
3819 /* {0,1}, {1,1} are allowed */
3820 child_state |= CEC_IN_FINITE_REPEAT;
3821
3822 /* check (a*){n,m}, (a+){n,m} => (a*){n,n}, (a+){n,n} */
3823 if (env->backrefed_mem == 0) {
3824 if (NTYPE(qn->target) == NT_ENCLOSE) {
3825 EncloseNode* en = NENCLOSE(qn->target);
3826 if (en->type == ENCLOSE_MEMORY) {
3827 if (NTYPE(en->target) == NT_QTFR) {
3828 QtfrNode* q = NQTFR(en->target);
3829 if (IS_REPEAT_INFINITE(q->upper)
3830 && q->greedy == qn->greedy) {
3831 qn->upper = (qn->lower == 0 ? 1 : qn->lower);
3832 if (qn->upper == 1)
3833 child_state = state;
3834 }
3835 }
3836 }
3837 }
3838 }
3839 }
3840 }
3841
3842 if (state & CEC_IN_FINITE_REPEAT) {
3843 qn->comb_exp_check_num = -1;
3844 }
3845 else {
3846 if (IS_REPEAT_INFINITE(qn->upper)) {
3847 var_num = CEC_INFINITE_NUM;
3848 child_state |= CEC_IN_INFINITE_REPEAT;
3849 }
3850 else {
3851 var_num = qn->upper - qn->lower;
3852 }
3853
3854 if (var_num >= CEC_THRES_NUM_BIG_REPEAT)
3855 add_state |= CEC_CONT_BIG_REPEAT;
3856
3857 if (((state & CEC_IN_INFINITE_REPEAT) != 0 && var_num != 0) ||
3858 ((state & CEC_CONT_BIG_REPEAT) != 0 &&
3859 var_num >= CEC_THRES_NUM_BIG_REPEAT)) {
3860 if (qn->comb_exp_check_num == 0) {
3861 env->num_comb_exp_check++;
3862 qn->comb_exp_check_num = env->num_comb_exp_check;
3863 if (env->curr_max_regnum > env->comb_exp_max_regnum)
3864 env->comb_exp_max_regnum = env->curr_max_regnum;
3865 }
3866 }
3867 }
3868
3869 r = setup_comb_exp_check(target, child_state, env);
3870 r |= add_state;
3871 }
3872 break;
3873
3874 case NT_ENCLOSE:
3875 {
3876 EncloseNode* en = NENCLOSE(node);
3877
3878 switch (en->type) {
3879 case ENCLOSE_MEMORY:
3880 {
3881 if (env->curr_max_regnum < en->regnum)
3882 env->curr_max_regnum = en->regnum;
3883
3884 r = setup_comb_exp_check(en->target, state, env);
3885 }
3886 break;
3887
3888 default:
3889 r = setup_comb_exp_check(en->target, state, env);
3890 break;
3891 }
3892 }
3893 break;
3894
3895# ifdef USE_SUBEXP_CALL
3896 case NT_CALL:
3897 if (IS_CALL_RECURSION(NCALL(node)))
3898 env->has_recursion = 1;
3899 else
3900 r = setup_comb_exp_check(NCALL(node)->target, state, env);
3901 break;
3902# endif
3903
3904 default:
3905 break;
3906 }
3907
3908 return r;
3909}
3910#endif
3911
3912/* setup_tree does the following work.
3913 1. check empty loop. (set qn->target_empty_info)
3914 2. expand ignore-case in char class.
3915 3. set memory status bit flags. (reg->mem_stats)
3916 4. set qn->head_exact for [push, exact] -> [push_or_jump_exact1, exact].
3917 5. find invalid patterns in look-behind.
3918 6. expand repeated string.
3919 */
3920static int
3921setup_tree(Node* node, regex_t* reg, int state, ScanEnv* env)
3922{
3923 int type;
3924 int r = 0;
3925
3926restart:
3927 type = NTYPE(node);
3928 switch (type) {
3929 case NT_LIST:
3930 {
3931 Node* prev = NULL_NODE;
3932 do {
3933 r = setup_tree(NCAR(node), reg, state, env);
3934 if (IS_NOT_NULL(prev) && r == 0) {
3935 r = next_setup(prev, NCAR(node), reg);
3936 }
3937 prev = NCAR(node);
3938 } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
3939 }
3940 break;
3941
3942 case NT_ALT:
3943 do {
3944 r = setup_tree(NCAR(node), reg, (state | IN_ALT), env);
3945 } while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
3946 break;
3947
3948 case NT_CCLASS:
3949 break;
3950
3951 case NT_STR:
3952 if (IS_IGNORECASE(reg->options) && !NSTRING_IS_RAW(node)) {
3953 r = expand_case_fold_string(node, reg, state);
3954 }
3955 break;
3956
3957 case NT_CTYPE:
3958 case NT_CANY:
3959 break;
3960
3961#ifdef USE_SUBEXP_CALL
3962 case NT_CALL:
3963 break;
3964#endif
3965
3966 case NT_BREF:
3967 {
3968 int i;
3969 int* p;
3970 Node** nodes = SCANENV_MEM_NODES(env);
3971 BRefNode* br = NBREF(node);
3972 p = BACKREFS_P(br);
3973 for (i = 0; i < br->back_num; i++) {
3974 if (p[i] > env->num_mem) return ONIGERR_INVALID_BACKREF;
3975 BIT_STATUS_ON_AT(env->backrefed_mem, p[i]);
3976 BIT_STATUS_ON_AT(env->bt_mem_start, p[i]);
3977#ifdef USE_BACKREF_WITH_LEVEL
3978 if (IS_BACKREF_NEST_LEVEL(br)) {
3979 BIT_STATUS_ON_AT(env->bt_mem_end, p[i]);
3980 }
3981#endif
3982 SET_ENCLOSE_STATUS(nodes[p[i]], NST_MEM_BACKREFED);
3983 }
3984 }
3985 break;
3986
3987 case NT_QTFR:
3988 {
3989 OnigDistance d;
3990 QtfrNode* qn = NQTFR(node);
3991 Node* target = qn->target;
3992
3993 if ((state & IN_REPEAT) != 0) {
3994 qn->state |= NST_IN_REPEAT;
3995 }
3996
3997 if (IS_REPEAT_INFINITE(qn->upper) || qn->upper >= 1) {
3998 r = get_min_match_length(target, &d, env);
3999 if (r) break;
4000 if (d == 0) {
4001 qn->target_empty_info = NQ_TARGET_IS_EMPTY;
4002#ifdef USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT
4003 r = quantifiers_memory_node_info(target);
4004 if (r < 0) break;
4005 if (r > 0) {
4006 qn->target_empty_info = r;
4007 }
4008#endif
4009#if 0
4010 r = get_max_match_length(target, &d, env);
4011 if (r == 0 && d == 0) {
4012 /* ()* ==> ()?, ()+ ==> () */
4013 qn->upper = 1;
4014 if (qn->lower > 1) qn->lower = 1;
4015 if (NTYPE(target) == NT_STR) {
4016 qn->upper = qn->lower = 0; /* /(?:)+/ ==> // */
4017 }
4018 }
4019#endif
4020 }
4021 }
4022
4023 state |= IN_REPEAT;
4024 if (qn->lower != qn->upper)
4025 state |= IN_VAR_REPEAT;
4026 r = setup_tree(target, reg, state, env);
4027 if (r) break;
4028
4029 /* expand string */
4030#define EXPAND_STRING_MAX_LENGTH 100
4031 if (NTYPE(target) == NT_STR) {
4032 if (qn->lower > 1) {
4033 int i, n = qn->lower;
4034 OnigDistance len = NSTRING_LEN(target);
4035 StrNode* sn = NSTR(target);
4036 Node* np;
4037
4038 np = onig_node_new_str(sn->s, sn->end);
4039 if (IS_NULL(np)) return ONIGERR_MEMORY;
4040 NSTR(np)->flag = sn->flag;
4041
4042 for (i = 1; i < n && (i+1) * len <= EXPAND_STRING_MAX_LENGTH; i++) {
4043 r = onig_node_str_cat(np, sn->s, sn->end);
4044 if (r) {
4045 onig_node_free(np);
4046 return r;
4047 }
4048 }
4049 if (i < qn->upper || IS_REPEAT_INFINITE(qn->upper)) {
4050 Node *np1, *np2;
4051
4052 qn->lower -= i;
4053 if (! IS_REPEAT_INFINITE(qn->upper))
4054 qn->upper -= i;
4055
4056 np1 = onig_node_new_list(np, NULL);
4057 if (IS_NULL(np1)) {
4058 onig_node_free(np);
4059 return ONIGERR_MEMORY;
4060 }
4061 swap_node(np1, node);
4062 np2 = onig_node_list_add(node, np1);
4063 if (IS_NULL(np2)) {
4064 onig_node_free(np1);
4065 return ONIGERR_MEMORY;
4066 }
4067 }
4068 else {
4069 swap_node(np, node);
4070 onig_node_free(np);
4071 }
4072 break; /* break case NT_QTFR: */
4073 }
4074 }
4075
4076#ifdef USE_OP_PUSH_OR_JUMP_EXACT
4077 if (qn->greedy && (qn->target_empty_info != 0)) {
4078 if (NTYPE(target) == NT_QTFR) {
4079 QtfrNode* tqn = NQTFR(target);
4080 if (IS_NOT_NULL(tqn->head_exact)) {
4081 qn->head_exact = tqn->head_exact;
4082 tqn->head_exact = NULL;
4083 }
4084 }
4085 else {
4086 qn->head_exact = get_head_value_node(qn->target, 1, reg);
4087 }
4088 }
4089#endif
4090 }
4091 break;
4092
4093 case NT_ENCLOSE:
4094 {
4095 EncloseNode* en = NENCLOSE(node);
4096
4097 switch (en->type) {
4098 case ENCLOSE_OPTION:
4099 {
4100 OnigOptionType options = reg->options;
4101 reg->options = NENCLOSE(node)->option;
4102 r = setup_tree(NENCLOSE(node)->target, reg, state, env);
4103 reg->options = options;
4104 }
4105 break;
4106
4107 case ENCLOSE_MEMORY:
4108 if ((state & (IN_ALT | IN_NOT | IN_VAR_REPEAT | IN_CALL)) != 0) {
4109 BIT_STATUS_ON_AT(env->bt_mem_start, en->regnum);
4110 /* SET_ENCLOSE_STATUS(node, NST_MEM_IN_ALT_NOT); */
4111 }
4112 if (IS_ENCLOSE_CALLED(en))
4113 state |= IN_CALL;
4114 if (IS_ENCLOSE_RECURSION(en))
4115 state |= IN_RECCALL;
4116 else if ((state & IN_RECCALL) != 0)
4117 SET_CALL_RECURSION(node);
4118 r = setup_tree(en->target, reg, state, env);
4119 break;
4120
4121 case ENCLOSE_STOP_BACKTRACK:
4122 {
4123 Node* target = en->target;
4124 r = setup_tree(target, reg, state, env);
4125 if (NTYPE(target) == NT_QTFR) {
4126 QtfrNode* tqn = NQTFR(target);
4127 if (IS_REPEAT_INFINITE(tqn->upper) && tqn->lower <= 1 &&
4128 tqn->greedy != 0) { /* (?>a*), a*+ etc... */
4129 int qtype = NTYPE(tqn->target);
4130 if (IS_NODE_TYPE_SIMPLE(qtype))
4131 SET_ENCLOSE_STATUS(node, NST_STOP_BT_SIMPLE_REPEAT);
4132 }
4133 }
4134 }
4135 break;
4136
4137 case ENCLOSE_CONDITION:
4138#ifdef USE_NAMED_GROUP
4139 if (! IS_ENCLOSE_NAME_REF(NENCLOSE(node)) &&
4140 env->num_named > 0 &&
4141 IS_SYNTAX_BV(env->syntax, ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP) &&
4142 !ONIG_IS_OPTION_ON(env->option, ONIG_OPTION_CAPTURE_GROUP)) {
4143 return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;
4144 }
4145#endif
4146 if (NENCLOSE(node)->regnum > env->num_mem)
4147 return ONIGERR_INVALID_BACKREF;
4148 r = setup_tree(NENCLOSE(node)->target, reg, state, env);
4149 break;
4150
4151 case ENCLOSE_ABSENT:
4152 r = setup_tree(NENCLOSE(node)->target, reg, state, env);
4153 break;
4154 }
4155 }
4156 break;
4157
4158 case NT_ANCHOR:
4159 {
4160 AnchorNode* an = NANCHOR(node);
4161
4162 switch (an->type) {
4163 case ANCHOR_PREC_READ:
4164 r = setup_tree(an->target, reg, state, env);
4165 break;
4166 case ANCHOR_PREC_READ_NOT:
4167 r = setup_tree(an->target, reg, (state | IN_NOT), env);
4168 break;
4169
4170/* allowed node types in look-behind */
4171#define ALLOWED_TYPE_IN_LB \
4172 ( BIT_NT_LIST | BIT_NT_ALT | BIT_NT_STR | BIT_NT_CCLASS | BIT_NT_CTYPE | \
4173 BIT_NT_CANY | BIT_NT_ANCHOR | BIT_NT_ENCLOSE | BIT_NT_QTFR | BIT_NT_CALL )
4174
4175#define ALLOWED_ENCLOSE_IN_LB ( ENCLOSE_MEMORY | ENCLOSE_OPTION )
4176#define ALLOWED_ENCLOSE_IN_LB_NOT ENCLOSE_OPTION
4177
4178#define ALLOWED_ANCHOR_IN_LB \
4179( ANCHOR_LOOK_BEHIND | ANCHOR_LOOK_BEHIND_NOT | ANCHOR_BEGIN_LINE | \
4180 ANCHOR_END_LINE | ANCHOR_BEGIN_BUF | ANCHOR_BEGIN_POSITION | ANCHOR_KEEP | \
4181 ANCHOR_WORD_BOUND | ANCHOR_NOT_WORD_BOUND | \
4182 ANCHOR_WORD_BEGIN | ANCHOR_WORD_END )
4183#define ALLOWED_ANCHOR_IN_LB_NOT \
4184( ANCHOR_LOOK_BEHIND | ANCHOR_LOOK_BEHIND_NOT | ANCHOR_BEGIN_LINE | \
4185 ANCHOR_END_LINE | ANCHOR_BEGIN_BUF | ANCHOR_BEGIN_POSITION | ANCHOR_KEEP | \
4186 ANCHOR_WORD_BOUND | ANCHOR_NOT_WORD_BOUND | \
4187 ANCHOR_WORD_BEGIN | ANCHOR_WORD_END )
4188
4189 case ANCHOR_LOOK_BEHIND:
4190 {
4191 r = check_type_tree(an->target, ALLOWED_TYPE_IN_LB,
4192 ALLOWED_ENCLOSE_IN_LB, ALLOWED_ANCHOR_IN_LB);
4193 if (r < 0) return r;
4194 if (r > 0) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
4195 if (NTYPE(node) != NT_ANCHOR) goto restart;
4196 r = setup_tree(an->target, reg, (state | IN_LOOK_BEHIND), env);
4197 if (r != 0) return r;
4198 r = setup_look_behind(node, reg, env);
4199 }
4200 break;
4201
4202 case ANCHOR_LOOK_BEHIND_NOT:
4203 {
4204 r = check_type_tree(an->target, ALLOWED_TYPE_IN_LB,
4205 ALLOWED_ENCLOSE_IN_LB_NOT, ALLOWED_ANCHOR_IN_LB_NOT);
4206 if (r < 0) return r;
4207 if (r > 0) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
4208 if (NTYPE(node) != NT_ANCHOR) goto restart;
4209 r = setup_tree(an->target, reg, (state | IN_NOT | IN_LOOK_BEHIND),
4210 env);
4211 if (r != 0) return r;
4212 r = setup_look_behind(node, reg, env);
4213 }
4214 break;
4215 }
4216 }
4217 break;
4218
4219 default:
4220 break;
4221 }
4222
4223 return r;
4224}
4225
4226/* set skip map for Sunday's quick search */
4227static int
4228set_bm_skip(UChar* s, UChar* end, regex_t* reg,
4229 UChar skip[], int ignore_case)
4230{
4231 OnigDistance i, len;
4232 int clen, flen, n, j, k;
4233 UChar *p, buf[ONIGENC_MBC_CASE_FOLD_MAXLEN];
4234 OnigCaseFoldCodeItem items[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM];
4235 OnigEncoding enc = reg->enc;
4236
4237 len = end - s;
4238 if (len >= ONIG_CHAR_TABLE_SIZE) {
4239 /* This should not happen. */
4240 return ONIGERR_TYPE_BUG;
4241 }
4242
4243 if (ignore_case) {
4244 for (i = 0; i < len; i += clen) {
4245 p = s + i;
4246 n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc, reg->case_fold_flag,
4247 p, end, items);
4248 clen = enclen(enc, p, end);
4249 if (p + clen > end)
4250 clen = (int )(end - p);
4251
4252 for (j = 0; j < n; j++) {
4253 if ((items[j].code_len != 1) || (items[j].byte_len != clen)) {
4254 /* Different length isn't supported. Stop optimization at here. */
4255 end = p;
4256 goto endcheck;
4257 }
4258 flen = ONIGENC_CODE_TO_MBC(enc, items[j].code[0], buf);
4259 if (flen != clen) {
4260 /* Different length isn't supported. Stop optimization at here. */
4261 end = p;
4262 goto endcheck;
4263 }
4264 }
4265 }
4266endcheck:
4267 len = end - s;
4268 }
4269
4270 for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++)
4271 skip[i] = (UChar )(len + 1);
4272 n = 0;
4273 for (i = 0; i < len; i += clen) {
4274 p = s + i;
4275 if (ignore_case)
4276 n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc, reg->case_fold_flag,
4277 p, end, items);
4278 clen = enclen(enc, p, end);
4279 if (p + clen > end)
4280 clen = (int )(end - p);
4281
4282 for (j = 0; j < clen; j++) {
4283 skip[s[i + j]] = (UChar )(len - i - j);
4284 for (k = 0; k < n; k++) {
4285 ONIGENC_CODE_TO_MBC(enc, items[k].code[0], buf);
4286 skip[buf[j]] = (UChar )(len - i - j);
4287 }
4288 }
4289 }
4290
4291 return (int )len;
4292}
4293
4294typedef struct {
4295 OnigDistance min; /* min byte length */
4296 OnigDistance max; /* max byte length */
4297} MinMaxLen;
4298
4299typedef struct {
4300 MinMaxLen mmd;
4301 OnigEncoding enc;
4302 OnigOptionType options;
4303 OnigCaseFoldType case_fold_flag;
4304 ScanEnv* scan_env;
4305} OptEnv;
4306
4307typedef struct {
4308 int left_anchor;
4309 int right_anchor;
4310} OptAncInfo;
4311
4312typedef struct {
4313 MinMaxLen mmd; /* info position */
4314 OptAncInfo anc;
4315
4316 int reach_end;
4317 int ignore_case; /* -1: unset, 0: case sensitive, 1: ignore case */
4318 int len;
4319 UChar s[OPT_EXACT_MAXLEN];
4320} OptExactInfo;
4321
4322typedef struct {
4323 MinMaxLen mmd; /* info position */
4324 OptAncInfo anc;
4325
4326 int value; /* weighted value */
4327 UChar map[ONIG_CHAR_TABLE_SIZE];
4328} OptMapInfo;
4329
4330typedef struct {
4331 MinMaxLen len;
4332
4333 OptAncInfo anc;
4334 OptExactInfo exb; /* boundary */
4335 OptExactInfo exm; /* middle */
4336 OptExactInfo expr; /* prec read (?=...) */
4337
4338 OptMapInfo map; /* boundary */
4339} NodeOptInfo;
4340
4341
4342static int
4343map_position_value(OnigEncoding enc, int i)
4344{
4345 static const short int ByteValTable[] = {
4346 5, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10, 1, 1, 10, 1, 1,
4347 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
4348 12, 4, 7, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5,
4349 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5,
4350 5, 6, 6, 6, 6, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
4351 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 5, 5, 5,
4352 5, 6, 6, 6, 6, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
4353 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 1
4354 };
4355
4356 if (i < numberof(ByteValTable)) {
4357 if (i == 0 && ONIGENC_MBC_MINLEN(enc) > 1)
4358 return 20;
4359 else
4360 return (int )ByteValTable[i];
4361 }
4362 else
4363 return 4; /* Take it easy. */
4364}
4365
4366static int
4367distance_value(MinMaxLen* mm)
4368{
4369 /* 1000 / (min-max-dist + 1) */
4370 static const short int dist_vals[] = {
4371 1000, 500, 333, 250, 200, 167, 143, 125, 111, 100,
4372 91, 83, 77, 71, 67, 63, 59, 56, 53, 50,
4373 48, 45, 43, 42, 40, 38, 37, 36, 34, 33,
4374 32, 31, 30, 29, 29, 28, 27, 26, 26, 25,
4375 24, 24, 23, 23, 22, 22, 21, 21, 20, 20,
4376 20, 19, 19, 19, 18, 18, 18, 17, 17, 17,
4377 16, 16, 16, 16, 15, 15, 15, 15, 14, 14,
4378 14, 14, 14, 14, 13, 13, 13, 13, 13, 13,
4379 12, 12, 12, 12, 12, 12, 11, 11, 11, 11,
4380 11, 11, 11, 11, 11, 10, 10, 10, 10, 10
4381 };
4382
4383 OnigDistance d;
4384
4385 if (mm->max == ONIG_INFINITE_DISTANCE) return 0;
4386
4387 d = mm->max - mm->min;
4388 if (d < numberof(dist_vals))
4389 /* return dist_vals[d] * 16 / (mm->min + 12); */
4390 return (int )dist_vals[d];
4391 else
4392 return 1;
4393}
4394
4395static int
4396comp_distance_value(MinMaxLen* d1, MinMaxLen* d2, int v1, int v2)
4397{
4398 if (v2 <= 0) return -1;
4399 if (v1 <= 0) return 1;
4400
4401 v1 *= distance_value(d1);
4402 v2 *= distance_value(d2);
4403
4404 if (v2 > v1) return 1;
4405 if (v2 < v1) return -1;
4406
4407 if (d2->min < d1->min) return 1;
4408 if (d2->min > d1->min) return -1;
4409 return 0;
4410}
4411
4412static int
4413is_equal_mml(MinMaxLen* a, MinMaxLen* b)
4414{
4415 return (a->min == b->min && a->max == b->max) ? 1 : 0;
4416}
4417
4418
4419static void
4420set_mml(MinMaxLen* mml, OnigDistance min, OnigDistance max)
4421{
4422 mml->min = min;
4423 mml->max = max;
4424}
4425
4426static void
4427clear_mml(MinMaxLen* mml)
4428{
4429 mml->min = mml->max = 0;
4430}
4431
4432static void
4433copy_mml(MinMaxLen* to, MinMaxLen* from)
4434{
4435 to->min = from->min;
4436 to->max = from->max;
4437}
4438
4439static void
4440add_mml(MinMaxLen* to, MinMaxLen* from)
4441{
4442 to->min = distance_add(to->min, from->min);
4443 to->max = distance_add(to->max, from->max);
4444}
4445
4446#if 0
4447static void
4448add_len_mml(MinMaxLen* to, OnigDistance len)
4449{
4450 to->min = distance_add(to->min, len);
4451 to->max = distance_add(to->max, len);
4452}
4453#endif
4454
4455static void
4456alt_merge_mml(MinMaxLen* to, MinMaxLen* from)
4457{
4458 if (to->min > from->min) to->min = from->min;
4459 if (to->max < from->max) to->max = from->max;
4460}
4461
4462static void
4463copy_opt_env(OptEnv* to, OptEnv* from)
4464{
4465 *to = *from;
4466}
4467
4468static void
4469clear_opt_anc_info(OptAncInfo* anc)
4470{
4471 anc->left_anchor = 0;
4472 anc->right_anchor = 0;
4473}
4474
4475static void
4476copy_opt_anc_info(OptAncInfo* to, OptAncInfo* from)
4477{
4478 *to = *from;
4479}
4480
4481static void
4482concat_opt_anc_info(OptAncInfo* to, OptAncInfo* left, OptAncInfo* right,
4483 OnigDistance left_len, OnigDistance right_len)
4484{
4485 clear_opt_anc_info(to);
4486
4487 to->left_anchor = left->left_anchor;
4488 if (left_len == 0) {
4489 to->left_anchor |= right->left_anchor;
4490 }
4491
4492 to->right_anchor = right->right_anchor;
4493 if (right_len == 0) {
4494 to->right_anchor |= left->right_anchor;
4495 }
4496 else {
4497 to->right_anchor |= (left->right_anchor & ANCHOR_PREC_READ_NOT);
4498 }
4499}
4500
4501static int
4502is_left_anchor(int anc)
4503{
4504 if (anc == ANCHOR_END_BUF || anc == ANCHOR_SEMI_END_BUF ||
4505 anc == ANCHOR_END_LINE || anc == ANCHOR_PREC_READ ||
4506 anc == ANCHOR_PREC_READ_NOT)
4507 return 0;
4508
4509 return 1;
4510}
4511
4512static int
4513is_set_opt_anc_info(OptAncInfo* to, int anc)
4514{
4515 if ((to->left_anchor & anc) != 0) return 1;
4516
4517 return ((to->right_anchor & anc) != 0 ? 1 : 0);
4518}
4519
4520static void
4521add_opt_anc_info(OptAncInfo* to, int anc)
4522{
4523 if (is_left_anchor(anc))
4524 to->left_anchor |= anc;
4525 else
4526 to->right_anchor |= anc;
4527}
4528
4529static void
4530remove_opt_anc_info(OptAncInfo* to, int anc)
4531{
4532 if (is_left_anchor(anc))
4533 to->left_anchor &= ~anc;
4534 else
4535 to->right_anchor &= ~anc;
4536}
4537
4538static void
4539alt_merge_opt_anc_info(OptAncInfo* to, OptAncInfo* add)
4540{
4541 to->left_anchor &= add->left_anchor;
4542 to->right_anchor &= add->right_anchor;
4543}
4544
4545static int
4546is_full_opt_exact_info(OptExactInfo* ex)
4547{
4548 return (ex->len >= OPT_EXACT_MAXLEN ? 1 : 0);
4549}
4550
4551static void
4552clear_opt_exact_info(OptExactInfo* ex)
4553{
4554 clear_mml(&ex->mmd);
4555 clear_opt_anc_info(&ex->anc);
4556 ex->reach_end = 0;
4557 ex->ignore_case = -1; /* unset */
4558 ex->len = 0;
4559 ex->s[0] = '\0';
4560}
4561
4562static void
4563copy_opt_exact_info(OptExactInfo* to, OptExactInfo* from)
4564{
4565 *to = *from;
4566}
4567
4568static void
4569concat_opt_exact_info(OptExactInfo* to, OptExactInfo* add, OnigEncoding enc)
4570{
4571 int i, j, len;
4572 UChar *p, *end;
4573 OptAncInfo tanc;
4574
4575 if (to->ignore_case < 0)
4576 to->ignore_case = add->ignore_case;
4577 else if (to->ignore_case != add->ignore_case)
4578 return ; /* avoid */
4579
4580 p = add->s;
4581 end = p + add->len;
4582 for (i = to->len; p < end; ) {
4583 len = enclen(enc, p, end);
4584 if (i + len > OPT_EXACT_MAXLEN) break;
4585 for (j = 0; j < len && p < end; j++)
4586 to->s[i++] = *p++;
4587 }
4588
4589 to->len = i;
4590 to->reach_end = (p == end ? add->reach_end : 0);
4591
4592 concat_opt_anc_info(&tanc, &to->anc, &add->anc, 1, 1);
4593 if (! to->reach_end) tanc.right_anchor = 0;
4594 copy_opt_anc_info(&to->anc, &tanc);
4595}
4596
4597static void
4598concat_opt_exact_info_str(OptExactInfo* to, UChar* s, UChar* end,
4599 int raw ARG_UNUSED, OnigEncoding enc)
4600{
4601 int i, j, len;
4602 UChar *p;
4603
4604 for (i = to->len, p = s; p < end && i < OPT_EXACT_MAXLEN; ) {
4605 len = enclen(enc, p, end);
4606 if (i + len > OPT_EXACT_MAXLEN) break;
4607 for (j = 0; j < len && p < end; j++)
4608 to->s[i++] = *p++;
4609 }
4610
4611 to->len = i;
4612}
4613
4614static void
4615alt_merge_opt_exact_info(OptExactInfo* to, OptExactInfo* add, OptEnv* env)
4616{
4617 int i, j, len;
4618
4619 if (add->len == 0 || to->len == 0) {
4620 clear_opt_exact_info(to);
4621 return ;
4622 }
4623
4624 if (! is_equal_mml(&to->mmd, &add->mmd)) {
4625 clear_opt_exact_info(to);
4626 return ;
4627 }
4628
4629 for (i = 0; i < to->len && i < add->len; ) {
4630 if (to->s[i] != add->s[i]) break;
4631 len = enclen(env->enc, to->s + i, to->s + to->len);
4632
4633 for (j = 1; j < len; j++) {
4634 if (to->s[i+j] != add->s[i+j]) break;
4635 }
4636 if (j < len) break;
4637 i += len;
4638 }
4639
4640 if (! add->reach_end || i < add->len || i < to->len) {
4641 to->reach_end = 0;
4642 }
4643 to->len = i;
4644 if (to->ignore_case < 0)
4645 to->ignore_case = add->ignore_case;
4646 else if (add->ignore_case >= 0)
4647 to->ignore_case |= add->ignore_case;
4648
4649 alt_merge_opt_anc_info(&to->anc, &add->anc);
4650 if (! to->reach_end) to->anc.right_anchor = 0;
4651}
4652
4653static void
4654select_opt_exact_info(OnigEncoding enc, OptExactInfo* now, OptExactInfo* alt)
4655{
4656 int v1, v2;
4657
4658 v1 = now->len;
4659 v2 = alt->len;
4660
4661 if (v2 == 0) {
4662 return ;
4663 }
4664 else if (v1 == 0) {
4665 copy_opt_exact_info(now, alt);
4666 return ;
4667 }
4668 else if (v1 <= 2 && v2 <= 2) {
4669 /* ByteValTable[x] is big value --> low price */
4670 v2 = map_position_value(enc, now->s[0]);
4671 v1 = map_position_value(enc, alt->s[0]);
4672
4673 if (now->len > 1) v1 += 5;
4674 if (alt->len > 1) v2 += 5;
4675 }
4676
4677 if (now->ignore_case <= 0) v1 *= 2;
4678 if (alt->ignore_case <= 0) v2 *= 2;
4679
4680 if (comp_distance_value(&now->mmd, &alt->mmd, v1, v2) > 0)
4681 copy_opt_exact_info(now, alt);
4682}
4683
4684static void
4685clear_opt_map_info(OptMapInfo* map)
4686{
4687 static const OptMapInfo clean_info = {
4688 {0, 0}, {0, 0}, 0,
4689 {
4690 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4691 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4692 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4693 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4694 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4695 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4696 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4697 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4698 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4699 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4700 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4701 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4702 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4703 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4704 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4705 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
4706 }
4707 };
4708
4709 xmemcpy(map, &clean_info, sizeof(OptMapInfo));
4710}
4711
4712static void
4713copy_opt_map_info(OptMapInfo* to, OptMapInfo* from)
4714{
4715 *to = *from;
4716}
4717
4718static void
4719add_char_opt_map_info(OptMapInfo* map, UChar c, OnigEncoding enc)
4720{
4721 if (map->map[c] == 0) {
4722 map->map[c] = 1;
4723 map->value += map_position_value(enc, c);
4724 }
4725}
4726
4727static int
4728add_char_amb_opt_map_info(OptMapInfo* map, UChar* p, UChar* end,
4729 OnigEncoding enc, OnigCaseFoldType case_fold_flag)
4730{
4731 OnigCaseFoldCodeItem items[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM];
4732 UChar buf[ONIGENC_CODE_TO_MBC_MAXLEN];
4733 int i, n;
4734
4735 add_char_opt_map_info(map, p[0], enc);
4736
4737 case_fold_flag = DISABLE_CASE_FOLD_MULTI_CHAR(case_fold_flag);
4738 n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc, case_fold_flag, p, end, items);
4739 if (n < 0) return n;
4740
4741 for (i = 0; i < n; i++) {
4742 ONIGENC_CODE_TO_MBC(enc, items[i].code[0], buf);
4743 add_char_opt_map_info(map, buf[0], enc);
4744 }
4745
4746 return 0;
4747}
4748
4749static void
4750select_opt_map_info(OptMapInfo* now, OptMapInfo* alt)
4751{
4752 const int z = 1<<15; /* 32768: something big value */
4753
4754 int v1, v2;
4755
4756 if (alt->value == 0) return ;
4757 if (now->value == 0) {
4758 copy_opt_map_info(now, alt);
4759 return ;
4760 }
4761
4762 v1 = z / now->value;
4763 v2 = z / alt->value;
4764 if (comp_distance_value(&now->mmd, &alt->mmd, v1, v2) > 0)
4765 copy_opt_map_info(now, alt);
4766}
4767
4768static int
4769comp_opt_exact_or_map_info(OptExactInfo* e, OptMapInfo* m)
4770{
4771#define COMP_EM_BASE 20
4772 int ve, vm;
4773
4774 if (m->value <= 0) return -1;
4775
4776 ve = COMP_EM_BASE * e->len * (e->ignore_case > 0 ? 1 : 2);
4777 vm = COMP_EM_BASE * 5 * 2 / m->value;
4778 return comp_distance_value(&e->mmd, &m->mmd, ve, vm);
4779}
4780
4781static void
4782alt_merge_opt_map_info(OnigEncoding enc, OptMapInfo* to, OptMapInfo* add)
4783{
4784 int i, val;
4785
4786 /* if (! is_equal_mml(&to->mmd, &add->mmd)) return ; */
4787 if (to->value == 0) return ;
4788 if (add->value == 0 || to->mmd.max < add->mmd.min) {
4789 clear_opt_map_info(to);
4790 return ;
4791 }
4792
4793 alt_merge_mml(&to->mmd, &add->mmd);
4794
4795 val = 0;
4796 for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) {
4797 if (add->map[i])
4798 to->map[i] = 1;
4799
4800 if (to->map[i])
4801 val += map_position_value(enc, i);
4802 }
4803 to->value = val;
4804
4805 alt_merge_opt_anc_info(&to->anc, &add->anc);
4806}
4807
4808static void
4809set_bound_node_opt_info(NodeOptInfo* opt, MinMaxLen* mmd)
4810{
4811 copy_mml(&(opt->exb.mmd), mmd);
4812 copy_mml(&(opt->expr.mmd), mmd);
4813 copy_mml(&(opt->map.mmd), mmd);
4814}
4815
4816static void
4817clear_node_opt_info(NodeOptInfo* opt)
4818{
4819 clear_mml(&opt->len);
4820 clear_opt_anc_info(&opt->anc);
4821 clear_opt_exact_info(&opt->exb);
4822 clear_opt_exact_info(&opt->exm);
4823 clear_opt_exact_info(&opt->expr);
4824 clear_opt_map_info(&opt->map);
4825}
4826
4827static void
4828copy_node_opt_info(NodeOptInfo* to, NodeOptInfo* from)
4829{
4830 *to = *from;
4831}
4832
4833static void
4834concat_left_node_opt_info(OnigEncoding enc, NodeOptInfo* to, NodeOptInfo* add)
4835{
4836 int exb_reach, exm_reach;
4837 OptAncInfo tanc;
4838
4839 concat_opt_anc_info(&tanc, &to->anc, &add->anc, to->len.max, add->len.max);
4840 copy_opt_anc_info(&to->anc, &tanc);
4841
4842 if (add->exb.len > 0 && to->len.max == 0) {
4843 concat_opt_anc_info(&tanc, &to->anc, &add->exb.anc,
4844 to->len.max, add->len.max);
4845 copy_opt_anc_info(&add->exb.anc, &tanc);
4846 }
4847
4848 if (add->map.value > 0 && to->len.max == 0) {
4849 if (add->map.mmd.max == 0)
4850 add->map.anc.left_anchor |= to->anc.left_anchor;
4851 }
4852
4853 exb_reach = to->exb.reach_end;
4854 exm_reach = to->exm.reach_end;
4855
4856 if (add->len.max != 0)
4857 to->exb.reach_end = to->exm.reach_end = 0;
4858
4859 if (add->exb.len > 0) {
4860 if (exb_reach) {
4861 concat_opt_exact_info(&to->exb, &add->exb, enc);
4862 clear_opt_exact_info(&add->exb);
4863 }
4864 else if (exm_reach) {
4865 concat_opt_exact_info(&to->exm, &add->exb, enc);
4866 clear_opt_exact_info(&add->exb);
4867 }
4868 }
4869 select_opt_exact_info(enc, &to->exm, &add->exb);
4870 select_opt_exact_info(enc, &to->exm, &add->exm);
4871
4872 if (to->expr.len > 0) {
4873 if (add->len.max > 0) {
4874 if (to->expr.len > (int )add->len.max)
4875 to->expr.len = (int )add->len.max;
4876
4877 if (to->expr.mmd.max == 0)
4878 select_opt_exact_info(enc, &to->exb, &to->expr);
4879 else
4880 select_opt_exact_info(enc, &to->exm, &to->expr);
4881 }
4882 }
4883 else if (add->expr.len > 0) {
4884 copy_opt_exact_info(&to->expr, &add->expr);
4885 }
4886
4887 select_opt_map_info(&to->map, &add->map);
4888
4889 add_mml(&to->len, &add->len);
4890}
4891
4892static void
4893alt_merge_node_opt_info(NodeOptInfo* to, NodeOptInfo* add, OptEnv* env)
4894{
4895 alt_merge_opt_anc_info (&to->anc, &add->anc);
4896 alt_merge_opt_exact_info(&to->exb, &add->exb, env);
4897 alt_merge_opt_exact_info(&to->exm, &add->exm, env);
4898 alt_merge_opt_exact_info(&to->expr, &add->expr, env);
4899 alt_merge_opt_map_info(env->enc, &to->map, &add->map);
4900
4901 alt_merge_mml(&to->len, &add->len);
4902}
4903
4904
4905#define MAX_NODE_OPT_INFO_REF_COUNT 5
4906
4907static int
4908optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env)
4909{
4910 int type;
4911 int r = 0;
4912
4913 clear_node_opt_info(opt);
4914 set_bound_node_opt_info(opt, &env->mmd);
4915
4916 type = NTYPE(node);
4917 switch (type) {
4918 case NT_LIST:
4919 {
4920 OptEnv nenv;
4921 NodeOptInfo nopt;
4922 Node* nd = node;
4923
4924 copy_opt_env(&nenv, env);
4925 do {
4926 r = optimize_node_left(NCAR(nd), &nopt, &nenv);
4927 if (r == 0) {
4928 add_mml(&nenv.mmd, &nopt.len);
4929 concat_left_node_opt_info(env->enc, opt, &nopt);
4930 }
4931 } while (r == 0 && IS_NOT_NULL(nd = NCDR(nd)));
4932 }
4933 break;
4934
4935 case NT_ALT:
4936 {
4937 NodeOptInfo nopt;
4938 Node* nd = node;
4939
4940 do {
4941 r = optimize_node_left(NCAR(nd), &nopt, env);
4942 if (r == 0) {
4943 if (nd == node) copy_node_opt_info(opt, &nopt);
4944 else alt_merge_node_opt_info(opt, &nopt, env);
4945 }
4946 } while ((r == 0) && IS_NOT_NULL(nd = NCDR(nd)));
4947 }
4948 break;
4949
4950 case NT_STR:
4951 {
4952 StrNode* sn = NSTR(node);
4953 OnigDistance slen = sn->end - sn->s;
4954 int is_raw = NSTRING_IS_RAW(node);
4955
4956 if (! NSTRING_IS_AMBIG(node)) {
4957 concat_opt_exact_info_str(&opt->exb, sn->s, sn->end,
4958 is_raw, env->enc);
4959 opt->exb.ignore_case = 0;
4960 if (slen > 0) {
4961 add_char_opt_map_info(&opt->map, *(sn->s), env->enc);
4962 }
4963 set_mml(&opt->len, slen, slen);
4964 }
4965 else {
4966 OnigDistance max;
4967
4968 if (NSTRING_IS_DONT_GET_OPT_INFO(node)) {
4969 int n = onigenc_strlen(env->enc, sn->s, sn->end);
4970 max = (OnigDistance )ONIGENC_MBC_MAXLEN_DIST(env->enc) * (OnigDistance)n;
4971 }
4972 else {
4973 concat_opt_exact_info_str(&opt->exb, sn->s, sn->end,
4974 is_raw, env->enc);
4975 opt->exb.ignore_case = 1;
4976
4977 if (slen > 0) {
4978 r = add_char_amb_opt_map_info(&opt->map, sn->s, sn->end,
4979 env->enc, env->case_fold_flag);
4980 if (r != 0) break;
4981 }
4982
4983 max = slen;
4984 }
4985
4986 set_mml(&opt->len, slen, max);
4987 }
4988
4989 if ((OnigDistance )opt->exb.len == slen)
4990 opt->exb.reach_end = 1;
4991 }
4992 break;
4993
4994 case NT_CCLASS:
4995 {
4996 int i, z;
4997 CClassNode* cc = NCCLASS(node);
4998
4999 /* no need to check ignore case. (set in setup_tree()) */
5000
5001 if (IS_NOT_NULL(cc->mbuf) || IS_NCCLASS_NOT(cc)) {
5002 OnigDistance min = ONIGENC_MBC_MINLEN(env->enc);
5003 OnigDistance max = ONIGENC_MBC_MAXLEN_DIST(env->enc);
5004
5005 set_mml(&opt->len, min, max);
5006 }
5007 else {
5008 for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
5009 z = BITSET_AT(cc->bs, i);
5010 if ((z && !IS_NCCLASS_NOT(cc)) || (!z && IS_NCCLASS_NOT(cc))) {
5011 add_char_opt_map_info(&opt->map, (UChar )i, env->enc);
5012 }
5013 }
5014 set_mml(&opt->len, 1, 1);
5015 }
5016 }
5017 break;
5018
5019 case NT_CTYPE:
5020 {
5021 int i, min, max;
5022 int maxcode;
5023
5024 max = ONIGENC_MBC_MAXLEN_DIST(env->enc);
5025
5026 if (max == 1) {
5027 min = 1;
5028
5029 maxcode = NCTYPE(node)->ascii_range ? 0x80 : SINGLE_BYTE_SIZE;
5030 switch (NCTYPE(node)->ctype) {
5031 case ONIGENC_CTYPE_WORD:
5032 if (NCTYPE(node)->not != 0) {
5033 for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
5034 if (! ONIGENC_IS_CODE_WORD(env->enc, i) || i >= maxcode) {
5035 add_char_opt_map_info(&opt->map, (UChar )i, env->enc);
5036 }
5037 }
5038 }
5039 else {
5040 for (i = 0; i < maxcode; i++) {
5041 if (ONIGENC_IS_CODE_WORD(env->enc, i)) {
5042 add_char_opt_map_info(&opt->map, (UChar )i, env->enc);
5043 }
5044 }
5045 }
5046 break;
5047 }
5048 }
5049 else {
5050 min = ONIGENC_MBC_MINLEN(env->enc);
5051 }
5052 set_mml(&opt->len, min, max);
5053 }
5054 break;
5055
5056 case NT_CANY:
5057 {
5058 OnigDistance min = ONIGENC_MBC_MINLEN(env->enc);
5059 OnigDistance max = ONIGENC_MBC_MAXLEN_DIST(env->enc);
5060 set_mml(&opt->len, min, max);
5061 }
5062 break;
5063
5064 case NT_ANCHOR:
5065 switch (NANCHOR(node)->type) {
5066 case ANCHOR_BEGIN_BUF:
5067 case ANCHOR_BEGIN_POSITION:
5068 case ANCHOR_BEGIN_LINE:
5069 case ANCHOR_END_BUF:
5070 case ANCHOR_SEMI_END_BUF:
5071 case ANCHOR_END_LINE:
5072 case ANCHOR_LOOK_BEHIND: /* just for (?<=x).* */
5073 case ANCHOR_PREC_READ_NOT: /* just for (?!x).* */
5074 add_opt_anc_info(&opt->anc, NANCHOR(node)->type);
5075 break;
5076
5077 case ANCHOR_PREC_READ:
5078 {
5079 NodeOptInfo nopt;
5080
5081 r = optimize_node_left(NANCHOR(node)->target, &nopt, env);
5082 if (r == 0) {
5083 if (nopt.exb.len > 0)
5084 copy_opt_exact_info(&opt->expr, &nopt.exb);
5085 else if (nopt.exm.len > 0)
5086 copy_opt_exact_info(&opt->expr, &nopt.exm);
5087
5088 opt->expr.reach_end = 0;
5089
5090 if (nopt.map.value > 0)
5091 copy_opt_map_info(&opt->map, &nopt.map);
5092 }
5093 }
5094 break;
5095
5096 case ANCHOR_LOOK_BEHIND_NOT:
5097 break;
5098 }
5099 break;
5100
5101 case NT_BREF:
5102 {
5103 int i;
5104 int* backs;
5105 OnigDistance min, max, tmin, tmax;
5106 Node** nodes = SCANENV_MEM_NODES(env->scan_env);
5107 BRefNode* br = NBREF(node);
5108
5109 if (br->state & NST_RECURSION) {
5110 set_mml(&opt->len, 0, ONIG_INFINITE_DISTANCE);
5111 break;
5112 }
5113 backs = BACKREFS_P(br);
5114 r = get_min_match_length(nodes[backs[0]], &min, env->scan_env);
5115 if (r != 0) break;
5116 r = get_max_match_length(nodes[backs[0]], &max, env->scan_env);
5117 if (r != 0) break;
5118 for (i = 1; i < br->back_num; i++) {
5119 r = get_min_match_length(nodes[backs[i]], &tmin, env->scan_env);
5120 if (r != 0) break;
5121 r = get_max_match_length(nodes[backs[i]], &tmax, env->scan_env);
5122 if (r != 0) break;
5123 if (min > tmin) min = tmin;
5124 if (max < tmax) max = tmax;
5125 }
5126 if (r == 0) set_mml(&opt->len, min, max);
5127 }
5128 break;
5129
5130#ifdef USE_SUBEXP_CALL
5131 case NT_CALL:
5132 if (IS_CALL_RECURSION(NCALL(node)))
5133 set_mml(&opt->len, 0, ONIG_INFINITE_DISTANCE);
5134 else {
5135 OnigOptionType save = env->options;
5136 env->options = NENCLOSE(NCALL(node)->target)->option;
5137 r = optimize_node_left(NCALL(node)->target, opt, env);
5138 env->options = save;
5139 }
5140 break;
5141#endif
5142
5143 case NT_QTFR:
5144 {
5145 int i;
5146 OnigDistance min, max;
5147 NodeOptInfo nopt;
5148 QtfrNode* qn = NQTFR(node);
5149
5150 r = optimize_node_left(qn->target, &nopt, env);
5151 if (r) break;
5152
5153 if (qn->lower == 0 && IS_REPEAT_INFINITE(qn->upper)) {
5154 if (env->mmd.max == 0 &&
5155 NTYPE(qn->target) == NT_CANY && qn->greedy) {
5156 if (IS_MULTILINE(env->options))
5157 /* implicit anchor: /.*a/ ==> /\A.*a/ */
5158 add_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR_ML);
5159 else
5160 add_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR);
5161 }
5162 }
5163 else {
5164 if (qn->lower > 0) {
5165 copy_node_opt_info(opt, &nopt);
5166 if (nopt.exb.len > 0) {
5167 if (nopt.exb.reach_end) {
5168 for (i = 2; i <= qn->lower &&
5169 ! is_full_opt_exact_info(&opt->exb); i++) {
5170 concat_opt_exact_info(&opt->exb, &nopt.exb, env->enc);
5171 }
5172 if (i < qn->lower) {
5173 opt->exb.reach_end = 0;
5174 }
5175 }
5176 }
5177
5178 if (qn->lower != qn->upper) {
5179 opt->exb.reach_end = 0;
5180 opt->exm.reach_end = 0;
5181 }
5182 if (qn->lower > 1)
5183 opt->exm.reach_end = 0;
5184 }
5185 }
5186
5187 min = distance_multiply(nopt.len.min, qn->lower);
5188 if (IS_REPEAT_INFINITE(qn->upper))
5189 max = (nopt.len.max > 0 ? ONIG_INFINITE_DISTANCE : 0);
5190 else
5191 max = distance_multiply(nopt.len.max, qn->upper);
5192
5193 set_mml(&opt->len, min, max);
5194 }
5195 break;
5196
5197 case NT_ENCLOSE:
5198 {
5199 EncloseNode* en = NENCLOSE(node);
5200
5201 switch (en->type) {
5202 case ENCLOSE_OPTION:
5203 {
5204 OnigOptionType save = env->options;
5205
5206 env->options = en->option;
5207 r = optimize_node_left(en->target, opt, env);
5208 env->options = save;
5209 }
5210 break;
5211
5212 case ENCLOSE_MEMORY:
5213#ifdef USE_SUBEXP_CALL
5214 en->opt_count++;
5215 if (en->opt_count > MAX_NODE_OPT_INFO_REF_COUNT) {
5216 OnigDistance min, max;
5217
5218 min = 0;
5219 max = ONIG_INFINITE_DISTANCE;
5220 if (IS_ENCLOSE_MIN_FIXED(en)) min = en->min_len;
5221 if (IS_ENCLOSE_MAX_FIXED(en)) max = en->max_len;
5222 set_mml(&opt->len, min, max);
5223 }
5224 else
5225#endif
5226 {
5227 r = optimize_node_left(en->target, opt, env);
5228
5229 if (is_set_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR_MASK)) {
5230 if (BIT_STATUS_AT(env->scan_env->backrefed_mem, en->regnum))
5231 remove_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR_MASK);
5232 }
5233 }
5234 break;
5235
5236 case ENCLOSE_STOP_BACKTRACK:
5237 case ENCLOSE_CONDITION:
5238 r = optimize_node_left(en->target, opt, env);
5239 break;
5240
5241 case ENCLOSE_ABSENT:
5242 set_mml(&opt->len, 0, ONIG_INFINITE_DISTANCE);
5243 break;
5244 }
5245 }
5246 break;
5247
5248 default:
5249#ifdef ONIG_DEBUG
5250 fprintf(stderr, "optimize_node_left: undefined node type %d\n",
5251 NTYPE(node));
5252#endif
5253 r = ONIGERR_TYPE_BUG;
5254 break;
5255 }
5256
5257 return r;
5258}
5259
5260static int
5261set_optimize_exact_info(regex_t* reg, OptExactInfo* e)
5262{
5263 int allow_reverse;
5264
5265 if (e->len == 0) return 0;
5266
5267 reg->exact = (UChar* )xmalloc(e->len);
5268 CHECK_NULL_RETURN_MEMERR(reg->exact);
5269 xmemcpy(reg->exact, e->s, e->len);
5270 reg->exact_end = reg->exact + e->len;
5271
5272 allow_reverse =
5273 ONIGENC_IS_ALLOWED_REVERSE_MATCH(reg->enc, reg->exact, reg->exact_end);
5274
5275 if (e->ignore_case > 0) {
5276 if (e->len >= 3 || (e->len >= 2 && allow_reverse)) {
5277 int orig_len = e->len;
5278 e->len = set_bm_skip(reg->exact, reg->exact_end, reg,
5279 reg->map, 1);
5280 if (e->len >= 3) {
5281 reg->exact_end = reg->exact + e->len;
5282 reg->optimize = (allow_reverse != 0
5283 ? ONIG_OPTIMIZE_EXACT_BM_IC : ONIG_OPTIMIZE_EXACT_BM_NOT_REV_IC);
5284 }
5285 else {
5286 /* Even if BM skip table can't be built (e.g., pattern starts with
5287 's' or 'k' which have multi-byte case fold variants), we should
5288 still use EXACT_IC optimization with the original pattern.
5289 Without this fallback, patterns like /slackware/i have no
5290 optimization at all, causing severe performance regression
5291 especially with non-ASCII strings. See [Bug #21824] */
5292 e->len = orig_len; /* Restore original length for EXACT_IC */
5293 reg->optimize = ONIG_OPTIMIZE_EXACT_IC;
5294 }
5295 }
5296 else {
5297 reg->optimize = ONIG_OPTIMIZE_EXACT_IC;
5298 }
5299 }
5300 else {
5301 if (e->len >= 3 || (e->len >= 2 && allow_reverse)) {
5302 set_bm_skip(reg->exact, reg->exact_end, reg,
5303 reg->map, 0);
5304 reg->optimize = (allow_reverse != 0
5305 ? ONIG_OPTIMIZE_EXACT_BM : ONIG_OPTIMIZE_EXACT_BM_NOT_REV);
5306 }
5307 else {
5308 reg->optimize = ONIG_OPTIMIZE_EXACT;
5309 }
5310 }
5311
5312 reg->dmin = e->mmd.min;
5313 reg->dmax = e->mmd.max;
5314
5315 if (reg->dmin != ONIG_INFINITE_DISTANCE) {
5316 reg->threshold_len = (int )(reg->dmin + (reg->exact_end - reg->exact));
5317 }
5318
5319 return 0;
5320}
5321
5322static void
5323set_optimize_map_info(regex_t* reg, OptMapInfo* m)
5324{
5325 int i;
5326
5327 for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++)
5328 reg->map[i] = m->map[i];
5329
5330 reg->optimize = ONIG_OPTIMIZE_MAP;
5331 reg->dmin = m->mmd.min;
5332 reg->dmax = m->mmd.max;
5333
5334 if (reg->dmin != ONIG_INFINITE_DISTANCE) {
5335 reg->threshold_len = (int )(reg->dmin + 1);
5336 }
5337}
5338
5339static void
5340set_sub_anchor(regex_t* reg, OptAncInfo* anc)
5341{
5342 reg->sub_anchor |= anc->left_anchor & ANCHOR_BEGIN_LINE;
5343 reg->sub_anchor |= anc->right_anchor & ANCHOR_END_LINE;
5344}
5345
5346#if defined(ONIG_DEBUG_COMPILE) || defined(ONIG_DEBUG_MATCH)
5347static void print_optimize_info(FILE* f, regex_t* reg);
5348#endif
5349
5350static int
5351set_optimize_info_from_tree(Node* node, regex_t* reg, ScanEnv* scan_env)
5352{
5353
5354 int r;
5355 NodeOptInfo opt;
5356 OptEnv env;
5357
5358 env.enc = reg->enc;
5359 env.options = reg->options;
5360 env.case_fold_flag = reg->case_fold_flag;
5361 env.scan_env = scan_env;
5362 clear_mml(&env.mmd);
5363
5364 r = optimize_node_left(node, &opt, &env);
5365 if (r) return r;
5366
5367 reg->anchor = opt.anc.left_anchor & (ANCHOR_BEGIN_BUF |
5368 ANCHOR_BEGIN_POSITION | ANCHOR_ANYCHAR_STAR | ANCHOR_ANYCHAR_STAR_ML |
5369 ANCHOR_LOOK_BEHIND);
5370
5371 if ((opt.anc.left_anchor & (ANCHOR_LOOK_BEHIND | ANCHOR_PREC_READ_NOT)) != 0)
5372 reg->anchor &= ~ANCHOR_ANYCHAR_STAR_ML;
5373
5374 reg->anchor |= opt.anc.right_anchor & (ANCHOR_END_BUF | ANCHOR_SEMI_END_BUF |
5375 ANCHOR_PREC_READ_NOT);
5376
5377 if (reg->anchor & (ANCHOR_END_BUF | ANCHOR_SEMI_END_BUF)) {
5378 reg->anchor_dmin = opt.len.min;
5379 reg->anchor_dmax = opt.len.max;
5380 }
5381
5382 if (opt.exb.len > 0 || opt.exm.len > 0) {
5383 select_opt_exact_info(reg->enc, &opt.exb, &opt.exm);
5384 if (opt.map.value > 0 &&
5385 comp_opt_exact_or_map_info(&opt.exb, &opt.map) > 0) {
5386 goto set_map;
5387 }
5388 else {
5389 r = set_optimize_exact_info(reg, &opt.exb);
5390 set_sub_anchor(reg, &opt.exb.anc);
5391 }
5392 }
5393 else if (opt.map.value > 0) {
5394 set_map:
5395 set_optimize_map_info(reg, &opt.map);
5396 set_sub_anchor(reg, &opt.map.anc);
5397 }
5398 else {
5399 reg->sub_anchor |= opt.anc.left_anchor & ANCHOR_BEGIN_LINE;
5400 if (opt.len.max == 0)
5401 reg->sub_anchor |= opt.anc.right_anchor & ANCHOR_END_LINE;
5402 }
5403
5404#if defined(ONIG_DEBUG_COMPILE) || defined(ONIG_DEBUG_MATCH)
5405 print_optimize_info(stderr, reg);
5406#endif
5407 return r;
5408}
5409
5410static void
5411clear_optimize_info(regex_t* reg)
5412{
5413 reg->optimize = ONIG_OPTIMIZE_NONE;
5414 reg->anchor = 0;
5415 reg->anchor_dmin = 0;
5416 reg->anchor_dmax = 0;
5417 reg->sub_anchor = 0;
5418 reg->exact_end = (UChar* )NULL;
5419 reg->threshold_len = 0;
5420 xfree(reg->exact);
5421 reg->exact = (UChar* )NULL;
5422}
5423
5424#ifdef ONIG_DEBUG
5425
5426static void print_enc_string(FILE* fp, OnigEncoding enc,
5427 const UChar *s, const UChar *end)
5428{
5429 fprintf(fp, "\nPATTERN: /");
5430
5431 if (ONIGENC_MBC_MINLEN(enc) > 1) {
5432 const UChar *p;
5433 OnigCodePoint code;
5434
5435 p = s;
5436 while (p < end) {
5437 code = ONIGENC_MBC_TO_CODE(enc, p, end);
5438 if (code >= 0x80) {
5439 fprintf(fp, " 0x%04x ", (int )code);
5440 }
5441 else {
5442 fputc((int )code, fp);
5443 }
5444
5445 p += enclen(enc, p, end);
5446 }
5447 }
5448 else {
5449 while (s < end) {
5450 fputc((int )*s, fp);
5451 s++;
5452 }
5453 }
5454
5455 fprintf(fp, "/ (%s)\n", enc->name);
5456}
5457#endif /* ONIG_DEBUG */
5458
5459#if defined(ONIG_DEBUG_COMPILE) || defined(ONIG_DEBUG_MATCH)
5460static void
5461print_distance_range(FILE* f, OnigDistance a, OnigDistance b)
5462{
5463 if (a == ONIG_INFINITE_DISTANCE)
5464 fputs("inf", f);
5465 else
5466 fprintf(f, "(%"PRIuPTR")", a);
5467
5468 fputs("-", f);
5469
5470 if (b == ONIG_INFINITE_DISTANCE)
5471 fputs("inf", f);
5472 else
5473 fprintf(f, "(%"PRIuPTR")", b);
5474}
5475
5476static void
5477print_anchor(FILE* f, int anchor)
5478{
5479 int q = 0;
5480
5481 fprintf(f, "[");
5482
5483 if (anchor & ANCHOR_BEGIN_BUF) {
5484 fprintf(f, "begin-buf");
5485 q = 1;
5486 }
5487 if (anchor & ANCHOR_BEGIN_LINE) {
5488 if (q) fprintf(f, ", ");
5489 q = 1;
5490 fprintf(f, "begin-line");
5491 }
5492 if (anchor & ANCHOR_BEGIN_POSITION) {
5493 if (q) fprintf(f, ", ");
5494 q = 1;
5495 fprintf(f, "begin-pos");
5496 }
5497 if (anchor & ANCHOR_END_BUF) {
5498 if (q) fprintf(f, ", ");
5499 q = 1;
5500 fprintf(f, "end-buf");
5501 }
5502 if (anchor & ANCHOR_SEMI_END_BUF) {
5503 if (q) fprintf(f, ", ");
5504 q = 1;
5505 fprintf(f, "semi-end-buf");
5506 }
5507 if (anchor & ANCHOR_END_LINE) {
5508 if (q) fprintf(f, ", ");
5509 q = 1;
5510 fprintf(f, "end-line");
5511 }
5512 if (anchor & ANCHOR_ANYCHAR_STAR) {
5513 if (q) fprintf(f, ", ");
5514 q = 1;
5515 fprintf(f, "anychar-star");
5516 }
5517 if (anchor & ANCHOR_ANYCHAR_STAR_ML) {
5518 if (q) fprintf(f, ", ");
5519 fprintf(f, "anychar-star-ml");
5520 }
5521
5522 fprintf(f, "]");
5523}
5524
5525static void
5526print_optimize_info(FILE* f, regex_t* reg)
5527{
5528 static const char* on[] = { "NONE", "EXACT", "EXACT_BM", "EXACT_BM_NOT_REV",
5529 "EXACT_IC", "MAP",
5530 "EXACT_BM_IC", "EXACT_BM_NOT_REV_IC" };
5531
5532 fprintf(f, "optimize: %s\n", on[reg->optimize]);
5533 fprintf(f, " anchor: "); print_anchor(f, reg->anchor);
5534 if ((reg->anchor & ANCHOR_END_BUF_MASK) != 0)
5535 print_distance_range(f, reg->anchor_dmin, reg->anchor_dmax);
5536 fprintf(f, "\n");
5537
5538 if (reg->optimize) {
5539 fprintf(f, " sub anchor: "); print_anchor(f, reg->sub_anchor);
5540 fprintf(f, "\n");
5541 }
5542 fprintf(f, "\n");
5543
5544 if (reg->exact) {
5545 UChar *p;
5546 fprintf(f, "exact: [");
5547 for (p = reg->exact; p < reg->exact_end; p++) {
5548 fputc(*p, f);
5549 }
5550 fprintf(f, "]: length: %"PRIdPTR"\n", (reg->exact_end - reg->exact));
5551 }
5552 else if (reg->optimize & ONIG_OPTIMIZE_MAP) {
5553 int c, i, n = 0;
5554
5555 for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++)
5556 if (reg->map[i]) n++;
5557
5558 fprintf(f, "map: n=%d\n", n);
5559 if (n > 0) {
5560 c = 0;
5561 fputc('[', f);
5562 for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) {
5563 if (reg->map[i] != 0) {
5564 if (c > 0) fputs(", ", f);
5565 c++;
5566 if (ONIGENC_MBC_MAXLEN(reg->enc) == 1 &&
5567 ONIGENC_IS_CODE_PRINT(reg->enc, (OnigCodePoint )i))
5568 fputc(i, f);
5569 else
5570 fprintf(f, "%d", i);
5571 }
5572 }
5573 fprintf(f, "]\n");
5574 }
5575 }
5576}
5577#endif /* ONIG_DEBUG_COMPILE || ONIG_DEBUG_MATCH */
5578
5579
5580extern void
5581onig_free_body(regex_t* reg)
5582{
5583 if (IS_NOT_NULL(reg)) {
5584 xfree(reg->p);
5585 xfree(reg->exact);
5586 xfree(reg->repeat_range);
5587 onig_free(reg->chain);
5588
5589#ifdef USE_NAMED_GROUP
5590 onig_names_free(reg);
5591#endif
5592 }
5593}
5594
5595extern void
5596onig_free(regex_t* reg)
5597{
5598 if (IS_NOT_NULL(reg)) {
5599 onig_free_body(reg);
5600 xfree(reg);
5601 }
5602}
5603
5604static void*
5605dup_copy(const void *ptr, size_t size)
5606{
5607 void *newptr = xmalloc(size);
5608 if (IS_NOT_NULL(newptr)) {
5609 memcpy(newptr, ptr, size);
5610 }
5611 return newptr;
5612}
5613
5614extern int
5615onig_reg_copy_body(regex_t* nreg, regex_t* oreg)
5616{
5617 if (IS_NOT_NULL(oreg)) {
5618 *nreg = *oreg;
5619
5620# define COPY_FAILED(mem, size) IS_NULL(nreg->mem = dup_copy(oreg->mem, size))
5621
5622 if (IS_NOT_NULL(oreg->exact)) {
5623 size_t exact_size = oreg->exact_end - oreg->exact;
5624 if (COPY_FAILED(exact, exact_size))
5625 goto err;
5626 (nreg)->exact_end = (nreg)->exact + exact_size;
5627 }
5628
5629 if (IS_NOT_NULL(oreg->p)) {
5630 if (COPY_FAILED(p, oreg->alloc))
5631 goto err_p;
5632 }
5633 if (IS_NOT_NULL(oreg->repeat_range)) {
5634 if (COPY_FAILED(repeat_range, oreg->repeat_range_alloc * sizeof(OnigRepeatRange)))
5635 goto err_repeat_range;
5636 }
5637 if (IS_NOT_NULL(oreg->name_table)) {
5638 if (onig_names_copy(nreg, oreg))
5639 goto err_name_table;
5640 }
5641 if (IS_NOT_NULL(oreg->chain)) {
5642 if (onig_reg_copy(&nreg->chain, oreg->chain))
5643 goto err_chain;
5644 }
5645 return 0;
5646# undef COPY_FAILED
5647
5648 err_chain:
5649 onig_names_free(nreg);
5650 err_name_table:
5651 xfree(nreg->repeat_range);
5652 err_repeat_range:
5653 xfree(nreg->p);
5654 err_p:
5655 xfree(nreg->exact);
5656 err:
5657 xfree(nreg);
5658 return ONIGERR_MEMORY;
5659 }
5660 return 0;
5661}
5662
5663extern int
5664onig_reg_copy(regex_t** nreg, regex_t* oreg)
5665{
5666 if (IS_NOT_NULL(oreg)) {
5667 regex_t *reg = *nreg = (regex_t* )xmalloc(sizeof(regex_t));
5668 if (IS_NULL(reg)) return ONIGERR_MEMORY;
5669
5670 return onig_reg_copy_body(reg, oreg);
5671 }
5672 return 0;
5673}
5674
5675#ifdef RUBY
5676size_t
5677onig_memsize(const regex_t *reg)
5678{
5679 size_t size = sizeof(regex_t);
5680 if (IS_NULL(reg)) return 0;
5681 if (IS_NOT_NULL(reg->p)) size += reg->alloc;
5682 if (IS_NOT_NULL(reg->exact)) size += reg->exact_end - reg->exact;
5683 if (IS_NOT_NULL(reg->repeat_range)) size += reg->repeat_range_alloc * sizeof(OnigRepeatRange);
5684 if (IS_NOT_NULL(reg->chain)) size += onig_memsize(reg->chain);
5685
5686 return size;
5687}
5688
5689size_t
5690onig_region_memsize(const OnigRegion *regs)
5691{
5692 size_t size = sizeof(*regs);
5693 if (IS_NULL(regs)) return 0;
5694 size += regs->allocated * (sizeof(*regs->beg) + sizeof(*regs->end));
5695 return size;
5696}
5697#endif
5698
5699#define REGEX_TRANSFER(to,from) do {\
5700 onig_free_body(to);\
5701 xmemcpy(to, from, sizeof(regex_t));\
5702 xfree(from);\
5703} while (0)
5704
5705#if 0
5706extern void
5707onig_transfer(regex_t* to, regex_t* from)
5708{
5709 REGEX_TRANSFER(to, from);
5710}
5711#endif
5712
5713#ifdef ONIG_DEBUG_COMPILE
5714static void print_compiled_byte_code_list(FILE* f, regex_t* reg);
5715#endif
5716#ifdef ONIG_DEBUG_PARSE_TREE
5717static void print_tree(FILE* f, Node* node);
5718#endif
5719
5720#ifdef RUBY
5721extern int
5722onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end,
5723 OnigErrorInfo* einfo)
5724{
5725 return onig_compile_ruby(reg, pattern, pattern_end, einfo, NULL, 0);
5726}
5727#endif
5728
5729#ifdef RUBY
5730extern int
5731onig_compile_ruby(regex_t* reg, const UChar* pattern, const UChar* pattern_end,
5732 OnigErrorInfo* einfo, const char *sourcefile, int sourceline)
5733#else
5734extern int
5735onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end,
5736 OnigErrorInfo* einfo)
5737#endif
5738{
5739#define COMPILE_INIT_SIZE 20
5740
5741 int r;
5742 OnigDistance init_size;
5743 Node* root;
5744 ScanEnv scan_env = {0};
5745#ifdef USE_SUBEXP_CALL
5746 UnsetAddrList uslist;
5747#endif
5748
5749 if (IS_NOT_NULL(einfo)) einfo->par = (UChar* )NULL;
5750
5751#ifdef RUBY
5752 scan_env.sourcefile = sourcefile;
5753 scan_env.sourceline = sourceline;
5754#endif
5755
5756#ifdef ONIG_DEBUG
5757 print_enc_string(stderr, reg->enc, pattern, pattern_end);
5758#endif
5759
5760 if (reg->alloc == 0) {
5761 init_size = (pattern_end - pattern) * 2;
5762 if (init_size <= 0) init_size = COMPILE_INIT_SIZE;
5763 r = BBUF_INIT(reg, init_size);
5764 if (r != 0) goto end;
5765 }
5766 else
5767 reg->used = 0;
5768
5769 reg->num_mem = 0;
5770 reg->num_repeat = 0;
5771 reg->num_null_check = 0;
5772 reg->repeat_range_alloc = 0;
5773 reg->repeat_range = (OnigRepeatRange* )NULL;
5774#ifdef USE_COMBINATION_EXPLOSION_CHECK
5775 reg->num_comb_exp_check = 0;
5776#endif
5777
5778 r = onig_parse_make_tree(&root, pattern, pattern_end, reg, &scan_env);
5779 if (r != 0) goto err;
5780
5781#ifdef ONIG_DEBUG_PARSE_TREE
5782# if 0
5783 fprintf(stderr, "ORIGINAL PARSE TREE:\n");
5784 print_tree(stderr, root);
5785# endif
5786#endif
5787
5788#ifdef USE_NAMED_GROUP
5789 /* mixed use named group and no-named group */
5790 if (scan_env.num_named > 0 &&
5791 IS_SYNTAX_BV(scan_env.syntax, ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP) &&
5792 !ONIG_IS_OPTION_ON(reg->options, ONIG_OPTION_CAPTURE_GROUP)) {
5793 if (scan_env.num_named != scan_env.num_mem)
5794 r = disable_noname_group_capture(&root, reg, &scan_env);
5795 else
5796 r = numbered_ref_check(root);
5797
5798 if (r != 0) goto err;
5799 }
5800#endif
5801
5802#ifdef USE_SUBEXP_CALL
5803 if (scan_env.num_call > 0) {
5804 r = unset_addr_list_init(&uslist, scan_env.num_call);
5805 if (r != 0) goto err;
5806 scan_env.unset_addr_list = &uslist;
5807 r = setup_subexp_call(root, &scan_env);
5808 if (r != 0) goto err_unset;
5809 r = subexp_recursive_check_trav(root, &scan_env);
5810 if (r < 0) goto err_unset;
5811 r = subexp_inf_recursive_check_trav(root, &scan_env);
5812 if (r != 0) goto err_unset;
5813
5814 reg->num_call = scan_env.num_call;
5815 }
5816 else
5817 reg->num_call = 0;
5818#endif
5819
5820 r = setup_tree(root, reg, 0, &scan_env);
5821 if (r != 0) goto err_unset;
5822
5823#ifdef ONIG_DEBUG_PARSE_TREE
5824 print_tree(stderr, root);
5825#endif
5826
5827 reg->capture_history = scan_env.capture_history;
5828 reg->bt_mem_start = scan_env.bt_mem_start;
5829 reg->bt_mem_start |= reg->capture_history;
5830 if (IS_FIND_CONDITION(reg->options))
5831 BIT_STATUS_ON_ALL(reg->bt_mem_end);
5832 else {
5833 reg->bt_mem_end = scan_env.bt_mem_end;
5834 reg->bt_mem_end |= reg->capture_history;
5835 }
5836
5837#ifdef USE_COMBINATION_EXPLOSION_CHECK
5838 if (scan_env.backrefed_mem == 0
5839# ifdef USE_SUBEXP_CALL
5840 || scan_env.num_call == 0
5841# endif
5842 ) {
5843 setup_comb_exp_check(root, 0, &scan_env);
5844# ifdef USE_SUBEXP_CALL
5845 if (scan_env.has_recursion != 0) {
5846 scan_env.num_comb_exp_check = 0;
5847 }
5848 else
5849# endif
5850 if (scan_env.comb_exp_max_regnum > 0) {
5851 int i;
5852 for (i = 1; i <= scan_env.comb_exp_max_regnum; i++) {
5853 if (BIT_STATUS_AT(scan_env.backrefed_mem, i) != 0) {
5854 scan_env.num_comb_exp_check = 0;
5855 break;
5856 }
5857 }
5858 }
5859 }
5860
5861 reg->num_comb_exp_check = scan_env.num_comb_exp_check;
5862#endif
5863
5864 clear_optimize_info(reg);
5865#ifndef ONIG_DONT_OPTIMIZE
5866 r = set_optimize_info_from_tree(root, reg, &scan_env);
5867 if (r != 0) goto err_unset;
5868#endif
5869
5870 if (IS_NOT_NULL(scan_env.mem_nodes_dynamic)) {
5871 xfree(scan_env.mem_nodes_dynamic);
5872 scan_env.mem_nodes_dynamic = (Node** )NULL;
5873 }
5874
5875 r = compile_tree(root, reg);
5876 if (r == 0) {
5877 r = add_opcode(reg, OP_END);
5878#ifdef USE_SUBEXP_CALL
5879 if (scan_env.num_call > 0) {
5880 r = unset_addr_list_fix(&uslist, reg);
5881 unset_addr_list_end(&uslist);
5882 if (r) goto err;
5883 }
5884#endif
5885
5886 if ((reg->num_repeat != 0) || (reg->bt_mem_end != 0))
5887 reg->stack_pop_level = STACK_POP_LEVEL_ALL;
5888 else {
5889 if (reg->bt_mem_start != 0)
5890 reg->stack_pop_level = STACK_POP_LEVEL_MEM_START;
5891 else
5892 reg->stack_pop_level = STACK_POP_LEVEL_FREE;
5893 }
5894 }
5895#ifdef USE_SUBEXP_CALL
5896 else if (scan_env.num_call > 0) {
5897 unset_addr_list_end(&uslist);
5898 }
5899#endif
5900 onig_node_free(root);
5901
5902#ifdef ONIG_DEBUG_COMPILE
5903# ifdef USE_NAMED_GROUP
5904 onig_print_names(stderr, reg);
5905# endif
5906 print_compiled_byte_code_list(stderr, reg);
5907#endif
5908
5909 end:
5910 onig_reg_resize(reg);
5911 return r;
5912
5913 err_unset:
5914#ifdef USE_SUBEXP_CALL
5915 if (scan_env.num_call > 0) {
5916 unset_addr_list_end(&uslist);
5917 }
5918#endif
5919 err:
5920 if (IS_NOT_NULL(scan_env.error)) {
5921 if (IS_NOT_NULL(einfo)) {
5922 einfo->enc = scan_env.enc;
5923 einfo->par = scan_env.error;
5924 einfo->par_end = scan_env.error_end;
5925 }
5926 }
5927
5928 onig_node_free(root);
5929 xfree(scan_env.mem_nodes_dynamic);
5930
5931 return r;
5932}
5933
5934static int onig_inited = 0;
5935
5936extern int
5937onig_reg_init(regex_t* reg, OnigOptionType option,
5938 OnigCaseFoldType case_fold_flag,
5939 OnigEncoding enc, const OnigSyntaxType* syntax)
5940{
5941 if (! onig_inited)
5942 onig_init();
5943
5944 if (IS_NULL(reg))
5945 return ONIGERR_INVALID_ARGUMENT;
5946
5947 (reg)->exact = (UChar* )NULL;
5948 (reg)->chain = (regex_t* )NULL;
5949 (reg)->p = (UChar* )NULL;
5950 (reg)->name_table = (void* )NULL;
5951 (reg)->repeat_range = (OnigRepeatRange* )NULL;
5952
5953 if (ONIGENC_IS_UNDEF(enc))
5954 return ONIGERR_DEFAULT_ENCODING_IS_NOT_SET;
5955
5956 if ((option & (ONIG_OPTION_DONT_CAPTURE_GROUP|ONIG_OPTION_CAPTURE_GROUP))
5957 == (ONIG_OPTION_DONT_CAPTURE_GROUP|ONIG_OPTION_CAPTURE_GROUP)) {
5958 return ONIGERR_INVALID_COMBINATION_OF_OPTIONS;
5959 }
5960
5961 if ((option & ONIG_OPTION_NEGATE_SINGLELINE) != 0) {
5962 option |= syntax->options;
5963 option &= ~ONIG_OPTION_SINGLELINE;
5964 }
5965 else
5966 option |= syntax->options;
5967
5968 (reg)->enc = enc;
5969 (reg)->options = option;
5970 (reg)->syntax = syntax;
5971 (reg)->optimize = 0;
5972
5973 (reg)->alloc = 0;
5974 (reg)->used = 0;
5975
5976 (reg)->case_fold_flag = case_fold_flag;
5977
5978 (reg)->timelimit = 0;
5979
5980 return 0;
5981}
5982
5983extern int
5984onig_new_without_alloc(regex_t* reg, const UChar* pattern,
5985 const UChar* pattern_end, OnigOptionType option, OnigEncoding enc,
5986 const OnigSyntaxType* syntax, OnigErrorInfo* einfo)
5987{
5988 int r;
5989
5990 r = onig_reg_init(reg, option, ONIGENC_CASE_FOLD_DEFAULT, enc, syntax);
5991 if (r) return r;
5992
5993 r = onig_compile(reg, pattern, pattern_end, einfo);
5994 return r;
5995}
5996
5997extern int
5998onig_new(regex_t** reg, const UChar* pattern, const UChar* pattern_end,
5999 OnigOptionType option, OnigEncoding enc, const OnigSyntaxType* syntax,
6000 OnigErrorInfo* einfo)
6001{
6002 *reg = (regex_t* )xmalloc(sizeof(regex_t));
6003 if (IS_NULL(*reg)) return ONIGERR_MEMORY;
6004
6005 int r = onig_new_without_alloc(*reg, pattern, pattern_end, option, enc, syntax, einfo);
6006 if (r) {
6007 onig_free(*reg);
6008 *reg = NULL;
6009 }
6010
6011 return r;
6012}
6013
6014extern int
6015onig_initialize(OnigEncoding encodings[] ARG_UNUSED, int n ARG_UNUSED)
6016{
6017 return onig_init();
6018}
6019
6020extern int
6021onig_init(void)
6022{
6023 if (onig_inited != 0)
6024 return 0;
6025
6026 onig_inited = 1;
6027
6028#if defined(ONIG_DEBUG_MEMLEAK) && defined(_MSC_VER)
6029 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
6030#endif
6031
6032 onigenc_init();
6033 /* onigenc_set_default_caseconv_table((UChar* )0); */
6034
6035#ifdef ONIG_DEBUG_STATISTICS
6036 onig_statistics_init();
6037#endif
6038
6039 return 0;
6040}
6041
6042
6043static OnigEndCallListItemType* EndCallTop;
6044
6045extern void onig_add_end_call(void (*func)(void))
6046{
6048
6049 item = (OnigEndCallListItemType* )xmalloc(sizeof(*item));
6050 if (item == 0) return ;
6051
6052 item->next = EndCallTop;
6053 item->func = func;
6054
6055 EndCallTop = item;
6056}
6057
6058static void
6059exec_end_call_list(void)
6060{
6062 void (*func)(void);
6063
6064 while (EndCallTop != 0) {
6065 func = EndCallTop->func;
6066 (*func)();
6067
6068 prev = EndCallTop;
6069 EndCallTop = EndCallTop->next;
6070 xfree(prev);
6071 }
6072}
6073
6074extern int
6075onig_end(void)
6076{
6077 exec_end_call_list();
6078
6079#ifdef ONIG_DEBUG_STATISTICS
6080 onig_print_statistics(stderr);
6081#endif
6082
6083#if defined(ONIG_DEBUG_MEMLEAK) && defined(_MSC_VER)
6084 _CrtDumpMemoryLeaks();
6085#endif
6086
6087 onig_inited = 0;
6088
6089 return 0;
6090}
6091
6092extern int
6093onig_is_in_code_range(const UChar* p, OnigCodePoint code)
6094{
6095 OnigCodePoint n, *data;
6096 OnigCodePoint low, high, x;
6097
6098 GET_CODE_POINT(n, p);
6099 data = (OnigCodePoint* )p;
6100 data++;
6101
6102 for (low = 0, high = n; low < high; ) {
6103 x = (low + high) >> 1;
6104 if (code > data[x * 2 + 1])
6105 low = x + 1;
6106 else
6107 high = x;
6108 }
6109
6110 return ((low < n && code >= data[low * 2]) ? 1 : 0);
6111}
6112
6113extern int
6114onig_is_code_in_cc_len(int elen, OnigCodePoint code, CClassNode* cc)
6115{
6116 int found;
6117
6118 if (elen > 1 || (code >= SINGLE_BYTE_SIZE)) {
6119 if (IS_NULL(cc->mbuf)) {
6120 found = 0;
6121 }
6122 else {
6123 found = (onig_is_in_code_range(cc->mbuf->p, code) != 0 ? 1 : 0);
6124 }
6125 }
6126 else {
6127 found = (BITSET_AT(cc->bs, code) == 0 ? 0 : 1);
6128 }
6129
6130 if (IS_NCCLASS_NOT(cc))
6131 return !found;
6132 else
6133 return found;
6134}
6135
6136extern int
6137onig_is_code_in_cc(OnigEncoding enc, OnigCodePoint code, CClassNode* cc)
6138{
6139 int len;
6140
6141 if (ONIGENC_MBC_MINLEN(enc) > 1) {
6142 len = 2;
6143 }
6144 else {
6145 len = ONIGENC_CODE_TO_MBCLEN(enc, code);
6146 }
6147 return onig_is_code_in_cc_len(len, code, cc);
6148}
6149
6150
6151#ifdef ONIG_DEBUG
6152
6153/* arguments type */
6154# define ARG_SPECIAL -1
6155# define ARG_NON 0
6156# define ARG_RELADDR 1
6157# define ARG_ABSADDR 2
6158# define ARG_LENGTH 3
6159# define ARG_MEMNUM 4
6160# define ARG_OPTION 5
6161# define ARG_STATE_CHECK 6
6162
6163OnigOpInfoType OnigOpInfo[] = {
6164 { OP_FINISH, "finish", ARG_NON },
6165 { OP_END, "end", ARG_NON },
6166 { OP_EXACT1, "exact1", ARG_SPECIAL },
6167 { OP_EXACT2, "exact2", ARG_SPECIAL },
6168 { OP_EXACT3, "exact3", ARG_SPECIAL },
6169 { OP_EXACT4, "exact4", ARG_SPECIAL },
6170 { OP_EXACT5, "exact5", ARG_SPECIAL },
6171 { OP_EXACTN, "exactn", ARG_SPECIAL },
6172 { OP_EXACTMB2N1, "exactmb2-n1", ARG_SPECIAL },
6173 { OP_EXACTMB2N2, "exactmb2-n2", ARG_SPECIAL },
6174 { OP_EXACTMB2N3, "exactmb2-n3", ARG_SPECIAL },
6175 { OP_EXACTMB2N, "exactmb2-n", ARG_SPECIAL },
6176 { OP_EXACTMB3N, "exactmb3n" , ARG_SPECIAL },
6177 { OP_EXACTMBN, "exactmbn", ARG_SPECIAL },
6178 { OP_EXACT1_IC, "exact1-ic", ARG_SPECIAL },
6179 { OP_EXACTN_IC, "exactn-ic", ARG_SPECIAL },
6180 { OP_CCLASS, "cclass", ARG_SPECIAL },
6181 { OP_CCLASS_MB, "cclass-mb", ARG_SPECIAL },
6182 { OP_CCLASS_MIX, "cclass-mix", ARG_SPECIAL },
6183 { OP_CCLASS_NOT, "cclass-not", ARG_SPECIAL },
6184 { OP_CCLASS_MB_NOT, "cclass-mb-not", ARG_SPECIAL },
6185 { OP_CCLASS_MIX_NOT, "cclass-mix-not", ARG_SPECIAL },
6186 { OP_ANYCHAR, "anychar", ARG_NON },
6187 { OP_ANYCHAR_ML, "anychar-ml", ARG_NON },
6188 { OP_ANYCHAR_STAR, "anychar*", ARG_NON },
6189 { OP_ANYCHAR_ML_STAR, "anychar-ml*", ARG_NON },
6190 { OP_ANYCHAR_STAR_PEEK_NEXT, "anychar*-peek-next", ARG_SPECIAL },
6191 { OP_ANYCHAR_ML_STAR_PEEK_NEXT, "anychar-ml*-peek-next", ARG_SPECIAL },
6192 { OP_WORD, "word", ARG_NON },
6193 { OP_NOT_WORD, "not-word", ARG_NON },
6194 { OP_WORD_BOUND, "word-bound", ARG_NON },
6195 { OP_NOT_WORD_BOUND, "not-word-bound", ARG_NON },
6196 { OP_WORD_BEGIN, "word-begin", ARG_NON },
6197 { OP_WORD_END, "word-end", ARG_NON },
6198 { OP_ASCII_WORD, "ascii-word", ARG_NON },
6199 { OP_NOT_ASCII_WORD, "not-ascii-word", ARG_NON },
6200 { OP_ASCII_WORD_BOUND, "ascii-word-bound", ARG_NON },
6201 { OP_NOT_ASCII_WORD_BOUND,"not-ascii-word-bound", ARG_NON },
6202 { OP_ASCII_WORD_BEGIN, "ascii-word-begin", ARG_NON },
6203 { OP_ASCII_WORD_END, "ascii-word-end", ARG_NON },
6204 { OP_BEGIN_BUF, "begin-buf", ARG_NON },
6205 { OP_END_BUF, "end-buf", ARG_NON },
6206 { OP_BEGIN_LINE, "begin-line", ARG_NON },
6207 { OP_END_LINE, "end-line", ARG_NON },
6208 { OP_SEMI_END_BUF, "semi-end-buf", ARG_NON },
6209 { OP_BEGIN_POSITION, "begin-position", ARG_NON },
6210 { OP_BACKREF1, "backref1", ARG_NON },
6211 { OP_BACKREF2, "backref2", ARG_NON },
6212 { OP_BACKREFN, "backrefn", ARG_MEMNUM },
6213 { OP_BACKREFN_IC, "backrefn-ic", ARG_SPECIAL },
6214 { OP_BACKREF_MULTI, "backref_multi", ARG_SPECIAL },
6215 { OP_BACKREF_MULTI_IC, "backref_multi-ic", ARG_SPECIAL },
6216 { OP_BACKREF_WITH_LEVEL, "backref_at_level", ARG_SPECIAL },
6217 { OP_MEMORY_START_PUSH, "mem-start-push", ARG_MEMNUM },
6218 { OP_MEMORY_START, "mem-start", ARG_MEMNUM },
6219 { OP_MEMORY_END_PUSH, "mem-end-push", ARG_MEMNUM },
6220 { OP_MEMORY_END_PUSH_REC, "mem-end-push-rec", ARG_MEMNUM },
6221 { OP_MEMORY_END, "mem-end", ARG_MEMNUM },
6222 { OP_MEMORY_END_REC, "mem-end-rec", ARG_MEMNUM },
6223 { OP_SET_OPTION_PUSH, "set-option-push", ARG_OPTION },
6224 { OP_SET_OPTION, "set-option", ARG_OPTION },
6225 { OP_KEEP, "keep", ARG_NON },
6226 { OP_FAIL, "fail", ARG_NON },
6227 { OP_JUMP, "jump", ARG_RELADDR },
6228 { OP_PUSH, "push", ARG_RELADDR },
6229 { OP_POP, "pop", ARG_NON },
6230 { OP_PUSH_OR_JUMP_EXACT1, "push-or-jump-e1", ARG_SPECIAL },
6231 { OP_PUSH_IF_PEEK_NEXT, "push-if-peek-next", ARG_SPECIAL },
6232 { OP_REPEAT, "repeat", ARG_SPECIAL },
6233 { OP_REPEAT_NG, "repeat-ng", ARG_SPECIAL },
6234 { OP_REPEAT_INC, "repeat-inc", ARG_MEMNUM },
6235 { OP_REPEAT_INC_NG, "repeat-inc-ng", ARG_MEMNUM },
6236 { OP_REPEAT_INC_SG, "repeat-inc-sg", ARG_MEMNUM },
6237 { OP_REPEAT_INC_NG_SG, "repeat-inc-ng-sg", ARG_MEMNUM },
6238 { OP_NULL_CHECK_START, "null-check-start", ARG_MEMNUM },
6239 { OP_NULL_CHECK_END, "null-check-end", ARG_MEMNUM },
6240 { OP_NULL_CHECK_END_MEMST,"null-check-end-memst", ARG_MEMNUM },
6241 { OP_NULL_CHECK_END_MEMST_PUSH,"null-check-end-memst-push", ARG_MEMNUM },
6242 { OP_PUSH_POS, "push-pos", ARG_NON },
6243 { OP_POP_POS, "pop-pos", ARG_NON },
6244 { OP_PUSH_POS_NOT, "push-pos-not", ARG_RELADDR },
6245 { OP_FAIL_POS, "fail-pos", ARG_NON },
6246 { OP_PUSH_STOP_BT, "push-stop-bt", ARG_NON },
6247 { OP_POP_STOP_BT, "pop-stop-bt", ARG_NON },
6248 { OP_LOOK_BEHIND, "look-behind", ARG_SPECIAL },
6249 { OP_PUSH_LOOK_BEHIND_NOT, "push-look-behind-not", ARG_SPECIAL },
6250 { OP_FAIL_LOOK_BEHIND_NOT, "fail-look-behind-not", ARG_NON },
6251 { OP_PUSH_ABSENT_POS, "push-absent-pos", ARG_NON },
6252 { OP_ABSENT, "absent", ARG_RELADDR },
6253 { OP_ABSENT_END, "absent-end", ARG_NON },
6254 { OP_CALL, "call", ARG_ABSADDR },
6255 { OP_RETURN, "return", ARG_NON },
6256 { OP_CONDITION, "condition", ARG_SPECIAL },
6257 { OP_STATE_CHECK_PUSH, "state-check-push", ARG_SPECIAL },
6258 { OP_STATE_CHECK_PUSH_OR_JUMP, "state-check-push-or-jump", ARG_SPECIAL },
6259 { OP_STATE_CHECK, "state-check", ARG_STATE_CHECK },
6260 { OP_STATE_CHECK_ANYCHAR_STAR, "state-check-anychar*", ARG_STATE_CHECK },
6261 { OP_STATE_CHECK_ANYCHAR_ML_STAR,
6262 "state-check-anychar-ml*", ARG_STATE_CHECK },
6263 { -1, "", ARG_NON }
6264};
6265
6266static const char*
6267op2name(int opcode)
6268{
6269 int i;
6270
6271 for (i = 0; OnigOpInfo[i].opcode >= 0; i++) {
6272 if (opcode == OnigOpInfo[i].opcode)
6273 return OnigOpInfo[i].name;
6274 }
6275 return "";
6276}
6277
6278static int
6279op2arg_type(int opcode)
6280{
6281 int i;
6282
6283 for (i = 0; OnigOpInfo[i].opcode >= 0; i++) {
6284 if (opcode == OnigOpInfo[i].opcode)
6285 return OnigOpInfo[i].arg_type;
6286 }
6287 return ARG_SPECIAL;
6288}
6289
6290# ifdef ONIG_DEBUG_PARSE_TREE
6291static void
6292Indent(FILE* f, int indent)
6293{
6294 int i;
6295 for (i = 0; i < indent; i++) putc(' ', f);
6296}
6297# endif /* ONIG_DEBUG_PARSE_TREE */
6298
6299static void
6300p_string(FILE* f, ptrdiff_t len, UChar* s)
6301{
6302 fputs(":", f);
6303 while (len-- > 0) { fputc(*s++, f); }
6304}
6305
6306static void
6307p_len_string(FILE* f, LengthType len, int mb_len, UChar* s)
6308{
6309 int x = len * mb_len;
6310
6311 fprintf(f, ":%d:", len);
6312 while (x-- > 0) { fputc(*s++, f); }
6313}
6314
6315extern void
6316onig_print_compiled_byte_code(FILE* f, UChar* bp, UChar* bpend, UChar** nextp,
6317 OnigEncoding enc)
6318{
6319 int i, n, arg_type;
6320 RelAddrType addr;
6321 LengthType len;
6322 MemNumType mem;
6323 StateCheckNumType scn;
6324 OnigCodePoint code;
6325 UChar *q;
6326
6327 fprintf(f, "[%s", op2name(*bp));
6328 arg_type = op2arg_type(*bp);
6329 if (arg_type != ARG_SPECIAL) {
6330 bp++;
6331 switch (arg_type) {
6332 case ARG_NON:
6333 break;
6334 case ARG_RELADDR:
6335 GET_RELADDR_INC(addr, bp);
6336 fprintf(f, ":(%s%d)", (addr >= 0) ? "+" : "", addr);
6337 break;
6338 case ARG_ABSADDR:
6339 GET_ABSADDR_INC(addr, bp);
6340 fprintf(f, ":(%d)", addr);
6341 break;
6342 case ARG_LENGTH:
6343 GET_LENGTH_INC(len, bp);
6344 fprintf(f, ":%d", len);
6345 break;
6346 case ARG_MEMNUM:
6347 mem = *((MemNumType* )bp);
6348 bp += SIZE_MEMNUM;
6349 fprintf(f, ":%d", mem);
6350 break;
6351 case ARG_OPTION:
6352 {
6353 OnigOptionType option = *((OnigOptionType* )bp);
6354 bp += SIZE_OPTION;
6355 fprintf(f, ":%d", option);
6356 }
6357 break;
6358
6359 case ARG_STATE_CHECK:
6360 scn = *((StateCheckNumType* )bp);
6361 bp += SIZE_STATE_CHECK_NUM;
6362 fprintf(f, ":%d", scn);
6363 break;
6364 }
6365 }
6366 else {
6367 switch (*bp++) {
6368 case OP_EXACT1:
6369 case OP_ANYCHAR_STAR_PEEK_NEXT:
6370 case OP_ANYCHAR_ML_STAR_PEEK_NEXT:
6371 p_string(f, 1, bp++); break;
6372 case OP_EXACT2:
6373 p_string(f, 2, bp); bp += 2; break;
6374 case OP_EXACT3:
6375 p_string(f, 3, bp); bp += 3; break;
6376 case OP_EXACT4:
6377 p_string(f, 4, bp); bp += 4; break;
6378 case OP_EXACT5:
6379 p_string(f, 5, bp); bp += 5; break;
6380 case OP_EXACTN:
6381 GET_LENGTH_INC(len, bp);
6382 p_len_string(f, len, 1, bp);
6383 bp += len;
6384 break;
6385
6386 case OP_EXACTMB2N1:
6387 p_string(f, 2, bp); bp += 2; break;
6388 case OP_EXACTMB2N2:
6389 p_string(f, 4, bp); bp += 4; break;
6390 case OP_EXACTMB2N3:
6391 p_string(f, 6, bp); bp += 6; break;
6392 case OP_EXACTMB2N:
6393 GET_LENGTH_INC(len, bp);
6394 p_len_string(f, len, 2, bp);
6395 bp += len * 2;
6396 break;
6397 case OP_EXACTMB3N:
6398 GET_LENGTH_INC(len, bp);
6399 p_len_string(f, len, 3, bp);
6400 bp += len * 3;
6401 break;
6402 case OP_EXACTMBN:
6403 {
6404 int mb_len;
6405
6406 GET_LENGTH_INC(mb_len, bp);
6407 GET_LENGTH_INC(len, bp);
6408 fprintf(f, ":%d:%d:", mb_len, len);
6409 n = len * mb_len;
6410 while (n-- > 0) { fputc(*bp++, f); }
6411 }
6412 break;
6413
6414 case OP_EXACT1_IC:
6415 len = enclen(enc, bp, bpend);
6416 p_string(f, len, bp);
6417 bp += len;
6418 break;
6419 case OP_EXACTN_IC:
6420 GET_LENGTH_INC(len, bp);
6421 p_len_string(f, len, 1, bp);
6422 bp += len;
6423 break;
6424
6425 case OP_CCLASS:
6426 n = bitset_on_num((BitSetRef )bp);
6427 bp += SIZE_BITSET;
6428 fprintf(f, ":%d", n);
6429 break;
6430
6431 case OP_CCLASS_NOT:
6432 n = bitset_on_num((BitSetRef )bp);
6433 bp += SIZE_BITSET;
6434 fprintf(f, ":%d", n);
6435 break;
6436
6437 case OP_CCLASS_MB:
6438 case OP_CCLASS_MB_NOT:
6439 GET_LENGTH_INC(len, bp);
6440 q = bp;
6441# ifndef PLATFORM_UNALIGNED_WORD_ACCESS
6442 ALIGNMENT_RIGHT(q);
6443# endif
6444 GET_CODE_POINT(code, q);
6445 bp += len;
6446 fprintf(f, ":%d:%d", (int )code, len);
6447 break;
6448
6449 case OP_CCLASS_MIX:
6450 case OP_CCLASS_MIX_NOT:
6451 n = bitset_on_num((BitSetRef )bp);
6452 bp += SIZE_BITSET;
6453 GET_LENGTH_INC(len, bp);
6454 q = bp;
6455# ifndef PLATFORM_UNALIGNED_WORD_ACCESS
6456 ALIGNMENT_RIGHT(q);
6457# endif
6458 GET_CODE_POINT(code, q);
6459 bp += len;
6460 fprintf(f, ":%d:%d:%d", n, (int )code, len);
6461 break;
6462
6463 case OP_BACKREFN_IC:
6464 mem = *((MemNumType* )bp);
6465 bp += SIZE_MEMNUM;
6466 fprintf(f, ":%d", mem);
6467 break;
6468
6469 case OP_BACKREF_MULTI_IC:
6470 case OP_BACKREF_MULTI:
6471 fputs(" ", f);
6472 GET_LENGTH_INC(len, bp);
6473 for (i = 0; i < len; i++) {
6474 GET_MEMNUM_INC(mem, bp);
6475 if (i > 0) fputs(", ", f);
6476 fprintf(f, "%d", mem);
6477 }
6478 break;
6479
6480 case OP_BACKREF_WITH_LEVEL:
6481 {
6482 OnigOptionType option;
6483 LengthType level;
6484
6485 GET_OPTION_INC(option, bp);
6486 fprintf(f, ":%d", option);
6487 GET_LENGTH_INC(level, bp);
6488 fprintf(f, ":%d", level);
6489
6490 fputs(" ", f);
6491 GET_LENGTH_INC(len, bp);
6492 for (i = 0; i < len; i++) {
6493 GET_MEMNUM_INC(mem, bp);
6494 if (i > 0) fputs(", ", f);
6495 fprintf(f, "%d", mem);
6496 }
6497 }
6498 break;
6499
6500 case OP_REPEAT:
6501 case OP_REPEAT_NG:
6502 {
6503 mem = *((MemNumType* )bp);
6504 bp += SIZE_MEMNUM;
6505 addr = *((RelAddrType* )bp);
6506 bp += SIZE_RELADDR;
6507 fprintf(f, ":%d:%d", mem, addr);
6508 }
6509 break;
6510
6511 case OP_PUSH_OR_JUMP_EXACT1:
6512 case OP_PUSH_IF_PEEK_NEXT:
6513 addr = *((RelAddrType* )bp);
6514 bp += SIZE_RELADDR;
6515 fprintf(f, ":(%s%d)", (addr >= 0) ? "+" : "", addr);
6516 p_string(f, 1, bp);
6517 bp += 1;
6518 break;
6519
6520 case OP_LOOK_BEHIND:
6521 GET_LENGTH_INC(len, bp);
6522 fprintf(f, ":%d", len);
6523 break;
6524
6525 case OP_PUSH_LOOK_BEHIND_NOT:
6526 GET_RELADDR_INC(addr, bp);
6527 GET_LENGTH_INC(len, bp);
6528 fprintf(f, ":%d:(%s%d)", len, (addr >= 0) ? "+" : "", addr);
6529 break;
6530
6531 case OP_STATE_CHECK_PUSH:
6532 case OP_STATE_CHECK_PUSH_OR_JUMP:
6533 scn = *((StateCheckNumType* )bp);
6534 bp += SIZE_STATE_CHECK_NUM;
6535 addr = *((RelAddrType* )bp);
6536 bp += SIZE_RELADDR;
6537 fprintf(f, ":%d:(%s%d)", scn, (addr >= 0) ? "+" : "", addr);
6538 break;
6539
6540 case OP_CONDITION:
6541 GET_MEMNUM_INC(mem, bp);
6542 GET_RELADDR_INC(addr, bp);
6543 fprintf(f, ":%d:(%s%d)", mem, (addr >= 0) ? "+" : "", addr);
6544 break;
6545
6546 default:
6547 fprintf(stderr, "onig_print_compiled_byte_code: undefined code %d\n",
6548 bp[-1]);
6549 }
6550 }
6551 fputs("]", f);
6552 if (nextp) *nextp = bp;
6553}
6554
6555# ifdef ONIG_DEBUG_COMPILE
6556static void
6557print_compiled_byte_code_list(FILE* f, regex_t* reg)
6558{
6559 int ncode;
6560 UChar* bp = reg->p;
6561 UChar* end = reg->p + reg->used;
6562
6563 fprintf(f, "code length: %d", reg->used);
6564
6565 ncode = -1;
6566 while (bp < end) {
6567 ncode++;
6568 if (ncode % 5 == 0)
6569 fprintf(f, "\n%ld:", bp - reg->p);
6570 else
6571 fprintf(f, " %ld:", bp - reg->p);
6572 onig_print_compiled_byte_code(f, bp, end, &bp, reg->enc);
6573 }
6574
6575 fprintf(f, "\n");
6576}
6577# endif /* ONIG_DEBUG_COMPILE */
6578
6579# ifdef ONIG_DEBUG_PARSE_TREE
6580static void
6581print_indent_tree(FILE* f, Node* node, int indent)
6582{
6583 int i, type, container_p = 0;
6584 int add = 3;
6585 UChar* p;
6586
6587 Indent(f, indent);
6588 if (IS_NULL(node)) {
6589 fprintf(f, "ERROR: null node!!!\n");
6590 exit (0);
6591 }
6592
6593 type = NTYPE(node);
6594 switch (type) {
6595 case NT_LIST:
6596 case NT_ALT:
6597 if (NTYPE(node) == NT_LIST)
6598 fprintf(f, "<list:%"PRIxPTR">\n", (intptr_t )node);
6599 else
6600 fprintf(f, "<alt:%"PRIxPTR">\n", (intptr_t )node);
6601
6602 print_indent_tree(f, NCAR(node), indent + add);
6603 while (IS_NOT_NULL(node = NCDR(node))) {
6604 if (NTYPE(node) != type) {
6605 fprintf(f, "ERROR: list/alt right is not a cons. %d\n", NTYPE(node));
6606 exit(0);
6607 }
6608 print_indent_tree(f, NCAR(node), indent + add);
6609 }
6610 break;
6611
6612 case NT_STR:
6613 fprintf(f, "<string%s:%"PRIxPTR">",
6614 (NSTRING_IS_RAW(node) ? "-raw" : ""), (intptr_t )node);
6615 for (p = NSTR(node)->s; p < NSTR(node)->end; p++) {
6616 if (*p >= 0x20 && *p < 0x7f)
6617 fputc(*p, f);
6618 else {
6619 fprintf(f, " 0x%02x", *p);
6620 }
6621 }
6622 break;
6623
6624 case NT_CCLASS:
6625 fprintf(f, "<cclass:%"PRIxPTR">", (intptr_t )node);
6626 if (IS_NCCLASS_NOT(NCCLASS(node))) fputs("not ", f);
6627 if (NCCLASS(node)->mbuf) {
6628 BBuf* bbuf = NCCLASS(node)->mbuf;
6629 OnigCodePoint* data = (OnigCodePoint* )bbuf->p;
6630 OnigCodePoint* end = (OnigCodePoint* )(bbuf->p + bbuf->used);
6631 fprintf(f, "%d", *data++);
6632 for (; data < end; data+=2) {
6633 fprintf(f, ",");
6634 fprintf(f, "%04x-%04x", data[0], data[1]);
6635 }
6636 }
6637 break;
6638
6639 case NT_CTYPE:
6640 fprintf(f, "<ctype:%"PRIxPTR"> ", (intptr_t )node);
6641 switch (NCTYPE(node)->ctype) {
6642 case ONIGENC_CTYPE_WORD:
6643 if (NCTYPE(node)->not != 0)
6644 fputs("not word", f);
6645 else
6646 fputs("word", f);
6647 break;
6648
6649 default:
6650 fprintf(f, "ERROR: undefined ctype.\n");
6651 exit(0);
6652 }
6653 break;
6654
6655 case NT_CANY:
6656 fprintf(f, "<anychar:%"PRIxPTR">", (intptr_t )node);
6657 break;
6658
6659 case NT_ANCHOR:
6660 fprintf(f, "<anchor:%"PRIxPTR"> ", (intptr_t )node);
6661 switch (NANCHOR(node)->type) {
6662 case ANCHOR_BEGIN_BUF: fputs("begin buf", f); break;
6663 case ANCHOR_END_BUF: fputs("end buf", f); break;
6664 case ANCHOR_BEGIN_LINE: fputs("begin line", f); break;
6665 case ANCHOR_END_LINE: fputs("end line", f); break;
6666 case ANCHOR_SEMI_END_BUF: fputs("semi end buf", f); break;
6667 case ANCHOR_BEGIN_POSITION: fputs("begin position", f); break;
6668
6669 case ANCHOR_WORD_BOUND: fputs("word bound", f); break;
6670 case ANCHOR_NOT_WORD_BOUND: fputs("not word bound", f); break;
6671# ifdef USE_WORD_BEGIN_END
6672 case ANCHOR_WORD_BEGIN: fputs("word begin", f); break;
6673 case ANCHOR_WORD_END: fputs("word end", f); break;
6674# endif
6675 case ANCHOR_PREC_READ: fputs("prec read", f); container_p = TRUE; break;
6676 case ANCHOR_PREC_READ_NOT: fputs("prec read not", f); container_p = TRUE; break;
6677 case ANCHOR_LOOK_BEHIND: fputs("look_behind", f); container_p = TRUE; break;
6678 case ANCHOR_LOOK_BEHIND_NOT: fputs("look_behind_not",f); container_p = TRUE; break;
6679 case ANCHOR_KEEP: fputs("keep",f); break;
6680
6681 default:
6682 fprintf(f, "ERROR: undefined anchor type.\n");
6683 break;
6684 }
6685 break;
6686
6687 case NT_BREF:
6688 {
6689 int* p;
6690 BRefNode* br = NBREF(node);
6691 p = BACKREFS_P(br);
6692 fprintf(f, "<backref:%"PRIxPTR">", (intptr_t )node);
6693 for (i = 0; i < br->back_num; i++) {
6694 if (i > 0) fputs(", ", f);
6695 fprintf(f, "%d", p[i]);
6696 }
6697 }
6698 break;
6699
6700# ifdef USE_SUBEXP_CALL
6701 case NT_CALL:
6702 {
6703 CallNode* cn = NCALL(node);
6704 fprintf(f, "<call:%"PRIxPTR">", (intptr_t )node);
6705 p_string(f, cn->name_end - cn->name, cn->name);
6706 }
6707 break;
6708# endif
6709
6710 case NT_QTFR:
6711 fprintf(f, "<quantifier:%"PRIxPTR">{%d,%d}%s\n", (intptr_t )node,
6712 NQTFR(node)->lower, NQTFR(node)->upper,
6713 (NQTFR(node)->greedy ? "" : "?"));
6714 print_indent_tree(f, NQTFR(node)->target, indent + add);
6715 break;
6716
6717 case NT_ENCLOSE:
6718 fprintf(f, "<enclose:%"PRIxPTR"> ", (intptr_t )node);
6719 switch (NENCLOSE(node)->type) {
6720 case ENCLOSE_OPTION:
6721 fprintf(f, "option:%d", NENCLOSE(node)->option);
6722 break;
6723 case ENCLOSE_MEMORY:
6724 fprintf(f, "memory:%d", NENCLOSE(node)->regnum);
6725 break;
6726 case ENCLOSE_STOP_BACKTRACK:
6727 fprintf(f, "stop-bt");
6728 break;
6729 case ENCLOSE_CONDITION:
6730 fprintf(f, "condition:%d", NENCLOSE(node)->regnum);
6731 break;
6732 case ENCLOSE_ABSENT:
6733 fprintf(f, "absent");
6734 break;
6735
6736 default:
6737 break;
6738 }
6739 fprintf(f, "\n");
6740 print_indent_tree(f, NENCLOSE(node)->target, indent + add);
6741 break;
6742
6743 default:
6744 fprintf(f, "print_indent_tree: undefined node type %d\n", NTYPE(node));
6745 break;
6746 }
6747
6748 if (type != NT_LIST && type != NT_ALT && type != NT_QTFR &&
6749 type != NT_ENCLOSE)
6750 fprintf(f, "\n");
6751
6752 if (container_p) print_indent_tree(f, NANCHOR(node)->target, indent + add);
6753
6754 fflush(f);
6755}
6756
6757static void
6758print_tree(FILE* f, Node* node)
6759{
6760 print_indent_tree(f, node, 0);
6761}
6762# endif /* ONIG_DEBUG_PARSE_TREE */
6763#endif /* ONIG_DEBUG */
#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
int len
Length of the buffer.
Definition io.h:8
VALUE type(ANYARGS)
ANYARGS-ed function type.