summaryrefslogtreecommitdiffstats
path: root/regsub.c
diff options
context:
space:
mode:
authornicm <nicm>2019-06-20 15:40:14 +0000
committernicm <nicm>2019-06-20 15:40:14 +0000
commitf4e835754c7e13ed6e810104290608fe27c83cca (patch)
tree3c80406446e219390d354589f05d65ec77c434f3 /regsub.c
parentfc1df91e034627f674ed905be6a1159da883545e (diff)
Fix how regex substitution works with empty matches.
Diffstat (limited to 'regsub.c')
-rw-r--r--regsub.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/regsub.c b/regsub.c
index 53c83a8f..89355bef 100644
--- a/regsub.c
+++ b/regsub.c
@@ -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';