Back to index

glibc  2.9
printf_fp.c
Go to the documentation of this file.
00001 /* Floating point output for `printf'.
00002    Copyright (C) 1995-2003, 2006, 2007, 2008 Free Software Foundation, Inc.
00003 
00004    This file is part of the GNU C Library.
00005    Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
00006 
00007    The GNU C Library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Lesser General Public
00009    License as published by the Free Software Foundation; either
00010    version 2.1 of the License, or (at your option) any later version.
00011 
00012    The GNU C Library is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Lesser General Public License for more details.
00016 
00017    You should have received a copy of the GNU Lesser General Public
00018    License along with the GNU C Library; if not, write to the Free
00019    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00020    02111-1307 USA.  */
00021 
00022 /* The gmp headers need some configuration frobs.  */
00023 #define HAVE_ALLOCA 1
00024 
00025 #include <libioP.h>
00026 #include <alloca.h>
00027 #include <ctype.h>
00028 #include <float.h>
00029 #include <gmp-mparam.h>
00030 #include <gmp.h>
00031 #include <stdlib/gmp-impl.h>
00032 #include <stdlib/longlong.h>
00033 #include <stdlib/fpioconst.h>
00034 #include <locale/localeinfo.h>
00035 #include <limits.h>
00036 #include <math.h>
00037 #include <printf.h>
00038 #include <string.h>
00039 #include <unistd.h>
00040 #include <stdlib.h>
00041 #include <wchar.h>
00042 
00043 #ifdef COMPILE_WPRINTF
00044 # define CHAR_T        wchar_t
00045 #else
00046 # define CHAR_T        char
00047 #endif
00048 
00049 #include "_i18n_number.h"
00050 
00051 #ifndef NDEBUG
00052 # define NDEBUG                    /* Undefine this for debugging assertions.  */
00053 #endif
00054 #include <assert.h>
00055 
00056 /* This defines make it possible to use the same code for GNU C library and
00057    the GNU I/O library.      */
00058 #define PUT(f, s, n) _IO_sputn (f, s, n)
00059 #define PAD(f, c, n) (wide ? _IO_wpadn (f, c, n) : INTUSE(_IO_padn) (f, c, n))
00060 /* We use this file GNU C library and GNU I/O library.  So make
00061    names equal.       */
00062 #undef putc
00063 #define putc(c, f) (wide \
00064                   ? (int)_IO_putwc_unlocked (c, f) : _IO_putc_unlocked (c, f))
00065 #define size_t     _IO_size_t
00066 #define FILE       _IO_FILE
00067 
00068 /* Macros for doing the actual output.  */
00069 
00070 #define outchar(ch)                                                  \
00071   do                                                                 \
00072     {                                                                \
00073       register const int outc = (ch);                                       \
00074       if (putc (outc, fp) == EOF)                                    \
00075        {                                                             \
00076          if (buffer_malloced)                                               \
00077            free (wbuffer);                                           \
00078          return -1;                                                  \
00079        }                                                             \
00080       ++done;                                                        \
00081     } while (0)
00082 
00083 #define PRINT(ptr, wptr, len)                                               \
00084   do                                                                 \
00085     {                                                                \
00086       register size_t outlen = (len);                                       \
00087       if (len > 20)                                                  \
00088        {                                                             \
00089          if (PUT (fp, wide ? (const char *) wptr : ptr, outlen) != outlen)   \
00090            {                                                         \
00091              if (buffer_malloced)                                    \
00092               free (wbuffer);                                               \
00093              return -1;                                              \
00094            }                                                         \
00095          ptr += outlen;                                              \
00096          done += outlen;                                             \
00097        }                                                             \
00098       else                                                           \
00099        {                                                             \
00100          if (wide)                                                   \
00101            while (outlen-- > 0)                                      \
00102              outchar (*wptr++);                                      \
00103          else                                                        \
00104            while (outlen-- > 0)                                      \
00105              outchar (*ptr++);                                              \
00106        }                                                             \
00107     } while (0)
00108 
00109 #define PADN(ch, len)                                                       \
00110   do                                                                 \
00111     {                                                                \
00112       if (PAD (fp, ch, len) != len)                                         \
00113        {                                                             \
00114          if (buffer_malloced)                                               \
00115            free (wbuffer);                                           \
00116          return -1;                                                  \
00117        }                                                             \
00118       done += len;                                                   \
00119     }                                                                \
00120   while (0)
00121 
00122 /* We use the GNU MP library to handle large numbers.
00123 
00124    An MP variable occupies a varying number of entries in its array.  We keep
00125    track of this number for efficiency reasons.  Otherwise we would always
00126    have to process the whole array.  */
00127 #define MPN_VAR(name) mp_limb_t *name; mp_size_t name##size
00128 
00129 #define MPN_ASSIGN(dst,src)                                          \
00130   memcpy (dst, src, (dst##size = src##size) * sizeof (mp_limb_t))
00131 #define MPN_GE(u,v) \
00132   (u##size > v##size || (u##size == v##size && __mpn_cmp (u, v, u##size) >= 0))
00133 
00134 extern int __isinfl_internal (long double) attribute_hidden;
00135 extern int __isnanl_internal (long double) attribute_hidden;
00136 
00137 extern mp_size_t __mpn_extract_double (mp_ptr res_ptr, mp_size_t size,
00138                                    int *expt, int *is_neg,
00139                                    double value);
00140 extern mp_size_t __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
00141                                        int *expt, int *is_neg,
00142                                        long double value);
00143 extern unsigned int __guess_grouping (unsigned int intdig_max,
00144                                   const char *grouping);
00145 
00146 
00147 static wchar_t *group_number (wchar_t *buf, wchar_t *bufend,
00148                            unsigned int intdig_no, const char *grouping,
00149                            wchar_t thousands_sep, int ngroups)
00150      internal_function;
00151 
00152 
00153 int
00154 ___printf_fp (FILE *fp,
00155              const struct printf_info *info,
00156              const void *const *args)
00157 {
00158   /* The floating-point value to output.  */
00159   union
00160     {
00161       double dbl;
00162       __long_double_t ldbl;
00163     }
00164   fpnum;
00165 
00166   /* Locale-dependent representation of decimal point.  */
00167   const char *decimal;
00168   wchar_t decimalwc;
00169 
00170   /* Locale-dependent thousands separator and grouping specification.  */
00171   const char *thousands_sep = NULL;
00172   wchar_t thousands_sepwc = 0;
00173   const char *grouping;
00174 
00175   /* "NaN" or "Inf" for the special cases.  */
00176   const char *special = NULL;
00177   const wchar_t *wspecial = NULL;
00178 
00179   /* We need just a few limbs for the input before shifting to the right
00180      position.       */
00181   mp_limb_t fp_input[(LDBL_MANT_DIG + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB];
00182   /* We need to shift the contents of fp_input by this amount of bits.       */
00183   int to_shift = 0;
00184 
00185   /* The fraction of the floting-point value in question  */
00186   MPN_VAR(frac);
00187   /* and the exponent.      */
00188   int exponent;
00189   /* Sign of the exponent.  */
00190   int expsign = 0;
00191   /* Sign of float number.  */
00192   int is_neg = 0;
00193 
00194   /* Scaling factor.  */
00195   MPN_VAR(scale);
00196 
00197   /* Temporary bignum value.  */
00198   MPN_VAR(tmp);
00199 
00200   /* Digit which is result of last hack_digit() call.  */
00201   wchar_t digit;
00202 
00203   /* The type of output format that will be used: 'e'/'E' or 'f'.  */
00204   int type;
00205 
00206   /* Counter for number of written characters.   */
00207   int done = 0;
00208 
00209   /* General helper (carry limb).  */
00210   mp_limb_t cy;
00211 
00212   /* Nonzero if this is output on a wide character stream.  */
00213   int wide = info->wide;
00214 
00215   /* Buffer in which we produce the output.  */
00216   wchar_t *wbuffer = NULL;
00217   /* Flag whether wbuffer is malloc'ed or not.  */
00218   int buffer_malloced = 0;
00219 
00220   auto wchar_t hack_digit (void);
00221 
00222   wchar_t hack_digit (void)
00223     {
00224       mp_limb_t hi;
00225 
00226       if (expsign != 0 && type == 'f' && exponent-- > 0)
00227        hi = 0;
00228       else if (scalesize == 0)
00229        {
00230          hi = frac[fracsize - 1];
00231          frac[fracsize - 1] = __mpn_mul_1 (frac, frac, fracsize - 1, 10);
00232        }
00233       else
00234        {
00235          if (fracsize < scalesize)
00236            hi = 0;
00237          else
00238            {
00239              hi = mpn_divmod (tmp, frac, fracsize, scale, scalesize);
00240              tmp[fracsize - scalesize] = hi;
00241              hi = tmp[0];
00242 
00243              fracsize = scalesize;
00244              while (fracsize != 0 && frac[fracsize - 1] == 0)
00245               --fracsize;
00246              if (fracsize == 0)
00247               {
00248                 /* We're not prepared for an mpn variable with zero
00249                    limbs.  */
00250                 fracsize = 1;
00251                 return L'0' + hi;
00252               }
00253            }
00254 
00255          mp_limb_t _cy = __mpn_mul_1 (frac, frac, fracsize, 10);
00256          if (_cy != 0)
00257            frac[fracsize++] = _cy;
00258        }
00259 
00260       return L'0' + hi;
00261     }
00262 
00263 
00264   /* Figure out the decimal point character.  */
00265   if (info->extra == 0)
00266     {
00267       decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
00268       decimalwc = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
00269     }
00270   else
00271     {
00272       decimal = _NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT);
00273       if (*decimal == '\0')
00274        decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
00275       decimalwc = _NL_CURRENT_WORD (LC_MONETARY,
00276                                 _NL_MONETARY_DECIMAL_POINT_WC);
00277       if (decimalwc == L'\0')
00278        decimalwc = _NL_CURRENT_WORD (LC_NUMERIC,
00279                                   _NL_NUMERIC_DECIMAL_POINT_WC);
00280     }
00281   /* The decimal point character must not be zero.  */
00282   assert (*decimal != '\0');
00283   assert (decimalwc != L'\0');
00284 
00285   if (info->group)
00286     {
00287       if (info->extra == 0)
00288        grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
00289       else
00290        grouping = _NL_CURRENT (LC_MONETARY, MON_GROUPING);
00291 
00292       if (*grouping <= 0 || *grouping == CHAR_MAX)
00293        grouping = NULL;
00294       else
00295        {
00296          /* Figure out the thousands separator character.  */
00297          if (wide)
00298            {
00299              if (info->extra == 0)
00300               thousands_sepwc =
00301                 _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC);
00302              else
00303               thousands_sepwc =
00304                 _NL_CURRENT_WORD (LC_MONETARY,
00305                                 _NL_MONETARY_THOUSANDS_SEP_WC);
00306            }
00307          else
00308            {
00309              if (info->extra == 0)
00310               thousands_sep = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
00311              else
00312               thousands_sep = _NL_CURRENT (LC_MONETARY, MON_THOUSANDS_SEP);
00313            }
00314 
00315          if ((wide && thousands_sepwc == L'\0')
00316              || (! wide && *thousands_sep == '\0'))
00317            grouping = NULL;
00318          else if (thousands_sepwc == L'\0')
00319            /* If we are printing multibyte characters and there is a
00320               multibyte representation for the thousands separator,
00321               we must ensure the wide character thousands separator
00322               is available, even if it is fake.  */
00323            thousands_sepwc = 0xfffffffe;
00324        }
00325     }
00326   else
00327     grouping = NULL;
00328 
00329   /* Fetch the argument value.     */
00330 #ifndef __NO_LONG_DOUBLE_MATH
00331   if (info->is_long_double && sizeof (long double) > sizeof (double))
00332     {
00333       fpnum.ldbl = *(const long double *) args[0];
00334 
00335       /* Check for special values: not a number or infinity.  */
00336       if (__isnanl (fpnum.ldbl))
00337        {
00338          if (isupper (info->spec))
00339            {
00340              special = "NAN";
00341              wspecial = L"NAN";
00342            }
00343            else
00344              {
00345               special = "nan";
00346               wspecial = L"nan";
00347              }
00348          is_neg = 0;
00349        }
00350       else if (__isinfl (fpnum.ldbl))
00351        {
00352          if (isupper (info->spec))
00353            {
00354              special = "INF";
00355              wspecial = L"INF";
00356            }
00357          else
00358            {
00359              special = "inf";
00360              wspecial = L"inf";
00361            }
00362          is_neg = fpnum.ldbl < 0;
00363        }
00364       else
00365        {
00366          fracsize = __mpn_extract_long_double (fp_input,
00367                                           (sizeof (fp_input) /
00368                                            sizeof (fp_input[0])),
00369                                           &exponent, &is_neg,
00370                                           fpnum.ldbl);
00371          to_shift = 1 + fracsize * BITS_PER_MP_LIMB - LDBL_MANT_DIG;
00372        }
00373     }
00374   else
00375 #endif /* no long double */
00376     {
00377       fpnum.dbl = *(const double *) args[0];
00378 
00379       /* Check for special values: not a number or infinity.  */
00380       if (__isnan (fpnum.dbl))
00381        {
00382          is_neg = 0;
00383          if (isupper (info->spec))
00384            {
00385              special = "NAN";
00386              wspecial = L"NAN";
00387            }
00388          else
00389            {
00390              special = "nan";
00391              wspecial = L"nan";
00392            }
00393        }
00394       else if (__isinf (fpnum.dbl))
00395        {
00396          is_neg = fpnum.dbl < 0;
00397          if (isupper (info->spec))
00398            {
00399              special = "INF";
00400              wspecial = L"INF";
00401            }
00402          else
00403            {
00404              special = "inf";
00405              wspecial = L"inf";
00406            }
00407        }
00408       else
00409        {
00410          fracsize = __mpn_extract_double (fp_input,
00411                                       (sizeof (fp_input)
00412                                        / sizeof (fp_input[0])),
00413                                       &exponent, &is_neg, fpnum.dbl);
00414          to_shift = 1 + fracsize * BITS_PER_MP_LIMB - DBL_MANT_DIG;
00415        }
00416     }
00417 
00418   if (special)
00419     {
00420       int width = info->width;
00421 
00422       if (is_neg || info->showsign || info->space)
00423        --width;
00424       width -= 3;
00425 
00426       if (!info->left && width > 0)
00427        PADN (' ', width);
00428 
00429       if (is_neg)
00430        outchar ('-');
00431       else if (info->showsign)
00432        outchar ('+');
00433       else if (info->space)
00434        outchar (' ');
00435 
00436       PRINT (special, wspecial, 3);
00437 
00438       if (info->left && width > 0)
00439        PADN (' ', width);
00440 
00441       return done;
00442     }
00443 
00444 
00445   /* We need three multiprecision variables.  Now that we have the exponent
00446      of the number we can allocate the needed memory.  It would be more
00447      efficient to use variables of the fixed maximum size but because this
00448      would be really big it could lead to memory problems.  */
00449   {
00450     mp_size_t bignum_size = ((ABS (exponent) + BITS_PER_MP_LIMB - 1)
00451                           / BITS_PER_MP_LIMB
00452                           + (LDBL_MANT_DIG / BITS_PER_MP_LIMB > 2 ? 8 : 4))
00453                          * sizeof (mp_limb_t);
00454     frac = (mp_limb_t *) alloca (bignum_size);
00455     tmp = (mp_limb_t *) alloca (bignum_size);
00456     scale = (mp_limb_t *) alloca (bignum_size);
00457   }
00458 
00459   /* We now have to distinguish between numbers with positive and negative
00460      exponents because the method used for the one is not applicable/efficient
00461      for the other.  */
00462   scalesize = 0;
00463   if (exponent > 2)
00464     {
00465       /* |FP| >= 8.0.  */
00466       int scaleexpo = 0;
00467       int explog = LDBL_MAX_10_EXP_LOG;
00468       int exp10 = 0;
00469       const struct mp_power *powers = &_fpioconst_pow10[explog + 1];
00470       int cnt_h, cnt_l, i;
00471 
00472       if ((exponent + to_shift) % BITS_PER_MP_LIMB == 0)
00473        {
00474          MPN_COPY_DECR (frac + (exponent + to_shift) / BITS_PER_MP_LIMB,
00475                       fp_input, fracsize);
00476          fracsize += (exponent + to_shift) / BITS_PER_MP_LIMB;
00477        }
00478       else
00479        {
00480          cy = __mpn_lshift (frac + (exponent + to_shift) / BITS_PER_MP_LIMB,
00481                           fp_input, fracsize,
00482                           (exponent + to_shift) % BITS_PER_MP_LIMB);
00483          fracsize += (exponent + to_shift) / BITS_PER_MP_LIMB;
00484          if (cy)
00485            frac[fracsize++] = cy;
00486        }
00487       MPN_ZERO (frac, (exponent + to_shift) / BITS_PER_MP_LIMB);
00488 
00489       assert (powers > &_fpioconst_pow10[0]);
00490       do
00491        {
00492          --powers;
00493 
00494          /* The number of the product of two binary numbers with n and m
00495             bits respectively has m+n or m+n-1 bits.    */
00496          if (exponent >= scaleexpo + powers->p_expo - 1)
00497            {
00498              if (scalesize == 0)
00499               {
00500 #ifndef __NO_LONG_DOUBLE_MATH
00501                 if (LDBL_MANT_DIG > _FPIO_CONST_OFFSET * BITS_PER_MP_LIMB
00502                     && info->is_long_double)
00503                   {
00504 #define _FPIO_CONST_SHIFT \
00505   (((LDBL_MANT_DIG + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB) \
00506    - _FPIO_CONST_OFFSET)
00507                     /* 64bit const offset is not enough for
00508                       IEEE quad long double.  */
00509                     tmpsize = powers->arraysize + _FPIO_CONST_SHIFT;
00510                     memcpy (tmp + _FPIO_CONST_SHIFT,
00511                            &__tens[powers->arrayoff],
00512                            tmpsize * sizeof (mp_limb_t));
00513                     MPN_ZERO (tmp, _FPIO_CONST_SHIFT);
00514                     /* Adjust exponent, as scaleexpo will be this much
00515                       bigger too.  */
00516                     exponent += _FPIO_CONST_SHIFT * BITS_PER_MP_LIMB;
00517                   }
00518                 else
00519 #endif
00520                   {
00521                     tmpsize = powers->arraysize;
00522                     memcpy (tmp, &__tens[powers->arrayoff],
00523                            tmpsize * sizeof (mp_limb_t));
00524                   }
00525               }
00526              else
00527               {
00528                 cy = __mpn_mul (tmp, scale, scalesize,
00529                               &__tens[powers->arrayoff
00530                                     + _FPIO_CONST_OFFSET],
00531                               powers->arraysize - _FPIO_CONST_OFFSET);
00532                 tmpsize = scalesize + powers->arraysize - _FPIO_CONST_OFFSET;
00533                 if (cy == 0)
00534                   --tmpsize;
00535               }
00536 
00537              if (MPN_GE (frac, tmp))
00538               {
00539                 int cnt;
00540                 MPN_ASSIGN (scale, tmp);
00541                 count_leading_zeros (cnt, scale[scalesize - 1]);
00542                 scaleexpo = (scalesize - 2) * BITS_PER_MP_LIMB - cnt - 1;
00543                 exp10 |= 1 << explog;
00544               }
00545            }
00546          --explog;
00547        }
00548       while (powers > &_fpioconst_pow10[0]);
00549       exponent = exp10;
00550 
00551       /* Optimize number representations.  We want to represent the numbers
00552         with the lowest number of bytes possible without losing any
00553         bytes. Also the highest bit in the scaling factor has to be set
00554         (this is a requirement of the MPN division routines).  */
00555       if (scalesize > 0)
00556        {
00557          /* Determine minimum number of zero bits at the end of
00558             both numbers.  */
00559          for (i = 0; scale[i] == 0 && frac[i] == 0; i++)
00560            ;
00561 
00562          /* Determine number of bits the scaling factor is misplaced. */
00563          count_leading_zeros (cnt_h, scale[scalesize - 1]);
00564 
00565          if (cnt_h == 0)
00566            {
00567              /* The highest bit of the scaling factor is already set. So
00568                we only have to remove the trailing empty limbs.  */
00569              if (i > 0)
00570               {
00571                 MPN_COPY_INCR (scale, scale + i, scalesize - i);
00572                 scalesize -= i;
00573                 MPN_COPY_INCR (frac, frac + i, fracsize - i);
00574                 fracsize -= i;
00575               }
00576            }
00577          else
00578            {
00579              if (scale[i] != 0)
00580               {
00581                 count_trailing_zeros (cnt_l, scale[i]);
00582                 if (frac[i] != 0)
00583                   {
00584                     int cnt_l2;
00585                     count_trailing_zeros (cnt_l2, frac[i]);
00586                     if (cnt_l2 < cnt_l)
00587                      cnt_l = cnt_l2;
00588                   }
00589               }
00590              else
00591               count_trailing_zeros (cnt_l, frac[i]);
00592 
00593              /* Now shift the numbers to their optimal position.  */
00594              if (i == 0 && BITS_PER_MP_LIMB - cnt_h > cnt_l)
00595               {
00596                 /* We cannot save any memory.     So just roll both numbers
00597                    so that the scaling factor has its highest bit set.  */
00598 
00599                 (void) __mpn_lshift (scale, scale, scalesize, cnt_h);
00600                 cy = __mpn_lshift (frac, frac, fracsize, cnt_h);
00601                 if (cy != 0)
00602                   frac[fracsize++] = cy;
00603               }
00604              else if (BITS_PER_MP_LIMB - cnt_h <= cnt_l)
00605               {
00606                 /* We can save memory by removing the trailing zero limbs
00607                    and by packing the non-zero limbs which gain another
00608                    free one. */
00609 
00610                 (void) __mpn_rshift (scale, scale + i, scalesize - i,
00611                                    BITS_PER_MP_LIMB - cnt_h);
00612                 scalesize -= i + 1;
00613                 (void) __mpn_rshift (frac, frac + i, fracsize - i,
00614                                    BITS_PER_MP_LIMB - cnt_h);
00615                 fracsize -= frac[fracsize - i - 1] == 0 ? i + 1 : i;
00616               }
00617              else
00618               {
00619                 /* We can only save the memory of the limbs which are zero.
00620                    The non-zero parts occupy the same number of limbs.  */
00621 
00622                 (void) __mpn_rshift (scale, scale + (i - 1),
00623                                    scalesize - (i - 1),
00624                                    BITS_PER_MP_LIMB - cnt_h);
00625                 scalesize -= i;
00626                 (void) __mpn_rshift (frac, frac + (i - 1),
00627                                    fracsize - (i - 1),
00628                                    BITS_PER_MP_LIMB - cnt_h);
00629                 fracsize -= frac[fracsize - (i - 1) - 1] == 0 ? i : i - 1;
00630               }
00631            }
00632        }
00633     }
00634   else if (exponent < 0)
00635     {
00636       /* |FP| < 1.0.  */
00637       int exp10 = 0;
00638       int explog = LDBL_MAX_10_EXP_LOG;
00639       const struct mp_power *powers = &_fpioconst_pow10[explog + 1];
00640       mp_size_t used_limbs = fracsize - 1;
00641 
00642       /* Now shift the input value to its right place.  */
00643       cy = __mpn_lshift (frac, fp_input, fracsize, to_shift);
00644       frac[fracsize++] = cy;
00645       assert (cy == 1 || (frac[fracsize - 2] == 0 && frac[0] == 0));
00646 
00647       expsign = 1;
00648       exponent = -exponent;
00649 
00650       assert (powers != &_fpioconst_pow10[0]);
00651       do
00652        {
00653          --powers;
00654 
00655          if (exponent >= powers->m_expo)
00656            {
00657              int i, incr, cnt_h, cnt_l;
00658              mp_limb_t topval[2];
00659 
00660              /* The __mpn_mul function expects the first argument to be
00661                bigger than the second.  */
00662              if (fracsize < powers->arraysize - _FPIO_CONST_OFFSET)
00663               cy = __mpn_mul (tmp, &__tens[powers->arrayoff
00664                                        + _FPIO_CONST_OFFSET],
00665                             powers->arraysize - _FPIO_CONST_OFFSET,
00666                             frac, fracsize);
00667              else
00668               cy = __mpn_mul (tmp, frac, fracsize,
00669                             &__tens[powers->arrayoff + _FPIO_CONST_OFFSET],
00670                             powers->arraysize - _FPIO_CONST_OFFSET);
00671              tmpsize = fracsize + powers->arraysize - _FPIO_CONST_OFFSET;
00672              if (cy == 0)
00673               --tmpsize;
00674 
00675              count_leading_zeros (cnt_h, tmp[tmpsize - 1]);
00676              incr = (tmpsize - fracsize) * BITS_PER_MP_LIMB
00677                    + BITS_PER_MP_LIMB - 1 - cnt_h;
00678 
00679              assert (incr <= powers->p_expo);
00680 
00681              /* If we increased the exponent by exactly 3 we have to test
00682                for overflow.       This is done by comparing with 10 shifted
00683                to the right position.      */
00684              if (incr == exponent + 3)
00685               {
00686                 if (cnt_h <= BITS_PER_MP_LIMB - 4)
00687                   {
00688                     topval[0] = 0;
00689                     topval[1]
00690                      = ((mp_limb_t) 10) << (BITS_PER_MP_LIMB - 4 - cnt_h);
00691                   }
00692                 else
00693                   {
00694                     topval[0] = ((mp_limb_t) 10) << (BITS_PER_MP_LIMB - 4);
00695                     topval[1] = 0;
00696                     (void) __mpn_lshift (topval, topval, 2,
00697                                       BITS_PER_MP_LIMB - cnt_h);
00698                   }
00699               }
00700 
00701              /* We have to be careful when multiplying the last factor.
00702                If the result is greater than 1.0 be have to test it
00703                against 10.0.  If it is greater or equal to 10.0 the
00704                multiplication was not valid.  This is because we cannot
00705                determine the number of bits in the result in advance.  */
00706              if (incr < exponent + 3
00707                 || (incr == exponent + 3 &&
00708                     (tmp[tmpsize - 1] < topval[1]
00709                      || (tmp[tmpsize - 1] == topval[1]
00710                         && tmp[tmpsize - 2] < topval[0]))))
00711               {
00712                 /* The factor is right.  Adapt binary and decimal
00713                    exponents.       */
00714                 exponent -= incr;
00715                 exp10 |= 1 << explog;
00716 
00717                 /* If this factor yields a number greater or equal to
00718                    1.0, we must not shift the non-fractional digits down. */
00719                 if (exponent < 0)
00720                   cnt_h += -exponent;
00721 
00722                 /* Now we optimize the number representation.   */
00723                 for (i = 0; tmp[i] == 0; ++i);
00724                 if (cnt_h == BITS_PER_MP_LIMB - 1)
00725                   {
00726                     MPN_COPY (frac, tmp + i, tmpsize - i);
00727                     fracsize = tmpsize - i;
00728                   }
00729                 else
00730                   {
00731                     count_trailing_zeros (cnt_l, tmp[i]);
00732 
00733                     /* Now shift the numbers to their optimal position.  */
00734                     if (i == 0 && BITS_PER_MP_LIMB - 1 - cnt_h > cnt_l)
00735                      {
00736                        /* We cannot save any memory.     Just roll the
00737                           number so that the leading digit is in a
00738                           separate limb.  */
00739 
00740                        cy = __mpn_lshift (frac, tmp, tmpsize, cnt_h + 1);
00741                        fracsize = tmpsize + 1;
00742                        frac[fracsize - 1] = cy;
00743                      }
00744                     else if (BITS_PER_MP_LIMB - 1 - cnt_h <= cnt_l)
00745                      {
00746                        (void) __mpn_rshift (frac, tmp + i, tmpsize - i,
00747                                           BITS_PER_MP_LIMB - 1 - cnt_h);
00748                        fracsize = tmpsize - i;
00749                      }
00750                     else
00751                      {
00752                        /* We can only save the memory of the limbs which
00753                           are zero.       The non-zero parts occupy the same
00754                           number of limbs.  */
00755 
00756                        (void) __mpn_rshift (frac, tmp + (i - 1),
00757                                           tmpsize - (i - 1),
00758                                           BITS_PER_MP_LIMB - 1 - cnt_h);
00759                        fracsize = tmpsize - (i - 1);
00760                      }
00761                   }
00762                 used_limbs = fracsize - 1;
00763               }
00764            }
00765          --explog;
00766        }
00767       while (powers != &_fpioconst_pow10[1] && exponent > 0);
00768       /* All factors but 10^-1 are tested now.   */
00769       if (exponent > 0)
00770        {
00771          int cnt_l;
00772 
00773          cy = __mpn_mul_1 (tmp, frac, fracsize, 10);
00774          tmpsize = fracsize;
00775          assert (cy == 0 || tmp[tmpsize - 1] < 20);
00776 
00777          count_trailing_zeros (cnt_l, tmp[0]);
00778          if (cnt_l < MIN (4, exponent))
00779            {
00780              cy = __mpn_lshift (frac, tmp, tmpsize,
00781                              BITS_PER_MP_LIMB - MIN (4, exponent));
00782              if (cy != 0)
00783               frac[tmpsize++] = cy;
00784            }
00785          else
00786            (void) __mpn_rshift (frac, tmp, tmpsize, MIN (4, exponent));
00787          fracsize = tmpsize;
00788          exp10 |= 1;
00789          assert (frac[fracsize - 1] < 10);
00790        }
00791       exponent = exp10;
00792     }
00793   else
00794     {
00795       /* This is a special case.  We don't need a factor because the
00796         numbers are in the range of 1.0 <= |fp| < 8.0.  We simply
00797         shift it to the right place and divide it by 1.0 to get the
00798         leading digit.       (Of course this division is not really made.)   */
00799       assert (0 <= exponent && exponent < 3 &&
00800              exponent + to_shift < BITS_PER_MP_LIMB);
00801 
00802       /* Now shift the input value to its right place.  */
00803       cy = __mpn_lshift (frac, fp_input, fracsize, (exponent + to_shift));
00804       frac[fracsize++] = cy;
00805       exponent = 0;
00806     }
00807 
00808   {
00809     int width = info->width;
00810     wchar_t *wstartp, *wcp;
00811     size_t chars_needed;
00812     int expscale;
00813     int intdig_max, intdig_no = 0;
00814     int fracdig_min;
00815     int fracdig_max;
00816     int dig_max;
00817     int significant;
00818     int ngroups = 0;
00819     char spec = _tolower (info->spec);
00820 
00821     if (spec == 'e')
00822       {
00823        type = info->spec;
00824        intdig_max = 1;
00825        fracdig_min = fracdig_max = info->prec < 0 ? 6 : info->prec;
00826        chars_needed = 1 + 1 + (size_t) fracdig_max + 1 + 1 + 4;
00827        /*            d   .   ddd        e  +-  ddd  */
00828        dig_max = INT_MAX;          /* Unlimited.  */
00829        significant = 1;            /* Does not matter here.  */
00830       }
00831     else if (spec == 'f')
00832       {
00833        type = 'f';
00834        fracdig_min = fracdig_max = info->prec < 0 ? 6 : info->prec;
00835        dig_max = INT_MAX;          /* Unlimited.  */
00836        significant = 1;            /* Does not matter here.  */
00837        if (expsign == 0)
00838          {
00839            intdig_max = exponent + 1;
00840            /* This can be really big!     */  /* XXX Maybe malloc if too big? */
00841            chars_needed = (size_t) exponent + 1 + 1 + (size_t) fracdig_max;
00842          }
00843        else
00844          {
00845            intdig_max = 1;
00846            chars_needed = 1 + 1 + (size_t) fracdig_max;
00847          }
00848       }
00849     else
00850       {
00851        dig_max = info->prec < 0 ? 6 : (info->prec == 0 ? 1 : info->prec);
00852        if ((expsign == 0 && exponent >= dig_max)
00853            || (expsign != 0 && exponent > 4))
00854          {
00855            if ('g' - 'G' == 'e' - 'E')
00856              type = 'E' + (info->spec - 'G');
00857            else
00858              type = isupper (info->spec) ? 'E' : 'e';
00859            fracdig_max = dig_max - 1;
00860            intdig_max = 1;
00861            chars_needed = 1 + 1 + (size_t) fracdig_max + 1 + 1 + 4;
00862          }
00863        else
00864          {
00865            type = 'f';
00866            intdig_max = expsign == 0 ? exponent + 1 : 0;
00867            fracdig_max = dig_max - intdig_max;
00868            /* We need space for the significant digits and perhaps
00869               for leading zeros when < 1.0.  The number of leading
00870               zeros can be as many as would be required for
00871               exponential notation with a negative two-digit
00872               exponent, which is 4.  */
00873            chars_needed = (size_t) dig_max + 1 + 4;
00874          }
00875        fracdig_min = info->alt ? fracdig_max : 0;
00876        significant = 0;            /* We count significant digits.     */
00877       }
00878 
00879     if (grouping)
00880       {
00881        /* Guess the number of groups we will make, and thus how
00882           many spaces we need for separator characters.  */
00883        ngroups = __guess_grouping (intdig_max, grouping);
00884        chars_needed += ngroups;
00885       }
00886 
00887     /* Allocate buffer for output.  We need two more because while rounding
00888        it is possible that we need two more characters in front of all the
00889        other output.  If the amount of memory we have to allocate is too
00890        large use `malloc' instead of `alloca'.  */
00891     size_t wbuffer_to_alloc = (2 + (size_t) chars_needed) * sizeof (wchar_t);
00892     buffer_malloced = ! __libc_use_alloca (chars_needed * 2 * sizeof (wchar_t));
00893     if (__builtin_expect (buffer_malloced, 0))
00894       {
00895        wbuffer = (wchar_t *) malloc (wbuffer_to_alloc);
00896        if (wbuffer == NULL)
00897          /* Signal an error to the caller.  */
00898          return -1;
00899       }
00900     else
00901       wbuffer = (wchar_t *) alloca (wbuffer_to_alloc);
00902     wcp = wstartp = wbuffer + 2;   /* Let room for rounding.  */
00903 
00904     /* Do the real work: put digits in allocated buffer.  */
00905     if (expsign == 0 || type != 'f')
00906       {
00907        assert (expsign == 0 || intdig_max == 1);
00908        while (intdig_no < intdig_max)
00909          {
00910            ++intdig_no;
00911            *wcp++ = hack_digit ();
00912          }
00913        significant = 1;
00914        if (info->alt
00915            || fracdig_min > 0
00916            || (fracdig_max > 0 && (fracsize > 1 || frac[0] != 0)))
00917          *wcp++ = decimalwc;
00918       }
00919     else
00920       {
00921        /* |fp| < 1.0 and the selected type is 'f', so put "0."
00922           in the buffer.  */
00923        *wcp++ = L'0';
00924        --exponent;
00925        *wcp++ = decimalwc;
00926       }
00927 
00928     /* Generate the needed number of fractional digits.  */
00929     int fracdig_no = 0;
00930     int added_zeros = 0;
00931     while (fracdig_no < fracdig_min + added_zeros
00932           || (fracdig_no < fracdig_max && (fracsize > 1 || frac[0] != 0)))
00933       {
00934        ++fracdig_no;
00935        *wcp = hack_digit ();
00936        if (*wcp++ != L'0')
00937          significant = 1;
00938        else if (significant == 0)
00939          {
00940            ++fracdig_max;
00941            if (fracdig_min > 0)
00942              ++added_zeros;
00943          }
00944       }
00945 
00946     /* Do rounding.  */
00947     digit = hack_digit ();
00948     if (digit > L'4')
00949       {
00950        wchar_t *wtp = wcp;
00951 
00952        if (digit == L'5'
00953            && ((*(wcp - 1) != decimalwc && (*(wcp - 1) & 1) == 0)
00954               || ((*(wcp - 1) == decimalwc && (*(wcp - 2) & 1) == 0))))
00955          {
00956            /* This is the critical case.   */
00957            if (fracsize == 1 && frac[0] == 0)
00958              /* Rest of the number is zero -> round to even.
00959                (IEEE 754-1985 4.1 says this is the default rounding.)  */
00960              goto do_expo;
00961            else if (scalesize == 0)
00962              {
00963               /* Here we have to see whether all limbs are zero since no
00964                  normalization happened.  */
00965               size_t lcnt = fracsize;
00966               while (lcnt >= 1 && frac[lcnt - 1] == 0)
00967                 --lcnt;
00968               if (lcnt == 0)
00969                 /* Rest of the number is zero -> round to even.
00970                    (IEEE 754-1985 4.1 says this is the default rounding.)  */
00971                 goto do_expo;
00972              }
00973          }
00974 
00975        if (fracdig_no > 0)
00976          {
00977            /* Process fractional digits.  Terminate if not rounded or
00978               radix character is reached.  */
00979            int removed = 0;
00980            while (*--wtp != decimalwc && *wtp == L'9')
00981              {
00982               *wtp = L'0';
00983               ++removed;
00984              }
00985            if (removed == fracdig_min && added_zeros > 0)
00986              --added_zeros;
00987            if (*wtp != decimalwc)
00988              /* Round up.  */
00989              (*wtp)++;
00990            else if (__builtin_expect (spec == 'g' && type == 'f' && info->alt
00991                                    && wtp == wstartp + 1
00992                                    && wstartp[0] == L'0',
00993                                    0))
00994              /* This is a special case: the rounded number is 1.0,
00995                the format is 'g' or 'G', and the alternative format
00996                is selected.  This means the result must be "1.".  */
00997              --added_zeros;
00998          }
00999 
01000        if (fracdig_no == 0 || *wtp == decimalwc)
01001          {
01002            /* Round the integer digits.  */
01003            if (*(wtp - 1) == decimalwc)
01004              --wtp;
01005 
01006            while (--wtp >= wstartp && *wtp == L'9')
01007              *wtp = L'0';
01008 
01009            if (wtp >= wstartp)
01010              /* Round up.  */
01011              (*wtp)++;
01012            else
01013              /* It is more critical.  All digits were 9's.  */
01014              {
01015               if (type != 'f')
01016                 {
01017                   *wstartp = '1';
01018                   exponent += expsign == 0 ? 1 : -1;
01019 
01020                   /* The above exponent adjustment could lead to 1.0e-00,
01021                      e.g. for 0.999999999.  Make sure exponent 0 always
01022                      uses + sign.  */
01023                   if (exponent == 0)
01024                     expsign = 0;
01025                 }
01026               else if (intdig_no == dig_max)
01027                 {
01028                   /* This is the case where for type %g the number fits
01029                      really in the range for %f output but after rounding
01030                      the number of digits is too big.    */
01031                   *--wstartp = decimalwc;
01032                   *--wstartp = L'1';
01033 
01034                   if (info->alt || fracdig_no > 0)
01035                     {
01036                      /* Overwrite the old radix character.  */
01037                      wstartp[intdig_no + 2] = L'0';
01038                      ++fracdig_no;
01039                     }
01040 
01041                   fracdig_no += intdig_no;
01042                   intdig_no = 1;
01043                   fracdig_max = intdig_max - intdig_no;
01044                   ++exponent;
01045                   /* Now we must print the exponent.    */
01046                   type = isupper (info->spec) ? 'E' : 'e';
01047                 }
01048               else
01049                 {
01050                   /* We can simply add another another digit before the
01051                      radix.  */
01052                   *--wstartp = L'1';
01053                   ++intdig_no;
01054                 }
01055 
01056               /* While rounding the number of digits can change.
01057                  If the number now exceeds the limits remove some
01058                  fractional digits.  */
01059               if (intdig_no + fracdig_no > dig_max)
01060                 {
01061                   wcp -= intdig_no + fracdig_no - dig_max;
01062                   fracdig_no -= intdig_no + fracdig_no - dig_max;
01063                 }
01064              }
01065          }
01066       }
01067 
01068   do_expo:
01069     /* Now remove unnecessary '0' at the end of the string.  */
01070     while (fracdig_no > fracdig_min + added_zeros && *(wcp - 1) == L'0')
01071       {
01072        --wcp;
01073        --fracdig_no;
01074       }
01075     /* If we eliminate all fractional digits we perhaps also can remove
01076        the radix character.  */
01077     if (fracdig_no == 0 && !info->alt && *(wcp - 1) == decimalwc)
01078       --wcp;
01079 
01080     if (grouping)
01081       /* Add in separator characters, overwriting the same buffer.  */
01082       wcp = group_number (wstartp, wcp, intdig_no, grouping, thousands_sepwc,
01083                        ngroups);
01084 
01085     /* Write the exponent if it is needed.  */
01086     if (type != 'f')
01087       {
01088        if (__builtin_expect (expsign != 0 && exponent == 4 && spec == 'g', 0))
01089          {
01090            /* This is another special case.  The exponent of the number is
01091               really smaller than -4, which requires the 'e'/'E' format.
01092               But after rounding the number has an exponent of -4.  */
01093            assert (wcp >= wstartp + 1);
01094            assert (wstartp[0] == L'1');
01095            __wmemcpy (wstartp, L"0.0001", 6);
01096            wstartp[1] = decimalwc;
01097            if (wcp >= wstartp + 2)
01098              {
01099               wmemset (wstartp + 6, L'0', wcp - (wstartp + 2));
01100               wcp += 4;
01101              }
01102            else
01103              wcp += 5;
01104          }
01105        else
01106          {
01107            *wcp++ = (wchar_t) type;
01108            *wcp++ = expsign ? L'-' : L'+';
01109 
01110            /* Find the magnitude of the exponent.       */
01111            expscale = 10;
01112            while (expscale <= exponent)
01113              expscale *= 10;
01114 
01115            if (exponent < 10)
01116              /* Exponent always has at least two digits.  */
01117              *wcp++ = L'0';
01118            else
01119              do
01120               {
01121                 expscale /= 10;
01122                 *wcp++ = L'0' + (exponent / expscale);
01123                 exponent %= expscale;
01124               }
01125              while (expscale > 10);
01126            *wcp++ = L'0' + exponent;
01127          }
01128       }
01129 
01130     /* Compute number of characters which must be filled with the padding
01131        character.  */
01132     if (is_neg || info->showsign || info->space)
01133       --width;
01134     width -= wcp - wstartp;
01135 
01136     if (!info->left && info->pad != '0' && width > 0)
01137       PADN (info->pad, width);
01138 
01139     if (is_neg)
01140       outchar ('-');
01141     else if (info->showsign)
01142       outchar ('+');
01143     else if (info->space)
01144       outchar (' ');
01145 
01146     if (!info->left && info->pad == '0' && width > 0)
01147       PADN ('0', width);
01148 
01149     {
01150       char *buffer = NULL;
01151       char *buffer_end = NULL;
01152       char *cp = NULL;
01153       char *tmpptr;
01154 
01155       if (! wide)
01156        {
01157          /* Create the single byte string.  */
01158          size_t decimal_len;
01159          size_t thousands_sep_len;
01160          wchar_t *copywc;
01161          size_t factor = (info->i18n
01162                         ? _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MB_CUR_MAX)
01163                         : 1);
01164 
01165          decimal_len = strlen (decimal);
01166 
01167          if (thousands_sep == NULL)
01168            thousands_sep_len = 0;
01169          else
01170            thousands_sep_len = strlen (thousands_sep);
01171 
01172          size_t nbuffer = (2 + chars_needed * factor + decimal_len
01173                          + ngroups * thousands_sep_len);
01174          if (__builtin_expect (buffer_malloced, 0))
01175            {
01176              buffer = (char *) malloc (nbuffer);
01177              if (buffer == NULL)
01178               {
01179                 /* Signal an error to the caller.  */
01180                 free (wbuffer);
01181                 return -1;
01182               }
01183            }
01184          else
01185            buffer = (char *) alloca (nbuffer);
01186          buffer_end = buffer + nbuffer;
01187 
01188          /* Now copy the wide character string.  Since the character
01189             (except for the decimal point and thousands separator) must
01190             be coming from the ASCII range we can esily convert the
01191             string without mapping tables.  */
01192          for (cp = buffer, copywc = wstartp; copywc < wcp; ++copywc)
01193            if (*copywc == decimalwc)
01194              cp = (char *) __mempcpy (cp, decimal, decimal_len);
01195            else if (*copywc == thousands_sepwc)
01196              cp = (char *) __mempcpy (cp, thousands_sep, thousands_sep_len);
01197            else
01198              *cp++ = (char) *copywc;
01199        }
01200 
01201       tmpptr = buffer;
01202       if (__builtin_expect (info->i18n, 0))
01203         {
01204 #ifdef COMPILE_WPRINTF
01205          wstartp = _i18n_number_rewrite (wstartp, wcp,
01206                                      wbuffer + wbuffer_to_alloc);
01207          wcp = wbuffer + wbuffer_to_alloc;
01208          assert ((uintptr_t) wbuffer <= (uintptr_t) wstartp);
01209          assert ((uintptr_t) wstartp
01210                 < (uintptr_t) wbuffer + wbuffer_to_alloc);
01211 #else
01212          tmpptr = _i18n_number_rewrite (tmpptr, cp, buffer_end);
01213          cp = buffer_end;
01214          assert ((uintptr_t) buffer <= (uintptr_t) tmpptr);
01215          assert ((uintptr_t) tmpptr < (uintptr_t) buffer_end);
01216 #endif
01217         }
01218 
01219       PRINT (tmpptr, wstartp, wide ? wcp - wstartp : cp - tmpptr);
01220 
01221       /* Free the memory if necessary.  */
01222       if (__builtin_expect (buffer_malloced, 0))
01223        {
01224          free (buffer);
01225          free (wbuffer);
01226        }
01227     }
01228 
01229     if (info->left && width > 0)
01230       PADN (info->pad, width);
01231   }
01232   return done;
01233 }
01234 ldbl_hidden_def (___printf_fp, __printf_fp)
01235 ldbl_strong_alias (___printf_fp, __printf_fp)
01236 
01237 /* Return the number of extra grouping characters that will be inserted
01238    into a number with INTDIG_MAX integer digits.  */
01239 
01240 unsigned int
01241 __guess_grouping (unsigned int intdig_max, const char *grouping)
01242 {
01243   unsigned int groups;
01244 
01245   /* We treat all negative values like CHAR_MAX.  */
01246 
01247   if (*grouping == CHAR_MAX || *grouping <= 0)
01248     /* No grouping should be done.  */
01249     return 0;
01250 
01251   groups = 0;
01252   while (intdig_max > (unsigned int) *grouping)
01253     {
01254       ++groups;
01255       intdig_max -= *grouping++;
01256 
01257       if (*grouping == CHAR_MAX
01258 #if CHAR_MIN < 0
01259          || *grouping < 0
01260 #endif
01261          )
01262        /* No more grouping should be done.  */
01263        break;
01264       else if (*grouping == 0)
01265        {
01266          /* Same grouping repeats.  */
01267          groups += (intdig_max - 1) / grouping[-1];
01268          break;
01269        }
01270     }
01271 
01272   return groups;
01273 }
01274 
01275 /* Group the INTDIG_NO integer digits of the number in [BUF,BUFEND).
01276    There is guaranteed enough space past BUFEND to extend it.
01277    Return the new end of buffer.  */
01278 
01279 static wchar_t *
01280 internal_function
01281 group_number (wchar_t *buf, wchar_t *bufend, unsigned int intdig_no,
01282              const char *grouping, wchar_t thousands_sep, int ngroups)
01283 {
01284   wchar_t *p;
01285 
01286   if (ngroups == 0)
01287     return bufend;
01288 
01289   /* Move the fractional part down.  */
01290   __wmemmove (buf + intdig_no + ngroups, buf + intdig_no,
01291              bufend - (buf + intdig_no));
01292 
01293   p = buf + intdig_no + ngroups - 1;
01294   do
01295     {
01296       unsigned int len = *grouping++;
01297       do
01298        *p-- = buf[--intdig_no];
01299       while (--len > 0);
01300       *p-- = thousands_sep;
01301 
01302       if (*grouping == CHAR_MAX
01303 #if CHAR_MIN < 0
01304          || *grouping < 0
01305 #endif
01306          )
01307        /* No more grouping should be done.  */
01308        break;
01309       else if (*grouping == 0)
01310        /* Same grouping repeats.  */
01311        --grouping;
01312     } while (intdig_no > (unsigned int) *grouping);
01313 
01314   /* Copy the remaining ungrouped digits.  */
01315   do
01316     *p-- = buf[--intdig_no];
01317   while (p > buf);
01318 
01319   return bufend + ngroups;
01320 }