From: nobu.nakada@... Date: 2003-02-14T12:20:08+09:00 Subject: [ruby-dev:19565] Re: Fw: Ruby 1.8.0 bugs なかだです。 At Fri, 14 Feb 2003 11:09:23 +0900, Yukihiro Matsumoto wrote: > |> 1) line numbers reported by error messages are too small. > |> 2) file reading/writing is inconsistent. > | > |textmodeでmountしたディレクトリで改行コードCR+LFで実行すると、再現できました。 > |binmodeでmountしなおしたほうが不具合に遭いにくいと思います。 > > ありがとうございます。binmodeでmountしたほうが良いというのは > 以前にも聞いたことがありますが、 > > * これは一般的にそういうものなのでしょうか > * Ruby側で対処する必要があるものでしょうか 一般的にはバッファ内を調べて読む長さを決めるなんてことはしませ んから、Ruby側で対処する必要があると思います。 (A) バッファ内の検査を止める (B) cygwinでは常にバイナリモードにする (C) テキストモードだったら適当にfread()する長さを減らす。 結構I/Oのパフォーマンスに効いてくるのでできればAは避けたいです。 とりあえずCのパッチも作ってみましたが、なんとなくBがいいような 気もして来ました。 Index: io.c =================================================================== RCS file: /cvs/ruby/src/ruby/io.c,v retrieving revision 1.185 diff -u -2 -p -r1.185 io.c --- io.c 9 Feb 2003 18:36:22 -0000 1.185 +++ io.c 14 Feb 2003 03:02:58 -0000 @@ -848,4 +848,11 @@ io_read(argc, argv, io) } +#if defined(__CYGWIN__) && defined(__SCLE) +#define LINE_CONV_MODE(f) ((f)->_flags & __SCLE) +#endif +#ifndef LINE_CONV_MODE +#define LINE_CONV_MODE(f) (0) +#endif + static int appendline(fptr, delim, strp) @@ -870,5 +877,11 @@ appendline(fptr, delim, strp) const char *e = memchr(p, delim, pending); long last = 0, len = (c != EOF); - if (e) pending = e - p + 1; + if (e) { + pending = e - p + 1; +#ifdef LINE_CONV_MODE + if (LINE_CONV_MODE(f)) + pending = (pending + 1) >> 1; +#endif + } len += pending; if (!NIL_P(str)) { @@ -878,5 +891,4 @@ appendline(fptr, delim, strp) else { *strp = str = rb_str_buf_new(len); - RSTRING(str)->len = len; RSTRING(str)->ptr[len] = '\0'; } @@ -884,6 +896,26 @@ appendline(fptr, delim, strp) RSTRING(str)->ptr[last++] = c; } - fread(RSTRING(str)->ptr + last, 1, pending, f); /* must not fail */ - if (e) return delim; + len = fread(RSTRING(str)->ptr + last, 1, pending, f); + if (len < 0) rb_sys_fail(fptr->path); + if (len == 0) return EOF; + RSTRING(str)->len = last += len; + if (e && (!LINE_CONV_MODE(f) || RSTRING(str)->ptr[last - 1] == delim)) + return delim; +#ifdef LINE_CONV_MODE + if (LINE_CONV_MODE(f)) { + while ((pending = READ_DATA_PENDING_COUNT(f)) > 0) { + p = READ_DATA_PENDING_PTR(f); + e = memchr(p, delim, pending); + if (e) pending = ((e - p) >> 1) + 1; + rb_str_resize(str, last + pending); + len = fread(RSTRING(str)->ptr + last, 1, pending, f); + if (len < 0) rb_sys_fail(fptr->path); + if (len == 0) return EOF; + RSTRING(str)->len = last += len; + if (e && RSTRING(str)->ptr[last - 1] == delim) + return delim; + } + } +#endif } else if (c != EOF) { -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦