AMK's latest -- synchronized with PCRE 1.04.

This commit is contained in:
Guido van Rossum 1997-12-22 22:46:52 +00:00
parent 0148bbf966
commit 557dea1ca2
4 changed files with 182 additions and 128 deletions

View file

@ -3,7 +3,7 @@
*************************************************/ *************************************************/
#define PCRE_VERSION "1.02 12-Dec-1997" #define PCRE_VERSION "1.04 22-Dec-1997"
/* This is a library of functions to support regular expressions whose syntax /* This is a library of functions to support regular expressions whose syntax
@ -39,6 +39,7 @@ modules, but which are not relevant to the outside. */
define a macro for memmove() if USE_BCOPY is defined. */ define a macro for memmove() if USE_BCOPY is defined. */
#ifdef USE_BCOPY #ifdef USE_BCOPY
#undef memmove /* some systems may have a macro */
#define memmove(a, b, c) bcopy(b, a, c) #define memmove(a, b, c) bcopy(b, a, c)
#endif #endif
@ -53,6 +54,13 @@ define a macro for memmove() if USE_BCOPY is defined. */
#include <string.h> #include <string.h>
#include "pcre.h" #include "pcre.h"
/* In case there is no definition of offsetof() provided - though any proper
Standard C system should have one. */
#ifndef offsetof
#define offsetof(p_type,field) ((size_t)&(((p_type *)0)->field))
#endif
/* Private options flags start at the most significant end of the two bytes. /* Private options flags start at the most significant end of the two bytes.
The public options defined in pcre.h start at the least significant end. Make The public options defined in pcre.h start at the least significant end. Make
sure they don't overlap! */ sure they don't overlap! */

View file

@ -14,6 +14,7 @@
/* Have to include stdlib.h in order to ensure that size_t is defined; /* Have to include stdlib.h in order to ensure that size_t is defined;
it is needed here for malloc. */ it is needed here for malloc. */
#include <sys/types.h>
#include <stdlib.h> #include <stdlib.h>
/* Options */ /* Options */

View file

@ -231,7 +231,7 @@ PyPcre_compile(self, args)
newpattern[j++]='\0'; newpattern[j++]='\0';
newpattern[j++]='\0'; newpattern[j++]='\0';
newpattern[j++]='\0'; newpattern[j++]='\0';
newpattern[j]='\0'; newpattern[j]='\0';
rv->regex = pcre_compile((char*)newpattern, options, rv->regex = pcre_compile((char*)newpattern, options,
&error, &erroroffset, dictionary); &error, &erroroffset, dictionary);

View file

@ -571,6 +571,15 @@ restrictions:
/* #define DEBUG */ /* #define DEBUG */
/* Use a macro for debugging printing, 'cause that eliminates the the use
of #ifdef inline, and there are *still* stupid compilers about that don't like
indented pre-processor statements. I suppose it's only been 10 years... */
#ifdef DEBUG
#define DPRINTF(p) printf p
#else
#define DPRINTF(p) /*nothing*/
#endif
/* Include the internals header, which itself includes Standard C headers plus /* Include the internals header, which itself includes Standard C headers plus
the external pcre header. */ the external pcre header. */
@ -740,7 +749,8 @@ Arguments:
Returns: nothing Returns: nothing
*/ */
static pchars(uschar *p, int length, BOOL is_subject, match_data *md) static void
pchars(const uschar *p, int length, BOOL is_subject, match_data *md)
{ {
int c; int c;
if (is_subject && length > md->end_subject - p) length = md->end_subject - p; if (is_subject && length > md->end_subject - p) length = md->end_subject - p;
@ -1605,9 +1615,17 @@ for (;; ptr++)
if (code == previous) code += 2; else previous[1]++; if (code == previous) code += 2; else previous[1]++;
} }
/* Insert an UPTO if the max is greater than the min. */ /* If the maximum is unlimited, insert an OP_STAR. */
if (repeat_max != repeat_min) if (repeat_max < 0)
{
*code++ = c;
*code++ = OP_STAR + repeat_type;
}
/* Else insert an UPTO if the max is greater than the min. */
else if (repeat_max != repeat_min)
{ {
*code++ = c; *code++ = c;
repeat_max -= repeat_min; repeat_max -= repeat_min;
@ -1651,7 +1669,7 @@ for (;; ptr++)
else if ((int)*previous >= OP_BRA) else if ((int)*previous >= OP_BRA)
{ {
int i; int i;
int length = code - previous; int len = code - previous;
if (repeat_max == -1 && could_be_empty(previous)) if (repeat_max == -1 && could_be_empty(previous))
{ {
@ -1668,8 +1686,8 @@ for (;; ptr++)
{ {
for (i = 1; i < repeat_min; i++) for (i = 1; i < repeat_min; i++)
{ {
memcpy(code, previous, length); memcpy(code, previous, len);
code += length; code += len;
} }
} }
@ -1681,22 +1699,22 @@ for (;; ptr++)
{ {
if (repeat_min == 0) if (repeat_min == 0)
{ {
memmove(previous+1, previous, length); memmove(previous+1, previous, len);
code++; code++;
*previous++ = OP_BRAZERO + repeat_type; *previous++ = OP_BRAZERO + repeat_type;
} }
for (i = 1; i < repeat_min; i++) for (i = 1; i < repeat_min; i++)
{ {
memcpy(code, previous, length); memcpy(code, previous, len);
code += length; code += len;
} }
for (i = (repeat_min > 0)? repeat_min : 1; i < repeat_max; i++) for (i = (repeat_min > 0)? repeat_min : 1; i < repeat_max; i++)
{ {
*code++ = OP_BRAZERO + repeat_type; *code++ = OP_BRAZERO + repeat_type;
memcpy(code, previous, length); memcpy(code, previous, len);
code += length; code += len;
} }
} }
@ -2240,10 +2258,8 @@ if ((options & ~PUBLIC_OPTIONS) != 0)
return NULL; return NULL;
} }
#ifdef DEBUG DPRINTF(("------------------------------------------------------------------\n"));
printf("------------------------------------------------------------------\n"); DPRINTF(("%s\n", pattern));
printf("%s\n", pattern);
#endif
/* The first thing to do is to make a pass over the pattern to compute the /* The first thing to do is to make a pass over the pattern to compute the
amount of store required to hold the compiled code. This does not have to be amount of store required to hold the compiled code. This does not have to be
@ -2358,9 +2374,9 @@ while ((c = *(++ptr)) != 0)
{ {
if (*ptr == '\\') if (*ptr == '\\')
{ {
int c = check_escape(&ptr, errorptr, bracount, options, TRUE); int ch = check_escape(&ptr, errorptr, bracount, options, TRUE);
if (*errorptr != NULL) goto PCRE_ERROR_RETURN; if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
if (-c == ESC_b) class_charcount++; else class_charcount = 10; if (-ch == ESC_b) class_charcount++; else class_charcount = 10;
} }
else class_charcount++; else class_charcount++;
ptr++; ptr++;
@ -2376,7 +2392,7 @@ while ((c = *(++ptr)) != 0)
/* A repeat needs either 1 or 5 bytes. */ /* A repeat needs either 1 or 5 bytes. */
if (ptr[1] == '{' && is_counted_repeat(ptr+2)) if (*ptr != 0 && ptr[1] == '{' && is_counted_repeat(ptr+2))
{ {
ptr = read_repeat_counts(ptr+2, &min, &max, errorptr); ptr = read_repeat_counts(ptr+2, &min, &max, errorptr);
if (*errorptr != NULL) goto PCRE_ERROR_RETURN; if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
@ -2508,37 +2524,38 @@ while ((c = *(++ptr)) != 0)
continue; continue;
/* Handle ket. Look for subsequent max/min; for certain sets of values we /* Handle ket. Look for subsequent max/min; for certain sets of values we
have to replicate this bracket up to that many times. */ have to replicate this bracket up to that many times. If brastackptr is
0 this is an unmatched bracket which will generate an error, but take care
not to try to access brastack[-1]. */
case ')': case ')':
length += 3; length += 3;
{ {
int min = 1; int minval = 1;
int max = 1; int maxval = 1;
int duplength = length - brastack[--brastackptr]; int duplength = (brastackptr > 0)? length - brastack[--brastackptr] : 0;
/* Leave ptr at the final char; for read_repeat_counts this happens /* Leave ptr at the final char; for read_repeat_counts this happens
automatically; for the others we need an increment. */ automatically; for the others we need an increment. */
if ((c = ptr[1]) == '{' && is_counted_repeat(ptr+2)) if ((c = ptr[1]) == '{' && is_counted_repeat(ptr+2))
{ {
ptr = read_repeat_counts(ptr+2, &min, &max, errorptr); ptr = read_repeat_counts(ptr+2, &minval, &maxval, errorptr);
if (*errorptr != NULL) goto PCRE_ERROR_RETURN; if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
} }
else if (c == '*') { min = 0; max = -1; ptr++; } else if (c == '*') { minval = 0; maxval = -1; ptr++; }
else if (c == '+') { max = -1; ptr++; } else if (c == '+') { maxval = -1; ptr++; }
else if (c == '?') { min = 0; ptr++; } else if (c == '?') { minval = 0; ptr++; }
/* If there is a minimum > 1 we have to replicate up to min-1 times; if /* If there is a minimum > 1 we have to replicate up to minval-1 times;
there is a limited maximum we have to replicate up to max-1 times and if there is a limited maximum we have to replicate up to maxval-1 times
allow for a BRAZERO item before each optional copy, as we also have to and allow for a BRAZERO item before each optional copy, as we also have
do before the first copy if the minimum is zero. */ to do before the first copy if the minimum is zero. */
if (min == 0) length++; if (minval == 0) length++;
else if (min > 1) length += (min - 1) * duplength; else if (minval > 1) length += (minval - 1) * duplength;
if (max > min) length += (max - min) * (duplength + 1); if (maxval > minval) length += (maxval - minval) * (duplength + 1);
} }
continue; continue;
/* Non-special character. For a run of such characters the length required /* Non-special character. For a run of such characters the length required
@ -2599,9 +2616,12 @@ if (length > 65539)
} }
/* Compute the size of data block needed and get it, either from malloc or /* Compute the size of data block needed and get it, either from malloc or
externally provided function. Put in the magic number and the options. */ externally provided function. We specify "code[0]" in the offsetof() expression
rather than just "code", because it has been reported that one broken compiler
fails on "code" because it is also an independent variable. It should make no
difference to the value of the offsetof(). */
size = length + offsetof(real_pcre, code); size = length + offsetof(real_pcre, code[0]);
re = (real_pcre *)(pcre_malloc)(size+50); re = (real_pcre *)(pcre_malloc)(size+50);
if (re == NULL) if (re == NULL)
@ -2610,6 +2630,8 @@ if (re == NULL)
return NULL; return NULL;
} }
/* Put in the magic number and the options. */
re->magic_number = MAGIC_NUMBER; re->magic_number = MAGIC_NUMBER;
re->options = options; re->options = options;
@ -2661,10 +2683,10 @@ if ((options & PCRE_ANCHORED) == 0)
re->options |= PCRE_ANCHORED; re->options |= PCRE_ANCHORED;
else else
{ {
int c = find_firstchar(re->code); int ch = find_firstchar(re->code);
if (c >= 0) if (ch >= 0)
{ {
re->first_char = c; re->first_char = ch;
re->options |= PCRE_FIRSTSET; re->options |= PCRE_FIRSTSET;
} }
else if (is_startline(re->code)) else if (is_startline(re->code))
@ -2756,7 +2778,7 @@ while (code < code_end)
case OP_MINUPTO: case OP_MINUPTO:
if (isprint(c = code[3])) printf(" %c{", c); if (isprint(c = code[3])) printf(" %c{", c);
else printf(" \\x%02x{", c); else printf(" \\x%02x{", c);
if (*code != OP_EXACT) printf(","); if (*code != OP_EXACT) printf("0,");
printf("%d}", (code[1] << 8) + code[2]); printf("%d}", (code[1] << 8) + code[2]);
if (*code == OP_MINUPTO) printf("?"); if (*code == OP_MINUPTO) printf("?");
code += 3; code += 3;
@ -2801,7 +2823,8 @@ while (code < code_end)
case OP_REF: case OP_REF:
printf(" \\%d", *(++code)); printf(" \\%d", *(++code));
break; code ++;
goto CLASS_REF_REPEAT;
case OP_CLASS: case OP_CLASS:
case OP_CLASS_L: case OP_CLASS_L:
@ -2840,6 +2863,8 @@ while (code < code_end)
code += 32; code += 32;
/* code ++;*/ /* code ++;*/
CLASS_REF_REPEAT:
switch(*code) switch(*code)
{ {
case OP_CRSTAR: case OP_CRSTAR:
@ -3071,9 +3096,7 @@ for (;;)
int number = (*ecode - OP_BRA) << 1; int number = (*ecode - OP_BRA) << 1;
int save_offset1 = 0, save_offset2 = 0; int save_offset1 = 0, save_offset2 = 0;
#ifdef DEBUG DPRINTF(("start bracket %d\n", number/2));
printf("start bracket %d\n", number/2);
#endif
if (number > 0 && number < md->offset_end) if (number > 0 && number < md->offset_end)
{ {
@ -3081,9 +3104,7 @@ for (;;)
save_offset2 = md->offset_vector[number+1]; save_offset2 = md->offset_vector[number+1];
md->offset_vector[number] = eptr - md->start_subject; md->offset_vector[number] = eptr - md->start_subject;
#ifdef DEBUG DPRINTF(("saving %d %d\n", save_offset1, save_offset2));
printf("saving %d %d\n", save_offset1, save_offset2);
#endif
} }
/* Recurse for all the alternatives. */ /* Recurse for all the alternatives. */
@ -3095,9 +3116,7 @@ for (;;)
} }
while (*ecode == OP_ALT); while (*ecode == OP_ALT);
#ifdef DEBUG DPRINTF(("bracket %d failed\n", number/2));
printf("bracket %d failed\n", number/2);
#endif
if (number > 0 && number < md->offset_end) if (number > 0 && number < md->offset_end)
{ {
@ -3170,7 +3189,7 @@ for (;;)
ecode += (ecode[1] << 8) + ecode[2]; ecode += (ecode[1] << 8) + ecode[2];
} }
while (*ecode == OP_ALT); while (*ecode == OP_ALT);
if (*ecode == OP_KET) return FALSE; if (*ecode == OP_KET) FAIL;
/* Continue as from after the assertion, updating the offsets high water /* Continue as from after the assertion, updating the offsets high water
mark, since extracts may have been taken. */ mark, since extracts may have been taken. */
@ -3236,9 +3255,7 @@ for (;;)
number = (*prev - OP_BRA) << 1; number = (*prev - OP_BRA) << 1;
#ifdef DEBUG DPRINTF(("end bracket %d\n", number/2));
printf("end bracket %d\n", number/2);
#endif
if (number > 0) if (number > 0)
{ {
@ -3457,14 +3474,14 @@ for (;;)
case OP_NOT_WORDCHAR_L: case OP_NOT_WORDCHAR_L:
if (eptr >= md->end_subject || (*eptr=='_' || isalnum(*eptr) )) if (eptr >= md->end_subject || (*eptr=='_' || isalnum(*eptr) ))
return FALSE; FAIL;
eptr++; eptr++;
ecode++; ecode++;
break; break;
case OP_WORDCHAR_L: case OP_WORDCHAR_L:
if (eptr >= md->end_subject || (*eptr!='_' && !isalnum(*eptr) )) if (eptr >= md->end_subject || (*eptr!='_' && !isalnum(*eptr) ))
return FALSE; FAIL;
eptr++; eptr++;
ecode++; ecode++;
break; break;
@ -3833,7 +3850,7 @@ for (;;)
register int length = ecode[1]; register int length = ecode[1];
ecode += 2; ecode += 2;
#ifdef DEBUG #ifdef DEBUG /* Sigh. Some compilers never learn. */
if (eptr >= md->end_subject) if (eptr >= md->end_subject)
printf("matching subject <null> against pattern "); printf("matching subject <null> against pattern ");
else else
@ -3901,10 +3918,8 @@ for (;;)
maximum. Alternatively, if maximizing, find the maximum number of maximum. Alternatively, if maximizing, find the maximum number of
characters and work backwards. */ characters and work backwards. */
#ifdef DEBUG DPRINTF(("matching %c{%d,%d} against subject %.*s\n", c, min, max,
printf("matching %c{%d,%d} against subject %.*s\n", c, min, max, max, eptr));
max, eptr);
#endif
if (md->caseless) if (md->caseless)
{ {
@ -3969,7 +3984,7 @@ for (;;)
/* Match a negated single character */ /* Match a negated single character */
case OP_NOT: case OP_NOT:
if (eptr > md->end_subject) FAIL; if (eptr >= md->end_subject) FAIL;
ecode++; ecode++;
if (md->caseless) if (md->caseless)
{ {
@ -4028,10 +4043,8 @@ for (;;)
maximum. Alternatively, if maximizing, find the maximum number of maximum. Alternatively, if maximizing, find the maximum number of
characters and work backwards. */ characters and work backwards. */
#ifdef DEBUG DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", c, min, max,
printf("negative matching %c{%d,%d} against subject %.*s\n", c, min, max, max, eptr));
max, eptr);
#endif
if (md->caseless) if (md->caseless)
{ {
@ -4174,12 +4187,12 @@ for (;;)
case OP_NOT_WORDCHAR_L: case OP_NOT_WORDCHAR_L:
for (i = 1; i <= min; i++, eptr++) if (*eptr=='_' || isalnum(*eptr)) for (i = 1; i <= min; i++, eptr++) if (*eptr=='_' || isalnum(*eptr))
return FALSE; FAIL;
break; break;
case OP_WORDCHAR_L: case OP_WORDCHAR_L:
for (i = 1; i <= min; i++, eptr++) if (*eptr!='_' && !isalnum(*eptr)) for (i = 1; i <= min; i++, eptr++) if (*eptr!='_' && !isalnum(*eptr))
return FALSE; FAIL;
break; break;
} }
@ -4308,9 +4321,7 @@ for (;;)
/* There's been some horrible disaster. */ /* There's been some horrible disaster. */
default: default:
#ifdef DEBUG DPRINTF(("Unknown opcode %d\n", *ecode));
printf("Unknown opcode %d\n", *ecode);
#endif
md->errorcode = PCRE_ERROR_UNKNOWN_NODE; md->errorcode = PCRE_ERROR_UNKNOWN_NODE;
FAIL; FAIL;
} }
@ -4354,6 +4365,35 @@ succeed:
/*************************************************
* Segregate setjmp() *
*************************************************/
/* The -Wall option of gcc gives warnings for all local variables when setjmp()
is used, even if the coding conforms to the rules of ANSI C. To avoid this, we
hide it in a separate function. This is called only when PCRE_EXTRA is set,
since it's needed only for the extension \X option, and with any luck, a good
compiler will spot the tail recursion and compile it efficiently.
Arguments:
eptr pointer in subject
ecode position in code
offset_top current top pointer
md pointer to "static" info for the match
Returns: TRUE if matched
*/
static BOOL
match_with_setjmp(const uschar *eptr, const uschar *ecode, int offset_top,
match_data *match_block)
{
return setjmp(match_block->fail_env) == 0 &&
match(eptr, ecode, offset_top, match_block);
}
/************************************************* /*************************************************
* Execute a Regular Expression * * Execute a Regular Expression *
*************************************************/ *************************************************/
@ -4384,17 +4424,17 @@ pcre_exec(const pcre *external_re, const pcre_extra *external_extra,
/* The "volatile" directives are to make gcc -Wall stop complaining /* The "volatile" directives are to make gcc -Wall stop complaining
that these variables can be clobbered by the longjmp. Hopefully that these variables can be clobbered by the longjmp. Hopefully
they won't cost too much performance. */ they won't cost too much performance. */
volatile int resetcount; int resetcount, ocount;
volatile int ocount = offsetcount; int first_char = -1;
volatile int first_char = -1;
match_data match_block; match_data match_block;
volatile const uschar *start_bits = NULL; const uschar *start_bits = NULL;
const uschar *start_match = (uschar *)subject; const uschar *start_match = (const uschar *)subject;
const uschar *end_subject; const uschar *end_subject;
const real_pcre *re = (const real_pcre *)external_re; const real_pcre *re = (const real_pcre *)external_re;
const real_pcre_extra *extra = (const real_pcre_extra *)external_extra; const real_pcre_extra *extra = (const real_pcre_extra *)external_extra;
volatile BOOL anchored = ((re->options | options) & PCRE_ANCHORED) != 0; BOOL using_temporary_offsets = FALSE;
volatile BOOL startline = (re->options & PCRE_STARTLINE) != 0; BOOL anchored = ((re->options | options) & PCRE_ANCHORED) != 0;
BOOL startline = (re->options & PCRE_STARTLINE) != 0;
if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION; if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION;
@ -4427,18 +4467,17 @@ match_block.errorcode = PCRE_ERROR_NOMATCH; /* Default error */
/* If the expression has got more back references than the offsets supplied can /* If the expression has got more back references than the offsets supplied can
hold, we get a temporary bit of working store to use during the matching. hold, we get a temporary bit of working store to use during the matching.
Otherwise, we can use the vector supplied, rounding down the size of it to a Otherwise, we can use the vector supplied, rounding down its size to a multiple
multiple of 2. */ of 2. */
ocount &= (-2); ocount = offsetcount & (-2);
if (re->top_backref > 0 && re->top_backref + 1 >= ocount/2) if (re->top_backref > 0 && re->top_backref >= ocount/2)
{ {
ocount = re->top_backref * 2 + 2; ocount = re->top_backref * 2 + 2;
match_block.offset_vector = (pcre_malloc)(ocount * sizeof(int)); match_block.offset_vector = (pcre_malloc)(ocount * sizeof(int));
if (match_block.offset_vector == NULL) return PCRE_ERROR_NOMEMORY; if (match_block.offset_vector == NULL) return PCRE_ERROR_NOMEMORY;
#ifdef DEBUG using_temporary_offsets = TRUE;
printf("Got memory to hold back references\n"); DPRINTF(("Got memory to hold back references\n"));
#endif
} }
else match_block.offset_vector = offsets; else match_block.offset_vector = offsets;
@ -4459,7 +4498,7 @@ the right check, because multiline is now set. If it now yields FALSE, the
expression must have had ^ starting some of its branches. Check to see if expression must have had ^ starting some of its branches. Check to see if
that is true for *all* branches, and if so, set the startline flag. */ that is true for *all* branches, and if so, set the startline flag. */
if (match_block. multiline && anchored && (re->options & PCRE_MULTILINE) == 0 && if (match_block.multiline && anchored && (re->options & PCRE_MULTILINE) == 0 &&
!is_anchored(re->code, match_block.multiline)) !is_anchored(re->code, match_block.multiline))
{ {
anchored = FALSE; anchored = FALSE;
@ -4491,6 +4530,7 @@ if (!anchored)
do do
{ {
int rc;
register int *iptr = match_block.offset_vector; register int *iptr = match_block.offset_vector;
register int *iend = iptr + resetcount; register int *iend = iptr + resetcount;
@ -4532,7 +4572,7 @@ do
} }
} }
#ifdef DEBUG #ifdef DEBUG /* Sigh. Some compilers never learn. */
printf(">>>> Match against: "); printf(">>>> Match against: ");
pchars(start_match, end_subject - start_match, TRUE, &match_block); pchars(start_match, end_subject - start_match, TRUE, &match_block);
printf("\n"); printf("\n");
@ -4546,7 +4586,10 @@ do
if certain parts of the pattern were not used. if certain parts of the pattern were not used.
Before starting the match, we have to set up a longjmp() target to enable Before starting the match, we have to set up a longjmp() target to enable
the "cut" operation to fail a match completely without backtracking. */ the "cut" operation to fail a match completely without backtracking. This
is done in a separate function to avoid compiler warnings. We need not do
it unless PCRE_EXTRA is set, since only in that case is the "cut" operation
enabled. */
/* To handle errors such as running out of memory for the failure /* To handle errors such as running out of memory for the failure
stack, we need to save this location via setjmp(), so stack, we need to save this location via setjmp(), so
@ -4554,45 +4597,41 @@ do
if (setjmp(match_block.error_env)==0) if (setjmp(match_block.error_env)==0)
{ {
if (setjmp(match_block.fail_env) == 0 && if ((re->options & PCRE_EXTRA) != 0)
match(start_match, re->code, 2, &match_block))
{ {
int rc; if (!match_with_setjmp(start_match, re->code, 2, &match_block))
continue;
if (ocount != offsetcount)
{
if (offsetcount >= 4)
{
memcpy(offsets + 2, match_block.offset_vector + 2,
(offsetcount - 2) * sizeof(int));
#ifdef DEBUG
printf("Copied offsets; freeing temporary memory\n");
#endif
}
if (match_block.end_offset_top > offsetcount)
match_block.offset_overflow = TRUE;
#ifdef DEBUG
printf("Freeing temporary memory\n");
#endif
(pcre_free)(match_block.offset_vector);
}
rc = match_block.offset_overflow? 0 : match_block.end_offset_top/2;
if (match_block.offset_end < 2) rc = 0; else
{
offsets[0] = start_match - match_block.start_subject;
offsets[1] = match_block.end_match_ptr - match_block.start_subject;
}
#ifdef DEBUG
printf(">>>> returning %d\n", rc);
#endif
free_stack(&match_block);
return rc;
} }
else if (!match(start_match, re->code, 2, &match_block)) continue;
/* Copy the offset information from temporary store if necessary */
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 (match_block.offset_end < 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));
free_stack(&match_block);
return rc;
} /* End of (if setjmp(match_block.error_env)...) */ } /* End of (if setjmp(match_block.error_env)...) */
/* Return an error code; pcremodule.c will preserve the exception */ /* Return an error code; pcremodule.c will preserve the exception */
if (PyErr_Occurred()) return PCRE_ERROR_NOMEMORY; if (PyErr_Occurred()) return PCRE_ERROR_NOMEMORY;
@ -4603,11 +4642,17 @@ while (!anchored &&
match_block.errorcode == PCRE_ERROR_NOMATCH && match_block.errorcode == PCRE_ERROR_NOMATCH &&
start_match++ < end_subject); start_match++ < end_subject);
if (using_temporary_offsets)
{
DPRINTF(("Freeing temporary memory\n"));
(pcre_free)(match_block.offset_vector);
}
#ifdef DEBUG #ifdef DEBUG
printf(">>>> returning %d\n", match_block.errorcode); printf(">>>> returning %d\n", match_block.errorcode);
#endif #endif
return match_block.errorcode; return match_block.errorcode;
} }
/* End of pcre.c */ /* End of pcre.c */