aboutsummaryrefslogtreecommitdiff
path: root/lib/libiconv_modules/iconv_std/citrus_iconv_std.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libiconv_modules/iconv_std/citrus_iconv_std.c')
-rw-r--r--lib/libiconv_modules/iconv_std/citrus_iconv_std.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/lib/libiconv_modules/iconv_std/citrus_iconv_std.c b/lib/libiconv_modules/iconv_std/citrus_iconv_std.c
index ec9f21de541e..8eb9f6f7c5ba 100644
--- a/lib/libiconv_modules/iconv_std/citrus_iconv_std.c
+++ b/lib/libiconv_modules/iconv_std/citrus_iconv_std.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/* $NetBSD: citrus_iconv_std.c,v 1.16 2012/02/12 13:51:29 wiz Exp $ */
/*-
@@ -472,7 +471,7 @@ _citrus_iconv_std_iconv_convert(struct _citrus_iconv * __restrict cv,
_csid_t csid;
_index_t idx;
char *tmpin;
- size_t inval, szrin, szrout;
+ size_t inval, in_mb_cur_min, szrin, szrout;
int ret, state = 0;
inval = 0;
@@ -504,6 +503,8 @@ _citrus_iconv_std_iconv_convert(struct _citrus_iconv * __restrict cv,
return (0);
}
+ in_mb_cur_min = _stdenc_get_mb_cur_min(is->is_src_encoding);
+
/* normal case */
for (;;) {
if (*inbytes == 0) {
@@ -522,8 +523,20 @@ _citrus_iconv_std_iconv_convert(struct _citrus_iconv * __restrict cv,
szrin = szrout = 0;
ret = mbtocsx(&sc->sc_src_encoding, &csid, &idx, &tmpin,
*inbytes, &szrin, cv->cv_shared->ci_hooks);
- if (ret)
+ if (ret != 0 && (ret != EILSEQ ||
+ !cv->cv_shared->ci_discard_ilseq)) {
goto err;
+ } else if (ret == EILSEQ) {
+ /*
+ * If //IGNORE was specified, we'll just keep crunching
+ * through invalid characters.
+ */
+ *in += in_mb_cur_min;
+ *inbytes -= in_mb_cur_min;
+ restore_encoding_state(&sc->sc_src_encoding);
+ restore_encoding_state(&sc->sc_dst_encoding);
+ continue;
+ }
if (szrin == (size_t)-2) {
/* incompleted character */