diff options
author | Roland McGrath <roland@gnu.org> | 1995-12-05 03:35:55 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 1995-12-05 03:35:55 +0000 |
commit | 77a58cad3fa0a286bd2581187a2463a762d711ba (patch) | |
tree | 50756d67e82e3edbe49f722662b0bed8c0cd19cc /stdio-common/vfscanf.c | |
parent | b5a08c5aca57835de5f69b8b017f09cd75f5cf7d (diff) | |
download | glibc-77a58cad3fa0a286bd2581187a2463a762d711ba.tar.gz glibc-77a58cad3fa0a286bd2581187a2463a762d711ba.tar.xz glibc-77a58cad3fa0a286bd2581187a2463a762d711ba.zip |
Tue Dec 5 02:27:32 1995 Ulrich Drepper <drepper@gnu.ai.mit.edu>
* libio/Makefile [routines]: Remove iofscanf, add iopopen, pclose. * libio/iofscanf.c: Remove file. * libio/iogetdelim.c (_IO_getdelim): Correct stupid bug at string termination. * libio/iopopen.c: New file from GNU libio. * libio/memstream.c: Fixed bug in fclose handling. Instead of providing a close callback we need a finish callback. * libio/pclose.c: New file. Derived from popen.c in GNU libio. * posix/gnu/types.h: Fixed typo. * stdio-common/errnobug.c: fputs returns EOF in error case. Do not test for != 0. * stdio-common/printf-parse.h (parse_one_spec): Do not force padding with ' ' if precision is given. Fix by HJ Lu. * stdio-common/printf_fp.c: Fix comment. * stdio-common/tfformat.c, stdio-common/tiformat.c, stdio-common/tstdiomisc.c: New files from GNU libio test suite. * stdio-common/tstgetln.c: Provide ssize_t type when testing libio. * stdio-common/vfprintf.c (outchar): Use PUTC instead of putc. (vfprintf): Cleasr args_type array before using it. When printing 0 as an integer with precision 0 nothing must be written for the number. Based on patch by HJ Lu. * stdio-common/vfscanf.c: Remove fixed input buffer. Now we have a dynamically extended buffer. * stdlib/strtod.c: Merge with version in Linux libc. This fixes some bugs with handling of very small numbers and has different solution for formaer patches. * sysdeps/i386/i586/add_n.S, sysdeps/i386/i586/sub_n.S: Rename macros r1 and r2 to t1, and t2 resp. This is necessary because glibc headers also define r1. Tue Dec 5 02:27:32 1995 Ulrich Drepper <drepper@gnu.ai.mit.edu> * libio/Makefile [routines]: Remove iofscanf, add iopopen, pclose. * libio/iofscanf.c: Remove file. * libio/iogetdelim.c (_IO_getdelim): Correct stupid bug at string termination. * libio/iopopen.c: New file from GNU libio. * libio/memstream.c: Fixed bug in fclose handling. Instead of providing a close callback we need a finish callback. * libio/pclose.c: New file. Derived from popen.c in GNU libio. * posix/gnu/types.h: Fixed typo. * stdio-common/errnobug.c: fputs returns EOF in error case. Do not test for != 0. * stdio-common/printf-parse.h (parse_one_spec): Do not force padding with ' ' if precision is given. Fix by HJ Lu. * stdio-common/printf_fp.c: Fix comment. * stdio-common/tfformat.c, stdio-common/tiformat.c, stdio-common/tstdiomisc.c: New files from GNU libio test suite. * stdio-common/tstgetln.c: Provide ssize_t type when testing libio. * stdio-common/vfprintf.c (outchar): Use PUTC instead of putc. (vfprintf): Cleasr args_type array before using it. When printing 0 as an integer with precision 0 nothing must be written for the number. Based on patch by HJ Lu. * stdio-common/vfscanf.c: Remove fixed input buffer. Now we have a dynamically extended buffer. * stdlib/strtod.c: Merge with version in Linux libc. This fixes some bugs with handling of very small numbers and has different solution for formaer patches. * sysdeps/i386/i586/add_n.S, sysdeps/i386/i586/sub_n.S: Rename macros r1 and r2 to t1, and t2 resp. This is necessary because glibc headers also define r1.
Diffstat (limited to 'stdio-common/vfscanf.c')
-rw-r--r-- | stdio-common/vfscanf.c | 94 |
1 files changed, 56 insertions, 38 deletions
diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c index b0e48df4f8..76c9936abe 100644 --- a/stdio-common/vfscanf.c +++ b/stdio-common/vfscanf.c @@ -132,6 +132,8 @@ __vfscanf (FILE *s, const char *format, va_list argptr) int base; /* Signedness for integral numbers. */ int number_signed; + /* Decimal point character. */ + wchar_t decimal; /* Integral holding variables. */ union { @@ -144,9 +146,24 @@ __vfscanf (FILE *s, const char *format, va_list argptr) register char *str, **strptr; size_t strsize; /* Workspace. */ - char work[200]; - char *w; /* Pointer into WORK. */ - wchar_t decimal; /* Decimal point character. */ + char *tw; /* Temporary pointer. */ + char *wp = NULL; /* Workspace. */ + size_t wpsize = 0; /* Currently used bytes in workspace. */ + size_t wpmax = 0; /* Maximal size of workspace. */ +#define ADDW(Ch) \ + do \ + { \ + if (wpsize == wpmax) \ + { \ + char *old = wp; \ + wpmax = 200 > 2 * wpmax ? 200 : 2 * wpmax; \ + wp = (char *) alloca (wpmax); \ + if (wpsize > 0) \ + memcpy (wp, old, wpsize); \ + } \ + wp[wpsize++] = (Ch); \ + } \ + while (0) ARGCHECK (s, format); @@ -338,7 +355,6 @@ __vfscanf (FILE *s, const char *format, va_list argptr) conv_error (); /* Find the conversion specifier. */ - w = work; fc = *f++; if (fc != '[' && fc != 'c' && fc != 'n') /* Eat whitespace. */ @@ -490,7 +506,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr) /* Check for a sign. */ if (c == '-' || c == '+') { - *w++ = c; + ADDW (c); if (width > 0) --width; (void) inchar (); @@ -501,7 +517,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr) { if (width > 0) --width; - *w++ = '0'; + ADDW ('0'); (void) inchar (); @@ -523,40 +539,40 @@ __vfscanf (FILE *s, const char *format, va_list argptr) if (base == 0) base = 10; - /* Read the number into WORK. */ + /* Read the number into workspace. */ do { if (base == 16 ? !isxdigit (c) : (!isdigit (c) || c - '0' >= base)) break; - *w++ = c; + ADDW (c); if (width > 0) --width; } while (inchar () != EOF && width != 0); - if (w == work || - (w - work == 1 && (work[0] == '+' || work[0] == '-'))) + if (wpsize == 0 || + (wpsize == 1 && (wp[0] == '+' || wp[0] == '-'))) /* There was no number. */ conv_error (); /* Convert the number. */ - *w = '\0'; + ADDW ('\0'); if (is_longlong) { if (number_signed) - num.q = __strtoq_internal (work, &w, base, group_flag); + num.q = __strtoq_internal (wp, &tw, base, group_flag); else - num.uq = __strtouq_internal (work, &w, base, group_flag); + num.uq = __strtouq_internal (wp, &tw, base, group_flag); } else { if (number_signed) - num.l = __strtol_internal (work, &w, base, group_flag); + num.l = __strtol_internal (wp, &tw, base, group_flag); else - num.ul = __strtoul_internal (work, &w, base, group_flag); + num.ul = __strtoul_internal (wp, &tw, base, group_flag); } - if (w == work) + if (wp == tw) conv_error (); if (do_assign) @@ -599,7 +615,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr) /* Check for a sign. */ if (c == '-' || c == '+') { - *w++ = c; + ADDW (c); if (inchar () == EOF) /* EOF is only an input error before we read any chars. */ conv_error (); @@ -611,17 +627,18 @@ __vfscanf (FILE *s, const char *format, va_list argptr) do { if (isdigit (c)) - *w++ = c; - else if (got_e && w[-1] == 'e' && (c == '-' || c == '+')) - *w++ = c; + ADDW (c); + else if (got_e && wp[wpsize - 1] == 'e' + && (c == '-' || c == '+')) + ADDW (c); else if (!got_e && tolower (c) == 'e') { - *w++ = 'e'; + ADDW ('e'); got_e = got_dot = 1; } else if (c == decimal && !got_dot) { - *w++ = c; + ADDW (c); got_dot = 1; } else @@ -630,33 +647,34 @@ __vfscanf (FILE *s, const char *format, va_list argptr) --width; } while (inchar () != EOF && width != 0); - if (w == work) + if (wpsize == 0) conv_error(); - if (w[-1] == '-' || w[-1] == '+' || w[-1] == 'e') + if (wp[wpsize - 1] == '-' || wp[wpsize - 1] == '+' + || wp[wpsize - 1] == 'e') conv_error (); /* Convert the number. */ - *w = '\0'; + ADDW ('\0'); if (is_long_double) { - long double d = __strtold_internal (work, &w, group_flag); - if (do_assign && w != work) + long double d = __strtold_internal (wp, &tw, group_flag); + if (do_assign && tw != wp) *ARG (long double *) = d; } else if (is_long) { - double d = __strtod_internal (work, &w, group_flag); - if (do_assign && w != work) + double d = __strtod_internal (wp, &tw, group_flag); + if (do_assign && tw != wp) *ARG (double *) = d; } else { - float d = __strtof_internal (work, &w, group_flag); - if (do_assign && w != work) + float d = __strtof_internal (wp, &tw, group_flag); + if (do_assign && tw != wp) *ARG (float *) = d; } - if (w == work) + if (tw == wp) conv_error (); if (do_assign) @@ -680,23 +698,23 @@ __vfscanf (FILE *s, const char *format, va_list argptr) while ((fc = *f++) != '\0' && fc != ']') { if (fc == '-' && *f != '\0' && *f != ']' && - w > work && w[-1] <= *f) + wpsize > 0 && wp[wpsize - 1] <= *f) /* Add all characters from the one before the '-' up to (but not including) the next format char. */ - for (fc = w[-1] + 1; fc < *f; ++fc) - *w++ = fc; + for (fc = wp[wpsize - 1] + 1; fc < *f; ++fc) + ADDW (fc); else /* Add the character to the list. */ - *w++ = fc; + ADDW (fc); } if (fc == '\0') conv_error(); - *w = '\0'; + ADDW ('\0'); num.ul = read_in; do { - if ((strchr (work, c) == NULL) != not_in) + if ((strchr (wp, c) == NULL) != not_in) break; STRING_ADD_CHAR (c); if (width > 0) |