From owner-p4-projects@FreeBSD.ORG Sun Aug 3 21:41:35 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 3732110656C4; Sun, 3 Aug 2008 21:41:35 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id D87F910656C0 for ; Sun, 3 Aug 2008 21:41:34 +0000 (UTC) (envelope-from konrad@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id C44468FC15 for ; Sun, 3 Aug 2008 21:41:34 +0000 (UTC) (envelope-from konrad@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.2/8.14.2) with ESMTP id m73LfYJS000914 for ; Sun, 3 Aug 2008 21:41:34 GMT (envelope-from konrad@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.2/8.14.1/Submit) id m73LfYoH000912 for perforce@freebsd.org; Sun, 3 Aug 2008 21:41:34 GMT (envelope-from konrad@FreeBSD.org) Date: Sun, 3 Aug 2008 21:41:34 GMT Message-Id: <200808032141.m73LfYoH000912@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to konrad@FreeBSD.org using -f From: Konrad Jankowski To: Perforce Change Reviews Cc: Subject: PERFORCE change 146565 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 03 Aug 2008 21:41:35 -0000 http://perforce.freebsd.org/chv.cgi?CH=146565 Change 146565 by konrad@vspredator on 2008/08/03 21:41:32 Finally, only the relevant deltas. Affected files ... .. //depot/projects/soc2008/konrad_collation/libc/locale/collate.h#6 edit .. //depot/projects/soc2008/konrad_collation/libc/locale/collcmp.c#6 edit .. //depot/projects/soc2008/konrad_collation/libc/locale/setlocale.c#6 edit .. //depot/projects/soc2008/konrad_collation/libc/string/strcoll.c#6 edit .. //depot/projects/soc2008/konrad_collation/libc/string/strxfrm.c#6 edit .. //depot/projects/soc2008/konrad_collation/libc/string/wcscoll.c#6 edit .. //depot/projects/soc2008/konrad_collation/libc/string/wcsxfrm.c#6 edit Differences ... ==== //depot/projects/soc2008/konrad_collation/libc/locale/collate.h#6 (text+ko) ==== @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/lib/libc/locale/collate.h,v 1.15 2005/02/27 20:31:13 ru Exp $ + * $FreeBSD: src/lib/libc/locale/collate.h,v 1.14 2002/08/30 20:26:02 ache Exp $ */ #ifndef _COLLATE_H_ @@ -33,34 +33,91 @@ #include #include #include +#include "setlocale.h" /* for ENCODING_LEN */ + +#undef COLL_WEIGHTS_MAX +#define COLL_WEIGHTS_MAX 4 #define STR_LEN 10 #define TABLE_SIZE 100 -#define COLLATE_VERSION "1.0\n" -#define COLLATE_VERSION1_2 "1.2\n" +#define COLLATE_VERSION "1.0\n" +#define COLLATE_VERSION1_1 "1.1\n" +#define COLLATE_VERSION1_1A "1.1A\n" +#define COLLATE_VERSION1_2 "1.2\n" +#define COLLATE_VERSION1_3 "1.3\n" +/* see discussion in string/FreeBSD/strxfrm for this value */ +#define COLLATE_MAX_PRIORITY ((1 << 24) - 1) + +#define DIRECTIVE_UNDEF 0x00 +#define DIRECTIVE_FORWARD 0x01 +#define DIRECTIVE_BACKWARD 0x02 +#define DIRECTIVE_POSITION 0x04 + +#define DIRECTIVE_DIRECTION_MASK (DIRECTIVE_FORWARD | DIRECTIVE_BACKWARD) + +#define COLLATE_SUBST_DUP 0x0001 + +#define IGNORE_EQUIV_CLASS 1 + +struct __collate_st_info { + __uint8_t directive[COLL_WEIGHTS_MAX]; + __uint8_t flags; +#if _BYTE_ORDER == _LITTLE_ENDIAN + unsigned int directive_count:4; + unsigned int chain_max_len:4; +#else + unsigned int chain_max_len:4; + unsigned int directive_count:4; +#endif + __int32_t undef_pri[COLL_WEIGHTS_MAX]; + __int32_t subst_count[COLL_WEIGHTS_MAX]; + __int32_t chain_count; + __int32_t large_pri_count; +}; struct __collate_st_char_pri { - int prim, sec; + __int32_t pri[COLL_WEIGHTS_MAX]; }; struct __collate_st_chain_pri { - u_char str[STR_LEN]; - int prim, sec; + wchar_t str[STR_LEN]; + __int32_t pri[COLL_WEIGHTS_MAX]; +}; +struct __collate_st_large_char_pri { + __int32_t val; + struct __collate_st_char_pri pri; +}; +struct __collate_st_subst { + __int32_t val; + wchar_t str[STR_LEN]; +}; + +struct __locale_st_collate { + char __encoding[ENCODING_LEN + 1]; + struct __collate_st_info __info; + struct __collate_st_subst *__substitute_table[COLL_WEIGHTS_MAX]; + struct __collate_st_chain_pri *__chain_pri_table; + struct __collate_st_large_char_pri *__large_char_pri_table; + struct __collate_st_char_pri __char_pri_table[UCHAR_MAX + 1]; }; extern int __collate_load_error; extern int __collate_substitute_nontrivial; -#define __collate_substitute_table (*__collate_substitute_table_ptr) -extern u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN]; -#define __collate_char_pri_table (*__collate_char_pri_table_ptr) -extern struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1]; -extern struct __collate_st_chain_pri *__collate_chain_pri_table; +extern struct __locale_st_collate *__collate_data; __BEGIN_DECLS -u_char *__collate_strdup(u_char *); -u_char *__collate_substitute(const u_char *); +wchar_t *__collate_mbstowcs(const char *); +wchar_t *__collate_wcsdup(const wchar_t *); +wchar_t *__collate_substitute(const wchar_t *, int); int __collate_load_tables(const char *); -void __collate_lookup(const u_char *, int *, int *, int *); -int __collate_range_cmp(int, int); +void __collate_lookup(const wchar_t *, int *, int *, int *); +void __collate_lookup_which(const wchar_t *, int *, int *, int); +void __collate_xfrm(const wchar_t *, wchar_t **); +int __collate_range_cmp(wchar_t, wchar_t); +size_t __collate_collating_symbol(wchar_t *, size_t, const char *, size_t, + mbstate_t *); +int __collate_equiv_class(const char *, size_t, mbstate_t *); +size_t __collate_equiv_match(int, wchar_t *, size_t, wchar_t, const char *, + size_t, mbstate_t *, size_t *); #ifdef COLLATE_DEBUG void __collate_print_tables(void); #endif ==== //depot/projects/soc2008/konrad_collation/libc/locale/collcmp.c#6 (text+ko) ==== @@ -28,17 +28,18 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/collcmp.c,v 1.18 2005/02/27 14:54:23 phantom Exp $"); #include +#include #include "collate.h" /* * Compare two characters using collate */ -int __collate_range_cmp(int c1, int c2) +int __collate_range_cmp(wchar_t c1, wchar_t c2) { - static char s1[2], s2[2]; + static wchar_t s1[2], s2[2]; s1[0] = c1; s2[0] = c2; - return (strcoll(s1, s2)); + return (wcscoll(s1, s2)); } ==== //depot/projects/soc2008/konrad_collation/libc/locale/setlocale.c#6 (text+ko) ==== @@ -46,6 +46,7 @@ #include #include #include +#include #include "collate.h" #include "lmonetary.h" /* for __monetary_load_locale() */ #include "lnumeric.h" /* for __numeric_load_locale() */ @@ -105,6 +106,10 @@ int i, j, len, saverr; const char *env, *r; +#ifdef LOCALE_DEBUG + fprintf(stderr, "setlocale: %s: %s\n", categories[category], + locale ? locale : "NULL"); +#endif if (category < LC_ALL || category >= _LC_LAST) { errno = EINVAL; return (NULL); @@ -191,11 +196,16 @@ for (i = 1; i < _LC_LAST; ++i) { (void)strcpy(saved_categories[i], current_categories[i]); - if (loadlocale(i) == NULL) { + if ((r = loadlocale(i)) == NULL) { saverr = errno; for (j = 1; j < i; j++) { (void)strcpy(new_categories[j], saved_categories[j]); +#ifdef LOCALE_DEBUG + fprintf(stderr, "setlocale: resetting " + "locale to %s\n", + saved_categories[j]); +#endif if (loadlocale(j) == NULL) { (void)strcpy(new_categories[j], "C"); (void)loadlocale(j); @@ -204,6 +214,9 @@ errno = saverr; return (NULL); } +#ifdef LOCALE_DEBUG + fprintf(stderr, "setlocale: loadlocale returned %s\n", r); +#endif } return (currentlocale()); } @@ -236,6 +249,10 @@ int (*func)(const char *); int saved_errno; +#ifdef LOCALE_DEBUG + fprintf(stderr, "loadlocale: %s->%s (was %s)\n", + categories[category], new, old); +#endif if ((new[0] == '.' && (new[1] == '\0' || (new[1] == '.' && new[2] == '\0'))) || strchr(new, '/') != NULL) { @@ -280,6 +297,9 @@ (void)strcpy(old, new); return (old); } +#ifdef LOCALE_DEBUG + fprintf(stderr, "loadlocale: returning NULL\n"); +#endif return (NULL); } @@ -327,6 +347,9 @@ } else _PathLocale = _PATH_LOCALE; } +#ifdef LOCALE_DEBUG + fprintf(stderr, "__detect_path_locale: %s\n", _PathLocale); +#endif return (0); } ==== //depot/projects/soc2008/konrad_collation/libc/string/strcoll.c#6 (text+ko) ==== @@ -30,57 +30,31 @@ #include #include +#include +#include #include "collate.h" int -strcoll(s, s2) - const char *s, *s2; +strcoll(const char *s, const char *s2) { - int len, len2, prim, prim2, sec, sec2, ret, ret2; - const char *t, *t2; - char *tt, *tt2; + int ret; + const wchar_t *t = NULL, *t2 = NULL; + int sverrno; - if (__collate_load_error) + if (__collate_load_error || (t = __collate_mbstowcs(s)) == NULL || + (t2 = __collate_mbstowcs(s2)) == NULL) { + sverrno = errno; + free((void *)t); + free((void *)t2); + errno = sverrno; return strcmp(s, s2); + } - len = len2 = 1; - ret = ret2 = 0; - if (__collate_substitute_nontrivial) { - t = tt = __collate_substitute(s); - t2 = tt2 = __collate_substitute(s2); - } else { - tt = tt2 = NULL; - t = s; - t2 = s2; - } - while(*t && *t2) { - prim = prim2 = 0; - while(*t && !prim) { - __collate_lookup(t, &len, &prim, &sec); - t += len; - } - while(*t2 && !prim2) { - __collate_lookup(t2, &len2, &prim2, &sec2); - t2 += len2; - } - if(!prim || !prim2) - break; - if(prim != prim2) { - ret = prim - prim2; - goto end; - } - if(!ret2) - ret2 = sec - sec2; - } - if(!*t && *t2) - ret = -(int)((u_char)*t2); - else if(*t && !*t2) - ret = (u_char)*t; - else if(!*t && !*t2) - ret = ret2; - end: - free(tt); - free(tt2); + ret = wcscoll(t, t2); + sverrno = errno; + free((void *)t); + free((void *)t2); + errno = sverrno; return ret; } ==== //depot/projects/soc2008/konrad_collation/libc/string/strxfrm.c#6 (text+ko) ==== @@ -30,22 +30,53 @@ #include #include +#include +#include #include "collate.h" +/* + * In the non-POSIX case, we transform each character into a string of + * characters representing the character's priority. Since char is usually + * signed, we are limited by 7 bits per byte. To avoid zero, we need to add + * XFRM_OFFSET, so we can't use a full 7 bits. For simplicity, we choose 6 + * bits per byte. We choose 4 bytes per character as a good compromise + * between maximum coverage and minimum size. This gives 24 bits, or 16M + * priorities. So we choose COLLATE_MAX_PRIORITY to be (2^24 - 1). This + * this can be increased if more is needed. + */ + +#define XFRM_BYTES 4 +#define XFRM_OFFSET ('0') /* make all printable characters */ +#define XFRM_SHIFT 6 +#define XFRM_MASK ((1 << XFRM_SHIFT) - 1) + +static void +xfrm(unsigned char *p, int pri) +{ + + p[3] = (pri & XFRM_MASK) + XFRM_OFFSET; + pri >>= XFRM_SHIFT; + p[2] = (pri & XFRM_MASK) + XFRM_OFFSET; + pri >>= XFRM_SHIFT; + p[1] = (pri & XFRM_MASK) + XFRM_OFFSET; + pri >>= XFRM_SHIFT; + p[0] = (pri & XFRM_MASK) + XFRM_OFFSET; +} + size_t strxfrm(char * __restrict dest, const char * __restrict src, size_t len) { - int prim, sec, l; size_t slen; - char *s, *ss; + wchar_t *wcs, *xf[2]; + int sverrno; - if (!*src) { + if (!*src && dest) { if (len > 0) *dest = '\0'; return 0; } - if (__collate_load_error) { + if (__collate_load_error || (wcs = __collate_mbstowcs(src)) == NULL) { slen = strlen(src); if (len > 0) { if (slen < len) @@ -58,26 +89,57 @@ return slen; } - slen = 0; - prim = sec = 0; - ss = s = __collate_substitute(src); - while (*s) { - while (*s && !prim) { - __collate_lookup(s, &l, &prim, &sec); - s += l; + __collate_xfrm(wcs, xf); + + slen = wcslen(xf[0]) * XFRM_BYTES; + if (xf[1]) + slen += (wcslen(xf[1]) + 1) * XFRM_BYTES; + if (len > 0) { + wchar_t *w = xf[0]; + int b = 0; + unsigned char buf[XFRM_BYTES]; + unsigned char *bp; + while (len > 1) { + if (!b) { + if (!*w) + break; + xfrm(bp = buf, *w++); + b = XFRM_BYTES; + } + *dest++ = *(char *)bp++; + b--; + len--; } - if (prim) { - if (len > 1) { - *dest++ = (char)prim; + if ((w = xf[1]) != NULL) { + xfrm(bp = buf, 0); + b = XFRM_BYTES; + while (len > 1) { + if (!b) + break; + *dest++ = *(char *)bp++; + b--; + len--; + } + b = 0; + while (len > 1) { + if (!b) { + if (!*w) + break; + xfrm(bp = buf, *w++); + b = XFRM_BYTES; + } + *dest++ = *(char *)bp++; + b--; len--; } - slen++; - prim = 0; } - } - free(ss); - if (len > 0) - *dest = '\0'; + *dest = 0; + } + sverrno = errno; + free(wcs); + free(xf[0]); + free(xf[1]); + errno = sverrno; return slen; } ==== //depot/projects/soc2008/konrad_collation/libc/string/wcscoll.c#6 (text+ko) ==== @@ -27,72 +27,220 @@ #include __FBSDID("$FreeBSD: src/lib/libc/string/wcscoll.c,v 1.3 2004/04/07 09:47:56 tjr Exp $"); + #include #include #include #include #include "collate.h" -static char *__mbsdup(const wchar_t *); +#define NOTFORWARD (DIRECTIVE_BACKWARD | DIRECTIVE_POSITION) -/* - * Placeholder implementation of wcscoll(). Attempts to use the single-byte - * collation ordering where possible, and falls back on wcscmp() in locales - * with extended character sets. - */ int wcscoll(const wchar_t *ws1, const wchar_t *ws2) { - char *mbs1, *mbs2; - int diff, sverrno; + int sverrno; + int len, len2, prim, prim2, sec, sec2, ret, ret2; + const wchar_t *t, *t2; + wchar_t *tt = NULL, *tt2 = NULL; + wchar_t *tr = NULL, *tr2 = NULL; + struct __collate_st_info *info; - if (__collate_load_error || MB_CUR_MAX > 1) + if (__collate_load_error) /* - * Locale has no special collating order, could not be - * loaded, or has an extended character set; do a fast binary - * comparison. + * Locale has no special collating order or could not be + * loaded, do a fast binary comparison. */ return (wcscmp(ws1, ws2)); - if ((mbs1 = __mbsdup(ws1)) == NULL || (mbs2 = __mbsdup(ws2)) == NULL) { - /* - * Out of memory or illegal wide chars; fall back to wcscmp() - * but leave errno indicating the error. Callers that don't - * check for error will get a reasonable but often slightly - * incorrect result. - */ - sverrno = errno; - free(mbs1); - errno = sverrno; - return (wcscmp(ws1, ws2)); + info = &__collate_data->__info; + len = len2 = 1; + ret = ret2 = 0; + + if ((info->directive[0] & NOTFORWARD) || + (info->directive[1] & NOTFORWARD) || + (!(info->flags && COLLATE_SUBST_DUP) && + (info->subst_count[0] > 0 || info->subst_count[1] > 0))) { + int direc, pass; + for(pass = 0; pass < info->directive_count; pass++) { + direc = info->directive[pass]; + if (pass == 0 || !(info->flags & COLLATE_SUBST_DUP)) { + free(tt); + tt = __collate_substitute(ws1, pass); + free(tt2); + tt2 = tt ? __collate_substitute(ws2, pass) : + NULL; + } + if (direc & DIRECTIVE_BACKWARD) { + wchar_t *bp, *fp, c; + tr = __collate_wcsdup(tt ? tt : ws1); + bp = tr; + fp = tr + wcslen(tr) - 1; + while(bp < fp) { + c = *bp; + *bp++ = *fp; + *fp-- = c; + } + tr2 = __collate_wcsdup(tt2 ? tt2 : ws2); + bp = tr2; + fp = tr2 + wcslen(tr2) - 1; + while(bp < fp) { + c = *bp; + *bp++ = *fp; + *fp-- = c; + } + t = (const wchar_t *)tr; + t2 = (const wchar_t *)tr2; + } else if (tt) { + t = (const wchar_t *)tt; + t2 = (const wchar_t *)tt2; + } else { + t = (const wchar_t *)ws1; + t2 = (const wchar_t *)ws2; + } + if(direc & DIRECTIVE_POSITION) { + while(*t && *t2) { + prim = prim2 = 0; + __collate_lookup_which(t, &len, + &prim, pass); + if (prim <= 0) { + if (prim < 0) { + errno = EINVAL; + ret = -1; + goto end; + } + prim = COLLATE_MAX_PRIORITY; + } + __collate_lookup_which(t2, &len2, + &prim2, pass); + if (prim2 <= 0) { + if (prim2 < 0) { + errno = EINVAL; + ret = -1; + goto end; + } + prim2 = COLLATE_MAX_PRIORITY; + } + if(prim != prim2) { + ret = prim - prim2; + goto end; + } + t += len; + t2 += len2; + } + } else { + while(*t && *t2) { + prim = prim2 = 0; + while(*t) { + __collate_lookup_which(t, &len, + &prim, pass); + if(prim > 0) + break; + if (prim < 0) { + errno = EINVAL; + ret = -1; + goto end; + } + t += len; + } + while(*t2) { + __collate_lookup_which(t2, + &len2, &prim2, pass); + if(prim2 > 0) + break; + if (prim2 < 0) { + errno = EINVAL; + ret = -1; + goto end; + } + t2 += len2; + } + if(!prim || !prim2) + break; + if(prim != prim2) { + ret = prim - prim2; + goto end; + } + t += len; + t2 += len2; + } + } + if(!*t) { + if(*t2) { + ret = -(int)*t2; + goto end; + } + } else { + ret = *t; + goto end; + } + } + ret = 0; + goto end; } - diff = strcoll(mbs1, mbs2); + /* + * Optimized common case: order_start forward;forward and duplicate + * (or no) substitute tables. + */ + tt = __collate_substitute(ws1, 0); + if (tt == NULL) { + tt2 = NULL; + t = (const wchar_t *)ws1; + t2 = (const wchar_t *)ws2; + } else { + tt2 = __collate_substitute(ws2, 0); + t = (const wchar_t *)tt; + t2 = (const wchar_t *)tt2; + } + while(*t && *t2) { + prim = prim2 = 0; + while(*t) { + __collate_lookup(t, &len, &prim, &sec); + if (prim > 0) + break; + if (prim < 0) { + errno = EINVAL; + ret = -1; + goto end; + } + t += len; + } + while(*t2) { + __collate_lookup(t2, &len2, &prim2, &sec2); + if (prim2 > 0) + break; + if (prim2 < 0) { + errno = EINVAL; + ret = -1; + goto end; + } + t2 += len2; + } + if(!prim || !prim2) + break; + if(prim != prim2) { + ret = prim - prim2; + goto end; + } + if(!ret2) + ret2 = sec - sec2; + t += len; + t2 += len2; + } + if(!*t && *t2) + ret = -(int)*t2; + else if(*t && !*t2) + ret = *t; + else if(!*t && !*t2) + ret = ret2; + end: sverrno = errno; - free(mbs1); - free(mbs2); + free(tt); + free(tt2); + free(tr); + free(tr2); errno = sverrno; - return (diff); -} - -static char * -__mbsdup(const wchar_t *ws) -{ - static const mbstate_t initial; - mbstate_t st; - const wchar_t *wcp; - size_t len; - char *mbs; - - wcp = ws; - st = initial; - if ((len = wcsrtombs(NULL, &wcp, 0, &st)) == (size_t)-1) - return (NULL); - if ((mbs = malloc(len + 1)) == NULL) - return (NULL); - st = initial; - wcsrtombs(mbs, &ws, len + 1, &st); - - return (mbs); + return ret; } ==== //depot/projects/soc2008/konrad_collation/libc/string/wcsxfrm.c#6 (text+ko) ==== @@ -34,20 +34,17 @@ #include #include #include +#include #include "collate.h" -static char *__mbsdup(const wchar_t *); +#define WCS_XFRM_OFFSET 1 -/* - * Placeholder wcsxfrm() implementation. See wcscoll.c for a description of - * the logic used. - */ size_t wcsxfrm(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len) { - int prim, sec, l; size_t slen; - char *mbsrc, *s, *ss; + wchar_t *xf[2]; + int sverrno; if (*src == L'\0') { if (len != 0) @@ -55,7 +52,7 @@ return (0); } - if (__collate_load_error || MB_CUR_MAX > 1) { + if (__collate_load_error) { slen = wcslen(src); if (len > 0) { if (slen < len) @@ -68,49 +65,35 @@ return (slen); } - mbsrc = __mbsdup(src); - slen = 0; - prim = sec = 0; - ss = s = __collate_substitute(mbsrc); - while (*s != '\0') { - while (*s != '\0' && prim == 0) { - __collate_lookup(s, &l, &prim, &sec); - s += l; + __collate_xfrm(src, xf); + + slen = wcslen(xf[0]); + if (xf[1]) + slen += wcslen(xf[1]) + 1; + if (len > 0) { + wchar_t *w = xf[0]; + while (len > 1) { + if (!*w) + break; + *dest++ = *w++ + WCS_XFRM_OFFSET; + len--; } - if (prim != 0) { - if (len > 1) { - *dest++ = (wchar_t)prim; + if ((w = xf[1]) != NULL) { + if (len > 1) + *dest++ = WCS_XFRM_OFFSET; + while (len > 1) { + if (!*w) + break; + *dest++ = *w++ + WCS_XFRM_OFFSET; len--; } - slen++; - prim = 0; } - } - free(ss); - free(mbsrc); - if (len != 0) - *dest = L'\0'; - + *dest = 0; + } + sverrno = errno; + free(xf[0]); + free(xf[1]); + errno = sverrno; + return (slen); } - -static char * -__mbsdup(const wchar_t *ws) -{ - static const mbstate_t initial; - mbstate_t st; - const wchar_t *wcp; - size_t len; - char *mbs; - - wcp = ws; - st = initial; - if ((len = wcsrtombs(NULL, &wcp, 0, &st)) == (size_t)-1) - return (NULL); - if ((mbs = malloc(len + 1)) == NULL) - return (NULL); - st = initial; - wcsrtombs(mbs, &ws, len + 1, &st); - - return (mbs); -}