*
**** Alterations to Henry's code are...
****
- **** Copyright (c) 1991-1998, Larry Wall
+ **** Copyright (c) 1991-1999, Larry Wall
****
**** You may distribute under the terms of either the GNU General Public
**** License or the Artistic License, as specified in the README file.
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. */
} scan_data_t;
#endif
-static scan_data_t zero_scan_data = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+static scan_data_t zero_scan_data = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0 };
#define SF_BEFORE_EOL (SF_BEFORE_SEOL|SF_BEFORE_MEOL)
#define SF_BEFORE_SEOL 0x1
#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;
l -= old;
/* Get the added string: */
- last_str = newSVpv(s + old, l);
+ last_str = newSVpvn(s + old, l);
if (deltanext == 0 && pos_before == b) {
/* What was added is a constant string */
if (mincount > 1) {
PL_colors[i] = ++s;
}
else
- PL_colors[i] = "";
+ PL_colors[i] = s = "";
}
} else {
while (i < 6)
PL_reg_flags = 0;
PL_regprecomp = savepvn(exp, xend - exp);
- DEBUG_r(
- if (!PL_colorset)
- reginitcolors();
- PerlIO_printf(Perl_debug_log, "%sCompiling%s RE `%s%*s%s'\n",
+ 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;
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. */
*/
minlen = 0;
- data.longest_fixed = newSVpv("",0);
- data.longest_float = newSVpv("",0);
- data.last_found = newSVpv("",0);
+ data.longest_fixed = newSVpvn("",0);
+ data.longest_float = newSVpvn("",0);
+ data.last_found = newSVpvn("",0);
data.longest = &(data.longest_fixed);
first = scan;
AV *av;
if (PL_regcomp_parse - 1 - s)
- sv = newSVpv(s, PL_regcomp_parse - 1 - s);
+ sv = newSVpvn(s, PL_regcomp_parse - 1 - s);
else
- sv = newSVpv("", 0);
+ sv = newSVpvn("", 0);
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':
flags |= ANYOF_FOLD;
if (LOC)
flags |= ANYOF_LOCALE;
- listsv = newSVpv("# comment\n",0);
+ listsv = newSVpvn("# comment\n",10);
}
if (*PL_regcomp_parse == ']' || *PL_regcomp_parse == '-')
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) {
e = strchr(PL_regcomp_parse++, '}');
if (!e)
FAIL("Missing right brace on \\x{}");
- value = scan_hex(PL_regcomp_parse + 1, e - PL_regcomp_parse, &numlen);
+ value = scan_hex(PL_regcomp_parse, e - PL_regcomp_parse, &numlen);
PL_regcomp_parse = e + 1;
}
else {
}
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;
STRLEN l1 = strlen(pat1);
STRLEN l2 = strlen(pat2);
char buf[512];
+ SV *msv;
char *message;
if (l1 > 510)
buf[l1 + l2] = '\n';
buf[l1 + l2 + 1] = '\0';
va_start(args, pat2);
- message = mess(buf, &args);
+ msv = mess(buf, &args);
va_end(args);
- l1 = strlen(message);
+ message = SvPV(msv,l1);
if (l1 > 512)
l1 = 512;
Copy(message, buf, l1 , char);
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
}