setrunelocale.c revision 232498
111695Sache/*- 211695Sache * Copyright (c) 1993 311695Sache * The Regents of the University of California. All rights reserved. 411695Sache * 511695Sache * This code is derived from software contributed to Berkeley by 611695Sache * Paul Borman at Krystal Technologies. 711695Sache * 8227753Stheraven * Copyright (c) 2011 The FreeBSD Foundation 9227753Stheraven * All rights reserved. 10227753Stheraven * Portions of this software were developed by David Chisnall 11227753Stheraven * under sponsorship from the FreeBSD Foundation. 12227753Stheraven * 1311695Sache * Redistribution and use in source and binary forms, with or without 1411695Sache * modification, are permitted provided that the following conditions 1511695Sache * are met: 1611695Sache * 1. Redistributions of source code must retain the above copyright 1711695Sache * notice, this list of conditions and the following disclaimer. 1811695Sache * 2. Redistributions in binary form must reproduce the above copyright 1911695Sache * notice, this list of conditions and the following disclaimer in the 2011695Sache * documentation and/or other materials provided with the distribution. 2111695Sache * 4. Neither the name of the University nor the names of its contributors 2211695Sache * may be used to endorse or promote products derived from this software 2311695Sache * without specific prior written permission. 2411695Sache * 2511695Sache * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2611695Sache * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2711695Sache * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2811695Sache * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2911695Sache * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3011695Sache * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3111695Sache * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3211695Sache * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3311695Sache * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3411695Sache * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3511695Sache * SUCH DAMAGE. 3611695Sache */ 3711695Sache 3892986Sobrien#include <sys/cdefs.h> 3992986Sobrien__FBSDID("$FreeBSD: head/lib/libc/locale/setrunelocale.c 232498 2012-03-04 15:31:13Z theraven $"); 4092986Sobrien 41232498Stheraven#define __RUNETYPE_INTERNAL 1 42232498Stheraven 43136609Stjr#include <runetype.h> 4411695Sache#include <errno.h> 4511695Sache#include <limits.h> 4611695Sache#include <string.h> 4711695Sache#include <stdio.h> 4811695Sache#include <stdlib.h> 4924694Sache#include <unistd.h> 50121845Stjr#include <wchar.h> 51117270Sache#include "ldpart.h" 52129153Stjr#include "mblocal.h" 5322330Sache#include "setlocale.h" 5411695Sache 55232498Stheraven#undef _CurrentRuneLocale 56232498Stheravenextern _RuneLocale const *_CurrentRuneLocale; 57232498Stheraven#ifndef __NO_TLS 58232498Stheraven/* 59232498Stheraven * A cached version of the runes for this thread. Used by ctype.h 60232498Stheraven */ 61232498Stheraven_Thread_local const _RuneLocale *_ThreadRuneLocale; 62232498Stheraven#endif 63232498Stheraven 64172619Sacheextern int __mb_sb_limit; 65172619Sache 66115626Sacheextern _RuneLocale *_Read_RuneMagi(FILE *); 6711695Sache 68227753Stheravenstatic int __setrunelocale(struct xlocale_ctype *l, const char *); 69117270Sache 70227753Stheraven#define __collate_load_error (table->__collate_load_error) 71227753Stheraven#define __collate_substitute_nontrivial (table->__collate_substitute_nontrivial) 72227753Stheraven#define __collate_substitute_table_ptr (table->__collate_substitute_table_ptr) 73227753Stheraven#define __collate_char_pri_table_ptr (table->__collate_char_pri_table_ptr) 74227753Stheraven#define __collate_chain_pri_table (table->__collate_chain_pri_table) 75227753Stheraven 76227753Stheraven 77227753Stheravenstatic void destruct_ctype(void *v) 78227753Stheraven{ 79227753Stheraven struct xlocale_ctype *l = v; 80227753Stheraven if (strcmp(l->runes->__encoding, "EUC") == 0) 81227753Stheraven free(l->runes->__variable); 82227753Stheraven if (&_DefaultRuneLocale != l->runes) 83227753Stheraven free(l->runes); 84227753Stheraven free(l); 85227753Stheraven} 86232498Stheraven 87232498Stheravenconst _RuneLocale *__getCurrentRuneLocale(void) 88227753Stheraven{ 89227753Stheraven return XLOCALE_CTYPE(__get_locale())->runes; 90227753Stheraven} 91227753Stheraven 92117270Sachestatic int 93227753Stheraven__setrunelocale(struct xlocale_ctype *l, const char *encoding) 94117270Sache{ 9511695Sache FILE *fp; 9611695Sache char name[PATH_MAX]; 9711695Sache _RuneLocale *rl; 98101498Sache int saverr, ret; 99227753Stheraven struct xlocale_ctype saved = *l; 10011695Sache 10111695Sache /* 10211695Sache * The "C" and "POSIX" locale are always here. 10311695Sache */ 104101498Sache if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) { 105227753Stheraven (void) _none_init(l, (_RuneLocale*)&_DefaultRuneLocale); 106101263Sache return (0); 10711695Sache } 10811695Sache 109117270Sache /* Range checking not needed, encoding length already checked before */ 11020810Sjoerg (void) strcpy(name, _PathLocale); 11120810Sjoerg (void) strcat(name, "/"); 11220810Sjoerg (void) strcat(name, encoding); 11320810Sjoerg (void) strcat(name, "/LC_CTYPE"); 11411695Sache 11511695Sache if ((fp = fopen(name, "r")) == NULL) 116101566Sache return (errno == 0 ? ENOENT : errno); 11711695Sache 118101498Sache if ((rl = _Read_RuneMagi(fp)) == NULL) { 119101566Sache saverr = (errno == 0 ? EFTYPE : errno); 120101498Sache (void)fclose(fp); 121101498Sache return (saverr); 12211695Sache } 123101498Sache (void)fclose(fp); 12411695Sache 125227753Stheraven l->__mbrtowc = NULL; 126227753Stheraven l->__mbsinit = NULL; 127227753Stheraven l->__mbsnrtowcs = __mbsnrtowcs_std; 128227753Stheraven l->__wcrtomb = NULL; 129227753Stheraven l->__wcsnrtombs = __wcsnrtombs_std; 130175586Sache 131136609Stjr rl->__sputrune = NULL; 132136609Stjr rl->__sgetrune = NULL; 133175586Sache if (strcmp(rl->__encoding, "NONE") == 0) 134227753Stheraven ret = _none_init(l, rl); 135175586Sache else if (strcmp(rl->__encoding, "ASCII") == 0) 136227753Stheraven ret = _ascii_init(l, rl); 137175586Sache else if (strcmp(rl->__encoding, "UTF-8") == 0) 138227753Stheraven ret = _UTF8_init(l, rl); 139175586Sache else if (strcmp(rl->__encoding, "EUC") == 0) 140227753Stheraven ret = _EUC_init(l, rl); 141175586Sache else if (strcmp(rl->__encoding, "GB18030") == 0) 142227753Stheraven ret = _GB18030_init(l, rl); 143175586Sache else if (strcmp(rl->__encoding, "GB2312") == 0) 144227753Stheraven ret = _GB2312_init(l, rl); 145175586Sache else if (strcmp(rl->__encoding, "GBK") == 0) 146227753Stheraven ret = _GBK_init(l, rl); 147175586Sache else if (strcmp(rl->__encoding, "BIG5") == 0) 148227753Stheraven ret = _BIG5_init(l, rl); 149175586Sache else if (strcmp(rl->__encoding, "MSKanji") == 0) 150227753Stheraven ret = _MSKanji_init(l, rl); 151175586Sache else 152101498Sache ret = EFTYPE; 153175585Sache 154101498Sache if (ret == 0) { 155227753Stheraven /* Free the old runes if it exists. */ 156227753Stheraven /* FIXME: The "EUC" check here is a hideous abstraction violation. */ 157227753Stheraven if ((saved.runes != &_DefaultRuneLocale) && (saved.runes)) { 158227753Stheraven if (strcmp(saved.runes->__encoding, "EUC") == 0) { 159227753Stheraven free(saved.runes->__variable); 160227753Stheraven } 161227753Stheraven free(saved.runes); 162101498Sache } 163175586Sache } else { 164227753Stheraven /* Restore the saved version if this failed. */ 165227753Stheraven memcpy(l, &saved, sizeof(struct xlocale_ctype)); 166101498Sache free(rl); 167175586Sache } 168101498Sache 169101498Sache return (ret); 17011695Sache} 17111695Sache 172117270Sacheint 173117270Sache__wrap_setrunelocale(const char *locale) 174117270Sache{ 175227753Stheraven int ret = __setrunelocale(&__xlocale_global_ctype, locale); 176117270Sache 177117270Sache if (ret != 0) { 178117270Sache errno = ret; 179117270Sache return (_LDP_ERROR); 180117270Sache } 181227753Stheraven __mb_cur_max = __xlocale_global_ctype.__mb_cur_max; 182227753Stheraven __mb_sb_limit = __xlocale_global_ctype.__mb_sb_limit; 183232498Stheraven _CurrentRuneLocale = __xlocale_global_ctype.runes; 184117270Sache return (_LDP_LOADED); 185117270Sache} 186232498Stheraven 187232498Stheraven#ifndef __NO_TLS 188232498Stheravenvoid 189232498Stheraven__set_thread_rune_locale(locale_t loc) { 190232498Stheraven 191232498Stheraven if (loc == NULL) { 192232498Stheraven _ThreadRuneLocale = &_DefaultRuneLocale; 193232498Stheraven } else { 194232498Stheraven _ThreadRuneLocale = XLOCALE_CTYPE(loc)->runes; 195232498Stheraven } 196232498Stheraven} 197232498Stheraven#endif 198232498Stheraven 199232498Stheravenvoid * 200232498Stheraven__ctype_load(const char *locale, locale_t unused) 201227753Stheraven{ 202227753Stheraven struct xlocale_ctype *l = calloc(sizeof(struct xlocale_ctype), 1); 203227753Stheraven l->header.header.destructor = destruct_ctype; 204227753Stheraven if (__setrunelocale(l, locale)) 205227753Stheraven { 206227753Stheraven free(l); 207227753Stheraven return NULL; 208227753Stheraven } 209227753Stheraven return l; 210227753Stheraven} 211