summary refs log tree commit diff
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)
downloadglibc-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')
-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)