Merge "Add clang3.2 to test list"
diff --git a/sources/cxx-stl/gabi++/src/terminate.cc b/sources/cxx-stl/gabi++/src/terminate.cc
index 576b18a..17435f9 100644
--- a/sources/cxx-stl/gabi++/src/terminate.cc
+++ b/sources/cxx-stl/gabi++/src/terminate.cc
@@ -157,11 +157,7 @@
bool uncaught_exception() throw() {
using namespace __cxxabiv1;
- __cxa_eh_globals* globals = __cxa_get_globals_fast();
- if (!globals) {
- return false;
- }
-
+ __cxa_eh_globals* globals = __cxa_get_globals();
return globals->uncaughtExceptions != 0;
}
diff --git a/sources/cxx-stl/llvm-libc++/android/llvm-libc++/Android.mk b/sources/cxx-stl/llvm-libc++/android/llvm-libc++/Android.mk
index 4e2448a..4bca4f6 100644
--- a/sources/cxx-stl/llvm-libc++/android/llvm-libc++/Android.mk
+++ b/sources/cxx-stl/llvm-libc++/android/llvm-libc++/Android.mk
@@ -28,6 +28,10 @@
utility.cpp \
valarray.cpp
+llvm_libc++_sources += \
+ support/android/locale_support.c \
+ support/android/wchar_support.c
+
llvm_libc++_sources := $(llvm_libc++_sources:%=src/%)
llvm_libc++_cxxflags := -std=c++11
diff --git a/sources/cxx-stl/llvm-libc++/include/support/android/ctype.h b/sources/cxx-stl/llvm-libc++/include/support/android/ctype.h
index 830fb78..847a340 100644
--- a/sources/cxx-stl/llvm-libc++/include/support/android/ctype.h
+++ b/sources/cxx-stl/llvm-libc++/include/support/android/ctype.h
@@ -4,7 +4,9 @@
#include_next <ctype.h>
#include <xlocale.h>
+#ifdef __cplusplus
extern "C" {
+#endif
# define __exctype_l(name) extern int name (int, locale_t)
@@ -24,6 +26,8 @@
int tolower_l(int c, locale_t);
int toupper_l(int c, locale_t);
+#ifdef __cplusplus
} // extern "C"
+#endif
#endif // LLVM_LIBCXX_SUPPORT_ANDROID_CTYPE_H
diff --git a/sources/cxx-stl/llvm-libc++/include/support/android/locale.h b/sources/cxx-stl/llvm-libc++/include/support/android/locale.h
index 9270560..2f98dc5 100644
--- a/sources/cxx-stl/llvm-libc++/include/support/android/locale.h
+++ b/sources/cxx-stl/llvm-libc++/include/support/android/locale.h
Binary files differ
diff --git a/sources/cxx-stl/llvm-libc++/include/support/android/math.h b/sources/cxx-stl/llvm-libc++/include/support/android/math.h
index ec5e566..1890945 100644
--- a/sources/cxx-stl/llvm-libc++/include/support/android/math.h
+++ b/sources/cxx-stl/llvm-libc++/include/support/android/math.h
@@ -3,6 +3,10 @@
#include_next <math.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
// TODO(digit): Check that this is not needed for Clang.
typedef double double_t;
typedef double float_t;
@@ -56,4 +60,8 @@
float log2f(float);
double log2(double);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif /* LLVM_LIBCXX_SUPPORT_ANDROID_MATH_H */
diff --git a/sources/cxx-stl/llvm-libc++/include/support/android/nl_types.h b/sources/cxx-stl/llvm-libc++/include/support/android/nl_types.h
index 46248c5..3346da8 100644
--- a/sources/cxx-stl/llvm-libc++/include/support/android/nl_types.h
+++ b/sources/cxx-stl/llvm-libc++/include/support/android/nl_types.h
@@ -4,6 +4,10 @@
#define NL_SETD 1
#define NL_CAT_LOCALE 1
+#ifdef __cplusplus
+extern "C" {
+#endif
+
typedef void* nl_catd;
typedef int nl_item;
@@ -11,5 +15,9 @@
char* catgets(nl_catd, int, int, const char*);
int catclose(nl_catd);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif /* LLVM_LIBCXX_SUPPORT_ANDROID_NL_TYPES_H */
diff --git a/sources/cxx-stl/llvm-libc++/include/support/android/stdio.h b/sources/cxx-stl/llvm-libc++/include/support/android/stdio.h
index 8a2915b..8d0b3da 100644
--- a/sources/cxx-stl/llvm-libc++/include/support/android/stdio.h
+++ b/sources/cxx-stl/llvm-libc++/include/support/android/stdio.h
@@ -10,9 +10,11 @@
#include <stdarg.h>
#include <xlocale.h>
+#ifdef __cplusplus
extern "C" {
+#endif
-char* asprintf_l(char**, locale_t, const char*, ...);
+int asprintf_l(char**, locale_t, const char*, ...);
int sprintf_l(char*, locale_t, const char*, ...);
int snprintf_l(char*, size_t, locale_t, const char*, ...);
int sscanf_l(const char*, locale_t, const char*, ...);
@@ -21,6 +23,8 @@
int vswscanf(const wchar_t *, const wchar_t *, va_list);
int vwscanf(const wchar_t *, va_list);
+#ifdef __cplusplus
} // extern "C"
+#endif
#endif // LLVM_LIBCXX_SUPPORT_ANDROID_STDIO_H
diff --git a/sources/cxx-stl/llvm-libc++/include/support/android/stdlib.h b/sources/cxx-stl/llvm-libc++/include/support/android/stdlib.h
index bb01582..3ce85dd 100644
--- a/sources/cxx-stl/llvm-libc++/include/support/android/stdlib.h
+++ b/sources/cxx-stl/llvm-libc++/include/support/android/stdlib.h
@@ -4,7 +4,9 @@
#include_next <stdlib.h>
#include <xlocale.h>
+#ifdef __cplusplus
extern "C" {
+#endif
long long strtoll(const char*, char**, int);
long double strtold(const char*, char**);
@@ -16,6 +18,8 @@
unsigned long long strtoull_l(const char *nptr, char **endptr, int base, locale_t loc);
long double strtold_l (const char *nptr, char **endptr, locale_t loc);
+#ifdef __cplusplus
} // extern "C"
+#endif
#endif // LLVM_LIBCXX_SUPPORT_ANDROID_STDLIB_H
diff --git a/sources/cxx-stl/llvm-libc++/include/support/android/string.h b/sources/cxx-stl/llvm-libc++/include/support/android/string.h
index d6b8500..b78b494 100644
--- a/sources/cxx-stl/llvm-libc++/include/support/android/string.h
+++ b/sources/cxx-stl/llvm-libc++/include/support/android/string.h
@@ -4,11 +4,15 @@
#include_next <string.h>
#include <xlocale.h>
+#ifdef __cplusplus
extern "C" {
+#endif
int strcoll_l(const char*, const char*, locale_t);
int strxfrm_l(char*, const char*, size_t, locale_t);
+#ifdef __cplusplus
} // extern "C"
+#endif
#endif // LLVM_LIBCXX_SUPPORT_ANDROID_STRING_H
diff --git a/sources/cxx-stl/llvm-libc++/include/support/android/time.h b/sources/cxx-stl/llvm-libc++/include/support/android/time.h
index 2715b3e..3706af8 100644
--- a/sources/cxx-stl/llvm-libc++/include/support/android/time.h
+++ b/sources/cxx-stl/llvm-libc++/include/support/android/time.h
@@ -4,11 +4,15 @@
#include_next <time.h>
#include <xlocale.h>
+#ifdef __cplusplus
extern "C" {
+#endif
size_t strftime_l(char *s, size_t maxsize, const char *format,
const struct tm * timeptr, locale_t locale);
+#ifdef __cplusplus
} // extern "C"
+#endif
#endif // LLVM_LIBCXX_SUPPORT_ANDROID_TIME_H
diff --git a/sources/cxx-stl/llvm-libc++/include/support/android/wchar.h b/sources/cxx-stl/llvm-libc++/include/support/android/wchar.h
index a438d05..f80f592 100644
--- a/sources/cxx-stl/llvm-libc++/include/support/android/wchar.h
+++ b/sources/cxx-stl/llvm-libc++/include/support/android/wchar.h
@@ -4,7 +4,9 @@
#include_next <wchar.h>
#include <xlocale.h>
+#ifdef __cplusplus
extern "C" {
+#endif
// Add missing declarations that are not in the NDK.
float wcstof(const wchar_t*, wchar_t**);
@@ -25,6 +27,8 @@
int wcscoll_l(const wchar_t*, const wchar_t*, locale_t);
int wcsxfrm_l(wchar_t*, const wchar_t*, size_t, locale_t);
+#ifdef __cplusplus
} // extern "C"
+#endif
#endif // LLVM_LIBCXX_SUPPORT_ANDROID_WCHAR_H
diff --git a/sources/cxx-stl/llvm-libc++/include/support/android/wctype.h b/sources/cxx-stl/llvm-libc++/include/support/android/wctype.h
index 7dd272f..4291f8a 100644
--- a/sources/cxx-stl/llvm-libc++/include/support/android/wctype.h
+++ b/sources/cxx-stl/llvm-libc++/include/support/android/wctype.h
@@ -4,7 +4,9 @@
#include_next <wctype.h>
#include <xlocale.h>
+#ifdef __cplusplus
extern "C" {
+#endif
// Add missing declarations from the NDK header. Implemented under
// src/android/wctype.cc
@@ -25,6 +27,8 @@
wint_t towlower_l(wint_t, locale_t);
wint_t towupper_l(wint_t, locale_t);
+#ifdef __cplusplus
} // extern "C"
+#endif
#endif // LLVM_LIBCXX_SUPPORT_ANDROID_WCTYPES_H
diff --git a/sources/cxx-stl/llvm-libc++/include/support/android/xlocale.h b/sources/cxx-stl/llvm-libc++/include/support/android/xlocale.h
index 23e2def..c391c57 100644
--- a/sources/cxx-stl/llvm-libc++/include/support/android/xlocale.h
+++ b/sources/cxx-stl/llvm-libc++/include/support/android/xlocale.h
@@ -1,7 +1,9 @@
#ifndef LLVM_LIBCXX_SUPPORT_ANDROID_XLOCALE_H
#define LLVM_LIBCXX_SUPPORT_ANDROID_XLOCALE_H
+#ifdef __cplusplus
extern "C" {
+#endif
typedef struct locale_struct* locale_t;
@@ -9,6 +11,8 @@
void* dummy;
};
+#ifdef __cplusplus
} // extern "C"
+#endif
#endif // LLVM_LIBCXX_SUPPORT_ANDROID_XLOCALE_H
diff --git a/sources/cxx-stl/llvm-libc++/src/support/android/locale_support.c b/sources/cxx-stl/llvm-libc++/src/support/android/locale_support.c
new file mode 100644
index 0000000..7bad7ec
--- /dev/null
+++ b/sources/cxx-stl/llvm-libc++/src/support/android/locale_support.c
@@ -0,0 +1,280 @@
+// -*- C++ -*-
+//===-------------------- support/android/locale_support.c ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <wctype.h>
+
+// Contains an implementation of all locale-specific functions (those
+// ending in _l, like strcoll_l()), as simple wrapper to the non-locale
+// specific ones for now.
+//
+// That's because Android's C library doesn't support locales. Or more
+// specifically, only supports the "C" one.
+//
+// TODO(digit): Write a more complete implementation that uses JNI to
+// invoke the platform APIs to implement proper handling.
+//
+
+///////////////////////////////////////////////////////////////////////
+// ctype.h declarations
+
+# define define_char_wrapper_l(name) \
+ int name ## _l (int ch, locale_t loc) { \
+ return name (ch); \
+ }
+
+define_char_wrapper_l (isalnum);
+define_char_wrapper_l (isalpha);
+define_char_wrapper_l (iscntrl);
+define_char_wrapper_l (isdigit);
+define_char_wrapper_l (islower);
+define_char_wrapper_l (isgraph);
+define_char_wrapper_l (isprint);
+define_char_wrapper_l (ispunct);
+define_char_wrapper_l (isspace);
+define_char_wrapper_l (isupper);
+define_char_wrapper_l (isxdigit);
+define_char_wrapper_l (isblank);
+define_char_wrapper_l (tolower)
+define_char_wrapper_l (toupper)
+
+///////////////////////////////////////////////////////////////////////
+// stdio.h declarations
+
+int vasprintf_l(char** strp, locale_t l, const char* fmt, va_list args) {
+ // Ignore locale.
+ return vasprintf(strp, fmt, args);
+}
+
+int asprintf_l(char** strp, locale_t locale, const char* fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ int result = vasprintf_l(strp, locale, fmt, args);
+ va_end(args);
+ return result;
+}
+
+int vsprintf_l(char* str, locale_t l, const char* fmt, va_list args) {
+ // Ignore locale.
+ return vsprintf(str, fmt, args);
+}
+
+int sprintf_l(char* str, locale_t l, const char* fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ int result = vsprintf_l(str, l, fmt, args);
+ va_end(args);
+ return result;
+}
+
+int vsnprintf_l(char* str, size_t size, locale_t l, const char* fmt, va_list args) {
+ return vsnprintf(str, size, fmt, args);
+}
+
+int snprintf_l(char* str, size_t size, locale_t l, const char* fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ int result = vsnprintf_l(str, size, l, fmt, args);
+ va_end(args);
+ return result;
+}
+
+int vsscanf_l(const char* str, locale_t l, const char* fmt, va_list args) {
+ return vsscanf(str, fmt, args);
+}
+
+int sscanf_l(const char* str, locale_t l, const char* fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ int result = vsscanf_l(str, l, fmt, args);
+ va_end(args);
+ return result;
+}
+
+///////////////////////////////////////////////////////////////////////
+// stdlib.h declarations
+
+long strtol_l(const char *nptr, char **endptr, int base, locale_t loc) {
+ return strtol(nptr, endptr, base);
+}
+
+long long strtoll_l(const char *nptr, char **endptr, int base, locale_t loc) {
+ return strtoll(nptr, endptr, base);
+}
+
+unsigned long strtoul_l(const char *nptr, char **endptr, int base, locale_t loc) {
+ return strtoul(nptr, endptr, base);
+}
+
+unsigned long long strtoull_l(const char *nptr, char **endptr, int base, locale_t loc) {
+ return strtoull(nptr, endptr, base);
+}
+
+long double strtold_l (const char *nptr, char **endptr, locale_t loc) {
+ return strtold(nptr, endptr);
+}
+
+///////////////////////////////////////////////////////////////////////
+// string.h declarations
+
+int strcoll_l(const char* s1, const char* s2, locale_t loc) {
+ return strcoll(s1, s2);
+}
+
+int strxfrm_l(char* dst, const char* src, size_t n, locale_t loc) {
+ return strxfrm(dst, src, n);
+}
+
+///////////////////////////////////////////////////////////////////////
+// time.h declarations
+
+size_t strftime_l(char *s, size_t maxsize, const char *format,
+ const struct tm * timeptr, locale_t loc) {
+ return strftime(s, maxsize, format, timeptr);
+}
+
+///////////////////////////////////////////////////////////////////////
+// wchar.h declarations
+
+int wcscoll_l(const wchar_t* s1, const wchar_t* s2, locale_t loc) {
+ return wcscoll(s1, s2);
+}
+
+int wcsxfrm_l(wchar_t* dst, const wchar_t* src, size_t n, locale_t loc) {
+ return wcsxfrm(dst, src, n);
+}
+
+///////////////////////////////////////////////////////////////////////
+// wctype.h declarations
+
+#define define_wchar_wrapper(name) \
+ int name ## _l (wint_t c, locale_t loc) { \
+ return name (c); \
+ }
+
+define_wchar_wrapper(iswspace)
+define_wchar_wrapper(iswprint)
+define_wchar_wrapper(iswcntrl)
+define_wchar_wrapper(iswupper)
+define_wchar_wrapper(iswlower)
+define_wchar_wrapper(iswalpha)
+define_wchar_wrapper(iswdigit)
+define_wchar_wrapper(iswpunct)
+define_wchar_wrapper(iswxdigit)
+define_wchar_wrapper(iswblank)
+
+wint_t towlower_l(wint_t c, locale_t loc) {
+ return towlower(c);
+}
+
+wint_t towupper_l(wint_t c, locale_t loc) {
+ return towupper(c);
+}
+
+///////////////////////////////////////////////////////////////////////
+// locale.h declarations
+
+#define LC_NULL_LOCALE ((locale_t)0)
+
+locale_t newlocale(int category_mask, const char* locale, locale_t base) {
+ if (base != LC_NULL_LOCALE)
+ return base;
+
+ locale_t loc = calloc(1, sizeof(*loc));
+ return loc;
+}
+
+locale_t duplocale(locale_t loc) {
+ if (loc == LC_GLOBAL_LOCALE)
+ return loc;
+ if (loc == LC_NULL_LOCALE) {
+ errno = EINVAL;
+ return LC_NULL_LOCALE;
+ }
+ locale_t copy = calloc(1, sizeof(*loc));
+ copy[0] = loc[0];
+ return copy;
+}
+
+
+// Static mutable variable because setlocale() is supposed to return
+// a pointer to a writable C string.
+static char g_C_LOCALE_SETTING[] = "C";
+
+char *setlocale(int category, const char *locale) {
+ // Sanity check.
+ if (!locale) {
+ errno = EINVAL;
+ return NULL;
+ }
+ // Only accept "", "C" or "POSIX", all equivalent on Android.
+ if (strcmp(locale, "") && strcmp(locale, "C") && strcmp(locale, "POSIX")) {
+ errno = EINVAL;
+ return NULL;
+ }
+ return g_C_LOCALE_SETTING;
+}
+
+locale_t uselocale(locale_t loc) {
+ // If 'loc' is LC_GLOBAL_LOCALE, should return the global locale set
+ // through setlocale(). Since the implementation above doesn't modify
+ // anything, just return LC_GLOBAL_LOCALE too.
+
+ // If 'loc' is (locale_t)0, should return either LC_GLOBAL_LOCALE or
+ // or the global locale if setlocale() has been called at least once.
+
+ // Should return the previous value from a previous call, of
+ // LC_GLOBAL_LOCALE.
+
+ // So, in all cases, return LC_GLOBAL_LOCALE
+ return LC_GLOBAL_LOCALE;
+}
+
+void freelocale(locale_t loc) {
+ if (loc != LC_NULL_LOCALE && loc != LC_GLOBAL_LOCALE)
+ free(loc);
+}
+
+static struct lconv g_C_LCONV[1] = { {
+ .decimal_point = ".",
+ .thousands_sep = "",
+ .grouping = "",
+ .int_curr_symbol = "",
+ .currency_symbol = "",
+ .mon_decimal_point = "",
+ .mon_thousands_sep = "",
+ .mon_grouping = "",
+ .positive_sign = "",
+ .negative_sign = "",
+ .int_frac_digits = CHAR_MAX,
+ .frac_digits = CHAR_MAX,
+ .p_cs_precedes = CHAR_MAX,
+ .p_sep_by_space = CHAR_MAX,
+ .n_cs_precedes = CHAR_MAX,
+ .n_sep_by_space = CHAR_MAX,
+ .p_sign_posn = CHAR_MAX,
+ .n_sign_posn = CHAR_MAX,
+ .int_p_cs_precedes = CHAR_MAX,
+ .int_p_sep_by_space = CHAR_MAX,
+ .int_n_cs_precedes = CHAR_MAX,
+ .int_n_sep_by_space = CHAR_MAX,
+ .int_p_sign_posn = CHAR_MAX,
+ .int_n_sign_posn = CHAR_MAX,
+} };
+
+struct lconv* localeconv(void) {
+ return g_C_LCONV;
+}
diff --git a/sources/cxx-stl/llvm-libc++/src/support/android/wchar_support.c b/sources/cxx-stl/llvm-libc++/src/support/android/wchar_support.c
new file mode 100644
index 0000000..6987bcd
--- /dev/null
+++ b/sources/cxx-stl/llvm-libc++/src/support/android/wchar_support.c
@@ -0,0 +1,379 @@
+// -*- C++ -*-
+//===-------------------- support/android/wchar_support.c ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+
+// Returns 1 if 'wc' is in the 'delim' string, 0 otherwise.
+static int _wc_indelim(wchar_t wc, const wchar_t* delim) {
+ while (*delim) {
+ if (wc == *delim)
+ return 1;
+ }
+ return 0;
+}
+
+wchar_t *wcpcpy(wchar_t *to, const wchar_t *from) {
+ size_t n = 0;
+ for (;;) {
+ wchar_t wc = from[n];
+ to[n] = wc;
+ if (wc == L'\0')
+ break;
+ n++;
+ }
+ return to;
+}
+
+wchar_t *wcpncpy(wchar_t *dst, const wchar_t *src, size_t n) {
+ size_t i;
+ for (i = 0; i < n; ++i) {
+ wchar_t wc = src[i];
+ dst[i] = wc;
+ if (wc == L'\0')
+ break;
+ }
+ while (i < n) {
+ dst[i] = L'\0';
+ ++i;
+ }
+ return &dst[n-1];
+}
+
+int wcscasecmp(const wchar_t *s1, const wchar_t *s2) {
+ size_t n = 0;
+ for (;;) {
+ wchar_t wc1 = towlower(s1[n]);
+ wchar_t wc2 = towlower(s2[n]);
+ if (wc1 != wc2)
+ return (wc1 > wc2) ? +1 : -1;
+ if (wc1 == L'\0')
+ return 0;
+ n++;
+ }
+}
+
+wchar_t *wcscat(wchar_t *s1, const wchar_t *s2) {
+ size_t n = 0;
+ while (s1[n] != L'\0')
+ n++;
+
+ size_t i = 0;
+ for (;;) {
+ wchar_t wc = s2[i];
+ s1[n+i] = wc;
+ if (wc == L'\0')
+ break;
+ }
+ return s1;
+}
+
+size_t wcslcat(wchar_t *dst, const wchar_t *src, size_t siz) {
+ // Sanity check simplifies code below
+ if (siz == 0)
+ return 0;
+
+ // Skip dst characters.
+ size_t n;
+ for (n = 0; n < siz && dst[n] != L'\0'; ++n)
+ ;
+
+ // Copy as much source characters as they fit into siz-1 bytes.
+ size_t i;
+ for (i = 0; n+i+1 < siz && src[i] != L'\0'; ++i)
+ dst[n+i] = src[i];
+
+ // Always zero terminate destination
+ dst[n+i] = L'\0';
+
+ // Skip remaining source characters
+ while (src[i] != L'\0')
+ i++;
+
+ return n+i;
+}
+
+size_t wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz) {
+ size_t i;
+
+ // Copy all non-zero bytes that fit into siz-1 destination bytes
+ for (i = 0; i + 1 < siz && src[i] != L'\0'; ++i)
+ dst[i] = src[i];
+
+ // Always zero-terminate destination buffer
+ dst[i] = L'\0';
+
+ // Skip other source characters.
+ while (src[i] != L'\0')
+ ++i;
+
+ return i;
+}
+
+size_t wcslen(const wchar_t *s) {
+ size_t n = 0;
+ for (;;) {
+ wchar_t wc = s[n];
+ if (wc == L'\0')
+ return n;
+ n++;
+ }
+}
+
+int wcsncasecmp(const wchar_t *s1, const wchar_t *s2, size_t n) {
+ size_t i;
+ for (i = 0; i < n; ++i) {
+ wchar_t wc1 = towlower(s1[i]);
+ wchar_t wc2 = towlower(s2[i]);
+ if (wc1 != wc2)
+ return (wc1 > wc2) ? +1 : -1;
+ }
+ return 0;
+}
+
+wchar_t *wcsncat(wchar_t *s1, const wchar_t *s2, size_t n) {
+ size_t start = 0;
+ while (s1[start] != L'\0')
+ start++;
+
+ // Append s2.
+ size_t i;
+ for (i = 0; i < n; ++i) {
+ wchar_t wc = s2[i];
+ s1[start + i] = wc;
+ if (wc == L'\0')
+ break;
+ }
+ return (wchar_t*)s1;
+}
+
+int wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n) {
+ size_t i;
+ for (i = 0; i < n; ++i) {
+ wchar_t wc = s1[i];
+ if (wc != s2[i])
+ return (wc > s2[i]) ? +1 : -1;
+ if (wc == L'\0')
+ break;
+ }
+ return 0;
+}
+
+wchar_t *wcsncpy(wchar_t *dst, const wchar_t *src, size_t n) {
+ // Copy initial characters.
+ size_t i;
+ for (i = 0; i < n; ++i) {
+ wchar_t wc = src[i];
+ if (wc == L'\0')
+ break;
+ dst[i] = wc;
+ }
+ // zero-pad the remainder.
+ for ( ; i < n; ++i)
+ dst[i] = L'\0';
+
+ return dst;
+}
+
+size_t wcsnlen(const wchar_t *s, size_t maxlen) {
+ size_t n;
+ for (n = 0; n < maxlen; ++n) {
+ if (s[n] == L'\0')
+ break;
+ }
+ return n;
+}
+
+wchar_t *wcspbrk(const wchar_t *s, const wchar_t *set) {
+ size_t n = 0;
+ for (;;) {
+ wchar_t wc = s[n];
+ if (!wc)
+ return NULL;
+ if (_wc_indelim(wc, set))
+ return (wchar_t*)&s[n];
+ n++;
+ }
+}
+
+wchar_t *wcsrchr(const wchar_t *s, wchar_t c) {
+ size_t n = 0;
+ wchar_t* last = NULL;
+ for (;;) {
+ wchar_t wc = s[n];
+ if (wc == c)
+ last = (wchar_t*)s + n;
+ if (wc == L'\0')
+ break;
+ n++;
+ }
+ return last;
+}
+
+size_t wcsspn(const wchar_t *s, const wchar_t *set) {
+ size_t n = 0;
+ for (;;) {
+ wchar_t wc = s[n];
+ if (wc == L'\0')
+ break;
+ if (!_wc_indelim(wc, set))
+ break;
+ ++n;
+ }
+ return n;
+}
+
+wchar_t *wcsstr(const wchar_t *s, const wchar_t *find) {
+ wchar_t find_c;
+
+ // Always find the empty string
+ find_c = *find++;
+ if (!find_c)
+ return (wchar_t*)s;
+
+ size_t find_len = wcslen(find);
+
+ for (;;) {
+ wchar_t* p = wcschr(s, find_c);
+ if (p == NULL)
+ return NULL;
+
+ if (!wmemcmp(p, find, find_len))
+ return p;
+
+ s = p + 1;
+ }
+ return NULL;
+}
+
+wchar_t *wcstok(wchar_t *s, const wchar_t *delim, wchar_t **last) {
+ if (s == NULL) {
+ s = *last;
+ if (s == NULL)
+ return NULL;
+ }
+
+ // Skip leading delimiters first.
+ size_t i = 0;
+ wchar_t wc;
+ for (;;) {
+ wc = s[i];
+ if (wc && _wc_indelim(wc, delim)) {
+ i++;
+ continue;
+ }
+ break;
+ }
+
+ if (!wc) {
+ // Nothing left.
+ *last = NULL;
+ return NULL;
+ }
+
+ size_t tok_start = i;
+
+ // Skip non delimiters now.
+ for (;;) {
+ wc = s[i];
+ if (wc && !_wc_indelim(wc, delim)) {
+ i++;
+ continue;
+ }
+ break;
+ }
+
+ if (!wc) {
+ *last = NULL;
+ } else {
+ s[i] = L'\0';
+ *last = &s[i+1];
+ }
+ return &s[tok_start];
+}
+
+int wcswidth(const wchar_t *str, size_t n) {
+ int len = 0;
+ size_t i;
+ for (i = 0; i < n; ++i) {
+ wchar_t wc = str[i];
+ if (wc == L'\0')
+ break;
+ int l = wcwidth(wc);
+ if (l < 0)
+ return -1;
+ len += l;
+ }
+ return len;
+}
+
+// TODO(digit): Handle real collations.
+size_t wcsxfrm(wchar_t *dst, const wchar_t *src, size_t len) {
+ // Handle trivial case first.
+ if (src[0] == L'\0') {
+ if (len != 0)
+ dst[0] = L'\0';
+ return 0;
+ }
+
+ size_t slen = wcslen(src);
+ if (len > 0) {
+ if (slen < len)
+ wcscpy(dst, src);
+ else {
+ wcsncpy(dst, src, len-1);
+ dst[len - 1] = L'\0';
+ }
+ }
+ return slen;
+}
+
+wchar_t * wmemchr(const wchar_t *s, wchar_t c, size_t n) {
+ size_t i;
+ for (i = 0; i < n; ++i) {
+ if (s[i] == c)
+ return (wchar_t*)&s[i];
+ }
+ return NULL;
+}
+
+int wmemcmp(const wchar_t *s1, const wchar_t *s2, size_t n) {
+ size_t i;
+ for (i = 0; i < n; ++i) {
+ if (s1[i] == s2[i])
+ continue;
+ if (s1[i] > s2[i])
+ return 1;
+ else
+ return -1;
+ }
+ return 0;
+}
+
+wchar_t * wmemcpy(wchar_t *d, const wchar_t *s, size_t n) {
+ return (wchar_t *)memcpy((char*)d,
+ (const char*)s,
+ n * sizeof(wchar_t));
+}
+
+wchar_t* wmemmove(wchar_t* d, const wchar_t* s, size_t n) {
+ return (wchar_t* )memmove((char*)d,
+ (const char*)s,
+ n * sizeof(wchar_t));
+}
+
+wchar_t* wmemset(wchar_t* s, wchar_t c, size_t n) {
+ size_t i;
+ for (i = 0; i < n; ++i)
+ s[i] = c;
+ return s;
+}
+