delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2003/04/07/08:01:03

Sender: rich AT phekda DOT freeserve DOT co DOT uk
Message-ID: <3E91678A.7F3AC0D2@phekda.freeserve.co.uk>
Date: Mon, 07 Apr 2003 12:56:58 +0100
From: Richard Dawe <rich AT phekda DOT freeserve DOT co DOT uk>
X-Mailer: Mozilla 4.77 [en] (X11; U; Linux 2.2.23 i586)
X-Accept-Language: de,fr
MIME-Version: 1.0
To: djgpp-workers AT delorie DOT com
Subject: Re: %n$, *m$ and some other c99 support for doprnt.c
References: <3E8B4CC9 DOT E21C27CF AT hrz1 DOT hrz DOT tu-darmstadt DOT de>
Reply-To: djgpp-workers AT delorie DOT com

Hello.

Juan Manuel Guerrero wrote:
> This is a patch to implement %n$, *m$ and some other c99 support for
> _doprnt.c.

Here are some comments on the patch:

[snip]
> diff -acprNC3 djgpp.orig/src/libc/ansi/stdio/doprnt.c djgpp/src/libc/ansi/stdio/doprnt.c
> *** djgpp.orig/src/libc/ansi/stdio/doprnt.c     Fri Oct 18 01:00:24 2002
> --- djgpp/src/libc/ansi/stdio/doprnt.c  Sun Oct 27 20:34:02 2002
[snip]
> *************** static int isspeciall(long double d, cha
> *** 75,80 ****
> --- 125,535 ----
> 
>   static char NULL_REP[] = "(null)";
>   static char UNNORMAL_REP[] = "Unnormal";
> + static char INF_REP[2][4] = {"inf", "INF"};  /* inf for [aefg] and INF for [aefg] */
> + static char NAN_REP[2][4] = {"nan", "NAN"};  /* nan for [aefg] and NAN for [aefg] */

Surely the second "[aefg]" should be "[AEFG]" for both INF_REP and NAN_REP?

Where possible, I think we should declare these character arrays as "const".
From what I remember of my work on making printf output nan(0x[0-9a-f]*) for
NaNs, NULL_REP can't be made const, but the others can.

[snip]
> *************** cvtl(long double number, int prec, int f
> *** 510,515 ****
> --- 1143,1284 ----
>     if ((expcnt = isspeciall(number, startp)))
>       return(expcnt);
> 
> +   if (fmtch == 'a' || fmtch == 'A')
> +   {
> +     /*
> +      *  We are dealing with intel's extended double format.
> +      *  The 64-bit mantissa explicitely contains the leading integer digit.
> +      *  C99 standard defines hex float format as: 0xh.hhhp+ddd
> +      *  where h is a hex digit, d is a decimal digit and p represents 2.
> +      *  The standard defines that the hex representation of the binary
> +      *  mantissa must be exact for all precisions greater zero.
> +      *  This implies that the 15 hex digits of the fractional part of the
> +      *  mantissa will always be outputed even if the requested precision
> +      *  is less than 15. If the requested precision is more than 15 digits
> +      *  then the mantissa is paded with zeros to the right. If the requested
> +      *  precision is zero then the leading hex digit will be rounded
> +      *  appropiately and the hole fractional part will be omitted.
> +      *  The 64 bit of the mantissa can be subdivided into 16 nibbles,
> +      *  so exact hex representation of the binary coded mantissa is
> +      *  possible. To get a single hex digit in the integer part of
> +      *  the mantissa the period must be shifted by three places
> +      *  to the right. This makes it necessary to adjust the bias
> +      *  from 0x3fff to 0x4002.
> +      */
> +
> + #define IEEE754_LONG_DOUBLE_BIAS                0x3fff
> + #define LONG_DOUBLE_BIAS                       (IEEE754_LONG_DOUBLE_BIAS + 0x03)
> + #define LONG_DOUBLE_DENORMALIZED_BIAS          (LONG_DOUBLE_BIAS - 0x01)
> +
> + #define ITOA(value, base, string_end, case)                 \
> +     /* Create a string from a positive/unsigned integer */  \
> +     do {                                                    \
> +       const char  udigits[] = "0123456789ABCDEF";           \
> +       const char  ldigits[] = "0123456789abcdef";           \
> +       const char *digit = (case) ? udigits : ldigits;       \

You should probably set these up outside the loop. I expect the compiler will
do that optimisation for you, but why rely on the compiler?

> +                                                             \
> +       do {                                                  \
> +         *--(string_end) = digit[(value) % (base)];          \
> +       } while ((value) /= (base));                          \
> +     } while (0)

Maybe his could be done as a static inline function instead? (I have a
personal preference of inline functions over macros (where possible), so feel
free to ignore me.)

> +
> +
> +     struct IEEExp {
> +       unsigned manl:32;
> +       unsigned manh:32;
> +       unsigned exp:15;
> +       unsigned sign:1;
> +     } *ip = (struct IEEExp *)&number;

[snip]
> diff -acprNC3 djgpp.orig/src/libc/ansi/stdio/printf.txh djgpp/src/libc/ansi/stdio/printf.txh
> *** djgpp.orig/src/libc/ansi/stdio/printf.txh   Thu Oct 17 12:17:18 2002
> --- djgpp/src/libc/ansi/stdio/printf.txh        Sun Oct 27 20:42:40 2002
> *************** int printf(const char *format, @dots{});
> *** 12,19 ****
>   Sends formatted output from the arguments (@dots{}) to @code{stdout}.
> 
>   The format string contains regular characters to print, as well as
> ! conversion specifiers, which begin with a percent symbol.  Each
> ! conversion speficier contains the following fields:
> 
>   @itemize @bullet
> 
> --- 12,35 ----
>   Sends formatted output from the arguments (@dots{}) to @code{stdout}.
> 
>   The format string contains regular characters to print, as well as
> ! conversion specifiers, which begin with a percent symbol.  Conversions
> ! can be applied to the nth argument after the format string in the argument
> ! list, rather than to the next unused argument.  In this case, the conversion
> ! specifier character @code{%} is replaced by the sequence @code{"%n$"}, where
> ! @code{n} is a decimal integer in the range [@code{1}, @code{NL_ARGMAX}],
> ! giving the position of the argument in the argument list.  @code{NL_ARGMAX}
> ! is the number of the last argument in the argument list.  The format string
> ! can contain either numbered argument conversion specifiers (that is,
> ! @code{"%n$"} and @code{"*m$"}), or unnumbered argument conversion specifiers
> ! (that is @code{%} and @code{*}), but not both.  The only exception to this
> ! is that @code{%%} can be mixed with @code{"%n$"} form.  When numbered argument
> ! specifications are used, specifying the Nth argument requires that all the
> ! leading arguments, from the first to the (N-1)th, are specified in the format
> ! string.  In format strings containig the @code{"%n$"} form of conversion

"containig" -> "containing"

> ! specification, numbered arguments in the argument list can be referenced
> ! from the format string as many times as required.
> !
> ! Each conversion speficier contains the following fields:

"speficier" -> "specifier"

> 
>   @itemize @bullet
> 

[snip]
> *************** The precision specifies the minimum numb
> *** 62,73 ****
>   integer, the number of fraction digits for a floating point number (max
>   for @code{g} or @code{G}, actual for others), or the maximum number of
>   characters for a string.
> 
>   @item
> 
> ! An optional conversion qualifier, which may be @code{h} to specify
> ! @code{short}, @code{l} to specify long ints, or @code{L} to specify
> ! long doubles. Long long type can be specified by @code{L} or @code{ll}.
> 
>   @item
> 
> --- 90,109 ----
>   integer, the number of fraction digits for a floating point number (max
>   for @code{g} or @code{G}, actual for others), or the maximum number of
>   characters for a string.
> + In format strings containing the @code{"%n$"} form of a conversion
> + specification, a precision can be indicated by the sequence @code{"*m$"},
> + where m is a decimal integer in the range [@code{1}, @code{NL_ARGMAX}],
> + giving the position in the argument list (after the format argument) of
> + an integer argument containing the precision.
> 
>   @item
> 
> ! An optional conversion qualifier, which may be @code{hh} to specify
> ! @code{char},  @code{h} to specify @code{short}, @code{l} to specify
> ! @code{long int}, @code{ll} (ell-ell) to specify @code{long long int},
> ! @code{j} to specify @code{intmax_t}, @code{t} to specify @code{ptrdiff_t},
> ! @code{z} to specify @code{size_t} or @code{L} to specify @code{long double}.
> ! Long long type can be specified by @code{L} or @code{ll}.

That's not true. Only 'll' is specified by the C standard for long longs. 'L'
is a DJGPP-specific extension. I don't think we should document it, to
encourgae people to use the standard conversion qualifier. I've removed the
description of 'L' for long longs in CVS.

>   @item
> 
> *************** A signed integer.
> *** 88,93 ****
> --- 124,139 ----
>   A signed long integer.  This is non-standard and obsolete.
>   Please use @code{ld} instead.
> 
> + @item a
> + @itemx A
> +
> + A floating point number (float or double) printed in the style
> + @code{"[-]0xh.hhhhp[+|-]dd"}, where @code{h} represents a hexadecimal
> + digit, @code{d} represents a decimal digit and @code{p} stands for the
> + base 2.  For long double, use @code{"La"} or @code{"LA"}.  The exponent
> + case, the letters @code{"abcdef"} case and the @code{"x"} case matches

"the letters @code{"abcdef"} case" -> "the case of the letters
@code{"abcdef"}"

It should probably be "the case of the exponent" and "the case of the
@code{"x"}" too.

> + the specifier case.  The representation always has an exponent.
> +
>   @item e
>   @itemx E
> 
[snip]

Bye, Rich =]

-- 
Richard Dawe [ http://www.phekda.freeserve.co.uk/richdawe/ ]

- Raw text -


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