Use defines in config.h for type & scanf-patterns for eval. Update docs.
authorJeremy Harris <jgh146exb@wizmail.org>
Sun, 13 May 2012 20:04:45 +0000 (21:04 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Sun, 13 May 2012 20:04:45 +0000 (21:04 +0100)
doc/doc-docbook/spec.xfpt
doc/doc-txt/ChangeLog
doc/doc-txt/NewStuff
src/src/buildconfig.c
src/src/config.h.defaults
src/src/expand.c
src/src/functions.h

index 5104e50f69ebbce0e1e737743a4ce868e37eeea3..0815c0e4d087d9278a54815fc17906f974323ffe 100644 (file)
@@ -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.
 
 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
 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
 
 .display
 &`${eval:1+1}            `&  yields 2
index 3315d0594ede0816b735fe91ed446425af7fd8a8..7cf2d8791ae7b69ad577bc7dce8a853f17c223bf 100644 (file)
@@ -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.
 
 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
 -----------------
 
 Exim version 4.77
 -----------------
index db77318db79a2595056917d447cf4cfbfa27c6df..ad173041f8fee8ed8b5e182f5a29efe8f49311c6 100644 (file)
@@ -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.
 
     "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
 ------------
 
 Version 4.77
 ------------
index dfb4497622f1205030f80498b23f0cc56de7acae..64902a1ee2d6a7e2e5fba31f537c0f5452517ec8 100644 (file)
@@ -332,6 +332,16 @@ while (fgets(buffer, sizeof(buffer), base) != NULL)
 
   while (*p == ' ' || *p == '\t') p++;
 
 
   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;
   if (strncmp(p, "#define ", 8) != 0) continue;
 
   p += 8;
index c082b9269c6bf74e68334c708ba0bcc3d4107f4a..61b2f38e0aab16896cc1cae366e182d4ed54c7c8 100644 (file)
@@ -171,4 +171,18 @@ just in case. */
 #define ROOT_UID                      0
 #define ROOT_GID                      0
 
 #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 */
 /* End of config.h.defaults */
index e847fb798b76de3e624e5e8363895b6bae5af53e..dcc813801f263de006c2e0c0fdb6afb7f88fa3ea 100644 (file)
@@ -1781,7 +1781,7 @@ BOOL tempcond, combined_cond;
 BOOL *subcondptr;
 BOOL sub2_honour_dollar = TRUE;
 int i, rc, cond_type, roffset;
 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];
 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
 */
 
               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;
 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)
 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;
 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;
 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;
   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 == '(')
   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;
 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 == '~')
   {
 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;
 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++;
 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
     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)
     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;
             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;
 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++;
 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;
     }
     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;
 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])
     {
 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);
     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;
 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 == '&')
     {
 if (*error == NULL)
   {
   while (*s == '&')
     {
-    int64_t y;
+    int_eximarith_t y;
     s++;
     y = eval_op_shift(&s, decimal, error);
     if (*error != NULL) break;
     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;
 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 == '^')
     {
 if (*error == NULL)
   {
   while (*s == '^')
     {
-    int64_t y;
+    int_eximarith_t y;
     s++;
     y = eval_op_and(&s, decimal, error);
     if (*error != NULL) break;
     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;
 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 == '|')
     {
 if (*error == NULL)
   {
   while (*s == '|')
     {
-    int64_t y;
+    int_eximarith_t y;
     s++;
     y = eval_op_xor(&s, decimal, error);
     if (*error != NULL) break;
     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;
         {
         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 "
         if (error != NULL)
           {
           expand_string_message = string_sprintf("error in expression "
@@ -5708,7 +5713,7 @@ while (*s != 0)
               save_sub);
           goto EXPAND_FAILED;
           }
               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;
         }
         yield = string_cat(yield, &size, &ptr, var_buffer, Ustrlen(var_buffer));
         continue;
         }
@@ -5913,7 +5918,7 @@ while (*s != 0)
 
       case EOP_RANDINT:
         {
 
       case EOP_RANDINT:
         {
-        int64_t max;
+        int_eximarith_t max;
         uschar *s;
 
         max = expand_string_integer(sub, TRUE);
         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
 */
 
           expand_string_message is set NULL for an OK integer
 */
 
-int64_t
+int_eximarith_t
 expand_string_integer(uschar *string, BOOL isplus)
 {
 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;
 uschar *s = expand_string(string);
 uschar *msg = US"invalid integer \"%s\"";
 uschar *endptr;
index 2ed9593cc77c8da47f955b31fec70cc0bc5941b8..8986f3a492edf584bb70a7e899f6c178bf274bea 100644 (file)
@@ -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 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);
 
 extern int     filter_interpret(uschar *, int, address_item **, uschar **);
 extern BOOL    filter_personal(string_item *, BOOL);