setrunelocale.c revision 264038
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 264038 2014-04-02 11:10:46Z 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_substitute_nontrivial (table->__collate_substitute_nontrivial) 71227753Stheraven#define __collate_substitute_table_ptr (table->__collate_substitute_table_ptr) 72227753Stheraven#define __collate_char_pri_table_ptr (table->__collate_char_pri_table_ptr) 73227753Stheraven#define __collate_chain_pri_table (table->__collate_chain_pri_table) 74227753Stheraven 75227753Stheraven 76244091Sbrooksstatic void 77244091Sbrooksdestruct_ctype(void *v) 78227753Stheraven{ 79227753Stheraven struct xlocale_ctype *l = v; 80244091Sbrooks 81227753Stheraven if (strcmp(l->runes->__encoding, "EUC") == 0) 82227753Stheraven free(l->runes->__variable); 83227753Stheraven if (&_DefaultRuneLocale != l->runes) 84227753Stheraven free(l->runes); 85227753Stheraven free(l); 86227753Stheraven} 87232498Stheraven 88244091Sbrooksconst _RuneLocale * 89244091Sbrooks__getCurrentRuneLocale(void) 90227753Stheraven{ 91244091Sbrooks 92227753Stheraven return XLOCALE_CTYPE(__get_locale())->runes; 93227753Stheraven} 94227753Stheraven 95244091Sbrooksstatic void 96244091Sbrooksfree_runes(_RuneLocale *rl) 97236889Stheraven{ 98244091Sbrooks 99236889Stheraven /* FIXME: The "EUC" check here is a hideous abstraction violation. */ 100236889Stheraven if ((rl != &_DefaultRuneLocale) && (rl)) { 101236889Stheraven if (strcmp(rl->__encoding, "EUC") == 0) { 102236889Stheraven free(rl->__variable); 103236889Stheraven } 104236889Stheraven free(rl); 105236889Stheraven } 106236889Stheraven} 107236889Stheraven 108117270Sachestatic int 109227753Stheraven__setrunelocale(struct xlocale_ctype *l, const char *encoding) 110117270Sache{ 11111695Sache FILE *fp; 11211695Sache char name[PATH_MAX]; 11311695Sache _RuneLocale *rl; 114101498Sache int saverr, ret; 115227753Stheraven struct xlocale_ctype saved = *l; 11611695Sache 11711695Sache /* 11811695Sache * The "C" and "POSIX" locale are always here. 11911695Sache */ 120101498Sache if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) { 121236889Stheraven free_runes(saved.runes); 122227753Stheraven (void) _none_init(l, (_RuneLocale*)&_DefaultRuneLocale); 123101263Sache return (0); 12411695Sache } 12511695Sache 126117270Sache /* Range checking not needed, encoding length already checked before */ 12720810Sjoerg (void) strcpy(name, _PathLocale); 12820810Sjoerg (void) strcat(name, "/"); 12920810Sjoerg (void) strcat(name, encoding); 13020810Sjoerg (void) strcat(name, "/LC_CTYPE"); 13111695Sache 132244126Sjilles if ((fp = fopen(name, "re")) == NULL) 133101566Sache return (errno == 0 ? ENOENT : errno); 13411695Sache 135101498Sache if ((rl = _Read_RuneMagi(fp)) == NULL) { 136101566Sache saverr = (errno == 0 ? EFTYPE : errno); 137101498Sache (void)fclose(fp); 138101498Sache return (saverr); 13911695Sache } 140101498Sache (void)fclose(fp); 14111695Sache 142227753Stheraven l->__mbrtowc = NULL; 143227753Stheraven l->__mbsinit = NULL; 144227753Stheraven l->__mbsnrtowcs = __mbsnrtowcs_std; 145227753Stheraven l->__wcrtomb = NULL; 146227753Stheraven l->__wcsnrtombs = __wcsnrtombs_std; 147175586Sache 148136609Stjr rl->__sputrune = NULL; 149136609Stjr rl->__sgetrune = NULL; 150175586Sache if (strcmp(rl->__encoding, "NONE") == 0) 151227753Stheraven ret = _none_init(l, rl); 152175586Sache else if (strcmp(rl->__encoding, "ASCII") == 0) 153227753Stheraven ret = _ascii_init(l, rl); 154175586Sache else if (strcmp(rl->__encoding, "UTF-8") == 0) 155227753Stheraven ret = _UTF8_init(l, rl); 156175586Sache else if (strcmp(rl->__encoding, "EUC") == 0) 157227753Stheraven ret = _EUC_init(l, rl); 158175586Sache else if (strcmp(rl->__encoding, "GB18030") == 0) 159227753Stheraven ret = _GB18030_init(l, rl); 160175586Sache else if (strcmp(rl->__encoding, "GB2312") == 0) 161227753Stheraven ret = _GB2312_init(l, rl); 162175586Sache else if (strcmp(rl->__encoding, "GBK") == 0) 163227753Stheraven ret = _GBK_init(l, rl); 164175586Sache else if (strcmp(rl->__encoding, "BIG5") == 0) 165227753Stheraven ret = _BIG5_init(l, rl); 166175586Sache else if (strcmp(rl->__encoding, "MSKanji") == 0) 167227753Stheraven ret = _MSKanji_init(l, rl); 168175586Sache else 169101498Sache ret = EFTYPE; 170175585Sache 171101498Sache if (ret == 0) { 172227753Stheraven /* Free the old runes if it exists. */ 173236889Stheraven free_runes(saved.runes); 174175586Sache } else { 175227753Stheraven /* Restore the saved version if this failed. */ 176227753Stheraven memcpy(l, &saved, sizeof(struct xlocale_ctype)); 177101498Sache free(rl); 178175586Sache } 179101498Sache 180101498Sache return (ret); 18111695Sache} 18211695Sache 183117270Sacheint 184117270Sache__wrap_setrunelocale(const char *locale) 185117270Sache{ 186227753Stheraven int ret = __setrunelocale(&__xlocale_global_ctype, locale); 187117270Sache 188117270Sache if (ret != 0) { 189117270Sache errno = ret; 190117270Sache return (_LDP_ERROR); 191117270Sache } 192227753Stheraven __mb_cur_max = __xlocale_global_ctype.__mb_cur_max; 193227753Stheraven __mb_sb_limit = __xlocale_global_ctype.__mb_sb_limit; 194232498Stheraven _CurrentRuneLocale = __xlocale_global_ctype.runes; 195117270Sache return (_LDP_LOADED); 196117270Sache} 197232498Stheraven 198232498Stheraven#ifndef __NO_TLS 199232498Stheravenvoid 200244091Sbrooks__set_thread_rune_locale(locale_t loc) 201244091Sbrooks{ 202232498Stheraven 203232498Stheraven if (loc == NULL) { 204232498Stheraven _ThreadRuneLocale = &_DefaultRuneLocale; 205264038Stheraven } else if (loc == LC_GLOBAL_LOCALE) { 206264038Stheraven _ThreadRuneLocale = 0; 207232498Stheraven } else { 208232498Stheraven _ThreadRuneLocale = XLOCALE_CTYPE(loc)->runes; 209232498Stheraven } 210232498Stheraven} 211232498Stheraven#endif 212232498Stheraven 213232498Stheravenvoid * 214232498Stheraven__ctype_load(const char *locale, locale_t unused) 215227753Stheraven{ 216227753Stheraven struct xlocale_ctype *l = calloc(sizeof(struct xlocale_ctype), 1); 217244091Sbrooks 218227753Stheraven l->header.header.destructor = destruct_ctype; 219227753Stheraven if (__setrunelocale(l, locale)) 220227753Stheraven { 221227753Stheraven free(l); 222227753Stheraven return NULL; 223227753Stheraven } 224227753Stheraven return l; 225227753Stheraven} 226