]>
Commit | Line | Data |
---|---|---|
09376451 | 1 | /* Skeleton for a conversion module. |
63e04088 | 2 | Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. |
8619129f UD |
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 can be included to provide definitions of several things | |
22 | many modules have in common. It can be customized using the following | |
23 | macros: | |
24 | ||
25 | DEFINE_INIT define the default initializer. This requires the | |
26 | following symbol to be defined. | |
27 | ||
28 | CHARSET_NAME string with official name of the coded character | |
29 | set (in all-caps) | |
30 | ||
31 | DEFINE_FINI define the default destructor function. | |
32 | ||
33 | MIN_NEEDED_FROM minimal number of bytes needed for the from-charset. | |
34 | MIN_NEEDED_TO likewise for the to-charset. | |
35 | ||
36 | MAX_NEEDED_FROM maximal number of bytes needed for the from-charset. | |
37 | This macro is optional, it defaults to MIN_NEEDED_FROM. | |
38 | MAX_NEEDED_TO likewise for the to-charset. | |
39 | ||
40 | DEFINE_DIRECTION_OBJECTS | |
41 | two objects will be defined to be used when the | |
42 | `gconv' function must only distinguish two | |
43 | directions. This is implied by DEFINE_INIT. | |
44 | If this macro is not defined the following | |
45 | macro must be available. | |
46 | ||
47 | FROM_DIRECTION this macro is supposed to return a value != 0 | |
48 | if we convert from the current character set, | |
49 | otherwise it return 0. | |
50 | ||
51 | EMIT_SHIFT_TO_INIT this symbol is optional. If it is defined it | |
52 | defines some code which writes out a sequence | |
53 | of characters which bring the current state into | |
54 | the initial state. | |
55 | ||
56 | FROM_LOOP name of the function implementing the conversion | |
57 | from the current characters. | |
58 | TO_LOOP likewise for the other direction | |
59 | ||
60 | RESET_STATE in case of an error we must reset the state for | |
61 | the rerun so this macro must be defined for | |
62 | stateful encodings. It takes an argument which | |
63 | is nonzero when saving. | |
64 | ||
65 | RESET_INPUT_BUFFER If the input character sets allow this the macro | |
66 | can be defined to reset the input buffer pointers | |
67 | to cover only those characters up to the error. | |
68 | ||
69 | FUNCTION_NAME if not set the conversion function is named `gconv'. | |
28f1c862 UD |
70 | |
71 | PREPARE_LOOP optional code preparing the conversion loop. Can | |
72 | contain variable definitions. | |
918b9d72 | 73 | END_LOOP also optional, may be used to store information |
28f1c862 UD |
74 | |
75 | EXTRA_LOOP_ARGS optional macro specifying extra arguments passed | |
76 | to loop function. | |
8619129f UD |
77 | */ |
78 | ||
79 | #include <assert.h> | |
80 | #include <gconv.h> | |
81 | #include <string.h> | |
82 | #define __need_size_t | |
83 | #define __need_NULL | |
84 | #include <stddef.h> | |
c66dbe00 UD |
85 | |
86 | #ifndef STATIC_GCONV | |
87 | # include <dlfcn.h> | |
c66dbe00 | 88 | #endif |
8619129f | 89 | |
a808d541 UD |
90 | #ifndef DL_CALL_FCT |
91 | # define DL_CALL_FCT(fct, args) fct args | |
92 | #endif | |
93 | ||
8619129f UD |
94 | /* The direction objects. */ |
95 | #if DEFINE_DIRECTION_OBJECTS || DEFINE_INIT | |
96 | static int from_object; | |
97 | static int to_object; | |
98 | ||
99 | # ifndef FROM_DIRECTION | |
d64b6ad0 | 100 | # define FROM_DIRECTION (step->__data == &from_object) |
8619129f UD |
101 | # endif |
102 | #else | |
103 | # ifndef FROM_DIRECTION | |
104 | # error "FROM_DIRECTION must be provided if direction objects are not used" | |
105 | # endif | |
106 | #endif | |
107 | ||
108 | ||
109 | /* How many bytes are needed at most for the from-charset. */ | |
110 | #ifndef MAX_NEEDED_FROM | |
111 | # define MAX_NEEDED_FROM MIN_NEEDED_FROM | |
112 | #endif | |
113 | ||
114 | /* Same for the to-charset. */ | |
115 | #ifndef MAX_NEEDED_TO | |
116 | # define MAX_NEEDED_TO MIN_NEEDED_TO | |
117 | #endif | |
118 | ||
119 | ||
77e1d15a UD |
120 | /* Define macros which can access unaligned buffers. These macros are |
121 | supposed to be used only in code outside the inner loops. For the inner | |
122 | loops we have other definitions which allow optimized access. */ | |
123 | #ifdef _STRING_ARCH_unaligned | |
124 | /* We can handle unaligned memory access. */ | |
c1db8b0d UD |
125 | # define get16u(addr) *((uint16_t *) (addr)) |
126 | # define get32u(addr) *((uint32_t *) (addr)) | |
77e1d15a UD |
127 | |
128 | /* We need no special support for writing values either. */ | |
c1db8b0d UD |
129 | # define put16u(addr, val) *((uint16_t *) (addr)) = (val) |
130 | # define put32u(addr, val) *((uint32_t *) (addr)) = (val) | |
77e1d15a UD |
131 | #else |
132 | /* Distinguish between big endian and little endian. */ | |
133 | # if __BYTE_ORDER == __LITTLE_ENDIAN | |
c1db8b0d | 134 | # define get16u(addr) \ |
77e1d15a UD |
135 | (((__const unsigned char *) (addr))[1] << 8 \ |
136 | | ((__const unsigned char *) (addr))[0]) | |
c1db8b0d | 137 | # define get32u(addr) \ |
77e1d15a UD |
138 | (((((__const unsigned char *) (addr))[3] << 8 \ |
139 | | ((__const unsigned char *) (addr))[2]) << 8 \ | |
140 | | ((__const unsigned char *) (addr))[1]) << 8 \ | |
141 | | ((__const unsigned char *) (addr))[0]) | |
142 | ||
c1db8b0d | 143 | # define put16u(addr, val) \ |
77e1d15a | 144 | ({ uint16_t __val = (val); \ |
cb2c5501 UD |
145 | ((unsigned char *) (addr))[0] = __val; \ |
146 | ((unsigned char *) (addr))[1] = __val >> 8; \ | |
77e1d15a | 147 | (void) 0; }) |
c1db8b0d | 148 | # define put32u(addr, val) \ |
cb2c5501 UD |
149 | ({ uint32_t __val = (val); \ |
150 | ((unsigned char *) (addr))[0] = __val; \ | |
77e1d15a | 151 | __val >>= 8; \ |
cb2c5501 | 152 | ((unsigned char *) (addr))[1] = __val; \ |
77e1d15a | 153 | __val >>= 8; \ |
cb2c5501 | 154 | ((unsigned char *) (addr))[2] = __val; \ |
77e1d15a | 155 | __val >>= 8; \ |
cb2c5501 | 156 | ((unsigned char *) (addr))[3] = __val; \ |
77e1d15a UD |
157 | (void) 0; }) |
158 | # else | |
c1db8b0d | 159 | # define get16u(addr) \ |
77e1d15a UD |
160 | (((__const unsigned char *) (addr))[0] << 8 \ |
161 | | ((__const unsigned char *) (addr))[1]) | |
c1db8b0d | 162 | # define get32u(addr) \ |
77e1d15a UD |
163 | (((((__const unsigned char *) (addr))[0] << 8 \ |
164 | | ((__const unsigned char *) (addr))[1]) << 8 \ | |
165 | | ((__const unsigned char *) (addr))[2]) << 8 \ | |
166 | | ((__const unsigned char *) (addr))[3]) | |
167 | ||
c1db8b0d | 168 | # define put16u(addr, val) \ |
77e1d15a | 169 | ({ uint16_t __val = (val); \ |
cb2c5501 | 170 | ((unsigned char *) (addr))[1] = __val; \ |
a1303dc8 | 171 | ((unsigned char *) (addr))[0] = __val >> 8; \ |
77e1d15a | 172 | (void) 0; }) |
c1db8b0d | 173 | # define put32u(addr, val) \ |
cb2c5501 UD |
174 | ({ uint32_t __val = (val); \ |
175 | ((unsigned char *) (addr))[3] = __val; \ | |
77e1d15a | 176 | __val >>= 8; \ |
cb2c5501 | 177 | ((unsigned char *) (addr))[2] = __val; \ |
77e1d15a | 178 | __val >>= 8; \ |
cb2c5501 | 179 | ((unsigned char *) (addr))[1] = __val; \ |
77e1d15a | 180 | __val >>= 8; \ |
cb2c5501 | 181 | ((unsigned char *) (addr))[0] = __val; \ |
77e1d15a UD |
182 | (void) 0; }) |
183 | # endif | |
184 | #endif | |
185 | ||
186 | ||
8619129f UD |
187 | /* For conversions from a fixed width character sets to another fixed width |
188 | character set we we can define RESET_INPUT_BUFFER is necessary. */ | |
189 | #if !defined RESET_INPUT_BUFFER && !defined SAVE_RESET_STATE | |
190 | # if MIN_NEEDED_FROM == MAX_NEEDED_FROM && MIN_NEEDED_TO == MAX_NEEDED_TO | |
390955cb | 191 | /* We have to use these `if's here since the compiler cannot know that |
8619129f UD |
192 | (outbuf - outerr) is always divisible by MIN_NEEDED_TO. */ |
193 | # define RESET_INPUT_BUFFER \ | |
194 | if (MIN_NEEDED_FROM % MIN_NEEDED_TO == 0) \ | |
fd1b5c0f | 195 | *inptrp -= (outbuf - outerr) * (MIN_NEEDED_FROM / MIN_NEEDED_TO); \ |
8619129f | 196 | else if (MIN_NEEDED_TO % MIN_NEEDED_FROM == 0) \ |
fd1b5c0f | 197 | *inptrp -= (outbuf - outerr) / (MIN_NEEDED_TO / MIN_NEEDED_FROM); \ |
8619129f | 198 | else \ |
fd1b5c0f | 199 | *inptrp -= ((outbuf - outerr) / MIN_NEEDED_TO) * MIN_NEEDED_FROM |
8619129f UD |
200 | # endif |
201 | #endif | |
202 | ||
203 | ||
204 | /* The default init function. It simply matches the name and initializes | |
205 | the step data to point to one of the objects above. */ | |
206 | #if DEFINE_INIT | |
207 | # ifndef CHARSET_NAME | |
208 | # error "CHARSET_NAME not defined" | |
209 | # endif | |
210 | ||
211 | int | |
d64b6ad0 | 212 | gconv_init (struct __gconv_step *step) |
8619129f UD |
213 | { |
214 | /* Determine which direction. */ | |
d64b6ad0 | 215 | if (strcmp (step->__from_name, CHARSET_NAME) == 0) |
918b9d72 | 216 | { |
d64b6ad0 | 217 | step->__data = &from_object; |
390955cb | 218 | |
d64b6ad0 UD |
219 | step->__min_needed_from = MIN_NEEDED_FROM; |
220 | step->__max_needed_from = MAX_NEEDED_FROM; | |
221 | step->__min_needed_to = MIN_NEEDED_TO; | |
222 | step->__max_needed_to = MAX_NEEDED_TO; | |
918b9d72 | 223 | } |
365afefc | 224 | else if (__builtin_expect (strcmp (step->__to_name, CHARSET_NAME), 0) == 0) |
918b9d72 | 225 | { |
d64b6ad0 | 226 | step->__data = &to_object; |
390955cb | 227 | |
d64b6ad0 UD |
228 | step->__min_needed_from = MIN_NEEDED_TO; |
229 | step->__max_needed_from = MAX_NEEDED_TO; | |
230 | step->__min_needed_to = MIN_NEEDED_FROM; | |
231 | step->__max_needed_to = MAX_NEEDED_FROM; | |
918b9d72 | 232 | } |
390955cb | 233 | else |
d64b6ad0 | 234 | return __GCONV_NOCONV; |
8619129f | 235 | |
9ce5071a | 236 | #ifdef RESET_STATE |
d64b6ad0 | 237 | step->__stateful = 1; |
9ce5071a | 238 | #else |
d64b6ad0 | 239 | step->__stateful = 0; |
9ce5071a UD |
240 | #endif |
241 | ||
d64b6ad0 | 242 | return __GCONV_OK; |
8619129f UD |
243 | } |
244 | #endif | |
245 | ||
246 | ||
247 | /* The default destructor function does nothing in the moment and so | |
248 | be define it at all. But we still provide the macro just in case | |
249 | we need it some day. */ | |
250 | #if DEFINE_FINI | |
251 | #endif | |
252 | ||
253 | ||
28f1c862 UD |
254 | /* If no arguments have to passed to the loop function define the macro |
255 | as empty. */ | |
256 | #ifndef EXTRA_LOOP_ARGS | |
257 | # define EXTRA_LOOP_ARGS | |
258 | #endif | |
259 | ||
260 | ||
8619129f UD |
261 | /* This is the actual conversion function. */ |
262 | #ifndef FUNCTION_NAME | |
263 | # define FUNCTION_NAME gconv | |
264 | #endif | |
265 | ||
fd1b5c0f UD |
266 | /* The macros are used to access the function to convert single characters. */ |
267 | #define SINGLE(fct) SINGLE2 (fct) | |
268 | #define SINGLE2(fct) fct##_single | |
269 | ||
270 | ||
8619129f | 271 | int |
d64b6ad0 | 272 | FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data, |
fd1b5c0f | 273 | const unsigned char **inptrp, const unsigned char *inend, |
f1d5c60d | 274 | unsigned char **outbufstart, size_t *irreversible, int do_flush, |
55985355 | 275 | int consume_incomplete) |
8619129f | 276 | { |
d64b6ad0 UD |
277 | struct __gconv_step *next_step = step + 1; |
278 | struct __gconv_step_data *next_data = data + 1; | |
85830c4c | 279 | __gconv_fct fct; |
8619129f UD |
280 | int status; |
281 | ||
85830c4c UD |
282 | fct = (data->__flags & __GCONV_IS_LAST) ? NULL : next_step->__fct; |
283 | ||
8619129f UD |
284 | /* If the function is called with no input this means we have to reset |
285 | to the initial state. The possibly partly converted input is | |
286 | dropped. */ | |
978ce92b | 287 | if (__builtin_expect (do_flush, 0)) |
8619129f | 288 | { |
d64b6ad0 | 289 | status = __GCONV_OK; |
8619129f | 290 | |
f1d5c60d UD |
291 | /* This should never happen during error handling. */ |
292 | assert (outbufstart == NULL); | |
293 | ||
390955cb UD |
294 | #ifdef EMIT_SHIFT_TO_INIT |
295 | /* Emit the escape sequence to reset the state. */ | |
296 | EMIT_SHIFT_TO_INIT; | |
777e222d UD |
297 | #else |
298 | /* Clear the state object. There might be bytes in there from | |
299 | previous calls with CONSUME_INCOMPLETE == 1. */ | |
300 | memset (data->__statep, '\0', sizeof (*data->__statep)); | |
8619129f | 301 | #endif |
390955cb | 302 | /* Call the steps down the chain if there are any but only if we |
777e222d UD |
303 | successfully emitted the escape sequence. This should only |
304 | fail if the output buffer is full. If the input is invalid | |
305 | it should be discarded since the user wants to start from a | |
306 | clean slate. */ | |
85830c4c | 307 | if (status == __GCONV_OK && ! (data->__flags & __GCONV_IS_LAST)) |
390955cb | 308 | status = DL_CALL_FCT (fct, (next_step, next_data, NULL, NULL, |
f1d5c60d | 309 | NULL, irreversible, 1, |
55985355 | 310 | consume_incomplete)); |
8619129f UD |
311 | } |
312 | else | |
313 | { | |
8619129f | 314 | /* We preserve the initial values of the pointer variables. */ |
fd1b5c0f | 315 | const unsigned char *inptr = *inptrp; |
f1d5c60d UD |
316 | unsigned char *outbuf = (__builtin_expect (outbufstart == NULL, 1) |
317 | ? data->__outbuf : *outbufstart); | |
d64b6ad0 | 318 | unsigned char *outend = data->__outbufend; |
b117f744 | 319 | unsigned char *outstart; |
3aaad0b6 UD |
320 | /* This variable is used to count the number of characters we |
321 | actually converted. */ | |
38677ace | 322 | size_t lirreversible = 0; |
b572c2da | 323 | size_t *lirreversiblep = irreversible ? &lirreversible : NULL; |
fdf64555 UD |
324 | #if defined _STRING_ARCH_unaligned \ |
325 | || MIN_NEEDED_FROM == 1 || MAX_NEEDED_FROM % MIN_NEEDED_FROM != 0 \ | |
326 | || MIN_NEEDED_TO == 1 || MAX_NEEDED_TO % MIN_NEEDED_TO != 0 | |
77e1d15a UD |
327 | # define unaligned 0 |
328 | #else | |
3aaad0b6 | 329 | int unaligned; |
77e1d15a UD |
330 | # define GEN_unaligned(name) GEN_unaligned2 (name) |
331 | # define GEN_unaligned2(name) name##_unaligned | |
332 | #endif | |
8619129f | 333 | |
28f1c862 UD |
334 | #ifdef PREPARE_LOOP |
335 | PREPARE_LOOP | |
336 | #endif | |
337 | ||
fd1b5c0f UD |
338 | #if MAX_NEEDED_FROM > 1 || MAX_NEEDED_TO > 1 |
339 | /* If the function is used to implement the mb*towc*() or wc*tomb*() | |
340 | functions we must test whether any bytes from the last call are | |
341 | stored in the `state' object. */ | |
342 | if (((MAX_NEEDED_FROM > 1 && FROM_DIRECTION) | |
343 | || (MAX_NEEDED_TO > 1 && !FROM_DIRECTION)) | |
344 | && consume_incomplete && (data->__statep->__count & 7) != 0) | |
345 | { | |
f1d5c60d UD |
346 | /* Yep, we have some bytes left over. Process them now. |
347 | But this must not happen while we are called from an | |
348 | error handler. */ | |
349 | assert (outbufstart == NULL); | |
fd1b5c0f UD |
350 | |
351 | # if MAX_NEEDED_FROM > 1 | |
352 | if (MAX_NEEDED_TO == 1 || FROM_DIRECTION) | |
55985355 | 353 | status = SINGLE(FROM_LOOP) (step, data, inptrp, inend, &outbuf, |
b572c2da | 354 | outend, lirreversiblep |
85830c4c | 355 | EXTRA_LOOP_ARGS); |
fd1b5c0f UD |
356 | # endif |
357 | # if MAX_NEEDED_FROM > 1 && MAX_NEEDED_TO > 1 && !ONE_DIRECTION | |
358 | else | |
359 | # endif | |
360 | # if MAX_NEEDED_TO > 1 && !ONE_DIRECTION | |
55985355 | 361 | status = SINGLE(TO_LOOP) (step, data, inptrp, inend, &outbuf, |
b572c2da | 362 | outend, lirreversiblep EXTRA_LOOP_ARGS); |
fd1b5c0f UD |
363 | # endif |
364 | ||
365afefc | 365 | if (__builtin_expect (status, __GCONV_OK) != __GCONV_OK) |
fd1b5c0f UD |
366 | return status; |
367 | } | |
368 | #endif | |
369 | ||
3aaad0b6 UD |
370 | #if !defined _STRING_ARCH_unaligned \ |
371 | && MIN_NEEDED_FROM != 1 && MAX_NEEDED_FROM % MIN_NEEDED_FROM == 0 \ | |
372 | && MIN_NEEDED_TO != 1 && MAX_NEEDED_TO % MIN_NEEDED_TO == 0 | |
373 | /* The following assumes that encodings, which have a variable length | |
374 | what might unalign a buffer even though it is a aligned in the | |
375 | beginning, either don't have the minimal number of bytes as a divisor | |
376 | of the maximum length or have a minimum length of 1. This is true | |
377 | for all known and supported encodings. */ | |
378 | unaligned = ((FROM_DIRECTION | |
379 | && ((uintptr_t) inptr % MIN_NEEDED_FROM != 0 | |
85830c4c | 380 | || ((data->__flags & __GCONV_IS_LAST) |
3aaad0b6 UD |
381 | && (uintptr_t) outbuf % MIN_NEEDED_TO != 0))) |
382 | || (!FROM_DIRECTION | |
85830c4c | 383 | && (((data->__flags & __GCONV_IS_LAST) |
3aaad0b6 UD |
384 | && (uintptr_t) outbuf % MIN_NEEDED_FROM != 0) |
385 | || (uintptr_t) inptr % MIN_NEEDED_TO != 0))); | |
386 | #endif | |
387 | ||
8619129f UD |
388 | do |
389 | { | |
d6204268 UD |
390 | struct __gconv_trans_data *trans; |
391 | ||
8619129f | 392 | /* Remember the start value for this round. */ |
fd1b5c0f | 393 | inptr = *inptrp; |
8619129f | 394 | /* The outbuf buffer is empty. */ |
b117f744 | 395 | outstart = outbuf; |
8619129f | 396 | |
8619129f UD |
397 | #ifdef SAVE_RESET_STATE |
398 | SAVE_RESET_STATE (1); | |
399 | #endif | |
400 | ||
365afefc | 401 | if (__builtin_expect (!unaligned, 1)) |
77e1d15a UD |
402 | { |
403 | if (FROM_DIRECTION) | |
404 | /* Run the conversion loop. */ | |
55985355 | 405 | status = FROM_LOOP (step, data, inptrp, inend, &outbuf, outend, |
b572c2da | 406 | lirreversiblep EXTRA_LOOP_ARGS); |
77e1d15a UD |
407 | else |
408 | /* Run the conversion loop. */ | |
55985355 | 409 | status = TO_LOOP (step, data, inptrp, inend, &outbuf, outend, |
b572c2da | 410 | lirreversiblep EXTRA_LOOP_ARGS); |
77e1d15a | 411 | } |
c1db8b0d UD |
412 | #if !defined _STRING_ARCH_unaligned \ |
413 | && MIN_NEEDED_FROM != 1 && MAX_NEEDED_FROM % MIN_NEEDED_FROM == 0 \ | |
414 | && MIN_NEEDED_TO != 1 && MAX_NEEDED_TO % MIN_NEEDED_TO == 0 | |
8619129f | 415 | else |
77e1d15a UD |
416 | { |
417 | if (FROM_DIRECTION) | |
418 | /* Run the conversion loop. */ | |
55985355 UD |
419 | status = GEN_unaligned (FROM_LOOP) (step, data, inptrp, inend, |
420 | &outbuf, outend, | |
b572c2da | 421 | lirreversiblep |
77e1d15a UD |
422 | EXTRA_LOOP_ARGS); |
423 | else | |
424 | /* Run the conversion loop. */ | |
55985355 UD |
425 | status = GEN_unaligned (TO_LOOP) (step, data, inptrp, inend, |
426 | &outbuf, outend, | |
b572c2da | 427 | lirreversiblep |
77e1d15a UD |
428 | EXTRA_LOOP_ARGS); |
429 | } | |
430 | #endif | |
8619129f | 431 | |
f1d5c60d UD |
432 | /* If we were called as part of an error handling module we |
433 | don't do anything else here. */ | |
434 | if (__builtin_expect (outbufstart != NULL, 0)) | |
435 | { | |
436 | *outbufstart = outbuf; | |
437 | return status; | |
438 | } | |
439 | ||
4d37e19c UD |
440 | /* Give the transliteration module the chance to store the |
441 | original text and the result in case it needs a context. */ | |
d6204268 UD |
442 | for (trans = data->__trans; trans != NULL; trans = trans->__next) |
443 | if (trans->__trans_context_fct != NULL) | |
444 | DL_CALL_FCT (trans->__trans_context_fct, | |
445 | (trans->__data, inptr, *inptrp, outstart, outbuf)); | |
4d37e19c | 446 | |
0aece08d UD |
447 | /* We finished one use of the loops. */ |
448 | ++data->__invocation_counter; | |
449 | ||
390955cb | 450 | /* If this is the last step leave the loop, there is nothing |
8619129f | 451 | we can do. */ |
365afefc | 452 | if (__builtin_expect (data->__flags & __GCONV_IS_LAST, 0)) |
8619129f UD |
453 | { |
454 | /* Store information about how many bytes are available. */ | |
d64b6ad0 | 455 | data->__outbuf = outbuf; |
bf979eef | 456 | |
38677ace UD |
457 | /* Remember how many non-identical characters we |
458 | converted in a irreversible way. */ | |
459 | *irreversible += lirreversible; | |
bf979eef | 460 | |
8619129f UD |
461 | break; |
462 | } | |
463 | ||
464 | /* Write out all output which was produced. */ | |
365afefc | 465 | if (__builtin_expect (outbuf > outstart, 1)) |
8619129f | 466 | { |
d64b6ad0 | 467 | const unsigned char *outerr = data->__outbuf; |
8619129f UD |
468 | int result; |
469 | ||
4bae5567 | 470 | result = DL_CALL_FCT (fct, (next_step, next_data, &outerr, |
f1d5c60d | 471 | outbuf, NULL, irreversible, 0, |
fd1b5c0f | 472 | consume_incomplete)); |
8619129f | 473 | |
d64b6ad0 | 474 | if (result != __GCONV_EMPTY_INPUT) |
8619129f | 475 | { |
978ce92b | 476 | if (__builtin_expect (outerr != outbuf, 0)) |
8619129f UD |
477 | { |
478 | #ifdef RESET_INPUT_BUFFER | |
479 | RESET_INPUT_BUFFER; | |
480 | #else | |
481 | /* We have a problem with the in on of the functions | |
482 | below. Undo the conversion upto the error point. */ | |
483 | size_t nstatus; | |
484 | ||
485 | /* Reload the pointers. */ | |
fd1b5c0f | 486 | *inptrp = inptr; |
b117f744 | 487 | outbuf = outstart; |
8619129f UD |
488 | |
489 | /* Reset the state. */ | |
490 | # ifdef SAVE_RESET_STATE | |
491 | SAVE_RESET_STATE (0); | |
492 | # endif | |
493 | ||
85830c4c | 494 | /* XXX Handle unaligned access here as well. */ |
8619129f UD |
495 | if (FROM_DIRECTION) |
496 | /* Run the conversion loop. */ | |
55985355 UD |
497 | nstatus = FROM_LOOP (step, data, |
498 | (const unsigned char **) inptrp, | |
fd1b5c0f | 499 | (const unsigned char *) inend, |
8619129f UD |
500 | (unsigned char **) &outbuf, |
501 | (unsigned char *) outerr, | |
b572c2da | 502 | lirreversiblep EXTRA_LOOP_ARGS); |
8619129f UD |
503 | else |
504 | /* Run the conversion loop. */ | |
55985355 UD |
505 | nstatus = TO_LOOP (step, data, |
506 | (const unsigned char **) inptrp, | |
fd1b5c0f | 507 | (const unsigned char *) inend, |
8619129f UD |
508 | (unsigned char **) &outbuf, |
509 | (unsigned char *) outerr, | |
b572c2da | 510 | lirreversiblep EXTRA_LOOP_ARGS); |
8619129f UD |
511 | |
512 | /* We must run out of output buffer space in this | |
513 | rerun. */ | |
5aa8ff62 | 514 | assert (outbuf == outerr); |
d64b6ad0 | 515 | assert (nstatus == __GCONV_FULL_OUTPUT); |
0aece08d UD |
516 | |
517 | /* If we haven't consumed a single byte decrement | |
518 | the invocation counter. */ | |
365afefc | 519 | if (__builtin_expect (outbuf == outstart, 0)) |
0aece08d | 520 | --data->__invocation_counter; |
8619129f UD |
521 | #endif /* reset input buffer */ |
522 | } | |
523 | ||
524 | /* Change the status. */ | |
525 | status = result; | |
526 | } | |
527 | else | |
528 | /* All the output is consumed, we can make another run | |
529 | if everything was ok. */ | |
d64b6ad0 UD |
530 | if (status == __GCONV_FULL_OUTPUT) |
531 | status = __GCONV_OK; | |
8619129f UD |
532 | } |
533 | } | |
d64b6ad0 | 534 | while (status == __GCONV_OK); |
8619129f | 535 | |
918b9d72 UD |
536 | #ifdef END_LOOP |
537 | END_LOOP | |
538 | #endif | |
fd1b5c0f UD |
539 | |
540 | /* If we are supposed to consume all character store now all of the | |
541 | remaining characters in the `state' object. */ | |
542 | #if MAX_NEEDED_FROM > 1 || MAX_NEEDED_TO > 1 | |
543 | if (((MAX_NEEDED_FROM > 1 && FROM_DIRECTION) | |
544 | || (MAX_NEEDED_TO > 1 && !FROM_DIRECTION)) | |
365afefc UD |
545 | && __builtin_expect (consume_incomplete, 0) |
546 | && status == __GCONV_INCOMPLETE_INPUT) | |
fd1b5c0f UD |
547 | { |
548 | # ifdef STORE_REST | |
549 | mbstate_t *state = data->__statep; | |
550 | ||
551 | STORE_REST | |
552 | # else | |
553 | size_t cnt; | |
554 | ||
555 | /* Make sure the remaining bytes fit into the state objects | |
556 | buffer. */ | |
557 | assert (inend - *inptrp < 4); | |
558 | ||
559 | for (cnt = 0; *inptrp < inend; ++cnt) | |
560 | data->__statep->__value.__wchb[cnt] = *(*inptrp)++; | |
561 | data->__statep->__count &= ~7; | |
562 | data->__statep->__count |= cnt; | |
563 | # endif | |
564 | } | |
565 | #endif | |
8619129f UD |
566 | } |
567 | ||
568 | return status; | |
569 | } | |
570 | ||
571 | #undef DEFINE_INIT | |
572 | #undef CHARSET_NAME | |
573 | #undef DEFINE_FINI | |
574 | #undef MIN_NEEDED_FROM | |
575 | #undef MIN_NEEDED_TO | |
576 | #undef MAX_NEEDED_FROM | |
577 | #undef MAX_NEEDED_TO | |
578 | #undef DEFINE_DIRECTION_OBJECTS | |
579 | #undef FROM_DIRECTION | |
580 | #undef EMIT_SHIFT_TO_INIT | |
581 | #undef FROM_LOOP | |
582 | #undef TO_LOOP | |
583 | #undef RESET_STATE | |
584 | #undef RESET_INPUT_BUFFER | |
585 | #undef FUNCTION_NAME | |
918b9d72 UD |
586 | #undef PREPARE_LOOP |
587 | #undef END_LOOP | |
fd1b5c0f UD |
588 | #undef ONE_DIRECTION |
589 | #undef STORE_REST |