|
version 1.1.1.2, 2012/02/21 23:50:25
|
version 1.1.1.3, 2012/10/09 09:19:17
|
|
Line 37 POSSIBILITY OF SUCH DAMAGE.
|
Line 37 POSSIBILITY OF SUCH DAMAGE.
|
| ----------------------------------------------------------------------------- |
----------------------------------------------------------------------------- |
| */ |
*/ |
| |
|
| |
|
| /* This module contains pcre_exec(), the externally visible function that does |
/* This module contains pcre_exec(), the externally visible function that does |
| pattern matching using an NFA algorithm, trying to mimic Perl as closely as |
pattern matching using an NFA algorithm, trying to mimic Perl as closely as |
| possible. There are also some static supporting functions. */ |
possible. There are also some static supporting functions. */ |
|
Line 140 Arguments:
|
Line 139 Arguments:
|
| md points to match data block |
md points to match data block |
| caseless TRUE if caseless |
caseless TRUE if caseless |
| |
|
| Returns: < 0 if not matched, otherwise the number of subject bytes matched | Returns: >= 0 the number of subject bytes matched |
| | -1 no match |
| | -2 partial match; always given if at end subject |
| */ |
*/ |
| |
|
| static int |
static int |
|
Line 163 pchars(p, length, FALSE, md);
|
Line 164 pchars(p, length, FALSE, md);
|
| printf("\n"); |
printf("\n"); |
| #endif |
#endif |
| |
|
| /* Always fail if reference not set (and not JavaScript compatible). */ | /* Always fail if reference not set (and not JavaScript compatible - in that |
| | case the length is passed as zero). */ |
| |
|
| if (length < 0) return -1; |
if (length < 0) return -1; |
| |
|
|
Line 189 if (caseless)
|
Line 191 if (caseless)
|
| while (p < endptr) |
while (p < endptr) |
| { |
{ |
| int c, d; |
int c, d; |
| if (eptr >= md->end_subject) return -1; | if (eptr >= md->end_subject) return -2; /* Partial match */ |
| GETCHARINC(c, eptr); |
GETCHARINC(c, eptr); |
| GETCHARINC(d, p); |
GETCHARINC(d, p); |
| if (c != d && c != UCD_OTHERCASE(d)) return -1; |
if (c != d && c != UCD_OTHERCASE(d)) return -1; |
|
Line 202 if (caseless)
|
Line 204 if (caseless)
|
| /* The same code works when not in UTF-8 mode and in UTF-8 mode when there |
/* The same code works when not in UTF-8 mode and in UTF-8 mode when there |
| is no UCP support. */ |
is no UCP support. */ |
| { |
{ |
| if (eptr + length > md->end_subject) return -1; |
|
| while (length-- > 0) |
while (length-- > 0) |
| { |
{ |
| |
if (eptr >= md->end_subject) return -2; /* Partial match */ |
| if (TABLE_GET(*p, md->lcc, *p) != TABLE_GET(*eptr, md->lcc, *eptr)) return -1; |
if (TABLE_GET(*p, md->lcc, *p) != TABLE_GET(*eptr, md->lcc, *eptr)) return -1; |
| p++; |
p++; |
| eptr++; |
eptr++; |
|
Line 217 are in UTF-8 mode. */
|
Line 219 are in UTF-8 mode. */
|
| |
|
| else |
else |
| { |
{ |
| if (eptr + length > md->end_subject) return -1; | while (length-- > 0) |
| while (length-- > 0) if (*p++ != *eptr++) return -1; | { |
| | if (eptr >= md->end_subject) return -2; /* Partial match */ |
| | if (*p++ != *eptr++) return -1; |
| | } |
| } |
} |
| |
|
| return (int)(eptr - eptr_start); |
return (int)(eptr - eptr_start); |
|
Line 311 argument of match(), which never changes. */
|
Line 316 argument of match(), which never changes. */
|
| |
|
| #define RMATCH(ra,rb,rc,rd,re,rw)\ |
#define RMATCH(ra,rb,rc,rd,re,rw)\ |
| {\ |
{\ |
| heapframe *newframe = (heapframe *)(PUBL(stack_malloc))(sizeof(heapframe));\ | heapframe *newframe = frame->Xnextframe;\ |
| if (newframe == NULL) RRETURN(PCRE_ERROR_NOMEMORY);\ | if (newframe == NULL)\ |
| frame->Xwhere = rw; \ | {\ |
| | newframe = (heapframe *)(PUBL(stack_malloc))(sizeof(heapframe));\ |
| | if (newframe == NULL) RRETURN(PCRE_ERROR_NOMEMORY);\ |
| | newframe->Xnextframe = NULL;\ |
| | frame->Xnextframe = newframe;\ |
| | }\ |
| | frame->Xwhere = rw;\ |
| newframe->Xeptr = ra;\ |
newframe->Xeptr = ra;\ |
| newframe->Xecode = rb;\ |
newframe->Xecode = rb;\ |
| newframe->Xmstart = mstart;\ |
newframe->Xmstart = mstart;\ |
|
Line 332 argument of match(), which never changes. */
|
Line 343 argument of match(), which never changes. */
|
| {\ |
{\ |
| heapframe *oldframe = frame;\ |
heapframe *oldframe = frame;\ |
| frame = oldframe->Xprevframe;\ |
frame = oldframe->Xprevframe;\ |
| if (oldframe != &frame_zero) (PUBL(stack_free))(oldframe);\ |
|
| if (frame != NULL)\ |
if (frame != NULL)\ |
| {\ |
{\ |
| rrc = ra;\ |
rrc = ra;\ |
|
Line 346 argument of match(), which never changes. */
|
Line 356 argument of match(), which never changes. */
|
| |
|
| typedef struct heapframe { |
typedef struct heapframe { |
| struct heapframe *Xprevframe; |
struct heapframe *Xprevframe; |
| |
struct heapframe *Xnextframe; |
| |
|
| /* Function arguments that may change */ |
/* Function arguments that may change */ |
| |
|
|
Line 492 the top-level on the stack rather than malloc-ing them
|
Line 503 the top-level on the stack rather than malloc-ing them
|
| boost in many cases where there is not much "recursion". */ |
boost in many cases where there is not much "recursion". */ |
| |
|
| #ifdef NO_RECURSE |
#ifdef NO_RECURSE |
| heapframe frame_zero; | heapframe *frame = (heapframe *)md->match_frames_base; |
| heapframe *frame = &frame_zero; | |
| frame->Xprevframe = NULL; /* Marks the top level */ | |
| |
|
| /* Copy in the original argument variables */ |
/* Copy in the original argument variables */ |
| |
|
|
Line 897 for (;;)
|
Line 906 for (;;)
|
| } |
} |
| else /* OP_KETRMAX */ |
else /* OP_KETRMAX */ |
| { |
{ |
| md->match_function_type = MATCH_CBEGROUP; |
|
| RMATCH(eptr, prev, offset_top, md, eptrb, RM66); |
RMATCH(eptr, prev, offset_top, md, eptrb, RM66); |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
| ecode += 1 + LINK_SIZE; |
ecode += 1 + LINK_SIZE; |
|
Line 1026 for (;;)
|
Line 1034 for (;;)
|
| |
|
| for (;;) |
for (;;) |
| { |
{ |
| if (op >= OP_SBRA || op == OP_ONCE) md->match_function_type = MATCH_CBEGROUP; | if (op >= OP_SBRA || op == OP_ONCE) |
| | md->match_function_type = MATCH_CBEGROUP; |
| |
|
| /* If this is not a possibly empty group, and there are no (*THEN)s in |
/* If this is not a possibly empty group, and there are no (*THEN)s in |
| the pattern, and this is the final alternative, optimize as described |
the pattern, and this is the final alternative, optimize as described |
|
Line 1565 for (;;)
|
Line 1574 for (;;)
|
| mstart = md->start_match_ptr; /* In case \K reset it */ |
mstart = md->start_match_ptr; /* In case \K reset it */ |
| break; |
break; |
| } |
} |
| |
md->mark = save_mark; |
| |
|
| /* PCRE does not allow THEN to escape beyond an assertion; it is treated | /* A COMMIT failure must fail the entire assertion, without trying any |
| as NOMATCH. */ | subsequent branches. */ |
| |
|
| |
if (rrc == MATCH_COMMIT) RRETURN(MATCH_NOMATCH); |
| |
|
| |
/* PCRE does not allow THEN to escape beyond an assertion; it |
| |
is treated as NOMATCH. */ |
| |
|
| if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc); |
if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc); |
| ecode += GET(ecode, 1); |
ecode += GET(ecode, 1); |
| md->mark = save_mark; |
|
| } |
} |
| while (*ecode == OP_ALT); |
while (*ecode == OP_ALT); |
| |
|
|
Line 1779 for (;;)
|
Line 1793 for (;;)
|
| goto RECURSION_MATCHED; /* Exit loop; end processing */ |
goto RECURSION_MATCHED; /* Exit loop; end processing */ |
| } |
} |
| |
|
| /* PCRE does not allow THEN to escape beyond a recursion; it is treated | /* PCRE does not allow THEN or COMMIT to escape beyond a recursion; it |
| as NOMATCH. */ | is treated as NOMATCH. */ |
| |
|
| else if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) | else if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN && |
| | rrc != MATCH_COMMIT) |
| { |
{ |
| DPRINTF(("Recursion gave error %d\n", rrc)); |
DPRINTF(("Recursion gave error %d\n", rrc)); |
| if (new_recursive.offset_save != stacksave) |
if (new_recursive.offset_save != stacksave) |
|
Line 1993 for (;;)
|
Line 2008 for (;;)
|
| } |
} |
| if (*prev >= OP_SBRA) /* Could match an empty string */ |
if (*prev >= OP_SBRA) /* Could match an empty string */ |
| { |
{ |
| md->match_function_type = MATCH_CBEGROUP; |
|
| RMATCH(eptr, prev, offset_top, md, eptrb, RM50); |
RMATCH(eptr, prev, offset_top, md, eptrb, RM50); |
| RRETURN(rrc); |
RRETURN(rrc); |
| } |
} |
|
Line 2002 for (;;)
|
Line 2016 for (;;)
|
| } |
} |
| else /* OP_KETRMAX */ |
else /* OP_KETRMAX */ |
| { |
{ |
| if (*prev >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP; |
|
| RMATCH(eptr, prev, offset_top, md, eptrb, RM13); |
RMATCH(eptr, prev, offset_top, md, eptrb, RM13); |
| if (rrc == MATCH_ONCE && md->once_target == prev) rrc = MATCH_NOMATCH; |
if (rrc == MATCH_ONCE && md->once_target == prev) rrc = MATCH_NOMATCH; |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
|
Line 2059 for (;;)
|
Line 2072 for (;;)
|
| |
|
| case OP_DOLLM: |
case OP_DOLLM: |
| if (eptr < md->end_subject) |
if (eptr < md->end_subject) |
| { if (!IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); } | { |
| | if (!IS_NEWLINE(eptr)) |
| | { |
| | if (md->partial != 0 && |
| | eptr + 1 >= md->end_subject && |
| | NLBLOCK->nltype == NLTYPE_FIXED && |
| | NLBLOCK->nllen == 2 && |
| | *eptr == NLBLOCK->nl[0]) |
| | { |
| | md->hitend = TRUE; |
| | if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); |
| | } |
| | RRETURN(MATCH_NOMATCH); |
| | } |
| | } |
| else |
else |
| { |
{ |
| if (md->noteol) RRETURN(MATCH_NOMATCH); |
if (md->noteol) RRETURN(MATCH_NOMATCH); |
|
Line 2091 for (;;)
|
Line 2118 for (;;)
|
| ASSERT_NL_OR_EOS: |
ASSERT_NL_OR_EOS: |
| if (eptr < md->end_subject && |
if (eptr < md->end_subject && |
| (!IS_NEWLINE(eptr) || eptr != md->end_subject - md->nllen)) |
(!IS_NEWLINE(eptr) || eptr != md->end_subject - md->nllen)) |
| |
{ |
| |
if (md->partial != 0 && |
| |
eptr + 1 >= md->end_subject && |
| |
NLBLOCK->nltype == NLTYPE_FIXED && |
| |
NLBLOCK->nllen == 2 && |
| |
*eptr == NLBLOCK->nl[0]) |
| |
{ |
| |
md->hitend = TRUE; |
| |
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); |
| |
} |
| RRETURN(MATCH_NOMATCH); |
RRETURN(MATCH_NOMATCH); |
| |
} |
| |
|
| /* Either at end of string or \n before end. */ |
/* Either at end of string or \n before end. */ |
| |
|
|
Line 2219 for (;;)
|
Line 2257 for (;;)
|
| } |
} |
| break; |
break; |
| |
|
| /* Match a single character type; inline for speed */ | /* Match any single character type except newline; have to take care with |
| | CRLF newlines and partial matching. */ |
| |
|
| case OP_ANY: |
case OP_ANY: |
| if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); |
if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); |
| |
if (md->partial != 0 && |
| |
eptr + 1 >= md->end_subject && |
| |
NLBLOCK->nltype == NLTYPE_FIXED && |
| |
NLBLOCK->nllen == 2 && |
| |
*eptr == NLBLOCK->nl[0]) |
| |
{ |
| |
md->hitend = TRUE; |
| |
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); |
| |
} |
| |
|
| /* Fall through */ |
/* Fall through */ |
| |
|
| |
/* Match any single character whatsoever. */ |
| |
|
| case OP_ALLANY: |
case OP_ALLANY: |
| if (eptr >= md->end_subject) /* DO NOT merge the eptr++ here; it must */ |
if (eptr >= md->end_subject) /* DO NOT merge the eptr++ here; it must */ |
| { /* not be updated before SCHECK_PARTIAL. */ |
{ /* not be updated before SCHECK_PARTIAL. */ |
|
Line 2365 for (;;)
|
Line 2416 for (;;)
|
| default: RRETURN(MATCH_NOMATCH); |
default: RRETURN(MATCH_NOMATCH); |
| |
|
| case 0x000d: |
case 0x000d: |
| if (eptr < md->end_subject && *eptr == 0x0a) eptr++; | if (eptr >= md->end_subject) |
| | { |
| | SCHECK_PARTIAL(); |
| | } |
| | else if (*eptr == 0x0a) eptr++; |
| break; |
break; |
| |
|
| case 0x000a: |
case 0x000a: |
|
Line 2595 for (;;)
|
Line 2650 for (;;)
|
| if (UCD_CATEGORY(c) != ucp_M) break; |
if (UCD_CATEGORY(c) != ucp_M) break; |
| eptr += len; |
eptr += len; |
| } |
} |
| |
CHECK_PARTIAL(); |
| ecode++; |
ecode++; |
| break; |
break; |
| #endif |
#endif |
|
Line 2660 for (;;)
|
Line 2716 for (;;)
|
| default: /* No repeat follows */ |
default: /* No repeat follows */ |
| if ((length = match_ref(offset, eptr, length, md, caseless)) < 0) |
if ((length = match_ref(offset, eptr, length, md, caseless)) < 0) |
| { |
{ |
| |
if (length == -2) eptr = md->end_subject; /* Partial match */ |
| CHECK_PARTIAL(); |
CHECK_PARTIAL(); |
| RRETURN(MATCH_NOMATCH); |
RRETURN(MATCH_NOMATCH); |
| } |
} |
|
Line 2685 for (;;)
|
Line 2742 for (;;)
|
| int slength; |
int slength; |
| if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0) |
if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0) |
| { |
{ |
| |
if (slength == -2) eptr = md->end_subject; /* Partial match */ |
| CHECK_PARTIAL(); |
CHECK_PARTIAL(); |
| RRETURN(MATCH_NOMATCH); |
RRETURN(MATCH_NOMATCH); |
| } |
} |
|
Line 2708 for (;;)
|
Line 2766 for (;;)
|
| if (fi >= max) RRETURN(MATCH_NOMATCH); |
if (fi >= max) RRETURN(MATCH_NOMATCH); |
| if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0) |
if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0) |
| { |
{ |
| |
if (slength == -2) eptr = md->end_subject; /* Partial match */ |
| CHECK_PARTIAL(); |
CHECK_PARTIAL(); |
| RRETURN(MATCH_NOMATCH); |
RRETURN(MATCH_NOMATCH); |
| } |
} |
|
Line 2726 for (;;)
|
Line 2785 for (;;)
|
| int slength; |
int slength; |
| if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0) |
if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0) |
| { |
{ |
| CHECK_PARTIAL(); | /* Can't use CHECK_PARTIAL because we don't want to update eptr in |
| | the soft partial matching case. */ |
| | |
| | if (slength == -2 && md->partial != 0 && |
| | md->end_subject > md->start_used_ptr) |
| | { |
| | md->hitend = TRUE; |
| | if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); |
| | } |
| break; |
break; |
| } |
} |
| eptr += slength; |
eptr += slength; |
| } |
} |
| |
|
| while (eptr >= pp) |
while (eptr >= pp) |
| { |
{ |
| RMATCH(eptr, ecode, offset_top, md, eptrb, RM15); |
RMATCH(eptr, ecode, offset_top, md, eptrb, RM15); |
|
Line 3360 for (;;)
|
Line 3428 for (;;)
|
| maximizing, find the maximum number of characters and work backwards. */ |
maximizing, find the maximum number of characters and work backwards. */ |
| |
|
| DPRINTF(("matching %c{%d,%d} against subject %.*s\n", fc, min, max, |
DPRINTF(("matching %c{%d,%d} against subject %.*s\n", fc, min, max, |
| max, eptr)); | max, (char *)eptr)); |
| |
|
| if (op >= OP_STARI) /* Caseless */ |
if (op >= OP_STARI) /* Caseless */ |
| { |
{ |
|
Line 3504 for (;;)
|
Line 3572 for (;;)
|
| SCHECK_PARTIAL(); |
SCHECK_PARTIAL(); |
| RRETURN(MATCH_NOMATCH); |
RRETURN(MATCH_NOMATCH); |
| } |
} |
| ecode++; | #ifdef SUPPORT_UTF |
| GETCHARINCTEST(c, eptr); | if (utf) |
| if (op == OP_NOTI) /* The caseless case */ | |
| { |
{ |
| register unsigned int ch, och; |
register unsigned int ch, och; |
| ch = *ecode++; | |
| #ifdef COMPILE_PCRE8 | ecode++; |
| /* ch must be < 128 if UTF is enabled. */ | GETCHARINC(ch, ecode); |
| och = md->fcc[ch]; | GETCHARINC(c, eptr); |
| #else | |
| #ifdef SUPPORT_UTF | if (op == OP_NOT) |
| | { |
| | if (ch == c) RRETURN(MATCH_NOMATCH); |
| | } |
| | else |
| | { |
| #ifdef SUPPORT_UCP |
#ifdef SUPPORT_UCP |
| if (utf && ch > 127) | if (ch > 127) |
| och = UCD_OTHERCASE(ch); | och = UCD_OTHERCASE(ch); |
| #else |
#else |
| if (utf && ch > 127) | if (ch > 127) |
| och = ch; | och = ch; |
| #endif /* SUPPORT_UCP */ |
#endif /* SUPPORT_UCP */ |
| else | else |
| #endif /* SUPPORT_UTF */ | och = TABLE_GET(ch, md->fcc, ch); |
| och = TABLE_GET(ch, md->fcc, ch); | if (ch == c || och == c) RRETURN(MATCH_NOMATCH); |
| #endif /* COMPILE_PCRE8 */ | } |
| if (ch == c || och == c) RRETURN(MATCH_NOMATCH); | |
| } |
} |
| else /* Caseful */ | else |
| | #endif |
| { |
{ |
| if (*ecode++ == c) RRETURN(MATCH_NOMATCH); | register unsigned int ch = ecode[1]; |
| | c = *eptr++; |
| | if (ch == c || (op == OP_NOTI && TABLE_GET(ch, md->fcc, ch) == c)) |
| | RRETURN(MATCH_NOMATCH); |
| | ecode += 2; |
| } |
} |
| break; |
break; |
| |
|
|
Line 3610 for (;;)
|
Line 3686 for (;;)
|
| /* Common code for all repeated single-byte matches. */ |
/* Common code for all repeated single-byte matches. */ |
| |
|
| REPEATNOTCHAR: |
REPEATNOTCHAR: |
| fc = *ecode++; | GETCHARINCTEST(fc, ecode); |
| |
|
| /* The code is duplicated for the caseless and caseful cases, for speed, |
/* The code is duplicated for the caseless and caseful cases, for speed, |
| since matching characters is likely to be quite common. First, ensure the |
since matching characters is likely to be quite common. First, ensure the |
|
Line 3621 for (;;)
|
Line 3697 for (;;)
|
| characters and work backwards. */ |
characters and work backwards. */ |
| |
|
| DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", fc, min, max, |
DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", fc, min, max, |
| max, eptr)); | max, (char *)eptr)); |
| |
|
| if (op >= OP_NOTSTARI) /* Caseless */ |
if (op >= OP_NOTSTARI) /* Caseless */ |
| { |
{ |
| #ifdef COMPILE_PCRE8 |
|
| /* fc must be < 128 if UTF is enabled. */ |
|
| foc = md->fcc[fc]; |
|
| #else |
|
| #ifdef SUPPORT_UTF |
#ifdef SUPPORT_UTF |
| #ifdef SUPPORT_UCP |
#ifdef SUPPORT_UCP |
| if (utf && fc > 127) |
if (utf && fc > 127) |
|
Line 3640 for (;;)
|
Line 3712 for (;;)
|
| else |
else |
| #endif /* SUPPORT_UTF */ |
#endif /* SUPPORT_UTF */ |
| foc = TABLE_GET(fc, md->fcc, fc); |
foc = TABLE_GET(fc, md->fcc, fc); |
| #endif /* COMPILE_PCRE8 */ |
|
| |
|
| #ifdef SUPPORT_UTF |
#ifdef SUPPORT_UTF |
| if (utf) |
if (utf) |
|
Line 3654 for (;;)
|
Line 3725 for (;;)
|
| RRETURN(MATCH_NOMATCH); |
RRETURN(MATCH_NOMATCH); |
| } |
} |
| GETCHARINC(d, eptr); |
GETCHARINC(d, eptr); |
| if (fc == d || (unsigned int) foc == d) RRETURN(MATCH_NOMATCH); | if (fc == d || (unsigned int)foc == d) RRETURN(MATCH_NOMATCH); |
| } |
} |
| } |
} |
| else |
else |
|
Line 4164 for (;;)
|
Line 4235 for (;;)
|
| if (UCD_CATEGORY(c) != ucp_M) break; |
if (UCD_CATEGORY(c) != ucp_M) break; |
| eptr += len; |
eptr += len; |
| } |
} |
| |
CHECK_PARTIAL(); |
| } |
} |
| } |
} |
| |
|
|
Line 4184 for (;;)
|
Line 4256 for (;;)
|
| RRETURN(MATCH_NOMATCH); |
RRETURN(MATCH_NOMATCH); |
| } |
} |
| if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); |
if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); |
| |
if (md->partial != 0 && |
| |
eptr + 1 >= md->end_subject && |
| |
NLBLOCK->nltype == NLTYPE_FIXED && |
| |
NLBLOCK->nllen == 2 && |
| |
*eptr == NLBLOCK->nl[0]) |
| |
{ |
| |
md->hitend = TRUE; |
| |
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); |
| |
} |
| eptr++; |
eptr++; |
| ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); |
ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); |
| } |
} |
|
Line 4468 for (;;)
|
Line 4549 for (;;)
|
| RRETURN(MATCH_NOMATCH); |
RRETURN(MATCH_NOMATCH); |
| } |
} |
| if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); |
if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); |
| |
if (md->partial != 0 && |
| |
eptr + 1 >= md->end_subject && |
| |
NLBLOCK->nltype == NLTYPE_FIXED && |
| |
NLBLOCK->nllen == 2 && |
| |
*eptr == NLBLOCK->nl[0]) |
| |
{ |
| |
md->hitend = TRUE; |
| |
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); |
| |
} |
| eptr++; |
eptr++; |
| } |
} |
| break; |
break; |
|
Line 4948 for (;;)
|
Line 5038 for (;;)
|
| if (UCD_CATEGORY(c) != ucp_M) break; |
if (UCD_CATEGORY(c) != ucp_M) break; |
| eptr += len; |
eptr += len; |
| } |
} |
| |
CHECK_PARTIAL(); |
| } |
} |
| } |
} |
| else |
else |
|
Line 4971 for (;;)
|
Line 5062 for (;;)
|
| GETCHARINC(c, eptr); |
GETCHARINC(c, eptr); |
| switch(ctype) |
switch(ctype) |
| { |
{ |
| case OP_ANY: /* This is the non-NL case */ | case OP_ANY: /* This is the non-NL case */ |
| | if (md->partial != 0 && /* Take care with CRLF partial */ |
| | eptr >= md->end_subject && |
| | NLBLOCK->nltype == NLTYPE_FIXED && |
| | NLBLOCK->nllen == 2 && |
| | c == NLBLOCK->nl[0]) |
| | { |
| | md->hitend = TRUE; |
| | if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); |
| | } |
| | break; |
| | |
| case OP_ALLANY: |
case OP_ALLANY: |
| case OP_ANYBYTE: |
case OP_ANYBYTE: |
| break; |
break; |
|
Line 5134 for (;;)
|
Line 5236 for (;;)
|
| c = *eptr++; |
c = *eptr++; |
| switch(ctype) |
switch(ctype) |
| { |
{ |
| case OP_ANY: /* This is the non-NL case */ | case OP_ANY: /* This is the non-NL case */ |
| | if (md->partial != 0 && /* Take care with CRLF partial */ |
| | eptr >= md->end_subject && |
| | NLBLOCK->nltype == NLTYPE_FIXED && |
| | NLBLOCK->nllen == 2 && |
| | c == NLBLOCK->nl[0]) |
| | { |
| | md->hitend = TRUE; |
| | if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); |
| | } |
| | break; |
| | |
| case OP_ALLANY: |
case OP_ALLANY: |
| case OP_ANYBYTE: |
case OP_ANYBYTE: |
| break; |
break; |
|
Line 5491 for (;;)
|
Line 5604 for (;;)
|
| if (UCD_CATEGORY(c) != ucp_M) break; |
if (UCD_CATEGORY(c) != ucp_M) break; |
| eptr += len; |
eptr += len; |
| } |
} |
| |
CHECK_PARTIAL(); |
| } |
} |
| |
|
| /* eptr is now past the end of the maximum run */ |
/* eptr is now past the end of the maximum run */ |
|
Line 5534 for (;;)
|
Line 5648 for (;;)
|
| break; |
break; |
| } |
} |
| if (IS_NEWLINE(eptr)) break; |
if (IS_NEWLINE(eptr)) break; |
| |
if (md->partial != 0 && /* Take care with CRLF partial */ |
| |
eptr + 1 >= md->end_subject && |
| |
NLBLOCK->nltype == NLTYPE_FIXED && |
| |
NLBLOCK->nllen == 2 && |
| |
*eptr == NLBLOCK->nl[0]) |
| |
{ |
| |
md->hitend = TRUE; |
| |
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); |
| |
} |
| eptr++; |
eptr++; |
| ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); |
ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); |
| } |
} |
|
Line 5551 for (;;)
|
Line 5674 for (;;)
|
| break; |
break; |
| } |
} |
| if (IS_NEWLINE(eptr)) break; |
if (IS_NEWLINE(eptr)) break; |
| |
if (md->partial != 0 && /* Take care with CRLF partial */ |
| |
eptr + 1 >= md->end_subject && |
| |
NLBLOCK->nltype == NLTYPE_FIXED && |
| |
NLBLOCK->nllen == 2 && |
| |
*eptr == NLBLOCK->nl[0]) |
| |
{ |
| |
md->hitend = TRUE; |
| |
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); |
| |
} |
| eptr++; |
eptr++; |
| ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); |
ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); |
| } |
} |
|
Line 5815 for (;;)
|
Line 5947 for (;;)
|
| break; |
break; |
| } |
} |
| if (IS_NEWLINE(eptr)) break; |
if (IS_NEWLINE(eptr)) break; |
| |
if (md->partial != 0 && /* Take care with CRLF partial */ |
| |
eptr + 1 >= md->end_subject && |
| |
NLBLOCK->nltype == NLTYPE_FIXED && |
| |
NLBLOCK->nllen == 2 && |
| |
*eptr == NLBLOCK->nl[0]) |
| |
{ |
| |
md->hitend = TRUE; |
| |
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); |
| |
} |
| eptr++; |
eptr++; |
| } |
} |
| break; |
break; |
|
Line 6145 Undefine all the macros that were defined above to han
|
Line 6286 Undefine all the macros that were defined above to han
|
| ***************************************************************************/ |
***************************************************************************/ |
| |
|
| |
|
| |
#ifdef NO_RECURSE |
| |
/************************************************* |
| |
* Release allocated heap frames * |
| |
*************************************************/ |
| |
|
| |
/* This function releases all the allocated frames. The base frame is on the |
| |
machine stack, and so must not be freed. |
| |
|
| |
Argument: the address of the base frame |
| |
Returns: nothing |
| |
*/ |
| |
|
| |
static void |
| |
release_match_heapframes (heapframe *frame_base) |
| |
{ |
| |
heapframe *nextframe = frame_base->Xnextframe; |
| |
while (nextframe != NULL) |
| |
{ |
| |
heapframe *oldframe = nextframe; |
| |
nextframe = nextframe->Xnextframe; |
| |
(PUBL(stack_free))(oldframe); |
| |
} |
| |
} |
| |
#endif |
| |
|
| |
|
| /************************************************* |
/************************************************* |
| * Execute a Regular Expression * |
* Execute a Regular Expression * |
| *************************************************/ |
*************************************************/ |
|
Line 6207 PCRE_PUCHAR req_char_ptr = start_match - 1;
|
Line 6373 PCRE_PUCHAR req_char_ptr = start_match - 1;
|
| const pcre_study_data *study; |
const pcre_study_data *study; |
| const REAL_PCRE *re = (const REAL_PCRE *)argument_re; |
const REAL_PCRE *re = (const REAL_PCRE *)argument_re; |
| |
|
| |
#ifdef NO_RECURSE |
| |
heapframe frame_zero; |
| |
frame_zero.Xprevframe = NULL; /* Marks the top level */ |
| |
frame_zero.Xnextframe = NULL; /* None are allocated yet */ |
| |
md->match_frames_base = &frame_zero; |
| |
#endif |
| |
|
| /* Check for the special magic call that measures the size of the stack used |
/* Check for the special magic call that measures the size of the stack used |
| per recursive call of match(). */ | per recursive call of match(). Without the funny casting for sizeof, a Windows |
| | compiler gave this error: "unary minus operator applied to unsigned type, |
| | result still unsigned". Hopefully the cast fixes that. */ |
| |
|
| if (re == NULL && extra_data == NULL && subject == NULL && length == -999 && |
if (re == NULL && extra_data == NULL && subject == NULL && length == -999 && |
| start_offset == -999) |
start_offset == -999) |
| #ifdef NO_RECURSE |
#ifdef NO_RECURSE |
| return -sizeof(heapframe); | return -((int)sizeof(heapframe)); |
| #else |
#else |
| return match(NULL, NULL, NULL, 0, NULL, NULL, 0); |
return match(NULL, NULL, NULL, 0, NULL, NULL, 0); |
| #endif |
#endif |
|
Line 6280 if (utf && (options & PCRE_NO_UTF8_CHECK) == 0)
|
Line 6455 if (utf && (options & PCRE_NO_UTF8_CHECK) == 0)
|
| /* If the pattern was successfully studied with JIT support, run the JIT |
/* If the pattern was successfully studied with JIT support, run the JIT |
| executable instead of the rest of this function. Most options must be set at |
executable instead of the rest of this function. Most options must be set at |
| compile time for the JIT code to be usable. Fallback to the normal code path if |
compile time for the JIT code to be usable. Fallback to the normal code path if |
| an unsupported flag is set. In particular, JIT does not support partial | an unsupported flag is set. */ |
| matching. */ | |
| |
|
| #ifdef SUPPORT_JIT |
#ifdef SUPPORT_JIT |
| if (extra_data != NULL |
if (extra_data != NULL |
| && (extra_data->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 | && (extra_data->flags & (PCRE_EXTRA_EXECUTABLE_JIT | |
| | PCRE_EXTRA_TABLES)) == PCRE_EXTRA_EXECUTABLE_JIT |
| && extra_data->executable_jit != NULL |
&& extra_data->executable_jit != NULL |
| && (extra_data->flags & PCRE_EXTRA_TABLES) == 0 |
|
| && (options & ~(PCRE_NO_UTF8_CHECK | PCRE_NOTBOL | PCRE_NOTEOL | |
&& (options & ~(PCRE_NO_UTF8_CHECK | PCRE_NOTBOL | PCRE_NOTEOL | |
| PCRE_NOTEMPTY | PCRE_NOTEMPTY_ATSTART)) == 0) | PCRE_NOTEMPTY | PCRE_NOTEMPTY_ATSTART | |
| return PRIV(jit_exec)(re, extra_data->executable_jit, | PCRE_PARTIAL_SOFT | PCRE_PARTIAL_HARD)) == 0) |
| (const pcre_uchar *)subject, length, start_offset, options, | { |
| ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) | rc = PRIV(jit_exec)(re, extra_data, (const pcre_uchar *)subject, length, |
| ? MATCH_LIMIT : extra_data->match_limit, offsets, offsetcount); | start_offset, options, offsets, offsetcount); |
| | |
| | /* PCRE_ERROR_NULL means that the selected normal or partial matching |
| | mode is not compiled. In this case we simply fallback to interpreter. */ |
| | |
| | if (rc != PCRE_ERROR_NULL) return rc; |
| | } |
| #endif |
#endif |
| |
|
| /* Carry on with non-JIT matching. This information is for finding all the |
/* Carry on with non-JIT matching. This information is for finding all the |
|
Line 6887 if (rc == MATCH_MATCH || rc == MATCH_ACCEPT)
|
Line 7067 if (rc == MATCH_MATCH || rc == MATCH_ACCEPT)
|
| { |
{ |
| register int *iptr, *iend; |
register int *iptr, *iend; |
| int resetcount = 2 + re->top_bracket * 2; |
int resetcount = 2 + re->top_bracket * 2; |
| if (resetcount > offsetcount) resetcount = ocount; | if (resetcount > offsetcount) resetcount = offsetcount; |
| iptr = offsets + md->end_offset_top; |
iptr = offsets + md->end_offset_top; |
| iend = offsets + resetcount; |
iend = offsets + resetcount; |
| while (iptr < iend) *iptr++ = -1; |
while (iptr < iend) *iptr++ = -1; |
|
Line 6908 if (rc == MATCH_MATCH || rc == MATCH_ACCEPT)
|
Line 7088 if (rc == MATCH_MATCH || rc == MATCH_ACCEPT)
|
| if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_MARK) != 0) |
if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_MARK) != 0) |
| *(extra_data->mark) = (pcre_uchar *)md->mark; |
*(extra_data->mark) = (pcre_uchar *)md->mark; |
| DPRINTF((">>>> returning %d\n", rc)); |
DPRINTF((">>>> returning %d\n", rc)); |
| |
#ifdef NO_RECURSE |
| |
release_match_heapframes(&frame_zero); |
| |
#endif |
| return rc; |
return rc; |
| } |
} |
| |
|
|
Line 6925 if (using_temporary_offsets)
|
Line 7108 if (using_temporary_offsets)
|
| if (rc != MATCH_NOMATCH && rc != PCRE_ERROR_PARTIAL) |
if (rc != MATCH_NOMATCH && rc != PCRE_ERROR_PARTIAL) |
| { |
{ |
| DPRINTF((">>>> error: returning %d\n", rc)); |
DPRINTF((">>>> error: returning %d\n", rc)); |
| |
#ifdef NO_RECURSE |
| |
release_match_heapframes(&frame_zero); |
| |
#endif |
| return rc; |
return rc; |
| } |
} |
| |
|
|
Line 6954 else
|
Line 7140 else
|
| |
|
| if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_MARK) != 0) |
if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_MARK) != 0) |
| *(extra_data->mark) = (pcre_uchar *)md->nomatch_mark; |
*(extra_data->mark) = (pcre_uchar *)md->nomatch_mark; |
| |
#ifdef NO_RECURSE |
| |
release_match_heapframes(&frame_zero); |
| |
#endif |
| return rc; |
return rc; |
| } |
} |
| |
|