diff options
Diffstat (limited to 'REORG.TODO/wcsmbs/wcsmbsload.c')
-rw-r--r-- | REORG.TODO/wcsmbs/wcsmbsload.c | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/REORG.TODO/wcsmbs/wcsmbsload.c b/REORG.TODO/wcsmbs/wcsmbsload.c new file mode 100644 index 0000000000..656cc0a8e8 --- /dev/null +++ b/REORG.TODO/wcsmbs/wcsmbsload.c @@ -0,0 +1,270 @@ +/* Copyright (C) 1998-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <ctype.h> +#include <langinfo.h> +#include <limits.h> +#include <stdlib.h> +#include <string.h> + +#include <locale/localeinfo.h> +#include <wcsmbsload.h> +#include <libc-lock.h> + + +/* These are the descriptions for the default conversion functions. */ +static const struct __gconv_step to_wc = +{ + .__shlib_handle = NULL, + .__modname = NULL, + .__counter = INT_MAX, + .__from_name = (char *) "ANSI_X3.4-1968//TRANSLIT", + .__to_name = (char *) "INTERNAL", + .__fct = __gconv_transform_ascii_internal, + .__btowc_fct = __gconv_btwoc_ascii, + .__init_fct = NULL, + .__end_fct = NULL, + .__min_needed_from = 1, + .__max_needed_from = 1, + .__min_needed_to = 4, + .__max_needed_to = 4, + .__stateful = 0, + .__data = NULL +}; + +static const struct __gconv_step to_mb = +{ + .__shlib_handle = NULL, + .__modname = NULL, + .__counter = INT_MAX, + .__from_name = (char *) "INTERNAL", + .__to_name = (char *) "ANSI_X3.4-1968//TRANSLIT", + .__fct = __gconv_transform_internal_ascii, + .__btowc_fct = NULL, + .__init_fct = NULL, + .__end_fct = NULL, + .__min_needed_from = 4, + .__max_needed_from = 4, + .__min_needed_to = 1, + .__max_needed_to = 1, + .__stateful = 0, + .__data = NULL +}; + + +/* For the default locale we only have to handle ANSI_X3.4-1968. */ +const struct gconv_fcts __wcsmbs_gconv_fcts_c = +{ + .towc = (struct __gconv_step *) &to_wc, + .towc_nsteps = 1, + .tomb = (struct __gconv_step *) &to_mb, + .tomb_nsteps = 1, +}; + + +attribute_hidden +struct __gconv_step * +__wcsmbs_getfct (const char *to, const char *from, size_t *nstepsp) +{ + size_t nsteps; + struct __gconv_step *result; +#if 0 + size_t nstateful; + size_t cnt; +#endif + + if (__gconv_find_transform (to, from, &result, &nsteps, 0) != __GCONV_OK) + /* Loading the conversion step is not possible. */ + return NULL; + + /* Maybe it is someday necessary to allow more than one step. + Currently this is not the case since the conversions handled here + are from and to INTERNAL and there always is a converted for + that. It the directly following code is enabled the libio + functions will have to allocate appropriate __gconv_step_data + elements instead of only one. */ +#if 0 + /* Count the number of stateful conversions. Since we will only + have one 'mbstate_t' object available we can only deal with one + stateful conversion. */ + nstateful = 0; + for (cnt = 0; cnt < nsteps; ++cnt) + if (result[cnt].__stateful) + ++nstateful; + if (nstateful > 1) +#else + if (nsteps > 1) +#endif + { + /* We cannot handle this case. */ + __gconv_close_transform (result, nsteps); + result = NULL; + } + else + *nstepsp = nsteps; + + return result; +} + + +/* Extract from the given locale name the character set portion. Since + only the XPG form of the name includes this information we don't have + to take care for the CEN form. */ +#define extract_charset_name(str) \ + ({ \ + const char *cp = str; \ + char *result = NULL; \ + \ + cp += strcspn (cp, "@.+,"); \ + if (*cp == '.') \ + { \ + const char *endp = ++cp; \ + while (*endp != '\0' && *endp != '@') \ + ++endp; \ + if (endp != cp) \ + result = strndupa (cp, endp - cp); \ + } \ + result; \ + }) + + +/* Some of the functions here must not be used while setlocale is called. */ +__libc_rwlock_define (extern, __libc_setlocale_lock attribute_hidden) + +/* Load conversion functions for the currently selected locale. */ +void +internal_function +__wcsmbs_load_conv (struct __locale_data *new_category) +{ + /* Acquire the lock. */ + __libc_rwlock_wrlock (__libc_setlocale_lock); + + /* We should repeat the test since while we waited some other thread + might have run this function. */ + if (__glibc_likely (new_category->private.ctype == NULL)) + { + /* We must find the real functions. */ + const char *charset_name; + const char *complete_name; + struct gconv_fcts *new_fcts; + int use_translit; + + /* Allocate the gconv_fcts structure. */ + new_fcts = calloc (1, sizeof *new_fcts); + if (new_fcts == NULL) + goto failed; + + /* Get name of charset of the locale. */ + charset_name = new_category->values[_NL_ITEM_INDEX(CODESET)].string; + + /* Does the user want transliteration? */ + use_translit = new_category->use_translit; + + /* Normalize the name and add the slashes necessary for a + complete lookup. */ + complete_name = norm_add_slashes (charset_name, + use_translit ? "TRANSLIT" : ""); + + /* It is not necessary to use transliteration in this direction + since the internal character set is supposed to be able to + represent all others. */ + new_fcts->towc = __wcsmbs_getfct ("INTERNAL", complete_name, + &new_fcts->towc_nsteps); + if (new_fcts->towc != NULL) + new_fcts->tomb = __wcsmbs_getfct (complete_name, "INTERNAL", + &new_fcts->tomb_nsteps); + + /* If any of the conversion functions is not available we don't + use any since this would mean we cannot convert back and + forth. NB: NEW_FCTS was allocated with calloc. */ + if (new_fcts->tomb == NULL) + { + if (new_fcts->towc != NULL) + __gconv_close_transform (new_fcts->towc, new_fcts->towc_nsteps); + + free (new_fcts); + + failed: + new_category->private.ctype = &__wcsmbs_gconv_fcts_c; + } + else + { + new_category->private.ctype = new_fcts; + new_category->private.cleanup = &_nl_cleanup_ctype; + } + } + + __libc_rwlock_unlock (__libc_setlocale_lock); +} + + +/* Clone the current conversion function set. */ +void +internal_function +__wcsmbs_clone_conv (struct gconv_fcts *copy) +{ + const struct gconv_fcts *orig; + + orig = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); + + /* Copy the data. */ + *copy = *orig; + + /* Now increment the usage counters. + Note: This assumes copy->*_nsteps == 1. */ + if (copy->towc->__shlib_handle != NULL) + ++copy->towc->__counter; + if (copy->tomb->__shlib_handle != NULL) + ++copy->tomb->__counter; +} + + +/* Get converters for named charset. */ +int +internal_function +__wcsmbs_named_conv (struct gconv_fcts *copy, const char *name) +{ + copy->towc = __wcsmbs_getfct ("INTERNAL", name, ©->towc_nsteps); + if (copy->towc == NULL) + return 1; + + copy->tomb = __wcsmbs_getfct (name, "INTERNAL", ©->tomb_nsteps); + if (copy->tomb == NULL) + { + __gconv_close_transform (copy->towc, copy->towc_nsteps); + return 1; + } + + return 0; +} + +void internal_function +_nl_cleanup_ctype (struct __locale_data *locale) +{ + const struct gconv_fcts *const data = locale->private.ctype; + if (data != NULL) + { + locale->private.ctype = NULL; + locale->private.cleanup = NULL; + + /* Free the old conversions. */ + __gconv_close_transform (data->tomb, data->tomb_nsteps); + __gconv_close_transform (data->towc, data->towc_nsteps); + free ((char *) data); + } +} |