* of t/op/regmesg.t, the tests in t/op/re_tests, and those in
* op/pragma/warn/regcomp.
*/
-#define MARKER1 "HERE" /* marker as it appears in the description */
-#define MARKER2 " << HERE " /* marker as it appears within the regex */
+#define MARKER1 "<-- HERE" /* marker as it appears in the description */
+#define MARKER2 " <-- HERE " /* marker as it appears within the regex */
-#define REPORT_LOCATION " before " MARKER1 " mark in regex m/%.*s" MARKER2 "%s/"
+#define REPORT_LOCATION " in regex; marked by " MARKER1 " in m/%.*s" MARKER2 "%s/"
/*
* Calls SAVEDESTRUCTOR_X if needed, then calls Perl_croak with the given
m, (int)offset, RExC_precomp, RExC_precomp + offset); \
} STMT_END \
+#define vWARNdep(loc,m) \
+ STMT_START { \
+ unsigned offset = strlen(RExC_precomp)-(RExC_end-(loc)); \
+ int warn_cat = ckWARN(WARN_REGEXP) ? WARN_REGEXP : WARN_DEPRECATED; \
+ Perl_warner(aTHX_ warn_cat, "%s" REPORT_LOCATION,\
+ m, (int)offset, RExC_precomp, RExC_precomp + offset); \
+ } STMT_END \
+
#define vWARN2(loc, m, a1) \
STMT_START { \
(int)offset, RExC_precomp, RExC_precomp + offset); \
} STMT_END
+/* used for the parse_flags section for (?c) -- japhy */
+#define vWARN5(loc, m, a1, a2, a3, a4) \
+ STMT_START { \
+ unsigned offset = strlen(RExC_precomp)-(RExC_end-(loc)); \
+ Perl_warner(aTHX_ WARN_REGEXP, m REPORT_LOCATION, \
+ a1, a2, a3, a4, \
+ (int)offset, RExC_precomp, RExC_precomp + offset); \
+ } STMT_END
+
/* Allow for side effects in s */
-#define REGC(c,s) STMT_START { if (!SIZE_ONLY) *(s) = (c); else (s);} STMT_END
+#define REGC(c,s) STMT_START { if (!SIZE_ONLY) *(s) = (c); else (void)(s);} STMT_END
/* Macros for recording node offsets. 20001227 mjd@plover.com
* Nodes are numbered 1, 2, 3, 4. Node #n's position is recorded in
int compat = 1;
if (uc >= 0x100 ||
- !(data->start_class->flags & (ANYOF_CLASS | ANYOF_LOCALE))
+ (!(data->start_class->flags & (ANYOF_CLASS | ANYOF_LOCALE))
&& !ANYOF_BITMAP_TEST(data->start_class, uc)
&& (!(data->start_class->flags & ANYOF_FOLD)
|| !ANYOF_BITMAP_TEST(data->start_class, PL_fold[uc])))
+ )
compat = 0;
ANYOF_CLASS_ZERO(data->start_class);
ANYOF_BITMAP_ZERO(data->start_class);
int compat = 1;
if (uc >= 0x100 ||
- !(data->start_class->flags & (ANYOF_CLASS | ANYOF_LOCALE))
+ (!(data->start_class->flags & (ANYOF_CLASS | ANYOF_LOCALE))
&& !ANYOF_BITMAP_TEST(data->start_class, uc)
- && !ANYOF_BITMAP_TEST(data->start_class, PL_fold[uc]))
+ && !ANYOF_BITMAP_TEST(data->start_class, PL_fold[uc])))
compat = 0;
ANYOF_CLASS_ZERO(data->start_class);
ANYOF_BITMAP_ZERO(data->start_class);
flags &= ~SCF_DO_STCLASS;
}
else if (strchr((char*)PL_varies,OP(scan))) {
- I32 mincount, maxcount, minnext, deltanext, fl;
+ I32 mincount, maxcount, minnext, deltanext, fl = 0;
I32 f = flags, pos_before = 0;
regnode *oscan = scan;
struct regnode_charclass_class this_class;
}
if (!scan) /* It was not CURLYX, but CURLY. */
scan = next;
- if (ckWARN(WARN_REGEXP) && (minnext + deltanext == 0)
- && !(data->flags & (SF_HAS_PAR|SF_IN_PAR))
+ if (ckWARN(WARN_REGEXP)
+ && (minnext == 0) && (deltanext == 0)
+ && data && !(data->flags & (SF_HAS_PAR|SF_IN_PAR))
&& maxcount <= REG_INFTY/3) /* Complement check for big count */
{
vWARN(RExC_parse,
&& !deltanext && minnext == 1 ) {
/* Try to optimize to CURLYN. */
regnode *nxt = NEXTOPER(oscan) + EXTRA_STEP_2ARGS;
- regnode *nxt1 = nxt, *nxt2;
+ regnode *nxt1 = nxt;
+#ifdef DEBUGGING
+ regnode *nxt2;
+#endif
/* Skip open. */
nxt = regnext(nxt);
&& !(PL_regkind[(U8)OP(nxt)] == EXACT
&& STR_LEN(nxt) == 1))
goto nogo;
+#ifdef DEBUGGING
nxt2 = nxt;
+#endif
nxt = regnext(nxt);
if (OP(nxt) != CLOSE)
goto nogo;
}
}
else if (strchr((char*)PL_simple,OP(scan))) {
- int value;
+ int value = 0;
if (flags & SCF_DO_SUBSTR) {
scan_commit(pRExC_state,data);
if ((!r->anchored_substr || r->anchored_offset) && stclass_flag
&& !(data.start_class->flags & ANYOF_EOS)
&& !cl_is_anything(data.start_class)) {
- SV *sv;
I32 n = add_data(pRExC_state, 1, "f");
New(1006, RExC_rx->data->data[n], 1,
r->regstclass = (regnode*)RExC_rx->data->data[n];
r->reganch &= ~ROPT_SKIP; /* Used in find_byclass(). */
PL_regdata = r->data; /* for regprop() */
- DEBUG_r((sv = sv_newmortal(),
- regprop(sv, (regnode*)data.start_class),
- PerlIO_printf(Perl_debug_log, "synthetic stclass `%s'.\n",
- SvPVX(sv))));
+ DEBUG_r({ SV *sv = sv_newmortal();
+ regprop(sv, (regnode*)data.start_class);
+ PerlIO_printf(Perl_debug_log,
+ "synthetic stclass `%s'.\n",
+ SvPVX(sv));});
}
/* A temporary algorithm prefers floated substr to fixed one to dig more info. */
r->check_substr = r->anchored_substr = r->float_substr = Nullsv;
if (!(data.start_class->flags & ANYOF_EOS)
&& !cl_is_anything(data.start_class)) {
- SV *sv;
I32 n = add_data(pRExC_state, 1, "f");
New(1006, RExC_rx->data->data[n], 1,
struct regnode_charclass_class);
r->regstclass = (regnode*)RExC_rx->data->data[n];
r->reganch &= ~ROPT_SKIP; /* Used in find_byclass(). */
- DEBUG_r((sv = sv_newmortal(),
- regprop(sv, (regnode*)data.start_class),
- PerlIO_printf(Perl_debug_log, "synthetic stclass `%s'.\n",
- SvPVX(sv))));
+ DEBUG_r({ SV* sv = sv_newmortal();
+ regprop(sv, (regnode*)data.start_class);
+ PerlIO_printf(Perl_debug_log,
+ "synthetic stclass `%s'.\n",
+ SvPVX(sv));});
}
}
r->reganch |= ROPT_LOOKBEHIND_SEEN;
if (RExC_seen & REG_SEEN_EVAL)
r->reganch |= ROPT_EVAL_SEEN;
- if (RExC_seen & REG_SEEN_SANY)
- r->reganch |= ROPT_SANY_SEEN;
+ if (RExC_seen & REG_SEEN_CANY)
+ r->reganch |= ROPT_CANY_SEEN;
Newz(1002, r->startp, RExC_npar, I32);
Newz(1002, r->endp, RExC_npar, I32);
PL_regdata = r->data; /* for regprop() */
register regnode *ender = 0;
register I32 parno = 0;
I32 flags, oregflags = RExC_flags16, have_branch = 0, open = 0;
+
+ /* for (?g), (?gc), and (?o) warnings; warning
+ about (?c) will warn about (?g) -- japhy */
+
+ I32 wastedflags = 0x00,
+ wasted_o = 0x01,
+ wasted_g = 0x02,
+ wasted_gc = 0x02 | 0x04,
+ wasted_c = 0x04;
+
char * parse_start = RExC_parse; /* MJD */
char *oregcomp_parse = RExC_parse;
char c;
*flagp = 0; /* Tentatively. */
+
/* Make an OPEN node, if parenthesized. */
if (paren) {
if (*RExC_parse == '?') { /* (?...) */
*flagp = TRYAGAIN;
return NULL;
case 'p': /* (?p...) */
- if (SIZE_ONLY)
- vWARN(RExC_parse, "(?p{}) is deprecated - use (??{})");
+ if (SIZE_ONLY && ckWARN2(WARN_DEPRECATED, WARN_REGEXP))
+ vWARNdep(RExC_parse, "(?p{}) is deprecated - use (??{})");
/* FALL THROUGH*/
case '?': /* (??...) */
logical = 1;
ENTER;
Perl_save_re_context(aTHX);
rop = sv_compile_2op(sv, &sop, "re", &av);
+ sop->op_private |= OPpREFCOUNTED;
+ /* re_dup will OpREFCNT_inc */
+ OpREFCNT_set(sop, 1);
LEAVE;
n = add_data(pRExC_state, 3, "nop");
/* No compiled RE interpolated, has runtime
components ===> unsafe. */
FAIL("Eval-group not allowed at runtime, use re 'eval'");
- if (PL_tainted)
+ if (PL_tainting && PL_tainted)
FAIL("Eval-group in insecure regular expression");
}
--RExC_parse;
parse_flags: /* (?i) */
while (*RExC_parse && strchr("iogcmsx", *RExC_parse)) {
- if (*RExC_parse != 'o')
- pmflag(flagsp, *RExC_parse);
+ /* (?g), (?gc) and (?o) are useless here
+ and must be globally applied -- japhy */
+
+ if (*RExC_parse == 'o' || *RExC_parse == 'g') {
+ if (SIZE_ONLY && ckWARN(WARN_REGEXP)) {
+ I32 wflagbit = *RExC_parse == 'o' ? wasted_o : wasted_g;
+ if (! (wastedflags & wflagbit) ) {
+ wastedflags |= wflagbit;
+ vWARN5(
+ RExC_parse + 1,
+ "Useless (%s%c) - %suse /%c modifier",
+ flagsp == &negflags ? "?-" : "?",
+ *RExC_parse,
+ flagsp == &negflags ? "don't " : "",
+ *RExC_parse
+ );
+ }
+ }
+ }
+ else if (*RExC_parse == 'c') {
+ if (SIZE_ONLY && ckWARN(WARN_REGEXP)) {
+ if (! (wastedflags & wasted_c) ) {
+ wastedflags |= wasted_gc;
+ vWARN3(
+ RExC_parse + 1,
+ "Useless (%sc) - %suse /gc modifier",
+ flagsp == &negflags ? "?-" : "?",
+ flagsp == &negflags ? "don't " : ""
+ );
+ }
+ }
+ }
+ else { pmflag(flagsp, *RExC_parse); }
+
++RExC_parse;
}
if (*RExC_parse == '-') {
flagsp = &negflags;
+ wastedflags = 0; /* reset so (?g-c) warns twice */
++RExC_parse;
goto parse_flags;
}
{
register regnode *ret = 0;
I32 flags;
- char *parse_start = RExC_parse;
+ char *parse_start = 0;
*flagp = WORST; /* Tentatively. */
Set_Node_Length(ret, 2); /* MJD */
break;
case 'C':
- ret = reg_node(pRExC_state, SANY);
- RExC_seen |= REG_SEEN_SANY;
+ ret = reg_node(pRExC_state, CANY);
+ RExC_seen |= REG_SEEN_CANY;
*flagp |= HASWIDTH|SIMPLE;
nextchar(pRExC_state);
Set_Node_Length(ret, 2); /* MJD */
register char *p;
char *oldp, *s;
STRLEN numlen;
- char *parse_start = RExC_parse - 1;
+
+ parse_start = RExC_parse - 1;
RExC_parse++;
register regnode *ret;
STRLEN numlen;
IV namedclass;
- char *rangebegin;
+ char *rangebegin = 0;
bool need_class = 0;
- SV *listsv;
+ SV *listsv = Nullsv;
register char *e;
- char *parse_start = RExC_parse; /* MJD */
UV n;
bool optimize_invert = TRUE;
ANYOF_BITMAP_SET(ret, value);
#else /* EBCDIC */
for (value = 0; value < 256; value++) {
- if (PL_hints & HINT_RE_ASCIIR) {
- if (NATIVE_TO_ASCII(value) < 128)
- ANYOF_BITMAP_SET(ret, value);
- }
- else {
- if (isASCII(value))
- ANYOF_BITMAP_SET(ret, value);
- }
+ if (isASCII(value))
+ ANYOF_BITMAP_SET(ret, value);
}
#endif /* EBCDIC */
}
ANYOF_BITMAP_SET(ret, value);
#else /* EBCDIC */
for (value = 0; value < 256; value++) {
- if (PL_hints & HINT_RE_ASCIIR) {
- if (NATIVE_TO_ASCII(value) >= 128)
- ANYOF_BITMAP_SET(ret, value);
- }
- else {
- if (!isASCII(value))
- ANYOF_BITMAP_SET(ret, value);
- }
+ if (!isASCII(value))
+ ANYOF_BITMAP_SET(ret, value);
}
#endif /* EBCDIC */
}
} /* end of namedclass \blah */
if (range) {
- if (((prevvalue > value) && !(PL_hints & HINT_RE_ASCIIR)) ||
- ((NATIVE_TO_UNI(prevvalue) > NATIVE_TO_UNI(value)) &&
- (PL_hints & HINT_RE_ASCIIR))) /* b-a */ {
+ if (prevvalue > value) /* b-a */ {
Simple_vFAIL4("Invalid [] range \"%*.*s\"",
RExC_parse - rangebegin,
RExC_parse - rangebegin,
IV ceilvalue = value < 256 ? value : 255;
#ifdef EBCDIC
- if (PL_hints & HINT_RE_ASCIIR) {
- /* New style scheme for ranges:
- * use re 'asciir';
- * do ranges in ASCII/Unicode space
- */
- for (i = NATIVE_TO_ASCII(prevvalue);
- i <= NATIVE_TO_ASCII(ceilvalue);
- i++)
- ANYOF_BITMAP_SET(ret, ASCII_TO_NATIVE(i));
- }
- else if ((isLOWER(prevvalue) && isLOWER(ceilvalue)) ||
- (isUPPER(prevvalue) && isUPPER(ceilvalue)))
+ if ((isLOWER(prevvalue) && isLOWER(ceilvalue)) ||
+ (isUPPER(prevvalue) && isUPPER(ceilvalue)))
{
if (isLOWER(prevvalue)) {
for (i = prevvalue; i <= ceilvalue; i++)
/* optimize case-insensitive simple patterns (e.g. /[a-z]/i) */
if (!SIZE_ONLY &&
- (ANYOF_FLAGS(ret) &
/* If the only flag is folding (plus possibly inversion). */
- (ANYOF_FLAGS_ALL ^ ANYOF_INVERT) == ANYOF_FOLD)) {
+ ((ANYOF_FLAGS(ret) & (ANYOF_FLAGS_ALL ^ ANYOF_INVERT)) == ANYOF_FOLD)
+ ) {
for (value = 0; value < 256; ++value) {
if (ANYOF_BITMAP_TEST(ret, value)) {
IV fold = PL_fold[value];
}
+#ifdef DEBUGGING
+
STATIC regnode *
S_dumpuntil(pTHX_ regnode *start, regnode *node, regnode *last, SV* sv, I32 l)
{
-#ifdef DEBUGGING
register U8 op = EXACT; /* Arbitrary non-END op. */
register regnode *next;
else if (op == WHILEM)
l--;
}
-#endif /* DEBUGGING */
return node;
}
+#endif /* DEBUGGING */
+
/*
- regdump - dump a regexp onto Perl_debug_log in vaguely comprehensible form
*/
#endif /* DEBUGGING */
}
+#ifdef DEBUGGING
+
STATIC void
S_put_byte(pTHX_ SV *sv, int c)
{
- if (isCNTRL(c) || c == 127 || c == 255 || !isPRINT(c))
+ if (isCNTRL(c) || c == 255 || !isPRINT(c))
Perl_sv_catpvf(aTHX_ sv, "\\%o", c);
else if (c == '-' || c == ']' || c == '\\' || c == '^')
Perl_sv_catpvf(aTHX_ sv, "\\%c", c);
Perl_sv_catpvf(aTHX_ sv, "%c", c);
}
+#endif /* DEBUGGING */
+
/*
- regprop - printable representation of opcode
*/
SV** old_curpad;
while (--n >= 0) {
+ /* If you add a ->what type here, update the comment in regcomp.h */
switch (r->data->what[n]) {
case 's':
SvREFCNT_dec((SV*)r->data->data[n]);
}
else
PL_curpad = NULL;
- op_free((OP_4tree*)r->data->data[n]);
+
+ if (!OpREFCNT_dec((OP_4tree*)r->data->data[n])) {
+ op_free((OP_4tree*)r->data->data[n]);
+ }
+
PL_comppad = old_comppad;
PL_curpad = old_curpad;
SvREFCNT_dec((SV*)new_comppad);
SAVEVPTR(PL_reg_oldcurpm); /* from regexec.c */
SAVEVPTR(PL_reg_curpm); /* from regexec.c */
SAVEI32(PL_regnpar); /* () count. */
+ SAVEI32(PL_regsize); /* from regexec.c */
#ifdef DEBUGGING
SAVEPPTR(PL_reg_starttry); /* from regexec.c */
#endif