--- lmessages.c.orig 2004-11-25 11:38:17.000000000 -0800 +++ lmessages.c 2005-02-17 10:13:34.000000000 -0800 @@ -27,7 +27,10 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD: src/lib/libc/locale/lmessages.c,v 1.14 2003/06/26 10:46:16 phantom Exp $"); +#include "xlocale_private.h" + #include <stddef.h> +#include <string.h> #include "ldpart.h" #include "lmessages.h" @@ -45,47 +48,76 @@ "no" /* nostr */ }; -static struct lc_messages_T _messages_locale; -static int _messages_using_locale; -static char *_messages_locale_buf; - -int -__messages_load_locale(const char *name) +__private_extern__ int +__messages_load_locale(const char *name, locale_t loc) { int ret; + struct __xlocale_st_messages *xp; + static struct __xlocale_st_messages *cache = NULL; + + /* 'name' must be already checked. */ + if (strcmp(name, "C") == 0 || strcmp(name, "POSIX") == 0) { + loc->_messages_using_locale = 0; + XL_RELEASE(loc->__lc_messages); + loc->__lc_messages = NULL; + return (_LDP_CACHE); + } - ret = __part_load_locale(name, &_messages_using_locale, - &_messages_locale_buf, "LC_MESSAGES", + /* + * If the locale name is the same as our cache, use the cache. + */ + if (cache && cache->_messages_locale_buf && strcmp(name, cache->_messages_locale_buf) == 0) { + loc->_messages_using_locale = 1; + XL_RELEASE(loc->__lc_messages); + loc->__lc_messages = cache; + XL_RETAIN(loc->__lc_messages); + return (_LDP_CACHE); + } + if ((xp = (struct __xlocale_st_messages *)malloc(sizeof(*xp))) == NULL) + return _LDP_ERROR; + xp->__refcount = 1; + xp->__free_extra = (__free_extra_t)__ldpart_free_extra; + xp->_messages_locale_buf = NULL; + + ret = __part_load_locale(name, &loc->_messages_using_locale, + &xp->_messages_locale_buf, "LC_MESSAGES/LC_MESSAGES", LCMESSAGES_SIZE_FULL, LCMESSAGES_SIZE_MIN, - (const char **)&_messages_locale); + (const char **)&xp->_messages_locale); if (ret == _LDP_LOADED) { - if (_messages_locale.yesstr == NULL) - _messages_locale.yesstr = empty; - if (_messages_locale.nostr == NULL) - _messages_locale.nostr = empty; - } + if (xp->_messages_locale.yesstr == NULL) + xp->_messages_locale.yesstr = empty; + if (xp->_messages_locale.nostr == NULL) + xp->_messages_locale.nostr = empty; + XL_RELEASE(loc->__lc_messages); + loc->__lc_messages = xp; + XL_RELEASE(cache); + cache = xp; + XL_RETAIN(cache); + } else if (ret == _LDP_ERROR) + free(xp); return (ret); } -struct lc_messages_T * -__get_current_messages_locale(void) +__private_extern__ struct lc_messages_T * +__get_current_messages_locale(locale_t loc) { - return (_messages_using_locale - ? &_messages_locale + return (loc->_messages_using_locale + ? &loc->__lc_messages->_messages_locale : (struct lc_messages_T *)&_C_messages_locale); } #ifdef LOCALE_DEBUG void msgdebug() { +locale_t loc = __current_locale(); printf( "yesexpr = %s\n" "noexpr = %s\n" "yesstr = %s\n" "nostr = %s\n", - _messages_locale.yesexpr, - _messages_locale.noexpr, - _messages_locale.yesstr, - _messages_locale.nostr + loc->__lc_messages->_messages_locale.yesexpr, + loc->__lc_messages->_messages_locale.noexpr, + loc->__lc_messages->_messages_locale.yesstr, + loc->__lc_messages->_messages_locale.nostr ); } #endif /* LOCALE_DEBUG */