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