4 * Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/types.h>
27 regsub_copy(char **buf
, size_t *len
, const char *text
, size_t start
, size_t end
)
29 size_t add
= end
- start
;
31 *buf
= xrealloc(*buf
, (*len
) + add
+ 1);
32 memcpy((*buf
) + *len
, text
+ start
, add
);
37 regsub_expand(char **buf
, size_t *len
, const char *with
, const char *text
,
38 regmatch_t
*m
, u_int n
)
43 for (cp
= with
; *cp
!= '\0'; cp
++) {
46 if (*cp
>= '0' && *cp
<= '9') {
48 if (i
< n
&& m
[i
].rm_so
!= m
[i
].rm_eo
) {
49 regsub_copy(buf
, len
, text
, m
[i
].rm_so
,
55 *buf
= xrealloc(*buf
, (*len
) + 2);
56 (*buf
)[(*len
)++] = *cp
;
61 regsub(const char *pattern
, const char *with
, const char *text
, int flags
)
65 ssize_t start
, end
, last
, len
= 0;
71 if (regcomp(&r
, pattern
, flags
) != 0)
78 while (start
<= end
) {
79 if (regexec(&r
, text
+ start
, nitems(m
), m
, 0) != 0) {
80 regsub_copy(&buf
, &len
, text
, start
, end
);
85 * Append any text not part of this match (from the end of the
88 regsub_copy(&buf
, &len
, text
, last
, m
[0].rm_so
+ start
);
91 * If the last match was empty and this one isn't (it is either
92 * later or has matched text), expand this match. If it is
93 * empty, move on one character and try again from there.
96 start
+ m
[0].rm_so
!= last
||
97 m
[0].rm_so
!= m
[0].rm_eo
) {
98 regsub_expand(&buf
, &len
, with
, text
+ start
, m
,
101 last
= start
+ m
[0].rm_eo
;
105 last
= start
+ m
[0].rm_eo
;
106 start
+= m
[0].rm_eo
+ 1;
110 /* Stop now if anchored to start. */
111 if (*pattern
== '^') {
112 regsub_copy(&buf
, &len
, text
, start
, end
);