なかだです。

At Sun, 5 Jan 2003 19:01:51 +0900,
U.Nakamura <usa / osb.att.ne.jp> wrote:
> > > bccwin32はfflush()では救えなかったので対処してません。
> > > fseek(fp, SEEK_CUR, 0)はOKっぽいので、下記のパッチのような方
> > > 法でこの問題自体は潰せますが、なんか他にもいろいろありそうな
> > > 感じだったので深く踏み込んではいません。
> > 
> > そもそもR/Wの切り替えのときには、fflushではなくてfseekしたほう
> > がいいような気がして来ました。
> 
> Cの規格によると、WからRはfflushでもいいけどRからWはfseek(か
> その類)じゃないといけないとなってるので、fseekの方が無難だろ
> うと思います。bccのような例もあるし。

元々fseekを使えばいいはずというのが頭にあったんですが、なぜか途
中でfflushに化けてしまったようです。

> ところで、1.6はどうしましょう?
> [ruby-dev:18439]にパッチはあるのですが、commitされてないのは
> なんででしたっけ?

忘れてました。パッチは作り直しました。


Index: configure.in =================================================================== RCS file: /cvs/ruby/src/ruby/configure.in,v retrieving revision 1.68.2.41 diff -u -2 -p -r1.68.2.41 configure.in --- configure.in 31 Dec 2002 11:24:47 -0000 1.68.2.41 +++ configure.in 5 Jan 2003 16:07:24 -0000 @@ -243,8 +243,12 @@ human*) ac_cv_func_getpgrp_void=yes;; beos*) ;; cygwin*) rb_cv_have_daylight=no + rb_cv_need_io_seek_between_rw=no + rb_cv_need_io_flush_before_seek=no ac_cv_var_tzname=no ac_cv_func_setitimer=no ;; mingw*) LIBS="-lwsock32 -lmsvcrt $LIBS" + rb_cv_need_io_seek_between_rw=yes + rb_cv_need_io_flush_before_seek=no ac_cv_header_a_out_h=no ac_cv_header_pwd_h=no @@ -457,4 +461,62 @@ else fi +AC_DEFUN(RUBY_CHECK_IO_NEED, +[AC_CACHE_CHECK(whether need to [$1], [$2], + [AC_TRY_RUN([ +#include <stdio.h> +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif +#define before_seek(f) ]ifelse(index($2,flush_before_seek),-1,[fflush(f)],[(f,0)])[ +#define reset_rw(f) ]ifelse(index($2,seek_between_rw),-1,[do_seek(f,SEEK_CUR)],[(f,0)])[ +#define do_seek(f, w) (before_seek(f), fseek(f,0,w)) + +char *fn = "conftest.dat"; +char *wombat = "wombat\n"; +char *koara = "koara\n"; + +int main() +{ + char buf[BUFSIZ]; + FILE *f; + int r = 1; + + if (!(f = fopen(fn, "w+"))) return 1; + fputs(wombat, f); + do_seek(f, SEEK_SET); + if (!fgets(buf, BUFSIZ, f) || strcmp(buf, wombat)) goto fail; + reset_rw(f); + fputs(koara, f); + do_seek(f, SEEK_SET); + if (!fgets(buf, BUFSIZ, f) || strcmp(buf, wombat)) goto fail; + if (!fgets(buf, BUFSIZ, f) || strcmp(buf, koara)) goto fail; + r = 0; + fail: + fclose(f); + unlink(fn); + return r; +} +], [$2]=no, [$2]=yes, [$2]=yes)])]) +RUBY_CHECK_IO_NEED(seek between R/W, rb_cv_need_io_seek_between_rw) +RUBY_CHECK_IO_NEED(flush before seek, rb_cv_need_io_flush_before_seek) +check_do_something_else=no +if test "$rb_cv_need_io_seek_between_rw" = yes; then + AC_DEFINE(NEED_IO_SEEK_BETWEEN_RW, 1) + check_do_something_else=yes +fi +if test "$rb_cv_need_io_flush_before_seek" = yes; then + AC_DEFINE(NEED_IO_FLUSH_BEFORE_SEEK, 1) + check_do_something_else=yes +fi +if test "$cross_compiling" = no -a "$check_do_something_else" = yes; then + RUBY_CHECK_IO_NEED(do something else, unexpected_stdio_behavior) + if test "$unexpected_stdio_behavior" = yes; then + AC_MSG_FAILURE([unexpected stdio behavior]) + fi +fi + dnl default value for $KANJI DEFAULT_KCODE="KCODE_NONE" Index: io.c =================================================================== RCS file: /cvs/ruby/src/ruby/io.c,v retrieving revision 1.69.2.29 diff -u -2 -p -r1.69.2.29 io.c --- io.c 31 Dec 2002 17:23:29 -0000 1.69.2.29 +++ io.c 5 Jan 2003 15:25:36 -0000 @@ -152,4 +152,29 @@ rb_io_check_closed(fptr) } +static void io_fflush _((FILE *, const char *)); + +#if NEED_IO_FLUSH_BEFORE_SEEK +static OpenFile * +flush_before_seek(fptr) + OpenFile *fptr; +{ + if (fptr->mode & FMODE_WBUF) { + io_fflush(GetWriteFile(fptr), fptr); + } + return fptr; +} +#else +#define flush_before_seek(fptr) fptr +#endif + +#define io_seek(fptr, ofs, whence) fseek(flush_before_seek(fptr)->f, ofs, whence) +#define io_tell(fptr) ftell(flush_before_seek(fptr)->f) + +#ifndef SEEK_CUR +# define SEEK_SET 0 +# define SEEK_CUR 1 +# define SEEK_END 2 +#endif + void rb_io_check_readable(fptr) @@ -159,4 +184,11 @@ rb_io_check_readable(fptr) rb_raise(rb_eIOError, "not opened for reading"); } +#if NEED_IO_SEEK_BETWEEN_RW + if ((fptr->mode & FMODE_WBUF) && !fptr->f2) { + io_seek(fptr, 0, SEEK_CUR); + fptr->mode &= ~FMODE_WBUF; + } + fptr->mode |= FMODE_RBUF; +#endif } @@ -168,4 +200,10 @@ rb_io_check_writable(fptr) rb_raise(rb_eIOError, "not opened for writing"); } +#if NEED_IO_SEEK_BETWEEN_RW + if ((fptr->mode & FMODE_RBUF) && !fptr->f2) { + io_seek(fptr, 0, SEEK_CUR); + fptr->mode &= ~FMODE_RBUF; + } +#endif } @@ -305,5 +343,5 @@ rb_io_tell(io) GetOpenFile(io, fptr); - pos = ftell(fptr->f); + pos = io_tell(fptr); if (ferror(fptr->f)) rb_sys_fail(fptr->path); @@ -311,10 +349,4 @@ rb_io_tell(io) } -#ifndef SEEK_CUR -# define SEEK_SET 0 -# define SEEK_CUR 1 -# define SEEK_END 2 -#endif - static VALUE rb_io_seek(argc, argv, io) @@ -333,5 +365,5 @@ rb_io_seek(argc, argv, io) GetOpenFile(io, fptr); - pos = fseek(fptr->f, NUM2INT(offset), whence); + pos = io_seek(fptr, NUM2INT(offset), whence); if (pos != 0) rb_sys_fail(fptr->path); clearerr(fptr->f); @@ -348,5 +380,5 @@ rb_io_set_pos(io, offset) GetOpenFile(io, fptr); - pos = fseek(fptr->f, NUM2INT(offset), SEEK_SET); + pos = io_seek(fptr, NUM2INT(offset), SEEK_SET); if (pos != 0) rb_sys_fail(fptr->path); clearerr(fptr->f); @@ -362,5 +394,5 @@ rb_io_rewind(io) GetOpenFile(io, fptr); - if (fseek(fptr->f, 0L, 0) != 0) rb_sys_fail(fptr->path); + if (io_seek(fptr, 0L, 0) != 0) rb_sys_fail(fptr->path); clearerr(fptr->f); if (io == current_file) { @@ -518,5 +550,5 @@ read_all(port) ) { - pos = ftell(fptr->f); + pos = io_tell(fptr); if (st.st_size > pos && pos >= 0) { siz = st.st_size - pos + 1; @@ -1853,6 +1885,6 @@ io_reopen(io, nfile) } if ((orig->mode & FMODE_READABLE) && pos >= 0) { - fseek(fptr->f, pos, SEEK_SET); - fseek(orig->f, pos, SEEK_SET); + io_seek(fptr, pos, SEEK_SET); + io_seek(orig, pos, SEEK_SET); } Index: rubyio.h =================================================================== RCS file: /cvs/ruby/src/ruby/rubyio.h,v retrieving revision 1.9.2.1 diff -u -2 -p -r1.9.2.1 rubyio.h --- rubyio.h 17 Dec 2001 08:13:17 -0000 1.9.2.1 +++ rubyio.h 2 Oct 2002 10:32:33 -0000 @@ -32,4 +32,6 @@ typedef struct OpenFile { #define FMODE_BINMODE 4 #define FMODE_SYNC 8 +#define FMODE_WBUF 16 +#define FMODE_RBUF 32 #define GetOpenFile(obj,fp) rb_io_check_closed((fp) = RFILE(rb_io_taint_check(obj))->fptr)
-- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦