Blame iconv/loop.c

Packit Service 82fcde
/* Conversion loop frame work.
Packit Service 82fcde
   Copyright (C) 1998-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
/* This file provides a frame for the reader loop in all conversion modules.
Packit Service 82fcde
   The actual code must (of course) be provided in the actual module source
Packit Service 82fcde
   code but certain actions can be written down generically, with some
Packit Service 82fcde
   customization options which are these:
Packit Service 82fcde
Packit Service 82fcde
     MIN_NEEDED_INPUT	minimal number of input bytes needed for the next
Packit Service 82fcde
			conversion.
Packit Service 82fcde
     MIN_NEEDED_OUTPUT	minimal number of bytes produced by the next round
Packit Service 82fcde
			of conversion.
Packit Service 82fcde
Packit Service 82fcde
     MAX_NEEDED_INPUT	you guess it, this is the maximal number of input
Packit Service 82fcde
			bytes needed.  It defaults to MIN_NEEDED_INPUT
Packit Service 82fcde
     MAX_NEEDED_OUTPUT	likewise for output bytes.
Packit Service 82fcde
Packit Service 82fcde
     LOOPFCT		name of the function created.  If not specified
Packit Service 82fcde
			the name is `loop' but this prevents the use
Packit Service 82fcde
			of multiple functions in the same file.
Packit Service 82fcde
Packit Service 82fcde
     BODY		this is supposed to expand to the body of the loop.
Packit Service 82fcde
			The user must provide this.
Packit Service 82fcde
Packit Service 82fcde
     EXTRA_LOOP_DECLS	extra arguments passed from conversion loop call.
Packit Service 82fcde
Packit Service 82fcde
     INIT_PARAMS	code to define and initialize variables from params.
Packit Service 82fcde
     UPDATE_PARAMS	code to store result in params.
Packit Service 82fcde
Packit Service 82fcde
     ONEBYTE_BODY	body of the specialized conversion function for a
Packit Service 82fcde
			single byte from the current character set to INTERNAL.
Packit Service 82fcde
*/
Packit Service 82fcde
Packit Service 82fcde
#include <assert.h>
Packit Service 82fcde
#include <endian.h>
Packit Service 82fcde
#include <gconv.h>
Packit Service 82fcde
#include <stdint.h>
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
#include <wchar.h>
Packit Service 82fcde
#include <sys/param.h>		/* For MIN.  */
Packit Service 82fcde
#define __need_size_t
Packit Service 82fcde
#include <stddef.h>
Packit Service 82fcde
#include <libc-diag.h>
Packit Service 82fcde
Packit Service 82fcde
/* We have to provide support for machines which are not able to handled
Packit Service 82fcde
   unaligned memory accesses.  Some of the character encodings have
Packit Service 82fcde
   representations with a fixed width of 2 or 4 bytes.  But if we cannot
Packit Service 82fcde
   access unaligned memory we still have to read byte-wise.  */
Packit Service 82fcde
#undef FCTNAME2
Packit Service 82fcde
#if _STRING_ARCH_unaligned || !defined DEFINE_UNALIGNED
Packit Service 82fcde
/* We can handle unaligned memory access.  */
Packit Service 82fcde
# define get16(addr) *((const uint16_t *) (addr))
Packit Service 82fcde
# define get32(addr) *((const uint32_t *) (addr))
Packit Service 82fcde
Packit Service 82fcde
/* We need no special support for writing values either.  */
Packit Service 82fcde
# define put16(addr, val) *((uint16_t *) (addr)) = (val)
Packit Service 82fcde
# define put32(addr, val) *((uint32_t *) (addr)) = (val)
Packit Service 82fcde
Packit Service 82fcde
# define FCTNAME2(name) name
Packit Service 82fcde
#else
Packit Service 82fcde
/* Distinguish between big endian and little endian.  */
Packit Service 82fcde
# if __BYTE_ORDER == __LITTLE_ENDIAN
Packit Service 82fcde
#  define get16(addr) \
Packit Service 82fcde
     (((const unsigned char *) (addr))[1] << 8				      \
Packit Service 82fcde
      | ((const unsigned char *) (addr))[0])
Packit Service 82fcde
#  define get32(addr) \
Packit Service 82fcde
     (((((const unsigned char *) (addr))[3] << 8			      \
Packit Service 82fcde
	| ((const unsigned char *) (addr))[2]) << 8			      \
Packit Service 82fcde
       | ((const unsigned char *) (addr))[1]) << 8			      \
Packit Service 82fcde
      | ((const unsigned char *) (addr))[0])
Packit Service 82fcde
Packit Service 82fcde
#  define put16(addr, val) \
Packit Service 82fcde
     ({ uint16_t __val = (val);						      \
Packit Service 82fcde
	((unsigned char *) (addr))[0] = __val;				      \
Packit Service 82fcde
	((unsigned char *) (addr))[1] = __val >> 8;			      \
Packit Service 82fcde
	(void) 0; })
Packit Service 82fcde
#  define put32(addr, val) \
Packit Service 82fcde
     ({ uint32_t __val = (val);						      \
Packit Service 82fcde
	((unsigned char *) (addr))[0] = __val;				      \
Packit Service 82fcde
	__val >>= 8;							      \
Packit Service 82fcde
	((unsigned char *) (addr))[1] = __val;				      \
Packit Service 82fcde
	__val >>= 8;							      \
Packit Service 82fcde
	((unsigned char *) (addr))[2] = __val;				      \
Packit Service 82fcde
	__val >>= 8;							      \
Packit Service 82fcde
	((unsigned char *) (addr))[3] = __val;				      \
Packit Service 82fcde
	(void) 0; })
Packit Service 82fcde
# else
Packit Service 82fcde
#  define get16(addr) \
Packit Service 82fcde
     (((const unsigned char *) (addr))[0] << 8				      \
Packit Service 82fcde
      | ((const unsigned char *) (addr))[1])
Packit Service 82fcde
#  define get32(addr) \
Packit Service 82fcde
     (((((const unsigned char *) (addr))[0] << 8			      \
Packit Service 82fcde
	| ((const unsigned char *) (addr))[1]) << 8			      \
Packit Service 82fcde
       | ((const unsigned char *) (addr))[2]) << 8			      \
Packit Service 82fcde
      | ((const unsigned char *) (addr))[3])
Packit Service 82fcde
Packit Service 82fcde
#  define put16(addr, val) \
Packit Service 82fcde
     ({ uint16_t __val = (val);						      \
Packit Service 82fcde
	((unsigned char *) (addr))[1] = __val;				      \
Packit Service 82fcde
	((unsigned char *) (addr))[0] = __val >> 8;			      \
Packit Service 82fcde
	(void) 0; })
Packit Service 82fcde
#  define put32(addr, val) \
Packit Service 82fcde
     ({ uint32_t __val = (val);						      \
Packit Service 82fcde
	((unsigned char *) (addr))[3] = __val;				      \
Packit Service 82fcde
	__val >>= 8;							      \
Packit Service 82fcde
	((unsigned char *) (addr))[2] = __val;				      \
Packit Service 82fcde
	__val >>= 8;							      \
Packit Service 82fcde
	((unsigned char *) (addr))[1] = __val;				      \
Packit Service 82fcde
	__val >>= 8;							      \
Packit Service 82fcde
	((unsigned char *) (addr))[0] = __val;				      \
Packit Service 82fcde
	(void) 0; })
Packit Service 82fcde
# endif
Packit Service 82fcde
Packit Service 82fcde
# define FCTNAME2(name) name##_unaligned
Packit Service 82fcde
#endif
Packit Service 82fcde
#define FCTNAME(name) FCTNAME2(name)
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* We need at least one byte for the next round.  */
Packit Service 82fcde
#ifndef MIN_NEEDED_INPUT
Packit Service 82fcde
# error "MIN_NEEDED_INPUT definition missing"
Packit Service 82fcde
#elif MIN_NEEDED_INPUT < 1
Packit Service 82fcde
# error "MIN_NEEDED_INPUT must be >= 1"
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* Let's see how many bytes we produce.  */
Packit Service 82fcde
#ifndef MAX_NEEDED_INPUT
Packit Service 82fcde
# define MAX_NEEDED_INPUT	MIN_NEEDED_INPUT
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* We produce at least one byte in the next round.  */
Packit Service 82fcde
#ifndef MIN_NEEDED_OUTPUT
Packit Service 82fcde
# error "MIN_NEEDED_OUTPUT definition missing"
Packit Service 82fcde
#elif MIN_NEEDED_OUTPUT < 1
Packit Service 82fcde
# error "MIN_NEEDED_OUTPUT must be >= 1"
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* Let's see how many bytes we produce.  */
Packit Service 82fcde
#ifndef MAX_NEEDED_OUTPUT
Packit Service 82fcde
# define MAX_NEEDED_OUTPUT	MIN_NEEDED_OUTPUT
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* Default name for the function.  */
Packit Service 82fcde
#ifndef LOOPFCT
Packit Service 82fcde
# define LOOPFCT		loop
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* Make sure we have a loop body.  */
Packit Service 82fcde
#ifndef BODY
Packit Service 82fcde
# error "Definition of BODY missing for function" LOOPFCT
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* If no arguments have to passed to the loop function define the macro
Packit Service 82fcde
   as empty.  */
Packit Service 82fcde
#ifndef EXTRA_LOOP_DECLS
Packit Service 82fcde
# define EXTRA_LOOP_DECLS
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* Allow using UPDATE_PARAMS in macros where #ifdef UPDATE_PARAMS test
Packit Service 82fcde
   isn't possible.  */
Packit Service 82fcde
#ifndef UPDATE_PARAMS
Packit Service 82fcde
# define UPDATE_PARAMS do { } while (0)
Packit Service 82fcde
#endif
Packit Service 82fcde
#ifndef REINIT_PARAMS
Packit Service 82fcde
# define REINIT_PARAMS do { } while (0)
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* To make it easier for the writers of the modules, we define a macro
Packit Service 82fcde
   to test whether we have to ignore errors.  */
Packit Service 82fcde
#define ignore_errors_p() \
Packit Service 82fcde
  (irreversible != NULL && (flags & __GCONV_IGNORE_ERRORS))
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Error handling for the FROM_LOOP direction, with ignoring of errors.
Packit Service 82fcde
   Note that we cannot use the do while (0) trick since `break' and
Packit Service 82fcde
   `continue' must reach certain points.  */
Packit Service 82fcde
#define STANDARD_FROM_LOOP_ERR_HANDLER(Incr) \
Packit Service 82fcde
  {									      \
Packit Service 82fcde
    result = __GCONV_ILLEGAL_INPUT;					      \
Packit Service 82fcde
									      \
Packit Service 82fcde
    if (! ignore_errors_p ())						      \
Packit Service 82fcde
      break;								      \
Packit Service 82fcde
									      \
Packit Service 82fcde
    /* We ignore the invalid input byte sequence.  */			      \
Packit Service 82fcde
    inptr += (Incr);							      \
Packit Service 82fcde
    ++*irreversible;							      \
Packit Service 82fcde
    /* But we keep result == __GCONV_ILLEGAL_INPUT, because of the constraint \
Packit Service 82fcde
       that "iconv -c" must give the same exitcode as "iconv".  */	      \
Packit Service 82fcde
    continue;								      \
Packit Service 82fcde
  }
Packit Service 82fcde
Packit Service 82fcde
/* Error handling for the TO_LOOP direction, with use of transliteration/
Packit Service 82fcde
   transcription functions and ignoring of errors.  Note that we cannot use
Packit Service 82fcde
   the do while (0) trick since `break' and `continue' must reach certain
Packit Service 82fcde
   points.  */
Packit Service 82fcde
#define STANDARD_TO_LOOP_ERR_HANDLER(Incr) \
Packit Service 82fcde
  {									      \
Packit Service 82fcde
    result = __GCONV_ILLEGAL_INPUT;					      \
Packit Service 82fcde
									      \
Packit Service 82fcde
    if (irreversible == NULL)						      \
Packit Service 82fcde
      /* This means we are in call from __gconv_transliterate.  In this	      \
Packit Service 82fcde
	 case we are not doing any error recovery outself.  */		      \
Packit Service 82fcde
      break;								      \
Packit Service 82fcde
									      \
Packit Service 82fcde
    /* If needed, flush any conversion state, so that __gconv_transliterate   \
Packit Service 82fcde
       starts with current shift state.  */				      \
Packit Service 82fcde
    UPDATE_PARAMS;							      \
Packit Service 82fcde
									      \
Packit Service 82fcde
    /* First try the transliteration methods.  */			      \
Packit Service 82fcde
    if ((step_data->__flags & __GCONV_TRANSLIT) != 0)			      \
Packit Service 82fcde
      result = __gconv_transliterate					      \
Packit Service 82fcde
	(step, step_data, *inptrp,					      \
Packit Service 82fcde
	 &inptr, inend, &outptr, irreversible);			      \
Packit Service 82fcde
									      \
Packit Service 82fcde
    REINIT_PARAMS;							      \
Packit Service 82fcde
									      \
Packit Service 82fcde
    /* If any of them recognized the input continue with the loop.  */	      \
Packit Service 82fcde
    if (result != __GCONV_ILLEGAL_INPUT)				      \
Packit Service 82fcde
      {									      \
Packit Service 82fcde
	if (__glibc_unlikely (result == __GCONV_FULL_OUTPUT))		      \
Packit Service 82fcde
	  break;							      \
Packit Service 82fcde
									      \
Packit Service 82fcde
	continue;							      \
Packit Service 82fcde
      }									      \
Packit Service 82fcde
									      \
Packit Service 82fcde
    /* Next see whether we have to ignore the error.  If not, stop.  */	      \
Packit Service 82fcde
    if (! ignore_errors_p ())						      \
Packit Service 82fcde
      break;								      \
Packit Service 82fcde
									      \
Packit Service 82fcde
    /* When we come here it means we ignore the character.  */		      \
Packit Service 82fcde
    ++*irreversible;							      \
Packit Service 82fcde
    inptr += Incr;							      \
Packit Service 82fcde
    /* But we keep result == __GCONV_ILLEGAL_INPUT, because of the constraint \
Packit Service 82fcde
       that "iconv -c" must give the same exitcode as "iconv".  */	      \
Packit Service 82fcde
    continue;								      \
Packit Service 82fcde
  }
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* With GCC 7 when compiling with -Os for 32-bit s390 the compiler
Packit Service 82fcde
   warns that the variable 'ch', in the definition of BODY in
Packit Service 82fcde
   sysdeps/s390/multiarch/8bit-generic.c, may be used uninitialized in
Packit Service 82fcde
   the call to UNICODE_TAG_HANDLER in that macro.  This variable is
Packit Service 82fcde
   actually always initialized before use, in the prior loop if INDEX
Packit Service 82fcde
   is nonzero and in the following 'if' if INDEX is zero.  That code
Packit Service 82fcde
   has a comment referencing this diagnostic disabling; updates in one
Packit Service 82fcde
   place may require updates in the other.  */
Packit Service 82fcde
DIAG_PUSH_NEEDS_COMMENT;
Packit Service 82fcde
DIAG_IGNORE_Os_NEEDS_COMMENT (7, "-Wmaybe-uninitialized");
Packit Service 82fcde
/* Handling of Unicode 3.1 TAG characters.  Unicode recommends
Packit Service 82fcde
   "If language codes are not relevant to the particular processing
Packit Service 82fcde
    operation, then they should be ignored."  This macro is usually
Packit Service 82fcde
   called right before  STANDARD_TO_LOOP_ERR_HANDLER (Incr).  */
Packit Service 82fcde
#define UNICODE_TAG_HANDLER(Character, Incr) \
Packit Service 82fcde
  {									      \
Packit Service 82fcde
    /* TAG characters are those in the range U+E0000..U+E007F.  */	      \
Packit Service 82fcde
    if (((Character) >> 7) == (0xe0000 >> 7))				      \
Packit Service 82fcde
      {									      \
Packit Service 82fcde
	inptr += Incr;							      \
Packit Service 82fcde
	continue;							      \
Packit Service 82fcde
      }									      \
Packit Service 82fcde
  }
Packit Service 82fcde
DIAG_POP_NEEDS_COMMENT;
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* The function returns the status, as defined in gconv.h.  */
Packit Service 82fcde
static inline int
Packit Service 82fcde
__attribute ((always_inline))
Packit Service 82fcde
FCTNAME (LOOPFCT) (struct __gconv_step *step,
Packit Service 82fcde
		   struct __gconv_step_data *step_data,
Packit Service 82fcde
		   const unsigned char **inptrp, const unsigned char *inend,
Packit Service 82fcde
		   unsigned char **outptrp, const unsigned char *outend,
Packit Service 82fcde
		   size_t *irreversible EXTRA_LOOP_DECLS)
Packit Service 82fcde
{
Packit Service 82fcde
#ifdef LOOP_NEED_STATE
Packit Service 82fcde
  mbstate_t *state = step_data->__statep;
Packit Service 82fcde
#endif
Packit Service 82fcde
#ifdef LOOP_NEED_FLAGS
Packit Service 82fcde
  int flags = step_data->__flags;
Packit Service 82fcde
#endif
Packit Service 82fcde
#ifdef LOOP_NEED_DATA
Packit Service 82fcde
  void *data = step->__data;
Packit Service 82fcde
#endif
Packit Service 82fcde
  int result = __GCONV_EMPTY_INPUT;
Packit Service 82fcde
  const unsigned char *inptr = *inptrp;
Packit Service 82fcde
  unsigned char *outptr = *outptrp;
Packit Service 82fcde
Packit Service 82fcde
#ifdef INIT_PARAMS
Packit Service 82fcde
  INIT_PARAMS;
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
  while (inptr != inend)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* `if' cases for MIN_NEEDED_OUTPUT ==/!= 1 is made to help the
Packit Service 82fcde
	 compiler generating better code.  They will be optimized away
Packit Service 82fcde
	 since MIN_NEEDED_OUTPUT is always a constant.  */
Packit Service 82fcde
      if (MIN_NEEDED_INPUT > 1
Packit Service 82fcde
	  && __builtin_expect (inptr + MIN_NEEDED_INPUT > inend, 0))
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* We don't have enough input for another complete input
Packit Service 82fcde
	     character.  */
Packit Service 82fcde
	  result = __GCONV_INCOMPLETE_INPUT;
Packit Service 82fcde
	  break;
Packit Service 82fcde
	}
Packit Service 82fcde
      if ((MIN_NEEDED_OUTPUT != 1
Packit Service 82fcde
	   && __builtin_expect (outptr + MIN_NEEDED_OUTPUT > outend, 0))
Packit Service 82fcde
	  || (MIN_NEEDED_OUTPUT == 1
Packit Service 82fcde
	      && __builtin_expect (outptr >= outend, 0)))
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* Overflow in the output buffer.  */
Packit Service 82fcde
	  result = __GCONV_FULL_OUTPUT;
Packit Service 82fcde
	  break;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      /* Here comes the body the user provides.  It can stop with
Packit Service 82fcde
	 RESULT set to GCONV_INCOMPLETE_INPUT (if the size of the
Packit Service 82fcde
	 input characters vary in size), GCONV_ILLEGAL_INPUT, or
Packit Service 82fcde
	 GCONV_FULL_OUTPUT (if the output characters vary in size).  */
Packit Service 82fcde
      BODY
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Update the pointers pointed to by the parameters.  */
Packit Service 82fcde
  *inptrp = inptr;
Packit Service 82fcde
  *outptrp = outptr;
Packit Service 82fcde
  UPDATE_PARAMS;
Packit Service 82fcde
Packit Service 82fcde
  return result;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Include the file a second time to define the function to handle
Packit Service 82fcde
   unaligned access.  */
Packit Service 82fcde
#if !defined DEFINE_UNALIGNED && !_STRING_ARCH_unaligned \
Packit Service 82fcde
    && MIN_NEEDED_INPUT != 1 && MAX_NEEDED_INPUT % MIN_NEEDED_INPUT == 0 \
Packit Service 82fcde
    && MIN_NEEDED_OUTPUT != 1 && MAX_NEEDED_OUTPUT % MIN_NEEDED_OUTPUT == 0
Packit Service 82fcde
# undef get16
Packit Service 82fcde
# undef get32
Packit Service 82fcde
# undef put16
Packit Service 82fcde
# undef put32
Packit Service 82fcde
# undef unaligned
Packit Service 82fcde
Packit Service 82fcde
# define DEFINE_UNALIGNED
Packit Service 82fcde
# include "loop.c"
Packit Service 82fcde
# undef DEFINE_UNALIGNED
Packit Service 82fcde
#else
Packit Service 82fcde
# if MAX_NEEDED_INPUT > 1
Packit Service 82fcde
#  define SINGLE(fct) SINGLE2 (fct)
Packit Service 82fcde
#  define SINGLE2(fct) fct##_single
Packit Service 82fcde
static inline int
Packit Service 82fcde
__attribute ((always_inline))
Packit Service 82fcde
SINGLE(LOOPFCT) (struct __gconv_step *step,
Packit Service 82fcde
		 struct __gconv_step_data *step_data,
Packit Service 82fcde
		 const unsigned char **inptrp, const unsigned char *inend,
Packit Service 82fcde
		 unsigned char **outptrp, unsigned char *outend,
Packit Service 82fcde
		 size_t *irreversible EXTRA_LOOP_DECLS)
Packit Service 82fcde
{
Packit Service 82fcde
  mbstate_t *state = step_data->__statep;
Packit Service 82fcde
#  ifdef LOOP_NEED_FLAGS
Packit Service 82fcde
  int flags = step_data->__flags;
Packit Service 82fcde
#  endif
Packit Service 82fcde
#  ifdef LOOP_NEED_DATA
Packit Service 82fcde
  void *data = step->__data;
Packit Service 82fcde
#  endif
Packit Service 82fcde
  int result = __GCONV_OK;
Packit Service 82fcde
  unsigned char bytebuf[MAX_NEEDED_INPUT];
Packit Service 82fcde
  const unsigned char *inptr = *inptrp;
Packit Service 82fcde
  unsigned char *outptr = *outptrp;
Packit Service 82fcde
  size_t inlen;
Packit Service 82fcde
Packit Service 82fcde
#  ifdef INIT_PARAMS
Packit Service 82fcde
  INIT_PARAMS;
Packit Service 82fcde
#  endif
Packit Service 82fcde
Packit Service 82fcde
#  ifdef UNPACK_BYTES
Packit Service 82fcde
  UNPACK_BYTES
Packit Service 82fcde
#  else
Packit Service 82fcde
  /* Add the bytes from the state to the input buffer.  */
Packit Service 82fcde
  assert ((state->__count & 7) <= sizeof (state->__value));
Packit Service 82fcde
  for (inlen = 0; inlen < (size_t) (state->__count & 7); ++inlen)
Packit Service 82fcde
    bytebuf[inlen] = state->__value.__wchb[inlen];
Packit Service 82fcde
#  endif
Packit Service 82fcde
Packit Service 82fcde
  /* Are there enough bytes in the input buffer?  */
Packit Service 82fcde
  if (MIN_NEEDED_INPUT > 1
Packit Service 82fcde
      && __builtin_expect (inptr + (MIN_NEEDED_INPUT - inlen) > inend, 0))
Packit Service 82fcde
    {
Packit Service 82fcde
      *inptrp = inend;
Packit Service 82fcde
#  ifdef STORE_REST
Packit Service 82fcde
Packit Service 82fcde
      /* Building with -O3 GCC emits a `array subscript is above array
Packit Service 82fcde
	 bounds' warning.  GCC BZ #64739 has been opened for this.  */
Packit Service 82fcde
      DIAG_PUSH_NEEDS_COMMENT;
Packit Service 82fcde
      DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Warray-bounds");
Packit Service 82fcde
      while (inptr < inend)
Packit Service 82fcde
	bytebuf[inlen++] = *inptr++;
Packit Service 82fcde
      DIAG_POP_NEEDS_COMMENT;
Packit Service 82fcde
Packit Service 82fcde
      inptr = bytebuf;
Packit Service 82fcde
      inptrp = &inptr;
Packit Service 82fcde
      inend = &bytebuf[inlen];
Packit Service 82fcde
Packit Service 82fcde
      STORE_REST
Packit Service 82fcde
#  else
Packit Service 82fcde
      /* We don't have enough input for another complete input
Packit Service 82fcde
	 character.  */
Packit Service 82fcde
      while (inptr < inend)
Packit Service 82fcde
	state->__value.__wchb[inlen++] = *inptr++;
Packit Service 82fcde
#  endif
Packit Service 82fcde
Packit Service 82fcde
      return __GCONV_INCOMPLETE_INPUT;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Enough space in output buffer.  */
Packit Service 82fcde
  if ((MIN_NEEDED_OUTPUT != 1 && outptr + MIN_NEEDED_OUTPUT > outend)
Packit Service 82fcde
      || (MIN_NEEDED_OUTPUT == 1 && outptr >= outend))
Packit Service 82fcde
    /* Overflow in the output buffer.  */
Packit Service 82fcde
    return __GCONV_FULL_OUTPUT;
Packit Service 82fcde
Packit Service 82fcde
  /*  Now add characters from the normal input buffer.  */
Packit Service 82fcde
  do
Packit Service 82fcde
    bytebuf[inlen++] = *inptr++;
Packit Service 82fcde
  while (inlen < MAX_NEEDED_INPUT && inptr < inend);
Packit Service 82fcde
Packit Service 82fcde
  inptr = bytebuf;
Packit Service 82fcde
  inend = &bytebuf[inlen];
Packit Service 82fcde
Packit Service 82fcde
  do
Packit Service 82fcde
    {
Packit Service 82fcde
      BODY
Packit Service 82fcde
    }
Packit Service 82fcde
  while (0);
Packit Service 82fcde
Packit Service 82fcde
  /* Now we either have produced an output character and consumed all the
Packit Service 82fcde
     bytes from the state and at least one more, or the character is still
Packit Service 82fcde
     incomplete, or we have some other error (like illegal input character,
Packit Service 82fcde
     no space in output buffer).  */
Packit Service 82fcde
  if (__glibc_likely (inptr != bytebuf))
Packit Service 82fcde
    {
Packit Service 82fcde
      /* We found a new character.  */
Packit Service 82fcde
      assert (inptr - bytebuf > (state->__count & 7));
Packit Service 82fcde
Packit Service 82fcde
      *inptrp += inptr - bytebuf - (state->__count & 7);
Packit Service 82fcde
      *outptrp = outptr;
Packit Service 82fcde
Packit Service 82fcde
      result = __GCONV_OK;
Packit Service 82fcde
Packit Service 82fcde
      /* Clear the state buffer.  */
Packit Service 82fcde
#  ifdef CLEAR_STATE
Packit Service 82fcde
      CLEAR_STATE;
Packit Service 82fcde
#  else
Packit Service 82fcde
      state->__count &= ~7;
Packit Service 82fcde
#  endif
Packit Service 82fcde
    }
Packit Service 82fcde
  else if (result == __GCONV_INCOMPLETE_INPUT)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* This can only happen if we have less than MAX_NEEDED_INPUT bytes
Packit Service 82fcde
	 available.  */
Packit Service 82fcde
      assert (inend != &bytebuf[MAX_NEEDED_INPUT]);
Packit Service 82fcde
Packit Service 82fcde
      *inptrp += inend - bytebuf - (state->__count & 7);
Packit Service 82fcde
#  ifdef STORE_REST
Packit Service 82fcde
      inptrp = &inptr;
Packit Service 82fcde
Packit Service 82fcde
      STORE_REST
Packit Service 82fcde
#  else
Packit Service 82fcde
      /* We don't have enough input for another complete input
Packit Service 82fcde
	 character.  */
Packit Service 82fcde
      assert (inend - inptr > (state->__count & ~7));
Packit Service 82fcde
      assert (inend - inptr <= sizeof (state->__value));
Packit Service 82fcde
      state->__count = (state->__count & ~7) | (inend - inptr);
Packit Service 82fcde
      inlen = 0;
Packit Service 82fcde
      while (inptr < inend)
Packit Service 82fcde
	state->__value.__wchb[inlen++] = *inptr++;
Packit Service 82fcde
#  endif
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  return result;
Packit Service 82fcde
}
Packit Service 82fcde
#  undef SINGLE
Packit Service 82fcde
#  undef SINGLE2
Packit Service 82fcde
# endif
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
# ifdef ONEBYTE_BODY
Packit Service 82fcde
/* Define the shortcut function for btowc.  */
Packit Service 82fcde
static wint_t
Packit Service 82fcde
gconv_btowc (struct __gconv_step *step, unsigned char c)
Packit Service 82fcde
  ONEBYTE_BODY
Packit Service 82fcde
#  define FROM_ONEBYTE gconv_btowc
Packit Service 82fcde
# endif
Packit Service 82fcde
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* We remove the macro definitions so that we can include this file again
Packit Service 82fcde
   for the definition of another function.  */
Packit Service 82fcde
#undef MIN_NEEDED_INPUT
Packit Service 82fcde
#undef MAX_NEEDED_INPUT
Packit Service 82fcde
#undef MIN_NEEDED_OUTPUT
Packit Service 82fcde
#undef MAX_NEEDED_OUTPUT
Packit Service 82fcde
#undef LOOPFCT
Packit Service 82fcde
#undef BODY
Packit Service 82fcde
#undef LOOPFCT
Packit Service 82fcde
#undef EXTRA_LOOP_DECLS
Packit Service 82fcde
#undef INIT_PARAMS
Packit Service 82fcde
#undef UPDATE_PARAMS
Packit Service 82fcde
#undef REINIT_PARAMS
Packit Service 82fcde
#undef ONEBYTE_BODY
Packit Service 82fcde
#undef UNPACK_BYTES
Packit Service 82fcde
#undef CLEAR_STATE
Packit Service 82fcde
#undef LOOP_NEED_STATE
Packit Service 82fcde
#undef LOOP_NEED_FLAGS
Packit Service 82fcde
#undef LOOP_NEED_DATA
Packit Service 82fcde
#undef get16
Packit Service 82fcde
#undef get32
Packit Service 82fcde
#undef put16
Packit Service 82fcde
#undef put32
Packit Service 82fcde
#undef unaligned