diff options
author | Nicholas Marriott <nicm@cvs.openbsd.org> | 2019-06-20 15:40:15 +0000 |
---|---|---|
committer | Nicholas Marriott <nicm@cvs.openbsd.org> | 2019-06-20 15:40:15 +0000 |
commit | 899626be22606a46f6adcd3ecb19de4060f70803 (patch) | |
tree | d8a8885c2c6475a2fe53c791436e4052a53976c7 /usr.bin/tmux/regsub.c | |
parent | f84cd4edbba57ed0faffbbd79d7b140b742ea297 (diff) |
Fix how regex substitution works with empty matches.
Diffstat (limited to 'usr.bin/tmux/regsub.c')
-rw-r--r-- | usr.bin/tmux/regsub.c | 37 |
1 files changed, 27 insertions, 10 deletions
diff --git a/usr.bin/tmux/regsub.c b/usr.bin/tmux/regsub.c index a7e14505346..cf5b917aee3 100644 --- a/usr.bin/tmux/regsub.c +++ b/usr.bin/tmux/regsub.c @@ -1,4 +1,4 @@ -/* $OpenBSD: regsub.c,v 1.1 2019/06/13 19:46:00 nicm Exp $ */ +/* $OpenBSD: regsub.c,v 1.2 2019/06/20 15:40:14 nicm Exp $ */ /* * Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -63,7 +63,8 @@ regsub(const char *pattern, const char *with, const char *text, int flags) { regex_t r; regmatch_t m[10]; - size_t start, end, len = 0; + ssize_t start, end, last, len = 0; + int empty = 0; char *buf = NULL; if (*text == '\0') @@ -72,9 +73,10 @@ regsub(const char *pattern, const char *with, const char *text, int flags) return (NULL); start = 0; + last = 0; end = strlen(text); - while (start != end) { + while (start <= end) { m[0].rm_so = start; m[0].rm_eo = end; @@ -82,14 +84,29 @@ regsub(const char *pattern, const char *with, const char *text, int flags) regsub_copy(&buf, &len, text, start, end); break; } - if (m[0].rm_so == m[0].rm_eo) { - regsub_copy(&buf, &len, text, start, end); - break; - } - regsub_copy(&buf, &len, text, start, m[0].rm_so); - regsub_expand(&buf, &len, with, text, m, nitems(m)); - start = m[0].rm_eo; + /* + * Append any text not part of this match (from the end of the + * last match). + */ + regsub_copy(&buf, &len, text, last, m[0].rm_so); + + /* + * If the last match was empty and this one isn't (it is either + * later or has matched text), expand this match. If it is + * empty, move on one character and try again from there. + */ + if (empty || m[0].rm_so != last || m[0].rm_so != m[0].rm_eo) { + regsub_expand(&buf, &len, with, text, m, nitems(m)); + + last = m[0].rm_eo; + start = m[0].rm_eo; + empty = 0; + } else { + last = m[0].rm_eo; + start = m[0].rm_eo + 1; + empty = 1; + } } buf[len] = '\0'; |