]> sourceware.org Git - glibc.git/blame - iconv/skeleton.c
hppa: Update libm-test-ulps
[glibc.git] / iconv / skeleton.c
CommitLineData
09376451 1/* Skeleton for a conversion module.
dff8da6b 2 Copyright (C) 1998-2024 Free Software Foundation, Inc.
8619129f 3 This file is part of the GNU C Library.
8619129f
UD
4
5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
8619129f
UD
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 13 Lesser General Public License for more details.
8619129f 14
41bdb6e2 15 You should have received a copy of the GNU Lesser General Public
59ba27a6 16 License along with the GNU C Library; if not, see
5a82c748 17 <https://www.gnu.org/licenses/>. */
8619129f
UD
18
19/* This file can be included to provide definitions of several things
20 many modules have in common. It can be customized using the following
21 macros:
22
23 DEFINE_INIT define the default initializer. This requires the
24 following symbol to be defined.
25
26 CHARSET_NAME string with official name of the coded character
27 set (in all-caps)
28
29 DEFINE_FINI define the default destructor function.
30
31 MIN_NEEDED_FROM minimal number of bytes needed for the from-charset.
32 MIN_NEEDED_TO likewise for the to-charset.
33
34 MAX_NEEDED_FROM maximal number of bytes needed for the from-charset.
35 This macro is optional, it defaults to MIN_NEEDED_FROM.
36 MAX_NEEDED_TO likewise for the to-charset.
37
faaa6f62
UD
38 FROM_LOOP_MIN_NEEDED_FROM
39 FROM_LOOP_MAX_NEEDED_FROM
a784e502
UD
40 minimal/maximal number of bytes needed on input
41 of one round through the FROM_LOOP. Defaults
42 to MIN_NEEDED_FROM and MAX_NEEDED_FROM, respectively.
faaa6f62
UD
43 FROM_LOOP_MIN_NEEDED_TO
44 FROM_LOOP_MAX_NEEDED_TO
a784e502
UD
45 minimal/maximal number of bytes needed on output
46 of one round through the FROM_LOOP. Defaults
47 to MIN_NEEDED_TO and MAX_NEEDED_TO, respectively.
faaa6f62
UD
48 TO_LOOP_MIN_NEEDED_FROM
49 TO_LOOP_MAX_NEEDED_FROM
a784e502
UD
50 minimal/maximal number of bytes needed on input
51 of one round through the TO_LOOP. Defaults
52 to MIN_NEEDED_TO and MAX_NEEDED_TO, respectively.
faaa6f62
UD
53 TO_LOOP_MIN_NEEDED_TO
54 TO_LOOP_MAX_NEEDED_TO
a784e502
UD
55 minimal/maximal number of bytes needed on output
56 of one round through the TO_LOOP. Defaults
57 to MIN_NEEDED_FROM and MAX_NEEDED_FROM, respectively.
faaa6f62 58
8619129f
UD
59 FROM_DIRECTION this macro is supposed to return a value != 0
60 if we convert from the current character set,
61 otherwise it return 0.
62
63 EMIT_SHIFT_TO_INIT this symbol is optional. If it is defined it
64 defines some code which writes out a sequence
faaa6f62 65 of bytes which bring the current state into
8619129f
UD
66 the initial state.
67
68 FROM_LOOP name of the function implementing the conversion
faaa6f62 69 from the current character set.
8619129f
UD
70 TO_LOOP likewise for the other direction
71
f6ad4726
UD
72 ONE_DIRECTION optional. If defined to 1, only one conversion
73 direction is defined instead of two. In this
74 case, FROM_DIRECTION should be defined to 1, and
75 FROM_LOOP and TO_LOOP should have the same value.
76
77 SAVE_RESET_STATE in case of an error we must reset the state for
8619129f
UD
78 the rerun so this macro must be defined for
79 stateful encodings. It takes an argument which
80 is nonzero when saving.
81
82 RESET_INPUT_BUFFER If the input character sets allow this the macro
83 can be defined to reset the input buffer pointers
84 to cover only those characters up to the error.
4802be92
AS
85 Note that if the conversion has skipped over
86 irreversible characters (due to
87 __GCONV_IGNORE_ERRORS) there is no longer a direct
88 correspondence between input and output pointers,
89 and this macro is not called.
8619129f
UD
90
91 FUNCTION_NAME if not set the conversion function is named `gconv'.
28f1c862
UD
92
93 PREPARE_LOOP optional code preparing the conversion loop. Can
94 contain variable definitions.
918b9d72 95 END_LOOP also optional, may be used to store information
28f1c862
UD
96
97 EXTRA_LOOP_ARGS optional macro specifying extra arguments passed
98 to loop function.
faaa6f62 99
f9ad060c
UD
100 STORE_REST optional, needed only when MAX_NEEDED_FROM > 4.
101 This macro stores the seen but unconverted input bytes
102 in the state.
103
104 FROM_ONEBYTE optional. If defined, should be the name of a
105 specialized conversion function for a single byte
106 from the current character set to INTERNAL. This
107 function has prototype
108 wint_t
109 FROM_ONEBYTE (struct __gconv_step *, unsigned char);
110 and does a special conversion:
111 - The input is a single byte.
112 - The output is a single uint32_t.
113 - The state before the conversion is the initial state;
114 the state after the conversion is irrelevant.
115 - No transliteration.
116 - __invocation_counter = 0.
117 - __internal_use = 1.
118 - do_flush = 0.
119
faaa6f62
UD
120 Modules can use mbstate_t to store conversion state as follows:
121
122 * Bits 2..0 of '__count' contain the number of lookahead input bytes
123 stored in __value.__wchb. Always zero if the converter never
124 returns __GCONV_INCOMPLETE_INPUT.
125
126 * Bits 31..3 of '__count' are module dependent shift state.
127
128 * __value: When STORE_REST/UNPACK_BYTES aren't defined and when the
129 converter has returned __GCONV_INCOMPLETE_INPUT, this contains
130 at most 4 lookahead bytes. Converters with an mb_cur_max > 4
131 (currently only UTF-8) must find a way to store their state
132 in __value.__wch and define STORE_REST/UNPACK_BYTES appropriately.
133
134 When __value contains lookahead, __count must not be zero, because
135 the converter is not in the initial state then, and mbsinit() --
136 defined as a (__count == 0) test -- must reflect this.
8619129f
UD
137 */
138
139#include <assert.h>
7ac6fad9 140#include <iconv/gconv_int.h>
8619129f
UD
141#include <string.h>
142#define __need_size_t
143#define __need_NULL
144#include <stddef.h>
c66dbe00
UD
145
146#ifndef STATIC_GCONV
147# include <dlfcn.h>
c66dbe00 148#endif
8619129f 149
88f4b692 150#include <pointer_guard.h>
e054f494 151#include <stdint.h>
915a6c51 152
a808d541
UD
153#ifndef DL_CALL_FCT
154# define DL_CALL_FCT(fct, args) fct args
155#endif
156
8619129f 157/* The direction objects. */
45541bdf 158#if DEFINE_INIT
8619129f 159# ifndef FROM_DIRECTION
45541bdf
UD
160# define FROM_DIRECTION_VAL NULL
161# define TO_DIRECTION_VAL ((void *) ~((uintptr_t) 0))
162# define FROM_DIRECTION (step->__data == FROM_DIRECTION_VAL)
8619129f
UD
163# endif
164#else
165# ifndef FROM_DIRECTION
dbc92dc6 166# error "FROM_DIRECTION must be provided if non-default init is used"
8619129f
UD
167# endif
168#endif
169
8619129f
UD
170/* How many bytes are needed at most for the from-charset. */
171#ifndef MAX_NEEDED_FROM
172# define MAX_NEEDED_FROM MIN_NEEDED_FROM
173#endif
174
175/* Same for the to-charset. */
176#ifndef MAX_NEEDED_TO
177# define MAX_NEEDED_TO MIN_NEEDED_TO
178#endif
179
faaa6f62
UD
180/* Defaults for the per-direction min/max constants. */
181#ifndef FROM_LOOP_MIN_NEEDED_FROM
182# define FROM_LOOP_MIN_NEEDED_FROM MIN_NEEDED_FROM
183#endif
184#ifndef FROM_LOOP_MAX_NEEDED_FROM
185# define FROM_LOOP_MAX_NEEDED_FROM MAX_NEEDED_FROM
186#endif
187#ifndef FROM_LOOP_MIN_NEEDED_TO
188# define FROM_LOOP_MIN_NEEDED_TO MIN_NEEDED_TO
189#endif
190#ifndef FROM_LOOP_MAX_NEEDED_TO
191# define FROM_LOOP_MAX_NEEDED_TO MAX_NEEDED_TO
192#endif
193#ifndef TO_LOOP_MIN_NEEDED_FROM
194# define TO_LOOP_MIN_NEEDED_FROM MIN_NEEDED_TO
195#endif
196#ifndef TO_LOOP_MAX_NEEDED_FROM
197# define TO_LOOP_MAX_NEEDED_FROM MAX_NEEDED_TO
198#endif
199#ifndef TO_LOOP_MIN_NEEDED_TO
200# define TO_LOOP_MIN_NEEDED_TO MIN_NEEDED_FROM
201#endif
202#ifndef TO_LOOP_MAX_NEEDED_TO
203# define TO_LOOP_MAX_NEEDED_TO MAX_NEEDED_FROM
204#endif
205
8619129f 206
f6ad4726
UD
207/* For conversions from a fixed width character set to another fixed width
208 character set we can define RESET_INPUT_BUFFER in a very fast way. */
8619129f 209#if !defined RESET_INPUT_BUFFER && !defined SAVE_RESET_STATE
faaa6f62
UD
210# if FROM_LOOP_MIN_NEEDED_FROM == FROM_LOOP_MAX_NEEDED_FROM \
211 && FROM_LOOP_MIN_NEEDED_TO == FROM_LOOP_MAX_NEEDED_TO \
212 && TO_LOOP_MIN_NEEDED_FROM == TO_LOOP_MAX_NEEDED_FROM \
213 && TO_LOOP_MIN_NEEDED_TO == TO_LOOP_MAX_NEEDED_TO
214/* We have to use these `if's here since the compiler cannot know that
215 (outbuf - outerr) is always divisible by FROM/TO_LOOP_MIN_NEEDED_TO.
216 The ?:1 avoids division by zero warnings that gcc 3.2 emits even for
217 obviously unreachable code. */
218# define RESET_INPUT_BUFFER \
219 if (FROM_DIRECTION) \
220 { \
221 if (FROM_LOOP_MIN_NEEDED_FROM % FROM_LOOP_MIN_NEEDED_TO == 0) \
222 *inptrp -= (outbuf - outerr) \
223 * (FROM_LOOP_MIN_NEEDED_FROM / FROM_LOOP_MIN_NEEDED_TO); \
224 else if (FROM_LOOP_MIN_NEEDED_TO % FROM_LOOP_MIN_NEEDED_FROM == 0) \
225 *inptrp -= (outbuf - outerr) \
226 / (FROM_LOOP_MIN_NEEDED_TO / FROM_LOOP_MIN_NEEDED_FROM \
227 ? : 1); \
228 else \
229 *inptrp -= ((outbuf - outerr) / FROM_LOOP_MIN_NEEDED_TO) \
230 * FROM_LOOP_MIN_NEEDED_FROM; \
231 } \
232 else \
233 { \
234 if (TO_LOOP_MIN_NEEDED_FROM % TO_LOOP_MIN_NEEDED_TO == 0) \
235 *inptrp -= (outbuf - outerr) \
236 * (TO_LOOP_MIN_NEEDED_FROM / TO_LOOP_MIN_NEEDED_TO); \
237 else if (TO_LOOP_MIN_NEEDED_TO % TO_LOOP_MIN_NEEDED_FROM == 0) \
238 *inptrp -= (outbuf - outerr) \
239 / (TO_LOOP_MIN_NEEDED_TO / TO_LOOP_MIN_NEEDED_FROM ? : 1); \
240 else \
241 *inptrp -= ((outbuf - outerr) / TO_LOOP_MIN_NEEDED_TO) \
242 * TO_LOOP_MIN_NEEDED_FROM; \
243 }
8619129f
UD
244# endif
245#endif
246
247
248/* The default init function. It simply matches the name and initializes
249 the step data to point to one of the objects above. */
250#if DEFINE_INIT
251# ifndef CHARSET_NAME
252# error "CHARSET_NAME not defined"
253# endif
254
a1620a4c 255extern int gconv_init (struct __gconv_step *step);
8619129f 256int
d64b6ad0 257gconv_init (struct __gconv_step *step)
8619129f
UD
258{
259 /* Determine which direction. */
d64b6ad0 260 if (strcmp (step->__from_name, CHARSET_NAME) == 0)
918b9d72 261 {
45541bdf 262 step->__data = FROM_DIRECTION_VAL;
390955cb 263
faaa6f62
UD
264 step->__min_needed_from = FROM_LOOP_MIN_NEEDED_FROM;
265 step->__max_needed_from = FROM_LOOP_MAX_NEEDED_FROM;
266 step->__min_needed_to = FROM_LOOP_MIN_NEEDED_TO;
267 step->__max_needed_to = FROM_LOOP_MAX_NEEDED_TO;
f9ad060c
UD
268
269#ifdef FROM_ONEBYTE
270 step->__btowc_fct = FROM_ONEBYTE;
271#endif
918b9d72 272 }
365afefc 273 else if (__builtin_expect (strcmp (step->__to_name, CHARSET_NAME), 0) == 0)
918b9d72 274 {
45541bdf 275 step->__data = TO_DIRECTION_VAL;
390955cb 276
faaa6f62
UD
277 step->__min_needed_from = TO_LOOP_MIN_NEEDED_FROM;
278 step->__max_needed_from = TO_LOOP_MAX_NEEDED_FROM;
279 step->__min_needed_to = TO_LOOP_MIN_NEEDED_TO;
280 step->__max_needed_to = TO_LOOP_MAX_NEEDED_TO;
918b9d72 281 }
390955cb 282 else
d64b6ad0 283 return __GCONV_NOCONV;
8619129f 284
f6ad4726 285#ifdef SAVE_RESET_STATE
d64b6ad0 286 step->__stateful = 1;
9ce5071a 287#else
d64b6ad0 288 step->__stateful = 0;
9ce5071a
UD
289#endif
290
d64b6ad0 291 return __GCONV_OK;
8619129f
UD
292}
293#endif
294
295
296/* The default destructor function does nothing in the moment and so
f6ad4726
UD
297 we don't define it at all. But we still provide the macro just in
298 case we need it some day. */
8619129f
UD
299#if DEFINE_FINI
300#endif
301
302
28f1c862
UD
303/* If no arguments have to passed to the loop function define the macro
304 as empty. */
305#ifndef EXTRA_LOOP_ARGS
306# define EXTRA_LOOP_ARGS
307#endif
308
309
8619129f
UD
310/* This is the actual conversion function. */
311#ifndef FUNCTION_NAME
312# define FUNCTION_NAME gconv
313#endif
314
fd1b5c0f
UD
315/* The macros are used to access the function to convert single characters. */
316#define SINGLE(fct) SINGLE2 (fct)
317#define SINGLE2(fct) fct##_single
318
319
a1620a4c
UD
320extern int FUNCTION_NAME (struct __gconv_step *step,
321 struct __gconv_step_data *data,
322 const unsigned char **inptrp,
323 const unsigned char *inend,
324 unsigned char **outbufstart, size_t *irreversible,
325 int do_flush, int consume_incomplete);
8619129f 326int
d64b6ad0 327FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
fd1b5c0f 328 const unsigned char **inptrp, const unsigned char *inend,
f1d5c60d 329 unsigned char **outbufstart, size_t *irreversible, int do_flush,
55985355 330 int consume_incomplete)
8619129f 331{
d64b6ad0
UD
332 struct __gconv_step *next_step = step + 1;
333 struct __gconv_step_data *next_data = data + 1;
915a6c51 334 __gconv_fct fct = NULL;
8619129f
UD
335 int status;
336
915a6c51
UD
337 if ((data->__flags & __GCONV_IS_LAST) == 0)
338 {
339 fct = next_step->__fct;
915a6c51
UD
340 if (next_step->__shlib_handle != NULL)
341 PTR_DEMANGLE (fct);
915a6c51 342 }
85830c4c 343
8619129f
UD
344 /* If the function is called with no input this means we have to reset
345 to the initial state. The possibly partly converted input is
346 dropped. */
a1ffb40e 347 if (__glibc_unlikely (do_flush))
8619129f 348 {
f1d5c60d
UD
349 /* This should never happen during error handling. */
350 assert (outbufstart == NULL);
351
2373b30e
UD
352 status = __GCONV_OK;
353
390955cb 354#ifdef EMIT_SHIFT_TO_INIT
2373b30e
UD
355 if (do_flush == 1)
356 {
357 /* We preserve the initial values of the pointer variables. */
358 unsigned char *outbuf = data->__outbuf;
359 unsigned char *outstart = outbuf;
360 unsigned char *outend = data->__outbufend;
361
362# ifdef PREPARE_LOOP
363 PREPARE_LOOP
364# endif
365
366# ifdef SAVE_RESET_STATE
367 SAVE_RESET_STATE (1);
368# endif
369
370 /* Emit the escape sequence to reset the state. */
371 EMIT_SHIFT_TO_INIT;
372
373 /* Call the steps down the chain if there are any but only if we
374 successfully emitted the escape sequence. This should only
375 fail if the output buffer is full. If the input is invalid
376 it should be discarded since the user wants to start from a
377 clean state. */
378 if (status == __GCONV_OK)
379 {
380 if (data->__flags & __GCONV_IS_LAST)
381 /* Store information about how many bytes are available. */
382 data->__outbuf = outbuf;
383 else
384 {
385 /* Write out all output which was produced. */
386 if (outbuf > outstart)
387 {
388 const unsigned char *outerr = outstart;
389 int result;
390
391 result = DL_CALL_FCT (fct, (next_step, next_data,
392 &outerr, outbuf, NULL,
393 irreversible, 0,
394 consume_incomplete));
395
396 if (result != __GCONV_EMPTY_INPUT)
397 {
a1ffb40e 398 if (__glibc_unlikely (outerr != outbuf))
2373b30e
UD
399 {
400 /* We have a problem. Undo the conversion. */
401 outbuf = outstart;
402
403 /* Restore the state. */
404# ifdef SAVE_RESET_STATE
405 SAVE_RESET_STATE (0);
406# endif
407 }
408
409 /* Change the status. */
410 status = result;
411 }
412 }
413
414 if (status == __GCONV_OK)
415 /* Now flush the remaining steps. */
416 status = DL_CALL_FCT (fct, (next_step, next_data, NULL,
417 NULL, NULL, irreversible, 1,
418 consume_incomplete));
419 }
420 }
421 }
422 else
8619129f 423#endif
2373b30e
UD
424 {
425 /* Clear the state object. There might be bytes in there from
426 previous calls with CONSUME_INCOMPLETE == 1. But don't emit
427 escape sequences. */
428 memset (data->__statep, '\0', sizeof (*data->__statep));
429
430 if (! (data->__flags & __GCONV_IS_LAST))
431 /* Now flush the remaining steps. */
432 status = DL_CALL_FCT (fct, (next_step, next_data, NULL, NULL,
433 NULL, irreversible, do_flush,
434 consume_incomplete));
435 }
8619129f
UD
436 }
437 else
438 {
ba7b4d29
FW
439 /* We preserve the initial values of the pointer variables,
440 but only some conversion modules need it. */
441 const unsigned char *inptr __attribute__ ((__unused__)) = *inptrp;
f1d5c60d
UD
442 unsigned char *outbuf = (__builtin_expect (outbufstart == NULL, 1)
443 ? data->__outbuf : *outbufstart);
d64b6ad0 444 unsigned char *outend = data->__outbufend;
b117f744 445 unsigned char *outstart;
3aaad0b6
UD
446 /* This variable is used to count the number of characters we
447 actually converted. */
38677ace 448 size_t lirreversible = 0;
b572c2da 449 size_t *lirreversiblep = irreversible ? &lirreversible : NULL;
faaa6f62 450
28f1c862
UD
451#ifdef PREPARE_LOOP
452 PREPARE_LOOP
453#endif
454
faaa6f62 455#if FROM_LOOP_MAX_NEEDED_FROM > 1 || TO_LOOP_MAX_NEEDED_FROM > 1
fd1b5c0f
UD
456 /* If the function is used to implement the mb*towc*() or wc*tomb*()
457 functions we must test whether any bytes from the last call are
458 stored in the `state' object. */
faaa6f62
UD
459 if (((FROM_LOOP_MAX_NEEDED_FROM > 1 && TO_LOOP_MAX_NEEDED_FROM > 1)
460 || (FROM_LOOP_MAX_NEEDED_FROM > 1 && FROM_DIRECTION)
461 || (TO_LOOP_MAX_NEEDED_FROM > 1 && !FROM_DIRECTION))
fd1b5c0f
UD
462 && consume_incomplete && (data->__statep->__count & 7) != 0)
463 {
f1d5c60d 464 /* Yep, we have some bytes left over. Process them now.
a784e502
UD
465 But this must not happen while we are called from an
466 error handler. */
f1d5c60d 467 assert (outbufstart == NULL);
fd1b5c0f 468
faaa6f62
UD
469# if FROM_LOOP_MAX_NEEDED_FROM > 1
470 if (TO_LOOP_MAX_NEEDED_FROM == 1 || FROM_DIRECTION)
55985355 471 status = SINGLE(FROM_LOOP) (step, data, inptrp, inend, &outbuf,
b572c2da 472 outend, lirreversiblep
85830c4c 473 EXTRA_LOOP_ARGS);
fd1b5c0f 474# endif
faaa6f62
UD
475# if !ONE_DIRECTION
476# if FROM_LOOP_MAX_NEEDED_FROM > 1 && TO_LOOP_MAX_NEEDED_FROM > 1
fd1b5c0f 477 else
faaa6f62
UD
478# endif
479# if TO_LOOP_MAX_NEEDED_FROM > 1
55985355 480 status = SINGLE(TO_LOOP) (step, data, inptrp, inend, &outbuf,
b572c2da 481 outend, lirreversiblep EXTRA_LOOP_ARGS);
faaa6f62 482# endif
fd1b5c0f
UD
483# endif
484
365afefc 485 if (__builtin_expect (status, __GCONV_OK) != __GCONV_OK)
fd1b5c0f
UD
486 return status;
487 }
488#endif
489
f1813b56 490 while (1)
8619129f
UD
491 {
492 /* Remember the start value for this round. */
fd1b5c0f 493 inptr = *inptrp;
8619129f 494 /* The outbuf buffer is empty. */
b117f744 495 outstart = outbuf;
4802be92
AS
496#ifdef RESET_INPUT_BUFFER
497 /* Remember how many irreversible characters were skipped before
498 this round. */
499 size_t loop_irreversible
500 = lirreversible + (irreversible ? *irreversible : 0);
501#endif
8619129f 502
8619129f
UD
503#ifdef SAVE_RESET_STATE
504 SAVE_RESET_STATE (1);
505#endif
506
3e20ddad
AZ
507 if (FROM_DIRECTION)
508 /* Run the conversion loop. */
509 status = FROM_LOOP (step, data, inptrp, inend, &outbuf, outend,
510 lirreversiblep EXTRA_LOOP_ARGS);
8619129f 511 else
3e20ddad
AZ
512 /* Run the conversion loop. */
513 status = TO_LOOP (step, data, inptrp, inend, &outbuf, outend,
514 lirreversiblep EXTRA_LOOP_ARGS);
8619129f 515
f1d5c60d
UD
516 /* If we were called as part of an error handling module we
517 don't do anything else here. */
a1ffb40e 518 if (__glibc_unlikely (outbufstart != NULL))
f1d5c60d
UD
519 {
520 *outbufstart = outbuf;
521 return status;
522 }
523
0aece08d
UD
524 /* We finished one use of the loops. */
525 ++data->__invocation_counter;
526
390955cb 527 /* If this is the last step leave the loop, there is nothing
a784e502 528 we can do. */
a1ffb40e 529 if (__glibc_unlikely (data->__flags & __GCONV_IS_LAST))
8619129f
UD
530 {
531 /* Store information about how many bytes are available. */
d64b6ad0 532 data->__outbuf = outbuf;
bf979eef 533
38677ace 534 /* Remember how many non-identical characters we
c0c3f78a 535 converted in an irreversible way. */
38677ace 536 *irreversible += lirreversible;
bf979eef 537
8619129f
UD
538 break;
539 }
540
541 /* Write out all output which was produced. */
a1ffb40e 542 if (__glibc_likely (outbuf > outstart))
8619129f 543 {
d64b6ad0 544 const unsigned char *outerr = data->__outbuf;
8619129f
UD
545 int result;
546
4bae5567 547 result = DL_CALL_FCT (fct, (next_step, next_data, &outerr,
f1d5c60d 548 outbuf, NULL, irreversible, 0,
fd1b5c0f 549 consume_incomplete));
8619129f 550
d64b6ad0 551 if (result != __GCONV_EMPTY_INPUT)
8619129f 552 {
a1ffb40e 553 if (__glibc_unlikely (outerr != outbuf))
8619129f
UD
554 {
555#ifdef RESET_INPUT_BUFFER
4802be92
AS
556 /* RESET_INPUT_BUFFER can only work when there were
557 no new irreversible characters skipped during
558 this round. */
559 if (loop_irreversible
560 == lirreversible + (irreversible ? *irreversible : 0))
561 {
562 RESET_INPUT_BUFFER;
563 goto done_reset;
564 }
565#endif
dbc92dc6
UD
566 /* We have a problem in one of the functions below.
567 Undo the conversion upto the error point. */
ad37480c 568 size_t nstatus __attribute__ ((unused));
8619129f
UD
569
570 /* Reload the pointers. */
fd1b5c0f 571 *inptrp = inptr;
b117f744 572 outbuf = outstart;
8619129f 573
2373b30e 574 /* Restore the state. */
4802be92 575#ifdef SAVE_RESET_STATE
8619129f 576 SAVE_RESET_STATE (0);
4802be92 577#endif
8619129f 578
3e20ddad
AZ
579 if (FROM_DIRECTION)
580 /* Run the conversion loop. */
581 nstatus = FROM_LOOP (step, data, inptrp, inend,
582 &outbuf, outerr,
583 lirreversiblep
584 EXTRA_LOOP_ARGS);
8619129f 585 else
3e20ddad
AZ
586 /* Run the conversion loop. */
587 nstatus = TO_LOOP (step, data, inptrp, inend,
588 &outbuf, outerr,
589 lirreversiblep
590 EXTRA_LOOP_ARGS);
8619129f
UD
591
592 /* We must run out of output buffer space in this
593 rerun. */
5aa8ff62 594 assert (outbuf == outerr);
d64b6ad0 595 assert (nstatus == __GCONV_FULL_OUTPUT);
0aece08d
UD
596
597 /* If we haven't consumed a single byte decrement
598 the invocation counter. */
a1ffb40e 599 if (__glibc_unlikely (outbuf == outstart))
0aece08d 600 --data->__invocation_counter;
8619129f
UD
601 }
602
4802be92
AS
603#ifdef RESET_INPUT_BUFFER
604 done_reset:
605#endif
8619129f
UD
606 /* Change the status. */
607 status = result;
608 }
609 else
610 /* All the output is consumed, we can make another run
611 if everything was ok. */
d64b6ad0 612 if (status == __GCONV_FULL_OUTPUT)
f1813b56
UD
613 {
614 status = __GCONV_OK;
615 outbuf = data->__outbuf;
616 }
8619129f 617 }
f1813b56
UD
618
619 if (status != __GCONV_OK)
620 break;
621
622 /* Reset the output buffer pointer for the next round. */
623 outbuf = data->__outbuf;
8619129f 624 }
8619129f 625
918b9d72
UD
626#ifdef END_LOOP
627 END_LOOP
628#endif
fd1b5c0f
UD
629
630 /* If we are supposed to consume all character store now all of the
631 remaining characters in the `state' object. */
faaa6f62
UD
632#if FROM_LOOP_MAX_NEEDED_FROM > 1 || TO_LOOP_MAX_NEEDED_FROM > 1
633 if (((FROM_LOOP_MAX_NEEDED_FROM > 1 && TO_LOOP_MAX_NEEDED_FROM > 1)
634 || (FROM_LOOP_MAX_NEEDED_FROM > 1 && FROM_DIRECTION)
635 || (TO_LOOP_MAX_NEEDED_FROM > 1 && !FROM_DIRECTION))
365afefc
UD
636 && __builtin_expect (consume_incomplete, 0)
637 && status == __GCONV_INCOMPLETE_INPUT)
fd1b5c0f
UD
638 {
639# ifdef STORE_REST
640 mbstate_t *state = data->__statep;
641
642 STORE_REST
643# else
fd1b5c0f 644 /* Make sure the remaining bytes fit into the state objects
a784e502 645 buffer. */
08538f36
SL
646 size_t cnt_after = inend - *inptrp;
647 assert (cnt_after <= sizeof (data->__statep->__value.__wchb));
fd1b5c0f 648
dbc92dc6 649 size_t cnt;
08538f36
SL
650 for (cnt = 0; cnt < cnt_after; ++cnt)
651 data->__statep->__value.__wchb[cnt] = (*inptrp)[cnt];
652 *inptrp = inend;
fd1b5c0f
UD
653 data->__statep->__count &= ~7;
654 data->__statep->__count |= cnt;
655# endif
656 }
657#endif
faaa6f62
UD
658#undef unaligned
659#undef POSSIBLY_UNALIGNED
8619129f
UD
660 }
661
662 return status;
663}
664
665#undef DEFINE_INIT
666#undef CHARSET_NAME
667#undef DEFINE_FINI
668#undef MIN_NEEDED_FROM
669#undef MIN_NEEDED_TO
670#undef MAX_NEEDED_FROM
671#undef MAX_NEEDED_TO
faaa6f62
UD
672#undef FROM_LOOP_MIN_NEEDED_FROM
673#undef FROM_LOOP_MAX_NEEDED_FROM
674#undef FROM_LOOP_MIN_NEEDED_TO
675#undef FROM_LOOP_MAX_NEEDED_TO
676#undef TO_LOOP_MIN_NEEDED_FROM
677#undef TO_LOOP_MAX_NEEDED_FROM
678#undef TO_LOOP_MIN_NEEDED_TO
679#undef TO_LOOP_MAX_NEEDED_TO
8619129f
UD
680#undef FROM_DIRECTION
681#undef EMIT_SHIFT_TO_INIT
682#undef FROM_LOOP
683#undef TO_LOOP
f9ad060c 684#undef ONE_DIRECTION
f6ad4726 685#undef SAVE_RESET_STATE
8619129f
UD
686#undef RESET_INPUT_BUFFER
687#undef FUNCTION_NAME
918b9d72
UD
688#undef PREPARE_LOOP
689#undef END_LOOP
f9ad060c 690#undef EXTRA_LOOP_ARGS
fd1b5c0f 691#undef STORE_REST
f9ad060c 692#undef FROM_ONEBYTE
This page took 0.663576 seconds and 6 git commands to generate.