summaryrefslogtreecommitdiff
path: root/libc/stdio/stdio.c
diff options
context:
space:
mode:
authorManuel Novoa III <mjn3@codepoet.org>2002-11-03 20:13:27 +0000
committerManuel Novoa III <mjn3@codepoet.org>2002-11-03 20:13:27 +0000
commit868df46adcf4637aadd773cbe42521ef980370b2 (patch)
tree512d59a1be375a21a8419d604342354886a7a8a7 /libc/stdio/stdio.c
parent9333e4142260e5451277a7b50b49b9c636a93b64 (diff)
Implement locale-specific grouping in printf for base 10 integer conversions
when the grouping flag "'" is specified. Grouping for floating point values may wait until I do a rewrite of the floating pt to string code...
Diffstat (limited to 'libc/stdio/stdio.c')
-rw-r--r--libc/stdio/stdio.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/libc/stdio/stdio.c b/libc/stdio/stdio.c
index b0b046900..f75011aec 100644
--- a/libc/stdio/stdio.c
+++ b/libc/stdio/stdio.c
@@ -3308,6 +3308,15 @@ void _stdio_fdout(int fd, ...)
#define INTERNAL_DIV_MOD
#endif
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning REMINDER: move _uintmaxtostr to locale.c???
+#endif
+#include <locale.h>
+
+#ifndef __LOCALE_C_ONLY
+#define CUR_LOCALE (__global_locale)
+#endif /* __LOCALE_C_ONLY */
+
char *_uintmaxtostr(register char * __restrict bufend, uintmax_t uval,
int base, __UIM_CASE alphacase)
{
@@ -3316,6 +3325,11 @@ char *_uintmaxtostr(register char * __restrict bufend, uintmax_t uval,
#ifdef INTERNAL_DIV_MOD
unsigned int H, L, high, low, rh;
#endif
+#ifndef __LOCALE_C_ONLY
+ int grouping;
+ size_t gslen; /* This does not need to be initialized. */
+ const char *g; /* This does not need to be initialized. */
+#endif /* __LOCALE_C_ONLY */
negative = 0;
if (base < 0) { /* signed value */
@@ -3329,10 +3343,46 @@ char *_uintmaxtostr(register char * __restrict bufend, uintmax_t uval,
/* this is an internal routine -- we shouldn't need to check this */
assert(!((base < 2) || (base > 36)));
+#ifndef __LOCALE_C_ONLY
+ grouping = -1;
+ if (alphacase == __UIM_GROUP) {
+ assert(base == 10);
+ if (*(g = CUR_LOCALE.grouping)
+ && ((gslen = strlen(CUR_LOCALE.thousands_sep)) > 0)
+ ) {
+ grouping = *g;
+ }
+ }
+#endif /* __LOCALE_C_ONLY */
+
*bufend = '\0';
#ifndef INTERNAL_DIV_MOD
do {
+#ifndef __LOCALE_C_ONLY
+ if (!grouping) { /* Finished a group. */
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning REMINDER: decide about memcpy in _uintmaxtostr
+#endif
+#if 0
+ bufend -= gslen;
+ memcpy(bufend, CUR_LOCALE.thousands_sep, gslen);
+#else
+ grouping = gslen;
+ do {
+ *--bufend = CUR_LOCALE.thousands_sep[--grouping];
+ } while (grouping);
+#endif
+ if (g[1] != 0) { /* g[1] == 0 means repeat last grouping. */
+ /* Note: g[1] == -1 means no further grouping. But since
+ * we'll never wrap around, we can set grouping to -1 without
+ * fear of */
+ ++g;
+ }
+ grouping = *g;
+ }
+ --grouping;
+#endif /* __LOCALE_C_ONLY */
digit = uval % base;
uval /= base;
@@ -3351,6 +3401,31 @@ char *_uintmaxtostr(register char * __restrict bufend, uintmax_t uval,
high = (unsigned int) (uval >> (sizeof(unsigned int) * CHAR_BIT));
do {
+#ifndef __LOCALE_C_ONLY
+ if (!grouping) { /* Finished a group. */
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning REMINDER: decide about memcpy in _uintmaxtostr
+#endif
+#if 0
+ bufend -= gslen;
+ memcpy(bufend, CUR_LOCALE.thousands_sep, gslen);
+#else
+ grouping = gslen;
+ do {
+ *--bufend = CUR_LOCALE.thousands_sep[--grouping];
+ } while (grouping);
+#endif
+ if (g[1] != 0) { /* g[1] == 0 means repeat last grouping. */
+ /* Note: g[1] == -1 means no further grouping. But since
+ * we'll never wrap around, we can set grouping to -1 without
+ * fear of */
+ ++g;
+ }
+ grouping = *g;
+ }
+ --grouping;
+#endif /* __LOCALE_C_ONLY */
+
rh = high % base;
high /= base;
digit = (low % base) + (L * rh);