File Coverage

engine.c
Criterion Covered Total %
statement 2029 2316 87.6
branch 610 894 68.2
condition n/a
subroutine n/a
pod n/a
total 2639 3210 82.2


line stmt bran cond sub pod time code
1             #include "engine.h"
2             #include "regnodes.h"
3             #include "regcomp.h"
4             #include
5             #include
6             #include
7              
8             #if PERL_API_REVISION != 5
9             #error This module is only for Perl 5
10             #else
11             #if PERL_API_VERSION == 24
12             /* nothing special */
13             #else
14             #if PERL_API_VERSION == 26
15             /* nothing special */
16             #else
17             #if PERL_API_VERSION == 28
18             #define RC_ANYOFM
19             #else
20             #error Unsupported PERL_API_VERSION
21             #endif
22             #endif
23             #endif
24             #endif
25              
26             #define SIZEOF_ARRAY(a) (sizeof(a) / sizeof(a[0]))
27              
28             #define TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
29              
30             #define LETTER_COUNT ('z' - 'a' + 1)
31              
32             #define INFINITE_COUNT 32767
33              
34             #define ALNUM_BLOCK 0x0001
35             #define SPACE_BLOCK 0x0002
36             #define ALPHA_BLOCK 0x0004
37             #define NUMBER_BLOCK 0x0008
38             #define UPPER_BLOCK 0x0010
39             #define LOWER_BLOCK 0x0020
40             #define HEX_DIGIT_BLOCK 0x0040
41             #define HORIZONTAL_SPACE_BLOCK 0x0080
42             #define VERTICAL_SPACE_BLOCK 0x0100
43              
44             #define MIRROR_SHIFT 16
45             #define NOT_ALNUM_BLOCK (ALNUM_BLOCK << MIRROR_SHIFT)
46             #define NOT_SPACE_BLOCK (SPACE_BLOCK << MIRROR_SHIFT)
47             #define NOT_ALPHA_BLOCK (ALPHA_BLOCK << MIRROR_SHIFT)
48             #define NOT_NUMBER_BLOCK (NUMBER_BLOCK << MIRROR_SHIFT)
49             #define NOT_UPPER_BLOCK (UPPER_BLOCK << MIRROR_SHIFT)
50             #define NOT_LOWER_BLOCK (LOWER_BLOCK << MIRROR_SHIFT)
51             #define NOT_HEX_DIGIT_BLOCK (HEX_DIGIT_BLOCK << MIRROR_SHIFT)
52             #define NOT_HORIZONTAL_SPACE_BLOCK (HORIZONTAL_SPACE_BLOCK << MIRROR_SHIFT)
53             #define NOT_VERTICAL_SPACE_BLOCK (VERTICAL_SPACE_BLOCK << MIRROR_SHIFT)
54              
55             #define EVERY_BLOCK 0x01ff01ff
56              
57             #define FORCED_BYTE 0x01
58             #define FORCED_CHAR 0x02
59             #define FORCED_MISMATCH (FORCED_BYTE | FORCED_CHAR)
60              
61             #define MIRROR_BLOCK(b) ((((b) & 0xffff) << MIRROR_SHIFT) | ((b) >> MIRROR_SHIFT))
62              
63             /* Regexp terms are normally regnodes, except for EXACT (and EXACTF)
64             nodes, which can bundle many characters, which we have to compare
65             separately. Occasionally, we also need access to extra regexp
66             data. */
67             typedef struct
68             {
69             regexp *origin;
70             regnode *rn;
71             int spent;
72             } Arrow;
73              
74             #define GET_LITERAL(a) (((char *)((a)->rn + 1)) + (a)->spent)
75             #define GET_OFFSET(rn) ((rn)->next_off ? (rn)->next_off : get_synth_offset(rn))
76              
77             /* Most functions below have this signature. The first parameter is a
78             flag set after the comparison actually matched something, second
79             parameter points into the first ("left") regexp passed into
80             rc_compare, the third into the second ("right") regexp. Return
81             value is 1 for match, 0 no match, -1 error (with the lowest-level
82             failing function setting rc_error before returning it). */
83             typedef int (*FCompare)(int, Arrow *, Arrow *);
84              
85             /* Place of a char in regexp bitmap. */
86             typedef struct
87             {
88             int offs;
89             unsigned char mask;
90             } BitFlag;
91              
92             /* Set of chars and its complement formatted for convenient
93             matching. */
94             typedef struct
95             {
96             char *expl;
97             int expl_size;
98             char lookup[256];
99             char nlookup[256];
100             unsigned char bitmap[ANYOF_BITMAP_SIZE];
101             unsigned char nbitmap[ANYOF_BITMAP_SIZE];
102             } ByteClass;
103              
104             char *rc_error = 0;
105              
106             unsigned char forced_byte[ANYOF_BITMAP_SIZE];
107              
108             /* matching \s i.e. not including \v - see perlre */
109             static char whitespace_expl[] = { ' ', '\f', '\n', '\r', '\t' };
110              
111             static ByteClass whitespace;
112              
113             static char horizontal_whitespace_expl[] = { '\t', ' ' };
114              
115             static ByteClass horizontal_whitespace;
116              
117             static char vertical_whitespace_expl[] = { '\r', '\v', '\f', '\n' };
118              
119             static ByteClass vertical_whitespace;
120              
121             static char digit_expl[10];
122              
123             static ByteClass digit;
124              
125             static char xdigit_expl[10 + 2 * 6];
126              
127             static ByteClass xdigit;
128              
129             static char ndot_expl[] = { '\n' };
130              
131             static ByteClass ndot;
132              
133             static char alphanumeric_expl[11 + 2 * LETTER_COUNT];
134              
135             static ByteClass word_bc;
136              
137             static ByteClass alnum_bc;
138              
139             static char alpha_expl[2 * LETTER_COUNT];
140              
141             static ByteClass alpha_bc;
142              
143             static char lower_expl[LETTER_COUNT];
144              
145             static ByteClass lower_bc;
146              
147             static char upper_expl[LETTER_COUNT];
148              
149             static ByteClass upper_bc;
150              
151             /* true flags for ALNUM and its subsets, 0 otherwise */
152             static unsigned char alphanumeric_classes[REGNODE_MAX];
153              
154             /* true flags for NALNUM and its subsets, 0 otherwise */
155             static unsigned char non_alphanumeric_classes[REGNODE_MAX];
156              
157             static unsigned char word_posix_regclasses[_CC_VERTSPACE + 1];
158              
159             static unsigned char non_word_posix_regclasses[_CC_VERTSPACE + 1];
160              
161             static unsigned char newline_posix_regclasses[_CC_VERTSPACE + 1];
162              
163             /* Simplified hierarchy of character classes; ignoring the difference
164             between classes (i.e. IsAlnum & IsWord), which we probably
165             shouldn't - it is a documented bug, though... */
166             static char *regclass_names[] = { "Digit", "IsAlnum", "IsSpacePerl",
167             "IsHorizSpace", "IsVertSpace",
168             "IsWord", "IsXPosixAlnum", "IsXPosixXDigit",
169             "IsAlpha", "IsXPosixAlpha",
170             "IsDigit", "IsLower", "IsUpper",
171             "IsXDigit", "SpacePerl", "VertSpace",
172             "Word", "XPosixDigit",
173             "XPosixWord", "XPosixAlpha", "XPosixAlnum",
174             "XPosixXDigit" };
175              
176             static U32 regclass_blocks[] = { NUMBER_BLOCK, ALNUM_BLOCK, SPACE_BLOCK,
177             HORIZONTAL_SPACE_BLOCK,
178             VERTICAL_SPACE_BLOCK, ALNUM_BLOCK,
179             ALNUM_BLOCK, HEX_DIGIT_BLOCK, ALPHA_BLOCK,
180             ALPHA_BLOCK, NUMBER_BLOCK, LOWER_BLOCK,
181             UPPER_BLOCK, HEX_DIGIT_BLOCK, SPACE_BLOCK,
182             VERTICAL_SPACE_BLOCK, ALNUM_BLOCK,
183             NUMBER_BLOCK, ALNUM_BLOCK, ALPHA_BLOCK,
184             ALNUM_BLOCK, HEX_DIGIT_BLOCK};
185              
186             static U32 regclass_superset[] = { NOT_SPACE_BLOCK,
187             NOT_ALPHA_BLOCK, NOT_NUMBER_BLOCK,
188             ALNUM_BLOCK, ALNUM_BLOCK,
189             ALPHA_BLOCK, ALPHA_BLOCK, HEX_DIGIT_BLOCK,
190             SPACE_BLOCK, NOT_NUMBER_BLOCK,
191             NOT_HEX_DIGIT_BLOCK };
192             static U32 regclass_subset[] = { ALNUM_BLOCK,
193             NOT_ALNUM_BLOCK, NOT_ALNUM_BLOCK,
194             ALPHA_BLOCK, NUMBER_BLOCK,
195             UPPER_BLOCK, LOWER_BLOCK, NUMBER_BLOCK,
196             HORIZONTAL_SPACE_BLOCK,
197             VERTICAL_SPACE_BLOCK, VERTICAL_SPACE_BLOCK };
198              
199             static U32 posix_regclass_blocks[_CC_VERTSPACE + 1] = {
200             ALNUM_BLOCK /* _CC_WORDCHAR == 0 */,
201             NUMBER_BLOCK /* _CC_DIGIT == 1 */,
202             ALPHA_BLOCK /* _CC_ALPHA == 2 */,
203             LOWER_BLOCK /* _CC_LOWER == 3 */,
204             UPPER_BLOCK /* _CC_UPPER == 4 */,
205             0,
206             0,
207             ALNUM_BLOCK /* _CC_ALPHANUMERIC == 7 */,
208             0,
209             0,
210             SPACE_BLOCK /* _CC_SPACE == 10 */,
211             HORIZONTAL_SPACE_BLOCK /* _CC_BLANK == 11, and according to perlrecharclass "\p{Blank}" and "\p{HorizSpace}" are synonyms. */,
212             HEX_DIGIT_BLOCK /* _CC_XDIGIT == 12 */
213             }; /* _CC_VERTSPACE set in rc_init because it has different values between perl 5.20 and 5.22 */
214              
215             static unsigned char *posix_regclass_bitmaps[_CC_VERTSPACE + 1] = {
216             word_bc.bitmap,
217             digit.bitmap,
218             alpha_bc.bitmap,
219             lower_bc.bitmap,
220             upper_bc.bitmap,
221             0,
222             0,
223             alnum_bc.bitmap,
224             0,
225             0,
226             whitespace.bitmap,
227             horizontal_whitespace.bitmap,
228             xdigit.bitmap
229             };
230              
231             static unsigned char *posix_regclass_nbitmaps[_CC_VERTSPACE + 1] = {
232             word_bc.nbitmap,
233             digit.nbitmap,
234             0,
235             0,
236             0,
237             0,
238             0,
239             alnum_bc.nbitmap,
240             0,
241             0,
242             whitespace.nbitmap,
243             horizontal_whitespace.nbitmap,
244             xdigit.nbitmap
245             };
246              
247             static unsigned char trivial_nodes[REGNODE_MAX];
248              
249             static FCompare dispatch[REGNODE_MAX][REGNODE_MAX];
250              
251             static int compare(int anchored, Arrow *a1, Arrow *a2);
252             static int compare_right_branch(int anchored, Arrow *a1, Arrow *a2);
253             static int compare_right_curly(int anchored, Arrow *a1, Arrow *a2);
254              
255 11626           static void init_bit_flag(BitFlag *bf, int c)
256             {
257             assert(c >= 0);
258              
259 11626           bf->offs = c / 8;
260 11626           bf->mask = 1 << (c % 8);
261 11626           }
262              
263 1           static void init_forced_byte()
264             {
265 1           char forced_byte_expl[] = { 'a', 'b', 'c', 'e', 'f', 'x' };
266             BitFlag bf;
267             int i;
268              
269 1           memset(forced_byte, 0, sizeof(forced_byte));
270              
271 7 100         for (i = 0; i < sizeof(forced_byte_expl); ++i)
272             {
273 6           init_bit_flag(&bf, (unsigned char)forced_byte_expl[i]);
274 6           forced_byte[bf.offs] |= bf.mask;
275             }
276              
277 9 100         for (i = 0; i < 8; ++i)
278             {
279 8           init_bit_flag(&bf, (unsigned char)('0' + i));
280 8           forced_byte[bf.offs] |= bf.mask;
281             }
282 1           }
283              
284 11           static void init_byte_class(ByteClass *bc, char *expl, int expl_size)
285             {
286             BitFlag bf;
287             int i;
288              
289 11           bc->expl = expl;
290 11           bc->expl_size = expl_size;
291              
292 11           memset(bc->lookup, 0, sizeof(bc->lookup));
293 11           memset(bc->nlookup, 1, sizeof(bc->nlookup));
294 11           memset(bc->bitmap, 0, sizeof(bc->bitmap));
295 11           memset(bc->nbitmap, 0xff, sizeof(bc->nbitmap));
296              
297 284 100         for (i = 0; i < expl_size; ++i)
298             {
299 273           bc->lookup[(unsigned char)expl[i]] = 1;
300 273           bc->nlookup[(unsigned char)expl[i]] = 0;
301              
302 273           init_bit_flag(&bf, (unsigned char)expl[i]);
303 273           bc->bitmap[bf.offs] |= bf.mask;
304 273           bc->nbitmap[bf.offs] &= ~bf.mask;
305             }
306 11           }
307              
308 261           static void init_unfolded(char *unf, char c)
309             {
310 261 100         *unf = TOLOWER(c);
    100          
311 261 100         unf[1] = ((*unf >= 'a') && (*unf <= 'z')) ? *unf - 'a' + 'A' : *unf;
    50          
312 261           }
313              
314 4946           static U32 extend_mask(U32 mask)
315             {
316             U32 prev_mask;
317             int i, j;
318              
319             /* extra cycle is inefficient but makes superset & subset
320             definitions order-independent */
321 4946           prev_mask = 0;
322 13219 100         while (mask != prev_mask)
323             {
324 8273           prev_mask = mask;
325 24819 100         for (i = 0; i < 2; ++i)
326             {
327 198552 100         for (j = 0; j < SIZEOF_ARRAY(regclass_superset); ++j)
328             {
329 182006           U32 b = regclass_superset[j];
330 182006           U32 s = regclass_subset[j];
331 182006 100         if (i)
332             {
333             U32 t;
334              
335 91003           t = MIRROR_BLOCK(b);
336 91003           b = MIRROR_BLOCK(s);
337 91003           s = t;
338             }
339              
340 182006 100         if (mask & b)
341             {
342 21752           mask |= s;
343             }
344             }
345             }
346             }
347              
348 4946           return mask;
349             }
350              
351 0           static int convert_desc_to_map(char *desc, int invert, U32 *map)
352             {
353             int i;
354 0           U32 mask = 0;
355             char *p;
356              
357             /* fprintf(stderr, "enter convert_desc_to_map(%s, %d\n", desc, invert); */
358              
359 0           p = strstr(desc, "utf8::");
360             /* make sure *(p - 1) is valid */
361 0 0         if (p == desc)
362             {
363 0           rc_error = "no inversion flag before character class description";
364 0           return -1;
365             }
366              
367 0 0         while (p)
368             {
369 0           char sign = *(p - 1);
370 0 0         for (i = 0; i < SIZEOF_ARRAY(regclass_names); ++i)
371             {
372 0 0         if (!strncmp(p + 6, regclass_names[i], strlen(regclass_names[i])))
373             {
374 0 0         if (sign == '+')
375             {
376 0 0         if (mask & (regclass_blocks[i] << MIRROR_SHIFT))
377             {
378 0 0         *map = invert ? 0 : EVERY_BLOCK;
379 0           return 1;
380             }
381              
382 0           mask |= regclass_blocks[i];
383             }
384 0 0         else if (sign == '!')
385             {
386 0 0         if (mask & regclass_blocks[i])
387             {
388 0 0         *map = invert ? 0 : EVERY_BLOCK;
389 0           return 1;
390             }
391              
392 0           mask |= (regclass_blocks[i] << MIRROR_SHIFT);
393             }
394             else
395             {
396 0           rc_error = "unknown inversion flag before character class description";
397 0           return -1;
398             }
399             }
400             }
401              
402 0           p = strstr(p + 6, "utf8::");
403             }
404              
405             /* fprintf(stderr, "parsed 0x%x\n", (unsigned)mask); */
406              
407 0 0         if ((mask & ALPHA_BLOCK) && (mask & NUMBER_BLOCK))
    0          
408             {
409 0           mask |= ALNUM_BLOCK;
410             }
411              
412 0 0         if (invert)
413             {
414 0           mask = MIRROR_BLOCK(mask);
415             }
416              
417 0 0         if ((mask & ALPHA_BLOCK) && (mask & NUMBER_BLOCK))
    0          
418             {
419 0           mask |= ALNUM_BLOCK;
420             }
421              
422 0           *map = extend_mask(mask);
423 0           return 1;
424             }
425              
426             /* invlist methods are static inside regcomp.c, so we must copy them... */
427 408           static bool *get_invlist_offset_addr(SV *invlist)
428             {
429 408           return &(((XINVLIST*) SvANY(invlist))->is_offset);
430             }
431              
432 204           static UV get_invlist_len(SV *invlist)
433             {
434 204           return (SvCUR(invlist) == 0)
435             ? 0
436 204 50         : (SvCUR(invlist) / sizeof(UV)) - *get_invlist_offset_addr(invlist);
437             }
438              
439 204           static UV *invlist_array(SV *invlist)
440             {
441 204           return ((UV *) SvPVX(invlist) + *get_invlist_offset_addr(invlist));
442             }
443              
444             /* #define DEBUG_dump_invlist */
445              
446 30           static int convert_invlist_to_map(SV *invlist, int invert, U32 *map)
447             {
448             /*
449             Not quite what's in charclass_invlists.h - we skip the header
450             as well as all ASCII values.
451             Note that changes to the arrays may require changing the switch
452             below.
453             */
454             static UV perl_space_invlist[] = { 128, 133, 134, 160, 161, 5760,
455             5761, 6158, 6159, 8192, 8203, 8232, 8234, 8239, 8240, 8287,
456             8288, 12288, 12289 };
457              
458             static UV horizontal_space_invlist[] = { 128, 160, 161, 5760, 5761,
459             6158, 6159, 8192, 8203, 8239, 8240, 8287, 8288, 12288, 12289 };
460              
461             static UV vertical_space_invlist[] = { 128, 133, 134, 8232, 8234 };
462              
463             static UV xposix_digit_invlist[] = { 128,
464             #include "XPosixDigit.22"
465             };
466              
467             static UV xposix_alnum_invlist[] = { 128,
468             #if PERL_API_VERSION == 24
469             #include "XPosixAlnum.24"
470             #else
471             #if PERL_API_VERSION == 26
472             #include "XPosixAlnum.26"
473             #else
474             #if PERL_API_VERSION == 28
475             #include "XPosixAlnum.28"
476             #else
477             #error unexpected PERL_API_VERSION
478             #endif
479             #endif
480             #endif
481             };
482              
483             static UV xposix_alpha_invlist[] = { 128,
484             #if PERL_API_VERSION == 24
485             #include "XPosixAlpha.24"
486             #else
487             #if PERL_API_VERSION == 26
488             #include "XPosixAlpha.26"
489             #else
490             #if PERL_API_VERSION == 28
491             #include "XPosixAlpha.28"
492             #else
493             #error unexpected PERL_API_VERSION
494             #endif
495             #endif
496             #endif
497             };
498              
499             static UV xposix_word_invlist[] = { 128,
500             #include "XPosixWord.22"
501             };
502              
503             static UV xposix_xdigit_invlist[] = { 128, 65296, 65306, 65313,
504             65319, 65345, 65351 };
505              
506             #ifdef DEBUG_dump_invlist
507             U16 i;
508             char div[3];
509             #endif
510              
511             UV *ila;
512             UV ill;
513 30           U32 mask = 0;
514              
515             #ifdef DEBUG_dump_invlist
516             fprintf(stderr, "enter convert_invlist_to_map(..., %d, ...)\n", invert);
517             #endif
518              
519 30           ill = get_invlist_len(invlist);
520 30 50         ila = ill ? invlist_array(invlist) : 0;
521              
522 30           switch (ill)
523             {
524             case SIZEOF_ARRAY(perl_space_invlist):
525 0 0         if (!memcmp(ila, perl_space_invlist, sizeof(perl_space_invlist)))
526             {
527             #ifdef DEBUG_dump_invlist
528             fprintf(stderr, "NOT_SPACE_BLOCK\n");
529             #endif
530 0           mask = NOT_SPACE_BLOCK;
531             }
532              
533 0           break;
534              
535             case SIZEOF_ARRAY(perl_space_invlist) - 1:
536 0 0         if (!memcmp(ila, perl_space_invlist + 1,
537             sizeof(perl_space_invlist) - sizeof(perl_space_invlist[0])))
538             {
539             #ifdef DEBUG_dump_invlist
540             fprintf(stderr, "SPACE_BLOCK\n");
541             #endif
542 0           mask = SPACE_BLOCK;
543             }
544              
545 0           break;
546              
547             case SIZEOF_ARRAY(horizontal_space_invlist):
548 0 0         if (!memcmp(ila, horizontal_space_invlist, sizeof(horizontal_space_invlist)))
549             {
550             #ifdef DEBUG_dump_invlist
551             fprintf(stderr, "NOT_HORIZONTAL_SPACE_BLOCK\n");
552             #endif
553 0           mask = NOT_HORIZONTAL_SPACE_BLOCK;
554             }
555              
556 0           break;
557              
558             case SIZEOF_ARRAY(horizontal_space_invlist) - 1:
559 0 0         if (!memcmp(ila, horizontal_space_invlist + 1,
560             sizeof(horizontal_space_invlist) - sizeof(horizontal_space_invlist[0])))
561             {
562             #ifdef DEBUG_dump_invlist
563             fprintf(stderr, "HORIZONTAL_SPACE_BLOCK\n");
564             #endif
565 0           mask = HORIZONTAL_SPACE_BLOCK;
566             }
567              
568 0           break;
569              
570             case SIZEOF_ARRAY(vertical_space_invlist):
571 0 0         if (!memcmp(ila, vertical_space_invlist, sizeof(vertical_space_invlist)))
572             {
573             #ifdef DEBUG_dump_invlist
574             fprintf(stderr, "NOT_VERTICAL_SPACE_BLOCK\n");
575             #endif
576 0           mask = NOT_VERTICAL_SPACE_BLOCK;
577             }
578              
579 0           break;
580              
581             case SIZEOF_ARRAY(vertical_space_invlist) - 1:
582 0 0         if (!memcmp(ila, vertical_space_invlist + 1,
583             sizeof(vertical_space_invlist) - sizeof(vertical_space_invlist[0])))
584             {
585             #ifdef DEBUG_dump_invlist
586             fprintf(stderr, "VERTICAL_SPACE_BLOCK\n");
587             #endif
588 0           mask = VERTICAL_SPACE_BLOCK;
589             }
590              
591 0           break;
592              
593             case SIZEOF_ARRAY(xposix_digit_invlist):
594 0 0         if (!memcmp(ila, xposix_digit_invlist, sizeof(xposix_digit_invlist)))
595             {
596             #ifdef DEBUG_dump_invlist
597             fprintf(stderr, "NOT_NUMBER_BLOCK\n");
598             #endif
599 0           mask = NOT_NUMBER_BLOCK;
600             }
601              
602 0           break;
603              
604             case SIZEOF_ARRAY(xposix_digit_invlist) - 1:
605 0 0         if (!memcmp(ila, xposix_digit_invlist + 1,
606             sizeof(xposix_digit_invlist) - sizeof(xposix_digit_invlist[0])))
607             {
608             #ifdef DEBUG_dump_invlist
609             fprintf(stderr, "NUMBER_BLOCK\n");
610             #endif
611 0           mask = NUMBER_BLOCK;
612             }
613              
614 0           break;
615              
616             case SIZEOF_ARRAY(xposix_alnum_invlist):
617 0 0         if (!memcmp(ila, xposix_alnum_invlist, sizeof(xposix_alnum_invlist)))
618             {
619             #ifdef DEBUG_dump_invlist
620             fprintf(stderr, "NOT_ALNUM_BLOCK\n");
621             #endif
622 0           mask = NOT_ALNUM_BLOCK;
623             }
624              
625 0           break;
626              
627             case SIZEOF_ARRAY(xposix_alnum_invlist) - 1:
628 10 50         if (!memcmp(ila, xposix_alnum_invlist + 1,
629             sizeof(xposix_alnum_invlist) - sizeof(xposix_alnum_invlist[0])))
630             {
631             #ifdef DEBUG_dump_invlist
632             fprintf(stderr, "ALNUM_BLOCK\n");
633             #endif
634 10           mask = ALNUM_BLOCK;
635             }
636              
637 10           break;
638              
639             case SIZEOF_ARRAY(xposix_alpha_invlist):
640 0 0         if (!memcmp(ila, xposix_alpha_invlist, sizeof(xposix_alpha_invlist)))
641             {
642             #ifdef DEBUG_dump_invlist
643             fprintf(stderr, "NOT_ALPHA_BLOCK\n");
644             #endif
645 0           mask = NOT_ALPHA_BLOCK;
646             }
647              
648 0           break;
649              
650             case SIZEOF_ARRAY(xposix_alpha_invlist) - 1:
651 20 50         if (!memcmp(ila, xposix_alpha_invlist + 1,
652             sizeof(xposix_alpha_invlist) - sizeof(xposix_alpha_invlist[0])))
653             {
654             #ifdef DEBUG_dump_invlist
655             fprintf(stderr, "ALPHA_BLOCK\n");
656             #endif
657 20           mask = ALPHA_BLOCK;
658             }
659              
660 20           break;
661              
662             case SIZEOF_ARRAY(xposix_word_invlist):
663 0 0         if (!memcmp(ila, xposix_word_invlist, sizeof(xposix_word_invlist)))
664             {
665             #ifdef DEBUG_dump_invlist
666             fprintf(stderr, "NOT_ALPHA_BLOCK\n");
667             #endif
668 0           mask = NOT_ALPHA_BLOCK;
669             }
670              
671 0           break;
672              
673             case SIZEOF_ARRAY(xposix_word_invlist) - 1:
674 0 0         if (!memcmp(ila, xposix_word_invlist + 1,
675             sizeof(xposix_word_invlist) - sizeof(xposix_word_invlist[0])))
676             {
677             #ifdef DEBUG_dump_invlist
678             fprintf(stderr, "ALPHA_BLOCK\n");
679             #endif
680 0           mask = ALPHA_BLOCK;
681             }
682              
683 0           break;
684              
685             case SIZEOF_ARRAY(xposix_xdigit_invlist):
686 0 0         if (!memcmp(ila, xposix_xdigit_invlist, sizeof(xposix_xdigit_invlist)))
687             {
688             #ifdef DEBUG_dump_invlist
689             fprintf(stderr, "NOT_NUMBER_BLOCK\n");
690             #endif
691 0           mask = NOT_NUMBER_BLOCK;
692             }
693              
694 0           break;
695              
696             case SIZEOF_ARRAY(xposix_xdigit_invlist) - 1:
697 0 0         if (!memcmp(ila, xposix_xdigit_invlist + 1,
698             sizeof(xposix_xdigit_invlist) - sizeof(xposix_xdigit_invlist[0])))
699             {
700             #ifdef DEBUG_dump_invlist
701             fprintf(stderr, "NUMBER_BLOCK\n");
702             #endif
703 0           mask = NUMBER_BLOCK;
704             }
705              
706 0           break;
707             }
708              
709 30 50         if (mask)
710             {
711 30 50         if (invert)
712             {
713 0           mask = MIRROR_BLOCK(mask);
714             }
715              
716 30           *map = extend_mask(mask);
717 30           return 1;
718             }
719              
720             #ifdef DEBUG_dump_invlist
721             div[0] = 0;
722             div[2] = 0;
723             for (i = 0; i < ill; ++i)
724             {
725             fprintf(stderr, "%s%d", div, (int)(ila[i]));
726             div[0] = ',';
727             div[1] = '\n';
728             }
729              
730             fprintf(stderr, "\n");
731             #endif
732              
733 0           return 0;
734             }
735              
736 30           static int convert_regclass_map(Arrow *a, U32 *map)
737             {
738             regexp_internal *pr;
739             U32 n;
740             struct reg_data *rdata;
741              
742             /* fprintf(stderr, "enter convert_regclass_map\n"); */
743              
744             assert((a->rn->type == ANYOF) || (a->rn->type == ANYOFD));
745              
746             /* basically copied from regexec.c:regclass_swash */
747 30           n = ARG_LOC(a->rn);
748 30           pr = RXi_GET(a->origin);
749 30 50         if (!pr) /* this should have been tested by find_internal during
750             initialization, but just in case... */
751             {
752 0           rc_error = "regexp_internal not found";
753 0           return -1;
754             }
755              
756 30           rdata = pr->data;
757              
758 30 50         if ((n < rdata->count) &&
    50          
759 30           (rdata->what[n] == 's')) {
760 30           SV *rv = (SV *)(rdata->data[n]);
761 30           AV *av = (AV *)SvRV(rv);
762 30           SV **ary = AvARRAY(av);
763 30           SV *si = *ary;
764              
765 30 50         if (si && (si != &PL_sv_undef))
    50          
766             {
767             /* From regcomp.c:regclass: the 0th element stores the
768             character class description in its textual form. It isn't
769             very clear what exactly the textual form is, but we hope
770             it's 0-terminated. */
771 0 0         return convert_desc_to_map(SvPV_nolen(*ary),
772 0           !!(a->rn->flags & ANYOF_INVERT),
773             map);
774             }
775             /* FIXME: in perl 5.18, crashes for inverted classes */
776             else
777             {
778             /* in perl 5.16, the textual form doesn't necessarily exist... */
779 30 50         if (av_len(av) >= 3)
780             {
781 30           SV *invlist = ary[3];
782              
783 30 50         if (SvUV(ary[4])) /* invlist_has_user_defined_property */
    50          
784             {
785             /* fprintf(stderr, "invlist has user defined property\n"); */
786 0           return 0;
787             }
788              
789 30           return convert_invlist_to_map(invlist,
790 30           !!(a->rn->flags & ANYOF_INVERT),
791             map);
792             }
793              
794             /* fprintf(stderr, "regclass invlist not found\n"); */
795 0           return 0;
796             }
797             }
798              
799 0           rc_error = "regclass not found";
800 0           return -1;
801             }
802              
803             /* lifted from Perl__get_regclass_nonbitmap_data */
804 174           static SV *get_invlist_sv(Arrow *a)
805             {
806 174           RXi_GET_DECL(a->origin, progi);
807 174           struct reg_data *data = progi->data;
808              
809             assert((a->rn->type == ANYOF) || (a->rn->type == ANYOFD));
810              
811 174 50         if (data && data->count)
    50          
812             {
813 174           const U32 n = ARG(a->rn);
814              
815 174 50         if (data->what[n] == 's')
816             {
817 174           SV * const rv = MUTABLE_SV(data->data[n]);
818 174           AV * const av = MUTABLE_AV(SvRV(rv));
819 174           SV **const ary = AvARRAY(av);
820              
821 174 50         if (av_tindex(av) >= 3)
822             {
823 174           return ary[3];
824             }
825             }
826             }
827              
828 0           return 0;
829             }
830              
831             /* returns 1 OK (map set), 0 map not recognized/representable, -1
832             unexpected input (rc_error set) */
833 62           static int convert_map(Arrow *a, U32 *map)
834             {
835             /* fprintf(stderr, "enter convert_map\n"); */
836              
837             assert((a->rn->type == ANYOF) || (a->rn->type == ANYOFD));
838             assert(map);
839              
840 62 100         if (ANYOF_FLAGS(a->rn) & ANYOF_SHARED_d_UPPER_LATIN1_UTF8_STRING_MATCHES_non_d_RUNTIME_USER_PROP)
841             {
842 30           return convert_regclass_map(a, map);
843             }
844             else
845             {
846             /* fprintf(stderr, "zero map\n"); */
847 32           *map = 0;
848 32           return 1;
849             }
850             }
851              
852             /* returns 1 OK (map set), 0 map not recognized/representable */
853 5116           static int convert_class_narrow(Arrow *a, U32 *map)
854             {
855             /* fprintf(stderr, "enter convert_class_narrow\n"); */
856              
857             assert(map);
858              
859 5116 50         if (a->rn->flags >= SIZEOF_ARRAY(posix_regclass_blocks))
860             {
861             /* fprintf(stderr, "unknown class %d\n", a->rn->flags); */
862 0           return 0;
863             }
864              
865 5116           U32 mask = posix_regclass_blocks[a->rn->flags];
866 5116 50         if (!mask)
867             {
868             /* fprintf(stderr, "class %d ignored\n", a->rn->flags); */
869 0           return 0;
870             }
871              
872 5116           *map = mask;
873 5116           return 1;
874             }
875              
876             #ifdef RC_ANYOFM
877             /* Adapted from regcomp.c:get_ANYOFM_contents. b must point to
878             ANYOF_BITMAP_SIZE bytes. Returns 1 OK (b set), 0 matches something
879             above the bitmap. */
880             static int convert_anyofm_to_bitmap(Arrow *a, unsigned char *b)
881             {
882             regnode *n = a->rn;
883             U8 lowest = (U8)ARG(n);
884             unsigned count = 0;
885             unsigned needed = 1U << PL_bitcount[(U8)~FLAGS(n)];
886             unsigned i;
887             BitFlag bf;
888            
889             memset(b, 0, ANYOF_BITMAP_SIZE);
890             for (i = lowest; i <= 0xFF; i++)
891             {
892             if ((i & FLAGS(n)) == ARG(n))
893             {
894             init_bit_flag(&bf, i);
895             b[bf.offs] |= bf.mask;
896            
897             if (++count >= needed)
898             {
899             return 1;
900             }
901             }
902             }
903            
904             return 0;
905             }
906             #endif
907              
908             /* returns 1 OK (map set), 0 map not recognized/representable */
909 3918           static int convert_class(Arrow *a, U32 *map)
910             {
911 3918 50         if (!convert_class_narrow(a, map))
912             {
913 0           return 0;
914             }
915              
916 3918           *map = extend_mask(*map);
917 3918           return 1;
918             }
919              
920 998           static int convert_negative_class(Arrow *a, U32 *map)
921             {
922             U32 mask;
923              
924 998 50         if (!convert_class_narrow(a, &mask))
925             {
926 0           return 0;
927             }
928              
929 998           *map = extend_mask(MIRROR_BLOCK(mask));
930 998           return 1;
931             }
932              
933 609           static int get_assertion_offset(regnode *p)
934             {
935             int offs;
936              
937 609           offs = ARG_LOC(p);
938 609 50         if (offs <= 2)
939             {
940 0           rc_error = "Assertion offset too small";
941 0           return -1;
942             }
943              
944 609           return offs;
945             }
946              
947 2925           static int get_synth_offset(regnode *p)
948             {
949             assert(!p->next_off);
950              
951 2925 100         if (((p->type == EXACT) || (p->type == EXACTF) || (p->type == EXACTFU)) &&
    50          
    100          
    50          
952 1471           (p->flags == 1))
953             {
954 1471           return 2;
955             }
956 1454 100         else if (trivial_nodes[p->type] ||
    100          
957 425 100         (p->type == REG_ANY) || (p->type == SANY) ||
    100          
958 342 100         (p->type == POSIXD) || (p->type == NPOSIXD) ||
    100          
959 240 100         (p->type == POSIXU) || (p->type == NPOSIXU) ||
    100          
960 158 100         (p->type == POSIXA) || (p->type == NPOSIXA))
961             {
962 1305           return 1;
963             }
964 149 100         else if ((p->type == ANYOF) || (p->type == ANYOFD))
    100          
965             {
966             /* other flags obviously exist, but they haven't been seen yet
967             and it isn't clear what they mean */
968 143           unsigned int unknown = p->flags & ~(ANYOF_INVERT |
969             ANYOF_MATCHES_ALL_ABOVE_BITMAP | ANYOF_SHARED_d_UPPER_LATIN1_UTF8_STRING_MATCHES_non_d_RUNTIME_USER_PROP | ANYOF_SHARED_d_UPPER_LATIN1_UTF8_STRING_MATCHES_non_d_RUNTIME_USER_PROP);
970 143 50         if (unknown)
971             {
972             /* p[10] seems always 0 on Linux, but 0xfbfaf9f8 seen on
973             Windows; for '[\\w\\-_.]+\\.', both 0 and 0x20202020
974             observed in p[11] - wonder what those are... */
975 0           rc_error = "Unknown bitmap format";
976 0           return -1;
977             }
978              
979 143           return 11;
980             }
981             #ifdef RC_ANYOFM
982             else if (p->type == ANYOFM)
983             {
984             return 2;
985             }
986             #endif
987 6 100         else if ((p->type == IFMATCH) || (p->type == UNLESSM) ||
    50          
    0          
988 0           (p->type == SUSPEND))
989             {
990 6           return get_assertion_offset(p);
991             }
992              
993             /* fprintf(stderr, "type %d\n", p->type); */
994 0           rc_error = "Offset not set";
995 0           return -1;
996             }
997              
998 2817           static int get_size(regnode *rn)
999             {
1000             int offs;
1001 2817           regnode *e = rn;
1002              
1003 6816 100         while (e->type != END)
1004             {
1005 3999 100         offs = GET_OFFSET(e);
1006 3999 50         if (offs <= 0)
1007             {
1008 0           return -1;
1009             }
1010              
1011 3999           e += offs;
1012             }
1013              
1014 2817           return e - rn + 1;
1015             }
1016              
1017             /* #define DEBUG_dump_data */
1018              
1019 16990           static regnode *find_internal(regexp *pt)
1020             {
1021             regexp_internal *pr;
1022             regnode *p;
1023             #ifdef DEBUG_dump_data
1024             struct reg_data *rdata;
1025             int n;
1026             #endif
1027              
1028             assert(pt);
1029              
1030             /* ActivePerl Build 1001 doesn't export PL_core_reg_engine, so
1031             the test, however useful, wouldn't link... */
1032             #if !defined(ACTIVEPERL_PRODUCT)
1033 16990 50         if (pt->engine && (pt->engine != &PL_core_reg_engine))
    50          
1034             {
1035 0           rc_error = "Alternative regexp engine not supported";
1036 0           return 0;
1037             }
1038             #endif
1039              
1040 16990           pr = RXi_GET(pt);
1041 16990 50         if (!pr)
1042             {
1043 0           rc_error = "Internal regexp not set";
1044 0           return 0;
1045             }
1046              
1047 16990           p = pr->program;
1048 16990 50         if (!p)
1049             {
1050 0           rc_error = "Compiled regexp not set";
1051 0           return 0;
1052             }
1053              
1054 16990 50         if (!((p->flags == REG_MAGIC) &&
    50          
1055 16990           (p->next_off == 0)))
1056             {
1057             /* fprintf(stderr, "%d %d %d\n", p->flags, p->type, p->next_off); */
1058 0           rc_error = "Invalid regexp signature";
1059 0           return 0;
1060             }
1061              
1062             #ifdef DEBUG_dump_data
1063             rdata = pr->data;
1064             if (rdata)
1065             {
1066             fprintf(stderr, "regexp data count = %d\n", (int)(rdata->count));
1067             for (n = 0; n < rdata->count; ++n)
1068             {
1069             fprintf(stderr, "\twhat[%d] = %c\n", n, rdata->what[n]);
1070             }
1071             }
1072             else
1073             {
1074             fprintf(stderr, "no regexp data\n");
1075             }
1076             #endif
1077              
1078 16990           return p + 1;
1079             }
1080              
1081 204           static unsigned char parse_hex_digit(char d)
1082             {
1083             unsigned char rv;
1084              
1085 204           d = tolower(d);
1086              
1087 204 50         if (('0' <= d) && (d <= '9'))
    100          
1088             {
1089 143           rv = d - '0';
1090             }
1091             else
1092             {
1093 61           rv = 10 + (d - 'a');
1094             }
1095              
1096 204           return rv;
1097             }
1098              
1099 102           static unsigned char parse_hex_byte(const char *first)
1100             {
1101 204           return 16 * parse_hex_digit(*first) +
1102 102           parse_hex_digit(first[1]);
1103             }
1104              
1105 17004           static unsigned get_forced_semantics(REGEXP *pt)
1106             {
1107 17004           const char *precomp = RX_PRECOMP(pt);
1108 17004           U32 prelen = RX_PRELEN(pt);
1109 17004           int quoted = 0;
1110             int matched;
1111 17004           unsigned forced = 0;
1112             U32 i;
1113             BitFlag bf;
1114             char c;
1115              
1116             /* fprintf(stderr, "precomp = %*s\n", (int)prelen, precomp); */
1117              
1118 123622 100         for (i = 0; i < prelen; ++i)
1119             {
1120 106618           c = precomp[i];
1121            
1122 106618 100         if (c == '.')
1123             {
1124             /* a dot does match Unicode character - the problem is
1125             that character might take up multiple bytes, and we
1126             don't want to match just one of them... */
1127 1214           forced |= FORCED_BYTE;
1128             }
1129            
1130 106618 100         if (!quoted)
1131             {
1132             /* technically, the backslash might be in a comment, but
1133             parsing that is too much hassle */
1134 95474 100         if (c == '\\')
1135             {
1136 95474           quoted = 1;
1137             }
1138             }
1139             else
1140             {
1141 11144           matched = 0;
1142              
1143 11144 100         if (c == 'N')
1144             {
1145             /* we have special cases only for \r & \n... */
1146 423 100         if ((i + 8 < prelen) &&
    100          
1147 11 50         !memcmp(precomp + i + 1, "{U+00", 5) &&
1148 22 50         isxdigit(precomp[i + 6]) && isxdigit(precomp[i + 7]) &&
    50          
1149 11           (precomp[i + 8] == '}'))
1150 11           {
1151 11           unsigned char x = parse_hex_byte(precomp + i + 6);
1152 11 100         if ((x != '\r') && (x != '\n'))
    50          
1153             {
1154 0           forced |= FORCED_CHAR;
1155             }
1156              
1157 11           i += 8;
1158             }
1159 412 100         else if ((i + 1 < prelen) &&
    100          
1160 211           (precomp[i + 1] == '{'))
1161             {
1162 13           forced |= FORCED_CHAR;
1163             }
1164              
1165             /* otherwise it's not an escape, but the inverse of \n
1166             - we aren't interested in that */
1167              
1168 423           matched = 1;
1169             }
1170 10721 100         else if (c == 'x')
1171             {
1172 214           if ((i + 2 < prelen) &&
1173 198 50         isxdigit(precomp[i + 1]) && isxdigit(precomp[i + 2]))
1174             {
1175 91           unsigned char x = parse_hex_byte(precomp + i + 1);
1176 91 100         if ((x != '\r') && (x != '\n'))
    50          
1177             {
1178 85           forced |= FORCED_BYTE;
1179             }
1180              
1181 91           matched = 1;
1182 91           i += 2;
1183             }
1184             }
1185              
1186             /* ...and we aren't bothering to parse octal numbers
1187             and \x{n+} at all... */
1188              
1189 11144 100         if (!matched)
1190             {
1191 10630           init_bit_flag(&bf, (unsigned char)c);
1192 10630 100         if (forced_byte[bf.offs] & bf.mask)
1193             {
1194 314           forced |= FORCED_BYTE;
1195             }
1196             }
1197              
1198 11144           quoted = 0;
1199             }
1200             }
1201              
1202 17004           return forced;
1203             }
1204              
1205 871           static regnode *alloc_alt(regnode *p, int sz)
1206             {
1207             regnode *alt;
1208              
1209 871           alt = (regnode *)malloc(sizeof(regnode) * sz);
1210 871 50         if (!alt)
1211             {
1212 0           rc_error = "Could not allocate memory for regexp copy";
1213 0           return 0;
1214             }
1215              
1216 871           memcpy(alt, p, sizeof(regnode) * sz);
1217              
1218 871           return alt;
1219             }
1220              
1221 350           static regnode *alloc_terminated(regnode *p, int sz)
1222             {
1223             regnode *alt;
1224             int last;
1225              
1226             /* fprintf(stderr, "enter alloc_terminated(, %d\n", sz); */
1227              
1228             assert(sz > 0);
1229 350           alt = alloc_alt(p, sz);
1230 350 50         if (!alt)
1231             {
1232 0           return 0;
1233             }
1234              
1235 350           last = alt[sz - 1].type;
1236             /* fprintf(stderr, "type: %d\n", last); */
1237 350 50         if ((last >= REGNODE_MAX) || !trivial_nodes[last])
    50          
1238             {
1239 0           rc_error = "Alternative doesn't end like subexpression";
1240 0           return 0;
1241             }
1242              
1243 350           alt[sz - 1].type = END;
1244 350           return alt;
1245             }
1246              
1247 15255           static int bump_exact(Arrow *a)
1248             {
1249             int offs;
1250              
1251             assert((a->rn->type == EXACT) || (a->rn->type == EXACTF) || (a->rn->type == EXACTFU));
1252              
1253 15255 100         offs = GET_OFFSET(a->rn);
1254 15255 50         if (offs <= 0)
1255             {
1256 0           return -1;
1257             }
1258              
1259 15255 100         if (++(a->spent) >= a->rn->flags)
1260             {
1261 10024           a->spent = 0;
1262 10024           a->rn += offs;
1263             }
1264              
1265 15255           return 1;
1266             }
1267              
1268 17034           static int bump_regular(Arrow *a)
1269             {
1270             int offs;
1271              
1272             assert(a->rn->type != END);
1273             assert(a->rn->type != EXACT);
1274             assert(a->rn->type != EXACTF);
1275             assert(!a->spent);
1276              
1277 17034 100         offs = GET_OFFSET(a->rn);
1278 17034 50         if (offs <= 0)
1279             {
1280 0           return -1;
1281             }
1282              
1283 17034           a->rn += offs;
1284 17034           return 1;
1285             }
1286              
1287 30537           static int bump_with_check(Arrow *a)
1288             {
1289 30537 100         if (a->rn->type == END)
1290             {
1291 73           return 0;
1292             }
1293 30464 100         else if ((a->rn->type == EXACT) || (a->rn->type == EXACTF) || (a->rn->type == EXACTFU))
    100          
    100          
1294             {
1295 15255           return bump_exact(a);
1296             }
1297             else
1298             {
1299 15209           return bump_regular(a);
1300             }
1301             }
1302              
1303 92           static int get_jump_offset(regnode *p)
1304             {
1305             int offs;
1306             regnode *q;
1307              
1308             assert(p->type != END);
1309              
1310 92 50         offs = GET_OFFSET(p);
1311 92 50         if (offs <= 0)
1312             {
1313 0           return -1;
1314             }
1315              
1316 92           q = p + offs;
1317 124 100         while (trivial_nodes[q->type])
1318             {
1319 32 100         offs = GET_OFFSET(q);
1320 32 50         if (offs <= 0)
1321             {
1322 0           return -1;
1323             }
1324              
1325 32           q += offs;
1326             }
1327              
1328 92           return q - p;
1329             }
1330              
1331 17011           REGEXP *rc_regcomp(SV *rs)
1332             {
1333             REGEXP *rx;
1334              
1335 17011 50         if (!rs)
1336             {
1337 0           croak("No regexp to compare");
1338             }
1339              
1340 17011           rx = pregcomp(rs, 0);
1341 17006 50         if (!rx)
1342             {
1343 0           croak("Cannot compile regexp");
1344             }
1345              
1346 17006           return rx;
1347             }
1348              
1349 17006           void rc_regfree(REGEXP *rx)
1350             {
1351 17006 50         if (rx)
1352             {
1353 17006           pregfree(rx);
1354             }
1355 17006           }
1356              
1357 5910           static int compare_mismatch(int anchored, Arrow *a1, Arrow *a2)
1358             {
1359             int rv;
1360              
1361             /* fprintf(stderr, "enter compare_mismatch(%d...)\n", anchored); */
1362              
1363 5910 100         if (anchored)
1364             {
1365 657           return 0;
1366             }
1367             else
1368             {
1369 5253           rv = bump_with_check(a1);
1370 5253 100         if (rv <= 0)
1371             {
1372 73           return rv;
1373             }
1374              
1375 5180           return compare(0, a1, a2);
1376             }
1377             }
1378              
1379 12159           static int compare_tails(int anchored, Arrow *a1, Arrow *a2)
1380             {
1381             Arrow tail1, tail2;
1382             int rv;
1383              
1384             /* is it worth using StructCopy? */
1385 12159           tail1 = *a1;
1386 12159           rv = bump_with_check(&tail1);
1387 12159 50         if (rv <= 0)
1388             {
1389 0           return rv;
1390             }
1391              
1392 12159           tail2 = *a2;
1393 12159           rv = bump_with_check(&tail2);
1394 12159 50         if (rv <= 0)
1395             {
1396 0           return rv;
1397             }
1398              
1399 12159           rv = compare(1, &tail1, &tail2);
1400 12159 50         if (rv < 0)
1401             {
1402 0           return rv;
1403             }
1404              
1405 12159 100         if (!rv)
1406             {
1407 251           rv = compare_mismatch(anchored, a1, a2);
1408             }
1409             else
1410             {
1411 11908           *a1 = tail1;
1412 11908           *a2 = tail2;
1413             }
1414              
1415 12159           return rv;
1416             }
1417              
1418 792           static int compare_left_tail(int anchored, Arrow *a1, Arrow *a2)
1419             {
1420             Arrow tail1;
1421             int rv;
1422              
1423 792           tail1 = *a1;
1424 792           rv = bump_with_check(&tail1);
1425 792 50         if (rv <= 0)
1426             {
1427 0           return rv;
1428             }
1429              
1430 792           return compare(anchored, &tail1, a2);
1431             }
1432              
1433 253           static int compare_after_assertion(int anchored, Arrow *a1, Arrow *a2)
1434             {
1435             Arrow tail1;
1436             int offs;
1437              
1438             assert((a1->rn->type == IFMATCH) || (a1->rn->type == UNLESSM));
1439              
1440 253           offs = get_assertion_offset(a1->rn);
1441 253 50         if (offs < 0)
1442             {
1443 0           return offs;
1444             }
1445              
1446 253           tail1.origin = a1->origin;
1447 253           tail1.rn = a1->rn + offs;
1448 253           tail1.spent = 0;
1449 253           return compare(anchored, &tail1, a2);
1450             }
1451              
1452 75           static int compare_positive_assertions(int anchored, Arrow *a1, Arrow *a2)
1453             {
1454             regnode *p1, *alt1, *p2, *alt2;
1455             int rv, sz1, sz2;
1456             Arrow left, right;
1457              
1458 75           p1 = a1->rn;
1459 75           p2 = a2->rn;
1460             assert(p1->type == IFMATCH);
1461             assert(p2->type == IFMATCH);
1462              
1463 75           sz1 = get_assertion_offset(p1);
1464 75 50         if (sz1 < 0)
1465             {
1466 0           return -1;
1467             }
1468              
1469 75           sz2 = get_assertion_offset(p2);
1470 75 50         if (sz2 < 0)
1471             {
1472 0           return -1;
1473             }
1474              
1475 75           alt1 = alloc_terminated(p1 + 2, sz1 - 2);
1476 75 50         if (!alt1)
1477             {
1478 0           return -1;
1479             }
1480              
1481 75           alt2 = alloc_terminated(p2 + 2, sz2 - 2);
1482 75 50         if (!alt2)
1483             {
1484 0           free(alt1);
1485 0           return -1;
1486             }
1487              
1488 75           left.origin = a1->origin;
1489 75           left.rn = alt1;
1490 75           left.spent = 0;
1491 75           right.origin = a2->origin;
1492 75           right.rn = alt2;
1493 75           right.spent = 0;
1494 75           rv = compare(0, &left, &right);
1495              
1496 75           free(alt1);
1497 75           free(alt2);
1498              
1499 75 100         if (rv <= 0)
1500             {
1501 1           return rv;
1502             }
1503              
1504             /* left & right.origin stays a1 & a2->origin, respectively */
1505 74           left.rn = p1 + sz1;
1506 74           left.spent = 0;
1507 74           right.rn = p2 + sz2;
1508 74           right.spent = 0;
1509 75           return compare(anchored, &left, &right);
1510             }
1511              
1512 72           static int compare_negative_assertions(int anchored, Arrow *a1, Arrow *a2)
1513             {
1514             regnode *p1, *alt1, *p2, *alt2;
1515             int rv, sz1, sz2;
1516             Arrow left, right;
1517              
1518 72           p1 = a1->rn;
1519 72           p2 = a2->rn;
1520             assert(p1->type == UNLESSM);
1521             assert(p2->type == UNLESSM);
1522              
1523 72           sz1 = get_assertion_offset(p1);
1524 72 50         if (sz1 < 0)
1525             {
1526 0           return -1;
1527             }
1528              
1529 72           sz2 = get_assertion_offset(p2);
1530 72 50         if (sz2 < 0)
1531             {
1532 0           return -1;
1533             }
1534              
1535 72           alt1 = alloc_terminated(p1 + 2, sz1 - 2);
1536 72 50         if (!alt1)
1537             {
1538 0           return -1;
1539             }
1540              
1541 72           alt2 = alloc_terminated(p2 + 2, sz2 - 2);
1542 72 50         if (!alt2)
1543             {
1544 0           free(alt1);
1545 0           return -1;
1546             }
1547              
1548 72           left.origin = a1->origin;
1549 72           left.rn = alt1;
1550 72           left.spent = 0;
1551 72           right.origin = a2->origin;
1552 72           right.rn = alt2;
1553 72           right.spent = 0;
1554 72           rv = compare(0, &right, &left);
1555              
1556 72           free(alt1);
1557 72           free(alt2);
1558              
1559 72 100         if (rv <= 0)
1560             {
1561 2           return rv;
1562             }
1563              
1564             /* left & right.origin stays a1 & a2->origin, respectively */
1565 70           left.rn = p1 + sz1;
1566 70           left.spent = 0;
1567 70           right.rn = p2 + sz2;
1568 70           right.spent = 0;
1569 72           return compare(anchored, &left, &right);
1570             }
1571              
1572 28           static int compare_subexpressions(int anchored, Arrow *a1, Arrow *a2)
1573             {
1574             regnode *p1, *alt1, *p2, *alt2;
1575             int rv, sz1, sz2;
1576             Arrow left, right;
1577              
1578 28           p1 = a1->rn;
1579 28           p2 = a2->rn;
1580             assert(p1->type == SUSPEND);
1581             assert(p2->type == SUSPEND);
1582              
1583 28           sz1 = get_assertion_offset(p1);
1584 28 50         if (sz1 < 0)
1585             {
1586 0           return -1;
1587             }
1588              
1589 28           sz2 = get_assertion_offset(p2);
1590 28 50         if (sz2 < 0)
1591             {
1592 0           return -1;
1593             }
1594              
1595 28           alt1 = alloc_terminated(p1 + 2, sz1 - 2);
1596 28 50         if (!alt1)
1597             {
1598 0           return -1;
1599             }
1600              
1601 28           alt2 = alloc_terminated(p2 + 2, sz2 - 2);
1602 28 50         if (!alt2)
1603             {
1604 0           free(alt1);
1605 0           return -1;
1606             }
1607              
1608 28           left.origin = a1->origin;
1609 28           left.rn = alt1;
1610 28           left.spent = 0;
1611 28           right.origin = a2->origin;
1612 28           right.rn = alt2;
1613 28           right.spent = 0;
1614 28           rv = compare(1, &left, &right);
1615              
1616 28           free(alt1);
1617 28           free(alt2);
1618              
1619 28 100         if (rv <= 0)
1620             {
1621 1           return rv;
1622             }
1623              
1624             /* left & right.origin stays a1 & a2->origin, respectively */
1625 27           left.rn = p1 + sz1;
1626 27           left.spent = 0;
1627 27           right.rn = p2 + sz2;
1628 27           right.spent = 0;
1629 28           return compare(1, &left, &right);
1630             }
1631              
1632 619           static int compare_bol(int anchored, Arrow *a1, Arrow *a2)
1633             {
1634             int rv;
1635              
1636             assert((a1->rn->type == MBOL) || (a1->rn->type == SBOL));
1637              
1638 619 100         if (anchored)
1639             {
1640 8           return 0;
1641             }
1642              
1643 611 50         if (bump_regular(a1) <= 0)
1644             {
1645 0           return -1;
1646             }
1647              
1648 611           rv = compare(1, a1, a2);
1649 611 100         if (!rv)
1650             {
1651 61           rv = compare_mismatch(0, a1, a2);
1652             }
1653              
1654 611           return rv;
1655             }
1656              
1657 26972           static unsigned char get_bitmap_byte(regnode *p, int i)
1658             {
1659             unsigned char *bitmap;
1660             unsigned char loc;
1661              
1662             assert((p->type == ANYOF) || (p->type == ANYOFD));
1663              
1664 26972           bitmap = (unsigned char *)(p + 2);
1665 26972           loc = bitmap[i];
1666 26972 100         if (p->flags & ANYOF_INVERT)
1667             {
1668 234           loc = ~loc;
1669             }
1670              
1671 26972           return loc;
1672             }
1673              
1674 553           static int compare_bitmaps(int anchored, Arrow *a1, Arrow *a2,
1675             unsigned char *b1, unsigned char *b2)
1676             {
1677             /* Note that aN->flags must be ignored when bN is set (necessary
1678             for ANYOFM, where they aren't really flags and can't be used as
1679             such). */
1680             unsigned char loc1, loc2;
1681             int i;
1682              
1683             /* fprintf(stderr, "enter compare_bitmaps(%d, %d, %d)\n", anchored,
1684             a1->rn->type, a2->rn->type); */
1685              
1686 15815 100         for (i = 0; i < ANYOF_BITMAP_SIZE; ++i)
1687             {
1688 15356 100         loc1 = b1 ? b1[i] : get_bitmap_byte(a1->rn, i);
1689 15356 100         loc2 = b2 ? b2[i] : get_bitmap_byte(a2->rn, i);
1690 15356 100         if (loc1 & ~loc2)
1691             {
1692             /* fprintf(stderr, "compare_bitmaps fails at %d: %d does not imply %d\n",
1693             i, loc1, loc2); */
1694 94           return compare_mismatch(anchored, a1, a2);
1695             }
1696             }
1697              
1698 459           return compare_tails(anchored, a1, a2);
1699             }
1700              
1701 3           static int compare_anyof_multiline(int anchored, Arrow *a1, Arrow *a2)
1702             {
1703             BitFlag bf;
1704             Arrow tail1, tail2;
1705             unsigned char req;
1706             int i;
1707              
1708             /* fprintf(stderr, "enter compare_anyof_multiline\n"); */
1709              
1710             assert((a1->rn->type == ANYOF) || (a1->rn->type == ANYOFD));
1711             assert((a2->rn->type == MBOL) || (a2->rn->type == MEOL));
1712              
1713 3 50         if (a1->rn->flags & ANYOF_MATCHES_ALL_ABOVE_BITMAP)
1714             {
1715 0           return compare_mismatch(anchored, a1, a2);
1716             }
1717              
1718 3           init_bit_flag(&bf, '\n');
1719 6 50         for (i = 0; i < ANYOF_BITMAP_SIZE; ++i)
1720             {
1721 6 100         req = (i != bf.offs) ? 0 : bf.mask;
1722 6 100         if (get_bitmap_byte(a1->rn, i) != req)
1723             {
1724 3           return compare_mismatch(anchored, a1, a2);
1725             }
1726             }
1727              
1728 0           tail1 = *a1;
1729 0 0         if (bump_regular(&tail1) <= 0)
1730             {
1731 0           return -1;
1732             }
1733              
1734 0           tail2 = *a2;
1735 0 0         if (bump_regular(&tail2) <= 0)
1736             {
1737 0           return -1;
1738             }
1739              
1740 3           return compare(1, &tail1, &tail2);
1741             }
1742              
1743             #ifdef RC_ANYOFM
1744             static int compare_anyofm_multiline(int anchored, Arrow *a1, Arrow *a2)
1745             {
1746             unsigned char req;
1747             int i;
1748             BitFlag bf;
1749             Arrow tail1, tail2;
1750             unsigned char left[ANYOF_BITMAP_SIZE];
1751              
1752             assert(a1->rn->type == ANYOFM);
1753             assert((a2->rn->type == MBOL) || (a2->rn->type == MEOL));
1754              
1755             if (!convert_anyofm_to_bitmap(a1, left))
1756             {
1757             return compare_mismatch(anchored, a1, a2);
1758             }
1759              
1760             init_bit_flag(&bf, '\n');
1761             for (i = 0; i < ANYOF_BITMAP_SIZE; ++i)
1762             {
1763             req = (i != bf.offs) ? 0 : bf.mask;
1764             if (left[i] != req)
1765             {
1766             return compare_mismatch(anchored, a1, a2);
1767             }
1768             }
1769              
1770             tail1 = *a1;
1771             if (bump_regular(&tail1) <= 0)
1772             {
1773             return -1;
1774             }
1775              
1776             tail2 = *a2;
1777             if (bump_regular(&tail2) <= 0)
1778             {
1779             return -1;
1780             }
1781              
1782             return compare(1, &tail1, &tail2);
1783             }
1784             #endif
1785              
1786 211           static int compare_anyof_anyof(int anchored, Arrow *a1, Arrow *a2)
1787             {
1788             int extra_left;
1789              
1790             /* fprintf(stderr, "enter compare_anyof_anyof(%d\n", anchored); */
1791              
1792             assert((a1->rn->type == ANYOF) || (a1->rn->type == ANYOFD));
1793             assert((a2->rn->type == ANYOF) || (a2->rn->type == ANYOFD));
1794              
1795 211           extra_left = ANYOF_FLAGS(a1->rn) &
1796             ANYOF_SHARED_d_UPPER_LATIN1_UTF8_STRING_MATCHES_non_d_RUNTIME_USER_PROP;
1797 211 100         if ((extra_left || (a1->rn->flags & ANYOF_MATCHES_ALL_ABOVE_BITMAP)) &&
    100          
    100          
1798 112           !(a2->rn->flags & ANYOF_MATCHES_ALL_ABOVE_BITMAP))
1799             {
1800             U32 m1, m2;
1801             int cr1, cr2;
1802              
1803             /* fprintf(stderr, "comparing invlists: left flags = 0x%x, right flags = 0x%x\n", (int)(a1->rn->flags), (int)(a2->rn->flags)); */
1804             /* before recognizing standard invlists, check whether they
1805             aren't the same - this duplicates the code to get to the
1806             invlist, but works even for non-standard ones,
1807             e.g. [\da] */
1808 90 50         if ((a1->rn->flags & ANYOF_SHARED_d_UPPER_LATIN1_UTF8_STRING_MATCHES_non_d_RUNTIME_USER_PROP) &&
    100          
1809 90           (a2->rn->flags & ANYOF_SHARED_d_UPPER_LATIN1_UTF8_STRING_MATCHES_non_d_RUNTIME_USER_PROP))
1810             {
1811 87           SV *invlist1 = get_invlist_sv(a1);
1812 87           SV *invlist2 = get_invlist_sv(a2);
1813 87 50         if (invlist1 && invlist2)
    50          
1814             {
1815 87           UV ill1 = get_invlist_len(invlist1);
1816 87           UV ill2 = get_invlist_len(invlist2);
1817 87 50         if (ill1 && (ill1 == ill2))
    50          
1818             {
1819 87           UV *ila1 = invlist_array(invlist1);
1820 87           UV *ila2 = invlist_array(invlist2);
1821 87 50         if (!memcmp(ila1, ila2, ill1 * sizeof(UV)))
1822             {
1823 90           return compare_bitmaps(anchored, a1, a2, 0, 0);
1824             }
1825             }
1826             }
1827             }
1828              
1829 3           cr1 = convert_map(a1, &m1);
1830 3 50         if (cr1 == -1)
1831             {
1832 0           return -1;
1833             }
1834              
1835 3           cr2 = convert_map(a2, &m2);
1836 3 50         if (cr2 == -1)
1837             {
1838 0           return -1;
1839             }
1840              
1841             /* clearly this hould happen at a lower level, but there it
1842             breaks other paths... */
1843 3 50         if (m2 & NOT_ALNUM_BLOCK)
1844             {
1845 0           m2 |= NOT_ALPHA_BLOCK | NOT_NUMBER_BLOCK;
1846 0           m2 = extend_mask(m2);
1847             }
1848              
1849 3 50         if (!cr1 || !cr2 || (m1 & ~m2))
    50          
    50          
1850             {
1851             /* fprintf(stderr, "cr1 = %d, cr2 = %d, m1 = 0x%x, m2 = 0x%x\n",
1852             cr1, cr2, (unsigned)m1, (unsigned)m2); */
1853 3           return compare_mismatch(anchored, a1, a2);
1854             }
1855             }
1856              
1857 121           return compare_bitmaps(anchored, a1, a2, 0, 0);
1858             }
1859              
1860             #ifdef RC_ANYOFM
1861             static int compare_anyof_anyofm(int anchored, Arrow *a1, Arrow *a2)
1862             {
1863             unsigned char right[ANYOF_BITMAP_SIZE];
1864            
1865             /* fprintf(stderr, "enter compare_anyof_anyofm(%d\n", anchored); */
1866              
1867             assert((a1->rn->type == ANYOF) || (a1->rn->type == ANYOFD));
1868             assert(a2->rn->type == ANYOFM);
1869              
1870             if (ANYOF_FLAGS(a1->rn) & ANYOF_SHARED_d_UPPER_LATIN1_UTF8_STRING_MATCHES_non_d_RUNTIME_USER_PROP)
1871             {
1872             return compare_mismatch(anchored, a1, a2);
1873             }
1874              
1875             if (!convert_anyofm_to_bitmap(a2, right))
1876             {
1877             return compare_mismatch(anchored, a1, a2);
1878             }
1879              
1880             return compare_bitmaps(anchored, a1, a2, 0, right);
1881             }
1882              
1883             static int compare_anyofm_anyof(int anchored, Arrow *a1, Arrow *a2)
1884             {
1885             unsigned char left[ANYOF_BITMAP_SIZE];
1886            
1887             /* fprintf(stderr, "enter compare_anyofm_anyof(%d\n", anchored); */
1888              
1889             assert(a1->rn->type == ANYOFM);
1890             assert((a2->rn->type == ANYOF) || (a2->rn->type == ANYOFD));
1891              
1892             if (!convert_anyofm_to_bitmap(a1, left))
1893             {
1894             return compare_mismatch(anchored, a1, a2);
1895             }
1896              
1897             return compare_bitmaps(anchored, a1, a2, left, 0);
1898             }
1899              
1900             static int compare_anyofm_anyofm(int anchored, Arrow *a1, Arrow *a2)
1901             {
1902             unsigned char left[ANYOF_BITMAP_SIZE];
1903             unsigned char right[ANYOF_BITMAP_SIZE];
1904            
1905             assert(a1->rn->type == ANYOFM);
1906             assert(a2->rn->type == ANYOFM);
1907              
1908             if (!convert_anyofm_to_bitmap(a1, left))
1909             {
1910             return compare_mismatch(anchored, a1, a2);
1911             }
1912            
1913             if (!convert_anyofm_to_bitmap(a2, right))
1914             {
1915             return compare_mismatch(anchored, a1, a2);
1916             }
1917            
1918             return compare_bitmaps(anchored, a1, a2, left, right);
1919             }
1920             #endif
1921              
1922             /* compare_bitmaps could replace this method, but when a class
1923             contains just a few characters, it seems more natural to compare
1924             them explicitly */
1925 0           static int compare_short_byte_class(int anchored, Arrow *a1, Arrow *a2,
1926             ByteClass *left)
1927             {
1928             BitFlag bf;
1929             int i;
1930              
1931 0 0         for (i = 0; i < left->expl_size; ++i)
1932             {
1933 0           init_bit_flag(&bf, (unsigned char)left->expl[i]);
1934 0 0         if (!(get_bitmap_byte(a2->rn, bf.offs) & bf.mask))
1935             {
1936 0           return compare_mismatch(anchored, a1, a2);
1937             }
1938             }
1939              
1940 0           return compare_tails(anchored, a1, a2);
1941             }
1942              
1943 2           static int compare_right_full(int anchored, Arrow *a1, Arrow *a2)
1944             {
1945             int i;
1946              
1947 34 100         for (i = 0; i < 16; ++i)
1948             {
1949 32 50         if (!(get_bitmap_byte(a2->rn, i) & 0xff))
1950             {
1951 0           return compare_mismatch(anchored, a1, a2);
1952             }
1953             }
1954              
1955 2           return compare_tails(anchored, a1, a2);
1956             }
1957              
1958 1276           static int compare_posix_posix(int anchored, Arrow *a1, Arrow *a2)
1959             {
1960             U32 m1, m2;
1961             int cr1, cr2;
1962              
1963             /* fprintf(stderr, "enter compare_posix_posix\n"); */
1964              
1965 1276           cr1 = convert_class(a1, &m1);
1966 1276           cr2 = convert_class(a2, &m2);
1967 1276 50         if (!cr1 || !cr2 || (m1 & ~m2))
    50          
    100          
1968             {
1969 231           return compare_mismatch(anchored, a1, a2);
1970             }
1971              
1972 1276           return compare_tails(anchored, a1, a2);
1973             }
1974              
1975 683           static int compare_posix_negative_posix(int anchored, Arrow *a1, Arrow *a2)
1976             {
1977             U32 m1, m2;
1978             int cr1, cr2;
1979              
1980             /* fprintf(stderr, "enter compare_posix_negative_posix\n"); */
1981              
1982 683           cr1 = convert_class(a1, &m1);
1983 683           cr2 = convert_class(a2, &m2);
1984 683 50         if (!cr1 || !cr2)
    50          
1985             {
1986 0           return compare_mismatch(anchored, a1, a2);
1987             }
1988              
1989             /* vertical space is not a strict subset of space, but it does
1990             have space elements, so we have to require space on the right */
1991 683 100         if ((m1 & VERTICAL_SPACE_BLOCK) && !(m2 & VERTICAL_SPACE_BLOCK))
    100          
1992             {
1993 72           m1 |= SPACE_BLOCK;
1994             }
1995              
1996 683 100         if (m1 & m2)
1997             {
1998 189           return compare_mismatch(anchored, a1, a2);
1999             }
2000              
2001 683           return compare_tails(anchored, a1, a2);
2002             }
2003              
2004 499           static int compare_negative_posix_negative_posix(int anchored, Arrow *a1, Arrow *a2)
2005             {
2006             U32 m1, m2;
2007             int cr1, cr2;
2008              
2009             assert((a1->rn->type == NPOSIXD) || (a1->rn->type == NPOSIXU) ||
2010             (a1->rn->type == NPOSIXA));
2011             assert((a2->rn->type == NPOSIXD) || (a2->rn->type == NPOSIXU) ||
2012             (a2->rn->type == NPOSIXA));
2013              
2014             /* fprintf(stderr, "enter compare_negative_posix_negative_posix\n"); */
2015              
2016 499           cr1 = convert_negative_class(a1, &m1);
2017 499           cr2 = convert_negative_class(a2, &m2);
2018 499 50         if (!cr2 || !cr2 || (m1 & ~m2))
    50          
    100          
2019             {
2020 128           return compare_mismatch(anchored, a1, a2);
2021             }
2022              
2023 499           return compare_tails(anchored, a1, a2);
2024             }
2025              
2026 808           static int compare_exact_posix(int anchored, Arrow *a1, Arrow *a2)
2027             {
2028             char *seq;
2029              
2030             assert((a1->rn->type == EXACT) || (a1->rn->type == EXACTF) ||
2031             (a1->rn->type == EXACTFU));
2032             assert((a2->rn->type == POSIXD) || (a2->rn->type == POSIXU) ||
2033             (a2->rn->type == POSIXA));
2034              
2035 808           seq = GET_LITERAL(a1);
2036              
2037 808 100         if (!_generic_isCC_A(*seq, a2->rn->flags))
2038             {
2039 55           return compare_mismatch(anchored, a1, a2);
2040             }
2041              
2042 753           return compare_tails(anchored, a1, a2);
2043             }
2044              
2045 39           static int compare_exactf_posix(int anchored, Arrow *a1, Arrow *a2)
2046             {
2047             char *seq;
2048             char unf[2];
2049             int i;
2050              
2051             assert((a1->rn->type == EXACTF) || (a1->rn->type == EXACTFU));
2052             assert(a2->rn->type == POSIXD);
2053              
2054 39           seq = GET_LITERAL(a1);
2055 39           init_unfolded(unf, *seq);
2056              
2057 111 100         for (i = 0; i < 2; ++i)
2058             {
2059 75 100         if (!_generic_isCC_A(unf[i], a2->rn->flags))
2060             {
2061 3           return compare_mismatch(anchored, a1, a2);
2062             }
2063             }
2064              
2065 39           return compare_tails(anchored, a1, a2);
2066             }
2067              
2068 759           static int compare_exact_negative_posix(int anchored, Arrow *a1, Arrow *a2)
2069             {
2070             char *seq;
2071              
2072             assert(a1->rn->type == EXACT);
2073             assert((a2->rn->type == NPOSIXD) || (a2->rn->type == NPOSIXU) ||
2074             (a2->rn->type == NPOSIXA));
2075              
2076 759           seq = GET_LITERAL(a1);
2077              
2078 759 100         if (_generic_isCC_A(*seq, a2->rn->flags))
2079             {
2080 21           return compare_mismatch(anchored, a1, a2);
2081             }
2082              
2083 738           return compare_tails(anchored, a1, a2);
2084             }
2085              
2086 61           static int compare_exactf_negative_posix(int anchored, Arrow *a1, Arrow *a2)
2087             {
2088             char *seq;
2089             char unf[2];
2090             int i;
2091              
2092             assert((a1->rn->type == EXACTF) || (a1->rn->type == EXACTFU));
2093             assert((a2->rn->type == NPOSIXD) || (a2->rn->type == NPOSIXU) ||
2094             (a2->rn->type == NPOSIXA));
2095              
2096 61           seq = GET_LITERAL(a1);
2097 61           init_unfolded(unf, *seq);
2098              
2099 181 100         for (i = 0; i < 2; ++i)
2100             {
2101 121 100         if (_generic_isCC_A(unf[i], a2->rn->flags))
2102             {
2103 1           return compare_mismatch(anchored, a1, a2);
2104             }
2105             }
2106              
2107 61           return compare_tails(anchored, a1, a2);
2108             }
2109              
2110 13           static int compare_reg_any_anyof(int anchored, Arrow *a1, Arrow *a2)
2111             {
2112             assert(a1->rn->type == REG_ANY);
2113             assert((a2->rn->type == ANYOF) || (a2->rn->type == ANYOFD));
2114              
2115 13           return compare_bitmaps(anchored, a1, a2, ndot.nbitmap, 0);
2116             }
2117              
2118 130           static int compare_posix_anyof(int anchored, Arrow *a1, Arrow *a2)
2119             {
2120             U32 left_block;
2121             unsigned char *b;
2122              
2123             /* fprintf(stderr, "enter compare_posix_anyof\n"); */
2124              
2125             assert((a1->rn->type == POSIXD) || (a1->rn->type == POSIXU) ||
2126             (a1->rn->type == POSIXA));
2127             assert((a2->rn->type == ANYOF) || (a2->rn->type == ANYOFD));
2128              
2129 130 50         if (!convert_class_narrow(a1, &left_block))
2130             {
2131 0           return compare_mismatch(anchored, a1, a2);
2132             }
2133              
2134             /* fprintf(stderr, "right flags = %d\n", a2->rn->flags); */
2135              
2136 130 100         if (!(a2->rn->flags & ANYOF_MATCHES_ALL_ABOVE_BITMAP))
2137             {
2138             U32 right_map;
2139              
2140             /* apparently a special case... */
2141 39 100         if (a2->rn->flags & ANYOF_INVERT)
2142             {
2143 33           return compare_mismatch(anchored, a1, a2);
2144             }
2145              
2146 38           int cr = convert_map(a2, &right_map);
2147 38 50         if (cr == -1)
2148             {
2149 0           return -1;
2150             }
2151              
2152 38 50         if (!cr || !(right_map & left_block))
    100          
2153             {
2154 38           return compare_mismatch(anchored, a1, a2);
2155             }
2156             }
2157              
2158             /* fprintf(stderr, "left flags = %d\n", a1->rn->flags); */
2159              
2160 97 50         if (a1->rn->flags >= SIZEOF_ARRAY(posix_regclass_bitmaps))
2161             {
2162 0           return compare_mismatch(anchored, a1, a2);
2163             }
2164              
2165 97           b = posix_regclass_bitmaps[a1->rn->flags];
2166 97 50         if (!b)
2167             {
2168 0           return compare_mismatch(anchored, a1, a2);
2169             }
2170              
2171 130           return compare_bitmaps(anchored, a1, a2, b, 0);
2172             }
2173              
2174 70           static int compare_negative_posix_anyof(int anchored, Arrow *a1, Arrow *a2)
2175             {
2176             U32 left_block;
2177             unsigned char *b;
2178              
2179             /* fprintf(stderr, "enter compare_negative_posix_anyof\n"); */
2180              
2181             assert((a1->rn->type == NPOSIXD) || (a1->rn->type == NPOSIXU) ||
2182             (a1->rn->type == NPOSIXA));
2183             assert((a2->rn->type == ANYOF) || (a2->rn->type == ANYOFD));
2184              
2185 70 50         if (!convert_class_narrow(a1, &left_block))
2186             {
2187 0           return compare_mismatch(anchored, a1, a2);
2188             }
2189              
2190 70           left_block = EVERY_BLOCK & ~left_block;
2191              
2192             /* fprintf(stderr, "left %d -> 0x%x\n", a1->rn->flags, (unsigned)left_block); */
2193              
2194 70 100         if (!(a2->rn->flags & ANYOF_MATCHES_ALL_ABOVE_BITMAP))
2195             {
2196             U32 right_map;
2197              
2198             /* analogically with compare_posix_anyof but untested */
2199 19 100         if (a2->rn->flags & ANYOF_INVERT)
2200             {
2201 8           return compare_mismatch(anchored, a1, a2);
2202             }
2203              
2204 18           int cr = convert_map(a2, &right_map);
2205 18 50         if (cr == -1)
2206             {
2207 0           return -1;
2208             }
2209              
2210             /* fprintf(stderr, "right map = 0x%x\n", (unsigned)right_map); */
2211              
2212 18 50         if (!cr || !(right_map & left_block))
    100          
2213             {
2214 18           return compare_mismatch(anchored, a1, a2);
2215             }
2216             }
2217              
2218 62 50         if (a1->rn->flags >= SIZEOF_ARRAY(posix_regclass_bitmaps))
2219             {
2220 0           return compare_mismatch(anchored, a1, a2);
2221             }
2222              
2223 62           b = posix_regclass_nbitmaps[a1->rn->flags];
2224 62 50         if (!b)
2225             {
2226 0           return compare_mismatch(anchored, a1, a2);
2227             }
2228              
2229 70           return compare_bitmaps(anchored, a1, a2, b, 0);
2230             }
2231              
2232 609           static int compare_exact_anyof(int anchored, Arrow *a1, Arrow *a2)
2233             {
2234             BitFlag bf;
2235             char *seq;
2236              
2237             /* fprintf(stderr, "enter compare_exact_anyof(%d, \n", anchored); */
2238              
2239             assert(a1->rn->type == EXACT);
2240             assert((a2->rn->type == ANYOF) || (a2->rn->type == ANYOFD));
2241              
2242 609           seq = GET_LITERAL(a1);
2243 609           init_bit_flag(&bf, (unsigned char)(*seq));
2244              
2245 609 100         if (!(get_bitmap_byte(a2->rn, bf.offs) & bf.mask))
2246             {
2247 36           return compare_mismatch(anchored, a1, a2);
2248             }
2249              
2250 609           return compare_tails(anchored, a1, a2);
2251             }
2252              
2253 31           static int compare_exactf_anyof(int anchored, Arrow *a1, Arrow *a2)
2254             {
2255             BitFlag bf;
2256             char *seq;
2257             char unf[2];
2258             int i;
2259              
2260             /* fprintf(stderr, "enter compare_exactf_anyof(%d, \n", anchored); */
2261              
2262             assert((a1->rn->type == EXACTF) || (a1->rn->type == EXACTFU));
2263             assert((a2->rn->type == ANYOF) || (a2->rn->type == ANYOFD));
2264              
2265 31           seq = GET_LITERAL(a1);
2266 31           init_unfolded(unf, *seq);
2267              
2268 92 100         for (i = 0; i < 2; ++i)
2269             {
2270 62           init_bit_flag(&bf, (unsigned char)unf[i]);
2271 62 100         if (!(get_bitmap_byte(a2->rn, bf.offs) & bf.mask))
2272             {
2273 1           return compare_mismatch(anchored, a1, a2);
2274             }
2275             }
2276              
2277 31           return compare_tails(anchored, a1, a2);
2278             }
2279              
2280             #ifdef RC_ANYOFM
2281             static int compare_exact_anyofm(int anchored, Arrow *a1, Arrow *a2)
2282             {
2283             char *seq;
2284             unsigned char right[ANYOF_BITMAP_SIZE];
2285             BitFlag bf;
2286              
2287             /* fprintf(stderr, "enter compare_exact_anyofm(%d, \n", anchored); */
2288              
2289             assert(a1->rn->type == EXACT);
2290             assert(a2->rn->type == ANYOFM);
2291              
2292             seq = GET_LITERAL(a1);
2293             init_bit_flag(&bf, *seq);
2294              
2295             if (!convert_anyofm_to_bitmap(a2, right))
2296             {
2297             return compare_mismatch(anchored, a1, a2);
2298             }
2299              
2300             if (right[bf.offs] & bf.mask)
2301             {
2302             return compare_tails(anchored, a1, a2);
2303             }
2304            
2305             return compare_mismatch(anchored, a1, a2);
2306             }
2307              
2308             static int compare_exactf_anyofm(int anchored, Arrow *a1, Arrow *a2)
2309             {
2310             char *seq;
2311             int i;
2312             char left[2];
2313             unsigned char right[ANYOF_BITMAP_SIZE];
2314             BitFlag bf;
2315              
2316             /* fprintf(stderr, "enter compare_exactf_anyofm(%d, \n", anchored); */
2317              
2318             assert((a1->rn->type == EXACTF) || (a1->rn->type == EXACTFU));
2319             assert(a2->rn->type == ANYOFM);
2320              
2321             seq = GET_LITERAL(a1);
2322             init_unfolded(left, *seq);
2323              
2324             if (!convert_anyofm_to_bitmap(a2, right))
2325             {
2326             return compare_mismatch(anchored, a1, a2);
2327             }
2328              
2329             for (i = 0; i < 2; ++i)
2330             {
2331             init_bit_flag(&bf, left[i]);
2332             if (!(right[bf.offs] & bf.mask))
2333             {
2334             return compare_mismatch(anchored, a1, a2);
2335             }
2336             }
2337            
2338             return compare_tails(anchored, a1, a2);
2339             }
2340             #endif
2341              
2342 604           static int compare_exact_byte_class(int anchored, Arrow *a1, Arrow *a2,
2343             char *lookup)
2344             {
2345             char *seq;
2346              
2347             assert((a1->rn->type == EXACT) || (a1->rn->type == EXACTF) || (a1->rn->type == EXACTFU));
2348              
2349 604           seq = GET_LITERAL(a1);
2350              
2351 604 100         if (!lookup[(unsigned char)(*seq)])
2352             {
2353 30           return compare_mismatch(anchored, a1, a2);
2354             }
2355              
2356 574           return compare_tails(anchored, a1, a2);
2357             }
2358              
2359 30           static int compare_exact_multiline(int anchored, Arrow *a1, Arrow *a2)
2360             {
2361             assert((a1->rn->type == EXACT) || (a1->rn->type == EXACTF) ||
2362             (a1->rn->type == EXACTFU));
2363             assert((a2->rn->type == MBOL) || (a2->rn->type == MEOL));
2364              
2365 30           return compare_exact_byte_class(anchored, a1, a2,
2366             ndot.lookup);
2367             }
2368              
2369 8           static int compare_sany_anyof(int anchored, Arrow *a1, Arrow *a2)
2370             {
2371             /* fprintf(stderr, "enter compare_sany_anyof\n"); */
2372              
2373             assert(a1->rn->type == SANY);
2374             assert((a2->rn->type == ANYOF) || (a2->rn->type == ANYOFD));
2375              
2376             /* fprintf(stderr, "left flags = 0x%x, right flags = 0x%x\n",
2377             a1->rn->flags, a2->rn->flags); */
2378              
2379 8 100         if (a2->rn->flags & ANYOF_MATCHES_ALL_ABOVE_BITMAP)
2380             {
2381 2           return compare_right_full(anchored, a1, a2);
2382             }
2383              
2384 6           return compare_mismatch(anchored, a1, a2);
2385             }
2386              
2387 48           static int compare_anyof_reg_any(int anchored, Arrow *a1, Arrow *a2)
2388             {
2389             assert((a1->rn->type == ANYOF) || (a1->rn->type == ANYOFD));
2390             assert(a2->rn->type == REG_ANY);
2391              
2392 48           return compare_bitmaps(anchored, a1, a2, 0, ndot.nbitmap);
2393             }
2394              
2395             #ifdef RC_ANYOFM
2396             static int compare_anyofm_reg_any(int anchored, Arrow *a1, Arrow *a2)
2397             {
2398             unsigned char left[ANYOF_BITMAP_SIZE];
2399            
2400             assert(a1->rn->type == ANYOFM);
2401             assert(a2->rn->type == REG_ANY);
2402              
2403             if (!convert_anyofm_to_bitmap(a1, left))
2404             {
2405             return compare_mismatch(anchored, a1, a2);
2406             }
2407              
2408             return compare_bitmaps(anchored, a1, a2, left, ndot.nbitmap);
2409             }
2410             #endif
2411            
2412 574           static int compare_exact_reg_any(int anchored, Arrow *a1, Arrow *a2)
2413             {
2414             assert((a1->rn->type == EXACT) || (a1->rn->type == EXACTF) || (a1->rn->type == EXACTFU));
2415             assert(a2->rn->type == REG_ANY);
2416              
2417 574           return compare_exact_byte_class(anchored, a1, a2, ndot.nlookup);
2418             }
2419              
2420 54           static int compare_anyof_posix(int anchored, Arrow *a1, Arrow *a2)
2421             {
2422             unsigned char *b;
2423              
2424             /* fprintf(stderr, "enter compare_anyof_posix\n"); */
2425              
2426             assert((a1->rn->type == ANYOF) || (a1->rn->type == ANYOFD));
2427             assert((a2->rn->type == POSIXD) || (a2->rn->type == POSIXU) || (a2->rn->type == POSIXA));
2428              
2429 54 50         if (a2->rn->flags >= SIZEOF_ARRAY(posix_regclass_bitmaps))
2430             {
2431             /* fprintf(stderr, "flags = %d\n", a2->rn->flags); */
2432 0           return compare_mismatch(anchored, a1, a2);
2433             }
2434              
2435 54           b = posix_regclass_bitmaps[a2->rn->flags];
2436 54 50         if (!b)
2437             {
2438             /* fprintf(stderr, "no bitmap for flags = %d\n", a2->rn->flags); */
2439 0           return compare_mismatch(anchored, a1, a2);
2440             }
2441              
2442 54           return compare_bitmaps(anchored, a1, a2, 0, b);
2443             }
2444              
2445             #ifdef RC_ANYOFM
2446             static int compare_anyofm_posix(int anchored, Arrow *a1, Arrow *a2)
2447             {
2448             unsigned char *b;
2449             unsigned char left[ANYOF_BITMAP_SIZE];
2450            
2451             /* fprintf(stderr, "enter compare_anyofm_posix\n"); */
2452              
2453             assert(a1->rn->type == ANYOFM);
2454             assert((a2->rn->type == POSIXD) || (a2->rn->type == POSIXU) || (a2->rn->type == POSIXA));
2455              
2456             if (!convert_anyofm_to_bitmap(a1, left))
2457             {
2458             return compare_mismatch(anchored, a1, a2);
2459             }
2460            
2461             b = posix_regclass_bitmaps[a2->rn->flags];
2462             if (!b)
2463             {
2464             return compare_mismatch(anchored, a1, a2);
2465             }
2466            
2467             return compare_bitmaps(anchored, a1, a2, left, b);
2468             }
2469             #endif
2470              
2471 7           static int compare_anyof_posixa(int anchored, Arrow *a1, Arrow *a2)
2472             {
2473             unsigned char *b;
2474              
2475             /* fprintf(stderr, "enter compare_anyof_posixa\n"); */
2476              
2477             assert((a1->rn->type == ANYOF) || (a1->rn->type == ANYOFD));
2478             assert(a2->rn->type == POSIXA);
2479              
2480 7 100         if (ANYOF_FLAGS(a1->rn) & ANYOF_SHARED_d_UPPER_LATIN1_UTF8_STRING_MATCHES_non_d_RUNTIME_USER_PROP)
2481             {
2482 1           return compare_mismatch(anchored, a1, a2);
2483             }
2484              
2485 6 50         if (a2->rn->flags >= SIZEOF_ARRAY(posix_regclass_bitmaps))
2486             {
2487             /* fprintf(stderr, "flags = %d\n", a2->rn->flags); */
2488 0           return compare_mismatch(anchored, a1, a2);
2489             }
2490              
2491 6           b = posix_regclass_bitmaps[a2->rn->flags];
2492 6 50         if (!b)
2493             {
2494             /* fprintf(stderr, "no bitmap for flags = %d\n", a2->rn->flags); */
2495 0           return compare_mismatch(anchored, a1, a2);
2496             }
2497              
2498 6           return compare_bitmaps(anchored, a1, a2, 0, b);
2499             }
2500              
2501 50           static int compare_anyof_negative_posix(int anchored, Arrow *a1, Arrow *a2)
2502             {
2503             unsigned char *b;
2504              
2505             /* fprintf(stderr, "enter compare_anyof_negative_posix\n"); */
2506              
2507             assert((a1->rn->type == ANYOF) || (a1->rn->type == ANYOFD));
2508             assert((a2->rn->type == NPOSIXD) || (a2->rn->type == NPOSIXU) ||
2509             (a2->rn->type == NPOSIXA));
2510              
2511 50 50         if (a2->rn->flags >= SIZEOF_ARRAY(posix_regclass_nbitmaps))
2512             {
2513             /* fprintf(stderr, "flags = %d\n", a2->rn->flags); */
2514 0           return compare_mismatch(anchored, a1, a2);
2515             }
2516              
2517 50           b = posix_regclass_nbitmaps[a2->rn->flags];
2518 50 50         if (!b)
2519             {
2520             /* fprintf(stderr, "no negative bitmap for flags = %d\n", a2->rn->flags); */
2521 0           return compare_mismatch(anchored, a1, a2);
2522             }
2523              
2524 50           return compare_bitmaps(anchored, a1, a2, 0, b);
2525             }
2526              
2527             #ifdef RC_ANYOFM
2528             static int compare_anyofm_negative_posix(int anchored, Arrow *a1, Arrow *a2)
2529             {
2530             unsigned char *posix_bitmap;
2531             unsigned char anyof_bitmap[ANYOF_BITMAP_SIZE];
2532              
2533             /* fprintf(stderr, "enter compare_anyofm_negative_posix\n"); */
2534              
2535             assert(a1->rn->type == ANYOFM);
2536             assert((a2->rn->type == NPOSIXD) || (a2->rn->type == NPOSIXU) ||
2537             (a2->rn->type == NPOSIXA));
2538              
2539             if (!convert_anyofm_to_bitmap(a1, anyof_bitmap))
2540             {
2541             return compare_mismatch(anchored, a1, a2);
2542             }
2543              
2544             if (a2->rn->flags >= SIZEOF_ARRAY(posix_regclass_nbitmaps))
2545             {
2546             /* fprintf(stderr, "flags = %d\n", a2->rn->flags); */
2547             return compare_mismatch(anchored, a1, a2);
2548             }
2549              
2550             posix_bitmap = posix_regclass_nbitmaps[a2->rn->flags];
2551             if (!posix_bitmap)
2552             {
2553             /* fprintf(stderr, "no negative bitmap for flags = %d\n", a2->rn->flags); */
2554             return compare_mismatch(anchored, a1, a2);
2555             }
2556              
2557             return compare_bitmaps(anchored, a1, a2, anyof_bitmap, posix_bitmap);
2558             }
2559             #endif
2560              
2561 248           static int compare_posix_reg_any(int anchored, Arrow *a1, Arrow *a2)
2562             {
2563             assert((a1->rn->type == POSIXD) || (a1->rn->type == POSIXU) ||
2564             (a1->rn->type == POSIXA));
2565             assert(a2->rn->type == REG_ANY);
2566              
2567 248           U8 flags = a1->rn->flags;
2568 248 50         if (flags >= SIZEOF_ARRAY(newline_posix_regclasses))
2569             {
2570             /* fprintf(stderr, "unknown POSIX character class %d\n", flags); */
2571 0           rc_error = "unknown POSIX character class";
2572 0           return -1;
2573             }
2574              
2575 248 100         if (newline_posix_regclasses[flags])
2576             {
2577 54           return compare_mismatch(anchored, a1, a2);
2578             }
2579              
2580 194           return compare_tails(anchored, a1, a2);
2581             }
2582              
2583 125           static int compare_negative_posix_reg_any(int anchored, Arrow *a1, Arrow *a2)
2584             {
2585             assert((a1->rn->type == NPOSIXD) || (a1->rn->type == NPOSIXU) ||
2586             (a1->rn->type == NPOSIXA));
2587             assert(a2->rn->type == REG_ANY);
2588              
2589 125           U8 flags = a1->rn->flags;
2590 125 50         if (flags >= SIZEOF_ARRAY(newline_posix_regclasses))
2591             {
2592 0           rc_error = "unknown negative POSIX character class";
2593 0           return -1;
2594             }
2595              
2596 125 100         if (!newline_posix_regclasses[flags])
2597             {
2598 82           return compare_mismatch(anchored, a1, a2);
2599             }
2600              
2601 43           return compare_tails(anchored, a1, a2);
2602             }
2603              
2604 5           static int compare_anyof_exact(int anchored, Arrow *a1, Arrow *a2)
2605             {
2606             BitFlag bf;
2607             char *seq;
2608             int i;
2609             unsigned char req;
2610              
2611             assert((a1->rn->type == ANYOF) || (a1->rn->type == ANYOFD));
2612             assert(a2->rn->type == EXACT);
2613              
2614 5 50         if (a1->rn->flags & ANYOF_MATCHES_ALL_ABOVE_BITMAP)
2615             {
2616 0           return compare_mismatch(anchored, a1, a2);
2617             }
2618              
2619 5           seq = GET_LITERAL(a2);
2620 5           init_bit_flag(&bf, *((unsigned char *)seq));
2621              
2622 41 50         for (i = 0; i < ANYOF_BITMAP_SIZE; ++i)
2623             {
2624 41 100         req = (i != bf.offs) ? 0 : bf.mask;
2625 41 100         if (get_bitmap_byte(a1->rn, i) != req)
2626             {
2627 5           return compare_mismatch(anchored, a1, a2);
2628             }
2629             }
2630              
2631 5           return compare_tails(anchored, a1, a2);
2632             }
2633              
2634             #ifdef RC_ANYOFM
2635             static int compare_anyofm_exact(int anchored, Arrow *a1, Arrow *a2)
2636             {
2637             unsigned char left[ANYOF_BITMAP_SIZE];
2638             BitFlag bf;
2639             char *seq;
2640             int i;
2641             unsigned char req;
2642              
2643             assert(a1->rn->type == ANYOFM);
2644             assert(a2->rn->type == EXACT);
2645              
2646             if (!convert_anyofm_to_bitmap(a1, left))
2647             {
2648             return compare_mismatch(anchored, a1, a2);
2649             }
2650            
2651             seq = GET_LITERAL(a2);
2652             init_bit_flag(&bf, *((unsigned char *)seq));
2653              
2654             for (i = 0; i < ANYOF_BITMAP_SIZE; ++i)
2655             {
2656             req = (i != bf.offs) ? 0 : bf.mask;
2657             if (left[i] != req)
2658             {
2659             return compare_mismatch(anchored, a1, a2);
2660             }
2661             }
2662              
2663             return compare_tails(anchored, a1, a2);
2664             }
2665             #endif
2666              
2667 15           static int compare_anyof_exactf(int anchored, Arrow *a1, Arrow *a2)
2668             {
2669             char *seq;
2670             char unf[2];
2671             BitFlag bf[2];
2672             unsigned char right[ANYOF_BITMAP_SIZE];
2673             int i;
2674              
2675             assert((a1->rn->type == ANYOF) || (a1->rn->type == ANYOFD));
2676             assert((a2->rn->type == EXACTF) || (a2->rn->type == EXACTFU));
2677              
2678 15 50         if (a1->rn->flags & ANYOF_MATCHES_ALL_ABOVE_BITMAP)
2679             {
2680 0           return compare_mismatch(anchored, a1, a2);
2681             }
2682              
2683 15           seq = GET_LITERAL(a2);
2684 15           init_unfolded(unf, *seq);
2685              
2686 45 100         for (i = 0; i < 2; ++i)
2687             {
2688 30           init_bit_flag(bf + i, (unsigned char)(unf[i]));
2689             }
2690              
2691 15 50         if (bf[0].offs == bf[1].offs)
2692             {
2693 0           bf[0].mask = bf[1].mask = bf[0].mask | bf[1].mask;
2694             }
2695              
2696 15           memset(right, 0, ANYOF_BITMAP_SIZE);
2697 45 100         for (i = 0; i < 2; ++i)
2698             {
2699 30           right[bf[i].offs] = bf[i].mask;
2700             }
2701              
2702 15           return compare_bitmaps(anchored, a1, a2, 0, right);
2703             }
2704              
2705             #ifdef RC_ANYOFM
2706             static int compare_anyofm_exactf(int anchored, Arrow *a1, Arrow *a2)
2707             {
2708             char *seq;
2709             int i;
2710             BitFlag bf;
2711             unsigned char left[ANYOF_BITMAP_SIZE];
2712             unsigned char right[ANYOF_BITMAP_SIZE];
2713             char unf[2];
2714              
2715             /* fprintf(stderr, "enter compare_anyofm_exactf(%d, \n", anchored); */
2716              
2717             assert(a1->rn->type == ANYOFM);
2718             assert((a2->rn->type == EXACTF) || (a2->rn->type == EXACTFU));
2719              
2720             if (!convert_anyofm_to_bitmap(a1, left))
2721             {
2722             return compare_mismatch(anchored, a1, a2);
2723             }
2724              
2725             seq = GET_LITERAL(a2);
2726             init_unfolded(unf, *seq);
2727              
2728             memset(right, 0, ANYOF_BITMAP_SIZE);
2729             for (i = 0; i < 2; ++i)
2730             {
2731             init_bit_flag(&bf, unf[i]);
2732             right[bf.offs] = bf.mask;
2733             }
2734            
2735             return compare_bitmaps(anchored, a1, a2, left, right);
2736             }
2737             #endif
2738            
2739 6605           static int compare_exact_exact(int anchored, Arrow *a1, Arrow *a2)
2740             {
2741             char *q1, *q2;
2742              
2743             assert(a1->rn->type == EXACT);
2744             assert(a2->rn->type == EXACT);
2745              
2746 6605           q1 = GET_LITERAL(a1);
2747 6605           q2 = GET_LITERAL(a2);
2748              
2749             /* fprintf(stderr, "compare_exact_exact(%d, '%c', '%c')\n", anchored,
2750             *q1, *q2); */
2751              
2752 6605 100         if (*q1 != *q2)
2753             {
2754 2531           return compare_mismatch(anchored, a1, a2);
2755             }
2756              
2757 4074           return compare_tails(anchored, a1, a2);
2758             }
2759              
2760 88           static int compare_exact_exactf(int anchored, Arrow *a1, Arrow *a2)
2761             {
2762             char *q1, *q2;
2763             char unf[2];
2764              
2765             assert(a1->rn->type == EXACT);
2766             assert((a2->rn->type == EXACTF) || (a2->rn->type == EXACTFU));
2767              
2768 88           q1 = GET_LITERAL(a1);
2769 88           q2 = GET_LITERAL(a2);
2770 88           init_unfolded(unf, *q2);
2771              
2772 88 100         if ((*q1 != unf[0]) && (*q1 != unf[1]))
    100          
2773             {
2774 6           return compare_mismatch(anchored, a1, a2);
2775             }
2776              
2777 88           return compare_tails(anchored, a1, a2);
2778             }
2779              
2780 27           static int compare_exactf_exact(int anchored, Arrow *a1, Arrow *a2)
2781             {
2782             char *q1, *q2;
2783             char unf[2];
2784              
2785             assert((a1->rn->type == EXACTF) || (a1->rn->type == EXACTFU));
2786             assert(a2->rn->type == EXACT);
2787              
2788 27           q1 = GET_LITERAL(a1);
2789 27           init_unfolded(unf, *q1);
2790 27           q2 = GET_LITERAL(a2);
2791              
2792 27 100         if ((unf[0] != *q2) || (unf[1] != *q2))
    100          
2793             {
2794 26           return compare_mismatch(anchored, a1, a2);
2795             }
2796              
2797 27           return compare_tails(anchored, a1, a2);
2798             }
2799              
2800 470           static int compare_exactf_exactf(int anchored, Arrow *a1, Arrow *a2)
2801             {
2802             char *q1, *q2;
2803             char l1, l2;
2804              
2805             assert((a1->rn->type == EXACTF) || (a1->rn->type == EXACTFU));
2806             assert((a2->rn->type == EXACTF) || (a2->rn->type == EXACTFU));
2807              
2808 470           q1 = GET_LITERAL(a1);
2809 470           q2 = GET_LITERAL(a2);
2810              
2811 470 100         l1 = TOLOWER(*q1);
    100          
2812 470 100         l2 = TOLOWER(*q2);
    100          
2813              
2814 470 100         if (l1 != l2)
2815             {
2816 49           return compare_mismatch(anchored, a1, a2);
2817             }
2818              
2819 421           return compare_tails(anchored, a1, a2);
2820             }
2821              
2822 604           static int compare_left_branch(int anchored, Arrow *a1, Arrow *a2)
2823             {
2824             int rv, tsz;
2825             regnode *p1;
2826             Arrow left, right;
2827              
2828             /* fprintf(stderr, "enter compare_left_branch\n"); */
2829              
2830             assert(a1->rn->type == BRANCH);
2831              
2832             /* origins stay the same throughout the cycle */
2833 604           left.origin = a1->origin;
2834 604           right.origin = a2->origin;
2835 604           p1 = a1->rn;
2836 1798 100         while (p1->type == BRANCH)
2837             {
2838 1231 50         if (p1->next_off == 0)
2839             {
2840 0           rc_error = "Branch with zero offset";
2841 0           return -1;
2842             }
2843              
2844 1231           left.rn = p1 + 1;
2845 1231           left.spent = 0;
2846              
2847 1231           right.rn = a2->rn;
2848 1231           right.spent = a2->spent;
2849              
2850 1231           rv = compare(anchored, &left, &right);
2851             /* fprintf(stderr, "rv = %d\n", rv); */
2852              
2853 1231 50         if (rv < 0)
2854             {
2855 0           return rv;
2856             }
2857              
2858 1231 100         if (!rv)
2859             {
2860             /* fprintf(stderr, "compare_left_branch doesn't match\n"); */
2861 37           return compare_mismatch(anchored, a1, a2);
2862             }
2863              
2864 1194           p1 += p1->next_off;
2865             }
2866              
2867 567           a1->rn = p1;
2868 567           a1->spent = 0;
2869              
2870 567           tsz = get_size(a2->rn);
2871 567 50         if (tsz <= 0)
2872             {
2873 0           return -1;
2874             }
2875              
2876 567           a2->rn += tsz - 1;
2877 567           a2->spent = 0;
2878              
2879 604           return 1;
2880             }
2881              
2882 17           static int compare_set(int anchored, Arrow *a1, Arrow *a2, unsigned char *b1)
2883             {
2884             regnode *alt, *t1;
2885             Arrow left, right;
2886             int i, j, power, rv, sz, offs;
2887             unsigned char loc;
2888              
2889 17 50         offs = GET_OFFSET(a1->rn);
2890 17 50         if (offs <= 0)
2891             {
2892 0           return -1;
2893             }
2894              
2895 17           t1 = a1->rn + offs;
2896 17           sz = get_size(t1);
2897 17 50         if (sz < 0)
2898             {
2899 0           return sz;
2900             }
2901              
2902 17           alt = (regnode *)malloc(sizeof(regnode) * (2 + sz));
2903 17 50         if (!alt)
2904             {
2905 0           rc_error = "Couldn't allocate memory for alternative copy";
2906 0           return -1;
2907             }
2908              
2909 17           alt[0].flags = 1;
2910 17           alt[0].type = EXACT;
2911 17           alt[0].next_off = 2;
2912 17           memcpy(alt + 2, t1, sizeof(regnode) * sz);
2913              
2914 17           left.origin = a1->origin;
2915 17           right.origin = a2->origin;
2916 17           right.rn = 0;
2917              
2918 541 100         for (i = 0; i < ANYOF_BITMAP_SIZE; ++i)
2919             {
2920 525           power = 1;
2921 4720 100         for (j = 0; j < 8; ++j)
2922             {
2923 4196 50         loc = b1 ? b1[i] : get_bitmap_byte(a1->rn, i);
2924 4196 100         if (loc & power)
2925             {
2926 210           alt[1].flags = 8 * i + j;
2927 210           left.rn = alt;
2928 210           left.spent = 0;
2929              
2930 210           right.rn = a2->rn;
2931 210           right.spent = a2->spent;
2932              
2933 210           rv = compare_right_branch(anchored, &left, &right);
2934 210 50         if (rv < 0)
2935             {
2936 0           free(alt);
2937 0           return rv;
2938             }
2939              
2940 210 100         if (!rv)
2941             {
2942 1           free(alt);
2943 1           return compare_mismatch(anchored, a1, a2);
2944             }
2945             }
2946              
2947 4195           power *= 2;
2948             }
2949             }
2950              
2951 16           free(alt);
2952              
2953 16 50         if (!right.rn)
2954             {
2955 0           rc_error = "Empty mask not supported";
2956 0           return -1;
2957             }
2958              
2959 16           a1->rn = t1 + sz - 1;
2960             assert(a1->rn->type == END);
2961 16           a1->spent = 0;
2962              
2963 16           a2->rn = right.rn;
2964 16           a2->spent = right.spent;
2965              
2966 17           return 1;
2967             }
2968              
2969 17           static int compare_anyof_branch(int anchored, Arrow *a1, Arrow *a2)
2970             {
2971             assert((a1->rn->type == ANYOF) || (a1->rn->type == ANYOFD));
2972             assert(a2->rn->type == BRANCH);
2973            
2974 17           return compare_set(anchored, a1, a2, 0);
2975             }
2976              
2977             #ifdef RC_ANYOFM
2978             static int compare_anyofm_branch(int anchored, Arrow *a1, Arrow *a2)
2979             {
2980             unsigned char left[ANYOF_BITMAP_SIZE];
2981            
2982             assert(a1->rn->type == ANYOFM);
2983             assert(a2->rn->type == BRANCH);
2984              
2985             if (!convert_anyofm_to_bitmap(a1, left))
2986             {
2987             return compare_mismatch(anchored, a1, a2);
2988             }
2989            
2990             return compare_set(anchored, a1, a2, left);
2991             }
2992             #endif
2993              
2994 1412           static int compare_right_branch(int anchored, Arrow *a1, Arrow *a2)
2995             {
2996             int rv;
2997             regnode *p2;
2998             Arrow left, right;
2999              
3000             /* fprintf(stderr, "enter compare_right_branch\n"); */
3001              
3002             assert(a2->rn->type == BRANCH);
3003              
3004             /* origins stay the same throughout the cycle */
3005 1412           left.origin = a1->origin;
3006 1412           right.origin = a2->origin;
3007 1412           p2 = a2->rn;
3008 1412           rv = 0;
3009 3697 100         while ((p2->type == BRANCH) && !rv)
    100          
3010             {
3011             /* fprintf(stderr, "p2->type = %d\n", p2->type); */
3012              
3013 2285           left.rn = a1->rn;
3014 2285           left.spent = a1->spent;
3015              
3016 2285 50         if (p2->next_off == 0)
3017             {
3018 0           rc_error = "Branch with offset zero";
3019 0           return -1;
3020             }
3021              
3022 2285           right.rn = p2 + 1;
3023 2285           right.spent = 0;
3024              
3025 2285           rv = compare(anchored, &left, &right);
3026             /* fprintf(stderr, "got %d\n", rv); */
3027              
3028 2285           p2 += p2->next_off;
3029             }
3030              
3031 1412 50         if (rv < 0)
3032             {
3033 0           return rv;
3034             }
3035              
3036 1412 100         if (!rv)
3037             {
3038 132           return compare_mismatch(anchored, a1, a2);
3039             }
3040              
3041 1280           a1->rn = left.rn;
3042 1280           a1->spent = left.spent;
3043              
3044 1280           a2->rn = right.rn;
3045 1280           a2->spent = right.spent;
3046              
3047 1412           return 1;
3048             }
3049              
3050 399           static int compare_right_star(int anchored, Arrow *a1, Arrow *a2)
3051             {
3052             regnode *p2;
3053             Arrow left, right;
3054             int sz, rv, offs;
3055              
3056             /* fprintf(stderr, "enter compare_right_star\n"); */
3057              
3058 399           p2 = a2->rn;
3059             assert(p2->type == STAR);
3060              
3061 399           sz = get_size(p2);
3062 399 50         if (sz < 0)
3063             {
3064 0           return sz;
3065             }
3066              
3067 399           left.origin = a1->origin;
3068 399           left.rn = a1->rn;
3069 399           left.spent = a1->spent;
3070              
3071 399 50         offs = GET_OFFSET(p2);
3072 399 50         if (offs <= 0)
3073             {
3074 0           return -1;
3075             }
3076              
3077 399           right.origin = a2->origin;
3078 399           right.rn = p2 + offs;
3079 399           right.spent = 0;
3080              
3081 399           rv = compare(anchored, &left, &right);
3082 399 50         if (rv < 0)
3083             {
3084 0           return rv;
3085             }
3086              
3087 399 100         if (rv == 0)
3088             {
3089 9           right.rn = p2 + 1;
3090 9           right.spent = 0;
3091              
3092 9           rv = compare(anchored, a1, &right);
3093 9 50         if (rv < 0)
3094             {
3095 0           return rv;
3096             }
3097              
3098 9 100         if (!rv)
3099             {
3100 4           return compare_mismatch(anchored, a1, a2);
3101             }
3102              
3103 5           right.rn = p2;
3104 5           right.spent = 0;
3105              
3106 5 50         if (!anchored)
3107             {
3108 0           rv = compare_right_star(1, a1, &right);
3109             }
3110             }
3111              
3112 395 50         if (rv <= 0)
3113             {
3114 0           return rv;
3115             }
3116              
3117 395           a2->rn += sz - 1;
3118             assert(a2->rn->type == END);
3119 395           a2->spent = 0;
3120              
3121 399           return rv;
3122             }
3123              
3124 131           static int compare_plus_plus(int anchored, Arrow *a1, Arrow *a2)
3125             {
3126             regnode *p1, *p2;
3127             Arrow left, right;
3128             int rv, offs;
3129              
3130 131           p1 = a1->rn;
3131             assert(p1->type == PLUS);
3132 131           p2 = a2->rn;
3133             assert(p2->type == PLUS);
3134              
3135 131           left.origin = a1->origin;
3136 131           left.rn = p1 + 1;
3137 131           left.spent = 0;
3138              
3139 131           right.origin = a2->origin;
3140 131           right.rn = p2 + 1;
3141 131           right.spent = 0;
3142              
3143 131           rv = compare(1, &left, &right);
3144 131 100         if (rv)
3145             {
3146 118           return rv;
3147             }
3148              
3149 13 50         offs = GET_OFFSET(p1);
3150             /* fprintf(stderr, "offs = %d\n", offs); */
3151 13 50         if (offs <= 0)
3152             {
3153 0           return -1;
3154             }
3155              
3156 13           left.origin = a1->origin;
3157 13           left.rn = p1 + offs;
3158 13           left.spent = 0;
3159 131           return compare(1, &left, a2);
3160             }
3161              
3162 155           static int compare_repeat_star(int anchored, Arrow *a1, Arrow *a2)
3163             {
3164             regnode *p1, *p2;
3165             Arrow left, right;
3166             int rv, offs;
3167              
3168 155           p1 = a1->rn;
3169             assert((p1->type == PLUS) || (p1->type == STAR));
3170 155           p2 = a2->rn;
3171             assert(p2->type == STAR);
3172             /* fprintf(stderr, "enter compare_repeat_star(%d, %d, %d)\n",
3173             anchored, p1->type, p2->type); */
3174              
3175 155           left.origin = a1->origin;
3176 155           left.rn = p1 + 1;
3177 155           left.spent = 0;
3178              
3179 155           right.origin = a2->origin;
3180 155           right.rn = p2 + 1;
3181 155           right.spent = 0;
3182              
3183 155           rv = compare(1, &left, &right);
3184             /* fprintf(stderr, "inclusive compare returned %d\n", rv); */
3185 155 100         if (rv)
3186             {
3187 139           return rv;
3188             }
3189              
3190 16 50         offs = GET_OFFSET(p2);
3191             /* fprintf(stderr, "offs = %d\n", offs); */
3192 16 50         if (offs <= 0)
3193             {
3194 0           return -1;
3195             }
3196              
3197 16           right.origin = a2->origin;
3198 16           right.rn = p2 + offs;
3199 16           right.spent = 0;
3200 155           return compare(1, &left, &right);
3201             }
3202              
3203 301           static int compare_right_curly_from_zero(int anchored, Arrow *a1, Arrow *a2)
3204             {
3205             regnode *p2, *alt;
3206             short n, *cnt;
3207             Arrow left, right;
3208             int sz, rv, offs;
3209              
3210 301           p2 = a2->rn;
3211              
3212 301           n = ((short *)(p2 + 1))[1];
3213 301 50         if (n <= 0)
3214             {
3215 0           rc_error = "Curly must have positive maximum";
3216 0           return -1;
3217             }
3218              
3219 301           sz = get_size(p2);
3220 301 50         if (sz < 0)
3221             {
3222 0           return sz;
3223             }
3224              
3225 301           left.origin = a1->origin;
3226 301           left.rn = a1->rn;
3227 301           left.spent = a1->spent;
3228              
3229 301 50         offs = GET_OFFSET(p2);
3230 301 50         if (offs <= 0)
3231             {
3232 0           return -1;
3233             }
3234              
3235 301           right.origin = a2->origin;
3236 301           right.rn = p2 + offs;
3237 301           right.spent = 0;
3238              
3239 301           rv = compare(anchored, &left, &right);
3240 301 50         if (rv < 0)
3241             {
3242 0           return rv;
3243             }
3244              
3245 301 100         if (rv == 0)
3246             {
3247 4           alt = alloc_alt(p2, sz);
3248 4 50         if (!alt)
3249             {
3250 0           return -1;
3251             }
3252              
3253 4           right.rn = alt + 2;
3254 4           right.spent = 0;
3255              
3256 4           rv = compare(anchored, a1, &right);
3257 4 50         if (rv < 0)
3258             {
3259 0           free(alt);
3260 0           return rv;
3261             }
3262              
3263 4 100         if (!rv)
3264             {
3265 2           free(alt);
3266 2           return compare_mismatch(anchored, a1, a2);
3267             }
3268              
3269 2           cnt = (short *)(alt + 1);
3270 2 50         if (cnt[1] < INFINITE_COUNT)
3271             {
3272 2           --cnt[1];
3273             }
3274              
3275 2 100         if ((cnt[1] > 0) && !anchored)
    50          
3276             {
3277 0           right.rn = alt;
3278 0           right.spent = 0;
3279              
3280 0           rv = compare_right_curly_from_zero(1, a1, &right);
3281             }
3282             else
3283             {
3284 2           rv = 1;
3285             }
3286              
3287 2           free(alt);
3288             }
3289              
3290 299 50         if (rv <= 0)
3291             {
3292 0           return rv;
3293             }
3294              
3295 299           a2->rn += sz - 1;
3296             assert(a2->rn->type == END);
3297 299           a2->spent = 0;
3298              
3299 301           return rv;
3300             }
3301              
3302 489           static int compare_left_plus(int anchored, Arrow *a1, Arrow *a2)
3303             {
3304             regnode *p1, *alt, *q;
3305             Arrow left, right;
3306             int sz, rv, offs, end_offs;
3307             unsigned char orig_type;
3308              
3309 489           p1 = a1->rn;
3310             assert(p1->type == PLUS);
3311              
3312 489           sz = get_size(p1);
3313 489 50         if (sz < 0)
3314             {
3315 0           return -1;
3316             }
3317              
3318 489 50         if (sz < 2)
3319             {
3320 0           rc_error = "Left plus offset too small";
3321 0           return -1;
3322             }
3323              
3324 489           alt = alloc_alt(p1 + 1, sz - 1);
3325 489 50         if (!alt)
3326             {
3327 0           return -1;
3328             }
3329              
3330 489 100         if (anchored)
3331             {
3332 14           offs = get_jump_offset(p1);
3333 14 50         if (offs <= 0)
3334             {
3335 0           return -1;
3336             }
3337              
3338 14           q = p1 + offs;
3339 14 100         if (q->type != END)
3340             {
3341             /* repeat with a tail after it can be more strict than a
3342             fixed-length match only if the tail is at least as
3343             strict as the repeated regexp */
3344 6           left.origin = a1->origin;
3345 6           left.rn = q;
3346 6           left.spent = 0;
3347              
3348 6           end_offs = offs - 1;
3349 6           orig_type = alt[end_offs].type;
3350 6           alt[end_offs].type = END;
3351              
3352 6           right.origin = a2->origin;
3353 6           right.rn = alt;
3354 6           right.spent = 0;
3355              
3356             /* fprintf(stderr, "comparing %d to %d\n", left.rn->type,
3357             right.rn->type); */
3358 6           rv = compare(1, &left, &right);
3359             /* fprintf(stderr, "compare returned %d\n", rv); */
3360 6 100         if (rv <= 0)
3361             {
3362 4           free(alt);
3363 4           return rv;
3364             }
3365              
3366 2           alt[end_offs].type = orig_type;
3367             }
3368             }
3369              
3370 485           left.origin = a1->origin;
3371 485           left.rn = alt;
3372 485           left.spent = 0;
3373 485           rv = compare(anchored, &left, a2);
3374 485           free(alt);
3375 489           return rv;
3376             }
3377              
3378 267           static int compare_right_plus(int anchored, Arrow *a1, Arrow *a2)
3379             {
3380             regnode *p2;
3381             Arrow right;
3382             int sz, rv;
3383              
3384 267           p2 = a2->rn;
3385             assert(p2->type == PLUS);
3386              
3387             /* fprintf(stderr, "enter compare_right_plus\n"); */
3388              
3389 267           sz = get_size(p2);
3390 267 50         if (sz < 0)
3391             {
3392 0           return -1;
3393             }
3394              
3395 267 50         if (sz < 2)
3396             {
3397 0           rc_error = "Plus offset too small";
3398 0           return -1;
3399             }
3400              
3401             /* fprintf(stderr, "sz = %d\n", sz); */
3402              
3403 267           right.origin = a2->origin;
3404 267           right.rn = p2 + 1;
3405 267           right.spent = 0;
3406              
3407 267           rv = compare(anchored, a1, &right);
3408              
3409 267 50         if (rv < 0)
3410             {
3411 0           return rv;
3412             }
3413              
3414 267 100         if (!rv)
3415             {
3416 24           return compare_mismatch(anchored, a1, a2);
3417             }
3418              
3419 243           a2->rn += sz - 1;
3420             assert(a2->rn->type == END);
3421 243           a2->spent = 0;
3422              
3423 267           return rv;
3424             }
3425              
3426 1214           static int compare_next(int anchored, Arrow *a1, Arrow *a2)
3427             {
3428 1214 50         if (bump_regular(a2) <= 0)
3429             {
3430 0           return -1;
3431             }
3432              
3433 1214           return compare(anchored, a1, a2);
3434             }
3435              
3436 21           static int compare_curly_plus(int anchored, Arrow *a1, Arrow *a2)
3437             {
3438             regnode *p1, *p2;
3439             Arrow left, right;
3440             short *cnt;
3441              
3442 21           p1 = a1->rn;
3443             assert((p1->type == CURLY) || (p1->type == CURLYM) ||
3444             (p1->type == CURLYX));
3445 21           p2 = a2->rn;
3446             assert(p2->type == PLUS);
3447              
3448 21           cnt = (short *)(p1 + 1);
3449 21 50         if (cnt[0] < 0)
3450             {
3451 0           rc_error = "Left curly has negative minimum";
3452 0           return -1;
3453             }
3454              
3455 21 50         if (!cnt[0])
3456             {
3457 0           return compare_mismatch(anchored, a1, a2);
3458             }
3459              
3460 21           left.origin = a1->origin;
3461 21           left.rn = p1 + 2;
3462 21           left.spent = 0;
3463              
3464 21           right.origin = a2->origin;
3465 21           right.rn = p2 + 1;
3466 21           right.spent = 0;
3467              
3468 21 100         if (cnt[0] > 1)
3469             {
3470 9           anchored = 1;
3471             }
3472              
3473 21           return compare(anchored, &left, &right);
3474             }
3475              
3476 30           static int compare_curly_star(int anchored, Arrow *a1, Arrow *a2)
3477             {
3478             regnode *p1, *p2;
3479             Arrow left, right;
3480             int rv;
3481              
3482 30           p1 = a1->rn;
3483             assert((p1->type == CURLY) || (p1->type == CURLYM) ||
3484             (p1->type == CURLYX));
3485 30           p2 = a2->rn;
3486             assert(p2->type == STAR);
3487              
3488 30           left.origin = a1->origin;
3489 30           left.rn = p1 + 2;
3490 30           left.spent = 0;
3491              
3492 30           right.origin = a2->origin;
3493 30           right.rn = p2 + 1;
3494 30           right.spent = 0;
3495              
3496 30           rv = compare(1, &left, &right);
3497 30 100         if (!rv)
3498             {
3499 11           rv = compare_next(anchored, a1, a2);
3500             }
3501              
3502 30           return rv;
3503             }
3504              
3505 41           static int compare_plus_curly(int anchored, Arrow *a1, Arrow *a2)
3506             {
3507             regnode *p1, *p2, *e2;
3508             Arrow left, right;
3509             short *cnt;
3510             int rv, offs;
3511              
3512 41           p1 = a1->rn;
3513             assert(p1->type == PLUS);
3514 41           p2 = a2->rn;
3515             assert((p2->type == CURLY) || (p2->type == CURLYM) ||
3516             (p2->type == CURLYX));
3517              
3518 41           cnt = (short *)(p2 + 1);
3519 41 50         if (cnt[0] < 0)
3520             {
3521 0           rc_error = "Negative minimum for curly";
3522 0           return -1;
3523             }
3524              
3525 41 100         if (cnt[0] > 1) /* FIXME: fails '(?:aa)+' => 'a{2,}' */
3526             {
3527 2           return compare_mismatch(anchored, a1, a2);
3528             }
3529              
3530 39           left.origin = a1->origin;
3531 39           left.rn = p1 + 1;
3532 39           left.spent = 0;
3533              
3534 39 100         if (cnt[1] != INFINITE_COUNT)
3535             {
3536 35           offs = get_jump_offset(p2);
3537 35 50         if (offs <= 0)
3538             {
3539 0           return -1;
3540             }
3541              
3542 35           e2 = p2 + offs;
3543 35 50         if (e2->type != END)
3544             {
3545 0           return compare_mismatch(anchored, a1, a2);
3546             }
3547             }
3548              
3549 39           right.origin = a2->origin;
3550 39           right.rn = p2 + 2;
3551 39           right.spent = 0;
3552              
3553 39           rv = compare(anchored, &left, &right);
3554 41 50         return (!rv && !cnt[0]) ? compare_next(anchored, a1, a2) : rv;
    0          
3555             }
3556              
3557 9           static int compare_suspend_curly(int anchored, Arrow *a1, Arrow *a2)
3558             {
3559             assert(a1->rn->type == SUSPEND);
3560             assert(!a1->spent);
3561              
3562 9           a1->rn += 2;
3563              
3564 9           return compare(1, a1, a2);
3565             }
3566              
3567 369           static void dec_curly_counts(short *altcnt)
3568             {
3569 369           --altcnt[0];
3570 369 100         if (altcnt[1] < INFINITE_COUNT)
3571             {
3572 150           --altcnt[1];
3573             }
3574 369           }
3575              
3576 622           static int compare_left_curly(int anchored, Arrow *a1, Arrow *a2)
3577             {
3578             regnode *p1, *alt, *q;
3579             Arrow left, right;
3580             int sz, rv, offs, end_offs;
3581             short *cnt;
3582              
3583             /* fprintf(stderr, "enter compare_left_curly(%d, %d, %d)\n", anchored,
3584             a1->rn->type, a2->rn->type); */
3585              
3586 622           p1 = a1->rn;
3587             assert((p1->type == CURLY) || (p1->type == CURLYM) ||
3588             (p1->type == CURLYX));
3589              
3590 622           cnt = (short *)(p1 + 1);
3591 622 100         if (!cnt[0])
3592             {
3593             /* fprintf(stderr, "curly from 0\n"); */
3594 8           return compare_mismatch(anchored, a1, a2);
3595             }
3596              
3597 614           sz = get_size(p1);
3598 614 50         if (sz < 0)
3599             {
3600 0           return -1;
3601             }
3602              
3603 614 50         if (sz < 3)
3604             {
3605 0           rc_error = "Left curly offset too small";
3606 0           return -1;
3607             }
3608              
3609 614 100         if (cnt[0] > 1)
3610             {
3611             /* fprintf(stderr, "curly with non-trivial repeat count\n"); */
3612              
3613 333 50         offs = GET_OFFSET(p1);
3614 333 50         if (offs < 0)
3615             {
3616 0           return -1;
3617             }
3618            
3619 333 50         if (offs < 3)
3620             {
3621 0           rc_error = "Left curly offset is too small";
3622 0           return -1;
3623             }
3624              
3625 333           alt = (regnode *)malloc(sizeof(regnode) * (offs - 2 + sz));
3626 333 50         if (!alt)
3627             {
3628 0           rc_error = "Could not allocate memory for unrolled curly";
3629 0           return -1;
3630             }
3631              
3632 333           memcpy(alt, p1 + 2, (offs - 2) * sizeof(regnode));
3633 333           memcpy(alt + offs - 2, p1, sz * sizeof(regnode));
3634              
3635 333           dec_curly_counts((short *)(alt + offs - 1));
3636              
3637 333           left.origin = a1->origin;
3638 333           left.rn = alt;
3639 333           left.spent = 0;
3640 333           rv = compare(1, &left, a2);
3641 333           free(alt);
3642 333           return rv;
3643             }
3644              
3645 281 100         if (anchored && !((cnt[0] == 1) && (cnt[1] == 1)))
    50          
    100          
3646             {
3647             /* fprintf(stderr, "anchored curly with variable length\n"); */
3648              
3649 7           alt = alloc_alt(p1 + 2, sz - 2);
3650 7 50         if (!alt)
3651             {
3652 0           return -1;
3653             }
3654              
3655 7           offs = get_jump_offset(p1);
3656 7 50         if (offs <= 0)
3657             {
3658 0           return -1;
3659             }
3660              
3661 7           q = p1 + offs;
3662 7 50         if (q->type != END)
3663             {
3664             /* repeat with a tail after it can be more strict than a
3665             fixed-length match only if the tail is at least as
3666             strict as the repeated regexp */
3667 0           left.origin = a1->origin;
3668 0           left.rn = q;
3669 0           left.spent = 0;
3670              
3671 0           end_offs = offs - 1;
3672 0           alt[end_offs].type = END;
3673              
3674 0           right.origin = a2->origin;
3675 0           right.rn = alt;
3676 0           right.spent = 0;
3677              
3678             /* fprintf(stderr, "comparing %d to %d\n", left.rn->type,
3679             right.rn->type); */
3680 0           rv = compare(1, &left, &right);
3681 0           free(alt);
3682             /* fprintf(stderr, "compare returned %d\n", rv); */
3683 0 0         if (rv <= 0)
3684             {
3685 0           return rv;
3686             }
3687             }
3688             }
3689              
3690 281           left.origin = a1->origin;
3691 281           left.rn = p1 + 2;
3692 281           left.spent = 0;
3693 622           return compare(anchored, &left, a2);
3694             }
3695              
3696 464           static int compare_right_curly(int anchored, Arrow *a1, Arrow *a2)
3697             {
3698             regnode *p2, *alt;
3699             Arrow right;
3700             short *cnt, *altcnt;
3701             int sz, rv, offs, nanch;
3702              
3703             /* fprintf(stderr, "enter compare_right_curly(%d...: a1->spent = %d, a2->spent = %d\n", anchored, a1->spent, a2->spent); */
3704              
3705 464           p2 = a2->rn;
3706              
3707 464           cnt = (short *)(p2 + 1);
3708 464 50         if (cnt[0] < 0)
3709             {
3710 0           rc_error = "Curly has negative minimum";
3711 0           return -1;
3712             }
3713              
3714             /* fprintf(stderr, "compare_right_curly: minimal repeat count = %d\n", cnt[0]); */
3715              
3716 464           nanch = anchored;
3717              
3718 464 100         if (cnt[0] > 0)
3719             {
3720             /* the repeated expression is mandatory: */
3721 163           sz = get_size(p2);
3722 163 50         if (sz < 0)
3723             {
3724 0           return sz;
3725             }
3726              
3727 163 50         if (sz < 3)
3728             {
3729 0           rc_error = "Right curly offset too small";
3730 0           return -1;
3731             }
3732              
3733 163           right.origin = a2->origin;
3734 163           right.rn = p2 + 2;
3735 163           right.spent = 0;
3736              
3737 163           rv = compare(anchored, a1, &right);
3738             /* fprintf(stderr, "compare_right_curly: compare returned %d\n", rv); */
3739 163 50         if (rv < 0)
3740             {
3741 0           return rv;
3742             }
3743              
3744 163 100         if (!rv)
3745             {
3746             /* ...or (if we aren't anchored yet) just do the left tail... */
3747 23           rv = compare_mismatch(anchored, a1, a2);
3748 23 50         if (rv)
3749             {
3750 0           return rv;
3751             }
3752              
3753             /* ...or (last try) unroll the repeat (works for e.g.
3754             'abbc' vs. 'ab{2}c' */
3755 23 100         if (cnt[0] > 1)
3756             {
3757 15 50         offs = GET_OFFSET(p2);
3758 15 50         if (offs < 0)
3759             {
3760 0           return -1;
3761             }
3762              
3763 15 50         if (offs < 3)
3764             {
3765 0           rc_error = "Left curly offset is too small";
3766 0           return -1;
3767             }
3768              
3769 15           alt = (regnode *)malloc(sizeof(regnode) * (offs - 2 + sz));
3770 15 50         if (!alt)
3771             {
3772 0           rc_error = "Couldn't allocate memory for unrolled curly";
3773 0           return -1;
3774             }
3775              
3776 15           memcpy(alt, p2 + 2, (offs - 2) * sizeof(regnode));
3777 15           memcpy(alt + offs - 2, p2, sz * sizeof(regnode));
3778              
3779 15           dec_curly_counts((short *)(alt + offs - 1));
3780              
3781 15           right.origin = a2->origin;
3782 15           right.rn = alt;
3783 15           right.spent = 0;
3784              
3785 15           rv = compare(anchored, a1, &right);
3786 15           free(alt);
3787 15           return rv;
3788             }
3789              
3790 8           return 0;
3791             }
3792              
3793 140 100         if (cnt[0] == 1)
3794             {
3795 79           return 1;
3796             }
3797              
3798 61 100         if (a1->rn->type == END)
3799             {
3800             /* we presume the repeated argument matches something, which
3801             isn't guaranteed, but it is conservative */
3802 40           return 0;
3803             }
3804              
3805             /* strictly speaking, matching one repeat didn't *necessarily*
3806             anchor the match, but we'll ignore such cases as
3807             pathological */
3808 21           nanch = 1;
3809              
3810 21           alt = alloc_alt(p2, sz);
3811 21 50         if (!alt)
3812             {
3813 0           return -1;
3814             }
3815              
3816 21           altcnt = (short *)(alt + 1);
3817 21           dec_curly_counts(altcnt);
3818 21 50         if (altcnt[1] > 0)
3819             {
3820 21           right.origin = a2->origin;
3821 21           right.rn = alt;
3822 21           right.spent = 0;
3823              
3824 21           rv = compare_right_curly(nanch, a1, &right);
3825             }
3826             else
3827             {
3828 0           rv = 1;
3829             }
3830              
3831 21           free(alt);
3832              
3833 21 100         if (rv <= 0)
3834             {
3835 2           return rv;
3836             }
3837              
3838 19           a2->rn += sz - 1;
3839             assert(a2->rn->type == END);
3840 19           a2->spent = 0;
3841 19           return rv;
3842             }
3843              
3844 464           return compare_right_curly_from_zero(nanch, a1, a2);
3845             }
3846              
3847 329           static int compare_curly_curly(int anchored, Arrow *a1, Arrow *a2)
3848             {
3849             regnode *p1, *p2, *e2;
3850             Arrow left, right;
3851             short *cnt1, *cnt2;
3852             int rv, offs;
3853              
3854             /* fprintf(stderr, "enter compare_curly_curly(%d...)\n", anchored); */
3855              
3856 329           p1 = a1->rn;
3857             assert((p1->type == CURLY) || (p1->type == CURLYM) ||
3858             (p1->type == CURLYX));
3859 329           p2 = a2->rn;
3860             assert((p2->type == CURLY) || (p2->type == CURLYM) ||
3861             (p2->type == CURLYX));
3862              
3863 329           cnt1 = (short *)(p1 + 1);
3864             /* fprintf(stderr, "*cnt1 = %d\n", cnt1[0]); */
3865 329 50         if (cnt1[0] < 0)
3866             {
3867 0           rc_error = "Negative minimum for left curly";
3868 0           return -1;
3869             }
3870              
3871 329           cnt2 = (short *)(p2 + 1);
3872             /* fprintf(stderr, "*cnt2 = %d\n", cnt2[0]); */
3873 329 50         if (cnt2[0] < 0)
3874             {
3875 0           rc_error = "Negative minimum for right curly";
3876 0           return -1;
3877             }
3878              
3879 329 100         if (cnt2[0] > cnt1[0]) /* FIXME: fails '(?:aa){1,}' => 'a{2,}' */
3880             {
3881             /* fprintf(stderr, "curly mismatch\n"); */
3882 5           return compare_mismatch(anchored, a1, a2);
3883             }
3884              
3885 324           left.origin = a1->origin;
3886 324           left.rn = p1 + 2;
3887 324           left.spent = 0;
3888              
3889 324 100         if (cnt1[1] > cnt2[1])
3890             {
3891 36           offs = get_jump_offset(p2);
3892             /* fprintf(stderr, "offs = %d\n", offs); */
3893 36 50         if (offs <= 0)
3894             {
3895 0           return -1;
3896             }
3897              
3898 36           e2 = p2 + offs;
3899             /* fprintf(stderr, "e2->type = %d\n", e2->type); */
3900 36 100         if (e2->type != END)
3901             {
3902 3           return compare_mismatch(anchored, a1, a2);
3903             }
3904             }
3905              
3906 321           right.origin = a2->origin;
3907 321           right.rn = p2 + 2;
3908 321           right.spent = 0;
3909              
3910             /* fprintf(stderr, "comparing tails\n"); */
3911              
3912 321           rv = compare(anchored, &left, &right);
3913             /* fprintf(stderr, "tail compare returned %d\n", rv); */
3914 329 100         return (!rv && !cnt2[0]) ? compare_next(anchored, a1, a2) : rv;
    100          
3915             }
3916              
3917 117           static int compare_bound(int anchored, Arrow *a1, Arrow *a2,
3918             int move_left, unsigned char *bitmap, char *lookup,
3919             unsigned char *oktypes,
3920             unsigned char *regclasses, U32 regclasses_size)
3921             {
3922             Arrow left, right;
3923             unsigned char t;
3924             int i;
3925             char *seq;
3926              
3927             assert((a2->rn->type == BOUND) || (a2->rn->type == NBOUND));
3928              
3929 117           left = *a1;
3930              
3931 117 50         if (bump_with_check(&left) <= 0)
3932             {
3933 0           return -1;
3934             }
3935              
3936 117           t = left.rn->type;
3937 117 50         if (t >= REGNODE_MAX)
3938             {
3939 0           rc_error = "Invalid node type";
3940 0           return -1;
3941             }
3942 117 100         else if (t == ANYOF)
3943             {
3944             /* fprintf(stderr, "next is bitmap; flags = 0x%x\n", left.rn->flags); */
3945              
3946 1 50         if (left.rn->flags & ANYOF_MATCHES_ALL_ABOVE_BITMAP)
3947             {
3948 0           return compare_mismatch(anchored, a1, a2);
3949             }
3950              
3951 33 100         for (i = 0; i < ANYOF_BITMAP_SIZE; ++i)
3952             {
3953 32 50         if (get_bitmap_byte(left.rn, i) & ~bitmap[i])
3954             {
3955 0           return compare_mismatch(anchored, a1, a2);
3956             }
3957             }
3958             }
3959 116 100         else if ((t == EXACT) || (t == EXACTF) || (t == EXACTFU))
    50          
    100          
3960             {
3961 85           seq = GET_LITERAL(&left);
3962 85 100         if (!lookup[(unsigned char)(*seq)])
3963             {
3964 43           return compare_mismatch(anchored, a1, a2);
3965             }
3966             }
3967 31 100         else if ((t == POSIXD) || (t == NPOSIXD) || (t == POSIXU) || (t == NPOSIXU))
    50          
    100          
    50          
3968 8           {
3969 8           U8 flags = left.rn->flags;
3970 8 50         if ((flags >= regclasses_size) || !regclasses[flags])
    50          
3971             {
3972 0           return compare_mismatch(anchored, a1, a2);
3973             }
3974             }
3975 23 100         else if (!oktypes[t])
3976             {
3977 17           return compare_mismatch(anchored, a1, a2);
3978             }
3979              
3980 57           right = *a2;
3981 57 50         if (bump_with_check(&right) <= 0)
3982             {
3983 0           return -1;
3984             }
3985              
3986 117 100         return move_left ? compare(1, &left, &right) :
3987             compare(anchored, a1, &right);
3988             }
3989              
3990 8           static int compare_bol_word(int anchored, Arrow *a1, Arrow *a2)
3991             {
3992 8           return compare_bound(anchored, a1, a2, 1, word_bc.bitmap,
3993             word_bc.lookup, alphanumeric_classes,
3994             word_posix_regclasses, SIZEOF_ARRAY(word_posix_regclasses));
3995             }
3996              
3997 2           static int compare_bol_nword(int anchored, Arrow *a1, Arrow *a2)
3998             {
3999 2           return compare_bound(anchored, a1, a2, 1, word_bc.nbitmap,
4000             word_bc.nlookup, non_alphanumeric_classes,
4001             non_word_posix_regclasses, SIZEOF_ARRAY(non_word_posix_regclasses));
4002             }
4003              
4004 30           static int compare_next_word(int anchored, Arrow *a1, Arrow *a2)
4005             {
4006 30           return compare_bound(anchored, a1, a2, 0, word_bc.bitmap,
4007             word_bc.lookup, alphanumeric_classes,
4008             word_posix_regclasses, SIZEOF_ARRAY(word_posix_regclasses));
4009             }
4010              
4011 77           static int compare_next_nword(int anchored, Arrow *a1, Arrow *a2)
4012             {
4013 77           return compare_bound(anchored, a1, a2, 0, word_bc.nbitmap,
4014             word_bc.nlookup, non_alphanumeric_classes,
4015             non_word_posix_regclasses, SIZEOF_ARRAY(non_word_posix_regclasses));
4016             }
4017              
4018 6           static int compare_anyof_bounds(int anchored, Arrow *a1, Arrow *a2,
4019             unsigned char *bitmap1, unsigned char *bitmap2)
4020             {
4021             unsigned char loc;
4022             FCompare cmp[2];
4023             int i;
4024              
4025 6           cmp[0] = compare_next_word;
4026 6           cmp[1] = compare_next_nword;
4027 179 100         for (i = 0; (i < ANYOF_BITMAP_SIZE) && (cmp[0] || cmp[1]); ++i)
    100          
    100          
4028             {
4029 173 50         loc = bitmap1 ? bitmap1[i] : get_bitmap_byte(a1->rn, i);
4030              
4031 173 100         if (loc & ~bitmap2[i])
4032             {
4033 13           cmp[0] = 0;
4034             }
4035              
4036 173 100         if (loc & bitmap2[i])
4037             {
4038 4           cmp[1] = 0;
4039             }
4040             }
4041              
4042 6 100         if (cmp[0] && cmp[1])
    50          
4043             {
4044 0           rc_error = "Zero bitmap";
4045 0           return -1;
4046             }
4047              
4048 10 100         for (i = 0; i < SIZEOF_ARRAY(cmp); ++i)
4049             {
4050 9 100         if (cmp[i])
4051             {
4052 5           return (cmp[i])(anchored, a1, a2);
4053             }
4054             }
4055              
4056             /* if would be more elegant to use compare_mismatch as a sentinel
4057             in cmp, but VC 2003 then warns that this function might be
4058             missing a return... */
4059 6           return compare_mismatch(anchored, a1, a2);
4060             }
4061              
4062 4           static int compare_anyof_bound(int anchored, Arrow *a1, Arrow *a2)
4063             {
4064             assert((a1->rn->type == ANYOF) || (a1->rn->type == ANYOFD));
4065             assert(a2->rn->type == BOUND);
4066              
4067 4 50         if (a1->rn->flags & ANYOF_MATCHES_ALL_ABOVE_BITMAP)
4068             {
4069 0           return compare_mismatch(anchored, a1, a2);
4070             }
4071              
4072 4           return compare_anyof_bounds(anchored, a1, a2, 0, word_bc.nbitmap);
4073             }
4074              
4075 2           static int compare_anyof_nbound(int anchored, Arrow *a1, Arrow *a2)
4076             {
4077             assert((a1->rn->type == ANYOF) || (a1->rn->type == ANYOFD));
4078             assert(a2->rn->type == NBOUND);
4079              
4080 2 50         if (a1->rn->flags & ANYOF_MATCHES_ALL_ABOVE_BITMAP)
4081             {
4082 0           return compare_mismatch(anchored, a1, a2);
4083             }
4084              
4085 2           return compare_anyof_bounds(anchored, a1, a2, 0, word_bc.bitmap);
4086             }
4087              
4088             #ifdef RC_ANYOFM
4089             static int compare_anyofm_bound(int anchored, Arrow *a1, Arrow *a2)
4090             {
4091             unsigned char left[ANYOF_BITMAP_SIZE];
4092            
4093             assert(a1->rn->type == ANYOFM);
4094             assert(a2->rn->type == BOUND);
4095              
4096             if (!convert_anyofm_to_bitmap(a1, left))
4097             {
4098             return compare_mismatch(anchored, a1, a2);
4099             }
4100              
4101             return compare_anyof_bounds(anchored, a1, a2, left, word_bc.nbitmap);
4102             }
4103              
4104             static int compare_anyofm_nbound(int anchored, Arrow *a1, Arrow *a2)
4105             {
4106             unsigned char left[ANYOF_BITMAP_SIZE];
4107            
4108             assert(a1->rn->type == ANYOFM);
4109             assert(a2->rn->type == BOUND);
4110              
4111             if (!convert_anyofm_to_bitmap(a1, left))
4112             {
4113             return compare_mismatch(anchored, a1, a2);
4114             }
4115              
4116             return compare_anyof_bounds(anchored, a1, a2, left, word_bc.bitmap);
4117             }
4118             #endif
4119              
4120 63           static int compare_exact_bound(int anchored, Arrow *a1, Arrow *a2)
4121             {
4122             char *seq;
4123             FCompare cmp;
4124              
4125             assert((a1->rn->type == EXACT) || (a1->rn->type == EXACTF) ||
4126             (a1->rn->type == EXACTFU));
4127             assert(a2->rn->type == BOUND);
4128              
4129 63           seq = GET_LITERAL(a1);
4130              
4131 126           cmp = word_bc.lookup[(unsigned char)(*seq)] ?
4132 63 100         compare_next_nword : compare_next_word;
4133 63           return cmp(anchored, a1, a2);
4134             }
4135              
4136 16           static int compare_exact_nbound(int anchored, Arrow *a1, Arrow *a2)
4137             {
4138             char *seq;
4139             FCompare cmp;
4140              
4141             assert((a1->rn->type == EXACT) || (a1->rn->type == EXACTF) ||
4142             (a1->rn->type == EXACTFU));
4143             assert(a2->rn->type == NBOUND);
4144              
4145 16           seq = GET_LITERAL(a1);
4146              
4147 32           cmp = word_bc.lookup[(unsigned char)(*seq)] ?
4148 16 100         compare_next_word : compare_next_nword;
4149 16           return cmp(anchored, a1, a2);
4150             }
4151              
4152 10           static int compare_posix_bound(int anchored, Arrow *a1, Arrow *a2)
4153             {
4154             assert((a1->rn->type == POSIXD) || (a1->rn->type == POSIXU) ||
4155             (a1->rn->type == POSIXA));
4156             assert(a2->rn->type == BOUND);
4157              
4158 10           U8 flags = a1->rn->flags;
4159 10 50         if ((flags >= SIZEOF_ARRAY(word_posix_regclasses)) ||
    50          
4160 10 100         (flags >= SIZEOF_ARRAY(non_word_posix_regclasses)) ||
4161 5 50         (!word_posix_regclasses[flags] && !non_word_posix_regclasses[flags]))
4162             {
4163 0           return compare_mismatch(anchored, a1, a2);
4164             }
4165              
4166             assert(!word_posix_regclasses[flags] || !non_word_posix_regclasses[flags]);
4167              
4168 20           FCompare cmp = word_posix_regclasses[flags] ?
4169 10 100         compare_next_nword : compare_next_word;
4170 10           return cmp(anchored, a1, a2);
4171             }
4172              
4173 9           static int compare_posix_nbound(int anchored, Arrow *a1, Arrow *a2)
4174             {
4175             assert((a1->rn->type == POSIXD) || (a1->rn->type == POSIXU) ||
4176             (a1->rn->type == POSIXA));
4177             assert(a2->rn->type == NBOUND);
4178              
4179 9           U8 flags = a1->rn->flags;
4180 9 50         if ((flags >= SIZEOF_ARRAY(word_posix_regclasses)) ||
    50          
4181 9 100         (flags >= SIZEOF_ARRAY(non_word_posix_regclasses)) ||
4182 4 50         (!word_posix_regclasses[flags] && !non_word_posix_regclasses[flags]))
4183             {
4184 0           return compare_mismatch(anchored, a1, a2);
4185             }
4186              
4187             assert(!word_posix_regclasses[flags] || !non_word_posix_regclasses[flags]);
4188              
4189 18           FCompare cmp = word_posix_regclasses[flags] ?
4190 9 100         compare_next_word : compare_next_nword;
4191 9           return cmp(anchored, a1, a2);
4192             }
4193              
4194 5           static int compare_negative_posix_word_bound(int anchored, Arrow *a1, Arrow *a2)
4195             {
4196             assert((a1->rn->type == NPOSIXD) || (a1->rn->type == NPOSIXU) ||
4197             (a1->rn->type == NPOSIXA));
4198             assert(a2->rn->type == BOUND);
4199              
4200             /* we could accept _CC_ALPHANUMERIC as well but let's postpone it
4201             until we see the need */
4202 5 100         if (a1->rn->flags != _CC_WORDCHAR)
4203             {
4204 3           return compare_mismatch(anchored, a1, a2);
4205             }
4206              
4207 2           return compare_next_word(anchored, a1, a2);
4208             }
4209              
4210 9           static int compare_negative_posix_word_nbound(int anchored, Arrow *a1, Arrow *a2)
4211             {
4212             assert((a1->rn->type == NPOSIXD) || (a1->rn->type == NPOSIXU) ||
4213             (a1->rn->type == NPOSIXA));
4214             assert(a2->rn->type == NBOUND);
4215              
4216             /* we could accept _CC_ALPHANUMERIC as well but let's postpone it
4217             until we see the need */
4218 9 100         if (a1->rn->flags != _CC_WORDCHAR)
4219             {
4220 7           return compare_mismatch(anchored, a1, a2);
4221             }
4222              
4223 2           return compare_next_nword(anchored, a1, a2);
4224             }
4225              
4226 44           static int compare_open_open(int anchored, Arrow *a1, Arrow *a2)
4227             {
4228 44           return compare_tails(anchored, a1, a2);
4229             }
4230              
4231 214           static int compare_left_open(int anchored, Arrow *a1, Arrow *a2)
4232             {
4233 214           return compare_left_tail(anchored, a1, a2);
4234             }
4235              
4236 203           static int compare_right_open(int anchored, Arrow *a1, Arrow *a2)
4237             {
4238 203           return compare_next(anchored, a1, a2);
4239             }
4240              
4241 9324           static int success(int anchored, Arrow *a1, Arrow *a2)
4242             {
4243 9324           return 1;
4244             }
4245              
4246             /* #define DEBUG_dump */
4247              
4248 8502           int rc_compare(REGEXP *pt1, REGEXP *pt2)
4249             {
4250             Arrow a1, a2;
4251             regnode *p1, *p2;
4252             #ifdef DEBUG_dump
4253             unsigned char *p;
4254             int i;
4255             #endif
4256              
4257 8502           a1.origin = SvANY(pt1);
4258 8502           a2.origin = SvANY(pt2);
4259              
4260 8502 100         if ((get_forced_semantics(pt1) | get_forced_semantics(pt2)) == FORCED_MISMATCH)
4261             {
4262 7           return 0;
4263             }
4264              
4265 8495           p1 = find_internal(a1.origin);
4266 8495 50         if (!p1)
4267             {
4268 0           return -1;
4269             }
4270              
4271 8495           p2 = find_internal(a2.origin);
4272 8495 50         if (!p2)
4273             {
4274 0           return -1;
4275             }
4276              
4277             #ifdef DEBUG_dump
4278             p = (unsigned char *)p1;
4279             for (i = 1; i <= 64; ++i)
4280             {
4281             fprintf(stderr, " %02x", (int)p[i - 1]);
4282             if (!(i % 4))
4283             {
4284             fprintf(stderr, "\n");
4285             }
4286             }
4287              
4288             fprintf(stderr, "\n\n");
4289              
4290             p = (unsigned char *)p2;
4291             for (i = 1; i <= 64; ++i)
4292             {
4293             fprintf(stderr, " %02x", (int)p[i - 1]);
4294             if (!(i % 4))
4295             {
4296             fprintf(stderr, "\n");
4297             }
4298             }
4299              
4300             fprintf(stderr, "\n\n");
4301             #endif
4302              
4303 8495           a1.rn = p1;
4304 8495           a1.spent = 0;
4305 8495           a2.rn = p2;
4306 8495           a2.spent = 0;
4307              
4308 8502           return compare(0, &a1, &a2);
4309             }
4310              
4311 35621           static int compare(int anchored, Arrow *a1, Arrow *a2)
4312             {
4313             FCompare cmp;
4314              
4315             /* fprintf(stderr, "enter compare(%d, %d, %d)\n", anchored,
4316             a1->rn->type, a2->rn->type); */
4317              
4318 35621 50         if ((a1->rn->type >= REGNODE_MAX) || (a2->rn->type >= REGNODE_MAX))
    50          
4319             {
4320 0           rc_error = "Invalid regexp node type";
4321 0           return -1;
4322             }
4323              
4324 35621           cmp = dispatch[a1->rn->type][a2->rn->type];
4325 35621 100         if (!cmp)
4326             {
4327             /* fprintf(stderr, "no comparator\n"); */
4328 926           return 0;
4329             }
4330              
4331 34695           return cmp(anchored, a1, a2);
4332             }
4333              
4334 1           void rc_init()
4335             {
4336             int i, wstart;
4337              
4338             /* could have used compile-time assertion, but why bother
4339             making it compatible... */
4340             assert(ANYOF_BITMAP_SIZE == 32);
4341              
4342 1           init_forced_byte();
4343              
4344 1           init_byte_class(&whitespace, whitespace_expl,
4345             SIZEOF_ARRAY(whitespace_expl));
4346 1           init_byte_class(&horizontal_whitespace, horizontal_whitespace_expl,
4347             SIZEOF_ARRAY(horizontal_whitespace_expl));
4348 1           init_byte_class(&vertical_whitespace, vertical_whitespace_expl,
4349             SIZEOF_ARRAY(vertical_whitespace_expl));
4350              
4351 11 100         for (i = 0; i < SIZEOF_ARRAY(digit_expl); ++i)
4352             {
4353 10           digit_expl[i] = '0' + i;
4354             }
4355              
4356 1           init_byte_class(&digit, digit_expl, SIZEOF_ARRAY(digit_expl));
4357              
4358 1           memcpy(xdigit_expl, digit_expl, 10 * sizeof(char));
4359              
4360 1           wstart = 10;
4361 7 100         for (i = 0; i < 6; ++i)
4362             {
4363 6           xdigit_expl[wstart + i] = 'a' + i;
4364             }
4365              
4366 1           wstart += 6;
4367 7 100         for (i = 0; i < 6; ++i)
4368             {
4369 6           xdigit_expl[wstart + i] = 'A' + i;
4370             }
4371              
4372 1           init_byte_class(&xdigit, xdigit_expl, SIZEOF_ARRAY(xdigit_expl));
4373              
4374 1           init_byte_class(&ndot, ndot_expl, SIZEOF_ARRAY(ndot_expl));
4375              
4376 1           alphanumeric_expl[0] = '_';
4377              
4378 1           wstart = 1;
4379 1           memcpy(alphanumeric_expl + wstart, digit_expl, 10 * sizeof(char));
4380              
4381 1           wstart += 10;
4382 27 100         for (i = 0; i < LETTER_COUNT; ++i)
4383             {
4384 26           alphanumeric_expl[wstart + i] = 'a' + i;
4385             }
4386              
4387 1           wstart += LETTER_COUNT;
4388 27 100         for (i = 0; i < LETTER_COUNT; ++i)
4389             {
4390 26           alphanumeric_expl[wstart + i] = 'A' + i;
4391             }
4392              
4393 1           init_byte_class(&word_bc, alphanumeric_expl,
4394             SIZEOF_ARRAY(alphanumeric_expl));
4395 1           init_byte_class(&alnum_bc, alphanumeric_expl + 1,
4396             SIZEOF_ARRAY(alphanumeric_expl) - 1);
4397              
4398 27 100         for (i = 0; i < LETTER_COUNT; ++i)
4399             {
4400 26           alpha_expl[i] = lower_expl[i] = 'a' + i;
4401             }
4402              
4403 1           wstart = LETTER_COUNT;
4404 27 100         for (i = 0; i < LETTER_COUNT; ++i)
4405             {
4406 26           alpha_expl[wstart + i] = upper_expl[i] = 'A' + i;
4407             }
4408              
4409 1           init_byte_class(&alpha_bc, alpha_expl,
4410             SIZEOF_ARRAY(alpha_expl));
4411 1           init_byte_class(&lower_bc, lower_expl,
4412             SIZEOF_ARRAY(lower_expl));
4413 1           init_byte_class(&upper_bc, upper_expl,
4414             SIZEOF_ARRAY(upper_expl));
4415              
4416 1           memset(alphanumeric_classes, 0, SIZEOF_ARRAY(alphanumeric_classes));
4417              
4418 1           memset(non_alphanumeric_classes, 0,
4419             SIZEOF_ARRAY(non_alphanumeric_classes));
4420 1           non_alphanumeric_classes[EOS] = non_alphanumeric_classes[EOL] =
4421 1           non_alphanumeric_classes[SEOL] = 1;
4422              
4423 1           posix_regclass_blocks[_CC_VERTSPACE] = VERTICAL_SPACE_BLOCK;
4424 1           posix_regclass_bitmaps[_CC_VERTSPACE] = vertical_whitespace.bitmap;
4425 1           posix_regclass_nbitmaps[_CC_VERTSPACE] = vertical_whitespace.nbitmap;
4426              
4427 1           memset(word_posix_regclasses, 0,
4428             SIZEOF_ARRAY(word_posix_regclasses));
4429 1           word_posix_regclasses[_CC_WORDCHAR] =
4430 1           word_posix_regclasses[_CC_DIGIT] =
4431 1           word_posix_regclasses[_CC_ALPHA] =
4432 1           word_posix_regclasses[_CC_LOWER] =
4433 1           word_posix_regclasses[_CC_UPPER] =
4434 1           word_posix_regclasses[_CC_UPPER] =
4435 1           word_posix_regclasses[_CC_ALPHANUMERIC] =
4436 1           word_posix_regclasses[_CC_CASED] =
4437 1           word_posix_regclasses[_CC_XDIGIT] = 1;
4438              
4439 1           memset(non_word_posix_regclasses, 0,
4440             SIZEOF_ARRAY(non_word_posix_regclasses));
4441 1           non_word_posix_regclasses[_CC_PUNCT] =
4442 1           non_word_posix_regclasses[_CC_SPACE] =
4443 1           non_word_posix_regclasses[_CC_BLANK] =
4444 1           non_word_posix_regclasses[_CC_VERTSPACE] = 1;
4445              
4446 1           memset(newline_posix_regclasses, 0,
4447             SIZEOF_ARRAY(newline_posix_regclasses));
4448 1           newline_posix_regclasses[_CC_SPACE] =
4449 1           newline_posix_regclasses[_CC_CNTRL] =
4450 1           newline_posix_regclasses[_CC_ASCII] =
4451 1           newline_posix_regclasses[_CC_VERTSPACE] = 1;
4452              
4453 1           memset(trivial_nodes, 0, SIZEOF_ARRAY(trivial_nodes));
4454 1           trivial_nodes[SUCCEED] = trivial_nodes[NOTHING] =
4455 1           trivial_nodes[TAIL] = trivial_nodes[WHILEM] = 1;
4456              
4457 1           memset(dispatch, 0, sizeof(FCompare) * REGNODE_MAX * REGNODE_MAX);
4458              
4459 93 100         for (i = 0; i < REGNODE_MAX; ++i)
4460             {
4461 92           dispatch[i][END] = success;
4462             }
4463              
4464 93 100         for (i = 0; i < REGNODE_MAX; ++i)
4465             {
4466 92           dispatch[i][SUCCEED] = compare_next;
4467             }
4468              
4469 1           dispatch[SUCCEED][SUCCEED] = compare_tails;
4470              
4471 1           dispatch[SUCCEED][MBOL] = compare_left_tail;
4472 1           dispatch[MBOL][MBOL] = compare_tails;
4473 1           dispatch[SBOL][MBOL] = compare_tails;
4474 1           dispatch[REG_ANY][MBOL] = compare_mismatch;
4475 1           dispatch[SANY][MBOL] = compare_mismatch;
4476 1           dispatch[ANYOF][MBOL] = compare_anyof_multiline;
4477 1           dispatch[ANYOFD][MBOL] = compare_anyof_multiline;
4478             #ifdef RC_ANYOFM
4479             dispatch[ANYOFM][MBOL] = compare_anyofm_multiline;
4480             #endif
4481 1           dispatch[POSIXD][MBOL] = compare_mismatch;
4482 1           dispatch[POSIXU][MBOL] = compare_mismatch;
4483 1           dispatch[POSIXA][MBOL] = compare_mismatch;
4484 1           dispatch[NPOSIXD][MBOL] = compare_mismatch;
4485 1           dispatch[NPOSIXU][MBOL] = compare_mismatch;
4486 1           dispatch[NPOSIXA][MBOL] = compare_mismatch;
4487 1           dispatch[BRANCH][MBOL] = compare_left_branch;
4488 1           dispatch[EXACT][MBOL] = compare_exact_multiline;
4489 1           dispatch[EXACTF][MBOL] = compare_exact_multiline;
4490 1           dispatch[EXACTFU][MBOL] = compare_exact_multiline;
4491 1           dispatch[NOTHING][MBOL] = compare_left_tail;
4492 1           dispatch[TAIL][MBOL] = compare_left_tail;
4493 1           dispatch[STAR][MBOL] = compare_mismatch;
4494 1           dispatch[PLUS][MBOL] = compare_left_plus;
4495 1           dispatch[CURLY][MBOL] = compare_left_curly;
4496 1           dispatch[CURLYM][MBOL] = compare_left_curly;
4497 1           dispatch[CURLYX][MBOL] = compare_left_curly;
4498 1           dispatch[WHILEM][MBOL] = compare_left_tail;
4499 1           dispatch[OPEN][MBOL] = compare_left_open;
4500 1           dispatch[CLOSE][MBOL] = compare_left_tail;
4501 1           dispatch[IFMATCH][MBOL] = compare_after_assertion;
4502 1           dispatch[UNLESSM][MBOL] = compare_after_assertion;
4503 1           dispatch[MINMOD][MBOL] = compare_left_tail;
4504 1           dispatch[OPTIMIZED][MBOL] = compare_left_tail;
4505              
4506 1           dispatch[SUCCEED][SBOL] = compare_left_tail;
4507 1           dispatch[SBOL][SBOL] = compare_tails;
4508 1           dispatch[BRANCH][SBOL] = compare_left_branch;
4509 1           dispatch[NOTHING][SBOL] = compare_left_tail;
4510 1           dispatch[TAIL][SBOL] = compare_left_tail;
4511 1           dispatch[STAR][SBOL] = compare_mismatch;
4512 1           dispatch[PLUS][SBOL] = compare_left_plus;
4513 1           dispatch[CURLY][SBOL] = compare_left_curly;
4514 1           dispatch[CURLYM][SBOL] = compare_left_curly;
4515 1           dispatch[CURLYX][SBOL] = compare_left_curly;
4516 1           dispatch[WHILEM][SBOL] = compare_left_tail;
4517 1           dispatch[OPEN][SBOL] = compare_left_open;
4518 1           dispatch[CLOSE][SBOL] = compare_left_tail;
4519 1           dispatch[IFMATCH][SBOL] = compare_after_assertion;
4520 1           dispatch[UNLESSM][SBOL] = compare_after_assertion;
4521 1           dispatch[MINMOD][SBOL] = compare_left_tail;
4522 1           dispatch[OPTIMIZED][SBOL] = compare_left_tail;
4523              
4524 1           dispatch[SUCCEED][EOS] = compare_left_tail;
4525 1           dispatch[EOS][EOS] = compare_tails;
4526 1           dispatch[EOL][EOS] = compare_mismatch;
4527 1           dispatch[SEOL][EOS] = compare_mismatch;
4528 1           dispatch[BRANCH][EOS] = compare_left_branch;
4529 1           dispatch[NOTHING][EOS] = compare_left_tail;
4530 1           dispatch[TAIL][EOS] = compare_left_tail;
4531 1           dispatch[STAR][EOS] = compare_mismatch;
4532 1           dispatch[PLUS][EOS] = compare_left_plus;
4533 1           dispatch[CURLY][EOS] = compare_left_curly;
4534 1           dispatch[CURLYM][EOS] = compare_left_curly;
4535 1           dispatch[CURLYX][EOS] = compare_left_curly;
4536 1           dispatch[WHILEM][EOS] = compare_left_tail;
4537 1           dispatch[OPEN][EOS] = compare_left_open;
4538 1           dispatch[CLOSE][EOS] = compare_left_tail;
4539 1           dispatch[IFMATCH][EOS] = compare_after_assertion;
4540 1           dispatch[UNLESSM][EOS] = compare_after_assertion;
4541 1           dispatch[MINMOD][EOS] = compare_left_tail;
4542 1           dispatch[OPTIMIZED][EOS] = compare_left_tail;
4543              
4544 1           dispatch[SUCCEED][EOL] = compare_left_tail;
4545 1           dispatch[EOS][EOL] = compare_tails;
4546 1           dispatch[EOL][EOL] = compare_tails;
4547 1           dispatch[SEOL][EOL] = compare_tails;
4548 1           dispatch[BRANCH][EOL] = compare_left_branch;
4549 1           dispatch[NOTHING][EOL] = compare_left_tail;
4550 1           dispatch[TAIL][EOL] = compare_left_tail;
4551 1           dispatch[STAR][EOL] = compare_mismatch;
4552 1           dispatch[PLUS][EOL] = compare_left_plus;
4553 1           dispatch[CURLY][EOL] = compare_left_curly;
4554 1           dispatch[CURLYM][EOL] = compare_left_curly;
4555 1           dispatch[CURLYX][EOL] = compare_left_curly;
4556 1           dispatch[WHILEM][EOL] = compare_left_tail;
4557 1           dispatch[OPEN][EOL] = compare_left_open;
4558 1           dispatch[CLOSE][EOL] = compare_left_tail;
4559 1           dispatch[IFMATCH][EOL] = compare_after_assertion;
4560 1           dispatch[UNLESSM][EOL] = compare_after_assertion;
4561 1           dispatch[MINMOD][EOL] = compare_left_tail;
4562 1           dispatch[OPTIMIZED][EOL] = compare_left_tail;
4563              
4564 1           dispatch[SUCCEED][MEOL] = compare_left_tail;
4565 1           dispatch[EOS][MEOL] = compare_tails;
4566 1           dispatch[EOL][MEOL] = compare_tails;
4567 1           dispatch[MEOL][MEOL] = compare_tails;
4568 1           dispatch[SEOL][MEOL] = compare_tails;
4569 1           dispatch[REG_ANY][MEOL] = compare_mismatch;
4570 1           dispatch[SANY][MEOL] = compare_mismatch;
4571 1           dispatch[ANYOF][MEOL] = compare_anyof_multiline; /* not in tests; remove? */
4572 1           dispatch[POSIXD][MEOL] = compare_mismatch;
4573 1           dispatch[POSIXU][MEOL] = compare_mismatch;
4574 1           dispatch[POSIXA][MEOL] = compare_mismatch;
4575 1           dispatch[NPOSIXD][MEOL] = compare_mismatch;
4576 1           dispatch[NPOSIXU][MEOL] = compare_mismatch;
4577 1           dispatch[NPOSIXA][MEOL] = compare_mismatch;
4578 1           dispatch[BRANCH][MEOL] = compare_left_branch;
4579 1           dispatch[EXACT][MEOL] = compare_exact_multiline;
4580 1           dispatch[EXACTF][MEOL] = compare_exact_multiline;
4581 1           dispatch[EXACTFU][MEOL] = compare_exact_multiline;
4582 1           dispatch[NOTHING][MEOL] = compare_left_tail;
4583 1           dispatch[TAIL][MEOL] = compare_left_tail;
4584 1           dispatch[STAR][MEOL] = compare_mismatch;
4585 1           dispatch[PLUS][MEOL] = compare_left_plus;
4586 1           dispatch[CURLY][MEOL] = compare_left_curly;
4587 1           dispatch[CURLYM][MEOL] = compare_left_curly;
4588 1           dispatch[CURLYX][MEOL] = compare_left_curly;
4589 1           dispatch[WHILEM][MEOL] = compare_left_tail;
4590 1           dispatch[OPEN][MEOL] = compare_left_open;
4591 1           dispatch[CLOSE][MEOL] = compare_left_tail;
4592 1           dispatch[IFMATCH][MEOL] = compare_after_assertion;
4593 1           dispatch[UNLESSM][MEOL] = compare_after_assertion;
4594 1           dispatch[MINMOD][MEOL] = compare_left_tail;
4595 1           dispatch[OPTIMIZED][MEOL] = compare_left_tail;
4596              
4597 1           dispatch[SUCCEED][SEOL] = compare_left_tail;
4598 1           dispatch[EOS][SEOL] = compare_tails;
4599 1           dispatch[EOL][SEOL] = compare_tails;
4600 1           dispatch[SEOL][SEOL] = compare_tails;
4601 1           dispatch[BRANCH][SEOL] = compare_left_branch;
4602 1           dispatch[NOTHING][SEOL] = compare_left_tail;
4603 1           dispatch[POSIXD][SEOL] = compare_mismatch;
4604 1           dispatch[POSIXU][SEOL] = compare_mismatch;
4605 1           dispatch[POSIXA][SEOL] = compare_mismatch;
4606 1           dispatch[NPOSIXD][SEOL] = compare_mismatch;
4607 1           dispatch[NPOSIXU][SEOL] = compare_mismatch;
4608 1           dispatch[NPOSIXA][SEOL] = compare_mismatch;
4609 1           dispatch[TAIL][SEOL] = compare_left_tail;
4610 1           dispatch[STAR][SEOL] = 0;
4611 1           dispatch[PLUS][SEOL] = compare_left_plus;
4612 1           dispatch[CURLY][SEOL] = compare_left_curly;
4613 1           dispatch[CURLYM][SEOL] = compare_left_curly;
4614 1           dispatch[CURLYX][SEOL] = compare_left_curly;
4615 1           dispatch[WHILEM][SEOL] = compare_left_tail;
4616 1           dispatch[OPEN][SEOL] = compare_left_open;
4617 1           dispatch[CLOSE][SEOL] = compare_left_tail;
4618 1           dispatch[IFMATCH][SEOL] = compare_after_assertion;
4619 1           dispatch[UNLESSM][SEOL] = compare_after_assertion;
4620 1           dispatch[MINMOD][SEOL] = compare_left_tail;
4621 1           dispatch[OPTIMIZED][SEOL] = compare_left_tail;
4622              
4623 1           dispatch[SUCCEED][BOUND] = compare_left_tail;
4624 1           dispatch[MBOL][BOUND] = compare_bol_word;
4625 1           dispatch[SBOL][BOUND] = compare_bol_word;
4626 1           dispatch[BOUND][BOUND] = compare_tails;
4627 1           dispatch[NBOUND][BOUND] = compare_mismatch;
4628 1           dispatch[REG_ANY][BOUND] = compare_mismatch;
4629 1           dispatch[SANY][BOUND] = compare_mismatch;
4630 1           dispatch[ANYOF][BOUND] = compare_anyof_bound;
4631 1           dispatch[ANYOFD][BOUND] = compare_anyof_bound;
4632             #ifdef RC_ANYOFM
4633             dispatch[ANYOFM][BOUND] = compare_anyofm_bound;
4634             #endif
4635 1           dispatch[POSIXD][BOUND] = compare_posix_bound;
4636 1           dispatch[POSIXU][BOUND] = compare_posix_bound;
4637 1           dispatch[POSIXA][BOUND] = compare_posix_bound;
4638 1           dispatch[NPOSIXD][BOUND] = compare_negative_posix_word_bound;
4639 1           dispatch[NPOSIXU][BOUND] = compare_mismatch; /* should be replaced, needs extra test */
4640 1           dispatch[NPOSIXA][BOUND] = compare_negative_posix_word_bound;
4641 1           dispatch[BRANCH][BOUND] = compare_left_branch;
4642 1           dispatch[EXACT][BOUND] = compare_exact_bound;
4643 1           dispatch[EXACTF][BOUND] = compare_exact_bound;
4644 1           dispatch[EXACTFU][BOUND] = compare_exact_bound;
4645 1           dispatch[NOTHING][BOUND] = compare_left_tail;
4646 1           dispatch[TAIL][BOUND] = compare_left_tail;
4647 1           dispatch[CURLY][BOUND] = compare_left_curly;
4648 1           dispatch[CURLYM][BOUND] = compare_left_curly;
4649 1           dispatch[CURLYX][BOUND] = compare_left_curly;
4650 1           dispatch[WHILEM][BOUND] = compare_left_tail;
4651 1           dispatch[OPEN][BOUND] = compare_left_open;
4652 1           dispatch[CLOSE][BOUND] = compare_left_tail;
4653 1           dispatch[IFMATCH][BOUND] = compare_after_assertion;
4654 1           dispatch[UNLESSM][BOUND] = compare_after_assertion;
4655 1           dispatch[MINMOD][BOUND] = compare_left_tail;
4656 1           dispatch[OPTIMIZED][BOUND] = compare_left_tail;
4657              
4658 1           dispatch[SUCCEED][NBOUND] = compare_left_tail;
4659 1           dispatch[MBOL][NBOUND] = compare_bol_nword;
4660 1           dispatch[SBOL][NBOUND] = compare_bol_nword;
4661 1           dispatch[BOUND][NBOUND] = compare_mismatch;
4662 1           dispatch[NBOUND][NBOUND] = compare_tails;
4663 1           dispatch[REG_ANY][NBOUND] = compare_mismatch;
4664 1           dispatch[SANY][NBOUND] = compare_mismatch;
4665 1           dispatch[ANYOF][NBOUND] = compare_anyof_nbound;
4666 1           dispatch[ANYOFD][NBOUND] = compare_anyof_nbound;
4667             #ifdef RC_ANYOFM
4668             dispatch[ANYOFM][NBOUND] = compare_anyofm_nbound;
4669             #endif
4670 1           dispatch[POSIXD][NBOUND] = compare_posix_nbound;
4671 1           dispatch[POSIXU][NBOUND] = compare_posix_nbound;
4672 1           dispatch[POSIXA][NBOUND] = compare_posix_nbound;
4673 1           dispatch[NPOSIXD][NBOUND] = compare_negative_posix_word_nbound;
4674 1           dispatch[NPOSIXU][NBOUND] = compare_negative_posix_word_nbound;
4675 1           dispatch[NPOSIXA][NBOUND] = compare_negative_posix_word_nbound;
4676 1           dispatch[BRANCH][NBOUND] = compare_left_branch;
4677 1           dispatch[EXACT][NBOUND] = compare_exact_nbound;
4678 1           dispatch[EXACTF][NBOUND] = compare_exact_nbound;
4679 1           dispatch[EXACTFU][NBOUND] = compare_exact_nbound;
4680 1           dispatch[NOTHING][NBOUND] = compare_left_tail;
4681 1           dispatch[TAIL][NBOUND] = compare_left_tail;
4682 1           dispatch[CURLY][NBOUND] = compare_left_curly;
4683 1           dispatch[CURLYM][NBOUND] = compare_left_curly;
4684 1           dispatch[CURLYX][NBOUND] = compare_left_curly;
4685 1           dispatch[WHILEM][NBOUND] = compare_left_tail;
4686 1           dispatch[OPEN][NBOUND] = compare_left_open;
4687 1           dispatch[CLOSE][NBOUND] = compare_left_tail;
4688 1           dispatch[IFMATCH][NBOUND] = compare_after_assertion;
4689 1           dispatch[UNLESSM][NBOUND] = compare_after_assertion;
4690 1           dispatch[MINMOD][NBOUND] = compare_left_tail;
4691 1           dispatch[OPTIMIZED][NBOUND] = compare_left_tail;
4692              
4693 1           dispatch[SUCCEED][REG_ANY] = compare_left_tail;
4694 1           dispatch[MBOL][REG_ANY] = compare_bol;
4695 1           dispatch[SBOL][REG_ANY] = compare_bol;
4696 1           dispatch[BOUND][REG_ANY] = compare_mismatch;
4697 1           dispatch[NBOUND][REG_ANY] = compare_mismatch;
4698 1           dispatch[REG_ANY][REG_ANY] = compare_tails;
4699 1           dispatch[SANY][REG_ANY] = compare_mismatch;
4700 1           dispatch[ANYOF][REG_ANY] = compare_anyof_reg_any;
4701 1           dispatch[ANYOFD][REG_ANY] = compare_anyof_reg_any;
4702             #ifdef RC_ANYOFM
4703             dispatch[ANYOFM][REG_ANY] = compare_anyofm_reg_any;
4704             #endif
4705 1           dispatch[POSIXD][REG_ANY] = compare_posix_reg_any;
4706 1           dispatch[POSIXU][REG_ANY] = compare_posix_reg_any;
4707 1           dispatch[POSIXA][REG_ANY] = compare_posix_reg_any;
4708 1           dispatch[NPOSIXD][REG_ANY] = compare_negative_posix_reg_any;
4709 1           dispatch[NPOSIXU][REG_ANY] = compare_negative_posix_reg_any;
4710 1           dispatch[NPOSIXA][REG_ANY] = compare_negative_posix_reg_any;
4711 1           dispatch[BRANCH][REG_ANY] = compare_left_branch;
4712 1           dispatch[EXACT][REG_ANY] = compare_exact_reg_any;
4713 1           dispatch[EXACTF][REG_ANY] = compare_exact_reg_any;
4714 1           dispatch[EXACTFU][REG_ANY] = compare_exact_reg_any;
4715 1           dispatch[NOTHING][REG_ANY] = compare_left_tail;
4716 1           dispatch[TAIL][REG_ANY] = compare_left_tail;
4717 1           dispatch[STAR][REG_ANY] = compare_mismatch;
4718 1           dispatch[PLUS][REG_ANY] = compare_left_plus;
4719 1           dispatch[CURLY][REG_ANY] = compare_left_curly;
4720 1           dispatch[CURLYM][REG_ANY] = compare_left_curly;
4721 1           dispatch[CURLYX][REG_ANY] = compare_left_curly;
4722 1           dispatch[WHILEM][REG_ANY] = compare_left_tail;
4723 1           dispatch[OPEN][REG_ANY] = compare_left_open;
4724 1           dispatch[CLOSE][REG_ANY] = compare_left_tail;
4725 1           dispatch[IFMATCH][REG_ANY] = compare_after_assertion;
4726 1           dispatch[UNLESSM][REG_ANY] = compare_after_assertion;
4727 1           dispatch[MINMOD][REG_ANY] = compare_left_tail;
4728 1           dispatch[OPTIMIZED][REG_ANY] = compare_left_tail;
4729              
4730 1           dispatch[SUCCEED][SANY] = compare_left_tail;
4731 1           dispatch[MBOL][SANY] = compare_bol;
4732 1           dispatch[SBOL][SANY] = compare_bol;
4733 1           dispatch[BOUND][SANY] = compare_mismatch;
4734 1           dispatch[NBOUND][SANY] = compare_mismatch;
4735 1           dispatch[REG_ANY][SANY] = compare_tails;
4736 1           dispatch[SANY][SANY] = compare_tails;
4737 1           dispatch[ANYOF][SANY] = compare_tails;
4738 1           dispatch[ANYOFD][SANY] = compare_tails;
4739             #ifdef RC_ANYOFM
4740             dispatch[ANYOFM][SANY] = compare_tails;
4741             #endif
4742 1           dispatch[POSIXD][SANY] = compare_tails;
4743 1           dispatch[POSIXU][SANY] = compare_tails;
4744 1           dispatch[POSIXA][SANY] = compare_tails;
4745 1           dispatch[NPOSIXD][SANY] = compare_tails;
4746 1           dispatch[NPOSIXU][SANY] = compare_tails;
4747 1           dispatch[NPOSIXA][SANY] = compare_tails;
4748 1           dispatch[BRANCH][SANY] = compare_left_branch;
4749 1           dispatch[EXACT][SANY] = compare_tails;
4750 1           dispatch[EXACTF][SANY] = compare_tails;
4751 1           dispatch[EXACTFU][SANY] = compare_tails;
4752 1           dispatch[NOTHING][SANY] = compare_left_tail;
4753 1           dispatch[TAIL][SANY] = compare_left_tail;
4754 1           dispatch[STAR][SANY] = compare_mismatch;
4755 1           dispatch[PLUS][SANY] = compare_left_plus;
4756 1           dispatch[CURLY][SANY] = compare_left_curly;
4757 1           dispatch[CURLYM][SANY] = compare_left_curly;
4758 1           dispatch[CURLYX][SANY] = compare_left_curly;
4759 1           dispatch[WHILEM][SANY] = compare_left_tail;
4760 1           dispatch[OPEN][SANY] = compare_left_open;
4761 1           dispatch[CLOSE][SANY] = compare_left_tail;
4762 1           dispatch[IFMATCH][SANY] = compare_after_assertion;
4763 1           dispatch[UNLESSM][SANY] = compare_after_assertion;
4764 1           dispatch[MINMOD][SANY] = compare_left_tail;
4765 1           dispatch[OPTIMIZED][SANY] = compare_left_tail;
4766              
4767 1           dispatch[SUCCEED][ANYOF] = compare_left_tail;
4768 1           dispatch[MBOL][ANYOF] = compare_bol;
4769 1           dispatch[SBOL][ANYOF] = compare_bol;
4770 1           dispatch[BOUND][ANYOF] = compare_mismatch;
4771 1           dispatch[NBOUND][ANYOF] = compare_mismatch;
4772 1           dispatch[REG_ANY][ANYOF] = compare_reg_any_anyof;
4773 1           dispatch[SANY][ANYOF] = compare_sany_anyof;
4774 1           dispatch[ANYOF][ANYOF] = compare_anyof_anyof;
4775 1           dispatch[ANYOFD][ANYOF] = compare_anyof_anyof;
4776             #ifdef RC_ANYOFM
4777             dispatch[ANYOFM][ANYOF] = compare_anyofm_anyof;
4778             #endif
4779 1           dispatch[POSIXD][ANYOF] = compare_posix_anyof;
4780 1           dispatch[POSIXU][ANYOF] = compare_posix_anyof;
4781 1           dispatch[POSIXA][ANYOF] = compare_posix_anyof;
4782 1           dispatch[NPOSIXD][ANYOF] = compare_negative_posix_anyof;
4783 1           dispatch[NPOSIXU][ANYOF] = compare_negative_posix_anyof;
4784 1           dispatch[NPOSIXA][ANYOF] = compare_negative_posix_anyof;
4785 1           dispatch[BRANCH][ANYOF] = compare_left_branch;
4786 1           dispatch[EXACT][ANYOF] = compare_exact_anyof;
4787 1           dispatch[EXACTF][ANYOF] = compare_exactf_anyof;
4788 1           dispatch[EXACTFU][ANYOF] = compare_exactf_anyof;
4789 1           dispatch[NOTHING][ANYOF] = compare_left_tail;
4790 1           dispatch[TAIL][ANYOF] = compare_left_tail;
4791 1           dispatch[STAR][ANYOF] = compare_mismatch;
4792 1           dispatch[PLUS][ANYOF] = compare_left_plus;
4793 1           dispatch[CURLY][ANYOF] = compare_left_curly;
4794 1           dispatch[CURLYM][ANYOF] = compare_left_curly;
4795 1           dispatch[CURLYX][ANYOF] = compare_left_curly;
4796 1           dispatch[WHILEM][ANYOF] = compare_left_tail;
4797 1           dispatch[OPEN][ANYOF] = compare_left_open;
4798 1           dispatch[CLOSE][ANYOF] = compare_left_tail;
4799 1           dispatch[IFMATCH][ANYOF] = compare_after_assertion;
4800 1           dispatch[UNLESSM][ANYOF] = compare_after_assertion;
4801 1           dispatch[MINMOD][ANYOF] = compare_left_tail;
4802 1           dispatch[OPTIMIZED][ANYOF] = compare_left_tail;
4803              
4804 1           dispatch[SUCCEED][ANYOFD] = compare_left_tail;
4805 1           dispatch[MBOL][ANYOFD] = compare_bol;
4806 1           dispatch[SBOL][ANYOFD] = compare_bol;
4807 1           dispatch[BOUND][ANYOFD] = compare_mismatch;
4808 1           dispatch[NBOUND][ANYOFD] = compare_mismatch;
4809 1           dispatch[REG_ANY][ANYOFD] = compare_reg_any_anyof;
4810 1           dispatch[SANY][ANYOFD] = compare_sany_anyof;
4811 1           dispatch[ANYOF][ANYOFD] = compare_anyof_anyof;
4812 1           dispatch[ANYOFD][ANYOFD] = compare_anyof_anyof;
4813             #ifdef RC_ANYOFM
4814             dispatch[ANYOFM][ANYOFD] = compare_anyofm_anyof;
4815             #endif
4816 1           dispatch[POSIXD][ANYOFD] = compare_posix_anyof;
4817 1           dispatch[POSIXU][ANYOFD] = compare_posix_anyof;
4818 1           dispatch[POSIXA][ANYOFD] = compare_posix_anyof;
4819 1           dispatch[NPOSIXD][ANYOFD] = compare_negative_posix_anyof;
4820 1           dispatch[NPOSIXU][ANYOFD] = compare_negative_posix_anyof;
4821 1           dispatch[NPOSIXA][ANYOFD] = compare_negative_posix_anyof;
4822 1           dispatch[BRANCH][ANYOFD] = compare_left_branch;
4823 1           dispatch[EXACT][ANYOFD] = compare_exact_anyof;
4824 1           dispatch[EXACTFU][ANYOFD] = compare_exactf_anyof;
4825 1           dispatch[NOTHING][ANYOFD] = compare_left_tail;
4826 1           dispatch[TAIL][ANYOFD] = compare_left_tail;
4827 1           dispatch[STAR][ANYOFD] = compare_mismatch;
4828 1           dispatch[PLUS][ANYOFD] = compare_left_plus;
4829 1           dispatch[CURLY][ANYOFD] = compare_left_curly;
4830 1           dispatch[CURLYM][ANYOFD] = compare_left_curly;
4831 1           dispatch[CURLYX][ANYOFD] = compare_left_curly;
4832 1           dispatch[OPEN][ANYOFD] = compare_left_open;
4833 1           dispatch[CLOSE][ANYOFD] = compare_left_tail;
4834 1           dispatch[IFMATCH][ANYOFD] = compare_after_assertion;
4835 1           dispatch[UNLESSM][ANYOFD] = compare_after_assertion;
4836 1           dispatch[MINMOD][ANYOFD] = compare_left_tail;
4837 1           dispatch[OPTIMIZED][ANYOFD] = compare_left_tail;
4838              
4839             #ifdef RC_ANYOFM
4840             dispatch[SUCCEED][ANYOFM] = compare_left_tail;
4841             dispatch[MBOL][ANYOFM] = compare_bol;
4842             dispatch[SBOL][ANYOFM] = compare_bol;
4843             dispatch[BOUND][ANYOFM] = compare_mismatch;
4844             dispatch[NBOUND][ANYOFM] = compare_mismatch;
4845             dispatch[REG_ANY][ANYOFM] = compare_mismatch;
4846             dispatch[SANY][ANYOFM] = compare_mismatch;
4847             dispatch[ANYOF][ANYOFM] = compare_anyof_anyofm;
4848             dispatch[ANYOFD][ANYOFM] = compare_anyof_anyofm;
4849             dispatch[ANYOFM][ANYOFM] = compare_anyofm_anyofm;
4850             dispatch[POSIXD][ANYOFM] = compare_mismatch;
4851             dispatch[POSIXU][ANYOFM] = compare_mismatch;
4852             dispatch[POSIXA][ANYOFM] = compare_mismatch;
4853             dispatch[NPOSIXD][ANYOFM] = compare_mismatch;
4854             dispatch[NPOSIXU][ANYOFM] = compare_mismatch;
4855             dispatch[NPOSIXA][ANYOFM] = compare_mismatch;
4856             dispatch[BRANCH][ANYOFM] = compare_left_branch;
4857             dispatch[EXACT][ANYOFM] = compare_exact_anyofm;
4858             dispatch[EXACTF][ANYOFM] = compare_exactf_anyofm;
4859             dispatch[EXACTFU][ANYOFM] = compare_exactf_anyofm;
4860             dispatch[NOTHING][ANYOFM] = compare_left_tail;
4861             dispatch[TAIL][ANYOFM] = compare_left_tail;
4862             dispatch[STAR][ANYOFM] = compare_mismatch;
4863             dispatch[PLUS][ANYOFM] = compare_left_plus;
4864             dispatch[CURLY][ANYOFM] = compare_left_curly;
4865             dispatch[CURLYM][ANYOFM] = compare_left_curly;
4866             dispatch[CURLYX][ANYOFM] = compare_left_curly;
4867             dispatch[OPEN][ANYOFM] = compare_left_open;
4868             dispatch[CLOSE][ANYOFM] = compare_left_tail;
4869             dispatch[IFMATCH][ANYOFM] = compare_after_assertion;
4870             dispatch[UNLESSM][ANYOFM] = compare_after_assertion;
4871             dispatch[MINMOD][ANYOFM] = compare_left_tail;
4872             dispatch[OPTIMIZED][ANYOFM] = compare_left_tail;
4873             #endif
4874            
4875 1           dispatch[SUCCEED][POSIXD] = compare_left_tail;
4876 1           dispatch[MBOL][POSIXD] = compare_bol;
4877 1           dispatch[SBOL][POSIXD] = compare_bol;
4878 1           dispatch[BOUND][POSIXD] = compare_mismatch;
4879 1           dispatch[NBOUND][POSIXD] = compare_mismatch;
4880 1           dispatch[REG_ANY][POSIXD] = compare_mismatch;
4881 1           dispatch[SANY][POSIXD] = compare_mismatch;
4882 1           dispatch[ANYOF][POSIXD] = compare_anyof_posix;
4883 1           dispatch[ANYOFD][POSIXD] = compare_anyof_posix;
4884             #ifdef RC_ANYOFM
4885             dispatch[ANYOFM][POSIXD] = compare_anyofm_posix;
4886             #endif
4887 1           dispatch[POSIXD][POSIXD] = compare_posix_posix;
4888 1           dispatch[POSIXU][POSIXD] = compare_posix_posix;
4889 1           dispatch[POSIXA][POSIXD] = compare_posix_posix;
4890 1           dispatch[NPOSIXD][POSIXD] = compare_mismatch;
4891 1           dispatch[NPOSIXU][POSIXD] = compare_mismatch;
4892 1           dispatch[NPOSIXA][POSIXD] = compare_mismatch;
4893 1           dispatch[BRANCH][POSIXD] = compare_left_branch;
4894 1           dispatch[EXACT][POSIXD] = compare_exact_posix;
4895 1           dispatch[EXACTF][POSIXD] = compare_exactf_posix;
4896 1           dispatch[EXACTFU][POSIXD] = compare_exactf_posix;
4897 1           dispatch[NOTHING][POSIXD] = compare_left_tail;
4898 1           dispatch[STAR][POSIXD] = compare_mismatch;
4899 1           dispatch[PLUS][POSIXD] = compare_left_plus;
4900 1           dispatch[CURLY][POSIXD] = compare_left_curly;
4901 1           dispatch[CURLYM][POSIXD] = compare_left_curly;
4902 1           dispatch[CURLYX][POSIXD] = compare_left_curly;
4903 1           dispatch[OPEN][POSIXD] = compare_left_open;
4904 1           dispatch[CLOSE][POSIXD] = compare_left_tail;
4905 1           dispatch[IFMATCH][POSIXD] = compare_after_assertion;
4906 1           dispatch[UNLESSM][POSIXD] = compare_after_assertion;
4907 1           dispatch[MINMOD][POSIXD] = compare_left_tail;
4908 1           dispatch[OPTIMIZED][POSIXD] = compare_left_tail;
4909              
4910 1           dispatch[SUCCEED][POSIXU] = compare_left_tail;
4911 1           dispatch[MBOL][POSIXU] = compare_bol;
4912 1           dispatch[SBOL][POSIXU] = compare_bol;
4913 1           dispatch[BOUND][POSIXU] = compare_mismatch;
4914 1           dispatch[NBOUND][POSIXU] = compare_mismatch;
4915 1           dispatch[REG_ANY][POSIXU] = compare_mismatch;
4916 1           dispatch[SANY][POSIXU] = compare_mismatch;
4917 1           dispatch[ANYOF][POSIXU] = compare_anyof_posix;
4918 1           dispatch[ANYOFD][POSIXU] = compare_anyof_posix;
4919             #ifdef RC_ANYOFM
4920             dispatch[ANYOFM][POSIXU] = compare_anyofm_posix;
4921             #endif
4922 1           dispatch[POSIXD][POSIXU] = compare_posix_posix;
4923 1           dispatch[POSIXA][POSIXU] = compare_posix_posix;
4924 1           dispatch[POSIXU][POSIXU] = compare_posix_posix;
4925 1           dispatch[NPOSIXD][POSIXU] = compare_mismatch;
4926 1           dispatch[NPOSIXU][POSIXU] = compare_mismatch;
4927 1           dispatch[NPOSIXA][POSIXU] = compare_mismatch;
4928 1           dispatch[BRANCH][POSIXU] = compare_left_branch;
4929 1           dispatch[EXACT][POSIXU] = compare_exact_posix;
4930 1           dispatch[EXACTF][POSIXU] = compare_exact_posix;
4931 1           dispatch[EXACTFU][POSIXU] = compare_exact_posix;
4932 1           dispatch[NOTHING][POSIXU] = compare_left_tail;
4933 1           dispatch[TAIL][POSIXU] = compare_left_tail;
4934 1           dispatch[STAR][POSIXU] = compare_mismatch;
4935 1           dispatch[PLUS][POSIXU] = compare_left_plus;
4936 1           dispatch[CURLY][POSIXU] = compare_left_curly;
4937 1           dispatch[CURLYM][POSIXU] = compare_left_curly;
4938 1           dispatch[CURLYX][POSIXU] = compare_left_curly;
4939 1           dispatch[OPEN][POSIXU] = compare_left_open;
4940 1           dispatch[CLOSE][POSIXU] = compare_left_tail;
4941 1           dispatch[IFMATCH][POSIXU] = compare_after_assertion;
4942 1           dispatch[UNLESSM][POSIXU] = compare_after_assertion;
4943 1           dispatch[MINMOD][POSIXU] = compare_left_tail;
4944 1           dispatch[OPTIMIZED][POSIXU] = compare_left_tail;
4945              
4946 1           dispatch[SUCCEED][POSIXA] = compare_left_tail;
4947 1           dispatch[MBOL][POSIXA] = compare_bol;
4948 1           dispatch[SBOL][POSIXA] = compare_bol;
4949 1           dispatch[BOUND][POSIXA] = compare_mismatch;
4950 1           dispatch[NBOUND][POSIXA] = compare_mismatch;
4951 1           dispatch[REG_ANY][POSIXA] = compare_mismatch;
4952 1           dispatch[SANY][POSIXA] = compare_mismatch;
4953 1           dispatch[ANYOF][POSIXA] = compare_anyof_posixa;
4954 1           dispatch[ANYOFD][POSIXA] = compare_anyof_posixa;
4955             #ifdef RC_ANYOFM
4956             dispatch[ANYOFM][POSIXA] = compare_anyofm_posix;
4957             #endif
4958 1           dispatch[POSIXD][POSIXA] = compare_mismatch;
4959 1           dispatch[POSIXU][POSIXA] = compare_mismatch;
4960 1           dispatch[POSIXA][POSIXA] = compare_posix_posix;
4961 1           dispatch[NPOSIXD][POSIXA] = compare_mismatch;
4962 1           dispatch[NPOSIXU][POSIXA] = compare_mismatch;
4963 1           dispatch[NPOSIXA][POSIXA] = compare_mismatch;
4964 1           dispatch[BRANCH][POSIXA] = compare_left_branch;
4965 1           dispatch[EXACT][POSIXA] = compare_exact_posix;
4966 1           dispatch[EXACTF][POSIXA] = compare_exact_posix;
4967 1           dispatch[EXACTFU][POSIXA] = compare_exact_posix;
4968 1           dispatch[NOTHING][POSIXA] = compare_left_tail;
4969 1           dispatch[STAR][POSIXA] = compare_mismatch;
4970 1           dispatch[PLUS][POSIXA] = compare_left_plus;
4971 1           dispatch[CURLY][POSIXA] = compare_left_curly;
4972 1           dispatch[CURLYM][POSIXA] = compare_left_curly;
4973 1           dispatch[CURLYX][POSIXA] = compare_left_curly;
4974 1           dispatch[OPEN][POSIXA] = compare_left_open;
4975 1           dispatch[CLOSE][POSIXA] = compare_left_tail;
4976 1           dispatch[IFMATCH][POSIXA] = compare_after_assertion;
4977 1           dispatch[UNLESSM][POSIXA] = compare_after_assertion;
4978 1           dispatch[MINMOD][POSIXA] = compare_left_tail;
4979 1           dispatch[OPTIMIZED][POSIXA] = compare_left_tail;
4980              
4981 1           dispatch[SUCCEED][NPOSIXD] = compare_left_tail;
4982 1           dispatch[MBOL][NPOSIXD] = compare_bol;
4983 1           dispatch[SBOL][NPOSIXD] = compare_bol;
4984 1           dispatch[BOUND][NPOSIXD] = compare_mismatch;
4985 1           dispatch[NBOUND][NPOSIXD] = compare_mismatch;
4986 1           dispatch[REG_ANY][NPOSIXD] = compare_mismatch;
4987 1           dispatch[SANY][NPOSIXD] = compare_mismatch;
4988 1           dispatch[ANYOF][NPOSIXD] = compare_anyof_negative_posix;
4989 1           dispatch[ANYOFD][NPOSIXD] = compare_anyof_negative_posix;
4990             #ifdef RC_ANYOFM
4991             dispatch[ANYOFM][NPOSIXD] = compare_anyofm_negative_posix;
4992             #endif
4993 1           dispatch[POSIXD][NPOSIXD] = compare_posix_negative_posix;
4994 1           dispatch[POSIXU][NPOSIXD] = compare_posix_negative_posix;
4995 1           dispatch[POSIXA][NPOSIXD] = compare_posix_negative_posix;
4996 1           dispatch[NPOSIXD][NPOSIXD] = compare_negative_posix_negative_posix;
4997 1           dispatch[NPOSIXU][NPOSIXD] = compare_negative_posix_negative_posix;
4998 1           dispatch[NPOSIXA][NPOSIXD] = compare_mismatch;
4999 1           dispatch[BRANCH][NPOSIXD] = compare_left_branch;
5000 1           dispatch[EXACT][NPOSIXD] = compare_exact_negative_posix;
5001 1           dispatch[EXACTF][NPOSIXD] = compare_exactf_negative_posix;
5002 1           dispatch[EXACTFU][NPOSIXD] = compare_exactf_negative_posix;
5003 1           dispatch[NOTHING][NPOSIXD] = compare_left_tail;
5004 1           dispatch[STAR][NPOSIXD] = compare_mismatch;
5005 1           dispatch[PLUS][NPOSIXD] = compare_left_plus;
5006 1           dispatch[CURLY][NPOSIXD] = compare_left_curly;
5007 1           dispatch[CURLYM][NPOSIXD] = compare_left_curly;
5008 1           dispatch[CURLYX][NPOSIXD] = compare_left_curly;
5009 1           dispatch[OPEN][NPOSIXD] = compare_left_open;
5010 1           dispatch[CLOSE][NPOSIXD] = compare_left_tail;
5011 1           dispatch[IFMATCH][NPOSIXD] = compare_after_assertion;
5012 1           dispatch[UNLESSM][NPOSIXD] = compare_after_assertion;
5013 1           dispatch[MINMOD][NPOSIXD] = compare_left_tail;
5014 1           dispatch[OPTIMIZED][NPOSIXD] = compare_left_tail;
5015              
5016 1           dispatch[SUCCEED][NPOSIXU] = compare_left_tail;
5017 1           dispatch[MBOL][NPOSIXU] = compare_bol;
5018 1           dispatch[SBOL][NPOSIXU] = compare_bol;
5019 1           dispatch[BOUND][NPOSIXU] = compare_mismatch;
5020 1           dispatch[NBOUND][NPOSIXU] = compare_mismatch;
5021 1           dispatch[REG_ANY][NPOSIXU] = compare_mismatch;
5022 1           dispatch[SANY][NPOSIXU] = compare_mismatch;
5023 1           dispatch[ANYOF][NPOSIXU] = compare_anyof_negative_posix;
5024 1           dispatch[ANYOFD][NPOSIXU] = compare_anyof_negative_posix;
5025             #ifdef RC_ANYOFM
5026             dispatch[ANYOFM][NPOSIXU] = compare_anyofm_negative_posix;
5027             #endif
5028 1           dispatch[POSIXD][NPOSIXU] = compare_posix_negative_posix;
5029 1           dispatch[POSIXU][NPOSIXU] = compare_posix_negative_posix;
5030 1           dispatch[POSIXA][NPOSIXU] = compare_posix_negative_posix;
5031 1           dispatch[NPOSIXD][NPOSIXU] = compare_negative_posix_negative_posix;
5032 1           dispatch[NPOSIXU][NPOSIXU] = compare_negative_posix_negative_posix;
5033 1           dispatch[NPOSIXA][NPOSIXU] = compare_mismatch;
5034 1           dispatch[BRANCH][NPOSIXU] = compare_left_branch;
5035 1           dispatch[EXACT][NPOSIXU] = compare_exact_negative_posix;
5036 1           dispatch[EXACTF][NPOSIXU] = compare_exactf_negative_posix;
5037 1           dispatch[EXACTFU][NPOSIXU] = compare_exactf_negative_posix;
5038 1           dispatch[NOTHING][NPOSIXU] = compare_left_tail;
5039 1           dispatch[STAR][NPOSIXU] = compare_mismatch;
5040 1           dispatch[PLUS][NPOSIXU] = compare_left_plus;
5041 1           dispatch[CURLY][NPOSIXU] = compare_left_curly;
5042 1           dispatch[CURLYM][NPOSIXU] = compare_left_curly;
5043 1           dispatch[CURLYX][NPOSIXU] = compare_left_curly;
5044 1           dispatch[OPEN][NPOSIXU] = compare_left_open;
5045 1           dispatch[CLOSE][NPOSIXU] = compare_left_tail;
5046 1           dispatch[IFMATCH][NPOSIXU] = compare_after_assertion;
5047 1           dispatch[UNLESSM][NPOSIXU] = compare_after_assertion;
5048 1           dispatch[MINMOD][NPOSIXU] = compare_left_tail;
5049 1           dispatch[OPTIMIZED][NPOSIXU] = compare_left_tail;
5050              
5051 1           dispatch[SUCCEED][NPOSIXA] = compare_left_tail;
5052 1           dispatch[MBOL][NPOSIXA] = compare_bol;
5053 1           dispatch[SBOL][NPOSIXA] = compare_bol;
5054 1           dispatch[BOUND][NPOSIXA] = compare_mismatch;
5055 1           dispatch[NBOUND][NPOSIXA] = compare_mismatch;
5056 1           dispatch[REG_ANY][NPOSIXA] = compare_mismatch;
5057 1           dispatch[SANY][NPOSIXA] = compare_mismatch;
5058 1           dispatch[ANYOF][NPOSIXA] = compare_anyof_negative_posix;
5059 1           dispatch[ANYOFD][NPOSIXA] = compare_anyof_negative_posix;
5060             #ifdef RC_ANYOFM
5061             dispatch[ANYOFM][NPOSIXA] = compare_anyofm_negative_posix;
5062             #endif
5063 1           dispatch[POSIXD][NPOSIXA] = compare_posix_negative_posix;
5064 1           dispatch[POSIXU][NPOSIXA] = compare_posix_negative_posix;
5065 1           dispatch[POSIXA][NPOSIXA] = compare_posix_negative_posix;
5066 1           dispatch[NPOSIXD][NPOSIXA] = compare_negative_posix_negative_posix;
5067 1           dispatch[NPOSIXU][NPOSIXA] = compare_negative_posix_negative_posix;
5068 1           dispatch[NPOSIXA][NPOSIXA] = compare_negative_posix_negative_posix;
5069 1           dispatch[BRANCH][NPOSIXA] = compare_left_branch;
5070 1           dispatch[EXACT][NPOSIXA] = compare_exact_negative_posix;
5071 1           dispatch[EXACTF][NPOSIXA] = compare_exactf_negative_posix;
5072 1           dispatch[EXACTFU][NPOSIXA] = compare_exactf_negative_posix;
5073 1           dispatch[NOTHING][NPOSIXA] = compare_left_tail;
5074 1           dispatch[STAR][NPOSIXA] = compare_mismatch;
5075 1           dispatch[PLUS][NPOSIXA] = compare_left_plus;
5076 1           dispatch[CURLY][NPOSIXA] = compare_left_curly;
5077 1           dispatch[CURLYM][NPOSIXA] = compare_left_curly;
5078 1           dispatch[CURLYX][NPOSIXA] = compare_left_curly;
5079 1           dispatch[OPEN][NPOSIXA] = compare_left_open;
5080 1           dispatch[CLOSE][NPOSIXA] = compare_left_tail;
5081 1           dispatch[IFMATCH][NPOSIXA] = compare_after_assertion;
5082 1           dispatch[UNLESSM][NPOSIXA] = compare_after_assertion;
5083 1           dispatch[MINMOD][NPOSIXA] = compare_left_tail;
5084 1           dispatch[OPTIMIZED][NPOSIXA] = compare_left_tail;
5085              
5086 93 100         for (i = 0; i < REGNODE_MAX; ++i)
5087             {
5088 92           dispatch[i][BRANCH] = compare_right_branch;
5089             }
5090              
5091 1           dispatch[SUCCEED][BRANCH] = compare_left_tail;
5092 1           dispatch[ANYOF][BRANCH] = compare_anyof_branch;
5093 1           dispatch[ANYOFD][BRANCH] = compare_anyof_branch;
5094             #ifdef RC_ANYOFM
5095             dispatch[ANYOFM][BRANCH] = compare_anyofm_branch;
5096             #endif
5097 1           dispatch[BRANCH][BRANCH] = compare_left_branch;
5098 1           dispatch[NOTHING][BRANCH] = compare_left_tail;
5099 1           dispatch[TAIL][BRANCH] = compare_left_tail;
5100 1           dispatch[WHILEM][BRANCH] = compare_left_tail;
5101 1           dispatch[OPEN][BRANCH] = compare_left_open;
5102 1           dispatch[CLOSE][BRANCH] = compare_left_tail;
5103 1           dispatch[IFMATCH][BRANCH] = compare_after_assertion;
5104 1           dispatch[UNLESSM][BRANCH] = compare_after_assertion;
5105 1           dispatch[MINMOD][BRANCH] = compare_left_tail;
5106 1           dispatch[OPTIMIZED][BRANCH] = compare_left_tail;
5107              
5108 1           dispatch[SUCCEED][EXACT] = compare_left_tail;
5109 1           dispatch[MBOL][EXACT] = compare_bol;
5110 1           dispatch[SBOL][EXACT] = compare_bol;
5111 1           dispatch[BOUND][EXACT] = compare_mismatch;
5112 1           dispatch[NBOUND][EXACT] = compare_mismatch;
5113 1           dispatch[REG_ANY][EXACT] = compare_mismatch;
5114 1           dispatch[SANY][EXACT] = compare_mismatch;
5115 1           dispatch[ANYOF][EXACT] = compare_anyof_exact;
5116 1           dispatch[ANYOFD][EXACT] = compare_anyof_exact;
5117             #ifdef RC_ANYOFM
5118             dispatch[ANYOFM][EXACT] = compare_anyofm_exact;
5119             #endif
5120 1           dispatch[POSIXD][EXACT] = compare_mismatch;
5121 1           dispatch[POSIXU][EXACT] = compare_mismatch;
5122 1           dispatch[POSIXA][EXACT] = compare_mismatch;
5123 1           dispatch[NPOSIXD][EXACT] = compare_mismatch;
5124 1           dispatch[NPOSIXU][EXACT] = compare_mismatch;
5125 1           dispatch[NPOSIXA][EXACT] = compare_mismatch;
5126 1           dispatch[BRANCH][EXACT] = compare_left_branch;
5127 1           dispatch[EXACT][EXACT] = compare_exact_exact;
5128 1           dispatch[EXACTF][EXACT] = compare_exactf_exact;
5129 1           dispatch[EXACTFU][EXACT] = compare_exactf_exact;
5130 1           dispatch[NOTHING][EXACT] = compare_left_tail;
5131 1           dispatch[TAIL][EXACT] = compare_left_tail;
5132 1           dispatch[STAR][EXACT] = compare_mismatch;
5133 1           dispatch[PLUS][EXACT] = compare_left_plus;
5134 1           dispatch[CURLY][EXACT] = compare_left_curly;
5135 1           dispatch[CURLYM][EXACT] = compare_left_curly;
5136 1           dispatch[CURLYX][EXACT] = compare_left_curly;
5137 1           dispatch[WHILEM][EXACT] = compare_left_tail;
5138 1           dispatch[OPEN][EXACT] = compare_left_open;
5139 1           dispatch[CLOSE][EXACT] = compare_left_tail;
5140 1           dispatch[IFMATCH][EXACT] = compare_after_assertion;
5141 1           dispatch[UNLESSM][EXACT] = compare_after_assertion;
5142 1           dispatch[MINMOD][EXACT] = compare_left_tail;
5143 1           dispatch[OPTIMIZED][EXACT] = compare_left_tail;
5144              
5145 1           dispatch[SUCCEED][EXACTF] = compare_left_tail;
5146 1           dispatch[MBOL][EXACTF] = compare_bol;
5147 1           dispatch[SBOL][EXACTF] = compare_bol;
5148 1           dispatch[BOUND][EXACTF] = compare_mismatch;
5149 1           dispatch[NBOUND][EXACTF] = compare_mismatch;
5150 1           dispatch[REG_ANY][EXACTF] = compare_mismatch;
5151 1           dispatch[SANY][EXACTF] = compare_mismatch;
5152 1           dispatch[ANYOF][EXACTF] = compare_anyof_exactf;
5153 1           dispatch[ANYOFD][EXACTF] = compare_anyof_exactf;
5154             #ifdef RC_ANYOFM
5155             dispatch[ANYOFM][EXACTF] = compare_anyofm_exactf;
5156             #endif
5157 1           dispatch[POSIXD][EXACTF] = compare_mismatch;
5158 1           dispatch[POSIXU][EXACTF] = compare_mismatch;
5159 1           dispatch[POSIXA][EXACTF] = compare_mismatch;
5160 1           dispatch[NPOSIXD][EXACTF] = compare_mismatch;
5161 1           dispatch[NPOSIXU][EXACTF] = compare_mismatch;
5162 1           dispatch[NPOSIXA][EXACTF] = compare_mismatch;
5163 1           dispatch[BRANCH][EXACTF] = compare_left_branch;
5164 1           dispatch[EXACT][EXACTF] = compare_exact_exactf;
5165 1           dispatch[EXACTF][EXACTF] = compare_exactf_exactf;
5166 1           dispatch[NOTHING][EXACTF] = compare_left_tail;
5167 1           dispatch[TAIL][EXACTF] = compare_left_tail;
5168 1           dispatch[STAR][EXACTF] = compare_mismatch;
5169 1           dispatch[PLUS][EXACTF] = compare_left_plus;
5170 1           dispatch[CURLY][EXACTF] = compare_left_curly;
5171 1           dispatch[CURLYM][EXACTF] = compare_left_curly;
5172 1           dispatch[CURLYX][EXACTF] = compare_left_curly;
5173 1           dispatch[WHILEM][EXACTF] = compare_left_tail;
5174 1           dispatch[OPEN][EXACTF] = compare_left_open;
5175 1           dispatch[CLOSE][EXACTF] = compare_left_tail;
5176 1           dispatch[IFMATCH][EXACTF] = compare_after_assertion;
5177 1           dispatch[UNLESSM][EXACTF] = compare_after_assertion;
5178 1           dispatch[MINMOD][EXACTF] = compare_left_tail;
5179 1           dispatch[OPTIMIZED][EXACTF] = compare_left_tail;
5180              
5181 1           dispatch[SUCCEED][EXACTFU] = compare_left_tail;
5182 1           dispatch[MBOL][EXACTFU] = compare_bol;
5183 1           dispatch[SBOL][EXACTFU] = compare_bol;
5184 1           dispatch[BOUND][EXACTFU] = compare_mismatch;
5185 1           dispatch[NBOUND][EXACTFU] = compare_mismatch;
5186 1           dispatch[REG_ANY][EXACTFU] = compare_mismatch;
5187 1           dispatch[SANY][EXACTFU] = compare_mismatch;
5188 1           dispatch[ANYOF][EXACTFU] = compare_anyof_exactf;
5189 1           dispatch[ANYOFD][EXACTFU] = compare_anyof_exactf;
5190             #ifdef RC_ANYOFM
5191             dispatch[ANYOFM][EXACTFU] = compare_anyofm_exactf;
5192             #endif
5193 1           dispatch[POSIXD][EXACTFU] = compare_mismatch;
5194 1           dispatch[POSIXU][EXACTFU] = compare_mismatch;
5195 1           dispatch[POSIXA][EXACTFU] = compare_mismatch;
5196 1           dispatch[NPOSIXD][EXACTFU] = compare_mismatch;
5197 1           dispatch[NPOSIXU][EXACTFU] = compare_mismatch;
5198 1           dispatch[NPOSIXA][EXACTFU] = compare_mismatch;
5199 1           dispatch[BRANCH][EXACTFU] = compare_left_branch;
5200 1           dispatch[EXACT][EXACTFU] = compare_exact_exactf;
5201 1           dispatch[EXACTFU][EXACTFU] = compare_exactf_exactf;
5202 1           dispatch[NOTHING][EXACTFU] = compare_left_tail;
5203 1           dispatch[STAR][EXACTFU] = compare_mismatch;
5204 1           dispatch[PLUS][EXACTFU] = compare_left_plus;
5205 1           dispatch[CURLY][EXACTFU] = compare_left_curly;
5206 1           dispatch[CURLYM][EXACTFU] = compare_left_curly;
5207 1           dispatch[CURLYX][EXACTFU] = compare_left_curly;
5208 1           dispatch[OPEN][EXACTFU] = compare_left_open;
5209 1           dispatch[CLOSE][EXACTFU] = compare_left_tail;
5210 1           dispatch[IFMATCH][EXACTFU] = compare_after_assertion;
5211 1           dispatch[UNLESSM][EXACTFU] = compare_after_assertion;
5212 1           dispatch[MINMOD][EXACTFU] = compare_left_tail;
5213 1           dispatch[OPTIMIZED][EXACTFU] = compare_left_tail;
5214              
5215 93 100         for (i = 0; i < REGNODE_MAX; ++i)
5216             {
5217 92           dispatch[i][NOTHING] = compare_next;
5218             }
5219              
5220 1           dispatch[SUCCEED][NOTHING] = compare_tails;
5221 1           dispatch[NOTHING][NOTHING] = compare_tails;
5222 1           dispatch[TAIL][NOTHING] = compare_tails;
5223 1           dispatch[WHILEM][NOTHING] = compare_tails;
5224 1           dispatch[CLOSE][NOTHING] = compare_tails;
5225 1           dispatch[MINMOD][NOTHING] = compare_tails;
5226 1           dispatch[OPTIMIZED][NOTHING] = compare_tails;
5227              
5228 93 100         for (i = 0; i < REGNODE_MAX; ++i)
5229             {
5230 92           dispatch[i][TAIL] = compare_next;
5231             }
5232              
5233 1           dispatch[SUCCEED][TAIL] = compare_tails;
5234 1           dispatch[NOTHING][TAIL] = compare_tails;
5235 1           dispatch[TAIL][TAIL] = compare_tails;
5236 1           dispatch[WHILEM][TAIL] = compare_tails;
5237 1           dispatch[CLOSE][TAIL] = compare_tails;
5238 1           dispatch[MINMOD][TAIL] = compare_tails;
5239 1           dispatch[OPTIMIZED][TAIL] = compare_tails;
5240              
5241 93 100         for (i = 0; i < REGNODE_MAX; ++i)
5242             {
5243 92           dispatch[i][STAR] = compare_right_star;
5244             }
5245              
5246 1           dispatch[SUCCEED][STAR] = compare_left_tail;
5247 1           dispatch[EOS][STAR] = compare_tails;
5248 1           dispatch[EOL][STAR] = compare_tails;
5249 1           dispatch[MEOL][STAR] = compare_tails;
5250 1           dispatch[SEOL][STAR] = compare_tails;
5251 1           dispatch[NOTHING][STAR] = compare_left_tail;
5252 1           dispatch[TAIL][STAR] = compare_left_tail;
5253 1           dispatch[STAR][STAR] = compare_repeat_star;
5254 1           dispatch[PLUS][STAR] = compare_repeat_star;
5255 1           dispatch[CURLY][STAR] = compare_curly_star;
5256 1           dispatch[CURLYM][STAR] = compare_curly_star;
5257 1           dispatch[CURLYX][STAR] = compare_curly_star;
5258 1           dispatch[WHILEM][STAR] = compare_left_tail;
5259 1           dispatch[OPEN][STAR] = compare_left_open;
5260 1           dispatch[CLOSE][STAR] = compare_left_tail;
5261 1           dispatch[IFMATCH][STAR] = compare_after_assertion;
5262 1           dispatch[UNLESSM][STAR] = compare_after_assertion;
5263 1           dispatch[MINMOD][STAR] = compare_left_tail;
5264 1           dispatch[OPTIMIZED][STAR] = compare_left_tail;
5265              
5266 93 100         for (i = 0; i < REGNODE_MAX; ++i)
5267             {
5268 92           dispatch[i][PLUS] = compare_right_plus;
5269             }
5270              
5271 1           dispatch[SUCCEED][PLUS] = compare_left_tail;
5272 1           dispatch[NOTHING][PLUS] = compare_left_tail;
5273 1           dispatch[TAIL][PLUS] = compare_left_tail;
5274 1           dispatch[PLUS][PLUS] = compare_plus_plus;
5275 1           dispatch[CURLY][PLUS] = compare_curly_plus;
5276 1           dispatch[CURLYM][PLUS] = compare_curly_plus;
5277 1           dispatch[CURLYX][PLUS] = compare_curly_plus;
5278 1           dispatch[WHILEM][PLUS] = compare_left_tail;
5279 1           dispatch[OPEN][PLUS] = compare_left_open;
5280 1           dispatch[CLOSE][PLUS] = compare_left_tail;
5281 1           dispatch[IFMATCH][PLUS] = compare_after_assertion;
5282 1           dispatch[UNLESSM][PLUS] = compare_after_assertion;
5283 1           dispatch[MINMOD][PLUS] = compare_left_tail;
5284 1           dispatch[OPTIMIZED][PLUS] = compare_left_tail;
5285              
5286 93 100         for (i = 0; i < REGNODE_MAX; ++i)
5287             {
5288 92           dispatch[i][CURLY] = compare_right_curly;
5289             }
5290              
5291 1           dispatch[SUCCEED][CURLY] = compare_left_tail;
5292 1           dispatch[NOTHING][CURLY] = compare_left_tail;
5293 1           dispatch[TAIL][CURLY] = compare_left_tail;
5294 1           dispatch[PLUS][CURLY] = compare_plus_curly;
5295 1           dispatch[CURLY][CURLY] = compare_curly_curly;
5296 1           dispatch[CURLYM][CURLY] = compare_curly_curly;
5297 1           dispatch[CURLYX][CURLY] = compare_curly_curly;
5298 1           dispatch[WHILEM][CURLY] = compare_left_tail;
5299 1           dispatch[OPEN][CURLY] = compare_left_open;
5300 1           dispatch[CLOSE][CURLY] = compare_left_tail;
5301 1           dispatch[IFMATCH][CURLY] = compare_after_assertion;
5302 1           dispatch[UNLESSM][CURLY] = compare_after_assertion;
5303 1           dispatch[SUSPEND][CURLY] = compare_suspend_curly;
5304 1           dispatch[MINMOD][CURLY] = compare_left_tail;
5305 1           dispatch[OPTIMIZED][CURLY] = compare_left_tail;
5306              
5307 93 100         for (i = 0; i < REGNODE_MAX; ++i)
5308             {
5309 92           dispatch[i][CURLYM] = compare_right_curly;
5310             }
5311              
5312 1           dispatch[SUCCEED][CURLYM] = compare_left_tail;
5313 1           dispatch[NOTHING][CURLYM] = compare_left_tail;
5314 1           dispatch[TAIL][CURLYM] = compare_left_tail;
5315 1           dispatch[PLUS][CURLYM] = compare_plus_curly;
5316 1           dispatch[CURLY][CURLYM] = compare_curly_curly;
5317 1           dispatch[CURLYM][CURLYM] = compare_curly_curly;
5318 1           dispatch[CURLYX][CURLYM] = compare_curly_curly;
5319 1           dispatch[WHILEM][CURLYM] = compare_left_tail;
5320 1           dispatch[OPEN][CURLYM] = compare_left_open;
5321 1           dispatch[CLOSE][CURLYM] = compare_left_tail;
5322 1           dispatch[IFMATCH][CURLYM] = compare_after_assertion;
5323 1           dispatch[UNLESSM][CURLYM] = compare_after_assertion;
5324 1           dispatch[SUSPEND][CURLYM] = compare_suspend_curly;
5325 1           dispatch[MINMOD][CURLYM] = compare_left_tail;
5326 1           dispatch[OPTIMIZED][CURLYM] = compare_left_tail;
5327              
5328 93 100         for (i = 0; i < REGNODE_MAX; ++i)
5329             {
5330 92           dispatch[i][CURLYX] = compare_right_curly;
5331             }
5332              
5333 1           dispatch[SUCCEED][CURLYX] = compare_left_tail;
5334 1           dispatch[NOTHING][CURLYX] = compare_left_tail;
5335 1           dispatch[TAIL][CURLYX] = compare_left_tail;
5336 1           dispatch[PLUS][CURLYX] = compare_plus_curly;
5337 1           dispatch[CURLY][CURLYX] = compare_curly_curly;
5338 1           dispatch[CURLYM][CURLYX] = compare_curly_curly;
5339 1           dispatch[CURLYX][CURLYX] = compare_curly_curly;
5340 1           dispatch[WHILEM][CURLYX] = compare_left_tail;
5341 1           dispatch[OPEN][CURLYX] = compare_left_open;
5342 1           dispatch[CLOSE][CURLYX] = compare_left_tail;
5343 1           dispatch[IFMATCH][CURLYX] = compare_after_assertion;
5344 1           dispatch[UNLESSM][CURLYX] = compare_after_assertion;
5345 1           dispatch[SUSPEND][CURLYX] = compare_suspend_curly;
5346 1           dispatch[MINMOD][CURLYX] = compare_left_tail;
5347 1           dispatch[OPTIMIZED][CURLYX] = compare_left_tail;
5348              
5349 93 100         for (i = 0; i < REGNODE_MAX; ++i)
5350             {
5351 92           dispatch[i][WHILEM] = compare_next;
5352             }
5353              
5354 1           dispatch[SUCCEED][WHILEM] = compare_tails;
5355 1           dispatch[NOTHING][WHILEM] = compare_tails;
5356 1           dispatch[TAIL][WHILEM] = compare_tails;
5357 1           dispatch[WHILEM][WHILEM] = compare_tails;
5358 1           dispatch[CLOSE][WHILEM] = compare_tails;
5359 1           dispatch[MINMOD][WHILEM] = compare_tails;
5360 1           dispatch[OPTIMIZED][WHILEM] = compare_tails;
5361              
5362 93 100         for (i = 0; i < REGNODE_MAX; ++i)
5363             {
5364 92           dispatch[i][OPEN] = compare_right_open;
5365             }
5366              
5367 1           dispatch[OPEN][OPEN] = compare_open_open;
5368              
5369 93 100         for (i = 0; i < REGNODE_MAX; ++i)
5370             {
5371 92           dispatch[i][CLOSE] = compare_next;
5372             }
5373              
5374 1           dispatch[SUCCEED][CLOSE] = compare_tails;
5375 1           dispatch[NOTHING][CLOSE] = compare_tails;
5376 1           dispatch[TAIL][CLOSE] = compare_tails;
5377 1           dispatch[WHILEM][CLOSE] = compare_tails;
5378 1           dispatch[CLOSE][CLOSE] = compare_tails;
5379 1           dispatch[MINMOD][CLOSE] = compare_tails;
5380 1           dispatch[OPTIMIZED][CLOSE] = compare_tails;
5381              
5382 1           dispatch[SUCCEED][IFMATCH] = compare_left_tail;
5383 1           dispatch[MBOL][IFMATCH] = compare_bol;
5384 1           dispatch[SBOL][IFMATCH] = compare_bol;
5385 1           dispatch[BOUND][IFMATCH] = compare_mismatch;
5386 1           dispatch[NBOUND][IFMATCH] = compare_mismatch;
5387 1           dispatch[REG_ANY][IFMATCH] = compare_mismatch;
5388 1           dispatch[SANY][IFMATCH] = compare_mismatch;
5389 1           dispatch[ANYOF][IFMATCH] = compare_mismatch;
5390 1           dispatch[ANYOFD][IFMATCH] = compare_mismatch;
5391             #ifdef RC_ANYOFM
5392             dispatch[ANYOFM][IFMATCH] = compare_mismatch;
5393             #endif
5394 1           dispatch[POSIXD][IFMATCH] = compare_mismatch;
5395 1           dispatch[POSIXU][IFMATCH] = compare_mismatch;
5396 1           dispatch[POSIXA][IFMATCH] = compare_mismatch;
5397 1           dispatch[NPOSIXD][IFMATCH] = compare_mismatch;
5398 1           dispatch[NPOSIXU][IFMATCH] = compare_mismatch;
5399 1           dispatch[NPOSIXA][IFMATCH] = compare_mismatch;
5400 1           dispatch[BRANCH][IFMATCH] = compare_mismatch;
5401 1           dispatch[EXACT][IFMATCH] = compare_mismatch;
5402 1           dispatch[EXACTF][IFMATCH] = compare_mismatch;
5403 1           dispatch[EXACTFU][IFMATCH] = compare_mismatch;
5404 1           dispatch[NOTHING][IFMATCH] = compare_left_tail;
5405 1           dispatch[TAIL][IFMATCH] = compare_left_tail;
5406 1           dispatch[STAR][IFMATCH] = compare_mismatch;
5407 1           dispatch[PLUS][IFMATCH] = compare_mismatch;
5408 1           dispatch[CURLY][IFMATCH] = compare_mismatch;
5409 1           dispatch[CURLYM][IFMATCH] = compare_mismatch;
5410 1           dispatch[CURLYX][IFMATCH] = compare_mismatch;
5411 1           dispatch[WHILEM][IFMATCH] = compare_left_tail;
5412 1           dispatch[OPEN][IFMATCH] = compare_left_open;
5413 1           dispatch[CLOSE][IFMATCH] = compare_left_tail;
5414 1           dispatch[IFMATCH][IFMATCH] = compare_positive_assertions;
5415 1           dispatch[UNLESSM][IFMATCH] = compare_mismatch;
5416 1           dispatch[MINMOD][IFMATCH] = compare_left_tail;
5417 1           dispatch[OPTIMIZED][IFMATCH] = compare_left_tail;
5418              
5419 1           dispatch[SUCCEED][UNLESSM] = compare_left_tail;
5420 1           dispatch[MBOL][UNLESSM] = compare_bol;
5421 1           dispatch[SBOL][UNLESSM] = compare_bol;
5422 1           dispatch[BOUND][UNLESSM] = compare_mismatch;
5423 1           dispatch[NBOUND][UNLESSM] = compare_mismatch;
5424 1           dispatch[REG_ANY][UNLESSM] = compare_mismatch;
5425 1           dispatch[SANY][UNLESSM] = compare_mismatch;
5426 1           dispatch[ANYOF][UNLESSM] = compare_mismatch;
5427 1           dispatch[ANYOFD][UNLESSM] = compare_mismatch;
5428             #ifdef RC_ANYOFM
5429             dispatch[ANYOFM][UNLESSM] = compare_mismatch;
5430             #endif
5431 1           dispatch[POSIXD][UNLESSM] = compare_mismatch;
5432 1           dispatch[POSIXU][UNLESSM] = compare_mismatch;
5433 1           dispatch[POSIXA][UNLESSM] = compare_mismatch;
5434 1           dispatch[NPOSIXD][UNLESSM] = compare_mismatch;
5435 1           dispatch[NPOSIXU][UNLESSM] = compare_mismatch;
5436 1           dispatch[NPOSIXA][UNLESSM] = compare_mismatch;
5437 1           dispatch[BRANCH][UNLESSM] = compare_mismatch;
5438 1           dispatch[EXACT][UNLESSM] = compare_mismatch;
5439 1           dispatch[EXACTF][UNLESSM] = compare_mismatch;
5440 1           dispatch[EXACTFU][UNLESSM] = compare_mismatch;
5441 1           dispatch[NOTHING][UNLESSM] = compare_left_tail;
5442 1           dispatch[TAIL][UNLESSM] = compare_left_tail;
5443 1           dispatch[STAR][UNLESSM] = compare_mismatch;
5444 1           dispatch[PLUS][UNLESSM] = compare_mismatch;
5445 1           dispatch[CURLY][UNLESSM] = compare_mismatch;
5446 1           dispatch[CURLYM][UNLESSM] = compare_mismatch;
5447 1           dispatch[CURLYX][UNLESSM] = compare_mismatch;
5448 1           dispatch[WHILEM][UNLESSM] = compare_left_tail;
5449 1           dispatch[OPEN][UNLESSM] = compare_left_open;
5450 1           dispatch[CLOSE][UNLESSM] = compare_left_tail;
5451 1           dispatch[IFMATCH][UNLESSM] = compare_mismatch;
5452 1           dispatch[UNLESSM][UNLESSM] = compare_negative_assertions;
5453 1           dispatch[MINMOD][UNLESSM] = compare_left_tail;
5454 1           dispatch[OPTIMIZED][UNLESSM] = compare_left_tail;
5455              
5456 1           dispatch[SUSPEND][SUSPEND] = compare_subexpressions;
5457              
5458 93 100         for (i = 0; i < REGNODE_MAX; ++i)
5459             {
5460 92           dispatch[i][MINMOD] = compare_next;
5461             }
5462              
5463 1           dispatch[SUCCEED][MINMOD] = compare_tails;
5464 1           dispatch[NOTHING][MINMOD] = compare_tails;
5465 1           dispatch[TAIL][MINMOD] = compare_tails;
5466 1           dispatch[WHILEM][MINMOD] = compare_tails;
5467 1           dispatch[CLOSE][MINMOD] = compare_tails;
5468 1           dispatch[MINMOD][MINMOD] = compare_tails;
5469 1           dispatch[OPTIMIZED][MINMOD] = compare_tails;
5470              
5471 93 100         for (i = 0; i < REGNODE_MAX; ++i)
5472             {
5473 92           dispatch[i][OPTIMIZED] = compare_next;
5474             }
5475              
5476 1           dispatch[SUCCEED][OPTIMIZED] = compare_tails;
5477 1           dispatch[NOTHING][OPTIMIZED] = compare_tails;
5478 1           dispatch[TAIL][OPTIMIZED] = compare_tails;
5479 1           dispatch[WHILEM][OPTIMIZED] = compare_tails;
5480 1           dispatch[CLOSE][OPTIMIZED] = compare_tails;
5481 1           dispatch[MINMOD][OPTIMIZED] = compare_tails;
5482 1           dispatch[OPTIMIZED][OPTIMIZED] = compare_tails;
5483 1           }