aboutsummaryrefslogtreecommitdiff
path: root/stdio
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1995-02-18 01:27:10 +0000
committerRoland McGrath <roland@gnu.org>1995-02-18 01:27:10 +0000
commit28f540f45bbacd939bfd07f213bcad2bf730b1bf (patch)
tree15f07c4c43d635959c6afee96bde71fb1b3614ee /stdio
downloadglibc-28f540f45bbacd939bfd07f213bcad2bf730b1bf.tar
glibc-28f540f45bbacd939bfd07f213bcad2bf730b1bf.tar.gz
glibc-28f540f45bbacd939bfd07f213bcad2bf730b1bf.tar.bz2
glibc-28f540f45bbacd939bfd07f213bcad2bf730b1bf.zip
initial import
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;
+}