From fd1b5c0fb6ca63dd76e833672be840cc4c3a7eff Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sun, 9 Apr 2000 17:43:29 +0000 Subject: Update. 2000-04-09 Ulrich Drepper Implement handling of restartable conversion functions according to ISO C. * iconv/gconv.h (__gconv_fct): Add additional parameter. * iconv/gconv_int.h (__BUILTIN_TRANS): Likewise. * iconv/gconv.c: Pass additional parameter to conversion function. * iconv/gconv_simple.c (internal_ucs4_loop_single): New function. (internal_ucs4le_loop_single): New function. (__gconv_transform_ascii_internal): Define ONE_DIRECTION. (__gconv_transform_internal_ascii): Likewise. (__gconv_transform_internal_utf8): Likewise. (__gconv_transform_utf8_internal): Likewise. (__gconv_transform_ucs2_internal): Likewise. (__gconv_transform_internal_ucs2): Likewise. (__gconv_transform_ucs2reverse_internal): Likewise. (__gconv_transform_internal_ucs2reverse): Likewise. (internal_ucs4le_loop_unaligned): Before return __GCONV_INCOMPLETE_INPUT check that the remaining bytes really form a valid character. Otherwise return __GCONV_ILLEGAL_INPUT. (__gconv_transform_utf8_internal): Define STORE_REST and UNPACK_BYTES. * iconv/loop.c: Fit in definition of function to convert one character for processing of left-over bytes from the state object. * iconv/skeleton.c (gconv): Rename inbuf to inptrp and inbufend to inend to match names in loop functions. (RESET_INPUT_BUFFER): Change apprpriately. (gconv): If needed, call function to process bytes from the state object. Similar at the end: store left over bytes if input is incomplete. Take extra argument and add new argument to all calls of the conversion function. * iconvdata/iso-2022-cn.c: Adjust numeric values used to store information in the state object to not conflict with length count. * iconvdata/iso-2022-jp.c: Likewise. * iconvdata/iso-2022-kr.c: Likewise. * iconvdata/unicode.c: Adjust for change change in parameters of skeleton function. * iconvdata/utf-16.c: Likewise. * libio/iofwide.c: Add new parameter to all calls of conversion function. * 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. * iconvdata/gbgbk.c: Always define MAX_NEEDED_OUTPUT and MAX_NEEDED_INPUT. --- iconv/skeleton.c | 100 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 82 insertions(+), 18 deletions(-) (limited to 'iconv/skeleton.c') diff --git a/iconv/skeleton.c b/iconv/skeleton.c index 27b1cab..50ee45d 100644 --- a/iconv/skeleton.c +++ b/iconv/skeleton.c @@ -192,11 +192,11 @@ static int to_object; (outbuf - outerr) is always divisible by MIN_NEEDED_TO. */ # define RESET_INPUT_BUFFER \ if (MIN_NEEDED_FROM % MIN_NEEDED_TO == 0) \ - *inbuf -= (outbuf - outerr) * (MIN_NEEDED_FROM / MIN_NEEDED_TO); \ + *inptrp -= (outbuf - outerr) * (MIN_NEEDED_FROM / MIN_NEEDED_TO); \ else if (MIN_NEEDED_TO % MIN_NEEDED_FROM == 0) \ - *inbuf -= (outbuf - outerr) / (MIN_NEEDED_TO / MIN_NEEDED_FROM); \ + *inptrp -= (outbuf - outerr) / (MIN_NEEDED_TO / MIN_NEEDED_FROM); \ else \ - *inbuf -= ((outbuf - outerr) / MIN_NEEDED_TO) * MIN_NEEDED_FROM + *inptrp -= ((outbuf - outerr) / MIN_NEEDED_TO) * MIN_NEEDED_FROM # endif #endif @@ -263,10 +263,15 @@ gconv_init (struct __gconv_step *step) # 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 + + int FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data, - const unsigned char **inbuf, const unsigned char *inbufend, - size_t *written, int do_flush) + const unsigned char **inptrp, const unsigned char *inend, + size_t *written, int do_flush, int consume_incomplete) { struct __gconv_step *next_step = step + 1; struct __gconv_step_data *next_data = data + 1; @@ -288,12 +293,12 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data, successfully emitted the escape sequence. */ if (status == __GCONV_OK && ! data->__is_last) status = DL_CALL_FCT (fct, (next_step, next_data, NULL, NULL, - written, 1)); + written, 1, consume_incomplete)); } else { /* We preserve the initial values of the pointer variables. */ - const unsigned char *inptr = *inbuf; + const unsigned char *inptr = *inptrp; unsigned char *outbuf = data->__outbuf; unsigned char *outend = data->__outbufend; unsigned char *outstart; @@ -314,6 +319,36 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data, PREPARE_LOOP #endif +#if MAX_NEEDED_FROM > 1 || MAX_NEEDED_TO > 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 (((MAX_NEEDED_FROM > 1 && FROM_DIRECTION) + || (MAX_NEEDED_TO > 1 && !FROM_DIRECTION)) + && consume_incomplete && (data->__statep->__count & 7) != 0) + { + /* Yep, we have some bytes left over. Process them now. */ + +# if MAX_NEEDED_FROM > 1 + if (MAX_NEEDED_TO == 1 || FROM_DIRECTION) + status = SINGLE(FROM_LOOP) (inptrp, inend, &outbuf, outend, + data->__statep, step->__data, + &converted EXTRA_LOOP_ARGS); +# endif +# if MAX_NEEDED_FROM > 1 && MAX_NEEDED_TO > 1 && !ONE_DIRECTION + else +# endif +# if MAX_NEEDED_TO > 1 && !ONE_DIRECTION + status = SINGLE(TO_LOOP) (inptrp, inend, &outbuf, outend, + data->__statep, step->__data, + &converted EXTRA_LOOP_ARGS); +# endif + + if (status != __GCONV_OK) + return status; + } +#endif + #if !defined _STRING_ARCH_unaligned \ && MIN_NEEDED_FROM != 1 && MAX_NEEDED_FROM % MIN_NEEDED_FROM == 0 \ && MIN_NEEDED_TO != 1 && MAX_NEEDED_TO % MIN_NEEDED_TO == 0 @@ -335,7 +370,7 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data, do { /* Remember the start value for this round. */ - inptr = *inbuf; + inptr = *inptrp; /* The outbuf buffer is empty. */ outstart = outbuf; @@ -347,12 +382,12 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data, { if (FROM_DIRECTION) /* Run the conversion loop. */ - status = FROM_LOOP (inbuf, inbufend, &outbuf, outend, + status = FROM_LOOP (inptrp, inend, &outbuf, outend, data->__statep, step->__data, &converted EXTRA_LOOP_ARGS); else /* Run the conversion loop. */ - status = TO_LOOP (inbuf, inbufend, &outbuf, outend, + status = TO_LOOP (inptrp, inend, &outbuf, outend, data->__statep, step->__data, &converted EXTRA_LOOP_ARGS); } @@ -363,13 +398,13 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data, { if (FROM_DIRECTION) /* Run the conversion loop. */ - status = GEN_unaligned (FROM_LOOP) (inbuf, inbufend, &outbuf, + status = GEN_unaligned (FROM_LOOP) (inptrp, inend, &outbuf, outend, data->__statep, step->__data, &converted EXTRA_LOOP_ARGS); else /* Run the conversion loop. */ - status = GEN_unaligned (TO_LOOP) (inbuf, inbufend, &outbuf, + status = GEN_unaligned (TO_LOOP) (inptrp, inend, &outbuf, outend, data->__statep, step->__data, &converted EXTRA_LOOP_ARGS); @@ -399,7 +434,8 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data, int result; result = DL_CALL_FCT (fct, (next_step, next_data, &outerr, - outbuf, written, 0)); + outbuf, written, 0, + consume_incomplete)); if (result != __GCONV_EMPTY_INPUT) { @@ -413,7 +449,7 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data, size_t nstatus; /* Reload the pointers. */ - *inbuf = inptr; + *inptrp = inptr; outbuf = outstart; /* Reset the state. */ @@ -423,16 +459,16 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data, if (FROM_DIRECTION) /* Run the conversion loop. */ - nstatus = FROM_LOOP ((const unsigned char **) inbuf, - (const unsigned char *) inbufend, + nstatus = FROM_LOOP ((const unsigned char **) inptrp, + (const unsigned char *) inend, (unsigned char **) &outbuf, (unsigned char *) outerr, data->__statep, step->__data, &converted EXTRA_LOOP_ARGS); else /* Run the conversion loop. */ - nstatus = TO_LOOP ((const unsigned char **) inbuf, - (const unsigned char *) inbufend, + nstatus = TO_LOOP ((const unsigned char **) inptrp, + (const unsigned char *) inend, (unsigned char **) &outbuf, (unsigned char *) outerr, data->__statep, step->__data, @@ -465,6 +501,32 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data, #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 MAX_NEEDED_FROM > 1 || MAX_NEEDED_TO > 1 + if (((MAX_NEEDED_FROM > 1 && FROM_DIRECTION) + || (MAX_NEEDED_TO > 1 && !FROM_DIRECTION)) + && consume_incomplete && status == __GCONV_INCOMPLETE_INPUT) + { +# ifdef STORE_REST + mbstate_t *state = data->__statep; + + STORE_REST +# else + size_t cnt; + + /* Make sure the remaining bytes fit into the state objects + buffer. */ + assert (inend - *inptrp < 4); + + for (cnt = 0; *inptrp < inend; ++cnt) + data->__statep->__value.__wchb[cnt] = *(*inptrp)++; + data->__statep->__count &= ~7; + data->__statep->__count |= cnt; +# endif + } +#endif } return status; @@ -487,3 +549,5 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data, #undef FUNCTION_NAME #undef PREPARE_LOOP #undef END_LOOP +#undef ONE_DIRECTION +#undef STORE_REST -- cgit v1.1