sub
__clean_eval {
eval
$_
[0] }
our
$VERSION
=
'0.47'
;
our
$VERBOSE
= 0;
our
$ALLOW_DEV_VERSION
= 0;
our
$FORK
= 0;
our
$UNSAFE
= $] < 5.010000 ? 1 : 0;
sub
new {
my
(
$class
,
$meta
,
$opts
) =
@_
;
bless
{%{
$opts
|| {} },
META_CONTENT
=>
$meta
},
$class
;
}
sub
parse {
my
(
$self
,
$pmfile
) =
@_
;
$pmfile
=~ s|\\|/|g;
my
(
$filemtime
) = (
stat
$pmfile
)[9];
$self
->{MTIME} =
$filemtime
;
$self
->{PMFILE} =
$pmfile
;
unless
(
$self
->_version_from_meta_ok) {
my
$version
;
unless
(
eval
{
$version
=
$self
->_parse_version; 1 }) {
$self
->_verbose(1,
"error with version in $pmfile: $@"
);
return
;
}
$self
->{VERSION} =
$version
;
if
(
$self
->{VERSION} =~ /^\{.*\}$/) {
}
elsif
(
$self
->{VERSION} =~ /[_\s]/ && !
$self
->{ALLOW_DEV_VERSION} && !
$ALLOW_DEV_VERSION
){
return
;
}
}
my
(
$ppp
) =
$self
->_packages_per_pmfile;
my
@keys_ppp
=
$self
->_filter_ppps(
sort
keys
%$ppp
);
$self
->_verbose(1,
"Will check keys_ppp[@keys_ppp]\n"
);
my
(
$package
,
%errors
);
my
%checked_in
;
DBPACK:
foreach
$package
(
@keys_ppp
) {
if
(
$package
!~ /^\w[\w\:\']*\w?\z/
||
$package
!~ /\w\z/
||
$package
=~ /:/ &&
$package
!~ /::/
||
$package
=~ /\w:\w/
||
$package
=~ /:::/
){
$self
->_verbose(1,
"Package[$package] did not pass the ultimate sanity check"
);
delete
$ppp
->{
$package
};
next
;
}
if
(
$self
->{USERID} &&
$self
->{PERMISSIONS} && !
$self
->_perm_check(
$package
)) {
delete
$ppp
->{
$package
};
next
;
}
{
my
(
undef
,
$module
) =
split
m{/lib/},
$self
->{PMFILE}, 2;
if
(
$module
) {
$module
=~ s{\.pm\z}{};
$module
=~ s{/}{::}g;
if
(
lc
$module
eq
lc
$package
&&
$module
ne
$package
) {
$errors
{
$package
} = {
indexing_warning
=>
"Capitalization of package ($package) does not match filename!"
,
infile
=>
$self
->{PMFILE},
};
}
}
}
my
$pp
=
$ppp
->{
$package
};
if
(
$pp
->{version} &&
$pp
->{version} =~ /^\{.*\}$/) {
my
$err
= JSON::PP::decode_json(
$pp
->{version});
if
(
$err
->{x_normalize}) {
$errors
{
$package
} = {
normalize
=>
$err
->{version},
infile
=>
$pp
->{infile},
};
$pp
->{version} =
"undef"
;
}
elsif
(
$err
->{openerr}) {
$pp
->{version} =
"undef"
;
$self
->_verbose(1,
qq{Parse::PMFile was not able to
read the file. It issued the following error: C< $err->{r}
>},
);
$errors
{
$package
} = {
open
=>
$err
->{r},
infile
=>
$pp
->{infile},
};
}
else
{
$pp
->{version} =
"undef"
;
$self
->_verbose(1,
qq{Parse::PMFile was not able to
parse the following line in that file: C< $err->{line}
>
Note: the indexer is running in a Safe compartement and cannot
provide the full functionality of perl in the VERSION line. It
is trying hard, but sometime it fails. As a workaround, please
consider writing a META.yml that contains a
'provides'
attribute or contact the CPAN admins to investigate (yet
another) workaround against
"Safe"
limitations.)},
);
$errors
{
$package
} = {
parse_version
=>
$err
->{line},
infile
=>
$err
->{file},
};
}
}
for
(
$package
,
$pp
->{version},
) {
if
(!
defined
|| /^\s*$/ || /\s/){
delete
$ppp
->{
$package
};
next
;
}
}
unless
(
$self
->_version_ok(
$pp
)) {
$errors
{
$package
} = {
long_version
=>
qq{Version string exceeds maximum allowed length of 16b: "$pp->{version}
"},
infile
=>
$pp
->{infile},
};
next
;
}
$checked_in
{
$package
} =
$ppp
->{
$package
};
}
return
(
wantarray
&&
%errors
) ? (\
%checked_in
, \
%errors
) : \
%checked_in
;
}
sub
_version_ok {
my
(
$self
,
$pp
) =
@_
;
return
if
length
(
$pp
->{version} || 0) > 16;
return
1
}
sub
_perm_check {
my
(
$self
,
$package
) =
@_
;
my
$userid
=
$self
->{USERID};
my
$module
=
$self
->{PERMISSIONS}->module_permissions(
$package
);
return
1
if
!
$module
;
return
1
if
defined
$module
->m &&
$module
->m eq
$userid
;
return
1
if
defined
$module
->f &&
$module
->f eq
$userid
;
return
1
if
defined
$module
->c &&
grep
{
$_
eq
$userid
} @{
$module
->c};
return
;
}
sub
_parse_version {
my
$self
=
shift
;
my
$pmfile
=
$self
->{PMFILE};
my
$tmpfile
= File::Spec->catfile(File::Spec->tmpdir,
"ParsePMFile$$"
.
rand
(1000));
my
$pmcp
=
$pmfile
;
for
(
$pmcp
) {
s/([^\\](\\\\)*)@/$1\\@/g;
}
my
(
$v
);
{
my
$pid
;
if
(
$self
->{FORK} ||
$FORK
) {
$pid
=
fork
();
die
"Can't fork: $!"
unless
defined
$pid
;
}
if
(
$pid
) {
waitpid
(
$pid
, 0);
if
(
open
my
$fh
,
'<'
,
$tmpfile
) {
$v
= <
$fh
>;
}
}
else
{
my
$comp
;
my
$eval
=
qq{
local(\$^W) = 0;
Parse::PMFile::_parse_version_safely("$pmcp");
}
;
unless
(
$self
->{UNSAFE} ||
$UNSAFE
) {
$comp
= Safe->new;
$comp
->permit(
"entereval"
);
$comp
->share(
"*Parse::PMFile::_parse_version_safely"
);
$comp
->share(
"*version::new"
);
$comp
->share(
"*version::numify"
);
$comp
->share_from(
'main'
, [
'*version::'
,
'*charstar::'
,
'*Exporter::'
,
'*DynaLoader::'
]);
$comp
->share_from(
'version'
, [
'&qv'
]);
$comp
->permit(
":base_math"
);
$comp
->deny(
qw/enteriter iter unstack goto/
);
}
version->
import
(
'qv'
)
if
$self
->{UNSAFE} ||
$UNSAFE
;
{
no
strict;
$v
=
$comp
?
$comp
->reval(
$eval
) :
eval
$eval
;
}
if
($@){
my
$err
= $@;
if
(
ref
$err
) {
if
(
$err
->{line} =~ /([\$*])([\w\:\']*)\bVERSION\b.*?\=(.*)/) {
local
($^W) = 0;
my
(
$sigil
,
$vstr
) = ($1, $3);
$self
->_restore_overloaded_stuff(1)
if
$err
->{line} =~ /
use
\s+version\b|version\->|qv\(/;
$v
=
$comp
?
$comp
->reval(
$vstr
) :
eval
$vstr
;
$v
=
$$v
if
$sigil
eq
'*'
&&
ref
$v
;
}
if
($@ or !
$v
) {
$self
->_verbose(1,
sprintf
(
"reval failed: err[%s] for eval[%s]"
,
JSON::PP::encode_json(
$err
),
$eval
,
));
$v
= JSON::PP::encode_json(
$err
);
}
}
else
{
$v
= JSON::PP::encode_json({
openerr
=>
$err
});
}
}
if
(
defined
$v
) {
no
warnings;
$v
=
$v
->numify
if
ref
(
$v
) =~ /^version(::vpp)?$/;
}
else
{
$v
=
""
;
}
if
(
$self
->{FORK} ||
$FORK
) {
open
my
$fh
,
'>:utf8'
,
$tmpfile
;
print
$fh
$v
;
exit
0;
}
else
{
utf8::encode(
$v
);
$v
=
undef
if
defined
$v
&& !
length
$v
;
$comp
->erase
if
(
$comp
);
$self
->_restore_overloaded_stuff;
}
}
}
unlink
$tmpfile
if
(
$self
->{FORK} ||
$FORK
) && -e
$tmpfile
;
return
$self
->_normalize_version(
$v
);
}
sub
_restore_overloaded_stuff {
my
(
$self
,
$used_version_in_safe
) =
@_
;
return
if
$self
->{UNSAFE} ||
$UNSAFE
;
no
strict
'refs'
;
no
warnings
'redefine'
;
my
$restored
;
if
(
$INC
{
'version/vxs.pm'
}) {
*{
'version::(""'
} = \
&version::vxs::stringify
;
*{
'version::(0+'
} = \
&version::vxs::numify
;
*{
'version::(cmp'
} = \
&version::vxs::VCMP
;
*{
'version::(<=>'
} = \
&version::vxs::VCMP
;
*{
'version::(bool'
} = \
&version::vxs::boolean
;
$restored
= 1;
}
if
(
$INC
{
'version/vpp.pm'
}) {
{
package
charstar;
overload->
import
;
}
if
(!
$used_version_in_safe
) {
package
version::vpp;
overload->
import
;
}
unless
(
$restored
) {
*{
'version::(""'
} = \
&version::vpp::stringify
;
*{
'version::(0+'
} = \
&version::vpp::numify
;
*{
'version::(cmp'
} = \
&version::vpp::vcmp
;
*{
'version::(<=>'
} = \
&version::vpp::vcmp
;
*{
'version::(bool'
} = \
&version::vpp::vbool
;
}
*{
'version::vpp::(""'
} = \
&version::vpp::stringify
;
*{
'version::vpp::(0+'
} = \
&version::vpp::numify
;
*{
'version::vpp::(cmp'
} = \
&version::vpp::vcmp
;
*{
'version::vpp::(<=>'
} = \
&version::vpp::vcmp
;
*{
'version::vpp::(bool'
} = \
&version::vpp::vbool
;
*{
'charstar::(""'
} = \
&charstar::thischar
;
*{
'charstar::(0+'
} = \
&charstar::thischar
;
*{
'charstar::(++'
} = \
&charstar::increment
;
*{
'charstar::(--'
} = \
&charstar::decrement
;
*{
'charstar::(+'
} = \
&charstar::plus
;
*{
'charstar::(-'
} = \
&charstar::minus
;
*{
'charstar::(*'
} = \
&charstar::multiply
;
*{
'charstar::(cmp'
} = \
&charstar::cmp
;
*{
'charstar::(<=>'
} = \
&charstar::spaceship
;
*{
'charstar::(bool'
} = \
&charstar::thischar
;
*{
'charstar::(='
} = \
&charstar::clone
;
$restored
= 1;
}
if
(!
$restored
) {
*{
'version::(""'
} = \
&version::stringify
;
*{
'version::(0+'
} = \
&version::numify
;
*{
'version::(cmp'
} = \
&version::vcmp
;
*{
'version::(<=>'
} = \
&version::vcmp
;
*{
'version::(bool'
} = \
&version::boolean
;
}
}
sub
_packages_per_pmfile {
my
$self
=
shift
;
my
$ppp
= {};
my
$pmfile
=
$self
->{PMFILE};
my
$filemtime
=
$self
->{MTIME};
my
$version
=
$self
->{VERSION};
open
my
$fh
,
"<"
,
"$pmfile"
or
return
$ppp
;
local
$/ =
"\n"
;
my
$inpod
= 0;
my
$package_or_class
=
'package'
;
my
$checked_bom
;
PLINE:
while
(<
$fh
>) {
chomp
;
my
(
$pline
) =
$_
;
$pline
=~ s/\A(?:\x00\x00\xfe\xff|\xff\xfe\x00\x00|\xfe\xff|\xff\xfe|\xef\xbb\xbf)//
unless
$checked_bom
;
$checked_bom
= 1;
$inpod
=
$pline
=~ /^=(?!cut)/ ? 1 :
$pline
=~ /^=cut/ ? 0 :
$inpod
;
next
if
$inpod
;
next
if
substr
(
$pline
,0,4) eq
"=cut"
;
$pline
=~ s/\
next
if
$pline
=~ /^\s*$/;
if
(
$pline
=~ /^__(?:END|DATA)__\b/
and
$pmfile
!~ /\.PL$/
){
last
PLINE;
}
Hide Show 12 lines of Pod
if
(
$pline
=~ /^[\s\{;]
*use
\s+(?:feature|experimental)\s+[^;]+\b(?:class|all)[^;]*;/) {
$package_or_class
=
'package|class'
;
}
if
(
$pline
=~ /^[\s\{;]
*use
\s+(?:Feature::Compat::Class)[^;]*;/) {
$package_or_class
=
'package|class'
;
}
if
(
$pline
=~ /^[\s\{;]
*use
\s+(?:Object::Pad)[^;]*;/) {
$package_or_class
=
'package|class|role'
;
}
my
$pkg
;
my
$strict_version
;
if
(
$pline
=~ m{
^[\s\{;]*
\b(?:
$package_or_class
)\s+
([\w\:\']+)
\s*
(?: $ | [\}\;] | \{ | \s+(
$version::STRICT
) )
}x) {
$pkg
= $1;
$strict_version
= $2;
if
(
$pkg
eq
"DB"
){
next
PLINE;
}
}
if
(
$pkg
) {
$pkg
=~ s/\'/::/g;
next
PLINE
unless
$pkg
=~ /^[A-Za-z]/;
next
PLINE
unless
$pkg
=~ /\w$/;
next
PLINE
if
$pkg
eq
"main"
;
next
PLINE
if
length
(
$pkg
) > 128;
$ppp
->{
$pkg
}{parsed}++;
$ppp
->{
$pkg
}{infile} =
$pmfile
;
if
(
$self
->_simile(
$pmfile
,
$pkg
)) {
$ppp
->{
$pkg
}{simile} =
$pmfile
;
if
(
$self
->_version_from_meta_ok) {
my
$provides
=
$self
->{META_CONTENT}{provides};
if
(
exists
$provides
->{
$pkg
}) {
if
(
defined
$provides
->{
$pkg
}{version}) {
my
$v
=
$provides
->{
$pkg
}{version};
if
(
$v
=~ /[_\s]/ && !
$self
->{ALLOW_DEV_VERSION} && !
$ALLOW_DEV_VERSION
){
next
PLINE;
}
unless
(
eval
{
$version
=
$self
->_normalize_version(
$v
); 1 }) {
$self
->_verbose(1,
"error with version in $pmfile: $@"
);
next
;
}
$ppp
->{
$pkg
}{version} =
$version
;
}
else
{
$ppp
->{
$pkg
}{version} =
"undef"
;
}
}
}
else
{
if
(
defined
$strict_version
){
$ppp
->{
$pkg
}{version} =
$strict_version
;
}
else
{
$ppp
->{
$pkg
}{version} =
defined
$version
?
$version
:
""
;
}
no
warnings;
if
(
$version
eq
'undef'
) {
$ppp
->{
$pkg
}{version} =
$version
unless
defined
$ppp
->{
$pkg
}{version};
}
else
{
$ppp
->{
$pkg
}{version} =
$version
if
$version
>
$ppp
->{
$pkg
}{version} ||
$version
gt
$ppp
->{
$pkg
}{version};
}
}
}
else
{
$ppp
->{
$pkg
}{version} =
$version
unless
defined
$ppp
->{
$pkg
}{version} &&
length
(
$ppp
->{
$pkg
}{version});
}
$ppp
->{
$pkg
}{filemtime} =
$filemtime
;
$ppp
->{
$pkg
}{version} .=
""
;
}
else
{
}
}
close
$fh
;
$ppp
;
}
{
no
strict;
sub
_parse_version_safely {
my
(
$parsefile
) =
@_
;
my
$result
;
local
*FH
;
local
$/ =
"\n"
;
open
(FH,
$parsefile
) or
die
"Could not open '$parsefile': $!"
;
my
$inpod
= 0;
while
(<FH>) {
$inpod
= /^=(?!cut)/ ? 1 : /^=cut/ ? 0 :
$inpod
;
next
if
$inpod
|| /^\s*
last
if
/^__(?:END|DATA)__\b/;
chop
;
if
(
my
(
$ver
) = /
package
\s+ \S+ \s+ (\S+) \s* [;{]/x) {
return
$ver
if
version::is_lax(
$ver
);
}
next
unless
/(?<!\\)([\$*])(([\w\:\']*)\bVERSION)\b.*(?<![!><=])\=(?![=>])/;
my
$current_parsed_line
=
$_
;
my
$eval
=
qq{
package #
ExtUtils::MakeMaker::_version;
local $1$2;
\$$2=undef; do {
$_
}
; \$$2
};
local
$^W = 0;
local
$SIG
{__WARN__} =
sub
{};
$result
= __clean_eval(
$eval
);
if
($@ or !
defined
$result
){
die
+{
eval
=>
$eval
,
line
=>
$current_parsed_line
,
file
=>
$parsefile
,
err
=> $@,
};
}
last
;
}
close
FH;
$result
=
"undef"
unless
defined
$result
;
if
((
ref
$result
) =~ /^version(?:::vpp)?\b/) {
no
warnings;
$result
=
$result
->numify;
}
return
$result
;
}
}
sub
_filter_ppps {
my
(
$self
,
@ppps
) =
@_
;
my
@res
;
MANI:
for
my
$ppp
(
@ppps
) {
if
(
$self
->{META_CONTENT}){
my
$no_index
=
$self
->{META_CONTENT}{no_index}
||
$self
->{META_CONTENT}{private};
if
(
ref
(
$no_index
) eq
'HASH'
) {
my
%map
= (
package
=>
qr{\z}
,
namespace
=>
qr{::}
,
);
for
my
$k
(
qw(package namespace)
) {
next
unless
my
$v
=
$no_index
->{
$k
};
my
$rest
=
$map
{
$k
};
if
(
ref
$v
eq
"ARRAY"
) {
for
my
$ve
(
@$v
) {
$ve
=~ s|::$||;
if
(
$ppp
=~ /^
$ve
$rest
/){
$self
->_verbose(1,
"Skipping ppp[$ppp] due to ve[$ve]"
);
next
MANI;
}
else
{
$self
->_verbose(1,
"NOT skipping ppp[$ppp] due to ve[$ve]"
);
}
}
}
else
{
$v
=~ s|::$||;
if
(
$ppp
=~ /^
$v
$rest
/){
$self
->_verbose(1,
"Skipping ppp[$ppp] due to v[$v]"
);
next
MANI;
}
else
{
$self
->_verbose(1,
"NOT skipping ppp[$ppp] due to v[$v]"
);
}
}
}
}
else
{
$self
->_verbose(1,
"No keyword 'no_index' or 'private' in META_CONTENT"
);
}
}
else
{
}
push
@res
,
$ppp
;
}
$self
->_verbose(1,
"Result of filter_ppps: res[@res]"
);
@res
;
}
sub
_simile {
my
(
$self
,
$file
,
$package
) =
@_
;
$file
=~ s|.*/||;
$file
=~ s|\.pm(?:\.PL)?||;
my
$ret
=
$package
=~ m/\b\Q
$file
\E$/;
$ret
||= 0;
unless
(
$ret
) {
$ret
= 1
if
lc
$file
eq
'version'
;
}
$self
->_verbose(1,
"Result of simile(): file[$file] package[$package] ret[$ret]\n"
);
$ret
;
}
sub
_normalize_version {
my
(
$self
,
$v
) =
@_
;
$v
=
"undef"
unless
defined
$v
;
my
$dv
= Dumpvalue->new;
my
$sdv
=
$dv
->stringify(
$v
,1);
$self
->_verbose(1,
"Result of normalize_version: sdv[$sdv]\n"
);
return
$v
if
$v
eq
"undef"
;
return
$v
if
$v
=~ /^\{.*\}$/;
$v
=~ s/^\s+//;
$v
=~ s/\s+\z//;
if
(
$v
=~ /_/) {
return
$v
;
}
if
(!version::is_lax(
$v
)) {
return
JSON::PP::encode_json({
x_normalize
=>
'version::is_lax failed'
,
version
=>
$v
});
}
my
$vv
=
eval
{
no
warnings; version->new(
$v
)->numify };
if
($@) {
return
JSON::PP::encode_json({
x_normalize
=> $@,
version
=>
$v
});
}
if
(
$vv
eq
$v
) {
}
else
{
my
$forced
=
$self
->_force_numeric(
$v
);
if
(
$forced
eq
$vv
) {
}
elsif
(
$forced
=~ /^v(.+)/) {
no
warnings;
$vv
= version->new($1)->numify;
}
else
{
if
(
$forced
==
$vv
) {
$vv
=
$forced
;
}
}
}
return
$vv
;
}
sub
_force_numeric {
my
(
$self
,
$v
) =
@_
;
$v
=
$self
->_readable(
$v
);
if
(
$v
=~
/^(\+?)(\d*)(\.(\d*))?/ &&
(
defined
$2 &&
length
$2
||
defined
$4 &&
length
$4
)
) {
my
$two
=
defined
$2 ? $2 :
""
;
my
$three
=
defined
$3 ? $3 :
""
;
$v
=
"$two$three"
;
}
$v
;
}
sub
_version_from_meta_ok {
my
(
$self
) =
@_
;
return
$self
->{VERSION_FROM_META_OK}
if
exists
$self
->{VERSION_FROM_META_OK};
my
$c
=
$self
->{META_CONTENT};
return
(
$self
->{VERSION_FROM_META_OK} = 0)
unless
$c
->{provides};
my
(
$mb_v
) = (
defined
$c
->{generated_by} ?
$c
->{generated_by} :
''
) =~ /Module::Build version ([\d\.]+)/;
return
(
$self
->{VERSION_FROM_META_OK} = 1)
unless
$mb_v
;
return
(
$self
->{VERSION_FROM_META_OK} = 1)
if
$mb_v
eq
'0.250.0'
;
if
(
$mb_v
>= 0.19 &&
$mb_v
< 0.26 && !
keys
%{
$c
->{provides}}) {
return
(
$self
->{VERSION_FROM_META_OK} = 0);
}
return
(
$self
->{VERSION_FROM_META_OK} = 1);
}
sub
_verbose {
my
(
$self
,
$level
,
@what
) =
@_
;
warn
@what
if
$level
<= ((
ref
$self
&&
$self
->{VERBOSE}) ||
$VERBOSE
);
}
sub
_vcmp {
my
(
$self
,
$l
,
$r
) =
@_
;
local
($^W) = 0;
$self
->_verbose(9,
"l[$l] r[$r]"
);
return
0
if
$l
eq
$r
;
for
(
$l
,
$r
) {
s/_//g;
}
$self
->_verbose(9,
"l[$l] r[$r]"
);
for
(
$l
,
$r
) {
next
unless
tr
/.// > 1 || /^v/;
s/^v?/v/;
1
while
s/\.0+(\d)/.$1/;
}
$self
->_verbose(9,
"l[$l] r[$r]"
);
if
(
$l
=~/^v/ <=>
$r
=~/^v/) {
for
(
$l
,
$r
) {
next
if
/^v/;
$_
=
$self
->_float2vv(
$_
);
}
}
$self
->_verbose(9,
"l[$l] r[$r]"
);
my
$lvstring
=
"v0"
;
my
$rvstring
=
"v0"
;
if
($] >= 5.006
&&
$l
=~ /^v/
&&
$r
=~ /^v/) {
$lvstring
=
$self
->_vstring(
$l
);
$rvstring
=
$self
->_vstring(
$r
);
$self
->_verbose(9,
sprintf
"lv[%vd] rv[%vd]"
,
$lvstring
,
$rvstring
);
}
return
(
(
$l
ne
"undef"
) <=> (
$r
ne
"undef"
)
||
$lvstring
cmp
$rvstring
||
$l
<=>
$r
||
$l
cmp
$r
);
}
sub
_vgt {
my
(
$self
,
$l
,
$r
) =
@_
;
$self
->_vcmp(
$l
,
$r
) > 0;
}
sub
_vlt {
my
(
$self
,
$l
,
$r
) =
@_
;
$self
->_vcmp(
$l
,
$r
) < 0;
}
sub
_vge {
my
(
$self
,
$l
,
$r
) =
@_
;
$self
->_vcmp(
$l
,
$r
) >= 0;
}
sub
_vle {
my
(
$self
,
$l
,
$r
) =
@_
;
$self
->_vcmp(
$l
,
$r
) <= 0;
}
sub
_vstring {
my
(
$self
,
$n
) =
@_
;
$n
=~ s/^v// or
die
"Parse::PMFile::_vstring() called with invalid arg [$n]"
;
pack
"U*"
,
split
/\./,
$n
;
}
sub
_float2vv {
my
(
$self
,
$n
) =
@_
;
my
(
$rev
) =
int
(
$n
);
$rev
||= 0;
my
(
$mantissa
) =
$n
=~ /\.(\d{1,12})/;
$mantissa
||= 0;
$mantissa
.=
"0"
while
length
(
$mantissa
)%3;
my
$ret
=
"v"
.
$rev
;
while
(
$mantissa
) {
$mantissa
=~ s/(\d{1,3})// or
die
"Panic: length>0 but not a digit? mantissa[$mantissa]"
;
$ret
.=
"."
.
int
($1);
}
$ret
=~ s/(\.0)+/.0/;
$ret
;
}
sub
_readable {
my
(
$self
,
$n
) =
@_
;
$n
=~ /^([\w\-\+\.]+)/;
return
$1
if
defined
$1 &&
length
($1)>0;
if
($] < 5.006) {
$self
->_verbose(9,
"Suspicious version string seen [$n]\n"
);
return
$n
;
}
my
$better
=
sprintf
"v%vd"
,
$n
;
$self
->_verbose(9,
"n[$n] better[$better]"
);
return
$better
;
}
1;
Hide Show 87 lines of Pod