diff options
author | Ulrich Drepper <drepper@redhat.com> | 2000-06-12 19:47:50 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2000-06-12 19:47:50 +0000 |
commit | 55985355ade2a038b567dd9b58153a98384ae703 (patch) | |
tree | b6252e23490e6d10d55ae926e30e32173f504190 /iconv/gconv_simple.c | |
parent | a5b97402f70a3cd43ffee9ccb71560457b4cd88c (diff) | |
download | glibc-55985355ade2a038b567dd9b58153a98384ae703.tar.gz glibc-55985355ade2a038b567dd9b58153a98384ae703.tar.xz glibc-55985355ade2a038b567dd9b58153a98384ae703.zip |
Update.
2000-06-12 Ulrich Drepper <drepper@redhat.com> * Rules (%.out): Define GCONV_PATH in the environment. * assert/Depend: New file. * iconvdata/Depend: New file. * intl/Depend: New file. * timezone/Makefile (build-testdata): Add GCONV_PATH to environment. * intl/tst-gettext.sh: Likewise. * iconv/Makefile (routines): Add gconv_trans. * iconv/gconv_trans.c: New file. * iconv/gconv.h (struct __gconv_trans_data): New type. (__gconv_fct): New parameter with starting position in output buffer. (__gconv_trans_fct, __gconv_trans_context_fct, __gconv_trans_query_fct, __gconv_trans_init_fct, __gconv_trans_end_fct): New types. (struct __gconv_step): Add new member __trans. * iconv/gconv_int.h: Pretty print prototypes. (gconv_transliterate): New prototype. (__BUILTIN_TRANS): Update for new conversion function interface. * iconv/gconv.c (__gconv): Pass new parameter to conversion function. * iconv/gconv_open.c (__gconv_open): Recognize error handling suffix in names, find appropriate function, and install in the conversion steps it can be used. * iconv/skeleton.c: Add additional parameter for beginning of output buffer. Change calls of downstream functions. * iconv/loop.c: Change loop function interface completely. Pass in step and step_data structure. Remove optimization for BODY with NEED_LENGTH_TEST == 0. * iconv/gconv_simple.c: Update interfaces of functions. Insert appropriate error handling code to use transliteration steps. Remove optimization for BODY with NEED_LENGTH_TEST == 0. * iconvdata/8bit-gap.c: Likewise. * iconvdata/8bit-generic.c: Likewise. * iconvdata/ansi_x3.110.c: Likewise. * iconvdata/big5.c: Likewise. * iconvdata/big5hkscs.c: Likewise. * iconvdata/euc-cn.c: Likewise. * iconvdata/euc-jp.c: Likewise. * iconvdata/euc-kr.c: Likewise. * iconvdata/euc-tw.c: Likewise. * iconvdata/gbgbk.c: Likewise. * iconvdata/gbk.c: Likewise. * iconvdata/iso-2022-cn.c: Likewise. * iconvdata/iso-2022-jp.c: Likewise. * iconvdata/iso-2022-kr.c: Likewise. * iconvdata/iso646.c: Likewise. * iconvdata/iso8859-1.c: Likewise. * iconvdata/iso_6937-2.c: Likewise. * iconvdata/iso_6937.c: Likewise. * iconvdata/johab.c: Likewise. * iconvdata/sjis.c: Likewise. * iconvdata/t.61.c: Likewise. * iconvdata/uhc.c: Likewise. * iconvdata/unicode.c: Likewise. * iconvdata/utf-16.c: Likewise. * libio/iofwide.c: Adjust to new interface of gconv functions. Use DL_CALL_FCT. * wcsmbs/btowc.c: Likewise. * wcsmbs/mbrtowc.c: Likewise. * wcsmbs/mbsnrtowcs.c: Likewise. * wcsmbs/mbsrtowcs.c: Likewise. * wcsmbs/wcrtomb.c: Likewise. * wcsmbs/wcsnrtombs.c: Likewise. * wcsmbs/wcsrtombs.c: Likewise. * wcsmbs/wctob.c: Likewise.
Diffstat (limited to 'iconv/gconv_simple.c')
-rw-r--r-- | iconv/gconv_simple.c | 177 |
1 files changed, 134 insertions, 43 deletions
diff --git a/iconv/gconv_simple.c b/iconv/gconv_simple.c index 4b7004caa6..188fc04c0e 100644 --- a/iconv/gconv_simple.c +++ b/iconv/gconv_simple.c @@ -19,6 +19,7 @@ Boston, MA 02111-1307, USA. */ #include <byteswap.h> +#include <dlfcn.h> #include <endian.h> #include <errno.h> #include <gconv.h> @@ -62,9 +63,10 @@ static const unsigned char encoding_byte[] = static inline int -internal_ucs4_loop (const unsigned char **inptrp, const unsigned char *inend, +internal_ucs4_loop (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, const unsigned char *inend, unsigned char **outptrp, unsigned char *outend, - mbstate_t *state, int flags, void *data, size_t *irreversible) { const unsigned char *inptr = *inptrp; @@ -102,10 +104,11 @@ internal_ucs4_loop (const unsigned char **inptrp, const unsigned char *inend, #ifndef _STRING_ARCH_unaligned static inline int -internal_ucs4_loop_unaligned (const unsigned char **inptrp, +internal_ucs4_loop_unaligned (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, const unsigned char *inend, unsigned char **outptrp, unsigned char *outend, - mbstate_t *state, int flags, void *data, size_t *irreversible) { const unsigned char *inptr = *inptrp; @@ -149,12 +152,14 @@ internal_ucs4_loop_unaligned (const unsigned char **inptrp, static inline int -internal_ucs4_loop_single (const unsigned char **inptrp, +internal_ucs4_loop_single (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, const unsigned char *inend, unsigned char **outptrp, unsigned char *outend, - mbstate_t *state, int flags, void *data, size_t *irreversible) { + mbstate_t *state = step_data->__statep; size_t cnt = state->__count & 7; while (*inptrp < inend && cnt < 4) @@ -205,11 +210,13 @@ internal_ucs4_loop_single (const unsigned char **inptrp, static inline int -ucs4_internal_loop (const unsigned char **inptrp, const unsigned char *inend, +ucs4_internal_loop (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, const unsigned char *inend, unsigned char **outptrp, unsigned char *outend, - mbstate_t *state, int flags, void *data, size_t *irreversible) { + int flags = step_data->__flags; const unsigned char *inptr = *inptrp; unsigned char *outptr = *outptrp; size_t n_convert = MIN (inend - inptr, outend - outptr) / 4; @@ -228,6 +235,10 @@ ucs4_internal_loop (const unsigned char **inptrp, const unsigned char *inend, if (__builtin_expect (inval, 0) > 0x7fffffff) { + /* The value is too large. We don't try transliteration here since + this is not an error because of the lack of possibilities to + represent the result. This is a genuine bug in the input since + UCS4 does not allow such values. */ if (flags & __GCONV_IGNORE_ERRORS) { /* Just ignore this character. */ @@ -259,23 +270,28 @@ ucs4_internal_loop (const unsigned char **inptrp, const unsigned char *inend, #ifndef _STRING_ARCH_unaligned static inline int -ucs4_internal_loop_unaligned (const unsigned char **inptrp, +ucs4_internal_loop_unaligned (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, const unsigned char *inend, unsigned char **outptrp, unsigned char *outend, - mbstate_t *state, int flags, void *data, size_t *irreversible) { + int flags = step_data->__flags; const unsigned char *inptr = *inptrp; unsigned char *outptr = *outptrp; size_t n_convert = MIN (inend - inptr, outend - outptr) / 4; int result; size_t cnt; - for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4, outptr += 4) + for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4) { if (__builtin_expect (inptr[0], 0) > 0x80) { - /* The value is too large. */ + /* The value is too large. We don't try transliteration here since + this is not an error because of the lack of possibilities to + represent the result. This is a genuine bug in the input since + UCS4 does not allow such values. */ if (flags & __GCONV_IGNORE_ERRORS) { /* Just ignore this character. */ @@ -299,6 +315,7 @@ ucs4_internal_loop_unaligned (const unsigned char **inptrp, outptr[2] = inptr[2]; outptr[3] = inptr[3]; # endif + outptr += 4; } *inptrp = inptr; @@ -318,12 +335,15 @@ ucs4_internal_loop_unaligned (const unsigned char **inptrp, static inline int -ucs4_internal_loop_single (const unsigned char **inptrp, +ucs4_internal_loop_single (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, const unsigned char *inend, unsigned char **outptrp, unsigned char *outend, - mbstate_t *state, int flags, void *data, size_t *irreversible) { + mbstate_t *state = step_data->__statep; + int flags = step_data->__flags; size_t cnt = state->__count & 7; while (*inptrp < inend && cnt < 4) @@ -341,7 +361,10 @@ ucs4_internal_loop_single (const unsigned char **inptrp, if (__builtin_expect (((unsigned char *) state->__value.__wchb)[0], 0) > 0x80) { - /* The value is too large. */ + /* The value is too large. We don't try transliteration here since + this is not an error because of the lack of possibilities to + represent the result. This is a genuine bug in the input since + UCS4 does not allow such values. */ if (!(flags & __GCONV_IGNORE_ERRORS)) { *inptrp -= cnt - (state->__count & 7); @@ -386,9 +409,10 @@ ucs4_internal_loop_single (const unsigned char **inptrp, static inline int -internal_ucs4le_loop (const unsigned char **inptrp, const unsigned char *inend, +internal_ucs4le_loop (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, const unsigned char *inend, unsigned char **outptrp, unsigned char *outend, - mbstate_t *state, int flags, void *data, size_t *irreversible) { const unsigned char *inptr = *inptrp; @@ -426,10 +450,11 @@ internal_ucs4le_loop (const unsigned char **inptrp, const unsigned char *inend, #ifndef _STRING_ARCH_unaligned static inline int -internal_ucs4le_loop_unaligned (const unsigned char **inptrp, +internal_ucs4le_loop_unaligned (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, const unsigned char *inend, unsigned char **outptrp, unsigned char *outend, - mbstate_t *state, int flags, void *data, size_t *irreversible) { const unsigned char *inptr = *inptrp; @@ -473,12 +498,14 @@ internal_ucs4le_loop_unaligned (const unsigned char **inptrp, static inline int -internal_ucs4le_loop_single (const unsigned char **inptrp, +internal_ucs4le_loop_single (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, const unsigned char *inend, unsigned char **outptrp, unsigned char *outend, - mbstate_t *state, int flags, void *data, size_t *irreversible) { + mbstate_t *state = step_data->__statep; size_t cnt = state->__count & 7; while (*inptrp < inend && cnt < 4) @@ -526,11 +553,13 @@ internal_ucs4le_loop_single (const unsigned char **inptrp, static inline int -ucs4le_internal_loop (const unsigned char **inptrp, const unsigned char *inend, +ucs4le_internal_loop (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, const unsigned char *inend, unsigned char **outptrp, unsigned char *outend, - mbstate_t *state, int flags, void *data, size_t *irreversible) { + int flags = step_data->__flags; const unsigned char *inptr = *inptrp; unsigned char *outptr = *outptrp; size_t n_convert = MIN (inend - inptr, outend - outptr) / 4; @@ -549,6 +578,10 @@ ucs4le_internal_loop (const unsigned char **inptrp, const unsigned char *inend, if (__builtin_expect (inval, 0) > 0x7fffffff) { + /* The value is too large. We don't try transliteration here since + this is not an error because of the lack of possibilities to + represent the result. This is a genuine bug in the input since + UCS4 does not allow such values. */ if (flags & __GCONV_IGNORE_ERRORS) { /* Just ignore this character. */ @@ -578,12 +611,14 @@ ucs4le_internal_loop (const unsigned char **inptrp, const unsigned char *inend, #ifndef _STRING_ARCH_unaligned static inline int -ucs4le_internal_loop_unaligned (const unsigned char **inptrp, +ucs4le_internal_loop_unaligned (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, const unsigned char *inend, unsigned char **outptrp, unsigned char *outend, - mbstate_t *state, int flags, void *data, size_t *irreversible) { + int flags = step_data->__flags; const unsigned char *inptr = *inptrp; unsigned char *outptr = *outptrp; size_t n_convert = MIN (inend - inptr, outend - outptr) / 4; @@ -594,7 +629,10 @@ ucs4le_internal_loop_unaligned (const unsigned char **inptrp, { if (__builtin_expect (inptr[3], 0) > 0x80) { - /* The value is too large. */ + /* The value is too large. We don't try transliteration here since + this is not an error because of the lack of possibilities to + represent the result. This is a genuine bug in the input since + UCS4 does not allow such values. */ if (flags & __GCONV_IGNORE_ERRORS) { /* Just ignore this character. */ @@ -639,12 +677,15 @@ ucs4le_internal_loop_unaligned (const unsigned char **inptrp, static inline int -ucs4le_internal_loop_single (const unsigned char **inptrp, +ucs4le_internal_loop_single (struct __gconv_step *step, + struct __gconv_step_data *step_data, + const unsigned char **inptrp, const unsigned char *inend, unsigned char **outptrp, unsigned char *outend, - mbstate_t *state, int flags, void *data, size_t *irreversible) { + mbstate_t *state = step_data->__statep; + int flags = step_data->__flags; size_t cnt = state->__count & 7; while (*inptrp < inend && cnt < 4) @@ -662,7 +703,10 @@ ucs4le_internal_loop_single (const unsigned char **inptrp, if (__builtin_expect (((unsigned char *) state->__value.__wchb)[3], 0) > 0x80) { - /* The value is too large. */ + /* The value is too large. We don't try transliteration here since + this is not an error because of the lack of possibilities to + represent the result. This is a genuine bug in the input since + UCS4 does not allow such values. */ if (!(flags & __GCONV_IGNORE_ERRORS)) return __GCONV_ILLEGAL_INPUT; } @@ -710,6 +754,10 @@ ucs4le_internal_loop_single (const unsigned char **inptrp, { \ if (__builtin_expect (*inptr, 0) > '\x7f') \ { \ + /* The value is too large. We don't try transliteration here since \ + this is not an error because of the lack of possibilities to \ + represent the result. This is a genuine bug in the input since \ + ASCII does not allow such values. */ \ if (! ignore_errors_p ()) \ { \ /* This is no correct ANSI_X3.4-1968 character. */ \ @@ -718,13 +766,14 @@ ucs4le_internal_loop_single (const unsigned char **inptrp, } \ \ ++*irreversible; \ - ++inptr; \ + ++inptr; \ } \ else \ /* It's an one byte sequence. */ \ /* XXX unaligned. */ \ *((uint32_t *) outptr)++ = *inptr++; \ } +#define LOOP_NEED_FLAGS #include <iconv/loop.c> #include <iconv/skeleton.c> @@ -740,6 +789,13 @@ ucs4le_internal_loop_single (const unsigned char **inptrp, #define FUNCTION_NAME __gconv_transform_internal_ascii #define ONE_DIRECTION 1 +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); + #define MIN_NEEDED_INPUT MIN_NEEDED_FROM #define MIN_NEEDED_OUTPUT MIN_NEEDED_TO #define LOOPFCT FROM_LOOP @@ -748,20 +804,31 @@ ucs4le_internal_loop_single (const unsigned char **inptrp, /* XXX unaligned. */ \ if (__builtin_expect (*((uint32_t *) inptr), 0) > 0x7f) \ { \ - if (! ignore_errors_p ()) \ + if (step_data->__trans.__trans_fct != NULL) \ + { \ + result = DL_CALL_FCT (step_data->__trans.__trans_fct, \ + (step, step_data, *inptrp, &inptr, inend, \ + *outptrp, &outptr, outend, irreversible)); \ + if (result != __GCONV_OK) \ + break; \ + } \ + else if (! ignore_errors_p ()) \ { \ /* This is no correct ANSI_X3.4-1968 character. */ \ result = __GCONV_ILLEGAL_INPUT; \ break; \ } \ - \ - ++*irreversible; \ - inptr += 4; \ + else \ + { \ + ++*irreversible; \ + inptr += 4; \ + } \ } \ else \ /* It's an one byte sequence. */ \ *outptr++ = *((uint32_t *) inptr)++; \ } +#define LOOP_NEED_FLAGS #include <iconv/loop.c> #include <iconv/skeleton.c> @@ -916,7 +983,7 @@ ucs4le_internal_loop_single (const unsigned char **inptrp, continue; \ } \ \ - if (NEED_LENGTH_TEST && __builtin_expect (inptr + cnt > inend, 0)) \ + if (__builtin_expect (inptr + cnt > inend, 0)) \ { \ /* We don't have enough input. But before we report that check \ that all the bytes are correct. */ \ @@ -979,6 +1046,7 @@ ucs4le_internal_loop_single (const unsigned char **inptrp, /* Now adjust the pointers and store the result. */ \ *((uint32_t *) outptr)++ = ch; \ } +#define LOOP_NEED_FLAGS #define STORE_REST \ { \ @@ -1125,18 +1193,29 @@ ucs4le_internal_loop_single (const unsigned char **inptrp, { \ if (__builtin_expect (*((uint32_t *) inptr), 0) >= 0x10000) \ { \ - if (! ignore_errors_p ()) \ + if (step_data->__trans.__trans_fct != NULL) \ + { \ + result = DL_CALL_FCT (step_data->__trans.__trans_fct, \ + (step, step_data, *inptrp, &inptr, inend, \ + *outptrp, &outptr, outend, irreversible)); \ + if (result != __GCONV_OK) \ + break; \ + } \ + else if (! ignore_errors_p ()) \ { \ result = __GCONV_ILLEGAL_INPUT; \ break; \ } \ - \ - inptr += 4; \ - ++*irreversible; \ + else \ + { \ + inptr += 4; \ + ++*irreversible; \ + } \ } \ else \ *((uint16_t *) outptr)++ = *((uint32_t *) inptr)++; \ } +#define LOOP_NEED_FLAGS #include <iconv/loop.c> #include <iconv/skeleton.c> @@ -1181,17 +1260,29 @@ ucs4le_internal_loop_single (const unsigned char **inptrp, uint32_t val = *((uint32_t *) inptr); \ if (__builtin_expect (val, 0) >= 0x10000) \ { \ - if (! ignore_errors_p ()) \ + if (step_data->__trans.__trans_fct != NULL) \ + { \ + result = DL_CALL_FCT (step_data->__trans.__trans_fct, \ + (step, step_data, *inptrp, &inptr, inend, \ + *outptrp, &outptr, outend, irreversible)); \ + if (result != __GCONV_OK) \ + break; \ + } \ + else if (! ignore_errors_p ()) \ { \ result = __GCONV_ILLEGAL_INPUT; \ break; \ } \ - \ - inptr += 4; \ - ++*irreversible; \ + else \ + { \ + inptr += 4; \ + ++*irreversible; \ + } \ + continue; \ } \ *((uint16_t *) outptr)++ = bswap_16 (val); \ inptr += 4; \ } +#define LOOP_NEED_FLAGS #include <iconv/loop.c> #include <iconv/skeleton.c> |