-/* $Cambridge: exim/src/src/pcre/pcre_exec.c,v 1.4 2007/01/23 15:08:45 ph10 Exp $ */
+/* $Cambridge: exim/src/src/pcre/pcre_exec.c,v 1.5 2007/06/26 11:16:54 ph10 Exp $ */
/*************************************************
* Perl-Compatible Regular Expressions *
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
- Copyright (c) 1997-2006 University of Cambridge
+ Copyright (c) 1997-2007 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
#include "pcre_internal.h"
+/* Undefine some potentially clashing cpp symbols */
+
+#undef min
+#undef max
+
/* The chain of eptrblocks for tail recursions uses memory in stack workspace,
obtained at top level, the size of which is defined by EPTR_WORK_SIZE. */
obtained from malloc() instead instead of on the stack. Macros are used to
achieve this so that the actual code doesn't look very different to what it
always used to.
+
+The original heap-recursive code used longjmp(). However, it seems that this
+can be very slow on some operating systems. Following a suggestion from Stan
+Switzer, the use of longjmp() has been abolished, at the cost of having to
+provide a unique number for each call to RMATCH. There is no way of generating
+a sequence of numbers at compile time in C. I have given them names, to make
+them stand out more clearly.
+
+Crude tests on x86 Linux show a small speedup of around 5-8%. However, on
+FreeBSD, avoiding longjmp() more than halves the time taken to run the standard
+tests. Furthermore, not using longjmp() means that local dynamic variables
+don't have indeterminate values; this has meant that the frame size can be
+reduced because the result can be "passed back" by straight setting of the
+variable instead of being passed in the frame.
****************************************************************************
***************************************************************************/
+/* Numbers for RMATCH calls */
+
+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 };
+
+
/* These versions of the macros use the stack, as normal. There are debugging
-versions and production versions. */
+versions and production versions. Note that the "rw" argument of RMATCH isn't
+actuall used in this definition. */
#ifndef NO_RECURSE
#define REGISTER register
+
#ifdef DEBUG
-#define RMATCH(rx,ra,rb,rc,rd,re,rf,rg) \
+#define RMATCH(ra,rb,rc,rd,re,rf,rg,rw) \
{ \
printf("match() called in line %d\n", __LINE__); \
- rx = match(ra,rb,rc,rd,re,rf,rg,rdepth+1); \
+ rrc = match(ra,rb,mstart,rc,rd,re,rf,rg,rdepth+1); \
printf("to line %d\n", __LINE__); \
}
#define RRETURN(ra) \
return ra; \
}
#else
-#define RMATCH(rx,ra,rb,rc,rd,re,rf,rg) \
- rx = match(ra,rb,rc,rd,re,rf,rg,rdepth+1)
+#define RMATCH(ra,rb,rc,rd,re,rf,rg,rw) \
+ rrc = match(ra,rb,mstart,rc,rd,re,rf,rg,rdepth+1)
#define RRETURN(ra) return ra
#endif
#else
-/* These versions of the macros manage a private stack on the heap. Note
-that the rd argument of RMATCH isn't actually used. It's the md argument of
-match(), which never changes. */
+/* These versions of the macros manage a private stack on the heap. Note that
+the "rd" argument of RMATCH isn't actually used in this definition. It's the md
+argument of match(), which never changes. */
#define REGISTER
-#define RMATCH(rx,ra,rb,rc,rd,re,rf,rg)\
+#define RMATCH(ra,rb,rc,rd,re,rf,rg,rw)\
{\
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->Xrdepth = frame->Xrdepth + 1;\
- 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;\
- }\
+ frame->Xwhere = rw; \
+ newframe->Xeptr = ra;\
+ newframe->Xecode = rb;\
+ newframe->Xmstart = mstart;\
+ newframe->Xoffset_top = rc;\
+ newframe->Xims = re;\
+ newframe->Xeptrb = rf;\
+ newframe->Xflags = rg;\
+ 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)\
(pcre_stack_free)(newframe);\
if (frame != NULL)\
{\
- frame->Xresult = ra;\
- md->thisframe = frame;\
- longjmp(frame->Xwhere, 1);\
+ rrc = ra;\
+ goto HEAP_RETURN;\
}\
return ra;\
}
const uschar *Xeptr;
const uschar *Xecode;
+ const uschar *Xmstart;
int Xoffset_top;
long int Xims;
eptrblock *Xeptrb;
int Xprop_category;
int Xprop_chartype;
int Xprop_script;
+ int Xoclength;
+ uschar Xocchars[8];
#endif
int Xctype;
eptrblock Xnewptrb;
- /* Place to pass back result, and where to jump back to */
+ /* Where to jump back to */
- int Xresult;
- jmp_buf Xwhere;
+ int Xwhere;
} heapframe;
Arguments:
eptr pointer to current character in subject
ecode pointer to current position in compiled code
+ mstart pointer to the current match start position (can be modified
+ by encountering \K)
offset_top current top pointer
md pointer to "static" info for the match
ims current /i, /m, and /s options
*/
static int
-match(REGISTER USPTR eptr, REGISTER const uschar *ecode,
+match(REGISTER USPTR eptr, REGISTER const uschar *ecode, const uschar *mstart,
int offset_top, match_data *md, unsigned long int ims, eptrblock *eptrb,
int flags, unsigned int rdepth)
{
frame->Xeptr = eptr;
frame->Xecode = ecode;
+frame->Xmstart = mstart;
frame->Xoffset_top = offset_top;
frame->Xims = ims;
frame->Xeptrb = eptrb;
#define eptr frame->Xeptr
#define ecode frame->Xecode
+#define mstart frame->Xmstart
#define offset_top frame->Xoffset_top
#define ims frame->Xims
#define eptrb frame->Xeptrb
#define prop_category frame->Xprop_category
#define prop_chartype frame->Xprop_chartype
#define prop_script frame->Xprop_script
+#define oclength frame->Xoclength
+#define occhars frame->Xocchars
#endif
#define ctype frame->Xctype
int prop_category;
int prop_chartype;
int prop_script;
+int oclength;
+uschar occhars[8];
#endif
int ctype;
complicated macro. It has to be used in one particular way. This shouldn't,
however, impact performance when true recursion is being used. */
+#ifdef SUPPORT_UTF8
+utf8 = md->utf8; /* Local copy of the flag */
+#else
+utf8 = FALSE;
+#endif
+
/* First check that we haven't called match() too many times, or that we
haven't exceeded the recursive call limit. */
original_ims = ims; /* Save for resetting on ')' */
-#ifdef SUPPORT_UTF8
-utf8 = md->utf8; /* Local copy of the flag */
-#else
-utf8 = FALSE;
-#endif
-
/* At the start of a group with an unlimited repeat that may match an empty
string, the match_cbegroup flag is set. When this is the case, add the current
subject pointer to the chain of such remembered pointers, to be checked when we
if (md->partial &&
eptr >= md->end_subject &&
- eptr > md->start_match)
+ eptr > mstart)
md->hitend = TRUE;
switch(op)
flags = (op == OP_SCBRA)? match_cbegroup : 0;
do
{
- RMATCH(rrc, eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
- ims, eptrb, flags);
+ RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
+ ims, eptrb, flags, RM1);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
md->capture_last = save_capture_last;
ecode += GET(ecode, 1);
/* For non-final alternatives, continue the loop for a NOMATCH result;
otherwise return. */
- RMATCH(rrc, eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, ims,
- eptrb, flags);
+ RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, ims,
+ eptrb, flags, RM2);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
ecode += GET(ecode, 1);
}
else
{
- RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL,
- match_condassert);
+ RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL,
+ match_condassert, RM3);
if (rrc == MATCH_MATCH)
{
condition = TRUE;
md->recursive = rec->prevrec;
memmove(md->offset_vector, rec->offset_save,
rec->saved_max * sizeof(int));
- md->start_match = rec->save_start;
+ mstart = rec->save_start;
ims = original_ims;
ecode = rec->after_call;
break;
/* Otherwise, if PCRE_NOTEMPTY is set, fail if we have matched an empty
string - backtracking will then try other alternatives, if any. */
- if (md->notempty && eptr == md->start_match) RRETURN(MATCH_NOMATCH);
- md->end_match_ptr = eptr; /* Record where we ended */
- md->end_offset_top = offset_top; /* and how many extracts were taken */
+ if (md->notempty && eptr == mstart) RRETURN(MATCH_NOMATCH);
+ md->end_match_ptr = eptr; /* Record where we ended */
+ md->end_offset_top = offset_top; /* and how many extracts were taken */
+ md->start_match_ptr = mstart; /* and the start (\K can modify) */
RRETURN(MATCH_MATCH);
/* Change option settings */
case OP_ASSERTBACK:
do
{
- RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, 0);
+ RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, 0,
+ RM4);
if (rrc == MATCH_MATCH) break;
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
ecode += GET(ecode, 1);
case OP_ASSERTBACK_NOT:
do
{
- RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, 0);
+ RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, 0,
+ RM5);
if (rrc == MATCH_MATCH) RRETURN(MATCH_NOMATCH);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
ecode += GET(ecode,1);
cb.offset_vector = md->offset_vector;
cb.subject = (PCRE_SPTR)md->start_subject;
cb.subject_length = md->end_subject - md->start_subject;
- cb.start_match = md->start_match - md->start_subject;
+ cb.start_match = mstart - 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);
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;
+ new_recursive.save_start = mstart;
+ mstart = eptr;
/* OK, now we can do the recursion. For each top-level alternative we
restore the offset and recursion data. */
flags = (*callpat >= OP_SBRA)? match_cbegroup : 0;
do
{
- RMATCH(rrc, eptr, callpat + _pcre_OP_lengths[*callpat], offset_top,
- md, ims, eptrb, flags);
+ RMATCH(eptr, callpat + _pcre_OP_lengths[*callpat], offset_top,
+ md, ims, eptrb, flags, RM6);
if (rrc == MATCH_MATCH)
{
DPRINTF(("Recursion matched\n"));
do
{
- RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims,
- eptrb, 0);
+ RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims,
+ eptrb, 0, RM7);
if (rrc == MATCH_MATCH) break;
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
ecode += GET(ecode,1);
if (*ecode == OP_KETRMIN)
{
- RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, 0,
+ RM8);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
ecode = prev;
flags = match_tail_recursed;
}
else /* OP_KETRMAX */
{
- RMATCH(rrc, eptr, prev, offset_top, md, ims, eptrb, match_cbegroup);
+ RMATCH(eptr, prev, offset_top, md, ims, eptrb, match_cbegroup, RM9);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
ecode += 1 + LINK_SIZE;
flags = match_tail_recursed;
case OP_BRAZERO:
{
next = ecode+1;
- RMATCH(rrc, eptr, next, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, next, offset_top, md, ims, eptrb, 0, RM10);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
do next += GET(next,1); while (*next == OP_ALT);
ecode = next + 1 + LINK_SIZE;
{
next = ecode+1;
do next += GET(next, 1); while (*next == OP_ALT);
- RMATCH(rrc, eptr, next + 1+LINK_SIZE, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, next + 1+LINK_SIZE, offset_top, md, ims, eptrb, 0, RM11);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
ecode++;
}
recursion_info *rec = md->recursive;
DPRINTF(("Recursion (%d) succeeded - continuing\n", number));
md->recursive = rec->prevrec;
- md->start_match = rec->save_start;
+ mstart = rec->save_start;
memcpy(md->offset_vector, rec->offset_save,
rec->saved_max * sizeof(int));
ecode = rec->after_call;
if (*ecode == OP_KETRMIN)
{
- RMATCH(rrc, eptr, ecode + 1+LINK_SIZE, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode + 1+LINK_SIZE, offset_top, md, ims, eptrb, 0,
+ RM12);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
ecode = prev;
flags |= match_tail_recursed;
}
else /* OP_KETRMAX */
{
- RMATCH(rrc, eptr, prev, offset_top, md, ims, eptrb, flags);
+ RMATCH(eptr, prev, offset_top, md, ims, eptrb, flags, RM13);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
ecode += 1 + LINK_SIZE;
flags = match_tail_recursed;
ecode++;
break;
+ /* Reset the start of match point */
+
+ case OP_SET_SOM:
+ mstart = eptr;
+ ecode++;
+ break;
+
/* Assert before internal newline if multiline, or before a terminating
newline unless endonly is set, else end of subject unless noteol is set. */
ecode++;
break;
+ case OP_NOT_HSPACE:
+ if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
+ GETCHARINCTEST(c, eptr);
+ switch(c)
+ {
+ default: break;
+ case 0x09: /* HT */
+ case 0x20: /* SPACE */
+ case 0xa0: /* NBSP */
+ case 0x1680: /* OGHAM SPACE MARK */
+ case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */
+ case 0x2000: /* EN QUAD */
+ case 0x2001: /* EM QUAD */
+ case 0x2002: /* EN SPACE */
+ case 0x2003: /* EM SPACE */
+ case 0x2004: /* THREE-PER-EM SPACE */
+ case 0x2005: /* FOUR-PER-EM SPACE */
+ case 0x2006: /* SIX-PER-EM SPACE */
+ case 0x2007: /* FIGURE SPACE */
+ case 0x2008: /* PUNCTUATION SPACE */
+ case 0x2009: /* THIN SPACE */
+ case 0x200A: /* HAIR SPACE */
+ case 0x202f: /* NARROW NO-BREAK SPACE */
+ case 0x205f: /* MEDIUM MATHEMATICAL SPACE */
+ case 0x3000: /* IDEOGRAPHIC SPACE */
+ RRETURN(MATCH_NOMATCH);
+ }
+ ecode++;
+ break;
+
+ case OP_HSPACE:
+ if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
+ GETCHARINCTEST(c, eptr);
+ switch(c)
+ {
+ default: RRETURN(MATCH_NOMATCH);
+ case 0x09: /* HT */
+ case 0x20: /* SPACE */
+ case 0xa0: /* NBSP */
+ case 0x1680: /* OGHAM SPACE MARK */
+ case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */
+ case 0x2000: /* EN QUAD */
+ case 0x2001: /* EM QUAD */
+ case 0x2002: /* EN SPACE */
+ case 0x2003: /* EM SPACE */
+ case 0x2004: /* THREE-PER-EM SPACE */
+ case 0x2005: /* FOUR-PER-EM SPACE */
+ case 0x2006: /* SIX-PER-EM SPACE */
+ case 0x2007: /* FIGURE SPACE */
+ case 0x2008: /* PUNCTUATION SPACE */
+ case 0x2009: /* THIN SPACE */
+ case 0x200A: /* HAIR SPACE */
+ case 0x202f: /* NARROW NO-BREAK SPACE */
+ case 0x205f: /* MEDIUM MATHEMATICAL SPACE */
+ case 0x3000: /* IDEOGRAPHIC SPACE */
+ break;
+ }
+ ecode++;
+ break;
+
+ case OP_NOT_VSPACE:
+ if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
+ GETCHARINCTEST(c, eptr);
+ switch(c)
+ {
+ default: break;
+ case 0x0a: /* LF */
+ case 0x0b: /* VT */
+ case 0x0c: /* FF */
+ case 0x0d: /* CR */
+ case 0x85: /* NEL */
+ case 0x2028: /* LINE SEPARATOR */
+ case 0x2029: /* PARAGRAPH SEPARATOR */
+ RRETURN(MATCH_NOMATCH);
+ }
+ ecode++;
+ break;
+
+ case OP_VSPACE:
+ if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
+ GETCHARINCTEST(c, eptr);
+ switch(c)
+ {
+ default: RRETURN(MATCH_NOMATCH);
+ case 0x0a: /* LF */
+ case 0x0b: /* VT */
+ case 0x0c: /* FF */
+ case 0x0d: /* CR */
+ case 0x85: /* NEL */
+ case 0x2028: /* LINE SEPARATOR */
+ case 0x2029: /* PARAGRAPH SEPARATOR */
+ break;
+ }
+ ecode++;
+ break;
+
#ifdef SUPPORT_UCP
/* Check the next character by Unicode property. We will get here only
if the support is in the binary; otherwise a compile-time error occurs. */
{
for (fi = min;; fi++)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM14);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || !match_ref(offset, eptr, length, md, ims))
RRETURN(MATCH_NOMATCH);
}
while (eptr >= pp)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM15);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr -= length;
}
{
for (fi = min;; fi++)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM16);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
GETCHARINC(c, eptr);
{
for (fi = min;; fi++)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM17);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
c = *eptr++;
}
for (;;)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM18);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (eptr-- == pp) break; /* Stop if tried at original pos */
BACKCHAR(eptr);
}
while (eptr >= pp)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM19);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
}
{
for (fi = min;; fi++)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM20);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
GETCHARINC(c, eptr);
}
for(;;)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM21);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (eptr-- == pp) break; /* Stop if tried at original pos */
BACKCHAR(eptr)
if (length > 1)
{
- int oclength = 0;
- uschar occhars[8];
-
#ifdef SUPPORT_UCP
unsigned int othercase;
if ((ims & PCRE_CASELESS) != 0 &&
(othercase = _pcre_ucp_othercase(fc)) != NOTACHAR)
oclength = _pcre_ord2utf8(othercase, occhars);
+ else oclength = 0;
#endif /* SUPPORT_UCP */
for (i = 1; i <= min; i++)
{
if (memcmp(eptr, charptr, length) == 0) eptr += length;
+#ifdef SUPPORT_UCP
/* Need braces because of following else */
else if (oclength == 0) { RRETURN(MATCH_NOMATCH); }
else
if (memcmp(eptr, occhars, oclength) != 0) RRETURN(MATCH_NOMATCH);
eptr += oclength;
}
+#else /* without SUPPORT_UCP */
+ else { RRETURN(MATCH_NOMATCH); }
+#endif /* SUPPORT_UCP */
}
if (min == max) continue;
{
for (fi = min;; fi++)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM22);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
if (memcmp(eptr, charptr, length) == 0) eptr += length;
+#ifdef SUPPORT_UCP
/* Need braces because of following else */
else if (oclength == 0) { RRETURN(MATCH_NOMATCH); }
else
if (memcmp(eptr, occhars, oclength) != 0) RRETURN(MATCH_NOMATCH);
eptr += oclength;
}
+#else /* without SUPPORT_UCP */
+ else { RRETURN (MATCH_NOMATCH); }
+#endif /* SUPPORT_UCP */
}
/* Control never gets here */
}
{
if (eptr > md->end_subject - length) break;
if (memcmp(eptr, charptr, length) == 0) eptr += length;
+#ifdef SUPPORT_UCP
else if (oclength == 0) break;
else
{
if (memcmp(eptr, occhars, oclength) != 0) break;
eptr += oclength;
}
+#else /* without SUPPORT_UCP */
+ else break;
+#endif /* SUPPORT_UCP */
}
if (possessive) continue;
- while (eptr >= pp)
+ for(;;)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM23);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (eptr == pp) RRETURN(MATCH_NOMATCH);
+#ifdef SUPPORT_UCP
+ eptr--;
+ BACKCHAR(eptr);
+#else /* without SUPPORT_UCP */
eptr -= length;
+#endif /* SUPPORT_UCP */
}
- RRETURN(MATCH_NOMATCH);
}
/* Control never gets here */
}
{
for (fi = min;; fi++)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM24);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject ||
fc != md->lcc[*eptr++])
if (possessive) continue;
while (eptr >= pp)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM25);
eptr--;
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
}
{
for (fi = min;; fi++)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM26);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject || fc != *eptr++)
RRETURN(MATCH_NOMATCH);
if (possessive) continue;
while (eptr >= pp)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM27);
eptr--;
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
}
register unsigned int d;
for (fi = min;; fi++)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM28);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
GETCHARINC(d, eptr);
if (d < 256) d = md->lcc[d];
{
for (fi = min;; fi++)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM29);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject || fc == md->lcc[*eptr++])
RRETURN(MATCH_NOMATCH);
if (possessive) continue;
for(;;)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM30);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (eptr-- == pp) break; /* Stop if tried at original pos */
BACKCHAR(eptr);
if (possessive) continue;
while (eptr >= pp)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM31);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
}
register unsigned int d;
for (fi = min;; fi++)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM32);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
GETCHARINC(d, eptr);
if (fi >= max || eptr >= md->end_subject || fc == d)
{
for (fi = min;; fi++)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM33);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject || fc == *eptr++)
RRETURN(MATCH_NOMATCH);
if (possessive) continue;
for(;;)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM34);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (eptr-- == pp) break; /* Stop if tried at original pos */
BACKCHAR(eptr);
if (possessive) continue;
while (eptr >= pp)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM35);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
}
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINC(c, eptr);
+ GETCHARINCTEST(c, eptr);
}
break;
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINC(c, eptr);
+ GETCHARINCTEST(c, eptr);
prop_category = _pcre_ucp_findprop(c, &prop_chartype, &prop_script);
if ((prop_chartype == ucp_Lu ||
prop_chartype == ucp_Ll ||
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINC(c, eptr);
+ GETCHARINCTEST(c, eptr);
prop_category = _pcre_ucp_findprop(c, &prop_chartype, &prop_script);
if ((prop_category == prop_value) == prop_fail_result)
RRETURN(MATCH_NOMATCH);
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINC(c, eptr);
+ GETCHARINCTEST(c, eptr);
prop_category = _pcre_ucp_findprop(c, &prop_chartype, &prop_script);
if ((prop_chartype == prop_value) == prop_fail_result)
RRETURN(MATCH_NOMATCH);
for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINC(c, eptr);
+ GETCHARINCTEST(c, eptr);
prop_category = _pcre_ucp_findprop(c, &prop_chartype, &prop_script);
if ((prop_script == prop_value) == prop_fail_result)
RRETURN(MATCH_NOMATCH);
}
break;
+ case OP_NOT_HSPACE:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
+ GETCHARINC(c, eptr);
+ switch(c)
+ {
+ default: break;
+ case 0x09: /* HT */
+ case 0x20: /* SPACE */
+ case 0xa0: /* NBSP */
+ case 0x1680: /* OGHAM SPACE MARK */
+ case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */
+ case 0x2000: /* EN QUAD */
+ case 0x2001: /* EM QUAD */
+ case 0x2002: /* EN SPACE */
+ case 0x2003: /* EM SPACE */
+ case 0x2004: /* THREE-PER-EM SPACE */
+ case 0x2005: /* FOUR-PER-EM SPACE */
+ case 0x2006: /* SIX-PER-EM SPACE */
+ case 0x2007: /* FIGURE SPACE */
+ case 0x2008: /* PUNCTUATION SPACE */
+ case 0x2009: /* THIN SPACE */
+ case 0x200A: /* HAIR SPACE */
+ case 0x202f: /* NARROW NO-BREAK SPACE */
+ case 0x205f: /* MEDIUM MATHEMATICAL SPACE */
+ case 0x3000: /* IDEOGRAPHIC SPACE */
+ RRETURN(MATCH_NOMATCH);
+ }
+ }
+ break;
+
+ case OP_HSPACE:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
+ GETCHARINC(c, eptr);
+ switch(c)
+ {
+ default: RRETURN(MATCH_NOMATCH);
+ case 0x09: /* HT */
+ case 0x20: /* SPACE */
+ case 0xa0: /* NBSP */
+ case 0x1680: /* OGHAM SPACE MARK */
+ case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */
+ case 0x2000: /* EN QUAD */
+ case 0x2001: /* EM QUAD */
+ case 0x2002: /* EN SPACE */
+ case 0x2003: /* EM SPACE */
+ case 0x2004: /* THREE-PER-EM SPACE */
+ case 0x2005: /* FOUR-PER-EM SPACE */
+ case 0x2006: /* SIX-PER-EM SPACE */
+ case 0x2007: /* FIGURE SPACE */
+ case 0x2008: /* PUNCTUATION SPACE */
+ case 0x2009: /* THIN SPACE */
+ case 0x200A: /* HAIR SPACE */
+ case 0x202f: /* NARROW NO-BREAK SPACE */
+ case 0x205f: /* MEDIUM MATHEMATICAL SPACE */
+ case 0x3000: /* IDEOGRAPHIC SPACE */
+ break;
+ }
+ }
+ break;
+
+ case OP_NOT_VSPACE:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
+ GETCHARINC(c, eptr);
+ switch(c)
+ {
+ default: break;
+ case 0x0a: /* LF */
+ case 0x0b: /* VT */
+ case 0x0c: /* FF */
+ case 0x0d: /* CR */
+ case 0x85: /* NEL */
+ case 0x2028: /* LINE SEPARATOR */
+ case 0x2029: /* PARAGRAPH SEPARATOR */
+ RRETURN(MATCH_NOMATCH);
+ }
+ }
+ break;
+
+ case OP_VSPACE:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
+ GETCHARINC(c, eptr);
+ switch(c)
+ {
+ default: RRETURN(MATCH_NOMATCH);
+ case 0x0a: /* LF */
+ case 0x0b: /* VT */
+ case 0x0c: /* FF */
+ case 0x0d: /* CR */
+ case 0x85: /* NEL */
+ case 0x2028: /* LINE SEPARATOR */
+ case 0x2029: /* PARAGRAPH SEPARATOR */
+ break;
+ }
+ }
+ break;
+
case OP_NOT_DIGIT:
for (i = 1; i <= min; i++)
{
}
break;
+ case OP_NOT_HSPACE:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
+ switch(*eptr++)
+ {
+ default: break;
+ case 0x09: /* HT */
+ case 0x20: /* SPACE */
+ case 0xa0: /* NBSP */
+ RRETURN(MATCH_NOMATCH);
+ }
+ }
+ break;
+
+ case OP_HSPACE:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
+ switch(*eptr++)
+ {
+ default: RRETURN(MATCH_NOMATCH);
+ case 0x09: /* HT */
+ case 0x20: /* SPACE */
+ case 0xa0: /* NBSP */
+ break;
+ }
+ }
+ break;
+
+ case OP_NOT_VSPACE:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
+ switch(*eptr++)
+ {
+ default: break;
+ case 0x0a: /* LF */
+ case 0x0b: /* VT */
+ case 0x0c: /* FF */
+ case 0x0d: /* CR */
+ case 0x85: /* NEL */
+ RRETURN(MATCH_NOMATCH);
+ }
+ }
+ break;
+
+ case OP_VSPACE:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
+ switch(*eptr++)
+ {
+ default: RRETURN(MATCH_NOMATCH);
+ case 0x0a: /* LF */
+ case 0x0b: /* VT */
+ case 0x0c: /* FF */
+ case 0x0d: /* CR */
+ case 0x85: /* NEL */
+ break;
+ }
+ }
+ break;
+
case OP_NOT_DIGIT:
for (i = 1; i <= min; i++)
if ((md->ctypes[*eptr++] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH);
case PT_ANY:
for (fi = min;; fi++)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM36);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
GETCHARINC(c, eptr);
case PT_LAMP:
for (fi = min;; fi++)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM37);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
GETCHARINC(c, eptr);
case PT_GC:
for (fi = min;; fi++)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM38);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
GETCHARINC(c, eptr);
case PT_PC:
for (fi = min;; fi++)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM39);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
GETCHARINC(c, eptr);
case PT_SC:
for (fi = min;; fi++)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM40);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
GETCHARINC(c, eptr);
{
for (fi = min;; fi++)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM41);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
GETCHARINCTEST(c, eptr);
{
for (fi = min;; fi++)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM42);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject ||
(ctype == OP_ANY && (ims & PCRE_DOTALL) == 0 &&
}
break;
+ case OP_NOT_HSPACE:
+ switch(c)
+ {
+ default: break;
+ case 0x09: /* HT */
+ case 0x20: /* SPACE */
+ case 0xa0: /* NBSP */
+ case 0x1680: /* OGHAM SPACE MARK */
+ case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */
+ case 0x2000: /* EN QUAD */
+ case 0x2001: /* EM QUAD */
+ case 0x2002: /* EN SPACE */
+ case 0x2003: /* EM SPACE */
+ case 0x2004: /* THREE-PER-EM SPACE */
+ case 0x2005: /* FOUR-PER-EM SPACE */
+ case 0x2006: /* SIX-PER-EM SPACE */
+ case 0x2007: /* FIGURE SPACE */
+ case 0x2008: /* PUNCTUATION SPACE */
+ case 0x2009: /* THIN SPACE */
+ case 0x200A: /* HAIR SPACE */
+ case 0x202f: /* NARROW NO-BREAK SPACE */
+ case 0x205f: /* MEDIUM MATHEMATICAL SPACE */
+ case 0x3000: /* IDEOGRAPHIC SPACE */
+ RRETURN(MATCH_NOMATCH);
+ }
+ break;
+
+ case OP_HSPACE:
+ switch(c)
+ {
+ default: RRETURN(MATCH_NOMATCH);
+ case 0x09: /* HT */
+ case 0x20: /* SPACE */
+ case 0xa0: /* NBSP */
+ case 0x1680: /* OGHAM SPACE MARK */
+ case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */
+ case 0x2000: /* EN QUAD */
+ case 0x2001: /* EM QUAD */
+ case 0x2002: /* EN SPACE */
+ case 0x2003: /* EM SPACE */
+ case 0x2004: /* THREE-PER-EM SPACE */
+ case 0x2005: /* FOUR-PER-EM SPACE */
+ case 0x2006: /* SIX-PER-EM SPACE */
+ case 0x2007: /* FIGURE SPACE */
+ case 0x2008: /* PUNCTUATION SPACE */
+ case 0x2009: /* THIN SPACE */
+ case 0x200A: /* HAIR SPACE */
+ case 0x202f: /* NARROW NO-BREAK SPACE */
+ case 0x205f: /* MEDIUM MATHEMATICAL SPACE */
+ case 0x3000: /* IDEOGRAPHIC SPACE */
+ break;
+ }
+ break;
+
+ case OP_NOT_VSPACE:
+ switch(c)
+ {
+ default: break;
+ case 0x0a: /* LF */
+ case 0x0b: /* VT */
+ case 0x0c: /* FF */
+ case 0x0d: /* CR */
+ case 0x85: /* NEL */
+ case 0x2028: /* LINE SEPARATOR */
+ case 0x2029: /* PARAGRAPH SEPARATOR */
+ RRETURN(MATCH_NOMATCH);
+ }
+ break;
+
+ case OP_VSPACE:
+ switch(c)
+ {
+ default: RRETURN(MATCH_NOMATCH);
+ case 0x0a: /* LF */
+ case 0x0b: /* VT */
+ case 0x0c: /* FF */
+ case 0x0d: /* CR */
+ case 0x85: /* NEL */
+ case 0x2028: /* LINE SEPARATOR */
+ case 0x2029: /* PARAGRAPH SEPARATOR */
+ break;
+ }
+ break;
+
case OP_NOT_DIGIT:
if (c < 256 && (md->ctypes[c] & ctype_digit) != 0)
RRETURN(MATCH_NOMATCH);
{
for (fi = min;; fi++)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM43);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max || eptr >= md->end_subject ||
((ims & PCRE_DOTALL) == 0 && IS_NEWLINE(eptr)))
}
break;
+ case OP_NOT_HSPACE:
+ switch(c)
+ {
+ default: break;
+ case 0x09: /* HT */
+ case 0x20: /* SPACE */
+ case 0xa0: /* NBSP */
+ RRETURN(MATCH_NOMATCH);
+ }
+ break;
+
+ case OP_HSPACE:
+ switch(c)
+ {
+ default: RRETURN(MATCH_NOMATCH);
+ case 0x09: /* HT */
+ case 0x20: /* SPACE */
+ case 0xa0: /* NBSP */
+ break;
+ }
+ break;
+
+ case OP_NOT_VSPACE:
+ switch(c)
+ {
+ default: break;
+ case 0x0a: /* LF */
+ case 0x0b: /* VT */
+ case 0x0c: /* FF */
+ case 0x0d: /* CR */
+ case 0x85: /* NEL */
+ RRETURN(MATCH_NOMATCH);
+ }
+ break;
+
+ case OP_VSPACE:
+ switch(c)
+ {
+ default: RRETURN(MATCH_NOMATCH);
+ case 0x0a: /* LF */
+ case 0x0b: /* VT */
+ case 0x0c: /* FF */
+ case 0x0d: /* CR */
+ case 0x85: /* NEL */
+ break;
+ }
+ break;
+
case OP_NOT_DIGIT:
if ((md->ctypes[c] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH);
break;
if (possessive) continue;
for(;;)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM44);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (eptr-- == pp) break; /* Stop if tried at original pos */
BACKCHAR(eptr);
if (possessive) continue;
for(;;)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM45);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (eptr-- == pp) break; /* Stop if tried at original pos */
for (;;) /* Move back over one extended */
}
break;
+ case OP_NOT_HSPACE:
+ case OP_HSPACE:
+ for (i = min; i < max; i++)
+ {
+ BOOL gotspace;
+ int len = 1;
+ if (eptr >= md->end_subject) break;
+ GETCHARLEN(c, eptr, len);
+ switch(c)
+ {
+ default: gotspace = FALSE; break;
+ case 0x09: /* HT */
+ case 0x20: /* SPACE */
+ case 0xa0: /* NBSP */
+ case 0x1680: /* OGHAM SPACE MARK */
+ case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */
+ case 0x2000: /* EN QUAD */
+ case 0x2001: /* EM QUAD */
+ case 0x2002: /* EN SPACE */
+ case 0x2003: /* EM SPACE */
+ case 0x2004: /* THREE-PER-EM SPACE */
+ case 0x2005: /* FOUR-PER-EM SPACE */
+ case 0x2006: /* SIX-PER-EM SPACE */
+ case 0x2007: /* FIGURE SPACE */
+ case 0x2008: /* PUNCTUATION SPACE */
+ case 0x2009: /* THIN SPACE */
+ case 0x200A: /* HAIR SPACE */
+ case 0x202f: /* NARROW NO-BREAK SPACE */
+ case 0x205f: /* MEDIUM MATHEMATICAL SPACE */
+ case 0x3000: /* IDEOGRAPHIC SPACE */
+ gotspace = TRUE;
+ 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) break;
+ GETCHARLEN(c, eptr, len);
+ switch(c)
+ {
+ default: gotspace = FALSE; break;
+ case 0x0a: /* LF */
+ case 0x0b: /* VT */
+ case 0x0c: /* FF */
+ case 0x0d: /* CR */
+ case 0x85: /* NEL */
+ case 0x2028: /* LINE SEPARATOR */
+ case 0x2029: /* PARAGRAPH SEPARATOR */
+ gotspace = TRUE;
+ break;
+ }
+ if (gotspace == (ctype == OP_NOT_VSPACE)) break;
+ eptr += len;
+ }
+ break;
+
case OP_NOT_DIGIT:
for (i = min; i < max; i++)
{
if (possessive) continue;
for(;;)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM46);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (eptr-- == pp) break; /* Stop if tried at original pos */
BACKCHAR(eptr);
}
break;
+ case OP_NOT_HSPACE:
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject) break;
+ c = *eptr;
+ if (c == 0x09 || c == 0x20 || c == 0xa0) break;
+ eptr++;
+ }
+ break;
+
+ case OP_HSPACE:
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject) break;
+ c = *eptr;
+ if (c != 0x09 && c != 0x20 && c != 0xa0) break;
+ eptr++;
+ }
+ break;
+
+ case OP_NOT_VSPACE:
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject) break;
+ c = *eptr;
+ if (c == 0x0a || c == 0x0b || c == 0x0c || c == 0x0d || c == 0x85)
+ break;
+ eptr++;
+ }
+ break;
+
+ case OP_VSPACE:
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject) break;
+ c = *eptr;
+ if (c != 0x0a && c != 0x0b && c != 0x0c && c != 0x0d && c != 0x85)
+ break;
+ eptr++;
+ }
+ break;
+
case OP_NOT_DIGIT:
for (i = min; i < max; i++)
{
if (possessive) continue;
while (eptr >= pp)
{
- RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0);
+ RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM47);
eptr--;
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
}
} /* End of main loop */
/* Control never reaches here */
+
+
+/* When compiling to use the heap rather than the stack for recursive calls to
+match(), the RRETURN() macro jumps here. The number that is saved in
+frame->Xwhere indicates which label we actually want to return to. */
+
+#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(16)
+ LBL(17) LBL(18) LBL(19) LBL(20) LBL(21) LBL(22) LBL(23) LBL(24)
+ LBL(25) LBL(26) LBL(27) LBL(28) LBL(29) LBL(30) LBL(31) LBL(32)
+ LBL(33) LBL(34) LBL(35) LBL(36) LBL(37) LBL(38) LBL(39) LBL(40)
+ LBL(41) LBL(42) LBL(43) LBL(44) LBL(45) LBL(46) LBL(47)
+ default:
+ DPRINTF(("jump error in pcre match: label %d non-existent\n", frame->Xwhere));
+ return PCRE_ERROR_INTERNAL;
+ }
+#undef LBL
+#endif /* NO_RECURSE */
}
#ifdef NO_RECURSE
#undef eptr
#undef ecode
+#undef mstart
#undef offset_top
#undef ims
#undef eptrb
< -1 => some kind of unexpected problem
*/
-PCRE_DATA_SCOPE int
+PCRE_EXP_DEFN int
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)
md->lcc = tables + lcc_offset;
md->ctypes = tables + ctypes_offset;
-/* Handle different types of newline. The two bits give four cases. If nothing
-is set at run time, whatever was used at compile time applies. */
+/* Handle different types of newline. The three bits give eight cases. If
+nothing is set at run time, whatever was used at compile time applies. */
-switch ((((options & PCRE_NEWLINE_BITS) == 0)? re->options : options) &
+switch ((((options & PCRE_NEWLINE_BITS) == 0)? re->options : (pcre_uint32)options) &
PCRE_NEWLINE_BITS)
{
case 0: newline = NEWLINE; break; /* Compile-time default */
case PCRE_NEWLINE_CR+
PCRE_NEWLINE_LF: newline = ('\r' << 8) | '\n'; break;
case PCRE_NEWLINE_ANY: newline = -1; break;
+ case PCRE_NEWLINE_ANYCRLF: newline = -2; break;
default: return PCRE_ERROR_BADNEWLINE;
}
-if (newline < 0)
+if (newline == -2)
+ {
+ md->nltype = NLTYPE_ANYCRLF;
+ }
+else if (newline < 0)
{
md->nltype = NLTYPE_ANY;
}
{
while (start_match <= end_subject && !WAS_NEWLINE(start_match))
start_match++;
+
+ /* If we have just passed a CR and the newline option is ANY or ANYCRLF,
+ and we are now at a LF, advance the match position by one more character.
+ */
+
+ if (start_match[-1] == '\r' &&
+ (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&
+ start_match < end_subject &&
+ *start_match == '\n')
+ start_match++;
}
}
/* OK, we can now run the match. */
- md->start_match = start_match;
+ md->start_match_ptr = start_match; /* Insurance */
md->match_call_count = 0;
md->eptrn = 0; /* Next free eptrchain slot */
- rc = match(start_match, md->start_code, 2, md, ims, NULL, 0, 0);
+ rc = match(start_match, md->start_code, start_match, 2, md,
+ ims, NULL, 0, 0);
/* Any return other than MATCH_NOMATCH breaks the loop. */
if (anchored || start_match > end_subject) break;
- /* If we have just passed a CR and the newline option is CRLF or ANY, and we
- are now at a LF, advance the match position by one more character. */
+ /* If we have just passed a CR and the newline option is CRLF or ANY or
+ ANYCRLF, and we are now at a LF, advance the match position by one more
+ character. */
if (start_match[-1] == '\r' &&
- (md->nltype == NLTYPE_ANY || md->nllen == 2) &&
+ (md->nltype == NLTYPE_ANY ||
+ md->nltype == NLTYPE_ANYCRLF ||
+ md->nllen == 2) &&
start_match < end_subject &&
*start_match == '\n')
start_match++;
rc = md->offset_overflow? 0 : md->end_offset_top/2;
- /* If there is space, set up the whole thing as substring 0. */
+ /* If there is space, set up the whole thing as substring 0. The value of
+ md->start_match_ptr might be modified if \K was encountered on the success
+ matching path. */
if (offsetcount < 2) rc = 0; else
{
- offsets[0] = start_match - md->start_subject;
+ offsets[0] = md->start_match_ptr - md->start_subject;
offsets[1] = md->end_match_ptr - md->start_subject;
}