From 97d1730589a1b7d1f630df1f3193df5b967d3aba Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Sun, 13 May 2012 21:04:45 +0100 Subject: [PATCH] Use defines in config.h for type & scanf-patterns for eval. Update docs. --- doc/doc-docbook/spec.xfpt | 5 +-- doc/doc-txt/ChangeLog | 3 ++ doc/doc-txt/NewStuff | 3 ++ src/src/buildconfig.c | 10 ++++++ src/src/config.h.defaults | 14 ++++++++ src/src/expand.c | 75 +++++++++++++++++++++------------------ src/src/functions.h | 2 +- 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); -- 2.30.2