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