summaryrefslogtreecommitdiff
path: root/Src/Modules/pcre.c
diff options
context:
space:
mode:
authorOliver Kiddle <opk@zsh.org>2023-10-31 01:04:19 +0100
committerOliver Kiddle <opk@zsh.org>2023-11-02 14:54:59 +0100
commitde635b4ee56c188ccbaf0009027f9d1c0d42af0f (patch)
treef45a398d019bb7aed4aa02093d5ae0af7ddbe5b9 /Src/Modules/pcre.c
parenta9b0ccd661db7292a4ab52b3ffe6fbc8dc8ade4f (diff)
downloadzsh-de635b4ee56c188ccbaf0009027f9d1c0d42af0f.tar.gz
zsh-de635b4ee56c188ccbaf0009027f9d1c0d42af0f.zip
52253: support pcre callouts with shell evaluation of the callout string
Diffstat (limited to 'Src/Modules/pcre.c')
-rw-r--r--Src/Modules/pcre.c34
1 files changed, 32 insertions, 2 deletions
diff --git a/Src/Modules/pcre.c b/Src/Modules/pcre.c
index f5cda6d38..e6b59831f 100644
--- a/Src/Modules/pcre.c
+++ b/Src/Modules/pcre.c
@@ -129,6 +129,31 @@ bin_pcre_study(char *nam, UNUSED(char **args), UNUSED(Options ops), UNUSED(int f
}
static int
+pcre_callout(pcre2_callout_block_8 *block, void *)
+{
+ Eprog prog;
+ int ret=0;
+
+ if (!block->callout_number &&
+ ((prog = parse_string((char *) block->callout_string, 0))))
+ {
+ int ef = errflag, lv = lastval;
+
+ setsparam(".pcre.subject",
+ metafy((char *) block->subject, block->subject_length, META_DUP));
+ setiparam(".pcre.pos", block->current_position + 1);
+ execode(prog, 1, 0, "pcre");
+ ret = lastval | errflag;
+
+ /* Restore any user interrupt error status */
+ errflag = ef | (errflag & ERRFLAG_INT);
+ lastval = lv;
+ }
+
+ return ret;
+}
+
+static int
zpcre_get_substrings(pcre2_code *pat, char *arg, pcre2_match_data *mdata,
int captured_count, char *matchvar, char *substravar, char *namedassoc,
int want_offset_pair, int matchedinarr, int want_begin_end)
@@ -339,6 +364,9 @@ bin_pcre_match(char *nam, char **args, Options ops, UNUSED(int func))
plaintext = ztrdup(*args);
unmetafy(plaintext, &subject_len);
+ pcre2_match_context_8 *mcontext = pcre2_match_context_create(NULL);
+ pcre2_set_callout(mcontext, &pcre_callout, 0);
+
if (offset_start > 0 && offset_start >= subject_len)
ret = PCRE2_ERROR_NOMATCH;
else if (use_dfa) {
@@ -347,7 +375,7 @@ bin_pcre_match(char *nam, char **args, Options ops, UNUSED(int func))
pcre_mdata = pcre2_match_data_create(capcount, NULL);
do {
ret = pcre2_dfa_match(pcre_pattern, (PCRE2_SPTR) plaintext, subject_len,
- offset_start, 0, pcre_mdata, NULL, (int *) workspace, wscount);
+ offset_start, 0, pcre_mdata, mcontext, (int *) workspace, wscount);
if (ret == PCRE2_ERROR_DFA_WSSIZE) {
old = wscount;
wscount += wscount / 2;
@@ -362,7 +390,7 @@ bin_pcre_match(char *nam, char **args, Options ops, UNUSED(int func))
} else {
pcre_mdata = pcre2_match_data_create_from_pattern(pcre_pattern, NULL);
ret = pcre2_match(pcre_pattern, (PCRE2_SPTR) plaintext, subject_len,
- offset_start, 0, pcre_mdata, NULL);
+ offset_start, 0, pcre_mdata, mcontext);
}
if (ret==0) return_value = 0;
@@ -380,6 +408,8 @@ bin_pcre_match(char *nam, char **args, Options ops, UNUSED(int func))
if (pcre_mdata)
pcre2_match_data_free(pcre_mdata);
+ if (mcontext)
+ pcre2_match_context_free(mcontext);
zsfree(plaintext);
return return_value;