perldoc diffs: don't search auto - much faster
[p5sagit/p5-mst-13.2.git] / regexec.c
1 /*    regexec.c
2  */
3
4 /*
5  * "One Ring to rule them all, One Ring to find them..."
6  */
7
8 /* NOTE: this is derived from Henry Spencer's regexp code, and should not
9  * confused with the original package (see point 3 below).  Thanks, Henry!
10  */
11
12 /* Additional note: this code is very heavily munged from Henry's version
13  * in places.  In some spots I've traded clarity for efficiency, so don't
14  * blame Henry for some of the lack of readability.
15  */
16
17 /* The names of the functions have been changed from regcomp and
18  * regexec to  pregcomp and pregexec in order to avoid conflicts
19  * with the POSIX routines of the same names.
20 */
21
22 /*SUPPRESS 112*/
23 /*
24  * pregcomp and pregexec -- regsub and regerror are not used in perl
25  *
26  *      Copyright (c) 1986 by University of Toronto.
27  *      Written by Henry Spencer.  Not derived from licensed software.
28  *
29  *      Permission is granted to anyone to use this software for any
30  *      purpose on any computer system, and to redistribute it freely,
31  *      subject to the following restrictions:
32  *
33  *      1. The author is not responsible for the consequences of use of
34  *              this software, no matter how awful, even if they arise
35  *              from defects in it.
36  *
37  *      2. The origin of this software must not be misrepresented, either
38  *              by explicit claim or by omission.
39  *
40  *      3. Altered versions must be plainly marked as such, and must not
41  *              be misrepresented as being the original software.
42  *
43  ****    Alterations to Henry's code are...
44  ****
45  ****    Copyright (c) 1991-1997, Larry Wall
46  ****
47  ****    You may distribute under the terms of either the GNU General Public
48  ****    License or the Artistic License, as specified in the README file.
49  *
50  * Beware that some of this code is subtly aware of the way operator
51  * precedence is structured in regular expressions.  Serious changes in
52  * regular-expression syntax might require a total rethink.
53  */
54 #include "EXTERN.h"
55 #include "perl.h"
56 #include "regcomp.h"
57
58 #ifndef STATIC
59 #define STATIC  static
60 #endif
61
62 #ifdef DEBUGGING
63 static I32 regnarrate = 0;
64 static char* regprogram = 0;
65 #endif
66
67 /* Current curly descriptor */
68 typedef struct curcur CURCUR;
69 struct curcur {
70     int         parenfloor;     /* how far back to strip paren data */
71     int         cur;            /* how many instances of scan we've matched */
72     int         min;            /* the minimal number of scans to match */
73     int         max;            /* the maximal number of scans to match */
74     int         minmod;         /* whether to work our way up or down */
75     char *      scan;           /* the thing to match */
76     char *      next;           /* what has to match after it */
77     char *      lastloc;        /* where we started matching this scan */
78     CURCUR *    oldcc;          /* current curly before we started this one */
79 };
80
81 static CURCUR* regcc;
82
83 typedef I32 CHECKPOINT;
84
85 static CHECKPOINT regcppush _((I32 parenfloor));
86 static char * regcppop _((void));
87
88 static CHECKPOINT
89 regcppush(parenfloor)
90 I32 parenfloor;
91 {
92     int retval = savestack_ix;
93     int i = (regsize - parenfloor) * 3;
94     int p;
95
96     SSCHECK(i + 5);
97     for (p = regsize; p > parenfloor; p--) {
98         SSPUSHPTR(regendp[p]);
99         SSPUSHPTR(regstartp[p]);
100         SSPUSHINT(p);
101     }
102     SSPUSHINT(regsize);
103     SSPUSHINT(*reglastparen);
104     SSPUSHPTR(reginput);
105     SSPUSHINT(i + 3);
106     SSPUSHINT(SAVEt_REGCONTEXT);
107     return retval;
108 }
109
110 static char *
111 regcppop()
112 {
113     I32 i = SSPOPINT;
114     U32 paren = 0;
115     char *input;
116     char *tmps;
117     assert(i == SAVEt_REGCONTEXT);
118     i = SSPOPINT;
119     input = (char *) SSPOPPTR;
120     *reglastparen = SSPOPINT;
121     regsize = SSPOPINT;
122     for (i -= 3; i > 0; i -= 3) {
123         paren = (U32)SSPOPINT;
124         regstartp[paren] = (char *) SSPOPPTR;
125         tmps = (char*)SSPOPPTR;
126         if (paren <= *reglastparen)
127             regendp[paren] = tmps;
128     }
129     for (paren = *reglastparen + 1; paren <= regnpar; paren++) {
130         if (paren > regsize)
131             regstartp[paren] = Nullch;
132         regendp[paren] = Nullch;
133     }
134     return input;
135 }
136
137 /* After a successful match in WHILEM, we want to restore paren matches
138  * that have been overwritten by a failed match attempt in the process
139  * of reaching this success. We do this by restoring regstartp[i]
140  * wherever regendp[i] has not changed; if OPEN is changed to modify
141  * regendp[], the '== endp' test below should be changed to match.
142  * This corrects the error of:
143  *      0 > length [ "foobar" =~ / ( (foo) | (bar) )* /x ]->[1]
144  */
145 static void
146 regcppartblow()
147 {
148     I32 i = SSPOPINT;
149     U32 paren;
150     char *startp;
151     char *endp;
152     assert(i == SAVEt_REGCONTEXT);
153     i = SSPOPINT;
154     /* input, lastparen, size */
155     SSPOPPTR; SSPOPINT; SSPOPINT;
156     for (i -= 3; i > 0; i -= 3) {
157         paren = (U32)SSPOPINT;
158         startp = (char *) SSPOPPTR;
159         endp = (char *) SSPOPPTR;
160         if (paren <= *reglastparen && regendp[paren] == endp)
161             regstartp[paren] = startp;
162     }
163 }
164
165 #define regcpblow(cp) leave_scope(cp)
166
167 /*
168  * pregexec and friends
169  */
170
171 /*
172  * Forwards.
173  */
174
175 static I32 regmatch _((char *prog));
176 static I32 regrepeat _((char *p, I32 max));
177 static I32 regtry _((regexp *prog, char *startpos));
178 static bool reginclass _((char *p, I32 c));
179
180 static bool regtainted;         /* tainted information used? */
181
182 /*
183  - pregexec - match a regexp against a string
184  */
185 I32
186 pregexec(prog, stringarg, strend, strbeg, minend, screamer, safebase)
187 register regexp *prog;
188 char *stringarg;
189 register char *strend;  /* pointer to null at end of string */
190 char *strbeg;   /* real beginning of string */
191 I32 minend;     /* end of match must be at least minend after stringarg */
192 SV *screamer;
193 I32 safebase;   /* no need to remember string in subbase */
194 {
195     register char *s;
196     register char *c;
197     register char *startpos = stringarg;
198     register I32 tmp;
199     I32 minlen = 0;             /* must match at least this many chars */
200     I32 dontbother = 0; /* how many characters not to try at end */
201     CURCUR cc;
202
203     cc.cur = 0;
204     cc.oldcc = 0;
205     regcc = &cc;
206
207 #ifdef DEBUGGING
208     regnarrate = debug & 512;
209     regprogram = prog->program;
210 #endif
211
212     /* Be paranoid... */
213     if (prog == NULL || startpos == NULL) {
214         croak("NULL regexp parameter");
215         return 0;
216     }
217
218     if (startpos == strbeg)     /* is ^ valid at stringarg? */
219         regprev = '\n';
220     else {
221         regprev = stringarg[-1];
222         if (!multiline && regprev == '\n')
223             regprev = '\0';             /* force ^ to NOT match */
224     }
225
226     regprecomp = prog->precomp;
227     /* Check validity of program. */
228     if (UCHARAT(prog->program) != MAGIC) {
229         FAIL("corrupted regexp program");
230     }
231
232     regnpar = prog->nparens;
233     regtainted = FALSE;
234
235     /* If there is a "must appear" string, look for it. */
236     s = startpos;
237     if (prog->regmust != Nullsv &&
238         !(prog->reganch & ROPT_ANCH_GPOS) &&
239         (!(prog->reganch & ROPT_ANCH_BOL)
240          || (multiline && prog->regback >= 0)) )
241     {
242         if (stringarg == strbeg && screamer) {
243             if (screamfirst[BmRARE(prog->regmust)] >= 0)
244                     s = screaminstr(screamer,prog->regmust);
245             else
246                     s = Nullch;
247         }
248         else
249             s = fbm_instr((unsigned char*)s, (unsigned char*)strend,
250                 prog->regmust);
251         if (!s) {
252             ++BmUSEFUL(prog->regmust);  /* hooray */
253             goto phooey;        /* not present */
254         }
255         else if (prog->regback >= 0) {
256             s -= prog->regback;
257             if (s < startpos)
258                 s = startpos;
259             minlen = prog->regback + SvCUR(prog->regmust);
260         }
261         else if (!prog->naughty && --BmUSEFUL(prog->regmust) < 0) { /* boo */
262             SvREFCNT_dec(prog->regmust);
263             prog->regmust = Nullsv;     /* disable regmust */
264             s = startpos;
265         }
266         else {
267             s = startpos;
268             minlen = SvCUR(prog->regmust);
269         }
270     }
271
272     /* Mark beginning of line for ^ . */
273     regbol = startpos;
274
275     /* Mark end of line for $ (and such) */
276     regeol = strend;
277
278     /* see how far we have to get to not match where we matched before */
279     regtill = startpos+minend;
280
281     /* Simplest case:  anchored match need be tried only once. */
282     /*  [unless only anchor is BOL and multiline is set] */
283     if (prog->reganch & ROPT_ANCH) {
284         if (regtry(prog, startpos))
285             goto got_it;
286         else if (!(prog->reganch & ROPT_ANCH_GPOS) &&
287                  (multiline || (prog->reganch & ROPT_IMPLICIT)))
288         {
289             if (minlen)
290                 dontbother = minlen - 1;
291             strend -= dontbother;
292             /* for multiline we only have to try after newlines */
293             if (s > startpos)
294                 s--;
295             while (s < strend) {
296                 if (*s++ == '\n') {
297                     if (s < strend && regtry(prog, s))
298                         goto got_it;
299                 }
300             }
301         }
302         goto phooey;
303     }
304
305     /* Messy cases:  unanchored match. */
306     if (prog->regstart) {
307         if (prog->reganch & ROPT_SKIP) {  /* we have /x+whatever/ */
308             /* it must be a one character string */
309             char ch = SvPVX(prog->regstart)[0];
310             while (s < strend) {
311                 if (*s == ch) {
312                     if (regtry(prog, s))
313                         goto got_it;
314                     s++;
315                     while (s < strend && *s == ch)
316                         s++;
317                 }
318                 s++;
319             }
320         }
321         else if (SvTYPE(prog->regstart) == SVt_PVBM) {
322             /* We know what string it must start with. */
323             while ((s = fbm_instr((unsigned char*)s,
324               (unsigned char*)strend, prog->regstart)) != NULL)
325             {
326                 if (regtry(prog, s))
327                     goto got_it;
328                 s++;
329             }
330         }
331         else {                          /* Optimized fbm_instr: */
332             c = SvPVX(prog->regstart);
333             while ((s = ninstr(s, strend, c, c + SvCUR(prog->regstart))) != NULL)
334             {
335                 if (regtry(prog, s))
336                     goto got_it;
337                 s++;
338             }
339         }
340         goto phooey;
341     }
342     /*SUPPRESS 560*/
343     if (c = prog->regstclass) {
344         I32 doevery = (prog->reganch & ROPT_SKIP) == 0;
345
346         if (minlen)
347             dontbother = minlen - 1;
348         strend -= dontbother;   /* don't bother with what can't match */
349         tmp = 1;
350         /* We know what class it must start with. */
351         switch (OP(c)) {
352         case ANYOF:
353             c = OPERAND(c);
354             while (s < strend) {
355                 if (reginclass(c, *s)) {
356                     if (tmp && regtry(prog, s))
357                         goto got_it;
358                     else
359                         tmp = doevery;
360                 }
361                 else
362                     tmp = 1;
363                 s++;
364             }
365             break;
366         case BOUNDL:
367             regtainted = TRUE;
368             /* FALL THROUGH */
369         case BOUND:
370             if (minlen)
371                 dontbother++,strend--;
372             tmp = (s != startpos) ? UCHARAT(s - 1) : regprev;
373             tmp = ((OP(c) == BOUND ? isALNUM(tmp) : isALNUM_LC(tmp)) != 0);
374             while (s < strend) {
375                 if (tmp == !(OP(c) == BOUND ? isALNUM(*s) : isALNUM_LC(*s))) {
376                     tmp = !tmp;
377                     if (regtry(prog, s))
378                         goto got_it;
379                 }
380                 s++;
381             }
382             if ((minlen || tmp) && regtry(prog,s))
383                 goto got_it;
384             break;
385         case NBOUNDL:
386             regtainted = TRUE;
387             /* FALL THROUGH */
388         case NBOUND:
389             if (minlen)
390                 dontbother++,strend--;
391             tmp = (s != startpos) ? UCHARAT(s - 1) : regprev;
392             tmp = ((OP(c) == NBOUND ? isALNUM(tmp) : isALNUM_LC(tmp)) != 0);
393             while (s < strend) {
394                 if (tmp == !(OP(c) == NBOUND ? isALNUM(*s) : isALNUM_LC(*s)))
395                     tmp = !tmp;
396                 else if (regtry(prog, s))
397                     goto got_it;
398                 s++;
399             }
400             if ((minlen || !tmp) && regtry(prog,s))
401                 goto got_it;
402             break;
403         case ALNUM:
404             while (s < strend) {
405                 if (isALNUM(*s)) {
406                     if (tmp && regtry(prog, s))
407                         goto got_it;
408                     else
409                         tmp = doevery;
410                 }
411                 else
412                     tmp = 1;
413                 s++;
414             }
415             break;
416         case ALNUML:
417             regtainted = TRUE;
418             while (s < strend) {
419                 if (isALNUM_LC(*s)) {
420                     if (tmp && regtry(prog, s))
421                         goto got_it;
422                     else
423                         tmp = doevery;
424                 }
425                 else
426                     tmp = 1;
427                 s++;
428             }
429             break;
430         case NALNUM:
431             while (s < strend) {
432                 if (!isALNUM(*s)) {
433                     if (tmp && regtry(prog, s))
434                         goto got_it;
435                     else
436                         tmp = doevery;
437                 }
438                 else
439                     tmp = 1;
440                 s++;
441             }
442             break;
443         case NALNUML:
444             regtainted = TRUE;
445             while (s < strend) {
446                 if (!isALNUM_LC(*s)) {
447                     if (tmp && regtry(prog, s))
448                         goto got_it;
449                     else
450                         tmp = doevery;
451                 }
452                 else
453                     tmp = 1;
454                 s++;
455             }
456             break;
457         case SPACE:
458             while (s < strend) {
459                 if (isSPACE(*s)) {
460                     if (tmp && regtry(prog, s))
461                         goto got_it;
462                     else
463                         tmp = doevery;
464                 }
465                 else
466                     tmp = 1;
467                 s++;
468             }
469             break;
470         case SPACEL:
471             regtainted = TRUE;
472             while (s < strend) {
473                 if (isSPACE_LC(*s)) {
474                     if (tmp && regtry(prog, s))
475                         goto got_it;
476                     else
477                         tmp = doevery;
478                 }
479                 else
480                     tmp = 1;
481                 s++;
482             }
483             break;
484         case NSPACE:
485             while (s < strend) {
486                 if (!isSPACE(*s)) {
487                     if (tmp && regtry(prog, s))
488                         goto got_it;
489                     else
490                         tmp = doevery;
491                 }
492                 else
493                     tmp = 1;
494                 s++;
495             }
496             break;
497         case NSPACEL:
498             regtainted = TRUE;
499             while (s < strend) {
500                 if (!isSPACE_LC(*s)) {
501                     if (tmp && regtry(prog, s))
502                         goto got_it;
503                     else
504                         tmp = doevery;
505                 }
506                 else
507                     tmp = 1;
508                 s++;
509             }
510             break;
511         case DIGIT:
512             while (s < strend) {
513                 if (isDIGIT(*s)) {
514                     if (tmp && regtry(prog, s))
515                         goto got_it;
516                     else
517                         tmp = doevery;
518                 }
519                 else
520                     tmp = 1;
521                 s++;
522             }
523             break;
524         case NDIGIT:
525             while (s < strend) {
526                 if (!isDIGIT(*s)) {
527                     if (tmp && regtry(prog, s))
528                         goto got_it;
529                     else
530                         tmp = doevery;
531                 }
532                 else
533                     tmp = 1;
534                 s++;
535             }
536             break;
537         }
538     }
539     else {
540         if (minlen)
541             dontbother = minlen - 1;
542         strend -= dontbother;
543         /* We don't know much -- general case. */
544         do {
545             if (regtry(prog, s))
546                 goto got_it;
547         } while (s++ < strend);
548     }
549
550     /* Failure. */
551     goto phooey;
552
553 got_it:
554     strend += dontbother;       /* uncheat */
555     prog->subbeg = strbeg;
556     prog->subend = strend;
557     prog->exec_tainted = regtainted;
558
559     /* make sure $`, $&, $', and $digit will work later */
560     if (strbeg != prog->subbase) {
561         if (safebase) {
562             if (prog->subbase) {
563                 Safefree(prog->subbase);
564                 prog->subbase = Nullch;
565             }
566         }
567         else {
568             I32 i = strend - startpos + (stringarg - strbeg);
569             s = savepvn(strbeg, i);
570             Safefree(prog->subbase);
571             prog->subbase = s;
572             prog->subbeg = prog->subbase;
573             prog->subend = prog->subbase + i;
574             s = prog->subbase + (stringarg - strbeg);
575             for (i = 0; i <= prog->nparens; i++) {
576                 if (prog->endp[i]) {
577                     prog->startp[i] = s + (prog->startp[i] - startpos);
578                     prog->endp[i] = s + (prog->endp[i] - startpos);
579                 }
580             }
581         }
582     }
583     return 1;
584
585 phooey:
586     return 0;
587 }
588
589 /*
590  - regtry - try match at specific point
591  */
592 static I32                      /* 0 failure, 1 success */
593 regtry(prog, startpos)
594 regexp *prog;
595 char *startpos;
596 {
597     register I32 i;
598     register char **sp;
599     register char **ep;
600
601     reginput = startpos;
602     regstartp = prog->startp;
603     regendp = prog->endp;
604     reglastparen = &prog->lastparen;
605     prog->lastparen = 0;
606     regsize = 0;
607
608     sp = prog->startp;
609     ep = prog->endp;
610     if (prog->nparens) {
611         for (i = prog->nparens; i >= 0; i--) {
612             *sp++ = NULL;
613             *ep++ = NULL;
614         }
615     }
616     if (regmatch(prog->program + 1) && reginput >= regtill) {
617         prog->startp[0] = startpos;
618         prog->endp[0] = reginput;
619         return 1;
620     }
621     else
622         return 0;
623 }
624
625 /*
626  - regmatch - main matching routine
627  *
628  * Conceptually the strategy is simple:  check to see whether the current
629  * node matches, call self recursively to see whether the rest matches,
630  * and then act accordingly.  In practice we make some effort to avoid
631  * recursion, in particular by going through "ordinary" nodes (that don't
632  * need to know whether the rest of the match failed) by a loop instead of
633  * by recursion.
634  */
635 /* [lwall] I've hoisted the register declarations to the outer block in order to
636  * maybe save a little bit of pushing and popping on the stack.  It also takes
637  * advantage of machines that use a register save mask on subroutine entry.
638  */
639 static I32                      /* 0 failure, 1 success */
640 regmatch(prog)
641 char *prog;
642 {
643     register char *scan;        /* Current node. */
644     char *next;                 /* Next node. */
645     register I32 nextchar;
646     register I32 n;             /* no or next */
647     register I32 ln;            /* len or last */
648     register char *s;           /* operand or save */
649     register char *locinput = reginput;
650     register I32 c1, c2;        /* case fold search */
651     int minmod = 0;
652 #ifdef DEBUGGING
653     static int regindent = 0;
654     regindent++;
655 #endif
656
657     nextchar = UCHARAT(locinput);
658     scan = prog;
659     while (scan != NULL) {
660 #ifdef DEBUGGING
661 #define sayYES goto yes
662 #define sayNO goto no
663 #define saySAME(x) if (x) goto yes; else goto no
664         if (regnarrate) {
665             SV *prop = sv_newmortal();
666             regprop(prop, scan);
667             PerlIO_printf(Perl_debug_log, "%*s%2d%-8.8s\t<%.10s>\n",
668                           regindent*2, "", scan - regprogram,
669                           SvPVX(prop), locinput);
670         }
671 #else
672 #define sayYES return 1
673 #define sayNO return 0
674 #define saySAME(x) return x
675 #endif
676
677 #ifdef REGALIGN
678         next = scan + NEXT(scan);
679         if (next == scan)
680             next = NULL;
681 #else
682         next = regnext(scan);
683 #endif
684
685         switch (OP(scan)) {
686         case BOL:
687             if (locinput == regbol
688                 ? regprev == '\n'
689                 : ((nextchar || locinput < regeol) && locinput[-1] == '\n') )
690             {
691                 /* regtill = regbol; */
692                 break;
693             }
694             sayNO;
695         case MBOL:
696             if (locinput == regbol
697                 ? regprev == '\n'
698                 : ((nextchar || locinput < regeol) && locinput[-1] == '\n') )
699             {
700                 break;
701             }
702             sayNO;
703         case SBOL:
704             if (locinput == regbol && regprev == '\n')
705                 break;
706             sayNO;
707         case GPOS:
708             if (locinput == regbol)
709                 break;
710             sayNO;
711         case EOL:
712             if (multiline)
713                 goto meol;
714             else
715                 goto seol;
716         case MEOL:
717           meol:
718             if ((nextchar || locinput < regeol) && nextchar != '\n')
719                 sayNO;
720             break;
721         case SEOL:
722           seol:
723             if ((nextchar || locinput < regeol) && nextchar != '\n')
724                 sayNO;
725             if (regeol - locinput > 1)
726                 sayNO;
727             break;
728         case SANY:
729             if (!nextchar && locinput >= regeol)
730                 sayNO;
731             nextchar = UCHARAT(++locinput);
732             break;
733         case ANY:
734             if (!nextchar && locinput >= regeol || nextchar == '\n')
735                 sayNO;
736             nextchar = UCHARAT(++locinput);
737             break;
738         case EXACT:
739             s = OPERAND(scan);
740             ln = *s++;
741             /* Inline the first character, for speed. */
742             if (UCHARAT(s) != nextchar)
743                 sayNO;
744             if (regeol - locinput < ln)
745                 sayNO;
746             if (ln > 1 && memNE(s, locinput, ln))
747                 sayNO;
748             locinput += ln;
749             nextchar = UCHARAT(locinput);
750             break;
751         case EXACTFL:
752             regtainted = TRUE;
753             /* FALL THROUGH */
754         case EXACTF:
755             s = OPERAND(scan);
756             ln = *s++;
757             /* Inline the first character, for speed. */
758             if (UCHARAT(s) != nextchar &&
759                 UCHARAT(s) != ((OP(scan) == EXACTF)
760                                ? fold : fold_locale)[nextchar])
761                 sayNO;
762             if (regeol - locinput < ln)
763                 sayNO;
764             if (ln > 1 && (OP(scan) == EXACTF
765                            ? ibcmp(s, locinput, ln)
766                            : ibcmp_locale(s, locinput, ln)))
767                 sayNO;
768             locinput += ln;
769             nextchar = UCHARAT(locinput);
770             break;
771         case ANYOF:
772             s = OPERAND(scan);
773             if (nextchar < 0)
774                 nextchar = UCHARAT(locinput);
775             if (!reginclass(s, nextchar))
776                 sayNO;
777             if (!nextchar && locinput >= regeol)
778                 sayNO;
779             nextchar = UCHARAT(++locinput);
780             break;
781         case ALNUML:
782             regtainted = TRUE;
783             /* FALL THROUGH */
784         case ALNUM:
785             if (!nextchar)
786                 sayNO;
787             if (!(OP(scan) == ALNUM
788                   ? isALNUM(nextchar) : isALNUM_LC(nextchar)))
789                 sayNO;
790             nextchar = UCHARAT(++locinput);
791             break;
792         case NALNUML:
793             regtainted = TRUE;
794             /* FALL THROUGH */
795         case NALNUM:
796             if (!nextchar && locinput >= regeol)
797                 sayNO;
798             if (OP(scan) == NALNUM
799                 ? isALNUM(nextchar) : isALNUM_LC(nextchar))
800                 sayNO;
801             nextchar = UCHARAT(++locinput);
802             break;
803         case BOUNDL:
804         case NBOUNDL:
805             regtainted = TRUE;
806             /* FALL THROUGH */
807         case BOUND:
808         case NBOUND:
809             /* was last char in word? */
810             ln = (locinput != regbol) ? UCHARAT(locinput - 1) : regprev;
811             if (OP(scan) == BOUND || OP(scan) == NBOUND) {
812                 ln = isALNUM(ln);
813                 n = isALNUM(nextchar);
814             }
815             else {
816                 ln = isALNUM_LC(ln);
817                 n = isALNUM_LC(nextchar);
818             }
819             if (((!ln) == (!n)) == (OP(scan) == BOUND || OP(scan) == BOUNDL))
820                 sayNO;
821             break;
822         case SPACEL:
823             regtainted = TRUE;
824             /* FALL THROUGH */
825         case SPACE:
826             if (!nextchar && locinput >= regeol)
827                 sayNO;
828             if (!(OP(scan) == SPACE
829                   ? isSPACE(nextchar) : isSPACE_LC(nextchar)))
830                 sayNO;
831             nextchar = UCHARAT(++locinput);
832             break;
833         case NSPACEL:
834             regtainted = TRUE;
835             /* FALL THROUGH */
836         case NSPACE:
837             if (!nextchar)
838                 sayNO;
839             if (OP(scan) == SPACE
840                 ? isSPACE(nextchar) : isSPACE_LC(nextchar))
841                 sayNO;
842             nextchar = UCHARAT(++locinput);
843             break;
844         case DIGIT:
845             if (!isDIGIT(nextchar))
846                 sayNO;
847             nextchar = UCHARAT(++locinput);
848             break;
849         case NDIGIT:
850             if (!nextchar && locinput >= regeol)
851                 sayNO;
852             if (isDIGIT(nextchar))
853                 sayNO;
854             nextchar = UCHARAT(++locinput);
855             break;
856         case REFFL:
857             regtainted = TRUE;
858             /* FALL THROUGH */
859         case REF:
860         case REFF:
861             n = ARG1(scan);  /* which paren pair */
862             s = regstartp[n];
863             if (!s)
864                 sayNO;
865             if (!regendp[n])
866                 sayNO;
867             if (s == regendp[n])
868                 break;
869             /* Inline the first character, for speed. */
870             if (UCHARAT(s) != nextchar &&
871                 (OP(scan) == REF ||
872                  (UCHARAT(s) != ((OP(scan) == REFF
873                                  ? fold : fold_locale)[nextchar]))))
874                 sayNO;
875             ln = regendp[n] - s;
876             if (locinput + ln > regeol)
877                 sayNO;
878             if (ln > 1 && (OP(scan) == REF
879                            ? memNE(s, locinput, ln)
880                            : (OP(scan) == REFF
881                               ? ibcmp(s, locinput, ln)
882                               : ibcmp_locale(s, locinput, ln))))
883                 sayNO;
884             locinput += ln;
885             nextchar = UCHARAT(locinput);
886             break;
887
888         case NOTHING:
889             break;
890         case BACK:
891             break;
892         case OPEN:
893             n = ARG1(scan);  /* which paren pair */
894             regstartp[n] = locinput;
895             if (n > regsize)
896                 regsize = n;
897             break;
898         case CLOSE:
899             n = ARG1(scan);  /* which paren pair */
900             regendp[n] = locinput;
901             if (n > *reglastparen)
902                 *reglastparen = n;
903             break;
904         case CURLYX: {
905                 CURCUR cc;
906                 CHECKPOINT cp = savestack_ix;
907                 cc.oldcc = regcc;
908                 regcc = &cc;
909                 cc.parenfloor = *reglastparen;
910                 cc.cur = -1;
911                 cc.min = ARG1(scan);
912                 cc.max  = ARG2(scan);
913                 cc.scan = NEXTOPER(scan) + 4;
914                 cc.next = next;
915                 cc.minmod = minmod;
916                 cc.lastloc = 0;
917                 reginput = locinput;
918                 n = regmatch(PREVOPER(next));   /* start on the WHILEM */
919                 regcpblow(cp);
920                 regcc = cc.oldcc;
921                 saySAME(n);
922             }
923             /* NOT REACHED */
924         case WHILEM: {
925                 /*
926                  * This is really hard to understand, because after we match
927                  * what we're trying to match, we must make sure the rest of
928                  * the RE is going to match for sure, and to do that we have
929                  * to go back UP the parse tree by recursing ever deeper.  And
930                  * if it fails, we have to reset our parent's current state
931                  * that we can try again after backing off.
932                  */
933
934                 CHECKPOINT cp;
935                 CURCUR* cc = regcc;
936                 n = cc->cur + 1;        /* how many we know we matched */
937                 reginput = locinput;
938
939 #ifdef DEBUGGING
940                 if (regnarrate)
941                     PerlIO_printf(Perl_debug_log, "%*s  %ld  %lx\n", regindent*2, "",
942                         (long)n, (long)cc);
943 #endif
944
945                 /* If degenerate scan matches "", assume scan done. */
946
947                 if (locinput == cc->lastloc && n >= cc->min) {
948                     regcc = cc->oldcc;
949                     ln = regcc->cur;
950                     if (regmatch(cc->next))
951                         sayYES;
952                     regcc->cur = ln;
953                     regcc = cc;
954                     sayNO;
955                 }
956
957                 /* First just match a string of min scans. */
958
959                 if (n < cc->min) {
960                     cc->cur = n;
961                     cc->lastloc = locinput;
962                     if (regmatch(cc->scan))
963                         sayYES;
964                     cc->cur = n - 1;
965                     sayNO;
966                 }
967
968                 /* Prefer next over scan for minimal matching. */
969
970                 if (cc->minmod) {
971                     regcc = cc->oldcc;
972                     ln = regcc->cur;
973                     cp = regcppush(cc->parenfloor);
974                     if (regmatch(cc->next)) {
975                         regcppartblow(cp);
976                         sayYES; /* All done. */
977                     }
978                     regcppop();
979                     regcc->cur = ln;
980                     regcc = cc;
981
982                     if (n >= cc->max)   /* Maximum greed exceeded? */
983                         sayNO;
984
985                     /* Try scanning more and see if it helps. */
986                     reginput = locinput;
987                     cc->cur = n;
988                     cc->lastloc = locinput;
989                     cp = regcppush(cc->parenfloor);
990                     if (regmatch(cc->scan)) {
991                         regcppartblow(cp);
992                         sayYES;
993                     }
994                     regcppop();
995                     cc->cur = n - 1;
996                     sayNO;
997                 }
998
999                 /* Prefer scan over next for maximal matching. */
1000
1001                 if (n < cc->max) {      /* More greed allowed? */
1002                     cp = regcppush(cc->parenfloor);
1003                     cc->cur = n;
1004                     cc->lastloc = locinput;
1005                     if (regmatch(cc->scan)) {
1006                         regcppartblow(cp);
1007                         sayYES;
1008                     }
1009                     regcppop();         /* Restore some previous $<digit>s? */
1010                     reginput = locinput;
1011                 }
1012
1013                 /* Failed deeper matches of scan, so see if this one works. */
1014                 regcc = cc->oldcc;
1015                 ln = regcc->cur;
1016                 if (regmatch(cc->next))
1017                     sayYES;
1018                 regcc->cur = ln;
1019                 regcc = cc;
1020                 cc->cur = n - 1;
1021                 sayNO;
1022             }
1023             /* NOT REACHED */
1024         case BRANCH: {
1025                 if (OP(next) != BRANCH)   /* No choice. */
1026                     next = NEXTOPER(scan);/* Avoid recursion. */
1027                 else {
1028                     int lastparen = *reglastparen;
1029                     do {
1030                         reginput = locinput;
1031                         if (regmatch(NEXTOPER(scan)))
1032                             sayYES;
1033                         for (n = *reglastparen; n > lastparen; n--)
1034                             regendp[n] = 0;
1035                         *reglastparen = n;
1036                             
1037 #ifdef REGALIGN
1038                         /*SUPPRESS 560*/
1039                         if (n = NEXT(scan))
1040                             scan += n;
1041                         else
1042                             scan = NULL;
1043 #else
1044                         scan = regnext(scan);
1045 #endif
1046                     } while (scan != NULL && OP(scan) == BRANCH);
1047                     sayNO;
1048                     /* NOTREACHED */
1049                 }
1050             }
1051             break;
1052         case MINMOD:
1053             minmod = 1;
1054             break;
1055         case CURLY:
1056             ln = ARG1(scan);  /* min to match */
1057             n  = ARG2(scan);  /* max to match */
1058             scan = NEXTOPER(scan) + 4;
1059             goto repeat;
1060         case STAR:
1061             ln = 0;
1062             n = 32767;
1063             scan = NEXTOPER(scan);
1064             goto repeat;
1065         case PLUS:
1066             /*
1067             * Lookahead to avoid useless match attempts
1068             * when we know what character comes next.
1069             */
1070             ln = 1;
1071             n = 32767;
1072             scan = NEXTOPER(scan);
1073           repeat:
1074             if (regkind[(U8)OP(next)] == EXACT) {
1075                 c1 = UCHARAT(OPERAND(next) + 1);
1076                 if (OP(next) == EXACTF)
1077                     c2 = fold[c1];
1078                 else if (OP(next) == EXACTFL)
1079                     c2 = fold_locale[c1];
1080                 else
1081                     c2 = c1;
1082             }
1083             else
1084                 c1 = c2 = -1000;
1085             reginput = locinput;
1086             if (minmod) {
1087                 minmod = 0;
1088                 if (ln && regrepeat(scan, ln) < ln)
1089                     sayNO;
1090                 while (n >= ln || (n == 32767 && ln > 0)) { /* ln overflow ? */
1091                     /* If it could work, try it. */
1092                     if (c1 == -1000 ||
1093                         UCHARAT(reginput) == c1 ||
1094                         UCHARAT(reginput) == c2)
1095                     {
1096                         if (regmatch(next))
1097                             sayYES;
1098                     }
1099                     /* Couldn't or didn't -- back up. */
1100                     reginput = locinput + ln;
1101                     if (regrepeat(scan, 1)) {
1102                         ln++;
1103                         reginput = locinput + ln;
1104                     }
1105                     else
1106                         sayNO;
1107                 }
1108             }
1109             else {
1110                 n = regrepeat(scan, n);
1111                 if (ln < n && regkind[(U8)OP(next)] == EOL &&
1112                     (!multiline || OP(next) == SEOL))
1113                     ln = n;                     /* why back off? */
1114                 while (n >= ln) {
1115                     /* If it could work, try it. */
1116                     if (c1 == -1000 ||
1117                         UCHARAT(reginput) == c1 ||
1118                         UCHARAT(reginput) == c2)
1119                     {
1120                         if (regmatch(next))
1121                             sayYES;
1122                     }
1123                     /* Couldn't or didn't -- back up. */
1124                     n--;
1125                     reginput = locinput + n;
1126                 }
1127             }
1128             sayNO;
1129         case SUCCEED:
1130         case END:
1131             reginput = locinput;        /* put where regtry can find it */
1132             sayYES;                     /* Success! */
1133         case IFMATCH:
1134             reginput = locinput;
1135             scan = NEXTOPER(scan);
1136             if (!regmatch(scan))
1137                 sayNO;
1138             break;
1139         case UNLESSM:
1140             reginput = locinput;
1141             scan = NEXTOPER(scan);
1142             if (regmatch(scan))
1143                 sayNO;
1144             break;
1145         default:
1146             PerlIO_printf(PerlIO_stderr(), "%lx %d\n",
1147                           (unsigned long)scan, scan[1]);
1148             FAIL("regexp memory corruption");
1149         }
1150         scan = next;
1151     }
1152
1153     /*
1154     * We get here only if there's trouble -- normally "case END" is
1155     * the terminating point.
1156     */
1157     FAIL("corrupted regexp pointers");
1158     /*NOTREACHED*/
1159     sayNO;
1160
1161 yes:
1162 #ifdef DEBUGGING
1163     regindent--;
1164 #endif
1165     return 1;
1166
1167 no:
1168 #ifdef DEBUGGING
1169     regindent--;
1170 #endif
1171     return 0;
1172 }
1173
1174 /*
1175  - regrepeat - repeatedly match something simple, report how many
1176  */
1177 /*
1178  * [This routine now assumes that it will only match on things of length 1.
1179  * That was true before, but now we assume scan - reginput is the count,
1180  * rather than incrementing count on every character.]
1181  */
1182 static I32
1183 regrepeat(p, max)
1184 char *p;
1185 I32 max;
1186 {
1187     register char *scan;
1188     register char *opnd;
1189     register I32 c;
1190     register char *loceol = regeol;
1191
1192     scan = reginput;
1193     if (max != 32767 && max < loceol - scan)
1194       loceol = scan + max;
1195     opnd = OPERAND(p);
1196     switch (OP(p)) {
1197     case ANY:
1198         while (scan < loceol && *scan != '\n')
1199             scan++;
1200         break;
1201     case SANY:
1202         scan = loceol;
1203         break;
1204     case EXACT:         /* length of string is 1 */
1205         c = UCHARAT(++opnd);
1206         while (scan < loceol && UCHARAT(scan) == c)
1207             scan++;
1208         break;
1209     case EXACTF:        /* length of string is 1 */
1210         c = UCHARAT(++opnd);
1211         while (scan < loceol &&
1212                (UCHARAT(scan) == c || UCHARAT(scan) == fold[c]))
1213             scan++;
1214         break;
1215     case EXACTFL:       /* length of string is 1 */
1216         regtainted = TRUE;
1217         c = UCHARAT(++opnd);
1218         while (scan < loceol &&
1219                (UCHARAT(scan) == c || UCHARAT(scan) == fold_locale[c]))
1220             scan++;
1221         break;
1222     case ANYOF:
1223         while (scan < loceol && reginclass(opnd, *scan))
1224             scan++;
1225         break;
1226     case ALNUM:
1227         while (scan < loceol && isALNUM(*scan))
1228             scan++;
1229         break;
1230     case ALNUML:
1231         regtainted = TRUE;
1232         while (scan < loceol && isALNUM_LC(*scan))
1233             scan++;
1234         break;
1235     case NALNUM:
1236         while (scan < loceol && !isALNUM(*scan))
1237             scan++;
1238         break;
1239     case NALNUML:
1240         regtainted = TRUE;
1241         while (scan < loceol && !isALNUM_LC(*scan))
1242             scan++;
1243         break;
1244     case SPACE:
1245         while (scan < loceol && isSPACE(*scan))
1246             scan++;
1247         break;
1248     case SPACEL:
1249         regtainted = TRUE;
1250         while (scan < loceol && isSPACE_LC(*scan))
1251             scan++;
1252         break;
1253     case NSPACE:
1254         while (scan < loceol && !isSPACE(*scan))
1255             scan++;
1256         break;
1257     case NSPACEL:
1258         regtainted = TRUE;
1259         while (scan < loceol && !isSPACE_LC(*scan))
1260             scan++;
1261         break;
1262     case DIGIT:
1263         while (scan < loceol && isDIGIT(*scan))
1264             scan++;
1265         break;
1266     case NDIGIT:
1267         while (scan < loceol && !isDIGIT(*scan))
1268             scan++;
1269         break;
1270     default:            /* Called on something of 0 width. */
1271         break;          /* So match right here or not at all. */
1272     }
1273
1274     c = scan - reginput;
1275     reginput = scan;
1276
1277     return(c);
1278 }
1279
1280 /*
1281  - regclass - determine if a character falls into a character class
1282  */
1283
1284 static bool
1285 reginclass(p, c)
1286 register char *p;
1287 register I32 c;
1288 {
1289     char flags = *p;
1290     bool match = FALSE;
1291
1292     c &= 0xFF;
1293     if (p[1 + (c >> 3)] & (1 << (c & 7)))
1294         match = TRUE;
1295     else if (flags & ANYOF_FOLD) {
1296         I32 cf;
1297         if (flags & ANYOF_LOCALE) {
1298             regtainted = TRUE;
1299             cf = fold_locale[c];
1300         }
1301         else
1302             cf = fold[c];
1303         if (p[1 + (cf >> 3)] & (1 << (cf & 7)))
1304             match = TRUE;
1305     }
1306
1307     if (!match && (flags & ANYOF_ISA)) {
1308         regtainted = TRUE;
1309
1310         if (((flags & ANYOF_ALNUML)  && isALNUM_LC(c))  ||
1311             ((flags & ANYOF_NALNUML) && !isALNUM_LC(c)) ||
1312             ((flags & ANYOF_SPACEL)  && isSPACE_LC(c))  ||
1313             ((flags & ANYOF_NSPACEL) && !isSPACE_LC(c)))
1314         {
1315             match = TRUE;
1316         }
1317     }
1318
1319     return match ^ ((flags & ANYOF_INVERT) != 0);
1320 }
1321
1322 /*
1323  - regnext - dig the "next" pointer out of a node
1324  *
1325  * [Note, when REGALIGN is defined there are two places in regmatch()
1326  * that bypass this code for speed.]
1327  */
1328 char *
1329 regnext(p)
1330 register char *p;
1331 {
1332     register I32 offset;
1333
1334     if (p == &regdummy)
1335         return(NULL);
1336
1337     offset = NEXT(p);
1338     if (offset == 0)
1339         return(NULL);
1340
1341 #ifdef REGALIGN
1342     return(p+offset);
1343 #else
1344     if (OP(p) == BACK)
1345         return(p-offset);
1346     else
1347         return(p+offset);
1348 #endif
1349 }