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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [newlib-1.17.0/] [newlib/] [libc/] [sys/] [linux/] [iconv/] [loop.c] - Blame information for rev 816

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 148 jeremybenn
/* Conversion loop frame work.
2
   Copyright (C) 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>, 1998.
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
/* This file provides a frame for the reader loop in all conversion modules.
22
   The actual code must (of course) be provided in the actual module source
23
   code but certain actions can be written down generically, with some
24
   customization options which are these:
25
 
26
     MIN_NEEDED_INPUT   minimal number of input bytes needed for the next
27
                        conversion.
28
     MIN_NEEDED_OUTPUT  minimal number of bytes produced by the next round
29
                        of conversion.
30
 
31
     MAX_NEEDED_INPUT   you guess it, this is the maximal number of input
32
                        bytes needed.  It defaults to MIN_NEEDED_INPUT
33
     MAX_NEEDED_OUTPUT  likewise for output bytes.
34
 
35
     LOOPFCT            name of the function created.  If not specified
36
                        the name is `loop' but this prevents the use
37
                        of multiple functions in the same file.
38
 
39
     BODY               this is supposed to expand to the body of the loop.
40
                        The user must provide this.
41
 
42
     EXTRA_LOOP_DECLS   extra arguments passed from converion loop call.
43
 
44
     INIT_PARAMS        code to define and initialize variables from params.
45
     UPDATE_PARAMS      code to store result in params.
46
*/
47
 
48
#include <assert.h>
49
#include <machine/endian.h>
50
#include <gconv.h>
51
#include <stdint.h>
52
#include <string.h>
53
#include <wchar.h>
54
#include <sys/param.h>          /* For MIN.  */
55
#define __need_size_t
56
#include <stddef.h>
57
 
58
 
59
/* We have to provide support for machines which are not able to handled
60
   unaligned memory accesses.  Some of the character encodings have
61
   representations with a fixed width of 2 or 4 bytes.  But if we cannot
62
   access unaligned memory we still have to read byte-wise.  */
63
#undef FCTNAME2
64
#if defined _STRING_ARCH_unaligned || !defined DEFINE_UNALIGNED
65
/* We can handle unaligned memory access.  */
66
# define get16(addr) *((__const uint16_t *) (addr))
67
# define get32(addr) *((__const uint32_t *) (addr))
68
 
69
/* We need no special support for writing values either.  */
70
# define put16(addr, val) *((uint16_t *) (addr)) = (val)
71
# define put32(addr, val) *((uint32_t *) (addr)) = (val)
72
 
73
# define FCTNAME2(name) name
74
#else
75
/* Distinguish between big endian and little endian.  */
76
# if __BYTE_ORDER == __LITTLE_ENDIAN
77
#  define get16(addr) \
78
     (((__const unsigned char *) (addr))[1] << 8                              \
79
      | ((__const unsigned char *) (addr))[0])
80
#  define get32(addr) \
81
     (((((__const unsigned char *) (addr))[3] << 8                            \
82
        | ((__const unsigned char *) (addr))[2]) << 8                         \
83
       | ((__const unsigned char *) (addr))[1]) << 8                          \
84
      | ((__const unsigned char *) (addr))[0])
85
 
86
#  define put16(addr, val) \
87
     ({ uint16_t __val = (val);                                               \
88
        ((unsigned char *) (addr))[0] = __val;                                 \
89
        ((unsigned char *) (addr))[1] = __val >> 8;                           \
90
        (void) 0; })
91
#  define put32(addr, val) \
92
     ({ uint32_t __val = (val);                                               \
93
        ((unsigned char *) (addr))[0] = __val;                                 \
94
        __val >>= 8;                                                          \
95
        ((unsigned char *) (addr))[1] = __val;                                \
96
        __val >>= 8;                                                          \
97
        ((unsigned char *) (addr))[2] = __val;                                \
98
        __val >>= 8;                                                          \
99
        ((unsigned char *) (addr))[3] = __val;                                \
100
        (void) 0; })
101
# else
102
#  define get16(addr) \
103
     (((__const unsigned char *) (addr))[0] << 8                       \
104
      | ((__const unsigned char *) (addr))[1])
105
#  define get32(addr) \
106
     (((((__const unsigned char *) (addr))[0] << 8                             \
107
        | ((__const unsigned char *) (addr))[1]) << 8                         \
108
       | ((__const unsigned char *) (addr))[2]) << 8                          \
109
      | ((__const unsigned char *) (addr))[3])
110
 
111
#  define put16(addr, val) \
112
     ({ uint16_t __val = (val);                                               \
113
        ((unsigned char *) (addr))[1] = __val;                                \
114
        ((unsigned char *) (addr))[0] = __val >> 8;                            \
115
        (void) 0; })
116
#  define put32(addr, val) \
117
     ({ uint32_t __val = (val);                                               \
118
        ((unsigned char *) (addr))[3] = __val;                                \
119
        __val >>= 8;                                                          \
120
        ((unsigned char *) (addr))[2] = __val;                                \
121
        __val >>= 8;                                                          \
122
        ((unsigned char *) (addr))[1] = __val;                                \
123
        __val >>= 8;                                                          \
124
        ((unsigned char *) (addr))[0] = __val;                                 \
125
        (void) 0; })
126
# endif
127
 
128
# define FCTNAME2(name) name##_unaligned
129
#endif
130
#define FCTNAME(name) FCTNAME2(name)
131
 
132
 
133
/* We need at least one byte for the next round.  */
134
#ifndef MIN_NEEDED_INPUT
135
# error "MIN_NEEDED_INPUT definition missing"
136
#endif
137
 
138
/* Let's see how many bytes we produce.  */
139
#ifndef MAX_NEEDED_INPUT
140
# define MAX_NEEDED_INPUT       MIN_NEEDED_INPUT
141
#endif
142
 
143
/* We produce at least one byte in the next round.  */
144
#ifndef MIN_NEEDED_OUTPUT
145
# error "MIN_NEEDED_OUTPUT definition missing"
146
#endif
147
 
148
/* Let's see how many bytes we produce.  */
149
#ifndef MAX_NEEDED_OUTPUT
150
# define MAX_NEEDED_OUTPUT      MIN_NEEDED_OUTPUT
151
#endif
152
 
153
/* Default name for the function.  */
154
#ifndef LOOPFCT
155
# define LOOPFCT                loop
156
#endif
157
 
158
/* Make sure we have a loop body.  */
159
#ifndef BODY
160
# error "Definition of BODY missing for function" LOOPFCT
161
#endif
162
 
163
 
164
/* If no arguments have to passed to the loop function define the macro
165
   as empty.  */
166
#ifndef EXTRA_LOOP_DECLS
167
# define EXTRA_LOOP_DECLS
168
#endif
169
 
170
 
171
/* To make it easier for the writers of the modules, we define a macro
172
   to test whether we have to ignore errors.  */
173
#define ignore_errors_p() \
174
  (irreversible != NULL && (flags & __GCONV_IGNORE_ERRORS))
175
 
176
 
177
/* Error handling with transliteration/transcription function use and
178
   ignoring of errors.  Note that we cannot use the do while (0) trick
179
   since `break' and `continue' must reach certain points.  */
180
#define STANDARD_ERR_HANDLER(Incr) \
181
  {                                                                           \
182
    struct __gconv_trans_data *trans;                                         \
183
                                                                              \
184
    result = __GCONV_ILLEGAL_INPUT;                                           \
185
                                                                              \
186
    if (irreversible == NULL)                                                 \
187
      /* This means we are in call from __gconv_transliterate.  In this       \
188
         case we are not doing any error recovery outself.  */                \
189
      break;                                                                  \
190
                                                                              \
191
    /* First try the transliteration methods.  */                             \
192
    for (trans = step_data->__trans; trans != NULL; trans = trans->__next)    \
193
      {                                                                       \
194
        result = trans->__trans_fct (step, step_data, trans->__data, *inptrp, \
195
                               &inptr, inend, &outptr, irreversible);         \
196
        if (result != __GCONV_ILLEGAL_INPUT)                                  \
197
          break;                                                              \
198
      }                                                                       \
199
    /* If any of them recognized the input continue with the loop.  */        \
200
    if (result != __GCONV_ILLEGAL_INPUT)                                      \
201
      continue;                                                               \
202
                                                                              \
203
    /* Next see whether we have to ignore the error.  If not, stop.  */       \
204
    if (! ignore_errors_p ())                                                 \
205
      break;                                                                  \
206
                                                                              \
207
    /* When we come here it means we ignore the character.  */                \
208
    ++*irreversible;                                                          \
209
    inptr += Incr;                                                            \
210
    continue;                                                                 \
211
  }
212
 
213
 
214
/* Handling of Unicode 3.1 TAG characters.  Unicode recommends
215
   "If language codes are not relevant to the particular processing
216
    operation, then they should be ignored."
217
   This macro is usually called right before STANDARD_ERR_HANDLER (Incr).  */
218
#define UNICODE_TAG_HANDLER(Character, Incr) \
219
  {                                                                           \
220
    /* TAG characters are those in the range U+E0000..U+E007F.  */            \
221
    if (((Character) >> 7) == (0xe0000 >> 7))                                 \
222
      {                                                                       \
223
        inptr += Incr;                                                        \
224
        continue;                                                             \
225
      }                                                                       \
226
  }
227
 
228
 
229
/* The function returns the status, as defined in gconv.h.  */
230
static inline int
231
FCTNAME (LOOPFCT) (struct __gconv_step *step,
232
                   struct __gconv_step_data *step_data,
233
                   const unsigned char **inptrp, const unsigned char *inend,
234
                   unsigned char **outptrp, const unsigned char *outend,
235
                   size_t *irreversible EXTRA_LOOP_DECLS)
236
{
237
#ifdef LOOP_NEED_STATE
238
  mbstate_t *state = step_data->__statep;
239
#endif
240
#ifdef LOOP_NEED_FLAGS
241
  int flags = step_data->__flags;
242
#endif
243
#ifdef LOOP_NEED_DATA
244
  void *data = step->__data;
245
#endif
246
  int result = __GCONV_EMPTY_INPUT;
247
  const unsigned char *inptr = *inptrp;
248
  unsigned char *outptr = *outptrp;
249
 
250
#ifdef INIT_PARAMS
251
  INIT_PARAMS;
252
#endif
253
 
254
  while (inptr != inend)
255
    {
256
      /* `if' cases for MIN_NEEDED_OUTPUT ==/!= 1 is made to help the
257
         compiler generating better code.  They will be optimized away
258
         since MIN_NEEDED_OUTPUT is always a constant.  */
259
      if ((MIN_NEEDED_OUTPUT != 1
260
           && __builtin_expect (outptr + MIN_NEEDED_OUTPUT > outend, 0))
261
          || (MIN_NEEDED_OUTPUT == 1
262
              && __builtin_expect (outptr >= outend, 0)))
263
        {
264
          /* Overflow in the output buffer.  */
265
          result = __GCONV_FULL_OUTPUT;
266
          break;
267
        }
268
      if (MIN_NEEDED_INPUT > 1
269
          && __builtin_expect (inptr + MIN_NEEDED_INPUT > inend, 0))
270
        {
271
          /* We don't have enough input for another complete input
272
             character.  */
273
          result = __GCONV_INCOMPLETE_INPUT;
274
          break;
275
        }
276
 
277
      /* Here comes the body the user provides.  It can stop with
278
         RESULT set to GCONV_INCOMPLETE_INPUT (if the size of the
279
         input characters vary in size), GCONV_ILLEGAL_INPUT, or
280
         GCONV_FULL_OUTPUT (if the output characters vary in size).  */
281
      BODY
282
    }
283
 
284
  /* Update the pointers pointed to by the parameters.  */
285
  *inptrp = inptr;
286
  *outptrp = outptr;
287
#ifdef UPDATE_PARAMS
288
  UPDATE_PARAMS;
289
#endif
290
 
291
  return result;
292
}
293
 
294
 
295
/* Include the file a second time to define the function to handle
296
   unaligned access.  */
297
#if !defined DEFINE_UNALIGNED && !defined _STRING_ARCH_unaligned \
298
    && MIN_NEEDED_FROM != 1 && MAX_NEEDED_FROM % MIN_NEEDED_FROM == 0 \
299
    && MIN_NEEDED_TO != 1 && MAX_NEEDED_TO % MIN_NEEDED_TO == 0
300
# undef get16
301
# undef get32
302
# undef put16
303
# undef put32
304
# undef unaligned
305
 
306
# define DEFINE_UNALIGNED
307
# include "loop.c"
308
# undef DEFINE_UNALIGNED
309
#endif
310
 
311
 
312
#if MAX_NEEDED_INPUT > 1
313
# define SINGLE(fct) SINGLE2 (fct)
314
# define SINGLE2(fct) fct##_single
315
static inline int
316
SINGLE(LOOPFCT) (struct __gconv_step *step,
317
                 struct __gconv_step_data *step_data,
318
                 const unsigned char **inptrp, const unsigned char *inend,
319
                 unsigned char **outptrp, unsigned char *outend,
320
                 size_t *irreversible EXTRA_LOOP_DECLS)
321
{
322
  mbstate_t *state = step_data->__statep;
323
#ifdef LOOP_NEED_FLAGS
324
  int flags = step_data->__flags;
325
#endif
326
#ifdef LOOP_NEED_DATA
327
  void *data = step->__data;
328
#endif
329
  int result = __GCONV_OK;
330
  unsigned char bytebuf[MAX_NEEDED_INPUT];
331
  const unsigned char *inptr = *inptrp;
332
  unsigned char *outptr = *outptrp;
333
  size_t inlen;
334
 
335
#ifdef INIT_PARAMS
336
  INIT_PARAMS;
337
#endif
338
 
339
#ifdef UNPACK_BYTES
340
  UNPACK_BYTES
341
#else
342
  /* Add the bytes from the state to the input buffer.  */
343
  for (inlen = 0; inlen < (size_t) (state->__count & 7); ++inlen)
344
    bytebuf[inlen] = state->__value.__wchb[inlen];
345
#endif
346
 
347
  /* Are there enough bytes in the input buffer?  */
348
  if (__builtin_expect (inptr + (MIN_NEEDED_INPUT - inlen) > inend, 0))
349
    {
350
      *inptrp = inend;
351
#ifdef STORE_REST
352
      inptr = bytebuf;
353
      inptrp = &inptr;
354
      inend = &bytebuf[inlen];
355
 
356
      STORE_REST
357
#else
358
      /* We don't have enough input for another complete input
359
         character.  */
360
      while (inptr < inend)
361
        state->__value.__wchb[inlen++] = *inptr++;
362
#endif
363
 
364
      return __GCONV_INCOMPLETE_INPUT;
365
    }
366
 
367
  /* Enough space in output buffer.  */
368
  if ((MIN_NEEDED_OUTPUT != 1 && outptr + MIN_NEEDED_OUTPUT > outend)
369
      || (MIN_NEEDED_OUTPUT == 1 && outptr >= outend))
370
    /* Overflow in the output buffer.  */
371
    return __GCONV_FULL_OUTPUT;
372
 
373
  /*  Now add characters from the normal input buffer.  */
374
  do
375
    bytebuf[inlen++] = *inptr++;
376
  while (inlen < MAX_NEEDED_INPUT && inptr < inend);
377
 
378
  inptr = bytebuf;
379
  inend = &bytebuf[inlen];
380
 
381
  do
382
    {
383
      BODY
384
    }
385
  while (0);
386
 
387
  /* Now we either have produced an output character and consumed all the
388
     bytes from the state and at least one more, or the character is still
389
     incomplete, or we have some other error (like illegal input character,
390
     no space in output buffer).  */
391
  if (__builtin_expect (inptr != bytebuf, 1))
392
    {
393
      /* We found a new character.  */
394
      assert (inptr - bytebuf > (state->__count & 7));
395
 
396
      *inptrp += inptr - bytebuf - (state->__count & 7);
397
      *outptrp = outptr;
398
 
399
      result = __GCONV_OK;
400
 
401
      /* Clear the state buffer.  */
402
      state->__count &= ~7;
403
    }
404
  else if (result == __GCONV_INCOMPLETE_INPUT)
405
    {
406
      /* This can only happen if we have less than MAX_NEEDED_INPUT bytes
407
         available.  */
408
      assert (inend != &bytebuf[MAX_NEEDED_INPUT]);
409
 
410
      *inptrp += inend - bytebuf - (state->__count & 7);
411
#ifdef STORE_REST
412
      inptrp = &inptr;
413
 
414
      STORE_REST
415
#else
416
      /* We don't have enough input for another complete input
417
         character.  */
418
      while (inptr < inend)
419
        state->__value.__wchb[inlen++] = *inptr++;
420
#endif
421
    }
422
 
423
  return result;
424
}
425
# undef SINGLE
426
# undef SINGLE2
427
#endif
428
 
429
 
430
/* We remove the macro definitions so that we can include this file again
431
   for the definition of another function.  */
432
#undef MIN_NEEDED_INPUT
433
#undef MAX_NEEDED_INPUT
434
#undef MIN_NEEDED_OUTPUT
435
#undef MAX_NEEDED_OUTPUT
436
#undef LOOPFCT
437
#undef BODY
438
#undef LOOPFCT
439
#undef EXTRA_LOOP_DECLS
440
#undef INIT_PARAMS
441
#undef UPDATE_PARAMS
442
#undef UNPACK_BYTES
443
#undef LOOP_NEED_STATE
444
#undef LOOP_NEED_FLAGS
445
#undef LOOP_NEED_DATA
446
#undef get16
447
#undef get32
448
#undef put16
449
#undef put32
450
#undef unaligned

powered by: WebSVN 2.1.0

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