X-Authentication-Warning: delorie.com: mail set sender to djgpp-workers-bounces using -f X-Recipient: djgpp-workers AT delorie DOT com X-Authenticated: #27081556 X-Provags-ID: V01U2FsdGVkX18sDss3RXIsMiM6uwsuf3V060oFxUYNcXI3c1/gLq 4jiJtpg3CY9La2 Message-ID: <50C3E68F.6080205@gmx.de> Date: Sun, 09 Dec 2012 02:17:03 +0100 From: Juan Manuel Guerrero User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:16.0) Gecko/20121025 Thunderbird/16.0.2 MIME-Version: 1.0 To: djgpp-workers AT delorie DOT com Subject: %[aA] conversion specifier for scanf Content-Type: text/plain; charset=ISO-8859-15; format=flowed Content-Transfer-Encoding: 7bit X-Y-GMX-Trusted: 0 Reply-To: djgpp-workers AT delorie DOT com A couple of years ago I implemented the conversion of hex floating point strings of the form 0xH.HHH[P|p][+|-]DDD for strtod and forgot to commit the corresponding %[aA] conversion specifier for scanf. Regards, Juan M. Guerrero 2009-02-02 Juan Manuel Guerrero * src/libc/ansi/stdio/doscan.c: Support for %[aA] conversion specifier added. * src/libc/ansi/stdio/scanf.txh: Information about %[aAF] conversion specifier added. * src/docs/kb/wc204.txi: Info about %[aAF] conversion specifier for doscan() added. * tests/libc/ansi/stdio/tscanf.c: Test case for %[aAF] conversion specifier added. diff -aprNU5 djgpp.orig/src/docs/kb/wc204.txi djgpp/src/docs/kb/wc204.txi --- djgpp.orig/src/docs/kb/wc204.txi 2012-10-03 19:34:16 +0000 +++ djgpp/src/docs/kb/wc204.txi 2012-12-08 23:27:52 +0000 @@ -1248,5 +1248,11 @@ overflown. The bit set in case of overf @pindex djtar AT r{, support for @code{tar} archives with @code{pax} headers} The djtar program can now unpack @code{tar} archives that contain @code{pax} headers conforming to @acronym{POSIX} 1003.1-2001. The @code{pax} headers are always skipped and their contents are discarded. + +@findex _doscan AT r{, and C99 conversion specifiers} +@findex scanf AT r{, and C99 conversion specifiers} +The @code{a}, @code{A} and @code{F} conversion specifiers +are now supported by @code{_doscan} and the @code{scanf} +family of functions. diff -aprNU5 djgpp.orig/src/libc/ansi/stdio/doscan.c djgpp/src/libc/ansi/stdio/doscan.c --- djgpp.orig/src/libc/ansi/stdio/doscan.c 2012-12-08 22:16:32 +0000 +++ djgpp/src/libc/ansi/stdio/doscan.c 2012-12-08 23:32:48 +0000 @@ -1,5 +1,6 @@ +/* Copyright (C) 2012 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 2002 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ @@ -42,11 +43,11 @@ static char _sctab[256] = { 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, }; static int nchars = 0; -static char decimal = '.'; +static char decimal_point = '.'; int _doscan(FILE *iop, const char *fmt, va_list argp) { return(_doscan_low(iop, fgetc, ungetc, fmt, argp)); @@ -58,11 +59,11 @@ _doscan_low(FILE *iop, int (*scan_getc)( register int ch; int nmatch, len, ch1; int *ptr, fileended, size; int suppressed; - decimal = localeconv()->decimal_point[0]; + decimal_point = localeconv()->decimal_point[0]; nchars = 0; nmatch = 0; fileended = 0; suppressed = 0; @@ -241,16 +242,16 @@ _innum(int *ptr, int type, int len, int return (_instr(ptr ? (char *)ptr : (char *)NULL, type, len, iop, scan_getc, scan_ungetc, eofptr)); lcval = 0; ndigit = 0; scale = INT; - if (type == 'e' || type == 'f' || type == 'g') + if (type == 'a' || type == 'e' || type == 'f' || type == 'g') scale = FLOAT; base = 10; if (type == 'o') base = 8; - else if (type == 'x' || type == 'p') + else if (type == 'x' || type == 'p' || type == 'a') base = 16; np = numbuf; expseen = 0; negflg = 0; @@ -277,11 +278,11 @@ _innum(int *ptr, int type, int len, int for ( ; --len >= 0; *np++ = c, c = scan_getc(iop), nchars++) { cpos++; if (c == '0' && cpos == 1 && type == 'i') base = 8; - if ((c == 'x' || c == 'X') && (type == 'i' || type == 'x') + if ((c == 'x' || c == 'X') && (type == 'a' || type == 'i' || type == 'x') && cpos == 2 && lcval == 0) { base = 16; continue; } @@ -304,20 +305,20 @@ _innum(int *ptr, int type, int len, int c -= 'A' - 10; lcval += c; c = c1; continue; } - else if (c == decimal) + else if (c == decimal_point) { - if (base != 10 || scale == INT) + if (scale == INT || base == 8) break; ndigit++; continue; } else if ((c == 'e' || c == 'E') && expseen == 0) { - if (base != 10 || scale == INT || ndigit == 0) + if (scale == INT || base == 8 || ndigit == 0) break; expseen++; *np++ = c; c = scan_getc(iop); nchars++; diff -aprNU5 djgpp.orig/src/libc/ansi/stdio/scanf.txh djgpp/src/libc/ansi/stdio/scanf.txh --- djgpp.orig/src/libc/ansi/stdio/scanf.txh 2003-01-29 12:28:44 +0000 +++ djgpp/src/libc/ansi/stdio/scanf.txh 2012-12-08 23:35:12 +0000 @@ -113,27 +113,45 @@ Convert the input to a @code{ptrdiff_t} @item zd Convert the input to a @code{size_t} using 10 as the base. + +@item a +@itemx A + +Convert the input of the form [+|-]0xH.HHHHp|P[+|-]DDD to a floating point number (a @code{float}). + @item e @itemx E @itemx f @itemx F @itemx g @itemx G Convert the input to a floating point number (a @code{float}). +@item la +@itemx lA + +Convert the input of the form [+|-]0xH.HHHHp|P[+|-]DDD to a floating point number (a @code{double}). + @item le @itemx lE @itemx lf @itemx lF @itemx lg @itemx lG -Convert the input to a @code{double}. +Convert the input to a floating point number (a @code{double}). + +@item La +@itemx LA +@item lla +@itemx llA + +Convert the input of the form [+|-]0xH.HHHHp|P[+|-]DDD to a floating point number (a @code{double}). @item Le @itemx LE @itemx lle @itemx llE @@ -144,11 +162,11 @@ Convert the input to a @code{double}. @itemx Lg @itemx LG @itemx llg @itemx llG -Convert the input to a @code{long double}. +Convert the input to a floating point number (a @code{long double}. @item i Convert the input, determining base automatically by the presence of @code{0x} or @code{0} prefixes, and store in a signed @code{int}. @@ -389,11 +407,12 @@ The conversion specifiers for the @code{ GCC extensions. The meaning of @samp{[a-c]} as a range of characters is a very popular extension to ANSI (which merely says a dash ``may have a special meaning'' in that context). @port-note ansi-c99 The @code{hh}, @code{j}, @code{t} -and @code{z} conversion specifiers first appeared +and @code{z} length modifiers and the @code{a}, @code{A} +and @code{F} conversion specifiers first appeared in the ANSI C99 standard. @portability ansi, posix @subheading Example diff -aprNU5 djgpp.orig/tests/libc/ansi/stdio/tscanf.c djgpp/tests/libc/ansi/stdio/tscanf.c --- djgpp.orig/tests/libc/ansi/stdio/tscanf.c 2002-06-08 13:54:12 +0000 +++ djgpp/tests/libc/ansi/stdio/tscanf.c 2012-12-09 01:32:02 +0000 @@ -117,12 +117,13 @@ int convert_and_print (const char *fmt, else printf ("Result: long %ld (0x%lx)\n", lnum[0], lnum[0]); return converted; } + case 'a': case 'A': case 'e': case 'E': - case 'f': + case 'f': case 'F': case 'g': case 'G': if (cnv_qual == 'L') { long double ldnum[2]; @@ -133,11 +134,16 @@ int convert_and_print (const char *fmt, printf ("ERROR: more than a single long double converted!\n"); printf ("Result: %.21Lg\n", ldnum[0]); converted = 0; } else - printf ("Result: long double %.21Lg\n", ldnum[0]); + { + if (cnv_spec == 'a' || cnv_spec == 'A') + printf ("Result: long double hex %.15La long double dec %.21Lg\n", ldnum[0], ldnum[0]); + else + printf ("Result: long double %.21Lg\n", ldnum[0]); + } return converted; } else if (cnv_qual == 'l') { @@ -150,11 +156,16 @@ int convert_and_print (const char *fmt, printf ("ERROR: more than a single double converted!\n"); printf ("Result: %.17g\n", dnum[0]); converted = 0; } else - printf ("Result: double %.17g\n", dnum[0]); + { + if (cnv_spec == 'a' || cnv_spec == 'A') + printf ("Result: double hex %.13a double dec %.17g\n", dnum[0], dnum[0]); + else + printf ("Result: long double %.17g\n", dnum[0]); + } return converted; } else { @@ -167,11 +178,16 @@ int convert_and_print (const char *fmt, printf ("ERROR: more than a single float converted!\n"); printf ("Result: %.7g\n", fnum[0]); converted = 0; } else - printf ("Result: float %.7g\n", fnum[0]); + { + if (cnv_spec == 'a' || cnv_spec == 'A') + printf ("Result: float hex %.6a float dec %.7g\n", fnum[0], fnum[0]); + else + printf ("Result: float %.7g\n", fnum[0]); + } return converted; } default: printf ("I don't know what to do with format `%s'...\n", fmt);