diff options
author | 1999-04-29 22:36:41 +0000 | |
---|---|---|
committer | 1999-04-29 22:36:41 +0000 | |
commit | 0a5f61bb653fdff7c29c2275df78c7f019a04c0c (patch) | |
tree | 0b6e610f8913b7c1e30fd7bf5bfc62edcbbd93e5 /gnu/usr.bin/perl/lib | |
parent | Y2K fix: allow 'shutdown yymmddhhmm' to work in the next century. (diff) | |
download | wireguard-openbsd-0a5f61bb653fdff7c29c2275df78c7f019a04c0c.tar.xz wireguard-openbsd-0a5f61bb653fdff7c29c2275df78c7f019a04c0c.zip |
perl5.005_03
Diffstat (limited to 'gnu/usr.bin/perl/lib')
-rw-r--r-- | gnu/usr.bin/perl/lib/CGI/Cookie.pm | 419 | ||||
-rw-r--r-- | gnu/usr.bin/perl/lib/Dumpvalue.pm | 600 | ||||
-rw-r--r-- | gnu/usr.bin/perl/lib/ExtUtils/Installed.pm | 272 | ||||
-rw-r--r-- | gnu/usr.bin/perl/lib/ExtUtils/Packlist.pm | 288 | ||||
-rw-r--r-- | gnu/usr.bin/perl/lib/ExtUtils/inst | 139 | ||||
-rw-r--r-- | gnu/usr.bin/perl/lib/Fatal.pm | 159 | ||||
-rw-r--r-- | gnu/usr.bin/perl/lib/File/Spec.pm | 116 | ||||
-rw-r--r-- | gnu/usr.bin/perl/lib/File/Spec/Mac.pm | 230 | ||||
-rw-r--r-- | gnu/usr.bin/perl/lib/File/Spec/OS2.pm | 51 | ||||
-rw-r--r-- | gnu/usr.bin/perl/lib/File/Spec/Unix.pm | 197 | ||||
-rw-r--r-- | gnu/usr.bin/perl/lib/File/Spec/VMS.pm | 148 | ||||
-rw-r--r-- | gnu/usr.bin/perl/lib/File/Spec/Win32.pm | 104 | ||||
-rw-r--r-- | gnu/usr.bin/perl/lib/Math/BigFloat.pm | 7 | ||||
-rw-r--r-- | gnu/usr.bin/perl/lib/Test.pm | 249 | ||||
-rw-r--r-- | gnu/usr.bin/perl/lib/Tie/Array.pm | 262 | ||||
-rw-r--r-- | gnu/usr.bin/perl/lib/Tie/Handle.pm | 161 | ||||
-rw-r--r-- | gnu/usr.bin/perl/lib/chat2.pl | 4 | ||||
-rw-r--r-- | gnu/usr.bin/perl/lib/fields.pm | 156 | ||||
-rw-r--r-- | gnu/usr.bin/perl/lib/integer.pm | 13 |
19 files changed, 3570 insertions, 5 deletions
diff --git a/gnu/usr.bin/perl/lib/CGI/Cookie.pm b/gnu/usr.bin/perl/lib/CGI/Cookie.pm new file mode 100644 index 00000000000..204d67b08ae --- /dev/null +++ b/gnu/usr.bin/perl/lib/CGI/Cookie.pm @@ -0,0 +1,419 @@ +package CGI::Cookie; + +# See the bottom of this file for the POD documentation. Search for the +# string '=head'. + +# You can run this file through either pod2man or pod2html to produce pretty +# documentation in manual or html file format (these utilities are part of the +# Perl 5 distribution). + +# Copyright 1995,1996, Lincoln D. Stein. All rights reserved. +# It may be used and modified freely, but I do request that this copyright +# notice remain attached to the file. You may modify this module as you +# wish, but if you redistribute a modified version, please attach a note +# listing the modifications you have made. + +# The most recent version and complete docs are available at: +# http://www.genome.wi.mit.edu/ftp/pub/software/WWW/cgi_docs.html +# ftp://ftp-genome.wi.mit.edu/pub/software/WWW/ + +$CGI::Cookie::VERSION='1.06'; + +use CGI; +use overload '""' => \&as_string, + 'cmp' => \&compare, + 'fallback'=>1; + +# fetch a list of cookies from the environment and +# return as a hash. the cookies are parsed as normal +# escaped URL data. +sub fetch { + my $class = shift; + my $raw_cookie = $ENV{HTTP_COOKIE} || $ENV{COOKIE}; + return () unless $raw_cookie; + return $class->parse($raw_cookie); +} + +# fetch a list of cookies from the environment and +# return as a hash. the cookie values are not unescaped +# or altered in any way. +sub raw_fetch { + my $class = shift; + my $raw_cookie = $ENV{HTTP_COOKIE} || $ENV{COOKIE}; + return () unless $raw_cookie; + my %results; + my($key,$value); + + my(@pairs) = split("; ",$raw_cookie); + foreach (@pairs) { + if (/^([^=]+)=(.*)/) { + $key = $1; + $value = $2; + } + else { + $key = $_; + $value = ''; + } + $results{$key} = $value; + } + return \%results unless wantarray; + return %results; +} + +sub parse { + my ($self,$raw_cookie) = @_; + my %results; + + my(@pairs) = split("; ",$raw_cookie); + foreach (@pairs) { + my($key,$value) = split("="); + my(@values) = map CGI::unescape($_),split('&',$value); + $key = CGI::unescape($key); + # A bug in Netscape can cause several cookies with same name to + # appear. The FIRST one in HTTP_COOKIE is the most recent version. + $results{$key} ||= $self->new(-name=>$key,-value=>\@values); + } + return \%results unless wantarray; + return %results; +} + +sub new { + my $class = shift; + $class = ref($class) if ref($class); + my($name,$value,$path,$domain,$secure,$expires) = + CGI->rearrange([NAME,[VALUE,VALUES],PATH,DOMAIN,SECURE,EXPIRES],@_); + + # Pull out our parameters. + my @values; + if (ref($value)) { + if (ref($value) eq 'ARRAY') { + @values = @$value; + } elsif (ref($value) eq 'HASH') { + @values = %$value; + } + } else { + @values = ($value); + } + + bless my $self = { + 'name'=>$name, + 'value'=>[@values], + },$class; + + # IE requires the path to be present for some reason. + ($path = $ENV{'SCRIPT_NAME'})=~s![^/]+$!! unless $path; + + $self->path($path) if defined $path; + $self->domain($domain) if defined $domain; + $self->secure($secure) if defined $secure; + $self->expires($expires) if defined $expires; + return $self; +} + +sub as_string { + my $self = shift; + return "" unless $self->name; + + my(@constant_values,$domain,$path,$expires,$secure); + + push(@constant_values,"domain=$domain") if $domain = $self->domain; + push(@constant_values,"path=$path") if $path = $self->path; + push(@constant_values,"expires=$expires") if $expires = $self->expires; + push(@constant_values,'secure') if $secure = $self->secure; + + my($key) = CGI::escape($self->name); + my($cookie) = join("=",$key,join("&",map CGI::escape($_),$self->value)); + return join("; ",$cookie,@constant_values); +} + +sub compare { + my $self = shift; + my $value = shift; + return "$self" cmp $value; +} + +# accessors +sub name { + my $self = shift; + my $name = shift; + $self->{'name'} = $name if defined $name; + return $self->{'name'}; +} + +sub value { + my $self = shift; + my $value = shift; + $self->{'value'} = $value if defined $value; + return wantarray ? @{$self->{'value'}} : $self->{'value'}->[0] +} + +sub domain { + my $self = shift; + my $domain = shift; + $self->{'domain'} = $domain if defined $domain; + return $self->{'domain'}; +} + +sub secure { + my $self = shift; + my $secure = shift; + $self->{'secure'} = $secure if defined $secure; + return $self->{'secure'}; +} + +sub expires { + my $self = shift; + my $expires = shift; + $self->{'expires'} = CGI::expires($expires,'cookie') if defined $expires; + return $self->{'expires'}; +} + +sub path { + my $self = shift; + my $path = shift; + $self->{'path'} = $path if defined $path; + return $self->{'path'}; +} + +1; + +=head1 NAME + +CGI::Cookie - Interface to Netscape Cookies + +=head1 SYNOPSIS + + use CGI qw/:standard/; + use CGI::Cookie; + + # Create new cookies and send them + $cookie1 = new CGI::Cookie(-name=>'ID',-value=>123456); + $cookie2 = new CGI::Cookie(-name=>'preferences', + -value=>{ font => Helvetica, + size => 12 } + ); + print header(-cookie=>[$cookie1,$cookie2]); + + # fetch existing cookies + %cookies = fetch CGI::Cookie; + $id = $cookies{'ID'}->value; + + # create cookies returned from an external source + %cookies = parse CGI::Cookie($ENV{COOKIE}); + +=head1 DESCRIPTION + +CGI::Cookie is an interface to Netscape (HTTP/1.1) cookies, an +innovation that allows Web servers to store persistent information on +the browser's side of the connection. Although CGI::Cookie is +intended to be used in conjunction with CGI.pm (and is in fact used by +it internally), you can use this module independently. + +For full information on cookies see + + http://www.ics.uci.edu/pub/ietf/http/rfc2109.txt + +=head1 USING CGI::Cookie + +CGI::Cookie is object oriented. Each cookie object has a name and a +value. The name is any scalar value. The value is any scalar or +array value (associative arrays are also allowed). Cookies also have +several optional attributes, including: + +=over 4 + +=item B<1. expiration date> + +The expiration date tells the browser how long to hang on to the +cookie. If the cookie specifies an expiration date in the future, the +browser will store the cookie information in a disk file and return it +to the server every time the user reconnects (until the expiration +date is reached). If the cookie species an expiration date in the +past, the browser will remove the cookie from the disk file. If the +expiration date is not specified, the cookie will persist only until +the user quits the browser. + +=item B<2. domain> + +This is a partial or complete domain name for which the cookie is +valid. The browser will return the cookie to any host that matches +the partial domain name. For example, if you specify a domain name +of ".capricorn.com", then Netscape will return the cookie to +Web servers running on any of the machines "www.capricorn.com", +"ftp.capricorn.com", "feckless.capricorn.com", etc. Domain names +must contain at least two periods to prevent attempts to match +on top level domains like ".edu". If no domain is specified, then +the browser will only return the cookie to servers on the host the +cookie originated from. + +=item B<3. path> + +If you provide a cookie path attribute, the browser will check it +against your script's URL before returning the cookie. For example, +if you specify the path "/cgi-bin", then the cookie will be returned +to each of the scripts "/cgi-bin/tally.pl", "/cgi-bin/order.pl", +and "/cgi-bin/customer_service/complain.pl", but not to the script +"/cgi-private/site_admin.pl". By default, path is set to "/", which +causes the cookie to be sent to any CGI script on your site. + +=item B<4. secure flag> + +If the "secure" attribute is set, the cookie will only be sent to your +script if the CGI request is occurring on a secure channel, such as SSL. + +=back + +=head2 Creating New Cookies + + $c = new CGI::Cookie(-name => 'foo', + -value => 'bar', + -expires => '+3M', + -domain => '.capricorn.com', + -path => '/cgi-bin/database' + -secure => 1 + ); + +Create cookies from scratch with the B<new> method. The B<-name> and +B<-value> parameters are required. The name must be a scalar value. +The value can be a scalar, an array reference, or a hash reference. +(At some point in the future cookies will support one of the Perl +object serialization protocols for full generality). + +B<-expires> accepts any of the relative or absolute date formats +recognized by CGI.pm, for example "+3M" for three months in the +future. See CGI.pm's documentation for details. + +B<-domain> points to a domain name or to a fully qualified host name. +If not specified, the cookie will be returned only to the Web server +that created it. + +B<-path> points to a partial URL on the current server. The cookie +will be returned to all URLs beginning with the specified path. If +not specified, it defaults to '/', which returns the cookie to all +pages at your site. + +B<-secure> if set to a true value instructs the browser to return the +cookie only when a cryptographic protocol is in use. + +=head2 Sending the Cookie to the Browser + +Within a CGI script you can send a cookie to the browser by creating +one or more Set-Cookie: fields in the HTTP header. Here is a typical +sequence: + + my $c = new CGI::Cookie(-name => 'foo', + -value => ['bar','baz'], + -expires => '+3M'); + + print "Set-Cookie: $c\n"; + print "Content-Type: text/html\n\n"; + +To send more than one cookie, create several Set-Cookie: fields. +Alternatively, you may concatenate the cookies together with "; " and +send them in one field. + +If you are using CGI.pm, you send cookies by providing a -cookie +argument to the header() method: + + print header(-cookie=>$c); + +Mod_perl users can set cookies using the request object's header_out() +method: + + $r->header_out('Set-Cookie',$c); + +Internally, Cookie overloads the "" operator to call its as_string() +method when incorporated into the HTTP header. as_string() turns the +Cookie's internal representation into an RFC-compliant text +representation. You may call as_string() yourself if you prefer: + + print "Set-Cookie: ",$c->as_string,"\n"; + +=head2 Recovering Previous Cookies + + %cookies = fetch CGI::Cookie; + +B<fetch> returns an associative array consisting of all cookies +returned by the browser. The keys of the array are the cookie names. You +can iterate through the cookies this way: + + %cookies = fetch CGI::Cookie; + foreach (keys %cookies) { + do_something($cookies{$_}); + } + +In a scalar context, fetch() returns a hash reference, which may be more +efficient if you are manipulating multiple cookies. + +CGI.pm uses the URL escaping methods to save and restore reserved characters +in its cookies. If you are trying to retrieve a cookie set by a foreign server, +this escaping method may trip you up. Use raw_fetch() instead, which has the +same semantics as fetch(), but performs no unescaping. + +You may also retrieve cookies that were stored in some external +form using the parse() class method: + + $COOKIES = `cat /usr/tmp/Cookie_stash`; + %cookies = parse CGI::Cookie($COOKIES); + +=head2 Manipulating Cookies + +Cookie objects have a series of accessor methods to get and set cookie +attributes. Each accessor has a similar syntax. Called without +arguments, the accessor returns the current value of the attribute. +Called with an argument, the accessor changes the attribute and +returns its new value. + +=over 4 + +=item B<name()> + +Get or set the cookie's name. Example: + + $name = $c->name; + $new_name = $c->name('fred'); + +=item B<value()> + +Get or set the cookie's value. Example: + + $value = $c->value; + @new_value = $c->value(['a','b','c','d']); + +B<value()> is context sensitive. In an array context it will return +the current value of the cookie as an array. In a scalar context it +will return the B<first> value of a multivalued cookie. + +=item B<domain()> + +Get or set the cookie's domain. + +=item B<path()> + +Get or set the cookie's path. + +=item B<expires()> + +Get or set the cookie's expiration time. + +=back + + +=head1 AUTHOR INFORMATION + +Copyright 1997-1998, Lincoln D. Stein. All rights reserved. + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +Address bug reports and comments to: lstein@cshl.org + +=head1 BUGS + +This section intentionally left blank. + +=head1 SEE ALSO + +L<CGI::Carp>, L<CGI> + +=cut diff --git a/gnu/usr.bin/perl/lib/Dumpvalue.pm b/gnu/usr.bin/perl/lib/Dumpvalue.pm new file mode 100644 index 00000000000..5bcd58f4fba --- /dev/null +++ b/gnu/usr.bin/perl/lib/Dumpvalue.pm @@ -0,0 +1,600 @@ +require 5.005; # For (defined ref) and $#$v +package Dumpvalue; +use strict; +use vars qw(%address *stab %subs); + +# translate control chars to ^X - Randal Schwartz +# Modifications to print types by Peter Gordon v1.0 + +# Ilya Zakharevich -- patches after 5.001 (and some before ;-) + +# Won't dump symbol tables and contents of debugged files by default + +# (IZ) changes for objectification: +# c) quote() renamed to method set_quote(); +# d) unctrlSet() renamed to method set_unctrl(); +# f) Compiles with `use strict', but in two places no strict refs is needed: +# maybe more problems are waiting... + +my %defaults = ( + globPrint => 0, + printUndef => 1, + tick => "auto", + unctrl => 'quote', + subdump => 1, + dumpReused => 0, + bareStringify => 1, + hashDepth => '', + arrayDepth => '', + dumpDBFiles => '', + dumpPackages => '', + quoteHighBit => '', + usageOnly => '', + compactDump => '', + veryCompact => '', + stopDbSignal => '', + ); + +sub new { + my $class = shift; + my %opt = (%defaults, @_); + bless \%opt, $class; +} + +sub set { + my $self = shift; + my %opt = @_; + @$self{keys %opt} = values %opt; +} + +sub get { + my $self = shift; + wantarray ? @$self{@_} : $$self{pop @_}; +} + +sub dumpValue { + my $self = shift; + die "usage: \$dumper->dumpValue(value)" unless @_ == 1; + local %address; + local $^W=0; + (print "undef\n"), return unless defined $_[0]; + (print $self->stringify($_[0]), "\n"), return unless ref $_[0]; + $self->unwrap($_[0],0); +} + +sub dumpValues { + my $self = shift; + local %address; + local $^W=0; + (print "undef\n"), return unless defined $_[0]; + $self->unwrap(\@_,0); +} + +# This one is good for variable names: + +sub unctrl { + local($_) = @_; + + return \$_ if ref \$_ eq "GLOB"; + s/([\001-\037\177])/'^'.pack('c',ord($1)^64)/eg; + $_; +} + +sub stringify { + my $self = shift; + local $_ = shift; + my $noticks = shift; + my $tick = $self->{tick}; + + return 'undef' unless defined $_ or not $self->{printUndef}; + return $_ . "" if ref \$_ eq 'GLOB'; + { no strict 'refs'; + $_ = &{'overload::StrVal'}($_) + if $self->{bareStringify} and ref $_ + and defined %overload:: and defined &{'overload::StrVal'}; + } + + if ($tick eq 'auto') { + if (/[\000-\011\013-\037\177]/) { + $tick = '"'; + } else { + $tick = "'"; + } + } + if ($tick eq "'") { + s/([\'\\])/\\$1/g; + } elsif ($self->{unctrl} eq 'unctrl') { + s/([\"\\])/\\$1/g ; + s/([\000-\037\177])/'^'.pack('c',ord($1)^64)/eg; + s/([\200-\377])/'\\0x'.sprintf('%2X',ord($1))/eg + if $self->{quoteHighBit}; + } elsif ($self->{unctrl} eq 'quote') { + s/([\"\\\$\@])/\\$1/g if $tick eq '"'; + s/\033/\\e/g; + s/([\000-\037\177])/'\\c'.chr(ord($1)^64)/eg; + } + s/([\200-\377])/'\\'.sprintf('%3o',ord($1))/eg if $self->{quoteHighBit}; + ($noticks || /^\d+(\.\d*)?\Z/) + ? $_ + : $tick . $_ . $tick; +} + +sub DumpElem { + my ($self, $v) = (shift, shift); + my $short = $self->stringify($v, ref $v); + my $shortmore = ''; + if ($self->{veryCompact} && ref $v + && (ref $v eq 'ARRAY' and !grep(ref $_, @$v) )) { + my $depth = $#$v; + ($shortmore, $depth) = (' ...', $self->{arrayDepth} - 1) + if $self->{arrayDepth} and $depth >= $self->{arrayDepth}; + my @a = map $self->stringify($_), @$v[0..$depth]; + print "0..$#{$v} @a$shortmore\n"; + } elsif ($self->{veryCompact} && ref $v + && (ref $v eq 'HASH') and !grep(ref $_, values %$v)) { + my @a = sort keys %$v; + my $depth = $#a; + ($shortmore, $depth) = (' ...', $self->{hashDepth} - 1) + if $self->{hashDepth} and $depth >= $self->{hashDepth}; + my @b = map {$self->stringify($_) . " => " . $self->stringify($$v{$_})} + @a[0..$depth]; + local $" = ', '; + print "@b$shortmore\n"; + } else { + print "$short\n"; + $self->unwrap($v,shift); + } +} + +sub unwrap { + my $self = shift; + return if $DB::signal and $self->{stopDbSignal}; + my ($v) = shift ; + my ($s) = shift ; # extra no of spaces + my $sp; + my (%v,@v,$address,$short,$fileno); + + $sp = " " x $s ; + $s += 3 ; + + # Check for reused addresses + if (ref $v) { + my $val = $v; + { no strict 'refs'; + $val = &{'overload::StrVal'}($v) + if defined %overload:: and defined &{'overload::StrVal'}; + } + ($address) = $val =~ /(0x[0-9a-f]+)\)$/ ; + if (!$self->{dumpReused} && defined $address) { + $address{$address}++ ; + if ( $address{$address} > 1 ) { + print "${sp}-> REUSED_ADDRESS\n" ; + return ; + } + } + } elsif (ref \$v eq 'GLOB') { + $address = "$v" . ""; # To avoid a bug with globs + $address{$address}++ ; + if ( $address{$address} > 1 ) { + print "${sp}*DUMPED_GLOB*\n" ; + return ; + } + } + + if ( UNIVERSAL::isa($v, 'HASH') ) { + my @sortKeys = sort keys(%$v) ; + my $more; + my $tHashDepth = $#sortKeys ; + $tHashDepth = $#sortKeys < $self->{hashDepth}-1 ? $#sortKeys : $self->{hashDepth}-1 + unless $self->{hashDepth} eq '' ; + $more = "....\n" if $tHashDepth < $#sortKeys ; + my $shortmore = ""; + $shortmore = ", ..." if $tHashDepth < $#sortKeys ; + $#sortKeys = $tHashDepth ; + if ($self->{compactDump} && !grep(ref $_, values %{$v})) { + $short = $sp; + my @keys; + for (@sortKeys) { + push @keys, $self->stringify($_) . " => " . $self->stringify($v->{$_}); + } + $short .= join ', ', @keys; + $short .= $shortmore; + (print "$short\n"), return if length $short <= $self->{compactDump}; + } + for my $key (@sortKeys) { + return if $DB::signal and $self->{stopDbSignal}; + my $value = $ {$v}{$key} ; + print $sp, $self->stringify($key), " => "; + $self->DumpElem($value, $s); + } + print "$sp empty hash\n" unless @sortKeys; + print "$sp$more" if defined $more ; + } elsif ( UNIVERSAL::isa($v, 'ARRAY') ) { + my $tArrayDepth = $#{$v} ; + my $more ; + $tArrayDepth = $#$v < $self->{arrayDepth}-1 ? $#$v : $self->{arrayDepth}-1 + unless $self->{arrayDepth} eq '' ; + $more = "....\n" if $tArrayDepth < $#{$v} ; + my $shortmore = ""; + $shortmore = " ..." if $tArrayDepth < $#{$v} ; + if ($self->{compactDump} && !grep(ref $_, @{$v})) { + if ($#$v >= 0) { + $short = $sp . "0..$#{$v} " . + join(" ", + map {$self->stringify($_)} @{$v}[0..$tArrayDepth]) + . "$shortmore"; + } else { + $short = $sp . "empty array"; + } + (print "$short\n"), return if length $short <= $self->{compactDump}; + } + for my $num ($[ .. $tArrayDepth) { + return if $DB::signal and $self->{stopDbSignal}; + print "$sp$num "; + $self->DumpElem($v->[$num], $s); + } + print "$sp empty array\n" unless @$v; + print "$sp$more" if defined $more ; + } elsif ( UNIVERSAL::isa($v, 'SCALAR') or ref $v eq 'REF' ) { + print "$sp-> "; + $self->DumpElem($$v, $s); + } elsif ( UNIVERSAL::isa($v, 'CODE') ) { + print "$sp-> "; + $self->dumpsub(0, $v); + } elsif ( UNIVERSAL::isa($v, 'GLOB') ) { + print "$sp-> ",$self->stringify($$v,1),"\n"; + if ($self->{globPrint}) { + $s += 3; + $self->dumpglob('', $s, "{$$v}", $$v, 1); + } elsif (defined ($fileno = fileno($v))) { + print( (' ' x ($s+3)) . "FileHandle({$$v}) => fileno($fileno)\n" ); + } + } elsif (ref \$v eq 'GLOB') { + if ($self->{globPrint}) { + $self->dumpglob('', $s, "{$v}", $v, 1); + } elsif (defined ($fileno = fileno(\$v))) { + print( (' ' x $s) . "FileHandle({$v}) => fileno($fileno)\n" ); + } + } +} + +sub matchvar { + $_[0] eq $_[1] or + ($_[1] =~ /^([!~])(.)([\x00-\xff]*)/) and + ($1 eq '!') ^ (eval {($_[2] . "::" . $_[0]) =~ /$2$3/}); +} + +sub compactDump { + my $self = shift; + $self->{compactDump} = shift if @_; + $self->{compactDump} = 6*80-1 + if $self->{compactDump} and $self->{compactDump} < 2; + $self->{compactDump}; +} + +sub veryCompact { + my $self = shift; + $self->{veryCompact} = shift if @_; + $self->compactDump(1) if !$self->{compactDump} and $self->{veryCompact}; + $self->{veryCompact}; +} + +sub set_unctrl { + my $self = shift; + if (@_) { + my $in = shift; + if ($in eq 'unctrl' or $in eq 'quote') { + $self->{unctrl} = $in; + } else { + print "Unknown value for `unctrl'.\n"; + } + } + $self->{unctrl}; +} + +sub set_quote { + my $self = shift; + if (@_ and $_[0] eq '"') { + $self->{tick} = '"'; + $self->{unctrl} = 'quote'; + } elsif (@_ and $_[0] eq 'auto') { + $self->{tick} = 'auto'; + $self->{unctrl} = 'quote'; + } elsif (@_) { # Need to set + $self->{tick} = "'"; + $self->{unctrl} = 'unctrl'; + } + $self->{tick}; +} + +sub dumpglob { + my $self = shift; + return if $DB::signal and $self->{stopDbSignal}; + my ($package, $off, $key, $val, $all) = @_; + local(*stab) = $val; + my $fileno; + if (($key !~ /^_</ or $self->{dumpDBFiles}) and defined $stab) { + print( (' ' x $off) . "\$", &unctrl($key), " = " ); + $self->DumpElem($stab, 3+$off); + } + if (($key !~ /^_</ or $self->{dumpDBFiles}) and defined @stab) { + print( (' ' x $off) . "\@$key = (\n" ); + $self->unwrap(\@stab,3+$off) ; + print( (' ' x $off) . ")\n" ); + } + if ($key ne "main::" && $key ne "DB::" && defined %stab + && ($self->{dumpPackages} or $key !~ /::$/) + && ($key !~ /^_</ or $self->{dumpDBFiles}) + && !($package eq "Dumpvalue" and $key eq "stab")) { + print( (' ' x $off) . "\%$key = (\n" ); + $self->unwrap(\%stab,3+$off) ; + print( (' ' x $off) . ")\n" ); + } + if (defined ($fileno = fileno(*stab))) { + print( (' ' x $off) . "FileHandle($key) => fileno($fileno)\n" ); + } + if ($all) { + if (defined &stab) { + $self->dumpsub($off, $key); + } + } +} + +sub dumpsub { + my $self = shift; + my ($off,$sub) = @_; + $sub = $1 if $sub =~ /^\{\*(.*)\}$/; + my $subref = \&$sub; + my $place = $DB::sub{$sub} || (($sub = $subs{"$subref"}) && $DB::sub{$sub}) + || ($self->{subdump} && ($sub = $self->findsubs("$subref")) + && $DB::sub{$sub}); + $place = '???' unless defined $place; + print( (' ' x $off) . "&$sub in $place\n" ); +} + +sub findsubs { + my $self = shift; + return undef unless defined %DB::sub; + my ($addr, $name, $loc); + while (($name, $loc) = each %DB::sub) { + $addr = \&$name; + $subs{"$addr"} = $name; + } + $self->{subdump} = 0; + $subs{ shift() }; +} + +sub dumpvars { + my $self = shift; + my ($package,@vars) = @_; + local(%address,$^W); + my ($key,$val); + $package .= "::" unless $package =~ /::$/; + *stab = *main::; + + while ($package =~ /(\w+?::)/g) { + *stab = $ {stab}{$1}; + } + $self->{TotalStrings} = 0; + $self->{Strings} = 0; + $self->{CompleteTotal} = 0; + while (($key,$val) = each(%stab)) { + return if $DB::signal and $self->{stopDbSignal}; + next if @vars && !grep( matchvar($key, $_), @vars ); + if ($self->{usageOnly}) { + $self->globUsage(\$val, $key) + unless $package eq 'Dumpvalue' and $key eq 'stab'; + } else { + $self->dumpglob($package, 0,$key, $val); + } + } + if ($self->{usageOnly}) { + print <<EOP; +String space: $self->{TotalStrings} bytes in $self->{Strings} strings. +EOP + $self->{CompleteTotal} += $self->{TotalStrings}; + print <<EOP; +Grand total = $self->{CompleteTotal} bytes (1 level deep) + overhead. +EOP + } +} + +sub scalarUsage { + my $self = shift; + my $size = length($_[0]); + $self->{TotalStrings} += $size; + $self->{Strings}++; + $size; +} + +sub arrayUsage { # array ref, name + my $self = shift; + my $size = 0; + map {$size += $self->scalarUsage($_)} @{$_[0]}; + my $len = @{$_[0]}; + print "\@$_[1] = $len item", ($len > 1 ? "s" : ""), " (data: $size bytes)\n" + if defined $_[1]; + $self->{CompleteTotal} += $size; + $size; +} + +sub hashUsage { # hash ref, name + my $self = shift; + my @keys = keys %{$_[0]}; + my @values = values %{$_[0]}; + my $keys = $self->arrayUsage(\@keys); + my $values = $self->arrayUsage(\@values); + my $len = @keys; + my $total = $keys + $values; + print "\%$_[1] = $len item", ($len > 1 ? "s" : ""), + " (keys: $keys; values: $values; total: $total bytes)\n" + if defined $_[1]; + $total; +} + +sub globUsage { # glob ref, name + my $self = shift; + local *stab = *{$_[0]}; + my $total = 0; + $total += $self->scalarUsage($stab) if defined $stab; + $total += $self->arrayUsage(\@stab, $_[1]) if defined @stab; + $total += $self->hashUsage(\%stab, $_[1]) + if defined %stab and $_[1] ne "main::" and $_[1] ne "DB::"; + #and !($package eq "Dumpvalue" and $key eq "stab")); + $total; +} + +1; + +=head1 NAME + +Dumpvalue - provides screen dump of Perl data. + +=head1 SYNOPSYS + + use Dumpvalue; + my $dumper = new Dumpvalue; + $dumper->set(globPrint => 1); + $dumper->dumpValue(\*::); + $dumper->dumpvars('main'); + +=head1 DESCRIPTION + +=head2 Creation + +A new dumper is created by a call + + $d = new Dumpvalue(option1 => value1, option2 => value2) + +Recognized options: + +=over + +=item C<arrayDepth>, C<hashDepth> + +Print only first N elements of arrays and hashes. If false, prints all the +elements. + +=item C<compactDump>, C<veryCompact> + +Change style of array and hash dump. If true, short array +may be printed on one line. + +=item C<globPrint> + +Whether to print contents of globs. + +=item C<DumpDBFiles> + +Dump arrays holding contents of debugged files. + +=item C<DumpPackages> + +Dump symbol tables of packages. + +=item C<DumpReused> + +Dump contents of "reused" addresses. + +=item C<tick>, C<HighBit>, C<printUndef> + +Change style of string dump. Default value of C<tick> is C<auto>, one +can enable either double-quotish dump, or single-quotish by setting it +to C<"> or C<'>. By default, characters with high bit set are printed +I<as is>. + +=item C<UsageOnly> + +I<very> rudimentally per-package memory usage dump. If set, +C<dumpvars> calculates total size of strings in variables in the package. + +=item unctrl + +Changes the style of printout of strings. Possible values are +C<unctrl> and C<quote>. + +=item subdump + +Whether to try to find the subroutine name given the reference. + +=item bareStringify + +Whether to write the non-overloaded form of the stringify-overloaded objects. + +=item quoteHighBit + +Whether to print chars with high bit set in binary or "as is". + +=item stopDbSignal + +Whether to abort printing if debugger signal flag is raised. + +=back + +Later in the life of the object the methods may be queries with get() +method and set() method (which accept multiple arguments). + +=head2 Methods + +=over + +=item dumpValue + + $dumper->dumpValue($value); + $dumper->dumpValue([$value1, $value2]); + +=item dumpValues + + $dumper->dumpValues($value1, $value2); + +=item dumpvars + + $dumper->dumpvars('my_package'); + $dumper->dumpvars('my_package', 'foo', '~bar$', '!......'); + +The optional arguments are considered as literal strings unless they +start with C<~> or C<!>, in which case they are interpreted as regular +expressions (possibly negated). + +The second example prints entries with names C<foo>, and also entries +with names which ends on C<bar>, or are shorter than 5 chars. + +=item set_quote + + $d->set_quote('"'); + +Sets C<tick> and C<unctrl> options to suitable values for printout with the +given quote char. Possible values are C<auto>, C<'> and C<">. + +=item set_unctrl + + $d->set_unctrl('"'); + +Sets C<unctrl> option with checking for an invalid argument. +Possible values are C<unctrl> and C<quote>. + +=item compactDump + + $d->compactDump(1); + +Sets C<compactDump> option. If the value is 1, sets to a reasonable +big number. + +=item veryCompact + + $d->veryCompact(1); + +Sets C<compactDump> and C<veryCompact> options simultaneously. + +=item set + + $d->set(option1 => value1, option2 => value2); + +=item get + + @values = $d->get('option1', 'option2'); + +=back + +=cut + diff --git a/gnu/usr.bin/perl/lib/ExtUtils/Installed.pm b/gnu/usr.bin/perl/lib/ExtUtils/Installed.pm new file mode 100644 index 00000000000..dda594e7843 --- /dev/null +++ b/gnu/usr.bin/perl/lib/ExtUtils/Installed.pm @@ -0,0 +1,272 @@ +package ExtUtils::Installed; +use strict; +use Carp qw(); +use ExtUtils::Packlist; +use ExtUtils::MakeMaker; +use Config; +use File::Find; +use File::Basename; +use vars qw($VERSION); +$VERSION = '0.02'; + +sub _is_type($$$) +{ +my ($self, $path, $type) = @_; +return(1) if ($type eq "all"); +if ($type eq "doc") + { + return(substr($path, 0, length($Config{installman1dir})) + eq $Config{installman1dir} + || + substr($path, 0, length($Config{installman3dir})) + eq $Config{installman3dir} + ? 1 : 0) + } +if ($type eq "prog") + { + return(substr($path, 0, length($Config{prefix})) eq $Config{prefix} + && + substr($path, 0, length($Config{installman1dir})) + ne $Config{installman1dir} + && + substr($path, 0, length($Config{installman3dir})) + ne $Config{installman3dir} + ? 1 : 0); + } +return(0); +} + +sub _is_under($$;) +{ +my ($self, $path, @under) = @_; +$under[0] = "" if (! @under); +foreach my $dir (@under) + { + return(1) if (substr($path, 0, length($dir)) eq $dir); + } +return(0); +} + +sub new($) +{ +my ($class) = @_; +$class = ref($class) || $class; +my $self = {}; + +# Read the core packlist +$self->{Perl}{packlist} = + ExtUtils::Packlist->new("$Config{installarchlib}/.packlist"); +$self->{Perl}{version} = $]; + +# Read the module packlists +my $sub = sub + { + # Only process module .packlists + return if ($_) ne ".packlist" || $File::Find::dir eq $Config{installarchlib}; + + # Hack of the leading bits of the paths & convert to a module name + my $module = $File::Find::name; + $module =~ s!$Config{archlib}/auto/(.*)/.packlist!$1!; + $module =~ s!$Config{sitearch}/auto/(.*)/.packlist!$1!; + my $modfile = "$module.pm"; + $module =~ s!/!::!g; + + # Find the top-level module file in @INC + $self->{$module}{version} = ''; + foreach my $dir (@INC) + { + my $p = MM->catfile($dir, $modfile); + if (-f $p) + { + $self->{$module}{version} = MM->parse_version($p); + last; + } + } + + # Read the .packlist + $self->{$module}{packlist} = ExtUtils::Packlist->new($File::Find::name); + }; +find($sub, $Config{archlib}, $Config{sitearch}); + +return(bless($self, $class)); +} + +sub modules($) +{ +my ($self) = @_; +return(sort(keys(%$self))); +} + +sub files($$;$) +{ +my ($self, $module, $type, @under) = @_; + +# Validate arguments +Carp::croak("$module is not installed") if (! exists($self->{$module})); +$type = "all" if (! defined($type)); +Carp::croak('type must be "all", "prog" or "doc"') + if ($type ne "all" && $type ne "prog" && $type ne "doc"); + +my (@files); +foreach my $file (keys(%{$self->{$module}{packlist}})) + { + push(@files, $file) + if ($self->_is_type($file, $type) && $self->_is_under($file, @under)); + } +return(@files); +} + +sub directories($$;$) +{ +my ($self, $module, $type, @under) = @_; +my (%dirs); +foreach my $file ($self->files($module, $type, @under)) + { + $dirs{dirname($file)}++; + } +return(sort(keys(%dirs))); +} + +sub directory_tree($$;$) +{ +my ($self, $module, $type, @under) = @_; +my (%dirs); +foreach my $dir ($self->directories($module, $type, @under)) + { + $dirs{$dir}++; + my ($last) = (""); + while ($last ne $dir) + { + $last = $dir; + $dir = dirname($dir); + last if (! $self->_is_under($dir, @under)); + $dirs{$dir}++; + } + } +return(sort(keys(%dirs))); +} + +sub validate($;$) +{ +my ($self, $module, $remove) = @_; +Carp::croak("$module is not installed") if (! exists($self->{$module})); +return($self->{$module}{packlist}->validate($remove)); +} + +sub packlist($$) +{ +my ($self, $module) = @_; +Carp::croak("$module is not installed") if (! exists($self->{$module})); +return($self->{$module}{packlist}); +} + +sub version($$) +{ +my ($self, $module) = @_; +Carp::croak("$module is not installed") if (! exists($self->{$module})); +return($self->{$module}{version}); +} + +sub DESTROY +{ +} + +1; + +__END__ + +=head1 NAME + +ExtUtils::Installed - Inventory management of installed modules + +=head1 SYNOPSIS + + use ExtUtils::Installed; + my ($inst) = ExtUtils::Installed->new(); + my (@modules) = $inst->modules(); + my (@missing) = $inst->validate("DBI"); + my $all_files = $inst->files("DBI"); + my $files_below_usr_local = $inst->files("DBI", "all", "/usr/local"); + my $all_dirs = $inst->directories("DBI"); + my $dirs_below_usr_local = $inst->directory_tree("DBI", "prog"); + my $packlist = $inst->packlist("DBI"); + +=head1 DESCRIPTION + +ExtUtils::Installed provides a standard way to find out what core and module +files have been installed. It uses the information stored in .packlist files +created during installation to provide this information. In addition it +provides facilities to classify the installed files and to extract directory +information from the .packlist files. + +=head1 USAGE + +The new() function searches for all the installed .packlists on the system, and +stores their contents. The .packlists can be queried with the functions +described below. + +=head1 FUNCTIONS + +=over + +=item new() + +This takes no parameters, and searches for all the installed .packlists on the +system. The packlists are read using the ExtUtils::packlist module. + +=item modules() + +This returns a list of the names of all the installed modules. The perl 'core' +is given the special name 'Perl'. + +=item files() + +This takes one mandatory parameter, the name of a module. It returns a list of +all the filenames from the package. To obtain a list of core perl files, use +the module name 'Perl'. Additional parameters are allowed. The first is one +of the strings "prog", "man" or "all", to select either just program files, +just manual files or all files. The remaining parameters are a list of +directories. The filenames returned will be restricted to those under the +specified directories. + +=item directories() + +This takes one mandatory parameter, the name of a module. It returns a list of +all the directories from the package. Additional parameters are allowed. The +first is one of the strings "prog", "man" or "all", to select either just +program directories, just manual directories or all directories. The remaining +parameters are a list of directories. The directories returned will be +restricted to those under the specified directories. This method returns only +the leaf directories that contain files from the specified module. + +=item directory_tree() + +This is identical in operation to directory(), except that it includes all the +intermediate directories back up to the specified directories. + +=item validate() + +This takes one mandatory parameter, the name of a module. It checks that all +the files listed in the modules .packlist actually exist, and returns a list of +any missing files. If an optional second argument which evaluates to true is +given any missing files will be removed from the .packlist + +=item packlist() + +This returns the ExtUtils::Packlist object for the specified module. + +=item version() + +This returns the version number for the specified module. + +=back + +=head1 EXAMPLE + +See the example in L<ExtUtils::Packlist>. + +=head1 AUTHOR + +Alan Burlison <Alan.Burlison@uk.sun.com> + +=cut diff --git a/gnu/usr.bin/perl/lib/ExtUtils/Packlist.pm b/gnu/usr.bin/perl/lib/ExtUtils/Packlist.pm new file mode 100644 index 00000000000..eeb0a5b0c1c --- /dev/null +++ b/gnu/usr.bin/perl/lib/ExtUtils/Packlist.pm @@ -0,0 +1,288 @@ +package ExtUtils::Packlist; +use strict; +use Carp qw(); +use vars qw($VERSION); +$VERSION = '0.03'; + +# Used for generating filehandle globs. IO::File might not be available! +my $fhname = "FH1"; + +sub mkfh() +{ +no strict; +my $fh = \*{$fhname++}; +use strict; +return($fh); +} + +sub new($$) +{ +my ($class, $packfile) = @_; +$class = ref($class) || $class; +my %self; +tie(%self, $class, $packfile); +return(bless(\%self, $class)); +} + +sub TIEHASH +{ +my ($class, $packfile) = @_; +my $self = { packfile => $packfile }; +bless($self, $class); +$self->read($packfile) if (defined($packfile) && -f $packfile); +return($self); +} + +sub STORE +{ +$_[0]->{data}->{$_[1]} = $_[2]; +} + +sub FETCH +{ +return($_[0]->{data}->{$_[1]}); +} + +sub FIRSTKEY +{ +my $reset = scalar(keys(%{$_[0]->{data}})); +return(each(%{$_[0]->{data}})); +} + +sub NEXTKEY +{ +return(each(%{$_[0]->{data}})); +} + +sub EXISTS +{ +return(exists($_[0]->{data}->{$_[1]})); +} + +sub DELETE +{ +return(delete($_[0]->{data}->{$_[1]})); +} + +sub CLEAR +{ +%{$_[0]->{data}} = (); +} + +sub DESTROY +{ +} + +sub read($;$) +{ +my ($self, $packfile) = @_; +$self = tied(%$self) || $self; + +if (defined($packfile)) { $self->{packfile} = $packfile; } +else { $packfile = $self->{packfile}; } +Carp::croak("No packlist filename specified") if (! defined($packfile)); +my $fh = mkfh(); +open($fh, "<$packfile") || Carp::croak("Can't open file $packfile: $!"); +$self->{data} = {}; +my ($line); +while (defined($line = <$fh>)) + { + chomp $line; + my ($key, @kvs) = split(' ', $line); + $key =~ s!/\./!/!g; # Some .packlists have spurious '/./' bits in the paths + if (! @kvs) + { + $self->{data}->{$key} = undef; + } + else + { + my ($data) = {}; + foreach my $kv (@kvs) + { + my ($k, $v) = split('=', $kv); + $data->{$k} = $v; + } + $self->{data}->{$key} = $data; + } + } +close($fh); +} + +sub write($;$) +{ +my ($self, $packfile) = @_; +$self = tied(%$self) || $self; +if (defined($packfile)) { $self->{packfile} = $packfile; } +else { $packfile = $self->{packfile}; } +Carp::croak("No packlist filename specified") if (! defined($packfile)); +my $fh = mkfh(); +open($fh, ">$packfile") || Carp::croak("Can't open file $packfile: $!"); +foreach my $key (sort(keys(%{$self->{data}}))) + { + print $fh ("$key"); + if (ref($self->{data}->{$key})) + { + my $data = $self->{data}->{$key}; + foreach my $k (sort(keys(%$data))) + { + print $fh (" $k=$data->{$k}"); + } + } + print $fh ("\n"); + } +close($fh); +} + +sub validate($;$) +{ +my ($self, $remove) = @_; +$self = tied(%$self) || $self; +my @missing; +foreach my $key (sort(keys(%{$self->{data}}))) + { + if (! -e $key) + { + push(@missing, $key); + delete($self->{data}{$key}) if ($remove); + } + } +return(@missing); +} + +sub packlist_file($) +{ +my ($self) = @_; +$self = tied(%$self) || $self; +return($self->{packfile}); +} + +1; + +__END__ + +=head1 NAME + +ExtUtils::Packlist - manage .packlist files + +=head1 SYNOPSIS + + use ExtUtils::Packlist; + my ($pl) = ExtUtils::Packlist->new('.packlist'); + $pl->read('/an/old/.packlist'); + my @missing_files = $pl->validate(); + $pl->write('/a/new/.packlist'); + + $pl->{'/some/file/name'}++; + or + $pl->{'/some/other/file/name'} = { type => 'file', + from => '/some/file' }; + +=head1 DESCRIPTION + +ExtUtils::Packlist provides a standard way to manage .packlist files. +Functions are provided to read and write .packlist files. The original +.packlist format is a simple list of absolute pathnames, one per line. In +addition, this package supports an extended format, where as well as a filename +each line may contain a list of attributes in the form of a space separated +list of key=value pairs. This is used by the installperl script to +differentiate between files and links, for example. + +=head1 USAGE + +The hash reference returned by the new() function can be used to examine and +modify the contents of the .packlist. Items may be added/deleted from the +.packlist by modifying the hash. If the value associated with a hash key is a +scalar, the entry written to the .packlist by any subsequent write() will be a +simple filename. If the value is a hash, the entry written will be the +filename followed by the key=value pairs from the hash. Reading back the +.packlist will recreate the original entries. + +=head1 FUNCTIONS + +=over + +=item new() + +This takes an optional parameter, the name of a .packlist. If the file exists, +it will be opened and the contents of the file will be read. The new() method +returns a reference to a hash. This hash holds an entry for each line in the +.packlist. In the case of old-style .packlists, the value associated with each +key is undef. In the case of new-style .packlists, the value associated with +each key is a hash containing the key=value pairs following the filename in the +.packlist. + +=item read() + +This takes an optional parameter, the name of the .packlist to be read. If +no file is specified, the .packlist specified to new() will be read. If the +.packlist does not exist, Carp::croak will be called. + +=item write() + +This takes an optional parameter, the name of the .packlist to be written. If +no file is specified, the .packlist specified to new() will be overwritten. + +=item validate() + +This checks that every file listed in the .packlist actually exists. If an +argument which evaluates to true is given, any missing files will be removed +from the internal hash. The return value is a list of the missing files, which +will be empty if they all exist. + +=item packlist_file() + +This returns the name of the associated .packlist file + +=back + +=head1 EXAMPLE + +Here's C<modrm>, a little utility to cleanly remove an installed module. + + #!/usr/local/bin/perl -w + + use strict; + use IO::Dir; + use ExtUtils::Packlist; + use ExtUtils::Installed; + + sub emptydir($) { + my ($dir) = @_; + my $dh = IO::Dir->new($dir) || return(0); + my @count = $dh->read(); + $dh->close(); + return(@count == 2 ? 1 : 0); + } + + # Find all the installed packages + print("Finding all installed modules...\n"); + my $installed = ExtUtils::Installed->new(); + + foreach my $module (grep(!/^Perl$/, $installed->modules())) { + my $version = $installed->version($module) || "???"; + print("Found module $module Version $version\n"); + print("Do you want to delete $module? [n] "); + my $r = <STDIN>; chomp($r); + if ($r && $r =~ /^y/i) { + # Remove all the files + foreach my $file (sort($installed->files($module))) { + print("rm $file\n"); + unlink($file); + } + my $pf = $installed->packlist($module)->packlist_file(); + print("rm $pf\n"); + unlink($pf); + foreach my $dir (sort($installed->directory_tree($module))) { + if (emptydir($dir)) { + print("rmdir $dir\n"); + rmdir($dir); + } + } + } + } + +=head1 AUTHOR + +Alan Burlison <Alan.Burlison@uk.sun.com> + +=cut diff --git a/gnu/usr.bin/perl/lib/ExtUtils/inst b/gnu/usr.bin/perl/lib/ExtUtils/inst new file mode 100644 index 00000000000..cbf2d01194a --- /dev/null +++ b/gnu/usr.bin/perl/lib/ExtUtils/inst @@ -0,0 +1,139 @@ +#!/usr/local/bin/perl -w + +use strict; +use IO::File; +use ExtUtils::Packlist; +use ExtUtils::Installed; + +use vars qw($Inst @Modules); + +################################################################################ + +sub do_module($) +{ +my ($module) = @_; +my $help = <<EOF; +Available commands are: + f [all|prog|doc] - List installed files of a given type + d [all|prog|doc] - List the directories used by a module + v - Validate the .packlist - check for missing files + t <tarfile> - Create a tar archive of the module + q - Quit the module +EOF +print($help); +while (1) + { + print("$module cmd? "); + my $reply = <STDIN>; chomp($reply); + CASE: + { + $reply =~ /^f\s*/ and do + { + my $class = (split(' ', $reply))[1]; + $class = 'all' if (! $class); + my @files; + if (eval { @files = $Inst->files($module, $class); }) + { + print("$class files in $module are:\n ", + join("\n ", @files), "\n"); + last CASE; + } + else + { print($@); } + }; + $reply =~ /^d\s*/ and do + { + my $class = (split(' ', $reply))[1]; + $class = 'all' if (! $class); + my @dirs; + if (eval { @dirs = $Inst->directories($module, $class); }) + { + print("$class directories in $module are:\n ", + join("\n ", @dirs), "\n"); + last CASE; + } + else + { print($@); } + }; + $reply =~ /^t\s*/ and do + { + my $file = (split(' ', $reply))[1]; + my $tmp = "/tmp/inst.$$"; + if (my $fh = IO::File->new($tmp, "w")) + { + $fh->print(join("\n", $Inst->files($module))); + $fh->close(); + system("tar cvf $file -I $tmp"); + unlink($tmp); + last CASE; + } + else { print("Can't open $file: $!\n"); } + last CASE; + }; + $reply eq 'v' and do + { + if (my @missing = $Inst->validate($module)) + { + print("Files missing from $module are:\n ", + join("\n ", @missing), "\n"); + } + else + { + print("$module has no missing files\n"); + } + last CASE; + }; + $reply eq 'q' and do + { + return; + }; + # Default + print($help); + } + } +} + +################################################################################ + +sub toplevel() +{ +my $help = <<EOF; +Available commands are: + l - List all installed modules + m <module> - Select a module + q - Quit the program +EOF +print($help); +while (1) + { + print("cmd? "); + my $reply = <STDIN>; chomp($reply); + CASE: + { + $reply eq 'l' and do + { + print("Installed modules are:\n ", join("\n ", @Modules), "\n"); + last CASE; + }; + $reply =~ /^m\s+/ and do + { + do_module((split(' ', $reply))[1]); + last CASE; + }; + $reply eq 'q' and do + { + exit(0); + }; + # Default + print($help); + } + } +} + +################################################################################ + +$Inst = ExtUtils::Installed->new(); +@Modules = $Inst->modules(); +toplevel(); + +################################################################################ diff --git a/gnu/usr.bin/perl/lib/Fatal.pm b/gnu/usr.bin/perl/lib/Fatal.pm new file mode 100644 index 00000000000..d1d95af8848 --- /dev/null +++ b/gnu/usr.bin/perl/lib/Fatal.pm @@ -0,0 +1,159 @@ +package Fatal; + +use Carp; +use strict; +use vars qw( $AUTOLOAD $Debug $VERSION); + +$VERSION = 1.02; + +$Debug = 0 unless defined $Debug; + +sub import { + my $self = shift(@_); + my($sym, $pkg); + $pkg = (caller)[0]; + foreach $sym (@_) { + &_make_fatal($sym, $pkg); + } +}; + +sub AUTOLOAD { + my $cmd = $AUTOLOAD; + $cmd =~ s/.*:://; + &_make_fatal($cmd, (caller)[0]); + goto &$AUTOLOAD; +} + +sub fill_protos { + my $proto = shift; + my ($n, $isref, @out, @out1, $seen_semi) = -1; + while ($proto =~ /\S/) { + $n++; + push(@out1,[$n,@out]) if $seen_semi; + push(@out, $1 . "{\$_[$n]}"), next if $proto =~ s/^\s*\\([\@%\$\&])//; + push(@out, "\$_[$n]"), next if $proto =~ s/^\s*([*\$&])//; + push(@out, "\@_[$n..\$#_]"), last if $proto =~ s/^\s*(;\s*)?\@//; + $seen_semi = 1, $n--, next if $proto =~ s/^\s*;//; # XXXX ???? + die "Unknown prototype letters: \"$proto\""; + } + push(@out1,[$n+1,@out]); + @out1; +} + +sub write_invocation { + my ($core, $call, $name, @argvs) = @_; + if (@argvs == 1) { # No optional arguments + my @argv = @{$argvs[0]}; + shift @argv; + return "\t" . one_invocation($core, $call, $name, @argv) . ";\n"; + } else { + my $else = "\t"; + my (@out, @argv, $n); + while (@argvs) { + @argv = @{shift @argvs}; + $n = shift @argv; + push @out, "$ {else}if (\@_ == $n) {\n"; + $else = "\t} els"; + push @out, + "\t\treturn " . one_invocation($core, $call, $name, @argv) . ";\n"; + } + push @out, <<EOC; + } + die "$name(\@_): Do not expect to get ", scalar \@_, " arguments"; +EOC + return join '', @out; + } +} + +sub one_invocation { + my ($core, $call, $name, @argv) = @_; + local $" = ', '; + return qq{$call(@argv) || croak "Can't $name(\@_)} . + ($core ? ': $!' : ', \$! is \"$!\"') . '"'; +} + +sub _make_fatal { + my($sub, $pkg) = @_; + my($name, $code, $sref, $real_proto, $proto, $core, $call); + my $ini = $sub; + + $sub = "${pkg}::$sub" unless $sub =~ /::/; + $name = $sub; + $name =~ s/.*::// or $name =~ s/^&//; + print "# _make_fatal: sub=$sub pkg=$pkg name=$name\n" if $Debug; + croak "Bad subroutine name for Fatal: $name" unless $name =~ /^\w+$/; + if (defined(&$sub)) { # user subroutine + $sref = \&$sub; + $proto = prototype $sref; + $call = '&$sref'; + } elsif ($sub eq $ini) { # Stray user subroutine + die "$sub is not a Perl subroutine" + } else { # CORE subroutine + $proto = eval { prototype "CORE::$name" }; + die "$name is neither a builtin, nor a Perl subroutine" + if $@; + die "Cannot make a non-overridable builtin fatal" + if not defined $proto; + $core = 1; + $call = "CORE::$name"; + } + if (defined $proto) { + $real_proto = " ($proto)"; + } else { + $real_proto = ''; + $proto = '@'; + } + $code = <<EOS; +sub$real_proto { + local(\$", \$!) = (', ', 0); +EOS + my @protos = fill_protos($proto); + $code .= write_invocation($core, $call, $name, @protos); + $code .= "}\n"; + print $code if $Debug; + { + no strict 'refs'; # to avoid: Can't use string (...) as a symbol ref ... + $code = eval("package $pkg; use Carp; $code"); + die if $@; + local($^W) = 0; # to avoid: Subroutine foo redefined ... + *{$sub} = $code; + } +} + +1; + +__END__ + +=head1 NAME + +Fatal - replace functions with equivalents which succeed or die + +=head1 SYNOPSIS + + use Fatal qw(open close); + + sub juggle { . . . } + import Fatal 'juggle'; + +=head1 DESCRIPTION + +C<Fatal> provides a way to conveniently replace functions which normally +return a false value when they fail with equivalents which halt execution +if they are not successful. This lets you use these functions without +having to test their return values explicitly on each call. Errors are +reported via C<die>, so you can trap them using C<$SIG{__DIE__}> if you +wish to take some action before the program exits. + +The do-or-die equivalents are set up simply by calling Fatal's +C<import> routine, passing it the names of the functions to be +replaced. You may wrap both user-defined functions and overridable +CORE operators (except C<exec>, C<system> which cannot be expressed +via prototypes) in this way. + +=head1 AUTHOR + +Lionel.Cons@cern.ch + +prototype updates by Ilya Zakharevich ilya@math.ohio-state.edu + +=cut diff --git a/gnu/usr.bin/perl/lib/File/Spec.pm b/gnu/usr.bin/perl/lib/File/Spec.pm new file mode 100644 index 00000000000..616dcbcb7a0 --- /dev/null +++ b/gnu/usr.bin/perl/lib/File/Spec.pm @@ -0,0 +1,116 @@ +package File::Spec; + +require Exporter; + +@ISA = qw(Exporter); +# Items to export into callers namespace by default. Note: do not export +# names by default without a very good reason. Use EXPORT_OK instead. +# Do not simply export all your public functions/methods/constants. +@EXPORT = qw( + +); +@EXPORT_OK = qw($Verbose); + +use strict; +use vars qw(@ISA $VERSION $Verbose); + +$VERSION = '0.6'; + +$Verbose = 0; + +require File::Spec::Unix; + + +sub load { + my($class,$OS) = @_; + if ($OS eq 'VMS') { + require File::Spec::VMS; + require VMS::Filespec; + 'File::Spec::VMS' + } elsif ($OS eq 'os2') { + require File::Spec::OS2; + 'File::Spec::OS2' + } elsif ($OS eq 'MacOS') { + require File::Spec::Mac; + 'File::Spec::Mac' + } elsif ($OS eq 'MSWin32') { + require File::Spec::Win32; + 'File::Spec::Win32' + } else { + 'File::Spec::Unix' + } +} + +@ISA = load('File::Spec', $^O); + +1; +__END__ + +=head1 NAME + +File::Spec - portably perform operations on file names + +=head1 SYNOPSIS + +C<use File::Spec;> + +C<$x=File::Spec-E<gt>catfile('a','b','c');> + +which returns 'a/b/c' under Unix. + +=head1 DESCRIPTION + +This module is designed to support operations commonly performed on file +specifications (usually called "file names", but not to be confused with the +contents of a file, or Perl's file handles), such as concatenating several +directory and file names into a single path, or determining whether a path +is rooted. It is based on code directly taken from MakeMaker 5.17, code +written by Andreas KE<ouml>nig, Andy Dougherty, Charles Bailey, Ilya +Zakharevich, Paul Schinder, and others. + +Since these functions are different for most operating systems, each set of +OS specific routines is available in a separate module, including: + + File::Spec::Unix + File::Spec::Mac + File::Spec::OS2 + File::Spec::Win32 + File::Spec::VMS + +The module appropriate for the current OS is automatically loaded by +File::Spec. Since some modules (like VMS) make use of OS specific +facilities, it may not be possible to load all modules under all operating +systems. + +Since File::Spec is object oriented, subroutines should not called directly, +as in: + + File::Spec::catfile('a','b'); + +but rather as class methods: + + File::Spec->catfile('a','b'); + +For a reference of available functions, please consult L<File::Spec::Unix>, +which contains the entire set, and inherited by the modules for other +platforms. For further information, please see L<File::Spec::Mac>, +L<File::Spec::OS2>, L<File::Spec::Win32>, or L<File::Spec::VMS>. + +=head1 SEE ALSO + +File::Spec::Unix, File::Spec::Mac, File::Spec::OS2, File::Spec::Win32, +File::Spec::VMS, ExtUtils::MakeMaker + +=head1 AUTHORS + +Kenneth Albanowski <F<kjahds@kjahds.com>>, Andy Dougherty +<F<doughera@lafcol.lafayette.edu>>, Andreas KE<ouml>nig +<F<A.Koenig@franz.ww.TU-Berlin.DE>>, Tim Bunce <F<Tim.Bunce@ig.co.uk>>. VMS +support by Charles Bailey <F<bailey@newman.upenn.edu>>. OS/2 support by +Ilya Zakharevich <F<ilya@math.ohio-state.edu>>. Mac support by Paul Schinder +<F<schinder@pobox.com>>. + +=cut + + +1; diff --git a/gnu/usr.bin/perl/lib/File/Spec/Mac.pm b/gnu/usr.bin/perl/lib/File/Spec/Mac.pm new file mode 100644 index 00000000000..63a9e1283e0 --- /dev/null +++ b/gnu/usr.bin/perl/lib/File/Spec/Mac.pm @@ -0,0 +1,230 @@ +package File::Spec::Mac; + +use Exporter (); +use Config; +use strict; +use File::Spec; +use vars qw(@ISA $VERSION $Is_Mac); + +$VERSION = '1.0'; + +@ISA = qw(File::Spec::Unix); +$Is_Mac = $^O eq 'MacOS'; + +Exporter::import('File::Spec', '$Verbose'); + + +=head1 NAME + +File::Spec::Mac - File::Spec for MacOS + +=head1 SYNOPSIS + +C<require File::Spec::Mac;> + +=head1 DESCRIPTION + +Methods for manipulating file specifications. + +=head1 METHODS + +=over 2 + +=item canonpath + +On MacOS, there's nothing to be done. Returns what it's given. + +=cut + +sub canonpath { + my($self,$path) = @_; + $path; +} + +=item catdir + +Concatenate two or more directory names to form a complete path ending with +a directory. Put a trailing : on the end of the complete path if there +isn't one, because that's what's done in MacPerl's environment. + +The fundamental requirement of this routine is that + + File::Spec->catdir(split(":",$path)) eq $path + +But because of the nature of Macintosh paths, some additional +possibilities are allowed to make using this routine give reasonable results +for some common situations. Here are the rules that are used. Each +argument has its trailing ":" removed. Each argument, except the first, +has its leading ":" removed. They are then joined together by a ":". + +So + + File::Spec->catdir("a","b") = "a:b:" + File::Spec->catdir("a:",":b") = "a:b:" + File::Spec->catdir("a:","b") = "a:b:" + File::Spec->catdir("a",":b") = "a:b" + File::Spec->catdir("a","","b") = "a::b" + +etc. + +To get a relative path (one beginning with :), begin the first argument with : +or put a "" as the first argument. + +If you don't want to worry about these rules, never allow a ":" on the ends +of any of the arguments except at the beginning of the first. + +Under MacPerl, there is an additional ambiguity. Does the user intend that + + File::Spec->catfile("LWP","Protocol","http.pm") + +be relative or absolute? There's no way of telling except by checking for the +existence of LWP: or :LWP, and even there he may mean a dismounted volume or +a relative path in a different directory (like in @INC). So those checks +aren't done here. This routine will treat this as absolute. + +=cut + +# '; + +sub catdir { + shift; + my @args = @_; + $args[0] =~ s/:$//; + my $result = shift @args; + for (@args) { + s/:$//; + s/^://; + $result .= ":$_"; + } + $result .= ":"; + $result; +} + +=item catfile + +Concatenate one or more directory names and a filename to form a +complete path ending with a filename. Since this uses catdir, the +same caveats apply. Note that the leading : is removed from the filename, +so that + + File::Spec->catfile($ENV{HOME},"file"); + +and + + File::Spec->catfile($ENV{HOME},":file"); + +give the same answer, as one might expect. + +=cut + +sub catfile { + my $self = shift @_; + my $file = pop @_; + return $file unless @_; + my $dir = $self->catdir(@_); + $file =~ s/^://; + return $dir.$file; +} + +=item curdir + +Returns a string representing of the current directory. + +=cut + +sub curdir { + return ":" ; +} + +=item rootdir + +Returns a string representing the root directory. Under MacPerl, +returns the name of the startup volume, since that's the closest in +concept, although other volumes aren't rooted there. On any other +platform returns '', since there's no common way to indicate "root +directory" across all Macs. + +=cut + +sub rootdir { +# +# There's no real root directory on MacOS. If you're using MacPerl, +# the name of the startup volume is returned, since that's the closest in +# concept. On other platforms, simply return '', because nothing better +# can be done. +# + if($Is_Mac) { + require Mac::Files; + my $system = Mac::Files::FindFolder(&Mac::Files::kOnSystemDisk, + &Mac::Files::kSystemFolderType); + $system =~ s/:.*$/:/; + return $system; + } else { + return ''; + } +} + +=item updir + +Returns a string representing the parent directory. + +=cut + +sub updir { + return "::"; +} + +=item file_name_is_absolute + +Takes as argument a path and returns true, if it is an absolute path. In +the case where a name can be either relative or absolute (for example, a +folder named "HD" in the current working directory on a drive named "HD"), +relative wins. Use ":" in the appropriate place in the path if you want to +distinguish unambiguously. + +=cut + +sub file_name_is_absolute { + my($self,$file) = @_; + if ($file =~ /:/) { + return ($file !~ m/^:/); + } else { + return (! -e ":$file"); + } +} + +=item path + +Returns the null list for the MacPerl application, since the concept is +usually meaningless under MacOS. But if you're using the MacPerl tool under +MPW, it gives back $ENV{Commands} suitably split, as is done in +:lib:ExtUtils:MM_Mac.pm. + +=cut + +sub path { +# +# The concept is meaningless under the MacPerl application. +# Under MPW, it has a meaning. +# + my($self) = @_; + my @path; + if(exists $ENV{Commands}) { + @path = split /,/,$ENV{Commands}; + } else { + @path = (); + } + @path; +} + +=back + +=head1 SEE ALSO + +L<File::Spec> + +=cut + +1; +__END__ + diff --git a/gnu/usr.bin/perl/lib/File/Spec/OS2.pm b/gnu/usr.bin/perl/lib/File/Spec/OS2.pm new file mode 100644 index 00000000000..d6026177028 --- /dev/null +++ b/gnu/usr.bin/perl/lib/File/Spec/OS2.pm @@ -0,0 +1,51 @@ +package File::Spec::OS2; + +#use Config; +#use Cwd; +#use File::Basename; +use strict; +require Exporter; + +use File::Spec; +use vars qw(@ISA); + +Exporter::import('File::Spec', + qw( $Verbose)); + +@ISA = qw(File::Spec::Unix); + +$ENV{EMXSHELL} = 'sh'; # to run `commands` + +sub file_name_is_absolute { + my($self,$file) = @_; + $file =~ m{^([a-z]:)?[\\/]}i ; +} + +sub path { + my($self) = @_; + my $path_sep = ";"; + my $path = $ENV{PATH}; + $path =~ s:\\:/:g; + my @path = split $path_sep, $path; + foreach(@path) { $_ = '.' if $_ eq '' } + @path; +} + +1; +__END__ + +=head1 NAME + +File::Spec::OS2 - methods for OS/2 file specs + +=head1 SYNOPSIS + + use File::Spec::OS2; # Done internally by File::Spec if needed + +=head1 DESCRIPTION + +See File::Spec::Unix for a documentation of the methods provided +there. This package overrides the implementation of these methods, not +the semantics. + +=cut diff --git a/gnu/usr.bin/perl/lib/File/Spec/Unix.pm b/gnu/usr.bin/perl/lib/File/Spec/Unix.pm new file mode 100644 index 00000000000..77de73a216a --- /dev/null +++ b/gnu/usr.bin/perl/lib/File/Spec/Unix.pm @@ -0,0 +1,197 @@ +package File::Spec::Unix; + +use Exporter (); +use Config; +use File::Basename qw(basename dirname fileparse); +use DirHandle; +use strict; +use vars qw(@ISA $Is_Mac $Is_OS2 $Is_VMS $Is_Win32); +use File::Spec; + +Exporter::import('File::Spec', '$Verbose'); + +$Is_OS2 = $^O eq 'os2'; +$Is_Mac = $^O eq 'MacOS'; +$Is_Win32 = $^O eq 'MSWin32'; + +if ($Is_VMS = $^O eq 'VMS') { + require VMS::Filespec; + import VMS::Filespec qw( &vmsify ); +} + +=head1 NAME + +File::Spec::Unix - methods used by File::Spec + +=head1 SYNOPSIS + +C<require File::Spec::Unix;> + +=head1 DESCRIPTION + +Methods for manipulating file specifications. + +=head1 METHODS + +=over 2 + +=item canonpath + +No physical check on the filesystem, but a logical cleanup of a +path. On UNIX eliminated successive slashes and successive "/.". + +=cut + +sub canonpath { + my($self,$path) = @_; + $path =~ s|/+|/|g ; # xx////xx -> xx/xx + $path =~ s|(/\.)+/|/|g ; # xx/././xx -> xx/xx + $path =~ s|^(\./)+|| unless $path eq "./"; # ./xx -> xx + $path =~ s|/$|| unless $path eq "/"; # xx/ -> xx + $path; +} + +=item catdir + +Concatenate two or more directory names to form a complete path ending +with a directory. But remove the trailing slash from the resulting +string, because it doesn't look good, isn't necessary and confuses +OS2. Of course, if this is the root directory, don't cut off the +trailing slash :-) + +=cut + +# '; + +sub catdir { + shift; + my @args = @_; + for (@args) { + # append a slash to each argument unless it has one there + $_ .= "/" if $_ eq '' or substr($_,-1) ne "/"; + } + my $result = join('', @args); + # remove a trailing slash unless we are root + substr($result,-1) = "" + if length($result) > 1 && substr($result,-1) eq "/"; + $result; +} + +=item catfile + +Concatenate one or more directory names and a filename to form a +complete path ending with a filename + +=cut + +sub catfile { + my $self = shift @_; + my $file = pop @_; + return $file unless @_; + my $dir = $self->catdir(@_); + for ($dir) { + $_ .= "/" unless substr($_,length($_)-1,1) eq "/"; + } + return $dir.$file; +} + +=item curdir + +Returns a string representing of the current directory. "." on UNIX. + +=cut + +sub curdir { + return "." ; +} + +=item rootdir + +Returns a string representing of the root directory. "/" on UNIX. + +=cut + +sub rootdir { + return "/"; +} + +=item updir + +Returns a string representing of the parent directory. ".." on UNIX. + +=cut + +sub updir { + return ".."; +} + +=item no_upwards + +Given a list of file names, strip out those that refer to a parent +directory. (Does not strip symlinks, only '.', '..', and equivalents.) + +=cut + +sub no_upwards { + my($self) = shift; + return grep(!/^\.{1,2}$/, @_); +} + +=item file_name_is_absolute + +Takes as argument a path and returns true, if it is an absolute path. + +=cut + +sub file_name_is_absolute { + my($self,$file) = @_; + $file =~ m:^/: ; +} + +=item path + +Takes no argument, returns the environment variable PATH as an array. + +=cut + +sub path { + my($self) = @_; + my $path_sep = ":"; + my $path = $ENV{PATH}; + my @path = split $path_sep, $path; + foreach(@path) { $_ = '.' if $_ eq '' } + @path; +} + +=item join + +join is the same as catfile. + +=cut + +sub join { + my($self) = shift @_; + $self->catfile(@_); +} + +=item nativename + +TBW. + +=cut + +sub nativename { + my($self,$name) = shift @_; + $name; +} + +=back + +=head1 SEE ALSO + +L<File::Spec> + +=cut + +1; +__END__ diff --git a/gnu/usr.bin/perl/lib/File/Spec/VMS.pm b/gnu/usr.bin/perl/lib/File/Spec/VMS.pm new file mode 100644 index 00000000000..c5269fd10c7 --- /dev/null +++ b/gnu/usr.bin/perl/lib/File/Spec/VMS.pm @@ -0,0 +1,148 @@ + +package File::Spec::VMS; + +use Carp qw( &carp ); +use Config; +require Exporter; +use VMS::Filespec; +use File::Basename; + +use File::Spec; +use vars qw($Revision); +$Revision = '5.3901 (6-Mar-1997)'; + +@ISA = qw(File::Spec::Unix); + +Exporter::import('File::Spec', '$Verbose'); + +=head1 NAME + +File::Spec::VMS - methods for VMS file specs + +=head1 SYNOPSIS + + use File::Spec::VMS; # Done internally by File::Spec if needed + +=head1 DESCRIPTION + +See File::Spec::Unix for a documentation of the methods provided +there. This package overrides the implementation of these methods, not +the semantics. + +=head2 Methods always loaded + +=over + +=item catdir + +Concatenates a list of file specifications, and returns the result as a +VMS-syntax directory specification. + +=cut + +sub catdir { + my($self,@dirs) = @_; + my($dir) = pop @dirs; + @dirs = grep($_,@dirs); + my($rslt); + 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 = $self->fixpath($self->eliminate_macros($spath)."/$sdir",1); + } + else { + if ($dir =~ /^\$\([^\)]+\)$/) { $rslt = $dir; } + else { $rslt = vmspath($dir); } + } + print "catdir(",join(',',@_[1..$#_]),") = |$rslt|\n" if $Verbose >= 3; + $rslt; +} + +=item catfile + +Concatenates a list of file specifications, and returns the result as a +VMS-syntax directory specification. + +=cut + +sub catfile { + my($self,@files) = @_; + my($file) = pop @files; + @files = grep($_,@files); + my($rslt); + 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; +} + +=item curdir (override) + +Returns a string representing of the current directory. + +=cut + +sub curdir { + return '[]'; +} + +=item rootdir (override) + +Returns a string representing of the root directory. + +=cut + +sub rootdir { + return ''; +} + +=item updir (override) + +Returns a string representing of the parent directory. + +=cut + +sub updir { + return '[-]'; +} + +=item path (override) + +Translate logical name DCL$PATH as a searchlist, rather than trying +to C<split> string value of C<$ENV{'PATH'}>. + +=cut + +sub path { + my(@dirs,$dir,$i); + while ($dir = $ENV{'DCL$PATH;' . $i++}) { push(@dirs,$dir); } + @dirs; +} + +=item file_name_is_absolute (override) + +Checks for VMS directory spec as well as Unix separators. + +=cut + +sub file_name_is_absolute { + my($self,$file) = @_; + # If it's a logical name, expand it. + $file = $ENV{$file} while $file =~ /^[\w\$\-]+$/ and $ENV{$file}; + $file =~ m!^/! or $file =~ m![<\[][^.\-\]>]! or $file =~ /:[^<\[]/; +} + +1; +__END__ + diff --git a/gnu/usr.bin/perl/lib/File/Spec/Win32.pm b/gnu/usr.bin/perl/lib/File/Spec/Win32.pm new file mode 100644 index 00000000000..034a0cbc2e6 --- /dev/null +++ b/gnu/usr.bin/perl/lib/File/Spec/Win32.pm @@ -0,0 +1,104 @@ +package File::Spec::Win32; + +=head1 NAME + +File::Spec::Win32 - methods for Win32 file specs + +=head1 SYNOPSIS + + use File::Spec::Win32; # Done internally by File::Spec if needed + +=head1 DESCRIPTION + +See File::Spec::Unix for a documentation of the methods provided +there. This package overrides the implementation of these methods, not +the semantics. + +=over + +=cut + +#use Config; +#use Cwd; +use File::Basename; +require Exporter; +use strict; + +use vars qw(@ISA); + +use File::Spec; +Exporter::import('File::Spec', qw( $Verbose)); + +@ISA = qw(File::Spec::Unix); + +$ENV{EMXSHELL} = 'sh'; # to run `commands` + +sub file_name_is_absolute { + my($self,$file) = @_; + $file =~ m{^([a-z]:)?[\\/]}i ; +} + +sub catdir { + my $self = shift; + my @args = @_; + for (@args) { + # append a slash to each argument unless it has one there + $_ .= "\\" if $_ eq '' or substr($_,-1) ne "\\"; + } + my $result = $self->canonpath(join('', @args)); + $result; +} + +=item catfile + +Concatenate one or more directory names and a filename to form a +complete path ending with a filename + +=cut + +sub catfile { + my $self = shift @_; + my $file = pop @_; + return $file unless @_; + my $dir = $self->catdir(@_); + $dir =~ s/(\\\.)$//; + $dir .= "\\" unless substr($dir,length($dir)-1,1) eq "\\"; + return $dir.$file; +} + +sub path { + local $^W = 1; + my($self) = @_; + my $path = $ENV{'PATH'} || $ENV{'Path'} || $ENV{'path'}; + my @path = split(';',$path); + foreach(@path) { $_ = '.' if $_ eq '' } + @path; +} + +=item canonpath + +No physical check on the filesystem, but a logical cleanup of a +path. On UNIX eliminated successive slashes and successive "/.". + +=cut + +sub canonpath { + my($self,$path) = @_; + $path =~ s/^([a-z]:)/\u$1/; + $path =~ s|/|\\|g; + $path =~ s|\\+|\\|g ; # xx////xx -> xx/xx + $path =~ s|(\\\.)+\\|\\|g ; # xx/././xx -> xx/xx + $path =~ s|^(\.\\)+|| unless $path eq ".\\"; # ./xx -> xx + $path =~ s|\\$|| + unless $path =~ m#^([a-z]:)?\\#; # xx/ -> xx + $path .= '.' if $path =~ m#\\$#; + $path; +} + +1; +__END__ + +=back + +=cut + diff --git a/gnu/usr.bin/perl/lib/Math/BigFloat.pm b/gnu/usr.bin/perl/lib/Math/BigFloat.pm index 7551ad01a38..03bc2f4e271 100644 --- a/gnu/usr.bin/perl/lib/Math/BigFloat.pm +++ b/gnu/usr.bin/perl/lib/Math/BigFloat.pm @@ -37,7 +37,7 @@ sub numify { 0 + "${$_[0]}" } # Not needed, additional overhead sub stringify { my $n = ${$_[0]}; - $n =~ s/^\+//; + my $minus = ($n =~ s/^([+-])// && $1 eq '-'); $n =~ s/E//; $n =~ s/([-+]\d+)$//; @@ -52,6 +52,7 @@ sub stringify { } else { $n = '.' . ("0" x (abs($e) - $ln)) . $n; } + $n = "-$n" if $minus; # 1 while $n =~ s/(.*\d)(\d\d\d)/$1,$2/; @@ -273,7 +274,7 @@ Math::BigFloat - Arbitrary length float math package =head1 SYNOPSIS - use Math::BogFloat; + use Math::BigFloat; $f = Math::BigFloat->new($string); $f->fadd(NSTR) return NSTR addition @@ -300,7 +301,7 @@ floats as =item number format canonical strings have the form /[+-]\d+E[+-]\d+/ . Input values can -have inbedded whitespace. +have imbedded whitespace. =item Error returns 'NaN' diff --git a/gnu/usr.bin/perl/lib/Test.pm b/gnu/usr.bin/perl/lib/Test.pm new file mode 100644 index 00000000000..7a0e59b855f --- /dev/null +++ b/gnu/usr.bin/perl/lib/Test.pm @@ -0,0 +1,249 @@ +use strict; +package Test; +use Test::Harness 1.1601 (); +use Carp; +use vars (qw($VERSION @ISA @EXPORT @EXPORT_OK $ntest $TestLevel), #public-ish + qw($TESTOUT $ONFAIL %todo %history $planned @FAILDETAIL)); #private-ish +$VERSION = '1.122'; +require Exporter; +@ISA=('Exporter'); +@EXPORT=qw(&plan &ok &skip); +@EXPORT_OK=qw($ntest $TESTOUT); + +$TestLevel = 0; # how many extra stack frames to skip +$|=1; +#$^W=1; ? +$ntest=1; +$TESTOUT = *STDOUT{IO}; + +# Use of this variable is strongly discouraged. It is set mainly to +# help test coverage analyzers know which test is running. +$ENV{REGRESSION_TEST} = $0; + +sub plan { + croak "Test::plan(%args): odd number of arguments" if @_ & 1; + croak "Test::plan(): should not be called more than once" if $planned; + my $max=0; + for (my $x=0; $x < @_; $x+=2) { + my ($k,$v) = @_[$x,$x+1]; + if ($k =~ /^test(s)?$/) { $max = $v; } + elsif ($k eq 'todo' or + $k eq 'failok') { for (@$v) { $todo{$_}=1; }; } + elsif ($k eq 'onfail') { + ref $v eq 'CODE' or croak "Test::plan(onfail => $v): must be CODE"; + $ONFAIL = $v; + } + else { carp "Test::plan(): skipping unrecognized directive '$k'" } + } + my @todo = sort { $a <=> $b } keys %todo; + if (@todo) { + print $TESTOUT "1..$max todo ".join(' ', @todo).";\n"; + } else { + print $TESTOUT "1..$max\n"; + } + ++$planned; +} + +sub to_value { + my ($v) = @_; + (ref $v or '') eq 'CODE' ? $v->() : $v; +} + +sub ok ($;$$) { + croak "ok: plan before you test!" if !$planned; + my ($pkg,$file,$line) = caller($TestLevel); + my $repetition = ++$history{"$file:$line"}; + my $context = ("$file at line $line". + ($repetition > 1 ? " fail \#$repetition" : '')); + my $ok=0; + my $result = to_value(shift); + my ($expected,$diag); + if (@_ == 0) { + $ok = $result; + } else { + $expected = to_value(shift); + my ($regex,$ignore); + if ((ref($expected)||'') eq 'Regexp') { + $ok = $result =~ /$expected/; + } elsif (($regex) = ($expected =~ m,^ / (.+) / $,sx) or + ($ignore, $regex) = ($expected =~ m,^ m([^\w\s]) (.+) \1 $,sx)) { + $ok = $result =~ /$regex/; + } else { + $ok = $result eq $expected; + } + } + my $todo = $todo{$ntest}; + if ($todo and $ok) { + $context .= ' TODO?!' if $todo; + print $TESTOUT "ok $ntest # ($context)\n"; + } else { + print $TESTOUT "not " if !$ok; + print $TESTOUT "ok $ntest\n"; + + if (!$ok) { + my $detail = { 'repetition' => $repetition, 'package' => $pkg, + 'result' => $result, 'todo' => $todo }; + $$detail{expected} = $expected if defined $expected; + $diag = $$detail{diagnostic} = to_value(shift) if @_; + $context .= ' *TODO*' if $todo; + if (!defined $expected) { + if (!$diag) { + print $TESTOUT "# Failed test $ntest in $context\n"; + } else { + print $TESTOUT "# Failed test $ntest in $context: $diag\n"; + } + } else { + my $prefix = "Test $ntest"; + print $TESTOUT "# $prefix got: '$result' ($context)\n"; + $prefix = ' ' x (length($prefix) - 5); + if ((ref($expected)||'') eq 'Regexp') { + $expected = 'qr/'.$expected.'/' + } else { + $expected = "'$expected'"; + } + if (!$diag) { + print $TESTOUT "# $prefix Expected: $expected\n"; + } else { + print $TESTOUT "# $prefix Expected: $expected ($diag)\n"; + } + } + push @FAILDETAIL, $detail; + } + } + ++ $ntest; + $ok; +} + +sub skip ($$;$$) { + my $whyskip = to_value(shift); + if ($whyskip) { + $whyskip = 'skip' if $whyskip =~ m/^\d+$/; + print $TESTOUT "ok $ntest # $whyskip\n"; + ++ $ntest; + 1; + } else { + local($TestLevel) = $TestLevel+1; #ignore this stack frame + &ok; + } +} + +END { + $ONFAIL->(\@FAILDETAIL) if @FAILDETAIL && $ONFAIL; +} + +1; +__END__ + +=head1 NAME + + Test - provides a simple framework for writing test scripts + +=head1 SYNOPSIS + + use strict; + use Test; + + # use a BEGIN block so we print our plan before MyModule is loaded + BEGIN { plan tests => 14, todo => [3,4] } + + # load your module... + use MyModule; + + ok(0); # failure + ok(1); # success + + ok(0); # ok, expected failure (see todo list, above) + ok(1); # surprise success! + + ok(0,1); # failure: '0' ne '1' + ok('broke','fixed'); # failure: 'broke' ne 'fixed' + ok('fixed','fixed'); # success: 'fixed' eq 'fixed' + ok('fixed',qr/x/); # success: 'fixed' =~ qr/x/ + + ok(sub { 1+1 }, 2); # success: '2' eq '2' + ok(sub { 1+1 }, 3); # failure: '2' ne '3' + ok(0, int(rand(2)); # (just kidding :-) + + my @list = (0,0); + ok @list, 3, "\@list=".join(',',@list); #extra diagnostics + ok 'segmentation fault', '/(?i)success/'; #regex match + + skip($feature_is_missing, ...); #do platform specific test + +=head1 DESCRIPTION + +L<Test::Harness> expects to see particular output when it executes +tests. This module aims to make writing proper test scripts just a +little bit easier (and less error prone :-). + +=head1 TEST TYPES + +=over 4 + +=item * NORMAL TESTS + +These tests are expected to succeed. If they don't something's +screwed up! + +=item * SKIPPED TESTS + +Skip is for tests that might or might not be possible to run depending +on the availability of platform specific features. The first argument +should evaluate to true (think "yes, please skip") if the required +feature is not available. After the first argument, skip works +exactly the same way as do normal tests. + +=item * TODO TESTS + +TODO tests are designed for maintaining an B<executable TODO list>. +These tests are expected NOT to succeed. If a TODO test does succeed, +the feature in question should not be on the TODO list, now should it? + +Packages should NOT be released with succeeding TODO tests. As soon +as a TODO test starts working, it should be promoted to a normal test +and the newly working feature should be documented in the release +notes or change log. + +=back + +=head1 RETURN VALUE + +Both C<ok> and C<skip> return true if their test succeeds and false +otherwise in a scalar context. + +=head1 ONFAIL + + BEGIN { plan test => 4, onfail => sub { warn "CALL 911!" } } + +While test failures should be enough, extra diagnostics can be +triggered at the end of a test run. C<onfail> is passed an array ref +of hash refs that describe each test failure. Each hash will contain +at least the following fields: C<package>, C<repetition>, and +C<result>. (The file, line, and test number are not included because +their correspondance to a particular test is tenuous.) If the test +had an expected value or a diagnostic string, these will also be +included. + +The B<optional> C<onfail> hook might be used simply to print out the +version of your package and/or how to report problems. It might also +be used to generate extremely sophisticated diagnostics for a +particularly bizarre test failure. However it's not a panacea. Core +dumps or other unrecoverable errors prevent the C<onfail> hook from +running. (It is run inside an C<END> block.) Besides, C<onfail> is +probably over-kill in most cases. (Your test code should be simpler +than the code it is testing, yes?) + +=head1 SEE ALSO + +L<Test::Harness> and, perhaps, test coverage analysis tools. + +=head1 AUTHOR + +Copyright (c) 1998 Joshua Nathaniel Pritikin. All rights reserved. + +This package is free software and is provided "as is" without express +or implied warranty. It may be used, redistributed and/or modified +under the terms of the Perl Artistic License (see +http://www.perl.com/perl/misc/Artistic.html) + +=cut diff --git a/gnu/usr.bin/perl/lib/Tie/Array.pm b/gnu/usr.bin/perl/lib/Tie/Array.pm new file mode 100644 index 00000000000..3f34c3b81ff --- /dev/null +++ b/gnu/usr.bin/perl/lib/Tie/Array.pm @@ -0,0 +1,262 @@ +package Tie::Array; +use vars qw($VERSION); +use strict; +$VERSION = '1.00'; + +# Pod documentation after __END__ below. + +sub DESTROY { } +sub EXTEND { } +sub UNSHIFT { shift->SPLICE(0,0,@_) } +sub SHIFT { shift->SPLICE(0,1) } +sub CLEAR { shift->STORESIZE(0) } + +sub PUSH +{ + my $obj = shift; + my $i = $obj->FETCHSIZE; + $obj->STORE($i++, shift) while (@_); +} + +sub POP +{ + my $obj = shift; + my $newsize = $obj->FETCHSIZE - 1; + my $val; + if ($newsize >= 0) + { + $val = $obj->FETCH($newsize); + $obj->STORESIZE($newsize); + } + $val; +} + +sub SPLICE +{ + my $obj = shift; + my $sz = $obj->FETCHSIZE; + my $off = (@_) ? shift : 0; + $off += $sz if ($off < 0); + my $len = (@_) ? shift : $sz - $off; + my @result; + for (my $i = 0; $i < $len; $i++) + { + push(@result,$obj->FETCH($off+$i)); + } + if (@_ > $len) + { + # Move items up to make room + my $d = @_ - $len; + my $e = $off+$len; + $obj->EXTEND($sz+$d); + for (my $i=$sz-1; $i >= $e; $i--) + { + my $val = $obj->FETCH($i); + $obj->STORE($i+$d,$val); + } + } + elsif (@_ < $len) + { + # Move items down to close the gap + my $d = $len - @_; + my $e = $off+$len; + for (my $i=$off+$len; $i < $sz; $i++) + { + my $val = $obj->FETCH($i); + $obj->STORE($i-$d,$val); + } + $obj->STORESIZE($sz-$d); + } + for (my $i=0; $i < @_; $i++) + { + $obj->STORE($off+$i,$_[$i]); + } + return @result; +} + +package Tie::StdArray; +use vars qw(@ISA); +@ISA = 'Tie::Array'; + +sub TIEARRAY { bless [], $_[0] } +sub FETCHSIZE { scalar @{$_[0]} } +sub STORESIZE { $#{$_[0]} = $_[1]-1 } +sub STORE { $_[0]->[$_[1]] = $_[2] } +sub FETCH { $_[0]->[$_[1]] } +sub CLEAR { @{$_[0]} = () } +sub POP { pop(@{$_[0]}) } +sub PUSH { my $o = shift; push(@$o,@_) } +sub SHIFT { shift(@{$_[0]}) } +sub UNSHIFT { my $o = shift; unshift(@$o,@_) } + +sub SPLICE +{ + my $ob = shift; + my $sz = $ob->FETCHSIZE; + my $off = @_ ? shift : 0; + $off += $sz if $off < 0; + my $len = @_ ? shift : $sz-$off; + return splice(@$ob,$off,$len,@_); +} + +1; + +__END__ + +=head1 NAME + +Tie::Array - base class for tied arrays + +=head1 SYNOPSIS + + package NewArray; + use Tie::Array; + @ISA = ('Tie::Array'); + + # mandatory methods + sub TIEARRAY { ... } + sub FETCH { ... } + sub FETCHSIZE { ... } + + sub STORE { ... } # mandatory if elements writeable + sub STORESIZE { ... } # mandatory if elements can be added/deleted + + # optional methods - for efficiency + sub CLEAR { ... } + sub PUSH { ... } + sub POP { ... } + sub SHIFT { ... } + sub UNSHIFT { ... } + sub SPLICE { ... } + sub EXTEND { ... } + sub DESTROY { ... } + + package NewStdArray; + use Tie::Array; + + @ISA = ('Tie::StdArray'); + + # all methods provided by default + + package main; + + $object = tie @somearray,Tie::NewArray; + $object = tie @somearray,Tie::StdArray; + $object = tie @somearray,Tie::NewStdArray; + + + +=head1 DESCRIPTION + +This module provides methods for array-tying classes. See +L<perltie> for a list of the functions required in order to tie an array +to a package. The basic B<Tie::Array> package provides stub C<DELETE> +and C<EXTEND> methods, and implementations of C<PUSH>, C<POP>, C<SHIFT>, +C<UNSHIFT>, C<SPLICE> and C<CLEAR> in terms of basic C<FETCH>, C<STORE>, +C<FETCHSIZE>, C<STORESIZE>. + +The B<Tie::StdArray> package provides efficient methods required for tied arrays +which are implemented as blessed references to an "inner" perl array. +It inherits from B<Tie::Array>, and should cause tied arrays to behave exactly +like standard arrays, allowing for selective overloading of methods. + +For developers wishing to write their own tied arrays, the required methods +are briefly defined below. See the L<perltie> section for more detailed +descriptive, as well as example code: + +=over + +=item TIEARRAY classname, LIST + +The class method is invoked by the command C<tie @array, classname>. Associates +an array instance with the specified class. C<LIST> would represent +additional arguments (along the lines of L<AnyDBM_File> and compatriots) needed +to complete the association. The method should return an object of a class which +provides the methods below. + +=item STORE this, index, value + +Store datum I<value> into I<index> for the tied array associated with +object I<this>. If this makes the array larger then +class's mapping of C<undef> should be returned for new positions. + +=item FETCH this, index + +Retrieve the datum in I<index> for the tied array associated with +object I<this>. + +=item FETCHSIZE this + +Returns the total number of items in the tied array associated with +object I<this>. (Equivalent to C<scalar(@array)>). + +=item STORESIZE this, count + +Sets the total number of items in the tied array associated with +object I<this> to be I<count>. If this makes the array larger then +class's mapping of C<undef> should be returned for new positions. +If the array becomes smaller then entries beyond count should be +deleted. + +=item EXTEND this, count + +Informative call that array is likely to grow to have I<count> entries. +Can be used to optimize allocation. This method need do nothing. + +=item CLEAR this + +Clear (remove, delete, ...) all values from the tied array associated with +object I<this>. + +=item DESTROY this + +Normal object destructor method. + +=item PUSH this, LIST + +Append elements of LIST to the array. + +=item POP this + +Remove last element of the array and return it. + +=item SHIFT this + +Remove the first element of the array (shifting other elements down) +and return it. + +=item UNSHIFT this, LIST + +Insert LIST elements at the beginning of the array, moving existing elements +up to make room. + +=item SPLICE this, offset, length, LIST + +Perform the equivalent of C<splice> on the array. + +I<offset> is optional and defaults to zero, negative values count back +from the end of the array. + +I<length> is optional and defaults to rest of the array. + +I<LIST> may be empty. + +Returns a list of the original I<length> elements at I<offset>. + +=back + +=head1 CAVEATS + +There is no support at present for tied @ISA. There is a potential conflict +between magic entries needed to notice setting of @ISA, and those needed to +implement 'tie'. + +Very little consideration has been given to the behaviour of tied arrays +when C<$[> is not default value of zero. + +=head1 AUTHOR + +Nick Ing-Simmons E<lt>nik@tiuk.ti.comE<gt> + +=cut + diff --git a/gnu/usr.bin/perl/lib/Tie/Handle.pm b/gnu/usr.bin/perl/lib/Tie/Handle.pm new file mode 100644 index 00000000000..c7550530b87 --- /dev/null +++ b/gnu/usr.bin/perl/lib/Tie/Handle.pm @@ -0,0 +1,161 @@ +package Tie::Handle; + +=head1 NAME + +Tie::Handle - base class definitions for tied handles + +=head1 SYNOPSIS + + package NewHandle; + require Tie::Handle; + + @ISA = (Tie::Handle); + + sub READ { ... } # Provide a needed method + sub TIEHANDLE { ... } # Overrides inherited method + + + package main; + + tie *FH, 'NewHandle'; + +=head1 DESCRIPTION + +This module provides some skeletal methods for handle-tying classes. See +L<perltie> for a list of the functions required in tying a handle to a package. +The basic B<Tie::Handle> package provides a C<new> method, as well as methods +C<TIESCALAR>, C<FETCH> and C<STORE>. The C<new> method is provided as a means +of grandfathering, for classes that forget to provide their own C<TIESCALAR> +method. + +For developers wishing to write their own tied-handle classes, the methods +are summarized below. The L<perltie> section not only documents these, but +has sample code as well: + +=over + +=item TIEHANDLE classname, LIST + +The method invoked by the command C<tie *glob, classname>. Associates a new +glob instance with the specified class. C<LIST> would represent additional +arguments (along the lines of L<AnyDBM_File> and compatriots) needed to +complete the association. + +=item WRITE this, scalar, length, offset + +Write I<length> bytes of data from I<scalar> starting at I<offset>. + +=item PRINT this, LIST + +Print the values in I<LIST> + +=item PRINTF this, format, LIST + +Print the values in I<LIST> using I<format> + +=item READ this, scalar, length, offset + +Read I<length> bytes of data into I<scalar> starting at I<offset>. + +=item READLINE this + +Read a single line + +=item GETC this + +Get a single character + +=item DESTROY this + +Free the storage associated with the tied handle referenced by I<this>. +This is rarely needed, as Perl manages its memory quite well. But the +option exists, should a class wish to perform specific actions upon the +destruction of an instance. + +=back + +=head1 MORE INFORMATION + +The L<perltie> section contains an example of tying handles. + +=cut + +use Carp; + +sub new { + my $pkg = shift; + $pkg->TIEHANDLE(@_); +} + +# "Grandfather" the new, a la Tie::Hash + +sub TIEHANDLE { + my $pkg = shift; + if (defined &{"{$pkg}::new"}) { + carp "WARNING: calling ${pkg}->new since ${pkg}->TIEHANDLE is missing" + if $^W; + $pkg->new(@_); + } + else { + croak "$pkg doesn't define a TIEHANDLE method"; + } +} + +sub PRINT { + my $self = shift; + if($self->can('WRITE') != \&WRITE) { + my $buf = join(defined $, ? $, : "",@_); + $buf .= $\ if defined $\; + $self->WRITE($buf,length($buf),0); + } + else { + croak ref($self)," doesn't define a PRINT method"; + } +} + +sub PRINTF { + my $self = shift; + + if($self->can('WRITE') != \&WRITE) { + my $buf = sprintf(@_); + $self->WRITE($buf,length($buf),0); + } + else { + croak ref($self)," doesn't define a PRINTF method"; + } +} + +sub READLINE { + my $pkg = ref $_[0]; + croak "$pkg doesn't define a READLINE method"; +} + +sub GETC { + my $self = shift; + + if($self->can('READ') != \&READ) { + my $buf; + $self->READ($buf,1); + return $buf; + } + else { + croak ref($self)," doesn't define a GETC method"; + } +} + +sub READ { + my $pkg = ref $_[0]; + croak "$pkg doesn't define a READ method"; +} + +sub WRITE { + my $pkg = ref $_[0]; + croak "$pkg doesn't define a WRITE method"; +} + +sub CLOSE { + my $pkg = ref $_[0]; + croak "$pkg doesn't define a CLOSE method"; +} + +1; diff --git a/gnu/usr.bin/perl/lib/chat2.pl b/gnu/usr.bin/perl/lib/chat2.pl index 0d9a7d3d503..094d3dff21a 100644 --- a/gnu/usr.bin/perl/lib/chat2.pl +++ b/gnu/usr.bin/perl/lib/chat2.pl @@ -275,7 +275,9 @@ sub print { ## public if ($_[0] =~ /$nextpat/) { *S = shift; } - print S @_; + + local $out = join $, , @_; + syswrite(S, $out, length $out); if( $chat'debug ){ print STDERR "printed:"; print STDERR @_; diff --git a/gnu/usr.bin/perl/lib/fields.pm b/gnu/usr.bin/perl/lib/fields.pm new file mode 100644 index 00000000000..54602a6b882 --- /dev/null +++ b/gnu/usr.bin/perl/lib/fields.pm @@ -0,0 +1,156 @@ +package fields; + +=head1 NAME + +fields - compile-time class fields + +=head1 SYNOPSIS + + { + package Foo; + use fields qw(foo bar _private); + } + ... + my Foo $var = new Foo; + $var->{foo} = 42; + + # This will generate a compile-time error. + $var->{zap} = 42; + + { + package Bar; + use base 'Foo'; + use fields 'bar'; # hides Foo->{bar} + use fields qw(baz _private); # not shared with Foo + } + +=head1 DESCRIPTION + +The C<fields> pragma enables compile-time verified class fields. It +does so by updating the %FIELDS hash in the calling package. + +If a typed lexical variable holding a reference is used to access a +hash element and the %FIELDS hash of the given type exists, then the +operation is turned into an array access at compile time. The %FIELDS +hash maps from hash element names to the array indices. If the hash +element is not present in the %FIELDS hash, then a compile-time error +is signaled. + +Since the %FIELDS hash is used at compile-time, it must be set up at +compile-time too. This is made easier with the help of the 'fields' +and the 'base' pragma modules. The 'base' pragma will copy fields +from base classes and the 'fields' pragma adds new fields. Field +names that start with an underscore character are made private to a +class and are not visible to subclasses. Inherited fields can be +overridden but will generate a warning if used together with the C<-w> +switch. + +The effect of all this is that you can have objects with named fields +which are as compact and as fast arrays to access. This only works +as long as the objects are accessed through properly typed variables. +For untyped access to work you have to make sure that a reference to +the proper %FIELDS hash is assigned to the 0'th element of the array +object (so that the objects can be treated like an pseudo-hash). A +constructor like this does the job: + + sub new + { + my $class = shift; + no strict 'refs'; + my $self = bless [\%{"$class\::FIELDS"}], $class; + $self; + } + + +=head1 SEE ALSO + +L<base>, +L<perlref/Pseudo-hashes: Using an array as a hash> + +=cut + +use strict; +no strict 'refs'; +use vars qw(%attr $VERSION); + +$VERSION = "0.02"; + +# some constants +sub _PUBLIC () { 1 } +sub _PRIVATE () { 2 } +sub _INHERITED () { 4 } + +# The %attr hash holds the attributes of the currently assigned fields +# per class. The hash is indexed by class names and the hash value is +# an array reference. The array is indexed with the field numbers +# (minus one) and the values are integer bit masks (or undef). The +# size of the array also indicate the next field index too assign for +# additional fields in this class. + +sub import { + my $class = shift; + my $package = caller(0); + my $fields = \%{"$package\::FIELDS"}; + my $fattr = ($attr{$package} ||= []); + + foreach my $f (@_) { + if (my $fno = $fields->{$f}) { + require Carp; + if ($fattr->[$fno-1] & _INHERITED) { + Carp::carp("Hides field '$f' in base class") if $^W; + } else { + Carp::croak("Field name '$f' already in use"); + } + } + $fields->{$f} = @$fattr + 1; + push(@$fattr, ($f =~ /^_/) ? _PRIVATE : _PUBLIC); + } +} + +sub inherit # called by base.pm +{ + my($derived, $base) = @_; + + if (defined %{"$derived\::FIELDS"}) { + require Carp; + Carp::croak("Inherited %FIELDS can't override existing %FIELDS"); + } else { + my $base_fields = \%{"$base\::FIELDS"}; + my $derived_fields = \%{"$derived\::FIELDS"}; + + $attr{$derived}[@{$attr{$base}}-1] = undef; + while (my($k,$v) = each %$base_fields) { + next if $attr{$base}[$v-1] & _PRIVATE; + $attr{$derived}[$v-1] = _INHERITED; + $derived_fields->{$k} = $v; + } + } + +} + +sub _dump # sometimes useful for debugging +{ + for my $pkg (sort keys %attr) { + print "\n$pkg"; + if (defined @{"$pkg\::ISA"}) { + print " (", join(", ", @{"$pkg\::ISA"}), ")"; + } + print "\n"; + my $fields = \%{"$pkg\::FIELDS"}; + for my $f (sort {$fields->{$a} <=> $fields->{$b}} keys %$fields) { + my $no = $fields->{$f}; + print " $no: $f"; + my $fattr = $attr{$pkg}[$no-1]; + if (defined $fattr) { + my @a; + push(@a, "public") if $fattr & _PUBLIC; + push(@a, "private") if $fattr & _PRIVATE; + push(@a, "inherited") if $fattr & _INHERITED; + print "\t(", join(", ", @a), ")"; + } + print "\n"; + } + } +} + +1; diff --git a/gnu/usr.bin/perl/lib/integer.pm b/gnu/usr.bin/perl/lib/integer.pm index a88ce6a77c8..894931896fc 100644 --- a/gnu/usr.bin/perl/lib/integer.pm +++ b/gnu/usr.bin/perl/lib/integer.pm @@ -12,11 +12,22 @@ integer - Perl pragma to compute arithmetic in integer instead of double =head1 DESCRIPTION -This tells the compiler that it's okay to use integer operations +This tells the compiler to use integer operations from here to the end of the enclosing BLOCK. On many machines, this doesn't matter a great deal for most computations, but on those without floating point hardware, it can make a big difference. +Note that this affects the operations, not the numbers. If you run this +code + + use integer; + $x = 1.5; + $y = $x + 1; + $z = -1.5; + +you'll be left with C<$x == 1.5>, C<$y == 2> and C<$z == -1>. The $z +case happens because unary C<-> counts as an operation. + See L<perlmod/Pragmatic Modules>. =cut |