libprelude/master: Use posix version of GnuLib snprintf/vsnprintf module
[email protected] Tue, 16 Mar 2010 15:51:57 +0100 (CET)
| Newsgroups | gmane.comp.security.ids.prelude.cvs |
|---|---|
| Message-ID | <[email protected]> |
--===============1472291964296053651== Content-type: text commit 5245209e041a9f3e51b844ec91ece07a1c608190 Author: Yoann Vandoorselaere <[email protected]> Date: Mon Feb 8 11:18:30 2010 +0100 Use posix version of GnuLib snprintf/vsnprintf module Prelude user can now rely on C99 format definition when using prelude-string. ======================================== libmissing/Makefile.am | 185 ++- libmissing/fpucw.h | 107 ++ libmissing/frexp.c | 166 ++ libmissing/frexpl.c | 18 + libmissing/isnan.c | 173 ++ libmissing/isnand-nolibm.h | 33 + libmissing/isnand.c | 19 + libmissing/isnanf-nolibm.h | 33 + libmissing/isnanf.c | 20 + libmissing/isnanl-nolibm.h | 33 + libmissing/isnanl.c | 20 + libmissing/m4/exponentd.m4 | 114 ++ libmissing/m4/exponentf.m4 | 91 + libmissing/m4/exponentl.m4 | 97 + libmissing/m4/fpieee.m4 | 52 + libmissing/m4/frexp.m4 | 146 ++ libmissing/m4/frexpl.m4 | 186 ++ libmissing/m4/getdelim.m4 | 65 +- libmissing/m4/getline.m4 | 38 +- libmissing/m4/gettimeofday.m4 | 61 +- libmissing/m4/gnulib-cache.m4 | 6 +- libmissing/m4/gnulib-comp.m4 | 80 + libmissing/m4/isnand.m4 | 95 + libmissing/m4/isnanf.m4 | 179 ++ libmissing/m4/isnanl.m4 | 245 +++ libmissing/m4/ldexpl.m4 | 88 + libmissing/m4/math_h.m4 | 128 ++ libmissing/m4/nocrash.m4 | 102 + libmissing/m4/printf-frexp.m4 | 45 + libmissing/m4/printf-frexpl.m4 | 64 + libmissing/m4/regex.m4 | 7 + libmissing/m4/signbit.m4 | 287 +++ libmissing/m4/snprintf-posix.m4 | 126 ++ libmissing/m4/stdio_h.m4 | 3 +- libmissing/m4/sys_time_h.m4 | 44 +- libmissing/m4/vsnprintf-posix.m4 | 127 ++ libmissing/math.in.h | 633 +++++++ libmissing/printf-frexp.c | 188 ++ libmissing/printf-frexp.h | 23 + libmissing/printf-frexpl.c | 18 + libmissing/printf-frexpl.h | 23 + libmissing/regcomp.c | 15 +- libmissing/signbitd.c | 64 + libmissing/signbitf.c | 64 + libmissing/signbitl.c | 64 + libmissing/stdio.in.h | 6 +- libmissing/sys_time.in.h | 16 +- libmissing/tests/Makefile.am | 102 + libmissing/tests/ignore-value.h | 37 + libmissing/tests/nan.h | 60 + libmissing/tests/test-frexp.c | 199 ++ libmissing/tests/test-frexpl.c | 223 +++ libmissing/tests/test-getdelim.c | 19 +- libmissing/tests/test-getline.c | 19 +- libmissing/tests/test-gettimeofday.c | 8 +- libmissing/tests/test-isnand-nolibm.c | 22 + libmissing/tests/test-isnand.h | 65 + libmissing/tests/test-isnanf-nolibm.c | 21 + libmissing/tests/test-isnanf.h | 67 + libmissing/tests/test-isnanl-nolibm.c | 23 + libmissing/tests/test-isnanl.h | 141 ++ libmissing/tests/test-lstat.c | 3 +- libmissing/tests/test-math.c | 53 + libmissing/tests/test-poll.c | 2 +- libmissing/tests/test-printf-frexp.c | 119 ++ libmissing/tests/test-printf-frexpl.c | 134 ++ libmissing/tests/test-signbit.c | 197 ++ libmissing/tests/test-snprintf-posix.c | 38 + libmissing/tests/test-snprintf-posix.h | 3113 +++++++++++++++++++++++++++++++ libmissing/tests/test-symlink.c | 3 +- libmissing/tests/test-vsnprintf-posix.c | 51 + 71 files changed, 9026 insertions(+), 90 deletions(-) ======================================== diff --git a/libmissing/Makefile.am b/libmissing/Makefile.am index a8c4cbf..eead8a8 100644 --- a/libmissing/Makefile.am +++ b/libmissing/Makefile.am @@ -9,7 +9,7 @@ # the same distribution terms as the rest of that program. # # Generated by gnulib-tool. -# Reproduce by: gnulib-tool --import --dir=. --lib=libmissing --source-base=libmissing --m4-base=libmissing/m4 --doc-base=libmissing/doc --tests-base=libmissing/tests --aux-dir=. --with-tests --lgpl --libtool --macro-prefix=gl --no-vc-files accept bind close cond connect dup2 fclose fopen ftw getaddrinfo getpass getsockname gettimeofday inet_ntop inet_pton ioctl listen lock lseek memmem minmax pathmax perror poll regex relocatable-lib-lgpl select setsockopt sigprocmask sleep snprintf socket socklen strcase strcasestr strdup strerror strndup strptime strsep sys_stat thread time_r timegm tls uname vsnprintf write +# Reproduce by: gnulib-tool --import --dir=. --lib=libmissing --source-base=libmissing --m4-base=libmissing/m4 --doc-base=libmissing/doc --tests-base=libmissing/tests --aux-dir=. --with-tests --lgpl --libtool --macro-prefix=gl --no-vc-files accept bind close cond connect dup2 fclose fopen ftw getaddrinfo getpass getsockname gettimeofday inet_ntop inet_pton ioctl listen lock lseek memmem minmax pathmax perror poll regex relocatable-lib-lgpl select setsockopt sigprocmask sleep snprintf-posix socket socklen strcase strcasestr strdup strerror strndup strptime strsep sys_stat thread time_r timegm tls uname vsnprintf-posix write AUTOMAKE_OPTIONS = 1.5 gnits subdir-objects @@ -330,6 +330,31 @@ EXTRA_libmissing_la_SOURCES += fopen.c ## end gnulib module fopen +## begin gnulib module fpucw + + +EXTRA_DIST += fpucw.h + +## end gnulib module fpucw + +## begin gnulib module frexp-nolibm + + +EXTRA_DIST += frexp.c + +EXTRA_libmissing_la_SOURCES += frexp.c + +## end gnulib module frexp-nolibm + +## begin gnulib module frexpl-nolibm + + +EXTRA_DIST += frexp.c frexpl.c + +EXTRA_libmissing_la_SOURCES += frexp.c frexpl.c + +## end gnulib module frexpl-nolibm + ## begin gnulib module fseeko @@ -459,6 +484,33 @@ EXTRA_libmissing_la_SOURCES += ioctl.c ## end gnulib module ioctl +## begin gnulib module isnand-nolibm + + +EXTRA_DIST += float+.h isnan.c isnand-nolibm.h isnand.c + +EXTRA_libmissing_la_SOURCES += isnan.c isnand.c + +## end gnulib module isnand-nolibm + +## begin gnulib module isnanf-nolibm + + +EXTRA_DIST += float+.h isnan.c isnanf-nolibm.h isnanf.c + +EXTRA_libmissing_la_SOURCES += isnan.c isnanf.c + +## end gnulib module isnanf-nolibm + +## begin gnulib module isnanl-nolibm + + +EXTRA_DIST += float+.h isnan.c isnanl-nolibm.h isnanl.c + +EXTRA_libmissing_la_SOURCES += isnan.c isnanl.c + +## end gnulib module isnanl-nolibm + ## begin gnulib module langinfo BUILT_SOURCES += langinfo.h @@ -603,6 +655,101 @@ EXTRA_libmissing_la_SOURCES += malloc.c ## end gnulib module malloc-posix +## begin gnulib module math + +BUILT_SOURCES += math.h + +# We need the following in order to create <math.h> when the system +# doesn't have one that works with the given compiler. +math.h: math.in.h $(WARN_ON_USE_H) $(ARG_NONNULL_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''INCLUDE_NEXT_AS_FIRST_DIRECTIVE''@|$(INCLUDE_NEXT_AS_FIRST_DIRECTIVE)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''NEXT_AS_FIRST_DIRECTIVE_MATH_H''@|$(NEXT_AS_FIRST_DIRECTIVE_MATH_H)|g' \ + -e 's|@''GNULIB_ACOSL''@|$(GNULIB_ACOSL)|g' \ + -e 's|@''GNULIB_ASINL''@|$(GNULIB_ASINL)|g' \ + -e 's|@''GNULIB_ATANL''@|$(GNULIB_ATANL)|g' \ + -e 's|@''GNULIB_CEILF''@|$(GNULIB_CEILF)|g' \ + -e 's|@''GNULIB_CEILL''@|$(GNULIB_CEILL)|g' \ + -e 's|@''GNULIB_COSL''@|$(GNULIB_COSL)|g' \ + -e 's|@''GNULIB_EXPL''@|$(GNULIB_EXPL)|g' \ + -e 's|@''GNULIB_FLOORF''@|$(GNULIB_FLOORF)|g' \ + -e 's|@''GNULIB_FLOORL''@|$(GNULIB_FLOORL)|g' \ + -e 's|@''GNULIB_FREXP''@|$(GNULIB_FREXP)|g' \ + -e 's|@''GNULIB_FREXPL''@|$(GNULIB_FREXPL)|g' \ + -e 's|@''GNULIB_ISFINITE''@|$(GNULIB_ISFINITE)|g' \ + -e 's|@''GNULIB_ISINF''@|$(GNULIB_ISINF)|g' \ + -e 's|@''GNULIB_ISNAN''@|$(GNULIB_ISNAN)|g' \ + -e 's|@''GNULIB_ISNANF''@|$(GNULIB_ISNANF)|g' \ + -e 's|@''GNULIB_ISNAND''@|$(GNULIB_ISNAND)|g' \ + -e 's|@''GNULIB_ISNANL''@|$(GNULIB_ISNANL)|g' \ + -e 's|@''GNULIB_LDEXPL''@|$(GNULIB_LDEXPL)|g' \ + -e 's|@''GNULIB_LOGL''@|$(GNULIB_LOGL)|g' \ + -e 's|@''GNULIB_ROUND''@|$(GNULIB_ROUND)|g' \ + -e 's|@''GNULIB_ROUNDF''@|$(GNULIB_ROUNDF)|g' \ + -e 's|@''GNULIB_ROUNDL''@|$(GNULIB_ROUNDL)|g' \ + -e 's|@''GNULIB_SIGNBIT''@|$(GNULIB_SIGNBIT)|g' \ + -e 's|@''GNULIB_SINL''@|$(GNULIB_SINL)|g' \ + -e 's|@''GNULIB_SQRTL''@|$(GNULIB_SQRTL)|g' \ + -e 's|@''GNULIB_TANL''@|$(GNULIB_TANL)|g' \ + -e 's|@''GNULIB_TRUNC''@|$(GNULIB_TRUNC)|g' \ + -e 's|@''GNULIB_TRUNCF''@|$(GNULIB_TRUNCF)|g' \ + -e 's|@''GNULIB_TRUNCL''@|$(GNULIB_TRUNCL)|g' \ + -e 's|@''HAVE_ACOSL''@|$(HAVE_ACOSL)|g' \ + -e 's|@''HAVE_ASINL''@|$(HAVE_ASINL)|g' \ + -e 's|@''HAVE_ATANL''@|$(HAVE_ATANL)|g' \ + -e 's|@''HAVE_COSL''@|$(HAVE_COSL)|g' \ + -e 's|@''HAVE_EXPL''@|$(HAVE_EXPL)|g' \ + -e 's|@''HAVE_ISNANF''@|$(HAVE_ISNANF)|g' \ + -e 's|@''HAVE_ISNAND''@|$(HAVE_ISNAND)|g' \ + -e 's|@''HAVE_ISNANL''@|$(HAVE_ISNANL)|g' \ + -e 's|@''HAVE_LOGL''@|$(HAVE_LOGL)|g' \ + -e 's|@''HAVE_SINL''@|$(HAVE_SINL)|g' \ + -e 's|@''HAVE_SQRTL''@|$(HAVE_SQRTL)|g' \ + -e 's|@''HAVE_TANL''@|$(HAVE_TANL)|g' \ + -e 's|@''HAVE_DECL_ACOSL''@|$(HAVE_DECL_ACOSL)|g' \ + -e 's|@''HAVE_DECL_ASINL''@|$(HAVE_DECL_ASINL)|g' \ + -e 's|@''HAVE_DECL_ATANL''@|$(HAVE_DECL_ATANL)|g' \ + -e 's|@''HAVE_DECL_COSL''@|$(HAVE_DECL_COSL)|g' \ + -e 's|@''HAVE_DECL_EXPL''@|$(HAVE_DECL_EXPL)|g' \ + -e 's|@''HAVE_DECL_FREXPL''@|$(HAVE_DECL_FREXPL)|g' \ + -e 's|@''HAVE_DECL_LDEXPL''@|$(HAVE_DECL_LDEXPL)|g' \ + -e 's|@''HAVE_DECL_LOGL''@|$(HAVE_DECL_LOGL)|g' \ + -e 's|@''HAVE_DECL_SINL''@|$(HAVE_DECL_SINL)|g' \ + -e 's|@''HAVE_DECL_SQRTL''@|$(HAVE_DECL_SQRTL)|g' \ + -e 's|@''HAVE_DECL_TANL''@|$(HAVE_DECL_TANL)|g' \ + -e 's|@''HAVE_DECL_TRUNC''@|$(HAVE_DECL_TRUNC)|g' \ + -e 's|@''HAVE_DECL_TRUNCF''@|$(HAVE_DECL_TRUNCF)|g' \ + -e 's|@''REPLACE_CEILF''@|$(REPLACE_CEILF)|g' \ + -e 's|@''REPLACE_CEILL''@|$(REPLACE_CEILL)|g' \ + -e 's|@''REPLACE_FLOORF''@|$(REPLACE_FLOORF)|g' \ + -e 's|@''REPLACE_FLOORL''@|$(REPLACE_FLOORL)|g' \ + -e 's|@''REPLACE_FREXP''@|$(REPLACE_FREXP)|g' \ + -e 's|@''REPLACE_FREXPL''@|$(REPLACE_FREXPL)|g' \ + -e 's|@''REPLACE_HUGE_VAL''@|$(REPLACE_HUGE_VAL)|g' \ + -e 's|@''REPLACE_ISFINITE''@|$(REPLACE_ISFINITE)|g' \ + -e 's|@''REPLACE_ISINF''@|$(REPLACE_ISINF)|g' \ + -e 's|@''REPLACE_ISNAN''@|$(REPLACE_ISNAN)|g' \ + -e 's|@''REPLACE_LDEXPL''@|$(REPLACE_LDEXPL)|g' \ + -e 's|@''REPLACE_NAN''@|$(REPLACE_NAN)|g' \ + -e 's|@''REPLACE_ROUND''@|$(REPLACE_ROUND)|g' \ + -e 's|@''REPLACE_ROUNDF''@|$(REPLACE_ROUNDF)|g' \ + -e 's|@''REPLACE_ROUNDL''@|$(REPLACE_ROUNDL)|g' \ + -e 's|@''REPLACE_SIGNBIT''@|$(REPLACE_SIGNBIT)|g' \ + -e 's|@''REPLACE_SIGNBIT_USING_GCC''@|$(REPLACE_SIGNBIT_USING_GCC)|g' \ + -e 's|@''REPLACE_TRUNCL''@|$(REPLACE_TRUNCL)|g' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/math.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += math.h math.h-t + +EXTRA_DIST += math.in.h + +## end gnulib module math + ## begin gnulib module mbrtowc @@ -752,6 +899,24 @@ EXTRA_libmissing_la_SOURCES += poll.c ## end gnulib module poll +## begin gnulib module printf-frexp + +libmissing_la_SOURCES += printf-frexp.c + +EXTRA_DIST += printf-frexp.h + +## end gnulib module printf-frexp + +## begin gnulib module printf-frexpl + +libmissing_la_SOURCES += printf-frexpl.c + +EXTRA_DIST += printf-frexp.c printf-frexpl.h + +EXTRA_libmissing_la_SOURCES += printf-frexp.c + +## end gnulib module printf-frexpl + ## begin gnulib module realloc-posix @@ -830,6 +995,15 @@ EXTRA_DIST += signal.in.h ## end gnulib module signal +## begin gnulib module signbit + + +EXTRA_DIST += float+.h signbitd.c signbitf.c signbitl.c + +EXTRA_libmissing_la_SOURCES += signbitd.c signbitf.c signbitl.c + +## end gnulib module signbit + ## begin gnulib module sigprocmask @@ -1046,6 +1220,7 @@ stdio.h: stdio.in.h $(WARN_ON_USE_H) $(ARG_NONNULL_H) -e 's|@''REPLACE_FSEEKO''@|$(REPLACE_FSEEKO)|g' \ -e 's|@''REPLACE_FTELL''@|$(REPLACE_FTELL)|g' \ -e 's|@''REPLACE_FTELLO''@|$(REPLACE_FTELLO)|g' \ + -e 's|@''REPLACE_GETDELIM''@|$(REPLACE_GETDELIM)|g' \ -e 's|@''REPLACE_GETLINE''@|$(REPLACE_GETLINE)|g' \ -e 's|@''REPLACE_OBSTACK_PRINTF''@|$(REPLACE_OBSTACK_PRINTF)|g' \ -e 's|@''REPLACE_PERROR''@|$(REPLACE_PERROR)|g' \ @@ -1508,11 +1683,11 @@ EXTRA_DIST += sys_stat.in.h ## begin gnulib module sys_time -BUILT_SOURCES += $(SYS_TIME_H) +BUILT_SOURCES += sys/time.h # We need the following in order to create <sys/time.h> when the system # doesn't have one that works with the given compiler. -sys/time.h: sys_time.in.h $(ARG_NONNULL_H) +sys/time.h: sys_time.in.h $(WARN_ON_USE_H) $(ARG_NONNULL_H) $(AM_V_at)$(MKDIR_P) sys $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ @@ -1520,9 +1695,11 @@ sys/time.h: sys_time.in.h $(ARG_NONNULL_H) -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ -e 's|@''NEXT_SYS_TIME_H''@|$(NEXT_SYS_TIME_H)|g' \ - -e 's/@''REPLACE_GETTIMEOFDAY''@/$(REPLACE_GETTIMEOFDAY)/g' \ + -e 's/@''GNULIB_GETTIMEOFDAY''@/$(GNULIB_GETTIMEOFDAY)/g' \ -e 's/@''HAVE_STRUCT_TIMEVAL''@/$(HAVE_STRUCT_TIMEVAL)/g' \ + -e 's/@''REPLACE_GETTIMEOFDAY''@/$(REPLACE_GETTIMEOFDAY)/g' \ -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ < $(srcdir)/sys_time.in.h; \ } > $@-t && \ mv $@-t $@ diff --git a/libmissing/fpucw.h b/libmissing/fpucw.h new file mode 100644 index 0000000..dbbe363 --- /dev/null +++ b/libmissing/fpucw.h @@ -0,0 +1,107 @@ +/* Manipulating the FPU control word. + Copyright (C) 2007-2010 Free Software Foundation, Inc. + Written by Bruno Haible <[email protected]>, 2007. + + This program 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that 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 this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef _FPUCW_H +#define _FPUCW_H + +/* The i386 floating point hardware (the 387 compatible FPU, not the modern + SSE/SSE2 hardware) has a controllable rounding precision. It is specified + through the 'PC' bits in the FPU control word ('fctrl' register). (See + the GNU libc i386 <fpu_control.h> header for details.) + + On some platforms, such as Linux or Solaris, the default precision setting + is set to "extended precision". This means that 'long double' instructions + operate correctly, but 'double' computations often produce slightly + different results as on strictly IEEE 754 conforming systems. + + On some platforms, such as NetBSD, the default precision is set to + "double precision". This means that 'long double' instructions will operate + only as 'double', i.e. lead wrong results. + + The FPU control word is under control of the application, i.e. it is + not required to be set either way by the ABI. (In fact, the i386 ABI + http://refspecs.freestandards.org/elf/abi386-4.pdf page 3-12 = page 38 + is not clear about it. But in any case, gcc treats the control word + like a "preserved" register: it emits code that assumes that the control + word is preserved across calls, and it restores the control word at the + end of functions that modify it.) + + See Vincent Lefèvre's page http://www.vinc17.org/research/extended.en.html + for a good explanation. + See http://www.uwsg.iu.edu/hypermail/linux/kernel/0103.0/0453.html for + some argumentation which setting should be the default. */ + +/* This header file provides the following facilities: + fpucw_t integral type holding the value of 'fctrl' + FPU_PC_MASK bit mask denoting the precision control + FPU_PC_DOUBLE precision control for 53 bits mantissa + FPU_PC_EXTENDED precision control for 64 bits mantissa + GET_FPUCW () yields the current FPU control word + SET_FPUCW (word) sets the FPU control word + DECL_LONG_DOUBLE_ROUNDING variable declaration for + BEGIN/END_LONG_DOUBLE_ROUNDING + BEGIN_LONG_DOUBLE_ROUNDING () starts a sequence of instructions with + 'long double' safe operation precision + END_LONG_DOUBLE_ROUNDING () ends a sequence of instructions with + 'long double' safe operation precision + */ + +/* Inline assembler like this works only with GNU C. */ +#if (defined __i386__ || defined __x86_64__) && defined __GNUC__ + +typedef unsigned short fpucw_t; /* glibc calls this fpu_control_t */ + +# define FPU_PC_MASK 0x0300 +# define FPU_PC_DOUBLE 0x200 /* glibc calls this _FPU_DOUBLE */ +# define FPU_PC_EXTENDED 0x300 /* glibc calls this _FPU_EXTENDED */ + +# define GET_FPUCW() \ + ({ fpucw_t _cw; \ + __asm__ __volatile__ ("fnstcw %0" : "=m" (*&_cw)); \ + _cw; \ + }) +# define SET_FPUCW(word) \ + (void)({ fpucw_t _ncw = (word); \ + __asm__ __volatile__ ("fldcw %0" : : "m" (*&_ncw)); \ + }) + +# define DECL_LONG_DOUBLE_ROUNDING \ + fpucw_t oldcw; +# define BEGIN_LONG_DOUBLE_ROUNDING() \ + (void)(oldcw = GET_FPUCW (), \ + SET_FPUCW ((oldcw & ~FPU_PC_MASK) | FPU_PC_EXTENDED)) +# define END_LONG_DOUBLE_ROUNDING() \ + SET_FPUCW (oldcw) + +#else + +typedef unsigned int fpucw_t; + +# define FPU_PC_MASK 0 +# define FPU_PC_DOUBLE 0 +# define FPU_PC_EXTENDED 0 + +# define GET_FPUCW() 0 +# define SET_FPUCW(word) (void)(word) + +# define DECL_LONG_DOUBLE_ROUNDING +# define BEGIN_LONG_DOUBLE_ROUNDING() +# define END_LONG_DOUBLE_ROUNDING() + +#endif + +#endif /* _FPUCW_H */ diff --git a/libmissing/frexp.c b/libmissing/frexp.c new file mode 100644 index 0000000..5828d62 --- /dev/null +++ b/libmissing/frexp.c @@ -0,0 +1,166 @@ +/* Split a double into fraction and mantissa. + Copyright (C) 2007-2010 Free Software Foundation, Inc. + + This program 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that 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 this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Paolo Bonzini <[email protected]>, 2003, and + Bruno Haible <[email protected]>, 2007. */ + +#include <config.h> + +/* Specification. */ +#include <math.h> + +#include <float.h> +#ifdef USE_LONG_DOUBLE +# include "isnanl-nolibm.h" +# include "fpucw.h" +#else +# include "isnand-nolibm.h" +#endif + +/* This file assumes FLT_RADIX = 2. If FLT_RADIX is a power of 2 greater + than 2, or not even a power of 2, some rounding errors can occur, so that + then the returned mantissa is only guaranteed to be <= 1.0, not < 1.0. */ + +#ifdef USE_LONG_DOUBLE +# define FUNC frexpl +# define DOUBLE long double +# define ISNAN isnanl +# define DECL_ROUNDING DECL_LONG_DOUBLE_ROUNDING +# define BEGIN_ROUNDING() BEGIN_LONG_DOUBLE_ROUNDING () +# define END_ROUNDING() END_LONG_DOUBLE_ROUNDING () +# define L_(literal) literal##L +#else +# define FUNC frexp +# define DOUBLE double +# define ISNAN isnand +# define DECL_ROUNDING +# define BEGIN_ROUNDING() +# define END_ROUNDING() +# define L_(literal) literal +#endif + +DOUBLE +FUNC (DOUBLE x, int *expptr) +{ + int sign; + int exponent; + DECL_ROUNDING + + /* Test for NaN, infinity, and zero. */ + if (ISNAN (x) || x + x == x) + { + *expptr = 0; + return x; + } + + sign = 0; + if (x < 0) + { + x = - x; + sign = -1; + } + + BEGIN_ROUNDING (); + + { + /* Since the exponent is an 'int', it fits in 64 bits. Therefore the + loops are executed no more than 64 times. */ + DOUBLE pow2[64]; /* pow2[i] = 2^2^i */ + DOUBLE powh[64]; /* powh[i] = 2^-2^i */ + int i; + + exponent = 0; + if (x >= L_(1.0)) + { + /* A positive exponent. */ + DOUBLE pow2_i; /* = pow2[i] */ + DOUBLE powh_i; /* = powh[i] */ + + /* Invariants: pow2_i = 2^2^i, powh_i = 2^-2^i, + x * 2^exponent = argument, x >= 1.0. */ + for (i = 0, pow2_i = L_(2.0), powh_i = L_(0.5); + ; + i++, pow2_i = pow2_i * pow2_i, powh_i = powh_i * powh_i) + { + if (x >= pow2_i) + { + exponent += (1 << i); + x *= powh_i; + } + else + break; + + pow2[i] = pow2_i; + powh[i] = powh_i; + } + /* Avoid making x too small, as it could become a denormalized + number and thus lose precision. */ + while (i > 0 && x < pow2[i - 1]) + { + i--; + powh_i = powh[i]; + } + exponent += (1 << i); + x *= powh_i; + /* Here 2^-2^i <= x < 1.0. */ + } + else + { + /* A negative or zero exponent. */ + DOUBLE pow2_i; /* = pow2[i] */ + DOUBLE powh_i; /* = powh[i] */ + + /* Invariants: pow2_i = 2^2^i, powh_i = 2^-2^i, + x * 2^exponent = argument, x < 1.0. */ + for (i = 0, pow2_i = L_(2.0), powh_i = L_(0.5); + ; + i++, pow2_i = pow2_i * pow2_i, powh_i = powh_i * powh_i) + { + if (x < powh_i) + { + exponent -= (1 << i); + x *= pow2_i; + } + else + break; + + pow2[i] = pow2_i; + powh[i] = powh_i; + } + /* Here 2^-2^i <= x < 1.0. */ + } + + /* Invariants: x * 2^exponent = argument, and 2^-2^i <= x < 1.0. */ + while (i > 0) + { + i--; + if (x < powh[i]) + { + exponent -= (1 << i); + x *= pow2[i]; + } + } + /* Here 0.5 <= x < 1.0. */ + } + + if (sign < 0) + x = - x; + + END_ROUNDING (); + + *expptr = exponent; + return x; +} diff --git a/libmissing/frexpl.c b/libmissing/frexpl.c new file mode 100644 index 0000000..9cf9bf6 --- /dev/null +++ b/libmissing/frexpl.c @@ -0,0 +1,18 @@ +/* Split a 'long double' into fraction and mantissa. + Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc. + + This program 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that 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 this program. If not, see <http://www.gnu.org/licenses/>. */ + +#define USE_LONG_DOUBLE +#include "frexp.c" diff --git a/libmissing/isnan.c b/libmissing/isnan.c new file mode 100644 index 0000000..a59dea7 --- /dev/null +++ b/libmissing/isnan.c @@ -0,0 +1,173 @@ +/* Test for NaN that does not need libm. + Copyright (C) 2007-2010 Free Software Foundation, Inc. + + This program 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that 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 this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <[email protected]>, 2007. */ + +#include <config.h> + +/* Specification. */ +#ifdef USE_LONG_DOUBLE +/* Specification found in math.h or isnanl-nolibm.h. */ +extern int rpl_isnanl (long double x); +#elif ! defined USE_FLOAT +/* Specification found in math.h or isnand-nolibm.h. */ +extern int rpl_isnand (double x); +#else /* defined USE_FLOAT */ +/* Specification found in math.h or isnanf-nolibm.h. */ +extern int rpl_isnanf (float x); +#endif + +#include <float.h> +#include <string.h> + +#include "float+.h" + +#ifdef USE_LONG_DOUBLE +# define FUNC rpl_isnanl +# define DOUBLE long double +# define MAX_EXP LDBL_MAX_EXP +# define MIN_EXP LDBL_MIN_EXP +# if defined LDBL_EXPBIT0_WORD && defined LDBL_EXPBIT0_BIT +# define KNOWN_EXPBIT0_LOCATION +# define EXPBIT0_WORD LDBL_EXPBIT0_WORD +# define EXPBIT0_BIT LDBL_EXPBIT0_BIT +# endif +# define SIZE SIZEOF_LDBL +# define L_(literal) literal##L +#elif ! defined USE_FLOAT +# define FUNC rpl_isnand +# define DOUBLE double +# define MAX_EXP DBL_MAX_EXP +# define MIN_EXP DBL_MIN_EXP +# if defined DBL_EXPBIT0_WORD && defined DBL_EXPBIT0_BIT +# define KNOWN_EXPBIT0_LOCATION +# define EXPBIT0_WORD DBL_EXPBIT0_WORD +# define EXPBIT0_BIT DBL_EXPBIT0_BIT +# endif +# define SIZE SIZEOF_DBL +# define L_(literal) literal +#else /* defined USE_FLOAT */ +# define FUNC rpl_isnanf +# define DOUBLE float +# define MAX_EXP FLT_MAX_EXP +# define MIN_EXP FLT_MIN_EXP +# if defined FLT_EXPBIT0_WORD && defined FLT_EXPBIT0_BIT +# define KNOWN_EXPBIT0_LOCATION +# define EXPBIT0_WORD FLT_EXPBIT0_WORD +# define EXPBIT0_BIT FLT_EXPBIT0_BIT +# endif +# define SIZE SIZEOF_FLT +# define L_(literal) literal##f +#endif + +#define EXP_MASK ((MAX_EXP - MIN_EXP) | 7) + +#define NWORDS \ + ((sizeof (DOUBLE) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) +typedef union { DOUBLE value; unsigned int word[NWORDS]; } memory_double; + +int +FUNC (DOUBLE x) +{ +#ifdef KNOWN_EXPBIT0_LOCATION +# if defined USE_LONG_DOUBLE && ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_)) + /* Special CPU dependent code is needed to treat bit patterns outside the + IEEE 754 specification (such as Pseudo-NaNs, Pseudo-Infinities, + Pseudo-Zeroes, Unnormalized Numbers, and Pseudo-Denormals) as NaNs. + These bit patterns are: + - exponent = 0x0001..0x7FFF, mantissa bit 63 = 0, + - exponent = 0x0000, mantissa bit 63 = 1. + The NaN bit pattern is: + - exponent = 0x7FFF, mantissa >= 0x8000000000000001. */ + memory_double m; + unsigned int exponent; + + m.value = x; + exponent = (m.word[EXPBIT0_WORD] >> EXPBIT0_BIT) & EXP_MASK; +# ifdef WORDS_BIGENDIAN + /* Big endian: EXPBIT0_WORD = 0, EXPBIT0_BIT = 16. */ + if (exponent == 0) + return 1 & (m.word[0] >> 15); + else if (exponent == EXP_MASK) + return (((m.word[0] ^ 0x8000U) << 16) | m.word[1] | (m.word[2] >> 16)) != 0; + else + return 1 & ~(m.word[0] >> 15); +# else + /* Little endian: EXPBIT0_WORD = 2, EXPBIT0_BIT = 0. */ + if (exponent == 0) + return (m.word[1] >> 31); + else if (exponent == EXP_MASK) + return ((m.word[1] ^ 0x80000000U) | m.word[0]) != 0; + else + return (m.word[1] >> 31) ^ 1; +# endif +# else + /* Be careful to not do any floating-point operation on x, such as x == x, + because x may be a signaling NaN. */ +# if defined __SUNPRO_C || defined __DECC || (defined __sgi && !defined __GNUC__) + /* The Sun C 5.0 compilers and the Compaq (ex-DEC) 6.4 compilers don't + recognize the initializers as constant expressions. The latter compiler + also fails when constant-folding 0.0 / 0.0 even when constant-folding is + not required. The SGI MIPSpro C compiler complains about "floating-point + operation result is out of range". */ + static DOUBLE zero = L_(0.0); + memory_double nan; + DOUBLE plus_inf = L_(1.0) / L_(0.0); + DOUBLE minus_inf = -L_(1.0) / L_(0.0); + nan.value = zero / zero; +# else + static memory_double nan = { L_(0.0) / L_(0.0) }; + static DOUBLE plus_inf = L_(1.0) / L_(0.0); + static DOUBLE minus_inf = -L_(1.0) / L_(0.0); +# endif + { + memory_double m; + + /* A NaN can be recognized through its exponent. But exclude +Infinity and + -Infinity, which have the same exponent. */ + m.value = x; + if (((m.word[EXPBIT0_WORD] ^ nan.word[EXPBIT0_WORD]) + & (EXP_MASK << EXPBIT0_BIT)) + == 0) + return (memcmp (&m.value, &plus_inf, SIZE) != 0 + && memcmp (&m.value, &minus_inf, SIZE) != 0); + else + return 0; + } +# endif +#else + /* The configuration did not find sufficient information. Give up about + the signaling NaNs, handle only the quiet NaNs. */ + if (x == x) + { +# if defined USE_LONG_DOUBLE && ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_)) + /* Detect any special bit patterns that pass ==; see comment above. */ + memory_double m1; + memory_double m2; + + memset (&m1.value, 0, SIZE); + memset (&m2.value, 0, SIZE); + m1.value = x; + m2.value = x + (x ? 0.0L : -0.0L); + if (memcmp (&m1.value, &m2.value, SIZE) != 0) + return 1; +# endif + return 0; + } + else + return 1; +#endif +} diff --git a/libmissing/isnand-nolibm.h b/libmissing/isnand-nolibm.h new file mode 100644 index 0000000..cc1d476 --- /dev/null +++ b/libmissing/isnand-nolibm.h @@ -0,0 +1,33 @@ +/* Test for NaN that does not need libm. + Copyright (C) 2007-2010 Free Software Foundation, Inc. + + This program 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that 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 this program. If not, see <http://www.gnu.org/licenses/>. */ + +#if HAVE_ISNAND_IN_LIBC +/* Get declaration of isnan macro. */ +# include <math.h> +# if __GNUC__ >= 4 + /* GCC 4.0 and newer provides three built-ins for isnan. */ +# undef isnand +# define isnand(x) __builtin_isnan ((double)(x)) +# else +# undef isnand +# define isnand(x) isnan ((double)(x)) +# endif +#else +/* Test whether X is a NaN. */ +# undef isnand +# define isnand rpl_isnand +extern int isnand (double x); +#endif diff --git a/libmissing/isnand.c b/libmissing/isnand.c new file mode 100644 index 0000000..f7a1565 --- /dev/null +++ b/libmissing/isnand.c @@ -0,0 +1,19 @@ +/* Test for NaN that does not need libm. + Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + + This program 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that 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 this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <[email protected]>, 2008. */ + +#include "isnan.c" diff --git a/libmissing/isnanf-nolibm.h b/libmissing/isnanf-nolibm.h new file mode 100644 index 0000000..5e29207 --- /dev/null +++ b/libmissing/isnanf-nolibm.h @@ -0,0 +1,33 @@ +/* Test for NaN that does not need libm. + Copyright (C) 2007-2010 Free Software Foundation, Inc. + + This program 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that 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 this program. If not, see <http://www.gnu.org/licenses/>. */ + +#if HAVE_ISNANF_IN_LIBC +/* Get declaration of isnan macro or (older) isnanf function. */ +# include <math.h> +# if __GNUC__ >= 4 + /* GCC 4.0 and newer provides three built-ins for isnan. */ +# undef isnanf +# define isnanf(x) __builtin_isnanf ((float)(x)) +# elif defined isnan +# undef isnanf +# define isnanf(x) isnan ((float)(x)) +# endif +#else +/* Test whether X is a NaN. */ +# undef isnanf +# define isnanf rpl_isnanf +extern int isnanf (float x); +#endif diff --git a/libmissing/isnanf.c b/libmissing/isnanf.c new file mode 100644 index 0000000..a352fdb --- /dev/null +++ b/libmissing/isnanf.c @@ -0,0 +1,20 @@ +/* Test for NaN that does not need libm. + Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc. + + This program 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that 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 this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <[email protected]>, 2007. */ + +#define USE_FLOAT +#include "isnan.c" diff --git a/libmissing/isnanl-nolibm.h b/libmissing/isnanl-nolibm.h new file mode 100644 index 0000000..e89a7fe --- /dev/null +++ b/libmissing/isnanl-nolibm.h @@ -0,0 +1,33 @@ +/* Test for NaN that does not need libm. + Copyright (C) 2007-2010 Free Software Foundation, Inc. + + This program 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that 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 this program. If not, see <http://www.gnu.org/licenses/>. */ + +#if HAVE_ISNANL_IN_LIBC +/* Get declaration of isnan macro or (older) isnanl function. */ +# include <math.h> +# if __GNUC__ >= 4 + /* GCC 4.0 and newer provides three built-ins for isnan. */ +# undef isnanl +# define isnanl(x) __builtin_isnanl ((long double)(x)) +# elif defined isnan +# undef isnanl +# define isnanl(x) isnan ((long double)(x)) +# endif +#else +/* Test whether X is a NaN. */ +# undef isnanl +# define isnanl rpl_isnanl +extern int isnanl (long double x); +#endif diff --git a/libmissing/isnanl.c b/libmissing/isnanl.c new file mode 100644 index 0000000..b45fef0 --- /dev/null +++ b/libmissing/isnanl.c @@ -0,0 +1,20 @@ +/* Test for NaN that does not need libm. + Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc. + + This program 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that 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 this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <[email protected]>, 2007. */ + +#define USE_LONG_DOUBLE +#include "isnan.c" diff --git a/libmissing/m4/exponentd.m4 b/libmissing/m4/exponentd.m4 new file mode 100644 index 0000000..5d44d0e --- /dev/null +++ b/libmissing/m4/exponentd.m4 @@ -0,0 +1,114 @@ +# exponentd.m4 serial 1 +dnl Copyright (C) 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +AC_DEFUN([gl_DOUBLE_EXPONENT_LOCATION], +[ + AC_CACHE_CHECK([where to find the exponent in a 'double'], + [gl_cv_cc_double_expbit0], + [ + AC_TRY_RUN([ +#include <float.h> +#include <stddef.h> +#include <stdio.h> +#include <string.h> +#define NWORDS \ + ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) +typedef union { double value; unsigned int word[NWORDS]; } memory_double; +static unsigned int ored_words[NWORDS]; +static unsigned int anded_words[NWORDS]; +static void add_to_ored_words (double x) +{ + memory_double m; + size_t i; + /* Clear it first, in case sizeof (double) < sizeof (memory_double). */ + memset (&m, 0, sizeof (memory_double)); + m.value = x; + for (i = 0; i < NWORDS; i++) + { + ored_words[i] |= m.word[i]; + anded_words[i] &= m.word[i]; + } +} +int main () +{ + size_t j; + FILE *fp = fopen ("conftest.out", "w"); + if (fp == NULL) + return 1; + for (j = 0; j < NWORDS; j++) + anded_words[j] = ~ (unsigned int) 0; + add_to_ored_words (0.25); + add_to_ored_words (0.5); + add_to_ored_words (1.0); + add_to_ored_words (2.0); + add_to_ored_words (4.0); + /* Remove bits that are common (e.g. if representation of the first mantissa + bit is explicit). */ + for (j = 0; j < NWORDS; j++) + ored_words[j] &= ~anded_words[j]; + /* Now find the nonzero word. */ + for (j = 0; j < NWORDS; j++) + if (ored_words[j] != 0) + break; + if (j < NWORDS) + { + size_t i; + for (i = j + 1; i < NWORDS; i++) + if (ored_words[i] != 0) + { + fprintf (fp, "unknown"); + return (fclose (fp) != 0); + } + for (i = 0; ; i++) + if ((ored_words[j] >> i) & 1) + { + fprintf (fp, "word %d bit %d", (int) j, (int) i); + return (fclose (fp) != 0); + } + } + fprintf (fp, "unknown"); + return (fclose (fp) != 0); +} + ], + [gl_cv_cc_double_expbit0=`cat conftest.out`], + [gl_cv_cc_double_expbit0="unknown"], + [ + dnl On ARM, there are two 'double' floating-point formats, used by + dnl different sets of instructions: The older FPA instructions assume + dnl that they are stored in big-endian word order, while the words + dnl (like integer types) are stored in little-endian byte order. + dnl The newer VFP instructions assume little-endian order consistenly. + AC_EGREP_CPP([mixed_endianness], [ +#if defined arm || defined __arm || defined __arm__ + mixed_endianness +#endif + ], + [gl_cv_cc_double_expbit0="unknown"], + [ + pushdef([AC_MSG_CHECKING],[:])dnl + pushdef([AC_MSG_RESULT],[:])dnl + pushdef([AC_MSG_RESULT_UNQUOTED],[:])dnl + AC_C_BIGENDIAN( + [gl_cv_cc_double_expbit0="word 0 bit 20"], + [gl_cv_cc_double_expbit0="word 1 bit 20"], + [gl_cv_cc_double_expbit0="unknown"]) + popdef([AC_MSG_RESULT_UNQUOTED])dnl + popdef([AC_MSG_RESULT])dnl + popdef([AC_MSG_CHECKING])dnl + ]) + ]) + rm -f conftest.out + ]) + case "$gl_cv_cc_double_expbit0" in + word*bit*) + word=`echo "$gl_cv_cc_double_expbit0" | sed -e 's/word //' -e 's/ bit.*//'` + bit=`echo "$gl_cv_cc_double_expbit0" | sed -e 's/word.*bit //'` + AC_DEFINE_UNQUOTED([DBL_EXPBIT0_WORD], [$word], + [Define as the word index where to find the exponent of 'double'.]) + AC_DEFINE_UNQUOTED([DBL_EXPBIT0_BIT], [$bit], + [Define as the bit index in the word where to find bit 0 of the exponent of 'double'.]) + ;; + esac +]) diff --git a/libmissing/m4/exponentf.m4 b/libmissing/m4/exponentf.m4 new file mode 100644 index 0000000..4d8063f --- /dev/null +++ b/libmissing/m4/exponentf.m4 @@ -0,0 +1,91 @@ +# exponentf.m4 serial 1 +dnl Copyright (C) 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +AC_DEFUN([gl_FLOAT_EXPONENT_LOCATION], +[ + AC_CACHE_CHECK([where to find the exponent in a 'float'], + [gl_cv_cc_float_expbit0], + [ + AC_TRY_RUN([ +#include <float.h> +#include <stddef.h> +#include <stdio.h> +#include <string.h> +#define NWORDS \ + ((sizeof (float) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) +typedef union { float value; unsigned int word[NWORDS]; } memory_float; +static unsigned int ored_words[NWORDS]; +static unsigned int anded_words[NWORDS]; +static void add_to_ored_words (float x) +{ + memory_float m; + size_t i; + /* Clear it first, in case + sizeof (float) < sizeof (memory_float). */ + memset (&m, 0, sizeof (memory_float)); + m.value = x; + for (i = 0; i < NWORDS; i++) + { + ored_words[i] |= m.word[i]; + anded_words[i] &= m.word[i]; + } +} +int main () +{ + size_t j; + FILE *fp = fopen ("conftest.out", "w"); + if (fp == NULL) + return 1; + for (j = 0; j < NWORDS; j++) + anded_words[j] = ~ (unsigned int) 0; + add_to_ored_words (0.25f); + add_to_ored_words (0.5f); + add_to_ored_words (1.0f); + add_to_ored_words (2.0f); + add_to_ored_words (4.0f); + /* Remove bits that are common (e.g. if representation of the first mantissa + bit is explicit). */ + for (j = 0; j < NWORDS; j++) + ored_words[j] &= ~anded_words[j]; + /* Now find the nonzero word. */ + for (j = 0; j < NWORDS; j++) + if (ored_words[j] != 0) + break; + if (j < NWORDS) + { + size_t i; + for (i = j + 1; i < NWORDS; i++) + if (ored_words[i] != 0) + { + fprintf (fp, "unknown"); + return (fclose (fp) != 0); + } + for (i = 0; ; i++) + if ((ored_words[j] >> i) & 1) + { + fprintf (fp, "word %d bit %d", (int) j, (int) i); + return (fclose (fp) != 0); + } + } + fprintf (fp, "unknown"); + return (fclose (fp) != 0); +} + ], + [gl_cv_cc_float_expbit0=`cat conftest.out`], + [gl_cv_cc_float_expbit0="unknown"], + [gl_cv_cc_float_expbit0="word 0 bit 23"]) + rm -f conftest.out + ]) + case "$gl_cv_cc_float_expbit0" in + word*bit*) + word=`echo "$gl_cv_cc_float_expbit0" | sed -e 's/word //' -e 's/ bit.*//'` + bit=`echo "$gl_cv_cc_float_expbit0" | sed -e 's/word.*bit //'` + AC_DEFINE_UNQUOTED([FLT_EXPBIT0_WORD], [$word], + [Define as the word index where to find the exponent of 'float'.]) + AC_DEFINE_UNQUOTED([FLT_EXPBIT0_BIT], [$bit], + [Define as the bit index in the word where to find bit 0 of the exponent of 'float'.]) + ;; + esac +]) diff --git a/libmissing/m4/exponentl.m4 b/libmissing/m4/exponentl.m4 new file mode 100644 index 0000000..a700d3b --- /dev/null +++ b/libmissing/m4/exponentl.m4 @@ -0,0 +1,97 @@ +# exponentl.m4 serial 2 +dnl Copyright (C) 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +AC_DEFUN([gl_LONG_DOUBLE_EXPONENT_LOCATION], +[ + AC_REQUIRE([gl_BIGENDIAN]) + AC_CACHE_CHECK([where to find the exponent in a 'long double'], + [gl_cv_cc_long_double_expbit0], + [ + AC_TRY_RUN([ +#include <float.h> +#include <stddef.h> +#include <stdio.h> +#include <string.h> +#define NWORDS \ + ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) +typedef union { long double value; unsigned int word[NWORDS]; } + memory_long_double; +static unsigned int ored_words[NWORDS]; +static unsigned int anded_words[NWORDS]; +static void add_to_ored_words (long double x) +{ + memory_long_double m; + size_t i; + /* Clear it first, in case + sizeof (long double) < sizeof (memory_long_double). */ + memset (&m, 0, sizeof (memory_long_double)); + m.value = x; + for (i = 0; i < NWORDS; i++) + { + ored_words[i] |= m.word[i]; + anded_words[i] &= m.word[i]; + } +} +int main () +{ + size_t j; + FILE *fp = fopen ("conftest.out", "w"); + if (fp == NULL) + return 1; + for (j = 0; j < NWORDS; j++) + anded_words[j] = ~ (unsigned int) 0; + add_to_ored_words (0.25L); + add_to_ored_words (0.5L); + add_to_ored_words (1.0L); + add_to_ored_words (2.0L); + add_to_ored_words (4.0L); + /* Remove bits that are common (e.g. if representation of the first mantissa + bit is explicit). */ + for (j = 0; j < NWORDS; j++) + ored_words[j] &= ~anded_words[j]; + /* Now find the nonzero word. */ + for (j = 0; j < NWORDS; j++) + if (ored_words[j] != 0) + break; + if (j < NWORDS) + { + size_t i; + for (i = j + 1; i < NWORDS; i++) + if (ored_words[i] != 0) + { + fprintf (fp, "unknown"); + return (fclose (fp) != 0); + } + for (i = 0; ; i++) + if ((ored_words[j] >> i) & 1) + { + fprintf (fp, "word %d bit %d", (int) j, (int) i); + return (fclose (fp) != 0); + } + } + fprintf (fp, "unknown"); + return (fclose (fp) != 0); +} + ], + [gl_cv_cc_long_double_expbit0=`cat conftest.out`], + [gl_cv_cc_long_double_expbit0="unknown"], + [ + dnl When cross-compiling, we don't know. It depends on the + dnl ABI and compiler version. There are too many cases. + gl_cv_cc_long_double_expbit0="unknown" + ]) + rm -f conftest.out + ]) + case "$gl_cv_cc_long_double_expbit0" in + word*bit*) + word=`echo "$gl_cv_cc_long_double_expbit0" | sed -e 's/word //' -e 's/ bit.*//'` + bit=`echo "$gl_cv_cc_long_double_expbit0" | sed -e 's/word.*bit //'` + AC_DEFINE_UNQUOTED([LDBL_EXPBIT0_WORD], [$word], + [Define as the word index where to find the exponent of 'long double'.]) + AC_DEFINE_UNQUOTED([LDBL_EXPBIT0_BIT], [$bit], + [Define as the bit index in the word where to find bit 0 of the exponent of 'long double'.]) + ;; + esac +]) diff --git a/libmissing/m4/fpieee.m4 b/libmissing/m4/fpieee.m4 new file mode 100644 index 0000000..532802d --- /dev/null +++ b/libmissing/m4/fpieee.m4 @@ -0,0 +1,52 @@ +# fpieee.m4 serial 1 +dnl Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl IEEE 754 standardized three items: +dnl - The formats of single-float and double-float - nowadays commonly +dnl available as 'float' and 'double' in C and C++. +dnl No autoconf test needed. +dnl - The overflow and division by zero behaviour: The result are values +dnl '±Inf' and 'NaN', rather than exceptions as it was before. +dnl This file provides an autoconf macro for ensuring this behaviour of +dnl floating-point operations. +dnl - A set of conditions (overflow, underflow, inexact, etc.) which can +dnl be configured to trigger an exception. +dnl This cannot be done in a portable way: it depends on the compiler, +dnl libc, kernel, and CPU. No autoconf macro is provided for this. + +dnl Ensure non-trapping behaviour of floating-point overflow and +dnl floating-point division by zero. +dnl (For integer overflow, see gcc's -ftrapv option; for integer division by +dnl zero, see the autoconf macro in intdiv0.m4.) + +AC_DEFUN([gl_FP_IEEE], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) + # IEEE behaviour is the default on all CPUs except Alpha and SH + # (according to the test results of Bruno Haible's ieeefp/fenv_default.m4 + # and the GCC 4.1.2 manual). + case "$host_cpu" in + alpha*) + # On Alpha systems, a compiler option provides the behaviour. + # See the ieee(3) manual page, also available at + # <http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/V51B_HTML/MAN/MAN3/0600____.HTM> + if test -n "$GCC"; then + # GCC has the option -mieee. + CPPFLAGS="$CPPFLAGS -mieee" + else + # Compaq (ex-DEC) C has the option -ieee. + CPPFLAGS="$CPPFLAGS -ieee" + fi + ;; + sh*) + if test -n "$GCC"; then + # GCC has the option -mieee. + CPPFLAGS="$CPPFLAGS -mieee" + fi + ;; + esac +]) diff --git a/libmissing/m4/frexp.m4 b/libmissing/m4/frexp.m4 new file mode 100644 index 0000000..3a450f6 --- /dev/null +++ b/libmissing/m4/frexp.m4 @@ -0,0 +1,146 @@ +# frexp.m4 serial 7 +dnl Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_FREXP], +[ + AC_REQUIRE([gl_MATH_H_DEFAULTS]) + FREXP_LIBM= + AC_CACHE_CHECK([whether frexp() can be used without linking with libm], + [gl_cv_func_frexp_no_libm], + [ + AC_TRY_LINK([#include <math.h> + double x;], + [int e; return frexp (x, &e) > 0;], + [gl_cv_func_frexp_no_libm=yes], + [gl_cv_func_frexp_no_libm=no]) + ]) + if test $gl_cv_func_frexp_no_libm = no; then + AC_CACHE_CHECK([whether frexp() can be used with libm], + [gl_cv_func_frexp_in_libm], + [ + save_LIBS="$LIBS" + LIBS="$LIBS -lm" + AC_TRY_LINK([#include <math.h> + double x;], + [int e; return frexp (x, &e) > 0;], + [gl_cv_func_frexp_in_libm=yes], + [gl_cv_func_frexp_in_libm=no]) + LIBS="$save_LIBS" + ]) + if test $gl_cv_func_frexp_in_libm = yes; then + FREXP_LIBM=-lm + fi + fi + if test $gl_cv_func_frexp_no_libm = yes \ + || test $gl_cv_func_frexp_in_libm = yes; then + save_LIBS="$LIBS" + LIBS="$LIBS $FREXP_LIBM" + gl_FUNC_FREXP_WORKS + LIBS="$save_LIBS" + case "$gl_cv_func_frexp_works" in + *yes) gl_func_frexp=yes ;; + *) gl_func_frexp=no; REPLACE_FREXP=1; FREXP_LIBM= ;; + esac + else + gl_func_frexp=no + fi + if test $gl_func_frexp = yes; then + AC_DEFINE([HAVE_FREXP], [1], + [Define if the frexp() function is available and works.]) + else + AC_LIBOBJ([frexp]) + fi + AC_SUBST([FREXP_LIBM]) +]) + +AC_DEFUN([gl_FUNC_FREXP_NO_LIBM], +[ + AC_REQUIRE([gl_MATH_H_DEFAULTS]) + AC_CACHE_CHECK([whether frexp() can be used without linking with libm], + [gl_cv_func_frexp_no_libm], + [ + AC_TRY_LINK([#include <math.h> + double x;], + [int e; return frexp (x, &e) > 0;], + [gl_cv_func_frexp_no_libm=yes], + [gl_cv_func_frexp_no_libm=no]) + ]) + if test $gl_cv_func_frexp_no_libm = yes; then + gl_FUNC_FREXP_WORKS + case "$gl_cv_func_frexp_works" in + *yes) gl_func_frexp_no_libm=yes ;; + *) gl_func_frexp_no_libm=no; REPLACE_FREXP=1 ;; + esac + else + gl_func_frexp_no_libm=no + dnl Set REPLACE_FREXP here because the system may have frexp in libm. + REPLACE_FREXP=1 + fi + if test $gl_func_frexp_no_libm = yes; then + AC_DEFINE([HAVE_FREXP_IN_LIBC], [1], + [Define if the frexp() function is available in libc.]) + else + AC_LIBOBJ([frexp]) + fi +]) + +dnl Test whether frexp() works also on denormalized numbers (this fails e.g. on +dnl NetBSD 3.0), on infinite numbers (this fails e.g. on IRIX 6.5 and mingw), +dnl and on negative zero (this fails e.g. on NetBSD 4.99). +AC_DEFUN([gl_FUNC_FREXP_WORKS], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether frexp works], [gl_cv_func_frexp_works], + [ + AC_TRY_RUN([ +#include <float.h> +#include <math.h> +#include <string.h> +int main() +{ + int i; + volatile double x; +/* HP cc on HP-UX 10.20 has a bug with the constant expression -0.0. + So we use -zero instead. */ + double zero = 0.0; + /* Test on denormalized numbers. */ + for (i = 1, x = 1.0; i >= DBL_MIN_EXP; i--, x *= 0.5) + ; + if (x > 0.0) + { + int exp; + double y = frexp (x, &exp); + /* On machines with IEEE754 arithmetic: x = 1.11254e-308, exp = -1022. + On NetBSD: y = 0.75. Correct: y = 0.5. */ + if (y != 0.5) + return 1; + } + /* Test on infinite numbers. */ + x = 1.0 / 0.0; + { + int exp; + double y = frexp (x, &exp); + if (y != x) + return 1; + } + /* Test on negative zero. */ + x = -zero; + { + int exp; + double y = frexp (x, &exp); + if (memcmp (&y, &x, sizeof x)) + return 1; + } + return 0; +}], [gl_cv_func_frexp_works=yes], [gl_cv_func_frexp_works=no], + [case "$host_os" in + netbsd* | irix* | mingw*) gl_cv_func_frexp_works="guessing no";; + *) gl_cv_func_frexp_works="guessing yes";; + esac + ]) + ]) +]) diff --git a/libmissing/m4/frexpl.m4 b/libmissing/m4/frexpl.m4 new file mode 100644 index 0000000..0fbc893 --- /dev/null +++ b/libmissing/m4/frexpl.m4 @@ -0,0 +1,186 @@ +# frexpl.m4 serial 9 +dnl Copyright (C) 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_FREXPL], +[ + AC_REQUIRE([gl_MATH_H_DEFAULTS]) + FREXPL_LIBM= + AC_CACHE_CHECK([whether frexpl() can be used without linking with libm], + [gl_cv_func_frexpl_no_libm], + [ + AC_TRY_LINK([#include <math.h> + long double x;], + [int e; return frexpl (x, &e) > 0;], + [gl_cv_func_frexpl_no_libm=yes], + [gl_cv_func_frexpl_no_libm=no]) + ]) + if test $gl_cv_func_frexpl_no_libm = no; then + AC_CACHE_CHECK([whether frexpl() can be used with libm], + [gl_cv_func_frexpl_in_libm], + [ + save_LIBS="$LIBS" + LIBS="$LIBS -lm" + AC_TRY_LINK([#include <math.h> + long double x;], + [int e; return frexpl (x, &e) > 0;], + [gl_cv_func_frexpl_in_libm=yes], + [gl_cv_func_frexpl_in_libm=no]) + LIBS="$save_LIBS" + ]) + if test $gl_cv_func_frexpl_in_libm = yes; then + FREXPL_LIBM=-lm + fi + fi + if test $gl_cv_func_frexpl_no_libm = yes \ + || test $gl_cv_func_frexpl_in_libm = yes; then + save_LIBS="$LIBS" + LIBS="$LIBS $FREXPL_LIBM" + gl_FUNC_FREXPL_WORKS + LIBS="$save_LIBS" + case "$gl_cv_func_frexpl_works" in + *yes) gl_func_frexpl=yes ;; + *) gl_func_frexpl=no; REPLACE_FREXPL=1; FREXPL_LIBM= ;; + esac + else + gl_func_frexpl=no + fi + if test $gl_func_frexpl = yes; then + AC_DEFINE([HAVE_FREXPL], [1], + [Define if the frexpl() function is available.]) + dnl Also check whether it's declared. + dnl MacOS X 10.3 has frexpl() in libc but doesn't declare it in <math.h>. + AC_CHECK_DECL([frexpl], , [HAVE_DECL_FREXPL=0], [#include <math.h>]) + else + HAVE_DECL_FREXPL=0 + AC_LIBOBJ([frexpl]) + fi + AC_SUBST([FREXPL_LIBM]) +]) + +AC_DEFUN([gl_FUNC_FREXPL_NO_LIBM], +[ + AC_REQUIRE([gl_MATH_H_DEFAULTS]) + AC_CACHE_CHECK([whether frexpl() can be used without linking with libm], + [gl_cv_func_frexpl_no_libm], + [ + AC_TRY_LINK([#include <math.h> + long double x;], + [int e; return frexpl (x, &e) > 0;], + [gl_cv_func_frexpl_no_libm=yes], + [gl_cv_func_frexpl_no_libm=no]) + ]) + if test $gl_cv_func_frexpl_no_libm = yes; then + gl_FUNC_FREXPL_WORKS + case "$gl_cv_func_frexpl_works" in + *yes) gl_func_frexpl_no_libm=yes ;; + *) gl_func_frexpl_no_libm=no; REPLACE_FREXPL=1 ;; + esac + else + gl_func_frexpl_no_libm=no + dnl Set REPLACE_FREXPL here because the system may have frexpl in libm. + REPLACE_FREXPL=1 + fi + if test $gl_func_frexpl_no_libm = yes; then + AC_DEFINE([HAVE_FREXPL_IN_LIBC], [1], + [Define if the frexpl() function is available in libc.]) + dnl Also check whether it's declared. + dnl MacOS X 10.3 has frexpl() in libc but doesn't declare it in <math.h>. + AC_CHECK_DECL([frexpl], , [HAVE_DECL_FREXPL=0], [#include <math.h>]) + else + HAVE_DECL_FREXPL=0 + AC_LIBOBJ([frexpl]) + fi +]) + +dnl Test whether frexpl() works on finite numbers (this fails on +dnl MacOS X 10.4/PowerPC, on AIX 5.1, and on BeOS), on denormalized numbers +dnl (this fails on MacOS X 10.5/i386), and also on infinite numbers (this +dnl fails e.g. on IRIX 6.5 and mingw). +AC_DEFUN([gl_FUNC_FREXPL_WORKS], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether frexpl works], [gl_cv_func_frexpl_works], + [ + AC_TRY_RUN([ +#include <float.h> +#include <math.h> +/* Override the values of <float.h>, like done in float.in.h. */ +#if defined __i386__ && (defined __BEOS__ || defined __OpenBSD__) +# undef LDBL_MIN_EXP +# define LDBL_MIN_EXP (-16381) +#endif +extern long double frexpl (long double, int *); +int main() +{ + volatile long double x; + /* Test on finite numbers that fails on AIX 5.1. */ + x = 16.0L; + { + int exp = -9999; + frexpl (x, &exp); + if (exp != 5) + return 1; + } + /* Test on finite numbers that fails on MacOS X 10.4, because its frexpl + function returns an invalid (incorrectly normalized) value: it returns + y = { 0x3fe028f5, 0xc28f5c28, 0x3c9eb851, 0xeb851eb8 } + but the correct result is + 0.505L = { 0x3fe028f5, 0xc28f5c29, 0xbc547ae1, 0x47ae1480 } */ + x = 1.01L; + { + int exp = -9999; + long double y = frexpl (x, &exp); + if (!(exp == 1 && y == 0.505L)) + return 1; + } + /* Test on large finite numbers. This fails on BeOS at i = 16322, while + LDBL_MAX_EXP = 16384. + In the loop end test, we test x against Infinity, rather than comparing + i with LDBL_MAX_EXP, because BeOS <float.h> has a wrong LDBL_MAX_EXP. */ + { + int i; + for (i = 1, x = 1.0L; x != x + x; i++, x *= 2.0L) + { + int exp = -9999; + frexpl (x, &exp); + if (exp != i) + return 1; + } + } + /* Test on denormalized numbers. */ + { + int i; + for (i = 1, x = 1.0L; i >= LDBL_MIN_EXP; i--, x *= 0.5L) + ; + if (x > 0.0L) + { + int exp; + long double y = frexpl (x, &exp); + /* On machines with IEEE854 arithmetic: x = 1.68105e-4932, + exp = -16382, y = 0.5. On MacOS X 10.5: exp = -16384, y = 0.5. */ + if (exp != LDBL_MIN_EXP - 1) + return 1; + } + } + /* Test on infinite numbers. */ + x = 1.0L / 0.0L; + { + int exp; + long double y = frexpl (x, &exp); + if (y != x) + return 1; + } + return 0; +}], [gl_cv_func_frexpl_works=yes], [gl_cv_func_frexpl_works=no], + [case "$host_os" in + aix* | beos* | darwin* | irix* | mingw* | pw*) + gl_cv_func_frexpl_works="guessing no";; + *) gl_cv_func_frexpl_works="guessing yes";; + esac + ]) + ]) +]) diff --git a/libmissing/m4/getdelim.m4 b/libmissing/m4/getdelim.m4 index 9e5ad5b..4beb150 100644 --- a/libmissing/m4/getdelim.m4 +++ b/libmissing/m4/getdelim.m4 @@ -1,6 +1,6 @@ -# getdelim.m4 serial 5 +# getdelim.m4 serial 6 -dnl Copyright (C) 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc. +dnl Copyright (C) 2005-2007, 2009-2010 Free Software Foundation, Inc. dnl dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -15,16 +15,71 @@ AC_DEFUN([gl_FUNC_GETDELIM], dnl Persuade glibc <stdio.h> to declare getdelim(). AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) - AC_REPLACE_FUNCS([getdelim]) AC_CHECK_DECLS_ONCE([getdelim]) - if test $ac_cv_func_getdelim = no; then - gl_PREREQ_GETDELIM + AC_CHECK_FUNCS_ONCE([getdelim]) + if test $ac_cv_func_getdelim = yes; then + dnl Found it in some library. Verify that it works. + AC_CACHE_CHECK([for working getdelim function], [gl_cv_func_working_getdelim], + [echo fooNbarN | tr -d '\012' | tr N '\012' > conftest.data + AC_RUN_IFELSE([AC_LANG_SOURCE([[ +# include <stdio.h> +# include <stdlib.h> +# include <string.h> + int main () + { + FILE *in = fopen ("./conftest.data", "r"); + if (!in) + return 1; + { + /* Test result for a NULL buffer and a zero size. + Based on a test program from Karl Heuer. */ + char *line = NULL; + size_t siz = 0; + int len = getdelim (&line, &siz, '\n', in); + if (!(len == 4 && line && strcmp (line, "foo\n") == 0)) + return 1; + } + { + /* Test result for a NULL buffer and a non-zero size. + This crashes on FreeBSD 8.0. */ + char *line = NULL; + size_t siz = (size_t)(~0) / 4; + if (getdelim (&line, &siz, '\n', in) == -1) + return 1; + } + return 0; + } + ]])], [gl_cv_func_working_getdelim=yes] dnl The library version works. + , [gl_cv_func_working_getdelim=no] dnl The library version does NOT work. + , dnl We're cross compiling. Assume it works on glibc2 systems. + [AC_EGREP_CPP([Lucky GNU user], + [ +#include <features.h> +#ifdef __GNU_LIBRARY__ + #if (__GLIBC__ >= 2) + Lucky GNU user + #endif +#endif + ], + [gl_cv_func_working_getdelim=yes], + [gl_cv_func_working_getdelim=no])] + )]) + else + gl_cv_func_working_getdelim=no fi if test $ac_cv_have_decl_getdelim = no; then HAVE_DECL_GETDELIM=0 fi + + if test $gl_cv_func_working_getdelim = no; then + if test $ac_cv_func_getdelim = yes; then + REPLACE_GETDELIM=1 + fi + AC_LIBOBJ([getdelim]) + gl_PREREQ_GETDELIM + fi ]) # Prerequisites of lib/getdelim.c. diff --git a/libmissing/m4/getline.m4 b/libmissing/m4/getline.m4 index 5b8a712..8300560 100644 --- a/libmissing/m4/getline.m4 +++ b/libmissing/m4/getline.m4 @@ -1,4 +1,4 @@ -# getline.m4 serial 20 +# getline.m4 serial 21 dnl Copyright (C) 1998-2003, 2005-2007, 2009-2010 Free Software Foundation, dnl Inc. @@ -24,26 +24,39 @@ AC_DEFUN([gl_FUNC_GETLINE], gl_getline_needs_run_time_check=no AC_CHECK_FUNC([getline], - dnl Found it in some library. Verify that it works. - gl_getline_needs_run_time_check=yes, - am_cv_func_working_getline=no) + [dnl Found it in some library. Verify that it works. + gl_getline_needs_run_time_check=yes], + [am_cv_func_working_getline=no]) if test $gl_getline_needs_run_time_check = yes; then AC_CACHE_CHECK([for working getline function], [am_cv_func_working_getline], - [echo fooN |tr -d '\012'|tr N '\012' > conftest.data + [echo fooNbarN | tr -d '\012' | tr N '\012' > conftest.data AC_RUN_IFELSE([AC_LANG_SOURCE([[ # include <stdio.h> # include <stdlib.h> # include <string.h> int main () - { /* Based on a test program from Karl Heuer. */ - char *line = NULL; - size_t siz = 0; - int len; + { FILE *in = fopen ("./conftest.data", "r"); if (!in) return 1; - len = getline (&line, &siz, in); - exit ((len == 4 && line && strcmp (line, "foo\n") == 0) ? 0 : 1); + { + /* Test result for a NULL buffer and a zero size. + Based on a test program from Karl Heuer. */ + char *line = NULL; + size_t siz = 0; + int len = getline (&line, &siz, in); + if (!(len == 4 && line && strcmp (line, "foo\n") == 0)) + return 1; + } + { + /* Test result for a NULL buffer and a non-zero size. + This crashes on FreeBSD 8.0. */ + char *line = NULL; + size_t siz = (size_t)(~0) / 4; + if (getline (&line, &siz, in) == -1) + return 1; + } + return 0; } ]])], [am_cv_func_working_getline=yes] dnl The library version works. , [am_cv_func_working_getline=no] dnl The library version does NOT work. @@ -67,6 +80,9 @@ AC_DEFUN([gl_FUNC_GETLINE], fi if test $am_cv_func_working_getline = no; then + dnl Set REPLACE_GETLINE always: Even if we have not found the broken + dnl getline function among $LIBS, it may exist in libinet and the + dnl executable may be linked with -linet. REPLACE_GETLINE=1 AC_LIBOBJ([getline]) diff --git a/libmissing/m4/gettimeofday.m4 b/libmissing/m4/gettimeofday.m4 index 735123e..32e4f29 100644 --- a/libmissing/m4/gettimeofday.m4 +++ b/libmissing/m4/gettimeofday.m4 @@ -1,4 +1,4 @@ -# serial 12 +# serial 14 # Copyright (C) 2001-2003, 2005, 2007, 2009-2010 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation @@ -11,33 +11,49 @@ AC_DEFUN([gl_FUNC_GETTIMEOFDAY], [ AC_REQUIRE([AC_C_RESTRICT]) AC_REQUIRE([gl_HEADER_SYS_TIME_H]) + AC_REQUIRE([gl_HEADER_SYS_TIME_H_DEFAULTS]) AC_CHECK_FUNCS_ONCE([gettimeofday]) - AC_CACHE_CHECK([for gettimeofday with POSIX signature], - [gl_cv_func_gettimeofday_posix_signature], - [AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM( - [[#include <sys/time.h> - struct timeval c; - ]], - [[ - int (*f) (struct timeval *restrict, void *restrict) = gettimeofday; - int x = f (&c, 0); - return !(x | c.tv_sec | c.tv_usec); - ]])], - [gl_cv_func_gettimeofday_posix_signature=yes], - [gl_cv_func_gettimeofday_posix_signature=no])]) - - gl_FUNC_GETTIMEOFDAY_CLOBBER - - if test $gl_cv_func_gettimeofday_posix_signature != yes; then - REPLACE_GETTIMEOFDAY=1 - SYS_TIME_H=sys/time.h - if test $gl_cv_func_gettimeofday_clobber != yes; then + gl_gettimeofday_timezone=void + if test $ac_cv_func_gettimeofday = yes; then + gl_FUNC_GETTIMEOFDAY_CLOBBER + AC_CACHE_CHECK([for gettimeofday with POSIX signature], + [gl_cv_func_gettimeofday_posix_signature], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include <sys/time.h> + struct timeval c; + int gettimeofday (struct timeval *restrict, void *restrict); + ]], + [[/* glibc uses struct timezone * rather than the POSIX void * + if _GNU_SOURCE is defined. However, since the only portable + use of gettimeofday uses NULL as the second parameter, and + since the glibc definition is actually more typesafe, it is + not worth wrapping this to get a compliant signature. */ + int (*f) (struct timeval *restrict, void *restrict) + = gettimeofday; + int x = f (&c, 0); + return !(x | c.tv_sec | c.tv_usec); + ]])], + [gl_cv_func_gettimeofday_posix_signature=yes], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include <sys/time.h> +int gettimeofday (struct timeval *restrict, struct timezone *restrict); + ]])], + [gl_cv_func_gettimeofday_posix_signature=almost], + [gl_cv_func_gettimeofday_posix_signature=no])])]) + if test $gl_cv_func_gettimeofday_posix_signature = almost; then + gl_gettimeofday_timezone='struct timezone' + elif test $gl_cv_func_gettimeofday_posix_signature != yes; then + REPLACE_GETTIMEOFDAY=1 AC_LIBOBJ([gettimeofday]) gl_PREREQ_GETTIMEOFDAY fi fi + AC_DEFINE_UNQUOTED([GETTIMEOFDAY_TIMEZONE], [$gl_gettimeofday_timezone], + [Define this to 'void' or 'struct timezone' to match the system's + declaration of the second argument to gettimeofday.]) ]) @@ -78,7 +94,6 @@ AC_DEFUN([gl_FUNC_GETTIMEOFDAY_CLOBBER], if test $gl_cv_func_gettimeofday_clobber = yes; then REPLACE_GETTIMEOFDAY=1 - SYS_TIME_H=sys/time.h gl_GETTIMEOFDAY_REPLACE_LOCALTIME AC_DEFINE([GETTIMEOFDAY_CLOBBERS_LOCALTIME], [1], [Define if gettimeofday clobbers the localtime buffer.]) diff --git a/libmissing/m4/gnulib-cache.m4 b/libmissing/m4/gnulib-cache.m4 index 1c76550..32f9a11 100644 --- a/libmissing/m4/gnulib-cache.m4 +++ b/libmissing/m4/gnulib-cache.m4 @@ -15,7 +15,7 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --dir=. --lib=libmissing --source-base=libmissing --m4-base=libmissing/m4 --doc-base=libmissing/doc --tests-base=libmissing/tests --aux-dir=. --with-tests --lgpl --libtool --macro-prefix=gl --no-vc-files accept bind close cond connect dup2 fclose fopen ftw getaddrinfo getpass getsockname gettimeofday inet_ntop inet_pton ioctl listen lock lseek memmem minmax pathmax perror poll regex relocatable-lib-lgpl select setsockopt sigprocmask sleep snprintf socket socklen strcase strcasestr strdup strerror strndup strptime strsep sys_stat thread time_r timegm tls uname vsnprintf write +# gnulib-tool --import --dir=. --lib=libmissing --source-base=libmissing --m4-base=libmissing/m4 --doc-base=libmissing/doc --tests-base=libmissing/tests --aux-dir=. --with-tests --lgpl --libtool --macro-prefix=gl --no-vc-files accept bind close cond connect dup2 fclose fopen ftw getaddrinfo getpass getsockname gettimeofday inet_ntop inet_pton ioctl listen lock lseek memmem minmax pathmax perror poll regex relocatable-lib-lgpl select setsockopt sigprocmask sleep snprintf-posix socket socklen strcase strcasestr strdup strerror strndup strptime strsep sys_stat thread time_r timegm tls uname vsnprintf-posix write # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([]) @@ -50,7 +50,7 @@ gl_MODULES([ setsockopt sigprocmask sleep - snprintf + snprintf-posix socket socklen strcase @@ -66,7 +66,7 @@ gl_MODULES([ timegm tls uname - vsnprintf + vsnprintf-posix write ]) gl_AVOID([]) diff --git a/libmissing/m4/gnulib-comp.m4 b/libmissing/m4/gnulib-comp.m4 index c34c33c..0f912fd 100644 --- a/libmissing/m4/gnulib-comp.m4 +++ b/libmissing/m4/gnulib-comp.m4 @@ -27,6 +27,7 @@ AC_DEFUN([gl_EARLY], AC_REQUIRE([AC_PROG_RANLIB]) AC_REQUIRE([AM_PROG_CC_C_O]) AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) + AC_REQUIRE([gl_FP_IEEE]) AC_REQUIRE([AC_FUNC_FSEEKO]) gl_THREADLIB_EARLY ]) @@ -79,6 +80,10 @@ AC_SUBST([LTALLOCA]) gl_FLOAT_H gl_FUNC_FOPEN gl_STDIO_MODULE_INDICATOR([fopen]) + gl_FUNC_FREXP_NO_LIBM + gl_MATH_MODULE_INDICATOR([frexp]) + gl_FUNC_FREXPL_NO_LIBM + gl_MATH_MODULE_INDICATOR([frexpl]) gl_FUNC_FSEEKO gl_STDIO_MODULE_INDICATOR([fseeko]) gl_FUNC_FTW @@ -99,6 +104,7 @@ AC_SUBST([LTALLOCA]) AC_SUBST([LIBINTL]) AC_SUBST([LTLIBINTL]) gl_FUNC_GETTIMEOFDAY + gl_SYS_TIME_MODULE_INDICATOR([gettimeofday]) gl_HOSTENT gl_INET_NTOP gl_ARPA_INET_MODULE_INDICATOR([inet_ntop]) @@ -114,6 +120,9 @@ AC_SUBST([LTALLOCA]) fi gl_SYS_IOCTL_MODULE_INDICATOR([ioctl]) gl_MODULE_INDICATOR([ioctl]) + gl_FUNC_ISNAND_NO_LIBM + gl_FUNC_ISNANF_NO_LIBM + gl_FUNC_ISNANL_NO_LIBM gl_LANGINFO_H AC_REQUIRE([gl_HEADER_SYS_SOCKET]) if test "$ac_cv_header_winsock2_h" = yes; then @@ -130,6 +139,7 @@ AC_SUBST([LTALLOCA]) AC_DEFINE([GNULIB_MALLOC_GNU], 1, [Define to indicate the 'malloc' module.]) gl_FUNC_MALLOC_POSIX gl_STDLIB_MODULE_INDICATOR([malloc-posix]) + gl_MATH_H gl_FUNC_MBRTOWC gl_WCHAR_MODULE_INDICATOR([mbrtowc]) gl_FUNC_MBSINIT @@ -151,6 +161,9 @@ AC_SUBST([LTALLOCA]) gl_FUNC_PERROR gl_STRING_MODULE_INDICATOR([perror]) gl_FUNC_POLL + gl_FUNC_PRINTF_FREXP + gl_FUNC_PRINTF_FREXPL + m4_divert_text([INIT_PREPARE], [gl_printf_safe=yes]) gl_FUNC_REALLOC_POSIX gl_STDLIB_MODULE_INDICATOR([realloc-posix]) gl_REGEX @@ -164,6 +177,8 @@ AC_SUBST([LTALLOCA]) fi gl_SYS_SOCKET_MODULE_INDICATOR([setsockopt]) gl_SIGNAL_H + gl_SIGNBIT + gl_MATH_MODULE_INDICATOR([signbit]) gl_SIGNALBLOCKING gl_SIGNAL_MODULE_INDICATOR([sigprocmask]) gl_SIZE_MAX @@ -171,6 +186,7 @@ AC_SUBST([LTALLOCA]) gl_UNISTD_MODULE_INDICATOR([sleep]) gl_FUNC_SNPRINTF gl_STDIO_MODULE_INDICATOR([snprintf]) + gl_FUNC_SNPRINTF_POSIX AC_REQUIRE([gl_HEADER_SYS_SOCKET]) if test "$ac_cv_header_winsock2_h" = yes; then AC_LIBOBJ([socket]) @@ -238,6 +254,7 @@ AC_SUBST([LTALLOCA]) gl_FUNC_VASNPRINTF gl_FUNC_VSNPRINTF gl_STDIO_MODULE_INDICATOR([vsnprintf]) + gl_FUNC_VSNPRINTF_POSIX gl_WCHAR_H gl_FUNC_WCRTOMB gl_WCHAR_MODULE_INDICATOR([wcrtomb]) @@ -292,8 +309,12 @@ AC_SUBST([LTALLOCA]) gl_FUNC_UNGETC_WORKS gl_FUNC_GETPAGESIZE gl_UNISTD_MODULE_INDICATOR([getpagesize]) + AC_REQUIRE([AC_C_INLINE]) AC_C_BIGENDIAN AC_C_BIGENDIAN + gl_DOUBLE_EXPONENT_LOCATION + gl_FLOAT_EXPONENT_LOCATION + gl_LONG_DOUBLE_EXPONENT_LOCATION gl_FUNC_LSTAT gl_SYS_STAT_MODULE_INDICATOR([lstat]) gt_LOCALE_FR @@ -312,13 +333,20 @@ AC_SUBST([LTALLOCA]) gl_FCNTL_MODULE_INDICATOR([open]) AC_CHECK_HEADERS_ONCE([unistd.h sys/wait.h]) AC_CHECK_HEADERS_ONCE([unistd.h sys/wait.h]) + AC_REQUIRE([gl_FLOAT_EXPONENT_LOCATION]) + AC_REQUIRE([gl_DOUBLE_EXPONENT_LOCATION]) + AC_REQUIRE([gl_LONG_DOUBLE_EXPONENT_LOCATION]) AC_CHECK_DECLS_ONCE([alarm]) + AC_DEFINE([CHECK_SNPRINTF_POSIX], 1, + [Define to 1 for strict checking in test-snprintf.c.]) gt_TYPE_WCHAR_T gt_TYPE_WINT_T AC_CHECK_DECLS_ONCE([alarm]) gl_FUNC_SYMLINK gl_UNISTD_MODULE_INDICATOR([symlink]) AC_CHECK_FUNCS_ONCE([shutdown]) + AC_DEFINE([CHECK_VSNPRINTF_POSIX], 1, + [Define to 1 for strict checking in test-vsnprintf.c.]) gt_LOCALE_FR gt_LOCALE_FR_UTF8 gt_LOCALE_JA @@ -442,6 +470,9 @@ AC_DEFUN([gl_FILE_LIST], [ lib/float+.h lib/float.in.h lib/fopen.c + lib/fpucw.h + lib/frexp.c + lib/frexpl.c lib/fseeko.c lib/ftw.c lib/ftw_.h @@ -468,12 +499,20 @@ AC_DEFUN([gl_FILE_LIST], [ lib/inet_pton.c lib/intprops.h lib/ioctl.c + lib/isnan.c + lib/isnand-nolibm.h + lib/isnand.c + lib/isnanf-nolibm.h + lib/isnanf.c + lib/isnanl-nolibm.h + lib/isnanl.c lib/langinfo.in.h lib/listen.c lib/localcharset.c lib/localcharset.h lib/lseek.c lib/malloc.c + lib/math.in.h lib/mbrtowc.c lib/mbsinit.c lib/memchr.c @@ -491,6 +530,10 @@ AC_DEFUN([gl_FILE_LIST], [ lib/poll.in.h lib/printf-args.c lib/printf-args.h + lib/printf-frexp.c + lib/printf-frexp.h + lib/printf-frexpl.c + lib/printf-frexpl.h lib/printf-parse.c lib/printf-parse.h lib/realloc.c @@ -507,6 +550,9 @@ AC_DEFUN([gl_FILE_LIST], [ lib/select.c lib/setsockopt.c lib/signal.in.h + lib/signbitd.c + lib/signbitf.c + lib/signbitl.c lib/sigprocmask.c lib/size_max.h lib/sleep.c @@ -566,12 +612,18 @@ AC_DEFUN([gl_FILE_LIST], [ m4/dos.m4 m4/dup2.m4 m4/errno_h.m4 + m4/exponentd.m4 + m4/exponentf.m4 + m4/exponentl.m4 m4/extensions.m4 m4/fclose.m4 m4/fcntl-o.m4 m4/fcntl_h.m4 m4/float_h.m4 m4/fopen.m4 + m4/fpieee.m4 + m4/frexp.m4 + m4/frexpl.m4 m4/fseeko.m4 m4/ftw.m4 m4/getaddrinfo.m4 @@ -589,7 +641,11 @@ AC_DEFUN([gl_FILE_LIST], [ m4/inet_pton.m4 m4/intmax_t.m4 m4/inttypes_h.m4 + m4/isnand.m4 + m4/isnanf.m4 + m4/isnanl.m4 m4/langinfo_h.m4 + m4/ldexpl.m4 m4/lib-ld.m4 m4/lib-link.m4 m4/lib-prefix.m4 @@ -603,6 +659,7 @@ AC_DEFUN([gl_FILE_LIST], [ m4/lseek.m4 m4/lstat.m4 m4/malloc.m4 + m4/math_h.m4 m4/mbrtowc.m4 m4/mbsinit.m4 m4/mbstate_t.m4 @@ -616,11 +673,14 @@ AC_DEFUN([gl_FILE_LIST], [ m4/netdb_h.m4 m4/netinet_in_h.m4 m4/nl_langinfo.m4 + m4/nocrash.m4 m4/onceonly.m4 m4/open.m4 m4/pathmax.m4 m4/perror.m4 m4/poll.m4 + m4/printf-frexp.m4 + m4/printf-frexpl.m4 m4/printf.m4 m4/realloc.m4 m4/regex.m4 @@ -629,8 +689,10 @@ AC_DEFUN([gl_FILE_LIST], [ m4/servent.m4 m4/signal_h.m4 m4/signalblocking.m4 + m4/signbit.m4 m4/size_max.m4 m4/sleep.m4 + m4/snprintf-posix.m4 m4/snprintf.m4 m4/sockets.m4 m4/socklen.m4 @@ -671,6 +733,7 @@ AC_DEFUN([gl_FILE_LIST], [ m4/ungetc.m4 m4/unistd_h.m4 m4/vasnprintf.m4 + m4/vsnprintf-posix.m4 m4/vsnprintf.m4 m4/warn-on-use.m4 m4/wchar.m4 @@ -683,6 +746,7 @@ AC_DEFUN([gl_FILE_LIST], [ m4/xsize.m4 m4/yield.m4 tests/macros.h + tests/nan.h tests/signature.h tests/test-alignof.c tests/test-alloca-opt.c @@ -702,6 +766,8 @@ AC_DEFUN([gl_FILE_LIST], [ tests/test-fcntl-h.c tests/test-fopen.c tests/test-fopen.h + tests/test-frexp.c + tests/test-frexpl.c tests/test-fseeko.c tests/test-fseeko.sh tests/test-fseeko2.sh @@ -712,12 +778,19 @@ AC_DEFUN([gl_FILE_LIST], [ tests/test-gettimeofday.c tests/test-inet_ntop.c tests/test-inet_pton.c + tests/test-isnand-nolibm.c + tests/test-isnand.h + tests/test-isnanf-nolibm.c + tests/test-isnanf.h + tests/test-isnanl-nolibm.c + tests/test-isnanl.h tests/test-langinfo.c tests/test-lock.c tests/test-lseek.c tests/test-lseek.sh tests/test-lstat.c tests/test-lstat.h + tests/test-math.c tests/test-mbrtowc.c tests/test-mbrtowc1.sh tests/test-mbrtowc2.sh @@ -736,13 +809,18 @@ AC_DEFUN([gl_FILE_LIST], [ tests/test-perror.c tests/test-perror.sh tests/test-poll.c + tests/test-printf-frexp.c + tests/test-printf-frexpl.c tests/test-select-fd.c tests/test-select-in.sh tests/test-select-out.sh tests/test-select-stdin.c tests/test-select.c tests/test-signal.c + tests/test-signbit.c tests/test-sleep.c + tests/test-snprintf-posix.c + tests/test-snprintf-posix.h tests/test-snprintf.c tests/test-sockets.c tests/test-stat.c @@ -769,6 +847,7 @@ AC_DEFUN([gl_FILE_LIST], [ tests/test-uname.c tests/test-unistd.c tests/test-vasnprintf.c + tests/test-vsnprintf-posix.c tests/test-vsnprintf.c tests/test-wchar.c tests/test-wcrtomb.c @@ -782,6 +861,7 @@ AC_DEFUN([gl_FILE_LIST], [ tests=lib/fcntl.in.h tests=lib/getpagesize.c tests=lib/glthread/yield.h + tests=lib/ignore-value.h tests=lib/lstat.c tests=lib/open.c tests=lib/same-inode.h diff --git a/libmissing/m4/isnand.m4 b/libmissing/m4/isnand.m4 new file mode 100644 index 0000000..cd91628 --- /dev/null +++ b/libmissing/m4/isnand.m4 @@ -0,0 +1,95 @@ +# isnand.m4 serial 6 +dnl Copyright (C) 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Check how to get or define isnand(). + +AC_DEFUN([gl_FUNC_ISNAND], +[ + AC_REQUIRE([gl_MATH_H_DEFAULTS]) + ISNAND_LIBM= + gl_HAVE_ISNAND_NO_LIBM + if test $gl_cv_func_isnand_no_libm = no; then + gl_HAVE_ISNAND_IN_LIBM + if test $gl_cv_func_isnand_in_libm = yes; then + ISNAND_LIBM=-lm + fi + fi + dnl The variable gl_func_isnand set here is used by isnan.m4. + if test $gl_cv_func_isnand_no_libm = yes \ + || test $gl_cv_func_isnand_in_libm = yes; then + gl_func_isnand=yes + else + gl_func_isnand=no + HAVE_ISNAND=0 + gl_BUILD_ISNAND + fi + AC_SUBST([ISNAND_LIBM]) +]) + +dnl Check how to get or define isnand() without linking with libm. + +AC_DEFUN([gl_FUNC_ISNAND_NO_LIBM], +[ + gl_HAVE_ISNAND_NO_LIBM + if test $gl_cv_func_isnand_no_libm = yes; then + AC_DEFINE([HAVE_ISNAND_IN_LIBC], [1], + [Define if the isnan(double) function is available in libc.]) + else + gl_BUILD_ISNAND + fi +]) + +dnl Pull in replacement isnand definition. It does not need -lm. +AC_DEFUN([gl_BUILD_ISNAND], +[ + AC_LIBOBJ([isnand]) + gl_DOUBLE_EXPONENT_LOCATION +]) + +dnl Test whether isnand() can be used with libm. + +AC_DEFUN([gl_HAVE_ISNAND_IN_LIBM], +[ + AC_CACHE_CHECK([whether isnan(double) can be used with libm], + [gl_cv_func_isnand_in_libm], + [ + save_LIBS="$LIBS" + LIBS="$LIBS -lm" + AC_TRY_LINK([#include <math.h> + #if __GNUC__ >= 4 + # undef isnand + # define isnand(x) __builtin_isnand ((double)(x)) + #elif defined isnan + # undef isnand + # define isnand(x) isnan ((double)(x)) + #endif + double x;], + [return isnand (x);], + [gl_cv_func_isnand_in_libm=yes], + [gl_cv_func_isnand_in_libm=no]) + LIBS="$save_LIBS" + ]) +]) + +AC_DEFUN([gl_HAVE_ISNAND_NO_LIBM], +[ + AC_CACHE_CHECK([whether isnan(double) can be used without linking with libm], + [gl_cv_func_isnand_no_libm], + [ + AC_TRY_LINK([#include <math.h> + #if __GNUC__ >= 4 + # undef isnand + # define isnand(x) __builtin_isnan ((double)(x)) + #else + # undef isnand + # define isnand(x) isnan ((double)(x)) + #endif + double x;], + [return isnand (x);], + [gl_cv_func_isnand_no_libm=yes], + [gl_cv_func_isnand_no_libm=no]) + ]) +]) diff --git a/libmissing/m4/isnanf.m4 b/libmissing/m4/isnanf.m4 new file mode 100644 index 0000000..1509fb4 --- /dev/null +++ b/libmissing/m4/isnanf.m4 @@ -0,0 +1,179 @@ +# isnanf.m4 serial 10 +dnl Copyright (C) 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Check how to get or define isnanf(). + +AC_DEFUN([gl_FUNC_ISNANF], +[ + AC_REQUIRE([gl_MATH_H_DEFAULTS]) + ISNANF_LIBM= + gl_HAVE_ISNANF_NO_LIBM + if test $gl_cv_func_isnanf_no_libm = no; then + gl_HAVE_ISNANF_IN_LIBM + if test $gl_cv_func_isnanf_in_libm = yes; then + ISNANF_LIBM=-lm + fi + fi + if test $gl_cv_func_isnanf_no_libm = yes \ + || test $gl_cv_func_isnanf_in_libm = yes; then + save_LIBS="$LIBS" + LIBS="$LIBS $ISNANF_LIBM" + gl_ISNANF_WORKS + LIBS="$save_LIBS" + case "$gl_cv_func_isnanf_works" in + *yes) gl_func_isnanf=yes ;; + *) gl_func_isnanf=no; ISNANF_LIBM= ;; + esac + else + gl_func_isnanf=no + fi + if test $gl_func_isnanf != yes; then + HAVE_ISNANF=0 + gl_BUILD_ISNANF + fi + AC_SUBST([ISNANF_LIBM]) +]) + +dnl Check how to get or define isnanf() without linking with libm. + +AC_DEFUN([gl_FUNC_ISNANF_NO_LIBM], +[ + gl_HAVE_ISNANF_NO_LIBM + if test $gl_cv_func_isnanf_no_libm = yes; then + gl_ISNANF_WORKS + fi + if test $gl_cv_func_isnanf_no_libm = yes \ + && { case "$gl_cv_func_isnanf_works" in + *yes) true;; + *) false;; + esac + }; then + AC_DEFINE([HAVE_ISNANF_IN_LIBC], [1], + [Define if the isnan(float) function is available in libc.]) + else + gl_BUILD_ISNANF + fi +]) + +dnl Pull in replacement isnanf definition. It does not need -lm. +AC_DEFUN([gl_BUILD_ISNANF], +[ + AC_LIBOBJ([isnanf]) + gl_FLOAT_EXPONENT_LOCATION +]) + +dnl Test whether isnanf() can be used without libm. +AC_DEFUN([gl_HAVE_ISNANF_NO_LIBM], +[ + AC_CACHE_CHECK([whether isnan(float) can be used without linking with libm], + [gl_cv_func_isnanf_no_libm], + [ + AC_TRY_LINK([#include <math.h> + #if __GNUC__ >= 4 + # undef isnanf + # define isnanf(x) __builtin_isnanf ((float)(x)) + #elif defined isnan + # undef isnanf + # define isnanf(x) isnan ((float)(x)) + #endif + float x;], + [return isnanf (x);], + [gl_cv_func_isnanf_no_libm=yes], + [gl_cv_func_isnanf_no_libm=no]) + ]) +]) + +dnl Test whether isnanf() can be used with libm. +AC_DEFUN([gl_HAVE_ISNANF_IN_LIBM], +[ + AC_CACHE_CHECK([whether isnan(float) can be used with libm], + [gl_cv_func_isnanf_in_libm], + [ + save_LIBS="$LIBS" + LIBS="$LIBS -lm" + AC_TRY_LINK([#include <math.h> + #if __GNUC__ >= 4 + # undef isnanf + # define isnanf(x) __builtin_isnanf ((float)(x)) + #elif defined isnan + # undef isnanf + # define isnanf(x) isnan ((float)(x)) + #endif + float x;], + [return isnanf (x);], + [gl_cv_func_isnanf_in_libm=yes], + [gl_cv_func_isnanf_in_libm=no]) + LIBS="$save_LIBS" + ]) +]) + +dnl Test whether isnanf() rejects Infinity (this fails on Solaris 2.5.1), +dnl recognizes a NaN (this fails on IRIX 6.5 with cc), and recognizes a NaN +dnl with in-memory representation 0x7fbfffff (this fails on IRIX 6.5). +AC_DEFUN([gl_ISNANF_WORKS], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_REQUIRE([gl_FLOAT_EXPONENT_LOCATION]) + AC_CACHE_CHECK([whether isnan(float) works], [gl_cv_func_isnanf_works], + [ + AC_TRY_RUN([ +#include <math.h> +#if __GNUC__ >= 4 +# undef isnanf +# define isnanf(x) __builtin_isnanf ((float)(x)) +#elif defined isnan +# undef isnanf +# define isnanf(x) isnan ((float)(x)) +#endif +/* The Compaq (ex-DEC) C 6.4 compiler chokes on the expression 0.0 / 0.0. */ +#ifdef __DECC +static float +NaN () +{ + static float zero = 0.0f; + return zero / zero; +} +#else +# define NaN() (0.0f / 0.0f) +#endif +#define NWORDS \ + ((sizeof (float) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) +typedef union { unsigned int word[NWORDS]; float value; } memory_float; +int main() +{ + memory_float m; + + if (isnanf (1.0f / 0.0f)) + return 1; + + if (!isnanf (NaN ())) + return 1; + +#if defined FLT_EXPBIT0_WORD && defined FLT_EXPBIT0_BIT + /* The isnanf function should be immune against changes in the sign bit and + in the mantissa bits. The xor operation twiddles a bit that can only be + a sign bit or a mantissa bit. */ + if (FLT_EXPBIT0_WORD == 0 && FLT_EXPBIT0_BIT > 0) + { + m.value = NaN (); + /* Set the bits below the exponent to 01111...111. */ + m.word[0] &= -1U << FLT_EXPBIT0_BIT; + m.word[0] |= 1U << (FLT_EXPBIT0_BIT - 1) - 1; + if (!isnanf (m.value)) + return 1; + } +#endif + + return 0; +}], [gl_cv_func_isnanf_works=yes], [gl_cv_func_isnanf_works=no], + [case "$host_os" in + irix* | solaris*) gl_cv_func_isnanf_works="guessing no";; + *) gl_cv_func_isnanf_works="guessing yes";; + esac + ]) + ]) +]) diff --git a/libmissing/m4/isnanl.m4 b/libmissing/m4/isnanl.m4 new file mode 100644 index 0000000..25daeca --- /dev/null +++ b/libmissing/m4/isnanl.m4 @@ -0,0 +1,245 @@ +# isnanl.m4 serial 12 +dnl Copyright (C) 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_ISNANL], +[ + AC_REQUIRE([gl_MATH_H_DEFAULTS]) + ISNANL_LIBM= + gl_HAVE_ISNANL_NO_LIBM + if test $gl_cv_func_isnanl_no_libm = no; then + gl_HAVE_ISNANL_IN_LIBM + if test $gl_cv_func_isnanl_in_libm = yes; then + ISNANL_LIBM=-lm + fi + fi + if test $gl_cv_func_isnanl_no_libm = yes \ + || test $gl_cv_func_isnanl_in_libm = yes; then + save_LIBS="$LIBS" + LIBS="$LIBS $ISNANL_LIBM" + gl_FUNC_ISNANL_WORKS + LIBS="$save_LIBS" + case "$gl_cv_func_isnanl_works" in + *yes) gl_func_isnanl=yes ;; + *) gl_func_isnanl=no; ISNANL_LIBM= ;; + esac + else + gl_func_isnanl=no + fi + if test $gl_func_isnanl != yes; then + HAVE_ISNANL=0 + gl_BUILD_ISNANL + fi + AC_SUBST([ISNANL_LIBM]) +]) + +AC_DEFUN([gl_FUNC_ISNANL_NO_LIBM], +[ + gl_HAVE_ISNANL_NO_LIBM + gl_func_isnanl_no_libm=$gl_cv_func_isnanl_no_libm + if test $gl_func_isnanl_no_libm = yes; then + gl_FUNC_ISNANL_WORKS + case "$gl_cv_func_isnanl_works" in + *yes) ;; + *) gl_func_isnanl_no_libm=no ;; + esac + fi + if test $gl_func_isnanl_no_libm = yes; then + AC_DEFINE([HAVE_ISNANL_IN_LIBC], [1], + [Define if the isnan(long double) function is available in libc.]) + else + gl_BUILD_ISNANL + fi +]) + +dnl Pull in replacement isnanl definition. It does not need -lm. +AC_DEFUN([gl_BUILD_ISNANL], +[ + AC_LIBOBJ([isnanl]) + gl_LONG_DOUBLE_EXPONENT_LOCATION +]) + +dnl Test whether isnanl() can be used without libm. +AC_DEFUN([gl_HAVE_ISNANL_NO_LIBM], +[ + AC_CACHE_CHECK([whether isnan(long double) can be used without linking with libm], + [gl_cv_func_isnanl_no_libm], + [ + AC_TRY_LINK([#include <math.h> + #if __GNUC__ >= 4 + # undef isnanl + # define isnanl(x) __builtin_isnanl ((long double)(x)) + #elif defined isnan + # undef isnanl + # define isnanl(x) isnan ((long double)(x)) + #endif + long double x;], + [return isnanl (x);], + [gl_cv_func_isnanl_no_libm=yes], + [gl_cv_func_isnanl_no_libm=no]) + ]) +]) + +dnl Test whether isnanl() can be used with libm. +AC_DEFUN([gl_HAVE_ISNANL_IN_LIBM], +[ + AC_CACHE_CHECK([whether isnan(long double) can be used with libm], + [gl_cv_func_isnanl_in_libm], + [ + save_LIBS="$LIBS" + LIBS="$LIBS -lm" + AC_TRY_LINK([#include <math.h> + #if __GNUC__ >= 4 + # undef isnanl + # define isnanl(x) __builtin_isnanl ((long double)(x)) + #elif defined isnan + # undef isnanl + # define isnanl(x) isnan ((long double)(x)) + #endif + long double x;], + [return isnanl (x);], + [gl_cv_func_isnanl_in_libm=yes], + [gl_cv_func_isnanl_in_libm=no]) + LIBS="$save_LIBS" + ]) +]) + +dnl Test whether isnanl() recognizes all numbers which are neither finite nor +dnl infinite. This test fails e.g. on NetBSD/i386 and on glibc/ia64. +dnl Also, the GCC >= 4.0 built-in __builtin_isnanl does not pass the tests +dnl - for pseudo-denormals on i686 and x86_64, +dnl - for pseudo-zeroes, unnormalized numbers, and pseudo-denormals on ia64. +AC_DEFUN([gl_FUNC_ISNANL_WORKS], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([gl_BIGENDIAN]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether isnanl works], [gl_cv_func_isnanl_works], + [ + AC_TRY_RUN([ +#include <float.h> +#include <limits.h> +#include <math.h> +#if __GNUC__ >= 4 +# undef isnanl +# define isnanl(x) __builtin_isnanl ((long double)(x)) +#elif defined isnan +# undef isnanl +# define isnanl(x) isnan ((long double)(x)) +#endif +#define NWORDS \ + ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) +typedef union { unsigned int word[NWORDS]; long double value; } + memory_long_double; +/* On Irix 6.5, gcc 3.4.3 can't compute compile-time NaN, and needs the + runtime type conversion. */ +#ifdef __sgi +static long double NaNl () +{ + double zero = 0.0; + return zero / zero; +} +#else +# define NaNl() (0.0L / 0.0L) +#endif +int main () +{ + memory_long_double m; + unsigned int i; + + if (!isnanl (NaNl ())) + return 1; + + /* The isnanl function should be immune against changes in the sign bit and + in the mantissa bits. The xor operation twiddles a bit that can only be + a sign bit or a mantissa bit (since the exponent never extends to + bit 31). */ + m.value = NaNl (); + m.word[NWORDS / 2] ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1); + for (i = 0; i < NWORDS; i++) + m.word[i] |= 1; + if (!isnanl (m.value)) + return 1; + +#if ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_)) +/* Representation of an 80-bit 'long double' as an initializer for a sequence + of 'unsigned int' words. */ +# ifdef WORDS_BIGENDIAN +# define LDBL80_WORDS(exponent,manthi,mantlo) \ + { ((unsigned int) (exponent) << 16) | ((unsigned int) (manthi) >> 16), \ + ((unsigned int) (manthi) << 16) | (unsigned int) (mantlo) >> 16), \ + (unsigned int) (mantlo) << 16 \ + } +# else +# define LDBL80_WORDS(exponent,manthi,mantlo) \ + { mantlo, manthi, exponent } +# endif + { /* Quiet NaN. */ + static memory_long_double x = + { LDBL80_WORDS (0xFFFF, 0xC3333333, 0x00000000) }; + if (!isnanl (x.value)) + return 1; + } + { + /* Signalling NaN. */ + static memory_long_double x = + { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) }; + if (!isnanl (x.value)) + return 1; + } + /* The isnanl function should recognize Pseudo-NaNs, Pseudo-Infinities, + Pseudo-Zeroes, Unnormalized Numbers, and Pseudo-Denormals, as defined in + Intel IA-64 Architecture Software Developer's Manual, Volume 1: + Application Architecture. + Table 5-2 "Floating-Point Register Encodings" + Figure 5-6 "Memory to Floating-Point Register Data Translation" + */ + { /* Pseudo-NaN. */ + static memory_long_double x = + { LDBL80_WORDS (0xFFFF, 0x40000001, 0x00000000) }; + if (!isnanl (x.value)) + return 1; + } + { /* Pseudo-Infinity. */ + static memory_long_double x = + { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) }; + if (!isnanl (x.value)) + return 1; + } + { /* Pseudo-Zero. */ + static memory_long_double x = + { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) }; + if (!isnanl (x.value)) + return 1; + } + { /* Unnormalized number. */ + static memory_long_double x = + { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) }; + if (!isnanl (x.value)) + return 1; + } + { /* Pseudo-Denormal. */ + static memory_long_double x = + { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) }; + if (!isnanl (x.value)) + return 1; + } +#endif + + return 0; +}], [gl_cv_func_isnanl_works=yes], [gl_cv_func_isnanl_works=no], + [case "$host_cpu" in + # Guess no on ia64, x86_64, i386. + ia64 | x86_64 | i*86) gl_cv_func_isnanl_works="guessing no";; + *) + case "$host_os" in + netbsd*) gl_cv_func_isnanl_works="guessing no";; + *) gl_cv_func_isnanl_works="guessing yes";; + esac + ;; + esac + ]) + ]) +]) diff --git a/libmissing/m4/ldexpl.m4 b/libmissing/m4/ldexpl.m4 new file mode 100644 index 0000000..bcc76b2 --- /dev/null +++ b/libmissing/m4/ldexpl.m4 @@ -0,0 +1,88 @@ +# ldexpl.m4 serial 4 +dnl Copyright (C) 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_LDEXPL], +[ + AC_REQUIRE([gl_MATH_H_DEFAULTS]) + LDEXPL_LIBM= + AC_CACHE_CHECK([whether ldexpl() can be used without linking with libm], + [gl_cv_func_ldexpl_no_libm], + [ + AC_TRY_LINK([#include <math.h> + long double x;], + [return ldexpl (x, -1) > 0;], + [gl_cv_func_ldexpl_no_libm=yes], + [gl_cv_func_ldexpl_no_libm=no]) + ]) + if test $gl_cv_func_ldexpl_no_libm = no; then + AC_CACHE_CHECK([whether ldexpl() can be used with libm], + [gl_cv_func_ldexpl_in_libm], + [ + save_LIBS="$LIBS" + LIBS="$LIBS -lm" + AC_TRY_LINK([#include <math.h> + long double x;], + [return ldexpl (x, -1) > 0;], + [gl_cv_func_ldexpl_in_libm=yes], + [gl_cv_func_ldexpl_in_libm=no]) + LIBS="$save_LIBS" + ]) + if test $gl_cv_func_ldexpl_in_libm = yes; then + LDEXPL_LIBM=-lm + fi + fi + if test $gl_cv_func_ldexpl_no_libm = yes \ + || test $gl_cv_func_ldexpl_in_libm = yes; then + save_LIBS="$LIBS" + LIBS="$LIBS $LDEXPL_LIBM" + gl_FUNC_LDEXPL_WORKS + LIBS="$save_LIBS" + case "$gl_cv_func_ldexpl_works" in + *yes) gl_func_ldexpl=yes ;; + *) gl_func_ldexpl=no; REPLACE_LDEXPL=1; LDEXPL_LIBM= ;; + esac + else + gl_func_ldexpl=no + fi + if test $gl_func_ldexpl = yes; then + AC_DEFINE([HAVE_LDEXPL], [1], + [Define if the ldexpl() function is available.]) + dnl Also check whether it's declared. + dnl MacOS X 10.3 has ldexpl() in libc but doesn't declare it in <math.h>. + AC_CHECK_DECL([ldexpl], , [HAVE_DECL_LDEXPL=0], [#include <math.h>]) + else + HAVE_DECL_LDEXPL=0 + AC_LIBOBJ([ldexpl]) + fi + AC_SUBST([LDEXPL_LIBM]) +]) + +dnl Test whether ldexpl() works on finite numbers (this fails on AIX 5.1 +dnl and MacOS X 10.4/PowerPC). +AC_DEFUN([gl_FUNC_LDEXPL_WORKS], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether ldexpl works], [gl_cv_func_ldexpl_works], + [ + AC_TRY_RUN([ +#include <math.h> +extern long double ldexpl (long double, int); +int main() +{ + volatile long double x1 = 1.0; + volatile long double y1 = ldexpl (x1, -1); + volatile long double x2 = 1.73205L; + volatile long double y2 = ldexpl (x2, 0); + return (y1 != 0.5L) || (y2 != x2); +}], [gl_cv_func_ldexpl_works=yes], [gl_cv_func_ldexpl_works=no], + [case "$host_os" in + aix*) gl_cv_func_ldexpl_works="guessing no";; + *) gl_cv_func_ldexpl_works="guessing yes";; + esac + ]) + ]) +]) diff --git a/libmissing/m4/math_h.m4 b/libmissing/m4/math_h.m4 new file mode 100644 index 0000000..e3b499e --- /dev/null +++ b/libmissing/m4/math_h.m4 @@ -0,0 +1,128 @@ +# math_h.m4 serial 17 +dnl Copyright (C) 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_MATH_H], +[ + AC_REQUIRE([gl_MATH_H_DEFAULTS]) + gl_CHECK_NEXT_HEADERS([math.h]) + AC_REQUIRE([AC_C_INLINE]) + + AC_CACHE_CHECK([whether NAN macro works], [gl_cv_header_math_nan_works], + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <math.h>]], + [[/* Solaris 10 has a broken definition of NAN. Other platforms + fail to provide NAN, or provide it only in C99 mode; this + test only needs to fail when NAN is provided but wrong. */ + float f = 1.0f; +#ifdef NAN + f = NAN; +#endif + return f == 0;]])], + [gl_cv_header_math_nan_works=yes], + [gl_cv_header_math_nan_works=no])]) + if test $gl_cv_header_math_nan_works = no; then + REPLACE_NAN=1 + fi + AC_CACHE_CHECK([whether HUGE_VAL works], [gl_cv_header_math_huge_val_works], + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <math.h>]], + [[/* Solaris 10 has a broken definition of HUGE_VAL. */ + double d = HUGE_VAL; + return d == 0;]])], + [gl_cv_header_math_huge_val_works=yes], + [gl_cv_header_math_huge_val_works=no])]) + if test $gl_cv_header_math_huge_val_works = no; then + REPLACE_HUGE_VAL=1 + fi + + dnl Check for declarations of anything we want to poison if the + dnl corresponding gnulib module is not in use. + gl_WARN_ON_USE_PREPARE([[#include <math.h> + ]], [acosl asinl atanl ceilf ceill cosl expl floorf floorl frexpl + ldexpl logl round roundf roundl sinl sqrtl tanl trunc truncf truncl]) +]) + +AC_DEFUN([gl_MATH_MODULE_INDICATOR], +[ + dnl Use AC_REQUIRE here, so that the default settings are expanded once only. + AC_REQUIRE([gl_MATH_H_DEFAULTS]) + GNULIB_[]m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./-],[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])=1 +]) + +AC_DEFUN([gl_MATH_H_DEFAULTS], +[ + GNULIB_ACOSL=0; AC_SUBST([GNULIB_ACOSL]) + GNULIB_ASINL=0; AC_SUBST([GNULIB_ASINL]) + GNULIB_ATANL=0; AC_SUBST([GNULIB_ATANL]) + GNULIB_CEILF=0; AC_SUBST([GNULIB_CEILF]) + GNULIB_CEILL=0; AC_SUBST([GNULIB_CEILL]) + GNULIB_COSL=0; AC_SUBST([GNULIB_COSL]) + GNULIB_EXPL=0; AC_SUBST([GNULIB_EXPL]) + GNULIB_FLOORF=0; AC_SUBST([GNULIB_FLOORF]) + GNULIB_FLOORL=0; AC_SUBST([GNULIB_FLOORL]) + GNULIB_FREXP=0; AC_SUBST([GNULIB_FREXP]) + GNULIB_FREXPL=0; AC_SUBST([GNULIB_FREXPL]) + GNULIB_ISFINITE=0; AC_SUBST([GNULIB_ISFINITE]) + GNULIB_ISINF=0; AC_SUBST([GNULIB_ISINF]) + GNULIB_ISNAN=0; AC_SUBST([GNULIB_ISNAN]) + GNULIB_ISNANF=0; AC_SUBST([GNULIB_ISNANF]) + GNULIB_ISNAND=0; AC_SUBST([GNULIB_ISNAND]) + GNULIB_ISNANL=0; AC_SUBST([GNULIB_ISNANL]) + GNULIB_LDEXPL=0; AC_SUBST([GNULIB_LDEXPL]) + GNULIB_LOGL=0; AC_SUBST([GNULIB_LOGL]) + GNULIB_ROUND=0; AC_SUBST([GNULIB_ROUND]) + GNULIB_ROUNDF=0; AC_SUBST([GNULIB_ROUNDF]) + GNULIB_ROUNDL=0; AC_SUBST([GNULIB_ROUNDL]) + GNULIB_SIGNBIT=0; AC_SUBST([GNULIB_SIGNBIT]) + GNULIB_SINL=0; AC_SUBST([GNULIB_SINL]) + GNULIB_SQRTL=0; AC_SUBST([GNULIB_SQRTL]) + GNULIB_TANL=0; AC_SUBST([GNULIB_TANL]) + GNULIB_TRUNC=0; AC_SUBST([GNULIB_TRUNC]) + GNULIB_TRUNCF=0; AC_SUBST([GNULIB_TRUNCF]) + GNULIB_TRUNCL=0; AC_SUBST([GNULIB_TRUNCL]) + dnl Assume proper GNU behavior unless another module says otherwise. + HAVE_ACOSL=1; AC_SUBST([HAVE_ACOSL]) + HAVE_ASINL=1; AC_SUBST([HAVE_ASINL]) + HAVE_ATANL=1; AC_SUBST([HAVE_ATANL]) + HAVE_COSL=1; AC_SUBST([HAVE_COSL]) + HAVE_EXPL=1; AC_SUBST([HAVE_EXPL]) + HAVE_ISNANF=1; AC_SUBST([HAVE_ISNANF]) + HAVE_ISNAND=1; AC_SUBST([HAVE_ISNAND]) + HAVE_ISNANL=1; AC_SUBST([HAVE_ISNANL]) + HAVE_LOGL=1; AC_SUBST([HAVE_LOGL]) + HAVE_SINL=1; AC_SUBST([HAVE_SINL]) + HAVE_SQRTL=1; AC_SUBST([HAVE_SQRTL]) + HAVE_TANL=1; AC_SUBST([HAVE_TANL]) + HAVE_DECL_ACOSL=1; AC_SUBST([HAVE_DECL_ACOSL]) + HAVE_DECL_ASINL=1; AC_SUBST([HAVE_DECL_ASINL]) + HAVE_DECL_ATANL=1; AC_SUBST([HAVE_DECL_ATANL]) + HAVE_DECL_COSL=1; AC_SUBST([HAVE_DECL_COSL]) + HAVE_DECL_EXPL=1; AC_SUBST([HAVE_DECL_EXPL]) + HAVE_DECL_FREXPL=1; AC_SUBST([HAVE_DECL_FREXPL]) + HAVE_DECL_LDEXPL=1; AC_SUBST([HAVE_DECL_LDEXPL]) + HAVE_DECL_LOGL=1; AC_SUBST([HAVE_DECL_LOGL]) + HAVE_DECL_SINL=1; AC_SUBST([HAVE_DECL_SINL]) + HAVE_DECL_SQRTL=1; AC_SUBST([HAVE_DECL_SQRTL]) + HAVE_DECL_TANL=1; AC_SUBST([HAVE_DECL_TANL]) + HAVE_DECL_TRUNC=1; AC_SUBST([HAVE_DECL_TRUNC]) + HAVE_DECL_TRUNCF=1; AC_SUBST([HAVE_DECL_TRUNCF]) + REPLACE_CEILF=0; AC_SUBST([REPLACE_CEILF]) + REPLACE_CEILL=0; AC_SUBST([REPLACE_CEILL]) + REPLACE_FLOORF=0; AC_SUBST([REPLACE_FLOORF]) + REPLACE_FLOORL=0; AC_SUBST([REPLACE_FLOORL]) + REPLACE_FREXP=0; AC_SUBST([REPLACE_FREXP]) + REPLACE_FREXPL=0; AC_SUBST([REPLACE_FREXPL]) + REPLACE_HUGE_VAL=0; AC_SUBST([REPLACE_HUGE_VAL]) + REPLACE_ISFINITE=0; AC_SUBST([REPLACE_ISFINITE]) + REPLACE_ISINF=0; AC_SUBST([REPLACE_ISINF]) + REPLACE_ISNAN=0; AC_SUBST([REPLACE_ISNAN]) + REPLACE_LDEXPL=0; AC_SUBST([REPLACE_LDEXPL]) + REPLACE_NAN=0; AC_SUBST([REPLACE_NAN]) + REPLACE_ROUND=0; AC_SUBST([REPLACE_ROUND]) + REPLACE_ROUNDF=0; AC_SUBST([REPLACE_ROUNDF]) + REPLACE_ROUNDL=0; AC_SUBST([REPLACE_ROUNDL]) + REPLACE_SIGNBIT=0; AC_SUBST([REPLACE_SIGNBIT]) + REPLACE_SIGNBIT_USING_GCC=0; AC_SUBST([REPLACE_SIGNBIT_USING_GCC]) + REPLACE_TRUNCL=0; AC_SUBST([REPLACE_TRUNCL]) +]) diff --git a/libmissing/m4/nocrash.m4 b/libmissing/m4/nocrash.m4 new file mode 100644 index 0000000..efbcfa6 --- /dev/null +++ b/libmissing/m4/nocrash.m4 @@ -0,0 +1,102 @@ +# nocrash.m4 serial 2 +dnl Copyright (C) 2005, 2009, 2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Based on libsigsegv, from Bruno Haible and Paolo Bonzini. + +AC_PREREQ([2.13]) + +dnl Expands to some code for use in .c programs that will cause the configure +dnl test to exit instead of crashing. This is useful to avoid triggering +dnl action from a background debugger and to avoid core dumps. +dnl Usage: ... +dnl ]GL_NOCRASH[ +dnl ... +dnl int main() { nocrash_init(); ... } +AC_DEFUN([GL_NOCRASH],[[ +#include <stdlib.h> +#if defined __MACH__ && defined __APPLE__ +/* Avoid a crash on MacOS X. */ +#include <mach/mach.h> +#include <mach/mach_error.h> +#include <mach/thread_status.h> +#include <mach/exception.h> +#include <mach/task.h> +#include <pthread.h> +/* The exception port on which our thread listens. */ +static mach_port_t our_exception_port; +/* The main function of the thread listening for exceptions of type + EXC_BAD_ACCESS. */ +static void * +mach_exception_thread (void *arg) +{ + /* Buffer for a message to be received. */ + struct { + mach_msg_header_t head; + mach_msg_body_t msgh_body; + char data[1024]; + } msg; + mach_msg_return_t retval; + /* Wait for a message on the exception port. */ + retval = mach_msg (&msg.head, MACH_RCV_MSG | MACH_RCV_LARGE, 0, sizeof (msg), + our_exception_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + if (retval != MACH_MSG_SUCCESS) + abort (); + exit (1); +} +static void +nocrash_init (void) +{ + mach_port_t self = mach_task_self (); + /* Allocate a port on which the thread shall listen for exceptions. */ + if (mach_port_allocate (self, MACH_PORT_RIGHT_RECEIVE, &our_exception_port) + == KERN_SUCCESS) { + /* See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/mach_port_insert_right.html. */ + if (mach_port_insert_right (self, our_exception_port, our_exception_port, + MACH_MSG_TYPE_MAKE_SEND) + == KERN_SUCCESS) { + /* The exceptions we want to catch. Only EXC_BAD_ACCESS is interesting + for us. */ + exception_mask_t mask = EXC_MASK_BAD_ACCESS; + /* Create the thread listening on the exception port. */ + pthread_attr_t attr; + pthread_t thread; + if (pthread_attr_init (&attr) == 0 + && pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED) == 0 + && pthread_create (&thread, &attr, mach_exception_thread, NULL) == 0) { + pthread_attr_destroy (&attr); + /* Replace the exception port info for these exceptions with our own. + Note that we replace the exception port for the entire task, not only + for a particular thread. This has the effect that when our exception + port gets the message, the thread specific exception port has already + been asked, and we don't need to bother about it. + See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/task_set_exception_ports.html. */ + task_set_exception_ports (self, mask, our_exception_port, + EXCEPTION_DEFAULT, MACHINE_THREAD_STATE); + } + } + } +} +#else +/* Avoid a crash on POSIX systems. */ +#include <signal.h> +/* A POSIX signal handler. */ +static void +exception_handler (int sig) +{ + exit (1); +} +static void +nocrash_init (void) +{ +#ifdef SIGSEGV + signal (SIGSEGV, exception_handler); +#endif +#ifdef SIGBUS + signal (SIGBUS, exception_handler); +#endif +} +#endif +]]) diff --git a/libmissing/m4/printf-frexp.m4 b/libmissing/m4/printf-frexp.m4 new file mode 100644 index 0000000..c42391a --- /dev/null +++ b/libmissing/m4/printf-frexp.m4 @@ -0,0 +1,45 @@ +# printf-frexp.m4 serial 3 +dnl Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Check how to define printf_frexp() without linking with libm. + +AC_DEFUN([gl_FUNC_PRINTF_FREXP], +[ + AC_CACHE_CHECK([whether frexp can be used without linking with libm], + [gl_cv_func_frexp_no_libm], + [ + AC_TRY_LINK([#include <math.h> + double x; + int y;], + [return frexp (x, &y) < 1;], + [gl_cv_func_frexp_no_libm=yes], + [gl_cv_func_frexp_no_libm=no]) + ]) + if test $gl_cv_func_frexp_no_libm = yes; then + gl_FUNC_FREXP_WORKS + case "$gl_cv_func_frexp_works" in + *yes) + AC_DEFINE([HAVE_FREXP_IN_LIBC], [1], + [Define if the frexp function is available in libc.]) + ;; + esac + fi + + AC_CACHE_CHECK([whether ldexp can be used without linking with libm], + [gl_cv_func_ldexp_no_libm], + [ + AC_TRY_LINK([#include <math.h> + double x; + int y;], + [return ldexp (x, y) < 1;], + [gl_cv_func_ldexp_no_libm=yes], + [gl_cv_func_ldexp_no_libm=no]) + ]) + if test $gl_cv_func_ldexp_no_libm = yes; then + AC_DEFINE([HAVE_LDEXP_IN_LIBC], [1], + [Define if the ldexp function is available in libc.]) + fi +]) diff --git a/libmissing/m4/printf-frexpl.m4 b/libmissing/m4/printf-frexpl.m4 new file mode 100644 index 0000000..14ffe1f --- /dev/null +++ b/libmissing/m4/printf-frexpl.m4 @@ -0,0 +1,64 @@ +# printf-frexpl.m4 serial 6 +dnl Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Check how to define printf_frexpl() without linking with libm. + +AC_DEFUN([gl_FUNC_PRINTF_FREXPL], +[ + AC_REQUIRE([gl_MATH_H_DEFAULTS]) + dnl Subset of gl_FUNC_FREXPL_NO_LIBM. + AC_CACHE_CHECK([whether frexpl can be used without linking with libm], + [gl_cv_func_frexpl_no_libm], + [ + AC_TRY_LINK([#include <math.h> + long double x; + int y;], + [return frexpl (x, &y) < 1;], + [gl_cv_func_frexpl_no_libm=yes], + [gl_cv_func_frexpl_no_libm=no]) + ]) + if test $gl_cv_func_frexpl_no_libm = yes; then + gl_FUNC_FREXPL_WORKS + case "$gl_cv_func_frexpl_works" in + *yes) gl_func_frexpl_no_libm=yes ;; + *) gl_func_frexpl_no_libm=no; REPLACE_FREXPL=1 ;; + esac + else + gl_func_frexpl_no_libm=no + dnl Set REPLACE_FREXPL here because the system may have frexpl in libm. + REPLACE_FREXPL=1 + fi + if test $gl_func_frexpl_no_libm = yes; then + AC_DEFINE([HAVE_FREXPL_IN_LIBC], [1], + [Define if the frexpl function is available in libc.]) + dnl Also check whether it's declared. + dnl MacOS X 10.3 has frexpl() in libc but doesn't declare it in <math.h>. + AC_CHECK_DECL([frexpl], , [HAVE_DECL_FREXPL=0], [#include <math.h>]) + fi + + AC_CACHE_CHECK([whether ldexpl can be used without linking with libm], + [gl_cv_func_ldexpl_no_libm], + [ + AC_TRY_LINK([#include <math.h> + long double x; + int y;], + [return ldexpl (x, y) < 1;], + [gl_cv_func_ldexpl_no_libm=yes], + [gl_cv_func_ldexpl_no_libm=no]) + ]) + if test $gl_cv_func_ldexpl_no_libm = yes; then + gl_FUNC_LDEXPL_WORKS + case "$gl_cv_func_ldexpl_works" in + *yes) + AC_DEFINE([HAVE_LDEXPL_IN_LIBC], [1], + [Define if the ldexpl function is available in libc.]) + dnl Also check whether it's declared. + dnl MacOS X 10.3 has ldexpl() in libc but doesn't declare it in <math.h>. + AC_CHECK_DECL([ldexpl], , [HAVE_DECL_LDEXPL=0], [#include <math.h>]) + ;; + esac + fi +]) diff --git a/libmissing/m4/regex.m4 b/libmissing/m4/regex.m4 index a702252..6bd6b8f 100644 --- a/libmissing/m4/regex.m4 +++ b/libmissing/m4/regex.m4 @@ -96,6 +96,13 @@ AC_DEFUN([gl_REGEX], if (!s) return 1; + /* Ensure that [b-a] is diagnosed as invalid. */ + re_set_syntax (RE_SYNTAX_POSIX_EGREP); + memset (®ex, 0, sizeof regex); + s = re_compile_pattern ("a[b-a]", 6, ®ex); + if (s == 0) + return 1; + /* This should succeed, but does not for glibc-2.1.3. */ memset (®ex, 0, sizeof regex); s = re_compile_pattern ("{1", 2, ®ex); diff --git a/libmissing/m4/signbit.m4 b/libmissing/m4/signbit.m4 new file mode 100644 index 0000000..56ff825 --- /dev/null +++ b/libmissing/m4/signbit.m4 @@ -0,0 +1,287 @@ +# signbit.m4 serial 6 +dnl Copyright (C) 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_SIGNBIT], +[ + AC_REQUIRE([gl_MATH_H_DEFAULTS]) + AC_CACHE_CHECK([for signbit macro], [gl_cv_func_signbit], + [ + AC_TRY_RUN([ +#include <math.h> +/* If signbit is defined as a function, don't use it, since calling it for + 'float' or 'long double' arguments would involve conversions. + If signbit is not declared at all but exists as a library function, don't + use it, since the prototype may not match. + If signbit is not declared at all but exists as a compiler built-in, don't + use it, since it's preferable to use __builtin_signbit* (no warnings, + no conversions). */ +#ifndef signbit +# error "signbit should be a macro" +#endif +#include <string.h> +]gl_SIGNBIT_TEST_PROGRAM +, [gl_cv_func_signbit=yes], [gl_cv_func_signbit=no], + [gl_cv_func_signbit="guessing no"]) + ]) + dnl GCC 4.0 and newer provides three built-ins for signbit. + dnl They can be used without warnings, also in C++, regardless of <math.h>. + dnl But they may expand to calls to functions, which may or may not be in + dnl libc. + AC_CACHE_CHECK([for signbit compiler built-ins], [gl_cv_func_signbit_gcc], + [ + AC_TRY_RUN([ +#if __GNUC__ >= 4 +# define signbit(x) \ + (sizeof (x) == sizeof (long double) ? __builtin_signbitl (x) : \ + sizeof (x) == sizeof (double) ? __builtin_signbit (x) : \ + __builtin_signbitf (x)) +#else +# error "signbit should be three compiler built-ins" +#endif +#include <string.h> +]gl_SIGNBIT_TEST_PROGRAM +, [gl_cv_func_signbit_gcc=yes], [gl_cv_func_signbit_gcc=no], + [gl_cv_func_signbit_gcc="guessing no"]) + ]) + dnl Use the compiler built-ins whenever possible, because they are more + dnl efficient than the system library functions (if they exist). + if test "$gl_cv_func_signbit_gcc" = yes; then + REPLACE_SIGNBIT_USING_GCC=1 + else + if test "$gl_cv_func_signbit" != yes; then + REPLACE_SIGNBIT=1 + AC_LIBOBJ([signbitf]) + AC_LIBOBJ([signbitd]) + AC_LIBOBJ([signbitl]) + gl_FLOAT_SIGN_LOCATION + gl_DOUBLE_SIGN_LOCATION + gl_LONG_DOUBLE_SIGN_LOCATION + if test "$gl_cv_cc_float_signbit" = unknown; then + dnl Test whether copysignf() is declared. + AC_CHECK_DECLS([copysignf], , , [#include <math.h>]) + if test "$ac_cv_have_decl_copysignf" = yes; then + dnl Test whether copysignf() can be used without libm. + AC_CACHE_CHECK([whether copysignf can be used without linking with libm], + [gl_cv_func_copysignf_no_libm], + [ + AC_TRY_LINK([#include <math.h> + float x, y;], + [return copysignf (x, y) < 0;], + [gl_cv_func_copysignf_no_libm=yes], + [gl_cv_func_copysignf_no_libm=no]) + ]) + if test $gl_cv_func_copysignf_no_libm = yes; then + AC_DEFINE([HAVE_COPYSIGNF_IN_LIBC], [1], + [Define if the copysignf function is declared in <math.h> and available in libc.]) + fi + fi + fi + if test "$gl_cv_cc_double_signbit" = unknown; then + dnl Test whether copysign() is declared. + AC_CHECK_DECLS([copysign], , , [#include <math.h>]) + if test "$ac_cv_have_decl_copysign" = yes; then + dnl Test whether copysign() can be used without libm. + AC_CACHE_CHECK([whether copysign can be used without linking with libm], + [gl_cv_func_copysign_no_libm], + [ + AC_TRY_LINK([#include <math.h> + double x, y;], + [return copysign (x, y) < 0;], + [gl_cv_func_copysign_no_libm=yes], + [gl_cv_func_copysign_no_libm=no]) + ]) + if test $gl_cv_func_copysign_no_libm = yes; then + AC_DEFINE([HAVE_COPYSIGN_IN_LIBC], [1], + [Define if the copysign function is declared in <math.h> and available in libc.]) + fi + fi + fi + if test "$gl_cv_cc_long_double_signbit" = unknown; then + dnl Test whether copysignl() is declared. + AC_CHECK_DECLS([copysignl], , , [#include <math.h>]) + if test "$ac_cv_have_decl_copysignl" = yes; then + dnl Test whether copysignl() can be used without libm. + AC_CACHE_CHECK([whether copysignl can be used without linking with libm], + [gl_cv_func_copysignl_no_libm], + [ + AC_TRY_LINK([#include <math.h> + long double x, y;], + [return copysignl (x, y) < 0;], + [gl_cv_func_copysignl_no_libm=yes], + [gl_cv_func_copysignl_no_libm=no]) + ]) + if test $gl_cv_func_copysignl_no_libm = yes; then + AC_DEFINE([HAVE_COPYSIGNL_IN_LIBC], [1], + [Define if the copysignl function is declared in <math.h> and available in libc.]) + fi + fi + fi + fi + fi +]) + +AC_DEFUN([gl_SIGNBIT_TEST_PROGRAM], [[ +/* Global variables. + Needed because GCC 4 constant-folds __builtin_signbitl (literal) + but cannot constant-fold __builtin_signbitl (variable). */ +float vf; +double vd; +long double vl; +int main () +{ +/* HP cc on HP-UX 10.20 has a bug with the constant expression -0.0. + So we use -p0f and -p0d instead. */ +float p0f = 0.0f; +float m0f = -p0f; +double p0d = 0.0; +double m0d = -p0d; +/* On HP-UX 10.20, negating 0.0L does not yield -0.0L. + So we use another constant expression instead. + But that expression does not work on other platforms, such as when + cross-compiling to PowerPC on MacOS X 10.5. */ +long double p0l = 0.0L; +#if defined __hpux || defined __sgi +long double m0l = -LDBL_MIN * LDBL_MIN; +#else +long double m0l = -p0l; +#endif + if (signbit (vf)) + vf++; + { + float plus_inf = 1.0f / p0f; + float minus_inf = -1.0f / p0f; + if (!(!signbit (255.0f) + && signbit (-255.0f) + && !signbit (p0f) + && (memcmp (&m0f, &p0f, sizeof (float)) == 0 || signbit (m0f)) + && !signbit (plus_inf) + && signbit (minus_inf))) + return 1; + } + if (signbit (vd)) + vd++; + { + double plus_inf = 1.0 / p0d; + double minus_inf = -1.0 / p0d; + if (!(!signbit (255.0) + && signbit (-255.0) + && !signbit (p0d) + && (memcmp (&m0d, &p0d, sizeof (double)) == 0 || signbit (m0d)) + && !signbit (plus_inf) + && signbit (minus_inf))) + return 1; + } + if (signbit (vl)) + vl++; + { + long double plus_inf = 1.0L / p0l; + long double minus_inf = -1.0L / p0l; + if (!(!signbit (255.0L) + && signbit (-255.0L) + && !signbit (p0l) + && (memcmp (&m0l, &p0l, sizeof (long double)) == 0 || signbit (m0l)) + && !signbit (plus_inf) + && signbit (minus_inf))) + return 1; + } + return 0; +} +]]) + +AC_DEFUN([gl_FLOAT_SIGN_LOCATION], +[ + gl_FLOATTYPE_SIGN_LOCATION([float], [gl_cv_cc_float_signbit], [f], [FLT]) +]) + +AC_DEFUN([gl_DOUBLE_SIGN_LOCATION], +[ + gl_FLOATTYPE_SIGN_LOCATION([double], [gl_cv_cc_double_signbit], [], [DBL]) +]) + +AC_DEFUN([gl_LONG_DOUBLE_SIGN_LOCATION], +[ + gl_FLOATTYPE_SIGN_LOCATION([long double], [gl_cv_cc_long_double_signbit], [L], [LDBL]) +]) + +AC_DEFUN([gl_FLOATTYPE_SIGN_LOCATION], +[ + AC_CACHE_CHECK([where to find the sign bit in a '$1'], + [$2], + [ + AC_TRY_RUN([ +#include <stddef.h> +#include <stdio.h> +#define NWORDS \ + ((sizeof ($1) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) +typedef union { $1 value; unsigned int word[NWORDS]; } + memory_float; +static memory_float plus = { 1.0$3 }; +static memory_float minus = { -1.0$3 }; +int main () +{ + size_t j, k, i; + unsigned int m; + FILE *fp = fopen ("conftest.out", "w"); + if (fp == NULL) + return 1; + /* Find the different bit. */ + k = 0; m = 0; + for (j = 0; j < NWORDS; j++) + { + unsigned int x = plus.word[j] ^ minus.word[j]; + if ((x & (x - 1)) || (x && m)) + { + /* More than one bit difference. */ + fprintf (fp, "unknown"); + return 1; + } + if (x) + { + k = j; + m = x; + } + } + if (m == 0) + { + /* No difference. */ + fprintf (fp, "unknown"); + return 1; + } + /* Now m = plus.word[k] ^ ~minus.word[k]. */ + if (plus.word[k] & ~minus.word[k]) + { + /* Oh? The sign bit is set in the positive and cleared in the negative + numbers? */ + fprintf (fp, "unknown"); + return 1; + } + for (i = 0; ; i++) + if ((m >> i) & 1) + break; + fprintf (fp, "word %d bit %d", (int) k, (int) i); + return (fclose (fp) != 0); +} + ], + [$2=`cat conftest.out`], + [$2="unknown"], + [ + dnl When cross-compiling, we don't know. It depends on the + dnl ABI and compiler version. There are too many cases. + $2="unknown" + ]) + rm -f conftest.out + ]) + case "$]$2[" in + word*bit*) + word=`echo "$]$2[" | sed -e 's/word //' -e 's/ bit.*//'` + bit=`echo "$]$2[" | sed -e 's/word.*bit //'` + AC_DEFINE_UNQUOTED([$4][_SIGNBIT_WORD], [$word], + [Define as the word index where to find the sign of '$1'.]) + AC_DEFINE_UNQUOTED([$4][_SIGNBIT_BIT], [$bit], + [Define as the bit index in the word where to find the sign of '$1'.]) + ;; + esac +]) diff --git a/libmissing/m4/snprintf-posix.m4 b/libmissing/m4/snprintf-posix.m4 new file mode 100644 index 0000000..77a2481 --- /dev/null +++ b/libmissing/m4/snprintf-posix.m4 @@ -0,0 +1,126 @@ +# snprintf-posix.m4 serial 14 +dnl Copyright (C) 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_SNPRINTF_POSIX], +[ + AC_REQUIRE([gl_PRINTF_SIZES_C99]) + AC_REQUIRE([gl_PRINTF_LONG_DOUBLE]) + AC_REQUIRE([gl_PRINTF_INFINITE]) + AC_REQUIRE([gl_PRINTF_INFINITE_LONG_DOUBLE]) + AC_REQUIRE([gl_PRINTF_DIRECTIVE_A]) + AC_REQUIRE([gl_PRINTF_DIRECTIVE_F]) + AC_REQUIRE([gl_PRINTF_DIRECTIVE_N]) + AC_REQUIRE([gl_PRINTF_DIRECTIVE_LS]) + AC_REQUIRE([gl_PRINTF_POSITIONS]) + AC_REQUIRE([gl_PRINTF_FLAG_GROUPING]) + AC_REQUIRE([gl_PRINTF_FLAG_LEFTADJUST]) + AC_REQUIRE([gl_PRINTF_FLAG_ZERO]) + AC_REQUIRE([gl_PRINTF_PRECISION]) + AC_REQUIRE([gl_PRINTF_ENOMEM]) + gl_cv_func_snprintf_posix=no + AC_CHECK_FUNCS([snprintf]) + if test $ac_cv_func_snprintf = yes; then + gl_SNPRINTF_TRUNCATION_C99 + gl_SNPRINTF_RETVAL_C99 + gl_SNPRINTF_DIRECTIVE_N + gl_SNPRINTF_SIZE1 + gl_VSNPRINTF_ZEROSIZE_C99 + case "$gl_cv_func_printf_sizes_c99" in + *yes) + case "$gl_cv_func_printf_long_double" in + *yes) + case "$gl_cv_func_printf_infinite" in + *yes) + case "$gl_cv_func_printf_infinite_long_double" in + *yes) + case "$gl_cv_func_printf_directive_a" in + *yes) + case "$gl_cv_func_printf_directive_f" in + *yes) + case "$gl_cv_func_printf_directive_n" in + *yes) + case "$gl_cv_func_printf_directive_ls" in + *yes) + case "$gl_cv_func_printf_positions" in + *yes) + case "$gl_cv_func_printf_flag_grouping" in + *yes) + case "$gl_cv_func_printf_flag_leftadjust" in + *yes) + case "$gl_cv_func_printf_flag_zero" in + *yes) + case "$gl_cv_func_printf_precision" in + *yes) + case "$gl_cv_func_printf_enomem" in + *yes) + case "$gl_cv_func_snprintf_truncation_c99" in + *yes) + case "$gl_cv_func_snprintf_retval_c99" in + *yes) + case "$gl_cv_func_snprintf_directive_n" in + *yes) + case "$gl_cv_func_snprintf_size1" in + *yes) + case "$gl_cv_func_vsnprintf_zerosize_c99" in + *yes) + # snprintf exists and is + # already POSIX compliant. + gl_cv_func_snprintf_posix=yes + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + fi + if test $gl_cv_func_snprintf_posix = no; then + gl_PREREQ_VASNPRINTF_LONG_DOUBLE + gl_PREREQ_VASNPRINTF_INFINITE_DOUBLE + gl_PREREQ_VASNPRINTF_INFINITE_LONG_DOUBLE + gl_PREREQ_VASNPRINTF_DIRECTIVE_A + gl_PREREQ_VASNPRINTF_DIRECTIVE_F + gl_PREREQ_VASNPRINTF_DIRECTIVE_LS + gl_PREREQ_VASNPRINTF_FLAG_GROUPING + gl_PREREQ_VASNPRINTF_FLAG_LEFTADJUST + gl_PREREQ_VASNPRINTF_FLAG_ZERO + gl_PREREQ_VASNPRINTF_PRECISION + gl_PREREQ_VASNPRINTF_ENOMEM + gl_REPLACE_VASNPRINTF + gl_REPLACE_SNPRINTF + fi +]) diff --git a/libmissing/m4/stdio_h.m4 b/libmissing/m4/stdio_h.m4 index 20af579..781fa8d 100644 --- a/libmissing/m4/stdio_h.m4 +++ b/libmissing/m4/stdio_h.m4 @@ -1,4 +1,4 @@ -# stdio_h.m4 serial 24 +# stdio_h.m4 serial 25 dnl Copyright (C) 2007-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -111,6 +111,7 @@ AC_DEFUN([gl_STDIO_H_DEFAULTS], REPLACE_FSEEKO=0; AC_SUBST([REPLACE_FSEEKO]) REPLACE_FTELL=0; AC_SUBST([REPLACE_FTELL]) REPLACE_FTELLO=0; AC_SUBST([REPLACE_FTELLO]) + REPLACE_GETDELIM=0; AC_SUBST([REPLACE_GETDELIM]) REPLACE_GETLINE=0; AC_SUBST([REPLACE_GETLINE]) REPLACE_OBSTACK_PRINTF=0; AC_SUBST([REPLACE_OBSTACK_PRINTF]) REPLACE_PERROR=0; AC_SUBST([REPLACE_PERROR]) diff --git a/libmissing/m4/sys_time_h.m4 b/libmissing/m4/sys_time_h.m4 index 9c16487..b14bc4b 100644 --- a/libmissing/m4/sys_time_h.m4 +++ b/libmissing/m4/sys_time_h.m4 @@ -1,5 +1,5 @@ # Configure a replacement for <sys/time.h>. -# serial 2 +# serial 3 # Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation @@ -19,15 +19,13 @@ AC_DEFUN([gl_HEADER_SYS_TIME_H], AC_DEFUN([gl_HEADER_SYS_TIME_H_BODY], [ AC_REQUIRE([AC_C_RESTRICT]) + AC_REQUIRE([gl_HEADER_SYS_TIME_H_DEFAULTS]) AC_CHECK_HEADERS_ONCE([sys/time.h]) gl_CHECK_NEXT_HEADERS([sys/time.h]) - if test $ac_cv_header_sys_time_h = yes; then - HAVE_SYS_TIME_H=1 - else + if test $ac_cv_header_sys_time_h != yes; then HAVE_SYS_TIME_H=0 fi - AC_SUBST([HAVE_SYS_TIME_H]) AC_CACHE_CHECK([for struct timeval], [gl_cv_sys_struct_timeval], [AC_COMPILE_IFELSE( @@ -40,20 +38,32 @@ AC_DEFUN([gl_HEADER_SYS_TIME_H_BODY], [[static struct timeval x; x.tv_sec = x.tv_usec;]])], [gl_cv_sys_struct_timeval=yes], [gl_cv_sys_struct_timeval=no])]) - if test $gl_cv_sys_struct_timeval = yes; then - HAVE_STRUCT_TIMEVAL=1 - else + if test $gl_cv_sys_struct_timeval != yes; then HAVE_STRUCT_TIMEVAL=0 fi - AC_SUBST([HAVE_STRUCT_TIMEVAL]) + dnl Check for declarations of anything we want to poison if the + dnl corresponding gnulib module is not in use. + gl_WARN_ON_USE_PREPARE([[ +#if HAVE_SYS_TIME_H +# include <sys/time.h> +#endif +#include <time.h> + ]], [gettimeofday]) +]) + +AC_DEFUN([gl_SYS_TIME_MODULE_INDICATOR], +[ + dnl Use AC_REQUIRE here, so that the default settings are expanded once only. + AC_REQUIRE([gl_HEADER_SYS_TIME_H_DEFAULTS]) + GNULIB_[]m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./-],[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])=1 +]) + +AC_DEFUN([gl_HEADER_SYS_TIME_H_DEFAULTS], +[ + GNULIB_GETTIMEOFDAY=0; AC_SUBST([GNULIB_GETTIMEOFDAY]) dnl Assume POSIX behavior unless another module says otherwise. - REPLACE_GETTIMEOFDAY=0 - AC_SUBST([REPLACE_GETTIMEOFDAY]) - if test $HAVE_SYS_TIME_H = 0 || test $HAVE_STRUCT_TIMEVAL = 0; then - SYS_TIME_H=sys/time.h - else - SYS_TIME_H= - fi - AC_SUBST([SYS_TIME_H]) + HAVE_STRUCT_TIMEVAL=1; AC_SUBST([HAVE_STRUCT_TIMEVAL]) + HAVE_SYS_TIME_H=1; AC_SUBST([HAVE_SYS_TIME_H]) + REPLACE_GETTIMEOFDAY=0; AC_SUBST([REPLACE_GETTIMEOFDAY]) ]) diff --git a/libmissing/m4/vsnprintf-posix.m4 b/libmissing/m4/vsnprintf-posix.m4 new file mode 100644 index 0000000..1243717 --- /dev/null +++ b/libmissing/m4/vsnprintf-posix.m4 @@ -0,0 +1,127 @@ +# vsnprintf-posix.m4 serial 14 +dnl Copyright (C) 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_VSNPRINTF_POSIX], +[ + AC_REQUIRE([gl_PRINTF_SIZES_C99]) + AC_REQUIRE([gl_PRINTF_LONG_DOUBLE]) + AC_REQUIRE([gl_PRINTF_INFINITE]) + AC_REQUIRE([gl_PRINTF_INFINITE_LONG_DOUBLE]) + AC_REQUIRE([gl_PRINTF_DIRECTIVE_A]) + AC_REQUIRE([gl_PRINTF_DIRECTIVE_F]) + AC_REQUIRE([gl_PRINTF_DIRECTIVE_N]) + AC_REQUIRE([gl_PRINTF_DIRECTIVE_LS]) + AC_REQUIRE([gl_PRINTF_POSITIONS]) + AC_REQUIRE([gl_PRINTF_FLAG_GROUPING]) + AC_REQUIRE([gl_PRINTF_FLAG_LEFTADJUST]) + AC_REQUIRE([gl_PRINTF_FLAG_ZERO]) + AC_REQUIRE([gl_PRINTF_PRECISION]) + AC_REQUIRE([gl_PRINTF_ENOMEM]) + gl_cv_func_vsnprintf_posix=no + AC_CHECK_FUNCS([vsnprintf]) + if test $ac_cv_func_vsnprintf = yes; then + dnl Assume that if vsnprintf() exists, snprintf() also exists. + gl_SNPRINTF_TRUNCATION_C99 + gl_SNPRINTF_RETVAL_C99 + gl_SNPRINTF_DIRECTIVE_N + gl_SNPRINTF_SIZE1 + gl_VSNPRINTF_ZEROSIZE_C99 + case "$gl_cv_func_printf_sizes_c99" in + *yes) + case "$gl_cv_func_printf_long_double" in + *yes) + case "$gl_cv_func_printf_infinite" in + *yes) + case "$gl_cv_func_printf_infinite_long_double" in + *yes) + case "$gl_cv_func_printf_directive_a" in + *yes) + case "$gl_cv_func_printf_directive_f" in + *yes) + case "$gl_cv_func_printf_directive_n" in + *yes) + case "$gl_cv_func_printf_directive_ls" in + *yes) + case "$gl_cv_func_printf_positions" in + *yes) + case "$gl_cv_func_printf_flag_grouping" in + *yes) + case "$gl_cv_func_printf_flag_leftadjust" in + *yes) + case "$gl_cv_func_printf_flag_zero" in + *yes) + case "$gl_cv_func_printf_precision" in + *yes) + case "$gl_cv_func_printf_enomem" in + *yes) + case "$gl_cv_func_snprintf_truncation_c99" in + *yes) + case "$gl_cv_func_snprintf_retval_c99" in + *yes) + case "$gl_cv_func_snprintf_directive_n" in + *yes) + case "$gl_cv_func_snprintf_size1" in + *yes) + case "$gl_cv_func_vsnprintf_zerosize_c99" in + *yes) + # vsnprintf exists and is + # already POSIX compliant. + gl_cv_func_vsnprintf_posix=yes + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + ;; + esac + fi + if test $gl_cv_func_vsnprintf_posix = no; then + gl_PREREQ_VASNPRINTF_LONG_DOUBLE + gl_PREREQ_VASNPRINTF_INFINITE_DOUBLE + gl_PREREQ_VASNPRINTF_INFINITE_LONG_DOUBLE + gl_PREREQ_VASNPRINTF_DIRECTIVE_A + gl_PREREQ_VASNPRINTF_DIRECTIVE_F + gl_PREREQ_VASNPRINTF_DIRECTIVE_LS + gl_PREREQ_VASNPRINTF_FLAG_GROUPING + gl_PREREQ_VASNPRINTF_FLAG_LEFTADJUST + gl_PREREQ_VASNPRINTF_FLAG_ZERO + gl_PREREQ_VASNPRINTF_PRECISION + gl_PREREQ_VASNPRINTF_ENOMEM + gl_REPLACE_VASNPRINTF + gl_REPLACE_VSNPRINTF + fi +]) diff --git a/libmissing/math.in.h b/libmissing/math.in.h new file mode 100644 index 0000000..4ddc953 --- /dev/null +++ b/libmissing/math.in.h @@ -0,0 +1,633 @@ +/* A GNU-like <math.h>. + + Copyright (C) 2002-2003, 2007-2010 Free Software Foundation, Inc. + + This program 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that 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 this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef _GL_MATH_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT_AS_FIRST_DIRECTIVE@ @NEXT_AS_FIRST_DIRECTIVE_MATH_H@ + +#ifndef _GL_MATH_H +#define _GL_MATH_H + + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + +/* Helper macros to define a portability warning for the + classification macro FUNC called with VALUE. POSIX declares the + classification macros with an argument of real-floating (that is, + one of float, double, or long double). */ +#define _GL_WARN_REAL_FLOATING_DECL(func) \ +static inline int \ +rpl_ ## func ## f (float f) \ +{ \ + return func (f); \ +} \ +static inline int \ +rpl_ ## func ## d (double d) \ +{ \ + return func (d); \ +} \ +static inline int \ +rpl_ ## func ## l (long double l) \ +{ \ + return func (l); \ +} \ +_GL_WARN_ON_USE (rpl_ ## func ## f, #func " is unportable - " \ + "use gnulib module " #func " for portability"); \ +_GL_WARN_ON_USE (rpl_ ## func ## d, #func " is unportable - " \ + "use gnulib module " #func " for portability"); \ +_GL_WARN_ON_USE (rpl_ ## func ## l, #func " is unportable - " \ + "use gnulib module " #func " for portability") +#define _GL_WARN_REAL_FLOATING_IMPL(func, value) \ + (sizeof (value) == sizeof (float) ? rpl_ ## func ## f (value) \ + : sizeof (value) == sizeof (double) ? rpl_ ## func ## d (value) \ + : rpl_ ## func ## l (value)) + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* POSIX allows platforms that don't support NAN. But all major + machines in the past 15 years have supported something close to + IEEE NaN, so we define this unconditionally. We also must define + it on platforms like Solaris 10, where NAN is present but defined + as a function pointer rather than a floating point constant. */ +#if !defined NAN || @REPLACE_NAN@ +# undef NAN + /* The Compaq (ex-DEC) C 6.4 compiler chokes on the expression 0.0 / 0.0. */ +# ifdef __DECC +static float +_NaN () +{ + static float zero = 0.0f; + return zero / zero; +} +# define NAN (_NaN()) +# else +# define NAN (0.0f / 0.0f) +# endif +#endif + +/* Solaris 10 defines HUGE_VAL, but as a function pointer rather + than a floating point constant. */ +#if @REPLACE_HUGE_VAL@ +# undef HUGE_VAL +# define HUGE_VAL (1.0 / 0.0) +#endif + +/* Write x as + x = mantissa * 2^exp + where + If x finite and nonzero: 0.5 <= |mantissa| < 1.0. + If x is zero: mantissa = x, exp = 0. + If x is infinite or NaN: mantissa = x, exp unspecified. + Store exp in *EXPPTR and return mantissa. */ +#if @GNULIB_FREXP@ +# if @REPLACE_FREXP@ +# define frexp rpl_frexp +extern double frexp (double x, int *expptr) _GL_ARG_NONNULL ((2)); +# endif +#elif defined GNULIB_POSIXCHECK +# undef frexp +/* Assume frexp is always declared. */ +_GL_WARN_ON_USE (frexp, "frexp is unportable - " + "use gnulib module frexp for portability"); +#endif + + +#if @GNULIB_ACOSL@ +# if !@HAVE_ACOSL@ || !@HAVE_DECL_ACOSL@ +extern long double acosl (long double x); +# endif +#elif defined GNULIB_POSIXCHECK +# undef acosl +# if HAVE_RAW_DECL_ACOSL +_GL_WARN_ON_USE (acosl, "acosl is unportable - " + "use gnulib module mathl for portability"); +# endif +#endif + + +#if @GNULIB_ASINL@ +# if !@HAVE_ASINL@ || !@HAVE_DECL_ASINL@ +extern long double asinl (long double x); +# endif +#elif defined GNULIB_POSIXCHECK +# undef asinl +# if HAVE_RAW_DECL_ASINL +_GL_WARN_ON_USE (asinl, "asinl is unportable - " + "use gnulib module mathl for portability"); +# endif +#endif + + +#if @GNULIB_ATANL@ +# if !@HAVE_ATANL@ || !@HAVE_DECL_ATANL@ +extern long double atanl (long double x); +# endif +#elif defined GNULIB_POSIXCHECK +# undef atanl +# if HAVE_RAW_DECL_ATANL +_GL_WARN_ON_USE (atanl, "atanl is unportable - " + "use gnulib module mathl for portability"); +# endif +#endif + + +#if @GNULIB_CEILF@ +# if @REPLACE_CEILF@ +# define ceilf rpl_ceilf +extern float ceilf (float x); +# endif +#elif defined GNULIB_POSIXCHECK +# undef ceilf +# if HAVE_RAW_DECL_CEILF +_GL_WARN_ON_USE (ceilf, "ceilf is unportable - " + "use gnulib module ceilf for portability"); +# endif +#endif + +#if @GNULIB_CEILL@ +# if @REPLACE_CEILL@ +# define ceill rpl_ceill +extern long double ceill (long double x); +# endif +#elif defined GNULIB_POSIXCHECK +# undef ceill +# if HAVE_RAW_DECL_CEILL +_GL_WARN_ON_USE (ceill, "ceill is unportable - " + "use gnulib module ceill for portability"); +# endif +#endif + + +#if @GNULIB_COSL@ +# if !@HAVE_COSL@ +# undef cosl +# define cosl rpl_cosl +# endif +# if !@HAVE_COSL@ || !@HAVE_DECL_COSL@ +extern long double cosl (long double x); +# endif +#elif defined GNULIB_POSIXCHECK +# undef cosl +# if HAVE_RAW_DECL_COSL +_GL_WARN_ON_USE (cosl, "cosl is unportable - " + "use gnulib module mathl for portability"); +# endif +#endif + + +#if @GNULIB_EXPL@ +# if !@HAVE_EXPL@ || !@HAVE_DECL_EXPL@ +extern long double expl (long double x); +# endif +#elif defined GNULIB_POSIXCHECK +# undef expl +# if HAVE_RAW_DECL_EXPL +_GL_WARN_ON_USE (expl, "expl is unportable - " + "use gnulib module mathl for portability"); +# endif +#endif + + +#if @GNULIB_FLOORF@ +# if @REPLACE_FLOORF@ +# define floorf rpl_floorf +extern float floorf (float x); +# endif +#elif defined GNULIB_POSIXCHECK +# undef floorf +# if HAVE_RAW_DECL_FLOORF +_GL_WARN_ON_USE (floorf, "floorf is unportable - " + "use gnulib module floorf for portability"); +# endif +#endif + +#if @GNULIB_FLOORL@ +# if @REPLACE_FLOORL@ +# define floorl rpl_floorl +extern long double floorl (long double x); +# endif +#elif defined GNULIB_POSIXCHECK +# undef floorl +# if HAVE_RAW_DECL_FLOORL +_GL_WARN_ON_USE (floorl, "floorl is unportable - " + "use gnulib module floorl for portability"); +# endif +#endif + + +/* Write x as + x = mantissa * 2^exp + where + If x finite and nonzero: 0.5 <= |mantissa| < 1.0. + If x is zero: mantissa = x, exp = 0. + If x is infinite or NaN: mantissa = x, exp unspecified. + Store exp in *EXPPTR and return mantissa. */ +#if @GNULIB_FREXPL@ && @REPLACE_FREXPL@ +# define frexpl rpl_frexpl +#endif +#if (@GNULIB_FREXPL@ && @REPLACE_FREXPL@) || !@HAVE_DECL_FREXPL@ +extern long double frexpl (long double x, int *expptr) _GL_ARG_NONNULL ((2)); +#endif +#if !@GNULIB_FREXPL@ && defined GNULIB_POSIXCHECK +# undef frexpl +# if HAVE_RAW_DECL_FREXPL +_GL_WARN_ON_USE (frexpl, "frexpl is unportable - " + "use gnulib module frexpl for portability"); +# endif +#endif + + +/* Return x * 2^exp. */ +#if @GNULIB_LDEXPL@ && @REPLACE_LDEXPL@ +# define ldexpl rpl_ldexpl +#endif +#if (@GNULIB_LDEXPL@ && @REPLACE_LDEXPL@) || !@HAVE_DECL_LDEXPL@ +extern long double ldexpl (long double x, int exp); +#endif +#if !@GNULIB_LDEXPL@ && defined GNULIB_POSIXCHECK +# undef ldexpl +# if HAVE_RAW_DECL_LDEXPL +_GL_WARN_ON_USE (ldexpl, "ldexpl is unportable - " + "use gnulib module ldexpl for portability"); +# endif +#endif + + +#if @GNULIB_LOGL@ +# if !@HAVE_LOGL@ +# undef logl +# define logl rpl_logl +# endif +# if !@HAVE_LOGL@ || !@HAVE_DECL_LOGL@ +extern long double logl (long double x); +# endif +#elif defined GNULIB_POSIXCHECK +# undef logl +# if HAVE_RAW_DECL_LOGL +_GL_WARN_ON_USE (logl, "logl is unportable - " + "use gnulib module mathl for portability"); +# endif +#endif + + +#if @GNULIB_ROUNDF@ +# if @REPLACE_ROUNDF@ +# undef roundf +# define roundf rpl_roundf +extern float roundf (float x); +# endif +#elif defined GNULIB_POSIXCHECK +# undef roundf +# if HAVE_RAW_DECL_ROUNDF +_GL_WARN_ON_USE (roundf, "roundf is unportable - " + "use gnulib module roundf for portability"); +# endif +#endif + +#if @GNULIB_ROUND@ +# if @REPLACE_ROUND@ +# undef round +# define round rpl_round +extern double round (double x); +# endif +#elif defined GNULIB_POSIXCHECK +# undef round +# if HAVE_RAW_DECL_ROUND +_GL_WARN_ON_USE (round, "round is unportable - " + "use gnulib module round for portability"); +# endif +#endif + +#if @GNULIB_ROUNDL@ +# if @REPLACE_ROUNDL@ +# undef roundl +# define roundl rpl_roundl +extern long double roundl (long double x); +# endif +#elif defined GNULIB_POSIXCHECK +# undef roundl +# if HAVE_RAW_DECL_ROUNDL +_GL_WARN_ON_USE (roundl, "roundl is unportable - " + "use gnulib module roundl for portability"); +# endif +#endif + + +#if @GNULIB_SINL@ +# if !@HAVE_SINL@ +# undef sinl +# define sinl rpl_sinl +# endif +# if !@HAVE_SINL@ || !@HAVE_DECL_SINL@ +extern long double sinl (long double x); +# endif +#elif defined GNULIB_POSIXCHECK +# undef sinl +# if HAVE_RAW_DECL_SINL +_GL_WARN_ON_USE (sinl, "sinl is unportable - " + "use gnulib module mathl for portability"); +# endif +#endif + + +#if @GNULIB_SQRTL@ +# if !@HAVE_SQRTL@ || !@HAVE_DECL_SQRTL@ +extern long double sqrtl (long double x); +# endif +#elif defined GNULIB_POSIXCHECK +# undef sqrtl +# if HAVE_RAW_DECL_SQRTL +_GL_WARN_ON_USE (sqrtl, "sqrtl is unportable - " + "use gnulib module mathl for portability"); +# endif +#endif + + +#if @GNULIB_TANL@ +# if !@HAVE_TANL@ || !@HAVE_DECL_TANL@ +extern long double tanl (long double x); +# endif +#elif defined GNULIB_POSIXCHECK +# undef tanl +# if HAVE_RAW_DECL_TANL +_GL_WARN_ON_USE (tanl, "tanl is unportable - " + "use gnulib module mathl for portability"); +# endif +#endif + + +#if @GNULIB_TRUNCF@ +# if !@HAVE_DECL_TRUNCF@ +# define truncf rpl_truncf +extern float truncf (float x); +# endif +#elif defined GNULIB_POSIXCHECK +# undef truncf +# if HAVE_RAW_DECL_TRUNCF +_GL_WARN_ON_USE (truncf, "truncf is unportable - " + "use gnulib module truncf for portability"); +# endif +#endif + +#if @GNULIB_TRUNC@ +# if !@HAVE_DECL_TRUNC@ +# define trunc rpl_trunc +extern double trunc (double x); +# endif +#elif defined GNULIB_POSIXCHECK +# undef trunc +# if HAVE_RAW_DECL_TRUNC +_GL_WARN_ON_USE (trunc, "trunc is unportable - " + "use gnulib module trunc for portability"); +# endif +#endif + +#if @GNULIB_TRUNCL@ +# if @REPLACE_TRUNCL@ +# undef truncl +# define truncl rpl_truncl +extern long double truncl (long double x); +# endif +#elif defined GNULIB_POSIXCHECK +# undef truncl +# if HAVE_RAW_DECL_TRUNCL +_GL_WARN_ON_USE (truncl, "truncl is unportable - " + "use gnulib module truncl for portability"); +# endif +#endif + + +#if @GNULIB_ISFINITE@ +# if @REPLACE_ISFINITE@ +extern int gl_isfinitef (float x); +extern int gl_isfinited (double x); +extern int gl_isfinitel (long double x); +# undef isfinite +# define isfinite(x) \ + (sizeof (x) == sizeof (long double) ? gl_isfinitel (x) : \ + sizeof (x) == sizeof (double) ? gl_isfinited (x) : \ + gl_isfinitef (x)) +# endif +#elif defined GNULIB_POSIXCHECK +# if defined isfinite +_GL_WARN_REAL_FLOATING_DECL (isfinite); +# undef isfinite +# define isfinite(x) _GL_WARN_REAL_FLOATING_IMPL (isfinite, x) +# endif +#endif + + +#if @GNULIB_ISINF@ +# if @REPLACE_ISINF@ +extern int gl_isinff (float x); +extern int gl_isinfd (double x); +extern int gl_isinfl (long double x); +# undef isinf +# define isinf(x) \ + (sizeof (x) == sizeof (long double) ? gl_isinfl (x) : \ + sizeof (x) == sizeof (double) ? gl_isinfd (x) : \ + gl_isinff (x)) +# endif +#elif defined GNULIB_POSIXCHECK +# if defined isinf +_GL_WARN_REAL_FLOATING_DECL (isinf); +# undef isinf +# define isinf(x) _GL_WARN_REAL_FLOATING_IMPL (isinf, x) +# endif +#endif + + +#if @GNULIB_ISNANF@ +/* Test for NaN for 'float' numbers. */ +# if @HAVE_ISNANF@ +/* The original <math.h> included above provides a declaration of isnan macro + or (older) isnanf function. */ +# if __GNUC__ >= 4 + /* GCC 4.0 and newer provides three built-ins for isnan. */ +# undef isnanf +# define isnanf(x) __builtin_isnanf ((float)(x)) +# elif defined isnan +# undef isnanf +# define isnanf(x) isnan ((float)(x)) +# endif +# else +/* Test whether X is a NaN. */ +# undef isnanf +# define isnanf rpl_isnanf +extern int isnanf (float x); +# endif +#endif + +#if @GNULIB_ISNAND@ +/* Test for NaN for 'double' numbers. + This function is a gnulib extension, unlike isnan() which applied only + to 'double' numbers earlier but now is a type-generic macro. */ +# if @HAVE_ISNAND@ +/* The original <math.h> included above provides a declaration of isnan macro. */ +# if __GNUC__ >= 4 + /* GCC 4.0 and newer provides three built-ins for isnan. */ +# undef isnand +# define isnand(x) __builtin_isnan ((double)(x)) +# else +# undef isnand +# define isnand(x) isnan ((double)(x)) +# endif +# else +/* Test whether X is a NaN. */ +# undef isnand +# define isnand rpl_isnand +extern int isnand (double x); +# endif +#endif + +#if @GNULIB_ISNANL@ +/* Test for NaN for 'long double' numbers. */ +# if @HAVE_ISNANL@ +/* The original <math.h> included above provides a declaration of isnan macro or (older) isnanl function. */ +# if __GNUC__ >= 4 + /* GCC 4.0 and newer provides three built-ins for isnan. */ +# undef isnanl +# define isnanl(x) __builtin_isnanl ((long double)(x)) +# elif defined isnan +# undef isnanl +# define isnanl(x) isnan ((long double)(x)) +# endif +# else +/* Test whether X is a NaN. */ +# undef isnanl +# define isnanl rpl_isnanl +extern int isnanl (long double x); +# endif +#endif + +/* This must come *after* the snippets for GNULIB_ISNANF and GNULIB_ISNANL! */ +#if @GNULIB_ISNAN@ +# if @REPLACE_ISNAN@ +/* We can't just use the isnanf macro (e.g.) as exposed by + isnanf.h (e.g.) here, because those may end up being macros + that recursively expand back to isnan. So use the gnulib + replacements for them directly. */ +# if @HAVE_ISNANF@ && __GNUC__ >= 4 +# define gl_isnan_f(x) __builtin_isnan ((float)(x)) +# else +extern int rpl_isnanf (float x); +# define gl_isnan_f(x) rpl_isnanf (x) +# endif +# if @HAVE_ISNAND@ && __GNUC__ >= 4 +# define gl_isnan_d(x) __builtin_isnan ((double)(x)) +# else +extern int rpl_isnand (double x); +# define gl_isnan_d(x) rpl_isnand (x) +# endif +# if @HAVE_ISNANL@ && __GNUC__ >= 4 +# define gl_isnan_l(x) __builtin_isnan ((long double)(x)) +# else +extern int rpl_isnanl (long double x); +# define gl_isnan_l(x) rpl_isnanl (x) +# endif +# undef isnan +# define isnan(x) \ + (sizeof (x) == sizeof (long double) ? gl_isnan_l (x) : \ + sizeof (x) == sizeof (double) ? gl_isnan_d (x) : \ + gl_isnan_f (x)) +# endif +#elif defined GNULIB_POSIXCHECK +# if defined isnan +_GL_WARN_REAL_FLOATING_DECL (isnan); +# undef isnan +# define isnan(x) _GL_WARN_REAL_FLOATING_IMPL (isnan, x) +# endif +#endif + + +#if @GNULIB_SIGNBIT@ +# if @REPLACE_SIGNBIT_USING_GCC@ +# undef signbit + /* GCC 4.0 and newer provides three built-ins for signbit. */ +# define signbit(x) \ + (sizeof (x) == sizeof (long double) ? __builtin_signbitl (x) : \ + sizeof (x) == sizeof (double) ? __builtin_signbit (x) : \ + __builtin_signbitf (x)) +# endif +# if @REPLACE_SIGNBIT@ +# undef signbit +extern int gl_signbitf (float arg); +extern int gl_signbitd (double arg); +extern int gl_signbitl (long double arg); +# if __GNUC__ >= 2 && !__STRICT_ANSI__ +# if defined FLT_SIGNBIT_WORD && defined FLT_SIGNBIT_BIT && !defined gl_signbitf +# define gl_signbitf_OPTIMIZED_MACRO +# define gl_signbitf(arg) \ + ({ union { float _value; \ + unsigned int _word[(sizeof (float) + sizeof (unsigned int) - 1) / sizeof (unsigned int)]; \ + } _m; \ + _m._value = (arg); \ + (_m._word[FLT_SIGNBIT_WORD] >> FLT_SIGNBIT_BIT) & 1; \ + }) +# endif +# if defined DBL_SIGNBIT_WORD && defined DBL_SIGNBIT_BIT && !defined gl_signbitd +# define gl_signbitd_OPTIMIZED_MACRO +# define gl_signbitd(arg) \ + ({ union { double _value; \ + unsigned int _word[(sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int)]; \ + } _m; \ + _m._value = (arg); \ + (_m._word[DBL_SIGNBIT_WORD] >> DBL_SIGNBIT_BIT) & 1; \ + }) +# endif +# if defined LDBL_SIGNBIT_WORD && defined LDBL_SIGNBIT_BIT && !defined gl_signbitl +# define gl_signbitl_OPTIMIZED_MACRO +# define gl_signbitl(arg) \ + ({ union { long double _value; \ + unsigned int _word[(sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int)]; \ + } _m; \ + _m._value = (arg); \ + (_m._word[LDBL_SIGNBIT_WORD] >> LDBL_SIGNBIT_BIT) & 1; \ + }) +# endif +# endif +# define signbit(x) \ + (sizeof (x) == sizeof (long double) ? gl_signbitl (x) : \ + sizeof (x) == sizeof (double) ? gl_signbitd (x) : \ + gl_signbitf (x)) +# endif +#elif defined GNULIB_POSIXCHECK +# if defined signbit +_GL_WARN_REAL_FLOATING_DECL (signbit); +# undef signbit +# define signbit(x) _GL_WARN_REAL_FLOATING_IMPL (signbit, x) +# endif +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* _GL_MATH_H */ +#endif /* _GL_MATH_H */ diff --git a/libmissing/printf-frexp.c b/libmissing/printf-frexp.c new file mode 100644 index 0000000..cf6efdb --- /dev/null +++ b/libmissing/printf-frexp.c @@ -0,0 +1,188 @@ +/* Split a double into fraction and mantissa, for hexadecimal printf. + Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc. + + This program 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that 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 this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#ifdef USE_LONG_DOUBLE +# include "printf-frexpl.h" +#else +# include "printf-frexp.h" +#endif + +#include <float.h> +#include <math.h> +#ifdef USE_LONG_DOUBLE +# include "fpucw.h" +#endif + +/* This file assumes FLT_RADIX = 2. If FLT_RADIX is a power of 2 greater + than 2, or not even a power of 2, some rounding errors can occur, so that + then the returned mantissa is only guaranteed to be <= 2.0, not < 2.0. */ + +#ifdef USE_LONG_DOUBLE +# define FUNC printf_frexpl +# define DOUBLE long double +# define MIN_EXP LDBL_MIN_EXP +# if HAVE_FREXPL_IN_LIBC && HAVE_LDEXPL_IN_LIBC +# define USE_FREXP_LDEXP +# define FREXP frexpl +# define LDEXP ldexpl +# endif +# define DECL_ROUNDING DECL_LONG_DOUBLE_ROUNDING +# define BEGIN_ROUNDING() BEGIN_LONG_DOUBLE_ROUNDING () +# define END_ROUNDING() END_LONG_DOUBLE_ROUNDING () +# define L_(literal) literal##L +#else +# define FUNC printf_frexp +# define DOUBLE double +# define MIN_EXP DBL_MIN_EXP +# if HAVE_FREXP_IN_LIBC && HAVE_LDEXP_IN_LIBC +# define USE_FREXP_LDEXP +# define FREXP frexp +# define LDEXP ldexp +# endif +# define DECL_ROUNDING +# define BEGIN_ROUNDING() +# define END_ROUNDING() +# define L_(literal) literal +#endif + +DOUBLE +FUNC (DOUBLE x, int *expptr) +{ + int exponent; + DECL_ROUNDING + + BEGIN_ROUNDING (); + +#ifdef USE_FREXP_LDEXP + /* frexp and ldexp are usually faster than the loop below. */ + x = FREXP (x, &exponent); + + x = x + x; + exponent -= 1; + + if (exponent < MIN_EXP - 1) + { + x = LDEXP (x, exponent - (MIN_EXP - 1)); + exponent = MIN_EXP - 1; + } +#else + { + /* Since the exponent is an 'int', it fits in 64 bits. Therefore the + loops are executed no more than 64 times. */ + DOUBLE pow2[64]; /* pow2[i] = 2^2^i */ + DOUBLE powh[64]; /* powh[i] = 2^-2^i */ + int i; + + exponent = 0; + if (x >= L_(1.0)) + { + /* A nonnegative exponent. */ + { + DOUBLE pow2_i; /* = pow2[i] */ + DOUBLE powh_i; /* = powh[i] */ + + /* Invariants: pow2_i = 2^2^i, powh_i = 2^-2^i, + x * 2^exponent = argument, x >= 1.0. */ + for (i = 0, pow2_i = L_(2.0), powh_i = L_(0.5); + ; + i++, pow2_i = pow2_i * pow2_i, powh_i = powh_i * powh_i) + { + if (x >= pow2_i) + { + exponent += (1 << i); + x *= powh_i; + } + else + break; + + pow2[i] = pow2_i; + powh[i] = powh_i; + } + } + /* Here 1.0 <= x < 2^2^i. */ + } + else + { + /* A negative exponent. */ + { + DOUBLE pow2_i; /* = pow2[i] */ + DOUBLE powh_i; /* = powh[i] */ + + /* Invariants: pow2_i = 2^2^i, powh_i = 2^-2^i, + x * 2^exponent = argument, x < 1.0, exponent >= MIN_EXP - 1. */ + for (i = 0, pow2_i = L_(2.0), powh_i = L_(0.5); + ; + i++, pow2_i = pow2_i * pow2_i, powh_i = powh_i * powh_i) + { + if (exponent - (1 << i) < MIN_EXP - 1) + break; + + exponent -= (1 << i); + x *= pow2_i; + if (x >= L_(1.0)) + break; + + pow2[i] = pow2_i; + powh[i] = powh_i; + } + } + /* Here either x < 1.0 and exponent - 2^i < MIN_EXP - 1 <= exponent, + or 1.0 <= x < 2^2^i and exponent >= MIN_EXP - 1. */ + + if (x < L_(1.0)) + /* Invariants: x * 2^exponent = argument, x < 1.0 and + exponent - 2^i < MIN_EXP - 1 <= exponent. */ + while (i > 0) + { + i--; + if (exponent - (1 << i) >= MIN_EXP - 1) + { + exponent -= (1 << i); + x *= pow2[i]; + if (x >= L_(1.0)) + break; + } + } + + /* Here either x < 1.0 and exponent = MIN_EXP - 1, + or 1.0 <= x < 2^2^i and exponent >= MIN_EXP - 1. */ + } + + /* Invariants: x * 2^exponent = argument, and + either x < 1.0 and exponent = MIN_EXP - 1, + or 1.0 <= x < 2^2^i and exponent >= MIN_EXP - 1. */ + while (i > 0) + { + i--; + if (x >= pow2[i]) + { + exponent += (1 << i); + x *= powh[i]; + } + } + /* Here either x < 1.0 and exponent = MIN_EXP - 1, + or 1.0 <= x < 2.0 and exponent >= MIN_EXP - 1. */ + } +#endif + + END_ROUNDING (); + + *expptr = exponent; + return x; +} diff --git a/libmissing/printf-frexp.h b/libmissing/printf-frexp.h new file mode 100644 index 0000000..1cbb096 --- /dev/null +++ b/libmissing/printf-frexp.h @@ -0,0 +1,23 @@ +/* Split a double into fraction and mantissa, for hexadecimal printf. + Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc. + + This program 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that 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 this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Write a finite, positive number x as + x = mantissa * 2^exp + where exp >= DBL_MIN_EXP - 1, + mantissa < 2.0, + if x is not a denormalized number then mantissa >= 1.0. + Store exp in *EXPPTR and return mantissa. */ +extern double printf_frexp (double x, int *expptr); diff --git a/libmissing/printf-frexpl.c b/libmissing/printf-frexpl.c new file mode 100644 index 0000000..6ee1e9b --- /dev/null +++ b/libmissing/printf-frexpl.c @@ -0,0 +1,18 @@ +/* Split a 'long double' into fraction and mantissa, for hexadecimal printf. + Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc. + + This program 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that 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 this program. If not, see <http://www.gnu.org/licenses/>. */ + +#define USE_LONG_DOUBLE +#include "printf-frexp.c" diff --git a/libmissing/printf-frexpl.h b/libmissing/printf-frexpl.h new file mode 100644 index 0000000..4783bbb --- /dev/null +++ b/libmissing/printf-frexpl.h @@ -0,0 +1,23 @@ +/* Split a 'long double' into fraction and mantissa, for hexadecimal printf. + Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc. + + This program 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that 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 this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Write a finite, positive number x as + x = mantissa * 2^exp + where exp >= LDBL_MIN_EXP - 1, + mantissa < 2.0, + if x is not a denormalized number then mantissa >= 1.0. + Store exp in *EXPPTR and return mantissa. */ +extern long double printf_frexpl (long double x, int *expptr); diff --git a/libmissing/regcomp.c b/libmissing/regcomp.c index f8c4aaa..fd1cc69 100644 --- a/libmissing/regcomp.c +++ b/libmissing/regcomp.c @@ -1021,11 +1021,10 @@ create_initial_state (re_dfa_t *dfa) Idx dest_idx = dfa->edests[node_idx].elems[0]; if (!re_node_set_contains (&init_nodes, dest_idx)) { - reg_errcode_t err = re_node_set_merge (&init_nodes, - dfa->eclosures - + dest_idx); - if (err != REG_NOERROR) - return err; + reg_errcode_t merge_err + = re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx); + if (merge_err != REG_NOERROR) + return merge_err; i = 0; } } @@ -2578,10 +2577,14 @@ parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa, if (BE (tree == NULL, 0)) goto parse_dup_op_espace; +/* From gnulib's "intprops.h": + True if the arithmetic type T is signed. */ +#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) + /* This loop is actually executed only when end != REG_MISSING, to rewrite <re>{0,n} as (<re>(<re>...<re>?)?)?... We have already created the start+1-th copy. */ - if ((Idx) -1 < 0 || end != REG_MISSING) + if (TYPE_SIGNED (Idx) || end != REG_MISSING) for (i = start + 2; i <= end; ++i) { elem = duplicate_tree (elem, dfa); diff --git a/libmissing/signbitd.c b/libmissing/signbitd.c new file mode 100644 index 0000000..d0fb4a9 --- /dev/null +++ b/libmissing/signbitd.c @@ -0,0 +1,64 @@ +/* signbit() macro: Determine the sign bit of a floating-point number. + Copyright (C) 2007-2010 Free Software Foundation, Inc. + + This program 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that 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 this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <math.h> + +#include <string.h> +#include "isnand-nolibm.h" +#include "float+.h" + +#ifdef gl_signbitd_OPTIMIZED_MACRO +# undef gl_signbitd +#endif + +int +gl_signbitd (double arg) +{ +#if defined DBL_SIGNBIT_WORD && defined DBL_SIGNBIT_BIT + /* The use of a union to extract the bits of the representation of a + 'long double' is safe in practice, despite of the "aliasing rules" of + C99, because the GCC docs say + "Even with '-fstrict-aliasing', type-punning is allowed, provided the + memory is accessed through the union type." + and similarly for other compilers. */ +# define NWORDS \ + ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) + union { double value; unsigned int word[NWORDS]; } m; + m.value = arg; + return (m.word[DBL_SIGNBIT_WORD] >> DBL_SIGNBIT_BIT) & 1; +#elif HAVE_COPYSIGN_IN_LIBC + return copysign (1.0, arg) < 0; +#else + /* This does not do the right thing for NaN, but this is irrelevant for + most use cases. */ + if (isnand (arg)) + return 0; + if (arg < 0.0) + return 1; + else if (arg == 0.0) + { + /* Distinguish 0.0 and -0.0. */ + static double plus_zero = 0.0; + double arg_mem = arg; + return (memcmp (&plus_zero, &arg_mem, SIZEOF_DBL) != 0); + } + else + return 0; +#endif +} diff --git a/libmissing/signbitf.c b/libmissing/signbitf.c new file mode 100644 index 0000000..f2ef1d9 --- /dev/null +++ b/libmissing/signbitf.c @@ -0,0 +1,64 @@ +/* signbit() macro: Determine the sign bit of a floating-point number. + Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc. + + This program 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that 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 this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <math.h> + +#include <string.h> +#include "isnanf-nolibm.h" +#include "float+.h" + +#ifdef gl_signbitf_OPTIMIZED_MACRO +# undef gl_signbitf +#endif + +int +gl_signbitf (float arg) +{ +#if defined FLT_SIGNBIT_WORD && defined FLT_SIGNBIT_BIT + /* The use of a union to extract the bits of the representation of a + 'long double' is safe in practice, despite of the "aliasing rules" of + C99, because the GCC docs say + "Even with '-fstrict-aliasing', type-punning is allowed, provided the + memory is accessed through the union type." + and similarly for other compilers. */ +# define NWORDS \ + ((sizeof (float) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) + union { float value; unsigned int word[NWORDS]; } m; + m.value = arg; + return (m.word[FLT_SIGNBIT_WORD] >> FLT_SIGNBIT_BIT) & 1; +#elif HAVE_COPYSIGNF_IN_LIBC + return copysignf (1.0f, arg) < 0; +#else + /* This does not do the right thing for NaN, but this is irrelevant for + most use cases. */ + if (isnanf (arg)) + return 0; + if (arg < 0.0f) + return 1; + else if (arg == 0.0f) + { + /* Distinguish 0.0f and -0.0f. */ + static float plus_zero = 0.0f; + float arg_mem = arg; + return (memcmp (&plus_zero, &arg_mem, SIZEOF_FLT) != 0); + } + else + return 0; +#endif +} diff --git a/libmissing/signbitl.c b/libmissing/signbitl.c new file mode 100644 index 0000000..adcb71e --- /dev/null +++ b/libmissing/signbitl.c @@ -0,0 +1,64 @@ +/* signbit() macro: Determine the sign bit of a floating-point number. + Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc. + + This program 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that 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 this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <math.h> + +#include <string.h> +#include "isnanl-nolibm.h" +#include "float+.h" + +#ifdef gl_signbitl_OPTIMIZED_MACRO +# undef gl_signbitl +#endif + +int +gl_signbitl (long double arg) +{ +#if defined LDBL_SIGNBIT_WORD && defined LDBL_SIGNBIT_BIT + /* The use of a union to extract the bits of the representation of a + 'long double' is safe in practice, despite of the "aliasing rules" of + C99, because the GCC docs say + "Even with '-fstrict-aliasing', type-punning is allowed, provided the + memory is accessed through the union type." + and similarly for other compilers. */ +# define NWORDS \ + ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) + union { long double value; unsigned int word[NWORDS]; } m; + m.value = arg; + return (m.word[LDBL_SIGNBIT_WORD] >> LDBL_SIGNBIT_BIT) & 1; +#elif HAVE_COPYSIGNL_IN_LIBC + return copysignl (1.0L, arg) < 0; +#else + /* This does not do the right thing for NaN, but this is irrelevant for + most use cases. */ + if (isnanl (arg)) + return 0; + if (arg < 0.0L) + return 1; + else if (arg == 0.0L) + { + /* Distinguish 0.0L and -0.0L. */ + static long double plus_zero = 0.0L; + long double arg_mem = arg; + return (memcmp (&plus_zero, &arg_mem, SIZEOF_LDBL) != 0); + } + else + return 0; +#endif +} diff --git a/libmissing/stdio.in.h b/libmissing/stdio.in.h index 5454245..f5d5d88 100644 --- a/libmissing/stdio.in.h +++ b/libmissing/stdio.in.h @@ -340,7 +340,11 @@ extern size_t fwrite (const void *ptr, size_t s, size_t n, FILE *stream) #endif #if @GNULIB_GETDELIM@ -# if !@HAVE_DECL_GETDELIM@ +# if @REPLACE_GETDELIM@ +# undef getdelim +# define getdelim rpl_getdelim +# endif +# if !@HAVE_DECL_GETDELIM@ || @REPLACE_GETDELIM@ /* Read input, up to (and including) the next occurrence of DELIMITER, from STREAM, store it in *LINEPTR (and NUL-terminate it). *LINEPTR is a pointer returned from malloc (or NULL), pointing to *LINESIZE diff --git a/libmissing/sys_time.in.h b/libmissing/sys_time.in.h index 544a725..00a497f 100644 --- a/libmissing/sys_time.in.h +++ b/libmissing/sys_time.in.h @@ -41,6 +41,8 @@ /* The definition of _GL_ARG_NONNULL is copied here. */ +/* The definition of _GL_WARN_ON_USE is copied here. */ + #ifdef __cplusplus extern "C" { #endif @@ -53,11 +55,19 @@ struct timeval }; # endif -# if @REPLACE_GETTIMEOFDAY@ -# undef gettimeofday -# define gettimeofday rpl_gettimeofday +# if @GNULIB_GETTIMEOFDAY@ +# if @REPLACE_GETTIMEOFDAY@ +# undef gettimeofday +# define gettimeofday rpl_gettimeofday extern int gettimeofday (struct timeval *restrict, void *restrict) _GL_ARG_NONNULL ((1)); +# endif +# elif defined GNULIB_POSIXCHECK +# undef gettimeofday +# if HAVE_RAW_DECL_GETTIMEOFDAY +_GL_WARN_ON_USE (gettimeofday, "gettimeofday is unportable - " + "use gnulib module gettimeofday for portability"); +# endif # endif #ifdef __cplusplus diff --git a/libmissing/tests/Makefile.am b/libmissing/tests/Makefile.am index a384629..9ef6d4b 100644 --- a/libmissing/tests/Makefile.am +++ b/libmissing/tests/Makefile.am @@ -218,6 +218,24 @@ EXTRA_DIST += test-fopen.h test-fopen.c signature.h macros.h ## end gnulib module fopen-tests +## begin gnulib module frexp-nolibm-tests + +TESTS += test-frexp-nolibm +check_PROGRAMS += test-frexp-nolibm +test_frexp_nolibm_SOURCES = test-frexp.c +EXTRA_DIST += test-frexp.c signature.h macros.h + +## end gnulib module frexp-nolibm-tests + +## begin gnulib module frexpl-nolibm-tests + +TESTS += test-frexpl-nolibm +check_PROGRAMS += test-frexpl-nolibm +test_frexpl_nolibm_SOURCES = test-frexpl.c +EXTRA_DIST += test-frexpl.c signature.h macros.h + +## end gnulib module frexpl-nolibm-tests + ## begin gnulib module fseeko-tests TESTS += test-fseeko.sh test-fseeko2.sh @@ -280,6 +298,12 @@ EXTRA_DIST += signature.h test-gettimeofday.c ## end gnulib module gettimeofday-tests +## begin gnulib module ignore-value + +libtests_a_SOURCES += ignore-value.h + +## end gnulib module ignore-value + ## begin gnulib module inet_ntop-tests TESTS += test-inet_ntop @@ -298,6 +322,33 @@ EXTRA_DIST += test-inet_pton.c signature.h macros.h ## end gnulib module inet_pton-tests +## begin gnulib module isnand-nolibm-tests + +TESTS += test-isnand-nolibm +check_PROGRAMS += test-isnand-nolibm + +EXTRA_DIST += test-isnand-nolibm.c test-isnand.h nan.h macros.h + +## end gnulib module isnand-nolibm-tests + +## begin gnulib module isnanf-nolibm-tests + +TESTS += test-isnanf-nolibm +check_PROGRAMS += test-isnanf-nolibm + +EXTRA_DIST += test-isnanf-nolibm.c test-isnanf.h nan.h macros.h + +## end gnulib module isnanf-nolibm-tests + +## begin gnulib module isnanl-nolibm-tests + +TESTS += test-isnanl-nolibm +check_PROGRAMS += test-isnanl-nolibm + +EXTRA_DIST += test-isnanl-nolibm.c test-isnanl.h nan.h macros.h + +## end gnulib module isnanl-nolibm-tests + ## begin gnulib module langinfo-tests TESTS += test-langinfo @@ -340,6 +391,14 @@ EXTRA_DIST += test-lstat.h test-lstat.c signature.h macros.h ## end gnulib module lstat-tests +## begin gnulib module math-tests + +TESTS += test-math +check_PROGRAMS += test-math +EXTRA_DIST += test-math.c + +## end gnulib module math-tests + ## begin gnulib module mbrtowc-tests TESTS += test-mbrtowc1.sh test-mbrtowc2.sh test-mbrtowc3.sh test-mbrtowc4.sh @@ -440,6 +499,22 @@ EXTRA_DIST += signature.h test-poll.c ## end gnulib module poll-tests +## begin gnulib module printf-frexp-tests + +TESTS += test-printf-frexp +check_PROGRAMS += test-printf-frexp +EXTRA_DIST += test-printf-frexp.c macros.h + +## end gnulib module printf-frexp-tests + +## begin gnulib module printf-frexpl-tests + +TESTS += test-printf-frexpl +check_PROGRAMS += test-printf-frexpl +EXTRA_DIST += test-printf-frexpl.c macros.h + +## end gnulib module printf-frexpl-tests + ## begin gnulib module same-inode @@ -467,6 +542,15 @@ EXTRA_DIST += test-signal.c ## end gnulib module signal-tests +## begin gnulib module signbit-tests + +TESTS += test-signbit +check_PROGRAMS += test-signbit + +EXTRA_DIST += test-signbit.c macros.h + +## end gnulib module signbit-tests + ## begin gnulib module sleep-tests TESTS += test-sleep @@ -475,6 +559,15 @@ EXTRA_DIST += test-sleep.c signature.h macros.h ## end gnulib module sleep-tests +## begin gnulib module snprintf-posix-tests + +TESTS += test-snprintf-posix test-snprintf +check_PROGRAMS += test-snprintf-posix test-snprintf + +EXTRA_DIST += test-snprintf-posix.c test-snprintf-posix.h test-snprintf.c nan.h signature.h macros.h + +## end gnulib module snprintf-posix-tests + ## begin gnulib module snprintf-tests TESTS += test-snprintf @@ -683,6 +776,15 @@ EXTRA_DIST += test-vasnprintf.c macros.h ## end gnulib module vasnprintf-tests +## begin gnulib module vsnprintf-posix-tests + +TESTS += test-vsnprintf-posix test-vsnprintf +check_PROGRAMS += test-vsnprintf-posix test-vsnprintf + +EXTRA_DIST += test-vsnprintf-posix.c test-snprintf-posix.h test-vsnprintf.c nan.h signature.h macros.h + +## end gnulib module vsnprintf-posix-tests + ## begin gnulib module vsnprintf-tests TESTS += test-vsnprintf diff --git a/libmissing/tests/ignore-value.h b/libmissing/tests/ignore-value.h new file mode 100644 index 0000000..2eb6918 --- /dev/null +++ b/libmissing/tests/ignore-value.h @@ -0,0 +1,37 @@ +/* ignore a function return without a compiler warning + + Copyright (C) 2008-2010 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Jim Meyering. */ + +/* Use these functions to avoid a warning when using a function declared with + gcc's warn_unused_result attribute, but for which you really do want to + ignore the result. Traditionally, people have used a "(void)" cast to + indicate that a function's return value is deliberately unused. However, + if the function is declared with __attribute__((warn_unused_result)), + gcc issues a warning even with the cast. + + Caution: most of the time, you really should heed gcc's warning, and + check the return value. However, in those exceptional cases in which + you're sure you know what you're doing, use this function. + + For the record, here's one of the ignorable warnings: + "copy.c:233: warning: ignoring return value of 'fchown', + declared with attribute warn_unused_result". */ + +static inline void ignore_value (int i) { (void) i; } +static inline void ignore_ptr (void* p) { (void) p; } +/* FIXME: what about aggregate types? */ diff --git a/libmissing/tests/nan.h b/libmissing/tests/nan.h new file mode 100644 index 0000000..611eed3 --- /dev/null +++ b/libmissing/tests/nan.h @@ -0,0 +1,60 @@ +/* Macros for not-a-number. + Copyright (C) 2007-2010 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + + +/* NaNf () returns a 'float' not-a-number. */ + +/* The Compaq (ex-DEC) C 6.4 compiler chokes on the expression 0.0 / 0.0. */ +#ifdef __DECC +static float +NaNf () +{ + static float zero = 0.0f; + return zero / zero; +} +#else +# define NaNf() (0.0f / 0.0f) +#endif + + +/* NaNd () returns a 'double' not-a-number. */ + +/* The Compaq (ex-DEC) C 6.4 compiler chokes on the expression 0.0 / 0.0. */ +#ifdef __DECC +static double +NaNd () +{ + static double zero = 0.0; + return zero / zero; +} +#else +# define NaNd() (0.0 / 0.0) +#endif + + +/* NaNl () returns a 'long double' not-a-number. */ + +/* On Irix 6.5, gcc 3.4.3 can't compute compile-time NaN, and needs the + runtime type conversion. */ +#ifdef __sgi +static long double NaNl () +{ + double zero = 0.0; + return zero / zero; +} +#else +# define NaNl() (0.0L / 0.0L) +#endif diff --git a/libmissing/tests/test-frexp.c b/libmissing/tests/test-frexp.c new file mode 100644 index 0000000..d5ab7e5 --- /dev/null +++ b/libmissing/tests/test-frexp.c @@ -0,0 +1,199 @@ +/* Test of splitting a double into fraction and mantissa. + Copyright (C) 2007-2010 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <[email protected]>, 2007. */ + +#include <config.h> + +#include <math.h> + +#include "signature.h" +SIGNATURE_CHECK (frexp, double, (double, int *)); + +#include <float.h> + +#include "isnand-nolibm.h" +#include "nan.h" +#include "macros.h" + +/* Avoid some warnings from "gcc -Wshadow". + This file doesn't use the exp() function. */ +#undef exp +#define exp exponent + +/* HP cc on HP-UX 10.20 has a bug with the constant expression -0.0. + So we use -zero instead. */ +double zero = 0.0; + +static double +my_ldexp (double x, int d) +{ + for (; d > 0; d--) + x *= 2.0; + for (; d < 0; d++) + x *= 0.5; + return x; +} + +int +main () +{ + int i; + /* The use of 'volatile' guarantees that excess precision bits are dropped + when dealing with denormalized numbers. It is necessary on x86 systems + where double-floats are not IEEE compliant by default, to avoid that the + results become platform and compiler option dependent. 'volatile' is a + portable alternative to gcc's -ffloat-store option. */ + volatile double x; + + { /* NaN. */ + int exp = -9999; + double mantissa; + x = NaNd (); + mantissa = frexp (x, &exp); + ASSERT (isnand (mantissa)); + } + + { /* Positive infinity. */ + int exp = -9999; + double mantissa; + x = 1.0 / 0.0; + mantissa = frexp (x, &exp); + ASSERT (mantissa == x); + } + + { /* Negative infinity. */ + int exp = -9999; + double mantissa; + x = -1.0 / 0.0; + mantissa = frexp (x, &exp); + ASSERT (mantissa == x); + } + + { /* Positive zero. */ + int exp = -9999; + double mantissa; + x = 0.0; + mantissa = frexp (x, &exp); + ASSERT (exp == 0); + ASSERT (mantissa == x); + ASSERT (!signbit (mantissa)); + } + + { /* Negative zero. */ + int exp = -9999; + double mantissa; + x = -zero; + mantissa = frexp (x, &exp); + ASSERT (exp == 0); + ASSERT (mantissa == x); + ASSERT (signbit (mantissa)); + } + + for (i = 1, x = 1.0; i <= DBL_MAX_EXP; i++, x *= 2.0) + { + int exp = -9999; + double mantissa = frexp (x, &exp); + ASSERT (exp == i); + ASSERT (mantissa == 0.5); + } + for (i = 1, x = 1.0; i >= DBL_MIN_EXP; i--, x *= 0.5) + { + int exp = -9999; + double mantissa = frexp (x, &exp); + ASSERT (exp == i); + ASSERT (mantissa == 0.5); + } + for (; i >= DBL_MIN_EXP - 100 && x > 0.0; i--, x *= 0.5) + { + int exp = -9999; + double mantissa = frexp (x, &exp); + ASSERT (exp == i); + ASSERT (mantissa == 0.5); + } + + for (i = 1, x = -1.0; i <= DBL_MAX_EXP; i++, x *= 2.0) + { + int exp = -9999; + double mantissa = frexp (x, &exp); + ASSERT (exp == i); + ASSERT (mantissa == -0.5); + } + for (i = 1, x = -1.0; i >= DBL_MIN_EXP; i--, x *= 0.5) + { + int exp = -9999; + double mantissa = frexp (x, &exp); + ASSERT (exp == i); + ASSERT (mantissa == -0.5); + } + for (; i >= DBL_MIN_EXP - 100 && x < 0.0; i--, x *= 0.5) + { + int exp = -9999; + double mantissa = frexp (x, &exp); + ASSERT (exp == i); + ASSERT (mantissa == -0.5); + } + + for (i = 1, x = 1.01; i <= DBL_MAX_EXP; i++, x *= 2.0) + { + int exp = -9999; + double mantissa = frexp (x, &exp); + ASSERT (exp == i); + ASSERT (mantissa == 0.505); + } + for (i = 1, x = 1.01; i >= DBL_MIN_EXP; i--, x *= 0.5) + { + int exp = -9999; + double mantissa = frexp (x, &exp); + ASSERT (exp == i); + ASSERT (mantissa == 0.505); + } + for (; i >= DBL_MIN_EXP - 100 && x > 0.0; i--, x *= 0.5) + { + int exp = -9999; + double mantissa = frexp (x, &exp); + ASSERT (exp == i); + ASSERT (mantissa >= 0.5); + ASSERT (mantissa < 1.0); + ASSERT (mantissa == my_ldexp (x, - exp)); + } + + for (i = 1, x = 1.73205; i <= DBL_MAX_EXP; i++, x *= 2.0) + { + int exp = -9999; + double mantissa = frexp (x, &exp); + ASSERT (exp == i); + ASSERT (mantissa == 0.866025); + } + for (i = 1, x = 1.73205; i >= DBL_MIN_EXP; i--, x *= 0.5) + { + int exp = -9999; + double mantissa = frexp (x, &exp); + ASSERT (exp == i); + ASSERT (mantissa == 0.866025); + } + for (; i >= DBL_MIN_EXP - 100 && x > 0.0; i--, x *= 0.5) + { + int exp = -9999; + double mantissa = frexp (x, &exp); + ASSERT (exp == i || exp == i + 1); + ASSERT (mantissa >= 0.5); + ASSERT (mantissa < 1.0); + ASSERT (mantissa == my_ldexp (x, - exp)); + } + + return 0; +} diff --git a/libmissing/tests/test-frexpl.c b/libmissing/tests/test-frexpl.c new file mode 100644 index 0000000..8d9d41d --- /dev/null +++ b/libmissing/tests/test-frexpl.c @@ -0,0 +1,223 @@ +/* Test of splitting a 'long double' into fraction and mantissa. + Copyright (C) 2007-2010 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <[email protected]>, 2007. */ + +#include <config.h> + +#include <math.h> + +#include "signature.h" +SIGNATURE_CHECK (frexpl, long double, (long double, int *)); + +#include <float.h> + +#include "fpucw.h" +#include "isnanl-nolibm.h" +#include "nan.h" +#include "macros.h" + +/* Avoid some warnings from "gcc -Wshadow". + This file doesn't use the exp() function. */ +#undef exp +#define exp exponent + +/* On MIPS IRIX machines, LDBL_MIN_EXP is -1021, but the smallest reliable + exponent for 'long double' is -964. Similarly, on PowerPC machines, + LDBL_MIN_EXP is -1021, but the smallest reliable exponent for 'long double' + is -968. For exponents below that, the precision may be truncated to the + precision used for 'double'. */ +#ifdef __sgi +# define MIN_NORMAL_EXP (LDBL_MIN_EXP + 57) +#elif defined __ppc || defined __ppc__ || defined __powerpc || defined __powerpc__ +# define MIN_NORMAL_EXP (LDBL_MIN_EXP + 53) +#else +# define MIN_NORMAL_EXP LDBL_MIN_EXP +#endif + +/* On HP-UX 10.20, negating 0.0L does not yield -0.0L. + So we use minus_zero instead. + IRIX cc can't put -0.0L into .data, but can compute at runtime. + Note that the expression -LDBL_MIN * LDBL_MIN does not work on other + platforms, such as when cross-compiling to PowerPC on MacOS X 10.5. */ +#if defined __hpux || defined __sgi +static long double +compute_minus_zero (void) +{ + return -LDBL_MIN * LDBL_MIN; +} +# define minus_zero compute_minus_zero () +#else +long double minus_zero = -0.0L; +#endif + +static long double +my_ldexp (long double x, int d) +{ + for (; d > 0; d--) + x *= 2.0L; + for (; d < 0; d++) + x *= 0.5L; + return x; +} + +int +main () +{ + int i; + long double x; + DECL_LONG_DOUBLE_ROUNDING + + BEGIN_LONG_DOUBLE_ROUNDING (); + + { /* NaN. */ + int exp = -9999; + long double mantissa; + x = NaNl (); + mantissa = frexpl (x, &exp); + ASSERT (isnanl (mantissa)); + } + + { /* Positive infinity. */ + int exp = -9999; + long double mantissa; + x = 1.0L / 0.0L; + mantissa = frexpl (x, &exp); + ASSERT (mantissa == x); + } + + { /* Negative infinity. */ + int exp = -9999; + long double mantissa; + x = -1.0L / 0.0L; + mantissa = frexpl (x, &exp); + ASSERT (mantissa == x); + } + + { /* Positive zero. */ + int exp = -9999; + long double mantissa; + x = 0.0L; + mantissa = frexpl (x, &exp); + ASSERT (exp == 0); + ASSERT (mantissa == x); + ASSERT (!signbit (mantissa)); + } + + { /* Negative zero. */ + int exp = -9999; + long double mantissa; + x = minus_zero; + mantissa = frexpl (x, &exp); + ASSERT (exp == 0); + ASSERT (mantissa == x); + ASSERT (signbit (mantissa)); + } + + for (i = 1, x = 1.0L; i <= LDBL_MAX_EXP; i++, x *= 2.0L) + { + int exp = -9999; + long double mantissa = frexpl (x, &exp); + ASSERT (exp == i); + ASSERT (mantissa == 0.5L); + } + for (i = 1, x = 1.0L; i >= MIN_NORMAL_EXP; i--, x *= 0.5L) + { + int exp = -9999; + long double mantissa = frexpl (x, &exp); + ASSERT (exp == i); + ASSERT (mantissa == 0.5L); + } + for (; i >= LDBL_MIN_EXP - 100 && x > 0.0L; i--, x *= 0.5L) + { + int exp = -9999; + long double mantissa = frexpl (x, &exp); + ASSERT (exp == i); + ASSERT (mantissa == 0.5L); + } + + for (i = 1, x = -1.0L; i <= LDBL_MAX_EXP; i++, x *= 2.0L) + { + int exp = -9999; + long double mantissa = frexpl (x, &exp); + ASSERT (exp == i); + ASSERT (mantissa == -0.5L); + } + for (i = 1, x = -1.0L; i >= MIN_NORMAL_EXP; i--, x *= 0.5L) + { + int exp = -9999; + long double mantissa = frexpl (x, &exp); + ASSERT (exp == i); + ASSERT (mantissa == -0.5L); + } + for (; i >= LDBL_MIN_EXP - 100 && x < 0.0L; i--, x *= 0.5L) + { + int exp = -9999; + long double mantissa = frexpl (x, &exp); + ASSERT (exp == i); + ASSERT (mantissa == -0.5L); + } + + for (i = 1, x = 1.01L; i <= LDBL_MAX_EXP; i++, x *= 2.0L) + { + int exp = -9999; + long double mantissa = frexpl (x, &exp); + ASSERT (exp == i); + ASSERT (mantissa == 0.505L); + } + for (i = 1, x = 1.01L; i >= MIN_NORMAL_EXP; i--, x *= 0.5L) + { + int exp = -9999; + long double mantissa = frexpl (x, &exp); + ASSERT (exp == i); + ASSERT (mantissa == 0.505L); + } + for (; i >= LDBL_MIN_EXP - 100 && x > 0.0L; i--, x *= 0.5L) + { + int exp = -9999; + long double mantissa = frexpl (x, &exp); + ASSERT (exp == i); + ASSERT (mantissa >= 0.5L); + ASSERT (mantissa < 1.0L); + ASSERT (mantissa == my_ldexp (x, - exp)); + } + + for (i = 1, x = 1.73205L; i <= LDBL_MAX_EXP; i++, x *= 2.0L) + { + int exp = -9999; + long double mantissa = frexpl (x, &exp); + ASSERT (exp == i); + ASSERT (mantissa == 0.866025L); + } + for (i = 1, x = 1.73205L; i >= MIN_NORMAL_EXP; i--, x *= 0.5L) + { + int exp = -9999; + long double mantissa = frexpl (x, &exp); + ASSERT (exp == i); + ASSERT (mantissa == 0.866025L); + } + for (; i >= LDBL_MIN_EXP - 100 && x > 0.0L; i--, x *= 0.5L) + { + int exp = -9999; + long double mantissa = frexpl (x, &exp); + ASSERT (exp == i || exp == i + 1); + ASSERT (mantissa >= 0.5L); + ASSERT (mantissa < 1.0L); + ASSERT (mantissa == my_ldexp (x, - exp)); + } + + return 0; +} diff --git a/libmissing/tests/test-getdelim.c b/libmissing/tests/test-getdelim.c index df99664..a5df49f 100644 --- a/libmissing/tests/test-getdelim.c +++ b/libmissing/tests/test-getdelim.c @@ -33,13 +33,13 @@ int main (void) { FILE *f; - char *line = NULL; - size_t len = 0; + char *line; + size_t len; ssize_t result; /* Create test file. */ f = fopen ("test-getdelim.txt", "wb"); - if (!f || fwrite ("anbcnd\0f", 1, 8, f) != 8 || fclose (f) != 0) + if (!f || fwrite ("anAnbcnd\0f", 1, 10, f) != 10 || fclose (f) != 0) { fputs ("Failed to create sample file.\n", stderr); remove ("test-getdelim.txt"); @@ -54,13 +54,24 @@ main (void) } /* Test initial allocation, which must include trailing NUL. */ + line = NULL; + len = 0; result = getdelim (&line, &len, 'n', f); ASSERT (result == 2); ASSERT (strcmp (line, "an") == 0); ASSERT (2 < len); + free (line); - /* Test growth of buffer. */ + /* Test initial allocation again, with line = NULL and len != 0. */ + line = NULL; + len = (size_t)(~0) / 4; + result = getdelim (&line, &len, 'n', f); + ASSERT (result == 2); + ASSERT (strcmp (line, "An") == 0); + ASSERT (2 < len); free (line); + + /* Test growth of buffer. */ line = malloc (1); len = 1; result = getdelim (&line, &len, 'n', f); diff --git a/libmissing/tests/test-getline.c b/libmissing/tests/test-getline.c index 7112b52..6a661ce 100644 --- a/libmissing/tests/test-getline.c +++ b/libmissing/tests/test-getline.c @@ -33,13 +33,13 @@ int main (void) { FILE *f; - char *line = NULL; - size_t len = 0; + char *line; + size_t len; ssize_t result; /* Create test file. */ f = fopen ("test-getline.txt", "wb"); - if (!f || fwrite ("a\nbc\nd\0f", 1, 8, f) != 8 || fclose (f) != 0) + if (!f || fwrite ("a\nA\nbc\nd\0f", 1, 10, f) != 10 || fclose (f) != 0) { fputs ("Failed to create sample file.\n", stderr); remove ("test-getline.txt"); @@ -54,13 +54,24 @@ main (void) } /* Test initial allocation, which must include trailing NUL. */ + line = NULL; + len = 0; result = getline (&line, &len, f); ASSERT (result == 2); ASSERT (strcmp (line, "a\n") == 0); ASSERT (2 < len); + free (line); - /* Test growth of buffer, must not leak. */ + /* Test initial allocation again, with line = NULL and len != 0. */ + line = NULL; + len = (size_t)(~0) / 4; + result = getline (&line, &len, f); + ASSERT (result == 2); + ASSERT (strcmp (line, "A\n") == 0); + ASSERT (2 < len); free (line); + + /* Test growth of buffer, must not leak. */ line = malloc (1); len = 0; result = getline (&line, &len, f); diff --git a/libmissing/tests/test-gettimeofday.c b/libmissing/tests/test-gettimeofday.c index 2a07814..ff2bc72 100644 --- a/libmissing/tests/test-gettimeofday.c +++ b/libmissing/tests/test-gettimeofday.c @@ -20,7 +20,8 @@ #include <sys/time.h> #include "signature.h" -SIGNATURE_CHECK (gettimeofday, int, (struct timeval *, void *)); +SIGNATURE_CHECK (gettimeofday, int, + (struct timeval *, GETTIMEOFDAY_TIMEZONE *)); #include <time.h> @@ -42,8 +43,5 @@ main (void) fprintf (stderr, "gettimeofday still clobbers the localtime buffer!\n"); return 1; } - else - { - return 0; - } + return 0; } diff --git a/libmissing/tests/test-isnand-nolibm.c b/libmissing/tests/test-isnand-nolibm.c new file mode 100644 index 0000000..b0ac0ba --- /dev/null +++ b/libmissing/tests/test-isnand-nolibm.c @@ -0,0 +1,22 @@ +/* Test of isnand() substitute. + Copyright (C) 2007-2010 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> + +#include "isnand-nolibm.h" + +#include "test-isnand.h" + diff --git a/libmissing/tests/test-isnand.h b/libmissing/tests/test-isnand.h new file mode 100644 index 0000000..f986621 --- /dev/null +++ b/libmissing/tests/test-isnand.h @@ -0,0 +1,65 @@ +/* Test of isnand() substitute. + Copyright (C) 2007-2010 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <[email protected]>, 2007. */ + +#include <limits.h> + +#include "nan.h" +#include "macros.h" + +/* HP cc on HP-UX 10.20 has a bug with the constant expression -0.0. + So we use -zero instead. */ +double zero = 0.0; + +int +main () +{ + /* Finite values. */ + ASSERT (!isnand (3.141)); + ASSERT (!isnand (3.141e30)); + ASSERT (!isnand (3.141e-30)); + ASSERT (!isnand (-2.718)); + ASSERT (!isnand (-2.718e30)); + ASSERT (!isnand (-2.718e-30)); + ASSERT (!isnand (0.0)); + ASSERT (!isnand (-zero)); + /* Infinite values. */ + ASSERT (!isnand (1.0 / 0.0)); + ASSERT (!isnand (-1.0 / 0.0)); + /* Quiet NaN. */ + ASSERT (isnand (NaNd ())); +#if defined DBL_EXPBIT0_WORD && defined DBL_EXPBIT0_BIT + /* Signalling NaN. */ + { + #define NWORDS \ + ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) + typedef union { double value; unsigned int word[NWORDS]; } memory_double; + memory_double m; + m.value = NaNd (); +# if DBL_EXPBIT0_BIT > 0 + m.word[DBL_EXPBIT0_WORD] ^= (unsigned int) 1 << (DBL_EXPBIT0_BIT - 1); +# else + m.word[DBL_EXPBIT0_WORD + (DBL_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)] + ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1); +# endif + m.word[DBL_EXPBIT0_WORD + (DBL_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)] + |= (unsigned int) 1 << DBL_EXPBIT0_BIT; + ASSERT (isnand (m.value)); + } +#endif + return 0; +} diff --git a/libmissing/tests/test-isnanf-nolibm.c b/libmissing/tests/test-isnanf-nolibm.c new file mode 100644 index 0000000..6ac69e0 --- /dev/null +++ b/libmissing/tests/test-isnanf-nolibm.c @@ -0,0 +1,21 @@ +/* Test of isnanf() substitute. + Copyright (C) 2007-2010 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> + +#include "isnanf-nolibm.h" + +#include "test-isnanf.h" diff --git a/libmissing/tests/test-isnanf.h b/libmissing/tests/test-isnanf.h new file mode 100644 index 0000000..d071b2c --- /dev/null +++ b/libmissing/tests/test-isnanf.h @@ -0,0 +1,67 @@ +/* Test of isnanf() substitute. + Copyright (C) 2007-2010 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <[email protected]>, 2007. */ + +#include <limits.h> + +#include "nan.h" +#include "macros.h" + +/* HP cc on HP-UX 10.20 has a bug with the constant expression -0.0f. + So we use -zero instead. */ +float zero = 0.0f; + +int +main () +{ + /* Finite values. */ + ASSERT (!isnanf (3.141f)); + ASSERT (!isnanf (3.141e30f)); + ASSERT (!isnanf (3.141e-30f)); + ASSERT (!isnanf (-2.718f)); + ASSERT (!isnanf (-2.718e30f)); + ASSERT (!isnanf (-2.718e-30f)); + ASSERT (!isnanf (0.0f)); + ASSERT (!isnanf (-zero)); + /* Infinite values. */ + ASSERT (!isnanf (1.0f / 0.0f)); + ASSERT (!isnanf (-1.0f / 0.0f)); + /* Quiet NaN. */ + ASSERT (isnanf (NaNf ())); +#if defined FLT_EXPBIT0_WORD && defined FLT_EXPBIT0_BIT + /* Signalling NaN. */ + { + #define NWORDS \ + ((sizeof (float) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) + typedef union { float value; unsigned int word[NWORDS]; } memory_float; + memory_float m; + m.value = NaNf (); +# if FLT_EXPBIT0_BIT > 0 + m.word[FLT_EXPBIT0_WORD] ^= (unsigned int) 1 << (FLT_EXPBIT0_BIT - 1); +# else + m.word[FLT_EXPBIT0_WORD + (FLT_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)] + ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1); +# endif + if (FLT_EXPBIT0_WORD < NWORDS / 2) + m.word[FLT_EXPBIT0_WORD + 1] |= (unsigned int) 1 << FLT_EXPBIT0_BIT; + else + m.word[0] |= (unsigned int) 1; + ASSERT (isnanf (m.value)); + } +#endif + return 0; +} diff --git a/libmissing/tests/test-isnanl-nolibm.c b/libmissing/tests/test-isnanl-nolibm.c new file mode 100644 index 0000000..eeca6d8 --- /dev/null +++ b/libmissing/tests/test-isnanl-nolibm.c @@ -0,0 +1,23 @@ +/* Test of isnanl() substitute. + Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <[email protected]>, 2007. */ + +#include <config.h> + +#include "isnanl-nolibm.h" + +#include "test-isnanl.h" diff --git a/libmissing/tests/test-isnanl.h b/libmissing/tests/test-isnanl.h new file mode 100644 index 0000000..1665cf4 --- /dev/null +++ b/libmissing/tests/test-isnanl.h @@ -0,0 +1,141 @@ +/* Test of isnanl() substitute. + Copyright (C) 2007-2010 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <[email protected]>, 2007. */ + +#include <float.h> +#include <limits.h> + +#include "nan.h" +#include "macros.h" + +/* On HP-UX 10.20, negating 0.0L does not yield -0.0L. + So we use minus_zero instead. + IRIX cc can't put -0.0L into .data, but can compute at runtime. + Note that the expression -LDBL_MIN * LDBL_MIN does not work on other + platforms, such as when cross-compiling to PowerPC on MacOS X 10.5. */ +#if defined __hpux || defined __sgi +static long double +compute_minus_zero (void) +{ + return -LDBL_MIN * LDBL_MIN; +} +# define minus_zero compute_minus_zero () +#else +long double minus_zero = -0.0L; +#endif + +int +main () +{ + #define NWORDS \ + ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) + typedef union { unsigned int word[NWORDS]; long double value; } + memory_long_double; + + /* Finite values. */ + ASSERT (!isnanl (3.141L)); + ASSERT (!isnanl (3.141e30L)); + ASSERT (!isnanl (3.141e-30L)); + ASSERT (!isnanl (-2.718L)); + ASSERT (!isnanl (-2.718e30L)); + ASSERT (!isnanl (-2.718e-30L)); + ASSERT (!isnanl (0.0L)); + ASSERT (!isnanl (minus_zero)); + /* Infinite values. */ + ASSERT (!isnanl (1.0L / 0.0L)); + ASSERT (!isnanl (-1.0L / 0.0L)); + /* Quiet NaN. */ + ASSERT (isnanl (NaNl ())); + +#if defined LDBL_EXPBIT0_WORD && defined LDBL_EXPBIT0_BIT + /* A bit pattern that is different from a Quiet NaN. With a bit of luck, + it's a Signalling NaN. */ + { + memory_long_double m; + m.value = NaNl (); +# if LDBL_EXPBIT0_BIT > 0 + m.word[LDBL_EXPBIT0_WORD] ^= (unsigned int) 1 << (LDBL_EXPBIT0_BIT - 1); +# else + m.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)] + ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1); +# endif + m.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)] + |= (unsigned int) 1 << LDBL_EXPBIT0_BIT; + ASSERT (isnanl (m.value)); + } +#endif + +#if ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_)) +/* Representation of an 80-bit 'long double' as an initializer for a sequence + of 'unsigned int' words. */ +# ifdef WORDS_BIGENDIAN +# define LDBL80_WORDS(exponent,manthi,mantlo) \ + { ((unsigned int) (exponent) << 16) | ((unsigned int) (manthi) >> 16), \ + ((unsigned int) (manthi) << 16) | (unsigned int) (mantlo) >> 16), \ + (unsigned int) (mantlo) << 16 \ + } +# else +# define LDBL80_WORDS(exponent,manthi,mantlo) \ + { mantlo, manthi, exponent } +# endif + { /* Quiet NaN. */ + static memory_long_double x = + { LDBL80_WORDS (0xFFFF, 0xC3333333, 0x00000000) }; + ASSERT (isnanl (x.value)); + } + { + /* Signalling NaN. */ + static memory_long_double x = + { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) }; + ASSERT (isnanl (x.value)); + } + /* The isnanl function should recognize Pseudo-NaNs, Pseudo-Infinities, + Pseudo-Zeroes, Unnormalized Numbers, and Pseudo-Denormals, as defined in + Intel IA-64 Architecture Software Developer's Manual, Volume 1: + Application Architecture. + Table 5-2 "Floating-Point Register Encodings" + Figure 5-6 "Memory to Floating-Point Register Data Translation" + */ + { /* Pseudo-NaN. */ + static memory_long_double x = + { LDBL80_WORDS (0xFFFF, 0x40000001, 0x00000000) }; + ASSERT (isnanl (x.value)); + } + { /* Pseudo-Infinity. */ + static memory_long_double x = + { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) }; + ASSERT (isnanl (x.value)); + } + { /* Pseudo-Zero. */ + static memory_long_double x = + { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) }; + ASSERT (isnanl (x.value)); + } + { /* Unnormalized number. */ + static memory_long_double x = + { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) }; + ASSERT (isnanl (x.value)); + } + { /* Pseudo-Denormal. */ + static memory_long_double x = + { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) }; + ASSERT (isnanl (x.value)); + } +#endif + + return 0; +} diff --git a/libmissing/tests/test-lstat.c b/libmissing/tests/test-lstat.c index 23ffec4..b8f9237 100644 --- a/libmissing/tests/test-lstat.c +++ b/libmissing/tests/test-lstat.c @@ -35,6 +35,7 @@ SIGNATURE_CHECK (lstat, int, (char const *, struct stat *)); #include <unistd.h> #include "same-inode.h" +#include "ignore-value.h" #include "macros.h" #define BASE "test-lstat.t" @@ -53,7 +54,7 @@ int main (void) { /* Remove any leftovers from a previous partial run. */ - system ("rm -rf " BASE "*"); + ignore_value (system ("rm -rf " BASE "*")); return test_lstat_func (do_lstat, true); } diff --git a/libmissing/tests/test-math.c b/libmissing/tests/test-math.c new file mode 100644 index 0000000..f940a24 --- /dev/null +++ b/libmissing/tests/test-math.c @@ -0,0 +1,53 @@ +/* Test of <math.h> substitute. + Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <[email protected]>, 2007. */ + +#include <config.h> + +#include <math.h> + +#ifndef NAN +# error NAN should be defined +choke me +#endif + +#if 0 +/* Check that NAN expands into a constant expression. */ +static float n = NAN; +#endif + +/* Compare two numbers with ==. + This is a separate function because IRIX 6.5 "cc -O" miscompiles an + 'x == x' test. */ +static int +numeric_equal (double x, double y) +{ + return x == y; +} + +int +main (void) +{ + double d = NAN; + double zero = 0.0; + if (numeric_equal (d, d)) + return 1; + d = HUGE_VAL; + if (!numeric_equal (d, 1.0 / zero)) + return 1; + return 0; +} diff --git a/libmissing/tests/test-poll.c b/libmissing/tests/test-poll.c index 1fb4c7b..7488090 100644 --- a/libmissing/tests/test-poll.c +++ b/libmissing/tests/test-poll.c @@ -371,7 +371,7 @@ main () result = test (test_connect_first, "Unconnected socket test"); result += test (test_socket_pair, "Connected sockets test"); result += test (test_accept_first, "General socket test with fork"); - //result += test (test_pipe, "Pipe test"); + result += test (test_pipe, "Pipe test"); exit (result); } diff --git a/libmissing/tests/test-printf-frexp.c b/libmissing/tests/test-printf-frexp.c new file mode 100644 index 0000000..13e1c30 --- /dev/null +++ b/libmissing/tests/test-printf-frexp.c @@ -0,0 +1,119 @@ +/* Test of splitting a double into fraction and mantissa. + Copyright (C) 2007-2010 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <[email protected]>, 2007. */ + +#include <config.h> + +#include "printf-frexp.h" + +#include <float.h> + +#include "macros.h" + +static double +my_ldexp (double x, int d) +{ + for (; d > 0; d--) + x *= 2.0; + for (; d < 0; d++) + x *= 0.5; + return x; +} + +int +main () +{ + int i; + /* The use of 'volatile' guarantees that excess precision bits are dropped + when dealing with denormalized numbers. It is necessary on x86 systems + where double-floats are not IEEE compliant by default, to avoid that the + results become platform and compiler option dependent. 'volatile' is a + portable alternative to gcc's -ffloat-store option. */ + volatile double x; + + for (i = 1, x = 1.0; i <= DBL_MAX_EXP; i++, x *= 2.0) + { + int exp = -9999; + double mantissa = printf_frexp (x, &exp); + ASSERT (exp == i - 1); + ASSERT (mantissa == 1.0); + } + for (i = 1, x = 1.0; i >= DBL_MIN_EXP; i--, x *= 0.5) + { + int exp = -9999; + double mantissa = printf_frexp (x, &exp); + ASSERT (exp == i - 1); + ASSERT (mantissa == 1.0); + } + for (; i >= DBL_MIN_EXP - 100 && x > 0.0; i--, x *= 0.5) + { + int exp = -9999; + double mantissa = printf_frexp (x, &exp); + ASSERT (exp == DBL_MIN_EXP - 1); + ASSERT (mantissa == my_ldexp (1.0, i - DBL_MIN_EXP)); + } + + for (i = 1, x = 1.01; i <= DBL_MAX_EXP; i++, x *= 2.0) + { + int exp = -9999; + double mantissa = printf_frexp (x, &exp); + ASSERT (exp == i - 1); + ASSERT (mantissa == 1.01); + } + for (i = 1, x = 1.01; i >= DBL_MIN_EXP; i--, x *= 0.5) + { + int exp = -9999; + double mantissa = printf_frexp (x, &exp); + ASSERT (exp == i - 1); + ASSERT (mantissa == 1.01); + } + for (; i >= DBL_MIN_EXP - 100 && x > 0.0; i--, x *= 0.5) + { + int exp = -9999; + double mantissa = printf_frexp (x, &exp); + ASSERT (exp == DBL_MIN_EXP - 1); + ASSERT (mantissa >= my_ldexp (1.0, i - DBL_MIN_EXP)); + ASSERT (mantissa <= my_ldexp (2.0, i - DBL_MIN_EXP)); + ASSERT (mantissa == my_ldexp (x, - exp)); + } + + for (i = 1, x = 1.73205; i <= DBL_MAX_EXP; i++, x *= 2.0) + { + int exp = -9999; + double mantissa = printf_frexp (x, &exp); + ASSERT (exp == i - 1); + ASSERT (mantissa == 1.73205); + } + for (i = 1, x = 1.73205; i >= DBL_MIN_EXP; i--, x *= 0.5) + { + int exp = -9999; + double mantissa = printf_frexp (x, &exp); + ASSERT (exp == i - 1); + ASSERT (mantissa == 1.73205); + } + for (; i >= DBL_MIN_EXP - 100 && x > 0.0; i--, x *= 0.5) + { + int exp = -9999; + double mantissa = printf_frexp (x, &exp); + ASSERT (exp == DBL_MIN_EXP - 1); + ASSERT (mantissa >= my_ldexp (1.0, i - DBL_MIN_EXP)); + ASSERT (mantissa <= my_ldexp (2.0, i - DBL_MIN_EXP)); + ASSERT (mantissa == my_ldexp (x, - exp)); + } + + return 0; +} diff --git a/libmissing/tests/test-printf-frexpl.c b/libmissing/tests/test-printf-frexpl.c new file mode 100644 index 0000000..6f7e4f7 --- /dev/null +++ b/libmissing/tests/test-printf-frexpl.c @@ -0,0 +1,134 @@ +/* Test of splitting a 'long double' into fraction and mantissa. + Copyright (C) 2007-2010 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <[email protected]>, 2007. */ + +#include <config.h> + +#include "printf-frexpl.h" + +#include <float.h> + +#include "fpucw.h" +#include "macros.h" + +/* On MIPS IRIX machines, LDBL_MIN_EXP is -1021, but the smallest reliable + exponent for 'long double' is -964. Similarly, on PowerPC machines, + LDBL_MIN_EXP is -1021, but the smallest reliable exponent for 'long double' + is -968. For exponents below that, the precision may be truncated to the + precision used for 'double'. */ +#ifdef __sgi +# define MIN_NORMAL_EXP (LDBL_MIN_EXP + 57) +# define MIN_SUBNORMAL_EXP MIN_NORMAL_EXP +#elif defined __ppc || defined __ppc__ || defined __powerpc || defined __powerpc__ +# define MIN_NORMAL_EXP (LDBL_MIN_EXP + 53) +# define MIN_SUBNORMAL_EXP MIN_NORMAL_EXP +#else +# define MIN_NORMAL_EXP LDBL_MIN_EXP +# define MIN_SUBNORMAL_EXP (LDBL_MIN_EXP - 100) +#endif + +static long double +my_ldexp (long double x, int d) +{ + for (; d > 0; d--) + x *= 2.0L; + for (; d < 0; d++) + x *= 0.5L; + return x; +} + +int +main () +{ + int i; + long double x; + DECL_LONG_DOUBLE_ROUNDING + + BEGIN_LONG_DOUBLE_ROUNDING (); + + for (i = 1, x = 1.0L; i <= LDBL_MAX_EXP; i++, x *= 2.0L) + { + int exp = -9999; + long double mantissa = printf_frexpl (x, &exp); + ASSERT (exp == i - 1); + ASSERT (mantissa == 1.0L); + } + for (i = 1, x = 1.0L; i >= MIN_NORMAL_EXP; i--, x *= 0.5L) + { + int exp = -9999; + long double mantissa = printf_frexpl (x, &exp); + ASSERT (exp == i - 1); + ASSERT (mantissa == 1.0L); + } + for (; i >= MIN_SUBNORMAL_EXP && x > 0.0L; i--, x *= 0.5L) + { + int exp = -9999; + long double mantissa = printf_frexpl (x, &exp); + ASSERT (exp == LDBL_MIN_EXP - 1); + ASSERT (mantissa == my_ldexp (1.0L, i - LDBL_MIN_EXP)); + } + + for (i = 1, x = 1.01L; i <= LDBL_MAX_EXP; i++, x *= 2.0L) + { + int exp = -9999; + long double mantissa = printf_frexpl (x, &exp); + ASSERT (exp == i - 1); + ASSERT (mantissa == 1.01L); + } + for (i = 1, x = 1.01L; i >= MIN_NORMAL_EXP; i--, x *= 0.5L) + { + int exp = -9999; + long double mantissa = printf_frexpl (x, &exp); + ASSERT (exp == i - 1); + ASSERT (mantissa == 1.01L); + } + for (; i >= MIN_SUBNORMAL_EXP && x > 0.0L; i--, x *= 0.5L) + { + int exp = -9999; + long double mantissa = printf_frexpl (x, &exp); + ASSERT (exp == LDBL_MIN_EXP - 1); + ASSERT (mantissa >= my_ldexp (1.0L, i - LDBL_MIN_EXP)); + ASSERT (mantissa <= my_ldexp (2.0L, i - LDBL_MIN_EXP)); + ASSERT (mantissa == my_ldexp (x, - exp)); + } + + for (i = 1, x = 1.73205L; i <= LDBL_MAX_EXP; i++, x *= 2.0L) + { + int exp = -9999; + long double mantissa = printf_frexpl (x, &exp); + ASSERT (exp == i - 1); + ASSERT (mantissa == 1.73205L); + } + for (i = 1, x = 1.73205L; i >= MIN_NORMAL_EXP; i--, x *= 0.5L) + { + int exp = -9999; + long double mantissa = printf_frexpl (x, &exp); + ASSERT (exp == i - 1); + ASSERT (mantissa == 1.73205L); + } + for (; i >= MIN_SUBNORMAL_EXP && x > 0.0L; i--, x *= 0.5L) + { + int exp = -9999; + long double mantissa = printf_frexpl (x, &exp); + ASSERT (exp == LDBL_MIN_EXP - 1); + ASSERT (mantissa >= my_ldexp (1.0L, i - LDBL_MIN_EXP)); + ASSERT (mantissa <= my_ldexp (2.0L, i - LDBL_MIN_EXP)); + ASSERT (mantissa == my_ldexp (x, - exp)); + } + + return 0; +} diff --git a/libmissing/tests/test-signbit.c b/libmissing/tests/test-signbit.c new file mode 100644 index 0000000..9581190 --- /dev/null +++ b/libmissing/tests/test-signbit.c @@ -0,0 +1,197 @@ +/* Test of signbit() substitute. + Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <[email protected]>, 2007. */ + +#include <config.h> + +#include <math.h> + +/* signbit must be a macro. */ +#ifndef signbit +# error missing declaration +#endif + +#include <float.h> +#include <limits.h> + +#include "macros.h" + +float zerof = 0.0f; +double zerod = 0.0; +long double zerol = 0.0L; + +/* HP cc on HP-UX 10.20 has a bug with the constant expression -0.0f. + So we use -zerof instead. */ + +/* HP cc on HP-UX 10.20 has a bug with the constant expression -0.0. + So we use -zerod instead. */ + +/* On HP-UX 10.20, negating 0.0L does not yield -0.0L. + So we use minus_zerol instead. + IRIX cc can't put -0.0L into .data, but can compute at runtime. + Note that the expression -LDBL_MIN * LDBL_MIN does not work on other + platforms, such as when cross-compiling to PowerPC on MacOS X 10.5. */ +#if defined __hpux || defined __sgi +static long double +compute_minus_zerol (void) +{ + return -LDBL_MIN * LDBL_MIN; +} +# define minus_zerol compute_minus_zerol () +#else +long double minus_zerol = -0.0L; +#endif + +static void +test_signbitf () +{ + /* Finite values. */ + ASSERT (!signbit (3.141f)); + ASSERT (!signbit (3.141e30f)); + ASSERT (!signbit (3.141e-30f)); + ASSERT (signbit (-2.718f)); + ASSERT (signbit (-2.718e30f)); + ASSERT (signbit (-2.718e-30f)); + /* Zeros. */ + ASSERT (!signbit (0.0f)); + if (1.0f / -zerof < 0) + ASSERT (signbit (-zerof)); + else + ASSERT (!signbit (-zerof)); + /* Infinite values. */ + ASSERT (!signbit (1.0f / 0.0f)); + ASSERT (signbit (-1.0f / 0.0f)); + /* Quiet NaN. */ + (void) signbit (zerof / zerof); +#if defined FLT_EXPBIT0_WORD && defined FLT_EXPBIT0_BIT + /* Signalling NaN. */ + { + #define NWORDS \ + ((sizeof (float) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) + typedef union { float value; unsigned int word[NWORDS]; } memory_float; + memory_float m; + m.value = zerof / zerof; +# if FLT_EXPBIT0_BIT > 0 + m.word[FLT_EXPBIT0_WORD] ^= (unsigned int) 1 << (FLT_EXPBIT0_BIT - 1); +# else + m.word[FLT_EXPBIT0_WORD + (FLT_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)] + ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1); +# endif + if (FLT_EXPBIT0_WORD < NWORDS / 2) + m.word[FLT_EXPBIT0_WORD + 1] |= (unsigned int) 1 << FLT_EXPBIT0_BIT; + else + m.word[0] |= (unsigned int) 1; + (void) signbit (m.value); + #undef NWORDS + } +#endif +} + +static void +test_signbitd () +{ + /* Finite values. */ + ASSERT (!signbit (3.141)); + ASSERT (!signbit (3.141e30)); + ASSERT (!signbit (3.141e-30)); + ASSERT (signbit (-2.718)); + ASSERT (signbit (-2.718e30)); + ASSERT (signbit (-2.718e-30)); + /* Zeros. */ + ASSERT (!signbit (0.0)); + if (1.0 / -zerod < 0) + ASSERT (signbit (-zerod)); + else + ASSERT (!signbit (-zerod)); + /* Infinite values. */ + ASSERT (!signbit (1.0 / 0.0)); + ASSERT (signbit (-1.0 / 0.0)); + /* Quiet NaN. */ + (void) signbit (zerod / zerod); +#if defined DBL_EXPBIT0_WORD && defined DBL_EXPBIT0_BIT + /* Signalling NaN. */ + { + #define NWORDS \ + ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) + typedef union { double value; unsigned int word[NWORDS]; } memory_double; + memory_double m; + m.value = zerod / zerod; +# if DBL_EXPBIT0_BIT > 0 + m.word[DBL_EXPBIT0_WORD] ^= (unsigned int) 1 << (DBL_EXPBIT0_BIT - 1); +# else + m.word[DBL_EXPBIT0_WORD + (DBL_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)] + ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1); +# endif + m.word[DBL_EXPBIT0_WORD + (DBL_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)] + |= (unsigned int) 1 << DBL_EXPBIT0_BIT; + (void) signbit (m.value); + #undef NWORDS + } +#endif +} + +static void +test_signbitl () +{ + /* Finite values. */ + ASSERT (!signbit (3.141L)); + ASSERT (!signbit (3.141e30L)); + ASSERT (!signbit (3.141e-30L)); + ASSERT (signbit (-2.718L)); + ASSERT (signbit (-2.718e30L)); + ASSERT (signbit (-2.718e-30L)); + /* Zeros. */ + ASSERT (!signbit (0.0L)); + if (1.0L / minus_zerol < 0) + ASSERT (signbit (minus_zerol)); + else + ASSERT (!signbit (minus_zerol)); + /* Infinite values. */ + ASSERT (!signbit (1.0L / 0.0L)); + ASSERT (signbit (-1.0L / 0.0L)); + /* Quiet NaN. */ + (void) signbit (zerol / zerol); +#if defined LDBL_EXPBIT0_WORD && defined LDBL_EXPBIT0_BIT + /* Signalling NaN. */ + { + #define NWORDS \ + ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) + typedef union { long double value; unsigned int word[NWORDS]; } memory_long_double; + memory_long_double m; + m.value = zerol / zerol; +# if LDBL_EXPBIT0_BIT > 0 + m.word[LDBL_EXPBIT0_WORD] ^= (unsigned int) 1 << (LDBL_EXPBIT0_BIT - 1); +# else + m.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)] + ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1); +# endif + m.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)] + |= (unsigned int) 1 << LDBL_EXPBIT0_BIT; + (void) signbit (m.value); + #undef NWORDS + } +#endif +} + +int +main () +{ + test_signbitf (); + test_signbitd (); + test_signbitl (); + return 0; +} diff --git a/libmissing/tests/test-snprintf-posix.c b/libmissing/tests/test-snprintf-posix.c new file mode 100644 index 0000000..452e90c --- /dev/null +++ b/libmissing/tests/test-snprintf-posix.c @@ -0,0 +1,38 @@ +/* Test of POSIX compatible snprintf() function. + Copyright (C) 2007-2010 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <[email protected]>, 2007. */ + +#include <config.h> + +#include <stdio.h> + +#include <float.h> +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include "macros.h" + +#include "test-snprintf-posix.h" + +int +main (int argc, char *argv[]) +{ + test_function (snprintf); + return 0; +} diff --git a/libmissing/tests/test-snprintf-posix.h b/libmissing/tests/test-snprintf-posix.h new file mode 100644 index 0000000..b796d5b --- /dev/null +++ b/libmissing/tests/test-snprintf-posix.h @@ -0,0 +1,3113 @@ +/* Test of POSIX compatible vsnprintf() and snprintf() functions. + Copyright (C) 2007-2010 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <[email protected]>, 2007. */ + +#include "nan.h" + +/* The SGI MIPS floating-point format does not distinguish 0.0 and -0.0. */ +static int +have_minus_zero () +{ + static double plus_zero = 0.0; + double minus_zero = - plus_zero; + return memcmp (&plus_zero, &minus_zero, sizeof (double)) != 0; +} + +/* HP cc on HP-UX 10.20 has a bug with the constant expression -0.0. + So we use -zerod instead. */ +double zerod = 0.0; + +/* On HP-UX 10.20, negating 0.0L does not yield -0.0L. + So we use minus_zerol instead. + IRIX cc can't put -0.0L into .data, but can compute at runtime. + Note that the expression -LDBL_MIN * LDBL_MIN does not work on other + platforms, such as when cross-compiling to PowerPC on MacOS X 10.5. */ +#if defined __hpux || defined __sgi +static long double +compute_minus_zerol (void) +{ + return -LDBL_MIN * LDBL_MIN; +} +# define minus_zerol compute_minus_zerol () +#else +long double minus_zerol = -0.0L; +#endif + +/* Representation of an 80-bit 'long double' as an initializer for a sequence + of 'unsigned int' words. */ +#ifdef WORDS_BIGENDIAN +# define LDBL80_WORDS(exponent,manthi,mantlo) \ + { ((unsigned int) (exponent) << 16) | ((unsigned int) (manthi) >> 16), \ + ((unsigned int) (manthi) << 16) | (unsigned int) (mantlo) >> 16), \ + (unsigned int) (mantlo) << 16 \ + } +#else +# define LDBL80_WORDS(exponent,manthi,mantlo) \ + { mantlo, manthi, exponent } +#endif + +static int +strmatch (const char *pattern, const char *string) +{ + if (strlen (pattern) != strlen (string)) + return 0; + for (; *pattern != '\0'; pattern++, string++) + if (*pattern != '*' && *string != *pattern) + return 0; + return 1; +} + +/* Test whether string[start_index..end_index-1] is a valid textual + representation of NaN. */ +static int +strisnan (const char *string, size_t start_index, size_t end_index, int uppercase) +{ + if (start_index < end_index) + { + if (string[start_index] == '-') + start_index++; + if (start_index + 3 <= end_index + && memcmp (string + start_index, uppercase ? "NAN" : "nan", 3) == 0) + { + start_index += 3; + if (start_index == end_index + || (string[start_index] == '(' && string[end_index - 1] == ')')) + return 1; + } + } + return 0; +} + +static void +test_function (int (*my_snprintf) (char *, size_t, const char *, ...)) +{ + char buf[8]; + int size; + + /* Test return value convention. */ + + for (size = 0; size <= 8; size++) + { + int retval; + + memcpy (buf, "DEADBEEF", 8); + retval = my_snprintf (buf, size, "%d", 12345); + ASSERT (retval == 5); + if (size < 6) + { + if (size > 0) + { + ASSERT (memcmp (buf, "12345", size - 1) == 0); + ASSERT (buf[size - 1] == '\0'); + } + ASSERT (memcmp (buf + size, "DEADBEEF" + size, 8 - size) == 0); + } + else + { + ASSERT (memcmp (buf, "12345\0EF", 8) == 0); + } + } + + /* Test support of size specifiers as in C99. */ + + { + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%ju %d", (uintmax_t) 12345671, 33, 44, 55); + ASSERT (strcmp (result, "12345671 33") == 0); + ASSERT (retval == strlen (result)); + } + + { + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%zu %d", (size_t) 12345672, 33, 44, 55); + ASSERT (strcmp (result, "12345672 33") == 0); + ASSERT (retval == strlen (result)); + } + + { + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%tu %d", (ptrdiff_t) 12345673, 33, 44, 55); + ASSERT (strcmp (result, "12345673 33") == 0); + ASSERT (retval == strlen (result)); + } + + { + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lg %d", (long double) 1.5, 33, 44, 55); + ASSERT (strcmp (result, "1.5 33") == 0); + ASSERT (retval == strlen (result)); + } + + /* Test the support of the 'a' and 'A' conversion specifier for hexadecimal + output of floating-point numbers. */ + + { /* A positive number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%a %d", 3.1416015625, 33, 44, 55); + ASSERT (strcmp (result, "0x1.922p+1 33") == 0 + || strcmp (result, "0x3.244p+0 33") == 0 + || strcmp (result, "0x6.488p-1 33") == 0 + || strcmp (result, "0xc.91p-2 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* A negative number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%A %d", -3.1416015625, 33, 44, 55); + ASSERT (strcmp (result, "-0X1.922P+1 33") == 0 + || strcmp (result, "-0X3.244P+0 33") == 0 + || strcmp (result, "-0X6.488P-1 33") == 0 + || strcmp (result, "-0XC.91P-2 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Positive zero. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%a %d", 0.0, 33, 44, 55); + ASSERT (strcmp (result, "0x0p+0 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Negative zero. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%a %d", -zerod, 33, 44, 55); + if (have_minus_zero ()) + ASSERT (strcmp (result, "-0x0p+0 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Positive infinity. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%a %d", 1.0 / 0.0, 33, 44, 55); + ASSERT (strcmp (result, "inf 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Negative infinity. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%a %d", -1.0 / 0.0, 33, 44, 55); + ASSERT (strcmp (result, "-inf 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* NaN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%a %d", NaNd (), 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Rounding near the decimal point. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.0a %d", 1.5, 33, 44, 55); + ASSERT (strcmp (result, "0x2p+0 33") == 0 + || strcmp (result, "0x3p-1 33") == 0 + || strcmp (result, "0x6p-2 33") == 0 + || strcmp (result, "0xcp-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Rounding with precision 0. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.0a %d", 1.51, 33, 44, 55); + ASSERT (strcmp (result, "0x2p+0 33") == 0 + || strcmp (result, "0x3p-1 33") == 0 + || strcmp (result, "0x6p-2 33") == 0 + || strcmp (result, "0xcp-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Rounding with precision 1. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.1a %d", 1.51, 33, 44, 55); + ASSERT (strcmp (result, "0x1.8p+0 33") == 0 + || strcmp (result, "0x3.0p-1 33") == 0 + || strcmp (result, "0x6.1p-2 33") == 0 + || strcmp (result, "0xc.1p-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Rounding with precision 2. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.2a %d", 1.51, 33, 44, 55); + ASSERT (strcmp (result, "0x1.83p+0 33") == 0 + || strcmp (result, "0x3.05p-1 33") == 0 + || strcmp (result, "0x6.0ap-2 33") == 0 + || strcmp (result, "0xc.14p-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Rounding with precision 3. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.3a %d", 1.51, 33, 44, 55); + ASSERT (strcmp (result, "0x1.829p+0 33") == 0 + || strcmp (result, "0x3.052p-1 33") == 0 + || strcmp (result, "0x6.0a4p-2 33") == 0 + || strcmp (result, "0xc.148p-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Rounding can turn a ...FFF into a ...000. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.3a %d", 1.49999, 33, 44, 55); + ASSERT (strcmp (result, "0x1.800p+0 33") == 0 + || strcmp (result, "0x3.000p-1 33") == 0 + || strcmp (result, "0x6.000p-2 33") == 0 + || strcmp (result, "0xc.000p-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Rounding can turn a ...FFF into a ...000. + This shows a MacOS X 10.3.9 (Darwin 7.9) bug. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.1a %d", 1.999, 33, 44, 55); + ASSERT (strcmp (result, "0x1.0p+1 33") == 0 + || strcmp (result, "0x2.0p+0 33") == 0 + || strcmp (result, "0x4.0p-1 33") == 0 + || strcmp (result, "0x8.0p-2 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Width. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%10a %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, " 0x1.cp+0 33") == 0 + || strcmp (result, " 0x3.8p-1 33") == 0 + || strcmp (result, " 0x7p-2 33") == 0 + || strcmp (result, " 0xep-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Small precision. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.10a %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, "0x1.c000000000p+0 33") == 0 + || strcmp (result, "0x3.8000000000p-1 33") == 0 + || strcmp (result, "0x7.0000000000p-2 33") == 0 + || strcmp (result, "0xe.0000000000p-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Large precision. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.50a %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, "0x1.c0000000000000000000000000000000000000000000000000p+0 33") == 0 + || strcmp (result, "0x3.80000000000000000000000000000000000000000000000000p-1 33") == 0 + || strcmp (result, "0x7.00000000000000000000000000000000000000000000000000p-2 33") == 0 + || strcmp (result, "0xe.00000000000000000000000000000000000000000000000000p-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_LEFT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%-10a %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, "0x1.cp+0 33") == 0 + || strcmp (result, "0x3.8p-1 33") == 0 + || strcmp (result, "0x7p-2 33") == 0 + || strcmp (result, "0xep-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_SHOWSIGN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%+a %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, "+0x1.cp+0 33") == 0 + || strcmp (result, "+0x3.8p-1 33") == 0 + || strcmp (result, "+0x7p-2 33") == 0 + || strcmp (result, "+0xep-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_SPACE. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "% a %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, " 0x1.cp+0 33") == 0 + || strcmp (result, " 0x3.8p-1 33") == 0 + || strcmp (result, " 0x7p-2 33") == 0 + || strcmp (result, " 0xep-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%#a %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, "0x1.cp+0 33") == 0 + || strcmp (result, "0x3.8p-1 33") == 0 + || strcmp (result, "0x7.p-2 33") == 0 + || strcmp (result, "0xe.p-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%#a %d", 1.0, 33, 44, 55); + ASSERT (strcmp (result, "0x1.p+0 33") == 0 + || strcmp (result, "0x2.p-1 33") == 0 + || strcmp (result, "0x4.p-2 33") == 0 + || strcmp (result, "0x8.p-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with finite number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%010a %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, "0x001.cp+0 33") == 0 + || strcmp (result, "0x003.8p-1 33") == 0 + || strcmp (result, "0x00007p-2 33") == 0 + || strcmp (result, "0x0000ep-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with infinite number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%010a %d", 1.0 / 0.0, 33, 44, 55); + /* "0000000inf 33" is not a valid result; see + <http://lists.gnu.org/archive/html/bug-gnulib/2007-04/msg00107.html> */ + ASSERT (strcmp (result, " inf 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with NaN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%050a %d", NaNd (), 33, 44, 55); + /* "0000000nan 33" is not a valid result; see + <http://lists.gnu.org/archive/html/bug-gnulib/2007-04/msg00107.html> */ + ASSERT (strlen (result) == 50 + 3 + && strisnan (result, strspn (result, " "), strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* A positive number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%La %d", 3.1416015625L, 33, 44, 55); + ASSERT (strcmp (result, "0x1.922p+1 33") == 0 + || strcmp (result, "0x3.244p+0 33") == 0 + || strcmp (result, "0x6.488p-1 33") == 0 + || strcmp (result, "0xc.91p-2 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* A negative number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%LA %d", -3.1416015625L, 33, 44, 55); + ASSERT (strcmp (result, "-0X1.922P+1 33") == 0 + || strcmp (result, "-0X3.244P+0 33") == 0 + || strcmp (result, "-0X6.488P-1 33") == 0 + || strcmp (result, "-0XC.91P-2 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Positive zero. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%La %d", 0.0L, 33, 44, 55); + ASSERT (strcmp (result, "0x0p+0 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Negative zero. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%La %d", minus_zerol, 33, 44, 55); + if (have_minus_zero ()) + ASSERT (strcmp (result, "-0x0p+0 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Positive infinity. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%La %d", 1.0L / 0.0L, 33, 44, 55); + ASSERT (strcmp (result, "inf 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Negative infinity. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%La %d", -1.0L / 0.0L, 33, 44, 55); + ASSERT (strcmp (result, "-inf 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* NaN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%La %d", NaNl (), 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } +#if CHECK_PRINTF_SAFE && ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_)) + { /* Quiet NaN. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0xC3333333, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%La %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + { + /* Signalling NaN. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%La %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + /* The isnanl function should recognize Pseudo-NaNs, Pseudo-Infinities, + Pseudo-Zeroes, Unnormalized Numbers, and Pseudo-Denormals, as defined in + Intel IA-64 Architecture Software Developer's Manual, Volume 1: + Application Architecture. + Table 5-2 "Floating-Point Register Encodings" + Figure 5-6 "Memory to Floating-Point Register Data Translation" + */ + { /* Pseudo-NaN. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0x40000001, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%La %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + { /* Pseudo-Infinity. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%La %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + { /* Pseudo-Zero. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%La %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + { /* Unnormalized number. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%La %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + { /* Pseudo-Denormal. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%La %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } +#endif + + { /* Rounding near the decimal point. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.0La %d", 1.5L, 33, 44, 55); + ASSERT (strcmp (result, "0x2p+0 33") == 0 + || strcmp (result, "0x3p-1 33") == 0 + || strcmp (result, "0x6p-2 33") == 0 + || strcmp (result, "0xcp-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Rounding with precision 0. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.0La %d", 1.51L, 33, 44, 55); + ASSERT (strcmp (result, "0x2p+0 33") == 0 + || strcmp (result, "0x3p-1 33") == 0 + || strcmp (result, "0x6p-2 33") == 0 + || strcmp (result, "0xcp-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Rounding with precision 1. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.1La %d", 1.51L, 33, 44, 55); + ASSERT (strcmp (result, "0x1.8p+0 33") == 0 + || strcmp (result, "0x3.0p-1 33") == 0 + || strcmp (result, "0x6.1p-2 33") == 0 + || strcmp (result, "0xc.1p-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Rounding with precision 2. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.2La %d", 1.51L, 33, 44, 55); + ASSERT (strcmp (result, "0x1.83p+0 33") == 0 + || strcmp (result, "0x3.05p-1 33") == 0 + || strcmp (result, "0x6.0ap-2 33") == 0 + || strcmp (result, "0xc.14p-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Rounding with precision 3. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.3La %d", 1.51L, 33, 44, 55); + ASSERT (strcmp (result, "0x1.829p+0 33") == 0 + || strcmp (result, "0x3.052p-1 33") == 0 + || strcmp (result, "0x6.0a4p-2 33") == 0 + || strcmp (result, "0xc.148p-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Rounding can turn a ...FFF into a ...000. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.3La %d", 1.49999L, 33, 44, 55); + ASSERT (strcmp (result, "0x1.800p+0 33") == 0 + || strcmp (result, "0x3.000p-1 33") == 0 + || strcmp (result, "0x6.000p-2 33") == 0 + || strcmp (result, "0xc.000p-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Rounding can turn a ...FFF into a ...000. + This shows a MacOS X 10.3.9 (Darwin 7.9) bug and a + glibc 2.4 bug <http://sourceware.org/bugzilla/show_bug.cgi?id=2908>. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.1La %d", 1.999L, 33, 44, 55); + ASSERT (strcmp (result, "0x1.0p+1 33") == 0 + || strcmp (result, "0x2.0p+0 33") == 0 + || strcmp (result, "0x4.0p-1 33") == 0 + || strcmp (result, "0x8.0p-2 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Width. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%10La %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, " 0x1.cp+0 33") == 0 + || strcmp (result, " 0x3.8p-1 33") == 0 + || strcmp (result, " 0x7p-2 33") == 0 + || strcmp (result, " 0xep-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Small precision. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.10La %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, "0x1.c000000000p+0 33") == 0 + || strcmp (result, "0x3.8000000000p-1 33") == 0 + || strcmp (result, "0x7.0000000000p-2 33") == 0 + || strcmp (result, "0xe.0000000000p-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Large precision. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.50La %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, "0x1.c0000000000000000000000000000000000000000000000000p+0 33") == 0 + || strcmp (result, "0x3.80000000000000000000000000000000000000000000000000p-1 33") == 0 + || strcmp (result, "0x7.00000000000000000000000000000000000000000000000000p-2 33") == 0 + || strcmp (result, "0xe.00000000000000000000000000000000000000000000000000p-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_LEFT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%-10La %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, "0x1.cp+0 33") == 0 + || strcmp (result, "0x3.8p-1 33") == 0 + || strcmp (result, "0x7p-2 33") == 0 + || strcmp (result, "0xep-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_SHOWSIGN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%+La %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, "+0x1.cp+0 33") == 0 + || strcmp (result, "+0x3.8p-1 33") == 0 + || strcmp (result, "+0x7p-2 33") == 0 + || strcmp (result, "+0xep-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_SPACE. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "% La %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, " 0x1.cp+0 33") == 0 + || strcmp (result, " 0x3.8p-1 33") == 0 + || strcmp (result, " 0x7p-2 33") == 0 + || strcmp (result, " 0xep-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%#La %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, "0x1.cp+0 33") == 0 + || strcmp (result, "0x3.8p-1 33") == 0 + || strcmp (result, "0x7.p-2 33") == 0 + || strcmp (result, "0xe.p-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%#La %d", 1.0L, 33, 44, 55); + ASSERT (strcmp (result, "0x1.p+0 33") == 0 + || strcmp (result, "0x2.p-1 33") == 0 + || strcmp (result, "0x4.p-2 33") == 0 + || strcmp (result, "0x8.p-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with finite number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%010La %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, "0x001.cp+0 33") == 0 + || strcmp (result, "0x003.8p-1 33") == 0 + || strcmp (result, "0x00007p-2 33") == 0 + || strcmp (result, "0x0000ep-3 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with infinite number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%010La %d", 1.0L / 0.0L, 33, 44, 55); + /* "0000000inf 33" is not a valid result; see + <http://lists.gnu.org/archive/html/bug-gnulib/2007-04/msg00107.html> */ + ASSERT (strcmp (result, " inf 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with NaN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%050La %d", NaNl (), 33, 44, 55); + /* "0000000nan 33" is not a valid result; see + <http://lists.gnu.org/archive/html/bug-gnulib/2007-04/msg00107.html> */ + ASSERT (strlen (result) == 50 + 3 + && strisnan (result, strspn (result, " "), strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + + /* Test the support of the %f format directive. */ + + { /* A positive number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%f %d", 12.75, 33, 44, 55); + ASSERT (strcmp (result, "12.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* A larger positive number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%f %d", 1234567.0, 33, 44, 55); + ASSERT (strcmp (result, "1234567.000000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Small and large positive numbers. */ + static struct { double value; const char *string; } data[] = + { + { 1.234321234321234e-37, "0.000000" }, + { 1.234321234321234e-36, "0.000000" }, + { 1.234321234321234e-35, "0.000000" }, + { 1.234321234321234e-34, "0.000000" }, + { 1.234321234321234e-33, "0.000000" }, + { 1.234321234321234e-32, "0.000000" }, + { 1.234321234321234e-31, "0.000000" }, + { 1.234321234321234e-30, "0.000000" }, + { 1.234321234321234e-29, "0.000000" }, + { 1.234321234321234e-28, "0.000000" }, + { 1.234321234321234e-27, "0.000000" }, + { 1.234321234321234e-26, "0.000000" }, + { 1.234321234321234e-25, "0.000000" }, + { 1.234321234321234e-24, "0.000000" }, + { 1.234321234321234e-23, "0.000000" }, + { 1.234321234321234e-22, "0.000000" }, + { 1.234321234321234e-21, "0.000000" }, + { 1.234321234321234e-20, "0.000000" }, + { 1.234321234321234e-19, "0.000000" }, + { 1.234321234321234e-18, "0.000000" }, + { 1.234321234321234e-17, "0.000000" }, + { 1.234321234321234e-16, "0.000000" }, + { 1.234321234321234e-15, "0.000000" }, + { 1.234321234321234e-14, "0.000000" }, + { 1.234321234321234e-13, "0.000000" }, + { 1.234321234321234e-12, "0.000000" }, + { 1.234321234321234e-11, "0.000000" }, + { 1.234321234321234e-10, "0.000000" }, + { 1.234321234321234e-9, "0.000000" }, + { 1.234321234321234e-8, "0.000000" }, + { 1.234321234321234e-7, "0.000000" }, + { 1.234321234321234e-6, "0.000001" }, + { 1.234321234321234e-5, "0.000012" }, + { 1.234321234321234e-4, "0.000123" }, + { 1.234321234321234e-3, "0.001234" }, + { 1.234321234321234e-2, "0.012343" }, + { 1.234321234321234e-1, "0.123432" }, + { 1.234321234321234, "1.234321" }, + { 1.234321234321234e1, "12.343212" }, + { 1.234321234321234e2, "123.432123" }, + { 1.234321234321234e3, "1234.321234" }, + { 1.234321234321234e4, "12343.212343" }, + { 1.234321234321234e5, "123432.123432" }, + { 1.234321234321234e6, "1234321.234321" }, + { 1.234321234321234e7, "12343212.343212" }, + { 1.234321234321234e8, "123432123.432123" }, + { 1.234321234321234e9, "1234321234.321234" }, + { 1.234321234321234e10, "12343212343.2123**" }, + { 1.234321234321234e11, "123432123432.123***" }, + { 1.234321234321234e12, "1234321234321.23****" }, + { 1.234321234321234e13, "12343212343212.3*****" }, + { 1.234321234321234e14, "123432123432123.******" }, + { 1.234321234321234e15, "1234321234321234.000000" }, + { 1.234321234321234e16, "123432123432123**.000000" }, + { 1.234321234321234e17, "123432123432123***.000000" }, + { 1.234321234321234e18, "123432123432123****.000000" }, + { 1.234321234321234e19, "123432123432123*****.000000" }, + { 1.234321234321234e20, "123432123432123******.000000" }, + { 1.234321234321234e21, "123432123432123*******.000000" }, + { 1.234321234321234e22, "123432123432123********.000000" }, + { 1.234321234321234e23, "123432123432123*********.000000" }, + { 1.234321234321234e24, "123432123432123**********.000000" }, + { 1.234321234321234e25, "123432123432123***********.000000" }, + { 1.234321234321234e26, "123432123432123************.000000" }, + { 1.234321234321234e27, "123432123432123*************.000000" }, + { 1.234321234321234e28, "123432123432123**************.000000" }, + { 1.234321234321234e29, "123432123432123***************.000000" }, + { 1.234321234321234e30, "123432123432123****************.000000" }, + { 1.234321234321234e31, "123432123432123*****************.000000" }, + { 1.234321234321234e32, "123432123432123******************.000000" }, + { 1.234321234321234e33, "123432123432123*******************.000000" }, + { 1.234321234321234e34, "123432123432123********************.000000" }, + { 1.234321234321234e35, "123432123432123*********************.000000" }, + { 1.234321234321234e36, "123432123432123**********************.000000" } + }; + size_t k; + for (k = 0; k < SIZEOF (data); k++) + { + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%f", data[k].value); + ASSERT (strmatch (data[k].string, result)); + ASSERT (retval == strlen (result)); + } + } + + { /* A negative number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%f %d", -0.03125, 33, 44, 55); + ASSERT (strcmp (result, "-0.031250 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Positive zero. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%f %d", 0.0, 33, 44, 55); + ASSERT (strcmp (result, "0.000000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Negative zero. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%f %d", -zerod, 33, 44, 55); + if (have_minus_zero ()) + ASSERT (strcmp (result, "-0.000000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Positive infinity. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%f %d", 1.0 / 0.0, 33, 44, 55); + ASSERT (strcmp (result, "inf 33") == 0 + || strcmp (result, "infinity 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Negative infinity. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%f %d", -1.0 / 0.0, 33, 44, 55); + ASSERT (strcmp (result, "-inf 33") == 0 + || strcmp (result, "-infinity 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* NaN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%f %d", NaNd (), 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Width. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%10f %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, " 1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_LEFT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%-10f %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, "1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_SHOWSIGN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%+f %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, "+1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_SPACE. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "% f %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, " 1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%#f %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, "1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%#.f %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, "2. 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with finite number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%015f %d", 1234.0, 33, 44, 55); + ASSERT (strcmp (result, "00001234.000000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with infinite number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%015f %d", -1.0 / 0.0, 33, 44, 55); + ASSERT (strcmp (result, " -inf 33") == 0 + || strcmp (result, " -infinity 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with NaN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%050f %d", NaNd (), 33, 44, 55); + ASSERT (strlen (result) == 50 + 3 + && strisnan (result, strspn (result, " "), strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.f %d", 1234.0, 33, 44, 55); + ASSERT (strcmp (result, "1234 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision with no rounding. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.2f %d", 999.951, 33, 44, 55); + ASSERT (strcmp (result, "999.95 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision with rounding. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.2f %d", 999.996, 33, 44, 55); + ASSERT (strcmp (result, "1000.00 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* A positive number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lf %d", 12.75L, 33, 44, 55); + ASSERT (strcmp (result, "12.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* A larger positive number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lf %d", 1234567.0L, 33, 44, 55); + ASSERT (strcmp (result, "1234567.000000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Small and large positive numbers. */ + static struct { long double value; const char *string; } data[] = + { + { 1.234321234321234e-37L, "0.000000" }, + { 1.234321234321234e-36L, "0.000000" }, + { 1.234321234321234e-35L, "0.000000" }, + { 1.234321234321234e-34L, "0.000000" }, + { 1.234321234321234e-33L, "0.000000" }, + { 1.234321234321234e-32L, "0.000000" }, + { 1.234321234321234e-31L, "0.000000" }, + { 1.234321234321234e-30L, "0.000000" }, + { 1.234321234321234e-29L, "0.000000" }, + { 1.234321234321234e-28L, "0.000000" }, + { 1.234321234321234e-27L, "0.000000" }, + { 1.234321234321234e-26L, "0.000000" }, + { 1.234321234321234e-25L, "0.000000" }, + { 1.234321234321234e-24L, "0.000000" }, + { 1.234321234321234e-23L, "0.000000" }, + { 1.234321234321234e-22L, "0.000000" }, + { 1.234321234321234e-21L, "0.000000" }, + { 1.234321234321234e-20L, "0.000000" }, + { 1.234321234321234e-19L, "0.000000" }, + { 1.234321234321234e-18L, "0.000000" }, + { 1.234321234321234e-17L, "0.000000" }, + { 1.234321234321234e-16L, "0.000000" }, + { 1.234321234321234e-15L, "0.000000" }, + { 1.234321234321234e-14L, "0.000000" }, + { 1.234321234321234e-13L, "0.000000" }, + { 1.234321234321234e-12L, "0.000000" }, + { 1.234321234321234e-11L, "0.000000" }, + { 1.234321234321234e-10L, "0.000000" }, + { 1.234321234321234e-9L, "0.000000" }, + { 1.234321234321234e-8L, "0.000000" }, + { 1.234321234321234e-7L, "0.000000" }, + { 1.234321234321234e-6L, "0.000001" }, + { 1.234321234321234e-5L, "0.000012" }, + { 1.234321234321234e-4L, "0.000123" }, + { 1.234321234321234e-3L, "0.001234" }, + { 1.234321234321234e-2L, "0.012343" }, + { 1.234321234321234e-1L, "0.123432" }, + { 1.234321234321234L, "1.234321" }, + { 1.234321234321234e1L, "12.343212" }, + { 1.234321234321234e2L, "123.432123" }, + { 1.234321234321234e3L, "1234.321234" }, + { 1.234321234321234e4L, "12343.212343" }, + { 1.234321234321234e5L, "123432.123432" }, + { 1.234321234321234e6L, "1234321.234321" }, + { 1.234321234321234e7L, "12343212.343212" }, + { 1.234321234321234e8L, "123432123.432123" }, + { 1.234321234321234e9L, "1234321234.321234" }, + { 1.234321234321234e10L, "12343212343.2123**" }, + { 1.234321234321234e11L, "123432123432.123***" }, + { 1.234321234321234e12L, "1234321234321.23****" }, + { 1.234321234321234e13L, "12343212343212.3*****" }, + { 1.234321234321234e14L, "123432123432123.******" }, + { 1.234321234321234e15L, "1234321234321234.000000" }, + { 1.234321234321234e16L, "123432123432123**.000000" }, + { 1.234321234321234e17L, "123432123432123***.000000" }, + { 1.234321234321234e18L, "123432123432123****.000000" }, + { 1.234321234321234e19L, "123432123432123*****.000000" }, + { 1.234321234321234e20L, "123432123432123******.000000" }, + { 1.234321234321234e21L, "123432123432123*******.000000" }, + { 1.234321234321234e22L, "123432123432123********.000000" }, + { 1.234321234321234e23L, "123432123432123*********.000000" }, + { 1.234321234321234e24L, "123432123432123**********.000000" }, + { 1.234321234321234e25L, "123432123432123***********.000000" }, + { 1.234321234321234e26L, "123432123432123************.000000" }, + { 1.234321234321234e27L, "123432123432123*************.000000" }, + { 1.234321234321234e28L, "123432123432123**************.000000" }, + { 1.234321234321234e29L, "123432123432123***************.000000" }, + { 1.234321234321234e30L, "123432123432123****************.000000" }, + { 1.234321234321234e31L, "123432123432123*****************.000000" }, + { 1.234321234321234e32L, "123432123432123******************.000000" }, + { 1.234321234321234e33L, "123432123432123*******************.000000" }, + { 1.234321234321234e34L, "123432123432123********************.000000" }, + { 1.234321234321234e35L, "123432123432123*********************.000000" }, + { 1.234321234321234e36L, "123432123432123**********************.000000" } + }; + size_t k; + for (k = 0; k < SIZEOF (data); k++) + { + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lf", data[k].value); + ASSERT (strmatch (data[k].string, result)); + ASSERT (retval == strlen (result)); + } + } + + { /* A negative number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lf %d", -0.03125L, 33, 44, 55); + ASSERT (strcmp (result, "-0.031250 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Positive zero. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lf %d", 0.0L, 33, 44, 55); + ASSERT (strcmp (result, "0.000000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Negative zero. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lf %d", minus_zerol, 33, 44, 55); + if (have_minus_zero ()) + ASSERT (strcmp (result, "-0.000000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Positive infinity. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lf %d", 1.0L / 0.0L, 33, 44, 55); + ASSERT (strcmp (result, "inf 33") == 0 + || strcmp (result, "infinity 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Negative infinity. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lf %d", -1.0L / 0.0L, 33, 44, 55); + ASSERT (strcmp (result, "-inf 33") == 0 + || strcmp (result, "-infinity 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* NaN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lf %d", NaNl (), 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } +#if CHECK_PRINTF_SAFE && ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_)) + { /* Quiet NaN. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0xC3333333, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lf %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + { + /* Signalling NaN. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lf %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + /* The isnanl function should recognize Pseudo-NaNs, Pseudo-Infinities, + Pseudo-Zeroes, Unnormalized Numbers, and Pseudo-Denormals, as defined in + Intel IA-64 Architecture Software Developer's Manual, Volume 1: + Application Architecture. + Table 5-2 "Floating-Point Register Encodings" + Figure 5-6 "Memory to Floating-Point Register Data Translation" + */ + { /* Pseudo-NaN. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0x40000001, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lf %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + { /* Pseudo-Infinity. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lf %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + { /* Pseudo-Zero. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lf %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + { /* Unnormalized number. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lf %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + { /* Pseudo-Denormal. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lf %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } +#endif + + { /* Width. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%10Lf %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, " 1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_LEFT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%-10Lf %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, "1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_SHOWSIGN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%+Lf %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, "+1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_SPACE. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "% Lf %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, " 1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%#Lf %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, "1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%#.Lf %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, "2. 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with finite number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%015Lf %d", 1234.0L, 33, 44, 55); + ASSERT (strcmp (result, "00001234.000000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with infinite number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%015Lf %d", -1.0L / 0.0L, 33, 44, 55); + ASSERT (strcmp (result, " -inf 33") == 0 + || strcmp (result, " -infinity 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with NaN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%050Lf %d", NaNl (), 33, 44, 55); + ASSERT (strlen (result) == 50 + 3 + && strisnan (result, strspn (result, " "), strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.Lf %d", 1234.0L, 33, 44, 55); + ASSERT (strcmp (result, "1234 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision with no rounding. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.2Lf %d", 999.951L, 33, 44, 55); + ASSERT (strcmp (result, "999.95 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision with rounding. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.2Lf %d", 999.996L, 33, 44, 55); + ASSERT (strcmp (result, "1000.00 33") == 0); + ASSERT (retval == strlen (result)); + } + + /* Test the support of the %F format directive. */ + + { /* A positive number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%F %d", 12.75, 33, 44, 55); + ASSERT (strcmp (result, "12.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* A larger positive number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%F %d", 1234567.0, 33, 44, 55); + ASSERT (strcmp (result, "1234567.000000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* A negative number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%F %d", -0.03125, 33, 44, 55); + ASSERT (strcmp (result, "-0.031250 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Positive zero. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%F %d", 0.0, 33, 44, 55); + ASSERT (strcmp (result, "0.000000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Negative zero. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%F %d", -zerod, 33, 44, 55); + if (have_minus_zero ()) + ASSERT (strcmp (result, "-0.000000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Positive infinity. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%F %d", 1.0 / 0.0, 33, 44, 55); + ASSERT (strcmp (result, "INF 33") == 0 + || strcmp (result, "INFINITY 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Negative infinity. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%F %d", -1.0 / 0.0, 33, 44, 55); + ASSERT (strcmp (result, "-INF 33") == 0 + || strcmp (result, "-INFINITY 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* NaN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%F %d", NaNd (), 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 1) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%015F %d", 1234.0, 33, 44, 55); + ASSERT (strcmp (result, "00001234.000000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with infinite number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%015F %d", -1.0 / 0.0, 33, 44, 55); + ASSERT (strcmp (result, " -INF 33") == 0 + || strcmp (result, " -INFINITY 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.F %d", 1234.0, 33, 44, 55); + ASSERT (strcmp (result, "1234 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision with no rounding. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.2F %d", 999.951, 33, 44, 55); + ASSERT (strcmp (result, "999.95 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision with rounding. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.2F %d", 999.996, 33, 44, 55); + ASSERT (strcmp (result, "1000.00 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* A positive number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%LF %d", 12.75L, 33, 44, 55); + ASSERT (strcmp (result, "12.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* A larger positive number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%LF %d", 1234567.0L, 33, 44, 55); + ASSERT (strcmp (result, "1234567.000000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* A negative number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%LF %d", -0.03125L, 33, 44, 55); + ASSERT (strcmp (result, "-0.031250 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Positive zero. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%LF %d", 0.0L, 33, 44, 55); + ASSERT (strcmp (result, "0.000000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Negative zero. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%LF %d", minus_zerol, 33, 44, 55); + if (have_minus_zero ()) + ASSERT (strcmp (result, "-0.000000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Positive infinity. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%LF %d", 1.0L / 0.0L, 33, 44, 55); + ASSERT (strcmp (result, "INF 33") == 0 + || strcmp (result, "INFINITY 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Negative infinity. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%LF %d", -1.0L / 0.0L, 33, 44, 55); + ASSERT (strcmp (result, "-INF 33") == 0 + || strcmp (result, "-INFINITY 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* NaN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%LF %d", NaNl (), 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 1) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%015LF %d", 1234.0L, 33, 44, 55); + ASSERT (strcmp (result, "00001234.000000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with infinite number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%015LF %d", -1.0L / 0.0L, 33, 44, 55); + ASSERT (strcmp (result, " -INF 33") == 0 + || strcmp (result, " -INFINITY 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.LF %d", 1234.0L, 33, 44, 55); + ASSERT (strcmp (result, "1234 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision with no rounding. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.2LF %d", 999.951L, 33, 44, 55); + ASSERT (strcmp (result, "999.95 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision with rounding. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.2LF %d", 999.996L, 33, 44, 55); + ASSERT (strcmp (result, "1000.00 33") == 0); + ASSERT (retval == strlen (result)); + } + + /* Test the support of the %e format directive. */ + + { /* A positive number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%e %d", 12.75, 33, 44, 55); + ASSERT (strcmp (result, "1.275000e+01 33") == 0 + || strcmp (result, "1.275000e+001 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* A larger positive number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%e %d", 1234567.0, 33, 44, 55); + ASSERT (strcmp (result, "1.234567e+06 33") == 0 + || strcmp (result, "1.234567e+006 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Small and large positive numbers. */ + static struct { double value; const char *string; } data[] = + { + { 1.234321234321234e-37, "1.234321e-37" }, + { 1.234321234321234e-36, "1.234321e-36" }, + { 1.234321234321234e-35, "1.234321e-35" }, + { 1.234321234321234e-34, "1.234321e-34" }, + { 1.234321234321234e-33, "1.234321e-33" }, + { 1.234321234321234e-32, "1.234321e-32" }, + { 1.234321234321234e-31, "1.234321e-31" }, + { 1.234321234321234e-30, "1.234321e-30" }, + { 1.234321234321234e-29, "1.234321e-29" }, + { 1.234321234321234e-28, "1.234321e-28" }, + { 1.234321234321234e-27, "1.234321e-27" }, + { 1.234321234321234e-26, "1.234321e-26" }, + { 1.234321234321234e-25, "1.234321e-25" }, + { 1.234321234321234e-24, "1.234321e-24" }, + { 1.234321234321234e-23, "1.234321e-23" }, + { 1.234321234321234e-22, "1.234321e-22" }, + { 1.234321234321234e-21, "1.234321e-21" }, + { 1.234321234321234e-20, "1.234321e-20" }, + { 1.234321234321234e-19, "1.234321e-19" }, + { 1.234321234321234e-18, "1.234321e-18" }, + { 1.234321234321234e-17, "1.234321e-17" }, + { 1.234321234321234e-16, "1.234321e-16" }, + { 1.234321234321234e-15, "1.234321e-15" }, + { 1.234321234321234e-14, "1.234321e-14" }, + { 1.234321234321234e-13, "1.234321e-13" }, + { 1.234321234321234e-12, "1.234321e-12" }, + { 1.234321234321234e-11, "1.234321e-11" }, + { 1.234321234321234e-10, "1.234321e-10" }, + { 1.234321234321234e-9, "1.234321e-09" }, + { 1.234321234321234e-8, "1.234321e-08" }, + { 1.234321234321234e-7, "1.234321e-07" }, + { 1.234321234321234e-6, "1.234321e-06" }, + { 1.234321234321234e-5, "1.234321e-05" }, + { 1.234321234321234e-4, "1.234321e-04" }, + { 1.234321234321234e-3, "1.234321e-03" }, + { 1.234321234321234e-2, "1.234321e-02" }, + { 1.234321234321234e-1, "1.234321e-01" }, + { 1.234321234321234, "1.234321e+00" }, + { 1.234321234321234e1, "1.234321e+01" }, + { 1.234321234321234e2, "1.234321e+02" }, + { 1.234321234321234e3, "1.234321e+03" }, + { 1.234321234321234e4, "1.234321e+04" }, + { 1.234321234321234e5, "1.234321e+05" }, + { 1.234321234321234e6, "1.234321e+06" }, + { 1.234321234321234e7, "1.234321e+07" }, + { 1.234321234321234e8, "1.234321e+08" }, + { 1.234321234321234e9, "1.234321e+09" }, + { 1.234321234321234e10, "1.234321e+10" }, + { 1.234321234321234e11, "1.234321e+11" }, + { 1.234321234321234e12, "1.234321e+12" }, + { 1.234321234321234e13, "1.234321e+13" }, + { 1.234321234321234e14, "1.234321e+14" }, + { 1.234321234321234e15, "1.234321e+15" }, + { 1.234321234321234e16, "1.234321e+16" }, + { 1.234321234321234e17, "1.234321e+17" }, + { 1.234321234321234e18, "1.234321e+18" }, + { 1.234321234321234e19, "1.234321e+19" }, + { 1.234321234321234e20, "1.234321e+20" }, + { 1.234321234321234e21, "1.234321e+21" }, + { 1.234321234321234e22, "1.234321e+22" }, + { 1.234321234321234e23, "1.234321e+23" }, + { 1.234321234321234e24, "1.234321e+24" }, + { 1.234321234321234e25, "1.234321e+25" }, + { 1.234321234321234e26, "1.234321e+26" }, + { 1.234321234321234e27, "1.234321e+27" }, + { 1.234321234321234e28, "1.234321e+28" }, + { 1.234321234321234e29, "1.234321e+29" }, + { 1.234321234321234e30, "1.234321e+30" }, + { 1.234321234321234e31, "1.234321e+31" }, + { 1.234321234321234e32, "1.234321e+32" }, + { 1.234321234321234e33, "1.234321e+33" }, + { 1.234321234321234e34, "1.234321e+34" }, + { 1.234321234321234e35, "1.234321e+35" }, + { 1.234321234321234e36, "1.234321e+36" } + }; + size_t k; + for (k = 0; k < SIZEOF (data); k++) + { + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%e", data[k].value); + const char *expected = data[k].string; + ASSERT (strcmp (result, expected) == 0 + /* Some implementations produce exponents with 3 digits. */ + || (strlen (result) == strlen (expected) + 1 + && memcmp (result, expected, strlen (expected) - 2) == 0 + && result[strlen (expected) - 2] == '0' + && strcmp (result + strlen (expected) - 1, + expected + strlen (expected) - 2) + == 0)); + ASSERT (retval == strlen (result)); + } + } + + { /* A negative number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%e %d", -0.03125, 33, 44, 55); + ASSERT (strcmp (result, "-3.125000e-02 33") == 0 + || strcmp (result, "-3.125000e-002 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Positive zero. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%e %d", 0.0, 33, 44, 55); + ASSERT (strcmp (result, "0.000000e+00 33") == 0 + || strcmp (result, "0.000000e+000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Negative zero. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%e %d", -zerod, 33, 44, 55); + if (have_minus_zero ()) + ASSERT (strcmp (result, "-0.000000e+00 33") == 0 + || strcmp (result, "-0.000000e+000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Positive infinity. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%e %d", 1.0 / 0.0, 33, 44, 55); + ASSERT (strcmp (result, "inf 33") == 0 + || strcmp (result, "infinity 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Negative infinity. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%e %d", -1.0 / 0.0, 33, 44, 55); + ASSERT (strcmp (result, "-inf 33") == 0 + || strcmp (result, "-infinity 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* NaN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%e %d", NaNd (), 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Width. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%15e %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, " 1.750000e+00 33") == 0 + || strcmp (result, " 1.750000e+000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_LEFT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%-15e %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, "1.750000e+00 33") == 0 + || strcmp (result, "1.750000e+000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_SHOWSIGN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%+e %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, "+1.750000e+00 33") == 0 + || strcmp (result, "+1.750000e+000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_SPACE. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "% e %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, " 1.750000e+00 33") == 0 + || strcmp (result, " 1.750000e+000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%#e %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, "1.750000e+00 33") == 0 + || strcmp (result, "1.750000e+000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%#.e %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, "2.e+00 33") == 0 + || strcmp (result, "2.e+000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%#.e %d", 9.75, 33, 44, 55); + ASSERT (strcmp (result, "1.e+01 33") == 0 + || strcmp (result, "1.e+001 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with finite number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%015e %d", 1234.0, 33, 44, 55); + ASSERT (strcmp (result, "0001.234000e+03 33") == 0 + || strcmp (result, "001.234000e+003 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with infinite number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%015e %d", -1.0 / 0.0, 33, 44, 55); + ASSERT (strcmp (result, " -inf 33") == 0 + || strcmp (result, " -infinity 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with NaN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%050e %d", NaNd (), 33, 44, 55); + ASSERT (strlen (result) == 50 + 3 + && strisnan (result, strspn (result, " "), strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.e %d", 1234.0, 33, 44, 55); + ASSERT (strcmp (result, "1e+03 33") == 0 + || strcmp (result, "1e+003 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision with no rounding. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.4e %d", 999.951, 33, 44, 55); + ASSERT (strcmp (result, "9.9995e+02 33") == 0 + || strcmp (result, "9.9995e+002 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision with rounding. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.4e %d", 999.996, 33, 44, 55); + ASSERT (strcmp (result, "1.0000e+03 33") == 0 + || strcmp (result, "1.0000e+003 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* A positive number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Le %d", 12.75L, 33, 44, 55); + ASSERT (strcmp (result, "1.275000e+01 33") == 0 + || strcmp (result, "1.275000e+001 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* A larger positive number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Le %d", 1234567.0L, 33, 44, 55); + ASSERT (strcmp (result, "1.234567e+06 33") == 0 + || strcmp (result, "1.234567e+006 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Small and large positive numbers. */ + static struct { long double value; const char *string; } data[] = + { + { 1.234321234321234e-37L, "1.234321e-37" }, + { 1.234321234321234e-36L, "1.234321e-36" }, + { 1.234321234321234e-35L, "1.234321e-35" }, + { 1.234321234321234e-34L, "1.234321e-34" }, + { 1.234321234321234e-33L, "1.234321e-33" }, + { 1.234321234321234e-32L, "1.234321e-32" }, + { 1.234321234321234e-31L, "1.234321e-31" }, + { 1.234321234321234e-30L, "1.234321e-30" }, + { 1.234321234321234e-29L, "1.234321e-29" }, + { 1.234321234321234e-28L, "1.234321e-28" }, + { 1.234321234321234e-27L, "1.234321e-27" }, + { 1.234321234321234e-26L, "1.234321e-26" }, + { 1.234321234321234e-25L, "1.234321e-25" }, + { 1.234321234321234e-24L, "1.234321e-24" }, + { 1.234321234321234e-23L, "1.234321e-23" }, + { 1.234321234321234e-22L, "1.234321e-22" }, + { 1.234321234321234e-21L, "1.234321e-21" }, + { 1.234321234321234e-20L, "1.234321e-20" }, + { 1.234321234321234e-19L, "1.234321e-19" }, + { 1.234321234321234e-18L, "1.234321e-18" }, + { 1.234321234321234e-17L, "1.234321e-17" }, + { 1.234321234321234e-16L, "1.234321e-16" }, + { 1.234321234321234e-15L, "1.234321e-15" }, + { 1.234321234321234e-14L, "1.234321e-14" }, + { 1.234321234321234e-13L, "1.234321e-13" }, + { 1.234321234321234e-12L, "1.234321e-12" }, + { 1.234321234321234e-11L, "1.234321e-11" }, + { 1.234321234321234e-10L, "1.234321e-10" }, + { 1.234321234321234e-9L, "1.234321e-09" }, + { 1.234321234321234e-8L, "1.234321e-08" }, + { 1.234321234321234e-7L, "1.234321e-07" }, + { 1.234321234321234e-6L, "1.234321e-06" }, + { 1.234321234321234e-5L, "1.234321e-05" }, + { 1.234321234321234e-4L, "1.234321e-04" }, + { 1.234321234321234e-3L, "1.234321e-03" }, + { 1.234321234321234e-2L, "1.234321e-02" }, + { 1.234321234321234e-1L, "1.234321e-01" }, + { 1.234321234321234L, "1.234321e+00" }, + { 1.234321234321234e1L, "1.234321e+01" }, + { 1.234321234321234e2L, "1.234321e+02" }, + { 1.234321234321234e3L, "1.234321e+03" }, + { 1.234321234321234e4L, "1.234321e+04" }, + { 1.234321234321234e5L, "1.234321e+05" }, + { 1.234321234321234e6L, "1.234321e+06" }, + { 1.234321234321234e7L, "1.234321e+07" }, + { 1.234321234321234e8L, "1.234321e+08" }, + { 1.234321234321234e9L, "1.234321e+09" }, + { 1.234321234321234e10L, "1.234321e+10" }, + { 1.234321234321234e11L, "1.234321e+11" }, + { 1.234321234321234e12L, "1.234321e+12" }, + { 1.234321234321234e13L, "1.234321e+13" }, + { 1.234321234321234e14L, "1.234321e+14" }, + { 1.234321234321234e15L, "1.234321e+15" }, + { 1.234321234321234e16L, "1.234321e+16" }, + { 1.234321234321234e17L, "1.234321e+17" }, + { 1.234321234321234e18L, "1.234321e+18" }, + { 1.234321234321234e19L, "1.234321e+19" }, + { 1.234321234321234e20L, "1.234321e+20" }, + { 1.234321234321234e21L, "1.234321e+21" }, + { 1.234321234321234e22L, "1.234321e+22" }, + { 1.234321234321234e23L, "1.234321e+23" }, + { 1.234321234321234e24L, "1.234321e+24" }, + { 1.234321234321234e25L, "1.234321e+25" }, + { 1.234321234321234e26L, "1.234321e+26" }, + { 1.234321234321234e27L, "1.234321e+27" }, + { 1.234321234321234e28L, "1.234321e+28" }, + { 1.234321234321234e29L, "1.234321e+29" }, + { 1.234321234321234e30L, "1.234321e+30" }, + { 1.234321234321234e31L, "1.234321e+31" }, + { 1.234321234321234e32L, "1.234321e+32" }, + { 1.234321234321234e33L, "1.234321e+33" }, + { 1.234321234321234e34L, "1.234321e+34" }, + { 1.234321234321234e35L, "1.234321e+35" }, + { 1.234321234321234e36L, "1.234321e+36" } + }; + size_t k; + for (k = 0; k < SIZEOF (data); k++) + { + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Le", data[k].value); + const char *expected = data[k].string; + ASSERT (strcmp (result, expected) == 0 + /* Some implementations produce exponents with 3 digits. */ + || (strlen (result) == strlen (expected) + 1 + && memcmp (result, expected, strlen (expected) - 2) == 0 + && result[strlen (expected) - 2] == '0' + && strcmp (result + strlen (expected) - 1, + expected + strlen (expected) - 2) + == 0)); + ASSERT (retval == strlen (result)); + } + } + + { /* A negative number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Le %d", -0.03125L, 33, 44, 55); + ASSERT (strcmp (result, "-3.125000e-02 33") == 0 + || strcmp (result, "-3.125000e-002 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Positive zero. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Le %d", 0.0L, 33, 44, 55); + ASSERT (strcmp (result, "0.000000e+00 33") == 0 + || strcmp (result, "0.000000e+000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Negative zero. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Le %d", minus_zerol, 33, 44, 55); + if (have_minus_zero ()) + ASSERT (strcmp (result, "-0.000000e+00 33") == 0 + || strcmp (result, "-0.000000e+000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Positive infinity. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Le %d", 1.0L / 0.0L, 33, 44, 55); + ASSERT (strcmp (result, "inf 33") == 0 + || strcmp (result, "infinity 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Negative infinity. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Le %d", -1.0L / 0.0L, 33, 44, 55); + ASSERT (strcmp (result, "-inf 33") == 0 + || strcmp (result, "-infinity 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* NaN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Le %d", NaNl (), 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } +#if CHECK_PRINTF_SAFE && ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_)) + { /* Quiet NaN. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0xC3333333, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Le %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + { + /* Signalling NaN. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Le %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + /* The isnanl function should recognize Pseudo-NaNs, Pseudo-Infinities, + Pseudo-Zeroes, Unnormalized Numbers, and Pseudo-Denormals, as defined in + Intel IA-64 Architecture Software Developer's Manual, Volume 1: + Application Architecture. + Table 5-2 "Floating-Point Register Encodings" + Figure 5-6 "Memory to Floating-Point Register Data Translation" + */ + { /* Pseudo-NaN. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0x40000001, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Le %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + { /* Pseudo-Infinity. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Le %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + { /* Pseudo-Zero. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Le %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + { /* Unnormalized number. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Le %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + { /* Pseudo-Denormal. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Le %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } +#endif + + { /* Width. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%15Le %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, " 1.750000e+00 33") == 0 + || strcmp (result, " 1.750000e+000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_LEFT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%-15Le %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, "1.750000e+00 33") == 0 + || strcmp (result, "1.750000e+000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_SHOWSIGN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%+Le %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, "+1.750000e+00 33") == 0 + || strcmp (result, "+1.750000e+000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_SPACE. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "% Le %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, " 1.750000e+00 33") == 0 + || strcmp (result, " 1.750000e+000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%#Le %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, "1.750000e+00 33") == 0 + || strcmp (result, "1.750000e+000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%#.Le %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, "2.e+00 33") == 0 + || strcmp (result, "2.e+000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%#.Le %d", 9.75L, 33, 44, 55); + ASSERT (strcmp (result, "1.e+01 33") == 0 + || strcmp (result, "1.e+001 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with finite number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%015Le %d", 1234.0L, 33, 44, 55); + ASSERT (strcmp (result, "0001.234000e+03 33") == 0 + || strcmp (result, "001.234000e+003 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with infinite number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%015Le %d", -1.0L / 0.0L, 33, 44, 55); + ASSERT (strcmp (result, " -inf 33") == 0 + || strcmp (result, " -infinity 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with NaN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%050Le %d", NaNl (), 33, 44, 55); + ASSERT (strlen (result) == 50 + 3 + && strisnan (result, strspn (result, " "), strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.Le %d", 1234.0L, 33, 44, 55); + ASSERT (strcmp (result, "1e+03 33") == 0 + || strcmp (result, "1e+003 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision with no rounding. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.4Le %d", 999.951L, 33, 44, 55); + ASSERT (strcmp (result, "9.9995e+02 33") == 0 + || strcmp (result, "9.9995e+002 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision with rounding. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.4Le %d", 999.996L, 33, 44, 55); + ASSERT (strcmp (result, "1.0000e+03 33") == 0 + || strcmp (result, "1.0000e+003 33") == 0); + ASSERT (retval == strlen (result)); + } + + /* Test the support of the %g format directive. */ + + { /* A positive number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%g %d", 12.75, 33, 44, 55); + ASSERT (strcmp (result, "12.75 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* A larger positive number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%g %d", 1234567.0, 33, 44, 55); + ASSERT (strcmp (result, "1.23457e+06 33") == 0 + || strcmp (result, "1.23457e+006 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Small and large positive numbers. */ + static struct { double value; const char *string; } data[] = + { + { 1.234321234321234e-37, "1.23432e-37" }, + { 1.234321234321234e-36, "1.23432e-36" }, + { 1.234321234321234e-35, "1.23432e-35" }, + { 1.234321234321234e-34, "1.23432e-34" }, + { 1.234321234321234e-33, "1.23432e-33" }, + { 1.234321234321234e-32, "1.23432e-32" }, + { 1.234321234321234e-31, "1.23432e-31" }, + { 1.234321234321234e-30, "1.23432e-30" }, + { 1.234321234321234e-29, "1.23432e-29" }, + { 1.234321234321234e-28, "1.23432e-28" }, + { 1.234321234321234e-27, "1.23432e-27" }, + { 1.234321234321234e-26, "1.23432e-26" }, + { 1.234321234321234e-25, "1.23432e-25" }, + { 1.234321234321234e-24, "1.23432e-24" }, + { 1.234321234321234e-23, "1.23432e-23" }, + { 1.234321234321234e-22, "1.23432e-22" }, + { 1.234321234321234e-21, "1.23432e-21" }, + { 1.234321234321234e-20, "1.23432e-20" }, + { 1.234321234321234e-19, "1.23432e-19" }, + { 1.234321234321234e-18, "1.23432e-18" }, + { 1.234321234321234e-17, "1.23432e-17" }, + { 1.234321234321234e-16, "1.23432e-16" }, + { 1.234321234321234e-15, "1.23432e-15" }, + { 1.234321234321234e-14, "1.23432e-14" }, + { 1.234321234321234e-13, "1.23432e-13" }, + { 1.234321234321234e-12, "1.23432e-12" }, + { 1.234321234321234e-11, "1.23432e-11" }, + { 1.234321234321234e-10, "1.23432e-10" }, + { 1.234321234321234e-9, "1.23432e-09" }, + { 1.234321234321234e-8, "1.23432e-08" }, + { 1.234321234321234e-7, "1.23432e-07" }, + { 1.234321234321234e-6, "1.23432e-06" }, + { 1.234321234321234e-5, "1.23432e-05" }, + { 1.234321234321234e-4, "0.000123432" }, + { 1.234321234321234e-3, "0.00123432" }, + { 1.234321234321234e-2, "0.0123432" }, + { 1.234321234321234e-1, "0.123432" }, + { 1.234321234321234, "1.23432" }, + { 1.234321234321234e1, "12.3432" }, + { 1.234321234321234e2, "123.432" }, + { 1.234321234321234e3, "1234.32" }, + { 1.234321234321234e4, "12343.2" }, + { 1.234321234321234e5, "123432" }, + { 1.234321234321234e6, "1.23432e+06" }, + { 1.234321234321234e7, "1.23432e+07" }, + { 1.234321234321234e8, "1.23432e+08" }, + { 1.234321234321234e9, "1.23432e+09" }, + { 1.234321234321234e10, "1.23432e+10" }, + { 1.234321234321234e11, "1.23432e+11" }, + { 1.234321234321234e12, "1.23432e+12" }, + { 1.234321234321234e13, "1.23432e+13" }, + { 1.234321234321234e14, "1.23432e+14" }, + { 1.234321234321234e15, "1.23432e+15" }, + { 1.234321234321234e16, "1.23432e+16" }, + { 1.234321234321234e17, "1.23432e+17" }, + { 1.234321234321234e18, "1.23432e+18" }, + { 1.234321234321234e19, "1.23432e+19" }, + { 1.234321234321234e20, "1.23432e+20" }, + { 1.234321234321234e21, "1.23432e+21" }, + { 1.234321234321234e22, "1.23432e+22" }, + { 1.234321234321234e23, "1.23432e+23" }, + { 1.234321234321234e24, "1.23432e+24" }, + { 1.234321234321234e25, "1.23432e+25" }, + { 1.234321234321234e26, "1.23432e+26" }, + { 1.234321234321234e27, "1.23432e+27" }, + { 1.234321234321234e28, "1.23432e+28" }, + { 1.234321234321234e29, "1.23432e+29" }, + { 1.234321234321234e30, "1.23432e+30" }, + { 1.234321234321234e31, "1.23432e+31" }, + { 1.234321234321234e32, "1.23432e+32" }, + { 1.234321234321234e33, "1.23432e+33" }, + { 1.234321234321234e34, "1.23432e+34" }, + { 1.234321234321234e35, "1.23432e+35" }, + { 1.234321234321234e36, "1.23432e+36" } + }; + size_t k; + for (k = 0; k < SIZEOF (data); k++) + { + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%g", data[k].value); + const char *expected = data[k].string; + ASSERT (strcmp (result, expected) == 0 + /* Some implementations produce exponents with 3 digits. */ + || (expected[strlen (expected) - 4] == 'e' + && strlen (result) == strlen (expected) + 1 + && memcmp (result, expected, strlen (expected) - 2) == 0 + && result[strlen (expected) - 2] == '0' + && strcmp (result + strlen (expected) - 1, + expected + strlen (expected) - 2) + == 0)); + ASSERT (retval == strlen (result)); + } + } + + { /* A negative number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%g %d", -0.03125, 33, 44, 55); + ASSERT (strcmp (result, "-0.03125 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Positive zero. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%g %d", 0.0, 33, 44, 55); + ASSERT (strcmp (result, "0 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Negative zero. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%g %d", -zerod, 33, 44, 55); + if (have_minus_zero ()) + ASSERT (strcmp (result, "-0 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Positive infinity. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%g %d", 1.0 / 0.0, 33, 44, 55); + ASSERT (strcmp (result, "inf 33") == 0 + || strcmp (result, "infinity 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Negative infinity. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%g %d", -1.0 / 0.0, 33, 44, 55); + ASSERT (strcmp (result, "-inf 33") == 0 + || strcmp (result, "-infinity 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* NaN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%g %d", NaNd (), 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Width. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%10g %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, " 1.75 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_LEFT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%-10g %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, "1.75 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_SHOWSIGN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%+g %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, "+1.75 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_SPACE. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "% g %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, " 1.75 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%#g %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, "1.75000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%#.g %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, "2. 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%#.g %d", 9.75, 33, 44, 55); + ASSERT (strcmp (result, "1.e+01 33") == 0 + || strcmp (result, "1.e+001 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with finite number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%010g %d", 1234.0, 33, 44, 55); + ASSERT (strcmp (result, "0000001234 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with infinite number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%015g %d", -1.0 / 0.0, 33, 44, 55); + ASSERT (strcmp (result, " -inf 33") == 0 + || strcmp (result, " -infinity 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with NaN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%050g %d", NaNd (), 33, 44, 55); + ASSERT (strlen (result) == 50 + 3 + && strisnan (result, strspn (result, " "), strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.g %d", 1234.0, 33, 44, 55); + ASSERT (strcmp (result, "1e+03 33") == 0 + || strcmp (result, "1e+003 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision with no rounding. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.5g %d", 999.951, 33, 44, 55); + ASSERT (strcmp (result, "999.95 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision with rounding. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.5g %d", 999.996, 33, 44, 55); + ASSERT (strcmp (result, "1000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* A positive number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lg %d", 12.75L, 33, 44, 55); + ASSERT (strcmp (result, "12.75 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* A larger positive number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lg %d", 1234567.0L, 33, 44, 55); + ASSERT (strcmp (result, "1.23457e+06 33") == 0 + || strcmp (result, "1.23457e+006 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Small and large positive numbers. */ + static struct { long double value; const char *string; } data[] = + { + { 1.234321234321234e-37L, "1.23432e-37" }, + { 1.234321234321234e-36L, "1.23432e-36" }, + { 1.234321234321234e-35L, "1.23432e-35" }, + { 1.234321234321234e-34L, "1.23432e-34" }, + { 1.234321234321234e-33L, "1.23432e-33" }, + { 1.234321234321234e-32L, "1.23432e-32" }, + { 1.234321234321234e-31L, "1.23432e-31" }, + { 1.234321234321234e-30L, "1.23432e-30" }, + { 1.234321234321234e-29L, "1.23432e-29" }, + { 1.234321234321234e-28L, "1.23432e-28" }, + { 1.234321234321234e-27L, "1.23432e-27" }, + { 1.234321234321234e-26L, "1.23432e-26" }, + { 1.234321234321234e-25L, "1.23432e-25" }, + { 1.234321234321234e-24L, "1.23432e-24" }, + { 1.234321234321234e-23L, "1.23432e-23" }, + { 1.234321234321234e-22L, "1.23432e-22" }, + { 1.234321234321234e-21L, "1.23432e-21" }, + { 1.234321234321234e-20L, "1.23432e-20" }, + { 1.234321234321234e-19L, "1.23432e-19" }, + { 1.234321234321234e-18L, "1.23432e-18" }, + { 1.234321234321234e-17L, "1.23432e-17" }, + { 1.234321234321234e-16L, "1.23432e-16" }, + { 1.234321234321234e-15L, "1.23432e-15" }, + { 1.234321234321234e-14L, "1.23432e-14" }, + { 1.234321234321234e-13L, "1.23432e-13" }, + { 1.234321234321234e-12L, "1.23432e-12" }, + { 1.234321234321234e-11L, "1.23432e-11" }, + { 1.234321234321234e-10L, "1.23432e-10" }, + { 1.234321234321234e-9L, "1.23432e-09" }, + { 1.234321234321234e-8L, "1.23432e-08" }, + { 1.234321234321234e-7L, "1.23432e-07" }, + { 1.234321234321234e-6L, "1.23432e-06" }, + { 1.234321234321234e-5L, "1.23432e-05" }, + { 1.234321234321234e-4L, "0.000123432" }, + { 1.234321234321234e-3L, "0.00123432" }, + { 1.234321234321234e-2L, "0.0123432" }, + { 1.234321234321234e-1L, "0.123432" }, + { 1.234321234321234L, "1.23432" }, + { 1.234321234321234e1L, "12.3432" }, + { 1.234321234321234e2L, "123.432" }, + { 1.234321234321234e3L, "1234.32" }, + { 1.234321234321234e4L, "12343.2" }, + { 1.234321234321234e5L, "123432" }, + { 1.234321234321234e6L, "1.23432e+06" }, + { 1.234321234321234e7L, "1.23432e+07" }, + { 1.234321234321234e8L, "1.23432e+08" }, + { 1.234321234321234e9L, "1.23432e+09" }, + { 1.234321234321234e10L, "1.23432e+10" }, + { 1.234321234321234e11L, "1.23432e+11" }, + { 1.234321234321234e12L, "1.23432e+12" }, + { 1.234321234321234e13L, "1.23432e+13" }, + { 1.234321234321234e14L, "1.23432e+14" }, + { 1.234321234321234e15L, "1.23432e+15" }, + { 1.234321234321234e16L, "1.23432e+16" }, + { 1.234321234321234e17L, "1.23432e+17" }, + { 1.234321234321234e18L, "1.23432e+18" }, + { 1.234321234321234e19L, "1.23432e+19" }, + { 1.234321234321234e20L, "1.23432e+20" }, + { 1.234321234321234e21L, "1.23432e+21" }, + { 1.234321234321234e22L, "1.23432e+22" }, + { 1.234321234321234e23L, "1.23432e+23" }, + { 1.234321234321234e24L, "1.23432e+24" }, + { 1.234321234321234e25L, "1.23432e+25" }, + { 1.234321234321234e26L, "1.23432e+26" }, + { 1.234321234321234e27L, "1.23432e+27" }, + { 1.234321234321234e28L, "1.23432e+28" }, + { 1.234321234321234e29L, "1.23432e+29" }, + { 1.234321234321234e30L, "1.23432e+30" }, + { 1.234321234321234e31L, "1.23432e+31" }, + { 1.234321234321234e32L, "1.23432e+32" }, + { 1.234321234321234e33L, "1.23432e+33" }, + { 1.234321234321234e34L, "1.23432e+34" }, + { 1.234321234321234e35L, "1.23432e+35" }, + { 1.234321234321234e36L, "1.23432e+36" } + }; + size_t k; + for (k = 0; k < SIZEOF (data); k++) + { + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lg", data[k].value); + const char *expected = data[k].string; + ASSERT (strcmp (result, expected) == 0 + /* Some implementations produce exponents with 3 digits. */ + || (expected[strlen (expected) - 4] == 'e' + && strlen (result) == strlen (expected) + 1 + && memcmp (result, expected, strlen (expected) - 2) == 0 + && result[strlen (expected) - 2] == '0' + && strcmp (result + strlen (expected) - 1, + expected + strlen (expected) - 2) + == 0)); + ASSERT (retval == strlen (result)); + } + } + + { /* A negative number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lg %d", -0.03125L, 33, 44, 55); + ASSERT (strcmp (result, "-0.03125 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Positive zero. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lg %d", 0.0L, 33, 44, 55); + ASSERT (strcmp (result, "0 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Negative zero. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lg %d", minus_zerol, 33, 44, 55); + if (have_minus_zero ()) + ASSERT (strcmp (result, "-0 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Positive infinity. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lg %d", 1.0L / 0.0L, 33, 44, 55); + ASSERT (strcmp (result, "inf 33") == 0 + || strcmp (result, "infinity 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Negative infinity. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lg %d", -1.0L / 0.0L, 33, 44, 55); + ASSERT (strcmp (result, "-inf 33") == 0 + || strcmp (result, "-infinity 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* NaN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lg %d", NaNl (), 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } +#if CHECK_PRINTF_SAFE && ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_)) + { /* Quiet NaN. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0xC3333333, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lg %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + { + /* Signalling NaN. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lg %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + /* The isnanl function should recognize Pseudo-NaNs, Pseudo-Infinities, + Pseudo-Zeroes, Unnormalized Numbers, and Pseudo-Denormals, as defined in + Intel IA-64 Architecture Software Developer's Manual, Volume 1: + Application Architecture. + Table 5-2 "Floating-Point Register Encodings" + Figure 5-6 "Memory to Floating-Point Register Data Translation" + */ + { /* Pseudo-NaN. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0x40000001, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lg %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + { /* Pseudo-Infinity. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lg %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + { /* Pseudo-Zero. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lg %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + { /* Unnormalized number. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lg %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + { /* Pseudo-Denormal. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) }; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%Lg %d", x.value, 33, 44, 55); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } +#endif + + { /* Width. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%10Lg %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, " 1.75 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_LEFT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%-10Lg %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, "1.75 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_SHOWSIGN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%+Lg %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, "+1.75 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_SPACE. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "% Lg %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, " 1.75 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%#Lg %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, "1.75000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%#.Lg %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, "2. 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%#.Lg %d", 9.75L, 33, 44, 55); + ASSERT (strcmp (result, "1.e+01 33") == 0 + || strcmp (result, "1.e+001 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with finite number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%010Lg %d", 1234.0L, 33, 44, 55); + ASSERT (strcmp (result, "0000001234 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with infinite number. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%015Lg %d", -1.0L / 0.0L, 33, 44, 55); + ASSERT (strcmp (result, " -inf 33") == 0 + || strcmp (result, " -infinity 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with NaN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%050Lg %d", NaNl (), 33, 44, 55); + ASSERT (strlen (result) == 50 + 3 + && strisnan (result, strspn (result, " "), strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.Lg %d", 1234.0L, 33, 44, 55); + ASSERT (strcmp (result, "1e+03 33") == 0 + || strcmp (result, "1e+003 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision with no rounding. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.5Lg %d", 999.951L, 33, 44, 55); + ASSERT (strcmp (result, "999.95 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision with rounding. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%.5Lg %d", 999.996L, 33, 44, 55); + ASSERT (strcmp (result, "1000 33") == 0); + ASSERT (retval == strlen (result)); + } + + /* Test the support of the %n format directive. */ + + { + int count = -1; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%d %n", 123, &count, 33, 44, 55); + ASSERT (strcmp (result, "123 ") == 0); + ASSERT (retval == strlen (result)); + ASSERT (count == 4); + } + + /* Test the support of the POSIX/XSI format strings with positions. */ + + { + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%2$d %1$d", 33, 55); + ASSERT (strcmp (result, "55 33") == 0); + ASSERT (retval == strlen (result)); + } + + /* Test the support of the grouping flag. */ + + { + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%'d %d", 1234567, 99); + ASSERT (result[strlen (result) - 1] == '9'); + ASSERT (retval == strlen (result)); + } + + /* Test the support of the left-adjust flag. */ + + { + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "a%*sc", -3, "b"); + ASSERT (strcmp (result, "ab c") == 0); + ASSERT (retval == strlen (result)); + } + + { + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "a%-*sc", 3, "b"); + ASSERT (strcmp (result, "ab c") == 0); + ASSERT (retval == strlen (result)); + } + + { + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "a%-*sc", -3, "b"); + ASSERT (strcmp (result, "ab c") == 0); + ASSERT (retval == strlen (result)); + } + + /* Test the support of large precision. */ + + { + char result[5000]; + int retval = + my_snprintf (result, sizeof (result), "%.4000d %d", 1234567, 99); + size_t i; + for (i = 0; i < 4000 - 7; i++) + ASSERT (result[i] == '0'); + ASSERT (strcmp (result + 4000 - 7, "1234567 99") == 0); + ASSERT (retval == strlen (result)); + } + + { + char result[5000]; + int retval = + my_snprintf (result, sizeof (result), "%.*d %d", 4000, 1234567, 99); + size_t i; + for (i = 0; i < 4000 - 7; i++) + ASSERT (result[i] == '0'); + ASSERT (strcmp (result + 4000 - 7, "1234567 99") == 0); + ASSERT (retval == strlen (result)); + } + + { + char result[5000]; + int retval = + my_snprintf (result, sizeof (result), "%.4000d %d", -1234567, 99); + size_t i; + ASSERT (result[0] == '-'); + for (i = 0; i < 4000 - 7; i++) + ASSERT (result[1 + i] == '0'); + ASSERT (strcmp (result + 1 + 4000 - 7, "1234567 99") == 0); + ASSERT (retval == strlen (result)); + } + + { + char result[5000]; + int retval = + my_snprintf (result, sizeof (result), "%.4000u %d", 1234567, 99); + size_t i; + for (i = 0; i < 4000 - 7; i++) + ASSERT (result[i] == '0'); + ASSERT (strcmp (result + 4000 - 7, "1234567 99") == 0); + ASSERT (retval == strlen (result)); + } + + { + char result[5000]; + int retval = + my_snprintf (result, sizeof (result), "%.4000o %d", 1234567, 99); + size_t i; + for (i = 0; i < 4000 - 7; i++) + ASSERT (result[i] == '0'); + ASSERT (strcmp (result + 4000 - 7, "4553207 99") == 0); + ASSERT (retval == strlen (result)); + } + + { + char result[5000]; + int retval = + my_snprintf (result, sizeof (result), "%.4000x %d", 1234567, 99); + size_t i; + for (i = 0; i < 4000 - 6; i++) + ASSERT (result[i] == '0'); + ASSERT (strcmp (result + 4000 - 6, "12d687 99") == 0); + ASSERT (retval == strlen (result)); + } + + { + char result[5000]; + int retval = + my_snprintf (result, sizeof (result), "%#.4000x %d", 1234567, 99); + size_t i; + ASSERT (result[0] == '0'); + ASSERT (result[1] == 'x'); + for (i = 0; i < 4000 - 6; i++) + ASSERT (result[2 + i] == '0'); + ASSERT (strcmp (result + 2 + 4000 - 6, "12d687 99") == 0); + ASSERT (retval == strlen (result)); + } + + { + char input[5000]; + char result[5000]; + int retval; + size_t i; + + for (i = 0; i < sizeof (input) - 1; i++) + input[i] = 'a' + ((1000000 / (i + 1)) % 26); + input[i] = '\0'; + retval = my_snprintf (result, sizeof (result), "%.4000s %d", input, 99); + ASSERT (memcmp (result, input, 4000) == 0); + ASSERT (strcmp (result + 4000, " 99") == 0); + ASSERT (retval == strlen (result)); + } + + /* Test the support of the %s format directive. */ + + /* To verify that these tests succeed, it is necessary to run them under + a tool that checks against invalid memory accesses, such as ElectricFence + or "valgrind --tool=memcheck". */ + { + size_t i; + + for (i = 1; i <= 8; i++) + { + char *block; + char result[5000]; + int retval; + + block = (char *) malloc (i); + memcpy (block, "abcdefgh", i); + retval = my_snprintf (result, sizeof (result), "%.*s", (int) i, block); + ASSERT (memcmp (result, block, i) == 0); + ASSERT (result[i] == '\0'); + ASSERT (retval == strlen (result)); + free (block); + } + } +#if HAVE_WCHAR_T + { + size_t i; + + for (i = 1; i <= 8; i++) + { + wchar_t *block; + size_t j; + char result[5000]; + int retval; + + block = (wchar_t *) malloc (i * sizeof (wchar_t)); + for (j = 0; j < i; j++) + block[j] = "abcdefgh"[j]; + retval = my_snprintf (result, sizeof (result), "%.*ls", (int) i, block); + ASSERT (memcmp (result, "abcdefgh", i) == 0); + ASSERT (result[i] == '\0'); + ASSERT (retval == strlen (result)); + free (block); + } + } +#endif +} diff --git a/libmissing/tests/test-symlink.c b/libmissing/tests/test-symlink.c index 2369773..d2df54c 100644 --- a/libmissing/tests/test-symlink.c +++ b/libmissing/tests/test-symlink.c @@ -30,6 +30,7 @@ SIGNATURE_CHECK (symlink, int, (char const *, char const *)); #include <stdlib.h> #include <sys/stat.h> +#include "ignore-value.h" #include "macros.h" #define BASE "test-symlink.t" @@ -40,7 +41,7 @@ int main (void) { /* Remove any leftovers from a previous partial run. */ - system ("rm -rf " BASE "*"); + ignore_value (system ("rm -rf " BASE "*")); return test_symlink (symlink, true); } diff --git a/libmissing/tests/test-vsnprintf-posix.c b/libmissing/tests/test-vsnprintf-posix.c new file mode 100644 index 0000000..8de5755 --- /dev/null +++ b/libmissing/tests/test-vsnprintf-posix.c @@ -0,0 +1,51 @@ +/* Test of POSIX compatible vsnprintf() function. + Copyright (C) 2007-2010 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <[email protected]>, 2007. */ + +#include <config.h> + +#include <stdio.h> + +#include <float.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include "macros.h" + +#include "test-snprintf-posix.h" + +static int +my_snprintf (char *str, size_t size, const char *format, ...) +{ + va_list args; + int ret; + + va_start (args, format); + ret = vsnprintf (str, size, format, args); + va_end (args); + return ret; +} + +int +main (int argc, char *argv[]) +{ + test_function (my_snprintf); + return 0; +} --===============1472291964296053651== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Prelude-cvslog site list [email protected] http://lists.prelude-technologies.com/mailman/listinfo/prelude-cvslog --===============1472291964296053651==--