develooper Front page | perl.perl5.porters | Postings from August 2008

Re: Diamond iteration (was: Fighting the Good Fight against spam deluge)

From:
Tom Christiansen
Date:
August 1, 2008 09:56
Subject:
Re: Diamond iteration (was: Fighting the Good Fight against spam deluge)
Message ID:
8054.1217609758@chthon
> On Fri, Aug 01, 2008 at 09:26:57AM -0600, Tom Christiansen wrote:

>> I still yearn for <> to work on DHs opened by opendir, too.
>> Never saw why it didn't.

> But how would you know whether <HANDLE> operates on a filehandle named
> HANDLE, or a dirhandle named HANDLE? Perl allows them to coexist:

>    use strict;
>    use warnings;

>    open HANDLE, "/etc/passwd" or die;
>    opendir HANDLE, "/etc" or die;
>    while (<HANDLE>) {print}        # Prints the content of /etc/passwd
>    say while $_ = readdir HANDLE;  # Prints the files in /etc

> If <HANDLE> operated on dirhandles as well, it wouldn't be clear what
> the penultimate line would do.

Hey Abigail,

Thanks for reminding me of why.  Forgive Rip VanWinkle as he renegotiates
neural pathways to long-since-accessed memory.  

But you're absolutely right, and that *was* always the precise 
reason why not, too.  

I used to tell people a *FOO typeglob comprised a scalar, array, a hash, a
subroutine, a format name, and both a file *AND* a directory handle by that
same name.

(Now if we could only get popen(PH, "|....|") to work both ways, but
no, that's a bad idea, I know, I know. :-)

Course these days, one can show

    *FOO{SCALAR} => \$FOO
    *FOO{ARRAY}  => \@FOO
    *FOO{HASH}   => \%FOO
    *FOO{CODE}   => \&FOO

But there's no good way to get at the bifurcated *FOO{IO} element,
as that split happens further down.  I can't seem to get anything
within Perl to cough it up.  Can you?

    DB<1> $FOO = 1
    DB<2> %FOO = (bad => "news")
    DB<3> open(FOO, "</dev/null") || die
    DB<4> x *FOO
    0  *main::FOO
    DB<5> x \*FOO
    0  GLOB(0x3c3fcd34)
       -> *main::FOO
	     FileHandle({*main::FOO}) => fileno(5)

    (more dinking around)

    DB<18> opendir(FOO, "/") || die
    DB<19> x *FOO{IO}
    0  IO::Handle=IO(0x3c3fcd98)
    DB<20> x *FOO{FILEHANDLE}
    0  IO::Handle=IO(0x3c3fcd98)
    DB<21> x *FOO{DIRHANDLE}
    0  undef

Bah, let's ask somebody who really knows:

    DB<22> system "fstat -p $$"
    USER     CMD          PID   FD MOUNT      INUM MODE       R/W    DV|SZ
    tchrist  perl       26526   wd /home    936785 drwxr-xr-x   r     4608
    tchrist  perl       26526    0 /         54040 crw--w----  rw    ttyp0
    tchrist  perl       26526    1 /         54040 crw--w----  rw    ttyp0
    tchrist  perl       26526    2 /         54040 crw--w----  rw    ttyp0
    tchrist  perl       26526    3 pipe 0xd3b92d38 state:
    tchrist  perl       26526    4 pipe 0xd3b92d38 state:
    tchrist  perl       26526    5 /         54185 crw-rw-rw-   r     null
    tchrist  perl       26526    6 /         54184 crw-rw-rw-  rw      tty
    tchrist  perl       26526    7 /         54184 crw-rw-rw-  rw      tty
    tchrist  perl       26526    8 /usr/local 383375 -r--r--r--   r    21264
    tchrist  perl       26526    9 /             2 drwxr-xr-x   r     1024
    tchrist  perl       26526   10 pipe 0xd3b92948 state: E

Gee, what's at inum=2 on the slash mount-point, eh? :-)

So it's there at fd 9.  Just can't get anything to admit it; can you?
Here's my little poke-about program (/tmp/fd) that I tried to dig it
out, but didn't find anything satisfactory.  I wonder whether Storable
would be better at preserving both parts of the IO object?

=cut here ===

use 5.010_000;
use strict;

$| = 1;
open(STDERR, ">&=1") || die $!;

package _Foo::__Bar__;

sub count_fds();

count_fds();

{   no strict "vars";

    *BAR = "FOO";
    $FOO = "bar";
    @FOO = ('ax' .. 'bb');
    %FOO = map { $_ => $FOO } @FOO;
}

*FOO = sub { local $~ = "FOO"; write; };
format FOO = 

Mind the gap!

.
open(FOO, "+< /dev/null") || die $!;
opendir(FOO, "/") 	  || die $!;

BAR();

for my $stent (sort qw[  SCALAR ARRAY HASH
			   CODE FORMAT IO
			   NAME PACKAGE
		    ]
	      )
{
    printf "%-20s = %s\n", "*FOO{$stent}", *FOO{$stent};
    if ($stent eq "CODE" && *FOO{$stent}) {
	print "\n\ntrying to uncompiling &FOO...\n";
	require B::Deparse;
	print B::Deparse->new()->coderef2text(\&FOO);
	print "\n\n";
    }
} 


print "\nAnd now for a dump:\n\n";

require Devel::Peek;
Devel::Peek::Dump(\*FOO);

count_fds();

{
    require Dumpvalue;
    my $dumper = new Dumpvalue;
    $dumper->set(globPrint => 1);
    print "\n\nLet's try dumpvaluing *BAR\n\n";
    $dumper->dumpValue(\*BAR);
}

count_fds();

sub count_fds() { 
    state $entered = 0;
    $entered++;
    print "\nTRY $entered on trying to count open fds...\n\n";
    for (my $fd = 0; $fd < 256; $fd++) {
	my $tmpfh;
	if (open($tmpfh, "+< &=$fd")) {
	    print "  ... looks like $fd is open\n";
	} 
    } 
    print "\ndone counting fds\n\n";
}

=cut here here and you break your monitor ===

And herebelow is its stdoutput on my system, indented:


    TRY 1 on trying to count open fds...

      ... looks like 0 is open
      ... looks like 1 is open
      ... looks like 2 is open
      ... looks like 3 is open
      ... looks like 4 is open
      ... looks like 5 is open

    done counting fds


    Mind the gap!

    *FOO{ARRAY}          = ARRAY(0x3c049e60)
    *FOO{CODE}           = CODE(0x3c049e4c)


    trying to uncompiling &FOO...
    {
	package _Foo::__Bar__;
	use strict 'refs';
	BEGIN {
	    $^H{'feature_say'} = q(1);
	    $^H{'feature_state'} = q(1);
	    $^H{'feature_switch'} = q(1);
	}
	local $~ = 'FOO';
	write;
    }

    *FOO{FORMAT}         = FORMAT(0x3c04f2f8)
    *FOO{HASH}           = HASH(0x3c04f1b8)
    *FOO{IO}             = IO::Handle=IO(0x3c04f2a8)
    *FOO{NAME}           = FOO
    *FOO{PACKAGE}        = _Foo::__Bar__
    *FOO{SCALAR}         = SCALAR(0x3c049a3c)

    And now for a dump:

    SV = RV(0x3c0398a4) at 0x3c039898
      REFCNT = 1
      FLAGS = (TEMP,ROK)
      RV = 0x3c049a50
      SV = PVGV(0x3c041080) at 0x3c049a50
	REFCNT = 14
	FLAGS = (PADTMP,MULTI,ASSUMECV,IN_PAD)
	NAME = "FOO"
	NAMELEN = 3
	GvSTASH = 0x3c039adc	"_Foo::__Bar__"
	GP = 0x3c04bf00
	  SV = 0x3c049a3c
	  REFCNT = 2
	  IO = 0x3c04f2a8
	  FORM = 0x3c04f2f8  
	  AV = 0x3c049e60
	  HV = 0x3c04f1b8
	  CV = 0x3c049e4c
	  CVGEN = 0x0
	  LINE = 16
	  FILE = "/tmp/fd"
	  FLAGS = 0xe
	  EGV = 0x3c049a50	"FOO"

    TRY 2 on trying to count open fds...

      ... looks like 0 is open
      ... looks like 1 is open
      ... looks like 2 is open
      ... looks like 3 is open
      ... looks like 4 is open
      ... looks like 5 is open
      ... looks like 6 is open

    done counting fds



    Let's try dumpvaluing *BAR

    -> *_Foo::__Bar__::FOO
	  ${*_Foo::__Bar__::FOO} = 'bar'
	  @{*_Foo::__Bar__::FOO} = (
	     0  'ax'
	     1  'ay'
	     2  'az'
	     3  'ba'
	     4  'bb'
	  )
	  %{*_Foo::__Bar__::FOO} = (
	     'ax' => 'bar'
	     'ay' => 'bar'
	     'az' => 'bar'
	     'ba' => 'bar'
	     'bb' => 'bar'
	  )
	  FileHandle({*_Foo::__Bar__::FOO}) => fileno(4)
	  &_Foo::__Bar__::FOO in ???

    TRY 3 on trying to count open fds...

      ... looks like 0 is open
      ... looks like 1 is open
      ... looks like 2 is open
      ... looks like 3 is open
      ... looks like 4 is open
      ... looks like 5 is open

    done counting fds

Hm.  Makes ya wonder.  You wonder whether these require's
leave things open, or where fd6 flaked off too.

--tom



nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About