Mailing List Archive

GLOBS, DEMIGLOBS, and HEROS: a robust filehandle package?
I'm thinking of how to make a decent FileHandle class for 5.002.
Preliminary work seems ok, but I have some questions about the
code below:

1) Why is my FileHandle::DESTROY called twice per object, and why
does its base type change en route? I didn't something could
even *HAVE* a basetype other than one of SCALAR, HASH,
ARRAY, GLOB, REF, CODE.

2) How can we jimmy in reasonable names so that the warn()s look
nice?

3) Maybe open could on a null could fill in a glob with the
name of the opened-to handle?

--tom

use FileHandle;
use Socket;
use strict;

{
package FileHandle;
use Carp;

sub gensym {
no strict 'refs';
local *{'FileHandle::DEMI_ANON_GLOB'}; # YANETUT
return \delete $FileHandle::{DEMI_ANON_GLOB};
}

sub new { bless &gensym => 'FileHandle' }

sub DESTROY {
my $self = shift;
my $type = ref $self;
carp "\tFH DESTROY of $type: $self";
if (defined fileno $self) {
warn "\t\tCLOSING";
close $self;
}
}
}

############################

{
package Socket;
no strict 'vars';
@ISA = qw(FileHandle);
}

############################

package main;

sub HR { STDOUT->print("\n" . ("=" x 30) . "\n\n") }

{
my $fh = new FileHandle;
open ($fh, "/etc/motd");
print <$fh>;
}

HR;


{
my $fh = new FileHandle;
open ($fh, "cat -n /etc/motd |");
print <$fh>;
close $fh;
}

HR;

{
my $sock = new Socket;
socket($sock, PF_INET, SOCK_STREAM, scalar getprotobyname 'tcp') || die "socket: $!";
}

HR;

{
my $p1 = new FileHandle;
my $p2 = new FileHandle;
pipe($p1,$p2) || die "pipe: $!";
}

HR;

print "ok, done\n";

HR;
Re: GLOBS, DEMIGLOBS, and HEROS: a robust filehandle package? [ In reply to ]
On Fri, 6 Oct 1995, Tom Christiansen wrote:

> 2) How can we jimmy in reasonable names so that the warn()s look
> nice?
>
> 3) Maybe open could on a null could fill in a glob with the
> name of the opened-to handle?

I'm sorry, but I didn't quite follow this. Could you restate it with some
examples of what it should look like?

> --tom

--
Kenneth Albanowski (kjahds@kjahds.com, CIS: 70705,126)
Re: GLOBS, DEMIGLOBS, and HEROS: a robust filehandle package? [ In reply to ]
> On Fri, 6 Oct 1995, Tom Christiansen wrote:

> > 2) How can we jimmy in reasonable names so that the warn()s look
> > nice?
> >
> > 3) Maybe open could on a null could fill in a glob with the
> > name of the opened-to handle?

> I'm sorry, but I didn't quite follow this. Could you restate it with some
> examples of what it should look like?


I'd like to be able to say something like

use FileHandle;
$path = '/etc/motd';
$fh = sysopen $path, O_EXCL|O_WRONLY|O_CREAT;

and then if you print out $fh, it is GLOB ref (er, FILEHANDLE ref?)
to

FileHandle::/etc/motd

so that when you do warn()s etc, it would say something useful.

I am trying to recall why Larry chose not to autovivify file vars.
Larry?

--tom
Re: GLOBS, DEMIGLOBS, and HEROS: a robust filehandle package? [ In reply to ]
On Fri, 6 Oct 1995, Tom Christiansen wrote:

> I'd like to be able to say something like
>
> use FileHandle;
> $path = '/etc/motd';
> $fh = sysopen $path, O_EXCL|O_WRONLY|O_CREAT;
>
> and then if you print out $fh, it is GLOB ref (er, FILEHANDLE ref?)
> to
>
> FileHandle::/etc/motd
>
> so that when you do warn()s etc, it would say something useful.

Um, ignoring character invalid in symbols, what about multiple uses of a
file? You'd have to have C<FileHandle::/etc/motd>,
C<FileHandle::/etc/motd#2>, etc. Or maybe append _R, _W, etc.

I halfway think this should be done with overloading of '""', so $fh
automatically gets turned into $path if used like C<or die "Unable to
open $fh">.

> I am trying to recall why Larry chose not to autovivify file vars.
> Larry?
>
> --tom
>

--
Kenneth Albanowski (kjahds@kjahds.com, CIS: 70705,126)
Re: GLOBS, DEMIGLOBS, and HEROS: a robust filehandle package? [ In reply to ]
On Fri, 6 Oct 1995, Tom Christiansen wrote:

> >> what about multiple uses of a
> >> file? You'd have to have C<FileHandle::/etc/motd>,
> >> C<FileHandle::/etc/motd#2>, etc. Or maybe append _R, _W, etc.
>
> >That's not a problem. Please look at this again very closely:
> >
> > sub gensym {
> > no strict 'refs';
> > local *{"FileHandle::DEMI_ANON_GLOB"}; # delay lookup to run-time
> > \delete $FileHandle::{DEMI_ANON_GLOB}; # ungensym now !
> > }
>
> Ok, now that you've looked long enough... :-)
>
> It returns a pointer to a new GLOB thingie, that just happens
> to have the same name. It's still a different thing, though.

Yes, I can see that. _Barely_. It wouldn't be completely inaccurate to
say that it is returning a named anonymous glob, right? And since it's
anonymous, it can have any name you like, even one already taken...

Next question: can the name of the anonymous glob be changed, or is it
fixed for the life of the glob? If fixed, then you'd really want open()
and socket() to return _new_ FileHandles, and not take current ones for
arguments.

OTOH, if FileHandle was overloaded so that stringification returned the
internal "name" element, then open() could just $fh->setname(), or
something like that.

> --tom

--
Kenneth Albanowski (kjahds@kjahds.com, CIS: 70705,126)
Re: GLOBS, DEMIGLOBS, and HEROS: a robust filehandle package? [ In reply to ]
> > $path = '/etc/motd';
> > $fh = sysopen $path, O_EXCL|O_WRONLY|O_CREAT;
> >
> > and then if you print out $fh, it is GLOB ref (er, FILEHANDLE ref?)
> > to
> >
> > FileHandle::/etc/motd
> >
> > so that when you do warn()s etc, it would say something useful.

> Um, ignoring character invalid in symbols,

That's not a problem. %FileHandle:: is happy to hold them.

> what about multiple uses of a
> file? You'd have to have C<FileHandle::/etc/motd>,
> C<FileHandle::/etc/motd#2>, etc. Or maybe append _R, _W, etc.

That's not a problem. Please look at this again very closely:

sub gensym {
no strict 'refs';
local *{"FileHandle::DEMI_ANON_GLOB"}; # delay lookup to run-time
\delete $FileHandle::{DEMI_ANON_GLOB}; # ungensym now !
}

sub new { bless &gensym => 'FileHandle' }
Re: GLOBS, DEMIGLOBS, and HEROS: a robust filehandle package? [ In reply to ]
>> what about multiple uses of a
>> file? You'd have to have C<FileHandle::/etc/motd>,
>> C<FileHandle::/etc/motd#2>, etc. Or maybe append _R, _W, etc.

>That's not a problem. Please look at this again very closely:
>
> sub gensym {
> no strict 'refs';
> local *{"FileHandle::DEMI_ANON_GLOB"}; # delay lookup to run-time
> \delete $FileHandle::{DEMI_ANON_GLOB}; # ungensym now !
> }

Ok, now that you've looked long enough... :-)

It returns a pointer to a new GLOB thingie, that just happens
to have the same name. It's still a different thing, though.

--tom
RE: GLOBS, DEMIGLOBS, and HEROS: a robust filehandle package? [ In reply to ]
On Wed, 11 Oct 1995, John Hughes wrote:

> Very interesting. Looks quite a lot like what I use here (except neater in some
> ways).
>
> But why keep "open" and "close". I don't see the point of 'em myself. What I
> do is have "new" do the open and "DESTROY" the close.
>
> my $fh = new FileHandle ">/dev/null";

Opened filehandles have different lives then filehandles themselves. You
can write stuff like this:


open(HANDLE,">a");
print HANDLE "a";
open(HANDLE,">b");
print HANDLE "b";
close(HANDLE);
open(HANDLE,">c");
print HANDLE "c";
exit;

If you are doing file processing in a loop, these can be useful shortcuts,
and really can't be done cleanly if you are stuck with lexical scopes, as
you are with new & DESTROY. There's no reason why you couldn't have both
styles available, though.

> --
> John Hughes <john@AtlanTech.COM> or <JH10@CalvaCom.FR>,
> Atlantic Technologies Inc. Tel: +33-1-43204546
> 24 rue Montbrun, Fax: +33-1-43204579
> 75014 PARIS.
>
>

--
Kenneth Albanowski (kjahds@kjahds.com, CIS: 70705,126)
RE: GLOBS, DEMIGLOBS, and HEROS: a robust filehandle package? [ In reply to ]
> From: John Hughes <john@atlantech.com>
>
> Very interesting. Looks quite a lot like what I use here (except neater
> in some ways).
>
> But why keep "open" and "close". I don't see the point of 'em myself.
> What I do is have "new" do the open and "DESTROY" the close.
>
> my $fh = new FileHandle ">/dev/null";

Having a form of new which does an open would be handy.
Having DESTROY do a close if required is important (pipes etc).

Having distinct open and close methods is still very useful.
For example, I may have a print method which wants to close,
rename, open+create if the log file I'm writing to gets too big.

Tim.
RE: GLOBS, DEMIGLOBS, and HEROS: a robust filehandle package? [ In reply to ]
Very interesting. Looks quite a lot like what I use here (except neater in some
ways).

But why keep "open" and "close". I don't see the point of 'em myself. What I
do is have "new" do the open and "DESTROY" the close.

my $fh = new FileHandle ">/dev/null";


--
John Hughes <john@AtlanTech.COM> or <JH10@CalvaCom.FR>,
Atlantic Technologies Inc. Tel: +33-1-43204546
24 rue Montbrun, Fax: +33-1-43204579
75014 PARIS.
RE: GLOBS, DEMIGLOBS, and HEROS: a robust filehandle package? [ In reply to ]
JH> Very interesting. Looks quite a lot like what I use here (except neater in some
JH> ways).

JH> But why keep "open" and "close". I don't see the point of 'em myself. What I
JH> do is have "new" do the open and "DESTROY" the close.

JH> my $fh = new FileHandle ">/dev/null";

I may be missing something but often I want to close the file before
the variable goes out of scope (and so gets destroyed), for instance
when some other process wants to look at the contents.

P.
RE: GLOBS, DEMIGLOBS, and HEROS: a robust filehandle package? [ In reply to ]
Tom says:

> 1) Why is my FileHandle::DESTROY called twice per object, and why
> does its base type change en route? I didn't something could
> even *HAVE* a basetype other than one of SCALAR, HASH,
> ARRAY, GLOB, REF, CODE.

I guess you already figured this out, but:

The result from "new FileHandle" is a "PVGV", a ref GLOB. When you pass this
to "open" a "PVIO" gets stashed in the GV (correct terminology?). The PVIO
is the real actual filehandle. All PVIO's are in class FileHandle. (See
"newIO" in gv.c). Your DESTROY is called for the PVGV that you blessed into
FileHandle. It does it's work then returns. Perl then zaps the GV, which
causes a DESTROY of the PVIO.

In my experiments I find that there is no point defining a DESTROY method
for FileHandle, the built in stuff makes sure that the file is closed when the
PVIO is deleted.

Examination of the source (sv_2pv in sv.c, the default "stringify" operator)
shows types "LVALUE", "FORMATLINE" and "UNKNOWN" as possible types.

--
John Hughes <john@AtlanTech.COM> or <JH10@CalvaCom.FR>,
Atlantic Technologies Inc. Tel: +33-1-43204546
24 rue Montbrun, Fax: +33-1-43204579
75014 PARIS.
RE: GLOBS, DEMIGLOBS, and HEROS: a robust filehandle package? [ In reply to ]
JH> But why keep "open" and "close". I don't see the point of 'em myself.
JH> What I do is have "new" do the open and "DESTROY" the close.

Paul> I may be missing something but often I want to close the file before
Paul> the variable goes out of scope (and so gets destroyed)

In that case I just do "undef $fh". Ok, it doesn't work if I have other
references to the same filehandle, but being careful with references is
necessary for so many other things.

close still exists, it's just that I don't use it anymore.

I can see why people want to do a "new" that doesn't open the file, for sockets
and pipes. My "FileHandle::new" only does the open if it is given a filename
argument, otherwise it just returns an unopened FileHandle.

--
John Hughes <john@AtlanTech.COM> or <JH10@CalvaCom.FR>,
Atlantic Technologies Inc. Tel: +33-1-43204546
24 rue Montbrun, Fax: +33-1-43204579
75014 PARIS.
RE: GLOBS, DEMIGLOBS, and HEROS: a robust filehandle package? [ In reply to ]
In <01BA97E1.A62CCE60@malvinas.AtlanTech.COM>
On Wed, 11 Oct 1995 13:58:29 +-100
John Hughes <john@AtlanTech.COM> writes:
>JH> But why keep "open" and "close". I don't see the point of 'em myself.
>JH> What I do is have "new" do the open and "DESTROY" the close.
>
>Paul> I may be missing something but often I want to close the file before
>Paul> the variable goes out of scope (and so gets destroyed)
>
>In that case I just do "undef $fh".

That looks messy and you may want to test return code of close().

I can conceive of case where you might want to open() close() and
re-open same filename but in different mode.

> Ok, it doesn't work if I have other
>references to the same filehandle, but being careful with references is
>necessary for so many other things.
>
>close still exists, it's just that I don't use it anymore.




>
>I can see why people want to do a "new" that doesn't open the file, for sockets
>and pipes. My "FileHandle::new" only does the open if it is given a filename
>argument, otherwise it just returns an unopened FileHandle.
RE: GLOBS, DEMIGLOBS, and HEROS: a robust filehandle package? [ In reply to ]
John> But why keep "open" and "close". I don't see the point of 'em myself.
John> What I do is have "new" do the open and "DESTROY" the close.

Paul> I may be missing something but often I want to close the file before
Paul> the variable goes out of scope (and so gets destroyed)

John> In that case I just do "undef $fh".

Nick> That looks messy and you may want to test return code of close().

I think leaving the FileHandle around after it's been closed is messy. I was
a FORTRAN programmer for years and the first thing I realy liked about C was
having stdio allocate FILE's for me instead of all that pissing around with
unit numbers. Returning to the same old nonsense with Perl was quite a shock.

Wanting to test the return of "close" is good point, a real use for close().

Nick> I can conceive of case where you might want to open() close() and
Nick> re-open same filename but in different mode.

I don't get this. You can close and re-open the same file without using the
same FileHandle.

Or do you want a "re-open" method?

$fh = new FileHandle "<fred";

while (<fred>) { ... };

$fh->reopen ">";

print $fh "xxx";


--
John Hughes <john@AtlanTech.COM> or <JH10@CalvaCom.FR>,
Atlantic Technologies Inc. Tel: +33-1-43204546
24 rue Montbrun, Fax: +33-1-43204579
75014 PARIS.
RE: GLOBS, DEMIGLOBS, and HEROS: a robust filehandle package? [ In reply to ]
Tim> Having a form of new which does an open would be handy.
Tim> Having DESTROY do a close if required is important (pipes etc).

In fact FileHandles get closed even if you DON'T have a DESTROY method.
Oddly enough DirHandles don't.

Tim> Having distinct open and close methods is still very useful.

Ok, I surrender, I now agree!

Tim> For example, I may have a print method which wants to close,
Tim> rename, open+create if the log file I'm writing to gets too big.

Ah, I guess that this is the kind of thing that Nick Ing was talking about.

--
John Hughes <john@AtlanTech.COM> or <JH10@CalvaCom.FR>,
Atlantic Technologies Inc. Tel: +33-1-43204546
24 rue Montbrun, Fax: +33-1-43204579
75014 PARIS.
RE: GLOBS, DEMIGLOBS, and HEROS: a robust filehandle package? [ In reply to ]
In <01BA97EA.E90A0780@malvinas.AtlanTech.COM>
On Wed, 11 Oct 1995 15:04:47 +-100
John Hughes <john@AtlanTech.COM> writes:
>
>Nick> I can conceive of case where you might want to open() close() and
>Nick> re-open same filename but in different mode.
>
>I don't get this. You can close and re-open the same file without using the
>same FileHandle.

If file handle was passed to me it may be only way I know what file name *is*.

Also undef'ing an object has caused problems in Tk - if someone has
derived a class from 'your' class there maybe other data associated
which needs to be cleaned up.

In case of file handle close in particular should *always* be done
as a method call, so that a derived class can determine what close
*means*.

>
>Or do you want a "re-open" method?
>
> $fh = new FileHandle "<fred";
>
> while (<fred>) { ... };
>
> $fh->reopen ">";
>
> print $fh "xxx";

That was what I had in mind - but there may be other obscure uses we have
not thought of yet.
For example if file handle was slave side of a pseudo tty, we may want
to keep it around to allow another child process to be forked using it.

Not that I am disagreeing in principle - I see not reason not
to have normal pattern of use being that new does open() and it gets
closed when object is destroyed.

But we should retain explcit open/close (and record of how it was
opened?) to cover obscure cases, and to allow them to be overridden in
derived classes.