From: Mike Kasick Date: 2009-07-26T12:01:13+09:00 Subject: [ruby-core:24562] Re: Expected change in behavior for ARGF.eof? On Sat, Jul 25, 2009 at 03:49:25PM +0900, Heesob Park wrote: > I guess it is a bug of 1.9.x. I concur. I took a close look today at the ARGF code. I'm not sure if this is documented elsewhere, but for the sake of explicitness, this is what looks like is going on: On startup, ARGF is in a kind of "pre-initalized" state in that the File object for ARGV[0] is yet to be loaded. This is flagged by "init_p", where "init_p == 0" means pre-initialized and "init_p == 1" means initialized (that is, ARGF.current_file points to an actual file). This initalization takes place in the "next_argv" function (actually a macro for argf_next_argv). There's also a "next_p" state flag, where 0 means ARGF.current_file is active and should be maintained across the next_argv function, 1 means ARGF.current_file is closed and should be switched to the next file, and -1 means ARGF.current_file points to $stdin. Anyways, it looks to me like all ARGF methods should respond to the pre-initalized state by either calling "next_argv", or otherwise maintain the illusion that ARGF is initialized. Most ARGF methods just call "next_argv" early on. The exceptions are ARGF.skip and ARGF.eof. Both are supposed to check the status of init_p to short circuit in the pre-initialized, but neither was actually doing so until recently. > > Also, is there a way to advance ARGF to the next (in ARGV) file once EOF > > for the current file has been reached? > > In my test, ARGF.gets advanced ARGF to the next file in ARGV Sorry, I should've qualified that by saying "without reading from the current ARGF stream". It looks like ARGF.skip is supposed to do this. ARGF.close will as well, but ARGF.skip won't close $stdin. The problem is that neither can be directly followed by a call to ARGF.eof: $ echo foo > /tmp/foo; echo bar > /tmp/bar $ ./ruby -e 'ARGF.gets; ARGF.skip; p ARGF.eof?' /tmp/foo /tmp/bar -e:1:in `eof?': closed stream (IOError) from -e:1:in `
' This can be made to work for now by calling one of the ARGF accessor methods that calls "next_argv" as a side-effect between skip and eof: $ ./ruby -e 'ARGF.gets; ARGF.skip.file; p ARGF.eof?' /tmp/foo /tmp/bar false But probably the better solution is to fix ARGF.eof to call "next_argv" in the "init_p != 0" case like other methods do. I submitted a bug/patch to the issue tracker, #1818. Thanks everyone!