52253: support pcre callouts with shell evaluation of the callout string

master
Oliver Kiddle 7 months ago
parent a9b0ccd661
commit de635b4ee5

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

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

@ -128,6 +128,31 @@ bin_pcre_study(char *nam, UNUSED(char **args), UNUSED(Options ops), UNUSED(int f
return 0;
}
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,
@ -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;

Loading…
Cancel
Save