Module Name: src
Committed By: joerg
Date: Sat Jun 8 21:35:18 UTC 2024
Modified Files:
src/lib/libc/locale: global_locale.c setlocale.c setlocale_local.h
src/lib/libc/string: Makefile.inc strerror_r.c
Log Message:
Redo l10n support in the strerror family.
Instead of opening the message catelog whenever strerror is called,
keep track of the translations in the locale cache. For the C locale,
the builtin sys_errlist is used directly. Other locales will open
the catalog file on the first strerror call and build a translation
table, so that further calls in this locale can just use an array
lookup.
To generate a diff of this commit:
cvs rdiff -u -r1.28 -r1.29 src/lib/libc/locale/global_locale.c
cvs rdiff -u -r1.65 -r1.66 src/lib/libc/locale/setlocale.c
cvs rdiff -u -r1.17 -r1.18 src/lib/libc/locale/setlocale_local.h
cvs rdiff -u -r1.89 -r1.90 src/lib/libc/string/Makefile.inc
cvs rdiff -u -r1.5 -r1.6 src/lib/libc/string/strerror_r.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/lib/libc/locale/global_locale.c
diff -u src/lib/libc/locale/global_locale.c:1.28 src/lib/libc/locale/global_locale.c:1.29
--- src/lib/libc/locale/global_locale.c:1.28 Fri Jun 7 13:53:23 2024
+++ src/lib/libc/locale/global_locale.c Sat Jun 8 21:35:18 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: global_locale.c,v 1.28 2024/06/07 13:53:23 riastradh Exp $ */
+/* $NetBSD: global_locale.c,v 1.29 2024/06/08 21:35:18 joerg Exp $ */
/*-
* Copyright (c)2008 Citrus Project,
@@ -28,12 +28,15 @@
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: global_locale.c,v 1.28 2024/06/07 13:53:23 riastradh Exp $");
+__RCSID("$NetBSD: global_locale.c,v 1.29 2024/06/08 21:35:18 joerg Exp $");
#endif /* LIBC_SCCS and not lint */
+#include "namespace.h"
+
#include <sys/types.h>
#include <sys/ctype_bits.h>
#include <sys/localedef.h>
+#include <errno.h>
#include <langinfo.h>
#include <limits.h>
#define __SETLOCALE_SOURCE__
@@ -137,6 +140,9 @@ __dso_hidden const struct _locale_cache_
},
.monetary_name = _lc_C_locale_name,
.numeric_name = _lc_C_locale_name,
+ .message_name = _lc_C_locale_name,
+ .errlistp = &sys_errlist,
+ .errlist_prefix = "Unknown error: %d",
};
struct _locale _lc_global_locale = {
Index: src/lib/libc/locale/setlocale.c
diff -u src/lib/libc/locale/setlocale.c:1.65 src/lib/libc/locale/setlocale.c:1.66
--- src/lib/libc/locale/setlocale.c:1.65 Thu Jan 4 20:57:29 2018
+++ src/lib/libc/locale/setlocale.c Sat Jun 8 21:35:18 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: setlocale.c,v 1.65 2018/01/04 20:57:29 kamil Exp $ */
+/* $NetBSD: setlocale.c,v 1.66 2024/06/08 21:35:18 joerg Exp $ */
/*-
* Copyright (c)2008 Citrus Project,
@@ -28,7 +28,7 @@
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: setlocale.c,v 1.65 2018/01/04 20:57:29 kamil Exp $");
+__RCSID("$NetBSD: setlocale.c,v 1.66 2024/06/08 21:35:18 joerg Exp $");
#endif /* LIBC_SCCS and not lint */
#include "namespace.h"
@@ -65,6 +65,7 @@ _setlocale_cache(locale_t loc, struct _l
{
const char *monetary_name = loc->part_name[LC_MONETARY];
const char *numeric_name = loc->part_name[LC_NUMERIC];
+ const char *message_name = loc->part_name[LC_MESSAGES];
_NumericLocale *numeric = loc->part_impl[LC_NUMERIC];
_MonetaryLocale *monetary = loc->part_impl[LC_MONETARY];
struct lconv *ldata;
@@ -78,6 +79,9 @@ _setlocale_cache(locale_t loc, struct _l
if (numeric_name != old_cache->numeric_name &&
strcmp(numeric_name, old_cache->numeric_name) != 0)
continue;
+ if (message_name != old_cache->message_name &&
+ strcmp(message_name, old_cache->message_name) != 0)
+ continue;
loc->cache = old_cache;
free(cache);
return 0;
@@ -91,6 +95,10 @@ _setlocale_cache(locale_t loc, struct _l
cache->monetary_name = monetary_name;
cache->numeric_name = numeric_name;
+ cache->message_name = message_name;
+ cache->errlist = NULL;
+ cache->errlistp = &cache->errlist;
+ cache->errlist_prefix = NULL;
ldata = &cache->ldata;
ldata->decimal_point = __UNCONST(numeric->decimal_point);
Index: src/lib/libc/locale/setlocale_local.h
diff -u src/lib/libc/locale/setlocale_local.h:1.17 src/lib/libc/locale/setlocale_local.h:1.18
--- src/lib/libc/locale/setlocale_local.h:1.17 Fri Apr 29 16:26:48 2016
+++ src/lib/libc/locale/setlocale_local.h Sat Jun 8 21:35:18 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: setlocale_local.h,v 1.17 2016/04/29 16:26:48 joerg Exp $ */
+/* $NetBSD: setlocale_local.h,v 1.18 2024/06/08 21:35:18 joerg Exp $ */
/*-
* Copyright (c)2008 Citrus Project,
@@ -48,7 +48,11 @@ struct _locale_cache_t {
SLIST_ENTRY(_locale_cache_t) cache_link;
const char *monetary_name;
const char *numeric_name;
+ const char *message_name;
struct lconv ldata;
+ const char * errlist_prefix;
+ const char * const *errlist;
+ const char * const **errlistp;
};
struct _locale {
Index: src/lib/libc/string/Makefile.inc
diff -u src/lib/libc/string/Makefile.inc:1.89 src/lib/libc/string/Makefile.inc:1.90
--- src/lib/libc/string/Makefile.inc:1.89 Fri Aug 11 13:07:17 2023
+++ src/lib/libc/string/Makefile.inc Sat Jun 8 21:35:18 2024
@@ -1,5 +1,5 @@
# from: @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
-# $NetBSD: Makefile.inc,v 1.89 2023/08/11 13:07:17 ryoon Exp $
+# $NetBSD: Makefile.inc,v 1.90 2024/06/08 21:35:18 joerg Exp $
# string sources
.PATH: ${ARCHDIR}/string ${.CURDIR}/string
@@ -40,6 +40,8 @@ CPPFLAGS.wmemcmp.c+= -I${LIBCDIR}/locale
# to recurse and blow the stack.
COPTS.memset.c+= ${${ACTIVE_CC} == "gcc":? -fno-builtin :}
+COPTS.strerror_r.c+= -Wno-format-nonliteral
+
.include "${ARCHDIR}/string/Makefile.inc"
MAN+= bm.3 bcmp.3 bcopy.3 bstring.3 bzero.3 consttime_memequal.3 \
Index: src/lib/libc/string/strerror_r.c
diff -u src/lib/libc/string/strerror_r.c:1.5 src/lib/libc/string/strerror_r.c:1.6
--- src/lib/libc/string/strerror_r.c:1.5 Wed Mar 25 16:15:41 2020
+++ src/lib/libc/string/strerror_r.c Sat Jun 8 21:35:18 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: strerror_r.c,v 1.5 2020/03/25 16:15:41 kre Exp $ */
+/* $NetBSD: strerror_r.c,v 1.6 2024/06/08 21:35:18 joerg Exp $ */
/*
* Copyright (c) 1988 Regents of the University of California.
@@ -30,12 +30,14 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: strerror_r.c,v 1.5 2020/03/25 16:15:41 kre Exp $");
+__RCSID("$NetBSD: strerror_r.c,v 1.6 2024/06/08 21:35:18 joerg Exp $");
#include "namespace.h"
#include <assert.h>
+#include <atomic.h>
#include <errno.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <stdio.h> /* for sys_nerr on FreeBSD */
#ifdef NLS
@@ -48,33 +50,97 @@ __RCSID("$NetBSD: strerror_r.c,v 1.5 202
#include "extern.h"
+#define UPREFIX "Unknown error: %d"
+
__weak_alias(strerror_r, _strerror_r)
+#ifdef NLS
+static void
+load_errlist(locale_t loc)
+{
+ const char **errlist;
+ char *errlist_prefix;
+ int i;
+ nl_catd catd;
+ catd = catopen_l("libc", NL_CAT_LOCALE, loc);
+
+ if (loc->cache->errlist_prefix == NULL) {
+ errlist_prefix = strdup(catgets(catd, 1, 0xffff, UPREFIX));
+ if (errlist_prefix == NULL)
+ goto cleanup2;
+
+ membar_release();
+ if (atomic_cas_ptr(__UNCONST(&loc->cache->errlist_prefix),
+ NULL, errlist_prefix) != NULL)
+ free(errlist_prefix);
+ }
+
+ if (loc->cache->errlist)
+ goto cleanup2;
+
+ errlist = calloc(sys_nerr, sizeof(*errlist));
+ if (errlist == NULL)
+ goto cleanup2;
+ for (i = 0; i < sys_nerr; ++i) {
+ errlist[i] = strdup(catgets(catd, 1, i, sys_errlist[i]));
+ if (errlist[i] == NULL)
+ goto cleanup;
+ }
+ membar_release();
+ if (atomic_cas_ptr(__UNCONST(&loc->cache->errlist), NULL, errlist) != NULL)
+ goto cleanup;
+ goto cleanup2;
+
+ cleanup:
+ for (i = 0; i < sys_nerr; ++i)
+ free(__UNCONST(errlist[i]));
+ free(errlist);
+ cleanup2:
+ catclose(catd);
+}
+#endif
+
int
_strerror_lr(int num, char *buf, size_t buflen, locale_t loc)
{
-#define UPREFIX "Unknown error: %d"
unsigned int errnum = num;
int retval = 0;
size_t slen;
int saved_errno = errno;
#ifdef NLS
- nl_catd catd;
- catd = catopen_l("libc", NL_CAT_LOCALE, loc);
+ const char * const *errlist;
+ const char *errlist_prefix;
#endif
+
_DIAGASSERT(buf != NULL);
if (errnum < (unsigned int) sys_nerr) {
#ifdef NLS
- slen = strlcpy(buf, catgets(catd, 1, num,
- sys_errlist[errnum]), buflen);
+ errlist = *loc->cache->errlistp;
+ membar_datadep_consumer();
+ if (errlist == NULL) {
+ load_errlist(loc);
+ errlist = *loc->cache->errlistp;
+ membar_datadep_consumer();
+ if (errlist == NULL)
+ errlist = *LC_C_LOCALE->cache->errlistp;
+ }
+ slen = strlcpy(buf, errlist[errnum], buflen);
#else
- slen = strlcpy(buf, sys_errlist[errnum], buflen);
+ slen = strlcpy(buf, sys_errlist[errnum], buflen);
#endif
} else {
#ifdef NLS
- slen = snprintf_l(buf, buflen, loc,
- catgets(catd, 1, 0xffff, UPREFIX), num);
+ errlist_prefix = loc->cache->errlist_prefix;
+ membar_datadep_consumer();
+ if (errlist_prefix == NULL) {
+ load_errlist(loc);
+ errlist_prefix = loc->cache->errlist_prefix;
+ membar_datadep_consumer();
+ if (errlist_prefix == NULL)
+ errlist_prefix = LC_C_LOCALE->cache->errlist_prefix;
+ }
+ slen = snprintf_l(buf, buflen, loc, errlist_prefix, num);
#else
slen = snprintf(buf, buflen, UPREFIX, num);
#endif
@@ -84,9 +150,6 @@ _strerror_lr(int num, char *buf, size_t
if (slen >= buflen)
retval = ERANGE;
-#ifdef NLS
- catclose(catd);
-#endif
errno = saved_errno;
return retval;