1 /*
2 * Copyright (c) 2011-2012 - Mauro Carvalho Chehab
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation version 2.1 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
17 */
18
19 /*
20 * handle character set correctly (e.g. via iconv)
21 * c.f. EN 300 468 annex A
22 */
23
24 #include <iconv.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <strings.h> /* strcasecmp */
29
30 #include <parse_string.h>
31 #include <libdvbv5/dvb-log.h>
32 #include <libdvbv5/dvb-fe.h>
33
34 #define CS_OPTIONS "//TRANSLIT"
35
36 struct charset_conv {
37 unsigned len;
38 unsigned char data[3];
39 };
40
41 /* This table is the Latin 00 table. Basically ISO-6937 + Euro sign */
42 static struct charset_conv en300468_latin_00_to_utf8[256] = {
43 [0x00] = { 1, {0x00, } },
44 [0x01] = { 1, {0x01, } },
45 [0x02] = { 1, {0x02, } },
46 [0x03] = { 1, {0x03, } },
47 [0x04] = { 1, {0x04, } },
48 [0x05] = { 1, {0x05, } },
49 [0x06] = { 1, {0x06, } },
50 [0x07] = { 1, {0x07, } },
51 [0x08] = { 1, {0x08, } },
52 [0x09] = { 1, {0x09, } },
53 [0x0a] = { 1, {0x0a, } },
54 [0x0b] = { 1, {0x0b, } },
55 [0x0c] = { 1, {0x0c, } },
56 [0x0d] = { 1, {0x0d, } },
57 [0x0e] = { 1, {0x0e, } },
58 [0x0f] = { 1, {0x0f, } },
59 [0x10] = { 1, {0x10, } },
60 [0x11] = { 1, {0x11, } },
61 [0x12] = { 1, {0x12, } },
62 [0x13] = { 1, {0x13, } },
63 [0x14] = { 1, {0x14, } },
64 [0x15] = { 1, {0x15, } },
65 [0x16] = { 1, {0x16, } },
66 [0x17] = { 1, {0x17, } },
67 [0x18] = { 1, {0x18, } },
68 [0x19] = { 1, {0x19, } },
69 [0x1a] = { 1, {0x1a, } },
70 [0x1b] = { 1, {0x1b, } },
71 [0x1c] = { 1, {0x1c, } },
72 [0x1d] = { 1, {0x1d, } },
73 [0x1e] = { 1, {0x1e, } },
74 [0x1f] = { 1, {0x1f, } },
75 [0x20] = { 1, {0x20, } },
76 [0x21] = { 1, {0x21, } },
77 [0x22] = { 1, {0x22, } },
78 [0x23] = { 1, {0x23, } },
79 [0x24] = { 1, {0x24, } },
80 [0x25] = { 1, {0x25, } },
81 [0x26] = { 1, {0x26, } },
82 [0x27] = { 1, {0x27, } },
83 [0x28] = { 1, {0x28, } },
84 [0x29] = { 1, {0x29, } },
85 [0x2a] = { 1, {0x2a, } },
86 [0x2b] = { 1, {0x2b, } },
87 [0x2c] = { 1, {0x2c, } },
88 [0x2d] = { 1, {0x2d, } },
89 [0x2e] = { 1, {0x2e, } },
90 [0x2f] = { 1, {0x2f, } },
91 [0x30] = { 1, {0x30, } },
92 [0x31] = { 1, {0x31, } },
93 [0x32] = { 1, {0x32, } },
94 [0x33] = { 1, {0x33, } },
95 [0x34] = { 1, {0x34, } },
96 [0x35] = { 1, {0x35, } },
97 [0x36] = { 1, {0x36, } },
98 [0x37] = { 1, {0x37, } },
99 [0x38] = { 1, {0x38, } },
100 [0x39] = { 1, {0x39, } },
101 [0x3a] = { 1, {0x3a, } },
102 [0x3b] = { 1, {0x3b, } },
103 [0x3c] = { 1, {0x3c, } },
104 [0x3d] = { 1, {0x3d, } },
105 [0x3e] = { 1, {0x3e, } },
106 [0x3f] = { 1, {0x3f, } },
107 [0x40] = { 1, {0x40, } },
108 [0x41] = { 1, {0x41, } },
109 [0x42] = { 1, {0x42, } },
110 [0x43] = { 1, {0x43, } },
111 [0x44] = { 1, {0x44, } },
112 [0x45] = { 1, {0x45, } },
113 [0x46] = { 1, {0x46, } },
114 [0x47] = { 1, {0x47, } },
115 [0x48] = { 1, {0x48, } },
116 [0x49] = { 1, {0x49, } },
117 [0x4a] = { 1, {0x4a, } },
118 [0x4b] = { 1, {0x4b, } },
119 [0x4c] = { 1, {0x4c, } },
120 [0x4d] = { 1, {0x4d, } },
121 [0x4e] = { 1, {0x4e, } },
122 [0x4f] = { 1, {0x4f, } },
123 [0x50] = { 1, {0x50, } },
124 [0x51] = { 1, {0x51, } },
125 [0x52] = { 1, {0x52, } },
126 [0x53] = { 1, {0x53, } },
127 [0x54] = { 1, {0x54, } },
128 [0x55] = { 1, {0x55, } },
129 [0x56] = { 1, {0x56, } },
130 [0x57] = { 1, {0x57, } },
131 [0x58] = { 1, {0x58, } },
132 [0x59] = { 1, {0x59, } },
133 [0x5a] = { 1, {0x5a, } },
134 [0x5b] = { 1, {0x5b, } },
135 [0x5c] = { 1, {0x5c, } },
136 [0x5d] = { 1, {0x5d, } },
137 [0x5e] = { 1, {0x5e, } },
138 [0x5f] = { 1, {0x5f, } },
139 [0x60] = { 1, {0x60, } },
140 [0x61] = { 1, {0x61, } },
141 [0x62] = { 1, {0x62, } },
142 [0x63] = { 1, {0x63, } },
143 [0x64] = { 1, {0x64, } },
144 [0x65] = { 1, {0x65, } },
145 [0x66] = { 1, {0x66, } },
146 [0x67] = { 1, {0x67, } },
147 [0x68] = { 1, {0x68, } },
148 [0x69] = { 1, {0x69, } },
149 [0x6a] = { 1, {0x6a, } },
150 [0x6b] = { 1, {0x6b, } },
151 [0x6c] = { 1, {0x6c, } },
152 [0x6d] = { 1, {0x6d, } },
153 [0x6e] = { 1, {0x6e, } },
154 [0x6f] = { 1, {0x6f, } },
155 [0x70] = { 1, {0x70, } },
156 [0x71] = { 1, {0x71, } },
157 [0x72] = { 1, {0x72, } },
158 [0x73] = { 1, {0x73, } },
159 [0x74] = { 1, {0x74, } },
160 [0x75] = { 1, {0x75, } },
161 [0x76] = { 1, {0x76, } },
162 [0x77] = { 1, {0x77, } },
163 [0x78] = { 1, {0x78, } },
164 [0x79] = { 1, {0x79, } },
165 [0x7a] = { 1, {0x7a, } },
166 [0x7b] = { 1, {0x7b, } },
167 [0x7c] = { 1, {0x7c, } },
168 [0x7d] = { 1, {0x7d, } },
169 [0x7e] = { 1, {0x7e, } },
170 [0x7f] = { 1, {0x7f, } },
171 [0x80] = { 2, {0xc2, 0x80, } },
172 [0x81] = { 2, {0xc2, 0x81, } },
173 [0x82] = { 2, {0xc2, 0x82, } },
174 [0x83] = { 2, {0xc2, 0x83, } },
175 [0x84] = { 2, {0xc2, 0x84, } },
176 [0x85] = { 2, {0xc2, 0x85, } },
177 [0x86] = { 2, {0xc2, 0x86, } },
178 [0x87] = { 2, {0xc2, 0x87, } },
179 [0x88] = { 2, {0xc2, 0x88, } },
180 [0x89] = { 2, {0xc2, 0x89, } },
181 [0x8a] = { 2, {0xc2, 0x8a, } },
182 [0x8b] = { 2, {0xc2, 0x8b, } },
183 [0x8c] = { 2, {0xc2, 0x8c, } },
184 [0x8d] = { 2, {0xc2, 0x8d, } },
185 [0x8e] = { 2, {0xc2, 0x8e, } },
186 [0x8f] = { 2, {0xc2, 0x8f, } },
187 [0x90] = { 2, {0xc2, 0x90, } },
188 [0x91] = { 2, {0xc2, 0x91, } },
189 [0x92] = { 2, {0xc2, 0x92, } },
190 [0x93] = { 2, {0xc2, 0x93, } },
191 [0x94] = { 2, {0xc2, 0x94, } },
192 [0x95] = { 2, {0xc2, 0x95, } },
193 [0x96] = { 2, {0xc2, 0x96, } },
194 [0x97] = { 2, {0xc2, 0x97, } },
195 [0x98] = { 2, {0xc2, 0x98, } },
196 [0x99] = { 2, {0xc2, 0x99, } },
197 [0x9a] = { 2, {0xc2, 0x9a, } },
198 [0x9b] = { 2, {0xc2, 0x9b, } },
199 [0x9c] = { 2, {0xc2, 0x9c, } },
200 [0x9d] = { 2, {0xc2, 0x9d, } },
201 [0x9e] = { 2, {0xc2, 0x9e, } },
202 [0x9f] = { 2, {0xc2, 0x9f, } },
203 [0xa0] = { 2, {0xc2, 0xa0, } },
204 [0xa1] = { 2, {0xc2, 0xa1, } },
205 [0xa2] = { 2, {0xc2, 0xa2, } },
206 [0xa3] = { 2, {0xc2, 0xa3, } },
207 [0xa4] = { 3, { 0xe2, 0x82, 0xac,} }, /* Euro sign. Addition over the ISO-6937 standard */
208 [0xa5] = { 2, {0xc2, 0xa5, } },
209 [0xa6] = { 0, {} },
210 [0xa7] = { 2, {0xc2, 0xa7, } },
211 [0xa8] = { 2, {0xc2, 0xa4, } },
212 [0xa9] = { 3, {0xe2, 0x80, 0x98, } },
213 [0xaa] = { 3, {0xe2, 0x80, 0x9c, } },
214 [0xab] = { 2, {0xc2, 0xab, } },
215 [0xac] = { 3, {0xe2, 0x86, 0x90, } },
216 [0xad] = { 3, {0xe2, 0x86, 0x91, } },
217 [0xae] = { 3, {0xe2, 0x86, 0x92, } },
218 [0xaf] = { 3, {0xe2, 0x86, 0x93, } },
219 [0xb0] = { 2, {0xc2, 0xb0, } },
220 [0xb1] = { 2, {0xc2, 0xb1, } },
221 [0xb2] = { 2, {0xc2, 0xb2, } },
222 [0xb3] = { 2, {0xc2, 0xb3, } },
223 [0xb4] = { 2, {0xc3, 0x97, } },
224 [0xb5] = { 2, {0xc2, 0xb5, } },
225 [0xb6] = { 2, {0xc2, 0xb6, } },
226 [0xb7] = { 2, {0xc2, 0xb7, } },
227 [0xb8] = { 2, {0xc3, 0xb7, } },
228 [0xb9] = { 3, {0xe2, 0x80, 0x99, } },
229 [0xba] = { 3, {0xe2, 0x80, 0x9d, } },
230 [0xbb] = { 2, {0xc2, 0xbb, } },
231 [0xbc] = { 2, {0xc2, 0xbc, } },
232 [0xbd] = { 2, {0xc2, 0xbd, } },
233 [0xbe] = { 2, {0xc2, 0xbe, } },
234 [0xbf] = { 2, {0xc2, 0xbf, } },
235 [0xc0] = { 0, {} },
236 [0xc1] = { 0, {} },
237 [0xc2] = { 0, {} },
238 [0xc3] = { 0, {} },
239 [0xc4] = { 0, {} },
240 [0xc5] = { 0, {} },
241 [0xc6] = { 0, {} },
242 [0xc7] = { 0, {} },
243 [0xc8] = { 0, {} },
244 [0xc9] = { 0, {} },
245 [0xca] = { 0, {} },
246 [0xcb] = { 0, {} },
247 [0xcc] = { 0, {} },
248 [0xcd] = { 0, {} },
249 [0xce] = { 0, {} },
250 [0xcf] = { 0, {} },
251 [0xd0] = { 3, {0xe2, 0x80, 0x94, } },
252 [0xd1] = { 2, {0xc2, 0xb9, } },
253 [0xd2] = { 2, {0xc2, 0xae, } },
254 [0xd3] = { 2, {0xc2, 0xa9, } },
255 [0xd4] = { 3, {0xe2, 0x84, 0xa2, } },
256 [0xd5] = { 3, {0xe2, 0x99, 0xaa, } },
257 [0xd6] = { 2, {0xc2, 0xac, } },
258 [0xd7] = { 2, {0xc2, 0xa6, } },
259 [0xd8] = { 0, {} },
260 [0xd9] = { 0, {} },
261 [0xda] = { 0, {} },
262 [0xdb] = { 0, {} },
263 [0xdc] = { 3, {0xe2, 0x85, 0x9b, } },
264 [0xdd] = { 3, {0xe2, 0x85, 0x9c, } },
265 [0xde] = { 3, {0xe2, 0x85, 0x9d, } },
266 [0xdf] = { 3, {0xe2, 0x85, 0x9e, } },
267 [0xe0] = { 3, {0xe2, 0x84, 0xa6, } },
268 [0xe1] = { 2, {0xc3, 0x86, } },
269 [0xe2] = { 2, {0xc3, 0x90, } },
270 [0xe3] = { 2, {0xc2, 0xaa, } },
271 [0xe4] = { 2, {0xc4, 0xa6, } },
272 [0xe5] = { 0, {} },
273 [0xe6] = { 2, {0xc4, 0xb2, } },
274 [0xe7] = { 2, {0xc4, 0xbf, } },
275 [0xe8] = { 2, {0xc5, 0x81, } },
276 [0xe9] = { 2, {0xc3, 0x98, } },
277 [0xea] = { 2, {0xc5, 0x92, } },
278 [0xeb] = { 2, {0xc2, 0xba, } },
279 [0xec] = { 2, {0xc3, 0x9e, } },
280 [0xed] = { 2, {0xc5, 0xa6, } },
281 [0xee] = { 2, {0xc5, 0x8a, } },
282 [0xef] = { 2, {0xc5, 0x89, } },
283 [0xf0] = { 2, {0xc4, 0xb8, } },
284 [0xf1] = { 2, {0xc3, 0xa6, } },
285 [0xf2] = { 2, {0xc4, 0x91, } },
286 [0xf3] = { 2, {0xc3, 0xb0, } },
287 [0xf4] = { 2, {0xc4, 0xa7, } },
288 [0xf5] = { 2, {0xc4, 0xb1, } },
289 [0xf6] = { 2, {0xc4, 0xb3, } },
290 [0xf7] = { 2, {0xc5, 0x80, } },
291 [0xf8] = { 2, {0xc5, 0x82, } },
292 [0xf9] = { 2, {0xc3, 0xb8, } },
293 [0xfa] = { 2, {0xc5, 0x93, } },
294 [0xfb] = { 2, {0xc3, 0x9f, } },
295 [0xfc] = { 2, {0xc3, 0xbe, } },
296 [0xfd] = { 2, {0xc5, 0xa7, } },
297 [0xfe] = { 2, {0xc5, 0x8b, } },
298 [0xff] = { 2, {0xc2, 0xad, } },
299 };
300
dvb_iconv_to_charset(struct dvb_v5_fe_parms * parms,char * dest,size_t destlen,const unsigned char * src,size_t len,char * input_charset,char * output_charset)301 void dvb_iconv_to_charset(struct dvb_v5_fe_parms *parms,
302 char *dest,
303 size_t destlen,
304 const unsigned char *src,
305 size_t len,
306 char *input_charset, char *output_charset)
307 {
308 char out_cs[strlen(output_charset) + 1 + sizeof(CS_OPTIONS)];
309 char *p = dest;
310
311 strcpy(out_cs, output_charset);
312 strcat(out_cs, CS_OPTIONS);
313
314 iconv_t cd = iconv_open(out_cs, input_charset);
315 if (cd == (iconv_t)(-1)) {
316 memcpy(p, src, len);
317 p[len] = '\0';
318 dvb_logerr("Conversion from %s to %s not supported\n",
319 input_charset, output_charset);
320 if (!strcasecmp(input_charset, "ARIB-STD-B24"))
321 dvb_log("Try setting GCONV_PATH to the bundled gconv dir.\n");
322 } else {
323 iconv(cd, (ICONV_CONST char **)&src, &len, &p, &destlen);
324 iconv_close(cd);
325 *p = '\0';
326 }
327 }
328
charset_conversion(struct dvb_v5_fe_parms * parms,char ** dest,const unsigned char * s,size_t len,char * input_charset)329 static void charset_conversion(struct dvb_v5_fe_parms *parms, char **dest, const unsigned char *s,
330 size_t len, char *input_charset)
331 {
332 size_t destlen = len * 3;
333 int need_conversion = 1;
334
335 /* Special handler for ISO-6937 */
336 if (!strcasecmp(input_charset, "ISO-6937")) {
337 char *p = *dest;
338 unsigned char *tmp;
339 unsigned char *p1, *p2;
340
341 /* Convert charset to UTF-8 using Code table 00 - Latin */
342 for (p1 = (unsigned char *)s; p1 < s + len; p1++)
343 for (p2 = en300468_latin_00_to_utf8[*p1].data;
344 p2 < en300468_latin_00_to_utf8[*p1].data + en300468_latin_00_to_utf8[*p1].len;
345 p2++)
346 *p++ = *p2;
347 *p = '\0';
348
349 /* If desired charset is not UTF-8, prepare for conversion */
350 if (strcasecmp(parms->output_charset, "UTF-8")) {
351 tmp = (unsigned char *)*dest;
352 len = p - *dest;
353
354 *dest = malloc(destlen + 1);
355 input_charset = "UTF-8";
356 s = tmp;
357 } else
358 need_conversion = 0;
359
360 }
361
362 /* Convert from original charset to the desired one */
363 if (need_conversion)
364 dvb_iconv_to_charset(parms, *dest, destlen, s, len,
365 input_charset,
366 parms->output_charset);
367 }
368
dvb_parse_string(struct dvb_v5_fe_parms * parms,char ** dest,char ** emph,const unsigned char * src,size_t len)369 void dvb_parse_string(struct dvb_v5_fe_parms *parms, char **dest, char **emph,
370 const unsigned char *src, size_t len)
371 {
372 size_t destlen, i, len2 = 0;
373 char *p, *p2, *type = parms->default_charset;
374 unsigned char *tmp1 = NULL, *tmp2 = NULL;
375 const unsigned char *s;
376 int emphasis = 0;
377
378 if (*dest) {
379 free(*dest);
380 *dest = NULL;
381 }
382 if (*emph) {
383 free(*emph);
384 *emph = NULL;
385 }
386 if (!len)
387 return;
388
389 /*
390 * Strings in ISDB-S/T(JP) do not start with a charset identifier,
391 * and can start with a control character (< 0x20).
392 */
393 if (strcasecmp(type, "ARIB-STD-B24") && *src < 0x20) {
394 switch (*src) {
395 case 0x00: type = "ISO-6937"; break;
396 case 0x01: type = "ISO-8859-5"; break;
397 case 0x02: type = "ISO-8859-6"; break;
398 case 0x03: type = "ISO-8859-7"; break;
399 case 0x04: type = "ISO-8859-8"; break;
400 case 0x05: type = "ISO-8859-9"; break;
401 case 0x06: type = "ISO-8859-10"; break;
402 case 0x07: type = "ISO-8859-11"; break;
403 case 0x09: type = "ISO-8859-13"; break;
404 case 0x0a: type = "ISO-8859-14"; break;
405 case 0x0b: type = "ISO-8859-15"; break;
406 case 0x11: type = "ISO-10646/UCS2"; break;
407 case 0x12: type = "ISO-2022-KR"; break;
408 case 0x13: type = "GB2312"; break;
409 case 0x14: type = "UTF-16BE"; break;
410 case 0x15: type = "ISO-10646/UTF-8"; break;
411 case 0x10: /* ISO8859 */
412 if (len < 2)
413 break;
414 if ((*(src + 1) != 0) || *(src + 2) > 0x0f)
415 break;
416 src+=2;
417 len-=2;
418 switch(*src) {
419 case 0x01: type = "ISO-8859-1"; break;
420 case 0x02: type = "ISO-8859-2"; break;
421 case 0x03: type = "ISO-8859-3"; break;
422 case 0x04: type = "ISO-8859-4"; break;
423 case 0x05: type = "ISO-8859-5"; break;
424 case 0x06: type = "ISO-8859-6"; break;
425 case 0x07: type = "ISO-8859-7"; break;
426 case 0x08: type = "ISO-8859-8"; break;
427 case 0x09: type = "ISO-8859-9"; break;
428 case 0x0a: type = "ISO-8859-10"; break;
429 case 0x0b: type = "ISO-8859-11"; break;
430 case 0x0d: type = "ISO-8859-13"; break;
431 case 0x0e: type = "ISO-8859-14"; break;
432 case 0x0f: type = "ISO-8859-15"; break;
433 }
434 }
435 src++;
436 len--;
437 }
438
439 /*
440 * Destination length should be bigger. As the worse case seems to
441 * use 3 chars for one code, use it for destlen
442 */
443 destlen = len * 3;
444 *dest = malloc(destlen + 1);
445 *emph = malloc(destlen + 1);
446
447 /* Remove special chars */
448 if (!strncasecmp(type, "ISO-8859", 8) || !strcasecmp(type, "ISO-6937") || !strcasecmp(type, "ISO-10646/UTF-8")) {
449 /*
450 * Handles the ISO/IEC 10646 1-byte control codes
451 * (EN 300 468 v1.11.1 Table A.1)
452 */
453 tmp1 = malloc(len + 2);
454 tmp2 = malloc(len + 2);
455 p = (char *)tmp1;
456 p2 = (char *)tmp2;
457 s = src;
458 for (i = 0; i < len; i++, s++) {
459 if (*s == 0x86)
460 emphasis = 1;
461 else if (*s == 0x87 && emphasis)
462 emphasis = 0;
463 else if (*s >= 0x20 && (*s < 0x80 || *s > 0x9f)) {
464 *p++ = *s;
465 if (emphasis)
466 *p2++ = *s;
467 }
468 else if (*s == 0x8a)
469 *p++ = '\n';
470 }
471 *p = '\0';
472 *p2 = '\0';
473 len = p - (char *)tmp1;
474 len2 = p2 - (char *)tmp2;
475 } else if (!strcasecmp(type, "ISO-10646/UCS2")) {
476 /*
477 * Handles the ISO/IEC 10646 2-bytes control codes
478 * (EN 300 468 v1.11.1 Table A.2)
479 */
480 uint16_t *in_code = (void *)src;
481 uint16_t *out_code;
482 uint16_t *out_emph;
483
484 tmp1 = malloc(len + 2);
485 tmp2 = malloc(len + 2);
486 out_code = (void *)tmp1;
487 out_emph = (void *)tmp2;
488
489 for (i = 0; i < len / 2; i ++, in_code++) {
490 uint16_t code = *in_code;
491
492 /*
493 * FIXME: should it do bswap16(code) here?
494 */
495 if (code == 0xe086)
496 emphasis = 1;
497 else if (code == 0xe087 && emphasis)
498 emphasis = 0;
499 else if (code == 0xe08a)
500 /* newline, append code blow */ ;
501 else if (code >= 0xe080 && code <= 0xe09f)
502 continue;
503
504 *out_code++ = code;
505 if (emphasis)
506 *out_emph++ = code;
507 }
508 *out_code = 0;
509 *out_emph = 0;
510 len = (char *)out_code - (char *)tmp1;
511 len2 = (char *)out_emph - (char *)tmp2;
512 }
513
514 if (tmp1)
515 s = tmp1;
516 else
517 s = src;
518
519 charset_conversion(parms, dest, s, len, type);
520 /* The code had over-sized the space. Fix it. */
521 if (*dest)
522 *dest = realloc(*dest, strlen(*dest) + 1);
523
524 if (!len2) {
525 if (tmp2) {
526 free (tmp2);
527 tmp2 = NULL;
528 }
529 free (*emph);
530 *emph = NULL;
531 } else {
532 charset_conversion(parms, emph, tmp2, len2, type);
533 *emph = realloc(*emph, strlen(*emph) + 1);
534 }
535
536 if (tmp1)
537 free(tmp1);
538 if (tmp2)
539 free(tmp2);
540 }
541
542