This is the mail archive of the cygwin-cvs@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[newlib-cygwin] Implement per-locale string functions


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

commit c1b7d9d93dc8e88693162c0d984a114371919fdd
Author: Corinna Vinschen <corinna@vinschen.de>
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 <corinna@vinschen.de>

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>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]