# 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;
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
*
PL_reg_flags = 0;
PL_regprecomp = savepvn(exp, xend - exp);
- DEBUG_r(
- if (!PL_colorset) {
- 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] = "";
- }
- } else {
- while (i < 6)
- PL_colors[i++] = "";
- }
- PL_colorset = 1;
- }
- );
+ 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_colors[4],PL_colors[5],PL_colors[0],
+ xend - exp, PL_regprecomp, PL_colors[1]));
PL_regflags = pm->op_pmflags;
PL_regsawback = 0;
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. */
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 */
}
/* 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);
}
break;
case 'b':
PL_seen_zerolen++;
+ PL_regseen |= REG_SEEN_LOOKBEHIND;
ret = reg_node(
UTF
? (LOC ? BOUNDLUTF8 : BOUNDUTF8)
break;
case 'B':
PL_seen_zerolen++;
+ PL_regseen |= REG_SEEN_LOOKBEHIND;
ret = reg_node(
UTF
? (LOC ? NBOUNDLUTF8 : NBOUNDUTF8)
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;
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;
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 (ckWARN(WARN_UNSAFE) && !SIZE_ONLY)
- warner(WARN_UNSAFE,
- "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':
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 (ckWARN(WARN_UNSAFE) && !SIZE_ONLY)
- warner(WARN_UNSAFE,
- "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 = utf8_to_uv((U8*)PL_regcomp_parse, &numlen);
PL_regcomp_parse += numlen;
switch (value) {
}
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
}