1
0
mirror of git://git.sv.gnu.org/coreutils.git synced 2026-04-21 11:16:16 +02:00

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.
This commit is contained in:
Paul Eggert
2010-12-22 23:11:05 -08:00
parent 8f90efd006
commit 83e0138480

View File

@@ -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) \