mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Merge branch 'obsd-master'
Also add a check for -lm via AC_SEARCH_LIBS in configure.ac for portablility fixes.
This commit is contained in:
		
							
								
								
									
										117
									
								
								format.c
									
									
									
									
									
								
							
							
						
						
									
										117
									
								
								format.c
									
									
									
									
									
								
							@@ -23,6 +23,7 @@
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fnmatch.h>
 | 
			
		||||
#include <libgen.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
#include <regex.h>
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
@@ -49,7 +50,6 @@ static void	 format_add_tv(struct format_tree *, const char *,
 | 
			
		||||
		     struct timeval *);
 | 
			
		||||
static int	 format_replace(struct format_tree *, const char *, size_t,
 | 
			
		||||
		     char **, size_t *, size_t *);
 | 
			
		||||
 | 
			
		||||
static void	 format_defaults_session(struct format_tree *,
 | 
			
		||||
		     struct session *);
 | 
			
		||||
static void	 format_defaults_client(struct format_tree *, struct client *);
 | 
			
		||||
@@ -1543,7 +1543,7 @@ format_build_modifiers(struct format_tree *ft, const char **s, u_int *count)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Now try single character with arguments. */
 | 
			
		||||
		if (strchr("mCs=p", cp[0]) == NULL)
 | 
			
		||||
		if (strchr("mCs=pe", cp[0]) == NULL)
 | 
			
		||||
			break;
 | 
			
		||||
		c = cp[0];
 | 
			
		||||
 | 
			
		||||
@@ -1799,6 +1799,108 @@ format_loop_panes(struct format_tree *ft, const char *fmt)
 | 
			
		||||
	return (value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *
 | 
			
		||||
format_replace_expression(struct format_modifier *mexp, struct format_tree *ft,
 | 
			
		||||
    const char *copy)
 | 
			
		||||
{
 | 
			
		||||
	int		 argc = mexp->argc;
 | 
			
		||||
	const char	*errstr;
 | 
			
		||||
	char		*endch, *value, *left = NULL, *right = NULL;
 | 
			
		||||
	int		 use_fp = 0;
 | 
			
		||||
	u_int		 prec = 0;
 | 
			
		||||
	double		 mleft, mright, result;
 | 
			
		||||
	enum { ADD, SUBTRACT, MULTIPLY, DIVIDE, MODULUS } operator;
 | 
			
		||||
 | 
			
		||||
	if (strcmp(mexp->argv[0], "+") == 0)
 | 
			
		||||
		operator = ADD;
 | 
			
		||||
	else if (strcmp(mexp->argv[0], "-") == 0)
 | 
			
		||||
		operator = SUBTRACT;
 | 
			
		||||
	else if (strcmp(mexp->argv[0], "*") == 0)
 | 
			
		||||
		operator = MULTIPLY;
 | 
			
		||||
	else if (strcmp(mexp->argv[0], "/") == 0)
 | 
			
		||||
		operator = DIVIDE;
 | 
			
		||||
	else if (strcmp(mexp->argv[0], "%") == 0 ||
 | 
			
		||||
	    strcmp(mexp->argv[0], "m") == 0)
 | 
			
		||||
		operator = MODULUS;
 | 
			
		||||
	else {
 | 
			
		||||
		format_log(ft, "expression has no valid operator: '%s'",
 | 
			
		||||
		    mexp->argv[0]);
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* The second argument may be flags. */
 | 
			
		||||
	if (argc >= 2 && strchr(mexp->argv[1], 'f') != NULL) {
 | 
			
		||||
		use_fp = 1;
 | 
			
		||||
		prec = 2;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* The third argument may be precision. */
 | 
			
		||||
	if (argc >= 3) {
 | 
			
		||||
		prec = strtonum(mexp->argv[2], INT_MIN, INT_MAX, &errstr);
 | 
			
		||||
		if (errstr != NULL) {
 | 
			
		||||
			format_log (ft, "expression precision %s: %s", errstr,
 | 
			
		||||
			    mexp->argv[2]);
 | 
			
		||||
			goto fail;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (format_choose(ft, copy, &left, &right, 1) != 0) {
 | 
			
		||||
		format_log(ft, "expression syntax error");
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mleft = strtod(left, &endch);
 | 
			
		||||
	if (*endch != '\0') {
 | 
			
		||||
		format_log(ft, "expression left side is invalid: %s", left);
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mright = strtod(right, &endch);
 | 
			
		||||
	if (*endch != '\0') {
 | 
			
		||||
		format_log(ft, "expression right side is invalid: %s", right);
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!use_fp) {
 | 
			
		||||
		mleft = (long long)mleft;
 | 
			
		||||
		mright = (long long)mright;
 | 
			
		||||
	}
 | 
			
		||||
	format_log(ft, "expression left side is: %.*f", prec, mleft);
 | 
			
		||||
	format_log(ft, "expression right side is:  %.*f", prec, mright);
 | 
			
		||||
 | 
			
		||||
	switch (operator) {
 | 
			
		||||
	case ADD:
 | 
			
		||||
		result = mleft + mright;
 | 
			
		||||
		break;
 | 
			
		||||
	case SUBTRACT:
 | 
			
		||||
		result = mleft - mright;
 | 
			
		||||
		break;
 | 
			
		||||
	case MULTIPLY:
 | 
			
		||||
		result = mleft * mright;
 | 
			
		||||
		break;
 | 
			
		||||
	case DIVIDE:
 | 
			
		||||
		result = mleft / mright;
 | 
			
		||||
		break;
 | 
			
		||||
	case MODULUS:
 | 
			
		||||
		result = fmod(mleft, mright);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	if (use_fp)
 | 
			
		||||
		xasprintf(&value, "%.*f", prec, result);
 | 
			
		||||
	else
 | 
			
		||||
		xasprintf(&value, "%.*f", prec, (double)(long long)result);
 | 
			
		||||
	format_log(ft, "expression result is %s", value);
 | 
			
		||||
 | 
			
		||||
	free(right);
 | 
			
		||||
	free(left);
 | 
			
		||||
	return value;
 | 
			
		||||
 | 
			
		||||
fail:
 | 
			
		||||
	free(right);
 | 
			
		||||
	free(left);
 | 
			
		||||
	return (NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Replace a key. */
 | 
			
		||||
static int
 | 
			
		||||
format_replace(struct format_tree *ft, const char *key, size_t keylen,
 | 
			
		||||
@@ -1811,7 +1913,7 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
 | 
			
		||||
	size_t			  valuelen;
 | 
			
		||||
	int			  modifiers = 0, limit = 0, width = 0, j;
 | 
			
		||||
	struct format_modifier   *list, *fm, *cmp = NULL, *search = NULL;
 | 
			
		||||
	struct format_modifier	**sub = NULL;
 | 
			
		||||
	struct format_modifier	**sub = NULL, *mexp = NULL;
 | 
			
		||||
	u_int			  i, count, nsub = 0;
 | 
			
		||||
 | 
			
		||||
	/* Make a copy of the key. */
 | 
			
		||||
@@ -1863,6 +1965,11 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
 | 
			
		||||
				if (errptr != NULL)
 | 
			
		||||
					width = 0;
 | 
			
		||||
				break;
 | 
			
		||||
			case 'e':
 | 
			
		||||
				if (fm->argc < 1 || fm->argc > 3)
 | 
			
		||||
					break;
 | 
			
		||||
			    mexp = fm;
 | 
			
		||||
				break;
 | 
			
		||||
			case 'l':
 | 
			
		||||
				modifiers |= FORMAT_LITERAL;
 | 
			
		||||
				break;
 | 
			
		||||
@@ -2039,6 +2146,10 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
 | 
			
		||||
 | 
			
		||||
		free(condition);
 | 
			
		||||
		free(found);
 | 
			
		||||
	} else if (mexp != NULL) {
 | 
			
		||||
		value = format_replace_expression(mexp, ft, copy);
 | 
			
		||||
		if (value == NULL)
 | 
			
		||||
			value = xstrdup("");
 | 
			
		||||
	} else {
 | 
			
		||||
		/* Neither: look up directly. */
 | 
			
		||||
		value = format_find(ft, copy, modifiers);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user