From deab9deadc372fe1a367aef2e78c0d8f2885bf23 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Tue, 17 Oct 1995 00:41:39 +0000 Subject: * Makefile (subdirs): Replace stdio with stdio-common and $(stdio). * configure.in: Grok arg --enable-libio. ($stdio = libio): Define USE_IN_LIBIO. * config.h.in (USE_IN_LIBIO): Add #undef. * config.make.in (stdio): New variable, set by configure. * Makeconfig (stdio): New variable. * stdio.h [USE_IN_LIBIO]: Include libio/stdio.h instead of stdio/stdio.h. * stdio-common/Makefile: New file. * stdio/Makefile: Half the contents moved to stdio-common/Makefile. * stdio/_itoa.c: Moved to stdio-common. * stdio/_itoa.h: Moved to stdio-common. * stdio/asprintf.c: Moved to stdio-common. * stdio/bug1.c: Moved to stdio-common. * stdio/bug1.input: Moved to stdio-common. * stdio/bug2.c: Moved to stdio-common. * stdio/bug3.c: Moved to stdio-common. * stdio/bug4.c: Moved to stdio-common. * stdio/bug5.c: Moved to stdio-common. * stdio/bug6.c: Moved to stdio-common. * stdio/bug6.input: Moved to stdio-common. * stdio/bug7.c: Moved to stdio-common. * stdio/dprintf.c: Moved to stdio-common. * stdio/errnobug.c: Moved to stdio-common. * stdio/getline.c: Moved to stdio-common. * stdio/getw.c: Moved to stdio-common. * stdio/perror.c: Moved to stdio-common. * stdio/printf-parse.h: Moved to stdio-common. * stdio/printf-prs.c: Moved to stdio-common. * stdio/printf.c: Moved to stdio-common. * stdio/printf.h: Moved to stdio-common. * stdio/printf_fp.c: Moved to stdio-common. * stdio/psignal.c: Moved to stdio-common. * stdio/putw.c: Moved to stdio-common. * stdio/reg-printf.c: Moved to stdio-common. * stdio/scanf.c: Moved to stdio-common. * stdio/snprintf.c: Moved to stdio-common. * stdio/sprintf.c: Moved to stdio-common. * stdio/sscanf.c: Moved to stdio-common. * stdio/tempnam.c: Moved to stdio-common. * stdio/temptest.c: Moved to stdio-common. * stdio/test-fseek.c: Moved to stdio-common. * stdio/test-fwrite.c: Moved to stdio-common. * stdio/test-popen.c: Moved to stdio-common. * stdio/test_rdwr.c: Moved to stdio-common. * stdio/tmpfile.c: Moved to stdio-common. * stdio/tmpnam.c: Moved to stdio-common. * stdio/tst-fileno.c: Moved to stdio-common. * stdio/tst-printf.c: Moved to stdio-common. * stdio/tstgetln.c: Moved to stdio-common. * stdio/tstgetln.input: Moved to stdio-common. * stdio/tstscanf.c: Moved to stdio-common. * stdio/tstscanf.input: Moved to stdio-common. * stdio/vfprintf.c: Moved to stdio-common. * stdio/vfscanf.c: Moved to stdio-common. * stdio/vprintf.c: Moved to stdio-common. * stdio/xbug.c: Moved to stdio-common. * sysdeps/generic/Makefile (siglist.c rules): Do this in subdir stdio-common instead of stdio. * sysdeps/unix/Makefile (errlist.c rules): Likewise. * stdio-common/asprintf.c [USE_IN_LIBIO]: Call libio primitive function. * stdio-common/dprintf.c: Likewise. * stdio-common/printf.c: Likewise. * stdio-common/scanf.c: Likewise. * stdio-common/snprintf.c: Likewise. * stdio-common/sprintf.c: Likewise. * stdio-common/sscanf.c: Likewise. * stdio-common/vprintf.c: Likewise. * Makerules: Include $(+depfiles) directly instead of generating depend-$(subdir). (depend-$(subdir)): Target removed. (common-clean): Don't remove depend-$(subdir). --- ChangeLog | 75 ++++ Makeconfig | 6 + Makefile | 8 +- Makerules | 16 +- config.h.in | 4 + config.make.in | 1 + configure.in | 8 + stdio-common/Makefile | 47 +++ stdio-common/_itoa.c | 418 +++++++++++++++++++ stdio-common/_itoa.h | 32 ++ stdio-common/asprintf.c | 42 ++ stdio-common/bug1.c | 28 ++ stdio-common/bug1.input | 1 + stdio-common/bug2.c | 12 + stdio-common/bug3.c | 52 +++ stdio-common/bug4.c | 50 +++ stdio-common/bug5.c | 60 +++ stdio-common/bug6.c | 27 ++ stdio-common/bug6.input | 1 + stdio-common/bug7.c | 53 +++ stdio-common/dprintf.c | 41 ++ stdio-common/errnobug.c | 60 +++ stdio-common/fprintf.c | 38 ++ stdio-common/fscanf.c | 38 ++ stdio-common/getline.c | 33 ++ stdio-common/getw.c | 33 ++ stdio-common/perror.c | 42 ++ stdio-common/printf-parse.h | 388 +++++++++++++++++ stdio-common/printf-prs.c | 72 ++++ stdio-common/printf.c | 40 ++ stdio-common/printf.h | 124 ++++++ stdio-common/printf_fp.c | 990 ++++++++++++++++++++++++++++++++++++++++++++ stdio-common/psignal.c | 49 +++ stdio-common/putw.c | 31 ++ stdio-common/reg-printf.c | 47 +++ stdio-common/scanf.c | 40 ++ stdio-common/snprintf.c | 43 ++ stdio-common/sprintf.c | 41 ++ stdio-common/sscanf.c | 41 ++ stdio-common/tempnam.c | 50 +++ stdio-common/temptest.c | 31 ++ stdio-common/test-fseek.c | 67 +++ stdio-common/test-fwrite.c | 68 +++ stdio-common/test-popen.c | 67 +++ stdio-common/test_rdwr.c | 130 ++++++ stdio-common/tmpfile.c | 43 ++ stdio-common/tmpnam.c | 42 ++ stdio-common/tst-fileno.c | 37 ++ stdio-common/tst-printf.c | 298 +++++++++++++ stdio-common/tstgetln.c | 46 ++ stdio-common/tstgetln.input | 3 + stdio-common/tstscanf.c | 100 +++++ stdio-common/tstscanf.input | 7 + stdio-common/vasprintf.c | 86 ++++ stdio-common/vdprintf.c | 51 +++ stdio-common/vfprintf.c | 858 ++++++++++++++++++++++++++++++++++++++ stdio-common/vfscanf.c | 624 ++++++++++++++++++++++++++++ stdio-common/vprintf.c | 37 ++ stdio-common/vscanf.c | 32 ++ stdio-common/vsnprintf.c | 56 +++ stdio-common/vsprintf.c | 50 +++ stdio-common/vsscanf.c | 58 +++ stdio-common/xbug.c | 63 +++ stdio.h | 4 + stdio/Makefile | 26 +- stdio/_itoa.c | 418 ------------------- stdio/_itoa.h | 32 -- stdio/asprintf.c | 39 -- stdio/bug1.c | 28 -- stdio/bug1.input | 1 - stdio/bug2.c | 12 - stdio/bug3.c | 52 --- stdio/bug4.c | 50 --- stdio/bug5.c | 60 --- stdio/bug6.c | 27 -- stdio/bug6.input | 1 - stdio/bug7.c | 53 --- stdio/dprintf.c | 37 -- stdio/errnobug.c | 60 --- stdio/fprintf.c | 38 -- stdio/fscanf.c | 38 -- stdio/getline.c | 33 -- stdio/getw.c | 33 -- stdio/perror.c | 42 -- stdio/printf-parse.h | 388 ----------------- stdio/printf-prs.c | 72 ---- stdio/printf.c | 37 -- stdio/printf.h | 124 ------ stdio/printf_fp.c | 990 -------------------------------------------- stdio/psignal.c | 49 --- stdio/putw.c | 31 -- stdio/reg-printf.c | 47 --- stdio/scanf.c | 37 -- stdio/snprintf.c | 39 -- stdio/sprintf.c | 37 -- stdio/sscanf.c | 37 -- stdio/tempnam.c | 50 --- stdio/temptest.c | 31 -- stdio/test-fseek.c | 67 --- stdio/test-fwrite.c | 68 --- stdio/test-popen.c | 67 --- stdio/test_rdwr.c | 130 ------ stdio/tmpfile.c | 43 -- stdio/tmpnam.c | 42 -- stdio/tst-fileno.c | 37 -- stdio/tst-printf.c | 298 ------------- stdio/tstgetln.c | 46 -- stdio/tstgetln.input | 3 - stdio/tstscanf.c | 100 ----- stdio/tstscanf.input | 7 - stdio/vasprintf.c | 86 ---- stdio/vdprintf.c | 51 --- stdio/vfprintf.c | 858 -------------------------------------- stdio/vfscanf.c | 624 ---------------------------- stdio/vprintf.c | 33 -- stdio/vscanf.c | 32 -- stdio/vsnprintf.c | 56 --- stdio/vsprintf.c | 50 --- stdio/vsscanf.c | 58 --- stdio/xbug.c | 63 --- sysdeps/generic/Makefile | 4 +- 121 files changed, 6030 insertions(+), 5882 deletions(-) create mode 100644 stdio-common/Makefile create mode 100644 stdio-common/_itoa.c create mode 100644 stdio-common/_itoa.h create mode 100644 stdio-common/asprintf.c create mode 100644 stdio-common/bug1.c create mode 100644 stdio-common/bug1.input create mode 100644 stdio-common/bug2.c create mode 100644 stdio-common/bug3.c create mode 100644 stdio-common/bug4.c create mode 100644 stdio-common/bug5.c create mode 100644 stdio-common/bug6.c create mode 100644 stdio-common/bug6.input create mode 100644 stdio-common/bug7.c create mode 100644 stdio-common/dprintf.c create mode 100644 stdio-common/errnobug.c create mode 100644 stdio-common/fprintf.c create mode 100644 stdio-common/fscanf.c create mode 100644 stdio-common/getline.c create mode 100644 stdio-common/getw.c create mode 100644 stdio-common/perror.c create mode 100644 stdio-common/printf-parse.h create mode 100644 stdio-common/printf-prs.c create mode 100644 stdio-common/printf.c create mode 100644 stdio-common/printf.h create mode 100644 stdio-common/printf_fp.c create mode 100644 stdio-common/psignal.c create mode 100644 stdio-common/putw.c create mode 100644 stdio-common/reg-printf.c create mode 100644 stdio-common/scanf.c create mode 100644 stdio-common/snprintf.c create mode 100644 stdio-common/sprintf.c create mode 100644 stdio-common/sscanf.c create mode 100644 stdio-common/tempnam.c create mode 100644 stdio-common/temptest.c create mode 100644 stdio-common/test-fseek.c create mode 100644 stdio-common/test-fwrite.c create mode 100644 stdio-common/test-popen.c create mode 100644 stdio-common/test_rdwr.c create mode 100644 stdio-common/tmpfile.c create mode 100644 stdio-common/tmpnam.c create mode 100644 stdio-common/tst-fileno.c create mode 100644 stdio-common/tst-printf.c create mode 100644 stdio-common/tstgetln.c create mode 100644 stdio-common/tstgetln.input create mode 100644 stdio-common/tstscanf.c create mode 100644 stdio-common/tstscanf.input create mode 100644 stdio-common/vasprintf.c create mode 100644 stdio-common/vdprintf.c create mode 100644 stdio-common/vfprintf.c create mode 100644 stdio-common/vfscanf.c create mode 100644 stdio-common/vprintf.c create mode 100644 stdio-common/vscanf.c create mode 100644 stdio-common/vsnprintf.c create mode 100644 stdio-common/vsprintf.c create mode 100644 stdio-common/vsscanf.c create mode 100644 stdio-common/xbug.c delete mode 100644 stdio/_itoa.c delete mode 100644 stdio/_itoa.h delete mode 100644 stdio/asprintf.c delete mode 100644 stdio/bug1.c delete mode 100644 stdio/bug1.input delete mode 100644 stdio/bug2.c delete mode 100644 stdio/bug3.c delete mode 100644 stdio/bug4.c delete mode 100644 stdio/bug5.c delete mode 100644 stdio/bug6.c delete mode 100644 stdio/bug6.input delete mode 100644 stdio/bug7.c delete mode 100644 stdio/dprintf.c delete mode 100644 stdio/errnobug.c delete mode 100644 stdio/fprintf.c delete mode 100644 stdio/fscanf.c delete mode 100644 stdio/getline.c delete mode 100644 stdio/getw.c delete mode 100644 stdio/perror.c delete mode 100644 stdio/printf-parse.h delete mode 100644 stdio/printf-prs.c delete mode 100644 stdio/printf.c delete mode 100644 stdio/printf.h delete mode 100644 stdio/printf_fp.c delete mode 100644 stdio/psignal.c delete mode 100644 stdio/putw.c delete mode 100644 stdio/reg-printf.c delete mode 100644 stdio/scanf.c delete mode 100644 stdio/snprintf.c delete mode 100644 stdio/sprintf.c delete mode 100644 stdio/sscanf.c delete mode 100644 stdio/tempnam.c delete mode 100644 stdio/temptest.c delete mode 100644 stdio/test-fseek.c delete mode 100644 stdio/test-fwrite.c delete mode 100644 stdio/test-popen.c delete mode 100644 stdio/test_rdwr.c delete mode 100644 stdio/tmpfile.c delete mode 100644 stdio/tmpnam.c delete mode 100644 stdio/tst-fileno.c delete mode 100644 stdio/tst-printf.c delete mode 100644 stdio/tstgetln.c delete mode 100644 stdio/tstgetln.input delete mode 100644 stdio/tstscanf.c delete mode 100644 stdio/tstscanf.input delete mode 100644 stdio/vasprintf.c delete mode 100644 stdio/vdprintf.c delete mode 100644 stdio/vfprintf.c delete mode 100644 stdio/vfscanf.c delete mode 100644 stdio/vprintf.c delete mode 100644 stdio/vscanf.c delete mode 100644 stdio/vsnprintf.c delete mode 100644 stdio/vsprintf.c delete mode 100644 stdio/vsscanf.c delete mode 100644 stdio/xbug.c diff --git a/ChangeLog b/ChangeLog index 610def7e75..5e0887b88a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,80 @@ Mon Oct 16 03:22:37 1995 Roland McGrath + * Makefile (subdirs): Replace stdio with stdio-common and $(stdio). + * configure.in: Grok arg --enable-libio. + ($stdio = libio): Define USE_IN_LIBIO. + * config.h.in (USE_IN_LIBIO): Add #undef. + * config.make.in (stdio): New variable, set by configure. + * Makeconfig (stdio): New variable. + * stdio.h [USE_IN_LIBIO]: Include libio/stdio.h instead of + stdio/stdio.h. + * stdio-common/Makefile: New file. + * stdio/Makefile: Half the contents moved to stdio-common/Makefile. + * stdio/_itoa.c: Moved to stdio-common. + * stdio/_itoa.h: Moved to stdio-common. + * stdio/asprintf.c: Moved to stdio-common. + * stdio/bug1.c: Moved to stdio-common. + * stdio/bug1.input: Moved to stdio-common. + * stdio/bug2.c: Moved to stdio-common. + * stdio/bug3.c: Moved to stdio-common. + * stdio/bug4.c: Moved to stdio-common. + * stdio/bug5.c: Moved to stdio-common. + * stdio/bug6.c: Moved to stdio-common. + * stdio/bug6.input: Moved to stdio-common. + * stdio/bug7.c: Moved to stdio-common. + * stdio/dprintf.c: Moved to stdio-common. + * stdio/errnobug.c: Moved to stdio-common. + * stdio/getline.c: Moved to stdio-common. + * stdio/getw.c: Moved to stdio-common. + * stdio/perror.c: Moved to stdio-common. + * stdio/printf-parse.h: Moved to stdio-common. + * stdio/printf-prs.c: Moved to stdio-common. + * stdio/printf.c: Moved to stdio-common. + * stdio/printf.h: Moved to stdio-common. + * stdio/printf_fp.c: Moved to stdio-common. + * stdio/psignal.c: Moved to stdio-common. + * stdio/putw.c: Moved to stdio-common. + * stdio/reg-printf.c: Moved to stdio-common. + * stdio/scanf.c: Moved to stdio-common. + * stdio/snprintf.c: Moved to stdio-common. + * stdio/sprintf.c: Moved to stdio-common. + * stdio/sscanf.c: Moved to stdio-common. + * stdio/tempnam.c: Moved to stdio-common. + * stdio/temptest.c: Moved to stdio-common. + * stdio/test-fseek.c: Moved to stdio-common. + * stdio/test-fwrite.c: Moved to stdio-common. + * stdio/test-popen.c: Moved to stdio-common. + * stdio/test_rdwr.c: Moved to stdio-common. + * stdio/tmpfile.c: Moved to stdio-common. + * stdio/tmpnam.c: Moved to stdio-common. + * stdio/tst-fileno.c: Moved to stdio-common. + * stdio/tst-printf.c: Moved to stdio-common. + * stdio/tstgetln.c: Moved to stdio-common. + * stdio/tstgetln.input: Moved to stdio-common. + * stdio/tstscanf.c: Moved to stdio-common. + * stdio/tstscanf.input: Moved to stdio-common. + * stdio/vfprintf.c: Moved to stdio-common. + * stdio/vfscanf.c: Moved to stdio-common. + * stdio/vprintf.c: Moved to stdio-common. + * stdio/xbug.c: Moved to stdio-common. + * sysdeps/generic/Makefile (siglist.c rules): Do this in subdir + stdio-common instead of stdio. + * sysdeps/unix/Makefile (errlist.c rules): Likewise. + * stdio-common/asprintf.c [USE_IN_LIBIO]: Call libio primitive + function. + * stdio-common/dprintf.c: Likewise. + * stdio-common/printf.c: Likewise. + * stdio-common/scanf.c: Likewise. + * stdio-common/snprintf.c: Likewise. + * stdio-common/sprintf.c: Likewise. + * stdio-common/sscanf.c: Likewise. + * stdio-common/vprintf.c: Likewise. + + * Makerules: Include $(+depfiles) directly instead of generating + depend-$(subdir). + (depend-$(subdir)): Target removed. + (common-clean): Don't remove depend-$(subdir). + * sysdeps/unix/sysv/linux/Makefile (rtld-installed-name): New variable. (config-LDFLAGS): Variable removed. diff --git a/Makeconfig b/Makeconfig index d21d7114e0..cbb2db0102 100644 --- a/Makeconfig +++ b/Makeconfig @@ -114,6 +114,12 @@ export sysdep_dir := $(sysdep_dir) #### +# Set this to either `stdio' or `libio', to compile in either GNU stdio +# or GNU libio. +ifndef stdio +stdio = stdio +endif + # Common prefix for machine-independent installation directories. ifeq ($(origin prefix),undefined) # ifndef would override explicit empty value. prefix = /usr/local diff --git a/Makefile b/Makefile index f3d5e1c2f2..f1aae8ed0b 100644 --- a/Makefile +++ b/Makefile @@ -51,10 +51,10 @@ sysdep-subdirs := $(subst $(\n), ,$(sysdep-subdirs)) endif # These are the subdirectories containing the library source. -subdirs := csu assert ctype locale intl math setjmp signal stdio stdlib \ - malloc string time dirent grp pwd posix io termios resource \ - misc socket sysvipc gmon gnulib $(wildcard crypt) manual \ - $(sysdep-subdirs) elf +subdirs = csu assert ctype locale intl math setjmp signal stdlib \ + stdio-common $(stdio) malloc string time dirent grp pwd \ + posix io termios resource misc socket sysvipc gmon gnulib \ + $(wildcard crypt) manual $(sysdep-subdirs) elf export subdirs := $(subdirs) # Benign, useless in GNU make before 3.63. # The mach and hurd subdirectories have many generated header files which diff --git a/Makerules b/Makerules index 56f8cc89e6..ac1ac39b48 100644 --- a/Makerules +++ b/Makerules @@ -301,19 +301,10 @@ endif $(filter-out $(addsuffix .d,$(omit-deps)),\ $(+depfiles))) -$(objpfx)depend-$(subdir): Makefile ifdef +depfiles - for file in $(+depfiles:$(objpfx)%=%); do \ - echo "include \$$(objpfx)$$file"; \ - done > $@-tmp - mv -f $@-tmp $@ -else - cp /dev/null $@ -endif - ifneq ($(no_deps),t) -# Include the generated dependencies of the sources in this directory. -include $(objpfx)depend-$(subdir) +include $(+depfiles) +endif endif # Maximize efficiency by minimizing the number of rules. @@ -623,8 +614,7 @@ endef # Also remove the dependencies and generated source files. common-clean: common-mostlyclean - -rm -f $(objpfx)depend-$(subdir) $(+depfiles) - -rm -f $(addprefix $(objpfx),$(generated)) + -rm -f $(addprefix $(objpfx),$(generated)) $(+depfiles) # Produce a file `stub-$(subdir)' which contains `#define __stub_FUNCTION' # for each function which is a stub. We grovel over all the .d files diff --git a/config.h.in b/config.h.in index 800fe15720..485f86170f 100644 --- a/config.h.in +++ b/config.h.in @@ -30,6 +30,10 @@ #define HAVE_WEAK_SYMBOLS #endif #endif + +/* Define to use GNU libio instead of GNU stdio. + This is defined by configure under --enable-libio. */ +#undef USE_IN_LIBIO /* */ /* These symbols might be defined by some sysdeps configures. */ diff --git a/config.make.in b/config.make.in index 69d4fcbdea..2af925da48 100644 --- a/config.make.in +++ b/config.make.in @@ -24,6 +24,7 @@ gnu-ld = @gnu_ld@ build-shared = @shared@ build-profile = @profile@ build-omitfp = @omitfp@ +stdio = @stdio@ # Build tools. CC = @CC@ diff --git a/configure.in b/configure.in index e7d4ecbb39..239e7fd874 100644 --- a/configure.in +++ b/configure.in @@ -40,6 +40,11 @@ AC_ARG_WITH(weak-symbols, dnl --with-weak-symbols if weak symbols are available in as and ld, weak=$withval, weak=no) +AC_ARG_ENABLE(libio, dnl +[ --enable-libio build in GNU libio instead of GNU stdio], + stdio=libio, stdio=stdio) +AC_SUBST(stdio) + dnl Arguments to enable or disable building the shared, profiled, and dnl -fomit-frame-pointer libraries. AC_ARG_ENABLE(shared, dnl @@ -485,6 +490,9 @@ fi AC_SUBST(profile) AC_SUBST(omitfp) +if test $stdio = libio; then + AC_DEFINE(USE_IN_LIBIO) +fi if test "`(cd $srcdir; pwd)`" = "`pwd`"; then config_makefile= diff --git a/stdio-common/Makefile b/stdio-common/Makefile new file mode 100644 index 0000000000..6ca6c7d1d3 --- /dev/null +++ b/stdio-common/Makefile @@ -0,0 +1,47 @@ +# Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. +# This file is part of the GNU C Library. + +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. + +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. + +# You should have received a copy of the GNU Library General Public +# License along with the GNU C Library; see the file COPYING.LIB. If +# not, write to the Free Software Foundation, Inc., 675 Mass Ave, +# Cambridge, MA 02139, USA. + +# +# Specific makefile for stdio-common. +# +subdir := stdio-common + +headers := stdio_lim.h printf.h + +routines := \ + ctermid cuserid \ + vfprintf vprintf printf_fp reg-printf printf-prs _itoa \ + vsnprintf vsprintf vasprintf \ + fprintf printf snprintf sprintf asprintf \ + dprintf vdprintf \ + vfscanf vscanf vsscanf \ + fscanf scanf sscanf \ + perror psignal \ + tmpfile tmpnam tempnam tempname \ + getline getw putw \ + remove rename +aux := errlist siglist +distribute := _itoa.h printf-parse.h + +tests := tst-printf tstscanf test_rdwr test-popen tstgetln test-fseek \ + temptest tst-fileno test-fwrite \ + xbug errnobug \ + bug1 bug2 bug3 bug4 bug5 bug6 bug7 + + +include ../Rules diff --git a/stdio-common/_itoa.c b/stdio-common/_itoa.c new file mode 100644 index 0000000000..caa8179624 --- /dev/null +++ b/stdio-common/_itoa.c @@ -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 +and Ulrich Drepper . + +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 +#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 index 0000000000..ab3d1d1d3a --- /dev/null +++ b/stdio-common/_itoa.h @@ -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 + +/* 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 index 0000000000..85ab7b1041 --- /dev/null +++ b/stdio-common/asprintf.c @@ -0,0 +1,42 @@ +/* Copyright (C) 1991, 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 +#include + +#ifdef USE_IN_LIBIO +# define vasprintf _IO_vasprintf +#endif + +/* Write formatted output from FORMAT to a string which is + allocated with malloc and stored in *STRING_PTR. */ +/* VARARGS2 */ +int +asprintf (string_ptr, format) + char **string_ptr; + const char *format; +{ + 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 index 0000000000..755bc4231b --- /dev/null +++ b/stdio-common/bug1.c @@ -0,0 +1,28 @@ +#include +#include +#include + +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 index 0000000000..5595fa46c0 --- /dev/null +++ b/stdio-common/bug1.input @@ -0,0 +1 @@ +95 diff --git a/stdio-common/bug2.c b/stdio-common/bug2.c new file mode 100644 index 0000000000..2b34c890bf --- /dev/null +++ b/stdio-common/bug2.c @@ -0,0 +1,12 @@ +#include +#include + +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 index 0000000000..1684720b9f --- /dev/null +++ b/stdio-common/bug3.c @@ -0,0 +1,52 @@ +#include +#include +#include + +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 index 0000000000..00abf3c502 --- /dev/null +++ b/stdio-common/bug4.c @@ -0,0 +1,50 @@ +#ifdef _LIBC +#include +#endif +#include +#include +#include + +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 index 0000000000..18f069ae29 --- /dev/null +++ b/stdio-common/bug5.c @@ -0,0 +1,60 @@ +/* If stdio is working correctly, after this is run infile and outfile + will have the same contents. If the bug (found in GNU C library 0.3) + exhibits itself, outfile will be missing the 2nd through 1023rd + characters. */ + +#include +#include +#include +#include + +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 index 0000000000..4a37ab2584 --- /dev/null +++ b/stdio-common/bug6.c @@ -0,0 +1,27 @@ +#include +#include + +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 index 0000000000..d996e399c3 --- /dev/null +++ b/stdio-common/bug6.input @@ -0,0 +1 @@ +XY 1234L diff --git a/stdio-common/bug7.c b/stdio-common/bug7.c new file mode 100644 index 0000000000..af06f8d6a5 --- /dev/null +++ b/stdio-common/bug7.c @@ -0,0 +1,53 @@ +/* Regression test for fseek and freopen bugs. */ + +#include + +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 index 0000000000..5746d49841 --- /dev/null +++ b/stdio-common/dprintf.c @@ -0,0 +1,41 @@ +/* Copyright (C) 1991, 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 +#include + +#ifdef USE_IN_LIBIO +# define vdprintf _IO_vdprintf +#endif + +/* Write formatted output to D, according to the format string FORMAT. */ +/* VARARGS2 */ +int +dprintf (d, format) + int d; + const char *format; +{ + 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 index 0000000000..cf17be30a2 --- /dev/null +++ b/stdio-common/errnobug.c @@ -0,0 +1,60 @@ +/* Regression test for reported old bug that errno is clobbered + by the first successful output to a stream on an unseekable object. +Copyright (C) 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include + +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 index 0000000000..bc6d1003b7 --- /dev/null +++ b/stdio-common/fprintf.c @@ -0,0 +1,38 @@ +/* Copyright (C) 1991 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include + + +/* 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 index 0000000000..cbe0103368 --- /dev/null +++ b/stdio-common/fscanf.c @@ -0,0 +1,38 @@ +/* Copyright (C) 1991 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include + + +/* 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 index 0000000000..1a2f975c75 --- /dev/null +++ b/stdio-common/getline.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1991, 1992, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include + +#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 index 0000000000..45d4d8875d --- /dev/null +++ b/stdio-common/getw.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1991 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include + + +/* 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 index 0000000000..1054acaa7d --- /dev/null +++ b/stdio-common/perror.c @@ -0,0 +1,42 @@ +/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include + +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 index 0000000000..0f6e9e287b --- /dev/null +++ b/stdio-common/printf-parse.h @@ -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 +#include +#include +#include + +#define NDEBUG 1 +#include + +#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 index 0000000000..811a9cb7eb --- /dev/null +++ b/stdio-common/printf-prs.c @@ -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 +#include +#include +#include + +#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 index 0000000000..d8aa895a77 --- /dev/null +++ b/stdio-common/printf.c @@ -0,0 +1,40 @@ +/* Copyright (C) 1991, 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 +#include + +#ifdef USE_IN_LIBIO +# define vprintf _IO_vprintf +#endif + +/* Write formatted output to stdout from the format string FORMAT. */ +/* VARARGS1 */ +int +printf (format) + const char *format; +{ + 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 index 0000000000..0f381c77f4 --- /dev/null +++ b/stdio-common/printf.h @@ -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 + +__BEGIN_DECLS + +#define __need_FILE +#include +#define __need_size_t +#include + + +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 index 0000000000..28d13d61b8 --- /dev/null +++ b/stdio-common/printf_fp.c @@ -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 +#else +# include +#endif +#include +#include +#include +#include +#include +#include "../stdlib/gmp.h" +#include "../stdlib/gmp-impl.h" +#include "../stdlib/longlong.h" +#include "../stdlib/fpioconst.h" +#include "../locale/localeinfo.h" +#include +#include +#include +#include +#include +#include + +#define NDEBUG /* Undefine this for debugging assertions. */ +#include + +/* This defines make it possible to use the same code for GNU C library and + the GNU I/O library. */ +#ifdef USE_IN_LIBIO +# define PUT(f, s, n) _IO_sputn (f, s, n) +# define PAD(f, c, n) _IO_padn (f, c, n) +/* We use this file GNU C library and GNU I/O library. So make + names equal. */ +# undef putc +# define putc(c, f) _IO_putc (c, f) +# define size_t _IO_size_t +# define FILE _IO_FILE +#else /* ! USE_IN_LIBIO */ +# define PUT(f, s, n) fwrite (s, 1, n, f) +# define PAD(f, c, n) __printf_pad (f, c, n) +ssize_t __printf_pad __P ((FILE *, char pad, int n)); /* In vfprintf.c. */ +#endif /* USE_IN_LIBIO */ + +/* Macros for doing the actual output. */ + +#define outchar(ch) \ + do \ + { \ + register CONST int outc = (ch); \ + if (putc (outc, fp) == EOF) \ + return -1; \ + ++done; \ + } while (0) + +#define PRINT(ptr, len) \ + do \ + { \ + register size_t outlen = (len); \ + if (len > 20) \ + { \ + if (PUT (fp, ptr, outlen) != outlen) \ + return -1; \ + ptr += outlen; \ + done += outlen; \ + } \ + else \ + { \ + while (outlen-- > 0) \ + outchar (*ptr++); \ + } \ + } while (0) + +#define PADN(ch, len) \ + do \ + { \ + if (PAD (fp, ch, len) != len) \ + return -1; \ + done += len; \ + } \ + while (0) + +/* We use the GNU MP library to handle large numbers. + + An MP variable occupies a varying number of entries in its array. We keep + track of this number for efficiency reasons. Otherwise we would always + have to process the whole array. */ +#define MPN_VAR(name) mp_limb *name; mp_size_t name##size + +#define MPN_ASSIGN(dst,src) \ + memcpy (dst, src, (dst##size = src##size) * sizeof (mp_limb)) +#define MPN_GE(u,v) \ + (u##size > v##size || (u##size == v##size && __mpn_cmp (u, v, u##size) >= 0)) + +extern int __isinfl (long double), __isnanl (long double); + +extern mp_size_t __mpn_extract_double (mp_ptr res_ptr, mp_size_t size, + int *expt, int *is_neg, + double value); +extern mp_size_t __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size, + int *expt, int *is_neg, + long double value); + + +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; +} + +/* 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 index 0000000000..8997a2ecdf --- /dev/null +++ b/stdio-common/psignal.c @@ -0,0 +1,49 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include + + +#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 index 0000000000..1b70baeeaf --- /dev/null +++ b/stdio-common/putw.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1991 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include + + +/* 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 index 0000000000..95d7a1f3c9 --- /dev/null +++ b/stdio-common/reg-printf.c @@ -0,0 +1,47 @@ +/* Copyright (C) 1991 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include + +/* 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 index 0000000000..cf43363958 --- /dev/null +++ b/stdio-common/scanf.c @@ -0,0 +1,40 @@ +/* Copyright (C) 1991, 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 +#include + +#ifdef USE_IN_LIBIO +# define vscanf _IO_vscanf +#endif + +/* Read formatted input from stdin according to the format string FORMAT. */ +/* VARARGS1 */ +int +scanf (format) + const char *format; +{ + 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 index 0000000000..00b85f3175 --- /dev/null +++ b/stdio-common/snprintf.c @@ -0,0 +1,43 @@ +/* Copyright (C) 1991, 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 +#include + +#ifdef USE_IN_LIBIO +# define vsnprintf _IO_vsnprintf +#endif + +/* Write formatted output into S, according to the format + string FORMAT, writing no more than MAXLEN characters. */ +/* VARARGS3 */ +int +snprintf (s, maxlen, format) + char *s; + size_t maxlen; + const char *format; +{ + 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 index 0000000000..9cfc89cb84 --- /dev/null +++ b/stdio-common/sprintf.c @@ -0,0 +1,41 @@ +/* Copyright (C) 1991, 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 +#include + +#ifdef USE_IN_LIBIO +# define vsprintf _IO_vsprintf +#endif + +/* Write formatted output into S, according to the format string FORMAT. */ +/* VARARGS2 */ +int +sprintf (s, format) + char *s; + const char *format; +{ + 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 index 0000000000..794a3ce628 --- /dev/null +++ b/stdio-common/sscanf.c @@ -0,0 +1,41 @@ +/* Copyright (C) 1991, 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 +#include + +#ifdef USE_IN_LIBIO +# define __vsscanf _IO_vsscanf +#endif + +/* Read formatted input from S, according to the format string FORMAT. */ +/* VARARGS2 */ +int +sscanf (s, format) + const char *s; + const char *format; +{ + 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 index 0000000000..14988a8656 --- /dev/null +++ b/stdio-common/tempnam.c @@ -0,0 +1,50 @@ +/* Copyright (C) 1991, 1993 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include +#include +#include + + +/* 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 index 0000000000..374719896a --- /dev/null +++ b/stdio-common/temptest.c @@ -0,0 +1,31 @@ +#include +#include +#include + +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 index 0000000000..d56c669a54 --- /dev/null +++ b/stdio-common/test-fseek.c @@ -0,0 +1,67 @@ +#include +#include + +#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 index 0000000000..cc6cdf038e --- /dev/null +++ b/stdio-common/test-fwrite.c @@ -0,0 +1,68 @@ +#include +#include + +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 index 0000000000..b452f3f63c --- /dev/null +++ b/stdio-common/test-popen.c @@ -0,0 +1,67 @@ +#include +#include +#include + +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 index 0000000000..f987f16cd4 --- /dev/null +++ b/stdio-common/test_rdwr.c @@ -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 +#include +#include +#include +#include + + +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 index 0000000000..dfe11ada50 --- /dev/null +++ b/stdio-common/tmpfile.c @@ -0,0 +1,43 @@ +/* Copyright (C) 1991, 1993 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include + + +/* 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 index 0000000000..88dd0a4ca5 --- /dev/null +++ b/stdio-common/tmpnam.c @@ -0,0 +1,42 @@ +/* Copyright (C) 1991, 1993 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include + + +/* 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 index 0000000000..81945f7b44 --- /dev/null +++ b/stdio-common/tst-fileno.c @@ -0,0 +1,37 @@ +/* Copyright (C) 1994 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include + +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 index 0000000000..c177da18b2 --- /dev/null +++ b/stdio-common/tst-printf.c @@ -0,0 +1,298 @@ +/* Copyright (C) 1991, 1992, 1993, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#ifdef BSD +#include +#define EXIT_SUCCESS 0 +#else +#include +#include +#include +#endif + +#include + + +void +DEFUN(fmtchk, (fmt), CONST char *fmt) +{ + (void) fputs(fmt, stdout); + (void) printf(":\t`"); + (void) printf(fmt, 0x12); + (void) printf("'\n"); +} + +void +DEFUN(fmtst1chk, (fmt), CONST char *fmt) +{ + (void) fputs(fmt, stdout); + (void) printf(":\t`"); + (void) printf(fmt, 4, 0x12); + (void) printf("'\n"); +} + +void +DEFUN(fmtst2chk, (fmt), CONST char *fmt) +{ + (void) fputs(fmt, stdout); + (void) printf(":\t`"); + (void) printf(fmt, 4, 4, 0x12); + (void) printf("'\n"); +} + +/* This page is covered by the following copyright: */ + +/* (C) Copyright C E Chew + * + * Feel free to copy, use and distribute this software provided: + * + * 1. you do not pretend that you wrote it + * 2. you leave this copyright notice intact. + */ + +/* + * Extracted from exercise.c for glibc-1.05 bug report by Bruce Evans. + */ + +#define DEC -123 +#define INT 255 +#define UNS (~0) + +/* Formatted Output Test + * + * This exercises the output formatting code. + */ + +void +DEFUN_VOID(fp_test) +{ + int i, j, k, l; + char buf[7]; + char *prefix = buf; + char tp[20]; + + puts("\nFormatted output test"); + printf("prefix 6d 6o 6x 6X 6u\n"); + strcpy(prefix, "%"); + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + for (k = 0; k < 2; k++) { + for (l = 0; l < 2; l++) { + strcpy(prefix, "%"); + if (i == 0) strcat(prefix, "-"); + if (j == 0) strcat(prefix, "+"); + if (k == 0) strcat(prefix, "#"); + if (l == 0) strcat(prefix, "0"); + printf("%5s |", prefix); + strcpy(tp, prefix); + strcat(tp, "6d |"); + printf(tp, DEC); + strcpy(tp, prefix); + strcat(tp, "6o |"); + printf(tp, INT); + strcpy(tp, prefix); + strcat(tp, "6x |"); + printf(tp, INT); + strcpy(tp, prefix); + strcat(tp, "6X |"); + printf(tp, INT); + strcpy(tp, prefix); + strcat(tp, "6u |"); + printf(tp, UNS); + printf("\n"); + } + } + } + } + printf("%10s\n", (char *) NULL); + printf("%-10s\n", (char *) NULL); +} + +int +DEFUN_VOID(main) +{ + static char shortstr[] = "Hi, Z."; + static char longstr[] = "Good morning, Doctor Chandra. This is Hal. \ +I am ready for my first lesson today."; + + fmtchk("%.4x"); + fmtchk("%04x"); + fmtchk("%4.4x"); + fmtchk("%04.4x"); + fmtchk("%4.3x"); + fmtchk("%04.3x"); + + fmtst1chk("%.*x"); + fmtst1chk("%0*x"); + fmtst2chk("%*.*x"); + fmtst2chk("%0*.*x"); + +#ifndef BSD + printf("bad format:\t\"%z\"\n"); + printf("nil pointer (padded):\t\"%10p\"\n", (PTR) NULL); +#endif + + printf("decimal negative:\t\"%d\"\n", -2345); + printf("octal negative:\t\"%o\"\n", -2345); + printf("hex negative:\t\"%x\"\n", -2345); + printf("long decimal number:\t\"%ld\"\n", -123456L); + printf("long octal negative:\t\"%lo\"\n", -2345L); + printf("long unsigned decimal number:\t\"%lu\"\n", -123456L); + printf("zero-padded LDN:\t\"%010ld\"\n", -123456L); + printf("left-adjusted ZLDN:\t\"%-010ld\"\n", -123456); + printf("space-padded LDN:\t\"%10ld\"\n", -123456L); + printf("left-adjusted SLDN:\t\"%-10ld\"\n", -123456L); + + printf("zero-padded string:\t\"%010s\"\n", shortstr); + printf("left-adjusted Z string:\t\"%-010s\"\n", shortstr); + printf("space-padded string:\t\"%10s\"\n", shortstr); + printf("left-adjusted S string:\t\"%-10s\"\n", shortstr); + printf("null string:\t\"%s\"\n", (char *)NULL); + printf("limited string:\t\"%.22s\"\n", longstr); + + printf("e-style >= 1:\t\"%e\"\n", 12.34); + printf("e-style >= .1:\t\"%e\"\n", 0.1234); + printf("e-style < .1:\t\"%e\"\n", 0.001234); + printf("e-style big:\t\"%.60e\"\n", 1e20); + printf ("e-style == .1:\t\"%e\"\n", 0.1); + printf("f-style >= 1:\t\"%f\"\n", 12.34); + printf("f-style >= .1:\t\"%f\"\n", 0.1234); + printf("f-style < .1:\t\"%f\"\n", 0.001234); + printf("g-style >= 1:\t\"%g\"\n", 12.34); + printf("g-style >= .1:\t\"%g\"\n", 0.1234); + printf("g-style < .1:\t\"%g\"\n", 0.001234); + printf("g-style big:\t\"%.60g\"\n", 1e20); + + printf (" %6.5f\n", .099999999860301614); + printf (" %6.5f\n", .1); + printf ("x%5.4fx\n", .5); + + printf ("%#03x\n", 1); + + { + double d = FLT_MIN; + int niter = 17; + + while (niter-- != 0) + printf ("%.17e\n", d / 2); + fflush (stdout); + } + + printf ("%15.5e\n", 4.9406564584124654e-324); + +#define FORMAT "|%12.4f|%12.4e|%12.4g|\n" + printf (FORMAT, 0.0, 0.0, 0.0); + printf (FORMAT, 1.0, 1.0, 1.0); + printf (FORMAT, -1.0, -1.0, -1.0); + printf (FORMAT, 100.0, 100.0, 100.0); + printf (FORMAT, 1000.0, 1000.0, 1000.0); + printf (FORMAT, 10000.0, 10000.0, 10000.0); + printf (FORMAT, 12345.0, 12345.0, 12345.0); + printf (FORMAT, 100000.0, 100000.0, 100000.0); + printf (FORMAT, 123456.0, 123456.0, 123456.0); +#undef FORMAT + + { + char buf[20]; + printf ("snprintf (\"%%30s\", \"foo\") == %d, \"%.*s\"\n", + snprintf (buf, sizeof (buf), "%30s", "foo"), sizeof (buf), buf); + } + + fp_test (); + + printf ("%e should be 1.234568e+06\n", 1234567.8); + printf ("%f should be 1234567.800000\n", 1234567.8); + printf ("%g should be 1.23457e+06\n", 1234567.8); + printf ("%g should be 123.456\n", 123.456); + printf ("%g should be 1e+06\n", 1000000.0); + printf ("%g should be 10\n", 10.0); + printf ("%g should be 0.02\n", 0.02); + + { + double x=1.0; + printf("%.17f\n",(1.0/x/10.0+1.0)*x-x); + } + + puts ("--- Should be no further output. ---"); + rfg1 (); + rfg2 (); + + exit(EXIT_SUCCESS); +} + +rfg1 () +{ + char buf[100]; + + sprintf (buf, "%5.s", "xyz"); + if (strcmp (buf, " ") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " "); + sprintf (buf, "%5.f", 33.3); + if (strcmp (buf, " 33") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " 33"); + sprintf (buf, "%8.e", 33.3e7); + if (strcmp (buf, " 3e+08") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " 3e+08"); + sprintf (buf, "%8.E", 33.3e7); + if (strcmp (buf, " 3E+08") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " 3E+08"); + sprintf (buf, "%.g", 33.3); + if (strcmp (buf, "3e+01") != 0) + printf ("got: '%s', expected: '%s'\n", buf, "3e+01"); + sprintf (buf, "%.G", 33.3); + if (strcmp (buf, "3E+01") != 0) + printf ("got: '%s', expected: '%s'\n", buf, "3E+01"); + return 0; +} + +rfg2 () +{ + int prec; + char buf[100]; + + prec = 0; + sprintf (buf, "%.*g", prec, 3.3); + if (strcmp (buf, "3") != 0) + printf ("got: '%s', expected: '%s'\n", buf, "3"); + prec = 0; + sprintf (buf, "%.*G", prec, 3.3); + if (strcmp (buf, "3") != 0) + printf ("got: '%s', expected: '%s'\n", buf, "3"); + prec = 0; + sprintf (buf, "%7.*G", prec, 3.33); + if (strcmp (buf, " 3") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " 3"); + prec = 3; + sprintf (buf, "%04.*o", prec, 33); + if (strcmp (buf, " 041") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " 041"); + prec = 7; + sprintf (buf, "%09.*u", prec, 33); + if (strcmp (buf, " 0000033") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " 0000033"); + prec = 3; + sprintf (buf, "%04.*x", prec, 33); + if (strcmp (buf, " 021") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " 021"); + prec = 3; + sprintf (buf, "%04.*X", prec, 33); + if (strcmp (buf, " 021") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " 021"); + return 0; +} diff --git a/stdio-common/tstgetln.c b/stdio-common/tstgetln.c new file mode 100644 index 0000000000..ea8ea817da --- /dev/null +++ b/stdio-common/tstgetln.c @@ -0,0 +1,46 @@ +/* Copyright (C) 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include + +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 index 0000000000..d04ed5bf78 --- /dev/null +++ b/stdio-common/tstgetln.input @@ -0,0 +1,3 @@ +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy +z diff --git a/stdio-common/tstscanf.c b/stdio-common/tstscanf.c new file mode 100644 index 0000000000..53d4b0ac47 --- /dev/null +++ b/stdio-common/tstscanf.c @@ -0,0 +1,100 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#ifdef BSD +#include +#else +#include +#endif +#include +#include + + +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 index 0000000000..26158652dd --- /dev/null +++ b/stdio-common/tstscanf.input @@ -0,0 +1,7 @@ +25 54.32E-1 thompson +56789 0123 56a72 +2 quarts of oil +-12.8degrees Celsius +lots of luck +10.0LBS of fertilizer +100ergs of energy diff --git a/stdio-common/vasprintf.c b/stdio-common/vasprintf.c new file mode 100644 index 0000000000..d2ad6b1da6 --- /dev/null +++ b/stdio-common/vasprintf.c @@ -0,0 +1,86 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include +#include +#include + + + +/* 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 index 0000000000..9df4e537bc --- /dev/null +++ b/stdio-common/vdprintf.c @@ -0,0 +1,51 @@ +/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include +#include +#include + + +/* 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 index 0000000000..63a5148463 --- /dev/null +++ b/stdio-common/vfprintf.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 +#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 +#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; +} + +/* Group the digits according to the grouping rules of the current locale. + The interpretation of GROUPING is as in `struct lconv' from . */ + +static char * +group_number (char *w, char *workend, const char *grouping, + wchar_t thousands_sep) +{ + int len; + char *src, *s; + + /* We treat all negative values like CHAR_MAX. */ + + if (*grouping == CHAR_MAX || *grouping < 0) + /* No grouping should be done. */ + return w; + + len = *grouping; + + /* Copy existing string so that nothing gets overwritten. */ + src = (char *) alloca (workend - w); + memcpy (src, w + 1, workend - w); + s = &src[workend - w - 1]; + w = workend; + + /* Process all characters in the string. */ + while (s >= src) + { + *w-- = *s--; + + if (--len == 0 && s >= src) + { + /* A new group begins. */ + *w-- = thousands_sep; + + len = *grouping++; + if (*grouping == '\0') + /* The previous grouping repeats ad infinitum. */ + --grouping; + else if (*grouping == CHAR_MAX || *grouping < 0) + { + /* No further grouping to be done. + Copy the rest of the number. */ + do + *w-- = *s--; + while (s >= src); + break; + } + } + } + return w; +} + +#ifdef USE_IN_LIBIO +/* Helper "class" for `fprintf to unbuffered': creates a temporary buffer. */ +struct helper_file + { + struct _IO_FILE_plus _f; + _IO_FILE *_put_stream; + }; + +static int +_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 index 0000000000..a778346287 --- /dev/null +++ b/stdio-common/vfscanf.c @@ -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 +#include "../locale/localeinfo.h" +#include +#include +#include +#include +#include +#include +#include + + +#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 index 0000000000..77f1da47e2 --- /dev/null +++ b/stdio-common/vprintf.c @@ -0,0 +1,37 @@ +/* Copyright (C) 1991, 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 +#undef __OPTIMIZE__ /* Avoid inline `vprintf' function. */ +#include + +#undef vprintf + +#ifdef USE_IN_LIBIO +# define vfprintf _IO_vfprintf +#endif + +/* Write formatted output to stdout according to the + format string FORMAT, using the argument list in ARG. */ +int +vprintf (format, arg) + const char *format; + __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 index 0000000000..0d829440e9 --- /dev/null +++ b/stdio-common/vscanf.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include + +#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 index 0000000000..a02c259131 --- /dev/null +++ b/stdio-common/vsnprintf.c @@ -0,0 +1,56 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include + + +/* + * 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 index 0000000000..82be90f1fa --- /dev/null +++ b/stdio-common/vsprintf.c @@ -0,0 +1,50 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include +#include +#include + + +/* 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 index 0000000000..6f027d5065 --- /dev/null +++ b/stdio-common/vsscanf.c @@ -0,0 +1,58 @@ +/* Copyright (C) 1991, 1992, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include +#include + +#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 index 0000000000..ec648f5566 --- /dev/null +++ b/stdio-common/xbug.c @@ -0,0 +1,63 @@ +#include + +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.h b/stdio.h index a82be070c3..457eabe32f 100644 --- a/stdio.h +++ b/stdio.h @@ -1 +1,5 @@ +#ifdef USE_IN_LIBIO +#include +#else #include +#endif diff --git a/stdio/Makefile b/stdio/Makefile index 955d7f1fcd..a15aa56aff 100644 --- a/stdio/Makefile +++ b/stdio/Makefile @@ -21,39 +21,23 @@ # subdir := stdio -headers := stdio.h stdio_lim.h printf.h +headers := stdio.h routines := \ - ctermid cuserid \ feof ferror clearerr fileno \ newstream fopen freopen fdopen fopncook fmemopen \ setbuf setvbuf setbuffer setlinebuf \ fseek ftell rewind fgetpos fsetpos \ - vfprintf vprintf printf_fp reg-printf printf-prs _itoa \ - vsnprintf vsprintf vasprintf \ - fprintf printf snprintf sprintf asprintf \ - dprintf vdprintf \ - vfscanf vscanf vsscanf \ - fscanf scanf sscanf \ fread fwrite \ ungetc \ - fgetc getc getchar getw \ - fputc putc putchar putw \ + fgetc getc getchar \ + fputc putc putchar \ fgets gets fputs puts \ - getdelim getline \ - perror psignal \ - tmpfile tmpnam tempnam tempname \ + getdelim \ fclose fflush \ - remove rename \ memstream obstream \ internals sysd-stdio pipestream stdio_init libc_fatal -aux := errlist siglist defs glue -distribute := _itoa.h printf-parse.h - -tests := tst-printf tstscanf test_rdwr test-popen tstgetln test-fseek \ - temptest tst-fileno test-fwrite \ - xbug errnobug \ - bug1 bug2 bug3 bug4 bug5 bug6 bug7 +aux := defs glue include ../Rules diff --git a/stdio/_itoa.c b/stdio/_itoa.c deleted file mode 100644 index caa8179624..0000000000 --- a/stdio/_itoa.c +++ /dev/null @@ -1,418 +0,0 @@ -/* 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 -and Ulrich Drepper . - -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 -#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/_itoa.h b/stdio/_itoa.h deleted file mode 100644 index ab3d1d1d3a..0000000000 --- a/stdio/_itoa.h +++ /dev/null @@ -1,32 +0,0 @@ -/* 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 - -/* 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/asprintf.c b/stdio/asprintf.c deleted file mode 100644 index 9b69800f73..0000000000 --- a/stdio/asprintf.c +++ /dev/null @@ -1,39 +0,0 @@ -/* 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 -#include -#include - - -/* Write formatted output from FORMAT to a string which is - allocated with malloc and stored in *STRING_PTR. */ -/* VARARGS2 */ -int -DEFUN(asprintf, (string_ptr, format), - char **string_ptr AND CONST char *format DOTS) -{ - va_list arg; - int done; - - va_start(arg, format); - done = vasprintf(string_ptr, format, arg); - va_end(arg); - - return done; -} diff --git a/stdio/bug1.c b/stdio/bug1.c deleted file mode 100644 index 755bc4231b..0000000000 --- a/stdio/bug1.c +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include -#include - -int -DEFUN_VOID(main) -{ - char *bp; - size_t size; - FILE *stream; - int lose = 0; - - stream = open_memstream (&bp, &size); - fprintf (stream, "hello"); - fflush (stream); - printf ("buf = %s, size = %d\n", bp, size); - lose |= size != 5; - lose |= strncmp (bp, "hello", size); - fprintf (stream, ", world"); - fclose (stream); - printf ("buf = %s, size = %d\n", bp, size); - lose |= size != 12; - lose |= strncmp (bp, "hello, world", 12); - - puts (lose ? "Test FAILED!" : "Test succeeded."); - - return lose; -} diff --git a/stdio/bug1.input b/stdio/bug1.input deleted file mode 100644 index 5595fa46c0..0000000000 --- a/stdio/bug1.input +++ /dev/null @@ -1 +0,0 @@ -95 diff --git a/stdio/bug2.c b/stdio/bug2.c deleted file mode 100644 index 2b34c890bf..0000000000 --- a/stdio/bug2.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include - -int -DEFUN_VOID(main) -{ - int i; - puts ("This should print \"wow = I\" for I from 0 to 39 inclusive."); - for (i = 0; i < 40; i++) - printf ("%s = %d\n", "wow", i); - return 0; -} diff --git a/stdio/bug3.c b/stdio/bug3.c deleted file mode 100644 index 1684720b9f..0000000000 --- a/stdio/bug3.c +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include -#include - -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/bug4.c b/stdio/bug4.c deleted file mode 100644 index 00abf3c502..0000000000 --- a/stdio/bug4.c +++ /dev/null @@ -1,50 +0,0 @@ -#ifdef _LIBC -#include -#endif -#include -#include -#include - -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/bug5.c b/stdio/bug5.c deleted file mode 100644 index 18f069ae29..0000000000 --- a/stdio/bug5.c +++ /dev/null @@ -1,60 +0,0 @@ -/* 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 -#include -#include -#include - -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/bug6.c b/stdio/bug6.c deleted file mode 100644 index 4a37ab2584..0000000000 --- a/stdio/bug6.c +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include - -int -DEFUN_VOID(main) -{ - char buf[80]; - int i; - int lost = 0; - - scanf ("%2s", buf); - lost |= (buf[0] != 'X' || buf[1] != 'Y' || buf[2] != '\0'); - if (lost) - puts ("test of %2s failed."); - scanf (" "); - scanf ("%d", &i); - lost |= (i != 1234); - if (lost) - puts ("test of %d failed."); - scanf ("%c", buf); - lost |= (buf[0] != 'L'); - if (lost) - puts ("test of %c failed.\n"); - - puts (lost ? "Test FAILED!" : "Test succeeded."); - return lost; -} diff --git a/stdio/bug6.input b/stdio/bug6.input deleted file mode 100644 index d996e399c3..0000000000 --- a/stdio/bug6.input +++ /dev/null @@ -1 +0,0 @@ -XY 1234L diff --git a/stdio/bug7.c b/stdio/bug7.c deleted file mode 100644 index af06f8d6a5..0000000000 --- a/stdio/bug7.c +++ /dev/null @@ -1,53 +0,0 @@ -/* Regression test for fseek and freopen bugs. */ - -#include - -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/dprintf.c b/stdio/dprintf.c deleted file mode 100644 index fc9faa4ca2..0000000000 --- a/stdio/dprintf.c +++ /dev/null @@ -1,37 +0,0 @@ -/* 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 -#include -#include - - -/* Write formatted output to D, according to the format string FORMAT. */ -/* VARARGS2 */ -int -DEFUN(dprintf, (d, format), int d AND CONST char *format DOTS) -{ - va_list arg; - int done; - - va_start(arg, format); - done = vdprintf(d, format, arg); - va_end(arg); - - return done; -} diff --git a/stdio/errnobug.c b/stdio/errnobug.c deleted file mode 100644 index cf17be30a2..0000000000 --- a/stdio/errnobug.c +++ /dev/null @@ -1,60 +0,0 @@ -/* 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 -#include -#include - -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/fprintf.c b/stdio/fprintf.c deleted file mode 100644 index bc6d1003b7..0000000000 --- a/stdio/fprintf.c +++ /dev/null @@ -1,38 +0,0 @@ -/* 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 -#include -#include - - -/* 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/fscanf.c b/stdio/fscanf.c deleted file mode 100644 index cbe0103368..0000000000 --- a/stdio/fscanf.c +++ /dev/null @@ -1,38 +0,0 @@ -/* 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 -#include -#include - - -/* 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/getline.c b/stdio/getline.c deleted file mode 100644 index 1a2f975c75..0000000000 --- a/stdio/getline.c +++ /dev/null @@ -1,33 +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 -#include -#include - -#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/getw.c b/stdio/getw.c deleted file mode 100644 index 45d4d8875d..0000000000 --- a/stdio/getw.c +++ /dev/null @@ -1,33 +0,0 @@ -/* 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 -#include - - -/* 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/perror.c b/stdio/perror.c deleted file mode 100644 index 1054acaa7d..0000000000 --- a/stdio/perror.c +++ /dev/null @@ -1,42 +0,0 @@ -/* 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 -#include -#include - -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/printf-parse.h b/stdio/printf-parse.h deleted file mode 100644 index 0f6e9e287b..0000000000 --- a/stdio/printf-parse.h +++ /dev/null @@ -1,388 +0,0 @@ -/* 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 -#include -#include -#include - -#define NDEBUG 1 -#include - -#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/printf-prs.c b/stdio/printf-prs.c deleted file mode 100644 index 811a9cb7eb..0000000000 --- a/stdio/printf-prs.c +++ /dev/null @@ -1,72 +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 -#include -#include -#include - -#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/printf.c b/stdio/printf.c deleted file mode 100644 index 9cdae768ae..0000000000 --- a/stdio/printf.c +++ /dev/null @@ -1,37 +0,0 @@ -/* 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 -#include -#include - - -/* Write formatted output to stdout from the format string FORMAT. */ -/* VARARGS1 */ -int -DEFUN(printf, (format), CONST char *format DOTS) -{ - va_list arg; - int done; - - va_start(arg, format); - done = vprintf(format, arg); - va_end(arg); - - return done; -} diff --git a/stdio/printf.h b/stdio/printf.h deleted file mode 100644 index 0f381c77f4..0000000000 --- a/stdio/printf.h +++ /dev/null @@ -1,124 +0,0 @@ -/* 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 - -__BEGIN_DECLS - -#define __need_FILE -#include -#define __need_size_t -#include - - -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/printf_fp.c b/stdio/printf_fp.c deleted file mode 100644 index 28d13d61b8..0000000000 --- a/stdio/printf_fp.c +++ /dev/null @@ -1,990 +0,0 @@ -/* 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 -#else -# include -#endif -#include -#include -#include -#include -#include -#include "../stdlib/gmp.h" -#include "../stdlib/gmp-impl.h" -#include "../stdlib/longlong.h" -#include "../stdlib/fpioconst.h" -#include "../locale/localeinfo.h" -#include -#include -#include -#include -#include -#include - -#define NDEBUG /* Undefine this for debugging assertions. */ -#include - -/* This defines make it possible to use the same code for GNU C library and - the GNU I/O library. */ -#ifdef USE_IN_LIBIO -# define PUT(f, s, n) _IO_sputn (f, s, n) -# define PAD(f, c, n) _IO_padn (f, c, n) -/* We use this file GNU C library and GNU I/O library. So make - names equal. */ -# undef putc -# define putc(c, f) _IO_putc (c, f) -# define size_t _IO_size_t -# define FILE _IO_FILE -#else /* ! USE_IN_LIBIO */ -# define PUT(f, s, n) fwrite (s, 1, n, f) -# define PAD(f, c, n) __printf_pad (f, c, n) -ssize_t __printf_pad __P ((FILE *, char pad, int n)); /* In vfprintf.c. */ -#endif /* USE_IN_LIBIO */ - -/* Macros for doing the actual output. */ - -#define outchar(ch) \ - do \ - { \ - register CONST int outc = (ch); \ - if (putc (outc, fp) == EOF) \ - return -1; \ - ++done; \ - } while (0) - -#define PRINT(ptr, len) \ - do \ - { \ - register size_t outlen = (len); \ - if (len > 20) \ - { \ - if (PUT (fp, ptr, outlen) != outlen) \ - return -1; \ - ptr += outlen; \ - done += outlen; \ - } \ - else \ - { \ - while (outlen-- > 0) \ - outchar (*ptr++); \ - } \ - } while (0) - -#define PADN(ch, len) \ - do \ - { \ - if (PAD (fp, ch, len) != len) \ - return -1; \ - done += len; \ - } \ - while (0) - -/* We use the GNU MP library to handle large numbers. - - An MP variable occupies a varying number of entries in its array. We keep - track of this number for efficiency reasons. Otherwise we would always - have to process the whole array. */ -#define MPN_VAR(name) mp_limb *name; mp_size_t name##size - -#define MPN_ASSIGN(dst,src) \ - memcpy (dst, src, (dst##size = src##size) * sizeof (mp_limb)) -#define MPN_GE(u,v) \ - (u##size > v##size || (u##size == v##size && __mpn_cmp (u, v, u##size) >= 0)) - -extern int __isinfl (long double), __isnanl (long double); - -extern mp_size_t __mpn_extract_double (mp_ptr res_ptr, mp_size_t size, - int *expt, int *is_neg, - double value); -extern mp_size_t __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size, - int *expt, int *is_neg, - long double value); - - -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; -} - -/* 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/psignal.c b/stdio/psignal.c deleted file mode 100644 index 8997a2ecdf..0000000000 --- a/stdio/psignal.c +++ /dev/null @@ -1,49 +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 -#include -#include - - -#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/putw.c b/stdio/putw.c deleted file mode 100644 index 1b70baeeaf..0000000000 --- a/stdio/putw.c +++ /dev/null @@ -1,31 +0,0 @@ -/* 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 -#include - - -/* Write the word (int) W to STREAM. */ -int -DEFUN(putw, (w, stream), int w AND FILE *stream) -{ - /* Is there a better way? */ - if (fwrite((CONST PTR) &w, sizeof(w), 1, stream) < 1) - return(EOF); - return(0); -} diff --git a/stdio/reg-printf.c b/stdio/reg-printf.c deleted file mode 100644 index 95d7a1f3c9..0000000000 --- a/stdio/reg-printf.c +++ /dev/null @@ -1,47 +0,0 @@ -/* 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 -#include -#include -#include - -/* 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/scanf.c b/stdio/scanf.c deleted file mode 100644 index aa7021526f..0000000000 --- a/stdio/scanf.c +++ /dev/null @@ -1,37 +0,0 @@ -/* 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 -#include -#include - - -/* 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/snprintf.c b/stdio/snprintf.c deleted file mode 100644 index 9f3e0c4868..0000000000 --- a/stdio/snprintf.c +++ /dev/null @@ -1,39 +0,0 @@ -/* 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 -#include -#include - - -/* Write formatted output into S, according to the format - string FORMAT, writing no more than MAXLEN characters. */ -/* VARARGS3 */ -int -DEFUN(snprintf, (s, maxlen, format), - char *s AND size_t maxlen AND CONST char *format DOTS) -{ - va_list arg; - int done; - - va_start(arg, format); - done = vsnprintf(s, maxlen, format, arg); - va_end(arg); - - return done; -} diff --git a/stdio/sprintf.c b/stdio/sprintf.c deleted file mode 100644 index ce3a970074..0000000000 --- a/stdio/sprintf.c +++ /dev/null @@ -1,37 +0,0 @@ -/* 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 -#include -#include - - -/* Write formatted output into S, according to the format string FORMAT. */ -/* VARARGS2 */ -int -DEFUN(sprintf, (s, format), char *s AND CONST char *format DOTS) -{ - va_list arg; - int done; - - va_start(arg, format); - done = vsprintf(s, format, arg); - va_end(arg); - - return done; -} diff --git a/stdio/sscanf.c b/stdio/sscanf.c deleted file mode 100644 index 33bc203577..0000000000 --- a/stdio/sscanf.c +++ /dev/null @@ -1,37 +0,0 @@ -/* 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 -#include -#include - - -/* 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/tempnam.c b/stdio/tempnam.c deleted file mode 100644 index 14988a8656..0000000000 --- a/stdio/tempnam.c +++ /dev/null @@ -1,50 +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 -#include -#include -#include -#include -#include - - -/* Generate a unique temporary filename using up to five characters of PFX - if it is not NULL. The directory to put this file in is searched for - as follows: First the environment variable "TMPDIR" is checked. - If it contains the name of a writable directory, that directory is used. - If not and if DIR is not NULL, that value is checked. If that fails, - P_tmpdir is tried and finally "/tmp". The storage for the filename - is allocated by `malloc'. */ -char * -DEFUN(tempnam, (dir, pfx), CONST char *dir AND CONST char *pfx) -{ - size_t len; - register char *s; - register char *t = __stdio_gen_tempname(dir, pfx, 1, &len, (FILE **) NULL); - - if (t == NULL) - return NULL; - - s = (char *) malloc(len); - if (s == NULL) - return NULL; - - (void) memcpy(s, t, len); - return s; -} diff --git a/stdio/temptest.c b/stdio/temptest.c deleted file mode 100644 index 374719896a..0000000000 --- a/stdio/temptest.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include -#include - -char *files[500]; - -int -main () -{ - char *fn; - FILE *fp; - int i; - - for (i = 0; i < 500; i++) { - fn = __stdio_gen_tempname((CONST char *) NULL, - "file", 0, (size_t *) NULL, (FILE **) NULL); - if (fn == NULL) { - printf ("__stdio_gen_tempname failed\n"); - exit (1); - } - files[i] = strdup (fn); - printf ("file: %s\n", fn); - fp = fopen (fn, "w"); - fclose (fp); - } - - for (i = 0; i < 500; i++) - remove (files[i]); - - exit (0); -} diff --git a/stdio/test-fseek.c b/stdio/test-fseek.c deleted file mode 100644 index d56c669a54..0000000000 --- a/stdio/test-fseek.c +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include - -#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/test-fwrite.c b/stdio/test-fwrite.c deleted file mode 100644 index cc6cdf038e..0000000000 --- a/stdio/test-fwrite.c +++ /dev/null @@ -1,68 +0,0 @@ -#include -#include - -int -main () -{ - FILE *f = tmpfile (); - char obuf[99999], ibuf[sizeof obuf]; - char *line; - size_t linesz; - - if (! f) - { - perror ("tmpfile"); - return 1; - } - - if (fputs ("line\n", f) == EOF) - { - perror ("fputs"); - return 1; - } - - memset (obuf, 'z', sizeof obuf); - memset (ibuf, 'y', sizeof ibuf); - - if (fwrite (obuf, sizeof obuf, 1, f) != 1) - { - perror ("fwrite"); - return 1; - } - - rewind (f); - - line = NULL; - linesz = 0; - if (getline (&line, &linesz, f) != 5) - { - perror ("getline"); - return 1; - } - if (strcmp (line, "line\n")) - { - puts ("Lines differ. Test FAILED!"); - return 1; - } - - if (fread (ibuf, sizeof ibuf, 1, f) != 1) - { - perror ("fread"); - return 1; - } - - if (memcmp (ibuf, obuf, sizeof ibuf)) - { - puts ("Buffers differ. Test FAILED!"); - return 1; - } - - asprintf (&line, "\ -GDB is free software and you are welcome to distribute copies of it\n\ - under certain conditions; type \"show copying\" to see the conditions.\n\ -There is absolutely no warranty for GDB; type \"show warranty\" for details.\n\ -"); - - puts ("Test succeeded."); - return 0; -} diff --git a/stdio/test-popen.c b/stdio/test-popen.c deleted file mode 100644 index b452f3f63c..0000000000 --- a/stdio/test-popen.c +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include -#include - -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/test_rdwr.c b/stdio/test_rdwr.c deleted file mode 100644 index f987f16cd4..0000000000 --- a/stdio/test_rdwr.c +++ /dev/null @@ -1,130 +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 -#include -#include -#include -#include - - -int -DEFUN(main, (argc, argv), int argc AND char **argv) -{ - static CONST char hello[] = "Hello, world.\n"; - static CONST char replace[] = "Hewwo, world.\n"; - static CONST size_t replace_from = 2, replace_to = 4; - char filename[FILENAME_MAX]; - char *name = strrchr(*argv, '/'); - char buf[BUFSIZ]; - FILE *f; - int lose = 0; - - if (name != NULL) - ++name; - else - name = *argv; - - (void) sprintf(filename, "/tmp/%s.test", name); - - f = fopen(filename, "w+"); - if (f == NULL) - { - perror(filename); - exit(1); - } - - (void) fputs(hello, f); - rewind(f); - (void) fgets(buf, sizeof(buf), f); - rewind(f); - (void) fputs(buf, f); - rewind(f); - { - register size_t i; - for (i = 0; i < replace_from; ++i) - { - int c = getc(f); - if (c == EOF) - { - printf("EOF at %u.\n", i); - lose = 1; - break; - } - else if (c != hello[i]) - { - printf("Got '%c' instead of '%c' at %u.\n", - (unsigned char) c, hello[i], i); - lose = 1; - break; - } - } - } - - { - long int where = ftell(f); - if (where == replace_from) - { - register size_t i; - for (i = replace_from; i < replace_to; ++i) - if (putc(replace[i], f) == EOF) - { - printf("putc('%c') got %s at %u.\n", - replace[i], strerror(errno), i); - lose = 1; - break; - } - } - else if (where == -1L) - { - printf("ftell got %s (should be at %u).\n", - strerror(errno), replace_from); - lose = 1; - } - else - { - printf("ftell returns %u; should be %u.\n", where, replace_from); - lose = 1; - } - } - - if (!lose) - { - rewind(f); - if (fgets(buf, sizeof(buf), f) == NULL) - { - printf("fgets got %s.\n", strerror(errno)); - lose = 1; - } - else if (strcmp(buf, replace)) - { - printf("Read \"%s\" instead of \"%s\".\n", buf, replace); - lose = 1; - } - } - - if (lose) - printf("Test FAILED! Losing file is \"%s\".\n", filename); - else - { - (void) remove(filename); - puts("Test succeeded."); - } - - exit(lose ? EXIT_FAILURE : EXIT_SUCCESS); -} diff --git a/stdio/tmpfile.c b/stdio/tmpfile.c deleted file mode 100644 index dfe11ada50..0000000000 --- a/stdio/tmpfile.c +++ /dev/null @@ -1,43 +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 -#include - - -/* This returns a new stream opened on a temporary file (generated - by tmpnam) The file is opened with mode "w+b" (binary read/write). - If we couldn't generate a unique filename or the file couldn't - be opened, NULL is returned. */ -FILE * -DEFUN_VOID(tmpfile) -{ - char *filename; - FILE *f; - - filename = __stdio_gen_tempname ((char *) NULL, "tmpf", 0, - (size_t *) NULL, &f); - if (filename == NULL) - return NULL; - - /* Note that this relies on the Unix semantics that - a file is not really removed until it is closed. */ - (void) remove (filename); - - return f; -} diff --git a/stdio/tmpnam.c b/stdio/tmpnam.c deleted file mode 100644 index 88dd0a4ca5..0000000000 --- a/stdio/tmpnam.c +++ /dev/null @@ -1,42 +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 -#include -#include -#include - - -/* Generate a unique filename in P_tmpdir. */ -char * -DEFUN(tmpnam, (s), register char *s) -{ - register char *t = __stdio_gen_tempname((CONST char *) NULL, - (CONST char *) NULL, 0, - (size_t *) NULL, (FILE **) NULL); - - if (t == NULL) - return NULL; - - if (s != NULL) - (void) strcpy(s, t); - else - s = t; - - return s; -} diff --git a/stdio/tst-fileno.c b/stdio/tst-fileno.c deleted file mode 100644 index 81945f7b44..0000000000 --- a/stdio/tst-fileno.c +++ /dev/null @@ -1,37 +0,0 @@ -/* 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 -#include -#include - -static int -DEFUN(check, (name, stream, fd), CONST char *name AND FILE *stream AND int fd) -{ - int sfd = fileno (stream); - printf ("(fileno (%s) = %d) %c= %d\n", name, sfd, sfd == fd ? '=' : '!', fd); - return sfd != fd; -} - -int -DEFUN_VOID(main) -{ - exit (check ("stdin", stdin, STDIN_FILENO) || - check ("stdout", stdout, STDOUT_FILENO) || - check ("stderr", stderr, STDERR_FILENO)); -} diff --git a/stdio/tst-printf.c b/stdio/tst-printf.c deleted file mode 100644 index c177da18b2..0000000000 --- a/stdio/tst-printf.c +++ /dev/null @@ -1,298 +0,0 @@ -/* 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 -#ifdef BSD -#include -#define EXIT_SUCCESS 0 -#else -#include -#include -#include -#endif - -#include - - -void -DEFUN(fmtchk, (fmt), CONST char *fmt) -{ - (void) fputs(fmt, stdout); - (void) printf(":\t`"); - (void) printf(fmt, 0x12); - (void) printf("'\n"); -} - -void -DEFUN(fmtst1chk, (fmt), CONST char *fmt) -{ - (void) fputs(fmt, stdout); - (void) printf(":\t`"); - (void) printf(fmt, 4, 0x12); - (void) printf("'\n"); -} - -void -DEFUN(fmtst2chk, (fmt), CONST char *fmt) -{ - (void) fputs(fmt, stdout); - (void) printf(":\t`"); - (void) printf(fmt, 4, 4, 0x12); - (void) printf("'\n"); -} - -/* This page is covered by the following copyright: */ - -/* (C) Copyright C E Chew - * - * Feel free to copy, use and distribute this software provided: - * - * 1. you do not pretend that you wrote it - * 2. you leave this copyright notice intact. - */ - -/* - * Extracted from exercise.c for glibc-1.05 bug report by Bruce Evans. - */ - -#define DEC -123 -#define INT 255 -#define UNS (~0) - -/* Formatted Output Test - * - * This exercises the output formatting code. - */ - -void -DEFUN_VOID(fp_test) -{ - int i, j, k, l; - char buf[7]; - char *prefix = buf; - char tp[20]; - - puts("\nFormatted output test"); - printf("prefix 6d 6o 6x 6X 6u\n"); - strcpy(prefix, "%"); - for (i = 0; i < 2; i++) { - for (j = 0; j < 2; j++) { - for (k = 0; k < 2; k++) { - for (l = 0; l < 2; l++) { - strcpy(prefix, "%"); - if (i == 0) strcat(prefix, "-"); - if (j == 0) strcat(prefix, "+"); - if (k == 0) strcat(prefix, "#"); - if (l == 0) strcat(prefix, "0"); - printf("%5s |", prefix); - strcpy(tp, prefix); - strcat(tp, "6d |"); - printf(tp, DEC); - strcpy(tp, prefix); - strcat(tp, "6o |"); - printf(tp, INT); - strcpy(tp, prefix); - strcat(tp, "6x |"); - printf(tp, INT); - strcpy(tp, prefix); - strcat(tp, "6X |"); - printf(tp, INT); - strcpy(tp, prefix); - strcat(tp, "6u |"); - printf(tp, UNS); - printf("\n"); - } - } - } - } - printf("%10s\n", (char *) NULL); - printf("%-10s\n", (char *) NULL); -} - -int -DEFUN_VOID(main) -{ - static char shortstr[] = "Hi, Z."; - static char longstr[] = "Good morning, Doctor Chandra. This is Hal. \ -I am ready for my first lesson today."; - - fmtchk("%.4x"); - fmtchk("%04x"); - fmtchk("%4.4x"); - fmtchk("%04.4x"); - fmtchk("%4.3x"); - fmtchk("%04.3x"); - - fmtst1chk("%.*x"); - fmtst1chk("%0*x"); - fmtst2chk("%*.*x"); - fmtst2chk("%0*.*x"); - -#ifndef BSD - printf("bad format:\t\"%z\"\n"); - printf("nil pointer (padded):\t\"%10p\"\n", (PTR) NULL); -#endif - - printf("decimal negative:\t\"%d\"\n", -2345); - printf("octal negative:\t\"%o\"\n", -2345); - printf("hex negative:\t\"%x\"\n", -2345); - printf("long decimal number:\t\"%ld\"\n", -123456L); - printf("long octal negative:\t\"%lo\"\n", -2345L); - printf("long unsigned decimal number:\t\"%lu\"\n", -123456L); - printf("zero-padded LDN:\t\"%010ld\"\n", -123456L); - printf("left-adjusted ZLDN:\t\"%-010ld\"\n", -123456); - printf("space-padded LDN:\t\"%10ld\"\n", -123456L); - printf("left-adjusted SLDN:\t\"%-10ld\"\n", -123456L); - - printf("zero-padded string:\t\"%010s\"\n", shortstr); - printf("left-adjusted Z string:\t\"%-010s\"\n", shortstr); - printf("space-padded string:\t\"%10s\"\n", shortstr); - printf("left-adjusted S string:\t\"%-10s\"\n", shortstr); - printf("null string:\t\"%s\"\n", (char *)NULL); - printf("limited string:\t\"%.22s\"\n", longstr); - - printf("e-style >= 1:\t\"%e\"\n", 12.34); - printf("e-style >= .1:\t\"%e\"\n", 0.1234); - printf("e-style < .1:\t\"%e\"\n", 0.001234); - printf("e-style big:\t\"%.60e\"\n", 1e20); - printf ("e-style == .1:\t\"%e\"\n", 0.1); - printf("f-style >= 1:\t\"%f\"\n", 12.34); - printf("f-style >= .1:\t\"%f\"\n", 0.1234); - printf("f-style < .1:\t\"%f\"\n", 0.001234); - printf("g-style >= 1:\t\"%g\"\n", 12.34); - printf("g-style >= .1:\t\"%g\"\n", 0.1234); - printf("g-style < .1:\t\"%g\"\n", 0.001234); - printf("g-style big:\t\"%.60g\"\n", 1e20); - - printf (" %6.5f\n", .099999999860301614); - printf (" %6.5f\n", .1); - printf ("x%5.4fx\n", .5); - - printf ("%#03x\n", 1); - - { - double d = FLT_MIN; - int niter = 17; - - while (niter-- != 0) - printf ("%.17e\n", d / 2); - fflush (stdout); - } - - printf ("%15.5e\n", 4.9406564584124654e-324); - -#define FORMAT "|%12.4f|%12.4e|%12.4g|\n" - printf (FORMAT, 0.0, 0.0, 0.0); - printf (FORMAT, 1.0, 1.0, 1.0); - printf (FORMAT, -1.0, -1.0, -1.0); - printf (FORMAT, 100.0, 100.0, 100.0); - printf (FORMAT, 1000.0, 1000.0, 1000.0); - printf (FORMAT, 10000.0, 10000.0, 10000.0); - printf (FORMAT, 12345.0, 12345.0, 12345.0); - printf (FORMAT, 100000.0, 100000.0, 100000.0); - printf (FORMAT, 123456.0, 123456.0, 123456.0); -#undef FORMAT - - { - char buf[20]; - printf ("snprintf (\"%%30s\", \"foo\") == %d, \"%.*s\"\n", - snprintf (buf, sizeof (buf), "%30s", "foo"), sizeof (buf), buf); - } - - fp_test (); - - printf ("%e should be 1.234568e+06\n", 1234567.8); - printf ("%f should be 1234567.800000\n", 1234567.8); - printf ("%g should be 1.23457e+06\n", 1234567.8); - printf ("%g should be 123.456\n", 123.456); - printf ("%g should be 1e+06\n", 1000000.0); - printf ("%g should be 10\n", 10.0); - printf ("%g should be 0.02\n", 0.02); - - { - double x=1.0; - printf("%.17f\n",(1.0/x/10.0+1.0)*x-x); - } - - puts ("--- Should be no further output. ---"); - rfg1 (); - rfg2 (); - - exit(EXIT_SUCCESS); -} - -rfg1 () -{ - char buf[100]; - - sprintf (buf, "%5.s", "xyz"); - if (strcmp (buf, " ") != 0) - printf ("got: '%s', expected: '%s'\n", buf, " "); - sprintf (buf, "%5.f", 33.3); - if (strcmp (buf, " 33") != 0) - printf ("got: '%s', expected: '%s'\n", buf, " 33"); - sprintf (buf, "%8.e", 33.3e7); - if (strcmp (buf, " 3e+08") != 0) - printf ("got: '%s', expected: '%s'\n", buf, " 3e+08"); - sprintf (buf, "%8.E", 33.3e7); - if (strcmp (buf, " 3E+08") != 0) - printf ("got: '%s', expected: '%s'\n", buf, " 3E+08"); - sprintf (buf, "%.g", 33.3); - if (strcmp (buf, "3e+01") != 0) - printf ("got: '%s', expected: '%s'\n", buf, "3e+01"); - sprintf (buf, "%.G", 33.3); - if (strcmp (buf, "3E+01") != 0) - printf ("got: '%s', expected: '%s'\n", buf, "3E+01"); - return 0; -} - -rfg2 () -{ - int prec; - char buf[100]; - - prec = 0; - sprintf (buf, "%.*g", prec, 3.3); - if (strcmp (buf, "3") != 0) - printf ("got: '%s', expected: '%s'\n", buf, "3"); - prec = 0; - sprintf (buf, "%.*G", prec, 3.3); - if (strcmp (buf, "3") != 0) - printf ("got: '%s', expected: '%s'\n", buf, "3"); - prec = 0; - sprintf (buf, "%7.*G", prec, 3.33); - if (strcmp (buf, " 3") != 0) - printf ("got: '%s', expected: '%s'\n", buf, " 3"); - prec = 3; - sprintf (buf, "%04.*o", prec, 33); - if (strcmp (buf, " 041") != 0) - printf ("got: '%s', expected: '%s'\n", buf, " 041"); - prec = 7; - sprintf (buf, "%09.*u", prec, 33); - if (strcmp (buf, " 0000033") != 0) - printf ("got: '%s', expected: '%s'\n", buf, " 0000033"); - prec = 3; - sprintf (buf, "%04.*x", prec, 33); - if (strcmp (buf, " 021") != 0) - printf ("got: '%s', expected: '%s'\n", buf, " 021"); - prec = 3; - sprintf (buf, "%04.*X", prec, 33); - if (strcmp (buf, " 021") != 0) - printf ("got: '%s', expected: '%s'\n", buf, " 021"); - return 0; -} diff --git a/stdio/tstgetln.c b/stdio/tstgetln.c deleted file mode 100644 index ea8ea817da..0000000000 --- a/stdio/tstgetln.c +++ /dev/null @@ -1,46 +0,0 @@ -/* 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 -#include - -int -DEFUN_VOID(main) -{ - char *buf = NULL; - size_t size = 0; - ssize_t len; - - while ((len = getline (&buf, &size, stdin)) != -1) - { - printf ("bufsize %u; read %d: ", size, len); - if (fwrite (buf, len, 1, stdout) != 1) - { - perror ("fwrite"); - return 1; - } - } - - if (ferror (stdin)) - { - perror ("getline"); - return 1; - } - - return 0; -} diff --git a/stdio/tstgetln.input b/stdio/tstgetln.input deleted file mode 100644 index d04ed5bf78..0000000000 --- a/stdio/tstgetln.input +++ /dev/null @@ -1,3 +0,0 @@ -xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy -z diff --git a/stdio/tstscanf.c b/stdio/tstscanf.c deleted file mode 100644 index 53d4b0ac47..0000000000 --- a/stdio/tstscanf.c +++ /dev/null @@ -1,100 +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 -#ifdef BSD -#include -#else -#include -#endif -#include -#include - - -int -DEFUN(main, (argc, argv), int argc AND char **argv) -{ - char buf[BUFSIZ]; - FILE *in = stdin, *out = stdout; - - if (argc == 2 && !strcmp (argv[1], "-opipe")) - { - out = popen ("/bin/cat", "w"); - if (out == NULL) - { - perror ("popen: /bin/cat"); - exit (EXIT_FAILURE); - } - } - else if (argc == 3 && !strcmp (argv[1], "-ipipe")) - { - sprintf (buf, "/bin/cat %s", argv[2]); - in = popen (buf, "r"); - } - - { - char name[50]; - fprintf (out, - "sscanf (\"thompson\", \"%%s\", name) == %d, name == \"%s\"\n", - sscanf ("thompson", "%s", name), - name); - } - - fputs ("Testing scanf (vfscanf)\n", out); - - fputs ("Test 1:\n", out); - { - int n, i; - float x; - char name[50]; - n = fscanf (in, "%d%f%s", &i, &x, name); - fprintf (out, "n = %d, i = %d, x = %f, name = \"%.50s\"\n", - n, i, x, name); - } - fprintf (out, "Residual: \"%s\"\n", fgets (buf, sizeof (buf), in)); - fputs ("Test 2:\n", out); - { - int i; - float x; - char name[50]; - (void) fscanf (in, "%2d%f%*d %[0123456789]", &i, &x, name); - fprintf (out, "i = %d, x = %f, name = \"%.50s\"\n", i, x, name); - } - fprintf (out, "Residual: \"%s\"\n", fgets (buf, sizeof (buf), in)); - fputs ("Test 3:\n", out); - { - float quant; - char units[21], item[21]; - while (!feof (in) && !ferror (in)) - { - int count; - quant = 0.0; - units[0] = item[0] = '\0'; - count = fscanf (in, "%f%20s of %20s", &quant, units, item); - (void) fscanf (in, "%*[^\n]"); - fprintf (out, "count = %d, quant = %f, item = %.21s, units = %.21s\n", - count, quant, item, units); - } - } - fprintf (out, "Residual: \"%s\"\n", fgets (buf, sizeof (buf), in)); - - if (out != stdout) - pclose (out); - - exit(EXIT_SUCCESS); -} diff --git a/stdio/tstscanf.input b/stdio/tstscanf.input deleted file mode 100644 index 26158652dd..0000000000 --- a/stdio/tstscanf.input +++ /dev/null @@ -1,7 +0,0 @@ -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/vasprintf.c b/stdio/vasprintf.c deleted file mode 100644 index d2ad6b1da6..0000000000 --- a/stdio/vasprintf.c +++ /dev/null @@ -1,86 +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 -#include -#include -#include -#include -#include - - - -/* Enlarge STREAM's buffer. */ -static void -DEFUN(enlarge_buffer, (stream, c), - register FILE *stream AND int c) -{ - ptrdiff_t bufp_offset = stream->__bufp - stream->__buffer; - char *newbuf; - - stream->__bufsize += 100; - newbuf = (char *) realloc ((PTR) stream->__buffer, stream->__bufsize); - if (newbuf == NULL) - { - free ((PTR) stream->__buffer); - stream->__buffer = stream->__bufp - = stream->__put_limit = stream->__get_limit = NULL; - stream->__error = 1; - } - else - { - stream->__buffer = newbuf; - stream->__bufp = stream->__buffer + bufp_offset; - stream->__get_limit = stream->__put_limit; - stream->__put_limit = stream->__buffer + stream->__bufsize; - if (c != EOF) - *stream->__bufp++ = (unsigned char) c; - } -} - -/* Write formatted output from FORMAT to a string which is - allocated with malloc and stored in *STRING_PTR. */ -int -DEFUN(vasprintf, (string_ptr, format, args), - char **string_ptr AND CONST char *format AND va_list args) -{ - FILE f; - int done; - - memset ((PTR) &f, 0, sizeof (f)); - f.__magic = _IOMAGIC; - f.__bufsize = 100; - f.__buffer = (char *) malloc (f.__bufsize); - if (f.__buffer == NULL) - return -1; - f.__bufp = f.__buffer; - f.__put_limit = f.__buffer + f.__bufsize; - f.__mode.__write = 1; - f.__room_funcs.__output = enlarge_buffer; - f.__seen = 1; - - done = vfprintf (&f, format, args); - if (done < 0) - return done; - - *string_ptr = realloc (f.__buffer, (f.__bufp - f.__buffer) + 1); - if (*string_ptr == NULL) - *string_ptr = f.__buffer; - (*string_ptr)[f.__bufp - f.__buffer] = '\0'; - return done; -} diff --git a/stdio/vdprintf.c b/stdio/vdprintf.c deleted file mode 100644 index 9df4e537bc..0000000000 --- a/stdio/vdprintf.c +++ /dev/null @@ -1,51 +0,0 @@ -/* 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 -#include -#include -#include -#include -#include - - -/* Write formatted output to file descriptor D according to the format string - FORMAT, using the argument list in ARG. */ -int -DEFUN(vdprintf, (d, format, arg), - int d AND CONST char *format AND va_list arg) -{ - int done; - FILE f; - - /* Create an unbuffered stream talking to D on the stack. */ - memset ((PTR) &f, 0, sizeof(f)); - f.__magic = _IOMAGIC; - f.__mode.__write = 1; - f.__cookie = (PTR) (long int) d; /* Casting to long quiets GCC on Alpha. */ - f.__room_funcs = __default_room_functions; - f.__io_funcs = __default_io_functions; - f.__seen = 1; - f.__userbuf = 1; - - /* vfprintf will use a buffer on the stack for the life of the call, - and flush it when finished. */ - done = vfprintf (&f, format, arg); - - return done; -} diff --git a/stdio/vfprintf.c b/stdio/vfprintf.c deleted file mode 100644 index 63a5148463..0000000000 --- a/stdio/vfprintf.c +++ /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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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 -#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 -#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; -} - -/* Group the digits according to the grouping rules of the current locale. - The interpretation of GROUPING is as in `struct lconv' from . */ - -static char * -group_number (char *w, char *workend, const char *grouping, - wchar_t thousands_sep) -{ - int len; - char *src, *s; - - /* We treat all negative values like CHAR_MAX. */ - - if (*grouping == CHAR_MAX || *grouping < 0) - /* No grouping should be done. */ - return w; - - len = *grouping; - - /* Copy existing string so that nothing gets overwritten. */ - src = (char *) alloca (workend - w); - memcpy (src, w + 1, workend - w); - s = &src[workend - w - 1]; - w = workend; - - /* Process all characters in the string. */ - while (s >= src) - { - *w-- = *s--; - - if (--len == 0 && s >= src) - { - /* A new group begins. */ - *w-- = thousands_sep; - - len = *grouping++; - if (*grouping == '\0') - /* The previous grouping repeats ad infinitum. */ - --grouping; - else if (*grouping == CHAR_MAX || *grouping < 0) - { - /* No further grouping to be done. - Copy the rest of the number. */ - do - *w-- = *s--; - while (s >= src); - break; - } - } - } - return w; -} - -#ifdef USE_IN_LIBIO -/* Helper "class" for `fprintf to unbuffered': creates a temporary buffer. */ -struct helper_file - { - struct _IO_FILE_plus _f; - _IO_FILE *_put_stream; - }; - -static int -_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 index a778346287..0000000000 --- a/stdio/vfscanf.c +++ /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 -#include "../locale/localeinfo.h" -#include -#include -#include -#include -#include -#include -#include - - -#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 index 97264f475c..0000000000 --- a/stdio/vprintf.c +++ /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 -#include -#undef __OPTIMIZE__ /* Avoid inline `vprintf' function. */ -#include - -#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 index 0d829440e9..0000000000 --- a/stdio/vscanf.c +++ /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 -#include -#include - -#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 index a02c259131..0000000000 --- a/stdio/vsnprintf.c +++ /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 -#include -#include -#include - - -/* - * 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 index 82be90f1fa..0000000000 --- a/stdio/vsprintf.c +++ /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 -#include -#include -#include -#include -#include - - -/* 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 index 6f027d5065..0000000000 --- a/stdio/vsscanf.c +++ /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 -#include -#include -#include -#include - -#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 index ec648f5566..0000000000 --- a/stdio/xbug.c +++ /dev/null @@ -1,63 +0,0 @@ -#include - -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/sysdeps/generic/Makefile b/sysdeps/generic/Makefile index b80b073d0c..1315a26b95 100644 --- a/sysdeps/generic/Makefile +++ b/sysdeps/generic/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. +# Copyright (C) 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 @@ -42,7 +42,7 @@ common-generated := $(common-generated) bytesex.h det_endian endif -ifeq ($(subdir),stdio) +ifeq ($(subdir),stdio-common) ifeq "$(filter $(objpfx)siglist.c,$(before-compile))" "" before-compile := $(before-compile) $(objpfx)siglist.c -- cgit v1.2.3