1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-05-23 12:41:29 +02:00

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

This commit is contained in:
Oliver Kiddle 2023-10-31 01:04:19 +01:00
parent a9b0ccd661
commit de635b4ee5
3 changed files with 40 additions and 2 deletions
ChangeLog
Doc/Zsh
Src/Modules

View file

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

View file

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

View file

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