diff options
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | Doc/Zsh/mod_pcre.yo | 5 | ||||
-rw-r--r-- | Src/Modules/pcre.c | 34 |
3 files changed, 40 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog index 719222048..3f1014db3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2023-11-02 Oliver Kiddle <opk@zsh.org> + * 52253: Src/Modules/pcre.c: support pcre callouts with shell + evaluation of the callout string + * 52260: Completion/Unix/Command/_sudo: handle variable assignments before the command in sudo completion diff --git a/Doc/Zsh/mod_pcre.yo b/Doc/Zsh/mod_pcre.yo index da73ac85a..41fab4475 100644 --- a/Doc/Zsh/mod_pcre.yo +++ b/Doc/Zsh/mod_pcre.yo @@ -69,6 +69,11 @@ print -l $accum) ) enditem() +If the regular expression contains callouts, these are executed as shell code. +During the execution of the callout, the string the regular expression is +matching against is available in the parameter tt(.pcre.subject). If there is a +non-zero return status from the shell code, the callout does not match. + The option tt(-d) uses the alternative breadth-first DFA search algorithm of pcre. This sets tt(match), or the array given with tt(-a), to all the matches found from the same start point in the subject. 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; |