/* Character set conversion with error handling and autodetection.
- Copyright (C) 2002, 2005, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2005, 2007, 2009-2011 Free Software Foundation, Inc.
Written by Bruno Haible.
- This program is free software; you can redistribute it and/or modify
+ This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdlib.h>
#include <string.h>
-#include "allocsa.h"
+#include "malloca.h"
#include "c-strcase.h"
+#include "striconveh.h"
#define SIZEOF(a) (sizeof(a)/sizeof(a[0]))
int
uniconv_register_autodetect (const char *name,
- const char * const *try_in_order)
+ const char * const *try_in_order)
{
size_t namelen;
size_t listlen;
memory += namelen;
for (i = 0; i < listlen; i++)
- {
- size_t len = strlen (try_in_order[i]) + 1;
- memcpy (memory, try_in_order[i], len);
- new_try_in_order[i] = (const char *) memory;
- memory += len;
- }
+ {
+ size_t len = strlen (try_in_order[i]) + 1;
+ memcpy (memory, try_in_order[i], len);
+ new_try_in_order[i] = (const char *) memory;
+ memory += len;
+ }
new_try_in_order[i] = NULL;
/* Now insert the new alias. */
/* Like mem_iconveha, except no handling of transliteration. */
static int
mem_iconveha_notranslit (const char *src, size_t srclen,
- const char *from_codeset, const char *to_codeset,
- enum iconv_ilseq_handler handler,
- size_t *offsets,
- char **resultp, size_t *lengthp)
+ const char *from_codeset, const char *to_codeset,
+ enum iconv_ilseq_handler handler,
+ size_t *offsets,
+ char **resultp, size_t *lengthp)
{
int retval = mem_iconveh (src, srclen, from_codeset, to_codeset, handler,
- offsets, resultp, lengthp);
+ offsets, resultp, lengthp);
if (retval >= 0 || errno != EINVAL)
return retval;
else
struct autodetect_alias *alias;
/* Unsupported from_codeset or to_codeset. Check whether the caller
- requested autodetection. */
+ requested autodetection. */
for (alias = autodetect_list; alias != NULL; alias = alias->next)
- if (strcmp (from_codeset, alias->name) == 0)
- {
- const char * const *encodings;
-
- if (handler != iconveh_error)
- {
- /* First try all encodings without any forgiving. */
- encodings = alias->encodings_to_try;
- do
- {
- retval = mem_iconveha_notranslit (src, srclen,
- *encodings, to_codeset,
- iconveh_error, offsets,
- resultp, lengthp);
- if (!(retval < 0 && errno == EILSEQ))
- return retval;
- encodings++;
- }
- while (*encodings != NULL);
- }
-
- encodings = alias->encodings_to_try;
- do
- {
- retval = mem_iconveha_notranslit (src, srclen,
- *encodings, to_codeset,
- handler, offsets,
- resultp, lengthp);
- if (!(retval < 0 && errno == EILSEQ))
- return retval;
- encodings++;
- }
- while (*encodings != NULL);
-
- /* Return the last call's result. */
- return -1;
- }
+ if (strcmp (from_codeset, alias->name) == 0)
+ {
+ const char * const *encodings;
+
+ if (handler != iconveh_error)
+ {
+ /* First try all encodings without any forgiving. */
+ encodings = alias->encodings_to_try;
+ do
+ {
+ retval = mem_iconveha_notranslit (src, srclen,
+ *encodings, to_codeset,
+ iconveh_error, offsets,
+ resultp, lengthp);
+ if (!(retval < 0 && errno == EILSEQ))
+ return retval;
+ encodings++;
+ }
+ while (*encodings != NULL);
+ }
+
+ encodings = alias->encodings_to_try;
+ do
+ {
+ retval = mem_iconveha_notranslit (src, srclen,
+ *encodings, to_codeset,
+ handler, offsets,
+ resultp, lengthp);
+ if (!(retval < 0 && errno == EILSEQ))
+ return retval;
+ encodings++;
+ }
+ while (*encodings != NULL);
+
+ /* Return the last call's result. */
+ return -1;
+ }
/* It wasn't an autodetection name. */
errno = EINVAL;
int
mem_iconveha (const char *src, size_t srclen,
- const char *from_codeset, const char *to_codeset,
- bool transliterate,
- enum iconv_ilseq_handler handler,
- size_t *offsets,
- char **resultp, size_t *lengthp)
+ const char *from_codeset, const char *to_codeset,
+ bool transliterate,
+ enum iconv_ilseq_handler handler,
+ size_t *offsets,
+ char **resultp, size_t *lengthp)
{
if (srclen == 0)
{
/* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
we want to use transliteration. */
-#if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 || _LIBICONV_VERSION >= 0x0105
+#if (((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2) \
+ && !defined __UCLIBC__) \
+ || _LIBICONV_VERSION >= 0x0105
if (transliterate)
{
int retval;
size_t len = strlen (to_codeset);
- char *to_codeset_suffixed = (char *) allocsa (len + 10 + 1);
+ char *to_codeset_suffixed = (char *) malloca (len + 10 + 1);
memcpy (to_codeset_suffixed, to_codeset, len);
memcpy (to_codeset_suffixed + len, "//TRANSLIT", 10 + 1);
retval = mem_iconveha_notranslit (src, srclen,
- from_codeset, to_codeset_suffixed,
- handler, offsets, resultp, lengthp);
+ from_codeset, to_codeset_suffixed,
+ handler, offsets, resultp, lengthp);
- freesa (to_codeset_suffixed);
+ freea (to_codeset_suffixed);
return retval;
}
else
#endif
return mem_iconveha_notranslit (src, srclen,
- from_codeset, to_codeset,
- handler, offsets, resultp, lengthp);
+ from_codeset, to_codeset,
+ handler, offsets, resultp, lengthp);
}
/* Like str_iconveha, except no handling of transliteration. */
static char *
str_iconveha_notranslit (const char *src,
- const char *from_codeset, const char *to_codeset,
- enum iconv_ilseq_handler handler)
+ const char *from_codeset, const char *to_codeset,
+ enum iconv_ilseq_handler handler)
{
char *result = str_iconveh (src, from_codeset, to_codeset, handler);
struct autodetect_alias *alias;
/* Unsupported from_codeset or to_codeset. Check whether the caller
- requested autodetection. */
+ requested autodetection. */
for (alias = autodetect_list; alias != NULL; alias = alias->next)
- if (strcmp (from_codeset, alias->name) == 0)
- {
- const char * const *encodings;
-
- if (handler != iconveh_error)
- {
- /* First try all encodings without any forgiving. */
- encodings = alias->encodings_to_try;
- do
- {
- result = str_iconveha_notranslit (src,
- *encodings, to_codeset,
- iconveh_error);
- if (!(result == NULL && errno == EILSEQ))
- return result;
- encodings++;
- }
- while (*encodings != NULL);
- }
-
- encodings = alias->encodings_to_try;
- do
- {
- result = str_iconveha_notranslit (src,
- *encodings, to_codeset,
- handler);
- if (!(result == NULL && errno == EILSEQ))
- return result;
- encodings++;
- }
- while (*encodings != NULL);
-
- /* Return the last call's result. */
- return NULL;
- }
+ if (strcmp (from_codeset, alias->name) == 0)
+ {
+ const char * const *encodings;
+
+ if (handler != iconveh_error)
+ {
+ /* First try all encodings without any forgiving. */
+ encodings = alias->encodings_to_try;
+ do
+ {
+ result = str_iconveha_notranslit (src,
+ *encodings, to_codeset,
+ iconveh_error);
+ if (!(result == NULL && errno == EILSEQ))
+ return result;
+ encodings++;
+ }
+ while (*encodings != NULL);
+ }
+
+ encodings = alias->encodings_to_try;
+ do
+ {
+ result = str_iconveha_notranslit (src,
+ *encodings, to_codeset,
+ handler);
+ if (!(result == NULL && errno == EILSEQ))
+ return result;
+ encodings++;
+ }
+ while (*encodings != NULL);
+
+ /* Return the last call's result. */
+ return NULL;
+ }
/* It wasn't an autodetection name. */
errno = EINVAL;
char *
str_iconveha (const char *src,
- const char *from_codeset, const char *to_codeset,
- bool transliterate,
- enum iconv_ilseq_handler handler)
+ const char *from_codeset, const char *to_codeset,
+ bool transliterate,
+ enum iconv_ilseq_handler handler)
{
if (*src == '\0' || c_strcasecmp (from_codeset, to_codeset) == 0)
{
char *result = strdup (src);
if (result == NULL)
- errno = ENOMEM;
+ errno = ENOMEM;
return result;
}
/* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
we want to use transliteration. */
-#if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 || _LIBICONV_VERSION >= 0x0105
+#if (((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2) \
+ && !defined __UCLIBC__) \
+ || _LIBICONV_VERSION >= 0x0105
if (transliterate)
{
char *result;
size_t len = strlen (to_codeset);
- char *to_codeset_suffixed = (char *) allocsa (len + 10 + 1);
+ char *to_codeset_suffixed = (char *) malloca (len + 10 + 1);
memcpy (to_codeset_suffixed, to_codeset, len);
memcpy (to_codeset_suffixed + len, "//TRANSLIT", 10 + 1);
result = str_iconveha_notranslit (src, from_codeset, to_codeset_suffixed,
- handler);
+ handler);
- freesa (to_codeset_suffixed);
+ freea (to_codeset_suffixed);
return result;
}