git diff v0.9.14..0311d1dd17ca diff --git a/INSTALL b/INSTALL index ee1fe09..27ed9d7 100644 --- a/INSTALL +++ b/INSTALL @@ -20,7 +20,7 @@ weak aliases, and stand-alone assembly source files. The system used to build musl does not need to be Linux-based, nor do the Linux kernel headers need to be available. -If support for dynamic linking is desired, some further requriements +If support for dynamic linking is desired, some further requirements are placed on the compiler and linker. In particular, the linker must support the -Bsymbolic-functions option. @@ -129,7 +129,7 @@ source/build tree. ==== Option 2: Installing musl as the primary C library ==== In this setup, you will need an existing compiler/toolchain. It -shouldnt matter whether it was configured for glibc, uClibc, musl, or +shouldn't matter whether it was configured for glibc, uClibc, musl, or something else entirely, but sometimes gcc can be uncooperative, especially if the system distributor has built gcc with strange options. It probably makes the most sense to perform the following diff --git a/Makefile b/Makefile index 7ac58d4..0ab0bfd 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,7 @@ SRCS = $(sort $(wildcard src/*/*.c arch/$(ARCH)/src/*.c)) OBJS = $(SRCS:.c=.o) LOBJS = $(OBJS:.o=.lo) GENH = include/bits/alltypes.h +GENH_INT = src/internal/version.h IMPH = src/internal/stdio_impl.h src/internal/pthread_impl.h src/internal/libc.h LDFLAGS = @@ -64,7 +65,7 @@ clean: rm -f $(LOBJS) rm -f $(ALL_LIBS) lib/*.[ao] lib/*.so rm -f $(ALL_TOOLS) - rm -f $(GENH) + rm -f $(GENH) $(GENH_INT) rm -f include/bits distclean: clean @@ -79,6 +80,11 @@ include/bits/alltypes.h.in: include/bits include/bits/alltypes.h: include/bits/alltypes.h.in include/alltypes.h.in tools/mkalltypes.sed sed -f tools/mkalltypes.sed include/bits/alltypes.h.in include/alltypes.h.in > $@ +src/internal/version.h: $(wildcard VERSION .git) + printf '#define VERSION "%s"\n' "$$(sh tools/version.sh)" > $@ + +src/internal/version.lo: src/internal/version.h + src/ldso/dynlink.lo: arch/$(ARCH)/reloc.h crt/crt1.o crt/Scrt1.o: $(wildcard arch/$(ARCH)/crt_arch.h) diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..6d44d22 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.9.14 diff --git a/arch/arm/bits/fcntl.h b/arch/arm/bits/fcntl.h index 98e91d5..eba10ff 100644 --- a/arch/arm/bits/fcntl.h +++ b/arch/arm/bits/fcntl.h @@ -15,6 +15,7 @@ #define O_DIRECT 0200000 #define O_LARGEFILE 0400000 #define O_NOATIME 01000000 +#define O_TMPFILE 020040000 #define O_NDELAY O_NONBLOCK #define F_DUPFD 0 diff --git a/arch/arm/bits/float.h b/arch/arm/bits/float.h index 89e9eb6..ec46b94 100644 --- a/arch/arm/bits/float.h +++ b/arch/arm/bits/float.h @@ -1,10 +1,10 @@ #define FLT_ROUNDS 1 #define FLT_EVAL_METHOD 0 -#define LDBL_TRUE_MIN 4.9406564584124654e-324 -#define LDBL_MIN 2.2250738585072014e-308 -#define LDBL_MAX 1.7976931348623157e+308 -#define LDBL_EPSILON 2.2204460492503131e-16 +#define LDBL_TRUE_MIN 4.94065645841246544177e-324L +#define LDBL_MIN 2.22507385850720138309e-308L +#define LDBL_MAX 1.79769313486231570815e+308L +#define LDBL_EPSILON 2.22044604925031308085e-16L #define LDBL_MANT_DIG 53 #define LDBL_MIN_EXP (-1021) diff --git a/arch/i386/bits/fcntl.h b/arch/i386/bits/fcntl.h index 4cc0312..0fa8e19 100644 --- a/arch/i386/bits/fcntl.h +++ b/arch/i386/bits/fcntl.h @@ -15,6 +15,7 @@ #define O_DIRECT 040000 #define O_LARGEFILE 0100000 #define O_NOATIME 01000000 +#define O_TMPFILE 020200000 #define O_NDELAY O_NONBLOCK #define F_DUPFD 0 diff --git a/arch/i386/bits/syscall.h b/arch/i386/bits/syscall.h index 800409a..2af242b 100644 --- a/arch/i386/bits/syscall.h +++ b/arch/i386/bits/syscall.h @@ -333,6 +333,11 @@ #define __NR_inotify_init1 332 #define __NR_preadv 333 #define __NR_pwritev 334 +#define __NR_rt_tgsigqueueinfo 335 +#define __NR_perf_event_open 336 +#define __NR_recvmmsg 337 +#define __NR_fanotify_init 338 +#define __NR_fanotify_mark 339 #define __NR_prlimit64 340 #define __NR_name_to_handle_at 341 #define __NR_open_by_handle_at 342 @@ -683,6 +688,11 @@ #define SYS_inotify_init1 332 #define SYS_preadv 333 #define SYS_pwritev 334 +#define SYS_rt_tgsigqueueinfo 335 +#define SYS_perf_event_open 336 +#define SYS_recvmmsg 337 +#define SYS_fanotify_init 338 +#define SYS_fanotify_mark 339 #define SYS_prlimit64 340 #define SYS_name_to_handle_at 341 #define SYS_open_by_handle_at 342 diff --git a/arch/microblaze/bits/fcntl.h b/arch/microblaze/bits/fcntl.h index 4cc0312..0fa8e19 100644 --- a/arch/microblaze/bits/fcntl.h +++ b/arch/microblaze/bits/fcntl.h @@ -15,6 +15,7 @@ #define O_DIRECT 040000 #define O_LARGEFILE 0100000 #define O_NOATIME 01000000 +#define O_TMPFILE 020200000 #define O_NDELAY O_NONBLOCK #define F_DUPFD 0 diff --git a/arch/microblaze/bits/float.h b/arch/microblaze/bits/float.h index 89e9eb6..ec46b94 100644 --- a/arch/microblaze/bits/float.h +++ b/arch/microblaze/bits/float.h @@ -1,10 +1,10 @@ #define FLT_ROUNDS 1 #define FLT_EVAL_METHOD 0 -#define LDBL_TRUE_MIN 4.9406564584124654e-324 -#define LDBL_MIN 2.2250738585072014e-308 -#define LDBL_MAX 1.7976931348623157e+308 -#define LDBL_EPSILON 2.2204460492503131e-16 +#define LDBL_TRUE_MIN 4.94065645841246544177e-324L +#define LDBL_MIN 2.22507385850720138309e-308L +#define LDBL_MAX 1.79769313486231570815e+308L +#define LDBL_EPSILON 2.22044604925031308085e-16L #define LDBL_MANT_DIG 53 #define LDBL_MIN_EXP (-1021) diff --git a/arch/mips/bits/fcntl.h b/arch/mips/bits/fcntl.h index c51ee7e..5e33f11 100644 --- a/arch/mips/bits/fcntl.h +++ b/arch/mips/bits/fcntl.h @@ -15,6 +15,7 @@ #define O_DIRECT 0100000 #define O_LARGEFILE 020000 #define O_NOATIME 01000000 +#define O_TMPFILE 020200000 #define O_NDELAY O_NONBLOCK #define F_DUPFD 0 diff --git a/arch/mips/bits/float.h b/arch/mips/bits/float.h index 89e9eb6..ec46b94 100644 --- a/arch/mips/bits/float.h +++ b/arch/mips/bits/float.h @@ -1,10 +1,10 @@ #define FLT_ROUNDS 1 #define FLT_EVAL_METHOD 0 -#define LDBL_TRUE_MIN 4.9406564584124654e-324 -#define LDBL_MIN 2.2250738585072014e-308 -#define LDBL_MAX 1.7976931348623157e+308 -#define LDBL_EPSILON 2.2204460492503131e-16 +#define LDBL_TRUE_MIN 4.94065645841246544177e-324L +#define LDBL_MIN 2.22507385850720138309e-308L +#define LDBL_MAX 1.79769313486231570815e+308L +#define LDBL_EPSILON 2.22044604925031308085e-16L #define LDBL_MANT_DIG 53 #define LDBL_MIN_EXP (-1021) diff --git a/arch/mips/bits/syscall.h b/arch/mips/bits/syscall.h index 2726019..574d603 100644 --- a/arch/mips/bits/syscall.h +++ b/arch/mips/bits/syscall.h @@ -318,30 +318,6 @@ #define __NR_timerfd 4318 #define __NR_eventfd 4319 #define __NR_fallocate 4320 -#define __NR_fallocate 4320 -#define __NR_timerfd_create 4321 -#define __NR_timerfd_gettime 4322 -#define __NR_timerfd_settime 4323 -#define __NR_signalfd4 4324 -#define __NR_eventfd2 4325 -#define __NR_epoll_create1 4326 -#define __NR_dup3 4327 -#define __NR_pipe2 4328 -#define __NR_inotify_init1 4329 -#define __NR_preadv 4330 -#define __NR_pwritev 4331 -#define __NR_rt_tgsigqueueinfo 4332 -#define __NR_perf_event_open 4333 -#define __NR_accept4 4334 -#define __NR_recvmmsg 4335 -#define __NR_fanotify_init 4336 -#define __NR_fanotify_mark 4337 -#define __NR_prlimit64 4338 -#define __NR_name_to_handle_at 4339 -#define __NR_open_by_handle_at 4340 -#define __NR_clock_adjtime 4341 -#define __NR_syncfs 4342 -#define __NR_fallocate 4320 #define __NR_timerfd_create 4321 #define __NR_timerfd_gettime 4322 #define __NR_timerfd_settime 4323 @@ -693,30 +669,6 @@ #define SYS_timerfd 4318 #define SYS_eventfd 4319 #define SYS_fallocate 4320 -#define SYS_fallocate 4320 -#define SYS_timerfd_create 4321 -#define SYS_timerfd_gettime 4322 -#define SYS_timerfd_settime 4323 -#define SYS_signalfd4 4324 -#define SYS_eventfd2 4325 -#define SYS_epoll_create1 4326 -#define SYS_dup3 4327 -#define SYS_pipe2 4328 -#define SYS_inotify_init1 4329 -#define SYS_preadv 4330 -#define SYS_pwritev 4331 -#define SYS_rt_tgsigqueueinfo 4332 -#define SYS_perf_event_open 4333 -#define SYS_accept4 4334 -#define SYS_recvmmsg 4335 -#define SYS_fanotify_init 4336 -#define SYS_fanotify_mark 4337 -#define SYS_prlimit64 4338 -#define SYS_name_to_handle_at 4339 -#define SYS_open_by_handle_at 4340 -#define SYS_clock_adjtime 4341 -#define SYS_syncfs 4342 -#define SYS_fallocate 4320 #define SYS_timerfd_create 4321 #define SYS_timerfd_gettime 4322 #define SYS_timerfd_settime 4323 diff --git a/arch/powerpc/bits/fcntl.h b/arch/powerpc/bits/fcntl.h index b57bd57..548e574 100644 --- a/arch/powerpc/bits/fcntl.h +++ b/arch/powerpc/bits/fcntl.h @@ -15,6 +15,7 @@ #define O_DIRECT 0400000 #define O_LARGEFILE 0200000 #define O_NOATIME 01000000 +#define O_TMPFILE 020040000 #define O_NDELAY O_NONBLOCK #define F_DUPFD 0 diff --git a/arch/powerpc/bits/float.h b/arch/powerpc/bits/float.h index 89e9eb6..ec46b94 100644 --- a/arch/powerpc/bits/float.h +++ b/arch/powerpc/bits/float.h @@ -1,10 +1,10 @@ #define FLT_ROUNDS 1 #define FLT_EVAL_METHOD 0 -#define LDBL_TRUE_MIN 4.9406564584124654e-324 -#define LDBL_MIN 2.2250738585072014e-308 -#define LDBL_MAX 1.7976931348623157e+308 -#define LDBL_EPSILON 2.2204460492503131e-16 +#define LDBL_TRUE_MIN 4.94065645841246544177e-324L +#define LDBL_MIN 2.22507385850720138309e-308L +#define LDBL_MAX 1.79769313486231570815e+308L +#define LDBL_EPSILON 2.22044604925031308085e-16L #define LDBL_MANT_DIG 53 #define LDBL_MIN_EXP (-1021) diff --git a/arch/powerpc/pthread_arch.h b/arch/powerpc/pthread_arch.h index cb2a70b..2d1ee43 100644 --- a/arch/powerpc/pthread_arch.h +++ b/arch/powerpc/pthread_arch.h @@ -1,6 +1,11 @@ static inline struct pthread *__pthread_self() { - register char* tp __asm__("r2"); +#ifdef __clang__ + char *tp; + __asm__ __volatile__ ("mr %0, 2" : "=r"(tp) : : ); +#else + register char *tp __asm__("r2"); +#endif return (pthread_t)(tp - 0x7000 - sizeof(struct pthread)); } diff --git a/arch/x86_64/bits/fcntl.h b/arch/x86_64/bits/fcntl.h index 0949f31..9977713 100644 --- a/arch/x86_64/bits/fcntl.h +++ b/arch/x86_64/bits/fcntl.h @@ -15,6 +15,7 @@ #define O_DIRECT 040000 #define O_LARGEFILE 0 #define O_NOATIME 01000000 +#define O_TMPFILE 020200000 #define O_NDELAY O_NONBLOCK #define F_DUPFD 0 diff --git a/include/arpa/ftp.h b/include/arpa/ftp.h index 4041aeb..fb0a46f 100644 --- a/include/arpa/ftp.h +++ b/include/arpa/ftp.h @@ -1,5 +1,5 @@ -#ifndef _ARPA_FTP_H_ -#define _ARPA_FTP_H_ +#ifndef _ARPA_FTP_H +#define _ARPA_FTP_H #define PRELIM 1 #define COMPLETE 2 #define CONTINUE 3 diff --git a/include/fcntl.h b/include/fcntl.h index b9bc269..55a89f9 100644 --- a/include/fcntl.h +++ b/include/fcntl.h @@ -59,8 +59,6 @@ int posix_fallocate(int, off_t, off_t); #define AT_REMOVEDIR 0x200 #define AT_SYMLINK_FOLLOW 0x400 #define AT_EACCESS 0x200 -#define AT_NO_AUTOMOUNT 0x800 -#define AT_EMPTY_PATH 0x1000 #define POSIX_FADV_NORMAL 0 #define POSIX_FADV_RANDOM 1 @@ -95,6 +93,9 @@ int posix_fallocate(int, off_t, off_t); #endif #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define AT_NO_AUTOMOUNT 0x800 +#define AT_EMPTY_PATH 0x1000 + #define FAPPEND O_APPEND #define FFSYNC O_FSYNC #define FASYNC O_ASYNC diff --git a/include/float.h b/include/float.h index c7b208a..2b2ad39 100644 --- a/include/float.h +++ b/include/float.h @@ -3,10 +3,10 @@ #define FLT_RADIX 2 -#define FLT_TRUE_MIN 1.40129846e-45F -#define FLT_MIN 1.17549435e-38F -#define FLT_MAX 3.40282347e+38F -#define FLT_EPSILON 1.19209290e-07F +#define FLT_TRUE_MIN 1.40129846432481707092e-45F +#define FLT_MIN 1.17549435082228750797e-38F +#define FLT_MAX 3.40282346638528859812e+38F +#define FLT_EPSILON 1.1920928955078125e-07F #define FLT_MANT_DIG 24 #define FLT_MIN_EXP (-125) @@ -16,10 +16,10 @@ #define FLT_MIN_10_EXP (-37) #define FLT_MAX_10_EXP 38 -#define DBL_TRUE_MIN 4.9406564584124654e-324 -#define DBL_MIN 2.2250738585072014e-308 -#define DBL_MAX 1.7976931348623157e+308 -#define DBL_EPSILON 2.2204460492503131e-16 +#define DBL_TRUE_MIN 4.94065645841246544177e-324 +#define DBL_MIN 2.22507385850720138309e-308 +#define DBL_MAX 1.79769313486231570815e+308 +#define DBL_EPSILON 2.22044604925031308085e-16 #define DBL_MANT_DIG 53 #define DBL_MIN_EXP (-1021) diff --git a/include/fnmatch.h b/include/fnmatch.h index 72345b8..f959321 100644 --- a/include/fnmatch.h +++ b/include/fnmatch.h @@ -5,17 +5,12 @@ extern "C" { #endif -#include - #define FNM_PATHNAME 0x1 #define FNM_NOESCAPE 0x2 #define FNM_PERIOD 0x4 - -#ifdef _GNU_SOURCE #define FNM_LEADING_DIR 0x8 #define FNM_CASEFOLD 0x10 #define FNM_FILE_NAME FNM_PATHNAME -#endif #define FNM_NOMATCH 1 #define FNM_NOSYS (-1) diff --git a/include/inttypes.h b/include/inttypes.h index c51769f..61dcb72 100644 --- a/include/inttypes.h +++ b/include/inttypes.h @@ -24,8 +24,10 @@ uintmax_t wcstoumax(const wchar_t *__restrict, wchar_t **__restrict, int); #if UINTPTR_MAX == UINT64_MAX #define __PRI64 "l" +#define __PRIPTR "l" #else #define __PRI64 "ll" +#define __PRIPTR "" #endif #define PRId8 "d" @@ -125,12 +127,12 @@ uintmax_t wcstoumax(const wchar_t *__restrict, wchar_t **__restrict, int); #define PRIxMAX __PRI64 "x" #define PRIXMAX __PRI64 "X" -#define PRIdPTR "ld" -#define PRIiPTR "li" -#define PRIoPTR "lo" -#define PRIuPTR "lu" -#define PRIxPTR "lx" -#define PRIXPTR "lX" +#define PRIdPTR __PRIPTR "d" +#define PRIiPTR __PRIPTR "i" +#define PRIoPTR __PRIPTR "o" +#define PRIuPTR __PRIPTR "u" +#define PRIxPTR __PRIPTR "x" +#define PRIXPTR __PRIPTR "X" #define SCNd8 "hhd" #define SCNd16 "hd" @@ -213,11 +215,11 @@ uintmax_t wcstoumax(const wchar_t *__restrict, wchar_t **__restrict, int); #define SCNuMAX __PRI64 "u" #define SCNxMAX __PRI64 "x" -#define SCNdPTR "ld" -#define SCNiPTR "li" -#define SCNoPTR "lo" -#define SCNuPTR "lu" -#define SCNxPTR "lx" +#define SCNdPTR __PRIPTR "d" +#define SCNiPTR __PRIPTR "i" +#define SCNoPTR __PRIPTR "o" +#define SCNuPTR __PRIPTR "u" +#define SCNxPTR __PRIPTR "x" #ifdef __cplusplus } diff --git a/include/langinfo.h b/include/langinfo.h index c6349ad..2153c42 100644 --- a/include/langinfo.h +++ b/include/langinfo.h @@ -5,6 +5,7 @@ extern "C" { #endif +#include #include #define __NEED_locale_t @@ -75,8 +76,11 @@ extern "C" { #define THOUSEP 0x10001 #define YESEXPR 0x50000 #define NOEXPR 0x50001 + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) #define YESSTR 0x50002 #define NOSTR 0x50003 +#endif char *nl_langinfo(nl_item); char *nl_langinfo_l(nl_item, locale_t); diff --git a/include/limits.h b/include/limits.h index a8460cc..f9805a1 100644 --- a/include/limits.h +++ b/include/limits.h @@ -55,7 +55,7 @@ #define WORD_BIT 32 #define SSIZE_MAX LONG_MAX #define TZNAME_MAX 6 -#define TTY_NAME_MAX 20 +#define TTY_NAME_MAX 32 #define HOST_NAME_MAX 255 /* Implementation choices... */ @@ -84,12 +84,18 @@ #define NL_ARGMAX 9 #define NL_LANGMAX 32 #define NL_MSGMAX 32767 -#define NL_NMAX (MB_LEN_MAX*4) #define NL_SETMAX 255 #define NL_TEXTMAX 2048 #endif +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) \ + || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE+0 < 700) + +#define NL_NMAX 16 + +#endif + /* POSIX/SUS requirements follow. These numbers come directly * from SUS and have nothing to do with the host system. */ diff --git a/include/locale.h b/include/locale.h index 7e80fd9..ce38438 100644 --- a/include/locale.h +++ b/include/locale.h @@ -7,7 +7,11 @@ extern "C" { #include +#ifdef __cplusplus #define NULL 0L +#else +#define NULL ((void*)0) +#endif #define LC_CTYPE 0 #define LC_NUMERIC 1 diff --git a/include/math.h b/include/math.h index c029156..bbee62e 100644 --- a/include/math.h +++ b/include/math.h @@ -16,7 +16,7 @@ extern "C" { #define INFINITY __builtin_inff() #else #define NAN (0.0f/0.0f) -#define INFINITY 1e40f +#define INFINITY 1e5000f #endif #define HUGE_VALF INFINITY @@ -91,20 +91,20 @@ int __signbitl(long double); static __inline int __is##rel(type __x, type __y) \ { return !isunordered(__x,__y) && __x op __y; } -__ISREL_DEF(lessf, <, float) -__ISREL_DEF(less, <, double) +__ISREL_DEF(lessf, <, float_t) +__ISREL_DEF(less, <, double_t) __ISREL_DEF(lessl, <, long double) -__ISREL_DEF(lessequalf, <=, float) -__ISREL_DEF(lessequal, <=, double) +__ISREL_DEF(lessequalf, <=, float_t) +__ISREL_DEF(lessequal, <=, double_t) __ISREL_DEF(lessequall, <=, long double) -__ISREL_DEF(lessgreaterf, !=, float) -__ISREL_DEF(lessgreater, !=, double) +__ISREL_DEF(lessgreaterf, !=, float_t) +__ISREL_DEF(lessgreater, !=, double_t) __ISREL_DEF(lessgreaterl, !=, long double) -__ISREL_DEF(greaterf, >, float) -__ISREL_DEF(greater, >, double) +__ISREL_DEF(greaterf, >, float_t) +__ISREL_DEF(greater, >, double_t) __ISREL_DEF(greaterl, >, long double) -__ISREL_DEF(greaterequalf, >=, float) -__ISREL_DEF(greaterequal, >=, double) +__ISREL_DEF(greaterequalf, >=, float_t) +__ISREL_DEF(greaterequal, >=, double_t) __ISREL_DEF(greaterequall, >=, long double) #define __tg_pred_2(x, y, p) ( \ @@ -349,7 +349,7 @@ long double truncl(long double); #if defined(_XOPEN_SOURCE) || defined(_BSD_SOURCE) #undef MAXFLOAT -#define MAXFLOAT 3.40282347e+38F +#define MAXFLOAT 3.40282346638528859812e+38F #endif #if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) @@ -379,7 +379,13 @@ double yn(int, double); #endif #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -#define HUGE 3.40282347e+38F +#define HUGE 3.40282346638528859812e+38F + +double drem(double, double); +float dremf(float, float); + +int finite(double); +int finitef(float); double scalb(double, double); float scalbf(float, float); diff --git a/include/netinet/in.h b/include/netinet/in.h index 881f670..8be51e8 100644 --- a/include/netinet/in.h +++ b/include/netinet/in.h @@ -206,7 +206,7 @@ uint16_t ntohs(uint16_t); #define IP_MULTICAST_ALL 49 #define IP_UNICAST_IF 50 -#ifdef _GNU_SOURCE +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) #define MCAST_JOIN_GROUP 42 #define MCAST_BLOCK_SOURCE 43 #define MCAST_UNBLOCK_SOURCE 44 @@ -251,6 +251,47 @@ struct ip_mreqn int imr_ifindex; }; +struct ip_mreq_source { + struct in_addr imr_multiaddr; + struct in_addr imr_interface; + struct in_addr imr_sourceaddr; +}; + +struct ip_msfilter { + struct in_addr imsf_multiaddr; + struct in_addr imsf_interface; + uint32_t imsf_fmode; + uint32_t imsf_numsrc; + struct in_addr imsf_slist[1]; +}; +#define IP_MSFILTER_SIZE(numsrc) \ + (sizeof(struct ip_msfilter) - sizeof(struct in_addr) \ + + (numsrc) * sizeof(struct in_addr)) + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +struct group_req { + uint32_t gr_interface; + struct sockaddr_storage gr_group; +}; + +struct group_source_req { + uint32_t gsr_interface; + struct sockaddr_storage gsr_group; + struct sockaddr_storage gsr_source; +}; + +struct group_filter { + uint32_t gf_interface; + struct sockaddr_storage gf_group; + uint32_t gf_fmode; + uint32_t gf_numsrc; + struct sockaddr_storage gf_slist[1]; +}; +#define GROUP_FILTER_SIZE(numsrc) \ + (sizeof(struct group_filter) - sizeof(struct sockaddr_storage) \ + + (numsrc) * sizeof(struct sockaddr_storage)) +#endif + struct in_pktinfo { int ipi_ifindex; diff --git a/include/netinet/tcp.h b/include/netinet/tcp.h index 8266f21..5212ef7 100644 --- a/include/netinet/tcp.h +++ b/include/netinet/tcp.h @@ -26,6 +26,19 @@ #define TCP_REPAIR_OPTIONS 22 #define TCP_FASTOPEN 23 #define TCP_TIMESTAMP 24 +#define TCP_NOTSENT_LOWAT 25 + +#define TCP_ESTABLISHED 1 +#define TCP_SYN_SENT 2 +#define TCP_SYN_RECV 3 +#define TCP_FIN_WAIT1 4 +#define TCP_FIN_WAIT2 5 +#define TCP_TIME_WAIT 6 +#define TCP_CLOSE 7 +#define TCP_CLOSE_WAIT 8 +#define TCP_LAST_ACK 9 +#define TCP_LISTEN 10 +#define TCP_CLOSING 11 #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) #define SOL_TCP 6 diff --git a/include/paths.h b/include/paths.h index 2284870..67de6b3 100644 --- a/include/paths.h +++ b/include/paths.h @@ -21,7 +21,6 @@ #define _PATH_UTMP "/dev/null/utmp" #define _PATH_VI "/usr/bin/vi" #define _PATH_WTMP "/dev/null/wtmp" -#define _PATH_LASTLOG "/var/log/lastlog" #define _PATH_DEV "/dev/" #define _PATH_TMP "/tmp/" diff --git a/include/resolv.h b/include/resolv.h index 259e4bc..e12cb3c 100644 --- a/include/resolv.h +++ b/include/resolv.h @@ -125,15 +125,13 @@ struct res_sym { struct __res_state *__res_state(void); #define _res (*__res_state()) -struct rrec; - int res_init(void); int res_query(const char *, int, int, unsigned char *, int); int res_querydomain(const char *, const char *, int, int, unsigned char *, int); int res_search(const char *, int, int, unsigned char *, int); -int res_mkquery(int, const char *, int, int, char *, int, struct rrec *, char *, int); -int res_send(const char *, int, char *, int); -int dn_comp(unsigned char *, unsigned char *, int, unsigned char **, unsigned char *, unsigned char **); +int res_mkquery(int, const char *, int, int, const unsigned char *, int, const unsigned char*, unsigned char *, int); +int res_send(const unsigned char *, int, unsigned char *, int); +int dn_comp(const char *, unsigned char *, int, unsigned char **, unsigned char **); int dn_expand(const unsigned char *, const unsigned char *, const unsigned char *, char *, int); int dn_skipname(const unsigned char *, const unsigned char *); diff --git a/include/search.h b/include/search.h index ebfe08a..27f6107 100644 --- a/include/search.h +++ b/include/search.h @@ -13,7 +13,7 @@ extern "C" { typedef enum { FIND, ENTER } ACTION; typedef enum { preorder, postorder, endorder, leaf } VISIT; -typedef struct { +typedef struct entry { char *key; void *data; } ENTRY; diff --git a/include/signal.h b/include/signal.h index e65a806..6f10a118 100644 --- a/include/signal.h +++ b/include/signal.h @@ -218,11 +218,8 @@ void (*sigset(int, void (*)(int)))(int); #define SIGSTKSZ 8192 #endif -#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) -#define NSIG _NSIG -#endif - #if defined(_BSD_SOURCE) || defined(_GNU_SOURCE) +#define NSIG _NSIG typedef void (*sig_t)(int); #endif diff --git a/include/stddef.h b/include/stddef.h index 9d52248..0a32919 100644 --- a/include/stddef.h +++ b/include/stddef.h @@ -1,7 +1,11 @@ #ifndef _STDDEF_H #define _STDDEF_H +#ifdef __cplusplus #define NULL 0L +#else +#define NULL ((void*)0) +#endif #define __NEED_ptrdiff_t #define __NEED_size_t diff --git a/include/stdio.h b/include/stdio.h index cd60bb5..884d2e6 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -21,7 +21,11 @@ extern "C" { #include +#ifdef __cplusplus #define NULL 0L +#else +#define NULL ((void*)0) +#endif #undef EOF #define EOF (-1) diff --git a/include/stdlib.h b/include/stdlib.h index bca1fb4..1e67b89 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -7,7 +7,11 @@ extern "C" { #include +#ifdef __cplusplus #define NULL 0L +#else +#define NULL ((void*)0) +#endif #define __NEED_size_t #define __NEED_wchar_t @@ -139,6 +143,7 @@ int mkstemps (char *, int); int mkostemps (char *, int, int); void *valloc (size_t); void *memalign(size_t, size_t); +int getloadavg(double *, int); #define WCOREDUMP(s) ((s) & 0x80) #define WIFCONTINUED(s) ((s) == 0xffff) #endif diff --git a/include/string.h b/include/string.h index d441233..ff9badb 100644 --- a/include/string.h +++ b/include/string.h @@ -7,7 +7,11 @@ extern "C" { #include +#ifdef __cplusplus #define NULL 0L +#else +#define NULL ((void*)0) +#endif #define __NEED_size_t #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ diff --git a/include/sys/mtio.h b/include/sys/mtio.h index dc8e5f5..f16a529 100644 --- a/include/sys/mtio.h +++ b/include/sys/mtio.h @@ -102,7 +102,7 @@ struct mt_tape_info { {MT_ISEVEREX_FT40A, "Everex FT40A, QIC-40"}, \ {MT_ISSCSI1, "Generic SCSI-1 tape"}, \ {MT_ISSCSI2, "Generic SCSI-2 tape"}, \ - {0, NULL} \ + {0, 0} \ } struct mtpos { diff --git a/include/sys/socket.h b/include/sys/socket.h index 9fd2025..82edd6f 100644 --- a/include/sys/socket.h +++ b/include/sys/socket.h @@ -19,12 +19,14 @@ extern "C" { #include +#ifdef _GNU_SOURCE struct ucred { pid_t pid; uid_t uid; gid_t gid; }; +#endif struct linger { @@ -33,7 +35,7 @@ struct linger }; #define SHUT_RD 0 -#define SHUT_WD 1 +#define SHUT_WR 1 #define SHUT_RDWR 2 #ifndef SOCK_STREAM @@ -225,7 +227,7 @@ struct linger #define MSG_EOR 0x0080 #define MSG_WAITALL 0x0100 #define MSG_FIN 0x0200 -#define MSD_SYN 0x0400 +#define MSG_SYN 0x0400 #define MSG_CONFIRM 0x0800 #define MSG_RST 0x1000 #define MSG_ERRQUEUE 0x2000 @@ -290,10 +292,6 @@ int setsockopt (int, int, int, const void *, socklen_t); int sockatmark (int); -#define SHUT_RD 0 -#define SHUT_WR 1 -#define SHUT_RDWR 2 - #ifdef __cplusplus } #endif diff --git a/include/sys/time.h b/include/sys/time.h index 3ce824e..b6787c3 100644 --- a/include/sys/time.h +++ b/include/sys/time.h @@ -43,10 +43,10 @@ int adjtime (const struct timeval *, struct timeval *); #define timerclear(t) ((t)->tv_sec = (t)->tv_usec = 0) #define timercmp(s,t,op) ((s)->tv_sec == (t)->tv_sec ? \ (s)->tv_usec op (t)->tv_usec : (s)->tv_sec op (t)->tv_sec) -#define timeradd(s,t,a) ( (a)->tv_sec = (s)->tv_sec + (t)->tv_sec, \ +#define timeradd(s,t,a) (void) ( (a)->tv_sec = (s)->tv_sec + (t)->tv_sec, \ ((a)->tv_usec = (s)->tv_usec + (t)->tv_usec) >= 1000000 && \ ((a)->tv_usec -= 1000000, (a)->tv_sec++) ) -#define timersub(s,t,a) ( (a)->tv_sec = (s)->tv_sec - (t)->tv_sec, \ +#define timersub(s,t,a) (void) ( (a)->tv_sec = (s)->tv_sec - (t)->tv_sec, \ ((a)->tv_usec = (s)->tv_usec - (t)->tv_usec) < 0 && \ ((a)->tv_usec += 1000000, (a)->tv_sec--) ) #endif diff --git a/include/sys/timeb.h b/include/sys/timeb.h new file mode 100644 index 0000000..108c1f5 --- /dev/null +++ b/include/sys/timeb.h @@ -0,0 +1,22 @@ +#ifndef _SYS_TIMEB_H +#define _SYS_TIMEB_H +#ifdef __cplusplus +extern "C" { +#endif + +#define __NEED_time_t + +#include + +struct timeb { + time_t time; + unsigned short millitm; + short timezone, dstflag; +}; + +int ftime(struct timeb *); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/sys/wait.h b/include/sys/wait.h index a7ad7cd..c794f5d 100644 --- a/include/sys/wait.h +++ b/include/sys/wait.h @@ -6,8 +6,6 @@ extern "C" { #include -#include - #define __NEED_pid_t #define __NEED_id_t #include @@ -19,9 +17,15 @@ typedef enum { } idtype_t; pid_t wait (int *); -int waitid (idtype_t, id_t, siginfo_t *, int); pid_t waitpid (pid_t, int *, int ); +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ + || defined(_BSD_SOURCE) +#include +int waitid (idtype_t, id_t, siginfo_t *, int); +#endif + #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) #include pid_t wait3 (int *, int, struct rusage *); diff --git a/include/syslog.h b/include/syslog.h index a9468d4..f7f545f 100644 --- a/include/syslog.h +++ b/include/syslog.h @@ -82,7 +82,7 @@ typedef struct { { "emerg", LOG_EMERG }, { "err", LOG_ERR }, { "error", LOG_ERR }, \ { "info", LOG_INFO }, { "none", INTERNAL_NOPRI }, \ { "notice", LOG_NOTICE }, { "panic", LOG_EMERG }, \ - { "warn", LOG_WARNING }, { "warning", LOG_WARNING }, { NULL, -1 } }) + { "warn", LOG_WARNING }, { "warning", LOG_WARNING }, { 0, -1 } }) #define facilitynames ((CODE *)(const struct __CODE []){ \ { "auth", LOG_AUTH }, { "authpriv", LOG_AUTHPRIV }, \ { "cron", LOG_CRON }, { "daemon", LOG_DAEMON }, { "ftp", LOG_FTP }, \ @@ -93,7 +93,7 @@ typedef struct { { "local0", LOG_LOCAL0 }, { "local1", LOG_LOCAL1 }, \ { "local2", LOG_LOCAL2 }, { "local3", LOG_LOCAL3 }, \ { "local4", LOG_LOCAL4 }, { "local5", LOG_LOCAL5 }, \ - { "local6", LOG_LOCAL6 }, { "local7", LOG_LOCAL7 }, { NULL, -1 } }) + { "local6", LOG_LOCAL6 }, { "local7", LOG_LOCAL7 }, { 0, -1 } }) #endif #endif diff --git a/include/time.h b/include/time.h index 6b2a069..7057409 100644 --- a/include/time.h +++ b/include/time.h @@ -7,7 +7,12 @@ extern "C" { #include +#ifdef __cplusplus #define NULL 0L +#else +#define NULL ((void*)0) +#endif + #define __NEED_size_t #define __NEED_time_t @@ -82,8 +87,8 @@ struct itimerspec #define CLOCK_PROCESS_CPUTIME_ID 2 #define CLOCK_THREAD_CPUTIME_ID 3 #define CLOCK_MONOTONIC_RAW 4 -#define CLOCK_REALTIME_COURSE 5 -#define CLOCK_MONOTONIC_COURSE 6 +#define CLOCK_REALTIME_COARSE 5 +#define CLOCK_MONOTONIC_COARSE 6 #define CLOCK_BOOTTIME 7 #define CLOCK_REALTIME_ALARM 8 #define CLOCK_BOOTTIME_ALARM 9 diff --git a/include/unistd.h b/include/unistd.h index a00a9c4..bf10a6d 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -15,7 +15,11 @@ extern "C" { #define SEEK_CUR 1 #define SEEK_END 2 +#ifdef __cplusplus #define NULL 0L +#else +#define NULL ((void*)0) +#endif #define __NEED_size_t #define __NEED_ssize_t @@ -31,6 +35,7 @@ extern "C" { int pipe(int [2]); int pipe2(int [2], int); int close(int); +int posix_close(int, int); int dup(int); int dup2(int, int); int dup3(int, int, int); @@ -196,6 +201,8 @@ int eaccess(const char *, int); #define off64_t off_t #endif +#define POSIX_CLOSE_RESTART 0 + #define _XOPEN_VERSION 700 #define _XOPEN_UNIX 1 #define _XOPEN_ENH_I18N 1 diff --git a/include/wchar.h b/include/wchar.h index fd5aac5..9fd967c 100644 --- a/include/wchar.h +++ b/include/wchar.h @@ -33,7 +33,11 @@ extern "C" { #define WCHAR_MIN (-1-0x7fffffff+L'\0') #endif +#ifdef __cplusplus #define NULL 0L +#else +#define NULL ((void*)0) +#endif #undef WEOF #define WEOF 0xffffffffU diff --git a/src/ctype/__ctype_b_loc.c b/src/ctype/__ctype_b_loc.c index 6e93dc0..f43795e 100644 --- a/src/ctype/__ctype_b_loc.c +++ b/src/ctype/__ctype_b_loc.c @@ -1,4 +1,3 @@ -#include #include #if __BYTE_ORDER == __BIG_ENDIAN diff --git a/src/ctype/__ctype_get_mb_cur_max.c b/src/ctype/__ctype_get_mb_cur_max.c index 42e4ee7..d235f4d 100644 --- a/src/ctype/__ctype_get_mb_cur_max.c +++ b/src/ctype/__ctype_get_mb_cur_max.c @@ -1,4 +1,4 @@ -#include +#include size_t __ctype_get_mb_cur_max() { diff --git a/src/ctype/__ctype_tolower_loc.c b/src/ctype/__ctype_tolower_loc.c index 62ce69a..efb9910 100644 --- a/src/ctype/__ctype_tolower_loc.c +++ b/src/ctype/__ctype_tolower_loc.c @@ -1,5 +1,4 @@ -#include -#include +#include static const int32_t table[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, diff --git a/src/ctype/__ctype_toupper_loc.c b/src/ctype/__ctype_toupper_loc.c index 1556164..ffaef0e 100644 --- a/src/ctype/__ctype_toupper_loc.c +++ b/src/ctype/__ctype_toupper_loc.c @@ -1,5 +1,4 @@ -#include -#include +#include static const int32_t table[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, diff --git a/src/ctype/iswspace.c b/src/ctype/iswspace.c index 99d517e..b0c0ae1 100644 --- a/src/ctype/iswspace.c +++ b/src/ctype/iswspace.c @@ -14,6 +14,5 @@ int iswspace(wint_t wc) 0x2006, 0x2008, 0x2009, 0x200a, 0x2028, 0x2029, 0x205f, 0x3000, 0 }; - if (wcschr(spaces, wc)) return 1; - return 0; + return wc && wcschr(spaces, wc); } diff --git a/src/dirent/fdopendir.c b/src/dirent/fdopendir.c index c684a86..c377271 100644 --- a/src/dirent/fdopendir.c +++ b/src/dirent/fdopendir.c @@ -3,8 +3,6 @@ #include #include #include -#include -#include #include "__dirent.h" DIR *fdopendir(int fd) diff --git a/src/dirent/opendir.c b/src/dirent/opendir.c index d33d892..5cb84e3 100644 --- a/src/dirent/opendir.c +++ b/src/dirent/opendir.c @@ -1,11 +1,7 @@ #define _GNU_SOURCE #include #include -#include -#include #include -#include -#include #include "__dirent.h" #include "syscall.h" diff --git a/src/dirent/readdir.c b/src/dirent/readdir.c index 2d27d29..98ec029 100644 --- a/src/dirent/readdir.c +++ b/src/dirent/readdir.c @@ -1,11 +1,5 @@ #include -#include -#include -#include -#include -#include #include "__dirent.h" -#include "syscall.h" #include "libc.h" int __getdents(int, struct dirent *, size_t); diff --git a/src/dirent/readdir_r.c b/src/dirent/readdir_r.c index 639d49a..daa6c6e 100644 --- a/src/dirent/readdir_r.c +++ b/src/dirent/readdir_r.c @@ -1,6 +1,5 @@ #include #include -#include #include #include "__dirent.h" #include "libc.h" diff --git a/src/dirent/scandir.c b/src/dirent/scandir.c index a85cfac..3af2b50 100644 --- a/src/dirent/scandir.c +++ b/src/dirent/scandir.c @@ -1,10 +1,10 @@ #include #include #include -#include +#include #include #include -#include +#include "libc.h" int scandir(const char *path, struct dirent ***res, int (*sel)(const struct dirent *), diff --git a/src/env/__init_security.c b/src/env/__init_security.c index 91b9b10..6204c5e 100644 --- a/src/env/__init_security.c +++ b/src/env/__init_security.c @@ -1,4 +1,3 @@ -#include #include #include #include diff --git a/src/env/__stack_chk_fail.c b/src/env/__stack_chk_fail.c index 031a1ed..daa1b07 100644 --- a/src/env/__stack_chk_fail.c +++ b/src/env/__stack_chk_fail.c @@ -1,6 +1,5 @@ #include -#include -#include +#include #include "pthread_impl.h" #include "atomic.h" diff --git a/src/env/clearenv.c b/src/env/clearenv.c index a2475ce..62d5095 100644 --- a/src/env/clearenv.c +++ b/src/env/clearenv.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include extern char **__environ; diff --git a/src/env/putenv.c b/src/env/putenv.c index d141db1..4042869 100644 --- a/src/env/putenv.c +++ b/src/env/putenv.c @@ -1,7 +1,5 @@ #include #include -#include -#include extern char **__environ; char **__env_map; diff --git a/src/env/setenv.c b/src/env/setenv.c index c2c2544..76e8ee1 100644 --- a/src/env/setenv.c +++ b/src/env/setenv.c @@ -18,14 +18,13 @@ int setenv(const char *var, const char *value, int overwrite) l1 = strlen(var); l2 = strlen(value); s = malloc(l1+l2+2); - memcpy(s, var, l1); - s[l1] = '='; - memcpy(s+l1+1, value, l2); - s[l1+l2+1] = 0; - if (__putenv(s, 1)) { - free(s); - errno = ENOMEM; - return -1; + if (s) { + memcpy(s, var, l1); + s[l1] = '='; + memcpy(s+l1+1, value, l2); + s[l1+l2+1] = 0; + if (!__putenv(s, 1)) return 0; } - return 0; + free(s); + return -1; } diff --git a/src/env/unsetenv.c b/src/env/unsetenv.c index 7493d97..3569335 100644 --- a/src/env/unsetenv.c +++ b/src/env/unsetenv.c @@ -1,4 +1,3 @@ -#include #include #include #include diff --git a/src/exit/atexit.c b/src/exit/atexit.c index c31f3dc..89ff4ff 100644 --- a/src/exit/atexit.c +++ b/src/exit/atexit.c @@ -1,7 +1,5 @@ -#include #include #include -#include #include "libc.h" /* Ensure that at least 32 atexit handlers can be registered without malloc */ diff --git a/src/exit/exit.c b/src/exit/exit.c index f259c98..353f50b 100644 --- a/src/exit/exit.c +++ b/src/exit/exit.c @@ -1,6 +1,5 @@ #include -#include -#include +#include #include "libc.h" #include "atomic.h" #include "syscall.h" diff --git a/src/fcntl/fcntl.c b/src/fcntl/fcntl.c index 390ef75..4c34ba0 100644 --- a/src/fcntl/fcntl.c +++ b/src/fcntl/fcntl.c @@ -1,6 +1,5 @@ #define _GNU_SOURCE #include -#include #include #include #include "syscall.h" diff --git a/src/fcntl/open.c b/src/fcntl/open.c index 31d6744..be44208 100644 --- a/src/fcntl/open.c +++ b/src/fcntl/open.c @@ -1,5 +1,4 @@ #include -#include #include #include "syscall.h" #include "libc.h" diff --git a/src/fcntl/openat.c b/src/fcntl/openat.c index bdecb8c..634c4bf 100644 --- a/src/fcntl/openat.c +++ b/src/fcntl/openat.c @@ -1,5 +1,4 @@ #include -#include #include #include "syscall.h" #include "libc.h" diff --git a/src/fenv/i386/fenv.s b/src/fenv/i386/fenv.s index eaeb6be..f6036d6 100644 --- a/src/fenv/i386/fenv.s +++ b/src/fenv/i386/fenv.s @@ -75,7 +75,7 @@ __fesetround: 1: addl $__hwcap-1b,(%esp) pop %edx testl $0x02000000,(%edx) - jmp 1f + jz 1f stmxcsr (%esp) shl $3,%ch andb $0x9f,1(%esp) diff --git a/src/internal/syscall_ret.c b/src/internal/syscall_ret.c index e4a1bdb..d99f4a5 100644 --- a/src/internal/syscall_ret.c +++ b/src/internal/syscall_ret.c @@ -1,5 +1,4 @@ #include -#include long __syscall_ret(unsigned long r) { diff --git a/src/internal/version.c b/src/internal/version.c new file mode 100644 index 0000000..16554ba --- /dev/null +++ b/src/internal/version.c @@ -0,0 +1,12 @@ +#ifdef SHARED + +#include "version.h" + +static const char version[] = VERSION; + +const char *__libc_get_version() +{ + return version; +} + +#endif diff --git a/src/ipc/ipc.h b/src/ipc/ipc.h index 5487582..30ab939 100644 --- a/src/ipc/ipc.h +++ b/src/ipc/ipc.h @@ -1,6 +1,7 @@ #define IPCOP_semop 1 #define IPCOP_semget 2 #define IPCOP_semctl 3 +#define IPCOP_semtimedop 4 #define IPCOP_msgsnd 11 #define IPCOP_msgrcv 12 #define IPCOP_msgget 13 diff --git a/src/ipc/semtimedop.c b/src/ipc/semtimedop.c new file mode 100644 index 0000000..b0c4cf9 --- /dev/null +++ b/src/ipc/semtimedop.c @@ -0,0 +1,13 @@ +#define _GNU_SOURCE +#include +#include "syscall.h" +#include "ipc.h" + +int semtimedop(int id, struct sembuf *buf, size_t n, const struct timespec *ts) +{ +#ifdef SYS_semtimedop + return syscall(SYS_semtimedop, id, buf, n, ts); +#else + return syscall(SYS_ipc, IPCOP_semtimedop, id, n, 0, buf, ts); +#endif +} diff --git a/src/ldso/dlinfo.c b/src/ldso/dlinfo.c index 4748eaf..63d276d 100644 --- a/src/ldso/dlinfo.c +++ b/src/ldso/dlinfo.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include int __dlinfo(void *, int, void *); diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c index a525b3d..27d92f2 100644 --- a/src/ldso/dynlink.c +++ b/src/ldso/dynlink.c @@ -7,12 +7,9 @@ #include #include #include -#include #include #include #include -#include -#include #include #include #include @@ -96,6 +93,8 @@ void __init_ssp(size_t *); void *__install_initial_tls(void *); void __init_libc(char **, char *); +const char *__libc_get_version(void); + static struct dso *head, *tail, *ldso, *fini_head; static char *env_path, *sys_path; static unsigned long long gencnt; @@ -1043,8 +1042,11 @@ void *__dynlink(int argc, char **argv) *argv++ = (void *)-1; if (argv[0] && !strcmp(argv[0], "--")) *argv++ = (void *)-1; if (!argv[0]) { - dprintf(2, "musl libc/dynamic program loader\n"); - dprintf(2, "usage: %s pathname%s\n", ldname, + dprintf(2, "musl libc\n" + "Version %s\n" + "Dynamic Program Loader\n" + "Usage: %s [--] pathname%s\n", + __libc_get_version(), ldname, ldd_mode ? "" : " [args]"); _exit(1); } @@ -1354,7 +1356,7 @@ int __dladdr(void *addr, Dl_info *info) uint32_t *hashval; buckets = p->ghashtab + 4 + (p->ghashtab[2]*sizeof(size_t)/4); sym += p->ghashtab[1]; - for (i = 0; i < p->ghashtab[0]; i++) { + for (i = nsym = 0; i < p->ghashtab[0]; i++) { if (buckets[i] > nsym) nsym = buckets[i]; } diff --git a/src/ldso/microblaze/start.s b/src/ldso/microblaze/start.s index 5ffbcba..4e0a0e5 100644 --- a/src/ldso/microblaze/start.s +++ b/src/ldso/microblaze/start.s @@ -9,11 +9,12 @@ _start: addi r7, r7, _GLOBAL_OFFSET_TABLE_+8 addi r7, r7, _DYNAMIC@GOTOFF brlid r15, __reloc_self@PLT - nop + addik r1, r1, -16 - lwi r5, r1, 0 + lwi r5, r1, 16 brlid r15, __dynlink@PLT - addi r6, r1, 4 + addi r6, r1, 20 + addik r1, r1, 16 lwi r4, r1, 0 1: lwi r5, r1, 4 diff --git a/src/legacy/euidaccess.c b/src/legacy/euidaccess.c index 47b464d..7307251 100644 --- a/src/legacy/euidaccess.c +++ b/src/legacy/euidaccess.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include #include #include "libc.h" diff --git a/src/legacy/futimes.c b/src/legacy/futimes.c index f8fd1cd..d81d83a 100644 --- a/src/legacy/futimes.c +++ b/src/legacy/futimes.c @@ -1,6 +1,6 @@ +#define _GNU_SOURCE #include #include -#include int futimes(int fd, const struct timeval tv[2]) { diff --git a/src/legacy/getdtablesize.c b/src/legacy/getdtablesize.c index 623a6af..682da6d 100644 --- a/src/legacy/getdtablesize.c +++ b/src/legacy/getdtablesize.c @@ -1,3 +1,5 @@ +#define _GNU_SOURCE +#include #include #include diff --git a/src/legacy/getloadavg.c b/src/legacy/getloadavg.c new file mode 100644 index 0000000..43a8c9e --- /dev/null +++ b/src/legacy/getloadavg.c @@ -0,0 +1,18 @@ +#define _GNU_SOURCE +#include +#include +#include + +int getloadavg(double *a, int n) +{ + int i; + double b[3]; + FILE *f = fopen("/proc/loadavg", "rbe"); + if (!f) return -1; + i = fscanf(f, "%lf %lf %lf", b, b+1, b+2); + fclose(f); + if (n > i) n = i; + if (n < 0) return -1; + memcpy(a, b, n * sizeof *a); + return n; +} diff --git a/src/legacy/getpagesize.c b/src/legacy/getpagesize.c index a47995c..0fc29ff 100644 --- a/src/legacy/getpagesize.c +++ b/src/legacy/getpagesize.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include #include "libc.h" diff --git a/src/legacy/getpass.c b/src/legacy/getpass.c index d439a2a..3565d95 100644 --- a/src/legacy/getpass.c +++ b/src/legacy/getpass.c @@ -1,5 +1,5 @@ +#define _GNU_SOURCE #include -#include #include #include #include diff --git a/src/legacy/getusershell.c b/src/legacy/getusershell.c index f31f404..5fecdec 100644 --- a/src/legacy/getusershell.c +++ b/src/legacy/getusershell.c @@ -1,7 +1,6 @@ #define _GNU_SOURCE #include -#include -#include +#include static const char defshells[] = "/bin/sh\n/bin/csh\n"; diff --git a/src/legacy/lutimes.c b/src/legacy/lutimes.c index 13dfe4e..2e5502d 100644 --- a/src/legacy/lutimes.c +++ b/src/legacy/lutimes.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include #include #include diff --git a/src/linux/chroot.c b/src/linux/chroot.c index 82b4fe7..0e69f14 100644 --- a/src/linux/chroot.c +++ b/src/linux/chroot.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include #include "syscall.h" diff --git a/src/linux/clock_adjtime.c b/src/linux/clock_adjtime.c index 1fc9bef..056ad6d 100644 --- a/src/linux/clock_adjtime.c +++ b/src/linux/clock_adjtime.c @@ -1,5 +1,3 @@ -#define _GNU_SOURCE -#include #include #include "syscall.h" diff --git a/src/linux/klogctl.c b/src/linux/klogctl.c index 209ae74..8102ee6 100644 --- a/src/linux/klogctl.c +++ b/src/linux/klogctl.c @@ -1,3 +1,4 @@ +#include #include "syscall.h" int klogctl (int type, char *buf, int len) diff --git a/src/linux/personality.c b/src/linux/personality.c index 06851f5..e00cf79 100644 --- a/src/linux/personality.c +++ b/src/linux/personality.c @@ -1,3 +1,4 @@ +#include #include "syscall.h" #ifdef SYS_personality int personality(unsigned long persona) diff --git a/src/linux/prlimit.c b/src/linux/prlimit.c index 1215248..d1639cc 100644 --- a/src/linux/prlimit.c +++ b/src/linux/prlimit.c @@ -1,4 +1,4 @@ -#include +#define _GNU_SOURCE #include #include "syscall.h" #include "libc.h" @@ -8,4 +8,5 @@ int prlimit(pid_t pid, int resource, const struct rlimit *new_limit, struct rlim return syscall(SYS_prlimit64, pid, resource, new_limit, old_limit); } +#undef prlimit64 LFS64(prlimit); diff --git a/src/linux/sendfile.c b/src/linux/sendfile.c index 818b19d..d63f419 100644 --- a/src/linux/sendfile.c +++ b/src/linux/sendfile.c @@ -1,4 +1,4 @@ -#include +#include #include "syscall.h" #include "libc.h" diff --git a/src/linux/setfsgid.c b/src/linux/setfsgid.c index a7ed9e9..ad80422 100644 --- a/src/linux/setfsgid.c +++ b/src/linux/setfsgid.c @@ -1,4 +1,4 @@ -#include +#include #include "syscall.h" #include "libc.h" diff --git a/src/linux/setfsuid.c b/src/linux/setfsuid.c index 1509e0a..8635873 100644 --- a/src/linux/setfsuid.c +++ b/src/linux/setfsuid.c @@ -1,4 +1,4 @@ -#include +#include #include "syscall.h" #include "libc.h" diff --git a/src/linux/setgroups.c b/src/linux/setgroups.c index 9758940..1248fdb 100644 --- a/src/linux/setgroups.c +++ b/src/linux/setgroups.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include #include "syscall.h" diff --git a/src/linux/sethostname.c b/src/linux/sethostname.c index 79a8707..9313b32 100644 --- a/src/linux/sethostname.c +++ b/src/linux/sethostname.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include #include "syscall.h" diff --git a/src/linux/setns.c b/src/linux/setns.c index 7029b74..0afec81 100644 --- a/src/linux/setns.c +++ b/src/linux/setns.c @@ -1,7 +1,6 @@ #define _GNU_SOURCE #include #include "syscall.h" -#include "libc.h" int setns(int fd, int nstype) { diff --git a/src/linux/stime.c b/src/linux/stime.c index 6a7e9e8..29a1ec6 100644 --- a/src/linux/stime.c +++ b/src/linux/stime.c @@ -1,4 +1,5 @@ #define _GNU_SOURCE +#include #include int stime(time_t *t) diff --git a/src/linux/sysinfo.c b/src/linux/sysinfo.c index 2dbd0ad..7e64f33 100644 --- a/src/linux/sysinfo.c +++ b/src/linux/sysinfo.c @@ -1,7 +1,6 @@ +#include #include "syscall.h" -struct sysinfo; - int sysinfo(struct sysinfo *info) { return syscall(SYS_sysinfo, info); diff --git a/src/linux/wait4.c b/src/linux/wait4.c index b3ae75e..97f12cc 100644 --- a/src/linux/wait4.c +++ b/src/linux/wait4.c @@ -1,7 +1,6 @@ #define _GNU_SOURCE #include #include -#include #include "syscall.h" pid_t wait4(pid_t pid, int *status, int options, struct rusage *usage) diff --git a/src/locale/intl.c b/src/locale/intl.c index 964f7da..ad04052 100644 --- a/src/locale/intl.c +++ b/src/locale/intl.c @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/src/locale/localeconv.c b/src/locale/localeconv.c index 494cbcc..cbc75d7 100644 --- a/src/locale/localeconv.c +++ b/src/locale/localeconv.c @@ -1,6 +1,4 @@ #include -#include -#include static const struct lconv posix_lconv = { .decimal_point = ".", diff --git a/src/locale/strcasecmp_l.c b/src/locale/strcasecmp_l.c index eea2f80..ca80543 100644 --- a/src/locale/strcasecmp_l.c +++ b/src/locale/strcasecmp_l.c @@ -1,5 +1,4 @@ #include -#include int strcasecmp_l(const char *l, const char *r, locale_t loc) { diff --git a/src/locale/strfmon.c b/src/locale/strfmon.c index f510d9a..e25db97 100644 --- a/src/locale/strfmon.c +++ b/src/locale/strfmon.c @@ -3,7 +3,6 @@ #include #include #include -#include static ssize_t vstrfmon_l(char *s, size_t n, locale_t loc, const char *fmt, va_list ap) { diff --git a/src/malloc/__brk.c b/src/malloc/__brk.c index 0b561ea..4c9119b 100644 --- a/src/malloc/__brk.c +++ b/src/malloc/__brk.c @@ -3,5 +3,5 @@ uintptr_t __brk(uintptr_t newbrk) { - return syscall(SYS_brk, newbrk); + return __syscall(SYS_brk, newbrk); } diff --git a/src/malloc/calloc.c b/src/malloc/calloc.c index 9d57456..c3dfb47 100644 --- a/src/malloc/calloc.c +++ b/src/malloc/calloc.c @@ -1,6 +1,5 @@ #include #include -#include void *calloc(size_t m, size_t n) { diff --git a/src/malloc/malloc.c b/src/malloc/malloc.c index fb65ab5..d6ad904 100644 --- a/src/malloc/malloc.c +++ b/src/malloc/malloc.c @@ -177,6 +177,7 @@ static struct chunk *expand_heap(size_t n) return w; fail: unlock(mal.brk_lock); + errno = ENOMEM; return 0; } diff --git a/src/math/__log1p.h b/src/math/__log1p.h deleted file mode 100644 index 5718711..0000000 --- a/src/math/__log1p.h +++ /dev/null @@ -1,94 +0,0 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/k_log.h */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* - * __log1p(f): - * Return log(1+f) - f for 1+f in ~[sqrt(2)/2, sqrt(2)]. - * - * The following describes the overall strategy for computing - * logarithms in base e. The argument reduction and adding the final - * term of the polynomial are done by the caller for increased accuracy - * when different bases are used. - * - * Method : - * 1. Argument Reduction: find k and f such that - * x = 2^k * (1+f), - * where sqrt(2)/2 < 1+f < sqrt(2) . - * - * 2. Approximation of log(1+f). - * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) - * = 2s + 2/3 s**3 + 2/5 s**5 + ....., - * = 2s + s*R - * We use a special Reme algorithm on [0,0.1716] to generate - * a polynomial of degree 14 to approximate R The maximum error - * of this polynomial approximation is bounded by 2**-58.45. In - * other words, - * 2 4 6 8 10 12 14 - * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s - * (the values of Lg1 to Lg7 are listed in the program) - * and - * | 2 14 | -58.45 - * | Lg1*s +...+Lg7*s - R(z) | <= 2 - * | | - * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. - * In order to guarantee error in log below 1ulp, we compute log - * by - * log(1+f) = f - s*(f - R) (if f is not too large) - * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy) - * - * 3. Finally, log(x) = k*ln2 + log(1+f). - * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) - * Here ln2 is split into two floating point number: - * ln2_hi + ln2_lo, - * where n*ln2_hi is always exact for |n| < 2000. - * - * Special cases: - * log(x) is NaN with signal if x < 0 (including -INF) ; - * log(+INF) is +INF; log(0) is -INF with signal; - * log(NaN) is that NaN with no signal. - * - * Accuracy: - * according to an error analysis, the error is always less than - * 1 ulp (unit in the last place). - * - * Constants: - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ - -static const double -Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ -Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ -Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ -Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ -Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ -Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ -Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ - -/* - * We always inline __log1p(), since doing so produces a - * substantial performance improvement (~40% on amd64). - */ -static inline double __log1p(double f) -{ - double_t hfsq,s,z,R,w,t1,t2; - - s = f/(2.0+f); - z = s*s; - w = z*z; - t1= w*(Lg2+w*(Lg4+w*Lg6)); - t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); - R = t2+t1; - hfsq = 0.5*f*f; - return s*(hfsq+R); -} diff --git a/src/math/__log1pf.h b/src/math/__log1pf.h deleted file mode 100644 index f2fbef2..0000000 --- a/src/math/__log1pf.h +++ /dev/null @@ -1,35 +0,0 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/k_logf.h */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* - * See comments in __log1p.h. - */ - -/* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */ -static const float -Lg1 = 0xaaaaaa.0p-24, /* 0.66666662693 */ -Lg2 = 0xccce13.0p-25, /* 0.40000972152 */ -Lg3 = 0x91e9ee.0p-25, /* 0.28498786688 */ -Lg4 = 0xf89e26.0p-26; /* 0.24279078841 */ - -static inline float __log1pf(float f) -{ - float_t hfsq,s,z,R,w,t1,t2; - - s = f/(2.0f + f); - z = s*s; - w = z*z; - t1 = w*(Lg2+w*Lg4); - t2 = z*(Lg1+w*Lg3); - R = t2+t1; - hfsq = 0.5f * f * f; - return s*(hfsq+R); -} diff --git a/src/math/__rem_pio2.c b/src/math/__rem_pio2.c index 9305be5..5fafc4a 100644 --- a/src/math/__rem_pio2.c +++ b/src/math/__rem_pio2.c @@ -29,7 +29,6 @@ * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) */ static const double -two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */ pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */ @@ -41,18 +40,19 @@ pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */ /* caller must handle the case when reduction is not needed: |x| ~<= pi/4 */ int __rem_pio2(double x, double *y) { - double z,w,t,r,fn; - double tx[3],ty[2]; - int32_t e0,i,j,nx,n,ix,hx; - uint32_t low; + union {double f; uint64_t i;} u = {x}; + double_t z,w,t,r; + double tx[3],ty[2],fn; + uint32_t ix; + int sign, n, ex, ey, i; - GET_HIGH_WORD(hx,x); - ix = hx & 0x7fffffff; + sign = u.i>>63; + ix = u.i>>32 & 0x7fffffff; if (ix <= 0x400f6a7a) { /* |x| ~<= 5pi/4 */ if ((ix & 0xfffff) == 0x921fb) /* |x| ~= pi/2 or 2pi/2 */ goto medium; /* cancellation -- use medium case */ if (ix <= 0x4002d97c) { /* |x| ~<= 3pi/4 */ - if (hx > 0) { + if (!sign) { z = x - pio2_1; /* one round good to 85 bits */ y[0] = z - pio2_1t; y[1] = (z-y[0]) - pio2_1t; @@ -64,7 +64,7 @@ int __rem_pio2(double x, double *y) return -1; } } else { - if (hx > 0) { + if (!sign) { z = x - 2*pio2_1; y[0] = z - 2*pio2_1t; y[1] = (z-y[0]) - 2*pio2_1t; @@ -81,7 +81,7 @@ int __rem_pio2(double x, double *y) if (ix <= 0x4015fdbc) { /* |x| ~<= 7pi/4 */ if (ix == 0x4012d97c) /* |x| ~= 3pi/2 */ goto medium; - if (hx > 0) { + if (!sign) { z = x - 3*pio2_1; y[0] = z - 3*pio2_1t; y[1] = (z-y[0]) - 3*pio2_1t; @@ -95,7 +95,7 @@ int __rem_pio2(double x, double *y) } else { if (ix == 0x401921fb) /* |x| ~= 4pi/2 */ goto medium; - if (hx > 0) { + if (!sign) { z = x - 4*pio2_1; y[0] = z - 4*pio2_1t; y[1] = (z-y[0]) - 4*pio2_1t; @@ -109,32 +109,26 @@ int __rem_pio2(double x, double *y) } } if (ix < 0x413921fb) { /* |x| ~< 2^20*(pi/2), medium size */ - uint32_t high; medium: - /* Use a specialized rint() to get fn. Assume round-to-nearest. */ + /* rint(x/(pi/2)), Assume round-to-nearest. */ fn = x*invpio2 + 0x1.8p52; fn = fn - 0x1.8p52; -// FIXME -#ifdef HAVE_EFFICIENT_IRINT - n = irint(fn); -#else n = (int32_t)fn; -#endif r = x - fn*pio2_1; w = fn*pio2_1t; /* 1st round, good to 85 bits */ - j = ix>>20; y[0] = r - w; - GET_HIGH_WORD(high,y[0]); - i = j - ((high>>20)&0x7ff); - if (i > 16) { /* 2nd round, good to 118 bits */ + u.f = y[0]; + ey = u.i>>52 & 0x7ff; + ex = ix>>20; + if (ex - ey > 16) { /* 2nd round, good to 118 bits */ t = r; w = fn*pio2_2; r = t - w; w = fn*pio2_2t - ((t-r)-w); y[0] = r - w; - GET_HIGH_WORD(high,y[0]); - i = j - ((high>>20)&0x7ff); - if (i > 49) { /* 3rd round, good to 151 bits, covers all cases */ + u.f = y[0]; + ey = u.i>>52 & 0x7ff; + if (ex - ey > 49) { /* 3rd round, good to 151 bits, covers all cases */ t = r; w = fn*pio2_3; r = t - w; @@ -142,7 +136,7 @@ medium: y[0] = r - w; } } - y[1] = (r-y[0]) - w; + y[1] = (r - y[0]) - w; return n; } /* @@ -152,19 +146,21 @@ medium: y[0] = y[1] = x - x; return 0; } - /* set z = scalbn(|x|,ilogb(x)-23) */ - GET_LOW_WORD(low,x); - e0 = (ix>>20) - 1046; /* e0 = ilogb(z)-23; */ - INSERT_WORDS(z, ix - ((int32_t)(e0<<20)), low); - for (i=0; i<2; i++) { - tx[i] = (double)((int32_t)(z)); - z = (z-tx[i])*two24; + /* set z = scalbn(|x|,-ilogb(x)+23) */ + u.f = x; + u.i &= (uint64_t)-1>>12; + u.i |= (uint64_t)(0x3ff + 23)<<52; + z = u.f; + for (i=0; i < 2; i++) { + tx[i] = (double)(int32_t)z; + z = (z-tx[i])*0x1p24; } - tx[2] = z; - nx = 3; - while (tx[nx-1] == 0.0) nx--; /* skip zero term */ - n = __rem_pio2_large(tx,ty,e0,nx,1); - if (hx < 0) { + tx[i] = z; + /* skip zero terms, first term is non-zero */ + while (tx[i] == 0.0) + i--; + n = __rem_pio2_large(tx,ty,(int)(ix>>20)-(0x3ff+23),i+1,1); + if (sign) { y[0] = -ty[0]; y[1] = -ty[1]; return -n; diff --git a/src/math/__rem_pio2_large.c b/src/math/__rem_pio2_large.c index bb2dc43..958f28c 100644 --- a/src/math/__rem_pio2_large.c +++ b/src/math/__rem_pio2_large.c @@ -270,10 +270,6 @@ static const double PIo2[] = { 2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */ }; -static const double -two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ -twon24 = 5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */ - int __rem_pio2_large(double *x, double *y, int e0, int nx, int prec) { int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih; @@ -304,8 +300,8 @@ int __rem_pio2_large(double *x, double *y, int e0, int nx, int prec) recompute: /* distill q[] into iq[] reversingly */ for (i=0,j=jz,z=q[jz]; j>0; i++,j--) { - fw = (double)((int32_t)(twon24* z)); - iq[i] = (int32_t)(z-two24*fw); + fw = (double)(int32_t)(0x1p-24*z); + iq[i] = (int32_t)(z - 0x1p24*fw); z = q[j-1]+fw; } @@ -330,7 +326,7 @@ recompute: if (carry == 0) { if (j != 0) { carry = 1; - iq[i] = 0x1000000- j; + iq[i] = 0x1000000 - j; } } else iq[i] = 0xffffff - j; @@ -378,9 +374,9 @@ recompute: } } else { /* break z into 24-bit if necessary */ z = scalbn(z,-q0); - if (z >= two24) { - fw = (double)((int32_t)(twon24*z)); - iq[jz] = (int32_t)(z-two24*fw); + if (z >= 0x1p24) { + fw = (double)(int32_t)(0x1p-24*z); + iq[jz] = (int32_t)(z - 0x1p24*fw); jz += 1; q0 += 24; iq[jz] = (int32_t)fw; @@ -392,7 +388,7 @@ recompute: fw = scalbn(1.0,q0); for (i=jz; i>=0; i--) { q[i] = fw*(double)iq[i]; - fw *= twon24; + fw *= 0x1p-24; } /* compute PIo2[0,...,jp]*q[jz,...,0] */ diff --git a/src/math/__rem_pio2f.c b/src/math/__rem_pio2f.c index 5bdeb52..838e1fc 100644 --- a/src/math/__rem_pio2f.c +++ b/src/math/__rem_pio2f.c @@ -34,42 +34,32 @@ pio2_1t = 1.58932547735281966916e-08; /* 0x3E5110b4, 0x611A6263 */ int __rem_pio2f(float x, double *y) { - double w,r,fn; - double tx[1],ty[1]; - float z; - int32_t e0,n,ix,hx; + union {float f; uint32_t i;} u = {x}; + double tx[1],ty[1],fn; + uint32_t ix; + int n, sign, e0; - GET_FLOAT_WORD(hx, x); - ix = hx & 0x7fffffff; + ix = u.i & 0x7fffffff; /* 25+53 bit pi is good enough for medium size */ if (ix < 0x4dc90fdb) { /* |x| ~< 2^28*(pi/2), medium size */ /* Use a specialized rint() to get fn. Assume round-to-nearest. */ fn = x*invpio2 + 0x1.8p52; fn = fn - 0x1.8p52; -// FIXME -#ifdef HAVE_EFFICIENT_IRINT - n = irint(fn); -#else n = (int32_t)fn; -#endif - r = x - fn*pio2_1; - w = fn*pio2_1t; - *y = r - w; + *y = x - fn*pio2_1 - fn*pio2_1t; return n; } - /* - * all other (large) arguments - */ if(ix>=0x7f800000) { /* x is inf or NaN */ *y = x-x; return 0; } - /* set z = scalbn(|x|,ilogb(|x|)-23) */ - e0 = (ix>>23) - 150; /* e0 = ilogb(|x|)-23; */ - SET_FLOAT_WORD(z, ix - ((int32_t)(e0<<23))); - tx[0] = z; + /* scale x into [2^23, 2^24-1] */ + sign = u.i>>31; + e0 = (ix>>23) - (0x7f+23); /* e0 = ilogb(|x|)-23, positive */ + u.i = ix - (e0<<23); + tx[0] = u.f; n = __rem_pio2_large(tx,ty,e0,1,0); - if (hx < 0) { + if (sign) { *y = -ty[0]; return -n; } diff --git a/src/math/acosh.c b/src/math/acosh.c index 4ce9b3d..badbf90 100644 --- a/src/math/acosh.c +++ b/src/math/acosh.c @@ -1,5 +1,10 @@ #include "libm.h" +#if FLT_EVAL_METHOD==2 +#undef sqrt +#define sqrt sqrtl +#endif + /* acosh(x) = log(x + sqrt(x*x-1)) */ double acosh(double x) { diff --git a/src/math/acoshf.c b/src/math/acoshf.c index 16550f1..8a4ec4d 100644 --- a/src/math/acoshf.c +++ b/src/math/acoshf.c @@ -1,5 +1,13 @@ #include "libm.h" +#if FLT_EVAL_METHOD==2 +#undef sqrtf +#define sqrtf sqrtl +#elif FLT_EVAL_METHOD==1 +#undef sqrtf +#define sqrtf sqrt +#endif + /* acosh(x) = log(x + sqrt(x*x-1)) */ float acoshf(float x) { diff --git a/src/math/erfl.c b/src/math/erfl.c index 42bb1a1..96b74de 100644 --- a/src/math/erfl.c +++ b/src/math/erfl.c @@ -266,23 +266,12 @@ static long double erfc2(uint32_t ix, long double x) s * (ra[5] + s * (ra[6] + s * (ra[7] + s * ra[8]))))))); S = sa[0] + s * (sa[1] + s * (sa[2] + s * (sa[3] + s * (sa[4] + s * (sa[5] + s * (sa[6] + s * (sa[7] + s * (sa[8] + s)))))))); - } else { /* 2.857 <= |x| */ + } else if (ix < 0x4001d555) { /* 2.857 <= |x| < 6.6666259765625 */ R = rb[0] + s * (rb[1] + s * (rb[2] + s * (rb[3] + s * (rb[4] + s * (rb[5] + s * (rb[6] + s * rb[7])))))); S = sb[0] + s * (sb[1] + s * (sb[2] + s * (sb[3] + s * (sb[4] + s * (sb[5] + s * (sb[6] + s)))))); - } - if (ix < 0x4000b6db) { /* 1.25 <= |x| < 2.85711669921875 ~ 1/.35 */ - R = ra[0] + s * (ra[1] + s * (ra[2] + s * (ra[3] + s * (ra[4] + - s * (ra[5] + s * (ra[6] + s * (ra[7] + s * ra[8]))))))); - S = sa[0] + s * (sa[1] + s * (sa[2] + s * (sa[3] + s * (sa[4] + - s * (sa[5] + s * (sa[6] + s * (sa[7] + s * (sa[8] + s)))))))); - } else if (ix < 0x4001d555) { /* 6.6666259765625 > |x| >= 1/.35 ~ 2.857143 */ - R = rb[0] + s * (rb[1] + s * (rb[2] + s * (rb[3] + s * (rb[4] + - s * (rb[5] + s * (rb[6] + s * rb[7])))))); - S = sb[0] + s * (sb[1] + s * (sb[2] + s * (sb[3] + s * (sb[4] + - s * (sb[5] + s * (sb[6] + s)))))); - } else { /* 107 > |x| >= 6.666 */ + } else { /* 6.666 <= |x| < 107 (erfc only) */ R = rc[0] + s * (rc[1] + s * (rc[2] + s * (rc[3] + s * (rc[4] + s * rc[5])))); S = sc[0] + s * (sc[1] + s * (sc[2] + s * (sc[3] + diff --git a/src/math/finite.c b/src/math/finite.c new file mode 100644 index 0000000..25a0575 --- /dev/null +++ b/src/math/finite.c @@ -0,0 +1,7 @@ +#define _GNU_SOURCE +#include + +int finite(double x) +{ + return isfinite(x); +} diff --git a/src/math/finitef.c b/src/math/finitef.c new file mode 100644 index 0000000..2c4c771 --- /dev/null +++ b/src/math/finitef.c @@ -0,0 +1,7 @@ +#define _GNU_SOURCE +#include + +int finitef(float x) +{ + return isfinite(x); +} diff --git a/src/math/fma.c b/src/math/fma.c index 84868be..02f5c86 100644 --- a/src/math/fma.c +++ b/src/math/fma.c @@ -431,12 +431,24 @@ double fma(double x, double y, double z) /* * There is no need to worry about double rounding in directed * rounding modes. - * TODO: underflow is not raised properly, example in downward rounding: + * But underflow may not be raised properly, example in downward rounding: * fma(0x1.000000001p-1000, 0x1.000000001p-30, -0x1p-1066) */ + double ret; +#if defined(FE_INEXACT) && defined(FE_UNDERFLOW) + int e = fetestexcept(FE_INEXACT); + feclearexcept(FE_INEXACT); +#endif fesetround(oround); adj = r.lo + xy.lo; - return scalbn(r.hi + adj, spread); + ret = scalbn(r.hi + adj, spread); +#if defined(FE_INEXACT) && defined(FE_UNDERFLOW) + if (ilogb(ret) < -1022 && fetestexcept(FE_INEXACT)) + feraiseexcept(FE_UNDERFLOW); + else if (e) + feraiseexcept(FE_INEXACT); +#endif + return ret; } adj = add_adjusted(r.lo, xy.lo); diff --git a/src/math/fmaf.c b/src/math/fmaf.c index 745ee39..aa57feb 100644 --- a/src/math/fmaf.c +++ b/src/math/fmaf.c @@ -26,7 +26,8 @@ */ #include -#include "libm.h" +#include +#include /* * Fused multiply-add: Compute x * y + z with a single rounding error. @@ -39,21 +40,35 @@ float fmaf(float x, float y, float z) { #pragma STDC FENV_ACCESS ON double xy, result; - uint32_t hr, lr; + union {double f; uint64_t i;} u; + int e; xy = (double)x * y; result = xy + z; - EXTRACT_WORDS(hr, lr, result); + u.f = result; + e = u.i>>52 & 0x7ff; /* Common case: The double precision result is fine. */ - if ((lr & 0x1fffffff) != 0x10000000 || /* not a halfway case */ - (hr & 0x7ff00000) == 0x7ff00000 || /* NaN */ + if ((u.i & 0x1fffffff) != 0x10000000 || /* not a halfway case */ + e == 0x7ff || /* NaN */ result - xy == z || /* exact */ fegetround() != FE_TONEAREST) /* not round-to-nearest */ { /* - TODO: underflow is not raised correctly, example in - downward rouding: fmaf(0x1p-120f, 0x1p-120f, 0x1p-149f) + underflow may not be raised correctly, example: + fmaf(0x1p-120f, 0x1p-120f, 0x1p-149f) */ +#if defined(FE_INEXACT) && defined(FE_UNDERFLOW) + if (e < 0x3ff-126 && e >= 0x3ff-149 && fetestexcept(FE_INEXACT)) { + feclearexcept(FE_INEXACT); + /* TODO: gcc and clang bug workaround */ + volatile float vz = z; + result = xy + vz; + if (fetestexcept(FE_INEXACT)) + feraiseexcept(FE_UNDERFLOW); + else + feraiseexcept(FE_INEXACT); + } +#endif z = result; return z; } @@ -68,8 +83,11 @@ float fmaf(float x, float y, float z) volatile double vxy = xy; /* XXX work around gcc CSE bug */ double adjusted_result = vxy + z; fesetround(FE_TONEAREST); - if (result == adjusted_result) - SET_LOW_WORD(adjusted_result, lr + 1); + if (result == adjusted_result) { + u.f = adjusted_result; + u.i++; + adjusted_result = u.f; + } z = adjusted_result; return z; } diff --git a/src/math/fmal.c b/src/math/fmal.c index c68db25..4506aac 100644 --- a/src/math/fmal.c +++ b/src/math/fmal.c @@ -264,12 +264,24 @@ long double fmal(long double x, long double y, long double z) /* * There is no need to worry about double rounding in directed * rounding modes. - * TODO: underflow is not raised correctly, example in downward rounding: + * But underflow may not be raised correctly, example in downward rounding: * fmal(0x1.0000000001p-16000L, 0x1.0000000001p-400L, -0x1p-16440L) */ + long double ret; +#if defined(FE_INEXACT) && defined(FE_UNDERFLOW) + int e = fetestexcept(FE_INEXACT); + feclearexcept(FE_INEXACT); +#endif fesetround(oround); adj = r.lo + xy.lo; - return scalbnl(r.hi + adj, spread); + ret = scalbnl(r.hi + adj, spread); +#if defined(FE_INEXACT) && defined(FE_UNDERFLOW) + if (ilogbl(ret) < -16382 && fetestexcept(FE_INEXACT)) + feraiseexcept(FE_UNDERFLOW); + else if (e) + feraiseexcept(FE_INEXACT); +#endif + return ret; } adj = add_adjusted(r.lo, xy.lo); diff --git a/src/math/j0f.c b/src/math/j0f.c index 4b0ee3b..45883dc 100644 --- a/src/math/j0f.c +++ b/src/math/j0f.c @@ -13,6 +13,7 @@ * ==================================================== */ +#define _GNU_SOURCE #include "libm.h" static float pzerof(float), qzerof(float); diff --git a/src/math/j1f.c b/src/math/j1f.c index 6abde34..58875af 100644 --- a/src/math/j1f.c +++ b/src/math/j1f.c @@ -13,6 +13,7 @@ * ==================================================== */ +#define _GNU_SOURCE #include "libm.h" static float ponef(float), qonef(float); diff --git a/src/math/lgamma_r.c b/src/math/lgamma_r.c index 82e296f..fff565d 100644 --- a/src/math/lgamma_r.c +++ b/src/math/lgamma_r.c @@ -82,7 +82,6 @@ #include "libc.h" static const double -two52= 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */ a0 = 7.72156649015328655494e-02, /* 0x3FB3C467, 0xE37DB0C8 */ a1 = 3.22467033424113591611e-01, /* 0x3FD4A34C, 0xC4A60FAD */ @@ -147,91 +146,62 @@ w4 = -5.95187557450339963135e-04, /* 0xBF4380CB, 0x8C0FE741 */ w5 = 8.36339918996282139126e-04, /* 0x3F4B67BA, 0x4CDAD5D1 */ w6 = -1.63092934096575273989e-03; /* 0xBF5AB89D, 0x0B9E43E4 */ +/* sin(pi*x) assuming x > 2^-100, if sin(pi*x)==0 the sign is arbitrary */ static double sin_pi(double x) { - double y,z; - int n,ix; + int n; - GET_HIGH_WORD(ix, x); - ix &= 0x7fffffff; + /* spurious inexact if odd int */ + x = 2.0*(x*0.5 - floor(x*0.5)); /* x mod 2.0 */ - if (ix < 0x3fd00000) - return __sin(pi*x, 0.0, 0); + n = (int)(x*4.0); + n = (n+1)/2; + x -= n*0.5f; + x *= pi; - y = -x; /* negative x is assumed */ - - /* - * argument reduction, make sure inexact flag not raised if input - * is an integer - */ - z = floor(y); - if (z != y) { /* inexact anyway */ - y *= 0.5; - y = 2.0*(y - floor(y)); /* y = |x| mod 2.0 */ - n = (int)(y*4.0); - } else { - if (ix >= 0x43400000) { - y = 0.0; /* y must be even */ - n = 0; - } else { - if (ix < 0x43300000) - z = y + two52; /* exact */ - GET_LOW_WORD(n, z); - n &= 1; - y = n; - n <<= 2; - } - } switch (n) { - case 0: y = __sin(pi*y, 0.0, 0); break; - case 1: - case 2: y = __cos(pi*(0.5-y), 0.0); break; - case 3: - case 4: y = __sin(pi*(1.0-y), 0.0, 0); break; - case 5: - case 6: y = -__cos(pi*(y-1.5), 0.0); break; - default: y = __sin(pi*(y-2.0), 0.0, 0); break; + default: /* case 4: */ + case 0: return __sin(x, 0.0, 0); + case 1: return __cos(x, 0.0); + case 2: return __sin(-x, 0.0, 0); + case 3: return -__cos(x, 0.0); } - return -y; } - double __lgamma_r(double x, int *signgamp) { - double t,y,z,nadj,p,p1,p2,p3,q,r,w; - int32_t hx; - int i,lx,ix; - - EXTRACT_WORDS(hx, lx, x); + union {double f; uint64_t i;} u = {x}; + double_t t,y,z,nadj,p,p1,p2,p3,q,r,w; + uint32_t ix; + int sign,i; /* purge off +-inf, NaN, +-0, tiny and negative arguments */ *signgamp = 1; - ix = hx & 0x7fffffff; + sign = u.i>>63; + ix = u.i>>32 & 0x7fffffff; if (ix >= 0x7ff00000) return x*x; - if ((ix|lx) == 0) - return 1.0/0.0; - if (ix < 0x3b900000) { /* |x|<2**-70, return -log(|x|) */ - if(hx < 0) { + if (ix < (0x3ff-70)<<20) { /* |x|<2**-70, return -log(|x|) */ + if(sign) { + x = -x; *signgamp = -1; - return -log(-x); } return -log(x); } - if (hx < 0) { - if (ix >= 0x43300000) /* |x|>=2**52, must be -integer */ - return 1.0/0.0; + if (sign) { + x = -x; t = sin_pi(x); if (t == 0.0) /* -integer */ - return 1.0/0.0; - nadj = log(pi/fabs(t*x)); - if (t < 0.0) + return 1.0/(x-x); + if (t > 0.0) *signgamp = -1; - x = -x; + else + t = -t; + nadj = log(pi/(t*x)); } /* purge off 1 and 2 */ - if (((ix - 0x3ff00000)|lx) == 0 || ((ix - 0x40000000)|lx) == 0) + if ((ix == 0x3ff00000 || ix == 0x40000000) && (uint32_t)u.i == 0) r = 0; /* for x < 2.0 */ else if (ix < 0x40000000) { @@ -306,7 +276,7 @@ double __lgamma_r(double x, int *signgamp) r = (x-0.5)*(t-1.0)+w; } else /* 2**58 <= x <= inf */ r = x*(log(x)-1.0); - if (hx < 0) + if (sign) r = nadj - r; return r; } diff --git a/src/math/lgammaf_r.c b/src/math/lgammaf_r.c index dc65bac..c5b43db 100644 --- a/src/math/lgammaf_r.c +++ b/src/math/lgammaf_r.c @@ -17,7 +17,6 @@ #include "libc.h" static const float -two23= 8.3886080000e+06, /* 0x4b000000 */ pi = 3.1415927410e+00, /* 0x40490fdb */ a0 = 7.7215664089e-02, /* 0x3d9e233f */ a1 = 3.2246702909e-01, /* 0x3ea51a66 */ @@ -82,87 +81,58 @@ w4 = -5.9518753551e-04, /* 0xba1c065c */ w5 = 8.3633989561e-04, /* 0x3a5b3dd2 */ w6 = -1.6309292987e-03; /* 0xbad5c4e8 */ -static float sin_pif(float x) +/* sin(pi*x) assuming x > 2^-100, if sin(pi*x)==0 the sign is arbitrary */ +static float sin_pi(float x) { - float y,z; - int n,ix; + double_t y; + int n; - GET_FLOAT_WORD(ix, x); - ix &= 0x7fffffff; + /* spurious inexact if odd int */ + x = 2*(x*0.5f - floorf(x*0.5f)); /* x mod 2.0 */ - if(ix < 0x3e800000) - return __sindf(pi*x); - - y = -x; /* negative x is assumed */ - - /* - * argument reduction, make sure inexact flag not raised if input - * is an integer - */ - z = floorf(y); - if (z != y) { /* inexact anyway */ - y *= 0.5f; - y = 2.0f*(y - floorf(y)); /* y = |x| mod 2.0 */ - n = (int)(y*4.0f); - } else { - if (ix >= 0x4b800000) { - y = 0.0f; /* y must be even */ - n = 0; - } else { - if (ix < 0x4b000000) - z = y + two23; /* exact */ - GET_FLOAT_WORD(n, z); - n &= 1; - y = n; - n <<= 2; - } - } + n = (int)(x*4); + n = (n+1)/2; + y = x - n*0.5f; + y *= 3.14159265358979323846; switch (n) { - case 0: y = __sindf(pi*y); break; - case 1: - case 2: y = __cosdf(pi*(0.5f - y)); break; - case 3: - case 4: y = __sindf(pi*(1.0f - y)); break; - case 5: - case 6: y = -__cosdf(pi*(y - 1.5f)); break; - default: y = __sindf(pi*(y - 2.0f)); break; + default: /* case 4: */ + case 0: return __sindf(y); + case 1: return __cosdf(y); + case 2: return __sindf(-y); + case 3: return -__cosdf(y); } - return -y; } - float __lgammaf_r(float x, int *signgamp) { + union {float f; uint32_t i;} u = {x}; float t,y,z,nadj,p,p1,p2,p3,q,r,w; - int32_t hx; - int i,ix; - - GET_FLOAT_WORD(hx, x); + uint32_t ix; + int i,sign; /* purge off +-inf, NaN, +-0, tiny and negative arguments */ *signgamp = 1; - ix = hx & 0x7fffffff; + sign = u.i>>31; + ix = u.i & 0x7fffffff; if (ix >= 0x7f800000) return x*x; - if (ix == 0) - return 1.0f/0.0f; if (ix < 0x35000000) { /* |x| < 2**-21, return -log(|x|) */ - if (hx < 0) { + if (sign) { *signgamp = -1; - return -logf(-x); + x = -x; } return -logf(x); } - if (hx < 0) { - if (ix >= 0x4b000000) /* |x| >= 2**23, must be -integer */ - return 1.0f/0.0f; - t = sin_pif(x); + if (sign) { + x = -x; + t = sin_pi(x); if (t == 0.0f) /* -integer */ - return 1.0f/0.0f; - nadj = logf(pi/fabsf(t*x)); - if (t < 0.0f) + return 1.0f/(x-x); + if (t > 0.0f) *signgamp = -1; - x = -x; + else + t = -t; + nadj = logf(pi/(t*x)); } /* purge off 1 and 2 */ @@ -241,7 +211,7 @@ float __lgammaf_r(float x, int *signgamp) r = (x-0.5f)*(t-1.0f)+w; } else /* 2**58 <= x <= inf */ r = x*(logf(x)-1.0f); - if (hx < 0) + if (sign) r = nadj - r; return r; } diff --git a/src/math/lgammal.c b/src/math/lgammal.c index cc4895e..55ec532 100644 --- a/src/math/lgammal.c +++ b/src/math/lgammal.c @@ -99,7 +99,6 @@ long double __lgammal_r(long double x, int *sg) #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 static const long double pi = 3.14159265358979323846264L, -two63 = 9.223372036854775808e18L, /* lgam(1+x) = 0.5 x + x a(x)/b(x) -0.268402099609375 <= x <= 0 @@ -201,61 +200,27 @@ w5 = 8.412723297322498080632E-4L, w6 = -1.880801938119376907179E-3L, w7 = 4.885026142432270781165E-3L; +/* sin(pi*x) assuming x > 2^-1000, if sin(pi*x)==0 the sign is arbitrary */ static long double sin_pi(long double x) { - union ldshape u = {x}; - uint32_t ix = (u.i.se & 0x7fffU)<<16 | u.i.m>>48; - long double y, z; int n; - if (ix < 0x3ffd8000) /* 0.25 */ - return sinl(pi * x); - y = -x; /* x is assume negative */ + /* spurious inexact if odd int */ + x *= 0.5; + x = 2.0*(x - floorl(x)); /* x mod 2.0 */ - /* - * argument reduction, make sure inexact flag not raised if input - * is an integer - */ - z = floorl(y); - if (z != y) { /* inexact anyway */ - y *= 0.5; - y = 2.0*(y - floorl(y));/* y = |x| mod 2.0 */ - n = (int) (y*4.0); - } else { - if (ix >= 0x403f8000) { /* 2^64 */ - y = 0.0; /* y must be even */ - n = 0; - } else { - if (ix < 0x403e8000) /* 2^63 */ - z = y + two63; /* exact */ - u.f = z; - n = u.i.m & 1; - y = n; - n <<= 2; - } - } + n = (int)(x*4.0); + n = (n+1)/2; + x -= n*0.5f; + x *= pi; switch (n) { - case 0: - y = sinl(pi * y); - break; - case 1: - case 2: - y = cosl(pi * (0.5 - y)); - break; - case 3: - case 4: - y = sinl(pi * (1.0 - y)); - break; - case 5: - case 6: - y = -cosl(pi * (y - 1.5)); - break; - default: - y = sinl(pi * (y - 2.0)); - break; + default: /* case 4: */ + case 0: return __sinl(x, 0.0, 0); + case 1: return __cosl(x, 0.0); + case 2: return __sinl(-x, 0.0, 0); + case 3: return -__cosl(x, 0.0); } - return -y; } long double __lgammal_r(long double x, int *sg) { @@ -267,31 +232,32 @@ long double __lgammal_r(long double x, int *sg) { *sg = 1; - /* purge off +-inf, NaN, +-0, and negative arguments */ + /* purge off +-inf, NaN, +-0, tiny and negative arguments */ if (ix >= 0x7fff0000) return x * x; - if (x == 0) { - *sg -= 2*sign; - return 1.0 / fabsl(x); - } if (ix < 0x3fc08000) { /* |x|<2**-63, return -log(|x|) */ if (sign) { *sg = -1; - return -logl(-x); + x = -x; } return -logl(x); } if (sign) { - t = sin_pi (x); + x = -x; + t = sin_pi(x); if (t == 0.0) - return 1.0 / fabsl(t); /* -integer */ - nadj = logl(pi / fabsl(t * x)); - if (t < 0.0) + return 1.0 / (x-x); /* -integer */ + if (t > 0.0) *sg = -1; - x = -x; + else + t = -t; + nadj = logl(pi / (t * x)); } - if (ix < 0x40008000) { /* x < 2.0 */ + /* purge off 1 and 2 (so the sign is ok with downward rounding) */ + if ((ix == 0x3fff8000 || ix == 0x40008000) && u.i.m == 0) { + r = 0; + } else if (ix < 0x40008000) { /* x < 2.0 */ if (ix <= 0x3ffee666) { /* 8.99993896484375e-1 */ /* lgamma(x) = lgamma(x+1) - log(x) */ r = -logl(x); @@ -341,12 +307,12 @@ long double __lgammal_r(long double x, int *sg) { } else if (ix < 0x40028000) { /* 8.0 */ /* x < 8.0 */ i = (int)x; - t = 0.0; y = x - (double)i; p = y * (s0 + y * (s1 + y * (s2 + y * (s3 + y * (s4 + y * (s5 + y * s6)))))); q = r0 + y * (r1 + y * (r2 + y * (r3 + y * (r4 + y * (r5 + y * (r6 + y)))))); r = 0.5 * y + p / q; - z = 1.0;/* lgamma(1+s) = log(s) + lgamma(s) */ + z = 1.0; + /* lgamma(1+s) = log(s) + lgamma(s) */ switch (i) { case 7: z *= (y + 6.0); /* FALLTHRU */ @@ -376,6 +342,7 @@ long double __lgammal_r(long double x, int *sg) { } #endif +#if (LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024) || (LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384) extern int __signgam; long double lgammal(long double x) @@ -384,3 +351,4 @@ long double lgammal(long double x) } weak_alias(__lgammal_r, lgammal_r); +#endif diff --git a/src/math/log.c b/src/math/log.c index 9805120..e61e113 100644 --- a/src/math/log.c +++ b/src/math/log.c @@ -10,7 +10,7 @@ * ==================================================== */ /* log(x) - * Return the logrithm of x + * Return the logarithm of x * * Method : * 1. Argument Reduction: find k and f such that @@ -60,12 +60,12 @@ * to produce the hexadecimal values shown. */ -#include "libm.h" +#include +#include static const double ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ -two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */ Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ @@ -76,63 +76,43 @@ Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ double log(double x) { - double hfsq,f,s,z,R,w,t1,t2,dk; - int32_t k,hx,i,j; - uint32_t lx; - - EXTRACT_WORDS(hx, lx, x); + union {double f; uint64_t i;} u = {x}; + double_t hfsq,f,s,z,R,w,t1,t2,dk; + uint32_t hx; + int k; + hx = u.i>>32; k = 0; - if (hx < 0x00100000) { /* x < 2**-1022 */ - if (((hx&0x7fffffff)|lx) == 0) - return -two54/0.0; /* log(+-0)=-inf */ - if (hx < 0) - return (x-x)/0.0; /* log(-#) = NaN */ - /* subnormal number, scale up x */ + if (hx < 0x00100000 || hx>>31) { + if (u.i<<1 == 0) + return -1/(x*x); /* log(+-0)=-inf */ + if (hx>>31) + return (x-x)/0.0; /* log(-#) = NaN */ + /* subnormal number, scale x up */ k -= 54; - x *= two54; - GET_HIGH_WORD(hx,x); - } - if (hx >= 0x7ff00000) - return x+x; - k += (hx>>20) - 1023; - hx &= 0x000fffff; - i = (hx+0x95f64)&0x100000; - SET_HIGH_WORD(x, hx|(i^0x3ff00000)); /* normalize x or x/2 */ - k += i>>20; + x *= 0x1p54; + u.f = x; + hx = u.i>>32; + } else if (hx >= 0x7ff00000) { + return x; + } else if (hx == 0x3ff00000 && u.i<<32 == 0) + return 0; + + /* reduce x into [sqrt(2)/2, sqrt(2)] */ + hx += 0x3ff00000 - 0x3fe6a09e; + k += (int)(hx>>20) - 0x3ff; + hx = (hx&0x000fffff) + 0x3fe6a09e; + u.i = (uint64_t)hx<<32 | (u.i&0xffffffff); + x = u.f; + f = x - 1.0; - if ((0x000fffff&(2+hx)) < 3) { /* -2**-20 <= f < 2**-20 */ - if (f == 0.0) { - if (k == 0) { - return 0.0; - } - dk = (double)k; - return dk*ln2_hi + dk*ln2_lo; - } - R = f*f*(0.5-0.33333333333333333*f); - if (k == 0) - return f - R; - dk = (double)k; - return dk*ln2_hi - ((R-dk*ln2_lo)-f); - } + hfsq = 0.5*f*f; s = f/(2.0+f); - dk = (double)k; z = s*s; - i = hx - 0x6147a; w = z*z; - j = 0x6b851 - hx; t1 = w*(Lg2+w*(Lg4+w*Lg6)); t2 = z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); - i |= j; R = t2 + t1; - if (i > 0) { - hfsq = 0.5*f*f; - if (k == 0) - return f - (hfsq-s*(hfsq+R)); - return dk*ln2_hi - ((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f); - } else { - if (k == 0) - return f - s*(f-R); - return dk*ln2_hi - ((s*(f-R)-dk*ln2_lo)-f); - } + dk = k; + return s*(hfsq+R) + dk*ln2_lo - hfsq + f + dk*ln2_hi; } diff --git a/src/math/log10.c b/src/math/log10.c index ed65d9b..8102687 100644 --- a/src/math/log10.c +++ b/src/math/log10.c @@ -10,72 +10,91 @@ * ==================================================== */ /* - * Return the base 10 logarithm of x. See e_log.c and k_log.h for most - * comments. + * Return the base 10 logarithm of x. See log.c for most comments. * - * log10(x) = (f - 0.5*f*f + k_log1p(f)) / ln10 + k * log10(2) - * in not-quite-routine extra precision. + * Reduce x to 2^k (1+f) and calculate r = log(1+f) - f + f*f/2 + * as in log.c, then combine and scale in extra precision: + * log10(x) = (f - f*f/2 + r)/log(10) + k*log10(2) */ -#include "libm.h" -#include "__log1p.h" +#include +#include static const double -two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ ivln10hi = 4.34294481878168880939e-01, /* 0x3fdbcb7b, 0x15200000 */ ivln10lo = 2.50829467116452752298e-11, /* 0x3dbb9438, 0xca9aadd5 */ log10_2hi = 3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */ -log10_2lo = 3.69423907715893078616e-13; /* 0x3D59FEF3, 0x11F12B36 */ +log10_2lo = 3.69423907715893078616e-13, /* 0x3D59FEF3, 0x11F12B36 */ +Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ +Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ +Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ +Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ +Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ +Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ +Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ double log10(double x) { - double f,hfsq,hi,lo,r,val_hi,val_lo,w,y,y2; - int32_t i,k,hx; - uint32_t lx; - - EXTRACT_WORDS(hx, lx, x); + union {double f; uint64_t i;} u = {x}; + double_t hfsq,f,s,z,R,w,t1,t2,dk,y,hi,lo,val_hi,val_lo; + uint32_t hx; + int k; + hx = u.i>>32; k = 0; - if (hx < 0x00100000) { /* x < 2**-1022 */ - if (((hx&0x7fffffff)|lx) == 0) - return -two54/0.0; /* log(+-0)=-inf */ - if (hx<0) - return (x-x)/0.0; /* log(-#) = NaN */ - /* subnormal number, scale up x */ + if (hx < 0x00100000 || hx>>31) { + if (u.i<<1 == 0) + return -1/(x*x); /* log(+-0)=-inf */ + if (hx>>31) + return (x-x)/0.0; /* log(-#) = NaN */ + /* subnormal number, scale x up */ k -= 54; - x *= two54; - GET_HIGH_WORD(hx, x); - } - if (hx >= 0x7ff00000) - return x+x; - if (hx == 0x3ff00000 && lx == 0) - return 0.0; /* log(1) = +0 */ - k += (hx>>20) - 1023; - hx &= 0x000fffff; - i = (hx+0x95f64)&0x100000; - SET_HIGH_WORD(x, hx|(i^0x3ff00000)); /* normalize x or x/2 */ - k += i>>20; - y = (double)k; + x *= 0x1p54; + u.f = x; + hx = u.i>>32; + } else if (hx >= 0x7ff00000) { + return x; + } else if (hx == 0x3ff00000 && u.i<<32 == 0) + return 0; + + /* reduce x into [sqrt(2)/2, sqrt(2)] */ + hx += 0x3ff00000 - 0x3fe6a09e; + k += (int)(hx>>20) - 0x3ff; + hx = (hx&0x000fffff) + 0x3fe6a09e; + u.i = (uint64_t)hx<<32 | (u.i&0xffffffff); + x = u.f; + f = x - 1.0; hfsq = 0.5*f*f; - r = __log1p(f); + s = f/(2.0+f); + z = s*s; + w = z*z; + t1 = w*(Lg2+w*(Lg4+w*Lg6)); + t2 = z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); + R = t2 + t1; /* See log2.c for details. */ + /* hi+lo = f - hfsq + s*(hfsq+R) ~ log(1+f) */ hi = f - hfsq; - SET_LOW_WORD(hi, 0); - lo = (f - hi) - hfsq + r; + u.f = hi; + u.i &= (uint64_t)-1<<32; + hi = u.f; + lo = f - hi - hfsq + s*(hfsq+R); + + /* val_hi+val_lo ~ log10(1+f) + k*log10(2) */ val_hi = hi*ivln10hi; - y2 = y*log10_2hi; - val_lo = y*log10_2lo + (lo+hi)*ivln10lo + lo*ivln10hi; + dk = k; + y = dk*log10_2hi; + val_lo = dk*log10_2lo + (lo+hi)*ivln10lo + lo*ivln10hi; /* - * Extra precision in for adding y*log10_2hi is not strictly needed + * Extra precision in for adding y is not strictly needed * since there is no very large cancellation near x = sqrt(2) or * x = 1/sqrt(2), but we do it anyway since it costs little on CPUs * with some parallelism and it reduces the error for many args. */ - w = y2 + val_hi; - val_lo += (y2 - w) + val_hi; + w = y + val_hi; + val_lo += (y - w) + val_hi; val_hi = w; return val_lo + val_hi; diff --git a/src/math/log10f.c b/src/math/log10f.c index e10749b..9ca2f01 100644 --- a/src/math/log10f.c +++ b/src/math/log10f.c @@ -13,57 +13,65 @@ * See comments in log10.c. */ -#include "libm.h" -#include "__log1pf.h" +#include +#include static const float -two25 = 3.3554432000e+07, /* 0x4c000000 */ ivln10hi = 4.3432617188e-01, /* 0x3ede6000 */ ivln10lo = -3.1689971365e-05, /* 0xb804ead9 */ log10_2hi = 3.0102920532e-01, /* 0x3e9a2080 */ -log10_2lo = 7.9034151668e-07; /* 0x355427db */ +log10_2lo = 7.9034151668e-07, /* 0x355427db */ +/* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */ +Lg1 = 0xaaaaaa.0p-24, /* 0.66666662693 */ +Lg2 = 0xccce13.0p-25, /* 0.40000972152 */ +Lg3 = 0x91e9ee.0p-25, /* 0.28498786688 */ +Lg4 = 0xf89e26.0p-26; /* 0.24279078841 */ float log10f(float x) { - float f,hfsq,hi,lo,r,y; - int32_t i,k,hx; - - GET_FLOAT_WORD(hx, x); + union {float f; uint32_t i;} u = {x}; + float_t hfsq,f,s,z,R,w,t1,t2,dk,hi,lo; + uint32_t ix; + int k; + ix = u.i; k = 0; - if (hx < 0x00800000) { /* x < 2**-126 */ - if ((hx&0x7fffffff) == 0) - return -two25/0.0f; /* log(+-0)=-inf */ - if (hx < 0) - return (x-x)/0.0f; /* log(-#) = NaN */ + if (ix < 0x00800000 || ix>>31) { /* x < 2**-126 */ + if (ix<<1 == 0) + return -1/(x*x); /* log(+-0)=-inf */ + if (ix>>31) + return (x-x)/0.0f; /* log(-#) = NaN */ /* subnormal number, scale up x */ k -= 25; - x *= two25; - GET_FLOAT_WORD(hx, x); - } - if (hx >= 0x7f800000) - return x+x; - if (hx == 0x3f800000) - return 0.0f; /* log(1) = +0 */ - k += (hx>>23) - 127; - hx &= 0x007fffff; - i = (hx+(0x4afb0d))&0x800000; - SET_FLOAT_WORD(x, hx|(i^0x3f800000)); /* normalize x or x/2 */ - k += i>>23; - y = (float)k; + x *= 0x1p25f; + u.f = x; + ix = u.i; + } else if (ix >= 0x7f800000) { + return x; + } else if (ix == 0x3f800000) + return 0; + + /* reduce x into [sqrt(2)/2, sqrt(2)] */ + ix += 0x3f800000 - 0x3f3504f3; + k += (int)(ix>>23) - 0x7f; + ix = (ix&0x007fffff) + 0x3f3504f3; + u.i = ix; + x = u.f; + f = x - 1.0f; - hfsq = 0.5f * f * f; - r = __log1pf(f); + s = f/(2.0f + f); + z = s*s; + w = z*z; + t1= w*(Lg2+w*Lg4); + t2= z*(Lg1+w*Lg3); + R = t2 + t1; + hfsq = 0.5f*f*f; -// FIXME -// /* See log2f.c and log2.c for details. */ -// if (sizeof(float_t) > sizeof(float)) -// return (r - hfsq + f) * ((float_t)ivln10lo + ivln10hi) + -// y * ((float_t)log10_2lo + log10_2hi); hi = f - hfsq; - GET_FLOAT_WORD(hx, hi); - SET_FLOAT_WORD(hi, hx&0xfffff000); - lo = (f - hi) - hfsq + r; - return y*log10_2lo + (lo+hi)*ivln10lo + lo*ivln10hi + - hi*ivln10hi + y*log10_2hi; + u.f = hi; + u.i &= 0xfffff000; + hi = u.f; + lo = f - hi - hfsq + s*(hfsq+R); + dk = k; + return dk*log10_2lo + (lo+hi)*ivln10lo + lo*ivln10hi + hi*ivln10hi + dk*log10_2hi; } diff --git a/src/math/log10l.c b/src/math/log10l.c index f0eeeaf..c7aacf9 100644 --- a/src/math/log10l.c +++ b/src/math/log10l.c @@ -117,16 +117,15 @@ static const long double S[4] = { long double log10l(long double x) { - long double y; - volatile long double z; + long double y, z; int e; if (isnan(x)) return x; if(x <= 0.0) { if(x == 0.0) - return -1.0 / (x - x); - return (x - x) / (x - x); + return -1.0 / (x*x); + return (x - x) / 0.0; } if (x == INFINITY) return INFINITY; diff --git a/src/math/log1p.c b/src/math/log1p.c index a71ac42..0097134 100644 --- a/src/math/log1p.c +++ b/src/math/log1p.c @@ -10,6 +10,7 @@ * ==================================================== */ /* double log1p(double x) + * Return the natural logarithm of 1+x. * * Method : * 1. Argument Reduction: find k and f such that @@ -23,31 +24,9 @@ * and add back the correction term c/u. * (Note: when x > 2**53, one can simply return log(x)) * - * 2. Approximation of log1p(f). - * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) - * = 2s + 2/3 s**3 + 2/5 s**5 + ....., - * = 2s + s*R - * We use a special Reme algorithm on [0,0.1716] to generate - * a polynomial of degree 14 to approximate R The maximum error - * of this polynomial approximation is bounded by 2**-58.45. In - * other words, - * 2 4 6 8 10 12 14 - * R(z) ~ Lp1*s +Lp2*s +Lp3*s +Lp4*s +Lp5*s +Lp6*s +Lp7*s - * (the values of Lp1 to Lp7 are listed in the program) - * and - * | 2 14 | -58.45 - * | Lp1*s +...+Lp7*s - R(z) | <= 2 - * | | - * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. - * In order to guarantee error in log below 1ulp, we compute log - * by - * log1p(f) = f - (hfsq - s*(hfsq+R)). + * 2. Approximation of log(1+f): See log.c * - * 3. Finally, log1p(x) = k*ln2 + log1p(f). - * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) - * Here ln2 is split into two floating point number: - * ln2_hi + ln2_lo, - * where n*ln2_hi is always exact for |n| < 2000. + * 3. Finally, log1p(x) = k*ln2 + log(1+f) + c/u. See log.c * * Special cases: * log1p(x) is NaN with signal if x < -1 (including -INF) ; @@ -79,94 +58,65 @@ static const double ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ -two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */ -Lp1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ -Lp2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ -Lp3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ -Lp4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ -Lp5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ -Lp6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ -Lp7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ +Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ +Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ +Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ +Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ +Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ +Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ +Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ double log1p(double x) { - double hfsq,f,c,s,z,R,u; - int32_t k,hx,hu,ax; - - GET_HIGH_WORD(hx, x); - ax = hx & 0x7fffffff; + union {double f; uint64_t i;} u = {x}; + double_t hfsq,f,c,s,z,R,w,t1,t2,dk; + uint32_t hx,hu; + int k; + hx = u.i>>32; k = 1; - if (hx < 0x3FDA827A) { /* 1+x < sqrt(2)+ */ - if (ax >= 0x3ff00000) { /* x <= -1.0 */ - if (x == -1.0) - return -two54/0.0; /* log1p(-1)=+inf */ - return (x-x)/(x-x); /* log1p(x<-1)=NaN */ + if (hx < 0x3fda827a || hx>>31) { /* 1+x < sqrt(2)+ */ + if (hx >= 0xbff00000) { /* x <= -1.0 */ + if (x == -1) + return x/0.0; /* log1p(-1) = -inf */ + return (x-x)/0.0; /* log1p(x<-1) = NaN */ } - if (ax < 0x3e200000) { /* |x| < 2**-29 */ - /* if 0x1p-1022 <= |x| < 0x1p-54, avoid raising underflow */ - if (ax < 0x3c900000 && ax >= 0x00100000) - return x; -#if FLT_EVAL_METHOD != 0 - FORCE_EVAL((float)x); -#endif - return x - x*x*0.5; + if (hx<<1 < 0x3ca00000<<1) { /* |x| < 2**-53 */ + /* underflow if subnormal */ + if ((hx&0x7ff00000) == 0) + FORCE_EVAL((float)x); + return x; } - if (hx > 0 || hx <= (int32_t)0xbfd2bec4) { /* sqrt(2)/2- <= 1+x < sqrt(2)+ */ + if (hx <= 0xbfd2bec4) { /* sqrt(2)/2- <= 1+x < sqrt(2)+ */ k = 0; + c = 0; f = x; - hu = 1; } - } - if (hx >= 0x7ff00000) - return x+x; - if (k != 0) { - if (hx < 0x43400000) { - u = 1 + x; - GET_HIGH_WORD(hu, u); - k = (hu>>20) - 1023; - c = k > 0 ? 1.0-(u-x) : x-(u-1.0); /* correction term */ - c /= u; - } else { - u = x; - GET_HIGH_WORD(hu,u); - k = (hu>>20) - 1023; + } else if (hx >= 0x7ff00000) + return x; + if (k) { + u.f = 1 + x; + hu = u.i>>32; + hu += 0x3ff00000 - 0x3fe6a09e; + k = (int)(hu>>20) - 0x3ff; + /* correction term ~ log(1+x)-log(u), avoid underflow in c/u */ + if (k < 54) { + c = k >= 2 ? 1-(u.f-x) : x-(u.f-1); + c /= u.f; + } else c = 0; - } - hu &= 0x000fffff; - /* - * The approximation to sqrt(2) used in thresholds is not - * critical. However, the ones used above must give less - * strict bounds than the one here so that the k==0 case is - * never reached from here, since here we have committed to - * using the correction term but don't use it if k==0. - */ - if (hu < 0x6a09e) { /* u ~< sqrt(2) */ - SET_HIGH_WORD(u, hu|0x3ff00000); /* normalize u */ - } else { - k += 1; - SET_HIGH_WORD(u, hu|0x3fe00000); /* normalize u/2 */ - hu = (0x00100000-hu)>>2; - } - f = u - 1.0; + /* reduce u into [sqrt(2)/2, sqrt(2)] */ + hu = (hu&0x000fffff) + 0x3fe6a09e; + u.i = (uint64_t)hu<<32 | (u.i&0xffffffff); + f = u.f - 1; } hfsq = 0.5*f*f; - if (hu == 0) { /* |f| < 2**-20 */ - if (f == 0.0) { - if(k == 0) - return 0.0; - c += k*ln2_lo; - return k*ln2_hi + c; - } - R = hfsq*(1.0 - 0.66666666666666666*f); - if (k == 0) - return f - R; - return k*ln2_hi - ((R-(k*ln2_lo+c))-f); - } s = f/(2.0+f); z = s*s; - R = z*(Lp1+z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7)))))); - if (k == 0) - return f - (hfsq-s*(hfsq+R)); - return k*ln2_hi - ((hfsq-(s*(hfsq+R)+(k*ln2_lo+c)))-f); + w = z*z; + t1 = w*(Lg2+w*(Lg4+w*Lg6)); + t2 = z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); + R = t2 + t1; + dk = k; + return s*(hfsq+R) + (dk*ln2_lo+c) - hfsq + f + dk*ln2_hi; } diff --git a/src/math/log1pf.c b/src/math/log1pf.c index e6940d2..23985c3 100644 --- a/src/math/log1pf.c +++ b/src/math/log1pf.c @@ -1,8 +1,5 @@ /* origin: FreeBSD /usr/src/lib/msun/src/s_log1pf.c */ /* - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ -/* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * @@ -18,95 +15,63 @@ static const float ln2_hi = 6.9313812256e-01, /* 0x3f317180 */ ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */ -two25 = 3.355443200e+07, /* 0x4c000000 */ -Lp1 = 6.6666668653e-01, /* 3F2AAAAB */ -Lp2 = 4.0000000596e-01, /* 3ECCCCCD */ -Lp3 = 2.8571429849e-01, /* 3E924925 */ -Lp4 = 2.2222198546e-01, /* 3E638E29 */ -Lp5 = 1.8183572590e-01, /* 3E3A3325 */ -Lp6 = 1.5313838422e-01, /* 3E1CD04F */ -Lp7 = 1.4798198640e-01; /* 3E178897 */ +/* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */ +Lg1 = 0xaaaaaa.0p-24, /* 0.66666662693 */ +Lg2 = 0xccce13.0p-25, /* 0.40000972152 */ +Lg3 = 0x91e9ee.0p-25, /* 0.28498786688 */ +Lg4 = 0xf89e26.0p-26; /* 0.24279078841 */ float log1pf(float x) { - float hfsq,f,c,s,z,R,u; - int32_t k,hx,hu,ax; - - GET_FLOAT_WORD(hx, x); - ax = hx & 0x7fffffff; + union {float f; uint32_t i;} u = {x}; + float_t hfsq,f,c,s,z,R,w,t1,t2,dk; + uint32_t ix,iu; + int k; + ix = u.i; k = 1; - if (hx < 0x3ed413d0) { /* 1+x < sqrt(2)+ */ - if (ax >= 0x3f800000) { /* x <= -1.0 */ - if (x == -1.0f) - return -two25/0.0f; /* log1p(-1)=+inf */ - return (x-x)/(x-x); /* log1p(x<-1)=NaN */ + if (ix < 0x3ed413d0 || ix>>31) { /* 1+x < sqrt(2)+ */ + if (ix >= 0xbf800000) { /* x <= -1.0 */ + if (x == -1) + return x/0.0f; /* log1p(-1)=+inf */ + return (x-x)/0.0f; /* log1p(x<-1)=NaN */ } - if (ax < 0x38000000) { /* |x| < 2**-15 */ - /* if 0x1p-126 <= |x| < 0x1p-24, avoid raising underflow */ - if (ax < 0x33800000 && ax >= 0x00800000) - return x; -#if FLT_EVAL_METHOD != 0 - FORCE_EVAL(x*x); -#endif - return x - x*x*0.5f; + if (ix<<1 < 0x33800000<<1) { /* |x| < 2**-24 */ + /* underflow if subnormal */ + if ((ix&0x7f800000) == 0) + FORCE_EVAL(x*x); + return x; } - if (hx > 0 || hx <= (int32_t)0xbe95f619) { /* sqrt(2)/2- <= 1+x < sqrt(2)+ */ + if (ix <= 0xbe95f619) { /* sqrt(2)/2- <= 1+x < sqrt(2)+ */ k = 0; + c = 0; f = x; - hu = 1; } - } - if (hx >= 0x7f800000) - return x+x; - if (k != 0) { - if (hx < 0x5a000000) { - u = 1 + x; - GET_FLOAT_WORD(hu, u); - k = (hu>>23) - 127; - /* correction term */ - c = k > 0 ? 1.0f-(u-x) : x-(u-1.0f); - c /= u; - } else { - u = x; - GET_FLOAT_WORD(hu,u); - k = (hu>>23) - 127; + } else if (ix >= 0x7f800000) + return x; + if (k) { + u.f = 1 + x; + iu = u.i; + iu += 0x3f800000 - 0x3f3504f3; + k = (int)(iu>>23) - 0x7f; + /* correction term ~ log(1+x)-log(u), avoid underflow in c/u */ + if (k < 25) { + c = k >= 2 ? 1-(u.f-x) : x-(u.f-1); + c /= u.f; + } else c = 0; - } - hu &= 0x007fffff; - /* - * The approximation to sqrt(2) used in thresholds is not - * critical. However, the ones used above must give less - * strict bounds than the one here so that the k==0 case is - * never reached from here, since here we have committed to - * using the correction term but don't use it if k==0. - */ - if (hu < 0x3504f4) { /* u < sqrt(2) */ - SET_FLOAT_WORD(u, hu|0x3f800000); /* normalize u */ - } else { - k += 1; - SET_FLOAT_WORD(u, hu|0x3f000000); /* normalize u/2 */ - hu = (0x00800000-hu)>>2; - } - f = u - 1.0f; - } - hfsq = 0.5f * f * f; - if (hu == 0) { /* |f| < 2**-20 */ - if (f == 0.0f) { - if (k == 0) - return 0.0f; - c += k*ln2_lo; - return k*ln2_hi+c; - } - R = hfsq*(1.0f - 0.66666666666666666f * f); - if (k == 0) - return f - R; - return k*ln2_hi - ((R-(k*ln2_lo+c))-f); + /* reduce u into [sqrt(2)/2, sqrt(2)] */ + iu = (iu&0x007fffff) + 0x3f3504f3; + u.i = iu; + f = u.f - 1; } s = f/(2.0f + f); z = s*s; - R = z*(Lp1+z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7)))))); - if (k == 0) - return f - (hfsq-s*(hfsq+R)); - return k*ln2_hi - ((hfsq-(s*(hfsq+R)+(k*ln2_lo+c)))-f); + w = z*z; + t1= w*(Lg2+w*Lg4); + t2= z*(Lg1+w*Lg3); + R = t2 + t1; + hfsq = 0.5f*f*f; + dk = k; + return s*(hfsq+R) + (dk*ln2_lo+c) - hfsq + f + dk*ln2_hi; } diff --git a/src/math/log1pl.c b/src/math/log1pl.c index edb48df..37da46d 100644 --- a/src/math/log1pl.c +++ b/src/math/log1pl.c @@ -118,7 +118,7 @@ long double log1pl(long double xm1) /* Test for domain errors. */ if (x <= 0.0) { if (x == 0.0) - return -1/x; /* -inf with divbyzero */ + return -1/(x*x); /* -inf with divbyzero */ return 0/0.0f; /* nan with invalid */ } diff --git a/src/math/log2.c b/src/math/log2.c index 1974215..0aafad4 100644 --- a/src/math/log2.c +++ b/src/math/log2.c @@ -10,55 +10,66 @@ * ==================================================== */ /* - * Return the base 2 logarithm of x. See log.c and __log1p.h for most - * comments. + * Return the base 2 logarithm of x. See log.c for most comments. * - * This reduces x to {k, 1+f} exactly as in e_log.c, then calls the kernel, - * then does the combining and scaling steps - * log2(x) = (f - 0.5*f*f + k_log1p(f)) / ln2 + k - * in not-quite-routine extra precision. + * Reduce x to 2^k (1+f) and calculate r = log(1+f) - f + f*f/2 + * as in log.c, then combine and scale in extra precision: + * log2(x) = (f - f*f/2 + r)/log(2) + k */ -#include "libm.h" -#include "__log1p.h" +#include +#include static const double -two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ ivln2hi = 1.44269504072144627571e+00, /* 0x3ff71547, 0x65200000 */ -ivln2lo = 1.67517131648865118353e-10; /* 0x3de705fc, 0x2eefa200 */ +ivln2lo = 1.67517131648865118353e-10, /* 0x3de705fc, 0x2eefa200 */ +Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ +Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ +Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ +Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ +Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ +Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ +Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ double log2(double x) { - double f,hfsq,hi,lo,r,val_hi,val_lo,w,y; - int32_t i,k,hx; - uint32_t lx; - - EXTRACT_WORDS(hx, lx, x); + union {double f; uint64_t i;} u = {x}; + double_t hfsq,f,s,z,R,w,t1,t2,y,hi,lo,val_hi,val_lo; + uint32_t hx; + int k; + hx = u.i>>32; k = 0; - if (hx < 0x00100000) { /* x < 2**-1022 */ - if (((hx&0x7fffffff)|lx) == 0) - return -two54/0.0; /* log(+-0)=-inf */ - if (hx < 0) - return (x-x)/0.0; /* log(-#) = NaN */ - /* subnormal number, scale up x */ + if (hx < 0x00100000 || hx>>31) { + if (u.i<<1 == 0) + return -1/(x*x); /* log(+-0)=-inf */ + if (hx>>31) + return (x-x)/0.0; /* log(-#) = NaN */ + /* subnormal number, scale x up */ k -= 54; - x *= two54; - GET_HIGH_WORD(hx, x); - } - if (hx >= 0x7ff00000) - return x+x; - if (hx == 0x3ff00000 && lx == 0) - return 0.0; /* log(1) = +0 */ - k += (hx>>20) - 1023; - hx &= 0x000fffff; - i = (hx+0x95f64) & 0x100000; - SET_HIGH_WORD(x, hx|(i^0x3ff00000)); /* normalize x or x/2 */ - k += i>>20; - y = (double)k; + x *= 0x1p54; + u.f = x; + hx = u.i>>32; + } else if (hx >= 0x7ff00000) { + return x; + } else if (hx == 0x3ff00000 && u.i<<32 == 0) + return 0; + + /* reduce x into [sqrt(2)/2, sqrt(2)] */ + hx += 0x3ff00000 - 0x3fe6a09e; + k += (int)(hx>>20) - 0x3ff; + hx = (hx&0x000fffff) + 0x3fe6a09e; + u.i = (uint64_t)hx<<32 | (u.i&0xffffffff); + x = u.f; + f = x - 1.0; hfsq = 0.5*f*f; - r = __log1p(f); + s = f/(2.0+f); + z = s*s; + w = z*z; + t1 = w*(Lg2+w*(Lg4+w*Lg6)); + t2 = z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); + R = t2 + t1; /* * f-hfsq must (for args near 1) be evaluated in extra precision @@ -90,13 +101,19 @@ double log2(double x) * The multi-precision calculations for the multiplications are * routine. */ + + /* hi+lo = f - hfsq + s*(hfsq+R) ~ log(1+f) */ hi = f - hfsq; - SET_LOW_WORD(hi, 0); - lo = (f - hi) - hfsq + r; + u.f = hi; + u.i &= (uint64_t)-1<<32; + hi = u.f; + lo = f - hi - hfsq + s*(hfsq+R); + val_hi = hi*ivln2hi; val_lo = (lo+hi)*ivln2lo + lo*ivln2hi; /* spadd(val_hi, val_lo, y), except for not using double_t: */ + y = k; w = y + val_hi; val_lo += (y - w) + val_hi; val_hi = w; diff --git a/src/math/log2f.c b/src/math/log2f.c index e0d6a9e..b3e305f 100644 --- a/src/math/log2f.c +++ b/src/math/log2f.c @@ -13,67 +13,62 @@ * See comments in log2.c. */ -#include "libm.h" -#include "__log1pf.h" +#include +#include static const float -two25 = 3.3554432000e+07, /* 0x4c000000 */ ivln2hi = 1.4428710938e+00, /* 0x3fb8b000 */ -ivln2lo = -1.7605285393e-04; /* 0xb9389ad4 */ +ivln2lo = -1.7605285393e-04, /* 0xb9389ad4 */ +/* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */ +Lg1 = 0xaaaaaa.0p-24, /* 0.66666662693 */ +Lg2 = 0xccce13.0p-25, /* 0.40000972152 */ +Lg3 = 0x91e9ee.0p-25, /* 0.28498786688 */ +Lg4 = 0xf89e26.0p-26; /* 0.24279078841 */ float log2f(float x) { - float f,hfsq,hi,lo,r,y; - int32_t i,k,hx; - - GET_FLOAT_WORD(hx, x); + union {float f; uint32_t i;} u = {x}; + float_t hfsq,f,s,z,R,w,t1,t2,hi,lo; + uint32_t ix; + int k; + ix = u.i; k = 0; - if (hx < 0x00800000) { /* x < 2**-126 */ - if ((hx&0x7fffffff) == 0) - return -two25/0.0f; /* log(+-0)=-inf */ - if (hx < 0) - return (x-x)/0.0f; /* log(-#) = NaN */ + if (ix < 0x00800000 || ix>>31) { /* x < 2**-126 */ + if (ix<<1 == 0) + return -1/(x*x); /* log(+-0)=-inf */ + if (ix>>31) + return (x-x)/0.0f; /* log(-#) = NaN */ /* subnormal number, scale up x */ k -= 25; - x *= two25; - GET_FLOAT_WORD(hx, x); - } - if (hx >= 0x7f800000) - return x+x; - if (hx == 0x3f800000) - return 0.0f; /* log(1) = +0 */ - k += (hx>>23) - 127; - hx &= 0x007fffff; - i = (hx+(0x4afb0d))&0x800000; - SET_FLOAT_WORD(x, hx|(i^0x3f800000)); /* normalize x or x/2 */ - k += i>>23; - y = (float)k; - f = x - 1.0f; - hfsq = 0.5f * f * f; - r = __log1pf(f); + x *= 0x1p25f; + u.f = x; + ix = u.i; + } else if (ix >= 0x7f800000) { + return x; + } else if (ix == 0x3f800000) + return 0; - /* - * We no longer need to avoid falling into the multi-precision - * calculations due to compiler bugs breaking Dekker's theorem. - * Keep avoiding this as an optimization. See log2.c for more - * details (some details are here only because the optimization - * is not yet available in double precision). - * - * Another compiler bug turned up. With gcc on i386, - * (ivln2lo + ivln2hi) would be evaluated in float precision - * despite runtime evaluations using double precision. So we - * must cast one of its terms to float_t. This makes the whole - * expression have type float_t, so return is forced to waste - * time clobbering its extra precision. - */ -// FIXME -// if (sizeof(float_t) > sizeof(float)) -// return (r - hfsq + f) * ((float_t)ivln2lo + ivln2hi) + y; + /* reduce x into [sqrt(2)/2, sqrt(2)] */ + ix += 0x3f800000 - 0x3f3504f3; + k += (int)(ix>>23) - 0x7f; + ix = (ix&0x007fffff) + 0x3f3504f3; + u.i = ix; + x = u.f; + + f = x - 1.0f; + s = f/(2.0f + f); + z = s*s; + w = z*z; + t1= w*(Lg2+w*Lg4); + t2= z*(Lg1+w*Lg3); + R = t2 + t1; + hfsq = 0.5f*f*f; hi = f - hfsq; - GET_FLOAT_WORD(hx,hi); - SET_FLOAT_WORD(hi,hx&0xfffff000); - lo = (f - hi) - hfsq + r; - return (lo+hi)*ivln2lo + lo*ivln2hi + hi*ivln2hi + y; + u.f = hi; + u.i &= 0xfffff000; + hi = u.f; + lo = f - hi - hfsq + s*(hfsq+R); + return (lo+hi)*ivln2lo + lo*ivln2hi + hi*ivln2hi + k; } diff --git a/src/math/log2l.c b/src/math/log2l.c index 345b395..d00531d 100644 --- a/src/math/log2l.c +++ b/src/math/log2l.c @@ -117,7 +117,7 @@ long double log2l(long double x) return x; if (x <= 0.0) { if (x == 0.0) - return -1/(x+0); /* -inf with divbyzero */ + return -1/(x*x); /* -inf with divbyzero */ return 0/0.0f; /* nan with invalid */ } diff --git a/src/math/logf.c b/src/math/logf.c index c7f7dbe..52230a1 100644 --- a/src/math/logf.c +++ b/src/math/logf.c @@ -13,12 +13,12 @@ * ==================================================== */ -#include "libm.h" +#include +#include static const float ln2_hi = 6.9313812256e-01, /* 0x3f317180 */ ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */ -two25 = 3.355443200e+07, /* 0x4c000000 */ /* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */ Lg1 = 0xaaaaaa.0p-24, /* 0.66666662693 */ Lg2 = 0xccce13.0p-25, /* 0.40000972152 */ @@ -27,61 +27,43 @@ Lg4 = 0xf89e26.0p-26; /* 0.24279078841 */ float logf(float x) { - float hfsq,f,s,z,R,w,t1,t2,dk; - int32_t k,ix,i,j; - - GET_FLOAT_WORD(ix, x); + union {float f; uint32_t i;} u = {x}; + float_t hfsq,f,s,z,R,w,t1,t2,dk; + uint32_t ix; + int k; + ix = u.i; k = 0; - if (ix < 0x00800000) { /* x < 2**-126 */ - if ((ix & 0x7fffffff) == 0) - return -two25/0.0f; /* log(+-0)=-inf */ - if (ix < 0) - return (x-x)/0.0f; /* log(-#) = NaN */ + if (ix < 0x00800000 || ix>>31) { /* x < 2**-126 */ + if (ix<<1 == 0) + return -1/(x*x); /* log(+-0)=-inf */ + if (ix>>31) + return (x-x)/0.0f; /* log(-#) = NaN */ /* subnormal number, scale up x */ k -= 25; - x *= two25; - GET_FLOAT_WORD(ix, x); - } - if (ix >= 0x7f800000) - return x+x; - k += (ix>>23) - 127; - ix &= 0x007fffff; - i = (ix + (0x95f64<<3)) & 0x800000; - SET_FLOAT_WORD(x, ix|(i^0x3f800000)); /* normalize x or x/2 */ - k += i>>23; + x *= 0x1p25f; + u.f = x; + ix = u.i; + } else if (ix >= 0x7f800000) { + return x; + } else if (ix == 0x3f800000) + return 0; + + /* reduce x into [sqrt(2)/2, sqrt(2)] */ + ix += 0x3f800000 - 0x3f3504f3; + k += (int)(ix>>23) - 0x7f; + ix = (ix&0x007fffff) + 0x3f3504f3; + u.i = ix; + x = u.f; + f = x - 1.0f; - if ((0x007fffff & (0x8000 + ix)) < 0xc000) { /* -2**-9 <= f < 2**-9 */ - if (f == 0.0f) { - if (k == 0) - return 0.0f; - dk = (float)k; - return dk*ln2_hi + dk*ln2_lo; - } - R = f*f*(0.5f - 0.33333333333333333f*f); - if (k == 0) - return f-R; - dk = (float)k; - return dk*ln2_hi - ((R-dk*ln2_lo)-f); - } s = f/(2.0f + f); - dk = (float)k; z = s*s; - i = ix-(0x6147a<<3); w = z*z; - j = (0x6b851<<3)-ix; t1= w*(Lg2+w*Lg4); t2= z*(Lg1+w*Lg3); - i |= j; R = t2 + t1; - if (i > 0) { - hfsq = 0.5f * f * f; - if (k == 0) - return f - (hfsq-s*(hfsq+R)); - return dk*ln2_hi - ((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f); - } else { - if (k == 0) - return f - s*(f-R); - return dk*ln2_hi - ((s*(f-R)-dk*ln2_lo)-f); - } + hfsq = 0.5f*f*f; + dk = k; + return s*(hfsq+R) + dk*ln2_lo - hfsq + f + dk*ln2_hi; } diff --git a/src/math/logl.c b/src/math/logl.c index ef2b551..03c5188 100644 --- a/src/math/logl.c +++ b/src/math/logl.c @@ -35,9 +35,9 @@ * * log(1+x) = x - 0.5 x**2 + x**3 P(x)/Q(x). * - * Otherwise, setting z = 2(x-1)/x+1), + * Otherwise, setting z = 2(x-1)/(x+1), * - * log(x) = z + z**3 P(z)/Q(z). + * log(x) = log(1+z/2) - log(1-z/2) = z + z**3 P(z)/Q(z). * * * ACCURACY: @@ -116,7 +116,7 @@ long double logl(long double x) return x; if (x <= 0.0) { if (x == 0.0) - return -1/(x+0); /* -inf with divbyzero */ + return -1/(x*x); /* -inf with divbyzero */ return 0/0.0f; /* nan with invalid */ } @@ -127,7 +127,7 @@ long double logl(long double x) x = frexpl(x, &e); /* logarithm using log(x) = z + z**3 P(z)/Q(z), - * where z = 2(x-1)/x+1) + * where z = 2(x-1)/(x+1) */ if (e > 2 || e < -2) { if (x < SQRTH) { /* 2(2x-1)/(2x+1) */ diff --git a/src/math/modfl.c b/src/math/modfl.c index fc85bb5..f736bba 100644 --- a/src/math/modfl.c +++ b/src/math/modfl.c @@ -14,7 +14,6 @@ long double modfl(long double x, long double *iptr) long double modfl(long double x, long double *iptr) { union ldshape u = {x}; - uint64_t mask; int e = (u.i.se & 0x7fff) - 0x3fff; int s = u.i.se >> 15; long double absx; diff --git a/src/math/remainder.c b/src/math/remainder.c index ed5c477..6cd089c 100644 --- a/src/math/remainder.c +++ b/src/math/remainder.c @@ -1,7 +1,10 @@ #include +#include "libc.h" double remainder(double x, double y) { int q; return remquo(x, y, &q); } + +weak_alias(remainder, drem); diff --git a/src/math/remainderf.c b/src/math/remainderf.c index b418bbf..420d3bf 100644 --- a/src/math/remainderf.c +++ b/src/math/remainderf.c @@ -1,7 +1,10 @@ #include +#include "libc.h" float remainderf(float x, float y) { int q; return remquof(x, y, &q); } + +weak_alias(remainderf, dremf); diff --git a/src/math/scalb.c b/src/math/scalb.c index a54bdf2..efe69e6 100644 --- a/src/math/scalb.c +++ b/src/math/scalb.c @@ -15,6 +15,7 @@ * should use scalbn() instead. */ +#define _GNU_SOURCE #include double scalb(double x, double fn) diff --git a/src/math/scalbf.c b/src/math/scalbf.c index 9436497..f44ed5b 100644 --- a/src/math/scalbf.c +++ b/src/math/scalbf.c @@ -13,6 +13,7 @@ * ==================================================== */ +#define _GNU_SOURCE #include float scalbf(float x, float fn) diff --git a/src/math/sincos.c b/src/math/sincos.c index 49f8a09..35b2d92 100644 --- a/src/math/sincos.c +++ b/src/math/sincos.c @@ -10,6 +10,7 @@ * ==================================================== */ +#define _GNU_SOURCE #include "libm.h" void sincos(double x, double *sin, double *cos) diff --git a/src/math/sincosf.c b/src/math/sincosf.c index 1b50f01..f8ca723 100644 --- a/src/math/sincosf.c +++ b/src/math/sincosf.c @@ -14,6 +14,7 @@ * ==================================================== */ +#define _GNU_SOURCE #include "libm.h" /* Small multiples of pi/2 rounded to double precision. */ diff --git a/src/math/tgamma.c b/src/math/tgamma.c index f91af73..28f6e0f 100644 --- a/src/math/tgamma.c +++ b/src/math/tgamma.c @@ -26,7 +26,7 @@ most ideas and constants are from boost and python static const double pi = 3.141592653589793238462643383279502884; -/* sin(pi x) with x > 0 && isnormal(x) assumption */ +/* sin(pi x) with x > 0x1p-100, if sin(pi*x)==0 the sign is arbitrary */ static double sinpi(double x) { int n; @@ -49,8 +49,7 @@ static double sinpi(double x) case 1: return __cos(x, 0); case 2: - /* sin(0-x) and -sin(x) have different sign at 0 */ - return __sin(0-x, 0, 0); + return __sin(-x, 0, 0); case 3: return -__cos(x, 0); } @@ -108,35 +107,33 @@ static double S(double x) double tgamma(double x) { - double absx, y, dy, z, r; + union {double f; uint64_t i;} u = {x}; + double absx, y; + double_t dy, z, r; + uint32_t ix = u.i>>32 & 0x7fffffff; + int sign = u.i>>63; /* special cases */ - if (!isfinite(x)) + if (ix >= 0x7ff00000) /* tgamma(nan)=nan, tgamma(inf)=inf, tgamma(-inf)=nan with invalid */ return x + INFINITY; + if (ix < (0x3ff-54)<<20) + /* |x| < 2^-54: tgamma(x) ~ 1/x, +-0 raises div-by-zero */ + return 1/x; /* integer arguments */ /* raise inexact when non-integer */ if (x == floor(x)) { - if (x == 0) - /* tgamma(+-0)=+-inf with divide-by-zero */ - return 1/x; - if (x < 0) + if (sign) return 0/0.0; if (x <= sizeof fact/sizeof *fact) return fact[(int)x - 1]; } - absx = fabs(x); - - /* x ~ 0: tgamma(x) ~ 1/x */ - if (absx < 0x1p-54) - return 1/x; - /* x >= 172: tgamma(x)=inf with overflow */ /* x =< -184: tgamma(x)=+-0 with underflow */ - if (absx >= 184) { - if (x < 0) { + if (ix >= 0x40670000) { /* |x| >= 184 */ + if (sign) { FORCE_EVAL((float)(0x1p-126/x)); if (floor(x) * 0.5 == floor(x * 0.5)) return 0; @@ -146,6 +143,8 @@ double tgamma(double x) return x; } + absx = sign ? -x : x; + /* handle the error of x + g - 0.5 */ y = absx + gmhalf; if (absx > gmhalf) { @@ -160,20 +159,21 @@ double tgamma(double x) r = S(absx) * exp(-y); if (x < 0) { /* reflection formula for negative x */ + /* sinpi(absx) is not 0, integers are already handled */ r = -pi / (sinpi(absx) * absx * r); dy = -dy; z = -z; } r += dy * (gmhalf+0.5) * r / y; z = pow(y, 0.5*z); - r = r * z * z; - return r; + y = r * z * z; + return y; } #if 0 double __lgamma_r(double x, int *sign) { - double r, absx, z, zz, w; + double r, absx; *sign = 1; diff --git a/src/misc/get_current_dir_name.c b/src/misc/get_current_dir_name.c index e0f463b..782cddc 100644 --- a/src/misc/get_current_dir_name.c +++ b/src/misc/get_current_dir_name.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include #include #include @@ -6,11 +7,9 @@ char *get_current_dir_name(void) { struct stat a, b; - char buf[PATH_MAX]; char *res = getenv("PWD"); if (res && *res && !stat(res, &a) && !stat(".", &b) && (a.st_dev == b.st_dev) && (a.st_ino == b.st_ino)) return strdup(res); - if(!getcwd(buf, sizeof(buf))) return NULL; - return strdup(buf); + return getcwd(0, 0); } diff --git a/src/misc/getgrouplist.c b/src/misc/getgrouplist.c index 63557af..c9a8f09 100644 --- a/src/misc/getgrouplist.c +++ b/src/misc/getgrouplist.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include #include #include diff --git a/src/misc/getrusage.c b/src/misc/getrusage.c index a5cbd75..0aaf0ac 100644 --- a/src/misc/getrusage.c +++ b/src/misc/getrusage.c @@ -1,5 +1,4 @@ #include -#include #include "syscall.h" int getrusage(int who, struct rusage *ru) diff --git a/src/misc/initgroups.c b/src/misc/initgroups.c index 545d185..922a958 100644 --- a/src/misc/initgroups.c +++ b/src/misc/initgroups.c @@ -1,11 +1,7 @@ -#include -#include +#define _GNU_SOURCE #include #include -int getgrouplist(const char *, gid_t, gid_t *, int *); -int setgroups(size_t, const gid_t *); - int initgroups(const char *user, gid_t gid) { gid_t groups[NGROUPS_MAX]; diff --git a/src/misc/nftw.c b/src/misc/nftw.c index 63d6aff..b2e84bc 100644 --- a/src/misc/nftw.c +++ b/src/misc/nftw.c @@ -2,8 +2,6 @@ #include #include #include -#include -#include #include #include #include diff --git a/src/misc/syslog.c b/src/misc/syslog.c index ba9cc62..1cd61ce 100644 --- a/src/misc/syslog.c +++ b/src/misc/syslog.c @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include diff --git a/src/misc/uname.c b/src/misc/uname.c index 46db90d..55ea342 100644 --- a/src/misc/uname.c +++ b/src/misc/uname.c @@ -1,5 +1,4 @@ #include -#include #include "syscall.h" int uname(struct utsname *uts) diff --git a/src/misc/wordexp.c b/src/misc/wordexp.c index 617706e..a5f1b65 100644 --- a/src/misc/wordexp.c +++ b/src/misc/wordexp.c @@ -7,7 +7,21 @@ #include #include #include -#include +#include +#include +#include "pthread_impl.h" + +static void reap(pid_t pid) +{ + int status; + for (;;) { + if (waitpid(pid, &status, 0) < 0) { + if (errno != EINTR) return; + } else { + if (WIFEXITED(status)) return; + } + } +} static char *getword(FILE *f) { @@ -22,12 +36,13 @@ static int do_wordexp(const char *s, wordexp_t *we, int flags) size_t np=0; char *w, **tmp; char *redir = (flags & WRDE_SHOWERR) ? "" : "2>/dev/null"; - int err = 0, status; + int err = 0; FILE *f; size_t wc = 0; char **wv = 0; int p[2]; pid_t pid; + sigset_t set; if (flags & WRDE_REUSE) wordfree(we); @@ -80,25 +95,26 @@ static int do_wordexp(const char *s, wordexp_t *we, int flags) i = wc; if (flags & WRDE_DOOFFS) { if (we->we_offs > SIZE_MAX/sizeof(void *)/4) - return WRDE_NOSPACE; + goto nospace; i += we->we_offs; } else { we->we_offs = 0; } - if (pipe(p) < 0) return WRDE_NOSPACE; + if (pipe2(p, O_CLOEXEC) < 0) goto nospace; + __block_all_sigs(&set); pid = fork(); + __restore_sigs(&set); if (pid < 0) { close(p[0]); close(p[1]); - return WRDE_NOSPACE; + goto nospace; } if (!pid) { - dup2(p[1], 1); - close(p[0]); - close(p[1]); + if (p[1] == 1) fcntl(1, F_SETFD, 0); + else dup2(p[1], 1); execl("/bin/sh", "sh", "-c", - "eval \"printf %s\\\\\\\\0 $1 $2\"", + "eval \"printf %s\\\\\\\\0 x $1 $2\"", "sh", s, redir, (char *)0); _exit(1); } @@ -108,12 +124,19 @@ static int do_wordexp(const char *s, wordexp_t *we, int flags) if (!f) { close(p[0]); kill(pid, SIGKILL); - waitpid(pid, &status, 0); - return WRDE_NOSPACE; + reap(pid); + goto nospace; } l = wv ? i+1 : 0; + free(getword(f)); + if (feof(f)) { + fclose(f); + reap(pid); + return WRDE_SYNTAX; + } + while ((w = getword(f))) { if (i+1 >= l) { l += l/2+10; @@ -127,24 +150,26 @@ static int do_wordexp(const char *s, wordexp_t *we, int flags) if (!feof(f)) err = WRDE_NOSPACE; fclose(f); - waitpid(pid, &status, 0); - if (WEXITSTATUS(status)) { - if (!(flags & WRDE_APPEND)) { - free(wv); - return WRDE_SYNTAX; - } else if (wv==we->we_wordv) { - return WRDE_SYNTAX; - } - } + reap(pid); + + if (!wv) wv = calloc(i+1, sizeof *wv); we->we_wordv = wv; we->we_wordc = i; - for (i=we->we_offs; i; i--) - we->we_wordv[i-1] = 0; - - if (flags & WRDE_DOOFFS) we->we_wordc -= we->we_offs; + if (flags & WRDE_DOOFFS) { + if (wv) for (i=we->we_offs; i; i--) + we->we_wordv[i-1] = 0; + we->we_wordc -= we->we_offs; + } return err; + +nospace: + if (!(flags & WRDE_APPEND)) { + we->we_wordc = 0; + we->we_wordv = 0; + } + return WRDE_NOSPACE; } int wordexp(const char *restrict s, wordexp_t *restrict we, int flags) diff --git a/src/mman/msync.c b/src/mman/msync.c index eaf35d3..bb20475 100644 --- a/src/mman/msync.c +++ b/src/mman/msync.c @@ -1,4 +1,3 @@ -#include #include #include "syscall.h" diff --git a/src/mman/munmap.c b/src/mman/munmap.c index 91aefd4..8488d75 100644 --- a/src/mman/munmap.c +++ b/src/mman/munmap.c @@ -1,4 +1,3 @@ -#include #include #include "syscall.h" #include "libc.h" diff --git a/src/multibyte/internal.c b/src/multibyte/internal.c index ab22806..1813b26 100644 --- a/src/multibyte/internal.c +++ b/src/multibyte/internal.c @@ -4,8 +4,6 @@ * unnecessary. */ -#include - #include "internal.h" #define C(x) ( x<2 ? -1 : ( R(0x80,0xc0) | x ) ) diff --git a/src/multibyte/internal.h b/src/multibyte/internal.h index 25ba240..82f5a07 100644 --- a/src/multibyte/internal.h +++ b/src/multibyte/internal.h @@ -6,6 +6,7 @@ #define bittab __fsmu8 +#include #include "libc.h" extern const uint32_t bittab[] ATTR_LIBC_VISIBILITY; diff --git a/src/multibyte/mblen.c b/src/multibyte/mblen.c index 26d3564..96b47b1 100644 --- a/src/multibyte/mblen.c +++ b/src/multibyte/mblen.c @@ -5,11 +5,6 @@ */ #include -#include -#include -#include - -#include "internal.h" int mblen(const char *s, size_t n) { diff --git a/src/multibyte/mbrlen.c b/src/multibyte/mbrlen.c index c9714ef..3a5a743 100644 --- a/src/multibyte/mbrlen.c +++ b/src/multibyte/mbrlen.c @@ -4,12 +4,7 @@ * unnecessary. */ -#include -#include #include -#include - -#include "internal.h" size_t mbrlen(const char *restrict s, size_t n, mbstate_t *restrict st) { diff --git a/src/multibyte/mbrtowc.c b/src/multibyte/mbrtowc.c index db80366..35e834e 100644 --- a/src/multibyte/mbrtowc.c +++ b/src/multibyte/mbrtowc.c @@ -4,11 +4,8 @@ * unnecessary. */ -#include -#include #include #include - #include "internal.h" size_t mbrtowc(wchar_t *restrict wc, const char *restrict src, size_t n, mbstate_t *restrict st) diff --git a/src/multibyte/mbsinit.c b/src/multibyte/mbsinit.c index c0e7e49..e001d84 100644 --- a/src/multibyte/mbsinit.c +++ b/src/multibyte/mbsinit.c @@ -4,12 +4,7 @@ * unnecessary. */ -#include -#include #include -#include - -#include "internal.h" int mbsinit(const mbstate_t *st) { diff --git a/src/multibyte/mbsnrtowcs.c b/src/multibyte/mbsnrtowcs.c index 33457f9..68b9960 100644 --- a/src/multibyte/mbsnrtowcs.c +++ b/src/multibyte/mbsnrtowcs.c @@ -4,13 +4,7 @@ * unnecessary. */ -#include -#include #include -#include -#include - -#include "internal.h" size_t mbsnrtowcs(wchar_t *restrict wcs, const char **restrict src, size_t n, size_t wn, mbstate_t *restrict st) { diff --git a/src/multibyte/mbsrtowcs.c b/src/multibyte/mbsrtowcs.c index b9bbc33..3c1343a 100644 --- a/src/multibyte/mbsrtowcs.c +++ b/src/multibyte/mbsrtowcs.c @@ -4,11 +4,9 @@ * unnecessary. */ -#include -#include +#include #include #include - #include "internal.h" size_t mbsrtowcs(wchar_t *restrict ws, const char **restrict src, size_t wn, mbstate_t *restrict st) @@ -59,7 +57,7 @@ resume0: return wn0; } if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) { - while (wn>=4 && !(( *(uint32_t*)s | *(uint32_t*)s-0x01010101) & 0x80808080)) { + while (wn>=5 && !(( *(uint32_t*)s | *(uint32_t*)s-0x01010101) & 0x80808080)) { *ws++ = *s++; *ws++ = *s++; *ws++ = *s++; diff --git a/src/multibyte/mbtowc.c b/src/multibyte/mbtowc.c index ec9e54a..6710637 100644 --- a/src/multibyte/mbtowc.c +++ b/src/multibyte/mbtowc.c @@ -4,13 +4,10 @@ * unnecessary. */ -#include -#include #include #include - #include "internal.h" -#include + int mbtowc(wchar_t *restrict wc, const char *restrict src, size_t n) { unsigned c; diff --git a/src/multibyte/wcrtomb.c b/src/multibyte/wcrtomb.c index 250649f..59f733d 100644 --- a/src/multibyte/wcrtomb.c +++ b/src/multibyte/wcrtomb.c @@ -4,13 +4,9 @@ * unnecessary. */ -#include -#include #include #include -#include "internal.h" - size_t wcrtomb(char *restrict s, wchar_t wc, mbstate_t *restrict st) { if (!s) return 1; diff --git a/src/multibyte/wcsnrtombs.c b/src/multibyte/wcsnrtombs.c index a2e308b..7eb05d4 100644 --- a/src/multibyte/wcsnrtombs.c +++ b/src/multibyte/wcsnrtombs.c @@ -4,12 +4,7 @@ * unnecessary. */ -#include -#include #include -#include - -#include "internal.h" size_t wcsnrtombs(char *restrict dst, const wchar_t **restrict wcs, size_t wn, size_t n, mbstate_t *restrict st) { diff --git a/src/multibyte/wcsrtombs.c b/src/multibyte/wcsrtombs.c index d48a65e..5cf8f3e 100644 --- a/src/multibyte/wcsrtombs.c +++ b/src/multibyte/wcsrtombs.c @@ -4,12 +4,7 @@ * unnecessary. */ -#include -#include #include -#include - -#include "internal.h" size_t wcsrtombs(char *restrict s, const wchar_t **restrict ws, size_t n, mbstate_t *restrict st) { diff --git a/src/multibyte/wctomb.c b/src/multibyte/wctomb.c index 6910ef3..de7ed84 100644 --- a/src/multibyte/wctomb.c +++ b/src/multibyte/wctomb.c @@ -5,11 +5,7 @@ */ #include -#include #include -#include - -#include "internal.h" int wctomb(char *s, wchar_t wc) { diff --git a/src/network/__dns.c b/src/network/__dns.c index 8f3c637..97d8031 100644 --- a/src/network/__dns.c +++ b/src/network/__dns.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "__dns.h" #include "stdio_impl.h" @@ -35,9 +36,9 @@ int __dns_doqueries(unsigned char *dest, const char *name, int *rr, int rrcnt) struct sockaddr_in sin; struct sockaddr_in6 sin6; } sa = {0}, ns[3] = {{0}}; - socklen_t sl; + socklen_t sl = sizeof sa.sin; int nns = 0; - int family = AF_UNSPEC; + int family = AF_INET; unsigned char q[280] = "", *r = dest; int ql; int rlen; @@ -75,10 +76,12 @@ int __dns_doqueries(unsigned char *dest, const char *name, int *rr, int rrcnt) for (s=line+11; isspace(*s); s++); for (z=s; *z && !isspace(*z); z++); *z=0; - if (__ipparse(ns+nns, family, s) < 0) continue; + if (__ipparse(ns+nns, AF_UNSPEC, s) < 0) continue; ns[nns].sin.sin_port = htons(53); - family = ns[nns++].sin.sin_family; - sl = family==AF_INET6 ? sizeof sa.sin6 : sizeof sa.sin; + if (ns[nns++].sin.sin_family == AF_INET6) { + family = AF_INET6; + sl = sizeof sa.sin6; + } } if (f) __fclose_ca(f); if (!nns) { @@ -93,6 +96,29 @@ int __dns_doqueries(unsigned char *dest, const char *name, int *rr, int rrcnt) sa.sin.sin_family = family; fd = socket(family, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + /* Handle case where system lacks IPv6 support */ + if (fd < 0 && errno == EAFNOSUPPORT) { + if (family != AF_INET6) return EAI_SYSTEM; + fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + family = AF_INET; + } + if (fd < 0) return EAI_SYSTEM; + + /* Convert any IPv4 addresses in a mixed environment to v4-mapped */ + if (family == AF_INET6) { + setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &(int){0}, sizeof 0); + for (i=0; i #include +#include #include #include #include #include "__dns.h" -#include int __ipparse(void *dest, int family, const char *s0) { const char *s = s0; unsigned char *d = dest; unsigned long a[16] = { 0 }; - const char *z; + char *z; int i; if (family == AF_INET6) goto not_v4; for (i=0; i<4; i++) { - a[i] = strtoul(s, (char **)&z, 0); - if (z==s || (*z && *z != '.')) goto not_v4; + a[i] = strtoul(s, &z, 0); + if (z==s || (*z && *z != '.') || !isdigit(*s)) { + if (family == AF_INET) return -1; + goto not_v4; + } if (!*z) break; s=z+1; } + if (i==4) return -1; switch (i) { case 0: a[1] = a[0] & 0xffffff; @@ -35,7 +38,10 @@ int __ipparse(void *dest, int family, const char *s0) } ((struct sockaddr_in *)d)->sin_family = AF_INET; d = (void *)&((struct sockaddr_in *)d)->sin_addr; - for (i=0; i<4; i++) d[i] = a[i]; + for (i=0; i<4; i++) { + if (a[i] > 255) return -1; + d[i] = a[i]; + } return 0; not_v4: diff --git a/src/network/dn_comp.c b/src/network/dn_comp.c new file mode 100644 index 0000000..4f4452a --- /dev/null +++ b/src/network/dn_comp.c @@ -0,0 +1,9 @@ +#include +#include "libc.h" + +int __dn_comp(const char *src, unsigned char *dst, int space, unsigned char **dnptrs, unsigned char **lastdnptr) +{ + return -1; +} + +weak_alias(__dn_comp, dn_comp); diff --git a/src/network/dn_expand.c b/src/network/dn_expand.c index 4e02e3d..96adf37 100644 --- a/src/network/dn_expand.c +++ b/src/network/dn_expand.c @@ -10,7 +10,7 @@ int __dn_expand(const unsigned char *base, const unsigned char *end, const unsig for (;;) { if (*p & 0xc0) { if (p+1==end) return -1; - j = (p[0]&1) | p[1]; + j = ((p[0] & 0x3f) << 8) | p[1]; if (len < 0) len = p+2-src; if (j >= end-base) return -1; p = base+j; diff --git a/src/network/getaddrinfo.c b/src/network/getaddrinfo.c index 4c1fe27..5d45be7 100644 --- a/src/network/getaddrinfo.c +++ b/src/network/getaddrinfo.c @@ -31,9 +31,6 @@ static int have_af(int family) } #endif -#include -#include - union sa { struct sockaddr_in sin; struct sockaddr_in6 sin6; @@ -65,6 +62,9 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru int result; int cnt; + if (family != AF_INET && family != AF_INET6 && family != AF_UNSPEC) + return EAI_FAMILY; + if (host && strlen(host)>255) return EAI_NONAME; if (serv && strlen(serv)>32) return EAI_SERVICE; diff --git a/src/network/gethostbyaddr.c b/src/network/gethostbyaddr.c index c9b6388..598e224 100644 --- a/src/network/gethostbyaddr.c +++ b/src/network/gethostbyaddr.c @@ -1,8 +1,6 @@ #define _GNU_SOURCE #include -#include -#include #include #include diff --git a/src/network/gethostbyname2.c b/src/network/gethostbyname2.c index c9f90da..dc9d662 100644 --- a/src/network/gethostbyname2.c +++ b/src/network/gethostbyname2.c @@ -2,8 +2,6 @@ #include #include -#include -#include #include #include diff --git a/src/network/gethostbyname2_r.c b/src/network/gethostbyname2_r.c index 0dc6dc0..27eb080 100644 --- a/src/network/gethostbyname2_r.c +++ b/src/network/gethostbyname2_r.c @@ -5,7 +5,7 @@ #include #include #include -#include +#include int gethostbyname2_r(const char *name, int af, struct hostent *h, char *buf, size_t buflen, diff --git a/src/network/getifaddrs.c b/src/network/getifaddrs.c index a14ac1b..5a94cc7 100644 --- a/src/network/getifaddrs.c +++ b/src/network/getifaddrs.c @@ -11,6 +11,7 @@ #include /* inet_pton */ #include #include +#include typedef union { struct sockaddr_in6 v6; @@ -66,7 +67,7 @@ static void ipv6netmask(unsigned prefix_length, struct sockaddr_in6 *sa) static void dealwithipv6(stor **list, stor** head) { - FILE* f = fopen("/proc/net/if_inet6", "r"); + FILE* f = fopen("/proc/net/if_inet6", "rbe"); /* 00000000000000000000000000000001 01 80 10 80 lo A B C D E F all numbers in hex diff --git a/src/network/getnameinfo.c b/src/network/getnameinfo.c index 3d115c7..33f89a3 100644 --- a/src/network/getnameinfo.c +++ b/src/network/getnameinfo.c @@ -1,6 +1,5 @@ #include #include -#include #include #include #include diff --git a/src/network/if_nameindex.c b/src/network/if_nameindex.c index ad0a766..53b80b2 100644 --- a/src/network/if_nameindex.c +++ b/src/network/if_nameindex.c @@ -6,8 +6,6 @@ #include #include "syscall.h" -#include - static void *do_nameindex(int s, size_t n) { size_t i, len, k; diff --git a/src/network/inet_addr.c b/src/network/inet_addr.c new file mode 100644 index 0000000..ea0a8f7 --- /dev/null +++ b/src/network/inet_addr.c @@ -0,0 +1,11 @@ +#include +#include +#include +#include "__dns.h" + +in_addr_t inet_addr(const char *p) +{ + struct sockaddr_in sin; + if (__ipparse(&sin, AF_INET, p) < 0) return -1; + return sin.sin_addr.s_addr; +} diff --git a/src/network/inet_legacy.c b/src/network/inet_legacy.c index e802557..0a0ad6f 100644 --- a/src/network/inet_legacy.c +++ b/src/network/inet_legacy.c @@ -1,16 +1,8 @@ #include #include #include -#include #include "__dns.h" -in_addr_t inet_addr(const char *p) -{ - struct sockaddr_in sin; - if (__ipparse(&sin, AF_INET, p)) return -1; - return sin.sin_addr.s_addr; -} - in_addr_t inet_network(const char *p) { return ntohl(inet_addr(p)); @@ -18,15 +10,10 @@ in_addr_t inet_network(const char *p) int inet_aton(const char *cp, struct in_addr *inp) { - return inet_pton(AF_INET, cp, (void *)inp) > 0; -} - -char *inet_ntoa(struct in_addr in) -{ - static char buf[16]; - unsigned char *a = (void *)∈ - snprintf(buf, sizeof buf, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]); - return buf; + struct sockaddr_in sin; + if (__ipparse(&sin, AF_INET, cp) < 0) return 0; + *inp = sin.sin_addr; + return 1; } struct in_addr inet_makeaddr(int net, int host) diff --git a/src/network/inet_ntoa.c b/src/network/inet_ntoa.c new file mode 100644 index 0000000..71411e0 --- /dev/null +++ b/src/network/inet_ntoa.c @@ -0,0 +1,10 @@ +#include +#include + +char *inet_ntoa(struct in_addr in) +{ + static char buf[16]; + unsigned char *a = (void *)∈ + snprintf(buf, sizeof buf, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]); + return buf; +} diff --git a/src/network/inet_ntop.c b/src/network/inet_ntop.c index ca33343..14f9f4c 100644 --- a/src/network/inet_ntop.c +++ b/src/network/inet_ntop.c @@ -1,7 +1,5 @@ #include -#include #include -#include #include #include #include diff --git a/src/network/inet_pton.c b/src/network/inet_pton.c index 5c4850a..4496b47 100644 --- a/src/network/inet_pton.c +++ b/src/network/inet_pton.c @@ -1,7 +1,5 @@ #include -#include #include -#include #include #include #include @@ -18,52 +16,46 @@ int inet_pton(int af, const char *restrict s, void *restrict a0) { uint16_t ip[8]; unsigned char *a = a0; - const char *z; - unsigned long x; int i, j, v, d, brk=-1, need_v4=0; - /* Reimplement this because inet_pton cannot accept special v4 forms */ if (af==AF_INET) { - for (i=0; i<4 && *s; i++) { - a[i] = x = strtoul(s, (char **)&z, 10); - if (!isdigit(*s) || z==s || (*z && *z != '.') || x>255) - return 0; - s=z+1; + for (i=0; i<4; i++) { + for (v=j=0; j<3 && isdigit(s[j]); j++) + v = 10*v + s[j]-'0'; + if (j==0 || (j>1 && s[0]=='0') || v>255) return 0; + a[i] = v; + if (s[j]==0 && i==3) return 1; + if (s[j]!='.') return 0; + s += j+1; } - return 1; + return 0; } else if (af!=AF_INET6) { errno = EAFNOSUPPORT; return -1; } - if (s[0]==':' && s[1]==':') s++; + if (*s==':' && *++s!=':') return 0; - for (i=0; ; i++, s+=j+1) { + for (i=0; ; i++) { if (s[0]==':' && brk<0) { brk=i; - j=0; ip[i]=0; - if (!s[1]) break; + if (!*++s) break; continue; } - if (hexval(s[0])<0) return -1; - while (s[0]=='0' && s[1]=='0') s++; - for (v=j=0; j<5 && (d=hexval(s[j]))>=0; j++) + for (v=j=0; j<4 && (d=hexval(s[j]))>=0; j++) v=16*v+d; - if (v > 65535) return -1; + if (j==0) return 0; ip[i] = v; - if (!s[j]) { - if (brk<0 && i!=7) return -1; - break; - } - if (i<7) { - if (s[j]==':') continue; - if (s[j]!='.') return -1; + if (!s[j] && (brk>=0 || i==7)) break; + if (i==7) return 0; + if (s[j]!=':') { + if (s[j]!='.' || (i<6 && brk<0)) return 0; need_v4=1; i++; break; } - return -1; + s += j+1; } if (brk>=0) { memmove(ip+brk+7-i, ip+brk, 2*(i+1-brk)); @@ -73,6 +65,6 @@ int inet_pton(int af, const char *restrict s, void *restrict a0) *a++ = ip[j]>>8; *a++ = ip[j]; } - if (need_v4 &&inet_pton(AF_INET, (void *)s, a-4) <= 0) return -1; + if (need_v4 && inet_pton(AF_INET, (void *)s, a-4) <= 0) return 0; return 1; } diff --git a/src/network/proto.c b/src/network/proto.c index 8c25c53..031003a 100644 --- a/src/network/proto.c +++ b/src/network/proto.c @@ -1,5 +1,4 @@ #include -#include #include /* do we really need all these?? */ diff --git a/src/network/recv.c b/src/network/recv.c index d04a54a..5970048 100644 --- a/src/network/recv.c +++ b/src/network/recv.c @@ -1,6 +1,4 @@ #include -#include "syscall.h" -#include "libc.h" ssize_t recv(int fd, void *buf, size_t len, int flags) { diff --git a/src/network/res_query.c b/src/network/res_query.c index c3ad109..3847da3 100644 --- a/src/network/res_query.c +++ b/src/network/res_query.c @@ -1,4 +1,5 @@ #define _GNU_SOURCE +#include #include #include "__dns.h" #include "libc.h" diff --git a/src/network/send.c b/src/network/send.c index b6ec310..9f10497 100644 --- a/src/network/send.c +++ b/src/network/send.c @@ -1,6 +1,4 @@ #include -#include "syscall.h" -#include "libc.h" ssize_t send(int fd, const void *buf, size_t len, int flags) { diff --git a/src/network/serv.c b/src/network/serv.c index 5ade6ad..41424e8 100644 --- a/src/network/serv.c +++ b/src/network/serv.c @@ -1,6 +1,4 @@ #include -#include -#include void endservent(void) { diff --git a/src/passwd/fgetgrent.c b/src/passwd/fgetgrent.c index 2f18d92..d8d1c77 100644 --- a/src/passwd/fgetgrent.c +++ b/src/passwd/fgetgrent.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include "pwf.h" struct group *fgetgrent(FILE *f) diff --git a/src/passwd/fgetpwent.c b/src/passwd/fgetpwent.c index e95fdb2..eb47b2a 100644 --- a/src/passwd/fgetpwent.c +++ b/src/passwd/fgetpwent.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include "pwf.h" struct passwd *fgetpwent(FILE *f) diff --git a/src/passwd/fgetspent.c b/src/passwd/fgetspent.c index a9a3c97..47473bd 100644 --- a/src/passwd/fgetspent.c +++ b/src/passwd/fgetspent.c @@ -1,11 +1,15 @@ #include "pwf.h" +#include struct spwd *fgetspent(FILE *f) { - return 0; -} - -int putspent(const struct spwd *sp, FILE *f) -{ - return -1; + static char *line; + static struct spwd sp; + size_t size = 0; + struct spwd *res = 0; + int cs; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); + if (getline(&line, &size, f) >= 0 && __parsespent(line, &sp) >= 0) res = &sp; + pthread_setcancelstate(cs, 0); + return res; } diff --git a/src/passwd/getgr_r.c b/src/passwd/getgr_r.c index 234c901..3fe2e2b 100644 --- a/src/passwd/getgr_r.c +++ b/src/passwd/getgr_r.c @@ -26,14 +26,14 @@ static int getgr_r(const char *name, gid_t gid, struct group *gr, char *buf, siz while (__getgrent_a(f, gr, &line, &len, &mem, &nmem)) { if (name && !strcmp(name, gr->gr_name) || !name && gr->gr_gid == gid) { - if (size < len + nmem*sizeof(char *) + 32) { + if (size < len + (nmem+1)*sizeof(char *) + 32) { rv = ERANGE; break; } *res = gr; buf += (16-(uintptr_t)buf)%16; gr->gr_mem = (void *)buf; - buf += nmem*sizeof(char *); + buf += (nmem+1)*sizeof(char *); memcpy(buf, line, len); FIX(name); FIX(passwd); diff --git a/src/passwd/getspnam_r.c b/src/passwd/getspnam_r.c index f4d7b35..15f8c87 100644 --- a/src/passwd/getspnam_r.c +++ b/src/passwd/getspnam_r.c @@ -12,9 +12,45 @@ * file. It also avoids any allocation to prevent memory-exhaustion * attacks via huge TCB shadow files. */ -static long xatol(const char *s) +static long xatol(char **s) { - return isdigit(*s) ? atol(s) : -1; + long x; + if (**s == ':' || **s == '\n') return -1; + for (x=0; **s-'0'<10U; ++*s) x=10*x+(**s-'0'); + return x; +} + +int __parsespent(char *s, struct spwd *sp) +{ + sp->sp_namp = s; + if (!(s = strchr(s, ':'))) return -1; + *s = 0; + + sp->sp_pwdp = ++s; + if (!(s = strchr(s, ':'))) return -1; + *s = 0; + + s++; sp->sp_lstchg = xatol(&s); + if (*s != ':') return -1; + + s++; sp->sp_min = xatol(&s); + if (*s != ':') return -1; + + s++; sp->sp_max = xatol(&s); + if (*s != ':') return -1; + + s++; sp->sp_warn = xatol(&s); + if (*s != ':') return -1; + + s++; sp->sp_inact = xatol(&s); + if (*s != ':') return -1; + + s++; sp->sp_expire = xatol(&s); + if (*s != ':') return -1; + + s++; sp->sp_flag = xatol(&s); + if (*s != '\n') return -1; + return 0; } static void cleanup(void *p) @@ -29,7 +65,6 @@ int getspnam_r(const char *name, struct spwd *sp, char *buf, size_t size, struct int rv = 0; int fd; size_t k, l = strlen(name); - char *s; int skip = 0; int cs; @@ -71,34 +106,8 @@ int getspnam_r(const char *name, struct spwd *sp, char *buf, size_t size, struct rv = ERANGE; break; } - buf[k-1] = 0; - - s = buf; - sp->sp_namp = s; - if (!(s = strchr(s, ':'))) continue; - - *s++ = 0; sp->sp_pwdp = s; - if (!(s = strchr(s, ':'))) continue; - - *s++ = 0; sp->sp_lstchg = xatol(s); - if (!(s = strchr(s, ':'))) continue; - - *s++ = 0; sp->sp_min = xatol(s); - if (!(s = strchr(s, ':'))) continue; - - *s++ = 0; sp->sp_max = xatol(s); - if (!(s = strchr(s, ':'))) continue; - - *s++ = 0; sp->sp_warn = xatol(s); - if (!(s = strchr(s, ':'))) continue; - - *s++ = 0; sp->sp_inact = xatol(s); - if (!(s = strchr(s, ':'))) continue; - - *s++ = 0; sp->sp_expire = xatol(s); - if (!(s = strchr(s, ':'))) continue; - *s++ = 0; sp->sp_flag = xatol(s); + if (__parsespent(buf, sp) < 0) continue; *res = sp; break; } diff --git a/src/passwd/putgrent.c b/src/passwd/putgrent.c index d7847b1..a0b320f 100644 --- a/src/passwd/putgrent.c +++ b/src/passwd/putgrent.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include #include @@ -6,9 +7,11 @@ int putgrent(const struct group *gr, FILE *f) int r; size_t i; flockfile(f); - r = fprintf(f, "%s:%s:%d:", gr->gr_name, gr->gr_passwd, gr->gr_gid); + if ((r = fprintf(f, "%s:%s:%d:", gr->gr_name, gr->gr_passwd, gr->gr_gid))<0) goto done; if (gr->gr_mem) for (i=0; gr->gr_mem[i]; i++) - if (fprintf(f, "%s%s", i?",":"", gr->gr_mem[i])<0) r = -1; + if ((r = fprintf(f, "%s%s", i?",":"", gr->gr_mem[i]))<0) goto done; + r = fputc('\n', f); +done: funlockfile(f); return r<0 ? -1 : 0; } diff --git a/src/passwd/putpwent.c b/src/passwd/putpwent.c index 80fbf38..3a02e57 100644 --- a/src/passwd/putpwent.c +++ b/src/passwd/putpwent.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include #include diff --git a/src/passwd/putspent.c b/src/passwd/putspent.c new file mode 100644 index 0000000..55c41bb --- /dev/null +++ b/src/passwd/putspent.c @@ -0,0 +1,13 @@ +#include +#include + +#define NUM(n) ((n) == -1 ? 0 : -1), ((n) == -1 ? 0 : (n)) +#define STR(s) ((s) ? (s) : "") + +int putspent(const struct spwd *sp, FILE *f) +{ + return fprintf(f, "%s:%s:%.*ld:%.*ld:%.*ld:%.*ld:%.*ld:%.*ld:%.*lu\n", + STR(sp->sp_namp), STR(sp->sp_pwdp), NUM(sp->sp_lstchg), + NUM(sp->sp_min), NUM(sp->sp_max), NUM(sp->sp_warn), + NUM(sp->sp_inact), NUM(sp->sp_expire), NUM(sp->sp_flag)) < 0 ? -1 : 0; +} diff --git a/src/passwd/pwf.h b/src/passwd/pwf.h index 0a76ef8..2d813ad 100644 --- a/src/passwd/pwf.h +++ b/src/passwd/pwf.h @@ -9,5 +9,5 @@ #include "libc.h" struct passwd *__getpwent_a(FILE *f, struct passwd *pw, char **line, size_t *size); -struct spwd *__getspent_a(FILE *f, struct spwd *sp, char **line, size_t *size); struct group *__getgrent_a(FILE *f, struct group *gr, char **line, size_t *size, char ***mem, size_t *nmem); +int __parsespent(char *s, struct spwd *sp); diff --git a/src/prng/__rand48_step.c b/src/prng/__rand48_step.c index 105f810..ccaffc3 100644 --- a/src/prng/__rand48_step.c +++ b/src/prng/__rand48_step.c @@ -1,4 +1,3 @@ -#include #include uint64_t __rand48_step(unsigned short *xi, unsigned short *lc) diff --git a/src/process/execl.c b/src/process/execl.c index 327d78b..5ee5c81 100644 --- a/src/process/execl.c +++ b/src/process/execl.c @@ -16,6 +16,7 @@ int execl(const char *path, const char *argv0, ...) for (i=1; i -#include #include void __procfdname(char *, unsigned); diff --git a/src/process/system.c b/src/process/system.c index f5b7b49..8cbdda0 100644 --- a/src/process/system.c +++ b/src/process/system.c @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include diff --git a/src/process/vfork.c b/src/process/vfork.c index 16d07ea..fc4adb4 100644 --- a/src/process/vfork.c +++ b/src/process/vfork.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include #include "syscall.h" #include "libc.h" diff --git a/src/regex/fnmatch.c b/src/regex/fnmatch.c index ffd3ea0..4df10a3 100644 --- a/src/regex/fnmatch.c +++ b/src/regex/fnmatch.c @@ -19,7 +19,7 @@ #include #include -#define END -1 +#define END 0 #define UNMATCHABLE -2 #define BRACKET -3 #define QUESTION -4 @@ -53,7 +53,7 @@ static int pat_next(const char *pat, size_t m, size_t *step, int flags) return END; } *step = 1; - if (pat[0]=='\\' && !(flags & FNM_NOESCAPE)) { + if (pat[0]=='\\' && pat[1] && !(flags & FNM_NOESCAPE)) { *step = 2; pat++; esc = 1; @@ -288,12 +288,19 @@ int fnmatch(const char *pat, const char *str, int flags) if (flags & FNM_PATHNAME) for (;;) { for (s=str; *s && *s!='/'; s++); for (p=pat; (c=pat_next(p, -1, &inc, flags))!=END && c!='/'; p+=inc); - if (*s && *p!=*s) return FNM_NOMATCH; + if (c!=*s && (!*s || !(flags & FNM_LEADING_DIR))) + return FNM_NOMATCH; if (fnmatch_internal(pat, p-pat, str, s-str, flags)) return FNM_NOMATCH; - if (!*s && c==END) return 0; + if (!c) return 0; str = s+1; - pat = p+1; + pat = p+inc; + } else if (flags & FNM_LEADING_DIR) { + for (s=str; *s; s++) { + if (*s != '/') continue; + if (!fnmatch_internal(pat, -1, str, s-str, flags)) + return 0; + } } return fnmatch_internal(pat, -1, str, -1, flags); } diff --git a/src/regex/glob.c b/src/regex/glob.c index 6c07e6b..6affee0 100644 --- a/src/regex/glob.c +++ b/src/regex/glob.c @@ -7,8 +7,6 @@ #include #include #include -#include -#include #include "libc.h" struct match diff --git a/src/regex/regcomp.c b/src/regex/regcomp.c index 5cedfd5..d907627 100644 --- a/src/regex/regcomp.c +++ b/src/regex/regcomp.c @@ -30,7 +30,6 @@ */ #include -#include #include #include #include @@ -516,7 +515,7 @@ tre_new_item(tre_mem_t mem, int min, int max, int *i, int *max_i, if (*max_i > 1024) return REG_ESPACE; *max_i *= 2; - new_items = xrealloc(array, sizeof(*items) * *max_i); + new_items = xrealloc(array, sizeof(*array) * *max_i); if (new_items == NULL) return REG_ESPACE; *items = array = new_items; @@ -765,7 +764,7 @@ tre_parse_bracket(tre_parse_ctx_t *ctx, tre_ast_node_t **result) if (num_neg_classes > 0) { l->neg_classes = tre_mem_alloc(ctx->mem, - (sizeof(l->neg_classes) + (sizeof(*l->neg_classes) * (num_neg_classes + 1))); if (l->neg_classes == NULL) { @@ -805,7 +804,7 @@ tre_parse_bracket(tre_parse_ctx_t *ctx, tre_ast_node_t **result) if (num_neg_classes > 0) { l->neg_classes = tre_mem_alloc(ctx->mem, - (sizeof(l->neg_classes) + (sizeof(*l->neg_classes) * (num_neg_classes + 1))); if (l->neg_classes == NULL) { @@ -3167,7 +3166,7 @@ regcomp(regex_t *restrict preg, const char *restrict regex, int cflags) sizeof(*tag_directions) * (tnfa->num_tags + 1)); } tnfa->minimal_tags = xcalloc((unsigned)tnfa->num_tags * 2 + 1, - sizeof(tnfa->minimal_tags)); + sizeof(*tnfa->minimal_tags)); if (tnfa->minimal_tags == NULL) ERROR_EXIT(REG_ESPACE); diff --git a/src/search/hsearch.c b/src/search/hsearch.c index be856b2..6fe5ced 100644 --- a/src/search/hsearch.c +++ b/src/search/hsearch.c @@ -14,14 +14,14 @@ with the posix api items cannot be iterated and length cannot be queried #define MINSIZE 8 #define MAXSIZE ((size_t)-1/2 + 1) -struct entry { +struct elem { ENTRY item; size_t hash; }; static size_t mask; static size_t used; -static struct entry *tab; +static struct elem *tab; static size_t keyhash(char *k) { @@ -37,9 +37,9 @@ static int resize(size_t nel) { size_t newsize; size_t i, j; - struct entry *e, *newe; - struct entry *oldtab = tab; - struct entry *oldend = tab + mask + 1; + struct elem *e, *newe; + struct elem *oldtab = tab; + struct elem *oldend = tab + mask + 1; if (nel > MAXSIZE) nel = MAXSIZE; @@ -81,10 +81,10 @@ void hdestroy(void) used = 0; } -static struct entry *lookup(char *key, size_t hash) +static struct elem *lookup(char *key, size_t hash) { size_t i, j; - struct entry *e; + struct elem *e; for (i=hash,j=1; ; i+=j++) { e = tab + (i & mask); @@ -98,7 +98,7 @@ static struct entry *lookup(char *key, size_t hash) ENTRY *hsearch(ENTRY item, ACTION action) { size_t hash = keyhash(item.key); - struct entry *e = lookup(item.key, hash); + struct elem *e = lookup(item.key, hash); if (e->item.key) return &e->item; diff --git a/src/signal/raise.c b/src/signal/raise.c index 6fa43be..35063c5 100644 --- a/src/signal/raise.c +++ b/src/signal/raise.c @@ -1,5 +1,4 @@ #include -#include #include #include "syscall.h" #include "pthread_impl.h" diff --git a/src/signal/sigaction.c b/src/signal/sigaction.c index 5499bd1..f7ff4a6 100644 --- a/src/signal/sigaction.c +++ b/src/signal/sigaction.c @@ -1,4 +1,3 @@ -#include #include #include #include diff --git a/src/signal/sigfillset.c b/src/signal/sigfillset.c index 4d0a807..16e7b4f 100644 --- a/src/signal/sigfillset.c +++ b/src/signal/sigfillset.c @@ -1,5 +1,4 @@ #include -#include #include int sigfillset(sigset_t *set) diff --git a/src/signal/sighold.c b/src/signal/sighold.c index 5b0f6b1..cfa2306 100644 --- a/src/signal/sighold.c +++ b/src/signal/sighold.c @@ -1,5 +1,4 @@ #include -#include int sighold(int sig) { @@ -7,5 +6,5 @@ int sighold(int sig) sigemptyset(&mask); if (sigaddset(&mask, sig) < 0) return -1; - return sigprocmask(SIG_BLOCK, &mask, NULL); + return sigprocmask(SIG_BLOCK, &mask, 0); } diff --git a/src/signal/sigignore.c b/src/signal/sigignore.c index 98dff61..5ba05e1 100644 --- a/src/signal/sigignore.c +++ b/src/signal/sigignore.c @@ -1,5 +1,4 @@ #include -#include int sigignore(int sig) { @@ -8,5 +7,5 @@ int sigignore(int sig) sigemptyset(&sa.sa_mask); sa.sa_handler = SIG_IGN; sa.sa_flags = 0; - return sigaction(sig, &sa, NULL); + return sigaction(sig, &sa, 0); } diff --git a/src/signal/siginterrupt.c b/src/signal/siginterrupt.c index 60b3405..7006340 100644 --- a/src/signal/siginterrupt.c +++ b/src/signal/siginterrupt.c @@ -1,13 +1,12 @@ -#include #include int siginterrupt(int sig, int flag) { struct sigaction sa; - sigaction(sig, NULL, &sa); + sigaction(sig, 0, &sa); if (flag) sa.sa_flags &= ~SA_RESTART; else sa.sa_flags |= SA_RESTART; - return sigaction(sig, &sa, NULL); + return sigaction(sig, &sa, 0); } diff --git a/src/signal/sigismember.c b/src/signal/sigismember.c index dd1a8db..ab87d62 100644 --- a/src/signal/sigismember.c +++ b/src/signal/sigismember.c @@ -1,5 +1,4 @@ #include -#include int sigismember(const sigset_t *set, int sig) { diff --git a/src/signal/siglongjmp.c b/src/signal/siglongjmp.c index 2974ff7..b644ceb 100644 --- a/src/signal/siglongjmp.c +++ b/src/signal/siglongjmp.c @@ -1,6 +1,5 @@ #include #include -#include #include "syscall.h" #include "pthread_impl.h" diff --git a/src/signal/signal.c b/src/signal/signal.c index 9d2f23a..c0f063e 100644 --- a/src/signal/signal.c +++ b/src/signal/signal.c @@ -1,5 +1,4 @@ #include -#include #include "syscall.h" #include "libc.h" diff --git a/src/signal/sigpause.c b/src/signal/sigpause.c index 6c0f05d..363d2fe 100644 --- a/src/signal/sigpause.c +++ b/src/signal/sigpause.c @@ -1,5 +1,4 @@ #include -#include int sigpause(int sig) { diff --git a/src/signal/sigqueue.c b/src/signal/sigqueue.c index eb4d184..b75f0c5 100644 --- a/src/signal/sigqueue.c +++ b/src/signal/sigqueue.c @@ -1,7 +1,6 @@ #include #include #include -#include #include "syscall.h" #include "pthread_impl.h" diff --git a/src/signal/sigrelse.c b/src/signal/sigrelse.c index b0b3024..b4c5a00 100644 --- a/src/signal/sigrelse.c +++ b/src/signal/sigrelse.c @@ -1,5 +1,4 @@ #include -#include int sigrelse(int sig) { @@ -7,5 +6,5 @@ int sigrelse(int sig) sigemptyset(&mask); if (sigaddset(&mask, sig) < 0) return -1; - return sigprocmask(SIG_UNBLOCK, &mask, NULL); + return sigprocmask(SIG_UNBLOCK, &mask, 0); } diff --git a/src/signal/sigset.c b/src/signal/sigset.c index 1b6b38f..0d7b456 100644 --- a/src/signal/sigset.c +++ b/src/signal/sigset.c @@ -1,5 +1,4 @@ #include -#include void (*sigset(int sig, void (*handler)(int)))(int) { @@ -11,7 +10,7 @@ void (*sigset(int sig, void (*handler)(int)))(int) return SIG_ERR; if (handler == SIG_HOLD) { - if (sigaction(sig, NULL, &sa_old) < 0) + if (sigaction(sig, 0, &sa_old) < 0) return SIG_ERR; if (sigprocmask(SIG_BLOCK, &mask, &mask) < 0) return SIG_ERR; diff --git a/src/signal/sigsetjmp.c b/src/signal/sigsetjmp.c index 6a5f6f1..cb2257f 100644 --- a/src/signal/sigsetjmp.c +++ b/src/signal/sigsetjmp.c @@ -1,6 +1,5 @@ #include #include -#include /* !!! This function will not work unless the compiler performs * tail call optimization. Machine-specific asm versions should diff --git a/src/signal/sigwait.c b/src/signal/sigwait.c index 48a855b..c8822ee 100644 --- a/src/signal/sigwait.c +++ b/src/signal/sigwait.c @@ -1,10 +1,9 @@ #include -#include int sigwait(const sigset_t *restrict mask, int *restrict sig) { siginfo_t si; - if (sigtimedwait(mask, &si, NULL) < 0) + if (sigtimedwait(mask, &si, 0) < 0) return -1; *sig = si.si_signo; return 0; diff --git a/src/signal/sigwaitinfo.c b/src/signal/sigwaitinfo.c index c7b164d..bb51f8b 100644 --- a/src/signal/sigwaitinfo.c +++ b/src/signal/sigwaitinfo.c @@ -1,7 +1,6 @@ #include -#include int sigwaitinfo(const sigset_t *restrict mask, siginfo_t *restrict si) { - return sigtimedwait(mask, si, NULL); + return sigtimedwait(mask, si, 0); } diff --git a/src/stat/fchmodat.c b/src/stat/fchmodat.c index aeb50bc..12e7ff0 100644 --- a/src/stat/fchmodat.c +++ b/src/stat/fchmodat.c @@ -1,7 +1,6 @@ #include #include #include -#include #include "syscall.h" void __procfdname(char *, unsigned); diff --git a/src/stat/futimesat.c b/src/stat/futimesat.c index 0cc1854..dbefc84 100644 --- a/src/stat/futimesat.c +++ b/src/stat/futimesat.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include #include "syscall.h" diff --git a/src/stat/lchmod.c b/src/stat/lchmod.c index c35f586..f324ba7 100644 --- a/src/stat/lchmod.c +++ b/src/stat/lchmod.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include #include diff --git a/src/stdio/fgetln.c b/src/stdio/fgetln.c index a2e4bd3..afe12b5 100644 --- a/src/stdio/fgetln.c +++ b/src/stdio/fgetln.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include "stdio_impl.h" #include diff --git a/src/stdio/fwide.c b/src/stdio/fwide.c index 4848068..fdf8e4b 100644 --- a/src/stdio/fwide.c +++ b/src/stdio/fwide.c @@ -1,3 +1,4 @@ +#include #include "stdio_impl.h" #define SH (8*sizeof(int)-1) diff --git a/src/stdio/swprintf.c b/src/stdio/swprintf.c index cbf83d2..f75eb11 100644 --- a/src/stdio/swprintf.c +++ b/src/stdio/swprintf.c @@ -1,4 +1,3 @@ -#include #include #include diff --git a/src/stdio/swscanf.c b/src/stdio/swscanf.c index c798609..d893fba 100644 --- a/src/stdio/swscanf.c +++ b/src/stdio/swscanf.c @@ -1,4 +1,3 @@ -#include #include #include #include "libc.h" diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c index a2b287b..b5948bd 100644 --- a/src/stdio/vfprintf.c +++ b/src/stdio/vfprintf.c @@ -530,7 +530,6 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, /* Check validity of argument type (nl/normal) */ if (st==NOARG) { if (argpos>=0) return -1; - else if (!f) continue; } else { if (argpos>=0) nl_type[argpos]=st, arg=nl_arg[argpos]; else if (f) pop_arg(&arg, st, ap); @@ -660,8 +659,12 @@ int vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap) unsigned char internal_buf[80], *saved_buf = 0; int ret; + /* the copy allows passing va_list* even if va_list is an array */ va_copy(ap2, ap); - if (printf_core(0, fmt, &ap2, nl_arg, nl_type) < 0) return -1; + if (printf_core(0, fmt, &ap2, nl_arg, nl_type) < 0) { + va_end(ap2); + return -1; + } FLOCK(f); if (!f->buf_size) { diff --git a/src/stdio/vfscanf.c b/src/stdio/vfscanf.c index c0e607f..0091a8d 100644 --- a/src/stdio/vfscanf.c +++ b/src/stdio/vfscanf.c @@ -5,10 +5,7 @@ #include #include #include -#include -#include -#include -#include +#include #include "stdio_impl.h" #include "shgetc.h" diff --git a/src/stdio/vfwprintf.c b/src/stdio/vfwprintf.c index eb07931..984ff7b 100644 --- a/src/stdio/vfwprintf.c +++ b/src/stdio/vfwprintf.c @@ -167,7 +167,7 @@ static const char sizeprefix['y'-'a'] = { static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_arg, int *nl_type) { - wchar_t *a, *z, *s=(wchar_t *)fmt, *s0; + wchar_t *a, *z, *s=(wchar_t *)fmt; unsigned l10n=0, litpct, fl; int w, p; union arg arg; @@ -242,7 +242,6 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_ } else p = -1; /* Format specifier state machine */ - s0=s; st=0; do { if (OOB(*s)) return -1; @@ -254,7 +253,6 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_ /* Check validity of argument type (nl/normal) */ if (st==NOARG) { if (argpos>=0) return -1; - else if (!f) continue; } else { if (argpos>=0) nl_type[argpos]=st, arg=nl_arg[argpos]; else if (f) pop_arg(&arg, st, ap); @@ -288,8 +286,7 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_ case 'S': a = arg.p; z = wmemchr(a, 0, p); - if (!z) z=a+p; - else p=z-a; + if (z) p=z-a; if (w #include #include -#include -#include -#include #include "stdio_impl.h" #include "shgetc.h" diff --git a/src/stdlib/ecvt.c b/src/stdlib/ecvt.c index 79c3de6..797b664 100644 --- a/src/stdlib/ecvt.c +++ b/src/stdlib/ecvt.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include #include diff --git a/src/stdlib/gcvt.c b/src/stdlib/gcvt.c index 6c075e2..f29bc30 100644 --- a/src/stdlib/gcvt.c +++ b/src/stdlib/gcvt.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include #include diff --git a/src/stdlib/wcstod.c b/src/stdlib/wcstod.c index 83f308d..26fe9af 100644 --- a/src/stdlib/wcstod.c +++ b/src/stdlib/wcstod.c @@ -1,6 +1,7 @@ #include "shgetc.h" #include "floatscan.h" #include "stdio_impl.h" +#include #include /* This read function heavily cheats. It knows: diff --git a/src/string/bcmp.c b/src/string/bcmp.c index 5d6a388..87c6007 100644 --- a/src/string/bcmp.c +++ b/src/string/bcmp.c @@ -1,3 +1,4 @@ +#define _BSD_SOURCE #include #include diff --git a/src/string/bcopy.c b/src/string/bcopy.c index e76272f..a07129f 100644 --- a/src/string/bcopy.c +++ b/src/string/bcopy.c @@ -1,3 +1,4 @@ +#define _BSD_SOURCE #include #include diff --git a/src/string/bzero.c b/src/string/bzero.c index 0f98b4a..ba536b0 100644 --- a/src/string/bzero.c +++ b/src/string/bzero.c @@ -1,3 +1,4 @@ +#define _BSD_SOURCE #include #include diff --git a/src/string/index.c b/src/string/index.c index dd61125..252948f 100644 --- a/src/string/index.c +++ b/src/string/index.c @@ -1,3 +1,4 @@ +#define _BSD_SOURCE #include #include diff --git a/src/string/memccpy.c b/src/string/memccpy.c index b85009c..7c233d5 100644 --- a/src/string/memccpy.c +++ b/src/string/memccpy.c @@ -1,5 +1,4 @@ #include -#include #include #include diff --git a/src/string/memchr.c b/src/string/memchr.c index a0472f7..4daff7b 100644 --- a/src/string/memchr.c +++ b/src/string/memchr.c @@ -1,5 +1,4 @@ #include -#include #include #include diff --git a/src/string/memmem.c b/src/string/memmem.c index 861fef2..5211d75 100644 --- a/src/string/memmem.c +++ b/src/string/memmem.c @@ -1,6 +1,5 @@ #define _GNU_SOURCE #include -#include #include static char *twobyte_memmem(const unsigned char *h, size_t k, const unsigned char *n) diff --git a/src/string/mempcpy.c b/src/string/mempcpy.c index c23ca69..a297985 100644 --- a/src/string/mempcpy.c +++ b/src/string/mempcpy.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include void *mempcpy(void *dest, const void *src, size_t n) diff --git a/src/string/rindex.c b/src/string/rindex.c index 17df2bf..693c750 100644 --- a/src/string/rindex.c +++ b/src/string/rindex.c @@ -1,3 +1,4 @@ +#define _BSD_SOURCE #include #include diff --git a/src/string/stpcpy.c b/src/string/stpcpy.c index feb9eb8..06623c4 100644 --- a/src/string/stpcpy.c +++ b/src/string/stpcpy.c @@ -1,5 +1,4 @@ #include -#include #include #include #include "libc.h" diff --git a/src/string/stpncpy.c b/src/string/stpncpy.c index 0a2c2a9..1f57a4d 100644 --- a/src/string/stpncpy.c +++ b/src/string/stpncpy.c @@ -1,5 +1,4 @@ #include -#include #include #include #include "libc.h" diff --git a/src/string/strchrnul.c b/src/string/strchrnul.c index ceae4d4..05700ad 100644 --- a/src/string/strchrnul.c +++ b/src/string/strchrnul.c @@ -1,5 +1,4 @@ #include -#include #include #include #include "libc.h" diff --git a/src/string/strcmp.c b/src/string/strcmp.c index 91eb740..808bd83 100644 --- a/src/string/strcmp.c +++ b/src/string/strcmp.c @@ -2,6 +2,6 @@ int strcmp(const char *l, const char *r) { - for (; *l==*r && *l && *r; l++, r++); + for (; *l==*r && *l; l++, r++); return *(unsigned char *)l - *(unsigned char *)r; } diff --git a/src/string/strlcpy.c b/src/string/strlcpy.c index 4d3ff92..193d724 100644 --- a/src/string/strlcpy.c +++ b/src/string/strlcpy.c @@ -1,5 +1,5 @@ +#define _BSD_SOURCE #include -#include #include #include #include "libc.h" diff --git a/src/string/strlen.c b/src/string/strlen.c index d6f8631..929ddcb 100644 --- a/src/string/strlen.c +++ b/src/string/strlen.c @@ -1,5 +1,4 @@ #include -#include #include #include diff --git a/src/string/strstr.c b/src/string/strstr.c index 0649174..915c0a2 100644 --- a/src/string/strstr.c +++ b/src/string/strstr.c @@ -1,5 +1,4 @@ #include -#include #include static char *twobyte_strstr(const unsigned char *h, const unsigned char *n) diff --git a/src/string/strverscmp.c b/src/string/strverscmp.c index 94d2e15..6f37cc6 100644 --- a/src/string/strverscmp.c +++ b/src/string/strverscmp.c @@ -1,7 +1,6 @@ #define _GNU_SOURCE #include #include -#include int strverscmp(const char *l, const char *r) { diff --git a/src/string/wcsstr.c b/src/string/wcsstr.c index 037d096..3e28e28 100644 --- a/src/string/wcsstr.c +++ b/src/string/wcsstr.c @@ -1,7 +1,4 @@ #include -#include -#include -#include #define MAX(a,b) ((a)>(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b)) diff --git a/src/string/wmemchr.c b/src/string/wmemchr.c index 37d6962..2bc2c27 100644 --- a/src/string/wmemchr.c +++ b/src/string/wmemchr.c @@ -1,4 +1,3 @@ -#include #include wchar_t *wmemchr(const wchar_t *s, wchar_t c, size_t n) diff --git a/src/string/wmemcmp.c b/src/string/wmemcmp.c index 6788a38..2a19326 100644 --- a/src/string/wmemcmp.c +++ b/src/string/wmemcmp.c @@ -1,4 +1,3 @@ -#include #include int wmemcmp(const wchar_t *l, const wchar_t *r, size_t n) diff --git a/src/string/wmemcpy.c b/src/string/wmemcpy.c index 55a8e1d..52e6e6e 100644 --- a/src/string/wmemcpy.c +++ b/src/string/wmemcpy.c @@ -1,4 +1,3 @@ -#include #include wchar_t *wmemcpy(wchar_t *restrict d, const wchar_t *restrict s, size_t n) diff --git a/src/string/wmemmove.c b/src/string/wmemmove.c index cde4fee..e406f3d 100644 --- a/src/string/wmemmove.c +++ b/src/string/wmemmove.c @@ -1,4 +1,3 @@ -#include #include wchar_t *wmemmove(wchar_t *d, const wchar_t *s, size_t n) diff --git a/src/string/wmemset.c b/src/string/wmemset.c index 1a2a861..07a037a 100644 --- a/src/string/wmemset.c +++ b/src/string/wmemset.c @@ -1,4 +1,3 @@ -#include #include wchar_t *wmemset(wchar_t *d, wchar_t c, size_t n) diff --git a/src/temp/__randname.c b/src/temp/__randname.c index 38c99d3..464b83d 100644 --- a/src/temp/__randname.c +++ b/src/temp/__randname.c @@ -1,4 +1,3 @@ -#include #include #include diff --git a/src/temp/mkdtemp.c b/src/temp/mkdtemp.c index 195e9cb..6c2c16e 100644 --- a/src/temp/mkdtemp.c +++ b/src/temp/mkdtemp.c @@ -1,12 +1,7 @@ #include -#include #include -#include -#include -#include #include #include -#include "libc.h" char *__randname(char *); diff --git a/src/temp/mktemp.c b/src/temp/mktemp.c index 67130e1..4ab0df2 100644 --- a/src/temp/mktemp.c +++ b/src/temp/mktemp.c @@ -1,6 +1,6 @@ +#define _GNU_SOURCE #include -#include -#include +#include #include #include diff --git a/src/termios/tcgetattr.c b/src/termios/tcgetattr.c index d9ce786..545a0bf 100644 --- a/src/termios/tcgetattr.c +++ b/src/termios/tcgetattr.c @@ -1,6 +1,5 @@ #include #include -#include int tcgetattr(int fd, struct termios *tio) { diff --git a/src/termios/tcsetattr.c b/src/termios/tcsetattr.c index e9a168f..94df18f 100644 --- a/src/termios/tcsetattr.c +++ b/src/termios/tcsetattr.c @@ -1,6 +1,5 @@ #include #include -#include #include int tcsetattr(int fd, int act, const struct termios *tio) diff --git a/src/thread/pthread_attr_init.c b/src/thread/pthread_attr_init.c index 6693488..969e0a3 100644 --- a/src/thread/pthread_attr_init.c +++ b/src/thread/pthread_attr_init.c @@ -1,5 +1,4 @@ #include "pthread_impl.h" -#include int pthread_attr_init(pthread_attr_t *a) { diff --git a/src/thread/pthread_key_create.c b/src/thread/pthread_key_create.c index e51cb02..c29935c 100644 --- a/src/thread/pthread_key_create.c +++ b/src/thread/pthread_key_create.c @@ -17,7 +17,7 @@ int pthread_key_create(pthread_key_t *k, void (*dtor)(void *)) __pthread_self_init(); if (!dtor) dtor = nodtor; do { - if (!a_cas_p(keys+j, 0, dtor)) { + if (!a_cas_p(keys+j, 0, (void *)dtor)) { *k = j; return 0; } diff --git a/src/thread/pthread_sigmask.c b/src/thread/pthread_sigmask.c index b274bd0..88c333f 100644 --- a/src/thread/pthread_sigmask.c +++ b/src/thread/pthread_sigmask.c @@ -1,6 +1,5 @@ #include #include -#include #include "syscall.h" int pthread_sigmask(int how, const sigset_t *restrict set, sigset_t *restrict old) diff --git a/src/thread/synccall.c b/src/thread/synccall.c index 4127a41..a21578d 100644 --- a/src/thread/synccall.c +++ b/src/thread/synccall.c @@ -1,6 +1,5 @@ #include "pthread_impl.h" #include -#include static struct chain { struct chain *next; diff --git a/src/time/__map_file.c b/src/time/__map_file.c index b322f09..84ae839 100644 --- a/src/time/__map_file.c +++ b/src/time/__map_file.c @@ -9,7 +9,7 @@ const char unsigned *__map_file(const char *pathname, size_t *size) { struct stat st; const unsigned char *map = MAP_FAILED; - int flags = O_RDONLY|O_LARGEFILE|O_CLOEXEC|O_NOFOLLOW|O_NONBLOCK; + int flags = O_RDONLY|O_LARGEFILE|O_CLOEXEC|O_NONBLOCK; int fd = __syscall(SYS_open, pathname, flags); if (fd < 0) return 0; if (!__syscall(SYS_fstat, fd, &st)) diff --git a/src/time/__tz.c b/src/time/__tz.c index 81676d3..9d56a61 100644 --- a/src/time/__tz.c +++ b/src/time/__tz.c @@ -138,7 +138,7 @@ static void do_tzset() * free so as not to pull it into static programs. Growth * strategy makes it so free would have minimal benefit anyway. */ i = strlen(s); - if (i > PATH_MAX+1) s = "", i = 0; + if (i > PATH_MAX+1) s = __gmt, i = 3; if (i >= old_tz_size) { old_tz_size *= 2; if (i >= old_tz_size) old_tz_size = i+1; @@ -162,7 +162,7 @@ static void do_tzset() break; memcpy(pathname, s, l+1); pathname[l] = 0; - for (try=search; !map && *try; try+=l) { + for (try=search; !map && *try; try+=l+1) { l = strlen(try); memcpy(pathname-l, try, l); map = __map_file(pathname-l, &map_size); @@ -176,8 +176,8 @@ static void do_tzset() if (map) { int scale = 2; if (sizeof(time_t) > 4 && map[4]=='2') { - size_t skip = zi_dotprod(zi, VEC(1,1,8,5,6,1), 6); - trans = zi+skip+44+20; + size_t skip = zi_dotprod(zi+20, VEC(1,1,8,5,6,1), 6); + trans = zi+skip+44+44; scale++; } else { trans = zi+44; diff --git a/src/time/ftime.c b/src/time/ftime.c new file mode 100644 index 0000000..a1734d0 --- /dev/null +++ b/src/time/ftime.c @@ -0,0 +1,12 @@ +#include +#include + +int ftime(struct timeb *tp) +{ + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + tp->time = ts.tv_sec; + tp->millitm = ts.tv_nsec / 1000000; + tp->timezone = tp->dstflag = 0; + return 0; +} diff --git a/src/time/mktime.c b/src/time/mktime.c index ef1fb42..0ab4780 100644 --- a/src/time/mktime.c +++ b/src/time/mktime.c @@ -1,7 +1,5 @@ #include "time_impl.h" #include -#include -#include time_t mktime(struct tm *tm) { diff --git a/src/time/nanosleep.c b/src/time/nanosleep.c index c8878b1..a2ff483 100644 --- a/src/time/nanosleep.c +++ b/src/time/nanosleep.c @@ -1,4 +1,3 @@ -#include #include #include "syscall.h" #include "libc.h" diff --git a/src/time/strftime.c b/src/time/strftime.c index dac6403..bc15013 100644 --- a/src/time/strftime.c +++ b/src/time/strftime.c @@ -216,7 +216,7 @@ size_t __strftime_l(char *restrict s, size_t n, const char *restrict f, const st const char *t; int plus; unsigned long width; - for (l=0; l+1= n-l) return 0; } else { width = 0; } f = p; if (*f == 'E' || *f == 'O') f++; t = __strftime_fmt_1(&buf, &k, *f, tm, loc); - if (!t) return 0; + if (!t) break; if (width) { for (; *t=='+' || *t=='-' || (*t=='0'&&t[1]); t++, k--); width--; @@ -247,14 +246,17 @@ size_t __strftime_l(char *restrict s, size_t n, const char *restrict f, const st s[l++] = '-'; else width++; - if (width >= n-l) return 0; - for (; width > k; width--) + for (; width > k && l < n; width--) s[l++] = '0'; } - if (k >= n-l) return 0; + if (k > n-l) k = n-l; memcpy(s+l, t, k); l += k; } + if (n) { + if (l==n) l=n-1; + s[l] = 0; + } return 0; } diff --git a/src/time/strptime.c b/src/time/strptime.c index 0f66e6c..d1d141e 100644 --- a/src/time/strptime.c +++ b/src/time/strptime.c @@ -1,4 +1,3 @@ -#include #include #include #include diff --git a/src/time/time.c b/src/time/time.c index 2275485..4b95e75 100644 --- a/src/time/time.c +++ b/src/time/time.c @@ -1,5 +1,4 @@ #include -#include #include "syscall.h" int __clock_gettime(clockid_t, struct timespec *); diff --git a/src/time/wcsftime.c b/src/time/wcsftime.c index 72af913..8d2a2eb 100644 --- a/src/time/wcsftime.c +++ b/src/time/wcsftime.c @@ -1,6 +1,5 @@ #include #include -#include #include #include "libc.h" @@ -16,7 +15,7 @@ size_t __wcsftime_l(wchar_t *restrict s, size_t n, const wchar_t *restrict f, co const wchar_t *t; int plus; unsigned long width; - for (l=0; l+1= n-l) return 0; } else { width = 0; } f = p; if (*f == 'E' || *f == 'O') f++; t_mb = __strftime_fmt_1(&buf, &k, *f, tm, loc); - if (!t_mb) return 0; + if (!t_mb) break; k = mbstowcs(wbuf, t_mb, sizeof wbuf / sizeof *wbuf); if (k == (size_t)-1) return 0; t = wbuf; @@ -50,14 +48,17 @@ size_t __wcsftime_l(wchar_t *restrict s, size_t n, const wchar_t *restrict f, co s[l++] = '-'; else width++; - if (width >= n-l) return 0; - for (; width > k; width--) + for (; width > k && l < n; width--) s[l++] = '0'; } - if (k >= n-l) return 0; + if (k >= n-l) k = n-l; wmemcpy(s+l, t, k); l += k; } + if (n) { + if (l==n) l=n-1; + s[l] = 0; + } return 0; } diff --git a/src/unistd/ctermid.c b/src/unistd/ctermid.c index ffa9b75..7768405 100644 --- a/src/unistd/ctermid.c +++ b/src/unistd/ctermid.c @@ -1,6 +1,4 @@ #include -#include -#include #include #include #include diff --git a/src/unistd/faccessat.c b/src/unistd/faccessat.c index 5b2c5e3..3347895 100644 --- a/src/unistd/faccessat.c +++ b/src/unistd/faccessat.c @@ -1,5 +1,7 @@ #include #include +#include +#include #include "syscall.h" #include "pthread_impl.h" @@ -7,19 +9,26 @@ struct ctx { int fd; const char *filename; int amode; - int p; +}; + +static const int errors[] = { + 0, -EACCES, -ELOOP, -ENAMETOOLONG, -ENOENT, -ENOTDIR, + -EROFS, -EBADF, -EINVAL, -ETXTBSY, + -EFAULT, -EIO, -ENOMEM, + -EBUSY }; static int checker(void *p) { struct ctx *c = p; int ret; - if (__syscall(SYS_setgid, __syscall(SYS_getegid)) - || __syscall(SYS_setuid, __syscall(SYS_geteuid))) + int i; + if (__syscall(SYS_setregid, __syscall(SYS_getegid), -1) + || __syscall(SYS_setreuid, __syscall(SYS_geteuid), -1)) __syscall(SYS_exit, 1); ret = __syscall(SYS_faccessat, c->fd, c->filename, c->amode, 0); - __syscall(SYS_write, c->p, &ret, sizeof ret); - return 0; + for (i=0; i < sizeof errors/sizeof *errors - 1 && ret!=errors[i]; i++); + return i; } int faccessat(int fd, const char *filename, int amode, int flag) @@ -32,19 +41,21 @@ int faccessat(int fd, const char *filename, int amode, int flag) char stack[1024]; sigset_t set; - int ret, p[2]; - - if (pipe(p)) return __syscall_ret(-EBUSY); - struct ctx c = { .fd = fd, .filename = filename, .amode = amode, .p = p[1] }; + pid_t pid; + int ret = -EBUSY; + struct ctx c = { .fd = fd, .filename = filename, .amode = amode }; __block_all_sigs(&set); - ret = __clone(checker, stack+sizeof stack, 0, &c); - __syscall(SYS_close, p[1]); - - if (ret<0 || __syscall(SYS_read, p[0], &ret, sizeof ret) != sizeof(ret)) - ret = -EBUSY; - __syscall(SYS_close, p[0]); + pid = __clone(checker, stack+sizeof stack, 0, &c); + if (pid > 0) { + int status; + do { + __syscall(SYS_wait4, pid, &status, __WCLONE, 0); + } while (!WIFEXITED(status) && !WIFSIGNALED(status)); + if (WIFEXITED(status)) + ret = errors[WEXITSTATUS(status)]; + } __restore_sigs(&set); diff --git a/src/unistd/getcwd.c b/src/unistd/getcwd.c index 2e540cd..a7b925d 100644 --- a/src/unistd/getcwd.c +++ b/src/unistd/getcwd.c @@ -7,7 +7,13 @@ char *getcwd(char *buf, size_t size) { char tmp[PATH_MAX]; - if (!buf) buf = tmp, size = PATH_MAX; + if (!buf) { + buf = tmp; + size = PATH_MAX; + } else if (!size) { + errno = EINVAL; + return 0; + } if (syscall(SYS_getcwd, buf, size) < 0) return 0; return buf == tmp ? strdup(buf) : buf; } diff --git a/src/unistd/gethostname.c b/src/unistd/gethostname.c index a406c4e..f984b7d 100644 --- a/src/unistd/gethostname.c +++ b/src/unistd/gethostname.c @@ -1,6 +1,5 @@ #include #include -#include int gethostname(char *name, size_t len) { diff --git a/src/unistd/getlogin_r.c b/src/unistd/getlogin_r.c index 37ce0d4..53866c6 100644 --- a/src/unistd/getlogin_r.c +++ b/src/unistd/getlogin_r.c @@ -1,5 +1,4 @@ #include -#include #include #include diff --git a/src/unistd/posix_close.c b/src/unistd/posix_close.c new file mode 100644 index 0000000..90f51a8 --- /dev/null +++ b/src/unistd/posix_close.c @@ -0,0 +1,6 @@ +#include + +int posix_close(int fd, int flags) +{ + return close(fd); +} diff --git a/src/unistd/ttyname_r.c b/src/unistd/ttyname_r.c index a2ce351..8bac7b2 100644 --- a/src/unistd/ttyname_r.c +++ b/src/unistd/ttyname_r.c @@ -1,7 +1,5 @@ #include #include -#include -#include void __procfdname(char *, unsigned); diff --git a/src/unistd/usleep.c b/src/unistd/usleep.c index ce1c814..6c96652 100644 --- a/src/unistd/usleep.c +++ b/src/unistd/usleep.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include #include diff --git a/tools/install.sh b/tools/install.sh index 7dcea33..4e5a8b9 100755 --- a/tools/install.sh +++ b/tools/install.sh @@ -53,7 +53,7 @@ else cat < "$1" > "$tmp" fi -mv "$tmp" "$2" +mv -f "$tmp" "$2" test -d "$2" && { rm -f "$2/$tmp" printf "%s: %s is a directory\n" "$0" "$dst" 1>&2 diff --git a/tools/version.sh b/tools/version.sh new file mode 100644 index 0000000..f1cc594 --- /dev/null +++ b/tools/version.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +if test -d .git ; then +if type git >/dev/null 2>&1 ; then +git describe --tags --match 'v[0-9]*' 2>/dev/null \ +| sed -e 's/^v//' -e 's/-/-git-/' +else +sed 's/$/-git/' < VERSION +fi +else +cat VERSION +fi