1/* 2 * Copyright (c) 2001 Alexey Zelkin <phantom@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: src/lib/libc/locale/lmessages.c,v 1.14 2003/06/26 10:46:16 phantom Exp $"); 29 30#include "xlocale_private.h" 31 32#include <stddef.h> 33#include <string.h> 34 35#include "ldpart.h" 36#include "lmessages.h" 37 38#define LCMESSAGES_SIZE_FULL (sizeof(struct lc_messages_T) / sizeof(char *)) 39#define LCMESSAGES_SIZE_MIN \ 40 (offsetof(struct lc_messages_T, yesstr) / sizeof(char *)) 41 42static char empty[] = ""; 43 44static const struct lc_messages_T _C_messages_locale = { 45 "^[yY]" , /* yesexpr */ 46 "^[nN]" , /* noexpr */ 47 "yes" , /* yesstr */ 48 "no" /* nostr */ 49}; 50 51__private_extern__ int 52__messages_load_locale(const char *name, locale_t loc) 53{ 54 int ret; 55 struct __xlocale_st_messages *xp; 56 static struct __xlocale_st_messages *cache = NULL; 57 58 /* 'name' must be already checked. */ 59 if (strcmp(name, "C") == 0 || strcmp(name, "POSIX") == 0) { 60 loc->_messages_using_locale = 0; 61 XL_RELEASE(loc->__lc_messages); 62 loc->__lc_messages = NULL; 63 return (_LDP_CACHE); 64 } 65 66 /* 67 * If the locale name is the same as our cache, use the cache. 68 */ 69 if (cache && cache->_messages_locale_buf && strcmp(name, cache->_messages_locale_buf) == 0) { 70 loc->_messages_using_locale = 1; 71 XL_RELEASE(loc->__lc_messages); 72 loc->__lc_messages = cache; 73 XL_RETAIN(loc->__lc_messages); 74 return (_LDP_CACHE); 75 } 76 if ((xp = (struct __xlocale_st_messages *)malloc(sizeof(*xp))) == NULL) 77 return _LDP_ERROR; 78 xp->__refcount = 1; 79 xp->__free_extra = (__free_extra_t)__ldpart_free_extra; 80 xp->_messages_locale_buf = NULL; 81 82 ret = __part_load_locale(name, &loc->_messages_using_locale, 83 &xp->_messages_locale_buf, "LC_MESSAGES/LC_MESSAGES", 84 LCMESSAGES_SIZE_FULL, LCMESSAGES_SIZE_MIN, 85 (const char **)&xp->_messages_locale); 86 if (ret == _LDP_LOADED) { 87 if (xp->_messages_locale.yesstr == NULL) 88 xp->_messages_locale.yesstr = empty; 89 if (xp->_messages_locale.nostr == NULL) 90 xp->_messages_locale.nostr = empty; 91 XL_RELEASE(loc->__lc_messages); 92 loc->__lc_messages = xp; 93 XL_RELEASE(cache); 94 cache = xp; 95 XL_RETAIN(cache); 96 } else if (ret == _LDP_ERROR) 97 free(xp); 98 return (ret); 99} 100 101__private_extern__ struct lc_messages_T * 102__get_current_messages_locale(locale_t loc) 103{ 104 return (loc->_messages_using_locale 105 ? &loc->__lc_messages->_messages_locale 106 : (struct lc_messages_T *)&_C_messages_locale); 107} 108 109#ifdef LOCALE_DEBUG 110void 111msgdebug() { 112locale_t loc = __current_locale(); 113printf( "yesexpr = %s\n" 114 "noexpr = %s\n" 115 "yesstr = %s\n" 116 "nostr = %s\n", 117 loc->__lc_messages->_messages_locale.yesexpr, 118 loc->__lc_messages->_messages_locale.noexpr, 119 loc->__lc_messages->_messages_locale.yesstr, 120 loc->__lc_messages->_messages_locale.nostr 121); 122} 123#endif /* LOCALE_DEBUG */ 124