delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2003/04/01/10:39:46

Date: Tue, 01 Apr 2003 16:43:23 +0100
From: "Richard Dawe" <rich AT phekda DOT freeserve DOT co DOT uk>
Sender: rich AT phekda DOT freeserve DOT co DOT uk
To: djgpp-workers AT delorie DOT com
X-Mailer: Emacs 21.3.50 (via feedmail 8.3.emacs20_6 I) and Blat ver 1.8.6
Subject: *printf and nan(0x[0-9a-f]*) - work-in-progress [PATCH]
Message-Id: <E190NrM-00010d-00@phekda.freeserve.co.uk>
Reply-To: djgpp-workers AT delorie DOT com

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 -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019