Mercurial > hg > octave-lojdl > gnulib-hg
annotate lib/striconveha.c @ 16201:8250f2777afc
maint: update all copyright year number ranges
Run "make update-copyright".
author | Jim Meyering <meyering@redhat.com> |
---|---|
date | Sun, 01 Jan 2012 10:04:58 +0100 |
parents | 97fc9a21a8fb |
children | e542fd46ad6f |
rev | line source |
---|---|
7919 | 1 /* Character set conversion with error handling and autodetection. |
16201
8250f2777afc
maint: update all copyright year number ranges
Jim Meyering <meyering@redhat.com>
parents:
14079
diff
changeset
|
2 Copyright (C) 2002, 2005, 2007, 2009-2012 Free Software Foundation, Inc. |
7919 | 3 Written by Bruno Haible. |
4 | |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8948
diff
changeset
|
5 This program is free software: you can redistribute it and/or modify |
7919 | 6 it under the terms of the GNU General Public License as published by |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8948
diff
changeset
|
7 the Free Software Foundation; either version 3 of the License, or |
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8948
diff
changeset
|
8 (at your option) any later version. |
7919 | 9 |
10 This program is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 GNU General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU General Public License | |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8948
diff
changeset
|
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
7919 | 17 |
18 #include <config.h> | |
19 | |
20 /* Specification. */ | |
21 #include "striconveha.h" | |
22 | |
23 #include <errno.h> | |
24 #include <stdlib.h> | |
25 #include <string.h> | |
26 | |
8948
a162347a0232
Update after allocsa -> malloca renaming.
Bruno Haible <bruno@clisp.org>
parents:
7944
diff
changeset
|
27 #include "malloca.h" |
7931
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
28 #include "c-strcase.h" |
11477
63b291ae83b6
Add include that is no longer done by striconveha.h.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
29 #include "striconveh.h" |
7931
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
30 |
7919 | 31 #define SIZEOF(a) (sizeof(a)/sizeof(a[0])) |
32 | |
33 | |
34 /* Autodetection list. */ | |
35 | |
36 struct autodetect_alias | |
37 { | |
38 struct autodetect_alias *next; | |
39 const char *name; | |
40 const char * const *encodings_to_try; | |
41 }; | |
42 | |
43 static const char * const autodetect_utf8_try[] = | |
44 { | |
45 /* Try UTF-8 first. There are very few ISO-8859-1 inputs that would | |
46 be valid UTF-8, but many UTF-8 inputs are valid ISO-8859-1. */ | |
47 "UTF-8", "ISO-8859-1", | |
48 NULL | |
49 }; | |
50 static const char * const autodetect_jp_try[] = | |
51 { | |
52 /* Try 7-bit encoding first. If the input contains bytes >= 0x80, | |
53 it will fail. | |
54 Try EUC-JP next. Short SHIFT_JIS inputs may come out wrong. This | |
55 is unavoidable. People will condemn SHIFT_JIS. | |
56 If we tried SHIFT_JIS first, then some short EUC-JP inputs would | |
57 come out wrong, and people would condemn EUC-JP and Unix, which | |
58 would not be good. | |
59 Finally try SHIFT_JIS. */ | |
60 "ISO-2022-JP-2", "EUC-JP", "SHIFT_JIS", | |
61 NULL | |
62 }; | |
63 static const char * const autodetect_kr_try[] = | |
64 { | |
65 /* Try 7-bit encoding first. If the input contains bytes >= 0x80, | |
66 it will fail. | |
67 Finally try EUC-KR. */ | |
68 "ISO-2022-KR", "EUC-KR", | |
69 NULL | |
70 }; | |
71 | |
72 static struct autodetect_alias autodetect_predefined[] = | |
73 { | |
74 { &autodetect_predefined[1], "autodetect_utf8", autodetect_utf8_try }, | |
75 { &autodetect_predefined[2], "autodetect_jp", autodetect_jp_try }, | |
76 { NULL, "autodetect_kr", autodetect_kr_try } | |
77 }; | |
78 | |
79 static struct autodetect_alias *autodetect_list = &autodetect_predefined[0]; | |
80 static struct autodetect_alias **autodetect_list_end = | |
81 &autodetect_predefined[SIZEOF(autodetect_predefined)-1].next; | |
82 | |
83 int | |
84 uniconv_register_autodetect (const char *name, | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
85 const char * const *try_in_order) |
7919 | 86 { |
87 size_t namelen; | |
88 size_t listlen; | |
89 size_t memneed; | |
90 size_t i; | |
91 char *memory; | |
92 struct autodetect_alias *new_alias; | |
93 char *new_name; | |
94 const char **new_try_in_order; | |
95 | |
96 /* The TRY_IN_ORDER list must not be empty. */ | |
97 if (try_in_order[0] == NULL) | |
98 { | |
99 errno = EINVAL; | |
100 return -1; | |
101 } | |
102 | |
103 /* We must deep-copy NAME and TRY_IN_ORDER, because they may be allocated | |
104 with dynamic extent. */ | |
105 namelen = strlen (name) + 1; | |
106 memneed = sizeof (struct autodetect_alias) + namelen + sizeof (char *); | |
107 for (i = 0; try_in_order[i] != NULL; i++) | |
108 memneed += sizeof (char *) + strlen (try_in_order[i]) + 1; | |
109 listlen = i; | |
110 | |
111 memory = (char *) malloc (memneed); | |
112 if (memory != NULL) | |
113 { | |
114 new_alias = (struct autodetect_alias *) memory; | |
115 memory += sizeof (struct autodetect_alias); | |
116 | |
117 new_try_in_order = (const char **) memory; | |
118 memory += (listlen + 1) * sizeof (char *); | |
119 | |
120 new_name = (char *) memory; | |
121 memcpy (new_name, name, namelen); | |
122 memory += namelen; | |
123 | |
124 for (i = 0; i < listlen; i++) | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
125 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
126 size_t len = strlen (try_in_order[i]) + 1; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
127 memcpy (memory, try_in_order[i], len); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
128 new_try_in_order[i] = (const char *) memory; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
129 memory += len; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
130 } |
7919 | 131 new_try_in_order[i] = NULL; |
132 | |
133 /* Now insert the new alias. */ | |
134 new_alias->name = new_name; | |
135 new_alias->encodings_to_try = new_try_in_order; | |
136 new_alias->next = NULL; | |
137 /* FIXME: Not multithread-safe. */ | |
138 *autodetect_list_end = new_alias; | |
139 autodetect_list_end = &new_alias->next; | |
140 return 0; | |
141 } | |
142 else | |
143 { | |
144 errno = ENOMEM; | |
145 return -1; | |
146 } | |
147 } | |
148 | |
7931
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
149 /* Like mem_iconveha, except no handling of transliteration. */ |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
150 static int |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
151 mem_iconveha_notranslit (const char *src, size_t srclen, |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
152 const char *from_codeset, const char *to_codeset, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
153 enum iconv_ilseq_handler handler, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
154 size_t *offsets, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
155 char **resultp, size_t *lengthp) |
7919 | 156 { |
157 int retval = mem_iconveh (src, srclen, from_codeset, to_codeset, handler, | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
158 offsets, resultp, lengthp); |
7919 | 159 if (retval >= 0 || errno != EINVAL) |
160 return retval; | |
161 else | |
162 { | |
163 struct autodetect_alias *alias; | |
164 | |
165 /* Unsupported from_codeset or to_codeset. Check whether the caller | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
166 requested autodetection. */ |
7919 | 167 for (alias = autodetect_list; alias != NULL; alias = alias->next) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
168 if (strcmp (from_codeset, alias->name) == 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
169 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
170 const char * const *encodings; |
7919 | 171 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
172 if (handler != iconveh_error) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
173 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
174 /* First try all encodings without any forgiving. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
175 encodings = alias->encodings_to_try; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
176 do |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
177 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
178 retval = mem_iconveha_notranslit (src, srclen, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
179 *encodings, to_codeset, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
180 iconveh_error, offsets, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
181 resultp, lengthp); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
182 if (!(retval < 0 && errno == EILSEQ)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
183 return retval; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
184 encodings++; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
185 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
186 while (*encodings != NULL); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
187 } |
7930
8929067c3772
Make the striconveha module actually work.
Bruno Haible <bruno@clisp.org>
parents:
7927
diff
changeset
|
188 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
189 encodings = alias->encodings_to_try; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
190 do |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
191 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
192 retval = mem_iconveha_notranslit (src, srclen, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
193 *encodings, to_codeset, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
194 handler, offsets, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
195 resultp, lengthp); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
196 if (!(retval < 0 && errno == EILSEQ)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
197 return retval; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
198 encodings++; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
199 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
200 while (*encodings != NULL); |
7919 | 201 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
202 /* Return the last call's result. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
203 return -1; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
204 } |
7919 | 205 |
206 /* It wasn't an autodetection name. */ | |
207 errno = EINVAL; | |
208 return -1; | |
209 } | |
210 } | |
211 | |
7931
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
212 int |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
213 mem_iconveha (const char *src, size_t srclen, |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
214 const char *from_codeset, const char *to_codeset, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
215 bool transliterate, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
216 enum iconv_ilseq_handler handler, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
217 size_t *offsets, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
218 char **resultp, size_t *lengthp) |
7931
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
219 { |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
220 if (srclen == 0) |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
221 { |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
222 /* Nothing to convert. */ |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
223 *lengthp = 0; |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
224 return 0; |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
225 } |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
226 |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
227 /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5, |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
228 we want to use transliteration. */ |
13885 | 229 #if (((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2) \ |
230 && !defined __UCLIBC__) \ | |
231 || _LIBICONV_VERSION >= 0x0105 | |
7931
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
232 if (transliterate) |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
233 { |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
234 int retval; |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
235 size_t len = strlen (to_codeset); |
8948
a162347a0232
Update after allocsa -> malloca renaming.
Bruno Haible <bruno@clisp.org>
parents:
7944
diff
changeset
|
236 char *to_codeset_suffixed = (char *) malloca (len + 10 + 1); |
7931
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
237 memcpy (to_codeset_suffixed, to_codeset, len); |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
238 memcpy (to_codeset_suffixed + len, "//TRANSLIT", 10 + 1); |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
239 |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
240 retval = mem_iconveha_notranslit (src, srclen, |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
241 from_codeset, to_codeset_suffixed, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
242 handler, offsets, resultp, lengthp); |
7931
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
243 |
8948
a162347a0232
Update after allocsa -> malloca renaming.
Bruno Haible <bruno@clisp.org>
parents:
7944
diff
changeset
|
244 freea (to_codeset_suffixed); |
7931
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
245 |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
246 return retval; |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
247 } |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
248 else |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
249 #endif |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
250 return mem_iconveha_notranslit (src, srclen, |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
251 from_codeset, to_codeset, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
252 handler, offsets, resultp, lengthp); |
7931
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
253 } |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
254 |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
255 /* Like str_iconveha, except no handling of transliteration. */ |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
256 static char * |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
257 str_iconveha_notranslit (const char *src, |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
258 const char *from_codeset, const char *to_codeset, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
259 enum iconv_ilseq_handler handler) |
7919 | 260 { |
261 char *result = str_iconveh (src, from_codeset, to_codeset, handler); | |
262 | |
263 if (result != NULL || errno != EINVAL) | |
264 return result; | |
265 else | |
266 { | |
267 struct autodetect_alias *alias; | |
268 | |
269 /* Unsupported from_codeset or to_codeset. Check whether the caller | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
270 requested autodetection. */ |
7919 | 271 for (alias = autodetect_list; alias != NULL; alias = alias->next) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
272 if (strcmp (from_codeset, alias->name) == 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
273 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
274 const char * const *encodings; |
7919 | 275 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
276 if (handler != iconveh_error) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
277 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
278 /* First try all encodings without any forgiving. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
279 encodings = alias->encodings_to_try; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
280 do |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
281 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
282 result = str_iconveha_notranslit (src, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
283 *encodings, to_codeset, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
284 iconveh_error); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
285 if (!(result == NULL && errno == EILSEQ)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
286 return result; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
287 encodings++; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
288 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
289 while (*encodings != NULL); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
290 } |
7930
8929067c3772
Make the striconveha module actually work.
Bruno Haible <bruno@clisp.org>
parents:
7927
diff
changeset
|
291 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
292 encodings = alias->encodings_to_try; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
293 do |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
294 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
295 result = str_iconveha_notranslit (src, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
296 *encodings, to_codeset, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
297 handler); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
298 if (!(result == NULL && errno == EILSEQ)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
299 return result; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
300 encodings++; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
301 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
302 while (*encodings != NULL); |
7919 | 303 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
304 /* Return the last call's result. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
305 return NULL; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
306 } |
7919 | 307 |
308 /* It wasn't an autodetection name. */ | |
309 errno = EINVAL; | |
310 return NULL; | |
311 } | |
312 } | |
7931
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
313 |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
314 char * |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
315 str_iconveha (const char *src, |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
316 const char *from_codeset, const char *to_codeset, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
317 bool transliterate, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
318 enum iconv_ilseq_handler handler) |
7931
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
319 { |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
320 if (*src == '\0' || c_strcasecmp (from_codeset, to_codeset) == 0) |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
321 { |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
322 char *result = strdup (src); |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
323 |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
324 if (result == NULL) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
325 errno = ENOMEM; |
7931
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
326 return result; |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
327 } |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
328 |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
329 /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5, |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
330 we want to use transliteration. */ |
13885 | 331 #if (((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2) \ |
332 && !defined __UCLIBC__) \ | |
333 || _LIBICONV_VERSION >= 0x0105 | |
7931
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
334 if (transliterate) |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
335 { |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
336 char *result; |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
337 size_t len = strlen (to_codeset); |
8948
a162347a0232
Update after allocsa -> malloca renaming.
Bruno Haible <bruno@clisp.org>
parents:
7944
diff
changeset
|
338 char *to_codeset_suffixed = (char *) malloca (len + 10 + 1); |
7931
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
339 memcpy (to_codeset_suffixed, to_codeset, len); |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
340 memcpy (to_codeset_suffixed + len, "//TRANSLIT", 10 + 1); |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
341 |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
342 result = str_iconveha_notranslit (src, from_codeset, to_codeset_suffixed, |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11477
diff
changeset
|
343 handler); |
7931
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
344 |
8948
a162347a0232
Update after allocsa -> malloca renaming.
Bruno Haible <bruno@clisp.org>
parents:
7944
diff
changeset
|
345 freea (to_codeset_suffixed); |
7931
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
346 |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
347 return result; |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
348 } |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
349 else |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
350 #endif |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
351 return str_iconveha_notranslit (src, from_codeset, to_codeset, handler); |
0a4679777f66
Add an optional argument specifying transliteration.
Bruno Haible <bruno@clisp.org>
parents:
7930
diff
changeset
|
352 } |