devdaily home | apple | java | perl | unix | directory | blog

What this is

This file is included in the DevDaily.com "Perl Source Code Warehouse" project. The intent of this project is to help you "Learn Perl by Example" TM.

Other links

The source code

#!./perl

print "1..75\n";

sub foo {
    local($a, $b) = @_;
    local($c, $d);
    $c = "ok 3\n";
    $d = "ok 4\n";
    { local($a,$c) = ("ok 9\n", "ok 10\n"); ($x, $y) = ($a, $c); }
    print $a, $b;
    $c . $d;
}

$a = "ok 5\n";
$b = "ok 6\n";
$c = "ok 7\n";
$d = "ok 8\n";

print &foo("ok 1\n","ok 2\n");

print $a,$b,$c,$d,$x,$y;

# same thing, only with arrays and associative arrays

sub foo2 {
    local($a, @b) = @_;
    local(@c, %d);
    @c = "ok 13\n";
    $d{''} = "ok 14\n";
    { local($a,@c) = ("ok 19\n", "ok 20\n"); ($x, $y) = ($a, @c); }
    print $a, @b;
    $c[0] . $d{''};
}

$a = "ok 15\n";
@b = "ok 16\n";
@c = "ok 17\n";
$d{''} = "ok 18\n";

print &foo2("ok 11\n","ok 12\n");

print $a,@b,@c,%d,$x,$y;

eval 'local($$e)';
print +($@ =~ /Can't localize through a reference/) ? "" : "not ", "ok 21\n";

eval '$e = []; local(@$e)';
print +($@ =~ /Can't localize through a reference/) ? "" : "not ", "ok 22\n";

eval '$e = {}; local(%$e)';
print +($@ =~ /Can't localize through a reference/) ? "" : "not ", "ok 23\n";

# Array and hash elements

@a = ('a', 'b', 'c');
{
    local($a[1]) = 'foo';
    local($a[2]) = $a[2];
    print +($a[1] eq 'foo') ? "" : "not ", "ok 24\n";
    print +($a[2] eq 'c') ? "" : "not ", "ok 25\n";
    undef @a;
}
print +($a[1] eq 'b') ? "" : "not ", "ok 26\n";
print +($a[2] eq 'c') ? "" : "not ", "ok 27\n";
print +(!defined $a[0]) ? "" : "not ", "ok 28\n";

@a = ('a', 'b', 'c');
{
    local($a[1]) = "X";
    shift @a;
}
print +($a[0].$a[1] eq "Xb") ? "" : "not ", "ok 29\n";

%h = ('a' => 1, 'b' => 2, 'c' => 3);
{
    local($h{'a'}) = 'foo';
    local($h{'b'}) = $h{'b'};
    print +($h{'a'} eq 'foo') ? "" : "not ", "ok 30\n";
    print +($h{'b'} == 2) ? "" : "not ", "ok 31\n";
    local($h{'c'});
    delete $h{'c'};
}
print +($h{'a'} == 1) ? "" : "not ", "ok 32\n";
print +($h{'b'} == 2) ? "" : "not ", "ok 33\n";
print +($h{'c'} == 3) ? "" : "not ", "ok 34\n";

# check for scope leakage
$a = 'outer';
if (1) { local $a = 'inner' }
print +($a eq 'outer') ? "" : "not ", "ok 35\n";

# see if localization works when scope unwinds
local $m = 5;
eval {
    for $m (6) {
	local $m = 7;
	die "bye";
    }
};
print $m == 5 ? "" : "not ", "ok 36\n";

# see if localization works on tied arrays
{
    package TA;
    sub TIEARRAY { bless [], $_[0] }
    sub STORE { print "# STORE [@_]\n"; $_[0]->[$_[1]] = $_[2] }
    sub FETCH { my $v = $_[0]->[$_[1]]; print "# FETCH [@_=$v]\n"; $v }
    sub CLEAR { print "# CLEAR [@_]\n"; @{$_[0]} = (); }
    sub FETCHSIZE { scalar(@{$_[0]}) }
    sub SHIFT { shift (@{$_[0]}) }
    sub EXTEND {}
}

tie @a, 'TA';
@a = ('a', 'b', 'c');
{
    local($a[1]) = 'foo';
    local($a[2]) = $a[2];
    print +($a[1] eq 'foo') ? "" : "not ", "ok 37\n";
    print +($a[2] eq 'c') ? "" : "not ", "ok 38\n";
    @a = ();
}
print +($a[1] eq 'b') ? "" : "not ", "ok 39\n";
print +($a[2] eq 'c') ? "" : "not ", "ok 40\n";
print +(!defined $a[0]) ? "" : "not ", "ok 41\n";

{
    package TH;
    sub TIEHASH { bless {}, $_[0] }
    sub STORE { print "# STORE [@_]\n"; $_[0]->{$_[1]} = $_[2] }
    sub FETCH { my $v = $_[0]->{$_[1]}; print "# FETCH [@_=$v]\n"; $v }
    sub EXISTS { print "# EXISTS [@_]\n"; exists $_[0]->{$_[1]}; }
    sub DELETE { print "# DELETE [@_]\n"; delete $_[0]->{$_[1]}; }
    sub CLEAR { print "# CLEAR [@_]\n"; %{$_[0]} = (); }
}

# see if localization works on tied hashes
tie %h, 'TH';
%h = ('a' => 1, 'b' => 2, 'c' => 3);

{
    local($h{'a'}) = 'foo';
    local($h{'b'}) = $h{'b'};
    local($h{'y'});
    local($h{'z'}) = 33;
    print +($h{'a'} eq 'foo') ? "" : "not ", "ok 42\n";
    print +($h{'b'} == 2) ? "" : "not ", "ok 43\n";
    local($h{'c'});
    delete $h{'c'};
}
print +($h{'a'} == 1) ? "" : "not ", "ok 44\n";
print +($h{'b'} == 2) ? "" : "not ", "ok 45\n";
print +($h{'c'} == 3) ? "" : "not ", "ok 46\n";

@a = ('a', 'b', 'c');
{
    local($a[1]) = "X";
    shift @a;
}
print +($a[0].$a[1] eq "Xb") ? "" : "not ", "ok 47\n";

# now try the same for %SIG

$SIG{TERM} = 'foo';
$SIG{INT} = \&foo;
$SIG{__WARN__} = $SIG{INT};
{
    local($SIG{TERM}) = $SIG{TERM};
    local($SIG{INT}) = $SIG{INT};
    local($SIG{__WARN__}) = $SIG{__WARN__};
    print +($SIG{TERM}		eq 'main::foo') ? "" : "not ", "ok 48\n";
    print +($SIG{INT}		eq \&foo) ? "" : "not ", "ok 49\n";
    print +($SIG{__WARN__}	eq \&foo) ? "" : "not ", "ok 50\n";
    local($SIG{INT});
    delete $SIG{__WARN__};
}
print +($SIG{TERM}	eq 'main::foo') ? "" : "not ", "ok 51\n";
print +($SIG{INT}	eq \&foo) ? "" : "not ", "ok 52\n";
print +($SIG{__WARN__}	eq \&foo) ? "" : "not ", "ok 53\n";

# and for %ENV

$ENV{_X_} = 'a';
$ENV{_Y_} = 'b';
$ENV{_Z_} = 'c';
{
    local($ENV{_A_});
    local($ENV{_B_}) = 'foo';
    local($ENV{_X_}) = 'foo';
    local($ENV{_Y_}) = $ENV{_Y_};
    print +($ENV{_X_} eq 'foo') ? "" : "not ", "ok 54\n";
    print +($ENV{_Y_} eq 'b') ? "" : "not ", "ok 55\n";
    local($ENV{_Z_});
    delete $ENV{_Z_};
}
print +($ENV{_X_} eq 'a') ? "" : "not ", "ok 56\n";
print +($ENV{_Y_} eq 'b') ? "" : "not ", "ok 57\n";
print +($ENV{_Z_} eq 'c') ? "" : "not ", "ok 58\n";

# does implicit localization in foreach skip magic?

$_ = "ok 59,ok 60,";
my $iter = 0;
while (/(o.+?),/gc) {
    print "$1\n";
    foreach (1..1) { $iter++ }
    if ($iter > 2) { print "not ok 60\n"; last; }
}

{
    package UnderScore;
    sub TIESCALAR { bless \my $self, shift }
    sub FETCH { die "read  \$_ forbidden" }
    sub STORE { die "write \$_ forbidden" }
    tie $_, __PACKAGE__;
    my $t = 61;
    my @tests = (
	"Nesting"     => sub { print '#'; for (1..3) { print }
			       print "\n" },			1,
	"Reading"     => sub { print },				0,
	"Matching"    => sub { $x = /badness/ },		0,
	"Concat"      => sub { $_ .= "a" },			0,
	"Chop"        => sub { chop },				0,
	"Filetest"    => sub { -x },				0,
	"Assignment"  => sub { $_ = "Bad" },			0,
	# XXX whether next one should fail is debatable
	"Local \$_"   => sub { local $_  = 'ok?'; print },	0,
	"for local"   => sub { for("#ok?\n"){ print } },	1,
    );
    while ( ($name, $code, $ok) = splice(@tests, 0, 3) ) {
	print "# Testing $name\n";
	eval { &$code };
	print(($ok xor $@) ? "ok $t\n" : "not ok $t\n");
	++$t;
    }
    untie $_;
}

{
    # BUG 20001205.22
    my %x;
    $x{a} = 1;
    { local $x{b} = 1; }
    print "not " if exists $x{b};
    print "ok 70\n";
    { local @x{c,d,e}; }
    print "not " if exists $x{c};
    print "ok 71\n"; 
}

# these tests should be physically located after tests 46 and 58,
# but are here instead to avoid renumbering everything. 

# local() should preserve the existenceness of tied hashes and %ENV
print "not " if exists $h{'y'}; print "ok 72\n";
print "not " if exists $h{'z'}; print "ok 73\n";
print "not " if exists $ENV{_A_}; print "ok 74\n";
print "not " if exists $ENV{_B_}; print "ok 75\n";




Copyright 1998-2008 Alvin Alexander
All Rights Reserved.
 
devdaily.com is based in louisville, kentucky, and this web site is hosted by godaddy.com