diff options
author | Thomas Adam <thomas@xteddy.org> | 2019-06-14 15:51:09 +0100 |
---|---|---|
committer | Thomas Adam <thomas@xteddy.org> | 2019-06-14 15:51:09 +0100 |
commit | 5e9757b30b8de13028149caa2683a7d76f231790 (patch) | |
tree | 5df34efc0213aa839e5ba6ddefa1193309cff383 /format.c | |
parent | 4bbf941436765201825c8d675f45b0cb70eb19d3 (diff) | |
parent | d1d3bbb458b50ec455d65774d5c6669546b3b4ca (diff) | |
download | rtmux-5e9757b30b8de13028149caa2683a7d76f231790.tar.gz rtmux-5e9757b30b8de13028149caa2683a7d76f231790.tar.bz2 rtmux-5e9757b30b8de13028149caa2683a7d76f231790.zip |
Merge branch 'obsd-master'
Diffstat (limited to 'format.c')
-rw-r--r-- | format.c | 112 |
1 files changed, 68 insertions, 44 deletions
@@ -23,6 +23,7 @@ #include <errno.h> #include <fnmatch.h> #include <libgen.h> +#include <regex.h> #include <stdarg.h> #include <stdlib.h> #include <string.h> @@ -1112,7 +1113,7 @@ format_find(struct format_tree *ft, const char *key, int modifiers) envent = environ_find(ft->s->environ, key); if (envent == NULL) envent = environ_find(global_environ, key); - if (envent != NULL) { + if (envent != NULL && envent->value != NULL) { found = xstrdup(envent->value); goto found; } @@ -1263,7 +1264,7 @@ format_build_modifiers(struct format_tree *ft, const char **s, u_int *count) cp++; /* Check single character modifiers with no arguments. */ - if (strchr("lmCbdtqETSWP<>", cp[0]) != NULL && + if (strchr("lbdtqETSWP<>", cp[0]) != NULL && format_is_end(cp[1])) { format_add_modifier(&list, count, cp, 1, NULL, 0); cp++; @@ -1284,7 +1285,7 @@ format_build_modifiers(struct format_tree *ft, const char **s, u_int *count) } /* Now try single character with arguments. */ - if (strchr("s=", cp[0]) == NULL) + if (strchr("mCs=", cp[0]) == NULL) break; c = cp[0]; @@ -1345,39 +1346,67 @@ format_build_modifiers(struct format_tree *ft, const char **s, u_int *count) return list; } -/* Perform substitution in string. */ +/* Match against an fnmatch(3) pattern or regular expression. */ static char * -format_substitute(const char *source, const char *from, const char *to) +format_match(struct format_modifier *fm, const char *pattern, const char *text) { - char *copy, *new; - const char *cp; - size_t fromlen, tolen, newlen, used; - - fromlen = strlen(from); - tolen = strlen(to); - - newlen = strlen(source) + 1; - copy = new = xmalloc(newlen); - - for (cp = source; *cp != '\0'; /* nothing */) { - if (strncmp(cp, from, fromlen) != 0) { - *new++ = *cp++; - continue; + const char *s = ""; + regex_t r; + int flags = 0; + + if (fm->argc >= 1) + s = fm->argv[0]; + if (strchr(s, 'r') == NULL) { + if (strchr(s, 'i') != NULL) + flags |= FNM_CASEFOLD; + if (fnmatch(pattern, text, flags) != 0) + return (xstrdup("0")); + } else { + flags = REG_EXTENDED|REG_NOSUB; + if (strchr(s, 'i') != NULL) + flags |= REG_ICASE; + if (regcomp(&r, pattern, flags) != 0) + return (xstrdup("0")); + if (regexec(&r, text, 0, NULL, 0) != 0) { + regfree(&r); + return (xstrdup("0")); } - used = new - copy; - - newlen += tolen; - copy = xrealloc(copy, newlen); + regfree(&r); + } + return (xstrdup("1")); +} - new = copy + used; - memcpy(new, to, tolen); +/* Perform substitution in string. */ +static char * +format_sub(struct format_modifier *fm, const char *text, const char *pattern, + const char *with) +{ + char *value; + int flags = REG_EXTENDED; + + if (fm->argc >= 3 && strchr(fm->argv[2], 'i') != NULL) + flags |= REG_ICASE; + value = regsub(pattern, with, text, flags); + if (value == NULL) + return (xstrdup(text)); + return (value); +} - new += tolen; - cp += fromlen; +/* Search inside pane. */ +static char * +format_search(struct format_modifier *fm, struct window_pane *wp, const char *s) +{ + int ignore = 0, regex = 0; + char *value; + + if (fm->argc >= 1) { + if (strchr(fm->argv[0], 'i') != NULL) + ignore = 1; + if (strchr(fm->argv[0], 'r') != NULL) + regex = 1; } - - *new = '\0'; - return (copy); + xasprintf(&value, "%u", window_pane_search(wp, s, regex, ignore)); + return (value); } /* Loop over sessions. */ @@ -1522,11 +1551,10 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen, char *copy0, *condition, *found, *new; char *value, *left, *right; size_t valuelen; - int modifiers = 0, limit = 0; + int modifiers = 0, limit = 0, j; struct format_modifier *list, *fm, *cmp = NULL, *search = NULL; struct format_modifier *sub = NULL; u_int i, count; - int j; /* Make a copy of the key. */ copy = copy0 = xstrndup(key, keylen); @@ -1553,18 +1581,18 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen, search = fm; break; case 's': - if (fm->argc != 2) + if (fm->argc < 2) break; sub = fm; break; case '=': - if (fm->argc != 1 && fm->argc != 2) + if (fm->argc < 1) break; limit = strtonum(fm->argv[0], INT_MIN, INT_MAX, &errptr); if (errptr != NULL) limit = 0; - if (fm->argc == 2 && fm->argv[1] != NULL) + if (fm->argc >= 2 && fm->argv[1] != NULL) marker = fm->argv[1]; break; case 'l': @@ -1635,7 +1663,7 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen, value = xstrdup("0"); } else { format_log(ft, "search '%s' pane %%%u", copy, wp->id); - xasprintf(&value, "%u", window_pane_search(wp, copy)); + value = format_search(fm, wp, copy); } } else if (cmp != NULL) { /* Comparison of left and right. */ @@ -1687,12 +1715,8 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen, value = xstrdup("1"); else value = xstrdup("0"); - } else if (strcmp(cmp->modifier, "m") == 0) { - if (fnmatch(left, right, 0) == 0) - value = xstrdup("1"); - else - value = xstrdup("0"); - } + } else if (strcmp(cmp->modifier, "m") == 0) + value = format_match(fm, left, right); free(right); free(left); @@ -1770,8 +1794,8 @@ done: /* Perform substitution if any. */ if (sub != NULL) { - new = format_substitute(value, sub->argv[0], sub->argv[1]); - format_log(ft, "substituted '%s' to '%s: %s", sub->argv[0], + new = format_sub(sub, value, sub->argv[0], sub->argv[1]); + format_log(ft, "substituted '%s' to '%s': %s", sub->argv[0], sub->argv[1], new); free(value); value = new; |