diff options
author | Roland McGrath <roland@gnu.org> | 1996-01-31 10:00:24 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 1996-01-31 10:00:24 +0000 |
commit | 01cdeca0c96838a92d9f810f9c4ae59e8129db2a (patch) | |
tree | c8f0ffd011deb496646771bf8fdf084e2c7281fb /stdio-common/vfscanf.c | |
parent | f0b11018358086848fe3b141a9520e1c6128211b (diff) | |
download | glibc-01cdeca0c96838a92d9f810f9c4ae59e8129db2a.tar.gz glibc-01cdeca0c96838a92d9f810f9c4ae59e8129db2a.tar.xz glibc-01cdeca0c96838a92d9f810f9c4ae59e8129db2a.zip |
Tue Jan 30 13:32:05 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu> cvs/libc-960131
* dirent/scandir.c: Allocate dirents with correct size for name, and copy with correct size. * hurd/hurdinit.c [! PIC] (map0): New function, on _hurd_preinit_hook. * stdio-common/vfscanf.c (TYPEMOD): New macro of all type modifier flag bits. (__vfscanf): Fix checking of extra type modifiers. * time/asia, time/australasia, time/backward: Updated from ADO 96b. Tue Jan 30 12:17:26 1996 Ulrich Drepper <drepper@ipd.info.uni-karlsruhe.de> * stdlib/strtod.c: Only negate exponent when there really is one. * stdio-common/vfscanf.c: Accept type modifiers on %n. Fix FP number parsing.
Diffstat (limited to 'stdio-common/vfscanf.c')
-rw-r--r-- | stdio-common/vfscanf.c | 47 |
1 files changed, 31 insertions, 16 deletions
diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c index 46f0658ef1..48aa059b9d 100644 --- a/stdio-common/vfscanf.c +++ b/stdio-common/vfscanf.c @@ -45,6 +45,8 @@ Cambridge, MA 02139, USA. */ # define GROUP 0x080 /* ': group numbers */ # define MALLOC 0x100 /* a: malloc strings */ +# define TYPEMOD (LONG|LONGDBL|SHORT) + #ifdef USE_IN_LIBIO # include <libioP.h> @@ -114,7 +116,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr) register int flags; /* Modifiers for current format element. */ /* Status for reading F-P nums. */ - char got_dot, got_e; + char got_dot, got_e, negative; /* If a [...] is a [^...]. */ char not_in; /* Base for integral numbers. */ @@ -307,7 +309,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr) { case 'h': /* int's are short int's. */ - if (flags & (LONG|LONGDBL)) + if (flags & TYPEMOD) /* Signal illegal format element. */ conv_error (); flags |= SHORT; @@ -328,12 +330,15 @@ __vfscanf (FILE *s, const char *format, va_list argptr) case 'q': case 'L': /* double's are long double's, and int's are long long int's. */ - if (flags & (LONG|SHORT)) + if (flags & TYPEMOD) /* Signal illegal format element. */ conv_error (); flags |= LONGDBL; break; case 'a': + if (flags & TYPEMOD) + /* Signal illegal format element. */ + conv_error (); /* String conversions (%s, %[) take a `char **' arg and fill it in with a malloc'd pointer. */ flags |= MALLOC; @@ -363,8 +368,18 @@ __vfscanf (FILE *s, const char *format, va_list argptr) break; case 'n': /* Answer number of assignments done. */ + /* Corrigendum 1 to ISO C 1990 describes the allowed flags + with the 'n' conversion specifier. */ if (!(flags & SUPPRESS)) - *ARG (int *) = read_in - 1; /* Don't count the read-ahead. */ + /* Don't count the read-ahead. */ + if (flags & LONGDBL) + *ARG (long long int *) = read_in - 1; + else if (flags & LONG) + *ARG (long int *) = read_in - 1; + else if (flags & SHORT) + *ARG (short int *) = read_in - 1; + else + *ARG (int *) = read_in - 1; break; case 'c': /* Match characters. */ @@ -439,7 +454,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr) { \ /* We lose. Oh well. \ Terminate the string and stop converting, \ - so at least we don't skip any input. */ \ + so at least we don't skip any input. */ \ (*strptr)[strsize] = '\0'; \ ++done; \ conv_error (); \ @@ -512,7 +527,6 @@ __vfscanf (FILE *s, const char *format, va_list argptr) { if (width > 0) --width; - ADDW ('0'); (void) inchar (); @@ -612,13 +626,15 @@ __vfscanf (FILE *s, const char *format, va_list argptr) /* Check for a sign. */ if (c == '-' || c == '+') { - ADDW (c); + negative = c == '-'; if (inchar () == EOF) /* EOF is only an input error before we read any chars. */ conv_error (); if (width > 0) --width; } + else + negative = 0; got_dot = got_e = 0; do @@ -628,7 +644,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr) else if (got_e && wp[wpsize - 1] == 'e' && (c == '-' || c == '+')) ADDW (c); - else if (!got_e && tolower (c) == 'e') + else if (wpsize > 0 && !got_e && tolower (c) == 'e') { ADDW ('e'); got_e = got_dot = 1; @@ -644,12 +660,10 @@ __vfscanf (FILE *s, const char *format, va_list argptr) break; if (width > 0) --width; - } while (inchar () != EOF && width != 0); + } + while (inchar () != EOF && width != 0); if (wpsize == 0) - conv_error(); - if (wp[wpsize - 1] == '-' || wp[wpsize - 1] == '+' - || wp[wpsize - 1] == 'e') conv_error (); /* Convert the number. */ @@ -658,19 +672,19 @@ __vfscanf (FILE *s, const char *format, va_list argptr) { long double d = __strtold_internal (wp, &tw, flags & GROUP); if (!(flags & SUPPRESS) && tw != wp) - *ARG (long double *) = d; + *ARG (long double *) = negative ? -d : d; } else if (flags & LONG) { double d = __strtod_internal (wp, &tw, flags & GROUP); if (!(flags & SUPPRESS) && tw != wp) - *ARG (double *) = d; + *ARG (double *) = negative ? -d : d; } else { float d = __strtof_internal (wp, &tw, flags & GROUP); if (!(flags & SUPPRESS) && tw != wp) - *ARG (float *) = d; + *ARG (float *) = negative ? -d : d; } if (tw == wp) @@ -738,7 +752,8 @@ __vfscanf (FILE *s, const char *format, va_list argptr) STRING_ADD_CHAR (c); if (width > 0) --width; - } while (inchar () != EOF && width != 0); + } + while (inchar () != EOF && width != 0); if (read_in == num.ul) conv_error (); |