diff options
author | Perl 5 Porters <perl5-porters@africa.nicoh.com> | 1996-02-02 18:52:27 -0800 |
---|---|---|
committer | Larry Wall <lwall@sems.com> | 1996-02-02 18:52:27 -0800 |
commit | c07a80fdfe3926b5eb0585b674aa5d1f57b32ade (patch) | |
tree | 6d56135571eb9ea6635748469bdaf72ad481247a /lib | |
parent | 91b7def858c29dac014df40946a128c06b3aa2ed (diff) | |
download | perl-c07a80fdfe3926b5eb0585b674aa5d1f57b32ade.tar.gz |
perl5.002beta3
[editor's note: no patch file was found for this release, so no
fine-grained changes]
I can't find the password for our ftp server, so I had to drop it into
ftp://ftp.sems.com/pub/incoming/perl5.002b3.tar.gz, which is a drop
directory you can't ls.
The current plan is that Andy is gonna whack on this a little more, and
then release a gamma in a few days when he's happy with it. So don't get
carried away. This is now *late* beta.
In other words, have less than the appropriate amount of fun. :-)
Larry
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Carp.pm | 22 | ||||
-rw-r--r-- | lib/DirHandle.pm | 72 | ||||
-rw-r--r-- | lib/Exporter.pm | 6 | ||||
-rw-r--r-- | lib/ExtUtils/Liblist.pm | 11 | ||||
-rw-r--r-- | lib/ExtUtils/MM_VMS.pm | 299 | ||||
-rw-r--r-- | lib/ExtUtils/MakeMaker.pm | 133 | ||||
-rw-r--r-- | lib/ExtUtils/Mksymlists.pm | 217 | ||||
-rw-r--r-- | lib/ExtUtils/typemap | 6 | ||||
-rwxr-xr-x | lib/ExtUtils/xsubpp | 50 | ||||
-rw-r--r-- | lib/FileCache.pm | 78 | ||||
-rw-r--r-- | lib/FileHandle.pm | 390 | ||||
-rw-r--r-- | lib/Getopt/Long.pm | 5 | ||||
-rw-r--r-- | lib/IPC/Open2.pm | 4 | ||||
-rw-r--r-- | lib/IPC/Open3.pm | 6 | ||||
-rw-r--r-- | lib/SelectSaver.pm | 50 | ||||
-rw-r--r-- | lib/Symbol.pm | 99 | ||||
-rw-r--r-- | lib/Term/Cap.pm | 7 | ||||
-rw-r--r-- | lib/Term/ReadLine.pm | 9 | ||||
-rw-r--r-- | lib/Test/Harness.pm | 169 | ||||
-rw-r--r-- | lib/complete.pl | 2 | ||||
-rwxr-xr-x | lib/diagnostics.pm | 6 | ||||
-rw-r--r-- | lib/perl5db.pl | 585 | ||||
-rw-r--r-- | lib/subs.pm | 2 | ||||
-rw-r--r-- | lib/vars.pm | 39 |
24 files changed, 1229 insertions, 1038 deletions
diff --git a/lib/Carp.pm b/lib/Carp.pm index 2d857ba4e7..f30bd24135 100644 --- a/lib/Carp.pm +++ b/lib/Carp.pm @@ -28,6 +28,7 @@ not where carp() was called. # exceptions outside of the current package. $CarpLevel = 0; # How many extra package levels to skip on carp. +$MaxEvalLen = 0; # How much eval '...text...' to show. 0 = all. require Exporter; @ISA = Exporter; @@ -37,11 +38,24 @@ sub longmess { my $error = shift; my $mess = ""; my $i = 1 + $CarpLevel; - my ($pack,$file,$line,$sub); - while (($pack,$file,$line,$sub) = caller($i++)) { + my ($pack,$file,$line,$sub,$eval,$require); + while (($pack,$file,$line,$sub,undef,undef,$eval,$require) = caller($i++)) { if ($error =~ m/\n$/) { $mess .= $error; } else { + if (defined $eval) { + if ($require) { + $sub = "require $eval"; + } else { + $eval =~ s/[\\\']/\\$&/g; + if ($MaxEvalLen && length($eval) > $MaxEvalLen) { + substr($eval,$MaxEvalLen) = '...'; + } + $sub = "eval '$eval'"; + } + } elsif ($sub eq '(eval)') { + $sub = 'eval {...}'; + } $mess .= "\t$sub " if $error eq "called"; $mess .= "$error at $file line $line\n"; } @@ -55,8 +69,8 @@ sub shortmess { # Short-circuit &longmess if called via multiple packages my ($curpack) = caller(1); my $extra = $CarpLevel; my $i = 2; - my ($pack,$file,$line,$sub); - while (($pack,$file,$line,$sub) = caller($i++)) { + my ($pack,$file,$line); + while (($pack,$file,$line) = caller($i++)) { if ($pack ne $curpack) { if ($extra-- > 0) { $curpack = $pack; diff --git a/lib/DirHandle.pm b/lib/DirHandle.pm new file mode 100644 index 0000000000..047755dc17 --- /dev/null +++ b/lib/DirHandle.pm @@ -0,0 +1,72 @@ +package DirHandle; + +=head1 NAME + +DirHandle - supply object methods for directory handles + +=head1 SYNOPSIS + + use DirHandle; + $d = new DirHandle "."; + if (defined $d) { + while (defined($_ = $d->read)) { something($_); } + $d->rewind; + while (defined($_ = $d->read)) { something_else($_); } + undef $d; + } + +=head1 DESCRIPTION + +The C<DirHandle> method provide an alternative interface to the +opendir(), closedir(), readdir(), and rewinddir() functions. + +The only objective benefit to using C<DirHandle> is that it avoids +namespace pollution by creating globs to hold directory handles. + +=cut + +require 5.000; +use Carp; +use Symbol; + +sub new { + @_ >= 1 && @_ <= 2 or croak 'usage: new DirHandle [DIRNAME]'; + my $class = shift; + my $dh = gensym; + if (@_) { + DirHandle::open($dh, $_[0]) + or return undef; + } + bless $dh, $class; +} + +sub DESTROY { + my ($dh) = @_; + closedir($dh); +} + +sub open { + @_ == 2 or croak 'usage: $dh->open(DIRNAME)'; + my ($dh, $dirname) = @_; + opendir($dh, $dirname); +} + +sub close { + @_ == 1 or croak 'usage: $dh->close()'; + my ($dh) = @_; + closedir($dh); +} + +sub read { + @_ == 1 or croak 'usage: $dh->read()'; + my ($dh) = @_; + readdir($dh); +} + +sub rewind { + @_ == 1 or croak 'usage: $dh->rewind()'; + my ($dh) = @_; + rewinddir($dh); +} + +1; diff --git a/lib/Exporter.pm b/lib/Exporter.pm index de0155b548..90a41d644b 100644 --- a/lib/Exporter.pm +++ b/lib/Exporter.pm @@ -3,7 +3,7 @@ package Exporter; require 5.001; $ExportLevel = 0; -$Verbose = 0; +$Verbose = 0 unless $Verbose; require Carp; @@ -125,7 +125,7 @@ sub export { } } - warn "Importing from $pkg into $callpkg: ", + warn "Importing into $callpkg from $pkg: ", join(", ",sort @imports) if $Verbose; foreach $sym (@imports) { @@ -155,7 +155,7 @@ sub import { sub _push_tags { my($pkg, $var, $syms) = @_; my $nontag; - *export_tags = *{"${pkg}::EXPORT_TAGS"}; + *export_tags = \%{"${pkg}::EXPORT_TAGS"}; push(@{"${pkg}::$var"}, map { $export_tags{$_} ? @{$export_tags{$_}} : scalar(++$nontag,$_) } (@$syms) ? @$syms : keys %export_tags); diff --git a/lib/ExtUtils/Liblist.pm b/lib/ExtUtils/Liblist.pm index ebb2536382..94d343bbf4 100644 --- a/lib/ExtUtils/Liblist.pm +++ b/lib/ExtUtils/Liblist.pm @@ -104,6 +104,17 @@ sub ext { } elsif (-f ($fullname="$thispth/lib$thislib$Config_libext")){ } elsif (-f ($fullname="$thispth/$thislib$Config_libext")){ } elsif (-f ($fullname="$thispth/Slib$thislib$Config_libext")){ + } elsif ($Config{'osname'} eq 'dgux' + && -l ($fullname="$thispth/lib$thislib$Config_libext") + && readlink($fullname) =~ /^elink:/) { + # Some of DG's libraries look like misconnected symbolic + # links, but development tools can follow them. (They + # look like this: + # + # libm.a -> elink:${SDE_PATH:-/usr}/sde/\ + # ${TARGET_BINARY_INTERFACE:-m88kdgux}/usr/lib/libm.a + # + # , the compilation tools expand the environment variables.) } else { print STDOUT "$thislib not found in $thispth\n" if $Verbose; next; diff --git a/lib/ExtUtils/MM_VMS.pm b/lib/ExtUtils/MM_VMS.pm index 158c55a508..fde022ca06 100644 --- a/lib/ExtUtils/MM_VMS.pm +++ b/lib/ExtUtils/MM_VMS.pm @@ -1,11 +1,11 @@ # MM_VMS.pm # MakeMaker default methods for VMS # This package is inserted into @ISA of MakeMaker's MM before the -# built-in MM_Unix methods if MakeMaker.pm is run under VMS. +# built-in ExtUtils::MM_Unix methods if MakeMaker.pm is run under VMS. # -# Version: 5.16 +# Version: 5.17 # Author: Charles Bailey bailey@genetics.upenn.edu -# Revised: 03-Jan-1996 +# Revised: 14-Jan-1996 package ExtUtils::MM_VMS; @@ -88,14 +88,17 @@ sub catdir { $self = $ExtUtils::MakeMaker::Parent[-1]; } my($dir) = pop @dirs; - my($path) = (@dirs == 1 ? $dirs[0] : $self->catdir(@dirs)); - my($spath,$sdir) = ($path,$dir); - $spath =~ s/.dir$//; $sdir =~ s/.dir$//; - $sdir = $self->eliminate_macros($sdir) unless $sdir =~ /^[\w\-]+$/; + @dirs = grep($_,@dirs); my($rslt); - - $rslt = vmspath($self->eliminate_macros($spath)."/$sdir"); - print "catdir($path,$dir) = |$rslt|\n" if $Verbose >= 3; + if (@dirs) { + my($path) = (@dirs == 1 ? $dirs[0] : $self->catdir(@dirs)); + my($spath,$sdir) = ($path,$dir); + $spath =~ s/.dir$//; $sdir =~ s/.dir$//; + $sdir = $self->eliminate_macros($sdir) unless $sdir =~ /^[\w\-]+$/; + $rslt = vmspath($self->eliminate_macros($spath)."/$sdir"); + } + else { $rslt = vmspath($dir); } + print "catdir(",join(',',@_[1..$#_]),") = |$rslt|\n" if $Verbose >= 3; $rslt; } @@ -106,13 +109,20 @@ sub catfile { $self = $ExtUtils::MakeMaker::Parent[-1]; } my($file) = pop @files; - my($path) = (@files == 1 ? $files[0] : $self->catdir(@files)); - my($spath) = $path; - $spath =~ s/.dir$//; + @files = grep($_,@files); my($rslt); - if ( $spath =~ /^[^\)\]\/:>]+\)$/ && basename($file) eq $file) { $rslt = "$spath$file"; } - else { $rslt = vmsify($self->eliminate_macros($spath).'/'.unixify($file)); } - print "catfile($path,$file) = |$rslt|\n" if $Verbose >= 3; + if (@files) { + my($path) = (@files == 1 ? $files[0] : $self->catdir(@files)); + my($spath) = $path; + $spath =~ s/.dir$//; + if ( $spath =~ /^[^\)\]\/:>]+\)$/ && basename($file) eq $file) { $rslt = "$spath$file"; } + else { + $rslt = $self->eliminate_macros($spath); + $rslt = vmsify($rslt.($rslt ? '/' : '').unixify($file)); + } + } + else { $rslt = vmsify($file); } + print "catfile(",join(',',@_[1..$#_]),") = |$rslt|\n" if $Verbose >= 3; $rslt; } @@ -263,15 +273,17 @@ sub init_others { $self->{NOOP} = "\t@ Continue"; $self->{FIRST_MAKEFILE} ||= 'Descrip.MMS'; + $self->{MAKE_APERL_FILE} ||= 'Makeaperl.MMS'; $self->{MAKEFILE} ||= $self->{FIRST_MAKEFILE}; + $self->{NOECHO} ||= '@ '; $self->{RM_F} = '$(PERL) -e "foreach (@ARGV) { 1 while ( -d $_ ? rmdir $_ : unlink $_)}"'; - $self->{RM_RF} = '$(PERL) -e "use File::Path; @dirs = map(VMS::Filespec::unixify($_),@ARGV); rmtree(\@dirs,0,0)"'; + $self->{RM_RF} = '$(PERL) "-I$(INST_LIB)" -e "use File::Path; @dirs = map(VMS::Filespec::unixify($_),@ARGV); rmtree(\@dirs,0,0)"'; $self->{TOUCH} = '$(PERL) -e "$t=time; foreach (@ARGV) { -e $_ ? utime($t,$t,@ARGV) : (open(F,qq(>$_)),close F)}"'; $self->{CHMOD} = '$(PERL) -e "chmod @ARGV"'; # expect Unix syntax from MakeMaker $self->{CP} = 'Copy/NoConfirm'; $self->{MV} = 'Rename/NoConfirm'; $self->{UMASK_NULL} = "\t!"; - &MM_Unix::init_others; + &ExtUtils::MM_Unix::init_others; } sub constants { @@ -343,7 +355,14 @@ FULLEXT = ",$self->fixpath($self->{FULLEXT},1)," BASEEXT = $self->{BASEEXT} ROOTEXT = ",($self->{ROOTEXT} eq '') ? '[]' : $self->fixpath($self->{ROOTEXT},1)," DLBASE = $self->{DLBASE} -INC = "; +"; + + push @m, " +VERSION_FROM = $self->{VERSION_FROM} +" if defined $self->{VERSION_FROM}; + + push @m,' +INC = '; if ($self->{'INC'}) { push @m,'/Include=('; @@ -404,7 +423,7 @@ MAN3EXT = $self->{MAN3EXT} MYEXTLIB = ",$self->fixpath($self->{MYEXTLIB})," # Here is the Config.pm that we are using/depend on -CONFIGDEP = \$(PERL_ARCHLIB)Config.pm, \$(PERL_INC)config.h +CONFIGDEP = \$(PERL_ARCHLIB)Config.pm, \$(PERL_INC)config.h \$(VERSION_FROM) # Where to put things: INST_LIBDIR = ",($self->{'INST_LIBDIR'} = $self->catdir($self->{INST_LIB},$self->{ROOTEXT}))," @@ -425,6 +444,8 @@ INST_BOOT = $(INST_ARCHAUTODIR)$(BASEEXT).bs INST_STATIC = INST_DYNAMIC = INST_BOOT = +EXPORT_LIST = $(BASEEXT).opt +PERL_ARCHIVE = ',($ENV{'PERLSHR'} ? $ENV{'PERLSHR'} : 'Sys$Share:PerlShr.Exe'),' '; } @@ -537,7 +558,7 @@ sub const_cccmd { if ($Config{'vms_cc_type'} ne 'decc') { push @m,' .FIRST - @ If F$TrnLnm("Sys").eqs."" Then Define/NoLog SYS ', + ',$self->{NOECHO},'If F$TrnLnm("Sys").eqs."" Then Define/NoLog SYS ', ($Config{'vms_cc_type'} eq 'gcc' ? 'GNU_CC_Include:[VMS]' : 'Sys$Library'),' @@ -677,7 +698,7 @@ sub tools_other { ExtUtils::MakeMaker::TieAtt::warndirectuse((caller(0))[3]); $self = $ExtUtils::MakeMaker::Parent[-1]; } - " + qq! # Assumes \$(MMS) invokes MMS or MMK # (It is assumed in some cases later that the default makefile name # (Descrip.MMS for MM[SK]) is used.) @@ -694,7 +715,8 @@ RM_F = $self->{RM_F} RM_RF = $self->{RM_RF} UMASK_NULL = $self->{UMASK_NULL} MKPATH = Create/Directory -"; +EQUALIZE_TIMESTAMP = \$(PERL) -we "open F,"">\$ARGV[1]"";close F;utime((stat(""\$ARGV[0]""))[8,9],\$ARGV[1])" +!; } @@ -789,7 +811,7 @@ sub top_targets { } my(@m); push @m, ' -all :: config $(INST_PM) subdirs linkext manifypods +all :: config $(INST_PM) subdirs linkext manifypods reorg_packlist $(NOOP) subdirs :: $(MYEXTLIB) @@ -809,7 +831,7 @@ config :: $(INST_AUTODIR).exists push @m, $self->dir_target(qw[$(INST_AUTODIR) $(INST_LIBDIR) $(INST_ARCHAUTODIR)]); if (%{$self->{MAN1PODS}}) { push @m, q[ -config :: $(INST_MAN1DIR)/.exists +config :: $(INST_MAN1DIR).exists $(NOOP) ]; push @m, $self->dir_target(qw[$(INST_MAN1DIR)]); @@ -833,9 +855,9 @@ help : push @m, q{ Version_check : - @ $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" - - -e "use ExtUtils::MakeMaker qw($Version &Version_check);" - - -e "&Version_check('$(MM_VERSION)')" + },$self->{NOECHO},q{$(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" - + -e "use ExtUtils::MakeMaker qw($Version &Version_check);" - + -e "&Version_check('$(MM_VERSION)')" }; join('',@m); @@ -852,17 +874,30 @@ sub dlsyms { return '' unless $self->needs_linking(); my($funcs) = $attribs{DL_FUNCS} || $self->{DL_FUNCS} || {}; - my($vars) = $attribs{DL_VARS} || $self->{DL_VARS} || []; + my($vars) = $attribs{DL_VARS} || $self->{DL_VARS} || []; + my($srcdir)= $attribs{PERL_SRC} || $self->{PERL_SRC} || ''; my(@m); - push(@m,' + unless ($self->{SKIPHASH}{'dynamic'}) { + push(@m,' dynamic :: rtls.opt $(INST_ARCHAUTODIR)$(BASEEXT).opt $(NOOP) - +'); + if ($srcdir) { + my($opt) = $self->catfile($srcdir,'perlshr.opt'); + push(@m,"# Depend on $(BASEEXT).opt to insure we copy here *after* autogenerating (wrong) rtls.opt in Mksymlists +rtls.opt : $opt \$(BASEEXT).opt + Copy/Log $opt Sys\$Disk:[]rtls.opt +"); + } + else { + push(@m,' # rtls.opt is built in the same step as $(BASEEXT).opt rtls.opt : $(BASEEXT).opt $(TOUCH) $(MMS$TARGET) -') unless $self->{SKIPHASH}{'dynamic'}; +'); + } + } push(@m,' static :: $(INST_ARCHAUTODIR)$(BASEEXT).opt @@ -872,12 +907,13 @@ static :: $(INST_ARCHAUTODIR)$(BASEEXT).opt push(@m,' $(INST_ARCHAUTODIR)$(BASEEXT).opt : $(BASEEXT).opt $(CP) $(MMS$SOURCE) $(MMS$TARGET) - @ $(PERL) -e "open F,\'>>$(INST_ARCHAUTODIR).packlist\';print F qq[$(MMS$TARGET)\n];close F;" + ',$self->{NOECHO},'$(PERL) -e "open F,\'>>$(INST_ARCHAUTODIR).packlist\';print F qq[$(MMS$TARGET)\n];close F;" -$(BASEEXT).opt : makefile.PL - $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -e "use ExtUtils::MakeMaker qw(&mksymlists);" - - -e "MM->new({NAME => \'',$self->{NAME},'\'})->mksymlists({DL_FUNCS => ',neatvalue($self->{DL_FUNCS}),', DL_VARS => ',neatvalue($self->{DL_VARS}),'})" - $(PERL) -e "open OPT,\'>>$(MMS$TARGET)\'; print OPT ""$(INST_STATIC)/Include=$(BASEEXT)\n$(INST_STATIC)/Library\n"";close OPT" +$(BASEEXT).opt : Makefile.PL + $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -e "use ExtUtils::Mksymlists;" - + ',qq[-e "Mksymlists('NAME' => '$self->{NAME}', 'DL_FUNCS' => ], + neatvalue($funcs),q[, 'DL_VARS' => ],neatvalue($vars),')" + $(PERL) -e "print ""$(INST_STATIC)/Include=$(BASEEXT)\n$(INST_STATIC)/Library\n"";" >>$(MMS$TARGET) '); join('',@m); @@ -896,18 +932,20 @@ sub dynamic_lib { return '' unless $self->has_link_code(); - ($otherldflags) = $attribs{OTHERLDFLAGS} || ""; + my($otherldflags) = $attribs{OTHERLDFLAGS} || ""; + my($inst_dynamic_dep) = $attribs{INST_DYNAMIC_DEP} || ""; my(@m); push @m," OTHERLDFLAGS = $otherldflags +INST_DYNAMIC_DEP = $inst_dynamic_dep "; push @m, ' -$(INST_DYNAMIC) : $(INST_STATIC) $(PERL_INC)perlshr_attr.opt rtls.opt $(BASEEXT).opt $(INST_ARCHAUTODIR).exists - @ $(MKPATH) $(INST_ARCHAUTODIR) +$(INST_DYNAMIC) : $(INST_STATIC) $(PERL_INC)perlshr_attr.opt rtls.opt $(INST_ARCHAUTODIR).exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(INST_DYNAMIC_DEP) + ',$self->{NOECHO},'$(MKPATH) $(INST_ARCHAUTODIR) Link $(LDFLAGS) /Shareable=$(MMS$TARGET)$(OTHERLDFLAGS) $(BASEEXT).opt/Option,rtls.opt/Option,$(PERL_INC)perlshr_attr.opt/Option - @ $(PERL) -e "open F,\'>>$(INST_ARCHAUTODIR).packlist\';print F qq[$(MMS$TARGET)\n];close F;" + ',$self->{NOECHO},'$(PERL) -e "open F,\'>>$(INST_ARCHAUTODIR).packlist\';print F qq[$(MMS$TARGET)\n];close F;" '; push @m, $self->dir_target('$(INST_ARCHAUTODIR)'); @@ -930,16 +968,16 @@ BOOTSTRAP = '."$self->{BASEEXT}.bs".' # we use touch to prevent make continually trying to remake it. # The DynaLoader only reads a non-empty file. $(BOOTSTRAP) : $(MAKEFILE) '."$self->{BOOTDEP}".' $(INST_ARCHAUTODIR).exists - @ Write Sys$Output "Running mkbootstrap for $(NAME) ($(BSLOADLIBS))" - @ $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" - + '.$self->{NOECHO}.'Write Sys$Output "Running mkbootstrap for $(NAME) ($(BSLOADLIBS))" + '.$self->{NOECHO}.'$(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" - -e "use ExtUtils::Mkbootstrap; Mkbootstrap(\'$(BASEEXT)\',\'$(BSLOADLIBS)\');" - @ $(TOUCH) $(MMS$TARGET) - @ $(PERL) -e "open F,\'>>$(INST_ARCHAUTODIR).packlist\';print F qq[$(MMS$TARGET)\n];close F;" + '.$self->{NOECHO}.' $(TOUCH) $(MMS$TARGET) + '.$self->{NOECHO}.'$(PERL) -e "open F,\'>>$(INST_ARCHAUTODIR).packlist\';print F qq[$(MMS$TARGET)\n];close F;" $(INST_BOOT) : $(BOOTSTRAP) $(INST_ARCHAUTODIR).exists - @ $(RM_RF) $(INST_BOOT) + '.$self->{NOECHO}.'$(RM_RF) $(INST_BOOT) - $(CP) $(BOOTSTRAP) $(INST_BOOT) - @ $(PERL) -e "open F,\'>>$(INST_ARCHAUTODIR).packlist\';print F qq[$(MMS$TARGET)\n];close F;" + '.$self->{NOECHO}.'$(PERL) -e "open F,\'>>$(INST_ARCHAUTODIR).packlist\';print F qq[$(MMS$TARGET)\n];close F;" '; } # --- Static Loading Sections --- @@ -971,8 +1009,8 @@ $(INST_STATIC) : $(OBJECT) $(MYEXTLIB) push(@m,' If F$Search("$(MMS$TARGET)").eqs."" Then Library/Object/Create $(MMS$TARGET) Library/Object/Replace $(MMS$TARGET) $(MMS$SOURCE_LIST) - @ $(PERL) -e "open F,\'>>$(INST_ARCHAUTODIR)extralibs.ld\';print F qq[$(EXTRALIBS)\n];close F;" - @ $(PERL) -e "open F,\'>>$(INST_ARCHAUTODIR).packlist\';print F qq[$(MMS$TARGET)\n];close F;" + ',$self->{NOECHO},'$(PERL) -e "open F,\'>>$(INST_ARCHAUTODIR)extralibs.ld\';print F qq[$(EXTRALIBS)\n];close F;" + ',$self->{NOECHO},'$(PERL) -e "open F,\'>>$(INST_ARCHAUTODIR).packlist\';print F qq[$(MMS$TARGET)\n];close F;" '); push @m, $self->dir_target('$(INST_ARCHAUTODIR)'); join('',@m); @@ -985,8 +1023,10 @@ sub installpm_x { # called by installpm perl file ExtUtils::MakeMaker::TieAtt::warndirectuse((caller(0))[3]); $self = $ExtUtils::MakeMaker::Parent[-1]; } - warn "Warning: Most probably 'make' will have problems processing this file: $inst\n" - if $inst =~ m!#!; + if ($inst =~ m!#!) { + warn "Warning: MM[SK] would have problems processing this file: $inst, SKIPPED\n"; + return ''; + } $inst = $self->fixpath($inst); $dist = $self->fixpath($dist); my($instdir) = $inst =~ /([^\)]+\))[^\)]*$/ ? $1 : dirname($inst); @@ -994,10 +1034,10 @@ sub installpm_x { # called by installpm perl file push(@m, " $inst : $dist \$(MAKEFILE) ${instdir}.exists \$(INST_ARCHAUTODIR).exists -",' @ $(RM_F) $(MMS$TARGET) - @ $(CP) ',"$dist $inst",' +",' ',$self->{NOECHO},'$(RM_F) $(MMS$TARGET) + ',$self->{NOECHO},'$(CP) ',"$dist $inst",' $(CHMOD) 644 $(MMS$TARGET) - @ $(PERL) -e "open F,\'>>$(INST_ARCHAUTODIR).packlist\';print F qq[$(MMS$TARGET)\n];close F;" + ',$self->{NOECHO},'$(PERL) -e "open F,\'>>$(INST_ARCHAUTODIR).packlist\';print F qq[$(MMS$TARGET)\n];close F;" '); push(@m, ' $(AUTOSPLITFILE) $(MMS$TARGET) ', $self->catdir($splitlib,'auto')."\n\n") @@ -1038,7 +1078,7 @@ END push @m, qq[POD2MAN_EXE = $pod2man_exe\n], q[POD2MAN = $(PERL) -we "%m=@ARGV;for (keys %m){" - --e "system(""$^X $(POD2MAN_EXE) $_ >$m{$_}"");}" +-e "system(""MCR $^X $(POD2MAN_EXE) $_ >$m{$_}"");}" ]; push @m, "\nmanifypods : "; push @m, join " ", keys %{$self->{MAN1PODS}}, keys %{$self->{MAN3PODS}}; @@ -1141,7 +1181,8 @@ sub pasthru { my(@pasthru); foreach $key (qw(INSTALLPRIVLIB INSTALLARCHLIB INSTALLBIN - INSTALLMAN1DIR INSTALLMAN3DIR LIBPERL_A LINKTYPE)){ + INSTALLMAN1DIR INSTALLMAN3DIR LIBPERL_A + LINKTYPE PREFIX)){ push @pasthru, "$key=\"$self->{$key}\""; } @@ -1194,7 +1235,7 @@ clean :: my(@otherfiles) = values %{$self->{XS}}; # .c files from *.xs files push(@otherfiles, $attribs{FILES}) if $attribs{FILES}; - push(@otherfiles, 'blib.dir', 'Makeaperl.MMS', 'extralibs.ld', 'perlmain.c'); + push(@otherfiles, 'blib.dir', '$(MAKE_APERL_FILE)', 'extralibs.ld', 'perlmain.c'); push(@otherfiles,$self->catfile('$(INST_ARCHAUTODIR)','extralibs.all')); my($file,$line); $line = ''; #avoid unitialized var warning @@ -1367,14 +1408,17 @@ sub install { $self = $ExtUtils::MakeMaker::Parent[-1]; } my(@m); - push @m, q{ + push @m, q[ doc_install :: - @ Write Sys$Output "Appending installation info to $(INST_ARCHLIB)perllocal.pod" - @ $(PERL) "-I$(PERL_LIB)" "-I$(PERL_ARCHLIB)" \\ - -e "use ExtUtils::MakeMaker; MY->new({})->writedoc('Module', '$(NAME)', \\ - 'LINKTYPE=$(LINKTYPE)', 'VERSION=$(VERSION)', 'XS_VERSION=$(XS_VERSION)', 'EXE_FILES=$(EXE_FILES)')" \\ - >>$(INSTALLARCHLIB)perllocal.pod -}; + ],$self->{NOECHO},q[Write Sys$Output "Appending installation info to $(INST_ARCHLIB)perllocal.pod" + ],$self->{NOECHO},q[$(PERL) -e "print q{use ExtUtils::MakeMaker; }" >.MM_tmp + ],$self->{NOECHO},q[$(PERL) -e "print q{MY->new({})->writedoc(}" >>.MM_tmp + ],$self->{NOECHO},q[$(PERL) -e "print q{'Module','$(NAME)','LINKTYPE=$(LINKTYPE)',}" >>.MM_tmp + ],$self->{NOECHO},q[$(PERL) -e "print q{'VERSION=$(VERSION)','XS_VERSION=$(XS_VERSION)',}" >>.MM_tmp + ],$self->{NOECHO},q[$(PERL) -e "print q{'EXE_FILES=$(EXE_FILES)')}" >>.MM_tmp + ],$self->{NOECHO},q[$(PERL) "-I$(PERL_LIB)" "-I$(PERL_ARCHLIB)" .MM_tmp >>$(INSTALLARCHLIB)perllocal.pod + ],$self->{NOECHO},q[If F$Search(".MM_tmp") .nes. "" then Delete/NoLog .MM_tmp; +]; push(@m, " install :: pure_install doc_install @@ -1392,12 +1436,12 @@ pure_install :: all # '; print `$(MMS) install`"'."\n"); # } # -# push(@m, ' @ $(PERL) "-I$(PERL_LIB)" -e "use File::Path; mkpath(\@ARGV)" $(INSTALLPRIVLIB) $(INSTALLARCHLIB) -# @ $(PERL) -e "die qq{You do not have permissions to install into $ARGV[0]\n} unless -w VMS::Filespec::fileify($ARGV[0])" $(INSTALLPRIVLIB) -# @ $(PERL) -e "die qq{You do not have permissions to install into $ARGV[0]\n} unless -w VMS::Filespec::fileify($ARGV[0])" $(INSTALLARCHLIB)'," +# push(@m, ' ',$self->{NOECHO},'$(PERL) "-I$(PERL_LIB)" -e "use File::Path; mkpath(\@ARGV)" $(INSTALLPRIVLIB) $(INSTALLARCHLIB) +# ',$self->{NOECHO},'$(PERL) -e "die qq{You do not have permissions to install into $ARGV[0]\n} unless -w VMS::Filespec::fileify($ARGV[0])" $(INSTALLPRIVLIB) +# ',$self->{NOECHO},'$(PERL) -e "die qq{You do not have permissions to install into $ARGV[0]\n} unless -w VMS::Filespec::fileify($ARGV[0])" $(INSTALLARCHLIB)'," # # Can't install manpages here -- INST_MAN%DIR macros make line >255 chars # \$(MMS) \$(USEMACROS)INST_LIB=$self->{INSTALLPRIVLIB},INST_ARCHLIB=$self->{INSTALLARCHLIB},INST_EXE=$self->{INSTALLBIN}\$(MACROEND)",' -# @ $(PERL) -i_bak -lne "print unless $seen{$_}++" $(INST_ARCHAUTODIR).packlist +# ',$self->{NOECHO},'$(PERL) -i_bak -lne "print unless $seen{$_}++" $(INST_ARCHAUTODIR).packlist #'); my($curtop,$insttop); @@ -1405,6 +1449,30 @@ pure_install :: all ($insttop = $self->fixpath($self->{INSTALLPRIVLIB},1)) =~ s/]$//; push(@m," Backup/Log ${curtop}...]*.*; ${insttop}...]/New_Version/By_Owner=Parent\n"); + my($oldpacklist) = $self->catfile('$(PERL_ARCHLIB)','auto','$(FULLEXT)','.packlist'); + push @m,' +# This song and dance brought to you by DCL\'s 255 char limit +reorg_packlist : +'; + my($oldpacklist) = $self->catfile('$(PERL_ARCHLIB)','auto','$(FULLEXT)','.packlist'); + if ("\L$oldpacklist" ne "\L$self->{INST_ARCHAUTODIR}.packlist") { + push(@m,' If F$Search("',$oldpacklist,'").nes."" Then Append/New ',$oldpacklist,' $(INST_ARCHAUTODIR).packlist'); + } + push @m,' + $(PERL) -ne "BEGIN{exit unless -e $ARGV[0];}print unless $s{$_}++;" $(INST_ARCHAUTODIR).packlist >.MM_tmp + If F$Search(".MM_tmp").nes."" Then Copy/NoConfirm .MM_tmp $(INST_ARCHAUTODIR).packlist + If F$Search(".MM_tmp").nes."" Then Delete/NoConfirm .MM_tmp; +'; + +# From MM 5.16: + + push @m, q[ +# Comment on .packlist rewrite above: +# Read both .packlist files: the old one in PERL_ARCHLIB/auto/FULLEXT, and the new one +# in INSTARCHAUTODIR. Don't croak if they are missing. Write to the one +# in INSTARCHAUTODIR. +]; + push @m, ' ##### UNINSTALL IS STILL EXPERIMENTAL #### uninstall :: @@ -1446,11 +1514,11 @@ $(OBJECT) : $(PERL_INC)vmsish.h, $(PERL_INC)util.h, $(PERL_INC)config.h # An out of date config.h is not fatal but complains loudly! #$(PERL_INC)config.h : $(PERL_SRC)config.sh $(PERL_INC)config.h : $(PERL_VMS)config.vms - @ Write Sys$Error "Warning: $(PERL_INC)config.h out of date with $(PERL_VMS)config.vms" + ',$self->{NOECHO},'Write Sys$Error "Warning: $(PERL_INC)config.h out of date with $(PERL_VMS)config.vms" #$(PERL_ARCHLIB)Config.pm : $(PERL_SRC)config.sh $(PERL_ARCHLIB)Config.pm : $(PERL_VMS)config.vms $(PERL_VMS)genconfig.pl - @ Write Sys$Error "$(PERL_ARCHLIB)Config.pm may be out of date with config.vms or genconfig.pl" + ',$self->{NOECHO},'Write Sys$Error "$(PERL_ARCHLIB)Config.pm may be out of date with config.vms or genconfig.pl" olddef = F$Environment("Default") Set Default $(PERL_SRC) $(MMS) $(USEMAKEFILE)[.VMS]$(MAKEFILE) [.lib.',$Config{'arch'},']config.pm @@ -1481,13 +1549,13 @@ $(OBJECT) : $(FIRST_MAKEFILE) # We take a very conservative approach here, but it\'s worth it. # We move $(MAKEFILE) to $(MAKEFILE)_old here to avoid gnu make looping. $(MAKEFILE) : Makefile.PL $(CONFIGDEP) - @ Write Sys$Output "$(MAKEFILE) out-of-date with respect to $(MMS$SOURCE_LIST)" - @ Write Sys$Output "Cleaning current config before rebuilding $(MAKEFILE) ..." + ',$self->{NOECHO},'Write Sys$Output "$(MAKEFILE) out-of-date with respect to $(MMS$SOURCE_LIST)" + ',$self->{NOECHO},'Write Sys$Output "Cleaning current config before rebuilding $(MAKEFILE) ..." - $(MV) $(MAKEFILE) $(MAKEFILE)_old - $(MMS) $(USEMAKEFILE)$(MAKEFILE)_old clean $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" Makefile.PL ',join(' ',@ARGV),' - @ Write Sys$Output "$(MAKEFILE) has been rebuilt." - @ Write Sys$Output "Please run $(MMS) to build the extension." + ',$self->{NOECHO},'Write Sys$Output "$(MAKEFILE) has been rebuilt." + ',$self->{NOECHO},'Write Sys$Output "Please run $(MMS) to build the extension." '; join('',@m); @@ -1514,13 +1582,14 @@ test : \$(TEST_TYPE) push(@m, ' If F$Search("',$vmsdir,'$(MAKEFILE)").nes."" Then $(PERL) -e "chdir ',"'$vmsdir'", '; print `$(MMS) $(PASTHRU2) test`'."\n"); } - push(@m, "\t\@ Write Sys\$Output 'No tests defined for \$(NAME) extension.'\n") + push(@m, "\t$self->{NOECHO}Write Sys\$Output \"No tests defined for \$(NAME) extension.\"\n") unless $tests or -f "test.pl" or @{$self->{DIR}}; push(@m, "\n"); push(@m, "test_dynamic :: all\n"); push(@m, $self->test_via_harness('$(FULLPERL)', $tests)) if $tests; push(@m, $self->test_via_script('$(FULLPERL)', 'test.pl')) if -f "test.pl"; + push(@m, " \$(NOOP)\n") if (!$tests && ! -f "test.pl"); push(@m, "\n"); # Occasionally we may face this degenerate target: @@ -1530,10 +1599,11 @@ test : \$(TEST_TYPE) push(@m, "test_static :: all \$(MAP_TARGET)\n"); push(@m, $self->test_via_harness('$(MAP_TARGET)', $tests)) if $tests; push(@m, $self->test_via_script('$(MAP_TARGET)', 'test.pl')) if -f "test.pl"; + push(@m, "\t$self->{NOECHO}\$(NOOP)\n") if (!$tests && ! -f "test.pl"); push(@m, "\n"); } else { - push @m, "test_static :: test_dynamic\n"; + push @m, "test_static :: test_dynamic\n\t$self->{NOECHO}\$(NOOP)\n"; } join('',@m); @@ -1582,8 +1652,8 @@ MAP_TARGET = $target unless ($self->{MAKEAPERL}) { push @m, q{ $(MAKE_APERL_FILE) : $(FIRST_MAKEFILE) - @ Write Sys$Output "Writing ""$(MMS$TARGET)"" for this $(MAP_TARGET)" - @ $(PERL) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" \ + },$self->{NOECHO},q{Write Sys$Output "Writing ""$(MMS$TARGET)"" for this $(MAP_TARGET)" + },$self->{NOECHO},q{$(PERL) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" \ Makefile.PL DIR=}, $dir, q{ \ MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \ MAKEAPERL=1 NORECURS=1 @@ -1699,19 +1769,19 @@ $(MAP_SHRTARGET) : $(MAP_LIBPERL) $(MAP_STATIC) ',"${libperldir}Perlshr_Attr.Opt $(MAP_LINKCMD)/Shareable=$(MMS$TARGET) $(MAP_OPTS), $(MAP_EXTRA), $(MAP_LIBPERL) ',"${libperldir}Perlshr_Attr.Opt",' $(MAP_TARGET) : $(MAP_SHRTARGET) ',"${tmp}perlmain\$(OBJ_EXT) ${tmp}PerlShr.Opt",' $(MAP_LINKCMD) ',"${tmp}perlmain\$(OBJ_EXT)",', PerlShr.Opt/Option - @ Write Sys$Output "To install the new ""$(MAP_TARGET)"" binary, say" - @ Write Sys$Output " $(MMS)$(USEMAKEFILE)$(MAKEFILE) inst_perl $(USEMACROS)MAP_TARGET=$(MAP_TARGET)$(ENDMACRO)" - @ Write Sys$Output "To remove the intermediate files, say - @ Write Sys$Output " $(MMS)$(USEMAKEFILE)$(MAKEFILE) map_clean" + ',$self->{NOECHO},'Write Sys$Output "To install the new ""$(MAP_TARGET)"" binary, say" + ',$self->{NOECHO},'Write Sys$Output " $(MMS)$(USEMAKEFILE)$(MAKEFILE) inst_perl $(USEMACROS)MAP_TARGET=$(MAP_TARGET)$(ENDMACRO)" + ',$self->{NOECHO},'Write Sys$Output "To remove the intermediate files, say + ',$self->{NOECHO},'Write Sys$Output " $(MMS)$(USEMAKEFILE)$(MAKEFILE) map_clean" '; push @m,' ',"${tmp}perlmain.c",' : $(MAKEFILE) - @ $(PERL) $(MAP_PERLINC) -e "use ExtUtils::Miniperl; writemain(qw|',@staticpkgs,'|)" >$(MMS$TARGET) + ',$self->{NOECHO},'$(PERL) $(MAP_PERLINC) -e "use ExtUtils::Miniperl; writemain(qw|',@staticpkgs,'|)" >$(MMS$TARGET) '; push @m, q{ doc_inst_perl : - @ $(PERL) -e "use ExtUtils::MakeMaker; MY->new()->writedoc('Perl binary','$(MAP_TARGET)','MAP_STATIC=$(MAP_STATIC)','MAP_EXTRA=$(MAP_EXTRA)','MAP_LIBPERL=$(MAP_LIBPERL)')" + },$self->{NOECHO},q{$(PERL) -e "use ExtUtils::MakeMaker; MY->new()->writedoc('Perl binary','$(MAP_TARGET)','MAP_STATIC=$(MAP_STATIC)','MAP_EXTRA=$(MAP_EXTRA)','MAP_LIBPERL=$(MAP_LIBPERL)')" }; push @m, " @@ -1743,63 +1813,6 @@ sub extliblist { } -sub mksymlists { - my($self,%attribs) = @_; - unless (ref $self){ - ExtUtils::MakeMaker::TieAtt::warndirectuse((caller(0))[3]); - $self = $ExtUtils::MakeMaker::Parent[-1]; - } - - my($vars) = $attribs{DL_VARS} || $self->{DL_VARS} || []; - my($procs) = $attribs{DL_FUNCS} || $self->{DL_FUNCS}; - my($package,$packprefix,$sym,$optname); - local(*OPT); - - if (!$procs) { - $package = $self->{NAME}; - $package =~ s/\W/_/g; - $procs = { $package => ["boot_$package"] }; - } - my($isvax) = $Config{'arch'} =~ /VAX/i; - - # Options file declaring universal symbols - # Used when linking shareable image for dynamic extension, - # or when linking PerlShr into which we've added this package - # as a static extension - # We don't do anything to preserve order, so we won't relax - # the GSMATCH criteria for a dynamic extension - - # BASEEXT is not available when mksymlists is run, so we - # create the options file name directly from NAME - # May cause trouble if Makefile.PL author specifies NAME - # and BASEEXT directly as unrelated strings. - ($optname = $self->{NAME}) =~ s/.*:://; - open OPT, ">$optname.opt"; - foreach $package (keys %$procs) { - ($packprefix = $package) =~ s/\W/_/g; - foreach $sym (@{$$procs{$package}}) { - $sym = "XS_${packprefix}_$sym" unless $sym =~ /^boot_/; - if ($isvax) { print OPT "UNIVERSAL=$sym\n" } - else { print OPT "SYMBOL_VECTOR=($sym=PROCEDURE)\n"; } - } - } - foreach $sym (@$vars) { - print OPT "PSECT_ATTR=${sym},PIC,OVR,RD,NOEXE,WRT,NOSHR\n"; - if ($isvax) { print OPT "UNIVERSAL=$sym\n" } - else { print OPT "SYMBOL_VECTOR=($sym=DATA)\n"; } - } - close OPT; - - # Options file specifying RTLs to which this extension must be linked. - # Eventually, the list of libraries will be supplied by a working - # extliblist routine. - open OPT,'>rtls.opt'; - print OPT "PerlShr/Share\n"; - foreach $rtl (split(/\s+/,$Config{'libs'})) { print OPT "$rtl\n"; } - close OPT; -} - - # --- Make-Directories section (internal method) --- # dir_target(@array) returns a Makefile entry for the file .exists in each # named directory. Returns nothing, if the entry has already been processed. @@ -1820,8 +1833,8 @@ sub dir_target { my($vmsdir) = $self->fixpath($dir,1); push @m, " ${vmsdir}.exists :: \$(PERL_INC)perl.h - \@ \$(MKPATH) $vmsdir - \@ \$(TOUCH) ${vmsdir}.exists + $self->{NOECHO}\$(MKPATH) $vmsdir + $self->{NOECHO}\$(EQUALIZE_TIMESTAMP) \$(MMS\$SOURCE) \$(MMS\$TARGET) "; } join "", @m; diff --git a/lib/ExtUtils/MakeMaker.pm b/lib/ExtUtils/MakeMaker.pm index a8b0fa173d..b66a91ba42 100644 --- a/lib/ExtUtils/MakeMaker.pm +++ b/lib/ExtUtils/MakeMaker.pm @@ -56,12 +56,12 @@ sub warndirectuse { package ExtUtils::MakeMaker; -# Last edited $Date: 1996/01/05 20:40:47 $ by Andreas Koenig -# $Id: MakeMaker.pm,v 1.135 1996/01/05 20:40:47 k Exp $ +# Last edited $Date: 1996/01/28 11:33:38 $ by Andreas Koenig +# $Id: MakeMaker.pm,v 1.141 1996/01/28 11:33:38 k Exp $ -$Version = $VERSION = "5.16"; +$Version = $VERSION = "5.18"; -$ExtUtils::MakeMaker::Version_OK = 4.13; # Makefiles older than $Version_OK will die +$ExtUtils::MakeMaker::Version_OK = "5.05"; # Makefiles older than $Version_OK will die # (Will be checked from MakeMaker version 4.13 onwards) use Config; @@ -116,7 +116,7 @@ unshift(@MY::ISA, qw(MM)); # default routine without having to know under what OS # it's running. -@MM::ISA = qw[MM_Unix ExtUtils::MakeMaker]; +@MM::ISA = qw[ExtUtils::MM_Unix ExtUtils::MakeMaker]; unshift @MM::ISA, 'ExtUtils::MM_VMS' if $Is_VMS; unshift @MM::ISA, 'ExtUtils::MM_OS2' if $Is_OS2; @@ -132,6 +132,7 @@ unshift @MM::ISA, 'ExtUtils::MM_OS2' if $Is_OS2; tools_other => {}, dist => {}, macro => {}, + depend => {}, post_constants => {}, pasthru => {}, c_o => {}, @@ -633,21 +634,12 @@ sub Version_check { Current Version is $ExtUtils::MakeMaker::VERSION. There have been considerable changes in the meantime. Please rerun 'perl Makefile.PL' to regenerate the Makefile.\n" - if $checkversion < $ExtUtils::MakeMaker::Version_OK; + if $checkversion lt $ExtUtils::MakeMaker::Version_OK; printf STDOUT "%s %s %s %s.\n", "Makefile built with ExtUtils::MakeMaker v", $checkversion, "Current Version is", $ExtUtils::MakeMaker::VERSION unless $checkversion == $ExtUtils::MakeMaker::VERSION; } -sub mksymlists { - my $class = shift; - my $self = shift; - bless $self, $class; - tie %att, ExtUtils::MakeMaker::TieAtt, $self; - $self->parse_args(@ARGV); - $self->mksymlists(@_); -} - # The following mkbootstrap() is only for installations that are calling # the pre-4.1 mkbootstrap() from their old Makefiles. This MakeMaker # writes Makefiles, that use ExtUtils::Mkbootstrap directly. @@ -659,6 +651,15 @@ sub mkbootstrap { END } +# Ditto for mksymlists() as of MakeMaker 5.17 +sub mksymlists { + die <<END; +!!! Your Makefile has been built such a long time ago, !!! +!!! that is unlikely to work with current MakeMaker. !!! +!!! Please rebuild your Makefile !!! +END +} + sub neatvalue { my($v) = @_; return "undef" unless defined $v; @@ -705,7 +706,7 @@ sub selfdocument { # # # # # # # ## # # # # # # # ####### ##### # # # # # -package MM_Unix; +package ExtUtils::MM_Unix; use Config; use Cwd; @@ -713,7 +714,7 @@ use File::Basename; require Exporter; Exporter::import('ExtUtils::MakeMaker', - qw( $Verbose)); + qw( $Verbose &neatvalue)); # These attributes cannot be overridden externally @Other_Att_Keys{qw(EXTRALIBS BSLOADLIBS LDLOADLIBS)} = (1) x 3; @@ -1026,8 +1027,6 @@ EOM close PM; } $self->{VERSION} = "0.10" unless $self->{VERSION}; - $self->{VERSION} = sprintf("%.10g",$self->{VERSION}) - if ($self->{VERSION} =~ /^[\d.]{9,}$/); ($self->{VERSION_SYM} = $self->{VERSION}) =~ s/\W/_/g; # Graham Barr and Paul Marquess had some ideas how to ensure @@ -1089,7 +1088,7 @@ sub init_dirscan { # --- File and Directory Lists (.xs .pm .pod etc) } elsif ($name =~ /\.h$/i){ $h{$name} = 1; } elsif ($name =~ /\.(p[ml]|pod)$/){ - $pm{$name} = $self->catfile('$(INST_LIBDIR)',"$name"); + $pm{$name} = $self->catfile('$(INST_LIBDIR)',$name); } elsif ($name =~ /\.PL$/ && $name ne "Makefile.PL") { ($pl_files{$name} = $name) =~ s/\.PL$// ; } elsif ($Is_VMS && $name =~ /\.pl$/ && $name ne 'makefile.pl' && @@ -1153,7 +1152,7 @@ sub init_dirscan { # --- File and Directory Lists (.xs .pm .pod etc) my($striplibpath,$striplibname); $prefix = '$(INST_LIB)' if (($striplibpath = $path) =~ s:^(\W*)lib\W:$1:); ($striplibname,$striplibpath) = fileparse($striplibpath); - my($inst) = $self->catfile($self->catdir($prefix,$striplibpath),$striplibname); + my($inst) = $self->catfile($prefix,$striplibpath,$striplibname); local($_) = $inst; # for backwards compatibility $inst = $self->libscan($inst); print "libscan($path) => '$inst'\n" if ($ExtUtils::MakeMaker::Verbose >= 2); @@ -1901,6 +1900,13 @@ MKPATH = $(PERL) -wle '$$"="/"; foreach $$p (@ARGV){' \\ -e 'next if -d $$p; my(@p); foreach(split(/\//,$$p)){' \\ -e 'push(@p,$$_); next if -d "@p/"; print "mkdir @p" if 0;' \\ -e 'mkdir("@p",0777)||die $$! } } exit 0;' + +# This helps us to minimize the effect of the .exists files A yet +# better solution would be to have a stable file in the perl +# distribution with a timestamp of zero. But this solution doesn't +# need any changes to the core distribution and works with older perls +EQUALIZE_TIMESTAMP = $(PERL) -we 'open F, ">$$ARGV[1]"; close F;' \\ +-e 'utime ((stat("$$ARGV[0]"))[8,9], $$ARGV[1])' }; } @@ -1955,6 +1961,19 @@ sub macro { join "", @m; } +sub depend { + my($self,%attribs) = @_; + unless (ref $self){ + ExtUtils::MakeMaker::TieAtt::warndirectuse((caller(0))[3]); + $self = $ExtUtils::MakeMaker::Parent[-1]; + } + my(@m,$key,$val); + while (($key,$val) = each %attribs){ + push @m, "$key: $val\n"; + } + join "", @m; +} + sub post_constants{ my($self) = shift; unless (ref $self){ @@ -1976,7 +1995,7 @@ sub pasthru { foreach $key (qw(INSTALLPRIVLIB INSTALLARCHLIB INSTALLBIN INSTALLMAN1DIR INSTALLMAN3DIR LIBPERL_A - LINKTYPE)){ + LINKTYPE PREFIX)){ push @pasthru, "$key=\"\$($key)\""; } @@ -2130,11 +2149,10 @@ static :: $self->{BASEEXT}.exp push(@m," $self->{BASEEXT}.exp: Makefile.PL -",' $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -e \'use ExtUtils::MakeMaker qw(&mksymlists); \\ - MM->new({NAME => "'.$self->{NAME}.'"})->mksymlists({DL_FUNCS => ', - %$funcs ? neatvalue($funcs) : '""',', DL_VARS => ', - @$vars ? neatvalue($vars) : '""', ", NAME => \"$self->{NAME}\"})' -"); +",' $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -e \'use ExtUtils::Mksymlists; \\ + Mksymlists("NAME" => "',$self->{NAME},'", "DL_FUNCS" => ', + neatvalue($funcs),', "DL_VARS" => ', neatvalue($vars), ');\' +'); join('',@m); } @@ -3101,39 +3119,6 @@ sub extliblist { ExtUtils::Liblist::ext($libs, $ExtUtils::MakeMaker::Verbose); } -sub mksymlists { - my($self) = shift; - unless (ref $self){ - ExtUtils::MakeMaker::TieAtt::warndirectuse((caller(0))[3]); - $self = $ExtUtils::MakeMaker::Parent[-1]; - } - my($pkg); - - # only AIX requires a symbol list at this point - # (so does VMS, but that's handled by the MM_VMS package) - return '' unless $Config::Config{osname} eq 'aix'; - - $self->init_main(@ARGV) unless defined $self->{BASEEXT}; - if (! $self->{DL_FUNCS}) { - my($bootfunc); - ($bootfunc = $self->{NAME}) =~ s/\W/_/g; - $self->{DL_FUNCS} = {$self->{BASEEXT} => ["boot_$bootfunc"]}; - } - rename "$self->{BASEEXT}.exp", "$self->{BASEEXT}.exp_old"; - - open(EXP,">$self->{BASEEXT}.exp") or die $!; - print EXP join("\n",@{$self->{DL_VARS}}, "\n") if $self->{DL_VARS}; - foreach $pkg (keys %{$self->{DL_FUNCS}}) { - (my($prefix) = $pkg) =~ s/\W/_/g; - my $func; - foreach $func (@{$self->{DL_FUNCS}->{$pkg}}) { - $func = "XS_${prefix}_$func" unless $func =~ /^boot_/; - print EXP "$func\n"; - } - } - close EXP; -} - # --- Make-Directories section (internal method) --- # dir_target(@array) returns a Makefile entry for the file .exists in each # named directory. Returns nothing, if the entry has already been processed. @@ -3154,7 +3139,7 @@ sub dir_target { push @m, " $dir/.exists :: \$(PERL) $self->{NOECHO}\$(MKPATH) $dir - $self->{NOECHO}\$(TOUCH) $dir/.exists + $self->{NOECHO}\$(EQUALIZE_TIMESTAMP) \$(PERL) $dir/.exists $self->{NOECHO}-\$(CHMOD) 755 $dir "; } @@ -3233,7 +3218,7 @@ package ExtUtils::MM_OS2; require Exporter; Exporter::import('ExtUtils::MakeMaker', - qw( $Verbose)); + qw( $Verbose &neatvalue)); sub dlsyms { my($self,%attribs) = @_; @@ -3245,20 +3230,12 @@ sub dlsyms { if (not $self->{SKIPHASH}{'dynamic'}) { push(@m," -$self->{BASEEXT}.def: Makefile.PL" - . ' - echo "LIBRARY ' . "'$self->{DLBASE}'" . ' INITINSTANCE TERMINSTANCE" > $@ ; \\ - echo "CODE LOADONCALL" >> $@ ; \\ - echo "DATA LOADONCALL NONSHARED MULTIPLE" >> $@ ; \\ - echo "EXPORTS" >> $@ ; \\ - echo " ' . "boot_$boot" . '" >> $@'); - foreach $sym (keys %$funcs, @$vars) { - push(@m, " ; \\ - echo \" $sym\" >> \$@"); - } - push(@m,"\n"); +$self->{BASEEXT}.def: Makefile.PL +",' $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -e \'use ExtUtils::Mksymlists; \\ + Mksymlists("NAME" => "',$self->{NAME},'", "DLBASE" => "',$self->{DLBASE}, + '", "DL_FUNCS" => ',neatvalue($funcs),', "DL_VARS" => ', neatvalue($vars), ');\' +'); } - join('',@m); } @@ -3979,7 +3956,7 @@ B<after> the eval() will be assigned to the VERSION attribute of the MakeMaker object. The following lines will be parsed o.k.: $VERSION = '1.00'; - ( $VERSION ) = '$Revision: 1.135 $ ' =~ /\$Revision:\s+([^\s]+)/; + ( $VERSION ) = '$Revision: 1.141 $ ' =~ /\$Revision:\s+([^\s]+)/; $FOO::VERSION = '1.10'; but these will fail: @@ -4031,6 +4008,10 @@ part of the Makefile. These are not normally required: {FILES => "*.xyz foo"} +=item depend + + {ANY_TARGET => ANY_DEPENDECY, ...} + =item dist {TARFLAGS => 'cvfF', COMPRESS => 'gzip', SUFFIX => 'gz', diff --git a/lib/ExtUtils/Mksymlists.pm b/lib/ExtUtils/Mksymlists.pm new file mode 100644 index 0000000000..cc4aca1c82 --- /dev/null +++ b/lib/ExtUtils/Mksymlists.pm @@ -0,0 +1,217 @@ +package ExtUtils::Mksymlists; +use strict qw[ subs refs ]; +# no strict 'vars'; # until filehandles are exempted + +use Carp; +use Config; +use Exporter; +# mention vars twice to prevent single-use warnings +@ExtUtils::Mksymlists::ISA = @ExtUtils::Mksymlists::ISA = 'Exporter'; +@ExtUtils::Mksymlists::EXPORT = @ExtUtils::Mksymlists::EXPORT = '&Mksymlists'; +$ExtUtils::Mksymlists::VERSION = $ExtUtils::Mksymlists::VERSION = '1.00'; + +sub Mksymlists { + my(%spec) = @_; + my($osname) = $Config{'osname'}; + + croak("Insufficient information specified to Mksymlists") + unless ( $spec{NAME} or + ($spec{FILE} and ($spec{DL_FUNCS} or $spec{FUNCLIST})) ); + + $spec{DL_VARS} = [] unless $spec{DL_VARS}; + ($spec{FILE} = $spec{NAME}) =~ s/.*::// unless $spec{FILE}; + $spec{DL_FUNCS} = { $spec{NAME} => [] } + unless ( ($spec{DL_FUNCS} and keys %{$spec{DL_FUNCS}}) or + $spec{FUNCLIST}); + $spec{FUNCLIST} = [] unless $spec{FUNCLIST}; + if (defined $spec{DL_FUNCS}) { + my($package); + foreach $package (keys %{$spec{DL_FUNCS}}) { + my($packprefix,$sym,$bootseen); + ($packprefix = $package) =~ s/\W/_/g; + foreach $sym (@{$spec{DL_FUNCS}->{$package}}) { + if ($sym =~ /^boot_/) { + push(@{$spec{FUNCLIST}},$sym); + $bootseen++; + } + else { push(@{$spec{FUNCLIST}},"XS_${packprefix}_$sym"); } + } + push(@{$spec{FUNCLIST}},"boot_$packprefix") unless $bootseen; + } + } + +# We'll need this if we ever add any OS which uses mod2fname +# require DynaLoader; +# if (defined &DynaLoader::mod2fname and not $spec{DLBASE}) { +# $spec{DLBASE} = DynaLoader::mod2fname([ split(/::/,$spec{NAME}) ]); +# } + + if ($osname eq 'aix') { _write_aix(\%spec); } + elsif ($osname eq 'VMS') { _write_vms(\%spec) } + elsif ($osname eq 'OS2') { _write_os2(\%spec) } + else { croak("Don't know how to create linker option file for $osname\n"); } +} + + +sub _write_aix { + my($data) = @_; + + rename "$data->{FILE}.exp", "$data->{FILE}.exp_old"; + + open(EXP,">$data->{FILE}.exp") + or croak("Can't create $data->{FILE}.exp: $!\n"); + print EXP join("\n",@{$data->{DL_VARS}}, "\n") if @{$data->{DL_VARS}}; + print EXP join("\n",@{$data->{FUNCLIST}}, "\n") if @{$data->{FUNCLIST}}; + close EXP; +} + + +sub _write_os2 { + my($data) = @_; + + if (not $data->{DLBASE}) { + ($data->{DLBASE} = $data->{NAME}) =~ s/.*:://; + $data->{DLBASE} = substr($data->{DLBASE},0,7) . '_'; + } + rename "$data->{FILE}.def", "$data->{FILE}_def.old"; + + open(DEF,">$data->{FILE}.def") + or croak("Can't create $data->{FILE}.def: $!\n"); + print DEF "LIBRARY '$data->{DLBASE}' INITINSTANCE TERMINSTANCE\n"; + print DEF "CODE LOADONCALL\n"; + print DEF "DATA LOADONCALL NONSHARED MULTIPLE\n"; + print DEF "EXPORTS\n"; + print DEF join("\n",@{$data->{DL_VARS}}, "\n") if @{$data->{DL_VARS}}; + print DEF join("\n",@{$data->{FUNCLIST}}, "\n") if @{$data->{FUNCLIST}}; + close DEF; +} + + +sub _write_vms { + my($data) = @_; + my($isvax) = $Config{'arch'} =~ /VAX/i; + my($sym); + + rename "$data->{FILE}.opt", "$data->{FILE}.opt_old"; + + open(OPT,">$data->{FILE}.opt") + or croak("Can't create $data->{FILE}.opt: $!\n"); + + # Options file declaring universal symbols + # Used when linking shareable image for dynamic extension, + # or when linking PerlShr into which we've added this package + # as a static extension + # We don't do anything to preserve order, so we won't relax + # the GSMATCH criteria for a dynamic extension + + foreach $sym (@{$data->{FUNCLIST}}) { + if ($isvax) { print OPT "UNIVERSAL=$sym\n" } + else { print OPT "SYMBOL_VECTOR=($sym=PROCEDURE)\n"; } + } + foreach $sym (@{$data->{DL_VARS}}) { + print OPT "PSECT_ATTR=${sym},PIC,OVR,RD,NOEXE,WRT,NOSHR\n"; + if ($isvax) { print OPT "UNIVERSAL=$sym\n" } + else { print OPT "SYMBOL_VECTOR=($sym=DATA)\n"; } + } + close OPT; + + # Options file specifying RTLs to which this extension must be linked. + # Eventually, the list of libraries will be supplied by a working + # extliblist routine. + open OPT,'>rtls.opt'; + print OPT "PerlShr/Share\n"; + foreach $rtl (split(/\s+/,$Config{'libs'})) { print OPT "$rtl\n"; } + close OPT; +} + +1; + +__END__ + +=head1 NAME + +ExtUtils::Mksymlists - write linker options files for dynamic extension + +=head1 SYNOPSIS + + use ExtUtils::Mksymlists; + Mksymlists({ NAME => $name , + DL_VARS => [ $var1, $var2, $var3 ], + DL_FUNCS => { $pkg1 => [ $func1, $func2 ], + $pkg2 => [ $func3 ] }); + +=head1 DESCRIPTION + +C<ExtUtils::Mksymlists> produces files used by the linker under some OSs +during the creation of shared libraries for synamic extensions. It is +normally called from a MakeMaker-generated Makefile when the extension +is built. The linker option file is generated by calling the function +C<Mksymlists>, which is exported by default from C<ExtUtils::Mksymlists>. +It takes one argument, a list of key-value pairs, in which the following +keys are recognized: + +=item NAME + +This gives the name of the extension (I<e.g.> Tk::Canvas) for which +the linker option file will be produced. + +=item DL_FUNCS + +This is identical to the DL_FUNCS attribute available via MakeMaker, +from which it is usually taken. Its value is a reference to an +associative array, in which each key is the name of a package, and +each value is an a reference to an array of function names which +should be exported by the extension. For instance, one might say +C<DL_FUNCS =E<gt> { Homer::Iliad =E<gt> [ qw(trojans greeks) ], +Homer::Odyssey =E<gt> [ qw(travellers family suitors) ] }>. The +function names should be identical to those in the XSUB code; +C<Mksymlists> will alter the names written to the linker option +file to match the changes made by F<xsubpp>. In addition, if +none of the functions in a list begin with the string B<boot_>, +C<Mksymlists> will add a bootstrap function for that package, +just as xsubpp does. (If a B<boot_E<lt>pkgE<gt>> function is +present in the list, it is passed through unchanged.) If +DL_FUNCS is not specified, it defaults to the bootstrap +function for the extension specified in NAME. + +=item DL_VARS + +This is identical to the DL_VARS attribute available via MakeMaker, +and, like DL_FUNCS, it is usually specified via MakeMaker. Its +value is a reference to an array of variable names which should +be exported by the extension. + +=item FILE + +This key can be used to specify the name of the linker option file +(minus the OS-specific extension), if for some reason you do not +want to use the default value, which is the last word of the NAME +attribute (I<e.g.> for Tk::Canvas, FILE defaults to 'Canvas'). + +=item FUNCLIST + +This provides an alternate means to specify function names to be +exported from the extension. Its value is a reference to an +array of function names to be exported by the extension. These +names are passed through unaltered to the linker options file. + +=item DLBASE + +This item specifies the name by which the linker knows the +extension, which may be different from the name of the +extension itself (for instance, some linkers add an '_' to the +name of the extension). If it is not specified, it is derived +from the NAME attribute. It is presently used only by OS2. + +When calling C<Mksymlists>, one should always specify the NAME +attribute. In most cases, this is all that's necessary. In +the case of unusual extensions, however, the other attributes +can be used to provide additional information to the linker. + +=head1 AUTHOR + +Charles Bailey I<E<lt>bailey@genetics.upenn.eduE<gt>> + +=head1 REVISION + +Last revised 14-Jan-1996, for Perl 5.002. diff --git a/lib/ExtUtils/typemap b/lib/ExtUtils/typemap index 98493e7c04..a9733d0f49 100644 --- a/lib/ExtUtils/typemap +++ b/lib/ExtUtils/typemap @@ -261,7 +261,7 @@ T_ARRAY T_IN { GV *gv = newGVgen("$Package"); - if ( do_open(gv, "<&", 2, $var) ) + if ( do_open(gv, "<&", 2, FALSE, 0, 0, $var) ) sv_setsv($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1))); else $arg = &sv_undef; @@ -269,7 +269,7 @@ T_IN T_INOUT { GV *gv = newGVgen("$Package"); - if ( do_open(gv, "+<&", 3, $var) ) + if ( do_open(gv, "+<&", 3, FALSE, 0, 0, $var) ) sv_setsv($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1))); else $arg = &sv_undef; @@ -277,7 +277,7 @@ T_INOUT T_OUT { GV *gv = newGVgen("$Package"); - if ( do_open(gv, "+>&", 3, $var) ) + if ( do_open(gv, "+>&", 3, FALSE, 0, 0, $var) ) sv_setsv($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1))); else $arg = &sv_undef; diff --git a/lib/ExtUtils/xsubpp b/lib/ExtUtils/xsubpp index 3113c62ed9..0d9c816abc 100755 --- a/lib/ExtUtils/xsubpp +++ b/lib/ExtUtils/xsubpp @@ -76,13 +76,12 @@ perl(1), perlxs(1), perlxstut(1), perlapi(1) =cut # Global Constants -$XSUBPP_version = "1.929"; +$XSUBPP_version = "1.932"; require 5.002; sub Q ; -$FH_string = 'File0000' ; -*FH = $FH_string ; +$FH = 'File0000' ; $usage = "Usage: xsubpp [-v] [-C++] [-except] [-prototypes] [-noversioncheck] [-s pattern] [-typemap typemap]... file.xs\n"; @@ -405,6 +404,9 @@ sub VERSIONCHECK_handler () sub PROTOTYPE_handler () { + death("Error: Only 1 PROTOTYPE definition allowed per xsub") + if $proto_in_this_xsub ++ ; + for (; !/^$BLOCK_re/o; $_ = shift(@line)) { next unless /\S/; TrimWhitespace($_) ; @@ -422,7 +424,9 @@ sub PROTOTYPE_handler () $ProtoThisXSUB = C_string($_) ; } } + $ProtoUsed = 1 ; + } sub PROTOTYPES_handler () @@ -448,9 +452,6 @@ sub INCLUDE_handler () TrimWhitespace($_) ; - # If the filename is enclosed in quotes, remove them. - s/^'([^']*)'$/$1/ or s/^"([^"]*)"$/$1/ ; - death("INCLUDE: filename missing") unless $_ ; @@ -470,13 +471,13 @@ sub INCLUDE_handler () Line => \@line, LineNo => \@line_no, Filename => $filename, - Handle => $FH_string, + Handle => $FH, }) ; - ++ $FH_string ; + ++ $FH ; # open the new file - open ($FH_string, "$_") or death("Cannot open '$_': $!") ; + open ($FH, "$_") or death("Cannot open '$_': $!") ; print Q<<"EOF" ; # @@ -484,11 +485,17 @@ sub INCLUDE_handler () # EOF - *FH = $FH_string ; $filename = $_ ; - # Prime the pump by reading the first line - $lastline = <FH> ; + # Prime the pump by reading the first + # non-blank line + + # skip leading blank lines + while (<$FH>) { + last unless /^\s*$/ ; + } + + $lastline = $_ ; $lastline_no = $. ; } @@ -504,9 +511,9 @@ sub PopFile() -- $IncludedFiles{$filename} unless $isPipe ; - close FH ; + close $FH ; - *FH = $data->{Handle} ; + $FH = $data->{Handle} ; $filename = $data->{Filename} ; $lastline = $data->{LastLine} ; $lastline_no = $data->{LastLineNo} ; @@ -581,7 +588,7 @@ sub Q { $text; } -open(FH, $filename) or die "cannot open $filename: $!\n"; +open($FH, $filename) or die "cannot open $filename: $!\n"; # Identify the version of xsubpp used print <<EOM ; @@ -596,7 +603,7 @@ print <<EOM ; EOM -while (<FH>) { +while (<$FH>) { last if ($Module, $Package, $Prefix) = /^MODULE\s*=\s*([\w:]+)(?:\s+PACKAGE\s*=\s*([\w:]+))?(?:\s+PREFIX\s*=\s*(\S+))?\s*$/; print $_; @@ -607,14 +614,14 @@ $lastline = $_; $lastline_no = $.; -# Read next xsub into @line from ($lastline, <FH>). +# Read next xsub into @line from ($lastline, <$FH>). sub fetch_para { # parse paragraph @line = (); @line_no = () ; if (! defined $lastline) { return 1 if PopFile() ; - return 0 ; + return 0 ; } if ($lastline =~ @@ -638,11 +645,11 @@ sub fetch_para { } # Read next line and continuation lines - last unless defined($lastline = <FH>); + last unless defined($lastline = <$FH>); $lastline_no = $.; my $tmp_line; $lastline .= $tmp_line - while ($lastline =~ /\\$/ && defined($tmp_line = <FH>)); + while ($lastline =~ /\\$/ && defined($tmp_line = <$FH>)); chomp $lastline; $lastline =~ s/^\s+$//; @@ -673,6 +680,7 @@ while (fetch_para()) { undef($wantRETVAL) ; undef(%arg_list) ; undef(@proto_arg) ; + undef($proto_in_this_xsub) ; $ProtoThisXSUB = $WantPrototypes ; $_ = shift(@line); @@ -986,7 +994,7 @@ for (@Func_name) { # XSANY.any_i32 = $value ; EOF print Q<<"EOF" if $proto ; -# sv_setpv(cv, $ProtoXSUB{$pname}) ; +# sv_setpv((SV*)cv, $ProtoXSUB{$pname}) ; EOF } } diff --git a/lib/FileCache.pm b/lib/FileCache.pm new file mode 100644 index 0000000000..3d01371b3b --- /dev/null +++ b/lib/FileCache.pm @@ -0,0 +1,78 @@ +package FileCache; + +=head1 NAME + +FileCache - keep more files open than the system permits + +=head1 SYNOPSIS + + cacheout $path; + print $path @data; + +=head1 DESCRIPTION + +The C<cacheout> function will make sure that there's a filehandle open +for writing available as the pathname you give it. It automatically +closes and re-opens files if you exceed your system file descriptor +maximum. + +=head1 BUGS + +F<sys/param.h> lies with its C<NOFILE> define on some systems, +so you may have to set $cacheout::maxopen yourself. + +=cut + +require 5.000; +use Carp; +use Exporter; + +@ISA = qw(Exporter); +@EXPORT = qw( + cacheout +); + +# Open in their package. + +sub cacheout_open { + my $pack = caller(1); + open(*{$pack . '::' . $_[0]}, $_[1]); +} + +sub cacheout_close { + my $pack = caller(1); + close(*{$pack . '::' . $_[0]}); +} + +# But only this sub name is visible to them. + +$cacheout_seq = 0; +$cacheout_numopen = 0; + +sub cacheout { + ($file) = @_; + unless (defined $cacheout_maxopen) { + if (open(PARAM,'/usr/include/sys/param.h')) { + local $.; + while (<PARAM>) { + $cacheout_maxopen = $1 - 4 + if /^\s*#\s*define\s+NOFILE\s+(\d+)/; + } + close PARAM; + } + $cacheout_maxopen = 16 unless $cacheout_maxopen; + } + if (!$isopen{$file}) { + if (++$cacheout_numopen > $cacheout_maxopen) { + my @lru = sort {$isopen{$a} <=> $isopen{$b};} keys(%isopen); + splice(@lru, $cacheout_maxopen / 3); + $cacheout_numopen -= @lru; + for (@lru) { &cacheout_close($_); delete $isopen{$_}; } + } + cacheout_open($file, ($saw{$file}++ ? '>>' : '>') . $file) + or croak("Can't create $file: $!"); + } + $isopen{$file} = ++$cacheout_seq; +} + +1; diff --git a/lib/FileHandle.pm b/lib/FileHandle.pm index cbc6efbc6c..93a3088886 100644 --- a/lib/FileHandle.pm +++ b/lib/FileHandle.pm @@ -1,25 +1,80 @@ package FileHandle; -# Note that some additional FileHandle methods are defined in POSIX.pm. - =head1 NAME FileHandle - supply object methods for filehandles -cacheout - keep more files open than the system permits - =head1 SYNOPSIS use FileHandle; - autoflush STDOUT 1; - cacheout($path); - print $path @data; + $fh = new FileHandle; + if ($fh->open "< file") { + print <$fh>; + $fh->close; + } + + $fh = new FileHandle "> FOO"; + if (defined $fh) { + print $fh "bar\n"; + $fh->close; + } + + $fh = new FileHandle "file", "r"; + if (defined $fh) { + print <$fh>; + undef $fh; # automatically closes the file + } + + $fh = new FileHandle "file", O_WRONLY|O_APPEND; + if (defined $fh) { + print $fh "corge\n"; + undef $fh; # automatically closes the file + } + + ($readfh, $writefh) = FileHandle::pipe; + autoflush STDOUT 1; + =head1 DESCRIPTION -See L<perlvar> for complete descriptions of each of the following supported C<FileHandle> -methods: +C<FileHandle::new> creates a C<FileHandle>, which is a reference to a +newly created symbol (see the C<Symbol> package). If it receives any +parameters, they are passed to C<FileHandle::open>; if the open fails, +the C<FileHandle> object is destroyed. Otherwise, it is returned to +the caller. + +C<FileHandle::new_from_fd> creates a C<FileHandle> like C<new> does. +It requires two parameters, which are passed to C<FileHandle::fdopen>; +if the fdopen fails, the C<FileHandle> object is destroyed. +Otherwise, it is returned to the caller. + +C<FileHandle::open> accepts one parameter or two. With one parameter, +it is just a front end for the built-in C<open> function. With two +parameters, the first parameter is a filename that may include +whitespace or other special characters, and the second parameter is +the open mode in either Perl form (">", "+<", etc.) or POSIX form +("w", "r+", etc.). + +C<FileHandle::fdopen> is like C<open> except that its first parameter +is not a filename but rather a file handle name, a FileHandle object, +or a file descriptor number. + +See L<perlfunc> for complete descriptions of each of the following +supported C<FileHandle> methods, which are just front ends for the +corresponding built-in functions: + + close + fileno + getc + gets + eof + clearerr + seek + tell + +See L<perlvar> for complete descriptions of each of the following +supported C<FileHandle> methods: autoflush output_field_separator @@ -48,9 +103,9 @@ See L<perlfunc/printf>. =item $fh->getline -This works like <$fh> described in L<perlop/"I/O Operators"> except that it's more readable -and can be safely called in an array context but still -returns just one line. +This works like <$fh> described in L<perlop/"I/O Operators"> +except that it's more readable and can be safely called in an +array context but still returns just one line. =item $fh->getlines @@ -60,12 +115,6 @@ It will also croak() if accidentally called in a scalar context. =back -=head2 The cacheout() Library - -The cacheout() function will make sure that there's a filehandle -open for writing available as the pathname you give it. It automatically -closes and re-opens files if you exceed your system file descriptor maximum. - =head1 SEE ALSO L<perlfunc>, @@ -74,15 +123,6 @@ L<POSIX/"FileHandle"> =head1 BUGS -F<sys/param.h> lies with its C<NOFILE> define on some systems, -so you may have to set $cacheout::maxopen yourself. - -Some of the methods that set variables (like format_name()) don't -seem to work. - -The POSIX functions that create FileHandle methods should be -in this module instead. - Due to backwards compatibility, all filehandles resemble objects of class C<FileHandle>, or actually classes derived from that class. They actually aren't. Which means you can't derive your own @@ -91,12 +131,20 @@ class from C<FileHandle> and inherit those methods. =cut require 5.000; -use English; use Carp; -use Exporter; +use Fcntl; +use Symbol; +use English; +use SelectSaver; + +require Exporter; +require DynaLoader; +@ISA = qw(Exporter DynaLoader); + +@EXPORT = (@Fcntl::EXPORT, + qw(_IOFBF _IOLBF _IONBF)); -@ISA = qw(Exporter); -@EXPORT = qw( +@EXPORT_OK = qw( autoflush output_field_separator output_record_separator @@ -114,173 +162,265 @@ use Exporter; printf getline getlines - - cacheout ); + +################################################ +## Interaction with the XS. +## + +bootstrap FileHandle; + +sub AUTOLOAD { + if ($AUTOLOAD =~ /::(_?[a-z])/) { + $AutoLoader::AUTOLOAD = $AUTOLOAD; + goto &AutoLoader::AUTOLOAD + } + my $constname = $AUTOLOAD; + $constname =~ s/.*:://; + my $val = constant($constname); + defined $val or croak "$constname is not a valid FileHandle macro"; + *$AUTOLOAD = sub { $val }; + goto &$AUTOLOAD; +} + + +################################################ +## Constructors, destructors. +## + +sub new { + @_ >= 1 && @_ <= 3 or croak 'usage: new FileHandle [FILENAME [,MODE]]'; + my $class = shift; + my $fh = gensym; + if (@_) { + FileHandle::open($fh, @_) + or return undef; + } + bless $fh, $class; +} + +sub new_from_fd { + @_ == 3 or croak 'usage: new_from_fd FileHandle FD, MODE'; + my $class = shift; + my $fh = gensym; + FileHandle::fdopen($fh, @_) + or return undef; + bless $fh, $class; +} + +sub DESTROY { + my ($fh) = @_; + close($fh); +} + +################################################ +## Open and close. +## + +sub pipe { + @_ and croak 'usage: FileHandle::pipe()'; + my $readfh = new FileHandle; + my $writefh = new FileHandle; + pipe($readfh, $writefh) + or return undef; + ($readfh, $writefh); +} + +sub _open_mode_string { + my ($mode) = @_; + $mode =~ /^\+?(<|>>?)$/ + or $mode =~ s/^r(\+?)$/$1</ + or $mode =~ s/^w(\+?)$/$1>/ + or $mode =~ s/^a(\+?)$/$1>>/ + or croak "FileHandle: bad open mode: $mode"; + $mode; +} + +sub open { + @_ >= 2 && @_ <= 4 or croak 'usage: $fh->open(FILENAME [,MODE [,PERMS]])'; + my ($fh, $file) = @_; + if (@_ > 2) { + my ($mode, $perms) = @_[2, 3]; + if ($mode =~ /^\d+$/) { + defined $perms or $perms = 0666; + return sysopen($fh, $file, $mode, $perms); + } + $file = "./" . $file unless $file =~ m#^/#; + $file = _open_mode_string($mode) . " $file\0"; + } + open($fh, $file); +} + +sub fdopen { + @_ == 3 or croak 'usage: $fh->fdopen(FD, MODE)'; + my ($fh, $fd, $mode) = @_; + if (ref($fd) =~ /GLOB\(/) { + # It's a glob reference; remove the star from its name. + ($fd = "".$$fd) =~ s/^\*//; + } elsif ($fd =~ m#^\d+$#) { + # It's an FD number; prefix with "=". + $fd = "=$fd"; + } + open($fh, _open_mode_string($mode) . '&' . $fd); +} + +sub close { + @_ == 1 or croak 'usage: $fh->close()'; + close($_[0]); +} + +################################################ +## Normal I/O functions. +## + +sub fileno { + @_ == 1 or croak 'usage: $fh->fileno()'; + fileno($_[0]); +} + +sub getc { + @_ == 1 or croak 'usage: $fh->getc()'; + getc($_[0]); +} + +sub gets { + @_ == 1 or croak 'usage: $fh->gets()'; + my ($handle) = @_; + scalar <$handle>; +} + +sub eof { + @_ == 1 or croak 'usage: $fh->eof()'; + eof($_[0]); +} + +sub clearerr { + @_ == 1 or croak 'usage: $fh->clearerr()'; + seek($_[0], 0, 1); +} + +sub seek { + @_ == 3 or croak 'usage: $fh->seek(POS, WHENCE)'; + seek($_[0], $_[1], $_[2]); +} + +sub tell { + @_ == 1 or croak 'usage: $fh->tell()'; + tell($_[0]); +} + sub print { - local($this) = shift; + @_ or croak 'usage: $fh->print([ARGS])'; + my $this = shift; print $this @_; } sub printf { - local($this) = shift; + @_ or croak 'usage: $fh->printf([ARGS])'; + my $this = shift; printf $this @_; } sub getline { - local($this) = shift; - croak "usage: FileHandle::getline()" if @_; + @_ == 1 or croak 'usage: $fh->getline'; + my $this = shift; return scalar <$this>; } sub getlines { - local($this) = shift; - croak "usage: FileHandle::getline()" if @_; - croak "can't call FileHandle::getlines in a scalar context" if wantarray; + @_ == 1 or croak 'usage: $fh->getline()'; + my $this = shift; + wantarray or croak "Can't call FileHandle::getlines in a scalar context"; return <$this>; -} +} + +################################################ +## State modification functions. +## sub autoflush { - local($old) = select($_[0]); - local($prev) = $OUTPUT_AUTOFLUSH; + my $old = new SelectSaver qualify($_[0], caller); + my $prev = $OUTPUT_AUTOFLUSH; $OUTPUT_AUTOFLUSH = @_ > 1 ? $_[1] : 1; - select($old); $prev; } sub output_field_separator { - local($old) = select($_[0]); - local($prev) = $OUTPUT_FIELD_SEPARATOR; + my $old = new SelectSaver qualify($_[0], caller); + my $prev = $OUTPUT_FIELD_SEPARATOR; $OUTPUT_FIELD_SEPARATOR = $_[1] if @_ > 1; - select($old); $prev; } sub output_record_separator { - local($old) = select($_[0]); - local($prev) = $OUTPUT_RECORD_SEPARATOR; + my $old = new SelectSaver qualify($_[0], caller); + my $prev = $OUTPUT_RECORD_SEPARATOR; $OUTPUT_RECORD_SEPARATOR = $_[1] if @_ > 1; - select($old); $prev; } sub input_record_separator { - local($old) = select($_[0]); - local($prev) = $INPUT_RECORD_SEPARATOR; + my $old = new SelectSaver qualify($_[0], caller); + my $prev = $INPUT_RECORD_SEPARATOR; $INPUT_RECORD_SEPARATOR = $_[1] if @_ > 1; - select($old); $prev; } sub input_line_number { - local($old) = select($_[0]); - local($prev) = $INPUT_LINE_NUMBER; + my $old = new SelectSaver qualify($_[0], caller); + my $prev = $INPUT_LINE_NUMBER; $INPUT_LINE_NUMBER = $_[1] if @_ > 1; - select($old); $prev; } sub format_page_number { - local($old) = select($_[0]); - local($prev) = $FORMAT_PAGE_NUMBER; + my $old = new SelectSaver qualify($_[0], caller); + my $prev = $FORMAT_PAGE_NUMBER; $FORMAT_PAGE_NUMBER = $_[1] if @_ > 1; - select($old); $prev; } sub format_lines_per_page { - local($old) = select($_[0]); - local($prev) = $FORMAT_LINES_PER_PAGE; + my $old = new SelectSaver qualify($_[0], caller); + my $prev = $FORMAT_LINES_PER_PAGE; $FORMAT_LINES_PER_PAGE = $_[1] if @_ > 1; - select($old); $prev; } sub format_lines_left { - local($old) = select($_[0]); - local($prev) = $FORMAT_LINES_LEFT; + my $old = new SelectSaver qualify($_[0], caller); + my $prev = $FORMAT_LINES_LEFT; $FORMAT_LINES_LEFT = $_[1] if @_ > 1; - select($old); $prev; } sub format_name { - local($old) = select($_[0]); - local($prev) = $FORMAT_NAME; - $FORMAT_NAME = $_[1] if @_ > 1; - select($old); + my $old = new SelectSaver qualify($_[0], caller); + my $prev = $FORMAT_NAME; + $FORMAT_NAME = qualify($_[1], caller) if @_ > 1; $prev; } sub format_top_name { - local($old) = select($_[0]); - local($prev) = $FORMAT_TOP_NAME; - $FORMAT_TOP_NAME = $_[1] if @_ > 1; - select($old); + my $old = new SelectSaver qualify($_[0], caller); + my $prev = $FORMAT_TOP_NAME; + $FORMAT_TOP_NAME = qualify($_[1], caller) if @_ > 1; $prev; } sub format_line_break_characters { - local($old) = select($_[0]); - local($prev) = $FORMAT_LINE_BREAK_CHARACTERS; + my $old = new SelectSaver qualify($_[0], caller); + my $prev = $FORMAT_LINE_BREAK_CHARACTERS; $FORMAT_LINE_BREAK_CHARACTERS = $_[1] if @_ > 1; - select($old); $prev; } sub format_formfeed { - local($old) = select($_[0]); - local($prev) = $FORMAT_FORMFEED; + my $old = new SelectSaver qualify($_[0], caller); + my $prev = $FORMAT_FORMFEED; $FORMAT_FORMFEED = $_[1] if @_ > 1; - select($old); $prev; } - -# --- cacheout functions --- - -# Open in their package. - -sub cacheout_open { - my $pack = caller(1); - open(*{$pack . '::' . $_[0]}, $_[1]); -} - -sub cacheout_close { - my $pack = caller(1); - close(*{$pack . '::' . $_[0]}); -} - -# But only this sub name is visible to them. - -sub cacheout { - ($file) = @_; - if (!$cacheout_maxopen){ - if (open(PARAM,'/usr/include/sys/param.h')) { - local($.); - while (<PARAM>) { - $cacheout_maxopen = $1 - 4 - if /^\s*#\s*define\s+NOFILE\s+(\d+)/; - } - close PARAM; - } - $cacheout_maxopen = 16 unless $cacheout_maxopen; - } - if (!$isopen{$file}) { - if (++$cacheout_numopen > $cacheout_maxopen) { - local(@lru) = sort {$isopen{$a} <=> $isopen{$b};} keys(%isopen); - splice(@lru, $cacheout_maxopen / 3); - $cacheout_numopen -= @lru; - for (@lru) { &cacheout_close($_); delete $isopen{$_}; } - } - &cacheout_open($file, ($saw{$file}++ ? '>>' : '>') . $file) - || croak("Can't create $file: $!"); - } - $isopen{$file} = ++$cacheout_seq; -} - -$cacheout_seq = 0; -$cacheout_numopen = 0; - 1; diff --git a/lib/Getopt/Long.pm b/lib/Getopt/Long.pm index 43e1e58e59..a3bd4fb765 100644 --- a/lib/Getopt/Long.pm +++ b/lib/Getopt/Long.pm @@ -137,11 +137,6 @@ Enable debugging output. Default is 0. =back -=head1 NOTE - -Does not yet use the Exporter--or even packages!! -Thus, it's not a real module. - =cut # newgetopt.pl -- new options parsing diff --git a/lib/IPC/Open2.pm b/lib/IPC/Open2.pm index 1ac963ab6b..243412ef09 100644 --- a/lib/IPC/Open2.pm +++ b/lib/IPC/Open2.pm @@ -96,8 +96,8 @@ sub open2 { open(STDIN, "<&$kid_rdr"); open(STDOUT, ">&$kid_wtr"); warn "execing @cmd\n" if $debug; - exec @cmd; - croak "open2: exec of @cmd failed"; + exec @cmd + or croak "open2: exec of @cmd failed"; } close $kid_rdr; close $kid_wtr; select((select($dad_wtr), $| = 1)[0]); # unbuffer pipe diff --git a/lib/IPC/Open3.pm b/lib/IPC/Open3.pm index 5bc757c344..dbf5562028 100644 --- a/lib/IPC/Open3.pm +++ b/lib/IPC/Open3.pm @@ -102,7 +102,7 @@ sub open3 { } if (($kidpid = fork) < 0) { - croak "open2: fork failed: $!"; + croak "open3: fork failed: $!"; } elsif ($kidpid == 0) { if ($dup_wtr) { open(STDIN, "<&$dad_wtr") if (fileno(STDIN) != fileno($dad_wtr)); @@ -128,8 +128,8 @@ sub open3 { open(STDERR, ">&STDOUT") if (fileno(STDERR) != fileno(STDOUT)); } local($")=(" "); - exec @cmd; - croak "open2: exec of @cmd failed"; + exec @cmd + or croak "open3: exec of @cmd failed"; } close $kid_rdr; close $kid_wtr; close $kid_err; diff --git a/lib/SelectSaver.pm b/lib/SelectSaver.pm new file mode 100644 index 0000000000..4c764bedcf --- /dev/null +++ b/lib/SelectSaver.pm @@ -0,0 +1,50 @@ +package SelectSaver; + +=head1 NAME + +SelectSaver - save and restore selected file handle + +=head1 SYNOPSIS + + use SelectSaver; + + { + my $saver = new SelectSaver(FILEHANDLE); + # FILEHANDLE is selected + } + # previous handle is selected + + { + my $saver = new SelectSaver; + # new handle may be selected, or not + } + # previous handle is selected + +=head1 DESCRIPTION + +A C<SelectSaver> object contains a reference to the file handle that +was selected when it was created. If its C<new> method gets an extra +parameter, then that parameter is selected; otherwise, the selected +file handle remains unchanged. + +When a C<SelectSaver> is destroyed, it re-selects the file handle +that was selected when it was created. + +=cut + +require 5.000; +use Carp; +use Symbol; + +sub new { + @_ >= 1 && @_ <= 2 or croak 'usage: new SelectSaver [FILEHANDLE]'; + my $fh = (@_ > 1) ? (select qualify($_[1], caller)) : select; + bless [$fh], $_[0]; +} + +sub DESTROY { + my $this = $_[0]; + select $$this[0]; +} + +1; diff --git a/lib/Symbol.pm b/lib/Symbol.pm new file mode 100644 index 0000000000..ccc12b67c7 --- /dev/null +++ b/lib/Symbol.pm @@ -0,0 +1,99 @@ +package Symbol; + +=head1 NAME + +Symbol - manipulate Perl symbols and their names + +=head1 SYNOPSIS + + use Symbol; + + $sym = gensym; + open($sym, "filename"); + $_ = <$sym>; + # etc. + + ungensym $sym; # no effect + + print qualify("x"), "\n"; # "Test::x" + print qualify("x", "FOO"), "\n" # "FOO::x" + print qualify("BAR::x"), "\n"; # "BAR::x" + print qualify("BAR::x", "FOO"), "\n"; # "BAR::x" + print qualify("STDOUT", "FOO"), "\n"; # "main::STDOUT" (global) + print qualify(\*x), "\n"; # returns \*x + print qualify(\*x, "FOO"), "\n"; # returns \*x + +=head1 DESCRIPTION + +C<Symbol::gensym> creates an anonymous glob and returns a reference +to it. Such a glob reference can be used as a file or directory +handle. + +For backward compatibility with older implementations that didn't +support anonymous globs, C<Symbol::ungensym> is also provided. +But it doesn't do anything. + +C<Symbol::qualify> turns unqualified symbol names into qualified +variable names (e.g. "myvar" -> "MyPackage::myvar"). If it is given a +second parameter, C<qualify> uses it as the default package; +otherwise, it uses the package of its caller. Regardless, global +variable names (e.g. "STDOUT", "ENV", "SIG") are always qualfied with +"main::". + +Qualification applies only to symbol names (strings). References are +left unchanged under the assumption that they are glob references, +which are qualified by their nature. + +=cut + +require 5.002; + +require Exporter; +@ISA = qw(Exporter); + +@EXPORT = qw(gensym ungensym qualify); + +my $genpkg = "Symbol::"; +my $genseq = 0; + +my %global; +while (<DATA>) { + chomp; + $global{$_} = 1; +} + +sub gensym () { + my $name = "GEN" . $genseq++; + local *{$genpkg . $name}; + \delete ${$genpkg}{$name}; +} + +sub ungensym ($) {} + +sub qualify ($;$) { + my ($name) = @_; + if (! ref($name) && $name !~ /::/) { + my $pkg; + # Global names: special character, "^x", or other. + if ($name =~ /^([^a-z])|(\^[a-z])$/i || $global{$name}) { + $pkg = "main"; + } + else { + $pkg = (@_ > 1) ? $_[1] : caller; + } + $name = $pkg . "::" . $name; + } + $name; +} + +1; + +__DATA__ +ARGV +ARGVOUT +ENV +INC +SIG +STDERR +STDIN +STDOUT diff --git a/lib/Term/Cap.pm b/lib/Term/Cap.pm index 5e900c3f23..656889591a 100644 --- a/lib/Term/Cap.pm +++ b/lib/Term/Cap.pm @@ -104,8 +104,9 @@ as C<$self-E<gt>{TERMCAP}>. sub termcap_path { ## private my @termcap_path; # $TERMCAP, if it's a filespec - push(@termcap_path, $ENV{TERMCAP}) if $ENV{TERMCAP} =~ /^\//; - if ($ENV{TERMPATH}) { + push(@termcap_path, $ENV{TERMCAP}) if ((exists $ENV{TERMCAP}) && + ($ENV{TERMCAP} =~ /^\//)); + if ((exists $ENV{TERMPATH}) && ($ENV{TERMPATH})) { # Add the users $TERMPATH push(@termcap_path, split(/(:|\s+)/, $ENV{TERMPATH})) } @@ -150,7 +151,7 @@ sub Tgetent { ## public -- static method # protect any pattern metacharacters in $tmp_term $termpat = $tmp_term; $termpat =~ s/(\W)/\\$1/g; - my $foo = $ENV{TERMCAP}; + my $foo = (exists $ENV{TERMCAP} ? $ENV{TERMCAP} : ''); # $entry is the extracted termcap entry if (($foo !~ m:^/:) && ($foo =~ m/(^|\|)${termpat}[:|]/)) { diff --git a/lib/Term/ReadLine.pm b/lib/Term/ReadLine.pm index 51044262fd..2ce7423186 100644 --- a/lib/Term/ReadLine.pm +++ b/lib/Term/ReadLine.pm @@ -1,6 +1,6 @@ =head1 NAME -C<Term::ReadLine>: Perl interface to various C<readline> packages. If +Term::ReadLine - Perl interface to various C<readline> packages. If no real package is found, substitutes stubs instead of basic functions. =head1 SYNOPSIS @@ -16,6 +16,13 @@ no real package is found, substitutes stubs instead of basic functions. $term->addhistory($_) if /\S/; } +=head1 DESCRIPTION + +This package is just a front end to some other packages. At the moment +this description is written, the only such package is Term-ReadLine, +available on CPAN near you. The real target of this stub package is to +set up a common interface to whatever Readline emerges with time. + =head1 Minimal set of supported functions All the supported functions should be called as methods, i.e., either as diff --git a/lib/Test/Harness.pm b/lib/Test/Harness.pm index 99e06f7381..7f6de4aac2 100644 --- a/lib/Test/Harness.pm +++ b/lib/Test/Harness.pm @@ -3,85 +3,127 @@ package Test::Harness; use Exporter; use Benchmark; use Config; +require 5.002; -$Is_OS2 = $Config{'osname'} =~ m|^os/?2$|i ; +$VERSION = $VERSION = "1.02"; -$ENV{EMXSHELL} = 'sh' if $Is_OS2; # to run commands -$path_s = $Is_OS2 ? ';' : ':' ; - -@ISA=(Exporter); +@ISA=('Exporter'); @EXPORT= qw(&runtests); @EXPORT_OK= qw($verbose $switches); -$verbose = 0; -$switches = "-w"; + +$Test::Harness::verbose = 0; +$Test::Harness::switches = "-w"; sub runtests { my(@tests) = @_; local($|) = 1; - my($test,$te,$ok,$next,$max,$totmax, $files,$pct); + my($test,$te,$ok,$next,$max,$totmax, $files,$pct,@failed); my $bad = 0; my $good = 0; my $total = @tests; - local($ENV{'PERL5LIB'}) = join($path_s, @INC); # pass -I flags to children + local($ENV{'PERL5LIB'}) = join($Config{path_sep}, @INC); # pass -I flags to children my $t_start = new Benchmark; while ($test = shift(@tests)) { - $te = $test; - chop($te); - print "$te" . '.' x (20 - length($te)); - my $fh = "RESULTS"; - open($fh,"$^X $switches $test|") || (print "can't run. $!\n"); - $ok = 0; - $next = 0; - while (<$fh>) { - if( $verbose ){ - print $_; - } - unless (/^#/) { - if (/^1\.\.([0-9]+)/) { - $max = $1; - $totmax += $max; - $files += 1; - $next = 1; - $ok = 1; - } else { - $next = $1, $ok = 0, last if /^not ok ([0-9]*)/; - if (/^ok (.*)/ && $1 == $next) { - $next = $next + 1; - } - } - } - } - close($fh); # must close to reap child resource values - $next -= 1; - if ($ok && $next == $max) { - print "ok\n"; - $good += 1; - } else { - $next += 1; - print "FAILED on test $next\n"; - $bad += 1; - $_ = $test; - } + $te = $test; + chop($te); + print "$te" . '.' x (20 - length($te)); + my $fh = "RESULTS"; + open($fh,"$^X $Test::Harness::switches $test|") || (print "can't run. $!\n"); + $ok = $next = $max = 0; + @failed = (); + while (<$fh>) { + if( $Test::Harness::verbose ){ + print $_; + } + unless (/^\#/) { + if (/^1\.\.([0-9]+)/) { + $max = $1; + $totmax += $max; + $files++; + $next = 1; + } elsif ($max) { + if (/^not ok ([0-9]*)/){ + push @failed, $next; + } elsif (/^ok (.*)/ && $1 == $next) { + $ok++; + } + $next = $1 + 1; + } + } + } + close($fh); # must close to reap child resource values + my $wstatus = $?; + my $estatus = $wstatus >> 8; + $next-- if $next; + if ($ok == $max && $next == $max && ! $wstatus) { + print "ok\n"; + $good++; + } else { + if (@failed) { + print canonfailed($max,@failed); + } else { + if ($next == 0) { + print "FAILED before any test output arrived\n"; + } else { + print canonfailed($max,$next+1..$max); + } + } + if ($wstatus) { + print "\tTest returned status $estatus (wstat $wstatus)\n"; + } + $bad++; + $_ = $test; + } } my $t_total = timediff(new Benchmark, $t_start); - + if ($bad == 0) { - if ($ok) { - print "All tests successful.\n"; - } else { - die "FAILED--no tests were run for some reason.\n"; - } + if ($ok) { + print "All tests successful.\n"; + } else { + die "FAILED--no tests were run for some reason.\n"; + } + } else { + $pct = sprintf("%.2f", $good / $total * 100); + if ($bad == 1) { + die "Failed 1 test script, $pct% okay.\n"; + } else { + die "Failed $bad/$total test scripts, $pct% okay.\n"; + } + } + printf("Files=%d, Tests=%d, %s\n", $files, $totmax, timestr($t_total, 'nop')); +} + +sub canonfailed ($@) { + my($max,@failed) = @_; + my $failed = @failed; + my @result = (); + my @canon = (); + my $min; + my $last = $min = shift @failed; + if (@failed) { + for (@failed, $failed[-1]) { # don't forget the last one + if ($_ > $last+1 || $_ == $last) { + if ($min == $last) { + push @canon, $last; + } else { + push @canon, "$min-$last"; + } + $min = $_; + } + $last = $_; + } + local $" = ", "; + push @result, "FAILED tests @canon\n"; } else { - $pct = sprintf("%.2f", $good / $total * 100); - if ($bad == 1) { - die "Failed 1 test, $pct% okay.\n"; - } else { - die "Failed $bad/$total tests, $pct% okay.\n"; - } + push @result, "FAILED test $last\n"; } - printf("Files=%d, Tests=%d, %s\n", $files,$totmax, timestr($t_total, 'nop')); + + push @result, "\tFailed $failed/$max tests, "; + push @result, sprintf("%.2f",100*(1-$failed/$max)), "% okay\n"; + join "", @result; } 1; @@ -134,7 +176,14 @@ above messages. =head1 SEE ALSO -See L<Benchmerk> for the underlying timing routines. +See L<Benchmark> for the underlying timing routines. + +=head1 AUTHORS + +Either Tim Bunce or Andreas Koenig, we don't know. What we know for +sure is, that it was inspired by Larry Wall's TEST script that came +with perl distributions for ages. Current maintainer is Andreas +Koenig. =head1 BUGS diff --git a/lib/complete.pl b/lib/complete.pl index dabf8f66ad..1e08f9145a 100644 --- a/lib/complete.pl +++ b/lib/complete.pl @@ -35,7 +35,7 @@ CONFIG: { sub Complete { package Complete; - local($[) = 0; + local($[,$return) = 0; if ($_[1] =~ /^StB\0/) { ($prompt, *_) = @_; } diff --git a/lib/diagnostics.pm b/lib/diagnostics.pm index f40c51e030..2c55430ff6 100755 --- a/lib/diagnostics.pm +++ b/lib/diagnostics.pm @@ -3,7 +3,11 @@ eval 'exec perl -S $0 ${1+"$@"}' if 0; use Config; -$diagnostics::PODFILE= $Config{privlib} . "/pod/perldiag.pod"; +if ($Config{'osname'} eq 'VMS') { + $diagnostics::PODFILE = VMS::Filespec::unixify($Config{'privlib'} . + '/pod/perldiag.pod'; +} +else { $diagnostics::PODFILE= $Config{privlib} . "/pod/perldiag.pod"; } package diagnostics; require 5.001; diff --git a/lib/perl5db.pl b/lib/perl5db.pl index f6e8ecae47..711003a511 100644 --- a/lib/perl5db.pl +++ b/lib/perl5db.pl @@ -1293,588 +1293,3 @@ BEGIN { # This does not compile, alas. #use Carp; # This did break, left for debuggin 1; -package DB; - -# modified Perl debugger, to be run from Emacs in perldb-mode -# Ray Lischner (uunet!mntgfx!lisch) as of 5 Nov 1990 -# Johan Vromans -- upgrade to 4.0 pl 10 - -$header = '$RCSfile: perl5db.pl,v $$Revision: 4.1 $$Date: 92/08/07 18:24:07 $'; -# -# This file is automatically included if you do perl -d. -# It's probably not useful to include this yourself. -# -# Perl supplies the values for @line and %sub. It effectively inserts -# a &DB'DB(<linenum>); in front of every place that can -# have a breakpoint. It also inserts a do 'perldb.pl' before the first line. -# -# $Log: perldb.pl,v $ - -# Is Perl being run from Emacs? -$emacs = ((defined $main::ARGV[0]) and ($main::ARGV[0] eq '-emacs')); -shift(@main::ARGV) if $emacs; - -#require Term::ReadLine; - -local($^W) = 0; - -if (-e "/dev/tty") { - $console = "/dev/tty"; - $rcfile=".perldb"; -} -elsif (-e "con") { - $console = "con"; - $rcfile="perldb.ini"; -} -else { - $console = "sys\$command"; - $rcfile="perldb.ini"; -} - -# Around a bug: -if (defined $ENV{'OS2_SHELL'}) { # In OS/2 - if ($DB::emacs) { - $console = undef; - } else { - $console = "/dev/con"; - } -} - -open(IN, "<$console") || open(IN, "<&STDIN"); # so we don't dingle stdin -open(OUT,">$console") || open(OUT, ">&STDERR") - || open(OUT, ">&STDOUT"); # so we don't dongle stdout -select(OUT); -$| = 1; # for DB::OUT -select(STDOUT); -$| = 1; # for real STDOUT -$sub = ''; - -$header =~ s/.Header: ([^,]+),v(\s+\S+\s+\S+).*$/$1$2/; -print OUT "\nLoading DB routines from $header\n"; -print OUT ("Emacs support ", - $emacs ? "enabled" : "available", - ".\n"); -print OUT "\nEnter h for help.\n\n"; - -@ARGS; - -sub DB { - &save; - ($pkg, $filename, $line) = caller; - $usercontext = '($@, $!, $,, $/, $\, $^W) = @saved;' . - "package $pkg;"; # this won't let them modify, alas - local(*dbline) = "::_<$filename"; - $max = $#dbline; - if (($stop,$action) = split(/\0/,$dbline{$line})) { - if ($stop eq '1') { - $signal |= 1; - } - else { - $evalarg = "\$DB::signal |= do {$stop;}"; &eval; - $dbline{$line} =~ s/;9($|\0)/$1/; - } - } - if ($single || $trace || $signal) { - if ($emacs) { - print OUT "\032\032$filename:$line:0\n"; - } else { - $prefix = $sub =~ /'|::/ ? "" : "${pkg}::"; - $prefix .= "$sub($filename:"; - if (length($prefix) > 30) { - print OUT "$prefix$line):\n$line:\t",$dbline[$line]; - $prefix = ""; - $infix = ":\t"; - } - else { - $infix = "):\t"; - print OUT "$prefix$line$infix",$dbline[$line]; - } - for ($i = $line + 1; $i <= $max && $dbline[$i] == 0; ++$i) { - last if $dbline[$i] =~ /^\s*(}|#|\n)/; - print OUT "$prefix$i$infix",$dbline[$i]; - } - } - } - $evalarg = $action, &eval if $action; - if ($single || $signal) { - $evalarg = $pre, &eval if $pre; - print OUT $#stack . " levels deep in subroutine calls!\n" - if $single & 4; - $start = $line; - CMD: - while ((print OUT " DB<", $#hist+1, "> "), $cmd=&gets) { - { - $single = 0; - $signal = 0; - $cmd eq '' && exit 0; - chop($cmd); - $cmd =~ s/\\$// && do { - print OUT " cont: "; - $cmd .= &gets; - redo CMD; - }; - $cmd =~ /^q$/ && exit 0; - $cmd =~ /^$/ && ($cmd = $laststep); - push(@hist,$cmd) if length($cmd) > 1; - ($i) = split(/\s+/,$cmd); - eval "\$cmd =~ $alias{$i}", print OUT $@ if $alias{$i}; - $cmd =~ /^h$/ && do { - print OUT " -T Stack trace. -s Single step. -n Next, steps over subroutine calls. -r Return from current subroutine. -c [line] Continue; optionally inserts a one-time-only breakpoint - at the specified line. -<CR> Repeat last n or s. -l min+incr List incr+1 lines starting at min. -l min-max List lines. -l line List line; -l List next window. -- List previous window. -w line List window around line. -l subname List subroutine. -f filename Switch to filename. -/pattern/ Search forwards for pattern; final / is optional. -?pattern? Search backwards for pattern. -L List breakpoints and actions. -S List subroutine names. -t Toggle trace mode. -b [line] [condition] - Set breakpoint; line defaults to the current execution line; - condition breaks if it evaluates to true, defaults to \'1\'. -b subname [condition] - Set breakpoint at first line of subroutine. -d [line] Delete breakpoint. -D Delete all breakpoints. -a [line] command - Set an action to be done before the line is executed. - Sequence is: check for breakpoint, print line if necessary, - do action, prompt user if breakpoint or step, evaluate line. -A Delete all actions. -V [pkg [vars]] List some (default all) variables in package (default current). -X [vars] Same as \"V currentpackage [vars]\". -< command Define command before prompt. -> command Define command after prompt. -! number Redo command (default previous command). -! -number Redo number\'th to last command. -H -number Display last number commands (default all). -q or ^D Quit. -p expr Same as \"print DB::OUT expr\" in current package. -= [alias value] Define a command alias, or list current aliases. -command Execute as a perl statement in current package. - -"; - next CMD; }; - $cmd =~ /^t$/ && do { - $trace = !$trace; - print OUT "Trace = ".($trace?"on":"off")."\n"; - next CMD; }; - $cmd =~ /^S$/ && do { - foreach $subname (sort(keys %sub)) { - print OUT $subname,"\n"; - } - next CMD; }; - $cmd =~ s/^X\b/V $pkg/; - $cmd =~ /^V$/ && do { - $cmd = "V $pkg"; }; - $cmd =~ /^V\b\s*(\S+)\s*(.*)/ && do { - local ($savout) = select(OUT); - $packname = $1; - @vars = split(' ',$2); - do 'dumpvar.pl' unless defined &main::dumpvar; - if (defined &main::dumpvar) { - &main::dumpvar($packname,@vars); - } - else { - print DB::OUT "dumpvar.pl not available.\n"; - } - select ($savout); - next CMD; }; - $cmd =~ /^f\b\s*(.*)/ && do { - $file = $1; - if (!$file) { - print OUT "The old f command is now the r command.\n"; - print OUT "The new f command switches filenames.\n"; - next CMD; - } - if (!defined $main::{'_<' . $file}) { - if (($try) = grep(m#^_<.*$file#, keys %main::)) { - $file = substr($try,2); - print "\n$file:\n"; - } - } - if (!defined $main::{'_<' . $file}) { - print OUT "There's no code here anything matching $file.\n"; - next CMD; - } - elsif ($file ne $filename) { - *dbline = "::_<$file"; - $max = $#dbline; - $filename = $file; - $start = 1; - $cmd = "l"; - } }; - $cmd =~ /^l\b\s*([':A-Za-z_][':\w]*)/ && do { - $subname = $1; - $subname = "main::" . $subname unless $subname =~ /'|::/; - $subname = "main" . $subname if substr($subname,0,1)eq "'"; - $subname = "main" . $subname if substr($subname,0,2)eq "::"; - # VMS filespecs may (usually do) contain ':', so don't use split - ($file,$subrange) = $sub{$subname} =~ /(.*):(.*)/; - if ($file ne $filename) { - *dbline = "::_<$file"; - $max = $#dbline; - $filename = $file; - } - if ($subrange) { - if (eval($subrange) < -$window) { - $subrange =~ s/-.*/+/; - } - $cmd = "l $subrange"; - } else { - print OUT "Subroutine $1 not found.\n"; - next CMD; - } }; - $cmd =~ /^w\b\s*(\d*)$/ && do { - $incr = $window - 1; - $start = $1 if $1; - $start -= $preview; - $cmd = 'l ' . $start . '-' . ($start + $incr); }; - $cmd =~ /^-$/ && do { - $incr = $window - 1; - $cmd = 'l ' . ($start-$window*2) . '+'; }; - $cmd =~ /^l$/ && do { - $incr = $window - 1; - $cmd = 'l ' . $start . '-' . ($start + $incr); }; - $cmd =~ /^l\b\s*(\d*)\+(\d*)$/ && do { - $start = $1 if $1; - $incr = $2; - $incr = $window - 1 unless $incr; - $cmd = 'l ' . $start . '-' . ($start + $incr); }; - $cmd =~ /^l\b\s*(([\d\$\.]+)([-,]([\d\$\.]+))?)?/ && do { - $end = (!$2) ? $max : ($4 ? $4 : $2); - $end = $max if $end > $max; - $i = $2; - $i = $line if $i eq '.'; - $i = 1 if $i < 1; - if ($emacs) { - print OUT "\032\032$filename:$i:0\n"; - $i = $end; - } else { - for (; $i <= $end; $i++) { - print OUT "$i:\t", $dbline[$i]; - last if $signal; - } - } - $start = $i; # remember in case they want more - $start = $max if $start > $max; - next CMD; }; - $cmd =~ /^D$/ && do { - print OUT "Deleting all breakpoints...\n"; - for ($i = 1; $i <= $max ; $i++) { - if (defined $dbline{$i}) { - $dbline{$i} =~ s/^[^\0]+//; - if ($dbline{$i} =~ s/^\0?$//) { - delete $dbline{$i}; - } - } - } - next CMD; }; - $cmd =~ /^L$/ && do { - for ($i = 1; $i <= $max; $i++) { - if (defined $dbline{$i}) { - print OUT "$i:\t", $dbline[$i]; - ($stop,$action) = split(/\0/, $dbline{$i}); - print OUT " break if (", $stop, ")\n" - if $stop; - print OUT " action: ", $action, "\n" - if $action; - last if $signal; - } - } - next CMD; }; - $cmd =~ /^b\b\s*([':A-Za-z_][':\w]*)\s*(.*)/ && do { - $subname = $1; - $cond = $2 || '1'; - $subname = "${pkg}::" . $subname - unless $subname =~ /'|::/; - $subname = "main" . $subname if substr($subname,0,1) eq "'"; - $subname = "main" . $subname if substr($subname,0,2) eq "::"; - # VMS filespecs may (usually do) contain ':', so don't use split - ($filename,$i) = $sub{$subname} =~ /(.*):(.*)/; - $i += 0; - if ($i) { - *dbline = "::_<$filename"; - ++$i while $dbline[$i] == 0 && $i < $#dbline; - $dbline{$i} =~ s/^[^\0]*/$cond/; - } else { - print OUT "Subroutine $subname not found.\n"; - } - next CMD; }; - $cmd =~ /^b\b\s*(\d*)\s*(.*)/ && do { - $i = ($1?$1:$line); - $cond = $2 || '1'; - if ($dbline[$i] == 0) { - print OUT "Line $i not breakable.\n"; - } else { - $dbline{$i} =~ s/^[^\0]*/$cond/; - } - next CMD; }; - $cmd =~ /^d\b\s*(\d+)?/ && do { - $i = ($1?$1:$line); - $dbline{$i} =~ s/^[^\0]*//; - delete $dbline{$i} if $dbline{$i} eq ''; - next CMD; }; - $cmd =~ /^A$/ && do { - for ($i = 1; $i <= $max ; $i++) { - if (defined $dbline{$i}) { - $dbline{$i} =~ s/\0[^\0]*//; - delete $dbline{$i} if $dbline{$i} eq ''; - } - } - next CMD; }; - $cmd =~ /^<\s*(.*)/ && do { - $pre = action($1); - next CMD; }; - $cmd =~ /^>\s*(.*)/ && do { - $post = action($1); - next CMD; }; - $cmd =~ /^a\b\s*(\d+)(\s+(.*))?/ && do { - $i = $1; - if ($dbline[$i] == 0) { - print OUT "Line $i may not have an action.\n"; - } else { - $dbline{$i} =~ s/\0[^\0]*//; - $dbline{$i} .= "\0" . action($3); - } - next CMD; }; - $cmd =~ /^n$/ && do { - $single = 2; - $laststep = $cmd; - last CMD; }; - $cmd =~ /^s$/ && do { - $single = 1; - $laststep = $cmd; - last CMD; }; - $cmd =~ /^c\b\s*(\d*)\s*$/ && do { - $i = $1; - if ($i) { - if ($dbline[$i] == 0) { - print OUT "Line $i not breakable.\n"; - next CMD; - } - $dbline{$i} =~ s/(\0|$)/;9$1/; # add one-time-only b.p. - } - for ($i=0; $i <= $#stack; ) { - $stack[$i++] &= ~1; - } - last CMD; }; - $cmd =~ /^r$/ && do { - $stack[$#stack] |= 2; - last CMD; }; - $cmd =~ /^T$/ && do { - local($p,$f,$l,$s,$h,$a,@a,@sub); - for ($i = 1; ($p,$f,$l,$s,$h,$w) = caller($i); $i++) { - @a = (); - for $arg (@args) { - $_ = "$arg"; - s/'/\\'/g; - s/([^\0]*)/'$1'/ - unless /^(?: -?[\d.]+ | \*[\w:]* )$/x; - s/([\200-\377])/sprintf("M-%c",ord($1)&0177)/eg; - s/([\0-\37\177])/sprintf("^%c",ord($1)^64)/eg; - push(@a, $_); - } - $w = $w ? '@ = ' : '$ = '; - $a = $h ? '(' . join(', ', @a) . ')' : ''; - push(@sub, "$w$s$a from file $f line $l\n"); - last if $signal; - } - for ($i=0; $i <= $#sub; $i++) { - last if $signal; - print OUT $sub[$i]; - } - next CMD; }; - $cmd =~ /^\/(.*)$/ && do { - $inpat = $1; - $inpat =~ s:([^\\])/$:$1:; - if ($inpat ne "") { - eval '$inpat =~ m'."\a$inpat\a"; - if ($@ ne "") { - print OUT "$@"; - next CMD; - } - $pat = $inpat; - } - $end = $start; - eval ' - for (;;) { - ++$start; - $start = 1 if ($start > $max); - last if ($start == $end); - if ($dbline[$start] =~ m'."\a$pat\a".'i) { - if ($emacs) { - print OUT "\032\032$filename:$start:0\n"; - } else { - print OUT "$start:\t", $dbline[$start], "\n"; - } - last; - } - } '; - print OUT "/$pat/: not found\n" if ($start == $end); - next CMD; }; - $cmd =~ /^\?(.*)$/ && do { - $inpat = $1; - $inpat =~ s:([^\\])\?$:$1:; - if ($inpat ne "") { - eval '$inpat =~ m'."\a$inpat\a"; - if ($@ ne "") { - print OUT "$@"; - next CMD; - } - $pat = $inpat; - } - $end = $start; - eval ' - for (;;) { - --$start; - $start = $max if ($start <= 0); - last if ($start == $end); - if ($dbline[$start] =~ m'."\a$pat\a".'i) { - if ($emacs) { - print OUT "\032\032$filename:$start:0\n"; - } else { - print OUT "$start:\t", $dbline[$start], "\n"; - } - last; - } - } '; - print OUT "?$pat?: not found\n" if ($start == $end); - next CMD; }; - $cmd =~ /^!+\s*(-)?(\d+)?$/ && do { - pop(@hist) if length($cmd) > 1; - $i = ($1?($#hist-($2?$2:1)):($2?$2:$#hist)); - $cmd = $hist[$i] . "\n"; - print OUT $cmd; - redo CMD; }; - $cmd =~ /^!(.+)$/ && do { - $pat = "^$1"; - pop(@hist) if length($cmd) > 1; - for ($i = $#hist; $i; --$i) { - last if $hist[$i] =~ $pat; - } - if (!$i) { - print OUT "No such command!\n\n"; - next CMD; - } - $cmd = $hist[$i] . "\n"; - print OUT $cmd; - redo CMD; }; - $cmd =~ /^H\b\s*(-(\d+))?/ && do { - $end = $2?($#hist-$2):0; - $hist = 0 if $hist < 0; - for ($i=$#hist; $i>$end; $i--) { - print OUT "$i: ",$hist[$i],"\n" - unless $hist[$i] =~ /^.?$/; - }; - next CMD; }; - $cmd =~ s/^p( .*)?$/print DB::OUT$1/; - $cmd =~ /^=/ && do { - if (local($k,$v) = ($cmd =~ /^=\s*(\S+)\s+(.*)/)) { - $alias{$k}="s~$k~$v~"; - print OUT "$k = $v\n"; - } elsif ($cmd =~ /^=\s*$/) { - foreach $k (sort keys(%alias)) { - if (($v = $alias{$k}) =~ s~^s\~$k\~(.*)\~$~$1~) { - print OUT "$k = $v\n"; - } else { - print OUT "$k\t$alias{$k}\n"; - }; - }; - }; - next CMD; }; - } - $evalarg = $cmd; &eval; - print OUT "\n"; - } - if ($post) { - $evalarg = $post; &eval; - } - } - ($@, $!, $,, $/, $\, $^W) = @saved; - (); -} - -sub save { - @saved = ($@, $!, $,, $/, $\, $^W); - $, = ""; $/ = "\n"; $\ = ""; $^W = 0; -} - -# The following takes its argument via $evalarg to preserve current @_ - -sub eval { - eval "$usercontext $evalarg; &DB::save"; - print OUT $@; -} - -sub action { - local($action) = @_; - while ($action =~ s/\\$//) { - print OUT "+ "; - $action .= &gets; - } - $action; -} - -sub gets { - local($.); - <IN>; -} - -sub catch { - $signal = 1; -} - -sub sub { - push(@stack, $single); - $single &= 1; - $single |= 4 if $#stack == $deep; - if (wantarray) { - @i = &$sub; - $single |= pop(@stack); - @i; - } - else { - $i = &$sub; - $single |= pop(@stack); - $i; - } -} - -$trace = $signal = $single = 0; # uninitialized warning suppression - -@hist = ('?'); -$SIG{'INT'} = "DB::catch"; -$deep = 100; # warning if stack gets this deep -$window = 10; -$preview = 3; - -@stack = (0); -@ARGS = @ARGV; -for (@args) { - s/'/\\'/g; - s/(.*)/'$1'/ unless /^-?[\d.]+$/; -} - -if (-f $rcfile) { - do "./$rcfile"; -} -elsif (-f "$ENV{'LOGDIR'}/$rcfile") { - do "$ENV{'LOGDIR'}/$rcfile"; -} -elsif (-f "$ENV{'HOME'}/$rcfile") { - do "$ENV{'HOME'}/$rcfile"; -} - -1; diff --git a/lib/subs.pm b/lib/subs.pm index 0dbbaddd11..84c913a346 100644 --- a/lib/subs.pm +++ b/lib/subs.pm @@ -20,8 +20,6 @@ See L<perlmod/Pragmatic Modules> and L<strict/subs>. =cut require 5.000; -$ExportLevel = 0; - sub import { my $callpack = caller; my $pack = shift; diff --git a/lib/vars.pm b/lib/vars.pm new file mode 100644 index 0000000000..b9519291c4 --- /dev/null +++ b/lib/vars.pm @@ -0,0 +1,39 @@ +package vars; + +=head1 NAME + +vars - Perl pragma to predeclare global variable names + +=head1 SYNOPSIS + + use vars qw($frob @mung %seen); + +=head1 DESCRIPTION + +This will predeclare all the variables whose names are +in the list, allowing you to use them under "use strict", and +disabling any typo warnings. + +See L<perlmod/Pragmatic Modules>. + +=cut +require 5.000; +use Carp; + +sub import { + my $callpack = caller; + my ($pack, @imports, $sym, $ch) = @_; + foreach $sym (@imports) { + croak "Can't declare another package's variables" if $sym =~ /::/; + ($ch, $sym) = unpack('a1a*', $sym); + *{"${callpack}::$sym"} = + ( $ch eq "\$" ? \$ {"${callpack}::$sym"} + : $ch eq "\@" ? \@ {"${callpack}::$sym"} + : $ch eq "\%" ? \% {"${callpack}::$sym"} + : $ch eq "\*" ? \* {"${callpack}::$sym"} + : $ch eq "\&" ? \& {"${callpack}::$sym"} + : croak "'$ch$sym' is not a valid variable name\n"); + } +}; + +1; |