allow final period in a file (not followed by a newline) to
[p5sagit/p5-mst-13.2.git] / regexec.c
1 /*    regexec.c
2  */
3
4 /*
5  * "One Ring to rule them all, One Ring to find them..."
6  */
7
8 /* NOTE: this is derived from Henry Spencer's regexp code, and should not
9  * confused with the original package (see point 3 below).  Thanks, Henry!
10  */
11
12 /* Additional note: this code is very heavily munged from Henry's version
13  * in places.  In some spots I've traded clarity for efficiency, so don't
14  * blame Henry for some of the lack of readability.
15  */
16
17 /* The names of the functions have been changed from regcomp and
18  * regexec to  pregcomp and pregexec in order to avoid conflicts
19  * with the POSIX routines of the same names.
20 */
21
22 #ifdef PERL_EXT_RE_BUILD
23 /* need to replace pregcomp et al, so enable that */
24 #  ifndef PERL_IN_XSUB_RE
25 #    define PERL_IN_XSUB_RE
26 #  endif
27 /* need access to debugger hooks */
28 #  ifndef DEBUGGING
29 #    define DEBUGGING
30 #  endif
31 #endif
32
33 #ifdef PERL_IN_XSUB_RE
34 /* We *really* need to overwrite these symbols: */
35 #  define Perl_regexec_flags my_regexec
36 #  define Perl_regdump my_regdump
37 #  define Perl_regprop my_regprop
38 /* *These* symbols are masked to allow static link. */
39 #  define Perl_pregexec my_pregexec
40 #endif 
41
42 /*SUPPRESS 112*/
43 /*
44  * pregcomp and pregexec -- regsub and regerror are not used in perl
45  *
46  *      Copyright (c) 1986 by University of Toronto.
47  *      Written by Henry Spencer.  Not derived from licensed software.
48  *
49  *      Permission is granted to anyone to use this software for any
50  *      purpose on any computer system, and to redistribute it freely,
51  *      subject to the following restrictions:
52  *
53  *      1. The author is not responsible for the consequences of use of
54  *              this software, no matter how awful, even if they arise
55  *              from defects in it.
56  *
57  *      2. The origin of this software must not be misrepresented, either
58  *              by explicit claim or by omission.
59  *
60  *      3. Altered versions must be plainly marked as such, and must not
61  *              be misrepresented as being the original software.
62  *
63  ****    Alterations to Henry's code are...
64  ****
65  ****    Copyright (c) 1991-1998, Larry Wall
66  ****
67  ****    You may distribute under the terms of either the GNU General Public
68  ****    License or the Artistic License, as specified in the README file.
69  *
70  * Beware that some of this code is subtly aware of the way operator
71  * precedence is structured in regular expressions.  Serious changes in
72  * regular-expression syntax might require a total rethink.
73  */
74 #include "EXTERN.h"
75 #include "perl.h"
76
77 #include "regcomp.h"
78
79 #define RF_tainted      1               /* tainted information used? */
80 #define RF_warned       2               /* warned about big count? */
81 #define RF_evaled       4               /* Did an EVAL with setting? */
82 #define RF_utf8         8               /* String contains multibyte chars? */
83
84 #define UTF (PL_reg_flags & RF_utf8)
85
86 #define RS_init         1               /* eval environment created */
87 #define RS_set          2               /* replsv value is set */
88
89 #ifndef STATIC
90 #define STATIC  static
91 #endif
92
93 #ifndef PERL_OBJECT
94 typedef I32 CHECKPOINT;
95
96 /*
97  * Forwards.
98  */
99
100 static I32 regmatch _((regnode *prog));
101 static I32 regrepeat _((regnode *p, I32 max));
102 static I32 regrepeat_hard _((regnode *p, I32 max, I32 *lp));
103 static I32 regtry _((regexp *prog, char *startpos));
104
105 static bool reginclass _((char *p, I32 c));
106 static bool reginclassutf8 _((regnode *f, U8* p));
107 static CHECKPOINT regcppush _((I32 parenfloor));
108 static char * regcppop _((void));
109 static char * regcp_set_to _((I32 ss));
110 static void cache_re _((regexp *prog));
111 static void restore_pos _((void *arg));
112 #endif
113
114 #define REGINCLASS(p,c)  (*(p) ? reginclass(p,c) : ANYOF_TEST(p,c))
115 #define REGINCLASSUTF8(f,p)  (ARG1(f) ? reginclassutf8(f,p) : swash_fetch((SV*)PL_regdata->data[ARG2(f)],p))
116
117 #define CHR_SVLEN(sv) (UTF ? sv_len_utf8(sv) : SvCUR(sv))
118 #define CHR_DIST(a,b) (UTF ? utf8_distance(a,b) : a - b)
119
120 #ifndef PERL_OBJECT
121 static U8 * reghop _((U8 *pos, I32 off));
122 static U8 * reghopmaybe _((U8 *pos, I32 off));
123 #endif
124 #define reghop_c(pos,off) ((char*)reghop((U8*)pos, off))
125 #define reghopmaybe_c(pos,off) ((char*)reghopmaybe((U8*)pos, off))
126 #define HOP(pos,off) (UTF ? reghop((U8*)pos, off) : (U8*)(pos + off))
127 #define HOPMAYBE(pos,off) (UTF ? reghopmaybe((U8*)pos, off) : (U8*)(pos + off))
128 #define HOPc(pos,off) ((char*)HOP(pos,off))
129 #define HOPMAYBEc(pos,off) ((char*)HOPMAYBE(pos,off))
130
131 STATIC CHECKPOINT
132 regcppush(I32 parenfloor)
133 {
134     dTHR;
135     int retval = PL_savestack_ix;
136     int i = (PL_regsize - parenfloor) * 4;
137     int p;
138
139     SSCHECK(i + 5);
140     for (p = PL_regsize; p > parenfloor; p--) {
141         SSPUSHPTR(PL_regendp[p]);
142         SSPUSHPTR(PL_regstartp[p]);
143         SSPUSHPTR(PL_reg_start_tmp[p]);
144         SSPUSHINT(p);
145     }
146     SSPUSHINT(PL_regsize);
147     SSPUSHINT(*PL_reglastparen);
148     SSPUSHPTR(PL_reginput);
149     SSPUSHINT(i + 3);
150     SSPUSHINT(SAVEt_REGCONTEXT);
151     return retval;
152 }
153
154 /* These are needed since we do not localize EVAL nodes: */
155 #  define REGCP_SET  DEBUG_r(PerlIO_printf(Perl_debug_log,              \
156                              "  Setting an EVAL scope, savestack=%i\n", \
157                              PL_savestack_ix)); lastcp = PL_savestack_ix
158
159 #  define REGCP_UNWIND  DEBUG_r(lastcp != PL_savestack_ix ?             \
160                                 PerlIO_printf(Perl_debug_log,           \
161                                 "  Clearing an EVAL scope, savestack=%i..%i\n", \
162                                 lastcp, PL_savestack_ix) : 0); regcpblow(lastcp)
163
164 STATIC char *
165 regcppop(void)
166 {
167     dTHR;
168     I32 i = SSPOPINT;
169     U32 paren = 0;
170     char *input;
171     char *tmps;
172     assert(i == SAVEt_REGCONTEXT);
173     i = SSPOPINT;
174     input = (char *) SSPOPPTR;
175     *PL_reglastparen = SSPOPINT;
176     PL_regsize = SSPOPINT;
177     for (i -= 3; i > 0; i -= 4) {
178         paren = (U32)SSPOPINT;
179         PL_reg_start_tmp[paren] = (char *) SSPOPPTR;
180         PL_regstartp[paren] = (char *) SSPOPPTR;
181         tmps = (char*)SSPOPPTR;
182         if (paren <= *PL_reglastparen)
183             PL_regendp[paren] = tmps;
184         DEBUG_r(
185             PerlIO_printf(Perl_debug_log,
186                           "     restoring \\%d to %d(%d)..%d%s\n",
187                           paren, PL_regstartp[paren] - PL_regbol, 
188                           PL_reg_start_tmp[paren] - PL_regbol,
189                           PL_regendp[paren] - PL_regbol, 
190                           (paren > *PL_reglastparen ? "(no)" : ""));
191         );
192     }
193     DEBUG_r(
194         if (*PL_reglastparen + 1 <= PL_regnpar) {
195             PerlIO_printf(Perl_debug_log,
196                           "     restoring \\%d..\\%d to undef\n",
197                           *PL_reglastparen + 1, PL_regnpar);
198         }
199     );
200     for (paren = *PL_reglastparen + 1; paren <= PL_regnpar; paren++) {
201         if (paren > PL_regsize)
202             PL_regstartp[paren] = Nullch;
203         PL_regendp[paren] = Nullch;
204     }
205     return input;
206 }
207
208 STATIC char *
209 regcp_set_to(I32 ss)
210 {
211     dTHR;
212     I32 tmp = PL_savestack_ix;
213
214     PL_savestack_ix = ss;
215     regcppop();
216     PL_savestack_ix = tmp;
217     return Nullch;
218 }
219
220 typedef struct re_cc_state
221 {
222     I32 ss;
223     regnode *node;
224     struct re_cc_state *prev;
225     CURCUR *cc;
226     regexp *re;
227 } re_cc_state;
228
229 #define regcpblow(cp) LEAVE_SCOPE(cp)
230
231 /*
232  * pregexec and friends
233  */
234
235 /*
236  - pregexec - match a regexp against a string
237  */
238 I32
239 pregexec(register regexp *prog, char *stringarg, register char *strend,
240          char *strbeg, I32 minend, SV *screamer, U32 nosave)
241 /* strend: pointer to null at end of string */
242 /* strbeg: real beginning of string */
243 /* minend: end of match must be >=minend after stringarg. */
244 /* nosave: For optimizations. */
245 {
246     return
247         regexec_flags(prog, stringarg, strend, strbeg, minend, screamer, NULL, 
248                       nosave ? 0 : REXEC_COPY_STR);
249 }
250
251 STATIC void
252 cache_re(regexp *prog)
253 {
254     dTHR;
255     PL_regprecomp = prog->precomp;              /* Needed for FAIL. */
256 #ifdef DEBUGGING
257     PL_regprogram = prog->program;
258 #endif
259     PL_regnpar = prog->nparens;
260     PL_regdata = prog->data;    
261     PL_reg_re = prog;    
262 }
263
264 STATIC void
265 restore_pos(void *arg)
266 {       
267     if (PL_reg_eval_set) {    
268         PL_reg_magic->mg_len = PL_reg_oldpos;
269         PL_reg_eval_set = 0;
270     }   
271 }
272
273
274 /*
275  - regexec_flags - match a regexp against a string
276  */
277 I32
278 regexec_flags(register regexp *prog, char *stringarg, register char *strend,
279               char *strbeg, I32 minend, SV *sv, void *data, U32 flags)
280 /* strend: pointer to null at end of string */
281 /* strbeg: real beginning of string */
282 /* minend: end of match must be >=minend after stringarg. */
283 /* data: May be used for some additional optimizations. */
284 /* nosave: For optimizations. */
285 {
286     dTHR;
287     register char *s;
288     register regnode *c;
289     register char *startpos = stringarg;
290     register I32 tmp;
291     I32 minlen;         /* must match at least this many chars */
292     I32 dontbother = 0; /* how many characters not to try at end */
293     CURCUR cc;
294     I32 start_shift = 0;                /* Offset of the start to find
295                                          constant substr. */            /* CC */
296     I32 end_shift = 0;                  /* Same for the end. */         /* CC */
297     I32 scream_pos = -1;                /* Internal iterator of scream. */
298     char *scream_olds;
299     SV* oreplsv = GvSV(PL_replgv);
300
301     cc.cur = 0;
302     cc.oldcc = 0;
303     PL_regcc = &cc;
304
305     cache_re(prog);
306 #ifdef DEBUGGING
307     PL_regnarrate = PL_debug & 512;
308 #endif
309
310     /* Be paranoid... */
311     if (prog == NULL || startpos == NULL) {
312         croak("NULL regexp parameter");
313         return 0;
314     }
315
316     minlen = prog->minlen;
317     if (strend - startpos < minlen) goto phooey;
318
319     if (startpos == strbeg)     /* is ^ valid at stringarg? */
320         PL_regprev = '\n';
321     else {
322         PL_regprev = (U32)stringarg[-1];
323         if (!PL_multiline && PL_regprev == '\n')
324             PL_regprev = '\0';          /* force ^ to NOT match */
325     }
326
327     /* Check validity of program. */
328     if (UCHARAT(prog->program) != REG_MAGIC) {
329         FAIL("corrupted regexp program");
330     }
331
332     PL_reg_flags = 0;
333     PL_reg_eval_set = 0;
334
335     if (prog->reganch & ROPT_UTF8)
336         PL_reg_flags |= RF_utf8;
337
338     /* Mark beginning of line for ^ and lookbehind. */
339     PL_regbol = startpos;
340     PL_bostr  = strbeg;
341     PL_reg_sv = sv;
342
343     /* Mark end of line for $ (and such) */
344     PL_regeol = strend;
345
346     /* see how far we have to get to not match where we matched before */
347     PL_regtill = startpos+minend;
348
349     /* We start without call_cc context.  */
350     PL_reg_call_cc = 0;
351
352     /* If there is a "must appear" string, look for it. */
353     s = startpos;
354     if (!(flags & REXEC_CHECKED) 
355         && prog->check_substr != Nullsv &&
356         !(prog->reganch & ROPT_ANCH_GPOS) &&
357         (!(prog->reganch & (ROPT_ANCH_BOL | ROPT_ANCH_MBOL))
358          || (PL_multiline && prog->check_substr == prog->anchored_substr)) )
359     {
360         char *t;
361         start_shift = prog->check_offset_min;   /* okay to underestimate on CC */
362         /* Should be nonnegative! */
363         end_shift = minlen - start_shift - CHR_SVLEN(prog->check_substr);
364         if (flags & REXEC_SCREAM) {
365             if (PL_screamfirst[BmRARE(prog->check_substr)] >= 0)
366                     s = screaminstr(sv, prog->check_substr, 
367                                     start_shift + (stringarg - strbeg),
368                                     end_shift, &scream_pos, 0);
369             else
370                     s = Nullch;
371             scream_olds = s;
372         }
373         else
374             s = fbm_instr((unsigned char*)s + start_shift,
375                           (unsigned char*)strend - end_shift,
376                 prog->check_substr, 0);
377         if (!s) {
378             ++BmUSEFUL(prog->check_substr);     /* hooray */
379             goto phooey;        /* not present */
380         }
381         else if (s - stringarg > prog->check_offset_max &&
382                  (UTF 
383                     ? ((t = reghopmaybe_c(s, -(prog->check_offset_max))) && t >= stringarg)
384                     : (t = s - prog->check_offset_max) != 0
385                  )
386                 )
387         {
388             ++BmUSEFUL(prog->check_substr);     /* hooray/2 */
389             s = t;
390         }
391         else if (!(prog->reganch & ROPT_NAUGHTY)
392                    && --BmUSEFUL(prog->check_substr) < 0
393                    && prog->check_substr == prog->float_substr) { /* boo */
394             SvREFCNT_dec(prog->check_substr);
395             prog->check_substr = Nullsv;        /* disable */
396             prog->float_substr = Nullsv;        /* clear */
397             s = startpos;
398         }
399         else
400             s = startpos;
401     }
402
403     DEBUG_r(
404         PerlIO_printf(Perl_debug_log, 
405                       "%sMatching%s `%s%.60s%s%s' against `%s%.*s%s%s'\n",
406                       PL_colors[4],PL_colors[5],PL_colors[0],
407                       prog->precomp,
408                       PL_colors[1],
409                       (strlen(prog->precomp) > 60 ? "..." : ""),
410                       PL_colors[0], 
411                       (strend - startpos > 60 ? 60 : strend - startpos),
412                       startpos, PL_colors[1],
413                       (strend - startpos > 60 ? "..." : ""))
414         );
415
416     if (prog->reganch & ROPT_GPOS_SEEN) {
417         MAGIC *mg;
418         int pos = 0;
419
420         if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv) 
421             && (mg = mg_find(sv, 'g')) && mg->mg_len >= 0)
422             pos = mg->mg_len;
423         PL_reg_ganch = startpos + pos;
424     }
425
426     /* Simplest case:  anchored match need be tried only once. */
427     /*  [unless only anchor is BOL and multiline is set] */
428     if (prog->reganch & (ROPT_ANCH & ~ROPT_ANCH_GPOS)) {
429         if (regtry(prog, startpos))
430             goto got_it;
431         else if (PL_multiline || (prog->reganch & ROPT_IMPLICIT)
432                  || (prog->reganch & ROPT_ANCH_MBOL)) /* XXXX SBOL? */
433         {
434             if (minlen)
435                 dontbother = minlen - 1;
436             strend = HOPc(strend, -dontbother);
437             /* for multiline we only have to try after newlines */
438             if (s > startpos)
439                 s--;
440             while (s < strend) {
441                 if (*s++ == '\n') {     /* don't need PL_utf8skip here */
442                     if (s < strend && regtry(prog, s))
443                         goto got_it;
444                 }
445             }
446         }
447         goto phooey;
448     } else if (prog->reganch & ROPT_ANCH_GPOS) {
449         if (regtry(prog, PL_reg_ganch))
450             goto got_it;
451         goto phooey;
452     }
453
454     /* Messy cases:  unanchored match. */
455     if (prog->anchored_substr && prog->reganch & ROPT_SKIP) { 
456         /* we have /x+whatever/ */
457         /* it must be a one character string */
458         char ch = SvPVX(prog->anchored_substr)[0];
459         if (UTF) {
460             while (s < strend) {
461                 if (*s == ch) {
462                     if (regtry(prog, s)) goto got_it;
463                     s += UTF8SKIP(s);
464                     while (s < strend && *s == ch)
465                         s += UTF8SKIP(s);
466                 }
467                 s += UTF8SKIP(s);
468             }
469         }
470         else {
471             while (s < strend) {
472                 if (*s == ch) {
473                     if (regtry(prog, s)) goto got_it;
474                     s++;
475                     while (s < strend && *s == ch)
476                         s++;
477                 }
478                 s++;
479             }
480         }
481     }
482     /*SUPPRESS 560*/
483     else if (prog->anchored_substr != Nullsv
484              || (prog->float_substr != Nullsv 
485                  && prog->float_max_offset < strend - s)) {
486         SV *must = prog->anchored_substr 
487             ? prog->anchored_substr : prog->float_substr;
488         I32 back_max = 
489             prog->anchored_substr ? prog->anchored_offset : prog->float_max_offset;
490         I32 back_min = 
491             prog->anchored_substr ? prog->anchored_offset : prog->float_min_offset;
492         I32 delta = back_max - back_min;
493         char *last = HOPc(strend, 0-(CHR_SVLEN(must) + back_min)); /* Cannot start after this */
494         char *last1;            /* Last position checked before */
495
496         if (s > PL_bostr)
497             last1 = HOPc(s, -1);
498         else
499             last1 = s - 1;      /* bogus */
500
501         /* XXXX check_substr already used to find `s', can optimize if
502            check_substr==must. */
503         scream_pos = -1;
504         dontbother = end_shift;
505         strend = HOPc(strend, -dontbother);
506         while ( (s <= last) &&
507                 ((flags & REXEC_SCREAM) 
508                  ? (s = screaminstr(sv, must, HOPc(s, back_min) - strbeg,
509                                     end_shift, &scream_pos, 0))
510                  : (s = fbm_instr((unsigned char*)HOP(s, back_min),
511                                   (unsigned char*)strend, must, 0))) ) {
512             if (HOPc(s, -back_max) > last1) {
513                 last1 = HOPc(s, -back_min);
514                 s = HOPc(s, -back_max);
515             }
516             else {
517                 char *t = (last1 >= PL_bostr) ? HOPc(last1, 1) : last1 + 1;
518
519                 last1 = HOPc(s, -back_min);
520                 s = t;          
521             }
522             if (UTF) {
523                 while (s <= last1) {
524                     if (regtry(prog, s))
525                         goto got_it;
526                     s += UTF8SKIP(s);
527                 }
528             }
529             else {
530                 while (s <= last1) {
531                     if (regtry(prog, s))
532                         goto got_it;
533                     s++;
534                 }
535             }
536         }
537         goto phooey;
538     }
539     else if (c = prog->regstclass) {
540         I32 doevery = (prog->reganch & ROPT_SKIP) == 0;
541         char *cc;
542
543         if (minlen)
544             dontbother = minlen - 1;
545         strend = HOPc(strend, -dontbother);     /* don't bother with what can't match */
546         tmp = 1;
547         /* We know what class it must start with. */
548         switch (OP(c)) {
549         case ANYOFUTF8:
550             cc = (char *) OPERAND(c);
551             while (s < strend) {
552                 if (REGINCLASSUTF8(c, (U8*)s)) {
553                     if (tmp && regtry(prog, s))
554                         goto got_it;
555                     else
556                         tmp = doevery;
557                 }
558                 else
559                     tmp = 1;
560                 s += UTF8SKIP(s);
561             }
562             break;
563         case ANYOF:
564             cc = (char *) OPERAND(c);
565             while (s < strend) {
566                 if (REGINCLASS(cc, *s)) {
567                     if (tmp && regtry(prog, s))
568                         goto got_it;
569                     else
570                         tmp = doevery;
571                 }
572                 else
573                     tmp = 1;
574                 s++;
575             }
576             break;
577         case BOUNDL:
578             PL_reg_flags |= RF_tainted;
579             /* FALL THROUGH */
580         case BOUND:
581             if (minlen) {
582                 dontbother++;
583                 strend -= 1;
584             }
585             tmp = (s != startpos) ? UCHARAT(s - 1) : PL_regprev;
586             tmp = ((OP(c) == BOUND ? isALNUM(tmp) : isALNUM_LC(tmp)) != 0);
587             while (s < strend) {
588                 if (tmp == !(OP(c) == BOUND ? isALNUM(*s) : isALNUM_LC(*s))) {
589                     tmp = !tmp;
590                     if (regtry(prog, s))
591                         goto got_it;
592                 }
593                 s++;
594             }
595             if ((minlen || tmp) && regtry(prog,s))
596                 goto got_it;
597             break;
598         case BOUNDLUTF8:
599             PL_reg_flags |= RF_tainted;
600             /* FALL THROUGH */
601         case BOUNDUTF8:
602             if (minlen) {
603                 dontbother++;
604                 strend = reghop_c(strend, -1);
605             }
606             tmp = (I32)(s != startpos) ? utf8_to_uv(reghop((U8*)s, -1), 0) : PL_regprev;
607             tmp = ((OP(c) == BOUND ? isALNUM_uni(tmp) : isALNUM_LC_uni(tmp)) != 0);
608             while (s < strend) {
609                 if (tmp == !(OP(c) == BOUND ?
610                              swash_fetch(PL_utf8_alnum, (U8*)s) :
611                              isALNUM_LC_utf8((U8*)s)))
612                 {
613                     tmp = !tmp;
614                     if (regtry(prog, s))
615                         goto got_it;
616                 }
617                 s += UTF8SKIP(s);
618             }
619             if ((minlen || tmp) && regtry(prog,s))
620                 goto got_it;
621             break;
622         case NBOUNDL:
623             PL_reg_flags |= RF_tainted;
624             /* FALL THROUGH */
625         case NBOUND:
626             if (minlen) {
627                 dontbother++;
628                 strend -= 1;
629             }
630             tmp = (s != startpos) ? UCHARAT(s - 1) : PL_regprev;
631             tmp = ((OP(c) == NBOUND ? isALNUM(tmp) : isALNUM_LC(tmp)) != 0);
632             while (s < strend) {
633                 if (tmp == !(OP(c) == NBOUND ? isALNUM(*s) : isALNUM_LC(*s)))
634                     tmp = !tmp;
635                 else if (regtry(prog, s))
636                     goto got_it;
637                 s++;
638             }
639             if ((minlen || !tmp) && regtry(prog,s))
640                 goto got_it;
641             break;
642         case NBOUNDLUTF8:
643             PL_reg_flags |= RF_tainted;
644             /* FALL THROUGH */
645         case NBOUNDUTF8:
646             if (minlen) {
647                 dontbother++;
648                 strend = reghop_c(strend, -1);
649             }
650             tmp = (I32)(s != startpos) ? utf8_to_uv(reghop((U8*)s, -1), 0) : PL_regprev;
651             tmp = ((OP(c) == NBOUND ? isALNUM_uni(tmp) : isALNUM_LC_uni(tmp)) != 0);
652             while (s < strend) {
653                 if (tmp == !(OP(c) == NBOUND ?
654                              swash_fetch(PL_utf8_alnum, (U8*)s) :
655                              isALNUM_LC_utf8((U8*)s)))
656                     tmp = !tmp;
657                 else if (regtry(prog, s))
658                     goto got_it;
659                 s += UTF8SKIP(s);
660             }
661             if ((minlen || !tmp) && regtry(prog,s))
662                 goto got_it;
663             break;
664         case ALNUM:
665             while (s < strend) {
666                 if (isALNUM(*s)) {
667                     if (tmp && regtry(prog, s))
668                         goto got_it;
669                     else
670                         tmp = doevery;
671                 }
672                 else
673                     tmp = 1;
674                 s++;
675             }
676             break;
677         case ALNUMUTF8:
678             while (s < strend) {
679                 if (swash_fetch(PL_utf8_alnum, (U8*)s)) {
680                     if (tmp && regtry(prog, s))
681                         goto got_it;
682                     else
683                         tmp = doevery;
684                 }
685                 else
686                     tmp = 1;
687                 s += UTF8SKIP(s);
688             }
689             break;
690         case ALNUML:
691             PL_reg_flags |= RF_tainted;
692             while (s < strend) {
693                 if (isALNUM_LC(*s)) {
694                     if (tmp && regtry(prog, s))
695                         goto got_it;
696                     else
697                         tmp = doevery;
698                 }
699                 else
700                     tmp = 1;
701                 s++;
702             }
703             break;
704         case ALNUMLUTF8:
705             PL_reg_flags |= RF_tainted;
706             while (s < strend) {
707                 if (isALNUM_LC_utf8((U8*)s)) {
708                     if (tmp && regtry(prog, s))
709                         goto got_it;
710                     else
711                         tmp = doevery;
712                 }
713                 else
714                     tmp = 1;
715                 s += UTF8SKIP(s);
716             }
717             break;
718         case NALNUM:
719             while (s < strend) {
720                 if (!isALNUM(*s)) {
721                     if (tmp && regtry(prog, s))
722                         goto got_it;
723                     else
724                         tmp = doevery;
725                 }
726                 else
727                     tmp = 1;
728                 s++;
729             }
730             break;
731         case NALNUMUTF8:
732             while (s < strend) {
733                 if (!swash_fetch(PL_utf8_alnum, (U8*)s)) {
734                     if (tmp && regtry(prog, s))
735                         goto got_it;
736                     else
737                         tmp = doevery;
738                 }
739                 else
740                     tmp = 1;
741                 s += UTF8SKIP(s);
742             }
743             break;
744         case NALNUML:
745             PL_reg_flags |= RF_tainted;
746             while (s < strend) {
747                 if (!isALNUM_LC(*s)) {
748                     if (tmp && regtry(prog, s))
749                         goto got_it;
750                     else
751                         tmp = doevery;
752                 }
753                 else
754                     tmp = 1;
755                 s++;
756             }
757             break;
758         case NALNUMLUTF8:
759             PL_reg_flags |= RF_tainted;
760             while (s < strend) {
761                 if (!isALNUM_LC_utf8((U8*)s)) {
762                     if (tmp && regtry(prog, s))
763                         goto got_it;
764                     else
765                         tmp = doevery;
766                 }
767                 else
768                     tmp = 1;
769                 s += UTF8SKIP(s);
770             }
771             break;
772         case SPACE:
773             while (s < strend) {
774                 if (isSPACE(*s)) {
775                     if (tmp && regtry(prog, s))
776                         goto got_it;
777                     else
778                         tmp = doevery;
779                 }
780                 else
781                     tmp = 1;
782                 s++;
783             }
784             break;
785         case SPACEUTF8:
786             while (s < strend) {
787                 if (*s == ' ' || swash_fetch(PL_utf8_space,(U8*)s)) {
788                     if (tmp && regtry(prog, s))
789                         goto got_it;
790                     else
791                         tmp = doevery;
792                 }
793                 else
794                     tmp = 1;
795                 s += UTF8SKIP(s);
796             }
797             break;
798         case SPACEL:
799             PL_reg_flags |= RF_tainted;
800             while (s < strend) {
801                 if (isSPACE_LC(*s)) {
802                     if (tmp && regtry(prog, s))
803                         goto got_it;
804                     else
805                         tmp = doevery;
806                 }
807                 else
808                     tmp = 1;
809                 s++;
810             }
811             break;
812         case SPACELUTF8:
813             PL_reg_flags |= RF_tainted;
814             while (s < strend) {
815                 if (*s == ' ' || isSPACE_LC_utf8((U8*)s)) {
816                     if (tmp && regtry(prog, s))
817                         goto got_it;
818                     else
819                         tmp = doevery;
820                 }
821                 else
822                     tmp = 1;
823                 s += UTF8SKIP(s);
824             }
825             break;
826         case NSPACE:
827             while (s < strend) {
828                 if (!isSPACE(*s)) {
829                     if (tmp && regtry(prog, s))
830                         goto got_it;
831                     else
832                         tmp = doevery;
833                 }
834                 else
835                     tmp = 1;
836                 s++;
837             }
838             break;
839         case NSPACEUTF8:
840             while (s < strend) {
841                 if (!(*s == ' ' || swash_fetch(PL_utf8_space,(U8*)s))) {
842                     if (tmp && regtry(prog, s))
843                         goto got_it;
844                     else
845                         tmp = doevery;
846                 }
847                 else
848                     tmp = 1;
849                 s += UTF8SKIP(s);
850             }
851             break;
852         case NSPACEL:
853             PL_reg_flags |= RF_tainted;
854             while (s < strend) {
855                 if (!isSPACE_LC(*s)) {
856                     if (tmp && regtry(prog, s))
857                         goto got_it;
858                     else
859                         tmp = doevery;
860                 }
861                 else
862                     tmp = 1;
863                 s++;
864             }
865             break;
866         case NSPACELUTF8:
867             PL_reg_flags |= RF_tainted;
868             while (s < strend) {
869                 if (!(*s == ' ' || isSPACE_LC_utf8((U8*)s))) {
870                     if (tmp && regtry(prog, s))
871                         goto got_it;
872                     else
873                         tmp = doevery;
874                 }
875                 else
876                     tmp = 1;
877                 s += UTF8SKIP(s);
878             }
879             break;
880         case DIGIT:
881             while (s < strend) {
882                 if (isDIGIT(*s)) {
883                     if (tmp && regtry(prog, s))
884                         goto got_it;
885                     else
886                         tmp = doevery;
887                 }
888                 else
889                     tmp = 1;
890                 s++;
891             }
892             break;
893         case DIGITUTF8:
894             while (s < strend) {
895                 if (swash_fetch(PL_utf8_digit,(U8*)s)) {
896                     if (tmp && regtry(prog, s))
897                         goto got_it;
898                     else
899                         tmp = doevery;
900                 }
901                 else
902                     tmp = 1;
903                 s += UTF8SKIP(s);
904             }
905             break;
906         case NDIGIT:
907             while (s < strend) {
908                 if (!isDIGIT(*s)) {
909                     if (tmp && regtry(prog, s))
910                         goto got_it;
911                     else
912                         tmp = doevery;
913                 }
914                 else
915                     tmp = 1;
916                 s++;
917             }
918             break;
919         case NDIGITUTF8:
920             while (s < strend) {
921                 if (!swash_fetch(PL_utf8_digit,(U8*)s)) {
922                     if (tmp && regtry(prog, s))
923                         goto got_it;
924                     else
925                         tmp = doevery;
926                 }
927                 else
928                     tmp = 1;
929                 s += UTF8SKIP(s);
930             }
931             break;
932         }
933     }
934     else {
935         dontbother = 0;
936         if (prog->float_substr != Nullsv) {     /* Trim the end. */
937             char *last;
938             I32 oldpos = scream_pos;
939
940             if (flags & REXEC_SCREAM) {
941                 last = screaminstr(sv, prog->float_substr, s - strbeg,
942                                    end_shift, &scream_pos, 1); /* last one */
943                 if (!last) {
944                     last = scream_olds; /* Only one occurence. */
945                 }
946             }
947             else {
948                 STRLEN len;
949                 char *little = SvPV(prog->float_substr, len);
950                 if (len) 
951                     last = rninstr(s, strend, little, little + len);
952                 else
953                     last = strend;      /* matching `$' */
954             }
955             if (last == NULL) goto phooey; /* Should not happen! */
956             dontbother = strend - last + prog->float_min_offset;
957         }
958         if (minlen && (dontbother < minlen))
959             dontbother = minlen - 1;
960         strend -= dontbother;              /* this one's always in bytes! */
961         /* We don't know much -- general case. */
962         if (UTF) {
963             for (;;) {
964                 if (regtry(prog, s))
965                     goto got_it;
966                 if (s >= strend)
967                     break;
968                 s += UTF8SKIP(s);
969             };
970         }
971         else {
972             do {
973                 if (regtry(prog, s))
974                     goto got_it;
975             } while (s++ < strend);
976         }
977     }
978
979     /* Failure. */
980     goto phooey;
981
982 got_it:
983     prog->subbeg = strbeg;
984     prog->subend = PL_regeol;   /* strend may have been modified */
985     RX_MATCH_TAINTED_set(prog, PL_reg_flags & RF_tainted);
986
987     /* make sure $`, $&, $', and $digit will work later */
988     if (strbeg != prog->subbase) {      /* second+ //g match.  */
989         if (!(flags & REXEC_COPY_STR)) {
990             if (prog->subbase) {
991                 Safefree(prog->subbase);
992                 prog->subbase = Nullch;
993             }
994         }
995         else {
996             I32 i = PL_regeol - startpos + (stringarg - strbeg);
997             s = savepvn(strbeg, i);
998             Safefree(prog->subbase);
999             prog->subbase = s;
1000             prog->subbeg = prog->subbase;
1001             prog->subend = prog->subbase + i;
1002             s = prog->subbase + (stringarg - strbeg);
1003             for (i = 0; i <= prog->nparens; i++) {
1004                 if (prog->endp[i]) {
1005                     prog->startp[i] = s + (prog->startp[i] - startpos);
1006                     prog->endp[i] = s + (prog->endp[i] - startpos);
1007                 }
1008             }
1009         }
1010     }
1011     /* Preserve the current value of $^R */
1012     if (oreplsv != GvSV(PL_replgv)) {
1013         sv_setsv(oreplsv, GvSV(PL_replgv));/* So that when GvSV(replgv) is
1014                                            restored, the value remains
1015                                            the same. */
1016     }
1017     if (PL_reg_eval_set)
1018         restore_pos(0);
1019     return 1;
1020
1021 phooey:
1022     if (PL_reg_eval_set)
1023         restore_pos(0);
1024     return 0;
1025 }
1026
1027 /*
1028  - regtry - try match at specific point
1029  */
1030 STATIC I32                      /* 0 failure, 1 success */
1031 regtry(regexp *prog, char *startpos)
1032 {
1033     dTHR;
1034     register I32 i;
1035     register char **sp;
1036     register char **ep;
1037     CHECKPOINT lastcp;
1038
1039     if ((prog->reganch & ROPT_EVAL_SEEN) && !PL_reg_eval_set) {
1040         MAGIC *mg;
1041
1042         PL_reg_eval_set = RS_init;
1043         DEBUG_r(DEBUG_s(
1044             PerlIO_printf(Perl_debug_log, "  setting stack tmpbase at %i\n",
1045                           PL_stack_sp - PL_stack_base);
1046             ));
1047         SAVEINT(cxstack[cxstack_ix].blk_oldsp);
1048         cxstack[cxstack_ix].blk_oldsp = PL_stack_sp - PL_stack_base;
1049         /* Otherwise OP_NEXTSTATE will free whatever on stack now.  */
1050         SAVETMPS;
1051         /* Apparently this is not needed, judging by wantarray. */
1052         /* SAVEINT(cxstack[cxstack_ix].blk_gimme);
1053            cxstack[cxstack_ix].blk_gimme = G_SCALAR; */
1054
1055         if (PL_reg_sv) {
1056             /* Make $_ available to executed code. */
1057             if (PL_reg_sv != GvSV(PL_defgv)) {
1058                 SAVESPTR(GvSV(PL_defgv));
1059                 GvSV(PL_defgv) = PL_reg_sv;
1060             }
1061         
1062             if (!(SvTYPE(PL_reg_sv) >= SVt_PVMG && SvMAGIC(PL_reg_sv) 
1063                   && (mg = mg_find(PL_reg_sv, 'g')))) {
1064                 /* prepare for quick setting of pos */
1065                 sv_magic(PL_reg_sv, (SV*)0, 'g', Nullch, 0);
1066                 mg = mg_find(PL_reg_sv, 'g');
1067                 mg->mg_len = -1;
1068             }
1069             PL_reg_magic    = mg;
1070             PL_reg_oldpos   = mg->mg_len;
1071             SAVEDESTRUCTOR(restore_pos, 0);
1072         }
1073     }
1074     PL_reginput = startpos;
1075     PL_regstartp = prog->startp;
1076     PL_regendp = prog->endp;
1077     PL_reglastparen = &prog->lastparen;
1078     prog->lastparen = 0;
1079     PL_regsize = 0;
1080     if (PL_reg_start_tmpl <= prog->nparens) {
1081         PL_reg_start_tmpl = prog->nparens*3/2 + 3;
1082         if(PL_reg_start_tmp)
1083             Renew(PL_reg_start_tmp, PL_reg_start_tmpl, char*);
1084         else
1085             New(22,PL_reg_start_tmp, PL_reg_start_tmpl, char*);
1086     }
1087
1088     sp = prog->startp;
1089     ep = prog->endp;
1090     if (prog->nparens) {
1091         for (i = prog->nparens; i >= 0; i--) {
1092             *sp++ = NULL;
1093             *ep++ = NULL;
1094         }
1095     }
1096     REGCP_SET;
1097     if (regmatch(prog->program + 1)) {
1098         prog->startp[0] = startpos;
1099         prog->endp[0] = PL_reginput;
1100         return 1;
1101     }
1102     REGCP_UNWIND;
1103     return 0;
1104 }
1105
1106 /*
1107  - regmatch - main matching routine
1108  *
1109  * Conceptually the strategy is simple:  check to see whether the current
1110  * node matches, call self recursively to see whether the rest matches,
1111  * and then act accordingly.  In practice we make some effort to avoid
1112  * recursion, in particular by going through "ordinary" nodes (that don't
1113  * need to know whether the rest of the match failed) by a loop instead of
1114  * by recursion.
1115  */
1116 /* [lwall] I've hoisted the register declarations to the outer block in order to
1117  * maybe save a little bit of pushing and popping on the stack.  It also takes
1118  * advantage of machines that use a register save mask on subroutine entry.
1119  */
1120 STATIC I32                      /* 0 failure, 1 success */
1121 regmatch(regnode *prog)
1122 {
1123     dTHR;
1124     register regnode *scan;     /* Current node. */
1125     regnode *next;              /* Next node. */
1126     regnode *inner;             /* Next node in internal branch. */
1127     register I32 nextchr;       /* renamed nextchr - nextchar colides with
1128                                    function of same name */
1129     register I32 n;             /* no or next */
1130     register I32 ln;            /* len or last */
1131     register char *s;           /* operand or save */
1132     register char *locinput = PL_reginput;
1133     register I32 c1, c2, paren; /* case fold search, parenth */
1134     int minmod = 0, sw = 0, logical = 0;
1135 #ifdef DEBUGGING
1136     PL_regindent++;
1137 #endif
1138
1139     /* Note that nextchr is a byte even in UTF */
1140     nextchr = UCHARAT(locinput);
1141     scan = prog;
1142     while (scan != NULL) {
1143 #define sayNO_L (logical ? (logical = 0, sw = 0, goto cont) : sayNO)
1144 #ifdef DEBUGGING
1145 #  define sayYES goto yes
1146 #  define sayNO goto no
1147 #  define saySAME(x) if (x) goto yes; else goto no
1148 #  define REPORT_CODE_OFF 24
1149 #else
1150 #  define sayYES return 1
1151 #  define sayNO return 0
1152 #  define saySAME(x) return x
1153 #endif
1154         DEBUG_r( {
1155             SV *prop = sv_newmortal();
1156             int docolor = *PL_colors[0];
1157             int taill = (docolor ? 10 : 7); /* 3 chars for "> <" */
1158             int l = (PL_regeol - locinput > taill ? taill : PL_regeol - locinput);
1159             int pref_len = (locinput - PL_bostr > (5 + taill) - l 
1160                             ? (5 + taill) - l : locinput - PL_bostr);
1161             int pref0_len = pref_len  - (locinput - PL_reginput);
1162
1163             if (l + pref_len < (5 + taill) && l < PL_regeol - locinput)
1164                 l = ( PL_regeol - locinput > (5 + taill) - pref_len 
1165                       ? (5 + taill) - pref_len : PL_regeol - locinput);
1166             if (pref0_len < 0)
1167                 pref0_len = 0;
1168             regprop(prop, scan);
1169             PerlIO_printf(Perl_debug_log, 
1170                           "%4i <%s%.*s%s%s%.*s%s%s%s%.*s%s>%*s|%3d:%*s%s\n",
1171                           locinput - PL_bostr, 
1172                           PL_colors[4], pref0_len, 
1173                           locinput - pref_len, PL_colors[5],
1174                           PL_colors[2], pref_len - pref0_len, 
1175                           locinput - pref_len + pref0_len, PL_colors[3],
1176                           (docolor ? "" : "> <"),
1177                           PL_colors[0], l, locinput, PL_colors[1],
1178                           15 - l - pref_len + 1,
1179                           "",
1180                           scan - PL_regprogram, PL_regindent*2, "",
1181                           SvPVX(prop));
1182         } );
1183
1184         next = scan + NEXT_OFF(scan);
1185         if (next == scan)
1186             next = NULL;
1187
1188         switch (OP(scan)) {
1189         case BOL:
1190             if (locinput == PL_bostr
1191                 ? PL_regprev == '\n'
1192                 : (PL_multiline && 
1193                    (nextchr || locinput < PL_regeol) && locinput[-1] == '\n') )
1194             {
1195                 /* regtill = regbol; */
1196                 break;
1197             }
1198             sayNO;
1199         case MBOL:
1200             if (locinput == PL_bostr
1201                 ? PL_regprev == '\n'
1202                 : ((nextchr || locinput < PL_regeol) && locinput[-1] == '\n') )
1203             {
1204                 break;
1205             }
1206             sayNO;
1207         case SBOL:
1208             if (locinput == PL_regbol && PL_regprev == '\n')
1209                 break;
1210             sayNO;
1211         case GPOS:
1212             if (locinput == PL_reg_ganch)
1213                 break;
1214             sayNO;
1215         case EOL:
1216             if (PL_multiline)
1217                 goto meol;
1218             else
1219                 goto seol;
1220         case MEOL:
1221           meol:
1222             if ((nextchr || locinput < PL_regeol) && nextchr != '\n')
1223                 sayNO;
1224             break;
1225         case SEOL:
1226           seol:
1227             if ((nextchr || locinput < PL_regeol) && nextchr != '\n')
1228                 sayNO;
1229             if (PL_regeol - locinput > 1)
1230                 sayNO;
1231             break;
1232         case EOS:
1233             if (PL_regeol != locinput)
1234                 sayNO;
1235             break;
1236         case SANYUTF8:
1237             if (nextchr & 0x80) {
1238                 locinput += PL_utf8skip[nextchr];
1239                 if (locinput > PL_regeol)
1240                     sayNO;
1241                 nextchr = UCHARAT(locinput);
1242                 break;
1243             }
1244             if (!nextchr && locinput >= PL_regeol)
1245                 sayNO;
1246             nextchr = UCHARAT(++locinput);
1247             break;
1248         case SANY:
1249             if (!nextchr && locinput >= PL_regeol)
1250                 sayNO;
1251             nextchr = UCHARAT(++locinput);
1252             break;
1253         case ANYUTF8:
1254             if (nextchr & 0x80) {
1255                 locinput += PL_utf8skip[nextchr];
1256                 if (locinput > PL_regeol)
1257                     sayNO;
1258                 nextchr = UCHARAT(locinput);
1259                 break;
1260             }
1261             if (!nextchr && locinput >= PL_regeol || nextchr == '\n')
1262                 sayNO;
1263             nextchr = UCHARAT(++locinput);
1264             break;
1265         case REG_ANY:
1266             if (!nextchr && locinput >= PL_regeol || nextchr == '\n')
1267                 sayNO;
1268             nextchr = UCHARAT(++locinput);
1269             break;
1270         case EXACT:
1271             s = (char *) OPERAND(scan);
1272             ln = UCHARAT(s++);
1273             /* Inline the first character, for speed. */
1274             if (UCHARAT(s) != nextchr)
1275                 sayNO;
1276             if (PL_regeol - locinput < ln)
1277                 sayNO;
1278             if (ln > 1 && memNE(s, locinput, ln))
1279                 sayNO;
1280             locinput += ln;
1281             nextchr = UCHARAT(locinput);
1282             break;
1283         case EXACTFL:
1284             PL_reg_flags |= RF_tainted;
1285             /* FALL THROUGH */
1286         case EXACTF:
1287             s = (char *) OPERAND(scan);
1288             ln = UCHARAT(s++);
1289
1290             if (UTF) {
1291                 char *l = locinput;
1292                 char *e = s + ln;
1293                 c1 = OP(scan) == EXACTF;
1294                 while (s < e) {
1295                     if (l >= PL_regeol)
1296                         sayNO;
1297                     if (utf8_to_uv((U8*)s, 0) != (c1 ?
1298                                                   toLOWER_utf8((U8*)l) :
1299                                                   toLOWER_LC_utf8((U8*)l)))
1300                     {
1301                         sayNO;
1302                     }
1303                     s += UTF8SKIP(s);
1304                     l += UTF8SKIP(l);
1305                 }
1306                 locinput = l;
1307                 nextchr = UCHARAT(locinput);
1308                 break;
1309             }
1310
1311             /* Inline the first character, for speed. */
1312             if (UCHARAT(s) != nextchr &&
1313                 UCHARAT(s) != ((OP(scan) == EXACTF)
1314                                ? PL_fold : PL_fold_locale)[nextchr])
1315                 sayNO;
1316             if (PL_regeol - locinput < ln)
1317                 sayNO;
1318             if (ln > 1 && (OP(scan) == EXACTF
1319                            ? ibcmp(s, locinput, ln)
1320                            : ibcmp_locale(s, locinput, ln)))
1321                 sayNO;
1322             locinput += ln;
1323             nextchr = UCHARAT(locinput);
1324             break;
1325         case ANYOFUTF8:
1326             s = (char *) OPERAND(scan);
1327             if (!REGINCLASSUTF8(scan, (U8*)locinput))
1328                 sayNO;
1329             if (locinput >= PL_regeol)
1330                 sayNO;
1331             locinput += PL_utf8skip[nextchr];
1332             nextchr = UCHARAT(locinput);
1333             break;
1334         case ANYOF:
1335             s = (char *) OPERAND(scan);
1336             if (nextchr < 0)
1337                 nextchr = UCHARAT(locinput);
1338             if (!REGINCLASS(s, nextchr))
1339                 sayNO;
1340             if (!nextchr && locinput >= PL_regeol)
1341                 sayNO;
1342             nextchr = UCHARAT(++locinput);
1343             break;
1344         case ALNUML:
1345             PL_reg_flags |= RF_tainted;
1346             /* FALL THROUGH */
1347         case ALNUM:
1348             if (!nextchr)
1349                 sayNO;
1350             if (!(OP(scan) == ALNUM
1351                   ? isALNUM(nextchr) : isALNUM_LC(nextchr)))
1352                 sayNO;
1353             nextchr = UCHARAT(++locinput);
1354             break;
1355         case ALNUMLUTF8:
1356             PL_reg_flags |= RF_tainted;
1357             /* FALL THROUGH */
1358         case ALNUMUTF8:
1359             if (!nextchr)
1360                 sayNO;
1361             if (nextchr & 0x80) {
1362                 if (!(OP(scan) == ALNUMUTF8
1363                       ? swash_fetch(PL_utf8_alnum, (U8*)locinput)
1364                       : isALNUM_LC_utf8((U8*)locinput)))
1365                 {
1366                     sayNO;
1367                 }
1368                 locinput += PL_utf8skip[nextchr];
1369                 nextchr = UCHARAT(locinput);
1370                 break;
1371             }
1372             if (!(OP(scan) == ALNUMUTF8
1373                   ? isALNUM(nextchr) : isALNUM_LC(nextchr)))
1374                 sayNO;
1375             nextchr = UCHARAT(++locinput);
1376             break;
1377         case NALNUML:
1378             PL_reg_flags |= RF_tainted;
1379             /* FALL THROUGH */
1380         case NALNUM:
1381             if (!nextchr && locinput >= PL_regeol)
1382                 sayNO;
1383             if (OP(scan) == NALNUM
1384                 ? isALNUM(nextchr) : isALNUM_LC(nextchr))
1385                 sayNO;
1386             nextchr = UCHARAT(++locinput);
1387             break;
1388         case NALNUMLUTF8:
1389             PL_reg_flags |= RF_tainted;
1390             /* FALL THROUGH */
1391         case NALNUMUTF8:
1392             if (!nextchr && locinput >= PL_regeol)
1393                 sayNO;
1394             if (nextchr & 0x80) {
1395                 if (OP(scan) == NALNUMUTF8
1396                     ? swash_fetch(PL_utf8_alnum, (U8*)locinput)
1397                     : isALNUM_LC_utf8((U8*)locinput))
1398                 {
1399                     sayNO;
1400                 }
1401                 locinput += PL_utf8skip[nextchr];
1402                 nextchr = UCHARAT(locinput);
1403                 break;
1404             }
1405             if (OP(scan) == NALNUMUTF8
1406                 ? isALNUM(nextchr) : isALNUM_LC(nextchr))
1407                 sayNO;
1408             nextchr = UCHARAT(++locinput);
1409             break;
1410         case BOUNDL:
1411         case NBOUNDL:
1412             PL_reg_flags |= RF_tainted;
1413             /* FALL THROUGH */
1414         case BOUND:
1415         case NBOUND:
1416             /* was last char in word? */
1417             ln = (locinput != PL_regbol) ? UCHARAT(locinput - 1) : PL_regprev;
1418             if (OP(scan) == BOUND || OP(scan) == NBOUND) {
1419                 ln = isALNUM(ln);
1420                 n = isALNUM(nextchr);
1421             }
1422             else {
1423                 ln = isALNUM_LC(ln);
1424                 n = isALNUM_LC(nextchr);
1425             }
1426             if (((!ln) == (!n)) == (OP(scan) == BOUND || OP(scan) == BOUNDL))
1427                 sayNO;
1428             break;
1429         case BOUNDLUTF8:
1430         case NBOUNDLUTF8:
1431             PL_reg_flags |= RF_tainted;
1432             /* FALL THROUGH */
1433         case BOUNDUTF8:
1434         case NBOUNDUTF8:
1435             /* was last char in word? */
1436             ln = (locinput != PL_regbol)
1437                 ? utf8_to_uv(reghop((U8*)locinput, -1), 0) : PL_regprev;
1438             if (OP(scan) == BOUNDUTF8 || OP(scan) == NBOUNDUTF8) {
1439                 ln = isALNUM_uni(ln);
1440                 n = swash_fetch(PL_utf8_alnum, (U8*)locinput);
1441             }
1442             else {
1443                 ln = isALNUM_LC_uni(ln);
1444                 n = isALNUM_LC_utf8((U8*)locinput);
1445             }
1446             if (((!ln) == (!n)) == (OP(scan) == BOUNDUTF8 || OP(scan) == BOUNDLUTF8))
1447                 sayNO;
1448             break;
1449         case SPACEL:
1450             PL_reg_flags |= RF_tainted;
1451             /* FALL THROUGH */
1452         case SPACE:
1453             if (!nextchr && locinput >= PL_regeol)
1454                 sayNO;
1455             if (!(OP(scan) == SPACE
1456                   ? isSPACE(nextchr) : isSPACE_LC(nextchr)))
1457                 sayNO;
1458             nextchr = UCHARAT(++locinput);
1459             break;
1460         case SPACELUTF8:
1461             PL_reg_flags |= RF_tainted;
1462             /* FALL THROUGH */
1463         case SPACEUTF8:
1464             if (!nextchr && locinput >= PL_regeol)
1465                 sayNO;
1466             if (nextchr & 0x80) {
1467                 if (!(OP(scan) == SPACEUTF8
1468                       ? swash_fetch(PL_utf8_space,(U8*)locinput)
1469                       : isSPACE_LC_utf8((U8*)locinput)))
1470                 {
1471                     sayNO;
1472                 }
1473                 locinput += PL_utf8skip[nextchr];
1474                 nextchr = UCHARAT(locinput);
1475                 break;
1476             }
1477             if (!(OP(scan) == SPACEUTF8
1478                   ? isSPACE(nextchr) : isSPACE_LC(nextchr)))
1479                 sayNO;
1480             nextchr = UCHARAT(++locinput);
1481             break;
1482         case NSPACEL:
1483             PL_reg_flags |= RF_tainted;
1484             /* FALL THROUGH */
1485         case NSPACE:
1486             if (!nextchr)
1487                 sayNO;
1488             if (OP(scan) == SPACE
1489                 ? isSPACE(nextchr) : isSPACE_LC(nextchr))
1490                 sayNO;
1491             nextchr = UCHARAT(++locinput);
1492             break;
1493         case NSPACELUTF8:
1494             PL_reg_flags |= RF_tainted;
1495             /* FALL THROUGH */
1496         case NSPACEUTF8:
1497             if (!nextchr)
1498                 sayNO;
1499             if (nextchr & 0x80) {
1500                 if (OP(scan) == NSPACEUTF8
1501                     ? swash_fetch(PL_utf8_space,(U8*)locinput)
1502                     : isSPACE_LC_utf8((U8*)locinput))
1503                 {
1504                     sayNO;
1505                 }
1506                 locinput += PL_utf8skip[nextchr];
1507                 nextchr = UCHARAT(locinput);
1508                 break;
1509             }
1510             if (OP(scan) == NSPACEUTF8
1511                 ? isSPACE(nextchr) : isSPACE_LC(nextchr))
1512                 sayNO;
1513             nextchr = UCHARAT(++locinput);
1514             break;
1515         case DIGIT:
1516             if (!isDIGIT(nextchr))
1517                 sayNO;
1518             nextchr = UCHARAT(++locinput);
1519             break;
1520         case DIGITUTF8:
1521             if (nextchr & 0x80) {
1522                 if (!(swash_fetch(PL_utf8_digit,(U8*)locinput)))
1523                     sayNO;
1524                 locinput += PL_utf8skip[nextchr];
1525                 nextchr = UCHARAT(locinput);
1526                 break;
1527             }
1528             if (!isDIGIT(nextchr))
1529                 sayNO;
1530             nextchr = UCHARAT(++locinput);
1531             break;
1532         case NDIGIT:
1533             if (!nextchr && locinput >= PL_regeol)
1534                 sayNO;
1535             if (isDIGIT(nextchr))
1536                 sayNO;
1537             nextchr = UCHARAT(++locinput);
1538             break;
1539         case NDIGITUTF8:
1540             if (!nextchr && locinput >= PL_regeol)
1541                 sayNO;
1542             if (nextchr & 0x80) {
1543                 if (swash_fetch(PL_utf8_digit,(U8*)locinput))
1544                     sayNO;
1545                 locinput += PL_utf8skip[nextchr];
1546                 nextchr = UCHARAT(locinput);
1547                 break;
1548             }
1549             if (isDIGIT(nextchr))
1550                 sayNO;
1551             nextchr = UCHARAT(++locinput);
1552             break;
1553         case CLUMP:
1554             if (locinput >= PL_regeol || swash_fetch(PL_utf8_mark,(U8*)locinput))
1555                 sayNO;
1556             locinput += PL_utf8skip[nextchr];
1557             while (locinput < PL_regeol && swash_fetch(PL_utf8_mark,(U8*)locinput))
1558                 locinput += UTF8SKIP(locinput);
1559             if (locinput > PL_regeol)
1560                 sayNO;
1561             nextchr = UCHARAT(locinput);
1562             break;
1563         case REFFL:
1564             PL_reg_flags |= RF_tainted;
1565             /* FALL THROUGH */
1566         case REF:
1567         case REFF:
1568             n = ARG(scan);  /* which paren pair */
1569             s = PL_regstartp[n];
1570             if (*PL_reglastparen < n || !s)
1571                 sayNO;                  /* Do not match unless seen CLOSEn. */
1572             if (s == PL_regendp[n])
1573                 break;
1574
1575             if (UTF && OP(scan) != REF) {       /* REF can do byte comparison */
1576                 char *l = locinput;
1577                 char *e = PL_regendp[n];
1578                 /*
1579                  * Note that we can't do the "other character" lookup trick as
1580                  * in the 8-bit case (no pun intended) because in Unicode we
1581                  * have to map both upper and title case to lower case.
1582                  */
1583                 if (OP(scan) == REFF) {
1584                     while (s < e) {
1585                         if (l >= PL_regeol)
1586                             sayNO;
1587                         if (toLOWER_utf8((U8*)s) != toLOWER_utf8((U8*)l))
1588                             sayNO;
1589                         s += UTF8SKIP(s);
1590                         l += UTF8SKIP(l);
1591                     }
1592                 }
1593                 else {
1594                     while (s < e) {
1595                         if (l >= PL_regeol)
1596                             sayNO;
1597                         if (toLOWER_LC_utf8((U8*)s) != toLOWER_LC_utf8((U8*)l))
1598                             sayNO;
1599                         s += UTF8SKIP(s);
1600                         l += UTF8SKIP(l);
1601                     }
1602                 }
1603                 locinput = l;
1604                 nextchr = UCHARAT(locinput);
1605                 break;
1606             }
1607
1608             /* Inline the first character, for speed. */
1609             if (UCHARAT(s) != nextchr &&
1610                 (OP(scan) == REF ||
1611                  (UCHARAT(s) != ((OP(scan) == REFF
1612                                   ? PL_fold : PL_fold_locale)[nextchr]))))
1613                 sayNO;
1614             ln = PL_regendp[n] - s;
1615             if (locinput + ln > PL_regeol)
1616                 sayNO;
1617             if (ln > 1 && (OP(scan) == REF
1618                            ? memNE(s, locinput, ln)
1619                            : (OP(scan) == REFF
1620                               ? ibcmp(s, locinput, ln)
1621                               : ibcmp_locale(s, locinput, ln))))
1622                 sayNO;
1623             locinput += ln;
1624             nextchr = UCHARAT(locinput);
1625             break;
1626
1627         case NOTHING:
1628         case TAIL:
1629             break;
1630         case BACK:
1631             break;
1632         case EVAL:
1633         {
1634             dSP;
1635             OP_4tree *oop = PL_op;
1636             COP *ocurcop = PL_curcop;
1637             SV **ocurpad = PL_curpad;
1638             SV *ret;
1639             
1640             n = ARG(scan);
1641             PL_op = (OP_4tree*)PL_regdata->data[n];
1642             DEBUG_r( PerlIO_printf(Perl_debug_log, "  re_eval 0x%x\n", PL_op) );
1643             PL_curpad = AvARRAY((AV*)PL_regdata->data[n + 1]);
1644             PL_reg_magic->mg_len = locinput - PL_bostr;
1645
1646             CALLRUNOPS();                       /* Scalar context. */
1647             SPAGAIN;
1648             ret = POPs;
1649             PUTBACK;
1650             
1651             PL_op = oop;
1652             PL_curpad = ocurpad;
1653             PL_curcop = ocurcop;
1654             if (logical) {
1655                 if (logical == 2) {     /* Postponed subexpression. */
1656                     regexp *re;
1657                     MAGIC *mg = Null(MAGIC*);
1658                     re_cc_state state;
1659                     CURCUR cctmp;
1660                     CHECKPOINT cp, lastcp;
1661
1662                     if(SvROK(ret) || SvRMAGICAL(ret)) {
1663                         SV *sv = SvROK(ret) ? SvRV(ret) : ret;
1664
1665                         if(SvMAGICAL(sv))
1666                             mg = mg_find(sv, 'r');
1667                     }
1668                     if (mg) {
1669                         re = (regexp *)mg->mg_obj;
1670                         (void)ReREFCNT_inc(re);
1671                     }
1672                     else {
1673                         STRLEN len;
1674                         char *t = SvPV(ret, len);
1675                         PMOP pm;
1676                         char *oprecomp = PL_regprecomp;
1677                         I32 osize = PL_regsize;
1678                         I32 onpar = PL_regnpar;
1679
1680                         pm.op_pmflags = 0;
1681                         re = CALLREGCOMP(t, t + len, &pm);
1682                         if (!(SvFLAGS(ret) 
1683                               & (SVs_TEMP | SVs_PADTMP | SVf_READONLY)))
1684                             sv_magic(ret,(SV*)ReREFCNT_inc(re),'r',0,0);
1685                         PL_regprecomp = oprecomp;
1686                         PL_regsize = osize;
1687                         PL_regnpar = onpar;
1688                     }
1689                     DEBUG_r(
1690                         PerlIO_printf(Perl_debug_log, 
1691                                       "Entering embedded `%s%.60s%s%s'\n",
1692                                       PL_colors[0],
1693                                       re->precomp,
1694                                       PL_colors[1],
1695                                       (strlen(re->precomp) > 60 ? "..." : ""))
1696                         );
1697                     state.node = next;
1698                     state.prev = PL_reg_call_cc;
1699                     state.cc = PL_regcc;
1700                     state.re = PL_reg_re;
1701
1702                     cctmp.cur = 0;
1703                     cctmp.oldcc = 0;
1704                     PL_regcc = &cctmp;
1705                     
1706                     cp = regcppush(0);  /* Save *all* the positions. */
1707                     REGCP_SET;
1708                     cache_re(re);
1709                     state.ss = PL_savestack_ix;
1710                     *PL_reglastparen = 0;
1711                     PL_reg_call_cc = &state;
1712                     PL_reginput = locinput;
1713                     if (regmatch(re->program + 1)) {
1714                         ReREFCNT_dec(re);
1715                         regcpblow(cp);
1716                         sayYES;
1717                     }
1718                     DEBUG_r(
1719                         PerlIO_printf(Perl_debug_log,
1720                                       "%*s  failed...\n",
1721                                       REPORT_CODE_OFF+PL_regindent*2, "")
1722                         );
1723                     ReREFCNT_dec(re);
1724                     REGCP_UNWIND;
1725                     regcppop();
1726                     PL_reg_call_cc = state.prev;
1727                     PL_regcc = state.cc;
1728                     PL_reg_re = state.re;
1729                     cache_re(PL_reg_re);
1730                     sayNO;
1731                 }
1732                 sw = SvTRUE(ret);
1733                 logical = 0;
1734             }
1735             else
1736                 sv_setsv(save_scalar(PL_replgv), ret);
1737             break;
1738         }
1739         case OPEN:
1740             n = ARG(scan);  /* which paren pair */
1741             PL_reg_start_tmp[n] = locinput;
1742             if (n > PL_regsize)
1743                 PL_regsize = n;
1744             break;
1745         case CLOSE:
1746             n = ARG(scan);  /* which paren pair */
1747             PL_regstartp[n] = PL_reg_start_tmp[n];
1748             PL_regendp[n] = locinput;
1749             if (n > *PL_reglastparen)
1750                 *PL_reglastparen = n;
1751             break;
1752         case GROUPP:
1753             n = ARG(scan);  /* which paren pair */
1754             sw = (*PL_reglastparen >= n && PL_regendp[n] != NULL);
1755             break;
1756         case IFTHEN:
1757             if (sw)
1758                 next = NEXTOPER(NEXTOPER(scan));
1759             else {
1760                 next = scan + ARG(scan);
1761                 if (OP(next) == IFTHEN) /* Fake one. */
1762                     next = NEXTOPER(NEXTOPER(next));
1763             }
1764             break;
1765         case LOGICAL:
1766             logical = scan->flags;
1767             break;
1768         case CURLYX: {
1769                 CURCUR cc;
1770                 CHECKPOINT cp = PL_savestack_ix;
1771
1772                 if (OP(PREVOPER(next)) == NOTHING) /* LONGJMP */
1773                     next += ARG(next);
1774                 cc.oldcc = PL_regcc;
1775                 PL_regcc = &cc;
1776                 cc.parenfloor = *PL_reglastparen;
1777                 cc.cur = -1;
1778                 cc.min = ARG1(scan);
1779                 cc.max  = ARG2(scan);
1780                 cc.scan = NEXTOPER(scan) + EXTRA_STEP_2ARGS;
1781                 cc.next = next;
1782                 cc.minmod = minmod;
1783                 cc.lastloc = 0;
1784                 PL_reginput = locinput;
1785                 n = regmatch(PREVOPER(next));   /* start on the WHILEM */
1786                 regcpblow(cp);
1787                 PL_regcc = cc.oldcc;
1788                 saySAME(n);
1789             }
1790             /* NOT REACHED */
1791         case WHILEM: {
1792                 /*
1793                  * This is really hard to understand, because after we match
1794                  * what we're trying to match, we must make sure the rest of
1795                  * the RE is going to match for sure, and to do that we have
1796                  * to go back UP the parse tree by recursing ever deeper.  And
1797                  * if it fails, we have to reset our parent's current state
1798                  * that we can try again after backing off.
1799                  */
1800
1801                 CHECKPOINT cp, lastcp;
1802                 CURCUR* cc = PL_regcc;
1803                 char *lastloc = cc->lastloc; /* Detection of 0-len. */
1804                 
1805                 n = cc->cur + 1;        /* how many we know we matched */
1806                 PL_reginput = locinput;
1807
1808                 DEBUG_r(
1809                     PerlIO_printf(Perl_debug_log, 
1810                                   "%*s  %ld out of %ld..%ld  cc=%lx\n", 
1811                                   REPORT_CODE_OFF+PL_regindent*2, "",
1812                                   (long)n, (long)cc->min, 
1813                                   (long)cc->max, (long)cc)
1814                     );
1815
1816                 /* If degenerate scan matches "", assume scan done. */
1817
1818                 if (locinput == cc->lastloc && n >= cc->min) {
1819                     PL_regcc = cc->oldcc;
1820                     ln = PL_regcc->cur;
1821                     DEBUG_r(
1822                         PerlIO_printf(Perl_debug_log,
1823                            "%*s  empty match detected, try continuation...\n",
1824                            REPORT_CODE_OFF+PL_regindent*2, "")
1825                         );
1826                     if (regmatch(cc->next))
1827                         sayYES;
1828                     DEBUG_r(
1829                         PerlIO_printf(Perl_debug_log,
1830                                       "%*s  failed...\n",
1831                                       REPORT_CODE_OFF+PL_regindent*2, "")
1832                         );
1833                     PL_regcc->cur = ln;
1834                     PL_regcc = cc;
1835                     sayNO;
1836                 }
1837
1838                 /* First just match a string of min scans. */
1839
1840                 if (n < cc->min) {
1841                     cc->cur = n;
1842                     cc->lastloc = locinput;
1843                     if (regmatch(cc->scan))
1844                         sayYES;
1845                     cc->cur = n - 1;
1846                     cc->lastloc = lastloc;
1847                     DEBUG_r(
1848                         PerlIO_printf(Perl_debug_log,
1849                                       "%*s  failed...\n",
1850                                       REPORT_CODE_OFF+PL_regindent*2, "")
1851                         );
1852                     sayNO;
1853                 }
1854
1855                 /* Prefer next over scan for minimal matching. */
1856
1857                 if (cc->minmod) {
1858                     PL_regcc = cc->oldcc;
1859                     ln = PL_regcc->cur;
1860                     cp = regcppush(cc->parenfloor);
1861                     REGCP_SET;
1862                     if (regmatch(cc->next)) {
1863                         regcpblow(cp);
1864                         sayYES; /* All done. */
1865                     }
1866                     REGCP_UNWIND;
1867                     regcppop();
1868                     PL_regcc->cur = ln;
1869                     PL_regcc = cc;
1870
1871                     if (n >= cc->max) { /* Maximum greed exceeded? */
1872                         if (ckWARN(WARN_UNSAFE) && n >= REG_INFTY 
1873                             && !(PL_reg_flags & RF_warned)) {
1874                             PL_reg_flags |= RF_warned;
1875                             warner(WARN_UNSAFE, "%s limit (%d) exceeded",
1876                                  "Complex regular subexpression recursion",
1877                                  REG_INFTY - 1);
1878                         }
1879                         sayNO;
1880                     }
1881
1882                     DEBUG_r(
1883                         PerlIO_printf(Perl_debug_log,
1884                                       "%*s  trying longer...\n",
1885                                       REPORT_CODE_OFF+PL_regindent*2, "")
1886                         );
1887                     /* Try scanning more and see if it helps. */
1888                     PL_reginput = locinput;
1889                     cc->cur = n;
1890                     cc->lastloc = locinput;
1891                     cp = regcppush(cc->parenfloor);
1892                     REGCP_SET;
1893                     if (regmatch(cc->scan)) {
1894                         regcpblow(cp);
1895                         sayYES;
1896                     }
1897                     DEBUG_r(
1898                         PerlIO_printf(Perl_debug_log,
1899                                       "%*s  failed...\n",
1900                                       REPORT_CODE_OFF+PL_regindent*2, "")
1901                         );
1902                     REGCP_UNWIND;
1903                     regcppop();
1904                     cc->cur = n - 1;
1905                     cc->lastloc = lastloc;
1906                     sayNO;
1907                 }
1908
1909                 /* Prefer scan over next for maximal matching. */
1910
1911                 if (n < cc->max) {      /* More greed allowed? */
1912                     cp = regcppush(cc->parenfloor);
1913                     cc->cur = n;
1914                     cc->lastloc = locinput;
1915                     REGCP_SET;
1916                     if (regmatch(cc->scan)) {
1917                         regcpblow(cp);
1918                         sayYES;
1919                     }
1920                     REGCP_UNWIND;
1921                     regcppop();         /* Restore some previous $<digit>s? */
1922                     PL_reginput = locinput;
1923                     DEBUG_r(
1924                         PerlIO_printf(Perl_debug_log,
1925                                       "%*s  failed, try continuation...\n",
1926                                       REPORT_CODE_OFF+PL_regindent*2, "")
1927                         );
1928                 }
1929                 if (ckWARN(WARN_UNSAFE) && n >= REG_INFTY 
1930                         && !(PL_reg_flags & RF_warned)) {
1931                     PL_reg_flags |= RF_warned;
1932                     warner(WARN_UNSAFE, "%s limit (%d) exceeded",
1933                          "Complex regular subexpression recursion",
1934                          REG_INFTY - 1);
1935                 }
1936
1937                 /* Failed deeper matches of scan, so see if this one works. */
1938                 PL_regcc = cc->oldcc;
1939                 ln = PL_regcc->cur;
1940                 if (regmatch(cc->next))
1941                     sayYES;
1942                 DEBUG_r(
1943                     PerlIO_printf(Perl_debug_log, "%*s  failed...\n",
1944                                   REPORT_CODE_OFF+PL_regindent*2, "")
1945                     );
1946                 PL_regcc->cur = ln;
1947                 PL_regcc = cc;
1948                 cc->cur = n - 1;
1949                 cc->lastloc = lastloc;
1950                 sayNO;
1951             }
1952             /* NOT REACHED */
1953         case BRANCHJ: 
1954             next = scan + ARG(scan);
1955             if (next == scan)
1956                 next = NULL;
1957             inner = NEXTOPER(NEXTOPER(scan));
1958             goto do_branch;
1959         case BRANCH: 
1960             inner = NEXTOPER(scan);
1961           do_branch:
1962             {
1963                 CHECKPOINT lastcp;
1964                 c1 = OP(scan);
1965                 if (OP(next) != c1)     /* No choice. */
1966                     next = inner;       /* Avoid recursion. */
1967                 else {
1968                     int lastparen = *PL_reglastparen;
1969
1970                     REGCP_SET;
1971                     do {
1972                         PL_reginput = locinput;
1973                         if (regmatch(inner))
1974                             sayYES;
1975                         REGCP_UNWIND;
1976                         for (n = *PL_reglastparen; n > lastparen; n--)
1977                             PL_regendp[n] = 0;
1978                         *PL_reglastparen = n;
1979                         scan = next;
1980                         /*SUPPRESS 560*/
1981                         if (n = (c1 == BRANCH ? NEXT_OFF(next) : ARG(next)))
1982                             next += n;
1983                         else
1984                             next = NULL;
1985                         inner = NEXTOPER(scan);
1986                         if (c1 == BRANCHJ) {
1987                             inner = NEXTOPER(inner);
1988                         }
1989                     } while (scan != NULL && OP(scan) == c1);
1990                     sayNO;
1991                     /* NOTREACHED */
1992                 }
1993             }
1994             break;
1995         case MINMOD:
1996             minmod = 1;
1997             break;
1998         case CURLYM:
1999         {
2000             I32 l = 0;
2001             CHECKPOINT lastcp;
2002             
2003             /* We suppose that the next guy does not need
2004                backtracking: in particular, it is of constant length,
2005                and has no parenths to influence future backrefs. */
2006             ln = ARG1(scan);  /* min to match */
2007             n  = ARG2(scan);  /* max to match */
2008             paren = scan->flags;
2009             if (paren) {
2010                 if (paren > PL_regsize)
2011                     PL_regsize = paren;
2012                 if (paren > *PL_reglastparen)
2013                     *PL_reglastparen = paren;
2014             }
2015             scan = NEXTOPER(scan) + NODE_STEP_REGNODE;
2016             if (paren)
2017                 scan += NEXT_OFF(scan); /* Skip former OPEN. */
2018             PL_reginput = locinput;
2019             if (minmod) {
2020                 minmod = 0;
2021                 if (ln && regrepeat_hard(scan, ln, &l) < ln)
2022                     sayNO;
2023                 if (ln && l == 0 && n >= ln
2024                     /* In fact, this is tricky.  If paren, then the
2025                        fact that we did/didnot match may influence
2026                        future execution. */
2027                     && !(paren && ln == 0))
2028                     ln = n;
2029                 locinput = PL_reginput;
2030                 if (PL_regkind[(U8)OP(next)] == EXACT) {
2031                     c1 = UCHARAT(OPERAND(next) + 1);
2032                     if (OP(next) == EXACTF)
2033                         c2 = PL_fold[c1];
2034                     else if (OP(next) == EXACTFL)
2035                         c2 = PL_fold_locale[c1];
2036                     else
2037                         c2 = c1;
2038                 }
2039                 else
2040                     c1 = c2 = -1000;
2041                 REGCP_SET;
2042                 /* This may be improved if l == 0.  */
2043                 while (n >= ln || (n == REG_INFTY && ln > 0 && l)) { /* ln overflow ? */
2044                     /* If it could work, try it. */
2045                     if (c1 == -1000 ||
2046                         UCHARAT(PL_reginput) == c1 ||
2047                         UCHARAT(PL_reginput) == c2)
2048                     {
2049                         if (paren) {
2050                             if (n) {
2051                                 PL_regstartp[paren] = HOPc(PL_reginput, -l);
2052                                 PL_regendp[paren] = PL_reginput;
2053                             }
2054                             else
2055                                 PL_regendp[paren] = NULL;
2056                         }
2057                         if (regmatch(next))
2058                             sayYES;
2059                         REGCP_UNWIND;
2060                     }
2061                     /* Couldn't or didn't -- move forward. */
2062                     PL_reginput = locinput;
2063                     if (regrepeat_hard(scan, 1, &l)) {
2064                         ln++;
2065                         locinput = PL_reginput;
2066                     }
2067                     else
2068                         sayNO;
2069                 }
2070             }
2071             else {
2072                 n = regrepeat_hard(scan, n, &l);
2073                 if (n != 0 && l == 0
2074                     /* In fact, this is tricky.  If paren, then the
2075                        fact that we did/didnot match may influence
2076                        future execution. */
2077                     && !(paren && ln == 0))
2078                     ln = n;
2079                 locinput = PL_reginput;
2080                 DEBUG_r(
2081                     PerlIO_printf(Perl_debug_log,
2082                                   "%*s  matched %ld times, len=%ld...\n",
2083                                   REPORT_CODE_OFF+PL_regindent*2, "", n, l)
2084                     );
2085                 if (n >= ln) {
2086                     if (PL_regkind[(U8)OP(next)] == EXACT) {
2087                         c1 = UCHARAT(OPERAND(next) + 1);
2088                         if (OP(next) == EXACTF)
2089                             c2 = PL_fold[c1];
2090                         else if (OP(next) == EXACTFL)
2091                             c2 = PL_fold_locale[c1];
2092                         else
2093                             c2 = c1;
2094                     }
2095                     else
2096                         c1 = c2 = -1000;
2097                 }
2098                 REGCP_SET;
2099                 while (n >= ln) {
2100                     /* If it could work, try it. */
2101                     if (c1 == -1000 ||
2102                         UCHARAT(PL_reginput) == c1 ||
2103                         UCHARAT(PL_reginput) == c2)
2104                     {
2105                         DEBUG_r(
2106                                 PerlIO_printf(Perl_debug_log,
2107                                               "%*s  trying tail with n=%ld...\n",
2108                                               REPORT_CODE_OFF+PL_regindent*2, "", n)
2109                             );
2110                         if (paren) {
2111                             if (n) {
2112                                 PL_regstartp[paren] = HOPc(PL_reginput, -l);
2113                                 PL_regendp[paren] = PL_reginput;
2114                             }
2115                             else
2116                                 PL_regendp[paren] = NULL;
2117                         }
2118                         if (regmatch(next))
2119                             sayYES;
2120                         REGCP_UNWIND;
2121                     }
2122                     /* Couldn't or didn't -- back up. */
2123                     n--;
2124                     locinput = HOPc(locinput, -l);
2125                     PL_reginput = locinput;
2126                 }
2127             }
2128             sayNO;
2129             break;
2130         }
2131         case CURLYN:
2132             paren = scan->flags;        /* Which paren to set */
2133             if (paren > PL_regsize)
2134                 PL_regsize = paren;
2135             if (paren > *PL_reglastparen)
2136                 *PL_reglastparen = paren;
2137             ln = ARG1(scan);  /* min to match */
2138             n  = ARG2(scan);  /* max to match */
2139             scan = regnext(NEXTOPER(scan) + NODE_STEP_REGNODE);
2140             goto repeat;
2141         case CURLY:
2142             paren = 0;
2143             ln = ARG1(scan);  /* min to match */
2144             n  = ARG2(scan);  /* max to match */
2145             scan = NEXTOPER(scan) + NODE_STEP_REGNODE;
2146             goto repeat;
2147         case STAR:
2148             ln = 0;
2149             n = REG_INFTY;
2150             scan = NEXTOPER(scan);
2151             paren = 0;
2152             goto repeat;
2153         case PLUS:
2154             ln = 1;
2155             n = REG_INFTY;
2156             scan = NEXTOPER(scan);
2157             paren = 0;
2158           repeat:
2159             /*
2160             * Lookahead to avoid useless match attempts
2161             * when we know what character comes next.
2162             */
2163             if (PL_regkind[(U8)OP(next)] == EXACT) {
2164                 c1 = UCHARAT(OPERAND(next) + 1);
2165                 if (OP(next) == EXACTF)
2166                     c2 = PL_fold[c1];
2167                 else if (OP(next) == EXACTFL)
2168                     c2 = PL_fold_locale[c1];
2169                 else
2170                     c2 = c1;
2171             }
2172             else
2173                 c1 = c2 = -1000;
2174             PL_reginput = locinput;
2175             if (minmod) {
2176                 CHECKPOINT lastcp;
2177                 minmod = 0;
2178                 if (ln && regrepeat(scan, ln) < ln)
2179                     sayNO;
2180                 locinput = PL_reginput;
2181                 REGCP_SET;
2182                 while (n >= ln || (n == REG_INFTY && ln > 0)) { /* ln overflow ? */
2183                     /* If it could work, try it. */
2184                     if (c1 == -1000 ||
2185                         UCHARAT(PL_reginput) == c1 ||
2186                         UCHARAT(PL_reginput) == c2)
2187                     {
2188                         if (paren) {
2189                             if (n) {
2190                                 PL_regstartp[paren] = HOPc(PL_reginput, -1);
2191                                 PL_regendp[paren] = PL_reginput;
2192                             }
2193                             else
2194                                 PL_regendp[paren] = NULL;
2195                         }
2196                         if (regmatch(next))
2197                             sayYES;
2198                         REGCP_UNWIND;
2199                     }
2200                     /* Couldn't or didn't -- move forward. */
2201                     PL_reginput = locinput;
2202                     if (regrepeat(scan, 1)) {
2203                         ln++;
2204                         locinput = PL_reginput;
2205                     }
2206                     else
2207                         sayNO;
2208                 }
2209             }
2210             else {
2211                 CHECKPOINT lastcp;
2212                 n = regrepeat(scan, n);
2213                 locinput = PL_reginput;
2214                 if (ln < n && PL_regkind[(U8)OP(next)] == EOL &&
2215                     (!PL_multiline  || OP(next) == SEOL))
2216                     ln = n;                     /* why back off? */
2217                 REGCP_SET;
2218                 if (paren) {
2219                     while (n >= ln) {
2220                         /* If it could work, try it. */
2221                         if (c1 == -1000 ||
2222                             UCHARAT(PL_reginput) == c1 ||
2223                             UCHARAT(PL_reginput) == c2)
2224                             {
2225                                 if (paren && n) {
2226                                     if (n) {
2227                                         PL_regstartp[paren] = HOPc(PL_reginput, -1);
2228                                         PL_regendp[paren] = PL_reginput;
2229                                     }
2230                                     else
2231                                         PL_regendp[paren] = NULL;
2232                                 }
2233                                 if (regmatch(next))
2234                                     sayYES;
2235                                 REGCP_UNWIND;
2236                             }
2237                         /* Couldn't or didn't -- back up. */
2238                         n--;
2239                         PL_reginput = locinput = HOPc(locinput, -1);
2240                     }
2241                 }
2242                 else {
2243                     while (n >= ln) {
2244                         /* If it could work, try it. */
2245                         if (c1 == -1000 ||
2246                             UCHARAT(PL_reginput) == c1 ||
2247                             UCHARAT(PL_reginput) == c2)
2248                             {
2249                                 if (regmatch(next))
2250                                     sayYES;
2251                                 REGCP_UNWIND;
2252                             }
2253                         /* Couldn't or didn't -- back up. */
2254                         n--;
2255                         PL_reginput = locinput = HOPc(locinput, -1);
2256                     }
2257                 }
2258             }
2259             sayNO;
2260             break;
2261         case END:
2262             if (PL_reg_call_cc) {
2263                 re_cc_state *cur_call_cc = PL_reg_call_cc;
2264                 CURCUR *cctmp = PL_regcc;
2265                 regexp *re = PL_reg_re;
2266                 CHECKPOINT cp, lastcp;
2267                 
2268                 cp = regcppush(0);      /* Save *all* the positions. */
2269                 REGCP_SET;
2270                 regcp_set_to(PL_reg_call_cc->ss); /* Restore parens of
2271                                                     the caller. */
2272                 PL_reginput = locinput; /* Make position available to
2273                                            the callcc. */
2274                 cache_re(PL_reg_call_cc->re);
2275                 PL_regcc = PL_reg_call_cc->cc;
2276                 PL_reg_call_cc = PL_reg_call_cc->prev;
2277                 if (regmatch(cur_call_cc->node)) {
2278                     PL_reg_call_cc = cur_call_cc;
2279                     regcpblow(cp);
2280                     sayYES;
2281                 }
2282                 REGCP_UNWIND;
2283                 regcppop();
2284                 PL_reg_call_cc = cur_call_cc;
2285                 PL_regcc = cctmp;
2286                 PL_reg_re = re;
2287                 cache_re(re);
2288
2289                 DEBUG_r(
2290                     PerlIO_printf(Perl_debug_log,
2291                                   "%*s  continuation failed...\n",
2292                                   REPORT_CODE_OFF+PL_regindent*2, "")
2293                     );
2294                 sayNO;
2295             }
2296             if (locinput < PL_regtill)
2297                 sayNO;                  /* Cannot match: too short. */
2298             /* Fall through */
2299         case SUCCEED:
2300             PL_reginput = locinput;     /* put where regtry can find it */
2301             sayYES;                     /* Success! */
2302         case SUSPEND:
2303             n = 1;
2304             PL_reginput = locinput;
2305             goto do_ifmatch;        
2306         case UNLESSM:
2307             n = 0;
2308             if (scan->flags) {
2309                 s = HOPMAYBEc(locinput, -scan->flags);
2310                 if (!s)
2311                     goto say_yes;
2312                 PL_reginput = s;
2313             }
2314             else
2315                 PL_reginput = locinput;
2316             goto do_ifmatch;
2317         case IFMATCH:
2318             n = 1;
2319             if (scan->flags) {
2320                 s = HOPMAYBEc(locinput, -scan->flags);
2321                 if (!s || s < PL_bostr)
2322                     goto say_no;
2323                 PL_reginput = s;
2324             }
2325             else
2326                 PL_reginput = locinput;
2327
2328           do_ifmatch:
2329             inner = NEXTOPER(NEXTOPER(scan));
2330             if (regmatch(inner) != n) {
2331               say_no:
2332                 if (logical) {
2333                     logical = 0;
2334                     sw = 0;
2335                     goto do_longjump;
2336                 }
2337                 else
2338                     sayNO;
2339             }
2340           say_yes:
2341             if (logical) {
2342                 logical = 0;
2343                 sw = 1;
2344             }
2345             if (OP(scan) == SUSPEND) {
2346                 locinput = PL_reginput;
2347                 nextchr = UCHARAT(locinput);
2348             }
2349             /* FALL THROUGH. */
2350         case LONGJMP:
2351           do_longjump:
2352             next = scan + ARG(scan);
2353             if (next == scan)
2354                 next = NULL;
2355             break;
2356         default:
2357             PerlIO_printf(PerlIO_stderr(), "%lx %d\n",
2358                           (unsigned long)scan, OP(scan));
2359             FAIL("regexp memory corruption");
2360         }
2361         scan = next;
2362     }
2363
2364     /*
2365     * We get here only if there's trouble -- normally "case END" is
2366     * the terminating point.
2367     */
2368     FAIL("corrupted regexp pointers");
2369     /*NOTREACHED*/
2370     sayNO;
2371
2372 yes:
2373 #ifdef DEBUGGING
2374     PL_regindent--;
2375 #endif
2376     return 1;
2377
2378 no:
2379 #ifdef DEBUGGING
2380     PL_regindent--;
2381 #endif
2382     return 0;
2383 }
2384
2385 /*
2386  - regrepeat - repeatedly match something simple, report how many
2387  */
2388 /*
2389  * [This routine now assumes that it will only match on things of length 1.
2390  * That was true before, but now we assume scan - reginput is the count,
2391  * rather than incrementing count on every character.  [Er, except utf8.]]
2392  */
2393 STATIC I32
2394 regrepeat(regnode *p, I32 max)
2395 {
2396     dTHR;
2397     register char *scan;
2398     register char *opnd;
2399     register I32 c;
2400     register char *loceol = PL_regeol;
2401     register I32 hardcount = 0;
2402
2403     scan = PL_reginput;
2404     if (max != REG_INFTY && max < loceol - scan)
2405       loceol = scan + max;
2406     opnd = (char *) OPERAND(p);
2407     switch (OP(p)) {
2408     case REG_ANY:
2409         while (scan < loceol && *scan != '\n')
2410             scan++;
2411         break;
2412     case SANY:
2413         scan = loceol;
2414         break;
2415     case ANYUTF8:
2416         loceol = PL_regeol;
2417         while (scan < loceol && *scan != '\n') {
2418             scan += UTF8SKIP(scan);
2419             hardcount++;
2420         }
2421         break;
2422     case SANYUTF8:
2423         loceol = PL_regeol;
2424         while (scan < loceol) {
2425             scan += UTF8SKIP(scan);
2426             hardcount++;
2427         }
2428         break;
2429     case EXACT:         /* length of string is 1 */
2430         c = UCHARAT(++opnd);
2431         while (scan < loceol && UCHARAT(scan) == c)
2432             scan++;
2433         break;
2434     case EXACTF:        /* length of string is 1 */
2435         c = UCHARAT(++opnd);
2436         while (scan < loceol &&
2437                (UCHARAT(scan) == c || UCHARAT(scan) == PL_fold[c]))
2438             scan++;
2439         break;
2440     case EXACTFL:       /* length of string is 1 */
2441         PL_reg_flags |= RF_tainted;
2442         c = UCHARAT(++opnd);
2443         while (scan < loceol &&
2444                (UCHARAT(scan) == c || UCHARAT(scan) == PL_fold_locale[c]))
2445             scan++;
2446         break;
2447     case ANYOFUTF8:
2448         loceol = PL_regeol;
2449         while (scan < loceol && REGINCLASSUTF8(p, (U8*)scan)) {
2450             scan += UTF8SKIP(scan);
2451             hardcount++;
2452         }
2453         break;
2454     case ANYOF:
2455         while (scan < loceol && REGINCLASS(opnd, *scan))
2456             scan++;
2457         break;
2458     case ALNUM:
2459         while (scan < loceol && isALNUM(*scan))
2460             scan++;
2461         break;
2462     case ALNUMUTF8:
2463         loceol = PL_regeol;
2464         while (scan < loceol && swash_fetch(PL_utf8_alnum, (U8*)scan)) {
2465             scan += UTF8SKIP(scan);
2466             hardcount++;
2467         }
2468         break;
2469     case ALNUML:
2470         PL_reg_flags |= RF_tainted;
2471         while (scan < loceol && isALNUM_LC(*scan))
2472             scan++;
2473         break;
2474     case ALNUMLUTF8:
2475         PL_reg_flags |= RF_tainted;
2476         loceol = PL_regeol;
2477         while (scan < loceol && isALNUM_LC_utf8((U8*)scan)) {
2478             scan += UTF8SKIP(scan);
2479             hardcount++;
2480         }
2481         break;
2482         break;
2483     case NALNUM:
2484         while (scan < loceol && !isALNUM(*scan))
2485             scan++;
2486         break;
2487     case NALNUMUTF8:
2488         loceol = PL_regeol;
2489         while (scan < loceol && !swash_fetch(PL_utf8_alnum, (U8*)scan)) {
2490             scan += UTF8SKIP(scan);
2491             hardcount++;
2492         }
2493         break;
2494     case NALNUML:
2495         PL_reg_flags |= RF_tainted;
2496         while (scan < loceol && !isALNUM_LC(*scan))
2497             scan++;
2498         break;
2499     case NALNUMLUTF8:
2500         PL_reg_flags |= RF_tainted;
2501         loceol = PL_regeol;
2502         while (scan < loceol && !isALNUM_LC_utf8((U8*)scan)) {
2503             scan += UTF8SKIP(scan);
2504             hardcount++;
2505         }
2506         break;
2507     case SPACE:
2508         while (scan < loceol && isSPACE(*scan))
2509             scan++;
2510         break;
2511     case SPACEUTF8:
2512         loceol = PL_regeol;
2513         while (scan < loceol && (*scan == ' ' || swash_fetch(PL_utf8_space,(U8*)scan))) {
2514             scan += UTF8SKIP(scan);
2515             hardcount++;
2516         }
2517         break;
2518     case SPACEL:
2519         PL_reg_flags |= RF_tainted;
2520         while (scan < loceol && isSPACE_LC(*scan))
2521             scan++;
2522         break;
2523     case SPACELUTF8:
2524         PL_reg_flags |= RF_tainted;
2525         loceol = PL_regeol;
2526         while (scan < loceol && (*scan == ' ' || isSPACE_LC_utf8((U8*)scan))) {
2527             scan += UTF8SKIP(scan);
2528             hardcount++;
2529         }
2530         break;
2531     case NSPACE:
2532         while (scan < loceol && !isSPACE(*scan))
2533             scan++;
2534         break;
2535     case NSPACEUTF8:
2536         loceol = PL_regeol;
2537         while (scan < loceol && !(*scan == ' ' || swash_fetch(PL_utf8_space,(U8*)scan))) {
2538             scan += UTF8SKIP(scan);
2539             hardcount++;
2540         }
2541         break;
2542     case NSPACEL:
2543         PL_reg_flags |= RF_tainted;
2544         while (scan < loceol && !isSPACE_LC(*scan))
2545             scan++;
2546         break;
2547     case NSPACELUTF8:
2548         PL_reg_flags |= RF_tainted;
2549         loceol = PL_regeol;
2550         while (scan < loceol && !(*scan == ' ' || isSPACE_LC_utf8((U8*)scan))) {
2551             scan += UTF8SKIP(scan);
2552             hardcount++;
2553         }
2554         break;
2555     case DIGIT:
2556         while (scan < loceol && isDIGIT(*scan))
2557             scan++;
2558         break;
2559     case DIGITUTF8:
2560         loceol = PL_regeol;
2561         while (scan < loceol && swash_fetch(PL_utf8_digit,(U8*)scan)) {
2562             scan += UTF8SKIP(scan);
2563             hardcount++;
2564         }
2565         break;
2566         break;
2567     case NDIGIT:
2568         while (scan < loceol && !isDIGIT(*scan))
2569             scan++;
2570         break;
2571     case NDIGITUTF8:
2572         loceol = PL_regeol;
2573         while (scan < loceol && !swash_fetch(PL_utf8_digit,(U8*)scan)) {
2574             scan += UTF8SKIP(scan);
2575             hardcount++;
2576         }
2577         break;
2578     default:            /* Called on something of 0 width. */
2579         break;          /* So match right here or not at all. */
2580     }
2581
2582     if (hardcount)
2583         c = hardcount;
2584     else
2585         c = scan - PL_reginput;
2586     PL_reginput = scan;
2587
2588     DEBUG_r( 
2589         {
2590                 SV *prop = sv_newmortal();
2591
2592                 regprop(prop, p);
2593                 PerlIO_printf(Perl_debug_log, 
2594                               "%*s  %s can match %ld times out of %ld...\n", 
2595                               REPORT_CODE_OFF+1, "", SvPVX(prop),c,max);
2596         });
2597     
2598     return(c);
2599 }
2600
2601 /*
2602  - regrepeat_hard - repeatedly match something, report total lenth and length
2603  * 
2604  * The repeater is supposed to have constant length.
2605  */
2606
2607 STATIC I32
2608 regrepeat_hard(regnode *p, I32 max, I32 *lp)
2609 {
2610     dTHR;
2611     register char *scan;
2612     register char *start;
2613     register char *loceol = PL_regeol;
2614     I32 l = 0;
2615     I32 count = 0, res = 1;
2616
2617     if (!max)
2618         return 0;
2619
2620     start = PL_reginput;
2621     if (UTF) {
2622         while (PL_reginput < loceol && (scan = PL_reginput, res = regmatch(p))) {
2623             if (!count++) {
2624                 l = 0;
2625                 while (start < PL_reginput) {
2626                     l++;
2627                     start += UTF8SKIP(start);
2628                 }
2629                 *lp = l;
2630                 if (l == 0)
2631                     return max;
2632             }
2633             if (count == max)
2634                 return count;
2635         }
2636     }
2637     else {
2638         while (PL_reginput < loceol && (scan = PL_reginput, res = regmatch(p))) {
2639             if (!count++) {
2640                 *lp = l = PL_reginput - start;
2641                 if (max != REG_INFTY && l*max < loceol - scan)
2642                     loceol = scan + l*max;
2643                 if (l == 0)
2644                     return max;
2645             }
2646         }
2647     }
2648     if (!res)
2649         PL_reginput = scan;
2650     
2651     return count;
2652 }
2653
2654 /*
2655  - regclass - determine if a character falls into a character class
2656  */
2657
2658 STATIC bool
2659 reginclass(register char *p, register I32 c)
2660 {
2661     dTHR;
2662     char flags = *p;
2663     bool match = FALSE;
2664
2665     c &= 0xFF;
2666     if (ANYOF_TEST(p, c))
2667         match = TRUE;
2668     else if (flags & ANYOF_FOLD) {
2669         I32 cf;
2670         if (flags & ANYOF_LOCALE) {
2671             PL_reg_flags |= RF_tainted;
2672             cf = PL_fold_locale[c];
2673         }
2674         else
2675             cf = PL_fold[c];
2676         if (ANYOF_TEST(p, cf))
2677             match = TRUE;
2678     }
2679
2680     if (!match && (flags & ANYOF_ISA)) {
2681         PL_reg_flags |= RF_tainted;
2682
2683         if (((flags & ANYOF_ALNUML)  && isALNUM_LC(c))  ||
2684             ((flags & ANYOF_NALNUML) && !isALNUM_LC(c)) ||
2685             ((flags & ANYOF_SPACEL)  && isSPACE_LC(c))  ||
2686             ((flags & ANYOF_NSPACEL) && !isSPACE_LC(c)))
2687         {
2688             match = TRUE;
2689         }
2690     }
2691
2692     return (flags & ANYOF_INVERT) ? !match : match;
2693 }
2694
2695 STATIC bool
2696 reginclassutf8(regnode *f, U8 *p)
2697 {                                           
2698     dTHR;
2699     char flags = ARG1(f);
2700     bool match = FALSE;
2701     SV *sv = (SV*)PL_regdata->data[ARG2(f)];
2702
2703     if (swash_fetch(sv, p))
2704         match = TRUE;
2705     else if (flags & ANYOF_FOLD) {
2706         I32 cf;
2707         U8 tmpbuf[10];
2708         if (flags & ANYOF_LOCALE) {
2709             PL_reg_flags |= RF_tainted;
2710             uv_to_utf8(tmpbuf, toLOWER_LC_utf8(p));
2711         }
2712         else
2713             uv_to_utf8(tmpbuf, toLOWER_utf8(p));
2714         if (swash_fetch(sv, tmpbuf))
2715             match = TRUE;
2716     }
2717
2718     if (!match && (flags & ANYOF_ISA)) {
2719         PL_reg_flags |= RF_tainted;
2720
2721         if (((flags & ANYOF_ALNUML)  && isALNUM_LC_utf8(p))  ||
2722             ((flags & ANYOF_NALNUML) && !isALNUM_LC_utf8(p)) ||
2723             ((flags & ANYOF_SPACEL)  && isSPACE_LC_utf8(p))  ||
2724             ((flags & ANYOF_NSPACEL) && !isSPACE_LC_utf8(p)))
2725         {
2726             match = TRUE;
2727         }
2728     }
2729
2730     return (flags & ANYOF_INVERT) ? !match : match;
2731 }
2732
2733 STATIC U8 *
2734 reghop(U8 *s, I32 off)
2735 {                               
2736     dTHR;
2737     if (off >= 0) {
2738         while (off-- && s < (U8*)PL_regeol)
2739             s += UTF8SKIP(s);
2740     }
2741     else {
2742         while (off++) {
2743             if (s > (U8*)PL_bostr) {
2744                 s--;
2745                 if (*s & 0x80) {
2746                     while (s > (U8*)PL_bostr && (*s & 0xc0) == 0x80)
2747                         s--;
2748                 }               /* XXX could check well-formedness here */
2749             }
2750         }
2751     }
2752     return s;
2753 }
2754
2755 STATIC U8 *
2756 reghopmaybe(U8* s, I32 off)
2757 {
2758     dTHR;
2759     if (off >= 0) {
2760         while (off-- && s < (U8*)PL_regeol)
2761             s += UTF8SKIP(s);
2762         if (off >= 0)
2763             return 0;
2764     }
2765     else {
2766         while (off++) {
2767             if (s > (U8*)PL_bostr) {
2768                 s--;
2769                 if (*s & 0x80) {
2770                     while (s > (U8*)PL_bostr && (*s & 0xc0) == 0x80)
2771                         s--;
2772                 }               /* XXX could check well-formedness here */
2773             }
2774             else
2775                 break;
2776         }
2777         if (off <= 0)
2778             return 0;
2779     }
2780     return s;
2781 }