about summary refs log tree commit diff
path: root/stdio
diff options
context:
space:
mode:
Diffstat (limited to 'stdio')
-rw-r--r--stdio/.cvsignore4
-rw-r--r--stdio/Makefile114
-rw-r--r--stdio/_itoa.c45
-rw-r--r--stdio/_itoa.h54
-rw-r--r--stdio/asprintf.c39
-rw-r--r--stdio/bug1.c28
-rw-r--r--stdio/bug1.input1
-rw-r--r--stdio/bug2.c12
-rw-r--r--stdio/bug3.c52
-rw-r--r--stdio/bug4.c50
-rw-r--r--stdio/bug5.c60
-rw-r--r--stdio/bug6.c27
-rw-r--r--stdio/bug6.input1
-rw-r--r--stdio/bug7.c53
-rw-r--r--stdio/clearerr.c31
-rw-r--r--stdio/dprintf.c37
-rw-r--r--stdio/errnobug.c60
-rw-r--r--stdio/fclose.c69
-rw-r--r--stdio/feof.c37
-rw-r--r--stdio/ferror.c37
-rw-r--r--stdio/fflush.c45
-rw-r--r--stdio/fgetc.c35
-rw-r--r--stdio/fgetpos.c40
-rw-r--r--stdio/fgets.c121
-rw-r--r--stdio/fileno.c48
-rw-r--r--stdio/fmemopen.c108
-rw-r--r--stdio/fopen.c110
-rw-r--r--stdio/fopncook.c48
-rw-r--r--stdio/fpioconst.c401
-rw-r--r--stdio/fpioconst.h52
-rw-r--r--stdio/fprintf.c38
-rw-r--r--stdio/fputc.c35
-rw-r--r--stdio/fputs.c35
-rw-r--r--stdio/fread.c128
-rw-r--r--stdio/freopen.c74
-rw-r--r--stdio/fscanf.c38
-rw-r--r--stdio/fseek.c177
-rw-r--r--stdio/fsetpos.c37
-rw-r--r--stdio/ftell.c54
-rw-r--r--stdio/fwrite.c208
-rw-r--r--stdio/gen-mpn-copy31
-rw-r--r--stdio/getc.c5
-rw-r--r--stdio/getchar.c30
-rw-r--r--stdio/getdelim.c173
-rw-r--r--stdio/getline.c33
-rw-r--r--stdio/gets.c59
-rw-r--r--stdio/getw.c33
-rw-r--r--stdio/glue.c114
-rw-r--r--stdio/gmp-impl.h283
-rw-r--r--stdio/gmp.h525
-rw-r--r--stdio/internals.c667
-rw-r--r--stdio/longlong.h1295
-rw-r--r--stdio/memstream.c177
-rw-r--r--stdio/mp_clz_tab.c39
-rw-r--r--stdio/newstream.c54
-rw-r--r--stdio/obstream.c187
-rw-r--r--stdio/perror.c42
-rw-r--r--stdio/printf-prs.c211
-rw-r--r--stdio/printf.c37
-rw-r--r--stdio/printf.h114
-rw-r--r--stdio/printf_fp.c991
-rw-r--r--stdio/psignal.c49
-rw-r--r--stdio/putc.c5
-rw-r--r--stdio/putchar.c30
-rw-r--r--stdio/puts.c32
-rw-r--r--stdio/putw.c31
-rw-r--r--stdio/reg-printf.c47
-rw-r--r--stdio/rewind.c33
-rw-r--r--stdio/scanf.c37
-rw-r--r--stdio/setbuf.c30
-rw-r--r--stdio/setbuffer.c30
-rw-r--r--stdio/setlinebuf.c29
-rw-r--r--stdio/setvbuf.c85
-rw-r--r--stdio/snprintf.c39
-rw-r--r--stdio/sprintf.c37
-rw-r--r--stdio/sscanf.c37
-rw-r--r--stdio/stdio.h681
-rw-r--r--stdio/tempnam.c50
-rw-r--r--stdio/temptest.c31
-rw-r--r--stdio/test-fseek.c67
-rw-r--r--stdio/test-fwrite.c68
-rw-r--r--stdio/test-popen.c67
-rw-r--r--stdio/test_rdwr.c129
-rw-r--r--stdio/tmpfile.c43
-rw-r--r--stdio/tmpnam.c42
-rw-r--r--stdio/tst-fileno.c37
-rw-r--r--stdio/tst-printf.c298
-rw-r--r--stdio/tstgetln.c46
-rw-r--r--stdio/tstgetln.input3
-rw-r--r--stdio/tstscanf.c100
-rw-r--r--stdio/tstscanf.input7
-rw-r--r--stdio/ungetc.c58
-rw-r--r--stdio/vasprintf.c86
-rw-r--r--stdio/vdprintf.c51
-rw-r--r--stdio/vfprintf.c907
-rw-r--r--stdio/vfscanf.c570
-rw-r--r--stdio/vprintf.c33
-rw-r--r--stdio/vscanf.c32
-rw-r--r--stdio/vsnprintf.c56
-rw-r--r--stdio/vsprintf.c50
-rw-r--r--stdio/vsscanf.c58
-rw-r--r--stdio/xbug.c63
102 files changed, 11927 insertions, 0 deletions
diff --git a/stdio/.cvsignore b/stdio/.cvsignore
new file mode 100644
index 0000000000..1f69fd919a
--- /dev/null
+++ b/stdio/.cvsignore
@@ -0,0 +1,4 @@
+*.gz *.Z *.tar *.tgz
+=*
+TODO COPYING* AUTHORS copyr-* copying.*
+glibc-*
diff --git a/stdio/Makefile b/stdio/Makefile
new file mode 100644
index 0000000000..579426186f
--- /dev/null
+++ b/stdio/Makefile
@@ -0,0 +1,114 @@
+# Copyright (C) 1991, 1992, 1993, 1994, 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
+# modify it under the terms of the GNU Library General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Library General Public License for more details.
+
+# You should have received a copy of the GNU Library General Public
+# License along with the GNU C Library; see the file COPYING.LIB.  If
+# not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+# Cambridge, MA 02139, USA.
+
+#
+#	Specific makefile for stdio.
+#
+subdir	:= stdio
+
+headers	:= stdio.h stdio_lim.h printf.h
+
+routines	:=							      \
+	ctermid cuserid							      \
+	feof ferror clearerr fileno					      \
+	newstream fopen freopen fdopen fopncook fmemopen		      \
+	setbuf setvbuf setbuffer setlinebuf				      \
+	fseek ftell rewind fgetpos fsetpos				      \
+	vfprintf vprintf printf_fp reg-printf printf-prs _itoa		      \
+	vsnprintf vsprintf vasprintf	      				      \
+	fprintf printf snprintf sprintf asprintf			      \
+	dprintf vdprintf						      \
+	vfscanf vscanf vsscanf						      \
+	fscanf scanf sscanf						      \
+	fread fwrite							      \
+	ungetc								      \
+	fgetc getc getchar getw						      \
+	fputc putc putchar putw						      \
+	fgets gets fputs puts						      \
+	getdelim getline						      \
+	perror psignal							      \
+	tmpfile tmpnam tempnam tempname					      \
+	fclose fflush							      \
+	remove rename							      \
+	memstream obstream						      \
+	internals sysd-stdio pipestream stdio_init libc_fatal
+
+# Several mpn functions from GNU MP are used by the printf_fp function.
+mpn-routines := add_1 add_n addmul_1 cmp divmod divmod_1 udiv_qrnnd \
+		lshift rshift mod_1 mul mul_1 mul_n sub_n submul_1 
+mpn-headers = longlong.h gmp.h gmp-impl.h gmp-mparam.h asm-syntax.h
+
+routines := $(strip $(routines) $(mpn-routines))	\
+	    dbl2mpn ldbl2mpn				\
+	    mpn2flt mpn2dbl mpn2ldbl
+aux	:= errlist siglist defs glue mp_clz_tab fpioconst 
+distribute = $(mpn-headers) gen-mpn-copy _itoa.h fpioconst.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
+
+
+include ../Rules
+
+
+ifdef gmp-srcdir
+
+gmp-srcdir := $(firstword $(filter-out ..//%,$(..)$(gmp-srcdir) $(gmp-srcdir)))
+
+# Copy the mpn source files we use from the GNU MP source directory.
+# `gmp-srcdir' is set by doing `configure --with-gmp=DIR'.
+# (Do not try this at home.  You need an as yet unreleased version of GNU MP.)
+
+mpn-sysdep := $(addsuffix .c,$(mpn-routines)) \
+	      $(addsuffix .S,$(mpn-routines)) \
+	      $(addsuffix .s,$(mpn-routines)) gmp-mparam.h asm-syntax.h
+
+mpn-try := $(addprefix $(gmp-srcdir)/mpn/*/,$(mpn-sysdep))
+mpn-found := $(wildcard $(mpn-try))
+mpn-found := $(filter-out $(patsubst %.S,%.s,$(filter %.s,$(mpn-found))),\
+			  $(mpn-found))
+
+include mpn-copy.mk
+%.mk: gen-%; sh $< > $@
+
+mpn-copy-1 := $(patsubst $(gmp-srcdir)/mpn/%,$(sysdep_dir)/%,$(mpn-found))
+mpn-copy-sysdep := $(mpn-copy-sysdep) $(mpn-copy-1)
+$(mpn-copy-1): $(sysdep_dir)/%: $(ignore gmp2glibc.sed) $(gmp-srcdir)/mpn/%
+	$(gmp2glibc)
+
+mpn-stuff = $(mpn-copy-sysdep) $(mpn-copy)
+
+# chmod so I don't edit them by mistake.
+define gmp2glibc
+$(ignore sed -f $^ > $@-tmp)
+cp $< $@-tmp
+chmod a-w $@-tmp
+mv -f $@-tmp $@
+endef
+
+mpn-copy = $(filter-out $(mpn-sysdep),$(mpn-headers) mp_clz_tab.c)
+$(mpn-copy): %: $(ignore gmp2glibc.sed) $(gmp-srcdir)/%; $(gmp2glibc)
+
+.PHONY: copy-mpn clean-mpn
+copy-mpn: $(mpn-stuff)
+clean-mpn:
+	rm -f $(mpn-stuff)
+
+endif
diff --git a/stdio/_itoa.c b/stdio/_itoa.c
new file mode 100644
index 0000000000..b781b1ea88
--- /dev/null
+++ b/stdio/_itoa.c
@@ -0,0 +1,45 @@
+/* Internal function for converting integers to ASCII.
+Copyright (C) 1994 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include "_itoa.h"
+
+/* Lower-case digits.  */
+CONST char _itoa_lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+/* Upper-case digits.  */
+CONST char _itoa_upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+char *
+DEFUN(_itoa, (value, buflim, base, upper_case),
+      unsigned long long int value AND char *buflim AND
+      unsigned int base AND int upper_case)
+{
+  /* Base-36 digits for numbers.  */
+  CONST char *digits = upper_case ? _itoa_upper_digits : _itoa_lower_digits;
+
+  register char *bp = buflim;
+
+  while (value > 0)
+    {
+      *--bp = digits[value % base];
+      value /= base;
+    }
+
+  return bp;
+}
diff --git a/stdio/_itoa.h b/stdio/_itoa.h
new file mode 100644
index 0000000000..791ce6c87f
--- /dev/null
+++ b/stdio/_itoa.h
@@ -0,0 +1,54 @@
+/* Internal function for converting integers to ASCII.
+Copyright (C) 1994 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#ifndef _ITOA_H
+#define _ITOA_H
+#include <sys/cdefs.h>
+
+extern const char _itoa_lower_digits[], _itoa_upper_digits[];
+
+/* Convert VALUE into ASCII in base BASE (2..36).
+   Write backwards starting the character just before BUFLIM.
+   Return the address of the first (left-to-right) character in the number.
+   Use upper case letters iff UPPER_CASE is nonzero.  */
+
+extern char *_itoa __P ((unsigned long long int value, char *buflim,
+			 unsigned int base, int upper_case));
+
+#if defined (__GNUC__) && defined (__OPTIMIZE__)
+extern __inline char *
+_itoa (unsigned long long int value, char *buflim,
+       unsigned int base, int upper_case)
+{
+  /* Base-36 digits for numbers.  */
+  const char *digits = upper_case ? _itoa_upper_digits : _itoa_lower_digits;
+
+  register char *bp = buflim;
+
+  while (value > 0)
+    {
+      *--bp = digits[value % base];
+      value /= base;
+    }
+
+  return bp;
+}
+#endif
+
+#endif	/* itoa.h */
diff --git a/stdio/asprintf.c b/stdio/asprintf.c
new file mode 100644
index 0000000000..9b69800f73
--- /dev/null
+++ b/stdio/asprintf.c
@@ -0,0 +1,39 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+
+/* Write formatted output from FORMAT to a string which is
+   allocated with malloc and stored in *STRING_PTR.  */
+/* VARARGS2 */
+int
+DEFUN(asprintf, (string_ptr, format),
+      char **string_ptr AND CONST char *format DOTS)
+{
+  va_list arg;
+  int done;
+
+  va_start(arg, format);
+  done = vasprintf(string_ptr, format, arg);
+  va_end(arg);
+
+  return done;
+}
diff --git a/stdio/bug1.c b/stdio/bug1.c
new file mode 100644
index 0000000000..755bc4231b
--- /dev/null
+++ b/stdio/bug1.c
@@ -0,0 +1,28 @@
+#include <ansidecl.h>
+#include <stdio.h>
+#include <string.h>
+
+int
+DEFUN_VOID(main)
+{
+  char *bp;
+  size_t size;
+  FILE *stream;
+  int lose = 0;
+
+  stream = open_memstream (&bp, &size);
+  fprintf (stream, "hello");
+  fflush (stream);
+  printf ("buf = %s, size = %d\n", bp, size);
+  lose |= size != 5;
+  lose |= strncmp (bp, "hello", size);
+  fprintf (stream, ", world");
+  fclose (stream);
+  printf ("buf = %s, size = %d\n", bp, size);
+  lose |= size != 12;
+  lose |= strncmp (bp, "hello, world", 12);
+
+  puts (lose ? "Test FAILED!" : "Test succeeded.");
+
+  return lose;
+}
diff --git a/stdio/bug1.input b/stdio/bug1.input
new file mode 100644
index 0000000000..5595fa46c0
--- /dev/null
+++ b/stdio/bug1.input
@@ -0,0 +1 @@
+95
diff --git a/stdio/bug2.c b/stdio/bug2.c
new file mode 100644
index 0000000000..2b34c890bf
--- /dev/null
+++ b/stdio/bug2.c
@@ -0,0 +1,12 @@
+#include <ansidecl.h>
+#include <stdio.h>
+
+int
+DEFUN_VOID(main)
+{
+  int i;
+  puts ("This should print \"wow = I\" for I from 0 to 39 inclusive.");
+  for (i = 0; i < 40; i++)
+    printf ("%s = %d\n", "wow", i);
+  return 0;
+}
diff --git a/stdio/bug3.c b/stdio/bug3.c
new file mode 100644
index 0000000000..0f3c7f1087
--- /dev/null
+++ b/stdio/bug3.c
@@ -0,0 +1,52 @@
+#include <ansidecl.h>
+#include <stdio.h>
+#include <string.h>
+
+int
+DEFUN_VOID(main)
+{
+  FILE *f;
+  int i;
+
+  f = fopen("bugtest", "w+");
+  for (i=0; i<9000; i++)
+    putc ('x', f);
+  fseek (f, 8180L, 0);
+  fwrite ("Where does this text go?", 1, 24, f);
+  fflush (f);
+
+  rewind (f);
+  for (i=0; i<9000; i++)
+    {
+      int j;
+
+      if ((j = getc(f)) != 'x')
+	{
+	  if (i != 8180)
+	    {
+	      printf ("Test FAILED!");
+	      return 1;
+	    }
+	  else
+	    {
+	      char buf[25];
+
+	      buf[0] = j;
+	      fread (buf + 1, 1, 23, f);
+	      buf[24] = '\0';
+	      if (strcmp (buf, "Where does this text go?") != 0)
+		{
+		  printf ("%s\nTest FAILED!\n", buf);
+		  return 1;
+		}
+	      i += 23;
+	    }
+	}
+    }
+
+  fclose(f);
+
+  puts ("Test succeeded.");
+
+  return 0;
+}
diff --git a/stdio/bug4.c b/stdio/bug4.c
new file mode 100644
index 0000000000..8e67f1d7b9
--- /dev/null
+++ b/stdio/bug4.c
@@ -0,0 +1,50 @@
+#ifdef _LIBC
+#include <ansidecl.h>
+#endif
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+int stdio_block_read = 1, stdio_block_write = 1;
+
+int
+DEFUN(main, (argc, argv),
+      int argc AND char **argv)
+{
+  FILE *f;
+  int i;
+  char buffer[31];
+
+  while ((i = getopt (argc, argv, "rw")) != EOF)
+    switch (i)
+      {
+      case 'r':
+	stdio_block_read = 0;
+	break;
+      case 'w':
+	stdio_block_write = 0;
+	break;
+      }
+
+  f = fopen("bugtest", "w+");
+  for (i=0; i<9000; i++) {
+    putc('x', f);
+  }
+  fseek(f, 8180L, 0);
+  fwrite("Where does this text come from?", 1, 31, f);
+  fseek(f, 8180L, 0);
+  fread(buffer, 1, 31, f);
+  fwrite(buffer, 1, 31, stdout);
+  fclose(f);
+
+  if (!memcmp (buffer, "Where does this text come from?", 31))
+    {
+      puts ("\nTest succeeded.");
+      return 0;
+    }
+  else
+    {
+      puts ("\nTest FAILED!");
+      return 1;
+    }
+}
diff --git a/stdio/bug5.c b/stdio/bug5.c
new file mode 100644
index 0000000000..218af31352
--- /dev/null
+++ b/stdio/bug5.c
@@ -0,0 +1,60 @@
+/* If stdio is working correctly, after this is run infile and outfile
+   will have the same contents.  If the bug (found in GNU C library 0.3)
+   exhibits itself, outfile will be missing the 2nd through 1023rd
+   characters.  */
+
+#include <ansidecl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static char buf[8192];
+
+int
+DEFUN_VOID(main)
+{
+  FILE *in;
+  FILE *out;
+  static char inname[] = "infile";
+  static char outname[] = "outfile";
+  int i;
+
+  /* Create a test file.  */
+  in = fopen (inname, "w+");
+  if (in == NULL)
+    {
+      perror (inname);
+      return 1;
+    }
+  for (i = 0; i < 1000; ++i)
+    fprintf (in, "%d\n", i);
+
+  out = fopen (outname, "w");
+  if (out == NULL)
+    {
+      perror (outname);
+      return 1;
+    }
+  if (fseek (in, 0L, SEEK_SET) != 0)
+    abort ();
+  putc (getc (in), out);
+  i = fread (buf, 1, sizeof (buf), in);
+  if (i == 0)
+    {
+      perror ("fread");
+      return 1;
+    }
+  if (fwrite (buf, 1, i, out) != i)
+    {
+      perror ("fwrite");
+      return 1;
+    }
+  fclose (in);
+  fclose (out);
+
+  puts ("There should be no further output from this test.");
+  fflush (stdout);
+  execlp ("cmp", "cmp", inname, outname, (char *) NULL);
+  perror ("execlp: cmp");
+  exit (1);
+}
diff --git a/stdio/bug6.c b/stdio/bug6.c
new file mode 100644
index 0000000000..4a37ab2584
--- /dev/null
+++ b/stdio/bug6.c
@@ -0,0 +1,27 @@
+#include <ansidecl.h>
+#include <stdio.h>
+
+int
+DEFUN_VOID(main)
+{
+  char buf[80];
+  int i;
+  int lost = 0;
+
+  scanf ("%2s", buf);
+  lost |= (buf[0] != 'X' || buf[1] != 'Y' || buf[2] != '\0');
+  if (lost)
+    puts ("test of %2s failed.");
+  scanf (" ");
+  scanf ("%d", &i);
+  lost |= (i != 1234);
+  if (lost)
+    puts ("test of %d failed.");
+  scanf ("%c", buf);
+  lost |= (buf[0] != 'L');
+  if (lost)
+    puts ("test of %c failed.\n");
+
+  puts (lost ? "Test FAILED!" : "Test succeeded.");
+  return lost;
+}
diff --git a/stdio/bug6.input b/stdio/bug6.input
new file mode 100644
index 0000000000..d996e399c3
--- /dev/null
+++ b/stdio/bug6.input
@@ -0,0 +1 @@
+XY 1234L
diff --git a/stdio/bug7.c b/stdio/bug7.c
new file mode 100644
index 0000000000..af06f8d6a5
--- /dev/null
+++ b/stdio/bug7.c
@@ -0,0 +1,53 @@
+/* Regression test for fseek and freopen bugs.  */
+
+#include <stdio.h>
+
+int
+main ()
+{
+  int lose = 0;
+  char filename[] = "/tmp/foo";
+  FILE *fp;
+ 
+  fp = fopen (filename, "w+");
+  fprintf (fp, "Hello world!\n");
+  fflush (fp);
+  fseek (fp, 5L, SEEK_SET);
+  if (fseek (fp, -1L, SEEK_CUR) < 0)
+    {
+      printf ("seek failed\n");
+      lose = 1;
+    }
+  fclose (fp);
+  remove (filename);
+
+  {
+    FILE *file1;
+    FILE *file2;
+    char filename1[] = "/tmp/foo";
+    char filename2[] = "/tmp/bar";
+    int ch;
+
+    file1 = fopen (filename1, "w");
+    fclose (file1);
+
+    file2 = fopen (filename2, "w");
+    fputc ('x', file2);
+    fclose (file2);
+
+    file1 = fopen (filename1, "r");
+    file2 = freopen (filename2, "r", file1);
+    if ((ch = fgetc (file2)) != 'x')
+      {
+	printf ("wrong character in reopened file, value = %d\n", ch);
+	lose = 1;
+      }
+    fclose (file1);
+    fclose (file2);
+    remove (filename1);
+    remove (filename2);
+  }
+
+  puts (lose ? "Test FAILED!" : "Test succeeded.");
+  return lose;
+}
diff --git a/stdio/clearerr.c b/stdio/clearerr.c
new file mode 100644
index 0000000000..1a9feaa413
--- /dev/null
+++ b/stdio/clearerr.c
@@ -0,0 +1,31 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stdio.h>
+
+#undef	clearerr
+
+
+/* Clear the EOF and error indicators for STREAM.  */
+void
+DEFUN(clearerr, (stream), FILE *stream)
+{
+  __clearerr(stream);
+}
diff --git a/stdio/dprintf.c b/stdio/dprintf.c
new file mode 100644
index 0000000000..fc9faa4ca2
--- /dev/null
+++ b/stdio/dprintf.c
@@ -0,0 +1,37 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+
+/* Write formatted output to D, according to the format string FORMAT.  */
+/* VARARGS2 */
+int
+DEFUN(dprintf, (d, format), int d AND CONST char *format DOTS)
+{
+  va_list arg;
+  int done;
+
+  va_start(arg, format);
+  done = vdprintf(d, format, arg);
+  va_end(arg);
+
+  return done;
+}
diff --git a/stdio/errnobug.c b/stdio/errnobug.c
new file mode 100644
index 0000000000..cf17be30a2
--- /dev/null
+++ b/stdio/errnobug.c
@@ -0,0 +1,60 @@
+/* Regression test for reported old bug that errno is clobbered
+   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.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int
+main (void)
+{
+  int fd[2];
+  FILE *f;
+
+  /* Get a stream that cannot seek.  */
+
+  if (pipe (fd))
+    {
+      perror ("pipe");
+      return 1;
+    }
+  f = fdopen (fd[1], "w");
+  if (f == NULL)
+    {
+      perror ("fdopen");
+      return 1;
+    }
+
+  errno = 0;
+  if (fputs ("fnord", f))
+    {
+      perror ("fputs");
+      return 1;
+    }
+
+  if (errno)
+    {
+      perror ("errno gratuitously set -- TEST FAILED");
+      return 1;
+    }
+
+  puts ("Test succeeded.");
+  return 0;
+}
diff --git a/stdio/fclose.c b/stdio/fclose.c
new file mode 100644
index 0000000000..becb85802f
--- /dev/null
+++ b/stdio/fclose.c
@@ -0,0 +1,69 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* Close a stream.  */
+int
+DEFUN(fclose, (stream), register FILE *stream)
+{
+  int status;
+
+  if (stream == NULL)
+    {
+      /* Close all streams.  */
+      register FILE *f;
+      for (f = __stdio_head; f != NULL; f = f->__next)
+	if (__validfp(f))
+	  (void) fclose(f);
+      return 0;
+    }
+
+  if (!__validfp(stream))
+    {
+      errno = EINVAL;
+      return EOF;
+    }
+	
+  if (stream->__mode.__write &&
+      /* Flush the buffer.  */
+      __flshfp (stream, EOF) == EOF)
+    return EOF;
+
+  /* Free the buffer's storage.  */
+  if (stream->__buffer != NULL && !stream->__userbuf)
+    free(stream->__buffer);
+
+  /* Close the system file descriptor.  */
+  if (stream->__io_funcs.__close != NULL)
+    status = (*stream->__io_funcs.__close)(stream->__cookie);
+  else if (!stream->__seen && stream->__cookie != NULL)
+    status = __stdio_close(stream->__cookie);
+  else
+    status = 0;
+
+  /* Nuke the stream, making it available for re-use.  */
+  __invalidate(stream);
+
+  return status < 0 ? EOF : 0;
+}
diff --git a/stdio/feof.c b/stdio/feof.c
new file mode 100644
index 0000000000..c18300f6b5
--- /dev/null
+++ b/stdio/feof.c
@@ -0,0 +1,37 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stdio.h>
+
+#undef	feof
+
+
+/* Return non-zero if STREAM has its EOF indicator set.  */
+int
+DEFUN(feof, (stream), FILE *stream)
+{
+  if (!__validfp(stream))
+    {
+      errno = EINVAL;
+      return(-1);
+    }
+
+  return(stream->__eof);
+}
diff --git a/stdio/ferror.c b/stdio/ferror.c
new file mode 100644
index 0000000000..ed8f74401a
--- /dev/null
+++ b/stdio/ferror.c
@@ -0,0 +1,37 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stdio.h>
+
+#undef	ferror
+
+
+/* Return non-zero if STREAM has its error indicator set.  */
+int
+DEFUN(ferror, (stream), FILE *stream)
+{
+  if (!__validfp(stream))
+    {
+      errno = EINVAL;
+      return(-1);
+    }
+
+  return(stream->__error);
+}
diff --git a/stdio/fflush.c b/stdio/fflush.c
new file mode 100644
index 0000000000..a6d52ba3e7
--- /dev/null
+++ b/stdio/fflush.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Flush STREAM's buffer.
+   If STREAM is NULL, flush the buffers of all streams that are writing.  */
+int
+DEFUN(fflush, (stream), register FILE *stream)
+{
+  if (stream == NULL)
+    {
+      int lossage = 0;
+      for (stream = __stdio_head; stream != NULL; stream = stream->__next)
+	if (__validfp(stream) && stream->__mode.__write)
+	  lossage |= fflush(stream) == EOF;
+      return lossage ? EOF : 0;
+    }
+
+  if (!__validfp(stream) || !stream->__mode.__write)
+    {
+      errno = EINVAL;
+      return EOF;
+    }
+
+  return __flshfp(stream, EOF);
+}
diff --git a/stdio/fgetc.c b/stdio/fgetc.c
new file mode 100644
index 0000000000..7f01090294
--- /dev/null
+++ b/stdio/fgetc.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stdio.h>
+
+
+/* Read a character from STREAM.  */
+int
+DEFUN(fgetc, (stream), FILE *stream)
+{
+  if (!__validfp(stream) || !stream->__mode.__read)
+    {
+      errno = EINVAL;
+      return EOF;
+    }
+
+  return __getc(stream);
+}
diff --git a/stdio/fgetpos.c b/stdio/fgetpos.c
new file mode 100644
index 0000000000..cb6a1588ba
--- /dev/null
+++ b/stdio/fgetpos.c
@@ -0,0 +1,40 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stdio.h>
+
+#undef	fgetpos
+
+
+/* Put the current position of STREAM in *POS.  */
+int
+DEFUN(fgetpos, (stream, pos), FILE *stream AND fpos_t *pos)
+{
+  if (!__validfp(stream) || pos == NULL)
+    {
+      errno = EINVAL;
+      return(-1);
+    }
+
+  *pos = ftell(stream);
+  if (*pos < 0L)
+    return(-1);
+  return(0);
+}
diff --git a/stdio/fgets.c b/stdio/fgets.c
new file mode 100644
index 0000000000..e9e53c88dd
--- /dev/null
+++ b/stdio/fgets.c
@@ -0,0 +1,121 @@
+/* Copyright (C) 1991, 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+/* Reads characters from STREAM into S, until either a newline character
+   is read, N - 1 characters have been read, or EOF is seen.  Returns
+   the newline, unlike gets.  Finishes by appending a null character and
+   returning S.  If EOF is seen before any characters have been written
+   to S, the function returns NULL without appending the null character.
+   If there is a file error, always return NULL.  */
+char *
+DEFUN(fgets, (s, n, stream), char *s AND int n AND register FILE *stream)
+{
+  register char *p = s;
+
+  if (!__validfp(stream) || s == NULL || n <= 0)
+    {
+      errno = EINVAL;
+      return NULL;
+    }
+
+  if (ferror (stream))
+    return NULL;
+
+  if (stream->__buffer == NULL && stream->__userbuf)
+    {
+      /* Unbuffered stream.  Not much optimization to do.  */
+      register int c = 0;
+      while (--n > 0 && (c = getc (stream)) != EOF) 
+	if ((*p++ = c) == '\n')
+	  break;
+      if (c == EOF && (p == s || ferror (stream)))
+	return NULL;
+      *p = '\0';
+      return s;
+    }
+
+  /* Leave space for the null.  */
+  --n;
+
+  if (n > 0 &&
+      (!stream->__seen || stream->__buffer == NULL || stream->__pushed_back))
+    {
+      /* Do one with getc to allocate a buffer.  */
+      int c = getc (stream);
+      if (c == EOF)
+	return NULL;
+      *p++ = c;
+      if (c == '\n')
+	{
+	  *p = '\0';
+	  return s;
+	}
+      else
+	--n;
+    }
+
+  while (n > 0)
+    {
+      size_t i;
+      char *found;
+
+      i = stream->__get_limit - stream->__bufp;	
+      if (i == 0)
+	{
+	  /* Refill the buffer.  */
+	  int c = __fillbf (stream);
+	  if (c == EOF)
+	    break;
+	  *p++ = c;
+	  --n;
+	  if (c == '\n')
+	    {
+	      *p = '\0';
+	      return s;
+	    }
+	  i = stream->__get_limit - stream->__bufp;	
+	}
+
+      if (i > n)
+	i = n;
+
+      found = (char *) __memccpy ((PTR) p, stream->__bufp, '\n', i);
+
+      if (found != NULL)
+	{
+	  stream->__bufp += found - p;
+	  p = found;
+	  break;
+	}
+
+      stream->__bufp += i;
+      n -= i;
+      p += i;
+    }
+
+  if (p == s)
+    return NULL;
+
+  *p = '\0';
+  return ferror (stream) ? NULL : s;
+}
diff --git a/stdio/fileno.c b/stdio/fileno.c
new file mode 100644
index 0000000000..da55300c8b
--- /dev/null
+++ b/stdio/fileno.c
@@ -0,0 +1,48 @@
+/* Copyright (C) 1991, 1993, 1994 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stdio.h>
+
+/* Return the system file descriptor associated with STREAM.  */
+int
+DEFUN(fileno, (stream), FILE *stream)
+{
+  extern void __stdio_check_funcs __P ((FILE *));
+
+  if (! __validfp (stream))
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  __stdio_check_funcs (stream);
+
+  if (stream->__io_funcs.__fileno == NULL)
+    {
+#ifdef EOPNOTSUPP
+      errno = EOPNOTSUPP;
+#else
+      errno = ENOSYS;
+#endif
+      return -1;
+    }
+
+  return (*stream->__io_funcs.__fileno) (stream->__cookie);
+}
diff --git a/stdio/fmemopen.c b/stdio/fmemopen.c
new file mode 100644
index 0000000000..42a137a2c8
--- /dev/null
+++ b/stdio/fmemopen.c
@@ -0,0 +1,108 @@
+/* Copyright (C) 1991, 1992, 1993 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* Defined in fopen.c.  */
+extern int EXFUN(__getmode, (CONST char *mode, __io_mode *mptr));
+
+/* Open a new stream that will read and/or write from the buffer in
+   S, which is of LEN bytes.  If the mode indicates appending, the
+   buffer pointer is set to point to the first '\0' in the buffer.
+   If S is NULL, the buffer is allocated by malloc and will be freed
+   when the stream is closed.  The only purpose of this is to write
+   things and then read what's been written.  If LEN is zero, writes will
+   always return errors and reads will always return end-of-file.
+
+   The stream is set up such that seeks and tells will always fail and
+   once the buffer is full of written characters or empty of characters
+   to read, attempted writes always return an output error and attempted
+   reads always return end-of-file.  */
+FILE *
+DEFUN(fmemopen, (s, len, mode),
+      PTR s AND size_t len AND CONST char *mode)
+{
+  __io_mode m;
+  register FILE *stream;
+
+  if (!__getmode (mode, &m))
+    return NULL;
+
+  stream = __newstream ();
+  if (stream == NULL)
+    return NULL;
+
+  stream->__mode = m;
+
+  /* Input gets EOF.  */
+  stream->__room_funcs.__input = NULL;
+  /* Output gets error.  */
+  stream->__room_funcs.__output = NULL;
+
+  /* Do nothing for close.  */
+  stream->__io_funcs.__close = NULL;
+  /* Can't seek outside the buffer.  */
+  stream->__io_funcs.__seek = NULL;
+  /* There is no associated file descriptor to fetch.  */
+  stream->__io_funcs.__fileno = NULL;
+
+  stream->__seen = 1;
+
+  stream->__userbuf = s != NULL && len > 0;
+  if (s == NULL)
+    {
+      s = malloc (len);
+      if (s == NULL)
+	{
+	  int save = errno;
+	  (void) fclose (stream);
+	  errno = save;
+	  return NULL;
+	}
+    }
+
+  stream->__buffer = (char *) s;
+  stream->__bufsize = len;
+
+  stream->__bufp = stream->__buffer;
+  stream->__get_limit = (stream->__buffer +
+			 (stream->__mode.__read ? stream->__bufsize : 0));
+  stream->__put_limit = (stream->__buffer +
+			 (stream->__mode.__write ? stream->__bufsize : 0));
+  stream->__cookie = NULL;
+
+  if (stream->__mode.__append)
+    {
+      char *p = memchr (stream->__bufp, '\0',
+			stream->__get_limit - stream->__bufp);
+      if (p == NULL)
+	stream->__bufp = stream->__get_limit;
+      else
+	stream->__bufp = p;
+    }
+  else if (stream->__mode.__truncate)
+    memset ((PTR) stream->__buffer, 0, len);
+
+  return stream;
+}
diff --git a/stdio/fopen.c b/stdio/fopen.c
new file mode 100644
index 0000000000..fba6ac436a
--- /dev/null
+++ b/stdio/fopen.c
@@ -0,0 +1,110 @@
+/* Copyright (C) 1991, 1992, 1993 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#define	badmode()	return ((errno = EINVAL), 0)
+
+/* Dissect the given mode string into an __io_mode.  */
+int
+DEFUN(__getmode, (mode, mptr), CONST char *mode AND __io_mode *mptr)
+{
+  register unsigned char i;
+
+  if (mode == NULL)
+    badmode ();
+
+  memset ((PTR) mptr, 0, sizeof (*mptr));
+
+  switch (*mode)
+    {
+    case 'a':
+      mptr->__write = mptr->__create = mptr->__append = 1;
+      break;
+    case 'w':
+      mptr->__write = mptr->__create = mptr->__truncate = 1;
+      break;
+    case 'r':
+      mptr->__read = 1;
+      break;
+    default:
+      badmode ();
+    }
+
+  for (i = 1; i < 3; ++i)
+    {
+      ++mode;
+      if (*mode == '\0')
+	break;
+      switch (*mode)
+	{
+	case '+':
+	  mptr->__read = mptr->__write = 1;
+	  break;
+	case 'b':
+	  mptr->__binary = 1;
+	  break;
+	}
+    }
+
+  if (!mptr->__read && !mptr->__write)
+    badmode ();
+
+  mptr->__exclusive = *mode == 'x';
+
+  return 1;
+}
+
+/* Open a new stream on the given file.  */
+FILE *
+DEFUN(fopen, (filename, mode), CONST char *filename AND CONST char *mode)
+{
+  FILE *stream;
+  __io_mode m;
+
+  if (filename == NULL)
+    {
+      errno = EINVAL;
+      return NULL;
+    }
+
+  if (!__getmode (mode, &m))
+    return NULL;
+
+  stream = __newstream ();
+  if (stream == NULL)
+    return NULL;
+
+  if (__stdio_open (filename, m, &stream->__cookie))
+    {
+      int save = errno;
+      (void) fclose (stream);
+      errno = save;
+      return NULL;
+    }
+
+  stream->__mode = m;
+
+  return stream;
+}
diff --git a/stdio/fopncook.c b/stdio/fopncook.c
new file mode 100644
index 0000000000..b61bdda959
--- /dev/null
+++ b/stdio/fopncook.c
@@ -0,0 +1,48 @@
+/* Copyright (C) 1991, 1992 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdio.h>
+
+
+/* Defined in fopen.c.  */
+extern int EXFUN(__getmode, (CONST char *mode, __io_mode *mptr));
+
+/* Open a new stream on the given magic cookie descriptor.  */
+FILE *
+DEFUN(fopencookie, (cookie, mode, functions),
+      PTR cookie AND CONST char *mode AND __io_functions functions)
+{
+  __io_mode m;
+  FILE *f;
+
+  if (!__getmode (mode, &m))
+    return NULL;
+
+  f = __newstream ();
+  if (f == NULL)
+    return NULL;
+
+  f->__cookie = cookie;
+  f->__mode = m;
+  f->__io_funcs = functions;
+  f->__room_funcs = __default_room_functions;
+  f->__seen = 1;
+
+  return f;
+}
diff --git a/stdio/fpioconst.c b/stdio/fpioconst.c
new file mode 100644
index 0000000000..231cae34ed
--- /dev/null
+++ b/stdio/fpioconst.c
@@ -0,0 +1,401 @@
+/* Table of MP integer constants 10^(2^i), used for floating point <-> decimal.
+Copyright (C) 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include "fpioconst.h"
+#include <gmp-mparam.h>		/* This defines BITS_PER_MP_LIMB.  */
+
+/* First page	: 32-bit limbs
+   Second page	: 64-bit limbs
+   Last page	: table of pointers
+ */
+
+#if BITS_PER_MP_LIMB == 32
+
+/* Table with constants of 10^(2^i), i=0..12 for 32-bit limbs.	*/
+
+static const mp_limb _ten_p0[] =
+  { 0x00000000, 0x00000000, 0x0000000a };
+static const mp_limb _ten_p1[] =
+  { 0x00000000, 0x00000000, 0x00000064 };
+static const mp_limb _ten_p2[] =
+  { 0x00000000, 0x00000000, 0x00002710 };
+static const mp_limb _ten_p3[] =
+  { 0x00000000, 0x00000000, 0x05f5e100 };
+static const mp_limb _ten_p4[] =
+  { 0x00000000, 0x00000000, 0x6fc10000, 0x002386f2 };
+static const mp_limb _ten_p5[] =
+  { 0x00000000, 0x00000000, 0x00000000, 0x85acef81, 0x2d6d415b, 0x000004ee };
+static const mp_limb _ten_p6[] =
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xbf6a1f01, 0x6e38ed64,
+    0xdaa797ed, 0xe93ff9f4, 0x00184f03 };
+static const mp_limb _ten_p7[] =
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x2e953e01, 0x03df9909, 0x0f1538fd, 0x2374e42f, 0xd3cff5ec, 0xc404dc08,
+    0xbccdb0da, 0xa6337f19, 0xe91f2603, 0x0000024e };
+static const mp_limb _ten_p8[] =
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x982e7c01, 0xbed3875b,
+    0xd8d99f72, 0x12152f87, 0x6bde50c6, 0xcf4a6e70, 0xd595d80f, 0x26b2716e,
+    0xadc666b0, 0x1d153624, 0x3c42d35a, 0x63ff540e, 0xcc5573c0, 0x65f9ef17,
+    0x55bc28f2, 0x80dcc7f7, 0xf46eeddc, 0x5fdcefce, 0x000553f7 };
+static const mp_limb _ten_p9[] =
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0xfc6cf801, 0x77f27267, 0x8f9546dc, 0x5d96976f, 0xb83a8a97, 0xc31e1ad9,
+    0x46c40513, 0x94e65747, 0xc88976c1, 0x4475b579, 0x28f8733b, 0xaa1da1bf,
+    0x703ed321, 0x1e25cfea, 0xb21a2f22, 0xbc51fb2e, 0x96e14f5d, 0xbfa3edac,
+    0x329c57ae, 0xe7fc7153, 0xc3fc0695, 0x85a91924, 0xf95f635e, 0xb2908ee0,
+    0x93abade4, 0x1366732a, 0x9449775c, 0x69be5b0e, 0x7343afac, 0xb099bc81,
+    0x45a71d46, 0xa2699748, 0x8cb07303, 0x8a0b1f13, 0x8cab8a97, 0xc1d238d9,
+    0x633415d4, 0x0000001c };
+static const mp_limb _ten_p10[] =
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x2919f001, 0xf55b2b72,
+    0x6e7c215b, 0x1ec29f86, 0x991c4e87, 0x15c51a88, 0x140ac535, 0x4c7d1e1a,
+    0xcc2cd819, 0x0ed1440e, 0x896634ee, 0x7de16cfb, 0x1e43f61f, 0x9fce837d,
+    0x231d2b9c, 0x233e55c7, 0x65dc60d7, 0xf451218b, 0x1c5cd134, 0xc9635986,
+    0x922bbb9f, 0xa7e89431, 0x9f9f2a07, 0x62be695a, 0x8e1042c4, 0x045b7a74,
+    0x1abe1de3, 0x8ad822a5, 0xba34c411, 0xd814b505, 0xbf3fdeb3, 0x8fc51a16,
+    0xb1b896bc, 0xf56deeec, 0x31fb6bfd, 0xb6f4654b, 0x101a3616, 0x6b7595fb,
+    0xdc1a47fe, 0x80d98089, 0x80bda5a5, 0x9a202882, 0x31eb0f66, 0xfc8f1f90,
+    0x976a3310, 0xe26a7b7e, 0xdf68368a, 0x3ce3a0b8, 0x8e4262ce, 0x75a351a2,
+    0x6cb0b6c9, 0x44597583, 0x31b5653f, 0xc356e38a, 0x35faaba6, 0x0190fba0,
+    0x9fc4ed52, 0x88bc491b, 0x1640114a, 0x005b8041, 0xf4f3235e, 0x1e8d4649,
+    0x36a8de06, 0x73c55349, 0xa7e6bd2a, 0xc1a6970c, 0x47187094, 0xd2db49ef,
+    0x926c3f5b, 0xae6209d4, 0x2d433949, 0x34f4a3c6, 0xd4305d94, 0xd9d61a05,
+    0x00000325 };
+static const mp_limb _ten_p11[] =
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x1333e001, 0xe3096865, 0xb27d4d3f, 0x49e28dcf, 0xec2e4721, 0xee87e354,
+    0xb6067584, 0x368b8abb, 0xa5e5a191, 0x2ed56d55, 0xfd827773, 0xea50d142,
+    0x51b78db2, 0x98342c9e, 0xc850dabc, 0x866ed6f1, 0x19342c12, 0x92794987,
+    0xd2f869c2, 0x66912e4a, 0x71c7fd8f, 0x57a7842d, 0x235552eb, 0xfb7fedcc,
+    0xf3861ce0, 0x38209ce1, 0x9713b449, 0x34c10134, 0x8c6c54de, 0xa7a8289c,
+    0x2dbb6643, 0xe3cb64f3, 0x8074ff01, 0xe3892ee9, 0x10c17f94, 0xa8f16f92,
+    0xa8281ed6, 0x967abbb3, 0x5a151440, 0x9952fbed, 0x13b41e44, 0xafe609c3,
+    0xa2bca416, 0xf111821f, 0xfb1264b4, 0x91bac974, 0xd6c7d6ab, 0x8e48ff35,
+    0x4419bd43, 0xc4a65665, 0x685e5510, 0x33554c36, 0xab498697, 0x0dbd21fe,
+    0x3cfe491d, 0x982da466, 0xcbea4ca7, 0x9e110c7b, 0x79c56b8a, 0x5fc5a047,
+    0x84d80e2e, 0x1aa9f444, 0x730f203c, 0x6a57b1ab, 0xd752f7a6, 0x87a7dc62,
+    0x944545ff, 0x40660460, 0x77c1a42f, 0xc9ac375d, 0xe866d7ef, 0x744695f0,
+    0x81428c85, 0xa1fc6b96, 0xd7917c7b, 0x7bf03c19, 0x5b33eb41, 0x5715f791,
+    0x8f6cae5f, 0xdb0708fd, 0xb125ac8e, 0x785ce6b7, 0x56c6815b, 0x6f46eadb,
+    0x4eeebeee, 0x195355d8, 0xa244de3c, 0x9d7389c0, 0x53761abd, 0xcf99d019,
+    0xde9ec24b, 0x0d76ce39, 0x70beb181, 0x2e55ecee, 0xd5f86079, 0xf56d9d4b,
+    0xfb8886fb, 0x13ef5a83, 0x408f43c5, 0x3f3389a4, 0xfad37943, 0x58ccf45c,
+    0xf82df846, 0x415c7f3e, 0x2915e818, 0x8b3d5cf4, 0x6a445f27, 0xf8dbb57a,
+    0xca8f0070, 0x8ad803ec, 0xb2e87c34, 0x038f9245, 0xbedd8a6c, 0xc7c9dee0,
+    0x0eac7d56, 0x2ad3fa14, 0xe0de0840, 0xf775677c, 0xf1bd0ad5, 0x92be221e,
+    0x87fa1fb9, 0xce9d04a4, 0xd2c36fa9, 0x3f6f7024, 0xb028af62, 0x907855ee,
+    0xd83e49d6, 0x4efac5dc, 0xe7151aab, 0x77cd8c6b, 0x0a753b7d, 0x0af908b4,
+    0x8c983623, 0xe50f3027, 0x94222771, 0x1d08e2d6, 0xf7e928e6, 0xf2ee5ca6,
+    0x1b61b93c, 0x11eb962b, 0x9648b21c, 0xce2bcba1, 0x34f77154, 0x7bbebe30,
+    0xe526a319, 0x8ce329ac, 0xde4a74d2, 0xb5dc53d5, 0x0009e8b3 };
+static const mp_limb _ten_p12[] =
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x2a67c001, 0xd4724e8d,
+    0x8efe7ae7, 0xf89a1e90, 0xef084117, 0x54e05154, 0x13b1bb51, 0x506be829,
+    0xfb29b172, 0xe599574e, 0xf0da6146, 0x806c0ed3, 0xb86ae5be, 0x45155e93,
+    0xc0591cc2, 0x7e1e7c34, 0x7c4823da, 0x1d1f4cce, 0x9b8ba1e8, 0xd6bfdf75,
+    0xe341be10, 0xc2dfae78, 0x016b67b2, 0x0f237f1a, 0x3dbeabcd, 0xaf6a2574,
+    0xcab3e6d7, 0x142e0e80, 0x61959127, 0x2c234811, 0x87009701, 0xcb4bf982,
+    0xf8169c84, 0x88052f8c, 0x68dde6d4, 0xbc131761, 0xff0b0905, 0x54ab9c41,
+    0x7613b224, 0x1a1c304e, 0x3bfe167b, 0x441c2d47, 0x4f6cea9c, 0x78f06181,
+    0xeb659fb8, 0x30c7ae41, 0x947e0d0e, 0xa1ebcad7, 0xd97d9556, 0x2130504d,
+    0x1a8309cb, 0xf2acd507, 0x3f8ec72a, 0xfd82373a, 0x95a842bc, 0x280f4d32,
+    0xf3618ac0, 0x811a4f04, 0x6dc3a5b4, 0xd3967a1b, 0x15b8c898, 0xdcfe388f,
+    0x454eb2a0, 0x8738b909, 0x10c4e996, 0x2bd9cc11, 0x3297cd0c, 0x655fec30,
+    0xae0725b1, 0xf4090ee8, 0x037d19ee, 0x398c6fed, 0x3b9af26b, 0xc994a450,
+    0xb5341743, 0x75a697b2, 0xac50b9c1, 0x3ccb5b92, 0xffe06205, 0xa8329761,
+    0xdfea5242, 0xeb83cadb, 0xe79dadf7, 0x3c20ee69, 0x1e0a6817, 0x7021b97a,
+    0x743074fa, 0x176ca776, 0x77fb8af6, 0xeca19beb, 0x92baf1de, 0xaf63b712,
+    0xde35c88b, 0xa4eb8f8c, 0xe137d5e9, 0x40b464a0, 0x87d1cde8, 0x42923bbd,
+    0xcd8f62ff, 0x2e2690f3, 0x095edc16, 0x59c89f1b, 0x1fa8fd5d, 0x5138753d,
+    0x390a2b29, 0x80152f18, 0x2dd8d925, 0xf984d83e, 0x7a872e74, 0xc19e1faf,
+    0xed4d542d, 0xecf9b5d0, 0x9462ea75, 0xc53c0adf, 0x0caea134, 0x37a2d439,
+    0xc8fa2e8a, 0x2181327e, 0x6e7bb827, 0x2d240820, 0x50be10e0, 0x5893d4b8,
+    0xab312bb9, 0x1f2b2322, 0x440b3f25, 0xbf627ede, 0x72dac789, 0xb608b895,
+    0x78787e2a, 0x86deb3f0, 0x6fee7aab, 0xbb9373f4, 0x27ecf57b, 0xf7d8b57e,
+    0xfca26a9f, 0x3d04e8d2, 0xc9df13cb, 0x3172826a, 0xcd9e8d7c, 0xa8fcd8e0,
+    0xb2c39497, 0x307641d9, 0x1cc939c1, 0x2608c4cf, 0xb6d1c7bf, 0x3d326a7e,
+    0xeeaf19e6, 0x8e13e25f, 0xee63302b, 0x2dfe6d97, 0x25971d58, 0xe41d3cc4,
+    0x0a80627c, 0xab8db59a, 0x9eea37c8, 0xe90afb77, 0x90ca19cf, 0x9ee3352c,
+    0x3613c850, 0xfe78d682, 0x788f6e50, 0x5b060904, 0xb71bd1a4, 0x3fecb534,
+    0xb32c450c, 0x20c33857, 0xa6e9cfda, 0x0239f4ce, 0x48497187, 0xa19adb95,
+    0xb492ed8a, 0x95aca6a8, 0x4dcd6cd9, 0xcf1b2350, 0xfbe8b12a, 0x1a67778c,
+    0x38eb3acc, 0xc32da383, 0xfb126ab1, 0xa03f40a8, 0xed5bf546, 0xe9ce4724,
+    0x4c4a74fd, 0x73a130d8, 0xd9960e2d, 0xa2ebd6c1, 0x94ab6feb, 0x6f233b7c,
+    0x49126080, 0x8e7b9a73, 0x4b8c9091, 0xd298f999, 0x35e836b5, 0xa96ddeff,
+    0x96119b31, 0x6b0dd9bc, 0xc6cc3f8d, 0x282566fb, 0x72b882e7, 0xd6769f3b,
+    0xa674343d, 0x00fc509b, 0xdcbf7789, 0xd6266a3f, 0xae9641fd, 0x4e89541b,
+    0x11953407, 0x53400d03, 0x8e0dd75a, 0xe5b53345, 0x108f19ad, 0x108b89bc,
+    0x41a4c954, 0xe03b2b63, 0x437b3d7f, 0x97aced8e, 0xcbd66670, 0x2c5508c2,
+    0x650ebc69, 0x5c4f2ef0, 0x904ff6bf, 0x9985a2df, 0x9faddd9e, 0x5ed8d239,
+    0x25585832, 0xe3e51cb9, 0x0ff4f1d4, 0x56c02d9a, 0x8c4ef804, 0xc1a08a13,
+    0x13fd01c8, 0xe6d27671, 0xa7c234f4, 0x9d0176cc, 0xd0d73df2, 0x4d8bfa89,
+    0x544f10cd, 0x2b17e0b2, 0xb70a5c7d, 0xfd86fe49, 0xdf373f41, 0x214495bb,
+    0x84e857fd, 0x00d313d5, 0x0496fcbe, 0xa4ba4744, 0xe8cac982, 0xaec29e6e,
+    0x87ec7038, 0x7000a519, 0xaeee333b, 0xff66e42c, 0x8afd6b25, 0x03b4f63b,
+    0xbd7991dc, 0x5ab8d9c7, 0x2ed4684e, 0x48741a6c, 0xaf06940d, 0x2fdc6349,
+    0xb03d7ecd, 0xe974996f, 0xac7867f9, 0x52ec8721, 0xbcdd9d4a, 0x8edd2d00,
+    0x3557de06, 0x41c759f8, 0x3956d4b9, 0xa75409f2, 0x123cd8a1, 0xb6100fab,
+    0x3e7b21e2, 0x2e8d623b, 0x92959da2, 0xbca35f77, 0x200c03a5, 0x35fcb457,
+    0x1bb6c6e4, 0xf74eb928, 0x3d5d0b54, 0x87cc1d21, 0x4964046f, 0x18ae4240,
+    0xd868b275, 0x8bd2b496, 0x1c5563f4, 0xc234d8f5, 0xf868e970, 0xf9151fff,
+    0xae7be4a2, 0x271133ee, 0xbb0fd922, 0x25254932, 0xa60a9fc0, 0x104bcd64,
+    0x30290145, 0x00000062 };
+
+#define LAST_POW10	12
+
+#elif BITS_PER_MP_LIMB == 64
+
+/* Table with constants of 10^(2^i), i=0..12 for 64-bit limbs.	*/
+
+static const mp_limb _ten_p0[] =
+  { 0x0000000000000000, 0x000000000000000a };
+static const mp_limb _ten_p1[] =
+  { 0x0000000000000000, 0x0000000000000064 };
+static const mp_limb _ten_p2[] =
+  { 0x0000000000000000, 0x0000000000002710 };
+static const mp_limb _ten_p3[] =
+  { 0x0000000000000000, 0x0000000005f5e100 };
+static const mp_limb _ten_p4[] =
+  { 0x0000000000000000, 0x002386f26fc10000 };
+static const mp_limb _ten_p5[] =
+  { 0x0000000000000000, 0x85acef8100000000, 0x000004ee2d6d415b };
+static const mp_limb _ten_p6[] =
+  { 0x0000000000000000, 0x0000000000000000, 0x6e38ed64bf6a1f01,
+    0xe93ff9f4daa797ed, 0x0000000000184f03 };
+static const mp_limb _ten_p7[] =
+  { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x03df99092e953e01, 0x2374e42f0f1538fd, 0xc404dc08d3cff5ec,
+    0xa6337f19bccdb0da, 0x0000024ee91f2603 };
+static const mp_limb _ten_p8[] =
+  { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0xbed3875b982e7c01,
+    0x12152f87d8d99f72, 0xcf4a6e706bde50c6, 0x26b2716ed595d80f,
+    0x1d153624adc666b0, 0x63ff540e3c42d35a, 0x65f9ef17cc5573c0,
+    0x80dcc7f755bc28f2, 0x5fdcefcef46eeddc, 0x00000000000553f7 };
+static const mp_limb _ten_p9[] =
+  { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x77f27267fc6cf801, 0x5d96976f8f9546dc, 0xc31e1ad9b83a8a97,
+    0x94e6574746c40513, 0x4475b579c88976c1, 0xaa1da1bf28f8733b,
+    0x1e25cfea703ed321, 0xbc51fb2eb21a2f22, 0xbfa3edac96e14f5d,
+    0xe7fc7153329c57ae, 0x85a91924c3fc0695, 0xb2908ee0f95f635e,
+    0x1366732a93abade4, 0x69be5b0e9449775c, 0xb099bc817343afac,
+    0xa269974845a71d46, 0x8a0b1f138cb07303, 0xc1d238d98cab8a97,
+    0x0000001c633415d4 };
+static const mp_limb _ten_p10[] =
+  { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0xf55b2b722919f001,
+    0x1ec29f866e7c215b, 0x15c51a88991c4e87, 0x4c7d1e1a140ac535,
+    0x0ed1440ecc2cd819, 0x7de16cfb896634ee, 0x9fce837d1e43f61f,
+    0x233e55c7231d2b9c, 0xf451218b65dc60d7, 0xc96359861c5cd134,
+    0xa7e89431922bbb9f, 0x62be695a9f9f2a07, 0x045b7a748e1042c4,
+    0x8ad822a51abe1de3, 0xd814b505ba34c411, 0x8fc51a16bf3fdeb3,
+    0xf56deeecb1b896bc, 0xb6f4654b31fb6bfd, 0x6b7595fb101a3616,
+    0x80d98089dc1a47fe, 0x9a20288280bda5a5, 0xfc8f1f9031eb0f66,
+    0xe26a7b7e976a3310, 0x3ce3a0b8df68368a, 0x75a351a28e4262ce,
+    0x445975836cb0b6c9, 0xc356e38a31b5653f, 0x0190fba035faaba6,
+    0x88bc491b9fc4ed52, 0x005b80411640114a, 0x1e8d4649f4f3235e,
+    0x73c5534936a8de06, 0xc1a6970ca7e6bd2a, 0xd2db49ef47187094,
+    0xae6209d4926c3f5b, 0x34f4a3c62d433949, 0xd9d61a05d4305d94,
+    0x0000000000000325 };
+static const mp_limb _ten_p11[] =
+  { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0xe30968651333e001, 0x49e28dcfb27d4d3f, 0xee87e354ec2e4721,
+    0x368b8abbb6067584, 0x2ed56d55a5e5a191, 0xea50d142fd827773,
+    0x98342c9e51b78db2, 0x866ed6f1c850dabc, 0x9279498719342c12,
+    0x66912e4ad2f869c2, 0x57a7842d71c7fd8f, 0xfb7fedcc235552eb,
+    0x38209ce1f3861ce0, 0x34c101349713b449, 0xa7a8289c8c6c54de,
+    0xe3cb64f32dbb6643, 0xe3892ee98074ff01, 0xa8f16f9210c17f94,
+    0x967abbb3a8281ed6, 0x9952fbed5a151440, 0xafe609c313b41e44,
+    0xf111821fa2bca416, 0x91bac974fb1264b4, 0x8e48ff35d6c7d6ab,
+    0xc4a656654419bd43, 0x33554c36685e5510, 0x0dbd21feab498697,
+    0x982da4663cfe491d, 0x9e110c7bcbea4ca7, 0x5fc5a04779c56b8a,
+    0x1aa9f44484d80e2e, 0x6a57b1ab730f203c, 0x87a7dc62d752f7a6,
+    0x40660460944545ff, 0xc9ac375d77c1a42f, 0x744695f0e866d7ef,
+    0xa1fc6b9681428c85, 0x7bf03c19d7917c7b, 0x5715f7915b33eb41,
+    0xdb0708fd8f6cae5f, 0x785ce6b7b125ac8e, 0x6f46eadb56c6815b,
+    0x195355d84eeebeee, 0x9d7389c0a244de3c, 0xcf99d01953761abd,
+    0x0d76ce39de9ec24b, 0x2e55ecee70beb181, 0xf56d9d4bd5f86079,
+    0x13ef5a83fb8886fb, 0x3f3389a4408f43c5, 0x58ccf45cfad37943,
+    0x415c7f3ef82df846, 0x8b3d5cf42915e818, 0xf8dbb57a6a445f27,
+    0x8ad803ecca8f0070, 0x038f9245b2e87c34, 0xc7c9dee0bedd8a6c,
+    0x2ad3fa140eac7d56, 0xf775677ce0de0840, 0x92be221ef1bd0ad5,
+    0xce9d04a487fa1fb9, 0x3f6f7024d2c36fa9, 0x907855eeb028af62,
+    0x4efac5dcd83e49d6, 0x77cd8c6be7151aab, 0x0af908b40a753b7d,
+    0xe50f30278c983623, 0x1d08e2d694222771, 0xf2ee5ca6f7e928e6,
+    0x11eb962b1b61b93c, 0xce2bcba19648b21c, 0x7bbebe3034f77154,
+    0x8ce329ace526a319, 0xb5dc53d5de4a74d2, 0x000000000009e8b3 };
+static const mp_limb _ten_p12[] =
+  { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+    0x0000000000000000, 0x0000000000000000, 0xd4724e8d2a67c001,
+    0xf89a1e908efe7ae7, 0x54e05154ef084117, 0x506be82913b1bb51,
+    0xe599574efb29b172, 0x806c0ed3f0da6146, 0x45155e93b86ae5be,
+    0x7e1e7c34c0591cc2, 0x1d1f4cce7c4823da, 0xd6bfdf759b8ba1e8,
+    0xc2dfae78e341be10, 0x0f237f1a016b67b2, 0xaf6a25743dbeabcd,
+    0x142e0e80cab3e6d7, 0x2c23481161959127, 0xcb4bf98287009701,
+    0x88052f8cf8169c84, 0xbc13176168dde6d4, 0x54ab9c41ff0b0905,
+    0x1a1c304e7613b224, 0x441c2d473bfe167b, 0x78f061814f6cea9c,
+    0x30c7ae41eb659fb8, 0xa1ebcad7947e0d0e, 0x2130504dd97d9556,
+    0xf2acd5071a8309cb, 0xfd82373a3f8ec72a, 0x280f4d3295a842bc,
+    0x811a4f04f3618ac0, 0xd3967a1b6dc3a5b4, 0xdcfe388f15b8c898,
+    0x8738b909454eb2a0, 0x2bd9cc1110c4e996, 0x655fec303297cd0c,
+    0xf4090ee8ae0725b1, 0x398c6fed037d19ee, 0xc994a4503b9af26b,
+    0x75a697b2b5341743, 0x3ccb5b92ac50b9c1, 0xa8329761ffe06205,
+    0xeb83cadbdfea5242, 0x3c20ee69e79dadf7, 0x7021b97a1e0a6817,
+    0x176ca776743074fa, 0xeca19beb77fb8af6, 0xaf63b71292baf1de,
+    0xa4eb8f8cde35c88b, 0x40b464a0e137d5e9, 0x42923bbd87d1cde8,
+    0x2e2690f3cd8f62ff, 0x59c89f1b095edc16, 0x5138753d1fa8fd5d,
+    0x80152f18390a2b29, 0xf984d83e2dd8d925, 0xc19e1faf7a872e74,
+    0xecf9b5d0ed4d542d, 0xc53c0adf9462ea75, 0x37a2d4390caea134,
+    0x2181327ec8fa2e8a, 0x2d2408206e7bb827, 0x5893d4b850be10e0,
+    0x1f2b2322ab312bb9, 0xbf627ede440b3f25, 0xb608b89572dac789,
+    0x86deb3f078787e2a, 0xbb9373f46fee7aab, 0xf7d8b57e27ecf57b,
+    0x3d04e8d2fca26a9f, 0x3172826ac9df13cb, 0xa8fcd8e0cd9e8d7c,
+    0x307641d9b2c39497, 0x2608c4cf1cc939c1, 0x3d326a7eb6d1c7bf,
+    0x8e13e25feeaf19e6, 0x2dfe6d97ee63302b, 0xe41d3cc425971d58,
+    0xab8db59a0a80627c, 0xe90afb779eea37c8, 0x9ee3352c90ca19cf,
+    0xfe78d6823613c850, 0x5b060904788f6e50, 0x3fecb534b71bd1a4,
+    0x20c33857b32c450c, 0x0239f4cea6e9cfda, 0xa19adb9548497187,
+    0x95aca6a8b492ed8a, 0xcf1b23504dcd6cd9, 0x1a67778cfbe8b12a,
+    0xc32da38338eb3acc, 0xa03f40a8fb126ab1, 0xe9ce4724ed5bf546,
+    0x73a130d84c4a74fd, 0xa2ebd6c1d9960e2d, 0x6f233b7c94ab6feb,
+    0x8e7b9a7349126080, 0xd298f9994b8c9091, 0xa96ddeff35e836b5,
+    0x6b0dd9bc96119b31, 0x282566fbc6cc3f8d, 0xd6769f3b72b882e7,
+    0x00fc509ba674343d, 0xd6266a3fdcbf7789, 0x4e89541bae9641fd,
+    0x53400d0311953407, 0xe5b533458e0dd75a, 0x108b89bc108f19ad,
+    0xe03b2b6341a4c954, 0x97aced8e437b3d7f, 0x2c5508c2cbd66670,
+    0x5c4f2ef0650ebc69, 0x9985a2df904ff6bf, 0x5ed8d2399faddd9e,
+    0xe3e51cb925585832, 0x56c02d9a0ff4f1d4, 0xc1a08a138c4ef804,
+    0xe6d2767113fd01c8, 0x9d0176cca7c234f4, 0x4d8bfa89d0d73df2,
+    0x2b17e0b2544f10cd, 0xfd86fe49b70a5c7d, 0x214495bbdf373f41,
+    0x00d313d584e857fd, 0xa4ba47440496fcbe, 0xaec29e6ee8cac982,
+    0x7000a51987ec7038, 0xff66e42caeee333b, 0x03b4f63b8afd6b25,
+    0x5ab8d9c7bd7991dc, 0x48741a6c2ed4684e, 0x2fdc6349af06940d,
+    0xe974996fb03d7ecd, 0x52ec8721ac7867f9, 0x8edd2d00bcdd9d4a,
+    0x41c759f83557de06, 0xa75409f23956d4b9, 0xb6100fab123cd8a1,
+    0x2e8d623b3e7b21e2, 0xbca35f7792959da2, 0x35fcb457200c03a5,
+    0xf74eb9281bb6c6e4, 0x87cc1d213d5d0b54, 0x18ae42404964046f,
+    0x8bd2b496d868b275, 0xc234d8f51c5563f4, 0xf9151ffff868e970,
+    0x271133eeae7be4a2, 0x25254932bb0fd922, 0x104bcd64a60a9fc0,
+    0x0000006230290145 };
+
+#define LAST_POW10	12
+
+#else
+#  error "mp_limb size " BITS_PER_MP_LIMB "not accounted for"
+#endif
+
+
+/* Each of array variable above defines one mpn integer which is a power of 10.
+   This table points to those variables, indexed by the exponent.  */
+
+const struct mp_power _fpioconst_pow10[LDBL_MAX_10_EXP_LOG + 1] =
+  {
+    { _ten_p0, sizeof (_ten_p0) / sizeof (_ten_p0[0]),		4,	     },
+    { _ten_p1, sizeof (_ten_p1) / sizeof (_ten_p0[1]),		7,	   4 },
+    { _ten_p2, sizeof (_ten_p2) / sizeof (_ten_p0[2]),		14,	  10 },
+    { _ten_p3, sizeof (_ten_p3) / sizeof (_ten_p0[3]),		27,	  24 },
+    { _ten_p4, sizeof (_ten_p4) / sizeof (_ten_p0[4]),		54,	  50 },
+    { _ten_p5, sizeof (_ten_p5) / sizeof (_ten_p0[5]),		107,	 103 },
+    { _ten_p6, sizeof (_ten_p6) / sizeof (_ten_p0[6]),		213,	 210 },
+    { _ten_p7, sizeof (_ten_p7) / sizeof (_ten_p0[7]),		426,	 422 },
+    { _ten_p8, sizeof (_ten_p8) / sizeof (_ten_p0[8]),	  	851,	 848 },
+    { _ten_p9, sizeof (_ten_p9) / sizeof (_ten_p0[9]),	 	1701,	1698 },
+    { _ten_p10, sizeof (_ten_p10) / sizeof (_ten_p0[10]),	3402,	3399 },
+    { _ten_p11, sizeof (_ten_p11) / sizeof (_ten_p0[11]),	6804,	6800 },
+    { _ten_p12, sizeof (_ten_p12) / sizeof (_ten_p0[12]), 	13607, 13604 }
+  };
+
+#if LDBL_MAX_10_EXP_LOG > LAST_POW10
+#error "Need to expand 10^(2^i) table for i up to" LDBL_MAX_10_EXP_LOG
+#endif
diff --git a/stdio/fpioconst.h b/stdio/fpioconst.h
new file mode 100644
index 0000000000..8edbdccb17
--- /dev/null
+++ b/stdio/fpioconst.h
@@ -0,0 +1,52 @@
+/* Header file for constants used in floating point <-> decimal conversions.
+Copyright (C) 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#ifndef _FPIOCONST_H
+#define	_FPIOCONST_H
+
+#include <float.h>
+#include "gmp.h"
+
+
+/* These values are used by __printf_fp, where they are noncritical (if the
+   value is not large enough, it will just be slower); and by
+   strtof/strtod/strtold, where it is critical (it's used for overflow
+   detection).
+
+   XXX These should be defined in <float.h>.  For the time being, we have the
+   IEEE754 values here.  */
+
+#define LDBL_MAX_10_EXP_LOG	12 /* = floor(log_2(LDBL_MAX_10_EXP)) */
+#define DBL_MAX_10_EXP_LOG	8 /* = floor(log_2(DBL_MAX_10_EXP)) */
+#define FLT_MAX_10_EXP_LOG	5 /* = floor(log_2(FLT_MAX_10_EXP)) */
+
+
+/* Table of powers of ten.  This is used by __printf_fp and by
+   strtof/strtod/strtold.  */
+struct mp_power
+  {
+    const mp_limb *array;	/* The array with the number representation. */
+    mp_size_t arraysize;	/* Size of the array.  */
+    int p_expo;			/* Exponent of the number 10^(2^i).  */
+    int m_expo;			/* Exponent of the number 10^-(2^i-1).  */
+  };
+extern const struct mp_power _fpioconst_pow10[LDBL_MAX_10_EXP_LOG + 1];
+
+
+#endif	/* fpioconst.h */
diff --git a/stdio/fprintf.c b/stdio/fprintf.c
new file mode 100644
index 0000000000..bc6d1003b7
--- /dev/null
+++ b/stdio/fprintf.c
@@ -0,0 +1,38 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+
+/* Write formatted output to STREAM from the format string FORMAT.  */
+/* VARARGS2 */
+int
+DEFUN(fprintf, (stream, format),
+      FILE *stream AND CONST char *format DOTS)
+{
+  va_list arg;
+  int done;
+
+  va_start(arg, format);
+  done = vfprintf(stream, format, arg);
+  va_end(arg);
+
+  return done;
+}
diff --git a/stdio/fputc.c b/stdio/fputc.c
new file mode 100644
index 0000000000..36b9501195
--- /dev/null
+++ b/stdio/fputc.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stdio.h>
+
+
+/* Write the character C to STREAM.  */
+int
+DEFUN(fputc, (c, stream), int c AND FILE *stream)
+{
+  if (!__validfp(stream) || !stream->__mode.__write)
+    {
+      errno = EINVAL;
+      return EOF;
+    }
+
+  return __putc(c, stream);
+}
diff --git a/stdio/fputs.c b/stdio/fputs.c
new file mode 100644
index 0000000000..a149a1c329
--- /dev/null
+++ b/stdio/fputs.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 1991, 1992 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+
+/* Write the string S to STREAM.  */
+int
+DEFUN(fputs, (s, stream), CONST char *s AND FILE *stream)
+{
+  register CONST size_t len = strlen (s);
+  if (len == 1)
+    return putc (*s, stream) == EOF ? EOF : 0;
+  if (fwrite ((PTR) s, 1, len, stream) != len)
+    return EOF;
+  return 0;
+}
diff --git a/stdio/fread.c b/stdio/fread.c
new file mode 100644
index 0000000000..347e8446e1
--- /dev/null
+++ b/stdio/fread.c
@@ -0,0 +1,128 @@
+/* Copyright (C) 1991, 1992 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+
+#define	default_func	__default_room_functions.__input
+
+/* Read NMEMB chunks of SIZE bytes each from STREAM into P.  */
+size_t
+DEFUN(fread, (p, size, nmemb, stream),
+      PTR p AND size_t size AND size_t nmemb AND register FILE *stream)
+{
+  register char *ptr = (char *) p;
+  register size_t to_read = size * nmemb;
+  size_t bytes = to_read;
+
+  if (!__validfp(stream) || !stream->__mode.__read)
+    {
+      errno = EINVAL;
+      return 0;
+    }
+  if (feof(stream) || ferror(stream))
+    return 0;
+  if (p == NULL || to_read == 0)
+    return 0;
+
+  if (!stream->__seen || stream->__buffer == NULL || stream->__pushed_back)
+    {
+      /* This stream has never been seen before, or it has a character
+	 pushed back.  Call __fillbf to deal with those cases.  Life will
+	 be simpler after this call.  */
+      int c = __fillbf(stream);
+      if (c == EOF)
+	return 0;
+      *ptr++ = c;
+      if (--to_read == 0)
+	return 1;
+    }
+
+ read_from_buffer:;
+  if (stream->__bufp < stream->__get_limit)
+    {
+      /* First off, empty out the buffer.  */
+      register size_t copy = stream->__get_limit - stream->__bufp;
+      if (copy > to_read)
+	copy = to_read;
+      to_read -= copy;
+      if (copy > 20)
+	memcpy((PTR) ptr, (PTR) stream->__bufp, copy);
+      else
+	{
+	  register size_t i;
+	  for (i = 0; i < copy; ++i)
+	    ptr[i] = stream->__bufp[i];
+	}
+      stream->__bufp += copy;
+      if (to_read == 0)
+	return nmemb;
+      ptr += copy;
+    }
+
+  /* Reading directly into the user's buffer doesn't help when
+     using a user-specified input buffer filling/expanding function,
+     so we don't do it in that case.  */
+  if (to_read >= stream->__bufsize &&
+      stream->__room_funcs.__input == default_func &&
+      stream->__offset == stream->__target)
+    {
+      /* Read directly into the user's buffer.  */
+      if (stream->__io_funcs.__read != NULL)
+	while (to_read > 0)
+	  {
+	    register int count;
+	    count = (*stream->__io_funcs.__read)(stream->__cookie,
+						 ptr, to_read);
+	    if (count > 0)
+	      {
+		to_read -= count;
+		stream->__offset += count;
+		stream->__target += count;
+		ptr += count;
+	      }
+	    else if (count == 0)
+	      {
+		stream->__eof = 1;
+		break;
+	      }
+	    else
+	      {
+		stream->__error = 1;
+		break;
+	      }
+	  }
+      else
+	stream->__eof = 1;
+    }
+  else
+    {
+      int c = __fillbf(stream);
+      if (c == EOF)
+	return (bytes - to_read) / size;
+      *ptr++ = (char) c;
+      --to_read;
+      if (to_read > 0)
+	goto read_from_buffer;
+    }
+
+  return (bytes - to_read) / size;
+}
diff --git a/stdio/freopen.c b/stdio/freopen.c
new file mode 100644
index 0000000000..bedddb1a63
--- /dev/null
+++ b/stdio/freopen.c
@@ -0,0 +1,74 @@
+/* Copyright (C) 1991, 1994, 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stdio.h>
+
+
+/* Defined in fopen.c.  */
+extern int __getmode __P ((const char *, __io_mode *));
+
+/* Defined in sysd-stdio.c.  */
+extern int __stdio_reopen __P ((const char *filename, __io_mode mode,
+				PTR *cookieptr, __io_close_fn closefn));
+
+/* Replace STREAM, opening it on FILENAME.  */
+FILE *
+DEFUN(freopen, (filename, mode, stream),
+      CONST char *filename AND CONST char *mode AND register FILE *stream)
+{
+  __io_mode m;
+  PTR cookie;
+
+  if (!__getmode (mode, &m))
+    {
+      (void) fclose (stream);
+      errno = EINVAL;
+      return NULL;
+    }
+
+  if (stream->__mode.__write)
+    /* Flush the stream.  */
+    (void) fflush (stream);
+
+  /* Open the file, attempting to preserve the old cookie value.  */
+  cookie = stream->__cookie;
+  if (__stdio_reopen (filename, m, &cookie,
+		      stream->__seen ?
+		      stream->__io_funcs.__close :
+		      __stdio_close))
+    {
+      int save = errno;
+      (void) fclose (stream);
+      errno = save;
+      return NULL;
+    }
+
+  /* Close the stream, first disabling its cookie close function because
+     __stdio_reopen has already dealt with closing the old cookie.  */
+  stream->__seen = 1;		/* It might have no functions yet.  */
+  stream->__io_funcs.__close = NULL;
+  (void) fclose (stream);
+
+  stream->__magic = _IOMAGIC;
+  stream->__cookie = cookie;
+  stream->__mode = m;
+
+  return stream;
+}
diff --git a/stdio/fscanf.c b/stdio/fscanf.c
new file mode 100644
index 0000000000..cbe0103368
--- /dev/null
+++ b/stdio/fscanf.c
@@ -0,0 +1,38 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+
+/* Read formatted input from STREAM according to the format string FORMAT.  */
+/* VARARGS2 */
+int
+DEFUN(fscanf, (stream, format),
+      FILE *stream AND CONST char *format DOTS)
+{
+  va_list arg;
+  int done;
+
+  va_start(arg, format);
+  done = __vfscanf(stream, format, arg);
+  va_end(arg);
+
+  return done;
+}
diff --git a/stdio/fseek.c b/stdio/fseek.c
new file mode 100644
index 0000000000..a5abfe4866
--- /dev/null
+++ b/stdio/fseek.c
@@ -0,0 +1,177 @@
+/* Copyright (C) 1991, 1992, 1993, 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stdio.h>
+
+
+/* Move the file position of STREAM to OFFSET
+   bytes from the beginning of the file if WHENCE
+   is SEEK_SET, the end of the file is it is SEEK_END,
+   or the current position if it is SEEK_CUR.  */
+int
+DEFUN(fseek, (stream, offset, whence),
+      register FILE *stream AND long int offset AND int whence)
+{
+  long int o;
+
+  if (!__validfp (stream))
+    {
+      errno = EINVAL;
+      return EOF;
+    }
+
+  /* Write out any pending data.  */
+  if (stream->__mode.__write && __flshfp (stream, EOF) == EOF)
+    return EOF;
+
+  /* Make sure we know the current offset info.  */
+  if (__stdio_check_offset (stream) == EOF)
+    return EOF;
+
+  /* We are moving the file position, so we are no longer at EOF.  */
+  stream->__eof = 0;
+
+  if (stream->__pushed_back)
+    {
+      /* Discard the character pushed back by ungetc.  */
+      stream->__bufp = stream->__pushback_bufp;
+      stream->__pushed_back = 0;
+    }
+
+  /* Check the WHENCE argument for validity, and process OFFSET
+     into an absolute position in O.  By the end of this switch,
+     either we have returned, or O contains an absolute position.  */
+  o = offset;
+  switch (whence)
+    {
+    default:
+      errno = EINVAL;
+      return EOF;
+
+    case SEEK_END:
+      /* We don't know where the end of the file is,
+	 so seek to the position in the file the user asked
+	 for, and then look where that is.  */
+      if (stream->__io_funcs.__seek == NULL)
+	{
+	  errno = ESPIPE;
+	  return EOF;
+	}
+      else
+	{
+	  fpos_t pos = (fpos_t) o;
+	  if ((*stream->__io_funcs.__seek)
+	      (stream->__cookie, &pos, SEEK_END) < 0)
+	    {
+	      if (errno == ESPIPE)
+		stream->__io_funcs.__seek = NULL;
+	      return EOF;
+	    }
+	  stream->__offset = pos;
+	  /* Make O be absolute, rather than
+	     relative to the end of the file.  */
+	  o = pos;
+	}
+
+      /* Fall through to try an absolute seek.  */
+
+    case SEEK_SET:
+      /* Make O be relative to the buffer.  */
+      o -= stream->__target;
+      /* Make O be relative to the current position in the buffer.  */
+      o -= stream->__bufp - stream->__buffer;
+
+      /* Fall through to see if we can do it by
+	 moving the pointer around in the buffer.  */
+
+    case SEEK_CUR:
+      /* If the offset is small enough, we can just
+	 move the pointer around in the buffer.  */
+
+#if 0	/* Why did I think this would ever work???  */
+      if (stream->__put_limit > stream->__buffer)
+	{
+	  /* We are writing.  */
+	  if (stream->__bufp + o >= stream->__buffer &&
+	      stream->__put_limit > stream->__bufp + o &&
+	      stream->__get_limit > stream->__bufp + o)
+	    {
+	      /* We have read all the data we will change soon.
+		 We can just move the pointer around.  */
+	      stream->__bufp += o;
+	      return 0;
+	    }
+	  else
+	    {
+	      /* Flush the buffer.  */
+	      if (__flshfp(stream, EOF) == EOF)
+		return EOF;
+	    }
+	} else
+#endif
+      if (o < 0 ?
+	  (-o <= stream->__bufp - stream->__buffer) :
+	  (o <= stream->__get_limit - stream->__bufp))
+	{
+	  stream->__bufp += o;
+	  return 0;
+	}
+
+      /* Turn it into an absolute seek.  */
+      o += stream->__bufp - stream->__buffer;
+      o += stream->__target;
+      break;
+    }
+
+  if (o < 0)
+    {
+      /* Negative file position is meaningless.  */
+      errno = EINVAL;
+      return -1;
+    }
+
+  /* O is now an absolute position, the new target.  */
+  stream->__target = o;
+
+  /* Set bufp and both end pointers to the beginning of the buffer.
+     The next i/o will force a call to the input/output room function.  */
+  stream->__bufp
+    = stream->__get_limit = stream->__put_limit = stream->__buffer;
+
+  /* Make sure __flshfp doesn't think the put_limit is at the beginning
+     of the buffer because of line-buffering magic.  */
+  stream->__linebuf_active = 0;
+
+  /* If there is no seek function, seeks always fail.  */
+  if (stream->__io_funcs.__seek == NULL)
+    {
+      /* This is preemptive, since we don't actually do the seeking.
+	 But it makes more sense for fseek to to fail with ESPIPE
+	 than for the next reading or writing operation to fail
+	 that way.  */
+      errno = ESPIPE;
+      return EOF;
+    }
+
+  /* Don't actually seek.  The next reading or writing operation
+     will force a call to the input or output room function,
+     which will move to the target file position before reading or writing.  */
+  return 0;
+}
diff --git a/stdio/fsetpos.c b/stdio/fsetpos.c
new file mode 100644
index 0000000000..7c8fcb78bb
--- /dev/null
+++ b/stdio/fsetpos.c
@@ -0,0 +1,37 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stdio.h>
+
+#undef	fsetpos
+
+
+/* Set the file position of STREAM to *POS.  */
+int
+DEFUN(fsetpos, (stream, pos), FILE *stream AND CONST fpos_t *pos)
+{
+  if (pos == NULL)
+    {
+      errno = EINVAL;
+      return EOF;
+    }
+
+  return fseek(stream, *pos, SEEK_SET);
+}
diff --git a/stdio/ftell.c b/stdio/ftell.c
new file mode 100644
index 0000000000..d27eaf7598
--- /dev/null
+++ b/stdio/ftell.c
@@ -0,0 +1,54 @@
+/* Copyright (C) 1991, 1992, 1994 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stdio.h>
+
+/* Return the offset in bytes from the beginning
+   of the file of the file position of STREAM.  */
+long int
+DEFUN(ftell, (stream), FILE *stream)
+{
+  long int pos;
+
+  if (!__validfp (stream))
+    {
+      errno = EINVAL;
+      return -1L;
+    }
+
+  if (__stdio_check_offset (stream) == EOF)
+    return -1L;
+
+  /* Start with the file position associated with the beginning
+     of our buffer.  */
+  pos = stream->__target;
+
+  if (stream->__pushed_back)
+    /* ungetc was just called, so our real buffer pointer is squirreled
+       away in STREAM->__pushback_bufp, not in STREAM->__bufp as normal.
+       Calling ungetc is supposed to decrement the file position.  ANSI
+       says the file position is unspecified if you ungetc when the
+       position is zero; -1 seems as good as anything to me.  */
+    pos += stream->__pushback_bufp - stream->__buffer - 1;
+  else
+    pos += stream->__bufp - stream->__buffer;
+
+  return pos;
+}
diff --git a/stdio/fwrite.c b/stdio/fwrite.c
new file mode 100644
index 0000000000..4d012f1779
--- /dev/null
+++ b/stdio/fwrite.c
@@ -0,0 +1,208 @@
+/* Copyright (C) 1991, 1992, 1993, 1994 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+
+/* Write NMEMB chunks of SIZE bytes each from PTR onto STREAM.  */
+size_t
+DEFUN(fwrite, (ptr, size, nmemb, stream),
+      CONST PTR ptr AND size_t size AND
+      size_t nmemb AND register FILE *stream)
+{
+  register CONST unsigned char *p = (CONST unsigned char *) ptr;
+  register size_t to_write = size * nmemb;
+  register size_t written = 0;
+  int newlinep;
+  size_t buffer_space;
+  int default_func;
+
+  if (!__validfp (stream) || !stream->__mode.__write)
+    {
+      errno = EINVAL;
+      return 0;
+    }
+
+  if (ferror (stream))
+    return 0;
+  if (p == NULL || to_write == 0)
+    return 0;
+
+  if (!stream->__seen || stream->__put_limit == stream->__buffer)
+    {
+      /* This stream has never been seen before.
+	 Calling __flshfp will give it a buffer
+	 and I/O functions if it needs them.  */
+      if (__flshfp (stream, *p++) == EOF)
+	return 0;
+      if (--to_write == 0)
+	return 1;
+      else
+	++written;
+    }
+
+  default_func
+    = stream->__room_funcs.__output == __default_room_functions.__output;
+
+  {
+    int save = errno;
+
+    if (__stdio_check_offset (stream) == EOF && errno != ESPIPE)
+      {
+	stream->__error = 1;
+	goto done;
+      }
+
+    errno = save;
+  }
+
+  if (stream->__buffer == NULL && default_func &&
+      stream->__offset == stream->__target)
+  write_through:
+    /* This is an unbuffered stream using the standard output
+       buffer-flushing function, so we just do a straight write.  */
+    {
+      int count = (stream->__io_funcs.__write == NULL ? to_write :
+		   (*stream->__io_funcs.__write) (stream->__cookie,
+						  (CONST char *) p,
+						  to_write));
+      if (count > 0)
+	{
+	  written += count;
+	  if (stream->__offset != -1)
+	    {
+	      stream->__offset += count;
+	      stream->__target = stream->__offset;
+	    }
+	  to_write -= count;
+	  p += count;
+	}
+      else
+	stream->__error = 1;
+      goto done;
+    }
+
+  /* We ignore the end pointer here since we want to find out how much space
+     is really in the buffer, even for a line-buffered stream.  */
+  buffer_space = stream->__bufsize - (stream->__bufp - stream->__buffer);
+
+  newlinep = (stream->__linebuf &&
+	      memchr ((CONST PTR) p, '\n', to_write) != NULL);
+
+  if (newlinep && stream->__bufp == stream->__buffer &&
+      stream->__offset == stream->__target)
+    /* The buffer's empty, and we want to write our data
+       out soon anyway, so just write it straight out.  */
+    goto write_through;
+
+  if (stream->__bufsize == 0 && !default_func)
+    {
+      /* No buffer, and a special function.
+	 We can't do much better than putc.  */
+      while (to_write-- > 0)
+	{
+	  if (__flshfp (stream, *p++) == EOF)
+	    break;
+	  else
+	    ++written;
+	}
+    }
+  else if (!default_func || buffer_space >= to_write)
+  fill_buffer:
+    /* There is enough room in the buffer for everything we
+       want to write or the user has specified his own output
+       buffer-flushing/expanding function.  */
+    while (to_write > 0)
+      {
+	register size_t n = to_write;
+
+	if (n > buffer_space)
+	  n = buffer_space;
+
+	buffer_space -= n;
+
+	written += n;
+	to_write -= n;
+
+	if (n < 20)
+	  while (n-- > 0)
+	    *stream->__bufp++ = *p++;
+	else
+	  {
+	    memcpy ((PTR) stream->__bufp, (PTR) p, n);
+	    stream->__bufp += n;
+	    p += n;
+	  }
+
+	if (buffer_space == 0 || (to_write == 0 && newlinep))
+	  {
+	    /* We've filled the buffer, so flush it.  */
+	    if (fflush (stream) == EOF)
+	      break;
+
+	    /* Reset our record of the space available in the buffer,
+	       since we have just flushed it.  */
+	  check_space:
+	    buffer_space = (stream->__bufsize -
+			    (stream->__bufp - stream->__buffer));
+	    if (buffer_space == 0)
+	      {
+		/* With a custom output-room function, flushing might
+		   not create any buffer space.  Try writing a single
+		   character to create the space.  */
+		if (__flshfp (stream, *p++) == EOF)
+		  goto done;
+		++written;
+		--to_write;
+		goto check_space;
+	      }
+	  }
+      }
+  else
+    {
+      /* It won't all fit in the buffer.  */
+
+      if (stream->__bufp != stream->__buffer)
+	{
+	  /* There are characters in the buffer.  Flush them.  */
+	  if (__flshfp (stream, EOF) == EOF)
+	    goto done;
+	}
+
+      /* The buffer has been flushed.
+	 Now either fill it or write directly.  */
+
+      buffer_space = stream->__bufsize - (stream->__bufp - stream->__buffer);
+
+      if (stream->__offset == stream->__target &&
+	  (buffer_space < to_write || newlinep))
+	/* What we have to write is bigger than the buffer,
+	   or it contains a newline and we're line-buffered,
+	   so write it out.  */
+	goto write_through;
+      else
+	/* It will fit in the buffer.  */
+	goto fill_buffer;
+    }
+
+ done:;
+  return (size_t) written / size;
+}
diff --git a/stdio/gen-mpn-copy b/stdio/gen-mpn-copy
new file mode 100644
index 0000000000..b403f27a55
--- /dev/null
+++ b/stdio/gen-mpn-copy
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+translations='
+pentium i386/i586
+sparc8 sparc/sparc8
+sparc9 sparc/sparc9
+mc68000 m68k/m68000
+mc68020 m68k/m68020
+mc88100 m88k/m88100
+mc88110 m88k/m88110
+r3000 mips
+r4000 mips/mips64
+hppa1_0 hppa/hppa1.0
+hppa1_1 hppa/hppa1.1
+'
+
+set $translations
+while [ $# -ge 2 ]; do
+  gmp=$1 glibc=$2
+  shift; shift
+  echo 'mpn-found-1 := $(filter $(gmp-srcdir)/mpn/'$gmp'/%,$(mpn-found))
+mpn-copy-1 := $(patsubst $(gmp-srcdir)/mpn/'$gmp'/%,$(sysdep_dir)/'$glibc\
+'/%,$(mpn-found-1))
+mpn-found := $(filter-out $(mpn-found-1),$(mpn-found))
+mpn-copy-sysdep := $(mpn-copy-sysdep) $(mpn-copy-1)
+$(mpn-copy-1): $(sysdep_dir)/'$glibc'/%: \
+	       $(ignore gmp2glibc.sed) $(gmp-srcdir)/mpn/'$gmp'/%
+	$(gmp2glibc)'
+done
+
+exit 0
diff --git a/stdio/getc.c b/stdio/getc.c
new file mode 100644
index 0000000000..00aee33d31
--- /dev/null
+++ b/stdio/getc.c
@@ -0,0 +1,5 @@
+#include <ansidecl.h>
+#include <stdio.h>
+#undef	getc
+#define	fgetc	getc
+#include <fgetc.c>
diff --git a/stdio/getchar.c b/stdio/getchar.c
new file mode 100644
index 0000000000..427de7738f
--- /dev/null
+++ b/stdio/getchar.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdio.h>
+
+#undef getchar
+
+
+/* Read a character from stdin.  */
+int
+DEFUN_VOID(getchar)
+{
+  return __getc(stdin);
+}
diff --git a/stdio/getdelim.c b/stdio/getdelim.c
new file mode 100644
index 0000000000..8047c1fe0c
--- /dev/null
+++ b/stdio/getdelim.c
@@ -0,0 +1,173 @@
+/* Copyright (C) 1991, 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+/* Read up to (and including) a TERMINATOR from STREAM into *LINEPTR
+   (and null-terminate it). *LINEPTR is a pointer returned from malloc (or
+   NULL), pointing to *N characters of space.  It is realloc'd as
+   necessary.  Returns the number of characters read (not including the
+   null terminator), or -1 on error or EOF.  */
+
+ssize_t
+DEFUN(__getdelim, (lineptr, n, terminator, stream),
+      char **lineptr AND size_t *n AND int terminator AND FILE *stream)
+{
+  char *line, *p;
+  size_t size, copy;
+
+  if (!__validfp (stream) || lineptr == NULL || n == NULL)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  if (ferror (stream))
+    return -1;
+
+  /* Make sure we have a line buffer to start with.  */
+  if (*lineptr == NULL || *n < 2) /* !seen and no buf yet need 2 chars.  */
+    {
+#ifndef	MAX_CANON
+#define	MAX_CANON	256
+#endif
+      line = realloc (*lineptr, MAX_CANON);
+      if (line == NULL)
+	return -1;
+      *lineptr = line;
+      *n = MAX_CANON;
+    }
+
+  line = *lineptr;
+  size = *n;
+
+  copy = size;
+  p = line;
+
+  if (stream->__buffer == NULL && stream->__userbuf)
+    {
+      /* Unbuffered stream.  Not much optimization to do.  */
+
+      while (1)
+	{
+	  size_t len;
+
+	  while (--copy > 0)
+	    {
+	      register int c = getc (stream);
+	      if (c == EOF)
+		goto lose;
+	      else if ((*p++ = c) == terminator)
+		goto win;
+	    }
+
+	  /* Need to enlarge the line buffer.  */
+	  len = p - line;
+	  size *= 2;
+	  line = realloc (line, size);
+	  if (line == NULL)
+	    goto lose;
+	  *lineptr = line;
+	  *n = size;
+	  p = line + len;
+	  copy = size - len;
+	}
+    }
+  else
+    {
+      /* Leave space for the terminating null.  */
+      --copy;
+
+      if (!stream->__seen || stream->__buffer == NULL || stream->__pushed_back)
+	{
+	  /* Do one with getc to allocate a buffer.  */
+	  int c = getc (stream);
+	  if (c == EOF)
+	    goto lose;
+	  *p++ = c;
+	  if (c == terminator)
+	    goto win;
+	  --copy;
+	}
+
+      while (1)
+	{
+	  size_t i;
+	  char *found;
+
+	  i = stream->__get_limit - stream->__bufp;	
+	  if (i == 0)
+	    {
+	      /* Refill the buffer.  */
+	      int c = __fillbf (stream);
+	      if (c == EOF)
+		goto lose;
+	      *p++ = c;
+	      if (c == terminator)
+		goto win;
+	      --copy;
+	      i = stream->__get_limit - stream->__bufp;	
+	    }
+
+	  if (i > copy)
+	    i = copy;
+
+	  found = (char *) __memccpy ((PTR) p, stream->__bufp, terminator, i);
+	  if (found != NULL)
+	    {
+	      stream->__bufp += found - p;
+	      p = found;
+	      goto win;
+	    }
+
+	  stream->__bufp += i;
+	  p += i;
+	  copy -= i;
+	  if (copy == 0)
+	    {
+	      /* Need to enlarge the line buffer.  */
+	      size_t len = p - line;
+	      size *= 2;
+	      line = realloc (line, size);
+	      if (line == NULL)
+		goto lose;
+	      *lineptr = line;
+	      *n = size;
+	      p = line + len;
+	      copy = size - len;
+	      /* Leave space for the terminating null.  */
+	      --copy;
+	    }
+	}
+    }
+
+ lose:
+  if (p == *lineptr)
+    return -1;
+  /* Return a partial line since we got an error in the middle.  */
+ win:
+  *p = '\0';
+  return p - *lineptr;
+}
+
+weak_alias (__getdelim, getdelim)
diff --git a/stdio/getline.c b/stdio/getline.c
new file mode 100644
index 0000000000..1a2f975c75
--- /dev/null
+++ b/stdio/getline.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 1991, 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#undef __getline
+
+/* Like getdelim, but always looks for a newline.  */
+ssize_t
+DEFUN(__getline, (lineptr, n, stream),
+      char **lineptr AND size_t *n AND FILE *stream)
+{
+  return __getdelim (lineptr, n, '\n', stream);
+}
+
+weak_alias (__getline, getline)
diff --git a/stdio/gets.c b/stdio/gets.c
new file mode 100644
index 0000000000..2267792fb0
--- /dev/null
+++ b/stdio/gets.c
@@ -0,0 +1,59 @@
+/* Copyright (C) 1991, 1994, 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+link_warning ("the `gets' function is unreliable and should not be used.")
+
+/* Read a newline-terminated string from stdin into S,
+   removing the trailing newline.  Return S or NULL.  */
+char *
+DEFUN(gets, (s), char *s)
+{
+  register char *p = s;
+  register int c;
+  FILE *stream = stdin;
+
+  if (!__validfp(stream) || p == NULL)
+    {
+      errno = EINVAL;
+      return NULL;
+    }
+
+  if (feof(stream) || ferror(stream))
+    return NULL;
+
+  while ((c = getchar()) != EOF)
+    if (c == '\n')
+      break;
+    else
+      *p++ = c;
+
+  *p = '\0';
+
+  /* Return null if we had an error, or if we got EOF
+     before writing any characters.  */
+
+  if (ferror (stream) || (feof (stream) && p == s))
+    return NULL;
+
+  return s;
+}
diff --git a/stdio/getw.c b/stdio/getw.c
new file mode 100644
index 0000000000..45d4d8875d
--- /dev/null
+++ b/stdio/getw.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdio.h>
+
+
+/* Read a word (int) from STREAM.  */
+int
+DEFUN(getw, (stream), FILE *stream)
+{
+	int w;
+
+	/* Is there a better way?  */
+	if (fread((PTR) &w, sizeof(w), 1, stream) != 1)
+	  return(EOF);
+	return(w);
+}
diff --git a/stdio/glue.c b/stdio/glue.c
new file mode 100644
index 0000000000..6ef52a7ada
--- /dev/null
+++ b/stdio/glue.c
@@ -0,0 +1,114 @@
+/* Copyright (C) 1991, 1992 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+/* This file provides glue between Unix stdio and GNU stdio.
+   It supports use of Unix stdio `getc' and `putc' (and, by extension,
+   `getchar' and `putchar') macros on GNU stdio streams (they are slow, but
+   they work).  It also supports all stdio operations (including Unix
+   `getc' and `putc') on Unix's stdin, stdout, and stderr (the elements of
+   `_iob').
+
+   The reasoning behind this is to allow programs (and especially
+   libraries) compiled with Unix header files to work with the GNU C
+   library.  */
+
+#include <ansidecl.h>
+#include <stdio.h>
+#include <errno.h>
+
+typedef union
+  {
+    struct
+      {
+	int magic;
+	FILE **streamp;		/* Overlaps GNU stdio `bufp' member.  */
+	/* These two overlap the GNU stdio `get_limit' and `put_limit'
+	   members.  They must be <= `streamp'/`bufp' for GNU getc and putc
+	   to do the right thing.  */
+	FILE **streamp2, **streamp3;
+      } glue;
+    struct _iobuf
+      {
+	int _cnt;
+	unsigned char *_ptr;
+	unsigned char *_base;
+	int _bufsiz;
+	short int _flag;
+	char _file;
+      } unix_iobuf;
+    FILE gnu_stream;
+  } unix_FILE;
+
+/* These are the Unix stdio's stdin, stdout, and stderr.
+   In Unix stdin is (&_iob[0]), stdout is (&_iob[1]), and stderr is
+   (&_iob[2]).  The magic number marks these as glued streams.  The
+   __validfp macro in stdio.h is used by every stdio function.  It checks
+   for glued streams, and replaces them with the GNU stdio stream.  */
+unix_FILE _iob[] =
+  {
+#define	S(name)	{ { _GLUEMAGIC, &name, &name, &name } }
+    S (stdin),
+    S (stdout),
+    S (stderr),
+#undef	S
+  };
+
+/* Called by the Unix stdio `getc' macro.
+   The macro is assumed to look something like:
+       (--file->_cnt < 0 ? _filbuf (file) ...)
+   In a Unix stdio FILE `_cnt' is the first element.
+   In a GNU stdio or glued FILE, the first element is the magic number.  */
+int
+DEFUN(_filbuf, (file), unix_FILE *file)
+{
+  switch (++file->glue.magic)	/* Compensate for Unix getc's decrement.  */
+    {
+    case _GLUEMAGIC:
+      /* This is a glued stream.  */
+      return getc (*file->glue.streamp);
+
+    case  _IOMAGIC:
+      /* This is a normal GNU stdio stream.  */
+      return getc ((FILE *) file);
+
+    default:
+      /* Bogus stream.  */
+      errno = EINVAL;
+      return EOF;
+    }
+}
+
+/* Called by the Unix stdio `putc' macro.  Much like getc, above.  */
+int
+DEFUN(_flsbuf, (c, file),
+      int c AND unix_FILE *file)
+{
+  /* Compensate for putc's decrement.  */
+  switch (++file->glue.magic)
+    {
+    case _GLUEMAGIC:
+      return putc (c, *file->glue.streamp);
+
+    case  _IOMAGIC:
+      return putc (c, (FILE *) file);
+
+    default:
+      errno = EINVAL;
+      return EOF;
+    }
+}
diff --git a/stdio/gmp-impl.h b/stdio/gmp-impl.h
new file mode 100644
index 0000000000..ccffe7bb1e
--- /dev/null
+++ b/stdio/gmp-impl.h
@@ -0,0 +1,283 @@
+/* Include file for internal GNU MP types and definitions.
+
+Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
+the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if ! defined (alloca)
+#if defined (__GNUC__) || defined (__sparc__) || defined (sparc)
+#define alloca __builtin_alloca
+#endif
+#endif
+
+#ifndef NULL
+#define NULL 0L
+#endif
+
+#if ! defined (__GNUC__)
+#define inline			/* Empty */
+void *alloca();
+#endif
+
+#define ABS(x) (x >= 0 ? x : -x)
+#define MIN(l,o) ((l) < (o) ? (l) : (o))
+#define MAX(h,i) ((h) > (i) ? (h) : (i))
+
+#include "gmp-mparam.h"
+/* #include "longlong.h" */
+
+#ifdef __STDC__
+void *malloc (size_t);
+void *realloc (void *, size_t);
+void free (void *);
+
+extern void *	(*_mp_allocate_func) (size_t);
+extern void *	(*_mp_reallocate_func) (void *, size_t, size_t);
+extern void	(*_mp_free_func) (void *, size_t);
+
+void *_mp_default_allocate (size_t);
+void *_mp_default_reallocate (void *, size_t, size_t);
+void _mp_default_free (void *, size_t);
+
+#else
+
+#define const			/* Empty */
+#define signed			/* Empty */
+
+void *malloc ();
+void *realloc ();
+void free ();
+
+extern void *	(*_mp_allocate_func) ();
+extern void *	(*_mp_reallocate_func) ();
+extern void	(*_mp_free_func) ();
+
+void *_mp_default_allocate ();
+void *_mp_default_reallocate ();
+void _mp_default_free ();
+#endif
+
+/* Copy NLIMBS *limbs* from SRC to DST.  */
+#define MPN_COPY_INCR(DST, SRC, NLIMBS) \
+  do {									\
+    mp_size_t __i;							\
+    for (__i = 0; __i < (NLIMBS); __i++)				\
+      (DST)[__i] = (SRC)[__i];						\
+  } while (0)
+#define MPN_COPY_DECR(DST, SRC, NLIMBS) \
+  do {									\
+    mp_size_t __i;							\
+    for (__i = (NLIMBS) - 1; __i >= 0; __i--)				\
+      (DST)[__i] = (SRC)[__i];						\
+  } while (0)
+#define MPN_COPY MPN_COPY_INCR
+
+/* Zero NLIMBS *limbs* AT DST.  */
+#define MPN_ZERO(DST, NLIMBS) \
+  do {									\
+    mp_size_t __i;							\
+    for (__i = 0; __i < (NLIMBS); __i++)				\
+      (DST)[__i] = 0;							\
+  } while (0)
+
+#define MPN_NORMALIZE(DST, NLIMBS) \
+  do {									\
+    while (NLIMBS > 0)							\
+      {									\
+	if ((DST)[(NLIMBS) - 1] != 0)					\
+	  break;							\
+	NLIMBS--;							\
+      }									\
+  } while (0)
+#define MPN_NORMALIZE_NOT_ZERO(DST, NLIMBS) \
+  do {									\
+    while (1)								\
+      {									\
+	if ((DST)[(NLIMBS) - 1] != 0)					\
+	  break;							\
+	NLIMBS--;							\
+      }									\
+  } while (0)
+
+/*  Swap (mp_ptr, mp_size_t) (U, UL) with (V, VL)  */
+#define MPN_SWAP(u, l, v, m) \
+  do {									\
+    { mp_ptr _; _ = (u), (u) = (v), (v) = _;}				\
+    { mp_size_t _; _ = (l), (l) = (m), (m) = _;}			\
+  } while (0)
+
+/*  Return true iff the limb X has less bits than the limb Y.  */
+#define MPN_LESS_BITS_LIMB(x,y) ((x) < (y) && (x) < ((x) ^ (y)))
+
+/*  Return true iff (mp_ptr, mp_size_t) (U, UL) has less bits than (V, VL).  */
+#define MPN_LESS_BITS(u, l, v, m) \
+  ((l) < (m)								\
+   || ((l) == (m) && (l) != 0 && MPN_LESS_BITS_LIMB ((u)[(l - 1)], (v)[(l) - 1])))
+
+/*  Return true iff (mp_ptr, mp_size_t) (U, UL) has more bits than (V, VL).  */
+#define MPN_MORE_BITS(u, l, v, m) MPN_LESS_BITS (v, m, u, l)
+
+/*  Perform twos complement on (mp_ptr, mp_size_t) (U, UL), 
+    putting result at (v, VL).  Precondition: U[0] != 0.  */
+#define MPN_COMPL_INCR(u, v, l)	\
+  do {									\
+    mp_size_t _ = 0;							\
+    (u)[0] = -(v)[_];							\
+    while (_++ < (l)) 							\
+      (u)[_] = ~(v)[_];							\
+  } while (0)
+#define MPN_COMPL MPN_COMPL_INCR
+
+/* Initialize the MP_INT X with space for NLIMBS limbs.
+   X should be a temporary variable, and it will be automatically
+   cleared out when the running function returns.
+   We use __x here to make it possible to accept both mpz_ptr and mpz_t
+   arguments.  */
+#define MPZ_TMP_INIT(X, NLIMBS) \
+  do {									\
+    mpz_ptr __x = (X);							\
+    __x->alloc = (NLIMBS);						\
+    __x->d = (mp_ptr) alloca ((NLIMBS) * BYTES_PER_MP_LIMB);		\
+  } while (0)
+
+#define MPN_MUL_N_RECURSE(prodp, up, vp, size, tspace) \
+  do {									\
+    if ((size) < KARATSUBA_THRESHOLD)					\
+      ____mpn_mul_n_basecase (prodp, up, vp, size);			\
+    else								\
+      ____mpn_mul_n (prodp, up, vp, size, tspace);			\
+  } while (0);
+#define MPN_SQR_N_RECURSE(prodp, up, size, tspace) \
+  do {									\
+    if ((size) < KARATSUBA_THRESHOLD)					\
+      ____mpn_sqr_n_basecase (prodp, up, size);				\
+    else								\
+      ____mpn_sqr_n (prodp, up, size, tspace);				\
+  } while (0);
+
+/* Structure for conversion between internal binary format and
+   strings in base 2..36.  */
+struct bases
+{
+  /* Number of digits in the conversion base that always fits in
+     an mp_limb.  For example, for base 10 this is 10, since
+     2**32 = 4294967296 has ten digits.  */
+  int chars_per_limb;
+
+  /* log(2)/log(conversion_base) */
+  float chars_per_bit_exactly;
+
+  /* big_base is conversion_base**chars_per_limb, i.e. the biggest
+     number that fits a word, built by factors of conversion_base.
+     Exception: For 2, 4, 8, etc, big_base is log2(base), i.e. the
+     number of bits used to represent each digit in the base.  */
+  mp_limb big_base;
+
+  /* big_base_inverted is a BITS_PER_MP_LIMB bit approximation to
+     1/big_base, represented as a fixed-point number.  Instead of
+     dividing by big_base an application can choose to multiply
+     by big_base_inverted.  */
+  mp_limb big_base_inverted;
+};
+
+extern const struct bases __mp_bases[];
+extern mp_size_t __gmp_default_fp_limb_precision;
+
+/* Divide the two-limb number in (NH,,NL) by D, with DI being a 32 bit
+   approximation to (2**(2*BITS_PER_MP_LIMB))/D - (2**BITS_PER_MP_LIMB).
+   Put the quotient in Q and the remainder in R.  */
+#define udiv_qrnnd_preinv(q, r, nh, nl, d, di) \
+  do {									\
+    mp_limb _q, _ql, _r;						\
+    mp_limb _xh, _xl;							\
+    umul_ppmm (_q, _ql, (nh), (di));					\
+    _q += (nh);			/* DI is 2**BITS_PER_MP_LIMB too small */\
+    umul_ppmm (_xh, _xl, _q, (d));					\
+    sub_ddmmss (_xh, _r, (nh), (nl), _xh, _xl);				\
+    if (_xh != 0)							\
+      {									\
+	sub_ddmmss (_xh, _r, _xh, _r, 0, (d));				\
+	_q += 1;							\
+	if (_xh != 0)							\
+	  {								\
+	    sub_ddmmss (_xh, _r, _xh, _r, 0, (d));			\
+	    _q += 1;							\
+	  }								\
+      }									\
+    if (_r >= (d))							\
+      {									\
+	_r -= (d);							\
+	_q += 1;							\
+      }									\
+    (r) = _r;								\
+    (q) = _q;								\
+  } while (0)
+#define udiv_qrnnd_preinv2gen(q, r, nh, nl, d, di, dnorm, lgup) \
+  do {									\
+    mp_limb n2, n10, n1, nadj, q1;					\
+    mp_limb _xh, _xl;							\
+    n2 = ((nh) << (BITS_PER_MP_LIMB - (lgup))) + ((nl) >> 1 >> (l - 1));\
+    n10 = (nl) << (BITS_PER_MP_LIMB - (lgup));				\
+    n1 = ((mp_limb_signed) n10 >> (BITS_PER_MP_LIMB - 1));		\
+    nadj = n10 + (n1 & (dnorm));					\
+    umul_ppmm (_xh, _xl, di, n2 - n1);					\
+    add_ssaaaa (_xh, _xl, _xh, _xl, 0, nadj);				\
+    q1 = ~(n2 + _xh);							\
+    umul_ppmm (_xh, _xl, q1, d);					\
+    add_ssaaaa (_xh, _xl, _xh, _xl, nh, nl);				\
+    _xh -= (d);								\
+    (r) = _xl + ((d) & _xh);						\
+    (q) = _xh - q1;							\
+  } while (0)
+#define udiv_qrnnd_preinv2norm(q, r, nh, nl, d, di) \
+  do {									\
+    mp_limb n2, n10, n1, nadj, q1;					\
+    mp_limb _xh, _xl;							\
+    n2 = (nh);								\
+    n10 = (nl);								\
+    n1 = ((mp_limb_signed) n10 >> (BITS_PER_MP_LIMB - 1));		\
+    nadj = n10 + (n1 & (d));						\
+    umul_ppmm (_xh, _xl, di, n2 - n1);					\
+    add_ssaaaa (_xh, _xl, _xh, _xl, 0, nadj);				\
+    q1 = ~(n2 + _xh);							\
+    umul_ppmm (_xh, _xl, q1, d);					\
+    add_ssaaaa (_xh, _xl, _xh, _xl, nh, nl);				\
+    _xh -= (d);								\
+    (r) = _xl + ((d) & _xh);						\
+    (q) = _xh - q1;							\
+  } while (0)
+
+#if defined (__GNUC__)
+/* Define stuff for longlong.h asm macros.  */
+#if __GNUC_NEW_ATTR_MODE_SYNTAX
+typedef unsigned int UQItype	__attribute__ ((mode ("QI")));
+typedef 	 int SItype	__attribute__ ((mode ("SI")));
+typedef unsigned int USItype	__attribute__ ((mode ("SI")));
+typedef		 int DItype	__attribute__ ((mode ("DI")));
+typedef unsigned int UDItype	__attribute__ ((mode ("DI")));
+#else
+typedef unsigned int UQItype	__attribute__ ((mode (QI)));
+typedef 	 int SItype	__attribute__ ((mode (SI)));
+typedef unsigned int USItype	__attribute__ ((mode (SI)));
+typedef		 int DItype	__attribute__ ((mode (DI)));
+typedef unsigned int UDItype	__attribute__ ((mode (DI)));
+#endif
+#endif
+
+typedef mp_limb UWtype;
+typedef unsigned int UHWtype;
+#define W_TYPE_SIZE BITS_PER_MP_LIMB
diff --git a/stdio/gmp.h b/stdio/gmp.h
new file mode 100644
index 0000000000..95c2f1beba
--- /dev/null
+++ b/stdio/gmp.h
@@ -0,0 +1,525 @@
+/* gmp.h -- Definitions for GNU multiple precision functions.
+
+Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
+the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef __GMP_H__
+
+#ifndef __GNU_MP__
+#define __need_size_t
+#include <stddef.h>
+
+#ifdef __STDC__
+#define __gmp_const const
+#else
+#define __gmp_const
+#endif
+
+#ifdef __GNUC__
+#define __gmp_inline inline
+#else
+#define __gmp_inline
+#endif
+
+#ifdef _SHORT_LIMB
+typedef unsigned int		mp_limb;
+typedef int			mp_limb_signed;
+#else
+typedef unsigned long int	mp_limb;
+typedef long int		mp_limb_signed;
+#endif
+
+typedef mp_limb *		mp_ptr;
+typedef __gmp_const mp_limb *	mp_srcptr;
+typedef int			mp_size_t;
+typedef long int		mp_exp_t;
+
+#ifndef __MP_SMALL__
+typedef struct
+{
+  long int alloc;		/* Number of *limbs* allocated and pointed
+				   to by the D field.  */
+  long int size;		/* abs(SIZE) is the number of limbs
+				   the last field points to.  If SIZE
+				   is negative this is a negative
+				   number.  */
+  mp_limb *d;			/* Pointer to the limbs.  */
+} __mpz_struct;
+#else
+typedef struct
+{
+  short int alloc;		/* Number of *limbs* allocated and pointed
+				   to by the D field.  */
+  short int size;		/* abs(SIZE) is the number of limbs
+				   the last field points to.  If SIZE
+				   is negative this is a negative
+				   number.  */
+  mp_limb *d;			/* Pointer to the limbs.  */
+} __mpz_struct;
+#endif
+#endif /* __GNU_MP__ */
+
+/* User-visible types.  */
+typedef __mpz_struct MP_INT;
+typedef __mpz_struct mpz_t[1];
+
+/* Structure for rational numbers.  Zero is represented as 0/any, i.e.
+   the denominator is ignored.  Negative numbers have the sign in
+   the numerator.  */
+typedef struct
+{
+  __mpz_struct num;
+  __mpz_struct den;
+#if 0
+  long int num_alloc;		/* Number of limbs allocated
+				   for the numerator.  */
+  long int num_size;		/* The absolute value of this field is the
+				   length of the numerator; the sign is the
+				   sign of the entire rational number.  */
+  mp_ptr num;			/* Pointer to the numerator limbs.  */
+  long int den_alloc;		/* Number of limbs allocated
+				   for the denominator.  */
+  long int den_size;		/* Length of the denominator.  (This field
+				   should always be positive.) */
+  mp_ptr den;			/* Pointer to the denominator limbs.  */
+#endif
+} __mpq_struct;
+
+typedef __mpq_struct MP_RAT;
+typedef __mpq_struct mpq_t[1];
+
+typedef struct
+{
+  mp_size_t alloc;		/* Number of *limbs* allocated and pointed
+				   to by the D field.  */
+  mp_size_t prec;		/* Max precision, in number of `mp_limb's.
+				   Set by mpf_init and modified by
+				   mpf_set_prec.  */
+  mp_size_t size;		/* abs(SIZE) is the number of limbs
+				   the last field points to.  If SIZE
+				   is negative this is a negative
+				   number.  */
+  mp_exp_t exp;			/* Exponent, in the base of `mp_limb'.  */
+  mp_limb *d;			/* Pointer to the limbs.  */
+} __mpf_struct;
+
+/* typedef __mpf_struct MP_FLOAT; */
+typedef __mpf_struct mpf_t[1];
+
+/* Types for function declarations in gmp files.  */
+/* ??? Should not pollute user name space ??? */
+typedef __gmp_const __mpz_struct *mpz_srcptr;
+typedef __mpz_struct *mpz_ptr;
+typedef __gmp_const __mpf_struct *mpf_srcptr;
+typedef __mpf_struct *mpf_ptr;
+typedef __gmp_const __mpq_struct *mpq_srcptr;
+typedef __mpq_struct *mpq_ptr;
+
+#ifdef __STDC__
+#define _PROTO(x) x
+#else
+#define _PROTO(x) ()
+#endif
+
+void mp_set_memory_functions _PROTO((void *(*) (size_t),
+				     void *(*) (void *, size_t, size_t),
+				     void (*) (void *, size_t)));
+
+/**************** Integer (i.e. Z) routines.  ****************/
+
+void *_mpz_realloc _PROTO ((mpz_ptr, mp_size_t));
+
+void mpz_abs _PROTO ((mpz_ptr, mpz_srcptr));
+void mpz_add _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
+void mpz_add_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_and _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
+void mpz_clear _PROTO ((mpz_ptr));
+void mpz_clrbit _PROTO ((mpz_ptr, unsigned long int));
+int mpz_cmp _PROTO ((mpz_srcptr, mpz_srcptr));
+int mpz_cmp_si _PROTO ((mpz_srcptr, signed long int));
+int mpz_cmp_ui _PROTO ((mpz_srcptr, unsigned long int));
+void mpz_com _PROTO ((mpz_ptr, mpz_srcptr));
+void mpz_div_2exp _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_fac_ui _PROTO ((mpz_ptr, unsigned long int));
+void mpz_gcd _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
+unsigned long int mpz_gcd_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_gcdext _PROTO ((mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr));
+/* signed */ long int mpz_get_si _PROTO ((mpz_srcptr));
+char *mpz_get_str _PROTO ((char *, int, mpz_srcptr));
+unsigned long int mpz_get_ui _PROTO ((mpz_srcptr));
+mp_limb mpz_getlimbn _PROTO ((mpz_srcptr, mp_size_t));
+mp_size_t mpz_hamdist _PROTO ((mpz_srcptr, mpz_srcptr));
+void mpz_init _PROTO ((mpz_ptr));
+#ifdef FILE
+void mpz_inp_raw _PROTO ((mpz_ptr, FILE *));
+int mpz_inp_str _PROTO ((mpz_ptr, FILE *, int));
+#endif
+void mpz_ior _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
+void mpz_init_set _PROTO ((mpz_ptr, mpz_srcptr));
+void mpz_init_set_si _PROTO ((mpz_ptr, signed long int));
+int mpz_init_set_str _PROTO ((mpz_ptr, const char *, int));
+void mpz_init_set_ui _PROTO ((mpz_ptr, unsigned long int));
+void mpz_lcm _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
+void mpz_mod_2exp _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_mul _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
+void mpz_mul_2exp _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_mul_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_neg _PROTO ((mpz_ptr, mpz_srcptr));
+#ifdef FILE
+void mpz_out_raw _PROTO ((FILE *, mpz_srcptr));
+void mpz_out_str _PROTO ((FILE *, int, mpz_srcptr));
+#endif
+int mpz_perfect_square_p _PROTO ((mpz_srcptr));
+mp_size_t mpz_popcount _PROTO ((mpz_srcptr));
+void mpz_pow_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_powm _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr));
+void mpz_powm_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int, mpz_srcptr));
+int mpz_probab_prime_p _PROTO ((mpz_srcptr, int));
+void mpz_random _PROTO ((mpz_ptr, mp_size_t));
+void mpz_random2 _PROTO ((mpz_ptr, mp_size_t));
+void mpz_set _PROTO ((mpz_ptr, mpz_srcptr));
+void mpz_set_si _PROTO ((mpz_ptr, signed long int));
+int mpz_set_str _PROTO ((mpz_ptr, const char *, int));
+void mpz_set_ui _PROTO ((mpz_ptr, unsigned long int));
+size_t mpz_size _PROTO ((mpz_srcptr));
+size_t mpz_sizeinbase _PROTO ((mpz_srcptr, int));
+void mpz_sqrt _PROTO ((mpz_ptr, mpz_srcptr));
+void mpz_sqrtrem _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr));
+void mpz_sub _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
+void mpz_sub_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_ui_pow_ui _PROTO ((mpz_ptr, unsigned long int, unsigned long int));
+
+void mpz_fdiv_q _PROTO((mpz_ptr, mpz_srcptr, mpz_srcptr));
+unsigned long int mpz_fdiv_q_ui _PROTO((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_fdiv_qr _PROTO((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr));
+unsigned long int mpz_fdiv_qr_ui _PROTO((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_fdiv_r _PROTO((mpz_ptr, mpz_srcptr, mpz_srcptr));
+unsigned long int mpz_fdiv_r_ui _PROTO((mpz_ptr, mpz_srcptr, unsigned long int));
+unsigned long int mpz_fdiv_ui _PROTO((mpz_srcptr, unsigned long int));
+void mpz_tdiv_q _PROTO((mpz_ptr, mpz_srcptr, mpz_srcptr));
+void mpz_tdiv_q_ui _PROTO((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_tdiv_qr _PROTO((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr));
+void mpz_tdiv_qr_ui _PROTO((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_tdiv_r _PROTO((mpz_ptr, mpz_srcptr, mpz_srcptr));
+void mpz_tdiv_r_ui _PROTO((mpz_ptr, mpz_srcptr, unsigned long int));
+
+/**************** Rational (i.e. Q) routines.  ****************/
+
+void mpq_init _PROTO ((mpq_ptr));
+void mpq_clear _PROTO ((mpq_ptr));
+void mpq_set _PROTO ((mpq_ptr, mpq_srcptr));
+void mpq_set_ui _PROTO ((mpq_ptr, unsigned long int, unsigned long int));
+void mpq_set_si _PROTO ((mpq_ptr, signed long int, unsigned long int));
+void mpq_add _PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr));
+void mpq_sub _PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr));
+void mpq_mul _PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr));
+void mpq_div _PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr));
+void mpq_neg _PROTO ((mpq_ptr, mpq_srcptr));
+int mpq_cmp _PROTO ((mpq_srcptr, mpq_srcptr));
+void mpq_inv _PROTO ((mpq_ptr, mpq_srcptr));
+void mpq_set_num _PROTO ((mpq_ptr, mpz_srcptr));
+void mpq_set_den _PROTO ((mpq_ptr, mpz_srcptr));
+void mpq_get_num _PROTO ((mpz_ptr, mpq_srcptr));
+void mpq_get_den _PROTO ((mpz_ptr, mpq_srcptr));
+
+/**************** Float (i.e. F) routines.  ****************/
+
+void mpf_abs _PROTO ((mpf_ptr, mpf_srcptr));
+void mpf_add _PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr));
+void mpf_add_ui _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int));
+void mpf_clear _PROTO ((mpf_ptr));
+int mpf_cmp _PROTO ((mpf_srcptr, mpf_srcptr));
+int mpf_cmp_si _PROTO ((mpf_srcptr, long int));
+int mpf_cmp_ui _PROTO ((mpf_srcptr, unsigned long int));
+void mpf_div _PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr));
+void mpf_div_2exp _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int));
+void mpf_div_ui _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int));
+void mpf_dump _PROTO ((mpf_srcptr));
+char *mpf_get_str _PROTO ((char *, mp_exp_t *, int, size_t, mpf_srcptr));
+void mpf_init _PROTO ((mpf_ptr));
+void mpf_init2 _PROTO ((mpf_ptr, mp_size_t));
+#ifdef FILE
+void mpf_inp_str _PROTO ((mpf_ptr, FILE *, int));
+#endif
+void mpf_init_set _PROTO ((mpf_ptr, mpf_srcptr));
+void mpf_init_set_d _PROTO ((mpf_ptr, double));
+void mpf_init_set_si _PROTO ((mpf_ptr, long int));
+int mpf_init_set_str _PROTO ((mpf_ptr, char *, int));
+void mpf_init_set_ui _PROTO ((mpf_ptr, unsigned long int));
+void mpf_mul _PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr));
+void mpf_mul_2exp _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int));
+void mpf_mul_ui _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int));
+void mpf_neg _PROTO ((mpf_ptr, mpf_srcptr));
+#ifdef FILE
+void mpf_out_str _PROTO ((mpf_ptr, int, size_t, FILE *));
+#endif
+void mpf_set _PROTO ((mpf_ptr, mpf_srcptr));
+void mpf_set_d _PROTO ((mpf_ptr, double));
+mp_size_t mpf_set_default_prec _PROTO ((mp_size_t));
+void mpf_set_si _PROTO ((mpf_ptr, long int));
+int mpf_set_str _PROTO ((mpf_ptr, const char *, int));
+void mpf_set_ui _PROTO ((mpf_ptr, unsigned long int));
+size_t mpf_size _PROTO ((mpf_srcptr));
+void mpf_sqrt _PROTO ((mpf_ptr, mpf_srcptr));
+void mpf_sqrt_ui _PROTO ((mpf_ptr, unsigned long int));
+void mpf_sub _PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr));
+void mpf_sub_ui _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int));
+void mpf_ui_div _PROTO ((mpf_ptr, unsigned long int, mpf_srcptr));
+
+/************ Low level positive-integer (i.e. N) routines.  ************/
+
+/* This is ugly, but we need to make usr calls reach the prefixed function.  */
+#define mpn_add_n	__mpn_add_n
+#define mpn_sub_n	__mpn_sub_n
+#define mpn_mul_1	__mpn_mul_1
+#define mpn_addmul_1	__mpn_addmul_1
+#define mpn_submul_1	__mpn_submul_1
+#define mpn_lshift	__mpn_lshift
+#define mpn_rshift	__mpn_rshift
+#define mpn_sub		__mpn_sub
+#define mpn_add		__mpn_add
+#define mpn_normal_size	__mpn_normal_size
+#define mpn_cmp		__mpn_cmp
+#define mpn_add_1	__mpn_add_1
+#define mpn_sub_1	__mpn_sub_1
+#define mpn_mul_n	__mpn_mul_n
+#define mpn_mul		__mpn_mul
+#define mpn_divmod	__mpn_divmod
+#define mpn_divmod_1	__mpn_divmod_1
+#define mpn_mod_1	__mpn_mod_1
+#define mpn_sqrt	__mpn_sqrt
+#define mpn_next_bit_set __mpn_next_bit_set
+#define mpn_popcount	__mpn_popcount
+#define mpn_hamdist	__mpn_hamdist
+#define mpn_random2	__mpn_random2
+#define mpn_set_str	__mpn_set_str
+#define mpn_get_str	__mpn_get_str
+#define mpn_gcd_1	__mpn_gcd_1
+
+mp_limb __mpn_add_n _PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t));
+mp_limb __mpn_sub_n _PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t));
+mp_limb __mpn_mul _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t));
+void __mpn_mul_n _PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t));
+mp_limb __mpn_mul_1 _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb));
+mp_limb __mpn_addmul_1 _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb));
+mp_limb __mpn_submul_1 _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb));
+mp_limb __mpn_divmod _PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t));
+mp_limb __mpn_divmod_1 _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb));
+mp_limb __mpn_mod_1 _PROTO ((mp_srcptr, mp_size_t, mp_limb));
+mp_limb __mpn_lshift _PROTO ((mp_ptr, mp_srcptr, mp_size_t, unsigned int));
+mp_limb __mpn_rshift _PROTO ((mp_ptr, mp_srcptr, mp_size_t, unsigned int));
+mp_size_t __mpn_sqrt _PROTO ((mp_ptr, mp_ptr, mp_srcptr, mp_size_t));
+int __mpn_cmp _PROTO ((mp_srcptr, mp_srcptr, mp_size_t));
+mp_size_t __mpn_next_bit_set _PROTO ((mp_srcptr, mp_size_t));
+mp_size_t __mpn_popcount _PROTO ((mp_srcptr, mp_size_t));
+mp_size_t __mpn_hamdist _PROTO ((mp_srcptr, mp_srcptr, mp_size_t));
+void __mpn_random2 _PROTO ((mp_ptr, mp_size_t));
+mp_size_t __mpn_set_str _PROTO ((mp_ptr, const unsigned char *, size_t, int));
+size_t __mpn_get_str _PROTO ((unsigned char *, int, mp_ptr, mp_size_t));
+mp_limb __mpn_gcd_1 _PROTO ((mp_srcptr, mp_size_t, mp_limb));
+
+
+static __gmp_inline mp_limb
+#if __STDC__
+__mpn_add_1 (register mp_ptr res_ptr,
+	     register mp_srcptr s1_ptr,
+	     register mp_size_t s1_size,
+	     register mp_limb s2_limb)
+#else
+__mpn_add_1 (res_ptr, s1_ptr, s1_size, s2_limb)
+     register mp_ptr res_ptr;
+     register mp_srcptr s1_ptr;
+     register mp_size_t s1_size;
+     register mp_limb s2_limb;
+#endif
+{
+  register mp_limb x;
+
+  x = *s1_ptr++;
+  s2_limb = x + s2_limb;
+  *res_ptr++ = s2_limb;
+  if (s2_limb < x)
+    {
+      while (--s1_size != 0)
+	{
+	  x = *s1_ptr++ + 1;
+	  *res_ptr++ = x;
+	  if (x != 0)
+	    goto fin;
+	}
+
+      return 1;
+    }
+
+ fin:
+  if (res_ptr != s1_ptr)
+    {
+      mp_size_t i;
+      for (i = 0; i < s1_size - 1; i++)
+	res_ptr[i] = s1_ptr[i];
+    }
+  return 0;
+}
+
+static __gmp_inline mp_limb
+#if __STDC__
+__mpn_add (register mp_ptr res_ptr,
+	   register mp_srcptr s1_ptr,
+	   register mp_size_t s1_size,
+	   register mp_srcptr s2_ptr,
+	   register mp_size_t s2_size)
+#else
+__mpn_add (res_ptr, s1_ptr, s1_size, s2_ptr, s2_size)
+     register mp_ptr res_ptr;
+     register mp_srcptr s1_ptr;
+     register mp_size_t s1_size;
+     register mp_srcptr s2_ptr;
+     register mp_size_t s2_size;
+#endif
+{
+  mp_limb cy_limb = 0;
+
+  if (s2_size != 0)
+    cy_limb = __mpn_add_n (res_ptr, s1_ptr, s2_ptr, s2_size);
+
+  if (s1_size - s2_size != 0)
+    cy_limb =  __mpn_add_1 (res_ptr + s2_size,
+			    s1_ptr + s2_size,
+			    s1_size - s2_size,
+			    cy_limb);
+  return cy_limb;
+}
+
+static __gmp_inline mp_limb
+#if __STDC__
+__mpn_sub_1 (register mp_ptr res_ptr,
+	     register mp_srcptr s1_ptr,
+	     register mp_size_t s1_size,
+	     register mp_limb s2_limb)
+#else
+__mpn_sub_1 (res_ptr, s1_ptr, s1_size, s2_limb)
+     register mp_ptr res_ptr;
+     register mp_srcptr s1_ptr;
+     register mp_size_t s1_size;
+     register mp_limb s2_limb;
+#endif
+{
+  register mp_limb x;
+
+  x = *s1_ptr++;
+  s2_limb = x - s2_limb;
+  *res_ptr++ = s2_limb;
+  if (s2_limb > x)
+    {
+      while (--s1_size != 0)
+	{
+	  x = *s1_ptr++;
+	  *res_ptr++ = x - 1;
+	  if (x != 0)
+	    goto fin;
+	}
+
+      return 1;
+    }
+
+ fin:
+  if (res_ptr != s1_ptr)
+    {
+      mp_size_t i;
+      for (i = 0; i < s1_size - 1; i++)
+	res_ptr[i] = s1_ptr[i];
+    }
+  return 0;
+}
+
+static __gmp_inline mp_limb
+#if __STDC__
+__mpn_sub (register mp_ptr res_ptr,
+	   register mp_srcptr s1_ptr,
+	   register mp_size_t s1_size,
+	   register mp_srcptr s2_ptr,
+	   register mp_size_t s2_size)
+#else
+__mpn_sub (res_ptr, s1_ptr, s1_size, s2_ptr, s2_size)
+     register mp_ptr res_ptr;
+     register mp_srcptr s1_ptr;
+     register mp_size_t s1_size;
+     register mp_srcptr s2_ptr;
+     register mp_size_t s2_size;
+#endif
+{
+  mp_limb cy_limb = 0;
+
+  if (s2_size != 0)
+    cy_limb = __mpn_sub_n (res_ptr, s1_ptr, s2_ptr, s2_size);
+
+  if (s1_size - s2_size != 0)
+    cy_limb =  __mpn_sub_1 (res_ptr + s2_size,
+			    s1_ptr + s2_size,
+			    s1_size - s2_size,
+			    cy_limb);
+  return cy_limb;
+}
+
+static __gmp_inline mp_size_t
+#if __STDC__
+__mpn_normal_size (mp_srcptr ptr, mp_size_t size)
+#else
+__mpn_normal_size (ptr, size)
+     mp_srcptr ptr;
+     mp_size_t size;
+#endif
+{
+  while (size)
+    {
+      size--;
+      if (ptr[size] != 0)
+	return size + 1;
+    }
+  return 0;
+}
+
+/* Compatibility with GMP 1.  */
+
+#define mpz_mdiv	mpz_fdiv_q
+#define mpz_mdivmod	mpz_fdiv_qr
+#define mpz_mmod	mpz_fdiv_r
+#define mpz_mdiv_ui	mpz_fdiv_q_ui
+#define mpz_mdivmod_ui(q,r,n,d) \
+  ((r == 0) ? mpz_fdiv_q_ui (q,n,d) : mpz_fdiv_qr_ui (q,r,n,d))
+#define mpz_mmod_ui(r,n,d) \
+  ((r == 0) ? mpz_fdiv_ui (n,d) : mpz_fdiv_r_ui (r,n,d))
+/* ??? Before release...
+#define mpz_div_2exp	mpz_fdiv_q_2exp
+#define mpz_mod_2exp	mpz_fdiv_r_2exp
+*/
+
+/* Useful synonyms, but not quite compatible with GMP 1.  */
+#define mpz_div		mpz_fdiv_q
+#define mpz_divmod	mpz_fdiv_qr
+#define mpz_mod		mpz_fdiv_r
+#define mpz_div_ui	mpz_fdiv_q_ui
+#define mpz_divmod_ui	mpz_fdiv_qr_ui
+#define mpz_mod_ui	mpz_fdiv_r_ui
+
+
+#define __GNU_MP__ 2
+#define __GNU_MP_VERSION 2
+#define __GNU_MP_VERSION_MINOR -900 /* ??? */
+#define __GMP_H__
+#endif /* __GMP_H__ */
diff --git a/stdio/internals.c b/stdio/internals.c
new file mode 100644
index 0000000000..b01c5bd531
--- /dev/null
+++ b/stdio/internals.c
@@ -0,0 +1,667 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* Make sure that FP has its functions set.  */
+void
+DEFUN(__stdio_check_funcs, (fp), register FILE *fp)
+{
+  if (!fp->__seen)
+    {
+      /* Initialize the stream's info, including buffering info.
+	 This may give a buffer, change I/O functions, etc.
+	 If no buffer is set (and the stream is not made explicitly
+	 unbuffered), we allocate a buffer below, using the bufsize
+	 set by this function.  */
+      extern void EXFUN(__stdio_init_stream, (FILE *));
+      fp->__room_funcs = __default_room_functions;
+      fp->__io_funcs = __default_io_functions;
+      __stdio_init_stream (fp);
+      fp->__seen = 1;
+    }
+}
+
+
+/* Minimum size of a buffer we will allocate by default.
+   If this much memory is not available,
+   the stream in question will be made unbuffered instead.  */
+#define	MIN_BUFSIZE	128
+
+/* Figure out what kind of buffering (none, line, or full)
+   and what buffer size to give FP.  */
+static void
+DEFUN(init_stream, (fp), register FILE *fp)
+{
+  __stdio_check_funcs (fp);
+
+  if (fp->__buffer == NULL && !fp->__userbuf)
+    {
+      int save;
+
+      if (fp->__bufsize == 0)
+	fp->__bufsize = BUFSIZ;
+
+      /* Try to get however many bytes of buffering __stdio_pickbuf
+	 specified, but if that much memory isn't available,
+	 try half as much each time until it succeeds or the buffer
+	 size becomes too small to be useful.  */
+      save = errno;
+      while (fp->__bufsize >= MIN_BUFSIZE)
+	{
+	  fp->__buffer = (char *) malloc(fp->__bufsize);
+	  if (fp->__buffer == NULL)
+	    fp->__bufsize /= 2;
+	  else
+	    break;
+	}
+      errno = save;
+
+      if (fp->__buffer == NULL)
+	{
+	  /* We can't get space for the buffer, so make it unbuffered.  */
+	  fp->__userbuf = 1;
+	  fp->__bufsize = 0;
+	}
+    }
+
+  if (fp->__bufp == NULL)
+    {
+      /* Set the buffer pointer to the beginning of the buffer.  */
+      fp->__bufp = fp->__buffer;
+      fp->__put_limit = fp->__get_limit = fp->__buffer;
+    }
+}
+
+
+/* Determine the current file position of STREAM if it is unknown.  */
+int
+DEFUN(__stdio_check_offset, (stream), FILE *stream)
+{
+  init_stream (stream);
+
+  if (stream->__offset == (fpos_t) -1)
+    {
+      /* This stream's offset is unknown or unknowable.  */
+      if (stream->__io_funcs.__seek == NULL)
+	{
+	  /* Unknowable.  */
+	  errno = ESPIPE;
+	  return EOF;
+	}
+      else
+	{
+	  /* Unknown.  Find it out.  */
+	  fpos_t pos = (fpos_t) 0;
+	  if ((*stream->__io_funcs.__seek)(stream->__cookie,
+					   &pos, SEEK_CUR) < 0)
+	    {
+	      if (errno == ESPIPE)
+		/* Object is incapable of seeking.  */
+		stream->__io_funcs.__seek = NULL;
+	      return EOF;
+	    }
+	  stream->__offset = pos;
+	}
+    }
+
+  if (stream->__target == (fpos_t) -1)
+    /* This stream was opened on an existing object with
+       an unknown file position.  The position is now known.
+       Make this the target position.  */
+    stream->__target = stream->__offset;
+
+  return 0;
+}
+
+
+/* Move FP's file position to its target file position,
+   seeking as necessary and updating its `offset' field.
+   Sets ferror(FP) (and possibly errno) for errors.  */
+static void
+DEFUN(seek_to_target, (fp), FILE *fp)
+{
+  int save = errno;
+  if (__stdio_check_offset (fp) == EOF)
+    {
+      if (errno == ESPIPE)
+	errno = save;
+      else
+	fp->__error = 1;
+    }
+  else if (fp->__target != fp->__offset)
+    {
+      /* We are not at the target file position.
+	 Seek to that position.  */
+      if (fp->__io_funcs.__seek == NULL)
+	{
+	  /* We can't seek!  */
+	  errno = ESPIPE;
+	  fp->__error = 1;
+	}
+      else
+	{
+	  fpos_t pos = fp->__target;
+	  if ((*fp->__io_funcs.__seek)(fp->__cookie, &pos, SEEK_SET) < 0)
+	    /* Seek failed!  */
+	    fp->__error = 1;
+	  else
+	    {
+	      fp->__offset = pos;
+	      if (pos != fp->__target)
+		/* Seek didn't go to the right place!  */
+		fp->__error = 1;
+	    }
+	}
+    }
+}
+
+/* Flush the buffer for FP.
+   If C is not EOF, it is also to be written.
+   If the stream is line buffered and C is a newline, it is written
+   to the output, otherwise it is put in the buffer after it has been
+   flushed to avoid a system call for a single character.
+   This is the default `output room' function.  */
+static void
+DEFUN(flushbuf, (fp, c),
+      register FILE *fp AND int c)
+{
+  int flush_only = c == EOF;
+  size_t buffer_written;
+  size_t to_write;
+
+  /* Set if target and get_limit have already been twiddled appropriately.  */
+  int twiddled = 0;
+
+  if (fp->__put_limit == fp->__buffer)
+    {
+      /* The stream needs to be primed for writing.  */
+
+      size_t buffer_offset = 0;
+
+      /* If the user has read some of the buffer, the target position
+	 is incremented for each character he has read.  */
+      fp->__target += fp->__bufp - fp->__buffer;
+
+      if (fp->__mode.__read && fp->__room_funcs.__input != NULL &&
+	  !fp->__mode.__append)
+	{
+	  int save = errno;
+	  CONST int aligned = (fp->__buffer == NULL ||
+			       __stdio_check_offset(fp) == EOF ||
+			       fp->__target % fp->__bufsize == 0);
+	  errno = save;
+
+	  if (!aligned)
+	    {
+	      /* Move to a block (buffer size) boundary and read in a block.
+		 Then the output will be written as a whole block, too.  */
+	      CONST size_t o = fp->__target % fp->__bufsize;
+	      fp->__target -= o;
+	      if ((*fp->__room_funcs.__input)(fp) == EOF && ferror(fp))
+		return;
+	      else
+		__clearerr(fp);
+
+	      if (fp->__get_limit - fp->__buffer < o)
+		/* Oops.  We didn't read enough (probably because we got EOF).
+		   Forget we even mentioned it.  */
+		fp->__target += o;
+	      else
+		/* Start bufp as far into the buffer as we were into
+		   this block before we read it.  */
+		buffer_offset = o;
+	    }
+
+	  /* The target position is now set to where the beginning of the
+	     buffer maps to; and the get_limit was set by the input-room
+	     function.  */
+	  twiddled = 1;
+	}
+
+      if (fp->__buffer != NULL)
+	{
+	  /* Set up to write output into the buffer.  */
+	  fp->__put_limit = fp->__buffer + fp->__bufsize;
+	  fp->__bufp = fp->__buffer + buffer_offset;
+
+	  if (!flush_only)
+	    {
+	      /* Put C in the buffer to be written out.
+		 We only need to actually write it out now if
+		 it is a newline on a line-buffered stream.  */
+	      *fp->__bufp++ = (unsigned char) c;
+	      if (!fp->__linebuf || (unsigned char) c != '\n')
+		{
+		  /* There is no need to flush C from the buffer right now.
+		     Record that nothing was written from the buffer,
+		     and go do clean-up at end.  */
+		  buffer_written = 0;
+		  goto end;
+		}
+	      else
+		/* We put C in the buffer, so don't write it again later.  */
+		flush_only = 1;
+	    }
+	}
+
+      if (fp->__bufp - fp->__buffer <= buffer_offset)
+	{
+	  /* There is nothing new in the buffer, only data that
+	     was read back aligned from the file.  */
+	  buffer_written = 0;
+	  goto end;
+	}
+    }
+
+  /* If there is read data in the buffer past what was written,
+     write all of that as well.  Otherwise, just write what has been
+     written into the buffer.  */
+  buffer_written = fp->__bufp - fp->__buffer;
+  to_write = (buffer_written == 0 ? 0 :
+	      fp->__get_limit > fp->__bufp ?
+	      fp->__get_limit - fp->__buffer :
+	      buffer_written);
+
+  if (fp->__io_funcs.__write == NULL || (to_write == 0 && flush_only))
+    {
+      /* There is no writing function or we're coming from an fflush
+	 call with nothing in the buffer, so just say the buffer's
+	 been flushed, increment the file offset, and return.  */
+      fp->__bufp = fp->__buffer;
+      fp->__offset += to_write;
+      goto end;
+    }
+
+  if (to_write > 0)
+    {
+      int wrote;
+
+      /* Go to the target file position.  Don't bother if appending;
+         the write will just ignore the file position anyway.  */
+      if (!fp->__mode.__append)
+	seek_to_target (fp);
+
+      if (!ferror(fp))
+	{
+	  /* Write out the buffered data.  */
+	  wrote = (*fp->__io_funcs.__write)(fp->__cookie, fp->__buffer,
+					    to_write);
+	  if (wrote > 0)
+	    {
+	      if (fp->__mode.__append)
+		/* The write has written the data to the end of the file
+		   and updated the file position to after the data.  Don't
+		   bother to find the current position; we can get it
+		   later if we need it.  */
+		fp->__offset = fp->__target = -1;
+	      else
+		/* Record that we've moved forward in the file.  */
+		fp->__offset += wrote;
+	    }
+	  if (wrote < (int) to_write)
+	    /* The writing function should always write
+	       the whole buffer unless there is an error.  */
+	    fp->__error = 1;
+	}
+    }
+
+  /* Reset the buffer pointer to the beginning of the buffer.  */
+  fp->__bufp = fp->__buffer;
+
+  /* If we're not just flushing, write the last character, C.  */
+  if (!flush_only && !ferror(fp))
+    {
+      if (fp->__buffer == NULL || (fp->__linebuf && (unsigned char) c == '\n'))
+	{
+	  /* Either we're unbuffered, or we're line-buffered and
+	     C is a newline, so really write it out immediately.  */
+	  char cc = (unsigned char) c;
+	  if ((*fp->__io_funcs.__write)(fp->__cookie, &cc, 1) < 1)
+	    fp->__error = 1;
+	  else
+	    {
+	      /* Record that we've moved forward in the file.  */
+	      ++fp->__offset;
+	      ++fp->__target;
+	    }
+	}
+      else
+	/* Just put C in the buffer.  */
+	*fp->__bufp++ = (unsigned char) c;
+    }
+
+ end:
+
+  if (!twiddled)
+    {
+      /* The new target position moves up as
+	 much as the user wrote into the buffer.  */
+      fp->__target += buffer_written;
+
+      /* Set the reading limit to the beginning of the buffer,
+	 so the next `getc' will call __fillbf.  */
+      fp->__get_limit = fp->__buffer;
+    }
+
+  if (feof(fp) || ferror(fp))
+    fp->__bufp = fp->__put_limit;
+}
+
+
+/* Fill the buffer for FP and return the first character read (or EOF).
+   This is the default `input_room' function.  */
+static int
+DEFUN(fillbuf, (fp), register FILE *fp)
+{
+  /* How far into the buffer we read we want to start bufp.  */
+  size_t buffer_offset = 0;
+  register char *buffer;
+  register size_t to_read, nread = 0;
+  /* This must be unsigned to avoid sign extension in return.  */
+  unsigned char c;
+
+  if (fp->__io_funcs.__read == NULL)
+    {
+      /* There is no read function, so always return EOF.  */
+      fp->__eof = 1;
+      goto end;
+    }
+
+  if (fp->__buffer == NULL)
+    {
+      /* We're unbuffered, so we want to read only one character.  */
+      buffer = (char *) &c;
+      to_read = 1;
+    }
+  else
+    {
+      /* We're buffered, so try to fill the buffer.  */
+      buffer = fp->__buffer;
+      to_read = fp->__bufsize;
+    }
+
+  /* We're reading, so we're not at the end-of-file.  */
+  fp->__eof = 0;
+
+  /* Go to the target file position.  */
+  {
+    int save = errno;
+    if (__stdio_check_offset (fp) == 0 && fp->__target != fp->__offset)
+      {
+	/* Move to a block (buffer size) boundary.  */
+	if (fp->__bufsize != 0)
+	  {
+	    buffer_offset = fp->__target % fp->__bufsize;
+	    fp->__target -= buffer_offset;
+	  }
+	seek_to_target (fp);
+      }
+    errno = save;
+  }
+
+  while (!ferror(fp) && !feof(fp) && nread <= buffer_offset)
+    {
+      /* Try to fill the buffer.  */
+      int count = (*fp->__io_funcs.__read)(fp->__cookie, buffer, to_read);
+      if (count == 0)
+	fp->__eof = 1;
+      else if (count < 0)
+	fp->__error = 1;
+      else
+	{
+	  buffer += count;
+	  nread += count;
+	  to_read -= count;
+	  /* Record that we've moved forward in the file.  */
+	  fp->__offset += count;
+	}
+    }
+
+  if (fp->__buffer == NULL)
+    /* There is no buffer, so return the character we read
+       without all the buffer pointer diddling.  */
+    return (feof(fp) || ferror(fp)) ? EOF : c;
+
+  /* Reset the buffer pointer to the beginning of the buffer
+     (plus whatever offset we may have set above).  */
+  fp->__bufp = fp->__buffer + buffer_offset;
+
+ end:;
+
+  if (feof(fp) || ferror(fp))
+    {
+      /* Set both end pointers to the beginning of the buffer so
+	 the next i/o call will force a call to __fillbf/__flshfp.  */
+      fp->__put_limit = fp->__get_limit = fp->__buffer;
+      return EOF;
+    }
+
+  /* Set the end pointer to one past the last character we read.  */
+  fp->__get_limit = fp->__buffer + nread;
+
+  /* Make it so the next `putc' will call __flshfp.  */
+  fp->__put_limit = fp->__buffer;
+
+  /* Return the first character in the buffer.  */
+  return *((unsigned char *) (fp->__bufp++));
+}
+
+
+/* Default I/O and room functions.  */
+
+extern __io_read_fn __stdio_read;
+extern __io_write_fn __stdio_write;
+extern __io_seek_fn __stdio_seek;
+extern __io_close_fn __stdio_close;
+extern __io_fileno_fn __stdio_fileno;
+CONST __io_functions __default_io_functions =
+  {
+    __stdio_read, __stdio_write, __stdio_seek, __stdio_close, __stdio_fileno
+  };
+
+CONST __room_functions __default_room_functions =
+  {
+    fillbuf, flushbuf
+  };
+
+
+/* Flush the buffer for FP and also write C if FLUSH_ONLY is nonzero.
+   This is the function used by putc and fflush.  */
+int
+DEFUN(__flshfp, (fp, c),
+      register FILE *fp AND int c)
+{
+  int flush_only = c == EOF;
+
+  if (!__validfp(fp) || !fp->__mode.__write)
+    {
+      errno = EINVAL;
+      return EOF;
+    }
+
+  if (ferror(fp))
+    return EOF;
+
+  if (fp->__pushed_back)
+    {
+      /* Discard the char pushed back by ungetc.  */
+      fp->__bufp = fp->__pushback_bufp;
+      fp->__pushed_back = 0;
+    }
+
+  /* Make sure the stream is initialized (has functions and buffering).  */
+  init_stream(fp);
+
+  /* Do this early, so a `putc' on such a stream will never return success.  */
+  if (fp->__room_funcs.__output == NULL)
+    {
+      /* A NULL `output room' function means
+	 to always return an output error.  */
+      fp->__error = 1;
+      return EOF;
+    }
+
+  if (!flush_only &&
+      /* Will C fit into the buffer?
+	 See below about linebuf_active.  */
+      fp->__bufp < (fp->__linebuf_active ? fp->__buffer + fp->__bufsize :
+		    fp->__put_limit))
+    {
+      /* The character will fit in the buffer, so put it there.  */
+      *fp->__bufp++ = (unsigned char) c;
+      if (fp->__linebuf && (unsigned char) c == '\n')
+	flush_only = 1;
+      else
+	return (unsigned char) c;
+    }
+
+  if (fp->__linebuf_active)
+    /* This is an active line-buffered stream, so its put-limit is set
+       to the beginning of the buffer in order to force a __flshfp call
+       on each putc (see below).  We undo this hack here (by setting
+       the limit to the end of the buffer) to simplify the interface
+       with the output-room function.  */
+    fp->__put_limit = fp->__buffer + fp->__bufsize;
+
+  /* Make room in the buffer.  */
+  (*fp->__room_funcs.__output) (fp, flush_only ? EOF : (unsigned char) c);
+
+  if (fp->__linebuf)
+    {
+      /* This is a line-buffered stream, and it is now ready to do
+	 some output.  We call this an "active line-buffered stream".
+	 We set the put_limit to the beginning of the buffer,
+	 so the next `putc' call will force a call to this function.
+	 Setting the linebuf_active flag tells the code above
+	 (on the next call) to undo this hackery.  */
+      fp->__put_limit = fp->__buffer;
+      fp->__linebuf_active = 1;
+    }
+
+  if (ferror (fp))
+    return EOF;
+  if (flush_only)
+    return 0;
+  return (unsigned char) c;
+}
+
+
+/* Fill the buffer for FP and return the first character read.
+   This is the function used by getc.  */
+int
+DEFUN(__fillbf, (fp), register FILE *fp)
+{
+  register int c;
+  fpos_t new_target;
+
+  if (!__validfp(fp) || !fp->__mode.__read)
+    {
+      errno = EINVAL;
+      return EOF;
+    }
+
+  if (fp->__pushed_back)
+    {
+      /* Return the char pushed back by ungetc.  */
+      fp->__bufp = fp->__pushback_bufp;
+      fp->__pushed_back = 0;
+      return fp->__pushback;
+    }
+
+  /* Make sure the stream is initialized (has functions and buffering). */
+  init_stream(fp);
+
+  /* If we're trying to read the first character of a new
+     line of input from an unbuffered or line buffered stream,
+     we must flush all line-buffered output streams. */
+  if (fp->__buffer == NULL || fp->__linebuf)
+    {
+      register FILE *f;
+      for (f = __stdio_head; f != NULL; f = f->__next)
+	if (__validfp (f) && f->__linebuf && f->__mode.__write)
+	  (void) __flshfp (f, EOF);
+    }
+
+  /* Note we must do this after flushing all line-buffered
+     streams, or else __flshfp would undo it!  */
+  if (fp->__linebuf_active)
+    {
+      /* This is an active line-buffered stream, meaning it is in the midst
+	 of writing, but has a bogus put_limit.  Restore it to normality.  */
+      fp->__put_limit = fp->__buffer + fp->__bufsize;
+      fp->__linebuf_active = 0;
+    }
+
+  /* We want the beginning of the buffer to now
+     map to just past the last data we read.  */
+  new_target = fp->__target + (fp->__get_limit - fp->__buffer);
+
+  if (fp->__put_limit > fp->__buffer)
+    {
+      /* There is written data in the buffer.
+	 Flush it out.  */
+      if (fp->__room_funcs.__output == NULL)
+	fp->__error = 1;
+      else
+	(*fp->__room_funcs.__output) (fp, EOF);
+    }
+
+  fp->__target = new_target;
+
+  if (ferror(fp))
+    c = EOF;
+  else if (fp->__room_funcs.__input != NULL)
+    {
+      c = (*fp->__room_funcs.__input)(fp);
+      if (fp->__buffer == NULL)
+	/* This is an unbuffered stream, so the target sync above
+	   won't do anything the next time around.  Instead, note that
+	   we have read one character.  The (nonexistent) buffer now
+	   maps to the position just past that character.  */
+	++fp->__target;
+    }
+  else
+    {
+      /* A NULL `input_room' function means always return EOF.  */
+      fp->__eof = 1;
+      c = EOF;
+    }
+
+  return c;
+}
+
+
+/* Nuke a stream, but don't kill its link in the chain.  */
+void
+DEFUN(__invalidate, (stream), register FILE *stream)
+{
+  /* Save its link.  */
+  register FILE *next = stream->__next;
+
+  /* Pulverize the fucker.  */
+  memset((PTR) stream, 0, sizeof(FILE));
+
+  /* Restore the deceased's link.  */
+  stream->__next = next;
+}
diff --git a/stdio/longlong.h b/stdio/longlong.h
new file mode 100644
index 0000000000..97c469d8c0
--- /dev/null
+++ b/stdio/longlong.h
@@ -0,0 +1,1295 @@
+/* longlong.h -- definitions for mixed size 32/64 bit arithmetic.
+
+Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+
+This file is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+This file is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with this file; see the file COPYING.LIB.  If not, write to
+the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* You have to define the following before including this file:
+
+   UWtype -- An unsigned type, default type for operations (typically a "word")
+   UHWtype -- An unsigned type, at least half the size of UWtype.
+   UDWtype -- An unsigned type, at least twice as large a UWtype
+   W_TYPE_SIZE -- size in bits of UWtype
+
+   SItype, USItype -- Signed and unsigned 32 bit types.
+   DItype, UDItype -- Signed and unsigned 64 bit types.
+
+   On a 32 bit machine UWtype should typically be USItype;
+   on a 64 bit machine, UWtype should typically be UDItype.
+*/
+
+#define __BITS4 (W_TYPE_SIZE / 4)
+#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
+#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
+#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
+
+/* Define auxiliary asm macros.
+
+   1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two
+   UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype
+   word product in HIGH_PROD and LOW_PROD.
+
+   2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a
+   UDWtype product.  This is just a variant of umul_ppmm.
+
+   3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
+   denominator) divides a UDWtype, composed by the UWtype integers
+   HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient
+   in QUOTIENT and the remainder in REMAINDER.  HIGH_NUMERATOR must be less
+   than DENOMINATOR for correct operation.  If, in addition, the most
+   significant bit of DENOMINATOR must be 1, then the pre-processor symbol
+   UDIV_NEEDS_NORMALIZATION is defined to 1.
+
+   4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
+   denominator).  Like udiv_qrnnd but the numbers are signed.  The quotient
+   is rounded towards 0.
+
+   5) count_leading_zeros(count, x) counts the number of zero-bits from the
+   msb to the first non-zero bit in the UWtype X.  This is the number of
+   steps X needs to be shifted left to set the msb.  Undefined for X == 0,
+   unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value.
+
+   6) count_trailing_zeros(count, x) like count_leading_zeros, but counts
+   from the least significant end.
+
+   7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1,
+   high_addend_2, low_addend_2) adds two UWtype integers, composed by
+   HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2
+   respectively.  The result is placed in HIGH_SUM and LOW_SUM.  Overflow
+   (i.e. carry out) is not stored anywhere, and is lost.
+
+   8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend,
+   high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers,
+   composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and
+   LOW_SUBTRAHEND_2 respectively.  The result is placed in HIGH_DIFFERENCE
+   and LOW_DIFFERENCE.  Overflow (i.e. carry out) is not stored anywhere,
+   and is lost.
+
+   If any of these macros are left undefined for a particular CPU,
+   C macros are used.  */
+
+/* The CPUs come in alphabetical order below.
+
+   Please add support for more CPUs here, or improve the current support
+   for the CPUs below!  */
+
+#if defined (__GNUC__) && !defined (NO_ASM)
+
+/* We sometimes need to clobber "cc" with gcc2, but that would not be
+   understood by gcc1.  Use cpp to avoid major code duplication.  */
+#if __GNUC__ < 2
+#define __CLOBBER_CC
+#define __AND_CLOBBER_CC
+#else /* __GNUC__ >= 2 */
+#define __CLOBBER_CC : "cc"
+#define __AND_CLOBBER_CC , "cc"
+#endif /* __GNUC__ < 2 */
+
+#if (defined (__a29k__) || defined (___AM29K__)) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("add %1,%4,%5
+	addc %0,%2,%3"							\
+	   : "=r" ((USItype)(sh)),					\
+	    "=&r" ((USItype)(sl))					\
+	   : "%r" ((USItype)(ah)),					\
+	     "rI" ((USItype)(bh)),					\
+	     "%r" ((USItype)(al)),					\
+	     "rI" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("sub %1,%4,%5
+	subc %0,%2,%3"							\
+	   : "=r" ((USItype)(sh)),					\
+	     "=&r" ((USItype)(sl))					\
+	   : "r" ((USItype)(ah)),					\
+	     "rI" ((USItype)(bh)),					\
+	     "r" ((USItype)(al)),					\
+	     "rI" ((USItype)(bl)))
+#define umul_ppmm(xh, xl, m0, m1) \
+  do {									\
+    USItype __m0 = (m0), __m1 = (m1);					\
+    __asm__ ("multiplu %0,%1,%2"					\
+	     : "=r" ((USItype)(xl))					\
+	     : "r" (__m0),						\
+	       "r" (__m1));						\
+    __asm__ ("multmu %0,%1,%2"						\
+	     : "=r" ((USItype)(xh))					\
+	     : "r" (__m0),						\
+	       "r" (__m1));						\
+  } while (0)
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  __asm__ ("dividu %0,%3,%4"						\
+	   : "=r" ((USItype)(q)),					\
+	     "=q" ((USItype)(r))					\
+	   : "1" ((USItype)(n1)),					\
+	     "r" ((USItype)(n0)),					\
+	     "r" ((USItype)(d)))
+#define count_leading_zeros(count, x) \
+    __asm__ ("clz %0,%1"						\
+	     : "=r" ((USItype)(count))					\
+	     : "r" ((USItype)(x)))
+#endif /* __a29k__ */
+
+#if defined (__alpha__) && W_TYPE_SIZE == 64
+#define umul_ppmm(ph, pl, m0, m1) \
+  do {									\
+    UDItype __m0 = (m0), __m1 = (m1);					\
+    __asm__ ("umulh %r1,%2,%0"						\
+	     : "=r" ((UDItype) ph)					\
+	     : "%rJ" (__m0),						\
+	       "rI" (__m1));						\
+    (pl) = __m0 * __m1;							\
+  } while (0)
+#define UMUL_TIME 46
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  do { UDItype __r;							\
+    (q) = __udiv_qrnnd (&__r, (n1), (n0), (d));				\
+    (r) = __r;								\
+  } while (0)
+extern UDItype __udiv_qrnnd ();
+#define UDIV_TIME 220
+#endif
+
+#if defined (__arm__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("adds %1,%4,%5
+	adc %0,%2,%3"							\
+	   : "=r" ((USItype)(sh)),					\
+	     "=&r" ((USItype)(sl))					\
+	   : "%r" ((USItype)(ah)),					\
+	     "rI" ((USItype)(bh)),					\
+	     "%r" ((USItype)(al)),					\
+	     "rI" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("subs %1,%4,%5
+	sbc %0,%2,%3"							\
+	   : "=r" ((USItype)(sh)),					\
+	     "=&r" ((USItype)(sl))					\
+	   : "r" ((USItype)(ah)),					\
+	     "rI" ((USItype)(bh)),					\
+	     "r" ((USItype)(al)),					\
+	     "rI" ((USItype)(bl)))
+#define umul_ppmm(xh, xl, a, b) \
+  __asm__ ("; Inlined umul_ppmm
+	mov	r0,%2 lsr 16
+	mov	r2,%3 lsr 16
+	bic	r1,%2,r0 lsl 16
+	bic	r2,%3,r2 lsl 16
+	mul	%1,r1,r2
+	mul	r2,r0,r2
+	mul	r1,%0,r1
+	mul	%0,r0,%0
+	adds	r1,r2,r1
+	addcs	%0,%0,0x10000
+	adds	%1,%1,r1 lsl 16
+	adc	%0,%0,r1 lsr 16"					\
+	   : "=&r" ((USItype)(xh)),					\
+	     "=r" ((USItype)(xl))					\
+	   : "r" ((USItype)(a)),					\
+	     "r" ((USItype)(b))						\
+	   : "r0", "r1", "r2")
+#define UMUL_TIME 20
+#define UDIV_TIME 100
+#endif /* __arm__ */
+
+#if defined (__clipper__) && W_TYPE_SIZE == 32
+#define umul_ppmm(w1, w0, u, v) \
+  ({union {UDItype __ll;						\
+	   struct {USItype __l, __h;} __i;				\
+	  } __xx;							\
+  __asm__ ("mulwux %2,%0"						\
+	   : "=r" (__xx.__ll)						\
+	   : "%0" ((USItype)(u)),					\
+	     "r" ((USItype)(v)));					\
+  (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
+#define smul_ppmm(w1, w0, u, v) \
+  ({union {DItype __ll;							\
+	   struct {SItype __l, __h;} __i;				\
+	  } __xx;							\
+  __asm__ ("mulwx %2,%0"						\
+	   : "=r" (__xx.__ll)						\
+	   : "%0" ((SItype)(u)),					\
+	     "r" ((SItype)(v)));					\
+  (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
+#define __umulsidi3(u, v) \
+  ({UDItype __w;							\
+    __asm__ ("mulwux %2,%0"						\
+	     : "=r" (__w)						\
+	     : "%0" ((USItype)(u)),					\
+	       "r" ((USItype)(v)));					\
+    __w; })
+#endif /* __clipper__ */
+
+#if defined (__gmicro__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("add.w %5,%1
+	addx %3,%0"							\
+	   : "=g" ((USItype)(sh)),					\
+	     "=&g" ((USItype)(sl))					\
+	   : "%0" ((USItype)(ah)),					\
+	     "g" ((USItype)(bh)),					\
+	     "%1" ((USItype)(al)),					\
+	     "g" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("sub.w %5,%1
+	subx %3,%0"							\
+	   : "=g" ((USItype)(sh)),					\
+	     "=&g" ((USItype)(sl))					\
+	   : "0" ((USItype)(ah)),					\
+	     "g" ((USItype)(bh)),					\
+	     "1" ((USItype)(al)),					\
+	     "g" ((USItype)(bl)))
+#define umul_ppmm(ph, pl, m0, m1) \
+  __asm__ ("mulx %3,%0,%1"						\
+	   : "=g" ((USItype)(ph)),					\
+	     "=r" ((USItype)(pl))					\
+	   : "%0" ((USItype)(m0)),					\
+	     "g" ((USItype)(m1)))
+#define udiv_qrnnd(q, r, nh, nl, d) \
+  __asm__ ("divx %4,%0,%1"						\
+	   : "=g" ((USItype)(q)),					\
+	     "=r" ((USItype)(r))					\
+	   : "1" ((USItype)(nh)),					\
+	     "0" ((USItype)(nl)),					\
+	     "g" ((USItype)(d)))
+#define count_leading_zeros(count, x) \
+  __asm__ ("bsch/1 %1,%0"						\
+	   : "=g" (count)						\
+	   : "g" ((USItype)(x)),					\
+	     "0" ((USItype)0))
+#endif
+
+#if defined (__hppa) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("add %4,%5,%1
+	addc %2,%3,%0"							\
+	   : "=r" ((USItype)(sh)),					\
+	     "=&r" ((USItype)(sl))					\
+	   : "%rM" ((USItype)(ah)),					\
+	     "rM" ((USItype)(bh)),					\
+	     "%rM" ((USItype)(al)),					\
+	     "rM" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("sub %4,%5,%1
+	subb %2,%3,%0"							\
+	   : "=r" ((USItype)(sh)),					\
+	     "=&r" ((USItype)(sl))					\
+	   : "rM" ((USItype)(ah)),					\
+	     "rM" ((USItype)(bh)),					\
+	     "rM" ((USItype)(al)),					\
+	     "rM" ((USItype)(bl)))
+#if defined (_PA_RISC1_1)
+#define umul_ppmm(wh, wl, u, v) \
+  do {									\
+    union {UDItype __ll;						\
+	   struct {USItype __h, __l;} __i;				\
+	  } __xx;							\
+    __asm__ ("xmpyu %1,%2,%0"						\
+	     : "=x" (__xx.__ll)						\
+	     : "x" ((USItype)(u)),					\
+	       "x" ((USItype)(v)));					\
+    (wh) = __xx.__i.__h;						\
+    (wl) = __xx.__i.__l;						\
+  } while (0)
+#define UMUL_TIME 8
+#define UDIV_TIME 60
+#else
+#define UMUL_TIME 40
+#define UDIV_TIME 80
+#endif
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  do { USItype __r;							\
+    (q) = __udiv_qrnnd (&__r, (n1), (n0), (d));				\
+    (r) = __r;								\
+  } while (0)
+extern USItype __udiv_qrnnd ();
+#define count_leading_zeros(count, x) \
+  do {									\
+    USItype __tmp;							\
+    __asm__ (								\
+       "ldi		1,%0
+	extru,=		%1,15,16,%%r0		; Bits 31..16 zero?
+	extru,tr	%1,15,16,%1		; No.  Shift down, skip add.
+	ldo		16(%0),%0		; Yes.  Perform add.
+	extru,=		%1,23,8,%%r0		; Bits 15..8 zero?
+	extru,tr	%1,23,8,%1		; No.  Shift down, skip add.
+	ldo		8(%0),%0		; Yes.  Perform add.
+	extru,=		%1,27,4,%%r0		; Bits 7..4 zero?
+	extru,tr	%1,27,4,%1		; No.  Shift down, skip add.
+	ldo		4(%0),%0		; Yes.  Perform add.
+	extru,=		%1,29,2,%%r0		; Bits 3..2 zero?
+	extru,tr	%1,29,2,%1		; No.  Shift down, skip add.
+	ldo		2(%0),%0		; Yes.  Perform add.
+	extru		%1,30,1,%1		; Extract bit 1.
+	sub		%0,%1,%0		; Subtract it.
+	" : "=r" (count), "=r" (__tmp) : "1" (x));			\
+  } while (0)
+#endif
+
+#if (defined (__i370__) || defined (__mvs__)) && W_TYPE_SIZE == 32
+#define umul_ppmm(xh, xl, m0, m1) \
+  do {									\
+    union {UDItype __ll;						\
+	   struct {USItype __h, __l;} __i;				\
+	  } __xx;							\
+    USItype __m0 = (m0), __m1 = (m1);					\
+    __asm__ ("mr %0,%3"							\
+	     : "=r" (__xx.__i.__h),					\
+	       "=r" (__xx.__i.__l)					\
+	     : "%1" (__m0),						\
+	       "r" (__m1));						\
+    (xh) = __xx.__i.__h; (xl) = __xx.__i.__l;				\
+    (xh) += ((((SItype) __m0 >> 31) & __m1)				\
+	     + (((SItype) __m1 >> 31) & __m0));				\
+  } while (0)
+#define smul_ppmm(xh, xl, m0, m1) \
+  do {									\
+    union {DItype __ll;							\
+	   struct {USItype __h, __l;} __i;				\
+	  } __xx;							\
+    __asm__ ("mr %0,%3"							\
+	     : "=r" (__xx.__i.__h),					\
+	       "=r" (__xx.__i.__l)					\
+	     : "%1" (m0),						\
+	       "r" (m1));						\
+    (xh) = __xx.__i.__h; (xl) = __xx.__i.__l;				\
+  } while (0)
+#define sdiv_qrnnd(q, r, n1, n0, d) \
+  do {									\
+    union {DItype __ll;							\
+	   struct {USItype __h, __l;} __i;				\
+	  } __xx;							\
+    __xx.__i.__h = n1; __xx.__i.__l = n0;				\
+    __asm__ ("dr %0,%2"							\
+	     : "=r" (__xx.__ll)						\
+	     : "0" (__xx.__ll), "r" (d));				\
+    (q) = __xx.__i.__l; (r) = __xx.__i.__h;				\
+  } while (0)
+#endif
+
+#if (defined (__i386__) || defined (__i486__)) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("addl %5,%1
+	adcl %3,%0"							\
+	   : "=r" ((USItype)(sh)),					\
+	     "=&r" ((USItype)(sl))					\
+	   : "%0" ((USItype)(ah)),					\
+	     "g" ((USItype)(bh)),					\
+	     "%1" ((USItype)(al)),					\
+	     "g" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("subl %5,%1
+	sbbl %3,%0"							\
+	   : "=r" ((USItype)(sh)),					\
+	     "=&r" ((USItype)(sl))					\
+	   : "0" ((USItype)(ah)),					\
+	     "g" ((USItype)(bh)),					\
+	     "1" ((USItype)(al)),					\
+	     "g" ((USItype)(bl)))
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("mull %3"							\
+	   : "=a" ((USItype)(w0)),					\
+	     "=d" ((USItype)(w1))					\
+	   : "%0" ((USItype)(u)),					\
+	     "rm" ((USItype)(v)))
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  __asm__ ("divl %4"							\
+	   : "=a" ((USItype)(q)),					\
+	     "=d" ((USItype)(r))					\
+	   : "0" ((USItype)(n0)),					\
+	     "1" ((USItype)(n1)),					\
+	     "rm" ((USItype)(d)))
+#define count_leading_zeros(count, x) \
+  do {									\
+    USItype __cbtmp;							\
+    __asm__ ("bsrl %1,%0"						\
+	     : "=r" (__cbtmp) : "rm" ((USItype)(x)));			\
+    (count) = __cbtmp ^ 31;						\
+  } while (0)
+#define count_trailing_zeros(count, x) \
+  __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x)))
+#define UMUL_TIME 40
+#define UDIV_TIME 40
+#endif /* 80x86 */
+
+#if defined (__i960__) && W_TYPE_SIZE == 32
+#define umul_ppmm(w1, w0, u, v) \
+  ({union {UDItype __ll;						\
+	   struct {USItype __l, __h;} __i;				\
+	  } __xx;							\
+  __asm__ ("emul	%2,%1,%0"					\
+	   : "=d" (__xx.__ll)						\
+	   : "%dI" ((USItype)(u)),					\
+	     "dI" ((USItype)(v)));					\
+  (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
+#define __umulsidi3(u, v) \
+  ({UDItype __w;							\
+    __asm__ ("emul	%2,%1,%0"					\
+	     : "=d" (__w)						\
+	     : "%dI" ((USItype)(u)),					\
+	       "dI" ((USItype)(v)));					\
+    __w; })  
+#endif /* __i960__ */
+
+#if defined (__mc68000__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("add%.l %5,%1
+	addx%.l %3,%0"							\
+	   : "=d" ((USItype)(sh)),					\
+	     "=&d" ((USItype)(sl))					\
+	   : "%0" ((USItype)(ah)),					\
+	     "d" ((USItype)(bh)),					\
+	     "%1" ((USItype)(al)),					\
+	     "g" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("sub%.l %5,%1
+	subx%.l %3,%0"							\
+	   : "=d" ((USItype)(sh)),					\
+	     "=&d" ((USItype)(sl))					\
+	   : "0" ((USItype)(ah)),					\
+	     "d" ((USItype)(bh)),					\
+	     "1" ((USItype)(al)),					\
+	     "g" ((USItype)(bl)))
+#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) && W_TYPE_SIZE == 32
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("mulu%.l %3,%1:%0"						\
+	   : "=d" ((USItype)(w0)),					\
+	     "=d" ((USItype)(w1))					\
+	   : "%0" ((USItype)(u)),					\
+	     "dmi" ((USItype)(v)))
+#define UMUL_TIME 45
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  __asm__ ("divu%.l %4,%1:%0"						\
+	   : "=d" ((USItype)(q)),					\
+	     "=d" ((USItype)(r))					\
+	   : "0" ((USItype)(n0)),					\
+	     "1" ((USItype)(n1)),					\
+	     "dmi" ((USItype)(d)))
+#define UDIV_TIME 90
+#define sdiv_qrnnd(q, r, n1, n0, d) \
+  __asm__ ("divs%.l %4,%1:%0"						\
+	   : "=d" ((USItype)(q)),					\
+	     "=d" ((USItype)(r))					\
+	   : "0" ((USItype)(n0)),					\
+	     "1" ((USItype)(n1)),					\
+	     "dmi" ((USItype)(d)))
+#define count_leading_zeros(count, x) \
+  __asm__ ("bfffo %1{%b2:%b2},%0"					\
+	   : "=d" ((USItype)(count))					\
+	   : "od" ((USItype)(x)), "n" (0))
+#else /* not mc68020 */
+#define umul_ppmm(xh, xl, a, b) \
+  __asm__ ("| Inlined umul_ppmm
+	move%.l	%2,%/d0
+	move%.l	%3,%/d1
+	move%.l	%/d0,%/d2
+	swap	%/d0
+	move%.l	%/d1,%/d3
+	swap	%/d1
+	move%.w	%/d2,%/d4
+	mulu	%/d3,%/d4
+	mulu	%/d1,%/d2
+	mulu	%/d0,%/d3
+	mulu	%/d0,%/d1
+	move%.l	%/d4,%/d0
+	eor%.w	%/d0,%/d0
+	swap	%/d0
+	add%.l	%/d0,%/d2
+	add%.l	%/d3,%/d2
+	jcc	1f
+	add%.l	#65536,%/d1
+1:	swap	%/d2
+	moveq	#0,%/d0
+	move%.w	%/d2,%/d0
+	move%.w	%/d4,%/d2
+	move%.l	%/d2,%1
+	add%.l	%/d1,%/d0
+	move%.l	%/d0,%0"						\
+	   : "=g" ((USItype)(xh)),					\
+	     "=g" ((USItype)(xl))					\
+	   : "g" ((USItype)(a)),					\
+	     "g" ((USItype)(b))						\
+	   : "d0", "d1", "d2", "d3", "d4")
+#define UMUL_TIME 100
+#define UDIV_TIME 400
+#endif /* not mc68020 */
+#endif /* mc68000 */
+
+#if defined (__m88000__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("addu.co %1,%r4,%r5
+	addu.ci %0,%r2,%r3"						\
+	   : "=r" ((USItype)(sh)),					\
+	     "=&r" ((USItype)(sl))					\
+	   : "%rJ" ((USItype)(ah)),					\
+	     "rJ" ((USItype)(bh)),					\
+	     "%rJ" ((USItype)(al)),					\
+	     "rJ" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("subu.co %1,%r4,%r5
+	subu.ci %0,%r2,%r3"						\
+	   : "=r" ((USItype)(sh)),					\
+	     "=&r" ((USItype)(sl))					\
+	   : "rJ" ((USItype)(ah)),					\
+	     "rJ" ((USItype)(bh)),					\
+	     "rJ" ((USItype)(al)),					\
+	     "rJ" ((USItype)(bl)))
+#define count_leading_zeros(count, x) \
+  do {									\
+    USItype __cbtmp;							\
+    __asm__ ("ff1 %0,%1"						\
+	     : "=r" (__cbtmp)						\
+	     : "r" ((USItype)(x)));					\
+    (count) = __cbtmp ^ 31;						\
+  } while (0)
+#if defined (__mc88110__)
+#define umul_ppmm(wh, wl, u, v) \
+  do {									\
+    union {UDItype __ll;						\
+	   struct {USItype __h, __l;} __i;				\
+	  } __xx;							\
+    __asm__ ("mulu.d	%0,%1,%2"					\
+	     : "=r" (__xx.__ll)						\
+	     : "r" ((USItype)(u)),					\
+	       "r" ((USItype)(v)));					\
+    (wh) = __xx.__i.__h;						\
+    (wl) = __xx.__i.__l;						\
+  } while (0)
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  ({union {UDItype __ll;						\
+	   struct {USItype __h, __l;} __i;				\
+	  } __xx;							\
+  USItype __q;								\
+  __xx.__i.__h = (n1); __xx.__i.__l = (n0);				\
+  __asm__ ("divu.d %0,%1,%2"						\
+	   : "=r" (__q)							\
+	   : "r" (__xx.__ll),						\
+	     "r" ((USItype)(d)));					\
+  (r) = (n0) - __q * (d); (q) = __q; })
+#define UMUL_TIME 5
+#define UDIV_TIME 25
+#else
+#define UMUL_TIME 17
+#define UDIV_TIME 150
+#endif /* __mc88110__ */
+#endif /* __m88000__ */
+
+#if defined (__mips__) && W_TYPE_SIZE == 32
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("multu %2,%3
+	mflo %0
+	mfhi %1"							\
+	   : "=d" ((USItype)(w0)),					\
+	     "=d" ((USItype)(w1))					\
+	   : "d" ((USItype)(u)),					\
+	     "d" ((USItype)(v)))
+#define UMUL_TIME 10
+#define UDIV_TIME 100
+#endif /* __mips__ */
+
+#if (defined (__mips) && __mips >= 3) && W_TYPE_SIZE == 64
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("dmultu %2,%3
+	mflo %0
+	mfhi %1"							\
+	   : "=d" ((UDItype)(w0)),					\
+	     "=d" ((UDItype)(w1))					\
+	   : "d" ((UDItype)(u)),					\
+	     "d" ((UDItype)(v)))
+#define UMUL_TIME 10
+#define UDIV_TIME 100
+#endif /* __mips__ */
+
+#if defined (__ns32000__) && W_TYPE_SIZE == 32
+#define umul_ppmm(w1, w0, u, v) \
+  ({union {UDItype __ll;						\
+	   struct {USItype __l, __h;} __i;				\
+	  } __xx;							\
+  __asm__ ("meid %2,%0"							\
+	   : "=g" (__xx.__ll)						\
+	   : "%0" ((USItype)(u)),					\
+	     "g" ((USItype)(v)));					\
+  (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
+#define __umulsidi3(u, v) \
+  ({UDItype __w;							\
+    __asm__ ("meid %2,%0"						\
+	     : "=g" (__w)						\
+	     : "%0" ((USItype)(u)),					\
+	       "g" ((USItype)(v)));					\
+    __w; })
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  ({union {UDItype __ll;						\
+	   struct {USItype __l, __h;} __i;				\
+	  } __xx;							\
+  __xx.__i.__h = (n1); __xx.__i.__l = (n0);				\
+  __asm__ ("deid %2,%0"							\
+	   : "=g" (__xx.__ll)						\
+	   : "0" (__xx.__ll),						\
+	     "g" ((USItype)(d)));					\
+  (r) = __xx.__i.__l; (q) = __xx.__i.__h; })
+#define count_trailing_zeros(count,x) \
+  do {
+    __asm__ ("ffsd	%2,%0"						\
+	     : "=r" ((USItype) (count))					\
+	     : "0" ((USItype) 0),					\
+	       "r" ((USItype) (x)));					\
+  } while (0)
+#endif /* __ns32000__ */
+
+#if (defined (__powerpc__) || defined (___IBMR2__)) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  do {									\
+    if (__builtin_constant_p (bh) && (bh) == 0)				\
+      __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2"		\
+	     : "=r" ((USItype)(sh)),					\
+	       "=&r" ((USItype)(sl))					\
+	     : "%r" ((USItype)(ah)),					\
+	       "%r" ((USItype)(al)),					\
+	       "rI" ((USItype)(bl)));					\
+    else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0)		\
+      __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2"		\
+	     : "=r" ((USItype)(sh)),					\
+	       "=&r" ((USItype)(sl))					\
+	     : "%r" ((USItype)(ah)),					\
+	       "%r" ((USItype)(al)),					\
+	       "rI" ((USItype)(bl)));					\
+    else								\
+      __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3"		\
+	     : "=r" ((USItype)(sh)),					\
+	       "=&r" ((USItype)(sl))					\
+	     : "%r" ((USItype)(ah)),					\
+	       "r" ((USItype)(bh)),					\
+	       "%r" ((USItype)(al)),					\
+	       "rI" ((USItype)(bl)));					\
+  } while (0)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  do {									\
+    if (__builtin_constant_p (ah) && (ah) == 0)				\
+      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2"		\
+	       : "=r" ((USItype)(sh)),					\
+		 "=&r" ((USItype)(sl))					\
+	       : "r" ((USItype)(bh)),					\
+		 "rI" ((USItype)(al)),					\
+		 "r" ((USItype)(bl)));					\
+    else if (__builtin_constant_p (ah) && (ah) ==~(USItype) 0)		\
+      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2"		\
+	       : "=r" ((USItype)(sh)),					\
+		 "=&r" ((USItype)(sl))					\
+	       : "r" ((USItype)(bh)),					\
+		 "rI" ((USItype)(al)),					\
+		 "r" ((USItype)(bl)));					\
+    else if (__builtin_constant_p (bh) && (bh) == 0)			\
+      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2"		\
+	       : "=r" ((USItype)(sh)),					\
+		 "=&r" ((USItype)(sl))					\
+	       : "r" ((USItype)(ah)),					\
+		 "rI" ((USItype)(al)),					\
+		 "r" ((USItype)(bl)));					\
+    else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0)		\
+      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2"		\
+	       : "=r" ((USItype)(sh)),					\
+		 "=&r" ((USItype)(sl))					\
+	       : "r" ((USItype)(ah)),					\
+		 "rI" ((USItype)(al)),					\
+		 "r" ((USItype)(bl)));					\
+    else								\
+      __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2"	\
+	       : "=r" ((USItype)(sh)),					\
+		 "=&r" ((USItype)(sl))					\
+	       : "r" ((USItype)(ah)),					\
+		 "r" ((USItype)(bh)),					\
+		 "rI" ((USItype)(al)),					\
+		 "r" ((USItype)(bl)));					\
+  } while (0)
+#define count_leading_zeros(count, x) \
+  __asm__ ("{cntlz|cntlzw} %0,%1"					\
+	   : "=r" ((USItype)(count))					\
+	   : "r" ((USItype)(x)))
+#if defined (__powerpc__)
+#define umul_ppmm(ph, pl, m0, m1) \
+  do {									\
+    USItype __m0 = (m0), __m1 = (m1);					\
+    __asm__ ("mulhwu %0,%1,%2"						\
+	     : "=r" ((USItype) ph)					\
+	     : "%r" (__m0),						\
+	       "r" (__m1));						\
+    (pl) = __m0 * __m1;							\
+  } while (0)
+#define UMUL_TIME 15
+#define smul_ppmm(ph, pl, m0, m1) \
+  do {									\
+    SItype __m0 = (m0), __m1 = (m1);					\
+    __asm__ ("mulhw %0,%1,%2"						\
+	     : "=r" ((SItype) ph)					\
+	     : "%r" (__m0),						\
+	       "r" (__m1));						\
+    (pl) = __m0 * __m1;							\
+  } while (0)
+#define SMUL_TIME 14
+#define UDIV_TIME 120
+#else
+#define umul_ppmm(xh, xl, m0, m1) \
+  do {									\
+    USItype __m0 = (m0), __m1 = (m1);					\
+    __asm__ ("mul %0,%2,%3"						\
+	     : "=r" ((USItype)(xh)),					\
+	       "=q" ((USItype)(xl))					\
+	     : "r" (__m0),						\
+	       "r" (__m1));						\
+    (xh) += ((((SItype) __m0 >> 31) & __m1)				\
+	     + (((SItype) __m1 >> 31) & __m0));				\
+  } while (0)
+#define UMUL_TIME 8
+#define smul_ppmm(xh, xl, m0, m1) \
+  __asm__ ("mul %0,%2,%3"						\
+	   : "=r" ((SItype)(xh)),					\
+	     "=q" ((SItype)(xl))					\
+	   : "r" (m0),							\
+	     "r" (m1))
+#define SMUL_TIME 4
+#define sdiv_qrnnd(q, r, nh, nl, d) \
+  __asm__ ("div %0,%2,%4"						\
+	   : "=r" ((SItype)(q)), "=q" ((SItype)(r))			\
+	   : "r" ((SItype)(nh)), "1" ((SItype)(nl)), "r" ((SItype)(d)))
+#define UDIV_TIME 100
+#endif
+#endif /* Power architecture variants.  */
+
+#if defined (__pyr__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("addw	%5,%1
+	addwc	%3,%0"							\
+	   : "=r" ((USItype)(sh)),					\
+	     "=&r" ((USItype)(sl))					\
+	   : "%0" ((USItype)(ah)),					\
+	     "g" ((USItype)(bh)),					\
+	     "%1" ((USItype)(al)),					\
+	     "g" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("subw	%5,%1
+	subwb	%3,%0"							\
+	   : "=r" ((USItype)(sh)),					\
+	     "=&r" ((USItype)(sl))					\
+	   : "0" ((USItype)(ah)),					\
+	     "g" ((USItype)(bh)),					\
+	     "1" ((USItype)(al)),					\
+	     "g" ((USItype)(bl)))
+/* This insn doesn't work on ancient pyramids.  */
+#define umul_ppmm(w1, w0, u, v) \
+  ({union {UDItype __ll;						\
+	   struct {USItype __h, __l;} __i;				\
+	  } __xx;							\
+  __xx.__i.__l = u;							\
+  __asm__ ("uemul %3,%0"						\
+	   : "=r" (__xx.__i.__h),					\
+	     "=r" (__xx.__i.__l)					\
+	   : "1" (__xx.__i.__l),					\
+	     "g" ((USItype)(v)));					\
+  (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
+#endif /* __pyr__ */
+
+#if defined (__ibm032__) /* RT/ROMP */  && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("a %1,%5
+	ae %0,%3"							\
+	   : "=r" ((USItype)(sh)),					\
+	     "=&r" ((USItype)(sl))					\
+	   : "%0" ((USItype)(ah)),					\
+	     "r" ((USItype)(bh)),					\
+	     "%1" ((USItype)(al)),					\
+	     "r" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("s %1,%5
+	se %0,%3"							\
+	   : "=r" ((USItype)(sh)),					\
+	     "=&r" ((USItype)(sl))					\
+	   : "0" ((USItype)(ah)),					\
+	     "r" ((USItype)(bh)),					\
+	     "1" ((USItype)(al)),					\
+	     "r" ((USItype)(bl)))
+#define umul_ppmm(ph, pl, m0, m1) \
+  do {									\
+    USItype __m0 = (m0), __m1 = (m1);					\
+    __asm__ (								\
+       "s	r2,r2
+	mts	r10,%2
+	m	r2,%3
+	m	r2,%3
+	m	r2,%3
+	m	r2,%3
+	m	r2,%3
+	m	r2,%3
+	m	r2,%3
+	m	r2,%3
+	m	r2,%3
+	m	r2,%3
+	m	r2,%3
+	m	r2,%3
+	m	r2,%3
+	m	r2,%3
+	m	r2,%3
+	m	r2,%3
+	cas	%0,r2,r0
+	mfs	r10,%1"							\
+	     : "=r" ((USItype)(ph)),					\
+	       "=r" ((USItype)(pl))					\
+	     : "%r" (__m0),						\
+		"r" (__m1)						\
+	     : "r2");							\
+    (ph) += ((((SItype) __m0 >> 31) & __m1)				\
+	     + (((SItype) __m1 >> 31) & __m0));				\
+  } while (0)
+#define UMUL_TIME 20
+#define UDIV_TIME 200
+#define count_leading_zeros(count, x) \
+  do {									\
+    if ((x) >= 0x10000)							\
+      __asm__ ("clz	%0,%1"						\
+	       : "=r" ((USItype)(count))				\
+	       : "r" ((USItype)(x) >> 16));				\
+    else								\
+      {									\
+	__asm__ ("clz	%0,%1"						\
+		 : "=r" ((USItype)(count))				\
+		 : "r" ((USItype)(x)));					\
+	(count) += 16;							\
+      }									\
+  } while (0)
+#endif
+
+#if defined (__sparc__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("addcc %r4,%5,%1
+	addx %r2,%3,%0"							\
+	   : "=r" ((USItype)(sh)),					\
+	     "=&r" ((USItype)(sl))					\
+	   : "%rJ" ((USItype)(ah)),					\
+	     "rI" ((USItype)(bh)),					\
+	     "%rJ" ((USItype)(al)),					\
+	     "rI" ((USItype)(bl))					\
+	   __CLOBBER_CC)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("subcc %r4,%5,%1
+	subx %r2,%3,%0"							\
+	   : "=r" ((USItype)(sh)),					\
+	     "=&r" ((USItype)(sl))					\
+	   : "rJ" ((USItype)(ah)),					\
+	     "rI" ((USItype)(bh)),					\
+	     "rJ" ((USItype)(al)),					\
+	     "rI" ((USItype)(bl))					\
+	   __CLOBBER_CC)
+#if defined (__sparc_v8__)
+/* Don't match immediate range because, 1) it is not often useful,
+   2) the 'I' flag thinks of the range as a 13 bit signed interval,
+   while we want to match a 13 bit interval, sign extended to 32 bits,
+   but INTERPRETED AS UNSIGNED.  */
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("umul %2,%3,%1;rd %%y,%0"					\
+	   : "=r" ((USItype)(w1)),					\
+	     "=r" ((USItype)(w0))					\
+	   : "r" ((USItype)(u)),					\
+	     "r" ((USItype)(v)))
+#define UMUL_TIME 5
+/* We might want to leave this undefined for `SuperSPARC (tm)' since
+   its implementation is crippled and often traps.  */
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  __asm__ ("mov %2,%%y;nop;nop;nop;udiv %3,%4,%0;umul %0,%4,%1;sub %3,%1,%1"\
+	   : "=&r" ((USItype)(q)),					\
+	     "=&r" ((USItype)(r))					\
+	   : "r" ((USItype)(n1)),					\
+	     "r" ((USItype)(n0)),					\
+	     "r" ((USItype)(d)))
+#define UDIV_TIME 25
+#else
+#if defined (__sparclite__)
+/* This has hardware multiply but not divide.  It also has two additional
+   instructions scan (ffs from high bit) and divscc.  */
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("umul %2,%3,%1;rd %%y,%0"					\
+	   : "=r" ((USItype)(w1)),					\
+	     "=r" ((USItype)(w0))					\
+	   : "r" ((USItype)(u)),					\
+	     "r" ((USItype)(v)))
+#define UMUL_TIME 5
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  __asm__ ("! Inlined udiv_qrnnd
+	wr	%%g0,%2,%%y	! Not a delayed write for sparclite
+	tst	%%g0
+	divscc	%3,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%%g1
+	divscc	%%g1,%4,%0
+	rd	%%y,%1
+	bl,a 1f
+	add	%1,%4,%1
+1:	! End of inline udiv_qrnnd"					\
+	   : "=r" ((USItype)(q)),					\
+	     "=r" ((USItype)(r))					\
+	   : "r" ((USItype)(n1)),					\
+	     "r" ((USItype)(n0)),					\
+	     "rI" ((USItype)(d))					\
+	   : "%g1" __AND_CLOBBER_CC)
+#define UDIV_TIME 37
+#define count_leading_zeros(count, x) \
+  __asm__ ("scan %1,0,%0"						\
+	   : "=r" ((USItype)(x))					\
+	   : "r" ((USItype)(count)))
+#else
+/* SPARC without integer multiplication and divide instructions.
+   (i.e. at least Sun4/20,40,60,65,75,110,260,280,330,360,380,470,490) */
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("! Inlined umul_ppmm
+	wr	%%g0,%2,%%y	! SPARC has 0-3 delay insn after a wr
+	sra	%3,31,%%g2	! Don't move this insn
+	and	%2,%%g2,%%g2	! Don't move this insn
+	andcc	%%g0,0,%%g1	! Don't move this insn
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,%3,%%g1
+	mulscc	%%g1,0,%%g1
+	add	%%g1,%%g2,%0
+	rd	%%y,%1"							\
+	   : "=r" ((USItype)(w1)),					\
+	     "=r" ((USItype)(w0))					\
+	   : "%rI" ((USItype)(u)),					\
+	     "r" ((USItype)(v))						\
+	   : "%g1", "%g2" __AND_CLOBBER_CC)
+#define UMUL_TIME 39		/* 39 instructions */
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  do { USItype __r;							\
+    (q) = __udiv_qrnnd (&__r, (n1), (n0), (d));				\
+    (r) = __r;								\
+  } while (0)
+extern USItype __udiv_qrnnd ();
+#define UDIV_TIME 140
+#endif /* __sparclite__ */
+#endif /* __sparc_v8__ */
+#endif /* __sparc__ */
+
+#if defined (__vax__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("addl2 %5,%1
+	adwc %3,%0"							\
+	   : "=g" ((USItype)(sh)),					\
+	     "=&g" ((USItype)(sl))					\
+	   : "%0" ((USItype)(ah)),					\
+	     "g" ((USItype)(bh)),					\
+	     "%1" ((USItype)(al)),					\
+	     "g" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("subl2 %5,%1
+	sbwc %3,%0"							\
+	   : "=g" ((USItype)(sh)),					\
+	     "=&g" ((USItype)(sl))					\
+	   : "0" ((USItype)(ah)),					\
+	     "g" ((USItype)(bh)),					\
+	     "1" ((USItype)(al)),					\
+	     "g" ((USItype)(bl)))
+#define umul_ppmm(xh, xl, m0, m1) \
+  do {									\
+    union {UDItype __ll;						\
+	   struct {USItype __l, __h;} __i;				\
+	  } __xx;							\
+    USItype __m0 = (m0), __m1 = (m1);					\
+    __asm__ ("emul %1,%2,$0,%0"						\
+	     : "=g" (__xx.__ll)						\
+	     : "g" (__m0),						\
+	       "g" (__m1));						\
+    (xh) = __xx.__i.__h; (xl) = __xx.__i.__l;				\
+    (xh) += ((((SItype) __m0 >> 31) & __m1)				\
+	     + (((SItype) __m1 >> 31) & __m0));				\
+  } while (0)
+#define sdiv_qrnnd(q, r, n1, n0, d) \
+  do {									\
+    union {DItype __ll;							\
+	   struct {SItype __l, __h;} __i;				\
+	  } __xx;							\
+    __xx.__i.__h = n1; __xx.__i.__l = n0;				\
+    __asm__ ("ediv %3,%2,%0,%1"						\
+	     : "=g" (q), "=g" (r)					\
+	     : "g" (__n1n0.ll), "g" (d));				\
+  } while (0)
+#endif /* __vax__ */
+
+#if defined (__z8000__) && W_TYPE_SIZE == 16
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("add	%H1,%H5\n\tadc	%H0,%H3"				\
+	   : "=r" ((unsigned int)(sh)),					\
+	     "=&r" ((unsigned int)(sl))					\
+	   : "%0" ((unsigned int)(ah)),					\
+	     "r" ((unsigned int)(bh)),					\
+	     "%1" ((unsigned int)(al)),					\
+	     "rQR" ((unsigned int)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("sub	%H1,%H5\n\tsbc	%H0,%H3"				\
+	   : "=r" ((unsigned int)(sh)),					\
+	     "=&r" ((unsigned int)(sl))					\
+	   : "0" ((unsigned int)(ah)),					\
+	     "r" ((unsigned int)(bh)),					\
+	     "1" ((unsigned int)(al)),					\
+	     "rQR" ((unsigned int)(bl)))
+#define umul_ppmm(xh, xl, m0, m1) \
+  do {									\
+    union {long int __ll;						\
+	   struct {unsigned int __h, __l;} __i;				\
+	  } __xx;							\
+    unsigned int __m0 = (m0), __m1 = (m1);				\
+    __asm__ ("mult	%S0,%H3"					\
+	     : "=r" (__xx.__i.__h),					\
+	       "=r" (__xx.__i.__l)					\
+	     : "%1" (__m0),						\
+	       "rQR" (__m1));						\
+    (xh) = __xx.__i.__h; (xl) = __xx.__i.__l;				\
+    (xh) += ((((signed int) __m0 >> 15) & __m1)				\
+	     + (((signed int) __m1 >> 15) & __m0));			\
+  } while (0)
+#define umul_ppmm_off(xh, xl, m0, m1) \
+  do {									\
+    union {long int __ll;						\
+	   struct {unsigned int __h, __l;} __i;				\
+	  } __xx;							\
+    __asm__ ("mult	%S0,%H3"					\
+	     : "=r" (__xx.__i.__h),					\
+	       "=r" (__xx.__i.__l)					\
+	     : "%1" (m0),						\
+	       "rQR" (m1));						\
+    (xh) = __xx.__i.__h + ((((signed int) m0 >> 15) & m1)		\
+			   + (((signed int) m1 >> 15) & m0));		\
+    (xl) = __xx.__i.__l;						\
+  } while (0)
+#endif /* __z8000__ */
+
+#endif /* __GNUC__ */
+
+
+#if !defined (umul_ppmm) && defined (__umulsidi3)
+#define umul_ppmm(ph, pl, m0, m1) \
+  {									\
+    UDWtype __ll = __umulsidi3 (m0, m1);				\
+    ph = (UWtype) (__ll >> W_TYPE_SIZE);				\
+    pl = (UWtype) __ll;							\
+  }
+#endif
+
+#if !defined (__umulsidi3)
+#define __umulsidi3(u, v) \
+  ({UWtype __hi, __lo;							\
+    umul_ppmm (__hi, __lo, u, v);					\
+    ((UDWtype) __hi << W_TYPE_SIZE) | __lo; })
+#endif
+
+/* If this machine has no inline assembler, use C macros.  */
+
+#if !defined (add_ssaaaa)
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  do {									\
+    UWtype __x;								\
+    __x = (al) + (bl);							\
+    (sh) = (ah) + (bh) + (__x < (al));					\
+    (sl) = __x;								\
+  } while (0)
+#endif
+
+#if !defined (sub_ddmmss)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  do {									\
+    UWtype __x;								\
+    __x = (al) - (bl);							\
+    (sh) = (ah) - (bh) - (__x > (al));					\
+    (sl) = __x;								\
+  } while (0)
+#endif
+
+#if !defined (umul_ppmm)
+#define umul_ppmm(w1, w0, u, v)						\
+  do {									\
+    UWtype __x0, __x1, __x2, __x3;					\
+    UHWtype __ul, __vl, __uh, __vh;					\
+									\
+    __ul = __ll_lowpart (u);						\
+    __uh = __ll_highpart (u);						\
+    __vl = __ll_lowpart (v);						\
+    __vh = __ll_highpart (v);						\
+									\
+    __x0 = (UWtype) __ul * __vl;					\
+    __x1 = (UWtype) __ul * __vh;					\
+    __x2 = (UWtype) __uh * __vl;					\
+    __x3 = (UWtype) __uh * __vh;					\
+									\
+    __x1 += __ll_highpart (__x0);/* this can't give carry */		\
+    __x1 += __x2;		/* but this indeed can */		\
+    if (__x1 < __x2)		/* did we get it? */			\
+      __x3 += __ll_B;		/* yes, add it in the proper pos. */	\
+									\
+    (w1) = __x3 + __ll_highpart (__x1);					\
+    (w0) = (__ll_lowpart (__x1) << W_TYPE_SIZE/2) + __ll_lowpart (__x0);\
+  } while (0)
+#endif
+
+/* Define this unconditionally, so it can be used for debugging.  */
+#define __udiv_qrnnd_c(q, r, n1, n0, d) \
+  do {									\
+    UWtype __d1, __d0, __q1, __q0, __r1, __r0, __m;			\
+    __d1 = __ll_highpart (d);						\
+    __d0 = __ll_lowpart (d);						\
+									\
+    __r1 = (n1) % __d1;							\
+    __q1 = (n1) / __d1;							\
+    __m = (UWtype) __q1 * __d0;						\
+    __r1 = __r1 * __ll_B | __ll_highpart (n0);				\
+    if (__r1 < __m)							\
+      {									\
+	__q1--, __r1 += (d);						\
+	if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
+	  if (__r1 < __m)						\
+	    __q1--, __r1 += (d);					\
+      }									\
+    __r1 -= __m;							\
+									\
+    __r0 = __r1 % __d1;							\
+    __q0 = __r1 / __d1;							\
+    __m = (UWtype) __q0 * __d0;						\
+    __r0 = __r0 * __ll_B | __ll_lowpart (n0);				\
+    if (__r0 < __m)							\
+      {									\
+	__q0--, __r0 += (d);						\
+	if (__r0 >= (d))						\
+	  if (__r0 < __m)						\
+	    __q0--, __r0 += (d);					\
+      }									\
+    __r0 -= __m;							\
+									\
+    (q) = (UWtype) __q1 * __ll_B | __q0;				\
+    (r) = __r0;								\
+  } while (0)
+
+/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through
+   __udiv_w_sdiv (defined in libgcc or elsewhere).  */
+#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd)
+#define udiv_qrnnd(q, r, nh, nl, d) \
+  do {									\
+    UWtype __r;								\
+    (q) = __udiv_w_sdiv (&__r, nh, nl, d);				\
+    (r) = __r;								\
+  } while (0)
+#endif
+
+/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c.  */
+#if !defined (udiv_qrnnd)
+#define UDIV_NEEDS_NORMALIZATION 1
+#define udiv_qrnnd __udiv_qrnnd_c
+#endif
+
+#if !defined (count_leading_zeros)
+extern
+#ifdef __STDC__
+const
+#endif
+unsigned char __clz_tab[];
+#define count_leading_zeros(count, x) \
+  do {									\
+    UWtype __xr = (x);							\
+    UWtype __a;								\
+									\
+    if (W_TYPE_SIZE <= 32)						\
+      {									\
+	__a = __xr < ((UWtype) 1 << 2*__BITS4)				\
+	  ? (__xr < ((UWtype) 1 << __BITS4) ? 0 : __BITS4)		\
+	  : (__xr < ((UWtype) 1 << 3*__BITS4) ?  2*__BITS4 : 3*__BITS4);\
+      }									\
+    else								\
+      {									\
+	for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8)			\
+	  if (((__xr >> __a) & 0xff) != 0)				\
+	    break;							\
+      }									\
+									\
+    (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a);		\
+  } while (0)
+/* This version gives a well-defined value for zero. */
+#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE
+#endif
+
+#if !defined (count_trailing_zeros)
+/* Define count_trailing_zeros using count_leading_zeros.  The latter might be
+   defined in asm, but if it is not, the C version above is good enough.  */
+#define count_trailing_zeros(count, x) \
+  do {									\
+    UWtype __ctz_x = (x);						\
+    UWtype __ctz_c;							\
+    count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x);			\
+    (count) = W_TYPE_SIZE - 1 - __ctz_c;				\
+  } while (0)
+#endif
+
+#ifndef UDIV_NEEDS_NORMALIZATION
+#define UDIV_NEEDS_NORMALIZATION 0
+#endif
diff --git a/stdio/memstream.c b/stdio/memstream.c
new file mode 100644
index 0000000000..704eca53b3
--- /dev/null
+++ b/stdio/memstream.c
@@ -0,0 +1,177 @@
+/* Copyright (C) 1991, 1992, 1994 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct memstream_info
+  {
+    char **buffer;
+    size_t *bufsize;
+  };
+
+/* Enlarge STREAM's buffer.  */
+static void
+DEFUN(enlarge_buffer, (stream, c),
+      register FILE *stream AND int c)
+{
+  struct memstream_info *info = (struct memstream_info *) stream->__cookie;
+  size_t need;
+
+  if (stream->__put_limit != stream->__buffer)
+    /* Record how much has actually been written into the buffer.  */
+    *info->bufsize = stream->__bufp - stream->__buffer;
+
+  if (stream->__target != -1
+      && stream->__target > *info->bufsize)
+    /* Our target (where the buffer maps to) is always zero except when
+       the user just did a SEEK_END fseek.  If he sought within the
+       buffer, we need do nothing and will zero the target below.  If he
+       sought past the end of the object, grow and zero-fill the buffer
+       up to the target address.  */
+    need = stream->__target;
+  else
+    need = *info->bufsize;
+
+  /* We always need an extra character in the buffer.  Either we are
+     writing C, or we are flushing and need to write a NUL terminator.  */
+  ++need;
+
+  if (stream->__bufsize < need)
+    {
+      /* Enlarge the buffer.  */
+      char *newbuf;
+      size_t newsize;
+      if (stream->__bufsize * 2 < need)
+	newsize = need;
+      else
+	newsize = stream->__bufsize * 2;
+      newbuf = (char *) realloc ((PTR) stream->__buffer, newsize);
+      if (newbuf == NULL)
+	{
+	  stream->__error = 1;
+	  return;
+	}
+      *info->buffer = stream->__buffer = newbuf;
+      stream->__bufsize = newsize;
+    }
+
+  stream->__target = stream->__offset = 0;
+  stream->__get_limit = stream->__bufp = stream->__buffer + *info->bufsize;
+  stream->__put_limit = stream->__buffer + stream->__bufsize;
+
+  need -= stream->__bufp - stream->__buffer + 1;
+  if (need > 0)
+    {
+      /* We are extending the buffer after an fseek; zero-fill new space.  */
+      bzero (stream->__bufp, need);
+      stream->__bufp += need;
+    }
+
+  if (c != EOF)
+    *stream->__bufp++ = (unsigned char) c;
+  else
+    *stream->__bufp = '\0';
+}
+
+/* Seek function for memstreams.
+   There is no external state to munge.  */
+
+static int
+DEFUN(seek, (cookie, pos, whence),
+      PTR cookie AND fpos_t *pos AND int whence)
+{
+  switch (whence)
+    {
+    case SEEK_SET:
+    case SEEK_CUR:
+      return 0;
+
+    case SEEK_END:
+      /* Return the position relative to the end of the object.
+	 fseek has just flushed us, so the info is consistent.  */
+      *pos += *((struct memstream_info *) cookie)->bufsize;
+      return 0;
+
+    default:
+      __libc_fatal ("memstream::seek called with bogus WHENCE\n");
+      return -1;
+    }
+}
+
+static int
+DEFUN(free_info, (cookie), PTR cookie)
+{
+#if 0
+  struct memstream_info *info = (struct memstream_info *) cookie;
+  char *buf;
+
+  buf = (char *) realloc ((PTR) *info->buffer, *info->bufsize);
+  if (buf != NULL)
+    *info->buffer = buf;
+#endif
+
+  free (cookie);
+
+  return 0;
+}
+
+/* Open a stream that writes into a malloc'd buffer that is expanded as
+   necessary.  *BUFLOC and *SIZELOC are updated with the buffer's location
+   and the number of characters written on fflush or fclose.  */
+FILE *
+DEFUN(open_memstream, (bufloc, sizeloc),
+      char **bufloc AND size_t *sizeloc)
+{
+  FILE *stream;
+  struct memstream_info *info;
+
+  if (bufloc == NULL || sizeloc == NULL)
+    {
+      errno = EINVAL;
+      return NULL;
+    }
+
+  stream = fmemopen ((char *) NULL, BUFSIZ, "w+");
+  if (stream == NULL)
+    return NULL;
+
+  info = (struct memstream_info *) malloc (sizeof (struct memstream_info));
+  if (info == NULL)
+    {
+      int save = errno;
+      (void) fclose (stream);
+      errno = save;
+      return NULL;
+    }
+
+  stream->__room_funcs.__output = enlarge_buffer;
+  stream->__io_funcs.__seek = seek;
+  stream->__io_funcs.__close = free_info;
+  stream->__cookie = (PTR) info;
+  stream->__userbuf = 1;
+
+  info->buffer = bufloc;
+  info->bufsize = sizeloc;
+
+  *bufloc = stream->__buffer;
+
+  return stream;
+}
diff --git a/stdio/mp_clz_tab.c b/stdio/mp_clz_tab.c
new file mode 100644
index 0000000000..ed1b7eebe8
--- /dev/null
+++ b/stdio/mp_clz_tab.c
@@ -0,0 +1,39 @@
+/* __clz_tab -- support for longlong.h
+
+Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
+the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if 0
+#include "gmp.h"
+#include "gmp-impl.h"
+#endif
+
+#if 0
+const
+#endif
+ unsigned char __clz_tab[] =
+{
+  0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+};
diff --git a/stdio/newstream.c b/stdio/newstream.c
new file mode 100644
index 0000000000..08feb8da6e
--- /dev/null
+++ b/stdio/newstream.c
@@ -0,0 +1,54 @@
+/* Copyright (C) 1991, 1992 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+/* Return a new, zeroed, stream.
+   You must set its cookie and io_mode.
+   The first operation will give it a buffer unless you do.
+   It will also give it the default functions unless you set the `seen' flag.
+   Returns NULL if a stream can't be created.  */
+FILE *
+DEFUN_VOID(__newstream)
+{
+  register FILE *stream;
+
+  stream = __stdio_head;
+  while (__validfp (stream))
+    stream = stream->__next;
+  if (stream == NULL)
+    {
+      /* None to reuse.  */
+      stream = (FILE *) malloc (sizeof (FILE));
+      if (stream == NULL)
+	return NULL;
+      stream->__next = __stdio_head;
+      __stdio_head = stream;
+    }
+
+  __invalidate (stream);
+  stream->__magic = _IOMAGIC;
+  stream->__offset = (fpos_t) -1;
+  stream->__target = (fpos_t) -1;
+
+  return stream;
+}
diff --git a/stdio/obstream.c b/stdio/obstream.c
new file mode 100644
index 0000000000..32f7220b59
--- /dev/null
+++ b/stdio/obstream.c
@@ -0,0 +1,187 @@
+/* Copyright (C) 1992 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdio.h>
+#include <obstack.h>
+#include <stdarg.h>
+#include <string.h>
+
+/* Output-room function for obstack streams.  */
+
+static void
+DEFUN(grow, (stream, c), FILE *stream AND int c)
+{
+  struct obstack *const obstack = (struct obstack *) stream->__cookie;
+
+  /* Move the end of the object back to include only the portion
+     of the buffer which the user has already written into.  */ 
+  obstack_blank_fast (obstack, - (stream->__put_limit - stream->__bufp));
+
+  if (stream->__target > obstack_object_size (obstack))
+    {
+      /* Our target (where the buffer maps to) is always zero except when
+	 the user just did a SEEK_END fseek.  If he sought within the
+	 buffer, we need do nothing and will zero the target below.  If he
+	 sought past the end of the object, grow and zero-fill the object
+	 up to the target address.  */
+
+      obstack_blank (obstack,
+		     stream->__target - obstack_object_size (obstack));
+      /* fseek has just flushed us, so the put limit points
+	 to the end of the written data.  */
+      bzero (stream->__put_limit,
+	     stream->__target - stream->__bufsize);
+    }
+
+  if (c != EOF)
+    obstack_1grow (obstack, (unsigned char) c);
+
+  /* The stream buffer always maps exactly to the object on the top
+     of the obstack.  The start of the buffer is the start of the object.
+     The put limit points just past the end of the object.  On fflush, the
+     obstack is sync'd so the end of the object points just past the last
+     character written to the stream.  */
+
+  stream->__target = stream->__offset = 0;
+  stream->__buffer = obstack_base (obstack);
+  stream->__bufsize = obstack_room (obstack);
+  stream->__bufp = obstack_next_free (obstack);
+  stream->__get_limit = stream->__bufp;
+
+  if (c == EOF)
+    /* This is fflush.  Make the stream buffer, the object,
+       and the characters actually written all match.  */
+    stream->__put_limit = stream->__get_limit;
+  else
+    {
+      /* Extend the buffer (and the object) to include
+	 the rest of the obstack chunk (which is unitialized).
+	 Data past bufp is undefined.  */
+      stream->__put_limit = stream->__buffer + stream->__bufsize;
+      obstack_blank_fast (obstack, stream->__put_limit - stream->__bufp);
+    }
+}
+
+/* Seek function for obstack streams.
+   There is no external state to munge.  */
+
+static int
+DEFUN(seek, (cookie, pos, whence),
+      PTR cookie AND fpos_t *pos AND int whence)
+{
+  switch (whence)
+    {
+    case SEEK_SET:
+    case SEEK_CUR:
+      return 0;
+
+    case SEEK_END:
+      /* Return the position relative to the end of the object.
+	 fseek has just flushed us, so the obstack is consistent.  */
+      *pos += obstack_object_size ((struct obstack *) cookie);
+      return 0;
+
+    default:
+      __libc_fatal ("obstream::seek called with bogus WHENCE\n");
+      return -1;
+    }
+}
+
+/* Input room function for obstack streams.
+   Only what has been written to the stream can be read back.  */
+
+static int
+DEFUN(input, (stream), FILE *stream)
+{
+  /* Re-sync with the obstack, growing the object if necessary.  */
+  grow (stream, EOF);
+
+  if (stream->__bufp < stream->__get_limit)
+    return (unsigned char) *stream->__bufp++;
+
+  stream->__eof = 1;
+  return EOF;
+}
+
+/* Initialize STREAM to talk to OBSTACK.  */
+
+static void
+DEFUN(init_obstream, (stream, obstack),
+      FILE *stream AND struct obstack *obstack)
+{
+  stream->__mode.__write = 1;
+  stream->__mode.__read = 1;
+
+  /* Input can read only what has been written.  */
+  stream->__room_funcs.__input = input;
+
+  /* Do nothing for close.  */
+  stream->__io_funcs.__close = NULL;
+
+  /* When the buffer is full, grow the obstack.  */
+  stream->__room_funcs.__output = grow;
+
+  /* Seek within the object, and extend it.  */
+  stream->__io_funcs.__seek = seek;
+  stream->__target = stream->__offset = 0;
+
+  stream->__seen = 1;
+
+  /* Don't deallocate that buffer!  */
+  stream->__userbuf = 1;
+
+  /* We don't have to initialize the buffer.
+     The first read attempt will call grow, which will do all the work.  */
+}
+
+FILE *
+open_obstack_stream (obstack)
+     struct obstack *obstack;
+{
+  register FILE *stream;
+
+  stream = __newstream ();
+  if (stream == NULL)
+    return NULL;
+
+  init_obstream (stream, obstack);
+  return stream;
+}
+
+int
+DEFUN(obstack_vprintf, (obstack, format, args),
+      struct obstack *obstack AND const char *format AND va_list args)
+{
+  FILE f;
+  bzero (&f, sizeof (f));
+  init_obstream (&f, obstack);
+  return vfprintf (&f, format, args);
+}
+
+int
+DEFUN(obstack_printf, (obstack, format),
+      struct obstack *obstack AND const char *format DOTS)
+{
+  int result;
+  va_list ap;
+  va_start (ap, format);
+  result = obstack_vprintf (obstack, format, ap);
+  va_end (ap);
+  return result;
+}
diff --git a/stdio/perror.c b/stdio/perror.c
new file mode 100644
index 0000000000..718a6f2256
--- /dev/null
+++ b/stdio/perror.c
@@ -0,0 +1,42 @@
+/* Copyright (C) 1991, 1992, 1993 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdio.h>
+#include <errno.h>
+
+extern char *_strerror_internal __P ((int, char buf[1024]));
+
+/* Print a line on stderr consisting of the text in S, a colon, a space,
+   a message describing the meaning of the contents of `errno' and a newline.
+   If S is NULL or "", the colon and space are omitted.  */
+void
+DEFUN(perror, (s), register CONST char *s)
+{
+  char buf[1024];
+  int errnum = errno;
+  CONST char *colon;
+
+  if (s == NULL || *s == '\0')
+    s = colon = "";
+  else
+    colon = ": ";
+
+  (void) fprintf (stderr, "%s%s%s\n",
+		  s, colon, _strerror_internal (errnum, buf));
+}
diff --git a/stdio/printf-prs.c b/stdio/printf-prs.c
new file mode 100644
index 0000000000..2f55dd3157
--- /dev/null
+++ b/stdio/printf-prs.c
@@ -0,0 +1,211 @@
+/* Copyright (C) 1991, 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdio.h>
+#include <printf.h>
+#include <limits.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifdef	__GNUC__
+#define	HAVE_LONGLONG
+#endif
+
+extern printf_arginfo_function *__printf_arginfo_table[];
+
+size_t
+DEFUN(parse_printf_format, (fmt, n, argtypes),
+      CONST char *fmt AND size_t n AND int *argtypes)
+{
+  register CONST char *f;
+  size_t need = 0;
+
+  for (f = strchr (fmt, '%'); f != NULL; f = strchr (f, '%'))
+    {
+      struct printf_info info;
+      printf_arginfo_function *arginfo;
+
+      ++f;
+
+      info.space = info.showsign = info.left = info.alt = info.group = 0;
+      info.pad = ' ';
+      while (*f == ' ' || *f == '+' || *f == '-' || *f == '#' || *f == '0' ||
+	     *f == '\'')
+	switch (*f++)
+	  {
+	  case ' ':
+	    info.space = 1;
+	    break;
+	  case '+':
+	    info.showsign = 1;
+	    break;
+	  case '-':
+	    info.left = 1;
+	    break;
+	  case '#':
+	    info.alt = 1;
+	    break;
+	  case '\'':
+	    info.group = 1;
+	    break;
+	  case '0':
+	    info.pad = '0';
+	    break;
+	  }
+      if (info.left)
+	info.pad = ' ';
+
+      /* Get the field width.  */
+      if (*f == '*')
+	{
+	  if (++need < n)
+	    *argtypes++ = PA_INT;
+	  info.width = INT_MIN;
+	  ++f;
+	}
+      else
+	{
+	  info.width = 0;
+	  while (isdigit(*f))
+	    {
+	      info.width *= 10;
+	      info.width += *f++ - '0';
+	    }
+	}
+
+      /* Get the precision.  */
+      /* -1 means none given; 0 means explicit 0.  */
+      info.prec = -1;
+      if (*f == '.')
+	{
+	  ++f;
+	  if (*f == '*')
+	    {
+	      /* The precision is given in an argument.  */
+	      if (++need < n)
+		*argtypes++ = PA_INT;
+	      info.prec = INT_MIN;
+	      ++f;
+	    }
+	  else if (isdigit(*f))
+	    {
+	      info.prec = 0;
+	      while (*f != '\0' && isdigit(*f))
+		{
+		  info.prec *= 10;
+		  info.prec += *f++ - '0';
+		}
+	    }
+	}
+
+      /* Check for type modifiers.  */
+      info.is_short = info.is_long = info.is_long_double = 0;
+      while (*f == 'h' || *f == 'l' || *f == 'L')
+	switch (*f++)
+	  {
+	  case 'h':
+	    /* int's are short int's.  */
+	    info.is_short = 1;
+	    break;
+	  case 'l':
+#ifdef	HAVE_LONGLONG
+	    if (info.is_long)
+	      /* A double `l' is equivalent to an `L'.  */
+	      info.is_long_double = 1;
+	    else
+#endif
+	      /* int's are long int's.  */
+	      info.is_long = 1;
+	    break;
+	  case 'L':
+	    /* double's are long double's, and int's are long long int's.  */
+	    info.is_long_double = 1;
+	    break;
+	  }
+
+      if (*f == '\0')
+	return need;
+
+      info.spec = *f++;
+
+      arginfo = __printf_arginfo_table[info.spec];
+      if (arginfo != NULL)
+	{
+	  size_t nargs
+	    = (*arginfo) (&info, need > n ? 0 : n - need, argtypes);
+	  need += nargs;
+	  argtypes += nargs;
+	}
+      else
+	{
+	  int type;
+	  switch (info.spec)
+	    {
+	    case 'i':
+	    case 'd':
+	    case 'u':
+	    case 'o':
+	    case 'X':
+	    case 'x':
+	      type = PA_INT;
+	      break;
+
+	    case 'e':
+	    case 'E':
+	    case 'f':
+	    case 'g':
+	    case 'G':
+	      type = PA_DOUBLE;
+	      break;
+
+	    case 'c':
+	      type = PA_CHAR;
+	      break;
+
+	    case 's':
+	      type = PA_STRING;
+	      break;
+
+	    case 'p':
+	      type = PA_POINTER;
+	      break;
+
+	    case 'n':
+	      type = PA_INT | PA_FLAG_PTR;
+	      break;
+
+	    default:
+	      /* No arg for an unknown spec.  */
+	      continue;
+	    }
+
+	  if (info.is_long_double)
+	    type |= PA_FLAG_LONG_DOUBLE;
+	  if (info.is_long)
+	    type |= PA_FLAG_LONG;
+	  if (info.is_short)
+	    type |= PA_FLAG_SHORT;
+
+	  if (++need < n)
+	    *argtypes++ = type;
+	}
+    }
+
+  return need;
+}
diff --git a/stdio/printf.c b/stdio/printf.c
new file mode 100644
index 0000000000..9cdae768ae
--- /dev/null
+++ b/stdio/printf.c
@@ -0,0 +1,37 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+
+/* Write formatted output to stdout from the format string FORMAT.  */
+/* VARARGS1 */
+int
+DEFUN(printf, (format), CONST char *format DOTS)
+{
+  va_list arg;
+  int done;
+
+  va_start(arg, format);
+  done = vprintf(format, arg);
+  va_end(arg);
+
+  return done;
+}
diff --git a/stdio/printf.h b/stdio/printf.h
new file mode 100644
index 0000000000..c369222281
--- /dev/null
+++ b/stdio/printf.h
@@ -0,0 +1,114 @@
+/* Copyright (C) 1991, 1992, 1993, 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the, 1992 Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#ifndef	_PRINTF_H
+
+#define	_PRINTF_H	1
+#include <features.h>
+
+__BEGIN_DECLS
+
+#define	__need_FILE
+#include <stdio.h>
+#define	__need_size_t
+#include <stddef.h>
+
+#include <stdarg.h>		/* Need va_list.  */
+
+
+struct printf_info
+{
+  int prec;			/* Precision.  */
+  int width;			/* Width.  */
+  unsigned char spec;		/* Format letter.  */
+  unsigned int is_long_double:1;/* L flag.  */
+  unsigned int is_short:1;	/* h flag.  */
+  unsigned int is_long:1;	/* l flag.  */
+  unsigned int alt:1;		/* # flag.  */
+  unsigned int space:1;		/* Space flag.  */
+  unsigned int left:1;		/* - flag.  */
+  unsigned int showsign:1;	/* + flag.  */
+  unsigned int group:1;		/* ' flag.  */
+  char pad;			/* Padding character.  */
+};
+
+
+/* Type of a printf specifier-handler function.
+   STREAM is the FILE on which to write output.
+   INFO gives information about the format specification.
+   Arguments can be read from ARGS.
+   The function should return the number of characters written,
+   or -1 for errors.  */
+
+typedef int printf_function __P ((FILE * __stream,
+				  __const struct printf_info * __info,
+				  va_list * __args));
+typedef int printf_arginfo_function __P ((__const struct printf_info * __info,
+					  size_t __n,
+					  int *__argtypes));
+
+/* Register FUNC to be called to format SPEC specifiers.
+   ARGINFO, if not NULL, is a function used by `parse_printf_format'
+   to determine how many arguments a SPEC conversion requires,
+   and what their types are.  */
+extern int register_printf_function __P ((int __spec, printf_function __func,
+					  printf_arginfo_function __arginfo));
+
+/* Parse FMT, and fill in N elements of ARGTYPES with the
+   types needed for the conversions FMT specifies.  Returns
+   the number of arguments required by FMT.
+
+   The ARGINFO function registered with a user-defined format is passed a
+   `struct printf_info' describing the format spec being parsed.  A width
+   or precision of INT_MIN means a `*' was used to indicate that the
+   width/precision will come from an arg.  The function should fill in the
+   array it is passed with the types of the arguments it wants, and return
+   the number of arguments it wants.  */
+
+extern size_t parse_printf_format __P ((__const char *__fmt,
+					size_t __n,
+					int *__argtypes));
+
+/* Codes returned by `parse_printf_format' for basic types.
+
+   These values cover all the standard format specifications.
+   Users can add new values after PA_LAST for their own types.  */
+
+enum
+{				/* C type: */
+  PA_INT,			/* int */
+  PA_CHAR,			/* int, cast to char */
+  PA_STRING,			/* const char *, a '\0'-terminated string */
+  PA_POINTER,			/* void * */
+  PA_FLOAT,			/* float */
+  PA_DOUBLE,			/* double */
+  PA_LAST
+};
+
+/* Flag bits that can be set in a type returned by `parse_printf_format'.  */
+#define	PA_FLAG_MASK		0xff00
+#define	PA_FLAG_LONG_LONG	(1 << 8)
+#define	PA_FLAG_LONG_DOUBLE	PA_FLAG_LONG_LONG
+#define	PA_FLAG_LONG		(1 << 9)
+#define	PA_FLAG_SHORT		(1 << 10)
+#define	PA_FLAG_PTR		(1 << 11)
+
+
+__END_DECLS
+
+#endif /* printf.h  */
diff --git a/stdio/printf_fp.c b/stdio/printf_fp.c
new file mode 100644
index 0000000000..ddf025721b
--- /dev/null
+++ b/stdio/printf_fp.c
@@ -0,0 +1,991 @@
+/* Floating point output for `printf'.
+Copyright (C) 1995 Free Software Foundation, Inc.
+Written by Ulrich Drepper.
+
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.	 If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#ifdef USE_IN_LIBIO
+#  include <libioP.h>
+#else
+#  include <stdio.h>
+#endif
+#include <alloca.h>
+#include <ansidecl.h>
+#include <ctype.h>
+#include <float.h>
+#include <gmp-mparam.h>
+#include <gmp.h>
+#include <gmp-impl.h>
+#include <longlong.h>
+#include <localeinfo.h>
+#include <math.h>
+#include <printf.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+/* #define NDEBUG 1 */
+#include <assert.h>
+
+/* This defines make it possible to use the same code for GNU C library and
+   the GNU I/O library.	 */
+#ifdef USE_IN_LIBIO
+#  define PUT(f, s, n) _IO_sputn (f, s, n)
+#  define PAD(f, c, n) _IO_padn (f, c, n)
+/* We use this file GNU C library and GNU I/O library.	So make
+   names equal.	 */
+#  undef putc
+#  define putc(c, f) _IO_putc (c, f)
+#  define size_t     _IO_size_t
+#  define FILE	     _IO_FILE
+#else	/* ! USE_IN_LIBIO */
+#  define PUT(f, s, n) fwrite (s, 1, n, f)
+#  define PAD(f, c, n) __printf_pad (f, c, n)
+ssize_t __printf_pad __P ((FILE *, char pad, int n)); /* In vfprintf.c.  */
+#endif	/* USE_IN_LIBIO */
+
+/* Macros for doing the actual output.  */
+
+#define outchar(ch)							      \
+  do									      \
+    {									      \
+      register CONST int outc = (ch);					      \
+      if (putc (outc, fp) == EOF)					      \
+	return -1;							      \
+      ++done;								      \
+    } while (0)
+
+#define PRINT(ptr, len)							      \
+  do									      \
+    {									      \
+      register size_t outlen = (len);					      \
+      if (len > 20)							      \
+	{								      \
+	  if (PUT (fp, ptr, outlen) != outlen)				      \
+	    return -1;							      \
+	  ptr += outlen;						      \
+	  done += outlen;						      \
+	}								      \
+      else								      \
+	{								      \
+	  while (outlen-- > 0)						      \
+	    outchar (*ptr++);						      \
+	}								      \
+    } while (0)
+
+#define PADN(ch, len)							      \
+  do									      \
+    {									      \
+      if (PAD (fp, ch, len) != len)					      \
+	return -1;							      \
+      done += len;							      \
+    }									      \
+  while (0)
+
+/* We use the GNU MP library to handle large numbers.
+
+   An MP variable occupies a varying number of entries in its array.  We keep
+   track of this number for efficiency reasons.  Otherwise we would always
+   have to process the whole array.  */
+#define MPN_VAR(name) mp_limb *name; mp_size_t name##size
+
+#define MPN_ASSIGN(dst,src)						      \
+  memcpy (dst, src, (dst##size = src##size) * sizeof (mp_limb))
+#define MPN_GE(u,v) \
+  (u##size > v##size || (u##size == v##size && __mpn_cmp (u, v, u##size) >= 0))
+
+extern int __isinfl (long double), __isnanl (long double);
+
+extern mp_size_t __mpn_extract_double (mp_ptr res_ptr, mp_size_t size,
+				       int *expt, int *is_neg,
+				       double value);
+extern mp_size_t __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
+					    int *expt, int *is_neg,
+					    long double value);
+
+#include "fpioconst.h"
+
+
+static unsigned int guess_grouping (unsigned int intdig_max,
+				    const char *grouping, wchar_t sepchar);
+static char *group_number (char *buf, char *bufend, unsigned int intdig_no,
+			   const char *grouping, wchar_t thousands_sep);
+
+
+int
+__printf_fp (fp, info, args)
+     FILE *fp;
+     const struct printf_info *info;
+     va_list *args;
+{
+  /* The floating-point value to output.  */
+  union
+    {
+      double dbl;
+      LONG_DOUBLE ldbl;
+    }
+  fpnum;
+
+  /* Locale-dependent representation of decimal point.	*/
+  wchar_t decimal;
+
+  /* Locale-dependent thousands separator and grouping specification.  */
+  wchar_t thousands_sep;
+  const char *grouping;
+
+  /* "NaN" or "Inf" for the special cases.  */
+  CONST char *special = NULL;
+
+  /* We need just a few limbs for the input before shifting to the right
+     position.	*/
+  mp_limb fp_input[(LDBL_MANT_DIG + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB];
+  /* We need to shift the contents of fp_input by this amount of bits.	*/
+  int to_shift;
+
+  /* The significant of the floting-point value in question  */
+  MPN_VAR(frac);
+  /* and the exponent.	*/
+  int exponent;
+  /* Sign of the exponent.  */
+  int expsign = 0;
+  /* Sign of float number.  */
+  int is_neg = 0;
+
+  /* Scaling factor.  */
+  MPN_VAR(scale);
+
+  /* Temporary bignum value.  */
+  MPN_VAR(tmp);
+
+  /* Digit which is result of last hack_digit() call.  */
+  int digit;
+
+  /* The type of output format that will be used: 'e'/'E' or 'f'.  */
+  int type;
+
+  /* Counter for number of written characters.	*/
+  int done = 0;
+
+  /* General helper (carry limb).  */
+  mp_limb cy;
+
+  char hack_digit (void)
+    {
+      mp_limb hi;
+
+      if (expsign != 0 && type == 'f' && exponent-- > 0)
+	hi = 0;
+      else if (scalesize == 0)
+	{
+	  hi = frac[fracsize - 1];
+	  cy = __mpn_mul_1 (frac, frac, fracsize - 1, 10);
+	  frac[fracsize - 1] = cy;
+	}
+      else
+	{
+	  if (fracsize < scalesize)
+	    hi = 0;
+	  else
+	    {
+	      hi = __mpn_divmod (tmp, frac, fracsize, scale, scalesize);
+	      tmp[fracsize - scalesize] = hi;
+	      hi = tmp[0];
+
+	      fracsize = __mpn_normal_size (frac, scalesize);
+	      if (fracsize == 0)
+		{
+		  /* We're not prepared for an mpn variable with zero
+		     limbs.  */
+		  fracsize = 1;
+		  return '0' + hi;
+		}
+	    }
+
+	  cy = __mpn_mul_1 (frac, frac, fracsize, 10);
+	  if (cy != 0)
+	    frac[fracsize++] = cy;
+	}
+
+      return '0' + hi;
+    }
+
+
+  /* Figure out the decimal point character.  */
+  if (mbtowc (&decimal, _numeric_info->decimal_point,
+	      strlen (_numeric_info->decimal_point)) <= 0)
+    decimal = (wchar_t) *_numeric_info->decimal_point;
+
+
+  if (info->group)
+    {
+      grouping = _numeric_info->grouping; /* Cache the grouping info array.  */
+      if (*grouping <= 0 || *grouping == CHAR_MAX)
+	grouping = NULL;
+      else
+	{
+	  /* Figure out the thousands seperator character.  */
+	  if (mbtowc (&thousands_sep, _numeric_info->thousands_sep,
+		      strlen (_numeric_info->thousands_sep)) <= 0)
+	    thousands_sep = (wchar_t) *_numeric_info->thousands_sep;
+	  if (thousands_sep == L'\0')
+	    grouping = NULL;
+	}
+    }
+  else
+    grouping = NULL;
+
+  /* Fetch the argument value.	*/
+  if (info->is_long_double && sizeof (long double) > sizeof (double))
+    {
+      fpnum.ldbl = va_arg (*args, LONG_DOUBLE);
+
+      /* Check for special values: not a number or infinity.  */
+      if (__isnanl (fpnum.ldbl))
+	{
+	  special = "NaN";
+	  is_neg = 0;
+	}
+      else if (__isinfl (fpnum.ldbl))
+	{
+	  special = "Inf";
+	  is_neg = fpnum.ldbl < 0;
+	}
+      else
+	{
+	  fracsize = __mpn_extract_long_double (fp_input,
+						(sizeof (fp_input) /
+						 sizeof (fp_input[0])), 
+						&exponent, &is_neg,
+						fpnum.ldbl);
+	  to_shift = 1 + fracsize * BITS_PER_MP_LIMB - LDBL_MANT_DIG;
+	}
+    }
+  else
+    {
+      fpnum.dbl = va_arg (*args, double);
+
+      /* Check for special values: not a number or infinity.  */
+      if (__isnan (fpnum.dbl))
+	{
+	  special = "NaN";
+	  is_neg = 0;
+	}
+      else if (__isinf (fpnum.dbl))
+	{
+	  special = "Inf";
+	  is_neg = fpnum.dbl < 0;
+	}
+      else
+	{
+	  fracsize = __mpn_extract_double (fp_input,
+					   (sizeof (fp_input)
+					    / sizeof (fp_input[0])),
+					   &exponent, &is_neg, fpnum.dbl);
+	  to_shift = 1 + fracsize * BITS_PER_MP_LIMB - DBL_MANT_DIG;
+	}
+    }
+
+  if (special)
+    {
+      int width = info->prec > info->width ? info->prec : info->width;
+
+      if (is_neg || info->showsign || info->space)
+	--width;
+      width -= 3;
+
+      if (!info->left && width > 0)
+	PADN (' ', width);
+
+      if (is_neg)
+	outchar ('-');
+      else if (info->showsign)
+	outchar ('+');
+      else if (info->space)
+	outchar (' ');
+
+      PRINT (special, 3);
+
+      if (info->left && width > 0)
+	PADN (' ', width);
+
+      return done;
+    }
+
+
+  /* We need three multiprecision variables.  Now that we have the exponent
+     of the number we can allocate the needed memory.  It would be more
+     efficient to use variables of the fixed maximum size but because this
+     would be really big it could lead to memory problems.  */
+  {
+    mp_size_t bignum_size = ((ABS (exponent) + BITS_PER_MP_LIMB - 1)
+			     / BITS_PER_MP_LIMB + 3) * sizeof (mp_limb);
+    frac = (mp_limb *) alloca (bignum_size);
+    tmp = (mp_limb *) alloca (bignum_size);
+    scale = (mp_limb *) alloca (bignum_size);
+  }
+
+  /* We now have to distinguish between numbers with positive and negative
+     exponents because the method used for the one is not applicable/efficient
+     for the other.  */
+  scalesize = 0;
+  if (exponent > 2)
+    {
+      /* |FP| >= 1.0.  */
+      int scaleexpo = 0;
+      int explog = LDBL_MAX_10_EXP_LOG;
+      int exp10 = 0;
+      const struct mp_power *tens = &_fpioconst_pow10[explog + 1];
+      int cnt_h, cnt_l, i;
+
+      if ((exponent + to_shift) % BITS_PER_MP_LIMB == 0)
+	{
+	  MPN_COPY_DECR (frac + (exponent + to_shift) / BITS_PER_MP_LIMB,
+			 fp_input, fracsize);
+	  fracsize += (exponent + to_shift) / BITS_PER_MP_LIMB;
+	}
+      else
+	{
+	  cy = __mpn_lshift (frac + (exponent + to_shift) / BITS_PER_MP_LIMB,
+			     fp_input, fracsize,
+			     (exponent + to_shift) % BITS_PER_MP_LIMB);
+	  fracsize += (exponent + to_shift) / BITS_PER_MP_LIMB;
+	  if (cy)
+	    frac[fracsize++] = cy;
+	}
+      MPN_ZERO (frac, (exponent + to_shift) / BITS_PER_MP_LIMB);
+
+      assert (tens > &_fpioconst_pow10[0]);
+      do
+	{
+	  --tens;
+
+	  /* The number of the product of two binary numbers with n and m
+	     bits respectively has m+n or m+n-1 bits.	*/
+	  if (exponent >= scaleexpo + tens->p_expo - 1)
+	    {
+	      if (scalesize == 0)
+		MPN_ASSIGN (tmp, tens->array);
+	      else
+		{
+		  cy = __mpn_mul (tmp, scale, scalesize,
+				  tens->array + 2, tens->arraysize - 2);
+		  tmpsize = scalesize + tens->arraysize - 2;
+		  if (cy == 0)
+		    --tmpsize;
+		}
+
+	      if (MPN_GE (frac, tmp))
+		{
+		  int cnt;
+		  MPN_ASSIGN (scale, tmp);
+		  count_leading_zeros (cnt, scale[scalesize - 1]);
+		  scaleexpo = (scalesize - 2) * BITS_PER_MP_LIMB - cnt - 1;
+		  exp10 |= 1 << explog;
+		}
+	    }
+	  --explog;
+	}
+      while (tens > &_fpioconst_pow10[0]);
+      exponent = exp10;
+
+      /* Optimize number representations.  We want to represent the numbers
+	 with the lowest number of bytes possible without losing any
+	 bytes. Also the highest bit in the scaling factor has to be set
+	 (this is a requirement of the MPN division routines).  */
+      if (scalesize > 0)
+	{
+	  /* Determine minimum number of zero bits at the end of
+	     both numbers.  */
+	  for (i = 0; scale[i] == 0 && frac[i] == 0; i++)
+	    ;
+
+	  /* Determine number of bits the scaling factor is misplaced.	*/
+	  count_leading_zeros (cnt_h, scale[scalesize - 1]);
+
+	  if (cnt_h == 0)
+	    {
+	      /* The highest bit of the scaling factor is already set.	So
+		 we only have to remove the trailing empty limbs.  */
+	      if (i > 0)
+		{
+		  MPN_COPY_INCR (scale, scale + i, scalesize - i);
+		  scalesize -= i;
+		  MPN_COPY_INCR (frac, frac + i, fracsize - i);
+		  fracsize -= i;
+		}
+	    }
+	  else
+	    {
+	      if (scale[i] != 0)
+		{
+		  count_trailing_zeros (cnt_l, scale[i]);
+		  if (frac[i] != 0)
+		    {
+		      int cnt_l2;
+		      count_trailing_zeros (cnt_l2, frac[i]);
+		      if (cnt_l2 < cnt_l)
+			cnt_l = cnt_l2;
+		    }
+		}
+	      else
+		count_trailing_zeros (cnt_l, frac[i]);
+
+	      /* Now shift the numbers to their optimal position.  */
+	      if (i == 0 && BITS_PER_MP_LIMB - cnt_h > cnt_l)
+		{
+		  /* We cannot save any memory.	 So just roll both numbers
+		     so that the scaling factor has its highest bit set.  */
+
+		  (void) __mpn_lshift (scale, scale, scalesize, cnt_h);
+		  cy = __mpn_lshift (frac, frac, fracsize, cnt_h);
+		  if (cy != 0)
+		    frac[fracsize++] = cy;
+		}
+	      else if (BITS_PER_MP_LIMB - cnt_h <= cnt_l)
+		{
+		  /* We can save memory by removing the trailing zero limbs
+		     and by packing the non-zero limbs which gain another
+		     free one. */
+
+		  (void) __mpn_rshift (scale, scale + i, scalesize - i,
+				       BITS_PER_MP_LIMB - cnt_h);
+		  scalesize -= i + 1;
+		  (void) __mpn_rshift (frac, frac + i, fracsize - i,
+				       BITS_PER_MP_LIMB - cnt_h);
+		  fracsize -= frac[fracsize - i - 1] == 0 ? i + 1 : i;
+		}
+	      else
+		{
+		  /* We can only save the memory of the limbs which are zero.
+		     The non-zero parts occupy the same number of limbs.  */
+
+		  (void) __mpn_rshift (scale, scale + (i - 1),
+				       scalesize - (i - 1),
+				       BITS_PER_MP_LIMB - cnt_h);
+		  scalesize -= i;
+		  (void) __mpn_rshift (frac, frac + (i - 1),
+				       fracsize - (i - 1),
+				       BITS_PER_MP_LIMB - cnt_h);
+		  fracsize -= frac[fracsize - (i - 1) - 1] == 0 ? i : i - 1;
+		}
+	    }
+	}
+    }
+  else if (exponent < 0)
+    {
+      /* |FP| < 1.0.  */
+      int exp10 = 0;
+      int explog = LDBL_MAX_10_EXP_LOG;
+      const struct mp_power *tens = &_fpioconst_pow10[explog + 1];
+      mp_size_t used_limbs = fracsize - 1;
+
+      /* Now shift the input value to its right place.	*/
+      cy = __mpn_lshift (frac, fp_input, fracsize, to_shift);
+      frac[fracsize++] = cy; 
+      assert (cy == 1 || (frac[fracsize - 2] == 0 && frac[0] == 0));
+
+      expsign = 1;
+      exponent = -exponent;
+
+      assert (tens != &_fpioconst_pow10[0]);
+      do
+	{
+	  --tens;
+
+	  if (exponent >= tens->m_expo)
+	    {
+	      int i, incr, cnt_h, cnt_l;
+	      mp_limb topval[2];
+
+	      /* The __mpn_mul function expects the first argument to be
+		 bigger than the second.  */
+	      if (fracsize < tens->arraysize - 2)
+		cy = __mpn_mul (tmp, &tens->array[2], tens->arraysize - 2,
+				frac, fracsize);
+	      else
+		cy = __mpn_mul (tmp, frac, fracsize,
+				&tens->array[2], tens->arraysize - 2);
+	      tmpsize = fracsize + tens->arraysize - 2;
+	      if (cy == 0)
+		--tmpsize;
+
+	      count_leading_zeros (cnt_h, tmp[tmpsize - 1]); 
+	      incr = (tmpsize - fracsize) * BITS_PER_MP_LIMB
+		     + BITS_PER_MP_LIMB - 1 - cnt_h;
+
+	      assert (incr <= tens->p_expo);
+
+	      /* If we increased the exponent by exactly 3 we have to test
+		 for overflow.	This is done by comparing with 10 shifted
+		 to the right position.	 */
+	      if (incr == exponent + 3)
+		if (cnt_h <= BITS_PER_MP_LIMB - 4)
+		  {
+		    topval[0] = 0;
+		    topval[1] = 10 << (BITS_PER_MP_LIMB - 4 - cnt_h);
+		  }
+		else
+		  {
+		    topval[0] = 10 << (BITS_PER_MP_LIMB - 4);
+		    topval[1] = 0;
+		    (void) __mpn_lshift (topval, topval, 2,
+					 BITS_PER_MP_LIMB - cnt_h);
+		  }
+
+	      /* We have to be careful when multiplying the last factor.
+		 If the result is greater than 1.0 be have to test it
+		 against 10.0.  If it is greater or equal to 10.0 the
+		 multiplication was not valid.  This is because we cannot
+		 determine the number of bits in the result in advance.  */
+	      if (incr < exponent + 3
+		  || (incr == exponent + 3 &&
+		      (tmp[tmpsize - 1] < topval[1]
+		       || (tmp[tmpsize - 1] == topval[1]
+			   && tmp[tmpsize - 2] < topval[0]))))
+		{
+		  /* The factor is right.  Adapt binary and decimal
+		     exponents.	 */ 
+		  exponent -= incr;
+		  exp10 |= 1 << explog;
+
+		  /* If this factor yields a number greater or equal to
+		     1.0, we must not shift the non-fractional digits down. */
+		  if (exponent < 0)
+		    cnt_h += -exponent;
+
+		  /* Now we optimize the number representation.	 */
+		  for (i = 0; tmp[i] == 0; ++i);
+		  if (cnt_h == BITS_PER_MP_LIMB - 1)
+		    {
+		      MPN_COPY (frac, tmp + i, tmpsize - i);
+		      fracsize = tmpsize - i;
+		    }
+		  else
+		    {
+		      count_trailing_zeros (cnt_l, tmp[i]);
+
+		      /* Now shift the numbers to their optimal position.  */
+		      if (i == 0 && BITS_PER_MP_LIMB - 1 - cnt_h > cnt_l)
+			{
+			  /* We cannot save any memory.	 Just roll the
+			     number so that the leading digit is in a
+			     seperate limb.  */
+
+			  cy = __mpn_lshift (frac, tmp, tmpsize, cnt_h + 1);
+			  fracsize = tmpsize + 1;
+			  frac[fracsize - 1] = cy;
+			}
+		      else if (BITS_PER_MP_LIMB - 1 - cnt_h <= cnt_l)
+			{
+			  (void) __mpn_rshift (frac, tmp + i, tmpsize - i,
+					       BITS_PER_MP_LIMB - 1 - cnt_h);
+			  fracsize = tmpsize - i;
+			}
+		      else
+			{
+			  /* We can only save the memory of the limbs which
+			     are zero.	The non-zero parts occupy the same
+			     number of limbs.  */
+
+			  (void) __mpn_rshift (frac, tmp + (i - 1),
+					       tmpsize - (i - 1),
+					       BITS_PER_MP_LIMB - 1 - cnt_h);
+			  fracsize = tmpsize - (i - 1);
+			}
+		    }
+		  used_limbs = fracsize - 1;
+		}
+	    }
+	  --explog;
+	}
+      while (tens != &_fpioconst_pow10[1] && exponent > 0);
+      /* All factors but 10^-1 are tested now.	*/
+      if (exponent > 0)
+	{
+	  cy = __mpn_mul_1 (tmp, frac, fracsize, 10);
+	  tmpsize = fracsize;
+	  assert (cy == 0 || tmp[tmpsize - 1] < 20);
+
+	  (void) __mpn_rshift (frac, tmp, tmpsize, MIN (4, exponent));
+	  fracsize = tmpsize;
+	  exp10 |= 1;
+	  assert (frac[fracsize - 1] < 10);
+	}
+      exponent = exp10;
+    }
+  else
+    {
+      /* This is a special case.  We don't need a factor because the
+	 numbers are in the range of 0.0 <= fp < 8.0.  We simply
+	 shift it to the right place and divide it by 1.0 to get the
+	 leading digit.	 (Of course this division is not really made.)	*/
+      assert (0 <= exponent && exponent < 3 &&
+	      exponent + to_shift < BITS_PER_MP_LIMB);
+
+      /* Now shift the input value to its right place.	*/
+      cy = __mpn_lshift (frac, fp_input, fracsize, (exponent + to_shift));
+      frac[fracsize++] = cy; 
+      exponent = 0;
+    }
+
+  {
+    int width = info->width;
+    char *buffer, *startp, *cp;
+    int chars_needed;
+    int expscale;
+    int intdig_max, intdig_no = 0;
+    int fracdig_min, fracdig_max, fracdig_no = 0;
+    int dig_max;
+    int significant;
+
+    if (tolower (info->spec) == 'e')
+      {
+	type = info->spec;
+	intdig_max = 1;
+	fracdig_min = fracdig_max = info->prec < 0 ? 6 : info->prec;
+	chars_needed = 1 + 1 + fracdig_max + 1 + 1 + 4;
+	/*	       d   .	 ddd	     e	 +-  ddd  */
+	dig_max = INT_MAX;		/* Unlimited.  */
+	significant = 1;		/* Does not matter here.  */
+      }
+    else if (info->spec == 'f')
+      {
+	type = 'f';
+	fracdig_min = fracdig_max = info->prec < 0 ? 6 : info->prec;
+	if (expsign == 0)
+	  {
+	    intdig_max = exponent + 1;
+	    /* This can be really big!	*/  /* XXX Maybe malloc if too big? */
+	    chars_needed = exponent + 1 + 1 + fracdig_max;
+	  }
+	else
+	  {
+	    intdig_max = 1;
+	    chars_needed = 1 + 1 + fracdig_max;
+	  }
+	dig_max = INT_MAX;		/* Unlimited.  */
+	significant = 1;		/* Does not matter here.  */
+      }
+    else
+      {
+	dig_max = info->prec < 0 ? 6 : (info->prec == 0 ? 1 : info->prec);
+	if ((expsign == 0 && exponent >= dig_max)
+	    || (expsign != 0 && exponent > 4))
+	  {
+	    type = isupper (info->spec) ? 'E' : 'e';
+	    fracdig_max = dig_max - 1;
+	    intdig_max = 1;
+	    chars_needed = 1 + 1 + fracdig_max + 1 + 1 + 4;
+	  }
+	else
+	  {
+	    type = 'f';
+	    intdig_max = expsign == 0 ? exponent + 1 : 0;
+	    fracdig_max = dig_max - intdig_max;
+	    /* We need space for the significant digits and perhaps for
+	       leading zeros when < 1.0.  Pessimistic guess: dig_max.  */
+	    chars_needed = dig_max + dig_max + 1;
+	  }
+	fracdig_min = info->alt ? fracdig_max : 0;
+	significant = 0;		/* We count significant digits.	 */
+      }
+
+    if (grouping)
+      /* Guess the number of groups we will make, and thus how
+	 many spaces we need for separator characters.  */
+      chars_needed += guess_grouping (intdig_max, grouping, thousands_sep);
+
+    /* Allocate buffer for output.  We need two more because while rounding
+       it is possible that we need two more characters in front of all the
+       other output.  */
+    buffer = alloca (2 + chars_needed);
+    cp = startp = buffer + 2;	/* Let room for rounding.  */ 
+
+    /* Do the real work: put digits in allocated buffer.  */
+    if (expsign == 0 || type != 'f')
+      {
+	assert (expsign == 0 || intdig_max == 1);
+	while (intdig_no < intdig_max)
+	  {
+	    ++intdig_no;
+	    *cp++ = hack_digit ();
+	  }
+	significant = 1;
+	if (info->alt
+	    || fracdig_min > 0
+	    || (fracdig_max > 0 && (fracsize > 1 || frac[0] != 0)))
+	  *cp++ = decimal;
+      }
+    else
+      {
+	/* |fp| < 1.0 and the selected type is 'f', so put "0."
+	   in the buffer.  */
+	*cp++ = '0';
+	--exponent;
+	*cp++ = decimal;
+      }
+
+    /* Generate the needed number of fractional digits.	 */
+    while (fracdig_no < fracdig_min
+	   || (fracdig_no < fracdig_max && (fracsize > 1 || frac[0] != 0)))
+      {
+	++fracdig_no;
+	*cp = hack_digit ();
+	if (*cp != '0')
+	  significant = 1;
+	else if (significant == 0)
+	  {
+	    ++fracdig_max;
+	    if (fracdig_min > 0)
+	      ++fracdig_min;
+	  }
+	++cp;
+      }
+
+    /* Do rounding.  */
+    digit = hack_digit ();
+    if (digit > '4')
+      {
+	char *tp = cp;
+
+	if (digit == '5')
+	  /* This is the critical case.	 */
+	  if (fracsize == 1 && frac[0] == 0)
+	    /* Rest of the number is zero -> round to even.
+	       (IEEE 754-1985 4.1 says this is the default rounding.)  */
+	    if ((*(cp - 1) & 1) == 0)
+	      goto do_expo;
+
+	if (fracdig_no > 0)
+	  {
+	    /* Process fractional digits.  Terminate if not rounded or
+	       radix character is reached.  */
+	    while (*--tp != decimal && *tp == '9')
+	      *tp = '0';
+	    if (*tp != decimal)
+	      /* Round up.  */
+	      (*tp)++;
+	  }
+
+	if (fracdig_no == 0 || *tp == decimal)
+	  {
+	    /* Round the integer digits.  */
+	    if (*(tp - 1) == decimal)
+	      --tp;
+
+	    while (--tp >= startp && *tp == '9')
+	      *tp = '0';
+
+	    if (tp >= startp)
+	      /* Round up.  */
+	      (*tp)++;
+	    else
+	      /* It is more citical.  All digits were 9's.  */
+	      {
+		if (type != 'f')
+		  {
+		    *startp = '1';
+		    exponent += expsign == 0 ? 1 : -1;
+		  }
+		else if (intdig_no == dig_max)
+		  {
+		    /* This is the case where for type %g the number fits
+		       really in the range for %f output but after rounding
+		       the number of digits is too big.	 */
+		    *--startp = decimal;
+		    *--startp = '1';
+
+		    if (info->alt || fracdig_no > 0)
+		      {
+			/* Overwrite the old radix character.  */
+			startp[intdig_no + 2] = '0';
+			++fracdig_no;
+		      }
+
+		    fracdig_no += intdig_no;
+		    intdig_no = 1;
+		    fracdig_max = intdig_max - intdig_no;
+		    ++exponent;
+		    /* Now we must print the exponent.	*/
+		    type = isupper (info->spec) ? 'E' : 'e';
+		  }
+		else
+		  {
+		    /* We can simply add another another digit before the
+		       radix.  */
+		    *--startp = '1';
+		    ++intdig_no;
+		  }
+
+		/* While rounding the number of digits can change.
+		   If the number now exceeds the limits remove some
+		   fractional digits.  */
+		if (intdig_no + fracdig_no > dig_max)
+		  {
+		    cp -= intdig_no + fracdig_no - dig_max;
+		    fracdig_no -= intdig_no + fracdig_no - dig_max;
+		  }
+	      }
+	  }
+      }
+
+  do_expo:
+    /* Now remove unnecessary '0' at the end of the string.  */
+    while (fracdig_no > fracdig_min && *(cp - 1) == '0')
+      {
+	--cp;
+	--fracdig_no;
+      }
+    /* If we eliminate all fractional digits we perhaps also can remove
+       the radix character.  */
+    if (fracdig_no == 0 && !info->alt && *(cp - 1) == decimal)
+      --cp;
+
+    if (grouping)
+      /* Add in separator characters, overwriting the same buffer.  */
+      cp = group_number (startp, cp, intdig_no, grouping, thousands_sep);
+
+    /* Write the exponent if it is needed.  */
+    if (type != 'f')
+      {
+	*cp++ = type;
+	*cp++ = expsign ? '-' : '+';
+
+	/* Find the magnitude of the exponent.	*/
+	expscale = 10;
+	while (expscale <= exponent)
+	  expscale *= 10;
+
+	if (exponent < 10)
+	  /* Exponent always has at least two digits.  */
+	  *cp++ = '0';
+	else
+	  do
+	    {
+	      expscale /= 10;
+	      *cp++ = '0' + (exponent / expscale);
+	      exponent %= expscale;
+	    }
+	  while (expscale > 10);
+	*cp++ = '0' + exponent;
+      }
+
+    /* Compute number of characters which must be filled with the padding
+       character.  */ 
+    if (is_neg || info->showsign || info->space)
+      --width;
+    width -= cp - startp;
+
+    if (!info->left && info->pad != '0' && width > 0)
+      PADN (info->pad, width);
+
+    if (is_neg)
+      outchar ('-');
+    else if (info->showsign)
+      outchar ('+');
+    else if (info->space)
+      outchar (' ');
+
+    if (!info->left && info->pad == '0' && width > 0)
+      PADN ('0', width);
+
+    PRINT (startp, cp - startp);
+
+    if (info->left && width > 0)
+      PADN (info->pad, width);
+  }
+  return done;
+}
+
+/* Return the number of extra grouping characters that will be inserted
+   into a number with INTDIG_MAX integer digits.  */
+
+static unsigned int
+guess_grouping (unsigned int intdig_max, const char *grouping, wchar_t sepchar)
+{
+  unsigned int groups;
+
+  /* We treat all negative values like CHAR_MAX.  */
+
+  if (*grouping == CHAR_MAX || *grouping <= 0)
+    /* No grouping should be done.  */
+    return 0;
+
+  groups = 0;
+  while (intdig_max > *grouping)
+    {
+      ++groups;
+      intdig_max -= *grouping++;
+
+      if (*grouping == CHAR_MAX || *grouping < 0)
+	/* No more grouping should be done.  */
+	break;
+      else if (*grouping == 0)
+	{
+	  /* Same grouping repeats.  */
+	  groups += intdig_max / grouping[-1];
+	  break;
+	}
+    }
+
+  return groups;
+}
+
+/* Group the INTDIG_NO integer digits of the number in [BUF,BUFEND).
+   There is guaranteed enough space past BUFEND to extend it.
+   Return the new end of buffer.  */
+
+static char *
+group_number (char *buf, char *bufend, unsigned int intdig_no,
+	      const char *grouping, wchar_t thousands_sep)
+{
+  unsigned int groups = guess_grouping (intdig_no, grouping, thousands_sep);
+  char *p;
+
+  if (groups == 0)
+    return bufend;
+
+  /* Move the fractional part down.  */
+  memmove (buf + intdig_no + groups, buf + intdig_no,
+	   bufend - (buf + intdig_no));
+
+  p = buf + intdig_no + groups - 1;
+  do
+    {
+      unsigned int len = *grouping++;
+      do
+	*p-- = buf[--intdig_no];
+      while (--len > 0);
+      *p-- = thousands_sep;
+
+      if (*grouping == CHAR_MAX || *grouping < 0)
+	/* No more grouping should be done.  */
+	break;
+      else if (*grouping == 0)
+	/* Same grouping repeats.  */
+	--grouping;
+    } while (intdig_no > *grouping);
+
+  /* Copy the remaining ungrouped digits.  */
+  do
+    *p-- = buf[--intdig_no];
+  while (p > buf);
+
+  return bufend + groups;
+}
diff --git a/stdio/psignal.c b/stdio/psignal.c
new file mode 100644
index 0000000000..8997a2ecdf
--- /dev/null
+++ b/stdio/psignal.c
@@ -0,0 +1,49 @@
+/* Copyright (C) 1991, 1992 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdio.h>
+#include <signal.h>
+
+
+#ifndef	HAVE_GNU_LD
+#define	_sys_siglist	sys_siglist
+#endif
+
+/* Defined in sys_siglist.c.  */
+extern CONST char *CONST _sys_siglist[];
+
+
+/* Print out on stderr a line consisting of the test in S, a colon, a space,
+   a message describing the meaning of the signal number SIG and a newline.
+   If S is NULL or "", the colon and space are omitted.  */
+void
+DEFUN(psignal, (sig, s), int sig AND register CONST char *s)
+{
+  CONST char *colon;
+
+  if (s == NULL || s == '\0')
+    s = colon = "";
+  else
+    colon = ": ";
+
+  if (sig >= 0 && sig < NSIG)
+    (void) fprintf(stderr, "%s%s%s\n", s, colon, _sys_siglist[sig]);
+  else
+    (void) fprintf(stderr, "%s%sUnknown signal %d\n", s, colon, sig);
+}
diff --git a/stdio/putc.c b/stdio/putc.c
new file mode 100644
index 0000000000..51aae378ae
--- /dev/null
+++ b/stdio/putc.c
@@ -0,0 +1,5 @@
+#include <ansidecl.h>
+#include <stdio.h>
+#undef	putc
+#define	fputc	putc
+#include <fputc.c>
diff --git a/stdio/putchar.c b/stdio/putchar.c
new file mode 100644
index 0000000000..90c037600a
--- /dev/null
+++ b/stdio/putchar.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdio.h>
+
+#undef	putchar
+
+
+/* Write the character C on stdout.  */
+int
+DEFUN(putchar, (c), int c)
+{
+  return __putc(c, stdout);
+}
diff --git a/stdio/puts.c b/stdio/puts.c
new file mode 100644
index 0000000000..269c607da7
--- /dev/null
+++ b/stdio/puts.c
@@ -0,0 +1,32 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+
+#undef	puts
+
+
+/* Write the string in S and a newline to stdout.  */
+int
+DEFUN(puts, (s), CONST char *s)
+{
+  return(fputs(s, stdout) || putchar('\n') == EOF ? EOF : 0);
+}
diff --git a/stdio/putw.c b/stdio/putw.c
new file mode 100644
index 0000000000..1b70baeeaf
--- /dev/null
+++ b/stdio/putw.c
@@ -0,0 +1,31 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdio.h>
+
+
+/* Write the word (int) W to STREAM.  */
+int
+DEFUN(putw, (w, stream), int w AND FILE *stream)
+{
+  /* Is there a better way?  */
+  if (fwrite((CONST PTR) &w, sizeof(w), 1, stream) < 1)
+    return(EOF);
+  return(0);
+}
diff --git a/stdio/reg-printf.c b/stdio/reg-printf.c
new file mode 100644
index 0000000000..95d7a1f3c9
--- /dev/null
+++ b/stdio/reg-printf.c
@@ -0,0 +1,47 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <limits.h>
+#include <printf.h>
+
+/* Array of functions indexed by format character.  */
+static printf_function *printf_funcs[UCHAR_MAX + 1];
+printf_arginfo_function *__printf_arginfo_table[UCHAR_MAX + 1];
+
+printf_function **__printf_function_table;
+
+/* Register FUNC to be called to format SPEC specifiers.  */
+int
+DEFUN(register_printf_function, (spec, converter, arginfo),
+      int spec AND printf_function converter AND
+      printf_arginfo_function arginfo)
+{
+  if (spec < 0 || spec > (int) UCHAR_MAX)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  __printf_function_table = printf_funcs;
+  __printf_arginfo_table[spec] = arginfo;
+  printf_funcs[spec] = converter;
+
+  return 0;
+}
diff --git a/stdio/rewind.c b/stdio/rewind.c
new file mode 100644
index 0000000000..038b0164d8
--- /dev/null
+++ b/stdio/rewind.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdio.h>
+
+#undef	rewind
+
+
+/* Rewind STREAM to the beginning of the
+   file and clear its error and EOF flags.  */
+void
+DEFUN(rewind, (stream), FILE *stream)
+{
+  clearerr(stream);
+  (void) fseek(stream, 0L, SEEK_SET);
+  clearerr(stream);
+}
diff --git a/stdio/scanf.c b/stdio/scanf.c
new file mode 100644
index 0000000000..aa7021526f
--- /dev/null
+++ b/stdio/scanf.c
@@ -0,0 +1,37 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+
+/* Read formatted input from stdin according to the format string FORMAT.  */
+/* VARARGS1 */
+int
+DEFUN(scanf, (format), CONST char *format DOTS)
+{
+  va_list arg;
+  int done;
+
+  va_start(arg, format);
+  done = vscanf(format, arg);
+  va_end(arg);
+
+  return done;
+}
diff --git a/stdio/setbuf.c b/stdio/setbuf.c
new file mode 100644
index 0000000000..99cfa9dd24
--- /dev/null
+++ b/stdio/setbuf.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stddef.h>
+#include <stdio.h>
+
+
+/* If BUF is NULL, make STREAM unbuffered.
+   If not, make BUF, which is BUFSIZ bytes long, be its buffer.  */
+void
+DEFUN(setbuf, (stream, buf), FILE *stream AND char *buf)
+{
+  (void) setvbuf(stream, buf, buf != NULL ? _IOFBF : _IONBF, BUFSIZ);
+}
diff --git a/stdio/setbuffer.c b/stdio/setbuffer.c
new file mode 100644
index 0000000000..7677c1e358
--- /dev/null
+++ b/stdio/setbuffer.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stddef.h>
+#include <stdio.h>
+
+
+/* If BUF is NULL, make stream unbuffered.
+   If not, make BUF, which is N bytes long, be its buffer.  */
+void
+DEFUN(setbuffer, (stream, buf, n), FILE *stream AND char *buf AND size_t n)
+{
+  (void) setvbuf(stream, buf, buf != NULL ? _IOFBF : _IONBF, n);
+}
diff --git a/stdio/setlinebuf.c b/stdio/setlinebuf.c
new file mode 100644
index 0000000000..578cdfa54f
--- /dev/null
+++ b/stdio/setlinebuf.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdio.h>
+
+
+/* Make STREAM line buffered.  */
+void
+DEFUN(setlinebuf, (stream), FILE *stream)
+{
+  if (stream->__buffer != NULL || !stream->__userbuf)
+    stream->__linebuf = 1;
+}
diff --git a/stdio/setvbuf.c b/stdio/setvbuf.c
new file mode 100644
index 0000000000..8c33386610
--- /dev/null
+++ b/stdio/setvbuf.c
@@ -0,0 +1,85 @@
+/* Copyright (C) 1991, 1993 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+/* Make STREAM use the buffering method given in MODE.
+   If MODE indicates full or line buffering, use BUF,
+   a buffer of SIZE bytes; if BUF is NULL, malloc a buffer.  */
+int
+DEFUN(setvbuf, (stream, buf, mode, size),
+      FILE *stream AND char *buf AND int mode AND size_t size)
+{
+  if (!__validfp(stream))
+    {
+      errno = EINVAL;
+      return EOF;
+    }
+
+  /* The ANSI standard says setvbuf can only be called before any I/O is done,
+     but we allow it to replace an old buffer, flushing it first.  */
+  if (stream->__buffer != NULL)
+    {
+      (void) fflush(stream);
+      /* Free the old buffer if it was malloc'd.  */
+      if (!stream->__userbuf)
+	free(stream->__buffer);
+    }
+
+  stream->__get_limit = stream->__put_limit = NULL;
+  stream->__bufp = stream->__buffer = NULL;
+  stream->__userbuf = stream->__linebuf = stream->__linebuf_active = 0;
+
+  switch (mode)
+    {
+    default:
+      errno = EINVAL;
+      return EOF;
+    case _IONBF:	/* Unbuffered.  */
+      stream->__buffer = NULL;
+      stream->__bufsize = 0;
+      stream->__userbuf = 1;
+      break;
+    case _IOLBF:	/* Line buffered.  */
+      stream->__linebuf = 1;
+    case _IOFBF:	/* Fully buffered.  */
+      if (size == 0)
+	{
+	  errno = EINVAL;
+	  return EOF;
+	}
+      stream->__bufsize = size;
+      if (buf != NULL)
+	stream->__userbuf = 1;
+      else if ((buf = (char *) malloc(size)) == NULL)
+	return EOF;
+      stream->__buffer = buf;
+      break;
+    }
+
+  stream->__bufp = stream->__buffer;
+  stream->__get_limit = stream->__buffer;
+  /* The next output operation will prime the stream for writing.  */
+  stream->__put_limit = stream->__buffer;
+
+  return 0;
+}
diff --git a/stdio/snprintf.c b/stdio/snprintf.c
new file mode 100644
index 0000000000..9f3e0c4868
--- /dev/null
+++ b/stdio/snprintf.c
@@ -0,0 +1,39 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+
+/* Write formatted output into S, according to the format
+   string FORMAT, writing no more than MAXLEN characters.  */
+/* VARARGS3 */
+int
+DEFUN(snprintf, (s, maxlen, format),
+      char *s AND size_t maxlen AND CONST char *format DOTS)
+{
+  va_list arg;
+  int done;
+
+  va_start(arg, format);
+  done = vsnprintf(s, maxlen, format, arg);
+  va_end(arg);
+
+  return done;
+}
diff --git a/stdio/sprintf.c b/stdio/sprintf.c
new file mode 100644
index 0000000000..ce3a970074
--- /dev/null
+++ b/stdio/sprintf.c
@@ -0,0 +1,37 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+
+/* Write formatted output into S, according to the format string FORMAT.  */
+/* VARARGS2 */
+int
+DEFUN(sprintf, (s, format), char *s AND CONST char *format DOTS)
+{
+  va_list arg;
+  int done;
+
+  va_start(arg, format);
+  done = vsprintf(s, format, arg);
+  va_end(arg);
+
+  return done;
+}
diff --git a/stdio/sscanf.c b/stdio/sscanf.c
new file mode 100644
index 0000000000..33bc203577
--- /dev/null
+++ b/stdio/sscanf.c
@@ -0,0 +1,37 @@
+/* Copyright (C) 1991 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+
+/* Read formatted input from S, according to the format string FORMAT.  */
+/* VARARGS2 */
+int
+DEFUN(sscanf, (s, format), CONST char *s AND CONST char *format DOTS)
+{
+  va_list arg;
+  int done;
+
+  va_start(arg, format);
+  done = __vsscanf(s, format, arg);
+  va_end(arg);
+
+  return done;
+}
diff --git a/stdio/stdio.h b/stdio/stdio.h
new file mode 100644
index 0000000000..2994432328
--- /dev/null
+++ b/stdio/stdio.h
@@ -0,0 +1,681 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+/*
+ *	ANSI Standard: 4.9 INPUT/OUTPUT	<stdio.h>
+ */
+
+#ifndef	_STDIO_H
+
+#if	!defined(__need_FILE)
+#define	_STDIO_H	1
+#include <features.h>
+
+__BEGIN_DECLS
+
+#define	__need_size_t
+#define	__need_NULL
+#include <stddef.h>
+
+#define	__need___va_list
+#include <stdarg.h>
+#ifndef	__GNUC_VA_LIST
+#define	__gnuc_va_list	__ptr_t
+#endif
+
+#include <gnu/types.h>
+#endif /* Don't need FILE.  */
+#undef	__need_FILE
+
+
+#ifndef	__FILE_defined
+
+/* The opaque type of streams.  */
+typedef struct __stdio_file FILE;
+
+#define	__FILE_defined	1
+#endif /* FILE not defined.  */
+
+
+#ifdef	_STDIO_H
+
+/* The type of the second argument to `fgetpos' and `fsetpos'.  */
+typedef __off_t fpos_t;
+
+/* The mode of I/O, as given in the MODE argument to fopen, etc.  */
+typedef struct
+{
+  unsigned int __read:1;	/* Open for reading.  */
+  unsigned int __write:1;	/* Open for writing.  */
+  unsigned int __append:1;	/* Open for appending.  */
+  unsigned int __binary:1;	/* Opened binary.  */
+  unsigned int __create:1;	/* Create the file.  */
+  unsigned int __exclusive:1;	/* Error if it already exists.  */
+  unsigned int __truncate:1;	/* Truncate the file on opening.  */
+} __io_mode;
+
+
+/* Functions to do I/O and file management for a stream.  */
+
+/* Read NBYTES bytes from COOKIE into a buffer pointed to by BUF.
+   Return number of bytes read.  */
+typedef __ssize_t __io_read_fn __P ((__ptr_t __cookie, char *__buf,
+				     size_t __nbytes));
+
+/* Write N bytes pointed to by BUF to COOKIE.  Write all N bytes
+   unless there is an error.  Return number of bytes written, or -1 if
+   there is an error without writing anything.  If the file has been
+   opened for append (__mode.__append set), then set the file pointer
+   to the end of the file and then do the write; if not, just write at
+   the current file pointer.  */
+typedef __ssize_t __io_write_fn __P ((__ptr_t __cookie, __const char *__buf,
+				      size_t __n));
+
+/* Move COOKIE's file position to *POS bytes from the
+   beginning of the file (if W is SEEK_SET),
+   the current position (if W is SEEK_CUR),
+   or the end of the file (if W is SEEK_END).
+   Set *POS to the new file position.
+   Returns zero if successful, nonzero if not.  */
+typedef int __io_seek_fn __P ((__ptr_t __cookie, fpos_t *__pos, int __w));
+
+/* Close COOKIE.  */
+typedef int __io_close_fn __P ((__ptr_t __cookie));
+
+/* Return the file descriptor associated with COOKIE,
+   or -1 on error.  There need not be any associated file descriptor.  */
+typedef int __io_fileno_fn __P ((__ptr_t __cookie));
+
+#ifdef __USE_GNU
+/* User-visible names for the above.  */
+typedef __io_read_fn cookie_read_function_t;
+typedef __io_write_fn cookie_write_function_t;
+typedef __io_seek_fn cookie_seek_function_t;
+typedef __io_close_fn cookie_close_function_t;
+typedef __io_fileno_fn cookie_fileno_function_t;
+#endif
+
+/* Low level interface, independent of FILE representation.  */
+#if defined (__USE_GNU) && !defined (_LIBC)
+/* Define the user-visible type, with user-friendly member names.  */
+typedef struct
+{
+  __io_read_fn *read;		/* Read bytes.  */
+  __io_write_fn *write;		/* Write bytes.  */
+  __io_seek_fn *seek;		/* Seek/tell file position.  */
+  __io_close_fn *close;		/* Close file.  */
+  __io_fileno_fn *fileno;	/* Return file descriptor.  */
+} cookie_io_functions_t;
+/* This name is still used in the prototypes in this file.  */
+typedef cookie_io_functions_t __io_functions;
+#else
+/* Stick to ANSI-safe names.  */
+typedef struct
+{
+  __io_read_fn *__read;		/* Read bytes.  */
+  __io_write_fn *__write;	/* Write bytes.  */
+  __io_seek_fn *__seek;		/* Seek/tell file position.  */
+  __io_close_fn *__close;	/* Close file.  */
+  __io_fileno_fn *__fileno;	/* Return file descriptor.  */
+} __io_functions;
+#endif
+
+/* Higher level interface, dependent on FILE representation.  */
+typedef struct
+{
+  /* Make room in the input buffer.  */
+  int (*__input) __P ((FILE *__stream));
+  /* Make room in the output buffer.  */
+  void (*__output) __P ((FILE *__stream, int __c));
+} __room_functions;
+
+extern __const __io_functions __default_io_functions;
+extern __const __room_functions __default_room_functions;
+
+
+/* Default close function.  */
+extern __io_close_fn __stdio_close;
+/* Open FILE with mode M, store cookie in *COOKIEPTR.  */
+extern int __stdio_open __P ((__const char *__file, __io_mode __m,
+			      __ptr_t *__cookieptr));
+/* Put out an error message for when stdio needs to die.  */
+extern void __stdio_errmsg __P ((__const char *__msg, size_t __len));
+/* Generate a unique file name (and possibly open it with mode "w+b").  */
+extern char *__stdio_gen_tempname __P ((__const char *__dir,
+					__const char *__pfx,
+					int __dir_search,
+					size_t *__lenptr,
+					FILE **__streamptr));
+
+
+/* Print out MESSAGE on the error output and abort.  */
+extern void __libc_fatal __P ((__const char *__message))
+     __attribute__ ((__noreturn__));
+
+
+/* The FILE structure.  */
+struct __stdio_file
+{
+  /* Magic number for validation.  Must be negative in open streams
+     for the glue to Unix stdio getc/putc to work.
+     NOTE: stdio/glue.c has special knowledge of these first four members.  */
+  int __magic;
+#define	_IOMAGIC	0xfedabeeb	/* Magic number to fill `__magic'.  */
+#define	_GLUEMAGIC	0xfeedbabe	/* Magic for glued Unix streams.  */
+
+  char *__bufp;			/* Pointer into the buffer.  */
+  char *__get_limit;		/* Reading limit.  */
+  char *__put_limit;		/* Writing limit.  */
+
+  char *__buffer;		/* Base of buffer.  */
+  size_t __bufsize;		/* Size of the buffer.  */
+  __ptr_t __cookie;		/* Magic cookie.  */
+  __io_mode __mode;		/* File access mode.  */
+  __io_functions __io_funcs;	/* I/O functions.  */
+  __room_functions __room_funcs;/* I/O buffer room functions.  */
+  fpos_t __offset;		/* Current file position.  */
+  fpos_t __target;		/* Target file position.  */
+  FILE *__next;			/* Next FILE in the linked list.  */
+  char *__pushback_bufp;	/* Old bufp if char pushed back.  */
+  unsigned char __pushback;	/* Pushed-back character.  */
+  unsigned int __pushed_back:1;	/* A char has been pushed back.  */
+  unsigned int __eof:1;		/* End of file encountered.  */
+  unsigned int __error:1;	/* Error encountered.  */
+  unsigned int __userbuf:1;	/* Buffer from user (should not be freed).  */
+  unsigned int __linebuf:1;	/* Flush on newline.  */
+  unsigned int __linebuf_active:1; /* put_limit is not really in use.  */
+  unsigned int __seen:1;	/* This stream has been seen.  */
+  unsigned int __ispipe:1;	/* Nonzero if opened by popen.  */
+};
+
+
+/* All macros used internally by other macros here and by stdio functions begin
+   with `__'.  All of these may evaluate their arguments more than once.  */
+
+
+/* Nonzero if STREAM is a valid stream.
+   STREAM must be a modifiable lvalue (wow, I got to use that term).
+   See stdio/glue.c for what the confusing bit is about.  */
+#define	__validfp(stream)						      \
+  (stream != NULL &&							      \
+   ((stream->__magic == _GLUEMAGIC &&					      \
+     (stream = *(((struct { int __magic; FILE **__p; } *) stream)->__p))),    \
+    (stream->__magic == _IOMAGIC)))
+
+/* Clear the error and EOF indicators of STREAM.  */
+#define	__clearerr(stream)	((stream)->__error = (stream)->__eof = 0)
+
+/* Nuke STREAM, making it unusable but available for reuse.  */
+extern void __invalidate __P ((FILE *__stream));
+
+/* Make sure STREAM->__offset and STREAM->__target are initialized.
+   Returns 0 if successful, or EOF on
+   error (but doesn't set STREAM->__error).  */
+extern int __stdio_check_offset __P ((FILE *__stream));
+
+
+/* The possibilities for the third argument to `setvbuf'.  */
+#define _IOFBF	0x1		/* Full buffering.  */
+#define _IOLBF	0x2		/* Line buffering.  */
+#define _IONBF	0x4		/* No buffering.  */
+
+
+/* Default buffer size.  */
+#define	BUFSIZ	1024
+
+
+/* End of file character.
+   Some things throughout the library rely on this being -1.  */
+#define	EOF	(-1)
+
+
+/* The possibilities for the third argument to `fseek'.
+   These values should not be changed.  */
+#define	SEEK_SET	0	/* Seek from beginning of file.  */
+#define	SEEK_CUR	1	/* Seek from current position.  */
+#define	SEEK_END	2	/* Seek from end of file.  */
+
+
+#ifdef	__USE_SVID
+/* Default path prefix for `tempnam' and `tmpnam'.  */
+#define	P_tmpdir	"/usr/tmp"
+#endif
+
+
+/* Get the values:
+   L_tmpnam	How long an array of chars must be to be passed to `tmpnam'.
+   TMP_MAX	The minimum number of unique filenames generated by tmpnam
+   		(and tempnam when it uses tmpnam's name space),
+		or tempnam (the two are separate).
+   L_ctermid	How long an array to pass to `ctermid'.
+   L_cuserid	How long an array to pass to `cuserid'.
+   FOPEN_MAX	Mininum number of files that can be open at once.
+   FILENAME_MAX	Maximum length of a filename.  */
+#include <stdio_lim.h>
+
+
+/* All the known streams are in a linked list
+   linked by the `next' field of the FILE structure.  */
+extern FILE *__stdio_head;	/* Head of the list.  */
+
+/* Standard streams.  */
+extern FILE *stdin, *stdout, *stderr;
+#ifdef __STRICT_ANSI__
+/* ANSI says these are macros; satisfy pedants.  */
+#define	stdin	stdin
+#define	stdout	stdout
+#define	stderr	stderr
+#endif
+
+
+/* Remove file FILENAME.  */
+extern int remove __P ((__const char *__filename));
+/* Rename file OLD to NEW.  */
+extern int rename __P ((__const char *__old, __const char *__new));
+
+
+/* Create a temporary file and open it read/write.  */
+extern FILE *tmpfile __P ((void));
+/* Generate a temporary filename.  */
+extern char *tmpnam __P ((char *__s));
+
+
+#ifdef	__USE_SVID
+/* Generate a unique temporary filename using up to five characters of PFX
+   if it is not NULL.  The directory to put this file in is searched for
+   as follows: First the environment variable "TMPDIR" is checked.
+   If it contains the name of a writable directory, that directory is used.
+   If not and if DIR is not NULL, that value is checked.  If that fails,
+   P_tmpdir is tried and finally "/tmp".  The storage for the filename
+   is allocated by `malloc'.  */
+extern char *tempnam __P ((__const char *__dir, __const char *__pfx));
+#endif
+
+
+/* This performs actual output when necessary, flushing
+   STREAM's buffer and optionally writing another character.  */
+extern int __flshfp __P ((FILE *__stream, int __c));
+
+
+/* Close STREAM, or all streams if STREAM is NULL.  */
+extern int fclose __P ((FILE *__stream));
+/* Flush STREAM, or all streams if STREAM is NULL.  */
+extern int fflush __P ((FILE *__stream));
+
+
+/* Open a file and create a new stream for it.  */
+extern FILE *fopen __P ((__const char *__filename, __const char *__modes));
+/* Open a file, replacing an existing stream with it. */
+extern FILE *freopen __P ((__const char *__filename,
+			   __const char *__modes, FILE *__stream));
+
+/* Return a new, zeroed, stream.
+   You must set its cookie and io_mode.
+   The first operation will give it a buffer unless you do.
+   It will also give it the default functions unless you set the `seen' flag.
+   The offset is set to -1, meaning it will be determined by doing a
+   stationary seek.  You can set it to avoid the initial tell call.
+   The target is set to -1, meaning it will be set to the offset
+   before the target is needed.
+   Returns NULL if a stream can't be created.  */
+extern FILE *__newstream __P ((void));
+
+#ifdef	__USE_POSIX
+/* Create a new stream that refers to an existing system file descriptor.  */
+extern FILE *fdopen __P ((int __fd, __const char *__modes));
+#endif
+
+#ifdef	__USE_GNU
+/* Create a new stream that refers to the given magic cookie,
+   and uses the given functions for input and output.  */
+extern FILE *fopencookie __P ((__ptr_t __magic_cookie, __const char *__modes,
+			       __io_functions __io_funcs));
+
+/* Create a new stream that refers to a memory buffer.  */
+extern FILE *fmemopen __P ((__ptr_t __s, size_t __len, __const char *__modes));
+
+/* Open a stream that writes into a malloc'd buffer that is expanded as
+   necessary.  *BUFLOC and *SIZELOC are updated with the buffer's location
+   and the number of characters written on fflush or fclose.  */
+extern FILE *open_memstream __P ((char **__bufloc, size_t *__sizeloc));
+#endif
+
+
+/* If BUF is NULL, make STREAM unbuffered.
+   Else make it use buffer BUF, of size BUFSIZ.  */
+extern void setbuf __P ((FILE *__stream, char *__buf));
+/* Make STREAM use buffering mode MODE.
+   If BUF is not NULL, use N bytes of it for buffering;
+   else allocate an internal buffer N bytes long.  */
+extern int setvbuf __P ((FILE *__stream, char *__buf,
+			 int __modes, size_t __n));
+
+#ifdef	__USE_BSD
+/* If BUF is NULL, make STREAM unbuffered.
+   Else make it use SIZE bytes of BUF for buffering.  */
+extern void setbuffer __P ((FILE *__stream, char *__buf, size_t __size));
+
+/* Make STREAM line-buffered.  */
+extern void setlinebuf __P ((FILE *__stream));
+#endif
+
+
+/* Write formatted output to STREAM.  */
+extern int fprintf __P ((FILE *__stream, __const char *__format, ...));
+/* Write formatted output to stdout.  */
+extern int printf __P ((__const char *__format, ...));
+/* Write formatted output to S.  */
+extern int sprintf __P ((char *__s, __const char *__format, ...));
+
+/* Write formatted output to S from argument list ARG.  */
+extern int vfprintf __P ((FILE *__s, __const char *__format,
+			  __gnuc_va_list __arg));
+/* Write formatted output to stdout from argument list ARG.  */
+extern int vprintf __P ((__const char *__format, __gnuc_va_list __arg));
+/* Write formatted output to S from argument list ARG.  */
+extern int vsprintf __P ((char *__s, __const char *__format,
+			  __gnuc_va_list __arg));
+
+#ifdef	__OPTIMIZE__
+extern __inline int
+vprintf (const char *__fmt, __gnuc_va_list __arg)
+{
+  return vfprintf (stdout, __fmt, __arg);
+}
+#endif /* Optimizing.  */
+
+#ifdef	__USE_GNU
+/* Maximum chars of output to write in MAXLEN.  */
+extern int snprintf __P ((char *__s, size_t __maxlen,
+			  __const char *__format, ...));
+
+extern int vsnprintf __P ((char *__s, size_t __maxlen,
+			   __const char *__format, __gnuc_va_list __arg));
+
+/* Write formatted output to a string dynamically allocated with `malloc'.
+   Store the address of the string in *PTR.  */
+extern int vasprintf __P ((char **__ptr, __const char *__f,
+			   __gnuc_va_list __arg));
+extern int asprintf __P ((char **__ptr, __const char *__fmt, ...));
+
+/* Write formatted output to a file descriptor.  */
+extern int vdprintf __P ((int __fd, __const char *__fmt,
+			  __gnuc_va_list __arg));
+extern int dprintf __P ((int __fd, __const char *__fmt, ...));
+#endif
+
+
+/* Read formatted input from STREAM.  */
+extern int fscanf __P ((FILE *__stream, __const char *__format, ...));
+/* Read formatted input from stdin.  */
+extern int scanf __P ((__const char *__format, ...));
+/* Read formatted input from S.  */
+extern int sscanf __P ((__const char *__s, __const char *__format, ...));
+
+#ifdef	__USE_GNU
+/* Read formatted input from S into argument list ARG.  */
+extern int __vfscanf __P ((FILE *__s, __const char *__format,
+			   __gnuc_va_list __arg));
+extern int vfscanf __P ((FILE *__s, __const char *__format,
+			 __gnuc_va_list __arg));
+
+/* Read formatted input from stdin into argument list ARG.  */
+extern int vscanf __P ((__const char *__format, __gnuc_va_list __arg));
+
+/* Read formatted input from S into argument list ARG.  */
+extern int __vsscanf __P ((__const char *__s, __const char *__format,
+			   __gnuc_va_list __arg));
+extern int vsscanf __P ((__const char *__s, __const char *__format,
+			 __gnuc_va_list __arg));
+
+
+#ifdef	__OPTIMIZE__
+extern __inline int
+vfscanf (FILE *__s, const char *__fmt, __gnuc_va_list __arg)
+{
+  return __vfscanf (__s, __fmt, __arg);
+}
+extern __inline int
+vscanf (const char *__fmt, __gnuc_va_list __arg)
+{
+  return __vfscanf (stdin, __fmt, __arg);
+}
+extern __inline int
+vsscanf (const char *__s, const char *__fmt, __gnuc_va_list __arg)
+{
+  return __vsscanf (__s, __fmt, __arg);
+}
+#endif /* Optimizing.  */
+#endif /* Use GNU.  */
+
+
+/* This does actual reading when necessary, filling STREAM's
+   buffer and returning the first character in it.  */
+extern int __fillbf __P ((FILE *__stream));
+
+
+/* Read a character from STREAM.  */
+extern int fgetc __P ((FILE *__stream));
+extern int getc __P ((FILE *__stream));
+
+/* Read a character from stdin.  */
+extern int getchar __P ((void));
+
+/* The C standard explicitly says this can
+   re-evaluate its argument, so it does. */
+#define	__getc(stream)							      \
+  ((stream)->__bufp < (stream)->__get_limit ?				      \
+   (int) ((unsigned char) *(stream)->__bufp++) : __fillbf(stream))
+
+/* The C standard explicitly says this is a macro,
+   so we always do the optimization for it.  */
+#define	getc(stream)	__getc(stream)
+
+#ifdef	__OPTIMIZE__
+extern __inline int
+getchar (void)
+{
+  return __getc (stdin);
+}
+#endif /* Optimizing.  */
+
+
+/* Write a character to STREAM.  */
+extern int fputc __P ((int __c, FILE *__stream));
+extern int putc __P ((int __c, FILE *__stream));
+
+/* Write a character to stdout.  */
+extern int putchar __P ((int __c));
+
+
+/* The C standard explicitly says this can
+   re-evaluate its arguments, so it does.  */
+#define	__putc(c, stream)						      \
+  ((stream)->__bufp < (stream)->__put_limit ?				      \
+   (int) (unsigned char) (*(stream)->__bufp++ = (unsigned char) (c)) :	      \
+   __flshfp ((stream), (unsigned char) (c)))
+
+/* The C standard explicitly says this can be a macro,
+   so we always do the optimization for it.  */
+#define	putc(c, stream)	__putc ((c), (stream))
+
+#ifdef __OPTIMIZE__
+extern __inline int
+putchar (int __c)
+{
+  return __putc (__c, stdout);
+}
+#endif
+
+
+#if defined(__USE_SVID) || defined(__USE_MISC)
+/* Get a word (int) from STREAM.  */
+extern int getw __P ((FILE *__stream));
+
+/* Write a word (int) to STREAM.  */
+extern int putw __P ((int __w, FILE *__stream));
+#endif
+
+
+/* Get a newline-terminated string of finite length from STREAM.  */
+extern char *fgets __P ((char *__s, int __n, FILE *__stream));
+
+/* Get a newline-terminated string from stdin, removing the newline.
+   DO NOT USE THIS FUNCTION!!  There is no limit on how much it will read.  */
+extern char *gets __P ((char *__s));
+
+
+#ifdef	__USE_GNU
+#include <sys/types.h>
+
+/* Read up to (and including) a DELIMITER from STREAM into *LINEPTR
+   (and null-terminate it). *LINEPTR is a pointer returned from malloc (or
+   NULL), pointing to *N characters of space.  It is realloc'd as
+   necessary.  Returns the number of characters read (not including the
+   null terminator), or -1 on error or EOF.  */
+ssize_t __getdelim __P ((char **__lineptr, size_t *__n,
+			 int __delimiter, FILE *__stream));
+ssize_t getdelim __P ((char **__lineptr, size_t *__n,
+		       int __delimiter, FILE *__stream));
+
+/* Like `getdelim', but reads up to a newline.  */
+ssize_t __getline __P ((char **__lineptr, size_t *__n, FILE *__stream));
+ssize_t getline __P ((char **__lineptr, size_t *__n, FILE *__stream));
+
+#ifdef	__OPTIMIZE__
+extern __inline ssize_t
+__getline (char **__lineptr, size_t *__n, FILE *__stream)
+{
+  return __getdelim (__lineptr, __n, '\n', __stream);
+}
+
+extern __inline ssize_t
+getdelim (char **__lineptr, size_t *__n, int __delimiter, FILE *__stream)
+{
+  return __getdelim (__lineptr, __n, __delimiter, __stream);
+}
+extern __inline ssize_t
+getline (char **__lineptr, size_t *__n, FILE *__stream)
+{
+  return __getline (__lineptr, __n, __stream);
+}
+#endif /* Optimizing.  */
+#endif
+
+
+/* Write a string to STREAM.  */
+extern int fputs __P ((__const char *__s, FILE *__stream));
+/* Write a string, followed by a newline, to stdout.  */
+extern int puts __P ((__const char *__s));
+
+
+/* Push a character back onto the input buffer of STREAM.  */
+extern int ungetc __P ((int __c, FILE *__stream));
+
+
+/* Read chunks of generic data from STREAM.  */
+extern size_t fread __P ((__ptr_t __ptr, size_t __size,
+			  size_t __n, FILE *__stream));
+/* Write chunks of generic data to STREAM.  */
+extern size_t fwrite __P ((__const __ptr_t __ptr, size_t __size,
+			   size_t __n, FILE *__s));
+
+
+/* Seek to a certain position on STREAM.  */
+extern int fseek __P ((FILE *__stream, long int __off, int __whence));
+/* Return the current position of STREAM.  */
+extern long int ftell __P ((FILE *__stream));
+/* Rewind to the beginning of STREAM.  */
+extern void rewind __P ((FILE *__stream));
+
+/* Get STREAM's position.  */
+extern int fgetpos __P ((FILE *__stream, fpos_t *__pos));
+/* Set STREAM's position.  */
+extern int fsetpos __P ((FILE *__stream, __const fpos_t *__pos));
+
+
+/* Clear the error and EOF indicators for STREAM.  */
+extern void clearerr __P ((FILE *__stream));
+/* Return the EOF indicator for STREAM.  */
+extern int feof __P ((FILE *__stream));
+/* Return the error indicator for STREAM.  */
+extern int ferror __P ((FILE *__stream));
+
+#ifdef	__OPTIMIZE__
+#define	feof(stream)	((stream)->__eof != 0)
+#define	ferror(stream)	((stream)->__error != 0)
+#endif /* Optimizing.  */
+
+
+/* Print a message describing the meaning of the value of errno.  */
+extern void perror __P ((__const char *__s));
+
+#ifdef	__USE_BSD
+extern int sys_nerr;
+extern char *sys_errlist[];
+#endif
+#ifdef	__USE_GNU
+extern int _sys_nerr;
+extern char *_sys_errlist[];
+#endif
+
+
+#ifdef	__USE_POSIX
+/* Return the system file descriptor for STREAM.  */
+extern int fileno __P ((FILE *__stream));
+#endif /* Use POSIX.  */
+
+
+#if (defined (__USE_POSIX2) || defined(__USE_SVID) || defined(__USE_BSD) || \
+     defined(__USE_MISC))
+/* Create a new stream connected to a pipe running the given command.  */
+extern FILE *popen __P ((__const char *__command, __const char *__modes));
+
+/* Close a stream opened by popen and return the status of its child.  */
+extern int pclose __P ((FILE *__stream));
+#endif
+
+
+#ifdef	__USE_POSIX
+/* Return the name of the controlling terminal.  */
+extern char *ctermid __P ((char *__s));
+/* Return the name of the current user.  */
+extern char *cuserid __P ((char *__s));
+#endif
+
+
+#ifdef	__USE_GNU
+struct obstack;			/* See <obstack.h>.  */
+
+/* Open a stream that writes to OBSTACK.  */
+extern FILE *open_obstack_stream __P ((struct obstack *__obstack));
+
+/* Write formatted output to an obstack.  */
+extern int obstack_printf __P ((struct obstack *__obstack,
+				__const char *__format, ...));
+extern int obstack_vprintf __P ((struct obstack *__obstack,
+				 __const char *__format,
+				 __gnuc_va_list __args));
+#endif
+
+
+__END_DECLS
+
+#endif /* <stdio.h> included.  */
+
+#endif /* stdio.h  */
diff --git a/stdio/tempnam.c b/stdio/tempnam.c
new file mode 100644
index 0000000000..14988a8656
--- /dev/null
+++ b/stdio/tempnam.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 1991, 1993 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* Generate a unique temporary filename using up to five characters of PFX
+   if it is not NULL.  The directory to put this file in is searched for
+   as follows: First the environment variable "TMPDIR" is checked.
+   If it contains the name of a writable directory, that directory is used.
+   If not and if DIR is not NULL, that value is checked.  If that fails,
+   P_tmpdir is tried and finally "/tmp".  The storage for the filename
+   is allocated by `malloc'.  */
+char *
+DEFUN(tempnam, (dir, pfx), CONST char *dir AND CONST char *pfx)
+{
+  size_t len;
+  register char *s;
+  register char *t = __stdio_gen_tempname(dir, pfx, 1, &len, (FILE **) NULL);
+
+  if (t == NULL)
+    return NULL;
+
+  s = (char *) malloc(len);
+  if (s == NULL)
+    return NULL;
+
+  (void) memcpy(s, t, len);
+  return s;
+}
diff --git a/stdio/temptest.c b/stdio/temptest.c
new file mode 100644
index 0000000000..374719896a
--- /dev/null
+++ b/stdio/temptest.c
@@ -0,0 +1,31 @@
+#include <ansidecl.h>
+#include <stdio.h>
+#include <string.h>
+
+char *files[500];
+
+int
+main ()
+{
+  char *fn;
+  FILE *fp;
+  int i;
+
+  for (i = 0; i < 500; i++) {
+    fn = __stdio_gen_tempname((CONST char *) NULL,
+	"file", 0, (size_t *) NULL, (FILE **) NULL);
+    if (fn == NULL) {
+      printf ("__stdio_gen_tempname failed\n");
+      exit (1);
+    }
+    files[i] = strdup (fn);
+    printf ("file: %s\n", fn);
+    fp = fopen (fn, "w");
+    fclose (fp);
+  }
+
+  for (i = 0; i < 500; i++)
+    remove (files[i]);
+
+  exit (0);
+}
diff --git a/stdio/test-fseek.c b/stdio/test-fseek.c
new file mode 100644
index 0000000000..398cac796f
--- /dev/null
+++ b/stdio/test-fseek.c
@@ -0,0 +1,67 @@
+#include <ansidecl.h>
+#include <stdio.h>
+
+#define TESTFILE "test.dat"
+
+int
+main __P((void))
+{
+  FILE *fp;
+  int i, j;
+
+  puts ("\nFile seek test");
+  fp = fopen (TESTFILE, "w");
+  if (fp == NULL)
+    {
+      perror (TESTFILE);
+      return 1;
+    }
+
+  for (i = 0; i < 256; i++)
+    putc (i, fp);
+  if (freopen (TESTFILE, "r", fp) != fp)
+    {
+      perror ("Cannot open file for reading");
+      return 1;
+    }
+
+  for (i = 1; i <= 255; i++)
+    {
+      printf ("%3d\n", i);
+      fseek (fp, (long) -i, SEEK_END);
+      if ((j = getc (fp)) != 256 - i)
+	{
+	  printf ("SEEK_END failed %d\n", j);
+	  break;
+	}
+      if (fseek (fp, (long) i, SEEK_SET))
+	{
+	  puts ("Cannot SEEK_SET");
+	  break;
+	}
+      if ((j = getc (fp)) != i)
+	{
+	  printf ("SEEK_SET failed %d\n", j);
+	  break;
+	}
+      if (fseek (fp, (long) i, SEEK_SET))
+	{
+	  puts ("Cannot SEEK_SET");
+	  break;
+	}
+      if (fseek (fp, (long) (i >= 128 ? -128 : 128), SEEK_CUR))
+	{
+	  puts ("Cannot SEEK_CUR");
+	  break;
+	}
+      if ((j = getc (fp)) != (i >= 128 ? i - 128 : i + 128))
+	{
+	  printf ("SEEK_CUR failed %d\n", j);
+	  break;
+	}
+    }
+  fclose (fp);
+
+  puts ((i > 255) ? "Test succeeded." : "Test FAILED!");
+  return (i > 255) ? 0 : 1;
+}
diff --git a/stdio/test-fwrite.c b/stdio/test-fwrite.c
new file mode 100644
index 0000000000..cc6cdf038e
--- /dev/null
+++ b/stdio/test-fwrite.c
@@ -0,0 +1,68 @@
+#include <stdio.h>
+#include <string.h>
+
+int
+main ()
+{
+  FILE *f = tmpfile ();
+  char obuf[99999], ibuf[sizeof obuf];
+  char *line;
+  size_t linesz;
+
+  if (! f)
+    {
+      perror ("tmpfile");
+      return 1;
+    }
+
+  if (fputs ("line\n", f) == EOF)
+    {
+      perror ("fputs");
+      return 1;
+    }
+
+  memset (obuf, 'z', sizeof obuf);
+  memset (ibuf, 'y', sizeof ibuf);
+  
+  if (fwrite (obuf, sizeof obuf, 1, f) != 1)
+    {
+      perror ("fwrite");
+      return 1;
+    }
+
+  rewind (f);
+
+  line = NULL;
+  linesz = 0;
+  if (getline (&line, &linesz, f) != 5)
+    {
+      perror ("getline");
+      return 1;
+    }
+  if (strcmp (line, "line\n"))
+    {
+      puts ("Lines differ.  Test FAILED!");
+      return 1;
+    }
+
+  if (fread (ibuf, sizeof ibuf, 1, f) != 1)
+    {
+      perror ("fread");
+      return 1;
+    }
+
+  if (memcmp (ibuf, obuf, sizeof ibuf))
+    {
+      puts ("Buffers differ.  Test FAILED!");
+      return 1;
+    }
+
+  asprintf (&line, "\
+GDB is free software and you are welcome to distribute copies of it\n\
+ under certain conditions; type \"show copying\" to see the conditions.\n\
+There is absolutely no warranty for GDB; type \"show warranty\" for details.\n\
+");
+
+  puts ("Test succeeded.");
+  return 0;
+}
diff --git a/stdio/test-popen.c b/stdio/test-popen.c
new file mode 100644
index 0000000000..df6138b76f
--- /dev/null
+++ b/stdio/test-popen.c
@@ -0,0 +1,67 @@
+#include <ansidecl.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+void
+DEFUN(write_data, (stream), FILE *stream)
+{
+  int i;
+  for (i=0; i<100; i++)
+    fprintf (stream, "%d\n", i);
+  if (ferror (stream))  {
+    fprintf (stderr, "Output to stream failed.\n");
+    exit (1);
+    }
+}
+
+void
+DEFUN(read_data, (stream), FILE *stream)
+{
+  int i, j;
+
+  for (i=0; i<100; i++)
+    {
+      if (fscanf (stream, "%d\n", &j) != 1 || j != i)
+	{
+	  if (ferror (stream))
+	    perror ("fscanf");
+	  puts ("Test FAILED!");
+	  exit (1);
+	}
+    }
+}
+
+int
+DEFUN_VOID(main)
+{
+  FILE *output, *input;
+  int wstatus, rstatus;
+
+  output = popen ("/bin/cat >tstpopen.tmp", "w");
+  if (output == NULL)
+    {
+      perror ("popen");
+      puts ("Test FAILED!");
+      exit (1);
+    }
+  write_data (output);
+  wstatus = pclose (output);
+  printf ("writing pclose returned %d\n", wstatus);
+  input = popen ("/bin/cat tstpopen.tmp", "r");
+  if (input == NULL)
+    {
+      perror ("tstpopen.tmp");
+      puts ("Test FAILED!");
+      exit (1);
+    }
+  read_data (input);
+  rstatus = pclose (input);
+  printf ("reading pclose returned %d\n", rstatus);
+
+  puts (wstatus | rstatus  ? "Test FAILED!" : "Test succeeded.");
+  exit (wstatus | rstatus);
+}
+
+  
+
+  
diff --git a/stdio/test_rdwr.c b/stdio/test_rdwr.c
new file mode 100644
index 0000000000..8e0c1dfade
--- /dev/null
+++ b/stdio/test_rdwr.c
@@ -0,0 +1,129 @@
+/* Copyright (C) 1991, 1992 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+int
+DEFUN(main, (argc, argv), int argc AND char **argv)
+{
+  static CONST char hello[] = "Hello, world.\n";
+  static CONST char replace[] = "Hewwo, world.\n";
+  static CONST size_t replace_from = 2, replace_to = 4;
+  char filename[FILENAME_MAX];
+  char *name = strrchr(*argv, '/');
+  char buf[BUFSIZ];
+  FILE *f;
+  int lose = 0;
+
+  if (name != NULL)
+    ++name;
+  else
+    name = *argv;
+
+  (void) sprintf(filename, "/tmp/%s.test", name);
+
+  f = fopen(filename, "w+");
+  if (f == NULL)
+    {
+      perror(filename);
+      exit(1);
+    }
+
+  (void) fputs(hello, f);
+  rewind(f);
+  (void) fgets(buf, sizeof(buf), f);
+  rewind(f);
+  (void) fputs(buf, f);
+  rewind(f);
+  {
+    register size_t i;
+    for (i = 0; i < replace_from; ++i)
+      {
+	int c = getc(f);
+	if (c == EOF)
+	  {
+	    printf("EOF at %u.\n", i);
+	    lose = 1;
+	    break;
+	  }
+	else if (c != hello[i])
+	  {
+	    printf("Got '%c' instead of '%c' at %u.\n",
+		   (unsigned char) c, hello[i], i);
+	    lose = 1;
+	    break;
+	  }
+      }
+  }
+
+  {
+    long int where = ftell(f);
+    if (where == replace_from)
+      {
+	register size_t i;
+	for (i = replace_from; i < replace_to; ++i)
+	  if (putc(replace[i], f) == EOF)
+	    {
+	      printf("putc('%c') got %s at %u.\n",
+		     replace[i], strerror(errno), i);
+	      lose = 1;
+	      break;
+	    }
+      }
+    else if (where == -1L)
+      {
+	printf("ftell got %s (should be at %u).\n",
+	       strerror(errno), replace_from);
+	lose = 1;
+      }
+    else
+      {
+	printf("ftell returns %u; should be %u.\n", where, replace_from);
+	lose = 1;
+      }
+  }
+
+  if (!lose)
+    {
+      rewind(f);
+      if (fgets(buf, sizeof(buf), f) == NULL)
+	{
+	  printf("fgets got %s.\n", strerror(errno));
+	  lose = 1;
+	}
+      else if (strcmp(buf, replace))
+	{
+	  printf("Read \"%s\" instead of \"%s\".\n", buf, replace);
+	  lose = 1;
+	}
+    }
+
+  if (lose)
+    printf("Test FAILED!  Losing file is \"%s\".\n", filename);
+  else
+    {
+      (void) remove(filename);
+      puts("Test succeeded.");
+    }
+
+  exit(lose ? EXIT_FAILURE : EXIT_SUCCESS);
+}
diff --git a/stdio/tmpfile.c b/stdio/tmpfile.c
new file mode 100644
index 0000000000..dfe11ada50
--- /dev/null
+++ b/stdio/tmpfile.c
@@ -0,0 +1,43 @@
+/* Copyright (C) 1991, 1993 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdio.h>
+
+
+/* This returns a new stream opened on a temporary file (generated
+   by tmpnam) The file is opened with mode "w+b" (binary read/write).
+   If we couldn't generate a unique filename or the file couldn't
+   be opened, NULL is returned.  */
+FILE *
+DEFUN_VOID(tmpfile)
+{
+  char *filename;
+  FILE *f;
+
+  filename = __stdio_gen_tempname ((char *) NULL, "tmpf", 0,
+				   (size_t *) NULL, &f);
+  if (filename == NULL)
+    return NULL;
+
+  /* Note that this relies on the Unix semantics that
+     a file is not really removed until it is closed.  */
+  (void) remove (filename);
+
+  return f;
+}
diff --git a/stdio/tmpnam.c b/stdio/tmpnam.c
new file mode 100644
index 0000000000..88dd0a4ca5
--- /dev/null
+++ b/stdio/tmpnam.c
@@ -0,0 +1,42 @@
+/* Copyright (C) 1991, 1993 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+
+
+/* Generate a unique filename in P_tmpdir.  */
+char *
+DEFUN(tmpnam, (s), register char *s)
+{
+  register char *t = __stdio_gen_tempname((CONST char *) NULL,
+					  (CONST char *) NULL, 0,
+					  (size_t *) NULL, (FILE **) NULL);
+
+  if (t == NULL)
+    return NULL;
+
+  if (s != NULL)
+    (void) strcpy(s, t);
+  else
+    s = t;
+
+  return s;
+}
diff --git a/stdio/tst-fileno.c b/stdio/tst-fileno.c
new file mode 100644
index 0000000000..81945f7b44
--- /dev/null
+++ b/stdio/tst-fileno.c
@@ -0,0 +1,37 @@
+/* Copyright (C) 1994 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static int
+DEFUN(check, (name, stream, fd), CONST char *name AND FILE *stream AND int fd)
+{
+  int sfd = fileno (stream);
+  printf ("(fileno (%s) = %d) %c= %d\n", name, sfd, sfd == fd ? '=' : '!', fd);
+  return sfd != fd;
+}
+
+int
+DEFUN_VOID(main)
+{
+  exit (check ("stdin", stdin, STDIN_FILENO) ||
+	check ("stdout", stdout, STDOUT_FILENO) ||
+	check ("stderr", stderr, STDERR_FILENO));
+}
diff --git a/stdio/tst-printf.c b/stdio/tst-printf.c
new file mode 100644
index 0000000000..c177da18b2
--- /dev/null
+++ b/stdio/tst-printf.c
@@ -0,0 +1,298 @@
+/* Copyright (C) 1991, 1992, 1993, 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#ifdef	BSD
+#include </usr/include/stdio.h>
+#define EXIT_SUCCESS 0
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#include <float.h>
+
+
+void
+DEFUN(fmtchk, (fmt), CONST char *fmt)
+{
+  (void) fputs(fmt, stdout);
+  (void) printf(":\t`");
+  (void) printf(fmt, 0x12);
+  (void) printf("'\n");
+}
+
+void
+DEFUN(fmtst1chk, (fmt), CONST char *fmt)
+{
+  (void) fputs(fmt, stdout);
+  (void) printf(":\t`");
+  (void) printf(fmt, 4, 0x12);
+  (void) printf("'\n");
+}
+
+void
+DEFUN(fmtst2chk, (fmt), CONST char *fmt)
+{
+  (void) fputs(fmt, stdout);
+  (void) printf(":\t`");
+  (void) printf(fmt, 4, 4, 0x12);
+  (void) printf("'\n");
+}
+
+/* This page is covered by the following copyright: */
+
+/* (C) Copyright C E Chew
+ *
+ * Feel free to copy, use and distribute this software provided:
+ *
+ *	1. you do not pretend that you wrote it
+ *	2. you leave this copyright notice intact.
+ */
+
+/*
+ * Extracted from exercise.c for glibc-1.05 bug report by Bruce Evans.
+ */
+
+#define DEC -123
+#define INT 255
+#define UNS (~0)
+
+/* Formatted Output Test
+ *
+ * This exercises the output formatting code.
+ */
+
+void
+DEFUN_VOID(fp_test)
+{
+  int i, j, k, l;
+  char buf[7];
+  char *prefix = buf;
+  char tp[20];
+
+  puts("\nFormatted output test");
+  printf("prefix  6d      6o      6x      6X      6u\n");
+  strcpy(prefix, "%");
+  for (i = 0; i < 2; i++) {
+    for (j = 0; j < 2; j++) {
+      for (k = 0; k < 2; k++) {
+	for (l = 0; l < 2; l++) {
+	  strcpy(prefix, "%");
+	  if (i == 0) strcat(prefix, "-");
+	  if (j == 0) strcat(prefix, "+");
+	  if (k == 0) strcat(prefix, "#");
+	  if (l == 0) strcat(prefix, "0");
+	  printf("%5s |", prefix);
+	  strcpy(tp, prefix);
+	  strcat(tp, "6d |");
+	  printf(tp, DEC);
+	  strcpy(tp, prefix);
+	  strcat(tp, "6o |");
+	  printf(tp, INT);
+	  strcpy(tp, prefix);
+	  strcat(tp, "6x |");
+	  printf(tp, INT);
+	  strcpy(tp, prefix);
+	  strcat(tp, "6X |");
+	  printf(tp, INT);
+	  strcpy(tp, prefix);
+	  strcat(tp, "6u |");
+	  printf(tp, UNS);
+	  printf("\n");
+	}
+      }
+    }
+  }
+  printf("%10s\n", (char *) NULL);
+  printf("%-10s\n", (char *) NULL);
+}
+
+int
+DEFUN_VOID(main)
+{
+  static char shortstr[] = "Hi, Z.";
+  static char longstr[] = "Good morning, Doctor Chandra.  This is Hal.  \
+I am ready for my first lesson today.";
+
+  fmtchk("%.4x");
+  fmtchk("%04x");
+  fmtchk("%4.4x");
+  fmtchk("%04.4x");
+  fmtchk("%4.3x");
+  fmtchk("%04.3x");
+
+  fmtst1chk("%.*x");
+  fmtst1chk("%0*x");
+  fmtst2chk("%*.*x");
+  fmtst2chk("%0*.*x");
+
+#ifndef	BSD
+  printf("bad format:\t\"%z\"\n");
+  printf("nil pointer (padded):\t\"%10p\"\n", (PTR) NULL);
+#endif
+
+  printf("decimal negative:\t\"%d\"\n", -2345);
+  printf("octal negative:\t\"%o\"\n", -2345);
+  printf("hex negative:\t\"%x\"\n", -2345);
+  printf("long decimal number:\t\"%ld\"\n", -123456L);
+  printf("long octal negative:\t\"%lo\"\n", -2345L);
+  printf("long unsigned decimal number:\t\"%lu\"\n", -123456L);
+  printf("zero-padded LDN:\t\"%010ld\"\n", -123456L);
+  printf("left-adjusted ZLDN:\t\"%-010ld\"\n", -123456);
+  printf("space-padded LDN:\t\"%10ld\"\n", -123456L);
+  printf("left-adjusted SLDN:\t\"%-10ld\"\n", -123456L);
+
+  printf("zero-padded string:\t\"%010s\"\n", shortstr);
+  printf("left-adjusted Z string:\t\"%-010s\"\n", shortstr);
+  printf("space-padded string:\t\"%10s\"\n", shortstr);
+  printf("left-adjusted S string:\t\"%-10s\"\n", shortstr);
+  printf("null string:\t\"%s\"\n", (char *)NULL);
+  printf("limited string:\t\"%.22s\"\n", longstr);
+
+  printf("e-style >= 1:\t\"%e\"\n", 12.34);
+  printf("e-style >= .1:\t\"%e\"\n", 0.1234);
+  printf("e-style < .1:\t\"%e\"\n", 0.001234);
+  printf("e-style big:\t\"%.60e\"\n", 1e20);
+  printf ("e-style == .1:\t\"%e\"\n", 0.1);
+  printf("f-style >= 1:\t\"%f\"\n", 12.34);
+  printf("f-style >= .1:\t\"%f\"\n", 0.1234);
+  printf("f-style < .1:\t\"%f\"\n", 0.001234);
+  printf("g-style >= 1:\t\"%g\"\n", 12.34);
+  printf("g-style >= .1:\t\"%g\"\n", 0.1234);
+  printf("g-style < .1:\t\"%g\"\n", 0.001234);
+  printf("g-style big:\t\"%.60g\"\n", 1e20);
+
+  printf (" %6.5f\n", .099999999860301614);
+  printf (" %6.5f\n", .1);
+  printf ("x%5.4fx\n", .5);
+
+  printf ("%#03x\n", 1);
+
+  {
+    double d = FLT_MIN;
+    int niter = 17;
+    
+    while (niter-- != 0)
+      printf ("%.17e\n", d / 2);
+    fflush (stdout);
+  }
+
+  printf ("%15.5e\n", 4.9406564584124654e-324);
+
+#define FORMAT "|%12.4f|%12.4e|%12.4g|\n"
+  printf (FORMAT, 0.0, 0.0, 0.0);
+  printf (FORMAT, 1.0, 1.0, 1.0);
+  printf (FORMAT, -1.0, -1.0, -1.0);
+  printf (FORMAT, 100.0, 100.0, 100.0);
+  printf (FORMAT, 1000.0, 1000.0, 1000.0);
+  printf (FORMAT, 10000.0, 10000.0, 10000.0);
+  printf (FORMAT, 12345.0, 12345.0, 12345.0);
+  printf (FORMAT, 100000.0, 100000.0, 100000.0);
+  printf (FORMAT, 123456.0, 123456.0, 123456.0);
+#undef	FORMAT
+
+  {
+    char buf[20];
+    printf ("snprintf (\"%%30s\", \"foo\") == %d, \"%.*s\"\n",
+	    snprintf (buf, sizeof (buf), "%30s", "foo"), sizeof (buf), buf);
+  }
+
+  fp_test ();
+
+  printf ("%e should be 1.234568e+06\n", 1234567.8);
+  printf ("%f should be 1234567.800000\n", 1234567.8);
+  printf ("%g should be 1.23457e+06\n", 1234567.8);
+  printf ("%g should be 123.456\n", 123.456);
+  printf ("%g should be 1e+06\n", 1000000.0);
+  printf ("%g should be 10\n", 10.0);
+  printf ("%g should be 0.02\n", 0.02);
+
+  {
+    double x=1.0;
+    printf("%.17f\n",(1.0/x/10.0+1.0)*x-x);
+  }
+
+  puts ("--- Should be no further output. ---");
+  rfg1 ();
+  rfg2 ();
+
+  exit(EXIT_SUCCESS);
+}
+
+rfg1 ()
+{
+  char buf[100];
+
+  sprintf (buf, "%5.s", "xyz");
+  if (strcmp (buf, "     ") != 0)
+    printf ("got: '%s', expected: '%s'\n", buf, "     ");
+  sprintf (buf, "%5.f", 33.3);
+  if (strcmp (buf, "   33") != 0)
+    printf ("got: '%s', expected: '%s'\n", buf, "   33");
+  sprintf (buf, "%8.e", 33.3e7);
+  if (strcmp (buf, "   3e+08") != 0)
+    printf ("got: '%s', expected: '%s'\n", buf, "   3e+08");
+  sprintf (buf, "%8.E", 33.3e7);
+  if (strcmp (buf, "   3E+08") != 0)
+    printf ("got: '%s', expected: '%s'\n", buf, "   3E+08");
+  sprintf (buf, "%.g", 33.3);
+  if (strcmp (buf, "3e+01") != 0)
+    printf ("got: '%s', expected: '%s'\n", buf, "3e+01");
+  sprintf (buf, "%.G", 33.3);
+  if (strcmp (buf, "3E+01") != 0)
+    printf ("got: '%s', expected: '%s'\n", buf, "3E+01");
+  return 0;
+}
+
+rfg2 ()
+{
+  int prec;
+  char buf[100];
+
+  prec = 0;
+  sprintf (buf, "%.*g", prec, 3.3);
+  if (strcmp (buf, "3") != 0)
+    printf ("got: '%s', expected: '%s'\n", buf, "3");
+  prec = 0;
+  sprintf (buf, "%.*G", prec, 3.3);
+  if (strcmp (buf, "3") != 0)
+    printf ("got: '%s', expected: '%s'\n", buf, "3");
+  prec = 0;
+  sprintf (buf, "%7.*G", prec, 3.33);
+  if (strcmp (buf, "      3") != 0)
+    printf ("got: '%s', expected: '%s'\n", buf, "      3");
+  prec = 3;
+  sprintf (buf, "%04.*o", prec, 33);
+  if (strcmp (buf, " 041") != 0)
+    printf ("got: '%s', expected: '%s'\n", buf, " 041");
+  prec = 7;
+  sprintf (buf, "%09.*u", prec, 33);
+  if (strcmp (buf, "  0000033") != 0)
+    printf ("got: '%s', expected: '%s'\n", buf, "  0000033");
+  prec = 3;
+  sprintf (buf, "%04.*x", prec, 33);
+  if (strcmp (buf, " 021") != 0)
+    printf ("got: '%s', expected: '%s'\n", buf, " 021");
+  prec = 3;
+  sprintf (buf, "%04.*X", prec, 33);
+  if (strcmp (buf, " 021") != 0)
+    printf ("got: '%s', expected: '%s'\n", buf, " 021");
+  return 0;
+}
diff --git a/stdio/tstgetln.c b/stdio/tstgetln.c
new file mode 100644
index 0000000000..ea8ea817da
--- /dev/null
+++ b/stdio/tstgetln.c
@@ -0,0 +1,46 @@
+/* Copyright (C) 1992 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdio.h>
+
+int
+DEFUN_VOID(main)
+{
+  char *buf = NULL;
+  size_t size = 0;
+  ssize_t len;
+
+  while ((len = getline (&buf, &size, stdin)) != -1)
+    {
+      printf ("bufsize %u; read %d: ", size, len);
+      if (fwrite (buf, len, 1, stdout) != 1)
+	{
+	  perror ("fwrite");
+	  return 1;
+	}
+    }
+
+  if (ferror (stdin))
+    {
+      perror ("getline");
+      return 1;
+    }
+
+  return 0;
+}
diff --git a/stdio/tstgetln.input b/stdio/tstgetln.input
new file mode 100644
index 0000000000..d04ed5bf78
--- /dev/null
+++ b/stdio/tstgetln.input
@@ -0,0 +1,3 @@
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
+z
diff --git a/stdio/tstscanf.c b/stdio/tstscanf.c
new file mode 100644
index 0000000000..53d4b0ac47
--- /dev/null
+++ b/stdio/tstscanf.c
@@ -0,0 +1,100 @@
+/* Copyright (C) 1991, 1992 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#ifdef	BSD
+#include </usr/include/stdio.h>
+#else
+#include <stdio.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+
+int
+DEFUN(main, (argc, argv), int argc AND char **argv)
+{
+  char buf[BUFSIZ];
+  FILE *in = stdin, *out = stdout;
+
+  if (argc == 2 && !strcmp (argv[1], "-opipe"))
+    {
+      out = popen ("/bin/cat", "w");
+      if (out == NULL)
+	{
+	  perror ("popen: /bin/cat");
+	  exit (EXIT_FAILURE);
+	}
+    }
+  else if (argc == 3 && !strcmp (argv[1], "-ipipe"))
+    {
+      sprintf (buf, "/bin/cat %s", argv[2]);
+      in = popen (buf, "r");
+    }
+
+  {
+    char name[50];
+    fprintf (out,
+	     "sscanf (\"thompson\", \"%%s\", name) == %d, name == \"%s\"\n",
+	     sscanf ("thompson", "%s", name),
+	     name);
+  }
+
+  fputs ("Testing scanf (vfscanf)\n", out);
+
+  fputs ("Test 1:\n", out);
+  {
+    int n, i;
+    float x;
+    char name[50];
+    n = fscanf (in, "%d%f%s", &i, &x, name);
+    fprintf (out, "n = %d, i = %d, x = %f, name = \"%.50s\"\n",
+	     n, i, x, name);
+  }
+  fprintf (out, "Residual: \"%s\"\n", fgets (buf, sizeof (buf), in));
+  fputs ("Test 2:\n", out);
+  {
+    int i;
+    float x;
+    char name[50];
+    (void) fscanf (in, "%2d%f%*d %[0123456789]", &i, &x, name);
+    fprintf (out, "i = %d, x = %f, name = \"%.50s\"\n", i, x, name);
+  }
+  fprintf (out, "Residual: \"%s\"\n", fgets (buf, sizeof (buf), in));
+  fputs ("Test 3:\n", out);
+  {
+    float quant;
+    char units[21], item[21];
+    while (!feof (in) && !ferror (in))
+      {
+	int count;
+	quant = 0.0;
+	units[0] = item[0] = '\0';
+	count = fscanf (in, "%f%20s of %20s", &quant, units, item);
+	(void) fscanf (in, "%*[^\n]");
+	fprintf (out, "count = %d, quant = %f, item = %.21s, units = %.21s\n",
+		 count, quant, item, units);
+      }
+  }
+  fprintf (out, "Residual: \"%s\"\n", fgets (buf, sizeof (buf), in));
+
+  if (out != stdout)
+    pclose (out);
+
+  exit(EXIT_SUCCESS);
+}
diff --git a/stdio/tstscanf.input b/stdio/tstscanf.input
new file mode 100644
index 0000000000..26158652dd
--- /dev/null
+++ b/stdio/tstscanf.input
@@ -0,0 +1,7 @@
+25 54.32E-1 thompson
+56789 0123 56a72
+2 quarts of oil
+-12.8degrees Celsius
+lots of luck
+10.0LBS      of       fertilizer
+100ergs of energy
diff --git a/stdio/ungetc.c b/stdio/ungetc.c
new file mode 100644
index 0000000000..7b22a200f6
--- /dev/null
+++ b/stdio/ungetc.c
@@ -0,0 +1,58 @@
+/* Copyright (C) 1991, 1993 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stdio.h>
+
+
+/* Push the character C back onto the input stream of STREAM.  */
+int
+DEFUN(ungetc, (c, stream), register int c AND register FILE *stream)
+{
+  if (!__validfp(stream) || !stream->__mode.__read)
+    {
+      errno = EINVAL;
+      return EOF;
+    }
+
+  if (c == EOF)
+    return EOF;
+
+  if (stream->__pushed_back)
+    /* There is already a char pushed back.  */
+    return EOF;
+
+  if ((stream->__linebuf_active || stream->__put_limit > stream->__buffer) &&
+      /* This is a read-write stream with something in its buffer.
+	 Flush the stream.  */
+      __flshfp (stream, EOF) == EOF)
+    return EOF;
+
+  stream->__pushback = (unsigned char) c;
+  /* Tell __fillbf we've pushed back a char.  */
+  stream->__pushed_back = 1;
+  stream->__pushback_bufp = stream->__bufp;
+  /* Make the next getc call __fillbf.  It will return C.  */
+  stream->__bufp = stream->__get_limit;
+
+  /* We just gave it another character to read, so it's not at EOF.  */
+  stream->__eof = 0;
+
+  return stream->__pushback;
+}
diff --git a/stdio/vasprintf.c b/stdio/vasprintf.c
new file mode 100644
index 0000000000..d2ad6b1da6
--- /dev/null
+++ b/stdio/vasprintf.c
@@ -0,0 +1,86 @@
+/* Copyright (C) 1991, 1992 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+
+/* Enlarge STREAM's buffer.  */
+static void
+DEFUN(enlarge_buffer, (stream, c),
+      register FILE *stream AND int c)
+{
+  ptrdiff_t bufp_offset = stream->__bufp - stream->__buffer;
+  char *newbuf;
+
+  stream->__bufsize += 100;
+  newbuf = (char *) realloc ((PTR) stream->__buffer, stream->__bufsize);
+  if (newbuf == NULL)
+    {
+      free ((PTR) stream->__buffer);
+      stream->__buffer = stream->__bufp
+	= stream->__put_limit = stream->__get_limit = NULL;
+      stream->__error = 1;
+    }
+  else
+    {
+      stream->__buffer = newbuf;
+      stream->__bufp = stream->__buffer + bufp_offset;
+      stream->__get_limit = stream->__put_limit;
+      stream->__put_limit = stream->__buffer + stream->__bufsize;
+      if (c != EOF)
+	*stream->__bufp++ = (unsigned char) c;
+    }
+}
+
+/* Write formatted output from FORMAT to a string which is
+   allocated with malloc and stored in *STRING_PTR.  */
+int
+DEFUN(vasprintf, (string_ptr, format, args),
+      char **string_ptr AND CONST char *format AND va_list args)
+{
+  FILE f;
+  int done;
+
+  memset ((PTR) &f, 0, sizeof (f));
+  f.__magic = _IOMAGIC;
+  f.__bufsize = 100;
+  f.__buffer = (char *) malloc (f.__bufsize);
+  if (f.__buffer == NULL)
+    return -1;
+  f.__bufp = f.__buffer;
+  f.__put_limit = f.__buffer + f.__bufsize;
+  f.__mode.__write = 1;
+  f.__room_funcs.__output = enlarge_buffer;
+  f.__seen = 1;
+
+  done = vfprintf (&f, format, args);
+  if (done < 0)
+    return done;
+
+  *string_ptr = realloc (f.__buffer, (f.__bufp - f.__buffer) + 1);
+  if (*string_ptr == NULL)
+    *string_ptr = f.__buffer;
+  (*string_ptr)[f.__bufp - f.__buffer] = '\0';
+  return done;
+}
diff --git a/stdio/vdprintf.c b/stdio/vdprintf.c
new file mode 100644
index 0000000000..9df4e537bc
--- /dev/null
+++ b/stdio/vdprintf.c
@@ -0,0 +1,51 @@
+/* Copyright (C) 1991, 1992, 1993 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+
+/* Write formatted output to file descriptor D according to the format string
+   FORMAT, using the argument list in ARG.  */
+int
+DEFUN(vdprintf, (d, format, arg),
+      int d AND CONST char *format AND va_list arg)
+{
+  int done;
+  FILE f;
+
+  /* Create an unbuffered stream talking to D on the stack.  */
+  memset ((PTR) &f, 0, sizeof(f));
+  f.__magic = _IOMAGIC;
+  f.__mode.__write = 1;
+  f.__cookie = (PTR) (long int) d; /* Casting to long quiets GCC on Alpha.  */
+  f.__room_funcs = __default_room_functions;
+  f.__io_funcs = __default_io_functions;
+  f.__seen = 1;
+  f.__userbuf = 1;
+
+  /* vfprintf will use a buffer on the stack for the life of the call,
+     and flush it when finished.  */
+  done = vfprintf (&f, format, arg);
+
+  return done;
+}
diff --git a/stdio/vfprintf.c b/stdio/vfprintf.c
new file mode 100644
index 0000000000..c480a93ab9
--- /dev/null
+++ b/stdio/vfprintf.c
@@ -0,0 +1,907 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <localeinfo.h>
+#include <ctype.h>
+#include <errno.h>
+#include <float.h>
+#include <limits.h>
+#include <math.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <printf.h>
+#include <assert.h>
+#include <stddef.h>
+#include "_itoa.h"
+
+/* This function from the GNU C library is also used in libio.
+   To compile for use in libio, compile with -DUSE_IN_LIBIO.  */
+
+#ifdef USE_IN_LIBIO
+/* This code is for use in libio.  */
+#include <libioP.h>
+#define PUT(f, s, n)	_IO_sputn (f, s, n)
+#define PAD(padchar)	_IO_padn (s, padchar, width)
+#define PUTC(c, f)	_IO_putc(c, f)
+#define vfprintf	_IO_vfprintf
+#define size_t		_IO_size_t
+#define FILE		_IO_FILE
+#define va_list		_IO_va_list
+#undef	BUFSIZ
+#define BUFSIZ		_IO_BUFSIZ
+#define ARGCHECK(s, format) \
+  do									      \
+    {									      \
+      /* Check file argument for consistence.  */			      \
+      CHECK_FILE(s, -1);						      \
+      if (s->_flags & _IO_NO_WRITES || format == NULL)			      \
+	{								      \
+	  MAYBE_SET_EINVAL;						      \
+	  return -1;							      \
+	}								      \
+    } while (0)
+#define UNBUFFERED_P(s)	((s)->_IO_file_flags & _IO_UNBUFFERED)
+#else /* ! USE_IN_LIBIO */
+/* This code is for use in the GNU C library.  */
+#include <stdio.h>
+#define PUTC(c, f)	putc (c, f)
+#define PUT(f, s, n)	fwrite (s, 1, n, f)
+ssize_t __printf_pad __P ((FILE *, char pad, int n));
+#define PAD(padchar)	__printf_pad (s, padchar, width)
+#define ARGCHECK(s, format) \
+  do									      \
+    {									      \
+      /* Check file argument for consistence.  */			      \
+      if (!__validfp(s) || !s->__mode.__write || format == NULL)	      \
+	{								      \
+	  errno = EINVAL;						      \
+	  return -1;							      \
+	}								      \
+      if (!s->__seen)							      \
+	{								      \
+	  if (__flshfp (s, EOF) == EOF)					      \
+	    return -1;							      \
+	}								      \
+    } while (0)
+#define UNBUFFERED_P(s)	((s)->__buffer == NULL)
+#endif /* USE_IN_LIBIO */
+
+
+#define	outchar(x)							      \
+  do									      \
+    {									      \
+      register CONST int outc = (x);					      \
+      if (putc(outc, s) == EOF)						      \
+	return -1;							      \
+      else								      \
+	++done;								      \
+    } while (0)
+
+/* Advances STRING after writing LEN chars of it.  */
+#define outstring(string, len)						      \
+  do									      \
+    {									      \
+      if (len > 20)							      \
+	{								      \
+	  if (PUT (s, string, len) != len)				      \
+	    return -1;							      \
+	  done += len;							      \
+	  string += len;						      \
+	}								      \
+      else								      \
+	while (len-- > 0)						      \
+	  outchar (*string++);						      \
+    } while (0)
+
+/* Helper function to provide temporary buffering for unbuffered streams.  */
+static int buffered_vfprintf __P ((FILE *stream, const char *fmt, va_list));
+
+/* Cast the next arg, of type ARGTYPE, into CASTTYPE, and put it in VAR.  */
+#define	castarg(var, argtype, casttype) \
+  var = (casttype) va_arg(args, argtype)
+/* Get the next arg, of type TYPE, and put it in VAR.  */
+#define	nextarg(var, type)	castarg(var, type, type)
+
+static printf_function printf_unknown;
+
+extern printf_function **__printf_function_table;
+
+#ifdef	__GNUC__
+#define	HAVE_LONGLONG
+#define	LONGLONG	long long
+#else
+#define	LONGLONG	long
+#endif
+
+static char *group_number __P ((char *, char *, const char *, wchar_t));
+
+int
+DEFUN(vfprintf, (s, format, args),
+      register FILE *s AND CONST char *format AND va_list args)
+{
+  /* The character used as thousands separator.  */
+  wchar_t thousands_sep;
+
+  /* The string describing the size of groups of digits.  */
+  const char *grouping; 
+
+  /* Pointer into the format string.  */
+  register CONST char *f;
+
+  /* Number of characters written.  */
+  register size_t done = 0;
+
+  ARGCHECK (s, format);
+
+  if (UNBUFFERED_P (s))
+    /* Use a helper function which will allocate a local temporary buffer
+       for the stream and then call us again.  */
+    return buffered_vfprintf (s, format, args);
+
+  /* Reset multibyte characters to their initial state.  */
+  (void) mblen ((char *) NULL, 0);
+
+  /* Figure out the thousands seperator character.  */
+  if (mbtowc (&thousands_sep, _numeric_info->thousands_sep,
+	      strlen (_numeric_info->thousands_sep)) <= 0)
+    thousands_sep = (wchar_t) *_numeric_info->thousands_sep;
+  grouping = _numeric_info->grouping; /* Cache the grouping info array.  */
+  if (*grouping == '\0' || thousands_sep == L'\0')
+    grouping = NULL;
+
+  f = format;
+  while (*f != '\0')
+    {
+      /* Type modifiers.  */
+      char is_short, is_long, is_long_double;
+#ifdef	HAVE_LONGLONG
+      /* We use the `L' modifier for `long long int'.  */
+#define	is_longlong	is_long_double
+#else
+#define	is_longlong	0
+#endif
+      /* Format spec modifiers.  */
+      char space, showsign, left, alt, group;
+
+      /* Padding character: ' ' or '0'.  */
+      char pad;
+      /* Width of a field.  */
+      register int width;
+      /* Precision of a field.  */
+      int prec;
+
+      /* Decimal integer is negative.  */
+      char is_neg;
+
+      /* Current character of the format.  */
+      char fc;
+
+      /* Base of a number to be written.  */
+      int base;
+      /* Integral values to be written.  */
+      unsigned LONGLONG int num;
+      LONGLONG int signed_num;
+
+      /* String to be written.  */
+      CONST char *str;
+      char errorbuf[1024];	/* Buffer sometimes used by %m.  */
+
+      /* Auxiliary function to do output.  */
+      printf_function *function;
+
+      if (!isascii(*f))
+	{
+	  /* Non-ASCII, may be a multibyte.  */
+	  int len = mblen (f, strlen (f));
+	  if (len > 0)
+	    {
+	      outstring (f, len);
+	      continue;
+	    }
+	}
+
+      if (*f != '%')
+	{
+	  /* This isn't a format spec, so write everything out until the
+	     next one.  To properly handle multibyte characters, we cannot
+	     just search for a '%'.  Since multibyte characters are hairy
+	     (and dealt with above), if we hit any byte above 127 (only
+	     those can start a multibyte character) we just punt back to
+	     that code.  */
+	  do
+	    outchar (*f++);
+	  while (*f != '\0' && *f != '%' && isascii (*f));
+	  continue;
+	}
+
+      ++f;
+
+      /* Check for "%%".  Note that although the ANSI standard lists
+	 '%' as a conversion specifier, it says "The complete format
+	 specification shall be `%%'," so we can avoid all the width
+	 and precision processing.  */
+      if (*f == '%')
+	{
+	  ++f;
+	  outchar('%');
+	  continue;
+	}
+
+      /* Check for spec modifiers.  */
+      space = showsign = left = alt = group = 0;
+      pad = ' ';
+      while (*f == ' ' || *f == '+' || *f == '-' || *f == '#' || *f == '0' ||
+	     *f == '\'')
+	switch (*f++)
+	  {
+	  case ' ':
+	    /* Output a space in place of a sign, when there is no sign.  */
+	    space = 1;
+	    break;
+	  case '+':
+	    /* Always output + or - for numbers.  */
+	    showsign = 1;
+	    break;
+	  case '-':
+	    /* Left-justify things.  */
+	    left = 1;
+	    break;
+	  case '#':
+	    /* Use the "alternate form":
+	       Hex has 0x or 0X, FP always has a decimal point.  */
+	    alt = 1;
+	    break;
+	  case '0':
+	    /* Pad with 0s.  */
+	    pad = '0';
+	    break;
+	  case '\'':
+	    /* Show grouping in numbers if the locale information
+	       indicates any.  */
+	    group = 1;
+	    break;
+	  }
+      if (left)
+	pad = ' ';
+
+      /* Get the field width.  */
+      width = 0;
+      if (*f == '*')
+	{
+	  /* The field width is given in an argument.
+	     A negative field width indicates left justification.  */
+	  nextarg(width, int);
+	  if (width < 0)
+	    {
+	      width = - width;
+	      left = 1;
+	    }
+	  ++f;
+	}
+      else
+	while (isdigit (*f))
+	  {
+	    width *= 10;
+	    width += *f++ - '0';
+	  }
+
+      /* Get the precision.  */
+      /* -1 means none given; 0 means explicit 0.  */
+      prec = -1;
+      if (*f == '.')
+	{
+	  ++f;
+	  if (*f == '*')
+	    {
+	      /* The precision is given in an argument.  */
+	      nextarg(prec, int);
+	      /* Avoid idiocy.  */
+	      if (prec < 0)
+		prec = -1;
+	      ++f;
+	    }
+	  else if (isdigit (*f))
+	    {
+	      prec = *f++ - '0';
+	      while (*f != '\0' && isdigit (*f))
+		{
+		  prec *= 10;
+		  prec += *f++ - '0';
+		}
+	    }
+	  else
+	    /* "%.?" is treated like "%.0?".  */
+	    prec = 0;
+	}
+
+      /* If there was a precision specified, ignore the 0 flag and always
+	 pad with spaces.  */
+      if (prec != -1)
+	pad = ' ';
+
+      /* Check for type modifiers.  */
+      is_short = is_long = is_long_double = 0;
+      while (*f == 'h' || *f == 'l' || *f == 'L' || *f == 'q')
+	switch (*f++)
+	  {
+	  case 'h':
+	    /* int's are short int's.  */
+	    is_short = 1;
+	    break;
+	  case 'l':
+#ifdef	HAVE_LONGLONG
+	    if (is_long)
+	      /* A double `l' is equivalent to an `L'.  */
+	      is_longlong = 1;
+	    else
+#endif
+	      /* int's are long int's.  */
+	      is_long = 1;
+	    break;
+	  case 'L':
+	    /* double's are long double's, and int's are long long int's.  */
+	    is_long_double = 1;
+	    break;
+
+	  case 'Z':
+	    /* int's are size_t's.  */
+#ifdef	HAVE_LONGLONG
+	    assert (sizeof(size_t) <= sizeof(unsigned long long int));
+	    is_longlong = sizeof(size_t) > sizeof(unsigned long int);
+#endif
+	    is_long = sizeof(size_t) > sizeof(unsigned int);
+	    break;
+
+	  case 'q':
+	    /* 4.4 uses this for long long.  */
+#ifdef	HAVE_LONGLONG
+	    is_longlong = 1;
+#else
+	    is_long = 1;
+#endif
+	    break;
+	  }
+
+      /* Format specification.  */
+      fc = *f++;
+      function = (__printf_function_table == NULL ? NULL :
+		  __printf_function_table[fc]);
+      if (function == NULL)
+	switch (fc)
+	  {
+	  case 'i':
+	  case 'd':
+	    /* Decimal integer.  */
+	    base = 10;
+	    if (is_longlong)
+	      nextarg(signed_num, LONGLONG int);
+	    else if (is_long)
+	      nextarg(signed_num, long int);
+	    else if (!is_short)
+	      castarg(signed_num, int, long int);
+	    else
+	      castarg(signed_num, int, short int);
+
+	    is_neg = signed_num < 0;
+	    num = is_neg ? (- signed_num) : signed_num;
+	    goto number;
+
+	  case 'u':
+	    /* Decimal unsigned integer.  */
+	    base = 10;
+	    goto unsigned_number;
+
+	  case 'o':
+	    /* Octal unsigned integer.  */
+	    base = 8;
+	    goto unsigned_number;
+
+	  case 'X':
+	    /* Hexadecimal unsigned integer.  */
+	  case 'x':
+	    /* Hex with lower-case digits.  */
+
+	    base = 16;
+
+	  unsigned_number:
+	    /* Unsigned number of base BASE.  */
+
+	    if (is_longlong)
+	      castarg(num, LONGLONG int, unsigned LONGLONG int);
+	    else if (is_long)
+	      castarg(num, long int, unsigned long int);
+	    else if (!is_short)
+	      castarg(num, int, unsigned int);
+	    else
+	      castarg(num, int, unsigned short int);
+
+	    /* ANSI only specifies the `+' and
+	       ` ' flags for signed conversions.  */
+	    is_neg = showsign = space = 0;
+
+	  number:
+	    /* Number of base BASE.  */
+	    {
+	      char work[BUFSIZ];
+	      char *CONST workend = &work[sizeof(work) - 1];
+	      register char *w;
+
+	      /* Supply a default precision if none was given.  */
+	      if (prec == -1)
+		prec = 1;
+
+	      /* Put the number in WORK.  */
+	      w = _itoa (num, workend + 1, base, fc == 'X') - 1;
+	      if (group && grouping)
+		w = group_number (w, workend, grouping, thousands_sep);
+	      width -= workend - w;
+	      prec -= workend - w;
+
+	      if (alt && base == 8 && prec <= 0)
+		{
+		  *w-- = '0';
+		  --width;
+		}
+
+	      if (prec > 0)
+		{
+		  width -= prec;
+		  while (prec-- > 0)
+		    *w-- = '0';
+		}
+
+	      if (alt && base == 16)
+		width -= 2;
+
+	      if (is_neg || showsign || space)
+		--width;
+
+	      if (!left && pad == ' ')
+		PAD (' ');
+
+	      if (is_neg)
+		outchar('-');
+	      else if (showsign)
+		outchar('+');
+	      else if (space)
+		outchar(' ');
+
+	      if (alt && base == 16)
+		{
+		  outchar ('0');
+		  outchar (fc);
+		}
+
+	      if (!left && pad == '0')
+		PAD ('0');
+
+	      /* Write the number.  */
+	      while (++w <= workend)
+		outchar(*w);
+
+	      if (left)
+		PAD (' ');
+	    }
+	    break;
+
+	  case 'e':
+	  case 'E':
+	  case 'f':
+	  case 'g':
+	  case 'G':
+	    {
+	      /* Floating-point number.  */
+	      extern printf_function __printf_fp;
+	      function = __printf_fp;
+	      goto use_function;
+	    }
+
+	  case 'c':
+	    /* Character.  */
+	    nextarg(num, int);
+	    if (!left)
+	      {
+		--width;
+		PAD (' ');
+	      }
+	    outchar ((unsigned char) num);
+	    if (left)
+	      PAD (' ');
+	    break;
+
+	  case 's':
+	    {
+	      static CONST char null[] = "(null)";
+	      size_t len;
+
+	      nextarg(str, CONST char *);
+
+	    string:
+
+	      if (str == NULL)
+		/* Write "(null)" if there's space.  */
+		if (prec == -1 || prec >= (int) sizeof(null) - 1)
+		  {
+		    str = null;
+		    len = sizeof(null) - 1;
+		  }
+		else
+		  {
+		    str = "";
+		    len = 0;
+		  }
+	      else
+		len = strlen(str);
+
+	      if (prec != -1 && (size_t) prec < len)
+		len = prec;
+	      width -= len;
+
+	      if (!left)
+		PAD (' ');
+	      outstring (str, len);
+	      if (left)
+		PAD (' ');
+	    }
+	    break;
+
+	  case 'p':
+	    /* Generic pointer.  */
+	    {
+	      CONST PTR ptr;
+	      nextarg(ptr, CONST PTR);
+	      if (ptr != NULL)
+		{
+		  /* If the pointer is not NULL, write it as a %#x spec.  */
+		  base = 16;
+		  fc = 'x';
+		  alt = 1;
+		  num = (unsigned LONGLONG int) (unsigned long int) ptr;
+		  is_neg = 0;
+		  group = 0;
+		  goto number;
+		}
+	      else
+		{
+		  /* Write "(nil)" for a nil pointer.  */
+		  static CONST char nil[] = "(nil)";
+		  register CONST char *p;
+
+		  width -= sizeof (nil) - 1;
+		  if (!left)
+		    PAD (' ');
+		  for (p = nil; *p != '\0'; ++p)
+		    outchar (*p);
+		  if (left)
+		    PAD (' ');
+		}
+	    }
+	    break;
+
+	  case 'n':
+	    /* Answer the count of characters written.  */
+	    if (is_longlong)
+	      {
+		LONGLONG int *p;
+		nextarg(p, LONGLONG int *);
+		*p = done;
+	      }
+	    else if (is_long)
+	      {
+		long int *p;
+		nextarg(p, long int *);
+		*p = done;
+	      }
+	    else if (!is_short)
+	      {
+		int *p;
+		nextarg(p, int *);
+		*p = done;
+	      }
+	    else
+	      {
+		short int *p;
+		nextarg(p, short int *);
+		*p = done;
+	      }
+	    break;
+
+	  case 'm':
+	    {
+	      extern char *_strerror_internal __P ((int, char buf[1024]));
+	      str = _strerror_internal (errno, errorbuf);
+	      goto string;
+	    }
+
+	  default:
+	    /* Unrecognized format specifier.  */
+	    function = printf_unknown;
+	    goto use_function;
+	  }
+      else
+      use_function:
+	{
+	  int function_done;
+	  struct printf_info info;
+
+	  info.prec = prec;
+	  info.width = width;
+	  info.spec = fc;
+	  info.is_long_double = is_long_double;
+	  info.is_short = is_short;
+	  info.is_long = is_long;
+	  info.alt = alt;
+	  info.space = space;
+	  info.left = left;
+	  info.showsign = showsign;
+	  info.group = group;
+	  info.pad = pad;
+
+	  function_done = (*function) (s, &info, &args);
+	  if (function_done < 0)
+	    return -1;
+
+	  done += function_done;
+	}
+    }
+
+  return done;
+}
+
+
+static int
+DEFUN(printf_unknown, (s, info, arg),
+      FILE *s AND CONST struct printf_info *info AND va_list *arg)
+{
+  int done = 0;
+  char work[BUFSIZ];
+  char *CONST workend = &work[sizeof(work) - 1];
+  register char *w;
+  register int prec = info->prec, width = info->width;
+
+  outchar('%');
+
+  if (info->alt)
+    outchar ('#');
+  if (info->group)
+    outchar ('\'');
+  if (info->showsign)
+    outchar ('+');
+  else if (info->space)
+    outchar (' ');
+  if (info->left)
+    outchar ('-');
+  if (info->pad == '0')
+    outchar ('0');
+
+  w = workend;
+  while (width > 0)
+    {
+      *w-- = '0' + (width % 10);
+      width /= 10;
+    }
+  while (++w <= workend)
+    outchar(*w);
+
+  if (info->prec != -1)
+    {
+      outchar('.');
+      w = workend;
+      while (prec > 0)
+	{
+	  *w-- = '0' + (prec % 10);
+	  prec /= 10;
+	}
+      while (++w <= workend)
+	outchar(*w);
+    }
+
+  outchar(info->spec);
+
+  return done;
+}
+
+/* Group the digits according to the grouping rules of the current locale.
+   The interpretation of GROUPING is as in `struct lconv' from <locale.h>.  */
+
+static char *
+group_number (char *w, char *workend, const char *grouping,
+	      wchar_t thousands_sep)
+{
+  int len;
+  char *src, *s;
+
+  /* We treat all negative values like CHAR_MAX.  */
+
+  if (*grouping == CHAR_MAX || *grouping < 0)
+    /* No grouping should be done.  */
+    return w;
+
+  len = *grouping;
+
+  /* Copy existing string so that nothing gets overwritten.  */
+  src = (char *) alloca (workend - w);
+  memcpy (src, w + 1, workend - w);
+  s = &src[workend - w - 1];
+  w = workend;
+
+  /* Process all characters in the string.  */
+  while (s >= src)
+    {
+      *w-- = *s--;
+
+      if (--len == 0 && s >= src)
+	{
+	  /* A new group begins.  */
+	  *w-- = thousands_sep;
+
+	  len = *grouping++;
+	  if (*grouping == '\0')
+	    /* The previous grouping repeats ad infinitum.  */
+	    --grouping;
+	  else if (*grouping == CHAR_MAX || *grouping < 0)
+	    {
+	      /* No further grouping to be done.
+		 Copy the rest of the number.  */
+	      do
+		*w-- = *s--;
+	      while (s >= src);
+	      break;
+	    }
+	}
+    }
+
+  return w;
+}
+
+#ifdef USE_IN_LIBIO
+/* Helper "class" for `fprintf to unbuffered': creates a temporary buffer.  */
+struct helper_file
+  {
+    struct _IO_FILE_plus _f;
+    _IO_FILE *_put_stream;
+  };
+
+static int
+DEFUN(_IO_helper_overflow, (s, c), _IO_FILE *s AND int c)
+{
+  _IO_FILE *target = ((struct helper_file*) s)->_put_stream;
+  int used = s->_IO_write_ptr - s->_IO_write_base;
+  if (used)
+    {
+      _IO_size_t written = _IO_sputn (target, s->_IO_write_base, used);
+      s->_IO_write_ptr -= written;
+    }
+  return _IO_putc (c, s);
+}
+
+static const struct _IO_jump_t _IO_helper_jumps =
+  {
+    _IO_helper_overflow,
+    _IO_default_underflow,
+    _IO_default_xsputn,
+    _IO_default_xsgetn,
+    _IO_default_read,
+    _IO_default_write,
+    _IO_default_doallocate,
+    _IO_default_pbackfail,
+    _IO_default_setbuf,
+    _IO_default_sync,
+    _IO_default_finish,
+    _IO_default_close,
+    _IO_default_stat,
+    _IO_default_seek,
+    _IO_default_seekoff,
+    _IO_default_seekpos,
+    _IO_default_uflow
+  };
+
+static int
+DEFUN(buffered_vfprintf, (s, format, args),
+      register _IO_FILE *s AND char CONST *format AND _IO_va_list args)
+{
+  char buf[_IO_BUFSIZ];
+  struct helper_file helper;
+  register _IO_FILE *hp = (_IO_FILE *) &helper;
+  int result, to_flush;
+
+  /* Initialize helper.  */
+  helper._put_stream = s;
+  hp->_IO_write_base = buf;
+  hp->_IO_write_ptr = buf;
+  hp->_IO_write_end = buf + sizeof buf;
+  hp->_IO_file_flags = _IO_MAGIC|_IO_NO_READS;
+  hp->_jumps = (struct _IO_jump_t *) &_IO_helper_jumps;
+  
+  /* Now print to helper instead.  */
+  result = _IO_vfprintf (hp, format, args);
+
+  /* Now flush anything from the helper to the S. */
+  if ((to_flush = hp->_IO_write_ptr - hp->_IO_write_base) > 0)
+    {
+      if (_IO_sputn (s, hp->_IO_write_base, to_flush) != to_flush)
+	return -1;
+    }
+
+  return result;
+}
+
+#else /* !USE_IN_LIBIO */
+
+static int
+DEFUN(buffered_vfprintf, (s, format, args),
+      register FILE *s AND char CONST *format AND va_list args)
+{
+  char buf[BUFSIZ];
+  int result;
+
+  s->__bufp = s->__buffer = buf;
+  s->__bufsize = sizeof buf;
+  s->__put_limit = s->__buffer + s->__bufsize;
+  s->__get_limit = s->__buffer;
+
+  /* Now use buffer to print.  */
+  result = vfprintf (s, format, args);
+
+  if (fflush (s) == EOF)
+    return -1;
+  s->__buffer = s->__bufp = s->__get_limit = s->__put_limit = NULL;
+  s->__bufsize = 0;
+
+  return result;
+}
+
+
+/* Pads string with given number of a specified character.
+   This code is taken from iopadn.c of the GNU I/O library.  */
+#define PADSIZE 16
+static const char blanks[PADSIZE] =
+{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
+static const char zeroes[PADSIZE] =
+{'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
+
+ssize_t
+__printf_pad (s, pad, count)
+     FILE *s;
+     char pad;
+     int count;
+{
+  CONST char *padptr;
+  register int i;
+  size_t written = 0, w;
+
+  padptr = pad == ' ' ? blanks : zeroes;
+
+  for (i = count; i >= PADSIZE; i -= PADSIZE)
+    {
+      w = PUT(s, padptr, PADSIZE);
+      written += w;
+      if (w != PADSIZE)
+	return written;
+    }
+  if (i > 0)
+    {
+      w = PUT(s, padptr, i);
+      written += w;
+    }
+  return written;
+}
+#undef PADSIZE
+#endif /* USE_IN_LIBIO */
diff --git a/stdio/vfscanf.c b/stdio/vfscanf.c
new file mode 100644
index 0000000000..681e89819b
--- /dev/null
+++ b/stdio/vfscanf.c
@@ -0,0 +1,570 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <localeinfo.h>
+#include <errno.h>
+#include <limits.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#ifdef	__GNUC__
+#define	HAVE_LONGLONG
+#define	LONGLONG	long long
+#else
+#define	LONGLONG	long
+#endif
+
+
+#define	inchar()	((c = getc(s)) == EOF ? EOF : (++read_in, c))
+#define	conv_error()	return ((c == EOF || ungetc(c, s)), done)
+#define input_error()	return (done == 0 ? EOF : done)
+#define	memory_error()	return ((errno = ENOMEM), EOF)
+
+
+/* Read formatted input from S according to the format string
+   FORMAT, using the argument list in ARG.
+   Return the number of assignments made, or -1 for an input error.  */
+int
+DEFUN(__vfscanf, (s, format, arg),
+      FILE *s AND CONST char *format AND va_list argptr)
+{
+  va_list arg = (va_list) argptr;
+
+  register CONST char *f = format;
+  register char fc;		/* Current character of the format.  */
+  register size_t done = 0;	/* Assignments done.  */
+  register size_t read_in = 0;	/* Chars read in.  */
+  register int c;		/* Last char read.  */
+  register int do_assign;	/* Whether to do an assignment.  */
+  register int width;		/* Maximum field width.  */
+
+  /* Type modifiers.  */
+  char is_short, is_long, is_long_double;
+#ifdef	HAVE_LONGLONG
+  /* We use the `L' modifier for `long long int'.  */
+#define	is_longlong	is_long_double
+#else
+#define	is_longlong	0
+#endif
+  int malloc_string;		/* Args are char ** to be filled in.  */
+  /* Status for reading F-P nums.  */
+  char got_dot, got_e;
+  /* If a [...] is a [^...].  */
+  char not_in;
+  /* Base for integral numbers.  */
+  int base;
+  /* Signedness for integral numbers.  */
+  int number_signed;
+  /* Integral holding variables.  */
+  long int num;
+  unsigned long int unum;
+  /* Character-buffer pointer.  */
+  register char *str, **strptr;
+  size_t strsize;
+  /* Workspace.  */
+  char work[200];
+  char *w;			/* Pointer into WORK.  */
+  wchar_t decimal;		/* Decimal point character.  */
+
+  if (!__validfp(s) || !s->__mode.__read || format == NULL)
+    {
+      errno = EINVAL;
+      return EOF;
+    }
+
+  /* Figure out the decimal point character.  */
+  if (mbtowc(&decimal, _numeric_info->decimal_point,
+	     strlen(_numeric_info->decimal_point)) <= 0)
+    decimal = (wchar_t) *_numeric_info->decimal_point;
+
+  c = inchar();
+
+  /* Run through the format string.  */
+  while (*f != '\0')
+    {
+      if (!isascii(*f))
+	{
+	  /* Non-ASCII, may be a multibyte.  */
+	  int len = mblen(f, strlen(f));
+	  if (len > 0)
+	    {
+	      while (len-- > 0)
+		if (c == EOF)
+		  input_error();
+		else if (c == *f++)
+		  (void) inchar();
+		else
+		  conv_error();
+	      continue;
+	    }
+	}
+
+      fc = *f++;
+      if (fc != '%')
+	{
+	  /* Characters other than format specs must just match.  */
+	  if (c == EOF)
+	    input_error();
+	  if (isspace(fc))
+	    {
+	      /* Whitespace characters match any amount of whitespace.  */
+	      while (isspace (c))
+		inchar ();
+	      continue;
+	    }
+	  else if (c == fc)
+	    (void) inchar();
+	  else
+	    conv_error();
+	  continue;
+	}
+
+      /* Check for the assignment-suppressant.  */
+      if (*f == '*')
+	{
+	  do_assign = 0;
+	  ++f;
+	}
+      else
+	do_assign = 1;
+		
+      /* Find the maximum field width.  */
+      width = 0;
+      while (isdigit(*f))
+	{
+	  width *= 10;
+	  width += *f++ - '0';
+	}
+      if (width == 0)
+	width = -1;
+
+      /* Check for type modifiers.  */
+      is_short = is_long = is_long_double = malloc_string = 0;
+      while (*f == 'h' || *f == 'l' || *f == 'L' || *f == 'a' || *f == 'q')
+	switch (*f++)
+	  {
+	  case 'h':
+	    /* int's are short int's.  */
+	    is_short = 1;
+	    break;
+	  case 'l':
+	    if (is_long)
+	      /* A double `l' is equivalent to an `L'.  */
+	      is_longlong = 1;
+	    else
+	      /* int's are long int's.  */
+	      is_long = 1;
+	    break;
+	  case 'q':
+	  case 'L':
+	    /* double's are long double's, and int's are long long int's.  */
+	    is_long_double = 1;
+	    break;
+	  case 'a':
+	    /* String conversions (%s, %[) take a `char **'
+	       arg and fill it in with a malloc'd pointer.  */
+	    malloc_string = 1;
+	    break;
+	  }
+
+      /* End of the format string?  */
+      if (*f == '\0')
+	conv_error();
+
+      /* Find the conversion specifier.  */
+      w = work;
+      fc = *f++;
+      if (fc != '[' && fc != 'c' && fc != 'n')
+	/* Eat whitespace.  */
+	while (isspace(c))
+	  (void) inchar();
+      switch (fc)
+	{
+	case '%':	/* Must match a literal '%'.  */
+	  if (c != fc)
+	    conv_error();
+	  break;
+
+	case 'n':	/* Answer number of assignments done.  */
+	  if (do_assign)
+	    *va_arg(arg, int *) = read_in;
+	  break;
+
+	case 'c':	/* Match characters.  */
+	  if (do_assign)
+	    {
+	      str = va_arg (arg, char *);
+	      if (str == NULL)
+		conv_error ();
+	    }
+
+	  if (c == EOF)
+	    input_error();
+
+	  if (width == -1)
+	    width = 1;
+
+	  if (do_assign)
+	    {
+	      do
+		*str++ = c;
+	      while (inchar() != EOF && --width > 0);
+	    }
+	  else
+	    while (inchar() != EOF && width > 0)
+	      --width;
+
+	  if (do_assign)
+	    ++done;
+
+	  break;
+
+	case 's':		/* Read a string.  */
+#define STRING_ARG							      \
+	  if (do_assign)						      \
+	    {								      \
+	      if (malloc_string)					      \
+		{							      \
+		  /* The string is to be stored in a malloc'd buffer.  */     \
+		  strptr = va_arg (arg, char **);			      \
+		  if (strptr == NULL)					      \
+		    conv_error ();					      \
+		  /* Allocate an initial buffer.  */			      \
+		  strsize = 100;					      \
+		  *strptr = str = malloc (strsize);			      \
+		}							      \
+	      else							      \
+		str = va_arg (arg, char *);				      \
+	      if (str == NULL)						      \
+		conv_error ();						      \
+	    }
+	  STRING_ARG;
+
+	  if (c == EOF)
+	    input_error ();
+
+	  do
+	    {
+	      if (isspace (c))
+		break;
+#define	STRING_ADD_CHAR(c)						      \
+	      if (do_assign)						      \
+		{							      \
+		  *str++ = c;						      \
+		  if (malloc_string && str == *strptr + strsize)	      \
+		    {							      \
+		      /* Enlarge the buffer.  */			      \
+		      str = realloc (*strptr, strsize * 2);		      \
+		      if (str == NULL)					      \
+			{						      \
+			  /* Can't allocate that much.  Last-ditch effort.  */\
+			  str = realloc (*strptr, strsize + 1);		      \
+			  if (str == NULL)				      \
+			    {						      \
+			      /* We lose.  Oh well.			      \
+				 Terminate the string and stop converting,    \
+				 so at least we don't swallow any input.  */  \
+			      (*strptr)[strsize] = '\0';		      \
+			      ++done;					      \
+			      conv_error ();				      \
+			    }						      \
+			  else						      \
+			    {						      \
+			      *strptr = str;				      \
+			      str += strsize;				      \
+			      ++strsize;				      \
+			    }						      \
+			}						      \
+		      else						      \
+			{						      \
+			  *strptr = str;				      \
+			  str += strsize;				      \
+			  strsize *= 2;					      \
+			}						      \
+		    }							      \
+		}
+	      STRING_ADD_CHAR (c);
+	    } while (inchar () != EOF && (width <= 0 || --width > 0));
+
+	  if (do_assign)
+	    {
+	      *str = '\0';
+	      ++done;
+	    }
+	  break;
+
+	case 'x':	/* Hexadecimal integer.  */
+	case 'X':	/* Ditto.  */ 
+	  base = 16;
+	  number_signed = 0;
+	  goto number;
+
+	case 'o':	/* Octal integer.  */
+	  base = 8;
+	  number_signed = 0;
+	  goto number;
+
+	case 'u':	/* Unsigned decimal integer.  */
+	  base = 10;
+	  number_signed = 0;
+	  goto number;
+
+	case 'd':	/* Signed decimal integer.  */
+	  base = 10;
+	  number_signed = 1;
+	  goto number;
+
+	case 'i':	/* Generic number.  */
+	  base = 0;
+	  number_signed = 1;
+
+	number:
+	  if (c == EOF)
+	    input_error();
+
+	  /* Check for a sign.  */
+	  if (c == '-' || c == '+')
+	    {
+	      *w++ = c;
+	      if (width > 0)
+		--width;
+	      (void) inchar();
+	    }
+
+	  /* Look for a leading indication of base.  */
+	  if (c == '0')
+	    {
+	      if (width > 0)
+		--width;
+	      *w++ = '0';
+
+	      (void) inchar();
+
+	      if (tolower(c) == 'x')
+		{
+		  if (base == 0)
+		    base = 16;
+		  if (base == 16)
+		    {
+		      if (width > 0)
+			--width;
+		      (void) inchar();
+		    }
+		}
+	      else if (base == 0)
+		base = 8;
+	    }
+
+	  if (base == 0)
+	    base = 10;
+
+	  /* Read the number into WORK.  */
+	  do
+	    {
+	      if (base == 16 ? !isxdigit(c) :
+		  (!isdigit(c) || c - '0' >= base))
+		break;
+	      *w++ = c;
+	      if (width > 0)
+		--width;
+	    } while (inchar() != EOF && width != 0);
+
+	  if (w == work ||
+	      (w - work == 1 && (work[0] == '+' || work[0] == '-')))
+	    /* There was on number.  */
+	    conv_error();
+
+	  /* Convert the number.  */
+	  *w = '\0';
+	  if (number_signed)
+	    num = strtol (work, &w, base);
+	  else
+	    unum = strtoul (work, &w, base);
+	  if (w == work)
+	    conv_error ();
+
+	  if (do_assign)
+	    {
+	      if (! number_signed)
+		{
+		  if (is_longlong)
+		    *va_arg (arg, unsigned LONGLONG int *) = unum;
+		  else if (is_long)
+		    *va_arg (arg, unsigned long int *) = unum;
+		  else if (is_short)
+		    *va_arg (arg, unsigned short int *)
+		      = (unsigned short int) unum;
+		  else
+		    *va_arg(arg, unsigned int *) = (unsigned int) unum;
+		}
+	      else
+		{
+		  if (is_longlong)
+		    *va_arg(arg, LONGLONG int *) = num;
+		  else if (is_long)
+		    *va_arg(arg, long int *) = num;
+		  else if (is_short)
+		    *va_arg(arg, short int *) = (short int) num;
+		  else
+		    *va_arg(arg, int *) = (int) num;
+		}
+	      ++done;
+	    }
+	  break;
+
+	case 'e':	/* Floating-point numbers.  */
+	case 'E':
+	case 'f':
+	case 'g':
+	case 'G':
+	  if (c == EOF)
+	    input_error();
+
+	  /* Check for a sign.  */
+	  if (c == '-' || c == '+')
+	    {
+	      *w++ = c;
+	      if (inchar() == EOF)
+		/* EOF is only an input error before we read any chars.  */
+		conv_error();
+	      if (width > 0)
+		--width;
+	    }
+
+	  got_dot = got_e = 0;
+	  do
+	    {
+	      if (isdigit(c))
+		*w++ = c;
+	      else if (got_e && w[-1] == 'e' && (c == '-' || c == '+'))
+		*w++ = c;
+	      else if (!got_e && tolower(c) == 'e')
+		{
+		  *w++ = 'e';
+		  got_e = got_dot = 1;
+		}
+	      else if (c == decimal && !got_dot)
+		{
+		  *w++ = c;
+		  got_dot = 1;
+		}
+	      else
+		break;
+	      if (width > 0)
+		--width;
+	    } while (inchar() != EOF && width != 0);
+
+	  if (w == work)
+	    conv_error();
+	  if (w[-1] == '-' || w[-1] == '+' || w[-1] == 'e')
+	    conv_error();
+
+	  /* Convert the number.  */
+	  *w = '\0';
+	  if (is_long_double)
+	    {
+	      long double d = __strtold (work, &w);
+	      if (do_assign && w != work)
+		*va_arg (arg, long double *) = d;
+	    }
+	  else if (is_long)
+	    {
+	      double d = strtod (work, &w);
+	      if (do_assign && w != work)
+		*va_arg (arg, double *) = d;
+	    }
+	  else
+	    {
+	      float d = __strtof (work, &w);
+	      if (do_assign && w != work)
+		*va_arg (arg, float *) = d;
+	    }
+
+	  if (w == work)
+	    conv_error ();
+
+	  if (do_assign)
+	    ++done;
+	  break;
+
+	case '[':	/* Character class.  */
+	  STRING_ARG;
+
+	  if (c == EOF)
+	    input_error();
+
+	  if (*f == '^')
+	    {
+	      ++f;
+	      not_in = 1;
+	    }
+	  else
+	    not_in = 0;
+
+	  while ((fc = *f++) != '\0' && fc != ']')
+	    {
+	      if (fc == '-' && *f != '\0' && *f != ']' &&
+		  w > work && w[-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;
+	      else
+		/* Add the character to the list.  */
+		*w++ = fc;
+	    }
+	  if (fc == '\0')
+	    conv_error();
+
+	  *w = '\0';
+	  unum = read_in;
+	  do
+	    {
+	      if ((strchr (work, c) == NULL) != not_in)
+		break;
+	      STRING_ADD_CHAR (c);
+	      if (width > 0)
+		--width;
+	    } while (inchar () != EOF && width != 0);
+	  if (read_in == unum)
+	    conv_error ();
+
+	  if (do_assign)
+	    {
+	      *str = '\0';
+	      ++done;
+	    }
+	  break;
+
+	case 'p':	/* Generic pointer.  */
+	  base = 16;
+	  /* A PTR must be the same size as a `long int'.  */
+	  is_long = 1;
+	  goto number;
+	}
+    }
+
+  conv_error();
+}
+
+weak_alias (__vfscanf, vfscanf)
diff --git a/stdio/vprintf.c b/stdio/vprintf.c
new file mode 100644
index 0000000000..97264f475c
--- /dev/null
+++ b/stdio/vprintf.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 1991, 1993 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdarg.h>
+#undef	__OPTIMIZE__	/* Avoid inline `vprintf' function.  */
+#include <stdio.h>
+
+#undef	vprintf
+
+
+/* Write formatted output to stdout according to the
+   format string FORMAT, using the argument list in ARG.  */
+int
+DEFUN(vprintf, (format, arg), CONST char *format AND __gnuc_va_list arg)
+{
+  return vfprintf (stdout, format, arg);
+}
diff --git a/stdio/vscanf.c b/stdio/vscanf.c
new file mode 100644
index 0000000000..0d829440e9
--- /dev/null
+++ b/stdio/vscanf.c
@@ -0,0 +1,32 @@
+/* Copyright (C) 1991, 1992 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#undef	vscanf
+
+
+/* Read formatted input from stdin according to the format
+   string in FORMAT, using the argument list in ARG.  */
+int
+DEFUN(vscanf, (format, arg), CONST char *format AND va_list arg)
+{
+  return vfscanf (stdin, format, arg);
+}
diff --git a/stdio/vsnprintf.c b/stdio/vsnprintf.c
new file mode 100644
index 0000000000..a02c259131
--- /dev/null
+++ b/stdio/vsnprintf.c
@@ -0,0 +1,56 @@
+/* Copyright (C) 1991, 1992 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+
+/*
+ * Write formatted output to S according to the format string
+ * FORMAT, using the argument list in ARG, writing no more
+ * than MAXLEN characters.
+ */
+int
+DEFUN(vsnprintf, (s, maxlen, format, arg),
+	char *s AND size_t maxlen AND CONST char *format AND va_list arg)
+{
+  int done;
+  FILE f;
+
+  memset((PTR) &f, 0, sizeof(f));
+  f.__magic = _IOMAGIC;
+  f.__mode.__write = 1;
+  /* The buffer size is one less than MAXLEN
+     so we have space for the null terminator.  */
+  f.__bufp = f.__buffer = (char *) s;
+  f.__bufsize = maxlen - 1;
+  f.__put_limit = f.__buffer + f.__bufsize;
+  f.__get_limit = f.__buffer;
+  /* After the buffer is full (MAXLEN characters have been written),
+     any more characters written will go to the bit bucket.  */
+  f.__room_funcs = __default_room_functions;
+  f.__io_funcs.__write = NULL;
+  f.__seen = 1;
+
+  done = vfprintf(&f, format, arg);
+  *f.__bufp = '\0';
+
+  return done;
+}
diff --git a/stdio/vsprintf.c b/stdio/vsprintf.c
new file mode 100644
index 0000000000..82be90f1fa
--- /dev/null
+++ b/stdio/vsprintf.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 1991, 1992 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+
+/* Write formatted output to S according to the format string
+   FORMAT, using the argument list in ARG.  */
+int
+DEFUN(vsprintf, (s, format, arg),
+      char *s AND CONST char *format AND va_list arg)
+{
+  int done;
+  FILE f;
+
+  memset((PTR) &f, 0, sizeof(f));
+  f.__magic = _IOMAGIC;
+  f.__mode.__write = 1;
+  f.__bufp = f.__buffer = (char *) s;
+  f.__put_limit = (char *) ULONG_MAX;
+  f.__bufsize = (size_t) (f.__put_limit - f.__bufp);
+  f.__get_limit = f.__buffer;
+  f.__room_funcs.__output = NULL;
+  f.__seen = 1;
+
+  done = vfprintf(&f, format, arg);
+  *f.__bufp = '\0';
+
+  return done;
+}
diff --git a/stdio/vsscanf.c b/stdio/vsscanf.c
new file mode 100644
index 0000000000..6f027d5065
--- /dev/null
+++ b/stdio/vsscanf.c
@@ -0,0 +1,58 @@
+/* Copyright (C) 1991, 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
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#undef	vsscanf
+
+
+/* Read formatted input from S according to the format
+   string FORMAT, using the argument list in ARG.  */
+int
+DEFUN(__vsscanf, (s, format, arg),
+      CONST char *s AND CONST char *format AND va_list arg)
+{
+  FILE f;
+
+  if (s == NULL)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  memset((PTR) &f, 0, sizeof(f));
+  f.__magic = _IOMAGIC;
+  f.__mode.__read = 1;
+  f.__bufp = f.__buffer = (char *) s;
+  f.__bufsize = strlen(s);
+  f.__get_limit = f.__buffer + f.__bufsize;
+  f.__put_limit = f.__buffer;
+  /* After the buffer is empty (strlen(S) characters have been read),
+     any more read attempts will get EOF.  */
+  f.__room_funcs.__input = NULL;
+  f.__seen = 1;
+
+  return __vfscanf(&f, format, arg);
+}
+
+
+weak_alias (__vsscanf, vsscanf)
diff --git a/stdio/xbug.c b/stdio/xbug.c
new file mode 100644
index 0000000000..ec648f5566
--- /dev/null
+++ b/stdio/xbug.c
@@ -0,0 +1,63 @@
+#include <stdio.h>
+
+typedef struct _Buffer {
+  char *buff;
+  int  room, used;
+} Buffer;
+
+#define INIT_BUFFER_SIZE 10000
+
+void InitBuffer(b)
+     Buffer *b;
+{
+  b->room = INIT_BUFFER_SIZE;
+  b->used = 0;
+  b->buff = (char *)malloc(INIT_BUFFER_SIZE*sizeof(char));
+}
+
+void AppendToBuffer(b, str, len)
+     register Buffer *b;
+     char *str;
+     register int len;
+{
+  while (b->used + len > b->room) {
+    b->buff = (char *)realloc(b->buff, 2*b->room*(sizeof(char)));
+    b->room *= 2;
+  }
+  strncpy(b->buff + b->used, str, len);
+  b->used += len;
+}
+
+void ReadFile(buffer, input)
+     register Buffer *buffer;
+     FILE *input;
+{
+  char       buf[BUFSIZ + 1];
+  register int        bytes;
+
+  buffer->used = 0;
+  while (!feof(input) && (bytes = fread(buf, 1, BUFSIZ, input)) > 0) {
+    AppendToBuffer(buffer, buf, bytes);
+  }
+  AppendToBuffer(buffer, "", 1);
+}
+
+main() 
+{
+  char * filename = "xbug.c";
+  FILE *input;
+  Buffer buffer;
+  
+  InitBuffer(&buffer);
+    
+  if (!freopen (filename, "r", stdin))
+    fprintf(stderr, "cannot open file\n");
+  
+  if (!(input = popen("/bin/cat", "r")))
+    fprintf(stderr, "cannot run \n");
+  
+  ReadFile(&buffer, input);
+  pclose(input);
+
+  return 0;
+}