OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [tags/] [gnu-src/] [newlib-1.18.0/] [newlib-1.18.0-or32-1.0rc2/] [newlib/] [libc/] [sys/] [linux/] [iconv/] [gconv_simple.c] - Blame information for rev 520

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.