(LOOPFC): Make outend parameter const. Add cast to avoid warning.
[kopensolaris-gnu/glibc.git] / iconv / loop.c
1 /* Conversion loop frame work.
2    Copyright (C) 1998, 1999, 2000 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 Library General Public License as
8    published by the Free Software Foundation; either version 2 of the
9    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    Library General Public License for more details.
15
16    You should have received a copy of the GNU Library General Public
17    License along with the GNU C Library; see the file COPYING.LIB.  If not,
18    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 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 <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) *((uint16_t *) (addr))
67 # define get32(addr) *((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))[2] = __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 = DL_CALL_FCT (trans->__trans_fct,                             \
195                               (step, step_data, trans->__data, *inptrp,       \
196                                &inptr, inend, &outptr, irreversible));        \
197         if (result != __GCONV_ILLEGAL_INPUT)                                  \
198           break;                                                              \
199       }                                                                       \
200     /* If any of them recognized the input continue with the loop.  */        \
201     if (result != __GCONV_ILLEGAL_INPUT)                                      \
202       continue;                                                               \
203                                                                               \
204     /* Next see whether we have to ignore the error.  If not, stop.  */       \
205     if (! ignore_errors_p ())                                                 \
206       break;                                                                  \
207                                                                               \
208     /* When we come here it means we ignore the character.  */                \
209     ++*irreversible;                                                          \
210     inptr += Incr;                                                            \
211     continue;                                                                 \
212   }
213
214
215 /* The function returns the status, as defined in gconv.h.  */
216 static inline int
217 FCTNAME (LOOPFCT) (struct __gconv_step *step,
218                    struct __gconv_step_data *step_data,
219                    const unsigned char **inptrp, const unsigned char *inend,
220                    unsigned char **outptrp, const unsigned char *outend,
221                    size_t *irreversible EXTRA_LOOP_DECLS)
222 {
223 #ifdef LOOP_NEED_STATE
224   mbstate_t *state = step_data->__statep;
225 #endif
226 #ifdef LOOP_NEED_FLAGS
227   int flags = step_data->__flags;
228 #endif
229 #ifdef LOOP_NEED_DATA
230   void *data = step->__data;
231 #endif
232   int result = __GCONV_EMPTY_INPUT;
233   const unsigned char *inptr = *inptrp;
234   unsigned char *outptr = *outptrp;
235
236 #ifdef INIT_PARAMS
237   INIT_PARAMS;
238 #endif
239
240   while (inptr != inend)
241     {
242       /* `if' cases for MIN_NEEDED_OUTPUT ==/!= 1 is made to help the
243          compiler generating better code.  They will be optimized away
244          since MIN_NEEDED_OUTPUT is always a constant.  */
245       if ((MIN_NEEDED_OUTPUT != 1
246            && __builtin_expect (outptr + MIN_NEEDED_OUTPUT > outend, 0))
247           || (MIN_NEEDED_OUTPUT == 1
248               && __builtin_expect (outptr >= outend, 0)))
249         {
250           /* Overflow in the output buffer.  */
251           result = __GCONV_FULL_OUTPUT;
252           break;
253         }
254       if (MIN_NEEDED_INPUT > 1
255           && __builtin_expect (inptr + MIN_NEEDED_INPUT > inend, 0))
256         {
257           /* We don't have enough input for another complete input
258              character.  */
259           result = __GCONV_INCOMPLETE_INPUT;
260           break;
261         }
262
263       /* Here comes the body the user provides.  It can stop with
264          RESULT set to GCONV_INCOMPLETE_INPUT (if the size of the
265          input characters vary in size), GCONV_ILLEGAL_INPUT, or
266          GCONV_FULL_OUTPUT (if the output characters vary in size).  */
267       BODY
268     }
269
270   /* Update the pointers pointed to by the parameters.  */
271   *inptrp = inptr;
272   *outptrp = outptr;
273 #ifdef UPDATE_PARAMS
274   UPDATE_PARAMS;
275 #endif
276
277   return result;
278 }
279
280
281 /* Include the file a second time to define the function to handle
282    unaligned access.  */
283 #if !defined DEFINE_UNALIGNED && !defined _STRING_ARCH_unaligned \
284     && MIN_NEEDED_FROM != 1 && MAX_NEEDED_FROM % MIN_NEEDED_FROM == 0 \
285     && MIN_NEEDED_TO != 1 && MAX_NEEDED_TO % MIN_NEEDED_TO == 0
286 # undef get16
287 # undef get32
288 # undef put16
289 # undef put32
290 # undef unaligned
291
292 # define DEFINE_UNALIGNED
293 # include "loop.c"
294 # undef DEFINE_UNALIGNED
295 #endif
296
297
298 #if MAX_NEEDED_INPUT > 1
299 # define SINGLE(fct) SINGLE2 (fct)
300 # define SINGLE2(fct) fct##_single
301 static inline int
302 SINGLE(LOOPFCT) (struct __gconv_step *step,
303                  struct __gconv_step_data *step_data,
304                  const unsigned char **inptrp, const unsigned char *inend,
305                  unsigned char **outptrp, unsigned char *outend,
306                  size_t *irreversible EXTRA_LOOP_DECLS)
307 {
308   mbstate_t *state = step_data->__statep;
309 #ifdef LOOP_NEED_FLAGS
310   int flags = step_data->__flags;
311 #endif
312 #ifdef LOOP_NEED_DATA
313   void *data = step->__data;
314 #endif
315   int result = __GCONV_OK;
316   unsigned char bytebuf[MAX_NEEDED_INPUT];
317   const unsigned char *inptr = *inptrp;
318   unsigned char *outptr = *outptrp;
319   size_t inlen;
320
321 #ifdef INIT_PARAMS
322   INIT_PARAMS;
323 #endif
324
325 #ifdef UNPACK_BYTES
326   UNPACK_BYTES
327 #else
328   /* Add the bytes from the state to the input buffer.  */
329   for (inlen = 0; inlen < (size_t) (state->__count & 7); ++inlen)
330     bytebuf[inlen] = state->__value.__wchb[inlen];
331 #endif
332
333   /* Are there enough bytes in the input buffer?  */
334   if (__builtin_expect (inptr + (MIN_NEEDED_INPUT - inlen) > inend, 0))
335     {
336       *inptrp = inend;
337 #ifdef STORE_REST
338       inptr = bytebuf;
339       inptrp = &inptr;
340       inend = &bytebuf[inlen];
341
342       STORE_REST
343 #else
344       /* We don't have enough input for another complete input
345          character.  */
346       while (inptr < inend)
347         state->__value.__wchb[inlen++] = *inptr++;
348 #endif
349
350       return __GCONV_INCOMPLETE_INPUT;
351     }
352
353   /* Enough space in output buffer.  */
354   if ((MIN_NEEDED_OUTPUT != 1 && outptr + MIN_NEEDED_OUTPUT > outend)
355       || (MIN_NEEDED_OUTPUT == 1 && outptr >= outend))
356     /* Overflow in the output buffer.  */
357     return __GCONV_FULL_OUTPUT;
358
359   /*  Now add characters from the normal input buffer.  */
360   do
361     bytebuf[inlen++] = *inptr++;
362   while (inlen < MAX_NEEDED_INPUT && inptr < inend);
363
364   inptr = bytebuf;
365   inend = &bytebuf[inlen];
366
367   do
368     {
369       BODY
370     }
371   while (0);
372
373   /* Now we either have produced an output character and consumed all the
374      bytes from the state and at least one more, or the character is still
375      incomplete, or we have some other error (like illegal input character,
376      no space in output buffer).  */
377   if (__builtin_expect (inptr != bytebuf, 1))
378     {
379       /* We found a new character.  */
380       assert (inptr - bytebuf > (state->__count & 7));
381
382       *inptrp += inptr - bytebuf - (state->__count & 7);
383       *outptrp = outptr;
384
385       result = __GCONV_OK;
386
387       /* Clear the state buffer.  */
388       state->__count &= ~7;
389     }
390   else if (result == __GCONV_INCOMPLETE_INPUT)
391     {
392       /* This can only happen if we have less than MAX_NEEDED_INPUT bytes
393          available.  */
394       assert (inend != &bytebuf[MAX_NEEDED_INPUT]);
395
396       *inptrp += inend - bytebuf - (state->__count & 7);
397 #ifdef STORE_REST
398       inptrp = &inptr;
399
400       STORE_REST
401 #else
402       /* We don't have enough input for another complete input
403          character.  */
404       while (inptr < inend)
405         state->__value.__wchb[inlen++] = *inptr++;
406 #endif
407     }
408
409   return result;
410 }
411 # undef SINGLE
412 # undef SINGLE2
413 #endif
414
415
416 /* We remove the macro definitions so that we can include this file again
417    for the definition of another function.  */
418 #undef MIN_NEEDED_INPUT
419 #undef MAX_NEEDED_INPUT
420 #undef MIN_NEEDED_OUTPUT
421 #undef MAX_NEEDED_OUTPUT
422 #undef LOOPFCT
423 #undef BODY
424 #undef LOOPFCT
425 #undef EXTRA_LOOP_DECLS
426 #undef INIT_PARAMS
427 #undef UPDATE_PARAMS
428 #undef UNPACK_BYTES
429 #undef LOOP_NEED_STATE
430 #undef LOOP_NEED_FLAGS
431 #undef LOOP_NEED_DATA
432 #undef get16
433 #undef get32
434 #undef put16
435 #undef put32
436 #undef unaligned