diff options
author | Jakub Jelinek <jakub@redhat.com> | 2007-07-12 18:26:36 +0000 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2007-07-12 18:26:36 +0000 |
commit | 0ecb606cb6cf65de1d9fc8a919bceb4be476c602 (patch) | |
tree | 2ea1f8305970753e4a657acb2ccc15ca3eec8e2c /stdio-common | |
parent | 7d58530341304d403a6626d7f7a1913165fe2f32 (diff) | |
download | glibc-0ecb606cb6cf65de1d9fc8a919bceb4be476c602.tar glibc-0ecb606cb6cf65de1d9fc8a919bceb4be476c602.tar.gz glibc-0ecb606cb6cf65de1d9fc8a919bceb4be476c602.tar.bz2 glibc-0ecb606cb6cf65de1d9fc8a919bceb4be476c602.zip |
2.5-18.1
Diffstat (limited to 'stdio-common')
52 files changed, 1835 insertions, 265 deletions
diff --git a/stdio-common/Makefile b/stdio-common/Makefile index 3a66f1d021..7bd368bdca 100644 --- a/stdio-common/Makefile +++ b/stdio-common/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1991-2002, 2003, 2004 Free Software Foundation, Inc. +# Copyright (C) 1991-2006, 2007 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -21,7 +21,7 @@ # subdir := stdio-common -headers := printf.h stdio_ext.h +headers := stdio_ext.h printf.h bits/printf-ldbl.h routines := \ ctermid cuserid \ @@ -33,14 +33,14 @@ routines := \ perror psignal \ tmpfile tmpfile64 tmpnam tmpnam_r tempnam tempname \ getline getw putw \ - remove rename \ + remove rename renameat \ flockfile ftrylockfile funlockfile install-others = $(inst_includedir)/bits/stdio_lim.h include ../Makeconfig -aux := errlist siglist printf-parsemb printf-parsewc +aux := errlist siglist printf-parsemb printf-parsewc fxprintf distribute := _itoa.h _itowa.h _i18n_number.h \ printf-parse.h stdio_lim.h.in tst-unbputc.sh tst-printf.sh @@ -53,7 +53,8 @@ tests := tstscanf test_rdwr test-popen tstgetln test-fseek \ scanf11 scanf12 tst-tmpnam tst-cookie tst-obprintf tst-sscanf \ tst-swprintf tst-fseek tst-fmemopen test-vfprintf tst-gets \ tst-perror tst-sprintf tst-rndseek tst-fdopen tst-fphex bug14 bug15 \ - tst-popen tst-unlockedio + tst-popen tst-unlockedio tst-fmemopen2 tst-put-error tst-fgets \ + tst-fwrite bug16 bug17 tst-sprintf2 test-srcs = tst-unbputc tst-printf diff --git a/stdio-common/Versions b/stdio-common/Versions index 1dbce1a124..2f64429346 100644 --- a/stdio-common/Versions +++ b/stdio-common/Versions @@ -37,7 +37,7 @@ libc { tempnam; tmpfile; tmpnam; tmpnam_r; # v* - vfprintf; vfscanf; vprintf; + vfprintf; vfscanf; vprintf; } GLIBC_2.1 { # p* @@ -46,6 +46,9 @@ libc { # t* tmpfile; tmpfile64; } + GLIBC_2.4 { + renameat; + } GLIBC_PRIVATE { # global variables _itoa_lower_digits; diff --git a/stdio-common/_itoa.c b/stdio-common/_itoa.c index f61b23fceb..285fde2ab9 100644 --- a/stdio-common/_itoa.c +++ b/stdio-common/_itoa.c @@ -1,5 +1,5 @@ /* Internal function for converting integers to ASCII. - Copyright (C) 1994, 1995, 1996, 1999, 2000, 2002, 2003, 2004 + Copyright (C) 1994, 1995, 1996, 1999, 2000, 2002, 2003, 2004, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Torbjorn Granlund <tege@matematik.su.se> @@ -269,6 +269,7 @@ _itoa (value, buflim, base, upper_case) default: { + char *bufend = buflim; #if BITS_PER_MP_LIMB == 64 mp_limb_t base_multiplier = brec->base_multiplier; if (brec->flag) @@ -454,6 +455,8 @@ _itoa (value, buflim, base, upper_case) } while (n != 0); #endif + if (buflim == bufend) + *--buflim = '0'; } break; } diff --git a/stdio-common/asprintf.c b/stdio-common/asprintf.c index 2c466d28d5..66e766ebfb 100644 --- a/stdio-common/asprintf.c +++ b/stdio-common/asprintf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1995, 1997, 1998, 2002, 2004 +/* Copyright (C) 1991, 1995, 1997, 1998, 2002, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -20,7 +20,7 @@ #include <stdarg.h> #include <stdio.h> -#include <libio/libioP.h> +#include <libioP.h> #define vasprintf(s, f, a) _IO_vasprintf (s, f, a) #undef __asprintf @@ -28,7 +28,7 @@ allocated with malloc and stored in *STRING_PTR. */ /* VARARGS2 */ int -__asprintf (char **string_ptr, const char *format, ...) +___asprintf (char **string_ptr, const char *format, ...) { va_list arg; int done; @@ -39,5 +39,7 @@ __asprintf (char **string_ptr, const char *format, ...) return done; } -INTDEF(__asprintf) -weak_alias (__asprintf, asprintf) +INTDEF2(___asprintf, __asprintf) + +ldbl_strong_alias (___asprintf, __asprintf) +ldbl_weak_alias (___asprintf, asprintf) diff --git a/stdio-common/bits/printf-ldbl.h b/stdio-common/bits/printf-ldbl.h new file mode 100644 index 0000000000..cbdc3f1cbc --- /dev/null +++ b/stdio-common/bits/printf-ldbl.h @@ -0,0 +1,24 @@ +/* -mlong-double-64 compatibility mode for <printf.h> functions. + Copyright (C) 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _PRINTF_H +# error "Never include <bits/printf-ldbl.h> directly; use <printf.h> instead." +#endif + +__LDBL_REDIR_DECL (printf_size) diff --git a/stdio-common/bug16.c b/stdio-common/bug16.c new file mode 100644 index 0000000000..84269f3b6d --- /dev/null +++ b/stdio-common/bug16.c @@ -0,0 +1,43 @@ +#include <stdio.h> +#include <string.h> + +struct +{ + long double val; + const char str[4][7]; +} tests[] = +{ + { 0x0.FFFFp+0L, { "0X1P+0", "0X2P-1", "0X4P-2", "0X8P-3" } }, + { 0x0.FFFFp+1L, { "0X1P+1", "0X2P+0", "0X4P-1", "0X8P-2" } }, + { 0x0.FFFFp+2L, { "0X1P+2", "0X2P+1", "0X4P+0", "0X8P-1" } }, + { 0x0.FFFFp+3L, { "0X1P+3", "0X2P+2", "0X4P+1", "0X8P+0" } } +}; + +static int +do_test (void) +{ + char buf[100]; + int ret = 0; + + for (size_t i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i) + { + snprintf (buf, sizeof (buf), "%.0LA", tests[i].val); + + size_t j; + for (j = 0; j < 4; ++j) + if (strcmp (buf, tests[i].str[j]) == 0) + break; + + if (j == 4) + { + printf ("%zd: got \"%s\", expected \"%s\" or equivalent\n", + i, buf, tests[i].str[0]); + ret = 1; + } + } + + return ret; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/stdio-common/bug17.c b/stdio-common/bug17.c new file mode 100644 index 0000000000..2ef398674b --- /dev/null +++ b/stdio-common/bug17.c @@ -0,0 +1,31 @@ +#include <stdio.h> +#include <string.h> + +static int +do_test (void) +{ + static const char expect[] = "0, 0, 0"; + char buf[100]; + int status = 0; + + static const char fmt1[] = "%0d, %0ld, %0lld"; + snprintf (buf, sizeof (buf), fmt1, 0, 0L, 0LL); + if (strcmp (buf, expect) != 0) + { + printf ("\"%s\": got \"%s\", expected \"%s\"\n", fmt1, buf, expect); + status = 1; + } + + static const char fmt2[] = "%0u, %0lu, %0llu"; + snprintf (buf, sizeof (buf), fmt2, 0u, 0uL, 0uLL); + if (strcmp (buf, expect) != 0) + { + printf ("\"%s\": got \"%s\", expected \"%s\"\n", fmt2, buf, expect); + status = 1; + } + + return status; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/stdio-common/ctermid.c b/stdio-common/ctermid.c new file mode 100644 index 0000000000..e4d94eada2 --- /dev/null +++ b/stdio-common/ctermid.c @@ -0,0 +1,36 @@ +/* Copyright (C) 1991, 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <stdio.h> + + +/* Return the name of the controlling terminal. + If S is not NULL, the name is copied into it (it should be at + least L_ctermid bytes long), otherwise a static buffer is used. */ +char * +ctermid (s) + char *s; +{ + __set_errno (ENOSYS); + return NULL; +} + + +stub_warning (ctermid) +#include <stub-tag.h> diff --git a/stdio-common/cuserid.c b/stdio-common/cuserid.c new file mode 100644 index 0000000000..826972f4de --- /dev/null +++ b/stdio-common/cuserid.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1991, 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <stdio.h> +#include <errno.h> + +/* Return the username of the caller. + If S is not NULL, it points to a buffer of at least L_cuserid bytes + into which the name is copied; otherwise, a static buffer is used. */ +char * +cuserid (s) + char *s; +{ + __set_errno (ENOSYS); + return NULL; +} + + +stub_warning (cuserid) +#include <stub-tag.h> diff --git a/stdio-common/dprintf.c b/stdio-common/dprintf.c index b362e5fa71..6d00e10a63 100644 --- a/stdio-common/dprintf.c +++ b/stdio-common/dprintf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991,95,97,98,2002,2004 Free Software Foundation, Inc. +/* Copyright (C) 1991,95,97,98,2002,2004,2006 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -19,13 +19,13 @@ #include <stdarg.h> #include <stdio.h> -#include <libio/libioP.h> +#include <libioP.h> #define vdprintf(d, f, a) _IO_vdprintf (d, f, a) /* Write formatted output to D, according to the format string FORMAT. */ /* VARARGS2 */ int -dprintf (int d, const char *format, ...) +__dprintf (int d, const char *format, ...) { va_list arg; int done; @@ -36,4 +36,5 @@ dprintf (int d, const char *format, ...) return done; } -libc_hidden_def (dprintf) +ldbl_hidden_def (__dprintf, dprintf) +ldbl_strong_alias (__dprintf, dprintf) diff --git a/stdio-common/errlist.c b/stdio-common/errlist.c new file mode 100644 index 0000000000..6a834fc329 --- /dev/null +++ b/stdio-common/errlist.c @@ -0,0 +1,37 @@ +/* Copyright (C) 1991, 1994, 1997, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <stddef.h> + + +const char *const _sys_errlist[] = + { + "Error 0", /* 0 */ + "Argument out of function's domain", /* 1 = EDOM */ + "Result out of range", /* 2 = ERANGE */ + "Operation not implemented", /* 3 = ENOSYS */ + "Invalid argument", /* 4 = EINVAL */ + "Illegal seek", /* 5 = ESPIPE */ + "Bad file descriptor", /* 6 = EBADF */ + "Cannot allocate memory", /* 7 = ENOMEM */ + "Permission denied", /* 8 = EACCES */ + "Too many open files in system", /* 9 = ENFILE */ + "Too many open files", /* 10 = EMFILE */ + }; + +const int _sys_nerr = sizeof (_sys_errlist) / sizeof (_sys_errlist[0]); diff --git a/stdio-common/flockfile.c b/stdio-common/flockfile.c new file mode 100644 index 0000000000..571930ee54 --- /dev/null +++ b/stdio-common/flockfile.c @@ -0,0 +1,30 @@ +/* Lock I/O stream. Singlethreaded version. + Copyright (C) 1996, 1997, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <stdio.h> + +#undef _IO_flockfile + +void +__flockfile (FILE *stream) +{ + /* Do nothing. Using this version does not do any locking. */ +} +weak_alias (__flockfile, flockfile); +weak_alias (__flockfile, _IO_flockfile) diff --git a/stdio-common/fprintf.c b/stdio-common/fprintf.c index 0b99fc8994..689e80f466 100644 --- a/stdio-common/fprintf.c +++ b/stdio-common/fprintf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991,97,2002,2004 Free Software Foundation, Inc. +/* Copyright (C) 1991, 1997, 2002, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -18,12 +18,13 @@ #include <stdarg.h> #include <stdio.h> +#include <libioP.h> /* Write formatted output to STREAM from the format string FORMAT. */ /* VARARGS2 */ int -fprintf (FILE *stream, const char *format, ...) +__fprintf (FILE *stream, const char *format, ...) { va_list arg; int done; @@ -34,9 +35,10 @@ fprintf (FILE *stream, const char *format, ...) return done; } -libc_hidden_def (fprintf) +ldbl_hidden_def (__fprintf, fprintf) +ldbl_strong_alias (__fprintf, fprintf) /* We define the function with the real name here. But deep down in libio the original function _IO_fprintf is also needed. So make an alias. */ -weak_alias (fprintf, _IO_fprintf) +ldbl_weak_alias (__fprintf, _IO_fprintf) diff --git a/stdio-common/fscanf.c b/stdio-common/fscanf.c index 58a66eaf30..a6b60162cf 100644 --- a/stdio-common/fscanf.c +++ b/stdio-common/fscanf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1991, 1997, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -16,13 +16,14 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include <libioP.h> #include <stdarg.h> #include <stdio.h> /* Read formatted input from STREAM according to the format string FORMAT. */ /* VARARGS2 */ int -fscanf (FILE *stream, const char *format, ...) +__fscanf (FILE *stream, const char *format, ...) { va_list arg; int done; @@ -33,3 +34,4 @@ fscanf (FILE *stream, const char *format, ...) return done; } +ldbl_strong_alias (__fscanf, fscanf) diff --git a/stdio-common/ftrylockfile.c b/stdio-common/ftrylockfile.c new file mode 100644 index 0000000000..7bd3e9b53b --- /dev/null +++ b/stdio-common/ftrylockfile.c @@ -0,0 +1,31 @@ +/* Try locking I/O stream. Singlethreaded version. + Copyright (C) 1996, 1997, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <stdio.h> + +#undef _IO_ftrylockfile + +int +__ftrylockfile (FILE *stream) +{ + /* Do nothing. Using this version does not do any locking. */ + return 1; +} +weak_alias (__ftrylockfile, ftrylockfile); +weak_alias (__ftrylockfile, _IO_ftrylockfile) diff --git a/stdio-common/funlockfile.c b/stdio-common/funlockfile.c new file mode 100644 index 0000000000..902d29478d --- /dev/null +++ b/stdio-common/funlockfile.c @@ -0,0 +1,30 @@ +/* Unlock I/O stream. Singlethreaded version. + Copyright (C) 1996, 1997, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <stdio.h> + +#undef _IO_funlockfile + +void +__funlockfile (FILE *stream) +{ + /* Do nothing. Using this version does not do any locking. */ +} +weak_alias (__funlockfile, _IO_funlockfile) +weak_alias (__funlockfile, funlockfile); diff --git a/stdio-common/fxprintf.c b/stdio-common/fxprintf.c new file mode 100644 index 0000000000..f6ba0ca558 --- /dev/null +++ b/stdio-common/fxprintf.c @@ -0,0 +1,56 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@gnu.org>. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <ctype.h> +#include <stdarg.h> +#include <stdio.h> +#include <wchar.h> +#include <string.h> +#include <libioP.h> + + +int +__fxprintf (FILE *fp, const char *fmt, ...) +{ + if (fp == NULL) + fp = stderr; + + va_list ap; + va_start (ap, fmt); + + int res; + if (_IO_fwide (fp, 0) > 0) + { + size_t len = strlen (fmt) + 1; + wchar_t wfmt[len]; + for (size_t i = 0; i < len; ++i) + { + assert (isascii (fmt[i])); + wfmt[i] = fmt[i]; + } + res = __vfwprintf (fp, wfmt, ap); + } + else + res = INTUSE(_IO_vfprintf) (fp, fmt, ap); + + va_end (ap); + + return res; +} diff --git a/stdio-common/perror.c b/stdio-common/perror.c index f0751375b5..3ee61520f4 100644 --- a/stdio-common/perror.c +++ b/stdio-common/perror.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-1993,1997,1998,2000-2004 Free Software Foundation, Inc. +/* Copyright (C) 1991-1993,1997,1998,2000-2005 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -37,10 +37,7 @@ perror_internal (FILE *fp, const char *s, int errnum) errstring = __strerror_r (errnum, buf, sizeof buf); - if (_IO_fwide (fp, 0) > 0) - (void) __fwprintf (fp, L"%s%s%s\n", s, colon, errstring); - else - (void) fprintf (fp, "%s%s%s\n", s, colon, errstring); + (void) __fxprintf (fp, "%s%s%s\n", s, colon, errstring); } diff --git a/stdio-common/printf-parsemb.c b/stdio-common/printf-parsemb.c index c55b97060c..2f21fc6365 100644 --- a/stdio-common/printf-parsemb.c +++ b/stdio-common/printf-parsemb.c @@ -1,5 +1,5 @@ /* Helper functions for parsing printf format strings. - Copyright (C) 1995-2000, 2002, 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 1995-2000,2002,2003,2004,2006 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 @@ -64,7 +64,8 @@ __find_specmb (const UCHAR_T *format, mbstate_t *ps) /* Remove any hints of a wrong encoding. */ ps->__count = 0; - if (! isascii (*format) && (len = __mbrlen (format, MB_CUR_MAX, ps)) > 0) + if (! isascii (*format) + && (len = __mbrlen ((const CHAR_T *) format, MB_CUR_MAX, ps)) > 0) format += len; else ++format; diff --git a/stdio-common/printf-prs.c b/stdio-common/printf-prs.c index f3b27d6712..015b01f1ed 100644 --- a/stdio-common/printf-prs.c +++ b/stdio-common/printf-prs.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1992, 1995, 1996, 1999, 2000, 2002, 2003, 2004 +/* Copyright (C) 1991, 1992, 1995, 1996, 1999, 2000, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -67,15 +67,16 @@ parse_printf_format (fmt, n, argtypes) size_t max_ref_arg; /* Highest index used in a positional arg. */ struct printf_spec spec; mbstate_t mbstate; + const unsigned char *f = (const unsigned char *) fmt; nargs = 0; max_ref_arg = 0; /* Search for format specifications. */ - for (fmt = __find_specmb (fmt, &mbstate); *fmt != '\0'; fmt = spec.next_fmt) + for (f = __find_specmb (f, &mbstate); *f != '\0'; f = spec.next_fmt) { /* Parse this spec. */ - nargs += __parse_one_specmb (fmt, nargs, &spec, &max_ref_arg, &mbstate); + nargs += __parse_one_specmb (f, nargs, &spec, &max_ref_arg, &mbstate); /* If the width is determined by an argument this is an int. */ if (spec.width_arg != -1 && (size_t) spec.width_arg < n) diff --git a/stdio-common/printf.c b/stdio-common/printf.c index e28c5837e5..4c8f3a2a0c 100644 --- a/stdio-common/printf.c +++ b/stdio-common/printf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1995, 1996, 1997, 2001, 2004 +/* Copyright (C) 1991, 1995, 1996, 1997, 2001, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -17,6 +17,7 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include <libioP.h> #include <stdarg.h> #include <stdio.h> @@ -25,7 +26,7 @@ /* Write formatted output to stdout from the format string FORMAT. */ /* VARARGS1 */ int -printf (const char *format, ...) +__printf (const char *format, ...) { va_list arg; int done; @@ -38,5 +39,6 @@ printf (const char *format, ...) } #undef _IO_printf +ldbl_strong_alias (__printf, printf); /* This is for libg++. */ -strong_alias (printf, _IO_printf); +ldbl_strong_alias (__printf, _IO_printf); diff --git a/stdio-common/printf.h b/stdio-common/printf.h index c16569b59b..360cdcce1d 100644 --- a/stdio-common/printf.h +++ b/stdio-common/printf.h @@ -1,4 +1,5 @@ -/* Copyright (C) 1991-1993,1995-1999,2000,2001 Free Software Foundation, Inc. +/* Copyright (C) 1991-1993,1995-1999,2000,2001,2006 + Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -139,6 +140,9 @@ extern int printf_size_info (__const struct printf_info *__restrict __info, size_t __n, int *__restrict __argtypes) __THROW; +#ifdef __LDBL_COMPAT +# include <bits/printf-ldbl.h> +#endif __END_DECLS diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c index ed225e05a6..c7a381a69d 100644 --- a/stdio-common/printf_fp.c +++ b/stdio-common/printf_fp.c @@ -1,5 +1,5 @@ /* Floating point output for `printf'. - Copyright (C) 1995-1999,2000,2001,2002,2003 Free Software Foundation, Inc. + Copyright (C) 1995-2003, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. @@ -71,7 +71,11 @@ { \ register const int outc = (ch); \ if (putc (outc, fp) == EOF) \ - return -1; \ + { \ + if (buffer_malloced) \ + free (wbuffer); \ + return -1; \ + } \ ++done; \ } while (0) @@ -82,7 +86,11 @@ if (len > 20) \ { \ if (PUT (fp, wide ? (const char *) wptr : ptr, outlen) != outlen) \ - return -1; \ + { \ + if (buffer_malloced) \ + free (wbuffer); \ + return -1; \ + } \ ptr += outlen; \ done += outlen; \ } \ @@ -101,7 +109,11 @@ do \ { \ if (PAD (fp, ch, len) != len) \ - return -1; \ + { \ + if (buffer_malloced) \ + free (wbuffer); \ + return -1; \ + } \ done += len; \ } \ while (0) @@ -138,9 +150,9 @@ static wchar_t *group_number (wchar_t *buf, wchar_t *bufend, int -__printf_fp (FILE *fp, - const struct printf_info *info, - const void *const *args) +___printf_fp (FILE *fp, + const struct printf_info *info, + const void *const *args) { /* The floating-point value to output. */ union @@ -199,6 +211,11 @@ __printf_fp (FILE *fp, /* Nonzero if this is output on a wide character stream. */ int wide = info->wide; + /* Buffer in which we produce the output. */ + wchar_t *wbuffer = NULL; + /* Flag whether wbuffer is malloc'ed or not. */ + int buffer_malloced = 0; + auto wchar_t hack_digit (void); wchar_t hack_digit (void) @@ -775,7 +792,7 @@ __printf_fp (FILE *fp, 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 + numbers are in the range of 1.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 && @@ -789,17 +806,18 @@ __printf_fp (FILE *fp, { int width = info->width; - wchar_t *wbuffer, *wstartp, *wcp; - int buffer_malloced; + wchar_t *wstartp, *wcp; int chars_needed; int expscale; int intdig_max, intdig_no = 0; - int fracdig_min, fracdig_max, fracdig_no = 0; + int fracdig_min; + int fracdig_max; int dig_max; int significant; int ngroups = 0; + char spec = _tolower (info->spec); - if (_tolower (info->spec) == 'e') + if (spec == 'e') { type = info->spec; intdig_max = 1; @@ -809,7 +827,7 @@ __printf_fp (FILE *fp, dig_max = INT_MAX; /* Unlimited. */ significant = 1; /* Does not matter here. */ } - else if (_tolower (info->spec) == 'f') + else if (spec == 'f') { type = 'f'; fracdig_min = fracdig_max = info->prec < 0 ? 6 : info->prec; @@ -906,7 +924,9 @@ __printf_fp (FILE *fp, } /* Generate the needed number of fractional digits. */ - while (fracdig_no < fracdig_min + int fracdig_no = 0; + int added_zeros = 0; + while (fracdig_no < fracdig_min + added_zeros || (fracdig_no < fracdig_max && (fracsize > 1 || frac[0] != 0))) { ++fracdig_no; @@ -917,7 +937,7 @@ __printf_fp (FILE *fp, { ++fracdig_max; if (fracdig_min > 0) - ++fracdig_min; + ++added_zeros; } } @@ -954,11 +974,23 @@ __printf_fp (FILE *fp, { /* Process fractional digits. Terminate if not rounded or radix character is reached. */ + int removed = 0; while (*--wtp != decimalwc && *wtp == L'9') - *wtp = '0'; + { + *wtp = L'0'; + ++removed; + } + if (removed == fracdig_min && added_zeros > 0) + --added_zeros; if (*wtp != decimalwc) /* Round up. */ (*wtp)++; + else if (__builtin_expect (spec == 'g' && type == 'f' && info->alt, + 0)) + /* This is a special case: the rounded number is 1.0, + the format is 'g' or 'G', and the alternative format + is selected. This means the result must be "1.". */ + --added_zeros; } if (fracdig_no == 0 || *wtp == decimalwc) @@ -980,6 +1012,12 @@ __printf_fp (FILE *fp, { *wstartp = '1'; exponent += expsign == 0 ? 1 : -1; + + /* The above exponent adjustment could lead to 1.0e-00, + e.g. for 0.999999999. Make sure exponent 0 always + uses + sign. */ + if (exponent == 0) + expsign = 0; } else if (intdig_no == dig_max) { @@ -1025,7 +1063,7 @@ __printf_fp (FILE *fp, do_expo: /* Now remove unnecessary '0' at the end of the string. */ - while (fracdig_no > fracdig_min && *(wcp - 1) == L'0') + while (fracdig_no > fracdig_min + added_zeros && *(wcp - 1) == L'0') { --wcp; --fracdig_no; @@ -1043,26 +1081,46 @@ __printf_fp (FILE *fp, /* Write the exponent if it is needed. */ if (type != 'f') { - *wcp++ = (wchar_t) type; - *wcp++ = expsign ? L'-' : L'+'; + if (__builtin_expect (expsign != 0 && exponent == 4 && spec == 'g', 0)) + { + /* This is another special case. The exponent of the number is + really smaller than -4, which requires the 'e'/'E' format. + But after rounding the number has an exponent of -4. */ + assert (wcp >= wstartp + 1); + assert (wstartp[0] == L'1'); + __wmemcpy (wstartp, L"0.0001", 6); + wstartp[1] = decimalwc; + if (wcp >= wstartp + 2) + { + wmemset (wstartp + 6, L'0', wcp - (wstartp + 2)); + wcp += 4; + } + else + wcp += 5; + } + else + { + *wcp++ = (wchar_t) type; + *wcp++ = expsign ? L'-' : L'+'; - /* Find the magnitude of the exponent. */ - expscale = 10; - while (expscale <= exponent) - expscale *= 10; + /* Find the magnitude of the exponent. */ + expscale = 10; + while (expscale <= exponent) + expscale *= 10; - if (exponent < 10) - /* Exponent always has at least two digits. */ - *wcp++ = L'0'; - else - do - { - expscale /= 10; - *wcp++ = L'0' + (exponent / expscale); - exponent %= expscale; - } - while (expscale > 10); - *wcp++ = L'0' + exponent; + if (exponent < 10) + /* Exponent always has at least two digits. */ + *wcp++ = L'0'; + else + do + { + expscale /= 10; + *wcp++ = L'0' + (exponent / expscale); + exponent %= expscale; + } + while (expscale > 10); + *wcp++ = L'0' + exponent; + } } /* Compute number of characters which must be filled with the padding @@ -1108,8 +1166,12 @@ __printf_fp (FILE *fp, buffer = (char *) malloc (2 + chars_needed + decimal_len + ngroups * thousands_sep_len); if (buffer == NULL) - /* Signal an error to the caller. */ - return -1; + { + /* Signal an error to the caller. */ + if (buffer_malloced) + free (wbuffer); + return -1; + } } else buffer = (char *) alloca (2 + chars_needed + decimal_len @@ -1153,7 +1215,8 @@ __printf_fp (FILE *fp, } return done; } -libc_hidden_def (__printf_fp) +ldbl_hidden_def (___printf_fp, __printf_fp) +ldbl_strong_alias (___printf_fp, __printf_fp) /* Return the number of extra grouping characters that will be inserted into a number with INTDIG_MAX integer digits. */ diff --git a/stdio-common/printf_fphex.c b/stdio-common/printf_fphex.c new file mode 100644 index 0000000000..4e30d94c61 --- /dev/null +++ b/stdio-common/printf_fphex.c @@ -0,0 +1,493 @@ +/* Print floating point number in hexadecimal notation according to ISO C99. + Copyright (C) 1997-2002,2004,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <ctype.h> +#include <ieee754.h> +#include <math.h> +#include <printf.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <wchar.h> +#include "_itoa.h" +#include "_itowa.h" +#include <locale/localeinfo.h> + +/* #define NDEBUG 1*/ /* Undefine this for debugging assertions. */ +#include <assert.h> + +/* This defines make it possible to use the same code for GNU C library and + the GNU I/O library. */ +#ifdef USE_IN_LIBIO +# include <libioP.h> +# define PUT(f, s, n) _IO_sputn (f, s, n) +# define PAD(f, c, n) (wide ? _IO_wpadn (f, c, n) : INTUSE(_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) (wide \ + ? (int)_IO_putwc_unlocked (c, f) : _IO_putc_unlocked (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 (FILE *, char pad, int n) __THROW; /* 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, wptr, len) \ + do \ + { \ + register size_t outlen = (len); \ + if (wide) \ + while (outlen-- > 0) \ + outchar (*wptr++); \ + 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) + +#ifndef MIN +# define MIN(a,b) ((a)<(b)?(a):(b)) +#endif + + +int +__printf_fphex (FILE *fp, + const struct printf_info *info, + const void *const *args) +{ + /* The floating-point value to output. */ + union + { + union ieee754_double dbl; + union ieee854_long_double ldbl; + } + fpnum; + + /* Locale-dependent representation of decimal point. */ + const char *decimal; + wchar_t decimalwc; + + /* "NaN" or "Inf" for the special cases. */ + const char *special = NULL; + const wchar_t *wspecial = NULL; + + /* Buffer for the generated number string for the mantissa. The + maximal size for the mantissa is 128 bits. */ + char numbuf[32]; + char *numstr; + char *numend; + wchar_t wnumbuf[32]; + wchar_t *wnumstr; + wchar_t *wnumend; + int negative; + + /* The maximal exponent of two in decimal notation has 5 digits. */ + char expbuf[5]; + char *expstr; + wchar_t wexpbuf[5]; + wchar_t *wexpstr; + int expnegative; + int exponent; + + /* Non-zero is mantissa is zero. */ + int zero_mantissa; + + /* The leading digit before the decimal point. */ + char leading; + + /* Precision. */ + int precision = info->prec; + + /* Width. */ + int width = info->width; + + /* Number of characters written. */ + int done = 0; + + /* Nonzero if this is output on a wide character stream. */ + int wide = info->wide; + + + /* Figure out the decimal point character. */ + if (info->extra == 0) + { + decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT); + decimalwc = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC); + } + else + { + decimal = _NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT); + decimalwc = _NL_CURRENT_WORD (LC_MONETARY, + _NL_MONETARY_DECIMAL_POINT_WC); + } + /* The decimal point character must never be zero. */ + assert (*decimal != '\0' && decimalwc != L'\0'); + + + /* Fetch the argument value. */ +#ifndef __NO_LONG_DOUBLE_MATH + if (info->is_long_double && sizeof (long double) > sizeof (double)) + { + fpnum.ldbl.d = *(const long double *) args[0]; + + /* Check for special values: not a number or infinity. */ + if (__isnanl (fpnum.ldbl.d)) + { + if (isupper (info->spec)) + { + special = "NAN"; + wspecial = L"NAN"; + } + else + { + special = "nan"; + wspecial = L"nan"; + } + negative = 0; + } + else + { + if (__isinfl (fpnum.ldbl.d)) + { + if (isupper (info->spec)) + { + special = "INF"; + wspecial = L"INF"; + } + else + { + special = "inf"; + wspecial = L"inf"; + } + } + + negative = signbit (fpnum.ldbl.d); + } + } + else +#endif /* no long double */ + { + fpnum.dbl.d = *(const double *) args[0]; + + /* Check for special values: not a number or infinity. */ + if (__isnan (fpnum.dbl.d)) + { + if (isupper (info->spec)) + { + special = "NAN"; + wspecial = L"NAN"; + } + else + { + special = "nan"; + wspecial = L"nan"; + } + negative = 0; + } + else + { + if (__isinf (fpnum.dbl.d)) + { + if (isupper (info->spec)) + { + special = "INF"; + wspecial = L"INF"; + } + else + { + special = "inf"; + wspecial = L"inf"; + } + } + + negative = signbit (fpnum.dbl.d); + } + } + + if (special) + { + int width = info->width; + + if (negative || info->showsign || info->space) + --width; + width -= 3; + + if (!info->left && width > 0) + PADN (' ', width); + + if (negative) + outchar ('-'); + else if (info->showsign) + outchar ('+'); + else if (info->space) + outchar (' '); + + PRINT (special, wspecial, 3); + + if (info->left && width > 0) + PADN (' ', width); + + return done; + } + + if (info->is_long_double == 0 || sizeof (double) == sizeof (long double)) + { + /* We have 52 bits of mantissa plus one implicit digit. Since + 52 bits are representable without rest using hexadecimal + digits we use only the implicit digits for the number before + the decimal point. */ + unsigned long long int num; + + num = (((unsigned long long int) fpnum.dbl.ieee.mantissa0) << 32 + | fpnum.dbl.ieee.mantissa1); + + zero_mantissa = num == 0; + + if (sizeof (unsigned long int) > 6) + { + wnumstr = _itowa_word (num, wnumbuf + (sizeof wnumbuf) / sizeof (wchar_t), 16, + info->spec == 'A'); + numstr = _itoa_word (num, numbuf + sizeof numbuf, 16, + info->spec == 'A'); + } + else + { + wnumstr = _itowa (num, wnumbuf + sizeof wnumbuf / sizeof (wchar_t), 16, + info->spec == 'A'); + numstr = _itoa (num, numbuf + sizeof numbuf, 16, + info->spec == 'A'); + } + + /* Fill with zeroes. */ + while (wnumstr > wnumbuf + (sizeof wnumbuf - 52) / sizeof (wchar_t)) + { + *--wnumstr = L'0'; + *--numstr = '0'; + } + + leading = fpnum.dbl.ieee.exponent == 0 ? '0' : '1'; + + exponent = fpnum.dbl.ieee.exponent; + + if (exponent == 0) + { + if (zero_mantissa) + expnegative = 0; + else + { + /* This is a denormalized number. */ + expnegative = 1; + exponent = IEEE754_DOUBLE_BIAS - 1; + } + } + else if (exponent >= IEEE754_DOUBLE_BIAS) + { + expnegative = 0; + exponent -= IEEE754_DOUBLE_BIAS; + } + else + { + expnegative = 1; + exponent = -(exponent - IEEE754_DOUBLE_BIAS); + } + } +#ifdef PRINT_FPHEX_LONG_DOUBLE + else + PRINT_FPHEX_LONG_DOUBLE; +#endif + + /* Look for trailing zeroes. */ + if (! zero_mantissa) + { + wnumend = &wnumbuf[sizeof wnumbuf / sizeof wnumbuf[0]]; + numend = &numbuf[sizeof numbuf / sizeof numbuf[0]]; + while (wnumend[-1] == L'0') + { + --wnumend; + --numend; + } + + if (precision == -1) + precision = numend - numstr; + else if (precision < numend - numstr + && (numstr[precision] > '8' + || (('A' < '0' || 'a' < '0') + && numstr[precision] < '0') + || (numstr[precision] == '8' + && (precision + 1 < numend - numstr + /* Round to even. */ + || (precision > 0 + && ((numstr[precision - 1] & 1) + ^ (isdigit (numstr[precision - 1]) == 0))) + || (precision == 0 + && ((leading & 1) + ^ (isdigit (leading) == 0))))))) + { + /* Round up. */ + int cnt = precision; + while (--cnt >= 0) + { + char ch = numstr[cnt]; + /* We assume that the digits and the letters are ordered + like in ASCII. This is true for the rest of GNU, too. */ + if (ch == '9') + { + wnumstr[cnt] = (wchar_t) info->spec; + numstr[cnt] = info->spec; /* This is tricky, + think about it! */ + break; + } + else if (tolower (ch) < 'f') + { + ++numstr[cnt]; + ++wnumstr[cnt]; + break; + } + else + { + numstr[cnt] = '0'; + wnumstr[cnt] = L'0'; + } + } + if (cnt < 0) + { + /* The mantissa so far was fff...f Now increment the + leading digit. Here it is again possible that we + get an overflow. */ + if (leading == '9') + leading = info->spec; + else if (tolower (leading) < 'f') + ++leading; + else + { + leading = '1'; + if (expnegative) + { + exponent -= 4; + if (exponent <= 0) + { + exponent = -exponent; + expnegative = 0; + } + } + else + exponent += 4; + } + } + } + } + else + { + if (precision == -1) + precision = 0; + numend = numstr; + wnumend = wnumstr; + } + + /* Now we can compute the exponent string. */ + expstr = _itoa_word (exponent, expbuf + sizeof expbuf, 10, 0); + wexpstr = _itowa_word (exponent, + wexpbuf + sizeof wexpbuf / sizeof (wchar_t), 10, 0); + + /* Now we have all information to compute the size. */ + width -= ((negative || info->showsign || info->space) + /* Sign. */ + + 2 + 1 + 0 + precision + 1 + 1 + /* 0x h . hhh P ExpoSign. */ + + ((expbuf + sizeof expbuf) - expstr)); + /* Exponent. */ + + /* Count the decimal point. + A special case when the mantissa or the precision is zero and the `#' + is not given. In this case we must not print the decimal point. */ + if (precision > 0 || info->alt) + width -= wide ? 1 : strlen (decimal); + + if (!info->left && info->pad != '0' && width > 0) + PADN (' ', width); + + if (negative) + outchar ('-'); + else if (info->showsign) + outchar ('+'); + else if (info->space) + outchar (' '); + + outchar ('0'); + if ('X' - 'A' == 'x' - 'a') + outchar (info->spec + ('x' - 'a')); + else + outchar (info->spec == 'A' ? 'X' : 'x'); + + if (!info->left && info->pad == '0' && width > 0) + PADN ('0', width); + + outchar (leading); + + if (precision > 0 || info->alt) + { + const wchar_t *wtmp = &decimalwc; + PRINT (decimal, wtmp, wide ? 1 : strlen (decimal)); + } + + if (precision > 0) + { + ssize_t tofill = precision - (numend - numstr); + PRINT (numstr, wnumstr, MIN (numend - numstr, precision)); + if (tofill > 0) + PADN ('0', tofill); + } + + if ('P' - 'A' == 'p' - 'a') + outchar (info->spec + ('p' - 'a')); + else + outchar (info->spec == 'A' ? 'P' : 'p'); + + outchar (expnegative ? '-' : '+'); + + PRINT (expstr, wexpstr, (expbuf + sizeof expbuf) - expstr); + + if (info->left && info->pad != '0' && width > 0) + PADN (info->pad, width); + + return done; +} diff --git a/stdio-common/printf_size.c b/stdio-common/printf_size.c index 32f262ead0..957de2f571 100644 --- a/stdio-common/printf_size.c +++ b/stdio-common/printf_size.c @@ -1,5 +1,5 @@ /* Print size value using units for orders of magnitude. - Copyright (C) 1997-2002, 2004 Free Software Foundation, Inc. + Copyright (C) 1997-2002, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. Based on a proposal by Larry McVoy <lm@sgi.com>. @@ -86,7 +86,8 @@ extern int __printf_fp (FILE *fp, const struct printf_info *info, int -printf_size (FILE *fp, const struct printf_info *info, const void *const *args) +__printf_size (FILE *fp, const struct printf_info *info, + const void *const *args) { /* Units for the both formats. */ #define BINARY_UNITS " kmgtpezy" @@ -233,6 +234,7 @@ printf_size (FILE *fp, const struct printf_info *info, const void *const *args) return done; } +ldbl_strong_alias (__printf_size, printf_size); /* This is the function used by `vfprintf' to determine number and type of the arguments. */ diff --git a/stdio-common/psignal.c b/stdio-common/psignal.c index 2e6588c692..98049a5871 100644 --- a/stdio-common/psignal.c +++ b/stdio-common/psignal.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1992, 1995, 1996, 1997, 2001, 2002, 2004 +/* Copyright (C) 1991, 1992, 1995, 1996, 1997, 2001, 2002, 2004, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -24,10 +24,6 @@ #include <wchar.h> -#ifndef HAVE_GNU_LD -#define _sys_siglist sys_siglist -#endif - /* Defined in sys_siglist.c. */ extern const char *const _sys_siglist[]; extern const char *const _sys_siglist_internal[] attribute_hidden; @@ -47,29 +43,16 @@ psignal (int sig, const char *s) colon = ": "; if (sig >= 0 && sig < NSIG && (desc = INTUSE(_sys_siglist)[sig]) != NULL) - { - if (_IO_fwide (stderr, 0) > 0) - (void) __fwprintf (stderr, L"%s%s%s\n", s, colon, _(desc)); - else - (void) fprintf (stderr, "%s%s%s\n", s, colon, _(desc)); - } + (void) __fxprintf (NULL, "%s%s%s\n", s, colon, _(desc)); else { char *buf; if (__asprintf (&buf, _("%s%sUnknown signal %d\n"), s, colon, sig) < 0) - { - if (_IO_fwide (stderr, 0) > 0) - (void) __fwprintf (stderr, L"%s%s%s\n", s, colon, _("Unknown signal")); - else - (void) fprintf (stderr, "%s%s%s\n", s, colon, _("Unknown signal")); - } + (void) __fxprintf (NULL, "%s%s%s\n", s, colon, _("Unknown signal")); else { - if (_IO_fwide (stderr, 0) > 0) - (void) __fwprintf (stderr, L"%s", buf); - else - (void) fputs (buf, stderr); + (void) __fxprintf (NULL, "%s", buf); free (buf); } diff --git a/stdio-common/remove.c b/stdio-common/remove.c new file mode 100644 index 0000000000..5dc0e9edf0 --- /dev/null +++ b/stdio-common/remove.c @@ -0,0 +1,33 @@ +/* ANSI C `remove' function to delete a file or directory. Stub version. + Copyright (C) 1995,96,97,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <stdio.h> + +int +remove (file) + const char *file; +{ + __set_errno (ENOSYS); + return -1; +} +libc_hidden_def (remove) + +stub_warning (remove) +#include <stub-tag.h> diff --git a/stdio-common/rename.c b/stdio-common/rename.c new file mode 100644 index 0000000000..b7d8392179 --- /dev/null +++ b/stdio-common/rename.c @@ -0,0 +1,41 @@ +/* Copyright (C) 1991, 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <stdio.h> +#include <errno.h> + + +/* Rename the file OLD to NEW. */ +int +rename (old, new) + const char *old; + const char *new; +{ + if (old == NULL || new == NULL) + { + __set_errno (EINVAL); + return -1; + } + + __set_errno (ENOSYS); + return -1; +} + + +stub_warning (rename) +#include <stub-tag.h> diff --git a/stdio-common/renameat.c b/stdio-common/renameat.c new file mode 100644 index 0000000000..1261da88a4 --- /dev/null +++ b/stdio-common/renameat.c @@ -0,0 +1,50 @@ +/* Copyright (C) 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> + + +/* Rename the file OLD relative to OLDFD to NEW relative to NEWFD. */ +int +renameat (oldfd, old, newfd, new) + int oldfd; + const char *old; + int newfd; + const char *new; +{ + if ((oldfd < 0 && oldfd != AT_FDCWD) || (newfd < 0 && newfd != AT_FDCWD)) + { + __set_errno (EBADF); + return -1; + } + + if (old == NULL || new == NULL) + { + __set_errno (EINVAL); + return -1; + } + + __set_errno (ENOSYS); + return -1; +} + + +stub_warning (renameat) +#include <stub-tag.h> diff --git a/stdio-common/scanf.c b/stdio-common/scanf.c index 62c9959651..d4a4daf726 100644 --- a/stdio-common/scanf.c +++ b/stdio-common/scanf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1995, 1996, 1997, 2002, 2004 +/* Copyright (C) 1991, 1995, 1996, 1997, 2002, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -26,7 +26,7 @@ /* Read formatted input from stdin according to the format string FORMAT. */ /* VARARGS1 */ int -scanf (const char *format, ...) +__scanf (const char *format, ...) { va_list arg; int done; @@ -37,3 +37,4 @@ scanf (const char *format, ...) return done; } +ldbl_strong_alias (__scanf, scanf) diff --git a/stdio-common/siglist.c b/stdio-common/siglist.c new file mode 100644 index 0000000000..80847cd491 --- /dev/null +++ b/stdio-common/siglist.c @@ -0,0 +1,38 @@ +/* Define list of all signal numbers and their names. + Copyright (C) 1997, 1998, 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <stddef.h> +#include <signal.h> +#include <libintl.h> + +const char *const _sys_siglist[NSIG] = +{ +#define init_sig(sig, abbrev, desc) [sig] = desc, +#include <siglist.h> +#undef init_sig +}; +strong_alias (_sys_siglist, _sys_siglist_internal) + + +const char *const _sys_sigabbrev[NSIG] = +{ +#define init_sig(sig, abbrev, desc) [sig] = abbrev, +#include <siglist.h> +#undef init_sig +}; diff --git a/stdio-common/snprintf.c b/stdio-common/snprintf.c index ce392f0096..00d2082350 100644 --- a/stdio-common/snprintf.c +++ b/stdio-common/snprintf.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1991, 1995, 1997, 1998, 2004 Free Software Foundation, Inc. +/* Copyright (C) 1991, 1995, 1997, 1998, 2004, 2006 + Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -18,8 +19,7 @@ #include <stdarg.h> #include <stdio.h> - -#include <libio/libioP.h> +#include <libioP.h> #define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a) /* Write formatted output into S, according to the format @@ -37,4 +37,4 @@ __snprintf (char *s, size_t maxlen, const char *format, ...) return done; } -weak_alias (__snprintf, snprintf) +ldbl_weak_alias (__snprintf, snprintf) diff --git a/stdio-common/sprintf.c b/stdio-common/sprintf.c index 249fcb0dde..7f564d5635 100644 --- a/stdio-common/sprintf.c +++ b/stdio-common/sprintf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1995, 1997, 1998, 2002, 2004 +/* Copyright (C) 1991, 1995, 1997, 1998, 2002, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -19,13 +19,13 @@ #include <stdarg.h> #include <stdio.h> -#include <libio/iolibio.h> +#include <libioP.h> #define vsprintf(s, f, a) INTUSE(_IO_vsprintf) (s, f, a) /* Write formatted output into S, according to the format string FORMAT. */ /* VARARGS2 */ int -sprintf (char *s, const char *format, ...) +__sprintf (char *s, const char *format, ...) { va_list arg; int done; @@ -36,6 +36,6 @@ sprintf (char *s, const char *format, ...) return done; } -libc_hidden_def (sprintf) - -strong_alias(sprintf, _IO_sprintf) +ldbl_hidden_def (__sprintf, sprintf) +ldbl_strong_alias (__sprintf, sprintf) +ldbl_strong_alias (__sprintf, _IO_sprintf) diff --git a/stdio-common/sscanf.c b/stdio-common/sscanf.c index b36976710b..384a6977dc 100644 --- a/stdio-common/sscanf.c +++ b/stdio-common/sscanf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1995, 1996, 1998, 2002, 2003, 2004 +/* Copyright (C) 1991, 1995, 1996, 1998, 2002, 2003, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -19,13 +19,13 @@ #include <stdarg.h> #include <stdio.h> -#include <libio/iolibio.h> +#include <libioP.h> #define __vsscanf(s, f, a) _IO_vsscanf (s, f, a) /* Read formatted input from S, according to the format string FORMAT. */ /* VARARGS2 */ int -sscanf (const char *s, const char *format, ...) +__sscanf (const char *s, const char *format, ...) { va_list arg; int done; @@ -36,8 +36,8 @@ sscanf (const char *s, const char *format, ...) return done; } -libc_hidden_def (sscanf) - +ldbl_hidden_def (__sscanf, sscanf) +ldbl_strong_alias (__sscanf, sscanf) #undef _IO_sscanf /* This is for libg++. */ -strong_alias (sscanf, _IO_sscanf) +ldbl_strong_alias (__sscanf, _IO_sscanf) diff --git a/stdio-common/tempname.c b/stdio-common/tempname.c new file mode 100644 index 0000000000..60c94d6409 --- /dev/null +++ b/stdio-common/tempname.c @@ -0,0 +1,59 @@ +/* Copyright (C) 1991, 92, 93, 95-98, 99 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __need_size_t +#include <stddef.h> +#include <stdio.h> +#include <errno.h> + +/* Perform the "SVID path search malarkey" on DIR and PFX. Write a + template suitable for use in __gen_tempname into TMPL, bounded + by TMPL_LEN. */ +int +__path_search (tmpl, tmpl_len, dir, pfx, try_tmpdir) + char *tmpl; + size_t tmpl_len; + const char *dir; + const char *pfx; + int try_tmpdir; +{ + __set_errno (ENOSYS); + return -1; +} +stub_warning (__path_search) + +/* Generate a (hopefully) unique temporary filename + in DIR (if applicable), using template TMPL. + KIND determines what to do with that name. It may be one of: + __GT_FILE: create a file and return a read-write fd. + __GT_BIGFILE: same, but use open64() (or equivalent). + __GT_DIR: create a directory. + __GT_NOCREATE: just find a name not currently in use. + */ + +int +__gen_tempname (tmpl, kind) + char *tmpl; + int kind; +{ + __set_errno (ENOSYS); + return -1; +} + +stub_warning (__gen_tempname) +#include <stub-tag.h> diff --git a/stdio-common/test-vfprintf.c b/stdio-common/test-vfprintf.c index a683eac779..342ac471da 100644 --- a/stdio-common/test-vfprintf.c +++ b/stdio-common/test-vfprintf.c @@ -1,5 +1,5 @@ /* Tests of *printf for very large strings. - Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2003, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2000. @@ -94,6 +94,7 @@ main (void) fprintf (fp, "%.*s", 30000, large); large[20000] = '\0'; fprintf (fp, large); + fprintf (fp, "%-1.300000000s", "hello"); if (fflush (fp) != 0 || ferror (fp) != 0 || fclose (fp) != 0) { @@ -108,11 +109,12 @@ main (void) setlocale (LC_ALL, NULL)); exit (1); } - else if (st.st_size != 99999) + else if (st.st_size != 50000 + 30000 + 19999 + 5) { printf ("file size incorrect for locale %s: %jd instead of %jd\n", setlocale (LC_ALL, NULL), - (intmax_t) st.st_size, (intmax_t) 99999); + (intmax_t) st.st_size, + (intmax_t) 50000 + 30000 + 19999 + 5); res = 1; } else diff --git a/stdio-common/tfformat.c b/stdio-common/tfformat.c index ea7365b2c9..d67b3b504d 100644 --- a/stdio-common/tfformat.c +++ b/stdio-common/tfformat.c @@ -4012,6 +4012,17 @@ sprint_double_type sprint_doubles[] = {__LINE__, 16, "0x1.0p+4", "%.1a"}, {__LINE__, 16, "0x1.00000000000000000000p+4", "%.20a"}, {__LINE__, 4444.88888888, "4445", "%2.F"}, + {__LINE__, 0.956, "1", "%.0g"}, + {__LINE__, 1.0956, "1.", "%#.0g"}, + {__LINE__, 0.956, "1.", "%#.0g"}, + {__LINE__, 0.0956, "0.1", "%#.0g"}, + {__LINE__, 0.00956, "0.01", "%#.0g"}, + {__LINE__, 0.000956, "0.001", "%#.0g"}, + {__LINE__, 0.000098, "0.0001", "%#.0g"}, + {__LINE__, 0.0000996, "0.00010", "%#.2g"}, + {__LINE__, 9.999999999999999e-05, "0.0001", "%g"}, + {__LINE__, 1.0, "1.000000e+00", "%e"}, + {__LINE__, .9999999999999999, "1.000000e+00", "%e"}, {0 } @@ -4023,13 +4034,8 @@ sprint_double_type sprint_doubles[] = int required_precision = 13; -#if defined(__STDC__) || defined(__cplusplus) static int matches (register char *result, register const char *desired) -#else -int matches(result, desired) - register char *result; register const char *desired; -#endif { int digits_seen = 0; for (;; result++, desired++) { @@ -4080,7 +4086,7 @@ int main(int argc, char *argv[]) /* And one special test. */ { - const char ref[] = "1.7763568394002504646778106689453125e-15"; + static const char ref[] = "1.7763568394002504646778106689453125e-15"; int i; d = 1.0; for (i = 1; i < 50; ++i) diff --git a/stdio-common/tmpfile.c b/stdio-common/tmpfile.c new file mode 100644 index 0000000000..41f12bc8ba --- /dev/null +++ b/stdio-common/tmpfile.c @@ -0,0 +1,66 @@ +/* Open a stdio stream on an anonymous temporary file. Generic/POSIX version. + Copyright (C) 1991,93,1996-2000,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <stdio.h> +#include <unistd.h> + +#ifdef USE_IN_LIBIO +# include <iolibio.h> +# define __fdopen INTUSE(_IO_fdopen) +# ifndef tmpfile +# define tmpfile __new_tmpfile +# endif +#endif + +#ifndef GEN_THIS +# define GEN_THIS __GT_FILE +#endif + +/* 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 * +tmpfile (void) +{ + char buf[FILENAME_MAX]; + int fd; + FILE *f; + + if (__path_search (buf, FILENAME_MAX, NULL, "tmpf", 0)) + return NULL; + fd = __gen_tempname (buf, GEN_THIS); + if (fd < 0) + return NULL; + + /* Note that this relies on the Unix semantics that + a file is not really removed until it is closed. */ + (void) __unlink (buf); + + if ((f = __fdopen (fd, "w+b")) == NULL) + __close (fd); + + return f; +} + +#if defined USE_IN_LIBIO && GEN_THIS == __GT_FILE /* Not for tmpfile64. */ +# undef tmpfile +# include <shlib-compat.h> +versioned_symbol (libc, __new_tmpfile, tmpfile, GLIBC_2_1); +#endif diff --git a/stdio-common/tmpfile64.c b/stdio-common/tmpfile64.c new file mode 100644 index 0000000000..b265aeee56 --- /dev/null +++ b/stdio-common/tmpfile64.c @@ -0,0 +1,3 @@ +#define GEN_THIS __GT_BIGFILE +#define tmpfile tmpfile64 +#include <tmpfile.c> diff --git a/stdio-common/tst-fgets.c b/stdio-common/tst-fgets.c new file mode 100644 index 0000000000..0aa9030e3a --- /dev/null +++ b/stdio-common/tst-fgets.c @@ -0,0 +1,20 @@ +/* Derived from the test case in + http://sourceware.org/bugzilla/show_bug.cgi?id=713. */ +#include <stdio.h> + +static int +do_test (void) +{ + FILE *fp = fmemopen ((char *) "hello", 5, "r"); + char buf[2]; + char *bp = fgets (buf, sizeof (buf), fp); + printf ("fgets: %s\n", bp == buf ? "OK" : "ERROR"); + int res = bp != buf; + bp = fgets_unlocked (buf, sizeof (buf), fp); + printf ("fgets_unlocked: %s\n", bp == buf ? "OK" : "ERROR"); + res |= bp != buf; + return res; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/stdio-common/tst-fmemopen2.c b/stdio-common/tst-fmemopen2.c new file mode 100644 index 0000000000..81beddddef --- /dev/null +++ b/stdio-common/tst-fmemopen2.c @@ -0,0 +1,68 @@ +#include <assert.h> +#include <stdio.h> +#include <string.h> +#include <sys/types.h> + + +static int +do_test (void) +{ + int result = 0; + char buf[100]; + FILE *fp = fmemopen (buf, sizeof (buf), "w"); + if (fp == NULL) + { + puts ("fmemopen failed"); + return 0; + } + static const char str[] = "hello world"; +#define nstr (sizeof (str) - 1) + fputs (str, fp); + off_t o = ftello (fp); + if (o != nstr) + { + printf ("first ftello returned %ld, expected %zu\n", o, nstr); + result = 1; + } + rewind (fp); + o = ftello (fp); + if (o != 0) + { + printf ("second ftello returned %ld, expected %zu\n", o, (off_t) 0); + result = 1; + } + if (fseeko (fp, 0, SEEK_END) != 0) + { + puts ("fseeko failed"); + return 1; + } + o = ftello (fp); + if (o != nstr) + { + printf ("third ftello returned %ld, expected %zu\n", o, nstr); + result = 1; + } + rewind (fp); + static const char str2[] = "just hello"; +#define nstr2 (sizeof (str2) - 1) + assert (nstr2 < nstr); + fputs (str2, fp); + o = ftello (fp); + if (o != nstr2) + { + printf ("fourth ftello returned %ld, expected %zu\n", o, nstr2); + result = 1; + } + fclose (fp); + static const char str3[] = "just hellod"; + if (strcmp (buf, str3) != 0) + { + printf ("final string is \"%s\", expected \"%s\"\n", + buf, str3); + result = 1; + } + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/stdio-common/tst-fwrite.c b/stdio-common/tst-fwrite.c new file mode 100644 index 0000000000..2986c8932a --- /dev/null +++ b/stdio-common/tst-fwrite.c @@ -0,0 +1,70 @@ +/* Derived from the test case in + http://sourceware.org/bugzilla/show_bug.cgi?id=1078. */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#define OUT_SIZE 10000 + + +static int fd; + +static void prepare (void); +#define PREPARE(argc, argv) prepare () + +static int do_test (void); +#define TEST_FUNCTION do_test () + +#include "../test-skeleton.c" + + +static void +prepare (void) +{ + fd = create_temp_file ("tst-fwrite.", NULL); + if (fd == -1) + { + puts ("cannot create temporary file"); + exit (1); + } +} + + +static int +do_test (void) +{ + FILE* f = fdopen (fd, "w+"); + if (f == NULL) { + puts ("cannot create stream"); + return 1; + } + puts ("Opened temp file"); + + if (fwrite ("a", 1, 1, f) != 1) + { + puts ("1st fwrite failed"); + return 1; + } + puts ("Wrote a byte"); + fflush (f); + + char buffer[10000]; + size_t i = fread (buffer, 1, sizeof (buffer), f); + printf ("Read %zu bytes\n", i); + + for (i = 0; i < OUT_SIZE; i++) + { + if (fwrite ("n", 1, 1, f) != 1) + { + printf ("fwrite in loop round %zu failed\n", i); + return 1; + } + + if ((i + 1) % 1000 == 0) + printf ("wrote %zu bytes ...\n", i + 1); + } + + printf ("Wrote %i bytes [done]\n", OUT_SIZE); + + return 0; +} diff --git a/stdio-common/tst-printf.c b/stdio-common/tst-printf.c index a9db7ad2de..06fa38ab55 100644 --- a/stdio-common/tst-printf.c +++ b/stdio-common/tst-printf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991,92,93,95,96,97,98,99, 2000, 2002 +/* Copyright (C) 1991,92,93,95,96,97,98,99, 2000, 2002, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -273,6 +273,15 @@ I am ready for my first lesson today."; printf ("printf (\"%%hhu\", %u) = %hhu\n", UCHAR_MAX + 2, UCHAR_MAX + 2); printf ("printf (\"%%hu\", %u) = %hu\n", USHRT_MAX + 2, USHRT_MAX + 2); + printf ("printf (\"%%hhi\", %i) = %hhi\n", UCHAR_MAX + 2, UCHAR_MAX + 2); + printf ("printf (\"%%hi\", %i) = %hi\n", USHRT_MAX + 2, USHRT_MAX + 2); + + printf ("printf (\"%%1$hhu\", %2$u) = %1$hhu\n", + UCHAR_MAX + 2, UCHAR_MAX + 2); + printf ("printf (\"%%1$hu\", %2$u) = %1$hu\n", USHRT_MAX + 2, USHRT_MAX + 2); + printf ("printf (\"%%1$hhi\", %2$i) = %1$hhi\n", + UCHAR_MAX + 2, UCHAR_MAX + 2); + printf ("printf (\"%%1$hi\", %2$i) = %1$hi\n", USHRT_MAX + 2, USHRT_MAX + 2); puts ("--- Should be no further output. ---"); rfg1 (); diff --git a/stdio-common/tst-printf.sh b/stdio-common/tst-printf.sh index 3655558d16..f3091d2f96 100644 --- a/stdio-common/tst-printf.sh +++ b/stdio-common/tst-printf.sh @@ -1,6 +1,6 @@ #! /bin/sh # Testing of printf. -# Copyright (C) 2000, 2002 Free Software Foundation, Inc. +# Copyright (C) 2000, 2002, 2006 Free Software Foundation, Inc. # This file is part of the GNU C Library. # @@ -136,6 +136,12 @@ Test ok. sprintf (buf, "%07Lo", 040000000000ll) = 40000000000 printf ("%hhu", 257) = 1 printf ("%hu", 65537) = 1 +printf ("%hhi", 257) = 1 +printf ("%hi", 65537) = 1 +printf ("%1$hhu", 257) = 1 +printf ("%1$hu", 65537) = 1 +printf ("%1$hhi", 257) = 1 +printf ("%1$hi", 65537) = 1 --- Should be no further output. --- EOF cmp - ${common_objpfx}stdio-common/tst-printf.out > /dev/null 2>&1 || @@ -246,6 +252,12 @@ Test ok. sprintf (buf, "%07Lo", 040000000000ll) = 40000000000 printf ("%hhu", 257) = 1 printf ("%hu", 65537) = 1 +printf ("%hhi", 257) = 1 +printf ("%hi", 65537) = 1 +printf ("%1$hhu", 257) = 1 +printf ("%1$hu", 65537) = 1 +printf ("%1$hhi", 257) = 1 +printf ("%1$hi", 65537) = 1 --- Should be no further output. --- EOF cmp - ${common_objpfx}stdio-common/tst-printf.out > /dev/null 2>&1 || diff --git a/stdio-common/tst-put-error.c b/stdio-common/tst-put-error.c new file mode 100644 index 0000000000..115dbd509a --- /dev/null +++ b/stdio-common/tst-put-error.c @@ -0,0 +1,33 @@ +#include <errno.h> +#include <error.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + + +static int +do_test (void) +{ + char tmpl[] = "/tmp/tst-put-error.XXXXXX"; + int fd = mkstemp (tmpl); + if (fd == -1) + error (EXIT_FAILURE, errno, "cannot create temporary file"); + FILE *fp = fdopen (fd, "w"); + if (fp == NULL) + error (EXIT_FAILURE, errno, "fdopen"); + setlinebuf (fp); + close (fd); + unlink (tmpl); + int n = fprintf (fp, "hello world\n"); + printf ("fprintf = %d\n", n); + if (n >= 0) + error (EXIT_FAILURE, 0, "first fprintf succeeded"); + n = fprintf (fp, "hello world\n"); + printf ("fprintf = %d\n", n); + if (n >= 0) + error (EXIT_FAILURE, 0, "second fprintf succeeded"); + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/stdio-common/tst-sprintf.c b/stdio-common/tst-sprintf.c index c61d3b50e4..c04fef18f4 100644 --- a/stdio-common/tst-sprintf.c +++ b/stdio-common/tst-sprintf.c @@ -37,5 +37,26 @@ main (void) free (dst); } + if (sprintf (buf, "%1$d%3$.*2$s%4$d", 7, 67108863, "x", 8) != 3 + || strcmp (buf, "7x8") != 0) + { + printf ("sprintf (buf, \"%%1$d%%3$.*2$s%%4$d\", 7, 67108863, \"x\", 8) produced `%s' output", buf); + result = 1; + } + + if (sprintf (buf, "%67108863.16\"%d", 7) != 14 + || strcmp (buf, "%67108863.16\"7") != 0) + { + printf ("sprintf (buf, \"%%67108863.16\\\"%%d\", 7) produced `%s' output", buf); + result = 1; + } + + if (sprintf (buf, "%*\"%d", 0x3ffffff, 7) != 11 + || strcmp (buf, "%67108863\"7") != 0) + { + printf ("sprintf (buf, \"%%*\\\"%%d\", 0x3ffffff, 7) produced `%s' output", buf); + result = 1; + } + return result; } diff --git a/stdio-common/tst-sprintf2.c b/stdio-common/tst-sprintf2.c new file mode 100644 index 0000000000..debb68e21f --- /dev/null +++ b/stdio-common/tst-sprintf2.c @@ -0,0 +1,82 @@ +#include <float.h> +#include <math.h> +#include <stdio.h> +#include <string.h> + +int +main (void) +{ + volatile union { long double l; long long x[2]; } u, v; + char buf[64]; + int result = 0; + +#if LDBL_MANT_DIG == 106 || LDBL_MANT_DIG == 113 +# define COMPARE_LDBL(u, v) \ + ((u).l == (v).l && (u).x[0] == (v).x[0] && (u).x[1] == (v).x[1]) +#else +# define COMPARE_LDBL(u, v) ((u).l == (v).l) +#endif + +#define TEST(val) \ + do \ + { \ + u.l = (val); \ + snprintf (buf, sizeof buf, "%LaL", u.l); \ + if (strcmp (buf, #val) != 0) \ + { \ + printf ("Error on line %d: %s != %s\n", __LINE__, buf, #val); \ + result = 1; \ + } \ + if (sscanf (#val, "%La", &v.l) != 1 || !COMPARE_LDBL (u, v)) \ + { \ + printf ("Error sscanf on line %d: %La != %La\n", __LINE__, \ + u.l, v.l); \ + result = 1; \ + } \ + /* printf ("%s %La %016Lx %016Lx\n", #val, u.l, u.x[0], u.x[1]); */ \ + } \ + while (0) + +#if LDBL_MANT_DIG >= 106 +# if LDBL_MANT_DIG == 106 + TEST (0x0.ffffffffffffp-1022L); + TEST (0x0.ffffffffffff1p-1022L); + TEST (0x0.fffffffffffffp-1022L); +# endif + TEST (0x1p-1022L); + TEST (0x1.0000000000001p-1022L); + TEST (0x1.00000000001e7p-1022L); + TEST (0x1.fffffffffffffp-1022L); + TEST (0x1p-1021L); + TEST (0x1.00000000000008p-1021L); + TEST (0x1.0000000000001p-1021L); + TEST (0x1.00000000000018p-1021L); + TEST (0x1.0000000000000f8p-1017L); + TEST (0x1.0000000000001p-1017L); + TEST (0x1.000000000000108p-1017L); + TEST (0x1.000000000000dcf8p-1013L); + TEST (0x1.000000000000ddp-1013L); + TEST (0x1.000000000000dd08p-1013L); + TEST (0x1.ffffffffffffffffffffffffffp-1L); + TEST (0x1.ffffffffffffffffffffffffff8p-1L); + TEST (0x1p+0L); + TEST (0x1.000000000000000000000000008p+0L); + TEST (0x1.00000000000000000000000001p+0L); + TEST (0x1.000000000000000000000000018p+0L); + TEST (0x1.23456789abcdef123456789abc8p+0L); + TEST (0x1.23456789abcde7123456789abc8p+0L); + TEST (0x1.23456789abcdef123456789abc8p+64L); + TEST (0x1.23456789abcde7123456789abc8p+64L); + TEST (0x1.123456789abcdef123456789p-969L); +# if LDBL_MANT_DIG == 106 + TEST (-0x1.2d71957cc1263bbbeb1d365f1e8p-969L); + TEST (0x1.23456789abcdef0123456789abp-970L); + TEST (0x1.579bde02468acp-1001L); + TEST (0x0.abcdef0123456p-1022L); + TEST (0x1.abcdef0123456p-1022L); + TEST (0x1.abcdef012345678p-1014L); + TEST (0x1.abcdef0123456f8p-1014L); +# endif +#endif + return result; +} diff --git a/stdio-common/tstdiomisc.c b/stdio-common/tstdiomisc.c index 452a21f9cb..db038fa2b0 100644 --- a/stdio-common/tstdiomisc.c +++ b/stdio-common/tstdiomisc.c @@ -46,6 +46,9 @@ t2 (void) return result; } +volatile double nanval; + + static int F (void) { @@ -53,8 +56,9 @@ F (void) wchar_t wbuf[10]; int result; - snprintf (buf, sizeof buf, "%f %F", DBL_MAX * DBL_MAX - DBL_MAX * DBL_MAX, - DBL_MAX * DBL_MAX - DBL_MAX * DBL_MAX); + nanval = NAN; + + snprintf (buf, sizeof buf, "%f %F", nanval, nanval); result = strcmp (buf, "nan NAN") != 0; printf ("expected \"nan NAN\", got \"%s\"\n", buf); @@ -62,9 +66,7 @@ F (void) result |= strcmp (buf, "inf INF") != 0; printf ("expected \"inf INF\", got \"%s\"\n", buf); - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%f %F", - DBL_MAX * DBL_MAX - DBL_MAX * DBL_MAX, - DBL_MAX * DBL_MAX - DBL_MAX * DBL_MAX); + swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%f %F", nanval, nanval); result |= wcscmp (wbuf, L"nan NAN") != 0; printf ("expected L\"nan NAN\", got L\"%S\"\n", wbuf); diff --git a/stdio-common/tstscanf.c b/stdio-common/tstscanf.c index 44ddf49e15..123d733e3f 100644 --- a/stdio-common/tstscanf.c +++ b/stdio-common/tstscanf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991,92,96,97,98,99,2000,2001 Free Software Foundation, Inc. +/* Copyright (C) 1991,92,1996-2001,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -272,7 +272,7 @@ main (int argc, char **argv) res = sscanf ("0x1234", "%lf", &d); printf ("res = %d, d = %f\n", res, d); - if (res != 0 || d != 123456.789) + if (res != 1 || d != 4660) { fputs ("test failed!\n", stdout); result = 1; diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c index 832a6ed547..bf5227873b 100644 --- a/stdio-common/vfprintf.c +++ b/stdio-common/vfprintf.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1991-2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 1991-2002, 2003, 2004, 2005, 2006, 2007 + Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -64,7 +65,7 @@ #define UNBUFFERED_P(S) ((S)->_IO_file_flags & _IO_UNBUFFERED) #ifndef COMPILE_WPRINTF -# define vfprintf _IO_vfprintf +# define vfprintf _IO_vfprintf_internal # define CHAR_T char # define UCHAR_T unsigned char # define INT_T int @@ -257,7 +258,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) #define NOT_IN_JUMP_RANGE(Ch) ((Ch) < L_(' ') || (Ch) > L_('z')) #define CHAR_CLASS(Ch) (jump_table[(INT_T) (Ch) - L_(' ')]) -#if defined HAVE_SUBTRACT_LOCAL_LABELS && defined SHARED +#ifdef SHARED /* 'int' is enough and it saves some space on 64 bit systems. */ # define JUMP_TABLE_TYPE const int # define JUMP(ChExpr, table) \ @@ -529,14 +530,24 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) { \ if (is_long_num) \ signed_number = va_arg (ap, long int); \ - else /* `char' and `short int' will be promoted to `int'. */ \ + else if (is_char) \ + signed_number = (signed char) va_arg (ap, unsigned int); \ + else if (!is_short) \ signed_number = va_arg (ap, int); \ + else \ + signed_number = (short int) va_arg (ap, unsigned int); \ } \ else \ if (is_long_num) \ signed_number = args_value[fspec->data_arg].pa_long_int; \ - else /* `char' and `short int' will be promoted to `int'. */ \ + else if (is_char) \ + signed_number = (signed char) \ + args_value[fspec->data_arg].pa_u_int; \ + else if (!is_short) \ signed_number = args_value[fspec->data_arg].pa_int; \ + else \ + signed_number = (short int) \ + args_value[fspec->data_arg].pa_u_int; \ \ is_negative = signed_number < 0; \ number.word = is_negative ? (- signed_number) : signed_number; \ @@ -758,6 +769,9 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) \ if (fspec == NULL) \ { \ + if (__ldbl_is_dbl) \ + is_long_double = 0; \ + \ struct printf_info info = { .prec = prec, \ .width = width, \ .spec = spec, \ @@ -785,6 +799,11 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) else \ { \ ptr = (const void *) &args_value[fspec->data_arg]; \ + if (__ldbl_is_dbl) \ + { \ + fspec->data_arg_type = PA_DOUBLE; \ + fspec->info.is_long_double = 0; \ + } \ \ function_done = __printf_fp (s, &fspec->info, &ptr); \ } \ @@ -808,6 +827,9 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) \ if (fspec == NULL) \ { \ + if (__ldbl_is_dbl) \ + is_long_double = 0; \ + \ struct printf_info info = { .prec = prec, \ .width = width, \ .spec = spec, \ @@ -834,6 +856,8 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) else \ { \ ptr = (const void *) &args_value[fspec->data_arg]; \ + if (__ldbl_is_dbl) \ + fspec->info.is_long_double = 0; \ \ function_done = __printf_fphex (s, &fspec->info, &ptr); \ } \ @@ -1001,10 +1025,11 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) const char *mbs = (const char *) string; \ mbstate_t mbstate; \ \ - len = prec != -1 ? (size_t) prec : strlen (mbs); \ + len = prec != -1 ? __strnlen (mbs, (size_t) prec) : strlen (mbs); \ \ /* Allocate dynamically an array which definitely is long \ - enough for the wide character version. */ \ + enough for the wide character version. Each byte in the \ + multi-byte string can produce at most one wide character. */ \ if (__libc_use_alloca (len * sizeof (wchar_t))) \ string = (CHAR_T *) alloca (len * sizeof (wchar_t)); \ else if ((string = (CHAR_T *) malloc (len * sizeof (wchar_t))) \ @@ -1135,19 +1160,26 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) else \ { \ /* In case we have a multibyte character set the \ - situation is more compilcated. We must not copy \ + situation is more complicated. We must not copy \ bytes at the end which form an incomplete character. */\ - wchar_t ignore[prec]; \ + size_t ignore_size = (unsigned) prec > 1024 ? 1024 : prec;\ + wchar_t ignore[ignore_size]; \ const char *str2 = string; \ - mbstate_t ps; \ + const char *strend = string + prec; \ + if (strend < string) \ + strend = (const char *) UINTPTR_MAX; \ \ + mbstate_t ps; \ memset (&ps, '\0', sizeof (ps)); \ - if (__mbsnrtowcs (ignore, &str2, prec, prec, &ps) \ - == (size_t) -1) \ - { \ - done = -1; \ - goto all_done; \ - } \ + \ + while (str2 != NULL && str2 < strend) \ + if (__mbsnrtowcs (ignore, &str2, strend - str2, \ + ignore_size, &ps) == (size_t) -1) \ + { \ + done = -1; \ + goto all_done; \ + } \ + \ if (str2 == NULL) \ len = strlen (string); \ else \ @@ -1283,7 +1315,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) /* Process whole format string. */ do { -#if defined HAVE_SUBTRACT_LOCAL_LABELS && defined SHARED +#ifdef SHARED # define REF(Name) &&do_##Name - &&do_form_unknown #else # define REF(Name) &&do_##Name @@ -1594,6 +1626,8 @@ do_positional: /* Just a counter. */ size_t cnt; + free (workstart); + workstart = NULL; if (grouping == (const char *) -1) { @@ -1704,7 +1738,15 @@ do_positional: T (PA_INT|PA_FLAG_LONG_LONG, pa_long_long_int, long long int); T (PA_FLOAT, pa_double, double); /* Promoted. */ T (PA_DOUBLE, pa_double, double); - T (PA_DOUBLE|PA_FLAG_LONG_DOUBLE, pa_long_double, long double); + case PA_DOUBLE|PA_FLAG_LONG_DOUBLE: + if (__ldbl_is_dbl) + { + args_value[cnt].pa_double = va_arg (ap_save, double); + args_type[cnt] &= ~PA_FLAG_LONG_DOUBLE; + } + else + args_value[cnt].pa_long_double = va_arg (ap_save, long double); + break; T (PA_STRING, pa_string, const char *); T (PA_WSTRING, pa_wstring, const wchar_t *); T (PA_POINTER, pa_pointer, void *); @@ -1726,7 +1768,7 @@ do_positional: for (; (size_t) nspecs_done < nspecs; ++nspecs_done) { #undef REF -#if defined HAVE_SUBTRACT_LOCAL_LABELS && defined SHARED +#ifdef SHARED # define REF(Name) &&do2_##Name - &&do_form_unknown #else # define REF(Name) &&do2_##Name @@ -1760,7 +1802,9 @@ do_positional: int use_outdigits = specs[nspecs_done].info.i18n; char pad = specs[nspecs_done].info.pad; CHAR_T spec = specs[nspecs_done].info.spec; - CHAR_T *workstart = NULL; + + workstart = NULL; + workend = &work_buffer[sizeof (work_buffer) / sizeof (CHAR_T)]; /* Fill in last information. */ if (specs[nspecs_done].width_arg != -1) @@ -1856,8 +1900,7 @@ do_positional: break; } - if (__builtin_expect (workstart != NULL, 0)) - free (workstart); + free (workstart); workstart = NULL; /* Write the following constant string. */ @@ -1885,7 +1928,7 @@ printf_unknown (FILE *s, const struct printf_info *info, { int done = 0; - CHAR_T work_buffer[MAX (info->width, info->spec) + 32]; + CHAR_T work_buffer[MAX (sizeof (info->width), sizeof (info->prec)) * 3]; CHAR_T *const workend = &work_buffer[sizeof (work_buffer) / sizeof (CHAR_T)]; register CHAR_T *w; @@ -2154,25 +2197,11 @@ buffered_vfprintf (register _IO_FILE *s, const CHAR_T *format, } #undef vfprintf -#ifdef strong_alias -/* This is for glibc. */ -# ifdef COMPILE_WPRINTF +#ifdef COMPILE_WPRINTF strong_alias (_IO_vfwprintf, __vfwprintf); -weak_alias (_IO_vfwprintf, vfwprintf); -# else -strong_alias (_IO_vfprintf, vfprintf); -libc_hidden_def (vfprintf) -INTDEF(_IO_vfprintf) -# endif +ldbl_weak_alias (_IO_vfwprintf, vfwprintf); #else -# if defined __ELF__ || defined __GNU_LIBRARY__ -# include <gnu-stabs.h> -# ifdef weak_alias -# ifdef COMPILE_WPRINTF -weak_alias (_IO_vfwprintf, vfwprintf); -# else -weak_alias (_IO_vfprintf, vfprintf); -# endif -# endif -# endif +ldbl_strong_alias (_IO_vfprintf_internal, vfprintf); +ldbl_hidden_def (_IO_vfprintf_internal, vfprintf) +ldbl_strong_alias (_IO_vfprintf_internal, _IO_vfprintf); #endif diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c index c641d2d371..6671602291 100644 --- a/stdio-common/vfscanf.c +++ b/stdio-common/vfscanf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 1991-2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -144,11 +144,6 @@ if (done == 0) done = EOF; \ goto errout; \ } while (0) -#define memory_error() do { \ - __set_errno (ENOMEM); \ - done = EOF; \ - goto errout; \ - } while (0) #define ARGCHECK(s, format) \ do \ { \ @@ -178,18 +173,12 @@ Return the number of assignments made, or -1 for an input error. */ #ifdef COMPILE_WSCANF int -_IO_vfwscanf (s, format, argptr, errp) - _IO_FILE *s; - const wchar_t *format; - _IO_va_list argptr; - int *errp; +_IO_vfwscanf (_IO_FILE *s, const wchar_t *format, _IO_va_list argptr, + int *errp) #else int -_IO_vfscanf (s, format, argptr, errp) - _IO_FILE *s; - const char *format; - _IO_va_list argptr; - int *errp; +_IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, + int *errp) #endif { va_list arg; @@ -360,7 +349,7 @@ _IO_vfscanf (s, format, argptr, errp) do { c = inchar (); - if (c == EOF) + if (__builtin_expect (c == EOF, 0)) input_error (); else if (c != (unsigned char) *f++) { @@ -388,7 +377,7 @@ _IO_vfscanf (s, format, argptr, errp) c = inchar (); /* Characters other than format specs must just match. */ - if (c == EOF) + if (__builtin_expect (c == EOF, 0)) input_error (); /* We saw white space char as the last character in the format @@ -396,12 +385,12 @@ _IO_vfscanf (s, format, argptr, errp) if (skip_space) { while (ISSPACE (c)) - if (inchar () == EOF) + if (__builtin_expect (inchar () == EOF, 0)) input_error (); skip_space = 0; } - if (c != fc) + if (__builtin_expect (c != fc, 0)) { ungetc (c, s); conv_error (); @@ -537,7 +526,7 @@ _IO_vfscanf (s, format, argptr, errp) } /* End of the format string? */ - if (*f == L_('\0')) + if (__builtin_expect (*f == L_('\0'), 0)) conv_error (); /* Find the conversion specifier. */ @@ -549,7 +538,7 @@ _IO_vfscanf (s, format, argptr, errp) int save_errno = errno; errno = 0; do - if (inchar () == EOF && errno == EINTR) + if (__builtin_expect (inchar () == EOF && errno == EINTR, 0)) input_error (); while (ISSPACE (c)); errno = save_errno; @@ -561,9 +550,9 @@ _IO_vfscanf (s, format, argptr, errp) { case L_('%'): /* Must match a literal '%'. */ c = inchar (); - if (c == EOF) + if (__builtin_expect (c == EOF, 0)) input_error (); - if (c != fc) + if (__builtin_expect (c != fc, 0)) { ungetc_not_eof (c, s); conv_error (); @@ -629,7 +618,7 @@ _IO_vfscanf (s, format, argptr, errp) } c = inchar (); - if (c == EOF) + if (__builtin_expect (c == EOF, 0)) input_error (); if (width == -1) @@ -645,7 +634,7 @@ _IO_vfscanf (s, format, argptr, errp) size_t n; n = __wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state); - if (n == (size_t) -1) + if (__builtin_expect (n == (size_t) -1, 0)) /* No valid wide character. */ input_error (); @@ -680,7 +669,7 @@ _IO_vfscanf (s, format, argptr, errp) } c = inchar (); - if (c == EOF) + if (__builtin_expect (c == EOF, 0)) input_error (); #ifdef COMPILE_WSCANF @@ -718,14 +707,14 @@ _IO_vfscanf (s, format, argptr, errp) { /* Possibly correct character, just not enough input. */ - if (inchar () == EOF) + if (__builtin_expect (inchar () == EOF, 0)) encode_error (); buf[0] = c; continue; } - if (n != 1) + if (__builtin_expect (n != 1, 0)) encode_error (); /* We have a match. */ @@ -769,7 +758,7 @@ _IO_vfscanf (s, format, argptr, errp) STRING_ARG (str, char); c = inchar (); - if (c == EOF) + if (__builtin_expect (c == EOF, 0)) input_error (); #ifdef COMPILE_WSCANF @@ -832,7 +821,7 @@ _IO_vfscanf (s, format, argptr, errp) n = __wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state); - if (n == (size_t) -1) + if (__builtin_expect (n == (size_t) -1, 0)) encode_error (); assert (n <= MB_CUR_MAX); @@ -940,7 +929,7 @@ _IO_vfscanf (s, format, argptr, errp) STRING_ARG (wstr, wchar_t); c = inchar (); - if (c == EOF) + if (__builtin_expect (c == EOF, 0)) input_error (); #ifndef COMPILE_WSCANF @@ -1015,14 +1004,14 @@ _IO_vfscanf (s, format, argptr, errp) { /* Possibly correct character, just not enough input. */ - if (inchar () == EOF) + if (__builtin_expect (inchar () == EOF, 0)) encode_error (); buf[0] = c; continue; } - if (n != 1) + if (__builtin_expect (n != 1, 0)) encode_error (); /* We have a match. */ @@ -1117,7 +1106,7 @@ _IO_vfscanf (s, format, argptr, errp) number: c = inchar (); - if (c == EOF) + if (__builtin_expect (c == EOF, 0)) input_error (); /* Check for a sign. */ @@ -1156,7 +1145,7 @@ _IO_vfscanf (s, format, argptr, errp) if (base == 0) base = 10; - if (base == 10 && (flags & I18N) != 0) + if (base == 10 && __builtin_expect ((flags & I18N) != 0, 0)) { int from_level; int to_level; @@ -1516,12 +1505,14 @@ _IO_vfscanf (s, format, argptr, errp) { /* There was no number. If we are supposed to read a pointer we must recognize "(nil)" as well. */ - if (wpsize == 0 && read_pointer && (width < 0 || width >= 0) - && c == '(' - && TOLOWER (inchar ()) == L_('n') - && TOLOWER (inchar ()) == L_('i') - && TOLOWER (inchar ()) == L_('l') - && inchar () == L_(')')) + if (__builtin_expect (wpsize == 0 + && read_pointer + && (width < 0 || width >= 0) + && c == '(' + && TOLOWER (inchar ()) == L_('n') + && TOLOWER (inchar ()) == L_('i') + && TOLOWER (inchar ()) == L_('l') + && inchar () == L_(')'), 1)) /* We must produce the value of a NULL pointer. A single '0' digit is enough. */ ADDW (L_('0')); @@ -1554,7 +1545,7 @@ _IO_vfscanf (s, format, argptr, errp) else num.ul = __strtoul_internal (wp, &tw, base, flags & GROUP); } - if (wp == tw) + if (__builtin_expect (wp == tw, 0)) conv_error (); if (!(flags & SUPPRESS)) @@ -1599,21 +1590,23 @@ _IO_vfscanf (s, format, argptr, errp) case L_('a'): case L_('A'): c = inchar (); - if (c == EOF) + if (__builtin_expect (c == EOF, 0)) input_error (); + got_dot = got_e = 0; + /* Check for a sign. */ if (c == L_('-') || c == L_('+')) { negative = c == L_('-'); - if (width == 0 || inchar () == EOF) + if (__builtin_expect (width == 0 || inchar () == EOF, 0)) /* EOF is only an input error before we read any chars. */ conv_error (); if (! ISDIGIT (c) && TOLOWER (c) != L_('i') && TOLOWER (c) != L_('n')) { #ifdef COMPILE_WSCANF - if (c != decimal) + if (__builtin_expect (c != decimal, 0)) { /* This is no valid number. */ ungetc (c, s); @@ -1629,17 +1622,16 @@ _IO_vfscanf (s, format, argptr, errp) const char *cmpp = decimal; int avail = width > 0 ? width : INT_MAX; - while ((unsigned char) *cmpp == c && avail > 0) + while ((unsigned char) *cmpp == c && avail-- > 0) if (*++cmpp == '\0') break; else { if (inchar () == EOF) break; - --avail; } - if (*cmpp != '\0') + if (__builtin_expect (*cmpp != '\0', 0)) { /* This is no valid number. */ while (1) @@ -1652,6 +1644,17 @@ _IO_vfscanf (s, format, argptr, errp) conv_error (); } + else + { + /* Add all the characters. */ + for (cmpp = decimal; *cmpp != '\0'; ++cmpp) + ADDW ((unsigned char) *cmpp); + if (width > 0) + width = avail; + got_dot = 1; + + c = inchar (); + } if (width > 0) width = avail; #endif @@ -1667,12 +1670,16 @@ _IO_vfscanf (s, format, argptr, errp) { /* Maybe "nan". */ ADDW (c); - if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('a')) + if (__builtin_expect (width == 0 + || inchar () == EOF + || TOLOWER (c) != L_('a'), 0)) conv_error (); if (width > 0) --width; ADDW (c); - if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('n')) + if (__builtin_expect (width == 0 + || inchar () == EOF + || TOLOWER (c) != L_('n'), 0)) conv_error (); if (width > 0) --width; @@ -1684,12 +1691,16 @@ _IO_vfscanf (s, format, argptr, errp) { /* Maybe "inf" or "infinity". */ ADDW (c); - if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('n')) + if (__builtin_expect (width == 0 + || inchar () == EOF + || TOLOWER (c) != L_('n'), 0)) conv_error (); if (width > 0) --width; ADDW (c); - if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('f')) + if (__builtin_expect (width == 0 + || inchar () == EOF + || TOLOWER (c) != L_('f'), 0)) conv_error (); if (width > 0) --width; @@ -1703,26 +1714,30 @@ _IO_vfscanf (s, format, argptr, errp) --width; /* Now we have to read the rest as well. */ ADDW (c); - if (width == 0 || inchar () == EOF - || TOLOWER (c) != L_('n')) + if (__builtin_expect (width == 0 + || inchar () == EOF + || TOLOWER (c) != L_('n'), 0)) conv_error (); if (width > 0) --width; ADDW (c); - if (width == 0 || inchar () == EOF - || TOLOWER (c) != L_('i')) + if (__builtin_expect (width == 0 + || inchar () == EOF + || TOLOWER (c) != L_('i'), 0)) conv_error (); if (width > 0) --width; ADDW (c); - if (width == 0 || inchar () == EOF - || TOLOWER (c) != L_('t')) + if (__builtin_expect (width == 0 + || inchar () == EOF + || TOLOWER (c) != L_('t'), 0)) conv_error (); if (width > 0) --width; ADDW (c); - if (width == 0 || inchar () == EOF - || TOLOWER (c) != L_('y')) + if (__builtin_expect (width == 0 + || inchar () == EOF + || TOLOWER (c) != L_('y'), 0)) conv_error (); if (width > 0) --width; @@ -1759,7 +1774,6 @@ _IO_vfscanf (s, format, argptr, errp) } } - got_dot = got_e = 0; do { if (ISDIGIT (c)) @@ -1873,20 +1887,20 @@ _IO_vfscanf (s, format, argptr, errp) /* Have we read any character? If we try to read a number in hexadecimal notation and we have read only the `0x' - prefix or no exponent this is an error. */ - if (wpsize == 0 || (is_hexa && (wpsize == 2 || ! got_e))) + prefix this is an error. */ + if (__builtin_expect (wpsize == 0 || (is_hexa && wpsize == 2), 0)) conv_error (); scan_float: /* Convert the number. */ ADDW (L_('\0')); - if (flags & LONGDBL) + if ((flags & LONGDBL) && !__ldbl_is_dbl) { long double d = __strtold_internal (wp, &tw, flags & GROUP); if (!(flags & SUPPRESS) && tw != wp) *ARG (long double *) = negative ? -d : d; } - else if (flags & LONG) + else if (flags & (LONG | LONGDBL)) { double d = __strtod_internal (wp, &tw, flags & GROUP); if (!(flags & SUPPRESS) && tw != wp) @@ -1899,7 +1913,7 @@ _IO_vfscanf (s, format, argptr, errp) *ARG (float *) = negative ? -d : d; } - if (tw == wp) + if (__builtin_expect (tw == wp, 0)) conv_error (); if (!(flags & SUPPRESS)) @@ -1939,7 +1953,7 @@ _IO_vfscanf (s, format, argptr, errp) while ((fc = *f++) != L'\0' && fc != L']'); - if (fc == L'\0') + if (__builtin_expect (fc == L'\0', 0)) conv_error (); wp = (wchar_t *) f - 1; #else @@ -1975,7 +1989,7 @@ _IO_vfscanf (s, format, argptr, errp) /* Add the character to the flag map. */ wp[fc] = 1; - if (fc == '\0') + if (__builtin_expect (fc == '\0', 0)) conv_error(); #endif @@ -1983,7 +1997,7 @@ _IO_vfscanf (s, format, argptr, errp) { size_t now = read_in; #ifdef COMPILE_WSCANF - if (inchar () == WEOF) + if (__builtin_expect (inchar () == WEOF, 0)) input_error (); do @@ -2088,7 +2102,7 @@ _IO_vfscanf (s, format, argptr, errp) size_t cnt = 0; mbstate_t cstate; - if (inchar () == EOF) + if (__builtin_expect (inchar () == EOF, 0)) input_error (); memset (&cstate, '\0', sizeof (cstate)); @@ -2165,13 +2179,13 @@ _IO_vfscanf (s, format, argptr, errp) } while (inchar () != EOF); - if (cnt != 0) + if (__builtin_expect (cnt != 0, 0)) /* We stopped in the middle of recognizing another character. That's a problem. */ encode_error (); #endif - if (now == read_in) + if (__builtin_expect (now == read_in, 0)) /* We haven't succesfully read any character. */ conv_error (); @@ -2196,7 +2210,7 @@ _IO_vfscanf (s, format, argptr, errp) { size_t now = read_in; - if (inchar () == EOF) + if (__builtin_expect (inchar () == EOF, 0)) input_error (); #ifdef COMPILE_WSCANF @@ -2298,7 +2312,7 @@ _IO_vfscanf (s, format, argptr, errp) } n = __wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state); - if (n == (size_t) -1) + if (__builtin_expect (n == (size_t) -1, 0)) encode_error (); assert (n <= MB_CUR_MAX); @@ -2355,7 +2369,7 @@ _IO_vfscanf (s, format, argptr, errp) while (--width > 0 && inchar () != EOF); #endif - if (now == read_in) + if (__builtin_expect (now == read_in, 0)) /* We haven't succesfully read any character. */ conv_error (); @@ -2449,18 +2463,15 @@ __vfwscanf (FILE *s, const wchar_t *format, va_list argptr) { return _IO_vfwscanf (s, format, argptr, NULL); } +ldbl_weak_alias (__vfwscanf, vfwscanf) #else int -__vfscanf (FILE *s, const char *format, va_list argptr) +___vfscanf (FILE *s, const char *format, va_list argptr) { - return INTUSE(_IO_vfscanf) (s, format, argptr, NULL); + return _IO_vfscanf_internal (s, format, argptr, NULL); } -libc_hidden_def (__vfscanf) -#endif - -#ifdef COMPILE_WSCANF -weak_alias (__vfwscanf, vfwscanf) -#else -weak_alias (__vfscanf, vfscanf) -INTDEF(_IO_vfscanf) +ldbl_strong_alias (_IO_vfscanf_internal, _IO_vfscanf) +ldbl_strong_alias (___vfscanf, __vfscanf) +ldbl_hidden_def (___vfscanf, __vfscanf) +ldbl_weak_alias (___vfscanf, vfscanf) #endif diff --git a/stdio-common/vprintf.c b/stdio-common/vprintf.c index a8c4a53cd8..5c9cac494a 100644 --- a/stdio-common/vprintf.c +++ b/stdio-common/vprintf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1993, 1995, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1991, 1993, 1995, 1997, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -19,15 +19,16 @@ #include <stdarg.h> #undef __OPTIMIZE__ /* Avoid inline `vprintf' function. */ #include <stdio.h> +#include <libioP.h> #undef vprintf /* 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; +__vprintf (const char *format, __gnuc_va_list arg) { return vfprintf (stdout, format, arg); } + +ldbl_strong_alias (__vprintf, vprintf) |