Many files moved from stdio to stdio-common.
authorroland <roland>
Mon, 16 Oct 1995 23:44:39 +0000 (23:44 +0000)
committerroland <roland>
Mon, 16 Oct 1995 23:44:39 +0000 (23:44 +0000)
63 files changed:
stdio-common/_itoa.c [new file with mode: 0644]
stdio-common/_itoa.h [new file with mode: 0644]
stdio-common/asprintf.c [new file with mode: 0644]
stdio-common/bug1.c [new file with mode: 0644]
stdio-common/bug1.input [new file with mode: 0644]
stdio-common/bug2.c [new file with mode: 0644]
stdio-common/bug3.c [new file with mode: 0644]
stdio-common/bug4.c [new file with mode: 0644]
stdio-common/bug5.c [new file with mode: 0644]
stdio-common/bug6.c [new file with mode: 0644]
stdio-common/bug6.input [new file with mode: 0644]
stdio-common/bug7.c [new file with mode: 0644]
stdio-common/dprintf.c [new file with mode: 0644]
stdio-common/errnobug.c [new file with mode: 0644]
stdio-common/fprintf.c [new file with mode: 0644]
stdio-common/fscanf.c [new file with mode: 0644]
stdio-common/getline.c [new file with mode: 0644]
stdio-common/getw.c [new file with mode: 0644]
stdio-common/perror.c [new file with mode: 0644]
stdio-common/printf-parse.h [new file with mode: 0644]
stdio-common/printf-prs.c [new file with mode: 0644]
stdio-common/printf.c [new file with mode: 0644]
stdio-common/printf.h [new file with mode: 0644]
stdio-common/printf_fp.c [new file with mode: 0644]
stdio-common/psignal.c [new file with mode: 0644]
stdio-common/putw.c [new file with mode: 0644]
stdio-common/reg-printf.c [new file with mode: 0644]
stdio-common/scanf.c [new file with mode: 0644]
stdio-common/snprintf.c [new file with mode: 0644]
stdio-common/sprintf.c [new file with mode: 0644]
stdio-common/sscanf.c [new file with mode: 0644]
stdio-common/tempnam.c [new file with mode: 0644]
stdio-common/temptest.c [new file with mode: 0644]
stdio-common/test-fseek.c [new file with mode: 0644]
stdio-common/test-fwrite.c [new file with mode: 0644]
stdio-common/test-popen.c [new file with mode: 0644]
stdio-common/test_rdwr.c [new file with mode: 0644]
stdio-common/tmpfile.c [new file with mode: 0644]
stdio-common/tmpnam.c [new file with mode: 0644]
stdio-common/tst-fileno.c [new file with mode: 0644]
stdio-common/tst-printf.c [new file with mode: 0644]
stdio-common/tstgetln.c [new file with mode: 0644]
stdio-common/tstgetln.input [new file with mode: 0644]
stdio-common/tstscanf.c [new file with mode: 0644]
stdio-common/tstscanf.input [new file with mode: 0644]
stdio-common/vasprintf.c [new file with mode: 0644]
stdio-common/vdprintf.c [new file with mode: 0644]
stdio-common/vfprintf.c [new file with mode: 0644]
stdio-common/vfscanf.c [new file with mode: 0644]
stdio-common/vprintf.c [new file with mode: 0644]
stdio-common/vscanf.c [new file with mode: 0644]
stdio-common/vsnprintf.c [new file with mode: 0644]
stdio-common/vsprintf.c [new file with mode: 0644]
stdio-common/vsscanf.c [new file with mode: 0644]
stdio-common/xbug.c [new file with mode: 0644]
stdio/vfprintf.c [deleted file]
stdio/vfscanf.c [deleted file]
stdio/vprintf.c [deleted file]
stdio/vscanf.c [deleted file]
stdio/vsnprintf.c [deleted file]
stdio/vsprintf.c [deleted file]
stdio/vsscanf.c [deleted file]
stdio/xbug.c [deleted file]

diff --git a/stdio-common/_itoa.c b/stdio-common/_itoa.c
new file mode 100644 (file)
index 0000000..caa8179
--- /dev/null
@@ -0,0 +1,418 @@
+/* Internal function for converting integers to ASCII.
+Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Contributed by Torbjorn Granlund <tege@matematik.su.se>
+and Ulrich Drepper <drepper@gnu.ai.mit.edu>.
+
+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 <gmp-mparam.h>
+#include "../stdlib/gmp.h"
+#include "../stdlib/gmp-impl.h"
+#include "../stdlib/longlong.h"
+
+#include "_itoa.h"
+
+
+/* Canonize environment.  For some architectures not all values might
+   be defined in the GMP header files.  */
+#ifndef UMUL_TIME
+# define UMUL_TIME 1
+#endif
+#ifndef UDIV_TIME
+# define UDIV_TIME 1
+#endif
+
+/* Control memory layout.  */
+#ifdef PACK
+# undef PACK
+# define PACK __attribute__ ((packed))
+#else
+# define PACK
+#endif
+
+
+/* Declare local types.  */
+struct base_table_t
+{
+#if (UDIV_TIME > 2 * UMUL_TIME)
+  mp_limb base_multiplier;
+#endif
+  char flag;
+  char post_shift;
+#if BITS_PER_MP_LIMB == 32
+  struct
+    {
+      char normalization_steps;
+      char ndigits;
+      mp_limb base PACK;
+#if UDIV_TIME > 2 * UMUL_TIME
+      mp_limb base_ninv PACK;
+#endif
+    } big;
+#endif
+};
+
+/* To reduce the memory needed we include some fields of the tables
+   only confitionally.  */
+#if BITS_PER_MP_LIMB == 32
+# if UDIV_TIME > 2 * UMUL_TIME
+#  define SEL1(X) X,
+#  define SEL2(X) ,X
+# else
+#  define SEL1(X)
+#  define SEL2(X)
+# endif
+#endif
+
+
+/* Local variables.  */
+static const struct base_table_t base_table[] =
+{
+#if BITS_PER_MP_LIMB == 64
+  /*  2 */ {0ul, 1, 1},
+  /*  3 */ {0xaaaaaaaaaaaaaaabul, 0, 1},
+  /*  4 */ {0ul, 1, 2},
+  /*  5 */ {0xcccccccccccccccdul, 0, 2},
+  /*  6 */ {0xaaaaaaaaaaaaaaabul, 0, 2},
+  /*  7 */ {0x2492492492492493ul, 1, 3},
+  /*  8 */ {0ul, 1, 3},
+  /*  9 */ {0xe38e38e38e38e38ful, 0, 3},
+  /* 10 */ {0xcccccccccccccccdul, 0, 3},
+  /* 11 */ {0x2e8ba2e8ba2e8ba3ul, 0, 1},
+  /* 12 */ {0xaaaaaaaaaaaaaaabul, 0, 3},
+  /* 13 */ {0x4ec4ec4ec4ec4ec5ul, 0, 2},
+  /* 14 */ {0x2492492492492493ul, 1, 4},
+  /* 15 */ {0x8888888888888889ul, 0, 3},
+  /* 16 */ {0ul, 1, 4},
+  /* 17 */ {0xf0f0f0f0f0f0f0f1ul, 0, 4},
+  /* 18 */ {0xe38e38e38e38e38ful, 0, 4},
+  /* 19 */ {0xd79435e50d79435ful, 0, 4},
+  /* 20 */ {0xcccccccccccccccdul, 0, 4},
+  /* 21 */ {0x8618618618618619ul, 1, 5},
+  /* 22 */ {0x2e8ba2e8ba2e8ba3ul, 0, 2},
+  /* 23 */ {0x642c8590b21642c9ul, 1, 5},
+  /* 24 */ {0xaaaaaaaaaaaaaaabul, 0, 4},
+  /* 25 */ {0x47ae147ae147ae15ul, 1, 5},
+  /* 26 */ {0x4ec4ec4ec4ec4ec5ul, 0, 3},
+  /* 27 */ {0x97b425ed097b425ful, 0, 4},
+  /* 28 */ {0x2492492492492493ul, 1, 5},
+  /* 29 */ {0x1a7b9611a7b9611bul, 1, 5},
+  /* 30 */ {0x8888888888888889ul, 0, 4},
+  /* 31 */ {0x0842108421084211ul, 1, 5},
+  /* 32 */ {0ul, 1, 5},
+  /* 33 */ {0x0f83e0f83e0f83e1ul, 0, 1},
+  /* 34 */ {0xf0f0f0f0f0f0f0f1ul, 0, 5},
+  /* 35 */ {0xea0ea0ea0ea0ea0ful, 0, 5},
+  /* 36 */ {0xe38e38e38e38e38ful, 0, 5}
+#endif
+#if BITS_PER_MP_LIMB == 32
+  /*  2 */ {SEL1(0ul) 1, 1, {0, 31, 0x80000000ul SEL2(0xfffffffful)}},
+  /*  3 */ {SEL1(0xaaaaaaabul) 0, 1, {0, 20, 0xcfd41b91ul SEL2(0x3b563c24ul)}},
+  /*  4 */ {SEL1(0ul) 1, 2, {1, 15, 0x40000000ul SEL2(0xfffffffful)}},
+  /*  5 */ {SEL1(0xcccccccdul) 0, 2, {1, 13, 0x48c27395ul SEL2(0xc25c2684ul)}},
+  /*  6 */ {SEL1(0xaaaaaaabul) 0, 2, {0, 12, 0x81bf1000ul SEL2(0xf91bd1b6ul)}},
+  /*  7 */ {SEL1(0x24924925ul) 1, 3, {1, 11, 0x75db9c97ul SEL2(0x1607a2cbul)}},
+  /*  8 */ {SEL1(0ul) 1, 3, {1, 10, 0x40000000ul SEL2(0xfffffffful)}},
+  /*  9 */ {SEL1(0x38e38e39ul) 0, 1, {0, 10, 0xcfd41b91ul SEL2(0x3b563c24ul)}},
+  /* 10 */ {SEL1(0xcccccccdul) 0, 3, {2, 9, 0x3b9aca00ul SEL2(0x12e0be82ul)}},
+  /* 11 */ {SEL1(0xba2e8ba3ul) 0, 3, {0, 9, 0x8c8b6d2bul SEL2(0xd24cde04ul)}},
+  /* 12 */ {SEL1(0xaaaaaaabul) 0, 3, {3, 8, 0x19a10000ul SEL2(0x3fa39ab5ul)}},
+  /* 13 */ {SEL1(0x4ec4ec4ful) 0, 2, {2, 8, 0x309f1021ul SEL2(0x50f8ac5ful)}},
+  /* 14 */ {SEL1(0x24924925ul) 1, 4, {1, 8, 0x57f6c100ul SEL2(0x74843b1eul)}},
+  /* 15 */ {SEL1(0x88888889ul) 0, 3, {0, 8, 0x98c29b81ul SEL2(0xad0326c2ul)}},
+  /* 16 */ {SEL1(0ul) 1, 4, {3, 7, 0x10000000ul SEL2(0xfffffffful)}},
+  /* 17 */ {SEL1(0xf0f0f0f1ul) 0, 4, {3, 7, 0x18754571ul SEL2(0x4ef0b6bdul)}},
+  /* 18 */ {SEL1(0x38e38e39ul) 0, 2, {2, 7, 0x247dbc80ul SEL2(0xc0fc48a1ul)}},
+  /* 19 */ {SEL1(0xaf286bcbul) 1, 5, {2, 7, 0x3547667bul SEL2(0x33838942ul)}},
+  /* 20 */ {SEL1(0xcccccccdul) 0, 4, {1, 7, 0x4c4b4000ul SEL2(0xad7f29abul)}},
+  /* 21 */ {SEL1(0x86186187ul) 1, 5, {1, 7, 0x6b5a6e1dul SEL2(0x313c3d15ul)}},
+  /* 22 */ {SEL1(0xba2e8ba3ul) 0, 4, {0, 7, 0x94ace180ul SEL2(0xb8cca9e0ul)}},
+  /* 23 */ {SEL1(0xb21642c9ul) 0, 4, {0, 7, 0xcaf18367ul SEL2(0x42ed6de9ul)}},
+  /* 24 */ {SEL1(0xaaaaaaabul) 0, 4, {4, 6, 0x0b640000ul SEL2(0x67980e0bul)}},
+  /* 25 */ {SEL1(0x51eb851ful) 0, 3, {4, 6, 0x0e8d4a51ul SEL2(0x19799812ul)}},
+  /* 26 */ {SEL1(0x4ec4ec4ful) 0, 3, {3, 6, 0x1269ae40ul SEL2(0xbce85396ul)}},
+  /* 27 */ {SEL1(0x2f684bdbul) 1, 5, {3, 6, 0x17179149ul SEL2(0x62c103a9ul)}},
+  /* 28 */ {SEL1(0x24924925ul) 1, 5, {3, 6, 0x1cb91000ul SEL2(0x1d353d43ul)}},
+  /* 29 */ {SEL1(0x8d3dcb09ul) 0, 4, {2, 6, 0x23744899ul SEL2(0xce1deceaul)}},
+  /* 30 */ {SEL1(0x88888889ul) 0, 4, {2, 6, 0x2b73a840ul SEL2(0x790fc511ul)}},
+  /* 31 */ {SEL1(0x08421085ul) 1, 5, {2, 6, 0x34e63b41ul SEL2(0x35b865a0ul)}},
+  /* 32 */ {SEL1(0ul) 1, 5, {1, 6, 0x40000000ul SEL2(0xfffffffful)}},
+  /* 33 */ {SEL1(0x3e0f83e1ul) 0, 3, {1, 6, 0x4cfa3cc1ul SEL2(0xa9aed1b3ul)}},
+  /* 34 */ {SEL1(0xf0f0f0f1ul) 0, 5, {1, 6, 0x5c13d840ul SEL2(0x63dfc229ul)}},
+  /* 35 */ {SEL1(0xd41d41d5ul) 1, 6, {1, 6, 0x6d91b519ul SEL2(0x2b0fee30ul)}},
+  /* 36 */ {SEL1(0x38e38e39ul) 0, 3, {0, 6, 0x81bf1000ul SEL2(0xf91bd1b6ul)}}
+#endif
+};
+
+/* Lower-case digits.  */
+static const char _itoa_lower_digits[]
+       = "0123456789abcdefghijklmnopqrstuvwxyz";
+/* Upper-case digits.  */
+static const char _itoa_upper_digits[]
+       = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+
+char *
+_itoa (value, buflim, base, upper_case)
+     unsigned long long int value;
+     char *buflim;
+     unsigned int base;
+     int upper_case;
+{
+  const char *digits = upper_case ? _itoa_upper_digits : _itoa_lower_digits;
+  char *bp = buflim;
+  const struct base_table_t *brec = &base_table[base - 2];
+
+  switch (base)
+    {
+#define RUN_2N(BITS)                                                     \
+      do                                                                 \
+        {                                                                \
+         /* `unsigned long long int' always has 64 bits.  */             \
+         mp_limb work_hi = value >> (64 - BITS_PER_MP_LIMB);             \
+                                                                         \
+         if (BITS_PER_MP_LIMB == 32)                                     \
+           if (work_hi != 0)                                             \
+             {                                                           \
+               mp_limb work_lo;                                          \
+               int cnt;                                                  \
+                                                                         \
+               work_lo = value & 0xfffffffful;                           \
+               for (cnt = BITS_PER_MP_LIMB / BITS; cnt > 0; --cnt)       \
+                 {                                                       \
+                   *--bp = digits[work_lo & ((1ul << BITS) - 1)];        \
+                   work_lo >>= BITS;                                     \
+                 }                                                       \
+               if (BITS_PER_MP_LIMB % BITS != 0)                         \
+                 {                                                       \
+                   work_lo |= ((work_hi                                  \
+                                & ((1 << BITS - BITS_PER_MP_LIMB % BITS) \
+                                   - 1))                                 \
+                               << BITS_PER_MP_LIMB % BITS);              \
+                   *--bp = digits[work_lo];                              \
+                   work_hi >>= BITS - BITS_PER_MP_LIMB % BITS;           \
+                 }                                                       \
+             }                                                           \
+           else                                                          \
+             work_hi = value & 0xfffffffful;                             \
+         do                                                              \
+           {                                                             \
+             *--bp = digits[work_hi & ((1 << BITS) - 1)];                \
+             work_hi >>= BITS;                                           \
+           }                                                             \
+         while (work_hi != 0);                                           \
+       }                                                                 \
+      while (0)
+    case 8:
+      RUN_2N (3);
+      break;
+
+    case 16:
+      RUN_2N (4);
+      break;
+
+    default:
+      {
+#if BITS_PER_MP_LIMB == 64
+       mp_limb base_multiplier = brec->base_multiplier;
+       if (brec->flag)
+         while (value != 0)
+           {
+             mp_limb quo, rem, x, dummy;
+
+             umul_ppmm (x, dummy, value, base_multiplier);
+             quo = (x + ((value - x) >> 1)) >> (brec->post_shift - 1);
+             rem = value - quo * base;
+             *--bp = digits[rem];
+             value = quo;
+           }
+       else
+         while (value != 0)
+           {
+             mp_limb quo, rem, x, dummy;
+
+             umul_ppmm (x, dummy, value, base_multiplier);
+             quo = x >> brec->post_shift;
+             rem = value - quo * base;
+             *--bp = digits[rem];
+             value = quo;
+           }
+#endif
+#if BITS_PER_MP_LIMB == 32
+       mp_limb t[3];
+       int n;
+
+       /* First convert x0 to 1-3 words in base s->big.base.
+          Optimize for frequent cases of 32 bit numbers.  */
+       if ((mp_limb) (value >> 32) >= 1)
+         {
+           int big_normalization_steps = brec->big.normalization_steps;
+           mp_limb big_base_norm = brec->big.base << big_normalization_steps;
+
+           if ((mp_limb) (value >> 32) >= brec->big.base)
+             {
+               mp_limb x1hi, x1lo, r;
+               /* If you want to optimize this, take advantage of
+                  that the quotient in the first udiv_qrnnd will
+                  always be very small.  It might be faster just to
+                  subtract in a tight loop.  */
+
+#if UDIV_TIME > 2 * UMUL_TIME
+               mp_limb x, xh, xl;
+
+               if (big_normalization_steps == 0)
+                 xh = 0;
+               else
+                 xh = (mp_limb) (value >> 64 - big_normalization_steps);
+               xl = (mp_limb) (value >> 32 - big_normalization_steps);
+               udiv_qrnnd_preinv (x1hi, r, xh, xl, big_base_norm,
+                                  brec->big.base_ninv);
+
+               xl = ((mp_limb) value) << big_normalization_steps;
+               udiv_qrnnd_preinv (x1lo, x, r, xl, big_base_norm,
+                                  big_normalization_steps);
+               t[2] = x >> big_normalization_steps;
+
+               if (big_normalization_steps == 0)
+                 xh = x1hi;
+               else
+                 xh = ((x1hi << big_normalization_steps)
+                       | (x1lo >> 32 - big_normalization_steps));
+               xl = x1lo << big_normalization_steps;
+               udiv_qrnnd_preinv (t[0], x, xh, xl, big_base_norm,
+                                  big_normalization_steps);
+               t[1] = x >> big_normalization_steps;
+#elif UDIV_NEEDS_NORMALIZATION
+               mp_limb x, xh, xl;
+
+               if (big_normalization_steps == 0)
+                 xh = 0;
+               else
+                 xh = (mp_limb) (value >> 64 - big_normalization_steps);
+               xl = (mp_limb) (value >> 32 - big_normalization_steps);
+               udiv_qrnnd (x1hi, r, xh, xl, big_base_norm);
+
+               xl = ((mp_limb) value) << big_normalization_steps;
+               udiv_qrnnd (x1lo, x, r, xl, big_base_norm);
+               t[2] = x >> big_normalization_steps;
+
+               if (big_normalization_steps == 0)
+                 xh = x1hi;
+               else
+                 xh = ((x1hi << big_normalization_steps)
+                       | (x1lo >> 32 - big_normalization_steps));
+               xl = x1lo << big_normalization_steps;
+               udiv_qrnnd (t[0], x, xh, xl, big_base_norm);
+               t[1] = x >> big_normalization_steps;
+#else
+               udiv_qrnnd (x1hi, r, 0, (mp_limb) (value >> 32),
+                           brec->big.base);
+               udiv_qrnnd (x1lo, t[2], r, (mp_limb) value, brec->big.base);
+               udiv_qrnnd (t[0], t[1], x1hi, x1lo, brec->big.base);
+#endif
+               n = 3;
+             }
+           else
+             {
+#if (UDIV_TIME > 2 * UMUL_TIME)
+               mp_limb x;
+
+               value <<= brec->big.normalization_steps;
+               udiv_qrnnd_preinv (t[0], x, (mp_limb) (value >> 32),
+                                  (mp_limb) value, big_base_norm,
+                                  brec->big.base_ninv);
+               t[1] = x >> brec->big.normalization_steps;
+#elif UDIV_NEEDS_NORMALIZATION
+               mp_limb x;
+
+               value <<= big_normalization_steps;
+               udiv_qrnnd (t[0], x, (mp_limb) (value >> 32),
+                           (mp_limb) value, big_base_norm);
+               t[1] = x >> big_normalization_steps;
+#else
+               udiv_qrnnd (t[0], t[1], (mp_limb) (value >> 32),
+                           (mp_limb) value, brec->big.base);
+#endif
+               n = 2;
+             }
+         }
+       else
+         {
+           t[0] = value;
+           n = 1;
+         }
+
+       /* Convert the 1-3 words in t[], word by word, to ASCII.  */
+       do
+         {
+           mp_limb ti = t[--n];
+           int ndig_for_this_limb = 0;
+
+#if UDIV_TIME > 2 * UMUL_TIME
+           mp_limb base_multiplier = brec->base_multiplier;
+           if (brec->flag)
+             while (ti != 0)
+               {
+                 mp_limb quo, rem, x, dummy;
+
+                 umul_ppmm (x, dummy, ti, base_multiplier);
+                 quo = (x + ((ti - x) >> 1)) >> (brec->post_shift - 1);
+                 rem = ti - quo * base;
+                 *--bp = digits[rem];
+                 ti = quo;
+                 ++ndig_for_this_limb;
+               }
+           else
+             while (ti != 0)
+               {
+                 mp_limb quo, rem, x, dummy;
+
+                 umul_ppmm (x, dummy, ti, base_multiplier);
+                 quo = x >> brec->post_shift;
+                 rem = ti - quo * base;
+                 *--bp = digits[rem];
+                 ti = quo;
+                 ++ndig_for_this_limb;
+               }
+#else
+           while (ti != 0)
+             {
+               mp_limb quo, rem;
+
+               quo = ti / base;
+               rem = ti % base;
+               *--bp = digits[rem];
+               ti = quo;
+               ++ndig_for_this_limb;
+             }
+#endif
+           /* If this wasn't the most significant word, pad with zeros.  */
+           if (n != 0)
+             while (ndig_for_this_limb < brec->big.ndigits)
+               {
+                 *--bp = '0';
+                 ++ndig_for_this_limb;
+               }
+         }
+       while (n != 0);
+#endif
+      }
+      break;
+    }
+
+  return bp;
+}
diff --git a/stdio-common/_itoa.h b/stdio-common/_itoa.h
new file mode 100644 (file)
index 0000000..ab3d1d1
--- /dev/null
@@ -0,0 +1,32 @@
+/* Internal function for converting integers to ASCII.
+Copyright (C) 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.  */
+
+#ifndef _ITOA_H
+#define _ITOA_H
+#include <sys/cdefs.h>
+
+/* 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));
+
+#endif /* itoa.h */
diff --git a/stdio-common/asprintf.c b/stdio-common/asprintf.c
new file mode 100644 (file)
index 0000000..9b69800
--- /dev/null
@@ -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-common/bug1.c b/stdio-common/bug1.c
new file mode 100644 (file)
index 0000000..755bc42
--- /dev/null
@@ -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-common/bug1.input b/stdio-common/bug1.input
new file mode 100644 (file)
index 0000000..5595fa4
--- /dev/null
@@ -0,0 +1 @@
+95
diff --git a/stdio-common/bug2.c b/stdio-common/bug2.c
new file mode 100644 (file)
index 0000000..2b34c89
--- /dev/null
@@ -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-common/bug3.c b/stdio-common/bug3.c
new file mode 100644 (file)
index 0000000..1684720
--- /dev/null
@@ -0,0 +1,52 @@
+#include <ansidecl.h>
+#include <stdio.h>
+#include <string.h>
+
+int
+DEFUN_VOID(main)
+{
+  FILE *f;
+  int i;
+
+  f = fopen("/tmp/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-common/bug4.c b/stdio-common/bug4.c
new file mode 100644 (file)
index 0000000..00abf3c
--- /dev/null
@@ -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("/tmp/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-common/bug5.c b/stdio-common/bug5.c
new file mode 100644 (file)
index 0000000..18f069a
--- /dev/null
@@ -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[] = "/tmp/bug5.in";
+  static char outname[] = "/tmp/bug5.out";
+  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-common/bug6.c b/stdio-common/bug6.c
new file mode 100644 (file)
index 0000000..4a37ab2
--- /dev/null
@@ -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-common/bug6.input b/stdio-common/bug6.input
new file mode 100644 (file)
index 0000000..d996e39
--- /dev/null
@@ -0,0 +1 @@
+XY 1234L
diff --git a/stdio-common/bug7.c b/stdio-common/bug7.c
new file mode 100644 (file)
index 0000000..af06f8d
--- /dev/null
@@ -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-common/dprintf.c b/stdio-common/dprintf.c
new file mode 100644 (file)
index 0000000..fc9faa4
--- /dev/null
@@ -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-common/errnobug.c b/stdio-common/errnobug.c
new file mode 100644 (file)
index 0000000..cf17be3
--- /dev/null
@@ -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-common/fprintf.c b/stdio-common/fprintf.c
new file mode 100644 (file)
index 0000000..bc6d100
--- /dev/null
@@ -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-common/fscanf.c b/stdio-common/fscanf.c
new file mode 100644 (file)
index 0000000..cbe0103
--- /dev/null
@@ -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-common/getline.c b/stdio-common/getline.c
new file mode 100644 (file)
index 0000000..1a2f975
--- /dev/null
@@ -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-common/getw.c b/stdio-common/getw.c
new file mode 100644 (file)
index 0000000..45d4d88
--- /dev/null
@@ -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-common/perror.c b/stdio-common/perror.c
new file mode 100644 (file)
index 0000000..1054aca
--- /dev/null
@@ -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, size_t));
+
+/* 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, sizeof buf));
+}
diff --git a/stdio-common/printf-parse.h b/stdio-common/printf-parse.h
new file mode 100644 (file)
index 0000000..0f6e9e2
--- /dev/null
@@ -0,0 +1,388 @@
+/* Internal header for parsing printf format strings.
+Copyright (C) 1995 Free Software Foundation, Inc.
+This file is part of th 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 <ctype.h>
+#include <printf.h>
+#include <string.h>
+#include <stddef.h>
+
+#define NDEBUG 1
+#include <assert.h>
+
+#define MAX(a,b)       ({typeof(a) _a = (a); typeof(b) _b = (b);             \
+                         _a > _b ? _a : _b; })
+#define MIN(a,b)       ({typeof(a) _a = (a); typeof(b) _b = (b);             \
+                         _a < _b ? _a : _b; })
+
+struct printf_spec
+  {
+    /* Information parsed from the format spec.  */ 
+    struct printf_info info;
+
+    /* Pointers into the format string for the end of this format
+       spec and the next (or to the end of the string if no more).  */
+    const char *end_of_fmt, *next_fmt;
+
+    /* Position of arguments for precision and width, or -1 if `info' has
+       the constant value.  */
+    int prec_arg, width_arg;
+
+    int data_arg;              /* Position of data argument.  */
+    int data_arg_type;         /* Type of first argument.  */
+    /* Number of arguments consumed by this format specifier.  */
+    size_t ndata_args;
+  };
+
+
+/* The various kinds off arguments that can be passed to printf.  */
+union printf_arg
+  {
+    unsigned char pa_char;
+    short int pa_short_int;
+    int pa_int;
+    long int pa_long_int;
+    long long int pa_long_long_int;
+    unsigned short int pa_u_short_int;
+    unsigned int pa_u_int;
+    unsigned long int pa_u_long_int;
+    unsigned long long int pa_u_long_long_int;
+    float pa_float;
+    double pa_double;
+    long double pa_long_double;
+    const char *pa_string;
+    void *pa_pointer;
+  };
+
+
+/* Read a simple integer from a string and update the string pointer.
+   It is assumed that the first character is a digit.  */
+static inline unsigned int
+read_int (const char * *pstr)
+{
+  unsigned int retval = **pstr - '0';
+
+  while (isdigit (*++(*pstr)))
+    {
+      retval *= 10;
+      retval += **pstr - '0';
+    }
+
+  return retval;
+}
+
+
+
+/* Find the next spec in FORMAT, or the end of the string.  Returns
+   a pointer into FORMAT, to a '%' or a '\0'.  */
+static inline const char *
+find_spec (const char *format)
+{
+  while (*format != '\0' && *format != '%')
+    {
+      int len;
+
+      if (isascii (*format) || (len = mblen (format, MB_CUR_MAX)) <= 0)
+       ++format;
+      else
+       format += len;
+    }
+  return format;
+}
+
+
+/* This is defined in reg-printf.c.  */
+extern printf_arginfo_function **__printf_arginfo_table;
+
+
+/* FORMAT must point to a '%' at the beginning of a spec.  Fills in *SPEC
+   with the parsed details.  POSN is the number of arguments already
+   consumed.  At most MAXTYPES - POSN types are filled in TYPES.  Return
+   the number of args consumed by this spec; *MAX_REF_ARG is updated so it
+   remains the highest argument index used.  */
+static inline size_t
+parse_one_spec (const char *format, size_t posn, struct printf_spec *spec,
+               size_t *max_ref_arg)
+{
+  unsigned int n;
+  size_t nargs = 0;
+
+  /* Skip the '%'.  */
+  ++format;
+
+  /* Clear information structure.  */
+  spec->data_arg = -1;
+  spec->info.alt = 0;
+  spec->info.space = 0;
+  spec->info.left = 0;
+  spec->info.showsign = 0;
+  spec->info.group = 0;
+  spec->info.pad = ' ';
+
+  /* Test for positional argument.  */
+  if (isdigit (*format))
+    {
+      const char *begin = format;
+
+      n = read_int (&format);
+
+      if (n > 0 && *format == '$')
+       /* Is positional parameter.  */
+       {
+         ++format;             /* Skip the '$'.  */
+         spec->data_arg = n - 1;
+         *max_ref_arg = MAX (*max_ref_arg, n);
+       }
+      else
+       /* Oops; that was actually the width and/or 0 padding flag.
+          Step back and read it again.  */
+       format = begin;
+    }
+
+  /* Check for spec modifiers.  */
+  while (*format == ' ' || *format == '+' || *format == '-' ||
+        *format == '#' || *format == '0' || *format == '\'')
+    switch (*format++)
+      {
+      case ' ':
+       /* Output a space in place of a sign, when there is no sign.  */
+       spec->info.space = 1;
+       break;
+      case '+':
+       /* Always output + or - for numbers.  */
+       spec->info.showsign = 1;
+       break;
+      case '-':
+       /* Left-justify things.  */
+       spec->info.left = 1;
+       break;
+      case '#':
+       /* Use the "alternate form":
+          Hex has 0x or 0X, FP always has a decimal point.  */
+       spec->info.alt = 1;
+       break;
+      case '0':
+       /* Pad with 0s.  */
+       spec->info.pad = '0';
+       break;
+      case '\'':
+       /* Show grouping in numbers if the locale information
+          indicates any.  */
+       spec->info.group = 1;
+       break;
+      }
+  if (spec->info.left)
+    spec->info.pad = ' ';
+
+  /* Get the field width.  */
+  spec->width_arg = -1;
+  spec->info.width = 0;
+  if (*format == '*')
+    {
+      /* The field width is given in an argument.
+        A negative field width indicates left justification.  */
+      const char *begin = ++format;
+
+      if (isdigit (*format))
+       {
+         /* The width argument might be found in a positional parameter.  */
+         n = read_int (&format);
+
+         if (n > 0 && *format == '$')
+           {
+             spec->width_arg = n - 1;
+             *max_ref_arg = MAX (*max_ref_arg, n);
+             ++format;         /* Skip '$'.  */
+           }
+       }
+
+      if (spec->width_arg < 0)
+       {
+         /* Not in a positional parameter.  Consume one argument.  */
+         spec->width_arg = posn++;
+         ++nargs;
+         format = begin;       /* Step back and reread.  */
+       }
+    }
+  else if (isdigit (*format))
+    /* Constant width specification.  */
+    spec->info.width = read_int (&format);
+
+  /* Get the precision.  */
+  spec->prec_arg = -1;
+  /* -1 means none given; 0 means explicit 0.  */
+  spec->info.prec = -1;
+  if (*format == '.')
+    {
+      ++format;
+      if (*format == '*')
+       {
+         /* The precision is given in an argument.  */
+         const char *begin = ++format;
+
+         if (isdigit (*format))
+           {
+             n = read_int (&format);
+
+             if (n > 0 && *format == '$')
+               {
+                 spec->prec_arg = n - 1;
+                 *max_ref_arg = MAX (*max_ref_arg, n);
+                 ++format;
+               }
+           }
+
+         if (spec->prec_arg < 0)
+           {
+             /* Not in a positional parameter.  */
+             spec->prec_arg = posn++;
+             ++nargs;
+             format = begin;
+           }
+       }
+      else if (isdigit (*format))
+       spec->info.prec = read_int (&format);
+      else
+       /* "%.?" is treated like "%.0?".  */
+       spec->info.prec = 0;
+
+      /* If there was a precision specified, ignore the 0 flag and always
+        pad with spaces.  */
+      spec->info.pad = ' ';
+    }
+
+  /* Check for type modifiers.  */
+#define is_longlong is_long_double
+  spec->info.is_long_double = 0;
+  spec->info.is_short = 0;
+  spec->info.is_long = 0;
+
+  while (*format == 'h' || *format == 'l' || *format == 'L' ||
+        *format == 'Z' || *format == 'q')
+    switch (*format++)
+      {
+      case 'h':
+       /* int's are short int's.  */
+       spec->info.is_short = 1;
+       break;
+      case 'l':
+       if (spec->info.is_long)
+         /* A double `l' is equivalent to an `L'.  */
+         spec->info.is_longlong = 1;
+       else
+         /* int's are long int's.  */
+         spec->info.is_long = 1;
+       break;
+      case 'L':
+       /* double's are long double's, and int's are long long int's.  */
+       spec->info.is_long_double = 1;
+       break;
+      case 'Z':
+       /* int's are size_t's.  */
+       assert (sizeof(size_t) <= sizeof(unsigned long long int));
+       spec->info.is_longlong = sizeof(size_t) > sizeof(unsigned long int);
+       spec->info.is_long = sizeof(size_t) > sizeof(unsigned int);
+       break;
+      case 'q':
+       /* 4.4 uses this for long long.  */
+       spec->info.is_longlong = 1;
+       break;
+      }
+
+  /* Get the format specification.  */
+  spec->info.spec = *format++;
+  if (__printf_arginfo_table != NULL &&
+      __printf_arginfo_table[spec->info.spec] != NULL)
+    /* We don't try to get the types for all arguments if the format
+       uses more than one.  The normal case is covered though.  */
+    spec->ndata_args = (*__printf_arginfo_table[spec->info.spec])
+      (&spec->info, 1, &spec->data_arg_type);
+  else
+    {
+      /* Find the data argument types of a built-in spec.  */
+      spec->ndata_args = 1;
+
+      switch (spec->info.spec)
+       {
+       case 'i':
+       case 'd':
+       case 'u':
+       case 'o':
+       case 'X':
+       case 'x':
+         if (spec->info.is_longlong)
+           spec->data_arg_type = PA_INT|PA_FLAG_LONG_LONG;
+         else if (spec->info.is_long)
+           spec->data_arg_type = PA_INT|PA_FLAG_LONG;
+         else if (spec->info.is_short)
+           spec->data_arg_type = PA_INT|PA_FLAG_SHORT;
+         else
+           spec->data_arg_type = PA_INT;
+         break;
+       case 'e':
+       case 'E':
+       case 'f':
+       case 'g':
+       case 'G':
+         if (spec->info.is_long_double)
+           spec->data_arg_type = PA_DOUBLE|PA_FLAG_LONG_DOUBLE;
+         else
+           spec->data_arg_type = PA_DOUBLE;
+         break;
+       case 'c':
+         spec->data_arg_type = PA_CHAR;
+         break;
+       case 's':
+         spec->data_arg_type = PA_STRING;
+         break;
+       case 'p':
+         spec->data_arg_type = PA_POINTER;
+         break;
+       case 'n':
+         spec->data_arg_type = PA_INT|PA_FLAG_PTR;
+         break;
+
+       case 'm':
+       default:
+         /* An unknown spec will consume no args.  */
+         spec->ndata_args = 0;
+         break;
+       }
+
+      if (spec->data_arg == -1 && spec->ndata_args > 0) 
+       {
+         /* There are args consumed, but no positional spec.
+            Use the next sequential arg position.  */
+         spec->data_arg = posn;
+         posn += spec->ndata_args;
+         nargs += spec->ndata_args;
+       }
+    }
+
+  if (spec->info.spec == '\0')
+    /* Format ended before this spec was complete.  */
+    spec->end_of_fmt = spec->next_fmt = format - 1;
+  else
+    {
+      /* Find the next format spec.  */
+      spec->end_of_fmt = format;
+      spec->next_fmt = find_spec (format);
+    }
+
+  return nargs;
+}
diff --git a/stdio-common/printf-prs.c b/stdio-common/printf-prs.c
new file mode 100644 (file)
index 0000000..811a9cb
--- /dev/null
@@ -0,0 +1,72 @@
+/* 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 <stdio.h>
+#include <printf.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "printf-parse.h"
+
+
+size_t
+parse_printf_format (fmt, n, argtypes)
+      const char *fmt;
+      size_t n;
+      int *argtypes;
+{
+  size_t nargs;                        /* Number of arguments.  */
+  size_t max_ref_arg;          /* Highest index used in a positional arg.  */
+  struct printf_spec spec;
+
+  nargs = 0;
+  max_ref_arg = 0;
+
+  /* Search for format specifications.  */
+  for (fmt = find_spec (fmt); *fmt != '\0'; fmt = spec.next_fmt)
+    {
+      /* Parse this spec.  */
+      nargs += parse_one_spec (fmt, nargs, &spec, &max_ref_arg);
+
+      /* If the width is determined by an argument this is an int.  */
+      if (spec.width_arg != -1 && spec.width_arg < n)
+       argtypes[spec.width_arg] = PA_INT;
+
+      /* If the precision is determined by an argument this is an int.  */
+      if (spec.prec_arg != -1 && spec.prec_arg < n)
+       argtypes[spec.prec_arg] = PA_INT;
+
+      if (spec.data_arg < n)
+       switch (spec.ndata_args)
+         {
+         case 0:               /* No arguments.  */
+           break;
+         case 1:               /* One argument; we already have the type.  */
+           argtypes[spec.data_arg] = spec.data_arg_type;
+           break;
+         default:
+           /* We have more than one argument for this format spec.  We must
+               call the arginfo function again to determine all the types.  */
+           (void) (*__printf_arginfo_table[spec.info.spec])
+             (&spec.info, n - spec.data_arg, &argtypes[spec.data_arg]);
+           break;
+         }
+    }
+
+  return MAX (nargs, max_ref_arg);
+}
diff --git a/stdio-common/printf.c b/stdio-common/printf.c
new file mode 100644 (file)
index 0000000..9cdae76
--- /dev/null
@@ -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-common/printf.h b/stdio-common/printf.h
new file mode 100644 (file)
index 0000000..0f381c7
--- /dev/null
@@ -0,0 +1,124 @@
+/* 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>
+
+
+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.
+   ARGS is a vector of pointers to the argument data;
+   the number of pointers will be the number returned
+   by the associated arginfo function for the same INFO.
+
+   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,
+                                 __const void **__const __args));
+
+/* Type of a printf specifier-arginfo function.
+   INFO gives information about the format specification.
+   N, ARGTYPES, and return value are as for printf_parse_format.  */
+
+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 must be
+   specified to determine how many arguments a SPEC conversion requires and
+   what their types are, even if your program never calls
+   `parse_printf_format'.  */
+
+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-common/printf_fp.c b/stdio-common/printf_fp.c
new file mode 100644 (file)
index 0000000..28d13d6
--- /dev/null
@@ -0,0 +1,990 @@
+/* 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 "../stdlib/gmp.h"
+#include "../stdlib/gmp-impl.h"
+#include "../stdlib/longlong.h"
+#include "../stdlib/fpioconst.h"
+#include "../locale/localeinfo.h"
+#include <limits.h>
+#include <math.h>
+#include <printf.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#define NDEBUG                 /* Undefine this for debugging assertions.  */
+#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 */
+\f
+/* 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)
+\f
+/* 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);
+
+
+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;
+     const **const 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, _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT),
+             strlen (_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT))) <= 0)
+    decimal = (wchar_t) *_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
+
+
+  if (info->group)
+    {
+      grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
+      if (*grouping <= 0 || *grouping == CHAR_MAX)
+       grouping = NULL;
+      else
+       {
+         /* Figure out the thousands seperator character.  */
+         if (mbtowc (&thousands_sep, _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
+                     strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0)
+           thousands_sep = (wchar_t) *_NL_CURRENT (LC_NUMERIC, 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 = *(const long double *) args[0];
+
+      /* 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 = *(const double *) args[0];
+
+      /* 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;
+}
+\f
+/* 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 > (unsigned int) *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 > (unsigned int) *grouping);
+
+  /* Copy the remaining ungrouped digits.  */
+  do
+    *p-- = buf[--intdig_no];
+  while (p > buf);
+
+  return bufend + groups;
+}
diff --git a/stdio-common/psignal.c b/stdio-common/psignal.c
new file mode 100644 (file)
index 0000000..8997a2e
--- /dev/null
@@ -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-common/putw.c b/stdio-common/putw.c
new file mode 100644 (file)
index 0000000..1b70bae
--- /dev/null
@@ -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-common/reg-printf.c b/stdio-common/reg-printf.c
new file mode 100644 (file)
index 0000000..95d7a1f
--- /dev/null
@@ -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-common/scanf.c b/stdio-common/scanf.c
new file mode 100644 (file)
index 0000000..aa70215
--- /dev/null
@@ -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-common/snprintf.c b/stdio-common/snprintf.c
new file mode 100644 (file)
index 0000000..9f3e0c4
--- /dev/null
@@ -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-common/sprintf.c b/stdio-common/sprintf.c
new file mode 100644 (file)
index 0000000..ce3a970
--- /dev/null
@@ -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-common/sscanf.c b/stdio-common/sscanf.c
new file mode 100644 (file)
index 0000000..33bc203
--- /dev/null
@@ -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-common/tempnam.c b/stdio-common/tempnam.c
new file mode 100644 (file)
index 0000000..14988a8
--- /dev/null
@@ -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-common/temptest.c b/stdio-common/temptest.c
new file mode 100644 (file)
index 0000000..3747198
--- /dev/null
@@ -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-common/test-fseek.c b/stdio-common/test-fseek.c
new file mode 100644 (file)
index 0000000..d56c669
--- /dev/null
@@ -0,0 +1,67 @@
+#include <ansidecl.h>
+#include <stdio.h>
+
+#define TESTFILE "/tmp/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-common/test-fwrite.c b/stdio-common/test-fwrite.c
new file mode 100644 (file)
index 0000000..cc6cdf0
--- /dev/null
@@ -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-common/test-popen.c b/stdio-common/test-popen.c
new file mode 100644 (file)
index 0000000..b452f3f
--- /dev/null
@@ -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 >/tmp/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 /tmp/tstpopen.tmp", "r");
+  if (input == NULL)
+    {
+      perror ("/tmp/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-common/test_rdwr.c b/stdio-common/test_rdwr.c
new file mode 100644 (file)
index 0000000..f987f16
--- /dev/null
@@ -0,0 +1,130 @@
+/* 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 <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-common/tmpfile.c b/stdio-common/tmpfile.c
new file mode 100644 (file)
index 0000000..dfe11ad
--- /dev/null
@@ -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-common/tmpnam.c b/stdio-common/tmpnam.c
new file mode 100644 (file)
index 0000000..88dd0a4
--- /dev/null
@@ -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-common/tst-fileno.c b/stdio-common/tst-fileno.c
new file mode 100644 (file)
index 0000000..81945f7
--- /dev/null
@@ -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-common/tst-printf.c b/stdio-common/tst-printf.c
new file mode 100644 (file)
index 0000000..c177da1
--- /dev/null
@@ -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");
+}
+\f
+/* 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);
+}
+\f
+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);
+}
+\f
+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-common/tstgetln.c b/stdio-common/tstgetln.c
new file mode 100644 (file)
index 0000000..ea8ea81
--- /dev/null
@@ -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-common/tstgetln.input b/stdio-common/tstgetln.input
new file mode 100644 (file)
index 0000000..d04ed5b
--- /dev/null
@@ -0,0 +1,3 @@
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
+z
diff --git a/stdio-common/tstscanf.c b/stdio-common/tstscanf.c
new file mode 100644 (file)
index 0000000..53d4b0a
--- /dev/null
@@ -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-common/tstscanf.input b/stdio-common/tstscanf.input
new file mode 100644 (file)
index 0000000..2615865
--- /dev/null
@@ -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-common/vasprintf.c b/stdio-common/vasprintf.c
new file mode 100644 (file)
index 0000000..d2ad6b1
--- /dev/null
@@ -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-common/vdprintf.c b/stdio-common/vdprintf.c
new file mode 100644 (file)
index 0000000..9df4e53
--- /dev/null
@@ -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-common/vfprintf.c b/stdio-common/vfprintf.c
new file mode 100644 (file)
index 0000000..63a5148
--- /dev/null
@@ -0,0 +1,858 @@
+/* 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 <ctype.h>
+#include <errno.h>
+#include <float.h>
+#include <limits.h>
+#include <math.h>
+#include <printf.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <printf.h>
+#include <stddef.h>
+#include "_itoa.h"
+#include "../locale/localeinfo.h"
+
+/* Include the shared code for parsing the format string.  */
+#include "printf-parse.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)                                                         \
+  if (specs[cnt].info.width > 0)                                             \
+    done += _IO_padn (s, padchar, specs[cnt].info.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, size_t n));
+#define PAD(padchar)                                                         \
+  if (specs[cnt].info.width > 0)                                             \
+    { if (__printf_pad (s, padchar, specs[cnt].info.width) == -1)            \
+       return -1; else done += specs[cnt].info.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)
+
+#define outstring(string, len)                                               \
+  do                                                                         \
+    {                                                                        \
+      if (len > 20)                                                          \
+       {                                                                     \
+         if (PUT (s, string, len) != len)                                    \
+           return -1;                                                        \
+         done += len;                                                        \
+       }                                                                     \
+      else                                                                   \
+       {                                                                     \
+         register const char *cp = string;                                   \
+         register int l = len;                                               \
+         while (l-- > 0)                                                     \
+           outchar (*cp++);                                                  \
+       }                                                                     \
+    } while (0)
+
+/* Helper function to provide temporary buffering for unbuffered streams.  */
+static int buffered_vfprintf __P ((FILE *stream, const char *fmt, va_list));
+
+static printf_function printf_unknown;
+
+extern printf_function **__printf_function_table;
+
+static char *group_number __P ((char *, char *, const char *, wchar_t));
+
+
+int
+vfprintf (s, format, ap)
+    register FILE *s;
+    const char *format;
+    va_list ap;
+{
+  /* The character used as thousands separator.  */
+  wchar_t thousands_sep;
+
+  /* The string describing the size of groups of digits.  */
+  const char *grouping;
+
+  /* Array with information about the needed arguments.  This has to be
+     dynamically extendable.  */
+  size_t nspecs;
+  size_t nspecs_max;
+  struct printf_spec *specs;
+
+  /* The number of arguments the format string requests.  This will
+     determine the size of the array needed to store the argument
+     attributes.  */
+  size_t nargs;
+  int *args_type;
+  union printf_arg *args_value;
+
+  /* Positional parameters refer to arguments directly.  This could also
+     determine the maximum number of arguments.  Track the maximum number.  */
+  size_t max_ref_arg;
+
+  /* End of leading constant string.  */
+  const char *lead_str_end;
+
+  /* Number of characters written.  */
+  register size_t done = 0;
+
+  /* Running pointer through format string.  */
+  const char *f;
+
+  /* Just a counter.  */
+  int cnt;
+
+  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, ap);
+
+  /* Reset multibyte characters to their initial state.  */
+  (void) mblen ((char *) NULL, 0);
+
+  /* Figure out the thousands separator character.  */
+  if (mbtowc (&thousands_sep, _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
+              strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0)
+    thousands_sep = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
+  grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
+  if (*grouping == '\0' || *grouping == CHAR_MAX || thousands_sep == L'\0')
+    grouping = NULL;
+
+  nspecs_max = 32;             /* A more or less arbitrary start value.  */
+  specs = alloca (nspecs_max * sizeof (struct printf_spec));
+  nspecs = 0;
+  nargs = 0;
+  max_ref_arg = 0;
+
+  /* Find the first format specifier.  */
+  lead_str_end = find_spec (format);
+
+  for (f = lead_str_end; *f != '\0'; f = specs[nspecs++].next_fmt)
+    {
+      if (nspecs >= nspecs_max)
+       {
+         /* Extend the array of format specifiers.  */
+         struct printf_spec *old = specs;
+
+         nspecs_max *= 2;
+         specs = alloca (nspecs_max * sizeof (struct printf_spec));
+         if (specs == &old[nspecs])
+           /* Stack grows up, OLD was the last thing allocated; extend it.  */
+           nspecs_max += nspecs_max / 2;
+         else
+           {
+             /* Copy the old array's elements to the new space.  */
+             memcpy (specs, old, nspecs * sizeof (struct printf_spec));
+             if (old == &specs[nspecs])
+               /* Stack grows down, OLD was just below the new SPECS.
+                  We can use that space when the new space runs out.  */
+               nspecs_max += nspecs_max / 2;
+           }
+       }
+
+      /* Parse the format specifier.  */
+      nargs += parse_one_spec (f, nargs, &specs[nspecs], &max_ref_arg);
+    }
+
+  /* Determine the number of arguments the format string consumes.  */
+  nargs = MAX (nargs, max_ref_arg);
+
+  /* Allocate memory for the argument descriptions.  */
+  args_type = alloca (nargs * sizeof (int));
+  args_value = alloca (nargs * sizeof (union printf_arg));
+
+  /* XXX Could do sanity check here:
+     Initialize args_type elts to zero.
+     If any is still zero after this loop, format is invalid.  */
+
+  /* Fill in the types of all the arguments.  */
+  for (cnt = 0; cnt < nspecs; ++cnt)
+    {
+      /* If the width is determined by an argument this is an int.  */ 
+      if (specs[cnt].width_arg != -1)
+       args_type[specs[cnt].width_arg] = PA_INT;
+
+      /* If the precision is determined by an argument this is an int.  */ 
+      if (specs[cnt].prec_arg != -1)
+       args_type[specs[cnt].prec_arg] = PA_INT;
+
+      switch (specs[cnt].ndata_args)
+       {
+       case 0:                 /* No arguments.  */
+         break;
+       case 1:                 /* One argument; we already have the type.  */
+         args_type[specs[cnt].data_arg] = specs[cnt].data_arg_type;
+         break;
+       default:
+         /* We have more than one argument for this format spec.  We must
+            call the arginfo function again to determine all the types.  */
+         (void) (*__printf_arginfo_table[specs[cnt].info.spec])
+           (&specs[cnt].info,
+            specs[cnt].ndata_args, &args_type[specs[cnt].data_arg]);
+         break;
+       }
+    }
+
+  /* Now we know all the types and the order.  Fill in the argument values.  */
+  for (cnt = 0; cnt < nargs; ++cnt)
+    switch (args_type[cnt])
+      {
+#define T(tag, mem, type)                                                    \
+      case tag:                                                                      \
+       args_value[cnt].mem = va_arg (ap, type);                              \
+       break
+
+       T (PA_CHAR, pa_char, int); /* Promoted.  */
+       T (PA_INT|PA_FLAG_SHORT, pa_short_int, int); /* Promoted.  */
+       T (PA_INT, pa_int, int);
+       T (PA_INT|PA_FLAG_LONG, pa_long_int, long int);
+       T (PA_INT|PA_FLAG_LONG_LONG, pa_long_long_int, long long int);
+       T (PA_FLOAT, pa_float, double); /* Promoted.  */
+       T (PA_DOUBLE, pa_double, double);
+       T (PA_DOUBLE|PA_FLAG_LONG_DOUBLE, pa_long_double, long double);
+       T (PA_STRING, pa_string, const char *);
+       T (PA_POINTER, pa_pointer, void *);
+#undef T
+      default:
+       if ((args_type[cnt] & PA_FLAG_PTR) != 0)
+         args_value[cnt].pa_pointer = va_arg (ap, void *);
+       break;
+      }
+
+  /* Write the literal text before the first format.  */
+  outstring (format, lead_str_end - format);
+
+  /* Now walk through all format specifiers and process them.  */
+  for (cnt = 0; cnt < nspecs; ++cnt)
+    {
+      printf_function *function; /* Auxiliary function to do output.  */
+      int is_neg;              /* Decimal integer is negative.  */
+      int base;                        /* Base of a number to be written.  */
+      unsigned long long int num; /* Integral number to be written.  */
+      const char *str;         /* String to be written.  */
+      char errorbuf[1024];      /* Buffer sometimes used by %m.  */
+
+      if (specs[cnt].width_arg != -1)
+       {
+         /* Extract the field width from an argument.  */
+         specs[cnt].info.width = args_value[specs[cnt].width_arg].pa_int;
+
+         if (specs[cnt].info.width < 0)
+           /* If the width value is negative left justification is selected
+              and the value is taken as being positive.  */
+           {
+             specs[cnt].info.width = -specs[cnt].info.width;
+             specs[cnt].info.left = 1;
+           }
+       }
+
+      if (specs[cnt].prec_arg != -1)
+       {
+         /* Extract the precision from an argument.  */
+         specs[cnt].info.prec = args_value[specs[cnt].prec_arg].pa_int;
+
+         if (specs[cnt].info.prec < 0)
+           /* If the precision is negative the precision is omitted.  */
+           specs[cnt].info.prec = -1;
+       }
+
+      /* Check for a user-defined handler for this spec.  */
+      function = (__printf_function_table == NULL ? NULL :
+                  __printf_function_table[specs[cnt].info.spec]);
+
+      if (function != NULL)
+      use_function:            /* Built-in formats with helpers use this.  */
+       {
+         int function_done;
+         unsigned int i;
+         const void *ptr[specs[cnt].ndata_args];
+
+         /* Fill in an array of pointers to the argument values.  */
+         for (i = 0; i < specs[cnt].ndata_args; ++i)
+           ptr[i] = &args_value[specs[cnt].data_arg + i];
+
+         /* Call the function.  */
+         function_done = (*function) (s, &specs[cnt].info, ptr);
+
+         /* If an error occured don't do any further work.  */
+         if (function_done < 0)
+           return -1;
+
+         done += function_done;
+       }
+      else
+       switch (specs[cnt].info.spec)
+         {
+         case '%':
+           /* Write a literal "%".  */
+           outchar ('%');
+           break;
+         case 'i':
+         case 'd':
+           {
+             long long int signed_num;
+
+             /* Decimal integer.  */
+             base = 10;
+             if (specs[cnt].info.is_longlong)
+               signed_num = args_value[specs[cnt].data_arg].pa_long_long_int;
+             else if (specs[cnt].info.is_long)
+               signed_num = args_value[specs[cnt].data_arg].pa_long_int;
+             else if (!specs[cnt].info.is_short)
+               signed_num = args_value[specs[cnt].data_arg].pa_int;
+             else
+               signed_num = args_value[specs[cnt].data_arg].pa_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 (specs[cnt].info.is_longlong)
+             num = args_value[specs[cnt].data_arg].pa_u_long_long_int;
+            else if (specs[cnt].info.is_long)
+             num = args_value[specs[cnt].data_arg].pa_u_long_int;
+            else if (!specs[cnt].info.is_short)
+             num = args_value[specs[cnt].data_arg].pa_u_int;
+            else
+             num = args_value[specs[cnt].data_arg].pa_u_short_int;
+
+            /* ANSI only specifies the `+' and
+               ` ' flags for signed conversions.  */
+            is_neg = 0;
+           specs[cnt].info.showsign = 0;
+           specs[cnt].info.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 (specs[cnt].info.prec == -1)
+                specs[cnt].info.prec = 1;
+
+              /* Put the number in WORK.  */
+              w = _itoa (num, workend + 1, base, specs[cnt].info.spec == 'X');
+             w -= 1;
+              if (specs[cnt].info.group && grouping)
+                w = group_number (w, workend, grouping, thousands_sep);
+              specs[cnt].info.width -= workend - w;
+              specs[cnt].info.prec -= workend - w;
+
+              if (num != 0 && specs[cnt].info.alt && base == 8
+                 && specs[cnt].info.prec <= 0)
+                {
+                 /* Add octal marker.  */
+                  *w-- = '0';
+                  --specs[cnt].info.width;
+                }
+
+              if (specs[cnt].info.prec > 0)
+                {
+                 /* Add zeros to the precision.  */
+                  specs[cnt].info.width -= specs[cnt].info.prec;
+                  while (specs[cnt].info.prec-- > 0)
+                    *w-- = '0';
+                }
+
+              if (num != 0 && specs[cnt].info.alt && base == 16)
+               /* Account for 0X hex marker.  */
+                specs[cnt].info.width -= 2;
+
+              if (is_neg || specs[cnt].info.showsign || specs[cnt].info.space)
+                --specs[cnt].info.width;
+
+              if (!specs[cnt].info.left && specs[cnt].info.pad == ' ')
+                PAD (' ');
+
+              if (is_neg)
+                outchar ('-');
+              else if (specs[cnt].info.showsign)
+                outchar ('+');
+              else if (specs[cnt].info.space)
+                outchar (' ');
+
+              if (num != 0 && specs[cnt].info.alt && base == 16)
+                {
+                  outchar ('0');
+                  outchar (specs[cnt].info.spec);
+                }
+
+              if (!specs[cnt].info.left && specs[cnt].info.pad == '0')
+                PAD ('0');
+
+              /* Write the number.  */
+              while (++w <= workend)
+                outchar (*w);
+
+              if (specs[cnt].info.left)
+                PAD (' ');
+            }
+            break;
+
+          case 'e':
+          case 'E':
+          case 'f':
+          case 'g':
+          case 'G':
+            {
+              /* Floating-point number.  This is handled by printf_fp.c.  */
+              extern printf_function __printf_fp;
+              function = __printf_fp;
+              goto use_function;
+            }
+
+          case 'c':
+            /* Character.  */
+            if (!specs[cnt].info.left)
+              {
+                --specs[cnt].info.width;
+                PAD (' ');
+              }
+            outchar ((unsigned char) args_value[specs[cnt].data_arg].pa_char);
+            if (specs[cnt].info.left)
+              PAD (' ');
+            break;
+
+          case 's':
+            {
+              static const char null[] = "(null)";
+              size_t len;
+
+             str = args_value[specs[cnt].data_arg].pa_string;
+
+           string:
+
+              if (str == NULL)
+               {
+                 /* Write "(null)" if there's space.  */
+                 if (specs[cnt].info.prec == -1
+                     || specs[cnt].info.prec >= (int) sizeof (null) - 1)
+                   {
+                     str = null;
+                     len = sizeof (null) - 1;
+                   }
+                 else
+                   {
+                     str = "";
+                     len = 0;
+                   }
+               }
+              else if (specs[cnt].info.prec != -1)
+               {
+                 /* Search for the end of the string, but don't search
+                    past the length specified by the precision.  */
+                 const char *end = memchr (str, '\0', specs[cnt].info.prec);
+                 if (end)
+                   len = end - str;
+                 else
+                   len = specs[cnt].info.prec;
+               }
+             else
+               len = strlen (str);
+
+              specs[cnt].info.width -= len;
+
+              if (!specs[cnt].info.left)
+                PAD (' ');
+              outstring (str, len);
+              if (specs[cnt].info.left)
+                PAD (' ');
+            }
+            break;
+
+          case 'p':
+            /* Generic pointer.  */
+            {
+              const void *ptr;
+              ptr = args_value[specs[cnt].data_arg].pa_pointer;
+              if (ptr != NULL)
+                {
+                  /* If the pointer is not NULL, write it as a %#x spec.  */
+                  base = 16;
+                  num = (unsigned long long int) (unsigned long int) ptr;
+                  is_neg = 0;
+                  specs[cnt].info.alt = 1;
+                 specs[cnt].info.spec = 'x';
+                  specs[cnt].info.group = 0;
+                  goto number;
+                }
+              else
+                {
+                  /* Write "(nil)" for a nil pointer.  */
+                  str = "(nil)";
+                 /* Make sure the full string "(nil)" is printed.  */
+                 if (specs[cnt].info.prec < 5)
+                   specs[cnt].info.prec = 5;
+                  goto string;
+                }
+            }
+            break;
+
+          case 'n':
+            /* Answer the count of characters written.  */
+            if (specs[cnt].info.is_longlong)
+             *(long long int *) 
+               args_value[specs[cnt].data_arg].pa_pointer = done;
+            else if (specs[cnt].info.is_long)
+             *(long int *) 
+               args_value[specs[cnt].data_arg].pa_pointer = done;
+            else if (!specs[cnt].info.is_short)
+             *(int *) 
+               args_value[specs[cnt].data_arg].pa_pointer = done;
+            else
+             *(short int *) 
+               args_value[specs[cnt].data_arg].pa_pointer = done;
+            break;
+
+          case 'm':
+            {
+              extern char *_strerror_internal __P ((int, char *buf, size_t));
+              str = _strerror_internal (errno, errorbuf, sizeof errorbuf);
+              goto string;
+            }
+
+          default:
+            /* Unrecognized format specifier.  */
+            function = printf_unknown;
+            goto use_function;
+         }
+
+      /* Write the following constant string.  */
+      outstring (specs[cnt].end_of_fmt,
+                specs[cnt].next_fmt - specs[cnt].end_of_fmt);
+    }
+
+  return done;
+}
+
+
+/* Handle an unknown format specifier.  This prints out a canonicalized
+   representation of the format spec itself.  */
+
+static int
+printf_unknown (s, info, args)
+  FILE *s;
+  const struct printf_info *info;
+  const void **const args;
+{
+  int done = 0;
+  char work[BUFSIZ];
+  char *const workend = &work[sizeof(work) - 1];
+  register char *w;
+
+  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');
+
+  if (info->width != 0)
+    {
+      w = _itoa (info->width, workend + 1, 10, 0);
+      while (++w <= workend)
+       outchar (*w);
+    }
+
+  if (info->prec != -1)
+    {
+      outchar ('.');
+      w = _itoa (info->prec, workend + 1, 10, 0);
+      while (++w <= workend)
+       outchar (*w);
+    }
+
+  if (info->spec != '\0')
+    outchar (info->spec);
+
+  return done;
+}
+\f
+/* 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;
+}
+\f
+#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
+_IO_helper_overflow (s, c)
+  _IO_FILE *s;
+  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
+buffered_vfprintf (s, format, args)
+  register _IO_FILE *s;
+  char const *format;
+  _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
+buffered_vfprintf (s, format, args)
+  register FILE *s;
+  char const *format;
+  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)
+    result = -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;
+     size_t count;
+{
+  const char *padptr;
+  register size_t i;
+
+  padptr = pad == ' ' ? blanks : zeroes;
+
+  for (i = count; i >= PADSIZE; i -= PADSIZE)
+    if (PUT (s, padptr, PADSIZE) != PADSIZE)
+      return -1;
+  if (i > 0)
+    if (PUT (s, padptr, i) != i)
+      return -1;
+
+  return count;
+}
+#undef PADSIZE
+#endif /* USE_IN_LIBIO */
diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c
new file mode 100644 (file)
index 0000000..a778346
--- /dev/null
@@ -0,0 +1,624 @@
+/* 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 "../locale/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 (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.  */
+  int group_flag;              /* %' modifier flag.  */
+
+  /* Type modifiers.  */
+  int 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.  */
+  union
+    {
+      long long int q;
+      unsigned long long int uq;
+      long int l;
+      unsigned long int ul;
+    } num;
+  /* 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, _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT),
+             strlen (_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT))) <= 0)
+    decimal = (wchar_t) *_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
+
+  c = inchar();
+
+  /* Run through the format string.  */
+  while (*f != '\0')
+    {
+      unsigned int argpos;
+      /* Extract the next argument, which is of type TYPE.
+        For a %N$... spec, this is the Nth argument from the beginning;
+        otherwise it is the next argument after the state now in ARG.  */
+#define ARG(type)      (argpos == 0 ? va_arg (arg, type) :                   \
+                        ({ unsigned int pos = argpos;                        \
+                           va_list arg = (va_list) argptr;                   \
+                           while (--pos > 0)                                 \
+                             (void) va_arg (arg, void *);                    \
+                           va_arg (arg, type);                               \
+                         }))
+
+      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;
+       }
+
+      /* Initialize state of modifiers.  */
+      argpos = 0;
+      do_assign = 1;
+      group_flag = 0;
+      is_short = is_long = is_long_double = malloc_string = 0;
+
+      /* Check for a positional parameter specification.  */
+      if (isdigit (*f))
+       {
+         argpos = *f++ - '0';
+         while (isdigit (*f))
+           argpos = argpos * 10 + (*f++ - '0');
+         if (*f == '$')
+           ++f;
+         else
+           {
+             /* Oops; that was actually the field width.  */
+             width = argpos;
+             argpos = 0;
+             goto got_width;
+           }
+       }
+
+      /* Check for the assignment-suppressant and the number grouping flag.  */
+      while (*f == '*' || *f == '\'')
+       switch (*f++)
+         {
+         case '*':
+           do_assign = 0;
+           break;
+         case '\'':
+           group_flag = 1;
+           break;
+         }
+
+      /* Find the maximum field width.  */
+      width = 0;
+      while (isdigit(*f))
+       {
+         width *= 10;
+         width += *f++ - '0';
+       }
+    got_width:
+      if (width == 0)
+       width = -1;
+
+      /* Check for type modifiers.  */
+      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)
+           *ARG (int *) = read_in - 1; /* Don't count the read-ahead.  */
+         break;
+
+       case 'c':       /* Match characters.  */
+         if (do_assign)
+           {
+             str = 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);
+
+         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 = ARG (char **);                             \
+                 if (strptr == NULL)                                         \
+                   conv_error ();                                            \
+                 /* Allocate an initial buffer.  */                          \
+                 strsize = 100;                                              \
+                 *strptr = str = malloc (strsize);                           \
+               }                                                             \
+             else                                                            \
+               str = 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.  */
+         while (width != 0 && c != EOF)
+           {
+             if (base == 16 ? !isxdigit(c) :
+                 (!isdigit(c) || c - '0' >= base))
+               break;
+             *w++ = c;
+             if (width > 0)
+               --width;
+             (void) inchar ();
+           }
+
+         if (w == work ||
+             (w - work == 1 && (work[0] == '+' || work[0] == '-')))
+           /* There was no number.  */
+           conv_error();
+
+         /* Convert the number.  */
+         *w = '\0';
+         if (is_longlong)
+           {
+             if (number_signed)
+               num.q = __strtoq_internal (work, &w, base, group_flag);
+             else
+               num.uq = __strtouq_internal (work, &w, base, group_flag);
+           }
+         else
+           {
+             if (number_signed)
+               num.l = __strtol_internal (work, &w, base, group_flag);
+             else
+               num.ul = __strtoul_internal (work, &w, base, group_flag);
+           }
+         if (w == work)
+           conv_error ();
+
+         if (do_assign)
+           {
+             if (! number_signed)
+               {
+                 if (is_longlong)
+                   *ARG (unsigned LONGLONG int *) = num.uq;
+                 else if (is_long)
+                   *ARG (unsigned long int *) = num.ul;
+                 else if (is_short)
+                   *ARG (unsigned short int *)
+                     = (unsigned short int) num.ul;
+                 else
+                   *ARG (unsigned int *) = (unsigned int) num.ul;
+               }
+             else
+               {
+                 if (is_longlong)
+                   *ARG (LONGLONG int *) = num.q;
+                 else if (is_long)
+                   *ARG (long int *) = num.l;
+                 else if (is_short)
+                   *ARG (short int *) = (short int) num.l;
+                 else
+                   *ARG (int *) = (int) num.l;
+               }
+             ++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_internal (work, &w, group_flag);
+             if (do_assign && w != work)
+               *ARG (long double *) = d;
+           }
+         else if (is_long)
+           {
+             double d = __strtod_internal (work, &w, group_flag);
+             if (do_assign && w != work)
+               *ARG (double *) = d;
+           }
+         else
+           {
+             float d = __strtof_internal (work, &w, group_flag);
+             if (do_assign && w != work)
+               *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';
+         num.ul = 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 == num.ul)
+           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-common/vprintf.c b/stdio-common/vprintf.c
new file mode 100644 (file)
index 0000000..97264f4
--- /dev/null
@@ -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-common/vscanf.c b/stdio-common/vscanf.c
new file mode 100644 (file)
index 0000000..0d82944
--- /dev/null
@@ -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-common/vsnprintf.c b/stdio-common/vsnprintf.c
new file mode 100644 (file)
index 0000000..a02c259
--- /dev/null
@@ -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-common/vsprintf.c b/stdio-common/vsprintf.c
new file mode 100644 (file)
index 0000000..82be90f
--- /dev/null
@@ -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-common/vsscanf.c b/stdio-common/vsscanf.c
new file mode 100644 (file)
index 0000000..6f027d5
--- /dev/null
@@ -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-common/xbug.c b/stdio-common/xbug.c
new file mode 100644 (file)
index 0000000..ec648f5
--- /dev/null
@@ -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;
+}
diff --git a/stdio/vfprintf.c b/stdio/vfprintf.c
deleted file mode 100644 (file)
index 63a5148..0000000
+++ /dev/null
@@ -1,858 +0,0 @@
-/* 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 <ctype.h>
-#include <errno.h>
-#include <float.h>
-#include <limits.h>
-#include <math.h>
-#include <printf.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <printf.h>
-#include <stddef.h>
-#include "_itoa.h"
-#include "../locale/localeinfo.h"
-
-/* Include the shared code for parsing the format string.  */
-#include "printf-parse.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)                                                         \
-  if (specs[cnt].info.width > 0)                                             \
-    done += _IO_padn (s, padchar, specs[cnt].info.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, size_t n));
-#define PAD(padchar)                                                         \
-  if (specs[cnt].info.width > 0)                                             \
-    { if (__printf_pad (s, padchar, specs[cnt].info.width) == -1)            \
-       return -1; else done += specs[cnt].info.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)
-
-#define outstring(string, len)                                               \
-  do                                                                         \
-    {                                                                        \
-      if (len > 20)                                                          \
-       {                                                                     \
-         if (PUT (s, string, len) != len)                                    \
-           return -1;                                                        \
-         done += len;                                                        \
-       }                                                                     \
-      else                                                                   \
-       {                                                                     \
-         register const char *cp = string;                                   \
-         register int l = len;                                               \
-         while (l-- > 0)                                                     \
-           outchar (*cp++);                                                  \
-       }                                                                     \
-    } while (0)
-
-/* Helper function to provide temporary buffering for unbuffered streams.  */
-static int buffered_vfprintf __P ((FILE *stream, const char *fmt, va_list));
-
-static printf_function printf_unknown;
-
-extern printf_function **__printf_function_table;
-
-static char *group_number __P ((char *, char *, const char *, wchar_t));
-
-
-int
-vfprintf (s, format, ap)
-    register FILE *s;
-    const char *format;
-    va_list ap;
-{
-  /* The character used as thousands separator.  */
-  wchar_t thousands_sep;
-
-  /* The string describing the size of groups of digits.  */
-  const char *grouping;
-
-  /* Array with information about the needed arguments.  This has to be
-     dynamically extendable.  */
-  size_t nspecs;
-  size_t nspecs_max;
-  struct printf_spec *specs;
-
-  /* The number of arguments the format string requests.  This will
-     determine the size of the array needed to store the argument
-     attributes.  */
-  size_t nargs;
-  int *args_type;
-  union printf_arg *args_value;
-
-  /* Positional parameters refer to arguments directly.  This could also
-     determine the maximum number of arguments.  Track the maximum number.  */
-  size_t max_ref_arg;
-
-  /* End of leading constant string.  */
-  const char *lead_str_end;
-
-  /* Number of characters written.  */
-  register size_t done = 0;
-
-  /* Running pointer through format string.  */
-  const char *f;
-
-  /* Just a counter.  */
-  int cnt;
-
-  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, ap);
-
-  /* Reset multibyte characters to their initial state.  */
-  (void) mblen ((char *) NULL, 0);
-
-  /* Figure out the thousands separator character.  */
-  if (mbtowc (&thousands_sep, _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
-              strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0)
-    thousands_sep = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
-  grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
-  if (*grouping == '\0' || *grouping == CHAR_MAX || thousands_sep == L'\0')
-    grouping = NULL;
-
-  nspecs_max = 32;             /* A more or less arbitrary start value.  */
-  specs = alloca (nspecs_max * sizeof (struct printf_spec));
-  nspecs = 0;
-  nargs = 0;
-  max_ref_arg = 0;
-
-  /* Find the first format specifier.  */
-  lead_str_end = find_spec (format);
-
-  for (f = lead_str_end; *f != '\0'; f = specs[nspecs++].next_fmt)
-    {
-      if (nspecs >= nspecs_max)
-       {
-         /* Extend the array of format specifiers.  */
-         struct printf_spec *old = specs;
-
-         nspecs_max *= 2;
-         specs = alloca (nspecs_max * sizeof (struct printf_spec));
-         if (specs == &old[nspecs])
-           /* Stack grows up, OLD was the last thing allocated; extend it.  */
-           nspecs_max += nspecs_max / 2;
-         else
-           {
-             /* Copy the old array's elements to the new space.  */
-             memcpy (specs, old, nspecs * sizeof (struct printf_spec));
-             if (old == &specs[nspecs])
-               /* Stack grows down, OLD was just below the new SPECS.
-                  We can use that space when the new space runs out.  */
-               nspecs_max += nspecs_max / 2;
-           }
-       }
-
-      /* Parse the format specifier.  */
-      nargs += parse_one_spec (f, nargs, &specs[nspecs], &max_ref_arg);
-    }
-
-  /* Determine the number of arguments the format string consumes.  */
-  nargs = MAX (nargs, max_ref_arg);
-
-  /* Allocate memory for the argument descriptions.  */
-  args_type = alloca (nargs * sizeof (int));
-  args_value = alloca (nargs * sizeof (union printf_arg));
-
-  /* XXX Could do sanity check here:
-     Initialize args_type elts to zero.
-     If any is still zero after this loop, format is invalid.  */
-
-  /* Fill in the types of all the arguments.  */
-  for (cnt = 0; cnt < nspecs; ++cnt)
-    {
-      /* If the width is determined by an argument this is an int.  */ 
-      if (specs[cnt].width_arg != -1)
-       args_type[specs[cnt].width_arg] = PA_INT;
-
-      /* If the precision is determined by an argument this is an int.  */ 
-      if (specs[cnt].prec_arg != -1)
-       args_type[specs[cnt].prec_arg] = PA_INT;
-
-      switch (specs[cnt].ndata_args)
-       {
-       case 0:                 /* No arguments.  */
-         break;
-       case 1:                 /* One argument; we already have the type.  */
-         args_type[specs[cnt].data_arg] = specs[cnt].data_arg_type;
-         break;
-       default:
-         /* We have more than one argument for this format spec.  We must
-            call the arginfo function again to determine all the types.  */
-         (void) (*__printf_arginfo_table[specs[cnt].info.spec])
-           (&specs[cnt].info,
-            specs[cnt].ndata_args, &args_type[specs[cnt].data_arg]);
-         break;
-       }
-    }
-
-  /* Now we know all the types and the order.  Fill in the argument values.  */
-  for (cnt = 0; cnt < nargs; ++cnt)
-    switch (args_type[cnt])
-      {
-#define T(tag, mem, type)                                                    \
-      case tag:                                                                      \
-       args_value[cnt].mem = va_arg (ap, type);                              \
-       break
-
-       T (PA_CHAR, pa_char, int); /* Promoted.  */
-       T (PA_INT|PA_FLAG_SHORT, pa_short_int, int); /* Promoted.  */
-       T (PA_INT, pa_int, int);
-       T (PA_INT|PA_FLAG_LONG, pa_long_int, long int);
-       T (PA_INT|PA_FLAG_LONG_LONG, pa_long_long_int, long long int);
-       T (PA_FLOAT, pa_float, double); /* Promoted.  */
-       T (PA_DOUBLE, pa_double, double);
-       T (PA_DOUBLE|PA_FLAG_LONG_DOUBLE, pa_long_double, long double);
-       T (PA_STRING, pa_string, const char *);
-       T (PA_POINTER, pa_pointer, void *);
-#undef T
-      default:
-       if ((args_type[cnt] & PA_FLAG_PTR) != 0)
-         args_value[cnt].pa_pointer = va_arg (ap, void *);
-       break;
-      }
-
-  /* Write the literal text before the first format.  */
-  outstring (format, lead_str_end - format);
-
-  /* Now walk through all format specifiers and process them.  */
-  for (cnt = 0; cnt < nspecs; ++cnt)
-    {
-      printf_function *function; /* Auxiliary function to do output.  */
-      int is_neg;              /* Decimal integer is negative.  */
-      int base;                        /* Base of a number to be written.  */
-      unsigned long long int num; /* Integral number to be written.  */
-      const char *str;         /* String to be written.  */
-      char errorbuf[1024];      /* Buffer sometimes used by %m.  */
-
-      if (specs[cnt].width_arg != -1)
-       {
-         /* Extract the field width from an argument.  */
-         specs[cnt].info.width = args_value[specs[cnt].width_arg].pa_int;
-
-         if (specs[cnt].info.width < 0)
-           /* If the width value is negative left justification is selected
-              and the value is taken as being positive.  */
-           {
-             specs[cnt].info.width = -specs[cnt].info.width;
-             specs[cnt].info.left = 1;
-           }
-       }
-
-      if (specs[cnt].prec_arg != -1)
-       {
-         /* Extract the precision from an argument.  */
-         specs[cnt].info.prec = args_value[specs[cnt].prec_arg].pa_int;
-
-         if (specs[cnt].info.prec < 0)
-           /* If the precision is negative the precision is omitted.  */
-           specs[cnt].info.prec = -1;
-       }
-
-      /* Check for a user-defined handler for this spec.  */
-      function = (__printf_function_table == NULL ? NULL :
-                  __printf_function_table[specs[cnt].info.spec]);
-
-      if (function != NULL)
-      use_function:            /* Built-in formats with helpers use this.  */
-       {
-         int function_done;
-         unsigned int i;
-         const void *ptr[specs[cnt].ndata_args];
-
-         /* Fill in an array of pointers to the argument values.  */
-         for (i = 0; i < specs[cnt].ndata_args; ++i)
-           ptr[i] = &args_value[specs[cnt].data_arg + i];
-
-         /* Call the function.  */
-         function_done = (*function) (s, &specs[cnt].info, ptr);
-
-         /* If an error occured don't do any further work.  */
-         if (function_done < 0)
-           return -1;
-
-         done += function_done;
-       }
-      else
-       switch (specs[cnt].info.spec)
-         {
-         case '%':
-           /* Write a literal "%".  */
-           outchar ('%');
-           break;
-         case 'i':
-         case 'd':
-           {
-             long long int signed_num;
-
-             /* Decimal integer.  */
-             base = 10;
-             if (specs[cnt].info.is_longlong)
-               signed_num = args_value[specs[cnt].data_arg].pa_long_long_int;
-             else if (specs[cnt].info.is_long)
-               signed_num = args_value[specs[cnt].data_arg].pa_long_int;
-             else if (!specs[cnt].info.is_short)
-               signed_num = args_value[specs[cnt].data_arg].pa_int;
-             else
-               signed_num = args_value[specs[cnt].data_arg].pa_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 (specs[cnt].info.is_longlong)
-             num = args_value[specs[cnt].data_arg].pa_u_long_long_int;
-            else if (specs[cnt].info.is_long)
-             num = args_value[specs[cnt].data_arg].pa_u_long_int;
-            else if (!specs[cnt].info.is_short)
-             num = args_value[specs[cnt].data_arg].pa_u_int;
-            else
-             num = args_value[specs[cnt].data_arg].pa_u_short_int;
-
-            /* ANSI only specifies the `+' and
-               ` ' flags for signed conversions.  */
-            is_neg = 0;
-           specs[cnt].info.showsign = 0;
-           specs[cnt].info.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 (specs[cnt].info.prec == -1)
-                specs[cnt].info.prec = 1;
-
-              /* Put the number in WORK.  */
-              w = _itoa (num, workend + 1, base, specs[cnt].info.spec == 'X');
-             w -= 1;
-              if (specs[cnt].info.group && grouping)
-                w = group_number (w, workend, grouping, thousands_sep);
-              specs[cnt].info.width -= workend - w;
-              specs[cnt].info.prec -= workend - w;
-
-              if (num != 0 && specs[cnt].info.alt && base == 8
-                 && specs[cnt].info.prec <= 0)
-                {
-                 /* Add octal marker.  */
-                  *w-- = '0';
-                  --specs[cnt].info.width;
-                }
-
-              if (specs[cnt].info.prec > 0)
-                {
-                 /* Add zeros to the precision.  */
-                  specs[cnt].info.width -= specs[cnt].info.prec;
-                  while (specs[cnt].info.prec-- > 0)
-                    *w-- = '0';
-                }
-
-              if (num != 0 && specs[cnt].info.alt && base == 16)
-               /* Account for 0X hex marker.  */
-                specs[cnt].info.width -= 2;
-
-              if (is_neg || specs[cnt].info.showsign || specs[cnt].info.space)
-                --specs[cnt].info.width;
-
-              if (!specs[cnt].info.left && specs[cnt].info.pad == ' ')
-                PAD (' ');
-
-              if (is_neg)
-                outchar ('-');
-              else if (specs[cnt].info.showsign)
-                outchar ('+');
-              else if (specs[cnt].info.space)
-                outchar (' ');
-
-              if (num != 0 && specs[cnt].info.alt && base == 16)
-                {
-                  outchar ('0');
-                  outchar (specs[cnt].info.spec);
-                }
-
-              if (!specs[cnt].info.left && specs[cnt].info.pad == '0')
-                PAD ('0');
-
-              /* Write the number.  */
-              while (++w <= workend)
-                outchar (*w);
-
-              if (specs[cnt].info.left)
-                PAD (' ');
-            }
-            break;
-
-          case 'e':
-          case 'E':
-          case 'f':
-          case 'g':
-          case 'G':
-            {
-              /* Floating-point number.  This is handled by printf_fp.c.  */
-              extern printf_function __printf_fp;
-              function = __printf_fp;
-              goto use_function;
-            }
-
-          case 'c':
-            /* Character.  */
-            if (!specs[cnt].info.left)
-              {
-                --specs[cnt].info.width;
-                PAD (' ');
-              }
-            outchar ((unsigned char) args_value[specs[cnt].data_arg].pa_char);
-            if (specs[cnt].info.left)
-              PAD (' ');
-            break;
-
-          case 's':
-            {
-              static const char null[] = "(null)";
-              size_t len;
-
-             str = args_value[specs[cnt].data_arg].pa_string;
-
-           string:
-
-              if (str == NULL)
-               {
-                 /* Write "(null)" if there's space.  */
-                 if (specs[cnt].info.prec == -1
-                     || specs[cnt].info.prec >= (int) sizeof (null) - 1)
-                   {
-                     str = null;
-                     len = sizeof (null) - 1;
-                   }
-                 else
-                   {
-                     str = "";
-                     len = 0;
-                   }
-               }
-              else if (specs[cnt].info.prec != -1)
-               {
-                 /* Search for the end of the string, but don't search
-                    past the length specified by the precision.  */
-                 const char *end = memchr (str, '\0', specs[cnt].info.prec);
-                 if (end)
-                   len = end - str;
-                 else
-                   len = specs[cnt].info.prec;
-               }
-             else
-               len = strlen (str);
-
-              specs[cnt].info.width -= len;
-
-              if (!specs[cnt].info.left)
-                PAD (' ');
-              outstring (str, len);
-              if (specs[cnt].info.left)
-                PAD (' ');
-            }
-            break;
-
-          case 'p':
-            /* Generic pointer.  */
-            {
-              const void *ptr;
-              ptr = args_value[specs[cnt].data_arg].pa_pointer;
-              if (ptr != NULL)
-                {
-                  /* If the pointer is not NULL, write it as a %#x spec.  */
-                  base = 16;
-                  num = (unsigned long long int) (unsigned long int) ptr;
-                  is_neg = 0;
-                  specs[cnt].info.alt = 1;
-                 specs[cnt].info.spec = 'x';
-                  specs[cnt].info.group = 0;
-                  goto number;
-                }
-              else
-                {
-                  /* Write "(nil)" for a nil pointer.  */
-                  str = "(nil)";
-                 /* Make sure the full string "(nil)" is printed.  */
-                 if (specs[cnt].info.prec < 5)
-                   specs[cnt].info.prec = 5;
-                  goto string;
-                }
-            }
-            break;
-
-          case 'n':
-            /* Answer the count of characters written.  */
-            if (specs[cnt].info.is_longlong)
-             *(long long int *) 
-               args_value[specs[cnt].data_arg].pa_pointer = done;
-            else if (specs[cnt].info.is_long)
-             *(long int *) 
-               args_value[specs[cnt].data_arg].pa_pointer = done;
-            else if (!specs[cnt].info.is_short)
-             *(int *) 
-               args_value[specs[cnt].data_arg].pa_pointer = done;
-            else
-             *(short int *) 
-               args_value[specs[cnt].data_arg].pa_pointer = done;
-            break;
-
-          case 'm':
-            {
-              extern char *_strerror_internal __P ((int, char *buf, size_t));
-              str = _strerror_internal (errno, errorbuf, sizeof errorbuf);
-              goto string;
-            }
-
-          default:
-            /* Unrecognized format specifier.  */
-            function = printf_unknown;
-            goto use_function;
-         }
-
-      /* Write the following constant string.  */
-      outstring (specs[cnt].end_of_fmt,
-                specs[cnt].next_fmt - specs[cnt].end_of_fmt);
-    }
-
-  return done;
-}
-
-
-/* Handle an unknown format specifier.  This prints out a canonicalized
-   representation of the format spec itself.  */
-
-static int
-printf_unknown (s, info, args)
-  FILE *s;
-  const struct printf_info *info;
-  const void **const args;
-{
-  int done = 0;
-  char work[BUFSIZ];
-  char *const workend = &work[sizeof(work) - 1];
-  register char *w;
-
-  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');
-
-  if (info->width != 0)
-    {
-      w = _itoa (info->width, workend + 1, 10, 0);
-      while (++w <= workend)
-       outchar (*w);
-    }
-
-  if (info->prec != -1)
-    {
-      outchar ('.');
-      w = _itoa (info->prec, workend + 1, 10, 0);
-      while (++w <= workend)
-       outchar (*w);
-    }
-
-  if (info->spec != '\0')
-    outchar (info->spec);
-
-  return done;
-}
-\f
-/* 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;
-}
-\f
-#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
-_IO_helper_overflow (s, c)
-  _IO_FILE *s;
-  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
-buffered_vfprintf (s, format, args)
-  register _IO_FILE *s;
-  char const *format;
-  _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
-buffered_vfprintf (s, format, args)
-  register FILE *s;
-  char const *format;
-  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)
-    result = -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;
-     size_t count;
-{
-  const char *padptr;
-  register size_t i;
-
-  padptr = pad == ' ' ? blanks : zeroes;
-
-  for (i = count; i >= PADSIZE; i -= PADSIZE)
-    if (PUT (s, padptr, PADSIZE) != PADSIZE)
-      return -1;
-  if (i > 0)
-    if (PUT (s, padptr, i) != i)
-      return -1;
-
-  return count;
-}
-#undef PADSIZE
-#endif /* USE_IN_LIBIO */
diff --git a/stdio/vfscanf.c b/stdio/vfscanf.c
deleted file mode 100644 (file)
index a778346..0000000
+++ /dev/null
@@ -1,624 +0,0 @@
-/* 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 "../locale/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 (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.  */
-  int group_flag;              /* %' modifier flag.  */
-
-  /* Type modifiers.  */
-  int 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.  */
-  union
-    {
-      long long int q;
-      unsigned long long int uq;
-      long int l;
-      unsigned long int ul;
-    } num;
-  /* 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, _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT),
-             strlen (_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT))) <= 0)
-    decimal = (wchar_t) *_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
-
-  c = inchar();
-
-  /* Run through the format string.  */
-  while (*f != '\0')
-    {
-      unsigned int argpos;
-      /* Extract the next argument, which is of type TYPE.
-        For a %N$... spec, this is the Nth argument from the beginning;
-        otherwise it is the next argument after the state now in ARG.  */
-#define ARG(type)      (argpos == 0 ? va_arg (arg, type) :                   \
-                        ({ unsigned int pos = argpos;                        \
-                           va_list arg = (va_list) argptr;                   \
-                           while (--pos > 0)                                 \
-                             (void) va_arg (arg, void *);                    \
-                           va_arg (arg, type);                               \
-                         }))
-
-      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;
-       }
-
-      /* Initialize state of modifiers.  */
-      argpos = 0;
-      do_assign = 1;
-      group_flag = 0;
-      is_short = is_long = is_long_double = malloc_string = 0;
-
-      /* Check for a positional parameter specification.  */
-      if (isdigit (*f))
-       {
-         argpos = *f++ - '0';
-         while (isdigit (*f))
-           argpos = argpos * 10 + (*f++ - '0');
-         if (*f == '$')
-           ++f;
-         else
-           {
-             /* Oops; that was actually the field width.  */
-             width = argpos;
-             argpos = 0;
-             goto got_width;
-           }
-       }
-
-      /* Check for the assignment-suppressant and the number grouping flag.  */
-      while (*f == '*' || *f == '\'')
-       switch (*f++)
-         {
-         case '*':
-           do_assign = 0;
-           break;
-         case '\'':
-           group_flag = 1;
-           break;
-         }
-
-      /* Find the maximum field width.  */
-      width = 0;
-      while (isdigit(*f))
-       {
-         width *= 10;
-         width += *f++ - '0';
-       }
-    got_width:
-      if (width == 0)
-       width = -1;
-
-      /* Check for type modifiers.  */
-      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)
-           *ARG (int *) = read_in - 1; /* Don't count the read-ahead.  */
-         break;
-
-       case 'c':       /* Match characters.  */
-         if (do_assign)
-           {
-             str = 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);
-
-         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 = ARG (char **);                             \
-                 if (strptr == NULL)                                         \
-                   conv_error ();                                            \
-                 /* Allocate an initial buffer.  */                          \
-                 strsize = 100;                                              \
-                 *strptr = str = malloc (strsize);                           \
-               }                                                             \
-             else                                                            \
-               str = 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.  */
-         while (width != 0 && c != EOF)
-           {
-             if (base == 16 ? !isxdigit(c) :
-                 (!isdigit(c) || c - '0' >= base))
-               break;
-             *w++ = c;
-             if (width > 0)
-               --width;
-             (void) inchar ();
-           }
-
-         if (w == work ||
-             (w - work == 1 && (work[0] == '+' || work[0] == '-')))
-           /* There was no number.  */
-           conv_error();
-
-         /* Convert the number.  */
-         *w = '\0';
-         if (is_longlong)
-           {
-             if (number_signed)
-               num.q = __strtoq_internal (work, &w, base, group_flag);
-             else
-               num.uq = __strtouq_internal (work, &w, base, group_flag);
-           }
-         else
-           {
-             if (number_signed)
-               num.l = __strtol_internal (work, &w, base, group_flag);
-             else
-               num.ul = __strtoul_internal (work, &w, base, group_flag);
-           }
-         if (w == work)
-           conv_error ();
-
-         if (do_assign)
-           {
-             if (! number_signed)
-               {
-                 if (is_longlong)
-                   *ARG (unsigned LONGLONG int *) = num.uq;
-                 else if (is_long)
-                   *ARG (unsigned long int *) = num.ul;
-                 else if (is_short)
-                   *ARG (unsigned short int *)
-                     = (unsigned short int) num.ul;
-                 else
-                   *ARG (unsigned int *) = (unsigned int) num.ul;
-               }
-             else
-               {
-                 if (is_longlong)
-                   *ARG (LONGLONG int *) = num.q;
-                 else if (is_long)
-                   *ARG (long int *) = num.l;
-                 else if (is_short)
-                   *ARG (short int *) = (short int) num.l;
-                 else
-                   *ARG (int *) = (int) num.l;
-               }
-             ++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_internal (work, &w, group_flag);
-             if (do_assign && w != work)
-               *ARG (long double *) = d;
-           }
-         else if (is_long)
-           {
-             double d = __strtod_internal (work, &w, group_flag);
-             if (do_assign && w != work)
-               *ARG (double *) = d;
-           }
-         else
-           {
-             float d = __strtof_internal (work, &w, group_flag);
-             if (do_assign && w != work)
-               *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';
-         num.ul = 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 == num.ul)
-           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
deleted file mode 100644 (file)
index 97264f4..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/* 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
deleted file mode 100644 (file)
index 0d82944..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/* 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
deleted file mode 100644 (file)
index a02c259..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/* 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
deleted file mode 100644 (file)
index 82be90f..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/* 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
deleted file mode 100644 (file)
index 6f027d5..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/* 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
deleted file mode 100644 (file)
index ec648f5..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-#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;
-}