}
\f
+/* Get grouping data, the separator and grouping info, by calling
+ localeconv(). The information is cached after the first call to
+ the function.
+
+ In locales that don't set a thousand separator (such as the "C"
+ locale), this forces it to be ",". We are now only showing
+ thousand separators in one place, so this shouldn't be a problem in
+ practice. */
+
static void
get_grouping_data (const char **sep, const char **grouping)
{
static bool initialized;
if (!initialized)
{
-#ifdef LC_NUMERIC
/* Get the grouping info from the locale. */
- struct lconv *lconv;
- const char *oldlocale = setlocale (LC_NUMERIC, "");
- lconv = localeconv ();
- cached_sep = xstrdup (lconv->thousands_sep);
- cached_grouping = xstrdup (lconv->grouping);
- /* Restore the locale to previous settings. */
- setlocale (LC_NUMERIC, oldlocale);
- if (!cached_sep)
-#endif
- /* Force separator for locales that specify no separators
- ("C", "hr", and probably many more.) */
- cached_sep = ",", cached_grouping = "\x03";
+ struct lconv *lconv = localeconv ();
+ cached_sep = lconv->thousands_sep;
+ cached_grouping = lconv->grouping;
+ if (!*cached_sep)
+ {
+ /* Many locales (such as "C" or "hr_HR") don't specify
+ grouping, which we still want to use it for legibility.
+ In those locales set the sep char to ',', unless that
+ character is used for decimal point, in which case set it
+ to " ". */
+ if (*lconv->decimal_point != ',')
+ cached_sep = ",";
+ else
+ cached_sep = " ";
+ cached_grouping = "\x03";
+ }
initialized = true;
}
*sep = cached_sep;
*grouping = cached_grouping;
}
-
/* Return a printed representation of N with thousand separators.
This should respect locale settings, with the exception of the "C"
locale which mandates no separator, but we use one anyway.
int i = 0, groupsize;
const char *atgroup;
+ bool negative = n < 0;
+
/* Initialize grouping data. */
get_grouping_data (&sep, &grouping);
seplen = strlen (sep);
atgroup = grouping;
groupsize = *atgroup++;
+ /* This will overflow on WGINT_MIN, but we're not using this to
+ print negative numbers anyway. */
+ if (negative)
+ n = -n;
+
/* Write the number into the buffer, backwards, inserting the
separators as necessary. */
*--p = '\0';
groupsize = *atgroup++;
}
}
+ if (negative)
+ *--p = '-';
+
return p;
}
*this* power. */
if ((n / 1024) < 1024 || i == countof (powers) - 1)
{
- /* Must cast to long first because MS VC can't directly cast
- __int64 to double. (This is safe because N is known to
- be < 1024^2, so always fits into long.) */
- double val = (double) (long) n / 1024.0;
+ double val = n / 1024.0;
/* Print values smaller than 10 with one decimal digits, and
others without any decimals. */
snprintf (buf, sizeof (buf), "%.*f%c",
#undef PR
#undef W
+#undef SPRINTF_WGINT
#undef DIGITS_1
#undef DIGITS_2
#undef DIGITS_3