From 371b65730c22961b59f6f6835ff7459c88e9a531 Mon Sep 17 00:00:00 2001 From: schwarze <> Date: Tue, 5 Sep 2017 03:16:14 +0000 Subject: [PATCH] New POSIX xlocale implementation written from scratch. Complete in the sense that all POSIX *locale(3) and *_l(3) functions are included, but in OpenBSD, we of course only really care about LC_CTYPE and we only support ASCII and UTF-8. With important help from kettenis@, guenther@, and jca@. Repeated testing in ports bulk builds by naddy@. Additional testing by jca@, sebastia@, dcoppa@, and others. OK kettenis@ dcoppa@, and guenther@ on an earlier version. Riding guenther@'s libc/librthread major bump. --- src/include/ctype.h | 114 ++++++++++++++++++++++++++++- src/include/langinfo.h | 13 +++- src/include/locale.h | 30 +++++++- src/include/stdlib.h | 7 +- src/include/string.h | 13 +++- src/include/strings.h | 11 ++- src/include/time.h | 15 +++- src/include/wchar.h | 13 +++- src/include/wctype.h | 31 +++++++- src/lib/libc/string/Makefile.inc | 10 +-- src/lib/libc/string/strcasecmp.3 | 76 ++++++++++++++----- src/lib/libc/string/strcasecmp_l.c | 21 ++++++ src/lib/libc/string/strcoll.3 | 53 ++++++++++---- src/lib/libc/string/strcoll_l.c | 14 ++++ src/lib/libc/string/strerror.3 | 75 +++++++++++++------ src/lib/libc/string/strerror_l.c | 33 +++++++++ src/lib/libc/string/strxfrm.3 | 57 ++++++++++----- src/lib/libc/string/strxfrm_l.c | 14 ++++ src/lib/libc/string/wcscasecmp.3 | 76 ++++++++++++++----- src/lib/libc/string/wcscasecmp_l.c | 63 ++++++++++++++++ 20 files changed, 630 insertions(+), 109 deletions(-) create mode 100644 src/lib/libc/string/strcasecmp_l.c create mode 100644 src/lib/libc/string/strcoll_l.c create mode 100644 src/lib/libc/string/strerror_l.c create mode 100644 src/lib/libc/string/strxfrm_l.c create mode 100644 src/lib/libc/string/wcscasecmp_l.c diff --git a/src/include/ctype.h b/src/include/ctype.h index 13ade6c2..e90d375c 100644 --- a/src/include/ctype.h +++ b/src/include/ctype.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ctype.h,v 1.24 2014/05/26 01:49:36 guenther Exp $ */ +/* $OpenBSD: ctype.h,v 1.25 2017/09/05 03:16:13 schwarze Exp $ */ /* $NetBSD: ctype.h,v 1.14 1994/10/26 00:55:47 cgd Exp $ */ /* @@ -51,6 +51,13 @@ #define _X 0x40 #define _B 0x80 +#if __POSIX_VISIBLE >= 200809 +#ifndef _LOCALE_T_DEFINED_ +#define _LOCALE_T_DEFINED_ +typedef void *locale_t; +#endif +#endif + __BEGIN_DECLS extern const char *_ctype_; @@ -84,9 +91,26 @@ int _tolower(int); int _toupper(int); #endif /* __BSD_VISIBLE || __XPG_VISIBLE */ +#if __POSIX_VISIBLE >= 200809 +int isalnum_l(int, locale_t); +int isalpha_l(int, locale_t); +int isblank_l(int, locale_t); +int iscntrl_l(int, locale_t); +int isdigit_l(int, locale_t); +int isgraph_l(int, locale_t); +int islower_l(int, locale_t); +int isprint_l(int, locale_t); +int ispunct_l(int, locale_t); +int isspace_l(int, locale_t); +int isupper_l(int, locale_t); +int isxdigit_l(int, locale_t); +int tolower_l(int, locale_t); +int toupper_l(int, locale_t); +#endif + #endif /* __GNUC__ || _ANSI_LIBRARY */ -#if !defined(_ANSI_LIBRARY) +#if !defined(_ANSI_LIBRARY) && !defined(__cplusplus) __only_inline int isalnum(int _c) { @@ -187,6 +211,92 @@ __only_inline int _toupper(int _c) } #endif /* __BSD_VISIBLE || __XPG_VISIBLE */ +#if __POSIX_VISIBLE >= 200809 +__only_inline int +isalnum_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return isalnum(_c); +} + +__only_inline int +isalpha_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return isalpha(_c); +} + +__only_inline int +isblank_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return isblank(_c); +} + +__only_inline int +iscntrl_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return iscntrl(_c); +} + +__only_inline int +isdigit_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return isdigit(_c); +} + +__only_inline int +isgraph_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return isgraph(_c); +} + +__only_inline int +islower_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return islower(_c); +} + +__only_inline int +isprint_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return isprint(_c); +} + +__only_inline int +ispunct_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return ispunct(_c); +} + +__only_inline int +isspace_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return isspace(_c); +} + +__only_inline int +isupper_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return isupper(_c); +} + +__only_inline int +isxdigit_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return isxdigit(_c); +} + +__only_inline int +tolower_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return tolower(_c); +} + +__only_inline int +toupper_l(int _c, locale_t _l __attribute__((__unused__))) +{ + return toupper(_c); +} +#endif /* __POSIX_VISIBLE >= 200809 */ + #endif /* !_ANSI_LIBRARY */ __END_DECLS diff --git a/src/include/langinfo.h b/src/include/langinfo.h index 62443094..dd37bfce 100644 --- a/src/include/langinfo.h +++ b/src/include/langinfo.h @@ -1,4 +1,4 @@ -/* $OpenBSD: langinfo.h,v 1.7 2012/12/05 23:19:57 deraadt Exp $ */ +/* $OpenBSD: langinfo.h,v 1.8 2017/09/05 03:16:13 schwarze Exp $ */ /* $NetBSD: langinfo.h,v 1.3 1995/04/28 23:30:54 jtc Exp $ */ /* @@ -70,8 +70,19 @@ #define CODESET 51 /* Codeset name */ +#if __POSIX_VISIBLE >= 200809 +#ifndef _LOCALE_T_DEFINED_ +#define _LOCALE_T_DEFINED_ +typedef void *locale_t; +#endif +#endif + __BEGIN_DECLS char *nl_langinfo(nl_item); + +#if __POSIX_VISIBLE >= 200809 +char *nl_langinfo_l(nl_item, locale_t); +#endif __END_DECLS #endif /* _LANGINFO_H_ */ diff --git a/src/include/locale.h b/src/include/locale.h index 38d7a408..78189962 100644 --- a/src/include/locale.h +++ b/src/include/locale.h @@ -1,4 +1,4 @@ -/* $OpenBSD: locale.h,v 1.10 2016/09/09 18:12:37 millert Exp $ */ +/* $OpenBSD: locale.h,v 1.11 2017/09/05 03:16:13 schwarze Exp $ */ /* $NetBSD: locale.h,v 1.6 1994/10/26 00:56:02 cgd Exp $ */ /* @@ -76,9 +76,37 @@ struct lconv { #include +#if __POSIX_VISIBLE >= 200809 + +#ifndef _LOCALE_T_DEFINED_ +#define _LOCALE_T_DEFINED_ +typedef void *locale_t; +#endif + +#define LC_COLLATE_MASK (1 << LC_COLLATE) +#define LC_CTYPE_MASK (1 << LC_CTYPE) +#define LC_MONETARY_MASK (1 << LC_MONETARY) +#define LC_NUMERIC_MASK (1 << LC_NUMERIC) +#define LC_TIME_MASK (1 << LC_TIME) +#define LC_MESSAGES_MASK (1 << LC_MESSAGES) + +#define LC_ALL_MASK ((1 << _LC_LAST) - 2) + +#define LC_GLOBAL_LOCALE ((locale_t)-1) + +#endif /* __POSIX_VISIBLE >= 200809 */ + + __BEGIN_DECLS struct lconv *localeconv(void); char *setlocale(int, const char *); + +#if __POSIX_VISIBLE >= 200809 +locale_t duplocale(locale_t); +void freelocale(locale_t); +locale_t newlocale(int, const char *, locale_t); +locale_t uselocale(locale_t); +#endif __END_DECLS #endif /* _LOCALE_H_ */ diff --git a/src/include/stdlib.h b/src/include/stdlib.h index 0374313a..cc359ab3 100644 --- a/src/include/stdlib.h +++ b/src/include/stdlib.h @@ -1,4 +1,4 @@ -/* $OpenBSD: stdlib.h,v 1.71 2017/05/11 11:52:18 tom Exp $ */ +/* $OpenBSD: stdlib.h,v 1.72 2017/09/05 03:16:13 schwarze Exp $ */ /* $NetBSD: stdlib.h,v 1.25 1995/12/27 21:19:08 jtc Exp $ */ /*- @@ -82,8 +82,7 @@ typedef struct { #define RAND_MAX 0x7fffffff -extern size_t __mb_cur_max; -#define MB_CUR_MAX __mb_cur_max +#define MB_CUR_MAX __mb_cur_max() /* * Some header files may define an abs macro. @@ -132,7 +131,7 @@ unsigned long strtoul(const char *__restrict, char **__restrict, int); int system(const char *); -/* these are currently just stubs */ +size_t __mb_cur_max(void); int mblen(const char *, size_t); size_t mbstowcs(wchar_t *, const char *, size_t); int wctomb(char *, wchar_t); diff --git a/src/include/string.h b/src/include/string.h index b4c880ce..9141c300 100644 --- a/src/include/string.h +++ b/src/include/string.h @@ -1,4 +1,4 @@ -/* $OpenBSD: string.h,v 1.31 2016/09/09 18:12:37 millert Exp $ */ +/* $OpenBSD: string.h,v 1.32 2017/09/05 03:16:13 schwarze Exp $ */ /* $NetBSD: string.h,v 1.6 1994/10/26 00:56:30 cgd Exp $ */ /*- @@ -52,6 +52,13 @@ typedef __size_t size_t; #endif +#if __POSIX_VISIBLE >= 200809 +#ifndef _LOCALE_T_DEFINED_ +#define _LOCALE_T_DEFINED_ +typedef void *locale_t; +#endif +#endif + __BEGIN_DECLS void *memchr(const void *, int, size_t); int memcmp(const void *, const void *, size_t); @@ -102,9 +109,13 @@ char *strdup(const char *); #if __POSIX_VISIBLE >= 200809 char *stpcpy(char *__restrict, const char *__restrict); char *stpncpy(char *__restrict, const char *__restrict, size_t); +int strcoll_l(const char *, const char *, locale_t); +char *strerror_l(int, locale_t); char *strndup(const char *, size_t); size_t strnlen(const char *, size_t); char *strsignal(int); +size_t strxfrm_l(char *__restrict, const char *__restrict, size_t, locale_t) + __attribute__ ((__bounded__(__string__,1,3))); #endif #if __BSD_VISIBLE diff --git a/src/include/strings.h b/src/include/strings.h index c9d4856d..7108bbe0 100644 --- a/src/include/strings.h +++ b/src/include/strings.h @@ -1,4 +1,4 @@ -/* $OpenBSD: strings.h,v 1.4 2015/11/20 23:40:32 millert Exp $ */ +/* $OpenBSD: strings.h,v 1.5 2017/09/05 03:16:13 schwarze Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. @@ -47,6 +47,13 @@ typedef __size_t size_t; #endif +#if __POSIX_VISIBLE >= 200809 +#ifndef _LOCALE_T_DEFINED_ +#define _LOCALE_T_DEFINED_ +typedef void *locale_t; +#endif +#endif + __BEGIN_DECLS #if __BSD_VISIBLE || (__XPG_VISIBLE >= 420 && __POSIX_VISIBLE <= 200112) /* @@ -66,6 +73,8 @@ char *rindex(const char *, int); int ffs(int); int strcasecmp(const char *, const char *); int strncasecmp(const char *, const char *, size_t); +int strcasecmp_l(const char *, const char *, locale_t); +int strncasecmp_l(const char *, const char *, size_t, locale_t); #endif __END_DECLS diff --git a/src/include/time.h b/src/include/time.h index a73f9c3a..fc9121e6 100644 --- a/src/include/time.h +++ b/src/include/time.h @@ -1,4 +1,4 @@ -/* $OpenBSD: time.h,v 1.29 2016/09/09 18:12:37 millert Exp $ */ +/* $OpenBSD: time.h,v 1.30 2017/09/05 03:16:13 schwarze Exp $ */ /* $NetBSD: time.h,v 1.9 1994/10/26 00:56:35 cgd Exp $ */ /* @@ -99,6 +99,13 @@ typedef __pid_t pid_t; #endif #endif +#if __POSIX_VISIBLE >= 200809 +#ifndef _LOCALE_T_DEFINED_ +#define _LOCALE_T_DEFINED_ +typedef void *locale_t; +#endif +#endif + struct tm { int tm_sec; /* seconds after the minute [0-60] */ int tm_min; /* minutes after the hour [0-59] */ @@ -160,6 +167,12 @@ int nanosleep(const struct timespec *, struct timespec *); int clock_getcpuclockid(pid_t, clockid_t *); #endif +#if __POSIX_VISIBLE >= 200809 +size_t strftime_l(char *__restrict, size_t, const char *__restrict, + const struct tm *__restrict, locale_t) + __attribute__ ((__bounded__(__string__,1,2))); +#endif + #if __BSD_VISIBLE void tzsetwall(void); time_t timelocal(struct tm *); diff --git a/src/include/wchar.h b/src/include/wchar.h index 7cdee59a..309f812d 100644 --- a/src/include/wchar.h +++ b/src/include/wchar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: wchar.h,v 1.30 2016/09/09 18:12:37 millert Exp $ */ +/* $OpenBSD: wchar.h,v 1.31 2017/09/05 03:16:13 schwarze Exp $ */ /* $NetBSD: wchar.h,v 1.16 2003/03/07 07:11:35 tshiozak Exp $ */ /*- @@ -96,6 +96,13 @@ typedef __size_t size_t; #define WCHAR_MAX 0x7fffffff #endif +#if __POSIX_VISIBLE >= 200809 +#ifndef _LOCALE_T_DEFINED_ +#define _LOCALE_T_DEFINED_ +typedef void *locale_t; +#endif +#endif + __BEGIN_DECLS wint_t btowc(int); size_t mbrlen(const char * __restrict, size_t, mbstate_t * __restrict); @@ -155,9 +162,13 @@ unsigned long int wcstoul(const wchar_t * __restrict, wchar_t ** __restrict, #if __POSIX_VISIBLE >= 200809 FILE *open_wmemstream(wchar_t **, size_t *); +int wcscoll_l(const wchar_t *, const wchar_t *, locale_t); wchar_t *wcsdup(const wchar_t *); int wcscasecmp(const wchar_t *, const wchar_t *); +int wcscasecmp_l(const wchar_t *, const wchar_t *, locale_t); int wcsncasecmp(const wchar_t *, const wchar_t *, size_t); +int wcsncasecmp_l(const wchar_t *, const wchar_t *, size_t, locale_t); +size_t wcsxfrm_l(wchar_t *, const wchar_t *, size_t, locale_t); size_t mbsnrtowcs(wchar_t * __restrict, const char ** __restrict, size_t, size_t, mbstate_t * __restrict) diff --git a/src/include/wctype.h b/src/include/wctype.h index 5d4e5573..bf61d255 100644 --- a/src/include/wctype.h +++ b/src/include/wctype.h @@ -1,4 +1,4 @@ -/* $OpenBSD: wctype.h,v 1.5 2006/01/06 18:53:04 millert Exp $ */ +/* $OpenBSD: wctype.h,v 1.6 2017/09/05 03:16:13 schwarze Exp $ */ /* $NetBSD: wctype.h,v 1.5 2003/03/02 22:18:11 tshiozak Exp $ */ /*- @@ -54,6 +54,13 @@ typedef __wctype_t wctype_t; #define WEOF ((wint_t)-1) #endif +#if __POSIX_VISIBLE >= 200809 +#ifndef _LOCALE_T_DEFINED_ +#define _LOCALE_T_DEFINED_ +typedef void *locale_t; +#endif +#endif + __BEGIN_DECLS int iswalnum(wint_t); int iswalpha(wint_t); @@ -73,6 +80,28 @@ wint_t towlower(wint_t); wint_t towupper(wint_t); wctrans_t wctrans(const char *); wctype_t wctype(const char *); + +#if __POSIX_VISIBLE >= 200809 +int iswalnum_l(wint_t, locale_t); +int iswalpha_l(wint_t, locale_t); +int iswblank_l(wint_t, locale_t); +int iswcntrl_l(wint_t, locale_t); +int iswdigit_l(wint_t, locale_t); +int iswgraph_l(wint_t, locale_t); +int iswlower_l(wint_t, locale_t); +int iswprint_l(wint_t, locale_t); +int iswpunct_l(wint_t, locale_t); +int iswspace_l(wint_t, locale_t); +int iswupper_l(wint_t, locale_t); +int iswxdigit_l(wint_t, locale_t); +int iswctype_l(wint_t, wctype_t, locale_t); +wint_t towctrans_l(wint_t, wctrans_t, locale_t); +wint_t towlower_l(wint_t, locale_t); +wint_t towupper_l(wint_t, locale_t); +wctrans_t wctrans_l(const char *, locale_t); +wctype_t wctype_l(const char *, locale_t); +#endif + __END_DECLS #endif /* _WCTYPE_H_ */ diff --git a/src/lib/libc/string/Makefile.inc b/src/lib/libc/string/Makefile.inc index 95eb9300..a1b1934a 100644 --- a/src/lib/libc/string/Makefile.inc +++ b/src/lib/libc/string/Makefile.inc @@ -1,17 +1,17 @@ -# $OpenBSD: Makefile.inc,v 1.38 2016/03/30 06:38:41 jmc Exp $ +# $OpenBSD: Makefile.inc,v 1.39 2017/09/05 03:16:13 schwarze Exp $ # string sources .PATH: ${LIBCSRCDIR}/arch/${MACHINE_CPU}/string ${LIBCSRCDIR}/string SRCS+= explicit_bzero.c memccpy.c memmem.c memrchr.c stpcpy.c stpncpy.c \ - strcasecmp.c strcasestr.c strcoll.c strdup.c \ - strerror.c strerror_r.c strmode.c strndup.c strnlen.c \ - strsignal.c strtok.c strxfrm.c \ + strcasecmp.c strcasecmp_l.c strcasestr.c strcoll.c strcoll_l.c \ + strdup.c strerror.c strerror_l.c strerror_r.c strmode.c \ + strndup.c strnlen.c strsignal.c strtok.c strxfrm.c strxfrm_l.c \ timingsafe_bcmp.c timingsafe_memcmp.c \ wcscat.c wcschr.c wcscmp.c wcscpy.c wcscspn.c wcslcat.c wcslcpy.c \ wcslen.c wcsncat.c wcsncmp.c wcsncpy.c wcspbrk.c wcsrchr.c wcsspn.c \ wcsstr.c wcstok.c wcswcs.c wcswidth.c wmemchr.c wmemcmp.c wmemcpy.c \ - wmemmove.c wmemset.c wcsdup.c wcscasecmp.c + wmemmove.c wmemset.c wcsdup.c wcscasecmp.c wcscasecmp_l.c # machine-dependent net sources # ../arch/ARCH/Makefile.inc must include sources for: diff --git a/src/lib/libc/string/strcasecmp.3 b/src/lib/libc/string/strcasecmp.3 index 38703622..bb39df89 100644 --- a/src/lib/libc/string/strcasecmp.3 +++ b/src/lib/libc/string/strcasecmp.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: strcasecmp.3,v 1.13 2015/11/24 09:14:35 daniel Exp $ +.\" $OpenBSD: strcasecmp.3,v 1.14 2017/09/05 03:16:13 schwarze Exp $ .\" .\" Copyright (c) 1990, 1991, 1993 .\" The Regents of the University of California. All rights reserved. +.\" Copyright (c) 2017 Ingo Schwarze .\" .\" This code is derived from software contributed to Berkeley by .\" Chris Torek. @@ -31,25 +32,43 @@ .\" .\" @(#)strcasecmp.3 8.1 (Berkeley) 6/9/93 .\" -.Dd $Mdocdate: November 24 2015 $ +.Dd $Mdocdate: September 5 2017 $ .Dt STRCASECMP 3 .Os .Sh NAME .Nm strcasecmp , -.Nm strncasecmp +.Nm strcasecmp_l , +.Nm strncasecmp , +.Nm strncasecmp_l .Nd compare strings, ignoring case .Sh SYNOPSIS .In strings.h .Ft int -.Fn strcasecmp "const char *s1" "const char *s2" +.Fo strcasecmp +.Fa "const char *s1" +.Fa "const char *s2" +.Fc .Ft int -.Fn strncasecmp "const char *s1" "const char *s2" "size_t len" +.Fo strcasecmp_l +.Fa "const char *s1" +.Fa "const char *s2" +.Fa "locale_t locale" +.Fc +.Ft int +.Fo strncasecmp +.Fa "const char *s1" +.Fa "const char *s2" +.Fa "size_t len" +.Fc +.Ft int +.Fo strncasecmp_l +.Fa "const char *s1" +.Fa "const char *s2" +.Fa "size_t len" +.Fa "locale_t locale" +.Fc .Sh DESCRIPTION -The -.Fn strcasecmp -and -.Fn strncasecmp -functions compare the NUL-terminated strings +These functions compare the NUL-terminated strings .Fa s1 and .Fa s2 @@ -66,27 +85,44 @@ is greater than .Ql \e0 . .Pp .Fn strncasecmp -compares at most +and +.Fn strncasecmp_l +compare at most .Fa len characters. +.Pp +On +.Ox , +these functions always use the C locale and ignore +the global locale, the thread-specific locale, and the +.Fa locale +argument. +.Sh ENVIRONMENT +On other operating systems, the behaviour of +.Fn strcasecmp +and +.Fn strncasecmp +may depend on the +.Dv LC_CTYPE +.Xr locale 1 . .Sh SEE ALSO -.Xr bcmp 3 , -.Xr memcmp 3 , .Xr strcmp 3 , .Xr strcoll 3 , .Xr strxfrm 3 , .Xr wcscasecmp 3 .Sh STANDARDS -The -.Fn strcasecmp -and -.Fn strncasecmp -functions conform to +These functions conform to .St -p1003.1-2008 . .Sh HISTORY The .Fn strcasecmp and .Fn strncasecmp -functions first appeared in -.Bx 4.3 Tahoe . +functions have been available since +.Bx 4.3 Tahoe , +and +.Fn strcasecmp_l +and +.Fn strncasecmp_l +since +.Ox 6.2 . diff --git a/src/lib/libc/string/strcasecmp_l.c b/src/lib/libc/string/strcasecmp_l.c new file mode 100644 index 00000000..a9543dda --- /dev/null +++ b/src/lib/libc/string/strcasecmp_l.c @@ -0,0 +1,21 @@ +/* $OpenBSD: strcasecmp_l.c,v 1.1 2017/09/05 03:16:13 schwarze Exp $ */ +/* + * Written in 2017 by Ingo Schwarze . + * Released into the public domain. + */ + +#include + +int +strcasecmp_l(const char *s1, const char *s2, + locale_t locale __attribute__((__unused__))) +{ + return strcasecmp(s1, s2); +} + +int +strncasecmp_l(const char *s1, const char *s2, size_t n, + locale_t locale __attribute__((__unused__))) +{ + return strncasecmp(s1, s2, n); +} diff --git a/src/lib/libc/string/strcoll.3 b/src/lib/libc/string/strcoll.3 index d421200b..4ba1f226 100644 --- a/src/lib/libc/string/strcoll.3 +++ b/src/lib/libc/string/strcoll.3 @@ -1,4 +1,7 @@ +.\" $OpenBSD: strcoll.3,v 1.10 2017/09/05 03:16:13 schwarze Exp $ +.\" .\" Copyright (c) 1990, 1991 The Regents of the University of California. +.\" Copyright (c) 2017 Ingo Schwarze .\" All rights reserved. .\" .\" This code is derived from software contributed to Berkeley by @@ -29,45 +32,69 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $OpenBSD: strcoll.3,v 1.9 2013/06/05 03:39:23 tedu Exp $ -.\" -.Dd $Mdocdate: June 5 2013 $ +.Dd $Mdocdate: September 5 2017 $ .Dt STRCOLL 3 .Os .Sh NAME -.Nm strcoll +.Nm strcoll , +.Nm strcoll_l .Nd compare strings according to current collation .Sh SYNOPSIS .In string.h .Ft int .Fn strcoll "const char *s1" "const char *s2" +.Ft int +.Fn strcoll_l "const char *s1" "const char *s2" "locale_t locale" .Sh DESCRIPTION The .Fn strcoll -function lexicographically compares the NUL-terminated strings +and +.Fn strcoll_l +functions lexicographically compare the NUL-terminated strings .Fa s1 and .Fa s2 according to the current locale collation -and returns an integer greater than, equal to, or less than 0, +and return an integer greater than, equal to, or less than 0, according to whether .Fa s1 is greater than, equal to, or less than .Fa s2 . +.Pp +On +.Ox , +they have the same effect as +.Xr strcmp 3 , +and the global locale, the thread-specific locale, and the +.Fa locale +argument are ignored. +.Sh ENVIRONMENT +On other operating systems, the behaviour of +.Fn strcoll +may depend on the +.Dv LC_CTYPE +.Xr locale 1 . .Sh SEE ALSO -.Xr bcmp 3 , -.Xr memcmp 3 , +.Xr newlocale 3 , .Xr setlocale 3 , -.Xr strcasecmp 3 , .Xr strcmp 3 , -.Xr strxfrm 3 +.Xr strxfrm 3 , +.Xr wcscoll 3 .Sh STANDARDS The .Fn strcoll function conforms to -.St -ansiC . +.St -ansiC , +and +.Fn strcoll_l +to +.St -p1003.1-2008 . .Sh HISTORY The .Fn strcoll -function first appeared in -.Bx 4.3 Reno . +function has been available since +.Bx 4.3 Reno , +and +.Fn strcoll_l +since +.Ox 6.2 . diff --git a/src/lib/libc/string/strcoll_l.c b/src/lib/libc/string/strcoll_l.c new file mode 100644 index 00000000..bcd5b0f4 --- /dev/null +++ b/src/lib/libc/string/strcoll_l.c @@ -0,0 +1,14 @@ +/* $OpenBSD: strcoll_l.c,v 1.1 2017/09/05 03:16:13 schwarze Exp $ */ +/* + * Written in 2017 by Ingo Schwarze . + * Released into the public domain. + */ + +#include + +int +strcoll_l(const char *s1, const char *s2, + locale_t locale __attribute__((__unused__))) +{ + return strcmp(s1, s2); +} diff --git a/src/lib/libc/string/strerror.3 b/src/lib/libc/string/strerror.3 index 8b2d32ea..0d4f084e 100644 --- a/src/lib/libc/string/strerror.3 +++ b/src/lib/libc/string/strerror.3 @@ -1,4 +1,7 @@ +.\" $OpenBSD: strerror.3,v 1.15 2017/09/05 03:16:13 schwarze Exp $ +.\" .\" Copyright (c) 1980, 1991 Regents of the University of California. +.\" Copyright (c) 2017 Ingo Schwarze .\" All rights reserved. .\" .\" This code is derived from software contributed to Berkeley by @@ -29,46 +32,61 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $OpenBSD: strerror.3,v 1.14 2014/11/30 21:21:59 schwarze Exp $ -.\" -.Dd $Mdocdate: November 30 2014 $ +.Dd $Mdocdate: September 5 2017 $ .Dt STRERROR 3 .Os .Sh NAME .Nm strerror , +.Nm strerror_l , .Nm strerror_r .Nd get error message string .Sh SYNOPSIS .In string.h .Ft char * .Fn strerror "int errnum" +.Ft char * +.Fn strerror_l "int errnum" "locale_t locale" .Ft int .Fn strerror_r "int errnum" "char *strerrbuf" "size_t buflen" .Sh DESCRIPTION -The -.Fn strerror -and -.Fn strerror_r -functions map the error number +These functions map the error number .Fa errnum -to a language-dependent error message string. +to an error message string. .Pp .Fn strerror -returns a string containing a maximum of +and +.Fn strerror_l +return a string containing a maximum of .Dv NL_TEXTMAX characters, including the trailing NUL. -This string is not to be modified by the calling program, -but may be overwritten by subsequent calls to -.Fn strerror . +This string is not to be modified by the calling program. +The string returned by +.Fn strerror +may be overwritten by subsequent calls to +.Fn strerror +in any thread. +The string returned by +.Fn strerror_l +may be overwritten by subsequent calls to +.Fn strerror_l +in the same thread. .Pp .Fn strerror_r is a thread safe version of .Fn strerror that places the error message in the specified buffer .Fa strerrbuf . +.Pp +On +.Ox , +the global locale, the thread-specific locale, and the +.Fa locale +argument are ignored. .Sh RETURN VALUES .Fn strerror -returns a pointer to the error message string. +and +.Fn strerror_l +return a pointer to the error message string. If an error occurs, the error code is stored in .Va errno . .Pp @@ -77,11 +95,16 @@ returns zero upon successful completion. If an error occurs, the error code is stored in .Va errno and the error code is returned. -.Sh ERRORS +.Sh ENVIRONMENT +On other operating systems, the behaviour of .Fn strerror and .Fn strerror_r -may fail if: +may depend on the +.Dv LC_MESSAGES +.Xr locale 1 . +.Sh ERRORS +All these functions may fail if: .Bl -tag -width Er .It Bq Er EINVAL .Fa errnum @@ -91,7 +114,7 @@ The returned error string will consist of an error message that includes .El .Pp .Fn strerror_r -may fail if: +may also fail if: .Bl -tag -width Er .It Bq Er ERANGE The error message is larger than @@ -101,6 +124,7 @@ The message will be truncated to fit. .El .Sh SEE ALSO .Xr intro 2 , +.Xr newlocale 3 , .Xr perror 3 , .Xr setlocale 3 .Sh STANDARDS @@ -109,15 +133,20 @@ The function conforms to .St -isoC-99 . The +.Fn strerror_l +and .Fn strerror_r -function conforms to +functions conform to .St -p1003.1-2008 . .Sh HISTORY The .Fn strerror -function first appeared in -.Bx 4.3 Reno . -The +function has been available since +.Bx 4.3 Reno , .Fn strerror_r -function first appeared in -.Ox 3.3 . +since +.Ox 3.3 , +and +.Fn strerror_l +since +.Ox 6.2 . diff --git a/src/lib/libc/string/strerror_l.c b/src/lib/libc/string/strerror_l.c new file mode 100644 index 00000000..c16be7a0 --- /dev/null +++ b/src/lib/libc/string/strerror_l.c @@ -0,0 +1,33 @@ +/* $OpenBSD: strerror_l.c,v 1.1 2017/09/05 03:16:13 schwarze Exp $ */ +/* + * Copyright (c) 2017 Ingo Schwarze + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include "thread_private.h" + +char * +strerror_l(int errnum, locale_t locale) +{ + static char sel_buf[NL_TEXTMAX]; + _THREAD_PRIVATE_KEY(strerror_l); + char *p = _THREAD_PRIVATE(strerror_l, sel_buf, NULL); + + return p == NULL ? "no buffer available in strerror_l" : + strerror_r(errnum, p, sizeof(sel_buf)) ? + "strerror_r failure" : p; +} diff --git a/src/lib/libc/string/strxfrm.3 b/src/lib/libc/string/strxfrm.3 index 481f741c..1a96c851 100644 --- a/src/lib/libc/string/strxfrm.3 +++ b/src/lib/libc/string/strxfrm.3 @@ -1,4 +1,7 @@ +.\" $OpenBSD: strxfrm.3,v 1.11 2017/09/05 03:16:13 schwarze Exp $ +.\" .\" Copyright (c) 1990, 1991 The Regents of the University of California. +.\" Copyright (c) 2017 Ingo Schwarze .\" All rights reserved. .\" .\" This code is derived from software contributed to Berkeley by @@ -29,24 +32,27 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $OpenBSD: strxfrm.3,v 1.10 2013/06/05 03:39:23 tedu Exp $ -.\" -.Dd $Mdocdate: June 5 2013 $ +.Dd $Mdocdate: September 5 2017 $ .Dt STRXFRM 3 .Os .Sh NAME -.Nm strxfrm +.Nm strxfrm , +.Nm strxfrm_l .Nd transform a string under locale .Sh SYNOPSIS .In string.h .Ft size_t .Fn strxfrm "char *dst" "const char *src" "size_t n" +.Ft size_t +.Fn strxfrm_l "char *dst" "const char *src" "size_t n" "locale_t locale" .Sh DESCRIPTION The idea of .Fn strxfrm +and +.Fn strxfrm_l is to .Dq un-localize -a string: the function transforms +a string: the functions transform .Ar src , storing the result in .Ar dst , @@ -55,25 +61,42 @@ such that on transformed strings returns what .Xr strcoll 3 on the original untransformed strings would return. +.Pp +On +.Ox , +both have the same effect as +.Xr strlcpy 3 , +and the global locale, the thread-specific locale, and the +.Fa locale +argument are ignored. +.Sh ENVIRONMENT +On other operating systems, the behaviour of +.Fn strxfrm +may depend on the +.Dv LC_CTYPE +.Xr locale 1 . .Sh SEE ALSO -.Xr bcmp 3 , -.Xr memcmp 3 , +.Xr newlocale 3 , .Xr setlocale 3 , -.Xr strcasecmp 3 , .Xr strcmp 3 , -.Xr strcoll 3 +.Xr strcoll 3 , +.Xr strlcpy 3 , +.Xr wcsxfrm 3 .Sh STANDARDS The .Fn strxfrm function conforms to -.St -ansiC . +.St -ansiC , +and +.Fn strxfrm_l +to +.St -p1003.1-2008 . .Sh HISTORY The .Fn strxfrm -function first appeared in -.Bx 4.3 Reno . -.Sh BUGS -Since locales are not fully implemented on -.Ox , -.Fn strxfrm -just returns a copy of the original string. +function has been available since +.Bx 4.3 Reno , +and +.Fn strxfrm_l +since +.Ox 6.2 . diff --git a/src/lib/libc/string/strxfrm_l.c b/src/lib/libc/string/strxfrm_l.c new file mode 100644 index 00000000..ff779479 --- /dev/null +++ b/src/lib/libc/string/strxfrm_l.c @@ -0,0 +1,14 @@ +/* $OpenBSD: strxfrm_l.c,v 1.1 2017/09/05 03:16:14 schwarze Exp $ */ +/* + * Written in 2017 by Ingo Schwarze . + * Released into the public domain. + */ + +#include + +size_t +strxfrm_l(char *dst, const char *src, size_t n, + locale_t locale __attribute__((__unused__))) +{ + return strxfrm(dst, src, n); +} diff --git a/src/lib/libc/string/wcscasecmp.3 b/src/lib/libc/string/wcscasecmp.3 index daf397ae..9db4a829 100644 --- a/src/lib/libc/string/wcscasecmp.3 +++ b/src/lib/libc/string/wcscasecmp.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: wcscasecmp.3,v 1.4 2013/07/16 15:21:11 schwarze Exp $ +.\" $OpenBSD: wcscasecmp.3,v 1.5 2017/09/05 03:16:14 schwarze Exp $ .\" .\" Copyright (c) 1990, 1991, 1993 .\" The Regents of the University of California. All rights reserved. +.\" Copyright (c) 2017 Ingo Schwarze .\" .\" This code is derived from software contributed to Berkeley by .\" Chris Torek. @@ -31,25 +32,43 @@ .\" .\" @(#)strcasecmp.3 8.1 (Berkeley) 6/9/93 .\" -.Dd $Mdocdate: July 16 2013 $ +.Dd $Mdocdate: September 5 2017 $ .Dt WCSCASECMP 3 .Os .Sh NAME .Nm wcscasecmp , -.Nm wcsncasecmp +.Nm wcscasecmp_l , +.Nm wcsncasecmp , +.Nm wcsncasecmp_l .Nd compare wide strings, ignoring case .Sh SYNOPSIS .In wchar.h .Ft int -.Fn wcscasecmp "const wchar_t *s1" "const wchar_t *s2" +.Fo wcscasecmp +.Fa "const wchar_t *s1" +.Fa "const wchar_t *s2" +.Fc .Ft int -.Fn wcsncasecmp "const wchar_t *s1" "const wchar_t *s2" "size_t len" +.Fo wcscasecmp_l +.Fa "const wchar_t *s1" +.Fa "const wchar_t *s2" +.Fa "locale_t locale" +.Fc +.Ft int +.Fo wcsncasecmp +.Fa "const wchar_t *s1" +.Fa "const wchar_t *s2" +.Fa "size_t len" +.Fc +.Ft int +.Fo wcsncasecmp_l +.Fa "const wchar_t *s1" +.Fa "const wchar_t *s2" +.Fa "size_t len" +.Fa "locale_t locale" +.Fc .Sh DESCRIPTION -The -.Fn wcscasecmp -and -.Fn wcsncasecmp -functions compare the wide strings +These functions compare the wide strings .Fa s1 and .Fa s2 @@ -61,28 +80,49 @@ is lexicographically greater than, equal to, or less than after translation of each corresponding wide character to lower case. The wide strings themselves are not modified. .Pp +For the translation to lower case, +.Fn wcscasecmp +and +.Fn wcsncasecmp +use the thread-specific locale as defined with +.Xr uselocale 3 , +falling back to the global locale defined with +.Xr setlocale 3 . +.Fn wcscasecmp_l +and +.Fn wcsncasecmp_l +use the +.Fa locale +argument instead. +.Pp .Fn wcsncasecmp -compares at most +and +.Fn wcsncasecmp_l +compare at most .Fa len wide characters. .Sh SEE ALSO +.Xr newlocale 3 , +.Xr setlocale 3 , .Xr strcasecmp 3 , .Xr wcscmp 3 , .Xr wmemcmp 3 .Sh STANDARDS -The -.Fn wcscasecmp -and -.Fn wcsncasecmp -functions conform to +These functions conform to .St -p1003.1-2008 . .Sh HISTORY The .Fn wcscasecmp and .Fn wcsncasecmp -functions first appeared in -.Ox 5.0 . +functions have been available since +.Ox 5.0 , +and +.Fn wcscasecmp_l +and +.Fn wcsncasecmp_l +since +.Ox 6.2 . .Sh AUTHORS The .Ox diff --git a/src/lib/libc/string/wcscasecmp_l.c b/src/lib/libc/string/wcscasecmp_l.c new file mode 100644 index 00000000..35b99225 --- /dev/null +++ b/src/lib/libc/string/wcscasecmp_l.c @@ -0,0 +1,63 @@ +/* $OpenBSD: wcscasecmp_l.c,v 1.1 2017/09/05 03:16:14 schwarze Exp $ */ + +/* + * Copyright (c) 2011 Marc Espie + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD + * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "locale/runetype.h" + +int +wcscasecmp_l(const wchar_t *s1, const wchar_t *s2, locale_t locale) +{ + wchar_t l1, l2; + + while ((l1 = towlower_l(*s1++, locale)) == + (l2 = towlower_l(*s2++, locale))) { + if (l1 == 0) + return (0); + } + /* XXX assumes wchar_t = int */ + return ((rune_t)l1 - (rune_t)l2); +} + +int +wcsncasecmp_l(const wchar_t *s1, const wchar_t *s2, size_t n, locale_t locale) +{ + wchar_t l1, l2; + + if (n == 0) + return (0); + do { + if (((l1 = towlower_l(*s1++, locale))) != + (l2 = towlower_l(*s2++, locale))) { + /* XXX assumes wchar_t = int */ + return ((rune_t)l1 - (rune_t)l2); + } + if (l1 == 0) + break; + } while (--n != 0); + return (0); +}