diff options
Diffstat (limited to 'REORG.TODO/iconv/gconv_open.c')
-rw-r--r-- | REORG.TODO/iconv/gconv_open.c | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/REORG.TODO/iconv/gconv_open.c b/REORG.TODO/iconv/gconv_open.c new file mode 100644 index 0000000000..ff4fd121eb --- /dev/null +++ b/REORG.TODO/iconv/gconv_open.c @@ -0,0 +1,208 @@ +/* Find matching transformation algorithms and initialize steps. + Copyright (C) 1997-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + 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 <errno.h> +#include <locale.h> +#include "../locale/localeinfo.h" +#include <stdlib.h> +#include <string.h> + +#include <gconv_int.h> + + +int +internal_function +__gconv_open (const char *toset, const char *fromset, __gconv_t *handle, + int flags) +{ + struct __gconv_step *steps; + size_t nsteps; + __gconv_t result = NULL; + size_t cnt = 0; + int res; + int conv_flags = 0; + const char *errhand; + const char *ignore; + bool translit = false; + + /* Find out whether any error handling method is specified. */ + errhand = strchr (toset, '/'); + if (errhand != NULL) + errhand = strchr (errhand + 1, '/'); + if (__glibc_likely (errhand != NULL)) + { + if (*++errhand == '\0') + errhand = NULL; + else + { + /* Make copy without the error handling description. */ + char *newtoset = (char *) alloca (errhand - toset + 1); + char *tok; + char *ptr = NULL /* Work around a bogus warning */; + + newtoset[errhand - toset] = '\0'; + toset = memcpy (newtoset, toset, errhand - toset); + + /* Find the appropriate transliteration handlers. */ + tok = strdupa (errhand); + + tok = __strtok_r (tok, ",", &ptr); + while (tok != NULL) + { + if (__strcasecmp_l (tok, "TRANSLIT", _nl_C_locobj_ptr) == 0) + translit = true; + else if (__strcasecmp_l (tok, "IGNORE", _nl_C_locobj_ptr) == 0) + /* Set the flag to ignore all errors. */ + conv_flags |= __GCONV_IGNORE_ERRORS; + + tok = __strtok_r (NULL, ",", &ptr); + } + } + } + + /* For the source character set we ignore the error handler specification. + XXX Is this really always the best? */ + ignore = strchr (fromset, '/'); + if (ignore != NULL && (ignore = strchr (ignore + 1, '/')) != NULL + && *++ignore != '\0') + { + char *newfromset = (char *) alloca (ignore - fromset + 1); + + newfromset[ignore - fromset] = '\0'; + fromset = memcpy (newfromset, fromset, ignore - fromset); + } + + /* If the string is empty define this to mean the charset of the + currently selected locale. */ + if (strcmp (toset, "//") == 0) + { + const char *codeset = _NL_CURRENT (LC_CTYPE, CODESET); + size_t len = strlen (codeset); + char *dest; + toset = dest = (char *) alloca (len + 3); + memcpy (__mempcpy (dest, codeset, len), "//", 3); + } + if (strcmp (fromset, "//") == 0) + { + const char *codeset = _NL_CURRENT (LC_CTYPE, CODESET); + size_t len = strlen (codeset); + char *dest; + fromset = dest = (char *) alloca (len + 3); + memcpy (__mempcpy (dest, codeset, len), "//", 3); + } + + res = __gconv_find_transform (toset, fromset, &steps, &nsteps, flags); + if (res == __GCONV_OK) + { + /* Allocate room for handle. */ + result = (__gconv_t) malloc (sizeof (struct __gconv_info) + + (nsteps + * sizeof (struct __gconv_step_data))); + if (result == NULL) + res = __GCONV_NOMEM; + else + { + /* Remember the list of steps. */ + result->__steps = steps; + result->__nsteps = nsteps; + + /* Clear the array for the step data. */ + memset (result->__data, '\0', + nsteps * sizeof (struct __gconv_step_data)); + + /* Call all initialization functions for the transformation + step implementations. */ + for (cnt = 0; cnt < nsteps; ++cnt) + { + size_t size; + + /* Would have to be done if we would not clear the whole + array above. */ +#if 0 + /* Reset the counter. */ + result->__data[cnt].__invocation_counter = 0; + + /* It's a regular use. */ + result->__data[cnt].__internal_use = 0; +#endif + + /* We use the `mbstate_t' member in DATA. */ + result->__data[cnt].__statep = &result->__data[cnt].__state; + + /* The builtin transliteration handling only + supports the internal encoding. */ + if (translit + && __strcasecmp_l (steps[cnt].__from_name, + "INTERNAL", _nl_C_locobj_ptr) == 0) + conv_flags |= __GCONV_TRANSLIT; + + /* If this is the last step we must not allocate an + output buffer. */ + if (cnt < nsteps - 1) + { + result->__data[cnt].__flags = conv_flags; + + /* Allocate the buffer. */ + size = (GCONV_NCHAR_GOAL * steps[cnt].__max_needed_to); + + result->__data[cnt].__outbuf = malloc (size); + if (result->__data[cnt].__outbuf == NULL) + { + res = __GCONV_NOMEM; + goto bail; + } + + result->__data[cnt].__outbufend = + result->__data[cnt].__outbuf + size; + } + else + { + /* Handle the last entry. */ + result->__data[cnt].__flags = conv_flags | __GCONV_IS_LAST; + + break; + } + } + } + + if (res != __GCONV_OK) + { + /* Something went wrong. Free all the resources. */ + int serrno; + bail: + serrno = errno; + + if (result != NULL) + { + while (cnt-- > 0) + free (result->__data[cnt].__outbuf); + + free (result); + result = NULL; + } + + __gconv_close_transform (steps, nsteps); + + __set_errno (serrno); + } + } + + *handle = result; + return res; +} |