summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>2010-10-10 17:33:07 +0000
committerph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>2010-10-10 17:33:07 +0000
commite5f5a0846fd1a4c912d3aa6c505a0bde13c40944 (patch)
treed9af1bbab36170e18d2fe85aa3941b7f81cd8f67
parenta0ab6e7fdaff6d0b459689f4bc5c79792cfd85cd (diff)
downloadpcre-e5f5a0846fd1a4c912d3aa6c505a0bde13c40944.tar.gz
Make (*COMMIT) override (*THEN) and similar.
git-svn-id: svn://vcs.exim.org/pcre/code/trunk@551 2f5784b3-3f2a-0410-8824-cb99058d5e15
-rw-r--r--ChangeLog6
-rw-r--r--doc/pcrepattern.318
-rw-r--r--pcre_exec.c21
-rw-r--r--testdata/testinput1111
-rw-r--r--testdata/testoutput1114
5 files changed, 65 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index 9986cfa..73f0db5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -10,6 +10,12 @@ Version 8.11 10-Oct-2010
at the same level (in this case, to look for "c"). The Perl documentation
is clear that when (*THEN) is backtracked onto, it goes to the "next
alternative in the innermost enclosing group".
+
+2. (*COMMIT) was not overriding (*THEN), as it does in Perl. In a pattern
+ such as (A(*COMMIT)B(*THEN)C|D) any failure after matching A should
+ result in overall failure. Similarly, (*COMMIT) now overrides (*PRUNE) and
+ (*SKIP), (*SKIP) overrides (*PRUNE) and (*THEN), and (*PRUNE) overrides
+ (*THEN).
Version 8.10 25-Jun-2010
diff --git a/doc/pcrepattern.3 b/doc/pcrepattern.3
index 63f3df8..04b4afd 100644
--- a/doc/pcrepattern.3
+++ b/doc/pcrepattern.3
@@ -2644,6 +2644,24 @@ behaviour of (*THEN:NAME) is exactly the same as (*MARK:NAME)(*THEN) if the
overall match fails. If (*THEN) is not directly inside an alternation, it acts
like (*PRUNE).
.
+.P
+The above verbs provide four different "strengths" of control when subsequent
+matching fails. (*THEN) is the weakest, carrying on the match at the next
+alternation. (*PRUNE) comes next, failing the match at the current starting
+position, but allowing an advance to the next character (for an unanchored
+pattern). (*SKIP) is similar, except that the advance may be more than one
+character. (*COMMIT) is the strongest, causing the entire match to fail.
+.P
+If more than one is present in a pattern, the "stongest" one wins. For example,
+consider this pattern, where A, B, etc. are complex pattern fragments:
+.sp
+ (A(*COMMIT)B(*THEN)C|D)
+.sp
+Once A has matched, PCRE is committed to this match, at the current starting
+position. If subsequently B matches, but C does not, the normal (*THEN) action
+of trying the next alternation (that is, D) does not happen because (*COMMIT)
+overrides.
+.
.
.SH "SEE ALSO"
.rs
diff --git a/pcre_exec.c b/pcre_exec.c
index 32f8c5a..1eeea52 100644
--- a/pcre_exec.c
+++ b/pcre_exec.c
@@ -710,36 +710,47 @@ for (;;)
case OP_FAIL:
MRRETURN(MATCH_NOMATCH);
+ /* COMMIT overrides PRUNE, SKIP, and THEN */
+
case OP_COMMIT:
RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
ims, eptrb, flags, RM52);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE &&
+ rrc != MATCH_SKIP && rrc != MATCH_SKIP_ARG &&
+ rrc != MATCH_THEN)
+ RRETURN(rrc);
MRRETURN(MATCH_COMMIT);
+ /* PRUNE overrides THEN */
+
case OP_PRUNE:
RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
ims, eptrb, flags, RM51);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);
MRRETURN(MATCH_PRUNE);
case OP_PRUNE_ARG:
RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode] + ecode[1], offset_top, md,
ims, eptrb, flags, RM56);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);
md->mark = ecode + 2;
RRETURN(MATCH_PRUNE);
+ /* SKIP overrides PRUNE and THEN */
+
case OP_SKIP:
RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
ims, eptrb, flags, RM53);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE && rrc != MATCH_THEN)
+ RRETURN(rrc);
md->start_match_ptr = eptr; /* Pass back current position */
MRRETURN(MATCH_SKIP);
case OP_SKIP_ARG:
RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode] + ecode[1], offset_top, md,
ims, eptrb, flags, RM57);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE && rrc != MATCH_THEN)
+ RRETURN(rrc);
/* Pass back the current skip name by overloading md->start_match_ptr and
returning the special MATCH_SKIP_ARG return code. This will either be
diff --git a/testdata/testinput11 b/testdata/testinput11
index 795e1be..5509b52 100644
--- a/testdata/testinput11
+++ b/testdata/testinput11
@@ -483,4 +483,15 @@ however, we need the complication for Perl. ---/
/(?&t)(?#()(?(DEFINE)(?<t>a))/
bac
+/--- COMMIT should override THEN ---/
+
+/(?>(*COMMIT)(?>yes|no)(*THEN)(*F))?/
+ yes
+
+/(?>(*COMMIT)(yes|no)(*THEN)(*F))?/
+ yes
+
+/^((yes|no)(*THEN)(*F))?/
+ yes
+
/-- End of testinput11 --/
diff --git a/testdata/testoutput11 b/testdata/testoutput11
index 6270d5b..0c56c66 100644
--- a/testdata/testoutput11
+++ b/testdata/testoutput11
@@ -942,4 +942,18 @@ No match
bac
0: a
+/--- COMMIT should override THEN ---/
+
+/(?>(*COMMIT)(?>yes|no)(*THEN)(*F))?/
+ yes
+No match
+
+/(?>(*COMMIT)(yes|no)(*THEN)(*F))?/
+ yes
+No match
+
+/^((yes|no)(*THEN)(*F))?/
+ yes
+ 0:
+
/-- End of testinput11 --/