Implemented pcre2_code_copy().

This commit is contained in:
Philip.Hazel 2016-02-26 18:26:17 +00:00
parent 6a3b36fa15
commit 96926349bc
15 changed files with 306 additions and 52 deletions

View File

@ -69,6 +69,9 @@ identification.
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
-----------------------------

View File

@ -25,6 +25,7 @@ dist_html_DATA = \
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 @@ dist_man_MANS = \
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 \

View File

@ -74,7 +74,7 @@ title16="Test 16: JIT-specific features when JIT is not available"
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"

View File

@ -91,6 +91,9 @@ in the library.
<tr><td><a href="pcre2_callout_enumerate.html">pcre2_callout_enumerate</a></td>
<td>&nbsp;&nbsp;Enumerate callouts in a compiled pattern</td></tr>
<tr><td><a href="pcre2_code_copy.html">pcre2_code_copy</a></td>
<td>&nbsp;&nbsp;Copy a compiled pattern</td></tr>
<tr><td><a href="pcre2_code_free.html">pcre2_code_free</a></td>
<td>&nbsp;&nbsp;Free a compiled pattern</td></tr>

30
doc/pcre2_code_copy.3 Normal file
View File

@ -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.

View File

@ -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 @@ document for an overview of all the PCRE2 documentation.
.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 @@ If JIT is being used, but the JIT compilation is not being done immediately,
(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,14 +1023,33 @@ zero.
.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
@ -1039,15 +1061,12 @@ match data block
.\"
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 @@ page. The \fBpcre2_get_error_message()\fP function can be called to obtain a
textual error message from any error code.
.
.
.\" HTML <a name="jitcompiling"></a>
.SH "JUST-IN-TIME (JIT) COMPILATION"
.rs
.sp
@ -3209,6 +3229,6 @@ Cambridge, England.
.rs
.sp
.nf
Last updated: 25 February 2016
Last updated: 26 February 2016
Copyright (c) 1997-2016 University of Cambridge.
.fi

View File

@ -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 @@ test files that are also processed by \fBperltest.sh\fP. The \fB#perltest\fP
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 @@ about the pattern:
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 @@ facility is used when saving compiled patterns to a file, as described in the
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 @@ can be used to test these functions.
.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 @@ modifier list containing only
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 @@ reloads two patterns.
.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.
.
.
.

View File

@ -436,7 +436,9 @@ PCRE2_EXP_DECL int pcre2_set_recursion_memory_management( \
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 @@ pcre2_compile are called by application code. */
/* 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_)

View File

@ -436,7 +436,9 @@ PCRE2_EXP_DECL int pcre2_set_recursion_memory_management( \
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 @@ pcre2_compile are called by application code. */
/* 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_)

View File

@ -729,6 +729,39 @@ static const uint8_t opcode_possessify[] = {
/*************************************************
* 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 *
*************************************************/

View File

@ -353,7 +353,7 @@ typedef struct cmdstruct {
} 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 @@ static cmdstruct cmdlist[] = {
{ "pattern", CMD_PATTERN },
{ "perltest", CMD_PERLTEST },
{ "pop", CMD_POP },
{ "popcopy", CMD_POPCOPY },
{ "save", CMD_SAVE },
{ "subject", CMD_SUBJECT }};
@ -427,9 +428,9 @@ so many of them that they are split into two fields. */
#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 @@ static modstruct modlist[] = {
{ "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 @@ static modstruct modlist[] = {
#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 @@ static modstruct modlist[] = {
#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 @@ CTL_POSIX, so it doesn't need its own entries. */
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 @@ are supported. */
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 @@ the three different cases. */
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 @@ the three different cases. */
#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 @@ the three different cases. */
#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 @@ the three different cases. */
#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 @@ Returns: nothing
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 @@ 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
((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 @@ switch(cmd)
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 @@ switch(cmd)
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 @@ if ((pat_patctl.control & CTL_POSIX) != 0)
/* 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 @@ if ((pat_patctl.control & CTL_PUSH) != 0)
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 @@ if (f != NULL) fprintf(f, "--->");
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 @@ PCHARS(post_start, cb->subject, cb->start_match,
/* 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). */

View File

@ -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

32
testdata/testinput20 vendored
View File

@ -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

View File

@ -392,6 +392,15 @@ JIT compilation was successful
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

41
testdata/testoutput20 vendored
View File

@ -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 @@ Serialization failed: error -30: patterns do not all use the same character tabl
#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