summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorGurusamy Sarathy <gsar@cpan.org>1998-03-01 06:52:26 +0000
committerGurusamy Sarathy <gsar@cpan.org>1998-03-01 06:52:26 +0000
commitfbbbcc485c1d03c76a91f998e1e4492c8ad56b38 (patch)
tree3b1a893d2288b11451c4d4419edd75f4f85d2481 /lib
parentc69f6586a27b86846a13e0177336730d72b33c95 (diff)
parent1c1c7f20b839aeb1c04942d0884c3efb087d3e4a (diff)
downloadperl-fbbbcc485c1d03c76a91f998e1e4492c8ad56b38.tar.gz
[asperl] integrate mainline changes
p4raw-id: //depot/asperl@607
Diffstat (limited to 'lib')
-rw-r--r--lib/AutoLoader.pm2
-rw-r--r--lib/Cwd.pm71
-rw-r--r--lib/ExtUtils/MM_VMS.pm14
-rw-r--r--lib/Term/ReadLine.pm43
-rw-r--r--lib/Test.pm131
-rw-r--r--lib/Tie/Handle.pm161
-rw-r--r--lib/perl5db.pl27
7 files changed, 332 insertions, 117 deletions
diff --git a/lib/AutoLoader.pm b/lib/AutoLoader.pm
index 2773a90f10..46e0a4be7a 100644
--- a/lib/AutoLoader.pm
+++ b/lib/AutoLoader.pm
@@ -73,7 +73,7 @@ sub import {
# 'auto/POSIX/autosplit.ix' (without the leading 'lib').
#
- (my $calldir = $callpkg) =~ s#::#/#;
+ (my $calldir = $callpkg) =~ s#::#/#g;
my $path = $INC{$calldir . '.pm'};
if (defined($path)) {
# Try absolute path name.
diff --git a/lib/Cwd.pm b/lib/Cwd.pm
index 19ff497759..652ee7e493 100644
--- a/lib/Cwd.pm
+++ b/lib/Cwd.pm
@@ -54,7 +54,7 @@ kept up to date if all packages which use chdir import it from Cwd.
use Carp;
-$VERSION = '2.00';
+$VERSION = '2.01';
require Exporter;
@ISA = qw(Exporter);
@@ -82,66 +82,9 @@ sub _backtick_pwd {
sub getcwd
{
- my($dotdots, $cwd, @pst, @cst, $dir, @tst);
-
- unless (@cst = stat('.'))
- {
- warn "stat(.): $!";
- return '';
- }
- $cwd = '';
- $dotdots = '';
- do
- {
- $dotdots .= '/' if $dotdots;
- $dotdots .= '..';
- @pst = @cst;
- unless (opendir(PARENT, $dotdots))
- {
- warn "opendir($dotdots): $!";
- return '';
- }
- unless (@cst = stat($dotdots))
- {
- warn "stat($dotdots): $!";
- closedir(PARENT);
- return '';
- }
- if ($pst[0] == $cst[0] && $pst[1] == $cst[1])
- {
- $dir = undef;
- }
- else
- {
- do
- {
- unless (defined ($dir = readdir(PARENT)))
- {
- warn "readdir($dotdots): $!";
- closedir(PARENT);
- return '';
- }
- unless (@tst = lstat("$dotdots/$dir"))
- {
- # warn "lstat($dotdots/$dir): $!";
- # Just because you can't lstat this directory
- # doesn't mean you'll never find the right one.
- # closedir(PARENT);
- # return '';
- }
- }
- while ($dir eq '.' || $dir eq '..' || $tst[0] != $pst[0] ||
- $tst[1] != $pst[1]);
- }
- $cwd = (defined $dir ? "$dir" : "" ) . "/$cwd" ;
- closedir(PARENT);
- } while (defined $dir);
- chop($cwd) unless $cwd eq '/'; # drop the trailing /
- $cwd;
+ abs_path('.');
}
-
-
# By John Bazik
#
# Usage: $cwd = &fastcwd;
@@ -249,7 +192,7 @@ sub chdir {
sub abs_path
{
- my $start = shift || '.';
+ my $start = @_ ? shift : '.';
my($dotdots, $cwd, @pst, @cst, $dir, @tst);
unless (@cst = stat( $start ))
@@ -276,7 +219,7 @@ sub abs_path
}
if ($pst[0] == $cst[0] && $pst[1] == $cst[1])
{
- $dir = '';
+ $dir = undef;
}
else
{
@@ -293,10 +236,10 @@ sub abs_path
while ($dir eq '.' || $dir eq '..' || $tst[0] != $pst[0] ||
$tst[1] != $pst[1]);
}
- $cwd = "$dir/$cwd";
+ $cwd = (defined $dir ? "$dir" : "" ) . "/$cwd" ;
closedir(PARENT);
- } while ($dir);
- chop($cwd); # drop the trailing /
+ } while (defined $dir);
+ chop($cwd) unless $cwd eq '/'; # drop the trailing /
$cwd;
}
diff --git a/lib/ExtUtils/MM_VMS.pm b/lib/ExtUtils/MM_VMS.pm
index dc3b4ceca6..954f6123d5 100644
--- a/lib/ExtUtils/MM_VMS.pm
+++ b/lib/ExtUtils/MM_VMS.pm
@@ -1422,7 +1422,21 @@ $(INST_STATIC) : $(OBJECT) $(MYEXTLIB)
push(@m,'
If F$Search("$(MMS$TARGET)").eqs."" Then Library/Object/Create $(MMS$TARGET)
+');
+ # if there was a library to copy, then we can't use MMS$SOURCE_LIST,
+ # 'cause it's a library and you can't stick them in other libraries.
+ # In that case, we use $OBJECT instead and hope for the best
+ if ($self->{MYEXTLIB}) {
+ push(@m,'
+ Library/Object/Replace $(MMS$TARGET) $(OBJECT)
+');
+ } else {
+ push(@m,'
Library/Object/Replace $(MMS$TARGET) $(MMS$SOURCE_LIST)
+');
+ }
+
+ push(@m, '
$(NOECHO) $(PERL) -e "open F,\'>>$(INST_ARCHAUTODIR)extralibs.ld\';print F qq{$(EXTRALIBS)\n};close F;"
');
push @m, $self->dir_target('$(INST_ARCHAUTODIR)');
diff --git a/lib/Term/ReadLine.pm b/lib/Term/ReadLine.pm
index b6923dd1e7..6b0b5e7f23 100644
--- a/lib/Term/ReadLine.pm
+++ b/lib/Term/ReadLine.pm
@@ -139,12 +139,23 @@ None
=head1 ENVIRONMENT
-The variable C<PERL_RL> governs which ReadLine clone is loaded. If the
-value is false, a dummy interface is used. If the value is true, it
-should be tail of the name of the package to use, such as C<Perl> or
-C<Gnu>.
+The envrironment variable C<PERL_RL> governs which ReadLine clone is
+loaded. If the value is false, a dummy interface is used. If the value
+is true, it should be tail of the name of the package to use, such as
+C<Perl> or C<Gnu>.
-If the variable is not set, the best available package is loaded.
+As a special case, if the value of this variable is space-separated,
+the tail might be used to disable the ornaments by setting the tail to
+be C<o=0> or C<ornaments=0>. The head should be as described above, say
+
+If the variable is not set, or if the head of space-separated list is
+empty, the best available package is loaded.
+
+ export "PERL_RL=Perl o=0" # Use Perl ReadLine without ornaments
+ export "PERL_RL= o=0" # Use best available ReadLine without ornaments
+
+(Note that processing of C<PERL_RL> for ornaments is in the discretion of the
+particular used C<Term::ReadLine::*> package).
=cut
@@ -205,7 +216,7 @@ sub new {
die "method new called with wrong number of arguments"
unless @_==2 or @_==4;
#local (*FIN, *FOUT);
- my ($FIN, $FOUT);
+ my ($FIN, $FOUT, $ret);
if (@_==2) {
($console, $consoleOUT) = findConsole;
@@ -215,15 +226,21 @@ sub new {
$sel = select(FOUT);
$| = 1; # for DB::OUT
select($sel);
- bless [\*FIN, \*FOUT];
+ $ret = bless [\*FIN, \*FOUT];
} else { # Filehandles supplied
$FIN = $_[2]; $FOUT = $_[3];
#OUT->autoflush(1); # Conflicts with debugger?
$sel = select($FOUT);
$| = 1; # for DB::OUT
select($sel);
- bless [$FIN, $FOUT];
+ $ret = bless [$FIN, $FOUT];
}
+ if ($ret->Features->{ornaments}
+ and not ($ENV{PERL_RL} and $ENV{PERL_RL} =~ /\bo\w*=0/)) {
+ local $Term::ReadLine::termcap_nowarn = 1;
+ $ret->ornaments(1);
+ }
+ return $ret;
}
sub newTTY {
@@ -245,7 +262,7 @@ sub Features { \%features }
package Term::ReadLine; # So late to allow the above code be defined?
-my $which = $ENV{PERL_RL};
+my ($which) = exists $ENV{PERL_RL} ? split /\s+/, $ENV{PERL_RL} : undef;
if ($which) {
if ($which =~ /\bgnu\b/i){
eval "use Term::ReadLine::Gnu;";
@@ -254,7 +271,7 @@ if ($which) {
} else {
eval "use Term::ReadLine::$which;";
}
-} elsif (defined $which) { # Defined but false
+} elsif (defined $which and $which ne '') { # Defined but false
# Do nothing fancy
} else {
eval "use Term::ReadLine::Gnu; 1" or eval "use Term::ReadLine::Perl; 1";
@@ -296,7 +313,11 @@ sub ornaments {
$rl_term_set = 'us,ue,md,me' if $rl_term_set == 1;
my @ts = split /,/, $rl_term_set, 4;
eval { LoadTermCap };
- warn("Cannot find termcap: $@\n"), return unless defined $terminal;
+ unless (defined $terminal) {
+ warn("Cannot find termcap: $@\n") unless $Term::ReadLine::termcap_nowarn;
+ $rl_term_set = ',,,';
+ return;
+ }
@rl_term_set = map {$_ ? $terminal->Tputs($_,1) || '' : ''} @ts;
return $rl_term_set;
}
diff --git a/lib/Test.pm b/lib/Test.pm
index 7e79da2bf4..b10d104ded 100644
--- a/lib/Test.pm
+++ b/lib/Test.pm
@@ -2,18 +2,19 @@ use strict;
package Test;
use Test::Harness 1.1601 ();
use Carp;
-use vars qw($VERSION @ISA @EXPORT $ntest %todo);
-$VERSION = '0.06';
+use vars qw($VERSION @ISA @EXPORT $ntest %todo %history $TestLevel);
+$VERSION = '0.08';
require Exporter;
@ISA=('Exporter');
@EXPORT= qw(&plan &ok &skip $ntest);
+$TestLevel = 0; # how many extra stack frames to skip
$|=1;
#$^W=1; ?
$ntest=1;
-# Use of this variable is strongly discouraged. It is set
-# exclusively for test coverage analyzers.
+# Use of this variable is strongly discouraged. It is set mainly to
+# help test coverage analyzers know which test is running.
$ENV{REGRESSION_TEST} = $0;
sub plan {
@@ -34,33 +35,81 @@ sub plan {
}
}
+sub to_value {
+ my ($v) = @_;
+ (ref $v or '') eq 'CODE' ? $v->() : $v;
+}
+
+# prototypes are not used for maximum flexibility
+
+# STDERR is NOT used for diagnostic output that should be fixed before
+# the module is released.
+
sub ok {
- my ($ok, $guess) = @_;
- carp "(this is ok $ntest)" if defined $guess && $guess != $ntest;
- $ok = $ok->() if (ref $ok or '') eq 'CODE';
- if ($ok) {
+ my ($pkg,$file,$line) = caller($TestLevel);
+ my $repetition = ++$history{"$file:$line"};
+ my $context = ("$file at line $line".
+ ($repetition > 1 ? " (\#$repetition)" : ''));
+ my $ok=0;
+
+ if (@_ == 0) {
+ print "not ok $ntest\n";
+ print "# test $context: DOESN'T TEST ANYTHING!\n";
+ } else {
+ my $result = to_value(shift);
+ my ($expected,$diag);
+ if (@_ == 0) {
+ $ok = $result;
+ } else {
+ $expected = to_value(shift);
+ $ok = $result eq $expected;
+ }
if ($todo{$ntest}) {
- print("ok $ntest # Wow!\n");
+ if ($ok) {
+ print "ok $ntest # Wow!\n";
+ } else {
+ $diag = to_value(shift) if @_;
+ if (!$diag) {
+ print "not ok $ntest # (failure expected)\n";
+ } else {
+ print "not ok $ntest # (failure expected: $diag)\n";
+ }
+ }
} else {
- print("ok $ntest # (failure expected)\n");
+ print "not " if !$ok;
+ print "ok $ntest\n";
+
+ if (!$ok) {
+ $diag = to_value(shift) if @_;
+ if (!defined $expected) {
+ if (!$diag) {
+ print STDERR "# Failed $context\n";
+ } else {
+ print STDERR "# Failed $context: $diag\n";
+ }
+ } else {
+ print STDERR "# Got: '$result' ($context)\n";
+ if (!$diag) {
+ print STDERR "# Expected: '$expected'\n";
+ } else {
+ print STDERR "# Expected: '$expected' ($diag)\n";
+ }
+ }
+ }
}
- } else {
- print("not ok $ntest\n");
}
++ $ntest;
$ok;
}
sub skip {
- my ($toskip, $ok, $guess) = @_;
- carp "(this is skip $ntest)" if defined $guess && $guess != $ntest;
- $toskip = $toskip->() if (ref $toskip or '') eq 'CODE';
- if ($toskip) {
+ if (to_value(shift)) {
print "ok $ntest # skip\n";
++ $ntest;
1;
} else {
- ok($ok);
+ local($TestLevel) += 1; #ignore this stack frame
+ ok(@_);
}
}
@@ -75,42 +124,54 @@ __END__
use strict;
use Test;
- BEGIN { plan tests => 5, todo => [3,4] }
+ BEGIN { plan tests => 12, todo => [3,4] }
+
+ ok(0); # failure
+ ok(1); # success
+
+ ok(0); # ok, expected failure (see todo list, above)
+ ok(1); # surprise success!
+
+ ok(0,1); # failure: '0' ne '1'
+ ok('broke','fixed'); # failure: 'broke' ne 'fixed'
+ ok('fixed','fixed'); # success: 'fixed' eq 'fixed'
- ok(0); #failure
- ok(1); #success
+ ok(sub { 1+1 }, 2); # success: '2' eq '2'
+ ok(sub { 1+1 }, 3); # failure: '2' ne '3'
+ ok(0, int(rand(2)); # (just kidding! :-)
- ok(0); #ok, expected failure (see todo above)
- ok(1); #surprise success!
+ my @list = (0,0);
+ ok(scalar(@list), 3, "\@list=".join(',',@list)); #extra diagnostics
- skip($feature_is_missing, sub {...}); #do platform specific test
+ skip($feature_is_missing, ...); #do platform specific test
=head1 DESCRIPTION
-Test::Harness expects to see particular output when it executes test
-scripts. This module tries to make conforming just a little bit
-easier (and less error prone).
+Test::Harness expects to see particular output when it executes tests.
+This module aims to make writing proper test scripts just a little bit
+easier (and less error prone :-).
-=head1 TEST CATEGORIES
+=head1 TEST TYPES
=over 4
=item * NORMAL TESTS
-These tests are expected to succeed. If they don't, something is
-wrong!
+These tests are expected to succeed. If they don't, something's
+screwed up!
=item * SKIPPED TESTS
-C<skip> should be used to skip tests for which a platform specific
-feature isn't available.
+Skip tests need a platform specific feature that might or might not be
+available. The first argument should evaluate to true if the required
+feature is NOT available. After the first argument, skip tests work
+exactly the same way as do normal tests.
=item * TODO TESTS
-TODO tests are designed for the purpose of maintaining an executable
-TODO list. These tests are expected NOT to succeed (otherwise the
-feature they test would be on the new feature list, not the TODO
-list).
+TODO tests are designed for maintaining an executable TODO list.
+These tests are expected NOT to succeed (otherwise the feature they
+test would be on the new feature list, not the TODO list).
Packages should NOT be released with successful TODO tests. As soon
as a TODO test starts working, it should be promoted to a normal test
diff --git a/lib/Tie/Handle.pm b/lib/Tie/Handle.pm
new file mode 100644
index 0000000000..c7550530b8
--- /dev/null
+++ b/lib/Tie/Handle.pm
@@ -0,0 +1,161 @@
+package Tie::Handle;
+
+=head1 NAME
+
+Tie::Handle - base class definitions for tied handles
+
+=head1 SYNOPSIS
+
+ package NewHandle;
+ require Tie::Handle;
+
+ @ISA = (Tie::Handle);
+
+ sub READ { ... } # Provide a needed method
+ sub TIEHANDLE { ... } # Overrides inherited method
+
+
+ package main;
+
+ tie *FH, 'NewHandle';
+
+=head1 DESCRIPTION
+
+This module provides some skeletal methods for handle-tying classes. See
+L<perltie> for a list of the functions required in tying a handle to a package.
+The basic B<Tie::Handle> package provides a C<new> method, as well as methods
+C<TIESCALAR>, C<FETCH> and C<STORE>. The C<new> method is provided as a means
+of grandfathering, for classes that forget to provide their own C<TIESCALAR>
+method.
+
+For developers wishing to write their own tied-handle classes, the methods
+are summarized below. The L<perltie> section not only documents these, but
+has sample code as well:
+
+=over
+
+=item TIEHANDLE classname, LIST
+
+The method invoked by the command C<tie *glob, classname>. Associates a new
+glob instance with the specified class. C<LIST> would represent additional
+arguments (along the lines of L<AnyDBM_File> and compatriots) needed to
+complete the association.
+
+=item WRITE this, scalar, length, offset
+
+Write I<length> bytes of data from I<scalar> starting at I<offset>.
+
+=item PRINT this, LIST
+
+Print the values in I<LIST>
+
+=item PRINTF this, format, LIST
+
+Print the values in I<LIST> using I<format>
+
+=item READ this, scalar, length, offset
+
+Read I<length> bytes of data into I<scalar> starting at I<offset>.
+
+=item READLINE this
+
+Read a single line
+
+=item GETC this
+
+Get a single character
+
+=item DESTROY this
+
+Free the storage associated with the tied handle referenced by I<this>.
+This is rarely needed, as Perl manages its memory quite well. But the
+option exists, should a class wish to perform specific actions upon the
+destruction of an instance.
+
+=back
+
+=head1 MORE INFORMATION
+
+The L<perltie> section contains an example of tying handles.
+
+=cut
+
+use Carp;
+
+sub new {
+ my $pkg = shift;
+ $pkg->TIEHANDLE(@_);
+}
+
+# "Grandfather" the new, a la Tie::Hash
+
+sub TIEHANDLE {
+ my $pkg = shift;
+ if (defined &{"{$pkg}::new"}) {
+ carp "WARNING: calling ${pkg}->new since ${pkg}->TIEHANDLE is missing"
+ if $^W;
+ $pkg->new(@_);
+ }
+ else {
+ croak "$pkg doesn't define a TIEHANDLE method";
+ }
+}
+
+sub PRINT {
+ my $self = shift;
+ if($self->can('WRITE') != \&WRITE) {
+ my $buf = join(defined $, ? $, : "",@_);
+ $buf .= $\ if defined $\;
+ $self->WRITE($buf,length($buf),0);
+ }
+ else {
+ croak ref($self)," doesn't define a PRINT method";
+ }
+}
+
+sub PRINTF {
+ my $self = shift;
+
+ if($self->can('WRITE') != \&WRITE) {
+ my $buf = sprintf(@_);
+ $self->WRITE($buf,length($buf),0);
+ }
+ else {
+ croak ref($self)," doesn't define a PRINTF method";
+ }
+}
+
+sub READLINE {
+ my $pkg = ref $_[0];
+ croak "$pkg doesn't define a READLINE method";
+}
+
+sub GETC {
+ my $self = shift;
+
+ if($self->can('READ') != \&READ) {
+ my $buf;
+ $self->READ($buf,1);
+ return $buf;
+ }
+ else {
+ croak ref($self)," doesn't define a GETC method";
+ }
+}
+
+sub READ {
+ my $pkg = ref $_[0];
+ croak "$pkg doesn't define a READ method";
+}
+
+sub WRITE {
+ my $pkg = ref $_[0];
+ croak "$pkg doesn't define a WRITE method";
+}
+
+sub CLOSE {
+ my $pkg = ref $_[0];
+ croak "$pkg doesn't define a CLOSE method";
+}
+
+1;
diff --git a/lib/perl5db.pl b/lib/perl5db.pl
index 9048ed2baf..a4a1b1aae6 100644
--- a/lib/perl5db.pl
+++ b/lib/perl5db.pl
@@ -390,9 +390,9 @@ sub DB {
if ($val ne $old_watch[$n]) {
$signal = 1;
print $OUT <<EOP;
-Watchpoint $n: $to_watch[$n] changed:
-old value: $old_watch[$n]
-new value: $val
+Watchpoint $n:\t$to_watch[$n] changed:
+ old value:\t$old_watch[$n]
+ new value:\t$val
EOP
$old_watch[$n] = $val;
}
@@ -409,6 +409,15 @@ EOP
if ($emacs) {
$position = "\032\032$filename:$line:0\n";
print $LINEINFO $position;
+ } elsif ($package eq 'DB::fake') {
+ print_help(<<EOP);
+Debugged program terminated. Use B<q> to quit or B<R> to restart,
+ use B<O> I<inhibit_exit> to avoid stopping after program termination,
+ B<h q>, B<h R> or B<h O> to get additional info.
+EOP
+ $package = 'main';
+ $usercontext = '($@, $!, $,, $/, $\, $^W) = @saved;' .
+ "package $package;"; # this won't let them modify, alas
} else {
$sub =~ s/\'/::/;
$prefix = $sub =~ /::/ ? "" : "${'package'}::";
@@ -1461,8 +1470,14 @@ sub resetterm { # We forked, so we need a different TTY
TTY($fork_TTY);
undef $fork_TTY;
} else {
- print $OUT "Forked, but do not know how to change a TTY.\n",
- "Define \$DB::fork_TTY or get_fork_TTY().\n";
+ print_help(<<EOP);
+I<#########> Forked, but do not know how to change a B<TTY>. I<#########>
+ Define B<\$DB::fork_TTY>
+ - or a function B<DB::get_fork_TTY()> which will set B<\$DB::fork_TTY>.
+ The value of B<\$DB::fork_TTY> should be the name of I<TTY> to use.
+ On I<UNIX>-like systems one can get the name of a I<TTY> for the given window
+ by typing B<tty>, and disconnect the I<shell> from I<TTY> by B<sleep 1000000>.
+EOP
}
}
@@ -1824,7 +1839,7 @@ B<R> Pure-man-restart of debugger, some of debugger state
and the following command-line options: I<-w>, I<-I>, I<-e>.
B<h> [I<db_command>] Get help [on a specific debugger command], enter B<|h> to page.
B<h h> Summary of debugger commands.
-B<q> or B<^D> Quit. Set \$DB::finished to 0 to debug global destruction.
+B<q> or B<^D> Quit. Set B<\$DB::finished = 0> to debug global destruction.
";
$summary = <<"END_SUM";