* "A fair jaw-cracker dwarf-language must be." --Samwise Gamgee
*/
+/* This file contains functions for compiling a regular expression. See
+ * also regexec.c which funnily enough, contains functions for executing
+ * a regular expression.
+ *
+ * This file is also copied at build time to ext/re/re_comp.c, where
+ * it's built with -DPERL_EXT_RE_BUILD -DPERL_EXT_RE_DEBUG -DPERL_EXT.
+ * This causes the main functions to be compiled under new names and with
+ * debugging support added, which makes "use re 'debug'" work.
+ */
+
/* NOTE: this is derived from Henry Spencer's regexp code, and should not
* confused with the original package (see point 3 below). Thanks, Henry!
*/
**** Alterations to Henry's code are...
****
**** Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- **** 2000, 2001, 2002, 2003, by Larry Wall and others
+ **** 2000, 2001, 2002, 2003, 2004, 2005, by Larry Wall and others
****
**** You may distribute under the terms of either the GNU General Public
**** License or the Artistic License, as specified in the README file.
#endif /* op */
#ifdef MSDOS
-# if defined(BUGGY_MSC6)
+# if defined(BUGGY_MSC6)
/* MSC 6.00A breaks on op/regexp.t test 85 unless we turn this off */
- # pragma optimize("a",off)
+# pragma optimize("a",off)
/* But MSC 6.00A is happy with 'w', for aliases only across function calls*/
- # pragma optimize("w",on )
-# endif /* BUGGY_MSC6 */
+# pragma optimize("w",on )
+# endif /* BUGGY_MSC6 */
#endif /* MSDOS */
#ifndef STATIC
if ( OP(oscan) == CURLYX && data
&& !(data->flags & SF_HAS_PAR)
&& !(data->flags & SF_HAS_EVAL)
- && !deltanext ) {
+ && !deltanext /* atom is fixed width */
+ && minnext != 0 /* CURLYM can't handle zero width */
+ ) {
/* XXXX How to optimize if data == 0? */
/* Optimize to a simpler form. */
regnode *nxt = NEXTOPER(oscan) + EXTRA_STEP_2ARGS; /* OPEN */
if (paren == '>')
node = SUSPEND, flag = 0;
reginsert(pRExC_state, node,ret);
- Set_Node_Offset(ret, oregcomp_parse);
- Set_Node_Length(ret, RExC_parse - oregcomp_parse + 2);
+ Set_Node_Cur_Length(ret);
+ Set_Node_Offset(ret, parse_start + 1);
ret->flags = flag;
regtail(pRExC_state, ret, reg_node(pRExC_state, TAIL));
}
{
register regnode *ret = 0;
I32 flags;
- char *parse_start = 0;
+ char *parse_start = RExC_parse;
*flagp = WORST; /* Tentatively. */
default:
/* Do not generate `unrecognized' warnings here, we fall
back into the quick-grab loop below */
+ parse_start--;
goto defchar;
}
break;
char *oldp, *s;
STRLEN numlen;
STRLEN foldlen;
- U8 tmpbuf[UTF8_MAXLEN_FOLD+1], *foldbuf;
+ U8 tmpbuf[UTF8_MAXBYTES_CASE+1], *foldbuf;
parse_start = RExC_parse - 1;
else {
char* t = RExC_parse++; /* skip over the c */
+ assert(*t == c);
+
if (UCHARAT(RExC_parse) == ']') {
RExC_parse++; /* skip over the ending ] */
posixcc = s + 1;
if (*s == ':') {
I32 complement = *posixcc == '^' ? *posixcc++ : 0;
- I32 skip = 5; /* the most common skip */
-
- switch (*posixcc) {
- case 'a':
- if (strnEQ(posixcc, "alnum", 5))
- namedclass =
- complement ? ANYOF_NALNUMC : ANYOF_ALNUMC;
- else if (strnEQ(posixcc, "alpha", 5))
- namedclass =
- complement ? ANYOF_NALPHA : ANYOF_ALPHA;
- else if (strnEQ(posixcc, "ascii", 5))
- namedclass =
- complement ? ANYOF_NASCII : ANYOF_ASCII;
- break;
- case 'b':
- if (strnEQ(posixcc, "blank", 5))
- namedclass =
- complement ? ANYOF_NBLANK : ANYOF_BLANK;
- break;
- case 'c':
- if (strnEQ(posixcc, "cntrl", 5))
- namedclass =
- complement ? ANYOF_NCNTRL : ANYOF_CNTRL;
- break;
- case 'd':
- if (strnEQ(posixcc, "digit", 5))
- namedclass =
- complement ? ANYOF_NDIGIT : ANYOF_DIGIT;
- break;
- case 'g':
- if (strnEQ(posixcc, "graph", 5))
- namedclass =
- complement ? ANYOF_NGRAPH : ANYOF_GRAPH;
- break;
- case 'l':
- if (strnEQ(posixcc, "lower", 5))
- namedclass =
- complement ? ANYOF_NLOWER : ANYOF_LOWER;
- break;
- case 'p':
- if (strnEQ(posixcc, "print", 5))
- namedclass =
- complement ? ANYOF_NPRINT : ANYOF_PRINT;
- else if (strnEQ(posixcc, "punct", 5))
- namedclass =
- complement ? ANYOF_NPUNCT : ANYOF_PUNCT;
- break;
- case 's':
- if (strnEQ(posixcc, "space", 5))
- namedclass =
- complement ? ANYOF_NPSXSPC : ANYOF_PSXSPC;
+ I32 skip = t - posixcc;
+
+ /* Initially switch on the length of the name. */
+ switch (skip) {
+ case 4:
+ if (memEQ(posixcc, "word", 4)) {
+ /* this is not POSIX, this is the Perl \w */;
+ namedclass
+ = complement ? ANYOF_NALNUM : ANYOF_ALNUM;
+ }
break;
- case 'u':
- if (strnEQ(posixcc, "upper", 5))
- namedclass =
- complement ? ANYOF_NUPPER : ANYOF_UPPER;
- break;
- case 'w': /* this is not POSIX, this is the Perl \w */
- if (strnEQ(posixcc, "word", 4)) {
- namedclass =
- complement ? ANYOF_NALNUM : ANYOF_ALNUM;
- skip = 4;
+ case 5:
+ /* Names all of length 5. */
+ /* alnum alpha ascii blank cntrl digit graph lower
+ print punct space upper */
+ /* Offset 4 gives the best switch position. */
+ switch (posixcc[4]) {
+ case 'a':
+ if (memEQ(posixcc, "alph", 4)) {
+ /* a */
+ namedclass
+ = complement ? ANYOF_NALPHA : ANYOF_ALPHA;
+ }
+ break;
+ case 'e':
+ if (memEQ(posixcc, "spac", 4)) {
+ /* e */
+ namedclass
+ = complement ? ANYOF_NPSXSPC : ANYOF_PSXSPC;
+ }
+ break;
+ case 'h':
+ if (memEQ(posixcc, "grap", 4)) {
+ /* h */
+ namedclass
+ = complement ? ANYOF_NGRAPH : ANYOF_GRAPH;
+ }
+ break;
+ case 'i':
+ if (memEQ(posixcc, "asci", 4)) {
+ /* i */
+ namedclass
+ = complement ? ANYOF_NASCII : ANYOF_ASCII;
+ }
+ break;
+ case 'k':
+ if (memEQ(posixcc, "blan", 4)) {
+ /* k */
+ namedclass
+ = complement ? ANYOF_NBLANK : ANYOF_BLANK;
+ }
+ break;
+ case 'l':
+ if (memEQ(posixcc, "cntr", 4)) {
+ /* l */
+ namedclass
+ = complement ? ANYOF_NCNTRL : ANYOF_CNTRL;
+ }
+ break;
+ case 'm':
+ if (memEQ(posixcc, "alnu", 4)) {
+ /* m */
+ namedclass
+ = complement ? ANYOF_NALNUMC : ANYOF_ALNUMC;
+ }
+ break;
+ case 'r':
+ if (memEQ(posixcc, "lowe", 4)) {
+ /* r */
+ namedclass
+ = complement ? ANYOF_NLOWER : ANYOF_LOWER;
+ }
+ if (memEQ(posixcc, "uppe", 4)) {
+ /* r */
+ namedclass
+ = complement ? ANYOF_NUPPER : ANYOF_UPPER;
+ }
+ break;
+ case 't':
+ if (memEQ(posixcc, "digi", 4)) {
+ /* t */
+ namedclass
+ = complement ? ANYOF_NDIGIT : ANYOF_DIGIT;
+ }
+ if (memEQ(posixcc, "prin", 4)) {
+ /* t */
+ namedclass
+ = complement ? ANYOF_NPRINT : ANYOF_PRINT;
+ }
+ if (memEQ(posixcc, "punc", 4)) {
+ /* t */
+ namedclass
+ = complement ? ANYOF_NPUNCT : ANYOF_PUNCT;
+ }
+ break;
}
break;
- case 'x':
- if (strnEQ(posixcc, "xdigit", 6)) {
- namedclass =
- complement ? ANYOF_NXDIGIT : ANYOF_XDIGIT;
- skip = 6;
+ case 6:
+ if (memEQ(posixcc, "xdigit", 6)) {
+ namedclass
+ = complement ? ANYOF_NXDIGIT : ANYOF_XDIGIT;
}
break;
}
- if (namedclass == OOB_NAMEDCLASS ||
- posixcc[skip] != ':' ||
- posixcc[skip+1] != ']')
+
+ if (namedclass == OOB_NAMEDCLASS)
{
Simple_vFAIL3("POSIX class [:%.*s:] unknown",
t - s - 1, s + 1);
}
+ assert (posixcc[skip] == ':');
+ assert (posixcc[skip+1] == ']');
} else if (!SIZE_ONLY) {
/* [[=foo=]] and [[.foo.]] are still future. */
}
RExC_parse = e + 1;
ANYOF_FLAGS(ret) |= ANYOF_UNICODE;
- continue;
+ namedclass = ANYOF_MAX; /* no official name, but it's named */
+ break;
case 'n': value = '\n'; break;
case 'r': value = '\r'; break;
case 't': value = '\t'; break;
}
if (!SIZE_ONLY) {
+ const char *what = NULL;
+ char yesno = 0;
+
if (namedclass > OOB_NAMEDCLASS)
optimize_invert = FALSE;
/* Possible truncation here but in some 64-bit environments
if (isALNUM(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsWord\n");
+ yesno = '+';
+ what = "Word";
break;
case ANYOF_NALNUM:
if (LOC)
if (!isALNUM(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsWord\n");
+ yesno = '!';
+ what = "Word";
break;
case ANYOF_ALNUMC:
if (LOC)
if (isALNUMC(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsAlnum\n");
+ yesno = '+';
+ what = "Alnum";
break;
case ANYOF_NALNUMC:
if (LOC)
if (!isALNUMC(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsAlnum\n");
+ yesno = '!';
+ what = "Alnum";
break;
case ANYOF_ALPHA:
if (LOC)
if (isALPHA(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsAlpha\n");
+ yesno = '+';
+ what = "Alpha";
break;
case ANYOF_NALPHA:
if (LOC)
if (!isALPHA(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsAlpha\n");
+ yesno = '!';
+ what = "Alpha";
break;
case ANYOF_ASCII:
if (LOC)
}
#endif /* EBCDIC */
}
- Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsASCII\n");
+ yesno = '+';
+ what = "ASCII";
break;
case ANYOF_NASCII:
if (LOC)
}
#endif /* EBCDIC */
}
- Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsASCII\n");
+ yesno = '!';
+ what = "ASCII";
break;
case ANYOF_BLANK:
if (LOC)
if (isBLANK(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsBlank\n");
+ yesno = '+';
+ what = "Blank";
break;
case ANYOF_NBLANK:
if (LOC)
if (!isBLANK(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsBlank\n");
+ yesno = '!';
+ what = "Blank";
break;
case ANYOF_CNTRL:
if (LOC)
if (isCNTRL(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsCntrl\n");
+ yesno = '+';
+ what = "Cntrl";
break;
case ANYOF_NCNTRL:
if (LOC)
if (!isCNTRL(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsCntrl\n");
+ yesno = '!';
+ what = "Cntrl";
break;
case ANYOF_DIGIT:
if (LOC)
for (value = '0'; value <= '9'; value++)
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsDigit\n");
+ yesno = '+';
+ what = "Digit";
break;
case ANYOF_NDIGIT:
if (LOC)
for (value = '9' + 1; value < 256; value++)
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsDigit\n");
+ yesno = '!';
+ what = "Digit";
break;
case ANYOF_GRAPH:
if (LOC)
if (isGRAPH(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsGraph\n");
+ yesno = '+';
+ what = "Graph";
break;
case ANYOF_NGRAPH:
if (LOC)
if (!isGRAPH(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsGraph\n");
+ yesno = '!';
+ what = "Graph";
break;
case ANYOF_LOWER:
if (LOC)
if (isLOWER(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsLower\n");
+ yesno = '+';
+ what = "Lower";
break;
case ANYOF_NLOWER:
if (LOC)
if (!isLOWER(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsLower\n");
+ yesno = '!';
+ what = "Lower";
break;
case ANYOF_PRINT:
if (LOC)
if (isPRINT(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsPrint\n");
+ yesno = '+';
+ what = "Print";
break;
case ANYOF_NPRINT:
if (LOC)
if (!isPRINT(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsPrint\n");
+ yesno = '!';
+ what = "Print";
break;
case ANYOF_PSXSPC:
if (LOC)
if (isPSXSPC(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsSpace\n");
+ yesno = '+';
+ what = "Space";
break;
case ANYOF_NPSXSPC:
if (LOC)
if (!isPSXSPC(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsSpace\n");
+ yesno = '!';
+ what = "Space";
break;
case ANYOF_PUNCT:
if (LOC)
if (isPUNCT(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsPunct\n");
+ yesno = '+';
+ what = "Punct";
break;
case ANYOF_NPUNCT:
if (LOC)
if (!isPUNCT(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsPunct\n");
+ yesno = '!';
+ what = "Punct";
break;
case ANYOF_SPACE:
if (LOC)
if (isSPACE(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsSpacePerl\n");
+ yesno = '+';
+ what = "SpacePerl";
break;
case ANYOF_NSPACE:
if (LOC)
if (!isSPACE(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsSpacePerl\n");
+ yesno = '!';
+ what = "SpacePerl";
break;
case ANYOF_UPPER:
if (LOC)
if (isUPPER(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsUpper\n");
+ yesno = '+';
+ what = "Upper";
break;
case ANYOF_NUPPER:
if (LOC)
if (!isUPPER(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsUpper\n");
+ yesno = '!';
+ what = "Upper";
break;
case ANYOF_XDIGIT:
if (LOC)
if (isXDIGIT(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsXDigit\n");
+ yesno = '+';
+ what = "XDigit";
break;
case ANYOF_NXDIGIT:
if (LOC)
if (!isXDIGIT(value))
ANYOF_BITMAP_SET(ret, value);
}
- Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsXDigit\n");
+ yesno = '!';
+ what = "XDigit";
+ break;
+ case ANYOF_MAX:
+ /* this is to handle \p and \P */
break;
default:
vFAIL("Invalid [::] class");
break;
}
+ if (what) {
+ /* Strings such as "+utf8::isWord\n" */
+ Perl_sv_catpvf(aTHX_ listsv, "%cutf8::Is%s\n", yesno, what);
+ }
if (LOC)
ANYOF_FLAGS(ret) |= ANYOF_CLASS;
continue;
else if (prevnatvalue == natvalue) {
Perl_sv_catpvf(aTHX_ listsv, "%04"UVxf"\n", natvalue);
if (FOLD) {
- U8 foldbuf[UTF8_MAXLEN_FOLD+1];
+ U8 foldbuf[UTF8_MAXBYTES_CASE+1];
STRLEN foldlen;
UV f = to_uni_fold(natvalue, foldbuf, &foldlen);
RExC_parse - RExC_start,
RExC_offsets[0]));
Set_Node_Offset(place, RExC_parse);
+ Set_Node_Length(place, 1);
}
src = NEXTOPER(place);
FILL_ADVANCE_NODE(place, op);
if (lv) {
if (sw) {
- U8 s[UTF8_MAXLEN+1];
+ U8 s[UTF8_MAXBYTES_CASE+1];
for (i = 0; i <= 256; i++) { /* just the first 256 */
U8 *e = uvchr_to_utf8(s, i);
}
{
- char *s = savepv(SvPVX(lv));
+ char *s = savesvpv(lv);
char *origs = s;
while(*s && *s != '\n') s++;
int n = r->data->count;
PAD* new_comppad = NULL;
PAD* old_comppad;
+ PADOFFSET refcnt;
while (--n >= 0) {
/* If you add a ->what type here, update the comment in regcomp.h */
(SvTYPE(new_comppad) == SVt_PVAV) ?
new_comppad : Null(PAD *)
);
- if (!OpREFCNT_dec((OP_4tree*)r->data->data[n])) {
+ OP_REFCNT_LOCK;
+ refcnt = OpREFCNT_dec((OP_4tree*)r->data->data[n]);
+ OP_REFCNT_UNLOCK;
+ if (!refcnt)
op_free((OP_4tree*)r->data->data[n]);
- }
PAD_RESTORE_LOCAL(old_comppad);
SvREFCNT_dec((SV*)new_comppad);
if (l1 > 512)
l1 = 512;
Copy(message, buf, l1 , char);
- buf[l1] = '\0'; /* Overwrite \n */
+ buf[l1-1] = '\0'; /* Overwrite \n */
Perl_croak(aTHX_ "%s", buf);
}
U32 i;
GV *mgv;
REGEXP *rx;
- char digits[16];
+ char digits[TYPE_CHARS(long)];
if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
for (i = 1; i <= rx->nparens; i++) {
ReREFCNT_dec((regexp *)r);
}
+/*
+ * Local variables:
+ * c-indentation-style: bsd
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ *
+ * vim: shiftwidth=4:
+*/