Back to index

glibc  2.9
skeleton.c
Go to the documentation of this file.
00001 /* Skeleton for a conversion module.
00002    Copyright (C) 1998-2002, 2005 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 /* This file can be included to provide definitions of several things
00022    many modules have in common.  It can be customized using the following
00023    macros:
00024 
00025      DEFINE_INIT     define the default initializer.  This requires the
00026                      following symbol to be defined.
00027 
00028      CHARSET_NAME    string with official name of the coded character
00029                      set (in all-caps)
00030 
00031      DEFINE_FINI     define the default destructor function.
00032 
00033      MIN_NEEDED_FROM minimal number of bytes needed for the from-charset.
00034      MIN_NEEDED_TO   likewise for the to-charset.
00035 
00036      MAX_NEEDED_FROM maximal number of bytes needed for the from-charset.
00037                      This macro is optional, it defaults to MIN_NEEDED_FROM.
00038      MAX_NEEDED_TO   likewise for the to-charset.
00039 
00040      FROM_LOOP_MIN_NEEDED_FROM
00041      FROM_LOOP_MAX_NEEDED_FROM
00042                         minimal/maximal number of bytes needed on input
00043                         of one round through the FROM_LOOP.  Defaults
00044                         to MIN_NEEDED_FROM and MAX_NEEDED_FROM, respectively.
00045      FROM_LOOP_MIN_NEEDED_TO
00046      FROM_LOOP_MAX_NEEDED_TO
00047                         minimal/maximal number of bytes needed on output
00048                         of one round through the FROM_LOOP.  Defaults
00049                         to MIN_NEEDED_TO and MAX_NEEDED_TO, respectively.
00050      TO_LOOP_MIN_NEEDED_FROM
00051      TO_LOOP_MAX_NEEDED_FROM
00052                         minimal/maximal number of bytes needed on input
00053                         of one round through the TO_LOOP.  Defaults
00054                         to MIN_NEEDED_TO and MAX_NEEDED_TO, respectively.
00055      TO_LOOP_MIN_NEEDED_TO
00056      TO_LOOP_MAX_NEEDED_TO
00057                         minimal/maximal number of bytes needed on output
00058                         of one round through the TO_LOOP.  Defaults
00059                         to MIN_NEEDED_FROM and MAX_NEEDED_FROM, respectively.
00060 
00061      FROM_DIRECTION  this macro is supposed to return a value != 0
00062                      if we convert from the current character set,
00063                      otherwise it return 0.
00064 
00065      EMIT_SHIFT_TO_INIT     this symbol is optional.  If it is defined it
00066                      defines some code which writes out a sequence
00067                      of bytes which bring the current state into
00068                      the initial state.
00069 
00070      FROM_LOOP              name of the function implementing the conversion
00071                      from the current character set.
00072      TO_LOOP         likewise for the other direction
00073 
00074      ONE_DIRECTION   optional.  If defined to 1, only one conversion
00075                      direction is defined instead of two.  In this
00076                      case, FROM_DIRECTION should be defined to 1, and
00077                      FROM_LOOP and TO_LOOP should have the same value.
00078 
00079      SAVE_RESET_STATE       in case of an error we must reset the state for
00080                      the rerun so this macro must be defined for
00081                      stateful encodings.  It takes an argument which
00082                      is nonzero when saving.
00083 
00084      RESET_INPUT_BUFFER     If the input character sets allow this the macro
00085                      can be defined to reset the input buffer pointers
00086                      to cover only those characters up to the error.
00087 
00088      FUNCTION_NAME   if not set the conversion function is named `gconv'.
00089 
00090      PREPARE_LOOP    optional code preparing the conversion loop.  Can
00091                      contain variable definitions.
00092      END_LOOP        also optional, may be used to store information
00093 
00094      EXTRA_LOOP_ARGS optional macro specifying extra arguments passed
00095                      to loop function.
00096 
00097      STORE_REST             optional, needed only when MAX_NEEDED_FROM > 4.
00098                      This macro stores the seen but unconverted input bytes
00099                      in the state.
00100 
00101      FROM_ONEBYTE    optional.  If defined, should be the name of a
00102                      specialized conversion function for a single byte
00103                      from the current character set to INTERNAL.  This
00104                      function has prototype
00105                         wint_t
00106                         FROM_ONEBYTE (struct __gconv_step *, unsigned char);
00107                      and does a special conversion:
00108                      - The input is a single byte.
00109                      - The output is a single uint32_t.
00110                      - The state before the conversion is the initial state;
00111                        the state after the conversion is irrelevant.
00112                      - No transliteration.
00113                      - __invocation_counter = 0.
00114                      - __internal_use = 1.
00115                      - do_flush = 0.
00116 
00117    Modules can use mbstate_t to store conversion state as follows:
00118 
00119    * Bits 2..0 of '__count' contain the number of lookahead input bytes
00120      stored in __value.__wchb.  Always zero if the converter never
00121      returns __GCONV_INCOMPLETE_INPUT.
00122 
00123    * Bits 31..3 of '__count' are module dependent shift state.
00124 
00125    * __value: When STORE_REST/UNPACK_BYTES aren't defined and when the
00126      converter has returned __GCONV_INCOMPLETE_INPUT, this contains
00127      at most 4 lookahead bytes. Converters with an mb_cur_max > 4
00128      (currently only UTF-8) must find a way to store their state
00129      in __value.__wch and define STORE_REST/UNPACK_BYTES appropriately.
00130 
00131    When __value contains lookahead, __count must not be zero, because
00132    the converter is not in the initial state then, and mbsinit() --
00133    defined as a (__count == 0) test -- must reflect this.
00134  */
00135 
00136 #include <assert.h>
00137 #include <gconv.h>
00138 #include <string.h>
00139 #define __need_size_t
00140 #define __need_NULL
00141 #include <stddef.h>
00142 
00143 #ifndef STATIC_GCONV
00144 # include <dlfcn.h>
00145 #endif
00146 
00147 #include <sysdep.h>
00148 
00149 #ifndef DL_CALL_FCT
00150 # define DL_CALL_FCT(fct, args) fct args
00151 #endif
00152 
00153 /* The direction objects.  */
00154 #if DEFINE_INIT
00155 # ifndef FROM_DIRECTION
00156 #  define FROM_DIRECTION_VAL NULL
00157 #  define TO_DIRECTION_VAL ((void *) ~((uintptr_t) 0))
00158 #  define FROM_DIRECTION (step->__data == FROM_DIRECTION_VAL)
00159 # endif
00160 #else
00161 # ifndef FROM_DIRECTION
00162 #  error "FROM_DIRECTION must be provided if non-default init is used"
00163 # endif
00164 #endif
00165 
00166 
00167 /* How many bytes are needed at most for the from-charset.  */
00168 #ifndef MAX_NEEDED_FROM
00169 # define MAX_NEEDED_FROM    MIN_NEEDED_FROM
00170 #endif
00171 
00172 /* Same for the to-charset.  */
00173 #ifndef MAX_NEEDED_TO
00174 # define MAX_NEEDED_TO             MIN_NEEDED_TO
00175 #endif
00176 
00177 /* Defaults for the per-direction min/max constants.  */
00178 #ifndef FROM_LOOP_MIN_NEEDED_FROM
00179 # define FROM_LOOP_MIN_NEEDED_FROM MIN_NEEDED_FROM
00180 #endif
00181 #ifndef FROM_LOOP_MAX_NEEDED_FROM
00182 # define FROM_LOOP_MAX_NEEDED_FROM MAX_NEEDED_FROM
00183 #endif
00184 #ifndef FROM_LOOP_MIN_NEEDED_TO
00185 # define FROM_LOOP_MIN_NEEDED_TO   MIN_NEEDED_TO
00186 #endif
00187 #ifndef FROM_LOOP_MAX_NEEDED_TO
00188 # define FROM_LOOP_MAX_NEEDED_TO   MAX_NEEDED_TO
00189 #endif
00190 #ifndef TO_LOOP_MIN_NEEDED_FROM
00191 # define TO_LOOP_MIN_NEEDED_FROM   MIN_NEEDED_TO
00192 #endif
00193 #ifndef TO_LOOP_MAX_NEEDED_FROM
00194 # define TO_LOOP_MAX_NEEDED_FROM   MAX_NEEDED_TO
00195 #endif
00196 #ifndef TO_LOOP_MIN_NEEDED_TO
00197 # define TO_LOOP_MIN_NEEDED_TO            MIN_NEEDED_FROM
00198 #endif
00199 #ifndef TO_LOOP_MAX_NEEDED_TO
00200 # define TO_LOOP_MAX_NEEDED_TO            MAX_NEEDED_FROM
00201 #endif
00202 
00203 
00204 /* Define macros which can access unaligned buffers.  These macros are
00205    supposed to be used only in code outside the inner loops.  For the inner
00206    loops we have other definitions which allow optimized access.  */
00207 #ifdef _STRING_ARCH_unaligned
00208 /* We can handle unaligned memory access.  */
00209 # define get16u(addr) *((__const uint16_t *) (addr))
00210 # define get32u(addr) *((__const uint32_t *) (addr))
00211 
00212 /* We need no special support for writing values either.  */
00213 # define put16u(addr, val) *((uint16_t *) (addr)) = (val)
00214 # define put32u(addr, val) *((uint32_t *) (addr)) = (val)
00215 #else
00216 /* Distinguish between big endian and little endian.  */
00217 # if __BYTE_ORDER == __LITTLE_ENDIAN
00218 #  define get16u(addr) \
00219      (((__const unsigned char *) (addr))[1] << 8                     \
00220       | ((__const unsigned char *) (addr))[0])
00221 #  define get32u(addr) \
00222      (((((__const unsigned char *) (addr))[3] << 8                          \
00223        | ((__const unsigned char *) (addr))[2]) << 8                        \
00224        | ((__const unsigned char *) (addr))[1]) << 8                        \
00225       | ((__const unsigned char *) (addr))[0])
00226 
00227 #  define put16u(addr, val) \
00228      ({ uint16_t __val = (val);                                             \
00229        ((unsigned char *) (addr))[0] = __val;                               \
00230        ((unsigned char *) (addr))[1] = __val >> 8;                          \
00231        (void) 0; })
00232 #  define put32u(addr, val) \
00233      ({ uint32_t __val = (val);                                             \
00234        ((unsigned char *) (addr))[0] = __val;                               \
00235        __val >>= 8;                                                  \
00236        ((unsigned char *) (addr))[1] = __val;                               \
00237        __val >>= 8;                                                  \
00238        ((unsigned char *) (addr))[2] = __val;                               \
00239        __val >>= 8;                                                  \
00240        ((unsigned char *) (addr))[3] = __val;                               \
00241        (void) 0; })
00242 # else
00243 #  define get16u(addr) \
00244      (((__const unsigned char *) (addr))[0] << 8                     \
00245       | ((__const unsigned char *) (addr))[1])
00246 #  define get32u(addr) \
00247      (((((__const unsigned char *) (addr))[0] << 8                          \
00248        | ((__const unsigned char *) (addr))[1]) << 8                        \
00249        | ((__const unsigned char *) (addr))[2]) << 8                        \
00250       | ((__const unsigned char *) (addr))[3])
00251 
00252 #  define put16u(addr, val) \
00253      ({ uint16_t __val = (val);                                             \
00254        ((unsigned char *) (addr))[1] = __val;                               \
00255        ((unsigned char *) (addr))[0] = __val >> 8;                          \
00256        (void) 0; })
00257 #  define put32u(addr, val) \
00258      ({ uint32_t __val = (val);                                             \
00259        ((unsigned char *) (addr))[3] = __val;                               \
00260        __val >>= 8;                                                  \
00261        ((unsigned char *) (addr))[2] = __val;                               \
00262        __val >>= 8;                                                  \
00263        ((unsigned char *) (addr))[1] = __val;                               \
00264        __val >>= 8;                                                  \
00265        ((unsigned char *) (addr))[0] = __val;                               \
00266        (void) 0; })
00267 # endif
00268 #endif
00269 
00270 
00271 /* For conversions from a fixed width character set to another fixed width
00272    character set we can define RESET_INPUT_BUFFER in a very fast way.  */
00273 #if !defined RESET_INPUT_BUFFER && !defined SAVE_RESET_STATE
00274 # if FROM_LOOP_MIN_NEEDED_FROM == FROM_LOOP_MAX_NEEDED_FROM \
00275      && FROM_LOOP_MIN_NEEDED_TO == FROM_LOOP_MAX_NEEDED_TO \
00276      && TO_LOOP_MIN_NEEDED_FROM == TO_LOOP_MAX_NEEDED_FROM \
00277      && TO_LOOP_MIN_NEEDED_TO == TO_LOOP_MAX_NEEDED_TO
00278 /* We have to use these `if's here since the compiler cannot know that
00279    (outbuf - outerr) is always divisible by FROM/TO_LOOP_MIN_NEEDED_TO.
00280    The ?:1 avoids division by zero warnings that gcc 3.2 emits even for
00281    obviously unreachable code.  */
00282 #  define RESET_INPUT_BUFFER \
00283   if (FROM_DIRECTION)                                                       \
00284     {                                                                \
00285       if (FROM_LOOP_MIN_NEEDED_FROM % FROM_LOOP_MIN_NEEDED_TO == 0)         \
00286        *inptrp -= (outbuf - outerr)                                         \
00287                  * (FROM_LOOP_MIN_NEEDED_FROM / FROM_LOOP_MIN_NEEDED_TO);   \
00288       else if (FROM_LOOP_MIN_NEEDED_TO % FROM_LOOP_MIN_NEEDED_FROM == 0)      \
00289        *inptrp -= (outbuf - outerr)                                         \
00290                  / (FROM_LOOP_MIN_NEEDED_TO / FROM_LOOP_MIN_NEEDED_FROM     \
00291                     ? : 1);                                          \
00292       else                                                           \
00293        *inptrp -= ((outbuf - outerr) / FROM_LOOP_MIN_NEEDED_TO)             \
00294                  * FROM_LOOP_MIN_NEEDED_FROM;                               \
00295     }                                                                \
00296   else                                                               \
00297     {                                                                \
00298       if (TO_LOOP_MIN_NEEDED_FROM % TO_LOOP_MIN_NEEDED_TO == 0)                    \
00299        *inptrp -= (outbuf - outerr)                                         \
00300                  * (TO_LOOP_MIN_NEEDED_FROM / TO_LOOP_MIN_NEEDED_TO);       \
00301       else if (TO_LOOP_MIN_NEEDED_TO % TO_LOOP_MIN_NEEDED_FROM == 0)        \
00302        *inptrp -= (outbuf - outerr)                                         \
00303                  / (TO_LOOP_MIN_NEEDED_TO / TO_LOOP_MIN_NEEDED_FROM ? : 1); \
00304       else                                                           \
00305        *inptrp -= ((outbuf - outerr) / TO_LOOP_MIN_NEEDED_TO)               \
00306                  * TO_LOOP_MIN_NEEDED_FROM;                                 \
00307     }
00308 # endif
00309 #endif
00310 
00311 
00312 /* The default init function.  It simply matches the name and initializes
00313    the step data to point to one of the objects above.  */
00314 #if DEFINE_INIT
00315 # ifndef CHARSET_NAME
00316 #  error "CHARSET_NAME not defined"
00317 # endif
00318 
00319 extern int gconv_init (struct __gconv_step *step);
00320 int
00321 gconv_init (struct __gconv_step *step)
00322 {
00323   /* Determine which direction.  */
00324   if (strcmp (step->__from_name, CHARSET_NAME) == 0)
00325     {
00326       step->__data = FROM_DIRECTION_VAL;
00327 
00328       step->__min_needed_from = FROM_LOOP_MIN_NEEDED_FROM;
00329       step->__max_needed_from = FROM_LOOP_MAX_NEEDED_FROM;
00330       step->__min_needed_to = FROM_LOOP_MIN_NEEDED_TO;
00331       step->__max_needed_to = FROM_LOOP_MAX_NEEDED_TO;
00332 
00333 #ifdef FROM_ONEBYTE
00334       step->__btowc_fct = FROM_ONEBYTE;
00335 #endif
00336     }
00337   else if (__builtin_expect (strcmp (step->__to_name, CHARSET_NAME), 0) == 0)
00338     {
00339       step->__data = TO_DIRECTION_VAL;
00340 
00341       step->__min_needed_from = TO_LOOP_MIN_NEEDED_FROM;
00342       step->__max_needed_from = TO_LOOP_MAX_NEEDED_FROM;
00343       step->__min_needed_to = TO_LOOP_MIN_NEEDED_TO;
00344       step->__max_needed_to = TO_LOOP_MAX_NEEDED_TO;
00345     }
00346   else
00347     return __GCONV_NOCONV;
00348 
00349 #ifdef SAVE_RESET_STATE
00350   step->__stateful = 1;
00351 #else
00352   step->__stateful = 0;
00353 #endif
00354 
00355   return __GCONV_OK;
00356 }
00357 #endif
00358 
00359 
00360 /* The default destructor function does nothing in the moment and so
00361    we don't define it at all.  But we still provide the macro just in
00362    case we need it some day.  */
00363 #if DEFINE_FINI
00364 #endif
00365 
00366 
00367 /* If no arguments have to passed to the loop function define the macro
00368    as empty.  */
00369 #ifndef EXTRA_LOOP_ARGS
00370 # define EXTRA_LOOP_ARGS
00371 #endif
00372 
00373 
00374 /* This is the actual conversion function.  */
00375 #ifndef FUNCTION_NAME
00376 # define FUNCTION_NAME      gconv
00377 #endif
00378 
00379 /* The macros are used to access the function to convert single characters.  */
00380 #define SINGLE(fct) SINGLE2 (fct)
00381 #define SINGLE2(fct) fct##_single
00382 
00383 
00384 extern int FUNCTION_NAME (struct __gconv_step *step,
00385                        struct __gconv_step_data *data,
00386                        const unsigned char **inptrp,
00387                        const unsigned char *inend,
00388                        unsigned char **outbufstart, size_t *irreversible,
00389                        int do_flush, int consume_incomplete);
00390 int
00391 FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
00392               const unsigned char **inptrp, const unsigned char *inend,
00393               unsigned char **outbufstart, size_t *irreversible, int do_flush,
00394               int consume_incomplete)
00395 {
00396   struct __gconv_step *next_step = step + 1;
00397   struct __gconv_step_data *next_data = data + 1;
00398   __gconv_fct fct = NULL;
00399   int status;
00400 
00401   if ((data->__flags & __GCONV_IS_LAST) == 0)
00402     {
00403       fct = next_step->__fct;
00404 #ifdef PTR_DEMANGLE
00405       if (next_step->__shlib_handle != NULL)
00406        PTR_DEMANGLE (fct);
00407 #endif
00408     }
00409 
00410   /* If the function is called with no input this means we have to reset
00411      to the initial state.  The possibly partly converted input is
00412      dropped.  */
00413   if (__builtin_expect (do_flush, 0))
00414     {
00415       /* This should never happen during error handling.  */
00416       assert (outbufstart == NULL);
00417 
00418       status = __GCONV_OK;
00419 
00420 #ifdef EMIT_SHIFT_TO_INIT
00421       if (do_flush == 1)
00422        {
00423          /* We preserve the initial values of the pointer variables.  */
00424          unsigned char *outbuf = data->__outbuf;
00425          unsigned char *outstart = outbuf;
00426          unsigned char *outend = data->__outbufend;
00427 
00428 # ifdef PREPARE_LOOP
00429          PREPARE_LOOP
00430 # endif
00431 
00432 # ifdef SAVE_RESET_STATE
00433          SAVE_RESET_STATE (1);
00434 # endif
00435 
00436          /* Emit the escape sequence to reset the state.  */
00437          EMIT_SHIFT_TO_INIT;
00438 
00439          /* Call the steps down the chain if there are any but only if we
00440             successfully emitted the escape sequence.  This should only
00441             fail if the output buffer is full.  If the input is invalid
00442             it should be discarded since the user wants to start from a
00443             clean state.  */
00444          if (status == __GCONV_OK)
00445            {
00446              if (data->__flags & __GCONV_IS_LAST)
00447               /* Store information about how many bytes are available.  */
00448               data->__outbuf = outbuf;
00449              else
00450               {
00451                 /* Write out all output which was produced.  */
00452                 if (outbuf > outstart)
00453                   {
00454                     const unsigned char *outerr = outstart;
00455                     int result;
00456 
00457                     result = DL_CALL_FCT (fct, (next_step, next_data,
00458                                             &outerr, outbuf, NULL,
00459                                             irreversible, 0,
00460                                             consume_incomplete));
00461 
00462                     if (result != __GCONV_EMPTY_INPUT)
00463                      {
00464                        if (__builtin_expect (outerr != outbuf, 0))
00465                          {
00466                            /* We have a problem.  Undo the conversion.  */
00467                            outbuf = outstart;
00468 
00469                            /* Restore the state.  */
00470 # ifdef SAVE_RESET_STATE
00471                            SAVE_RESET_STATE (0);
00472 # endif
00473                          }
00474 
00475                        /* Change the status.  */
00476                        status = result;
00477                      }
00478                   }
00479 
00480                 if (status == __GCONV_OK)
00481                   /* Now flush the remaining steps.  */
00482                   status = DL_CALL_FCT (fct, (next_step, next_data, NULL,
00483                                           NULL, NULL, irreversible, 1,
00484                                           consume_incomplete));
00485               }
00486            }
00487        }
00488       else
00489 #endif
00490        {
00491          /* Clear the state object.  There might be bytes in there from
00492             previous calls with CONSUME_INCOMPLETE == 1.  But don't emit
00493             escape sequences.  */
00494          memset (data->__statep, '\0', sizeof (*data->__statep));
00495 
00496          if (! (data->__flags & __GCONV_IS_LAST))
00497            /* Now flush the remaining steps.  */
00498            status = DL_CALL_FCT (fct, (next_step, next_data, NULL, NULL,
00499                                    NULL, irreversible, do_flush,
00500                                    consume_incomplete));
00501        }
00502     }
00503   else
00504     {
00505       /* We preserve the initial values of the pointer variables.  */
00506       const unsigned char *inptr = *inptrp;
00507       unsigned char *outbuf = (__builtin_expect (outbufstart == NULL, 1)
00508                             ? data->__outbuf : *outbufstart);
00509       unsigned char *outend = data->__outbufend;
00510       unsigned char *outstart;
00511       /* This variable is used to count the number of characters we
00512         actually converted.  */
00513       size_t lirreversible = 0;
00514       size_t *lirreversiblep = irreversible ? &lirreversible : NULL;
00515 
00516       /* The following assumes that encodings, which have a variable length
00517         what might unalign a buffer even though it is a aligned in the
00518         beginning, either don't have the minimal number of bytes as a divisor
00519         of the maximum length or have a minimum length of 1.  This is true
00520         for all known and supported encodings.
00521         We use && instead of || to combine the subexpression for the FROM
00522         encoding and for the TO encoding, because usually one of them is
00523         INTERNAL, for which the subexpression evaluates to 1, but INTERNAL
00524         buffers are always aligned correctly.  */
00525 #define POSSIBLY_UNALIGNED \
00526   (!defined _STRING_ARCH_unaligned                                   \
00527    && (((FROM_LOOP_MIN_NEEDED_FROM != 1                                     \
00528         && FROM_LOOP_MAX_NEEDED_FROM % FROM_LOOP_MIN_NEEDED_FROM == 0)             \
00529        && (FROM_LOOP_MIN_NEEDED_TO != 1                              \
00530            && FROM_LOOP_MAX_NEEDED_TO % FROM_LOOP_MIN_NEEDED_TO == 0))             \
00531        || ((TO_LOOP_MIN_NEEDED_FROM != 1                             \
00532            && TO_LOOP_MAX_NEEDED_FROM % TO_LOOP_MIN_NEEDED_FROM == 0)       \
00533           && (TO_LOOP_MIN_NEEDED_TO != 1                             \
00534               && TO_LOOP_MAX_NEEDED_TO % TO_LOOP_MIN_NEEDED_TO == 0))))
00535 #if POSSIBLY_UNALIGNED
00536       int unaligned;
00537 # define GEN_unaligned(name) GEN_unaligned2 (name)
00538 # define GEN_unaligned2(name) name##_unaligned
00539 #else
00540 # define unaligned 0
00541 #endif
00542 
00543 #ifdef PREPARE_LOOP
00544       PREPARE_LOOP
00545 #endif
00546 
00547 #if FROM_LOOP_MAX_NEEDED_FROM > 1 || TO_LOOP_MAX_NEEDED_FROM > 1
00548       /* If the function is used to implement the mb*towc*() or wc*tomb*()
00549         functions we must test whether any bytes from the last call are
00550         stored in the `state' object.  */
00551       if (((FROM_LOOP_MAX_NEEDED_FROM > 1 && TO_LOOP_MAX_NEEDED_FROM > 1)
00552           || (FROM_LOOP_MAX_NEEDED_FROM > 1 && FROM_DIRECTION)
00553           || (TO_LOOP_MAX_NEEDED_FROM > 1 && !FROM_DIRECTION))
00554          && consume_incomplete && (data->__statep->__count & 7) != 0)
00555        {
00556          /* Yep, we have some bytes left over.  Process them now.
00557              But this must not happen while we are called from an
00558              error handler.  */
00559          assert (outbufstart == NULL);
00560 
00561 # if FROM_LOOP_MAX_NEEDED_FROM > 1
00562          if (TO_LOOP_MAX_NEEDED_FROM == 1 || FROM_DIRECTION)
00563            status = SINGLE(FROM_LOOP) (step, data, inptrp, inend, &outbuf,
00564                                    outend, lirreversiblep
00565                                    EXTRA_LOOP_ARGS);
00566 # endif
00567 # if !ONE_DIRECTION
00568 #  if FROM_LOOP_MAX_NEEDED_FROM > 1 && TO_LOOP_MAX_NEEDED_FROM > 1
00569          else
00570 #  endif
00571 #  if TO_LOOP_MAX_NEEDED_FROM > 1
00572            status = SINGLE(TO_LOOP) (step, data, inptrp, inend, &outbuf,
00573                                   outend, lirreversiblep EXTRA_LOOP_ARGS);
00574 #  endif
00575 # endif
00576 
00577          if (__builtin_expect (status, __GCONV_OK) != __GCONV_OK)
00578            return status;
00579        }
00580 #endif
00581 
00582 #if POSSIBLY_UNALIGNED
00583       unaligned =
00584        ((FROM_DIRECTION
00585          && ((uintptr_t) inptr % FROM_LOOP_MIN_NEEDED_FROM != 0
00586              || ((data->__flags & __GCONV_IS_LAST)
00587                 && (uintptr_t) outbuf % FROM_LOOP_MIN_NEEDED_TO != 0)))
00588         || (!FROM_DIRECTION
00589             && (((data->__flags & __GCONV_IS_LAST)
00590                 && (uintptr_t) outbuf % TO_LOOP_MIN_NEEDED_TO != 0)
00591                || (uintptr_t) inptr % TO_LOOP_MIN_NEEDED_FROM != 0)));
00592 #endif
00593 
00594       while (1)
00595        {
00596          struct __gconv_trans_data *trans;
00597 
00598          /* Remember the start value for this round.  */
00599          inptr = *inptrp;
00600          /* The outbuf buffer is empty.  */
00601          outstart = outbuf;
00602 
00603 #ifdef SAVE_RESET_STATE
00604          SAVE_RESET_STATE (1);
00605 #endif
00606 
00607          if (__builtin_expect (!unaligned, 1))
00608            {
00609              if (FROM_DIRECTION)
00610               /* Run the conversion loop.  */
00611               status = FROM_LOOP (step, data, inptrp, inend, &outbuf, outend,
00612                                 lirreversiblep EXTRA_LOOP_ARGS);
00613              else
00614               /* Run the conversion loop.  */
00615               status = TO_LOOP (step, data, inptrp, inend, &outbuf, outend,
00616                               lirreversiblep EXTRA_LOOP_ARGS);
00617            }
00618 #if POSSIBLY_UNALIGNED
00619          else
00620            {
00621              if (FROM_DIRECTION)
00622               /* Run the conversion loop.  */
00623               status = GEN_unaligned (FROM_LOOP) (step, data, inptrp, inend,
00624                                               &outbuf, outend,
00625                                               lirreversiblep
00626                                               EXTRA_LOOP_ARGS);
00627              else
00628               /* Run the conversion loop.  */
00629               status = GEN_unaligned (TO_LOOP) (step, data, inptrp, inend,
00630                                             &outbuf, outend,
00631                                             lirreversiblep
00632                                             EXTRA_LOOP_ARGS);
00633            }
00634 #endif
00635 
00636          /* If we were called as part of an error handling module we
00637             don't do anything else here.  */
00638          if (__builtin_expect (outbufstart != NULL, 0))
00639            {
00640              *outbufstart = outbuf;
00641              return status;
00642            }
00643 
00644          /* Give the transliteration module the chance to store the
00645             original text and the result in case it needs a context.  */
00646          for (trans = data->__trans; trans != NULL; trans = trans->__next)
00647            if (trans->__trans_context_fct != NULL)
00648              DL_CALL_FCT (trans->__trans_context_fct,
00649                         (trans->__data, inptr, *inptrp, outstart, outbuf));
00650 
00651          /* We finished one use of the loops.  */
00652          ++data->__invocation_counter;
00653 
00654          /* If this is the last step leave the loop, there is nothing
00655              we can do.  */
00656          if (__builtin_expect (data->__flags & __GCONV_IS_LAST, 0))
00657            {
00658              /* Store information about how many bytes are available.  */
00659              data->__outbuf = outbuf;
00660 
00661              /* Remember how many non-identical characters we
00662                  converted in a irreversible way.  */
00663              *irreversible += lirreversible;
00664 
00665              break;
00666            }
00667 
00668          /* Write out all output which was produced.  */
00669          if (__builtin_expect (outbuf > outstart, 1))
00670            {
00671              const unsigned char *outerr = data->__outbuf;
00672              int result;
00673 
00674              result = DL_CALL_FCT (fct, (next_step, next_data, &outerr,
00675                                      outbuf, NULL, irreversible, 0,
00676                                      consume_incomplete));
00677 
00678              if (result != __GCONV_EMPTY_INPUT)
00679               {
00680                 if (__builtin_expect (outerr != outbuf, 0))
00681                   {
00682 #ifdef RESET_INPUT_BUFFER
00683                     RESET_INPUT_BUFFER;
00684 #else
00685                     /* We have a problem in one of the functions below.
00686                       Undo the conversion upto the error point.  */
00687                     size_t nstatus;
00688 
00689                     /* Reload the pointers.  */
00690                     *inptrp = inptr;
00691                     outbuf = outstart;
00692 
00693                     /* Restore the state.  */
00694 # ifdef SAVE_RESET_STATE
00695                     SAVE_RESET_STATE (0);
00696 # endif
00697 
00698                     if (__builtin_expect (!unaligned, 1))
00699                      {
00700                        if (FROM_DIRECTION)
00701                          /* Run the conversion loop.  */
00702                          nstatus = FROM_LOOP (step, data, inptrp, inend,
00703                                            &outbuf, outerr,
00704                                            lirreversiblep
00705                                            EXTRA_LOOP_ARGS);
00706                        else
00707                          /* Run the conversion loop.  */
00708                          nstatus = TO_LOOP (step, data, inptrp, inend,
00709                                           &outbuf, outerr,
00710                                           lirreversiblep
00711                                           EXTRA_LOOP_ARGS);
00712                      }
00713 # if POSSIBLY_UNALIGNED
00714                     else
00715                      {
00716                        if (FROM_DIRECTION)
00717                          /* Run the conversion loop.  */
00718                          nstatus = GEN_unaligned (FROM_LOOP) (step, data,
00719                                                          inptrp, inend,
00720                                                          &outbuf,
00721                                                          outerr,
00722                                                          lirreversiblep
00723                                                          EXTRA_LOOP_ARGS);
00724                        else
00725                          /* Run the conversion loop.  */
00726                          nstatus = GEN_unaligned (TO_LOOP) (step, data,
00727                                                         inptrp, inend,
00728                                                         &outbuf, outerr,
00729                                                         lirreversiblep
00730                                                         EXTRA_LOOP_ARGS);
00731                      }
00732 # endif
00733 
00734                     /* We must run out of output buffer space in this
00735                       rerun.  */
00736                     assert (outbuf == outerr);
00737                     assert (nstatus == __GCONV_FULL_OUTPUT);
00738 
00739                     /* If we haven't consumed a single byte decrement
00740                       the invocation counter.  */
00741                     if (__builtin_expect (outbuf == outstart, 0))
00742                      --data->__invocation_counter;
00743 #endif /* reset input buffer */
00744                   }
00745 
00746                 /* Change the status.  */
00747                 status = result;
00748               }
00749              else
00750               /* All the output is consumed, we can make another run
00751                  if everything was ok.  */
00752               if (status == __GCONV_FULL_OUTPUT)
00753                 {
00754                   status = __GCONV_OK;
00755                   outbuf = data->__outbuf;
00756                 }
00757            }
00758 
00759          if (status != __GCONV_OK)
00760            break;
00761 
00762          /* Reset the output buffer pointer for the next round.  */
00763          outbuf = data->__outbuf;
00764        }
00765 
00766 #ifdef END_LOOP
00767       END_LOOP
00768 #endif
00769 
00770       /* If we are supposed to consume all character store now all of the
00771         remaining characters in the `state' object.  */
00772 #if FROM_LOOP_MAX_NEEDED_FROM > 1 || TO_LOOP_MAX_NEEDED_FROM > 1
00773       if (((FROM_LOOP_MAX_NEEDED_FROM > 1 && TO_LOOP_MAX_NEEDED_FROM > 1)
00774           || (FROM_LOOP_MAX_NEEDED_FROM > 1 && FROM_DIRECTION)
00775           || (TO_LOOP_MAX_NEEDED_FROM > 1 && !FROM_DIRECTION))
00776          && __builtin_expect (consume_incomplete, 0)
00777          && status == __GCONV_INCOMPLETE_INPUT)
00778        {
00779 # ifdef STORE_REST
00780          mbstate_t *state = data->__statep;
00781 
00782          STORE_REST
00783 # else
00784          /* Make sure the remaining bytes fit into the state objects
00785              buffer.  */
00786          assert (inend - *inptrp < 4);
00787 
00788          size_t cnt;
00789          for (cnt = 0; *inptrp < inend; ++cnt)
00790            data->__statep->__value.__wchb[cnt] = *(*inptrp)++;
00791          data->__statep->__count &= ~7;
00792          data->__statep->__count |= cnt;
00793 # endif
00794        }
00795 #endif
00796 #undef unaligned
00797 #undef POSSIBLY_UNALIGNED
00798     }
00799 
00800   return status;
00801 }
00802 
00803 #undef DEFINE_INIT
00804 #undef CHARSET_NAME
00805 #undef DEFINE_FINI
00806 #undef MIN_NEEDED_FROM
00807 #undef MIN_NEEDED_TO
00808 #undef MAX_NEEDED_FROM
00809 #undef MAX_NEEDED_TO
00810 #undef FROM_LOOP_MIN_NEEDED_FROM
00811 #undef FROM_LOOP_MAX_NEEDED_FROM
00812 #undef FROM_LOOP_MIN_NEEDED_TO
00813 #undef FROM_LOOP_MAX_NEEDED_TO
00814 #undef TO_LOOP_MIN_NEEDED_FROM
00815 #undef TO_LOOP_MAX_NEEDED_FROM
00816 #undef TO_LOOP_MIN_NEEDED_TO
00817 #undef TO_LOOP_MAX_NEEDED_TO
00818 #undef FROM_DIRECTION
00819 #undef EMIT_SHIFT_TO_INIT
00820 #undef FROM_LOOP
00821 #undef TO_LOOP
00822 #undef ONE_DIRECTION
00823 #undef SAVE_RESET_STATE
00824 #undef RESET_INPUT_BUFFER
00825 #undef FUNCTION_NAME
00826 #undef PREPARE_LOOP
00827 #undef END_LOOP
00828 #undef EXTRA_LOOP_ARGS
00829 #undef STORE_REST
00830 #undef FROM_ONEBYTE