• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500-V1.0.1.40_1.0.68/ap/gpl/timemachine/gettext-0.17/gettext-tools/libgettextpo/
1/* Character set conversion.
2   Copyright (C) 2007 Free Software Foundation, Inc.
3
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU General Public License as published by
6   the Free Software Foundation; either version 2, or (at your option)
7   any later version.
8
9   This program is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   GNU General Public License for more details.
13
14   You should have received a copy of the GNU General Public License along
15   with this program; if not, write to the Free Software Foundation,
16   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
17
18#include <config.h>
19
20/* Specification.  */
21#include <iconv.h>
22
23#include <errno.h>
24#include <string.h>
25#include "c-ctype.h"
26#include "c-strcase.h"
27
28#define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
29
30/* Namespace cleanliness.  */
31#define mapping_lookup rpl_iconv_open_mapping_lookup
32
33/* The macro ICONV_FLAVOR is defined to one of these or undefined.  */
34
35#define ICONV_FLAVOR_AIX "iconv_open-aix.h"
36#define ICONV_FLAVOR_HPUX "iconv_open-hpux.h"
37#define ICONV_FLAVOR_IRIX "iconv_open-irix.h"
38#define ICONV_FLAVOR_OSF "iconv_open-osf.h"
39
40#ifdef ICONV_FLAVOR
41# include ICONV_FLAVOR
42#endif
43
44iconv_t
45rpl_iconv_open (const char *tocode, const char *fromcode)
46#undef iconv_open
47{
48  char fromcode_upper[32];
49  char tocode_upper[32];
50  char *fromcode_upper_end;
51  char *tocode_upper_end;
52
53#if REPLACE_ICONV_UTF
54  /* Special handling of conversion between UTF-8 and UTF-{16,32}{BE,LE}.
55     Do this here, before calling the real iconv_open(), because  OSF/1 5.1
56     iconv() to these encoding inserts a BOM, which is wrong.
57     We do not need to handle conversion between arbitrary encodings and
58     UTF-{16,32}{BE,LE}, because the 'striconveh' module implements two-step
59     conversion throough UTF-8.
60     The _ICONV_* constants are chosen to be disjoint from any iconv_t
61     returned by the system's iconv_open() functions.  Recall that iconv_t
62     is a scalar type.  */
63  if (c_toupper (fromcode[0]) == 'U'
64      && c_toupper (fromcode[1]) == 'T'
65      && c_toupper (fromcode[2]) == 'F'
66      && fromcode[3] == '-')
67    {
68      if (c_toupper (tocode[0]) == 'U'
69	  && c_toupper (tocode[1]) == 'T'
70	  && c_toupper (tocode[2]) == 'F'
71	  && tocode[3] == '-')
72	{
73	  if (strcmp (fromcode + 4, "8") == 0)
74	    {
75	      if (c_strcasecmp (tocode + 4, "16BE") == 0)
76		return _ICONV_UTF8_UTF16BE;
77	      if (c_strcasecmp (tocode + 4, "16LE") == 0)
78		return _ICONV_UTF8_UTF16LE;
79	      if (c_strcasecmp (tocode + 4, "32BE") == 0)
80		return _ICONV_UTF8_UTF32BE;
81	      if (c_strcasecmp (tocode + 4, "32LE") == 0)
82		return _ICONV_UTF8_UTF32LE;
83	    }
84	  else if (strcmp (tocode + 4, "8") == 0)
85	    {
86	      if (c_strcasecmp (fromcode + 4, "16BE") == 0)
87		return _ICONV_UTF16BE_UTF8;
88	      if (c_strcasecmp (fromcode + 4, "16LE") == 0)
89		return _ICONV_UTF16LE_UTF8;
90	      if (c_strcasecmp (fromcode + 4, "32BE") == 0)
91		return _ICONV_UTF32BE_UTF8;
92	      if (c_strcasecmp (fromcode + 4, "32LE") == 0)
93		return _ICONV_UTF32LE_UTF8;
94	    }
95	}
96    }
97#endif
98
99  /* Do *not* add special support for 8-bit encodings like ASCII or ISO-8859-1
100     here.  This would lead to programs that work in some locales (such as the
101     "C" or "en_US" locales) but do not work in East Asian locales.  It is
102     better if programmers make their programs depend on GNU libiconv (except
103     on glibc systems), e.g. by using the AM_ICONV macro and documenting the
104     dependency in an INSTALL or DEPENDENCIES file.  */
105
106  /* Try with the original names first.
107     This covers the case when fromcode or tocode is a lowercase encoding name
108     that is understood by the system's iconv_open but not listed in our
109     mappings table.  */
110  {
111    iconv_t cd = iconv_open (tocode, fromcode);
112    if (cd != (iconv_t)(-1))
113      return cd;
114  }
115
116  /* Convert the encodings to upper case, because
117       1. in the arguments of iconv_open() on AIX, HP-UX, and OSF/1 the case
118	  matters,
119       2. it makes searching in the table faster.  */
120  {
121    const char *p = fromcode;
122    char *q = fromcode_upper;
123    while ((*q = c_toupper (*p)) != '\0')
124      {
125	p++;
126	q++;
127	if (q == &fromcode_upper[SIZEOF (fromcode_upper)])
128	  {
129	    errno = EINVAL;
130	    return (iconv_t)(-1);
131	  }
132      }
133    fromcode_upper_end = q;
134  }
135
136  {
137    const char *p = tocode;
138    char *q = tocode_upper;
139    while ((*q = c_toupper (*p)) != '\0')
140      {
141	p++;
142	q++;
143	if (q == &tocode_upper[SIZEOF (tocode_upper)])
144	  {
145	    errno = EINVAL;
146	    return (iconv_t)(-1);
147	  }
148      }
149    tocode_upper_end = q;
150  }
151
152#ifdef ICONV_FLAVOR
153  /* Apply the mappings.  */
154  {
155    const struct mapping *m =
156      mapping_lookup (fromcode_upper, fromcode_upper_end - fromcode_upper);
157
158    fromcode = (m != NULL ? m->vendor_name : fromcode_upper);
159  }
160  {
161    const struct mapping *m =
162      mapping_lookup (tocode_upper, tocode_upper_end - tocode_upper);
163
164    tocode = (m != NULL ? m->vendor_name : tocode_upper);
165  }
166#else
167  fromcode = fromcode_upper;
168  tocode = tocode_upper;
169#endif
170
171  return iconv_open (tocode, fromcode);
172}
173