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