diff options
Diffstat (limited to 'stdio-common')
-rw-r--r-- | stdio-common/Makefile | 4 | ||||
-rw-r--r-- | stdio-common/_itoa.c | 57 | ||||
-rw-r--r-- | stdio-common/_itoa.h | 13 | ||||
-rw-r--r-- | stdio-common/_itowa.c | 41 | ||||
-rw-r--r-- | stdio-common/bug17.c | 31 |
5 files changed, 100 insertions, 46 deletions
diff --git a/stdio-common/Makefile b/stdio-common/Makefile index 37bcdb3bc8..98220550f4 100644 --- a/stdio-common/Makefile +++ b/stdio-common/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1991-2002,2003,2004,2005,2006 Free Software Foundation, Inc. +# Copyright (C) 1991-2006, 2007 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -54,7 +54,7 @@ tests := tstscanf test_rdwr test-popen tstgetln test-fseek \ tst-swprintf tst-fseek tst-fmemopen test-vfprintf tst-gets \ tst-perror tst-sprintf tst-rndseek tst-fdopen tst-fphex bug14 bug15 \ tst-popen tst-unlockedio tst-fmemopen2 tst-put-error tst-fgets \ - tst-fwrite bug16 + tst-fwrite bug16 bug17 test-srcs = tst-unbputc tst-printf diff --git a/stdio-common/_itoa.c b/stdio-common/_itoa.c index f61b23fceb..373843f1cd 100644 --- a/stdio-common/_itoa.c +++ b/stdio-common/_itoa.c @@ -1,5 +1,5 @@ /* Internal function for converting integers to ASCII. - Copyright (C) 1994, 1995, 1996, 1999, 2000, 2002, 2003, 2004 + Copyright (C) 1994, 1995, 1996, 1999, 2000, 2002, 2003, 2004, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Torbjorn Granlund <tege@matematik.su.se> @@ -22,6 +22,7 @@ #include <gmp-mparam.h> #include <gmp.h> +#include <limits.h> #include <stdlib/gmp-impl.h> #include <stdlib/longlong.h> @@ -78,10 +79,12 @@ struct base_table_t #endif +/* We do not compile _itoa if we always can use _itoa_word. */ +#if LLONG_MAX != LONG_MAX /* Local variables. */ const struct base_table_t _itoa_base_table[] attribute_hidden = { -#if BITS_PER_MP_LIMB == 64 +# if BITS_PER_MP_LIMB == 64 /* 2 */ {SEL1(0ull) 1, 1}, /* 3 */ {SEL1(0xaaaaaaaaaaaaaaabull) 0, 1}, /* 4 */ {SEL1(0ull) 1, 2}, @@ -117,8 +120,8 @@ const struct base_table_t _itoa_base_table[] attribute_hidden = /* 34 */ {SEL1(0xf0f0f0f0f0f0f0f1ull) 0, 5}, /* 35 */ {SEL1(0xea0ea0ea0ea0ea0full) 0, 5}, /* 36 */ {SEL1(0xe38e38e38e38e38full) 0, 5} -#endif -#if BITS_PER_MP_LIMB == 32 +# endif +# if BITS_PER_MP_LIMB == 32 /* 2 */ {SEL1(0ul) 1, 1, {0, 31, 0x80000000ul SEL2(0xfffffffful)}}, /* 3 */ {SEL1(0xaaaaaaabul) 0, 1, {0, 20, 0xcfd41b91ul SEL2(0x3b563c24ul)}}, /* 4 */ {SEL1(0ul) 1, 2, {1, 15, 0x40000000ul SEL2(0xfffffffful)}}, @@ -154,8 +157,9 @@ const struct base_table_t _itoa_base_table[] attribute_hidden = /* 34 */ {SEL1(0xf0f0f0f1ul) 0, 5, {1, 6, 0x5c13d840ul SEL2(0x63dfc229ul)}}, /* 35 */ {SEL1(0xd41d41d5ul) 1, 6, {1, 6, 0x6d91b519ul SEL2(0x2b0fee30ul)}}, /* 36 */ {SEL1(0x38e38e39ul) 0, 3, {0, 6, 0x81bf1000ul SEL2(0xf91bd1b6ul)}} -#endif +# endif }; +#endif /* Lower-case digits. */ extern const char _itoa_lower_digits[]; @@ -201,6 +205,7 @@ _itoa_word (unsigned long value, char *buflim, #undef SPECIAL +#if LLONG_MAX != LONG_MAX char * _itoa (value, buflim, base, upper_case) unsigned long long int value; @@ -215,7 +220,7 @@ _itoa (value, buflim, base, upper_case) switch (base) { -#define RUN_2N(BITS) \ +# define RUN_2N(BITS) \ do \ { \ /* `unsigned long long int' always has 64 bits. */ \ @@ -269,7 +274,8 @@ _itoa (value, buflim, base, upper_case) default: { -#if BITS_PER_MP_LIMB == 64 + char *bufend = buflim; +# if BITS_PER_MP_LIMB == 64 mp_limb_t base_multiplier = brec->base_multiplier; if (brec->flag) while (value != 0) @@ -293,8 +299,8 @@ _itoa (value, buflim, base, upper_case) *--buflim = digits[rem]; value = quo; } -#endif -#if BITS_PER_MP_LIMB == 32 +# endif +# if BITS_PER_MP_LIMB == 32 mp_limb_t t[3]; int n; @@ -302,11 +308,11 @@ _itoa (value, buflim, base, upper_case) Optimize for frequent cases of 32 bit numbers. */ if ((mp_limb_t) (value >> 32) >= 1) { -#if UDIV_TIME > 2 * UMUL_TIME || UDIV_NEEDS_NORMALIZATION +# if UDIV_TIME > 2 * UMUL_TIME || UDIV_NEEDS_NORMALIZATION int big_normalization_steps = brec->big.normalization_steps; mp_limb_t big_base_norm = brec->big.base << big_normalization_steps; -#endif +# endif if ((mp_limb_t) (value >> 32) >= brec->big.base) { mp_limb_t x1hi, x1lo, r; @@ -315,7 +321,7 @@ _itoa (value, buflim, base, upper_case) always be very small. It might be faster just to subtract in a tight loop. */ -#if UDIV_TIME > 2 * UMUL_TIME +# if UDIV_TIME > 2 * UMUL_TIME mp_limb_t x, xh, xl; if (big_normalization_steps == 0) @@ -340,7 +346,7 @@ _itoa (value, buflim, base, upper_case) udiv_qrnnd_preinv (t[0], x, xh, xl, big_base_norm, brec->big.base_ninv); t[1] = x >> big_normalization_steps; -#elif UDIV_NEEDS_NORMALIZATION +# elif UDIV_NEEDS_NORMALIZATION mp_limb_t x, xh, xl; if (big_normalization_steps == 0) @@ -362,17 +368,17 @@ _itoa (value, buflim, base, upper_case) xl = x1lo << big_normalization_steps; udiv_qrnnd (t[0], x, xh, xl, big_base_norm); t[1] = x >> big_normalization_steps; -#else +# else udiv_qrnnd (x1hi, r, 0, (mp_limb_t) (value >> 32), brec->big.base); udiv_qrnnd (x1lo, t[2], r, (mp_limb_t) value, brec->big.base); udiv_qrnnd (t[0], t[1], x1hi, x1lo, brec->big.base); -#endif +# endif n = 3; } else { -#if (UDIV_TIME > 2 * UMUL_TIME) +# if UDIV_TIME > 2 * UMUL_TIME mp_limb_t x; value <<= brec->big.normalization_steps; @@ -380,17 +386,17 @@ _itoa (value, buflim, base, upper_case) (mp_limb_t) value, big_base_norm, brec->big.base_ninv); t[1] = x >> brec->big.normalization_steps; -#elif UDIV_NEEDS_NORMALIZATION +# elif UDIV_NEEDS_NORMALIZATION mp_limb_t x; value <<= big_normalization_steps; udiv_qrnnd (t[0], x, (mp_limb_t) (value >> 32), (mp_limb_t) value, big_base_norm); t[1] = x >> big_normalization_steps; -#else +# else udiv_qrnnd (t[0], t[1], (mp_limb_t) (value >> 32), (mp_limb_t) value, brec->big.base); -#endif +# endif n = 2; } } @@ -406,7 +412,7 @@ _itoa (value, buflim, base, upper_case) mp_limb_t ti = t[--n]; int ndig_for_this_limb = 0; -#if UDIV_TIME > 2 * UMUL_TIME +# if UDIV_TIME > 2 * UMUL_TIME mp_limb_t base_multiplier = brec->base_multiplier; if (brec->flag) while (ti != 0) @@ -432,7 +438,7 @@ _itoa (value, buflim, base, upper_case) ti = quo; ++ndig_for_this_limb; } -#else +# else while (ti != 0) { mp_limb_t quo, rem; @@ -443,7 +449,7 @@ _itoa (value, buflim, base, upper_case) ti = quo; ++ndig_for_this_limb; } -#endif +# endif /* If this wasn't the most significant word, pad with zeros. */ if (n != 0) while (ndig_for_this_limb < brec->big.ndigits) @@ -453,13 +459,16 @@ _itoa (value, buflim, base, upper_case) } } while (n != 0); -#endif +# endif + if (buflim == bufend) + *--buflim = '0'; } break; } return buflim; } +#endif char * _fitoa_word (unsigned long value, char *buf, unsigned int base, int upper_case) @@ -471,6 +480,7 @@ _fitoa_word (unsigned long value, char *buf, unsigned int base, int upper_case) return buf; } +#if LLONG_MAX != LONG_MAX char * _fitoa (unsigned long long value, char *buf, unsigned int base, int upper_case) { @@ -480,3 +490,4 @@ _fitoa (unsigned long long value, char *buf, unsigned int base, int upper_case) *buf++ = *cp++; return buf; } +#endif diff --git a/stdio-common/_itoa.h b/stdio-common/_itoa.h index 21a9c39294..6d9812fe32 100644 --- a/stdio-common/_itoa.h +++ b/stdio-common/_itoa.h @@ -1,5 +1,5 @@ /* Internal function for converting integers to ASCII. - Copyright (C) 1994,95,96,97,98,99,2002,2003 Free Software Foundation, Inc. + Copyright (C) 1994-1999,2002,2003,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -19,7 +19,8 @@ #ifndef _ITOA_H #define _ITOA_H -#include <sys/cdefs.h> + +#include <limits.h> /* Convert VALUE into ASCII in base BASE (2..36). Write backwards starting the character just before BUFLIM. @@ -81,4 +82,12 @@ extern char *_fitoa_word (unsigned long value, char *buf, unsigned int base, extern char *_fitoa (unsigned long long value, char *buf, unsigned int base, int upper_case) attribute_hidden; +#if LONG_MAX == LLONG_MAX +/* No need for special long long versions. */ +# define _itoa(value, buf, base, upper_case) \ + _itoa_word (value, buf, base, upper_case) +# define _fitoa(value, buf, base, upper_case) \ + _fitoa_word (value, buf, base, upper_case) +#endif + #endif /* itoa.h */ diff --git a/stdio-common/_itowa.c b/stdio-common/_itowa.c index b9cc341dd9..09a961dfaf 100644 --- a/stdio-common/_itowa.c +++ b/stdio-common/_itowa.c @@ -1,5 +1,5 @@ /* Internal function for converting integers to ASCII. - Copyright (C) 1994,1995,1996,1999,2000,2002 Free Software Foundation, Inc. + Copyright (C) 1994-1996,1999,2000,2002,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Torbjorn Granlund <tege@matematik.su.se> and Ulrich Drepper <drepper@gnu.org>. @@ -21,6 +21,7 @@ #include <gmp-mparam.h> #include <gmp.h> +#include <limits.h> #include <stdlib/gmp-impl.h> #include <stdlib/longlong.h> @@ -85,6 +86,7 @@ extern const wchar_t _itowa_lower_digits[] attribute_hidden; extern const wchar_t _itowa_upper_digits[] attribute_hidden; +#if LLONG_MAX != LONG_MAX wchar_t * _itowa (value, buflim, base, upper_case) unsigned long long int value; @@ -99,7 +101,7 @@ _itowa (value, buflim, base, upper_case) switch (base) { -#define RUN_2N(BITS) \ +# define RUN_2N(BITS) \ do \ { \ /* `unsigned long long int' always has 64 bits. */ \ @@ -153,7 +155,7 @@ _itowa (value, buflim, base, upper_case) default: { -#if BITS_PER_MP_LIMB == 64 +# if BITS_PER_MP_LIMB == 64 mp_limb_t base_multiplier = brec->base_multiplier; if (brec->flag) while (value != 0) @@ -177,8 +179,8 @@ _itowa (value, buflim, base, upper_case) *--bp = digits[rem]; value = quo; } -#endif -#if BITS_PER_MP_LIMB == 32 +# endif +# if BITS_PER_MP_LIMB == 32 mp_limb_t t[3]; int n; @@ -186,11 +188,11 @@ _itowa (value, buflim, base, upper_case) Optimize for frequent cases of 32 bit numbers. */ if ((mp_limb_t) (value >> 32) >= 1) { -#if UDIV_TIME > 2 * UMUL_TIME || UDIV_NEEDS_NORMALIZATION +# if UDIV_TIME > 2 * UMUL_TIME || UDIV_NEEDS_NORMALIZATION int big_normalization_steps = brec->big.normalization_steps; mp_limb_t big_base_norm = brec->big.base << big_normalization_steps; -#endif +# endif if ((mp_limb_t) (value >> 32) >= brec->big.base) { mp_limb_t x1hi, x1lo, r; @@ -199,7 +201,7 @@ _itowa (value, buflim, base, upper_case) always be very small. It might be faster just to subtract in a tight loop. */ -#if UDIV_TIME > 2 * UMUL_TIME +# if UDIV_TIME > 2 * UMUL_TIME mp_limb_t x, xh, xl; if (big_normalization_steps == 0) @@ -224,7 +226,7 @@ _itowa (value, buflim, base, upper_case) udiv_qrnnd_preinv (t[0], x, xh, xl, big_base_norm, brec->big.base_ninv); t[1] = x >> big_normalization_steps; -#elif UDIV_NEEDS_NORMALIZATION +# elif UDIV_NEEDS_NORMALIZATION mp_limb_t x, xh, xl; if (big_normalization_steps == 0) @@ -246,17 +248,17 @@ _itowa (value, buflim, base, upper_case) xl = x1lo << big_normalization_steps; udiv_qrnnd (t[0], x, xh, xl, big_base_norm); t[1] = x >> big_normalization_steps; -#else +# else udiv_qrnnd (x1hi, r, 0, (mp_limb_t) (value >> 32), brec->big.base); udiv_qrnnd (x1lo, t[2], r, (mp_limb_t) value, brec->big.base); udiv_qrnnd (t[0], t[1], x1hi, x1lo, brec->big.base); -#endif +# endif n = 3; } else { -#if (UDIV_TIME > 2 * UMUL_TIME) +# if UDIV_TIME > 2 * UMUL_TIME mp_limb_t x; value <<= brec->big.normalization_steps; @@ -264,17 +266,17 @@ _itowa (value, buflim, base, upper_case) (mp_limb_t) value, big_base_norm, brec->big.base_ninv); t[1] = x >> brec->big.normalization_steps; -#elif UDIV_NEEDS_NORMALIZATION +# elif UDIV_NEEDS_NORMALIZATION mp_limb_t x; value <<= big_normalization_steps; udiv_qrnnd (t[0], x, (mp_limb_t) (value >> 32), (mp_limb_t) value, big_base_norm); t[1] = x >> big_normalization_steps; -#else +# else udiv_qrnnd (t[0], t[1], (mp_limb_t) (value >> 32), (mp_limb_t) value, brec->big.base); -#endif +# endif n = 2; } } @@ -290,7 +292,7 @@ _itowa (value, buflim, base, upper_case) mp_limb_t ti = t[--n]; int ndig_for_this_limb = 0; -#if UDIV_TIME > 2 * UMUL_TIME +# if UDIV_TIME > 2 * UMUL_TIME mp_limb_t base_multiplier = brec->base_multiplier; if (brec->flag) while (ti != 0) @@ -316,7 +318,7 @@ _itowa (value, buflim, base, upper_case) ti = quo; ++ndig_for_this_limb; } -#else +# else while (ti != 0) { mp_limb_t quo, rem; @@ -327,7 +329,7 @@ _itowa (value, buflim, base, upper_case) ti = quo; ++ndig_for_this_limb; } -#endif +# endif /* If this wasn't the most significant word, pad with zeros. */ if (n != 0) while (ndig_for_this_limb < brec->big.ndigits) @@ -337,10 +339,11 @@ _itowa (value, buflim, base, upper_case) } } while (n != 0); -#endif +# endif } break; } return bp; } +#endif diff --git a/stdio-common/bug17.c b/stdio-common/bug17.c new file mode 100644 index 0000000000..2ef398674b --- /dev/null +++ b/stdio-common/bug17.c @@ -0,0 +1,31 @@ +#include <stdio.h> +#include <string.h> + +static int +do_test (void) +{ + static const char expect[] = "0, 0, 0"; + char buf[100]; + int status = 0; + + static const char fmt1[] = "%0d, %0ld, %0lld"; + snprintf (buf, sizeof (buf), fmt1, 0, 0L, 0LL); + if (strcmp (buf, expect) != 0) + { + printf ("\"%s\": got \"%s\", expected \"%s\"\n", fmt1, buf, expect); + status = 1; + } + + static const char fmt2[] = "%0u, %0lu, %0llu"; + snprintf (buf, sizeof (buf), fmt2, 0u, 0uL, 0uLL); + if (strcmp (buf, expect) != 0) + { + printf ("\"%s\": got \"%s\", expected \"%s\"\n", fmt2, buf, expect); + status = 1; + } + + return status; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" |