aboutsummaryrefslogtreecommitdiff
path: root/system/lib/libcxx/support
diff options
context:
space:
mode:
authorBruce Mitchener <bruce.mitchener@gmail.com>2013-02-17 14:29:14 +0700
committerBruce Mitchener <bruce.mitchener@gmail.com>2013-03-25 00:34:11 +0700
commit59ff5a6a3c3e1f5255c5cf29f98df633a77b89b3 (patch)
treec7660fa62600366e3479dbf6b2fd1d25709af1b5 /system/lib/libcxx/support
parent80fd6f0bce2b95db6ec539c9275ce24585550e7c (diff)
Update to current libcxx.
This doesn't work yet as it needs to be customized for use with emscripten still.
Diffstat (limited to 'system/lib/libcxx/support')
-rw-r--r--system/lib/libcxx/support/solaris/README4
-rw-r--r--system/lib/libcxx/support/solaris/mbsnrtowcs.inc76
-rw-r--r--system/lib/libcxx/support/solaris/wcsnrtombs.inc93
-rw-r--r--system/lib/libcxx/support/solaris/xlocale.c245
-rw-r--r--system/lib/libcxx/support/win32/locale_win32.cpp94
-rw-r--r--system/lib/libcxx/support/win32/support.cpp70
6 files changed, 582 insertions, 0 deletions
diff --git a/system/lib/libcxx/support/solaris/README b/system/lib/libcxx/support/solaris/README
new file mode 100644
index 00000000..89c887a3
--- /dev/null
+++ b/system/lib/libcxx/support/solaris/README
@@ -0,0 +1,4 @@
+This directory contains a partial implementation of the xlocale APIs for
+Solaris. Some portions are lifted from FreeBSD libc, and so are covered by a
+2-clause BSD license instead of the MIT/UUIC license that the rest of libc++ is
+distributed under.
diff --git a/system/lib/libcxx/support/solaris/mbsnrtowcs.inc b/system/lib/libcxx/support/solaris/mbsnrtowcs.inc
new file mode 100644
index 00000000..07404527
--- /dev/null
+++ b/system/lib/libcxx/support/solaris/mbsnrtowcs.inc
@@ -0,0 +1,76 @@
+
+
+/*-
+ * As noted in the source, some portions of this implementation are copied from
+ * FreeBSD libc. These are covered by the following copyright:
+ *
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ *
+ * 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.
+ */
+
+size_t
+mbsnrtowcs_l(wchar_t * __restrict dst, const char ** __restrict src,
+ size_t nms, size_t len, mbstate_t * __restrict ps, locale_t loc)
+{
+ const char *s;
+ size_t nchr;
+ wchar_t wc;
+ size_t nb;
+ FIX_LOCALE(loc);
+
+ s = *src;
+ nchr = 0;
+
+ if (dst == NULL) {
+ for (;;) {
+ if ((nb = mbrtowc_l(&wc, s, nms, ps, loc)) == (size_t)-1)
+ /* Invalid sequence - mbrtowc() sets errno. */
+ return ((size_t)-1);
+ else if (nb == 0 || nb == (size_t)-2)
+ return (nchr);
+ s += nb;
+ nms -= nb;
+ nchr++;
+ }
+ /*NOTREACHED*/
+ }
+
+ while (len-- > 0) {
+ if ((nb = mbrtowc_l(dst, s, nms, ps, loc)) == (size_t)-1) {
+ *src = s;
+ return ((size_t)-1);
+ } else if (nb == (size_t)-2) {
+ *src = s + nms;
+ return (nchr);
+ } else if (nb == 0) {
+ *src = NULL;
+ return (nchr);
+ }
+ s += nb;
+ nms -= nb;
+ nchr++;
+ dst++;
+ }
+ *src = s;
+ return (nchr);
+}
diff --git a/system/lib/libcxx/support/solaris/wcsnrtombs.inc b/system/lib/libcxx/support/solaris/wcsnrtombs.inc
new file mode 100644
index 00000000..67e7078f
--- /dev/null
+++ b/system/lib/libcxx/support/solaris/wcsnrtombs.inc
@@ -0,0 +1,93 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ *
+ * 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.
+ */
+
+
+size_t
+wcsnrtombs_l(char * __restrict dst, const wchar_t ** __restrict src,
+ size_t nwc, size_t len, mbstate_t * __restrict ps, locale_t loc)
+{
+ FIX_LOCALE(loc);
+ mbstate_t mbsbak;
+ char buf[MB_CUR_MAX_L(loc)];
+ const wchar_t *s;
+ size_t nbytes;
+ size_t nb;
+
+ s = *src;
+ nbytes = 0;
+
+ if (dst == NULL) {
+ while (nwc-- > 0) {
+ if ((nb = wcrtomb_l(buf, *s, ps, loc)) == (size_t)-1)
+ /* Invalid character - wcrtomb() sets errno. */
+ return ((size_t)-1);
+ else if (*s == L'\0')
+ return (nbytes + nb - 1);
+ s++;
+ nbytes += nb;
+ }
+ return (nbytes);
+ }
+
+ while (len > 0 && nwc-- > 0) {
+ if (len > (size_t)MB_CUR_MAX_L(loc)) {
+ /* Enough space to translate in-place. */
+ if ((nb = wcrtomb_l(dst, *s, ps, loc)) == (size_t)-1) {
+ *src = s;
+ return ((size_t)-1);
+ }
+ } else {
+ /*
+ * May not be enough space; use temp. buffer.
+ *
+ * We need to save a copy of the conversion state
+ * here so we can restore it if the multibyte
+ * character is too long for the buffer.
+ */
+ mbsbak = *ps;
+ if ((nb = wcrtomb_l(buf, *s, ps, loc)) == (size_t)-1) {
+ *src = s;
+ return ((size_t)-1);
+ }
+ if (nb > (int)len) {
+ /* MB sequence for character won't fit. */
+ *ps = mbsbak;
+ break;
+ }
+ memcpy(dst, buf, nb);
+ }
+ if (*s == L'\0') {
+ *src = NULL;
+ return (nbytes + nb - 1);
+ }
+ s++;
+ dst += nb;
+ len -= nb;
+ nbytes += nb;
+ }
+ *src = s;
+ return (nbytes);
+}
+
diff --git a/system/lib/libcxx/support/solaris/xlocale.c b/system/lib/libcxx/support/solaris/xlocale.c
new file mode 100644
index 00000000..a2c1fa90
--- /dev/null
+++ b/system/lib/libcxx/support/solaris/xlocale.c
@@ -0,0 +1,245 @@
+
+#ifdef __sun__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <locale.h>
+#include <limits.h>
+#include <assert.h>
+#include <sys/localedef.h>
+#include "xlocale.h"
+
+static _LC_locale_t *__C_locale;
+
+#define FIX_LOCALE(l) l = (l == 0) ? __C_locale : l
+
+#include "mbsnrtowcs.inc"
+#include "wcsnrtombs.inc"
+
+size_t __mb_cur_max(locale_t __l) {
+ FIX_LOCALE(__l);
+ return (__l->lc_ctype->cmapp->cm_mb_cur_max);
+}
+
+wint_t btowc_l(int __c, locale_t __l) {
+ FIX_LOCALE(__l);
+ return __l->lc_ctype->cmapp->core.user_api->btowc(__l->lc_ctype->cmapp, __c);
+}
+
+int wctob_l(wint_t __c, locale_t __l) {
+ FIX_LOCALE(__l);
+ return __l->lc_ctype->cmapp->core.user_api->wctob(__l->lc_ctype->cmapp, __c);
+}
+
+size_t wcrtomb_l(char *__s, wchar_t __wc, mbstate_t *__ps, locale_t __l) {
+ FIX_LOCALE(__l);
+ return __l->lc_ctype->cmapp->core.user_api->wcrtomb(__l->lc_ctype->cmapp,
+ __s, __wc, __ps);
+}
+
+size_t mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n,
+ mbstate_t *__ps, locale_t __l) {
+ FIX_LOCALE(__l);
+ return __l->lc_ctype->cmapp->core.user_api->mbrtowc(__l->lc_ctype->cmapp,
+ __pwc, __s, __n, __ps);
+}
+
+int mbtowc_l(wchar_t *__pwc, const char *__pmb, size_t __max, locale_t __l) {
+ FIX_LOCALE(__l);
+ return __l->lc_ctype->cmapp->core.user_api->mbtowc(__l->lc_ctype->cmapp,
+ __pwc, __pmb, __max);
+}
+
+size_t mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __l) {
+ FIX_LOCALE(__l);
+ return __l->lc_ctype->cmapp->core.user_api->mbrlen(__l->lc_ctype->cmapp, __s,
+ __n, __ps);
+}
+
+struct lconv *localeconv_l(locale_t __l) {
+ FIX_LOCALE(__l);
+ return __l->core.user_api->localeconv(__l);
+}
+
+size_t mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len,
+ mbstate_t *__ps, locale_t __l) {
+ FIX_LOCALE(__l);
+ return __l->lc_ctype->cmapp->core.user_api->mbsrtowcs(__l->lc_ctype->cmapp,
+ __dest, __src, __len, __ps);
+}
+
+int wcscoll_l(const wchar_t *__s1, const wchar_t *__s2, locale_t __l) {
+ FIX_LOCALE(__l);
+ return __l->lc_collate->core.user_api->wcscoll(__l->lc_collate,
+ __s1, __s2);
+}
+
+int strcoll_l(const char *__s1, const char *__s2, locale_t __l) {
+ FIX_LOCALE(__l);
+ return __l->lc_collate->core.user_api->strcoll(__l->lc_collate,
+ __s1, __s2);
+}
+
+size_t strxfrm_l(char *__s1, const char *__s2, size_t __n, locale_t __l) {
+ FIX_LOCALE(__l);
+ return __l->lc_collate->core.user_api->strxfrm(__l->lc_collate,
+ __s1, __s2, __n);
+}
+size_t strftime_l(char *__s, size_t __size, const char *__fmt, const struct tm
+ *__tm, locale_t __l) {
+ FIX_LOCALE(__l);
+ return __l->lc_time->core.user_api->strftime(__l->lc_time,
+ __s, __size, __fmt, __tm);
+}
+
+size_t wcsxfrm_l(wchar_t *__ws1, const wchar_t *__ws2, size_t __n,
+ locale_t __l) {
+ FIX_LOCALE(__l);
+ return __l->lc_collate->core.user_api->wcsxfrm(__l->lc_collate,
+ __ws1, __ws2, __n);
+}
+
+#define LOCALE_ISCTYPE(ctype, m) \
+ int is##ctype##_l(int __c, locale_t __l) { \
+ if ((__c < 0) || (__c > 255)) return 0;\
+ FIX_LOCALE(__l);\
+ return __l->lc_ctype->mask[__c] & m;\
+ }\
+ int isw##ctype##_l(wchar_t __c, locale_t __l) { \
+ FIX_LOCALE(__l);\
+ return __l->lc_ctype->core.user_api->iswctype(__l->lc_ctype, __c, m);\
+ }
+
+LOCALE_ISCTYPE(alnum, _ISALNUM)
+LOCALE_ISCTYPE(alpha, _ISALPHA)
+LOCALE_ISCTYPE(blank, _ISALPHA)
+LOCALE_ISCTYPE(cntrl, _ISCNTRL)
+LOCALE_ISCTYPE(digit, _ISDIGIT)
+LOCALE_ISCTYPE(graph, _ISGRAPH)
+LOCALE_ISCTYPE(lower, _ISLOWER)
+LOCALE_ISCTYPE(print, _ISPRINT)
+LOCALE_ISCTYPE(punct, _ISPUNCT)
+LOCALE_ISCTYPE(space, _ISSPACE)
+LOCALE_ISCTYPE(upper, _ISUPPER)
+LOCALE_ISCTYPE(xdigit, _ISXDIGIT)
+
+int iswctype_l(wint_t __c, wctype_t __m, locale_t __l) {
+ FIX_LOCALE(__l);\
+ return __l->lc_ctype->core.user_api->iswctype(__l->lc_ctype, __c, __m);\
+}
+
+int toupper_l(int __c, locale_t __l) {
+ FIX_LOCALE(__l);
+ if ((__c < 0) || (__c > __l->lc_ctype->max_upper)) return __c;
+ return __l->lc_ctype->upper[__c];
+}
+int tolower_l(int __c, locale_t __l) {
+ FIX_LOCALE(__l);
+ if ((__c < 0) || (__c > __l->lc_ctype->max_lower)) return __c;
+ return __l->lc_ctype->lower[__c];
+}
+wint_t towupper_l(wint_t __c, locale_t __l) {
+ FIX_LOCALE(__l);
+ return __l->lc_ctype->core.user_api->towupper(__l->lc_ctype, __c);
+}
+wint_t towlower_l(wint_t __c, locale_t __l) {
+ FIX_LOCALE(__l);
+ return __l->lc_ctype->core.user_api->towlower(__l->lc_ctype, __c);
+}
+
+// FIXME: This disregards the locale, which is Very Wrong
+#define vsnprintf_l(__s, __n, __l, __format, __va) \
+ vsnprintf(__s, __n, __format, __va)
+
+int sprintf_l(char *__s, locale_t __l, const char *__format, ...) {
+ va_list __va;
+ va_start(__va, __format);
+ int __res = vsnprintf_l(__s, SIZE_MAX, __l, __format, __va);
+ va_end(__va);
+ return __res;
+}
+
+int snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...)
+{
+ va_list __va;
+ va_start(__va, __format);
+ int __res = vsnprintf_l(__s, __n , __l, __format, __va);
+ va_end(__va);
+ return __res;
+}
+
+int asprintf_l(char **__s, locale_t __l, const char *__format, ...) {
+ va_list __va;
+ va_start(__va, __format);
+ // FIXME:
+ int __res = vasprintf(__s, __format, __va);
+ va_end(__va);
+ return __res;
+}
+
+int sscanf_l(const char *__s, locale_t __l, const char *__format, ...) {
+ va_list __va;
+ va_start(__va, __format);
+ // FIXME:
+ int __res = vsscanf(__s, __format, __va);
+ va_end(__va);
+ return __res;
+}
+
+locale_t newlocale(int mask, const char *locale, locale_t base) {
+
+ if ((locale == NULL) || (locale[0] == '\0') ||
+ ((locale[0] == 'C') && (locale[1] == '\0')))
+ {
+ return __C_locale;
+ }
+
+ // Solaris locales are shared libraries that contain
+ char *path;
+#ifdef __LP64
+ asprintf(&path, "/usr/lib/locale/%1$s/amd64/%1$s.so.3", locale);
+#else
+ asprintf(&path, "/usr/lib/locale/%1$s/%1$s.so.3", locale);
+#endif
+ void *handle = dlopen(path, RTLD_LOCAL | RTLD_NOW);
+ free(path);
+ if (!handle)
+ return 0;
+ _LC_locale_t *(*init)() = dlsym(handle, "instantiate");
+ if (!init)
+ return 0;
+ _LC_locale_t *p = init();
+ if (!p)
+ return 0;
+
+ if (!base)
+ base = __C_locale;
+
+ locale_t ret = calloc(1, sizeof(struct _LC_locale_t));
+ memcpy(ret, p, sizeof (_LC_locale_t));
+ ret->lc_collate = (mask & LC_COLLATE_MASK) ? p->lc_collate : base->lc_collate;
+ ret->lc_ctype = (mask & LC_CTYPE_MASK) ? p->lc_ctype : base->lc_ctype;
+ ret->lc_messages = (mask & LC_MESSAGES_MASK) ? p->lc_messages : base->lc_messages;
+ ret->lc_monetary = (mask & LC_MONETARY_MASK) ? p->lc_monetary : base->lc_monetary;
+ ret->lc_time = (mask & LC_TIME_MASK) ? p->lc_time : base->lc_time;
+ return ret;
+}
+
+void freelocale(locale_t loc)
+{
+ if (loc != __C_locale)
+ free(loc);
+}
+
+__attribute__((constructor))
+static void setupCLocale(void) {
+ // The default initial locale is the C locale. This is a statically
+ // allocated locale inside libc. At program start, __lc_locale will point to
+ // this. We need to grab a copy because it's not a public symbol. If we had
+ // access to the source code for libc, then we'd just use it directly...
+ assert('C' == setlocale(LC_ALL, 0)[0]);
+ __C_locale = __lc_locale;
+}
+#endif
diff --git a/system/lib/libcxx/support/win32/locale_win32.cpp b/system/lib/libcxx/support/win32/locale_win32.cpp
new file mode 100644
index 00000000..02b5874e
--- /dev/null
+++ b/system/lib/libcxx/support/win32/locale_win32.cpp
@@ -0,0 +1,94 @@
+// -*- C++ -*-
+//===-------------------- support/win32/locale_win32.cpp ------------------===//
+//
+// 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 "support/win32/locale_win32.h"
+
+#include <stdarg.h> // va_start, va_end
+
+// FIXME: base currently unused. Needs manual work to construct the new locale
+locale_t newlocale( int mask, const char * locale, locale_t /*base*/ )
+{
+ return _create_locale( mask, locale );
+}
+locale_t uselocale( locale_t newloc )
+{
+ locale_t old_locale = _get_current_locale();
+ // uselocale sets the thread's locale by definition, so unconditionally use thread-local locale
+ _configthreadlocale( _ENABLE_PER_THREAD_LOCALE );
+ // uselocale sets all categories
+ setlocale( LC_ALL, newloc->locinfo->lc_category[LC_ALL].locale );
+ // uselocale returns the old locale_t
+ return old_locale;
+}
+lconv *localeconv_l( locale_t loc )
+{
+ __locale_raii __current( uselocale(loc), uselocale );
+ return localeconv();
+}
+size_t mbrlen_l( const char *__restrict__ s, size_t n,
+ mbstate_t *__restrict__ ps, locale_t loc )
+{
+ __locale_raii __current( uselocale(loc), uselocale );
+ return mbrlen( s, n, ps );
+}
+size_t mbsrtowcs_l( wchar_t *__restrict__ dst, const char **__restrict__ src,
+ size_t len, mbstate_t *__restrict__ ps, locale_t loc )
+{
+ __locale_raii __current( uselocale(loc), uselocale );
+ return mbsrtowcs( dst, src, len, ps );
+}
+size_t wcrtomb_l( char *__restrict__ s, wchar_t wc, mbstate_t *__restrict__ ps,
+ locale_t loc )
+{
+ __locale_raii __current( uselocale(loc), uselocale );
+ return wcrtomb( s, wc, ps );
+}
+size_t mbrtowc_l( wchar_t *__restrict__ pwc, const char *__restrict__ s,
+ size_t n, mbstate_t *__restrict__ ps, locale_t loc )
+{
+ __locale_raii __current( uselocale(loc), uselocale );
+ return mbrtowc( pwc, s, n, ps );
+}
+size_t mbsnrtowcs_l( wchar_t *__restrict__ dst, const char **__restrict__ src,
+ size_t nms, size_t len, mbstate_t *__restrict__ ps, locale_t loc )
+{
+ __locale_raii __current( uselocale(loc), uselocale );
+ return mbsnrtowcs( dst, src, nms, len, ps );
+}
+size_t wcsnrtombs_l( char *__restrict__ dst, const wchar_t **__restrict__ src,
+ size_t nwc, size_t len, mbstate_t *__restrict__ ps, locale_t loc )
+{
+ __locale_raii __current( uselocale(loc), uselocale );
+ return wcsnrtombs( dst, src, nwc, len, ps );
+}
+wint_t btowc_l( int c, locale_t loc )
+{
+ __locale_raii __current( uselocale(loc), uselocale );
+ return btowc( c );
+}
+int wctob_l( wint_t c, locale_t loc )
+{
+ __locale_raii __current( uselocale(loc), uselocale );
+ return wctob( c );
+}
+
+int asprintf_l( char **ret, locale_t loc, const char *format, ... )
+{
+ va_list ap;
+ va_start( ap, format );
+ int result = vasprintf_l( ret, loc, format, ap );
+ va_end(ap);
+ return result;
+}
+int vasprintf_l( char **ret, locale_t loc, const char *format, va_list ap )
+{
+ __locale_raii __current( uselocale(loc), uselocale );
+ return vasprintf( ret, format, ap );
+}
diff --git a/system/lib/libcxx/support/win32/support.cpp b/system/lib/libcxx/support/win32/support.cpp
new file mode 100644
index 00000000..9e85077a
--- /dev/null
+++ b/system/lib/libcxx/support/win32/support.cpp
@@ -0,0 +1,70 @@
+// -*- C++ -*-
+//===----------------------- support/win32/support.h ----------------------===//
+//
+// 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 <support/win32/support.h>
+#include <stdarg.h> // va_start, va_end
+#include <stddef.h> // size_t
+#include <stdlib.h> // malloc
+#include <stdio.h> // vsprintf, vsnprintf
+#include <string.h> // strcpy, wcsncpy
+
+int asprintf(char **sptr, const char *__restrict fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ int result = vasprintf(sptr, fmt, ap);
+ va_end(ap);
+ return result;
+}
+int vasprintf( char **sptr, const char *__restrict fmt, va_list ap )
+{
+ *sptr = NULL;
+ int count = vsnprintf( *sptr, 0, fmt, ap );
+ if( (count >= 0) && ((*sptr = (char*)malloc(count+1)) != NULL) )
+ {
+ vsprintf( *sptr, fmt, ap );
+ sptr[count] = '\0';
+ }
+
+ return count;
+}
+
+// FIXME: use wcrtomb and avoid copy
+// use mbsrtowcs which is available, first copy first nwc elements of src
+size_t mbsnrtowcs( wchar_t *__restrict dst, const char **__restrict src,
+ size_t nmc, size_t len, mbstate_t *__restrict ps )
+{
+ char* local_src = new char[nmc+1];
+ char* nmcsrc = local_src;
+ strncpy( nmcsrc, *src, nmc );
+ nmcsrc[nmc] = '\0';
+ const size_t result = mbsrtowcs( dst, const_cast<const char **>(&nmcsrc), len, ps );
+ // propagate error
+ if( nmcsrc == NULL )
+ *src = NULL;
+ delete[] local_src;
+ return result;
+}
+// FIXME: use wcrtomb and avoid copy
+// use wcsrtombs which is available, first copy first nwc elements of src
+size_t wcsnrtombs( char *__restrict dst, const wchar_t **__restrict src,
+ size_t nwc, size_t len, mbstate_t *__restrict ps )
+{
+ wchar_t* local_src = new wchar_t[nwc];
+ wchar_t* nwcsrc = local_src;
+ wcsncpy(nwcsrc, *src, nwc);
+ nwcsrc[nwc] = '\0';
+ const size_t result = wcsrtombs( dst, const_cast<const wchar_t **>(&nwcsrc), len, ps );
+ // propogate error
+ if( nwcsrc == NULL )
+ *src = NULL;
+ delete[] nwcsrc;
+ return result;
+}