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 a report of compiler warnings from Visual Studio 2013 and a few tests with
gcc's -Wconversion (which still throws up a lot). 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 Version 10.21 12-January-2016
----------------------------- -----------------------------

View File

@ -25,6 +25,7 @@ dist_html_DATA = \
doc/html/pcre2-config.html \ doc/html/pcre2-config.html \
doc/html/pcre2.html \ doc/html/pcre2.html \
doc/html/pcre2_callout_enumerate.html \ doc/html/pcre2_callout_enumerate.html \
doc/html/pcre2_code_copy.html \
doc/html/pcre2_code_free.html \ doc/html/pcre2_code_free.html \
doc/html/pcre2_compile.html \ doc/html/pcre2_compile.html \
doc/html/pcre2_compile_context_copy.html \ doc/html/pcre2_compile_context_copy.html \
@ -105,6 +106,7 @@ dist_man_MANS = \
doc/pcre2-config.1 \ doc/pcre2-config.1 \
doc/pcre2.3 \ doc/pcre2.3 \
doc/pcre2_callout_enumerate.3 \ doc/pcre2_callout_enumerate.3 \
doc/pcre2_code_copy.3 \
doc/pcre2_code_free.3 \ doc/pcre2_code_free.3 \
doc/pcre2_compile.3 \ doc/pcre2_compile.3 \
doc/pcre2_compile_context_copy.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" title17="Test 17: JIT-specific features when JIT is available"
title18="Test 18: Tests of the POSIX interface, excluding UTF/UCP" title18="Test 18: Tests of the POSIX interface, excluding UTF/UCP"
title19="Test 19: Tests of the POSIX interface with 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)" title21="Test 21: \C tests without UTF (supported for DFA matching)"
title22="Test 22: \C tests with UTF (not supported for DFA matching)" title22="Test 22: \C tests with UTF (not supported for DFA matching)"
title23="Test 23: \C disabled test" 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> <tr><td><a href="pcre2_callout_enumerate.html">pcre2_callout_enumerate</a></td>
<td>&nbsp;&nbsp;Enumerate callouts in a compiled pattern</td></tr> <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> <tr><td><a href="pcre2_code_free.html">pcre2_code_free</a></td>
<td>&nbsp;&nbsp;Free a compiled pattern</td></tr> <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 .SH NAME
PCRE2 - Perl-compatible regular expressions (revised API) PCRE2 - Perl-compatible regular expressions (revised API)
.sp .sp
@ -233,6 +233,8 @@ document for an overview of all the PCRE2 documentation.
.rs .rs
.sp .sp
.nf .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 int pcre2_get_error_message(int \fIerrorcode\fP, PCRE2_UCHAR *\fIbuffer\fP,
.B " PCRE2_SIZE \fIbufflen\fP);" .B " PCRE2_SIZE \fIbufflen\fP);"
.sp .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 (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 required. JIT compilation updates a pointer within the compiled code block, so
a thread must gain unique write access to the pointer before calling 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" .SS "Context blocks"
@ -1020,14 +1023,33 @@ zero.
.B " pcre2_compile_context *\fIccontext\fP);" .B " pcre2_compile_context *\fIccontext\fP);"
.sp .sp
.B void pcre2_code_free(pcre2_code *\fIcode\fP); .B void pcre2_code_free(pcre2_code *\fIcode\fP);
.sp
.B pcre2_code *pcre2_code_copy(const pcre2_code *\fIcode\fP);
.fi .fi
.P .P
The \fBpcre2_compile()\fP function compiles a pattern into an internal form. 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 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 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 contains the compiled pattern and related data.
by calling \fBpcre2_code_free()\fP when it is no longer needed. .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 .P
NOTE: When one of the matching functions is called, pointers to the compiled 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 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. have taken place.
.P .P
If the compile context argument \fIccontext\fP is NULL, memory for the compiled The \fIoptions\fP argument for \fBpcre2_compile()\fP contains various bit
pattern is obtained by calling \fBmalloc()\fP. Otherwise, it is obtained from settings that affect the compilation. It should be zero if no options are
the same memory function that was used for the compile context. required. The available options are described below. Some of them (in
.P particular, those that are compatible with Perl, but some others as well) can
The \fIoptions\fP argument contains various bit settings that affect the also be set and unset from within the pattern (see the detailed description in
compilation. It should be zero if no options are required. The available the
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 .\" HREF
\fBpcre2pattern\fP \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. textual error message from any error code.
. .
. .
.\" HTML <a name="jitcompiling"></a>
.SH "JUST-IN-TIME (JIT) COMPILATION" .SH "JUST-IN-TIME (JIT) COMPILATION"
.rs .rs
.sp .sp
@ -3209,6 +3229,6 @@ Cambridge, England.
.rs .rs
.sp .sp
.nf .nf
Last updated: 25 February 2016 Last updated: 26 February 2016
Copyright (c) 1997-2016 University of Cambridge. Copyright (c) 1997-2016 University of Cambridge.
.fi .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 .SH NAME
pcre2test - a program for testing Perl-compatible regular expressions. pcre2test - a program for testing Perl-compatible regular expressions.
.SH SYNOPSIS .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. command helps detect tests that are accidentally put in the wrong file.
.sp .sp
#pop [<modifiers>] #pop [<modifiers>]
#popcopy [<modifiers>]
.sp .sp
This command is used to manipulate the stack of compiled patterns, as described These commands are used to manipulate the stack of compiled patterns, as
in the section entitled "Saving and restoring compiled patterns" described in the section entitled "Saving and restoring compiled patterns"
.\" HTML <a href="#saverestore"> .\" HTML <a href="#saverestore">
.\" </a> .\" </a>
below. below.
@ -537,6 +538,7 @@ about the pattern:
posix use the POSIX API posix use the POSIX API
posix_nosub use the POSIX API with REG_NOSUB posix_nosub use the POSIX API with REG_NOSUB
push push compiled pattern onto the stack push push compiled pattern onto the stack
pushcopy push a copy onto the stack
stackguard=<number> test the stackguard feature stackguard=<number> test the stackguard feature
tables=[0|1|2] select internal tables tables=[0|1|2] select internal tables
.sp .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" section entitled "Saving and restoring compiled patterns"
.\" HTML <a href="#saverestore"> .\" HTML <a href="#saverestore">
.\" </a> .\" </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 The \fBpush\fP and \fBpushcopy \fP modifiers are incompatible with compilation
\fBglobal\fP that act at match time. Any that are specified are ignored, with a modifiers such as \fBglobal\fP that act at match time. Any that are specified
warning message, except for \fBreplace\fP, which causes an error. Note that, are ignored (for the stacked copy), with a warning message, except for
\fBjitverify\fP, which is allowed, does not carry through to any subsequent \fBreplace\fP, which causes an error. Note that \fBjitverify\fP, which is
matching that uses this pattern. allowed, does not carry through to any subsequent matching that uses a stacked
pattern.
. .
. .
.\" HTML <a name="subjectmodifiers"></a> .\" HTML <a name="subjectmodifiers"></a>
@ -1590,11 +1596,15 @@ can be used to test these functions.
.P .P
When a pattern with \fBpush\fP modifier is successfully compiled, it is pushed 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 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 contain a new pattern (or command) instead of a subject line. By contrast,
number of patterns can be compiled and retained. The \fBpush\fP modifier is the \fBpushcopy\fP modifier causes a copy of the compiled pattern to be
incompatible with \fBposix\fP, and control modifiers that act at match time are stacked, leaving the original available for immediate matching. By using
ignored (with a message). The \fBjitverify\fP modifier applies only at compile \fBpush\fP and/or \fBpushcopy\fP, a number of patterns can be compiled and
time. The command 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 .sp
#save <filename> #save <filename>
.sp .sp
@ -1614,7 +1624,8 @@ modifier list containing only
control modifiers control modifiers
.\" .\"
that act after a pattern has been compiled. In particular, \fBhex\fP, 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"> .\" HTML <a href="#optionmodifiers">
.\" </a> .\" </a>
option-setting modifiers. option-setting modifiers.
@ -1634,6 +1645,10 @@ reloads two patterns.
.sp .sp
If \fBjitverify\fP is used with #pop, it does not automatically imply 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. \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_EXP_DECL \
pcre2_code *pcre2_compile(PCRE2_SPTR, PCRE2_SIZE, uint32_t, \ pcre2_code *pcre2_compile(PCRE2_SPTR, PCRE2_SIZE, uint32_t, \
int *, PCRE2_SIZE *, pcre2_compile_context *); \ 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. */ /* 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 */ /* Functions: the complete list in alphabetical order */
#define pcre2_callout_enumerate PCRE2_SUFFIX(pcre2_callout_enumerate_) #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_code_free PCRE2_SUFFIX(pcre2_code_free_)
#define pcre2_compile PCRE2_SUFFIX(pcre2_compile_) #define pcre2_compile PCRE2_SUFFIX(pcre2_compile_)
#define pcre2_compile_context_copy PCRE2_SUFFIX(pcre2_compile_context_copy_) #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_EXP_DECL \
pcre2_code *pcre2_compile(PCRE2_SPTR, PCRE2_SIZE, uint32_t, \ pcre2_code *pcre2_compile(PCRE2_SPTR, PCRE2_SIZE, uint32_t, \
int *, PCRE2_SIZE *, pcre2_compile_context *); \ 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. */ /* 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 */ /* Functions: the complete list in alphabetical order */
#define pcre2_callout_enumerate PCRE2_SUFFIX(pcre2_callout_enumerate_) #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_code_free PCRE2_SUFFIX(pcre2_code_free_)
#define pcre2_compile PCRE2_SUFFIX(pcre2_compile_) #define pcre2_compile PCRE2_SUFFIX(pcre2_compile_)
#define pcre2_compile_context_copy PCRE2_SUFFIX(pcre2_compile_context_copy_) #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 * * Free compiled code *
*************************************************/ *************************************************/

View File

@ -353,7 +353,7 @@ typedef struct cmdstruct {
} cmdstruct; } cmdstruct;
enum { CMD_FORBID_UTF, CMD_LOAD, CMD_NEWLINE_DEFAULT, CMD_PATTERN, 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[] = { static cmdstruct cmdlist[] = {
{ "forbid_utf", CMD_FORBID_UTF }, { "forbid_utf", CMD_FORBID_UTF },
@ -362,6 +362,7 @@ static cmdstruct cmdlist[] = {
{ "pattern", CMD_PATTERN }, { "pattern", CMD_PATTERN },
{ "perltest", CMD_PERLTEST }, { "perltest", CMD_PERLTEST },
{ "pop", CMD_POP }, { "pop", CMD_POP },
{ "popcopy", CMD_POPCOPY },
{ "save", CMD_SAVE }, { "save", CMD_SAVE },
{ "subject", CMD_SUBJECT }}; { "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 0x00400000u
#define CTL_POSIX_NOSUB 0x00800000u #define CTL_POSIX_NOSUB 0x00800000u
#define CTL_PUSH 0x01000000u #define CTL_PUSH 0x01000000u
#define CTL_STARTCHAR 0x02000000u #define CTL_PUSHCOPY 0x02000000u
#define CTL_ZERO_TERMINATE 0x04000000u #define CTL_STARTCHAR 0x04000000u
/* Spare 0x08000000u */ #define CTL_ZERO_TERMINATE 0x08000000u
/* Spare 0x10000000u */ /* Spare 0x10000000u */
/* Spare 0x20000000u */ /* Spare 0x20000000u */
#define CTL_NL_SET 0x40000000u /* Informational */ #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) }, { "posix_nosub", MOD_PAT, MOD_CTL, CTL_POSIX|CTL_POSIX_NOSUB, PO(control) },
{ "ps", MOD_DAT, MOD_OPT, PCRE2_PARTIAL_SOFT, DO(options) }, { "ps", MOD_DAT, MOD_OPT, PCRE2_PARTIAL_SOFT, DO(options) },
{ "push", MOD_PAT, MOD_CTL, CTL_PUSH, PO(control) }, { "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) }, { "recursion_limit", MOD_CTM, MOD_INT, 0, MO(recursion_limit) },
{ "regerror_buffsize", MOD_PAT, MOD_INT, 0, PO(regerror_buffsize) }, { "regerror_buffsize", MOD_PAT, MOD_INT, 0, PO(regerror_buffsize) },
{ "replace", MOD_PND, MOD_STR, REPLACE_MODSIZE, PO(replacement) }, { "replace", MOD_PND, MOD_STR, REPLACE_MODSIZE, PO(replacement) },
@ -644,7 +646,7 @@ static modstruct modlist[] = {
#define PUSH_SUPPORTED_COMPILE_CONTROLS ( \ #define PUSH_SUPPORTED_COMPILE_CONTROLS ( \
CTL_BINCODE|CTL_CALLOUT_INFO|CTL_FULLBINCODE|CTL_HEXPAT|CTL_INFO| \ 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) #define PUSH_SUPPORTED_COMPILE_CONTROLS2 (0)
@ -653,9 +655,10 @@ static modstruct modlist[] = {
#define PUSH_COMPILE_ONLY_CONTROLS CTL_JITVERIFY #define PUSH_COMPILE_ONLY_CONTROLS CTL_JITVERIFY
#define PUSH_COMPILE_ONLY_CONTROLS2 (0) #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 /* 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 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[] = { static uint32_t exclusive_pat_controls[] = {
CTL_POSIX | CTL_HEXPAT, CTL_POSIX | CTL_HEXPAT,
CTL_POSIX | CTL_PUSH, CTL_POSIX | CTL_PUSH,
CTL_POSIX | CTL_PUSHCOPY,
CTL_EXPAND | CTL_HEXPAT }; CTL_EXPAND | CTL_HEXPAT };
/* Data controls that are mutually exclusive. At present these are all in the /* 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, \ a = pcre2_callout_enumerate_32(compiled_code32, \
(int (*)(struct pcre2_callout_enumerate_block_32 *, void *))b,c) (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) \ #define PCRE2_COMPILE(a,b,c,d,e,f,g) \
if (test_mode == PCRE8_MODE) \ if (test_mode == PCRE8_MODE) \
G(a,8) = pcre2_compile_8(G(b,8),c,d,e,f,g); \ 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), \ a = G(pcre2_callout_enumerate,BITTWO)(G(compiled_code,BITTWO), \
(int (*)(struct G(pcre2_callout_enumerate_block_,BITTWO) *, void *))b,c) (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) \ #define PCRE2_COMPILE(a,b,c,d,e,f,g) \
if (test_mode == G(G(PCRE,BITONE),_MODE)) \ if (test_mode == G(G(PCRE,BITONE),_MODE)) \
G(a,BITONE) = G(pcre2_compile_,BITONE)(G(b,BITONE),c,d,e,f,g); \ 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) \ #define PCRE2_CALLOUT_ENUMERATE(a,b,c) \
a = pcre2_callout_enumerate_8(compiled_code8, \ a = pcre2_callout_enumerate_8(compiled_code8, \
(int (*)(struct pcre2_callout_enumerate_block_8 *, void *))b,c) (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) \ #define PCRE2_COMPILE(a,b,c,d,e,f,g) \
G(a,8) = pcre2_compile_8(G(b,8),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) \ #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) \ #define PCRE2_CALLOUT_ENUMERATE(a,b,c) \
a = pcre2_callout_enumerate_16(compiled_code16, \ a = pcre2_callout_enumerate_16(compiled_code16, \
(int (*)(struct pcre2_callout_enumerate_block_16 *, void *))b,c) (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) \ #define PCRE2_COMPILE(a,b,c,d,e,f,g) \
G(a,16) = pcre2_compile_16(G(b,16),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) \ #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) \ #define PCRE2_CALLOUT_ENUMERATE(a,b,c) \
a = pcre2_callout_enumerate_32(compiled_code32, \ a = pcre2_callout_enumerate_32(compiled_code32, \
(int (*)(struct pcre2_callout_enumerate_block_32 *, void *))b,c) (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) \ #define PCRE2_COMPILE(a,b,c,d,e,f,g) \
G(a,32) = pcre2_compile_32(G(b,32),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) \ #define PCRE2_DFA_MATCH(a,b,c,d,e,f,g,h,i,j) \
@ -3584,7 +3622,7 @@ Returns: nothing
static void static void
show_controls(uint32_t controls, uint32_t controls2, const char *before) 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, before,
((controls & CTL_AFTERTEXT) != 0)? " aftertext" : "", ((controls & CTL_AFTERTEXT) != 0)? " aftertext" : "",
((controls & CTL_ALLAFTERTEXT) != 0)? " allaftertext" : "", ((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) != 0)? " posix" : "",
((controls & CTL_POSIX_NOSUB) != 0)? " posix_nosub" : "", ((controls & CTL_POSIX_NOSUB) != 0)? " posix_nosub" : "",
((controls & CTL_PUSH) != 0)? " push" : "", ((controls & CTL_PUSH) != 0)? " push" : "",
((controls & CTL_PUSHCOPY) != 0)? " pushcopy" : "",
((controls & CTL_STARTCHAR) != 0)? " startchar" : "", ((controls & CTL_STARTCHAR) != 0)? " startchar" : "",
((controls2 & CTL2_SUBSTITUTE_EXTENDED) != 0)? " substitute_extended" : "", ((controls2 & CTL2_SUBSTITUTE_EXTENDED) != 0)? " substitute_extended" : "",
((controls2 & CTL2_SUBSTITUTE_OVERFLOW_LENGTH) != 0)? " substitute_overflow_length" : "", ((controls2 & CTL2_SUBSTITUTE_OVERFLOW_LENGTH) != 0)? " substitute_overflow_length" : "",
@ -4260,11 +4299,12 @@ switch(cmd)
local_newline_default = first_listed_newline; local_newline_default = first_listed_newline;
break; break;
/* Pop a compiled pattern off the stack. Modifiers that do not affect the /* Pop or copy a compiled pattern off the stack. Modifiers that do not affect
compiled pattern (e.g. to give information) are permitted. The default the compiled pattern (e.g. to give information) are permitted. The default
pattern modifiers are ignored. */ pattern modifiers are ignored. */
case CMD_POP: case CMD_POP:
case CMD_POPCOPY:
if (patstacknext <= 0) if (patstacknext <= 0)
{ {
fprintf(outfile, "** Can't pop off an empty stack\n"); fprintf(outfile, "** Can't pop off an empty stack\n");
@ -4273,7 +4313,16 @@ switch(cmd)
memset(&pat_patctl, 0, sizeof(patctl)); /* Completely unset */ memset(&pat_patctl, 0, sizeof(patctl)); /* Completely unset */
if (!decode_modifiers(argptr, CTX_POPPAT, &pat_patctl, NULL)) if (!decode_modifiers(argptr, CTX_POPPAT, &pat_patctl, NULL))
return PR_SKIP; 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) if (pat_patctl.jit != 0)
{ {
PCRE2_JIT_COMPILE(jitrc, compiled_code, pat_patctl.jit); 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 /* Handle compiling via the native interface. Controls that act later are
ignored with "push". Replacements are locked out. */ 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) if (pat_patctl.replacement[0] != 0)
{ {
@ -4972,6 +5021,19 @@ if ((pat_patctl.control & CTL_PUSH) != 0)
SET(compiled_code, NULL); 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; return PR_OK;
} }
@ -5116,10 +5178,10 @@ if (f != NULL) fprintf(f, "--->");
PCHARS(pre_start, cb->subject, 0, cb->start_match, utf, 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. */ 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; cb->current_position : cb->start_match;
/* The subject between the match start and the current position. */ /* 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. */ /* 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); utf, f);
/* Calculate the total subject printed length (no print). */ /* Calculate the total subject printed length (no print). */

View File

@ -213,6 +213,12 @@
#pop jit,jitverify #pop jit,jitverify
abcdef abcdef
/abcd/pushcopy,jitverify
abcd
#pop jitverify
abcd
# Test pattern compilation # Test pattern compilation
/(?:a|b|c|d|e)(?R)/jit=1 /(?: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 # This set of tests exercises the serialization/deserialization and code copy
# the library. It does not use UTF or JIT. # functions in the library. It does not use UTF or JIT.
#forbid_utf #forbid_utf
@ -59,5 +59,33 @@
#pop should give an error #pop should give an error
pqr 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 # End of testinput20

View File

@ -392,6 +392,15 @@ JIT compilation was successful
abcdef abcdef
0: def (JIT) 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 # Test pattern compilation
/(?:a|b|c|d|e)(?R)/jit=1 /(?: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 # This set of tests exercises the serialization/deserialization and code copy
# the library. It does not use UTF or JIT. # functions in the library. It does not use UTF or JIT.
#forbid_utf #forbid_utf
@ -97,5 +97,42 @@ Serialization failed: error -30: patterns do not all use the same character tabl
#pop should give an error #pop should give an error
** Can't pop off an empty stack ** Can't pop off an empty stack
pqr 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 # End of testinput20