Subject: bug#7701: closed (Re: bug#7701: [PATCH] getlimits: port to hosts with very wide int, or non-ASCII)

From: [email-masked] (GNU bug Tracking System)
Date: Tue, 21 Dec 2010 22:56:02 +0000

Your bug report

#7701: [PATCH] getlimits: port to hosts with very wide int, or non-ASCII

which was filed against the coreutils package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
7701: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=7701
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#7701: [PATCH] getlimits: port to hosts with very wide int, or non-ASCII
From: Pádraig Brady <[email-masked]>
To: Paul Eggert <[email-masked]>
Cc: [email-masked]
Date: Tue, 21 Dec 2010 22:58:33 +0000
List-Id: <debbugs-submit.debbugs.gnu.org>

On 21/12/10 22:14, Paul Eggert wrote:
> I haven't pushed this, since the portability bugs it fixes aren't triggered on
> any hosts that I know of, and we're currently just fixing known bugs.

Thanks for the cleanup Paul.
Your 'add' routine is less general
but also simpler, so you're free
to push that after the imminent release.

Mildly related to this is; speeding up seq.
That might be able to use the more general
routine (without allocs) in certain cases.
It might be simple/faster than using gmp?

cheers,
Pádraig.

p.s. savannah is down ATM

Subject: [PATCH] getlimits: port to hosts with very wide int, or non-ASCII
From: Paul Eggert <[email-masked]>
To: [email-masked]
Date: Tue, 21 Dec 2010 14:14:15 -0800
List-Id: <debbugs-submit.debbugs.gnu.org>

I haven't pushed this, since the portability bugs it fixes aren't triggered on
any hosts that I know of, and we're currently just fixing known bugs.

>From dc02fc920e6f866e0e0ed407681ef5c4795e4e77 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Tue, 21 Dec 2010 13:53:34 -0800
Subject: [PATCH] getlimits: port to hosts with very wide int, or non-ASCII

* src/getlimits.c (decimal_ascii_add): Remove, replacing with ...
(decimal_absval_add_one): New function, with different signature,
which does not assume ASCII.  All callers changed.
(print_int): Remove assumptions that integers fit in 206 bits, and
that characters are ASCII.  These assumptions are portable in
practice but are easy to remove here.
---
 src/getlimits.c |   74 ++++++++++++++++++-------------------------------------
 1 files changed, 24 insertions(+), 50 deletions(-)

diff --git a/src/getlimits.c b/src/getlimits.c
index 93d4035..986a5d7 100644
--- a/src/getlimits.c
+++ b/src/getlimits.c
@@ -79,53 +79,31 @@ Output platform dependent limits in a format useful for shell scripts.\n\
   exit (status);
 }
 
-/* Add absolute values of ascii decimal strings.
- * Strings can have leading spaces.
- * If any string has a '-' it's preserved in the output:
- * I.E.
- *    1 +  1 ->  2
- *   -1 + -1 -> -2
- *   -1 +  1 -> -2
- *    1 + -1 -> -2
- */
-static char *
-decimal_ascii_add (const char *str1, const char *str2)
+/* Add one to the absolute value of the number whose textual
+   representation is BUF + 1.  Do this in-place, in the buffer.
+   Return a pointer to the result, which is normally BUF + 1, but is
+   BUF if the representation grew in size.  */
+static char const *
+decimal_absval_add_one (char *buf)
 {
-  int len1 = strlen (str1);
-  int len2 = strlen (str2);
-  int rlen = MAX (len1, len2) + 3;  /* space for extra digit or sign + NUL */
-  char *result = xmalloc (rlen);
-  char *rp = result + rlen - 1;
-  const char *d1 = str1 + len1 - 1;
-  const char *d2 = str2 + len2 - 1;
-  int carry = 0;
-  *rp = '\0';
-
-  while (1)
-    {
-      char c1 = (d1 < str1 ? ' ' : (*d1 == '-' ? ' ' : *d1--));
-      char c2 = (d2 < str2 ? ' ' : (*d2 == '-' ? ' ' : *d2--));
-      char t1 = c1 + c2 + carry;    /* ASCII digits are BCD */
-      if (!c_isdigit (c1) && !c_isdigit (c2) && !carry)
-        break;
-      carry = t1 > '0' + '9' || t1 == ' ' + '9' + 1;
-      t1 += 6 * carry;
-      *--rp = (t1 & 0x0F) | 0x30;   /* top nibble to ASCII */
-    }
-  if ((d1 >= str1 && *d1 == '-') || (d2 >= str2 && (*d2 == '-')))
-    *--rp = '-';
-
-  if (rp != result)
-    memmove (result, rp, rlen - (rp - result));
-
+  bool negative = (buf[1] == '-');
+  char *absnum = buf + 1 + negative;
+  char *p = absnum + strlen (absnum);
+  absnum[-1] = '0';
+  while (*--p == '9')
+    *p = '0';
+  ++*p;
+  char *result = MIN (absnum, p);
+  if (negative)
+    *--result = '-';
   return result;
 }
 
 int
 main (int argc, char **argv)
 {
-  char limit[64];               /* big enough for 128 bit integers at least */
-  char *oflow;
+  char limit[1 + MAX (INT_BUFSIZE_BOUND (intmax_t),
+                      INT_BUFSIZE_BOUND (uintmax_t))];
 
   initialize_main (&argc, &argv);
   set_program_name (argv[0]);
@@ -140,18 +118,14 @@ main (int argc, char **argv)
                       usage, AUTHORS, (char const *) NULL);
 
 #define print_int(TYPE)                                                  \
-  snprintf (limit, sizeof limit, "%"PRIuMAX, (uintmax_t)TYPE##_MAX);     \
-  printf (#TYPE"_MAX=%s\n", limit);                                      \
-  oflow = decimal_ascii_add (limit, "1");                                \
-  printf (#TYPE"_OFLOW=%s\n", oflow);                                    \
-  free (oflow);                                                          \
+  sprintf (limit + 1, "%"PRIuMAX, (uintmax_t) TYPE##_MAX);               \
+  printf (#TYPE"_MAX=%s\n", limit + 1);                                  \
+  printf (#TYPE"_OFLOW=%s\n", decimal_absval_add_one (limit));           \
   if (TYPE##_MIN)                                                        \
     {                                                                    \
-      snprintf (limit, sizeof limit, "%"PRIdMAX, (intmax_t)TYPE##_MIN);  \
-      printf (#TYPE"_MIN=%s\n", limit);                                  \
-      oflow = decimal_ascii_add (limit, "-1");                           \
-      printf (#TYPE"_UFLOW=%s\n", oflow);                                \
-      free (oflow);                                                      \
+      sprintf (limit + 1, "%"PRIdMAX, (intmax_t) TYPE##_MIN);            \
+      printf (#TYPE"_MIN=%s\n", limit + 1);                              \
+      printf (#TYPE"_UFLOW=%s\n", decimal_absval_add_one (limit));       \
     }
 
 #define print_float(TYPE)                                                \
-- 
1.7.2