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: iconvctl() support. [EXPERIMENTAL]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9514 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2005-11-07 11:55:48 +00:00
parent f4413f1487
commit 1aa48a4ea9
3 changed files with 340 additions and 15 deletions

View file

@ -1,3 +1,7 @@
Mon Nov 7 20:54:57 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ext/iconv/iconv.c: iconvctl() support. [EXPERIMENTAL]
Mon Nov 7 16:23:23 2005 NAKAMURA Usaku <usa@ruby-lang.org> Mon Nov 7 16:23:23 2005 NAKAMURA Usaku <usa@ruby-lang.org>
* ext/openssl/ossl.h: need to include winsock2.h before including * ext/openssl/ossl.h: need to include winsock2.h before including
@ -5,9 +9,9 @@ Mon Nov 7 16:23:23 2005 NAKAMURA Usaku <usa@ruby-lang.org>
Mon Nov 7 13:43:51 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> Mon Nov 7 13:43:51 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
* ext/tk/stubs.c (_nativethread_consistency_check): use simpler * ext/tk/stubs.c (_nativethread_consistency_check): use simpler
(low cost) way to check whether the Tcl interpreter was compiled (low cost) way to check whether the Tcl interpreter was compiled
with threads enabled of not. with threads enabled of not.
* ext/tk/tcltklib.c: reduce warnings. * ext/tk/tcltklib.c: reduce warnings.

View file

@ -83,6 +83,14 @@ struct iconv_env_t
VALUE (*append)_((VALUE, VALUE)); VALUE (*append)_((VALUE, VALUE));
}; };
struct rb_iconv_opt_t
{
VALUE transliterate;
VALUE discard_ilseq;
};
static ID id_transliterate, id_discard_ilseq;
static VALUE rb_eIconvInvalidEncoding; static VALUE rb_eIconvInvalidEncoding;
static VALUE rb_eIconvFailure; static VALUE rb_eIconvFailure;
static VALUE rb_eIconvIllegalSeq; static VALUE rb_eIconvIllegalSeq;
@ -96,20 +104,21 @@ static VALUE iconv_failure_initialize _((VALUE error, VALUE mesg, VALUE success,
static VALUE iconv_failure_success _((VALUE self)); static VALUE iconv_failure_success _((VALUE self));
static VALUE iconv_failure_failed _((VALUE self)); static VALUE iconv_failure_failed _((VALUE self));
static iconv_t iconv_create _((VALUE to, VALUE from)); static iconv_t iconv_create _((VALUE to, VALUE from, struct rb_iconv_opt_t *opt));
static void iconv_dfree _((void *cd)); static void iconv_dfree _((void *cd));
static VALUE iconv_free _((VALUE cd)); static VALUE iconv_free _((VALUE cd));
static VALUE iconv_try _((iconv_t cd, const char **inptr, size_t *inlen, char **outptr, size_t *outlen)); static VALUE iconv_try _((iconv_t cd, const char **inptr, size_t *inlen, char **outptr, size_t *outlen));
static VALUE rb_str_derive _((VALUE str, const char* ptr, int len)); static VALUE rb_str_derive _((VALUE str, const char* ptr, int len));
static VALUE iconv_convert _((iconv_t cd, VALUE str, int start, int length, struct iconv_env_t* env)); static VALUE iconv_convert _((iconv_t cd, VALUE str, int start, int length, struct iconv_env_t* env));
static VALUE iconv_s_allocate _((VALUE klass)); static VALUE iconv_s_allocate _((VALUE klass));
static VALUE iconv_initialize _((VALUE self, VALUE to, VALUE from)); static VALUE iconv_initialize _((int argc, VALUE *argv, VALUE self));
static VALUE iconv_s_open _((VALUE self, VALUE to, VALUE from)); static VALUE iconv_s_open _((int argc, VALUE *argv, VALUE self));
static VALUE iconv_s_convert _((struct iconv_env_t* env)); static VALUE iconv_s_convert _((struct iconv_env_t* env));
static VALUE iconv_s_iconv _((int argc, VALUE *argv, VALUE self)); static VALUE iconv_s_iconv _((int argc, VALUE *argv, VALUE self));
static VALUE iconv_init_state _((VALUE cd)); static VALUE iconv_init_state _((VALUE cd));
static VALUE iconv_finish _((VALUE self)); static VALUE iconv_finish _((VALUE self));
static VALUE iconv_iconv _((int argc, VALUE *argv, VALUE self)); static VALUE iconv_iconv _((int argc, VALUE *argv, VALUE self));
static VALUE iconv_conv _((int argc, VALUE *argv, VALUE self));
static VALUE charset_map; static VALUE charset_map;
@ -140,7 +149,7 @@ map_charset(VALUE *code)
} }
static iconv_t static iconv_t
iconv_create(VALUE to, VALUE from) iconv_create(VALUE to, VALUE from, struct rb_iconv_opt_t *opt)
{ {
const char* tocode = map_charset(&to); const char* tocode = map_charset(&to);
const char* fromcode = map_charset(&from); const char* fromcode = map_charset(&from);
@ -171,6 +180,24 @@ iconv_create(VALUE to, VALUE from)
} }
} }
if (opt) {
int flag;
#ifdef ICONV_SET_TRANSLITERATE
if (opt->transliterate != Qundef) {
flag = RTEST(opt->transliterate);
if (iconvctl(cd, ICONV_SET_TRANSLITERATE, (void *)&flag))
rb_sys_fail("ICONV_SET_TRANSLITERATE");
}
#endif
#ifdef ICONV_SET_DISCARD_ILSEQ
if (opt->discard_ilseq != Qundef) {
flag = RTEST(opt->discard_ilseq);
if (iconvctl(cd, ICONV_SET_DISCARD_ILSEQ, (void *)&flag))
rb_sys_fail("ICONV_SET_DISCARD_ILSEQ");
}
#endif
}
return cd; return cd;
} }
@ -436,9 +463,76 @@ iconv_s_allocate(VALUE klass)
return Data_Wrap_Struct(klass, 0, ICONV_FREE, 0); return Data_Wrap_Struct(klass, 0, ICONV_FREE, 0);
} }
static VALUE
get_iconv_opt_i(VALUE i, VALUE arg)
{
struct rb_iconv_opt_t *opt = (struct rb_iconv_opt_t *)arg;
VALUE name, val;
i = rb_Array(i);
name = rb_ary_entry(i, 0);
val = rb_ary_entry(i, 1);
do {
if (SYMBOL_P(name)) {
ID id = SYM2ID(name);
if (id == id_transliterate) {
#ifdef ICONV_SET_TRANSLITERATE
opt->transliterate = val;
#else
rb_notimplement();
#endif
break;
}
if (id == id_discard_ilseq) {
#ifdef ICONV_SET_DISCARD_ILSEQ
opt->discard_ilseq = val;
#else
rb_notimplement();
#endif
break;
}
}
else {
const char *s = StringValueCStr(name);
if (strcmp(s, "transliterate") == 0) {
#ifdef ICONV_SET_TRANSLITERATE
opt->transliterate = val;
#else
rb_notimplement();
#endif
break;
}
if (strcmp(s, "discard_ilseq") == 0) {
#ifdef ICONV_SET_DISCARD_ILSEQ
opt->discard_ilseq = val;
#else
rb_notimplement();
#endif
break;
}
}
name = rb_inspect(name);
rb_raise(rb_eArgError, "unknown option - %s", StringValueCStr(name));
} while (0);
return Qnil;
}
static void
get_iconv_opt(struct rb_iconv_opt_t *opt, VALUE options)
{
opt->transliterate = Qundef;
opt->discard_ilseq = Qundef;
if (!NIL_P(options)) {
rb_iterate(rb_each, options, get_iconv_opt_i, (VALUE)opt);
}
}
#define iconv_ctl(self, func, val) (\
iconvctl(VALUE2ICONV(check_iconv(self)), func, (void *)&(val)) ? \
rb_sys_fail(#func) : (void)0)
/* /*
* Document-method: new * Document-method: new
* call-seq: Iconv.new(to, from) * call-seq: Iconv.new(to, from, [options])
* *
* Creates new code converter from a coding-system designated with +from+ * Creates new code converter from a coding-system designated with +from+
* to another one designated with +to+. * to another one designated with +to+.
@ -447,6 +541,7 @@ iconv_s_allocate(VALUE klass)
* *
* +to+:: encoding name for destination * +to+:: encoding name for destination
* +from+:: encoding name for source * +from+:: encoding name for source
* +options+:: options for converter
* *
* === Exceptions * === Exceptions
* *
@ -455,11 +550,16 @@ iconv_s_allocate(VALUE klass)
* SystemCallError:: if <tt>iconv_open(3)</tt> fails * SystemCallError:: if <tt>iconv_open(3)</tt> fails
*/ */
static VALUE static VALUE
iconv_initialize(VALUE self, VALUE to, VALUE from) iconv_initialize(int argc, VALUE *argv, VALUE self)
{ {
VALUE to, from, options;
struct rb_iconv_opt_t opt;
rb_scan_args(argc, argv, "21", &to, &from, &options);
get_iconv_opt(&opt, options);
iconv_free(check_iconv(self)); iconv_free(check_iconv(self));
DATA_PTR(self) = NULL; DATA_PTR(self) = NULL;
DATA_PTR(self) = (void *)ICONV2VALUE(iconv_create(to, from)); DATA_PTR(self) = (void *)ICONV2VALUE(iconv_create(to, from, &opt));
return self; return self;
} }
@ -472,9 +572,14 @@ iconv_initialize(VALUE self, VALUE to, VALUE from)
* returned from the block. * returned from the block.
*/ */
static VALUE static VALUE
iconv_s_open(VALUE self, VALUE to, VALUE from) iconv_s_open(int argc, VALUE *argv, VALUE self)
{ {
VALUE cd = ICONV2VALUE(iconv_create(to, from)); VALUE to, from, options, cd;
struct rb_iconv_opt_t opt;
rb_scan_args(argc, argv, "21", &to, &from, &options);
get_iconv_opt(&opt, options);
cd = ICONV2VALUE(iconv_create(to, from, &opt));
self = Data_Wrap_Struct(self, NULL, ICONV_FREE, (void *)cd); self = Data_Wrap_Struct(self, NULL, ICONV_FREE, (void *)cd);
if (rb_block_given_p()) { if (rb_block_given_p()) {
@ -534,7 +639,7 @@ iconv_s_iconv(int argc, VALUE *argv, VALUE self)
arg.argv = argv + 2; arg.argv = argv + 2;
arg.append = rb_ary_push; arg.append = rb_ary_push;
arg.ret = rb_ary_new2(argc); arg.ret = rb_ary_new2(argc);
arg.cd = iconv_create(argv[0], argv[1]); arg.cd = iconv_create(argv[0], argv[1], NULL);
return rb_ensure(iconv_s_convert, (VALUE)&arg, iconv_free, ICONV2VALUE(arg.cd)); return rb_ensure(iconv_s_convert, (VALUE)&arg, iconv_free, ICONV2VALUE(arg.cd));
} }
@ -555,7 +660,7 @@ iconv_s_conv(VALUE self, VALUE to, VALUE from, VALUE str)
arg.argv = &str; arg.argv = &str;
arg.append = rb_str_append; arg.append = rb_str_append;
arg.ret = rb_str_new(0, 0); arg.ret = rb_str_new(0, 0);
arg.cd = iconv_create(to, from); arg.cd = iconv_create(to, from, NULL);
return rb_ensure(iconv_s_convert, (VALUE)&arg, iconv_free, ICONV2VALUE(arg.cd)); return rb_ensure(iconv_s_convert, (VALUE)&arg, iconv_free, ICONV2VALUE(arg.cd));
} }
@ -693,6 +798,160 @@ iconv_iconv(int argc, VALUE *argv, VALUE self)
NULL); NULL);
} }
/*
* Document-method: conv
* call-seq: conv(str...)
*
* Equivalent to
*
* iconv(nil, str..., nil).join
*/
static VALUE
iconv_conv(int argc, VALUE *argv, VALUE self)
{
iconv_t cd = VALUE2ICONV(check_iconv(self));
VALUE str, s;
str = iconv_convert(cd, Qnil, 0, 0, NULL);
if (argc > 0) {
do {
s = iconv_convert(cd, *argv++, 0, -1, NULL);
if (RSTRING(s)->len)
rb_str_buf_append(str, s);
else
str = s;
} while (--argc);
s = iconv_convert(cd, Qnil, 0, 0, NULL);
if (RSTRING(s)->len)
rb_str_buf_append(str, s);
else
str = s;
}
return str;
}
/*
* Document-method: trivial?
* call-seq: trivial?
*
* Returns trivial flag.
*/
static VALUE
iconv_trivialp(VALUE self)
{
#ifdef ICONV_TRIVIALP
int trivial = 0;
iconv_ctl(self, ICONV_TRIVIALP, trivial);
if (trivial) return Qtrue;
#else
rb_notimplement();
#endif
return Qfalse;
}
/*
* Document-method: transliterate?
* call-seq: transliterate?
*
* Returns transliterate flag.
*/
static VALUE
iconv_get_transliterate(VALUE self)
{
#ifdef ICONV_GET_TRANSLITERATE
int trans = 0;
iconv_ctl(self, ICONV_GET_TRANSLITERATE, trans);
if (trans) return Qtrue;
#else
rb_notimplement();
#endif
return Qfalse;
}
/*
* Document-method: transliterate=
* call-seq: cd.transliterate = flag
*
* Sets transliterate flag.
*/
static VALUE
iconv_set_transliterate(VALUE self, VALUE transliterate)
{
#ifdef ICONV_SET_TRANSLITERATE
int trans = RTEST(transliterate);
iconv_ctl(self, ICONV_SET_TRANSLITERATE, trans);
#else
rb_notimplement();
#endif
return self;
}
/*
* Document-method: discard_ilseq?
* call-seq: discard_ilseq?
*
* Returns discard_ilseq flag.
*/
static VALUE
iconv_get_discard_ilseq(VALUE self)
{
#ifdef ICONV_GET_DISCARD_ILSEQ
int dis = 0;
iconv_ctl(self, ICONV_GET_DISCARD_ILSEQ, dis);
if (dis) return Qtrue;
#else
rb_notimplement();
#endif
return Qfalse;
}
/*
* Document-method: discard_ilseq=
* call-seq: cd.discard_ilseq = flag
*
* Sets discard_ilseq flag.
*/
static VALUE
iconv_set_discard_ilseq(VALUE self, VALUE discard_ilseq)
{
#ifdef ICONV_SET_DISCARD_ILSEQ
int dis = RTEST(discard_ilseq);
iconv_ctl(self, ICONV_SET_DISCARD_ILSEQ, dis);
#else
rb_notimplement();
#endif
return self;
}
/*
* Document-method: ctlmethods
* call-seq: Iconv.ctlmethods => array
*
* Returns available iconvctl() method list.
*/
static VALUE
iconv_s_ctlmethods(VALUE klass)
{
VALUE ary = rb_ary_new();
#ifdef ICONV_TRIVIALP
rb_ary_push(ary, ID2SYM(rb_intern("trivial?")));
#endif
#ifdef ICONV_GET_TRANSLITERATE
rb_ary_push(ary, ID2SYM(rb_intern("transliterate?")));
#endif
#ifdef ICONV_SET_TRANSLITERATE
rb_ary_push(ary, ID2SYM(rb_intern("transliterate=")));
#endif
#ifdef ICONV_GET_DISCARD_ILSEQ
rb_ary_push(ary, ID2SYM(rb_intern("discard_ilseq?")));
#endif
#ifdef ICONV_SET_DISCARD_ILSEQ
rb_ary_push(ary, ID2SYM(rb_intern("discard_ilseq=")));
#endif
return ary;
}
/* /*
* Document-class: Iconv::Failure * Document-class: Iconv::Failure
* *
@ -787,13 +1046,20 @@ Init_iconv(void)
VALUE rb_cIconv = rb_define_class("Iconv", rb_cData); VALUE rb_cIconv = rb_define_class("Iconv", rb_cData);
rb_define_alloc_func(rb_cIconv, iconv_s_allocate); rb_define_alloc_func(rb_cIconv, iconv_s_allocate);
rb_define_singleton_method(rb_cIconv, "open", iconv_s_open, 2); rb_define_singleton_method(rb_cIconv, "open", iconv_s_open, -1);
rb_define_singleton_method(rb_cIconv, "iconv", iconv_s_iconv, -1); rb_define_singleton_method(rb_cIconv, "iconv", iconv_s_iconv, -1);
rb_define_singleton_method(rb_cIconv, "conv", iconv_s_conv, 3); rb_define_singleton_method(rb_cIconv, "conv", iconv_s_conv, 3);
rb_define_singleton_method(rb_cIconv, "list", iconv_s_list, 0); rb_define_singleton_method(rb_cIconv, "list", iconv_s_list, 0);
rb_define_method(rb_cIconv, "initialize", iconv_initialize, 2); rb_define_singleton_method(rb_cIconv, "ctlmethods", iconv_s_ctlmethods, 0);
rb_define_method(rb_cIconv, "initialize", iconv_initialize, -1);
rb_define_method(rb_cIconv, "close", iconv_finish, 0); rb_define_method(rb_cIconv, "close", iconv_finish, 0);
rb_define_method(rb_cIconv, "iconv", iconv_iconv, -1); rb_define_method(rb_cIconv, "iconv", iconv_iconv, -1);
rb_define_method(rb_cIconv, "conv", iconv_conv, -1);
rb_define_method(rb_cIconv, "trivial?", iconv_trivialp, 0);
rb_define_method(rb_cIconv, "transliterate?", iconv_get_transliterate, 0);
rb_define_method(rb_cIconv, "transliterate=", iconv_set_transliterate, 1);
rb_define_method(rb_cIconv, "discard_ilseq?", iconv_get_discard_ilseq, 0);
rb_define_method(rb_cIconv, "discard_ilseq=", iconv_set_discard_ilseq, 1);
rb_eIconvFailure = rb_define_module_under(rb_cIconv, "Failure"); rb_eIconvFailure = rb_define_module_under(rb_cIconv, "Failure");
rb_define_method(rb_eIconvFailure, "initialize", iconv_failure_initialize, 3); rb_define_method(rb_eIconvFailure, "initialize", iconv_failure_initialize, 3);
@ -814,6 +1080,8 @@ Init_iconv(void)
rb_success = rb_intern("success"); rb_success = rb_intern("success");
rb_failed = rb_intern("failed"); rb_failed = rb_intern("failed");
id_transliterate = rb_intern("transliterate");
id_discard_ilseq = rb_intern("discard_ilseq");
charset_map = rb_hash_new(); charset_map = rb_hash_new();
rb_gc_register_address(&charset_map); rb_gc_register_address(&charset_map);

53
ext/iconv/mkwrapper.rb Normal file
View file

@ -0,0 +1,53 @@
#! /usr/bin/ruby
require 'rbconfig'
require 'optparse'
# http://www.ctan.org/tex-archive/macros/texinfo/texinfo/intl/config.charset
# Fri, 30 May 2003 00:09:00 GMT'
HEADER = <<SRC
require 'iconv.so'
class Iconv
case RUBY_PLATFORM
SRC
def charset_alias(config_charset, mapfile = nil)
found = nil
src = [HEADER]
open(config_charset) do |input|
input.find {|line| /^case "\$os" in/ =~ line} or return
input.each do |line|
case line
when /^\s*([-\w\*]+(?:\s*\|\s*[-\w\*]+)*)(?=\))/
(s = " when ") << $&.split('|').collect {|targ|
targ.strip!
tail = targ.chomp!("*") ? '' : '\z'
head = targ.slice!(/\A\*/) ? '' : '\A'
targ.gsub!(/\*/, '.*')
"/#{head}#{targ}#{tail}/"
}.join(", ")
src << s
found = {}
when /^\s*echo "(?:\$\w+\.)?([-\w*]+)\s+([-\w]+)"/
sys, can = $1, $2
can.downcase!
unless found[can] or (/\Aen_(?!US\z)/ =~ sys && /\ACP437\z/i =~ can)
found[can] = true
src << " charset_map['#{can}'] = '#{sys}'.freeze"
end
when /^\s*;;/
found = nil
end
end
end
src << " end" << "end"
if mapfile
open(mapfile, "wb") {|f| f.puts *src}
else
puts *src
end
end
(1..2) === ARGV.size or abort "usage: #{$0} config_charset [mapfile]"
charset_alias(*ARGV)