1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* ext/iconv/iconv.c (iconv_create): strips glibc style option before

charset mapping.  retris without options if they seemed causing
  error, and warns.  [ruby-dev:36147]


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@19147 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2008-09-05 09:16:34 +00:00
parent f0bf74a07b
commit 07e08245d3
2 changed files with 74 additions and 13 deletions

View file

@ -1,3 +1,9 @@
Fri Sep 5 18:16:31 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ext/iconv/iconv.c (iconv_create): strips glibc style option before
charset mapping. retris without options if they seemed causing
error, and warns. [ruby-dev:36147]
Fri Sep 5 03:09:48 2008 Koichi Sasada <ko1@atdot.net> Fri Sep 5 03:09:48 2008 Koichi Sasada <ko1@atdot.net>
* iseq.c (iseq_data_to_ary): make it static. * iseq.c (iseq_data_to_ary): make it static.

View file

@ -135,6 +135,21 @@ charset_map_get(void)
return charset_map; return charset_map;
} }
static VALUE
strip_glibc_option(VALUE *code)
{
VALUE val = *code;
const char *ptr = RSTRING_PTR(val), *pend = RSTRING_END(val);
const char *slash = memchr(ptr, '/', pend - ptr);
if (slash && slash < pend - 1 && slash[1] == '/') {
VALUE opt = rb_str_subseq(val, slash - ptr, pend - slash);
val = rb_str_subseq(val, 0, slash - ptr);
*code = val;
return opt;
}
return 0;
}
static char * static char *
map_charset(VALUE *code) map_charset(VALUE *code)
{ {
@ -153,29 +168,53 @@ map_charset(VALUE *code)
static iconv_t static iconv_t
iconv_create(VALUE to, VALUE from, struct rb_iconv_opt_t *opt, int *idx) iconv_create(VALUE to, VALUE from, struct rb_iconv_opt_t *opt, int *idx)
{ {
VALUE toopt = strip_glibc_option(&to);
VALUE fromopt = strip_glibc_option(&from);
VALUE toenc = 0, fromenc = 0;
const char* tocode = map_charset(&to); const char* tocode = map_charset(&to);
const char* fromcode = map_charset(&from); const char* fromcode = map_charset(&from);
iconv_t cd; iconv_t cd;
int retry = 0;
if ((*idx = rb_enc_find_index(tocode)) < 0) { *idx = rb_enc_find_index(tocode);
const char *slash = strchr(tocode, '/');
if (slash && slash[1] == '/') {
VALUE tmp = rb_str_new(tocode, slash - tocode);
*idx = rb_enc_find_index(RSTRING_PTR(tmp));
}
}
cd = iconv_open(tocode, fromcode); if (toopt) {
if (cd == (iconv_t)-1) { toenc = rb_str_plus(to, toopt);
tocode = RSTRING_PTR(toenc);
}
if (fromopt) {
fromenc = rb_str_plus(from, fromopt);
fromcode = RSTRING_PTR(fromenc);
}
while ((cd = iconv_open(tocode, fromcode)) == (iconv_t)-1) {
int inval = 0;
switch (errno) { switch (errno) {
case EMFILE: case EMFILE:
case ENFILE: case ENFILE:
case ENOMEM: case ENOMEM:
if (!retry++) {
rb_gc(); rb_gc();
cd = iconv_open(tocode, fromcode); continue;
} }
if (cd == (iconv_t)-1) { break;
int inval = errno == EINVAL; case EINVAL:
retry = 0;
inval = 1;
if (toenc) {
tocode = RSTRING_PTR(to);
rb_str_resize(toenc, 0);
toenc = 0;
continue;
}
if (fromenc) {
fromcode = RSTRING_PTR(from);
rb_str_resize(fromenc, 0);
fromenc = 0;
continue;
}
break;
}
{
const char *s = inval ? "invalid encoding " : "iconv"; const char *s = inval ? "invalid encoding " : "iconv";
volatile VALUE msg = rb_str_new(0, strlen(s) + RSTRING_LEN(to) + volatile VALUE msg = rb_str_new(0, strlen(s) + RSTRING_LEN(to) +
RSTRING_LEN(from) + 8); RSTRING_LEN(from) + 8);
@ -190,10 +229,25 @@ iconv_create(VALUE to, VALUE from, struct rb_iconv_opt_t *opt, int *idx)
} }
} }
if (toopt || fromopt) {
if (toopt && fromopt && RTEST(rb_str_equal(toopt, fromopt))) {
fromopt = 0;
}
if (toopt && fromopt) {
rb_warning("encoding option isn't portable: %s, %s",
RSTRING_PTR(toopt) + 2, RSTRING_PTR(fromopt) + 2);
}
else {
rb_warning("encoding option isn't portable: %s",
(toopt ? RSTRING_PTR(toopt) : RSTRING_PTR(fromopt)) + 2);
}
}
if (opt) { if (opt) {
#ifdef ICONV_SET_TRANSLITERATE #ifdef ICONV_SET_TRANSLITERATE
if (opt->transliterate != Qundef) { if (opt->transliterate != Qundef) {
int flag = RTEST(opt->transliterate); int flag = RTEST(opt->transliterate);
rb_warning("encoding option isn't portable: transliterate");
if (iconvctl(cd, ICONV_SET_TRANSLITERATE, (void *)&flag)) if (iconvctl(cd, ICONV_SET_TRANSLITERATE, (void *)&flag))
rb_sys_fail("ICONV_SET_TRANSLITERATE"); rb_sys_fail("ICONV_SET_TRANSLITERATE");
} }
@ -201,6 +255,7 @@ iconv_create(VALUE to, VALUE from, struct rb_iconv_opt_t *opt, int *idx)
#ifdef ICONV_SET_DISCARD_ILSEQ #ifdef ICONV_SET_DISCARD_ILSEQ
if (opt->discard_ilseq != Qundef) { if (opt->discard_ilseq != Qundef) {
int flag = RTEST(opt->discard_ilseq); int flag = RTEST(opt->discard_ilseq);
rb_warning("encoding option isn't portable: discard_ilseq");
if (iconvctl(cd, ICONV_SET_DISCARD_ILSEQ, (void *)&flag)) if (iconvctl(cd, ICONV_SET_DISCARD_ILSEQ, (void *)&flag))
rb_sys_fail("ICONV_SET_DISCARD_ILSEQ"); rb_sys_fail("ICONV_SET_DISCARD_ILSEQ");
} }