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 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> Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit 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/ ]