version 1.201, 2019/05/31 21:41:17 |
version 1.202, 2019/06/13 19:46:00 |
|
|
#include <errno.h> |
#include <errno.h> |
#include <fnmatch.h> |
#include <fnmatch.h> |
#include <libgen.h> |
#include <libgen.h> |
|
#include <regex.h> |
#include <stdarg.h> |
#include <stdarg.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
|
|
cp++; |
cp++; |
|
|
/* Check single character modifiers with no arguments. */ |
/* 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_is_end(cp[1])) { |
format_add_modifier(&list, count, cp, 1, NULL, 0); |
format_add_modifier(&list, count, cp, 1, NULL, 0); |
cp++; |
cp++; |
|
|
} |
} |
|
|
/* Now try single character with arguments. */ |
/* Now try single character with arguments. */ |
if (strchr("s=", cp[0]) == NULL) |
if (strchr("mCs=", cp[0]) == NULL) |
break; |
break; |
c = cp[0]; |
c = cp[0]; |
|
|
|
|
return list; |
return list; |
} |
} |
|
|
/* Perform substitution in string. */ |
/* Match against an fnmatch(3) pattern or regular expression. */ |
static char * |
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 *s = ""; |
const char *cp; |
regex_t r; |
size_t fromlen, tolen, newlen, used; |
int flags = 0; |
|
|
fromlen = strlen(from); |
if (fm->argc >= 1) |
tolen = strlen(to); |
s = fm->argv[0]; |
|
if (strchr(s, 'r') == NULL) { |
newlen = strlen(source) + 1; |
if (strchr(s, 'i') != NULL) |
copy = new = xmalloc(newlen); |
flags |= FNM_CASEFOLD; |
|
if (fnmatch(pattern, text, flags) != 0) |
for (cp = source; *cp != '\0'; /* nothing */) { |
return (xstrdup("0")); |
if (strncmp(cp, from, fromlen) != 0) { |
} else { |
*new++ = *cp++; |
flags = REG_EXTENDED|REG_NOSUB; |
continue; |
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; |
regfree(&r); |
|
} |
|
return (xstrdup("1")); |
|
} |
|
|
newlen += tolen; |
/* Perform substitution in string. */ |
copy = xrealloc(copy, newlen); |
static char * |
|
format_sub(struct format_modifier *fm, const char *text, const char *pattern, |
|
const char *with) |
|
{ |
|
char *value; |
|
int flags = REG_EXTENDED; |
|
|
new = copy + used; |
if (fm->argc >= 3 && strchr(fm->argv[2], 'i') != NULL) |
memcpy(new, to, tolen); |
flags |= REG_ICASE; |
|
value = regsub(pattern, with, text, flags); |
|
if (value == NULL) |
|
return (xstrdup(text)); |
|
return (value); |
|
} |
|
|
new += tolen; |
/* Search inside pane. */ |
cp += fromlen; |
static char * |
} |
format_search(struct format_modifier *fm, struct window_pane *wp, const char *s) |
|
{ |
|
int ignore = 0, regex = 0; |
|
char *value; |
|
|
*new = '\0'; |
if (fm->argc >= 1) { |
return (copy); |
if (strchr(fm->argv[0], 'i') != NULL) |
|
ignore = 1; |
|
if (strchr(fm->argv[0], 'r') != NULL) |
|
regex = 1; |
|
} |
|
xasprintf(&value, "%u", window_pane_search(wp, s, regex, ignore)); |
|
return (value); |
} |
} |
|
|
/* Loop over sessions. */ |
/* Loop over sessions. */ |
|
|
char *copy0, *condition, *found, *new; |
char *copy0, *condition, *found, *new; |
char *value, *left, *right; |
char *value, *left, *right; |
size_t valuelen; |
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 *list, *fm, *cmp = NULL, *search = NULL; |
struct format_modifier *sub = NULL; |
struct format_modifier *sub = NULL; |
u_int i, count; |
u_int i, count; |
int j; |
|
|
|
/* Make a copy of the key. */ |
/* Make a copy of the key. */ |
copy = copy0 = xstrndup(key, keylen); |
copy = copy0 = xstrndup(key, keylen); |
|
|
search = fm; |
search = fm; |
break; |
break; |
case 's': |
case 's': |
if (fm->argc != 2) |
if (fm->argc < 2) |
break; |
break; |
sub = fm; |
sub = fm; |
break; |
break; |
case '=': |
case '=': |
if (fm->argc != 1 && fm->argc != 2) |
if (fm->argc < 1) |
break; |
break; |
limit = strtonum(fm->argv[0], INT_MIN, INT_MAX, |
limit = strtonum(fm->argv[0], INT_MIN, INT_MAX, |
&errptr); |
&errptr); |
if (errptr != NULL) |
if (errptr != NULL) |
limit = 0; |
limit = 0; |
if (fm->argc == 2 && fm->argv[1] != NULL) |
if (fm->argc >= 2 && fm->argv[1] != NULL) |
marker = fm->argv[1]; |
marker = fm->argv[1]; |
break; |
break; |
case 'l': |
case 'l': |
|
|
value = xstrdup("0"); |
value = xstrdup("0"); |
} else { |
} else { |
format_log(ft, "search '%s' pane %%%u", copy, wp->id); |
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) { |
} else if (cmp != NULL) { |
/* Comparison of left and right. */ |
/* Comparison of left and right. */ |
|
|
value = xstrdup("1"); |
value = xstrdup("1"); |
else |
else |
value = xstrdup("0"); |
value = xstrdup("0"); |
} else if (strcmp(cmp->modifier, "m") == 0) { |
} else if (strcmp(cmp->modifier, "m") == 0) |
if (fnmatch(left, right, 0) == 0) |
value = format_match(fm, left, right); |
value = xstrdup("1"); |
|
else |
|
value = xstrdup("0"); |
|
} |
|
|
|
free(right); |
free(right); |
free(left); |
free(left); |
|
|
|
|
/* Perform substitution if any. */ |
/* Perform substitution if any. */ |
if (sub != NULL) { |
if (sub != NULL) { |
new = format_substitute(value, sub->argv[0], sub->argv[1]); |
new = format_sub(sub, value, sub->argv[0], sub->argv[1]); |
format_log(ft, "substituted '%s' to '%s: %s", sub->argv[0], |
format_log(ft, "substituted '%s' to '%s': %s", sub->argv[0], |
sub->argv[1], new); |
sub->argv[1], new); |
free(value); |
free(value); |
value = new; |
value = new; |