aboutsummaryrefslogtreecommitdiffstats
path: root/libc/bionic
diff options
context:
space:
mode:
Diffstat (limited to 'libc/bionic')
-rw-r--r--libc/bionic/__cmsg_nxthdr.cpp (renamed from libc/bionic/cmsg_nxthdr.cpp)3
-rw-r--r--libc/bionic/ctype.cpp89
-rw-r--r--libc/bionic/dlmalloc.h2
-rw-r--r--libc/bionic/jemalloc_wrapper.cpp2
-rw-r--r--libc/bionic/malloc_debug_check.cpp26
-rw-r--r--libc/bionic/malloc_debug_common.cpp12
-rw-r--r--libc/bionic/malloc_debug_common.h13
-rw-r--r--libc/bionic/malloc_debug_leak.cpp41
-rw-r--r--libc/bionic/malloc_debug_qemu.cpp37
-rw-r--r--libc/bionic/pthread_create.cpp19
-rw-r--r--libc/bionic/strcoll_l.cpp33
-rw-r--r--libc/bionic/strerror_r.cpp5
-rw-r--r--libc/bionic/strftime_l.cpp34
-rw-r--r--libc/bionic/strtold_l.cpp33
-rw-r--r--libc/bionic/strtoll_l.cpp33
-rw-r--r--libc/bionic/strtoull_l.cpp34
-rw-r--r--libc/bionic/strxfrm_l.cpp33
-rw-r--r--libc/bionic/stubs.cpp3
-rw-r--r--libc/bionic/wchar.cpp22
-rw-r--r--libc/bionic/wctype.cpp25
20 files changed, 412 insertions, 87 deletions
diff --git a/libc/bionic/cmsg_nxthdr.cpp b/libc/bionic/__cmsg_nxthdr.cpp
index 8a2b33e0d..f96278890 100644
--- a/libc/bionic/cmsg_nxthdr.cpp
+++ b/libc/bionic/__cmsg_nxthdr.cpp
@@ -37,6 +37,3 @@ cmsghdr* __cmsg_nxthdr(msghdr* msg, cmsghdr* cmsg) {
}
return ptr;
}
-
-// TODO: remove after NDK refresh.
-__weak_alias(cmsg_nxthdr, __cmsg_nxthdr);
diff --git a/libc/bionic/ctype.cpp b/libc/bionic/ctype.cpp
new file mode 100644
index 000000000..3960d9d4c
--- /dev/null
+++ b/libc/bionic/ctype.cpp
@@ -0,0 +1,89 @@
+/*
+ * 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 <ctype.h>
+
+int isalnum_l(int c, locale_t) {
+ return isalnum(c);
+}
+
+int isalpha_l(int c, locale_t) {
+ return isalpha(c);
+}
+
+int isascii_l(int c, locale_t) {
+ return isascii(c);
+}
+
+int isblank_l(int c, locale_t) {
+ return isblank(c);
+}
+
+int iscntrl_l(int c, locale_t) {
+ return iscntrl(c);
+}
+
+int isdigit_l(int c, locale_t) {
+ return isdigit(c);
+}
+
+int isgraph_l(int c, locale_t) {
+ return isgraph(c);
+}
+
+int islower_l(int c, locale_t) {
+ return islower(c);
+}
+
+int isprint_l(int c, locale_t) {
+ return isprint(c);
+}
+
+int ispunct_l(int c, locale_t) {
+ return ispunct(c);
+}
+
+int isspace_l(int c, locale_t) {
+ return isspace(c);
+}
+
+int isupper_l(int c, locale_t) {
+ return isupper(c);
+}
+
+int isxdigit_l(int c, locale_t) {
+ return isxdigit(c);
+}
+
+int toupper_l(int c, locale_t) {
+ return toupper(c);
+}
+
+int tolower_l(int c, locale_t) {
+ return tolower(c);
+}
diff --git a/libc/bionic/dlmalloc.h b/libc/bionic/dlmalloc.h
index e0656877f..46efa911f 100644
--- a/libc/bionic/dlmalloc.h
+++ b/libc/bionic/dlmalloc.h
@@ -32,6 +32,8 @@
#define USE_SPIN_LOCKS 0
#define DEFAULT_MMAP_THRESHOLD (64U * 1024U)
+#define malloc_getpagesize getpagesize()
+
/* Export two symbols used by the VM. */
__BEGIN_DECLS
int dlmalloc_trim(size_t) __LIBC_ABI_PUBLIC__;
diff --git a/libc/bionic/jemalloc_wrapper.cpp b/libc/bionic/jemalloc_wrapper.cpp
index d1fe96056..e33d560a4 100644
--- a/libc/bionic/jemalloc_wrapper.cpp
+++ b/libc/bionic/jemalloc_wrapper.cpp
@@ -21,7 +21,7 @@
#include "private/bionic_macros.h"
void* je_pvalloc(size_t bytes) {
- size_t pagesize = sysconf(_SC_PAGESIZE);
+ size_t pagesize = getpagesize();
size_t size = BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) {
return NULL;
diff --git a/libc/bionic/malloc_debug_check.cpp b/libc/bionic/malloc_debug_check.cpp
index e4e4c2eb0..1c63d4dcf 100644
--- a/libc/bionic/malloc_debug_check.cpp
+++ b/libc/bionic/malloc_debug_check.cpp
@@ -123,6 +123,7 @@ static pthread_mutex_t backlog_lock = PTHREAD_MUTEX_INITIALIZER;
static unsigned g_malloc_debug_backlog = 100;
__LIBC_HIDDEN__ HashTable* g_hash_table;
+__LIBC_HIDDEN__ const MallocDebug* g_malloc_dispatch;
static inline void init_front_guard(hdr_t* hdr) {
memset(hdr->front_guard, FRONT_GUARD, FRONT_GUARD_LEN);
@@ -324,7 +325,7 @@ static inline void add_to_backlog(hdr_t* hdr) {
while (backlog_num > g_malloc_debug_backlog) {
hdr_t* gone = backlog_tail;
del_from_backlog_locked(gone);
- Malloc(free)(gone->base);
+ g_malloc_dispatch->free(gone->base);
}
}
@@ -336,7 +337,7 @@ extern "C" void* chk_malloc(size_t bytes) {
errno = ENOMEM;
return NULL;
}
- hdr_t* hdr = static_cast<hdr_t*>(Malloc(malloc)(size));
+ hdr_t* hdr = static_cast<hdr_t*>(g_malloc_dispatch->malloc(size));
if (hdr) {
hdr->base = hdr;
hdr->bt_depth = get_backtrace(hdr->bt, MAX_BACKTRACE_DEPTH);
@@ -364,7 +365,7 @@ extern "C" void* chk_memalign(size_t alignment, size_t bytes) {
return NULL;
}
- void* base = Malloc(malloc)(sizeof(hdr_t) + size + sizeof(ftr_t));
+ void* base = g_malloc_dispatch->malloc(sizeof(hdr_t) + size + sizeof(ftr_t));
if (base != NULL) {
// Check that the actual pointer that will be returned is aligned
// properly.
@@ -461,7 +462,7 @@ extern "C" void* chk_realloc(void* ptr, size_t bytes) {
user(hdr), bytes);
log_backtrace(bt, depth);
// just get a whole new allocation and leak the old one
- return Malloc(realloc)(0, bytes);
+ return g_malloc_dispatch->realloc(0, bytes);
// return realloc(user(hdr), bytes); // assuming it was allocated externally
}
}
@@ -474,15 +475,15 @@ extern "C" void* chk_realloc(void* ptr, size_t bytes) {
if (hdr->base != hdr) {
// An allocation from memalign, so create another allocation and
// copy the data out.
- void* newMem = Malloc(malloc)(size);
+ void* newMem = g_malloc_dispatch->malloc(size);
if (newMem == NULL) {
return NULL;
}
memcpy(newMem, hdr, sizeof(hdr_t) + hdr->size);
- Malloc(free)(hdr->base);
+ g_malloc_dispatch->free(hdr->base);
hdr = static_cast<hdr_t*>(newMem);
} else {
- hdr = static_cast<hdr_t*>(Malloc(realloc)(hdr, size));
+ hdr = static_cast<hdr_t*>(g_malloc_dispatch->realloc(hdr, size));
}
if (hdr) {
hdr->base = hdr;
@@ -501,7 +502,7 @@ extern "C" void* chk_calloc(size_t nmemb, size_t bytes) {
errno = ENOMEM;
return NULL;
}
- hdr_t* hdr = static_cast<hdr_t*>(Malloc(calloc)(1, size));
+ hdr_t* hdr = static_cast<hdr_t*>(g_malloc_dispatch->calloc(1, size));
if (hdr) {
hdr->base = hdr;
hdr->bt_depth = get_backtrace(hdr->bt, MAX_BACKTRACE_DEPTH);
@@ -524,7 +525,7 @@ extern "C" size_t chk_malloc_usable_size(const void* ptr) {
}
extern "C" struct mallinfo chk_mallinfo() {
- return Malloc(mallinfo)();
+ return g_malloc_dispatch->mallinfo();
}
extern "C" int chk_posix_memalign(void** memptr, size_t alignment, size_t size) {
@@ -538,7 +539,7 @@ extern "C" int chk_posix_memalign(void** memptr, size_t alignment, size_t size)
}
extern "C" void* chk_pvalloc(size_t bytes) {
- size_t pagesize = sysconf(_SC_PAGESIZE);
+ size_t pagesize = getpagesize();
size_t size = BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) { // Overflow
return NULL;
@@ -547,7 +548,7 @@ extern "C" void* chk_pvalloc(size_t bytes) {
}
extern "C" void* chk_valloc(size_t size) {
- return chk_memalign(sysconf(_SC_PAGESIZE), size);
+ return chk_memalign(getpagesize(), size);
}
static void ReportMemoryLeaks() {
@@ -584,8 +585,9 @@ static void ReportMemoryLeaks() {
}
}
-extern "C" bool malloc_debug_initialize(HashTable* hash_table) {
+extern "C" bool malloc_debug_initialize(HashTable* hash_table, const MallocDebug* malloc_dispatch) {
g_hash_table = hash_table;
+ g_malloc_dispatch = malloc_dispatch;
char debug_backlog[PROP_VALUE_MAX];
if (__system_property_get("libc.debug.malloc.backlog", debug_backlog)) {
diff --git a/libc/bionic/malloc_debug_common.cpp b/libc/bionic/malloc_debug_common.cpp
index 9399237fb..be16625b8 100644
--- a/libc/bionic/malloc_debug_common.cpp
+++ b/libc/bionic/malloc_debug_common.cpp
@@ -46,6 +46,16 @@
#include "private/ScopedPthreadMutexLocker.h"
+#if defined(USE_JEMALLOC)
+#include "jemalloc.h"
+#define Malloc(function) je_ ## function
+#elif defined(USE_DLMALLOC)
+#include "dlmalloc.h"
+#define Malloc(function) dl ## function
+#else
+#error "Either one of USE_DLMALLOC or USE_JEMALLOC must be defined."
+#endif
+
// In a VM process, this is set to 1 after fork()ing out of zygote.
int gMallocLeakZygoteChild = 0;
@@ -408,7 +418,7 @@ static void malloc_init_impl() {
dlclose(malloc_impl_handle);
return;
}
- if (!malloc_debug_initialize(&g_hash_table)) {
+ if (!malloc_debug_initialize(&g_hash_table, &__libc_malloc_default_dispatch)) {
dlclose(malloc_impl_handle);
return;
}
diff --git a/libc/bionic/malloc_debug_common.h b/libc/bionic/malloc_debug_common.h
index fb2f03d06..5c73da31a 100644
--- a/libc/bionic/malloc_debug_common.h
+++ b/libc/bionic/malloc_debug_common.h
@@ -51,17 +51,6 @@
#define MALLOC_ALIGNMENT ((size_t)(2 * sizeof(void *)))
#endif
-#ifdef USE_JEMALLOC
-#include "jemalloc.h"
-#define Malloc(function) je_ ## function
-#else
-#ifndef USE_DLMALLOC
-#error "Either one of USE_DLMALLOC or USE_JEMALLOC must be defined."
-#endif
-#include "dlmalloc.h"
-#define Malloc(function) dl ## function
-#endif
-
// =============================================================================
// Structures
// =============================================================================
@@ -116,7 +105,7 @@ struct MallocDebug {
#endif
};
-typedef bool (*MallocDebugInit)(HashTable*);
+typedef bool (*MallocDebugInit)(HashTable*, const MallocDebug*);
typedef void (*MallocDebugFini)(int);
// =============================================================================
diff --git a/libc/bionic/malloc_debug_leak.cpp b/libc/bionic/malloc_debug_leak.cpp
index 308d40b9a..d9824f09f 100644
--- a/libc/bionic/malloc_debug_leak.cpp
+++ b/libc/bionic/malloc_debug_leak.cpp
@@ -62,6 +62,7 @@
extern int gMallocLeakZygoteChild;
extern HashTable* g_hash_table;
+extern const MallocDebug* g_malloc_dispatch;
// =============================================================================
// stack trace functions
@@ -143,7 +144,7 @@ static HashEntry* record_backtrace(uintptr_t* backtrace, size_t numEntries, size
entry->allocations++;
} else {
// create a new entry
- entry = static_cast<HashEntry*>(Malloc(malloc)(sizeof(HashEntry) + numEntries*sizeof(uintptr_t)));
+ entry = static_cast<HashEntry*>(g_malloc_dispatch->malloc(sizeof(HashEntry) + numEntries*sizeof(uintptr_t)));
if (!entry) {
return NULL;
}
@@ -208,11 +209,11 @@ static void remove_entry(HashEntry* entry) {
#define CHK_SENTINEL_VALUE 0xeb
extern "C" void* fill_calloc(size_t n_elements, size_t elem_size) {
- return Malloc(calloc)(n_elements, elem_size);
+ return g_malloc_dispatch->calloc(n_elements, elem_size);
}
extern "C" void* fill_malloc(size_t bytes) {
- void* buffer = Malloc(malloc)(bytes);
+ void* buffer = g_malloc_dispatch->malloc(bytes);
if (buffer) {
memset(buffer, CHK_SENTINEL_VALUE, bytes);
}
@@ -220,17 +221,17 @@ extern "C" void* fill_malloc(size_t bytes) {
}
extern "C" void fill_free(void* mem) {
- size_t bytes = Malloc(malloc_usable_size)(mem);
+ size_t bytes = g_malloc_dispatch->malloc_usable_size(mem);
memset(mem, CHK_FILL_FREE, bytes);
- Malloc(free)(mem);
+ g_malloc_dispatch->free(mem);
}
extern "C" void* fill_realloc(void* mem, size_t bytes) {
- size_t oldSize = Malloc(malloc_usable_size)(mem);
- void* newMem = Malloc(realloc)(mem, bytes);
+ size_t oldSize = g_malloc_dispatch->malloc_usable_size(mem);
+ void* newMem = g_malloc_dispatch->realloc(mem, bytes);
if (newMem) {
// If this is larger than before, fill the extra with our pattern.
- size_t newSize = Malloc(malloc_usable_size)(newMem);
+ size_t newSize = g_malloc_dispatch->malloc_usable_size(newMem);
if (newSize > oldSize) {
memset(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(newMem)+oldSize), CHK_FILL_FREE, newSize-oldSize);
}
@@ -239,7 +240,7 @@ extern "C" void* fill_realloc(void* mem, size_t bytes) {
}
extern "C" void* fill_memalign(size_t alignment, size_t bytes) {
- void* buffer = Malloc(memalign)(alignment, bytes);
+ void* buffer = g_malloc_dispatch->memalign(alignment, bytes);
if (buffer) {
memset(buffer, CHK_SENTINEL_VALUE, bytes);
}
@@ -249,11 +250,11 @@ extern "C" void* fill_memalign(size_t alignment, size_t bytes) {
extern "C" size_t fill_malloc_usable_size(const void* mem) {
// Since we didn't allocate extra bytes before or after, we can
// report the normal usable size here.
- return Malloc(malloc_usable_size)(mem);
+ return g_malloc_dispatch->malloc_usable_size(mem);
}
extern "C" struct mallinfo fill_mallinfo() {
- return Malloc(mallinfo)();
+ return g_malloc_dispatch->mallinfo();
}
extern "C" int fill_posix_memalign(void** memptr, size_t alignment, size_t size) {
@@ -267,7 +268,7 @@ extern "C" int fill_posix_memalign(void** memptr, size_t alignment, size_t size)
}
extern "C" void* fill_pvalloc(size_t bytes) {
- size_t pagesize = sysconf(_SC_PAGESIZE);
+ size_t pagesize = getpagesize();
size_t size = BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) { // Overflow
return NULL;
@@ -276,7 +277,7 @@ extern "C" void* fill_pvalloc(size_t bytes) {
}
extern "C" void* fill_valloc(size_t size) {
- return fill_memalign(sysconf(_SC_PAGESIZE), size);
+ return fill_memalign(getpagesize(), size);
}
// =============================================================================
@@ -298,7 +299,7 @@ extern "C" void* leak_malloc(size_t bytes) {
return NULL;
}
- void* base = Malloc(malloc)(size);
+ void* base = g_malloc_dispatch->malloc(size);
if (base != NULL) {
ScopedPthreadMutexLocker locker(&g_hash_table->lock);
@@ -342,11 +343,11 @@ extern "C" void leak_free(void* mem) {
entry->allocations--;
if (entry->allocations <= 0) {
remove_entry(entry);
- Malloc(free)(entry);
+ g_malloc_dispatch->free(entry);
}
// now free the memory!
- Malloc(free)(header);
+ g_malloc_dispatch->free(header);
} else {
debug_log("WARNING bad header guard: '0x%x'! and invalid entry: %p\n",
header->guard, header->entry);
@@ -452,7 +453,7 @@ extern "C" size_t leak_malloc_usable_size(const void* mem) {
return 0;
}
- size_t ret = Malloc(malloc_usable_size)(header);
+ size_t ret = g_malloc_dispatch->malloc_usable_size(header);
if (ret != 0) {
// The usable area starts at 'mem' and stops at 'header+ret'.
return reinterpret_cast<uintptr_t>(header) + ret - reinterpret_cast<uintptr_t>(mem);
@@ -462,7 +463,7 @@ extern "C" size_t leak_malloc_usable_size(const void* mem) {
}
extern "C" struct mallinfo leak_mallinfo() {
- return Malloc(mallinfo)();
+ return g_malloc_dispatch->mallinfo();
}
extern "C" int leak_posix_memalign(void** memptr, size_t alignment, size_t size) {
@@ -476,7 +477,7 @@ extern "C" int leak_posix_memalign(void** memptr, size_t alignment, size_t size)
}
extern "C" void* leak_pvalloc(size_t bytes) {
- size_t pagesize = sysconf(_SC_PAGESIZE);
+ size_t pagesize = getpagesize();
size_t size = BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) { // Overflow
return NULL;
@@ -485,5 +486,5 @@ extern "C" void* leak_pvalloc(size_t bytes) {
}
extern "C" void* leak_valloc(size_t size) {
- return leak_memalign(sysconf(_SC_PAGESIZE), size);
+ return leak_memalign(getpagesize(), size);
}
diff --git a/libc/bionic/malloc_debug_qemu.cpp b/libc/bionic/malloc_debug_qemu.cpp
index fd5161a7e..b3b604d86 100644
--- a/libc/bionic/malloc_debug_qemu.cpp
+++ b/libc/bionic/malloc_debug_qemu.cpp
@@ -336,6 +336,9 @@ static void dump_malloc_descriptor(char* str,
// Static data
// =============================================================================
+// The underlying malloc implementation to use to get memory.
+static const MallocDebug* g_malloc_dispatch = NULL;
+
/* Emulator's magic page address.
* This page (mapped on /dev/qemu_trace device) is used to fire up events
* in the emulator. */
@@ -595,7 +598,9 @@ extern "C" void* qemu_instrumented_valloc(size_t);
* Return:
* 0 on success, or -1 on failure.
*/
-extern "C" bool malloc_debug_initialize(HashTable*) {
+extern "C" bool malloc_debug_initialize(HashTable*, const MallocDebug* malloc_dispatch) {
+ g_malloc_dispatch = malloc_dispatch;
+
/* We will be using emulator's magic page to report memory allocation
* activities. In essence, what magic page does, it translates writes to
* the memory mapped spaces into writes to an I/O port that emulator
@@ -693,7 +698,7 @@ extern "C" void* qemu_instrumented_malloc(size_t bytes) {
errno = ENOMEM;
return NULL;
}
- desc.ptr = Malloc(malloc)(size);
+ desc.ptr = g_malloc_dispatch->malloc(size);
if (desc.ptr == NULL) {
qemu_error_log("<libc_pid=%03u, pid=%03u> malloc(%zu): malloc(%zu) failed.",
malloc_pid, getpid(), bytes, size);
@@ -704,7 +709,7 @@ extern "C" void* qemu_instrumented_malloc(size_t bytes) {
if (notify_qemu_malloc(&desc)) {
log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: malloc: notify_malloc failed for ",
malloc_pid, getpid());
- Malloc(free)(desc.ptr);
+ g_malloc_dispatch->free(desc.ptr);
errno = ENOMEM;
return NULL;
} else {
@@ -726,7 +731,7 @@ extern "C" void qemu_instrumented_free(void* mem) {
if (mem == NULL) {
// Just let go NULL free
- Malloc(free)(mem);
+ g_malloc_dispatch->free(mem);
return;
}
@@ -757,7 +762,7 @@ extern "C" void qemu_instrumented_free(void* mem) {
} else {
log_mdesc(info, &desc, "--- <libc_pid=%03u, pid=%03u> free(%p) -> ",
malloc_pid, getpid(), mem);
- Malloc(free)(desc.ptr);
+ g_malloc_dispatch->free(desc.ptr);
}
}
@@ -816,7 +821,7 @@ extern "C" void* qemu_instrumented_calloc(size_t n_elements, size_t elem_size) {
total_elements++;
desc.suffix_size += (elem_size - total_size);
}
- desc.ptr = Malloc(calloc)(total_elements, elem_size);
+ desc.ptr = g_malloc_dispatch->calloc(total_elements, elem_size);
if (desc.ptr == NULL) {
error_log("<libc_pid=%03u, pid=%03u> calloc: calloc(%zu(%zu), %zu) (prx=%u, sfx=%u) failed.",
malloc_pid, getpid(), n_elements, total_elements, elem_size,
@@ -827,7 +832,7 @@ extern "C" void* qemu_instrumented_calloc(size_t n_elements, size_t elem_size) {
if (notify_qemu_malloc(&desc)) {
log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: calloc(%zu(%zu), %zu): notify_malloc failed for ",
malloc_pid, getpid(), n_elements, total_elements, elem_size);
- Malloc(free)(desc.ptr);
+ g_malloc_dispatch->free(desc.ptr);
errno = ENOMEM;
return NULL;
} else {
@@ -905,7 +910,7 @@ extern "C" void* qemu_instrumented_realloc(void* mem, size_t bytes) {
errno = ENOMEM;
return NULL;
}
- new_desc.ptr = Malloc(malloc)(new_size);
+ new_desc.ptr = g_malloc_dispatch->malloc(new_size);
if (new_desc.ptr == NULL) {
log_mdesc(error, &cur_desc, "<libc_pid=%03u, pid=%03u>: realloc(%p, %zu): malloc(%zu) failed on ",
malloc_pid, getpid(), mem, bytes, new_size);
@@ -924,7 +929,7 @@ extern "C" void* qemu_instrumented_realloc(void* mem, size_t bytes) {
log_mdesc(error, &new_desc, "<libc_pid=%03u, pid=%03u>: realloc(%p, %zu) notify_malloc failed -> ",
malloc_pid, getpid(), mem, bytes);
log_mdesc(error, &cur_desc, " <- ");
- Malloc(free)(new_desc.ptr);
+ g_malloc_dispatch->free(new_desc.ptr);
errno = ENOMEM;
return NULL;
}
@@ -940,11 +945,11 @@ extern "C" void* qemu_instrumented_realloc(void* mem, size_t bytes) {
/* Since we registered new decriptor with the emulator, we need
* to unregister it before freeing newly allocated block. */
notify_qemu_free(mallocdesc_user_ptr(&new_desc));
- Malloc(free)(new_desc.ptr);
+ g_malloc_dispatch->free(new_desc.ptr);
errno = ENOMEM;
return NULL;
}
- Malloc(free)(cur_desc.ptr);
+ g_malloc_dispatch->free(cur_desc.ptr);
log_mdesc(info, &new_desc, "=== <libc_pid=%03u, pid=%03u>: realloc(%p, %zu) -> ",
malloc_pid, getpid(), mem, bytes);
@@ -985,7 +990,7 @@ extern "C" void* qemu_instrumented_memalign(size_t alignment, size_t bytes) {
return NULL;
}
- desc.ptr = Malloc(memalign)(desc.prefix_size, size);
+ desc.ptr = g_malloc_dispatch->memalign(desc.prefix_size, size);
if (desc.ptr == NULL) {
error_log("<libc_pid=%03u, pid=%03u> memalign(%zx, %zu): malloc(%zu) failed.",
malloc_pid, getpid(), alignment, bytes, size);
@@ -994,7 +999,7 @@ extern "C" void* qemu_instrumented_memalign(size_t alignment, size_t bytes) {
if (notify_qemu_malloc(&desc)) {
log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: memalign(%zx, %zu): notify_malloc failed for ",
malloc_pid, getpid(), alignment, bytes);
- Malloc(free)(desc.ptr);
+ g_malloc_dispatch->free(desc.ptr);
return NULL;
}
@@ -1032,7 +1037,7 @@ extern "C" size_t qemu_instrumented_malloc_usable_size(const void* mem) {
}
extern "C" struct mallinfo qemu_instrumented_mallinfo() {
- return Malloc(mallinfo)();
+ return g_malloc_dispatch->mallinfo();
}
extern "C" int qemu_instrumented_posix_memalign(void** memptr, size_t alignment, size_t size) {
@@ -1048,7 +1053,7 @@ extern "C" int qemu_instrumented_posix_memalign(void** memptr, size_t alignment,
}
extern "C" void* qemu_instrumented_pvalloc(size_t bytes) {
- size_t pagesize = sysconf(_SC_PAGESIZE);
+ size_t pagesize = getpagesize();
size_t size = BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) { // Overflow
qemu_error_log("<libc_pid=%03u, pid=%03u> pvalloc(%zu): overflow (%zu).",
@@ -1059,5 +1064,5 @@ extern "C" void* qemu_instrumented_pvalloc(size_t bytes) {
}
extern "C" void* qemu_instrumented_valloc(size_t size) {
- return qemu_instrumented_memalign(sysconf(_SC_PAGESIZE), size);
+ return qemu_instrumented_memalign(getpagesize(), size);
}
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 2ded22b0f..174e30807 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -41,23 +41,12 @@
#include "private/ErrnoRestorer.h"
#include "private/ScopedPthreadMutexLocker.h"
-// Used by gdb to track thread creation. See libthread_db.
-#ifdef __i386__
-extern "C" __attribute__((noinline)) __attribute__((fastcall)) void _thread_created_hook(pid_t) {}
-#else
-extern "C" __attribute__((noinline)) void _thread_created_hook(pid_t) {}
-#endif
-
// x86 uses segment descriptors rather than a direct pointer to TLS.
#if __i386__
#include <asm/ldt.h>
extern "C" __LIBC_HIDDEN__ void __init_user_desc(struct user_desc*, int, void*);
#endif
-static pthread_mutex_t g_pthread_stack_creation_lock = PTHREAD_MUTEX_INITIALIZER;
-
-static pthread_mutex_t g_debugger_notification_lock = PTHREAD_MUTEX_INITIALIZER;
-
extern "C" int __isthreaded;
// This code is used both by each new pthread and the code that initializes the main thread.
@@ -113,8 +102,6 @@ int __init_thread(pthread_internal_t* thread, bool add_to_thread_list) {
}
static void* __create_thread_stack(pthread_internal_t* thread) {
- ScopedPthreadMutexLocker lock(&g_pthread_stack_creation_lock);
-
// Create a new private anonymous map.
int prot = PROT_READ | PROT_WRITE;
int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE;
@@ -258,12 +245,6 @@ int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr,
return init_errno;
}
- // Notify any debuggers about the new thread.
- {
- ScopedPthreadMutexLocker debugger_locker(&g_debugger_notification_lock);
- _thread_created_hook(thread->tid);
- }
-
// Publish the pthread_t and unlock the mutex to let the new thread start running.
*thread_out = reinterpret_cast<pthread_t>(thread);
pthread_mutex_unlock(&thread->startup_handshake_mutex);
diff --git a/libc/bionic/strcoll_l.cpp b/libc/bionic/strcoll_l.cpp
new file mode 100644
index 000000000..7d7c28bef
--- /dev/null
+++ b/libc/bionic/strcoll_l.cpp
@@ -0,0 +1,33 @@
+/*
+ * 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/strerror_r.cpp b/libc/bionic/strerror_r.cpp
index 5f2d36214..1e57cc0b3 100644
--- a/libc/bionic/strerror_r.cpp
+++ b/libc/bionic/strerror_r.cpp
@@ -8,6 +8,7 @@
#include <string.h>
#include "private/ErrnoRestorer.h"
+#include "private/libc_logging.h"
struct Pair {
int code;
@@ -49,9 +50,9 @@ int strerror_r(int error_number, char* buf, size_t buf_len) {
const char* error_name = __strerror_lookup(error_number);
if (error_name != NULL) {
- length = snprintf(buf, buf_len, "%s", error_name);
+ length = strlcpy(buf, error_name, buf_len);
} else {
- length = snprintf(buf, buf_len, "Unknown error %d", error_number);
+ length = __libc_format_buffer(buf, buf_len, "Unknown error %d", error_number);
}
if (length >= buf_len) {
errno_restorer.override(ERANGE);
diff --git a/libc/bionic/strftime_l.cpp b/libc/bionic/strftime_l.cpp
new file mode 100644
index 000000000..fb01da5f2
--- /dev/null
+++ b/libc/bionic/strftime_l.cpp
@@ -0,0 +1,34 @@
+/*
+ * 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
new file mode 100644
index 000000000..4b230b94a
--- /dev/null
+++ b/libc/bionic/strtold_l.cpp
@@ -0,0 +1,33 @@
+/*
+ * 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
new file mode 100644
index 000000000..05fb76083
--- /dev/null
+++ b/libc/bionic/strtoll_l.cpp
@@ -0,0 +1,33 @@
+/*
+ * 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, size_t base, locale_t) {
+ return strtoll(nptr, endptr, base);
+}
diff --git a/libc/bionic/strtoull_l.cpp b/libc/bionic/strtoull_l.cpp
new file mode 100644
index 000000000..ba0bc6ad4
--- /dev/null
+++ b/libc/bionic/strtoull_l.cpp
@@ -0,0 +1,34 @@
+/*
+ * 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, size_t base,
+ locale_t) {
+ return strtoull(nptr, endptr, base);
+}
diff --git a/libc/bionic/strxfrm_l.cpp b/libc/bionic/strxfrm_l.cpp
new file mode 100644
index 000000000..afe3b965c
--- /dev/null
+++ b/libc/bionic/strxfrm_l.cpp
@@ -0,0 +1,33 @@
+/*
+ * 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);
+}
diff --git a/libc/bionic/stubs.cpp b/libc/bionic/stubs.cpp
index 9b025df7c..0937e9c06 100644
--- a/libc/bionic/stubs.cpp
+++ b/libc/bionic/stubs.cpp
@@ -469,5 +469,6 @@ void endusershell() {
// Portable code should use sysconf(_SC_PAGE_SIZE) directly instead.
int getpagesize() {
- return sysconf(_SC_PAGE_SIZE);
+ // We dont use sysconf(3) here because that drags in stdio, which makes static binaries fat.
+ return PAGE_SIZE;
}
diff --git a/libc/bionic/wchar.cpp b/libc/bionic/wchar.cpp
index acb27617a..ecb8b3391 100644
--- a/libc/bionic/wchar.cpp
+++ b/libc/bionic/wchar.cpp
@@ -219,3 +219,25 @@ size_t wcsnrtombs(char* dst, const wchar_t** src, size_t nwc, size_t len, mbstat
size_t wcsrtombs(char* dst, const wchar_t** src, size_t len, mbstate_t* ps) {
return wcsnrtombs(dst, src, SIZE_MAX, len, ps);
}
+
+int wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t) {
+ return wcscoll(ws1, ws2);
+}
+
+size_t wcsxfrm_l(wchar_t *dest, const wchar_t *src, size_t n, locale_t) {
+ return wcsxfrm(dest, src, n);
+}
+
+long long wcstoll_l(const wchar_t *nptr, wchar_t **endptr, size_t base,
+ locale_t) {
+ return wcstoll(nptr, endptr, base);
+}
+
+unsigned long long wcstoull_l(const wchar_t *nptr, wchar_t **endptr,
+ size_t base, locale_t) {
+ return wcstoull(nptr, endptr, base);
+}
+
+long double wcstold_l(const wchar_t *nptr, wchar_t **endptr, locale_t) {
+ return wcstold(nptr, endptr);
+}
diff --git a/libc/bionic/wctype.cpp b/libc/bionic/wctype.cpp
index 673402d6b..f2d7861c2 100644
--- a/libc/bionic/wctype.cpp
+++ b/libc/bionic/wctype.cpp
@@ -30,6 +30,7 @@
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
+#include <wctype.h>
// TODO: these only work for the ASCII range; rewrite to dlsym icu4c? http://b/14499654
@@ -46,6 +47,19 @@ int iswspace(wint_t wc) { return isspace(wc); }
int iswupper(wint_t wc) { return isupper(wc); }
int iswxdigit(wint_t wc) { return isxdigit(wc); }
+int iswalnum_l(wint_t c, locale_t) { return iswalnum(c); }
+int iswalpha_l(wint_t c, locale_t) { return iswalpha(c); }
+int iswblank_l(wint_t c, locale_t) { return iswblank(c); }
+int iswcntrl_l(wint_t c, locale_t) { return iswcntrl(c); }
+int iswdigit_l(wint_t c, locale_t) { return iswdigit(c); }
+int iswgraph_l(wint_t c, locale_t) { return iswgraph(c); }
+int iswlower_l(wint_t c, locale_t) { return iswlower(c); }
+int iswprint_l(wint_t c, locale_t) { return iswprint(c); }
+int iswpunct_l(wint_t c, locale_t) { return iswpunct(c); }
+int iswspace_l(wint_t c, locale_t) { return iswspace(c); }
+int iswupper_l(wint_t c, locale_t) { return iswupper(c); }
+int iswxdigit_l(wint_t c, locale_t) { return iswxdigit(c); }
+
int iswctype(wint_t wc, wctype_t char_class) {
switch (char_class) {
case WC_TYPE_ALNUM: return iswalnum(wc);
@@ -64,9 +78,16 @@ int iswctype(wint_t wc, wctype_t char_class) {
}
}
+int iswctype_l(wint_t wc, wctype_t char_class, locale_t) {
+ return iswctype(wc, char_class);
+}
+
wint_t towlower(wint_t wc) { return tolower(wc); }
wint_t towupper(wint_t wc) { return toupper(wc); }
+int towupper_l(int c, locale_t) { return towupper(c); }
+int towlower_l(int c, locale_t) { return towlower(c); }
+
wctype_t wctype(const char* property) {
static const char* const properties[WC_TYPE_MAX] = {
"<invalid>",
@@ -81,6 +102,10 @@ wctype_t wctype(const char* property) {
return static_cast<wctype_t>(0);
}
+wctype_t wctype_l(const char* property, locale_t) {
+ return wctype(property);
+}
+
int wcwidth(wchar_t wc) {
return (wc > 0);
}