Merge "implement missing seekdir and telldir"
authorYabin Cui <yabinc@google.com>
Wed, 12 Nov 2014 20:36:25 +0000 (20:36 +0000)
committerGerrit Code Review <noreply-gerritcodereview@google.com>
Wed, 12 Nov 2014 20:36:26 +0000 (20:36 +0000)
49 files changed:
libc/Android.mk
libc/SYSCALLS.TXT
libc/arch-arm/syscalls/sethostname.S [new file with mode: 0644]
libc/arch-arm64/syscalls/sethostname.S [new file with mode: 0644]
libc/arch-mips/syscalls/sethostname.S [new file with mode: 0644]
libc/arch-mips64/syscalls/sethostname.S [new file with mode: 0644]
libc/arch-x86/syscalls/sethostname.S [new file with mode: 0644]
libc/arch-x86_64/syscalls/sethostname.S [new file with mode: 0644]
libc/bionic/gethostname.cpp [moved from libc/bionic/gethostname.c with 78% similarity]
libc/bionic/locale.cpp
libc/bionic/strcoll_l.cpp [deleted file]
libc/bionic/strftime_l.cpp [deleted file]
libc/bionic/strtold_l.cpp [deleted file]
libc/bionic/strtoll_l.cpp [deleted file]
libc/bionic/strtoull_l.cpp [deleted file]
libc/bionic/strxfrm_l.cpp [deleted file]
libc/dns/gethnamaddr.c
libc/dns/include/resolv_cache.h
libc/dns/include/resolv_netid.h
libc/dns/include/resolv_private.h
libc/dns/net/getaddrinfo.c
libc/dns/resolv/res_cache.c
libc/dns/resolv/res_send.c
libc/include/dirent.h
libc/include/stdlib.h
libc/include/string.h
libc/include/strings.h
libc/include/sys/_system_properties.h
libc/include/sys/stat.h
libc/include/unistd.h
libc/include/wchar.h
libc/kernel/uapi/linux/ion.h
libc/private/bionic_macros.h
libc/tools/check-symbols-glibc.py
libc/tools/posix-2013.txt [new file with mode: 0644]
libc/tools/zoneinfo/ZoneCompactor.java
libc/tools/zoneinfo/update-tzdata.py
libc/upstream-netbsd/lib/libc/stdlib/lcong48.c [new file with mode: 0644]
libc/zoneinfo/tzdata
libm/Android.mk
libm/include/complex.h
libm/upstream-freebsd/lib/msun/src/catrig.c [new file with mode: 0644]
libm/upstream-freebsd/lib/msun/src/catrigf.c [new file with mode: 0644]
tests/Android.mk
tests/complex_test.cpp [new file with mode: 0644]
tests/stdlib_test.cpp
tests/string_test.cpp
tests/strings_test.cpp
tests/unistd_test.cpp

index d0441456e6600ff654f89e53f58251afa25da12d..345a1f3f036756918ff6d84f6cac3ec5a16b3230 100644 (file)
@@ -43,7 +43,6 @@ libc_common_src_files := \
     bionic/ether_aton.c \
     bionic/ether_ntoa.c \
     bionic/fts.c \
-    bionic/gethostname.c \
     bionic/getpriority.c \
     bionic/if_indextoname.c \
     bionic/if_nametoindex.c \
@@ -120,6 +119,7 @@ libc_bionic_src_files := \
     bionic/getauxval.cpp \
     bionic/getcwd.cpp \
     bionic/getentropy_linux.c \
+    bionic/gethostname.cpp \
     bionic/getpgrp.cpp \
     bionic/getpid.cpp \
     bionic/gettid.cpp \
@@ -206,16 +206,10 @@ libc_bionic_src_files := \
     bionic/socket.cpp \
     bionic/stat.cpp \
     bionic/statvfs.cpp \
-    bionic/strcoll_l.cpp \
     bionic/strerror.cpp \
     bionic/strerror_r.cpp \
-    bionic/strftime_l.cpp \
     bionic/strsignal.cpp \
     bionic/strtold.cpp \
-    bionic/strtold_l.cpp \
-    bionic/strtoll_l.cpp \
-    bionic/strtoull_l.cpp \
-    bionic/strxfrm_l.cpp \
     bionic/stubs.cpp \
     bionic/symlink.cpp \
     bionic/sysconf.cpp \
@@ -290,6 +284,7 @@ libc_upstream_netbsd_src_files := \
     upstream-netbsd/lib/libc/stdlib/drand48.c \
     upstream-netbsd/lib/libc/stdlib/erand48.c \
     upstream-netbsd/lib/libc/stdlib/jrand48.c \
+    upstream-netbsd/lib/libc/stdlib/lcong48.c \
     upstream-netbsd/lib/libc/stdlib/ldiv.c \
     upstream-netbsd/lib/libc/stdlib/lldiv.c \
     upstream-netbsd/lib/libc/stdlib/lrand48.c \
index 866671d6a400d5d616eede14d39eb6d01e76393d..39ff37de0e387a64ce4a948961689f5a5e912e48 100644 (file)
@@ -313,6 +313,8 @@ int __set_tid_address:set_tid_address(int*)  all
 int setfsgid(gid_t)  all
 int setfsuid(uid_t)  all
 
+int sethostname(const char*, size_t)  all
+
 pid_t wait4(pid_t, int*, int, struct rusage*)  all
 int __waitid:waitid(int, pid_t, struct siginfo_t*, int, void*)  all
 
diff --git a/libc/arch-arm/syscalls/sethostname.S b/libc/arch-arm/syscalls/sethostname.S
new file mode 100644 (file)
index 0000000..0a98fd3
--- /dev/null
@@ -0,0 +1,14 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(sethostname)
+    mov     ip, r7
+    ldr     r7, =__NR_sethostname
+    swi     #0
+    mov     r7, ip
+    cmn     r0, #(MAX_ERRNO + 1)
+    bxls    lr
+    neg     r0, r0
+    b       __set_errno_internal
+END(sethostname)
diff --git a/libc/arch-arm64/syscalls/sethostname.S b/libc/arch-arm64/syscalls/sethostname.S
new file mode 100644 (file)
index 0000000..2dea457
--- /dev/null
@@ -0,0 +1,14 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(sethostname)
+    mov     x8, __NR_sethostname
+    svc     #0
+
+    cmn     x0, #(MAX_ERRNO + 1)
+    cneg    x0, x0, hi
+    b.hi    __set_errno_internal
+
+    ret
+END(sethostname)
diff --git a/libc/arch-mips/syscalls/sethostname.S b/libc/arch-mips/syscalls/sethostname.S
new file mode 100644 (file)
index 0000000..2987b52
--- /dev/null
@@ -0,0 +1,19 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(sethostname)
+    .set noreorder
+    .cpload t9
+    li v0, __NR_sethostname
+    syscall
+    bnez a3, 1f
+    move a0, v0
+    j ra
+    nop
+1:
+    la t9,__set_errno_internal
+    j t9
+    nop
+    .set reorder
+END(sethostname)
diff --git a/libc/arch-mips64/syscalls/sethostname.S b/libc/arch-mips64/syscalls/sethostname.S
new file mode 100644 (file)
index 0000000..2f132a2
--- /dev/null
@@ -0,0 +1,25 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(sethostname)
+    .set push
+    .set noreorder
+    li v0, __NR_sethostname
+    syscall
+    bnez a3, 1f
+    move a0, v0
+    j ra
+    nop
+1:
+    move t0, ra
+    bal     2f
+    nop
+2:
+    .cpsetup ra, t1, 2b
+    LA t9,__set_errno_internal
+    .cpreturn
+    j t9
+    move ra, t0
+    .set pop
+END(sethostname)
diff --git a/libc/arch-x86/syscalls/sethostname.S b/libc/arch-x86/syscalls/sethostname.S
new file mode 100644 (file)
index 0000000..bfcfd73
--- /dev/null
@@ -0,0 +1,26 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(sethostname)
+    pushl   %ebx
+    .cfi_def_cfa_offset 8
+    .cfi_rel_offset ebx, 0
+    pushl   %ecx
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset ecx, 0
+    mov     12(%esp), %ebx
+    mov     16(%esp), %ecx
+    movl    $__NR_sethostname, %eax
+    int     $0x80
+    cmpl    $-MAX_ERRNO, %eax
+    jb      1f
+    negl    %eax
+    pushl   %eax
+    call    __set_errno_internal
+    addl    $4, %esp
+1:
+    popl    %ecx
+    popl    %ebx
+    ret
+END(sethostname)
diff --git a/libc/arch-x86_64/syscalls/sethostname.S b/libc/arch-x86_64/syscalls/sethostname.S
new file mode 100644 (file)
index 0000000..4bcd12d
--- /dev/null
@@ -0,0 +1,15 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(sethostname)
+    movl    $__NR_sethostname, %eax
+    syscall
+    cmpq    $-MAX_ERRNO, %rax
+    jb      1f
+    negl    %eax
+    movl    %eax, %edi
+    call    __set_errno_internal
+1:
+    ret
+END(sethostname)
similarity index 78%
rename from libc/bionic/gethostname.c
rename to libc/bionic/gethostname.cpp
index 5d3d7d9623e9ca52703de452ac07fc6a4fd1f43d..962fea1b11fbf3e197a7b2feef531e564aae9114 100644 (file)
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+
 #include <errno.h>
-#include <unistd.h>
 #include <string.h>
 #include <sys/utsname.h>
+#include <unistd.h>
 
-int gethostname(char*  buff, size_t  buflen)
-{
-    struct utsname  name;
-    int             result = 0;
+int gethostname(char* buf, size_t n) {
+  struct utsname name;
+  if (uname(&name) == -1) {
+    return -1;
+  }
 
-    result = uname(&name);
-    if (result != -1)
-    {
-        int  namelen = strlen(name.nodename);
+  size_t name_length = static_cast<size_t>(strlen(name.nodename) + 1);
+  if (name_length > n) {
+    errno = ENAMETOOLONG;
+    return -1;
+  }
 
-        if ((int)buflen < namelen+1) {
-            errno = EINVAL;
-            result = -1;
-        } else {
-            memcpy( buff, name.nodename, namelen+1 );
-        }
-    }
-    return result;
+  memcpy(buf, name.nodename, name_length);
+  return 0;
 }
index b4a3472d739b74f230ae71bc98531516a7263c91..681e038369cf2a852dd3f3dc3244c6ddb0f17977 100644 (file)
 #include <locale.h>
 #include <pthread.h>
 #include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <time.h>
+#include <wchar.h>
 
 #include "private/bionic_macros.h"
 
@@ -171,3 +175,47 @@ locale_t uselocale(locale_t new_locale) {
 
   return old_locale;
 }
+
+int strcasecmp_l(const char* s1, const char* s2, locale_t) {
+  return strcasecmp(s1, s2);
+}
+
+int strcoll_l(const char* s1, const char* s2, locale_t) {
+  return strcoll(s1, s2);
+}
+
+char* strerror_l(int error, locale_t) {
+  return strerror(error);
+}
+
+size_t strftime_l(char* s, size_t max, const char* format, const struct tm* tm, locale_t) {
+  return strftime(s, max, format, tm);
+}
+
+int strncasecmp_l(const char* s1, const char* s2, size_t n, locale_t) {
+  return strncasecmp(s1, s2, n);
+}
+
+long double strtold_l(const char* s, char** end_ptr, locale_t) {
+  return strtold(s, end_ptr);
+}
+
+long long strtoll_l(const char* s, char** end_ptr, int base, locale_t) {
+  return strtoll(s, end_ptr, base);
+}
+
+unsigned long long strtoull_l(const char* s, char** end_ptr, int base, locale_t) {
+  return strtoull(s, end_ptr, base);
+}
+
+size_t strxfrm_l(char* dst, const char* src, size_t n, locale_t) {
+  return strxfrm(dst, src, n);
+}
+
+int wcscasecmp_l(const wchar_t* ws1, const wchar_t* ws2, locale_t) {
+  return wcscasecmp(ws1, ws2);
+}
+
+int wcsncasecmp_l(const wchar_t* ws1, const wchar_t* ws2, size_t n, locale_t) {
+  return wcsncasecmp(ws1, ws2, n);
+}
diff --git a/libc/bionic/strcoll_l.cpp b/libc/bionic/strcoll_l.cpp
deleted file mode 100644 (file)
index 7d7c28b..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <string.h>
-
-int strcoll_l(const char *s1, const char *s2, locale_t) {
-  return strcoll(s1, s2);
-}
diff --git a/libc/bionic/strftime_l.cpp b/libc/bionic/strftime_l.cpp
deleted file mode 100644 (file)
index fb01da5..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <time.h>
-
-size_t strftime_l(char *s, size_t max, const char *format, const struct tm *tm,
-                  locale_t) {
-  return strftime(s, max, format, tm);
-}
diff --git a/libc/bionic/strtold_l.cpp b/libc/bionic/strtold_l.cpp
deleted file mode 100644 (file)
index 4b230b9..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <stdlib.h>
-
-long double strtold_l(const char *nptr, char **endptr, locale_t) {
-  return strtold(nptr, endptr);
-}
diff --git a/libc/bionic/strtoll_l.cpp b/libc/bionic/strtoll_l.cpp
deleted file mode 100644 (file)
index 47b126e..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <stdlib.h>
-
-long long strtoll_l(const char *nptr, char **endptr, int base, locale_t) {
-  return strtoll(nptr, endptr, base);
-}
diff --git a/libc/bionic/strtoull_l.cpp b/libc/bionic/strtoull_l.cpp
deleted file mode 100644 (file)
index 398ba0e..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <stdlib.h>
-
-unsigned long long strtoull_l(const char *nptr, char **endptr, int base,
-                              locale_t) {
-  return strtoull(nptr, endptr, base);
-}
diff --git a/libc/bionic/strxfrm_l.cpp b/libc/bionic/strxfrm_l.cpp
deleted file mode 100644 (file)
index afe3b96..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <string.h>
-
-size_t strxfrm_l(char *dest, const char *src, size_t n, locale_t) {
-  return strxfrm(dest, src, n);
-}
index cc33c612cb78729c326c6203532155d2c80fa128..0bd838e86249223e2b033a2e0d7eae324ddc14db 100644 (file)
@@ -565,7 +565,7 @@ android_read_hostent(FILE* proxy)
        char buf[4];
        if (fread(buf, 1, sizeof(buf), proxy) != sizeof(buf)) return NULL;
 
-       /* This is reading serialized data from system/netd/DnsProxyListener.cpp
+       /* This is reading serialized data from system/netd/server/DnsProxyListener.cpp
         * and changes here need to be matched there */
        int result_code = strtol(buf, NULL, 10);
        if (result_code != DnsProxyQueryResult) {
@@ -763,7 +763,7 @@ gethostbyname_internal(const char *name, int af, res_state res, unsigned netid,
 
        netid = __netdClientDispatch.netIdForResolv(netid);
 
-       /* This is writing to system/netd/DnsProxyListener.cpp and changes
+       /* This is writing to system/netd/server/DnsProxyListener.cpp and changes
         * here need to be matched there */
        if (fprintf(proxy, "gethostbyname %u %s %d",
                        netid,
index 16f3e43a1207f91560c3044f9fd4275148bad187..e049d951ff9eb06e283c6e642befae4a1c73619b 100644 (file)
 #include <sys/cdefs.h>
 
 struct __res_state;
-struct resolv_cache;  /* forward */
-
-/* Gets the cache for a network. Returned cache might be NULL. */
-__LIBC_HIDDEN__
-extern struct resolv_cache* __get_res_cache(unsigned netid);
 
 /* sets the name server addresses to the provided res_state structure. The
  * name servers are retrieved from the cache which is associated
@@ -53,7 +48,7 @@ typedef enum {
 
 __LIBC_HIDDEN__
 extern ResolvCacheStatus
-_resolv_cache_lookup( struct resolv_cache*  cache,
+_resolv_cache_lookup( unsigned              netid,
                       const void*           query,
                       int                   querylen,
                       void*                 answer,
@@ -65,7 +60,7 @@ _resolv_cache_lookup( struct resolv_cache*  cache,
  */
 __LIBC_HIDDEN__
 extern void
-_resolv_cache_add( struct resolv_cache*  cache,
+_resolv_cache_add( unsigned              netid,
                    const void*           query,
                    int                   querylen,
                    const void*           answer,
@@ -74,7 +69,7 @@ _resolv_cache_add( struct resolv_cache*  cache,
 /* Notify the cache a request failed */
 __LIBC_HIDDEN__
 extern void
-_resolv_cache_query_failed( struct resolv_cache* cache,
+_resolv_cache_query_failed( unsigned     netid,
                    const void* query,
                    int         querylen);
 
index bada18a441bf17d68e1fd691c7699c4d6252edd1..e5521b809b82765e4207c496438c26019b114ee9 100644 (file)
@@ -36,7 +36,7 @@
 #include <netinet/in.h>
 
 /*
- * Passing NETID_UNSET as the netId causes system/netd/DnsProxyListener.cpp to
+ * Passing NETID_UNSET as the netId causes system/netd/server/DnsProxyListener.cpp to
  * fill in the appropriate default netId for the query.
  */
 #define NETID_UNSET 0u
@@ -72,6 +72,9 @@ struct hostent *android_gethostbyaddrfornet_proxy(const void *, socklen_t, int ,
 int android_getnameinfofornet(const struct sockaddr *, socklen_t, char *, size_t, char *, size_t,
                 int, unsigned, unsigned);
 
+/* delete the cache associated with a certain network */
+extern void _resolv_delete_cache_for_net(unsigned netid);
+
 __END_DECLS
 
 #endif /* _RESOLV_NETID_H */
index 5a1f25c0fdb1078d523c55bcb4dee24f9e30c0e8..4a832d0e3dd7b59b2470727e51dd27e5918b4c24 100644 (file)
@@ -498,6 +498,16 @@ __LIBC_HIDDEN__ void res_setnetid(res_state, unsigned);
 __LIBC_HIDDEN__ void res_setmark(res_state, unsigned);
 u_int  res_randomid(void);
 
+#ifdef __i386__
+# define __socketcall extern __attribute__((__cdecl__))
+#else
+# define __socketcall extern
+#endif
+
+__socketcall int __connect(int, const struct sockaddr*, socklen_t);
+
+#undef __socketcall
+
 __END_DECLS
 
 #pragma GCC visibility pop
index a4923187ec6ed4562c0d25bf3c96dfe23ba0319e..54439996539b51015397631f045468ce9cccf6eb 100644 (file)
@@ -369,7 +369,7 @@ _test_connect(int pf, struct sockaddr *addr, size_t addrlen, unsigned mark) {
                return 0;
        int ret;
        do {
-               ret = connect(s, addr, addrlen);
+               ret = __connect(s, addr, addrlen);
        } while (ret < 0 && errno == EINTR);
        int success = (ret == 0);
        do {
@@ -1803,7 +1803,7 @@ _find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr, unsigned
        if (mark != MARK_UNSET && setsockopt(sock, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0)
                return 0;
        do {
-               ret = connect(sock, addr, len);
+               ret = __connect(sock, addr, len);
        } while (ret == -1 && errno == EINTR);
 
        if (ret == -1) {
index dd7769330f2f423f17f45a92a41999c6b1067599..15d04c2fa67a2c48a28372a9738bf04118008785 100644 (file)
@@ -1218,7 +1218,6 @@ typedef struct resolv_cache {
     int              max_entries;
     int              num_entries;
     Entry            mru_list;
-    pthread_mutex_t  lock;
     int              last_id;
     Entry*           entries;
     PendingReqInfo   pending_requests;
@@ -1236,6 +1235,15 @@ struct resolv_cache_info {
 
 #define  HTABLE_VALID(x)  ((x) != NULL && (x) != HTABLE_DELETED)
 
+static pthread_once_t        _res_cache_once = PTHREAD_ONCE_INIT;
+static void _res_cache_init(void);
+
+// lock protecting everything in the _resolve_cache_info structs (next ptr, etc)
+static pthread_mutex_t _res_cache_list_lock;
+
+/* gets cache associated with a network, or NULL if none exists */
+static struct resolv_cache* _find_named_cache_locked(unsigned netid);
+
 static void
 _cache_flush_pending_requests_locked( struct resolv_cache* cache )
 {
@@ -1256,18 +1264,18 @@ _cache_flush_pending_requests_locked( struct resolv_cache* cache )
     }
 }
 
-/* return 0 if no pending request is found matching the key
- * if a matching request is found the calling thread will wait
- * and return 1 when released */
+/* Return 0 if no pending request is found matching the key.
+ * If a matching request is found the calling thread will wait until
+ * the matching request completes, then update *cache and return 1. */
 static int
-_cache_check_pending_request_locked( struct resolv_cache* cache, Entry* key )
+_cache_check_pending_request_locked( struct resolv_cache** cache, Entry* key, unsigned netid )
 {
     struct pending_req_info *ri, *prev;
     int exist = 0;
 
-    if (cache && key) {
-        ri = cache->pending_requests.next;
-        prev = &cache->pending_requests;
+    if (*cache && key) {
+        ri = (*cache)->pending_requests.next;
+        prev = &(*cache)->pending_requests;
         while (ri) {
             if (ri->hash == key->hash) {
                 exist = 1;
@@ -1288,7 +1296,9 @@ _cache_check_pending_request_locked( struct resolv_cache* cache, Entry* key )
             struct timespec ts = {0,0};
             XLOG("Waiting for previous request");
             ts.tv_sec = _time_now() + PENDING_REQUEST_TIMEOUT;
-            pthread_cond_timedwait(&ri->cond, &cache->lock, &ts);
+            pthread_cond_timedwait(&ri->cond, &_res_cache_list_lock, &ts);
+            /* Must update *cache as it could have been deleted. */
+            *cache = _find_named_cache_locked(netid);
         }
     }
 
@@ -1325,17 +1335,25 @@ _cache_notify_waiting_tid_locked( struct resolv_cache* cache, Entry* key )
 
 /* notify the cache that the query failed */
 void
-_resolv_cache_query_failed( struct resolv_cache* cache,
+_resolv_cache_query_failed( unsigned    netid,
                    const void* query,
                    int         querylen)
 {
     Entry    key[1];
+    Cache*   cache;
+
+    if (!entry_init_key(key, query, querylen))
+        return;
+
+    pthread_mutex_lock(&_res_cache_list_lock);
+
+    cache = _find_named_cache_locked(netid);
 
-    if (cache && entry_init_key(key, query, querylen)) {
-        pthread_mutex_lock(&cache->lock);
+    if (cache) {
         _cache_notify_waiting_tid_locked(cache, key);
-        pthread_mutex_unlock(&cache->lock);
     }
+
+    pthread_mutex_unlock(&_res_cache_list_lock);
 }
 
 static void
@@ -1391,7 +1409,6 @@ _resolv_cache_create( void )
         cache->max_entries = _res_cache_get_max_entries();
         cache->entries = calloc(sizeof(*cache->entries), cache->max_entries);
         if (cache->entries) {
-            pthread_mutex_init( &cache->lock, NULL );
             cache->mru_list.mru_prev = cache->mru_list.mru_next = &cache->mru_list;
             XLOG("%s: cache created\n", __FUNCTION__);
         } else {
@@ -1586,7 +1603,7 @@ static void _cache_remove_expired(Cache* cache) {
 }
 
 ResolvCacheStatus
-_resolv_cache_lookup( struct resolv_cache*  cache,
+_resolv_cache_lookup( unsigned              netid,
                       const void*           query,
                       int                   querylen,
                       void*                 answer,
@@ -1597,6 +1614,7 @@ _resolv_cache_lookup( struct resolv_cache*  cache,
     Entry**    lookup;
     Entry*     e;
     time_t     now;
+    Cache*     cache;
 
     ResolvCacheStatus  result = RESOLV_CACHE_NOTFOUND;
 
@@ -1609,7 +1627,14 @@ _resolv_cache_lookup( struct resolv_cache*  cache,
         return RESOLV_CACHE_UNSUPPORTED;
     }
     /* lookup cache */
-    pthread_mutex_lock( &cache->lock );
+    pthread_once(&_res_cache_once, _res_cache_init);
+    pthread_mutex_lock(&_res_cache_list_lock);
+
+    cache = _find_named_cache_locked(netid);
+    if (cache == NULL) {
+        result = RESOLV_CACHE_UNSUPPORTED;
+        goto Exit;
+    }
 
     /* see the description of _lookup_p to understand this.
      * the function always return a non-NULL pointer.
@@ -1621,7 +1646,7 @@ _resolv_cache_lookup( struct resolv_cache*  cache,
         XLOG( "NOT IN CACHE");
         // calling thread will wait if an outstanding request is found
         // that matching this query
-        if (!_cache_check_pending_request_locked(cache, key)) {
+        if (!_cache_check_pending_request_locked(&cache, key, netid) || cache == NULL) {
             goto Exit;
         } else {
             lookup = _cache_lookup_p(cache, key);
@@ -1662,13 +1687,13 @@ _resolv_cache_lookup( struct resolv_cache*  cache,
     result = RESOLV_CACHE_FOUND;
 
 Exit:
-    pthread_mutex_unlock( &cache->lock );
+    pthread_mutex_unlock(&_res_cache_list_lock);
     return result;
 }
 
 
 void
-_resolv_cache_add( struct resolv_cache*  cache,
+_resolv_cache_add( unsigned              netid,
                    const void*           query,
                    int                   querylen,
                    const void*           answer,
@@ -1678,6 +1703,7 @@ _resolv_cache_add( struct resolv_cache*  cache,
     Entry*   e;
     Entry**  lookup;
     u_long   ttl;
+    Cache*   cache = NULL;
 
     /* don't assume that the query has already been cached
      */
@@ -1686,7 +1712,12 @@ _resolv_cache_add( struct resolv_cache*  cache,
         return;
     }
 
-    pthread_mutex_lock( &cache->lock );
+    pthread_mutex_lock(&_res_cache_list_lock);
+
+    cache = _find_named_cache_locked(netid);
+    if (cache == NULL) {
+        goto Exit;
+    }
 
     XLOG( "%s: query:", __FUNCTION__ );
     XLOG_QUERY(query,querylen);
@@ -1732,8 +1763,10 @@ _resolv_cache_add( struct resolv_cache*  cache,
     _cache_dump_mru(cache);
 #endif
 Exit:
-    _cache_notify_waiting_tid_locked(cache, key);
-    pthread_mutex_unlock( &cache->lock );
+    if (cache != NULL) {
+      _cache_notify_waiting_tid_locked(cache, key);
+    }
+    pthread_mutex_unlock(&_res_cache_list_lock);
 }
 
 /****************************************************************************/
@@ -1744,20 +1777,13 @@ Exit:
 /****************************************************************************/
 /****************************************************************************/
 
-static pthread_once_t        _res_cache_once = PTHREAD_ONCE_INIT;
-
 // Head of the list of caches.  Protected by _res_cache_list_lock.
 static struct resolv_cache_info _res_cache_list;
 
-// lock protecting everything in the _resolve_cache_info structs (next ptr, etc)
-static pthread_mutex_t _res_cache_list_lock;
-
 /* insert resolv_cache_info into the list of resolv_cache_infos */
 static void _insert_cache_info_locked(struct resolv_cache_info* cache_info);
 /* creates a resolv_cache_info */
 static struct resolv_cache_info* _create_cache_info( void );
-/* gets cache associated with a network, or NULL if none exists */
-static struct resolv_cache* _find_named_cache_locked(unsigned netid);
 /* gets a resolv_cache_info associated with a network, or NULL if not found */
 static struct resolv_cache_info* _find_cache_info_locked(unsigned netid);
 /* look up the named cache, and creates one if needed */
@@ -1785,22 +1811,6 @@ _res_cache_init(void)
     pthread_mutex_init(&_res_cache_list_lock, NULL);
 }
 
-struct resolv_cache*
-__get_res_cache(unsigned netid)
-{
-    struct resolv_cache *cache;
-
-    pthread_once(&_res_cache_once, _res_cache_init);
-    pthread_mutex_lock(&_res_cache_list_lock);
-
-    /* Does NOT create a cache if it does not exist. */
-    cache = _find_named_cache_locked(netid);
-
-    pthread_mutex_unlock(&_res_cache_list_lock);
-    XLOG("%s: netid=%u, cache=%p\n", __FUNCTION__, netid, cache);
-    return cache;
-}
-
 static struct resolv_cache*
 _get_res_cache_for_net_locked(unsigned netid)
 {
@@ -1837,12 +1847,36 @@ _flush_cache_for_net_locked(unsigned netid)
 {
     struct resolv_cache* cache = _find_named_cache_locked(netid);
     if (cache) {
-        pthread_mutex_lock(&cache->lock);
         _cache_flush_locked(cache);
-        pthread_mutex_unlock(&cache->lock);
     }
 }
 
+void _resolv_delete_cache_for_net(unsigned netid)
+{
+    pthread_once(&_res_cache_once, _res_cache_init);
+    pthread_mutex_lock(&_res_cache_list_lock);
+
+    struct resolv_cache_info* prev_cache_info = &_res_cache_list;
+
+    while (prev_cache_info->next) {
+        struct resolv_cache_info* cache_info = prev_cache_info->next;
+
+        if (cache_info->netid == netid) {
+            prev_cache_info->next = cache_info->next;
+            _cache_flush_locked(cache_info->cache);
+            free(cache_info->cache->entries);
+            free(cache_info->cache);
+            _free_nameservers_locked(cache_info);
+            free(cache_info);
+            break;
+        }
+
+        prev_cache_info = prev_cache_info->next;
+    }
+
+    pthread_mutex_unlock(&_res_cache_list_lock);
+}
+
 static struct resolv_cache_info*
 _create_cache_info(void)
 {
index de093856ab1b5b66a065e6e09041fa8ce91efb76..6439e31ce8bd4e4f1e290c3d8607cb7694a52b31 100644 (file)
@@ -367,7 +367,6 @@ res_nsend(res_state statp,
        int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
        char abuf[NI_MAXHOST];
 #if USE_RESOLV_CACHE
-        struct resolv_cache*  cache;
         ResolvCacheStatus     cache_status = RESOLV_CACHE_UNSUPPORTED;
 #endif
 
@@ -389,21 +388,17 @@ res_nsend(res_state statp,
        terrno = ETIMEDOUT;
 
 #if USE_RESOLV_CACHE
-       // get the cache associated with the network
-       cache = __get_res_cache(statp->netid);
-       if (cache != NULL) {
-               int  anslen = 0;
-               cache_status = _resolv_cache_lookup(
-                               cache, buf, buflen,
-                               ans, anssiz, &anslen);
-
-               if (cache_status == RESOLV_CACHE_FOUND) {
-                       return anslen;
-               } else {
-                       // had a cache miss for a known network, so populate the thread private
-                       // data so the normal resolve path can do its thing
-                       _resolv_populate_res_for_net(statp);
-               }
+       int  anslen = 0;
+       cache_status = _resolv_cache_lookup(
+                       statp->netid, buf, buflen,
+                       ans, anssiz, &anslen);
+
+       if (cache_status == RESOLV_CACHE_FOUND) {
+               return anslen;
+       } else if (cache_status != RESOLV_CACHE_UNSUPPORTED) {
+               // had a cache miss for a known network, so populate the thread private
+               // data so the normal resolve path can do its thing
+               _resolv_populate_res_for_net(statp);
        }
 
        if (statp->nscount == 0) {
@@ -602,7 +597,7 @@ res_nsend(res_state statp,
 
 #if USE_RESOLV_CACHE
                 if (cache_status == RESOLV_CACHE_NOTFOUND) {
-                    _resolv_cache_add(cache, buf, buflen,
+                    _resolv_cache_add(statp->netid, buf, buflen,
                                       ans, resplen);
                 }
 #endif
@@ -658,13 +653,13 @@ res_nsend(res_state statp,
                errno = terrno;
 
 #if USE_RESOLV_CACHE
-        _resolv_cache_query_failed(cache, buf, buflen);
+        _resolv_cache_query_failed(statp->netid, buf, buflen);
 #endif
 
        return (-1);
  fail:
 #if USE_RESOLV_CACHE
-       _resolv_cache_query_failed(cache, buf, buflen);
+       _resolv_cache_query_failed(statp->netid, buf, buflen);
 #endif
        res_nclose(statp);
        return (-1);
@@ -951,7 +946,7 @@ connect_with_timeout(int sock, const struct sockaddr *nsap, socklen_t salen, int
        origflags = fcntl(sock, F_GETFL, 0);
        fcntl(sock, F_SETFL, origflags | O_NONBLOCK);
 
-       res = connect(sock, nsap, salen);
+       res = __connect(sock, nsap, salen);
        if (res < 0 && errno != EINPROGRESS) {
                 res = -1;
                 goto done;
@@ -1108,7 +1103,7 @@ send_dg(res_state statp,
                        res_nclose(statp);
                        return (0);
                }
-               if (connect(EXT(statp).nssocks[ns], nsap, (socklen_t)nsaplen) < 0) {
+               if (__connect(EXT(statp).nssocks[ns], nsap, (socklen_t)nsaplen) < 0) {
                        Aerror(statp, stderr, "connect(dg)", errno, nsap,
                            nsaplen);
                        res_nclose(statp);
index 820558a77e285be08733689a17a28e3512aef47a..63716a4b7cbcd108019d4f1139ba3b7040186a72 100644 (file)
@@ -58,6 +58,12 @@ struct dirent64 { __DIRENT64_BODY };
 
 #undef __DIRENT64_BODY
 
+/* glibc compatibility. */
+#undef _DIRENT_HAVE_D_NAMLEN /* Linux doesn't have a d_namlen field. */
+#define _DIRENT_HAVE_D_RECLEN
+#define _DIRENT_HAVE_D_OFF
+#define _DIRENT_HAVE_D_TYPE
+
 #define d_fileno d_ino
 
 typedef struct DIR DIR;
index b97eaf9fbd6a00952561bfc80a79ef4837bad0c5..3053e85b2f46f15fd9ea9e97e78193de0ffdf229 100644 (file)
@@ -103,15 +103,6 @@ extern void * bsearch(const void *key, const void *base0,
 
 extern void qsort(void *, size_t, size_t, int (*)(const void *, const void *));
 
-extern long jrand48(unsigned short *);
-extern long mrand48(void);
-extern long nrand48(unsigned short *);
-extern long lrand48(void);
-extern unsigned short *seed48(unsigned short*);
-extern double erand48(unsigned short xsubi[3]);
-extern double drand48(void);
-extern void srand48(long);
-
 uint32_t arc4random(void);
 uint32_t arc4random_uniform(uint32_t);
 void arc4random_buf(void*, size_t);
@@ -122,6 +113,16 @@ int rand(void);
 int rand_r(unsigned int*);
 void srand(unsigned int);
 
+double drand48(void);
+double erand48(unsigned short[3]);
+long jrand48(unsigned short[3]);
+void lcong48(unsigned short[7]);
+long lrand48(void);
+long mrand48(void);
+long nrand48(unsigned short[3]);
+unsigned short* seed48(unsigned short[3]);
+void srand48(long);
+
 char* initstate(unsigned int, char*, size_t);
 long random(void);
 char* setstate(char*);
index 611c31a7a1f7a272ab063ad3721d5b4bca368331..f0bed100c198eb03ad30b1a156b678025495f958 100644 (file)
@@ -58,8 +58,11 @@ extern char*  stpcpy(char* __restrict, const char* __restrict);
 extern char*  strcpy(char* __restrict, const char* __restrict);
 extern char*  strcat(char* __restrict, const char* __restrict);
 
-extern int    strcasecmp(const char *, const char *) __purefunc;
-extern int    strncasecmp(const char *, const char *, size_t) __purefunc;
+int strcasecmp(const char*, const char*) __purefunc;
+int strcasecmp_l(const char*, const char*, locale_t) __purefunc;
+int strncasecmp(const char*, const char*, size_t) __purefunc;
+int strncasecmp_l(const char*, const char*, size_t, locale_t) __purefunc;
+
 extern char*  strdup(const char *);
 
 extern char*  strstr(const char *, const char *) __purefunc;
@@ -68,6 +71,7 @@ extern char*  strtok(char* __restrict, const char* __restrict);
 extern char*  strtok_r(char* __restrict, const char* __restrict, char** __restrict);
 
 extern char* strerror(int);
+extern char* strerror_l(int, locale_t);
 #if defined(__USE_GNU)
 extern char* strerror_r(int, char*, size_t) __RENAME(__gnu_strerror_r);
 #else /* POSIX */
index ae261cff6e917367e4a95d4e11e99fb3af50a00e..1253006a0254fa11b6feedf0dbe2c1f4b4e4be30 100644 (file)
 
 #include <sys/types.h>
 #include <sys/cdefs.h>
+#include <xlocale.h>
 
 __BEGIN_DECLS
 #if defined(__BIONIC_FORTIFY)
-#define bcopy(b1, b2, len) \
-  (void)(__builtin___memmove_chk((b2), (b1), (len), __bos0(b2)))
-#define bzero(b, len) \
-  (void)(__builtin___memset_chk((b), '\0', (len), __bos0(b)))
+#define bcopy(b1, b2, len) (void)(__builtin___memmove_chk((b2), (b1), (len), __bos0(b2)))
+#define bzero(b, len) (void)(__builtin___memset_chk((b), '\0', (len), __bos0(b)))
 #else
 #define bcopy(b1, b2, len) (void)(__builtin_memmove((b2), (b1), (len)))
 #define bzero(b, len) (void)(__builtin_memset((b), '\0', (len)))
 #endif
 
+int ffs(int);
 
-int     ffs(int);
-int     strcasecmp(const char *, const char *);
-int     strncasecmp(const char *, const char *, size_t);
+int strcasecmp(const char*, const char*) __purefunc;
+int strcasecmp_l(const char*, const char*, locale_t) __purefunc;
+int strncasecmp(const char*, const char*, size_t) __purefunc;
+int strncasecmp_l(const char*, const char*, size_t, locale_t) __purefunc;
 
 __END_DECLS
 
index 5a681df725956391dc0ca1d3f9c16710018f7f98..0349e4c3d055d5f43cdda9981d19a6579d444966 100644 (file)
@@ -81,6 +81,7 @@ struct prop_msg
 #define PROP_PATH_RAMDISK_DEFAULT  "/default.prop"
 #define PROP_PATH_SYSTEM_BUILD     "/system/build.prop"
 #define PROP_PATH_SYSTEM_DEFAULT   "/system/default.prop"
+#define PROP_PATH_VENDOR_BUILD     "/vendor/build.prop"
 #define PROP_PATH_LOCAL_OVERRIDE   "/data/local.prop"
 #define PROP_PATH_FACTORY          "/factory/factory.prop"
 
index 4900e849f5fce42577bc39620cc6dc90b2cf604c..7d85dd1ef29696177612c63b063e2a789d7845ec 100644 (file)
@@ -52,12 +52,9 @@ __BEGIN_DECLS
   int st_blksize; \
   int __pad2; \
   long st_blocks; \
-  long st_atime; \
-  unsigned long st_atime_nsec; \
-  long st_mtime; \
-  unsigned long st_mtime_nsec; \
-  long st_ctime; \
-  unsigned long st_ctime_nsec; \
+  struct timespec st_atim; \
+  struct timespec st_mtim; \
+  struct timespec st_ctim; \
   unsigned int __unused4; \
   unsigned int __unused5; \
 
@@ -73,12 +70,9 @@ __BEGIN_DECLS
   unsigned int st_rdev; \
   unsigned int __pad1[3]; \
   long long st_size; \
-  unsigned int st_atime; \
-  unsigned int st_atime_nsec; \
-  unsigned int st_mtime; \
-  unsigned int st_mtime_nsec; \
-  unsigned int st_ctime; \
-  unsigned int st_ctime_nsec; \
+  struct timespec st_atim; \
+  struct timespec st_mtim; \
+  struct timespec st_ctim; \
   unsigned int st_blksize; \
   unsigned int __pad2; \
   unsigned long long st_blocks; \
@@ -96,12 +90,9 @@ __BEGIN_DECLS
   long st_size; \
   long st_blksize; \
   long st_blocks; \
-  unsigned long st_atime; \
-  unsigned long st_atime_nsec; \
-  unsigned long st_mtime; \
-  unsigned long st_mtime_nsec; \
-  unsigned long st_ctime; \
-  unsigned long st_ctime_nsec; \
+  struct timespec st_atim; \
+  struct timespec st_mtim; \
+  struct timespec st_ctim; \
   long __pad3[3]; \
 
 #else
@@ -118,12 +109,9 @@ __BEGIN_DECLS
   long long st_size; \
   unsigned long st_blksize; \
   unsigned long long st_blocks; \
-  unsigned long st_atime; \
-  unsigned long st_atime_nsec; \
-  unsigned long st_mtime; \
-  unsigned long st_mtime_nsec; \
-  unsigned long st_ctime; \
-  unsigned long st_ctime_nsec; \
+  struct timespec st_atim; \
+  struct timespec st_mtim; \
+  struct timespec st_ctim; \
   unsigned long long st_ino; \
 
 #endif
@@ -133,9 +121,14 @@ struct stat64 { __STAT64_BODY };
 
 #undef __STAT64_BODY
 
-#define st_atimensec st_atime_nsec
-#define st_mtimensec st_mtime_nsec
-#define st_ctimensec st_ctime_nsec
+/* Compatibility with older versions of POSIX. */
+#define st_atime st_atim.tv_sec
+#define st_mtime st_mtim.tv_sec
+#define st_ctime st_ctim.tv_sec
+/* Compatibility with glibc. */
+#define st_atimensec st_atim.tv_nsec
+#define st_mtimensec st_mtim.tv_nsec
+#define st_ctimensec st_ctim.tv_nsec
 
 #ifdef __USE_BSD
 /* Permission macros provided by glibc for compatibility with BSDs. */
index deac92b6a912ef3c5a68557afec6a6091efbd17b..dca9b3da9c3f44596e67cc5a8627fc27b63c52ad 100644 (file)
@@ -183,7 +183,8 @@ extern unsigned int alarm(unsigned int);
 extern unsigned int sleep(unsigned int);
 extern int usleep(useconds_t);
 
-extern int gethostname(char *, size_t);
+int gethostname(char*, size_t);
+int sethostname(const char*, size_t);
 
 extern void *__brk(void *);
 extern int brk(void *);
index 10a78b8974a8b6bfde46ee09788fc7f4834a88b4..9e279d3deb8a53d0143ae4cc2eadbbdd3eb4c354 100644 (file)
@@ -34,6 +34,7 @@
 #include <stdarg.h>
 #include <stddef.h>
 #include <time.h>
+#include <xlocale.h>
 
 #include <machine/wchar_limits.h>
 
@@ -112,6 +113,7 @@ extern int vwprintf(const wchar_t*, va_list);
 extern int vwscanf(const wchar_t*, va_list);
 extern size_t            wcrtomb(char *, wchar_t, mbstate_t *);
 extern int               wcscasecmp(const wchar_t *, const wchar_t *);
+extern int               wcscasecmp_l(const wchar_t *, const wchar_t *, locale_t);
 extern wchar_t          *wcscat(wchar_t *, const wchar_t *);
 extern wchar_t          *wcschr(const wchar_t *, wchar_t);
 extern int               wcscmp(const wchar_t *, const wchar_t *);
@@ -121,6 +123,7 @@ extern size_t            wcscspn(const wchar_t *, const wchar_t *);
 extern size_t            wcsftime(wchar_t *, size_t, const wchar_t *, const struct tm *) __LIBC_ABI_PUBLIC__;
 extern size_t            wcslen(const wchar_t *);
 extern int               wcsncasecmp(const wchar_t *, const wchar_t *, size_t);
+extern int               wcsncasecmp_l(const wchar_t *, const wchar_t *, size_t, locale_t);
 extern wchar_t          *wcsncat(wchar_t *, const wchar_t *, size_t);
 extern int               wcsncmp(const wchar_t *, const wchar_t *, size_t);
 extern wchar_t          *wcsncpy(wchar_t *, const wchar_t *, size_t);
index f18939d1165b6e35beaac26ad00c8d8a88f4bce2..5af39d04f342961f7da2f71b9d0c60068057e5f1 100644 (file)
  ***
  ****************************************************************************
  ****************************************************************************/
-#ifndef _LINUX_ION_H
-#define _LINUX_ION_H
+#ifndef _UAPI_LINUX_ION_H
+#define _UAPI_LINUX_ION_H
+#include <linux/ioctl.h>
 #include <linux/types.h>
-struct ion_handle;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+typedef int ion_user_handle_t;
 enum ion_heap_type {
  ION_HEAP_TYPE_SYSTEM,
  ION_HEAP_TYPE_SYSTEM_CONTIG,
- ION_HEAP_TYPE_CARVEOUT,
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ ION_HEAP_TYPE_CARVEOUT,
+ ION_HEAP_TYPE_CHUNK,
+ ION_HEAP_TYPE_DMA,
  ION_HEAP_TYPE_CUSTOM,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  ION_NUM_HEAPS = 16,
 };
 #define ION_HEAP_SYSTEM_MASK (1 << ION_HEAP_TYPE_SYSTEM)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define ION_HEAP_SYSTEM_CONTIG_MASK (1 << ION_HEAP_TYPE_SYSTEM_CONTIG)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define ION_HEAP_CARVEOUT_MASK (1 << ION_HEAP_TYPE_CARVEOUT)
+#define ION_HEAP_TYPE_DMA_MASK (1 << ION_HEAP_TYPE_DMA)
+#define ION_NUM_HEAP_IDS sizeof(unsigned int) * 8
 #define ION_FLAG_CACHED 1
-#define ION_FLAG_CACHED_NEEDS_SYNC 2
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ION_FLAG_CACHED_NEEDS_SYNC 2
 struct ion_allocation_data {
  size_t len;
  size_t align;
- unsigned int heap_mask;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ unsigned int heap_id_mask;
  unsigned int flags;
struct ion_handle *handle;
ion_user_handle_t handle;
 };
-struct ion_fd_data {
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- struct ion_handle *handle;
+struct ion_fd_data {
+ ion_user_handle_t handle;
  int fd;
 };
-struct ion_handle_data {
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- struct ion_handle *handle;
+struct ion_handle_data {
+ ion_user_handle_t handle;
 };
 struct ion_custom_data {
- unsigned int cmd;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ unsigned int cmd;
  unsigned long arg;
 };
 #define ION_IOC_MAGIC 'I'
-#define ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0,   struct ion_allocation_data)
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0,   struct ion_allocation_data)
 #define ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data)
 #define ION_IOC_MAP _IOWR(ION_IOC_MAGIC, 2, struct ion_fd_data)
 #define ION_IOC_SHARE _IOWR(ION_IOC_MAGIC, 4, struct ion_fd_data)
-#define ION_IOC_IMPORT _IOWR(ION_IOC_MAGIC, 5, struct ion_fd_data)
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ION_IOC_IMPORT _IOWR(ION_IOC_MAGIC, 5, struct ion_fd_data)
 #define ION_IOC_SYNC _IOWR(ION_IOC_MAGIC, 7, struct ion_fd_data)
 #define ION_IOC_CUSTOM _IOWR(ION_IOC_MAGIC, 6, struct ion_custom_data)
 #endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
index 491b3ace04c0af932a8c1a081489850496c17500..4f3cf8997cd7210f500bd07ac0870b849615bd4e 100644 (file)
 #ifndef _BIONIC_MACROS_H_
 #define _BIONIC_MACROS_H_
 
+// Frameworks OpenGL code currently leaks this header and allows
+// collisions with other declarations, e.g., from libnativehelper.
+// TODO: Remove once cleaned up. b/18334516
+#if !defined(DISALLOW_COPY_AND_ASSIGN)
 // DISALLOW_COPY_AND_ASSIGN disallows the copy and operator= functions.
 // It goes in the private: declarations in a class.
 #define DISALLOW_COPY_AND_ASSIGN(TypeName) \
   TypeName(const TypeName&) = delete;      \
   void operator=(const TypeName&) = delete
+#endif  // !defined(DISALLOW_COPY_AND_ASSIGN)
 
 // A macro to disallow all the implicit constructors, namely the
 // default constructor, copy constructor and operator= functions.
index 8bcf7fcc526e5a0a1bf3e8c3b7ce3ac74adcfae3..0c7e28efe51f20f26345d3e1e480b4350f3d2b11 100755 (executable)
@@ -16,6 +16,14 @@ arch = re.sub(r'.*/linux-x86/([^/]+)/.*', r'\1', toolchain)
 if arch == 'aarch64':
   arch = 'arm64'
 
+def GetSymbolsFromTxt(txt_file):
+  symbols = set()
+  f = open(txt_file, 'r')
+  for line in f.read().splitlines():
+    symbols.add(line)
+  f.close()
+  return symbols
+
 def GetSymbolsFromSo(so_file):
   # Example readelf output:
   #   264: 0001623c     4 FUNC    GLOBAL DEFAULT    8 cabsf
@@ -75,6 +83,7 @@ glibc_to_bionic_names = {
 
 glibc = GetSymbolsFromSystemSo('libc.so.*', 'librt.so.*', 'libpthread.so.*', 'libresolv.so.*', 'libm.so.*')
 bionic = GetSymbolsFromAndroidSo('libc.so', 'libm.so')
+posix = GetSymbolsFromTxt(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'posix-2013.txt'))
 ndk_ignored = GetNdkIgnored()
 
 glibc = map(MangleGlibcNameToBionic, glibc)
@@ -189,6 +198,11 @@ if not only_unwanted:
   for symbol in sorted(bionic):
     print symbol
 
+  print
+  print 'in posix but not bionic:'
+  for symbol in sorted(posix.difference(bionic)):
+    print symbol
+
   print
   print 'in bionic but not glibc:'
 
diff --git a/libc/tools/posix-2013.txt b/libc/tools/posix-2013.txt
new file mode 100644 (file)
index 0000000..6972c81
--- /dev/null
@@ -0,0 +1,1191 @@
+FD_CLR
+FD_ISSET
+FD_SET
+FD_ZERO
+_Exit
+_exit
+_longjmp
+_setjmp
+_tolower
+_toupper
+a64l
+abort
+abs
+accept
+access
+acosf
+acoshf
+acosh
+acoshl
+acos
+acosl
+aio_cancel
+aio_error
+aio_fsync
+aio_read
+aio_return
+aio_suspend
+aio_write
+alarm
+alphasort
+asctime
+asctime_r
+asinf
+asinhf
+asinh
+asinhl
+asin
+asinl
+assert
+atan2f
+atan2
+atan2l
+atanf
+atanhf
+atanh
+atanhl
+atan
+atanl
+atexit
+atof
+atoi
+atol
+atoll
+basename
+bind
+bsearch
+btowc
+cabsf
+cabs
+cabsl
+cacosf
+cacoshf
+cacosh
+cacoshl
+cacos
+cacosl
+calloc
+cargf
+carg
+cargl
+casinf
+casinhf
+casinh
+casinhl
+casin
+casinl
+catanf
+catanhf
+catanh
+catanhl
+catan
+catanl
+catclose
+catgets
+catopen
+cbrtf
+cbrt
+cbrtl
+ccosf
+ccoshf
+ccosh
+ccoshl
+ccos
+ccosl
+ceilf
+ceil
+ceill
+cexpf
+cexp
+cexpl
+cfgetispeed
+cfgetospeed
+cfsetispeed
+cfsetospeed
+chdir
+chmod
+chown
+cimagf
+cimag
+cimagl
+clearerr
+clock_getcpuclockid
+clock_getres
+clock_gettime
+clock
+clock_nanosleep
+clock_settime
+clogf
+clog
+clogl
+closedir
+close
+closelog
+confstr
+conjf
+conj
+conjl
+connect
+copysignf
+copysign
+copysignl
+cosf
+coshf
+cosh
+coshl
+cos
+cosl
+cpowf
+cpow
+cpowl
+cprojf
+cproj
+cprojl
+crealf
+creal
+creall
+creat
+crypt
+csinf
+csinhf
+csinh
+csinhl
+csin
+csinl
+csqrtf
+csqrt
+csqrtl
+ctanf
+ctanhf
+ctanh
+ctanhl
+ctan
+ctanl
+ctermid
+ctime
+ctime_r
+daylight
+dbm_clearerr
+dbm_close
+dbm_delete
+dbm_error
+dbm_fetch
+dbm_firstkey
+dbm_nextkey
+dbm_open
+dbm_store
+difftime
+dirfd
+dirname
+div
+dlclose
+dlerror
+dlopen
+dlsym
+dprintf
+drand48
+dup2
+dup
+duplocale
+encrypt
+endgrent
+endhostent
+endnetent
+endprotoent
+endpwent
+endservent
+endutxent
+environ
+erand48
+erfcf
+erfc
+erfcl
+erff
+erf
+erfl
+errno
+execle
+execl
+execlp
+execve
+execv
+execvp
+exit
+exp2f
+exp2
+exp2l
+expf
+exp
+expl
+expm1f
+expm1
+expm1l
+fabsf
+fabs
+fabsl
+faccessat
+fattach
+fchdir
+fchmodat
+fchmod
+fchownat
+fchown
+fclose
+fcntl
+fdatasync
+fdetach
+fdimf
+fdim
+fdiml
+fdopendir
+fdopen
+feclearexcept
+fegetenv
+fegetexceptflag
+fegetround
+feholdexcept
+feof
+feraiseexcept
+ferror
+fesetenv
+fesetexceptflag
+fesetround
+fetestexcept
+feupdateenv
+fexecve
+fflush
+ffs
+fgetc
+fgetpos
+fgets
+fgetwc
+fgetws
+fileno
+flockfile
+floorf
+floor
+floorl
+fmaf
+fma
+fmal
+fmaxf
+fmax
+fmaxl
+fmemopen
+fminf
+fmin
+fminl
+fmodf
+fmod
+fmodl
+fmtmsg
+fnmatch
+fopen
+fork
+fpathconf
+fpclassify
+fprintf
+fputc
+fputs
+fputwc
+fputws
+fread
+freeaddrinfo
+free
+freelocale
+freopen
+frexpf
+frexp
+frexpl
+fscanf
+fseek
+fseeko
+fsetpos
+fstatat
+fstat
+fstatvfs
+fsync
+ftell
+ftello
+ftok
+ftruncate
+ftrylockfile
+ftw
+funlockfile
+futimens
+fwide
+fwprintf
+fwrite
+fwscanf
+gai_strerror
+getaddrinfo
+getchar
+getchar_unlocked
+getc
+getc_unlocked
+getcwd
+getdate_err
+getdate
+getdelim
+getegid
+getenv
+geteuid
+getgid
+getgrent
+getgrgid
+getgrgid_r
+getgrnam
+getgrnam_r
+getgroups
+gethostent
+gethostid
+gethostname
+getitimer
+getline
+getlogin
+getlogin_r
+getmsg
+getnameinfo
+getnetbyaddr
+getnetbyname
+getnetent
+getopt
+getpeername
+getpgid
+getpgrp
+getpid
+getpmsg
+getppid
+getpriority
+getprotobyname
+getprotobynumber
+getprotoent
+getpwent
+getpwnam
+getpwnam_r
+getpwuid
+getpwuid_r
+getrlimit
+getrusage
+getservbyname
+getservbyport
+getservent
+gets
+getsid
+getsockname
+getsockopt
+getsubopt
+gettimeofday
+getuid
+getutxent
+getutxid
+getutxline
+getwchar
+getwc
+globfree
+glob
+gmtime
+gmtime_r
+grantpt
+hcreate
+hdestroy
+hsearch
+htonl
+htons
+hypotf
+hypot
+hypotl
+iconv_close
+iconv
+iconv_open
+if_freenameindex
+if_indextoname
+if_nameindex
+if_nametoindex
+ilogbf
+ilogb
+ilogbl
+imaxabs
+imaxdiv
+inet_addr
+inet_ntoa
+inet_ntop
+inet_pton
+initstate
+insque
+ioctl
+isalnum
+isalnum_l
+isalpha
+isalpha_l
+isascii
+isastream
+isatty
+isblank
+isblank_l
+iscntrl
+iscntrl_l
+isdigit
+isdigit_l
+isfinite
+isgraph
+isgraph_l
+isgreaterequal
+isgreater
+isinf
+islessequal
+islessgreater
+isless
+islower
+islower_l
+isnan
+isnormal
+isprint
+isprint_l
+ispunct
+ispunct_l
+isspace
+isspace_l
+isunordered
+isupper
+isupper_l
+iswalnum
+iswalnum_l
+iswalpha
+iswalpha_l
+iswblank
+iswblank_l
+iswcntrl
+iswcntrl_l
+iswctype
+iswctype_l
+iswdigit
+iswdigit_l
+iswgraph
+iswgraph_l
+iswlower
+iswlower_l
+iswprint
+iswprint_l
+iswpunct
+iswpunct_l
+iswspace
+iswspace_l
+iswupper
+iswupper_l
+iswxdigit
+iswxdigit_l
+isxdigit
+isxdigit_l
+j0
+j1
+jn
+jrand48
+kill
+killpg
+l64a
+labs
+lchown
+lcong48
+ldexpf
+ldexp
+ldexpl
+ldiv
+lfind
+lgammaf
+lgamma
+lgammal
+linkat
+link
+lio_listio
+listen
+llabs
+lldiv
+llrintf
+llrint
+llrintl
+llroundf
+llround
+llroundl
+localeconv
+localtime
+localtime_r
+lockf
+log10f
+log10
+log10l
+log1pf
+log1p
+log1pl
+log2f
+log2
+log2l
+logbf
+logb
+logbl
+logf
+log
+logl
+longjmp
+lrand48
+lrintf
+lrint
+lrintl
+lroundf
+lround
+lroundl
+lsearch
+lseek
+lstat
+malloc
+mblen
+mbrlen
+mbrtowc
+mbsinit
+mbsnrtowcs
+mbsrtowcs
+mbstowcs
+mbtowc
+memccpy
+memchr
+memcmp
+memcpy
+memmove
+memset
+mkdirat
+mkdir
+mkdtemp
+mkfifoat
+mkfifo
+mknodat
+mknod
+mkstemp
+mktime
+mlockall
+mlock
+mmap
+modff
+modf
+modfl
+mprotect
+mq_close
+mq_getattr
+mq_notify
+mq_open
+mq_receive
+mq_send
+mq_setattr
+mq_timedreceive
+mq_timedsend
+mq_unlink
+mrand48
+msgctl
+msgget
+msgrcv
+msgsnd
+msync
+munlockall
+munlock
+munmap
+nanf
+nan
+nanl
+nanosleep
+nearbyintf
+nearbyint
+nearbyintl
+newlocale
+nextafterf
+nextafter
+nextafterl
+nexttowardf
+nexttoward
+nexttowardl
+nftw
+nice
+nl_langinfo
+nl_langinfo_l
+nrand48
+ntohl
+ntohs
+openat
+opendir
+open
+openlog
+open_memstream
+open_wmemstream
+optarg
+opterr
+optind
+optopt
+pathconf
+pause
+pclose
+perror
+pipe
+poll
+popen
+posix_fadvise
+posix_fallocate
+posix_madvise
+posix_memalign
+posix_mem_offset
+posix_openpt
+posix_spawnattr_destroy
+posix_spawnattr_getflags
+posix_spawnattr_getpgroup
+posix_spawnattr_getschedparam
+posix_spawnattr_getschedpolicy
+posix_spawnattr_getsigdefault
+posix_spawnattr_getsigmask
+posix_spawnattr_init
+posix_spawnattr_setflags
+posix_spawnattr_setpgroup
+posix_spawnattr_setschedparam
+posix_spawnattr_setschedpolicy
+posix_spawnattr_setsigdefault
+posix_spawnattr_setsigmask
+posix_spawn_file_actions_addclose
+posix_spawn_file_actions_adddup2
+posix_spawn_file_actions_addopen
+posix_spawn_file_actions_destroy
+posix_spawn_file_actions_init
+posix_spawn
+posix_spawnp
+posix_trace_attr_destroy
+posix_trace_attr_getclockres
+posix_trace_attr_getcreatetime
+posix_trace_attr_getgenversion
+posix_trace_attr_getinherited
+posix_trace_attr_getlogfullpolicy
+posix_trace_attr_getlogsize
+posix_trace_attr_getmaxdatasize
+posix_trace_attr_getmaxsystemeventsize
+posix_trace_attr_getmaxusereventsize
+posix_trace_attr_getname
+posix_trace_attr_getstreamfullpolicy
+posix_trace_attr_getstreamsize
+posix_trace_attr_init
+posix_trace_attr_setinherited
+posix_trace_attr_setlogfullpolicy
+posix_trace_attr_setlogsize
+posix_trace_attr_setmaxdatasize
+posix_trace_attr_setname
+posix_trace_attr_setstreamfullpolicy
+posix_trace_attr_setstreamsize
+posix_trace_clear
+posix_trace_close
+posix_trace_create
+posix_trace_create_withlog
+posix_trace_event
+posix_trace_eventid_equal
+posix_trace_eventid_get_name
+posix_trace_eventid_open
+posix_trace_eventset_add
+posix_trace_eventset_del
+posix_trace_eventset_empty
+posix_trace_eventset_fill
+posix_trace_eventset_ismember
+posix_trace_eventtypelist_getnext_id
+posix_trace_eventtypelist_rewind
+posix_trace_flush
+posix_trace_get_attr
+posix_trace_get_filter
+posix_trace_getnext_event
+posix_trace_get_status
+posix_trace_open
+posix_trace_rewind
+posix_trace_set_filter
+posix_trace_shutdown
+posix_trace_start
+posix_trace_stop
+posix_trace_timedgetnext_event
+posix_trace_trid_eventid_open
+posix_trace_trygetnext_event
+posix_typed_mem_get_info
+posix_typed_mem_open
+powf
+pow
+powl
+pread
+printf
+pselect
+psiginfo
+psignal
+pthread_atfork
+pthread_attr_destroy
+pthread_attr_getdetachstate
+pthread_attr_getguardsize
+pthread_attr_getinheritsched
+pthread_attr_getschedparam
+pthread_attr_getschedpolicy
+pthread_attr_getscope
+pthread_attr_getstack
+pthread_attr_getstacksize
+pthread_attr_init
+pthread_attr_setdetachstate
+pthread_attr_setguardsize
+pthread_attr_setinheritsched
+pthread_attr_setschedparam
+pthread_attr_setschedpolicy
+pthread_attr_setscope
+pthread_attr_setstack
+pthread_attr_setstacksize
+pthread_barrierattr_destroy
+pthread_barrierattr_getpshared
+pthread_barrierattr_init
+pthread_barrierattr_setpshared
+pthread_barrier_destroy
+pthread_barrier_init
+pthread_barrier_wait
+pthread_cancel
+pthread_cleanup_pop
+pthread_cleanup_push
+pthread_condattr_destroy
+pthread_condattr_getclock
+pthread_condattr_getpshared
+pthread_condattr_init
+pthread_condattr_setclock
+pthread_condattr_setpshared
+pthread_cond_broadcast
+pthread_cond_destroy
+pthread_cond_init
+pthread_cond_signal
+pthread_cond_timedwait
+pthread_cond_wait
+pthread_create
+pthread_detach
+pthread_equal
+pthread_exit
+pthread_getconcurrency
+pthread_getcpuclockid
+pthread_getschedparam
+pthread_getspecific
+pthread_join
+pthread_key_create
+pthread_key_delete
+pthread_kill
+pthread_mutexattr_destroy
+pthread_mutexattr_getprioceiling
+pthread_mutexattr_getprotocol
+pthread_mutexattr_getpshared
+pthread_mutexattr_getrobust
+pthread_mutexattr_gettype
+pthread_mutexattr_init
+pthread_mutexattr_setprioceiling
+pthread_mutexattr_setprotocol
+pthread_mutexattr_setpshared
+pthread_mutexattr_setrobust
+pthread_mutexattr_settype
+pthread_mutex_consistent
+pthread_mutex_destroy
+pthread_mutex_getprioceiling
+pthread_mutex_init
+pthread_mutex_lock
+pthread_mutex_setprioceiling
+pthread_mutex_timedlock
+pthread_mutex_trylock
+pthread_mutex_unlock
+pthread_once
+pthread_rwlockattr_destroy
+pthread_rwlockattr_getpshared
+pthread_rwlockattr_init
+pthread_rwlockattr_setpshared
+pthread_rwlock_destroy
+pthread_rwlock_init
+pthread_rwlock_rdlock
+pthread_rwlock_timedrdlock
+pthread_rwlock_timedwrlock
+pthread_rwlock_tryrdlock
+pthread_rwlock_trywrlock
+pthread_rwlock_unlock
+pthread_rwlock_wrlock
+pthread_self
+pthread_setcancelstate
+pthread_setcanceltype
+pthread_setconcurrency
+pthread_setschedparam
+pthread_setschedprio
+pthread_setspecific
+pthread_sigmask
+pthread_spin_destroy
+pthread_spin_init
+pthread_spin_lock
+pthread_spin_trylock
+pthread_spin_unlock
+pthread_testcancel
+ptsname
+putchar
+putchar_unlocked
+putc
+putc_unlocked
+putenv
+putmsg
+putpmsg
+puts
+pututxline
+putwchar
+putwc
+pwrite
+qsort
+raise
+rand
+random
+rand_r
+readdir
+readdir_r
+read
+readlinkat
+readlink
+readv
+realloc
+realpath
+recvfrom
+recv
+recvmsg
+regcomp
+regerror
+regexec
+regfree
+remainderf
+remainder
+remainderl
+remove
+remque
+remquof
+remquo
+remquol
+renameat
+rename
+rewinddir
+rewind
+rintf
+rint
+rintl
+rmdir
+roundf
+round
+roundl
+scalblnf
+scalbln
+scalblnl
+scalbnf
+scalbn
+scalbnl
+scandir
+scanf
+sched_getparam
+sched_get_priority_max
+sched_get_priority_min
+sched_getscheduler
+sched_rr_get_interval
+sched_setparam
+sched_setscheduler
+sched_yield
+seed48
+seekdir
+select
+sem_close
+semctl
+sem_destroy
+semget
+sem_getvalue
+sem_init
+sem_open
+semop
+sem_post
+sem_timedwait
+sem_trywait
+sem_unlink
+sem_wait
+send
+sendmsg
+sendto
+setbuf
+setegid
+setenv
+seteuid
+setgid
+setgrent
+sethostent
+setitimer
+setjmp
+setkey
+setlocale
+setlogmask
+setnetent
+setpgid
+setpgrp
+setpriority
+setprotoent
+setpwent
+setregid
+setreuid
+setrlimit
+setservent
+setsid
+setsockopt
+setstate
+setuid
+setutxent
+setvbuf
+shmat
+shmctl
+shmdt
+shmget
+shm_open
+shm_unlink
+shutdown
+sigaction
+sigaddset
+sigaltstack
+sigdelset
+sigemptyset
+sigfillset
+sighold
+sigignore
+siginterrupt
+sigismember
+siglongjmp
+signal
+signbit
+signgam
+sigpause
+sigpending
+sigprocmask
+sigqueue
+sigrelse
+sigset
+sigsetjmp
+sigsuspend
+sigtimedwait
+sigwait
+sigwaitinfo
+sinf
+sinhf
+sinh
+sinhl
+sin
+sinl
+sleep
+snprintf
+sockatmark
+socket
+socketpair
+sprintf
+sqrtf
+sqrt
+sqrtl
+srand48
+srand
+srandom
+sscanf
+stat
+statvfs
+stderr
+stdin
+stdout
+stpcpy
+stpncpy
+strcasecmp
+strcasecmp_l
+strcat
+strchr
+strcmp
+strcoll
+strcoll_l
+strcpy
+strcspn
+strdup
+strerror
+strerror_l
+strerror_r
+strfmon
+strfmon_l
+strftime
+strftime_l
+strlen
+strncasecmp
+strncasecmp_l
+strncat
+strncmp
+strncpy
+strndup
+strnlen
+strpbrk
+strptime
+strrchr
+strsignal
+strspn
+strstr
+strtod
+strtof
+strtoimax
+strtok
+strtok_r
+strtold
+strtol
+strtoll
+strtoul
+strtoull
+strtoumax
+strxfrm
+strxfrm_l
+swab
+swprintf
+swscanf
+symlinkat
+symlink
+sync
+sysconf
+syslog
+system
+tanf
+tanhf
+tanh
+tanhl
+tan
+tanl
+tcdrain
+tcflow
+tcflush
+tcgetattr
+tcgetpgrp
+tcgetsid
+tcsendbreak
+tcsetattr
+tcsetpgrp
+tdelete
+telldir
+tempnam
+tfind
+tgammaf
+tgamma
+tgammal
+time
+timer_create
+timer_delete
+timer_getoverrun
+timer_gettime
+timer_settime
+times
+timezone
+tmpfile
+tmpnam
+toascii
+tolower
+tolower_l
+toupper
+toupper_l
+towctrans
+towctrans_l
+towlower
+towlower_l
+towupper
+towupper_l
+truncate
+truncf
+trunc
+truncl
+tsearch
+ttyname
+ttyname_r
+twalk
+tzname
+tzset
+ulimit
+umask
+uname
+ungetc
+ungetwc
+unlinkat
+unlink
+unlockpt
+unsetenv
+uselocale
+utime
+utimensat
+utimes
+va_arg
+va_copy
+va_end
+va_start
+vdprintf
+vfprintf
+vfscanf
+vfwprintf
+vfwscanf
+vprintf
+vscanf
+vsnprintf
+vsprintf
+vsscanf
+vswprintf
+vswscanf
+vwprintf
+vwscanf
+wait
+waitid
+waitpid
+wcpcpy
+wcpncpy
+wcrtomb
+wcscasecmp
+wcscasecmp_l
+wcscat
+wcschr
+wcscmp
+wcscoll
+wcscoll_l
+wcscpy
+wcscspn
+wcsdup
+wcsftime
+wcslen
+wcsncasecmp
+wcsncasecmp_l
+wcsncat
+wcsncmp
+wcsncpy
+wcsnlen
+wcsnrtombs
+wcspbrk
+wcsrchr
+wcsrtombs
+wcsspn
+wcsstr
+wcstod
+wcstof
+wcstoimax
+wcstok
+wcstold
+wcstol
+wcstoll
+wcstombs
+wcstoul
+wcstoull
+wcstoumax
+wcswidth
+wcsxfrm
+wcsxfrm_l
+wctob
+wctomb
+wctrans
+wctrans_l
+wctype
+wctype_l
+wcwidth
+wmemchr
+wmemcmp
+wmemcpy
+wmemmove
+wmemset
+wordexp
+wordfree
+wprintf
+write
+writev
+wscanf
+y0
+y1
+yn
index bf3153eff559c33aac6f9444900d19d9bfb107c0..2d598fec041c6888689698dd0e0db5ed7e36ea02 100644 (file)
@@ -132,9 +132,15 @@ public class ZoneCompactor {
         throw new RuntimeException("zone filename too long: " + zoneName.length());
       }
 
+      // Follow the chain of links to work out where the real data for this zone lives.
+      String actualZoneName = zoneName;
+      while (links.get(actualZoneName) != null) {
+        actualZoneName = links.get(actualZoneName);
+      }
+
       f.write(toAscii(new byte[MAXNAME], zoneName));
-      f.writeInt(offsets.get(zoneName));
-      f.writeInt(lengths.get(zoneName));
+      f.writeInt(offsets.get(actualZoneName));
+      f.writeInt(lengths.get(actualZoneName));
       f.writeInt(0); // Used to be raw GMT offset. No longer used.
     }
 
index f5681beb22dbd8c8f25e8347bcea8b6955164400..330f1662d275e3f91e7cedb1a0577865b51131c4 100755 (executable)
@@ -13,8 +13,11 @@ import sys
 import tarfile
 import tempfile
 
-regions = ['africa', 'antarctica', 'asia', 'australasia', 'backward',
-           'etcetera', 'europe', 'northamerica', 'southamerica']
+regions = ['africa', 'antarctica', 'asia', 'australasia',
+           'etcetera', 'europe', 'northamerica', 'southamerica',
+           # These two deliberately come last so they override what came
+           # before (and each other).
+           'backward', 'backzone' ]
 
 def CheckDirExists(dir, dirname):
   if not os.path.isdir(dir):
@@ -49,16 +52,16 @@ def WriteSetupFile():
       fields = line.split()
       if fields:
         if fields[0] == 'Link':
-          links.append('%s %s %s\n' % (fields[0], fields[1], fields[2]))
+          links.append('%s %s %s' % (fields[0], fields[1], fields[2]))
           zones.append(fields[2])
         elif fields[0] == 'Zone':
           zones.append(fields[1])
   zones.sort()
 
   setup = open('setup', 'w')
-  for link in links:
-    setup.write(link)
-  for zone in zones:
+  for link in sorted(set(links)):
+    setup.write('%s\n' % link)
+  for zone in sorted(set(zones)):
     setup.write('%s\n' % zone)
   setup.close()
 
@@ -165,9 +168,10 @@ def BuildBionicToolsAndData(data_filename):
 
   print 'Calling zic(1)...'
   os.mkdir('data')
-  for region in regions:
-    if region != 'backward':
-      subprocess.check_call(['zic', '-d', 'data', 'extracted/%s' % region])
+  zic_inputs = [ 'extracted/%s' % x for x in regions ]
+  zic_cmd = ['zic', '-d', 'data' ]
+  zic_cmd.extend(zic_inputs)
+  subprocess.check_call(zic_cmd)
 
   WriteSetupFile()
 
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/lcong48.c b/libc/upstream-netbsd/lib/libc/stdlib/lcong48.c
new file mode 100644 (file)
index 0000000..42ce979
--- /dev/null
@@ -0,0 +1,43 @@
+/*     $NetBSD: lcong48.c,v 1.8 2005/06/12 05:21:28 lukem Exp $        */
+
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: lcong48.c,v 1.8 2005/06/12 05:21:28 lukem Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include "namespace.h"
+
+#include <assert.h>
+
+#include "rand48.h"
+
+#ifdef __weak_alias
+__weak_alias(lcong48,_lcong48)
+#endif
+
+void
+lcong48(unsigned short p[7])
+{
+       _DIAGASSERT(p != NULL);
+
+       __rand48_seed[0] = p[0];
+       __rand48_seed[1] = p[1];
+       __rand48_seed[2] = p[2];
+       __rand48_mult[0] = p[3];
+       __rand48_mult[1] = p[4];
+       __rand48_mult[2] = p[5];
+       __rand48_add = p[6];
+}
index e9cf16428fd3a6bd6e022ff8f460ee134f9c9a41..fc6c5babb83b74177bbaa18f47f38cd5de8d7c5b 100644 (file)
Binary files a/libc/zoneinfo/tzdata and b/libc/zoneinfo/tzdata differ
index 0f63d7b91f444080749ab46b922b656aca1ba3d7..d4cd7c3e84d01eeae3a47b89759eacd779cfd919 100644 (file)
@@ -18,6 +18,8 @@ libm_common_src_files += \
     upstream-freebsd/lib/msun/bsdsrc/b_exp.c \
     upstream-freebsd/lib/msun/bsdsrc/b_log.c \
     upstream-freebsd/lib/msun/bsdsrc/b_tgamma.c \
+    upstream-freebsd/lib/msun/src/catrig.c \
+    upstream-freebsd/lib/msun/src/catrigf.c \
     upstream-freebsd/lib/msun/src/e_acos.c \
     upstream-freebsd/lib/msun/src/e_acosf.c \
     upstream-freebsd/lib/msun/src/e_acosh.c \
@@ -84,6 +86,7 @@ libm_common_src_files += \
     upstream-freebsd/lib/msun/src/s_atanf.c \
     upstream-freebsd/lib/msun/src/s_carg.c \
     upstream-freebsd/lib/msun/src/s_cargf.c \
+    upstream-freebsd/lib/msun/src/s_cargl.c \
     upstream-freebsd/lib/msun/src/s_cbrt.c \
     upstream-freebsd/lib/msun/src/s_cbrtf.c \
     upstream-freebsd/lib/msun/src/s_ccosh.c \
@@ -94,20 +97,25 @@ libm_common_src_files += \
     upstream-freebsd/lib/msun/src/s_cexpf.c \
     upstream-freebsd/lib/msun/src/s_cimag.c \
     upstream-freebsd/lib/msun/src/s_cimagf.c \
+    upstream-freebsd/lib/msun/src/s_cimagl.c \
     upstream-freebsd/lib/msun/src/s_conj.c \
     upstream-freebsd/lib/msun/src/s_conjf.c \
+    upstream-freebsd/lib/msun/src/s_conjl.c \
     upstream-freebsd/lib/msun/src/s_copysign.c \
     upstream-freebsd/lib/msun/src/s_copysignf.c \
     upstream-freebsd/lib/msun/src/s_cos.c \
     upstream-freebsd/lib/msun/src/s_cosf.c \
     upstream-freebsd/lib/msun/src/s_cproj.c \
     upstream-freebsd/lib/msun/src/s_cprojf.c \
+    upstream-freebsd/lib/msun/src/s_cprojl.c \
     upstream-freebsd/lib/msun/src/s_creal.c \
     upstream-freebsd/lib/msun/src/s_crealf.c \
+    upstream-freebsd/lib/msun/src/s_creall.c \
     upstream-freebsd/lib/msun/src/s_csinh.c \
     upstream-freebsd/lib/msun/src/s_csinhf.c \
     upstream-freebsd/lib/msun/src/s_csqrt.c \
     upstream-freebsd/lib/msun/src/s_csqrtf.c \
+    upstream-freebsd/lib/msun/src/s_csqrtl.c \
     upstream-freebsd/lib/msun/src/s_ctanh.c \
     upstream-freebsd/lib/msun/src/s_ctanhf.c \
     upstream-freebsd/lib/msun/src/s_erf.c \
@@ -174,6 +182,7 @@ libm_common_src_files += \
     upstream-freebsd/lib/msun/src/s_truncf.c \
     upstream-freebsd/lib/msun/src/w_cabs.c \
     upstream-freebsd/lib/msun/src/w_cabsf.c \
+    upstream-freebsd/lib/msun/src/w_cabsl.c \
     upstream-freebsd/lib/msun/src/w_drem.c \
     upstream-freebsd/lib/msun/src/w_dremf.c \
 
@@ -181,7 +190,7 @@ libm_common_src_files += \
     fake_long_double.c \
     signbit.c \
 
-libm_ld_src_files = \
+libm_ld128_src_files = \
     upstream-freebsd/lib/msun/src/e_acosl.c \
     upstream-freebsd/lib/msun/src/e_acoshl.c \
     upstream-freebsd/lib/msun/src/e_asinl.c \
@@ -225,7 +234,7 @@ libm_ld_src_files = \
     upstream-freebsd/lib/msun/src/s_tanl.c \
     upstream-freebsd/lib/msun/src/s_truncl.c \
 
-libm_ld_src_files += \
+libm_ld128_src_files += \
     upstream-freebsd/lib/msun/ld128/invtrig.c \
     upstream-freebsd/lib/msun/ld128/e_lgammal_r.c \
     upstream-freebsd/lib/msun/ld128/k_cosl.c \
@@ -282,18 +291,18 @@ LOCAL_C_INCLUDES_arm := $(LOCAL_PATH)/arm
 LOCAL_SRC_FILES_arm := arm/fenv.c
 
 LOCAL_C_INCLUDES_arm64 := $(libm_ld_includes)
-LOCAL_SRC_FILES_arm64 := arm64/fenv.c $(libm_ld_src_files)
+LOCAL_SRC_FILES_arm64 := arm64/fenv.c $(libm_ld128_src_files)
 
 LOCAL_C_INCLUDES_x86 := $(LOCAL_PATH)/i387
 LOCAL_SRC_FILES_x86 := i387/fenv.c
 
 LOCAL_C_INCLUDES_x86_64 := $(libm_ld_includes)
-LOCAL_SRC_FILES_x86_64 := amd64/fenv.c $(libm_ld_src_files)
+LOCAL_SRC_FILES_x86_64 := amd64/fenv.c $(libm_ld128_src_files)
 
 LOCAL_SRC_FILES_mips := mips/fenv.c
 
 LOCAL_C_INCLUDES_mips64 := $(libm_ld_includes)
-LOCAL_SRC_FILES_mips64 := mips/fenv.c $(libm_ld_src_files)
+LOCAL_SRC_FILES_mips64 := mips/fenv.c $(libm_ld128_src_files)
 
 LOCAL_CXX_STL := none
 include $(BUILD_STATIC_LIBRARY)
index 0702541c44aaf14f363e2f5ac501506a62b4d039..ff6b166f4df3e6804c96d7b021f004c37516e168 100644 (file)
@@ -46,14 +46,39 @@ _Static_assert(__generic(_Complex_I, float _Complex, 1, 0),
 #define        complex         _Complex
 #define        I               _Complex_I
 
+#if __ISO_C_VISIBLE >= 2011
+#ifdef __clang__
+#define        CMPLX(x, y)     ((double complex){ x, y })
+#define        CMPLXF(x, y)    ((float complex){ x, y })
+#define        CMPLXL(x, y)    ((long double complex){ x, y })
+#elif __GNUC_PREREQ__(4, 7)
+#define        CMPLX(x, y)     __builtin_complex((double)(x), (double)(y))
+#define        CMPLXF(x, y)    __builtin_complex((float)(x), (float)(y))
+#define        CMPLXL(x, y)    __builtin_complex((long double)(x), (long double)(y))
+#endif
+#endif /* __ISO_C_VISIBLE >= 2011 */
+
 __BEGIN_DECLS
+#pragma GCC visibility push(default)
 
 double         cabs(double complex);
 float          cabsf(float complex);
 long double    cabsl(long double complex);
+double complex cacos(double complex);
+float complex  cacosf(float complex);
+double complex cacosh(double complex);
+float complex  cacoshf(float complex);
 double         carg(double complex);
 float          cargf(float complex);
 long double    cargl(long double complex);
+double complex casin(double complex);
+float complex  casinf(float complex);
+double complex casinh(double complex);
+float complex  casinhf(float complex);
+double complex catan(double complex);
+float complex  catanf(float complex);
+double complex catanh(double complex);
+float complex  catanhf(float complex);
 double complex ccos(double complex);
 float complex  ccosf(float complex);
 double complex ccosh(double complex);
@@ -87,6 +112,7 @@ float complex        ctanf(float complex);
 double complex ctanh(double complex);
 float complex  ctanhf(float complex);
 
+#pragma GCC visibility pop
 __END_DECLS
 
 #endif /* _COMPLEX_H */
diff --git a/libm/upstream-freebsd/lib/msun/src/catrig.c b/libm/upstream-freebsd/lib/msun/src/catrig.c
new file mode 100644 (file)
index 0000000..200977c
--- /dev/null
@@ -0,0 +1,639 @@
+/*-
+ * Copyright (c) 2012 Stephen Montgomery-Smith <stephen@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <complex.h>
+#include <float.h>
+
+#include "math.h"
+#include "math_private.h"
+
+#undef isinf
+#define isinf(x)       (fabs(x) == INFINITY)
+#undef isnan
+#define isnan(x)       ((x) != (x))
+#define        raise_inexact() do { volatile float junk = 1 + tiny; } while(0)
+#undef signbit
+#define signbit(x)     (__builtin_signbit(x))
+
+/* We need that DBL_EPSILON^2/128 is larger than FOUR_SQRT_MIN. */
+static const double
+A_crossover =          10, /* Hull et al suggest 1.5, but 10 works better */
+B_crossover =          0.6417,                 /* suggested by Hull et al */
+FOUR_SQRT_MIN =                0x1p-509,               /* >= 4 * sqrt(DBL_MIN) */
+QUARTER_SQRT_MAX =     0x1p509,                /* <= sqrt(DBL_MAX) / 4 */
+m_e =                  2.7182818284590452e0,   /*  0x15bf0a8b145769.0p-51 */
+m_ln2 =                        6.9314718055994531e-1,  /*  0x162e42fefa39ef.0p-53 */
+pio2_hi =              1.5707963267948966e0,   /*  0x1921fb54442d18.0p-52 */
+RECIP_EPSILON =                1 / DBL_EPSILON,
+SQRT_3_EPSILON =       2.5809568279517849e-8,  /*  0x1bb67ae8584caa.0p-78 */
+SQRT_6_EPSILON =       3.6500241499888571e-8,  /*  0x13988e1409212e.0p-77 */
+SQRT_MIN =             0x1p-511;               /* >= sqrt(DBL_MIN) */
+
+static const volatile double
+pio2_lo =              6.1232339957367659e-17; /*  0x11a62633145c07.0p-106 */
+static const volatile float
+tiny =                 0x1p-100; 
+
+static double complex clog_for_large_values(double complex z);
+
+/*
+ * Testing indicates that all these functions are accurate up to 4 ULP.
+ * The functions casin(h) and cacos(h) are about 2.5 times slower than asinh.
+ * The functions catan(h) are a little under 2 times slower than atanh.
+ *
+ * The code for casinh, casin, cacos, and cacosh comes first.  The code is
+ * rather complicated, and the four functions are highly interdependent.
+ *
+ * The code for catanh and catan comes at the end.  It is much simpler than
+ * the other functions, and the code for these can be disconnected from the
+ * rest of the code.
+ */
+
+/*
+ *                     ================================
+ *                     | casinh, casin, cacos, cacosh |
+ *                     ================================
+ */
+
+/*
+ * The algorithm is very close to that in "Implementing the complex arcsine
+ * and arccosine functions using exception handling" by T. E. Hull, Thomas F.
+ * Fairgrieve, and Ping Tak Peter Tang, published in ACM Transactions on
+ * Mathematical Software, Volume 23 Issue 3, 1997, Pages 299-335,
+ * http://dl.acm.org/citation.cfm?id=275324.
+ *
+ * Throughout we use the convention z = x + I*y.
+ *
+ * casinh(z) = sign(x)*log(A+sqrt(A*A-1)) + I*asin(B)
+ * where
+ * A = (|z+I| + |z-I|) / 2
+ * B = (|z+I| - |z-I|) / 2 = y/A
+ *
+ * These formulas become numerically unstable:
+ *   (a) for Re(casinh(z)) when z is close to the line segment [-I, I] (that
+ *       is, Re(casinh(z)) is close to 0);
+ *   (b) for Im(casinh(z)) when z is close to either of the intervals
+ *       [I, I*infinity) or (-I*infinity, -I] (that is, |Im(casinh(z))| is
+ *       close to PI/2).
+ *
+ * These numerical problems are overcome by defining
+ * f(a, b) = (hypot(a, b) - b) / 2 = a*a / (hypot(a, b) + b) / 2
+ * Then if A < A_crossover, we use
+ *   log(A + sqrt(A*A-1)) = log1p((A-1) + sqrt((A-1)*(A+1)))
+ *   A-1 = f(x, 1+y) + f(x, 1-y)
+ * and if B > B_crossover, we use
+ *   asin(B) = atan2(y, sqrt(A*A - y*y)) = atan2(y, sqrt((A+y)*(A-y)))
+ *   A-y = f(x, y+1) + f(x, y-1)
+ * where without loss of generality we have assumed that x and y are
+ * non-negative.
+ *
+ * Much of the difficulty comes because the intermediate computations may
+ * produce overflows or underflows.  This is dealt with in the paper by Hull
+ * et al by using exception handling.  We do this by detecting when
+ * computations risk underflow or overflow.  The hardest part is handling the
+ * underflows when computing f(a, b).
+ *
+ * Note that the function f(a, b) does not appear explicitly in the paper by
+ * Hull et al, but the idea may be found on pages 308 and 309.  Introducing the
+ * function f(a, b) allows us to concentrate many of the clever tricks in this
+ * paper into one function.
+ */
+
+/*
+ * Function f(a, b, hypot_a_b) = (hypot(a, b) - b) / 2.
+ * Pass hypot(a, b) as the third argument.
+ */
+static inline double
+f(double a, double b, double hypot_a_b)
+{
+       if (b < 0)
+               return ((hypot_a_b - b) / 2);
+       if (b == 0)
+               return (a / 2);
+       return (a * a / (hypot_a_b + b) / 2);
+}
+
+/*
+ * All the hard work is contained in this function.
+ * x and y are assumed positive or zero, and less than RECIP_EPSILON.
+ * Upon return:
+ * rx = Re(casinh(z)) = -Im(cacos(y + I*x)).
+ * B_is_usable is set to 1 if the value of B is usable.
+ * If B_is_usable is set to 0, sqrt_A2my2 = sqrt(A*A - y*y), and new_y = y.
+ * If returning sqrt_A2my2 has potential to result in an underflow, it is
+ * rescaled, and new_y is similarly rescaled.
+ */
+static inline void
+do_hard_work(double x, double y, double *rx, int *B_is_usable, double *B,
+    double *sqrt_A2my2, double *new_y)
+{
+       double R, S, A; /* A, B, R, and S are as in Hull et al. */
+       double Am1, Amy; /* A-1, A-y. */
+
+       R = hypot(x, y + 1);            /* |z+I| */
+       S = hypot(x, y - 1);            /* |z-I| */
+
+       /* A = (|z+I| + |z-I|) / 2 */
+       A = (R + S) / 2;
+       /*
+        * Mathematically A >= 1.  There is a small chance that this will not
+        * be so because of rounding errors.  So we will make certain it is
+        * so.
+        */
+       if (A < 1)
+               A = 1;
+
+       if (A < A_crossover) {
+               /*
+                * Am1 = fp + fm, where fp = f(x, 1+y), and fm = f(x, 1-y).
+                * rx = log1p(Am1 + sqrt(Am1*(A+1)))
+                */
+               if (y == 1 && x < DBL_EPSILON * DBL_EPSILON / 128) {
+                       /*
+                        * fp is of order x^2, and fm = x/2.
+                        * A = 1 (inexactly).
+                        */
+                       *rx = sqrt(x);
+               } else if (x >= DBL_EPSILON * fabs(y - 1)) {
+                       /*
+                        * Underflow will not occur because
+                        * x >= DBL_EPSILON^2/128 >= FOUR_SQRT_MIN
+                        */
+                       Am1 = f(x, 1 + y, R) + f(x, 1 - y, S);
+                       *rx = log1p(Am1 + sqrt(Am1 * (A + 1)));
+               } else if (y < 1) {
+                       /*
+                        * fp = x*x/(1+y)/4, fm = x*x/(1-y)/4, and
+                        * A = 1 (inexactly).
+                        */
+                       *rx = x / sqrt((1 - y) * (1 + y));
+               } else {                /* if (y > 1) */
+                       /*
+                        * A-1 = y-1 (inexactly).
+                        */
+                       *rx = log1p((y - 1) + sqrt((y - 1) * (y + 1)));
+               }
+       } else {
+               *rx = log(A + sqrt(A * A - 1));
+       }
+
+       *new_y = y;
+
+       if (y < FOUR_SQRT_MIN) {
+               /*
+                * Avoid a possible underflow caused by y/A.  For casinh this
+                * would be legitimate, but will be picked up by invoking atan2
+                * later on.  For cacos this would not be legitimate.
+                */
+               *B_is_usable = 0;
+               *sqrt_A2my2 = A * (2 / DBL_EPSILON);
+               *new_y = y * (2 / DBL_EPSILON);
+               return;
+       }
+
+       /* B = (|z+I| - |z-I|) / 2 = y/A */
+       *B = y / A;
+       *B_is_usable = 1;
+
+       if (*B > B_crossover) {
+               *B_is_usable = 0;
+               /*
+                * Amy = fp + fm, where fp = f(x, y+1), and fm = f(x, y-1).
+                * sqrt_A2my2 = sqrt(Amy*(A+y))
+                */
+               if (y == 1 && x < DBL_EPSILON / 128) {
+                       /*
+                        * fp is of order x^2, and fm = x/2.
+                        * A = 1 (inexactly).
+                        */
+                       *sqrt_A2my2 = sqrt(x) * sqrt((A + y) / 2);
+               } else if (x >= DBL_EPSILON * fabs(y - 1)) {
+                       /*
+                        * Underflow will not occur because
+                        * x >= DBL_EPSILON/128 >= FOUR_SQRT_MIN
+                        * and
+                        * x >= DBL_EPSILON^2 >= FOUR_SQRT_MIN
+                        */
+                       Amy = f(x, y + 1, R) + f(x, y - 1, S);
+                       *sqrt_A2my2 = sqrt(Amy * (A + y));
+               } else if (y > 1) {
+                       /*
+                        * fp = x*x/(y+1)/4, fm = x*x/(y-1)/4, and
+                        * A = y (inexactly).
+                        *
+                        * y < RECIP_EPSILON.  So the following
+                        * scaling should avoid any underflow problems.
+                        */
+                       *sqrt_A2my2 = x * (4 / DBL_EPSILON / DBL_EPSILON) * y /
+                           sqrt((y + 1) * (y - 1));
+                       *new_y = y * (4 / DBL_EPSILON / DBL_EPSILON);
+               } else {                /* if (y < 1) */
+                       /*
+                        * fm = 1-y >= DBL_EPSILON, fp is of order x^2, and
+                        * A = 1 (inexactly).
+                        */
+                       *sqrt_A2my2 = sqrt((1 - y) * (1 + y));
+               }
+       }
+}
+
+/*
+ * casinh(z) = z + O(z^3)   as z -> 0
+ *
+ * casinh(z) = sign(x)*clog(sign(x)*z) + O(1/z^2)   as z -> infinity
+ * The above formula works for the imaginary part as well, because
+ * Im(casinh(z)) = sign(x)*atan2(sign(x)*y, fabs(x)) + O(y/z^3)
+ *    as z -> infinity, uniformly in y
+ */
+double complex
+casinh(double complex z)
+{
+       double x, y, ax, ay, rx, ry, B, sqrt_A2my2, new_y;
+       int B_is_usable;
+       double complex w;
+
+       x = creal(z);
+       y = cimag(z);
+       ax = fabs(x);
+       ay = fabs(y);
+
+       if (isnan(x) || isnan(y)) {
+               /* casinh(+-Inf + I*NaN) = +-Inf + I*NaN */
+               if (isinf(x))
+                       return (cpack(x, y + y));
+               /* casinh(NaN + I*+-Inf) = opt(+-)Inf + I*NaN */
+               if (isinf(y))
+                       return (cpack(y, x + x));
+               /* casinh(NaN + I*0) = NaN + I*0 */
+               if (y == 0)
+                       return (cpack(x + x, y));
+               /*
+                * All other cases involving NaN return NaN + I*NaN.
+                * C99 leaves it optional whether to raise invalid if one of
+                * the arguments is not NaN, so we opt not to raise it.
+                */
+               return (cpack(x + 0.0L + (y + 0), x + 0.0L + (y + 0)));
+       }
+
+       if (ax > RECIP_EPSILON || ay > RECIP_EPSILON) {
+               /* clog...() will raise inexact unless x or y is infinite. */
+               if (signbit(x) == 0)
+                       w = clog_for_large_values(z) + m_ln2;
+               else
+                       w = clog_for_large_values(-z) + m_ln2;
+               return (cpack(copysign(creal(w), x), copysign(cimag(w), y)));
+       }
+
+       /* Avoid spuriously raising inexact for z = 0. */
+       if (x == 0 && y == 0)
+               return (z);
+
+       /* All remaining cases are inexact. */
+       raise_inexact();
+
+       if (ax < SQRT_6_EPSILON / 4 && ay < SQRT_6_EPSILON / 4)
+               return (z);
+
+       do_hard_work(ax, ay, &rx, &B_is_usable, &B, &sqrt_A2my2, &new_y);
+       if (B_is_usable)
+               ry = asin(B);
+       else
+               ry = atan2(new_y, sqrt_A2my2);
+       return (cpack(copysign(rx, x), copysign(ry, y)));
+}
+
+/*
+ * casin(z) = reverse(casinh(reverse(z)))
+ * where reverse(x + I*y) = y + I*x = I*conj(z).
+ */
+double complex
+casin(double complex z)
+{
+       double complex w = casinh(cpack(cimag(z), creal(z)));
+
+       return (cpack(cimag(w), creal(w)));
+}
+
+/*
+ * cacos(z) = PI/2 - casin(z)
+ * but do the computation carefully so cacos(z) is accurate when z is
+ * close to 1.
+ *
+ * cacos(z) = PI/2 - z + O(z^3)   as z -> 0
+ *
+ * cacos(z) = -sign(y)*I*clog(z) + O(1/z^2)   as z -> infinity
+ * The above formula works for the real part as well, because
+ * Re(cacos(z)) = atan2(fabs(y), x) + O(y/z^3)
+ *    as z -> infinity, uniformly in y
+ */
+double complex
+cacos(double complex z)
+{
+       double x, y, ax, ay, rx, ry, B, sqrt_A2mx2, new_x;
+       int sx, sy;
+       int B_is_usable;
+       double complex w;
+
+       x = creal(z);
+       y = cimag(z);
+       sx = signbit(x);
+       sy = signbit(y);
+       ax = fabs(x);
+       ay = fabs(y);
+
+       if (isnan(x) || isnan(y)) {
+               /* cacos(+-Inf + I*NaN) = NaN + I*opt(-)Inf */
+               if (isinf(x))
+                       return (cpack(y + y, -INFINITY));
+               /* cacos(NaN + I*+-Inf) = NaN + I*-+Inf */
+               if (isinf(y))
+                       return (cpack(x + x, -y));
+               /* cacos(0 + I*NaN) = PI/2 + I*NaN with inexact */
+               if (x == 0)
+                       return (cpack(pio2_hi + pio2_lo, y + y));
+               /*
+                * All other cases involving NaN return NaN + I*NaN.
+                * C99 leaves it optional whether to raise invalid if one of
+                * the arguments is not NaN, so we opt not to raise it.
+                */
+               return (cpack(x + 0.0L + (y + 0), x + 0.0L + (y + 0)));
+       }
+
+       if (ax > RECIP_EPSILON || ay > RECIP_EPSILON) {
+               /* clog...() will raise inexact unless x or y is infinite. */
+               w = clog_for_large_values(z);
+               rx = fabs(cimag(w));
+               ry = creal(w) + m_ln2;
+               if (sy == 0)
+                       ry = -ry;
+               return (cpack(rx, ry));
+       }
+
+       /* Avoid spuriously raising inexact for z = 1. */
+       if (x == 1 && y == 0)
+               return (cpack(0, -y));
+
+       /* All remaining cases are inexact. */
+       raise_inexact();
+
+       if (ax < SQRT_6_EPSILON / 4 && ay < SQRT_6_EPSILON / 4)
+               return (cpack(pio2_hi - (x - pio2_lo), -y));
+
+       do_hard_work(ay, ax, &ry, &B_is_usable, &B, &sqrt_A2mx2, &new_x);
+       if (B_is_usable) {
+               if (sx == 0)
+                       rx = acos(B);
+               else
+                       rx = acos(-B);
+       } else {
+               if (sx == 0)
+                       rx = atan2(sqrt_A2mx2, new_x);
+               else
+                       rx = atan2(sqrt_A2mx2, -new_x);
+       }
+       if (sy == 0)
+               ry = -ry;
+       return (cpack(rx, ry));
+}
+
+/*
+ * cacosh(z) = I*cacos(z) or -I*cacos(z)
+ * where the sign is chosen so Re(cacosh(z)) >= 0.
+ */
+double complex
+cacosh(double complex z)
+{
+       double complex w;
+       double rx, ry;
+
+       w = cacos(z);
+       rx = creal(w);
+       ry = cimag(w);
+       /* cacosh(NaN + I*NaN) = NaN + I*NaN */
+       if (isnan(rx) && isnan(ry))
+               return (cpack(ry, rx));
+       /* cacosh(NaN + I*+-Inf) = +Inf + I*NaN */
+       /* cacosh(+-Inf + I*NaN) = +Inf + I*NaN */
+       if (isnan(rx))
+               return (cpack(fabs(ry), rx));
+       /* cacosh(0 + I*NaN) = NaN + I*NaN */
+       if (isnan(ry))
+               return (cpack(ry, ry));
+       return (cpack(fabs(ry), copysign(rx, cimag(z))));
+}
+
+/*
+ * Optimized version of clog() for |z| finite and larger than ~RECIP_EPSILON.
+ */
+static double complex
+clog_for_large_values(double complex z)
+{
+       double x, y;
+       double ax, ay, t;
+
+       x = creal(z);
+       y = cimag(z);
+       ax = fabs(x);
+       ay = fabs(y);
+       if (ax < ay) {
+               t = ax;
+               ax = ay;
+               ay = t;
+       }
+
+       /*
+        * Avoid overflow in hypot() when x and y are both very large.
+        * Divide x and y by E, and then add 1 to the logarithm.  This depends
+        * on E being larger than sqrt(2).
+        * Dividing by E causes an insignificant loss of accuracy; however
+        * this method is still poor since it is uneccessarily slow.
+        */
+       if (ax > DBL_MAX / 2)
+               return (cpack(log(hypot(x / m_e, y / m_e)) + 1, atan2(y, x)));
+
+       /*
+        * Avoid overflow when x or y is large.  Avoid underflow when x or
+        * y is small.
+        */
+       if (ax > QUARTER_SQRT_MAX || ay < SQRT_MIN)
+               return (cpack(log(hypot(x, y)), atan2(y, x)));
+
+       return (cpack(log(ax * ax + ay * ay) / 2, atan2(y, x)));
+}
+
+/*
+ *                             =================
+ *                             | catanh, catan |
+ *                             =================
+ */
+
+/*
+ * sum_squares(x,y) = x*x + y*y (or just x*x if y*y would underflow).
+ * Assumes x*x and y*y will not overflow.
+ * Assumes x and y are finite.
+ * Assumes y is non-negative.
+ * Assumes fabs(x) >= DBL_EPSILON.
+ */
+static inline double
+sum_squares(double x, double y)
+{
+
+       /* Avoid underflow when y is small. */
+       if (y < SQRT_MIN)
+               return (x * x);
+
+       return (x * x + y * y);
+}
+
+/*
+ * real_part_reciprocal(x, y) = Re(1/(x+I*y)) = x/(x*x + y*y).
+ * Assumes x and y are not NaN, and one of x and y is larger than
+ * RECIP_EPSILON.  We avoid unwarranted underflow.  It is important to not use
+ * the code creal(1/z), because the imaginary part may produce an unwanted
+ * underflow.
+ * This is only called in a context where inexact is always raised before
+ * the call, so no effort is made to avoid or force inexact.
+ */
+static inline double
+real_part_reciprocal(double x, double y)
+{
+       double scale;
+       uint32_t hx, hy;
+       int32_t ix, iy;
+
+       /*
+        * This code is inspired by the C99 document n1124.pdf, Section G.5.1,
+        * example 2.
+        */
+       GET_HIGH_WORD(hx, x);
+       ix = hx & 0x7ff00000;
+       GET_HIGH_WORD(hy, y);
+       iy = hy & 0x7ff00000;
+#define        BIAS    (DBL_MAX_EXP - 1)
+/* XXX more guard digits are useful iff there is extra precision. */
+#define        CUTOFF  (DBL_MANT_DIG / 2 + 1)  /* just half or 1 guard digit */
+       if (ix - iy >= CUTOFF << 20 || isinf(x))
+               return (1 / x);         /* +-Inf -> +-0 is special */
+       if (iy - ix >= CUTOFF << 20)
+               return (x / y / y);     /* should avoid double div, but hard */
+       if (ix <= (BIAS + DBL_MAX_EXP / 2 - CUTOFF) << 20)
+               return (x / (x * x + y * y));
+       scale = 1;
+       SET_HIGH_WORD(scale, 0x7ff00000 - ix);  /* 2**(1-ilogb(x)) */
+       x *= scale;
+       y *= scale;
+       return (x / (x * x + y * y) * scale);
+}
+
+/*
+ * catanh(z) = log((1+z)/(1-z)) / 2
+ *           = log1p(4*x / |z-1|^2) / 4
+ *             + I * atan2(2*y, (1-x)*(1+x)-y*y) / 2
+ *
+ * catanh(z) = z + O(z^3)   as z -> 0
+ *
+ * catanh(z) = 1/z + sign(y)*I*PI/2 + O(1/z^3)   as z -> infinity
+ * The above formula works for the real part as well, because
+ * Re(catanh(z)) = x/|z|^2 + O(x/z^4)
+ *    as z -> infinity, uniformly in x
+ */
+double complex
+catanh(double complex z)
+{
+       double x, y, ax, ay, rx, ry;
+
+       x = creal(z);
+       y = cimag(z);
+       ax = fabs(x);
+       ay = fabs(y);
+
+       /* This helps handle many cases. */
+       if (y == 0 && ax <= 1)
+               return (cpack(atanh(x), y));
+
+       /* To ensure the same accuracy as atan(), and to filter out z = 0. */
+       if (x == 0)
+               return (cpack(x, atan(y)));
+
+       if (isnan(x) || isnan(y)) {
+               /* catanh(+-Inf + I*NaN) = +-0 + I*NaN */
+               if (isinf(x))
+                       return (cpack(copysign(0, x), y + y));
+               /* catanh(NaN + I*+-Inf) = sign(NaN)0 + I*+-PI/2 */
+               if (isinf(y))
+                       return (cpack(copysign(0, x),
+                           copysign(pio2_hi + pio2_lo, y)));
+               /*
+                * All other cases involving NaN return NaN + I*NaN.
+                * C99 leaves it optional whether to raise invalid if one of
+                * the arguments is not NaN, so we opt not to raise it.
+                */
+               return (cpack(x + 0.0L + (y + 0), x + 0.0L + (y + 0)));
+       }
+
+       if (ax > RECIP_EPSILON || ay > RECIP_EPSILON)
+               return (cpack(real_part_reciprocal(x, y),
+                   copysign(pio2_hi + pio2_lo, y)));
+
+       if (ax < SQRT_3_EPSILON / 2 && ay < SQRT_3_EPSILON / 2) {
+               /*
+                * z = 0 was filtered out above.  All other cases must raise
+                * inexact, but this is the only only that needs to do it
+                * explicitly.
+                */
+               raise_inexact();
+               return (z);
+       }
+
+       if (ax == 1 && ay < DBL_EPSILON)
+               rx = (m_ln2 - log(ay)) / 2;
+       else
+               rx = log1p(4 * ax / sum_squares(ax - 1, ay)) / 4;
+
+       if (ax == 1)
+               ry = atan2(2, -ay) / 2;
+       else if (ay < DBL_EPSILON)
+               ry = atan2(2 * ay, (1 - ax) * (1 + ax)) / 2;
+       else
+               ry = atan2(2 * ay, (1 - ax) * (1 + ax) - ay * ay) / 2;
+
+       return (cpack(copysign(rx, x), copysign(ry, y)));
+}
+
+/*
+ * catan(z) = reverse(catanh(reverse(z)))
+ * where reverse(x + I*y) = y + I*x = I*conj(z).
+ */
+double complex
+catan(double complex z)
+{
+       double complex w = catanh(cpack(cimag(z), creal(z)));
+
+       return (cpack(cimag(w), creal(w)));
+}
diff --git a/libm/upstream-freebsd/lib/msun/src/catrigf.c b/libm/upstream-freebsd/lib/msun/src/catrigf.c
new file mode 100644 (file)
index 0000000..08ebef7
--- /dev/null
@@ -0,0 +1,393 @@
+/*-
+ * Copyright (c) 2012 Stephen Montgomery-Smith <stephen@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * The algorithm is very close to that in "Implementing the complex arcsine
+ * and arccosine functions using exception handling" by T. E. Hull, Thomas F.
+ * Fairgrieve, and Ping Tak Peter Tang, published in ACM Transactions on
+ * Mathematical Software, Volume 23 Issue 3, 1997, Pages 299-335,
+ * http://dl.acm.org/citation.cfm?id=275324.
+ *
+ * See catrig.c for complete comments.
+ *
+ * XXX comments were removed automatically, and even short ones on the right
+ * of statements were removed (all of them), contrary to normal style.  Only
+ * a few comments on the right of declarations remain.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <complex.h>
+#include <float.h>
+
+#include "math.h"
+#include "math_private.h"
+
+#undef isinf
+#define isinf(x)       (fabsf(x) == INFINITY)
+#undef isnan
+#define isnan(x)       ((x) != (x))
+#define        raise_inexact() do { volatile float junk = 1 + tiny; } while(0)
+#undef signbit
+#define signbit(x)     (__builtin_signbitf(x))
+
+static const float
+A_crossover =          10,
+B_crossover =          0.6417,
+FOUR_SQRT_MIN =                0x1p-61,
+QUARTER_SQRT_MAX =     0x1p61,
+m_e =                  2.7182818285e0,         /*  0xadf854.0p-22 */
+m_ln2 =                        6.9314718056e-1,        /*  0xb17218.0p-24 */
+pio2_hi =              1.5707962513e0,         /*  0xc90fda.0p-23 */
+RECIP_EPSILON =                1 / FLT_EPSILON,
+SQRT_3_EPSILON =       5.9801995673e-4,        /*  0x9cc471.0p-34 */
+SQRT_6_EPSILON =       8.4572793338e-4,        /*  0xddb3d7.0p-34 */
+SQRT_MIN =             0x1p-63;
+
+static const volatile float
+pio2_lo =              7.5497899549e-8,        /*  0xa22169.0p-47 */
+tiny =                 0x1p-100;
+
+static float complex clog_for_large_values(float complex z);
+
+static inline float
+f(float a, float b, float hypot_a_b)
+{
+       if (b < 0)
+               return ((hypot_a_b - b) / 2);
+       if (b == 0)
+               return (a / 2);
+       return (a * a / (hypot_a_b + b) / 2);
+}
+
+static inline void
+do_hard_work(float x, float y, float *rx, int *B_is_usable, float *B,
+    float *sqrt_A2my2, float *new_y)
+{
+       float R, S, A;
+       float Am1, Amy;
+
+       R = hypotf(x, y + 1);
+       S = hypotf(x, y - 1);
+
+       A = (R + S) / 2;
+       if (A < 1)
+               A = 1;
+
+       if (A < A_crossover) {
+               if (y == 1 && x < FLT_EPSILON * FLT_EPSILON / 128) {
+                       *rx = sqrtf(x);
+               } else if (x >= FLT_EPSILON * fabsf(y - 1)) {
+                       Am1 = f(x, 1 + y, R) + f(x, 1 - y, S);
+                       *rx = log1pf(Am1 + sqrtf(Am1 * (A + 1)));
+               } else if (y < 1) {
+                       *rx = x / sqrtf((1 - y) * (1 + y));
+               } else {
+                       *rx = log1pf((y - 1) + sqrtf((y - 1) * (y + 1)));
+               }
+       } else {
+               *rx = logf(A + sqrtf(A * A - 1));
+       }
+
+       *new_y = y;
+
+       if (y < FOUR_SQRT_MIN) {
+               *B_is_usable = 0;
+               *sqrt_A2my2 = A * (2 / FLT_EPSILON);
+               *new_y = y * (2 / FLT_EPSILON);
+               return;
+       }
+
+       *B = y / A;
+       *B_is_usable = 1;
+
+       if (*B > B_crossover) {
+               *B_is_usable = 0;
+               if (y == 1 && x < FLT_EPSILON / 128) {
+                       *sqrt_A2my2 = sqrtf(x) * sqrtf((A + y) / 2);
+               } else if (x >= FLT_EPSILON * fabsf(y - 1)) {
+                       Amy = f(x, y + 1, R) + f(x, y - 1, S);
+                       *sqrt_A2my2 = sqrtf(Amy * (A + y));
+               } else if (y > 1) {
+                       *sqrt_A2my2 = x * (4 / FLT_EPSILON / FLT_EPSILON) * y /
+                           sqrtf((y + 1) * (y - 1));
+                       *new_y = y * (4 / FLT_EPSILON / FLT_EPSILON);
+               } else {
+                       *sqrt_A2my2 = sqrtf((1 - y) * (1 + y));
+               }
+       }
+}
+
+float complex
+casinhf(float complex z)
+{
+       float x, y, ax, ay, rx, ry, B, sqrt_A2my2, new_y;
+       int B_is_usable;
+       float complex w;
+
+       x = crealf(z);
+       y = cimagf(z);
+       ax = fabsf(x);
+       ay = fabsf(y);
+
+       if (isnan(x) || isnan(y)) {
+               if (isinf(x))
+                       return (cpackf(x, y + y));
+               if (isinf(y))
+                       return (cpackf(y, x + x));
+               if (y == 0)
+                       return (cpackf(x + x, y));
+               return (cpackf(x + 0.0L + (y + 0), x + 0.0L + (y + 0)));
+       }
+
+       if (ax > RECIP_EPSILON || ay > RECIP_EPSILON) {
+               if (signbit(x) == 0)
+                       w = clog_for_large_values(z) + m_ln2;
+               else
+                       w = clog_for_large_values(-z) + m_ln2;
+               return (cpackf(copysignf(crealf(w), x),
+                   copysignf(cimagf(w), y)));
+       }
+
+       if (x == 0 && y == 0)
+               return (z);
+
+       raise_inexact();
+
+       if (ax < SQRT_6_EPSILON / 4 && ay < SQRT_6_EPSILON / 4)
+               return (z);
+
+       do_hard_work(ax, ay, &rx, &B_is_usable, &B, &sqrt_A2my2, &new_y);
+       if (B_is_usable)
+               ry = asinf(B);
+       else
+               ry = atan2f(new_y, sqrt_A2my2);
+       return (cpackf(copysignf(rx, x), copysignf(ry, y)));
+}
+
+float complex
+casinf(float complex z)
+{
+       float complex w = casinhf(cpackf(cimagf(z), crealf(z)));
+
+       return (cpackf(cimagf(w), crealf(w)));
+}
+
+float complex
+cacosf(float complex z)
+{
+       float x, y, ax, ay, rx, ry, B, sqrt_A2mx2, new_x;
+       int sx, sy;
+       int B_is_usable;
+       float complex w;
+
+       x = crealf(z);
+       y = cimagf(z);
+       sx = signbit(x);
+       sy = signbit(y);
+       ax = fabsf(x);
+       ay = fabsf(y);
+
+       if (isnan(x) || isnan(y)) {
+               if (isinf(x))
+                       return (cpackf(y + y, -INFINITY));
+               if (isinf(y))
+                       return (cpackf(x + x, -y));
+               if (x == 0)
+                       return (cpackf(pio2_hi + pio2_lo, y + y));
+               return (cpackf(x + 0.0L + (y + 0), x + 0.0L + (y + 0)));
+       }
+
+       if (ax > RECIP_EPSILON || ay > RECIP_EPSILON) {
+               w = clog_for_large_values(z);
+               rx = fabsf(cimagf(w));
+               ry = crealf(w) + m_ln2;
+               if (sy == 0)
+                       ry = -ry;
+               return (cpackf(rx, ry));
+       }
+
+       if (x == 1 && y == 0)
+               return (cpackf(0, -y));
+
+       raise_inexact();
+
+       if (ax < SQRT_6_EPSILON / 4 && ay < SQRT_6_EPSILON / 4)
+               return (cpackf(pio2_hi - (x - pio2_lo), -y));
+
+       do_hard_work(ay, ax, &ry, &B_is_usable, &B, &sqrt_A2mx2, &new_x);
+       if (B_is_usable) {
+               if (sx == 0)
+                       rx = acosf(B);
+               else
+                       rx = acosf(-B);
+       } else {
+               if (sx == 0)
+                       rx = atan2f(sqrt_A2mx2, new_x);
+               else
+                       rx = atan2f(sqrt_A2mx2, -new_x);
+       }
+       if (sy == 0)
+               ry = -ry;
+       return (cpackf(rx, ry));
+}
+
+float complex
+cacoshf(float complex z)
+{
+       float complex w;
+       float rx, ry;
+
+       w = cacosf(z);
+       rx = crealf(w);
+       ry = cimagf(w);
+       if (isnan(rx) && isnan(ry))
+               return (cpackf(ry, rx));
+       if (isnan(rx))
+               return (cpackf(fabsf(ry), rx));
+       if (isnan(ry))
+               return (cpackf(ry, ry));
+       return (cpackf(fabsf(ry), copysignf(rx, cimagf(z))));
+}
+
+static float complex
+clog_for_large_values(float complex z)
+{
+       float x, y;
+       float ax, ay, t;
+
+       x = crealf(z);
+       y = cimagf(z);
+       ax = fabsf(x);
+       ay = fabsf(y);
+       if (ax < ay) {
+               t = ax;
+               ax = ay;
+               ay = t;
+       }
+
+       if (ax > FLT_MAX / 2)
+               return (cpackf(logf(hypotf(x / m_e, y / m_e)) + 1,
+                   atan2f(y, x)));
+
+       if (ax > QUARTER_SQRT_MAX || ay < SQRT_MIN)
+               return (cpackf(logf(hypotf(x, y)), atan2f(y, x)));
+
+       return (cpackf(logf(ax * ax + ay * ay) / 2, atan2f(y, x)));
+}
+
+static inline float
+sum_squares(float x, float y)
+{
+
+       if (y < SQRT_MIN)
+               return (x * x);
+
+       return (x * x + y * y);
+}
+
+static inline float
+real_part_reciprocal(float x, float y)
+{
+       float scale;
+       uint32_t hx, hy;
+       int32_t ix, iy;
+
+       GET_FLOAT_WORD(hx, x);
+       ix = hx & 0x7f800000;
+       GET_FLOAT_WORD(hy, y);
+       iy = hy & 0x7f800000;
+#define        BIAS    (FLT_MAX_EXP - 1)
+#define        CUTOFF  (FLT_MANT_DIG / 2 + 1)
+       if (ix - iy >= CUTOFF << 23 || isinf(x))
+               return (1 / x);
+       if (iy - ix >= CUTOFF << 23)
+               return (x / y / y);
+       if (ix <= (BIAS + FLT_MAX_EXP / 2 - CUTOFF) << 23)
+               return (x / (x * x + y * y));
+       SET_FLOAT_WORD(scale, 0x7f800000 - ix);
+       x *= scale;
+       y *= scale;
+       return (x / (x * x + y * y) * scale);
+}
+
+float complex
+catanhf(float complex z)
+{
+       float x, y, ax, ay, rx, ry;
+
+       x = crealf(z);
+       y = cimagf(z);
+       ax = fabsf(x);
+       ay = fabsf(y);
+
+       if (y == 0 && ax <= 1)
+               return (cpackf(atanhf(x), y));
+
+       if (x == 0)
+               return (cpackf(x, atanf(y)));
+
+       if (isnan(x) || isnan(y)) {
+               if (isinf(x))
+                       return (cpackf(copysignf(0, x), y + y));
+               if (isinf(y))
+                       return (cpackf(copysignf(0, x),
+                           copysignf(pio2_hi + pio2_lo, y)));
+               return (cpackf(x + 0.0L + (y + 0), x + 0.0L + (y + 0)));
+       }
+
+       if (ax > RECIP_EPSILON || ay > RECIP_EPSILON)
+               return (cpackf(real_part_reciprocal(x, y),
+                   copysignf(pio2_hi + pio2_lo, y)));
+
+       if (ax < SQRT_3_EPSILON / 2 && ay < SQRT_3_EPSILON / 2) {
+               raise_inexact();
+               return (z);
+       }
+
+       if (ax == 1 && ay < FLT_EPSILON)
+               rx = (m_ln2 - logf(ay)) / 2;
+       else
+               rx = log1pf(4 * ax / sum_squares(ax - 1, ay)) / 4;
+
+       if (ax == 1)
+               ry = atan2f(2, -ay) / 2;
+       else if (ay < FLT_EPSILON)
+               ry = atan2f(2 * ay, (1 - ax) * (1 + ax)) / 2;
+       else
+               ry = atan2f(2 * ay, (1 - ax) * (1 + ax) - ay * ay) / 2;
+
+       return (cpackf(copysignf(rx, x), copysignf(ry, y)));
+}
+
+float complex
+catanf(float complex z)
+{
+       float complex w = catanhf(cpackf(cimagf(z), crealf(z)));
+
+       return (cpackf(cimagf(w), crealf(w)));
+}
index 1a7a5e063382a0429cc74fdc63b429cafba79b3c..5e0c593f7e260e52e920e4cbb6339846c4f83c4e 100644 (file)
@@ -54,6 +54,7 @@ test_cppflags = \
 libBionicStandardTests_src_files := \
     arpa_inet_test.cpp \
     buffer_tests.cpp \
+    complex_test.cpp \
     ctype_test.cpp \
     dirent_test.cpp \
     eventfd_test.cpp \
diff --git a/tests/complex_test.cpp b/tests/complex_test.cpp
new file mode 100644 (file)
index 0000000..47964f6
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+// libc++ actively gets in the way of including <complex.h> from C++, so we
+// have to declare the complex math functions ourselves.
+// (libc++ also seems to have really bad implementations of its own that ignore
+// the intricacies of floating point math.)
+// http://llvm.org/bugs/show_bug.cgi?id=21504
+
+#include <math.h> // For M_PI.
+
+extern "C" double cabs(double _Complex);
+TEST(complex, cabs) {
+  ASSERT_EQ(0.0, cabs(0));
+}
+
+extern "C" float cabsf(float _Complex);
+TEST(complex, cabsf) {
+  ASSERT_EQ(0.0, cabsf(0));
+}
+
+extern "C" long double cabsl(long double _Complex);
+TEST(complex, cabsl) {
+  ASSERT_EQ(0.0, cabsl(0));
+}
+
+extern "C" double _Complex cacos(double _Complex);
+TEST(complex, cacos) {
+  ASSERT_EQ(M_PI/2.0, cacos(0.0));
+}
+
+extern "C" float _Complex cacosf(float _Complex);
+TEST(complex, cacosf) {
+  ASSERT_EQ(static_cast<float>(M_PI)/2.0f, cacosf(0.0));
+}
+
+extern "C" double _Complex cacosh(double _Complex);
+TEST(complex, cacosh) {
+  ASSERT_EQ(0.0, cacosh(1.0));
+}
+
+extern "C" float _Complex cacoshf(float _Complex);
+TEST(complex, cacoshf) {
+  ASSERT_EQ(0.0, cacoshf(1.0));
+}
+
+extern "C" double carg(double _Complex);
+TEST(complex, carg) {
+  ASSERT_EQ(0.0, carg(0));
+}
+
+extern "C" float cargf(float _Complex);
+TEST(complex, cargf) {
+  ASSERT_EQ(0.0, cargf(0));
+}
+
+extern "C" long double cargl(long double _Complex);
+TEST(complex, cargl) {
+  ASSERT_EQ(0.0, cargl(0));
+}
+
+extern "C" double _Complex casin(double _Complex);
+TEST(complex, casin) {
+  ASSERT_EQ(0.0, casin(0));
+}
+
+extern "C" float _Complex casinf(float _Complex);
+TEST(complex, casinf) {
+  ASSERT_EQ(0.0, casinf(0));
+}
+
+extern "C" double _Complex casinh(double _Complex);
+TEST(complex, casinh) {
+  ASSERT_EQ(0.0, casinh(0));
+}
+
+extern "C" float _Complex casinhf(float _Complex);
+TEST(complex, casinhf) {
+  ASSERT_EQ(0.0, casinhf(0));
+}
+
+extern "C" double _Complex catan(double _Complex);
+TEST(complex, catan) {
+  ASSERT_EQ(0.0, catan(0));
+}
+
+extern "C" float _Complex catanf(float _Complex);
+TEST(complex, catanf) {
+  ASSERT_EQ(0.0, catanf(0));
+}
+
+extern "C" double _Complex catanh(double _Complex);
+TEST(complex, catanh) {
+  ASSERT_EQ(0.0, catanh(0));
+}
+
+extern "C" float _Complex catanhf(float _Complex);
+TEST(complex, catanhf) {
+  ASSERT_EQ(0.0, catanhf(0));
+}
+
+extern "C" double _Complex ccos(double _Complex);
+TEST(complex, ccos) {
+  ASSERT_EQ(1.0, ccos(0));
+}
+
+extern "C" float _Complex ccosf(float _Complex);
+TEST(complex, ccosf) {
+  ASSERT_EQ(1.0, ccosf(0));
+}
+
+extern "C" double _Complex ccosh(double _Complex);
+TEST(complex, ccosh) {
+  ASSERT_EQ(1.0, ccosh(0));
+}
+
+extern "C" float _Complex ccoshf(float _Complex);
+TEST(complex, ccoshf) {
+  ASSERT_EQ(1.0, ccoshf(0));
+}
+
+extern "C" double _Complex cexp(double _Complex);
+TEST(complex, cexp) {
+  ASSERT_EQ(1.0, cexp(0));
+}
+
+extern "C" float _Complex cexpf(float _Complex);
+TEST(complex, cexpf) {
+  ASSERT_EQ(1.0, cexpf(0));
+}
+
+extern "C" double cimag(double _Complex);
+TEST(complex, cimag) {
+  ASSERT_EQ(0.0, cimag(0));
+}
+
+extern "C" float cimagf(float _Complex);
+TEST(complex, cimagf) {
+  ASSERT_EQ(0.0f, cimagf(0));
+}
+
+extern "C" long double cimagl(long double _Complex);
+TEST(complex, cimagl) {
+  ASSERT_EQ(0.0, cimagl(0));
+}
+
+extern "C" double _Complex conj(double _Complex);
+TEST(complex, conj) {
+  ASSERT_EQ(0.0, conj(0));
+}
+
+extern "C" float _Complex conjf(float _Complex);
+TEST(complex, conjf) {
+  ASSERT_EQ(0.0f, conjf(0));
+}
+
+extern "C" long double _Complex conjl(long double _Complex);
+TEST(complex, conjl) {
+  ASSERT_EQ(0.0, conjl(0));
+}
+
+extern "C" double _Complex cproj(double _Complex);
+TEST(complex, cproj) {
+  ASSERT_EQ(0.0, cproj(0));
+}
+
+extern "C" float _Complex cprojf(float _Complex);
+TEST(complex, cprojf) {
+  ASSERT_EQ(0.0f, cprojf(0));
+}
+
+extern "C" long double _Complex cprojl(long double _Complex);
+TEST(complex, cprojl) {
+  ASSERT_EQ(0.0, cprojl(0));
+}
+
+extern "C" double creal(double _Complex);
+TEST(complex, creal) {
+  ASSERT_EQ(0.0, creal(0));
+}
+
+extern "C" float crealf(float _Complex);
+TEST(complex, crealf) {
+  ASSERT_EQ(0.0f, crealf(0));
+}
+
+extern "C" long double creall(long double _Complex);
+TEST(complex, creall) {
+  ASSERT_EQ(0.0, creall(0));
+}
+
+extern "C" double _Complex csin(double _Complex);
+TEST(complex, csin) {
+  ASSERT_EQ(0.0, csin(0));
+}
+
+extern "C" float _Complex csinf(float _Complex);
+TEST(complex, csinf) {
+  ASSERT_EQ(0.0, csinf(0));
+}
+
+extern "C" double _Complex csinh(double _Complex);
+TEST(complex, csinh) {
+  ASSERT_EQ(0.0, csinh(0));
+}
+
+extern "C" float _Complex csinhf(float _Complex);
+TEST(complex, csinhf) {
+  ASSERT_EQ(0.0, csinhf(0));
+}
+
+extern "C" double _Complex csqrt(double _Complex);
+TEST(complex, csqrt) {
+  ASSERT_EQ(0.0, csqrt(0));
+}
+
+extern "C" float _Complex csqrtf(float _Complex);
+TEST(complex, csqrtf) {
+  ASSERT_EQ(0.0f, csqrt(0));
+}
+
+extern "C" long double _Complex csqrtl(long double _Complex);
+TEST(complex, csqrtl) {
+  ASSERT_EQ(0.0, csqrtl(0));
+}
+
+extern "C" double _Complex ctan(double _Complex);
+TEST(complex, ctan) {
+  ASSERT_EQ(0.0, ctan(0));
+}
+
+extern "C" float _Complex ctanf(float _Complex);
+TEST(complex, ctanf) {
+  ASSERT_EQ(0.0, ctanf(0));
+}
+
+extern "C" double _Complex ctanh(double _Complex);
+TEST(complex, ctanh) {
+  ASSERT_EQ(0.0, ctanh(0));
+}
+
+extern "C" float _Complex ctanhf(float _Complex);
+TEST(complex, ctanhf) {
+  ASSERT_EQ(0.0, ctanhf(0));
+}
index 421cd8263d25025141c63a0cbfe1e7cae920da2b..050f5a766265d1a62c9a47683d1c99020f16f8d4 100644 (file)
 #include <sys/types.h>
 #include <sys/wait.h>
 
+// The random number generator tests all set the seed, get four values, reset the seed and check
+// that they get the first two values repeated, and then reset the seed and check two more values
+// to rule out the possibility that we're just going round a cycle of four values.
+// TODO: factor this out.
+
 TEST(stdlib, drand48) {
   srand48(0x01020304);
   EXPECT_DOUBLE_EQ(0.65619299195623526, drand48());
   EXPECT_DOUBLE_EQ(0.18522597229772941, drand48());
   EXPECT_DOUBLE_EQ(0.42015087072844537, drand48());
   EXPECT_DOUBLE_EQ(0.061637783047395089, drand48());
+  srand48(0x01020304);
+  EXPECT_DOUBLE_EQ(0.65619299195623526, drand48());
+  EXPECT_DOUBLE_EQ(0.18522597229772941, drand48());
+  srand48(0x01020304);
+  EXPECT_DOUBLE_EQ(0.65619299195623526, drand48());
+  EXPECT_DOUBLE_EQ(0.18522597229772941, drand48());
+}
+
+TEST(stdlib, erand48) {
+  const unsigned short seed[3] = { 0x330e, 0xabcd, 0x1234 };
+  unsigned short xsubi[3];
+  memcpy(xsubi, seed, sizeof(seed));
+  EXPECT_DOUBLE_EQ(0.39646477376027534, erand48(xsubi));
+  EXPECT_DOUBLE_EQ(0.84048536941142515, erand48(xsubi));
+  EXPECT_DOUBLE_EQ(0.35333609724524351, erand48(xsubi));
+  EXPECT_DOUBLE_EQ(0.44658343479654405, erand48(xsubi));
+  memcpy(xsubi, seed, sizeof(seed));
+  EXPECT_DOUBLE_EQ(0.39646477376027534, erand48(xsubi));
+  EXPECT_DOUBLE_EQ(0.84048536941142515, erand48(xsubi));
+  memcpy(xsubi, seed, sizeof(seed));
+  EXPECT_DOUBLE_EQ(0.39646477376027534, erand48(xsubi));
+  EXPECT_DOUBLE_EQ(0.84048536941142515, erand48(xsubi));
+}
+
+TEST(stdlib, lcong48) {
+  unsigned short p[7] = { 0x0102, 0x0304, 0x0506, 0x0708, 0x090a, 0x0b0c, 0x0d0e };
+  lcong48(p);
+  EXPECT_EQ(1531389981, lrand48());
+  EXPECT_EQ(1598801533, lrand48());
+  EXPECT_EQ(2080534853, lrand48());
+  EXPECT_EQ(1102488897, lrand48());
+  lcong48(p);
+  EXPECT_EQ(1531389981, lrand48());
+  EXPECT_EQ(1598801533, lrand48());
+  lcong48(p);
+  EXPECT_EQ(1531389981, lrand48());
+  EXPECT_EQ(1598801533, lrand48());
 }
 
 TEST(stdlib, lrand48) {
@@ -42,6 +84,12 @@ TEST(stdlib, lrand48) {
   EXPECT_EQ(397769746, lrand48());
   EXPECT_EQ(902267124, lrand48());
   EXPECT_EQ(132366131, lrand48());
+  srand48(0x01020304);
+  EXPECT_EQ(1409163720, lrand48());
+  EXPECT_EQ(397769746, lrand48());
+  srand48(0x01020304);
+  EXPECT_EQ(1409163720, lrand48());
+  EXPECT_EQ(397769746, lrand48());
 }
 
 TEST(stdlib, random) {
@@ -50,6 +98,12 @@ TEST(stdlib, random) {
   EXPECT_EQ(1399865117, random());
   EXPECT_EQ(2032643283, random());
   EXPECT_EQ(571329216, random());
+  srandom(0x01020304);
+  EXPECT_EQ(55436735, random());
+  EXPECT_EQ(1399865117, random());
+  srandom(0x01020304);
+  EXPECT_EQ(55436735, random());
+  EXPECT_EQ(1399865117, random());
 }
 
 TEST(stdlib, rand) {
@@ -58,6 +112,12 @@ TEST(stdlib, rand) {
   EXPECT_EQ(1399865117, rand());
   EXPECT_EQ(2032643283, rand());
   EXPECT_EQ(571329216, rand());
+  srand(0x01020304);
+  EXPECT_EQ(55436735, rand());
+  EXPECT_EQ(1399865117, rand());
+  srand(0x01020304);
+  EXPECT_EQ(55436735, rand());
+  EXPECT_EQ(1399865117, rand());
 }
 
 TEST(stdlib, mrand48) {
@@ -66,6 +126,12 @@ TEST(stdlib, mrand48) {
   EXPECT_EQ(795539493, mrand48());
   EXPECT_EQ(1804534249, mrand48());
   EXPECT_EQ(264732262, mrand48());
+  srand48(0x01020304);
+  EXPECT_EQ(-1476639856, mrand48());
+  EXPECT_EQ(795539493, mrand48());
+  srand48(0x01020304);
+  EXPECT_EQ(-1476639856, mrand48());
+  EXPECT_EQ(795539493, mrand48());
 }
 
 TEST(stdlib, posix_memalign) {
index 6ecbb6470116738431067568cb73e8acd173bcb7..137565e25082c89b4547fa1053737868968797f9 100644 (file)
 
 #include "buffer_tests.h"
 
+#if defined(__BIONIC__)
+#define STRLCPY_SUPPORTED
+#define STRLCAT_SUPPORTED
+#endif
+
 #define KB 1024
 #define SMALL 1*KB
 #define MEDIUM 4*KB
@@ -70,7 +75,7 @@ TEST(string, strerror_concurrent) {
 
   ASSERT_STREQ("Unknown error 1001", strerror1001);
 #else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
+  GTEST_LOG_(INFO) << "Skipping test, requires a thread safe strerror.";
 #endif // __BIONIC__
 }
 
@@ -532,7 +537,7 @@ TEST(string, strcpy) {
 }
 
 TEST(string, strlcat) {
-#if defined(__BIONIC__)
+#if defined(STRLCAT_SUPPORTED)
   StringTestState<char> state(SMALL);
   for (size_t i = 0; i < state.n; i++) {
     for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
@@ -555,13 +560,13 @@ TEST(string, strlcat) {
       ASSERT_TRUE(memcmp(state.ptr, state.ptr2, state.MAX_LEN + state.len[i]) == 0);
     }
   }
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif // __BIONIC__
+#else
+  GTEST_LOG_(INFO) << "Skipping test, strlcat not supported on this platform.";
+#endif
 }
 
 TEST(string, strlcpy) {
-#if defined(__BIONIC__)
+#if defined(STRLCPY_SUPPORTED)
   StringTestState<char> state(SMALL);
   for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
     int rand = 'O';
@@ -587,9 +592,9 @@ TEST(string, strlcpy) {
     ASSERT_FALSE((memcmp(state.ptr1, state.ptr, state.MAX_LEN) != 0) ||
                  (memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN) != 0));
   }
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif // __BIONIC__
+#else
+  GTEST_LOG_(INFO) << "Skipping test, strlcpy not supported on this platform.";
+#endif
 }
 
 TEST(string, strncat) {
@@ -1100,6 +1105,36 @@ TEST(string, strcpy_overread) {
   RunSrcDstBufferOverreadTest(DoStrcpyTest);
 }
 
+#if defined(STRLCPY_SUPPORTED)
+static void DoStrlcpyTest(uint8_t* src, uint8_t* dst, size_t len) {
+  if (len >= 1) {
+    memset(src, (32 + (len % 96)), len - 1);
+    src[len-1] = '\0';
+    memset(dst, 0, len);
+    ASSERT_EQ(len-1, strlcpy(reinterpret_cast<char*>(dst),
+                             reinterpret_cast<char*>(src), len));
+    ASSERT_TRUE(memcmp(src, dst, len) == 0);
+  }
+}
+#endif
+
+TEST(string, strlcpy_align) {
+#if defined(STRLCPY_SUPPORTED)
+  RunSrcDstBufferAlignTest(LARGE, DoStrlcpyTest);
+#else
+  GTEST_LOG_(INFO) << "Skipping test, strlcpy not supported on this platform.";
+#endif
+}
+
+TEST(string, strlcpy_overread) {
+#if defined(STRLCPY_SUPPORTED)
+  RunSrcDstBufferOverreadTest(DoStrlcpyTest);
+#else
+  GTEST_LOG_(INFO) << "Skipping test, strlcpy not supported on this platform.";
+#endif
+}
+
+
 static void DoStpcpyTest(uint8_t* src, uint8_t* dst, size_t len) {
   if (len >= 1) {
     memset(src, (32 + (len % 96)), len - 1);
@@ -1172,6 +1207,55 @@ TEST(string, strcat_overread) {
   RunSrcDstBufferOverreadTest(DoStrcatTest);
 }
 
+#if defined(STRLCAT_SUPPORTED)
+static void DoStrlcatTest(uint8_t* src, uint8_t* dst, size_t len) {
+  if (len >= 1) {
+    int value = 32 + (len % 96);
+    memset(src, value, len - 1);
+    src[len-1] = '\0';
+
+    if (len >= STRCAT_DST_LEN) {
+      // Create a small buffer for doing quick compares in each loop.
+      uint8_t cmp_buf[STRCAT_DST_LEN];
+      // Make sure dst string contains a different value then the src string.
+      int value2 = 32 + (value + 2) % 96;
+      memset(cmp_buf, value2, sizeof(cmp_buf));
+
+      for (size_t i = 1; i <= STRCAT_DST_LEN; i++) {
+        memset(dst, value2, i-1);
+        memset(dst+i-1, 0, len-i);
+        src[len-i] = '\0';
+        ASSERT_EQ(len-1, strlcat(reinterpret_cast<char*>(dst),
+                                 reinterpret_cast<char*>(src), len));
+        ASSERT_TRUE(memcmp(dst, cmp_buf, i-1) == 0);
+        ASSERT_TRUE(memcmp(src, dst+i-1, len-i+1) == 0);
+      }
+    } else {
+      dst[0] = '\0';
+      ASSERT_EQ(len-1, strlcat(reinterpret_cast<char*>(dst),
+                               reinterpret_cast<char*>(src), len));
+      ASSERT_TRUE(memcmp(src, dst, len) == 0);
+    }
+  }
+}
+#endif
+
+TEST(string, strlcat_align) {
+#if defined(STRLCAT_SUPPORTED)
+  RunSrcDstBufferAlignTest(MEDIUM, DoStrlcatTest, LargeSetIncrement);
+#else
+  GTEST_LOG_(INFO) << "Skipping test, strlcat not supported on this platform.";
+#endif
+}
+
+TEST(string, strlcat_overread) {
+#if defined(STRLCAT_SUPPORTED)
+  RunSrcDstBufferOverreadTest(DoStrlcatTest);
+#else
+  GTEST_LOG_(INFO) << "Skipping test, strlcat not supported on this platform.";
+#endif
+}
+
 static void DoStrcmpTest(uint8_t* buf1, uint8_t* buf2, size_t len) {
   if (len >= 1) {
     memset(buf1, (32 + (len % 96)), len - 1);
index 5200859fbd6633552a0d52d7406d10a5aee5cdef..823aa4f0f7d675b8326a5353304281fb0df2e1ce 100644 (file)
@@ -17,6 +17,7 @@
 #include <gtest/gtest.h>
 
 #include <errno.h>
+#include <locale.h>
 #include <strings.h>
 
 TEST(strings, ffs) {
@@ -30,3 +31,33 @@ TEST(strings, ffs) {
   ASSERT_EQ(27, ffs(0x04000000));
   ASSERT_EQ(32, ffs(0x80000000));
 }
+
+TEST(strings, strcasecmp) {
+  ASSERT_EQ(0, strcasecmp("hello", "HELLO"));
+  ASSERT_LT(strcasecmp("hello1", "hello2"), 0);
+  ASSERT_GT(strcasecmp("hello2", "hello1"), 0);
+}
+
+TEST(strings, strcasecmp_l) {
+  locale_t l = newlocale(LC_ALL, "C", 0);
+  ASSERT_EQ(0, strcasecmp_l("hello", "HELLO", l));
+  ASSERT_LT(strcasecmp_l("hello1", "hello2", l), 0);
+  ASSERT_GT(strcasecmp_l("hello2", "hello1", l), 0);
+  freelocale(l);
+}
+
+TEST(strings, strncasecmp) {
+  ASSERT_EQ(0, strncasecmp("hello", "HELLO", 3));
+  ASSERT_EQ(0, strncasecmp("abcXX", "ABCYY", 3));
+  ASSERT_LT(strncasecmp("hello1", "hello2", 6), 0);
+  ASSERT_GT(strncasecmp("hello2", "hello1", 6), 0);
+}
+
+TEST(strings, strncasecmp_l) {
+  locale_t l = newlocale(LC_ALL, "C", 0);
+  ASSERT_EQ(0, strncasecmp_l("hello", "HELLO", 3, l));
+  ASSERT_EQ(0, strncasecmp_l("abcXX", "ABCYY", 3, l));
+  ASSERT_LT(strncasecmp_l("hello1", "hello2", 6, l), 0);
+  ASSERT_GT(strncasecmp_l("hello2", "hello1", 6, l), 0);
+  freelocale(l);
+}
index 7232ae23451d5ccc4ea0b2de7a8d69d6b487de20..19d4017733bf8a1fdf8d7bb2532ea5841cc98805 100644 (file)
@@ -25,6 +25,7 @@
 #include <stdint.h>
 #include <sys/syscall.h>
 #include <sys/types.h>
+#include <sys/utsname.h>
 #include <sys/wait.h>
 #include <unistd.h>
 
@@ -470,3 +471,34 @@ class unistd_DeathTest : public BionicDeathTest {};
 TEST_F(unistd_DeathTest, abort) {
   ASSERT_EXIT(abort(), testing::KilledBySignal(SIGABRT), "");
 }
+
+TEST(unistd, sethostname) {
+  // The permissions check happens before the argument check, so this will
+  // fail for a different reason if you're running as root than if you're
+  // not, but it'll fail either way. Checking that we have the symbol is about
+  // all we can do for sethostname(2).
+  ASSERT_EQ(-1, sethostname("", -1));
+}
+
+TEST(unistd, gethostname) {
+  char hostname[HOST_NAME_MAX + 1];
+  memset(hostname, 0, sizeof(hostname));
+
+  // Can we get the hostname with a big buffer?
+  ASSERT_EQ(0, gethostname(hostname, HOST_NAME_MAX));
+
+  // Can we get the hostname with a right-sized buffer?
+  errno = 0;
+  ASSERT_EQ(0, gethostname(hostname, strlen(hostname) + 1));
+
+  // Does uname(2) agree?
+  utsname buf;
+  ASSERT_EQ(0, uname(&buf));
+  ASSERT_EQ(0, strncmp(hostname, buf.nodename, SYS_NMLN));
+  ASSERT_GT(strlen(hostname), 0U);
+
+  // Do we correctly detect truncation?
+  errno = 0;
+  ASSERT_EQ(-1, gethostname(hostname, strlen(hostname)));
+  ASSERT_EQ(ENAMETOOLONG, errno);
+}