2 * re_*exec and friends - match REs
4 * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
6 * Development of this software was funded, in part, by Cray Research Inc.,
7 * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
8 * Corporation, none of whom are responsible for the results. The author
11 * Redistribution and use in source and binary forms -- with or without
12 * modification -- are permitted for any purpose, provided that
13 * redistributions in source form retain this entire copyright notice and
14 * indicate the origin and nature of any modifications.
16 * I'd appreciate being given credit for this package in the documentation
17 * of software which uses it, but that is not a requirement.
19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
21 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * $PostgreSQL: pgsql/src/backend/regex/regexec.c,v 1.25 2005/07/10 04:54:30 momjian Exp $
34 #include "regex/regguts.h"
38 /* lazy-DFA representation */
40 { /* "pointer" to an outarc */
47 unsigned *states; /* pointer to bitvector */
48 unsigned hash; /* hash of bitvector */
49 #define HASH(bv, nw) (((nw) == 1) ? *(bv) : hash(bv, nw))
50 #define HIT(h,bv,ss,nw) ((ss)->hash == (h) && ((nw) == 1 || \
51 memcmp(VS(bv), VS((ss)->states), (nw)*sizeof(unsigned)) == 0))
53 #define STARTER 01 /* the initial state set */
54 #define POSTSTATE 02 /* includes the goal state */
55 #define LOCKED 04 /* locked in cache */
56 #define NOPROGRESS 010 /* zero-progress state set */
57 struct arcp ins; /* chain of inarcs pointing here */
58 chr *lastseen; /* last entered on arrival here */
59 struct sset **outs; /* outarc vector indexed by color */
60 struct arcp *inchain; /* chain-pointer vector for outarcs */
65 int nssets; /* size of cache */
66 int nssused; /* how many entries occupied yet */
67 int nstates; /* number of states */
68 int ncolors; /* length of outarc and inchain vectors */
69 int wordsper; /* length of state-set bitvectors */
70 struct sset *ssets; /* state-set cache */
71 unsigned *statesarea; /* bitvector storage */
72 unsigned *work; /* pointer to work area within statesarea */
73 struct sset **outsarea; /* outarc-vector storage */
74 struct arcp *incarea; /* inchain storage */
77 chr *lastpost; /* location of last cache-flushed success */
78 chr *lastnopr; /* location of last cache-flushed
80 struct sset *search; /* replacement-search-pointer memory */
81 int cptsmalloced; /* were the areas individually malloced? */
82 char *mallocarea; /* self, or master malloced area, or NULL */
85 #define WORK 1 /* number of work bitvectors needed */
87 /* setup for non-malloc allocation for small cases */
88 #define FEWSTATES 20 /* must be less than UBITS */
93 struct sset ssets[FEWSTATES * 2];
94 unsigned statesarea[FEWSTATES * 2 + WORK];
95 struct sset *outsarea[FEWSTATES * 2 * FEWCOLORS];
96 struct arcp incarea[FEWSTATES * 2 * FEWCOLORS];
99 #define DOMALLOC ((struct smalldfa *)NULL) /* force malloc */
103 /* internal variables, bundled for easy passing around */
108 int eflags; /* copies of arguments */
111 rm_detail_t *details;
112 chr *start; /* start of string */
113 chr *search_start; /* search start of string */
114 chr *stop; /* just past end of string */
115 int err; /* error code if any (0 none) */
116 regoff_t *mem; /* memory vector for backtracking */
117 struct smalldfa dfa1;
118 struct smalldfa dfa2;
121 #define VISERR(vv) ((vv)->err != 0) /* have we seen an error yet? */
122 #define ISERR() VISERR(v)
123 #define VERR(vv,e) (((vv)->err) ? (vv)->err : ((vv)->err = (e)))
124 #define ERR(e) VERR(v, e) /* record an error */
125 #define NOERR() {if (ISERR()) return v->err;} /* if error seen, return
127 #define OFF(p) ((p) - v->start)
128 #define LOFF(p) ((long)OFF(p))
133 * forward declarations
135 /* === regexec.c === */
136 static int find(struct vars *, struct cnfa *, struct colormap *);
137 static int cfind(struct vars *, struct cnfa *, struct colormap *);
138 static int cfindloop(struct vars *, struct cnfa *, struct colormap *, struct dfa *, struct dfa *, chr **);
139 static void zapsubs(regmatch_t *, size_t);
140 static void zapmem(struct vars *, struct subre *);
141 static void subset(struct vars *, struct subre *, chr *, chr *);
142 static int dissect(struct vars *, struct subre *, chr *, chr *);
143 static int condissect(struct vars *, struct subre *, chr *, chr *);
144 static int altdissect(struct vars *, struct subre *, chr *, chr *);
145 static int cdissect(struct vars *, struct subre *, chr *, chr *);
146 static int ccondissect(struct vars *, struct subre *, chr *, chr *);
147 static int crevdissect(struct vars *, struct subre *, chr *, chr *);
148 static int cbrdissect(struct vars *, struct subre *, chr *, chr *);
149 static int caltdissect(struct vars *, struct subre *, chr *, chr *);
151 /* === rege_dfa.c === */
152 static chr *longest(struct vars *, struct dfa *, chr *, chr *, int *);
153 static chr *shortest(struct vars *, struct dfa *, chr *, chr *, chr *, chr **, int *);
154 static chr *lastcold(struct vars *, struct dfa *);
155 static struct dfa *newdfa(struct vars *, struct cnfa *, struct colormap *, struct smalldfa *);
156 static void freedfa(struct dfa *);
157 static unsigned hash(unsigned *, int);
158 static struct sset *initialize(struct vars *, struct dfa *, chr *);
159 static struct sset *miss(struct vars *, struct dfa *, struct sset *, pcolor, chr *, chr *);
160 static int lacon(struct vars *, struct cnfa *, chr *, pcolor);
161 static struct sset *getvacant(struct vars *, struct dfa *, chr *, chr *);
162 static struct sset *pickss(struct vars *, struct dfa *, chr *, chr *);
166 * pg_regexec - match regular expression
169 pg_regexec(regex_t *re,
173 rm_detail_t *details,
179 register struct vars *v = &var;
185 regmatch_t mat[LOCALMAT];
188 regoff_t mem[LOCALMEM];
191 if (re == NULL || string == NULL || re->re_magic != REMAGIC)
193 if (re->re_csize != sizeof(chr))
198 v->g = (struct guts *) re->re_guts;
199 if ((v->g->cflags & REG_EXPECT) && details == NULL)
201 if (v->g->info & REG_UIMPOSSIBLE)
203 backref = (v->g->info & REG_UBACKREF) ? 1 : 0;
205 if (v->g->cflags & REG_NOSUB)
206 nmatch = 0; /* override client */
211 if (v->g->nsub + 1 <= LOCALMAT)
214 v->pmatch = (regmatch_t *) MALLOC((v->g->nsub + 1) *
216 if (v->pmatch == NULL)
218 v->nmatch = v->g->nsub + 1;
222 v->details = details;
223 v->start = (chr *) string;
224 v->search_start = (chr *) string + search_start;
225 v->stop = (chr *) string + len;
229 /* need retry memory */
230 assert(v->g->ntree >= 0);
231 n = (size_t) v->g->ntree;
235 v->mem = (regoff_t *) MALLOC(n * sizeof(regoff_t));
238 if (v->pmatch != pmatch && v->pmatch != mat)
247 assert(v->g->tree != NULL);
249 st = cfind(v, &v->g->tree->cnfa, &v->g->cmap);
251 st = find(v, &v->g->tree->cnfa, &v->g->cmap);
253 /* copy (portion of) match vector over if necessary */
254 if (st == REG_OKAY && v->pmatch != pmatch && nmatch > 0)
256 zapsubs(pmatch, nmatch);
257 n = (nmatch < v->nmatch) ? nmatch : v->nmatch;
258 memcpy(VS(pmatch), VS(v->pmatch), n * sizeof(regmatch_t));
262 if (v->pmatch != pmatch && v->pmatch != mat)
264 if (v->mem != NULL && v->mem != mem)
270 * find - find a match for the main NFA (no-complications case)
273 find(struct vars * v,
275 struct colormap * cm)
282 chr *open; /* open and close of range of possible
286 int shorter = (v->g->tree->flags & SHORTER) ? 1 : 0;
288 /* first, a shot with the search RE */
289 s = newdfa(v, &v->g->search, cm, &v->dfa1);
290 assert(!(ISERR() && s != NULL));
292 MDEBUG(("\nsearch at %ld\n", LOFF(v->start)));
294 close = shortest(v, s, v->search_start, v->search_start, v->stop,
295 &cold, (int *) NULL);
298 if (v->g->cflags & REG_EXPECT)
300 assert(v->details != NULL);
302 v->details->rm_extend.rm_so = OFF(cold);
304 v->details->rm_extend.rm_so = OFF(v->stop);
305 v->details->rm_extend.rm_eo = OFF(v->stop); /* unknown */
307 if (close == NULL) /* not found */
309 if (v->nmatch == 0) /* found, don't need exact location */
312 /* find starting point and match */
313 assert(cold != NULL);
316 MDEBUG(("between %ld and %ld\n", LOFF(open), LOFF(close)));
317 d = newdfa(v, cnfa, cm, &v->dfa1);
318 assert(!(ISERR() && d != NULL));
320 for (begin = open; begin <= close; begin++)
322 MDEBUG(("\nfind trying at %ld\n", LOFF(begin)));
324 end = shortest(v, d, begin, begin, v->stop,
325 (chr **) NULL, &hitend);
327 end = longest(v, d, begin, v->stop, &hitend);
329 if (hitend && cold == NULL)
332 break; /* NOTE BREAK OUT */
334 assert(end != NULL); /* search RE succeeded so loop should */
337 /* and pin down details */
338 assert(v->nmatch > 0);
339 v->pmatch[0].rm_so = OFF(begin);
340 v->pmatch[0].rm_eo = OFF(end);
341 if (v->g->cflags & REG_EXPECT)
344 v->details->rm_extend.rm_so = OFF(cold);
346 v->details->rm_extend.rm_so = OFF(v->stop);
347 v->details->rm_extend.rm_eo = OFF(v->stop); /* unknown */
349 if (v->nmatch == 1) /* no need for submatches */
353 zapsubs(v->pmatch, v->nmatch);
354 return dissect(v, v->g->tree, begin, end);
358 * cfind - find a match for the main NFA (with complications)
361 cfind(struct vars * v,
363 struct colormap * cm)
370 s = newdfa(v, &v->g->search, cm, &v->dfa1);
372 d = newdfa(v, cnfa, cm, &v->dfa2);
380 ret = cfindloop(v, cnfa, cm, d, s, &cold);
385 if (v->g->cflags & REG_EXPECT)
387 assert(v->details != NULL);
389 v->details->rm_extend.rm_so = OFF(cold);
391 v->details->rm_extend.rm_so = OFF(v->stop);
392 v->details->rm_extend.rm_eo = OFF(v->stop); /* unknown */
398 * cfindloop - the heart of cfind
401 cfindloop(struct vars * v,
403 struct colormap * cm,
406 chr **coldp) /* where to put coldstart pointer */
411 chr *open; /* open and close of range of possible
417 int shorter = v->g->tree->flags & SHORTER;
420 assert(d != NULL && s != NULL);
422 close = v->search_start;
425 MDEBUG(("\ncsearch at %ld\n", LOFF(close)));
426 close = shortest(v, s, close, close, v->stop, &cold, (int *) NULL);
428 break; /* NOTE BREAK */
429 assert(cold != NULL);
432 MDEBUG(("cbetween %ld and %ld\n", LOFF(open), LOFF(close)));
433 for (begin = open; begin <= close; begin++)
435 MDEBUG(("\ncfind trying at %ld\n", LOFF(begin)));
441 end = shortest(v, d, begin, estart,
442 estop, (chr **) NULL, &hitend);
444 end = longest(v, d, begin, estop,
446 if (hitend && cold == NULL)
449 break; /* NOTE BREAK OUT */
450 MDEBUG(("tentative end %ld\n", LOFF(end)));
451 zapsubs(v->pmatch, v->nmatch);
452 zapmem(v, v->g->tree);
453 er = cdissect(v, v->g->tree, begin, end);
458 v->pmatch[0].rm_so = OFF(begin);
459 v->pmatch[0].rm_eo = OFF(end);
464 if (er != REG_NOMATCH)
469 if ((shorter) ? end == estop : end == begin)
471 /* no point in trying again */
475 /* go around and try again */
482 } while (close < v->stop);
489 * zapsubs - initialize the subexpression matches to "no match"
492 zapsubs(regmatch_t *p,
497 for (i = n - 1; i > 0; i--)
505 * zapmem - initialize the retry memory of a subtree to zeros
508 zapmem(struct vars * v,
514 assert(v->mem != NULL);
515 v->mem[t->retry] = 0;
518 assert(t->subno > 0);
519 v->pmatch[t->subno].rm_so = -1;
520 v->pmatch[t->subno].rm_eo = -1;
525 if (t->right != NULL)
530 * subset - set any subexpression relevant to a successful subre
533 subset(struct vars * v,
541 if ((size_t) n >= v->nmatch)
544 MDEBUG(("setting %d\n", n));
545 v->pmatch[n].rm_so = OFF(begin);
546 v->pmatch[n].rm_eo = OFF(end);
550 * dissect - determine subexpression matches (uncomplicated case)
552 static int /* regexec return code */
553 dissect(struct vars * v,
555 chr *begin, /* beginning of relevant substring */
556 chr *end) /* end of same */
559 MDEBUG(("dissect %ld-%ld\n", LOFF(begin), LOFF(end)));
563 case '=': /* terminal node */
564 assert(t->left == NULL && t->right == NULL);
565 return REG_OKAY; /* no action, parent did the work */
567 case '|': /* alternation */
568 assert(t->left != NULL);
569 return altdissect(v, t, begin, end);
571 case 'b': /* back ref -- shouldn't be calling us! */
574 case '.': /* concatenation */
575 assert(t->left != NULL && t->right != NULL);
576 return condissect(v, t, begin, end);
578 case '(': /* capturing */
579 assert(t->left != NULL && t->right == NULL);
580 assert(t->subno > 0);
581 subset(v, t, begin, end);
582 return dissect(v, t->left, begin, end);
591 * condissect - determine concatenation subexpression matches (uncomplicated)
593 static int /* regexec return code */
594 condissect(struct vars * v,
596 chr *begin, /* beginning of relevant substring */
597 chr *end) /* end of same */
603 int shorter = (t->left->flags & SHORTER) ? 1 : 0;
604 chr *stop = (shorter) ? end : begin;
606 assert(t->op == '.');
607 assert(t->left != NULL && t->left->cnfa.nstates > 0);
608 assert(t->right != NULL && t->right->cnfa.nstates > 0);
610 d = newdfa(v, &t->left->cnfa, &v->g->cmap, &v->dfa1);
612 d2 = newdfa(v, &t->right->cnfa, &v->g->cmap, &v->dfa2);
620 /* pick a tentative midpoint */
622 mid = shortest(v, d, begin, begin, end, (chr **) NULL,
625 mid = longest(v, d, begin, end, (int *) NULL);
632 MDEBUG(("tentative midpoint %ld\n", LOFF(mid)));
634 /* iterate until satisfaction or failure */
635 while (longest(v, d2, mid, end, (int *) NULL) != end)
637 /* that midpoint didn't work, find a new one */
640 /* all possibilities exhausted! */
641 MDEBUG(("no midpoint!\n"));
647 mid = shortest(v, d, begin, mid + 1, end, (chr **) NULL,
650 mid = longest(v, d, begin, mid - 1, (int *) NULL);
653 /* failed to find a new one! */
654 MDEBUG(("failed midpoint!\n"));
659 MDEBUG(("new midpoint %ld\n", LOFF(mid)));
663 MDEBUG(("successful\n"));
666 i = dissect(v, t->left, begin, mid);
669 return dissect(v, t->right, mid, end);
673 * altdissect - determine alternative subexpression matches (uncomplicated)
675 static int /* regexec return code */
676 altdissect(struct vars * v,
678 chr *begin, /* beginning of relevant substring */
679 chr *end) /* end of same */
685 assert(t->op == '|');
687 for (i = 0; t != NULL; t = t->right, i++)
689 MDEBUG(("trying %dth\n", i));
690 assert(t->left != NULL && t->left->cnfa.nstates > 0);
691 d = newdfa(v, &t->left->cnfa, &v->g->cmap, &v->dfa1);
694 if (longest(v, d, begin, end, (int *) NULL) == end)
696 MDEBUG(("success\n"));
698 return dissect(v, t->left, begin, end);
702 return REG_ASSERT; /* none of them matched?!? */
706 * cdissect - determine subexpression matches (with complications)
707 * The retry memory stores the offset of the trial midpoint from begin,
708 * plus 1 so that 0 uniquely means "clean slate".
710 static int /* regexec return code */
711 cdissect(struct vars * v,
713 chr *begin, /* beginning of relevant substring */
714 chr *end) /* end of same */
719 MDEBUG(("cdissect %ld-%ld %c\n", LOFF(begin), LOFF(end), t->op));
723 case '=': /* terminal node */
724 assert(t->left == NULL && t->right == NULL);
725 return REG_OKAY; /* no action, parent did the work */
727 case '|': /* alternation */
728 assert(t->left != NULL);
729 return caltdissect(v, t, begin, end);
731 case 'b': /* back ref -- shouldn't be calling us! */
732 assert(t->left == NULL && t->right == NULL);
733 return cbrdissect(v, t, begin, end);
735 case '.': /* concatenation */
736 assert(t->left != NULL && t->right != NULL);
737 return ccondissect(v, t, begin, end);
739 case '(': /* capturing */
740 assert(t->left != NULL && t->right == NULL);
741 assert(t->subno > 0);
742 er = cdissect(v, t->left, begin, end);
744 subset(v, t, begin, end);
754 * ccondissect - concatenation subexpression matches (with complications)
755 * The retry memory stores the offset of the trial midpoint from begin,
756 * plus 1 so that 0 uniquely means "clean slate".
758 static int /* regexec return code */
759 ccondissect(struct vars * v,
761 chr *begin, /* beginning of relevant substring */
762 chr *end) /* end of same */
769 assert(t->op == '.');
770 assert(t->left != NULL && t->left->cnfa.nstates > 0);
771 assert(t->right != NULL && t->right->cnfa.nstates > 0);
773 if (t->left->flags & SHORTER) /* reverse scan */
774 return crevdissect(v, t, begin, end);
776 d = newdfa(v, &t->left->cnfa, &v->g->cmap, DOMALLOC);
779 d2 = newdfa(v, &t->right->cnfa, &v->g->cmap, DOMALLOC);
785 MDEBUG(("cconcat %d\n", t->retry));
787 /* pick a tentative midpoint */
788 if (v->mem[t->retry] == 0)
790 mid = longest(v, d, begin, end, (int *) NULL);
797 MDEBUG(("tentative midpoint %ld\n", LOFF(mid)));
798 v->mem[t->retry] = (mid - begin) + 1;
802 mid = begin + (v->mem[t->retry] - 1);
803 MDEBUG(("working midpoint %ld\n", LOFF(mid)));
806 /* iterate until satisfaction or failure */
809 /* try this midpoint on for size */
810 er = cdissect(v, t->left, begin, mid);
811 if (er == REG_OKAY &&
812 longest(v, d2, mid, end, (int *) NULL) == end &&
813 (er = cdissect(v, t->right, mid, end)) ==
815 break; /* NOTE BREAK OUT */
816 if (er != REG_OKAY && er != REG_NOMATCH)
823 /* that midpoint didn't work, find a new one */
826 /* all possibilities exhausted */
827 MDEBUG(("%d no midpoint\n", t->retry));
832 mid = longest(v, d, begin, mid - 1, (int *) NULL);
835 /* failed to find a new one */
836 MDEBUG(("%d failed midpoint\n", t->retry));
841 MDEBUG(("%d: new midpoint %ld\n", t->retry, LOFF(mid)));
842 v->mem[t->retry] = (mid - begin) + 1;
848 MDEBUG(("successful\n"));
855 * crevdissect - determine backref shortest-first subexpression matches
856 * The retry memory stores the offset of the trial midpoint from begin,
857 * plus 1 so that 0 uniquely means "clean slate".
859 static int /* regexec return code */
860 crevdissect(struct vars * v,
862 chr *begin, /* beginning of relevant substring */
863 chr *end) /* end of same */
870 assert(t->op == '.');
871 assert(t->left != NULL && t->left->cnfa.nstates > 0);
872 assert(t->right != NULL && t->right->cnfa.nstates > 0);
873 assert(t->left->flags & SHORTER);
875 /* concatenation -- need to split the substring between parts */
876 d = newdfa(v, &t->left->cnfa, &v->g->cmap, DOMALLOC);
879 d2 = newdfa(v, &t->right->cnfa, &v->g->cmap, DOMALLOC);
885 MDEBUG(("crev %d\n", t->retry));
887 /* pick a tentative midpoint */
888 if (v->mem[t->retry] == 0)
890 mid = shortest(v, d, begin, begin, end, (chr **) NULL, (int *) NULL);
897 MDEBUG(("tentative midpoint %ld\n", LOFF(mid)));
898 v->mem[t->retry] = (mid - begin) + 1;
902 mid = begin + (v->mem[t->retry] - 1);
903 MDEBUG(("working midpoint %ld\n", LOFF(mid)));
906 /* iterate until satisfaction or failure */
909 /* try this midpoint on for size */
910 er = cdissect(v, t->left, begin, mid);
911 if (er == REG_OKAY &&
912 longest(v, d2, mid, end, (int *) NULL) == end &&
913 (er = cdissect(v, t->right, mid, end)) ==
915 break; /* NOTE BREAK OUT */
916 if (er != REG_OKAY && er != REG_NOMATCH)
923 /* that midpoint didn't work, find a new one */
926 /* all possibilities exhausted */
927 MDEBUG(("%d no midpoint\n", t->retry));
932 mid = shortest(v, d, begin, mid + 1, end, (chr **) NULL, (int *) NULL);
935 /* failed to find a new one */
936 MDEBUG(("%d failed midpoint\n", t->retry));
941 MDEBUG(("%d: new midpoint %ld\n", t->retry, LOFF(mid)));
942 v->mem[t->retry] = (mid - begin) + 1;
948 MDEBUG(("successful\n"));
955 * cbrdissect - determine backref subexpression matches
957 static int /* regexec return code */
958 cbrdissect(struct vars * v,
960 chr *begin, /* beginning of relevant substring */
961 chr *end) /* end of same */
973 assert(t->op == 'b');
975 assert((size_t) n < v->nmatch);
977 MDEBUG(("cbackref n%d %d{%d-%d}\n", t->retry, n, min, max));
979 if (v->pmatch[n].rm_so == -1)
981 paren = v->start + v->pmatch[n].rm_so;
982 len = v->pmatch[n].rm_eo - v->pmatch[n].rm_so;
984 /* no room to maneuver -- retries are pointless */
985 if (v->mem[t->retry])
987 v->mem[t->retry] = 1;
989 /* special-case zero-length string */
997 /* and too-short string */
998 assert(end >= begin);
999 if ((size_t) (end - begin) < len)
1003 /* count occurrences */
1005 for (p = begin; p <= stop && (i < max || max == INFINITY); p += len)
1007 if ((*v->g->compare) (paren, p, len) != 0)
1011 MDEBUG(("cbackref found %d\n", i));
1013 /* and sort it out */
1014 if (p != end) /* didn't consume all of it */
1016 if (min <= i && (i <= max || max == INFINITY))
1018 return REG_NOMATCH; /* out of range */
1022 * caltdissect - determine alternative subexpression matches (w. complications)
1024 static int /* regexec return code */
1025 caltdissect(struct vars * v,
1027 chr *begin, /* beginning of relevant substring */
1028 chr *end) /* end of same */
1033 #define UNTRIED 0 /* not yet tried at all */
1034 #define TRYING 1 /* top matched, trying submatches */
1035 #define TRIED 2 /* top didn't match or submatches
1040 assert(t->op == '|');
1041 if (v->mem[t->retry] == TRIED)
1042 return caltdissect(v, t->right, begin, end);
1044 MDEBUG(("calt n%d\n", t->retry));
1045 assert(t->left != NULL);
1047 if (v->mem[t->retry] == UNTRIED)
1049 d = newdfa(v, &t->left->cnfa, &v->g->cmap, DOMALLOC);
1052 if (longest(v, d, begin, end, (int *) NULL) != end)
1055 v->mem[t->retry] = TRIED;
1056 return caltdissect(v, t->right, begin, end);
1059 MDEBUG(("calt matched\n"));
1060 v->mem[t->retry] = TRYING;
1063 er = cdissect(v, t->left, begin, end);
1064 if (er != REG_NOMATCH)
1067 v->mem[t->retry] = TRIED;
1068 return caltdissect(v, t->right, begin, end);
1073 #include "rege_dfa.c"