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;