(__gconv_transform_utf8_internal): Use only one copy of error handling code.
[kopensolaris-gnu/glibc.git] / iconv / gconv_simple.c
1 /* Simple transformations functions.
2    Copyright (C) 1997-2003, 2004 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
20
21 #include <byteswap.h>
22 #include <dlfcn.h>
23 #include <endian.h>
24 #include <errno.h>
25 #include <gconv.h>
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <wchar.h>
30 #include <sys/param.h>
31 #include <gconv_int.h>
32
33 #define BUILTIN_ALIAS(s1, s2) /* nothing */
34 #define BUILTIN_TRANSFORMATION(From, To, Cost, Name, Fct, BtowcFct, \
35                                MinF, MaxF, MinT, MaxT) \
36   extern int Fct (struct __gconv_step *, struct __gconv_step_data *,          \
37                   __const unsigned char **, __const unsigned char *,          \
38                   unsigned char **, size_t *, int, int);
39 #include "gconv_builtin.h"
40
41
42 #ifndef EILSEQ
43 # define EILSEQ EINVAL
44 #endif
45
46
47 /* Specialized conversion function for a single byte to INTERNAL, recognizing
48    only ASCII characters.  */
49 wint_t
50 __gconv_btwoc_ascii (struct __gconv_step *step, unsigned char c)
51 {
52   if (c < 0x80)
53     return c;
54   else
55     return WEOF;
56 }
57
58
59 /* Transform from the internal, UCS4-like format, to UCS4.  The
60    difference between the internal ucs4 format and the real UCS4
61    format is, if any, the endianess.  The Unicode/ISO 10646 says that
62    unless some higher protocol specifies it differently, the byte
63    order is big endian.*/
64 #define DEFINE_INIT             0
65 #define DEFINE_FINI             0
66 #define MIN_NEEDED_FROM         4
67 #define MIN_NEEDED_TO           4
68 #define FROM_DIRECTION          1
69 #define FROM_LOOP               internal_ucs4_loop
70 #define TO_LOOP                 internal_ucs4_loop /* This is not used.  */
71 #define FUNCTION_NAME           __gconv_transform_internal_ucs4
72
73
74 static inline int
75 __attribute ((always_inline))
76 internal_ucs4_loop (struct __gconv_step *step,
77                     struct __gconv_step_data *step_data,
78                     const unsigned char **inptrp, const unsigned char *inend,
79                     unsigned char **outptrp, unsigned char *outend,
80                     size_t *irreversible)
81 {
82   const unsigned char *inptr = *inptrp;
83   unsigned char *outptr = *outptrp;
84   size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
85   int result;
86
87 #if __BYTE_ORDER == __LITTLE_ENDIAN
88   /* Sigh, we have to do some real work.  */
89   size_t cnt;
90   uint32_t *outptr32 = (uint32_t *) outptr;
91
92   for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
93     *outptr32++ = bswap_32 (*(const uint32_t *) inptr);
94
95   *inptrp = inptr;
96   *outptrp = (unsigned char *) outptr32;
97 #elif __BYTE_ORDER == __BIG_ENDIAN
98   /* Simply copy the data.  */
99   *inptrp = inptr + n_convert * 4;
100   *outptrp = __mempcpy (outptr, inptr, n_convert * 4);
101 #else
102 # error "This endianess is not supported."
103 #endif
104
105   /* Determine the status.  */
106   if (*inptrp == inend)
107     result = __GCONV_EMPTY_INPUT;
108   else if (*outptrp + 4 > outend)
109     result = __GCONV_FULL_OUTPUT;
110   else
111     result = __GCONV_INCOMPLETE_INPUT;
112
113   return result;
114 }
115
116 #ifndef _STRING_ARCH_unaligned
117 static inline int
118 __attribute ((always_inline))
119 internal_ucs4_loop_unaligned (struct __gconv_step *step,
120                               struct __gconv_step_data *step_data,
121                               const unsigned char **inptrp,
122                               const unsigned char *inend,
123                               unsigned char **outptrp, unsigned char *outend,
124                               size_t *irreversible)
125 {
126   const unsigned char *inptr = *inptrp;
127   unsigned char *outptr = *outptrp;
128   size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
129   int result;
130
131 # if __BYTE_ORDER == __LITTLE_ENDIAN
132   /* Sigh, we have to do some real work.  */
133   size_t cnt;
134
135   for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4, outptr += 4)
136     {
137       outptr[0] = inptr[3];
138       outptr[1] = inptr[2];
139       outptr[2] = inptr[1];
140       outptr[3] = inptr[0];
141     }
142
143   *inptrp = inptr;
144   *outptrp = outptr;
145 # elif __BYTE_ORDER == __BIG_ENDIAN
146   /* Simply copy the data.  */
147   *inptrp = inptr + n_convert * 4;
148   *outptrp = __mempcpy (outptr, inptr, n_convert * 4);
149 # else
150 #  error "This endianess is not supported."
151 # endif
152
153   /* Determine the status.  */
154   if (*inptrp == inend)
155     result = __GCONV_EMPTY_INPUT;
156   else if (*outptrp + 4 > outend)
157     result = __GCONV_FULL_OUTPUT;
158   else
159     result = __GCONV_INCOMPLETE_INPUT;
160
161   return result;
162 }
163 #endif
164
165
166 static inline int
167 __attribute ((always_inline))
168 internal_ucs4_loop_single (struct __gconv_step *step,
169                            struct __gconv_step_data *step_data,
170                            const unsigned char **inptrp,
171                            const unsigned char *inend,
172                            unsigned char **outptrp, unsigned char *outend,
173                            size_t *irreversible)
174 {
175   mbstate_t *state = step_data->__statep;
176   size_t cnt = state->__count & 7;
177
178   while (*inptrp < inend && cnt < 4)
179     state->__value.__wchb[cnt++] = *(*inptrp)++;
180
181   if (__builtin_expect (cnt < 4, 0))
182     {
183       /* Still not enough bytes.  Store the ones in the input buffer.  */
184       state->__count &= ~7;
185       state->__count |= cnt;
186
187       return __GCONV_INCOMPLETE_INPUT;
188     }
189
190 #if __BYTE_ORDER == __LITTLE_ENDIAN
191   (*outptrp)[0] = state->__value.__wchb[3];
192   (*outptrp)[1] = state->__value.__wchb[2];
193   (*outptrp)[2] = state->__value.__wchb[1];
194   (*outptrp)[3] = state->__value.__wchb[0];
195
196 #elif __BYTE_ORDER == __BIG_ENDIAN
197   /* XXX unaligned */
198   (*outptrp)[0] = state->__value.__wchb[0];
199   (*outptrp)[1] = state->__value.__wchb[1];
200   (*outptrp)[2] = state->__value.__wchb[2];
201   (*outptrp)[3] = state->__value.__wchb[3];
202 #else
203 # error "This endianess is not supported."
204 #endif
205   *outptrp += 4;
206
207   /* Clear the state buffer.  */
208   state->__count &= ~7;
209
210   return __GCONV_OK;
211 }
212
213 #include <iconv/skeleton.c>
214
215
216 /* Transform from UCS4 to the internal, UCS4-like format.  Unlike
217    for the other direction we have to check for correct values here.  */
218 #define DEFINE_INIT             0
219 #define DEFINE_FINI             0
220 #define MIN_NEEDED_FROM         4
221 #define MIN_NEEDED_TO           4
222 #define FROM_DIRECTION          1
223 #define FROM_LOOP               ucs4_internal_loop
224 #define TO_LOOP                 ucs4_internal_loop /* This is not used.  */
225 #define FUNCTION_NAME           __gconv_transform_ucs4_internal
226
227
228 static inline int
229 __attribute ((always_inline))
230 ucs4_internal_loop (struct __gconv_step *step,
231                     struct __gconv_step_data *step_data,
232                     const unsigned char **inptrp, const unsigned char *inend,
233                     unsigned char **outptrp, unsigned char *outend,
234                     size_t *irreversible)
235 {
236   int flags = step_data->__flags;
237   const unsigned char *inptr = *inptrp;
238   unsigned char *outptr = *outptrp;
239   size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
240   int result;
241   size_t cnt;
242
243   for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
244     {
245       uint32_t inval;
246
247 #if __BYTE_ORDER == __LITTLE_ENDIAN
248       inval = bswap_32 (*(const uint32_t *) inptr);
249 #else
250       inval = *(const uint32_t *) inptr;
251 #endif
252
253       if (__builtin_expect (inval > 0x7fffffff, 0))
254         {
255           /* The value is too large.  We don't try transliteration here since
256              this is not an error because of the lack of possibilities to
257              represent the result.  This is a genuine bug in the input since
258              UCS4 does not allow such values.  */
259           if (irreversible == NULL)
260             /* We are transliterating, don't try to correct anything.  */
261             return __GCONV_ILLEGAL_INPUT;
262
263           if (flags & __GCONV_IGNORE_ERRORS)
264             {
265               /* Just ignore this character.  */
266               ++*irreversible;
267               continue;
268             }
269
270           *inptrp = inptr;
271           *outptrp = outptr;
272           return __GCONV_ILLEGAL_INPUT;
273         }
274
275       *((uint32_t *) outptr) = inval;
276       outptr += sizeof (uint32_t);
277     }
278
279   *inptrp = inptr;
280   *outptrp = outptr;
281
282   /* Determine the status.  */
283   if (*inptrp == inend)
284     result = __GCONV_EMPTY_INPUT;
285   else if (*outptrp + 4 > outend)
286     result = __GCONV_FULL_OUTPUT;
287   else
288     result = __GCONV_INCOMPLETE_INPUT;
289
290   return result;
291 }
292
293 #ifndef _STRING_ARCH_unaligned
294 static inline int
295 __attribute ((always_inline))
296 ucs4_internal_loop_unaligned (struct __gconv_step *step,
297                               struct __gconv_step_data *step_data,
298                               const unsigned char **inptrp,
299                               const unsigned char *inend,
300                               unsigned char **outptrp, unsigned char *outend,
301                               size_t *irreversible)
302 {
303   int flags = step_data->__flags;
304   const unsigned char *inptr = *inptrp;
305   unsigned char *outptr = *outptrp;
306   size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
307   int result;
308   size_t cnt;
309
310   for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
311     {
312       if (__builtin_expect (inptr[0] > 0x80, 0))
313         {
314           /* The value is too large.  We don't try transliteration here since
315              this is not an error because of the lack of possibilities to
316              represent the result.  This is a genuine bug in the input since
317              UCS4 does not allow such values.  */
318           if (irreversible == NULL)
319             /* We are transliterating, don't try to correct anything.  */
320             return __GCONV_ILLEGAL_INPUT;
321
322           if (flags & __GCONV_IGNORE_ERRORS)
323             {
324               /* Just ignore this character.  */
325               ++*irreversible;
326               continue;
327             }
328
329           *inptrp = inptr;
330           *outptrp = outptr;
331           return __GCONV_ILLEGAL_INPUT;
332         }
333
334 # if __BYTE_ORDER == __LITTLE_ENDIAN
335       outptr[3] = inptr[0];
336       outptr[2] = inptr[1];
337       outptr[1] = inptr[2];
338       outptr[0] = inptr[3];
339 # else
340       outptr[0] = inptr[0];
341       outptr[1] = inptr[1];
342       outptr[2] = inptr[2];
343       outptr[3] = inptr[3];
344 # endif
345       outptr += 4;
346     }
347
348   *inptrp = inptr;
349   *outptrp = outptr;
350
351   /* Determine the status.  */
352   if (*inptrp == inend)
353     result = __GCONV_EMPTY_INPUT;
354   else if (*outptrp + 4 > outend)
355     result = __GCONV_FULL_OUTPUT;
356   else
357     result = __GCONV_INCOMPLETE_INPUT;
358
359   return result;
360 }
361 #endif
362
363
364 static inline int
365 __attribute ((always_inline))
366 ucs4_internal_loop_single (struct __gconv_step *step,
367                            struct __gconv_step_data *step_data,
368                            const unsigned char **inptrp,
369                            const unsigned char *inend,
370                            unsigned char **outptrp, unsigned char *outend,
371                            size_t *irreversible)
372 {
373   mbstate_t *state = step_data->__statep;
374   int flags = step_data->__flags;
375   size_t cnt = state->__count & 7;
376
377   while (*inptrp < inend && cnt < 4)
378     state->__value.__wchb[cnt++] = *(*inptrp)++;
379
380   if (__builtin_expect (cnt < 4, 0))
381     {
382       /* Still not enough bytes.  Store the ones in the input buffer.  */
383       state->__count &= ~7;
384       state->__count |= cnt;
385
386       return __GCONV_INCOMPLETE_INPUT;
387     }
388
389   if (__builtin_expect (((unsigned char *) state->__value.__wchb)[0] > 0x80,
390                         0))
391     {
392       /* The value is too large.  We don't try transliteration here since
393          this is not an error because of the lack of possibilities to
394          represent the result.  This is a genuine bug in the input since
395          UCS4 does not allow such values.  */
396       if (!(flags & __GCONV_IGNORE_ERRORS))
397         {
398           *inptrp -= cnt - (state->__count & 7);
399           return __GCONV_ILLEGAL_INPUT;
400         }
401     }
402   else
403     {
404 #if __BYTE_ORDER == __LITTLE_ENDIAN
405       (*outptrp)[0] = state->__value.__wchb[3];
406       (*outptrp)[1] = state->__value.__wchb[2];
407       (*outptrp)[2] = state->__value.__wchb[1];
408       (*outptrp)[3] = state->__value.__wchb[0];
409 #elif __BYTE_ORDER == __BIG_ENDIAN
410       (*outptrp)[0] = state->__value.__wchb[0];
411       (*outptrp)[1] = state->__value.__wchb[1];
412       (*outptrp)[2] = state->__value.__wchb[2];
413       (*outptrp)[3] = state->__value.__wchb[3];
414 #endif
415
416       *outptrp += 4;
417     }
418
419   /* Clear the state buffer.  */
420   state->__count &= ~7;
421
422   return __GCONV_OK;
423 }
424
425 #include <iconv/skeleton.c>
426
427
428 /* Similarly for the little endian form.  */
429 #define DEFINE_INIT             0
430 #define DEFINE_FINI             0
431 #define MIN_NEEDED_FROM         4
432 #define MIN_NEEDED_TO           4
433 #define FROM_DIRECTION          1
434 #define FROM_LOOP               internal_ucs4le_loop
435 #define TO_LOOP                 internal_ucs4le_loop /* This is not used.  */
436 #define FUNCTION_NAME           __gconv_transform_internal_ucs4le
437
438
439 static inline int
440 __attribute ((always_inline))
441 internal_ucs4le_loop (struct __gconv_step *step,
442                       struct __gconv_step_data *step_data,
443                       const unsigned char **inptrp, const unsigned char *inend,
444                       unsigned char **outptrp, unsigned char *outend,
445                       size_t *irreversible)
446 {
447   const unsigned char *inptr = *inptrp;
448   unsigned char *outptr = *outptrp;
449   size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
450   int result;
451
452 #if __BYTE_ORDER == __BIG_ENDIAN
453   /* Sigh, we have to do some real work.  */
454   size_t cnt;
455   uint32_t *outptr32 = (uint32_t *) outptr;
456
457   for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
458     *outptr32++ = bswap_32 (*(const uint32_t *) inptr);
459   outptr = (unsigned char *) outptr32;
460
461   *inptrp = inptr;
462   *outptrp = outptr;
463 #elif __BYTE_ORDER == __LITTLE_ENDIAN
464   /* Simply copy the data.  */
465   *inptrp = inptr + n_convert * 4;
466   *outptrp = __mempcpy (outptr, inptr, n_convert * 4);
467 #else
468 # error "This endianess is not supported."
469 #endif
470
471   /* Determine the status.  */
472   if (*inptrp == inend)
473     result = __GCONV_EMPTY_INPUT;
474   else if (*outptrp + 4 > outend)
475     result = __GCONV_FULL_OUTPUT;
476   else
477     result = __GCONV_INCOMPLETE_INPUT;
478
479   return result;
480 }
481
482 #ifndef _STRING_ARCH_unaligned
483 static inline int
484 __attribute ((always_inline))
485 internal_ucs4le_loop_unaligned (struct __gconv_step *step,
486                                 struct __gconv_step_data *step_data,
487                                 const unsigned char **inptrp,
488                                 const unsigned char *inend,
489                                 unsigned char **outptrp, unsigned char *outend,
490                                 size_t *irreversible)
491 {
492   const unsigned char *inptr = *inptrp;
493   unsigned char *outptr = *outptrp;
494   size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
495   int result;
496
497 # if __BYTE_ORDER == __BIG_ENDIAN
498   /* Sigh, we have to do some real work.  */
499   size_t cnt;
500
501   for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4, outptr += 4)
502     {
503       outptr[0] = inptr[3];
504       outptr[1] = inptr[2];
505       outptr[2] = inptr[1];
506       outptr[3] = inptr[0];
507     }
508
509   *inptrp = inptr;
510   *outptrp = outptr;
511 # elif __BYTE_ORDER == __LITTLE_ENDIAN
512   /* Simply copy the data.  */
513   *inptrp = inptr + n_convert * 4;
514   *outptrp = __mempcpy (outptr, inptr, n_convert * 4);
515 # else
516 #  error "This endianess is not supported."
517 # endif
518
519   /* Determine the status.  */
520   if (*inptrp == inend)
521     result = __GCONV_EMPTY_INPUT;
522   else if (*inptrp + 4 > inend)
523     result = __GCONV_INCOMPLETE_INPUT;
524   else
525     {
526       assert (*outptrp + 4 > outend);
527       result = __GCONV_FULL_OUTPUT;
528     }
529
530   return result;
531 }
532 #endif
533
534
535 static inline int
536 __attribute ((always_inline))
537 internal_ucs4le_loop_single (struct __gconv_step *step,
538                              struct __gconv_step_data *step_data,
539                              const unsigned char **inptrp,
540                              const unsigned char *inend,
541                              unsigned char **outptrp, unsigned char *outend,
542                              size_t *irreversible)
543 {
544   mbstate_t *state = step_data->__statep;
545   size_t cnt = state->__count & 7;
546
547   while (*inptrp < inend && cnt < 4)
548     state->__value.__wchb[cnt++] = *(*inptrp)++;
549
550   if (__builtin_expect (cnt < 4, 0))
551     {
552       /* Still not enough bytes.  Store the ones in the input buffer.  */
553       state->__count &= ~7;
554       state->__count |= cnt;
555
556       return __GCONV_INCOMPLETE_INPUT;
557     }
558
559 #if __BYTE_ORDER == __BIG_ENDIAN
560   (*outptrp)[0] = state->__value.__wchb[3];
561   (*outptrp)[1] = state->__value.__wchb[2];
562   (*outptrp)[2] = state->__value.__wchb[1];
563   (*outptrp)[3] = state->__value.__wchb[0];
564
565 #else
566   /* XXX unaligned */
567   (*outptrp)[0] = state->__value.__wchb[0];
568   (*outptrp)[1] = state->__value.__wchb[1];
569   (*outptrp)[2] = state->__value.__wchb[2];
570   (*outptrp)[3] = state->__value.__wchb[3];
571
572 #endif
573
574   *outptrp += 4;
575
576   /* Clear the state buffer.  */
577   state->__count &= ~7;
578
579   return __GCONV_OK;
580 }
581
582 #include <iconv/skeleton.c>
583
584
585 /* And finally from UCS4-LE to the internal encoding.  */
586 #define DEFINE_INIT             0
587 #define DEFINE_FINI             0
588 #define MIN_NEEDED_FROM         4
589 #define MIN_NEEDED_TO           4
590 #define FROM_DIRECTION          1
591 #define FROM_LOOP               ucs4le_internal_loop
592 #define TO_LOOP                 ucs4le_internal_loop /* This is not used.  */
593 #define FUNCTION_NAME           __gconv_transform_ucs4le_internal
594
595
596 static inline int
597 __attribute ((always_inline))
598 ucs4le_internal_loop (struct __gconv_step *step,
599                       struct __gconv_step_data *step_data,
600                       const unsigned char **inptrp, const unsigned char *inend,
601                       unsigned char **outptrp, unsigned char *outend,
602                       size_t *irreversible)
603 {
604   int flags = step_data->__flags;
605   const unsigned char *inptr = *inptrp;
606   unsigned char *outptr = *outptrp;
607   size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
608   int result;
609   size_t cnt;
610
611   for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
612     {
613       uint32_t inval;
614
615 #if __BYTE_ORDER == __BIG_ENDIAN
616       inval = bswap_32 (*(const uint32_t *) inptr);
617 #else
618       inval = *(const uint32_t *) inptr;
619 #endif
620
621       if (__builtin_expect (inval > 0x7fffffff, 0))
622         {
623           /* The value is too large.  We don't try transliteration here since
624              this is not an error because of the lack of possibilities to
625              represent the result.  This is a genuine bug in the input since
626              UCS4 does not allow such values.  */
627           if (irreversible == NULL)
628             /* We are transliterating, don't try to correct anything.  */
629             return __GCONV_ILLEGAL_INPUT;
630
631           if (flags & __GCONV_IGNORE_ERRORS)
632             {
633               /* Just ignore this character.  */
634               ++*irreversible;
635               continue;
636             }
637
638           return __GCONV_ILLEGAL_INPUT;
639         }
640
641       *((uint32_t *) outptr) = inval;
642       outptr += sizeof (uint32_t);
643     }
644
645   *inptrp = inptr;
646   *outptrp = outptr;
647
648   /* Determine the status.  */
649   if (*inptrp == inend)
650     result = __GCONV_EMPTY_INPUT;
651   else if (*inptrp + 4 > inend)
652     result = __GCONV_INCOMPLETE_INPUT;
653   else
654     {
655       assert (*outptrp + 4 > outend);
656       result = __GCONV_FULL_OUTPUT;
657     }
658
659   return result;
660 }
661
662 #ifndef _STRING_ARCH_unaligned
663 static inline int
664 __attribute ((always_inline))
665 ucs4le_internal_loop_unaligned (struct __gconv_step *step,
666                                 struct __gconv_step_data *step_data,
667                                 const unsigned char **inptrp,
668                                 const unsigned char *inend,
669                                 unsigned char **outptrp, unsigned char *outend,
670                                 size_t *irreversible)
671 {
672   int flags = step_data->__flags;
673   const unsigned char *inptr = *inptrp;
674   unsigned char *outptr = *outptrp;
675   size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
676   int result;
677   size_t cnt;
678
679   for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
680     {
681       if (__builtin_expect (inptr[3] > 0x80, 0))
682         {
683           /* The value is too large.  We don't try transliteration here since
684              this is not an error because of the lack of possibilities to
685              represent the result.  This is a genuine bug in the input since
686              UCS4 does not allow such values.  */
687           if (irreversible == NULL)
688             /* We are transliterating, don't try to correct anything.  */
689             return __GCONV_ILLEGAL_INPUT;
690
691           if (flags & __GCONV_IGNORE_ERRORS)
692             {
693               /* Just ignore this character.  */
694               ++*irreversible;
695               continue;
696             }
697
698           *inptrp = inptr;
699           *outptrp = outptr;
700           return __GCONV_ILLEGAL_INPUT;
701         }
702
703 # if __BYTE_ORDER == __BIG_ENDIAN
704       outptr[3] = inptr[0];
705       outptr[2] = inptr[1];
706       outptr[1] = inptr[2];
707       outptr[0] = inptr[3];
708 # else
709       outptr[0] = inptr[0];
710       outptr[1] = inptr[1];
711       outptr[2] = inptr[2];
712       outptr[3] = inptr[3];
713 # endif
714
715       outptr += 4;
716     }
717
718   *inptrp = inptr;
719   *outptrp = outptr;
720
721   /* Determine the status.  */
722   if (*inptrp == inend)
723     result = __GCONV_EMPTY_INPUT;
724   else if (*inptrp + 4 > inend)
725     result = __GCONV_INCOMPLETE_INPUT;
726   else
727     {
728       assert (*outptrp + 4 > outend);
729       result = __GCONV_FULL_OUTPUT;
730     }
731
732   return result;
733 }
734 #endif
735
736
737 static inline int
738 __attribute ((always_inline))
739 ucs4le_internal_loop_single (struct __gconv_step *step,
740                              struct __gconv_step_data *step_data,
741                              const unsigned char **inptrp,
742                              const unsigned char *inend,
743                              unsigned char **outptrp, unsigned char *outend,
744                              size_t *irreversible)
745 {
746   mbstate_t *state = step_data->__statep;
747   int flags = step_data->__flags;
748   size_t cnt = state->__count & 7;
749
750   while (*inptrp < inend && cnt < 4)
751     state->__value.__wchb[cnt++] = *(*inptrp)++;
752
753   if (__builtin_expect (cnt < 4, 0))
754     {
755       /* Still not enough bytes.  Store the ones in the input buffer.  */
756       state->__count &= ~7;
757       state->__count |= cnt;
758
759       return __GCONV_INCOMPLETE_INPUT;
760     }
761
762   if (__builtin_expect (((unsigned char *) state->__value.__wchb)[3] > 0x80,
763                         0))
764     {
765       /* The value is too large.  We don't try transliteration here since
766          this is not an error because of the lack of possibilities to
767          represent the result.  This is a genuine bug in the input since
768          UCS4 does not allow such values.  */
769       if (!(flags & __GCONV_IGNORE_ERRORS))
770         return __GCONV_ILLEGAL_INPUT;
771     }
772   else
773     {
774 #if __BYTE_ORDER == __BIG_ENDIAN
775       (*outptrp)[0] = state->__value.__wchb[3];
776       (*outptrp)[1] = state->__value.__wchb[2];
777       (*outptrp)[2] = state->__value.__wchb[1];
778       (*outptrp)[3] = state->__value.__wchb[0];
779 #else
780       (*outptrp)[0] = state->__value.__wchb[0];
781       (*outptrp)[1] = state->__value.__wchb[1];
782       (*outptrp)[2] = state->__value.__wchb[2];
783       (*outptrp)[3] = state->__value.__wchb[3];
784 #endif
785
786       *outptrp += 4;
787     }
788
789   /* Clear the state buffer.  */
790   state->__count &= ~7;
791
792   return __GCONV_OK;
793 }
794
795 #include <iconv/skeleton.c>
796
797
798 /* Convert from ISO 646-IRV to the internal (UCS4-like) format.  */
799 #define DEFINE_INIT             0
800 #define DEFINE_FINI             0
801 #define MIN_NEEDED_FROM         1
802 #define MIN_NEEDED_TO           4
803 #define FROM_DIRECTION          1
804 #define FROM_LOOP               ascii_internal_loop
805 #define TO_LOOP                 ascii_internal_loop /* This is not used.  */
806 #define FUNCTION_NAME           __gconv_transform_ascii_internal
807 #define ONE_DIRECTION           1
808
809 #define MIN_NEEDED_INPUT        MIN_NEEDED_FROM
810 #define MIN_NEEDED_OUTPUT       MIN_NEEDED_TO
811 #define LOOPFCT                 FROM_LOOP
812 #define BODY \
813   {                                                                           \
814     if (__builtin_expect (*inptr > '\x7f', 0))                                \
815       {                                                                       \
816         /* The value is too large.  We don't try transliteration here since   \
817            this is not an error because of the lack of possibilities to       \
818            represent the result.  This is a genuine bug in the input since    \
819            ASCII does not allow such values.  */                              \
820         STANDARD_FROM_LOOP_ERR_HANDLER (1);                                   \
821       }                                                                       \
822     else                                                                      \
823       /* It's an one byte sequence.  */                                       \
824       *((uint32_t *) outptr) = *inptr++;                                      \
825       outptr += sizeof (uint32_t);                                            \
826   }
827 #define LOOP_NEED_FLAGS
828 #include <iconv/loop.c>
829 #include <iconv/skeleton.c>
830
831
832 /* Convert from the internal (UCS4-like) format to ISO 646-IRV.  */
833 #define DEFINE_INIT             0
834 #define DEFINE_FINI             0
835 #define MIN_NEEDED_FROM         4
836 #define MIN_NEEDED_TO           1
837 #define FROM_DIRECTION          1
838 #define FROM_LOOP               internal_ascii_loop
839 #define TO_LOOP                 internal_ascii_loop /* This is not used.  */
840 #define FUNCTION_NAME           __gconv_transform_internal_ascii
841 #define ONE_DIRECTION           1
842
843 #define MIN_NEEDED_INPUT        MIN_NEEDED_FROM
844 #define MIN_NEEDED_OUTPUT       MIN_NEEDED_TO
845 #define LOOPFCT                 FROM_LOOP
846 #define BODY \
847   {                                                                           \
848     if (__builtin_expect (*((const uint32_t *) inptr) > 0x7f, 0))             \
849       {                                                                       \
850         UNICODE_TAG_HANDLER (*((const uint32_t *) inptr), 4);                 \
851         STANDARD_TO_LOOP_ERR_HANDLER (4);                                     \
852       }                                                                       \
853     else                                                                      \
854       /* It's an one byte sequence.  */                                       \
855       *outptr++ = *((const uint32_t *) inptr);                                \
856       inptr += sizeof (uint32_t);                                             \
857   }
858 #define LOOP_NEED_FLAGS
859 #include <iconv/loop.c>
860 #include <iconv/skeleton.c>
861
862
863 /* Convert from the internal (UCS4-like) format to UTF-8.  */
864 #define DEFINE_INIT             0
865 #define DEFINE_FINI             0
866 #define MIN_NEEDED_FROM         4
867 #define MIN_NEEDED_TO           1
868 #define MAX_NEEDED_TO           6
869 #define FROM_DIRECTION          1
870 #define FROM_LOOP               internal_utf8_loop
871 #define TO_LOOP                 internal_utf8_loop /* This is not used.  */
872 #define FUNCTION_NAME           __gconv_transform_internal_utf8
873 #define ONE_DIRECTION           1
874
875 #define MIN_NEEDED_INPUT        MIN_NEEDED_FROM
876 #define MIN_NEEDED_OUTPUT       MIN_NEEDED_TO
877 #define MAX_NEEDED_OUTPUT       MAX_NEEDED_TO
878 #define LOOPFCT                 FROM_LOOP
879 #define BODY \
880   {                                                                           \
881     uint32_t wc = *((const uint32_t *) inptr);                                \
882                                                                               \
883     if (wc < 0x80)                                                            \
884       /* It's an one byte sequence.  */                                       \
885       *outptr++ = (unsigned char) wc;                                         \
886     else if (__builtin_expect (wc <= 0x7fffffff, 1))                          \
887       {                                                                       \
888         size_t step;                                                          \
889         char *start;                                                          \
890                                                                               \
891         for (step = 2; step < 6; ++step)                                      \
892           if ((wc & (~(uint32_t)0 << (5 * step + 1))) == 0)                   \
893             break;                                                            \
894                                                                               \
895         if (__builtin_expect (outptr + step > outend, 0))                     \
896           {                                                                   \
897             /* Too long.  */                                                  \
898             result = __GCONV_FULL_OUTPUT;                                     \
899             break;                                                            \
900           }                                                                   \
901                                                                               \
902         start = outptr;                                                       \
903         *outptr = (unsigned char) (~0xff >> step);                            \
904         outptr += step;                                                       \
905         do                                                                    \
906           {                                                                   \
907             start[--step] = 0x80 | (wc & 0x3f);                               \
908             wc >>= 6;                                                         \
909           }                                                                   \
910         while (step > 1);                                                     \
911         start[0] |= wc;                                                       \
912       }                                                                       \
913     else                                                                      \
914       {                                                                       \
915         STANDARD_TO_LOOP_ERR_HANDLER (4);                                     \
916       }                                                                       \
917                                                                               \
918     inptr += 4;                                                               \
919   }
920 #define LOOP_NEED_FLAGS
921 #include <iconv/loop.c>
922 #include <iconv/skeleton.c>
923
924
925 /* Convert from UTF-8 to the internal (UCS4-like) format.  */
926 #define DEFINE_INIT             0
927 #define DEFINE_FINI             0
928 #define MIN_NEEDED_FROM         1
929 #define MAX_NEEDED_FROM         6
930 #define MIN_NEEDED_TO           4
931 #define FROM_DIRECTION          1
932 #define FROM_LOOP               utf8_internal_loop
933 #define TO_LOOP                 utf8_internal_loop /* This is not used.  */
934 #define FUNCTION_NAME           __gconv_transform_utf8_internal
935 #define ONE_DIRECTION           1
936
937 #define MIN_NEEDED_INPUT        MIN_NEEDED_FROM
938 #define MAX_NEEDED_INPUT        MAX_NEEDED_FROM
939 #define MIN_NEEDED_OUTPUT       MIN_NEEDED_TO
940 #define LOOPFCT                 FROM_LOOP
941 #define BODY \
942   {                                                                           \
943     uint32_t ch;                                                              \
944     uint_fast32_t cnt;                                                        \
945     uint_fast32_t i;                                                          \
946                                                                               \
947     /* Next input byte.  */                                                   \
948     ch = *inptr;                                                              \
949                                                                               \
950     if (ch < 0x80)                                                            \
951       {                                                                       \
952         /* One byte sequence.  */                                             \
953         cnt = 1;                                                              \
954         ++inptr;                                                              \
955       }                                                                       \
956     else                                                                      \
957       {                                                                       \
958         if (ch >= 0xc2 && ch < 0xe0)                                          \
959           {                                                                   \
960             /* We expect two bytes.  The first byte cannot be 0xc0 or 0xc1,   \
961                otherwise the wide character could have been represented       \
962                using a single byte.  */                                       \
963             cnt = 2;                                                          \
964             ch &= 0x1f;                                                       \
965           }                                                                   \
966         else if (__builtin_expect ((ch & 0xf0) == 0xe0, 1))                   \
967           {                                                                   \
968             /* We expect three bytes.  */                                     \
969             cnt = 3;                                                          \
970             ch &= 0x0f;                                                       \
971           }                                                                   \
972         else if (__builtin_expect ((ch & 0xf8) == 0xf0, 1))                   \
973           {                                                                   \
974             /* We expect four bytes.  */                                      \
975             cnt = 4;                                                          \
976             ch &= 0x07;                                                       \
977           }                                                                   \
978         else if (__builtin_expect ((ch & 0xfc) == 0xf8, 1))                   \
979           {                                                                   \
980             /* We expect five bytes.  */                                      \
981             cnt = 5;                                                          \
982             ch &= 0x03;                                                       \
983           }                                                                   \
984         else if (__builtin_expect ((ch & 0xfe) == 0xfc, 1))                   \
985           {                                                                   \
986             /* We expect six bytes.  */                                       \
987             cnt = 6;                                                          \
988             ch &= 0x01;                                                       \
989           }                                                                   \
990         else                                                                  \
991           {                                                                   \
992             /* Search the end of this ill-formed UTF-8 character.  This       \
993                is the next byte with (x & 0xc0) != 0x80.  */                  \
994             i = 0;                                                            \
995             do                                                                \
996               ++i;                                                            \
997             while (inptr + i < inend                                          \
998                    && (*(inptr + i) & 0xc0) == 0x80                           \
999                    && i < 5);                                                 \
1000                                                                               \
1001           errout:                                                             \
1002             STANDARD_FROM_LOOP_ERR_HANDLER (i);                               \
1003           }                                                                   \
1004                                                                               \
1005         if (__builtin_expect (inptr + cnt > inend, 0))                        \
1006           {                                                                   \
1007             /* We don't have enough input.  But before we report that check   \
1008                that all the bytes are correct.  */                            \
1009             for (i = 1; inptr + i < inend; ++i)                               \
1010               if ((inptr[i] & 0xc0) != 0x80)                                  \
1011                 break;                                                        \
1012                                                                               \
1013             if (__builtin_expect (inptr + i == inend, 1))                     \
1014               {                                                               \
1015                 result = __GCONV_INCOMPLETE_INPUT;                            \
1016                 break;                                                        \
1017               }                                                               \
1018                                                                               \
1019             goto errout;                                                      \
1020           }                                                                   \
1021                                                                               \
1022         /* Read the possible remaining bytes.  */                             \
1023         for (i = 1; i < cnt; ++i)                                             \
1024           {                                                                   \
1025             uint32_t byte = inptr[i];                                         \
1026                                                                               \
1027             if ((byte & 0xc0) != 0x80)                                        \
1028               /* This is an illegal encoding.  */                             \
1029               break;                                                          \
1030                                                                               \
1031             ch <<= 6;                                                         \
1032             ch |= byte & 0x3f;                                                \
1033           }                                                                   \
1034                                                                               \
1035         /* If i < cnt, some trail byte was not >= 0x80, < 0xc0.               \
1036            If cnt > 2 and ch < 2^(5*cnt-4), the wide character ch could       \
1037            have been represented with fewer than cnt bytes.  */               \
1038         if (i < cnt || (cnt > 2 && (ch >> (5 * cnt - 4)) == 0))               \
1039           {                                                                   \
1040             /* This is an illegal encoding.  */                               \
1041             goto errout;                                                      \
1042           }                                                                   \
1043                                                                               \
1044         inptr += cnt;                                                         \
1045       }                                                                       \
1046                                                                               \
1047     /* Now adjust the pointers and store the result.  */                      \
1048     *((uint32_t *) outptr) = ch;                                              \
1049     outptr += sizeof (uint32_t);                                              \
1050   }
1051 #define LOOP_NEED_FLAGS
1052
1053 #define STORE_REST \
1054   {                                                                           \
1055     /* We store the remaining bytes while converting them into the UCS4       \
1056        format.  We can assume that the first byte in the buffer is            \
1057        correct and that it requires a larger number of bytes than there       \
1058        are in the input buffer.  */                                           \
1059     wint_t ch = **inptrp;                                                     \
1060     size_t cnt, r;                                                            \
1061                                                                               \
1062     state->__count = inend - *inptrp;                                         \
1063                                                                               \
1064     if (ch >= 0xc2 && ch < 0xe0)                                              \
1065       {                                                                       \
1066         /* We expect two bytes.  The first byte cannot be 0xc0 or             \
1067            0xc1, otherwise the wide character could have been                 \
1068            represented using a single byte.  */                               \
1069         cnt = 2;                                                              \
1070         ch &= 0x1f;                                                           \
1071       }                                                                       \
1072     else if (__builtin_expect ((ch & 0xf0) == 0xe0, 1))                       \
1073       {                                                                       \
1074         /* We expect three bytes.  */                                         \
1075         cnt = 3;                                                              \
1076         ch &= 0x0f;                                                           \
1077       }                                                                       \
1078     else if (__builtin_expect ((ch & 0xf8) == 0xf0, 1))                       \
1079       {                                                                       \
1080         /* We expect four bytes.  */                                          \
1081         cnt = 4;                                                              \
1082         ch &= 0x07;                                                           \
1083       }                                                                       \
1084     else if (__builtin_expect ((ch & 0xfc) == 0xf8, 1))                       \
1085       {                                                                       \
1086         /* We expect five bytes.  */                                          \
1087         cnt = 5;                                                              \
1088         ch &= 0x03;                                                           \
1089       }                                                                       \
1090     else                                                                      \
1091       {                                                                       \
1092         /* We expect six bytes.  */                                           \
1093         cnt = 6;                                                              \
1094         ch &= 0x01;                                                           \
1095       }                                                                       \
1096                                                                               \
1097     /* The first byte is already consumed.  */                                \
1098     r = cnt - 1;                                                              \
1099     while (++(*inptrp) < inend)                                               \
1100       {                                                                       \
1101         ch <<= 6;                                                             \
1102         ch |= **inptrp & 0x3f;                                                \
1103         --r;                                                                  \
1104       }                                                                       \
1105                                                                               \
1106     /* Shift for the so far missing bytes.  */                                \
1107     ch <<= r * 6;                                                             \
1108                                                                               \
1109     /* Store the number of bytes expected for the entire sequence.  */        \
1110     state->__count |= cnt << 8;                                               \
1111                                                                               \
1112     /* Store the value.  */                                                   \
1113     state->__value.__wch = ch;                                                \
1114   }
1115
1116 #define UNPACK_BYTES \
1117   {                                                                           \
1118     static const unsigned char inmask[5] = { 0xc0, 0xe0, 0xf0, 0xf8, 0xfc };  \
1119     wint_t wch = state->__value.__wch;                                        \
1120     size_t ntotal = state->__count >> 8;                                      \
1121                                                                               \
1122     inlen = state->__count & 255;                                             \
1123                                                                               \
1124     bytebuf[0] = inmask[ntotal - 2];                                          \
1125                                                                               \
1126     do                                                                        \
1127       {                                                                       \
1128         if (--ntotal < inlen)                                                 \
1129           bytebuf[ntotal] = 0x80 | (wch & 0x3f);                              \
1130         wch >>= 6;                                                            \
1131       }                                                                       \
1132     while (ntotal > 1);                                                       \
1133                                                                               \
1134     bytebuf[0] |= wch;                                                        \
1135   }
1136
1137 #define CLEAR_STATE \
1138   state->__count = 0
1139
1140
1141 #include <iconv/loop.c>
1142 #include <iconv/skeleton.c>
1143
1144
1145 /* Convert from UCS2 to the internal (UCS4-like) format.  */
1146 #define DEFINE_INIT             0
1147 #define DEFINE_FINI             0
1148 #define MIN_NEEDED_FROM         2
1149 #define MIN_NEEDED_TO           4
1150 #define FROM_DIRECTION          1
1151 #define FROM_LOOP               ucs2_internal_loop
1152 #define TO_LOOP                 ucs2_internal_loop /* This is not used.  */
1153 #define FUNCTION_NAME           __gconv_transform_ucs2_internal
1154 #define ONE_DIRECTION           1
1155
1156 #define MIN_NEEDED_INPUT        MIN_NEEDED_FROM
1157 #define MIN_NEEDED_OUTPUT       MIN_NEEDED_TO
1158 #define LOOPFCT                 FROM_LOOP
1159 #define BODY \
1160   {                                                                           \
1161     uint16_t u1 = *((const uint16_t *) inptr);                                \
1162                                                                               \
1163     if (__builtin_expect (u1 >= 0xd800 && u1 < 0xe000, 0))                    \
1164       {                                                                       \
1165         /* Surrogate characters in UCS-2 input are not valid.  Reject         \
1166            them.  (Catching this here is not security relevant.)  */          \
1167         STANDARD_FROM_LOOP_ERR_HANDLER (2);                                   \
1168       }                                                                       \
1169                                                                               \
1170     *((uint32_t *) outptr) = u1;                                              \
1171     outptr += sizeof (uint32_t);                                              \
1172     inptr += 2;                                                               \
1173   }
1174 #define LOOP_NEED_FLAGS
1175 #include <iconv/loop.c>
1176 #include <iconv/skeleton.c>
1177
1178
1179 /* Convert from the internal (UCS4-like) format to UCS2.  */
1180 #define DEFINE_INIT             0
1181 #define DEFINE_FINI             0
1182 #define MIN_NEEDED_FROM         4
1183 #define MIN_NEEDED_TO           2
1184 #define FROM_DIRECTION          1
1185 #define FROM_LOOP               internal_ucs2_loop
1186 #define TO_LOOP                 internal_ucs2_loop /* This is not used.  */
1187 #define FUNCTION_NAME           __gconv_transform_internal_ucs2
1188 #define ONE_DIRECTION           1
1189
1190 #define MIN_NEEDED_INPUT        MIN_NEEDED_FROM
1191 #define MIN_NEEDED_OUTPUT       MIN_NEEDED_TO
1192 #define LOOPFCT                 FROM_LOOP
1193 #define BODY \
1194   {                                                                           \
1195     uint32_t val = *((const uint32_t *) inptr);                               \
1196                                                                               \
1197     if (__builtin_expect (val >= 0x10000, 0))                                 \
1198       {                                                                       \
1199         UNICODE_TAG_HANDLER (val, 4);                                         \
1200         STANDARD_TO_LOOP_ERR_HANDLER (4);                                     \
1201       }                                                                       \
1202     else if (__builtin_expect (val >= 0xd800 && val < 0xe000, 0))             \
1203       {                                                                       \
1204         /* Surrogate characters in UCS-4 input are not valid.                 \
1205            We must catch this, because the UCS-2 output might be              \
1206            interpreted as UTF-16 by other programs.  If we let                \
1207            surrogates pass through, attackers could make a security           \
1208            hole exploit by synthesizing any desired plane 1-16                \
1209            character.  */                                                     \
1210         result = __GCONV_ILLEGAL_INPUT;                                       \
1211         if (! ignore_errors_p ())                                             \
1212           break;                                                              \
1213         inptr += 4;                                                           \
1214         ++*irreversible;                                                      \
1215         continue;                                                             \
1216       }                                                                       \
1217     else                                                                      \
1218       {                                                                       \
1219         *((uint16_t *) outptr) = val;                                         \
1220         outptr += sizeof (uint16_t);                                          \
1221         inptr += 4;                                                           \
1222       }                                                                       \
1223   }
1224 #define LOOP_NEED_FLAGS
1225 #include <iconv/loop.c>
1226 #include <iconv/skeleton.c>
1227
1228
1229 /* Convert from UCS2 in other endianness to the internal (UCS4-like) format. */
1230 #define DEFINE_INIT             0
1231 #define DEFINE_FINI             0
1232 #define MIN_NEEDED_FROM         2
1233 #define MIN_NEEDED_TO           4
1234 #define FROM_DIRECTION          1
1235 #define FROM_LOOP               ucs2reverse_internal_loop
1236 #define TO_LOOP                 ucs2reverse_internal_loop/* This is not used.*/
1237 #define FUNCTION_NAME           __gconv_transform_ucs2reverse_internal
1238 #define ONE_DIRECTION           1
1239
1240 #define MIN_NEEDED_INPUT        MIN_NEEDED_FROM
1241 #define MIN_NEEDED_OUTPUT       MIN_NEEDED_TO
1242 #define LOOPFCT                 FROM_LOOP
1243 #define BODY \
1244   {                                                                           \
1245     uint16_t u1 = bswap_16 (*((const uint16_t *) inptr));                     \
1246                                                                               \
1247     if (__builtin_expect (u1 >= 0xd800 && u1 < 0xe000, 0))                    \
1248       {                                                                       \
1249         /* Surrogate characters in UCS-2 input are not valid.  Reject         \
1250            them.  (Catching this here is not security relevant.)  */          \
1251         if (! ignore_errors_p ())                                             \
1252           {                                                                   \
1253             result = __GCONV_ILLEGAL_INPUT;                                   \
1254             break;                                                            \
1255           }                                                                   \
1256         inptr += 2;                                                           \
1257         ++*irreversible;                                                      \
1258         continue;                                                             \
1259       }                                                                       \
1260                                                                               \
1261     *((uint32_t *) outptr) = u1;                                              \
1262     outptr += sizeof (uint32_t);                                              \
1263     inptr += 2;                                                               \
1264   }
1265 #define LOOP_NEED_FLAGS
1266 #include <iconv/loop.c>
1267 #include <iconv/skeleton.c>
1268
1269
1270 /* Convert from the internal (UCS4-like) format to UCS2 in other endianness. */
1271 #define DEFINE_INIT             0
1272 #define DEFINE_FINI             0
1273 #define MIN_NEEDED_FROM         4
1274 #define MIN_NEEDED_TO           2
1275 #define FROM_DIRECTION          1
1276 #define FROM_LOOP               internal_ucs2reverse_loop
1277 #define TO_LOOP                 internal_ucs2reverse_loop/* This is not used.*/
1278 #define FUNCTION_NAME           __gconv_transform_internal_ucs2reverse
1279 #define ONE_DIRECTION           1
1280
1281 #define MIN_NEEDED_INPUT        MIN_NEEDED_FROM
1282 #define MIN_NEEDED_OUTPUT       MIN_NEEDED_TO
1283 #define LOOPFCT                 FROM_LOOP
1284 #define BODY \
1285   {                                                                           \
1286     uint32_t val = *((const uint32_t *) inptr);                               \
1287     if (__builtin_expect (val >= 0x10000, 0))                                 \
1288       {                                                                       \
1289         UNICODE_TAG_HANDLER (val, 4);                                         \
1290         STANDARD_TO_LOOP_ERR_HANDLER (4);                                     \
1291       }                                                                       \
1292     else if (__builtin_expect (val >= 0xd800 && val < 0xe000, 0))             \
1293       {                                                                       \
1294         /* Surrogate characters in UCS-4 input are not valid.                 \
1295            We must catch this, because the UCS-2 output might be              \
1296            interpreted as UTF-16 by other programs.  If we let                \
1297            surrogates pass through, attackers could make a security           \
1298            hole exploit by synthesizing any desired plane 1-16                \
1299            character.  */                                                     \
1300         if (! ignore_errors_p ())                                             \
1301           {                                                                   \
1302             result = __GCONV_ILLEGAL_INPUT;                                   \
1303             break;                                                            \
1304           }                                                                   \
1305         inptr += 4;                                                           \
1306         ++*irreversible;                                                      \
1307         continue;                                                             \
1308       }                                                                       \
1309     else                                                                      \
1310       {                                                                       \
1311         *((uint16_t *) outptr) = bswap_16 (val);                              \
1312         outptr += sizeof (uint16_t);                                          \
1313         inptr += 4;                                                           \
1314       }                                                                       \
1315   }
1316 #define LOOP_NEED_FLAGS
1317 #include <iconv/loop.c>
1318 #include <iconv/skeleton.c>