Mail Archives: djgpp-workers/2003/04/01/10:39:46
Hello.
Below is my work-in-progress for *printf and supporting nan(0x[0-9a-f]*).
This is just for information - don't apply this!
Bye, Rich =]
Index: src/libc/ansi/stdio/doprnt.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/ansi/stdio/doprnt.c,v
retrieving revision 1.14
diff -p -c -3 -r1.14 doprnt.c
*** src/libc/ansi/stdio/doprnt.c 24 Jan 2003 18:53:33 -0000 1.14
--- src/libc/ansi/stdio/doprnt.c 1 Apr 2003 15:37:44 -0000
***************
*** 17,22 ****
--- 17,30 ----
#include <math.h>
#include <libc/file.h>
#include <libc/local.h>
+ #include <libc/ieee.h>
+
+ struct IEEExp {
+ unsigned manl:32;
+ unsigned manh:32;
+ unsigned exp:15;
+ unsigned sign:1;
+ };
static char decimal = '.';
*************** static char decimal = '.';
*** 40,47 ****
flags&CHARINT ? (char basetype)va_arg(argp, int) : \
(basetype)va_arg(argp, int)
- static int nan_p = 0;
-
static __inline__ int todigit(char c)
{
if (c<='0') return 0;
--- 48,53 ----
*************** static char *roundl(long double fract, i
*** 72,82 ****
char ch, char *signp);
static char *exponentl(char *p, int expv, unsigned char fmtch);
#ifdef __GO32__
! static int isspeciall(long double d, char *bufp);
#endif
static char NULL_REP[] = "(null)";
! static char UNNORMAL_REP[] = "Unnormal";
int
_doprnt(const char *fmt0, va_list argp, FILE *fp)
--- 78,91 ----
char ch, char *signp);
static char *exponentl(char *p, int expv, unsigned char fmtch);
#ifdef __GO32__
! static int isspeciall(long double d, const int was_double, const int do_upper,
! char *signp, char *startp, char *endp);
#endif
static char NULL_REP[] = "(null)";
! static const char UNNORMAL_REP[] = "Unnormal";
! static const char HEX_LOWER_DIGITS[] = "0123456789abcdef";
! static const char HEX_UPPER_DIGITS[] = "0123456789ABCDEF";
int
_doprnt(const char *fmt0, va_list argp, FILE *fp)
*************** _doprnt(const char *fmt0, va_list argp,
*** 115,121 ****
return (EOF);
fmt = fmt0;
! digs = "0123456789abcdef";
for (cnt = 0;; ++fmt)
{
while ((ch = *fmt) && ch != '%')
--- 124,130 ----
return (EOF);
fmt = fmt0;
! digs = HEX_LOWER_DIGITS;
for (cnt = 0;; ++fmt)
{
while ((ch = *fmt) && ch != '%')
*************** _doprnt(const char *fmt0, va_list argp,
*** 239,244 ****
--- 248,254 ----
case 'e':
case 'E':
case 'f':
+ case 'F':
case 'g':
case 'G':
if (flags & LONGDBL)
*************** _doprnt(const char *fmt0, va_list argp,
*** 274,285 ****
}
else
{
! struct IEEExp {
! unsigned manl:32;
! unsigned manh:32;
! unsigned exp:15;
! unsigned sign:1;
! } ip = *(struct IEEExp *)&_ldouble;
if (ip.sign)
neg_ldouble = 1;
--- 284,290 ----
}
else
{
! struct IEEExp ip = *(struct IEEExp *)&_ldouble;
if (ip.sign)
neg_ldouble = 1;
*************** _doprnt(const char *fmt0, va_list argp,
*** 301,309 ****
* will be shown, and we also print a sign for a NaN. In
* other words, "%+f" might print -0.000000, +NaN and -NaN.
*/
! if (softsign || (sign == '+' && (neg_ldouble || nan_p == -1)))
sign = '-';
- nan_p = 0;
t = *buf ? buf : buf + 1;
goto pforw;
case 'n':
--- 306,313 ----
* will be shown, and we also print a sign for a NaN. In
* other words, "%+f" might print -0.000000, +NaN and -NaN.
*/
! if (softsign || (sign == '+' && neg_ldouble))
sign = '-';
t = *buf ? buf : buf + 1;
goto pforw;
case 'n':
*************** _doprnt(const char *fmt0, va_list argp,
*** 370,376 ****
base = 10;
goto nosign;
case 'X':
! digs = "0123456789ABCDEF";
/* FALLTHROUGH */
case 'x':
ARG(unsigned);
--- 374,380 ----
base = 10;
goto nosign;
case 'X':
! digs = HEX_UPPER_DIGITS;
/* FALLTHROUGH */
case 'x':
ARG(unsigned);
*************** _doprnt(const char *fmt0, va_list argp,
*** 419,425 ****
*--t = '0'; /* octal leading 0 */
}
! digs = "0123456789abcdef";
size = buf + BUF - t;
pforw:
--- 423,429 ----
*--t = '0'; /* octal leading 0 */
}
! digs = HEX_LOWER_DIGITS;
size = buf + BUF - t;
pforw:
*************** cvtl(long double number, int prec, int f
*** 527,533 ****
int doingzero=0; /* We're displaying 0.0 */
long double integer, tmp;
! if ((expcnt = isspeciall(number, startp)))
return(expcnt);
dotrim = expcnt = gformat = 0;
--- 531,539 ----
int doingzero=0; /* We're displaying 0.0 */
long double integer, tmp;
! if ((expcnt = isspeciall(number,
! !(flags & LONGDBL) /* double -> long double? */,
! isupper(fmtch), signp, startp, endp)))
return(expcnt);
dotrim = expcnt = gformat = 0;
*************** cvtl(long double number, int prec, int f
*** 595,600 ****
--- 601,607 ----
switch(fmtch)
{
case 'f':
+ case 'F':
/* reverse integer into beginning of buffer */
if (expcnt)
for (; ++p < endp; *t++ = *p);
*************** exponentl(char *p, int expv, unsigned ch
*** 890,924 ****
}
static int
! isspeciall(long double d, char *bufp)
{
! struct IEEExp {
! unsigned manl:32;
! unsigned manh:32;
! unsigned exp:15;
! unsigned sign:1;
! } *ip = (struct IEEExp *)&d;
! nan_p = 0; /* don't assume the static is 0 (emacs) */
/* Unnormals: the MSB of mantissa is non-zero, but the exponent is
not zero either. */
! if ((ip->manh & 0x80000000U) == 0 && ip->exp != 0)
{
! if (ip->sign)
*bufp++ = '-';
strcpy(bufp, UNNORMAL_REP);
! return strlen(bufp) + ip->sign;
}
! if (ip->exp != 0x7fff)
return(0);
! if ((ip->manh & 0x7fffffff) || ip->manl)
! {
! strcpy(bufp, "NaN");
! nan_p = ip->sign ? -1 : 1; /* kludge: we don't need the sign, it's
! not nice, but it should work */
! }
else
! (void)strcpy(bufp, "Inf");
! return(3);
}
--- 897,1043 ----
}
static int
! hexify (unsigned t, char **p, int leading_zero, const char *digs)
! {
! int i = 7;
!
! /* Skip leading zeroes, if any. */
! if (leading_zero)
! {
! for (; i >= 0; i--)
! {
! if ((t >> (i * 4)) & 0xf)
! break;
! }
! }
!
! if (i >= 0)
! leading_zero = 0;
!
! for (; i >= 0; i--)
! {
! **p = digs[(t >> (i * 4)) & 0xf];
! (*p)++;
! }
!
! return(leading_zero);
! }
!
! static void
! addnan (const long double ld, const struct IEEExp ip,
! const int was_double /* was double converted to a long double? */,
! const int do_upper /* inf & nan should be upper-case? */,
! char *startp, char *endp)
! {
! const char *digs = NULL;
!
! /* For converting the long double back to a double, if necessary. */
! double d;
! double_t ip_d;
!
! /* For checking whether we have one of the NaN values that we don't
! * expand to nan(0x[0-9a-f]*). */
! long double ld_cast_nan = NAN;
! long_double_t ip_ld_cast_nan;
!
! double_t ip_d_nan = { 0xffffffffU, 0xfffffU, 0x7ffU, 0U };
! long_double_t ip_ld_nan = { 0xffffffffU, 0xffffffffU, 0x7fffU, 0U };
!
! int do_brackets = 1;
! int leading_zero = 1;
! char *p;
!
! ip_ld_cast_nan = *(long_double_t *)&ld_cast_nan;
!
! if (was_double)
! {
! d = (double)ld;
! ip_d = *(double_t *)&d;
! }
!
! if (do_upper)
! digs = HEX_UPPER_DIGITS;
! else
! digs = HEX_LOWER_DIGITS;
!
! strcpy(startp, do_upper ? "NAN" : "nan");
!
! /* If the NaN is one of the following, don't expand the brackets:
! *
! * 1. a long-double NaN;
! * 2. a double NaN;
! * 3. a float NaN (NB: it's been cast to long double).
! */
! if ( (ip.manh == ip_ld_nan.mantissah)
! && (ip.manl == ip_ld_nan.mantissal))
! do_brackets = 0;
!
! /* TODO: I think we need to test for double NaN cast
! * to a long double too. Maybe one test when !was_double,
! * one test when was_double? */
! if ( (ip_d.mantissah == ip_d_nan.mantissah)
! && (ip_d.mantissal == ip_d_nan.mantissal))
! do_brackets = 0;
!
! if ( (ip.manh == ip_ld_cast_nan.mantissah)
! && (ip.manl == ip_ld_cast_nan.mantissal))
! do_brackets = 0;
!
! if (do_brackets)
! {
! strcat(startp, "(0x");
!
! p = startp + strlen(startp);
! leading_zero = hexify(was_double ? ip_d.mantissah : ip.manh,
! &p, leading_zero, digs);
! leading_zero = hexify(was_double ? ip_d.mantissal : ip.manl,
! &p, leading_zero, digs);
!
! /* If no digits have been written, just write 0. */
! if (leading_zero)
! {
! *p = digs[0];
! p++;
! }
!
! *p = '\0';
!
! strcat(startp, ")");
! }
! }
!
! static int
! isspeciall(long double ld,
! const int was_double /* was double converted to a long double? */,
! const int do_upper /* inf & nan should be upper-case? */,
! char *signp, char *startp, char *endp)
{
! struct IEEExp ip = *(struct IEEExp *)&ld;
! /* TODO: Buffer overflows? */
/* Unnormals: the MSB of mantissa is non-zero, but the exponent is
not zero either. */
! if ((ip.manh & 0x80000000U) == 0 && ip.exp != 0)
{
! char *bufp = startp;
!
! if (ip.sign)
*bufp++ = '-';
strcpy(bufp, UNNORMAL_REP);
! return strlen(bufp) + ip.sign;
}
!
! if (ip.exp != 0x7fffU)
return(0);
!
! if (ip.sign)
! *signp = '-';
!
! if (!(ip.manh & 0x7fffffffU) && !ip.manl)
! strcpy(startp, do_upper ? "INF" : "inf");
else
! addnan(ld, ip, was_double, do_upper, startp, endp);
!
! return(strlen(startp));
}
- Raw text -