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

Revision 10724, 37.0 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/*    regcomp.c
2 */
3
4/*
5 * "A fair jaw-cracker dwarf-language must be."  --Samwise Gamgee
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 *
44 ****    Alterations to Henry's code are...
45 ****
46 ****    Copyright (c) 1991-1997, Larry Wall
47 ****
48 ****    You may distribute under the terms of either the GNU General Public
49 ****    License or the Artistic License, as specified in the README file.
50
51 *
52 * Beware that some of this code is subtly aware of the way operator
53 * precedence is structured in regular expressions.  Serious changes in
54 * regular-expression syntax might require a total rethink.
55 */
56#include "EXTERN.h"
57#include "perl.h"
58#include "INTERN.h"
59#include "regcomp.h"
60
61#ifdef MSDOS
62# if defined(BUGGY_MSC6)
63 /* MSC 6.00A breaks on op/regexp.t test 85 unless we turn this off */
64 # pragma optimize("a",off)
65 /* But MSC 6.00A is happy with 'w', for aliases only across function calls*/
66 # pragma optimize("w",on )
67# endif /* BUGGY_MSC6 */
68#endif /* MSDOS */
69
70#ifndef STATIC
71#define STATIC  static
72#endif
73
74#define ISMULT1(c)      ((c) == '*' || (c) == '+' || (c) == '?')
75#define ISMULT2(s)      ((*s) == '*' || (*s) == '+' || (*s) == '?' || \
76        ((*s) == '{' && regcurly(s)))
77#ifdef atarist
78#define PERL_META       "^$.[()|?+*\\"
79#else
80#define META    "^$.[()|?+*\\"
81#endif
82
83#ifdef SPSTART
84#undef SPSTART          /* dratted cpp namespace... */
85#endif
86/*
87 * Flags to be passed up and down.
88 */
89#define WORST           0       /* Worst case. */
90#define HASWIDTH        0x1     /* Known never to match null string. */
91#define SIMPLE          0x2     /* Simple enough to be STAR/PLUS operand. */
92#define SPSTART         0x4     /* Starts with * or +. */
93#define TRYAGAIN        0x8     /* Weeded out a declaration. */
94
95/*
96 * Forward declarations for pregcomp()'s friends.
97 */
98
99static char *reg _((I32, I32 *));
100static char *reganode _((char, unsigned short));
101static char *regatom _((I32 *));
102static char *regbranch _((I32 *));
103static void regc _((char));
104static char *regclass _((void));
105STATIC I32 regcurly _((char *));
106static char *regnode _((char));
107static char *regpiece _((I32 *));
108static void reginsert _((char, char *));
109static void regoptail _((char *, char *));
110static void regset _((char *, I32));
111static void regtail _((char *, char *));
112static char* regwhite _((char *, char *));
113static char* nextchar _((void));
114
115/*
116 - pregcomp - compile a regular expression into internal code
117 *
118 * We can't allocate space until we know how big the compiled form will be,
119 * but we can't compile it (and thus know how big it is) until we've got a
120 * place to put the code.  So we cheat:  we compile it twice, once with code
121 * generation turned off and size counting turned on, and once "for real".
122 * This also means that we don't allocate space until we are sure that the
123 * thing really will compile successfully, and we never have to move the
124 * code and thus invalidate pointers into it.  (Note that it has to be in
125 * one piece because free() must be able to free it all.) [NB: not true in perl]
126 *
127 * Beware that the optimization-preparation code in here knows about some
128 * of the structure of the compiled regexp.  [I'll say.]
129 */
130regexp *
131pregcomp(exp,xend,pm)
132char* exp;
133char* xend;
134PMOP* pm;
135{
136    register regexp *r;
137    register char *scan;
138    register SV *longish;
139    SV *longest;
140    register I32 len;
141    register char *first;
142    I32 flags;
143    I32 backish;
144    I32 backest;
145    I32 curback;
146    I32 minlen = 0;
147    I32 sawplus = 0;
148    I32 sawopen = 0;
149#define MAX_REPEAT_DEPTH 12
150    struct {
151        char *opcode;
152        I32 count;
153    } repeat_stack[MAX_REPEAT_DEPTH];
154    I32 repeat_depth = 0;
155    I32 repeat_count = 1;       /* We start unmultiplied. */
156
157    if (exp == NULL)
158        croak("NULL regexp argument");
159
160    regprecomp = savepvn(exp, xend - exp);
161    regflags = pm->op_pmflags;
162    regsawback = 0;
163
164    /* First pass: determine size, legality. */
165    regparse = exp;
166    regxend = xend;
167    regnaughty = 0;
168    regnpar = 1;
169    regsize = 0L;
170    regcode = &regdummy;
171    regc((char)MAGIC);
172    if (reg(0, &flags) == NULL) {
173        Safefree(regprecomp);
174        regprecomp = Nullch;
175        return(NULL);
176    }
177
178    /* Small enough for pointer-storage convention? */
179    if (regsize >= 32767L)              /* Probably could be 65535L. */
180        FAIL("regexp too big");
181
182    /* Allocate space and initialize. */
183    Newc(1001, r, sizeof(regexp) + (unsigned)regsize, char, regexp);
184    if (r == NULL)
185        FAIL("regexp out of space");
186    r->prelen = xend - exp;
187    r->precomp = regprecomp;
188    r->subbeg = r->subbase = NULL;
189
190    /* Second pass: emit code. */
191    regparse = exp;
192    regxend = xend;
193    regnaughty = 0;
194    regnpar = 1;
195    regcode = r->program;
196    regc((char)MAGIC);
197    if (reg(0, &flags) == NULL)
198        return(NULL);
199
200    /* Dig out information for optimizations. */
201    pm->op_pmflags = regflags;
202    r->regstart = Nullsv;       /* Worst-case defaults. */
203    r->reganch = 0;
204    r->regmust = Nullsv;
205    r->regback = -1;
206    r->regstclass = Nullch;
207    r->naughty = regnaughty >= 10;      /* Probably an expensive pattern. */
208    scan = r->program+1;                        /* First BRANCH. */
209    if (OP(regnext(scan)) == END) {/* Only one top-level choice. */
210        scan = NEXTOPER(scan);
211
212        first = scan;
213        while ((OP(first) == OPEN && (sawopen = 1)) ||
214            (OP(first) == BRANCH && OP(regnext(first)) != BRANCH) ||
215            (OP(first) == PLUS) ||
216            (OP(first) == MINMOD) ||
217            (regkind[(U8)OP(first)] == CURLY && ARG1(first) > 0) ) {
218                if (OP(first) == PLUS)
219                    sawplus = 1;
220                else
221                    first += regarglen[(U8)OP(first)];
222                first = NEXTOPER(first);
223        }
224
225        /* Starting-point info. */
226      again:
227        if (OP(first) == EXACT) {
228            r->regstart = newSVpv(OPERAND(first)+1,*OPERAND(first));
229            if (SvCUR(r->regstart) > !sawstudy)
230                fbm_compile(r->regstart);
231            (void)SvUPGRADE(r->regstart, SVt_PVBM);
232        }
233        else if (strchr(simple+2,OP(first)))
234            r->regstclass = first;
235        else if (regkind[(U8)OP(first)] == BOUND ||
236                 regkind[(U8)OP(first)] == NBOUND)
237            r->regstclass = first;
238        else if (regkind[(U8)OP(first)] == BOL) {
239            r->reganch |= ROPT_ANCH_BOL;
240            first = NEXTOPER(first);
241            goto again;
242        }
243        else if (OP(first) == GPOS) {
244            r->reganch |= ROPT_ANCH_GPOS;
245            first = NEXTOPER(first);
246            goto again;
247        }
248        else if ((OP(first) == STAR &&
249            regkind[(U8)OP(NEXTOPER(first))] == ANY) &&
250            !(r->reganch & ROPT_ANCH) )
251        {
252            /* turn .* into ^.* with an implied $*=1 */
253            r->reganch |= ROPT_ANCH_BOL | ROPT_IMPLICIT;
254            first = NEXTOPER(first);
255            goto again;
256        }
257        if (sawplus && (!sawopen || !regsawback))
258            r->reganch |= ROPT_SKIP;    /* x+ must match 1st of run */
259
260        DEBUG_r(PerlIO_printf(Perl_debug_log, "first %d next %d offset %ld\n",
261           OP(first), OP(NEXTOPER(first)), (long)(first - scan)));
262        /*
263        * If there's something expensive in the r.e., find the
264        * longest literal string that must appear and make it the
265        * regmust.  Resolve ties in favor of later strings, since
266        * the regstart check works with the beginning of the r.e.
267        * and avoiding duplication strengthens checking.  Not a
268        * strong reason, but sufficient in the absence of others.
269        * [Now we resolve ties in favor of the earlier string if
270        * it happens that curback has been invalidated, since the
271        * earlier string may buy us something the later one won't.]
272        */
273        longish = newSVpv("",0);
274        longest = newSVpv("",0);
275        len = 0;
276        minlen = 0;
277        curback = 0;
278        backish = 0;
279        backest = 0;
280        while (OP(scan) != END) {
281            if (OP(scan) == BRANCH) {
282                if (OP(regnext(scan)) == BRANCH) {
283                    curback = -30000;
284                    while (OP(scan) == BRANCH)
285                        scan = regnext(scan);
286                }
287                else    /* single branch is ok */
288                    scan = NEXTOPER(scan);
289                continue;
290            }
291            if (OP(scan) == UNLESSM) {
292                curback = -30000;
293                scan = regnext(scan);
294                continue;
295            }
296            if (OP(scan) == EXACT) {
297                char *t;
298
299                first = scan;
300                while ((t = regnext(scan)) && OP(t) == CLOSE)
301                    scan = t;
302                minlen += *OPERAND(first) * repeat_count;
303                if (curback - backish == len) {
304                    sv_catpvn(longish, OPERAND(first)+1,
305                        *OPERAND(first));
306                    len += *OPERAND(first);
307                    curback += *OPERAND(first);
308                    first = regnext(scan);
309                }
310                else if (*OPERAND(first) >= len + (curback >= 0)) {
311                    len = *OPERAND(first);
312                    sv_setpvn(longish, OPERAND(first)+1,len);
313                    backish = curback;
314                    curback += len;
315                    first = regnext(scan);
316                }
317                else
318                    curback += *OPERAND(first);
319            }
320            else if (strchr(varies,OP(scan))) {
321                int tcount;
322                char *next;
323
324                if (repeat_depth < MAX_REPEAT_DEPTH
325                    && ((OP(scan) == PLUS
326                         && (tcount = 1)
327                         && (next = NEXTOPER(scan)))
328                        || (regkind[(U8)OP(scan)] == CURLY
329                            && (tcount = ARG1(scan))
330                            && (next = NEXTOPER(scan)+4))))
331                {
332                    /* We treat (abc)+ as (abc)(abc)*. */
333
334                    /* Mark the place to return back. */
335                    repeat_stack[repeat_depth].opcode = regnext(scan);
336                    repeat_stack[repeat_depth].count = repeat_count;
337                    repeat_depth++;
338                    repeat_count *= tcount;
339
340                    /* Go deeper: */
341                    scan = next;
342                    continue;
343                }
344                else {
345                    curback = -30000;
346                    len = 0;
347                    if (SvCUR(longish) > SvCUR(longest)) {
348                        sv_setsv(longest,longish);
349                        backest = backish;
350                    }
351                    sv_setpvn(longish,"",0);
352                }
353            }
354            else if (strchr(simple,OP(scan))) {
355                curback++;
356                minlen += repeat_count;
357                len = 0;
358                if (SvCUR(longish) > SvCUR(longest)) {
359                    sv_setsv(longest,longish);
360                    backest = backish;
361                }
362                sv_setpvn(longish,"",0);
363            }
364            scan = regnext(scan);
365            if (!scan) {                /* Go up PLUS or CURLY. */
366                if (!repeat_depth--)
367                    croak("panic: re scan");
368                scan = repeat_stack[repeat_depth].opcode;
369                repeat_count = repeat_stack[repeat_depth].count;
370                /* Need to submit the longest string found: */
371                curback = -30000;
372                len = 0;
373                if (SvCUR(longish) > SvCUR(longest)) {
374                    sv_setsv(longest,longish);
375                    backest = backish;
376                }
377                sv_setpvn(longish,"",0);
378            }
379        }
380
381        /* Prefer earlier on tie, unless we can tail match latter */
382
383        if (SvCUR(longish) + (first && regkind[(U8)OP(first)] == EOL)
384                > SvCUR(longest))
385        {
386            sv_setsv(longest,longish);
387            backest = backish;
388        }
389        else
390            sv_setpvn(longish,"",0);
391        if (SvCUR(longest)
392            && (!r->regstart
393                || !fbm_instr((unsigned char*) SvPVX(r->regstart),
394                              (unsigned char *) (SvPVX(r->regstart)
395                                                 + SvCUR(r->regstart)),
396                              longest)))
397        {
398            r->regmust = longest;
399            if (backest < 0)
400                backest = -1;
401            r->regback = backest;
402            if (SvCUR(longest) > !(sawstudy ||
403                                   (first && regkind[(U8)OP(first)] == EOL)))
404                fbm_compile(r->regmust);
405            (void)SvUPGRADE(r->regmust, SVt_PVBM);
406            BmUSEFUL(r->regmust) = 100;
407            if (first && regkind[(U8)OP(first)] == EOL && SvCUR(longish))
408                SvTAIL_on(r->regmust);
409        }
410        else {
411            SvREFCNT_dec(longest);
412            longest = Nullsv;
413        }
414        SvREFCNT_dec(longish);
415    }
416
417    r->nparens = regnpar - 1;
418    r->minlen = minlen;
419    Newz(1002, r->startp, regnpar, char*);
420    Newz(1002, r->endp, regnpar, char*);
421    DEBUG_r(regdump(r));
422    return(r);
423}
424
425/*
426 - reg - regular expression, i.e. main body or parenthesized thing
427 *
428 * Caller must absorb opening parenthesis.
429 *
430 * Combining parenthesis handling with the base level of regular expression
431 * is a trifle forced, but the need to tie the tails of the branches to what
432 * follows makes it hard to avoid.
433 */
434static char *
435reg(paren, flagp)
436I32 paren;                      /* Parenthesized? */
437I32 *flagp;
438{
439    register char *ret;
440    register char *br;
441    register char *ender = 0;
442    register I32 parno = 0;
443    I32 flags;
444
445    *flagp = HASWIDTH;  /* Tentatively. */
446
447    /* Make an OPEN node, if parenthesized. */
448    if (paren) {
449        if (*regparse == '?') {
450            regparse++;
451            paren = *regparse++;
452            ret = NULL;
453            switch (paren) {
454            case ':':
455            case '=':
456            case '!':
457                break;
458            case '$':
459            case '@':
460                croak("Sequence (?%c...) not implemented", (int)paren);
461                break;
462            case '#':
463                while (*regparse && *regparse != ')')
464                    regparse++;
465                if (*regparse != ')')
466                    croak("Sequence (?#... not terminated");
467                nextchar();
468                *flagp = TRYAGAIN;
469                return NULL;
470            case 0:
471                croak("Sequence (? incomplete");
472                break;
473            default:
474                --regparse;
475                while (*regparse && strchr("iogcmsx", *regparse))
476                    pmflag(&regflags, *regparse++);
477                if (*regparse != ')')
478                    croak("Sequence (?%c...) not recognized", *regparse);
479                nextchar();
480                *flagp = TRYAGAIN;
481                return NULL;
482            }
483        }
484        else {
485            parno = regnpar;
486            regnpar++;
487            ret = reganode(OPEN, parno);
488        }
489    } else
490        ret = NULL;
491
492    /* Pick up the branches, linking them together. */
493    br = regbranch(&flags);
494    if (br == NULL)
495        return(NULL);
496    if (ret != NULL)
497        regtail(ret, br);       /* OPEN -> first. */
498    else
499        ret = br;
500    if (!(flags&HASWIDTH))
501        *flagp &= ~HASWIDTH;
502    *flagp |= flags&SPSTART;
503    while (*regparse == '|') {
504        nextchar();
505        br = regbranch(&flags);
506        if (br == NULL)
507            return(NULL);
508        regtail(ret, br);       /* BRANCH -> BRANCH. */
509        if (!(flags&HASWIDTH))
510            *flagp &= ~HASWIDTH;
511        *flagp |= flags&SPSTART;
512    }
513
514    /* Make a closing node, and hook it on the end. */
515    switch (paren) {
516    case ':':
517        ender = regnode(NOTHING);
518        break;
519    case 1:
520        ender = reganode(CLOSE, parno);
521        break;
522    case '=':
523    case '!':
524        ender = regnode(SUCCEED);
525        *flagp &= ~HASWIDTH;
526        break;
527    case 0:
528        ender = regnode(END);
529        break;
530    }
531    regtail(ret, ender);
532
533    /* Hook the tails of the branches to the closing node. */
534    for (br = ret; br != NULL; br = regnext(br))
535        regoptail(br, ender);
536
537    if (paren == '=') {
538        reginsert(IFMATCH,ret);
539        regtail(ret, regnode(NOTHING));
540    }
541    else if (paren == '!') {
542        reginsert(UNLESSM,ret);
543        regtail(ret, regnode(NOTHING));
544    }
545
546    /* Check for proper termination. */
547    if (paren && (regparse >= regxend || *nextchar() != ')')) {
548        FAIL("unmatched () in regexp");
549    } else if (!paren && regparse < regxend) {
550        if (*regparse == ')') {
551            FAIL("unmatched () in regexp");
552        } else
553            FAIL("junk on end of regexp");      /* "Can't happen". */
554        /* NOTREACHED */
555    }
556
557    return(ret);
558}
559
560/*
561 - regbranch - one alternative of an | operator
562 *
563 * Implements the concatenation operator.
564 */
565static char *
566regbranch(flagp)
567I32 *flagp;
568{
569    register char *ret;
570    register char *chain;
571    register char *latest;
572    I32 flags = 0;
573
574    *flagp = WORST;             /* Tentatively. */
575
576    ret = regnode(BRANCH);
577    chain = NULL;
578    regparse--;
579    nextchar();
580    while (regparse < regxend && *regparse != '|' && *regparse != ')') {
581        flags &= ~TRYAGAIN;
582        latest = regpiece(&flags);
583        if (latest == NULL) {
584            if (flags & TRYAGAIN)
585                continue;
586            return(NULL);
587        }
588        *flagp |= flags&HASWIDTH;
589        if (chain == NULL)      /* First piece. */
590            *flagp |= flags&SPSTART;
591        else {
592            regnaughty++;
593            regtail(chain, latest);
594        }
595        chain = latest;
596    }
597    if (chain == NULL)  /* Loop ran zero times. */
598        (void) regnode(NOTHING);
599
600    return(ret);
601}
602
603/*
604 - regpiece - something followed by possible [*+?]
605 *
606 * Note that the branching code sequences used for ? and the general cases
607 * of * and + are somewhat optimized:  they use the same NOTHING node as
608 * both the endmarker for their branch list and the body of the last branch.
609 * It might seem that this node could be dispensed with entirely, but the
610 * endmarker role is not redundant.
611 */
612static char *
613regpiece(flagp)
614I32 *flagp;
615{
616    register char *ret;
617    register char op;
618    register char *next;
619    I32 flags;
620    char *origparse = regparse;
621    char *maxpos;
622    I32 min;
623    I32 max = 32767;
624
625    ret = regatom(&flags);
626    if (ret == NULL) {
627        if (flags & TRYAGAIN)
628            *flagp |= TRYAGAIN;
629        return(NULL);
630    }
631
632    op = *regparse;
633    if (op == '(' && regparse[1] == '?' && regparse[2] == '#') {
634        while (op && op != ')')
635            op = *++regparse;
636        if (op) {
637            nextchar();
638            op = *regparse;
639        }
640    }
641
642    if (op == '{' && regcurly(regparse)) {
643        next = regparse + 1;
644        maxpos = Nullch;
645        while (isDIGIT(*next) || *next == ',') {
646            if (*next == ',') {
647                if (maxpos)
648                    break;
649                else
650                    maxpos = next;
651            }
652            next++;
653        }
654        if (*next == '}') {             /* got one */
655            if (!maxpos)
656                maxpos = next;
657            regparse++;
658            min = atoi(regparse);
659            if (*maxpos == ',')
660                maxpos++;
661            else
662                maxpos = regparse;
663            max = atoi(maxpos);
664            if (!max && *maxpos != '0')
665                max = 32767;            /* meaning "infinity" */
666            regparse = next;
667            nextchar();
668
669        do_curly:
670            if ((flags&SIMPLE)) {
671                regnaughty += 2 + regnaughty / 2;
672                reginsert(CURLY, ret);
673            }
674            else {
675                regnaughty += 4 + regnaughty;   /* compound interest */
676                regtail(ret, regnode(WHILEM));
677                reginsert(CURLYX,ret);
678                regtail(ret, regnode(NOTHING));
679            }
680
681            if (min > 0)
682                *flagp = (WORST|HASWIDTH);
683            if (max && max < min)
684                croak("Can't do {n,m} with n > m");
685            if (regcode != &regdummy) {
686#ifdef REGALIGN
687                *(unsigned short *)(ret+3) = min;
688                *(unsigned short *)(ret+5) = max;
689#else
690                ret[3] = min >> 8; ret[4] = min & 0377;
691                ret[5] = max  >> 8; ret[6] = max  & 0377;
692#endif
693            }
694
695            goto nest_check;
696        }
697    }
698
699    if (!ISMULT1(op)) {
700        *flagp = flags;
701        return(ret);
702    }
703
704    if (!(flags&HASWIDTH) && op != '?')
705      FAIL("regexp *+ operand could be empty"); /* else may core dump */
706
707    nextchar();
708
709    *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
710
711    if (op == '*' && (flags&SIMPLE)) {
712        reginsert(STAR, ret);
713        regnaughty += 4;
714    }
715    else if (op == '*') {
716        min = 0;
717        goto do_curly;
718    } else if (op == '+' && (flags&SIMPLE)) {
719        reginsert(PLUS, ret);
720        regnaughty += 3;
721    }
722    else if (op == '+') {
723        min = 1;
724        goto do_curly;
725    } else if (op == '?') {
726        min = 0; max = 1;
727        goto do_curly;
728    }
729  nest_check:
730    if (dowarn && regcode != &regdummy && !(flags&HASWIDTH) && max > 10000) {
731        warn("%.*s matches null string many times",
732            regparse - origparse, origparse);
733    }
734
735    if (*regparse == '?') {
736        nextchar();
737        reginsert(MINMOD, ret);
738#ifdef REGALIGN
739        regtail(ret, ret + 4);
740#else
741        regtail(ret, ret + 3);
742#endif
743    }
744    if (ISMULT2(regparse))
745        FAIL("nested *?+ in regexp");
746
747    return(ret);
748}
749
750/*
751 - regatom - the lowest level
752 *
753 * Optimization:  gobbles an entire sequence of ordinary characters so that
754 * it can turn them into a single node, which is smaller to store and
755 * faster to run.  Backslashed characters are exceptions, each becoming a
756 * separate node; the code is simpler that way and it's not worth fixing.
757 *
758 * [Yes, it is worth fixing, some scripts can run twice the speed.]
759 */
760static char *
761regatom(flagp)
762I32 *flagp;
763{
764    register char *ret = 0;
765    I32 flags;
766
767    *flagp = WORST;             /* Tentatively. */
768
769tryagain:
770    switch (*regparse) {
771    case '^':
772        nextchar();
773        if (regflags & PMf_MULTILINE)
774            ret = regnode(MBOL);
775        else if (regflags & PMf_SINGLELINE)
776            ret = regnode(SBOL);
777        else
778            ret = regnode(BOL);
779        break;
780    case '$':
781        nextchar();
782        if (regflags & PMf_MULTILINE)
783            ret = regnode(MEOL);
784        else if (regflags & PMf_SINGLELINE)
785            ret = regnode(SEOL);
786        else
787            ret = regnode(EOL);
788        break;
789    case '.':
790        nextchar();
791        if (regflags & PMf_SINGLELINE)
792            ret = regnode(SANY);
793        else
794            ret = regnode(ANY);
795        regnaughty++;
796        *flagp |= HASWIDTH|SIMPLE;
797        break;
798    case '[':
799        regparse++;
800        ret = regclass();
801        *flagp |= HASWIDTH|SIMPLE;
802        break;
803    case '(':
804        nextchar();
805        ret = reg(1, &flags);
806        if (ret == NULL) {
807                if (flags & TRYAGAIN)
808                    goto tryagain;
809                return(NULL);
810        }
811        *flagp |= flags&(HASWIDTH|SPSTART);
812        break;
813    case '|':
814    case ')':
815        if (flags & TRYAGAIN) {
816            *flagp |= TRYAGAIN;
817            return NULL;
818        }
819        croak("internal urp in regexp at /%s/", regparse);
820                                /* Supposed to be caught earlier. */
821        break;
822    case '{':
823        if (!regcurly(regparse)) {
824            regparse++;
825            goto defchar;
826        }
827        /* FALL THROUGH */
828    case '?':
829    case '+':
830    case '*':
831        FAIL("?+*{} follows nothing in regexp");
832        break;
833    case '\\':
834        switch (*++regparse) {
835        case 'A':
836            ret = regnode(SBOL);
837            *flagp |= SIMPLE;
838            nextchar();
839            break;
840        case 'G':
841            ret = regnode(GPOS);
842            *flagp |= SIMPLE;
843            nextchar();
844            break;
845        case 'Z':
846            ret = regnode(SEOL);
847            *flagp |= SIMPLE;
848            nextchar();
849            break;
850        case 'w':
851            ret = regnode((regflags & PMf_LOCALE) ? ALNUML : ALNUM);
852            *flagp |= HASWIDTH|SIMPLE;
853            nextchar();
854            break;
855        case 'W':
856            ret = regnode((regflags & PMf_LOCALE) ? NALNUML : NALNUM);
857            *flagp |= HASWIDTH|SIMPLE;
858            nextchar();
859            break;
860        case 'b':
861            ret = regnode((regflags & PMf_LOCALE) ? BOUNDL : BOUND);
862            *flagp |= SIMPLE;
863            nextchar();
864            break;
865        case 'B':
866            ret = regnode((regflags & PMf_LOCALE) ? NBOUNDL : NBOUND);
867            *flagp |= SIMPLE;
868            nextchar();
869            break;
870        case 's':
871            ret = regnode((regflags & PMf_LOCALE) ? SPACEL : SPACE);
872            *flagp |= HASWIDTH|SIMPLE;
873            nextchar();
874            break;
875        case 'S':
876            ret = regnode((regflags & PMf_LOCALE) ? NSPACEL : NSPACE);
877            *flagp |= HASWIDTH|SIMPLE;
878            nextchar();
879            break;
880        case 'd':
881            ret = regnode(DIGIT);
882            *flagp |= HASWIDTH|SIMPLE;
883            nextchar();
884            break;
885        case 'D':
886            ret = regnode(NDIGIT);
887            *flagp |= HASWIDTH|SIMPLE;
888            nextchar();
889            break;
890        case 'n':
891        case 'r':
892        case 't':
893        case 'f':
894        case 'e':
895        case 'a':
896        case 'x':
897        case 'c':
898        case '0':
899            goto defchar;
900        case '1': case '2': case '3': case '4':
901        case '5': case '6': case '7': case '8': case '9':
902            {
903                I32 num = atoi(regparse);
904
905                if (num > 9 && num >= regnpar)
906                    goto defchar;
907                else {
908                    regsawback = 1;
909                    ret = reganode((regflags & PMf_FOLD)
910                                   ? ((regflags & PMf_LOCALE) ? REFFL : REFF)
911                                   : REF, num);
912                    *flagp |= HASWIDTH;
913                    while (isDIGIT(*regparse))
914                        regparse++;
915                    regparse--;
916                    nextchar();
917                }
918            }
919            break;
920        case '\0':
921            if (regparse >= regxend)
922                FAIL("trailing \\ in regexp");
923            /* FALL THROUGH */
924        default:
925            goto defchar;
926        }
927        break;
928
929    case '#':
930        if (regflags & PMf_EXTENDED) {
931            while (regparse < regxend && *regparse != '\n') regparse++;
932            if (regparse < regxend)
933                goto tryagain;
934        }
935        /* FALL THROUGH */
936
937    default: {
938            register I32 len;
939            register char ender;
940            register char *p;
941            char *oldp;
942            I32 numlen;
943
944            regparse++;
945
946        defchar:
947            ret = regnode((regflags & PMf_FOLD)
948                          ? ((regflags & PMf_LOCALE) ? EXACTFL : EXACTF)
949                          : EXACT);
950            regc(0);            /* save spot for len */
951            for (len = 0, p = regparse - 1;
952              len < 127 && p < regxend;
953              len++)
954            {
955                oldp = p;
956
957                if (regflags & PMf_EXTENDED)
958                    p = regwhite(p, regxend);
959                switch (*p) {
960                case '^':
961                case '$':
962                case '.':
963                case '[':
964                case '(':
965                case ')':
966                case '|':
967                    goto loopdone;
968                case '\\':
969                    switch (*++p) {
970                    case 'A':
971                    case 'G':
972                    case 'Z':
973                    case 'w':
974                    case 'W':
975                    case 'b':
976                    case 'B':
977                    case 's':
978                    case 'S':
979                    case 'd':
980                    case 'D':
981                        --p;
982                        goto loopdone;
983                    case 'n':
984                        ender = '\n';
985                        p++;
986                        break;
987                    case 'r':
988                        ender = '\r';
989                        p++;
990                        break;
991                    case 't':
992                        ender = '\t';
993                        p++;
994                        break;
995                    case 'f':
996                        ender = '\f';
997                        p++;
998                        break;
999                    case 'e':
1000                        ender = '\033';
1001                        p++;
1002                        break;
1003                    case 'a':
1004                        ender = '\007';
1005                        p++;
1006                        break;
1007                    case 'x':
1008                        ender = scan_hex(++p, 2, &numlen);
1009                        p += numlen;
1010                        break;
1011                    case 'c':
1012                        p++;
1013                        ender = UCHARAT(p++);
1014                        ender = toCTRL(ender);
1015                        break;
1016                    case '0': case '1': case '2': case '3':case '4':
1017                    case '5': case '6': case '7': case '8':case '9':
1018                        if (*p == '0' ||
1019                          (isDIGIT(p[1]) && atoi(p) >= regnpar) ) {
1020                            ender = scan_oct(p, 3, &numlen);
1021                            p += numlen;
1022                        }
1023                        else {
1024                            --p;
1025                            goto loopdone;
1026                        }
1027                        break;
1028                    case '\0':
1029                        if (p >= regxend)
1030                            FAIL("trailing \\ in regexp");
1031                        /* FALL THROUGH */
1032                    default:
1033                        ender = *p++;
1034                        break;
1035                    }
1036                    break;
1037                default:
1038                    ender = *p++;
1039                    break;
1040                }
1041                if (regflags & PMf_EXTENDED)
1042                    p = regwhite(p, regxend);
1043                if (ISMULT2(p)) { /* Back off on ?+*. */
1044                    if (len)
1045                        p = oldp;
1046                    else {
1047                        len++;
1048                        regc(ender);
1049                    }
1050                    break;
1051                }
1052                regc(ender);
1053            }
1054        loopdone:
1055            regparse = p - 1;
1056            nextchar();
1057            if (len < 0)
1058                FAIL("internal disaster in regexp");
1059            if (len > 0)
1060                *flagp |= HASWIDTH;
1061            if (len == 1)
1062                *flagp |= SIMPLE;
1063            if (regcode != &regdummy)
1064                *OPERAND(ret) = len;
1065            regc('\0');
1066        }
1067        break;
1068    }
1069
1070    return(ret);
1071}
1072
1073static char *
1074regwhite(p, e)
1075char *p;
1076char *e;
1077{
1078    while (p < e) {
1079        if (isSPACE(*p))
1080            ++p;
1081        else if (*p == '#') {
1082            do {
1083                p++;
1084            } while (p < e && *p != '\n');
1085        }
1086        else
1087            break;
1088    }
1089    return p;
1090}
1091
1092static void
1093regset(opnd, c)
1094char *opnd;
1095register I32 c;
1096{
1097    if (opnd == &regdummy)
1098        return;
1099    c &= 0xFF;
1100    opnd[1 + (c >> 3)] |= (1 << (c & 7));
1101}
1102
1103static char *
1104regclass()
1105{
1106    register char *opnd;
1107    register I32 class;
1108    register I32 lastclass = 1234;
1109    register I32 range = 0;
1110    register char *ret;
1111    register I32 def;
1112    I32 numlen;
1113
1114    ret = regnode(ANYOF);
1115    opnd = regcode;
1116    for (class = 0; class < 33; class++)
1117        regc(0);
1118    if (*regparse == '^') {     /* Complement of range. */
1119        regnaughty++;
1120        regparse++;
1121        if (opnd != &regdummy)
1122            *opnd |= ANYOF_INVERT;
1123    }
1124    if (opnd != &regdummy) {
1125        if (regflags & PMf_FOLD)
1126            *opnd |= ANYOF_FOLD;
1127        if (regflags & PMf_LOCALE)
1128            *opnd |= ANYOF_LOCALE;
1129    }
1130    if (*regparse == ']' || *regparse == '-')
1131        goto skipcond;          /* allow 1st char to be ] or - */
1132    while (regparse < regxend && *regparse != ']') {
1133       skipcond:
1134        class = UCHARAT(regparse++);
1135        if (class == '\\') {
1136            class = UCHARAT(regparse++);
1137            switch (class) {
1138            case 'w':
1139                if (regflags & PMf_LOCALE) {
1140                    if (opnd != &regdummy)
1141                        *opnd |= ANYOF_ALNUML;
1142                }
1143                else {
1144                    for (class = 0; class < 256; class++)
1145                        if (isALNUM(class))
1146                            regset(opnd, class);
1147                }
1148                lastclass = 1234;
1149                continue;
1150            case 'W':
1151                if (regflags & PMf_LOCALE) {
1152                    if (opnd != &regdummy)
1153                        *opnd |= ANYOF_NALNUML;
1154                }
1155                else {
1156                    for (class = 0; class < 256; class++)
1157                        if (!isALNUM(class))
1158                            regset(opnd, class);
1159                }
1160                lastclass = 1234;
1161                continue;
1162            case 's':
1163                if (regflags & PMf_LOCALE) {
1164                    if (opnd != &regdummy)
1165                        *opnd |= ANYOF_SPACEL;
1166                }
1167                else {
1168                    for (class = 0; class < 256; class++)
1169                        if (isSPACE(class))
1170                            regset(opnd, class);
1171                }
1172                lastclass = 1234;
1173                continue;
1174            case 'S':
1175                if (regflags & PMf_LOCALE) {
1176                    if (opnd != &regdummy)
1177                        *opnd |= ANYOF_NSPACEL;
1178                }
1179                else {
1180                    for (class = 0; class < 256; class++)
1181                        if (!isSPACE(class))
1182                            regset(opnd, class);
1183                }
1184                lastclass = 1234;
1185                continue;
1186            case 'd':
1187                for (class = '0'; class <= '9'; class++)
1188                    regset(opnd, class);
1189                lastclass = 1234;
1190                continue;
1191            case 'D':
1192                for (class = 0; class < '0'; class++)
1193                    regset(opnd, class);
1194                for (class = '9' + 1; class < 256; class++)
1195                    regset(opnd, class);
1196                lastclass = 1234;
1197                continue;
1198            case 'n':
1199                class = '\n';
1200                break;
1201            case 'r':
1202                class = '\r';
1203                break;
1204            case 't':
1205                class = '\t';
1206                break;
1207            case 'f':
1208                class = '\f';
1209                break;
1210            case 'b':
1211                class = '\b';
1212                break;
1213            case 'e':
1214                class = '\033';
1215                break;
1216            case 'a':
1217                class = '\007';
1218                break;
1219            case 'x':
1220                class = scan_hex(regparse, 2, &numlen);
1221                regparse += numlen;
1222                break;
1223            case 'c':
1224                class = UCHARAT(regparse++);
1225                class = toCTRL(class);
1226                break;
1227            case '0': case '1': case '2': case '3': case '4':
1228            case '5': case '6': case '7': case '8': case '9':
1229                class = scan_oct(--regparse, 3, &numlen);
1230                regparse += numlen;
1231                break;
1232            }
1233        }
1234        if (range) {
1235            if (lastclass > class)
1236                FAIL("invalid [] range in regexp");
1237            range = 0;
1238        }
1239        else {
1240            lastclass = class;
1241            if (*regparse == '-' && regparse+1 < regxend &&
1242              regparse[1] != ']') {
1243                regparse++;
1244                range = 1;
1245                continue;       /* do it next time */
1246            }
1247        }
1248        for ( ; lastclass <= class; lastclass++)
1249            regset(opnd, lastclass);
1250        lastclass = class;
1251    }
1252    if (*regparse != ']')
1253        FAIL("unmatched [] in regexp");
1254    nextchar();
1255    return ret;
1256}
1257
1258static char*
1259nextchar()
1260{
1261    char* retval = regparse++;
1262
1263    for (;;) {
1264        if (*regparse == '(' && regparse[1] == '?' &&
1265                regparse[2] == '#') {
1266            while (*regparse && *regparse != ')')
1267                regparse++;
1268            regparse++;
1269            continue;
1270        }
1271        if (regflags & PMf_EXTENDED) {
1272            if (isSPACE(*regparse)) {
1273                regparse++;
1274                continue;
1275            }
1276            else if (*regparse == '#') {
1277                while (*regparse && *regparse != '\n')
1278                    regparse++;
1279                regparse++;
1280                continue;
1281            }
1282        }
1283        return retval;
1284    }
1285}
1286
1287/*
1288- regnode - emit a node
1289*/
1290#ifdef CAN_PROTOTYPE
1291static char *                   /* Location. */
1292regnode(char op)
1293#else
1294static char *                   /* Location. */
1295regnode(op)
1296char op;
1297#endif
1298{
1299    register char *ret;
1300    register char *ptr;
1301
1302    ret = regcode;
1303    if (ret == &regdummy) {
1304#ifdef REGALIGN
1305        if (!(regsize & 1))
1306            regsize++;
1307#endif
1308        regsize += 3;
1309        return(ret);
1310    }
1311
1312#ifdef REGALIGN
1313#ifndef lint
1314    if (!((long)ret & 1))
1315      *ret++ = 127;
1316#endif
1317#endif
1318    ptr = ret;
1319    *ptr++ = op;
1320    *ptr++ = '\0';              /* Null "next" pointer. */
1321    *ptr++ = '\0';
1322    regcode = ptr;
1323
1324    return(ret);
1325}
1326
1327/*
1328- reganode - emit a node with an argument
1329*/
1330#ifdef CAN_PROTOTYPE
1331static char *                   /* Location. */
1332reganode(char op, unsigned short arg)
1333#else
1334static char *                   /* Location. */
1335reganode(op, arg)
1336char op;
1337unsigned short arg;
1338#endif
1339{
1340    register char *ret;
1341    register char *ptr;
1342
1343    ret = regcode;
1344    if (ret == &regdummy) {
1345#ifdef REGALIGN
1346        if (!(regsize & 1))
1347            regsize++;
1348#endif
1349        regsize += 5;
1350        return(ret);
1351    }
1352
1353#ifdef REGALIGN
1354#ifndef lint
1355    if (!((long)ret & 1))
1356      *ret++ = 127;
1357#endif
1358#endif
1359    ptr = ret;
1360    *ptr++ = op;
1361    *ptr++ = '\0';              /* Null "next" pointer. */
1362    *ptr++ = '\0';
1363#ifdef REGALIGN
1364    *(unsigned short *)(ret+3) = arg;
1365#else
1366    ret[3] = arg >> 8; ret[4] = arg & 0377;
1367#endif
1368    ptr += 2;
1369    regcode = ptr;
1370
1371    return(ret);
1372}
1373
1374/*
1375- regc - emit (if appropriate) a byte of code
1376*/
1377#ifdef CAN_PROTOTYPE
1378static void
1379regc(char b)
1380#else
1381static void
1382regc(b)
1383char b;
1384#endif
1385{
1386    if (regcode != &regdummy)
1387        *regcode++ = b;
1388    else
1389        regsize++;
1390}
1391
1392/*
1393- reginsert - insert an operator in front of already-emitted operand
1394*
1395* Means relocating the operand.
1396*/
1397#ifdef CAN_PROTOTYPE
1398static void
1399reginsert(char op, char *opnd)
1400#else
1401static void
1402reginsert(op, opnd)
1403char op;
1404char *opnd;
1405#endif
1406{
1407    register char *src;
1408    register char *dst;
1409    register char *place;
1410    register int offset = (regkind[(U8)op] == CURLY ? 4 : 0);
1411
1412    if (regcode == &regdummy) {
1413#ifdef REGALIGN
1414        regsize += 4 + offset;
1415#else
1416        regsize += 3 + offset;
1417#endif
1418        return;
1419    }
1420
1421    src = regcode;
1422#ifdef REGALIGN
1423    regcode += 4 + offset;
1424#else
1425    regcode += 3 + offset;
1426#endif
1427    dst = regcode;
1428    while (src > opnd)
1429        *--dst = *--src;
1430
1431    place = opnd;               /* Op node, where operand used to be. */
1432    *place++ = op;
1433    *place++ = '\0';
1434    *place++ = '\0';
1435    while (offset-- > 0)
1436        *place++ = '\0';
1437#ifdef REGALIGN
1438    *place++ = '\177';
1439#endif
1440}
1441
1442/*
1443- regtail - set the next-pointer at the end of a node chain
1444*/
1445static void
1446regtail(p, val)
1447char *p;
1448char *val;
1449{
1450    register char *scan;
1451    register char *temp;
1452    register I32 offset;
1453
1454    if (p == &regdummy)
1455        return;
1456
1457    /* Find last node. */
1458    scan = p;
1459    for (;;) {
1460        temp = regnext(scan);
1461        if (temp == NULL)
1462            break;
1463        scan = temp;
1464    }
1465
1466#ifdef REGALIGN
1467    offset = val - scan;
1468#ifndef lint
1469    *(short*)(scan+1) = offset;
1470#else
1471    offset = offset;
1472#endif
1473#else
1474    if (OP(scan) == BACK)
1475        offset = scan - val;
1476    else
1477        offset = val - scan;
1478    *(scan+1) = (offset>>8)&0377;
1479    *(scan+2) = offset&0377;
1480#endif
1481}
1482
1483/*
1484- regoptail - regtail on operand of first argument; nop if operandless
1485*/
1486static void
1487regoptail(p, val)
1488char *p;
1489char *val;
1490{
1491    /* "Operandless" and "op != BRANCH" are synonymous in practice. */
1492    if (p == NULL || p == &regdummy || regkind[(U8)OP(p)] != BRANCH)
1493        return;
1494    regtail(NEXTOPER(p), val);
1495}
1496
1497/*
1498 - regcurly - a little FSA that accepts {\d+,?\d*}
1499 */
1500STATIC I32
1501regcurly(s)
1502register char *s;
1503{
1504    if (*s++ != '{')
1505        return FALSE;
1506    if (!isDIGIT(*s))
1507        return FALSE;
1508    while (isDIGIT(*s))
1509        s++;
1510    if (*s == ',')
1511        s++;
1512    while (isDIGIT(*s))
1513        s++;
1514    if (*s != '}')
1515        return FALSE;
1516    return TRUE;
1517}
1518
1519#ifdef DEBUGGING
1520
1521/*
1522 - regdump - dump a regexp onto Perl_debug_log in vaguely comprehensible form
1523 */
1524void
1525regdump(r)
1526regexp *r;
1527{
1528    register char *s;
1529    register char op = EXACT;   /* Arbitrary non-END op. */
1530    register char *next;
1531    SV *sv = sv_newmortal();
1532
1533    s = r->program + 1;
1534    while (op != END) { /* While that wasn't END last time... */
1535#ifdef REGALIGN
1536        if (!((long)s & 1))
1537            s++;
1538#endif
1539        op = OP(s);
1540        /* where, what */
1541        regprop(sv, s);
1542        PerlIO_printf(Perl_debug_log, "%2ld%s", (long)(s - r->program), SvPVX(sv));
1543        next = regnext(s);
1544        s += regarglen[(U8)op];
1545        if (next == NULL)               /* Next ptr. */
1546            PerlIO_printf(Perl_debug_log, "(0)");
1547        else
1548            PerlIO_printf(Perl_debug_log, "(%ld)", (long)(s-r->program)+(next-s));
1549        s += 3;
1550        if (op == ANYOF) {
1551            s += 33;
1552        }
1553        if (regkind[(U8)op] == EXACT) {
1554            /* Literal string, where present. */
1555            s++;
1556            (void)PerlIO_putc(Perl_debug_log, ' ');
1557            (void)PerlIO_putc(Perl_debug_log, '<');
1558            while (*s != '\0') {
1559                (void)PerlIO_putc(Perl_debug_log,*s);
1560                s++;
1561            }
1562            (void)PerlIO_putc(Perl_debug_log, '>');
1563            s++;
1564        }
1565        (void)PerlIO_putc(Perl_debug_log, '\n');
1566    }
1567
1568    /* Header fields of interest. */
1569    if (r->regstart)
1570        PerlIO_printf(Perl_debug_log, "start `%s' ", SvPVX(r->regstart));
1571    if (r->regstclass) {
1572        regprop(sv, r->regstclass);
1573        PerlIO_printf(Perl_debug_log, "stclass `%s' ", SvPVX(sv));
1574    }
1575    if (r->reganch & ROPT_ANCH) {
1576        PerlIO_printf(Perl_debug_log, "anchored");
1577        if (r->reganch & ROPT_ANCH_BOL)
1578            PerlIO_printf(Perl_debug_log, "(BOL)");
1579        if (r->reganch & ROPT_ANCH_GPOS)
1580            PerlIO_printf(Perl_debug_log, "(GPOS)");
1581        PerlIO_putc(Perl_debug_log, ' ');
1582    }
1583    if (r->reganch & ROPT_SKIP)
1584        PerlIO_printf(Perl_debug_log, "plus ");
1585    if (r->reganch & ROPT_IMPLICIT)
1586        PerlIO_printf(Perl_debug_log, "implicit ");
1587    if (r->regmust != NULL)
1588        PerlIO_printf(Perl_debug_log, "must have \"%s\" back %ld ", SvPVX(r->regmust),
1589         (long) r->regback);
1590    PerlIO_printf(Perl_debug_log, "minlen %ld ", (long) r->minlen);
1591    PerlIO_printf(Perl_debug_log, "\n");
1592}
1593
1594/*
1595- regprop - printable representation of opcode
1596*/
1597void
1598regprop(sv, op)
1599SV *sv;
1600char *op;
1601{
1602    register char *p = 0;
1603
1604    sv_setpv(sv, ":");
1605    switch (OP(op)) {
1606    case BOL:
1607        p = "BOL";
1608        break;
1609    case MBOL:
1610        p = "MBOL";
1611        break;
1612    case SBOL:
1613        p = "SBOL";
1614        break;
1615    case EOL:
1616        p = "EOL";
1617        break;
1618    case MEOL:
1619        p = "MEOL";
1620        break;
1621    case SEOL:
1622        p = "SEOL";
1623        break;
1624    case ANY:
1625        p = "ANY";
1626        break;
1627    case SANY:
1628        p = "SANY";
1629        break;
1630    case ANYOF:
1631        p = "ANYOF";
1632        break;
1633    case BRANCH:
1634        p = "BRANCH";
1635        break;
1636    case EXACT:
1637        p = "EXACT";
1638        break;
1639    case EXACTF:
1640        p = "EXACTF";
1641        break;
1642    case EXACTFL:
1643        p = "EXACTFL";
1644        break;
1645    case NOTHING:
1646        p = "NOTHING";
1647        break;
1648    case BACK:
1649        p = "BACK";
1650        break;
1651    case END:
1652        p = "END";
1653        break;
1654    case BOUND:
1655        p = "BOUND";
1656        break;
1657    case BOUNDL:
1658        p = "BOUNDL";
1659        break;
1660    case NBOUND:
1661        p = "NBOUND";
1662        break;
1663    case NBOUNDL:
1664        p = "NBOUNDL";
1665        break;
1666    case CURLY:
1667        sv_catpvf(sv, "CURLY {%d,%d}", ARG1(op), ARG2(op));
1668        break;
1669    case CURLYX:
1670        sv_catpvf(sv, "CURLYX {%d,%d}", ARG1(op), ARG2(op));
1671        break;
1672    case REF:
1673        sv_catpvf(sv, "REF%d", ARG1(op));
1674        break;
1675    case REFF:
1676        sv_catpvf(sv, "REFF%d", ARG1(op));
1677        break;
1678    case REFFL:
1679        sv_catpvf(sv, "REFFL%d", ARG1(op));
1680        break;
1681    case OPEN:
1682        sv_catpvf(sv, "OPEN%d", ARG1(op));
1683        break;
1684    case CLOSE:
1685        sv_catpvf(sv, "CLOSE%d", ARG1(op));
1686        p = NULL;
1687        break;
1688    case STAR:
1689        p = "STAR";
1690        break;
1691    case PLUS:
1692        p = "PLUS";
1693        break;
1694    case MINMOD:
1695        p = "MINMOD";
1696        break;
1697    case GPOS:
1698        p = "GPOS";
1699        break;
1700    case UNLESSM:
1701        p = "UNLESSM";
1702        break;
1703    case IFMATCH:
1704        p = "IFMATCH";
1705        break;
1706    case SUCCEED:
1707        p = "SUCCEED";
1708        break;
1709    case WHILEM:
1710        p = "WHILEM";
1711        break;
1712    case DIGIT:
1713        p = "DIGIT";
1714        break;
1715    case NDIGIT:
1716        p = "NDIGIT";
1717        break;
1718    case ALNUM:
1719        p = "ALNUM";
1720        break;
1721    case NALNUM:
1722        p = "NALNUM";
1723        break;
1724    case SPACE:
1725        p = "SPACE";
1726        break;
1727    case NSPACE:
1728        p = "NSPACE";
1729        break;
1730    case ALNUML:
1731        p = "ALNUML";
1732        break;
1733    case NALNUML:
1734        p = "NALNUML";
1735        break;
1736    case SPACEL:
1737        p = "SPACEL";
1738        break;
1739    case NSPACEL:
1740        p = "NSPACEL";
1741        break;
1742    default:
1743        FAIL("corrupted regexp opcode");
1744    }
1745    if (p)
1746        sv_catpv(sv, p);
1747}
1748#endif /* DEBUGGING */
1749
1750void
1751pregfree(r)
1752struct regexp *r;
1753{
1754    if (!r)
1755        return;
1756    if (r->precomp) {
1757        Safefree(r->precomp);
1758        r->precomp = Nullch;
1759    }
1760    if (r->subbase) {
1761        Safefree(r->subbase);
1762        r->subbase = Nullch;
1763    }
1764    if (r->regmust) {
1765        SvREFCNT_dec(r->regmust);
1766        r->regmust = Nullsv;
1767    }
1768    if (r->regstart) {
1769        SvREFCNT_dec(r->regstart);
1770        r->regstart = Nullsv;
1771    }
1772    Safefree(r->startp);
1773    Safefree(r->endp);
1774    Safefree(r);
1775}
Note: See TracBrowser for help on using the repository browser.