Annotation of src/usr.bin/tmux/regsub.c, Revision 1.1
1.1 ! nicm 1: /* $OpenBSD$ */
! 2:
! 3: /*
! 4: * Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
! 5: *
! 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.
! 9: *
! 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.
! 17: */
! 18:
! 19: #include <sys/types.h>
! 20:
! 21: #include <regex.h>
! 22: #include <string.h>
! 23:
! 24: #include "tmux.h"
! 25:
! 26: static void
! 27: regsub_copy(char **buf, size_t *len, const char *text, size_t start,
! 28: size_t end)
! 29: {
! 30: size_t add = end - start;
! 31:
! 32: *buf = xrealloc(*buf, (*len) + add + 1);
! 33: memcpy((*buf) + *len, text + start, add);
! 34: (*len) += add;
! 35: }
! 36:
! 37: static void
! 38: regsub_expand(char **buf, size_t *len, const char *with, const char *text,
! 39: regmatch_t *m, u_int n)
! 40: {
! 41: const char *cp;
! 42: u_int i;
! 43:
! 44: for (cp = with; *cp != '\0'; cp++) {
! 45: if (*cp == '\\') {
! 46: cp++;
! 47: if (*cp >= '0' && *cp <= '9') {
! 48: i = *cp - '0';
! 49: if (i < n && m[i].rm_so != m[i].rm_eo) {
! 50: regsub_copy(buf, len, text, m[i].rm_so,
! 51: m[i].rm_eo);
! 52: continue;
! 53: }
! 54: }
! 55: }
! 56: *buf = xrealloc(*buf, (*len) + 2);
! 57: (*buf)[(*len)++] = *cp;
! 58: }
! 59: }
! 60:
! 61: char *
! 62: regsub(const char *pattern, const char *with, const char *text, int flags)
! 63: {
! 64: regex_t r;
! 65: regmatch_t m[10];
! 66: size_t start, end, len = 0;
! 67: char *buf = NULL;
! 68:
! 69: if (*text == '\0')
! 70: return (xstrdup(""));
! 71: if (regcomp(&r, pattern, flags) != 0)
! 72: return (NULL);
! 73:
! 74: start = 0;
! 75: end = strlen(text);
! 76:
! 77: while (start != end) {
! 78: m[0].rm_so = start;
! 79: m[0].rm_eo = end;
! 80:
! 81: if (regexec(&r, text, nitems(m), m, REG_STARTEND) != 0) {
! 82: regsub_copy(&buf, &len, text, start, end);
! 83: break;
! 84: }
! 85: if (m[0].rm_so == m[0].rm_eo) {
! 86: regsub_copy(&buf, &len, text, start, end);
! 87: break;
! 88: }
! 89:
! 90: regsub_copy(&buf, &len, text, start, m[0].rm_so);
! 91: regsub_expand(&buf, &len, with, text, m, nitems(m));
! 92: start = m[0].rm_eo;
! 93: }
! 94: buf[len] = '\0';
! 95:
! 96: regfree(&r);
! 97: return (buf);
! 98: }