summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--ext/iconv/iconv.c92
2 files changed, 58 insertions, 43 deletions
diff --git a/ChangeLog b/ChangeLog
index 1f910097c2..752aee6c5c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Thu Oct 2 20:33:49 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/iconv/iconv.c (iconv_failure_initialize): conform with
+ orthodox initialization method.
+
+ * ext/iconv/iconv.c (iconv_fail): initialize exception instance
+ from the class, and do not share instance variables with the
+ others. [ruby-dev:21470]
+
Thu Oct 2 18:20:27 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
* time.c (Init_Time): define initialize. [ruby-dev:21469]
diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c
index 03e7dac0a7..8e978b8730 100644
--- a/ext/iconv/iconv.c
+++ b/ext/iconv/iconv.c
@@ -50,17 +50,17 @@ struct iconv_env_t
int argc;
VALUE *argv;
VALUE ret;
+ VALUE (*append)_((VALUE, VALUE));
};
static VALUE rb_eIconvFailure;
static VALUE rb_eIconvIllegalSeq;
static VALUE rb_eIconvInvalidChar;
static VALUE rb_eIconvOutOfRange;
-static ID rb_inserter;
-static ID rb_success, rb_failed, rb_mesg;
-static VALUE iconv_fail _((VALUE error, VALUE success, VALUE failed, struct iconv_env_t* env));
-static VALUE iconv_failure_initialize _((VALUE error, VALUE success, VALUE failed, struct iconv_env_t* env));
+static ID rb_success, rb_failed;
+static VALUE iconv_fail _((VALUE error, VALUE success, VALUE failed, struct iconv_env_t* env, const char *mesg));
+static VALUE iconv_failure_initialize _((VALUE error, VALUE mesg, VALUE success, VALUE failed));
static VALUE iconv_failure_success _((VALUE self));
static VALUE iconv_failure_failed _((VALUE self));
@@ -223,16 +223,16 @@ iconv_try
/* try the left in next loop */
break;
case EILSEQ:
- return rb_class_new_instance(0, 0, rb_eIconvIllegalSeq);
+ return rb_eIconvIllegalSeq;
case EINVAL:
- return rb_class_new_instance(0, 0, rb_eIconvInvalidChar);
+ return rb_eIconvInvalidChar;
default:
rb_sys_fail("iconv");
}
}
else if (*inlen > 0) {
/* something goes wrong */
- return rb_class_new_instance(0, 0, rb_eIconvIllegalSeq);
+ return rb_eIconvIllegalSeq;
}
else if (ret) {
return Qnil; /* conversion */
@@ -242,35 +242,15 @@ iconv_try
#define FAILED_MAXLEN 16
-static VALUE
-iconv_failure_initialize
+static VALUE iconv_failure_initialize
#ifdef HAVE_PROTOTYPES
- (VALUE error, VALUE success, VALUE failed, struct iconv_env_t* env)
+ (VALUE error, VALUE mesg, VALUE success, VALUE failed)
#else /* HAVE_PROTOTYPES */
- (error, success, failed, env)
- VALUE error;
- VALUE success;
- VALUE failed;
- struct iconv_env_t *env;
+ (error, mesg, success, failed)
+ VALUE error, mesg, success, failed;
#endif /* HAVE_PROTOTYPES */
{
- if (NIL_P(rb_attr_get(error, rb_mesg))) {
- if (TYPE(failed) != T_STRING || RSTRING(failed)->len < FAILED_MAXLEN) {
- rb_ivar_set(error, rb_mesg, rb_inspect(failed));
- }
- else {
- VALUE mesg = rb_inspect(rb_str_substr(failed, 0, FAILED_MAXLEN));
- rb_str_cat2(mesg, "...");
- rb_ivar_set(error, rb_mesg, mesg);
- }
- }
- if (env) {
- success = rb_funcall3(env->ret, rb_inserter, 1, &success);
- if (env->argc > 0) {
- *(env->argv) = failed;
- failed = rb_ary_new4(env->argc, env->argv);
- }
- }
+ rb_call_super(1, &mesg);
rb_ivar_set(error, rb_success, success);
rb_ivar_set(error, rb_failed, failed);
return error;
@@ -279,14 +259,36 @@ iconv_failure_initialize
static VALUE
iconv_fail
#ifdef HAVE_PROTOTYPES
- (VALUE error, VALUE success, VALUE failed, struct iconv_env_t* env)
+ (VALUE error, VALUE success, VALUE failed, struct iconv_env_t* env, const char *mesg)
#else /* HAVE_PROTOTYPES */
- (error, success, failed, env)
+ (error, success, failed, env, mesg)
VALUE error, success, failed;
struct iconv_env_t *env;
+ const char *mesg;
#endif /* HAVE_PROTOTYPES */
{
- error = iconv_failure_initialize(error, success, failed, env);
+ VALUE args[3];
+
+ if (mesg && *mesg) {
+ args[0] = rb_str_new2(mesg);
+ }
+ else if (TYPE(failed) != T_STRING || RSTRING(failed)->len < FAILED_MAXLEN) {
+ args[0] = rb_inspect(failed);
+ }
+ else {
+ args[0] = rb_inspect(rb_str_substr(failed, 0, FAILED_MAXLEN));
+ rb_str_cat2(args[0], "...");
+ }
+ args[1] = success;
+ args[2] = failed;
+ if (env) {
+ args[1] = env->append(rb_obj_dup(env->ret), success);
+ if (env->argc > 0) {
+ *(env->argv) = failed;
+ args[2] = rb_ary_new4(env->argc, env->argv);
+ }
+ }
+ error = rb_class_new_instance(3, args, error);
if (!rb_block_given_p()) rb_exc_raise(error);
ruby_errinfo = error;
return rb_yield(failed);
@@ -352,7 +354,7 @@ iconv_convert
error = iconv_try(cd, &inptr, &inlen, &outptr, &outlen);
if (RTEST(error)) {
unsigned int i;
- rescue = iconv_fail(error, Qnil, Qnil, env);
+ rescue = iconv_fail(error, Qnil, Qnil, env, 0);
if (TYPE(rescue) == T_ARRAY) {
str = RARRAY(rescue)->len > 0 ? RARRAY(rescue)->ptr[0] : Qnil;
}
@@ -388,10 +390,12 @@ iconv_convert
inlen = length;
do {
+ char errmsg[50];
const char *tmpstart = inptr;
outptr = buffer;
outlen = sizeof(buffer);
+ errmsg[0] = 0;
error = iconv_try(cd, &inptr, &inlen, &outptr, &outlen);
if (0 <= outlen && outlen <= sizeof(buffer)) {
@@ -422,9 +426,8 @@ iconv_convert
}
else {
/* Some iconv() have a bug, return *outlen out of range */
- char errmsg[50];
sprintf(errmsg, "bug?(output length = %d)", sizeof(buffer) - outlen);
- error = rb_exc_new2(rb_eIconvOutOfRange, errmsg);
+ error = rb_eIconvOutOfRange;
}
if (RTEST(error)) {
@@ -432,8 +435,10 @@ iconv_convert
if (!ret)
ret = rb_str_derive(str, instart, inptr - instart);
+ else if (inptr > instart)
+ rb_str_cat(ret, instart, inptr - instart);
str = rb_str_derive(str, inptr, inlen);
- rescue = iconv_fail(error, ret, str, env);
+ rescue = iconv_fail(error, ret, str, env, errmsg);
if (TYPE(rescue) == T_ARRAY) {
if ((len = RARRAY(rescue)->len) > 0)
rb_str_concat(ret, RARRAY(rescue)->ptr[0]);
@@ -568,13 +573,13 @@ iconv_s_convert
for (; env->argc > 0; --env->argc, ++env->argv) {
VALUE s = iconv_convert(env->cd, last = *(env->argv), 0, -1, env);
- rb_funcall3(env->ret, rb_inserter, 1, &s);
+ env->append(env->ret, s);
}
if (!NIL_P(last)) {
VALUE s = iconv_convert(env->cd, Qnil, 0, 0, env);
if (RSTRING(s)->len)
- rb_funcall3(env->ret, rb_inserter, 1, &s);
+ env->append(env->ret, s);
}
return env->ret;
@@ -598,6 +603,7 @@ iconv_s_iconv
arg.argc = argc -= 2;
arg.argv = argv + 2;
+ arg.append = rb_ary_push;
arg.ret = rb_ary_new2(argc);
arg.cd = iconv_create(argv[0], argv[1]);
return rb_ensure(iconv_s_convert, (VALUE)&arg, iconv_free, ICONV2VALUE(arg.cd));
@@ -616,6 +622,7 @@ iconv_s_conv
arg.argc = 1;
arg.argv = &str;
+ arg.append = rb_str_append;
arg.ret = rb_str_new(0, 0);
arg.cd = iconv_create(to, from);
return rb_ensure(iconv_s_convert, (VALUE)&arg, iconv_free, ICONV2VALUE(arg.cd));
@@ -840,6 +847,7 @@ Init_iconv _((void))
rb_define_method(rb_cIconv, "iconv", iconv_iconv, -1);
rb_eIconvFailure = rb_define_module_under(rb_cIconv, "Failure");
+ rb_define_method(rb_eIconvFailure, "initialize", iconv_failure_initialize, 3);
rb_define_method(rb_eIconvFailure, "success", iconv_failure_success, 0);
rb_define_method(rb_eIconvFailure, "failed", iconv_failure_failed, 0);
rb_define_method(rb_eIconvFailure, "inspect", iconv_failure_inspect, 0);
@@ -851,10 +859,8 @@ Init_iconv _((void))
rb_include_module(rb_eIconvInvalidChar, rb_eIconvFailure);
rb_include_module(rb_eIconvOutOfRange, rb_eIconvFailure);
- rb_inserter = rb_intern("<<");
rb_success = rb_intern("success");
rb_failed = rb_intern("failed");
- rb_mesg = rb_intern("mesg");
charset_map = rb_hash_new();
rb_gc_register_address(&charset_map);