Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

eof() Returns True Incorrectly Before Input Read. #904

Closed
p5pRT opened this issue Nov 30, 1999 · 16 comments
Closed

eof() Returns True Incorrectly Before Input Read. #904

p5pRT opened this issue Nov 30, 1999 · 16 comments

Comments

@p5pRT
Copy link

@p5pRT p5pRT commented Nov 30, 1999

Migrated from rt.perl.org#1839 (status was 'resolved')

Searchable as RT1839$

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Nov 30, 1999

From ralph@inputplus.demon.co.uk

eof() (the <> magic version) returns true if no attempt to read from <>
has yet been made.

A simple test case (that doesn't illustrate why I want to do this) is

  #! /usr/local/bin/perl -w

  use strict;

  my $l;
  while (1) {
  eof() and print "eof\n";
  $l = <>;
  print "l='$l'\n";
  }

Here's it running; I've added comments.

  % ./p
  eof # this is printed immediately.
  abc # I type this
  l='abc # this is OK
  '
  eof # I type ^D it prints eof; again OK.
  Use of uninitialized value at ./p line 9, <> chunk 1.
  l='' # it's a never ending loop so ^C to stop.
  eof

The behaviour once something has been read using <> is fine; it's
before this the problem occurs. If I have `eof() and last' instead or
use it as the `while ()' condition the body never gets executed.

I'm trying this now on a fairly old version, 5.00404, but I've just
logged into work and used 5.00502 with the same result. Here's my
configuration at home for what it's worth.

Ralph.

Site configuration information for perl 5.00404​:

Configured by root at Thu Sep 10 02​:15​:30 EDT 1998.

Summary of my perl5 (5.0 patchlevel 4 subversion 4) configuration​:
  Platform​:
  osname=linux, osvers=2.0.34, archname=i386-linux
  uname='linux porky.redhat.com 2.0.34 #1 thu may 7 10​:17​:44 edt 1998 i686 un
known '
  hint=recommended, useposix=true, d_sigaction=define
  bincompat3=y useperlio=undef d_sfio=undef
  Compiler​:
  cc='cc', optimize='-O2', gccversion=2.7.2.3
  cppflags='-Dbool=char -DHAS_BOOL -I/usr/local/include'
  ccflags ='-Dbool=char -DHAS_BOOL -I/usr/local/include'
  stdchar='char', d_stdstdio=define, usevfork=false
  intsize=4, longsize=4, ptrsize=undef, doublesize=undef
  alignbytes=4, usemymalloc=n, prototype=define
  Linker and Libraries​:
  ld='cc', ldflags =' -L/usr/local/lib'
  libpth=/usr/local/lib /lib /usr/lib
  libs=-lnsl -lndbm -lgdbm -ldb -ldl -lm -lc -lposix -lcrypt
  libc=, so=so
  useshrplib=false, libperl=libperl.a
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic'
  cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib'

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Nov 30, 1999

From [Unknown Contact. See original ticket]

On Tue, Nov 30, 1999 at 06​:23​:53PM +0000, Ralph Corderoy wrote​:

Hi,

eof() (the <> magic version) returns true if no attempt to read from <>
has yet been made.

A simple test case (that doesn't illustrate why I want to do this) is

\#\! /usr/local/bin/perl \-w

use strict;

my $l;
while \(1\) \{
    eof\(\) and print "eof\\n";
    $l = \<>;
    print "l='$l'\\n";
\}

I'd say this is working as documented. To quote the documentation on
eof()​:

  Returns 1 if the next read on FILEHANDLE will return end of file,
  or if FILEHANDLE is not open.
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

No file handle is open at that point in your program (because we
haven't made it to the first use of <> yet), so eof() returns 1.

The documentation on eof() goes on to say

  (Note that this function actually reads a character and then
  C<ungetc()>s it, so isn't very useful in an interactive context.)

and

  Practical hint​: you almost never need to use C<eof> in Perl,
  because the input operators return false values when they run
  out of data, or if there was an error.

Hope this helps,

-Scott
--
Jonathan Scott Duff
duff@​cbi.tamucc.edu

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Nov 30, 1999

From [Unknown Contact. See original ticket]

duff@​cbi.tamucc.edu writes​:

and

Practical hint&#8203;: you almost never need to use C\<eof> in Perl\,
because the input operators return false values when they run
out of data\, or if there was an error\.

This needs to be corrected. Is "false (undefined) values" a better wording?

Ilya

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Dec 1, 1999

From [Unknown Contact. See original ticket]

Ilya Zakharevich <ilya@​math.ohio-state.edu> wrote

This needs to be corrected. Is "false (undefined) values" a better wording?

To avoid confusion, I think all mention of "false" needs to be
expunged. Suggested patch for 5.005_62 attached.

Mike Guy

Inline Patch
--- ./pod/perlfunc.pod.orig	Thu Nov 18 19:10:49 1999
+++ ./pod/perlfunc.pod	Wed Dec  1 15:32:51 1999
@@ -1199,7 +1199,7 @@
     }
 
 Practical hint: you almost never need to use C<eof> in Perl, because the
-input operators return false values when they run out of data, or if there
+input operators return C<undef> when they run out of data, or if there
 was an error.
 
 =item eval EXPR

End of patch

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Dec 1, 1999

From [Unknown Contact. See original ticket]

duff@​cbi.tamucc.edu wrote​:

eof() (the <> magic version) returns true if no attempt to read from <>
has yet been made.

A simple test case (that doesn't illustrate why I want to do this) is

\#\! /usr/local/bin/perl \-w

use strict;

my $l;
while \(1\) \{
    eof\(\) and print "eof\\n";
    $l = \<>;
    print "l='$l'\\n";
\}

I'd say this is working as documented. To quote the documentation on
eof()​:

Returns 1 if the next read on FILEHANDLE will return end of file\,
or if FILEHANDLE is not open\.
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

No file handle is open at that point in your program (because we
haven't made it to the first use of <> yet), so eof() returns 1.

Hi,

I agree it's as documented but since eof() is testing the magic <>
filehandle, which is main'ARGV internally but with magic that can't be
accessed from a script, I can't explicitly open it.

And while I know it almost never necessary to use eof I think I have an
occassion that warrants it. An example that shows the problem but is
more close to real life than my original is

  #! /usr/local/bin/perl -w

  use strict;

  my $p = '.' x 0x20000; $p = '';

  while (!eof()) {
  print "in body\n";
  substr($p, length $p, 0) = <>;

  # just an example; real life is more complex!
  substr($p, -3) eq "\n}\n" and $p = '';
  }
  print "post while\n";

Regardless of @​ARGV only `post while' is printed because, as documented,
<> isn't open.

But, I thought eof was meant to indicate that the next read from the
filehandle would give end of file, and in this case eof() says true but
the next read from <> gives me data (probably).

The non-<> version of eof works fine in this respect.

  $ perl -we 'close F; eof F or die'
  $

But shouldn't eof(), associated as it is with the magic <>, have a
little magic of its own and trigger the first getc+ungetc from <>?

Ralph.

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Dec 1, 1999

From @tamias

On Wed, Dec 01, 1999 at 05​:51​:34PM +0000, ralph@​inputplus.demon.co.uk wrote​:

while \(\!eof\(\)\) \{

Have you tried

do { } until eof()

? That may allow you to do what you want.

Ronald

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Dec 1, 1999

From @TimToady

ralph@​inputplus.demon.co.uk writes​:
: But shouldn't eof(), associated as it is with the magic <>, have a
: little magic of its own and trigger the first getc+ungetc from <>?

Makes sense to me, as much as eof() ever makes sense.

Larry

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Dec 1, 1999

From [Unknown Contact. See original ticket]

On Wed, Dec 01, 1999 at 05​:51​:34PM +0000, ralph@​inputplus.demon.co.uk wrote​:

I agree it's as documented but since eof() is testing the magic <>
filehandle, which is main'ARGV internally but with magic that can't be
accessed from a script, I can't explicitly open it.

You don't *have* to use <> you know. It's a short cut for those
people that know what it means and want that (common) behavior.

Nothing is stopping you from treating each thing in @​ARGV as a file
and attempting to open and read from them.

\#\! /usr/local/bin/perl \-w

use strict;

my $p = '\.' x 0x20000; $p = '';

  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
Why would you do this?

while \(\!eof\(\)\) \{
print "in body\\n";
substr\($p\, length $p\, 0\) = \<>;

\# just an example;  real life is more complex\!
substr\($p\, \-3\) eq "\\n\}\\n" and $p = '';
\}
print "post while\\n";

while (1) {
  print "in body\n";
  $_ = <>;
  last unless defined $_; # exit the loop on EOF
  # stuff here
}
print "post while\n";

I don't see the problem.

-Scott
--
Jonathan Scott Duff
duff@​cbi.tamucc.edu

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Dec 1, 1999

From [Unknown Contact. See original ticket]

On Wed, Dec 01, 1999 at 04​:06​:58PM -0600, duff@​cbi.tamucc.edu wrote​:

my $p = '\.' x 0x20000; $p = '';
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^

Why would you do this?

Preallocate buffer to avoid incremental growth.

Ilya

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Dec 1, 1999

From @vanstyn

In <199912011751.RAA121642@​cm01.ess>, ralph@​inputplus.demon.co.uk writes​:
:An example that shows the problem but is
:more close to real life than my original is
:
: #! /usr/local/bin/perl -w
:
: use strict;
:
: my $p = '.' x 0x20000; $p = '';
:
: while (!eof()) {
: print "in body\n";
: substr($p, length $p, 0) = <>;
:
: # just an example; real life is more complex!
: substr($p, -3) eq "\n}\n" and $p = '';
: }
: print "post while\n";
:
:Regardless of @​ARGV only `post while' is printed because, as documented,
:<> isn't open.
:
:But, I thought eof was meant to indicate that the next read from the
:filehandle would give end of file, and in this case eof() says true but
:the next read from <> gives me data (probably).

No, it says that you are currently at the end of the current file, or
that there is no current file.

When reading from <> in particular, there may be several files to read
from​: in that case eof() is better interpreted to mean 'the next read
will attempt to start reading from a new file, if there is one'.

I think it would be a bad idea to change eof() in the way you suggest.

Hugo

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Dec 2, 1999

From [Unknown Contact. See original ticket]

Hi Hugo,

When reading from <> in particular, there may be several files to
read from​:

Only when reading from <>?

in that case eof() is better interpreted to mean 'the next read will
attempt to start reading from a new file, if there is one'.

No, that's eof. I'm talking about eof().

Ralph.

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Dec 2, 1999

From [Unknown Contact. See original ticket]

On Wed, Dec 01, 1999 at 05​:51​:34PM +0000, ralph@​inputplus.demon.co.uk wrote​:

I agree it's as documented but since eof() is testing the magic <>
filehandle, which is main'ARGV internally but with magic that can't
be accessed from a script, I can't explicitly open it.

You don't *have* to use <> you know. It's a short cut for those
people that know what it means and want that (common) behavior.

Nothing is stopping you from treating each thing in @​ARGV as a file
and attempting to open and read from them.

No, but if, as I stated, I want the magical behaviour of <> I have to
use it; I can't simulate it.

while \(\!eof\(\)\) \{
  print "in body\\n";
  substr\($p\, length $p\, 0\) = \<>;

  \# just an example;  real life is more complex\!
  substr\($p\, \-3\) eq "\\n\}\\n" and $p = '';
\}
print "post while\\n";

while (1) {
print "in body\n";
$_ = <>;
last unless defined $_; # exit the loop on EOF
# stuff here
}
print "post while\n";

I don't see the problem.

Take the time to study my example again. ;-)

  $ perl -we '$_ = "x"; substr($_, length, 0) = <>' </dev/null
  Use of uninitialized value at -e line 1.

Ralph.

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Dec 2, 1999

From [Unknown Contact. See original ticket]

On Wed, Dec 01, 1999 at 05​:51​:34PM +0000, ralph@​inputplus.demon.co.uk wrote​:

while \(\!eof\(\)\) \{

Have you tried

do { } until eof()

? That may allow you to do what you want.

Hi, thanks for the suggestion but I want to avoid a <> that hits the
end of the last file. And if there is no input whatsoever then this
will still make me execute the body of the loop at least once.

Ralph.

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Dec 4, 1999

From @gsar

On Tue, 30 Nov 1999 18​:23​:53 GMT, Ralph Corderoy wrote​:

eof() (the <> magic version) returns true if no attempt to read from <>
has yet been made.

A simple test case (that doesn't illustrate why I want to do this) is

#! /usr/local/bin/perl -w

use strict;

my $l;
while (1) {
eof() and print "eof\n";
$l = <>;
print "l='$l'\n";
}

Here's it running; I've added comments.

% ./p
eof # this is printed immediately.
abc # I type this
l='abc # this is OK
'
eof # I type ^D it prints eof; again OK.
Use of uninitialized value at ./p line 9, <> chunk 1.
l='' # it's a never ending loop so ^C to stop.
eof

The behaviour once something has been read using <> is fine; it's
before this the problem occurs. If I have `eof() and last' instead or
use it as the `while ()' condition the body never gets executed.

Despite what the documentation claims, it turns out that eof()
could operate on any last read filehandle rather than just ARGV.

The attached patch fixes both problems and appears to work on your
example, but it has barely been tested. Can you write a patch for
the test suite? Thanks.

Sarathy
gsar@​ActiveState.com

Inline Patch
-----------------------------------8<-----------------------------------
Change 4642 by gsar@auger on 1999/12/04 21:11:51

	make eof() open ARGV if it isn't open already; also fixes bug
	where eof() would operate on any last-read filehandle, not
	just ARGV

Affected files ...

... //depot/perl/pp_sys.c#131 edit

Differences ...

==== //depot/perl/pp_sys.c#131 (text) ====
Index: perl/pp_sys.c
--- perl/pp_sys.c.~1~	Sat Dec  4 13:15:57 1999
+++ perl/pp_sys.c	Sat Dec  4 13:15:57 1999
@@ -1703,10 +1703,28 @@
     GV *gv;
     MAGIC *mg;
 
-    if (MAXARG <= 0)
-	gv = PL_last_in_gv;
+    if (MAXARG <= 0) {
+	if (PL_op->op_flags & OPf_SPECIAL) {	/* eof() */
+	    IO *io;
+	    gv = PL_last_in_gv = PL_argvgv;
+	    io = GvIO(gv);
+	    if (io && !IoIFP(io)) {
+		if ((IoFLAGS(io) & IOf_START) && av_len(GvAVn(gv)) < 0) {
+		    IoLINES(io) = 0;
+		    IoFLAGS(io) &= ~IOf_START;
+		    do_open(gv, "-", 1, FALSE, O_RDONLY, 0, Nullfp);
+		    sv_setpvn(GvSV(gv), "-", 1);
+		    SvSETMAGIC(GvSV(gv));
+		}
+		else if (!nextargv(gv))
+		    RETPUSHYES;
+	    }
+	}
+	else
+	    gv = PL_last_in_gv;			/* eof */
+    }
     else
-	gv = PL_last_in_gv = (GV*)POPs;
+	gv = PL_last_in_gv = (GV*)POPs;		/* eof(FH) */
 
     if (gv && (mg = SvTIED_mg((SV*)gv, 'q'))) {
 	PUSHMARK(SP);
End of Patch.

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Dec 6, 1999

From [Unknown Contact. See original ticket]

Hi,

gsar@​activestate.com wrote​:

eof() (the <> magic version) returns true if no attempt to read from
<> has yet been made.

Despite what the documentation claims, it turns out that eof() could
operate on any last read filehandle rather than just ARGV.

The attached patch fixes both problems and appears to work on your
example, but it has barely been tested. Can you write a patch for the
test suite? Thanks.

Just to let you know I am working on this and haven't slunk off
expecting someone else to do it.

I already had a patch to t/io/argv.t, some of which correctly failed,
and using readline as a guide I'd also come up with a patch for eof()
but it was failing one of the test cases; I was loosing some magic
somewhere.

Your patch seems fine after an initial check. Should I also patch
pod/perldelta.pod?

Ralph.

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Dec 14, 1999

From [Unknown Contact. See original ticket]

Hi,

The behaviour once something has been read using <> is fine; it's
before this the problem occurs. If I have `eof() and last' instead
or use it as the `while ()' condition the body never gets executed.

Despite what the documentation claims, it turns out that eof() could
operate on any last read filehandle rather than just ARGV.

The attached patch fixes both problems and appears to work on your
example, but it has barely been tested. Can you write a patch for
the test suite? Thanks.

Change 4642 by gsar@​auger on 1999/12/04 21​:11​:51

  make eof\(\) open ARGV if it isn't open already; also fixes bug
  where eof\(\) would operate on any last\-read filehandle\, not
  just ARGV

Below are three patches. Sorry if I haven't submitted them in the
correct manner. All patches work fine when applied in order against
perl5.005_62.

patch01.fixme justs add a FIXME comment to pp_getc because it is doing
something that appears undocumented.

patch02.perlre.pod fixes some problems I happened to notice with
perlre.pod; maybe someone else has already fixed them by now. A few
bits of verbatim text was being indented eight spaces when the majority
is just four. And some =item paragraphs were indented which caused
them to be treated as verbatim.

patch03.eof_magic is the fix for ID 19991130.004. As well as the code
change I've altered perldelta.pod, perlfunc.pod, and t/io/argv.t.
Gurusamy suggested a patch originally but the one I'm submitting here
is something I've come up with based on the existing code for readline;
consequently the logic is split between pp_sys.c and doio.c. I'm not
sure which is preferable; both my and Gurusamy's patch pass the
updated t/io/argv.t tests.

Ralph.

======== 8< patch01.fixme ========

Inline Patch
diff -ruN perl5.005_62/pp_sys.c new/pp_sys.c
--- perl5.005_62/pp_sys.c	Sat Oct  9 18:23:30 1999
+++ new/pp_sys.c	Tue Dec  7 22:48:50 1999
@@ -1095,6 +1095,8 @@
 	gv = PL_stdingv;
     else
 	gv = (GV*)POPs;
+    /* FIXME:  why use argvgv?  what situation can this occur under?
+     * it doesn't seem to be documented in perlfunc(1). */
     if (!gv)
 	gv = PL_argvgv;
 

======== 8< patch02.perlre.pod ========
Inline Patch
diff -ruN perl5.005_62/pod/perlre.pod new/pod/perlre.pod
--- perl5.005_62/pod/perlre.pod	Thu Oct 14 19:14:24 1999
+++ new/pod/perlre.pod	Tue Dec  7 23:34:47 1999
@@ -121,7 +121,7 @@
 This is usually 32766 on the most common platforms.  The actual limit can
 be seen in the error message generated by code such as this:
 
-	$_ **= $_ , / {$_} / for 2 .. 42;
+    $_ **= $_ , / {$_} / for 2 .. 42;
 
 By default, a quantified subpattern is "greedy", that is, it will match as
 many times as possible (given a particular starting location) while still
@@ -191,7 +191,7 @@
 
 The POSIX character class syntax
 
-	[:class:]
+    [:class:]
 
 is also available.  The available classes and their backslash
 equivalents (if available) are as follows:
@@ -214,7 +214,7 @@
 Note that the C<[]> are part of the C<[::]> construct, not part of the whole
 character class.  For example:
 
-	[01[:alpha:]%]
+    [01[:alpha:]%]
 
 matches one, zero, any alphabetic character, and the percentage sign.
 
@@ -247,29 +247,27 @@
 
 =item cntrl
 
-        Any control character.  Usually characters that don't produce
-        output as such but instead control the terminal somehow:
-        for example newline and backspace are control characters.
-	All characters with ord() less than 32 are most often control
-	classified as characters.
+Any control character.  Usually characters that don't produce output as
+such but instead control the terminal somehow: for example newline and
+backspace are control characters.  All characters with ord() less than
+32 are most often control classified as characters.
 
 =item graph
 
-        Any alphanumeric or punctuation character.
+Any alphanumeric or punctuation character.
 
 =item print
 
-        Any alphanumeric or punctuation character or space.
+Any alphanumeric or punctuation character or space.
 
 =item punct
 
-        Any punctuation character.
+Any punctuation character.
 
 =item xdigit
 
-        Any hexadecimal digit.  Though this may feel silly
-        (/0-9a-f/i would work just fine) it is included
-        for completeness.
+Any hexadecimal digit.  Though this may feel silly (/0-9a-f/i would
+work just fine) it is included for completeness.
 
 =item 
 

======== 8< patch03.eof_magic ========
Inline Patch
diff -ruN cvs/pod/perlfunc.pod new/pod/perlfunc.pod
--- cvs/pod/perlfunc.pod	Wed Oct 13 17:13:36 1999
+++ new/pod/perlfunc.pod	Sun Dec 12 18:17:07 1999
@@ -1172,13 +1172,17 @@
 C<eof(FILEHANDLE)> on it) after end-of-file is reached.  File types such
 as terminals may lose the end-of-file condition if you do.
 
-An C<eof> without an argument uses the last file read as argument.
-Using C<eof()> with empty parentheses is very different.  It indicates
-the pseudo file formed of the files listed on the command line,
-i.e., C<eof()> is reasonable to use inside a C<while (E<lt>E<gt>)>
-loop to detect the end of only the last file.  Use C<eof(ARGV)> or
-C<eof> without the parentheses to test I<each> file in a while
-(E<lt>E<gt>) loop.  Examples:
+An C<eof> without an argument uses the last file read.  Using C<eof()>
+with empty parentheses is very different.  It refers to the pseudo file
+formed from the files listed on the command line and accessed via the
+C<E<lt>E<gt>> operator.  Since C<E<lt>E<gt>> isn't explicitly opened,
+as a normal filehandle is, an C<eof()> before C<E<lt>E<gt>> has been
+used will cause C<@ARGV> to be examined to determine if input is
+available.
+
+In a C<while (E<lt>E<gt>)> loop, C<eof> or C<eof(ARGV)> can be used to
+detect the end of each file, C<eof()> will only detect the end of the
+last file.  Examples:
 
     # reset line numbering on each input file
     while (<>) {
diff -ruN cvs/pod/perldelta.pod new/pod/perldelta.pod
--- cvs/pod/perldelta.pod	Fri Oct 15 10:40:01 1999
+++ new/pod/perldelta.pod	Tue Dec  7 23:15:00 1999
@@ -685,6 +685,12 @@
 on C<OLD>.  Formerly, it would have returned the data from the start
 of the following disk block instead.
 
+=head2 eof() has the same old magic as <>
+
+C<eof()> would return true if no attempt to read from C<E<lt>E<gt>> had
+yet been made.  C<eof()> has been changed to have a little magic of its
+own, it now opens the C<E<lt>E<gt>> files.
+
 =head2 system(), backticks and pipe open now reflect exec() failure
 
 On Unix and similar platforms, system(), qx() and open(FOO, "cmd |")
diff -ruN cvs/pp_sys.c new/pp_sys.c
--- cvs/pp_sys.c	Tue Dec 14 14:04:02 1999
+++ new/pp_sys.c	Tue Dec  7 22:48:50 1999
@@ -1697,10 +1697,15 @@
     GV *gv;
     MAGIC *mg;
 
-    if (MAXARG <= 0)
-	gv = PL_last_in_gv;
-    else
-	gv = PL_last_in_gv = (GV*)POPs;
+    if (MAXARG > 0)
+	PL_last_in_gv = (GV*)POPs;
+    else if (PL_op->op_flags & OPf_SPECIAL)
+	PL_last_in_gv = PL_argvgv;
+
+    if (!PL_last_in_gv)
+	PL_last_in_gv = PL_argvgv;
+
+    gv = PL_last_in_gv;
 
     if (gv && (mg = SvTIED_mg((SV*)gv, 'q'))) {
 	PUSHMARK(SP);
diff -ruN cvs/doio.c new/doio.c
--- cvs/doio.c	Wed Oct  6 04:20:25 1999
+++ new/doio.c	Tue Dec  7 23:26:36 1999
@@ -785,6 +785,7 @@
 {
     dTHR;
     register IO *io;
+    PerlIO *fp;
     int ch;
 
     io = GvIO(gv);
@@ -800,6 +801,29 @@
 	Perl_warner(aTHX_ WARN_IO, "Filehandle %s opened only for output",
 		    SvPV_nolen(sv));
     }
+
+    fp = IoIFP(io);
+    if (!fp) {
+	if (IoFLAGS(io) & IOf_ARGV) {
+	    if (IoFLAGS(io) & IOf_START) {
+		IoFLAGS(io) &= ~IOf_START;
+		IoLINES(io) = 0;
+		if (av_len(GvAVn(PL_last_in_gv)) < 0) {
+		    do_open(PL_last_in_gv,"-",1,FALSE,O_RDONLY,0,Nullfp);
+		    sv_setpvn(GvSV(PL_last_in_gv), "-", 1);
+		    SvSETMAGIC(GvSV(PL_last_in_gv));
+		    fp = IoIFP(io);
+		    goto have_fp;
+		}
+	    }
+	    fp = nextargv(PL_last_in_gv);
+	    if (!fp) { /* Note: fp != IoIFP(io) */
+		do_close(PL_last_in_gv, FALSE); /* now it does*/
+		IoFLAGS(io) |= IOf_START;
+	    }
+	}
+    }
+have_fp:
 
     while (IoIFP(io)) {
 
diff -ruN cvs/t/io/argv.t new/t/io/argv.t
--- cvs/t/io/argv.t	Tue Jul 20 18:18:12 1999
+++ new/t/io/argv.t	Tue Dec  7 22:37:12 1999
@@ -1,6 +1,6 @@
 #!./perl
 
-print "1..6\n";
+print "1..14\n";
 
 open(try, '>Io.argv.tmp') || (die "Can't open temp file: $!");
 print try "a line\n";
@@ -55,5 +55,37 @@
 open(try, '<Io.argv.tmp') or die "Can't open temp file: $!";
 print while <try>;
 close try;
+undef $^I;
+
+eof try or print 'not ';
+print "ok 7\n";
+
+eof NEVEROPENED or print 'not ';
+print "ok 8\n";
+
+open STDIN, 'Io.argv.tmp' or die $!;
+@ARGV = ();
+!eof() or print 'not ';
+print "ok 9\n";
+
+<> eq "ok 6\n" or print 'not ';
+print "ok 10\n";
+
+open STDIN, '/dev/null' or die $!;
+@ARGV = ();
+eof() or print 'not ';
+print "ok 11\n";
+
+@ARGV = ('Io.argv.tmp');
+!eof() or print 'not ';
+print "ok 12\n";
+
+@ARGV = ('/dev/null', '/dev/null');
+!eof() or print 'not ';
+print "ok 13\n";
+
+close ARGV or die $!;
+eof() or print 'not ';
+print "ok 14\n";
 
 END { unlink 'Io.argv.tmp', 'Io.argv.tmp.bak' }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
1 participant