1 /* Conversion to and from the various ISO 646 CCS.
2    Copyright (C) 1998-2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library 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 GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 /* The implementation of the conversion which can be performed by this
20    module are not very sophisticated and not tuned at all.  There are
21    zillions of ISO 646 derivates and supporting them all in a separate
22    module is overkill since these coded character sets are hardly ever
23    used anymore (except ANSI_X3.4-1968 == ASCII, which is compatible
24    with ISO 8859-1).  The European variants are superceded by the
25    various ISO 8859-? standards and the Asian variants are embedded in
26    larger character sets.  Therefore this implementation is simply
27    here to make it possible to do the conversion if it is necessary.
28    The cost in the gconv-modules file is set to `2' and therefore
29    allows one to easily provide a tuned implementation in case this
30    proofs to be necessary.  */
31 
32 #include <dlfcn.h>
33 #include <gconv.h>
34 #include <stdint.h>
35 #include <stdlib.h>
36 #include <string.h>
37 
38 /* Definitions used in the body of the `gconv' function.  */
39 #define FROM_LOOP		from_ascii
40 #define TO_LOOP			to_ascii
41 #define DEFINE_INIT		0
42 #define DEFINE_FINI		0
43 #define MIN_NEEDED_FROM		1
44 #define MIN_NEEDED_TO		4
45 #define ONE_DIRECTION		0
46 
47 #define FROM_DIRECTION		(dir == from_iso646)
48 #define PREPARE_LOOP \
49   enum direction dir = ((struct iso646_data *) step->__data)->dir;	      \
50   enum variant var = ((struct iso646_data *) step->__data)->var;
51 #define EXTRA_LOOP_ARGS		, var
52 
53 
54 /* Direction of the transformation.  */
55 enum direction
56 {
57   illegal_dir,
58   to_iso646,
59   from_iso646
60 };
61 
62 /* See names below, must be in the same order.  */
63 enum variant
64 {
65   GB,		/* BS_4730 */
66   CA,		/* CSA_Z243.4-1985-1 */
67   CA2,		/* CSA_Z243.4-1985-2 */
68   DE,		/* DIN_66003 */
69   DK,		/* DS_2089 */
70   ES,		/* ES */
71   ES2,		/* ES2 */
72   CN,		/* GB_1988-80 */
73   IT,		/* IT */
74   JP,		/* JIS_C6220-1969-RO */
75   JP_OCR_B,	/* JIS_C6229-1984-B */
76   YU,		/* JUS_I.B1.002 */
77   KR,		/* KSC5636 */
78   HU,		/* MSZ_7795.3 */
79   CU,		/* NC_NC00-10 */
80   FR,		/* NF_Z_62-010 */
81   FR1,		/* NF_Z_62-010_(1973) */
82   NO,		/* NS_4551-1 */
83   NO2,		/* NS_4551-2 */
84   PT,		/* PT */
85   PT2,		/* PT2 */
86   SE,		/* SEN_850200_B */
87   SE2		/* SEN_850200_C */
88 };
89 
90 /* Must be in the same order as enum variant above.  */
91 static const char names[] =
92   "BS_4730//\0"
93   "CSA_Z243.4-1985-1//\0"
94   "CSA_Z243.4-1985-2//\0"
95   "DIN_66003//\0"
96   "DS_2089//\0"
97   "ES//\0"
98   "ES2//\0"
99   "GB_1988-80//\0"
100   "IT//\0"
101   "JIS_C6220-1969-RO//\0"
102   "JIS_C6229-1984-B//\0"
103   "JUS_I.B1.002//\0"
104   "KSC5636//\0"
105   "MSZ_7795.3//\0"
106   "NC_NC00-10//\0"
107   "NF_Z_62-010//\0"
108   "NF_Z_62-010_1973//\0" /* Note that we don't have the parenthesis in
109 			    the name.  */
110   "NS_4551-1//\0"
111   "NS_4551-2//\0"
112   "PT//\0"
113   "PT2//\0"
114   "SEN_850200_B//\0"
115   "SEN_850200_C//\0"
116   "\0";
117 
118 struct iso646_data
119 {
120   enum direction dir;
121   enum variant var;
122 };
123 
124 
125 extern int gconv_init (struct __gconv_step *step);
126 int
gconv_init(struct __gconv_step * step)127 gconv_init (struct __gconv_step *step)
128 {
129   /* Determine which direction.  */
130   struct iso646_data *new_data;
131   enum direction dir = illegal_dir;
132   int result;
133 
134   enum variant var = 0;
135   for (const char *name = names; *name != '\0';
136        name = __rawmemchr (name, '\0') + 1)
137     {
138       if (__strcasecmp (step->__from_name, name) == 0)
139 	{
140 	  dir = from_iso646;
141 	  break;
142 	}
143       else if (__strcasecmp (step->__to_name, name) == 0)
144 	{
145 	  dir = to_iso646;
146 	  break;
147 	}
148       ++var;
149     }
150 
151   result = __GCONV_NOCONV;
152   if (__builtin_expect (dir, from_iso646) != illegal_dir)
153     {
154       new_data = (struct iso646_data *) malloc (sizeof (struct iso646_data));
155 
156       result = __GCONV_NOMEM;
157       if (new_data != NULL)
158 	{
159 	  new_data->dir = dir;
160 	  new_data->var = var;
161 	  step->__data = new_data;
162 
163 	  if (dir == from_iso646)
164 	    {
165 	      step->__min_needed_from = MIN_NEEDED_FROM;
166 	      step->__max_needed_from = MIN_NEEDED_FROM;
167 	      step->__min_needed_to = MIN_NEEDED_TO;
168 	      step->__max_needed_to = MIN_NEEDED_TO;
169 	    }
170 	  else
171 	    {
172 	      step->__min_needed_from = MIN_NEEDED_TO;
173 	      step->__max_needed_from = MIN_NEEDED_TO;
174 	      step->__min_needed_to = MIN_NEEDED_FROM;
175 	      step->__max_needed_to = MIN_NEEDED_FROM;
176 	    }
177 
178 	  step->__stateful = 0;
179 
180 	  result = __GCONV_OK;
181 	}
182     }
183 
184   return result;
185 }
186 
187 
188 extern void gconv_end (struct __gconv_step *data);
189 void
gconv_end(struct __gconv_step * data)190 gconv_end (struct __gconv_step *data)
191 {
192   free (data->__data);
193 }
194 
195 
196 /* First define the conversion function from ASCII to UCS4.  */
197 #define MIN_NEEDED_INPUT	MIN_NEEDED_FROM
198 #define MIN_NEEDED_OUTPUT	MIN_NEEDED_TO
199 #define LOOPFCT			FROM_LOOP
200 #define BODY \
201   {									      \
202     uint32_t ch;							      \
203     int failure = __GCONV_OK;						      \
204 									      \
205     ch = *inptr;							      \
206     switch (ch)								      \
207       {									      \
208       case 0x23:							      \
209 	if (var == GB || var == ES || var == IT || var == FR || var == FR1)   \
210 	  ch = 0xa3;							      \
211 	else if (var == NO2)						      \
212 	  ch = 0xa7;							      \
213 	break;								      \
214       case 0x24:							      \
215 	if (var == CN)							      \
216 	  ch = 0xa5;							      \
217 	else if (var == HU || var == CU || var == SE || var == SE2)	      \
218 	  ch = 0xa4;							      \
219 	break;								      \
220       case 0x40:							      \
221 	if (var == CA || var == CA2 || var == FR || var == FR1)		      \
222 	  ch = 0xe0;							      \
223 	else if (var == DE || var == ES || var == IT || var == PT)	      \
224 	  ch = 0xa7;							      \
225 	else if (var == ES2)						      \
226 	  ch = 0x2022;							      \
227 	else if (var == YU)						      \
228 	  ch = 0x17d;							      \
229 	else if (var == HU)						      \
230 	  ch = 0xc1;							      \
231 	else if (var == PT2)						      \
232 	  ch = 0xb4;							      \
233 	else if (var == SE2)						      \
234 	  ch = 0xc9;							      \
235 	break;								      \
236       case 0x5b:							      \
237 	if (var == CA || var == CA2)					      \
238 	  ch = 0xe2;							      \
239 	else if (var == DE || var == SE || var == SE2)			      \
240 	  ch = 0xc4;							      \
241 	else if (var == DK || var == NO || var == NO2)			      \
242 	  ch = 0xc6;							      \
243 	else if (var == ES || var == ES2 || var == CU)			      \
244 	  ch = 0xa1;							      \
245 	else if (var == IT || var == FR || var == FR1)			      \
246 	  ch = 0xb0;							      \
247 	else if (var == JP_OCR_B)					      \
248 	  ch = 0x2329;							      \
249 	else if (var == YU)						      \
250 	  ch = 0x160;							      \
251 	else if (var == HU)						      \
252 	  ch = 0xc9;							      \
253 	else if (var == PT || var == PT2)				      \
254 	  ch = 0xc3;							      \
255 	break;								      \
256       case 0x5c:							      \
257 	if (var == CA || var == CA2 || var == IT || var == FR || var == FR1)  \
258 	  ch = 0xe7;							      \
259 	else if (var == DE || var == HU || var == SE || var == SE2)	      \
260 	  ch = 0xd6;							      \
261 	else if (var == DK || var == NO || var == NO2)			      \
262 	  ch = 0xd8;							      \
263 	else if (var == ES || var == ES2 || var == CU)			      \
264 	  ch = 0xd1;							      \
265 	else if (var == JP || var == JP_OCR_B)				      \
266 	  ch = 0xa5;							      \
267 	else if (var == YU)						      \
268 	  ch = 0x110;							      \
269 	else if (var == KR)						      \
270 	  ch = 0x20a9;							      \
271 	else if (var == PT || var == PT2)				      \
272 	  ch = 0xc7;							      \
273 	break;								      \
274       case 0x5d:							      \
275 	if (var == CA || var == CA2)					      \
276 	  ch = 0xea;							      \
277 	else if (var == DE || var == HU)				      \
278 	  ch = 0xdc;							      \
279 	else if (var == DK || var == NO || var == NO2 || var == SE	      \
280 		 || var == SE2)						      \
281 	  ch = 0xc5;							      \
282 	else if (var == ES)						      \
283 	  ch = 0xbf;							      \
284 	else if (var == ES2)						      \
285 	  ch = 0xc7;							      \
286 	else if (var == IT)						      \
287 	  ch = 0xe9;							      \
288 	else if (var == JP_OCR_B)					      \
289 	  ch = 0x232a;							      \
290 	else if (var == YU)						      \
291 	  ch = 0x106;							      \
292 	else if (var == FR || var == FR1)				      \
293 	  ch = 0xa7;							      \
294 	else if (var == PT || var == PT2)				      \
295 	  ch = 0xd5;							      \
296 	break;								      \
297       case 0x5e:							      \
298 	if (var == CA)							      \
299 	  ch = 0xee;							      \
300 	else if (var == CA2)						      \
301 	  ch = 0xc9;							      \
302 	else if (var == ES2 || var == CU)				      \
303 	  ch = 0xbf;							      \
304 	else if (var == YU)						      \
305 	  ch = 0x10c;							      \
306 	else if (var == SE2)						      \
307 	  ch = 0xdc;							      \
308 	break;								      \
309       case 0x60:							      \
310 	if (var == CA || var == CA2)					      \
311 	  ch = 0xf4;							      \
312 	else if (var == IT)						      \
313 	  ch = 0xf9;							      \
314 	else if (var == JP_OCR_B)					      \
315 	  /* Illegal character.  */					      \
316 	  failure = __GCONV_ILLEGAL_INPUT;				      \
317 	else if (var == YU)						      \
318 	  ch = 0x17e;							      \
319 	else if (var == HU)						      \
320 	  ch = 0xe1;							      \
321 	else if (var == FR)						      \
322 	  ch = 0xb5;							      \
323 	else if (var == SE2)						      \
324 	  ch = 0xe9;							      \
325 	break;								      \
326       case 0x7b:							      \
327 	if (var == CA || var == CA2 || var == HU || var == FR || var == FR1)  \
328 	  ch = 0xe9;							      \
329 	else if (var == DE || var == SE || var == SE2)			      \
330 	  ch = 0xe4;							      \
331 	else if (var == DK || var == NO || var == NO2)			      \
332 	  ch = 0xe6;							      \
333 	else if (var == ES)						      \
334 	  ch = 0xb0;							      \
335 	else if (var == ES2 || var == CU)				      \
336 	  ch = 0xb4;							      \
337 	else if (var == IT)						      \
338 	  ch = 0xe0;							      \
339 	else if (var == YU)						      \
340 	  ch = 0x161;							      \
341 	else if (var == PT || var == PT2)				      \
342 	  ch = 0xe3;							      \
343 	break;								      \
344       case 0x7c:							      \
345 	if (var == CA || var == CA2 || var == FR || var == FR1)		      \
346 	  ch = 0xf9;							      \
347 	else if (var == DE || var == HU || var == SE || var == SE2)	      \
348 	  ch = 0xf6;							      \
349 	else if (var == DK || var == NO || var == NO2)			      \
350 	  ch = 0xf8;							      \
351 	else if (var == ES || var == ES2 || var == CU)			      \
352 	  ch = 0xf1;							      \
353 	else if (var == IT)						      \
354 	  ch = 0xf2;							      \
355 	else if (var == YU)						      \
356 	  ch = 0x111;							      \
357 	else if (var == PT || var == PT2)				      \
358 	  ch = 0xe7;							      \
359 	break;								      \
360       case 0x7d:							      \
361 	if (var == CA || var == CA2 || var == IT || var == FR || var == FR1)  \
362 	  ch = 0xe8;							      \
363 	else if (var == DE || var == HU)				      \
364 	  ch = 0xfc;							      \
365 	else if (var == DK || var == NO || var == NO2 || var == SE	      \
366 		 || var == SE2)						      \
367 	  ch = 0xe5;							      \
368 	else if (var == ES || var == ES2)				      \
369 	  ch = 0xe7;							      \
370 	else if (var == YU)						      \
371 	  ch = 0x107;							      \
372 	else if (var == CU)						      \
373 	  ch = 0x5b;							      \
374 	else if (var == PT || var == PT2)				      \
375 	  ch = 0xf5;							      \
376 	break;								      \
377       case 0x7e:							      \
378 	if (var == GB || var == CN || var == JP || var == NO || var == SE)    \
379 	  ch = 0x203e;							      \
380 	else if (var == CA || var == CA2)				      \
381 	  ch = 0xfb;							      \
382 	else if (var == DE)						      \
383 	  ch = 0xdf;							      \
384 	else if (var == ES2 || var == CU || var == FR || var == FR1)	      \
385 	  ch = 0xa8;							      \
386 	else if (var == IT)						      \
387 	  ch = 0xec;							      \
388 	else if (var == JP_OCR_B)					      \
389 	  /* Illegal character.  */					      \
390 	  failure = __GCONV_ILLEGAL_INPUT;				      \
391 	else if (var == YU)						      \
392 	  ch = 0x10d;							      \
393 	else if (var == HU)						      \
394 	  ch = 0x2dd;							      \
395 	else if (var == NO2)						      \
396 	  ch = 0x7c;							      \
397 	else if (var == PT)						      \
398 	  ch = 0xb0;							      \
399 	else if (var == SE2)						      \
400 	  ch = 0xfc;							      \
401 	break;								      \
402       default:								      \
403 	break;								      \
404       case 0x80 ... 0xff:						      \
405 	/* Illegal character.  */					      \
406 	failure = __GCONV_ILLEGAL_INPUT;				      \
407 	break;								      \
408       }									      \
409 									      \
410     /* Hopefully gcc can recognize that the following `if' is only true	      \
411        when we reach the default case in the `switch' statement.  */	      \
412     if (__builtin_expect (failure, __GCONV_OK) == __GCONV_ILLEGAL_INPUT)      \
413       {									      \
414 	STANDARD_FROM_LOOP_ERR_HANDLER (1);				      \
415       }									      \
416     else								      \
417       {									      \
418 	put32 (outptr, ch);						      \
419 	outptr += 4;							      \
420       }									      \
421     ++inptr;								      \
422   }
423 #define LOOP_NEED_FLAGS
424 #define EXTRA_LOOP_DECLS	, enum variant var
425 #include <iconv/loop.c>
426 
427 
428 /* Next, define the other direction.  */
429 #define MIN_NEEDED_INPUT	MIN_NEEDED_TO
430 #define MIN_NEEDED_OUTPUT	MIN_NEEDED_FROM
431 #define LOOPFCT			TO_LOOP
432 #define BODY \
433   {									      \
434     unsigned int ch;							      \
435     int failure = __GCONV_OK;						      \
436 									      \
437     ch = get32 (inptr);							      \
438     switch (ch)								      \
439       {									      \
440       case 0x23:							      \
441 	if (var == GB || var == ES || var == IT || var == FR || var == FR1    \
442 	    || var == NO2)						      \
443 	  failure = __GCONV_ILLEGAL_INPUT;				      \
444 	break;								      \
445       case 0x24:							      \
446 	if (var == CN || var == HU || var == CU || var == SE || var == SE2)   \
447 	  failure = __GCONV_ILLEGAL_INPUT;				      \
448 	break;								      \
449       case 0x40:							      \
450 	if (var == CA || var == CA2 || var == DE || var == ES || var == ES2   \
451 	    || var == IT || var == YU || var == HU || var == FR || var == FR1 \
452 	    || var == PT || var == PT2 || var == SE2)			      \
453 	  failure = __GCONV_ILLEGAL_INPUT;				      \
454 	break;								      \
455       case 0x5b:							      \
456 	if (var == CA || var == CA2 || var == DE || var == DK || var == ES    \
457 	    || var == ES2 || var == IT || var == JP_OCR_B || var == YU	      \
458 	    || var == HU || var == FR || var == FR1 || var == NO	      \
459 	    || var == NO2 || var == PT || var == PT2 || var == SE	      \
460 	    || var == SE2)						      \
461 	  failure = __GCONV_ILLEGAL_INPUT;				      \
462 	else if (var == CU)						      \
463 	  ch = 0x7d;							      \
464 	break;								      \
465       case 0x5c:							      \
466 	if (var == CA || var == CA2 || var == DE || var == DK || var == ES    \
467 	    || var == ES2 || var == IT || var == JP || var == JP_OCR_B	      \
468 	    || var == YU || var == KR || var == HU || var == CU || var == FR  \
469 	    || var == FR1 || var == NO || var == NO2 || var == PT	      \
470 	    || var == PT2 || var == SE || var == SE2)			      \
471 	  failure = __GCONV_ILLEGAL_INPUT;				      \
472 	break;								      \
473       case 0x5d:							      \
474 	if (var == CA || var == CA2 || var == DE || var == DK || var == ES    \
475 	    || var == ES2 || var == IT || var == JP_OCR_B || var == YU	      \
476 	    || var == HU || var == FR || var == FR1 || var == NO	      \
477 	    || var == NO2 || var == PT || var == PT2 || var == SE	      \
478 	    || var == SE2)						      \
479 	  failure = __GCONV_ILLEGAL_INPUT;				      \
480 	break;								      \
481       case 0x5e:							      \
482 	if (var == CA || var == CA2 || var == ES2 || var == YU || var == CU   \
483 	    || var == SE2)						      \
484 	  failure = __GCONV_ILLEGAL_INPUT;				      \
485 	break;								      \
486       case 0x60:							      \
487 	if (var == CA || var == CA2 || var == IT || var == JP_OCR_B	      \
488 	    || var == YU || var == HU || var == FR || var == SE2)	      \
489 	  failure = __GCONV_ILLEGAL_INPUT;				      \
490 	break;								      \
491       case 0x7b:							      \
492 	if (var == CA || var == CA2 || var == DE || var == DK || var == ES    \
493 	    || var == ES2 || var == IT || var == YU || var == HU	      \
494 	    || var == CU || var == FR || var == FR1 || var == NO	      \
495 	    || var == NO2 || var == PT || var == PT2 || var == SE	      \
496 	    || var == SE2)						      \
497 	  failure = __GCONV_ILLEGAL_INPUT;				      \
498 	break;								      \
499       case 0x7c:							      \
500 	if (var == CA || var == CA2 || var == DE || var == DK || var == ES    \
501 	    || var == ES2 || var == IT || var == YU || var == HU || var == CU \
502 	    || var == FR || var == FR1 || var == NO || var == PT	      \
503 	    || var == PT2 || var == SE || var == SE2)			      \
504 	  failure = __GCONV_ILLEGAL_INPUT;				      \
505 	else if (var == NO2)						      \
506 	  ch = 0x7e;							      \
507 	break;								      \
508       case 0x7d:							      \
509 	if (var == CA || var == CA2 || var == DE || var == DK || var == ES    \
510 	    || var == ES2 || var == IT || var == YU || var == HU || var == CU \
511 	    || var == FR || var == FR1 || var == NO || var == NO2	      \
512 	    || var == PT || var == PT2 || var == SE || var == SE2)	      \
513 	  failure = __GCONV_ILLEGAL_INPUT;				      \
514 	break;								      \
515       case 0x7e:							      \
516 	if (var == GB || var == CA || var == CA2 || var == DE || var == ES2   \
517 	    || var == CN || var == IT || var == JP || var == JP_OCR_B	      \
518 	    || var == YU || var == HU || var == CU || var == FR || var == FR1 \
519 	    || var == NO || var == NO2 || var == PT || var == SE	      \
520 	    || var == SE2)						      \
521 	  failure = __GCONV_ILLEGAL_INPUT;				      \
522 	break;								      \
523       case 0xa1:							      \
524 	if (var != ES && var != ES2 && var != CU)			      \
525 	  failure = __GCONV_ILLEGAL_INPUT;				      \
526 	ch = 0x5b;							      \
527 	break;								      \
528       case 0xa3:							      \
529 	if (var != GB && var != ES && var != IT && var != FR && var != FR1)   \
530 	  failure = __GCONV_ILLEGAL_INPUT;				      \
531 	ch = 0x23;							      \
532 	break;								      \
533       case 0xa4:							      \
534 	if (var != HU && var != CU && var != SE && var != SE2)		      \
535 	  failure = __GCONV_ILLEGAL_INPUT;				      \
536 	ch = 0x24;							      \
537 	break;								      \
538       case 0xa5:							      \
539 	if (var == CN)							      \
540 	  ch = 0x24;							      \
541 	else if (var == JP || var == JP_OCR_B)				      \
542 	  ch = 0x5c;							      \
543 	else								      \
544 	  failure = __GCONV_ILLEGAL_INPUT;				      \
545 	break;								      \
546       case 0xa7:							      \
547 	if (var == DE || var == ES || var == IT || var == PT)		      \
548 	  ch = 0x40;							      \
549 	else if (var == FR || var == FR1)				      \
550 	  ch = 0x5d;							      \
551 	else if (var == NO2)						      \
552 	  ch = 0x23;							      \
553 	else								      \
554 	  failure = __GCONV_ILLEGAL_INPUT;				      \
555 	break;								      \
556       case 0xa8:							      \
557 	if (var != ES2 && var != CU && var != FR && var != FR1)		      \
558 	  failure = __GCONV_ILLEGAL_INPUT;				      \
559 	ch = 0x7e;							      \
560 	break;								      \
561       case 0xb0:							      \
562 	if (var == ES)							      \
563 	  ch = 0x7b;							      \
564 	else if (var == IT || var == FR || var == FR1)			      \
565 	  ch = 0x5b;							      \
566 	else if (var == PT)						      \
567 	  ch = 0x7e;							      \
568 	else								      \
569 	  failure = __GCONV_ILLEGAL_INPUT;				      \
570 	break;								      \
571       case 0xb4:							      \
572 	if (var == ES2 || var == CU)					      \
573 	  ch = 0x7b;							      \
574 	else if (var == PT2)						      \
575 	  ch = 0x40;							      \
576 	else								      \
577 	  failure = __GCONV_ILLEGAL_INPUT;				      \
578 	break;								      \
579       case 0xb5:							      \
580 	if (var != FR)							      \
581 	  failure = __GCONV_ILLEGAL_INPUT;				      \
582 	ch = 0x60;							      \
583 	break;								      \
584       case 0xbf:							      \
585 	if (var == ES)							      \
586 	  ch = 0x5d;							      \
587 	else if (var == ES2 || var == CU)				      \
588 	  ch = 0x5e;							      \
589 	else								      \
590 	  failure = __GCONV_ILLEGAL_INPUT;				      \
591 	break;								      \
592       case 0xc1:							      \
593 	if (var != HU)							      \
594 	  failure = __GCONV_ILLEGAL_INPUT;				      \
595 	ch = 0x40;							      \
596 	break;								      \
597       case 0xc3:							      \
598 	if (var != PT && var != PT2)					      \
599 	  failure = __GCONV_ILLEGAL_INPUT;				      \
600 	ch = 0x5b;							      \
601 	break;								      \
602       case 0xc4:							      \
603 	if (var != DE && var != SE && var != SE2)			      \
604 	  failure = __GCONV_ILLEGAL_INPUT;				      \
605 	ch = 0x5b;							      \
606 	break;								      \
607       case 0xc5:							      \
608 	if (var != DK && var != NO && var != NO2 && var != SE && var != SE2)  \
609 	  failure = __GCONV_ILLEGAL_INPUT;				      \
610 	ch = 0x5d;							      \
611 	break;								      \
612       case 0xc6:							      \
613 	if (var != DK && var != NO && var != NO2)			      \
614 	  failure = __GCONV_ILLEGAL_INPUT;				      \
615 	ch = 0x5b;							      \
616 	break;								      \
617       case 0xc7:							      \
618 	if (var == ES2)							      \
619 	  ch = 0x5d;							      \
620 	else if (var == PT || var == PT2)				      \
621 	  ch = 0x5c;							      \
622 	else								      \
623 	  failure = __GCONV_ILLEGAL_INPUT;				      \
624 	break;								      \
625       case 0xc9:							      \
626 	if (var == CA2)							      \
627 	  ch = 0x5e;							      \
628 	else if (var == HU)						      \
629 	  ch = 0x5b;							      \
630 	else if (var == SE2)						      \
631 	  ch = 0x40;							      \
632 	else								      \
633 	  failure = __GCONV_ILLEGAL_INPUT;				      \
634 	break;								      \
635       case 0xd1:							      \
636 	if (var != ES && var != ES2 && var != CU)			      \
637 	  failure = __GCONV_ILLEGAL_INPUT;				      \
638 	ch = 0x5c;							      \
639 	break;								      \
640       case 0xd5:							      \
641 	if (var != PT && var != PT2)					      \
642 	  failure = __GCONV_ILLEGAL_INPUT;				      \
643 	ch = 0x5d;							      \
644 	break;								      \
645       case 0xd6:							      \
646 	if (var != DE && var != HU && var != SE && var != SE2)		      \
647 	  failure = __GCONV_ILLEGAL_INPUT;				      \
648 	ch = 0x5c;							      \
649 	break;								      \
650       case 0xd8:							      \
651 	if (var != DK && var != NO && var != NO2)			      \
652 	  failure = __GCONV_ILLEGAL_INPUT;				      \
653 	ch = 0x5c;							      \
654 	break;								      \
655       case 0xdc:							      \
656 	if (var == DE || var == HU)					      \
657 	  ch = 0x5d;							      \
658 	else if (var == SE2)						      \
659 	  ch = 0x5e;							      \
660 	else								      \
661 	  failure = __GCONV_ILLEGAL_INPUT;				      \
662 	break;								      \
663       case 0xdf:							      \
664 	if (var != DE)							      \
665 	  failure = __GCONV_ILLEGAL_INPUT;				      \
666 	ch = 0x7e;							      \
667 	break;								      \
668       case 0xe0:							      \
669 	if (var == CA || var == CA2 || var == FR || var == FR1)		      \
670 	  ch = 0x40;							      \
671 	else if (var == IT)						      \
672 	  ch = 0x7b;							      \
673 	else								      \
674 	  failure = __GCONV_ILLEGAL_INPUT;				      \
675 	break;								      \
676       case 0xe1:							      \
677 	if (var != HU)							      \
678 	  failure = __GCONV_ILLEGAL_INPUT;				      \
679 	ch = 0x60;							      \
680 	break;								      \
681       case 0xe2:							      \
682 	if (var != CA && var != CA2)					      \
683 	  failure = __GCONV_ILLEGAL_INPUT;				      \
684 	ch = 0x5b;							      \
685 	break;								      \
686       case 0xe3:							      \
687 	if (var != PT && var != PT2)					      \
688 	  failure = __GCONV_ILLEGAL_INPUT;				      \
689 	ch = 0x7b;							      \
690 	break;								      \
691       case 0xe4:							      \
692 	if (var != DE && var != SE && var != SE2)			      \
693 	  failure = __GCONV_ILLEGAL_INPUT;				      \
694 	ch = 0x7b;							      \
695 	break;								      \
696       case 0xe5:							      \
697 	if (var != DK && var != NO && var != NO2 && var != SE && var != SE2)  \
698 	  failure = __GCONV_ILLEGAL_INPUT;				      \
699 	ch = 0x7d;							      \
700 	break;								      \
701       case 0xe6:							      \
702 	if (var != DK && var != NO && var != NO2)			      \
703 	  failure = __GCONV_ILLEGAL_INPUT;				      \
704 	ch = 0x7b;							      \
705 	break;								      \
706       case 0xe7:							      \
707 	if (var == CA || var == CA2 || var == IT || var == FR || var == FR1)  \
708 	  ch = 0x5c;							      \
709 	else if (var == ES || var == ES2)				      \
710 	  ch = 0x7d;							      \
711 	else if (var == PT || var == PT2)				      \
712 	  ch = 0x7c;							      \
713 	else								      \
714 	  failure = __GCONV_ILLEGAL_INPUT;				      \
715 	break;								      \
716       case 0xe8:							      \
717 	if (var != CA && var != CA2 && var != IT && var != FR && var != FR1)  \
718 	  failure = __GCONV_ILLEGAL_INPUT;				      \
719 	ch = 0x7d;							      \
720 	break;								      \
721       case 0xe9:							      \
722 	if (var == CA || var == CA2 || var == HU || var == FR || var == FR1)  \
723 	  ch = 0x7b;							      \
724 	else if (var == IT)						      \
725 	  ch = 0x5d;							      \
726 	else if (var == SE2)						      \
727 	  ch = 0x60;							      \
728 	else								      \
729 	  failure = __GCONV_ILLEGAL_INPUT;				      \
730 	break;								      \
731       case 0xea:							      \
732 	if (var != CA && var != CA2)					      \
733 	  failure = __GCONV_ILLEGAL_INPUT;				      \
734 	ch = 0x5d;							      \
735 	break;								      \
736       case 0xec:							      \
737 	if (var != IT)							      \
738 	  failure = __GCONV_ILLEGAL_INPUT;				      \
739 	ch = 0x7e;							      \
740 	break;								      \
741       case 0xee:							      \
742 	if (var != CA)							      \
743 	  failure = __GCONV_ILLEGAL_INPUT;				      \
744 	ch = 0x5e;							      \
745 	break;								      \
746       case 0xf1:							      \
747 	if (var != ES && var != ES2 && var != CU)			      \
748 	  failure = __GCONV_ILLEGAL_INPUT;				      \
749 	ch = 0x7c;							      \
750 	break;								      \
751       case 0xf2:							      \
752 	if (var != IT)							      \
753 	  failure = __GCONV_ILLEGAL_INPUT;				      \
754 	ch = 0x7c;							      \
755 	break;								      \
756       case 0xf4:							      \
757 	if (var != CA && var != CA2)					      \
758 	  failure = __GCONV_ILLEGAL_INPUT;				      \
759 	ch = 0x60;							      \
760 	break;								      \
761       case 0xf5:							      \
762 	if (var != PT && var != PT2)					      \
763 	  failure = __GCONV_ILLEGAL_INPUT;				      \
764 	ch = 0x7d;							      \
765 	break;								      \
766       case 0xf6:							      \
767 	if (var != DE && var != HU && var != SE && var != SE2)		      \
768 	  failure = __GCONV_ILLEGAL_INPUT;				      \
769 	ch = 0x7c;							      \
770 	break;								      \
771       case 0xf8:							      \
772 	if (var != DK && var != NO && var != NO2)			      \
773 	  failure = __GCONV_ILLEGAL_INPUT;				      \
774 	ch = 0x7c;							      \
775 	break;								      \
776       case 0xf9:							      \
777 	if (var == CA || var == CA2 || var == FR || var == FR1)		      \
778 	  ch = 0x7c;							      \
779 	else if (var == IT)						      \
780 	  ch = 0x60;							      \
781 	else								      \
782 	  failure = __GCONV_ILLEGAL_INPUT;				      \
783 	break;								      \
784       case 0xfb:							      \
785 	if (var != CA && var != CA2)					      \
786 	  failure = __GCONV_ILLEGAL_INPUT;				      \
787 	ch = 0x7e;							      \
788 	break;								      \
789       case 0xfc:							      \
790 	if (var == DE || var == HU)					      \
791 	  ch = 0x7d;							      \
792 	else if (var == SE2)						      \
793 	  ch = 0x7e;							      \
794 	else								      \
795 	  failure = __GCONV_ILLEGAL_INPUT;				      \
796 	break;								      \
797       case 0x160:							      \
798 	if (var != YU)							      \
799 	  failure = __GCONV_ILLEGAL_INPUT;				      \
800 	ch = 0x5b;							      \
801 	break;								      \
802       case 0x106:							      \
803 	if (var != YU)							      \
804 	  failure = __GCONV_ILLEGAL_INPUT;				      \
805 	ch = 0x5d;							      \
806 	break;								      \
807       case 0x107:							      \
808 	if (var != YU)							      \
809 	  failure = __GCONV_ILLEGAL_INPUT;				      \
810 	ch = 0x7d;							      \
811 	break;								      \
812       case 0x10c:							      \
813 	if (var != YU)							      \
814 	  failure = __GCONV_ILLEGAL_INPUT;				      \
815 	ch = 0x5e;							      \
816 	break;								      \
817       case 0x10d:							      \
818 	if (var != YU)							      \
819 	  failure = __GCONV_ILLEGAL_INPUT;				      \
820 	ch = 0x7e;							      \
821 	break;								      \
822       case 0x110:							      \
823 	if (var != YU)							      \
824 	  failure = __GCONV_ILLEGAL_INPUT;				      \
825 	ch = 0x5c;							      \
826 	break;								      \
827       case 0x111:							      \
828 	if (var != YU)							      \
829 	  failure = __GCONV_ILLEGAL_INPUT;				      \
830 	ch = 0x7c;							      \
831 	break;								      \
832       case 0x161:							      \
833 	if (var != YU)							      \
834 	  failure = __GCONV_ILLEGAL_INPUT;				      \
835 	ch = 0x7b;							      \
836 	break;								      \
837       case 0x17d:							      \
838 	if (var != YU)							      \
839 	  failure = __GCONV_ILLEGAL_INPUT;				      \
840 	ch = 0x40;							      \
841 	break;								      \
842       case 0x17e:							      \
843 	if (var != YU)							      \
844 	  failure = __GCONV_ILLEGAL_INPUT;				      \
845 	ch = 0x60;							      \
846 	break;								      \
847       case 0x2dd:							      \
848 	if (var != HU)							      \
849 	  failure = __GCONV_ILLEGAL_INPUT;				      \
850 	ch = 0x7e;							      \
851 	break;								      \
852       case 0x2022:							      \
853 	if (var != ES2)							      \
854 	  failure = __GCONV_ILLEGAL_INPUT;				      \
855 	ch = 0x40;							      \
856 	break;								      \
857       case 0x203e:							      \
858 	if (var != GB && var != CN && var != JP && var != NO && var != SE)    \
859 	  failure = __GCONV_ILLEGAL_INPUT;				      \
860 	ch = 0x7e;							      \
861 	break;								      \
862       case 0x20a9:							      \
863 	if (var != KR)							      \
864 	  failure = __GCONV_ILLEGAL_INPUT;				      \
865 	ch = 0x5c;							      \
866 	break;								      \
867       case 0x2329:							      \
868 	if (var != JP_OCR_B)						      \
869 	  failure = __GCONV_ILLEGAL_INPUT;				      \
870 	ch = 0x5b;							      \
871 	break;								      \
872       case 0x232a:							      \
873 	if (var != JP_OCR_B)						      \
874 	  failure = __GCONV_ILLEGAL_INPUT;				      \
875 	ch = 0x5d;							      \
876 	break;								      \
877       default:								      \
878 	if (__glibc_unlikely (ch > 0x7f))				      \
879 	  {								      \
880 	    UNICODE_TAG_HANDLER (ch, 4);				      \
881 	    failure = __GCONV_ILLEGAL_INPUT;				      \
882 	  }								      \
883 	break;								      \
884       }									      \
885 									      \
886     if (__builtin_expect (failure, __GCONV_OK) == __GCONV_ILLEGAL_INPUT)      \
887       {									      \
888 	STANDARD_TO_LOOP_ERR_HANDLER (4);				      \
889       }									      \
890 									      \
891     *outptr++ = (unsigned char) ch;					      \
892     inptr += 4;								      \
893   }
894 #define LOOP_NEED_FLAGS
895 #define EXTRA_LOOP_DECLS	, enum variant var
896 #include <iconv/loop.c>
897 
898 
899 /* Now define the toplevel functions.  */
900 #include <iconv/skeleton.c>
901