// This is part of the iostream library, providing input/output for C++.
// Copyright (C) 1992 Per Bothner.
// This 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.
// This 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 this library; if not, write to the Free
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// Format floating-point number and print them.
// Return number of chars printed, or EOF on error.
// sign_mode == '+' : print "-" or "+"
// sign_mode == ' ' : print "-" or " "
// sign_mode == '\0' : print "-' or ""
int __outfloat(double value, streambuf *sb, char type,
int width, int precision, ios::fmtflags flags,
char sign_mode, char fill)
#define PUT(x) do {if (sb->sputc(x) < 0) goto error; count++;} while (0)
do {int _n=n; count+=_n; if (sb->sputn(p,_n) != _n) goto error;} while(0)
do {int _n = n; count+=_n; if (sb->padn(fill, _n) < 0) goto error;} while (0)
ios::fmtflags pad_kind = flags & (ios::left|ios::right|ios::internal);
int show_dot = (flags & ios::showpoint) != 0;
#define EBUF_END &ebuf[EBUF_SIZE]
precision++; // Add one to include digit before decimal point.
exp = type == 'g' ? 'e' : 'E';
if (precision == 0) precision = 1;
if (!(flags & ios::showpoint))
/* Do the actual convension */
if (precision == 999 && mode != 3)
char *p = dtoa(value, mode, precision, &decpt, &sign, &end);
int useful_digits = end-p;
char *exponent_start = EBUF_END;
precision = useful_digits;
// Check if we need to emit an exponent.
if (mode != 3 && decpt != 9999) {
if ((type != 'g' && type != 'F') || i < -4 || i >= precision) {
// Print the exponent into ebuf.
// We write ebuf in reverse order (right-to-left).
/* Note: ANSI requires at least 2 exponent digits. */
*--exponent_start = (i % 10) + '0';
*--exponent_start = i + '0';
*--exponent_start = sign;
int exponent_size = EBUF_END - exponent_start;
/* If we print an exponent, always show just one digit before point. */
if (decpt == 9999) { // Infinity or NaN
// dtoa truncates trailing zeroes. Set the variable trailing_zeroes to
// the number of 0's we have to add (after the decimal point).
trailing_zeroes = useful_digits <= decpt ? precision
: precision-(useful_digits-decpt);
else if (exponent_size) // 'e' 'E' or 'g' format using exponential notation.
trailing_zeroes = precision - useful_digits;
else // 'g' format not using exponential notation.
trailing_zeroes = useful_digits <= decpt ? precision - decpt
: precision-useful_digits;
if (trailing_zeroes < 0) trailing_zeroes = 0;
if (trailing_zeroes != 0 || useful_digits > decpt)
print_sign = sign ? '-' : 0;
else if (sign_mode == '+')
print_sign = sign ? '-' : '+';
else /* if (sign_mode == ' ') */
print_sign = sign ? '-' : ' ';
// Calculate the width (before padding).
(print_sign != 0) + trailing_zeroes + exponent_size + show_dot
+ (decpt > useful_digits ? decpt - useful_digits
: decpt > 0 ? 0 : 1 - decpt);
int padding = width > unpadded_width ? width - unpadded_width : 0;
&& pad_kind != (ios::fmtflags)ios::left
&& pad_kind != (ios::fmtflags)ios::internal) // Default (right) adjust.
if (pad_kind == (ios::fmtflags)ios::internal && padding > 0)
if (useful_digits >= decpt)
PADN('0', decpt-useful_digits);
// Print digits after the decimal point.
if (useful_digits > decpt)
PUTN(p + decpt, useful_digits-decpt);
// Print digits after the decimal point.
PADN('0', trailing_zeroes);
PUTN(exponent_start, exponent_size);
if (pad_kind == (ios::fmtflags)ios::left && padding > 0) // Left adjustment