[comp.lang.perl] funky filehandle

jsb@cs.brown.edu (John Bazik) (07/17/90)

Here's a funny thing.  I have a short script and a package it utilizes:

script...

	#!/cs/bin/perl

	do 'tfio.pl' || die "tfio.pl: ($@)";

	if (&f_open(*F, '/tmp/xxx')) {
		($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size) = stat(F);
		print "stat uid $uid gid $gid size $size\n";
		print "/tmp/xxx is okay\n";
		print "but eof\n" if eof(F);
	}
	else {
		print "/tmp/xxx nogood\n";
	}

	while (<F>) {
		print "<$_>\n";
	}

package...

	package tfio;

	sub main'f_open {
		local(*F,$file) = @_;

		if (open(F, $file)) {
			return 1;
		}
		else {
			print "cannot open $file\n";
		}
		return 0;
	}

	1;

Now, this works perfectly.  But if I comment out the while loop, the stat
fails to return anything and the eof(F) is true (though the file contains
two lines).  Why does the file have to be read to stat?  I'm relatively
new to perl, so please help me out if I'm totally off base.

John Bazik
jsb@cs.brown.edu

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (07/18/90)

In article <45087@brunix.UUCP> jsb@cs.brown.edu (John Bazik) writes:
: Here's a funny thing.  I have a short script and a package it utilizes:
: 
: script...
: 
: 	#!/cs/bin/perl
: 
: 	do 'tfio.pl' || die "tfio.pl: ($@)";
: 
: 	if (&f_open(*F, '/tmp/xxx')) {
: 		($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size) = stat(F);
: 		print "stat uid $uid gid $gid size $size\n";
: 		print "/tmp/xxx is okay\n";
: 		print "but eof\n" if eof(F);
: 	}
: 	else {
: 		print "/tmp/xxx nogood\n";
: 	}
: 
: 	while (<F>) {
: 		print "<$_>\n";
: 	}
: 
: package...
: 
: 	package tfio;
: 
: 	sub main'f_open {
: 		local(*F,$file) = @_;
: 
: 		if (open(F, $file)) {
: 			return 1;
: 		}
: 		else {
: 			print "cannot open $file\n";
: 		}
: 		return 0;
: 	}
: 
: 	1;
: 
: Now, this works perfectly.  But if I comment out the while loop, the stat
: fails to return anything and the eof(F) is true (though the file contains
: two lines).  Why does the file have to be read to stat?  I'm relatively
: new to perl, so please help me out if I'm totally off base.

I'd call it a bug.  Perl tries to be lazy about some things, including
allocating memory for arrays, hash tables and IO structures in the symbol
table entry.  Overall this is a win because most symbols aren't going to
have all those items.

However, it was interacting badly with local(*F)=@_, which made a local
copy of the symbol table entry.  Then when you did the open (which ordinarily
allocates the IO structure), it attached it to the local copy rather than
the global symbol table entry.  The reason it worked with the read is that
the compiler goes ahead and allocates a IO structure when it sees a <>, so
the global entry already had one, so open didn't add one to the local copy,
so it used the global entry's IO structure like it was supposed to.

Anyway, I fixed it by making any use of *F force allocation of unallocated
structures.  This will fix some comparable problems with generic array
routines too.

You probably didn't want to know all that...

Larry