1.1 --- a/templates/native/iconv.c Mon Dec 12 18:00:17 2016 +0100
1.2 +++ b/templates/native/iconv.c Mon Dec 12 18:30:40 2016 +0100
1.3 @@ -35,19 +35,17 @@
1.4 __attr __fn_native_iconv_iconv(__attr __args[])
1.5 {
1.6 __attr * const cd = &__args[1];
1.7 - __attr * const instr = &__args[2];
1.8 - __attr * const state = &__args[3];
1.9 + __attr * const state = &__args[2];
1.10 /* cd interpreted as iconv_t */
1.11 iconv_t c = (iconv_t) cd->datavalue;
1.12 - /* instr.__data__ interpreted as string */
1.13 - char *inbuf = __load_via_object(instr->value, __pos___data__).strvalue;
1.14 /* state.__data__ interpreted as list */
1.15 __fragment *f = __load_via_object(state->value, __pos___data__).seqvalue;
1.16
1.17 - /* Obtain the start position from the state. */
1.18 + /* Obtain the string, start position, and remaining bytes from the state. */
1.19
1.20 - int start = __load_via_object(f->attrs[0].value, __pos___data__).intvalue;
1.21 - int remaining = __load_via_object(f->attrs[1].value, __pos___data__).intvalue;
1.22 + char *inbuf = __load_via_object(f->attrs[0].value, __pos___data__).strvalue;
1.23 + int start = __load_via_object(f->attrs[1].value, __pos___data__).intvalue;
1.24 + int remaining = __load_via_object(f->attrs[2].value, __pos___data__).intvalue;
1.25
1.26 /* Allocate a string for the output buffer using the remaining input size
1.27 as a guide. */
1.28 @@ -69,7 +67,7 @@
1.29
1.30 /* Return any string. */
1.31
1.32 - if ((result != -1) || (errno == E2BIG))
1.33 + if ((result != -1) || (errno == E2BIG) || (errno == EINVAL))
1.34 {
1.35 outbytestotal = outbufsize - outbytesleft;
1.36 resultbuf = __ALLOCATE(outbytestotal + 1, sizeof(char));
1.37 @@ -77,8 +75,14 @@
1.38
1.39 /* Mutate the state to indicate the next input buffer position. */
1.40
1.41 - f->attrs[0] = __new_int(start + remaining - inbytesleft);
1.42 - f->attrs[1] = __new_int(inbytesleft);
1.43 + f->attrs[1] = __new_int(start + remaining - inbytesleft);
1.44 + f->attrs[2] = __new_int(inbytesleft);
1.45 +
1.46 + /* Incomplete sequence: raise the string in an OSError instead. */
1.47 +
1.48 + if (errno == EINVAL)
1.49 + __raise_os_error(__new_int(errno), __new_str(resultbuf, outbytestotal));
1.50 +
1.51 return __new_str(resultbuf, outbytestotal);
1.52 }
1.53
1.54 @@ -91,15 +95,6 @@
1.55 __raise_os_error(__new_int(errno), __new_str(resultbuf, inbytesleft));
1.56 }
1.57
1.58 - /* Incomplete sequence. */
1.59 -
1.60 - else if (errno == EINVAL)
1.61 - {
1.62 - resultbuf = __ALLOCATE(inbytesleft + 1, sizeof(char));
1.63 - memcpy(resultbuf, inbuf, inbytesleft);
1.64 - __raise_os_error(__new_int(errno), __new_str(resultbuf, inbytesleft));
1.65 - }
1.66 -
1.67 /* General failure. */
1.68
1.69 else
1.70 @@ -144,6 +139,16 @@
1.71 return attr;
1.72 }
1.73
1.74 +__attr __fn_native_iconv_iconv_reset(__attr __args[])
1.75 +{
1.76 + __attr * const cd = &__args[1];
1.77 + /* cd interpreted as iconv_t */
1.78 + iconv_t c = (iconv_t) cd->datavalue;
1.79 +
1.80 + iconv(c, NULL, NULL, NULL, NULL);
1.81 + return __builtins___none_None;
1.82 +}
1.83 +
1.84 /* Module initialisation. */
1.85
1.86 void __main_native_iconv()