Revision: 495
http://www.exim.org/viewvc/pcre2?view=rev&revision=495
Author: ph10
Date: 2016-02-26 18:26:17 +0000 (Fri, 26 Feb 2016)
Log Message:
-----------
Implemented pcre2_code_copy().
Modified Paths:
--------------
code/trunk/ChangeLog
code/trunk/Makefile.am
code/trunk/RunTest
code/trunk/doc/index.html.src
code/trunk/doc/pcre2api.3
code/trunk/doc/pcre2test.1
code/trunk/src/pcre2.h
code/trunk/src/pcre2.h.in
code/trunk/src/pcre2_compile.c
code/trunk/src/pcre2test.c
code/trunk/testdata/testinput17
code/trunk/testdata/testinput20
code/trunk/testdata/testoutput17
code/trunk/testdata/testoutput20
Added Paths:
-----------
code/trunk/doc/pcre2_code_copy.3
Modified: code/trunk/ChangeLog
===================================================================
--- code/trunk/ChangeLog 2016-02-25 17:40:16 UTC (rev 494)
+++ code/trunk/ChangeLog 2016-02-26 18:26:17 UTC (rev 495)
@@ -69,7 +69,10 @@
a report of compiler warnings from Visual Studio 2013 and a few tests with
gcc's -Wconversion (which still throws up a lot).
+15. Implemented pcre2_code_copy(), and added pushcopy and #popcopy to pcre2test
+for testing it.
+
Version 10.21 12-January-2016
-----------------------------
Modified: code/trunk/Makefile.am
===================================================================
--- code/trunk/Makefile.am 2016-02-25 17:40:16 UTC (rev 494)
+++ code/trunk/Makefile.am 2016-02-26 18:26:17 UTC (rev 495)
@@ -25,6 +25,7 @@
doc/html/pcre2-config.html \
doc/html/pcre2.html \
doc/html/pcre2_callout_enumerate.html \
+ doc/html/pcre2_code_copy.html \
doc/html/pcre2_code_free.html \
doc/html/pcre2_compile.html \
doc/html/pcre2_compile_context_copy.html \
@@ -105,6 +106,7 @@
doc/pcre2-config.1 \
doc/pcre2.3 \
doc/pcre2_callout_enumerate.3 \
+ doc/pcre2_code_copy.3 \
doc/pcre2_code_free.3 \
doc/pcre2_compile.3 \
doc/pcre2_compile_context_copy.3 \
Modified: code/trunk/RunTest
===================================================================
--- code/trunk/RunTest 2016-02-25 17:40:16 UTC (rev 494)
+++ code/trunk/RunTest 2016-02-26 18:26:17 UTC (rev 495)
@@ -74,7 +74,7 @@
title17="Test 17: JIT-specific features when JIT is available"
title18="Test 18: Tests of the POSIX interface, excluding UTF/UCP"
title19="Test 19: Tests of the POSIX interface with UTF/UCP"
-title20="Test 20: Serialization tests"
+title20="Test 20: Serialization and code copy tests"
title21="Test 21: \C tests without UTF (supported for DFA matching)"
title22="Test 22: \C tests with UTF (not supported for DFA matching)"
title23="Test 23: \C disabled test"
Modified: code/trunk/doc/index.html.src
===================================================================
--- code/trunk/doc/index.html.src 2016-02-25 17:40:16 UTC (rev 494)
+++ code/trunk/doc/index.html.src 2016-02-26 18:26:17 UTC (rev 495)
@@ -91,6 +91,9 @@
<tr><td><a href="pcre2_callout_enumerate.html">pcre2_callout_enumerate</a></td>
<td> Enumerate callouts in a compiled pattern</td></tr>
+<tr><td><a href="pcre2_code_copy.html">pcre2_code_copy</a></td>
+ <td> Copy a compiled pattern</td></tr>
+
<tr><td><a href="pcre2_code_free.html">pcre2_code_free</a></td>
<td> Free a compiled pattern</td></tr>
Added: code/trunk/doc/pcre2_code_copy.3
===================================================================
--- code/trunk/doc/pcre2_code_copy.3 (rev 0)
+++ code/trunk/doc/pcre2_code_copy.3 2016-02-26 18:26:17 UTC (rev 495)
@@ -0,0 +1,30 @@
+.TH PCRE2_CODE_COPY 3 "26 February 2016" "PCRE2 10.22"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include <pcre2.h>
+.PP
+.nf
+.B pcre2_code *pcre2_code_copy(const pcre2_code *\fIcode\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function makes a copy of the memory used for a compiled pattern, excluding
+any memory used by the JIT compiler. Without a subsequent call to
+\fBpcre2_jit_compile()\fP, the copy can be used only for non-JIT matching. The
+yield of the function is NULL if \fIcode\fP is NULL or if sufficient memory
+cannot be obtained.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
Modified: code/trunk/doc/pcre2api.3
===================================================================
--- code/trunk/doc/pcre2api.3 2016-02-25 17:40:16 UTC (rev 494)
+++ code/trunk/doc/pcre2api.3 2016-02-26 18:26:17 UTC (rev 495)
@@ -1,4 +1,4 @@
-.TH PCRE2API 3 "25 February 2016" "PCRE2 10.22"
+.TH PCRE2API 3 "26 February 2016" "PCRE2 10.22"
.SH NAME
PCRE2 - Perl-compatible regular expressions (revised API)
.sp
@@ -233,6 +233,8 @@
.rs
.sp
.nf
+.B pcre2_code *pcre2_code_copy(const pcre2_code *\fIcode\fP);
+.sp
.B int pcre2_get_error_message(int \fIerrorcode\fP, PCRE2_UCHAR *\fIbuffer\fP,
.B " PCRE2_SIZE \fIbufflen\fP);"
.sp
@@ -506,7 +508,8 @@
(perhaps waiting to see if the pattern is used often enough) similar logic is
required. JIT compilation updates a pointer within the compiled code block, so
a thread must gain unique write access to the pointer before calling
-\fBpcre2_jit_compile()\fP.
+\fBpcre2_jit_compile()\fP. Alternatively, \fBpcre2_code_copy()\fP can be used
+to obtain a private copy of the compiled code.
.
.
.SS "Context blocks"
@@ -1020,15 +1023,34 @@
.B " pcre2_compile_context *\fIccontext\fP);"
.sp
.B void pcre2_code_free(pcre2_code *\fIcode\fP);
+.sp
+.B pcre2_code *pcre2_code_copy(const pcre2_code *\fIcode\fP);
.fi
.P
The \fBpcre2_compile()\fP function compiles a pattern into an internal form.
-The pattern is defined by a pointer to a string of code units and a length, If
+The pattern is defined by a pointer to a string of code units and a length. If
the pattern is zero-terminated, the length can be specified as
PCRE2_ZERO_TERMINATED. The function returns a pointer to a block of memory that
-contains the compiled pattern and related data. The caller must free the memory
-by calling \fBpcre2_code_free()\fP when it is no longer needed.
+contains the compiled pattern and related data.
.P
+If the compile context argument \fIccontext\fP is NULL, memory for the compiled
+pattern is obtained by calling \fBmalloc()\fP. Otherwise, it is obtained from
+the same memory function that was used for the compile context. The caller must
+free the memory by calling \fBpcre2_code_free()\fP when it is no longer needed.
+.P
+The function \fBpcre2_code_copy()\fP makes a copy of the compiled code in new
+memory, using the same memory allocator as was used for the original. However,
+if the code has been processed by the JIT compiler (see
+.\" HTML <a href="#jitcompiling">
+.\" </a>
+below),
+.\"
+the JIT information cannot be copied (because it is position-dependent).
+The new copy can initially be used only for non-JIT matching, though it can be
+passed to \fBpcre2_jit_compile()\fP if required. The \fBpcre2_code_copy()\fP
+function provides a way for individual threads in a multithreaded application
+to acquire a private copy of shared compiled code.
+.P
NOTE: When one of the matching functions is called, pointers to the compiled
pattern and the subject string are set in the match data block so that they can
be referenced by the extraction functions. After running a match, you must not
@@ -1039,15 +1061,12 @@
.\"
have taken place.
.P
-If the compile context argument \fIccontext\fP is NULL, memory for the compiled
-pattern is obtained by calling \fBmalloc()\fP. Otherwise, it is obtained from
-the same memory function that was used for the compile context.
-.P
-The \fIoptions\fP argument contains various bit settings that affect the
-compilation. It should be zero if no options are required. The available
-options are described below. Some of them (in particular, those that are
-compatible with Perl, but some others as well) can also be set and unset from
-within the pattern (see the detailed description in the
+The \fIoptions\fP argument for \fBpcre2_compile()\fP contains various bit
+settings that affect the compilation. It should be zero if no options are
+required. The available options are described below. Some of them (in
+particular, those that are compatible with Perl, but some others as well) can
+also be set and unset from within the pattern (see the detailed description in
+the
.\" HREF
\fBpcre2pattern\fP
.\"
@@ -1470,6 +1489,7 @@
textual error message from any error code.
.
.
+.\" HTML <a name="jitcompiling"></a>
.SH "JUST-IN-TIME (JIT) COMPILATION"
.rs
.sp
@@ -3209,6 +3229,6 @@
.rs
.sp
.nf
-Last updated: 25 February 2016
+Last updated: 26 February 2016
Copyright (c) 1997-2016 University of Cambridge.
.fi
Modified: code/trunk/doc/pcre2test.1
===================================================================
--- code/trunk/doc/pcre2test.1 2016-02-25 17:40:16 UTC (rev 494)
+++ code/trunk/doc/pcre2test.1 2016-02-26 18:26:17 UTC (rev 495)
@@ -1,4 +1,4 @@
-.TH PCRE2TEST 1 "06 February 2016" "PCRE 10.22"
+.TH PCRE2TEST 1 "26 February 2016" "PCRE 10.22"
.SH NAME
pcre2test - a program for testing Perl-compatible regular expressions.
.SH SYNOPSIS
@@ -306,9 +306,10 @@
command helps detect tests that are accidentally put in the wrong file.
.sp
#pop [<modifiers>]
+ #popcopy [<modifiers>]
.sp
-This command is used to manipulate the stack of compiled patterns, as described
-in the section entitled "Saving and restoring compiled patterns"
+These commands are used to manipulate the stack of compiled patterns, as
+described in the section entitled "Saving and restoring compiled patterns"
.\" HTML <a href="#saverestore">
.\" </a>
below.
@@ -537,6 +538,7 @@
posix use the POSIX API
posix_nosub use the POSIX API with REG_NOSUB
push push compiled pattern onto the stack
+ pushcopy push a copy onto the stack
stackguard=<number> test the stackguard feature
tables=[0|1|2] select internal tables
.sp
@@ -895,13 +897,17 @@
section entitled "Saving and restoring compiled patterns"
.\" HTML <a href="#saverestore">
.\" </a>
-below.
+below. If \fBpushcopy\fP is used instead of \fBpush\fP, a copy of the compiled
+pattern is stacked, leaving the original as current, ready to match the
+following input lines. This provides a way of testing the
+\fBpcre2_code_copy()\fP function.
.\"
-The \fBpush\fP modifier is incompatible with compilation modifiers such as
-\fBglobal\fP that act at match time. Any that are specified are ignored, with a
-warning message, except for \fBreplace\fP, which causes an error. Note that,
-\fBjitverify\fP, which is allowed, does not carry through to any subsequent
-matching that uses this pattern.
+The \fBpush\fP and \fBpushcopy \fP modifiers are incompatible with compilation
+modifiers such as \fBglobal\fP that act at match time. Any that are specified
+are ignored (for the stacked copy), with a warning message, except for
+\fBreplace\fP, which causes an error. Note that \fBjitverify\fP, which is
+allowed, does not carry through to any subsequent matching that uses a stacked
+pattern.
.
.
.\" HTML <a name="subjectmodifiers"></a>
@@ -1590,11 +1596,15 @@
.P
When a pattern with \fBpush\fP modifier is successfully compiled, it is pushed
onto a stack of compiled patterns, and \fBpcre2test\fP expects the next line to
-contain a new pattern (or command) instead of a subject line. By this means, a
-number of patterns can be compiled and retained. The \fBpush\fP modifier is
-incompatible with \fBposix\fP, and control modifiers that act at match time are
-ignored (with a message). The \fBjitverify\fP modifier applies only at compile
-time. The command
+contain a new pattern (or command) instead of a subject line. By contrast,
+the \fBpushcopy\fP modifier causes a copy of the compiled pattern to be
+stacked, leaving the original available for immediate matching. By using
+\fBpush\fP and/or \fBpushcopy\fP, a number of patterns can be compiled and
+retained. These modifiers are incompatible with \fBposix\fP, and control
+modifiers that act at match time are ignored (with a message) for the stacked
+patterns. The \fBjitverify\fP modifier applies only at compile time.
+.P
+The command
.sp
#save <filename>
.sp
@@ -1614,7 +1624,8 @@
control modifiers
.\"
that act after a pattern has been compiled. In particular, \fBhex\fP,
-\fBposix\fP, \fBposix_nosub\fP, and \fBpush\fP are not allowed, nor are any
+\fBposix\fP, \fBposix_nosub\fP, \fBpush\fP, and \fBpushcopy\fP are not allowed,
+nor are any
.\" HTML <a href="#optionmodifiers">
.\" </a>
option-setting modifiers.
@@ -1634,6 +1645,10 @@
.sp
If \fBjitverify\fP is used with #pop, it does not automatically imply
\fBjit\fP, which is different behaviour from when it is used on a pattern.
+.P
+The #popcopy command is analagous to the \fBpushcopy\fP modifier in that it
+makes current a copy of the topmost stack pattern, leaving the original still
+on the stack.
.
.
.
Modified: code/trunk/src/pcre2.h
===================================================================
--- code/trunk/src/pcre2.h 2016-02-25 17:40:16 UTC (rev 494)
+++ code/trunk/src/pcre2.h 2016-02-26 18:26:17 UTC (rev 495)
@@ -436,7 +436,9 @@
PCRE2_EXP_DECL \
pcre2_code *pcre2_compile(PCRE2_SPTR, PCRE2_SIZE, uint32_t, \
int *, PCRE2_SIZE *, pcre2_compile_context *); \
-PCRE2_EXP_DECL void pcre2_code_free(pcre2_code *);
+PCRE2_EXP_DECL void pcre2_code_free(pcre2_code *); \
+PCRE2_EXP_DECL \
+ pcre2_code *pcre2_code_copy(const pcre2_code *);
/* Functions that give information about a compiled pattern. */
@@ -585,6 +587,7 @@
/* Functions: the complete list in alphabetical order */
#define pcre2_callout_enumerate PCRE2_SUFFIX(pcre2_callout_enumerate_)
+#define pcre2_code_copy PCRE2_SUFFIX(pcre2_code_copy_)
#define pcre2_code_free PCRE2_SUFFIX(pcre2_code_free_)
#define pcre2_compile PCRE2_SUFFIX(pcre2_compile_)
#define pcre2_compile_context_copy PCRE2_SUFFIX(pcre2_compile_context_copy_)
Modified: code/trunk/src/pcre2.h.in
===================================================================
--- code/trunk/src/pcre2.h.in 2016-02-25 17:40:16 UTC (rev 494)
+++ code/trunk/src/pcre2.h.in 2016-02-26 18:26:17 UTC (rev 495)
@@ -436,7 +436,9 @@
PCRE2_EXP_DECL \
pcre2_code *pcre2_compile(PCRE2_SPTR, PCRE2_SIZE, uint32_t, \
int *, PCRE2_SIZE *, pcre2_compile_context *); \
-PCRE2_EXP_DECL void pcre2_code_free(pcre2_code *);
+PCRE2_EXP_DECL void pcre2_code_free(pcre2_code *); \
+PCRE2_EXP_DECL \
+ pcre2_code *pcre2_code_copy(const pcre2_code *);
/* Functions that give information about a compiled pattern. */
@@ -585,6 +587,7 @@
/* Functions: the complete list in alphabetical order */
#define pcre2_callout_enumerate PCRE2_SUFFIX(pcre2_callout_enumerate_)
+#define pcre2_code_copy PCRE2_SUFFIX(pcre2_code_copy_)
#define pcre2_code_free PCRE2_SUFFIX(pcre2_code_free_)
#define pcre2_compile PCRE2_SUFFIX(pcre2_compile_)
#define pcre2_compile_context_copy PCRE2_SUFFIX(pcre2_compile_context_copy_)
Modified: code/trunk/src/pcre2_compile.c
===================================================================
--- code/trunk/src/pcre2_compile.c 2016-02-25 17:40:16 UTC (rev 494)
+++ code/trunk/src/pcre2_compile.c 2016-02-26 18:26:17 UTC (rev 495)
@@ -730,6 +730,39 @@
/*************************************************
+* Copy compiled code *
+*************************************************/
+
+/* Compiled JIT code cannot be copied, so the new compiled block has no
+associated JIT data. */
+
+PCRE2_EXP_DEFN pcre2_code * PCRE2_CALL_CONVENTION
+pcre2_code_copy(const pcre2_code *code)
+{
+PCRE2_SIZE* ref_count;
+pcre2_code *newcode;
+
+if (code == NULL) return NULL;
+newcode = code->memctl.malloc(code->blocksize, code->memctl.memory_data);
+if (newcode == NULL) return NULL;
+memcpy(newcode, code, code->blocksize);
+newcode->executable_jit = NULL;
+
+/* If the code is one that has been deserialized, increment the reference count
+in the decoded tables. */
+
+if ((code->flags & PCRE2_DEREF_TABLES) != 0)
+ {
+ ref_count = (PCRE2_SIZE *)(code->tables + tables_length);
+ (*ref_count)++;
+ }
+
+return newcode;
+}
+
+
+
+/*************************************************
* Free compiled code *
*************************************************/
Modified: code/trunk/src/pcre2test.c
===================================================================
--- code/trunk/src/pcre2test.c 2016-02-25 17:40:16 UTC (rev 494)
+++ code/trunk/src/pcre2test.c 2016-02-26 18:26:17 UTC (rev 495)
@@ -353,7 +353,7 @@
} cmdstruct;
enum { CMD_FORBID_UTF, CMD_LOAD, CMD_NEWLINE_DEFAULT, CMD_PATTERN,
- CMD_PERLTEST, CMD_POP, CMD_SAVE, CMD_SUBJECT, CMD_UNKNOWN };
+ CMD_PERLTEST, CMD_POP, CMD_POPCOPY, CMD_SAVE, CMD_SUBJECT, CMD_UNKNOWN };
static cmdstruct cmdlist[] = {
{ "forbid_utf", CMD_FORBID_UTF },
@@ -362,6 +362,7 @@
{ "pattern", CMD_PATTERN },
{ "perltest", CMD_PERLTEST },
{ "pop", CMD_POP },
+ { "popcopy", CMD_POPCOPY },
{ "save", CMD_SAVE },
{ "subject", CMD_SUBJECT }};
@@ -427,9 +428,9 @@
#define CTL_POSIX 0x00400000u
#define CTL_POSIX_NOSUB 0x00800000u
#define CTL_PUSH 0x01000000u
-#define CTL_STARTCHAR 0x02000000u
-#define CTL_ZERO_TERMINATE 0x04000000u
-/* Spare 0x08000000u */
+#define CTL_PUSHCOPY 0x02000000u
+#define CTL_STARTCHAR 0x04000000u
+#define CTL_ZERO_TERMINATE 0x08000000u
/* Spare 0x10000000u */
/* Spare 0x20000000u */
#define CTL_NL_SET 0x40000000u /* Informational */
@@ -603,6 +604,7 @@
{ "posix_nosub", MOD_PAT, MOD_CTL, CTL_POSIX|CTL_POSIX_NOSUB, PO(control) },
{ "ps", MOD_DAT, MOD_OPT, PCRE2_PARTIAL_SOFT, DO(options) },
{ "push", MOD_PAT, MOD_CTL, CTL_PUSH, PO(control) },
+ { "pushcopy", MOD_PAT, MOD_CTL, CTL_PUSHCOPY, PO(control) },
{ "recursion_limit", MOD_CTM, MOD_INT, 0, MO(recursion_limit) },
{ "regerror_buffsize", MOD_PAT, MOD_INT, 0, PO(regerror_buffsize) },
{ "replace", MOD_PND, MOD_STR, REPLACE_MODSIZE, PO(replacement) },
@@ -644,7 +646,7 @@
#define PUSH_SUPPORTED_COMPILE_CONTROLS ( \
CTL_BINCODE|CTL_CALLOUT_INFO|CTL_FULLBINCODE|CTL_HEXPAT|CTL_INFO| \
- CTL_JITVERIFY|CTL_MEMORY|CTL_PUSH|CTL_BSR_SET|CTL_NL_SET)
+ CTL_JITVERIFY|CTL_MEMORY|CTL_PUSH|CTL_PUSHCOPY|CTL_BSR_SET|CTL_NL_SET)
#define PUSH_SUPPORTED_COMPILE_CONTROLS2 (0)
@@ -653,9 +655,10 @@
#define PUSH_COMPILE_ONLY_CONTROLS CTL_JITVERIFY
#define PUSH_COMPILE_ONLY_CONTROLS2 (0)
-/* Controls that are forbidden with #pop. */
+/* Controls that are forbidden with #pop or #popcopy. */
-#define NOTPOP_CONTROLS (CTL_HEXPAT|CTL_POSIX|CTL_POSIX_NOSUB|CTL_PUSH)
+#define NOTPOP_CONTROLS (CTL_HEXPAT|CTL_POSIX|CTL_POSIX_NOSUB|CTL_PUSH| \
+ CTL_PUSHCOPY)
/* Pattern controls that are mutually exclusive. At present these are all in
the first control word. Note that CTL_POSIX_NOSUB is always accompanied by
@@ -664,6 +667,7 @@
static uint32_t exclusive_pat_controls[] = {
CTL_POSIX | CTL_HEXPAT,
CTL_POSIX | CTL_PUSH,
+ CTL_POSIX | CTL_PUSHCOPY,
CTL_EXPAND | CTL_HEXPAT };
/* Data controls that are mutually exclusive. At present these are all in the
@@ -945,6 +949,22 @@
a = pcre2_callout_enumerate_32(compiled_code32, \
(int (*)(struct pcre2_callout_enumerate_block_32 *, void *))b,c)
+#define PCRE2_CODE_COPY_FROM_VOID(a,b) \
+ if (test_mode == PCRE8_MODE) \
+ G(a,8) = pcre2_code_copy_8(b); \
+ else if (test_mode == PCRE16_MODE) \
+ G(a,16) = pcre2_code_copy_16(b); \
+ else \
+ G(a,32) = pcre2_code_copy_32(b)
+
+#define PCRE2_CODE_COPY_TO_VOID(a,b) \
+ if (test_mode == PCRE8_MODE) \
+ a = (void *)pcre2_code_copy_8(G(b,8)); \
+ else if (test_mode == PCRE16_MODE) \
+ a = (void *)pcre2_code_copy_16(G(b,16)); \
+ else \
+ a = (void *)pcre2_code_copy_32(G(b,32))
+
#define PCRE2_COMPILE(a,b,c,d,e,f,g) \
if (test_mode == PCRE8_MODE) \
G(a,8) = pcre2_compile_8(G(b,8),c,d,e,f,g); \
@@ -1396,6 +1416,18 @@
a = G(pcre2_callout_enumerate,BITTWO)(G(compiled_code,BITTWO), \
(int (*)(struct G(pcre2_callout_enumerate_block_,BITTWO) *, void *))b,c)
+#define PCRE2_CODE_COPY_FROM_VOID(a,b) \
+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \
+ G(a,BITONE) = G(pcre2_code_copy_,BITONE)(b); \
+ else \
+ G(a,BITTWO) = G(pcre2_code_copy_,BITTWO)(b)
+
+#define PCRE2_CODE_COPY_TO_VOID(a,b) \
+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \
+ a = (void *)G(pcre2_code_copy_,BITONE)(G(b,BITONE)); \
+ else \
+ a = (void *)G(pcre2_code_copy_,BITTWO)(G(b,BITTWO))
+
#define PCRE2_COMPILE(a,b,c,d,e,f,g) \
if (test_mode == G(G(PCRE,BITONE),_MODE)) \
G(a,BITONE) = G(pcre2_compile_,BITONE)(G(b,BITONE),c,d,e,f,g); \
@@ -1731,6 +1763,8 @@
#define PCRE2_CALLOUT_ENUMERATE(a,b,c) \
a = pcre2_callout_enumerate_8(compiled_code8, \
(int (*)(struct pcre2_callout_enumerate_block_8 *, void *))b,c)
+#define PCRE2_CODE_COPY_FROM_VOID(a,b) G(a,8) = pcre2_code_copy_8(b)
+#define PCRE2_CODE_COPY_TO_VOID(a,b) a = (void *)pcre2_code_copy_8(G(b,8))
#define PCRE2_COMPILE(a,b,c,d,e,f,g) \
G(a,8) = pcre2_compile_8(G(b,8),c,d,e,f,g)
#define PCRE2_DFA_MATCH(a,b,c,d,e,f,g,h,i,j) \
@@ -1824,6 +1858,8 @@
#define PCRE2_CALLOUT_ENUMERATE(a,b,c) \
a = pcre2_callout_enumerate_16(compiled_code16, \
(int (*)(struct pcre2_callout_enumerate_block_16 *, void *))b,c)
+#define PCRE2_CODE_COPY_FROM_VOID(a,b) G(a,16) = pcre2_code_copy_16(b)
+#define PCRE2_CODE_COPY_TO_VOID(a,b) a = (void *)pcre2_code_copy_16(G(b,16))
#define PCRE2_COMPILE(a,b,c,d,e,f,g) \
G(a,16) = pcre2_compile_16(G(b,16),c,d,e,f,g)
#define PCRE2_DFA_MATCH(a,b,c,d,e,f,g,h,i,j) \
@@ -1917,6 +1953,8 @@
#define PCRE2_CALLOUT_ENUMERATE(a,b,c) \
a = pcre2_callout_enumerate_32(compiled_code32, \
(int (*)(struct pcre2_callout_enumerate_block_32 *, void *))b,c)
+#define PCRE2_CODE_COPY_FROM_VOID(a,b) G(a,32) = pcre2_code_copy_32(b)
+#define PCRE2_CODE_COPY_TO_VOID(a,b) a = (void *)pcre2_code_copy_32(G(b,32))
#define PCRE2_COMPILE(a,b,c,d,e,f,g) \
G(a,32) = pcre2_compile_32(G(b,32),c,d,e,f,g)
#define PCRE2_DFA_MATCH(a,b,c,d,e,f,g,h,i,j) \
@@ -3584,7 +3622,7 @@
static void
show_controls(uint32_t controls, uint32_t controls2, const char *before)
{
-fprintf(outfile, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+fprintf(outfile, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
before,
((controls & CTL_AFTERTEXT) != 0)? " aftertext" : "",
((controls & CTL_ALLAFTERTEXT) != 0)? " allaftertext" : "",
@@ -3613,6 +3651,7 @@
((controls & CTL_POSIX) != 0)? " posix" : "",
((controls & CTL_POSIX_NOSUB) != 0)? " posix_nosub" : "",
((controls & CTL_PUSH) != 0)? " push" : "",
+ ((controls & CTL_PUSHCOPY) != 0)? " pushcopy" : "",
((controls & CTL_STARTCHAR) != 0)? " startchar" : "",
((controls2 & CTL2_SUBSTITUTE_EXTENDED) != 0)? " substitute_extended" : "",
((controls2 & CTL2_SUBSTITUTE_OVERFLOW_LENGTH) != 0)? " substitute_overflow_length" : "",
@@ -4260,11 +4299,12 @@
local_newline_default = first_listed_newline;
break;
- /* Pop a compiled pattern off the stack. Modifiers that do not affect the
- compiled pattern (e.g. to give information) are permitted. The default
+ /* Pop or copy a compiled pattern off the stack. Modifiers that do not affect
+ the compiled pattern (e.g. to give information) are permitted. The default
pattern modifiers are ignored. */
case CMD_POP:
+ case CMD_POPCOPY:
if (patstacknext <= 0)
{
fprintf(outfile, "** Can't pop off an empty stack\n");
@@ -4273,7 +4313,16 @@
memset(&pat_patctl, 0, sizeof(patctl)); /* Completely unset */
if (!decode_modifiers(argptr, CTX_POPPAT, &pat_patctl, NULL))
return PR_SKIP;
- SET(compiled_code, patstack[--patstacknext]);
+
+ if (cmd == CMD_POP)
+ {
+ SET(compiled_code, patstack[--patstacknext]);
+ }
+ else
+ {
+ PCRE2_CODE_COPY_FROM_VOID(compiled_code, patstack[patstacknext - 1]);
+ }
+
if (pat_patctl.jit != 0)
{
PCRE2_JIT_COMPILE(jitrc, compiled_code, pat_patctl.jit);
@@ -4769,7 +4818,7 @@
/* Handle compiling via the native interface. Controls that act later are
ignored with "push". Replacements are locked out. */
-if ((pat_patctl.control & CTL_PUSH) != 0)
+if ((pat_patctl.control & (CTL_PUSH|CTL_PUSHCOPY)) != 0)
{
if (pat_patctl.replacement[0] != 0)
{
@@ -4972,6 +5021,19 @@
SET(compiled_code, NULL);
}
+/* The "pushcopy" control is similar, but pushes a copy of the pattern. This
+tests the pcre2_code_copy() function. */
+
+if ((pat_patctl.control & CTL_PUSHCOPY) != 0)
+ {
+ if (patstacknext >= PATSTACKSIZE)
+ {
+ fprintf(outfile, "** Too many pushed patterns (max %d)\n", PATSTACKSIZE);
+ return PR_ABEND;
+ }
+ PCRE2_CODE_COPY_TO_VOID(patstack[patstacknext++], compiled_code);
+ }
+
return PR_OK;
}
@@ -5116,10 +5178,10 @@
PCHARS(pre_start, cb->subject, 0, cb->start_match, utf, f);
-/* If a lookbehind is involved, the current position may be earlier than the
+/* If a lookbehind is involved, the current position may be earlier than the
match start. If so, use the match start instead. */
-current_position = (cb->current_position >= cb->start_match)?
+current_position = (cb->current_position >= cb->start_match)?
cb->current_position : cb->start_match;
/* The subject between the match start and the current position. */
@@ -5129,7 +5191,7 @@
/* Print from the current position to the end. */
-PCHARSV(cb->subject, current_position, cb->subject_length - current_position,
+PCHARSV(cb->subject, current_position, cb->subject_length - current_position,
utf, f);
/* Calculate the total subject printed length (no print). */
Modified: code/trunk/testdata/testinput17
===================================================================
--- code/trunk/testdata/testinput17 2016-02-25 17:40:16 UTC (rev 494)
+++ code/trunk/testdata/testinput17 2016-02-26 18:26:17 UTC (rev 495)
@@ -213,6 +213,12 @@
#pop jit,jitverify
abcdef
+/abcd/pushcopy,jitverify
+ abcd
+
+#pop jitverify
+ abcd
+
# Test pattern compilation
/(?:a|b|c|d|e)(?R)/jit=1
Modified: code/trunk/testdata/testinput20
===================================================================
--- code/trunk/testdata/testinput20 2016-02-25 17:40:16 UTC (rev 494)
+++ code/trunk/testdata/testinput20 2016-02-26 18:26:17 UTC (rev 495)
@@ -1,5 +1,5 @@
-# This set of tests exercises the serialization/deserialization functions in
-# the library. It does not use UTF or JIT.
+# This set of tests exercises the serialization/deserialization and code copy
+# functions in the library. It does not use UTF or JIT.
#forbid_utf
@@ -59,5 +59,33 @@
#pop should give an error
pqr
+
+/abcd/pushcopy
+ abcd
+
+#pop
+ abcd
+#pop should give an error
+
+/abcd/push
+#popcopy
+ abcd
+
+#pop
+ abcd
+
+/abcd/push
+#save testsaved1
+#pop should give an error
+
+#load testsaved1
+#popcopy
+ abcd
+
+#pop
+ abcd
+
+#pop should give an error
+
# End of testinput20
Modified: code/trunk/testdata/testoutput17
===================================================================
--- code/trunk/testdata/testoutput17 2016-02-25 17:40:16 UTC (rev 494)
+++ code/trunk/testdata/testoutput17 2016-02-26 18:26:17 UTC (rev 495)
@@ -392,6 +392,15 @@
abcdef
0: def (JIT)
+/abcd/pushcopy,jitverify
+** Applies only to compile when pattern is stacked with 'push': jitverify
+ abcd
+ 0: abcd (JIT)
+
+#pop jitverify
+ abcd
+ 0: abcd
+
# Test pattern compilation
/(?:a|b|c|d|e)(?R)/jit=1
Modified: code/trunk/testdata/testoutput20
===================================================================
--- code/trunk/testdata/testoutput20 2016-02-25 17:40:16 UTC (rev 494)
+++ code/trunk/testdata/testoutput20 2016-02-26 18:26:17 UTC (rev 495)
@@ -1,5 +1,5 @@
-# This set of tests exercises the serialization/deserialization functions in
-# the library. It does not use UTF or JIT.
+# This set of tests exercises the serialization/deserialization and code copy
+# functions in the library. It does not use UTF or JIT.
#forbid_utf
@@ -97,5 +97,42 @@
#pop should give an error
** Can't pop off an empty stack
pqr
+
+/abcd/pushcopy
+ abcd
+ 0: abcd
+
+#pop
+ abcd
+ 0: abcd
+#pop should give an error
+** Can't pop off an empty stack
+
+/abcd/push
+#popcopy
+ abcd
+ 0: abcd
+
+#pop
+ abcd
+ 0: abcd
+
+/abcd/push
+#save testsaved1
+#pop should give an error
+** Can't pop off an empty stack
+
+#load testsaved1
+#popcopy
+ abcd
+ 0: abcd
+
+#pop
+ abcd
+ 0: abcd
+
+#pop should give an error
+** Can't pop off an empty stack
+
# End of testinput20