rem: r = utf8_decode_x(in, id + dip, iilen - dip,
add: r = utf8_decode_x(in, id + dip, iilen,
context: static char *do_convert(iconv_t cd,			/* if cd == -1 and either from_e or to_e can be NULL, then			   reset_locale() must have been called */			const char *from_e, const char *to_e,			/* 1 => UCS-4 -> UTF-8; 2 => UTF-8 -> UCS-4; 0 => other */			int to_from_utf8,			/* in can be NULL to output just a shift; in that case,			   id should be 0, too */			char *in, int id, int iilen,			char *out, int od, int iolen,			/* if grow, then reallocate when out isn't big enough */			int grow,			/* if add_end_shift, add a shift sequence to the end;			   not useful if in is already NULL to indicate a shift */			int add_end_shift,			/* extra specifies the length of a terminator,			   not included in iolen or *oolen */			int extra,			/* these two report actual read/wrote sizes: */			long *oilen, long *oolen,			/* status is set to			   0 for complete,			   -1 for partial input,			   -2 for error,			   1 for more avail */			int *status){  int dip, dop, close_it = 0, mz_utf8 = 0;  size_t il, ol, r;  GC_CAN_IGNORE char *ip, *op;  /* Defaults: */  *status = -1;  if (oilen)    *oilen = 0;  *oolen = 0;  if (cd == (iconv_t)-1) {    if (!iconv_ready) init_iconv();    if (iconv_open) {      if (!from_e)	from_e = mz_iconv_nl_langinfo();      if (!to_e)	to_e = mz_iconv_nl_langinfo();      cd = iconv_open(to_e, from_e);      close_it = 1;    } else if (to_from_utf8) {      /* Assume UTF-8 */      mz_utf8 = 1;    }  }  if ((cd == (iconv_t)-1) && !mz_utf8) {    if (out) {      while (extra--) {	out[extra] = 0;      }    }    return out;  }  /* The converter is ready. Allocate out space, if necessary */  if (!out) {    if (iolen <= 0)      iolen = iilen;    out = (char *)scheme_malloc_atomic(iolen + extra);    od = 0;  }  /* il and ol are the number of available chars */  il = iilen;  ol = iolen;  /* dip and dop are the number of characters read so far;     we use these and NULL out the ip and op pointers     for the sake of precise GC */  dip = 0;  dop = 0;  if (!in)    add_end_shift = 0;  while (1) {    int icerr;    if (mz_utf8) {      /* Use our UTF-8 routines as if they were iconv */      if (to_from_utf8 == 1) {	/* UCS-4 -> UTF-8 */	/* We assume that in + id and iilen are mzchar-aligned */	int opos, uid, uilen;	uid = (id + dip) >> 2;	uilen = (iilen - dip) >> 2;	opos = scheme_utf8_encode((const unsigned int *)in, uid, uilen,				  NULL, 0,				  0);	if (opos <= iolen) {	  opos = scheme_utf8_encode((const unsigned int *)in, uid, uilen,				    out, od + dop,				    0);	  dop += opos;	  dip += iilen;	  icerr = 0;	  r = (size_t)opos;	} else {	  icerr = E2BIG;	  r = (size_t)-1;	}      } else {	/* UTF-8 -> UCS-4 */	/* We assume that out + od is mzchar-aligned */	long ipos, opos;	r = utf8_decode_x(in, id + dip, iilen - dip,			  (unsigned int *)out, (od + dop) >> 2, iolen >> 2,			  &ipos, &opos,			  0, 0, NULL, 0, 0);	opos <<= 2;	dop += opos;	dip = (ipos - id);	if ((r == -1) || (r == -2)) {	  r = (size_t)-1;	  icerr = EILSEQ;	} else if (r == -3) {	  icerr = E2BIG;	  r = (size_t)-1;	} else	  icerr = 0;      }    } else  {      ip = in XFORM_OK_PLUS id + dip;      op = out XFORM_OK_PLUS od + dop;      r = iconv(cd, ICONV_ARG_CAST &ip, &il, &op, &ol);      dip = ip - (in XFORM_OK_PLUS id);      dop = op - (out XFORM_OK_PLUS od);      ip = op = NULL;      icerr = ICONV_errno;    }    /* Record how many chars processed, now */    if (oilen)      *oilen = dip;    *oolen = dop;    /* Got all the chars? */    if (r == (size_t)-1) {      if (icerr == E2BIG) {	if (grow) {	  /* Double the string size and try again */	  char *naya;	  naya = (char *)scheme_malloc_atomic((iolen * 2) + extra);	  memcpy(naya, out + od, *oolen);	  ol += iolen;	  iolen += iolen;	  out = naya;	  od = 0;	} else {	  *status = 1;	  if (close_it)	    iconv_close(cd);	  while (extra--) {	    out[od + dop + extra] = 0;	  }	  return out;	}      } else {	/* Either EINVAL (premature end) or EILSEQ (bad sequence) */	if (icerr == EILSEQ)	  *status = -2;	if (close_it)	  iconv_close(cd);	while (extra--) {	  out[od + dop + extra] = 0;	}	return out;      }    } else {      /* All done... */      if (add_end_shift) {	add_end_shift = 0;	in = NULL;	dip = 0;	id = 0;	il = 0; /* should be redundant */	oilen = NULL; /* so it doesn't get set to 0 */      } else {	*status = 0;	if (close_it)	  iconv_close(cd);	while (extra--) {	  out[od + dop + extra] = 0;	}	return out;      }    }  }}