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

Previous Next

Package: coreutils;

Reported by: Paul Eggert <eggert <at> cs.ucla.edu>

Date: Tue, 21 Dec 2010 22:08:02 UTC

Severity: normal

Tags: patch

Done: Pádraig Brady <P <at> draigBrady.com>

Bug is archived. No further changes may be made.

Full log


View this message in rfc822 format

From: help-debbugs <at> gnu.org (GNU bug Tracking System)
To: Pádraig Brady <P <at> draigBrady.com>
Cc: tracker <at> debbugs.gnu.org
Subject: bug#7701: closed ([PATCH] getlimits: port to hosts with very wide
 int, or non-ASCII)
Date: Tue, 21 Dec 2010 22:56:02 +0000
[Message part 1 (text/plain, inline)]
Your message dated Tue, 21 Dec 2010 22:58:33 +0000
with message-id <4D113119.5070103 <at> draigBrady.com>
and subject line Re: bug#7701: [PATCH] getlimits: port to hosts with very wide int, or non-ASCII
has caused the GNU bug report #7701,
regarding [PATCH] getlimits: port to hosts with very wide int, or non-ASCII
to be marked as done.

(If you believe you have received this mail in error, please contact
help-debbugs <at> gnu.org.)


-- 
7701: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=7701
GNU Bug Tracking System
Contact help-debbugs <at> gnu.org with problems
[Message part 2 (message/rfc822, inline)]
From: Paul Eggert <eggert <at> cs.ucla.edu>
To: bug-coreutils <at> gnu.org
Subject: [PATCH] getlimits: port to hosts with very wide int, or non-ASCII
Date: Tue, 21 Dec 2010 14:14:15 -0800
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 <eggert <at> cs.ucla.edu>
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



[Message part 3 (message/rfc822, inline)]
From: Pádraig Brady <P <at> draigBrady.com>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 7701-done <at> debbugs.gnu.org
Subject: Re: bug#7701: [PATCH] getlimits: port to hosts with very wide int,
	or non-ASCII
Date: Tue, 21 Dec 2010 22:58:33 +0000
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


This bug report was last modified 14 years and 156 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.