#include "pcre_internal.h"
typedef struct eptrblock {
struct eptrblock *epb_prev;
const pcre_uchar *epb_saved_eptr;
} eptrblock;
#define match_condassert 0x01
#define match_isgroup 0x02
#define MATCH_MATCH 1
#define MATCH_NOMATCH 0
#define REC_STACK_SAVE_MAX 30
static const char rep_min[] = { 0, 0, 1, 1, 0, 0 };
static const char rep_max[] = { 0, 0, 0, 0, 1, 1 };
#ifdef DEBUG
static void
pchars(const pcre_uchar *p, int length, BOOL is_subject, match_data *md)
{
int c;
if (is_subject && length > md->end_subject - p) length = md->end_subject - p;
while (length-- > 0)
if (isprint(c = *(p++))) printf("%c", c);
#if PCRE_UTF16
else if (c < 256) printf("\\x%02x", c);
else printf("\\x{%x}", c);
#else
else printf("\\x%02x", c);
#endif
}
#endif
static BOOL
match_ref(int offset, register const pcre_uchar *eptr, int length, match_data *md,
unsigned long int ims)
{
const pcre_uchar *p = md->start_subject + md->offset_vector[offset];
#ifdef 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 > md->end_subject - eptr) return FALSE;
if ((ims & PCRE_CASELESS) != 0)
{
while (length-- > 0)
if (md->lcc[*p++] != md->lcc[*eptr++]) return FALSE;
}
else
{ while (length-- > 0) if (*p++ != *eptr++) return FALSE; }
return TRUE;
}
#ifndef NO_RECURSE
#define REGISTER register
#define RMATCH(rx,ra,rb,rc,rd,re,rf,rg) rx = match(ra,rb,rc,rd,re,rf,rg)
#define RRETURN(ra) return ra
#else
#define REGISTER
#define RMATCH(rx,ra,rb,rc,rd,re,rf,rg)\
{\
heapframe *newframe = (pcre_stack_malloc)(sizeof(heapframe));\
if (setjmp(frame->Xwhere) == 0)\
{\
newframe->Xeptr = ra;\
newframe->Xecode = rb;\
newframe->Xoffset_top = rc;\
newframe->Xims = re;\
newframe->Xeptrb = rf;\
newframe->Xflags = rg;\
newframe->Xprevframe = frame;\
frame = newframe;\
DPRINTF(("restarting from line %d\n", __LINE__));\
goto HEAP_RECURSE;\
}\
else\
{\
DPRINTF(("longjumped back to line %d\n", __LINE__));\
frame = md->thisframe;\
rx = frame->Xresult;\
}\
}
#define RRETURN(ra)\
{\
heapframe *newframe = frame;\
frame = newframe->Xprevframe;\
(pcre_stack_free)(newframe);\
if (frame != NULL)\
{\
frame->Xresult = ra;\
md->thisframe = frame;\
longjmp(frame->Xwhere, 1);\
}\
return ra;\
}
typedef struct heapframe {
struct heapframe *Xprevframe;
const pcre_uchar *Xeptr;
const uschar *Xecode;
int Xoffset_top;
long int Xims;
eptrblock *Xeptrb;
int Xflags;
const uschar *Xcallpat;
const uschar *Xcharptr;
const uschar *Xdata;
const uschar *Xnext;
const pcre_uchar *Xpp;
const uschar *Xprev;
const pcre_uchar *Xsaved_eptr;
recursion_info Xnew_recursive;
BOOL Xcur_is_word;
BOOL Xcondition;
BOOL Xminimize;
BOOL Xprev_is_word;
unsigned long int Xoriginal_ims;
#ifdef SUPPORT_UCP
int Xprop_type;
int Xprop_fail_result;
int Xprop_category;
int Xprop_chartype;
int Xprop_othercase;
int Xprop_test_against;
int *Xprop_test_variable;
#endif
int Xctype;
int Xfc;
int Xfi;
int Xlength;
int Xmax;
int Xmin;
int Xnumber;
int Xoffset;
int Xop;
int Xsave_capture_last;
int Xsave_offset1, Xsave_offset2, Xsave_offset3;
int Xstacksave[REC_STACK_SAVE_MAX];
eptrblock Xnewptrb;
int Xresult;
jmp_buf Xwhere;
} heapframe;
#endif
static int
match(REGISTER const pcre_uchar *eptr, REGISTER const uschar *ecode,
int offset_top, match_data *md, unsigned long int ims, eptrblock *eptrb,
int flags)
{
register int rrc;
register int i;
register int c;
register BOOL utf8;
#ifdef NO_RECURSE
heapframe *frame = (pcre_stack_malloc)(sizeof(heapframe));
frame->Xprevframe = NULL;
frame->Xeptr = eptr;
frame->Xecode = ecode;
frame->Xoffset_top = offset_top;
frame->Xims = ims;
frame->Xeptrb = eptrb;
frame->Xflags = flags;
HEAP_RECURSE:
#define eptr frame->Xeptr
#define ecode frame->Xecode
#define offset_top frame->Xoffset_top
#define ims frame->Xims
#define eptrb frame->Xeptrb
#define flags frame->Xflags
#ifdef SUPPORT_UTF8
#define charptr frame->Xcharptr
#endif
#define callpat frame->Xcallpat
#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 minimize frame->Xminimize
#define prev_is_word frame->Xprev_is_word
#define original_ims frame->Xoriginal_ims
#ifdef SUPPORT_UCP
#define prop_type frame->Xprop_type
#define prop_fail_result frame->Xprop_fail_result
#define prop_category frame->Xprop_category
#define prop_chartype frame->Xprop_chartype
#define prop_othercase frame->Xprop_othercase
#define prop_test_against frame->Xprop_test_against
#define prop_test_variable frame->Xprop_test_variable
#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
#if !PCRE_UTF16
#ifdef SUPPORT_UTF8
const uschar *charptr;
#endif
#endif
const uschar *callpat;
const uschar *data;
const uschar *next;
const pcre_uchar *pp;
const uschar *prev;
const pcre_uchar *saved_eptr;
recursion_info new_recursive;
BOOL cur_is_word;
BOOL condition;
BOOL minimize;
BOOL prev_is_word;
unsigned long int original_ims;
#ifdef SUPPORT_UCP
int prop_type;
int prop_fail_result;
int prop_category;
int prop_chartype;
int prop_othercase;
int prop_test_against;
int *prop_test_variable;
#endif
int ctype;
int length;
int max;
int min;
int number;
int offset;
int op;
int save_capture_last;
int save_offset1, save_offset2, save_offset3;
int stacksave[REC_STACK_SAVE_MAX];
eptrblock newptrb;
#endif
#ifdef SUPPORT_UCP
prop_fail_result = 0;
prop_test_against = 0;
prop_test_variable = NULL;
#endif
if (md->match_call_count++ >= md->match_limit) RRETURN(PCRE_ERROR_MATCHLIMIT);
original_ims = ims;
utf8 = md->utf8;
if ((flags & match_isgroup) != 0)
{
newptrb.epb_prev = eptrb;
newptrb.epb_saved_eptr = eptr;
eptrb = &newptrb;
}
for (;;)
{
op = *ecode;
minimize = FALSE;
if (md->partial &&
eptr >= md->end_subject &&
eptr > md->start_match)
md->hitend = TRUE;
if (op > OP_BRA)
{
number = op - OP_BRA;
if (number > EXTRACT_BASIC_MAX)
number = GET2(ecode, 2+LINK_SIZE);
offset = number << 1;
#ifdef DEBUG
printf("start bracket %d subject=", number);
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;
DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3));
md->offset_vector[md->offset_end - number] = eptr - md->start_subject;
do
{
RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb,
match_isgroup);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
md->capture_last = save_capture_last;
ecode += GET(ecode, 1);
}
while (*ecode == OP_ALT);
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(MATCH_NOMATCH);
}
else op = OP_BRA;
}
switch(op)
{
case OP_BRA:
DPRINTF(("start bracket 0\n"));
do
{
RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb,
match_isgroup);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
ecode += GET(ecode, 1);
}
while (*ecode == OP_ALT);
DPRINTF(("bracket 0 failed\n"));
RRETURN(MATCH_NOMATCH);
case OP_COND:
if (ecode[LINK_SIZE+1] == OP_CREF)
{
offset = GET2(ecode, LINK_SIZE+2) << 1;
condition = (offset == CREF_RECURSE * 2)?
(md->recursive != NULL) :
(offset < offset_top && md->offset_vector[offset] >= 0);
RMATCH(rrc, eptr, ecode + (condition?
(LINK_SIZE + 4) : (LINK_SIZE + 1 + GET(ecode, 1))),
offset_top, md, ims, eptrb, match_isgroup);
RRETURN(rrc);
}
else
{
RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL,
match_condassert | match_isgroup);
if (rrc == MATCH_MATCH)
{
ecode += 1 + LINK_SIZE + GET(ecode, LINK_SIZE+2);
while (*ecode == OP_ALT) ecode += GET(ecode, 1);
}
else if (rrc != MATCH_NOMATCH)
{
RRETURN(rrc);
}
else ecode += GET(ecode, 1);
RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb,
match_isgroup);
RRETURN(rrc);
}
case OP_CREF:
case OP_BRANUMBER:
ecode += 3;
break;
case OP_END:
if (md->recursive != NULL && md->recursive->group_num == 0)
{
recursion_info *rec = md->recursive;
DPRINTF(("Hit the end in a (?0) recursion\n"));
md->recursive = rec->prevrec;
memmove(md->offset_vector, rec->offset_save,
rec->saved_max * sizeof(int));
md->start_match = rec->save_start;
ims = original_ims;
ecode = rec->after_call;
break;
}
if (md->notempty && eptr == md->start_match) RRETURN(MATCH_NOMATCH);
md->end_match_ptr = eptr;
md->end_offset_top = offset_top;
RRETURN(MATCH_MATCH);
case OP_OPT:
ims = ecode[1];
ecode += 2;
DPRINTF(("ims set to %02lx\n", ims));
break;
case OP_ASSERT:
case OP_ASSERTBACK:
do
{
RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL,
match_isgroup);
if (rrc == MATCH_MATCH) break;
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
ecode += GET(ecode, 1);
}
while (*ecode == OP_ALT);
if (*ecode == OP_KET) RRETURN(MATCH_NOMATCH);
if ((flags & match_condassert) != 0) 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:
do
{
RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL,
match_isgroup);
if (rrc == MATCH_MATCH) RRETURN(MATCH_NOMATCH);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
ecode += GET(ecode,1);
}
while (*ecode == OP_ALT);
if ((flags & match_condassert) != 0) RRETURN(MATCH_MATCH);
ecode += 1 + LINK_SIZE;
continue;
case OP_REVERSE:
#ifdef SUPPORT_UTF8
if (utf8)
{
c = GET(ecode,1);
for (i = 0; i < c; i++)
{
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);
}
ecode += 1 + LINK_SIZE;
break;
case OP_CALLOUT:
if (pcre_callout != NULL)
{
pcre_callout_block cb;
cb.version = 1;
cb.callout_number = ecode[1];
cb.offset_vector = md->offset_vector;
cb.subject = (const pcre_char *)md->start_subject;
cb.subject_length = md->end_subject - md->start_subject;
cb.start_match = md->start_match - md->start_subject;
cb.current_position = 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;
cb.callout_data = md->callout_data;
if ((rrc = (*pcre_callout)(&cb)) > 0) RRETURN(MATCH_NOMATCH);
if (rrc < 0) RRETURN(rrc);
}
ecode += 2 + 2*LINK_SIZE;
break;
case OP_RECURSE:
{
callpat = md->start_code + GET(ecode, 1);
new_recursive.group_num = *callpat - OP_BRA;
if (new_recursive.group_num > EXTRACT_BASIC_MAX)
new_recursive.group_num = GET2(callpat, 2+LINK_SIZE);
new_recursive.prevrec = md->recursive;
md->recursive = &new_recursive;
ecode += 1 + LINK_SIZE;
new_recursive.after_call = ecode;
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 *)(pcre_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));
new_recursive.save_start = md->start_match;
md->start_match = eptr;
DPRINTF(("Recursing into group %d\n", new_recursive.group_num));
do
{
RMATCH(rrc, eptr, callpat + 1 + LINK_SIZE, offset_top, md, ims,
eptrb, match_isgroup);
if (rrc == MATCH_MATCH)
{
md->recursive = new_recursive.prevrec;
if (new_recursive.offset_save != stacksave)
(pcre_free)(new_recursive.offset_save);
RRETURN(MATCH_MATCH);
}
else if (rrc != MATCH_NOMATCH) RRETURN(rrc);
md->recursive = &new_recursive;
memcpy(md->offset_vector, new_recursive.offset_save,
new_recursive.saved_max * sizeof(int));
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)
(pcre_free)(new_recursive.offset_save);
RRETURN(MATCH_NOMATCH);
}
case OP_ONCE:
{
prev = ecode;
saved_eptr = eptr;
do
{
RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims,
eptrb, match_isgroup);
if (rrc == MATCH_MATCH) break;
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
ecode += GET(ecode,1);
}
while (*ecode == OP_ALT);
if (*ecode != OP_ONCE && *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[1+LINK_SIZE] == OP_OPT)
{
ims = (ims & ~PCRE_IMS) | ecode[4];
DPRINTF(("ims set to %02lx at group repeat\n", ims));
}
if (*ecode == OP_KETRMIN)
{
RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
RMATCH(rrc, eptr, prev, offset_top, md, ims, eptrb, match_isgroup);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
}
else
{
RMATCH(rrc, eptr, prev, offset_top, md, ims, eptrb, match_isgroup);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
RMATCH(rrc, eptr, ecode + 1+LINK_SIZE, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
}
}
RRETURN(MATCH_NOMATCH);
case OP_ALT:
do ecode += GET(ecode,1); while (*ecode == OP_ALT);
break;
case OP_BRAZERO:
{
next = ecode+1;
RMATCH(rrc, eptr, next, offset_top, md, ims, eptrb, match_isgroup);
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(rrc, eptr, next + 1+LINK_SIZE, offset_top, md, ims, eptrb,
match_isgroup);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
ecode++;
}
break;
case OP_KET:
case OP_KETRMIN:
case OP_KETRMAX:
{
prev = ecode - GET(ecode, 1);
saved_eptr = eptrb->epb_saved_eptr;
eptrb = eptrb->epb_prev;
if (*prev == OP_ASSERT || *prev == OP_ASSERT_NOT ||
*prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT ||
*prev == OP_ONCE)
{
md->end_match_ptr = eptr;
md->end_offset_top = offset_top;
RRETURN(MATCH_MATCH);
}
if (*prev != OP_COND)
{
number = *prev - OP_BRA;
if (number > EXTRACT_BASIC_MAX) number = GET2(prev, 2+LINK_SIZE);
offset = number << 1;
#ifdef DEBUG
printf("end bracket %d", number);
printf("\n");
#endif
if (number > 0)
{
md->capture_last = number;
if (offset >= md->offset_max) md->offset_overflow = TRUE; else
{
md->offset_vector[offset] =
md->offset_vector[md->offset_end - number];
md->offset_vector[offset+1] = eptr - md->start_subject;
if (offset_top <= offset) offset_top = offset + 2;
}
if (md->recursive != NULL && md->recursive->group_num == number)
{
recursion_info *rec = md->recursive;
DPRINTF(("Recursion (%d) succeeded - continuing\n", number));
md->recursive = rec->prevrec;
md->start_match = rec->save_start;
memcpy(md->offset_vector, rec->offset_save,
rec->saved_max * sizeof(int));
ecode = rec->after_call;
ims = original_ims;
break;
}
}
}
ims = original_ims;
DPRINTF(("ims reset to %02lx\n", ims));
if (*ecode == OP_KET || eptr == saved_eptr)
{
ecode += 1 + LINK_SIZE;
break;
}
if (*ecode == OP_KETRMIN)
{
RMATCH(rrc, eptr, ecode + 1+LINK_SIZE, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
RMATCH(rrc, eptr, prev, offset_top, md, ims, eptrb, match_isgroup);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
}
else
{
RMATCH(rrc, eptr, prev, offset_top, md, ims, eptrb, match_isgroup);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
RMATCH(rrc, eptr, ecode + 1+LINK_SIZE, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
}
}
RRETURN(MATCH_NOMATCH);
case OP_CIRC:
if (md->notbol && eptr == md->start_subject) RRETURN(MATCH_NOMATCH);
if ((ims & PCRE_MULTILINE) != 0)
{
if (eptr != md->start_subject && eptr[-1] != NEWLINE)
RRETURN(MATCH_NOMATCH);
ecode++;
break;
}
case OP_SOD:
if (eptr != md->start_subject) RRETURN(MATCH_NOMATCH);
ecode++;
break;
case OP_SOM:
if (eptr != md->start_subject + md->start_offset) RRETURN(MATCH_NOMATCH);
ecode++;
break;
case OP_DOLL:
if ((ims & PCRE_MULTILINE) != 0)
{
if (eptr < md->end_subject)
{ if (*eptr != NEWLINE) RRETURN(MATCH_NOMATCH); }
else
{ if (md->noteol) RRETURN(MATCH_NOMATCH); }
ecode++;
break;
}
else
{
if (md->noteol) RRETURN(MATCH_NOMATCH);
if (!md->endonly)
{
if (eptr < md->end_subject - 1 ||
(eptr == md->end_subject - 1 && *eptr != NEWLINE))
RRETURN(MATCH_NOMATCH);
ecode++;
break;
}
}
case OP_EOD:
if (eptr < md->end_subject) RRETURN(MATCH_NOMATCH);
ecode++;
break;
case OP_EODN:
if (eptr < md->end_subject - 1 ||
(eptr == md->end_subject - 1 && *eptr != NEWLINE)) RRETURN(MATCH_NOMATCH);
ecode++;
break;
case OP_NOT_WORD_BOUNDARY:
case OP_WORD_BOUNDARY:
{
#ifdef SUPPORT_UTF8
if (utf8)
{
if (eptr == md->start_subject) prev_is_word = FALSE; else
{
const pcre_uchar *lastptr = eptr - 1;
while(ISMIDCHAR(*lastptr)) lastptr--;
GETCHAR(c, lastptr);
prev_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0;
}
if (eptr >= md->end_subject) cur_is_word = FALSE; else
{
GETCHAR(c, eptr);
cur_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0;
}
}
else
#endif
{
prev_is_word = (eptr != md->start_subject) &&
((md->ctypes[eptr[-1]] & ctype_word) != 0);
cur_is_word = (eptr < md->end_subject) &&
((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 ((ims & PCRE_DOTALL) == 0 && eptr < md->end_subject && *eptr == NEWLINE)
RRETURN(MATCH_NOMATCH);
if (eptr++ >= md->end_subject) RRETURN(MATCH_NOMATCH);
#ifdef SUPPORT_UTF8
if (utf8)
while (eptr < md->end_subject && ISMIDCHAR(*eptr)) eptr++;
#endif
ecode++;
break;
case OP_ANYBYTE:
if (eptr++ >= md->end_subject) RRETURN(MATCH_NOMATCH);
ecode++;
break;
case OP_NOT_DIGIT:
if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
GETCHARINCTEST(c, eptr);
if (
#ifdef SUPPORT_UTF8
c < 256 &&
#endif
(md->ctypes[c] & ctype_digit) != 0
)
RRETURN(MATCH_NOMATCH);
ecode++;
break;
case OP_DIGIT:
if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
GETCHARINCTEST(c, eptr);
if (
#ifdef SUPPORT_UTF8
c >= 256 ||
#endif
(md->ctypes[c] & ctype_digit) == 0
)
RRETURN(MATCH_NOMATCH);
ecode++;
break;
case OP_NOT_WHITESPACE:
if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
GETCHARINCTEST(c, eptr);
if (
#ifdef SUPPORT_UTF8
c < 256 &&
#endif
(md->ctypes[c] & ctype_space) != 0
)
RRETURN(MATCH_NOMATCH);
ecode++;
break;
case OP_WHITESPACE:
if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
GETCHARINCTEST(c, eptr);
if (
#ifdef SUPPORT_UTF8
c >= 256 ||
#endif
(md->ctypes[c] & ctype_space) == 0
)
RRETURN(MATCH_NOMATCH);
ecode++;
break;
case OP_NOT_WORDCHAR:
if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
GETCHARINCTEST(c, eptr);
if (
#ifdef SUPPORT_UTF8
c < 256 &&
#endif
(md->ctypes[c] & ctype_word) != 0
)
RRETURN(MATCH_NOMATCH);
ecode++;
break;
case OP_WORDCHAR:
if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
GETCHARINCTEST(c, eptr);
if (
#ifdef SUPPORT_UTF8
c >= 256 ||
#endif
(md->ctypes[c] & ctype_word) == 0
)
RRETURN(MATCH_NOMATCH);
ecode++;
break;
#ifdef SUPPORT_UCP
case OP_PROP:
case OP_NOTPROP:
if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
GETCHARINCTEST(c, eptr);
{
int chartype, rqdtype;
int othercase;
int category = ucp_findchar(c, &chartype, &othercase);
rqdtype = *(++ecode);
ecode++;
if (rqdtype >= 128)
{
if ((rqdtype - 128 != category) == (op == OP_PROP))
RRETURN(MATCH_NOMATCH);
}
else
{
if ((rqdtype != chartype) == (op == OP_PROP))
RRETURN(MATCH_NOMATCH);
}
}
break;
case OP_EXTUNI:
if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
GETCHARINCTEST(c, eptr);
{
int chartype;
int othercase;
int category = ucp_findchar(c, &chartype, &othercase);
if (category == ucp_M) RRETURN(MATCH_NOMATCH);
while (eptr < md->end_subject)
{
int len = 1;
if (!utf8) c = *eptr; else
{
GETCHARLEN(c, eptr, len);
}
category = ucp_findchar(c, &chartype, &othercase);
if (category != ucp_M) break;
eptr += len;
}
}
ecode++;
break;
#endif
case OP_REF:
{
offset = GET2(ecode, 1) << 1;
ecode += 3;
length = (offset >= offset_top || md->offset_vector[offset] < 0)?
md->end_subject - eptr + 1 :
md->offset_vector[offset+1] - md->offset_vector[offset];
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, 3);
if (max == 0) max = INT_MAX;
ecode += 5;
break;
default:
if (!match_ref(offset, eptr, length, md, ims)) RRETURN(MATCH_NOMATCH);
eptr += length;
continue;
}
if (length == 0) continue;
for (i = 1; i <= min; i++)
{
if (!match_ref(offset, eptr, length, md, ims)) RRETURN(MATCH_NOMATCH);
eptr += length;
}
if (min == max) continue;
if (minimize)
{
for (fi = min;; fi++)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || !match_ref(offset, eptr, length, md, ims))
RRETURN(MATCH_NOMATCH);
eptr += length;
}
}
else
{
pp = eptr;
for (i = min; i < max; i++)
{
if (!match_ref(offset, eptr, length, md, ims)) break;
eptr += length;
}
while (eptr >= pp)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr -= length;
}
RRETURN(MATCH_NOMATCH);
}
}
case OP_NCLASS:
case OP_CLASS:
{
data = ecode + 1;
ecode += 33;
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, 3);
if (max == 0) max = INT_MAX;
ecode += 5;
break;
default:
min = max = 1;
break;
}
#ifdef SUPPORT_UTF8
if (utf8)
{
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
GETCHARINC(c, eptr);
if (c > 255)
{
if (op == OP_CLASS) RRETURN(MATCH_NOMATCH);
}
else
{
if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
}
}
}
else
#endif
{
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
c = *eptr++;
if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
}
}
if (min == max) continue;
if (minimize)
{
#ifdef SUPPORT_UTF8
if (utf8)
{
for (fi = min;; fi++)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
GETCHARINC(c, eptr);
if (c > 255)
{
if (op == OP_CLASS) RRETURN(MATCH_NOMATCH);
}
else
{
if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
}
}
}
else
#endif
{
for (fi = min;; fi++)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
c = *eptr++;
if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
}
}
}
else
{
pp = eptr;
#ifdef SUPPORT_UTF8
if (utf8)
{
for (i = min; i < max; i++)
{
int len = 1;
if (eptr >= md->end_subject) break;
GETCHARLEN(c, eptr, len);
if (c > 255)
{
if (op == OP_CLASS) break;
}
else
{
if ((data[c/8] & (1 << (c&7))) == 0) break;
}
eptr += len;
}
for (;;)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
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) break;
c = *eptr;
if ((data[c/8] & (1 << (c&7))) == 0) break;
eptr++;
}
while (eptr >= pp)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
eptr--;
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
}
}
RRETURN(MATCH_NOMATCH);
}
}
#ifdef SUPPORT_UTF8
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:
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, 3);
if (max == 0) max = INT_MAX;
ecode += 5;
break;
default:
min = max = 1;
break;
}
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
GETCHARINC(c, eptr);
if (!_pcre_xclass(c, data)) RRETURN(MATCH_NOMATCH);
}
if (min == max) continue;
if (minimize)
{
for (fi = min;; fi++)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
GETCHARINC(c, eptr);
if (!_pcre_xclass(c, data)) RRETURN(MATCH_NOMATCH);
}
}
else
{
pp = eptr;
for (i = min; i < max; i++)
{
int len = 1;
if (eptr >= md->end_subject) break;
GETCHARLEN(c, eptr, len);
if (!_pcre_xclass(c, data)) break;
eptr += len;
}
for(;;)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (eptr-- == pp) break;
BACKCHAR(eptr)
}
RRETURN(MATCH_NOMATCH);
}
}
#endif
case OP_CHAR:
#ifdef SUPPORT_UTF8
if (utf8)
{
length = 1;
ecode++;
GETUTF8CHARLEN(fc, ecode, length);
#if PCRE_UTF16
{
int dc;
ecode += length;
switch (md->end_subject - eptr)
{
case 0:
RRETURN(MATCH_NOMATCH);
case 1:
dc = *eptr++;
if (IS_LEADING_SURROGATE(dc))
RRETURN(MATCH_NOMATCH);
break;
default:
GETCHARINC(dc, eptr);
}
if (fc != dc) RRETURN(MATCH_NOMATCH);
}
#else
if (length > md->end_subject - eptr) RRETURN(MATCH_NOMATCH);
while (length-- > 0) if (*ecode++ != *eptr++) RRETURN(MATCH_NOMATCH);
#endif
}
else
#endif
{
if (md->end_subject - eptr < 1) RRETURN(MATCH_NOMATCH);
if (ecode[1] != *eptr++) RRETURN(MATCH_NOMATCH);
ecode += 2;
}
break;
case OP_CHARNC:
#ifdef SUPPORT_UTF8
if (utf8)
{
length = 1;
ecode++;
GETUTF8CHARLEN(fc, ecode, length);
#if PCRE_UTF16
if (md->end_subject - eptr == 0) RRETURN(MATCH_NOMATCH);
#else
if (length > md->end_subject - eptr) RRETURN(MATCH_NOMATCH);
#endif
if (fc < 128)
{
#if PCRE_UTF16
int dc;
ecode++;
dc = *eptr++;
if (dc >= 128 || md->lcc[fc] != md->lcc[dc]) RRETURN(MATCH_NOMATCH);
#else
if (md->lcc[*ecode++] != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);
#endif
}
else
{
int dc;
#if PCRE_UTF16
if (md->end_subject - eptr == 1) {
dc = *eptr++;
if (IS_LEADING_SURROGATE(dc))
RRETURN(MATCH_NOMATCH);
} else
#endif
GETCHARINC(dc, eptr);
ecode += length;
if (fc != dc)
{
#ifdef SUPPORT_UCP
int chartype;
int othercase;
if (ucp_findchar(fc, &chartype, &othercase) != ucp_L || dc != othercase)
#endif
RRETURN(MATCH_NOMATCH);
}
}
}
else
#endif
{
if (md->end_subject - eptr < 1) RRETURN(MATCH_NOMATCH);
if (md->lcc[ecode[1]] != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);
ecode += 2;
}
break;
case OP_EXACT:
min = max = GET2(ecode, 1);
ecode += 3;
goto REPEATCHAR;
case OP_UPTO:
case OP_MINUPTO:
min = 0;
max = GET2(ecode, 1);
minimize = *ecode == OP_MINUPTO;
ecode += 3;
goto REPEATCHAR;
case OP_STAR:
case OP_MINSTAR:
case OP_PLUS:
case OP_MINPLUS:
case OP_QUERY:
case OP_MINQUERY:
c = *ecode++ - OP_STAR;
minimize = (c & 1) != 0;
min = rep_min[c];
max = rep_max[c];
if (max == 0) max = INT_MAX;
REPEATCHAR:
#ifdef SUPPORT_UTF8
#if PCRE_UTF16
length = 1;
GETUTF8CHARLEN(fc, ecode, length);
{
if (min * (fc > 0xFFFF ? 2 : 1) > md->end_subject - eptr) RRETURN(MATCH_NOMATCH);
ecode += length;
if (fc <= 0xFFFF)
{
#ifdef SUPPORT_UCP
int othercase;
int chartype;
if ((ims & PCRE_CASELESS) == 0 || ucp_findchar(fc, &chartype, &othercase) != ucp_L)
othercase = -1;
#endif
for (i = 1; i <= min; i++)
{
if (*eptr != fc && *eptr != othercase) RRETURN(MATCH_NOMATCH);
++eptr;
}
if (min == max) continue;
if (minimize)
{
for (fi = min;; fi++)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
if (*eptr != fc && *eptr != othercase) RRETURN(MATCH_NOMATCH);
++eptr;
}
}
else
{
pp = eptr;
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject) break;
if (*eptr != fc && *eptr != othercase) break;
++eptr;
}
while (eptr >= pp)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
--eptr;
}
RRETURN(MATCH_NOMATCH);
}
}
else
{
for (i = 1; i <= min; i++)
{
int nc;
GETCHAR(nc, eptr);
if (nc != fc) RRETURN(MATCH_NOMATCH);
eptr += 2;
}
if (min == max) continue;
if (minimize)
{
for (fi = min;; fi++)
{
int nc;
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
GETCHAR(nc, eptr);
if (*eptr != fc) RRETURN(MATCH_NOMATCH);
eptr += 2;
}
}
else
{
pp = eptr;
for (i = min; i < max; i++)
{
int nc;
if (eptr > md->end_subject - 2) break;
GETCHAR(nc, eptr);
if (*eptr != fc) break;
eptr += 2;
}
while (eptr >= pp)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr -= 2;
}
RRETURN(MATCH_NOMATCH);
}
}
}
#else
if (utf8)
{
length = 1;
charptr = ecode;
GETCHARLEN(fc, ecode, length);
if (min * length > md->end_subject - eptr) RRETURN(MATCH_NOMATCH);
ecode += length;
if (length > 1)
{
int oclength = 0;
uschar occhars[8];
#ifdef SUPPORT_UCP
int othercase;
int chartype;
if ((ims & PCRE_CASELESS) != 0 &&
ucp_findchar(fc, &chartype, &othercase) == ucp_L &&
othercase > 0)
oclength = _pcre_ord2utf8(othercase, occhars);
#endif
for (i = 1; i <= min; i++)
{
if (memcmp(eptr, charptr, length) == 0) eptr += length;
else if (oclength == 0) { RRETURN(MATCH_NOMATCH); }
else
{
if (memcmp(eptr, occhars, oclength) != 0) RRETURN(MATCH_NOMATCH);
eptr += oclength;
}
}
if (min == max) continue;
if (minimize)
{
for (fi = min;; fi++)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
if (memcmp(eptr, charptr, length) == 0) eptr += length;
else if (oclength == 0) { RRETURN(MATCH_NOMATCH); }
else
{
if (memcmp(eptr, occhars, oclength) != 0) RRETURN(MATCH_NOMATCH);
eptr += oclength;
}
}
}
else
{
pp = eptr;
for (i = min; i < max; i++)
{
if (eptr > md->end_subject - length) break;
if (memcmp(eptr, charptr, length) == 0) eptr += length;
else if (oclength == 0) break;
else
{
if (memcmp(eptr, occhars, oclength) != 0) break;
eptr += oclength;
}
}
while (eptr >= pp)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr -= length;
}
RRETURN(MATCH_NOMATCH);
}
}
}
else
#endif
#endif
{
if (min > md->end_subject - eptr) RRETURN(MATCH_NOMATCH);
fc = *ecode++;
}
#if PCRE_UTF16
DPRINTF(("matching %c{%d,%d}\n", fc, min, max));
#else
DPRINTF(("matching %c{%d,%d} against subject %.*s\n", fc, min, max,
max, eptr));
#endif
if ((ims & PCRE_CASELESS) != 0)
{
fc = md->lcc[fc];
for (i = 1; i <= min; i++)
if (fc != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);
if (min == max) continue;
if (minimize)
{
for (fi = min;; fi++)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject ||
fc != md->lcc[*eptr++])
RRETURN(MATCH_NOMATCH);
}
}
else
{
pp = eptr;
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject || fc != md->lcc[*eptr]) break;
eptr++;
}
while (eptr >= pp)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
eptr--;
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
}
RRETURN(MATCH_NOMATCH);
}
}
else
{
for (i = 1; i <= min; i++) if (fc != *eptr++) RRETURN(MATCH_NOMATCH);
if (min == max) continue;
if (minimize)
{
for (fi = min;; fi++)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject || fc != *eptr++)
RRETURN(MATCH_NOMATCH);
}
}
else
{
pp = eptr;
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject || fc != *eptr) break;
eptr++;
}
while (eptr >= pp)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
eptr--;
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
}
RRETURN(MATCH_NOMATCH);
}
}
case OP_NOT:
if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
ecode++;
GETCHARINCTEST(c, eptr);
if ((ims & PCRE_CASELESS) != 0)
{
#ifdef SUPPORT_UTF8
if (c < 256)
#endif
c = md->lcc[c];
if (md->lcc[*ecode++] == c) RRETURN(MATCH_NOMATCH);
}
else
{
if (*ecode++ == c) RRETURN(MATCH_NOMATCH);
}
break;
case OP_NOTEXACT:
min = max = GET2(ecode, 1);
ecode += 3;
goto REPEATNOTCHAR;
case OP_NOTUPTO:
case OP_NOTMINUPTO:
min = 0;
max = GET2(ecode, 1);
minimize = *ecode == OP_NOTMINUPTO;
ecode += 3;
goto REPEATNOTCHAR;
case OP_NOTSTAR:
case OP_NOTMINSTAR:
case OP_NOTPLUS:
case OP_NOTMINPLUS:
case OP_NOTQUERY:
case OP_NOTMINQUERY:
c = *ecode++ - OP_NOTSTAR;
minimize = (c & 1) != 0;
min = rep_min[c];
max = rep_max[c];
if (max == 0) max = INT_MAX;
REPEATNOTCHAR:
if (min > md->end_subject - eptr) RRETURN(MATCH_NOMATCH);
fc = *ecode++;
#if PCRE_UTF16
DPRINTF(("negative matching %c{%d,%d}\n", fc, min, max));
#else
DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", fc, min, max,
max, eptr));
#endif
if ((ims & PCRE_CASELESS) != 0)
{
fc = md->lcc[fc];
#ifdef SUPPORT_UTF8
if (utf8)
{
register int d;
for (i = 1; i <= min; i++)
{
GETCHARINC(d, eptr);
if (d < 256) d = md->lcc[d];
if (fc == d) RRETURN(MATCH_NOMATCH);
}
}
else
#endif
{
for (i = 1; i <= min; i++)
if (fc == md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);
}
if (min == max) continue;
if (minimize)
{
#ifdef SUPPORT_UTF8
if (utf8)
{
register int d;
for (fi = min;; fi++)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
GETCHARINC(d, eptr);
if (d < 256) d = md->lcc[d];
if (fi >= max || eptr >= md->end_subject || fc == d)
RRETURN(MATCH_NOMATCH);
}
}
else
#endif
{
for (fi = min;; fi++)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject || fc == md->lcc[*eptr++])
RRETURN(MATCH_NOMATCH);
}
}
}
else
{
pp = eptr;
#ifdef SUPPORT_UTF8
if (utf8)
{
register int d;
for (i = min; i < max; i++)
{
int len = 1;
if (eptr >= md->end_subject) break;
GETCHARLEN(d, eptr, len);
if (d < 256) d = md->lcc[d];
if (fc == d) break;
eptr += len;
}
for(;;)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
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 || fc == md->lcc[*eptr]) break;
eptr++;
}
while (eptr >= pp)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
}
}
RRETURN(MATCH_NOMATCH);
}
}
else
{
#ifdef SUPPORT_UTF8
if (utf8)
{
register int d;
for (i = 1; i <= min; i++)
{
GETCHARINC(d, eptr);
if (fc == d) RRETURN(MATCH_NOMATCH);
}
}
else
#endif
{
for (i = 1; i <= min; i++)
if (fc == *eptr++) RRETURN(MATCH_NOMATCH);
}
if (min == max) continue;
if (minimize)
{
#ifdef SUPPORT_UTF8
if (utf8)
{
register int d;
for (fi = min;; fi++)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
GETCHARINC(d, eptr);
if (fi >= max || eptr >= md->end_subject || fc == d)
RRETURN(MATCH_NOMATCH);
}
}
else
#endif
{
for (fi = min;; fi++)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject || fc == *eptr++)
RRETURN(MATCH_NOMATCH);
}
}
}
else
{
pp = eptr;
#ifdef SUPPORT_UTF8
if (utf8)
{
register int d;
for (i = min; i < max; i++)
{
int len = 1;
if (eptr >= md->end_subject) break;
GETCHARLEN(d, eptr, len);
if (fc == d) break;
eptr += len;
}
for(;;)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
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 || fc == *eptr) break;
eptr++;
}
while (eptr >= pp)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
}
}
RRETURN(MATCH_NOMATCH);
}
}
case OP_TYPEEXACT:
min = max = GET2(ecode, 1);
minimize = TRUE;
ecode += 3;
goto REPEATTYPE;
case OP_TYPEUPTO:
case OP_TYPEMINUPTO:
min = 0;
max = GET2(ecode, 1);
minimize = *ecode == OP_TYPEMINUPTO;
ecode += 3;
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++;
if (prop_type >= 128)
{
prop_test_against = prop_type - 128;
prop_test_variable = &prop_category;
}
else
{
prop_test_against = prop_type;
prop_test_variable = &prop_chartype;
}
}
else prop_type = -1;
#endif
if (min > md->end_subject - eptr) RRETURN(MATCH_NOMATCH);
if (min > 0)
{
#ifdef SUPPORT_UCP
if (prop_type > 0)
{
for (i = 1; i <= min; i++)
{
GETCHARINC(c, eptr);
prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase);
if ((*prop_test_variable == prop_test_against) == prop_fail_result)
RRETURN(MATCH_NOMATCH);
}
}
else if (ctype == OP_EXTUNI)
{
for (i = 1; i <= min; i++)
{
GETCHARINCTEST(c, eptr);
prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase);
if (prop_category == ucp_M) RRETURN(MATCH_NOMATCH);
while (eptr < md->end_subject)
{
int len = 1;
if (!utf8) c = *eptr; else
{
GETCHARLEN(c, eptr, len);
}
prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase);
if (prop_category != ucp_M) break;
eptr += len;
}
}
}
else
#endif
#ifdef SUPPORT_UTF8
if (utf8) switch(ctype)
{
case OP_ANY:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject ||
(*eptr++ == NEWLINE && (ims & PCRE_DOTALL) == 0))
RRETURN(MATCH_NOMATCH);
while (eptr < md->end_subject && ISMIDCHAR(*eptr)) eptr++;
}
break;
case OP_ANYBYTE:
eptr += min;
break;
case OP_NOT_DIGIT:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject) 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++)
{
if (eptr >= md->end_subject ||
*eptr >= 128 || (md->ctypes[*eptr++] & ctype_digit) == 0)
RRETURN(MATCH_NOMATCH);
}
break;
case OP_NOT_WHITESPACE:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject ||
(*eptr < 128 && (md->ctypes[*eptr++] & ctype_space) != 0))
RRETURN(MATCH_NOMATCH);
while (eptr < md->end_subject && ISMIDCHAR(*eptr)) eptr++;
}
break;
case OP_WHITESPACE:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject ||
*eptr >= 128 || (md->ctypes[*eptr++] & ctype_space) == 0)
RRETURN(MATCH_NOMATCH);
}
break;
case OP_NOT_WORDCHAR:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject ||
(*eptr < 128 && (md->ctypes[*eptr++] & ctype_word) != 0))
RRETURN(MATCH_NOMATCH);
while (eptr < md->end_subject && ISMIDCHAR(*eptr)) eptr++;
}
break;
case OP_WORDCHAR:
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject ||
*eptr >= 128 || (md->ctypes[*eptr++] & ctype_word) == 0)
RRETURN(MATCH_NOMATCH);
}
break;
default:
RRETURN(PCRE_ERROR_INTERNAL);
}
else
#endif
switch(ctype)
{
case OP_ANY:
if ((ims & PCRE_DOTALL) == 0)
{
for (i = 1; i <= min; i++)
if (*eptr++ == NEWLINE) RRETURN(MATCH_NOMATCH);
}
else eptr += min;
break;
case OP_ANYBYTE:
eptr += min;
break;
case OP_NOT_DIGIT:
for (i = 1; i <= min; i++)
if ((md->ctypes[*eptr++] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH);
break;
case OP_DIGIT:
for (i = 1; i <= min; i++)
if ((md->ctypes[*eptr++] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH);
break;
case OP_NOT_WHITESPACE:
for (i = 1; i <= min; i++)
if ((md->ctypes[*eptr++] & ctype_space) != 0) RRETURN(MATCH_NOMATCH);
break;
case OP_WHITESPACE:
for (i = 1; i <= min; i++)
if ((md->ctypes[*eptr++] & ctype_space) == 0) RRETURN(MATCH_NOMATCH);
break;
case OP_NOT_WORDCHAR:
for (i = 1; i <= min; i++)
if ((md->ctypes[*eptr++] & ctype_word) != 0)
RRETURN(MATCH_NOMATCH);
break;
case OP_WORDCHAR:
for (i = 1; i <= min; i++)
if ((md->ctypes[*eptr++] & ctype_word) == 0)
RRETURN(MATCH_NOMATCH);
break;
default:
RRETURN(PCRE_ERROR_INTERNAL);
}
}
if (min == max) continue;
if (minimize)
{
#ifdef SUPPORT_UCP
if (prop_type > 0)
{
for (fi = min;; fi++)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
GETCHARINC(c, eptr);
prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase);
if ((*prop_test_variable == prop_test_against) == prop_fail_result)
RRETURN(MATCH_NOMATCH);
}
}
else if (ctype == OP_EXTUNI)
{
for (fi = min;; fi++)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
GETCHARINCTEST(c, eptr);
prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase);
if (prop_category == ucp_M) RRETURN(MATCH_NOMATCH);
while (eptr < md->end_subject)
{
int len = 1;
if (!utf8) c = *eptr; else
{
GETCHARLEN(c, eptr, len);
}
prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase);
if (prop_category != ucp_M) break;
eptr += len;
}
}
}
else
#endif
#ifdef SUPPORT_UTF8
if (utf8)
{
for (fi = min;; fi++)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
GETCHARINC(c, eptr);
switch(ctype)
{
case OP_ANY:
if ((ims & PCRE_DOTALL) == 0 && c == NEWLINE) RRETURN(MATCH_NOMATCH);
break;
case OP_ANYBYTE:
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(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
c = *eptr++;
switch(ctype)
{
case OP_ANY:
if ((ims & PCRE_DOTALL) == 0 && c == NEWLINE) RRETURN(MATCH_NOMATCH);
break;
case OP_ANYBYTE:
break;
case OP_NOT_DIGIT:
if ((md->ctypes[c] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH);
break;
case OP_DIGIT:
if ((md->ctypes[c] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH);
break;
case OP_NOT_WHITESPACE:
if ((md->ctypes[c] & ctype_space) != 0) RRETURN(MATCH_NOMATCH);
break;
case OP_WHITESPACE:
if ((md->ctypes[c] & ctype_space) == 0) RRETURN(MATCH_NOMATCH);
break;
case OP_NOT_WORDCHAR:
if ((md->ctypes[c] & ctype_word) != 0) RRETURN(MATCH_NOMATCH);
break;
case OP_WORDCHAR:
if ((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)
{
for (i = min; i < max; i++)
{
int len = 1;
if (eptr >= md->end_subject) break;
GETCHARLEN(c, eptr, len);
prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase);
if ((*prop_test_variable == prop_test_against) == prop_fail_result)
break;
eptr+= len;
}
for(;;)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (eptr-- == pp) break;
BACKCHAR(eptr);
}
}
else if (ctype == OP_EXTUNI)
{
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject) break;
GETCHARINCTEST(c, eptr);
prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase);
if (prop_category == ucp_M) break;
while (eptr < md->end_subject)
{
int len = 1;
if (!utf8) c = *eptr; else
{
GETCHARLEN(c, eptr, len);
}
prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase);
if (prop_category != ucp_M) break;
eptr += len;
}
}
for(;;)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (eptr-- == pp) break;
for (;;)
{
int len = 1;
BACKCHAR(eptr);
if (!utf8) c = *eptr; else
{
GETCHARLEN(c, eptr, len);
}
prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase);
if (prop_category != ucp_M) break;
eptr--;
}
}
}
else
#endif
#ifdef SUPPORT_UTF8
if (utf8)
{
switch(ctype)
{
case OP_ANY:
if (max < INT_MAX)
{
if ((ims & PCRE_DOTALL) == 0)
{
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject || *eptr == NEWLINE) break;
eptr++;
while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
}
}
else
{
for (i = min; i < max; i++)
{
eptr++;
while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
}
}
}
else
{
if ((ims & PCRE_DOTALL) == 0)
{
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject || *eptr == NEWLINE) break;
eptr++;
}
break;
}
else
{
c = max - min;
if (c > md->end_subject - eptr) c = md->end_subject - eptr;
eptr += c;
}
}
break;
case OP_ANYBYTE:
c = max - min;
if (c > md->end_subject - eptr) c = md->end_subject - eptr;
eptr += c;
break;
case OP_NOT_DIGIT:
for (i = min; i < max; i++)
{
int len = 1;
if (eptr >= md->end_subject) 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) 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) 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) 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) 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) break;
GETCHARLEN(c, eptr, len);
if (c >= 256 || (md->ctypes[c] & ctype_word) == 0) break;
eptr+= len;
}
break;
default:
RRETURN(PCRE_ERROR_INTERNAL);
}
for(;;)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (eptr-- == pp) break;
BACKCHAR(eptr);
}
}
else
#endif
{
switch(ctype)
{
case OP_ANY:
if ((ims & PCRE_DOTALL) == 0)
{
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject || *eptr == NEWLINE) break;
eptr++;
}
break;
}
case OP_ANYBYTE:
c = max - min;
if (c > md->end_subject - eptr) c = md->end_subject - eptr;
eptr += c;
break;
case OP_NOT_DIGIT:
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) != 0)
break;
eptr++;
}
break;
case OP_DIGIT:
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) == 0)
break;
eptr++;
}
break;
case OP_NOT_WHITESPACE:
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) != 0)
break;
eptr++;
}
break;
case OP_WHITESPACE:
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) == 0)
break;
eptr++;
}
break;
case OP_NOT_WORDCHAR:
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) != 0)
break;
eptr++;
}
break;
case OP_WORDCHAR:
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) == 0)
break;
eptr++;
}
break;
default:
RRETURN(PCRE_ERROR_INTERNAL);
}
while (eptr >= pp)
{
RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
eptr--;
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
}
}
RRETURN(MATCH_NOMATCH);
}
default:
DPRINTF(("Unknown opcode %d\n", *ecode));
RRETURN(PCRE_ERROR_UNKNOWN_NODE);
}
}
}
#ifdef NO_RECURSE
#undef eptr
#undef ecode
#undef offset_top
#undef ims
#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 minimize
#undef prev_is_word
#undef original_ims
#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
EXPORT int
pcre_exec(const pcre *argument_re, const pcre_extra *extra_data,
const pcre_char *subject, int length, int start_offset, int options, int *offsets,
int offsetcount)
{
int rc, resetcount, ocount;
int first_byte = -1;
int req_byte = -1;
int req_byte2 = -1;
unsigned long int ims = 0;
BOOL using_temporary_offsets = FALSE;
BOOL anchored;
BOOL startline;
BOOL firstline;
BOOL first_byte_caseless = FALSE;
BOOL req_byte_caseless = FALSE;
match_data match_block;
const uschar *tables;
const uschar *start_bits = NULL;
const pcre_uchar *start_match = (const pcre_uchar *)subject + start_offset;
const pcre_uchar *end_subject;
const pcre_uchar *req_byte_ptr = start_match - 1;
pcre_study_data internal_study;
const pcre_study_data *study;
real_pcre internal_re;
const real_pcre *external_re = (const real_pcre *)argument_re;
const real_pcre *re = external_re;
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;
study = NULL;
match_block.match_limit = MATCH_LIMIT;
match_block.callout_data = NULL;
tables = external_re->tables;
if (extra_data != NULL)
{
register unsigned 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)
match_block.match_limit = extra_data->match_limit;
if ((flags & PCRE_EXTRA_CALLOUT_DATA) != 0)
match_block.callout_data = extra_data->callout_data;
if ((flags & PCRE_EXTRA_TABLES) != 0) tables = extra_data->tables;
}
if (tables == NULL) tables = _pcre_default_tables;
if (re->magic_number != MAGIC_NUMBER)
{
re = _pcre_try_flipped(re, &internal_re, study, &internal_study);
if (re == NULL) return PCRE_ERROR_BADMAGIC;
if (study != NULL) study = &internal_study;
}
anchored = ((re->options | options) & PCRE_ANCHORED) != 0;
startline = (re->options & PCRE_STARTLINE) != 0;
firstline = (re->options & PCRE_FIRSTLINE) != 0;
match_block.start_code = (const uschar *)external_re + re->name_table_offset +
re->name_count * re->name_entry_size;
match_block.start_subject = (const pcre_uchar *)subject;
match_block.start_offset = start_offset;
match_block.end_subject = match_block.start_subject + length;
end_subject = match_block.end_subject;
match_block.endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
match_block.utf8 = (re->options & PCRE_UTF8) != 0;
match_block.notbol = (options & PCRE_NOTBOL) != 0;
match_block.noteol = (options & PCRE_NOTEOL) != 0;
match_block.notempty = (options & PCRE_NOTEMPTY) != 0;
match_block.partial = (options & PCRE_PARTIAL) != 0;
match_block.hitend = FALSE;
match_block.recursive = NULL;
match_block.lcc = tables + lcc_offset;
match_block.ctypes = tables + ctypes_offset;
if (match_block.partial && (re->options & PCRE_NOPARTIAL) != 0)
return PCRE_ERROR_BADPARTIAL;
#if !PCRE_UTF16
#ifdef SUPPORT_UTF8
if (match_block.utf8 && (options & PCRE_NO_UTF8_CHECK) == 0)
{
if (_pcre_valid_utf8((pcre_uchar *)subject, length) >= 0)
return PCRE_ERROR_BADUTF8;
if (start_offset > 0 && start_offset < length)
{
int tb = ((pcre_uchar *)subject)[start_offset];
if (tb > 127)
{
tb &= 0xc0;
if (tb != 0 && tb != 0xc0) return PCRE_ERROR_BADUTF8_OFFSET;
}
}
}
#endif
#endif
ims = re->options & (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL);
ocount = offsetcount - (offsetcount % 3);
if (re->top_backref > 0 && re->top_backref >= ocount/3)
{
ocount = re->top_backref * 3 + 3;
match_block.offset_vector = (int *)(pcre_malloc)(ocount * sizeof(int));
if (match_block.offset_vector == NULL) return PCRE_ERROR_NOMEMORY;
using_temporary_offsets = TRUE;
DPRINTF(("Got memory to hold back references\n"));
}
else match_block.offset_vector = offsets;
match_block.offset_end = ocount;
match_block.offset_max = (2*ocount)/3;
match_block.offset_overflow = FALSE;
match_block.capture_last = -1;
resetcount = 2 + re->top_bracket * 2;
if (resetcount > offsetcount) resetcount = ocount;
if (match_block.offset_vector != NULL)
{
register int *iptr = match_block.offset_vector + ocount;
register int *iend = iptr - resetcount/2 + 1;
while (--iptr >= iend) *iptr = -1;
}
if (!anchored)
{
if ((re->options & PCRE_FIRSTSET) != 0)
{
first_byte = re->first_byte & 255;
if ((first_byte_caseless = ((re->first_byte & REQ_CASELESS) != 0)) == TRUE)
first_byte = match_block.lcc[first_byte];
}
else
if (!startline && study != NULL &&
(study->options & PCRE_STUDY_MAPPED) != 0)
start_bits = study->start_bits;
}
if ((re->options & PCRE_REQCHSET) != 0)
{
req_byte = re->req_byte & 255;
req_byte_caseless = (re->req_byte & REQ_CASELESS) != 0;
req_byte2 = (tables + fcc_offset)[req_byte];
}
do
{
const pcre_uchar *save_end_subject = end_subject;
if (match_block.offset_vector != NULL)
{
register int *iptr = match_block.offset_vector;
register int *iend = iptr + resetcount;
while (iptr < iend) *iptr++ = -1;
}
if (firstline)
{
const pcre_uchar *t = start_match;
while (t < save_end_subject && *t != '\n') t++;
end_subject = t;
}
if (first_byte >= 0)
{
if (first_byte_caseless)
while (start_match < end_subject)
{
int sm = *start_match;
#if PCRE_UTF16
if (sm > 127)
break;
#endif
if (match_block.lcc[sm] == first_byte)
break;
start_match++;
}
else
while (start_match < end_subject && *start_match != first_byte)
start_match++;
}
else if (startline)
{
if (start_match > match_block.start_subject + start_offset)
{
while (start_match < end_subject && start_match[-1] != NEWLINE)
start_match++;
}
}
else if (start_bits != NULL)
{
while (start_match < end_subject)
{
register unsigned int c = *start_match;
if ((start_bits[c/8] & (1 << (c&7))) == 0) start_match++; else break;
}
}
end_subject = save_end_subject;
#ifdef DEBUG
printf(">>>> Match against: ");
pchars(start_match, end_subject - start_match, TRUE, &match_block);
printf("\n");
#endif
if (req_byte >= 0 &&
end_subject - start_match < REQ_BYTE_MAX &&
!match_block.partial)
{
register const pcre_uchar *p = start_match + ((first_byte >= 0)? 1 : 0);
if (p > req_byte_ptr)
{
if (req_byte_caseless)
{
while (p < end_subject)
{
register int pp = *p++;
if (pp == req_byte || pp == req_byte2) { p--; break; }
}
}
else
{
while (p < end_subject)
{
if (*p++ == req_byte) { p--; break; }
}
}
if (p >= end_subject) break;
req_byte_ptr = p;
}
}
match_block.start_match = start_match;
match_block.match_call_count = 0;
rc = match(start_match, match_block.start_code, 2, &match_block, ims, NULL,
match_isgroup);
if (rc == MATCH_NOMATCH)
{
if (firstline && *start_match == NEWLINE) break;
start_match++;
#ifdef SUPPORT_UTF8
if (match_block.utf8)
while(start_match < end_subject && ISMIDCHAR(*start_match))
start_match++;
#endif
continue;
}
if (rc != MATCH_MATCH)
{
DPRINTF((">>>> error: returning %d\n", rc));
return rc;
}
if (using_temporary_offsets)
{
if (offsetcount >= 4)
{
memcpy(offsets + 2, match_block.offset_vector + 2,
(offsetcount - 2) * sizeof(int));
DPRINTF(("Copied offsets from temporary memory\n"));
}
if (match_block.end_offset_top > offsetcount)
match_block.offset_overflow = TRUE;
DPRINTF(("Freeing temporary memory\n"));
(pcre_free)(match_block.offset_vector);
}
rc = match_block.offset_overflow? 0 : match_block.end_offset_top/2;
if (offsetcount < 2) rc = 0; else
{
offsets[0] = start_match - match_block.start_subject;
offsets[1] = match_block.end_match_ptr - match_block.start_subject;
}
DPRINTF((">>>> returning %d\n", rc));
return rc;
}
while (!anchored && start_match <= end_subject);
if (using_temporary_offsets)
{
DPRINTF(("Freeing temporary memory\n"));
(pcre_free)(match_block.offset_vector);
}
if (match_block.partial && match_block.hitend)
{
DPRINTF((">>>> returning PCRE_ERROR_PARTIAL\n"));
return PCRE_ERROR_PARTIAL;
}
else
{
DPRINTF((">>>> returning PCRE_ERROR_NOMATCH\n"));
return PCRE_ERROR_NOMATCH;
}
}