summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGustavo Niemeyer <gustavo@niemeyer.net>2003-04-27 14:42:54 (GMT)
committerGustavo Niemeyer <gustavo@niemeyer.net>2003-04-27 14:42:54 (GMT)
commitcaf1c9dfe779c2a07c7d3320a9c53ca6e47c1d1b (patch)
tree86a2462c3e89d748cb4160d4fe489d164ce01390
parent3646ab98af41f37eacf9cdc9d711327956b911f0 (diff)
downloadcpython-caf1c9dfe779c2a07c7d3320a9c53ca6e47c1d1b.zip
cpython-caf1c9dfe779c2a07c7d3320a9c53ca6e47c1d1b.tar.gz
cpython-caf1c9dfe779c2a07c7d3320a9c53ca6e47c1d1b.tar.bz2
- Included detailed documentation in _sre.c explaining how, when, and why
to use LASTMARK_SAVE()/LASTMARK_RESTORE(), based on the discussion in patch #712900. - Cleaned up LASTMARK_SAVE()/LASTMARK_RESTORE() usage, based on the established rules. - Moved the upper part of the just commited patch (relative to bug #725106) to outside the for() loop of BRANCH OP. There's no need to mark_save() in every loop iteration.
-rw-r--r--Modules/_sre.c58
1 files changed, 41 insertions, 17 deletions
diff --git a/Modules/_sre.c b/Modules/_sre.c
index 4f040f1..b50eae3 100644
--- a/Modules/_sre.c
+++ b/Modules/_sre.c
@@ -688,7 +688,34 @@ SRE_INFO(SRE_STATE* state, SRE_CODE* pattern)
}
#endif
-/* macros to preserve lastmark in case of backtracking */
+/* The macros below should be used to protect recursive SRE_MATCH()
+ * calls that *failed* and do *not* return immediately (IOW, those
+ * that will backtrack). Explaining:
+ *
+ * - Recursive SRE_MATCH() returned true: that's usually a success
+ * (besides atypical cases like ASSERT_NOT), therefore there's no
+ * reason to restore lastmark;
+ *
+ * - Recursive SRE_MATCH() returned false but the current SRE_MATCH()
+ * is returning to the caller: If the current SRE_MATCH() is the
+ * top function of the recursion, returning false will be a matching
+ * failure, and it doesn't matter where lastmark is pointing to.
+ * If it's *not* the top function, it will be a recursive SRE_MATCH()
+ * failure by itself, and the calling SRE_MATCH() will have to deal
+ * with the failure by the same rules explained here (it will restore
+ * lastmark by itself if necessary);
+ *
+ * - Recursive SRE_MATCH() returned false, and will continue the
+ * outside 'for' loop: must be protected when breaking, since the next
+ * OP could potentially depend on lastmark;
+ *
+ * - Recursive SRE_MATCH() returned false, and will be called again
+ * inside a local for/while loop: must be protected between each
+ * loop iteration, since the recursive SRE_MATCH() could do anything,
+ * and could potentially depend on lastmark.
+ *
+ * For more information, check the discussion at SF patch #712900.
+ */
#define LASTMARK_SAVE() \
do { \
lastmark = state->lastmark; \
@@ -942,6 +969,11 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
/* <BRANCH> <0=skip> code <JUMP> ... <NULL> */
TRACE(("|%p|%p|BRANCH\n", pattern, ptr));
LASTMARK_SAVE();
+ if (state->repeat) {
+ i = mark_save(state, 0, lastmark, &mark_stack_base);
+ if (i < 0)
+ return i;
+ }
for (; pattern[0]; pattern += pattern[0]) {
if (pattern[1] == SRE_OP_LITERAL &&
(ptr >= end || (SRE_CODE) *ptr != pattern[2]))
@@ -949,11 +981,6 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
if (pattern[1] == SRE_OP_IN &&
(ptr >= end || !SRE_CHARSET(pattern + 3, (SRE_CODE) *ptr)))
continue;
- if (state->repeat) {
- i = mark_save(state, 0, lastmark, &mark_stack_base);
- if (i < 0)
- return i;
- }
state->ptr = ptr;
i = SRE_MATCH(state, pattern + 1, level + 1);
if (i)
@@ -1092,12 +1119,12 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
c = SRE_COUNT(state, pattern+3, 1, level+1);
if (c < 0)
return c;
- LASTMARK_RESTORE();
if (c == 0)
break;
assert(c == 1);
ptr++;
count++;
+ LASTMARK_RESTORE();
}
}
return 0;
@@ -1140,8 +1167,6 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
TRACE(("|%p|%p|MAX_UNTIL %d\n", pattern, ptr, count));
- LASTMARK_SAVE();
-
if (count < rp->pattern[1]) {
/* not enough matches */
rp->count = count;
@@ -1151,7 +1176,6 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
return i;
rp->count = count - 1;
state->ptr = ptr;
- LASTMARK_RESTORE();
return 0;
}
@@ -1159,6 +1183,7 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
/* we may have enough matches, but if we can
match another item, do so */
rp->count = count;
+ LASTMARK_SAVE();
i = mark_save(state, 0, lastmark, &mark_stack_base);
if (i < 0)
return i;
@@ -1167,9 +1192,9 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
if (i)
return i;
i = mark_restore(state, 0, lastmark, &mark_stack_base);
- LASTMARK_RESTORE();
if (i < 0)
return i;
+ LASTMARK_RESTORE();
rp->count = count - 1;
state->ptr = ptr;
}
@@ -1182,7 +1207,6 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
return i;
state->repeat = rp;
state->ptr = ptr;
- LASTMARK_RESTORE();
return 0;
case SRE_OP_MIN_UNTIL:
@@ -1200,8 +1224,6 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
TRACE(("|%p|%p|MIN_UNTIL %d %p\n", pattern, ptr, count,
rp->pattern));
- LASTMARK_SAVE();
-
if (count < rp->pattern[1]) {
/* not enough matches */
rp->count = count;
@@ -1211,10 +1233,11 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
return i;
rp->count = count-1;
state->ptr = ptr;
- LASTMARK_RESTORE();
return 0;
}
+ LASTMARK_SAVE();
+
/* see if the tail matches */
state->repeat = rp->prev;
i = SRE_MATCH(state, pattern, level + 1);
@@ -1224,10 +1247,11 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
state->ptr = ptr;
state->repeat = rp;
- LASTMARK_RESTORE();
if (count >= rp->pattern[2] && rp->pattern[2] != 65535)
return 0;
+ LASTMARK_RESTORE();
+
rp->count = count;
/* RECURSIVE */
i = SRE_MATCH(state, rp->pattern + 3, level + 1);
@@ -1235,7 +1259,7 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
return i;
rp->count = count - 1;
state->ptr = ptr;
- LASTMARK_RESTORE();
+
return 0;
default: