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