summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Ing-Simmons <nik@tiuk.ti.com>1998-07-02 18:36:59 +0000
committerNick Ing-Simmons <nik@tiuk.ti.com>1998-07-02 18:36:59 +0000
commitfc657161c79c5094cda4af53f8d9a4421dfe9959 (patch)
tree81d1503cdb838e943eb250357f5a52dea20b60c9
parent4464c260eb4d110a8ad689e646a8f3f337061a11 (diff)
parenteacd03c1d97275b2758afcdbb834e028f5a3b9d8 (diff)
downloadperl-fc657161c79c5094cda4af53f8d9a4421dfe9959.tar.gz
Integrate mainline, just to keep up.
p4raw-id: //depot/ansiperl@1275
-rw-r--r--MANIFEST2
-rw-r--r--lib/ExtUtils/MM_Unix.pm84
-rw-r--r--lib/ExtUtils/MakeMaker.pm17
-rw-r--r--lib/Math/Trig.pm250
-rw-r--r--lib/Math/Trig/Radial.pm193
-rw-r--r--lib/base.pm35
-rw-r--r--lib/fields.pm131
-rw-r--r--mg.c48
-rw-r--r--pod/perldiag.pod12
-rw-r--r--pod/perltrap.pod27
-rw-r--r--pp_hot.c32
-rw-r--r--scope.c2
-rw-r--r--scope.h35
-rwxr-xr-xt/lib/fields.t110
-rwxr-xr-xt/lib/trig.t101
-rwxr-xr-xt/op/array.t32
-rw-r--r--toke.c4
-rw-r--r--utils/perldoc.PL6
-rw-r--r--win32/config.bc4
-rw-r--r--win32/config.gc4
-rw-r--r--win32/config.vc4
-rw-r--r--win32/include/dirent.h12
-rw-r--r--win32/makedef.pl6
-rw-r--r--win32/win32.c12
-rw-r--r--win32/win32iop.h7
25 files changed, 796 insertions, 374 deletions
diff --git a/MANIFEST b/MANIFEST
index f4108deb6e..6dd7c5941b 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -481,7 +481,6 @@ lib/Math/BigFloat.pm An arbitrary precision floating-point arithmetic package
lib/Math/BigInt.pm An arbitrary precision integer arithmetic package
lib/Math/Complex.pm A Complex package
lib/Math/Trig.pm A simple interface to complex trigonometry
-lib/Math/Trig/Radial.pm Spherical and cylindrical trigonometry
lib/Net/Ping.pm Hello, anybody home?
lib/Net/hostent.pm By-name interface to Perl's builtin gethost*
lib/Net/netent.pm By-name interface to Perl's builtin getnet*
@@ -796,6 +795,7 @@ t/lib/dosglob.t See if File::DosGlob works
t/lib/english.t See if English works
t/lib/env.t See if Env works
t/lib/errno.t See if Errno works
+t/lib/fields.t See if base/fields works
t/lib/filecache.t See if FileCache works
t/lib/filecopy.t See if File::Copy works
t/lib/filefind.t See if File::Find works
diff --git a/lib/ExtUtils/MM_Unix.pm b/lib/ExtUtils/MM_Unix.pm
index daa477cd10..6739743da0 100644
--- a/lib/ExtUtils/MM_Unix.pm
+++ b/lib/ExtUtils/MM_Unix.pm
@@ -5,7 +5,7 @@ use Config;
use File::Basename qw(basename dirname fileparse);
use DirHandle;
use strict;
-use vars qw($VERSION $Is_Mac $Is_OS2 $Is_VMS $Is_Win32 $Is_Dos
+use vars qw($VERSION $Is_Mac $Is_OS2 $Is_VMS $Is_Win32 $Is_Dos $Is_PERL_OBJECT
$Verbose %pm %static $Xsubpp_Version);
$VERSION = substr q$Revision: 1.126 $, 10;
@@ -19,6 +19,8 @@ $Is_Mac = $^O eq 'MacOS';
$Is_Win32 = $^O eq 'MSWin32';
$Is_Dos = $^O eq 'dos';
+$Is_PERL_OBJECT = 1 if $Config{'ccflags'} =~ /-DPERL_OBJECT/;
+
if ($Is_VMS = $^O eq 'VMS') {
require VMS::Filespec;
import VMS::Filespec qw( &vmsify );
@@ -212,6 +214,7 @@ sub ExtUtils::MM_Unix::pm_to_blib ;
sub ExtUtils::MM_Unix::post_constants ;
sub ExtUtils::MM_Unix::post_initialize ;
sub ExtUtils::MM_Unix::postamble ;
+sub ExtUtils::MM_Unix::ppd ;
sub ExtUtils::MM_Unix::prefixify ;
sub ExtUtils::MM_Unix::processPL ;
sub ExtUtils::MM_Unix::realclean ;
@@ -371,7 +374,7 @@ sub cflags {
$self->{uc $_} ||= $cflags{$_}
}
- if ($self->{CAPI}) {
+ if ($self->{CAPI} && $Is_PERL_OBJECT == 1) {
$self->{CCFLAGS} =~ s/-DPERL_OBJECT(\s|$)//;
$self->{CCFLAGS} .= '-DPERL_CAPI';
if ($Is_Win32 && $Config{'cc'} =~ /^cl.exe/i) {
@@ -2596,6 +2599,32 @@ sub parse_version {
return $result;
}
+=item parse_abstract
+
+parse a file and return what you think is the ABSTRACT
+
+=cut
+
+sub parse_abstract {
+ my($self,$parsefile) = @_;
+ my $result;
+ local *FH;
+ local $/ = "\n";
+ open(FH,$parsefile) or die "Could not open '$parsefile': $!";
+ my $inpod = 0;
+ my $package = $self->{DISTNAME};
+ $package =~ s/-/::/;
+ while (<FH>) {
+ $inpod = /^=(?!cut)/ ? 1 : /^=cut/ ? 0 : $inpod;
+ next if !$inpod;
+ chop;
+ next unless /^($package\s-\s)(.*)/;
+ $result = $2;
+ last;
+ }
+ close FH;
+ return $result;
+}
=item pasthru (o)
@@ -2695,6 +2724,57 @@ $(OBJECT) : $(PERL_HDRS)
join "\n", @m;
}
+=item ppd
+
+Defines target that creates a PPD (Perl Package Description) file
+for a binary distribution.
+
+=cut
+
+sub ppd {
+ my($self) = @_;
+ my(@m);
+ if ($self->{ABSTRACT_FROM}){
+ $self->{ABSTRACT} = $self->parse_abstract($self->{ABSTRACT_FROM}) or
+ Carp::carp "WARNING: Setting ABSTRACT via file '$self->{ABSTRACT_FROM}' failed\n";
+ }
+ my ($pack_ver) = join ",", (split (/\./, $self->{VERSION}), (0) x 4) [0 .. 3];
+ push(@m, "# Creates a PPD (Perl Package Description) for a binary distribution.\n");
+ push(@m, "ppd:\n");
+ push(@m, "\t\@\$(PERL) -e \"print qq{<SOFTPKG NAME=\\\"$self->{DISTNAME}\\\" VERSION=\\\"$pack_ver\\\">\\n}");
+ push(@m, ". qq{\\t<TITLE>$self->{DISTNAME}</TITLE>\\n}");
+ my $abstract = $self->{ABSTRACT};
+ $abstract =~ s/</&lt;/g;
+ $abstract =~ s/>/&gt;/g;
+ push(@m, ". qq{\\t<ABSTRACT>$abstract</ABSTRACT>\\n}");
+ my ($author) = $self->{AUTHOR};
+ $author =~ s/@/\\@/g;
+ push(@m, ". qq{\\t<AUTHOR>$author</AUTHOR>\\n}");
+ push(@m, ". qq{\\t<IMPLEMENTATION>\\n}");
+ my ($prereq);
+ foreach $prereq (sort keys %{$self->{PREREQ_PM}}) {
+ my $pre_req = $prereq;
+ $pre_req =~ s/::/-/g;
+ push(@m, ". qq{\\t\\t<DEPENDENCY NAME=\\\"$pre_req\\\" />\\n}");
+ }
+ push(@m, ". qq{\\t\\t<OS NAME=\\\"\$(OSNAME)\\\" />\\n}");
+ my ($bin_location) = $self->{BINARY_LOCATION};
+ $bin_location =~ s/\\/\\\\/g;
+ if ($self->{PPM_INSTALL_SCRIPT}) {
+ if ($self->{PPM_INSTALL_EXEC}) {
+ push(@m, " . qq{\\t\\t<INSTALL EXEC=\\\"$self->{PPM_INSTALL_EXEC}\\\">$self->{PPM_INSTALL_SCRIPT}</INSTALL>\\n}");
+ }
+ else {
+ push(@m, " . qq{\\t\\t<INSTALL>$self->{PPM_INSTALL_SCRIPT}</INSTALL>\\n}");
+ }
+ }
+ push(@m, ". qq{\\t\\t<CODEBASE HREF=\\\"$bin_location\\\" />\\n}");
+ push(@m, ". qq{\\t</IMPLEMENTATION>\\n}");
+ push(@m, ". qq{</SOFTPKG>\\n}\" > $self->{DISTNAME}.ppd");
+
+ join("", @m);
+}
+
=item perm_rw (o)
Returns the attribute C<PERM_RW> or the string C<644>.
diff --git a/lib/ExtUtils/MakeMaker.pm b/lib/ExtUtils/MakeMaker.pm
index eac32ace23..375a699c49 100644
--- a/lib/ExtUtils/MakeMaker.pm
+++ b/lib/ExtUtils/MakeMaker.pm
@@ -73,6 +73,10 @@ $Is_OS2 = $^O eq 'os2';
$Is_Mac = $^O eq 'MacOS';
$Is_Win32 = $^O eq 'MSWin32';
+# This is for module authors to query, so they can enable 'CAPI' => 'TRUE'
+# in their Makefile.pl
+$CAPI_support = 1;
+
require ExtUtils::MM_Unix;
if ($Is_VMS) {
@@ -235,7 +239,7 @@ sub full_setup {
@Attrib_help = qw/
- CAPI
+ AUTHOR ABSTRACT ABSTRACT_FROM BINARY_LOCATION LICENSE_HREF CAPI
C CCFLAGS CONFIG CONFIGURE DEFINE DIR DISTNAME DL_FUNCS DL_VARS
EXE_FILES EXCLUDE_EXT INCLUDE_EXT NO_VC FIRST_MAKEFILE FULLPERL H
INC INSTALLARCHLIB INSTALLBIN INSTALLDIRS INSTALLMAN1DIR
@@ -248,7 +252,7 @@ sub full_setup {
PL_FILES PM PMLIBDIRS PREFIX
PREREQ_PM SKIP TYPEMAPS VERSION VERSION_FROM XS XSOPT XSPROTOARG
XS_VERSION clean depend dist dynamic_lib linkext macro realclean
- tool_autosplit
+ tool_autosplit PPM_INSTALL_SCRIPT PPM_INSTALL_EXEC
IMPORTS
@@ -280,7 +284,7 @@ sub full_setup {
c_o xs_c xs_o top_targets linkext dlsyms dynamic dynamic_bs
dynamic_lib static static_lib manifypods processPL installbin subdirs
clean realclean dist_basics dist_core dist_dir dist_test dist_ci
- install force perldepend makefile staticmake test
+ install force perldepend makefile staticmake test ppd
); # loses section ordering
@@ -309,7 +313,7 @@ sub full_setup {
@Get_from_Config =
qw(
ar cc cccdlflags ccdlflags dlext dlsrc ld lddlflags ldflags libc
- lib_ext obj_ext ranlib sitelibexp sitearchexp so exe_ext
+ lib_ext obj_ext osname osvers ranlib sitelibexp sitearchexp so exe_ext
);
my $item;
@@ -383,8 +387,9 @@ sub ExtUtils::MakeMaker::new {
eval $eval;
if ($@){
warn "Warning: prerequisite $prereq $self->{PREREQ_PM}->{$prereq} not found";
- } else {
- delete $self->{PREREQ_PM}{$prereq};
+# Why is/was this 'delete' here? We need PREREQ_PM later to make PPDs.
+# } else {
+# delete $self->{PREREQ_PM}{$prereq};
}
}
# if (@unsatisfied){
diff --git a/lib/Math/Trig.pm b/lib/Math/Trig.pm
index a1cbb07234..7192d76fe9 100644
--- a/lib/Math/Trig.pm
+++ b/lib/Math/Trig.pm
@@ -1,6 +1,6 @@
#
# Trigonometric functions, mostly inherited from Math::Complex.
-# -- Jarkko Hietaniemi, April 1997
+# -- Jarkko Hietaniemi, since April 1997
# -- Raphael Manfredi, September 1996 (indirectly: because of Math::Complex)
#
@@ -13,7 +13,7 @@ use Math::Complex qw(:trig);
use vars qw($VERSION $PACKAGE
@ISA
- @EXPORT);
+ @EXPORT @EXPORT_OK %EXPORT_TAGS);
@ISA = qw(Exporter);
@@ -26,13 +26,25 @@ my @angcnv = qw(rad2deg rad2grad
@EXPORT = (@{$Math::Complex::EXPORT_TAGS{'trig'}},
@angcnv);
-use constant pi2 => 2 * pi;
-use constant DR => pi2/360;
-use constant RD => 360/pi2;
-use constant DG => 400/360;
-use constant GD => 360/400;
-use constant RG => 400/pi2;
-use constant GR => pi2/400;
+my @rdlcnv = qw(cartesian_to_cylindrical
+ cartesian_to_spherical
+ cylindrical_to_cartesian
+ cylindrical_to_spherical
+ spherical_to_cartesian
+ spherical_to_cylindrical);
+
+@EXPORT_OK = (@rdlcnv, 'great_circle_distance');
+
+%EXPORT_TAGS = ('radial' => [ @rdlcnv ]);
+
+use constant pi2 => 2 * pi;
+use constant pip2 => pi / 2;
+use constant DR => pi2/360;
+use constant RD => 360/pi2;
+use constant DG => 400/360;
+use constant GD => 360/400;
+use constant RG => 400/pi2;
+use constant GR => pi2/400;
#
# Truncating remainder.
@@ -59,6 +71,61 @@ sub rad2grad ($) { remt(RG * $_[0], 400) }
sub grad2rad ($) { remt(GR * $_[0], pi2) }
+sub cartesian_to_spherical {
+ my ( $x, $y, $z ) = @_;
+
+ my $rho = sqrt( $x * $x + $y * $y + $z * $z );
+
+ return ( $rho,
+ atan2( $y, $x ),
+ $rho ? acos( $z / $rho ) : 0 );
+}
+
+sub spherical_to_cartesian {
+ my ( $rho, $theta, $phi ) = @_;
+
+ return ( $rho * cos( $theta ) * sin( $phi ),
+ $rho * sin( $theta ) * sin( $phi ),
+ $rho * cos( $phi ) );
+}
+
+sub spherical_to_cylindrical {
+ my ( $x, $y, $z ) = spherical_to_cartesian( @_ );
+
+ return ( sqrt( $x * $x + $y * $y ), $_[1], $z );
+}
+
+sub cartesian_to_cylindrical {
+ my ( $x, $y, $z ) = @_;
+
+ return ( sqrt( $x * $x + $y * $y ), atan2( $y, $x ), $z );
+}
+
+sub cylindrical_to_cartesian {
+ my ( $rho, $theta, $z ) = @_;
+
+ return ( $rho * cos( $theta ), $rho * sin( $theta ), $z );
+}
+
+sub cylindrical_to_spherical {
+ return ( cartesian_to_spherical( cylindrical_to_cartesian( @_ ) ) );
+}
+
+sub great_circle_distance {
+ my ( $theta0, $phi0, $theta1, $phi1, $rho ) = @_;
+
+ $rho = 1 unless defined $rho; # Default to the unit sphere.
+
+ my $lat0 = pip2 - $phi0;
+ my $lat1 = pip2 - $phi1;
+
+ return $rho *
+ acos(cos( $lat0 ) * cos( $lat1 ) * cos( $theta0 - $theta1 ) +
+ sin( $lat0 ) * sin( $lat1 ) );
+}
+
+=pod
+
=head1 NAME
Math::Trig - trigonometric functions
@@ -86,68 +153,72 @@ conversions.
The tangent
- tan
+=over 4
+
+=item B<tan>
+
+=back
The cofunctions of the sine, cosine, and tangent (cosec/csc and cotan/cot
are aliases)
- csc cosec sec cot cotan
+B<csc>, B<cosec>, B<sec>, B<sec>, B<cot>, B<cotan>
The arcus (also known as the inverse) functions of the sine, cosine,
and tangent
- asin acos atan
+B<asin>, B<acos>, B<atan>
The principal value of the arc tangent of y/x
- atan2(y, x)
+B<atan2>(y, x)
The arcus cofunctions of the sine, cosine, and tangent (acosec/acsc
and acotan/acot are aliases)
- acsc acosec asec acot acotan
+B<acsc>, B<acosec>, B<asec>, B<acot>, B<acotan>
The hyperbolic sine, cosine, and tangent
- sinh cosh tanh
+B<sinh>, B<cosh>, B<tanh>
The cofunctions of the hyperbolic sine, cosine, and tangent (cosech/csch
and cotanh/coth are aliases)
- csch cosech sech coth cotanh
+B<csch>, B<cosech>, B<sech>, B<coth>, B<cotanh>
The arcus (also known as the inverse) functions of the hyperbolic
sine, cosine, and tangent
- asinh acosh atanh
+B<asinh>, B<acosh>, B<atanh>
The arcus cofunctions of the hyperbolic sine, cosine, and tangent
(acsch/acosech and acoth/acotanh are aliases)
- acsch acosech asech acoth acotanh
+B<acsch>, B<acosech>, B<asech>, B<acoth>, B<acotanh>
The trigonometric constant B<pi> is also defined.
- $pi2 = 2 * pi;
+$pi2 = 2 * B<pi>;
=head2 ERRORS DUE TO DIVISION BY ZERO
The following functions
- tan
- sec
- csc
- cot
- asec
+ acoth
acsc
- tanh
- sech
- csch
- coth
- atanh
- asech
acsch
- acoth
+ asec
+ asech
+ atanh
+ cot
+ coth
+ csc
+ csch
+ sec
+ sech
+ tan
+ tanh
cannot be computed for all arguments because that would mean dividing
by zero or taking logarithm of zero. These situations cause fatal
@@ -196,7 +267,7 @@ should produce something like this (take or leave few last decimals):
That is, a complex number with the real part of approximately C<1.571>
and the imaginary part of approximately C<-1.317>.
-=head1 ANGLE CONVERSIONS
+=head1 PLANE ANGLE CONVERSIONS
(Plane, 2-dimensional) angles may be converted with the following functions.
@@ -211,6 +282,121 @@ and the imaginary part of approximately C<-1.317>.
The full circle is 2 I<pi> radians or I<360> degrees or I<400> gradians.
+=head1 RADIAL COORDINATE CONVERSIONS
+
+B<Radial coordinate systems> are the B<spherical> and the B<cylindrical>
+systems, explained shortly in more detail.
+
+You can import radial coordinate conversion functions by using the
+C<:radial> tag:
+
+ use Math::Trig ':radial';
+
+ ($rho, $theta, $z) = cartesian_to_cylindrical($x, $y, $z);
+ ($rho, $theta, $phi) = cartesian_to_spherical($x, $y, $z);
+ ($x, $y, $z) = cylindrical_to_cartesian($rho, $theta, $z);
+ ($rho_s, $theta, $phi) = cylindrical_to_spherical($rho_c, $theta, $z);
+ ($x, $y, $z) = spherical_to_cartesian($rho, $theta, $phi);
+ ($rho_c, $theta, $z) = spherical_to_cylindrical($rho_s, $theta, $phi);
+
+B<All angles are in radians>.
+
+=head2 COORDINATE SYSTEMS
+
+B<Cartesian> coordinates are the usual rectangular I<(x, y,
+z)>-coordinates.
+
+Spherical coordinates, I<(rho, theta, pi)>, are three-dimensional
+coordinates which define a point in three-dimensional space. They are
+based on a sphere surface. The radius of the sphere is B<rho>, also
+known as the I<radial> coordinate. The angle in the I<xy>-plane
+(around the I<z>-axis) is B<theta>, also known as the I<azimuthal>
+coordinate. The angle from the I<z>-axis is B<phi>, also known as the
+I<polar> coordinate. The `North Pole' is therefore I<0, 0, rho>, and
+the `Bay of Guinea' (think of the missing big chunk of Africa) I<0,
+pi/2, rho>.
+
+B<Beware>: some texts define I<theta> and I<phi> the other way round,
+some texts define the I<phi> to start from the horizontal plane, some
+texts use I<r> in place of I<rho>.
+
+Cylindrical coordinates, I<(rho, theta, z)>, are three-dimensional
+coordinates which define a point in three-dimensional space. They are
+based on a cylinder surface. The radius of the cylinder is B<rho>,
+also known as the I<radial> coordinate. The angle in the I<xy>-plane
+(around the I<z>-axis) is B<theta>, also known as the I<azimuthal>
+coordinate. The third coordinate is the I<z>, pointing up from the
+B<theta>-plane.
+
+=head2 3-D ANGLE CONVERSIONS
+
+Conversions to and from spherical and cylindrical coordinates are
+available. Please notice that the conversions are not necessarily
+reversible because of the equalities like I<pi> angles being equal to
+I<-pi> angles.
+
+=over 4
+
+=item cartesian_to_cylindrical
+
+ ($rho, $theta, $z) = cartesian_to_cylindrical($x, $y, $z);
+
+=item cartesian_to_spherical
+
+ ($rho, $theta, $phi) = cartesian_to_spherical($x, $y, $z);
+
+=item cylindrical_to_cartesian
+
+ ($x, $y, $z) = cylindrical_to_cartesian($rho, $theta, $z);
+
+=item cylindrical_to_spherical
+
+ ($rho_s, $theta, $phi) = cylindrical_to_spherical($rho_c, $theta, $z);
+
+Notice that when C<$z> is not 0 C<$rho_s> is not equal to C<$rho_c>.
+
+=item spherical_to_cartesian
+
+ ($x, $y, $z) = spherical_to_cartesian($rho, $theta, $phi);
+
+=item spherical_to_cylindrical
+
+ ($rho_c, $theta, $z) = spherical_to_cylindrical($rho_s, $theta, $phi);
+
+Notice that when C<$z> is not 0 C<$rho_c> is not equal to C<$rho_s>.
+
+=back
+
+=head1 GREAT CIRCLE DISTANCES
+
+You can compute spherical distances, called B<great circle distances>,
+by importing the C<great_circle_distance> function:
+
+ use Math::Trig 'great_circle_distance'
+
+ $distance = great_circle_distance($theta0, $phi0, $theta1, $phi, [, $rho]);
+
+The I<great circle distance> is the shortest distance between two
+points on a sphere. The distance is in C<$rho> units. The C<$rho> is
+optional, it defaults to 1 (the unit sphere), therefore the distance
+defaults to radians.
+
+=head EXAMPLES
+
+To calculate the distance between London (51.3N 0.5W) and Tokyo (35.7N
+139.8E) in kilometers:
+
+ use Math::Trig qw(great_circle_distance deg2rad);
+
+ # Notice the 90 - latitude: phi zero is at the North Pole.
+ @L = (deg2rad(-0.5), deg2rad(90 - 51.3));
+ @T = (deg2rad(139.8),deg2rad(90 - 35.7));
+
+ $km = great_circle_distance(@L, @T, 6378);
+
+The answer may be off by up to 0.3% because of the irregular (slightly
+aspherical) form of the Earth.
+
=head1 BUGS
Saying C<use Math::Trig;> exports many mathematical routines in the
diff --git a/lib/Math/Trig/Radial.pm b/lib/Math/Trig/Radial.pm
deleted file mode 100644
index 0001cb7323..0000000000
--- a/lib/Math/Trig/Radial.pm
+++ /dev/null
@@ -1,193 +0,0 @@
-package Math::Trig::Radial;
-
-use strict;
-use vars qw(@ISA @EXPORT);
-@ISA = qw(Exporter);
-
-@EXPORT =
- qw(
- cartesian_to_cylindrical
- cartesian_to_spherical
- cylindrical_to_cartesian
- cylindrical_to_spherical
- spherical_to_cartesian
- spherical_to_cylindrical
- great_circle_distance
- );
-
-use Math::Trig;
-
-sub pip2 { pi/2 }
-
-=pod
-
-=head1 NAME
-
-Math::Trig::Radial - spherical and cylindrical trigonometry
-
-=head1 SYNOPSIS
-
- use Math::Trig::Radial;
-
- ($rho, $theta, $z) = cartesian_to_cylindrical($x, $y, $z);
- ($rho, $theta, $phi) = cartesian_to_spherical($x, $y, $z);
- ($x, $y, $z) = cylindrical_to_cartesian($rho, $theta, $z);
- ($rho_s, $theta, $phi) = cylindrical_to_spherical($rho_c, $theta, $z);
- ($x, $y, $z) = spherical_to_cartesian($rho, $theta, $phi);
- ($rho_c, $theta, $z) = spherical_to_cylindrical($rho_s, $theta, $phi);
-
-=head1 DESCRIPTION
-
-This module contains a few basic spherical and cylindrical
-trigonometric formulas. B<All angles are in radians>, if needed
-use C<Math::Trig> angle unit conversions.
-
-=head2 COORDINATE SYSTEMS
-
-B<Cartesian> coordinates are the usual rectangular I<xyz>-coordinates.
-
-Spherical coordinates are three-dimensional coordinates which define a
-point in three-dimensional space. They are based on a sphere surface.
-The radius of the sphere is B<rho>, also known as the I<radial>
-coordinate. The angle in the I<xy>-plane (around the I<z>-axis) is
-B<theta>, also known as the I<azimuthal> coordinate. The angle from
-the I<z>-axis is B<phi>, also known as the I<polar> coordinate. The
-`North Pole' is therefore I<0, 0, rho>, and the `Bay of Guinea' (think
-Africa) I<0, pi/2, rho>.
-
-Cylindrical coordinates are three-dimensional coordinates which define
-a point in three-dimensional space. They are based on a cylinder
-surface. The radius of the cylinder is B<rho>, also known as the
-I<radial> coordinate. The angle in the I<xy>-plane (around the
-I<z>-axis) is B<theta>, also known as the I<azimuthal> coordinate.
-The third coordinate is the I<z>.
-
-=head2 CONVERSIONS
-
-Conversions to and from spherical and cylindrical coordinates are
-available. Please notice that the conversions are not necessarily
-reversible because of the equalities like I<pi> angles equals I<-pi>
-angles.
-
-=over 4
-
-=item cartesian_to_cylindrical
-
- ($rho, $theta, $z) = cartesian_to_cylindrical($x, $y, $z);
-
-=item cartesian_to_spherical
-
- ($rho, $theta, $phi) = cartesian_to_spherical($x, $y, $z);
-
-=item cylindrical_to_cartesian
-
- ($x, $y, $z) = cylindrical_to_cartesian($rho, $theta, $z);
-
-=item cylindrical_to_spherical
-
- ($rho_s, $theta, $phi) = cylindrical_to_spherical($rho_c, $theta, $z);
-
-Notice that when C<$z> is not 0 C<$rho_s> is not equal to C<$rho_c>.
-
-=item spherical_to_cartesian
-
- ($x, $y, $z) = spherical_to_cartesian($rho, $theta, $phi);
-
-=item spherical_to_cylindrical
-
- ($rho_c, $theta, $z) = spherical_to_cylindrical($rho_s, $theta, $phi);
-
-Notice that when C<$z> is not 0 C<$rho_c> is not equal to C<$rho_s>.
-
-=back
-
-=head2 GREAT CIRCLE DISTANCE
-
- $distance = great_circle_distance($x0, $y0, $z0, $x1, $y1, $z1 [, $rho]);
-
-The I<great circle distance> is the shortest distance between two
-points on a sphere. The distance is in C<$rho> units. The C<$rho> is
-optional, it defaults to 1 (the unit sphere), therefore the distance
-defaults to radians. The coordinates C<$x0> ... C<$z1> are in
-cartesian coordinates.
-
-=head EXAMPLES
-
-To calculate the distance between London (51.3N 0.5W) and Tokyo (35.7N
-139.8E) in kilometers:
-
- use Math::Trig::Radial;
- use Math::Trig;
-
- my @L = spherical_to_cartesian(1, map { deg2rad $_ } qw(51.3 -0.5));
- my @T = spherical_to_cartesian(1, map { deg2rad $_ } qw(35.7 139.8));
-
- $km = great_circle_distance(@L, @T, 6378);
-
-The answer may be off by up to 0.3% because of the irregular (slightly
-aspherical) form of the Earth.
-
-=head2 AUTHOR
-
-Jarkko Hietaniemi F<E<lt>jhi@iki.fiE<gt>>
-
-=cut
-
-sub cartesian_to_spherical {
- my ( $x, $y, $z ) = @_;
-
- my $rho = sqrt( $x * $x + $y * $y + $z * $z );
-
- return ( $rho,
- atan2( $y, $x ),
- $rho ? acos( $z / $rho ) : 0 );
-}
-
-sub spherical_to_cartesian {
- my ( $rho, $theta, $phi ) = @_;
-
- return ( $rho * cos( $theta ) * sin( $phi ),
- $rho * sin( $theta ) * sin( $phi ),
- $rho * cos( $phi ) );
-}
-
-sub spherical_to_cylindrical {
- my ( $x, $y, $z ) = spherical_to_cartesian( @_ );
-
- return ( sqrt( $x * $x + $y * $y ), $_[1], $z );
-}
-
-sub cartesian_to_cylindrical {
- my ( $x, $y, $z ) = @_;
-
- return ( sqrt( $x * $x + $y * $y ), atan2( $y, $x ), $z );
-}
-
-sub cylindrical_to_cartesian {
- my ( $rho, $theta, $z ) = @_;
-
- return ( $rho * cos( $theta ), $rho * sin( $theta ), $z );
-}
-
-sub cylindrical_to_spherical {
- return ( cartesian_to_spherical( cylindrical_to_cartesian( @_ ) ) );
-}
-
-sub great_circle_distance {
- my ( $x0, $y0, $z0, $x1, $y1, $z1, $rho ) = @_;
-
- $rho = 1 unless defined $rho; # Default to the unit sphere.
-
- my ( $r0, $theta0, $phi0 ) = cartesian_to_spherical( $x0, $y0, $z0 );
- my ( $r1, $theta1, $phi1 ) = cartesian_to_spherical( $x1, $y1, $z1 );
-
- my $lat0 = pip2 - $phi0;
- my $lat1 = pip2 - $phi1;
-
- return $rho *
- acos(cos( $lat0 ) * cos( $lat1 ) * cos( $theta0 - $theta1 ) +
- sin( $lat0 ) * sin( $lat1 ) );
-}
-
-1;
-
diff --git a/lib/base.pm b/lib/base.pm
index 4c4fb8b86b..3500cbfb89 100644
--- a/lib/base.pm
+++ b/lib/base.pm
@@ -5,7 +5,6 @@ base - Establish IS-A relationship with base class at compile time
=head1 SYNOPSIS
package Baz;
-
use base qw(Foo Bar);
=head1 DESCRIPTION
@@ -18,11 +17,19 @@ Roughly similar in effect to
push @ISA, qw(Foo Bar);
}
+Will also initialize the %FIELDS hash if one of the base classes has
+it. Multiple inheritance of %FIELDS is not supported. The 'base'
+pragma will croak if multiple base classes has a %FIELDS hash. See
+L<fields> for a description of this feature.
+
+When strict 'vars' is in scope I<base> also let you assign to @ISA
+without having to declare @ISA with the 'vars' pragma first.
+
This module was introduced with Perl 5.004_04.
-=head1 BUGS
+=head1 SEE ALSO
-Needs proper documentation!
+L<fields>
=cut
@@ -30,6 +37,7 @@ package base;
sub import {
my $class = shift;
+ my $fields_base;
foreach my $base (@_) {
unless (defined %{"$base\::"}) {
@@ -44,9 +52,26 @@ sub import {
"which defines that package first.)");
}
}
+
+ # A simple test like (defined %{"$base\::FIELDS"}) will
+ # sometimes produce typo warnings because it would create
+ # the hash if it was not present before.
+ my $fglob;
+ if ($fglob = ${"$base\::"}{"FIELDS"} and *$fglob{HASH}) {
+ if ($fields_base) {
+ require Carp;
+ Carp::croak("Can't multiply inherit %FIELDS");
+ } else {
+ $fields_base = $base;
+ }
+ }
+ }
+ my $pkg = caller(0);
+ push @{"$pkg\::ISA"}, @_;
+ if ($fields_base) {
+ require fields;
+ fields::inherit($pkg, $fields_base);
}
-
- push @{caller(0) . '::ISA'}, @_;
}
1;
diff --git a/lib/fields.pm b/lib/fields.pm
index c2cf1d6a5d..2c75ff4e61 100644
--- a/lib/fields.pm
+++ b/lib/fields.pm
@@ -8,7 +8,7 @@ fields - compile-time class fields
{
package Foo;
- use fields qw(foo bar baz);
+ use fields qw(foo bar _private);
}
...
my Foo $var = new Foo;
@@ -17,25 +17,140 @@ fields - compile-time class fields
# 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.
+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 map 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 -w
+option.
+
+The effect of all this is that you can have objects with named fields
+which are as compact and as fast arrays too 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 AVHV). 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>,
+I<description of AVHVs>
=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;
+ my $package = caller(0);
my $fields = \%{"$package\::FIELDS"};
- my $i = $fields->{__MAX__};
+ my $fattr = ($attr{$package} ||= []);
+
foreach my $f (@_) {
- if (defined($fields->{$f})) {
+ if (my $fno = $fields->{$f}) {
require Carp;
- Carp::croak("Field name $f already in use");
+ 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} = ++$i;
+ $fields->{$f} = @$fattr + 1;
+ push(@$fattr, ($f =~ /^_/) ? _PRIVATE : _PUBLIC);
}
- $fields->{__MAX__} = $i;
+}
+
+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/mg.c b/mg.c
index def57c47b2..4f0616f6c9 100644
--- a/mg.c
+++ b/mg.c
@@ -899,55 +899,7 @@ magic_setsig(SV *sv, MAGIC *mg)
int
magic_setisa(SV *sv, MAGIC *mg)
{
- HV *stash;
- SV **svp;
- I32 fill;
- HV *basefields = Nullhv;
- GV **gvp;
- GV *gv;
- HE *he;
- static char *FIELDS = "FIELDS";
-
sub_generation++;
-
- if (mg->mg_type == 'i')
- return 0; /* Ignore lower-case version of the magic */
-
- stash = GvSTASH(mg->mg_obj);
- svp = AvARRAY((AV*)sv);
-
- /* NOTE: No support for tied ISA */
- for (fill = AvFILLp((AV*)sv); fill >= 0; fill--, svp++) {
- HV *basestash = gv_stashsv(*svp, FALSE);
-
- if (!basestash) {
- if (dowarn)
- warn("No such package \"%_\" in @ISA assignment", *svp);
- continue;
- }
- gvp = (GV**)hv_fetch(basestash, FIELDS, 6, FALSE);
- if (gvp && *gvp && GvHV(*gvp)) {
- if (basefields)
- croak("Can't multiply inherit %%FIELDS");
- basefields = GvHV(*gvp);
- }
- }
-
- if (!basefields)
- return 0;
-
- gv = (GV*)*hv_fetch(stash, FIELDS, 6, TRUE);
- if (!isGV(gv))
- gv_init(gv, stash, FIELDS, 6, TRUE);
- if (!GvHV(gv))
- GvHV(gv) = newHV();
- if (HvKEYS(GvHV(gv)))
- croak("Inherited %%FIELDS can't override existing %%FIELDS");
-
- hv_iterinit(GvHV(gv));
- while ((he = hv_iternext(basefields)))
- hv_store(GvHV(gv), HeKEY(he), HeKLEN(he), HeVAL(he), HeHASH(he));
-
return 0;
}
diff --git a/pod/perldiag.pod b/pod/perldiag.pod
index b58885609b..841be546a6 100644
--- a/pod/perldiag.pod
+++ b/pod/perldiag.pod
@@ -316,6 +316,11 @@ system malloc().
(P) One of the internal hash routines was passed a null HV pointer.
+=item Bad index while coercing array into hash
+
+(F) A field name of a typed variable was looked up in the %FIELDS
+hash, but the index found was not legal, i.e. less than 1.
+
=item Bad name after %s::
(F) You started to name a symbol by using a package prefix, and then didn't
@@ -1601,6 +1606,13 @@ your system.
(F) The argument to B<-I> must follow the B<-I> immediately with no
intervening space.
+=item No such field "%s" in variable %s of type %s
+
+(F) You tried to access a field of a typed variable where the type
+does not know about the field name. The field names are looked up in
+the %FIELDS hash in the type package at compile time. The %FIELDS hash
+is usually set up with the 'fields' pragma.
+
=item No such pipe open
(P) An error peculiar to VMS. The internal routine my_pclose() tried to
diff --git a/pod/perltrap.pod b/pod/perltrap.pod
index 4159777146..8a3e3bcdab 100644
--- a/pod/perltrap.pod
+++ b/pod/perltrap.pod
@@ -921,6 +921,10 @@ Probably a bug.
Perl4-to-Perl5 traps involving precedence order.
+Perl 4 has almost the same precedence rules as Perl 5 for the operators
+that they both have. Perl 4 however, seems to have had some
+inconsistencies that made the behavior differ from what was documented.
+
=over 5
=item * Precedence
@@ -996,13 +1000,34 @@ treats C<$::> as main C<package>
=item * Precedence
-concatenation precedence over filetest operator?
+perl4 had buggy precedence for the file test operators vis-a-vis
+the assignment operators. Thus, although the precedence table
+for perl4 leads one to believe C<-e $foo .= "q"> should parse as
+C<((-e $foo) .= "q")>, it actually parses as C<(-e ($foo .= "q"))>.
+In perl5, the precedence is as documented.
-e $foo .= "q"
# perl4 prints: no output
# perl5 prints: Can't modify -e in concatenation
+=item * Precedence
+
+In perl4, keys(), each() and values() were special high-precedence operators
+that operated on a single hash, but in perl5, they are regular named unary
+operators. As documented, named unary operators have lower precedence
+than the arithmetic and concatenation operators C<+ - .>, but the perl4
+variants of these operators actually bind tighter than C<+ - .>.
+Thus, for:
+
+ %foo = 1..10;
+ print keys %foo - 1
+
+ # perl4 prints: 4
+ # perl5 prints: Type of arg 1 to keys must be hash (not subtraction)
+
+The perl4 behavior was probably more useful, if less consistent.
+
=back
=head2 General Regular Expression Traps using s///, etc.
diff --git a/pp_hot.c b/pp_hot.c
index 8331bb36a9..bd8a74e81f 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -626,7 +626,6 @@ PP(pp_aassign)
hv_clear(hash);
while (relem < lastrelem) { /* gobble up all the rest */
- STRLEN len;
HE *didstore;
if (*relem)
sv = *(relem++);
@@ -645,14 +644,29 @@ PP(pp_aassign)
}
TAINT_NOT;
}
- if (relem == lastrelem && dowarn) {
- if (relem == firstrelem &&
- SvROK(*relem) &&
- ( SvTYPE(SvRV(*relem)) == SVt_PVAV ||
- SvTYPE(SvRV(*relem)) == SVt_PVHV ) )
- warn("Reference found where even-sized list expected");
- else
- warn("Odd number of elements in hash assignment");
+ if (relem == lastrelem) {
+ if (*relem) {
+ HE *didstore;
+ if (dowarn) {
+ if (relem == firstrelem &&
+ SvROK(*relem) &&
+ ( SvTYPE(SvRV(*relem)) == SVt_PVAV ||
+ SvTYPE(SvRV(*relem)) == SVt_PVHV ) )
+ warn("Reference found where even-sized list expected");
+ else
+ warn("Odd number of elements in hash assignment");
+ }
+ tmpstr = NEWSV(29,0);
+ didstore = hv_store_ent(hash,*relem,tmpstr,0);
+ if (magic) {
+ if (SvSMAGICAL(tmpstr))
+ mg_set(tmpstr);
+ if (!didstore)
+ SvREFCNT_dec(tmpstr);
+ }
+ TAINT_NOT;
+ }
+ relem++;
}
}
break;
diff --git a/scope.c b/scope.c
index c95ae54c20..985c650b3c 100644
--- a/scope.c
+++ b/scope.c
@@ -806,7 +806,7 @@ leave_scope(I32 base)
case SAVEt_OP:
op = (OP*)SSPOPPTR;
break;
- case SAVEt_NOHINTS:
+ case SAVEt_HINTS:
if (GvHV(hintgv)) {
SvREFCNT_dec((SV*)GvHV(hintgv));
GvHV(hintgv) = NULL;
diff --git a/scope.h b/scope.h
index 1f8fb44a81..3ac4a59d51 100644
--- a/scope.h
+++ b/scope.h
@@ -25,7 +25,7 @@
#define SAVEt_AELEM 24
#define SAVEt_HELEM 25
#define SAVEt_OP 26
-#define SAVEt_NOHINTS 27
+#define SAVEt_HINTS 27
#define SSCHECK(need) if (savestack_ix + need > savestack_max) savestack_grow()
#define SSPUSHINT(i) (savestack[savestack_ix++].any_i32 = (I32)(i))
@@ -89,21 +89,26 @@
save_destructor(SOFT_CAST(void(*)_((void*)))(FUNC_NAME_TO_PTR(f)), \
SOFT_CAST(void*)(p))
#endif
-#define SAVESTACK_POS() STMT_START { \
- SSCHECK(2); \
- SSPUSHINT(stack_sp - stack_base); \
- SSPUSHINT(SAVEt_STACK_POS); \
- } STMT_END
+
+#define SAVESTACK_POS() \
+ STMT_START { \
+ SSCHECK(2); \
+ SSPUSHINT(stack_sp - stack_base); \
+ SSPUSHINT(SAVEt_STACK_POS); \
+ } STMT_END
+
#define SAVEOP() save_op()
-#define SAVEHINTS() STMT_START { \
- if (hints & HINT_LOCALIZE_HH) \
- save_hints(); \
- else { \
- SSCHECK(2); \
- SSPUSHINT(hints); \
- SSPUSHINT(SAVEt_NOHINTS); \
- } \
- } STMT_END
+
+#define SAVEHINTS() \
+ STMT_START { \
+ if (hints & HINT_LOCALIZE_HH) \
+ save_hints(); \
+ else { \
+ SSCHECK(2); \
+ SSPUSHINT(hints); \
+ SSPUSHINT(SAVEt_HINTS); \
+ } \
+ } STMT_END
/* A jmpenv packages the state required to perform a proper non-local jump.
* Note that there is a start_env initialized when perl starts, and top_env
diff --git a/t/lib/fields.t b/t/lib/fields.t
new file mode 100755
index 0000000000..7fad5d78f2
--- /dev/null
+++ b/t/lib/fields.t
@@ -0,0 +1,110 @@
+#!./perl -w
+
+use strict;
+use vars qw($DEBUG);
+
+my $w;
+
+BEGIN {
+ $SIG{__WARN__} = sub {
+ if ($_[0] =~ /^Hides field 'b1' in base class/) {
+ $w++;
+ return;
+ }
+ print $_[0];
+ };
+}
+
+package B1;
+use fields qw(b1 b2 b3);
+
+package B2;
+use fields '_b1';
+use fields qw(b1 _b2 b2);
+
+sub new { bless [], shift }
+
+package D1;
+use base 'B1';
+use fields qw(d1 d2 d3);
+
+package D2;
+use base 'B1';
+use fields qw(_d1 _d2);
+use fields qw(d1 d2);
+
+package D3;
+use base 'B2';
+use fields qw(b1 d1 _b1 _d1); # hide b1
+
+package D4;
+use base 'D3';
+use fields qw(_d3 d3);
+
+package M;
+sub m {}
+
+package D5;
+use base qw(M B2);
+
+package Foo::Bar;
+use base 'B1';
+
+package Foo::Bar::Baz;
+use base 'Foo::Bar';
+use fields qw(foo bar baz);
+
+package main;
+
+sub fstr
+{
+ my $h = shift;
+ my @tmp;
+ for my $k (sort {$h->{$a} <=> $h->{$b}} keys %$h) {
+ my $v = $h->{$k};
+ push(@tmp, "$k:$v");
+ }
+ my $str = join(",", @tmp);
+ print "$h => $str\n" if $DEBUG;
+ $str;
+}
+
+my %expect = (
+ B1 => "b1:1,b2:2,b3:3",
+ B2 => "_b1:1,b1:2,_b2:3,b2:4",
+ D1 => "b1:1,b2:2,b3:3,d1:4,d2:5,d3:6",
+ D2 => "b1:1,b2:2,b3:3,_d1:4,_d2:5,d1:6,d2:7",
+ D3 => "b2:4,b1:5,d1:6,_b1:7,_d1:8",
+ D4 => "b2:4,b1:5,d1:6,_d3:9,d3:10",
+ D5 => "b1:2,b2:4",
+ 'Foo::Bar::Baz' => 'b1:1,b2:2,b3:3,foo:4,bar:5,baz:6',
+);
+
+print "1..", int(keys %expect)+3, "\n";
+my $testno = 0;
+while (my($class, $exp) = each %expect) {
+ no strict 'refs';
+ my $fstr = fstr(\%{$class."::FIELDS"});
+ print "EXP: $exp\nGOT: $fstr\nnot " unless $fstr eq $exp;
+ print "ok ", ++$testno, "\n";
+}
+
+# Did we get the appropriate amount of warnings?
+print "not " unless $w == 1;
+print "ok ", ++$testno, "\n";
+
+# A simple object creation and AVHV attribute access test
+my B2 $obj1 = D3->new;
+$obj1->{b1} = "B2";
+my D3 $obj2 = $obj1;
+$obj2->{b1} = "D3";
+
+print "not " unless $obj1->[2] eq "B2" && $obj1->[5] eq "D3";
+print "ok ", ++$testno, "\n";
+
+# We should get compile time failures field name typos
+eval q(my D3 $obj3 = $obj2; $obj3->{notthere} = "");
+print "not " unless $@ && $@ =~ /^No such field "notthere"/;
+print "ok ", ++$testno, "\n";
+
+#fields::_dump();
diff --git a/t/lib/trig.t b/t/lib/trig.t
index c2bc2a8b5b..09147112c7 100755
--- a/t/lib/trig.t
+++ b/t/lib/trig.t
@@ -25,7 +25,7 @@ sub near ($$;$) {
abs($_[0] - $_[1]) < (defined $_[2] ? $_[2] : $eps);
}
-print "1..7\n";
+print "1..20\n";
$x = 0.9;
print 'not ' unless (near(tan($x), sin($x) / cos($x)));
@@ -54,4 +54,103 @@ print "ok 6\n";
print 'not ' unless (near(rad2deg(pi), 180));
print "ok 7\n";
+use Math::Trig ':radial';
+
+{
+ my ($r,$t,$z) = cartesian_to_cylindrical(1,1,1);
+
+ print 'not ' unless (near($r, sqrt(2))) and
+ (near($t, deg2rad(45))) and
+ (near($z, 1));
+ print "ok 8\n";
+
+ ($x,$y,$z) = cylindrical_to_cartesian($r, $t, $z);
+
+ print 'not ' unless (near($x, 1)) and
+ (near($y, 1)) and
+ (near($z, 1));
+ print "ok 9\n";
+
+ ($r,$t,$z) = cartesian_to_cylindrical(1,1,0);
+
+ print 'not ' unless (near($r, sqrt(2))) and
+ (near($t, deg2rad(45))) and
+ (near($z, 0));
+ print "ok 10\n";
+
+ ($x,$y,$z) = cylindrical_to_cartesian($r, $t, $z);
+
+ print 'not ' unless (near($x, 1)) and
+ (near($y, 1)) and
+ (near($z, 0));
+ print "ok 11\n";
+}
+
+{
+ my ($r,$t,$f) = cartesian_to_spherical(1,1,1);
+
+ print 'not ' unless (near($r, sqrt(3))) and
+ (near($t, deg2rad(45))) and
+ (near($f, atan2(sqrt(2), 1)));
+ print "ok 12\n";
+
+ ($x,$y,$z) = spherical_to_cartesian($r, $t, $f);
+
+ print 'not ' unless (near($x, 1)) and
+ (near($y, 1)) and
+ (near($z, 1));
+ print "ok 13\n";
+
+ ($r,$t,$f) = cartesian_to_spherical(1,1,0);
+
+ print 'not ' unless (near($r, sqrt(2))) and
+ (near($t, deg2rad(45))) and
+ (near($f, deg2rad(90)));
+ print "ok 14\n";
+
+ ($x,$y,$z) = spherical_to_cartesian($r, $t, $f);
+
+ print 'not ' unless (near($x, 1)) and
+ (near($y, 1)) and
+ (near($z, 0));
+ print "ok 15\n";
+}
+
+{
+ my ($r,$t,$z) = cylindrical_to_spherical(spherical_to_cylindrical(1,1,1));
+
+ print 'not ' unless (near($r, 1)) and
+ (near($t, 1)) and
+ (near($z, 1));
+ print "ok 16\n";
+
+ ($r,$t,$z) = spherical_to_cylindrical(cylindrical_to_spherical(1,1,1));
+
+ print 'not ' unless (near($r, 1)) and
+ (near($t, 1)) and
+ (near($z, 1));
+ print "ok 17\n";
+}
+
+{
+ use Math::Trig 'great_circle_distance';
+
+ print 'not '
+ unless (near(great_circle_distance(0, 0, 0, pi/2), pi/2));
+ print "ok 18\n";
+
+ print 'not '
+ unless (near(great_circle_distance(0, 0, pi, pi), pi));
+ print "ok 19\n";
+
+ # London to Tokyo.
+ my @L = (deg2rad(-0.5), deg2rad(90 - 51.3));
+ my @T = (deg2rad(139.8),deg2rad(90 - 35.7));
+
+ my $km = great_circle_distance(@L, @T, 6378);
+
+ print 'not ' unless (near($km, 9605.26637021388));
+ print "ok 20\n";
+}
+
# eof
diff --git a/t/op/array.t b/t/op/array.t
index f307655ced..c0225a1107 100755
--- a/t/op/array.t
+++ b/t/op/array.t
@@ -1,8 +1,6 @@
#!./perl
-# $RCSfile: array.t,v $$Revision: 4.1 $$Date: 92/08/07 18:27:37 $
-
-print "1..40\n";
+print "1..37\n";
@ary = (1,2,3,4,5);
if (join('',@ary) eq '12345') {print "ok 1\n";} else {print "not ok 1\n";}
@@ -119,32 +117,6 @@ print $foo eq 'e' ? "ok 35\n" : "not ok 35\n";
$foo = ('a','b','c','d','e','f')[1];
print $foo eq 'b' ? "ok 36\n" : "not ok 36\n";
-# Test pseudo-hashes and %FIELDS. Real programs would "use fields..."
-# but we assign to %FIELDS manually since the real module tests come later.
-
-BEGIN {
- %Base::WithFields::FIELDS = (foo => 1, bar => 2, baz => 3, __MAX__ => 3);
- %OtherBase::WithFields::FIELDS = (one => 1, two => 2, __MAX__ => 2);
-}
-{
- package Base::WithoutFields;
-}
-@ISA = qw(Base::WithoutFields Base::WithFields);
-@k = sort keys %FIELDS;
-print "not " unless "@k" eq "__MAX__ bar baz foo";
-print "ok 37\n";
-eval {
- @ISA = 'OtherBase::WithFields';
-};
-print "not " unless $@ =~ /Inherited %FIELDS can't override existing %FIELDS/;
-print "ok 38\n";
-undef %FIELDS;
-eval {
- @ISA = qw(Base::WithFields OtherBase::WithFields);
-};
-print "not " unless $@ =~ /Can't multiply inherit %FIELDS/;
-print "ok 39\n";
-
@foo = ( 'foo', 'bar', 'burbl');
push(foo, 'blah');
-print $#foo == 3 ? "ok 40\n" : "not ok 40\n";
+print $#foo == 3 ? "ok 37\n" : "not ok 37\n";
diff --git a/toke.c b/toke.c
index 24bf27dd5e..c734fc8813 100644
--- a/toke.c
+++ b/toke.c
@@ -4716,7 +4716,7 @@ STATIC SV *
new_constant(char *s, STRLEN len, char *key, SV *sv, SV *pv, char *type)
{
dSP;
- HV *table = perl_get_hv("\10", FALSE); /* ^H */
+ HV *table = GvHV(hintgv); /* ^H */
BINOP myop;
SV *res;
bool oldcatch = CATCH_GET;
@@ -4757,7 +4757,7 @@ new_constant(char *s, STRLEN len, char *key, SV *sv, SV *pv, char *type)
PUTBACK;
pp_pushmark(ARGS);
- EXTEND(sp, 3);
+ EXTEND(sp, 4);
PUSHs(pv);
PUSHs(sv);
PUSHs(typesv);
diff --git a/utils/perldoc.PL b/utils/perldoc.PL
index 3805f6abe4..2b4ef6a0a9 100644
--- a/utils/perldoc.PL
+++ b/utils/perldoc.PL
@@ -123,8 +123,10 @@ getopts("mhtluvriFf:Xq:") || usage;
usage if $opt_h || $opt_h; # avoid -w warning
-$podidx = "$Config{'archlib'}/pod.idx";
-$podidx = "" if $opt_X || !-f "pod.idx" && !-r _ && -M _ > 7;
+if( $opt_X ) {
+ $podidx = "$Config{'archlib'}/pod.idx";
+ $podidx = "" unless -f $podidx && -r _ && -M _ <= 7;
+}
if ($opt_t + $opt_u + $opt_m + $opt_l > 1) {
usage("only one of -t, -u, -m or -l")
diff --git a/win32/config.bc b/win32/config.bc
index 5ee5af64f7..447a999462 100644
--- a/win32/config.bc
+++ b/win32/config.bc
@@ -321,8 +321,8 @@ i_dld='undef'
i_dlfcn='define'
i_fcntl='define'
i_float='define'
-i_gdbm='define'
-i_grp='define'
+i_gdbm='undef'
+i_grp='undef'
i_limits='define'
i_locale='define'
i_malloc='define'
diff --git a/win32/config.gc b/win32/config.gc
index 73f8219819..0c5f5e039e 100644
--- a/win32/config.gc
+++ b/win32/config.gc
@@ -321,8 +321,8 @@ i_dld='undef'
i_dlfcn='define'
i_fcntl='define'
i_float='define'
-i_gdbm='define'
-i_grp='define'
+i_gdbm='undef'
+i_grp='undef'
i_limits='define'
i_locale='define'
i_malloc='define'
diff --git a/win32/config.vc b/win32/config.vc
index aefd0347c1..4740b50d08 100644
--- a/win32/config.vc
+++ b/win32/config.vc
@@ -321,8 +321,8 @@ i_dld='undef'
i_dlfcn='define'
i_fcntl='define'
i_float='define'
-i_gdbm='define'
-i_grp='define'
+i_gdbm='undef'
+i_grp='undef'
i_limits='define'
i_locale='define'
i_malloc='define'
diff --git a/win32/include/dirent.h b/win32/include/dirent.h
index 8cc7e11479..be363ce804 100644
--- a/win32/include/dirent.h
+++ b/win32/include/dirent.h
@@ -38,12 +38,12 @@ typedef struct _dir_struc
struct direct dirstr; // Directory structure to return
} DIR;
-DIR *opendir(char *filename);
-struct direct *readdir(DIR *dirp);
-long telldir(DIR *dirp);
-void seekdir(DIR *dirp,long loc);
-void rewinddir(DIR *dirp);
-int closedir(DIR *dirp);
+DIR * win32_opendir(char *filename);
+struct direct * win32_readdir(DIR *dirp);
+long win32_telldir(DIR *dirp);
+void win32_seekdir(DIR *dirp,long loc);
+void win32_rewinddir(DIR *dirp);
+int win32_closedir(DIR *dirp);
#endif //_INC_DIRENT
diff --git a/win32/makedef.pl b/win32/makedef.pl
index d3a5196d7a..6592e468ed 100644
--- a/win32/makedef.pl
+++ b/win32/makedef.pl
@@ -583,6 +583,12 @@ win32_wait
win32_waitpid
win32_kill
win32_str_os_error
+win32_opendir
+win32_readdir
+win32_telldir
+win32_seekdir
+win32_rewinddir
+win32_closedir
Perl_win32_init
Perl_init_os_extras
Perl_getTHR
diff --git a/win32/win32.c b/win32/win32.c
index 68b6bb8962..03552debbf 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -637,7 +637,7 @@ do_exec(char *cmd)
* return the pointer to the current file name.
*/
DIR *
-opendir(char *filename)
+win32_opendir(char *filename)
{
DIR *p;
long len;
@@ -715,7 +715,7 @@ opendir(char *filename)
* string pointer to the nDllExport entry.
*/
struct direct *
-readdir(DIR *dirp)
+win32_readdir(DIR *dirp)
{
int len;
static int dummy = 0;
@@ -743,7 +743,7 @@ readdir(DIR *dirp)
/* Telldir returns the current string pointer position */
long
-telldir(DIR *dirp)
+win32_telldir(DIR *dirp)
{
return (long) dirp->curr;
}
@@ -753,21 +753,21 @@ telldir(DIR *dirp)
*(Saved by telldir).
*/
void
-seekdir(DIR *dirp, long loc)
+win32_seekdir(DIR *dirp, long loc)
{
dirp->curr = (char *)loc;
}
/* Rewinddir resets the string pointer to the start */
void
-rewinddir(DIR *dirp)
+win32_rewinddir(DIR *dirp)
{
dirp->curr = dirp->start;
}
/* free the memory allocated by opendir */
int
-closedir(DIR *dirp)
+win32_closedir(DIR *dirp)
{
Safefree(dirp->start);
Safefree(dirp);
diff --git a/win32/win32iop.h b/win32/win32iop.h
index 6f4444eb3b..b22a1870a9 100644
--- a/win32/win32iop.h
+++ b/win32/win32iop.h
@@ -262,6 +262,13 @@ END_EXTERN_C
#define waitpid win32_waitpid
#define kill win32_kill
+#define opendir win32_opendir
+#define readdir win32_readdir
+#define telldir win32_telldir
+#define seekdir win32_seekdir
+#define rewinddir win32_rewinddir
+#define closedir win32_closedir
+
#ifdef HAVE_DES_FCRYPT
#undef crypt
#define crypt win32_crypt