Convert miniperl sources to ANSI C. Several passes of
[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(I32 parenfloor)
90 {
91     dTHR;
92     int retval = savestack_ix;
93     int i = (regsize - parenfloor) * 3;
94     int p;
95
96     SSCHECK(i + 5);
97     for (p = regsize; p > parenfloor; p--) {
98         SSPUSHPTR(regendp[p]);
99         SSPUSHPTR(regstartp[p]);
100         SSPUSHINT(p);
101     }
102     SSPUSHINT(regsize);
103     SSPUSHINT(*reglastparen);
104     SSPUSHPTR(reginput);
105     SSPUSHINT(i + 3);
106     SSPUSHINT(SAVEt_REGCONTEXT);
107     return retval;
108 }
109
110 static char *
111 regcppop(void)
112 {
113     dTHR;
114     I32 i = SSPOPINT;
115     U32 paren = 0;
116     char *input;
117     char *tmps;
118     assert(i == SAVEt_REGCONTEXT);
119     i = SSPOPINT;
120     input = (char *) SSPOPPTR;
121     *reglastparen = SSPOPINT;
122     regsize = SSPOPINT;
123     for (i -= 3; i > 0; i -= 3) {
124         paren = (U32)SSPOPINT;
125         regstartp[paren] = (char *) SSPOPPTR;
126         tmps = (char*)SSPOPPTR;
127         if (paren <= *reglastparen)
128             regendp[paren] = tmps;
129     }
130     for (paren = *reglastparen + 1; paren <= regnpar; paren++) {
131         if (paren > regsize)
132             regstartp[paren] = Nullch;
133         regendp[paren] = Nullch;
134     }
135     return input;
136 }
137
138 /* After a successful match in WHILEM, we want to restore paren matches
139  * that have been overwritten by a failed match attempt in the process
140  * of reaching this success. We do this by restoring regstartp[i]
141  * wherever regendp[i] has not changed; if OPEN is changed to modify
142  * regendp[], the '== endp' test below should be changed to match.
143  * This corrects the error of:
144  *      0 > length [ "foobar" =~ / ( (foo) | (bar) )* /x ]->[1]
145  */
146 static void
147 regcppartblow(I32 base)
148 {
149     dTHR;
150     I32 i = SSPOPINT;
151     U32 paren;
152     char *startp;
153     char *endp;
154     assert(i == SAVEt_REGCONTEXT);
155     i = SSPOPINT;
156     /* input, lastparen, size */
157     SSPOPPTR; SSPOPINT; SSPOPINT;
158     for (i -= 3; i > 0; i -= 3) {
159         paren = (U32)SSPOPINT;
160         startp = (char *) SSPOPPTR;
161         endp = (char *) SSPOPPTR;
162         if (paren <= *reglastparen && regendp[paren] == endp)
163             regstartp[paren] = startp;
164     }
165     assert(savestack_ix == base);
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(register regexp *prog, char *stringarg, register char *strend, char *strbeg, I32 minend, SV *screamer, I32 safebase)
190                       
191                 
192                         /* pointer to null at end of string */
193                 /* real beginning of string */
194                 /* end of match must be at least minend after stringarg */
195              
196                 /* 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(regexp *prog, char *startpos)
597 {
598     register I32 i;
599     register char **sp;
600     register char **ep;
601
602     reginput = startpos;
603     regstartp = prog->startp;
604     regendp = prog->endp;
605     reglastparen = &prog->lastparen;
606     prog->lastparen = 0;
607     regsize = 0;
608
609     sp = prog->startp;
610     ep = prog->endp;
611     if (prog->nparens) {
612         for (i = prog->nparens; i >= 0; i--) {
613             *sp++ = NULL;
614             *ep++ = NULL;
615         }
616     }
617     if (regmatch(prog->program + 1) && reginput >= regtill) {
618         prog->startp[0] = startpos;
619         prog->endp[0] = reginput;
620         return 1;
621     }
622     else
623         return 0;
624 }
625
626 /*
627  - regmatch - main matching routine
628  *
629  * Conceptually the strategy is simple:  check to see whether the current
630  * node matches, call self recursively to see whether the rest matches,
631  * and then act accordingly.  In practice we make some effort to avoid
632  * recursion, in particular by going through "ordinary" nodes (that don't
633  * need to know whether the rest of the match failed) by a loop instead of
634  * by recursion.
635  */
636 /* [lwall] I've hoisted the register declarations to the outer block in order to
637  * maybe save a little bit of pushing and popping on the stack.  It also takes
638  * advantage of machines that use a register save mask on subroutine entry.
639  */
640 static I32                      /* 0 failure, 1 success */
641 regmatch(char *prog)
642 {
643     register char *scan;        /* Current node. */
644     char *next;                 /* Next node. */
645     register I32 nextchar;
646     register I32 n;             /* no or next */
647     register I32 ln;            /* len or last */
648     register char *s;           /* operand or save */
649     register char *locinput = reginput;
650     register I32 c1, c2;        /* case fold search */
651     int minmod = 0;
652 #ifdef DEBUGGING
653     static int regindent = 0;
654     regindent++;
655 #endif
656
657     nextchar = UCHARAT(locinput);
658     scan = prog;
659     while (scan != NULL) {
660 #ifdef DEBUGGING
661 #define sayYES goto yes
662 #define sayNO goto no
663 #define saySAME(x) if (x) goto yes; else goto no
664         if (regnarrate) {
665             SV *prop = sv_newmortal();
666             regprop(prop, scan);
667             PerlIO_printf(Perl_debug_log, "%*s%2ld%-8.8s\t<%.10s>\n",
668                           regindent*2, "", (long)(scan - regprogram),
669                           SvPVX(prop), locinput);
670         }
671 #else
672 #define sayYES return 1
673 #define sayNO return 0
674 #define saySAME(x) return x
675 #endif
676
677 #ifdef REGALIGN
678         next = scan + NEXT(scan);
679         if (next == scan)
680             next = NULL;
681 #else
682         next = regnext(scan);
683 #endif
684
685         switch (OP(scan)) {
686         case BOL:
687             if (locinput == regbol
688                 ? regprev == '\n'
689                 : ((nextchar || locinput < regeol) && locinput[-1] == '\n') )
690             {
691                 /* regtill = regbol; */
692                 break;
693             }
694             sayNO;
695         case MBOL:
696             if (locinput == regbol
697                 ? regprev == '\n'
698                 : ((nextchar || locinput < regeol) && locinput[-1] == '\n') )
699             {
700                 break;
701             }
702             sayNO;
703         case SBOL:
704             if (locinput == regbol && regprev == '\n')
705                 break;
706             sayNO;
707         case GPOS:
708             if (locinput == regbol)
709                 break;
710             sayNO;
711         case EOL:
712             if (multiline)
713                 goto meol;
714             else
715                 goto seol;
716         case MEOL:
717           meol:
718             if ((nextchar || locinput < regeol) && nextchar != '\n')
719                 sayNO;
720             break;
721         case SEOL:
722           seol:
723             if ((nextchar || locinput < regeol) && nextchar != '\n')
724                 sayNO;
725             if (regeol - locinput > 1)
726                 sayNO;
727             break;
728         case SANY:
729             if (!nextchar && locinput >= regeol)
730                 sayNO;
731             nextchar = UCHARAT(++locinput);
732             break;
733         case ANY:
734             if (!nextchar && locinput >= regeol || nextchar == '\n')
735                 sayNO;
736             nextchar = UCHARAT(++locinput);
737             break;
738         case EXACT:
739             s = OPERAND(scan);
740             ln = *s++;
741             /* Inline the first character, for speed. */
742             if (UCHARAT(s) != nextchar)
743                 sayNO;
744             if (regeol - locinput < ln)
745                 sayNO;
746             if (ln > 1 && memNE(s, locinput, ln))
747                 sayNO;
748             locinput += ln;
749             nextchar = UCHARAT(locinput);
750             break;
751         case EXACTFL:
752             regtainted = TRUE;
753             /* FALL THROUGH */
754         case EXACTF:
755             s = OPERAND(scan);
756             ln = *s++;
757             /* Inline the first character, for speed. */
758             if (UCHARAT(s) != nextchar &&
759                 UCHARAT(s) != ((OP(scan) == EXACTF)
760                                ? fold : fold_locale)[nextchar])
761                 sayNO;
762             if (regeol - locinput < ln)
763                 sayNO;
764             if (ln > 1 && (OP(scan) == EXACTF
765                            ? ibcmp(s, locinput, ln)
766                            : ibcmp_locale(s, locinput, ln)))
767                 sayNO;
768             locinput += ln;
769             nextchar = UCHARAT(locinput);
770             break;
771         case ANYOF:
772             s = OPERAND(scan);
773             if (nextchar < 0)
774                 nextchar = UCHARAT(locinput);
775             if (!reginclass(s, nextchar))
776                 sayNO;
777             if (!nextchar && locinput >= regeol)
778                 sayNO;
779             nextchar = UCHARAT(++locinput);
780             break;
781         case ALNUML:
782             regtainted = TRUE;
783             /* FALL THROUGH */
784         case ALNUM:
785             if (!nextchar)
786                 sayNO;
787             if (!(OP(scan) == ALNUM
788                   ? isALNUM(nextchar) : isALNUM_LC(nextchar)))
789                 sayNO;
790             nextchar = UCHARAT(++locinput);
791             break;
792         case NALNUML:
793             regtainted = TRUE;
794             /* FALL THROUGH */
795         case NALNUM:
796             if (!nextchar && locinput >= regeol)
797                 sayNO;
798             if (OP(scan) == NALNUM
799                 ? isALNUM(nextchar) : isALNUM_LC(nextchar))
800                 sayNO;
801             nextchar = UCHARAT(++locinput);
802             break;
803         case BOUNDL:
804         case NBOUNDL:
805             regtainted = TRUE;
806             /* FALL THROUGH */
807         case BOUND:
808         case NBOUND:
809             /* was last char in word? */
810             ln = (locinput != regbol) ? UCHARAT(locinput - 1) : regprev;
811             if (OP(scan) == BOUND || OP(scan) == NBOUND) {
812                 ln = isALNUM(ln);
813                 n = isALNUM(nextchar);
814             }
815             else {
816                 ln = isALNUM_LC(ln);
817                 n = isALNUM_LC(nextchar);
818             }
819             if (((!ln) == (!n)) == (OP(scan) == BOUND || OP(scan) == BOUNDL))
820                 sayNO;
821             break;
822         case SPACEL:
823             regtainted = TRUE;
824             /* FALL THROUGH */
825         case SPACE:
826             if (!nextchar && locinput >= regeol)
827                 sayNO;
828             if (!(OP(scan) == SPACE
829                   ? isSPACE(nextchar) : isSPACE_LC(nextchar)))
830                 sayNO;
831             nextchar = UCHARAT(++locinput);
832             break;
833         case NSPACEL:
834             regtainted = TRUE;
835             /* FALL THROUGH */
836         case NSPACE:
837             if (!nextchar)
838                 sayNO;
839             if (OP(scan) == SPACE
840                 ? isSPACE(nextchar) : isSPACE_LC(nextchar))
841                 sayNO;
842             nextchar = UCHARAT(++locinput);
843             break;
844         case DIGIT:
845             if (!isDIGIT(nextchar))
846                 sayNO;
847             nextchar = UCHARAT(++locinput);
848             break;
849         case NDIGIT:
850             if (!nextchar && locinput >= regeol)
851                 sayNO;
852             if (isDIGIT(nextchar))
853                 sayNO;
854             nextchar = UCHARAT(++locinput);
855             break;
856         case REFFL:
857             regtainted = TRUE;
858             /* FALL THROUGH */
859         case REF:
860         case REFF:
861             n = ARG1(scan);  /* which paren pair */
862             s = regstartp[n];
863             if (!s)
864                 sayNO;
865             if (!regendp[n])
866                 sayNO;
867             if (s == regendp[n])
868                 break;
869             /* Inline the first character, for speed. */
870             if (UCHARAT(s) != nextchar &&
871                 (OP(scan) == REF ||
872                  (UCHARAT(s) != ((OP(scan) == REFF
873                                  ? fold : fold_locale)[nextchar]))))
874                 sayNO;
875             ln = regendp[n] - s;
876             if (locinput + ln > regeol)
877                 sayNO;
878             if (ln > 1 && (OP(scan) == REF
879                            ? memNE(s, locinput, ln)
880                            : (OP(scan) == REFF
881                               ? ibcmp(s, locinput, ln)
882                               : ibcmp_locale(s, locinput, ln))))
883                 sayNO;
884             locinput += ln;
885             nextchar = UCHARAT(locinput);
886             break;
887
888         case NOTHING:
889             break;
890         case BACK:
891             break;
892         case OPEN:
893             n = ARG1(scan);  /* which paren pair */
894             regstartp[n] = locinput;
895             if (n > regsize)
896                 regsize = n;
897             break;
898         case CLOSE:
899             n = ARG1(scan);  /* which paren pair */
900             regendp[n] = locinput;
901             if (n > *reglastparen)
902                 *reglastparen = n;
903             break;
904         case CURLYX: {
905                 dTHR;       
906                 CURCUR cc;
907                 CHECKPOINT cp = savestack_ix;
908                 cc.oldcc = regcc;
909                 regcc = &cc;
910                 cc.parenfloor = *reglastparen;
911                 cc.cur = -1;
912                 cc.min = ARG1(scan);
913                 cc.max  = ARG2(scan);
914                 cc.scan = NEXTOPER(scan) + 4;
915                 cc.next = next;
916                 cc.minmod = minmod;
917                 cc.lastloc = 0;
918                 reginput = locinput;
919                 n = regmatch(PREVOPER(next));   /* start on the WHILEM */
920                 regcpblow(cp);
921                 regcc = cc.oldcc;
922                 saySAME(n);
923             }
924             /* NOT REACHED */
925         case WHILEM: {
926                 /*
927                  * This is really hard to understand, because after we match
928                  * what we're trying to match, we must make sure the rest of
929                  * the RE is going to match for sure, and to do that we have
930                  * to go back UP the parse tree by recursing ever deeper.  And
931                  * if it fails, we have to reset our parent's current state
932                  * that we can try again after backing off.
933                  */
934
935                 CHECKPOINT cp;
936                 CURCUR* cc = regcc;
937                 n = cc->cur + 1;        /* how many we know we matched */
938                 reginput = locinput;
939
940 #ifdef DEBUGGING
941                 if (regnarrate)
942                     PerlIO_printf(Perl_debug_log, "%*s  %ld  %lx\n", regindent*2, "",
943                         (long)n, (long)cc);
944 #endif
945
946                 /* If degenerate scan matches "", assume scan done. */
947
948                 if (locinput == cc->lastloc && n >= cc->min) {
949                     regcc = cc->oldcc;
950                     ln = regcc->cur;
951                     if (regmatch(cc->next))
952                         sayYES;
953                     regcc->cur = ln;
954                     regcc = cc;
955                     sayNO;
956                 }
957
958                 /* First just match a string of min scans. */
959
960                 if (n < cc->min) {
961                     cc->cur = n;
962                     cc->lastloc = locinput;
963                     if (regmatch(cc->scan))
964                         sayYES;
965                     cc->cur = n - 1;
966                     sayNO;
967                 }
968
969                 /* Prefer next over scan for minimal matching. */
970
971                 if (cc->minmod) {
972                     regcc = cc->oldcc;
973                     ln = regcc->cur;
974                     cp = regcppush(cc->parenfloor);
975                     if (regmatch(cc->next)) {
976                         regcppartblow(cp);
977                         sayYES; /* All done. */
978                     }
979                     regcppop();
980                     regcc->cur = ln;
981                     regcc = cc;
982
983                     if (n >= cc->max)   /* Maximum greed exceeded? */
984                         sayNO;
985
986                     /* Try scanning more and see if it helps. */
987                     reginput = locinput;
988                     cc->cur = n;
989                     cc->lastloc = locinput;
990                     cp = regcppush(cc->parenfloor);
991                     if (regmatch(cc->scan)) {
992                         regcppartblow(cp);
993                         sayYES;
994                     }
995                     regcppop();
996                     cc->cur = n - 1;
997                     sayNO;
998                 }
999
1000                 /* Prefer scan over next for maximal matching. */
1001
1002                 if (n < cc->max) {      /* More greed allowed? */
1003                     cp = regcppush(cc->parenfloor);
1004                     cc->cur = n;
1005                     cc->lastloc = locinput;
1006                     if (regmatch(cc->scan)) {
1007                         regcppartblow(cp);
1008                         sayYES;
1009                     }
1010                     regcppop();         /* Restore some previous $<digit>s? */
1011                     reginput = locinput;
1012                 }
1013
1014                 /* Failed deeper matches of scan, so see if this one works. */
1015                 regcc = cc->oldcc;
1016                 ln = regcc->cur;
1017                 if (regmatch(cc->next))
1018                     sayYES;
1019                 regcc->cur = ln;
1020                 regcc = cc;
1021                 cc->cur = n - 1;
1022                 sayNO;
1023             }
1024             /* NOT REACHED */
1025         case BRANCH: {
1026                 if (OP(next) != BRANCH)   /* No choice. */
1027                     next = NEXTOPER(scan);/* Avoid recursion. */
1028                 else {
1029                     int lastparen = *reglastparen;
1030                     do {
1031                         reginput = locinput;
1032                         if (regmatch(NEXTOPER(scan)))
1033                             sayYES;
1034                         for (n = *reglastparen; n > lastparen; n--)
1035                             regendp[n] = 0;
1036                         *reglastparen = n;
1037                             
1038 #ifdef REGALIGN
1039                         /*SUPPRESS 560*/
1040                         if (n = NEXT(scan))
1041                             scan += n;
1042                         else
1043                             scan = NULL;
1044 #else
1045                         scan = regnext(scan);
1046 #endif
1047                     } while (scan != NULL && OP(scan) == BRANCH);
1048                     sayNO;
1049                     /* NOTREACHED */
1050                 }
1051             }
1052             break;
1053         case MINMOD:
1054             minmod = 1;
1055             break;
1056         case CURLY:
1057             ln = ARG1(scan);  /* min to match */
1058             n  = ARG2(scan);  /* max to match */
1059             scan = NEXTOPER(scan) + 4;
1060             goto repeat;
1061         case STAR:
1062             ln = 0;
1063             n = 32767;
1064             scan = NEXTOPER(scan);
1065             goto repeat;
1066         case PLUS:
1067             /*
1068             * Lookahead to avoid useless match attempts
1069             * when we know what character comes next.
1070             */
1071             ln = 1;
1072             n = 32767;
1073             scan = NEXTOPER(scan);
1074           repeat:
1075             if (regkind[(U8)OP(next)] == EXACT) {
1076                 c1 = UCHARAT(OPERAND(next) + 1);
1077                 if (OP(next) == EXACTF)
1078                     c2 = fold[c1];
1079                 else if (OP(next) == EXACTFL)
1080                     c2 = fold_locale[c1];
1081                 else
1082                     c2 = c1;
1083             }
1084             else
1085                 c1 = c2 = -1000;
1086             reginput = locinput;
1087             if (minmod) {
1088                 minmod = 0;
1089                 if (ln && regrepeat(scan, ln) < ln)
1090                     sayNO;
1091                 while (n >= ln || (n == 32767 && ln > 0)) { /* ln overflow ? */
1092                     /* If it could work, try it. */
1093                     if (c1 == -1000 ||
1094                         UCHARAT(reginput) == c1 ||
1095                         UCHARAT(reginput) == c2)
1096                     {
1097                         if (regmatch(next))
1098                             sayYES;
1099                     }
1100                     /* Couldn't or didn't -- back up. */
1101                     reginput = locinput + ln;
1102                     if (regrepeat(scan, 1)) {
1103                         ln++;
1104                         reginput = locinput + ln;
1105                     }
1106                     else
1107                         sayNO;
1108                 }
1109             }
1110             else {
1111                 n = regrepeat(scan, n);
1112                 if (ln < n && regkind[(U8)OP(next)] == EOL &&
1113                     (!multiline || OP(next) == SEOL))
1114                     ln = n;                     /* why back off? */
1115                 while (n >= ln) {
1116                     /* If it could work, try it. */
1117                     if (c1 == -1000 ||
1118                         UCHARAT(reginput) == c1 ||
1119                         UCHARAT(reginput) == c2)
1120                     {
1121                         if (regmatch(next))
1122                             sayYES;
1123                     }
1124                     /* Couldn't or didn't -- back up. */
1125                     n--;
1126                     reginput = locinput + n;
1127                 }
1128             }
1129             sayNO;
1130         case SUCCEED:
1131         case END:
1132             reginput = locinput;        /* put where regtry can find it */
1133             sayYES;                     /* Success! */
1134         case IFMATCH:
1135             reginput = locinput;
1136             scan = NEXTOPER(scan);
1137             if (!regmatch(scan))
1138                 sayNO;
1139             break;
1140         case UNLESSM:
1141             reginput = locinput;
1142             scan = NEXTOPER(scan);
1143             if (regmatch(scan))
1144                 sayNO;
1145             break;
1146         default:
1147             PerlIO_printf(PerlIO_stderr(), "%lx %d\n",
1148                           (unsigned long)scan, scan[1]);
1149             FAIL("regexp memory corruption");
1150         }
1151         scan = next;
1152     }
1153
1154     /*
1155     * We get here only if there's trouble -- normally "case END" is
1156     * the terminating point.
1157     */
1158     FAIL("corrupted regexp pointers");
1159     /*NOTREACHED*/
1160     sayNO;
1161
1162 yes:
1163 #ifdef DEBUGGING
1164     regindent--;
1165 #endif
1166     return 1;
1167
1168 no:
1169 #ifdef DEBUGGING
1170     regindent--;
1171 #endif
1172     return 0;
1173 }
1174
1175 /*
1176  - regrepeat - repeatedly match something simple, report how many
1177  */
1178 /*
1179  * [This routine now assumes that it will only match on things of length 1.
1180  * That was true before, but now we assume scan - reginput is the count,
1181  * rather than incrementing count on every character.]
1182  */
1183 static I32
1184 regrepeat(char *p, I32 max)
1185 {
1186     register char *scan;
1187     register char *opnd;
1188     register I32 c;
1189     register char *loceol = regeol;
1190
1191     scan = reginput;
1192     if (max != 32767 && max < loceol - scan)
1193       loceol = scan + max;
1194     opnd = OPERAND(p);
1195     switch (OP(p)) {
1196     case ANY:
1197         while (scan < loceol && *scan != '\n')
1198             scan++;
1199         break;
1200     case SANY:
1201         scan = loceol;
1202         break;
1203     case EXACT:         /* length of string is 1 */
1204         c = UCHARAT(++opnd);
1205         while (scan < loceol && UCHARAT(scan) == c)
1206             scan++;
1207         break;
1208     case EXACTF:        /* length of string is 1 */
1209         c = UCHARAT(++opnd);
1210         while (scan < loceol &&
1211                (UCHARAT(scan) == c || UCHARAT(scan) == fold[c]))
1212             scan++;
1213         break;
1214     case EXACTFL:       /* length of string is 1 */
1215         regtainted = TRUE;
1216         c = UCHARAT(++opnd);
1217         while (scan < loceol &&
1218                (UCHARAT(scan) == c || UCHARAT(scan) == fold_locale[c]))
1219             scan++;
1220         break;
1221     case ANYOF:
1222         while (scan < loceol && reginclass(opnd, *scan))
1223             scan++;
1224         break;
1225     case ALNUM:
1226         while (scan < loceol && isALNUM(*scan))
1227             scan++;
1228         break;
1229     case ALNUML:
1230         regtainted = TRUE;
1231         while (scan < loceol && isALNUM_LC(*scan))
1232             scan++;
1233         break;
1234     case NALNUM:
1235         while (scan < loceol && !isALNUM(*scan))
1236             scan++;
1237         break;
1238     case NALNUML:
1239         regtainted = TRUE;
1240         while (scan < loceol && !isALNUM_LC(*scan))
1241             scan++;
1242         break;
1243     case SPACE:
1244         while (scan < loceol && isSPACE(*scan))
1245             scan++;
1246         break;
1247     case SPACEL:
1248         regtainted = TRUE;
1249         while (scan < loceol && isSPACE_LC(*scan))
1250             scan++;
1251         break;
1252     case NSPACE:
1253         while (scan < loceol && !isSPACE(*scan))
1254             scan++;
1255         break;
1256     case NSPACEL:
1257         regtainted = TRUE;
1258         while (scan < loceol && !isSPACE_LC(*scan))
1259             scan++;
1260         break;
1261     case DIGIT:
1262         while (scan < loceol && isDIGIT(*scan))
1263             scan++;
1264         break;
1265     case NDIGIT:
1266         while (scan < loceol && !isDIGIT(*scan))
1267             scan++;
1268         break;
1269     default:            /* Called on something of 0 width. */
1270         break;          /* So match right here or not at all. */
1271     }
1272
1273     c = scan - reginput;
1274     reginput = scan;
1275
1276     return(c);
1277 }
1278
1279 /*
1280  - regclass - determine if a character falls into a character class
1281  */
1282
1283 static bool
1284 reginclass(register char *p, register I32 c)
1285 {
1286     char flags = *p;
1287     bool match = FALSE;
1288
1289     c &= 0xFF;
1290     if (p[1 + (c >> 3)] & (1 << (c & 7)))
1291         match = TRUE;
1292     else if (flags & ANYOF_FOLD) {
1293         I32 cf;
1294         if (flags & ANYOF_LOCALE) {
1295             regtainted = TRUE;
1296             cf = fold_locale[c];
1297         }
1298         else
1299             cf = fold[c];
1300         if (p[1 + (cf >> 3)] & (1 << (cf & 7)))
1301             match = TRUE;
1302     }
1303
1304     if (!match && (flags & ANYOF_ISA)) {
1305         regtainted = TRUE;
1306
1307         if (((flags & ANYOF_ALNUML)  && isALNUM_LC(c))  ||
1308             ((flags & ANYOF_NALNUML) && !isALNUM_LC(c)) ||
1309             ((flags & ANYOF_SPACEL)  && isSPACE_LC(c))  ||
1310             ((flags & ANYOF_NSPACEL) && !isSPACE_LC(c)))
1311         {
1312             match = TRUE;
1313         }
1314     }
1315
1316     return match ^ ((flags & ANYOF_INVERT) != 0);
1317 }
1318
1319 /*
1320  - regnext - dig the "next" pointer out of a node
1321  *
1322  * [Note, when REGALIGN is defined there are two places in regmatch()
1323  * that bypass this code for speed.]
1324  */
1325 char *
1326 regnext(register char *p)
1327 {
1328     register I32 offset;
1329
1330     if (p == &regdummy)
1331         return(NULL);
1332
1333     offset = NEXT(p);
1334     if (offset == 0)
1335         return(NULL);
1336
1337 #ifdef REGALIGN
1338     return(p+offset);
1339 #else
1340     if (OP(p) == BACK)
1341         return(p-offset);
1342     else
1343         return(p+offset);
1344 #endif
1345 }