#include "config.h"
#define NLBLOCK md
#define PSSTART start_subject
#define PSEND end_subject
#include "pcre_internal.h"
#undef min
#undef max
#define CAPLMASK 0x0000ffff
#define OVFLMASK 0xffff0000
#define OVFLBIT 0x00010000
#define MATCH_CONDASSERT 1
#define MATCH_CBEGROUP 2
#define MATCH_MATCH 1
#define MATCH_NOMATCH 0
#define MATCH_ACCEPT (-999)
#define MATCH_KETRPOS (-998)
#define MATCH_ONCE (-997)
#define MATCH_COMMIT (-996)
#define MATCH_PRUNE (-995)
#define MATCH_SKIP (-994)
#define MATCH_SKIP_ARG (-993)
#define MATCH_THEN (-992)
#define MATCH_BACKTRACK_MAX MATCH_THEN
#define MATCH_BACKTRACK_MIN MATCH_COMMIT
#define REC_STACK_SAVE_MAX 30
static const char rep_min[] = { 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, };
static const char rep_max[] = { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, };
#ifdef PCRE_DEBUG
static void
pchars(const pcre_uchar *p, int length, BOOL is_subject, match_data *md)
{
pcre_uint32 c;
BOOL utf = md->utf;
if (is_subject && length > md->end_subject - p) length = md->end_subject - p;
while (length-- > 0)
if (isprint(c = UCHAR21INCTEST(p))) printf("%c", (char)c); else printf("\\x{%02x}", c);
}
#endif
static int
match_ref(int offset, register PCRE_PUCHAR eptr, int length, match_data *md,
BOOL caseless)
{
PCRE_PUCHAR eptr_start = eptr;
register PCRE_PUCHAR p = md->start_subject + md->offset_vector[offset];
#if defined SUPPORT_UTF && defined SUPPORT_UCP
BOOL utf = md->utf;
#endif
#ifdef PCRE_DEBUG
if (eptr >= md->end_subject)
printf("matching subject <null>");
else
{
printf("matching subject ");
pchars(eptr, length, TRUE, md);
}
printf(" against backref ");
pchars(p, length, FALSE, md);
printf("\n");
#endif
if (length < 0) return -1;
if (caseless)
{
#if defined SUPPORT_UTF && defined SUPPORT_UCP
if (utf)
{
PCRE_PUCHAR endptr = p + length;
while (p < endptr)
{
pcre_uint32 c, d;
const ucd_record *ur;
if (eptr >= md->end_subject) return -2;
GETCHARINC(c, eptr);
GETCHARINC(d, p);
ur = GET_UCD(d);
if (c != d && c != d + ur->other_case)
{
const pcre_uint32 *pp = PRIV(ucd_caseless_sets) + ur->caseset;
for (;;)
{
if (c < *pp) return -1;
if (c == *pp++) break;
}
}
}
}
else
#endif
{
while (length-- > 0)
{
pcre_uint32 cc, cp;
if (eptr >= md->end_subject) return -2;
cc = UCHAR21TEST(eptr);
cp = UCHAR21TEST(p);
if (TABLE_GET(cp, md->lcc, cp) != TABLE_GET(cc, md->lcc, cc)) return -1;
p++;
eptr++;
}
}
}
else
{
while (length-- > 0)
{
if (eptr >= md->end_subject) return -2;
if (UCHAR21INCTEST(p) != UCHAR21INCTEST(eptr)) return -1;
}
}
return (int)(eptr - eptr_start);
}
enum { RM1=1, RM2, RM3, RM4, RM5, RM6, RM7, RM8, RM9, RM10,
RM11, RM12, RM13, RM14, RM15, RM16, RM17, RM18, RM19, RM20,
RM21, RM22, RM23, RM24, RM25, RM26, RM27, RM28, RM29, RM30,
RM31, RM32, RM33, RM34, RM35, RM36, RM37, RM38, RM39, RM40,
RM41, RM42, RM43, RM44, RM45, RM46, RM47, RM48, RM49, RM50,
RM51, RM52, RM53, RM54, RM55, RM56, RM57, RM58, RM59, RM60,
RM61, RM62, RM63, RM64, RM65, RM66, RM67 };
#ifndef NO_RECURSE
#define REGISTER register
#ifdef PCRE_DEBUG
#define RMATCH(ra,rb,rc,rd,re,rw) \
{ \
printf("match() called in line %d\n", __LINE__); \
rrc = match(ra,rb,mstart,rc,rd,re,rdepth+1); \
printf("to line %d\n", __LINE__); \
}
#define RRETURN(ra) \
{ \
printf("match() returned %d from line %d\n", ra, __LINE__); \
return ra; \
}
#else
#define RMATCH(ra,rb,rc,rd,re,rw) \
rrc = match(ra,rb,mstart,rc,rd,re,rdepth+1)
#define RRETURN(ra) return ra
#endif
#else
#define REGISTER
#define RMATCH(ra,rb,rc,rd,re,rw)\
{\
heapframe *newframe = frame->Xnextframe;\
if (newframe == NULL)\
{\
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->Xecode = rb;\
newframe->Xmstart = mstart;\
newframe->Xoffset_top = rc;\
newframe->Xeptrb = re;\
newframe->Xrdepth = frame->Xrdepth + 1;\
newframe->Xprevframe = frame;\
frame = newframe;\
DPRINTF(("restarting from line %d\n", __LINE__));\
goto HEAP_RECURSE;\
L_##rw:\
DPRINTF(("jumped back to line %d\n", __LINE__));\
}
#define RRETURN(ra)\
{\
heapframe *oldframe = frame;\
frame = oldframe->Xprevframe;\
if (frame != NULL)\
{\
rrc = ra;\
goto HEAP_RETURN;\
}\
return ra;\
}
typedef struct heapframe {
struct heapframe *Xprevframe;
struct heapframe *Xnextframe;
PCRE_PUCHAR Xeptr;
const pcre_uchar *Xecode;
PCRE_PUCHAR Xmstart;
int Xoffset_top;
eptrblock *Xeptrb;
unsigned int Xrdepth;
PCRE_PUCHAR Xcallpat;
#ifdef SUPPORT_UTF
PCRE_PUCHAR Xcharptr;
#endif
PCRE_PUCHAR Xdata;
PCRE_PUCHAR Xnext;
PCRE_PUCHAR Xpp;
PCRE_PUCHAR Xprev;
PCRE_PUCHAR Xsaved_eptr;
recursion_info Xnew_recursive;
BOOL Xcur_is_word;
BOOL Xcondition;
BOOL Xprev_is_word;
#ifdef SUPPORT_UCP
int Xprop_type;
unsigned int Xprop_value;
int Xprop_fail_result;
int Xoclength;
pcre_uchar Xocchars[6];
#endif
int Xcodelink;
int Xctype;
unsigned int Xfc;
int Xfi;
int Xlength;
int Xmax;
int Xmin;
unsigned int Xnumber;
int Xoffset;
unsigned int Xop;
pcre_int32 Xsave_capture_last;
int Xsave_offset1, Xsave_offset2, Xsave_offset3;
int Xstacksave[REC_STACK_SAVE_MAX];
eptrblock Xnewptrb;
int Xwhere;
} heapframe;
#endif
#define CHECK_PARTIAL()\
if (md->partial != 0 && eptr >= md->end_subject && \
eptr > md->start_used_ptr) \
{ \
md->hitend = TRUE; \
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); \
}
#define SCHECK_PARTIAL()\
if (md->partial != 0 && eptr > md->start_used_ptr) \
{ \
md->hitend = TRUE; \
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); \
}
static int
match(REGISTER PCRE_PUCHAR eptr, REGISTER const pcre_uchar *ecode,
PCRE_PUCHAR mstart, int offset_top, match_data *md, eptrblock *eptrb,
unsigned int rdepth)
{
register int rrc;
register int i;
register pcre_uint32 c;
register BOOL utf;
BOOL minimize, possessive;
BOOL caseless;
int condcode;
#ifdef NO_RECURSE
heapframe *frame = (heapframe *)md->match_frames_base;
frame->Xeptr = eptr;
frame->Xecode = ecode;
frame->Xmstart = mstart;
frame->Xoffset_top = offset_top;
frame->Xeptrb = eptrb;
frame->Xrdepth = rdepth;
HEAP_RECURSE:
#define eptr frame->Xeptr
#define ecode frame->Xecode
#define mstart frame->Xmstart
#define offset_top frame->Xoffset_top
#define eptrb frame->Xeptrb
#define rdepth frame->Xrdepth
#ifdef SUPPORT_UTF
#define charptr frame->Xcharptr
#endif
#define callpat frame->Xcallpat
#define codelink frame->Xcodelink
#define data frame->Xdata
#define next frame->Xnext
#define pp frame->Xpp
#define prev frame->Xprev
#define saved_eptr frame->Xsaved_eptr
#define new_recursive frame->Xnew_recursive
#define cur_is_word frame->Xcur_is_word
#define condition frame->Xcondition
#define prev_is_word frame->Xprev_is_word
#ifdef SUPPORT_UCP
#define prop_type frame->Xprop_type
#define prop_value frame->Xprop_value
#define prop_fail_result frame->Xprop_fail_result
#define oclength frame->Xoclength
#define occhars frame->Xocchars
#endif
#define ctype frame->Xctype
#define fc frame->Xfc
#define fi frame->Xfi
#define length frame->Xlength
#define max frame->Xmax
#define min frame->Xmin
#define number frame->Xnumber
#define offset frame->Xoffset
#define op frame->Xop
#define save_capture_last frame->Xsave_capture_last
#define save_offset1 frame->Xsave_offset1
#define save_offset2 frame->Xsave_offset2
#define save_offset3 frame->Xsave_offset3
#define stacksave frame->Xstacksave
#define newptrb frame->Xnewptrb
#else
#define fi i
#define fc c
#ifdef SUPPORT_UTF
const pcre_uchar *charptr;
#endif
const pcre_uchar *callpat;
const pcre_uchar *data;
const pcre_uchar *next;
PCRE_PUCHAR pp;
const pcre_uchar *prev;
PCRE_PUCHAR saved_eptr;
recursion_info new_recursive;
BOOL cur_is_word;
BOOL condition;
BOOL prev_is_word;
#ifdef SUPPORT_UCP
int prop_type;
unsigned int prop_value;
int prop_fail_result;
int oclength;
pcre_uchar occhars[6];
#endif
int codelink;
int ctype;
int length;
int max;
int min;
unsigned int number;
int offset;
unsigned int op;
pcre_int32 save_capture_last;
int save_offset1, save_offset2, save_offset3;
int stacksave[REC_STACK_SAVE_MAX];
eptrblock newptrb;
if (ecode == NULL)
{
if (rdepth == 0)
return match((PCRE_PUCHAR)&rdepth, NULL, NULL, 0, NULL, NULL, 1);
else
{
int len = (char *)&rdepth - (char *)eptr;
return (len > 0)? -len : len;
}
}
#endif
#define allow_zero cur_is_word
#define cbegroup condition
#define code_offset codelink
#define condassert condition
#define matched_once prev_is_word
#define foc number
#define save_mark data
#ifdef SUPPORT_UCP
prop_value = 0;
prop_fail_result = 0;
#endif
TAIL_RECURSE:
#ifdef SUPPORT_UTF
utf = md->utf;
#else
utf = FALSE;
#endif
if (md->match_call_count++ >= md->match_limit) RRETURN(PCRE_ERROR_MATCHLIMIT);
if (rdepth >= md->match_limit_recursion) RRETURN(PCRE_ERROR_RECURSIONLIMIT);
if (md->match_function_type == MATCH_CBEGROUP)
{
newptrb.epb_saved_eptr = eptr;
newptrb.epb_prev = eptrb;
eptrb = &newptrb;
md->match_function_type = 0;
}
for (;;)
{
minimize = possessive = FALSE;
op = *ecode;
switch(op)
{
case OP_MARK:
md->nomatch_mark = ecode + 2;
md->mark = NULL;
RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, md,
eptrb, RM55);
if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) &&
md->mark == NULL) md->mark = ecode + 2;
else if (rrc == MATCH_SKIP_ARG &&
STRCMP_UC_UC_TEST(ecode + 2, md->start_match_ptr) == 0)
{
md->start_match_ptr = eptr;
RRETURN(MATCH_SKIP);
}
RRETURN(rrc);
case OP_FAIL:
RRETURN(MATCH_NOMATCH);
case OP_COMMIT:
RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
eptrb, RM52);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
RRETURN(MATCH_COMMIT);
case OP_PRUNE:
RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
eptrb, RM51);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
RRETURN(MATCH_PRUNE);
case OP_PRUNE_ARG:
md->nomatch_mark = ecode + 2;
md->mark = NULL;
RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, md,
eptrb, RM56);
if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) &&
md->mark == NULL) md->mark = ecode + 2;
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
RRETURN(MATCH_PRUNE);
case OP_SKIP:
RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
eptrb, RM53);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
md->start_match_ptr = eptr;
RRETURN(MATCH_SKIP);
case OP_SKIP_ARG:
md->skip_arg_count++;
if (md->skip_arg_count <= md->ignore_skip_arg)
{
ecode += PRIV(OP_lengths)[*ecode] + ecode[1];
break;
}
RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, md,
eptrb, RM57);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
md->start_match_ptr = ecode + 2;
RRETURN(MATCH_SKIP_ARG);
case OP_THEN:
RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
eptrb, RM54);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
md->start_match_ptr = ecode;
RRETURN(MATCH_THEN);
case OP_THEN_ARG:
md->nomatch_mark = ecode + 2;
md->mark = NULL;
RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top,
md, eptrb, RM58);
if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) &&
md->mark == NULL) md->mark = ecode + 2;
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
md->start_match_ptr = ecode;
RRETURN(MATCH_THEN);
case OP_ONCE_NC:
prev = ecode;
saved_eptr = eptr;
save_mark = md->mark;
do
{
RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM64);
if (rrc == MATCH_MATCH)
{
mstart = md->start_match_ptr;
break;
}
if (rrc == MATCH_THEN)
{
next = ecode + GET(ecode,1);
if (md->start_match_ptr < next &&
(*ecode == OP_ALT || *next == OP_ALT))
rrc = MATCH_NOMATCH;
}
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
ecode += GET(ecode,1);
md->mark = save_mark;
}
while (*ecode == OP_ALT);
if (*ecode != OP_ONCE_NC && *ecode != OP_ALT) RRETURN(MATCH_NOMATCH);
do ecode += GET(ecode, 1); while (*ecode == OP_ALT);
offset_top = md->end_offset_top;
eptr = md->end_match_ptr;
if (*ecode == OP_KET || eptr == saved_eptr)
{
ecode += 1+LINK_SIZE;
break;
}
if (*ecode == OP_KETRMIN)
{
RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM65);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
ecode = prev;
goto TAIL_RECURSE;
}
else
{
RMATCH(eptr, prev, offset_top, md, eptrb, RM66);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
ecode += 1 + LINK_SIZE;
goto TAIL_RECURSE;
}
case OP_CBRA:
case OP_SCBRA:
number = GET2(ecode, 1+LINK_SIZE);
offset = number << 1;
#ifdef PCRE_DEBUG
printf("start bracket %d\n", number);
printf("subject=");
pchars(eptr, 16, TRUE, md);
printf("\n");
#endif
if (offset < md->offset_max)
{
save_offset1 = md->offset_vector[offset];
save_offset2 = md->offset_vector[offset+1];
save_offset3 = md->offset_vector[md->offset_end - number];
save_capture_last = md->capture_last;
save_mark = md->mark;
DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3));
md->offset_vector[md->offset_end - number] =
(int)(eptr - md->start_subject);
for (;;)
{
if (op >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP;
RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
eptrb, RM1);
if (rrc == MATCH_ONCE) break;
if (rrc == MATCH_THEN)
{
next = ecode + GET(ecode,1);
if (md->start_match_ptr < next &&
(*ecode == OP_ALT || *next == OP_ALT))
rrc = MATCH_NOMATCH;
}
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
md->capture_last = save_capture_last;
ecode += GET(ecode, 1);
md->mark = save_mark;
if (*ecode != OP_ALT) break;
}
DPRINTF(("bracket %d failed\n", number));
md->offset_vector[offset] = save_offset1;
md->offset_vector[offset+1] = save_offset2;
md->offset_vector[md->offset_end - number] = save_offset3;
RRETURN(rrc);
}
DPRINTF(("insufficient capture room: treat as non-capturing\n"));
case OP_ONCE:
case OP_BRA:
case OP_SBRA:
DPRINTF(("start non-capturing bracket\n"));
for (;;)
{
if (op >= OP_SBRA || op == OP_ONCE)
md->match_function_type = MATCH_CBEGROUP;
else if (!md->hasthen && ecode[GET(ecode, 1)] != OP_ALT)
{
ecode += PRIV(OP_lengths)[*ecode];
goto TAIL_RECURSE;
}
save_mark = md->mark;
save_capture_last = md->capture_last;
RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, eptrb,
RM2);
if (rrc == MATCH_THEN)
{
next = ecode + GET(ecode,1);
if (md->start_match_ptr < next &&
(*ecode == OP_ALT || *next == OP_ALT))
rrc = MATCH_NOMATCH;
}
if (rrc != MATCH_NOMATCH)
{
if (rrc == MATCH_ONCE)
{
const pcre_uchar *scode = ecode;
if (*scode != OP_ONCE)
{
while (*scode == OP_ALT) scode += GET(scode, 1);
scode -= GET(scode, 1);
}
if (md->once_target == scode) rrc = MATCH_NOMATCH;
}
RRETURN(rrc);
}
ecode += GET(ecode, 1);
md->mark = save_mark;
if (*ecode != OP_ALT) break;
md->capture_last = save_capture_last;
}
RRETURN(MATCH_NOMATCH);
case OP_CBRAPOS:
case OP_SCBRAPOS:
allow_zero = FALSE;
POSSESSIVE_CAPTURE:
number = GET2(ecode, 1+LINK_SIZE);
offset = number << 1;
#ifdef PCRE_DEBUG
printf("start possessive bracket %d\n", number);
printf("subject=");
pchars(eptr, 16, TRUE, md);
printf("\n");
#endif
if (offset >= md->offset_max) goto POSSESSIVE_NON_CAPTURE;
matched_once = FALSE;
code_offset = (int)(ecode - md->start_code);
save_offset1 = md->offset_vector[offset];
save_offset2 = md->offset_vector[offset+1];
save_offset3 = md->offset_vector[md->offset_end - number];
save_capture_last = md->capture_last;
DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3));
for (;;)
{
md->offset_vector[md->offset_end - number] =
(int)(eptr - md->start_subject);
if (op >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP;
RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
eptrb, RM63);
if (rrc == MATCH_KETRPOS)
{
offset_top = md->end_offset_top;
ecode = md->start_code + code_offset;
save_capture_last = md->capture_last;
matched_once = TRUE;
mstart = md->start_match_ptr;
if (eptr == md->end_match_ptr)
{
do ecode += GET(ecode, 1); while (*ecode == OP_ALT);
break;
}
eptr = md->end_match_ptr;
continue;
}
if (rrc == MATCH_THEN)
{
next = ecode + GET(ecode,1);
if (md->start_match_ptr < next &&
(*ecode == OP_ALT || *next == OP_ALT))
rrc = MATCH_NOMATCH;
}
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
md->capture_last = save_capture_last;
ecode += GET(ecode, 1);
if (*ecode != OP_ALT) break;
}
if (!matched_once)
{
md->offset_vector[offset] = save_offset1;
md->offset_vector[offset+1] = save_offset2;
md->offset_vector[md->offset_end - number] = save_offset3;
}
if (allow_zero || matched_once)
{
ecode += 1 + LINK_SIZE;
break;
}
RRETURN(MATCH_NOMATCH);
case OP_BRAPOS:
case OP_SBRAPOS:
allow_zero = FALSE;
POSSESSIVE_NON_CAPTURE:
matched_once = FALSE;
code_offset = (int)(ecode - md->start_code);
save_capture_last = md->capture_last;
for (;;)
{
if (op >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP;
RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
eptrb, RM48);
if (rrc == MATCH_KETRPOS)
{
offset_top = md->end_offset_top;
ecode = md->start_code + code_offset;
matched_once = TRUE;
mstart = md->start_match_ptr;
if (eptr == md->end_match_ptr)
{
do ecode += GET(ecode, 1); while (*ecode == OP_ALT);
break;
}
eptr = md->end_match_ptr;
continue;
}
if (rrc == MATCH_THEN)
{
next = ecode + GET(ecode,1);
if (md->start_match_ptr < next &&
(*ecode == OP_ALT || *next == OP_ALT))
rrc = MATCH_NOMATCH;
}
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
ecode += GET(ecode, 1);
if (*ecode != OP_ALT) break;
md->capture_last = save_capture_last;
}
if (matched_once || allow_zero)
{
ecode += 1 + LINK_SIZE;
break;
}
RRETURN(MATCH_NOMATCH);
case OP_COND:
case OP_SCOND:
codelink = GET(ecode, 1);
ecode += 1 + LINK_SIZE;
if (*ecode == OP_CALLOUT)
{
if (PUBL(callout) != NULL)
{
PUBL(callout_block) cb;
cb.version = 2;
cb.callout_number = ecode[1];
cb.offset_vector = md->offset_vector;
#if defined COMPILE_PCRE8
cb.subject = (PCRE_SPTR)md->start_subject;
#elif defined COMPILE_PCRE16
cb.subject = (PCRE_SPTR16)md->start_subject;
#elif defined COMPILE_PCRE32
cb.subject = (PCRE_SPTR32)md->start_subject;
#endif
cb.subject_length = (int)(md->end_subject - md->start_subject);
cb.start_match = (int)(mstart - md->start_subject);
cb.current_position = (int)(eptr - md->start_subject);
cb.pattern_position = GET(ecode, 2);
cb.next_item_length = GET(ecode, 2 + LINK_SIZE);
cb.capture_top = offset_top/2;
cb.capture_last = md->capture_last & CAPLMASK;
if (cb.capture_last == 0) cb.capture_last = -1;
cb.callout_data = md->callout_data;
cb.mark = md->nomatch_mark;
if ((rrc = (*PUBL(callout))(&cb)) > 0) RRETURN(MATCH_NOMATCH);
if (rrc < 0) RRETURN(rrc);
}
ecode += PRIV(OP_lengths)[OP_CALLOUT];
codelink -= PRIV(OP_lengths)[OP_CALLOUT];
}
condition = FALSE;
switch(condcode = *ecode)
{
case OP_RREF:
if (md->recursive != NULL)
{
unsigned int recno = GET2(ecode, 1);
condition = (recno == RREF_ANY || recno == md->recursive->group_num);
}
break;
case OP_DNRREF:
if (md->recursive != NULL)
{
int count = GET2(ecode, 1 + IMM2_SIZE);
pcre_uchar *slot = md->name_table + GET2(ecode, 1) * md->name_entry_size;
while (count-- > 0)
{
unsigned int recno = GET2(slot, 0);
condition = recno == md->recursive->group_num;
if (condition) break;
slot += md->name_entry_size;
}
}
break;
case OP_CREF:
offset = GET2(ecode, 1) << 1;
condition = offset < offset_top && md->offset_vector[offset] >= 0;
break;
case OP_DNCREF:
{
int count = GET2(ecode, 1 + IMM2_SIZE);
pcre_uchar *slot = md->name_table + GET2(ecode, 1) * md->name_entry_size;
while (count-- > 0)
{
offset = GET2(slot, 0) << 1;
condition = offset < offset_top && md->offset_vector[offset] >= 0;
if (condition) break;
slot += md->name_entry_size;
}
}
break;
case OP_DEF:
case OP_FAIL:
break;
default:
md->match_function_type = MATCH_CONDASSERT;
RMATCH(eptr, ecode, offset_top, md, NULL, RM3);
if (rrc == MATCH_MATCH)
{
if (md->end_offset_top > offset_top)
offset_top = md->end_offset_top;
condition = TRUE;
if (*ecode == OP_BRAZERO) ecode++;
ecode += GET(ecode, 1);
while (*ecode == OP_ALT) ecode += GET(ecode, 1);
ecode += 1 + LINK_SIZE - PRIV(OP_lengths)[condcode];
}
else if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN)
{
RRETURN(rrc);
}
break;
}
ecode += condition? PRIV(OP_lengths)[condcode] : codelink;
if (condition || ecode[-(1+LINK_SIZE)] == OP_ALT)
{
if (op != OP_SCOND)
{
goto TAIL_RECURSE;
}
md->match_function_type = MATCH_CBEGROUP;
RMATCH(eptr, ecode, offset_top, md, eptrb, RM49);
RRETURN(rrc);
}
else
{
}
break;
case OP_CLOSE:
number = GET2(ecode, 1);
offset = number << 1;
#ifdef PCRE_DEBUG
printf("end bracket %d at *ACCEPT", number);
printf("\n");
#endif
md->capture_last = (md->capture_last & OVFLMASK) | number;
if (offset >= md->offset_max) md->capture_last |= OVFLBIT; else
{
md->offset_vector[offset] =
md->offset_vector[md->offset_end - number];
md->offset_vector[offset+1] = (int)(eptr - md->start_subject);
if (offset >= offset_top)
{
register int *iptr = md->offset_vector + offset_top;
register int *iend = md->offset_vector + offset;
while (iptr < iend) *iptr++ = -1;
offset_top = offset + 2;
}
}
ecode += 1 + IMM2_SIZE;
break;
case OP_END:
case OP_ACCEPT:
case OP_ASSERT_ACCEPT:
if (eptr == mstart && op != OP_ASSERT_ACCEPT &&
md->recursive == NULL &&
(md->notempty ||
(md->notempty_atstart &&
mstart == md->start_subject + md->start_offset)))
RRETURN(MATCH_NOMATCH);
md->end_match_ptr = eptr;
md->end_offset_top = offset_top;
md->start_match_ptr = mstart;
rrc = (op == OP_END)? MATCH_MATCH : MATCH_ACCEPT;
RRETURN(rrc);
case OP_ASSERT:
case OP_ASSERTBACK:
save_mark = md->mark;
if (md->match_function_type == MATCH_CONDASSERT)
{
condassert = TRUE;
md->match_function_type = 0;
}
else condassert = FALSE;
do
{
RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, RM4);
if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT)
{
mstart = md->start_match_ptr;
break;
}
md->mark = save_mark;
if (rrc == MATCH_THEN)
{
next = ecode + GET(ecode,1);
if (md->start_match_ptr < next &&
(*ecode == OP_ALT || *next == OP_ALT))
rrc = MATCH_NOMATCH;
}
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
ecode += GET(ecode, 1);
}
while (*ecode == OP_ALT);
if (*ecode == OP_KET) RRETURN(MATCH_NOMATCH);
if (condassert) RRETURN(MATCH_MATCH);
do ecode += GET(ecode,1); while (*ecode == OP_ALT);
ecode += 1 + LINK_SIZE;
offset_top = md->end_offset_top;
continue;
case OP_ASSERT_NOT:
case OP_ASSERTBACK_NOT:
save_mark = md->mark;
if (md->match_function_type == MATCH_CONDASSERT)
{
condassert = TRUE;
md->match_function_type = 0;
}
else condassert = FALSE;
do
{
RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, RM5);
md->mark = save_mark;
switch(rrc)
{
case MATCH_MATCH:
case MATCH_ACCEPT:
RRETURN(MATCH_NOMATCH);
case MATCH_NOMATCH:
break;
case MATCH_THEN:
next = ecode + GET(ecode,1);
if (md->start_match_ptr < next &&
(*ecode == OP_ALT || *next == OP_ALT))
{
rrc = MATCH_NOMATCH;
break;
}
case MATCH_COMMIT:
case MATCH_SKIP:
case MATCH_SKIP_ARG:
case MATCH_PRUNE:
do ecode += GET(ecode,1); while (*ecode == OP_ALT);
goto NEG_ASSERT_TRUE;
default:
RRETURN(rrc);
}
ecode += GET(ecode,1);
}
while (*ecode == OP_ALT);
NEG_ASSERT_TRUE:
if (condassert) RRETURN(MATCH_MATCH);
ecode += 1 + LINK_SIZE;
continue;
case OP_REVERSE:
#ifdef SUPPORT_UTF
if (utf)
{
i = GET(ecode, 1);
while (i-- > 0)
{
eptr--;
if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH);
BACKCHAR(eptr);
}
}
else
#endif
{
eptr -= GET(ecode, 1);
if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH);
}
if (eptr < md->start_used_ptr) md->start_used_ptr = eptr;
ecode += 1 + LINK_SIZE;
break;
case OP_CALLOUT:
if (PUBL(callout) != NULL)
{
PUBL(callout_block) cb;
cb.version = 2;
cb.callout_number = ecode[1];
cb.offset_vector = md->offset_vector;
#if defined COMPILE_PCRE8
cb.subject = (PCRE_SPTR)md->start_subject;
#elif defined COMPILE_PCRE16
cb.subject = (PCRE_SPTR16)md->start_subject;
#elif defined COMPILE_PCRE32
cb.subject = (PCRE_SPTR32)md->start_subject;
#endif
cb.subject_length = (int)(md->end_subject - md->start_subject);
cb.start_match = (int)(mstart - md->start_subject);
cb.current_position = (int)(eptr - md->start_subject);
cb.pattern_position = GET(ecode, 2);
cb.next_item_length = GET(ecode, 2 + LINK_SIZE);
cb.capture_top = offset_top/2;
cb.capture_last = md->capture_last & CAPLMASK;
if (cb.capture_last == 0) cb.capture_last = -1;
cb.callout_data = md->callout_data;
cb.mark = md->nomatch_mark;
if ((rrc = (*PUBL(callout))(&cb)) > 0) RRETURN(MATCH_NOMATCH);
if (rrc < 0) RRETURN(rrc);
}
ecode += 2 + 2*LINK_SIZE;
break;
case OP_RECURSE:
{
recursion_info *ri;
unsigned int recno;
callpat = md->start_code + GET(ecode, 1);
recno = (callpat == md->start_code)? 0 :
GET2(callpat, 1 + LINK_SIZE);
for (ri = md->recursive; ri != NULL; ri = ri->prevrec)
if (recno == ri->group_num && eptr == ri->subject_position)
RRETURN(PCRE_ERROR_RECURSELOOP);
new_recursive.group_num = recno;
new_recursive.saved_capture_last = md->capture_last;
new_recursive.subject_position = eptr;
new_recursive.prevrec = md->recursive;
md->recursive = &new_recursive;
ecode += 1 + LINK_SIZE;
new_recursive.saved_max = md->offset_end;
if (new_recursive.saved_max <= REC_STACK_SAVE_MAX)
new_recursive.offset_save = stacksave;
else
{
new_recursive.offset_save =
(int *)(PUBL(malloc))(new_recursive.saved_max * sizeof(int));
if (new_recursive.offset_save == NULL) RRETURN(PCRE_ERROR_NOMEMORY);
}
memcpy(new_recursive.offset_save, md->offset_vector,
new_recursive.saved_max * sizeof(int));
DPRINTF(("Recursing into group %d\n", new_recursive.group_num));
cbegroup = (*callpat >= OP_SBRA);
do
{
if (cbegroup) md->match_function_type = MATCH_CBEGROUP;
RMATCH(eptr, callpat + PRIV(OP_lengths)[*callpat], offset_top,
md, eptrb, RM6);
memcpy(md->offset_vector, new_recursive.offset_save,
new_recursive.saved_max * sizeof(int));
md->capture_last = new_recursive.saved_capture_last;
md->recursive = new_recursive.prevrec;
if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT)
{
DPRINTF(("Recursion matched\n"));
if (new_recursive.offset_save != stacksave)
(PUBL(free))(new_recursive.offset_save);
eptr = md->end_match_ptr;
mstart = md->start_match_ptr;
goto RECURSION_MATCHED;
}
if (rrc >= MATCH_BACKTRACK_MIN && rrc <= MATCH_BACKTRACK_MAX)
{
if (new_recursive.offset_save != stacksave)
(PUBL(free))(new_recursive.offset_save);
RRETURN(MATCH_NOMATCH);
}
if (rrc != MATCH_NOMATCH)
{
DPRINTF(("Recursion gave error %d\n", rrc));
if (new_recursive.offset_save != stacksave)
(PUBL(free))(new_recursive.offset_save);
RRETURN(rrc);
}
md->recursive = &new_recursive;
callpat += GET(callpat, 1);
}
while (*callpat == OP_ALT);
DPRINTF(("Recursion didn't match\n"));
md->recursive = new_recursive.prevrec;
if (new_recursive.offset_save != stacksave)
(PUBL(free))(new_recursive.offset_save);
RRETURN(MATCH_NOMATCH);
}
RECURSION_MATCHED:
break;
case OP_ALT:
do ecode += GET(ecode,1); while (*ecode == OP_ALT);
break;
case OP_BRAZERO:
next = ecode + 1;
RMATCH(eptr, next, offset_top, md, eptrb, RM10);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
do next += GET(next, 1); while (*next == OP_ALT);
ecode = next + 1 + LINK_SIZE;
break;
case OP_BRAMINZERO:
next = ecode + 1;
do next += GET(next, 1); while (*next == OP_ALT);
RMATCH(eptr, next + 1+LINK_SIZE, offset_top, md, eptrb, RM11);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
ecode++;
break;
case OP_SKIPZERO:
next = ecode+1;
do next += GET(next,1); while (*next == OP_ALT);
ecode = next + 1 + LINK_SIZE;
break;
case OP_BRAPOSZERO:
op = *(++ecode);
allow_zero = TRUE;
if (op == OP_CBRAPOS || op == OP_SCBRAPOS) goto POSSESSIVE_CAPTURE;
goto POSSESSIVE_NON_CAPTURE;
case OP_KET:
case OP_KETRMIN:
case OP_KETRMAX:
case OP_KETRPOS:
prev = ecode - GET(ecode, 1);
if (*prev >= OP_SBRA || *prev == OP_ONCE)
{
saved_eptr = eptrb->epb_saved_eptr;
eptrb = eptrb->epb_prev;
}
else saved_eptr = NULL;
if ((*prev >= OP_ASSERT && *prev <= OP_ASSERTBACK_NOT) ||
*prev == OP_ONCE_NC)
{
md->end_match_ptr = eptr;
md->end_offset_top = offset_top;
md->start_match_ptr = mstart;
RRETURN(MATCH_MATCH);
}
if (*prev == OP_CBRA || *prev == OP_SCBRA ||
*prev == OP_CBRAPOS || *prev == OP_SCBRAPOS)
{
number = GET2(prev, 1+LINK_SIZE);
offset = number << 1;
#ifdef PCRE_DEBUG
printf("end bracket %d", number);
printf("\n");
#endif
if (md->recursive != NULL && md->recursive->group_num == number)
{
md->end_match_ptr = eptr;
md->start_match_ptr = mstart;
RRETURN(MATCH_MATCH);
}
md->capture_last = (md->capture_last & OVFLMASK) | number;
if (offset >= md->offset_max) md->capture_last |= OVFLBIT; else
{
if (offset > offset_top)
{
register int *iptr = md->offset_vector + offset_top;
register int *iend = md->offset_vector + offset;
while (iptr < iend) *iptr++ = -1;
}
md->offset_vector[offset] =
md->offset_vector[md->offset_end - number];
md->offset_vector[offset+1] = (int)(eptr - md->start_subject);
if (offset_top <= offset) offset_top = offset + 2;
}
}
if (*ecode == OP_KETRPOS)
{
md->start_match_ptr = mstart;
md->end_match_ptr = eptr;
md->end_offset_top = offset_top;
RRETURN(MATCH_KETRPOS);
}
if (*ecode == OP_KET || eptr == saved_eptr)
{
if (*prev == OP_ONCE)
{
RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM12);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
md->once_target = prev;
RRETURN(MATCH_ONCE);
}
ecode += 1 + LINK_SIZE;
break;
}
if (*ecode == OP_KETRMIN)
{
RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM7);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (*prev == OP_ONCE)
{
RMATCH(eptr, prev, offset_top, md, eptrb, RM8);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
md->once_target = prev;
RRETURN(MATCH_ONCE);
}
if (*prev >= OP_SBRA)
{
RMATCH(eptr, prev, offset_top, md, eptrb, RM50);
RRETURN(rrc);
}
ecode = prev;
goto TAIL_RECURSE;
}
else
{
RMATCH(eptr, prev, offset_top, md, eptrb, RM13);
if (rrc == MATCH_ONCE && md->once_target == prev) rrc = MATCH_NOMATCH;
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (*prev == OP_ONCE)
{
RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM9);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
md->once_target = prev;
RRETURN(MATCH_ONCE);
}
ecode += 1 + LINK_SIZE;
goto TAIL_RECURSE;
}
case OP_CIRC:
if (md->notbol && eptr == md->start_subject) RRETURN(MATCH_NOMATCH);
case OP_SOD:
if (eptr != md->start_subject) RRETURN(MATCH_NOMATCH);
ecode++;
break;
case OP_CIRCM:
if (md->notbol && eptr == md->start_subject) RRETURN(MATCH_NOMATCH);
if (eptr != md->start_subject &&
(eptr == md->end_subject || !WAS_NEWLINE(eptr)))
RRETURN(MATCH_NOMATCH);
ecode++;
break;
case OP_SOM:
if (eptr != md->start_subject + md->start_offset) RRETURN(MATCH_NOMATCH);
ecode++;
break;
case OP_SET_SOM:
mstart = eptr;
ecode++;
break;
case OP_DOLLM:
if (eptr < md->end_subject)
{
if (!IS_NEWLINE(eptr))
{
if (md->partial != 0 &&
eptr + 1 >= md->end_subject &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
UCHAR21TEST(eptr) == NLBLOCK->nl[0])
{
md->hitend = TRUE;
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
}
RRETURN(MATCH_NOMATCH);
}
}
else
{
if (md->noteol) RRETURN(MATCH_NOMATCH);
SCHECK_PARTIAL();
}
ecode++;
break;
case OP_DOLL:
if (md->noteol) RRETURN(MATCH_NOMATCH);
if (!md->endonly) goto ASSERT_NL_OR_EOS;
case OP_EOD:
if (eptr < md->end_subject) RRETURN(MATCH_NOMATCH);
SCHECK_PARTIAL();
ecode++;
break;
case OP_EODN:
ASSERT_NL_OR_EOS:
if (eptr < md->end_subject &&
(!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 &&
UCHAR21TEST(eptr) == NLBLOCK->nl[0])
{
md->hitend = TRUE;
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
}
RRETURN(MATCH_NOMATCH);
}
SCHECK_PARTIAL();
ecode++;
break;
case OP_NOT_WORD_BOUNDARY:
case OP_WORD_BOUNDARY:
{
#ifdef SUPPORT_UTF
if (utf)
{
if (eptr == md->start_subject) prev_is_word = FALSE; else
{
PCRE_PUCHAR lastptr = eptr - 1;
BACKCHAR(lastptr);
if (lastptr < md->start_used_ptr) md->start_used_ptr = lastptr;
GETCHAR(c, lastptr);
#ifdef SUPPORT_UCP
if (md->use_ucp)
{
if (c == '_') prev_is_word = TRUE; else
{
int cat = UCD_CATEGORY(c);
prev_is_word = (cat == ucp_L || cat == ucp_N);
}
}
else
#endif
prev_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0;
}
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
cur_is_word = FALSE;
}
else
{
GETCHAR(c, eptr);
#ifdef SUPPORT_UCP
if (md->use_ucp)
{
if (c == '_') cur_is_word = TRUE; else
{
int cat = UCD_CATEGORY(c);
cur_is_word = (cat == ucp_L || cat == ucp_N);
}
}
else
#endif
cur_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0;
}
}
else
#endif
{
if (eptr == md->start_subject) prev_is_word = FALSE; else
{
if (eptr <= md->start_used_ptr) md->start_used_ptr = eptr - 1;
#ifdef SUPPORT_UCP
if (md->use_ucp)
{
c = eptr[-1];
if (c == '_') prev_is_word = TRUE; else
{
int cat = UCD_CATEGORY(c);
prev_is_word = (cat == ucp_L || cat == ucp_N);
}
}
else
#endif
prev_is_word = MAX_255(eptr[-1])
&& ((md->ctypes[eptr[-1]] & ctype_word) != 0);
}
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
cur_is_word = FALSE;
}
else
#ifdef SUPPORT_UCP
if (md->use_ucp)
{
c = *eptr;
if (c == '_') cur_is_word = TRUE; else
{
int cat = UCD_CATEGORY(c);
cur_is_word = (cat == ucp_L || cat == ucp_N);
}
}
else
#endif
cur_is_word = MAX_255(*eptr)
&& ((md->ctypes[*eptr] & ctype_word) != 0);
}
if ((*ecode++ == OP_WORD_BOUNDARY)?
cur_is_word == prev_is_word : cur_is_word != prev_is_word)
RRETURN(MATCH_NOMATCH);
}
break;
case OP_ANY:
if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH);
if (md->partial != 0 &&
eptr + 1 >= md->end_subject &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
UCHAR21TEST(eptr) == NLBLOCK->nl[0])
{
md->hitend = TRUE;
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
}
case OP_ALLANY:
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
eptr++;
#ifdef SUPPORT_UTF
if (utf) ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
#endif
ecode++;
break;
case OP_ANYBYTE:
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
eptr++;
ecode++;
break;
case OP_NOT_DIGIT:
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
if (
#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
c < 256 &&
#endif
(md->ctypes[c] & ctype_digit) != 0
)
RRETURN(MATCH_NOMATCH);
ecode++;
break;
case OP_DIGIT:
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
if (
#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
c > 255 ||
#endif
(md->ctypes[c] & ctype_digit) == 0
)
RRETURN(MATCH_NOMATCH);
ecode++;
break;
case OP_NOT_WHITESPACE:
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
if (
#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
c < 256 &&
#endif
(md->ctypes[c] & ctype_space) != 0
)
RRETURN(MATCH_NOMATCH);
ecode++;
break;
case OP_WHITESPACE:
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
if (
#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
c > 255 ||
#endif
(md->ctypes[c] & ctype_space) == 0
)
RRETURN(MATCH_NOMATCH);
ecode++;
break;
case OP_NOT_WORDCHAR:
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
if (
#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
c < 256 &&
#endif
(md->ctypes[c] & ctype_word) != 0
)
RRETURN(MATCH_NOMATCH);
ecode++;
break;
case OP_WORDCHAR:
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
if (
#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
c > 255 ||
#endif
(md->ctypes[c] & ctype_word) == 0
)
RRETURN(MATCH_NOMATCH);
ecode++;
break;
case OP_ANYNL:
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
switch(c)
{
default: RRETURN(MATCH_NOMATCH);
case CHAR_CR:
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
}
else if (UCHAR21TEST(eptr) == CHAR_LF) eptr++;
break;
case CHAR_LF:
break;
case CHAR_VT:
case CHAR_FF:
case CHAR_NEL:
#ifndef EBCDIC
case 0x2028:
case 0x2029:
#endif
if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
break;
}
ecode++;
break;
case OP_NOT_HSPACE:
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
switch(c)
{
HSPACE_CASES: RRETURN(MATCH_NOMATCH);
default: break;
}
ecode++;
break;
case OP_HSPACE:
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
switch(c)
{
HSPACE_CASES: break;
default: RRETURN(MATCH_NOMATCH);
}
ecode++;
break;
case OP_NOT_VSPACE:
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
switch(c)
{
VSPACE_CASES: RRETURN(MATCH_NOMATCH);
default: break;
}
ecode++;
break;
case OP_VSPACE:
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
switch(c)
{
VSPACE_CASES: break;
default: RRETURN(MATCH_NOMATCH);
}
ecode++;
break;
#ifdef SUPPORT_UCP
case OP_PROP:
case OP_NOTPROP:
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
{
const pcre_uint32 *cp;
const ucd_record *prop = GET_UCD(c);
switch(ecode[1])
{
case PT_ANY:
if (op == OP_NOTPROP) RRETURN(MATCH_NOMATCH);
break;
case PT_LAMP:
if ((prop->chartype == ucp_Lu ||
prop->chartype == ucp_Ll ||
prop->chartype == ucp_Lt) == (op == OP_NOTPROP))
RRETURN(MATCH_NOMATCH);
break;
case PT_GC:
if ((ecode[2] != PRIV(ucp_gentype)[prop->chartype]) == (op == OP_PROP))
RRETURN(MATCH_NOMATCH);
break;
case PT_PC:
if ((ecode[2] != prop->chartype) == (op == OP_PROP))
RRETURN(MATCH_NOMATCH);
break;
case PT_SC:
if ((ecode[2] != prop->script) == (op == OP_PROP))
RRETURN(MATCH_NOMATCH);
break;
case PT_ALNUM:
if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
PRIV(ucp_gentype)[prop->chartype] == ucp_N) == (op == OP_NOTPROP))
RRETURN(MATCH_NOMATCH);
break;
case PT_SPACE:
case PT_PXSPACE:
switch(c)
{
HSPACE_CASES:
VSPACE_CASES:
if (op == OP_NOTPROP) RRETURN(MATCH_NOMATCH);
break;
default:
if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z) ==
(op == OP_NOTPROP)) RRETURN(MATCH_NOMATCH);
break;
}
break;
case PT_WORD:
if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
c == CHAR_UNDERSCORE) == (op == OP_NOTPROP))
RRETURN(MATCH_NOMATCH);
break;
case PT_CLIST:
cp = PRIV(ucd_caseless_sets) + ecode[2];
for (;;)
{
if (c < *cp)
{ if (op == OP_PROP) { RRETURN(MATCH_NOMATCH); } else break; }
if (c == *cp++)
{ if (op == OP_PROP) break; else { RRETURN(MATCH_NOMATCH); } }
}
break;
case PT_UCNC:
if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT ||
c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) ||
c >= 0xe000) == (op == OP_NOTPROP))
RRETURN(MATCH_NOMATCH);
break;
default:
RRETURN(PCRE_ERROR_INTERNAL);
}
ecode += 3;
}
break;
case OP_EXTUNI:
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
else
{
int lgb, rgb;
GETCHARINCTEST(c, eptr);
lgb = UCD_GRAPHBREAK(c);
while (eptr < md->end_subject)
{
int len = 1;
if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }
rgb = UCD_GRAPHBREAK(c);
if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
lgb = rgb;
eptr += len;
}
}
CHECK_PARTIAL();
ecode++;
break;
#endif
case OP_DNREF:
case OP_DNREFI:
caseless = op == OP_DNREFI;
{
int count = GET2(ecode, 1+IMM2_SIZE);
pcre_uchar *slot = md->name_table + GET2(ecode, 1) * md->name_entry_size;
ecode += 1 + 2*IMM2_SIZE;
length = (md->jscript_compat)? 0 : -1;
offset = 0;
while (count-- > 0)
{
offset = GET2(slot, 0) << 1;
if (offset < offset_top && md->offset_vector[offset] >= 0)
{
length = md->offset_vector[offset+1] - md->offset_vector[offset];
break;
}
slot += md->name_entry_size;
}
}
goto REF_REPEAT;
case OP_REF:
case OP_REFI:
caseless = op == OP_REFI;
offset = GET2(ecode, 1) << 1;
ecode += 1 + IMM2_SIZE;
if (offset >= offset_top || md->offset_vector[offset] < 0)
length = (md->jscript_compat)? 0 : -1;
else
length = md->offset_vector[offset+1] - md->offset_vector[offset];
REF_REPEAT:
switch (*ecode)
{
case OP_CRSTAR:
case OP_CRMINSTAR:
case OP_CRPLUS:
case OP_CRMINPLUS:
case OP_CRQUERY:
case OP_CRMINQUERY:
c = *ecode++ - OP_CRSTAR;
minimize = (c & 1) != 0;
min = rep_min[c];
max = rep_max[c];
if (max == 0) max = INT_MAX;
break;
case OP_CRRANGE:
case OP_CRMINRANGE:
minimize = (*ecode == OP_CRMINRANGE);
min = GET2(ecode, 1);
max = GET2(ecode, 1 + IMM2_SIZE);
if (max == 0) max = INT_MAX;
ecode += 1 + 2 * IMM2_SIZE;
break;
default:
if ((length = match_ref(offset, eptr, length, md, caseless)) < 0)
{
if (length == -2) eptr = md->end_subject;
CHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
eptr += length;
continue;
}
if (length == 0) continue;
if (length < 0 && min == 0) continue;
for (i = 1; i <= min; i++)
{
int slength;
if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0)
{
if (slength == -2) eptr = md->end_subject;
CHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
eptr += slength;
}
if (min == max) continue;
if (minimize)
{
for (fi = min;; fi++)
{
int slength;
RMATCH(eptr, ecode, offset_top, md, eptrb, RM14);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0)
{
if (slength == -2) eptr = md->end_subject;
CHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
eptr += slength;
}
}
else
{
pp = eptr;
for (i = min; i < max; i++)
{
int slength;
if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0)
{
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;
}
eptr += slength;
}
while (eptr >= pp)
{
RMATCH(eptr, ecode, offset_top, md, eptrb, RM15);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr -= length;
}
RRETURN(MATCH_NOMATCH);
}
case OP_NCLASS:
case OP_CLASS:
{
#define BYTE_MAP ((pcre_uint8 *)data)
data = ecode + 1;
ecode += 1 + (32 / sizeof(pcre_uchar));
switch (*ecode)
{
case OP_CRSTAR:
case OP_CRMINSTAR:
case OP_CRPLUS:
case OP_CRMINPLUS:
case OP_CRQUERY:
case OP_CRMINQUERY:
case OP_CRPOSSTAR:
case OP_CRPOSPLUS:
case OP_CRPOSQUERY:
c = *ecode++ - OP_CRSTAR;
if (c < OP_CRPOSSTAR - OP_CRSTAR) minimize = (c & 1) != 0;
else possessive = TRUE;
min = rep_min[c];
max = rep_max[c];
if (max == 0) max = INT_MAX;
break;
case OP_CRRANGE:
case OP_CRMINRANGE:
case OP_CRPOSRANGE:
minimize = (*ecode == OP_CRMINRANGE);
possessive = (*ecode == OP_CRPOSRANGE);
min = GET2(ecode, 1);
max = GET2(ecode, 1 + IMM2_SIZE);
if (max == 0) max = INT_MAX;
ecode += 1 + 2 * IMM2_SIZE;
break;
default:
min = max = 1;
break;
}
#ifdef SUPPORT_UTF
if (utf)
{
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINC(c, eptr);
if (c > 255)
{
if (op == OP_CLASS) RRETURN(MATCH_NOMATCH);
}
else
if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
}
}
else
#endif
{
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
c = *eptr++;
#ifndef COMPILE_PCRE8
if (c > 255)
{
if (op == OP_CLASS) RRETURN(MATCH_NOMATCH);
}
else
#endif
if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
}
}
if (min == max) continue;
if (minimize)
{
#ifdef SUPPORT_UTF
if (utf)
{
for (fi = min;; fi++)
{
RMATCH(eptr, ecode, offset_top, md, eptrb, RM16);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINC(c, eptr);
if (c > 255)
{
if (op == OP_CLASS) RRETURN(MATCH_NOMATCH);
}
else
if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
}
}
else
#endif
{
for (fi = min;; fi++)
{
RMATCH(eptr, ecode, offset_top, md, eptrb, RM17);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
c = *eptr++;
#ifndef COMPILE_PCRE8
if (c > 255)
{
if (op == OP_CLASS) RRETURN(MATCH_NOMATCH);
}
else
#endif
if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
}
}
}
else
{
pp = eptr;
#ifdef SUPPORT_UTF
if (utf)
{
for (i = min; i < max; i++)
{
int len = 1;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLEN(c, eptr, len);
if (c > 255)
{
if (op == OP_CLASS) break;
}
else
if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) break;
eptr += len;
}
if (possessive) continue;
for (;;)
{
RMATCH(eptr, ecode, offset_top, md, eptrb, RM18);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (eptr-- == pp) break;
BACKCHAR(eptr);
}
}
else
#endif
{
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
c = *eptr;
#ifndef COMPILE_PCRE8
if (c > 255)
{
if (op == OP_CLASS) break;
}
else
#endif
if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) break;
eptr++;
}
if (possessive) continue;
while (eptr >= pp)
{
RMATCH(eptr, ecode, offset_top, md, eptrb, RM19);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
}
}
RRETURN(MATCH_NOMATCH);
}
#undef BYTE_MAP
}
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
case OP_XCLASS:
{
data = ecode + 1 + LINK_SIZE;
ecode += GET(ecode, 1);
switch (*ecode)
{
case OP_CRSTAR:
case OP_CRMINSTAR:
case OP_CRPLUS:
case OP_CRMINPLUS:
case OP_CRQUERY:
case OP_CRMINQUERY:
case OP_CRPOSSTAR:
case OP_CRPOSPLUS:
case OP_CRPOSQUERY:
c = *ecode++ - OP_CRSTAR;
if (c < OP_CRPOSSTAR - OP_CRSTAR) minimize = (c & 1) != 0;
else possessive = TRUE;
min = rep_min[c];
max = rep_max[c];
if (max == 0) max = INT_MAX;
break;
case OP_CRRANGE:
case OP_CRMINRANGE:
case OP_CRPOSRANGE:
minimize = (*ecode == OP_CRMINRANGE);
possessive = (*ecode == OP_CRPOSRANGE);
min = GET2(ecode, 1);
max = GET2(ecode, 1 + IMM2_SIZE);
if (max == 0) max = INT_MAX;
ecode += 1 + 2 * IMM2_SIZE;
break;
default:
min = max = 1;
break;
}
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
if (!PRIV(xclass)(c, data, utf)) RRETURN(MATCH_NOMATCH);
}
if (min == max) continue;
if (minimize)
{
for (fi = min;; fi++)
{
RMATCH(eptr, ecode, offset_top, md, eptrb, RM20);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
if (!PRIV(xclass)(c, data, utf)) RRETURN(MATCH_NOMATCH);
}
}
else
{
pp = eptr;
for (i = min; i < max; i++)
{
int len = 1;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
#ifdef SUPPORT_UTF
GETCHARLENTEST(c, eptr, len);
#else
c = *eptr;
#endif
if (!PRIV(xclass)(c, data, utf)) break;
eptr += len;
}
if (possessive) continue;
for(;;)
{
RMATCH(eptr, ecode, offset_top, md, eptrb, RM21);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (eptr-- == pp) break;
#ifdef SUPPORT_UTF
if (utf) BACKCHAR(eptr);
#endif
}
RRETURN(MATCH_NOMATCH);
}
}
#endif
case OP_CHAR:
#ifdef SUPPORT_UTF
if (utf)
{
length = 1;
ecode++;
GETCHARLEN(fc, ecode, length);
if (length > md->end_subject - eptr)
{
CHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
while (length-- > 0) if (*ecode++ != UCHAR21INC(eptr)) RRETURN(MATCH_NOMATCH);
}
else
#endif
{
if (md->end_subject - eptr < 1)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
if (ecode[1] != *eptr++) RRETURN(MATCH_NOMATCH);
ecode += 2;
}
break;
case OP_CHARI:
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
#ifdef SUPPORT_UTF
if (utf)
{
length = 1;
ecode++;
GETCHARLEN(fc, ecode, length);
if (fc < 128)
{
pcre_uint32 cc = UCHAR21(eptr);
if (md->lcc[fc] != TABLE_GET(cc, md->lcc, cc)) RRETURN(MATCH_NOMATCH);
ecode++;
eptr++;
}
else
{
pcre_uint32 dc;
GETCHARINC(dc, eptr);
ecode += length;
if (fc != dc)
{
#ifdef SUPPORT_UCP
if (dc != UCD_OTHERCASE(fc))
#endif
RRETURN(MATCH_NOMATCH);
}
}
}
else
#endif
{
if (TABLE_GET(ecode[1], md->lcc, ecode[1])
!= TABLE_GET(*eptr, md->lcc, *eptr)) RRETURN(MATCH_NOMATCH);
eptr++;
ecode += 2;
}
break;
case OP_EXACT:
case OP_EXACTI:
min = max = GET2(ecode, 1);
ecode += 1 + IMM2_SIZE;
goto REPEATCHAR;
case OP_POSUPTO:
case OP_POSUPTOI:
possessive = TRUE;
case OP_UPTO:
case OP_UPTOI:
case OP_MINUPTO:
case OP_MINUPTOI:
min = 0;
max = GET2(ecode, 1);
minimize = *ecode == OP_MINUPTO || *ecode == OP_MINUPTOI;
ecode += 1 + IMM2_SIZE;
goto REPEATCHAR;
case OP_POSSTAR:
case OP_POSSTARI:
possessive = TRUE;
min = 0;
max = INT_MAX;
ecode++;
goto REPEATCHAR;
case OP_POSPLUS:
case OP_POSPLUSI:
possessive = TRUE;
min = 1;
max = INT_MAX;
ecode++;
goto REPEATCHAR;
case OP_POSQUERY:
case OP_POSQUERYI:
possessive = TRUE;
min = 0;
max = 1;
ecode++;
goto REPEATCHAR;
case OP_STAR:
case OP_STARI:
case OP_MINSTAR:
case OP_MINSTARI:
case OP_PLUS:
case OP_PLUSI:
case OP_MINPLUS:
case OP_MINPLUSI:
case OP_QUERY:
case OP_QUERYI:
case OP_MINQUERY:
case OP_MINQUERYI:
c = *ecode++ - ((op < OP_STARI)? OP_STAR : OP_STARI);
minimize = (c & 1) != 0;
min = rep_min[c];
max = rep_max[c];
if (max == 0) max = INT_MAX;
REPEATCHAR:
#ifdef SUPPORT_UTF
if (utf)
{
length = 1;
charptr = ecode;
GETCHARLEN(fc, ecode, length);
ecode += length;
if (length > 1)
{
#ifdef SUPPORT_UCP
pcre_uint32 othercase;
if (op >= OP_STARI &&
(othercase = UCD_OTHERCASE(fc)) != fc)
oclength = PRIV(ord2utf)(othercase, occhars);
else oclength = 0;
#endif
for (i = 1; i <= min; i++)
{
if (eptr <= md->end_subject - length &&
memcmp(eptr, charptr, IN_UCHARS(length)) == 0) eptr += length;
#ifdef SUPPORT_UCP
else if (oclength > 0 &&
eptr <= md->end_subject - oclength &&
memcmp(eptr, occhars, IN_UCHARS(oclength)) == 0) eptr += oclength;
#endif
else
{
CHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
}
if (min == max) continue;
if (minimize)
{
for (fi = min;; fi++)
{
RMATCH(eptr, ecode, offset_top, md, eptrb, RM22);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
if (eptr <= md->end_subject - length &&
memcmp(eptr, charptr, IN_UCHARS(length)) == 0) eptr += length;
#ifdef SUPPORT_UCP
else if (oclength > 0 &&
eptr <= md->end_subject - oclength &&
memcmp(eptr, occhars, IN_UCHARS(oclength)) == 0) eptr += oclength;
#endif
else
{
CHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
}
}
else
{
pp = eptr;
for (i = min; i < max; i++)
{
if (eptr <= md->end_subject - length &&
memcmp(eptr, charptr, IN_UCHARS(length)) == 0) eptr += length;
#ifdef SUPPORT_UCP
else if (oclength > 0 &&
eptr <= md->end_subject - oclength &&
memcmp(eptr, occhars, IN_UCHARS(oclength)) == 0) eptr += oclength;
#endif
else
{
CHECK_PARTIAL();
break;
}
}
if (possessive) continue;
for(;;)
{
if (eptr <= pp) goto TAIL_RECURSE;
RMATCH(eptr, ecode, offset_top, md, eptrb, RM23);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
#ifdef SUPPORT_UCP
eptr--;
BACKCHAR(eptr);
#else
eptr -= length;
#endif
}
}
}
}
else
#endif
fc = *ecode++;
DPRINTF(("matching %c{%d,%d} against subject %.*s\n", fc, min, max,
max, (char *)eptr));
if (op >= OP_STARI)
{
#ifdef COMPILE_PCRE8
foc = md->fcc[fc];
#else
#ifdef SUPPORT_UTF
#ifdef SUPPORT_UCP
if (utf && fc > 127)
foc = UCD_OTHERCASE(fc);
#else
if (utf && fc > 127)
foc = fc;
#endif
else
#endif
foc = TABLE_GET(fc, md->fcc, fc);
#endif
for (i = 1; i <= min; i++)
{
pcre_uint32 cc;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
cc = UCHAR21TEST(eptr);
if (fc != cc && foc != cc) RRETURN(MATCH_NOMATCH);
eptr++;
}
if (min == max) continue;
if (minimize)
{
for (fi = min;; fi++)
{
pcre_uint32 cc;
RMATCH(eptr, ecode, offset_top, md, eptrb, RM24);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
cc = UCHAR21TEST(eptr);
if (fc != cc && foc != cc) RRETURN(MATCH_NOMATCH);
eptr++;
}
}
else
{
pp = eptr;
for (i = min; i < max; i++)
{
pcre_uint32 cc;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
cc = UCHAR21TEST(eptr);
if (fc != cc && foc != cc) break;
eptr++;
}
if (possessive) continue;
for (;;)
{
if (eptr == pp) goto TAIL_RECURSE;
RMATCH(eptr, ecode, offset_top, md, eptrb, RM25);
eptr--;
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
}
}
}
else
{
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
if (fc != UCHAR21INCTEST(eptr)) RRETURN(MATCH_NOMATCH);
}
if (min == max) continue;
if (minimize)
{
for (fi = min;; fi++)
{
RMATCH(eptr, ecode, offset_top, md, eptrb, RM26);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
if (fc != UCHAR21INCTEST(eptr)) RRETURN(MATCH_NOMATCH);
}
}
else
{
pp = eptr;
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
if (fc != UCHAR21TEST(eptr)) break;
eptr++;
}
if (possessive) continue;
for (;;)
{
if (eptr == pp) goto TAIL_RECURSE;
RMATCH(eptr, ecode, offset_top, md, eptrb, RM27);
eptr--;
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
}
}
}
case OP_NOT:
case OP_NOTI:
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
#ifdef SUPPORT_UTF
if (utf)
{
register pcre_uint32 ch, och;
ecode++;
GETCHARINC(ch, ecode);
GETCHARINC(c, eptr);
if (op == OP_NOT)
{
if (ch == c) RRETURN(MATCH_NOMATCH);
}
else
{
#ifdef SUPPORT_UCP
if (ch > 127)
och = UCD_OTHERCASE(ch);
#else
if (ch > 127)
och = ch;
#endif
else
och = TABLE_GET(ch, md->fcc, ch);
if (ch == c || och == c) RRETURN(MATCH_NOMATCH);
}
}
else
#endif
{
register pcre_uint32 ch = ecode[1];
c = *eptr++;
if (ch == c || (op == OP_NOTI && TABLE_GET(ch, md->fcc, ch) == c))
RRETURN(MATCH_NOMATCH);
ecode += 2;
}
break;
case OP_NOTEXACT:
case OP_NOTEXACTI:
min = max = GET2(ecode, 1);
ecode += 1 + IMM2_SIZE;
goto REPEATNOTCHAR;
case OP_NOTUPTO:
case OP_NOTUPTOI:
case OP_NOTMINUPTO:
case OP_NOTMINUPTOI:
min = 0;
max = GET2(ecode, 1);
minimize = *ecode == OP_NOTMINUPTO || *ecode == OP_NOTMINUPTOI;
ecode += 1 + IMM2_SIZE;
goto REPEATNOTCHAR;
case OP_NOTPOSSTAR:
case OP_NOTPOSSTARI:
possessive = TRUE;
min = 0;
max = INT_MAX;
ecode++;
goto REPEATNOTCHAR;
case OP_NOTPOSPLUS:
case OP_NOTPOSPLUSI:
possessive = TRUE;
min = 1;
max = INT_MAX;
ecode++;
goto REPEATNOTCHAR;
case OP_NOTPOSQUERY:
case OP_NOTPOSQUERYI:
possessive = TRUE;
min = 0;
max = 1;
ecode++;
goto REPEATNOTCHAR;
case OP_NOTPOSUPTO:
case OP_NOTPOSUPTOI:
possessive = TRUE;
min = 0;
max = GET2(ecode, 1);
ecode += 1 + IMM2_SIZE;
goto REPEATNOTCHAR;
case OP_NOTSTAR:
case OP_NOTSTARI:
case OP_NOTMINSTAR:
case OP_NOTMINSTARI:
case OP_NOTPLUS:
case OP_NOTPLUSI:
case OP_NOTMINPLUS:
case OP_NOTMINPLUSI:
case OP_NOTQUERY:
case OP_NOTQUERYI:
case OP_NOTMINQUERY:
case OP_NOTMINQUERYI:
c = *ecode++ - ((op >= OP_NOTSTARI)? OP_NOTSTARI: OP_NOTSTAR);
minimize = (c & 1) != 0;
min = rep_min[c];
max = rep_max[c];
if (max == 0) max = INT_MAX;
REPEATNOTCHAR:
GETCHARINCTEST(fc, ecode);
DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", fc, min, max,
max, (char *)eptr));
if (op >= OP_NOTSTARI)
{
#ifdef SUPPORT_UTF
#ifdef SUPPORT_UCP
if (utf && fc > 127)
foc = UCD_OTHERCASE(fc);
#else
if (utf && fc > 127)
foc = fc;
#endif
else
#endif
foc = TABLE_GET(fc, md->fcc, fc);
#ifdef SUPPORT_UTF
if (utf)
{
register pcre_uint32 d;
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINC(d, eptr);
if (fc == d || (unsigned int)foc == d) RRETURN(MATCH_NOMATCH);
}
}
else
#endif
{
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
if (fc == *eptr || foc == *eptr) RRETURN(MATCH_NOMATCH);
eptr++;
}
}
if (min == max) continue;
if (minimize)
{
#ifdef SUPPORT_UTF
if (utf)
{
register pcre_uint32 d;
for (fi = min;; fi++)
{
RMATCH(eptr, ecode, offset_top, md, eptrb, RM28);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINC(d, eptr);
if (fc == d || (unsigned int)foc == d) RRETURN(MATCH_NOMATCH);
}
}
else
#endif
{
for (fi = min;; fi++)
{
RMATCH(eptr, ecode, offset_top, md, eptrb, RM29);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
if (fc == *eptr || foc == *eptr) RRETURN(MATCH_NOMATCH);
eptr++;
}
}
}
else
{
pp = eptr;
#ifdef SUPPORT_UTF
if (utf)
{
register pcre_uint32 d;
for (i = min; i < max; i++)
{
int len = 1;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLEN(d, eptr, len);
if (fc == d || (unsigned int)foc == d) break;
eptr += len;
}
if (possessive) continue;
for(;;)
{
if (eptr <= pp) goto TAIL_RECURSE;
RMATCH(eptr, ecode, offset_top, md, eptrb, RM30);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
BACKCHAR(eptr);
}
}
else
#endif
{
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
if (fc == *eptr || foc == *eptr) break;
eptr++;
}
if (possessive) continue;
for (;;)
{
if (eptr == pp) goto TAIL_RECURSE;
RMATCH(eptr, ecode, offset_top, md, eptrb, RM31);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
}
}
}
}
else
{
#ifdef SUPPORT_UTF
if (utf)
{
register pcre_uint32 d;
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINC(d, eptr);
if (fc == d) RRETURN(MATCH_NOMATCH);
}
}
else
#endif
{
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
if (fc == *eptr++) RRETURN(MATCH_NOMATCH);
}
}
if (min == max) continue;
if (minimize)
{
#ifdef SUPPORT_UTF
if (utf)
{
register pcre_uint32 d;
for (fi = min;; fi++)
{
RMATCH(eptr, ecode, offset_top, md, eptrb, RM32);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINC(d, eptr);
if (fc == d) RRETURN(MATCH_NOMATCH);
}
}
else
#endif
{
for (fi = min;; fi++)
{
RMATCH(eptr, ecode, offset_top, md, eptrb, RM33);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
if (fc == *eptr++) RRETURN(MATCH_NOMATCH);
}
}
}
else
{
pp = eptr;
#ifdef SUPPORT_UTF
if (utf)
{
register pcre_uint32 d;
for (i = min; i < max; i++)
{
int len = 1;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLEN(d, eptr, len);
if (fc == d) break;
eptr += len;
}
if (possessive) continue;
for(;;)
{
if (eptr <= pp) goto TAIL_RECURSE;
RMATCH(eptr, ecode, offset_top, md, eptrb, RM34);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
BACKCHAR(eptr);
}
}
else
#endif
{
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
if (fc == *eptr) break;
eptr++;
}
if (possessive) continue;
for (;;)
{
if (eptr == pp) goto TAIL_RECURSE;
RMATCH(eptr, ecode, offset_top, md, eptrb, RM35);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
}
}
}
}
case OP_TYPEEXACT:
min = max = GET2(ecode, 1);
minimize = TRUE;
ecode += 1 + IMM2_SIZE;
goto REPEATTYPE;
case OP_TYPEUPTO:
case OP_TYPEMINUPTO:
min = 0;
max = GET2(ecode, 1);
minimize = *ecode == OP_TYPEMINUPTO;
ecode += 1 + IMM2_SIZE;
goto REPEATTYPE;
case OP_TYPEPOSSTAR:
possessive = TRUE;
min = 0;
max = INT_MAX;
ecode++;
goto REPEATTYPE;
case OP_TYPEPOSPLUS:
possessive = TRUE;
min = 1;
max = INT_MAX;
ecode++;
goto REPEATTYPE;
case OP_TYPEPOSQUERY:
possessive = TRUE;
min = 0;
max = 1;
ecode++;
goto REPEATTYPE;
case OP_TYPEPOSUPTO:
possessive = TRUE;
min = 0;
max = GET2(ecode, 1);
ecode += 1 + IMM2_SIZE;
goto REPEATTYPE;
case OP_TYPESTAR:
case OP_TYPEMINSTAR:
case OP_TYPEPLUS:
case OP_TYPEMINPLUS:
case OP_TYPEQUERY:
case OP_TYPEMINQUERY:
c = *ecode++ - OP_TYPESTAR;
minimize = (c & 1) != 0;
min = rep_min[c];
max = rep_max[c];
if (max == 0) max = INT_MAX;
REPEATTYPE:
ctype = *ecode++;
#ifdef SUPPORT_UCP
if (ctype == OP_PROP || ctype == OP_NOTPROP)
{
prop_fail_result = ctype == OP_NOTPROP;
prop_type = *ecode++;
prop_value = *ecode++;
}
else prop_type = -1;
#endif
if (min > 0)
{
#ifdef SUPPORT_UCP
if (prop_type >= 0)
{
switch(prop_type)
{
case PT_ANY:
if (prop_fail_result) RRETURN(MATCH_NOMATCH);
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
}
break;
case PT_LAMP:
for (i = 1; i <= min; i++)
{
int chartype;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
chartype = UCD_CHARTYPE(c);
if ((chartype == ucp_Lu ||
chartype == ucp_Ll ||
chartype == ucp_Lt) == prop_fail_result)
RRETURN(MATCH_NOMATCH);
}
break;
case PT_GC:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
if ((UCD_CATEGORY(c) == prop_value) == prop_fail_result)
RRETURN(MATCH_NOMATCH);
}
break;
case PT_PC:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
if ((UCD_CHARTYPE(c) == prop_value) == prop_fail_result)
RRETURN(MATCH_NOMATCH);
}
break;
case PT_SC:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
if ((UCD_SCRIPT(c) == prop_value) == prop_fail_result)
RRETURN(MATCH_NOMATCH);
}
break;
case PT_ALNUM:
for (i = 1; i <= min; i++)
{
int category;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
category = UCD_CATEGORY(c);
if ((category == ucp_L || category == ucp_N) == prop_fail_result)
RRETURN(MATCH_NOMATCH);
}
break;
case PT_SPACE:
case PT_PXSPACE:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
switch(c)
{
HSPACE_CASES:
VSPACE_CASES:
if (prop_fail_result) RRETURN(MATCH_NOMATCH);
break;
default:
if ((UCD_CATEGORY(c) == ucp_Z) == prop_fail_result)
RRETURN(MATCH_NOMATCH);
break;
}
}
break;
case PT_WORD:
for (i = 1; i <= min; i++)
{
int category;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
category = UCD_CATEGORY(c);
if ((category == ucp_L || category == ucp_N || c == CHAR_UNDERSCORE)
== prop_fail_result)
RRETURN(MATCH_NOMATCH);
}
break;
case PT_CLIST:
for (i = 1; i <= min; i++)
{
const pcre_uint32 *cp;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
cp = PRIV(ucd_caseless_sets) + prop_value;
for (;;)
{
if (c < *cp)
{ if (prop_fail_result) break; else { RRETURN(MATCH_NOMATCH); } }
if (c == *cp++)
{ if (prop_fail_result) { RRETURN(MATCH_NOMATCH); } else break; }
}
}
break;
case PT_UCNC:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT ||
c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) ||
c >= 0xe000) == prop_fail_result)
RRETURN(MATCH_NOMATCH);
}
break;
default:
RRETURN(PCRE_ERROR_INTERNAL);
}
}
else if (ctype == OP_EXTUNI)
{
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
else
{
int lgb, rgb;
GETCHARINCTEST(c, eptr);
lgb = UCD_GRAPHBREAK(c);
while (eptr < md->end_subject)
{
int len = 1;
if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }
rgb = UCD_GRAPHBREAK(c);
if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
lgb = rgb;
eptr += len;
}
}
CHECK_PARTIAL();
}
}
else
#endif
#ifdef SUPPORT_UTF
if (utf) switch(ctype)
{
case OP_ANY:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
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 &&
UCHAR21(eptr) == NLBLOCK->nl[0])
{
md->hitend = TRUE;
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
}
eptr++;
ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
}
break;
case OP_ALLANY:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
eptr++;
ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
}
break;
case OP_ANYBYTE:
if (eptr > md->end_subject - min) RRETURN(MATCH_NOMATCH);
eptr += min;
break;
case OP_ANYNL:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINC(c, eptr);
switch(c)
{
default: RRETURN(MATCH_NOMATCH);
case CHAR_CR:
if (eptr < md->end_subject && UCHAR21(eptr) == CHAR_LF) eptr++;
break;
case CHAR_LF:
break;
case CHAR_VT:
case CHAR_FF:
case CHAR_NEL:
#ifndef EBCDIC
case 0x2028:
case 0x2029:
#endif
if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
break;
}
}
break;
case OP_NOT_HSPACE:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINC(c, eptr);
switch(c)
{
HSPACE_CASES: RRETURN(MATCH_NOMATCH);
default: break;
}
}
break;
case OP_HSPACE:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINC(c, eptr);
switch(c)
{
HSPACE_CASES: break;
default: RRETURN(MATCH_NOMATCH);
}
}
break;
case OP_NOT_VSPACE:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINC(c, eptr);
switch(c)
{
VSPACE_CASES: RRETURN(MATCH_NOMATCH);
default: break;
}
}
break;
case OP_VSPACE:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINC(c, eptr);
switch(c)
{
VSPACE_CASES: break;
default: RRETURN(MATCH_NOMATCH);
}
}
break;
case OP_NOT_DIGIT:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINC(c, eptr);
if (c < 128 && (md->ctypes[c] & ctype_digit) != 0)
RRETURN(MATCH_NOMATCH);
}
break;
case OP_DIGIT:
for (i = 1; i <= min; i++)
{
pcre_uint32 cc;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
cc = UCHAR21(eptr);
if (cc >= 128 || (md->ctypes[cc] & ctype_digit) == 0)
RRETURN(MATCH_NOMATCH);
eptr++;
}
break;
case OP_NOT_WHITESPACE:
for (i = 1; i <= min; i++)
{
pcre_uint32 cc;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
cc = UCHAR21(eptr);
if (cc < 128 && (md->ctypes[cc] & ctype_space) != 0)
RRETURN(MATCH_NOMATCH);
eptr++;
ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
}
break;
case OP_WHITESPACE:
for (i = 1; i <= min; i++)
{
pcre_uint32 cc;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
cc = UCHAR21(eptr);
if (cc >= 128 || (md->ctypes[cc] & ctype_space) == 0)
RRETURN(MATCH_NOMATCH);
eptr++;
}
break;
case OP_NOT_WORDCHAR:
for (i = 1; i <= min; i++)
{
pcre_uint32 cc;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
cc = UCHAR21(eptr);
if (cc < 128 && (md->ctypes[cc] & ctype_word) != 0)
RRETURN(MATCH_NOMATCH);
eptr++;
ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
}
break;
case OP_WORDCHAR:
for (i = 1; i <= min; i++)
{
pcre_uint32 cc;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
cc = UCHAR21(eptr);
if (cc >= 128 || (md->ctypes[cc] & ctype_word) == 0)
RRETURN(MATCH_NOMATCH);
eptr++;
}
break;
default:
RRETURN(PCRE_ERROR_INTERNAL);
}
else
#endif
switch(ctype)
{
case OP_ANY:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
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++;
}
break;
case OP_ALLANY:
if (eptr > md->end_subject - min)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
eptr += min;
break;
case OP_ANYBYTE:
if (eptr > md->end_subject - min)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
eptr += min;
break;
case OP_ANYNL:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
switch(*eptr++)
{
default: RRETURN(MATCH_NOMATCH);
case CHAR_CR:
if (eptr < md->end_subject && *eptr == CHAR_LF) eptr++;
break;
case CHAR_LF:
break;
case CHAR_VT:
case CHAR_FF:
case CHAR_NEL:
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
case 0x2028:
case 0x2029:
#endif
if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
break;
}
}
break;
case OP_NOT_HSPACE:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
switch(*eptr++)
{
default: break;
HSPACE_BYTE_CASES:
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
HSPACE_MULTIBYTE_CASES:
#endif
RRETURN(MATCH_NOMATCH);
}
}
break;
case OP_HSPACE:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
switch(*eptr++)
{
default: RRETURN(MATCH_NOMATCH);
HSPACE_BYTE_CASES:
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
HSPACE_MULTIBYTE_CASES:
#endif
break;
}
}
break;
case OP_NOT_VSPACE:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
switch(*eptr++)
{
VSPACE_BYTE_CASES:
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
VSPACE_MULTIBYTE_CASES:
#endif
RRETURN(MATCH_NOMATCH);
default: break;
}
}
break;
case OP_VSPACE:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
switch(*eptr++)
{
default: RRETURN(MATCH_NOMATCH);
VSPACE_BYTE_CASES:
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
VSPACE_MULTIBYTE_CASES:
#endif
break;
}
}
break;
case OP_NOT_DIGIT:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_digit) != 0)
RRETURN(MATCH_NOMATCH);
eptr++;
}
break;
case OP_DIGIT:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_digit) == 0)
RRETURN(MATCH_NOMATCH);
eptr++;
}
break;
case OP_NOT_WHITESPACE:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_space) != 0)
RRETURN(MATCH_NOMATCH);
eptr++;
}
break;
case OP_WHITESPACE:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_space) == 0)
RRETURN(MATCH_NOMATCH);
eptr++;
}
break;
case OP_NOT_WORDCHAR:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_word) != 0)
RRETURN(MATCH_NOMATCH);
eptr++;
}
break;
case OP_WORDCHAR:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_word) == 0)
RRETURN(MATCH_NOMATCH);
eptr++;
}
break;
default:
RRETURN(PCRE_ERROR_INTERNAL);
}
}
if (min == max) continue;
if (minimize)
{
#ifdef SUPPORT_UCP
if (prop_type >= 0)
{
switch(prop_type)
{
case PT_ANY:
for (fi = min;; fi++)
{
RMATCH(eptr, ecode, offset_top, md, eptrb, RM36);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
if (prop_fail_result) RRETURN(MATCH_NOMATCH);
}
case PT_LAMP:
for (fi = min;; fi++)
{
int chartype;
RMATCH(eptr, ecode, offset_top, md, eptrb, RM37);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
chartype = UCD_CHARTYPE(c);
if ((chartype == ucp_Lu ||
chartype == ucp_Ll ||
chartype == ucp_Lt) == prop_fail_result)
RRETURN(MATCH_NOMATCH);
}
case PT_GC:
for (fi = min;; fi++)
{
RMATCH(eptr, ecode, offset_top, md, eptrb, RM38);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
if ((UCD_CATEGORY(c) == prop_value) == prop_fail_result)
RRETURN(MATCH_NOMATCH);
}
case PT_PC:
for (fi = min;; fi++)
{
RMATCH(eptr, ecode, offset_top, md, eptrb, RM39);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
if ((UCD_CHARTYPE(c) == prop_value) == prop_fail_result)
RRETURN(MATCH_NOMATCH);
}
case PT_SC:
for (fi = min;; fi++)
{
RMATCH(eptr, ecode, offset_top, md, eptrb, RM40);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
if ((UCD_SCRIPT(c) == prop_value) == prop_fail_result)
RRETURN(MATCH_NOMATCH);
}
case PT_ALNUM:
for (fi = min;; fi++)
{
int category;
RMATCH(eptr, ecode, offset_top, md, eptrb, RM59);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
category = UCD_CATEGORY(c);
if ((category == ucp_L || category == ucp_N) == prop_fail_result)
RRETURN(MATCH_NOMATCH);
}
case PT_SPACE:
case PT_PXSPACE:
for (fi = min;; fi++)
{
RMATCH(eptr, ecode, offset_top, md, eptrb, RM61);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
switch(c)
{
HSPACE_CASES:
VSPACE_CASES:
if (prop_fail_result) RRETURN(MATCH_NOMATCH);
break;
default:
if ((UCD_CATEGORY(c) == ucp_Z) == prop_fail_result)
RRETURN(MATCH_NOMATCH);
break;
}
}
case PT_WORD:
for (fi = min;; fi++)
{
int category;
RMATCH(eptr, ecode, offset_top, md, eptrb, RM62);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
category = UCD_CATEGORY(c);
if ((category == ucp_L ||
category == ucp_N ||
c == CHAR_UNDERSCORE)
== prop_fail_result)
RRETURN(MATCH_NOMATCH);
}
case PT_CLIST:
for (fi = min;; fi++)
{
const pcre_uint32 *cp;
RMATCH(eptr, ecode, offset_top, md, eptrb, RM67);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
cp = PRIV(ucd_caseless_sets) + prop_value;
for (;;)
{
if (c < *cp)
{ if (prop_fail_result) break; else { RRETURN(MATCH_NOMATCH); } }
if (c == *cp++)
{ if (prop_fail_result) { RRETURN(MATCH_NOMATCH); } else break; }
}
}
case PT_UCNC:
for (fi = min;; fi++)
{
RMATCH(eptr, ecode, offset_top, md, eptrb, RM60);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT ||
c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) ||
c >= 0xe000) == prop_fail_result)
RRETURN(MATCH_NOMATCH);
}
default:
RRETURN(PCRE_ERROR_INTERNAL);
}
}
else if (ctype == OP_EXTUNI)
{
for (fi = min;; fi++)
{
RMATCH(eptr, ecode, offset_top, md, eptrb, RM41);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
else
{
int lgb, rgb;
GETCHARINCTEST(c, eptr);
lgb = UCD_GRAPHBREAK(c);
while (eptr < md->end_subject)
{
int len = 1;
if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }
rgb = UCD_GRAPHBREAK(c);
if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
lgb = rgb;
eptr += len;
}
}
CHECK_PARTIAL();
}
}
else
#endif
#ifdef SUPPORT_UTF
if (utf)
{
for (fi = min;; fi++)
{
RMATCH(eptr, ecode, offset_top, md, eptrb, RM42);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
if (ctype == OP_ANY && IS_NEWLINE(eptr))
RRETURN(MATCH_NOMATCH);
GETCHARINC(c, eptr);
switch(ctype)
{
case OP_ANY:
if (md->partial != 0 &&
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_ANYBYTE:
break;
case OP_ANYNL:
switch(c)
{
default: RRETURN(MATCH_NOMATCH);
case CHAR_CR:
if (eptr < md->end_subject && UCHAR21(eptr) == CHAR_LF) eptr++;
break;
case CHAR_LF:
break;
case CHAR_VT:
case CHAR_FF:
case CHAR_NEL:
#ifndef EBCDIC
case 0x2028:
case 0x2029:
#endif
if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
break;
}
break;
case OP_NOT_HSPACE:
switch(c)
{
HSPACE_CASES: RRETURN(MATCH_NOMATCH);
default: break;
}
break;
case OP_HSPACE:
switch(c)
{
HSPACE_CASES: break;
default: RRETURN(MATCH_NOMATCH);
}
break;
case OP_NOT_VSPACE:
switch(c)
{
VSPACE_CASES: RRETURN(MATCH_NOMATCH);
default: break;
}
break;
case OP_VSPACE:
switch(c)
{
VSPACE_CASES: break;
default: RRETURN(MATCH_NOMATCH);
}
break;
case OP_NOT_DIGIT:
if (c < 256 && (md->ctypes[c] & ctype_digit) != 0)
RRETURN(MATCH_NOMATCH);
break;
case OP_DIGIT:
if (c >= 256 || (md->ctypes[c] & ctype_digit) == 0)
RRETURN(MATCH_NOMATCH);
break;
case OP_NOT_WHITESPACE:
if (c < 256 && (md->ctypes[c] & ctype_space) != 0)
RRETURN(MATCH_NOMATCH);
break;
case OP_WHITESPACE:
if (c >= 256 || (md->ctypes[c] & ctype_space) == 0)
RRETURN(MATCH_NOMATCH);
break;
case OP_NOT_WORDCHAR:
if (c < 256 && (md->ctypes[c] & ctype_word) != 0)
RRETURN(MATCH_NOMATCH);
break;
case OP_WORDCHAR:
if (c >= 256 || (md->ctypes[c] & ctype_word) == 0)
RRETURN(MATCH_NOMATCH);
break;
default:
RRETURN(PCRE_ERROR_INTERNAL);
}
}
}
else
#endif
{
for (fi = min;; fi++)
{
RMATCH(eptr, ecode, offset_top, md, eptrb, RM43);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
if (ctype == OP_ANY && IS_NEWLINE(eptr))
RRETURN(MATCH_NOMATCH);
c = *eptr++;
switch(ctype)
{
case OP_ANY:
if (md->partial != 0 &&
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_ANYBYTE:
break;
case OP_ANYNL:
switch(c)
{
default: RRETURN(MATCH_NOMATCH);
case CHAR_CR:
if (eptr < md->end_subject && *eptr == CHAR_LF) eptr++;
break;
case CHAR_LF:
break;
case CHAR_VT:
case CHAR_FF:
case CHAR_NEL:
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
case 0x2028:
case 0x2029:
#endif
if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
break;
}
break;
case OP_NOT_HSPACE:
switch(c)
{
default: break;
HSPACE_BYTE_CASES:
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
HSPACE_MULTIBYTE_CASES:
#endif
RRETURN(MATCH_NOMATCH);
}
break;
case OP_HSPACE:
switch(c)
{
default: RRETURN(MATCH_NOMATCH);
HSPACE_BYTE_CASES:
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
HSPACE_MULTIBYTE_CASES:
#endif
break;
}
break;
case OP_NOT_VSPACE:
switch(c)
{
default: break;
VSPACE_BYTE_CASES:
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
VSPACE_MULTIBYTE_CASES:
#endif
RRETURN(MATCH_NOMATCH);
}
break;
case OP_VSPACE:
switch(c)
{
default: RRETURN(MATCH_NOMATCH);
VSPACE_BYTE_CASES:
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
VSPACE_MULTIBYTE_CASES:
#endif
break;
}
break;
case OP_NOT_DIGIT:
if (MAX_255(c) && (md->ctypes[c] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH);
break;
case OP_DIGIT:
if (!MAX_255(c) || (md->ctypes[c] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH);
break;
case OP_NOT_WHITESPACE:
if (MAX_255(c) && (md->ctypes[c] & ctype_space) != 0) RRETURN(MATCH_NOMATCH);
break;
case OP_WHITESPACE:
if (!MAX_255(c) || (md->ctypes[c] & ctype_space) == 0) RRETURN(MATCH_NOMATCH);
break;
case OP_NOT_WORDCHAR:
if (MAX_255(c) && (md->ctypes[c] & ctype_word) != 0) RRETURN(MATCH_NOMATCH);
break;
case OP_WORDCHAR:
if (!MAX_255(c) || (md->ctypes[c] & ctype_word) == 0) RRETURN(MATCH_NOMATCH);
break;
default:
RRETURN(PCRE_ERROR_INTERNAL);
}
}
}
}
else
{
pp = eptr;
#ifdef SUPPORT_UCP
if (prop_type >= 0)
{
switch(prop_type)
{
case PT_ANY:
for (i = min; i < max; i++)
{
int len = 1;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLENTEST(c, eptr, len);
if (prop_fail_result) break;
eptr+= len;
}
break;
case PT_LAMP:
for (i = min; i < max; i++)
{
int chartype;
int len = 1;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLENTEST(c, eptr, len);
chartype = UCD_CHARTYPE(c);
if ((chartype == ucp_Lu ||
chartype == ucp_Ll ||
chartype == ucp_Lt) == prop_fail_result)
break;
eptr+= len;
}
break;
case PT_GC:
for (i = min; i < max; i++)
{
int len = 1;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLENTEST(c, eptr, len);
if ((UCD_CATEGORY(c) == prop_value) == prop_fail_result) break;
eptr+= len;
}
break;
case PT_PC:
for (i = min; i < max; i++)
{
int len = 1;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLENTEST(c, eptr, len);
if ((UCD_CHARTYPE(c) == prop_value) == prop_fail_result) break;
eptr+= len;
}
break;
case PT_SC:
for (i = min; i < max; i++)
{
int len = 1;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLENTEST(c, eptr, len);
if ((UCD_SCRIPT(c) == prop_value) == prop_fail_result) break;
eptr+= len;
}
break;
case PT_ALNUM:
for (i = min; i < max; i++)
{
int category;
int len = 1;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLENTEST(c, eptr, len);
category = UCD_CATEGORY(c);
if ((category == ucp_L || category == ucp_N) == prop_fail_result)
break;
eptr+= len;
}
break;
case PT_SPACE:
case PT_PXSPACE:
for (i = min; i < max; i++)
{
int len = 1;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLENTEST(c, eptr, len);
switch(c)
{
HSPACE_CASES:
VSPACE_CASES:
if (prop_fail_result) goto ENDLOOP99;
break;
default:
if ((UCD_CATEGORY(c) == ucp_Z) == prop_fail_result)
goto ENDLOOP99;
break;
}
eptr+= len;
}
ENDLOOP99:
break;
case PT_WORD:
for (i = min; i < max; i++)
{
int category;
int len = 1;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLENTEST(c, eptr, len);
category = UCD_CATEGORY(c);
if ((category == ucp_L || category == ucp_N ||
c == CHAR_UNDERSCORE) == prop_fail_result)
break;
eptr+= len;
}
break;
case PT_CLIST:
for (i = min; i < max; i++)
{
const pcre_uint32 *cp;
int len = 1;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLENTEST(c, eptr, len);
cp = PRIV(ucd_caseless_sets) + prop_value;
for (;;)
{
if (c < *cp)
{ if (prop_fail_result) break; else goto GOT_MAX; }
if (c == *cp++)
{ if (prop_fail_result) goto GOT_MAX; else break; }
}
eptr += len;
}
GOT_MAX:
break;
case PT_UCNC:
for (i = min; i < max; i++)
{
int len = 1;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLENTEST(c, eptr, len);
if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT ||
c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) ||
c >= 0xe000) == prop_fail_result)
break;
eptr += len;
}
break;
default:
RRETURN(PCRE_ERROR_INTERNAL);
}
if (possessive) continue;
for(;;)
{
if (eptr <= pp) goto TAIL_RECURSE;
RMATCH(eptr, ecode, offset_top, md, eptrb, RM44);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
if (utf) BACKCHAR(eptr);
}
}
else if (ctype == OP_EXTUNI)
{
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
else
{
int lgb, rgb;
GETCHARINCTEST(c, eptr);
lgb = UCD_GRAPHBREAK(c);
while (eptr < md->end_subject)
{
int len = 1;
if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }
rgb = UCD_GRAPHBREAK(c);
if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
lgb = rgb;
eptr += len;
}
}
CHECK_PARTIAL();
}
if (possessive) continue;
for(;;)
{
int lgb, rgb;
PCRE_PUCHAR fptr;
if (eptr <= pp) goto TAIL_RECURSE;
RMATCH(eptr, ecode, offset_top, md, eptrb, RM45);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
if (!utf) c = *eptr; else
{
BACKCHAR(eptr);
GETCHAR(c, eptr);
}
rgb = UCD_GRAPHBREAK(c);
for (;;)
{
if (eptr <= pp) goto TAIL_RECURSE;
fptr = eptr - 1;
if (!utf) c = *fptr; else
{
BACKCHAR(fptr);
GETCHAR(c, fptr);
}
lgb = UCD_GRAPHBREAK(c);
if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
eptr = fptr;
rgb = lgb;
}
}
}
else
#endif
#ifdef SUPPORT_UTF
if (utf)
{
switch(ctype)
{
case OP_ANY:
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
if (IS_NEWLINE(eptr)) break;
if (md->partial != 0 &&
eptr + 1 >= md->end_subject &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
UCHAR21(eptr) == NLBLOCK->nl[0])
{
md->hitend = TRUE;
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
}
eptr++;
ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
}
break;
case OP_ALLANY:
if (max < INT_MAX)
{
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
eptr++;
ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
}
}
else
{
eptr = md->end_subject;
SCHECK_PARTIAL();
}
break;
case OP_ANYBYTE:
c = max - min;
if (c > (unsigned int)(md->end_subject - eptr))
{
eptr = md->end_subject;
SCHECK_PARTIAL();
}
else eptr += c;
break;
case OP_ANYNL:
for (i = min; i < max; i++)
{
int len = 1;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLEN(c, eptr, len);
if (c == CHAR_CR)
{
if (++eptr >= md->end_subject) break;
if (UCHAR21(eptr) == CHAR_LF) eptr++;
}
else
{
if (c != CHAR_LF &&
(md->bsr_anycrlf ||
(c != CHAR_VT && c != CHAR_FF && c != CHAR_NEL
#ifndef EBCDIC
&& c != 0x2028 && c != 0x2029
#endif
)))
break;
eptr += len;
}
}
break;
case OP_NOT_HSPACE:
case OP_HSPACE:
for (i = min; i < max; i++)
{
BOOL gotspace;
int len = 1;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLEN(c, eptr, len);
switch(c)
{
HSPACE_CASES: gotspace = TRUE; break;
default: gotspace = FALSE; break;
}
if (gotspace == (ctype == OP_NOT_HSPACE)) break;
eptr += len;
}
break;
case OP_NOT_VSPACE:
case OP_VSPACE:
for (i = min; i < max; i++)
{
BOOL gotspace;
int len = 1;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLEN(c, eptr, len);
switch(c)
{
VSPACE_CASES: gotspace = TRUE; break;
default: gotspace = FALSE; break;
}
if (gotspace == (ctype == OP_NOT_VSPACE)) break;
eptr += len;
}
break;
case OP_NOT_DIGIT:
for (i = min; i < max; i++)
{
int len = 1;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLEN(c, eptr, len);
if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) break;
eptr+= len;
}
break;
case OP_DIGIT:
for (i = min; i < max; i++)
{
int len = 1;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLEN(c, eptr, len);
if (c >= 256 ||(md->ctypes[c] & ctype_digit) == 0) break;
eptr+= len;
}
break;
case OP_NOT_WHITESPACE:
for (i = min; i < max; i++)
{
int len = 1;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLEN(c, eptr, len);
if (c < 256 && (md->ctypes[c] & ctype_space) != 0) break;
eptr+= len;
}
break;
case OP_WHITESPACE:
for (i = min; i < max; i++)
{
int len = 1;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLEN(c, eptr, len);
if (c >= 256 ||(md->ctypes[c] & ctype_space) == 0) break;
eptr+= len;
}
break;
case OP_NOT_WORDCHAR:
for (i = min; i < max; i++)
{
int len = 1;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLEN(c, eptr, len);
if (c < 256 && (md->ctypes[c] & ctype_word) != 0) break;
eptr+= len;
}
break;
case OP_WORDCHAR:
for (i = min; i < max; i++)
{
int len = 1;
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLEN(c, eptr, len);
if (c >= 256 || (md->ctypes[c] & ctype_word) == 0) break;
eptr+= len;
}
break;
default:
RRETURN(PCRE_ERROR_INTERNAL);
}
if (possessive) continue;
for(;;)
{
if (eptr <= pp) goto TAIL_RECURSE;
RMATCH(eptr, ecode, offset_top, md, eptrb, RM46);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
BACKCHAR(eptr);
if (ctype == OP_ANYNL && eptr > pp && UCHAR21(eptr) == CHAR_NL &&
UCHAR21(eptr - 1) == CHAR_CR) eptr--;
}
}
else
#endif
{
switch(ctype)
{
case OP_ANY:
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
if (IS_NEWLINE(eptr)) break;
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++;
}
break;
case OP_ALLANY:
case OP_ANYBYTE:
c = max - min;
if (c > (unsigned int)(md->end_subject - eptr))
{
eptr = md->end_subject;
SCHECK_PARTIAL();
}
else eptr += c;
break;
case OP_ANYNL:
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
c = *eptr;
if (c == CHAR_CR)
{
if (++eptr >= md->end_subject) break;
if (*eptr == CHAR_LF) eptr++;
}
else
{
if (c != CHAR_LF && (md->bsr_anycrlf ||
(c != CHAR_VT && c != CHAR_FF && c != CHAR_NEL
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
&& c != 0x2028 && c != 0x2029
#endif
))) break;
eptr++;
}
}
break;
case OP_NOT_HSPACE:
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
switch(*eptr)
{
default: eptr++; break;
HSPACE_BYTE_CASES:
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
HSPACE_MULTIBYTE_CASES:
#endif
goto ENDLOOP00;
}
}
ENDLOOP00:
break;
case OP_HSPACE:
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
switch(*eptr)
{
default: goto ENDLOOP01;
HSPACE_BYTE_CASES:
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
HSPACE_MULTIBYTE_CASES:
#endif
eptr++; break;
}
}
ENDLOOP01:
break;
case OP_NOT_VSPACE:
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
switch(*eptr)
{
default: eptr++; break;
VSPACE_BYTE_CASES:
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
VSPACE_MULTIBYTE_CASES:
#endif
goto ENDLOOP02;
}
}
ENDLOOP02:
break;
case OP_VSPACE:
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
switch(*eptr)
{
default: goto ENDLOOP03;
VSPACE_BYTE_CASES:
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
VSPACE_MULTIBYTE_CASES:
#endif
eptr++; break;
}
}
ENDLOOP03:
break;
case OP_NOT_DIGIT:
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_digit) != 0) break;
eptr++;
}
break;
case OP_DIGIT:
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_digit) == 0) break;
eptr++;
}
break;
case OP_NOT_WHITESPACE:
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_space) != 0) break;
eptr++;
}
break;
case OP_WHITESPACE:
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_space) == 0) break;
eptr++;
}
break;
case OP_NOT_WORDCHAR:
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_word) != 0) break;
eptr++;
}
break;
case OP_WORDCHAR:
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject)
{
SCHECK_PARTIAL();
break;
}
if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_word) == 0) break;
eptr++;
}
break;
default:
RRETURN(PCRE_ERROR_INTERNAL);
}
if (possessive) continue;
for (;;)
{
if (eptr == pp) goto TAIL_RECURSE;
RMATCH(eptr, ecode, offset_top, md, eptrb, RM47);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
if (ctype == OP_ANYNL && eptr > pp && *eptr == CHAR_LF &&
eptr[-1] == CHAR_CR) eptr--;
}
}
}
default:
DPRINTF(("Unknown opcode %d\n", *ecode));
RRETURN(PCRE_ERROR_UNKNOWN_OPCODE);
}
}
#ifdef NO_RECURSE
#define LBL(val) case val: goto L_RM##val;
HEAP_RETURN:
switch (frame->Xwhere)
{
LBL( 1) LBL( 2) LBL( 3) LBL( 4) LBL( 5) LBL( 6) LBL( 7) LBL( 8)
LBL( 9) LBL(10) LBL(11) LBL(12) LBL(13) LBL(14) LBL(15) LBL(17)
LBL(19) LBL(24) LBL(25) LBL(26) LBL(27) LBL(29) LBL(31) LBL(33)
LBL(35) LBL(43) LBL(47) LBL(48) LBL(49) LBL(50) LBL(51) LBL(52)
LBL(53) LBL(54) LBL(55) LBL(56) LBL(57) LBL(58) LBL(63) LBL(64)
LBL(65) LBL(66)
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
LBL(20) LBL(21)
#endif
#ifdef SUPPORT_UTF
LBL(16) LBL(18)
LBL(22) LBL(23) LBL(28) LBL(30)
LBL(32) LBL(34) LBL(42) LBL(46)
#ifdef SUPPORT_UCP
LBL(36) LBL(37) LBL(38) LBL(39) LBL(40) LBL(41) LBL(44) LBL(45)
LBL(59) LBL(60) LBL(61) LBL(62) LBL(67)
#endif
#endif
default:
DPRINTF(("jump error in pcre match: label %d non-existent\n", frame->Xwhere));
return PCRE_ERROR_INTERNAL;
}
#undef LBL
#endif
}
#ifdef NO_RECURSE
#undef eptr
#undef ecode
#undef mstart
#undef offset_top
#undef eptrb
#undef flags
#undef callpat
#undef charptr
#undef data
#undef next
#undef pp
#undef prev
#undef saved_eptr
#undef new_recursive
#undef cur_is_word
#undef condition
#undef prev_is_word
#undef ctype
#undef length
#undef max
#undef min
#undef number
#undef offset
#undef op
#undef save_capture_last
#undef save_offset1
#undef save_offset2
#undef save_offset3
#undef stacksave
#undef newptrb
#endif
#undef fc
#undef fi
#ifdef NO_RECURSE
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
#if defined COMPILE_PCRE8
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre_exec(const pcre *argument_re, const pcre_extra *extra_data,
PCRE_SPTR subject, int length, int start_offset, int options, int *offsets,
int offsetcount)
#elif defined COMPILE_PCRE16
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre16_exec(const pcre16 *argument_re, const pcre16_extra *extra_data,
PCRE_SPTR16 subject, int length, int start_offset, int options, int *offsets,
int offsetcount)
#elif defined COMPILE_PCRE32
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre32_exec(const pcre32 *argument_re, const pcre32_extra *extra_data,
PCRE_SPTR32 subject, int length, int start_offset, int options, int *offsets,
int offsetcount)
#endif
{
int rc, ocount, arg_offset_max;
int newline;
BOOL using_temporary_offsets = FALSE;
BOOL anchored;
BOOL startline;
BOOL firstline;
BOOL utf;
BOOL has_first_char = FALSE;
BOOL has_req_char = FALSE;
pcre_uchar first_char = 0;
pcre_uchar first_char2 = 0;
pcre_uchar req_char = 0;
pcre_uchar req_char2 = 0;
match_data match_block;
match_data *md = &match_block;
const pcre_uint8 *tables;
const pcre_uint8 *start_bits = NULL;
PCRE_PUCHAR start_match = (PCRE_PUCHAR)subject + start_offset;
PCRE_PUCHAR end_subject;
PCRE_PUCHAR start_partial = NULL;
PCRE_PUCHAR match_partial = NULL;
PCRE_PUCHAR req_char_ptr = start_match - 1;
const pcre_study_data *study;
const REAL_PCRE *re = (const REAL_PCRE *)argument_re;
#ifdef NO_RECURSE
heapframe frame_zero;
frame_zero.Xprevframe = NULL;
frame_zero.Xnextframe = NULL;
md->match_frames_base = &frame_zero;
#endif
if (re == NULL && extra_data == NULL && subject == NULL && length == -999 &&
start_offset == -999)
#ifdef NO_RECURSE
return -((int)sizeof(heapframe));
#else
return match(NULL, NULL, NULL, 0, NULL, NULL, 0);
#endif
if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION;
if (re == NULL || subject == NULL || (offsets == NULL && offsetcount > 0))
return PCRE_ERROR_NULL;
if (offsetcount < 0) return PCRE_ERROR_BADCOUNT;
if (length < 0) return PCRE_ERROR_BADLENGTH;
if (start_offset < 0 || start_offset > length) return PCRE_ERROR_BADOFFSET;
if (re->magic_number != MAGIC_NUMBER)
return re->magic_number == REVERSED_MAGIC_NUMBER?
PCRE_ERROR_BADENDIANNESS:PCRE_ERROR_BADMAGIC;
if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE;
utf = md->utf = (re->options & PCRE_UTF8) != 0;
md->partial = ((options & PCRE_PARTIAL_HARD) != 0)? 2 :
((options & PCRE_PARTIAL_SOFT) != 0)? 1 : 0;
#ifdef SUPPORT_UTF
if (utf && (options & PCRE_NO_UTF8_CHECK) == 0)
{
int erroroffset;
int errorcode = PRIV(valid_utf)((PCRE_PUCHAR)subject, length, &erroroffset);
if (errorcode != 0)
{
if (offsetcount >= 2)
{
offsets[0] = erroroffset;
offsets[1] = errorcode;
}
#if defined COMPILE_PCRE8
return (errorcode <= PCRE_UTF8_ERR5 && md->partial > 1)?
PCRE_ERROR_SHORTUTF8 : PCRE_ERROR_BADUTF8;
#elif defined COMPILE_PCRE16
return (errorcode <= PCRE_UTF16_ERR1 && md->partial > 1)?
PCRE_ERROR_SHORTUTF16 : PCRE_ERROR_BADUTF16;
#elif defined COMPILE_PCRE32
return PCRE_ERROR_BADUTF32;
#endif
}
#if defined COMPILE_PCRE8 || defined COMPILE_PCRE16
if (start_offset > 0 && start_offset < length &&
NOT_FIRSTCHAR(((PCRE_PUCHAR)subject)[start_offset]))
return PCRE_ERROR_BADUTF8_OFFSET;
#endif
}
#endif
#ifdef SUPPORT_JIT
if (extra_data != NULL
&& (extra_data->flags & (PCRE_EXTRA_EXECUTABLE_JIT |
PCRE_EXTRA_TABLES)) == PCRE_EXTRA_EXECUTABLE_JIT
&& extra_data->executable_jit != NULL
&& (options & ~PUBLIC_JIT_EXEC_OPTIONS) == 0)
{
rc = PRIV(jit_exec)(extra_data, (const pcre_uchar *)subject, length,
start_offset, options, offsets, offsetcount);
if (rc != PCRE_ERROR_JIT_BADOPTION) return rc;
}
#endif
md->name_table = (pcre_uchar *)re + re->name_table_offset;
md->name_count = re->name_count;
md->name_entry_size = re->name_entry_size;
study = NULL;
md->match_limit = MATCH_LIMIT;
md->match_limit_recursion = MATCH_LIMIT_RECURSION;
md->callout_data = NULL;
tables = re->tables;
if (extra_data != NULL)
{
unsigned long int flags = extra_data->flags;
if ((flags & PCRE_EXTRA_STUDY_DATA) != 0)
study = (const pcre_study_data *)extra_data->study_data;
if ((flags & PCRE_EXTRA_MATCH_LIMIT) != 0)
md->match_limit = extra_data->match_limit;
if ((flags & PCRE_EXTRA_MATCH_LIMIT_RECURSION) != 0)
md->match_limit_recursion = extra_data->match_limit_recursion;
if ((flags & PCRE_EXTRA_CALLOUT_DATA) != 0)
md->callout_data = extra_data->callout_data;
if ((flags & PCRE_EXTRA_TABLES) != 0) tables = extra_data->tables;
}
if ((re->flags & PCRE_MLSET) != 0 && re->limit_match < md->match_limit)
md->match_limit = re->limit_match;
if ((re->flags & PCRE_RLSET) != 0 &&
re->limit_recursion < md->match_limit_recursion)
md->match_limit_recursion = re->limit_recursion;
if (tables == NULL) tables = PRIV(default_tables);
anchored = ((re->options | options) & PCRE_ANCHORED) != 0;
startline = (re->flags & PCRE_STARTLINE) != 0;
firstline = (re->options & PCRE_FIRSTLINE) != 0;
md->start_code = (const pcre_uchar *)re + re->name_table_offset +
re->name_count * re->name_entry_size;
md->start_subject = (PCRE_PUCHAR)subject;
md->start_offset = start_offset;
md->end_subject = md->start_subject + length;
end_subject = md->end_subject;
md->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
md->use_ucp = (re->options & PCRE_UCP) != 0;
md->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0;
md->ignore_skip_arg = 0;
md->notbol = (options & PCRE_NOTBOL) != 0;
md->noteol = (options & PCRE_NOTEOL) != 0;
md->notempty = (options & PCRE_NOTEMPTY) != 0;
md->notempty_atstart = (options & PCRE_NOTEMPTY_ATSTART) != 0;
md->hitend = FALSE;
md->mark = md->nomatch_mark = NULL;
md->recursive = NULL;
md->hasthen = (re->flags & PCRE_HASTHEN) != 0;
md->lcc = tables + lcc_offset;
md->fcc = tables + fcc_offset;
md->ctypes = tables + ctypes_offset;
switch (options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE))
{
case 0:
if ((re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) != 0)
md->bsr_anycrlf = (re->options & PCRE_BSR_ANYCRLF) != 0;
else
#ifdef BSR_ANYCRLF
md->bsr_anycrlf = TRUE;
#else
md->bsr_anycrlf = FALSE;
#endif
break;
case PCRE_BSR_ANYCRLF:
md->bsr_anycrlf = TRUE;
break;
case PCRE_BSR_UNICODE:
md->bsr_anycrlf = FALSE;
break;
default: return PCRE_ERROR_BADNEWLINE;
}
switch ((((options & PCRE_NEWLINE_BITS) == 0)? re->options :
(pcre_uint32)options) & PCRE_NEWLINE_BITS)
{
case 0: newline = NEWLINE; break;
case PCRE_NEWLINE_CR: newline = CHAR_CR; break;
case PCRE_NEWLINE_LF: newline = CHAR_NL; break;
case PCRE_NEWLINE_CR+
PCRE_NEWLINE_LF: newline = (CHAR_CR << 8) | CHAR_NL; break;
case PCRE_NEWLINE_ANY: newline = -1; break;
case PCRE_NEWLINE_ANYCRLF: newline = -2; break;
default: return PCRE_ERROR_BADNEWLINE;
}
if (newline == -2)
{
md->nltype = NLTYPE_ANYCRLF;
}
else if (newline < 0)
{
md->nltype = NLTYPE_ANY;
}
else
{
md->nltype = NLTYPE_FIXED;
if (newline > 255)
{
md->nllen = 2;
md->nl[0] = (newline >> 8) & 255;
md->nl[1] = newline & 255;
}
else
{
md->nllen = 1;
md->nl[0] = newline;
}
}
if (md->partial && (re->flags & PCRE_NOPARTIAL) != 0)
return PCRE_ERROR_BADPARTIAL;
ocount = offsetcount - (offsetcount % 3);
arg_offset_max = (2*ocount)/3;
if (re->top_backref > 0 && re->top_backref >= ocount/3)
{
ocount = re->top_backref * 3 + 3;
md->offset_vector = (int *)(PUBL(malloc))(ocount * sizeof(int));
if (md->offset_vector == NULL) return PCRE_ERROR_NOMEMORY;
using_temporary_offsets = TRUE;
DPRINTF(("Got memory to hold back references\n"));
}
else md->offset_vector = offsets;
md->offset_end = ocount;
md->offset_max = (2*ocount)/3;
md->capture_last = 0;
if (md->offset_vector != NULL)
{
register int *iptr = md->offset_vector + ocount;
register int *iend = iptr - re->top_bracket;
if (iend < md->offset_vector + 2) iend = md->offset_vector + 2;
while (--iptr >= iend) *iptr = -1;
if (offsetcount > 0) md->offset_vector[0] = -1;
if (offsetcount > 1) md->offset_vector[1] = -1;
}
if (!anchored)
{
if ((re->flags & PCRE_FIRSTSET) != 0)
{
has_first_char = TRUE;
first_char = first_char2 = (pcre_uchar)(re->first_char);
if ((re->flags & PCRE_FCH_CASELESS) != 0)
{
first_char2 = TABLE_GET(first_char, md->fcc, first_char);
#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
if (utf && first_char > 127)
first_char2 = UCD_OTHERCASE(first_char);
#endif
}
}
else
if (!startline && study != NULL &&
(study->flags & PCRE_STUDY_MAPPED) != 0)
start_bits = study->start_bits;
}
if ((re->flags & PCRE_REQCHSET) != 0)
{
has_req_char = TRUE;
req_char = req_char2 = (pcre_uchar)(re->req_char);
if ((re->flags & PCRE_RCH_CASELESS) != 0)
{
req_char2 = TABLE_GET(req_char, md->fcc, req_char);
#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
if (utf && req_char > 127)
req_char2 = UCD_OTHERCASE(req_char);
#endif
}
}
for(;;)
{
PCRE_PUCHAR save_end_subject = end_subject;
PCRE_PUCHAR new_start_match;
if (firstline)
{
PCRE_PUCHAR t = start_match;
#ifdef SUPPORT_UTF
if (utf)
{
while (t < md->end_subject && !IS_NEWLINE(t))
{
t++;
ACROSSCHAR(t < end_subject, *t, t++);
}
}
else
#endif
while (t < md->end_subject && !IS_NEWLINE(t)) t++;
end_subject = t;
}
if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0)
{
if (has_first_char)
{
pcre_uchar smc;
if (first_char != first_char2)
while (start_match < end_subject &&
(smc = UCHAR21TEST(start_match)) != first_char && smc != first_char2)
start_match++;
else
while (start_match < end_subject && UCHAR21TEST(start_match) != first_char)
start_match++;
}
else if (startline)
{
if (start_match > md->start_subject + start_offset)
{
#ifdef SUPPORT_UTF
if (utf)
{
while (start_match < end_subject && !WAS_NEWLINE(start_match))
{
start_match++;
ACROSSCHAR(start_match < end_subject, *start_match,
start_match++);
}
}
else
#endif
while (start_match < end_subject && !WAS_NEWLINE(start_match))
start_match++;
if (start_match[-1] == CHAR_CR &&
(md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&
start_match < end_subject &&
UCHAR21TEST(start_match) == CHAR_NL)
start_match++;
}
}
else if (start_bits != NULL)
{
while (start_match < end_subject)
{
register pcre_uint32 c = UCHAR21TEST(start_match);
#ifndef COMPILE_PCRE8
if (c > 255) c = 255;
#endif
if ((start_bits[c/8] & (1 << (c&7))) != 0) break;
start_match++;
}
}
}
end_subject = save_end_subject;
if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0 && !md->partial)
{
if (study != NULL && (study->flags & PCRE_STUDY_MINLEN) != 0 &&
(pcre_uint32)(end_subject - start_match) < study->minlength)
{
rc = MATCH_NOMATCH;
break;
}
if (has_req_char && end_subject - start_match < REQ_BYTE_MAX)
{
register PCRE_PUCHAR p = start_match + (has_first_char? 1:0);
if (p > req_char_ptr)
{
if (req_char != req_char2)
{
while (p < end_subject)
{
register pcre_uint32 pp = UCHAR21INCTEST(p);
if (pp == req_char || pp == req_char2) { p--; break; }
}
}
else
{
while (p < end_subject)
{
if (UCHAR21INCTEST(p) == req_char) { p--; break; }
}
}
if (p >= end_subject)
{
rc = MATCH_NOMATCH;
break;
}
req_char_ptr = p;
}
}
}
#ifdef PCRE_DEBUG
printf(">>>> Match against: ");
pchars(start_match, end_subject - start_match, TRUE, md);
printf("\n");
#endif
md->start_match_ptr = start_match;
md->start_used_ptr = start_match;
md->match_call_count = 0;
md->match_function_type = 0;
md->end_offset_top = 0;
md->skip_arg_count = 0;
rc = match(start_match, md->start_code, start_match, 2, md, NULL, 0);
if (md->hitend && start_partial == NULL)
{
start_partial = md->start_used_ptr;
match_partial = start_match;
}
switch(rc)
{
case MATCH_SKIP_ARG:
new_start_match = start_match;
md->ignore_skip_arg = md->skip_arg_count;
break;
case MATCH_SKIP:
if (md->start_match_ptr > start_match)
{
new_start_match = md->start_match_ptr;
break;
}
case MATCH_NOMATCH:
case MATCH_PRUNE:
case MATCH_THEN:
md->ignore_skip_arg = 0;
new_start_match = start_match + 1;
#ifdef SUPPORT_UTF
if (utf)
ACROSSCHAR(new_start_match < end_subject, *new_start_match,
new_start_match++);
#endif
break;
case MATCH_COMMIT:
rc = MATCH_NOMATCH;
goto ENDLOOP;
default:
goto ENDLOOP;
}
rc = MATCH_NOMATCH;
if (firstline && IS_NEWLINE(start_match)) break;
start_match = new_start_match;
if (anchored || start_match > end_subject) break;
if (start_match > (PCRE_PUCHAR)subject + start_offset &&
start_match[-1] == CHAR_CR &&
start_match < end_subject &&
*start_match == CHAR_NL &&
(re->flags & PCRE_HASCRORLF) == 0 &&
(md->nltype == NLTYPE_ANY ||
md->nltype == NLTYPE_ANYCRLF ||
md->nllen == 2))
start_match++;
md->mark = NULL;
}
ENDLOOP:
if (rc == MATCH_MATCH || rc == MATCH_ACCEPT)
{
if (using_temporary_offsets)
{
if (arg_offset_max >= 4)
{
memcpy(offsets + 2, md->offset_vector + 2,
(arg_offset_max - 2) * sizeof(int));
DPRINTF(("Copied offsets from temporary memory\n"));
}
if (md->end_offset_top > arg_offset_max) md->capture_last |= OVFLBIT;
DPRINTF(("Freeing temporary memory\n"));
(PUBL(free))(md->offset_vector);
}
rc = ((md->capture_last & OVFLBIT) != 0 &&
md->end_offset_top >= arg_offset_max)?
0 : md->end_offset_top/2;
if (md->end_offset_top/2 <= re->top_bracket && offsets != NULL)
{
register int *iptr, *iend;
int resetcount = 2 + re->top_bracket * 2;
if (resetcount > offsetcount) resetcount = offsetcount;
iptr = offsets + md->end_offset_top;
iend = offsets + resetcount;
while (iptr < iend) *iptr++ = -1;
}
if (offsetcount < 2) rc = 0; else
{
offsets[0] = (int)(md->start_match_ptr - md->start_subject);
offsets[1] = (int)(md->end_match_ptr - md->start_subject);
}
if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_MARK) != 0)
*(extra_data->mark) = (pcre_uchar *)md->mark;
DPRINTF((">>>> returning %d\n", rc));
#ifdef NO_RECURSE
release_match_heapframes(&frame_zero);
#endif
return rc;
}
if (using_temporary_offsets)
{
DPRINTF(("Freeing temporary memory\n"));
(PUBL(free))(md->offset_vector);
}
if (rc != MATCH_NOMATCH && rc != PCRE_ERROR_PARTIAL)
{
DPRINTF((">>>> error: returning %d\n", rc));
#ifdef NO_RECURSE
release_match_heapframes(&frame_zero);
#endif
return rc;
}
if (match_partial != NULL)
{
DPRINTF((">>>> returning PCRE_ERROR_PARTIAL\n"));
md->mark = NULL;
if (offsetcount > 1)
{
offsets[0] = (int)(start_partial - (PCRE_PUCHAR)subject);
offsets[1] = (int)(end_subject - (PCRE_PUCHAR)subject);
if (offsetcount > 2)
offsets[2] = (int)(match_partial - (PCRE_PUCHAR)subject);
}
rc = PCRE_ERROR_PARTIAL;
}
else
{
DPRINTF((">>>> returning PCRE_ERROR_NOMATCH\n"));
rc = PCRE_ERROR_NOMATCH;
}
if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_MARK) != 0)
*(extra_data->mark) = (pcre_uchar *)md->nomatch_mark;
#ifdef NO_RECURSE
release_match_heapframes(&frame_zero);
#endif
return rc;
}