Merge "libc: fix kernel cleanup script typo."
diff --git a/libc/netbsd/net/getaddrinfo.c b/libc/netbsd/net/getaddrinfo.c
index 778f44c..bb6645c 100644
--- a/libc/netbsd/net/getaddrinfo.c
+++ b/libc/netbsd/net/getaddrinfo.c
@@ -347,35 +347,55 @@
return -1;
}
-/* Determine whether IPv6 connectivity is available. */
+/*
+ * Connect a UDP socket to a given unicast address. This will cause no network
+ * traffic, but will fail fast if the system has no or limited reachability to
+ * the destination (e.g., no IPv4 address, no IPv6 default route, ...).
+ */
static int
-_have_ipv6() {
- /*
- * Connect a UDP socket to an global unicast IPv6 address. This will
- * cause no network traffic, but will fail fast if the system has no or
- * limited IPv6 connectivity (e.g., only a link-local address).
- */
- static const struct sockaddr_in6 sin6_test = {
- /* family, port, flow label */
- AF_INET6, 0, 0,
- /* 2000:: */
- {{{ 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}},
- /* scope ID */
- 0};
- sockaddr_union addr_test;
- addr_test.in6 = sin6_test;
- int s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+_test_connect(int pf, struct sockaddr *addr, size_t addrlen) {
+ int s = socket(pf, SOCK_DGRAM, IPPROTO_UDP);
if (s < 0)
return 0;
int ret;
do {
- ret = connect(s, &addr_test.generic, sizeof(addr_test.in6));
+ ret = connect(s, addr, addrlen);
} while (ret < 0 && errno == EINTR);
- int have_ipv6 = (ret == 0);
+ int success = (ret == 0);
do {
ret = close(s);
} while (ret < 0 && errno == EINTR);
- return have_ipv6;
+ return success;
+}
+
+/*
+ * The following functions determine whether IPv4 or IPv6 connectivity is
+ * available in order to implement AI_ADDRCONFIG.
+ *
+ * Strictly speaking, AI_ADDRCONFIG should not look at whether connectivity is
+ * available, but whether addresses of the specified family are "configured
+ * on the local system". However, bionic doesn't currently support getifaddrs,
+ * so checking for connectivity is the next best thing.
+ */
+static int
+_have_ipv6() {
+ static const struct sockaddr_in6 sin6_test = {
+ .sin6_family = AF_INET6,
+ .sin6_addr.s6_addr = { // 2000::
+ 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+ };
+ sockaddr_union addr = { .in6 = sin6_test };
+ return _test_connect(PF_INET6, &addr.generic, sizeof(addr.in6));
+}
+
+static int
+_have_ipv4() {
+ static const struct sockaddr_in sin_test = {
+ .sin_family = AF_INET,
+ .sin_addr.s_addr = __constant_htonl(0x08080808L) // 8.8.8.8
+ };
+ sockaddr_union addr = { .in = sin_test };
+ return _test_connect(PF_INET, &addr.generic, sizeof(addr.in));
}
// Returns 0 on success, else returns non-zero on error (in which case
@@ -1525,9 +1545,13 @@
#define IN6_IS_ADDR_6TO4(a) \
(((a)->s6_addr[0] == 0x20) && ((a)->s6_addr[1] == 0x02))
+/* 6bone testing address area (3ffe::/16), deprecated in RFC 3701. */
+#define IN6_IS_ADDR_6BONE(a) \
+ (((a)->s6_addr[0] == 0x3f) && ((a)->s6_addr[1] == 0xfe))
+
/*
* Get the label for a given IPv4/IPv6 address.
- * RFC 3484, section 2.1, plus Teredo added in with label 5.
+ * RFC 3484, section 2.1, plus changes from draft-ietf-6man-rfc3484-revise-01.
*/
/*ARGSUSED*/
@@ -1535,19 +1559,27 @@
_get_label(const struct sockaddr *addr)
{
if (addr->sa_family == AF_INET) {
- return 4;
+ return 3;
} else if (addr->sa_family == AF_INET6) {
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr)) {
return 0;
- } else if (IN6_IS_ADDR_V4COMPAT(&addr6->sin6_addr)) {
+ } else if (IN6_IS_ADDR_ULA(&addr6->sin6_addr)) {
+ return 1;
+ } else if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr)) {
return 3;
+ } else if (IN6_IS_ADDR_6TO4(&addr6->sin6_addr)) {
+ return 4;
} else if (IN6_IS_ADDR_TEREDO(&addr6->sin6_addr)) {
return 5;
- } else if (IN6_IS_ADDR_6TO4(&addr6->sin6_addr)) {
- return 2;
+ } else if (IN6_IS_ADDR_V4COMPAT(&addr6->sin6_addr)) {
+ return 10;
+ } else if (IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr)) {
+ return 11;
+ } else if (IN6_IS_ADDR_6BONE(&addr6->sin6_addr)) {
+ return 12;
} else {
- return 1;
+ return 2;
}
} else {
/*
@@ -1560,7 +1592,7 @@
/*
* Get the precedence for a given IPv4/IPv6 address.
- * RFC 3484, section 2.1, plus Teredo added in with precedence 25.
+ * RFC 3484, section 2.1, plus changes from draft-ietf-6man-rfc3484-revise-01.
*/
/*ARGSUSED*/
@@ -1568,22 +1600,28 @@
_get_precedence(const struct sockaddr *addr)
{
if (addr->sa_family == AF_INET) {
- return 10;
+ return 30;
} else if (addr->sa_family == AF_INET6) {
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr)) {
+ return 60;
+ } else if (IN6_IS_ADDR_ULA(&addr6->sin6_addr)) {
return 50;
- } else if (IN6_IS_ADDR_V4COMPAT(&addr6->sin6_addr)) {
+ } else if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr)) {
+ return 30;
+ } else if (IN6_IS_ADDR_6TO4(&addr6->sin6_addr)) {
return 20;
} else if (IN6_IS_ADDR_TEREDO(&addr6->sin6_addr)) {
- return 25;
- } else if (IN6_IS_ADDR_6TO4(&addr6->sin6_addr)) {
- return 30;
+ return 10;
+ } else if (IN6_IS_ADDR_V4COMPAT(&addr6->sin6_addr) ||
+ IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr) ||
+ IN6_IS_ADDR_6BONE(&addr6->sin6_addr)) {
+ return 1;
} else {
return 40;
}
} else {
- return 5;
+ return 1;
}
}
@@ -1867,17 +1905,27 @@
q.qclass = C_IN;
q.answer = buf->buf;
q.anslen = sizeof(buf->buf);
- /* If AI_ADDRCONFIG, lookup IPv6 only if we have connectivity */
- if (!(pai->ai_flags & AI_ADDRCONFIG) || _have_ipv6()) {
+ int query_ipv6 = 1, query_ipv4 = 1;
+ if (pai->ai_flags & AI_ADDRCONFIG) {
+ query_ipv6 = _have_ipv6();
+ query_ipv4 = _have_ipv4();
+ }
+ if (query_ipv6) {
q.qtype = T_AAAA;
- q.next = &q2;
- q2.name = name;
- q2.qclass = C_IN;
- q2.qtype = T_A;
- q2.answer = buf2->buf;
- q2.anslen = sizeof(buf2->buf);
- } else {
+ if (query_ipv4) {
+ q.next = &q2;
+ q2.name = name;
+ q2.qclass = C_IN;
+ q2.qtype = T_A;
+ q2.answer = buf2->buf;
+ q2.anslen = sizeof(buf2->buf);
+ }
+ } else if (query_ipv4) {
q.qtype = T_A;
+ } else {
+ free(buf);
+ free(buf2);
+ return NS_NOTFOUND;
}
break;
case AF_INET:
diff --git a/libc/stdio/fvwrite.c b/libc/stdio/fvwrite.c
index 57a57e6..39d0604 100644
--- a/libc/stdio/fvwrite.c
+++ b/libc/stdio/fvwrite.c
@@ -48,7 +48,7 @@
__sfvwrite(FILE *fp, struct __suio *uio)
{
size_t len;
- char *p;
+ const char *p;
struct __siov *iov;
int w, s;
char *nl;
diff --git a/libc/stdio/fvwrite.h b/libc/stdio/fvwrite.h
index 2344e42..96f65de 100644
--- a/libc/stdio/fvwrite.h
+++ b/libc/stdio/fvwrite.h
@@ -36,7 +36,7 @@
* I/O descriptors for __sfvwrite().
*/
struct __siov {
- void *iov_base;
+ const void *iov_base;
size_t iov_len;
};
struct __suio {
diff --git a/libc/stdio/vfprintf.c b/libc/stdio/vfprintf.c
index 5c52127..9c36b79 100644
--- a/libc/stdio/vfprintf.c
+++ b/libc/stdio/vfprintf.c
@@ -203,9 +203,9 @@
* below longer.
*/
#define PADSIZE 16 /* pad chunk size */
- static char blanks[PADSIZE] =
+ static const char blanks[PADSIZE] =
{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
- static char zeroes[PADSIZE] =
+ static const char zeroes[PADSIZE] =
{'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
/*
diff --git a/libc/tzcode/strptime.c b/libc/tzcode/strptime.c
index 1f481c9..0567aa4 100644
--- a/libc/tzcode/strptime.c
+++ b/libc/tzcode/strptime.c
@@ -89,29 +89,31 @@
#define _LEGAL_ALT(x) { if (alt_format & ~(x)) return (0); }
+struct century_relyear {
+ int century;
+ int relyear;
+};
static int _conv_num(const unsigned char **, int *, int, int);
-static unsigned char *_strptime(const unsigned char *, const char *, struct tm *, int);
+static unsigned char *_strptime(const unsigned char *, const char *, struct tm *,
+ struct century_relyear *);
char *
strptime(const char *buf, const char *fmt, struct tm *tm)
{
- return (char*)(_strptime((const unsigned char*)buf, fmt, tm, 1));
+ struct century_relyear cr;
+ cr.century = TM_YEAR_BASE;
+ cr.relyear = -1;
+ return (char*)(_strptime((const unsigned char*)buf, fmt, tm, &cr));
}
static unsigned char *
-_strptime(const unsigned char *buf, const char *fmt, struct tm *tm, int initialize)
+_strptime(const unsigned char *buf, const char *fmt, struct tm *tm, struct century_relyear *cr)
{
unsigned char c;
const unsigned char *bp;
size_t len = 0;
int alt_format, i;
- static int century, relyear;
-
- if (initialize) {
- century = TM_YEAR_BASE;
- relyear = -1;
- }
bp = (unsigned char *)buf;
while ((c = *fmt) != '\0') {
@@ -158,43 +160,43 @@
*/
case 'c': /* Date and time, using the locale's format. */
_LEGAL_ALT(_ALT_E);
- if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, 0)))
+ if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, cr)))
return (NULL);
break;
case 'D': /* The date as "%m/%d/%y". */
_LEGAL_ALT(0);
- if (!(bp = _strptime(bp, "%m/%d/%y", tm, 0)))
+ if (!(bp = _strptime(bp, "%m/%d/%y", tm, cr)))
return (NULL);
break;
case 'R': /* The time as "%H:%M". */
_LEGAL_ALT(0);
- if (!(bp = _strptime(bp, "%H:%M", tm, 0)))
+ if (!(bp = _strptime(bp, "%H:%M", tm, cr)))
return (NULL);
break;
case 'r': /* The time as "%I:%M:%S %p". */
_LEGAL_ALT(0);
- if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, 0)))
+ if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, cr)))
return (NULL);
break;
case 'T': /* The time as "%H:%M:%S". */
_LEGAL_ALT(0);
- if (!(bp = _strptime(bp, "%H:%M:%S", tm, 0)))
+ if (!(bp = _strptime(bp, "%H:%M:%S", tm, cr)))
return (NULL);
break;
case 'X': /* The time, using the locale's format. */
_LEGAL_ALT(_ALT_E);
- if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, 0)))
+ if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, cr)))
return (NULL);
break;
case 'x': /* The date, using the locale's format. */
_LEGAL_ALT(_ALT_E);
- if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, 0)))
+ if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, cr)))
return (NULL);
break;
@@ -253,7 +255,7 @@
if (!(_conv_num(&bp, &i, 0, 99)))
return (NULL);
- century = i * 100;
+ cr->century = i * 100;
break;
case 'd': /* The day of month. */
@@ -359,13 +361,13 @@
if (!(_conv_num(&bp, &i, 0, 9999)))
return (NULL);
- relyear = -1;
+ cr->relyear = -1;
tm->tm_year = i - TM_YEAR_BASE;
break;
case 'y': /* The year within the century (2 digits). */
_LEGAL_ALT(_ALT_E | _ALT_O);
- if (!(_conv_num(&bp, &relyear, 0, 99)))
+ if (!(_conv_num(&bp, &cr->relyear, 0, 99)))
return (NULL);
break;
@@ -391,14 +393,14 @@
* We need to evaluate the two digit year spec (%y)
* last as we can get a century spec (%C) at any time.
*/
- if (relyear != -1) {
- if (century == TM_YEAR_BASE) {
- if (relyear <= 68)
- tm->tm_year = relyear + 2000 - TM_YEAR_BASE;
+ if (cr->relyear != -1) {
+ if (cr->century == TM_YEAR_BASE) {
+ if (cr->relyear <= 68)
+ tm->tm_year = cr->relyear + 2000 - TM_YEAR_BASE;
else
- tm->tm_year = relyear + 1900 - TM_YEAR_BASE;
+ tm->tm_year = cr->relyear + 1900 - TM_YEAR_BASE;
} else {
- tm->tm_year = relyear + century - TM_YEAR_BASE;
+ tm->tm_year = cr->relyear + cr->century - TM_YEAR_BASE;
}
}
diff --git a/libc/unistd/raise.c b/libc/unistd/raise.c
index de099da..7b03a7a 100644
--- a/libc/unistd/raise.c
+++ b/libc/unistd/raise.c
@@ -30,5 +30,5 @@
int raise(int signum)
{
- return kill(getpid(), signum);
+ return kill(gettid(), signum);
}
diff --git a/libc/unistd/time.c b/libc/unistd/time.c
index 13d7366..4b51675 100644
--- a/libc/unistd/time.c
+++ b/libc/unistd/time.c
@@ -42,21 +42,29 @@
return (tt.tv_sec);
}
+// return monotonically increasing CPU time in ticks relative to unspecified epoch
+static inline clock_t clock_now(void)
+{
+ struct timespec tm;
+ clock_gettime( CLOCK_MONOTONIC, &tm);
+ return tm.tv_sec * CLOCKS_PER_SEC + (tm.tv_nsec * (CLOCKS_PER_SEC/1e9));
+}
+// initialized by the constructor below
+static clock_t clock_start;
+
+// called by dlopen when .so is loaded
+__attribute__((constructor)) static void clock_crt0(void)
+{
+ clock_start = clock_now();
+}
+
+// return elapsed CPU time in clock ticks, since start of program execution
+// (spec says epoch is undefined, but glibc uses crt0 as epoch)
clock_t
clock(void)
{
- struct timespec tm;
- static int clock_inited;
- static clock_t clock_start;
- clock_t now;
-
- clock_gettime( CLOCK_MONOTONIC, &tm);
- now = tm.tv_sec * CLOCKS_PER_SEC + (tm.tv_nsec * (CLOCKS_PER_SEC/1e9));
-
- if (!clock_inited) {
- clock_start = now;
- clock_inited = 1;
- }
- return now - clock_start;
+ // note that if we are executing in a different thread than crt0, then the
+ // pthread_create that made us had a memory barrier so clock_start is defined
+ return clock_now() - clock_start;
}
diff --git a/libm/Android.mk b/libm/Android.mk
index 28e8f33..29c75a2 100644
--- a/libm/Android.mk
+++ b/libm/Android.mk
@@ -117,6 +117,7 @@
src/s_lroundf.c \
src/s_lroundl.c \
src/s_modff.c \
+ src/s_nan.c \
src/s_nearbyint.c \
src/s_nextafter.c \
src/s_nextafterf.c \
@@ -138,6 +139,7 @@
src/s_tanf.c \
src/s_tanh.c \
src/s_tanhf.c \
+ src/s_tgammaf.c \
src/s_trunc.c \
src/s_truncf.c \
src/s_truncl.c \
diff --git a/libm/include/math.h b/libm/include/math.h
index 3b5660f..a86a16f 100644
--- a/libm/include/math.h
+++ b/libm/include/math.h
@@ -251,6 +251,7 @@
double logb(double);
long lrint(double);
long lround(double);
+double nan(const char *) __pure2;
double nextafter(double, double);
double remainder(double, double);
double remquo(double, double, int *);
@@ -343,6 +344,7 @@
float erfcf(float);
float hypotf(float, float);
float lgammaf(float);
+float tgammaf(float);
float acoshf(float);
float asinhf(float);
@@ -354,6 +356,7 @@
long long llroundf(float);
long lrintf(float);
long lroundf(float);
+float nanf(const char *) __pure2;
float nearbyintf(float);
float nextafterf(float, float);
float remainderf(float, float);
diff --git a/libm/src/s_nan.c b/libm/src/s_nan.c
new file mode 100644
index 0000000..e366e6b
--- /dev/null
+++ b/libm/src/s_nan.c
@@ -0,0 +1,131 @@
+/*-
+ * Copyright (c) 2007 David Schultz
+ * 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 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 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/endian.h>
+#include <ctype.h>
+#include <float.h>
+#include <math.h>
+#include <stdint.h>
+#include <strings.h>
+
+#include "math_private.h"
+
+/* digittoint is in the FreeBSD C library, but not Bionic at this point */
+static int
+digittoint(char ch)
+{
+ int d;
+
+ d = ch - '0';
+ if ((unsigned)d < 10) {
+ return d;
+ }
+ d = ch - 'a';
+ if ((unsigned)d < 6) {
+ return d + 10;
+ }
+ d = ch - 'A';
+ if ((unsigned)d < 6) {
+ return d + 10;
+ }
+ return -1;
+}
+
+/*
+ * Scan a string of hexadecimal digits (the format nan(3) expects) and
+ * make a bit array (using the local endianness). We stop when we
+ * encounter an invalid character, NUL, etc. If we overflow, we do
+ * the same as gcc's __builtin_nan(), namely, discard the high order bits.
+ *
+ * The format this routine accepts needs to be compatible with what is used
+ * in contrib/gdtoa/hexnan.c (for strtod/scanf) and what is used in
+ * __builtin_nan(). In fact, we're only 100% compatible for strings we
+ * consider valid, so we might be violating the C standard. But it's
+ * impossible to use nan(3) portably anyway, so this seems good enough.
+ */
+void
+_scan_nan(uint32_t *words, int num_words, const char *s)
+{
+ int si; /* index into s */
+ int bitpos; /* index into words (in bits) */
+
+ bzero(words, num_words * sizeof(uint32_t));
+
+ /* Allow a leading '0x'. (It's expected, but redundant.) */
+ if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
+ s += 2;
+
+ /* Scan forwards in the string, looking for the end of the sequence. */
+ for (si = 0; isxdigit(s[si]); si++)
+ ;
+
+ /* Scan backwards, filling in the bits in words[] as we go. */
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+ for (bitpos = 0; bitpos < 32 * num_words; bitpos += 4) {
+#else
+ for (bitpos = 32 * num_words - 4; bitpos >= 0; bitpos -= 4) {
+#endif
+ if (--si < 0)
+ break;
+ words[bitpos / 32] |= digittoint(s[si]) << (bitpos % 32);
+ }
+}
+
+double
+nan(const char *s)
+{
+ union {
+ double d;
+ uint32_t bits[2];
+ } u;
+
+ _scan_nan(u.bits, 2, s);
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+ u.bits[1] |= 0x7ff80000;
+#else
+ u.bits[0] |= 0x7ff80000;
+#endif
+ return (u.d);
+}
+
+float
+nanf(const char *s)
+{
+ union {
+ float f;
+ uint32_t bits[1];
+ } u;
+
+ _scan_nan(u.bits, 1, s);
+ u.bits[0] |= 0x7fc00000;
+ return (u.f);
+}
+
+#if (LDBL_MANT_DIG == 53)
+__weak_alias(nanl, nan);
+#endif
diff --git a/libm/src/s_tgammaf.c b/libm/src/s_tgammaf.c
new file mode 100644
index 0000000..9993d91
--- /dev/null
+++ b/libm/src/s_tgammaf.c
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2008 David Schultz <das@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 <math.h>
+
+/*
+ * We simply call tgamma() rather than bloating the math library with
+ * a float-optimized version of it. The reason is that tgammaf() is
+ * essentially useless, since the function is superexponential and
+ * floats have very limited range.
+ */
+float
+tgammaf(float x)
+{
+
+ return (tgamma(x));
+}
diff --git a/linker/README.TXT b/linker/README.TXT
index 052a65b..a8efe35 100644
--- a/linker/README.TXT
+++ b/linker/README.TXT
@@ -77,7 +77,7 @@
Same as DT_INITARRAY but for finalizers. Note that the
functions must be called in reverse-order though
- Note: this is generally stroed in a .fini_array section
+ Note: this is generally stored in a .fini_array section
DT_FINI_ARRAYSZ
Size of FT_FINIARRAY
@@ -88,7 +88,7 @@
a list of functions that need to be called before any other
initialization function (i.e. DT_INIT and/or DT_INIT_ARRAY)
- Note: this is generally stroed in a .preinit_array section
+ Note: this is generally stored in a .preinit_array section
DT_PREINIT_ARRAYSZ
The size of DT_PREINIT_ARRAY
@@ -103,14 +103,14 @@
much processor dependent, and may use different ELF sections.
On the ARM (see "C++ ABI for ARM" document), the static constructors
-must be called explicitely from the DT_INIT_ARRAY, and each one of them
+must be called explicitly from the DT_INIT_ARRAY, and each one of them
shall register a destructor by calling the special __eabi_atexit()
function (provided by the C library). The DT_FINI_ARRAY is not used
by static C++ destructors.
On x86, the lists of constructors and destructors are placed in special
sections named ".ctors" and ".dtors", and the DT_INIT / DT_FINI functions
-are in charge of calling them explicitely.
+are in charge of calling them explicitly.
Debugging:
@@ -140,4 +140,4 @@
By default, traces are sent to logcat, with the "linker" tag. You can
change this to go to stdout instead by setting the definition of
-LINKER_DEBUG_TO_LOG to 0 in "linker_debug.h"
+LINKER_DEBUG_TO_LOG to 0 in "linker_debug.h".
diff --git a/linker/linker_environ.c b/linker/linker_environ.c
index 6c5b571..b71dd80 100644
--- a/linker/linker_environ.c
+++ b/linker/linker_environ.c
@@ -110,7 +110,7 @@
while (envstr[cnt] == name[cnt] && name[cnt] != '\0')
cnt++;
- if (name[cnt] != '\0' && envstr[cnt] == '=')
+ if (name[cnt] == '\0' && envstr[cnt] == '=')
return envstr + cnt + 1;
return NULL;