From deab9deadc372fe1a367aef2e78c0d8f2885bf23 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Tue, 17 Oct 1995 00:41:39 +0000 Subject: * Makefile (subdirs): Replace stdio with stdio-common and $(stdio). * configure.in: Grok arg --enable-libio. ($stdio = libio): Define USE_IN_LIBIO. * config.h.in (USE_IN_LIBIO): Add #undef. * config.make.in (stdio): New variable, set by configure. * Makeconfig (stdio): New variable. * stdio.h [USE_IN_LIBIO]: Include libio/stdio.h instead of stdio/stdio.h. * stdio-common/Makefile: New file. * stdio/Makefile: Half the contents moved to stdio-common/Makefile. * stdio/_itoa.c: Moved to stdio-common. * stdio/_itoa.h: Moved to stdio-common. * stdio/asprintf.c: Moved to stdio-common. * stdio/bug1.c: Moved to stdio-common. * stdio/bug1.input: Moved to stdio-common. * stdio/bug2.c: Moved to stdio-common. * stdio/bug3.c: Moved to stdio-common. * stdio/bug4.c: Moved to stdio-common. * stdio/bug5.c: Moved to stdio-common. * stdio/bug6.c: Moved to stdio-common. * stdio/bug6.input: Moved to stdio-common. * stdio/bug7.c: Moved to stdio-common. * stdio/dprintf.c: Moved to stdio-common. * stdio/errnobug.c: Moved to stdio-common. * stdio/getline.c: Moved to stdio-common. * stdio/getw.c: Moved to stdio-common. * stdio/perror.c: Moved to stdio-common. * stdio/printf-parse.h: Moved to stdio-common. * stdio/printf-prs.c: Moved to stdio-common. * stdio/printf.c: Moved to stdio-common. * stdio/printf.h: Moved to stdio-common. * stdio/printf_fp.c: Moved to stdio-common. * stdio/psignal.c: Moved to stdio-common. * stdio/putw.c: Moved to stdio-common. * stdio/reg-printf.c: Moved to stdio-common. * stdio/scanf.c: Moved to stdio-common. * stdio/snprintf.c: Moved to stdio-common. * stdio/sprintf.c: Moved to stdio-common. * stdio/sscanf.c: Moved to stdio-common. * stdio/tempnam.c: Moved to stdio-common. * stdio/temptest.c: Moved to stdio-common. * stdio/test-fseek.c: Moved to stdio-common. * stdio/test-fwrite.c: Moved to stdio-common. * stdio/test-popen.c: Moved to stdio-common. * stdio/test_rdwr.c: Moved to stdio-common. * stdio/tmpfile.c: Moved to stdio-common. * stdio/tmpnam.c: Moved to stdio-common. * stdio/tst-fileno.c: Moved to stdio-common. * stdio/tst-printf.c: Moved to stdio-common. * stdio/tstgetln.c: Moved to stdio-common. * stdio/tstgetln.input: Moved to stdio-common. * stdio/tstscanf.c: Moved to stdio-common. * stdio/tstscanf.input: Moved to stdio-common. * stdio/vfprintf.c: Moved to stdio-common. * stdio/vfscanf.c: Moved to stdio-common. * stdio/vprintf.c: Moved to stdio-common. * stdio/xbug.c: Moved to stdio-common. * sysdeps/generic/Makefile (siglist.c rules): Do this in subdir stdio-common instead of stdio. * sysdeps/unix/Makefile (errlist.c rules): Likewise. * stdio-common/asprintf.c [USE_IN_LIBIO]: Call libio primitive function. * stdio-common/dprintf.c: Likewise. * stdio-common/printf.c: Likewise. * stdio-common/scanf.c: Likewise. * stdio-common/snprintf.c: Likewise. * stdio-common/sprintf.c: Likewise. * stdio-common/sscanf.c: Likewise. * stdio-common/vprintf.c: Likewise. * Makerules: Include $(+depfiles) directly instead of generating depend-$(subdir). (depend-$(subdir)): Target removed. (common-clean): Don't remove depend-$(subdir). --- stdio/printf_fp.c | 990 ------------------------------------------------------ 1 file changed, 990 deletions(-) delete mode 100644 stdio/printf_fp.c (limited to 'stdio/printf_fp.c') diff --git a/stdio/printf_fp.c b/stdio/printf_fp.c deleted file mode 100644 index 28d13d61b8..0000000000 --- a/stdio/printf_fp.c +++ /dev/null @@ -1,990 +0,0 @@ -/* Floating point output for `printf'. -Copyright (C) 1995 Free Software Foundation, Inc. -Written by Ulrich Drepper. - -This file is part of the GNU C Library. - -The GNU C Library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as -published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. - -The GNU C Library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with the GNU C Library; see the file COPYING.LIB. If -not, write to the Free Software Foundation, Inc., 675 Mass Ave, -Cambridge, MA 02139, USA. */ - -#ifdef USE_IN_LIBIO -# include -#else -# include -#endif -#include -#include -#include -#include -#include -#include "../stdlib/gmp.h" -#include "../stdlib/gmp-impl.h" -#include "../stdlib/longlong.h" -#include "../stdlib/fpioconst.h" -#include "../locale/localeinfo.h" -#include -#include -#include -#include -#include -#include - -#define NDEBUG /* Undefine this for debugging assertions. */ -#include - -/* This defines make it possible to use the same code for GNU C library and - the GNU I/O library. */ -#ifdef USE_IN_LIBIO -# define PUT(f, s, n) _IO_sputn (f, s, n) -# define PAD(f, c, n) _IO_padn (f, c, n) -/* We use this file GNU C library and GNU I/O library. So make - names equal. */ -# undef putc -# define putc(c, f) _IO_putc (c, f) -# define size_t _IO_size_t -# define FILE _IO_FILE -#else /* ! USE_IN_LIBIO */ -# define PUT(f, s, n) fwrite (s, 1, n, f) -# define PAD(f, c, n) __printf_pad (f, c, n) -ssize_t __printf_pad __P ((FILE *, char pad, int n)); /* In vfprintf.c. */ -#endif /* USE_IN_LIBIO */ - -/* Macros for doing the actual output. */ - -#define outchar(ch) \ - do \ - { \ - register CONST int outc = (ch); \ - if (putc (outc, fp) == EOF) \ - return -1; \ - ++done; \ - } while (0) - -#define PRINT(ptr, len) \ - do \ - { \ - register size_t outlen = (len); \ - if (len > 20) \ - { \ - if (PUT (fp, ptr, outlen) != outlen) \ - return -1; \ - ptr += outlen; \ - done += outlen; \ - } \ - else \ - { \ - while (outlen-- > 0) \ - outchar (*ptr++); \ - } \ - } while (0) - -#define PADN(ch, len) \ - do \ - { \ - if (PAD (fp, ch, len) != len) \ - return -1; \ - done += len; \ - } \ - while (0) - -/* We use the GNU MP library to handle large numbers. - - An MP variable occupies a varying number of entries in its array. We keep - track of this number for efficiency reasons. Otherwise we would always - have to process the whole array. */ -#define MPN_VAR(name) mp_limb *name; mp_size_t name##size - -#define MPN_ASSIGN(dst,src) \ - memcpy (dst, src, (dst##size = src##size) * sizeof (mp_limb)) -#define MPN_GE(u,v) \ - (u##size > v##size || (u##size == v##size && __mpn_cmp (u, v, u##size) >= 0)) - -extern int __isinfl (long double), __isnanl (long double); - -extern mp_size_t __mpn_extract_double (mp_ptr res_ptr, mp_size_t size, - int *expt, int *is_neg, - double value); -extern mp_size_t __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size, - int *expt, int *is_neg, - long double value); - - -static unsigned int guess_grouping (unsigned int intdig_max, - const char *grouping, wchar_t sepchar); -static char *group_number (char *buf, char *bufend, unsigned int intdig_no, - const char *grouping, wchar_t thousands_sep); - - -int -__printf_fp (fp, info, args) - FILE *fp; - const struct printf_info *info; - const **const args; -{ - /* The floating-point value to output. */ - union - { - double dbl; - LONG_DOUBLE ldbl; - } - fpnum; - - /* Locale-dependent representation of decimal point. */ - wchar_t decimal; - - /* Locale-dependent thousands separator and grouping specification. */ - wchar_t thousands_sep; - const char *grouping; - - /* "NaN" or "Inf" for the special cases. */ - CONST char *special = NULL; - - /* We need just a few limbs for the input before shifting to the right - position. */ - mp_limb fp_input[(LDBL_MANT_DIG + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB]; - /* We need to shift the contents of fp_input by this amount of bits. */ - int to_shift; - - /* The significant of the floting-point value in question */ - MPN_VAR(frac); - /* and the exponent. */ - int exponent; - /* Sign of the exponent. */ - int expsign = 0; - /* Sign of float number. */ - int is_neg = 0; - - /* Scaling factor. */ - MPN_VAR(scale); - - /* Temporary bignum value. */ - MPN_VAR(tmp); - - /* Digit which is result of last hack_digit() call. */ - int digit; - - /* The type of output format that will be used: 'e'/'E' or 'f'. */ - int type; - - /* Counter for number of written characters. */ - int done = 0; - - /* General helper (carry limb). */ - mp_limb cy; - - char hack_digit (void) - { - mp_limb hi; - - if (expsign != 0 && type == 'f' && exponent-- > 0) - hi = 0; - else if (scalesize == 0) - { - hi = frac[fracsize - 1]; - cy = __mpn_mul_1 (frac, frac, fracsize - 1, 10); - frac[fracsize - 1] = cy; - } - else - { - if (fracsize < scalesize) - hi = 0; - else - { - hi = __mpn_divmod (tmp, frac, fracsize, scale, scalesize); - tmp[fracsize - scalesize] = hi; - hi = tmp[0]; - - fracsize = __mpn_normal_size (frac, scalesize); - if (fracsize == 0) - { - /* We're not prepared for an mpn variable with zero - limbs. */ - fracsize = 1; - return '0' + hi; - } - } - - cy = __mpn_mul_1 (frac, frac, fracsize, 10); - if (cy != 0) - frac[fracsize++] = cy; - } - - return '0' + hi; - } - - - /* Figure out the decimal point character. */ - if (mbtowc (&decimal, _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT), - strlen (_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT))) <= 0) - decimal = (wchar_t) *_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT); - - - if (info->group) - { - grouping = _NL_CURRENT (LC_NUMERIC, GROUPING); - if (*grouping <= 0 || *grouping == CHAR_MAX) - grouping = NULL; - else - { - /* Figure out the thousands seperator character. */ - if (mbtowc (&thousands_sep, _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP), - strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0) - thousands_sep = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP); - if (thousands_sep == L'\0') - grouping = NULL; - } - } - else - grouping = NULL; - - /* Fetch the argument value. */ - if (info->is_long_double && sizeof (long double) > sizeof (double)) - { - fpnum.ldbl = *(const long double *) args[0]; - - /* Check for special values: not a number or infinity. */ - if (__isnanl (fpnum.ldbl)) - { - special = "NaN"; - is_neg = 0; - } - else if (__isinfl (fpnum.ldbl)) - { - special = "Inf"; - is_neg = fpnum.ldbl < 0; - } - else - { - fracsize = __mpn_extract_long_double (fp_input, - (sizeof (fp_input) / - sizeof (fp_input[0])), - &exponent, &is_neg, - fpnum.ldbl); - to_shift = 1 + fracsize * BITS_PER_MP_LIMB - LDBL_MANT_DIG; - } - } - else - { - fpnum.dbl = *(const double *) args[0]; - - /* Check for special values: not a number or infinity. */ - if (__isnan (fpnum.dbl)) - { - special = "NaN"; - is_neg = 0; - } - else if (__isinf (fpnum.dbl)) - { - special = "Inf"; - is_neg = fpnum.dbl < 0; - } - else - { - fracsize = __mpn_extract_double (fp_input, - (sizeof (fp_input) - / sizeof (fp_input[0])), - &exponent, &is_neg, fpnum.dbl); - to_shift = 1 + fracsize * BITS_PER_MP_LIMB - DBL_MANT_DIG; - } - } - - if (special) - { - int width = info->prec > info->width ? info->prec : info->width; - - if (is_neg || info->showsign || info->space) - --width; - width -= 3; - - if (!info->left && width > 0) - PADN (' ', width); - - if (is_neg) - outchar ('-'); - else if (info->showsign) - outchar ('+'); - else if (info->space) - outchar (' '); - - PRINT (special, 3); - - if (info->left && width > 0) - PADN (' ', width); - - return done; - } - - - /* We need three multiprecision variables. Now that we have the exponent - of the number we can allocate the needed memory. It would be more - efficient to use variables of the fixed maximum size but because this - would be really big it could lead to memory problems. */ - { - mp_size_t bignum_size = ((ABS (exponent) + BITS_PER_MP_LIMB - 1) - / BITS_PER_MP_LIMB + 3) * sizeof (mp_limb); - frac = (mp_limb *) alloca (bignum_size); - tmp = (mp_limb *) alloca (bignum_size); - scale = (mp_limb *) alloca (bignum_size); - } - - /* We now have to distinguish between numbers with positive and negative - exponents because the method used for the one is not applicable/efficient - for the other. */ - scalesize = 0; - if (exponent > 2) - { - /* |FP| >= 1.0. */ - int scaleexpo = 0; - int explog = LDBL_MAX_10_EXP_LOG; - int exp10 = 0; - const struct mp_power *tens = &_fpioconst_pow10[explog + 1]; - int cnt_h, cnt_l, i; - - if ((exponent + to_shift) % BITS_PER_MP_LIMB == 0) - { - MPN_COPY_DECR (frac + (exponent + to_shift) / BITS_PER_MP_LIMB, - fp_input, fracsize); - fracsize += (exponent + to_shift) / BITS_PER_MP_LIMB; - } - else - { - cy = __mpn_lshift (frac + (exponent + to_shift) / BITS_PER_MP_LIMB, - fp_input, fracsize, - (exponent + to_shift) % BITS_PER_MP_LIMB); - fracsize += (exponent + to_shift) / BITS_PER_MP_LIMB; - if (cy) - frac[fracsize++] = cy; - } - MPN_ZERO (frac, (exponent + to_shift) / BITS_PER_MP_LIMB); - - assert (tens > &_fpioconst_pow10[0]); - do - { - --tens; - - /* The number of the product of two binary numbers with n and m - bits respectively has m+n or m+n-1 bits. */ - if (exponent >= scaleexpo + tens->p_expo - 1) - { - if (scalesize == 0) - MPN_ASSIGN (tmp, tens->array); - else - { - cy = __mpn_mul (tmp, scale, scalesize, - tens->array + 2, tens->arraysize - 2); - tmpsize = scalesize + tens->arraysize - 2; - if (cy == 0) - --tmpsize; - } - - if (MPN_GE (frac, tmp)) - { - int cnt; - MPN_ASSIGN (scale, tmp); - count_leading_zeros (cnt, scale[scalesize - 1]); - scaleexpo = (scalesize - 2) * BITS_PER_MP_LIMB - cnt - 1; - exp10 |= 1 << explog; - } - } - --explog; - } - while (tens > &_fpioconst_pow10[0]); - exponent = exp10; - - /* Optimize number representations. We want to represent the numbers - with the lowest number of bytes possible without losing any - bytes. Also the highest bit in the scaling factor has to be set - (this is a requirement of the MPN division routines). */ - if (scalesize > 0) - { - /* Determine minimum number of zero bits at the end of - both numbers. */ - for (i = 0; scale[i] == 0 && frac[i] == 0; i++) - ; - - /* Determine number of bits the scaling factor is misplaced. */ - count_leading_zeros (cnt_h, scale[scalesize - 1]); - - if (cnt_h == 0) - { - /* The highest bit of the scaling factor is already set. So - we only have to remove the trailing empty limbs. */ - if (i > 0) - { - MPN_COPY_INCR (scale, scale + i, scalesize - i); - scalesize -= i; - MPN_COPY_INCR (frac, frac + i, fracsize - i); - fracsize -= i; - } - } - else - { - if (scale[i] != 0) - { - count_trailing_zeros (cnt_l, scale[i]); - if (frac[i] != 0) - { - int cnt_l2; - count_trailing_zeros (cnt_l2, frac[i]); - if (cnt_l2 < cnt_l) - cnt_l = cnt_l2; - } - } - else - count_trailing_zeros (cnt_l, frac[i]); - - /* Now shift the numbers to their optimal position. */ - if (i == 0 && BITS_PER_MP_LIMB - cnt_h > cnt_l) - { - /* We cannot save any memory. So just roll both numbers - so that the scaling factor has its highest bit set. */ - - (void) __mpn_lshift (scale, scale, scalesize, cnt_h); - cy = __mpn_lshift (frac, frac, fracsize, cnt_h); - if (cy != 0) - frac[fracsize++] = cy; - } - else if (BITS_PER_MP_LIMB - cnt_h <= cnt_l) - { - /* We can save memory by removing the trailing zero limbs - and by packing the non-zero limbs which gain another - free one. */ - - (void) __mpn_rshift (scale, scale + i, scalesize - i, - BITS_PER_MP_LIMB - cnt_h); - scalesize -= i + 1; - (void) __mpn_rshift (frac, frac + i, fracsize - i, - BITS_PER_MP_LIMB - cnt_h); - fracsize -= frac[fracsize - i - 1] == 0 ? i + 1 : i; - } - else - { - /* We can only save the memory of the limbs which are zero. - The non-zero parts occupy the same number of limbs. */ - - (void) __mpn_rshift (scale, scale + (i - 1), - scalesize - (i - 1), - BITS_PER_MP_LIMB - cnt_h); - scalesize -= i; - (void) __mpn_rshift (frac, frac + (i - 1), - fracsize - (i - 1), - BITS_PER_MP_LIMB - cnt_h); - fracsize -= frac[fracsize - (i - 1) - 1] == 0 ? i : i - 1; - } - } - } - } - else if (exponent < 0) - { - /* |FP| < 1.0. */ - int exp10 = 0; - int explog = LDBL_MAX_10_EXP_LOG; - const struct mp_power *tens = &_fpioconst_pow10[explog + 1]; - mp_size_t used_limbs = fracsize - 1; - - /* Now shift the input value to its right place. */ - cy = __mpn_lshift (frac, fp_input, fracsize, to_shift); - frac[fracsize++] = cy; - assert (cy == 1 || (frac[fracsize - 2] == 0 && frac[0] == 0)); - - expsign = 1; - exponent = -exponent; - - assert (tens != &_fpioconst_pow10[0]); - do - { - --tens; - - if (exponent >= tens->m_expo) - { - int i, incr, cnt_h, cnt_l; - mp_limb topval[2]; - - /* The __mpn_mul function expects the first argument to be - bigger than the second. */ - if (fracsize < tens->arraysize - 2) - cy = __mpn_mul (tmp, &tens->array[2], tens->arraysize - 2, - frac, fracsize); - else - cy = __mpn_mul (tmp, frac, fracsize, - &tens->array[2], tens->arraysize - 2); - tmpsize = fracsize + tens->arraysize - 2; - if (cy == 0) - --tmpsize; - - count_leading_zeros (cnt_h, tmp[tmpsize - 1]); - incr = (tmpsize - fracsize) * BITS_PER_MP_LIMB - + BITS_PER_MP_LIMB - 1 - cnt_h; - - assert (incr <= tens->p_expo); - - /* If we increased the exponent by exactly 3 we have to test - for overflow. This is done by comparing with 10 shifted - to the right position. */ - if (incr == exponent + 3) - if (cnt_h <= BITS_PER_MP_LIMB - 4) - { - topval[0] = 0; - topval[1] = 10 << (BITS_PER_MP_LIMB - 4 - cnt_h); - } - else - { - topval[0] = 10 << (BITS_PER_MP_LIMB - 4); - topval[1] = 0; - (void) __mpn_lshift (topval, topval, 2, - BITS_PER_MP_LIMB - cnt_h); - } - - /* We have to be careful when multiplying the last factor. - If the result is greater than 1.0 be have to test it - against 10.0. If it is greater or equal to 10.0 the - multiplication was not valid. This is because we cannot - determine the number of bits in the result in advance. */ - if (incr < exponent + 3 - || (incr == exponent + 3 && - (tmp[tmpsize - 1] < topval[1] - || (tmp[tmpsize - 1] == topval[1] - && tmp[tmpsize - 2] < topval[0])))) - { - /* The factor is right. Adapt binary and decimal - exponents. */ - exponent -= incr; - exp10 |= 1 << explog; - - /* If this factor yields a number greater or equal to - 1.0, we must not shift the non-fractional digits down. */ - if (exponent < 0) - cnt_h += -exponent; - - /* Now we optimize the number representation. */ - for (i = 0; tmp[i] == 0; ++i); - if (cnt_h == BITS_PER_MP_LIMB - 1) - { - MPN_COPY (frac, tmp + i, tmpsize - i); - fracsize = tmpsize - i; - } - else - { - count_trailing_zeros (cnt_l, tmp[i]); - - /* Now shift the numbers to their optimal position. */ - if (i == 0 && BITS_PER_MP_LIMB - 1 - cnt_h > cnt_l) - { - /* We cannot save any memory. Just roll the - number so that the leading digit is in a - seperate limb. */ - - cy = __mpn_lshift (frac, tmp, tmpsize, cnt_h + 1); - fracsize = tmpsize + 1; - frac[fracsize - 1] = cy; - } - else if (BITS_PER_MP_LIMB - 1 - cnt_h <= cnt_l) - { - (void) __mpn_rshift (frac, tmp + i, tmpsize - i, - BITS_PER_MP_LIMB - 1 - cnt_h); - fracsize = tmpsize - i; - } - else - { - /* We can only save the memory of the limbs which - are zero. The non-zero parts occupy the same - number of limbs. */ - - (void) __mpn_rshift (frac, tmp + (i - 1), - tmpsize - (i - 1), - BITS_PER_MP_LIMB - 1 - cnt_h); - fracsize = tmpsize - (i - 1); - } - } - used_limbs = fracsize - 1; - } - } - --explog; - } - while (tens != &_fpioconst_pow10[1] && exponent > 0); - /* All factors but 10^-1 are tested now. */ - if (exponent > 0) - { - cy = __mpn_mul_1 (tmp, frac, fracsize, 10); - tmpsize = fracsize; - assert (cy == 0 || tmp[tmpsize - 1] < 20); - - (void) __mpn_rshift (frac, tmp, tmpsize, MIN (4, exponent)); - fracsize = tmpsize; - exp10 |= 1; - assert (frac[fracsize - 1] < 10); - } - exponent = exp10; - } - else - { - /* This is a special case. We don't need a factor because the - numbers are in the range of 0.0 <= fp < 8.0. We simply - shift it to the right place and divide it by 1.0 to get the - leading digit. (Of course this division is not really made.) */ - assert (0 <= exponent && exponent < 3 && - exponent + to_shift < BITS_PER_MP_LIMB); - - /* Now shift the input value to its right place. */ - cy = __mpn_lshift (frac, fp_input, fracsize, (exponent + to_shift)); - frac[fracsize++] = cy; - exponent = 0; - } - - { - int width = info->width; - char *buffer, *startp, *cp; - int chars_needed; - int expscale; - int intdig_max, intdig_no = 0; - int fracdig_min, fracdig_max, fracdig_no = 0; - int dig_max; - int significant; - - if (tolower (info->spec) == 'e') - { - type = info->spec; - intdig_max = 1; - fracdig_min = fracdig_max = info->prec < 0 ? 6 : info->prec; - chars_needed = 1 + 1 + fracdig_max + 1 + 1 + 4; - /* d . ddd e +- ddd */ - dig_max = INT_MAX; /* Unlimited. */ - significant = 1; /* Does not matter here. */ - } - else if (info->spec == 'f') - { - type = 'f'; - fracdig_min = fracdig_max = info->prec < 0 ? 6 : info->prec; - if (expsign == 0) - { - intdig_max = exponent + 1; - /* This can be really big! */ /* XXX Maybe malloc if too big? */ - chars_needed = exponent + 1 + 1 + fracdig_max; - } - else - { - intdig_max = 1; - chars_needed = 1 + 1 + fracdig_max; - } - dig_max = INT_MAX; /* Unlimited. */ - significant = 1; /* Does not matter here. */ - } - else - { - dig_max = info->prec < 0 ? 6 : (info->prec == 0 ? 1 : info->prec); - if ((expsign == 0 && exponent >= dig_max) - || (expsign != 0 && exponent > 4)) - { - type = isupper (info->spec) ? 'E' : 'e'; - fracdig_max = dig_max - 1; - intdig_max = 1; - chars_needed = 1 + 1 + fracdig_max + 1 + 1 + 4; - } - else - { - type = 'f'; - intdig_max = expsign == 0 ? exponent + 1 : 0; - fracdig_max = dig_max - intdig_max; - /* We need space for the significant digits and perhaps for - leading zeros when < 1.0. Pessimistic guess: dig_max. */ - chars_needed = dig_max + dig_max + 1; - } - fracdig_min = info->alt ? fracdig_max : 0; - significant = 0; /* We count significant digits. */ - } - - if (grouping) - /* Guess the number of groups we will make, and thus how - many spaces we need for separator characters. */ - chars_needed += guess_grouping (intdig_max, grouping, thousands_sep); - - /* Allocate buffer for output. We need two more because while rounding - it is possible that we need two more characters in front of all the - other output. */ - buffer = alloca (2 + chars_needed); - cp = startp = buffer + 2; /* Let room for rounding. */ - - /* Do the real work: put digits in allocated buffer. */ - if (expsign == 0 || type != 'f') - { - assert (expsign == 0 || intdig_max == 1); - while (intdig_no < intdig_max) - { - ++intdig_no; - *cp++ = hack_digit (); - } - significant = 1; - if (info->alt - || fracdig_min > 0 - || (fracdig_max > 0 && (fracsize > 1 || frac[0] != 0))) - *cp++ = decimal; - } - else - { - /* |fp| < 1.0 and the selected type is 'f', so put "0." - in the buffer. */ - *cp++ = '0'; - --exponent; - *cp++ = decimal; - } - - /* Generate the needed number of fractional digits. */ - while (fracdig_no < fracdig_min - || (fracdig_no < fracdig_max && (fracsize > 1 || frac[0] != 0))) - { - ++fracdig_no; - *cp = hack_digit (); - if (*cp != '0') - significant = 1; - else if (significant == 0) - { - ++fracdig_max; - if (fracdig_min > 0) - ++fracdig_min; - } - ++cp; - } - - /* Do rounding. */ - digit = hack_digit (); - if (digit > '4') - { - char *tp = cp; - - if (digit == '5') - /* This is the critical case. */ - if (fracsize == 1 && frac[0] == 0) - /* Rest of the number is zero -> round to even. - (IEEE 754-1985 4.1 says this is the default rounding.) */ - if ((*(cp - 1) & 1) == 0) - goto do_expo; - - if (fracdig_no > 0) - { - /* Process fractional digits. Terminate if not rounded or - radix character is reached. */ - while (*--tp != decimal && *tp == '9') - *tp = '0'; - if (*tp != decimal) - /* Round up. */ - (*tp)++; - } - - if (fracdig_no == 0 || *tp == decimal) - { - /* Round the integer digits. */ - if (*(tp - 1) == decimal) - --tp; - - while (--tp >= startp && *tp == '9') - *tp = '0'; - - if (tp >= startp) - /* Round up. */ - (*tp)++; - else - /* It is more citical. All digits were 9's. */ - { - if (type != 'f') - { - *startp = '1'; - exponent += expsign == 0 ? 1 : -1; - } - else if (intdig_no == dig_max) - { - /* This is the case where for type %g the number fits - really in the range for %f output but after rounding - the number of digits is too big. */ - *--startp = decimal; - *--startp = '1'; - - if (info->alt || fracdig_no > 0) - { - /* Overwrite the old radix character. */ - startp[intdig_no + 2] = '0'; - ++fracdig_no; - } - - fracdig_no += intdig_no; - intdig_no = 1; - fracdig_max = intdig_max - intdig_no; - ++exponent; - /* Now we must print the exponent. */ - type = isupper (info->spec) ? 'E' : 'e'; - } - else - { - /* We can simply add another another digit before the - radix. */ - *--startp = '1'; - ++intdig_no; - } - - /* While rounding the number of digits can change. - If the number now exceeds the limits remove some - fractional digits. */ - if (intdig_no + fracdig_no > dig_max) - { - cp -= intdig_no + fracdig_no - dig_max; - fracdig_no -= intdig_no + fracdig_no - dig_max; - } - } - } - } - - do_expo: - /* Now remove unnecessary '0' at the end of the string. */ - while (fracdig_no > fracdig_min && *(cp - 1) == '0') - { - --cp; - --fracdig_no; - } - /* If we eliminate all fractional digits we perhaps also can remove - the radix character. */ - if (fracdig_no == 0 && !info->alt && *(cp - 1) == decimal) - --cp; - - if (grouping) - /* Add in separator characters, overwriting the same buffer. */ - cp = group_number (startp, cp, intdig_no, grouping, thousands_sep); - - /* Write the exponent if it is needed. */ - if (type != 'f') - { - *cp++ = type; - *cp++ = expsign ? '-' : '+'; - - /* Find the magnitude of the exponent. */ - expscale = 10; - while (expscale <= exponent) - expscale *= 10; - - if (exponent < 10) - /* Exponent always has at least two digits. */ - *cp++ = '0'; - else - do - { - expscale /= 10; - *cp++ = '0' + (exponent / expscale); - exponent %= expscale; - } - while (expscale > 10); - *cp++ = '0' + exponent; - } - - /* Compute number of characters which must be filled with the padding - character. */ - if (is_neg || info->showsign || info->space) - --width; - width -= cp - startp; - - if (!info->left && info->pad != '0' && width > 0) - PADN (info->pad, width); - - if (is_neg) - outchar ('-'); - else if (info->showsign) - outchar ('+'); - else if (info->space) - outchar (' '); - - if (!info->left && info->pad == '0' && width > 0) - PADN ('0', width); - - PRINT (startp, cp - startp); - - if (info->left && width > 0) - PADN (info->pad, width); - } - return done; -} - -/* Return the number of extra grouping characters that will be inserted - into a number with INTDIG_MAX integer digits. */ - -static unsigned int -guess_grouping (unsigned int intdig_max, const char *grouping, wchar_t sepchar) -{ - unsigned int groups; - - /* We treat all negative values like CHAR_MAX. */ - - if (*grouping == CHAR_MAX || *grouping <= 0) - /* No grouping should be done. */ - return 0; - - groups = 0; - while (intdig_max > (unsigned int) *grouping) - { - ++groups; - intdig_max -= *grouping++; - - if (*grouping == CHAR_MAX || *grouping < 0) - /* No more grouping should be done. */ - break; - else if (*grouping == 0) - { - /* Same grouping repeats. */ - groups += intdig_max / grouping[-1]; - break; - } - } - - return groups; -} - -/* Group the INTDIG_NO integer digits of the number in [BUF,BUFEND). - There is guaranteed enough space past BUFEND to extend it. - Return the new end of buffer. */ - -static char * -group_number (char *buf, char *bufend, unsigned int intdig_no, - const char *grouping, wchar_t thousands_sep) -{ - unsigned int groups = guess_grouping (intdig_no, grouping, thousands_sep); - char *p; - - if (groups == 0) - return bufend; - - /* Move the fractional part down. */ - memmove (buf + intdig_no + groups, buf + intdig_no, - bufend - (buf + intdig_no)); - - p = buf + intdig_no + groups - 1; - do - { - unsigned int len = *grouping++; - do - *p-- = buf[--intdig_no]; - while (--len > 0); - *p-- = thousands_sep; - - if (*grouping == CHAR_MAX || *grouping < 0) - /* No more grouping should be done. */ - break; - else if (*grouping == 0) - /* Same grouping repeats. */ - --grouping; - } while (intdig_no > (unsigned int) *grouping); - - /* Copy the remaining ungrouped digits. */ - do - *p-- = buf[--intdig_no]; - while (p > buf); - - return bufend + groups; -} -- cgit v1.2.3