2.11BSD/ingres/source/gutil/ftoa.c
# define MAXDIG 25
/*
** FLOATING POINT TO ASCII CONVERSION
**
** 'Value' is converted to an ascii character string and stored
** into 'ascii'. Ascii should have room for at least 'width' + 1
** characters. 'Width' is the width of the output field (max).
** 'Prec' is the number of characters to put after the decimal
** point. The format of the output string is controlled by
** 'format'.
**
** 'Format' can be:
** e or E: "E" format output
** f or F: "F" format output
** g or G: "F" format output if it will fit, otherwise
** use "E" format.
** n or N: same as G, but decimal points will not always
** be aligned.
**
** If 'format' is upper case, the "E" comes out in upper case;
** otherwise it comes out in lower case.
**
** When the field width is not big enough, it fills the field with
** stars ("*****") and returns zero. Normal return is the width
** of the output field (sometimes shorter than 'width').
*/
ftoa(value, ascii, width, prec1, format)
double value;
char *ascii;
int width;
int prec1;
char format;
{
auto int expon;
auto int sign;
register int avail;
register char *a;
register char *p;
char mode;
int lowercase;
int prec;
char *fcvt(), *ecvt();
prec = prec1;
mode = format;
lowercase = 'a' - 'A';
if (mode >= 'a')
mode -= 'a' - 'A';
else
lowercase = 0;
if (mode != 'E')
{
/* try 'F' style output */
p = fcvt(value, prec, &expon, &sign);
avail = width;
a = ascii;
/* output sign */
if (sign)
{
avail--;
*a++ = '-';
}
/* output '0' before the decimal point */
if (expon <= 0)
{
*a++ = '0';
avail--;
}
/* compute space length left after dec pt and fraction */
avail -= prec + 1;
if (mode == 'G')
avail -= 4;
if (avail >= expon)
{
/* it fits. output */
while (expon > 0)
{
/* output left of dp */
expon--;
if (*p)
{
*a++ = *p++;
}
else
*a++ = '0';
}
/* output fraction (right of dec pt) */
avail = expon;
goto frac_out;
}
/* won't fit; let's hope for G format */
}
if (mode != 'F')
{
/* try to do E style output */
p = ecvt(value, prec + 1, &expon, &sign);
avail = width - 5;
a = ascii;
/* output the sign */
if (sign)
{
*a++ = '-';
avail--;
}
}
/* check for field too small */
if (mode == 'F' || avail < prec)
{
/* sorry joker, you lose */
a = ascii;
for (avail = width; avail > 0; avail--)
*a++ = '*';
*a = 0;
return (0);
}
/* it fits; output the number */
mode = 'E';
/* output the LHS single digit */
*a++ = *p++;
expon--;
/* output the rhs */
avail = 1;
frac_out:
*a++ = '.';
while (prec > 0)
{
prec--;
if (avail < 0)
{
avail++;
*a++ = '0';
}
else
{
if (*p)
*a++ = *p++;
else
*a++ = '0';
}
}
/* output the exponent */
if (mode == 'E')
{
*a++ = 'E' + lowercase;
if (expon < 0)
{
*a++ = '-';
expon = -expon;
}
else
*a++ = '+';
*a++ = (expon / 10) % 10 + '0';
*a++ = expon % 10 + '0';
}
/* output spaces on the end in G format */
if (mode == 'G')
{
*a++ = ' ';
*a++ = ' ';
*a++ = ' ';
*a++ = ' ';
}
/* finally, we can return */
*a = 0;
avail = a - ascii;
return (avail);
}