|  | /* Skeleton for a conversion module. | 
|  | Copyright (C) 1998-2016 Free Software Foundation, Inc. | 
|  | This file is part of the GNU C Library. | 
|  | Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. | 
|  |  | 
|  | The GNU C Library is free software; you can redistribute it and/or | 
|  | modify it under the terms of the GNU Lesser General Public | 
|  | License as published by the Free Software Foundation; either | 
|  | version 2.1 of the License, or (at your option) any later version. | 
|  |  | 
|  | The GNU C Library is distributed in the hope that it will be useful, | 
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | Lesser General Public License for more details. | 
|  |  | 
|  | You should have received a copy of the GNU Lesser General Public | 
|  | License along with the GNU C Library; if not, see | 
|  | <http://www.gnu.org/licenses/>.  */ | 
|  |  | 
|  | /* This file can be included to provide definitions of several things | 
|  | many modules have in common.  It can be customized using the following | 
|  | macros: | 
|  |  | 
|  | DEFINE_INIT	define the default initializer.  This requires the | 
|  | following symbol to be defined. | 
|  |  | 
|  | CHARSET_NAME	string with official name of the coded character | 
|  | set (in all-caps) | 
|  |  | 
|  | DEFINE_FINI	define the default destructor function. | 
|  |  | 
|  | MIN_NEEDED_FROM	minimal number of bytes needed for the from-charset. | 
|  | MIN_NEEDED_TO	likewise for the to-charset. | 
|  |  | 
|  | MAX_NEEDED_FROM	maximal number of bytes needed for the from-charset. | 
|  | This macro is optional, it defaults to MIN_NEEDED_FROM. | 
|  | MAX_NEEDED_TO	likewise for the to-charset. | 
|  |  | 
|  | FROM_LOOP_MIN_NEEDED_FROM | 
|  | FROM_LOOP_MAX_NEEDED_FROM | 
|  | minimal/maximal number of bytes needed on input | 
|  | of one round through the FROM_LOOP.  Defaults | 
|  | to MIN_NEEDED_FROM and MAX_NEEDED_FROM, respectively. | 
|  | FROM_LOOP_MIN_NEEDED_TO | 
|  | FROM_LOOP_MAX_NEEDED_TO | 
|  | minimal/maximal number of bytes needed on output | 
|  | of one round through the FROM_LOOP.  Defaults | 
|  | to MIN_NEEDED_TO and MAX_NEEDED_TO, respectively. | 
|  | TO_LOOP_MIN_NEEDED_FROM | 
|  | TO_LOOP_MAX_NEEDED_FROM | 
|  | minimal/maximal number of bytes needed on input | 
|  | of one round through the TO_LOOP.  Defaults | 
|  | to MIN_NEEDED_TO and MAX_NEEDED_TO, respectively. | 
|  | TO_LOOP_MIN_NEEDED_TO | 
|  | TO_LOOP_MAX_NEEDED_TO | 
|  | minimal/maximal number of bytes needed on output | 
|  | of one round through the TO_LOOP.  Defaults | 
|  | to MIN_NEEDED_FROM and MAX_NEEDED_FROM, respectively. | 
|  |  | 
|  | FROM_DIRECTION	this macro is supposed to return a value != 0 | 
|  | if we convert from the current character set, | 
|  | otherwise it return 0. | 
|  |  | 
|  | EMIT_SHIFT_TO_INIT	this symbol is optional.  If it is defined it | 
|  | defines some code which writes out a sequence | 
|  | of bytes which bring the current state into | 
|  | the initial state. | 
|  |  | 
|  | FROM_LOOP		name of the function implementing the conversion | 
|  | from the current character set. | 
|  | TO_LOOP		likewise for the other direction | 
|  |  | 
|  | ONE_DIRECTION	optional.  If defined to 1, only one conversion | 
|  | direction is defined instead of two.  In this | 
|  | case, FROM_DIRECTION should be defined to 1, and | 
|  | FROM_LOOP and TO_LOOP should have the same value. | 
|  |  | 
|  | SAVE_RESET_STATE	in case of an error we must reset the state for | 
|  | the rerun so this macro must be defined for | 
|  | stateful encodings.  It takes an argument which | 
|  | is nonzero when saving. | 
|  |  | 
|  | RESET_INPUT_BUFFER	If the input character sets allow this the macro | 
|  | can be defined to reset the input buffer pointers | 
|  | to cover only those characters up to the error. | 
|  |  | 
|  | FUNCTION_NAME	if not set the conversion function is named `gconv'. | 
|  |  | 
|  | PREPARE_LOOP	optional code preparing the conversion loop.  Can | 
|  | contain variable definitions. | 
|  | END_LOOP		also optional, may be used to store information | 
|  |  | 
|  | EXTRA_LOOP_ARGS	optional macro specifying extra arguments passed | 
|  | to loop function. | 
|  |  | 
|  | STORE_REST		optional, needed only when MAX_NEEDED_FROM > 4. | 
|  | This macro stores the seen but unconverted input bytes | 
|  | in the state. | 
|  |  | 
|  | FROM_ONEBYTE	optional.  If defined, should be the name of a | 
|  | specialized conversion function for a single byte | 
|  | from the current character set to INTERNAL.  This | 
|  | function has prototype | 
|  | wint_t | 
|  | FROM_ONEBYTE (struct __gconv_step *, unsigned char); | 
|  | and does a special conversion: | 
|  | - The input is a single byte. | 
|  | - The output is a single uint32_t. | 
|  | - The state before the conversion is the initial state; | 
|  | the state after the conversion is irrelevant. | 
|  | - No transliteration. | 
|  | - __invocation_counter = 0. | 
|  | - __internal_use = 1. | 
|  | - do_flush = 0. | 
|  |  | 
|  | Modules can use mbstate_t to store conversion state as follows: | 
|  |  | 
|  | * Bits 2..0 of '__count' contain the number of lookahead input bytes | 
|  | stored in __value.__wchb.  Always zero if the converter never | 
|  | returns __GCONV_INCOMPLETE_INPUT. | 
|  |  | 
|  | * Bits 31..3 of '__count' are module dependent shift state. | 
|  |  | 
|  | * __value: When STORE_REST/UNPACK_BYTES aren't defined and when the | 
|  | converter has returned __GCONV_INCOMPLETE_INPUT, this contains | 
|  | at most 4 lookahead bytes. Converters with an mb_cur_max > 4 | 
|  | (currently only UTF-8) must find a way to store their state | 
|  | in __value.__wch and define STORE_REST/UNPACK_BYTES appropriately. | 
|  |  | 
|  | When __value contains lookahead, __count must not be zero, because | 
|  | the converter is not in the initial state then, and mbsinit() -- | 
|  | defined as a (__count == 0) test -- must reflect this. | 
|  | */ | 
|  |  | 
|  | #include <assert.h> | 
|  | #include <gconv.h> | 
|  | #include <string.h> | 
|  | #define __need_size_t | 
|  | #define __need_NULL | 
|  | #include <stddef.h> | 
|  |  | 
|  | #ifndef STATIC_GCONV | 
|  | # include <dlfcn.h> | 
|  | #endif | 
|  |  | 
|  | #include <sysdep.h> | 
|  | #include <stdint.h> | 
|  |  | 
|  | #ifndef DL_CALL_FCT | 
|  | # define DL_CALL_FCT(fct, args) fct args | 
|  | #endif | 
|  |  | 
|  | /* The direction objects.  */ | 
|  | #if DEFINE_INIT | 
|  | # ifndef FROM_DIRECTION | 
|  | #  define FROM_DIRECTION_VAL NULL | 
|  | #  define TO_DIRECTION_VAL ((void *) ~((uintptr_t) 0)) | 
|  | #  define FROM_DIRECTION (step->__data == FROM_DIRECTION_VAL) | 
|  | # endif | 
|  | #else | 
|  | # ifndef FROM_DIRECTION | 
|  | #  error "FROM_DIRECTION must be provided if non-default init is used" | 
|  | # endif | 
|  | #endif | 
|  |  | 
|  | /* How many bytes are needed at most for the from-charset.  */ | 
|  | #ifndef MAX_NEEDED_FROM | 
|  | # define MAX_NEEDED_FROM	MIN_NEEDED_FROM | 
|  | #endif | 
|  |  | 
|  | /* Same for the to-charset.  */ | 
|  | #ifndef MAX_NEEDED_TO | 
|  | # define MAX_NEEDED_TO		MIN_NEEDED_TO | 
|  | #endif | 
|  |  | 
|  | /* Defaults for the per-direction min/max constants.  */ | 
|  | #ifndef FROM_LOOP_MIN_NEEDED_FROM | 
|  | # define FROM_LOOP_MIN_NEEDED_FROM	MIN_NEEDED_FROM | 
|  | #endif | 
|  | #ifndef FROM_LOOP_MAX_NEEDED_FROM | 
|  | # define FROM_LOOP_MAX_NEEDED_FROM	MAX_NEEDED_FROM | 
|  | #endif | 
|  | #ifndef FROM_LOOP_MIN_NEEDED_TO | 
|  | # define FROM_LOOP_MIN_NEEDED_TO	MIN_NEEDED_TO | 
|  | #endif | 
|  | #ifndef FROM_LOOP_MAX_NEEDED_TO | 
|  | # define FROM_LOOP_MAX_NEEDED_TO	MAX_NEEDED_TO | 
|  | #endif | 
|  | #ifndef TO_LOOP_MIN_NEEDED_FROM | 
|  | # define TO_LOOP_MIN_NEEDED_FROM	MIN_NEEDED_TO | 
|  | #endif | 
|  | #ifndef TO_LOOP_MAX_NEEDED_FROM | 
|  | # define TO_LOOP_MAX_NEEDED_FROM	MAX_NEEDED_TO | 
|  | #endif | 
|  | #ifndef TO_LOOP_MIN_NEEDED_TO | 
|  | # define TO_LOOP_MIN_NEEDED_TO		MIN_NEEDED_FROM | 
|  | #endif | 
|  | #ifndef TO_LOOP_MAX_NEEDED_TO | 
|  | # define TO_LOOP_MAX_NEEDED_TO		MAX_NEEDED_FROM | 
|  | #endif | 
|  |  | 
|  |  | 
|  | /* Define macros which can access unaligned buffers.  These macros are | 
|  | supposed to be used only in code outside the inner loops.  For the inner | 
|  | loops we have other definitions which allow optimized access.  */ | 
|  | #if _STRING_ARCH_unaligned | 
|  | /* We can handle unaligned memory access.  */ | 
|  | # define get16u(addr) *((const uint16_t *) (addr)) | 
|  | # define get32u(addr) *((const uint32_t *) (addr)) | 
|  |  | 
|  | /* We need no special support for writing values either.  */ | 
|  | # define put16u(addr, val) *((uint16_t *) (addr)) = (val) | 
|  | # define put32u(addr, val) *((uint32_t *) (addr)) = (val) | 
|  | #else | 
|  | /* Distinguish between big endian and little endian.  */ | 
|  | # if __BYTE_ORDER == __LITTLE_ENDIAN | 
|  | #  define get16u(addr) \ | 
|  | (((const unsigned char *) (addr))[1] << 8				      \ | 
|  | | ((const unsigned char *) (addr))[0]) | 
|  | #  define get32u(addr) \ | 
|  | (((((const unsigned char *) (addr))[3] << 8			      \ | 
|  | | ((const unsigned char *) (addr))[2]) << 8			      \ | 
|  | | ((const unsigned char *) (addr))[1]) << 8			      \ | 
|  | | ((const unsigned char *) (addr))[0]) | 
|  |  | 
|  | #  define put16u(addr, val) \ | 
|  | ({ uint16_t __val = (val);						      \ | 
|  | ((unsigned char *) (addr))[0] = __val;				      \ | 
|  | ((unsigned char *) (addr))[1] = __val >> 8;			      \ | 
|  | (void) 0; }) | 
|  | #  define put32u(addr, val) \ | 
|  | ({ uint32_t __val = (val);						      \ | 
|  | ((unsigned char *) (addr))[0] = __val;				      \ | 
|  | __val >>= 8;							      \ | 
|  | ((unsigned char *) (addr))[1] = __val;				      \ | 
|  | __val >>= 8;							      \ | 
|  | ((unsigned char *) (addr))[2] = __val;				      \ | 
|  | __val >>= 8;							      \ | 
|  | ((unsigned char *) (addr))[3] = __val;				      \ | 
|  | (void) 0; }) | 
|  | # else | 
|  | #  define get16u(addr) \ | 
|  | (((const unsigned char *) (addr))[0] << 8				      \ | 
|  | | ((const unsigned char *) (addr))[1]) | 
|  | #  define get32u(addr) \ | 
|  | (((((const unsigned char *) (addr))[0] << 8			      \ | 
|  | | ((const unsigned char *) (addr))[1]) << 8			      \ | 
|  | | ((const unsigned char *) (addr))[2]) << 8			      \ | 
|  | | ((const unsigned char *) (addr))[3]) | 
|  |  | 
|  | #  define put16u(addr, val) \ | 
|  | ({ uint16_t __val = (val);						      \ | 
|  | ((unsigned char *) (addr))[1] = __val;				      \ | 
|  | ((unsigned char *) (addr))[0] = __val >> 8;			      \ | 
|  | (void) 0; }) | 
|  | #  define put32u(addr, val) \ | 
|  | ({ uint32_t __val = (val);						      \ | 
|  | ((unsigned char *) (addr))[3] = __val;				      \ | 
|  | __val >>= 8;							      \ | 
|  | ((unsigned char *) (addr))[2] = __val;				      \ | 
|  | __val >>= 8;							      \ | 
|  | ((unsigned char *) (addr))[1] = __val;				      \ | 
|  | __val >>= 8;							      \ | 
|  | ((unsigned char *) (addr))[0] = __val;				      \ | 
|  | (void) 0; }) | 
|  | # endif | 
|  | #endif | 
|  |  | 
|  |  | 
|  | /* For conversions from a fixed width character set to another fixed width | 
|  | character set we can define RESET_INPUT_BUFFER in a very fast way.  */ | 
|  | #if !defined RESET_INPUT_BUFFER && !defined SAVE_RESET_STATE | 
|  | # if FROM_LOOP_MIN_NEEDED_FROM == FROM_LOOP_MAX_NEEDED_FROM \ | 
|  | && FROM_LOOP_MIN_NEEDED_TO == FROM_LOOP_MAX_NEEDED_TO \ | 
|  | && TO_LOOP_MIN_NEEDED_FROM == TO_LOOP_MAX_NEEDED_FROM \ | 
|  | && TO_LOOP_MIN_NEEDED_TO == TO_LOOP_MAX_NEEDED_TO | 
|  | /* We have to use these `if's here since the compiler cannot know that | 
|  | (outbuf - outerr) is always divisible by FROM/TO_LOOP_MIN_NEEDED_TO. | 
|  | The ?:1 avoids division by zero warnings that gcc 3.2 emits even for | 
|  | obviously unreachable code.  */ | 
|  | #  define RESET_INPUT_BUFFER \ | 
|  | if (FROM_DIRECTION)							      \ | 
|  | {									      \ | 
|  | if (FROM_LOOP_MIN_NEEDED_FROM % FROM_LOOP_MIN_NEEDED_TO == 0)	      \ | 
|  | *inptrp -= (outbuf - outerr)					      \ | 
|  | * (FROM_LOOP_MIN_NEEDED_FROM / FROM_LOOP_MIN_NEEDED_TO);   \ | 
|  | else if (FROM_LOOP_MIN_NEEDED_TO % FROM_LOOP_MIN_NEEDED_FROM == 0)      \ | 
|  | *inptrp -= (outbuf - outerr)					      \ | 
|  | / (FROM_LOOP_MIN_NEEDED_TO / FROM_LOOP_MIN_NEEDED_FROM     \ | 
|  | ? : 1);						      \ | 
|  | else								      \ | 
|  | *inptrp -= ((outbuf - outerr) / FROM_LOOP_MIN_NEEDED_TO)	      \ | 
|  | * FROM_LOOP_MIN_NEEDED_FROM;				      \ | 
|  | }									      \ | 
|  | else									      \ | 
|  | {									      \ | 
|  | if (TO_LOOP_MIN_NEEDED_FROM % TO_LOOP_MIN_NEEDED_TO == 0)		      \ | 
|  | *inptrp -= (outbuf - outerr)					      \ | 
|  | * (TO_LOOP_MIN_NEEDED_FROM / TO_LOOP_MIN_NEEDED_TO);	      \ | 
|  | else if (TO_LOOP_MIN_NEEDED_TO % TO_LOOP_MIN_NEEDED_FROM == 0)	      \ | 
|  | *inptrp -= (outbuf - outerr)					      \ | 
|  | / (TO_LOOP_MIN_NEEDED_TO / TO_LOOP_MIN_NEEDED_FROM ? : 1); \ | 
|  | else								      \ | 
|  | *inptrp -= ((outbuf - outerr) / TO_LOOP_MIN_NEEDED_TO)		      \ | 
|  | * TO_LOOP_MIN_NEEDED_FROM;				      \ | 
|  | } | 
|  | # endif | 
|  | #endif | 
|  |  | 
|  |  | 
|  | /* The default init function.  It simply matches the name and initializes | 
|  | the step data to point to one of the objects above.  */ | 
|  | #if DEFINE_INIT | 
|  | # ifndef CHARSET_NAME | 
|  | #  error "CHARSET_NAME not defined" | 
|  | # endif | 
|  |  | 
|  | extern int gconv_init (struct __gconv_step *step); | 
|  | int | 
|  | gconv_init (struct __gconv_step *step) | 
|  | { | 
|  | /* Determine which direction.  */ | 
|  | if (strcmp (step->__from_name, CHARSET_NAME) == 0) | 
|  | { | 
|  | step->__data = FROM_DIRECTION_VAL; | 
|  |  | 
|  | step->__min_needed_from = FROM_LOOP_MIN_NEEDED_FROM; | 
|  | step->__max_needed_from = FROM_LOOP_MAX_NEEDED_FROM; | 
|  | step->__min_needed_to = FROM_LOOP_MIN_NEEDED_TO; | 
|  | step->__max_needed_to = FROM_LOOP_MAX_NEEDED_TO; | 
|  |  | 
|  | #ifdef FROM_ONEBYTE | 
|  | step->__btowc_fct = FROM_ONEBYTE; | 
|  | #endif | 
|  | } | 
|  | else if (__builtin_expect (strcmp (step->__to_name, CHARSET_NAME), 0) == 0) | 
|  | { | 
|  | step->__data = TO_DIRECTION_VAL; | 
|  |  | 
|  | step->__min_needed_from = TO_LOOP_MIN_NEEDED_FROM; | 
|  | step->__max_needed_from = TO_LOOP_MAX_NEEDED_FROM; | 
|  | step->__min_needed_to = TO_LOOP_MIN_NEEDED_TO; | 
|  | step->__max_needed_to = TO_LOOP_MAX_NEEDED_TO; | 
|  | } | 
|  | else | 
|  | return __GCONV_NOCONV; | 
|  |  | 
|  | #ifdef SAVE_RESET_STATE | 
|  | step->__stateful = 1; | 
|  | #else | 
|  | step->__stateful = 0; | 
|  | #endif | 
|  |  | 
|  | return __GCONV_OK; | 
|  | } | 
|  | #endif | 
|  |  | 
|  |  | 
|  | /* The default destructor function does nothing in the moment and so | 
|  | we don't define it at all.  But we still provide the macro just in | 
|  | case we need it some day.  */ | 
|  | #if DEFINE_FINI | 
|  | #endif | 
|  |  | 
|  |  | 
|  | /* If no arguments have to passed to the loop function define the macro | 
|  | as empty.  */ | 
|  | #ifndef EXTRA_LOOP_ARGS | 
|  | # define EXTRA_LOOP_ARGS | 
|  | #endif | 
|  |  | 
|  |  | 
|  | /* This is the actual conversion function.  */ | 
|  | #ifndef FUNCTION_NAME | 
|  | # define FUNCTION_NAME	gconv | 
|  | #endif | 
|  |  | 
|  | /* The macros are used to access the function to convert single characters.  */ | 
|  | #define SINGLE(fct) SINGLE2 (fct) | 
|  | #define SINGLE2(fct) fct##_single | 
|  |  | 
|  |  | 
|  | extern int FUNCTION_NAME (struct __gconv_step *step, | 
|  | struct __gconv_step_data *data, | 
|  | const unsigned char **inptrp, | 
|  | const unsigned char *inend, | 
|  | unsigned char **outbufstart, size_t *irreversible, | 
|  | int do_flush, int consume_incomplete); | 
|  | int | 
|  | FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data, | 
|  | const unsigned char **inptrp, const unsigned char *inend, | 
|  | unsigned char **outbufstart, size_t *irreversible, int do_flush, | 
|  | int consume_incomplete) | 
|  | { | 
|  | struct __gconv_step *next_step = step + 1; | 
|  | struct __gconv_step_data *next_data = data + 1; | 
|  | __gconv_fct fct = NULL; | 
|  | int status; | 
|  |  | 
|  | if ((data->__flags & __GCONV_IS_LAST) == 0) | 
|  | { | 
|  | fct = next_step->__fct; | 
|  | #ifdef PTR_DEMANGLE | 
|  | if (next_step->__shlib_handle != NULL) | 
|  | PTR_DEMANGLE (fct); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | /* If the function is called with no input this means we have to reset | 
|  | to the initial state.  The possibly partly converted input is | 
|  | dropped.  */ | 
|  | if (__glibc_unlikely (do_flush)) | 
|  | { | 
|  | /* This should never happen during error handling.  */ | 
|  | assert (outbufstart == NULL); | 
|  |  | 
|  | status = __GCONV_OK; | 
|  |  | 
|  | #ifdef EMIT_SHIFT_TO_INIT | 
|  | if (do_flush == 1) | 
|  | { | 
|  | /* We preserve the initial values of the pointer variables.  */ | 
|  | unsigned char *outbuf = data->__outbuf; | 
|  | unsigned char *outstart = outbuf; | 
|  | unsigned char *outend = data->__outbufend; | 
|  |  | 
|  | # ifdef PREPARE_LOOP | 
|  | PREPARE_LOOP | 
|  | # endif | 
|  |  | 
|  | # ifdef SAVE_RESET_STATE | 
|  | SAVE_RESET_STATE (1); | 
|  | # endif | 
|  |  | 
|  | /* Emit the escape sequence to reset the state.  */ | 
|  | EMIT_SHIFT_TO_INIT; | 
|  |  | 
|  | /* Call the steps down the chain if there are any but only if we | 
|  | successfully emitted the escape sequence.  This should only | 
|  | fail if the output buffer is full.  If the input is invalid | 
|  | it should be discarded since the user wants to start from a | 
|  | clean state.  */ | 
|  | if (status == __GCONV_OK) | 
|  | { | 
|  | if (data->__flags & __GCONV_IS_LAST) | 
|  | /* Store information about how many bytes are available.  */ | 
|  | data->__outbuf = outbuf; | 
|  | else | 
|  | { | 
|  | /* Write out all output which was produced.  */ | 
|  | if (outbuf > outstart) | 
|  | { | 
|  | const unsigned char *outerr = outstart; | 
|  | int result; | 
|  |  | 
|  | result = DL_CALL_FCT (fct, (next_step, next_data, | 
|  | &outerr, outbuf, NULL, | 
|  | irreversible, 0, | 
|  | consume_incomplete)); | 
|  |  | 
|  | if (result != __GCONV_EMPTY_INPUT) | 
|  | { | 
|  | if (__glibc_unlikely (outerr != outbuf)) | 
|  | { | 
|  | /* We have a problem.  Undo the conversion.  */ | 
|  | outbuf = outstart; | 
|  |  | 
|  | /* Restore the state.  */ | 
|  | # ifdef SAVE_RESET_STATE | 
|  | SAVE_RESET_STATE (0); | 
|  | # endif | 
|  | } | 
|  |  | 
|  | /* Change the status.  */ | 
|  | status = result; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (status == __GCONV_OK) | 
|  | /* Now flush the remaining steps.  */ | 
|  | status = DL_CALL_FCT (fct, (next_step, next_data, NULL, | 
|  | NULL, NULL, irreversible, 1, | 
|  | consume_incomplete)); | 
|  | } | 
|  | } | 
|  | } | 
|  | else | 
|  | #endif | 
|  | { | 
|  | /* Clear the state object.  There might be bytes in there from | 
|  | previous calls with CONSUME_INCOMPLETE == 1.  But don't emit | 
|  | escape sequences.  */ | 
|  | memset (data->__statep, '\0', sizeof (*data->__statep)); | 
|  |  | 
|  | if (! (data->__flags & __GCONV_IS_LAST)) | 
|  | /* Now flush the remaining steps.  */ | 
|  | status = DL_CALL_FCT (fct, (next_step, next_data, NULL, NULL, | 
|  | NULL, irreversible, do_flush, | 
|  | consume_incomplete)); | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | /* We preserve the initial values of the pointer variables, | 
|  | but only some conversion modules need it.  */ | 
|  | const unsigned char *inptr __attribute__ ((__unused__)) = *inptrp; | 
|  | unsigned char *outbuf = (__builtin_expect (outbufstart == NULL, 1) | 
|  | ? data->__outbuf : *outbufstart); | 
|  | unsigned char *outend = data->__outbufend; | 
|  | unsigned char *outstart; | 
|  | /* This variable is used to count the number of characters we | 
|  | actually converted.  */ | 
|  | size_t lirreversible = 0; | 
|  | size_t *lirreversiblep = irreversible ? &lirreversible : NULL; | 
|  |  | 
|  | /* The following assumes that encodings, which have a variable length | 
|  | what might unalign a buffer even though it is an aligned in the | 
|  | beginning, either don't have the minimal number of bytes as a divisor | 
|  | of the maximum length or have a minimum length of 1.  This is true | 
|  | for all known and supported encodings. | 
|  | We use && instead of || to combine the subexpression for the FROM | 
|  | encoding and for the TO encoding, because usually one of them is | 
|  | INTERNAL, for which the subexpression evaluates to 1, but INTERNAL | 
|  | buffers are always aligned correctly.  */ | 
|  | #define POSSIBLY_UNALIGNED \ | 
|  | (!_STRING_ARCH_unaligned					              \ | 
|  | && (((FROM_LOOP_MIN_NEEDED_FROM != 1					      \ | 
|  | && FROM_LOOP_MAX_NEEDED_FROM % FROM_LOOP_MIN_NEEDED_FROM == 0)	      \ | 
|  | && (FROM_LOOP_MIN_NEEDED_TO != 1				      \ | 
|  | && FROM_LOOP_MAX_NEEDED_TO % FROM_LOOP_MIN_NEEDED_TO == 0))	      \ | 
|  | || ((TO_LOOP_MIN_NEEDED_FROM != 1				      \ | 
|  | && TO_LOOP_MAX_NEEDED_FROM % TO_LOOP_MIN_NEEDED_FROM == 0)	      \ | 
|  | && (TO_LOOP_MIN_NEEDED_TO != 1				      \ | 
|  | && TO_LOOP_MAX_NEEDED_TO % TO_LOOP_MIN_NEEDED_TO == 0)))) | 
|  | #if POSSIBLY_UNALIGNED | 
|  | int unaligned; | 
|  | # define GEN_unaligned(name) GEN_unaligned2 (name) | 
|  | # define GEN_unaligned2(name) name##_unaligned | 
|  | #else | 
|  | # define unaligned 0 | 
|  | #endif | 
|  |  | 
|  | #ifdef PREPARE_LOOP | 
|  | PREPARE_LOOP | 
|  | #endif | 
|  |  | 
|  | #if FROM_LOOP_MAX_NEEDED_FROM > 1 || TO_LOOP_MAX_NEEDED_FROM > 1 | 
|  | /* If the function is used to implement the mb*towc*() or wc*tomb*() | 
|  | functions we must test whether any bytes from the last call are | 
|  | stored in the `state' object.  */ | 
|  | if (((FROM_LOOP_MAX_NEEDED_FROM > 1 && TO_LOOP_MAX_NEEDED_FROM > 1) | 
|  | || (FROM_LOOP_MAX_NEEDED_FROM > 1 && FROM_DIRECTION) | 
|  | || (TO_LOOP_MAX_NEEDED_FROM > 1 && !FROM_DIRECTION)) | 
|  | && consume_incomplete && (data->__statep->__count & 7) != 0) | 
|  | { | 
|  | /* Yep, we have some bytes left over.  Process them now. | 
|  | But this must not happen while we are called from an | 
|  | error handler.  */ | 
|  | assert (outbufstart == NULL); | 
|  |  | 
|  | # if FROM_LOOP_MAX_NEEDED_FROM > 1 | 
|  | if (TO_LOOP_MAX_NEEDED_FROM == 1 || FROM_DIRECTION) | 
|  | status = SINGLE(FROM_LOOP) (step, data, inptrp, inend, &outbuf, | 
|  | outend, lirreversiblep | 
|  | EXTRA_LOOP_ARGS); | 
|  | # endif | 
|  | # if !ONE_DIRECTION | 
|  | #  if FROM_LOOP_MAX_NEEDED_FROM > 1 && TO_LOOP_MAX_NEEDED_FROM > 1 | 
|  | else | 
|  | #  endif | 
|  | #  if TO_LOOP_MAX_NEEDED_FROM > 1 | 
|  | status = SINGLE(TO_LOOP) (step, data, inptrp, inend, &outbuf, | 
|  | outend, lirreversiblep EXTRA_LOOP_ARGS); | 
|  | #  endif | 
|  | # endif | 
|  |  | 
|  | if (__builtin_expect (status, __GCONV_OK) != __GCONV_OK) | 
|  | return status; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #if POSSIBLY_UNALIGNED | 
|  | unaligned = | 
|  | ((FROM_DIRECTION | 
|  | && ((uintptr_t) inptr % FROM_LOOP_MIN_NEEDED_FROM != 0 | 
|  | || ((data->__flags & __GCONV_IS_LAST) | 
|  | && (uintptr_t) outbuf % FROM_LOOP_MIN_NEEDED_TO != 0))) | 
|  | || (!FROM_DIRECTION | 
|  | && (((data->__flags & __GCONV_IS_LAST) | 
|  | && (uintptr_t) outbuf % TO_LOOP_MIN_NEEDED_TO != 0) | 
|  | || (uintptr_t) inptr % TO_LOOP_MIN_NEEDED_FROM != 0))); | 
|  | #endif | 
|  |  | 
|  | while (1) | 
|  | { | 
|  | /* Remember the start value for this round.  */ | 
|  | inptr = *inptrp; | 
|  | /* The outbuf buffer is empty.  */ | 
|  | outstart = outbuf; | 
|  |  | 
|  | #ifdef SAVE_RESET_STATE | 
|  | SAVE_RESET_STATE (1); | 
|  | #endif | 
|  |  | 
|  | if (__glibc_likely (!unaligned)) | 
|  | { | 
|  | if (FROM_DIRECTION) | 
|  | /* Run the conversion loop.  */ | 
|  | status = FROM_LOOP (step, data, inptrp, inend, &outbuf, outend, | 
|  | lirreversiblep EXTRA_LOOP_ARGS); | 
|  | else | 
|  | /* Run the conversion loop.  */ | 
|  | status = TO_LOOP (step, data, inptrp, inend, &outbuf, outend, | 
|  | lirreversiblep EXTRA_LOOP_ARGS); | 
|  | } | 
|  | #if POSSIBLY_UNALIGNED | 
|  | else | 
|  | { | 
|  | if (FROM_DIRECTION) | 
|  | /* Run the conversion loop.  */ | 
|  | status = GEN_unaligned (FROM_LOOP) (step, data, inptrp, inend, | 
|  | &outbuf, outend, | 
|  | lirreversiblep | 
|  | EXTRA_LOOP_ARGS); | 
|  | else | 
|  | /* Run the conversion loop.  */ | 
|  | status = GEN_unaligned (TO_LOOP) (step, data, inptrp, inend, | 
|  | &outbuf, outend, | 
|  | lirreversiblep | 
|  | EXTRA_LOOP_ARGS); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | /* If we were called as part of an error handling module we | 
|  | don't do anything else here.  */ | 
|  | if (__glibc_unlikely (outbufstart != NULL)) | 
|  | { | 
|  | *outbufstart = outbuf; | 
|  | return status; | 
|  | } | 
|  |  | 
|  | /* We finished one use of the loops.  */ | 
|  | ++data->__invocation_counter; | 
|  |  | 
|  | /* If this is the last step leave the loop, there is nothing | 
|  | we can do.  */ | 
|  | if (__glibc_unlikely (data->__flags & __GCONV_IS_LAST)) | 
|  | { | 
|  | /* Store information about how many bytes are available.  */ | 
|  | data->__outbuf = outbuf; | 
|  |  | 
|  | /* Remember how many non-identical characters we | 
|  | converted in an irreversible way.  */ | 
|  | *irreversible += lirreversible; | 
|  |  | 
|  | break; | 
|  | } | 
|  |  | 
|  | /* Write out all output which was produced.  */ | 
|  | if (__glibc_likely (outbuf > outstart)) | 
|  | { | 
|  | const unsigned char *outerr = data->__outbuf; | 
|  | int result; | 
|  |  | 
|  | result = DL_CALL_FCT (fct, (next_step, next_data, &outerr, | 
|  | outbuf, NULL, irreversible, 0, | 
|  | consume_incomplete)); | 
|  |  | 
|  | if (result != __GCONV_EMPTY_INPUT) | 
|  | { | 
|  | if (__glibc_unlikely (outerr != outbuf)) | 
|  | { | 
|  | #ifdef RESET_INPUT_BUFFER | 
|  | RESET_INPUT_BUFFER; | 
|  | #else | 
|  | /* We have a problem in one of the functions below. | 
|  | Undo the conversion upto the error point.  */ | 
|  | size_t nstatus __attribute__ ((unused)); | 
|  |  | 
|  | /* Reload the pointers.  */ | 
|  | *inptrp = inptr; | 
|  | outbuf = outstart; | 
|  |  | 
|  | /* Restore the state.  */ | 
|  | # ifdef SAVE_RESET_STATE | 
|  | SAVE_RESET_STATE (0); | 
|  | # endif | 
|  |  | 
|  | if (__glibc_likely (!unaligned)) | 
|  | { | 
|  | if (FROM_DIRECTION) | 
|  | /* Run the conversion loop.  */ | 
|  | nstatus = FROM_LOOP (step, data, inptrp, inend, | 
|  | &outbuf, outerr, | 
|  | lirreversiblep | 
|  | EXTRA_LOOP_ARGS); | 
|  | else | 
|  | /* Run the conversion loop.  */ | 
|  | nstatus = TO_LOOP (step, data, inptrp, inend, | 
|  | &outbuf, outerr, | 
|  | lirreversiblep | 
|  | EXTRA_LOOP_ARGS); | 
|  | } | 
|  | # if POSSIBLY_UNALIGNED | 
|  | else | 
|  | { | 
|  | if (FROM_DIRECTION) | 
|  | /* Run the conversion loop.  */ | 
|  | nstatus = GEN_unaligned (FROM_LOOP) (step, data, | 
|  | inptrp, inend, | 
|  | &outbuf, | 
|  | outerr, | 
|  | lirreversiblep | 
|  | EXTRA_LOOP_ARGS); | 
|  | else | 
|  | /* Run the conversion loop.  */ | 
|  | nstatus = GEN_unaligned (TO_LOOP) (step, data, | 
|  | inptrp, inend, | 
|  | &outbuf, outerr, | 
|  | lirreversiblep | 
|  | EXTRA_LOOP_ARGS); | 
|  | } | 
|  | # endif | 
|  |  | 
|  | /* We must run out of output buffer space in this | 
|  | rerun.  */ | 
|  | assert (outbuf == outerr); | 
|  | assert (nstatus == __GCONV_FULL_OUTPUT); | 
|  |  | 
|  | /* If we haven't consumed a single byte decrement | 
|  | the invocation counter.  */ | 
|  | if (__glibc_unlikely (outbuf == outstart)) | 
|  | --data->__invocation_counter; | 
|  | #endif	/* reset input buffer */ | 
|  | } | 
|  |  | 
|  | /* Change the status.  */ | 
|  | status = result; | 
|  | } | 
|  | else | 
|  | /* All the output is consumed, we can make another run | 
|  | if everything was ok.  */ | 
|  | if (status == __GCONV_FULL_OUTPUT) | 
|  | { | 
|  | status = __GCONV_OK; | 
|  | outbuf = data->__outbuf; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (status != __GCONV_OK) | 
|  | break; | 
|  |  | 
|  | /* Reset the output buffer pointer for the next round.  */ | 
|  | outbuf = data->__outbuf; | 
|  | } | 
|  |  | 
|  | #ifdef END_LOOP | 
|  | END_LOOP | 
|  | #endif | 
|  |  | 
|  | /* If we are supposed to consume all character store now all of the | 
|  | remaining characters in the `state' object.  */ | 
|  | #if FROM_LOOP_MAX_NEEDED_FROM > 1 || TO_LOOP_MAX_NEEDED_FROM > 1 | 
|  | if (((FROM_LOOP_MAX_NEEDED_FROM > 1 && TO_LOOP_MAX_NEEDED_FROM > 1) | 
|  | || (FROM_LOOP_MAX_NEEDED_FROM > 1 && FROM_DIRECTION) | 
|  | || (TO_LOOP_MAX_NEEDED_FROM > 1 && !FROM_DIRECTION)) | 
|  | && __builtin_expect (consume_incomplete, 0) | 
|  | && status == __GCONV_INCOMPLETE_INPUT) | 
|  | { | 
|  | # ifdef STORE_REST | 
|  | mbstate_t *state = data->__statep; | 
|  |  | 
|  | STORE_REST | 
|  | # else | 
|  | /* Make sure the remaining bytes fit into the state objects | 
|  | buffer.  */ | 
|  | assert (inend - *inptrp < 4); | 
|  |  | 
|  | size_t cnt; | 
|  | for (cnt = 0; *inptrp < inend; ++cnt) | 
|  | data->__statep->__value.__wchb[cnt] = *(*inptrp)++; | 
|  | data->__statep->__count &= ~7; | 
|  | data->__statep->__count |= cnt; | 
|  | # endif | 
|  | } | 
|  | #endif | 
|  | #undef unaligned | 
|  | #undef POSSIBLY_UNALIGNED | 
|  | } | 
|  |  | 
|  | return status; | 
|  | } | 
|  |  | 
|  | #undef DEFINE_INIT | 
|  | #undef CHARSET_NAME | 
|  | #undef DEFINE_FINI | 
|  | #undef MIN_NEEDED_FROM | 
|  | #undef MIN_NEEDED_TO | 
|  | #undef MAX_NEEDED_FROM | 
|  | #undef MAX_NEEDED_TO | 
|  | #undef FROM_LOOP_MIN_NEEDED_FROM | 
|  | #undef FROM_LOOP_MAX_NEEDED_FROM | 
|  | #undef FROM_LOOP_MIN_NEEDED_TO | 
|  | #undef FROM_LOOP_MAX_NEEDED_TO | 
|  | #undef TO_LOOP_MIN_NEEDED_FROM | 
|  | #undef TO_LOOP_MAX_NEEDED_FROM | 
|  | #undef TO_LOOP_MIN_NEEDED_TO | 
|  | #undef TO_LOOP_MAX_NEEDED_TO | 
|  | #undef FROM_DIRECTION | 
|  | #undef EMIT_SHIFT_TO_INIT | 
|  | #undef FROM_LOOP | 
|  | #undef TO_LOOP | 
|  | #undef ONE_DIRECTION | 
|  | #undef SAVE_RESET_STATE | 
|  | #undef RESET_INPUT_BUFFER | 
|  | #undef FUNCTION_NAME | 
|  | #undef PREPARE_LOOP | 
|  | #undef END_LOOP | 
|  | #undef EXTRA_LOOP_ARGS | 
|  | #undef STORE_REST | 
|  | #undef FROM_ONEBYTE |