https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=c1b7d9d93dc8e88693162c0d984a114371919fdd

commit c1b7d9d93dc8e88693162c0d984a114371919fdd
Author: Corinna Vinschen <[email protected]>
Date:   Sun Jul 24 20:00:34 2016 +0200

    Implement per-locale string functions
    
    strcasecmp_l, strcoll_l, strncasecmp_l, strxfrm_l,
    wcscasecmp_l, wcscoll_l, wcstrncasecmp_l, wcstrxfrm_l,
    strftime_l.
    
    Add missing CHEWOUT_FILES from previous patch.
    
    TODO: strfmon_l.
    
    Signed-off by: Corinna Vinschen <[email protected]>

Diff:
---
 newlib/libc/ctype/Makefile.am      |  35 +++++++++-
 newlib/libc/ctype/Makefile.in      |  35 +++++++++-
 newlib/libc/include/string.h       |  13 ++++
 newlib/libc/include/wchar.h        |  13 ++++
 newlib/libc/locale/setlocale.h     |  36 +++++++---
 newlib/libc/string/Makefile.am     |  14 +++-
 newlib/libc/string/Makefile.in     | 132 ++++++++++++++++++++++++++++++-------
 newlib/libc/string/strcasecmp.c    |   6 +-
 newlib/libc/string/strcasecmp_l.c  |  54 +++++++++++++++
 newlib/libc/string/strcoll.c       |   3 +
 newlib/libc/string/strcoll_l.c     |  46 +++++++++++++
 newlib/libc/string/strncasecmp.c   |   6 +-
 newlib/libc/string/strncasecmp_l.c |  56 ++++++++++++++++
 newlib/libc/string/strxfrm.c       |   3 +-
 newlib/libc/string/strxfrm_l.c     |  71 ++++++++++++++++++++
 newlib/libc/string/wcscasecmp.c    |  12 ++--
 newlib/libc/string/wcscasecmp_l.c  |  54 +++++++++++++++
 newlib/libc/string/wcscoll.c       |   4 +-
 newlib/libc/string/wcscoll_l.c     |  43 ++++++++++++
 newlib/libc/string/wcsncasecmp.c   |  17 ++---
 newlib/libc/string/wcsncasecmp_l.c |  56 ++++++++++++++++
 newlib/libc/string/wcsxfrm.c       |   4 +-
 newlib/libc/string/wcsxfrm_l.c     |  47 +++++++++++++
 newlib/libc/time/strftime.c        | 100 +++++++++++++++++-----------
 winsup/cygwin/common.din           |   9 +++
 winsup/cygwin/nlsfuncs.cc          |  48 +++++++++++---
 winsup/doc/posix.xml               |  17 ++---
 27 files changed, 816 insertions(+), 118 deletions(-)

diff --git a/newlib/libc/ctype/Makefile.am b/newlib/libc/ctype/Makefile.am
index 0cda2a3..00b91bf 100644
--- a/newlib/libc/ctype/Makefile.am
+++ b/newlib/libc/ctype/Makefile.am
@@ -98,38 +98,71 @@ include $(srcdir)/../../Makefile.shared
 
 CHEWOUT_FILES= \
        isalnum.def     \
+       isalnum_l.def   \
        isalpha.def     \
+       isalpha_l.def   \
        isascii.def     \
+       isascii_l.def   \
        isblank.def     \
+       isblank_l.def   \
        iscntrl.def     \
+       iscntrl_l.def   \
        isdigit.def     \
+       isdigit_l.def   \
        islower.def     \
+       islower_l.def   \
        isprint.def     \
+       isprint_l.def   \
        ispunct.def     \
+       ispunct_l.def   \
        isspace.def     \
+       isspace_l.def   \
        isupper.def     \
+       isupper_l.def   \
        iswalnum.def    \
+       iswalnum_l.def  \
        iswalpha.def    \
+       iswalpha_l.def  \
        iswblank.def    \
+       iswblank_l.def  \
        iswcntrl.def    \
+       iswcntrl_l.def  \
        iswctype.def    \
+       iswctype_l.def  \
        iswdigit.def    \
+       iswdigit_l.def  \
        iswgraph.def    \
+       iswgraph_l.def  \
        iswlower.def    \
+       iswlower_l.def  \
        iswprint.def    \
+       iswprint_l.def  \
        iswpunct.def    \
+       iswpunct_l.def  \
        iswspace.def    \
+       iswspace_l.def  \
        iswupper.def    \
+       iswupper_l.def  \
        iswxdigit.def   \
+       iswxdigit_l.def \
        isxdigit.def    \
+       isxdigit_l.def  \
        toascii.def     \
+       toascii_l.def   \
        tolower.def     \
+       tolower_l.def   \
        toupper.def     \
+       toupper_l.def   \
        towctrans.def   \
+       towctrans_l.def \
        towlower.def    \
+       towlower_l.def  \
        towupper.def    \
+       towupper_l.def  \
        wctrans.def     \
-       wctype.def      
+       wctrans_l.def   \
+       wctype.def      \
+       wctype_l.def
 
 CHAPTERS = ctype.tex
 
diff --git a/newlib/libc/ctype/Makefile.in b/newlib/libc/ctype/Makefile.in
index d29495a..02f7071 100644
--- a/newlib/libc/ctype/Makefile.in
+++ b/newlib/libc/ctype/Makefile.in
@@ -426,38 +426,71 @@ DOCBOOK_CHAPTERS = $(CHAPTERS:.tex=.xml)
 CLEANFILES = $(CHEWOUT_FILES) $(CHEWOUT_FILES:.def=.ref) $(DOCBOOK_OUT_FILES)
 CHEWOUT_FILES = \
        isalnum.def     \
+       isalnum_l.def   \
        isalpha.def     \
+       isalpha_l.def   \
        isascii.def     \
+       isascii_l.def   \
        isblank.def     \
+       isblank_l.def   \
        iscntrl.def     \
+       iscntrl_l.def   \
        isdigit.def     \
+       isdigit_l.def   \
        islower.def     \
+       islower_l.def   \
        isprint.def     \
+       isprint_l.def   \
        ispunct.def     \
+       ispunct_l.def   \
        isspace.def     \
+       isspace_l.def   \
        isupper.def     \
+       isupper_l.def   \
        iswalnum.def    \
+       iswalnum_l.def  \
        iswalpha.def    \
+       iswalpha_l.def  \
        iswblank.def    \
+       iswblank_l.def  \
        iswcntrl.def    \
+       iswcntrl_l.def  \
        iswctype.def    \
+       iswctype_l.def  \
        iswdigit.def    \
+       iswdigit_l.def  \
        iswgraph.def    \
+       iswgraph_l.def  \
        iswlower.def    \
+       iswlower_l.def  \
        iswprint.def    \
+       iswprint_l.def  \
        iswpunct.def    \
+       iswpunct_l.def  \
        iswspace.def    \
+       iswspace_l.def  \
        iswupper.def    \
+       iswupper_l.def  \
        iswxdigit.def   \
+       iswxdigit_l.def \
        isxdigit.def    \
+       isxdigit_l.def  \
        toascii.def     \
+       toascii_l.def   \
        tolower.def     \
+       tolower_l.def   \
        toupper.def     \
+       toupper_l.def   \
        towctrans.def   \
+       towctrans_l.def \
        towlower.def    \
+       towlower_l.def  \
        towupper.def    \
+       towupper_l.def  \
        wctrans.def     \
-       wctype.def      
+       wctrans_l.def   \
+       wctype.def      \
+       wctype_l.def
 
 CHAPTERS = ctype.tex
 all: all-am
diff --git a/newlib/libc/include/string.h b/newlib/libc/include/string.h
index 56c7fc2..549d511 100644
--- a/newlib/libc/include/string.h
+++ b/newlib/libc/include/string.h
@@ -16,6 +16,11 @@
 #define __need_NULL
 #include <stddef.h>
 
+#if __POSIX_VISIBLE >= 200809 || defined (_COMPILING_NEWLIB)
+struct __locale_t;
+typedef struct __locale_t *locale_t;
+#endif
+
 _BEGIN_STD_C
 
 _PTR    _EXFUN(memchr,(const _PTR, int, size_t));
@@ -43,6 +48,14 @@ char         *_EXFUN(strtok,(char *__restrict, const char 
*__restrict));
 #endif
 size_t  _EXFUN(strxfrm,(char *__restrict, const char *__restrict, size_t));
 
+#if __POSIX_VISIBLE >= 200809
+extern int strcasecmp_l (const char *, const char *, locale_t);
+extern int strncasecmp_l (const char *, const char *, size_t, locale_t);
+extern int strcoll_l (const char *, const char *, locale_t);
+extern size_t strxfrm_l (char *__restrict, const char *__restrict, size_t,
+                        locale_t);
+#endif
+
 #if __MISC_VISIBLE || __POSIX_VISIBLE
 char   *_EXFUN(strtok_r,(char *__restrict, const char *__restrict, char 
**__restrict));
 #endif
diff --git a/newlib/libc/include/wchar.h b/newlib/libc/include/wchar.h
index 3a2b89b..a03f642 100644
--- a/newlib/libc/include/wchar.h
+++ b/newlib/libc/include/wchar.h
@@ -63,6 +63,11 @@ typedef __gnuc_va_list va_list;
 #endif
 #endif
 
+#if __POSIX_VISIBLE >= 200809 || defined (_COMPILING_NEWLIB)
+struct __locale_t;
+typedef struct __locale_t *locale_t;
+#endif
+
 _BEGIN_STD_C
 
 #if __POSIX_VISIBLE >= 200809 || _XSI_VISIBLE
@@ -162,6 +167,14 @@ int        _EXFUN(wcswidth, (const wchar_t *, size_t));
 #endif
 size_t _EXFUN(wcsxfrm, (wchar_t *__restrict, const wchar_t *__restrict,
                                size_t));
+#if __POSIX_VISIBLE >= 200809
+extern int wcscasecmp_l (const wchar_t *, const wchar_t *, locale_t);
+extern int wcsncasecmp_l (const wchar_t *, const wchar_t *, size_t, locale_t);
+extern int wcscoll_l (const wchar_t *, const wchar_t *, locale_t);
+extern size_t wcsxfrm_l (wchar_t *__restrict, const wchar_t *__restrict, 
size_t,
+                        locale_t);
+#endif
+
 #if __XSI_VISIBLE
 int    _EXFUN(wcwidth, (const wchar_t));
 #endif
diff --git a/newlib/libc/locale/setlocale.h b/newlib/libc/locale/setlocale.h
index a737063..8f5c93c 100644
--- a/newlib/libc/locale/setlocale.h
+++ b/newlib/libc/locale/setlocale.h
@@ -220,16 +220,14 @@ __get_current_locale ()
   return _REENT->_locale ?: &__global_locale;
 }
 
-#define __get_locale_ctype(__l) \
-       ((const struct lc_ctype_T *) (__l)->lc_cat[LC_CTYPE].ptr)
-#ifdef __HAVE_LOCALE_INFO__
-#define __locale_mb_cur_max_l(__l)     (__get_locale_ctype (__l)->mb_cur_max)
-#else
-#define __locale_mb_cur_max_l(__l)     ((__l)->mb_cur_max)
-#endif
-
 #ifdef __CYGWIN__
 _ELIDABLE_INLINE const struct lc_collate_T *
+__get_locale_collate (struct __locale_t *locale)
+{
+  return (const struct lc_collate_T *) locale->lc_cat[LC_COLLATE].ptr;
+}
+
+_ELIDABLE_INLINE const struct lc_collate_T *
 __get_current_collate_locale (void)
 {
   return (const struct lc_collate_T *) __get_current_locale 
()->lc_cat[LC_COLLATE].ptr;
@@ -237,6 +235,22 @@ __get_current_collate_locale (void)
 #endif
 
 _ELIDABLE_INLINE const struct lc_ctype_T *
+__get_locale_ctype (struct __locale_t *locale)
+{
+  return (const struct lc_ctype_T *) (locale)->lc_cat[LC_CTYPE].ptr;
+}
+
+_ELIDABLE_INLINE int
+__locale_mb_cur_max_l (struct __locale_t *locale)
+{
+#ifdef __HAVE_LOCALE_INFO__
+  return __get_locale_ctype (locale)->mb_cur_max[0];
+#else
+  return locale->mb_cur_max[0];
+#endif
+}
+
+_ELIDABLE_INLINE const struct lc_ctype_T *
 __get_current_ctype_locale (void)
 {
   return (const struct lc_ctype_T *) __get_current_locale 
()->lc_cat[LC_CTYPE].ptr;
@@ -260,6 +274,12 @@ __get_current_time_locale (void)
   return (const struct lc_time_T *) __get_current_locale 
()->lc_cat[LC_TIME].ptr;
 }
 
+_ELIDABLE_INLINE const struct lc_ctype_T *
+__get_locale_time (struct __locale_t *locale)
+{
+  return (const struct lc_time_T *) (locale)->lc_cat[LC_TIME].ptr;
+}
+
 _ELIDABLE_INLINE const struct lc_messages_T *
 __get_current_messages_locale (void)
 {
diff --git a/newlib/libc/string/Makefile.am b/newlib/libc/string/Makefile.am
index 1c047f5..e1f7f3b 100644
--- a/newlib/libc/string/Makefile.am
+++ b/newlib/libc/string/Makefile.am
@@ -109,8 +109,16 @@ ELIX_4_SOURCES = \
        memmem.c \
        memrchr.c \
        rawmemchr.c \
+       strcasecmp_l.c \
+       strcoll_l.c \
+       strncasecmp_l.c \
+       strxfrm_l.c \
        wcscasecmp.c \
-       wcsncasecmp.c
+       wcscasecmp_l.c \
+       wcscoll_l.c \
+       wcsncasecmp.c \
+       wcsncasecmp_l.c \
+       wcsxfrm_l.c
 endif !ELIX_LEVEL_3
 endif !ELIX_LEVEL_2
 endif !ELIX_LEVEL_1
@@ -146,6 +154,8 @@ wcsncmp.def wcsncpy.def     wcsnlen.def     wcspbrk.def \
 wcsrchr.def    wcsspn.def      wcsstr.def      wcstok.def  \
 wcswidth.def   wcsxfrm.def     wcwidth.def     wmemchr.def \
 wmemcmp.def    wmemcpy.def     wmemmove.def    wmemset.def \
-memmem.def     memrchr.def     rawmemchr.def   strchrnul.def
+memmem.def     memrchr.def     rawmemchr.def   strchrnul.def \
+strcasecmp_l.def strcoll_l.def strncasecmp_l.def strxfrm_l.def \
+wcscasecmp_l.def wcscoll_l.def wcsncasecmp_l.def wcsxfrm_l.def
 
 CHAPTERS = strings.tex wcstrings.tex
diff --git a/newlib/libc/string/Makefile.in b/newlib/libc/string/Makefile.in
index 95826bb..857d800 100644
--- a/newlib/libc/string/Makefile.in
+++ b/newlib/libc/string/Makefile.in
@@ -1,9 +1,8 @@
-# Makefile.in generated by automake 1.11.6 from Makefile.am.
+# Makefile.in generated by automake 1.12.2 from Makefile.am.
 # @configure_input@
 
-# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
-# Foundation, Inc.
+# Copyright (C) 1994-2012 Free Software Foundation, Inc.
+
 # This Makefile.in is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
@@ -54,15 +53,11 @@ POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
 DIST_COMMON = $(srcdir)/../../Makefile.shared $(srcdir)/Makefile.in \
-       $(srcdir)/Makefile.am
+       $(srcdir)/Makefile.am $(top_srcdir)/../../mkinstalldirs
 subdir = string
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/../../libtool.m4 \
-       $(top_srcdir)/../../ltoptions.m4 \
-       $(top_srcdir)/../../ltsugar.m4 \
-       $(top_srcdir)/../../ltversion.m4 \
-       $(top_srcdir)/../../lt~obsolete.m4 \
-       $(top_srcdir)/../acinclude.m4 $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/../acinclude.m4 \
+       $(top_srcdir)/configure.in
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
        $(ACLOCAL_M4)
 mkinstalldirs = $(SHELL) $(top_srcdir)/../../mkinstalldirs
@@ -124,8 +119,16 @@ am__objects_1 = lib_a-bcopy.$(OBJEXT) 
lib_a-bzero.$(OBJEXT) \
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   
lib_a-memmem.$(OBJEXT) \
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   
lib_a-memrchr.$(OBJEXT) \
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   
lib_a-rawmemchr.$(OBJEXT) \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   
lib_a-strcasecmp_l.$(OBJEXT) \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   
lib_a-strcoll_l.$(OBJEXT) \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   
lib_a-strncasecmp_l.$(OBJEXT) \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   
lib_a-strxfrm_l.$(OBJEXT) \
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   
lib_a-wcscasecmp.$(OBJEXT) \
-@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   
lib_a-wcsncasecmp.$(OBJEXT)
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   
lib_a-wcscasecmp_l.$(OBJEXT) \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   
lib_a-wcscoll_l.$(OBJEXT) \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   
lib_a-wcsncasecmp.$(OBJEXT) \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   
lib_a-wcsncasecmp_l.$(OBJEXT) \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   
lib_a-wcsxfrm_l.$(OBJEXT)
 @USE_LIBTOOL_FALSE@am_lib_a_OBJECTS = $(am__objects_1) \
 @USE_LIBTOOL_FALSE@    $(am__objects_2) $(am__objects_3)
 lib_a_OBJECTS = $(am_lib_a_OBJECTS)
@@ -153,8 +156,16 @@ am__objects_4 = bcopy.lo bzero.lo explicit_bzero.lo 
index.lo memchr.lo \
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   memmem.lo \
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   memrchr.lo \
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   rawmemchr.lo \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   strcasecmp_l.lo 
\
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   strcoll_l.lo \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   
strncasecmp_l.lo \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   strxfrm_l.lo \
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   wcscasecmp.lo \
-@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   wcsncasecmp.lo
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   wcscasecmp_l.lo 
\
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   wcscoll_l.lo \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   wcsncasecmp.lo \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   
wcsncasecmp_l.lo \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   wcsxfrm_l.lo
 @USE_LIBTOOL_TRUE@am_libstring_la_OBJECTS = $(am__objects_4) \
 @USE_LIBTOOL_TRUE@     $(am__objects_5) $(am__objects_6)
 libstring_la_OBJECTS = $(am_libstring_la_OBJECTS)
@@ -241,8 +252,10 @@ LIBTOOL = @LIBTOOL@
 LIPO = @LIPO@
 LN_S = @LN_S@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
 MKDIR_P = @MKDIR_P@
 NEWLIB_CFLAGS = @NEWLIB_CFLAGS@
 NM = @NM@
@@ -271,6 +284,7 @@ abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
 abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
 ac_ct_CC = @ac_ct_CC@
 ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
 aext = @aext@
@@ -422,8 +436,16 @@ GENERAL_SOURCES = \
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   memmem.c \
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   memrchr.c \
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   rawmemchr.c \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   strcasecmp_l.c \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   strcoll_l.c \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   strncasecmp_l.c 
\
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   strxfrm_l.c \
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   wcscasecmp.c \
-@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   wcsncasecmp.c
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   wcscasecmp_l.c \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   wcscoll_l.c \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   wcsncasecmp.c \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   wcsncasecmp_l.c 
\
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@   wcsxfrm_l.c
 
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_TRUE@ELIX_4_SOURCES = 
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_TRUE@ELIX_4_SOURCES = 
@@ -462,7 +484,9 @@ wcsncmp.def wcsncpy.def     wcsnlen.def     wcspbrk.def \
 wcsrchr.def    wcsspn.def      wcsstr.def      wcstok.def  \
 wcswidth.def   wcsxfrm.def     wcwidth.def     wmemchr.def \
 wmemcmp.def    wmemcpy.def     wmemmove.def    wmemset.def \
-memmem.def     memrchr.def     rawmemchr.def   strchrnul.def
+memmem.def     memrchr.def     rawmemchr.def   strchrnul.def \
+strcasecmp_l.def strcoll_l.def strncasecmp_l.def strxfrm_l.def \
+wcscasecmp_l.def wcscoll_l.def wcsncasecmp_l.def wcsxfrm_l.def
 
 CHAPTERS = strings.tex wcstrings.tex
 all: all-am
@@ -510,12 +534,14 @@ lib.a: $(lib_a_OBJECTS) $(lib_a_DEPENDENCIES) 
$(EXTRA_lib_a_DEPENDENCIES)
 
 clean-noinstLTLIBRARIES:
        -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
-       @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
-         dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
-         test "$$dir" != "$$p" || dir=.; \
-         echo "rm -f \"$${dir}/so_locations\""; \
-         rm -f "$${dir}/so_locations"; \
-       done
+       @list='$(noinst_LTLIBRARIES)'; \
+       locs=`for p in $$list; do echo $$p; done | \
+             sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+             sort -u`; \
+       test -z "$$locs" || { \
+         echo rm -f $${locs}; \
+         rm -f $${locs}; \
+       }
 libstring.la: $(libstring_la_OBJECTS) $(libstring_la_DEPENDENCIES) 
$(EXTRA_libstring_la_DEPENDENCIES) 
        $(libstring_la_LINK) $(am_libstring_la_rpath) $(libstring_la_OBJECTS) 
$(libstring_la_LIBADD) $(LIBS)
 
@@ -1056,18 +1082,66 @@ lib_a-rawmemchr.o: rawmemchr.c
 lib_a-rawmemchr.obj: rawmemchr.c
        $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) 
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-rawmemchr.obj `if test -f 
'rawmemchr.c'; then $(CYGPATH_W) 'rawmemchr.c'; else $(CYGPATH_W) 
'$(srcdir)/rawmemchr.c'; fi`
 
+lib_a-strcasecmp_l.o: strcasecmp_l.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) 
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strcasecmp_l.o `test -f 
'strcasecmp_l.c' || echo '$(srcdir)/'`strcasecmp_l.c
+
+lib_a-strcasecmp_l.obj: strcasecmp_l.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) 
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strcasecmp_l.obj `if test -f 
'strcasecmp_l.c'; then $(CYGPATH_W) 'strcasecmp_l.c'; else $(CYGPATH_W) 
'$(srcdir)/strcasecmp_l.c'; fi`
+
+lib_a-strcoll_l.o: strcoll_l.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) 
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strcoll_l.o `test -f 
'strcoll_l.c' || echo '$(srcdir)/'`strcoll_l.c
+
+lib_a-strcoll_l.obj: strcoll_l.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) 
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strcoll_l.obj `if test -f 
'strcoll_l.c'; then $(CYGPATH_W) 'strcoll_l.c'; else $(CYGPATH_W) 
'$(srcdir)/strcoll_l.c'; fi`
+
+lib_a-strncasecmp_l.o: strncasecmp_l.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) 
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strncasecmp_l.o `test -f 
'strncasecmp_l.c' || echo '$(srcdir)/'`strncasecmp_l.c
+
+lib_a-strncasecmp_l.obj: strncasecmp_l.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) 
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strncasecmp_l.obj `if test -f 
'strncasecmp_l.c'; then $(CYGPATH_W) 'strncasecmp_l.c'; else $(CYGPATH_W) 
'$(srcdir)/strncasecmp_l.c'; fi`
+
+lib_a-strxfrm_l.o: strxfrm_l.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) 
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strxfrm_l.o `test -f 
'strxfrm_l.c' || echo '$(srcdir)/'`strxfrm_l.c
+
+lib_a-strxfrm_l.obj: strxfrm_l.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) 
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strxfrm_l.obj `if test -f 
'strxfrm_l.c'; then $(CYGPATH_W) 'strxfrm_l.c'; else $(CYGPATH_W) 
'$(srcdir)/strxfrm_l.c'; fi`
+
 lib_a-wcscasecmp.o: wcscasecmp.c
        $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) 
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-wcscasecmp.o `test -f 
'wcscasecmp.c' || echo '$(srcdir)/'`wcscasecmp.c
 
 lib_a-wcscasecmp.obj: wcscasecmp.c
        $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) 
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-wcscasecmp.obj `if test -f 
'wcscasecmp.c'; then $(CYGPATH_W) 'wcscasecmp.c'; else $(CYGPATH_W) 
'$(srcdir)/wcscasecmp.c'; fi`
 
+lib_a-wcscasecmp_l.o: wcscasecmp_l.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) 
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-wcscasecmp_l.o `test -f 
'wcscasecmp_l.c' || echo '$(srcdir)/'`wcscasecmp_l.c
+
+lib_a-wcscasecmp_l.obj: wcscasecmp_l.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) 
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-wcscasecmp_l.obj `if test -f 
'wcscasecmp_l.c'; then $(CYGPATH_W) 'wcscasecmp_l.c'; else $(CYGPATH_W) 
'$(srcdir)/wcscasecmp_l.c'; fi`
+
+lib_a-wcscoll_l.o: wcscoll_l.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) 
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-wcscoll_l.o `test -f 
'wcscoll_l.c' || echo '$(srcdir)/'`wcscoll_l.c
+
+lib_a-wcscoll_l.obj: wcscoll_l.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) 
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-wcscoll_l.obj `if test -f 
'wcscoll_l.c'; then $(CYGPATH_W) 'wcscoll_l.c'; else $(CYGPATH_W) 
'$(srcdir)/wcscoll_l.c'; fi`
+
 lib_a-wcsncasecmp.o: wcsncasecmp.c
        $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) 
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-wcsncasecmp.o `test -f 
'wcsncasecmp.c' || echo '$(srcdir)/'`wcsncasecmp.c
 
 lib_a-wcsncasecmp.obj: wcsncasecmp.c
        $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) 
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-wcsncasecmp.obj `if test -f 
'wcsncasecmp.c'; then $(CYGPATH_W) 'wcsncasecmp.c'; else $(CYGPATH_W) 
'$(srcdir)/wcsncasecmp.c'; fi`
 
+lib_a-wcsncasecmp_l.o: wcsncasecmp_l.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) 
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-wcsncasecmp_l.o `test -f 
'wcsncasecmp_l.c' || echo '$(srcdir)/'`wcsncasecmp_l.c
+
+lib_a-wcsncasecmp_l.obj: wcsncasecmp_l.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) 
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-wcsncasecmp_l.obj `if test -f 
'wcsncasecmp_l.c'; then $(CYGPATH_W) 'wcsncasecmp_l.c'; else $(CYGPATH_W) 
'$(srcdir)/wcsncasecmp_l.c'; fi`
+
+lib_a-wcsxfrm_l.o: wcsxfrm_l.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) 
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-wcsxfrm_l.o `test -f 
'wcsxfrm_l.c' || echo '$(srcdir)/'`wcsxfrm_l.c
+
+lib_a-wcsxfrm_l.obj: wcsxfrm_l.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) 
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-wcsxfrm_l.obj `if test -f 
'wcsxfrm_l.c'; then $(CYGPATH_W) 'wcsxfrm_l.c'; else $(CYGPATH_W) 
'$(srcdir)/wcsxfrm_l.c'; fi`
+
 mostlyclean-libtool:
        -rm -f *.lo
 
@@ -1123,6 +1197,20 @@ GTAGS:
          && $(am__cd) $(top_srcdir) \
          && gtags -i $(GTAGS_ARGS) "$$here"
 
+cscopelist:  $(HEADERS) $(SOURCES) $(LISP)
+       list='$(SOURCES) $(HEADERS) $(LISP)'; \
+       case "$(srcdir)" in \
+         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+         *) sdir=$(subdir)/$(srcdir) ;; \
+       esac; \
+       for i in $$list; do \
+         if test -f "$$i"; then \
+           echo "$(subdir)/$$i"; \
+         else \
+           echo "$$sdir/$$i"; \
+         fi; \
+       done >> $(top_builddir)/cscope.files
+
 distclean-tags:
        -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
 check-am:
@@ -1233,7 +1321,7 @@ uninstall-am:
 
 .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
        clean-libtool clean-noinstLIBRARIES clean-noinstLTLIBRARIES \
-       ctags distclean distclean-compile distclean-generic \
+       cscopelist ctags distclean distclean-compile distclean-generic \
        distclean-libtool distclean-tags dvi dvi-am html html-am info \
        info-am install install-am install-data install-data-am \
        install-dvi install-dvi-am install-exec install-exec-am \
diff --git a/newlib/libc/string/strcasecmp.c b/newlib/libc/string/strcasecmp.c
index ebf23cd..df8510b 100644
--- a/newlib/libc/string/strcasecmp.c
+++ b/newlib/libc/string/strcasecmp.c
@@ -46,13 +46,11 @@ _DEFUN (strcasecmp, (s1, s2),
        _CONST char *s1 _AND
        _CONST char *s2)
 {
-  _CONST unsigned char *ucs1 = (_CONST unsigned char *) s1;
-  _CONST unsigned char *ucs2 = (_CONST unsigned char *) s2;
   int d = 0;
   for ( ; ; )
     {
-      _CONST int c1 = tolower(*ucs1++);
-      _CONST int c2 = tolower(*ucs2++);
+      _CONST int c1 = tolower(*s1++);
+      _CONST int c2 = tolower(*s2++);
       if (((d = c1 - c2) != 0) || (c2 == '\0'))
         break;
     }
diff --git a/newlib/libc/string/strcasecmp_l.c 
b/newlib/libc/string/strcasecmp_l.c
new file mode 100644
index 0000000..f87039d
--- /dev/null
+++ b/newlib/libc/string/strcasecmp_l.c
@@ -0,0 +1,54 @@
+/*
+FUNCTION
+       <<strcasecmp_l>>---case-insensitive character string compare
+       
+INDEX
+       strcasecmp_l
+
+ANSI_SYNOPSIS
+       #include <strings.h>
+       int strcasecmp_l(const char *<[a]>, const char *<[b]>,
+                        locale_t <[locale]>);
+
+DESCRIPTION
+       <<strcasecmp_l>> compares the string at <[a]> to
+       the string at <[b]> in a case-insensitive manner.
+
+       if <[locale]> is LC_GLOBAL_LOCALE or not a valid locale object, the
+       behaviour is undefined.
+
+RETURNS 
+
+       If <<*<[a]>>> sorts lexicographically after <<*<[b]>>> (after
+       both are converted to lowercase), <<strcasecmp_l>> returns a
+       number greater than zero.  If the two strings match,
+       <<strcasecmp_l>> returns zero.  If <<*<[a]>>> sorts
+       lexicographically before <<*<[b]>>>, <<strcasecmp_l>> returns a
+       number less than zero.
+
+PORTABILITY
+<<strcasecmp_l>> is POSIX-1.2008.
+
+<<strcasecmp_l>> requires no supporting OS subroutines. It uses
+tolower_l() from elsewhere in this library.
+
+QUICKREF
+       strcasecmp_l
+*/
+
+#include <strings.h>
+#include <ctype.h>
+
+int
+strcasecmp_l (const char *s1, const char *s2, struct __locale_t *locale)
+{
+  int d = 0;
+  for ( ; ; )
+    {
+      const int c1 = tolower_l (*s1++, locale);
+      const int c2 = tolower_l (*s2++, locale);
+      if (((d = c1 - c2) != 0) || (c2 == '\0'))
+        break;
+    }
+  return d;
+}
diff --git a/newlib/libc/string/strcoll.c b/newlib/libc/string/strcoll.c
index 65dc380..a6bb31a 100644
--- a/newlib/libc/string/strcoll.c
+++ b/newlib/libc/string/strcoll.c
@@ -20,6 +20,9 @@ DESCRIPTION
        the string pointed to by <[strb]>, using an interpretation
        appropriate to the current <<LC_COLLATE>> state.
 
+       (NOT Cygwin:) The current implementation of <<strcoll>> simply
+       uses <<strcmp>> and does not support any language-specific sorting.
+
 RETURNS
        If the first string is greater than the second string,
        <<strcoll>> returns a number greater than zero.  If the two
diff --git a/newlib/libc/string/strcoll_l.c b/newlib/libc/string/strcoll_l.c
new file mode 100644
index 0000000..5032f84
--- /dev/null
+++ b/newlib/libc/string/strcoll_l.c
@@ -0,0 +1,46 @@
+/*
+FUNCTION
+       <<strcoll_l>>---locale-specific character string compare
+       
+INDEX
+       strcoll_l
+
+ANSI_SYNOPSIS
+       #include <string.h>
+       int strcoll_l(const char *<[stra]>, const char * <[strb]>,
+                     locale_t <[locale]>);
+
+DESCRIPTION
+       <<strcoll_l>> compares the string pointed to by <[stra]> to
+       the string pointed to by <[strb]>, using an interpretation
+       appropriate to the current <<LC_COLLATE>> state.
+
+       (NOT Cygwin:) The current implementation of <<strcoll_l>> simply
+       uses <<strcmp>> and does not support any language-specific sorting.
+
+       If <[locale]> is LC_GLOBAL_LOCALE or not a valid locale object, the
+       behaviour is undefined.
+
+RETURNS
+       If the first string is greater than the second string,
+       <<strcoll_l>> returns a number greater than zero.  If the two
+       strings are equivalent, <<strcoll_l>> returns zero.  If the first
+       string is less than the second string, <<strcoll_l>> returns a
+       number less than zero.
+
+PORTABILITY
+<<strcoll_l>> is POSIX-1.2008.
+
+<<strcoll_l>> requires no supporting OS subroutines.
+
+QUICKREF
+       strcoll_l ansi pure
+*/
+
+#include <string.h>
+
+int
+strcoll_l (const char *a, const char *b, struct __locale_t *locale)
+{
+  return strcmp (a, b);
+}
diff --git a/newlib/libc/string/strncasecmp.c b/newlib/libc/string/strncasecmp.c
index 27778e0..828f30b 100644
--- a/newlib/libc/string/strncasecmp.c
+++ b/newlib/libc/string/strncasecmp.c
@@ -49,13 +49,11 @@ _DEFUN (strncasecmp, (s1, s2, n),
        _CONST char *s2 _AND
        size_t n)
 {
-  _CONST unsigned char *ucs1 = (_CONST unsigned char *) s1;
-  _CONST unsigned char *ucs2 = (_CONST unsigned char *) s2;
   int d = 0;
   for ( ; n != 0; n--)
     {
-      _CONST int c1 = tolower(*ucs1++);
-      _CONST int c2 = tolower(*ucs2++);
+      _CONST int c1 = tolower(*s1++);
+      _CONST int c2 = tolower(*s2++);
       if (((d = c1 - c2) != 0) || (c2 == '\0'))
         break;
     }
diff --git a/newlib/libc/string/strncasecmp_l.c 
b/newlib/libc/string/strncasecmp_l.c
new file mode 100644
index 0000000..41ae582
--- /dev/null
+++ b/newlib/libc/string/strncasecmp_l.c
@@ -0,0 +1,56 @@
+/*
+FUNCTION
+       <<strncasecmp_l>>---case-insensitive character string compare
+       
+INDEX
+       strncasecmp_l
+
+ANSI_SYNOPSIS
+       #include <strings.h>
+       int strncasecmp_l(const char *<[a]>, const char * <[b]>,
+                         size_t <[length]>, locale_t <[locale]>);
+
+DESCRIPTION
+       <<strncasecmp_l>> compares up to <[length]> characters
+       from the string at <[a]> to the string at <[b]> in a 
+       case-insensitive manner.
+
+       if <[locale]> is LC_GLOBAL_LOCALE or not a valid locale object, the
+       behaviour is undefined.
+
+RETURNS
+
+       If <<*<[a]>>> sorts lexicographically after <<*<[b]>>> (after
+       both are converted to lowercase), <<strncasecmp_l>> returns a
+       number greater than zero.  If the two strings are equivalent,
+       <<strncasecmp_l>> returns zero.  If <<*<[a]>>> sorts
+       lexicographically before <<*<[b]>>>, <<strncasecmp_l>> returns a
+       number less than zero.
+
+PORTABILITY
+<<strncasecmp_l>> is POSIX-1.2008.
+
+<<strncasecmp_l>> requires no supporting OS subroutines. It uses
+tolower_l() from elsewhere in this library.
+
+QUICKREF
+       strncasecmp_l
+*/
+
+#include <strings.h>
+#include <ctype.h>
+
+int 
+strncasecmp_l (const char *s1, const char *s2, size_t n,
+              struct __locale_t *locale)
+{
+  int d = 0;
+  for ( ; n != 0; n--)
+    {
+      const int c1 = tolower_l (*s1++, locale);
+      const int c2 = tolower_l (*s2++, locale);
+      if (((d = c1 - c2) != 0) || (c2 == '\0'))
+        break;
+    }
+  return d;
+}
diff --git a/newlib/libc/string/strxfrm.c b/newlib/libc/string/strxfrm.c
index 9d0ab88..edc1272 100644
--- a/newlib/libc/string/strxfrm.c
+++ b/newlib/libc/string/strxfrm.c
@@ -32,7 +32,8 @@ DESCRIPTION
        copying takes place between objects that overlap, the behavior
        is undefined.
 
-       With a C locale, this function just copies.
+       (NOT Cygwin:) The current implementation of <<strxfrm>> simply copies
+       the input and does not support any language-specific transformations.
 
 RETURNS
        The <<strxfrm>> function returns the length of the transformed string
diff --git a/newlib/libc/string/strxfrm_l.c b/newlib/libc/string/strxfrm_l.c
new file mode 100644
index 0000000..a1f4fe2
--- /dev/null
+++ b/newlib/libc/string/strxfrm_l.c
@@ -0,0 +1,71 @@
+/*
+FUNCTION
+       <<strxfrm_l>>---transform string
+
+INDEX
+       strxfrm_l
+
+ANSI_SYNOPSIS
+       #include <string.h>
+       size_t strxfrm_l(char *restrict <[s1]>, const char *restrict <[s2]>,
+                       size_t <[n]>, locale_t <[locale]>);
+
+DESCRIPTION
+       This function transforms the string pointed to by <[s2]> and
+       places the resulting string into the array pointed to by
+       <[s1]>. The transformation is such that if the <<strcmp>>
+       function is applied to the two transformed strings, it returns
+       a value greater than, equal to, or less than zero,
+       correspoinding to the result of a <<strcoll>> function applied
+       to the same two original strings.
+
+       No more than <[n]> characters are placed into the resulting
+       array pointed to by <[s1]>, including the terminating null
+       character. If <[n]> is zero, <[s1]> may be a null pointer. If
+       copying takes place between objects that overlap, the behavior
+       is undefined.
+
+       (NOT Cygwin:) The current implementation of <<strxfrm_l>> simply copies
+       the input and does not support any language-specific transformations.
+
+       If <[locale]> is LC_GLOBAL_LOCALE or not a valid locale object, the
+       behaviour is undefined.
+
+RETURNS
+       The <<strxfrm_l>> function returns the length of the transformed string
+       (not including the terminating null character). If the value returned
+       is <[n]> or more, the contents of the array pointed to by
+       <[s1]> are indeterminate.
+
+PORTABILITY
+<<strxfrm_l>> is POSIX-1.2008.
+
+<<strxfrm_l>> requires no supporting OS subroutines.
+
+QUICKREF
+       strxfrm_l ansi pure
+*/
+
+#include <string.h>
+
+size_t
+strxfrm_l (char *__restrict s1, const char *__restrict s2, size_t n,
+          struct __locale_t *locale)
+{
+  size_t res;
+  res = 0;
+  while (n-- > 0)
+    {
+      if ((*s1++ = *s2++) != '\0')
+        ++res;
+      else
+        return res;
+    }
+  while (*s2)
+    {
+      ++s2;
+      ++res;
+    }
+
+  return res;
+}
diff --git a/newlib/libc/string/wcscasecmp.c b/newlib/libc/string/wcscasecmp.c
index f9f169f..05f9561 100644
--- a/newlib/libc/string/wcscasecmp.c
+++ b/newlib/libc/string/wcscasecmp.c
@@ -46,11 +46,13 @@ _DEFUN (wcscasecmp, (s1, s2),
        _CONST wchar_t *s1 _AND
        _CONST wchar_t *s2)
 {
-  while (*s1 != '\0' && towlower(*s1) == towlower(*s2))
+  int d = 0;
+  for ( ; ; )
     {
-      s1++;
-      s2++;
+      const int c1 = towlower (*s1++);
+      const int c2 = towlower (*s2++);
+      if (((d = c1 - c2) != 0) || (c2 == '\0'))
+        break;
     }
-
-  return towlower(*s1) - towlower(*s2);
+  return d;
 }
diff --git a/newlib/libc/string/wcscasecmp_l.c 
b/newlib/libc/string/wcscasecmp_l.c
new file mode 100644
index 0000000..329be05
--- /dev/null
+++ b/newlib/libc/string/wcscasecmp_l.c
@@ -0,0 +1,54 @@
+/*
+FUNCTION
+       <<wcscasecmp_l>>---case-insensitive wide character string compare
+       
+INDEX
+       wcscasecmp_l
+
+ANSI_SYNOPSIS
+       #include <wchar.h>
+       int wcscasecmp_l(const wchar_t *<[a]>, const wchar_t *<[b]>,
+                        locale_t <[locale]>);
+
+DESCRIPTION
+       <<wcscasecmp_l>> compares the wide character string at <[a]> to
+       the wide character string at <[b]> in a case-insensitive manner.
+
+       if <[locale]> is LC_GLOBAL_LOCALE or not a valid locale object,
+       the behaviour is undefined.
+
+RETURNS 
+
+       If <<*<[a]>>> sorts lexicographically after <<*<[b]>>> (after
+       both are converted to uppercase), <<wcscasecmp_l>> returns a
+       number greater than zero.  If the two strings match,
+       <<wcscasecmp_l>> returns zero.  If <<*<[a]>>> sorts
+       lexicographically before <<*<[b]>>>, <<wcscasecmp_l>> returns a
+       number less than zero.
+
+PORTABILITY
+<<wcscasecmp_l>> is POSIX-1.2008
+
+<<wcscasecmp_l>> requires no supporting OS subroutines. It uses
+tolower() from elsewhere in this library.
+
+QUICKREF
+       wcscasecmp_l 
+*/
+
+#include <wchar.h>
+#include <wctype.h>
+
+int
+wcscasecmp_l (const wchar_t *s1, const wchar_t *s2, struct __locale_t *locale)
+{
+  int d = 0;
+  for ( ; ; )
+    {
+      const int c1 = towlower_l (*s1++, locale);
+      const int c2 = towlower_l (*s2++, locale);
+      if (((d = c1 - c2) != 0) || (c2 == '\0'))
+        break;
+    }
+  return d;
+}
diff --git a/newlib/libc/string/wcscoll.c b/newlib/libc/string/wcscoll.c
index 0f0513a..726f4ca 100644
--- a/newlib/libc/string/wcscoll.c
+++ b/newlib/libc/string/wcscoll.c
@@ -21,8 +21,8 @@ DESCRIPTION
        using an interpretation appropriate to the current <<LC_COLLATE>>
        state.
 
-       The current implementation of <<wcscoll>> simply uses <<wcscmp>>
-       and does not support any language-specific sorting.
+       (NOT Cygwin:) The current implementation of <<wcscoll>> simply
+       uses <<wcscmp>> and does not support any language-specific sorting.
 
 RETURNS
        If the first string is greater than the second string,
diff --git a/newlib/libc/string/wcscoll_l.c b/newlib/libc/string/wcscoll_l.c
new file mode 100644
index 0000000..e71d02a
--- /dev/null
+++ b/newlib/libc/string/wcscoll_l.c
@@ -0,0 +1,43 @@
+/*
+FUNCTION
+       <<wcscoll_l>>---locale-specific wide-character string compare
+       
+INDEX
+       wcscoll_l
+
+ANSI_SYNOPSIS
+       #include <wchar.h>
+       int wcscoll_l(const wchar_t *<[stra]>, const wchar_t * <[strb]>,
+                     locale_t <[locale]>);
+
+DESCRIPTION
+       <<wcscoll_l>> compares the wide-character string pointed to by
+       <[stra]> to the wide-character string pointed to by <[strb]>,
+       using an interpretation appropriate to the current <<LC_COLLATE>>
+       state.
+
+       (NOT Cygwin:) The current implementation of <<wcscoll_l>> simply
+       uses <<wcscmp>> and does not support any language-specific sorting.
+
+       If <[locale]> is LC_GLOBAL_LOCALE or not a valid locale object, the
+       behaviour is undefined.
+
+RETURNS
+       If the first string is greater than the second string,
+       <<wcscoll_l>> returns a number greater than zero.  If the two
+       strings are equivalent, <<wcscoll_l>> returns zero.  If the first
+       string is less than the second string, <<wcscoll_l>> returns a
+       number less than zero.
+
+PORTABILITY
+<<wcscoll_l>> is POSIX-1.2008.
+*/
+
+#include <_ansi.h>
+#include <wchar.h>
+
+int
+wcscoll_l (const wchar_t *a, const wchar_t *b, struct __locale_t *locale)
+{
+  return wcscmp (a, b);
+}
diff --git a/newlib/libc/string/wcsncasecmp.c b/newlib/libc/string/wcsncasecmp.c
index 1634ca1..c6fc08e 100644
--- a/newlib/libc/string/wcsncasecmp.c
+++ b/newlib/libc/string/wcsncasecmp.c
@@ -49,16 +49,13 @@ _DEFUN (wcsncasecmp, (s1, s2, n),
        _CONST wchar_t *s2 _AND
        size_t n)
 {
-  if (n == 0)
-    return 0;
-
-  while (n-- != 0 && towlower(*s1) == towlower(*s2))
+  int d = 0;
+  for ( ; n != 0; n--)
     {
-      if (n == 0 || *s1 == '\0' || *s2 == '\0')
-       break;
-      s1++;
-      s2++;
+      const int c1 = towlower (*s1++);
+      const int c2 = towlower (*s2++);
+      if (((d = c1 - c2) != 0) || (c2 == '\0'))
+        break;
     }
-
-  return towlower(*s1) - towlower(*s2);
+  return d;
 }
diff --git a/newlib/libc/string/wcsncasecmp_l.c 
b/newlib/libc/string/wcsncasecmp_l.c
new file mode 100644
index 0000000..4b360b8
--- /dev/null
+++ b/newlib/libc/string/wcsncasecmp_l.c
@@ -0,0 +1,56 @@
+/*
+FUNCTION
+       <<wcsncasecmp_l>>---case-insensitive wide character string compare
+       
+INDEX
+       wcsncasecmp_l
+
+ANSI_SYNOPSIS
+       #include <wchar.h>
+       int wcsncasecmp_l(const wchar_t *<[a]>, const wchar_t * <[b]>,
+                         size_t <[length]>, locale_t <[locale]>);
+
+DESCRIPTION
+       <<wcsncasecmp_l>> compares up to <[length]> wide characters
+       from the string at <[a]> to the string at <[b]> in a 
+       case-insensitive manner.
+
+       if <[locale]> is LC_GLOBAL_LOCALE or not a valid locale object, the
+       behaviour is undefined.
+
+RETURNS
+
+       If <<*<[a]>>> sorts lexicographically after <<*<[b]>>> (after
+       both are converted to uppercase), <<wcsncasecmp_l>> returns a
+       number greater than zero.  If the two strings are equivalent,
+       <<wcsncasecmp_l>> returns zero.  If <<*<[a]>>> sorts
+       lexicographically before <<*<[b]>>>, <<wcsncasecmp_l>> returns a
+       number less than zero.
+
+PORTABILITY
+POSIX-1.2008
+
+<<wcsncasecmp_l>> requires no supporting OS subroutines. It uses
+tolower() from elsewhere in this library.
+
+QUICKREF
+       wcsncasecmp_l
+*/
+
+#include <wchar.h>
+#include <wctype.h>
+
+int 
+wcsncasecmp_l (const wchar_t *s1, const wchar_t *s2, size_t n,
+              struct __locale_t *locale)
+{
+  int d = 0;
+  for ( ; n != 0; n--)
+    {
+      const int c1 = towlower_l (*s1++, locale);
+      const int c2 = towlower_l (*s2++, locale);
+      if (((d = c1 - c2) != 0) || (c2 == '\0'))
+        break;
+    }
+  return d;
+}
diff --git a/newlib/libc/string/wcsxfrm.c b/newlib/libc/string/wcsxfrm.c
index d5a3172..d267d27 100644
--- a/newlib/libc/string/wcsxfrm.c
+++ b/newlib/libc/string/wcsxfrm.c
@@ -27,8 +27,8 @@ DESCRIPTION
 
        If <[n]> is 0, <[stra]> may be a NULL pointer.
 
-       The current implementation of <<wcsxfrm>> simply uses <<wcslcpy>>
-       and does not support any language-specific transformations.
+       (NOT Cygwin:) The current implementation of <<wcsxfrm>> simply uses
+       <<wcslcpy>> and does not support any language-specific transformations.
 
 RETURNS
        <<wcsxfrm>> returns the length of the transformed wide character
diff --git a/newlib/libc/string/wcsxfrm_l.c b/newlib/libc/string/wcsxfrm_l.c
new file mode 100644
index 0000000..c44b0d6
--- /dev/null
+++ b/newlib/libc/string/wcsxfrm_l.c
@@ -0,0 +1,47 @@
+/*
+FUNCTION
+       <<wcsxfrm_l>>---locale-specific wide-character string transformation
+       
+INDEX
+       wcsxfrm_l
+
+ANSI_SYNOPSIS
+       #include <wchar.h>
+       int wcsxfrm_l(wchar_t *__restrict <[stra]>,
+                     const wchar_t *__restrict <[strb]>, size_t <[n]>,
+                     locale_t <[locale]>);
+
+DESCRIPTION
+       <<wcsxfrm_l>> transforms the wide-character string pointed to by
+       <[strb]> to the wide-character string pointed to by <[stra]>,
+       Comparing two transformed wide strings with <<wcscmp>> should return
+       the same result as comparing the original strings with <<wcscoll>>.
+       No more than <[n]> wide characters are transformed, including the
+       trailing null character.
+
+       If <[n]> is 0, <[stra]> may be a NULL pointer.
+
+       If <[locale]> is LC_GLOBAL_LOCALE or not a valid locale object, the
+       behaviour is undefined.
+
+       (NOT Cygwin:) The current implementation of <<wcsxfrm_l>> simply uses
+       <<wcslcpy>> and does not support any language-specific transformations.
+
+RETURNS
+       <<wcsxfrm_l>> returns the length of the transformed wide character
+       string.  if the return value is greater or equal to <[n]>, the
+       content of <[stra]> is undefined.
+
+PORTABILITY
+<<wcsxfrm_l>> is POSIX-1.2008.
+*/
+
+#include <_ansi.h>
+#include <wchar.h>
+
+size_t
+wcsxfrm_l (wchar_t *__restrict a, const wchar_t *__restrict b, size_t n,
+          struct __locale_t *locale)
+{
+  return wcslcpy (a, b, n);
+}
diff --git a/newlib/libc/time/strftime.c b/newlib/libc/time/strftime.c
index 12c37eb..0d5bbd5 100644
--- a/newlib/libc/time/strftime.c
+++ b/newlib/libc/time/strftime.c
@@ -4,7 +4,7 @@
 /*
  * strftime.c
  * Original Author:    G. Haley
- * Additions from:     Eric Blake
+ * Additions from:     Eric Blake, Corinna Vinschen
  * Changes to allow dual use as wcstime, also: Craig Howland
  *
  * Places characters into the array pointed to by s as controlled by the string
@@ -17,16 +17,23 @@
 
 /*
 FUNCTION
-<<strftime>>---convert date and time to a formatted string
+<<strftime>>, <<strftime_l>>---convert date and time to a formatted string
 
 INDEX
        strftime
 
+INDEX
+       strftime_l
+
 ANSI_SYNOPSIS
        #include <time.h>
        size_t strftime(char *restrict <[s]>, size_t <[maxsize]>,
                        const char *restrict <[format]>,
                         const struct tm *restrict <[timp]>);
+       size_t strftime_l(char *restrict <[s]>, size_t <[maxsize]>,
+                         const char *restrict <[format]>,
+                         const struct tm *restrict <[timp]>,
+                         locale_t <[locale]>);
 
 TRAD_SYNOPSIS
        #include <time.h>
@@ -41,6 +48,9 @@ DESCRIPTION
 <[timp]>) into a null-terminated string, starting at <[s]> and occupying
 no more than <[maxsize]> characters.
 
+<<strftime_l>> is like <<strftime>> but creates a string in a format
+as expected in locale <[locale]>.
+
 You control the format of the output using the string at <[format]>.
 <<*<[format]>>> can contain two kinds of specifications: text to be
 copied literally into the formatted string, and time conversion
@@ -258,11 +268,13 @@ value beforehand to distinguish between failure and an 
empty string.
 This implementation does not support <<s>> being NULL, nor overlapping
 <<s>> and <<format>>.
 
-<<strftime>> requires no supporting OS subroutines.
+<<strftime_l>> is POSIX-1.2008.
+
+<<strftime>> and <<strftime_l>> require no supporting OS subroutines.
 
 BUGS
-<<strftime>> ignores the LC_TIME category of the current locale, hard-coding
-the "C" locale settings.
+(NOT Cygwin:) <<strftime>> ignores the LC_TIME category of the current
+locale, hard-coding the "C" locale settings.
 */
 
 #include <newlib.h>
@@ -662,39 +674,16 @@ conv_to_alt_digits (CHAR *buf, size_t bufsiz, unsigned 
num, alt_digits_t *adi)
   return 0;
 }
 
-static size_t __strftime (CHAR *, size_t, const CHAR *, const struct tm *,
-                         era_info_t **, alt_digits_t **);
-
-size_t
-_DEFUN (strftime, (s, maxsize, format, tim_p),
-       CHAR *__restrict s _AND
-       size_t maxsize _AND
-       _CONST CHAR *__restrict format _AND
-       _CONST struct tm *__restrict tim_p)
-{
-  era_info_t *era_info = NULL;
-  alt_digits_t *alt_digits = NULL;
-  size_t ret = __strftime (s, maxsize, format, tim_p, &era_info, &alt_digits);
-  if (era_info)
-    free_era_info (era_info);
-  if (alt_digits)
-    free_alt_digits (alt_digits);
-  return ret;
-}
-
 static size_t
 __strftime (CHAR *s, size_t maxsize, const CHAR *format,
-           const struct tm *tim_p, era_info_t **era_info,
-           alt_digits_t **alt_digits)
-#else /* !_WANT_C99_TIME_FORMATS */
-# define __strftime(s,m,f,t,e,a)       strftime((s),(m),(f),(t))
+           const struct tm *tim_p, struct __locale_t *locale,
+           era_info_t **era_info, alt_digits_t **alt_digits)
+#else
+static size_t
+__strftime (CHAR *s, size_t maxsize, const CHAR *format,
+           const struct tm *tim_p, struct __locale_t *locale)
 
-size_t
-_DEFUN (strftime, (s, maxsize, format, tim_p),
-       CHAR *__restrict s _AND
-       size_t maxsize _AND
-       _CONST CHAR *__restrict format _AND
-       _CONST struct tm *__restrict tim_p)
+#define __strftime(s,m,f,t,l,e,a)      __strftime((s),(m),(f),(t),(l))
 #endif /* !_WANT_C99_TIME_FORMATS */
 {
   size_t count = 0;
@@ -709,7 +698,7 @@ _DEFUN (strftime, (s, maxsize, format, tim_p),
   unsigned long width;
   int tzset_called = 0;
 
-  const struct lc_time_T *_CurrentTimeLocale = __get_current_time_locale ();
+  const struct lc_time_T *_CurrentTimeLocale = __get_locale_time (locale);
   for (;;)
     {
       while (*format && *format != CQ('%'))
@@ -840,7 +829,7 @@ recurse:
            {
              /* Recurse to avoid need to replicate %Y formation. */
              len = __strftime (&s[count], maxsize - count, ctloc, tim_p,
-                               era_info, alt_digits);
+                               locale, era_info, alt_digits);
              if (len > 0)
                count += len;
              else
@@ -957,7 +946,7 @@ recurse:
              }
            STRCPY (fmt, CQ("Y-%m-%d"));
            len = __strftime (&s[count], maxsize - count, fmtbuf, tim_p,
-                             era_info, alt_digits);
+                             locale, era_info, alt_digits);
            if (len > 0)
              count += len;
            else
@@ -1447,6 +1436,41 @@ recurse:
   return count;
 }
 
+size_t
+_DEFUN (strftime, (s, maxsize, format, tim_p),
+       CHAR *__restrict s _AND
+       size_t maxsize _AND
+       _CONST CHAR *__restrict format _AND
+       _CONST struct tm *__restrict tim_p)
+{
+  era_info_t *era_info = NULL;
+  alt_digits_t *alt_digits = NULL;
+  size_t ret = __strftime (s, maxsize, format, tim_p, __get_current_locale (),
+                          &era_info, &alt_digits);
+  if (era_info)
+    free_era_info (era_info);
+  if (alt_digits)
+    free_alt_digits (alt_digits);
+  return ret;
+}
+
+#if !defined(MAKE_WCSFTIME)
+size_t
+strftime_l (char *__restrict s, size_t maxsize, const char *__restrict format,
+           const struct tm *__restrict tim_p, struct __locale_t *locale)
+{
+  era_info_t *era_info = NULL;
+  alt_digits_t *alt_digits = NULL;
+  size_t ret = __strftime (s, maxsize, format, tim_p, locale,
+                          &era_info, &alt_digits);
+  if (era_info)
+    free_era_info (era_info);
+  if (alt_digits)
+    free_alt_digits (alt_digits);
+  return ret;
+}
+#endif
+
 /* The remainder of this file can serve as a regression test.  Compile
  *  with -D_REGRESSION_TEST.  */
 #if defined(_REGRESSION_TEST)  /* [Test code:  */
diff --git a/winsup/cygwin/common.din b/winsup/cygwin/common.din
index 7d80c3d..114adc9 100644
--- a/winsup/cygwin/common.din
+++ b/winsup/cygwin/common.din
@@ -1330,12 +1330,14 @@ stime SIGFE
 stpcpy NOSIGFE
 stpncpy NOSIGFE
 strcasecmp NOSIGFE
+strcasecmp_l NOSIGFE
 strcasestr NOSIGFE
 strcat NOSIGFE
 strchr NOSIGFE
 strchrnul NOSIGFE
 strcmp NOSIGFE
 strcoll NOSIGFE
+strcoll_l NOSIGFE
 strcpy NOSIGFE
 strcspn NOSIGFE
 strdup SIGFE
@@ -1343,11 +1345,13 @@ strerror SIGFE
 strerror_r SIGFE
 strfmon SIGFE
 strftime SIGFE
+strftime_l SIGFE
 strlcat NOSIGFE
 strlcpy NOSIGFE
 strlen NOSIGFE
 strlwr NOSIGFE
 strncasecmp NOSIGFE
+strncasecmp_l NOSIGFE
 strncat NOSIGFE
 strncmp NOSIGFE
 strncpy NOSIGFE
@@ -1374,6 +1378,7 @@ strtoull NOSIGFE
 strtoumax = strtoull NOSIGFE
 strupr NOSIGFE
 strxfrm NOSIGFE
+strxfrm_l NOSIGFE
 swab NOSIGFE
 swapcontext NOSIGFE
 swprintf SIGFE
@@ -1495,10 +1500,12 @@ wcpcpy NOSIGFE
 wcpncpy NOSIGFE
 wcrtomb NOSIGFE
 wcscasecmp NOSIGFE
+wcscasecmp_l NOSIGFE
 wcscat NOSIGFE
 wcschr NOSIGFE
 wcscmp NOSIGFE
 wcscoll NOSIGFE
+wcscoll_l NOSIGFE
 wcscpy NOSIGFE
 wcscspn NOSIGFE
 wcsdup NOSIGFE
@@ -1507,6 +1514,7 @@ wcslcat NOSIGFE
 wcslcpy NOSIGFE
 wcslen NOSIGFE
 wcsncasecmp NOSIGFE
+wcsncasecmp_l NOSIGFE
 wcsncat NOSIGFE
 wcsncmp NOSIGFE
 wcsncpy NOSIGFE
@@ -1530,6 +1538,7 @@ wcstoull NOSIGFE
 wcstoumax = wcstoull NOSIGFE
 wcswidth NOSIGFE
 wcsxfrm NOSIGFE
+wcsxfrm_l NOSIGFE
 wctob NOSIGFE
 wctomb NOSIGFE
 wctrans NOSIGFE
diff --git a/winsup/cygwin/nlsfuncs.cc b/winsup/cygwin/nlsfuncs.cc
index 9b19f2a..7145771 100644
--- a/winsup/cygwin/nlsfuncs.cc
+++ b/winsup/cygwin/nlsfuncs.cc
@@ -1117,10 +1117,11 @@ __collate_load_locale (struct __locale_t *locale, const 
char *name,
    transformation.  The advantage is that we don't need any files with
    collation information. */
 extern "C" int
-wcscoll (const wchar_t *__restrict ws1, const wchar_t *__restrict ws2)
+wcscoll_l (const wchar_t *__restrict ws1, const wchar_t *__restrict ws2,
+          struct __locale_t *locale)
 {
   int ret;
-  LCID collate_lcid = __get_current_collate_locale ()->lcid;
+  LCID collate_lcid = __get_locale_collate (locale)->lcid;
 
   if (!collate_lcid)
     return wcscmp (ws1, ws2);
@@ -1131,19 +1132,26 @@ wcscoll (const wchar_t *__restrict ws1, const wchar_t 
*__restrict ws2)
 }
 
 extern "C" int
-strcoll (const char *__restrict s1, const char *__restrict s2)
+wcscoll (const wchar_t *__restrict ws1, const wchar_t *__restrict ws2)
+{
+  return wcscoll_l (ws1, ws2, __get_current_locale ());
+}
+
+extern "C" int
+strcoll_l (const char *__restrict s1, const char *__restrict s2,
+          struct __locale_t *locale)
 {
   size_t n1, n2;
   wchar_t *ws1, *ws2;
   tmp_pathbuf tp;
   int ret;
-  LCID collate_lcid = __get_current_collate_locale ()->lcid;
+  LCID collate_lcid = __get_locale_collate (locale)->lcid;
 
   if (!collate_lcid)
     return strcmp (s1, s2);
   /* The ANSI version of CompareString uses the default charset of the lcid,
      so we must use the Unicode version. */
-  mbtowc_p collate_mbtowc = __get_current_collate_locale ()->mbtowc;
+  mbtowc_p collate_mbtowc = __get_locale_collate (locale)->mbtowc;
   n1 = lc_mbstowcs (collate_mbtowc, NULL, s1, 0) + 1;
   ws1 = (n1 > NT_MAX_PATH ? (wchar_t *) malloc (n1 * sizeof (wchar_t))
                          : tp.w_get ());
@@ -1162,6 +1170,12 @@ strcoll (const char *__restrict s1, const char 
*__restrict s2)
   return ret - CSTR_EQUAL;
 }
 
+extern "C" int
+strcoll (const char *__restrict s1, const char *__restrict s2)
+{
+  return strcoll_l (s1, s2, __get_current_locale ());
+}
+
 /* BSD.  Used from glob.cc, fnmatch.c and regcomp.c.  Make sure caller is
    using wide chars.  Unfortunately the definition of this functions hides
    the required input type. */
@@ -1174,10 +1188,11 @@ __collate_range_cmp (int c1, int c2)
 }
 
 extern "C" size_t
-wcsxfrm (wchar_t *__restrict ws1, const wchar_t *__restrict ws2, size_t wsn)
+wcsxfrm_l (wchar_t *__restrict ws1, const wchar_t *__restrict ws2, size_t wsn,
+          struct __locale_t *locale)
 {
   size_t ret;
-  LCID collate_lcid = __get_current_collate_locale ()->lcid;
+  LCID collate_lcid = __get_locale_collate (locale)->lcid;
 
   if (!collate_lcid)
     return wcslcpy (ws1, ws2, wsn);
@@ -1207,19 +1222,26 @@ wcsxfrm (wchar_t *__restrict ws1, const wchar_t 
*__restrict ws2, size_t wsn)
 }
 
 extern "C" size_t
-strxfrm (char *__restrict s1, const char *__restrict s2, size_t sn)
+wcsxfrm (wchar_t *__restrict ws1, const wchar_t *__restrict ws2, size_t wsn)
+{
+  return wcsxfrm_l (ws1, ws2, wsn, __get_current_locale ());
+}
+
+extern "C" size_t
+strxfrm_l (char *__restrict s1, const char *__restrict s2, size_t sn,
+          struct __locale_t *locale)
 {
   size_t ret = 0;
   size_t n2;
   wchar_t *ws2;
   tmp_pathbuf tp;
-  LCID collate_lcid = __get_current_collate_locale ()->lcid;
+  LCID collate_lcid = __get_locale_collate (locale)->lcid;
 
   if (!collate_lcid)
     return strlcpy (s1, s2, sn);
   /* The ANSI version of LCMapString uses the default charset of the lcid,
      so we must use the Unicode version. */
-  mbtowc_p collate_mbtowc = __get_current_collate_locale ()->mbtowc;
+  mbtowc_p collate_mbtowc = __get_locale_collate (locale)->mbtowc;
   n2 = lc_mbstowcs (collate_mbtowc, NULL, s2, 0) + 1;
   ws2 = (n2 > NT_MAX_PATH ? (wchar_t *) malloc (n2 * sizeof (wchar_t))
                          : tp.w_get ());
@@ -1245,6 +1267,12 @@ strxfrm (char *__restrict s1, const char *__restrict s2, 
size_t sn)
   return ret - 1;
 }
 
+extern "C" size_t
+strxfrm (char *__restrict s1, const char *__restrict s2, size_t sn)
+{
+  return strxfrm_l (s1, s2, sn, __get_current_locale ());
+}
+
 /* Fetch default ANSI codepage from locale info and generate a setlocale
    compatible character set code.  Called from newlib's setlocale(), if the
    charset isn't given explicitely in the POSIX compatible locale specifier. */
diff --git a/winsup/doc/posix.xml b/winsup/doc/posix.xml
index 38a5bbc..bc38f39 100644
--- a/winsup/doc/posix.xml
+++ b/winsup/doc/posix.xml
@@ -913,10 +913,12 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
     stpcpy
     stpncpy
     strcasecmp
+    strcasecmp_l
     strcat
     strchr
     strcmp
     strcoll
+    strcoll_l
     strcpy
     strcspn
     strdup
@@ -924,8 +926,10 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
     strerror_r
     strfmon
     strftime
+    strftime_l
     strlen
     strncasecmp
+    strncasecmp_l
     strncat
     strncmp
     strncpy
@@ -949,6 +953,7 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
     strtoull
     strtoumax
     strxfrm
+    strxfrm_l
     swab
     swprintf
     swscanf
@@ -1045,16 +1050,19 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
     wcpncpy
     wcrtomb
     wcscasecmp
+    wcscasecmp_l
     wcscat
     wcschr
     wcscmp
     wcscoll
+    wcscoll_l
     wcscpy
     wcscspn
     wcsdup
     wcsftime
     wcslen
     wcsncasecmp
+    wcsncasecmp_l
     wcsncat
     wcsncmp
     wcsncpy
@@ -1078,6 +1086,7 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
     wcstoumax
     wcswidth
     wcsxfrm
+    wcsxfrm_l
     wctob
     wctomb
     wctrans
@@ -1539,18 +1548,10 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
     putmsg
     setnetent
     sigtimedwait
-    strcasecmp_l
-    strcoll_l
     strfmon_l
-    strncasecmp_l
-    strxfrm_l
     timer_getoverrun
     ulimit
     waitid
-    wcscasecmp_l
-    wcscoll_l
-    wcsncasecmp_l
-    wcsxfrm_l
 </screen>
 
 </sect1>

Reply via email to