summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/doc-docbook/spec.xfpt5
-rw-r--r--doc/doc-txt/ChangeLog3
-rw-r--r--doc/doc-txt/NewStuff3
-rw-r--r--src/src/buildconfig.c10
-rw-r--r--src/src/config.h.defaults14
-rw-r--r--src/src/expand.c75
-rw-r--r--src/src/functions.h2
7 files changed, 74 insertions, 38 deletions
diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt
index 5104e50f6..0815c0e4d 100644
--- a/doc/doc-docbook/spec.xfpt
+++ b/doc/doc-docbook/spec.xfpt
@@ -9544,9 +9544,10 @@ decimal, even if they start with a leading zero; hexadecimal numbers are not
permitted. This can be useful when processing numbers extracted from dates or
times, which often do have leading zeros.
-A number may be followed by &"K"& or &"M"& to multiply it by 1024 or 1024*1024,
+A number may be followed by &"K"&, &"M"& or &"G"& to multiply it by 1024, 1024*1024
+or 1024*1024*1024,
respectively. Negative numbers are supported. The result of the computation is
-a decimal representation of the answer (without &"K"& or &"M"&). For example:
+a decimal representation of the answer (without &"K"&, &"M"& or &"G"&). For example:
.display
&`${eval:1+1} `& yields 2
diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index 3315d0594..7cf2d8791 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -99,6 +99,9 @@ PP/23 Added PCRE_CONFIG=yes support to Makefile for using pcre-config to
PP/24 Fixed headers_only on smtp transports (was not sending trailing dot).
Bugzilla 1246, report and most of solution from Tomasz Kusy.
+JH/02 ${eval } now uses 64-bit and supports a "g" suffix (like to "k" and "m").
+ This may cause build issues on older platforms.
+
Exim version 4.77
-----------------
diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff
index db77318db..ad173041f 100644
--- a/doc/doc-txt/NewStuff
+++ b/doc/doc-txt/NewStuff
@@ -71,6 +71,9 @@ Version 4.78
"socket activation", but forcing the activated socket to fd 0. We're
interested in adding more support for modern variants.
+10. ${eval } now uses 64-bit values on supporting platforms. A new "G" suffux
+ for numbers indicates multiplication by 1024^3.
+
Version 4.77
------------
diff --git a/src/src/buildconfig.c b/src/src/buildconfig.c
index dfb449762..64902a1ee 100644
--- a/src/src/buildconfig.c
+++ b/src/src/buildconfig.c
@@ -332,6 +332,16 @@ while (fgets(buffer, sizeof(buffer), base) != NULL)
while (*p == ' ' || *p == '\t') p++;
+ if (strncmp(p, "#ifdef ", 7) == 0
+ || strncmp(p, "#ifndef ", 8) == 0
+ || strncmp(p, "#if ", 4) == 0
+ || strncmp(p, "#endif", 6) == 0
+ )
+ {
+ fputs(buffer, new);
+ continue;
+ }
+
if (strncmp(p, "#define ", 8) != 0) continue;
p += 8;
diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults
index c082b9269..61b2f38e0 100644
--- a/src/src/config.h.defaults
+++ b/src/src/config.h.defaults
@@ -171,4 +171,18 @@ just in case. */
#define ROOT_UID 0
#define ROOT_GID 0
+/* Sizes for integer arithmetic. Go for 64bit; can be overridden in OS/os.h-FOO */
+#ifndef int_eximarith_t
+ #define int_eximarith_t int64_t
+#endif
+#ifndef PR_EXIM_ARITH
+ #define PR_EXIM_ARITH "%" PRId64 /* C99 standard, printf %lld */
+#endif
+#ifndef SC_EXIM_ARITH
+ #define SC_EXIM_ARITH "%" SCNi64 /* scanf incl. 0x prefix */
+#endif
+#ifndef SC_EXIM_DEC
+ #define SC_EXIM_DEC "%" SCNd64 /* scanf decimal */
+#endif
+
/* End of config.h.defaults */
diff --git a/src/src/expand.c b/src/src/expand.c
index e847fb798..dcc813801 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -1781,7 +1781,7 @@ BOOL tempcond, combined_cond;
BOOL *subcondptr;
BOOL sub2_honour_dollar = TRUE;
int i, rc, cond_type, roffset;
-int64_t num[2];
+int_eximarith_t num[2];
struct stat statbuf;
uschar name[256];
uschar *sub[4];
@@ -3069,14 +3069,14 @@ Returns: on success: the value of the expression, with *error still NULL
on failure: an undefined value, with *error = a message
*/
-static int64_t eval_op_or(uschar **, BOOL, uschar **);
+static int_eximarith_t eval_op_or(uschar **, BOOL, uschar **);
-static int64_t
+static int_eximarith_t
eval_expr(uschar **sptr, BOOL decimal, uschar **error, BOOL endket)
{
uschar *s = *sptr;
-int64_t x = eval_op_or(&s, decimal, error);
+int_eximarith_t x = eval_op_or(&s, decimal, error);
if (*error == NULL)
{
if (endket)
@@ -3093,21 +3093,26 @@ return x;
}
-static int64_t
+static int_eximarith_t
eval_number(uschar **sptr, BOOL decimal, uschar **error)
{
register int c;
-int64_t n;
+int_eximarith_t n;
uschar *s = *sptr;
while (isspace(*s)) s++;
c = *s;
if (isdigit(c))
{
int count;
- (void)sscanf(CS s, (decimal? "%lld%n" : "%lli%n"), &n, &count);
+ (void)sscanf(CS s, (decimal? SC_EXIM_DEC "%n" : SC_EXIM_ARITH "%n"), &n, &count);
s += count;
- if (tolower(*s) == 'k') { n *= 1024; s++; }
- else if (tolower(*s) == 'm') { n *= 1024*1024; s++; }
+ switch (tolower(*s))
+ {
+ default: break;
+ case 'k': n *= 1024; s++; break;
+ case 'm': n *= 1024*1024; s++; break;
+ case 'g': n *= 1024*1024*1024; s++; break;
+ }
while (isspace (*s)) s++;
}
else if (c == '(')
@@ -3125,11 +3130,11 @@ return n;
}
-static int64_t
+static int_eximarith_t
eval_op_unary(uschar **sptr, BOOL decimal, uschar **error)
{
uschar *s = *sptr;
-int64_t x;
+int_eximarith_t x;
while (isspace(*s)) s++;
if (*s == '+' || *s == '-' || *s == '~')
{
@@ -3147,17 +3152,17 @@ return x;
}
-static int64_t
+static int_eximarith_t
eval_op_mult(uschar **sptr, BOOL decimal, uschar **error)
{
uschar *s = *sptr;
-int64_t x = eval_op_unary(&s, decimal, error);
+int_eximarith_t x = eval_op_unary(&s, decimal, error);
if (*error == NULL)
{
while (*s == '*' || *s == '/' || *s == '%')
{
int op = *s++;
- int64_t y = eval_op_unary(&s, decimal, error);
+ int_eximarith_t y = eval_op_unary(&s, decimal, error);
if (*error != NULL) break;
/* SIGFPE both on div/mod by zero and on INT_MIN / -1, which would give
* a value of INT_MAX+1. Note that INT_MIN * -1 gives INT_MIN for me, which
@@ -3180,7 +3185,7 @@ if (*error == NULL)
if (y == -1 && x == LLONG_MIN && op != '*')
{
DEBUG(D_expand)
- debug_printf("Integer exception dodging: %lld%c-1 coerced to %lld\n",
+ debug_printf("Integer exception dodging: " PR_EXIM_ARITH "%c-1 coerced to " PR_EXIM_ARITH "\n",
LLONG_MIN, op, LLONG_MAX);
x = LLONG_MAX;
continue;
@@ -3207,17 +3212,17 @@ return x;
}
-static int64_t
+static int_eximarith_t
eval_op_sum(uschar **sptr, BOOL decimal, uschar **error)
{
uschar *s = *sptr;
-int64_t x = eval_op_mult(&s, decimal, error);
+int_eximarith_t x = eval_op_mult(&s, decimal, error);
if (*error == NULL)
{
while (*s == '+' || *s == '-')
{
int op = *s++;
- int64_t y = eval_op_mult(&s, decimal, error);
+ int_eximarith_t y = eval_op_mult(&s, decimal, error);
if (*error != NULL) break;
if (op == '+') x += y; else x -= y;
}
@@ -3227,16 +3232,16 @@ return x;
}
-static int64_t
+static int_eximarith_t
eval_op_shift(uschar **sptr, BOOL decimal, uschar **error)
{
uschar *s = *sptr;
-int64_t x = eval_op_sum(&s, decimal, error);
+int_eximarith_t x = eval_op_sum(&s, decimal, error);
if (*error == NULL)
{
while ((*s == '<' || *s == '>') && s[1] == s[0])
{
- int64_t y;
+ int_eximarith_t y;
int op = *s++;
s++;
y = eval_op_sum(&s, decimal, error);
@@ -3249,16 +3254,16 @@ return x;
}
-static int64_t
+static int_eximarith_t
eval_op_and(uschar **sptr, BOOL decimal, uschar **error)
{
uschar *s = *sptr;
-int64_t x = eval_op_shift(&s, decimal, error);
+int_eximarith_t x = eval_op_shift(&s, decimal, error);
if (*error == NULL)
{
while (*s == '&')
{
- int64_t y;
+ int_eximarith_t y;
s++;
y = eval_op_shift(&s, decimal, error);
if (*error != NULL) break;
@@ -3270,16 +3275,16 @@ return x;
}
-static int64_t
+static int_eximarith_t
eval_op_xor(uschar **sptr, BOOL decimal, uschar **error)
{
uschar *s = *sptr;
-int64_t x = eval_op_and(&s, decimal, error);
+int_eximarith_t x = eval_op_and(&s, decimal, error);
if (*error == NULL)
{
while (*s == '^')
{
- int64_t y;
+ int_eximarith_t y;
s++;
y = eval_op_and(&s, decimal, error);
if (*error != NULL) break;
@@ -3291,16 +3296,16 @@ return x;
}
-static int64_t
+static int_eximarith_t
eval_op_or(uschar **sptr, BOOL decimal, uschar **error)
{
uschar *s = *sptr;
-int64_t x = eval_op_xor(&s, decimal, error);
+int_eximarith_t x = eval_op_xor(&s, decimal, error);
if (*error == NULL)
{
while (*s == '|')
{
- int64_t y;
+ int_eximarith_t y;
s++;
y = eval_op_xor(&s, decimal, error);
if (*error != NULL) break;
@@ -5700,7 +5705,7 @@ while (*s != 0)
{
uschar *save_sub = sub;
uschar *error = NULL;
- int64_t n = eval_expr(&sub, (c == EOP_EVAL10), &error, FALSE);
+ int_eximarith_t n = eval_expr(&sub, (c == EOP_EVAL10), &error, FALSE);
if (error != NULL)
{
expand_string_message = string_sprintf("error in expression "
@@ -5708,7 +5713,7 @@ while (*s != 0)
save_sub);
goto EXPAND_FAILED;
}
- sprintf(CS var_buffer, "%lld", n);
+ sprintf(CS var_buffer, PR_EXIM_ARITH, n);
yield = string_cat(yield, &size, &ptr, var_buffer, Ustrlen(var_buffer));
continue;
}
@@ -5913,7 +5918,7 @@ while (*s != 0)
case EOP_RANDINT:
{
- int64_t max;
+ int_eximarith_t max;
uschar *s;
max = expand_string_integer(sub, TRUE);
@@ -6110,10 +6115,10 @@ Returns: the integer value, or
expand_string_message is set NULL for an OK integer
*/
-int64_t
+int_eximarith_t
expand_string_integer(uschar *string, BOOL isplus)
{
-int64_t value;
+int_eximarith_t value;
uschar *s = expand_string(string);
uschar *msg = US"invalid integer \"%s\"";
uschar *endptr;
diff --git a/src/src/functions.h b/src/src/functions.h
index 2ed9593cc..8986f3a49 100644
--- a/src/src/functions.h
+++ b/src/src/functions.h
@@ -114,7 +114,7 @@ extern void exim_wait_tick(struct timeval *, int);
extern BOOL expand_check_condition(uschar *, uschar *, uschar *);
extern uschar *expand_string(uschar *);
extern uschar *expand_string_copy(uschar *);
-extern int64_t expand_string_integer(uschar *, BOOL);
+extern int_eximarith_t expand_string_integer(uschar *, BOOL);
extern int filter_interpret(uschar *, int, address_item **, uschar **);
extern BOOL filter_personal(string_item *, BOOL);