/* *These* symbols are masked to allow static link. */
# define Perl_pregfree my_regfree
# define Perl_regnext my_regnext
+# define Perl_save_re_context my_save_re_context
+# define Perl_reginitcolors my_reginitcolors
#endif
/*SUPPRESS 112*/
static char* regwhite _((char *, char *));
static char* nextchar _((void));
static void re_croak2 _((const char* pat1,const char* pat2,...)) __attribute__((noreturn));
+static char* regpposixcc _((I32 value));
+static void clear_re _((void *r));
#endif
/* Length of a variant. */
#define CHR_DIST(a,b) (UTF ? utf8_distance(a,b) : a - b)
STATIC void
+clear_re(void *r)
+{
+ ReREFCNT_dec((regexp *)r);
+}
+
+STATIC void
scan_commit(scan_data_t *data)
{
dTHR;
regnode *scan = *scanp, *next;
I32 delta = 0;
int is_inf = (flags & SCF_DO_SUBSTR) && (data->flags & SF_IS_INF);
+ int is_inf_internal = 0; /* The studied chunk is infinite */
I32 is_par = OP(scan) == OPEN ? ARG(scan) : 0;
scan_data_t data_fake;
while (scan && OP(scan) != END && scan < last) {
/* Peephole optimizer: */
- if (regkind[(U8)OP(scan)] == EXACT) {
+ if (PL_regkind[(U8)OP(scan)] == EXACT) {
regnode *n = regnext(scan);
U32 stringok = 1;
#ifdef DEBUGGING
next = scan + (*OPERAND(scan) + 2 - 1)/sizeof(regnode) + 2;
/* Skip NOTHING, merge EXACT*. */
while (n &&
- ( regkind[(U8)OP(n)] == NOTHING ||
+ ( PL_regkind[(U8)OP(n)] == NOTHING ||
(stringok && (OP(n) == OP(scan))))
&& NEXT_OFF(n)
&& NEXT_OFF(scan) + NEXT_OFF(n) < I16_MAX) {
if (OP(n) == TAIL || n > next)
stringok = 0;
- if (regkind[(U8)OP(n)] == NOTHING) {
+ if (PL_regkind[(U8)OP(n)] == NOTHING) {
NEXT_OFF(scan) += NEXT_OFF(n);
next = n + NODE_STEP_REGNODE;
#ifdef DEBUGGING
* don't initialize the OP() slot of a node when that node
* is occupied by just the trailing null of the string in
* an EXACT node */
- if (regkind[(U8)OP(n)] != NOTHING || OP(n) == NOTHING) {
+ if (PL_regkind[(U8)OP(n)] != NOTHING || OP(n) == NOTHING) {
OP(n) = OPTIMIZED;
NEXT_OFF(n) = 0;
}
/* Skip NOTHING and LONGJMP. */
while ((n = regnext(n))
- && ((regkind[(U8)OP(n)] == NOTHING && (noff = NEXT_OFF(n)))
+ && ((PL_regkind[(U8)OP(n)] == NOTHING && (noff = NEXT_OFF(n)))
|| ((OP(n) == LONGJMP) && (noff = ARG(n))))
&& off + noff < max)
off += noff;
if (max1 < minnext + deltanext)
max1 = minnext + deltanext;
if (deltanext == I32_MAX)
- is_inf = 1;
+ is_inf = is_inf_internal = 1;
scan = next;
if (data_fake.flags & (SF_HAS_PAR|SF_IN_PAR))
pars++;
data->flags &= ~SF_BEFORE_EOL;
}
}
- else if (regkind[(U8)OP(scan)] == EXACT) {
+ else if (PL_regkind[(U8)OP(scan)] == EXACT) {
I32 l = *OPERAND(scan);
if (flags & SCF_DO_SUBSTR)
scan_commit(data);
if (data && (flags & SCF_DO_SUBSTR))
data->pos_min += l;
}
- else if (strchr(varies,OP(scan))) {
+ else if (strchr(PL_varies,OP(scan))) {
I32 mincount, maxcount, minnext, deltanext, pos_before, fl;
regnode *oscan = scan;
- switch (regkind[(U8)OP(scan)]) {
+ switch (PL_regkind[(U8)OP(scan)]) {
case WHILEM:
scan = NEXTOPER(scan);
goto finish;
min++;
/* Fall through. */
case STAR:
- is_inf = 1;
+ is_inf = is_inf_internal = 1;
scan = regnext(scan);
if (flags & SCF_DO_SUBSTR) {
scan_commit(data);
? (flags & ~SCF_DO_SUBSTR) : flags);
if (!scan) /* It was not CURLYX, but CURLY. */
scan = next;
- if (PL_dowarn && (minnext + deltanext == 0)
+ if (ckWARN(WARN_UNSAFE) && (minnext + deltanext == 0)
&& !(data->flags & (SF_HAS_PAR|SF_IN_PAR))
- && maxcount <= 10000) /* Complement check for big count */
- warn("Strange *+?{} on zero-length expression");
+ && maxcount <= REG_INFTY/3) /* Complement check for big count */
+ warner(WARN_UNSAFE, "Strange *+?{} on zero-length expression");
min += minnext * mincount;
- is_inf |= (maxcount == REG_INFTY && (minnext + deltanext) > 0
- || deltanext == I32_MAX);
+ is_inf_internal |= (maxcount == REG_INFTY
+ && (minnext + deltanext) > 0
+ || deltanext == I32_MAX);
+ is_inf |= is_inf_internal;
delta += (minnext + deltanext) * maxcount - minnext * mincount;
/* Try powerful optimization CURLYX => CURLYN. */
/* Skip open. */
nxt = regnext(nxt);
- if (!strchr(simple,OP(nxt))
- && !(regkind[(U8)OP(nxt)] == EXACT
+ if (!strchr(PL_simple,OP(nxt))
+ && !(PL_regkind[(U8)OP(nxt)] == EXACT
&& *OPERAND(nxt) == 1))
goto nogo;
nxt2 = nxt;
}
data->longest = &(data->longest_float);
}
+ SvREFCNT_dec(last_str);
}
if (data && (fl & SF_HAS_EVAL))
data->flags |= SF_HAS_EVAL;
optimize_curly_tail:
if (OP(oscan) != CURLYX) {
- while (regkind[(U8)OP(next = regnext(oscan))] == NOTHING
+ while (PL_regkind[(U8)OP(next = regnext(oscan))] == NOTHING
&& NEXT_OFF(next))
NEXT_OFF(oscan) += NEXT_OFF(next);
}
scan_commit(data);
data->longest = &(data->longest_float);
}
- is_inf = 1;
+ is_inf = is_inf_internal = 1;
break;
}
}
- else if (strchr(simple,OP(scan)) || regkind[(U8)OP(scan)] == ANYUTF8) {
+ else if (strchr(PL_simple,OP(scan)) || PL_regkind[(U8)OP(scan)] == ANYUTF8) {
if (flags & SCF_DO_SUBSTR) {
scan_commit(data);
data->pos_min++;
}
min++;
}
- else if (regkind[(U8)OP(scan)] == EOL && flags & SCF_DO_SUBSTR) {
+ else if (PL_regkind[(U8)OP(scan)] == EOL && flags & SCF_DO_SUBSTR) {
data->flags |= (OP(scan) == MEOL
? SF_BEFORE_MEOL
: SF_BEFORE_SEOL);
}
- else if (regkind[(U8)OP(scan)] == BRANCHJ
+ else if (PL_regkind[(U8)OP(scan)] == BRANCHJ
&& (scan->flags || data)
&& (OP(scan) == IFMATCH || OP(scan) == UNLESSM)) {
I32 deltanext, minnext;
if (data)
data->flags |= SF_HAS_EVAL;
}
+ else if (OP(scan) == LOGICAL && scan->flags == 2) { /* Embedded */
+ if (flags & SCF_DO_SUBSTR) {
+ scan_commit(data);
+ data->longest = &(data->longest_float);
+ }
+ is_inf = is_inf_internal = 1;
+ }
/* Else: zero-length, ignore. */
scan = regnext(scan);
}
finish:
*scanp = scan;
- *deltap = is_inf ? I32_MAX : delta;
+ *deltap = is_inf_internal ? I32_MAX : delta;
if (flags & SCF_DO_SUBSTR && is_inf)
data->pos_delta = I32_MAX - data->pos_min;
if (is_par > U8_MAX)
return PL_regcomp_rx->data->count - n;
}
+void
+reginitcolors(void)
+{
+ dTHR;
+ int i = 0;
+ char *s = PerlEnv_getenv("PERL_RE_COLORS");
+
+ if (s) {
+ PL_colors[0] = s = savepv(s);
+ while (++i < 6) {
+ s = strchr(s, '\t');
+ if (s) {
+ *s = '\0';
+ PL_colors[i] = ++s;
+ }
+ else
+ PL_colors[i] = s = "";
+ }
+ } else {
+ while (i < 6)
+ PL_colors[i++] = "";
+ }
+ PL_colorset = 1;
+}
+
/*
- pregcomp - compile a regular expression into internal code
*
if (exp == NULL)
FAIL("NULL regexp argument");
- if (PL_curcop == &compiling ? (PL_hints & HINT_UTF8) : IN_UTF8)
+ if (PL_curcop == &PL_compiling ? (PL_hints & HINT_UTF8) : IN_UTF8)
PL_reg_flags |= RF_utf8;
else
PL_reg_flags = 0;
PL_regprecomp = savepvn(exp, xend - exp);
- DEBUG_r(PerlIO_printf(Perl_debug_log, "compiling RE `%*s'\n",
- xend - exp, PL_regprecomp));
+ DEBUG_r(if (!PL_colorset) reginitcolors());
+ DEBUG_r(PerlIO_printf(Perl_debug_log, "%sCompiling%s RE `%s%*s%s'\n",
+ PL_colors[4],PL_colors[5],PL_colors[0],
+ xend - exp, PL_regprecomp, PL_colors[1]));
PL_regflags = pm->op_pmflags;
PL_regsawback = 0;
PL_regnpar = 1;
PL_regsize = 0L;
PL_regcode = &PL_regdummy;
- regc((U8)MAGIC, (char*)PL_regcode);
+ regc((U8)REG_MAGIC, (char*)PL_regcode);
if (reg(0, &flags) == NULL) {
Safefree(PL_regprecomp);
PL_regprecomp = Nullch;
}
DEBUG_r(PerlIO_printf(Perl_debug_log, "size %d ", PL_regsize));
- DEBUG_r(
- if (!PL_colorset) {
- int i = 0;
- char *s = PerlEnv_getenv("TERMCAP_COLORS");
-
- PL_colorset = 1;
- if (s) {
- PL_colors[0] = s = savepv(s);
- while (++i < 4) {
- s = strchr(s, '\t');
- if (!s)
- FAIL("Not enough TABs in TERMCAP_COLORS");
- *s = '\0';
- PL_colors[i] = ++s;
- }
- }
- else {
- while (i < 4)
- PL_colors[i++] = "";
- }
- /* Reset colors: */
- PerlIO_printf(Perl_debug_log, "%s%s%s%s",
- PL_colors[0],PL_colors[1],PL_colors[2],PL_colors[3]);
- }
- );
-
/* Small enough for pointer-storage convention?
If extralen==0, this means that we will not need long jumps. */
if (PL_regsize >= 0x10000L && PL_extralen)
r->prelen = xend - exp;
r->precomp = PL_regprecomp;
r->subbeg = r->subbase = NULL;
- r->nparens = PL_regnpar - 1; /* set early to validate backrefs */
+ r->nparens = PL_regnpar - 1; /* set early to validate backrefs */
+
+ r->substrs = 0; /* Useful during FAIL. */
+ r->startp = 0; /* Useful during FAIL. */
+ r->endp = 0; /* Useful during FAIL. */
+
PL_regcomp_rx = r;
/* Second pass: emit code. */
PL_regcode = r->program;
/* Store the count of eval-groups for security checks: */
PL_regcode->next_off = ((PL_seen_evals > U16_MAX) ? U16_MAX : PL_seen_evals);
- regc((U8)MAGIC, (char*) PL_regcode++);
+ regc((U8)REG_MAGIC, (char*) PL_regcode++);
r->data = 0;
if (reg(0, &flags) == NULL)
return(NULL);
(OP(first) == BRANCH && OP(regnext(first)) != BRANCH) ||
(OP(first) == PLUS) ||
(OP(first) == MINMOD) ||
- (regkind[(U8)OP(first)] == CURLY && ARG1(first) > 0) ) {
+ (PL_regkind[(U8)OP(first)] == CURLY && ARG1(first) > 0) ) {
if (OP(first) == PLUS)
sawplus = 1;
else
/* Starting-point info. */
again:
if (OP(first) == EXACT); /* Empty, get anchored substr later. */
- else if (strchr(simple+4,OP(first)))
+ else if (strchr(PL_simple+4,OP(first)))
r->regstclass = first;
- else if (regkind[(U8)OP(first)] == BOUND ||
- regkind[(U8)OP(first)] == NBOUND)
+ else if (PL_regkind[(U8)OP(first)] == BOUND ||
+ PL_regkind[(U8)OP(first)] == NBOUND)
r->regstclass = first;
- else if (regkind[(U8)OP(first)] == BOL) {
+ else if (PL_regkind[(U8)OP(first)] == BOL) {
r->reganch |= (OP(first) == MBOL ? ROPT_ANCH_MBOL: ROPT_ANCH_BOL);
first = NEXTOPER(first);
goto again;
goto again;
}
else if ((OP(first) == STAR &&
- regkind[(U8)OP(NEXTOPER(first))] == ANY) &&
+ PL_regkind[(U8)OP(NEXTOPER(first))] == REG_ANY) &&
!(r->reganch & ROPT_ANCH) )
{
/* turn .* into ^.* with an implied $*=1 */
&& (!(data.flags & SF_FL_BEFORE_MEOL)
|| (PL_regflags & PMf_MULTILINE)))) {
if (SvCUR(data.longest_fixed) /* ok to leave SvCUR */
- && data.offset_fixed == data.offset_float_min)
- goto remove; /* Like in (a)+. */
-
+ && data.offset_fixed == data.offset_float_min
+ && SvCUR(data.longest_fixed) == SvCUR(data.longest_float))
+ goto remove_float; /* As in (a)+. */
+
r->float_substr = data.longest_float;
r->float_min_offset = data.offset_float_min;
r->float_max_offset = data.offset_float_max;
SvTAIL_on(r->float_substr);
}
else {
- remove:
+ remove_float:
r->float_substr = Nullsv;
SvREFCNT_dec(data.longest_float);
longest_float_length = 0;
if (*PL_regcomp_parse == '?') {
U16 posflags = 0, negflags = 0;
U16 *flagsp = &posflags;
+ int logical = 0;
PL_regcomp_parse++;
paren = *PL_regcomp_parse++;
nextchar();
*flagp = TRYAGAIN;
return NULL;
+ case 'p':
+ logical = 1;
+ paren = *PL_regcomp_parse++;
+ /* FALL THROUGH */
case '{':
{
dTHR;
rop = sv_compile_2op(sv, &sop, "re", &av);
- n = add_data(3, "nso");
+ n = add_data(3, "nop");
PL_regcomp_rx->data->data[n] = (void*)rop;
- PL_regcomp_rx->data->data[n+1] = (void*)av;
- PL_regcomp_rx->data->data[n+2] = (void*)sop;
+ PL_regcomp_rx->data->data[n+1] = (void*)sop;
+ PL_regcomp_rx->data->data[n+2] = (void*)av;
SvREFCNT_dec(sv);
}
- else { /* First pass */
- if (PL_reginterp_cnt < ++PL_seen_evals && PL_curcop != &compiling)
+ else { /* First pass */
+ if (PL_reginterp_cnt < ++PL_seen_evals
+ && PL_curcop != &PL_compiling)
/* No compiled RE interpolated, has runtime
components ===> unsafe. */
FAIL("Eval-group not allowed at runtime, use re 'eval'");
}
nextchar();
+ if (logical) {
+ ret = reg_node(LOGICAL);
+ if (!SIZE_ONLY)
+ ret->flags = 2;
+ regtail(ret, reganode(EVAL, n));
+ return ret;
+ }
return reganode(EVAL, n);
}
case '(':
I32 flag;
ret = reg_node(LOGICAL);
+ if (!SIZE_ONLY)
+ ret->flags = 1;
regtail(ret, reg(1, &flag));
goto insert_if;
}
else
regtail(br, reganode(LONGJMP, 0));
c = *nextchar();
+ if (flags&HASWIDTH)
+ *flagp |= HASWIDTH;
if (c == '|') {
lastbr = reganode(IFTHEN, 0); /* Fake one for optimizer. */
regbranch(&flags, 1);
regtail(ret, lastbr);
+ if (flags&HASWIDTH)
+ *flagp |= HASWIDTH;
c = *nextchar();
}
else
}
/* Check for proper termination. */
- if (paren && (PL_regcomp_parse >= PL_regxend || *nextchar() != ')')) {
- FAIL("unmatched () in regexp");
+ if (paren) {
+ PL_regflags = oregflags;
+ if (PL_regcomp_parse >= PL_regxend || *nextchar() != ')') {
+ FAIL("unmatched () in regexp");
+ }
}
else if (!paren && PL_regcomp_parse < PL_regxend) {
if (*PL_regcomp_parse == ')') {
FAIL("junk on end of regexp"); /* "Can't happen". */
/* NOTREACHED */
}
- if (paren != 0) {
- PL_regflags = oregflags;
- }
return(ret);
}
goto do_curly;
}
nest_check:
- if (PL_dowarn && !SIZE_ONLY && !(flags&HASWIDTH) && max > 10000) {
- warn("%.*s matches null string many times",
+ if (ckWARN(WARN_UNSAFE) && !SIZE_ONLY && !(flags&HASWIDTH) && max > REG_INFTY/3) {
+ warner(WARN_UNSAFE, "%.*s matches null string many times",
PL_regcomp_parse - origparse, origparse);
}
if (PL_regflags & PMf_SINGLELINE)
ret = reg_node(SANY);
else
- ret = reg_node(ANY);
+ ret = reg_node(REG_ANY);
*flagp |= HASWIDTH|SIMPLE;
}
PL_regnaughty++;
case '[':
PL_regcomp_parse++;
ret = (UTF ? regclassutf8() : regclass());
+ if (*PL_regcomp_parse != ']')
+ FAIL("unmatched [] in regexp");
+ nextchar();
*flagp |= HASWIDTH|SIMPLE;
break;
case '(':
*flagp |= HASWIDTH;
nextchar();
if (UTF && !PL_utf8_mark)
- is_utf8_mark("~"); /* preload table */
+ is_utf8_mark((U8*)"~"); /* preload table */
break;
case 'w':
ret = reg_node(
*flagp |= HASWIDTH|SIMPLE;
nextchar();
if (UTF && !PL_utf8_alnum)
- is_utf8_alnum("a"); /* preload table */
+ is_utf8_alnum((U8*)"a"); /* preload table */
break;
case 'W':
ret = reg_node(
*flagp |= HASWIDTH|SIMPLE;
nextchar();
if (UTF && !PL_utf8_alnum)
- is_utf8_alnum("a"); /* preload table */
+ is_utf8_alnum((U8*)"a"); /* preload table */
break;
case 'b':
PL_seen_zerolen++;
+ PL_regseen |= REG_SEEN_LOOKBEHIND;
ret = reg_node(
UTF
? (LOC ? BOUNDLUTF8 : BOUNDUTF8)
*flagp |= SIMPLE;
nextchar();
if (UTF && !PL_utf8_alnum)
- is_utf8_alnum("a"); /* preload table */
+ is_utf8_alnum((U8*)"a"); /* preload table */
break;
case 'B':
PL_seen_zerolen++;
+ PL_regseen |= REG_SEEN_LOOKBEHIND;
ret = reg_node(
UTF
? (LOC ? NBOUNDLUTF8 : NBOUNDUTF8)
*flagp |= SIMPLE;
nextchar();
if (UTF && !PL_utf8_alnum)
- is_utf8_alnum("a"); /* preload table */
+ is_utf8_alnum((U8*)"a"); /* preload table */
break;
case 's':
ret = reg_node(
*flagp |= HASWIDTH|SIMPLE;
nextchar();
if (UTF && !PL_utf8_space)
- is_utf8_space(" "); /* preload table */
+ is_utf8_space((U8*)" "); /* preload table */
break;
case 'S':
ret = reg_node(
*flagp |= HASWIDTH|SIMPLE;
nextchar();
if (UTF && !PL_utf8_space)
- is_utf8_space(" "); /* preload table */
+ is_utf8_space((U8*)" "); /* preload table */
break;
case 'd':
ret = reg_node(UTF ? DIGITUTF8 : DIGIT);
*flagp |= HASWIDTH|SIMPLE;
nextchar();
if (UTF && !PL_utf8_digit)
- is_utf8_digit("1"); /* preload table */
+ is_utf8_digit((U8*)"1"); /* preload table */
break;
case 'D':
ret = reg_node(UTF ? NDIGITUTF8 : NDIGIT);
*flagp |= HASWIDTH|SIMPLE;
nextchar();
if (UTF && !PL_utf8_digit)
- is_utf8_digit("1"); /* preload table */
+ is_utf8_digit((U8*)"1"); /* preload table */
+ break;
+ case 'p':
+ case 'P':
+ { /* a lovely hack--pretend we saw [\pX] instead */
+ char* oldregxend = PL_regxend;
+
+ if (PL_regcomp_parse[1] == '{') {
+ PL_regxend = strchr(PL_regcomp_parse, '}');
+ if (!PL_regxend)
+ FAIL("Missing right brace on \\p{}");
+ PL_regxend++;
+ }
+ else
+ PL_regxend = PL_regcomp_parse + 2;
+ PL_regcomp_parse--;
+
+ ret = regclassutf8();
+
+ PL_regxend = oldregxend;
+ PL_regcomp_parse--;
+ nextchar();
+ *flagp |= HASWIDTH|SIMPLE;
+ }
break;
case 'n':
case 'r':
FAIL("trailing \\ in regexp");
/* FALL THROUGH */
default:
+ /* Do not generate `unrecognized' warnings here, we fall
+ back into the quick-grab loop below */
goto defchar;
}
break;
case 'S':
case 'd':
case 'D':
+ case 'p':
+ case 'P':
--p;
goto loopdone;
case 'n':
FAIL("trailing \\ in regexp");
/* FALL THROUGH */
default:
+ if (!SIZE_ONLY && ckWARN(WARN_UNSAFE) && isALPHA(*p))
+ warner(WARN_UNSAFE,
+ "/%.127s/: Unrecognized escape \\%c passed through",
+ PL_regprecomp,
+ *p);
goto normal_default;
}
break;
default:
normal_default:
if ((*p & 0xc0) == 0xc0 && UTF) {
- ender = utf8_to_uv(p, &numlen);
+ ender = utf8_to_uv((U8*)p, &numlen);
p += numlen;
}
else
return p;
}
+/* parse POSIX character classes like [[:foo:]] */
+STATIC char*
+regpposixcc(I32 value)
+{
+ dTHR;
+ char *posixcc = 0;
+
+ if (value == '[' && PL_regcomp_parse + 1 < PL_regxend &&
+ /* I smell either [: or [= or [. -- POSIX has been here, right? */
+ (*PL_regcomp_parse == ':' ||
+ *PL_regcomp_parse == '=' ||
+ *PL_regcomp_parse == '.')) {
+ char c = *PL_regcomp_parse;
+ char* s = PL_regcomp_parse++;
+
+ while (PL_regcomp_parse < PL_regxend && *PL_regcomp_parse != c)
+ PL_regcomp_parse++;
+ if (PL_regcomp_parse == PL_regxend)
+ /* Grandfather lone [:, [=, [. */
+ PL_regcomp_parse = s;
+ else {
+ PL_regcomp_parse++; /* skip over the c */
+ if (*PL_regcomp_parse == ']') {
+ /* Not Implemented Yet.
+ * (POSIX Extended Character Classes, that is)
+ * The text between e.g. [: and :] would start
+ * at s + 1 and stop at regcomp_parse - 2. */
+ if (ckWARN(WARN_UNSAFE) && !SIZE_ONLY)
+ warner(WARN_UNSAFE,
+ "Character class syntax [%c %c] is reserved for future extensions", c, c);
+ PL_regcomp_parse++; /* skip over the ending ] */
+ posixcc = s + 1;
+ }
+ }
+ }
+
+ return posixcc;
+}
+
STATIC regnode *
regclass(void)
{
while (PL_regcomp_parse < PL_regxend && *PL_regcomp_parse != ']') {
skipcond:
value = UCHARAT(PL_regcomp_parse++);
- if (value == '[' && PL_regcomp_parse + 1 < PL_regxend &&
- /* I smell either [: or [= or [. -- POSIX has been here, right? */
- (*PL_regcomp_parse == ':' || *PL_regcomp_parse == '=' || *PL_regcomp_parse == '.')) {
- char posixccc = *PL_regcomp_parse;
- char* posixccs = PL_regcomp_parse++;
-
- while (PL_regcomp_parse < PL_regxend && *PL_regcomp_parse != posixccc)
- PL_regcomp_parse++;
- if (PL_regcomp_parse == PL_regxend)
- /* Grandfather lone [:, [=, [. */
- PL_regcomp_parse = posixccs;
- else {
- PL_regcomp_parse++; /* skip over the posixccc */
- if (*PL_regcomp_parse == ']') {
- /* Not Implemented Yet.
- * (POSIX Extended Character Classes, that is)
- * The text between e.g. [: and :] would start
- * at posixccs + 1 and stop at regcomp_parse - 2. */
- if (dowarn && !SIZE_ONLY)
- warn("Character class syntax [%c %c] is reserved for future extensions", posixccc, posixccc);
- PL_regcomp_parse++; /* skip over the ending ] */
- }
- }
- }
- if (value == '\\') {
+ if (value == '[')
+ (void)regpposixcc(value); /* ignore the return value for now */
+ else if (value == '\\') {
value = UCHARAT(PL_regcomp_parse++);
switch (value) {
case 'w':
}
}
if (!SIZE_ONLY) {
- for ( ; lastvalue <= value; lastvalue++)
- ANYOF_SET(opnd, lastvalue);
- }
+#ifndef ASCIIish
+ if ((isLOWER(lastvalue) && isLOWER(value)) ||
+ (isUPPER(lastvalue) && isUPPER(value)))
+ {
+ I32 i;
+ if (isLOWER(lastvalue)) {
+ for (i = lastvalue; i <= value; i++)
+ if (isLOWER(i))
+ ANYOF_SET(opnd, i);
+ } else {
+ for (i = lastvalue; i <= value; i++)
+ if (isUPPER(i))
+ ANYOF_SET(opnd, i);
+ }
+ }
+ else
+#endif
+ for ( ; lastvalue <= value; lastvalue++)
+ ANYOF_SET(opnd, lastvalue);
+ }
lastvalue = value;
}
- if (*PL_regcomp_parse != ']')
- FAIL("unmatched [] in regexp");
- nextchar();
/* optimize case-insensitive simple patterns (e.g. /[a-z]/i) */
if (!SIZE_ONLY && (*opnd & (0xFF ^ ANYOF_INVERT)) == ANYOF_FOLD) {
for (value = 0; value < 256; ++value) {
if (ANYOF_TEST(opnd, value)) {
- I32 cf = fold[value];
+ I32 cf = PL_fold[value];
ANYOF_SET(opnd, cf);
}
}
while (PL_regcomp_parse < PL_regxend && *PL_regcomp_parse != ']') {
skipcond:
- value = utf8_to_uv(PL_regcomp_parse, &numlen);
+ value = utf8_to_uv((U8*)PL_regcomp_parse, &numlen);
PL_regcomp_parse += numlen;
- if (value == '[' && PL_regcomp_parse + 1 < PL_regxend &&
- /* I smell either [: or [= or [. -- POSIX has been here, right? */
- (*PL_regcomp_parse == ':' || *PL_regcomp_parse == '=' || *PL_regcomp_parse == '.')) {
- char posixccc = *PL_regcomp_parse;
- char* posixccs = PL_regcomp_parse++;
-
- while (PL_regcomp_parse < PL_regxend && *PL_regcomp_parse != posixccc)
- PL_regcomp_parse++;
- if (PL_regcomp_parse == PL_regxend)
- /* Grandfather lone [:, [=, [. */
- PL_regcomp_parse = posixccs;
- else {
- PL_regcomp_parse++; /* skip over the posixccc */
- if (*PL_regcomp_parse == ']') {
- /* Not Implemented Yet.
- * (POSIX Extended Character Classes, that is)
- * The text between e.g. [: and :] would start
- * at posixccs + 1 and stop at regcomp_parse - 2. */
- if (dowarn && !SIZE_ONLY)
- warn("Character class syntax [%c %c] is reserved for future extensions", posixccc, posixccc);
- PL_regcomp_parse++; /* skip over the ending ] */
- }
- }
- }
-
- if (value == '\\') {
- value = utf8_to_uv(PL_regcomp_parse, &numlen);
+ if (value == '[')
+ (void)regpposixcc(value); /* ignore the return value for now */
+ else if (value == '\\') {
+ value = utf8_to_uv((U8*)PL_regcomp_parse, &numlen);
PL_regcomp_parse += numlen;
switch (value) {
case 'w':
flags |= ANYOF_SPACEL;
sv_catpvf(listsv, "+utf8::IsSpace\n");
if (!PL_utf8_space)
- is_utf8_space(" ");
+ is_utf8_space((U8*)" ");
}
lastvalue = 123456;
continue;
sv_catpvf(listsv,
"!utf8::IsSpace\n");
if (!PL_utf8_space)
- is_utf8_space(" ");
+ is_utf8_space((U8*)" ");
}
lastvalue = 123456;
continue;
sv_catpvf(listsv, "%04x\n", value);
}
}
- if (*PL_regcomp_parse != ']')
- FAIL("unmatched [] in regexp");
- nextchar();
ret = reganode(ANYOFUTF8, 0);
{
dTHR;
if (SIZE_ONLY) {
- char tmpbuf[10];
+ U8 tmpbuf[10];
*lenp = uv_to_utf8(tmpbuf, uv) - tmpbuf;
}
else
- *lenp = uv_to_utf8(s, uv) - s;
+ *lenp = uv_to_utf8((U8*)s, uv) - (U8*)s;
}
register regnode *place;
register int offset = regarglen[(U8)op];
-/* (regkind[(U8)op] == CURLY ? EXTRA_STEP_2ARGS : 0); */
+/* (PL_regkind[(U8)op] == CURLY ? EXTRA_STEP_2ARGS : 0); */
if (SIZE_ONLY) {
PL_regsize += NODE_STEP_REGNODE + offset;
/* "Operandless" and "op != BRANCH" are synonymous in practice. */
if (p == NULL || SIZE_ONLY)
return;
- if (regkind[(U8)OP(p)] == BRANCH) {
+ if (PL_regkind[(U8)OP(p)] == BRANCH) {
regtail(NEXTOPER(p), val);
}
- else if ( regkind[(U8)OP(p)] == BRANCHJ) {
+ else if ( PL_regkind[(U8)OP(p)] == BRANCHJ) {
regtail(NEXTOPER(NEXTOPER(p)), val);
}
else
PerlIO_printf(Perl_debug_log, "(%d)", next - start);
(void)PerlIO_putc(Perl_debug_log, '\n');
after_print:
- if (regkind[(U8)op] == BRANCHJ) {
+ if (PL_regkind[(U8)op] == BRANCHJ) {
register regnode *nnode = (OP(next) == LONGJMP
? regnext(next)
: next);
nnode = last;
node = dumpuntil(start, NEXTOPER(NEXTOPER(node)), nnode, sv, l + 1);
}
- else if (regkind[(U8)op] == BRANCH) {
+ else if (PL_regkind[(U8)op] == BRANCH) {
node = dumpuntil(start, NEXTOPER(node), next, sv, l + 1);
}
else if ( op == CURLY) { /* `next' might be very big: optimizer */
node = dumpuntil(start, NEXTOPER(node) + EXTRA_STEP_2ARGS,
NEXTOPER(node) + EXTRA_STEP_2ARGS + 1, sv, l + 1);
}
- else if (regkind[(U8)op] == CURLY && op != CURLYX) {
+ else if (PL_regkind[(U8)op] == CURLY && op != CURLYX) {
node = dumpuntil(start, NEXTOPER(node) + EXTRA_STEP_2ARGS,
next, sv, l + 1);
}
node = NEXTOPER(node);
node += ANY_SKIP;
}
- else if (regkind[(U8)op] == EXACT) {
+ else if (PL_regkind[(U8)op] == EXACT) {
/* Literal string, where present. */
node += ((*OPERAND(node)) + 2 + sizeof(regnode) - 1) / sizeof(regnode);
node = NEXTOPER(node);
case SEOL:
p = "SEOL";
break;
- case ANY:
+ case REG_ANY:
p = "ANY";
break;
case SANY:
sv_catpvf(sv, "GROUPP%d", ARG(o));
break;
case LOGICAL:
- p = "LOGICAL";
+ sv_catpvf(sv, "LOGICAL[%d]", o->flags);
break;
case SUSPEND:
p = "SUSPEND";
}
if (r->data) {
int n = r->data->count;
+ AV* new_comppad = NULL;
+ AV* old_comppad;
+ SV** old_curpad;
+
while (--n >= 0) {
switch (r->data->what[n]) {
case 's':
SvREFCNT_dec((SV*)r->data->data[n]);
break;
+ case 'p':
+ new_comppad = (AV*)r->data->data[n];
+ break;
case 'o':
+ if (new_comppad == NULL)
+ croak("panic: pregfree comppad");
+ old_comppad = PL_comppad;
+ old_curpad = PL_curpad;
+ PL_comppad = new_comppad;
+ PL_curpad = AvARRAY(new_comppad);
op_free((OP_4tree*)r->data->data[n]);
+ PL_comppad = old_comppad;
+ PL_curpad = old_curpad;
+ SvREFCNT_dec((SV*)new_comppad);
+ new_comppad = NULL;
break;
case 'n':
break;
SAVESPTR(PL_regcode); /* Code-emit pointer; ®dummy = don't */
SAVEPPTR(PL_regxend); /* End of input for compile */
SAVEPPTR(PL_regcomp_parse); /* Input-scan pointer. */
+ SAVESPTR(PL_reg_call_cc); /* from regexec.c */
+ SAVESPTR(PL_reg_re); /* from regexec.c */
+ SAVEPPTR(PL_reg_ganch); /* from regexec.c */
+ SAVESPTR(PL_reg_sv); /* from regexec.c */
+ SAVESPTR(PL_reg_magic); /* from regexec.c */
+ SAVEI32(PL_reg_oldpos); /* from regexec.c */
+ SAVESPTR(PL_reg_oldcurpm); /* from regexec.c */
+ SAVESPTR(PL_reg_curpm); /* from regexec.c */
+#ifdef DEBUGGING
+ SAVEPPTR(PL_reg_starttry); /* from regexec.c */
+#endif
}