[Gauche-devel-jp] formatがエラーを通知するバグ

Back to archive index

Rui Ueyama rui31****@gmail*****
2007年 2月 11日 (日) 00:07:27 JST


次のような式がエラーを通知する問題を修正するパッチです。

(format #t "~,,,,5s\n" #[あ])
=> *** ERROR: end argument out of range: 5

このバグは、Scm_WriteLimitedに渡されるオブジェクトの文字列表現が
マルチバイト文字列になるもので、かつテンポラリなDstringにバイト単位
で出力されるオブジェクトである場合に限り発現するようです。そのような
場合にマルチバイト文字の文字数の代わりに誤ってバイト数を使っている
ために、文字列の長さ以上のサブストリングを取得しようとして、エラーに
なっていました。

パッチなんですが、マルチバイト文字を扱う再にバイト数と文字数を混同
しているバグを修正しました。また、文字集合の出力で文字をバイトごと
に出力するのをやめ、1文字をそのままの単位で出力するようにしました。

-- 植山 類 <rui31****@gmail*****>
-------------- next part --------------
Index: ChangeLog
===================================================================
RCS file: /cvsroot/gauche/Gauche/ChangeLog,v
retrieving revision 1.1360
diff -u -r1.1360 ChangeLog
--- ChangeLog	5 Feb 2007 01:35:01 -0000	1.1360
+++ ChangeLog	10 Feb 2007 10:01:33 -0000
@@ -1,3 +1,11 @@
+2007-02-10  Rui Ueyama  <rui31****@gmail*****>
+
+	* src/char.c (charset_print): write a character at once instead of
+	  byte-by-byte.
+
+	* src/write.c: fixed a bug of handling multibyte character,
+	  causing Scm_WriteLimited to raise an error.
+
 2007-02-04  Shiro Kawai  <shiro****@acm*****>
 
 	* lib/www/cgi/test.scm: Renamed www.cgi-test module to www.cgi.test
Index: src/char.c
===================================================================
RCS file: /cvsroot/gauche/Gauche/src/char.c,v
retrieving revision 1.44
diff -u -r1.44 char.c
--- src/char.c	29 Apr 2006 10:14:08 -0000	1.44
+++ src/char.c	10 Feb 2007 10:01:33 -0000
@@ -198,12 +198,7 @@
     if (ch < 0x20 || ch == 0x7f) {
         Scm_Printf(out, "\\x%02x", ch);
     } else {
-        char chbuf[SCM_CHAR_MAX_BYTES];
-        int i;
-        SCM_CHAR_PUT(chbuf, ch);
-        for (i=0; i<SCM_CHAR_NBYTES(ch); i++) {
-            Scm_Printf(out, "%c", chbuf[i]);
-        }
+        Scm_Putc(ch, out);
     }
 }
 
Index: src/write.c
===================================================================
RCS file: /cvsroot/gauche/Gauche/src/write.c,v
retrieving revision 1.65
diff -u -r1.65 write.c
--- src/write.c	4 Feb 2007 12:39:59 -0000	1.65
+++ src/write.c	10 Feb 2007 10:01:33 -0000
@@ -115,16 +115,6 @@
    (SCM_VM_RUNTIME_FLAG_IS_SET(Scm_VM(), SCM_CASE_FOLD)? \
     SCM_WRITE_CASE_FOLD:SCM_WRITE_CASE_NOFOLD)
 
-static inline int outlen(ScmPort *out)
-{
-    SCM_ASSERT(SCM_PORT_TYPE(out) == SCM_PORT_OSTR);
-    if (out->src.ostr.length < 0) {
-        return Scm_DStringSize(&out->src.ostr);
-    } else {
-        return out->src.ostr.length;
-    }
-}
-
 /*
  * Scm_Write - Standard Write.
  */
@@ -180,6 +170,7 @@
 int Scm_WriteLimited(ScmObj obj, ScmObj port, int mode, int width)
 {
     ScmWriteContext ctx;
+    ScmString *str;
     ScmObj out;
     int nc, sharedp = FALSE;
     
@@ -201,14 +192,14 @@
     /* we don't need to lock out, for it is private. */
     sharedp = SCM_WRITE_MODE(&ctx) == SCM_WRITE_SHARED;
     format_write(obj, SCM_PORT(out), &ctx, sharedp);
-    nc = outlen(SCM_PORT(out));
+    str = SCM_STRING(Scm_GetOutputString(SCM_PORT(out), 0));
+    nc = SCM_STRING_BODY_LENGTH(SCM_STRING_BODY(str));
     if (nc > width) {
-        ScmObj sub = Scm_Substring(SCM_STRING(Scm_GetOutputString(SCM_PORT(out), 0)),
-                                   0, width, FALSE);
+        ScmObj sub = Scm_Substring(str, 0, width, FALSE);
         SCM_PUTS(sub, port);    /* this locks port */
         return -1;
     } else {
-        SCM_PUTS(Scm_GetOutputString(SCM_PORT(out), 0), port); /* this locks port */
+        SCM_PUTS(str, port);    /* this locks port */
         return nc;
     }
 }
@@ -220,6 +211,7 @@
 int Scm_WriteCircular(ScmObj obj, ScmObj port, int mode, int width)
 {
     ScmObj out;
+    ScmString *str;
     ScmWriteContext ctx;
     int nc;
 
@@ -255,14 +247,14 @@
     SCM_PORT(out)->data = SCM_PORT(port)->data;
     /* no need to lock out, for it is private */
     format_write(obj, SCM_PORT(out), &ctx, TRUE);
-    nc = outlen(SCM_PORT(out));
+    str = SCM_STRING(Scm_GetOutputString(SCM_PORT(out),0));
+    nc = SCM_STRING_BODY_LENGTH(SCM_STRING_BODY(str));
     if (nc > width) {
-        ScmObj sub = Scm_Substring(SCM_STRING(Scm_GetOutputString(SCM_PORT(out),0)),
-                                   0, width, FALSE);
-        SCM_PUTS(sub, port); /* this locks port */
+        ScmObj sub = Scm_Substring(str, 0, width, FALSE);
+        SCM_PUTS(sub, port);    /* this locks port */
         return -1;
     } else {
-        SCM_PUTS(Scm_GetOutputString(SCM_PORT(out),0), port); /* this locks port */
+        SCM_PUTS(str, port);    /* this locks port */
         return nc;
     }
 }
@@ -421,7 +413,7 @@
     ScmHashTable *ht = NULL;
 
     if (ctx->flags & WRITE_LIMITED) {
-        if (outlen(port) >= ctx->limit) return;
+        if (port->src.ostr.length >= ctx->limit) return;
     }
 
     if (SCM_PAIRP(port->data) && SCM_HASH_TABLE_P(SCM_CDR(port->data))) {


Gauche-devel-jp メーリングリストの案内
Back to archive index