source: trunk/third/perl/regexec.c @ 10724

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