summaryrefslogtreecommitdiff
path: root/stdio-common
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1995-12-05 03:35:55 +0000
committerRoland McGrath <roland@gnu.org>1995-12-05 03:35:55 +0000
commit77a58cad3fa0a286bd2581187a2463a762d711ba (patch)
tree50756d67e82e3edbe49f722662b0bed8c0cd19cc /stdio-common
parentb5a08c5aca57835de5f69b8b017f09cd75f5cf7d (diff)
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')
-rw-r--r--stdio-common/Makefile3
-rw-r--r--stdio-common/errnobug.c4
-rw-r--r--stdio-common/printf-parse.h8
-rw-r--r--stdio-common/printf_fp.c2
-rw-r--r--stdio-common/tstgetln.c6
-rw-r--r--stdio-common/vfprintf.c51
-rw-r--r--stdio-common/vfscanf.c94
7 files changed, 106 insertions, 62 deletions
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
index 3afb555458..8ae8b48e1d 100644
--- a/stdio-common/Makefile
+++ b/stdio-common/Makefile
@@ -39,7 +39,8 @@ distribute := _itoa.h printf-parse.h
tests := tst-printf tstscanf test_rdwr test-popen tstgetln test-fseek \
temptest tst-fileno test-fwrite \
xbug errnobug \
- bug1 bug2 bug3 bug4 bug5 bug6 bug7
+ bug1 bug2 bug3 bug4 bug5 bug6 bug7 \
+ tfformat tiformat tstdiomisc
include ../Rules
diff --git a/stdio-common/errnobug.c b/stdio-common/errnobug.c
index cf17be30a2..d1122e4e9b 100644
--- a/stdio-common/errnobug.c
+++ b/stdio-common/errnobug.c
@@ -1,5 +1,5 @@
/* Regression test for reported old bug that errno is clobbered
- by the first successful output to a stream on an unseekable object.
+ by the first successful output to a stream on an unseekable object.
Copyright (C) 1995 Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -43,7 +43,7 @@ main (void)
}
errno = 0;
- if (fputs ("fnord", f))
+ if (fputs ("fnord", f) == EOF)
{
perror ("fputs");
return 1;
diff --git a/stdio-common/printf-parse.h b/stdio-common/printf-parse.h
index 0f6e9e287b..9abbdba187 100644
--- a/stdio-common/printf-parse.h
+++ b/stdio-common/printf-parse.h
@@ -32,7 +32,7 @@ Cambridge, MA 02139, USA. */
struct printf_spec
{
- /* Information parsed from the format spec. */
+ /* Information parsed from the format spec. */
struct printf_info info;
/* Pointers into the format string for the end of this format
@@ -260,10 +260,6 @@ parse_one_spec (const char *format, size_t posn, struct printf_spec *spec,
else
/* "%.?" is treated like "%.0?". */
spec->info.prec = 0;
-
- /* If there was a precision specified, ignore the 0 flag and always
- pad with spaces. */
- spec->info.pad = ' ';
}
/* Check for type modifiers. */
@@ -364,7 +360,7 @@ parse_one_spec (const char *format, size_t posn, struct printf_spec *spec,
break;
}
- if (spec->data_arg == -1 && spec->ndata_args > 0)
+ if (spec->data_arg == -1 && spec->ndata_args > 0)
{
/* There are args consumed, but no positional spec.
Use the next sequential arg position. */
diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c
index 31c009e891..44f501f206 100644
--- a/stdio-common/printf_fp.c
+++ b/stdio-common/printf_fp.c
@@ -345,7 +345,7 @@ __printf_fp (fp, info, args)
scalesize = 0;
if (exponent > 2)
{
- /* |FP| >= 1.0. */
+ /* |FP| >= 8.0. */
int scaleexpo = 0;
int explog = LDBL_MAX_10_EXP_LOG;
int exp10 = 0;
diff --git a/stdio-common/tstgetln.c b/stdio-common/tstgetln.c
index ea8ea817da..a35be272e9 100644
--- a/stdio-common/tstgetln.c
+++ b/stdio-common/tstgetln.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1992, 1995 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -19,6 +19,10 @@ Cambridge, MA 02139, USA. */
#include <ansidecl.h>
#include <stdio.h>
+#ifdef USE_IN_LIBIO
+# define ssize_t _IO_ssize_t
+#endif
+
int
DEFUN_VOID(main)
{
diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c
index c73661973a..08a488ce81 100644
--- a/stdio-common/vfprintf.c
+++ b/stdio-common/vfprintf.c
@@ -96,7 +96,7 @@ ssize_t __printf_pad __P ((FILE *, char pad, size_t n));
do \
{ \
register const int outc = (x); \
- if (putc (outc, s) == EOF) \
+ if (PUTC (outc, s) == EOF) \
return -1; \
else \
++done; \
@@ -230,11 +230,12 @@ vfprintf (s, format, ap)
/* Allocate memory for the argument descriptions. */
args_type = alloca (nargs * sizeof (int));
+ memset (args_type, 0, nargs * sizeof (int));
args_value = alloca (nargs * sizeof (union printf_arg));
- /* XXX Could do sanity check here:
- Initialize args_type elts to zero.
- If any is still zero after this loop, format is invalid. */
+ /* XXX Could do sanity check here: If any element in ARGS_TYPE is
+ still zero after this loop, format is invalid. For now we simply
+ use 0 as the value. */
/* Fill in the types of all the arguments. */
for (cnt = 0; cnt < nspecs; ++cnt)
@@ -287,6 +288,8 @@ vfprintf (s, format, ap)
default:
if ((args_type[cnt] & PA_FLAG_PTR) != 0)
args_value[cnt].pa_pointer = va_arg (ap, void *);
+ else
+ args_value[cnt].pa_long_double = 0.0;
break;
}
@@ -420,15 +423,27 @@ vfprintf (s, format, ap)
char *const workend = &work[sizeof(work) - 1];
register char *w;
- /* Supply a default precision if none was given. */
if (specs[cnt].info.prec == -1)
- specs[cnt].info.prec = 1;
-
- /* Put the number in WORK. */
- w = _itoa (num, workend + 1, base, specs[cnt].info.spec == 'X');
- w -= 1;
- if (specs[cnt].info.group && grouping)
- w = group_number (w, workend, grouping, thousands_sep);
+ /* Supply a default precision if none was given. */
+ specs[cnt].info.prec = 1;
+ else
+ /* We have to take care for the '0' flag. If a
+ precision is given it must be ignored. */
+ specs[cnt].info.pad = ' ';
+
+ /* If the precision is 0 and the number is 0 nothing has
+ to be written for the number. */
+ if (specs[cnt].info.prec == 0 && num == 0)
+ w = workend;
+ else
+ {
+ /* Put the number in WORK. */
+ w = _itoa (num, workend + 1, base,
+ specs[cnt].info.spec == 'X');
+ w -= 1;
+ if (specs[cnt].info.group && grouping)
+ w = group_number (w, workend, grouping, thousands_sep);
+ }
specs[cnt].info.width -= workend - w;
specs[cnt].info.prec -= workend - w;
@@ -618,8 +633,18 @@ vfprintf (s, format, ap)
}
#ifdef USE_IN_LIBIO
-#undef vfprintf
+# undef vfprintf
+# ifdef strong_alias
+/* This is for glibc. */
strong_alias (_IO_vfprintf, vfprintf)
+# else
+# if defined __ELF__ || defined __GNU_LIBRARY__
+# include <gnu-stabs.h>
+# ifdef weak_alias
+weak_alias (_IO_vfprintf, vfprintf);
+# endif
+# endif
+# endif
#endif
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)